1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (C) 2018-2020, Intel Corporation. */ 3 4 #include "ice.h" 5 #include "ice_fltr.h" 6 7 /** 8 * ice_fltr_free_list - free filter lists helper 9 * @dev: pointer to the device struct 10 * @h: pointer to the list head to be freed 11 * 12 * Helper function to free filter lists previously created using 13 * ice_fltr_add_mac_to_list 14 */ 15 void ice_fltr_free_list(struct device *dev, struct list_head *h) 16 { 17 struct ice_fltr_list_entry *e, *tmp; 18 19 list_for_each_entry_safe(e, tmp, h, list_entry) { 20 list_del(&e->list_entry); 21 devm_kfree(dev, e); 22 } 23 } 24 25 /** 26 * ice_fltr_add_entry_to_list - allocate and add filter entry to list 27 * @dev: pointer to device needed by alloc function 28 * @info: filter info struct that gets added to the passed in list 29 * @list: pointer to the list which contains MAC filters entry 30 */ 31 static int 32 ice_fltr_add_entry_to_list(struct device *dev, struct ice_fltr_info *info, 33 struct list_head *list) 34 { 35 struct ice_fltr_list_entry *entry; 36 37 entry = devm_kzalloc(dev, sizeof(*entry), GFP_ATOMIC); 38 if (!entry) 39 return -ENOMEM; 40 41 entry->fltr_info = *info; 42 43 INIT_LIST_HEAD(&entry->list_entry); 44 list_add(&entry->list_entry, list); 45 46 return 0; 47 } 48 49 /** 50 * ice_fltr_set_vlan_vsi_promisc 51 * @hw: pointer to the hardware structure 52 * @vsi: the VSI being configured 53 * @promisc_mask: mask of promiscuous config bits 54 * 55 * Set VSI with all associated VLANs to given promiscuous mode(s) 56 */ 57 int 58 ice_fltr_set_vlan_vsi_promisc(struct ice_hw *hw, struct ice_vsi *vsi, 59 u8 promisc_mask) 60 { 61 return ice_set_vlan_vsi_promisc(hw, vsi->idx, promisc_mask, false); 62 } 63 64 /** 65 * ice_fltr_clear_vlan_vsi_promisc 66 * @hw: pointer to the hardware structure 67 * @vsi: the VSI being configured 68 * @promisc_mask: mask of promiscuous config bits 69 * 70 * Clear VSI with all associated VLANs to given promiscuous mode(s) 71 */ 72 int 73 ice_fltr_clear_vlan_vsi_promisc(struct ice_hw *hw, struct ice_vsi *vsi, 74 u8 promisc_mask) 75 { 76 return ice_set_vlan_vsi_promisc(hw, vsi->idx, promisc_mask, true); 77 } 78 79 /** 80 * ice_fltr_clear_vsi_promisc - clear specified promiscuous mode(s) 81 * @hw: pointer to the hardware structure 82 * @vsi_handle: VSI handle to clear mode 83 * @promisc_mask: mask of promiscuous config bits to clear 84 * @vid: VLAN ID to clear VLAN promiscuous 85 */ 86 int 87 ice_fltr_clear_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, 88 u16 vid) 89 { 90 return ice_clear_vsi_promisc(hw, vsi_handle, promisc_mask, vid); 91 } 92 93 /** 94 * ice_fltr_set_vsi_promisc - set given VSI to given promiscuous mode(s) 95 * @hw: pointer to the hardware structure 96 * @vsi_handle: VSI handle to configure 97 * @promisc_mask: mask of promiscuous config bits 98 * @vid: VLAN ID to set VLAN promiscuous 99 */ 100 int 101 ice_fltr_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, 102 u16 vid) 103 { 104 return ice_set_vsi_promisc(hw, vsi_handle, promisc_mask, vid); 105 } 106 107 /** 108 * ice_fltr_add_mac_list - add list of MAC filters 109 * @vsi: pointer to VSI struct 110 * @list: list of filters 111 */ 112 int ice_fltr_add_mac_list(struct ice_vsi *vsi, struct list_head *list) 113 { 114 return ice_add_mac(&vsi->back->hw, list); 115 } 116 117 /** 118 * ice_fltr_remove_mac_list - remove list of MAC filters 119 * @vsi: pointer to VSI struct 120 * @list: list of filters 121 */ 122 int ice_fltr_remove_mac_list(struct ice_vsi *vsi, struct list_head *list) 123 { 124 return ice_remove_mac(&vsi->back->hw, list); 125 } 126 127 /** 128 * ice_fltr_add_vlan_list - add list of VLAN filters 129 * @vsi: pointer to VSI struct 130 * @list: list of filters 131 */ 132 static int ice_fltr_add_vlan_list(struct ice_vsi *vsi, struct list_head *list) 133 { 134 return ice_add_vlan(&vsi->back->hw, list); 135 } 136 137 /** 138 * ice_fltr_remove_vlan_list - remove list of VLAN filters 139 * @vsi: pointer to VSI struct 140 * @list: list of filters 141 */ 142 static int 143 ice_fltr_remove_vlan_list(struct ice_vsi *vsi, struct list_head *list) 144 { 145 return ice_remove_vlan(&vsi->back->hw, list); 146 } 147 148 /** 149 * ice_fltr_add_eth_list - add list of ethertype filters 150 * @vsi: pointer to VSI struct 151 * @list: list of filters 152 */ 153 static int ice_fltr_add_eth_list(struct ice_vsi *vsi, struct list_head *list) 154 { 155 return ice_add_eth_mac(&vsi->back->hw, list); 156 } 157 158 /** 159 * ice_fltr_remove_eth_list - remove list of ethertype filters 160 * @vsi: pointer to VSI struct 161 * @list: list of filters 162 */ 163 static int ice_fltr_remove_eth_list(struct ice_vsi *vsi, struct list_head *list) 164 { 165 return ice_remove_eth_mac(&vsi->back->hw, list); 166 } 167 168 /** 169 * ice_fltr_remove_all - remove all filters associated with VSI 170 * @vsi: pointer to VSI struct 171 */ 172 void ice_fltr_remove_all(struct ice_vsi *vsi) 173 { 174 ice_remove_vsi_fltr(&vsi->back->hw, vsi->idx); 175 } 176 177 /** 178 * ice_fltr_add_mac_to_list - add MAC filter info to exsisting list 179 * @vsi: pointer to VSI struct 180 * @list: list to add filter info to 181 * @mac: MAC address to add 182 * @action: filter action 183 */ 184 int 185 ice_fltr_add_mac_to_list(struct ice_vsi *vsi, struct list_head *list, 186 const u8 *mac, enum ice_sw_fwd_act_type action) 187 { 188 struct ice_fltr_info info = { 0 }; 189 190 info.flag = ICE_FLTR_TX; 191 info.src_id = ICE_SRC_ID_VSI; 192 info.lkup_type = ICE_SW_LKUP_MAC; 193 info.fltr_act = action; 194 info.vsi_handle = vsi->idx; 195 196 ether_addr_copy(info.l_data.mac.mac_addr, mac); 197 198 return ice_fltr_add_entry_to_list(ice_pf_to_dev(vsi->back), &info, 199 list); 200 } 201 202 /** 203 * ice_fltr_add_vlan_to_list - add VLAN filter info to exsisting list 204 * @vsi: pointer to VSI struct 205 * @list: list to add filter info to 206 * @vlan: VLAN filter details 207 */ 208 static int 209 ice_fltr_add_vlan_to_list(struct ice_vsi *vsi, struct list_head *list, 210 struct ice_vlan *vlan) 211 { 212 struct ice_fltr_info info = { 0 }; 213 214 info.flag = ICE_FLTR_TX; 215 info.src_id = ICE_SRC_ID_VSI; 216 info.lkup_type = ICE_SW_LKUP_VLAN; 217 info.fltr_act = ICE_FWD_TO_VSI; 218 info.vsi_handle = vsi->idx; 219 info.l_data.vlan.vlan_id = vlan->vid; 220 info.l_data.vlan.tpid = vlan->tpid; 221 info.l_data.vlan.tpid_valid = true; 222 223 return ice_fltr_add_entry_to_list(ice_pf_to_dev(vsi->back), &info, 224 list); 225 } 226 227 /** 228 * ice_fltr_add_eth_to_list - add ethertype filter info to exsisting list 229 * @vsi: pointer to VSI struct 230 * @list: list to add filter info to 231 * @ethertype: ethertype of packet that matches filter 232 * @flag: filter direction, Tx or Rx 233 * @action: filter action 234 */ 235 static int 236 ice_fltr_add_eth_to_list(struct ice_vsi *vsi, struct list_head *list, 237 u16 ethertype, u16 flag, 238 enum ice_sw_fwd_act_type action) 239 { 240 struct ice_fltr_info info = { 0 }; 241 242 info.flag = flag; 243 info.lkup_type = ICE_SW_LKUP_ETHERTYPE; 244 info.fltr_act = action; 245 info.vsi_handle = vsi->idx; 246 info.l_data.ethertype_mac.ethertype = ethertype; 247 248 if (flag == ICE_FLTR_TX) 249 info.src_id = ICE_SRC_ID_VSI; 250 else 251 info.src_id = ICE_SRC_ID_LPORT; 252 253 return ice_fltr_add_entry_to_list(ice_pf_to_dev(vsi->back), &info, 254 list); 255 } 256 257 /** 258 * ice_fltr_prepare_mac - add or remove MAC rule 259 * @vsi: pointer to VSI struct 260 * @mac: MAC address to add 261 * @action: action to be performed on filter match 262 * @mac_action: pointer to add or remove MAC function 263 */ 264 static int 265 ice_fltr_prepare_mac(struct ice_vsi *vsi, const u8 *mac, 266 enum ice_sw_fwd_act_type action, 267 int (*mac_action)(struct ice_vsi *, struct list_head *)) 268 { 269 LIST_HEAD(tmp_list); 270 int result; 271 272 if (ice_fltr_add_mac_to_list(vsi, &tmp_list, mac, action)) { 273 ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list); 274 return -ENOMEM; 275 } 276 277 result = mac_action(vsi, &tmp_list); 278 ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list); 279 return result; 280 } 281 282 /** 283 * ice_fltr_prepare_mac_and_broadcast - add or remove MAC and broadcast filter 284 * @vsi: pointer to VSI struct 285 * @mac: MAC address to add 286 * @action: action to be performed on filter match 287 * @mac_action: pointer to add or remove MAC function 288 */ 289 static int 290 ice_fltr_prepare_mac_and_broadcast(struct ice_vsi *vsi, const u8 *mac, 291 enum ice_sw_fwd_act_type action, 292 int(*mac_action) 293 (struct ice_vsi *, struct list_head *)) 294 { 295 u8 broadcast[ETH_ALEN]; 296 LIST_HEAD(tmp_list); 297 int result; 298 299 eth_broadcast_addr(broadcast); 300 if (ice_fltr_add_mac_to_list(vsi, &tmp_list, mac, action) || 301 ice_fltr_add_mac_to_list(vsi, &tmp_list, broadcast, action)) { 302 ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list); 303 return -ENOMEM; 304 } 305 306 result = mac_action(vsi, &tmp_list); 307 ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list); 308 return result; 309 } 310 311 /** 312 * ice_fltr_prepare_vlan - add or remove VLAN filter 313 * @vsi: pointer to VSI struct 314 * @vlan: VLAN filter details 315 * @vlan_action: pointer to add or remove VLAN function 316 */ 317 static int 318 ice_fltr_prepare_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan, 319 int (*vlan_action)(struct ice_vsi *, struct list_head *)) 320 { 321 LIST_HEAD(tmp_list); 322 int result; 323 324 if (ice_fltr_add_vlan_to_list(vsi, &tmp_list, vlan)) 325 return -ENOMEM; 326 327 result = vlan_action(vsi, &tmp_list); 328 ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list); 329 return result; 330 } 331 332 /** 333 * ice_fltr_prepare_eth - add or remove ethertype filter 334 * @vsi: pointer to VSI struct 335 * @ethertype: ethertype of packet to be filtered 336 * @flag: direction of packet, Tx or Rx 337 * @action: action to be performed on filter match 338 * @eth_action: pointer to add or remove ethertype function 339 */ 340 static int 341 ice_fltr_prepare_eth(struct ice_vsi *vsi, u16 ethertype, u16 flag, 342 enum ice_sw_fwd_act_type action, 343 int (*eth_action)(struct ice_vsi *, struct list_head *)) 344 { 345 LIST_HEAD(tmp_list); 346 int result; 347 348 if (ice_fltr_add_eth_to_list(vsi, &tmp_list, ethertype, flag, action)) 349 return -ENOMEM; 350 351 result = eth_action(vsi, &tmp_list); 352 ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list); 353 return result; 354 } 355 356 /** 357 * ice_fltr_add_mac - add single MAC filter 358 * @vsi: pointer to VSI struct 359 * @mac: MAC to add 360 * @action: action to be performed on filter match 361 */ 362 int ice_fltr_add_mac(struct ice_vsi *vsi, const u8 *mac, 363 enum ice_sw_fwd_act_type action) 364 { 365 return ice_fltr_prepare_mac(vsi, mac, action, ice_fltr_add_mac_list); 366 } 367 368 /** 369 * ice_fltr_add_mac_and_broadcast - add single MAC and broadcast 370 * @vsi: pointer to VSI struct 371 * @mac: MAC to add 372 * @action: action to be performed on filter match 373 */ 374 int 375 ice_fltr_add_mac_and_broadcast(struct ice_vsi *vsi, const u8 *mac, 376 enum ice_sw_fwd_act_type action) 377 { 378 return ice_fltr_prepare_mac_and_broadcast(vsi, mac, action, 379 ice_fltr_add_mac_list); 380 } 381 382 /** 383 * ice_fltr_remove_mac - remove MAC filter 384 * @vsi: pointer to VSI struct 385 * @mac: filter MAC to remove 386 * @action: action to remove 387 */ 388 int ice_fltr_remove_mac(struct ice_vsi *vsi, const u8 *mac, 389 enum ice_sw_fwd_act_type action) 390 { 391 return ice_fltr_prepare_mac(vsi, mac, action, ice_fltr_remove_mac_list); 392 } 393 394 /** 395 * ice_fltr_add_vlan - add single VLAN filter 396 * @vsi: pointer to VSI struct 397 * @vlan: VLAN filter details 398 */ 399 int ice_fltr_add_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan) 400 { 401 return ice_fltr_prepare_vlan(vsi, vlan, ice_fltr_add_vlan_list); 402 } 403 404 /** 405 * ice_fltr_remove_vlan - remove VLAN filter 406 * @vsi: pointer to VSI struct 407 * @vlan: VLAN filter details 408 */ 409 int ice_fltr_remove_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan) 410 { 411 return ice_fltr_prepare_vlan(vsi, vlan, ice_fltr_remove_vlan_list); 412 } 413 414 /** 415 * ice_fltr_add_eth - add specyfic ethertype filter 416 * @vsi: pointer to VSI struct 417 * @ethertype: ethertype of filter 418 * @flag: direction of packet to be filtered, Tx or Rx 419 * @action: action to be performed on filter match 420 */ 421 int ice_fltr_add_eth(struct ice_vsi *vsi, u16 ethertype, u16 flag, 422 enum ice_sw_fwd_act_type action) 423 { 424 return ice_fltr_prepare_eth(vsi, ethertype, flag, action, 425 ice_fltr_add_eth_list); 426 } 427 428 /** 429 * ice_fltr_remove_eth - remove ethertype filter 430 * @vsi: pointer to VSI struct 431 * @ethertype: ethertype of filter 432 * @flag: direction of filter 433 * @action: action to remove 434 */ 435 int ice_fltr_remove_eth(struct ice_vsi *vsi, u16 ethertype, u16 flag, 436 enum ice_sw_fwd_act_type action) 437 { 438 return ice_fltr_prepare_eth(vsi, ethertype, flag, action, 439 ice_fltr_remove_eth_list); 440 } 441