Skip to content

Commit

Permalink
enic: Add vxlan offload support for IPv6 pkts
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Govindarajulu Varadarajan authored and David S. Miller committed Mar 4, 2018
1 parent 4a464a2 commit d117909
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 13 deletions.
1 change: 1 addition & 0 deletions drivers/net/ethernet/cisco/enic/enic.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ struct enic_rfs_flw_tbl {
struct vxlan_offload {
u16 vxlan_udp_port_number;
u8 patch_level;
u8 flags;
};

/* Per-instance private data structure */
Expand Down
44 changes: 35 additions & 9 deletions drivers/net/ethernet/cisco/enic/enic_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,16 @@ static void enic_udp_tunnel_add(struct net_device *netdev,
goto error;
}

if (ti->sa_family != AF_INET) {
netdev_info(netdev, "vxlan: only IPv4 offload supported");
switch (ti->sa_family) {
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;
}

Expand Down Expand Up @@ -271,22 +279,37 @@ static netdev_features_t enic_features_check(struct sk_buff *skb,
struct enic *enic = netdev_priv(dev);
struct udphdr *udph;
u16 port = 0;
u16 proto;
u8 proto;

if (!skb->encapsulation)
return features;

features = vxlan_features_check(skb, features);

/* hardware only supports IPv4 vxlan tunnel */
if (vlan_get_protocol(skb) != htons(ETH_P_IP))
switch (vlan_get_protocol(skb)) {
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;
}

/* hardware does not support offload of ipv6 inner pkt */
if (eth->h_proto != ntohs(ETH_P_IP))
switch (eth->h_proto) {
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;
}

proto = ip_hdr(skb)->protocol;

if (proto == IPPROTO_UDP) {
udph = udp_hdr(skb);
Expand Down Expand Up @@ -2914,9 +2937,11 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->hw_features |= NETIF_F_RXCSUM;
if (ENIC_SETTING(enic, VXLAN)) {
u64 patch_level;
u64 a1 = 0;

netdev->hw_enc_features |= NETIF_F_RXCSUM |
NETIF_F_TSO |
NETIF_F_TSO6 |
NETIF_F_TSO_ECN |
NETIF_F_GSO_UDP_TUNNEL |
NETIF_F_HW_CSUM |
Expand All @@ -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,
VIC_FEATURE_VXLAN,
&patch_level);
&patch_level, &a1);
if (err)
patch_level = 0;
enic->vxlan.flags = (u8)a1;
/* mask bits that are supported by driver
*/
patch_level &= BIT_ULL(0) | BIT_ULL(2);
Expand Down
5 changes: 2 additions & 3 deletions drivers/net/ethernet/cisco/enic/vnic_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
u64 *supported_versions)
u64 *supported_versions, u64 *a1)
{
u64 a0 = feature;
int wait = 1000;
u64 a1 = 0;
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)
*supported_versions = a0;

Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/cisco/enic/vnic_dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
u16 vxlan_udp_port_number);
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_ */
3 changes: 3 additions & 0 deletions drivers/net/ethernet/cisco/enic/vnic_devcmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,9 @@ enum overlay_ofld_cmd {

#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
* 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
Expand Down

0 comments on commit d117909

Please sign in to comment.