Commit e7bcbd7b authored by Kalesh AP's avatar Kalesh AP Committed by David S. Miller

be2net: add support for spoofchk setting

This patch adds support for spoofchk configuration for VFs.
When it is enabled, "spoof checking" is done for both MAC-address and VLAN.
For each VF, the HW ensures that the source MAC address (or vlan) of
every outgoing packet exists in the MAC-list (or vlan-list) configured
for RX filtering for that VF. If not, the packet is dropped and an error
is reported to the driver in the TX completion; this is reflected in the
"tx_spoof_check_err" ethtool counter.
This feature is supported in Skyhawk FW version 10.6.31.0 and above.
Signed-off-by: default avatarKalesh AP <kalesh.purayil@emulex.com>
Signed-off-by: default avatarSathya Perla <sathya.perla@avagotech.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1a676d2b
...@@ -366,6 +366,7 @@ struct be_vf_cfg { ...@@ -366,6 +366,7 @@ struct be_vf_cfg {
u32 tx_rate; u32 tx_rate;
u32 plink_tracking; u32 plink_tracking;
u32 privileges; u32 privileges;
bool spoofchk;
}; };
enum vf_state { enum vf_state {
......
...@@ -3153,7 +3153,7 @@ int be_cmd_set_mac(struct be_adapter *adapter, u8 *mac, int if_id, u32 dom) ...@@ -3153,7 +3153,7 @@ int be_cmd_set_mac(struct be_adapter *adapter, u8 *mac, int if_id, u32 dom)
} }
int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid, int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid,
u32 domain, u16 intf_id, u16 hsw_mode) u32 domain, u16 intf_id, u16 hsw_mode, u8 spoofchk)
{ {
struct be_mcc_wrb *wrb; struct be_mcc_wrb *wrb;
struct be_cmd_req_set_hsw_config *req; struct be_cmd_req_set_hsw_config *req;
...@@ -3189,6 +3189,14 @@ int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid, ...@@ -3189,6 +3189,14 @@ int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid,
ctxt, hsw_mode); ctxt, hsw_mode);
} }
/* Enable/disable both mac and vlan spoof checking */
if (!BEx_chip(adapter) && spoofchk) {
AMAP_SET_BITS(struct amap_set_hsw_context, mac_spoofchk,
ctxt, spoofchk);
AMAP_SET_BITS(struct amap_set_hsw_context, vlan_spoofchk,
ctxt, spoofchk);
}
be_dws_cpu_to_le(req->context, sizeof(req->context)); be_dws_cpu_to_le(req->context, sizeof(req->context));
status = be_mcc_notify_wait(adapter); status = be_mcc_notify_wait(adapter);
...@@ -3199,7 +3207,7 @@ int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid, ...@@ -3199,7 +3207,7 @@ int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid,
/* Get Hyper switch config */ /* Get Hyper switch config */
int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid, int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid,
u32 domain, u16 intf_id, u8 *mode) u32 domain, u16 intf_id, u8 *mode, bool *spoofchk)
{ {
struct be_mcc_wrb *wrb; struct be_mcc_wrb *wrb;
struct be_cmd_req_get_hsw_config *req; struct be_cmd_req_get_hsw_config *req;
...@@ -3247,6 +3255,10 @@ int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid, ...@@ -3247,6 +3255,10 @@ int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid,
if (mode) if (mode)
*mode = AMAP_GET_BITS(struct amap_get_hsw_resp_context, *mode = AMAP_GET_BITS(struct amap_get_hsw_resp_context,
port_fwd_type, &resp->context); port_fwd_type, &resp->context);
if (spoofchk)
*spoofchk =
AMAP_GET_BITS(struct amap_get_hsw_resp_context,
spoofchk, &resp->context);
} }
err: err:
......
...@@ -1745,18 +1745,24 @@ struct be_cmd_req_set_mac_list { ...@@ -1745,18 +1745,24 @@ struct be_cmd_req_set_mac_list {
#define PORT_FWD_TYPE_VEPA 0x3 #define PORT_FWD_TYPE_VEPA 0x3
#define PORT_FWD_TYPE_VEB 0x2 #define PORT_FWD_TYPE_VEB 0x2
#define ENABLE_MAC_SPOOFCHK 0x2
#define DISABLE_MAC_SPOOFCHK 0x3
struct amap_set_hsw_context { struct amap_set_hsw_context {
u8 interface_id[16]; u8 interface_id[16];
u8 rsvd0[14]; u8 rsvd0[8];
u8 mac_spoofchk[2];
u8 rsvd1[4];
u8 pvid_valid; u8 pvid_valid;
u8 pport; u8 pport;
u8 rsvd1[6]; u8 rsvd2[6];
u8 port_fwd_type[3]; u8 port_fwd_type[3];
u8 rsvd2[7]; u8 rsvd3[5];
u8 vlan_spoofchk[2];
u8 pvid[16]; u8 pvid[16];
u8 rsvd3[32];
u8 rsvd4[32]; u8 rsvd4[32];
u8 rsvd5[32]; u8 rsvd5[32];
u8 rsvd6[32];
} __packed; } __packed;
struct be_cmd_req_set_hsw_config { struct be_cmd_req_set_hsw_config {
...@@ -1774,11 +1780,13 @@ struct amap_get_hsw_req_context { ...@@ -1774,11 +1780,13 @@ struct amap_get_hsw_req_context {
struct amap_get_hsw_resp_context { struct amap_get_hsw_resp_context {
u8 rsvd0[6]; u8 rsvd0[6];
u8 port_fwd_type[3]; u8 port_fwd_type[3];
u8 rsvd1[7]; u8 rsvd1[5];
u8 spoofchk;
u8 rsvd2;
u8 pvid[16]; u8 pvid[16];
u8 rsvd2[32];
u8 rsvd3[32]; u8 rsvd3[32];
u8 rsvd4[32]; u8 rsvd4[32];
u8 rsvd5[32];
} __packed; } __packed;
struct be_cmd_req_get_hsw_config { struct be_cmd_req_get_hsw_config {
...@@ -2334,9 +2342,9 @@ int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array, u8 mac_count, ...@@ -2334,9 +2342,9 @@ int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array, u8 mac_count,
u32 domain); u32 domain);
int be_cmd_set_mac(struct be_adapter *adapter, u8 *mac, int if_id, u32 dom); int be_cmd_set_mac(struct be_adapter *adapter, u8 *mac, int if_id, u32 dom);
int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid, u32 domain, int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid, u32 domain,
u16 intf_id, u16 hsw_mode); u16 intf_id, u16 hsw_mode, u8 spoofchk);
int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid, u32 domain, int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid, u32 domain,
u16 intf_id, u8 *mode); u16 intf_id, u8 *mode, bool *spoofchk);
int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter); int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter);
int be_cmd_set_fw_log_level(struct be_adapter *adapter, u32 level); int be_cmd_set_fw_log_level(struct be_adapter *adapter, u32 level);
int be_cmd_get_fw_log_level(struct be_adapter *adapter); int be_cmd_get_fw_log_level(struct be_adapter *adapter);
......
...@@ -1468,6 +1468,7 @@ static int be_get_vf_config(struct net_device *netdev, int vf, ...@@ -1468,6 +1468,7 @@ static int be_get_vf_config(struct net_device *netdev, int vf,
vi->qos = vf_cfg->vlan_tag >> VLAN_PRIO_SHIFT; vi->qos = vf_cfg->vlan_tag >> VLAN_PRIO_SHIFT;
memcpy(&vi->mac, vf_cfg->mac_addr, ETH_ALEN); memcpy(&vi->mac, vf_cfg->mac_addr, ETH_ALEN);
vi->linkstate = adapter->vf_cfg[vf].plink_tracking; vi->linkstate = adapter->vf_cfg[vf].plink_tracking;
vi->spoofchk = adapter->vf_cfg[vf].spoofchk;
return 0; return 0;
} }
...@@ -1480,7 +1481,7 @@ static int be_set_vf_tvt(struct be_adapter *adapter, int vf, u16 vlan) ...@@ -1480,7 +1481,7 @@ static int be_set_vf_tvt(struct be_adapter *adapter, int vf, u16 vlan)
int status; int status;
/* Enable Transparent VLAN Tagging */ /* Enable Transparent VLAN Tagging */
status = be_cmd_set_hsw_config(adapter, vlan, vf + 1, vf_if_id, 0); status = be_cmd_set_hsw_config(adapter, vlan, vf + 1, vf_if_id, 0, 0);
if (status) if (status)
return status; return status;
...@@ -1509,7 +1510,7 @@ static int be_clear_vf_tvt(struct be_adapter *adapter, int vf) ...@@ -1509,7 +1510,7 @@ static int be_clear_vf_tvt(struct be_adapter *adapter, int vf)
/* Reset Transparent VLAN Tagging. */ /* Reset Transparent VLAN Tagging. */
status = be_cmd_set_hsw_config(adapter, BE_RESET_VLAN_TAG_ID, vf + 1, status = be_cmd_set_hsw_config(adapter, BE_RESET_VLAN_TAG_ID, vf + 1,
vf_cfg->if_handle, 0); vf_cfg->if_handle, 0, 0);
if (status) if (status)
return status; return status;
...@@ -1644,6 +1645,39 @@ static int be_set_vf_link_state(struct net_device *netdev, int vf, ...@@ -1644,6 +1645,39 @@ static int be_set_vf_link_state(struct net_device *netdev, int vf,
return 0; return 0;
} }
static int be_set_vf_spoofchk(struct net_device *netdev, int vf, bool enable)
{
struct be_adapter *adapter = netdev_priv(netdev);
struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf];
u8 spoofchk;
int status;
if (!sriov_enabled(adapter))
return -EPERM;
if (vf >= adapter->num_vfs)
return -EINVAL;
if (BEx_chip(adapter))
return -EOPNOTSUPP;
if (enable == vf_cfg->spoofchk)
return 0;
spoofchk = enable ? ENABLE_MAC_SPOOFCHK : DISABLE_MAC_SPOOFCHK;
status = be_cmd_set_hsw_config(adapter, 0, vf + 1, vf_cfg->if_handle,
0, spoofchk);
if (status) {
dev_err(&adapter->pdev->dev,
"Spoofchk change on VF %d failed: %#x\n", vf, status);
return be_cmd_status(status);
}
vf_cfg->spoofchk = enable;
return 0;
}
static void be_aic_update(struct be_aic_obj *aic, u64 rx_pkts, u64 tx_pkts, static void be_aic_update(struct be_aic_obj *aic, u64 rx_pkts, u64 tx_pkts,
ulong now) ulong now)
{ {
...@@ -3612,6 +3646,7 @@ static int be_vf_setup(struct be_adapter *adapter) ...@@ -3612,6 +3646,7 @@ static int be_vf_setup(struct be_adapter *adapter)
struct device *dev = &adapter->pdev->dev; struct device *dev = &adapter->pdev->dev;
struct be_vf_cfg *vf_cfg; struct be_vf_cfg *vf_cfg;
int status, old_vfs, vf; int status, old_vfs, vf;
bool spoofchk;
old_vfs = pci_num_vf(adapter->pdev); old_vfs = pci_num_vf(adapter->pdev);
...@@ -3659,6 +3694,12 @@ static int be_vf_setup(struct be_adapter *adapter) ...@@ -3659,6 +3694,12 @@ static int be_vf_setup(struct be_adapter *adapter)
if (!old_vfs) if (!old_vfs)
be_cmd_config_qos(adapter, 0, 0, vf + 1); be_cmd_config_qos(adapter, 0, 0, vf + 1);
status = be_cmd_get_hsw_config(adapter, NULL, vf + 1,
vf_cfg->if_handle, NULL,
&spoofchk);
if (!status)
vf_cfg->spoofchk = spoofchk;
if (!old_vfs) { if (!old_vfs) {
be_cmd_enable_vf(adapter, vf + 1); be_cmd_enable_vf(adapter, vf + 1);
be_cmd_set_logical_link_config(adapter, be_cmd_set_logical_link_config(adapter,
...@@ -4831,7 +4872,7 @@ static int be_ndo_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh, ...@@ -4831,7 +4872,7 @@ static int be_ndo_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh,
adapter->if_handle, adapter->if_handle,
mode == BRIDGE_MODE_VEPA ? mode == BRIDGE_MODE_VEPA ?
PORT_FWD_TYPE_VEPA : PORT_FWD_TYPE_VEPA :
PORT_FWD_TYPE_VEB); PORT_FWD_TYPE_VEB, 0);
if (status) if (status)
goto err; goto err;
...@@ -4863,7 +4904,8 @@ static int be_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq, ...@@ -4863,7 +4904,8 @@ static int be_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
hsw_mode = PORT_FWD_TYPE_VEB; hsw_mode = PORT_FWD_TYPE_VEB;
} else { } else {
status = be_cmd_get_hsw_config(adapter, NULL, 0, status = be_cmd_get_hsw_config(adapter, NULL, 0,
adapter->if_handle, &hsw_mode); adapter->if_handle, &hsw_mode,
NULL);
if (status) if (status)
return 0; return 0;
} }
...@@ -5016,6 +5058,7 @@ static const struct net_device_ops be_netdev_ops = { ...@@ -5016,6 +5058,7 @@ static const struct net_device_ops be_netdev_ops = {
.ndo_set_vf_rate = be_set_vf_tx_rate, .ndo_set_vf_rate = be_set_vf_tx_rate,
.ndo_get_vf_config = be_get_vf_config, .ndo_get_vf_config = be_get_vf_config,
.ndo_set_vf_link_state = be_set_vf_link_state, .ndo_set_vf_link_state = be_set_vf_link_state,
.ndo_set_vf_spoofchk = be_set_vf_spoofchk,
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = be_netpoll, .ndo_poll_controller = be_netpoll,
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment