ice: Add switch rules to handle LLDP packets
authorDave Ertman <david.m.ertman@intel.com>
Tue, 16 Apr 2019 17:34:55 +0000 (10:34 -0700)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Thu, 30 May 2019 17:31:42 +0000 (10:31 -0700)
Add call to configure dropping egress LLDP packets in ice_vsi_setup
and remove the rule in ice_vsi_release.

Add calls to add/remove rule to route LLDP packets to default VSI when
FW LLDP engine is disabled/enabled and remove rule if applied during
ice_vsi_release.

In the function ice_add_eth_mac(), there is a line that hard codes the
filter info flag to TX. This is incorrect as this flag will be set by
the calling function that built the list of filters to add. So remove
the hard coded value.

This patch also contains a fix to stop treating the DCBx state of
"Not Started" as an error state that kicks DCB in SW mode. This will
address having non-cabled interfaces automatically go into SW mode
with the FW engine running.

Signed-off-by: Dave Ertman <david.m.ertman@intel.com>
Signed-off-by: Anirudh Venkataramanan <anirudh.venkataramanan@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/ice/ice_dcb_lib.c
drivers/net/ethernet/intel/ice/ice_ethtool.c
drivers/net/ethernet/intel/ice/ice_lib.c
drivers/net/ethernet/intel/ice/ice_lib.h
drivers/net/ethernet/intel/ice/ice_switch.c

index b97e3e8d499b860f7915c8e476a113f33612fe4b..e6a4ef6a2565ca9081bb29d1ba9b1d5bf9449044 100644 (file)
@@ -387,10 +387,8 @@ int ice_init_pf_dcb(struct ice_pf *pf, bool locked)
                set_bit(ICE_FLAG_ENABLE_FW_LLDP, pf->flags);
        }
 
-       if (port_info->dcbx_status == ICE_DCBX_STATUS_NOT_STARTED) {
-               sw_default = 1;
+       if (port_info->dcbx_status == ICE_DCBX_STATUS_NOT_STARTED)
                dev_info(&pf->pdev->dev, "DCBX not started\n");
-       }
 
        if (sw_default) {
                err = ice_dcb_sw_dflt_cfg(pf, locked);
index 2da83847b9dca37e2aa3a4ecc70aae14ce5ff8a1..6beb918f625fcaa033958063f5e59ae065023d12 100644 (file)
@@ -1205,6 +1205,7 @@ static int ice_set_priv_flags(struct net_device *netdev, u32 flags)
                if (!test_bit(ICE_FLAG_ENABLE_FW_LLDP, pf->flags)) {
                        enum ice_status status;
 
+                       /* Disable FW LLDP engine */
                        status = ice_aq_cfg_lldp_mib_change(&pf->hw, false,
                                                            NULL);
                        /* If unregistering for LLDP events fails, this is
@@ -1229,6 +1230,11 @@ static int ice_set_priv_flags(struct net_device *netdev, u32 flags)
                        status = ice_init_pf_dcb(pf, true);
                        if (status)
                                dev_warn(&pf->pdev->dev, "Fail to init DCB\n");
+
+                       /* Forward LLDP packets to default VSI so that they
+                        * are passed up the stack
+                        */
+                       ice_cfg_sw_lldp(vsi, false, true);
                } else {
                        enum ice_status status;
                        bool dcbx_agent_status;
@@ -1262,6 +1268,11 @@ static int ice_set_priv_flags(struct net_device *netdev, u32 flags)
                        status = ice_init_pf_dcb(pf, true);
                        if (status)
                                dev_dbg(&pf->pdev->dev, "Fail to init DCB\n");
+
+                       /* Remove rule to direct LLDP packets to default VSI.
+                        * The FW LLDP engine will now be consuming them.
+                        */
+                       ice_cfg_sw_lldp(vsi, false, false);
                }
        }
        clear_bit(ICE_FLAG_ETHTOOL_CTXT, pf->flags);
index d0410c686ef4d9e383b90d716b51824e20bf2d94..7625a4c0532d686beaf0814c2907293cc11d7fa5 100644 (file)
@@ -2345,6 +2345,56 @@ ice_vsi_add_rem_eth_mac(struct ice_vsi *vsi, bool add_rule)
        ice_free_fltr_list(&pf->pdev->dev, &tmp_add_list);
 }
 
