Commit 31deb12e authored by Andrii Staikov's avatar Andrii Staikov Committed by Tony Nguyen
Browse files

i40e: Fix VF disable behavior to block all traffic



Currently, if a VF is disabled using the
'ip link set dev $ETHX vf $VF_NUM state disable' command, the VF is still
able to receive traffic.

Fix the behavior of the 'ip link set dev $ETHX vf $VF_NUM state disable'
to completely shutdown the VF's queues making it entirely disabled and
not able to receive or send any traffic.

Modify the behavior of the 'ip link set $ETHX vf $VF_NUM state enable'
command to make a VF do reinitialization bringing the queues back up.

Co-developed-by: default avatarAleksandr Loktionov <aleksandr.loktionov@intel.com>
Signed-off-by: default avatarAleksandr Loktionov <aleksandr.loktionov@intel.com>
Reviewed-by: default avatarJan Sokolowski <jan.sokolowski@intel.com>
Reviewed-by: default avatarWojciech Drewek <wojciech.drewek@intel.com>
Reviewed-by: default avatarPrzemek Kitszel <przemyslaw.kitszel@intel.com>
Signed-off-by: default avatarAndrii Staikov <andrii.staikov@intel.com>
Tested-by: default avatarRafal Romanowski <rafal.romanowski@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent 5795f533
Loading
Loading
Loading
Loading
+32 −0
Original line number Diff line number Diff line
@@ -2579,6 +2579,14 @@ static int i40e_vc_enable_queues_msg(struct i40e_vf *vf, u8 *msg)
	int aq_ret = 0;
	int i;

	if (vf->is_disabled_from_host) {
		aq_ret = -EPERM;
		dev_info(&pf->pdev->dev,
			 "Admin has disabled VF %d, will not enable queues\n",
			 vf->vf_id);
		goto error_param;
	}

	if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) {
		aq_ret = -EINVAL;
		goto error_param;
@@ -4705,9 +4713,12 @@ int i40e_ndo_set_vf_link_state(struct net_device *netdev, int vf_id, int link)
	struct i40e_link_status *ls = &pf->hw.phy.link_info;
	struct virtchnl_pf_event pfe;
	struct i40e_hw *hw = &pf->hw;
	struct i40e_vsi *vsi;
	unsigned long q_map;
	struct i40e_vf *vf;
	int abs_vf_id;
	int ret = 0;
	int tmp;

	if (test_and_set_bit(__I40E_VIRTCHNL_OP_PENDING, pf->state)) {
		dev_warn(&pf->pdev->dev, "Unable to configure VFs, other operation is pending.\n");
@@ -4730,17 +4741,38 @@ int i40e_ndo_set_vf_link_state(struct net_device *netdev, int vf_id, int link)
	switch (link) {
	case IFLA_VF_LINK_STATE_AUTO:
		vf->link_forced = false;
		vf->is_disabled_from_host = false;
		/* reset needed to reinit VF resources */
		i40e_vc_reset_vf(vf, true);
		i40e_set_vf_link_state(vf, &pfe, ls);
		break;
	case IFLA_VF_LINK_STATE_ENABLE:
		vf->link_forced = true;
		vf->link_up = true;
		vf->is_disabled_from_host = false;
		/* reset needed to reinit VF resources */
		i40e_vc_reset_vf(vf, true);
		i40e_set_vf_link_state(vf, &pfe, ls);
		break;
	case IFLA_VF_LINK_STATE_DISABLE:
		vf->link_forced = true;
		vf->link_up = false;
		i40e_set_vf_link_state(vf, &pfe, ls);

		vsi = pf->vsi[vf->lan_vsi_idx];
		q_map = BIT(vsi->num_queue_pairs) - 1;

		vf->is_disabled_from_host = true;

		/* Try to stop both Tx&Rx rings even if one of the calls fails
		 * to ensure we stop the rings even in case of errors.
		 * If any of them returns with an error then the first
		 * error that occurred will be returned.
		 */
		tmp = i40e_ctrl_vf_tx_rings(vsi, q_map, false);
		ret = i40e_ctrl_vf_rx_rings(vsi, q_map, false);

		ret = tmp ? tmp : ret;
		break;
	default:
		ret = -EINVAL;
+1 −0
Original line number Diff line number Diff line
@@ -100,6 +100,7 @@ struct i40e_vf {
	bool link_forced;
	bool link_up;		/* only valid if VF link is forced */
	bool spoofchk;
	bool is_disabled_from_host; /* PF ctrl of VF enable/disable */
	u16 num_vlan;

	/* ADq related variables */