diff options
author | Kalesh AP <kalesh.purayil@emulex.com> | 2015-05-06 12:30:32 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-05-09 23:27:03 +0300 |
commit | e7bcbd7b81a129d79f205b19f9dd96b00c7e2364 (patch) | |
tree | 54a6ff181a3e2dfdda4561775a6cf72bc6184ad4 /drivers/net/ethernet/emulex | |
parent | 1a676d2b135c34de67f8fdd9b42c5d33b17f98dd (diff) | |
download | linux-e7bcbd7b81a129d79f205b19f9dd96b00c7e2364.tar.xz |
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: Kalesh AP <kalesh.purayil@emulex.com>
Signed-off-by: Sathya Perla <sathya.perla@avagotech.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/emulex')
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_cmds.c | 16 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_cmds.h | 24 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_main.c | 51 |
4 files changed, 78 insertions, 14 deletions
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index 1bf1cdce74ac..bbfbbb313178 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h @@ -366,6 +366,7 @@ struct be_vf_cfg { u32 tx_rate; u32 plink_tracking; u32 privileges; + bool spoofchk; }; enum vf_state { diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index fb140faeafb1..e630fe0c1e44 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -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, - 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_cmd_req_set_hsw_config *req; @@ -3189,6 +3189,14 @@ int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid, 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)); status = be_mcc_notify_wait(adapter); @@ -3199,7 +3207,7 @@ err: /* Get Hyper switch config */ 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_cmd_req_get_hsw_config *req; @@ -3247,6 +3255,10 @@ int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid, if (mode) *mode = AMAP_GET_BITS(struct amap_get_hsw_resp_context, port_fwd_type, &resp->context); + if (spoofchk) + *spoofchk = + AMAP_GET_BITS(struct amap_get_hsw_resp_context, + spoofchk, &resp->context); } err: diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h index 1ec22300e254..cf5f85544874 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.h +++ b/drivers/net/ethernet/emulex/benet/be_cmds.h @@ -1745,18 +1745,24 @@ struct be_cmd_req_set_mac_list { #define PORT_FWD_TYPE_VEPA 0x3 #define PORT_FWD_TYPE_VEB 0x2 +#define ENABLE_MAC_SPOOFCHK 0x2 +#define DISABLE_MAC_SPOOFCHK 0x3 + struct amap_set_hsw_context { u8 interface_id[16]; - u8 rsvd0[14]; + u8 rsvd0[8]; + u8 mac_spoofchk[2]; + u8 rsvd1[4]; u8 pvid_valid; u8 pport; - u8 rsvd1[6]; + u8 rsvd2[6]; u8 port_fwd_type[3]; - u8 rsvd2[7]; + u8 rsvd3[5]; + u8 vlan_spoofchk[2]; u8 pvid[16]; - u8 rsvd3[32]; u8 rsvd4[32]; u8 rsvd5[32]; + u8 rsvd6[32]; } __packed; struct be_cmd_req_set_hsw_config { @@ -1774,11 +1780,13 @@ struct amap_get_hsw_req_context { struct amap_get_hsw_resp_context { u8 rsvd0[6]; u8 port_fwd_type[3]; - u8 rsvd1[7]; + u8 rsvd1[5]; + u8 spoofchk; + u8 rsvd2; u8 pvid[16]; - u8 rsvd2[32]; u8 rsvd3[32]; u8 rsvd4[32]; + u8 rsvd5[32]; } __packed; 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, u32 domain); 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, - 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, - 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_set_fw_log_level(struct be_adapter *adapter, u32 level); int be_cmd_get_fw_log_level(struct be_adapter *adapter); diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index b69c42ee505a..d4f25a4b8af7 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -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; memcpy(&vi->mac, vf_cfg->mac_addr, ETH_ALEN); vi->linkstate = adapter->vf_cfg[vf].plink_tracking; + vi->spoofchk = adapter->vf_cfg[vf].spoofchk; return 0; } @@ -1480,7 +1481,7 @@ static int be_set_vf_tvt(struct be_adapter *adapter, int vf, u16 vlan) int status; /* 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) return status; @@ -1509,7 +1510,7 @@ static int be_clear_vf_tvt(struct be_adapter *adapter, int vf) /* Reset Transparent VLAN Tagging. */ 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) return status; @@ -1644,6 +1645,39 @@ static int be_set_vf_link_state(struct net_device *netdev, int vf, 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, ulong now) { @@ -3612,6 +3646,7 @@ static int be_vf_setup(struct be_adapter *adapter) struct device *dev = &adapter->pdev->dev; struct be_vf_cfg *vf_cfg; int status, old_vfs, vf; + bool spoofchk; old_vfs = pci_num_vf(adapter->pdev); @@ -3659,6 +3694,12 @@ static int be_vf_setup(struct be_adapter *adapter) if (!old_vfs) 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) { be_cmd_enable_vf(adapter, vf + 1); be_cmd_set_logical_link_config(adapter, @@ -4831,7 +4872,7 @@ static int be_ndo_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh, adapter->if_handle, mode == BRIDGE_MODE_VEPA ? PORT_FWD_TYPE_VEPA : - PORT_FWD_TYPE_VEB); + PORT_FWD_TYPE_VEB, 0); if (status) goto err; @@ -4863,7 +4904,8 @@ static int be_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq, hsw_mode = PORT_FWD_TYPE_VEB; } else { status = be_cmd_get_hsw_config(adapter, NULL, 0, - adapter->if_handle, &hsw_mode); + adapter->if_handle, &hsw_mode, + NULL); if (status) return 0; } @@ -5016,6 +5058,7 @@ static const struct net_device_ops be_netdev_ops = { .ndo_set_vf_rate = be_set_vf_tx_rate, .ndo_get_vf_config = be_get_vf_config, .ndo_set_vf_link_state = be_set_vf_link_state, + .ndo_set_vf_spoofchk = be_set_vf_spoofchk, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = be_netpoll, #endif |