Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright (C) 2018-2020, Intel Corporation. */
0003 
0004 #include "ice.h"
0005 #include "ice_fltr.h"
0006 
0007 /**
0008  * ice_fltr_free_list - free filter lists helper
0009  * @dev: pointer to the device struct
0010  * @h: pointer to the list head to be freed
0011  *
0012  * Helper function to free filter lists previously created using
0013  * ice_fltr_add_mac_to_list
0014  */
0015 void ice_fltr_free_list(struct device *dev, struct list_head *h)
0016 {
0017     struct ice_fltr_list_entry *e, *tmp;
0018 
0019     list_for_each_entry_safe(e, tmp, h, list_entry) {
0020         list_del(&e->list_entry);
0021         devm_kfree(dev, e);
0022     }
0023 }
0024 
0025 /**
0026  * ice_fltr_add_entry_to_list - allocate and add filter entry to list
0027  * @dev: pointer to device needed by alloc function
0028  * @info: filter info struct that gets added to the passed in list
0029  * @list: pointer to the list which contains MAC filters entry
0030  */
0031 static int
0032 ice_fltr_add_entry_to_list(struct device *dev, struct ice_fltr_info *info,
0033                struct list_head *list)
0034 {
0035     struct ice_fltr_list_entry *entry;
0036 
0037     entry = devm_kzalloc(dev, sizeof(*entry), GFP_ATOMIC);
0038     if (!entry)
0039         return -ENOMEM;
0040 
0041     entry->fltr_info = *info;
0042 
0043     INIT_LIST_HEAD(&entry->list_entry);
0044     list_add(&entry->list_entry, list);
0045 
0046     return 0;
0047 }
0048 
0049 /**
0050  * ice_fltr_set_vlan_vsi_promisc
0051  * @hw: pointer to the hardware structure
0052  * @vsi: the VSI being configured
0053  * @promisc_mask: mask of promiscuous config bits
0054  *
0055  * Set VSI with all associated VLANs to given promiscuous mode(s)
0056  */
0057 int
0058 ice_fltr_set_vlan_vsi_promisc(struct ice_hw *hw, struct ice_vsi *vsi,
0059                   u8 promisc_mask)
0060 {
0061     struct ice_pf *pf = hw->back;
0062     int result;
0063 
0064     result = ice_set_vlan_vsi_promisc(hw, vsi->idx, promisc_mask, false);
0065     if (result && result != -EEXIST)
0066         dev_err(ice_pf_to_dev(pf),
0067             "Error setting promisc mode on VSI %i (rc=%d)\n",
0068             vsi->vsi_num, result);
0069 
0070     return result;
0071 }
0072 
0073 /**
0074  * ice_fltr_clear_vlan_vsi_promisc
0075  * @hw: pointer to the hardware structure
0076  * @vsi: the VSI being configured
0077  * @promisc_mask: mask of promiscuous config bits
0078  *
0079  * Clear VSI with all associated VLANs to given promiscuous mode(s)
0080  */
0081 int
0082 ice_fltr_clear_vlan_vsi_promisc(struct ice_hw *hw, struct ice_vsi *vsi,
0083                 u8 promisc_mask)
0084 {
0085     struct ice_pf *pf = hw->back;
0086     int result;
0087 
0088     result = ice_set_vlan_vsi_promisc(hw, vsi->idx, promisc_mask, true);
0089     if (result && result != -EEXIST)
0090         dev_err(ice_pf_to_dev(pf),
0091             "Error clearing promisc mode on VSI %i (rc=%d)\n",
0092             vsi->vsi_num, result);
0093 
0094     return result;
0095 }
0096 
0097 /**
0098  * ice_fltr_clear_vsi_promisc - clear specified promiscuous mode(s)
0099  * @hw: pointer to the hardware structure
0100  * @vsi_handle: VSI handle to clear mode
0101  * @promisc_mask: mask of promiscuous config bits to clear
0102  * @vid: VLAN ID to clear VLAN promiscuous
0103  */
0104 int
0105 ice_fltr_clear_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
0106                u16 vid)
0107 {
0108     struct ice_pf *pf = hw->back;
0109     int result;
0110 
0111     result = ice_clear_vsi_promisc(hw, vsi_handle, promisc_mask, vid);
0112     if (result && result != -EEXIST)
0113         dev_err(ice_pf_to_dev(pf),
0114             "Error clearing promisc mode on VSI %i for VID %u (rc=%d)\n",
0115             ice_get_hw_vsi_num(hw, vsi_handle), vid, result);
0116 
0117     return result;
0118 }
0119 
0120 /**
0121  * ice_fltr_set_vsi_promisc - set given VSI to given promiscuous mode(s)
0122  * @hw: pointer to the hardware structure
0123  * @vsi_handle: VSI handle to configure
0124  * @promisc_mask: mask of promiscuous config bits
0125  * @vid: VLAN ID to set VLAN promiscuous
0126  */
0127 int
0128 ice_fltr_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
0129              u16 vid)
0130 {
0131     struct ice_pf *pf = hw->back;
0132     int result;
0133 
0134     result = ice_set_vsi_promisc(hw, vsi_handle, promisc_mask, vid);
0135     if (result && result != -EEXIST)
0136         dev_err(ice_pf_to_dev(pf),
0137             "Error setting promisc mode on VSI %i for VID %u (rc=%d)\n",
0138             ice_get_hw_vsi_num(hw, vsi_handle), vid, result);
0139 
0140     return result;
0141 }
0142 
0143 /**
0144  * ice_fltr_add_mac_list - add list of MAC filters
0145  * @vsi: pointer to VSI struct
0146  * @list: list of filters
0147  */
0148 int ice_fltr_add_mac_list(struct ice_vsi *vsi, struct list_head *list)
0149 {
0150     return ice_add_mac(&vsi->back->hw, list);
0151 }
0152 
0153 /**
0154  * ice_fltr_remove_mac_list - remove list of MAC filters
0155  * @vsi: pointer to VSI struct
0156  * @list: list of filters
0157  */
0158 int ice_fltr_remove_mac_list(struct ice_vsi *vsi, struct list_head *list)
0159 {
0160     return ice_remove_mac(&vsi->back->hw, list);
0161 }
0162 
0163 /**
0164  * ice_fltr_add_vlan_list - add list of VLAN filters
0165  * @vsi: pointer to VSI struct
0166  * @list: list of filters
0167  */
0168 static int ice_fltr_add_vlan_list(struct ice_vsi *vsi, struct list_head *list)
0169 {
0170     return ice_add_vlan(&vsi->back->hw, list);
0171 }
0172 
0173 /**
0174  * ice_fltr_remove_vlan_list - remove list of VLAN filters
0175  * @vsi: pointer to VSI struct
0176  * @list: list of filters
0177  */
0178 static int
0179 ice_fltr_remove_vlan_list(struct ice_vsi *vsi, struct list_head *list)
0180 {
0181     return ice_remove_vlan(&vsi->back->hw, list);
0182 }
0183 
0184 /**
0185  * ice_fltr_add_eth_list - add list of ethertype filters
0186  * @vsi: pointer to VSI struct
0187  * @list: list of filters
0188  */
0189 static int ice_fltr_add_eth_list(struct ice_vsi *vsi, struct list_head *list)
0190 {
0191     return ice_add_eth_mac(&vsi->back->hw, list);
0192 }
0193 
0194 /**
0195  * ice_fltr_remove_eth_list - remove list of ethertype filters
0196  * @vsi: pointer to VSI struct
0197  * @list: list of filters
0198  */
0199 static int ice_fltr_remove_eth_list(struct ice_vsi *vsi, struct list_head *list)
0200 {
0201     return ice_remove_eth_mac(&vsi->back->hw, list);
0202 }
0203 
0204 /**
0205  * ice_fltr_remove_all - remove all filters associated with VSI
0206  * @vsi: pointer to VSI struct
0207  */
0208 void ice_fltr_remove_all(struct ice_vsi *vsi)
0209 {
0210     ice_remove_vsi_fltr(&vsi->back->hw, vsi->idx);
0211 }
0212 
0213 /**
0214  * ice_fltr_add_mac_to_list - add MAC filter info to exsisting list
0215  * @vsi: pointer to VSI struct
0216  * @list: list to add filter info to
0217  * @mac: MAC address to add
0218  * @action: filter action
0219  */
0220 int
0221 ice_fltr_add_mac_to_list(struct ice_vsi *vsi, struct list_head *list,
0222              const u8 *mac, enum ice_sw_fwd_act_type action)
0223 {
0224     struct ice_fltr_info info = { 0 };
0225 
0226     info.flag = ICE_FLTR_TX;
0227     info.src_id = ICE_SRC_ID_VSI;
0228     info.lkup_type = ICE_SW_LKUP_MAC;
0229     info.fltr_act = action;
0230     info.vsi_handle = vsi->idx;
0231 
0232     ether_addr_copy(info.l_data.mac.mac_addr, mac);
0233 
0234     return ice_fltr_add_entry_to_list(ice_pf_to_dev(vsi->back), &info,
0235                       list);
0236 }
0237 
0238 /**
0239  * ice_fltr_add_vlan_to_list - add VLAN filter info to exsisting list
0240  * @vsi: pointer to VSI struct
0241  * @list: list to add filter info to
0242  * @vlan: VLAN filter details
0243  */
0244 static int
0245 ice_fltr_add_vlan_to_list(struct ice_vsi *vsi, struct list_head *list,
0246               struct ice_vlan *vlan)
0247 {
0248     struct ice_fltr_info info = { 0 };
0249 
0250     info.flag = ICE_FLTR_TX;
0251     info.src_id = ICE_SRC_ID_VSI;
0252     info.lkup_type = ICE_SW_LKUP_VLAN;
0253     info.fltr_act = ICE_FWD_TO_VSI;
0254     info.vsi_handle = vsi->idx;
0255     info.l_data.vlan.vlan_id = vlan->vid;
0256     info.l_data.vlan.tpid = vlan->tpid;
0257     info.l_data.vlan.tpid_valid = true;
0258 
0259     return ice_fltr_add_entry_to_list(ice_pf_to_dev(vsi->back), &info,
0260                       list);
0261 }
0262 
0263 /**
0264  * ice_fltr_add_eth_to_list - add ethertype filter info to exsisting list
0265  * @vsi: pointer to VSI struct
0266  * @list: list to add filter info to
0267  * @ethertype: ethertype of packet that matches filter
0268  * @flag: filter direction, Tx or Rx
0269  * @action: filter action
0270  */
0271 static int
0272 ice_fltr_add_eth_to_list(struct ice_vsi *vsi, struct list_head *list,
0273              u16 ethertype, u16 flag,
0274              enum ice_sw_fwd_act_type action)
0275 {
0276     struct ice_fltr_info info = { 0 };
0277 
0278     info.flag = flag;
0279     info.lkup_type = ICE_SW_LKUP_ETHERTYPE;
0280     info.fltr_act = action;
0281     info.vsi_handle = vsi->idx;
0282     info.l_data.ethertype_mac.ethertype = ethertype;
0283 
0284     if (flag == ICE_FLTR_TX)
0285         info.src_id = ICE_SRC_ID_VSI;
0286     else
0287         info.src_id = ICE_SRC_ID_LPORT;
0288 
0289     return ice_fltr_add_entry_to_list(ice_pf_to_dev(vsi->back), &info,
0290                       list);
0291 }
0292 
0293 /**
0294  * ice_fltr_prepare_mac - add or remove MAC rule
0295  * @vsi: pointer to VSI struct
0296  * @mac: MAC address to add
0297  * @action: action to be performed on filter match
0298  * @mac_action: pointer to add or remove MAC function
0299  */
0300 static int
0301 ice_fltr_prepare_mac(struct ice_vsi *vsi, const u8 *mac,
0302              enum ice_sw_fwd_act_type action,
0303              int (*mac_action)(struct ice_vsi *, struct list_head *))
0304 {
0305     LIST_HEAD(tmp_list);
0306     int result;
0307 
0308     if (ice_fltr_add_mac_to_list(vsi, &tmp_list, mac, action)) {
0309         ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list);
0310         return -ENOMEM;
0311     }
0312 
0313     result = mac_action(vsi, &tmp_list);
0314     ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list);
0315     return result;
0316 }
0317 
0318 /**
0319  * ice_fltr_prepare_mac_and_broadcast - add or remove MAC and broadcast filter
0320  * @vsi: pointer to VSI struct
0321  * @mac: MAC address to add
0322  * @action: action to be performed on filter match
0323  * @mac_action: pointer to add or remove MAC function
0324  */
0325 static int
0326 ice_fltr_prepare_mac_and_broadcast(struct ice_vsi *vsi, const u8 *mac,
0327                    enum ice_sw_fwd_act_type action,
0328                    int(*mac_action)
0329                    (struct ice_vsi *, struct list_head *))
0330 {
0331     u8 broadcast[ETH_ALEN];
0332     LIST_HEAD(tmp_list);
0333     int result;
0334 
0335     eth_broadcast_addr(broadcast);
0336     if (ice_fltr_add_mac_to_list(vsi, &tmp_list, mac, action) ||
0337         ice_fltr_add_mac_to_list(vsi, &tmp_list, broadcast, action)) {
0338         ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list);
0339         return -ENOMEM;
0340     }
0341 
0342     result = mac_action(vsi, &tmp_list);
0343     ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list);
0344     return result;
0345 }
0346 
0347 /**
0348  * ice_fltr_prepare_vlan - add or remove VLAN filter
0349  * @vsi: pointer to VSI struct
0350  * @vlan: VLAN filter details
0351  * @vlan_action: pointer to add or remove VLAN function
0352  */
0353 static int
0354 ice_fltr_prepare_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan,
0355               int (*vlan_action)(struct ice_vsi *, struct list_head *))
0356 {
0357     LIST_HEAD(tmp_list);
0358     int result;
0359 
0360     if (ice_fltr_add_vlan_to_list(vsi, &tmp_list, vlan))
0361         return -ENOMEM;
0362 
0363     result = vlan_action(vsi, &tmp_list);
0364     ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list);
0365     return result;
0366 }
0367 
0368 /**
0369  * ice_fltr_prepare_eth - add or remove ethertype filter
0370  * @vsi: pointer to VSI struct
0371  * @ethertype: ethertype of packet to be filtered
0372  * @flag: direction of packet, Tx or Rx
0373  * @action: action to be performed on filter match
0374  * @eth_action: pointer to add or remove ethertype function
0375  */
0376 static int
0377 ice_fltr_prepare_eth(struct ice_vsi *vsi, u16 ethertype, u16 flag,
0378              enum ice_sw_fwd_act_type action,
0379              int (*eth_action)(struct ice_vsi *, struct list_head *))
0380 {
0381     LIST_HEAD(tmp_list);
0382     int result;
0383 
0384     if (ice_fltr_add_eth_to_list(vsi, &tmp_list, ethertype, flag, action))
0385         return -ENOMEM;
0386 
0387     result = eth_action(vsi, &tmp_list);
0388     ice_fltr_free_list(ice_pf_to_dev(vsi->back), &tmp_list);
0389     return result;
0390 }
0391 
0392 /**
0393  * ice_fltr_add_mac - add single MAC filter
0394  * @vsi: pointer to VSI struct
0395  * @mac: MAC to add
0396  * @action: action to be performed on filter match
0397  */
0398 int ice_fltr_add_mac(struct ice_vsi *vsi, const u8 *mac,
0399              enum ice_sw_fwd_act_type action)
0400 {
0401     return ice_fltr_prepare_mac(vsi, mac, action, ice_fltr_add_mac_list);
0402 }
0403 
0404 /**
0405  * ice_fltr_add_mac_and_broadcast - add single MAC and broadcast
0406  * @vsi: pointer to VSI struct
0407  * @mac: MAC to add
0408  * @action: action to be performed on filter match
0409  */
0410 int
0411 ice_fltr_add_mac_and_broadcast(struct ice_vsi *vsi, const u8 *mac,
0412                    enum ice_sw_fwd_act_type action)
0413 {
0414     return ice_fltr_prepare_mac_and_broadcast(vsi, mac, action,
0415                           ice_fltr_add_mac_list);
0416 }
0417 
0418 /**
0419  * ice_fltr_remove_mac - remove MAC filter
0420  * @vsi: pointer to VSI struct
0421  * @mac: filter MAC to remove
0422  * @action: action to remove
0423  */
0424 int ice_fltr_remove_mac(struct ice_vsi *vsi, const u8 *mac,
0425             enum ice_sw_fwd_act_type action)
0426 {
0427     return ice_fltr_prepare_mac(vsi, mac, action, ice_fltr_remove_mac_list);
0428 }
0429 
0430 /**
0431  * ice_fltr_add_vlan - add single VLAN filter
0432  * @vsi: pointer to VSI struct
0433  * @vlan: VLAN filter details
0434  */
0435 int ice_fltr_add_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan)
0436 {
0437     return ice_fltr_prepare_vlan(vsi, vlan, ice_fltr_add_vlan_list);
0438 }
0439 
0440 /**
0441  * ice_fltr_remove_vlan - remove VLAN filter
0442  * @vsi: pointer to VSI struct
0443  * @vlan: VLAN filter details
0444  */
0445 int ice_fltr_remove_vlan(struct ice_vsi *vsi, struct ice_vlan *vlan)
0446 {
0447     return ice_fltr_prepare_vlan(vsi, vlan, ice_fltr_remove_vlan_list);
0448 }
0449 
0450 /**
0451  * ice_fltr_add_eth - add specyfic ethertype filter
0452  * @vsi: pointer to VSI struct
0453  * @ethertype: ethertype of filter
0454  * @flag: direction of packet to be filtered, Tx or Rx
0455  * @action: action to be performed on filter match
0456  */
0457 int ice_fltr_add_eth(struct ice_vsi *vsi, u16 ethertype, u16 flag,
0458              enum ice_sw_fwd_act_type action)
0459 {
0460     return ice_fltr_prepare_eth(vsi, ethertype, flag, action,
0461                     ice_fltr_add_eth_list);
0462 }
0463 
0464 /**
0465  * ice_fltr_remove_eth - remove ethertype filter
0466  * @vsi: pointer to VSI struct
0467  * @ethertype: ethertype of filter
0468  * @flag: direction of filter
0469  * @action: action to remove
0470  */
0471 int ice_fltr_remove_eth(struct ice_vsi *vsi, u16 ethertype, u16 flag,
0472             enum ice_sw_fwd_act_type action)
0473 {
0474     return ice_fltr_prepare_eth(vsi, ethertype, flag, action,
0475                     ice_fltr_remove_eth_list);
0476 }