mirror of
https://github.com/torvalds/linux.git
synced 2024-12-27 05:11:48 +00:00
enic: Add vxlan offload support for IPv6 pkts
New adaptors supports vxlan offload for inner IPv6 and outer IPv6 vxlan pkts. Fw sets BIT(0) & BIT(1) in a1 if hw supports ipv6 inner & outer pkt offload. Signed-off-by: Govindarajulu Varadarajan <gvaradar@cisco.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
4a464a2b06
commit
d11790941d
@ -140,6 +140,7 @@ struct enic_rfs_flw_tbl {
|
|||||||
struct vxlan_offload {
|
struct vxlan_offload {
|
||||||
u16 vxlan_udp_port_number;
|
u16 vxlan_udp_port_number;
|
||||||
u8 patch_level;
|
u8 patch_level;
|
||||||
|
u8 flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Per-instance private data structure */
|
/* Per-instance private data structure */
|
||||||
|
@ -191,8 +191,16 @@ static void enic_udp_tunnel_add(struct net_device *netdev,
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ti->sa_family != AF_INET) {
|
switch (ti->sa_family) {
|
||||||
netdev_info(netdev, "vxlan: only IPv4 offload supported");
|
case AF_INET6:
|
||||||
|
if (!(enic->vxlan.flags & ENIC_VXLAN_OUTER_IPV6)) {
|
||||||
|
netdev_info(netdev, "vxlan: only IPv4 offload supported");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
/* Fall through */
|
||||||
|
case AF_INET:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,22 +279,37 @@ static netdev_features_t enic_features_check(struct sk_buff *skb,
|
|||||||
struct enic *enic = netdev_priv(dev);
|
struct enic *enic = netdev_priv(dev);
|
||||||
struct udphdr *udph;
|
struct udphdr *udph;
|
||||||
u16 port = 0;
|
u16 port = 0;
|
||||||
u16 proto;
|
u8 proto;
|
||||||
|
|
||||||
if (!skb->encapsulation)
|
if (!skb->encapsulation)
|
||||||
return features;
|
return features;
|
||||||
|
|
||||||
features = vxlan_features_check(skb, features);
|
features = vxlan_features_check(skb, features);
|
||||||
|
|
||||||
/* hardware only supports IPv4 vxlan tunnel */
|
switch (vlan_get_protocol(skb)) {
|
||||||
if (vlan_get_protocol(skb) != htons(ETH_P_IP))
|
case htons(ETH_P_IPV6):
|
||||||
|
if (!(enic->vxlan.flags & ENIC_VXLAN_OUTER_IPV6))
|
||||||
|
goto out;
|
||||||
|
proto = ipv6_hdr(skb)->nexthdr;
|
||||||
|
break;
|
||||||
|
case htons(ETH_P_IP):
|
||||||
|
proto = ip_hdr(skb)->protocol;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
goto out;
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/* hardware does not support offload of ipv6 inner pkt */
|
switch (eth->h_proto) {
|
||||||
if (eth->h_proto != ntohs(ETH_P_IP))
|
case ntohs(ETH_P_IPV6):
|
||||||
|
if (!(enic->vxlan.flags & ENIC_VXLAN_INNER_IPV6))
|
||||||
|
goto out;
|
||||||
|
/* Fall through */
|
||||||
|
case ntohs(ETH_P_IP):
|
||||||
|
break;
|
||||||
|
default:
|
||||||
goto out;
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
proto = ip_hdr(skb)->protocol;
|
|
||||||
|
|
||||||
if (proto == IPPROTO_UDP) {
|
if (proto == IPPROTO_UDP) {
|
||||||
udph = udp_hdr(skb);
|
udph = udp_hdr(skb);
|
||||||
@ -2914,9 +2937,11 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||||||
netdev->hw_features |= NETIF_F_RXCSUM;
|
netdev->hw_features |= NETIF_F_RXCSUM;
|
||||||
if (ENIC_SETTING(enic, VXLAN)) {
|
if (ENIC_SETTING(enic, VXLAN)) {
|
||||||
u64 patch_level;
|
u64 patch_level;
|
||||||
|
u64 a1 = 0;
|
||||||
|
|
||||||
netdev->hw_enc_features |= NETIF_F_RXCSUM |
|
netdev->hw_enc_features |= NETIF_F_RXCSUM |
|
||||||
NETIF_F_TSO |
|
NETIF_F_TSO |
|
||||||
|
NETIF_F_TSO6 |
|
||||||
NETIF_F_TSO_ECN |
|
NETIF_F_TSO_ECN |
|
||||||
NETIF_F_GSO_UDP_TUNNEL |
|
NETIF_F_GSO_UDP_TUNNEL |
|
||||||
NETIF_F_HW_CSUM |
|
NETIF_F_HW_CSUM |
|
||||||
@ -2935,9 +2960,10 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||||||
*/
|
*/
|
||||||
err = vnic_dev_get_supported_feature_ver(enic->vdev,
|
err = vnic_dev_get_supported_feature_ver(enic->vdev,
|
||||||
VIC_FEATURE_VXLAN,
|
VIC_FEATURE_VXLAN,
|
||||||
&patch_level);
|
&patch_level, &a1);
|
||||||
if (err)
|
if (err)
|
||||||
patch_level = 0;
|
patch_level = 0;
|
||||||
|
enic->vxlan.flags = (u8)a1;
|
||||||
/* mask bits that are supported by driver
|
/* mask bits that are supported by driver
|
||||||
*/
|
*/
|
||||||
patch_level &= BIT_ULL(0) | BIT_ULL(2);
|
patch_level &= BIT_ULL(0) | BIT_ULL(2);
|
||||||
|
@ -1269,14 +1269,13 @@ int vnic_dev_overlay_offload_cfg(struct vnic_dev *vdev, u8 overlay,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int vnic_dev_get_supported_feature_ver(struct vnic_dev *vdev, u8 feature,
|
int vnic_dev_get_supported_feature_ver(struct vnic_dev *vdev, u8 feature,
|
||||||
u64 *supported_versions)
|
u64 *supported_versions, u64 *a1)
|
||||||
{
|
{
|
||||||
u64 a0 = feature;
|
u64 a0 = feature;
|
||||||
int wait = 1000;
|
int wait = 1000;
|
||||||
u64 a1 = 0;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = vnic_dev_cmd(vdev, CMD_GET_SUPP_FEATURE_VER, &a0, &a1, wait);
|
ret = vnic_dev_cmd(vdev, CMD_GET_SUPP_FEATURE_VER, &a0, a1, wait);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
*supported_versions = a0;
|
*supported_versions = a0;
|
||||||
|
|
||||||
|
@ -183,6 +183,6 @@ int vnic_dev_overlay_offload_ctrl(struct vnic_dev *vdev, u8 overlay, u8 config);
|
|||||||
int vnic_dev_overlay_offload_cfg(struct vnic_dev *vdev, u8 overlay,
|
int vnic_dev_overlay_offload_cfg(struct vnic_dev *vdev, u8 overlay,
|
||||||
u16 vxlan_udp_port_number);
|
u16 vxlan_udp_port_number);
|
||||||
int vnic_dev_get_supported_feature_ver(struct vnic_dev *vdev, u8 feature,
|
int vnic_dev_get_supported_feature_ver(struct vnic_dev *vdev, u8 feature,
|
||||||
u64 *supported_versions);
|
u64 *supported_versions, u64 *a1);
|
||||||
|
|
||||||
#endif /* _VNIC_DEV_H_ */
|
#endif /* _VNIC_DEV_H_ */
|
||||||
|
@ -697,6 +697,9 @@ enum overlay_ofld_cmd {
|
|||||||
|
|
||||||
#define OVERLAY_CFG_VXLAN_PORT_UPDATE 0
|
#define OVERLAY_CFG_VXLAN_PORT_UPDATE 0
|
||||||
|
|
||||||
|
#define ENIC_VXLAN_INNER_IPV6 BIT(0)
|
||||||
|
#define ENIC_VXLAN_OUTER_IPV6 BIT(1)
|
||||||
|
|
||||||
/* Use this enum to get the supported versions for each of these features
|
/* Use this enum to get the supported versions for each of these features
|
||||||
* If you need to use the devcmd_get_supported_feature_version(), add
|
* If you need to use the devcmd_get_supported_feature_version(), add
|
||||||
* the new feature into this enum and install function handler in devcmd.c
|
* the new feature into this enum and install function handler in devcmd.c
|
||||||
|
Loading…
Reference in New Issue
Block a user