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;
}
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);
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 |
*/
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);
}
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;
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_ */
#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