OSDN Git Service

igc: Refactor igc_ethtool_add_nfc_rule()
authorAndre Guedes <andre.guedes@intel.com>
Fri, 24 Apr 2020 20:16:12 +0000 (13:16 -0700)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Sat, 23 May 2020 01:21:51 +0000 (18:21 -0700)
Current implementation of igc_ethtool_add_nfc_rule() is quite long and a
bit convoluted so this patch does a code refactoring to improve the
code.

Code related to NFC rule object initialization is refactored out to the
local helper function igc_ethtool_init_nfc_rule(). Likewise, code
related to NFC rule validation is refactored out to another local
helper, igc_ethtool_is_nfc_rule_valid().

RX_CLS_FLOW_DISC check is removed since it is redundant. The macro is
defined as the max value fsp->ring_cookie can have, so checking if
fsp->ring_cookie >= adapter->num_rx_queues is already sufficient.

Finally, some log messages are improved or added, and obvious comments
are removed.

Signed-off-by: Andre Guedes <andre.guedes@intel.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/igc/igc_ethtool.c

index 66e0760..1145c88 100644 (file)
@@ -1271,9 +1271,6 @@ static int igc_ethtool_update_nfc_rule(struct igc_adapter *adapter,
        if (!input)
                return err;
 
-       /* initialize node */
-       INIT_HLIST_NODE(&input->nfc_node);
-
        /* add filter to the list */
        if (parent)
                hlist_add_behind(&input->nfc_node, &parent->nfc_node);
@@ -1286,41 +1283,19 @@ static int igc_ethtool_update_nfc_rule(struct igc_adapter *adapter,
        return 0;
 }
 
-static int igc_ethtool_add_nfc_rule(struct igc_adapter *adapter,
-                                   struct ethtool_rxnfc *cmd)
+static void igc_ethtool_init_nfc_rule(struct igc_nfc_rule *rule,
+                                     const struct ethtool_rx_flow_spec *fsp)
 {
-       struct net_device *netdev = adapter->netdev;
-       struct ethtool_rx_flow_spec *fsp =
-               (struct ethtool_rx_flow_spec *)&cmd->fs;
-       struct igc_nfc_rule *rule, *tmp;
-       int err = 0;
-
-       if (!(netdev->hw_features & NETIF_F_NTUPLE))
-               return -EOPNOTSUPP;
+       INIT_HLIST_NODE(&rule->nfc_node);
 
-       /* Don't allow programming if the action is a queue greater than
-        * the number of online Rx queues.
-        */
-       if (fsp->ring_cookie == RX_CLS_FLOW_DISC ||
-           fsp->ring_cookie >= adapter->num_rx_queues) {
-               netdev_err(netdev,
-                          "ethtool -N: The specified action is invalid\n");
-               return -EINVAL;
-       }
+       rule->action = fsp->ring_cookie;
+       rule->sw_idx = fsp->location;
 
-       /* Don't allow indexes to exist outside of available space */
-       if (fsp->location >= IGC_MAX_RXNFC_RULES) {
-               netdev_err(netdev, "Location out of range\n");
-               return -EINVAL;
+       if ((fsp->flow_type & FLOW_EXT) && fsp->m_ext.vlan_tci) {
+               rule->filter.vlan_tci = ntohs(fsp->h_ext.vlan_tci);
+               rule->filter.match_flags |= IGC_FILTER_FLAG_VLAN_TCI;
        }
 
-       if ((fsp->flow_type & ~FLOW_EXT) != ETHER_FLOW)
-               return -EINVAL;
-
-       rule = kzalloc(sizeof(*rule), GFP_KERNEL);
-       if (!rule)
-               return -ENOMEM;
-
        if (fsp->m_u.ether_spec.h_proto == ETHER_TYPE_FULL_MASK) {
                rule->filter.etype = ntohs(fsp->h_u.ether_spec.h_proto);
                rule->filter.match_flags = IGC_FILTER_FLAG_ETHER_TYPE;
@@ -1340,51 +1315,110 @@ static int igc_ethtool_add_nfc_rule(struct igc_adapter *adapter,
                ether_addr_copy(rule->filter.dst_addr,
                                fsp->h_u.ether_spec.h_dest);
        }
+}
 
-       if (rule->filter.match_flags & IGC_FILTER_FLAG_DST_MAC_ADDR &&
-           rule->filter.match_flags & IGC_FILTER_FLAG_SRC_MAC_ADDR) {
-               netdev_dbg(netdev, "Filters with both dst and src are not supported\n");
-               err = -EOPNOTSUPP;
-               goto err_out;
-       }
+/**
+ * igc_ethtool_check_nfc_rule() - Check if NFC rule is valid
+ * @adapter: Pointer to adapter
+ * @rule: Rule under evaluation
+ *
+ * Rules with both destination and source MAC addresses are considered invalid
+ * since the driver doesn't support them.
+ *
+ * Also, if there is already another rule with the same filter, @rule is
+ * considered invalid.
+ *
+ * Context: Expects adapter->nfc_rule_lock to be held by caller.
+ *
+ * Return: 0 in case of success, negative errno code otherwise.
+ */
+static int igc_ethtool_check_nfc_rule(struct igc_adapter *adapter,
+                                     struct igc_nfc_rule *rule)
+{
+       struct net_device *dev = adapter->netdev;
+       u8 flags = rule->filter.match_flags;
+       struct igc_nfc_rule *tmp;
 
-       if ((fsp->flow_type & FLOW_EXT) && fsp->m_ext.vlan_tci) {
-               if (fsp->m_ext.vlan_tci != htons(VLAN_PRIO_MASK)) {
-                       netdev_dbg(netdev, "VLAN mask not supported\n");
-                       err = -EOPNOTSUPP;
-                       goto err_out;
-               }
-               rule->filter.vlan_tci = ntohs(fsp->h_ext.vlan_tci);
-               rule->filter.match_flags |= IGC_FILTER_FLAG_VLAN_TCI;
+       if (!flags) {
+               netdev_dbg(dev, "Rule with no match\n");
+               return -EINVAL;
        }
 
-       rule->action = fsp->ring_cookie;
-       rule->sw_idx = fsp->location;
-
-       spin_lock(&adapter->nfc_rule_lock);
+       if (flags & IGC_FILTER_FLAG_DST_MAC_ADDR &&
+           flags & IGC_FILTER_FLAG_SRC_MAC_ADDR) {
+               netdev_dbg(dev, "Filters with both dst and src are not supported\n");
+               return -EOPNOTSUPP;
+       }
 
        hlist_for_each_entry(tmp, &adapter->nfc_rule_list, nfc_node) {
                if (!memcmp(&rule->filter, &tmp->filter,
                            sizeof(rule->filter))) {
-                       err = -EEXIST;
-                       netdev_err(netdev,
-                                  "ethtool: this filter is already set\n");
-                       goto err_out_w_lock;
+                       netdev_dbg(dev, "Rule already exists\n");
+                       return -EEXIST;
                }
        }
 
+       return 0;
+}
+
+static int igc_ethtool_add_nfc_rule(struct igc_adapter *adapter,
+                                   struct ethtool_rxnfc *cmd)
+{
+       struct net_device *netdev = adapter->netdev;
+       struct ethtool_rx_flow_spec *fsp =
+               (struct ethtool_rx_flow_spec *)&cmd->fs;
+       struct igc_nfc_rule *rule;
+       int err;
+
+       if (!(netdev->hw_features & NETIF_F_NTUPLE)) {
+               netdev_dbg(netdev, "N-tuple filters disabled\n");
+               return -EOPNOTSUPP;
+       }
+
+       if ((fsp->flow_type & ~FLOW_EXT) != ETHER_FLOW) {
+               netdev_dbg(netdev, "Only ethernet flow type is supported\n");
+               return -EOPNOTSUPP;
+       }
+
+       if ((fsp->flow_type & FLOW_EXT) &&
+           fsp->m_ext.vlan_tci != htons(VLAN_PRIO_MASK)) {
+               netdev_dbg(netdev, "VLAN mask not supported\n");
+               return -EOPNOTSUPP;
+       }
+
+       if (fsp->ring_cookie >= adapter->num_rx_queues) {
+               netdev_dbg(netdev, "Invalid action\n");
+               return -EINVAL;
+       }
+
+       if (fsp->location >= IGC_MAX_RXNFC_RULES) {
+               netdev_dbg(netdev, "Invalid location\n");
+               return -EINVAL;
+       }
+
+       rule = kzalloc(sizeof(*rule), GFP_KERNEL);
+       if (!rule)
+               return -ENOMEM;
+
+       igc_ethtool_init_nfc_rule(rule, fsp);
+
+       spin_lock(&adapter->nfc_rule_lock);
+
+       err = igc_ethtool_check_nfc_rule(adapter, rule);
+       if (err)
+               goto err;
+
        err = igc_enable_nfc_rule(adapter, rule);
        if (err)
-               goto err_out_w_lock;
+               goto err;
 
        igc_ethtool_update_nfc_rule(adapter, rule, rule->sw_idx);
 
        spin_unlock(&adapter->nfc_rule_lock);
        return 0;
 
-err_out_w_lock:
+err:
        spin_unlock(&adapter->nfc_rule_lock);
-err_out:
        kfree(rule);
        return err;
 }