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_id: VLAN ID to add 207 * @action: filter action 208 */ 209 static int 210 ice_fltr_add_vlan_to_list(struct ice_vsi *vsi, struct list_head *list, 211 u16 vlan_id, enum ice_sw_fwd_act_type action) 212 { 213 struct ice_fltr_info info = { 0 }; 214 215 info.flag = ICE_FLTR_TX; 216 info.src_id = ICE_SRC_ID_VSI; 217 info.lkup_type = ICE_SW_LKUP_VLAN; 218 info.fltr_act = action; 219 info.vsi_handle = vsi->idx; 220 info.l_data.vlan.vlan_id = vlan_id; 221 222 return ice_fltr_add_entry_to_list(ice_pf_to_dev(vsi->back), &info, 223 list); 224 } 225 226 /** 227 * ice_fltr_add_eth_to_list - add ethertype filter info to exsisting list 228 * @vsi: pointer to VSI struct 229 * @list: list to add filter info to 230 * @ethertype: ethertype of packet that matches filter 231 * @flag: filter direction, Tx or Rx 232 * @action: filter action 233 */ 234 static int 235 ice_fltr_add_eth_to_list(struct ice_vsi *vsi, struct list_head *list, 236 u16 ethertype, u16 flag, 237 enum ice_sw_fwd_act_type action) 238 { 239 struct ice_fltr_info info = { 0 }; 240 241 info.flag = flag; 242 info.lkup_type = ICE_SW_LKUP_ETHERTYPE; 243 info.fltr_act = action; 244 info.vsi_handle = vsi->idx; 245 info.l_data.ethertype_mac.ethertype = ethertype; 246 247 if (flag == ICE_FLTR_TX) 248 info.src_id = ICE_SRC_ID_VSI; 249 else 250 info.src_id = ICE_SRC_ID_LPORT; 251 252 return ice_fltr_add_entry_to_list(ice_pf_to_dev(vsi->back), &info, 253 list); 254 } 255 256 /** 257 * ice_fltr_prepare_mac - add or remove MAC rule 258 * @vsi: pointer to VSI struct 259 * @mac: MAC address to add 260 * @action: action to be performed on filter match 261 * @mac_action: pointer to add or remove MAC function 262 */ 263 static int 264 ice_fltr_prepare_mac(struct ice_vsi *vsi, const u8 *mac, 265 enum ice_sw_fwd_act_type action, 266 int (*mac_action)(struct ice_vsi *, struct list_head *)) 267 { 268 LIST_HEAD(tmp_list); 269 int result; 270 271 if (ice_fltr_add_mac_to_list(vsi, &tmp_list, mac, action)) { 272 ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list); 273 return -ENOMEM; 274 } 275 276 result = mac_action(vsi, &tmp_list); 277 ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list); 278 return result; 279 } 280 281 /** 282 * ice_fltr_prepare_mac_and_broadcast - add or remove MAC and broadcast filter 283 * @vsi: pointer to VSI struct 284 * @mac: MAC address to add 285 * @action: action to be performed on filter match 286 * @mac_action: pointer to add or remove MAC function 287 */ 288 static int 289 ice_fltr_prepare_mac_and_broadcast(struct ice_vsi *vsi, const u8 *mac, 290 enum ice_sw_fwd_act_type action, 291 int(*mac_action) 292 (struct ice_vsi *, struct list_head *)) 293 { 294 u8 broadcast[ETH_ALEN]; 295 LIST_HEAD(tmp_list); 296 int result; 297 298 eth_broadcast_addr(broadcast); 299 if (ice_fltr_add_mac_to_list(vsi, &tmp_list, mac, action) || 300 ice_fltr_add_mac_to_list(vsi, &tmp_list, broadcast, action)) { 301 ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list); 302 return -ENOMEM; 303 } 304 305 result = mac_action(vsi, &tmp_list); 306 ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list); 307 return result; 308 } 309 310 /** 311 * ice_fltr_prepare_vlan - add or remove VLAN filter 312 * @vsi: pointer to VSI struct 313 * @vlan_id: VLAN ID to add 314 * @action: action to be performed on filter match 315 * @vlan_action: pointer to add or remove VLAN function 316 */ 317 static int 318 ice_fltr_prepare_vlan(struct ice_vsi *vsi, u16 vlan_id, 319 enum ice_sw_fwd_act_type action, 320 int (*vlan_action)(struct ice_vsi *, struct list_head *)) 321 { 322 LIST_HEAD(tmp_list); 323 int result; 324 325 if (ice_fltr_add_vlan_to_list(vsi, &tmp_list, vlan_id, action)) 326 return -ENOMEM; 327 328 result = vlan_action(vsi, &tmp_list); 329 ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list); 330 return result; 331 } 332 333 /** 334 * ice_fltr_prepare_eth - add or remove ethertype filter 335 * @vsi: pointer to VSI struct 336 * @ethertype: ethertype of packet to be filtered 337 * @flag: direction of packet, Tx or Rx 338 * @action: action to be performed on filter match 339 * @eth_action: pointer to add or remove ethertype function 340 */ 341 static int 342 ice_fltr_prepare_eth(struct ice_vsi *vsi, u16 ethertype, u16 flag, 343 enum ice_sw_fwd_act_type action, 344 int (*eth_action)(struct ice_vsi *, struct list_head *)) 345 { 346 LIST_HEAD(tmp_list); 347 int result; 348 349 if (ice_fltr_add_eth_to_list(vsi, &tmp_list, ethertype, flag, action)) 350 return -ENOMEM; 351 352 result = eth_action(vsi, &tmp_list); 353 ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list); 354 return result; 355 } 356 357 /** 358 * ice_fltr_add_mac - add single MAC filter 359 * @vsi: pointer to VSI struct 360 * @mac: MAC to add 361 * @action: action to be performed on filter match 362 */ 363 int ice_fltr_add_mac(struct ice_vsi *vsi, const u8 *mac, 364 enum ice_sw_fwd_act_type action) 365 { 366 return ice_fltr_prepare_mac(vsi, mac, action, ice_fltr_add_mac_list); 367 } 368 369 /** 370 * ice_fltr_add_mac_and_broadcast - add single MAC and broadcast 371 * @vsi: pointer to VSI struct 372 * @mac: MAC to add 373 * @action: action to be performed on filter match 374 */ 375 int 376 ice_fltr_add_mac_and_broadcast(struct ice_vsi *vsi, const u8 *mac, 377 enum ice_sw_fwd_act_type action) 378 { 379 return ice_fltr_prepare_mac_and_broadcast(vsi, mac, action, 380 ice_fltr_add_mac_list); 381 } 382 383 /** 384 * ice_fltr_remove_mac - remove MAC filter 385 * @vsi: pointer to VSI struct 386 * @mac: filter MAC to remove 387 * @action: action to remove 388 */ 389 int ice_fltr_remove_mac(struct ice_vsi *vsi, const u8 *mac, 390 enum ice_sw_fwd_act_type action) 391 { 392 return ice_fltr_prepare_mac(vsi, mac, action, ice_fltr_remove_mac_list); 393 } 394 395 /** 396 * ice_fltr_add_vlan - add single VLAN filter 397 * @vsi: pointer to VSI struct 398 * @vlan_id: VLAN ID to add 399 * @action: action to be performed on filter match 400 */ 401 int ice_fltr_add_vlan(struct ice_vsi *vsi, u16 vlan_id, 402 enum ice_sw_fwd_act_type action) 403 { 404 return ice_fltr_prepare_vlan(vsi, vlan_id, action, 405 ice_fltr_add_vlan_list); 406 } 407 408 /** 409 * ice_fltr_remove_vlan - remove VLAN filter 410 * @vsi: pointer to VSI struct 411 * @vlan_id: filter VLAN to remove 412 * @action: action to remove 413 */ 414 int ice_fltr_remove_vlan(struct ice_vsi *vsi, u16 vlan_id, 415 enum ice_sw_fwd_act_type action) 416 { 417 return ice_fltr_prepare_vlan(vsi, vlan_id, action, 418 ice_fltr_remove_vlan_list); 419 } 420 421 /** 422 * ice_fltr_add_eth - add specyfic ethertype filter 423 * @vsi: pointer to VSI struct 424 * @ethertype: ethertype of filter 425 * @flag: direction of packet to be filtered, Tx or Rx 426 * @action: action to be performed on filter match 427 */ 428 int ice_fltr_add_eth(struct ice_vsi *vsi, u16 ethertype, u16 flag, 429 enum ice_sw_fwd_act_type action) 430 { 431 return ice_fltr_prepare_eth(vsi, ethertype, flag, action, 432 ice_fltr_add_eth_list); 433 } 434 435 /** 436 * ice_fltr_remove_eth - remove ethertype filter 437 * @vsi: pointer to VSI struct 438 * @ethertype: ethertype of filter 439 * @flag: direction of filter 440 * @action: action to remove 441 */ 442 int ice_fltr_remove_eth(struct ice_vsi *vsi, u16 ethertype, u16 flag, 443 enum ice_sw_fwd_act_type action) 444 { 445 return ice_fltr_prepare_eth(vsi, ethertype, flag, action, 446 ice_fltr_remove_eth_list); 447 } 448