diff options
| author | Tom Herbert <therbert@google.com> | 2014-06-04 20:20:29 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2014-06-05 01:46:39 -0400 |
| commit | 359a0ea9875ef4f32c8425bbe1ae348e1fd2ed2a (patch) | |
| tree | ca8567d5204c6b891dcf5d3e012ceb4a4f027c09 | |
| parent | 4749c09c37030ccdc44aecebe0f71b02a377fc14 (diff) | |
vxlan: Add support for UDP checksums (v4 sending, v6 zero csums)
Added VXLAN link configuration for sending UDP checksums, and allowing
TX and RX of UDP6 checksums.
Also, call common iptunnel_handle_offloads and added GSO support for
checksums.
Signed-off-by: Tom Herbert <therbert@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | drivers/net/vxlan.c | 120 | ||||
| -rw-r--r-- | include/net/vxlan.h | 12 | ||||
| -rw-r--r-- | include/uapi/linux/if_link.h | 3 | ||||
| -rw-r--r-- | net/openvswitch/vport-vxlan.c | 2 |
4 files changed, 74 insertions, 63 deletions
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index e68c8eb4ea8e..4e2caaf8b5da 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c | |||
| @@ -135,7 +135,7 @@ struct vxlan_dev { | |||
| 135 | __u16 port_max; | 135 | __u16 port_max; |
| 136 | __u8 tos; /* TOS override */ | 136 | __u8 tos; /* TOS override */ |
| 137 | __u8 ttl; | 137 | __u8 ttl; |
| 138 | u32 flags; /* VXLAN_F_* below */ | 138 | u32 flags; /* VXLAN_F_* in vxlan.h */ |
| 139 | 139 | ||
| 140 | struct work_struct sock_work; | 140 | struct work_struct sock_work; |
| 141 | struct work_struct igmp_join; | 141 | struct work_struct igmp_join; |
| @@ -150,13 +150,6 @@ struct vxlan_dev { | |||
| 150 | struct hlist_head fdb_head[FDB_HASH_SIZE]; | 150 | struct hlist_head fdb_head[FDB_HASH_SIZE]; |
| 151 | }; | 151 | }; |
| 152 | 152 | ||
| 153 | #define VXLAN_F_LEARN 0x01 | ||
| 154 | #define VXLAN_F_PROXY 0x02 | ||
| 155 | #define VXLAN_F_RSC 0x04 | ||
| 156 | #define VXLAN_F_L2MISS 0x08 | ||
| 157 | #define VXLAN_F_L3MISS 0x10 | ||
| 158 | #define VXLAN_F_IPV6 0x20 /* internal flag */ | ||
| 159 | |||
| 160 | /* salt for hash table */ | 153 | /* salt for hash table */ |
| 161 | static u32 vxlan_salt __read_mostly; | 154 | static u32 vxlan_salt __read_mostly; |
| 162 | static struct workqueue_struct *vxlan_wq; | 155 | static struct workqueue_struct *vxlan_wq; |
| @@ -1601,18 +1594,11 @@ __be16 vxlan_src_port(__u16 port_min, __u16 port_max, struct sk_buff *skb) | |||
| 1601 | } | 1594 | } |
| 1602 | EXPORT_SYMBOL_GPL(vxlan_src_port); | 1595 | EXPORT_SYMBOL_GPL(vxlan_src_port); |
| 1603 | 1596 | ||
| 1604 | static int handle_offloads(struct sk_buff *skb) | 1597 | static inline struct sk_buff *vxlan_handle_offloads(struct sk_buff *skb, |
| 1598 | bool udp_csum) | ||
| 1605 | { | 1599 | { |
| 1606 | if (skb_is_gso(skb)) { | 1600 | int type = udp_csum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL; |
| 1607 | int err = skb_unclone(skb, GFP_ATOMIC); | 1601 | return iptunnel_handle_offloads(skb, udp_csum, type); |
| 1608 | if (unlikely(err)) | ||
| 1609 | return err; | ||
| 1610 | |||
| 1611 | skb_shinfo(skb)->gso_type |= SKB_GSO_UDP_TUNNEL; | ||
| 1612 | } else if (skb->ip_summed != CHECKSUM_PARTIAL) | ||
| 1613 | skb->ip_summed = CHECKSUM_NONE; | ||
| 1614 | |||
| 1615 | return 0; | ||
| 1616 | } | 1602 | } |
| 1617 | 1603 | ||
| 1618 | #if IS_ENABLED(CONFIG_IPV6) | 1604 | #if IS_ENABLED(CONFIG_IPV6) |
| @@ -1629,10 +1615,9 @@ static int vxlan6_xmit_skb(struct vxlan_sock *vs, | |||
| 1629 | int min_headroom; | 1615 | int min_headroom; |
| 1630 | int err; | 1616 | int err; |
| 1631 | 1617 | ||
| 1632 | if (!skb->encapsulation) { | 1618 | skb = vxlan_handle_offloads(skb, !udp_get_no_check6_tx(vs->sock->sk)); |
| 1633 | skb_reset_inner_headers(skb); | 1619 | if (IS_ERR(skb)) |
| 1634 | skb->encapsulation = 1; | 1620 | return -EINVAL; |
| 1635 | } | ||
| 1636 | 1621 | ||
| 1637 | skb_scrub_packet(skb, xnet); | 1622 | skb_scrub_packet(skb, xnet); |
| 1638 | 1623 | ||
| @@ -1666,27 +1651,14 @@ static int vxlan6_xmit_skb(struct vxlan_sock *vs, | |||
| 1666 | uh->source = src_port; | 1651 | uh->source = src_port; |
| 1667 | 1652 | ||
| 1668 | uh->len = htons(skb->len); | 1653 | uh->len = htons(skb->len); |
| 1669 | uh->check = 0; | ||
| 1670 | 1654 | ||
| 1671 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); | 1655 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); |
| 1672 | IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | | 1656 | IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | |
| 1673 | IPSKB_REROUTED); | 1657 | IPSKB_REROUTED); |
| 1674 | skb_dst_set(skb, dst); | 1658 | skb_dst_set(skb, dst); |
| 1675 | 1659 | ||
| 1676 | if (!skb_is_gso(skb) && !(dst->dev->features & NETIF_F_IPV6_CSUM)) { | 1660 | udp6_set_csum(udp_get_no_check6_tx(vs->sock->sk), skb, |
| 1677 | __wsum csum = skb_checksum(skb, 0, skb->len, 0); | 1661 | saddr, daddr, skb->len); |
| 1678 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
| 1679 | uh->check = csum_ipv6_magic(saddr, daddr, skb->len, | ||
| 1680 | IPPROTO_UDP, csum); | ||
| 1681 | if (uh->check == 0) | ||
| 1682 | uh->check = CSUM_MANGLED_0; | ||
| 1683 | } else { | ||
| 1684 | skb->ip_summed = CHECKSUM_PARTIAL; | ||
| 1685 | skb->csum_start = skb_transport_header(skb) - skb->head; | ||
| 1686 | skb->csum_offset = offsetof(struct udphdr, check); | ||
| 1687 | uh->check = ~csum_ipv6_magic(saddr, daddr, | ||
| 1688 | skb->len, IPPROTO_UDP, 0); | ||
| 1689 | } | ||
| 1690 | 1662 | ||
| 1691 | __skb_push(skb, sizeof(*ip6h)); | 1663 | __skb_push(skb, sizeof(*ip6h)); |
| 1692 | skb_reset_network_header(skb); | 1664 | skb_reset_network_header(skb); |
| @@ -1702,10 +1674,6 @@ static int vxlan6_xmit_skb(struct vxlan_sock *vs, | |||
| 1702 | ip6h->daddr = *daddr; | 1674 | ip6h->daddr = *daddr; |
| 1703 | ip6h->saddr = *saddr; | 1675 | ip6h->saddr = *saddr; |
| 1704 | 1676 | ||
| 1705 | err = handle_offloads(skb); | ||
| 1706 | if (err) | ||
| 1707 | return err; | ||
| 1708 | |||
| 1709 | ip6tunnel_xmit(skb, dev); | 1677 | ip6tunnel_xmit(skb, dev); |
| 1710 | return 0; | 1678 | return 0; |
| 1711 | } | 1679 | } |
| @@ -1721,10 +1689,9 @@ int vxlan_xmit_skb(struct vxlan_sock *vs, | |||
| 1721 | int min_headroom; | 1689 | int min_headroom; |
| 1722 | int err; | 1690 | int err; |
| 1723 | 1691 | ||
| 1724 | if (!skb->encapsulation) { | 1692 | skb = vxlan_handle_offloads(skb, !vs->sock->sk->sk_no_check_tx); |
| 1725 | skb_reset_inner_headers(skb); | 1693 | if (IS_ERR(skb)) |
| 1726 | skb->encapsulation = 1; | 1694 | return -EINVAL; |
| 1727 | } | ||
| 1728 | 1695 | ||
| 1729 | min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len | 1696 | min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len |
| 1730 | + VXLAN_HLEN + sizeof(struct iphdr) | 1697 | + VXLAN_HLEN + sizeof(struct iphdr) |
| @@ -1756,11 +1723,9 @@ int vxlan_xmit_skb(struct vxlan_sock *vs, | |||
| 1756 | uh->source = src_port; | 1723 | uh->source = src_port; |
| 1757 | 1724 | ||
| 1758 | uh->len = htons(skb->len); | 1725 | uh->len = htons(skb->len); |
| 1759 | uh->check = 0; | ||
| 1760 | 1726 | ||
| 1761 | err = handle_offloads(skb); | 1727 | udp_set_csum(vs->sock->sk->sk_no_check_tx, skb, |
| 1762 | if (err) | 1728 | src, dst, skb->len); |
| 1763 | return err; | ||
| 1764 | 1729 | ||
| 1765 | return iptunnel_xmit(vs->sock->sk, rt, skb, src, dst, IPPROTO_UDP, | 1730 | return iptunnel_xmit(vs->sock->sk, rt, skb, src, dst, IPPROTO_UDP, |
| 1766 | tos, ttl, df, xnet); | 1731 | tos, ttl, df, xnet); |
| @@ -2405,7 +2370,7 @@ static void vxlan_del_work(struct work_struct *work) | |||
| 2405 | * could be used for both IPv4 and IPv6 communications, but | 2370 | * could be used for both IPv4 and IPv6 communications, but |
| 2406 | * users may set bindv6only=1. | 2371 | * users may set bindv6only=1. |
| 2407 | */ | 2372 | */ |
| 2408 | static struct socket *create_v6_sock(struct net *net, __be16 port) | 2373 | static struct socket *create_v6_sock(struct net *net, __be16 port, u32 flags) |
| 2409 | { | 2374 | { |
| 2410 | struct sock *sk; | 2375 | struct sock *sk; |
| 2411 | struct socket *sock; | 2376 | struct socket *sock; |
| @@ -2442,18 +2407,25 @@ static struct socket *create_v6_sock(struct net *net, __be16 port) | |||
| 2442 | 2407 | ||
| 2443 | /* Disable multicast loopback */ | 2408 | /* Disable multicast loopback */ |
| 2444 | inet_sk(sk)->mc_loop = 0; | 2409 | inet_sk(sk)->mc_loop = 0; |
| 2410 | |||
| 2411 | if (flags & VXLAN_F_UDP_ZERO_CSUM6_TX) | ||
| 2412 | udp_set_no_check6_tx(sk, true); | ||
| 2413 | |||
| 2414 | if (flags & VXLAN_F_UDP_ZERO_CSUM6_RX) | ||
| 2415 | udp_set_no_check6_rx(sk, true); | ||
| 2416 | |||
| 2445 | return sock; | 2417 | return sock; |
| 2446 | } | 2418 | } |
| 2447 | 2419 | ||
| 2448 | #else | 2420 | #else |
| 2449 | 2421 | ||
| 2450 | static struct socket *create_v6_sock(struct net *net, __be16 port) | 2422 | static struct socket *create_v6_sock(struct net *net, __be16 port, u32 flags) |
| 2451 | { | 2423 | { |
| 2452 | return ERR_PTR(-EPFNOSUPPORT); | 2424 | return ERR_PTR(-EPFNOSUPPORT); |
| 2453 | } | 2425 | } |
| 2454 | #endif | 2426 | #endif |
| 2455 | 2427 | ||
| 2456 | static struct socket *create_v4_sock(struct net *net, __be16 port) | 2428 | static struct socket *create_v4_sock(struct net *net, __be16 port, u32 flags) |
| 2457 | { | 2429 | { |
| 2458 | struct sock *sk; | 2430 | struct sock *sk; |
| 2459 | struct socket *sock; | 2431 | struct socket *sock; |
| @@ -2486,18 +2458,24 @@ static struct socket *create_v4_sock(struct net *net, __be16 port) | |||
| 2486 | 2458 | ||
| 2487 | /* Disable multicast loopback */ | 2459 | /* Disable multicast loopback */ |
| 2488 | inet_sk(sk)->mc_loop = 0; | 2460 | inet_sk(sk)->mc_loop = 0; |
| 2461 | |||
| 2462 | if (!(flags & VXLAN_F_UDP_CSUM)) | ||
| 2463 | sock->sk->sk_no_check_tx = 1; | ||
| 2464 | |||
| 2489 | return sock; | 2465 | return sock; |
| 2490 | } | 2466 | } |
| 2491 | 2467 | ||
| 2492 | /* Create new listen socket if needed */ | 2468 | /* Create new listen socket if needed */ |
| 2493 | static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port, | 2469 | static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port, |
| 2494 | vxlan_rcv_t *rcv, void *data, bool ipv6) | 2470 | vxlan_rcv_t *rcv, void *data, |
| 2471 | u32 flags) | ||
| 2495 | { | 2472 | { |
| 2496 | struct vxlan_net *vn = net_generic(net, vxlan_net_id); | 2473 | struct vxlan_net *vn = net_generic(net, vxlan_net_id); |
| 2497 | struct vxlan_sock *vs; | 2474 | struct vxlan_sock *vs; |
| 2498 | struct socket *sock; | 2475 | struct socket *sock; |
| 2499 | struct sock *sk; | 2476 | struct sock *sk; |
| 2500 | unsigned int h; | 2477 | unsigned int h; |
| 2478 | bool ipv6 = !!(flags & VXLAN_F_IPV6); | ||
| 2501 | 2479 | ||
| 2502 | vs = kzalloc(sizeof(*vs), GFP_KERNEL); | 2480 | vs = kzalloc(sizeof(*vs), GFP_KERNEL); |
| 2503 | if (!vs) | 2481 | if (!vs) |
| @@ -2509,9 +2487,9 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port, | |||
| 2509 | INIT_WORK(&vs->del_work, vxlan_del_work); | 2487 | INIT_WORK(&vs->del_work, vxlan_del_work); |
| 2510 | 2488 | ||
| 2511 | if (ipv6) | 2489 | if (ipv6) |
| 2512 | sock = create_v6_sock(net, port); | 2490 | sock = create_v6_sock(net, port, flags); |
| 2513 | else | 2491 | else |
| 2514 | sock = create_v4_sock(net, port); | 2492 | sock = create_v4_sock(net, port, flags); |
| 2515 | if (IS_ERR(sock)) { | 2493 | if (IS_ERR(sock)) { |
| 2516 | kfree(vs); | 2494 | kfree(vs); |
| 2517 | return ERR_CAST(sock); | 2495 | return ERR_CAST(sock); |
| @@ -2549,12 +2527,12 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port, | |||
| 2549 | 2527 | ||
| 2550 | struct vxlan_sock *vxlan_sock_add(struct net *net, __be16 port, | 2528 | struct vxlan_sock *vxlan_sock_add(struct net *net, __be16 port, |
| 2551 | vxlan_rcv_t *rcv, void *data, | 2529 | vxlan_rcv_t *rcv, void *data, |
| 2552 | bool no_share, bool ipv6) | 2530 | bool no_share, u32 flags) |
| 2553 | { | 2531 | { |
| 2554 | struct vxlan_net *vn = net_generic(net, vxlan_net_id); | 2532 | struct vxlan_net *vn = net_generic(net, vxlan_net_id); |
| 2555 | struct vxlan_sock *vs; | 2533 | struct vxlan_sock *vs; |
| 2556 | 2534 | ||
| 2557 | vs = vxlan_socket_create(net, port, rcv, data, ipv6); | 2535 | vs = vxlan_socket_create(net, port, rcv, data, flags); |
| 2558 | if (!IS_ERR(vs)) | 2536 | if (!IS_ERR(vs)) |
| 2559 | return vs; | 2537 | return vs; |
| 2560 | 2538 | ||
| @@ -2587,7 +2565,7 @@ static void vxlan_sock_work(struct work_struct *work) | |||
| 2587 | __be16 port = vxlan->dst_port; | 2565 | __be16 port = vxlan->dst_port; |
| 2588 | struct vxlan_sock *nvs; | 2566 | struct vxlan_sock *nvs; |
| 2589 | 2567 | ||
| 2590 | nvs = vxlan_sock_add(net, port, vxlan_rcv, NULL, false, vxlan->flags & VXLAN_F_IPV6); | 2568 | nvs = vxlan_sock_add(net, port, vxlan_rcv, NULL, false, vxlan->flags); |
| 2591 | spin_lock(&vn->sock_lock); | 2569 | spin_lock(&vn->sock_lock); |
| 2592 | if (!IS_ERR(nvs)) | 2570 | if (!IS_ERR(nvs)) |
| 2593 | vxlan_vs_add_dev(nvs, vxlan); | 2571 | vxlan_vs_add_dev(nvs, vxlan); |
| @@ -2711,6 +2689,17 @@ static int vxlan_newlink(struct net *net, struct net_device *dev, | |||
| 2711 | if (data[IFLA_VXLAN_PORT]) | 2689 | if (data[IFLA_VXLAN_PORT]) |
| 2712 | vxlan->dst_port = nla_get_be16(data[IFLA_VXLAN_PORT]); | 2690 | vxlan->dst_port = nla_get_be16(data[IFLA_VXLAN_PORT]); |
| 2713 | 2691 | ||
| 2692 | if (data[IFLA_VXLAN_UDP_CSUM] && nla_get_u8(data[IFLA_VXLAN_UDP_CSUM])) | ||
| 2693 | vxlan->flags |= VXLAN_F_UDP_CSUM; | ||
| 2694 | |||
| 2695 | if (data[IFLA_VXLAN_UDP_ZERO_CSUM6_TX] && | ||
| 2696 | nla_get_u8(data[IFLA_VXLAN_UDP_ZERO_CSUM6_TX])) | ||
| 2697 | vxlan->flags |= VXLAN_F_UDP_ZERO_CSUM6_TX; | ||
| 2698 | |||
| 2699 | if (data[IFLA_VXLAN_UDP_ZERO_CSUM6_RX] && | ||
| 2700 | nla_get_u8(data[IFLA_VXLAN_UDP_ZERO_CSUM6_RX])) | ||
| 2701 | vxlan->flags |= VXLAN_F_UDP_ZERO_CSUM6_RX; | ||
| 2702 | |||
| 2714 | if (vxlan_find_vni(net, vni, vxlan->dst_port)) { | 2703 | if (vxlan_find_vni(net, vni, vxlan->dst_port)) { |
| 2715 | pr_info("duplicate VNI %u\n", vni); | 2704 | pr_info("duplicate VNI %u\n", vni); |
| 2716 | return -EEXIST; | 2705 | return -EEXIST; |
| @@ -2774,7 +2763,10 @@ static size_t vxlan_get_size(const struct net_device *dev) | |||
| 2774 | nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_AGEING */ | 2763 | nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_AGEING */ |
| 2775 | nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_LIMIT */ | 2764 | nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_LIMIT */ |
| 2776 | nla_total_size(sizeof(struct ifla_vxlan_port_range)) + | 2765 | nla_total_size(sizeof(struct ifla_vxlan_port_range)) + |
| 2777 | nla_total_size(sizeof(__be16))+ /* IFLA_VXLAN_PORT */ | 2766 | nla_total_size(sizeof(__be16)) + /* IFLA_VXLAN_PORT */ |
| 2767 | nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_UDP_CSUM */ | ||
| 2768 | nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_UDP_ZERO_CSUM6_TX */ | ||
| 2769 | nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_UDP_ZERO_CSUM6_RX */ | ||
| 2778 | 0; | 2770 | 0; |
| 2779 | } | 2771 | } |
| 2780 | 2772 | ||
| @@ -2834,7 +2826,13 @@ static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev) | |||
| 2834 | !!(vxlan->flags & VXLAN_F_L3MISS)) || | 2826 | !!(vxlan->flags & VXLAN_F_L3MISS)) || |
| 2835 | nla_put_u32(skb, IFLA_VXLAN_AGEING, vxlan->age_interval) || | 2827 | nla_put_u32(skb, IFLA_VXLAN_AGEING, vxlan->age_interval) || |
| 2836 | nla_put_u32(skb, IFLA_VXLAN_LIMIT, vxlan->addrmax) || | 2828 | nla_put_u32(skb, IFLA_VXLAN_LIMIT, vxlan->addrmax) || |
| 2837 | nla_put_be16(skb, IFLA_VXLAN_PORT, vxlan->dst_port)) | 2829 | nla_put_be16(skb, IFLA_VXLAN_PORT, vxlan->dst_port) || |
| 2830 | nla_put_u8(skb, IFLA_VXLAN_UDP_CSUM, | ||
| 2831 | !!(vxlan->flags & VXLAN_F_UDP_CSUM)) || | ||
| 2832 | nla_put_u8(skb, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, | ||
| 2833 | !!(vxlan->flags & VXLAN_F_UDP_ZERO_CSUM6_TX)) || | ||
| 2834 | nla_put_u8(skb, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, | ||
| 2835 | !!(vxlan->flags & VXLAN_F_UDP_ZERO_CSUM6_RX))) | ||
| 2838 | goto nla_put_failure; | 2836 | goto nla_put_failure; |
| 2839 | 2837 | ||
| 2840 | if (nla_put(skb, IFLA_VXLAN_PORT_RANGE, sizeof(ports), &ports)) | 2838 | if (nla_put(skb, IFLA_VXLAN_PORT_RANGE, sizeof(ports), &ports)) |
diff --git a/include/net/vxlan.h b/include/net/vxlan.h index 7bb4084b1bd0..12196ce661d9 100644 --- a/include/net/vxlan.h +++ b/include/net/vxlan.h | |||
| @@ -24,9 +24,19 @@ struct vxlan_sock { | |||
| 24 | struct udp_offload udp_offloads; | 24 | struct udp_offload udp_offloads; |
| 25 | }; | 25 | }; |
| 26 | 26 | ||
| 27 | #define VXLAN_F_LEARN 0x01 | ||
| 28 | #define VXLAN_F_PROXY 0x02 | ||
| 29 | #define VXLAN_F_RSC 0x04 | ||
| 30 | #define VXLAN_F_L2MISS 0x08 | ||
| 31 | #define VXLAN_F_L3MISS 0x10 | ||
| 32 | #define VXLAN_F_IPV6 0x20 | ||
| 33 | #define VXLAN_F_UDP_CSUM 0x40 | ||
| 34 | #define VXLAN_F_UDP_ZERO_CSUM6_TX 0x80 | ||
| 35 | #define VXLAN_F_UDP_ZERO_CSUM6_RX 0x100 | ||
| 36 | |||
| 27 | struct vxlan_sock *vxlan_sock_add(struct net *net, __be16 port, | 37 | struct vxlan_sock *vxlan_sock_add(struct net *net, __be16 port, |
| 28 | vxlan_rcv_t *rcv, void *data, | 38 | vxlan_rcv_t *rcv, void *data, |
| 29 | bool no_share, bool ipv6); | 39 | bool no_share, u32 flags); |
| 30 | 40 | ||
| 31 | void vxlan_sock_release(struct vxlan_sock *vs); | 41 | void vxlan_sock_release(struct vxlan_sock *vs); |
| 32 | 42 | ||
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index 622e7910b8cc..b38534895db5 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h | |||
| @@ -319,6 +319,9 @@ enum { | |||
| 319 | IFLA_VXLAN_PORT, /* destination port */ | 319 | IFLA_VXLAN_PORT, /* destination port */ |
| 320 | IFLA_VXLAN_GROUP6, | 320 | IFLA_VXLAN_GROUP6, |
| 321 | IFLA_VXLAN_LOCAL6, | 321 | IFLA_VXLAN_LOCAL6, |
| 322 | IFLA_VXLAN_UDP_CSUM, | ||
| 323 | IFLA_VXLAN_UDP_ZERO_CSUM6_TX, | ||
| 324 | IFLA_VXLAN_UDP_ZERO_CSUM6_RX, | ||
| 322 | __IFLA_VXLAN_MAX | 325 | __IFLA_VXLAN_MAX |
| 323 | }; | 326 | }; |
| 324 | #define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1) | 327 | #define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1) |
diff --git a/net/openvswitch/vport-vxlan.c b/net/openvswitch/vport-vxlan.c index a93efa3f64c3..0edbd95c60e7 100644 --- a/net/openvswitch/vport-vxlan.c +++ b/net/openvswitch/vport-vxlan.c | |||
| @@ -122,7 +122,7 @@ static struct vport *vxlan_tnl_create(const struct vport_parms *parms) | |||
| 122 | vxlan_port = vxlan_vport(vport); | 122 | vxlan_port = vxlan_vport(vport); |
| 123 | strncpy(vxlan_port->name, parms->name, IFNAMSIZ); | 123 | strncpy(vxlan_port->name, parms->name, IFNAMSIZ); |
| 124 | 124 | ||
| 125 | vs = vxlan_sock_add(net, htons(dst_port), vxlan_rcv, vport, true, false); | 125 | vs = vxlan_sock_add(net, htons(dst_port), vxlan_rcv, vport, true, 0); |
| 126 | if (IS_ERR(vs)) { | 126 | if (IS_ERR(vs)) { |
| 127 | ovs_vport_free(vport); | 127 | ovs_vport_free(vport); |
| 128 | return (void *)vs; | 128 | return (void *)vs; |
