]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
i40e: Change the default for VFs to be not privileged
authorAnjali Singhai Jain <anjali.singhai@intel.com>
Thu, 26 May 2016 17:42:11 +0000 (13:42 -0400)
committerChuck Anderson <chuck.anderson@oracle.com>
Thu, 7 Jul 2016 17:41:12 +0000 (10:41 -0700)
Orabug: 23176970

Make sure a VF is not trusted/privileged until its explicitly
set for trust through the new NDO op interface.

Change-Id: I476385c290d2b4901d8fceb29de43546accdc499
Signed-off-by: Anjali Singhai Jain <anjali.singhai@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
(backport of commit 692fb0a75e816d2676f222c9db33e91f46ea1e03)

Signed-off-by: Brian Maly <brian.maly@oracle.com>
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h

index 419ed1cc894551078a4702746a33079539dca3ef..f5c984b9d28d10b51daca2906f8872a46c562410 100644 (file)
@@ -2094,6 +2094,12 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
                }
        }
 
+       /* if the VF is not trusted do not do promisc */
+       if ((vsi->type == I40E_VSI_SRIOV) && !pf->vf[vsi->vf_id].trusted) {
+               clear_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state);
+               goto out;
+       }
+
        /* check for changes in promiscuous modes */
        if (changed_flags & IFF_ALLMULTI) {
                bool cur_multipromisc;
index 9cffcccbc70a162355d1de62b8e37c1963a902cf..30f01b323dc09de5964d45dd3af538da8c031027 100644 (file)
@@ -860,7 +860,11 @@ static int i40e_alloc_vf_res(struct i40e_vf *vf)
        if (ret)
                goto error_alloc;
        total_queue_pairs += pf->vsi[vf->lan_vsi_idx]->alloc_queue_pairs;
-       set_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps);
+
+       if (vf->trusted)
+               set_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps);
+       else
+               clear_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps);
 
        /* store the total qps number for the runtime
         * VF req validation
@@ -1827,6 +1831,10 @@ error_param:
                                      (u8 *)&stats, sizeof(stats));
 }
 
+/* If the VF is not trusted restrict the number of MAC/VLAN it can program */
+#define I40E_VC_MAX_MAC_ADDR_PER_VF 8
+#define I40E_VC_MAX_VLAN_PER_VF 8
+
 /**
  * i40e_check_vf_permission
  * @vf: pointer to the VF info
@@ -1847,15 +1855,22 @@ static inline int i40e_check_vf_permission(struct i40e_vf *vf, u8 *macaddr)
                dev_err(&pf->pdev->dev, "invalid VF MAC addr %pM\n", macaddr);
                ret = I40E_ERR_INVALID_MAC_ADDR;
        } else if (vf->pf_set_mac && !is_multicast_ether_addr(macaddr) &&
+                  !test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps) &&
                   !ether_addr_equal(macaddr, vf->default_lan_addr.addr)) {
                /* If the host VMM administrator has set the VF MAC address
                 * administratively via the ndo_set_vf_mac command then deny
                 * permission to the VF to add or delete unicast MAC addresses.
+                * Unless the VF is privileged and then it can do whatever.
                 * The VF may request to set the MAC address filter already
                 * assigned to it so do not return an error in that case.
                 */
                dev_err(&pf->pdev->dev,
-                       "VF attempting to override administratively set MAC address\nPlease reload the VF driver to resume normal operation\n");
+                       "VF attempting to override administratively set MAC address, reload the VF driver to resume normal operation\n");
+               ret = -EPERM;
+       } else if ((vf->num_mac >= I40E_VC_MAX_MAC_ADDR_PER_VF) &&
+                  !test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps)) {
+               dev_err(&pf->pdev->dev,
+                       "VF is not trusted, switch the VF to trusted to add more functionality\n");
                ret = -EPERM;
        }
        return ret;
@@ -1880,7 +1895,6 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
        int i;
 
        if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states) ||
-           !test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps) ||
            !i40e_vc_isvalid_vsi_id(vf, vsi_id)) {
                ret = I40E_ERR_PARAM;
                goto error_param;
@@ -1954,7 +1968,6 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
        int i;
 
        if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states) ||
