Commit cdc220e7 authored by Chiqijun's avatar Chiqijun Committed by Yang Yingliang
Browse files

Enable trust mode control for SR-IOV ports



driver inclusion
category: feature
bugzilla: 4472

-----------------------------------------------------------------------

Added support for trust mode on VFs. This allows the VM to change the MAC
address of the VF on the host at run time.

Signed-off-by: default avatarChiqijun <chiqijun@huawei.com>
Reviewed-by: default avatarLuoshaokai <luoshaokai@huawei.com>
Signed-off-by: default avatarYang Yingliang <yangyingliang@huawei.com>
parent 9bfc5a8c
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -2127,6 +2127,14 @@ static const struct net_device_ops hinic_netdev_ops = {
#ifdef HAVE_VF_SPOOFCHK_CONFIGURE
	.ndo_set_vf_spoofchk	= hinic_ndo_set_vf_spoofchk,
#endif
#ifdef HAVE_NDO_SET_VF_TRUST
#ifdef HAVE_RHEL7_NET_DEVICE_OPS_EXT
	.extended.ndo_set_vf_trust = hinic_ndo_set_vf_trust,
#else
	.ndo_set_vf_trust	= hinic_ndo_set_vf_trust,
#endif /* HAVE_RHEL7_NET_DEVICE_OPS_EXT */
#endif /* HAVE_NDO_SET_VF_TRUST */

	.ndo_get_vf_config	= hinic_ndo_get_vf_config,
#endif

+1 −0
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ struct vf_data_storage {
	bool link_forced;
	bool link_up;		/* only valid if VF link is forced */
	bool spoofchk;
	bool trust;
};

struct hinic_nic_cfg {
+42 −3
Original line number Diff line number Diff line
@@ -2432,7 +2432,8 @@ static int hinic_set_vf_mac_msg_handler(struct hinic_nic_io *nic_io, u16 vf,
	struct hinic_port_mac_set *mac_out = buf_out;
	int err;

	if (vf_info->pf_set_mac && is_valid_ether_addr(mac_in->mac)) {
	if (vf_info->pf_set_mac && !(vf_info->trust) &&
	    is_valid_ether_addr(mac_in->mac)) {
		nic_warn(nic_io->hwdev->dev_hdl, "PF has already set VF %d MAC address\n",
			 HW_VF_ID_TO_OS(vf));
		mac_out->status = HINIC_PF_SET_VF_ALREADY;
@@ -2462,7 +2463,8 @@ static int hinic_del_vf_mac_msg_handler(struct hinic_nic_io *nic_io, u16 vf,
	struct hinic_port_mac_set *mac_out = buf_out;
	int err;

	if (vf_info->pf_set_mac && is_valid_ether_addr(mac_in->mac) &&
	if (vf_info->pf_set_mac && !(vf_info->trust) &&
	    is_valid_ether_addr(mac_in->mac) &&
	    !memcmp(vf_info->vf_mac_addr, mac_in->mac, ETH_ALEN)) {
		nic_warn(nic_io->hwdev->dev_hdl, "PF has already set VF mac.\n");
		mac_out->status = HINIC_PF_SET_VF_ALREADY;
@@ -2497,7 +2499,7 @@ static int hinic_update_vf_mac_msg_handler(struct hinic_nic_io *nic_io, u16 vf,
		return -EINVAL;
	}

	if (vf_info->pf_set_mac) {
	if (vf_info->pf_set_mac && !(vf_info->trust)) {
		nic_warn(nic_io->hwdev->dev_hdl, "PF has already set VF mac.\n");
		mac_out->status = HINIC_PF_SET_VF_ALREADY;
		*out_size = sizeof(*mac_out);
@@ -3026,6 +3028,10 @@ void hinic_get_vf_config(void *hwdev, u16 vf_id, struct ifla_vf_info *ivi)
	ivi->spoofchk = vfinfo->spoofchk;
#endif

#ifdef HAVE_NDO_SET_VF_TRUST
	ivi->trusted = vfinfo->trust;
#endif

#ifdef HAVE_NDO_SET_VF_MIN_MAX_TX_RATE
	ivi->max_tx_rate = vfinfo->max_rate;
	ivi->min_tx_rate = vfinfo->min_rate;
@@ -3063,6 +3069,11 @@ void hinic_clear_vf_infos(void *hwdev, u16 vf_id)
	if (vf_infos->spoofchk)
		hinic_set_vf_spoofchk(hwdev, vf_id, false);

#ifdef HAVE_NDO_SET_VF_TRUST
	if (vf_infos->trust)
		hinic_set_vf_trust(hwdev, vf_id, false);
#endif

	memset(vf_infos, 0, sizeof(*vf_infos));
	/* set vf_infos to default */
	hinic_init_vf_infos(hw_dev->nic_io, HW_VF_ID_TO_OS(vf_id));
@@ -3181,6 +3192,24 @@ int hinic_set_vf_spoofchk(void *hwdev, u16 vf_id, bool spoofchk)
	return err;
}

#ifdef HAVE_NDO_SET_VF_TRUST
int hinic_set_vf_trust(void *hwdev, u16 vf_id, bool trust)
{
	struct hinic_hwdev *hw_dev = hwdev;
	struct hinic_nic_io *nic_io = NULL;
	struct vf_data_storage *vf_infos = NULL;

	if (!hwdev)
		return -EINVAL;

	nic_io = hw_dev->nic_io;
	vf_infos = nic_io->vf_infos;
	vf_infos[HW_VF_ID_TO_OS(vf_id)].trust = trust;

	return 0;
}
#endif

bool hinic_vf_info_spoofchk(void *hwdev, int vf_id)
{
	struct hinic_nic_io *nic_io = ((struct hinic_hwdev *)hwdev)->nic_io;
@@ -3189,6 +3218,16 @@ bool hinic_vf_info_spoofchk(void *hwdev, int vf_id)
	return spoofchk;
}

#ifdef HAVE_NDO_SET_VF_TRUST
bool hinic_vf_info_trust(void *hwdev, int vf_id)
{
	struct hinic_nic_io *nic_io = ((struct hinic_hwdev *)hwdev)->nic_io;
	bool trust = nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].trust;

	return trust;
}
#endif

static int hinic_set_vf_rate_limit(void *hwdev, u16 vf_id, u32 tx_rate)
{
	struct hinic_hwdev *hw_dev = hwdev;
+5 −0
Original line number Diff line number Diff line
@@ -578,6 +578,11 @@ int hinic_set_vf_spoofchk(void *hwdev, u16 vf_id, bool spoofchk);

bool hinic_vf_info_spoofchk(void *hwdev, int vf_id);

#ifdef HAVE_NDO_SET_VF_TRUST
int hinic_set_vf_trust(void *hwdev, u16 vf_id, bool trust);
bool hinic_vf_info_trust(void *hwdev, int vf_id);
#endif

int hinic_set_vf_tx_rate(void *hwdev, u16 vf_id, u32 max_rate, u32 min_rate);

int hinic_init_vf_hw(void *hwdev, u16 start_vf_id, u16 end_vf_id);
+31 −0
Original line number Diff line number Diff line
@@ -356,6 +356,37 @@ int hinic_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting)
}
#endif

#ifdef HAVE_NDO_SET_VF_TRUST
int hinic_ndo_set_vf_trust(struct net_device *netdev, int vf, bool setting)
{
	struct hinic_nic_dev *adapter = netdev_priv(netdev);
	struct hinic_sriov_info *sriov_info;
	int err = 0;
	bool cur_trust;

	sriov_info = hinic_get_sriov_info_by_pcidev(adapter->pdev);
	if (vf >= sriov_info->num_vfs)
		return -EINVAL;

	cur_trust = hinic_vf_info_trust(sriov_info->hwdev,
					OS_VF_ID_TO_HW(vf));
	/* same request, so just return success */
	if ((setting && cur_trust) || (!setting && !cur_trust))
		return 0;

	err = hinic_set_vf_trust(sriov_info->hwdev,
				 OS_VF_ID_TO_HW(vf), setting);
	if (!err)
		nicif_info(adapter, drv, netdev, "Set VF %d trusted %s succeed\n",
			   vf, setting ? "on" : "off");
	else
		nicif_err(adapter, drv, netdev, "Failed set VF %d trusted %s\n",
			  vf, setting ? "on" : "off");

	return err;
}
#endif

int hinic_ndo_get_vf_config(struct net_device *netdev,
			    int vf, struct ifla_vf_info *ivi)
{
Loading