ice_fltr.c (12696B)
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 */ 15void 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 */ 31static int 32ice_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 */ 57int 58ice_fltr_set_vlan_vsi_promisc(struct ice_hw *hw, struct ice_vsi *vsi, 59 u8 promisc_mask) 60{ 61 struct ice_pf *pf = hw->back; 62 int result; 63 64 result = ice_set_vlan_vsi_promisc(hw, vsi->idx, promisc_mask, false); 65 if (result) 66 dev_err(ice_pf_to_dev(pf), 67 "Error setting promisc mode on VSI %i (rc=%d)\n", 68 vsi->vsi_num, result); 69 70 return result; 71} 72 73/** 74 * ice_fltr_clear_vlan_vsi_promisc 75 * @hw: pointer to the hardware structure 76 * @vsi: the VSI being configured 77 * @promisc_mask: mask of promiscuous config bits 78 * 79 * Clear VSI with all associated VLANs to given promiscuous mode(s) 80 */ 81int 82ice_fltr_clear_vlan_vsi_promisc(struct ice_hw *hw, struct ice_vsi *vsi, 83 u8 promisc_mask) 84{ 85 struct ice_pf *pf = hw->back; 86 int result; 87 88 result = ice_set_vlan_vsi_promisc(hw, vsi->idx, promisc_mask, true); 89 if (result) 90 dev_err(ice_pf_to_dev(pf), 91 "Error clearing promisc mode on VSI %i (rc=%d)\n", 92 vsi->vsi_num, result); 93 94 return result; 95} 96 97/** 98 * ice_fltr_clear_vsi_promisc - clear specified promiscuous mode(s) 99 * @hw: pointer to the hardware structure 100 * @vsi_handle: VSI handle to clear mode 101 * @promisc_mask: mask of promiscuous config bits to clear 102 * @vid: VLAN ID to clear VLAN promiscuous 103 */ 104int 105ice_fltr_clear_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, 106 u16 vid) 107{ 108 struct ice_pf *pf = hw->back; 109 int result; 110 111 result = ice_clear_vsi_promisc(hw, vsi_handle, promisc_mask, vid); 112 if (result) 113 dev_err(ice_pf_to_dev(pf), 114 "Error clearing promisc mode on VSI %i for VID %u (rc=%d)\n", 115 ice_get_hw_vsi_num(hw, vsi_handle), vid, result); 116 117 return result; 118} 119 120/** 121 * ice_fltr_set_vsi_promisc - set given VSI to given promiscuous mode(s) 122 * @hw: pointer to the hardware structure 123 * @vsi_handle: VSI handle to configure 124 * @promisc_mask: mask of promiscuous config bits 125 * @vid: VLAN ID to set VLAN promiscuous 126 */ 127int 128ice_fltr_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, 129 u16 vid) 130{ 131 struct ice_pf *pf = hw->back; 132 int result; 133 134 result = ice_set_vsi_promisc(hw, vsi_handle, promisc_mask, vid); 135 if (result) 136 dev_err(ice_pf_to_dev(pf), 137 "Error setting promisc mode on VSI %i for VID %u (rc=%d)\n", 138 ice_get_hw_vsi_num(hw, vsi_handle), vid, result); 139 140 return result; 141} 142 143/** 144 * ice_fltr_add_mac_list - add list of MAC filters 145 * @vsi: pointer to VSI struct 146 * @list: list of filters 147 */ 148int ice_fltr_add_mac_list(struct ice_vsi *vsi, struct list_head *list) 149{ 150 return ice_add_mac(&vsi->back->hw, list); 151} 152 153/** 154 * ice_fltr_remove_mac_list - remove list of MAC filters 155 * @vsi: pointer to VSI struct 156 * @list: list of filters 157 */ 158int ice_fltr_remove_mac_list(struct ice_vsi *vsi, struct list_head *list) 159{ 160 return ice_remove_mac(&vsi->back->hw, list); 161} 162 163/** 164 * ice_fltr_add_vlan_list - add list of VLAN filters 165 * @vsi: pointer to VSI struct 166 * @list: list of filters 167 */ 168static int ice_fltr_add_vlan_list(struct ice_vsi *vsi, struct list_head *list) 169{ 170 return ice_add_vlan(&vsi->back->hw, list); 171} 172 173/** 174 * ice_fltr_remove_vlan_list - remove list of VLAN filters 175 * @vsi: pointer to VSI struct 176 * @list: list of filters 177 */ 178static int 179ice_fltr_remove_vlan_list(struct ice_vsi *vsi, struct list_head *list) 180{ 181 return ice_remove_vlan(&vsi->back->hw, list); 182} 183 184/** 185 * ice_fltr_add_eth_list - add list of ethertype filters 186 * @vsi: pointer to VSI struct 187 * @list: list of filters 188 */ 189static int ice_fltr_add_eth_list(struct ice_vsi *vsi, struct list_head *list) 190{ 191 return ice_add_eth_mac(&vsi->back->hw, list); 192} 193 194/** 195 * ice_fltr_remove_eth_list - remove list of ethertype filters 196 * @vsi: pointer to VSI struct 197 * @list: list of filters 198 */ 199static int ice_fltr_remove_eth_list(struct ice_vsi *vsi, struct list_head *list) 200{ 201 return ice_remove_eth_mac(&vsi->back->hw, list); 202} 203 204/** 205 * ice_fltr_remove_all - remove all filters associated with VSI 206 * @vsi: pointer to VSI struct 207 */ 208void ice_fltr_remove_all(struct ice_vsi *vsi) 209{ 210 ice_remove_vsi_fltr(&vsi->back->hw, vsi->idx); 211} 212 213/** 214 * ice_fltr_add_mac_to_list - add MAC filter info to exsisting list 215 * @vsi: pointer to VSI struct 216 * @list: list to add filter info to 217 * @mac: MAC address to add 218 * @action: filter action 219 */ 220int 221ice_fltr_add_mac_to_list(struct ice_vsi *vsi, struct list_head *list, 222 const u8 *mac, enum ice_sw_fwd_act_type action) 223{ 224 struct ice_fltr_info info = { 0 }; 225 226 info.flag = ICE_FLTR_TX; 227 info.src_id = ICE_SRC_ID_VSI; 228 info.lkup_type = ICE_SW_LKUP_MAC; 229 info.fltr_act = action; 230 info.vsi_handle = vsi->idx; 231 232 ether_addr_copy(info.l_data.mac.mac_addr, mac); 233 234 return ice_fltr_add_entry_to_list(ice_pf_to_dev(vsi->back), &info, 235 list); 236} 237 238/** 239 * ice_fltr_add_vlan_to_list - add VLAN filter info to exsisting list 240 * @vsi: pointer to VSI struct 241 * @list: list to add filter info to 242 * @vlan: VLAN filter details 243 */ 244static int 245ice_fltr_add_vlan_to_list(struct ice_vsi *vsi, struct list_head *list, 246 struct ice_vlan *vlan) 247{ 248 struct ice_fltr_info info = { 0 }; 249 250 info.flag = ICE_FLTR_TX; 251 info.src_id = ICE_SRC_ID_VSI; 252 info.lkup_type = ICE_SW_LKUP_VLAN; 253 info.fltr_act = ICE_FWD_TO_VSI; 254 info.vsi_handle = vsi->idx; 255 info.l_data.vlan.vlan_id = vlan->vid; 256 info.l_data.vlan.tpid = vlan->tpid; 257 info.l_data.vlan.tpid_valid = true; 258 259 return ice_fltr_add_entry_to_list(ice_pf_to_dev(vsi->back), &info, 260 list); 261} 262 263/** 264 * ice_fltr_add_eth_to_list - add ethertype filter info to exsisting list 265 * @vsi: pointer to VSI struct 266 * @list: list to add filter info to 267 * @ethertype: ethertype of packet that matches filter 268 * @flag: filter direction, Tx or Rx 269 * @action: filter action 270 */ 271static int 272ice_fltr_add_eth_to_list(struct ice_vsi *vsi, struct list_head *list, 273 u16 ethertype, u16 flag, 274 enum ice_sw_fwd_act_type action) 275{ 276 struct ice_fltr_info info = { 0 }; 277 278 info.flag = flag; 279 info.lkup_type = ICE_SW_LKUP_ETHERTYPE; 280 info.fltr_act = action; 281 info.vsi_handle = vsi->idx; 282 info.l_data.ethertype_mac.ethertype = ethertype; 283 284 if (flag == ICE_FLTR_TX) 285 info.src_id = ICE_SRC_ID_VSI; 286 else 287 info.src_id = ICE_SRC_ID_LPORT; 288 289 return ice_fltr_add_entry_to_list(ice_pf_to_dev(vsi->back), &info, 290 list); 291} 292 293/** 294 * ice_fltr_prepare_mac - add or remove MAC rule 295 * @vsi: pointer to VSI struct 296 * @mac: MAC address to add 297 * @action: action to be performed on filter match 298 * @mac_action: pointer to add or remove MAC function 299 */ 300static int 301ice_fltr_prepare_mac(struct ice_vsi *vsi, const u8 *mac, 302 enum ice_sw_fwd_act_type action, 303 int (*mac_action)(struct ice_vsi *, struct list_head *)) 304{ 305 LIST_HEAD(tmp_list); 306 int result; 307 308 if (ice_fltr_add_mac_to_list(vsi, &tmp_list, mac, action)) { 309 ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list); 310 return -ENOMEM; 311 } 312 313 result = mac_action(vsi, &tmp_list); 314 ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list); 315 return result; 316} 317 318/** 319 * ice_fltr_prepare_mac_and_broadcast - add or remove MAC and broadcast filter 320 * @vsi: pointer to VSI struct 321 * @mac: MAC address to add 322 * @action: action to be performed on filter match 323 * @mac_action: pointer to add or remove MAC function 324 */ 325static int 326ice_fltr_prepare_mac_and_broadcast(struct ice_vsi *vsi, const u8 *mac, 327 enum ice_sw_fwd_act_type action, 328 int(*mac_action) 329 (struct ice_vsi *, struct list_head *)) 330{ 331 u8 broadcast[ETH_ALEN]; 332 LIST_HEAD(tmp_list); 333 int result; 334 335 eth_broadcast_addr(broadcast); 336 if (ice_fltr_add_mac_to_list(vsi, &tmp_list, mac, action) || 337 ice_fltr_add_mac_to_list(vsi, &tmp_list, broadcast, action)) { 338 ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list); 339 return -ENOMEM; 340 } 341 342 result = mac_action(vsi, &tmp_list); 343 ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list); 344 return result; 345} 346 347/** 348 * ice_fltr_prepare_vlan - add or remove VLAN filter 349 * @vsi: pointer to VSI struct 350 * @vlan: VLAN filter details 351 * @vlan_action: pointer to add or remove VLAN function 352 */ 353static int 354ice_fltr_prepare_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan, 355 int (*vlan_action)(struct ice_vsi *, struct list_head *)) 356{ 357 LIST_HEAD(tmp_list); 358 int result; 359 360 if (ice_fltr_add_vlan_to_list(vsi, &tmp_list, vlan)) 361 return -ENOMEM; 362 363 result = vlan_action(vsi, &tmp_list); 364 ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list); 365 return result; 366} 367 368/** 369 * ice_fltr_prepare_eth - add or remove ethertype filter 370 * @vsi: pointer to VSI struct 371 * @ethertype: ethertype of packet to be filtered 372 * @flag: direction of packet, Tx or Rx 373 * @action: action to be performed on filter match 374 * @eth_action: pointer to add or remove ethertype function 375 */ 376static int 377ice_fltr_prepare_eth(struct ice_vsi *vsi, u16 ethertype, u16 flag, 378 enum ice_sw_fwd_act_type action, 379 int (*eth_action)(struct ice_vsi *, struct list_head *)) 380{ 381 LIST_HEAD(tmp_list); 382 int result; 383 384 if (ice_fltr_add_eth_to_list(vsi, &tmp_list, ethertype, flag, action)) 385 return -ENOMEM; 386 387 result = eth_action(vsi, &tmp_list); 388 ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list); 389 return result; 390} 391 392/** 393 * ice_fltr_add_mac - add single MAC filter 394 * @vsi: pointer to VSI struct 395 * @mac: MAC to add 396 * @action: action to be performed on filter match 397 */ 398int ice_fltr_add_mac(struct ice_vsi *vsi, const u8 *mac, 399 enum ice_sw_fwd_act_type action) 400{ 401 return ice_fltr_prepare_mac(vsi, mac, action, ice_fltr_add_mac_list); 402} 403 404/** 405 * ice_fltr_add_mac_and_broadcast - add single MAC and broadcast 406 * @vsi: pointer to VSI struct 407 * @mac: MAC to add 408 * @action: action to be performed on filter match 409 */ 410int 411ice_fltr_add_mac_and_broadcast(struct ice_vsi *vsi, const u8 *mac, 412 enum ice_sw_fwd_act_type action) 413{ 414 return ice_fltr_prepare_mac_and_broadcast(vsi, mac, action, 415 ice_fltr_add_mac_list); 416} 417 418/** 419 * ice_fltr_remove_mac - remove MAC filter 420 * @vsi: pointer to VSI struct 421 * @mac: filter MAC to remove 422 * @action: action to remove 423 */ 424int ice_fltr_remove_mac(struct ice_vsi *vsi, const u8 *mac, 425 enum ice_sw_fwd_act_type action) 426{ 427 return ice_fltr_prepare_mac(vsi, mac, action, ice_fltr_remove_mac_list); 428} 429 430/** 431 * ice_fltr_add_vlan - add single VLAN filter 432 * @vsi: pointer to VSI struct 433 * @vlan: VLAN filter details 434 */ 435int ice_fltr_add_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan) 436{ 437 return ice_fltr_prepare_vlan(vsi, vlan, ice_fltr_add_vlan_list); 438} 439 440/** 441 * ice_fltr_remove_vlan - remove VLAN filter 442 * @vsi: pointer to VSI struct 443 * @vlan: VLAN filter details 444 */ 445int ice_fltr_remove_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan) 446{ 447 return ice_fltr_prepare_vlan(vsi, vlan, ice_fltr_remove_vlan_list); 448} 449 450/** 451 * ice_fltr_add_eth - add specyfic ethertype filter 452 * @vsi: pointer to VSI struct 453 * @ethertype: ethertype of filter 454 * @flag: direction of packet to be filtered, Tx or Rx 455 * @action: action to be performed on filter match 456 */ 457int ice_fltr_add_eth(struct ice_vsi *vsi, u16 ethertype, u16 flag, 458 enum ice_sw_fwd_act_type action) 459{ 460 return ice_fltr_prepare_eth(vsi, ethertype, flag, action, 461 ice_fltr_add_eth_list); 462} 463 464/** 465 * ice_fltr_remove_eth - remove ethertype filter 466 * @vsi: pointer to VSI struct 467 * @ethertype: ethertype of filter 468 * @flag: direction of filter 469 * @action: action to remove 470 */ 471int ice_fltr_remove_eth(struct ice_vsi *vsi, u16 ethertype, u16 flag, 472 enum ice_sw_fwd_act_type action) 473{ 474 return ice_fltr_prepare_eth(vsi, ethertype, flag, action, 475 ice_fltr_remove_eth_list); 476}