-           !test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps) ||
            !i40e_vc_isvalid_vsi_id(vf, vsi_id)) {
                ret = I40E_ERR_PARAM;
                goto error_param;
@@ -2012,6 +2025,12 @@ static int i40e_vc_add_vlan_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
        i40e_status aq_ret = 0;
        int i;
 
+       if ((vf->num_vlan >= I40E_VC_MAX_VLAN_PER_VF) &&
+           !test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps)) {
+               dev_err(&pf->pdev->dev,
+                       "VF is not trusted, switch the VF to trusted to add more VLAN addresses\n");
+               goto error_param;
+       }
        if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states) ||
            !test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps) ||
            !i40e_vc_isvalid_vsi_id(vf, vsi_id)) {
@@ -2207,7 +2226,6 @@ static int i40e_vc_config_rss_key(struct i40e_vf *vf, u8 *msg, u16 msglen)
        i40e_status aq_ret = 0;
 
        if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states) ||
-           !test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps) ||
            !i40e_vc_isvalid_vsi_id(vf, vsi_id) ||
            (vrk->key_len != I40E_HKEY_ARRAY_SIZE)) {
                aq_ret = I40E_ERR_PARAM;
@@ -2240,7 +2258,6 @@ static int i40e_vc_config_rss_lut(struct i40e_vf *vf, u8 *msg, u16 msglen)
        i40e_status aq_ret = 0;
 
        if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states) ||
-           !test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps) ||
            !i40e_vc_isvalid_vsi_id(vf, vsi_id) ||
            (vrl->lut_entries != I40E_VF_HLUT_ARRAY_SIZE)) {
                aq_ret = I40E_ERR_PARAM;
@@ -2270,8 +2287,7 @@ static int i40e_vc_get_rss_hena(struct i40e_vf *vf, u8 *msg, u16 msglen)
        i40e_status aq_ret = 0;
        int len = 0;
 
-       if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states) ||
-           !test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps)) {
+       if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states)) {
                aq_ret = I40E_ERR_PARAM;
                goto err;
        }
@@ -2307,8 +2323,7 @@ static int i40e_vc_set_rss_hena(struct i40e_vf *vf, u8 *msg, u16 msglen)
        struct i40e_hw *hw = &pf->hw;
        i40e_status aq_ret = 0;
 
-       if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states) ||
-           !test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps)) {
+       if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states)) {
                aq_ret = I40E_ERR_PARAM;
                goto err;
        }
@@ -3095,3 +3110,45 @@ int i40e_ndo_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool enable)
 out:
        return ret;
 }
+
+/**
+ * i40e_ndo_set_vf_trust
+ * @netdev: network interface device structure of the pf
+ * @vf_id: VF identifier
+ * @setting: trust setting
+ *
+ * Enable or disable VF trust setting
+ **/
+int i40e_ndo_set_vf_trust(struct net_device *netdev, int vf_id, bool setting)
+{
+       struct i40e_netdev_priv *np = netdev_priv(netdev);
+       struct i40e_pf *pf = np->vsi->back;
+       struct i40e_vf *vf;
+       int ret = 0;
+
+       /* validate the request */
+       if (vf_id >= pf->num_alloc_vfs) {
+               dev_err(&pf->pdev->dev, "Invalid VF Identifier %d\n", vf_id);
+               return -EINVAL;
+       }
+
+       if (pf->flags & I40E_FLAG_MFP_ENABLED) {
+               dev_err(&pf->pdev->dev, "Trusted VF not supported in MFP mode.\n");
+               return -EINVAL;
+       }
+
+       vf = &pf->vf[vf_id];
+
+       if (!vf)
+               return -EINVAL;
+       if (setting == vf->trusted)
+               goto out;
+
+       vf->trusted = setting;
+       i40e_vc_notify_vf_reset(vf);
+       i40e_reset_vf(vf, false);
+       dev_info(&pf->pdev->dev, "VF %u is now %strusted\n",
+                vf_id, setting ? "" : "un");
+out:
+       return ret;
+}
index 25c73c73dfe3efa8e7d9fcc0401bbb549c8bc51b..9dc9f8008d8c140d84094713b6dc7dcb87ad6cf9 100644 (file)
@@ -90,6 +90,7 @@ struct i40e_vf {
        struct i40e_virtchnl_ether_addr default_fcoe_addr;
        u16 port_vlan_id;
        bool pf_set_mac;        /* The VMM admin set the VF MAC address */
+       bool trusted;
 
        /* VSI indices - actual VSI pointers are maintained in the PF structure
         * When assigned, these will be non-zero, because VSI 0 is always
@@ -110,6 +111,9 @@ struct i40e_vf {
        bool link_forced;
        bool link_up;           /* only valid if VF link is forced */
        bool spoofchk;
+       u16 num_mac;
+       u16 num_vlan;
+
        /* RDMA Client */
        struct i40e_virtchnl_iwarp_qvlist_info *qvlist_info;
 };