+#define ICE_ETH_P_LLDP 0x88CC
+
+/**
+ * ice_cfg_sw_lldp - Config switch rules for LLDP packet handling
+ * @vsi: the VSI being configured
+ * @tx: bool to determine Tx or Rx rule
+ * @create: bool to determine create or remove Rule
+ */
+void ice_cfg_sw_lldp(struct ice_vsi *vsi, bool tx, bool create)
+{
+       struct ice_fltr_list_entry *list;
+       struct ice_pf *pf = vsi->back;
+       LIST_HEAD(tmp_add_list);
+       enum ice_status status;
+
+       list = devm_kzalloc(&pf->pdev->dev, sizeof(*list), GFP_KERNEL);
+       if (!list)
+               return;
+
+       list->fltr_info.lkup_type = ICE_SW_LKUP_ETHERTYPE;
+       list->fltr_info.vsi_handle = vsi->idx;
+       list->fltr_info.l_data.ethertype_mac.ethertype = ICE_ETH_P_LLDP;
+
+       if (tx) {
+               list->fltr_info.fltr_act = ICE_DROP_PACKET;
+               list->fltr_info.flag = ICE_FLTR_TX;
+               list->fltr_info.src_id = ICE_SRC_ID_VSI;
+       } else {
+               list->fltr_info.fltr_act = ICE_FWD_TO_VSI;
+               list->fltr_info.flag = ICE_FLTR_RX;
+               list->fltr_info.src_id = ICE_SRC_ID_LPORT;
+       }
+
+       INIT_LIST_HEAD(&list->list_entry);
+       list_add(&list->list_entry, &tmp_add_list);
+
+       if (create)
+               status = ice_add_eth_mac(&pf->hw, &tmp_add_list);
+       else
+               status = ice_remove_eth_mac(&pf->hw, &tmp_add_list);
+
+       if (status)
+               dev_err(&pf->pdev->dev,
+                       "Fail %s %s LLDP rule on VSI %i error: %d\n",
+                       create ? "adding" : "removing", tx ? "TX" : "RX",
+                       vsi->vsi_num, status);
+
+       ice_free_fltr_list(&pf->pdev->dev, &tmp_add_list);
+}
+
 /**
  * ice_vsi_setup - Set up a VSI by a given type
  * @pf: board private structure
@@ -2487,10 +2537,22 @@ ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi,
         * out PAUSE or PFC frames. If enabled, FW can still send FC frames.
         * The rule is added once for PF VSI in order to create appropriate
         * recipe, since VSI/VSI list is ignored with drop action...
+        * Also add rules to handle LLDP Tx and Rx packets.  Tx LLDP packets
+        * need to be dropped so that VFs cannot send LLDP packets to reconfig
+        * DCB settings in the HW.  Also, if the FW DCBx engine is not running
+        * then Rx LLDP packets need to be redirected up the stack.
         */
-       if (vsi->type == ICE_VSI_PF)
+       if (vsi->type == ICE_VSI_PF) {
                ice_vsi_add_rem_eth_mac(vsi, true);
 
+               /* Tx LLDP packets */
+               ice_cfg_sw_lldp(vsi, true, true);
+
+               /* Rx LLDP packets */
+               if (!test_bit(ICE_FLAG_ENABLE_FW_LLDP, pf->flags))
+                       ice_cfg_sw_lldp(vsi, false, true);
+       }
+
        return vsi;
 
 unroll_vector_base:
@@ -2829,8 +2891,15 @@ int ice_vsi_release(struct ice_vsi *vsi)
                pf->num_avail_sw_msix += vsi->num_q_vectors;
        }
 
-       if (vsi->type == ICE_VSI_PF)
+       if (vsi->type == ICE_VSI_PF) {
                ice_vsi_add_rem_eth_mac(vsi, false);
+               ice_cfg_sw_lldp(vsi, true, false);
+               /* The Rx rule will only exist to remove if the LLDP FW
+                * engine is currently stopped
+                */
+               if (!test_bit(ICE_FLAG_ENABLE_FW_LLDP, pf->flags))
+                       ice_cfg_sw_lldp(vsi, false, false);
+       }
 
        ice_remove_vsi_fltr(&pf->hw, vsi->idx);
        ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx);
index 2acae3215f5f4d118b92ef6d07c8d9b4da7d1892..6e43ef03bfc3571e8fa2a8f30c897f9acbc3dafe 100644 (file)
@@ -45,6 +45,8 @@ ice_vsi_stop_lan_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src,
 
 int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena, bool vlan_promisc);
 
+void ice_cfg_sw_lldp(struct ice_vsi *vsi, bool tx, bool create);
+
 void ice_vsi_delete(struct ice_vsi *vsi);
 
 int ice_vsi_clear(struct ice_vsi *vsi);
index 5b82a7280783755e6f5f625cfaf89ab013ed9a1f..8271fd6517254de88dc384363dfb598556d12870 100644 (file)
@@ -1973,6 +1973,10 @@ ice_add_vlan(struct ice_hw *hw, struct list_head *v_list)
  * ice_add_eth_mac - Add ethertype and MAC based filter rule
  * @hw: pointer to the hardware structure
  * @em_list: list of ether type MAC filter, MAC is optional
+ *
+ * This function requires the caller to populate the entries in
+ * the filter list with the necessary fields (including flags to
+ * indicate Tx or Rx rules).
  */
 enum ice_status
 ice_add_eth_mac(struct ice_hw *hw, struct list_head *em_list)
@@ -1990,7 +1994,6 @@ ice_add_eth_mac(struct ice_hw *hw, struct list_head *em_list)
                    l_type != ICE_SW_LKUP_ETHERTYPE)
                        return ICE_ERR_PARAM;
 
-               em_list_itr->fltr_info.flag = ICE_FLTR_TX;
                em_list_itr->status = ice_add_rule_internal(hw, l_type,
                                                            em_list_itr);
                if (em_list_itr->status)