netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [Patch net-next v7 0/6] vxlan: add ipv6 support
@ 2013-04-30  8:43 Cong Wang
  2013-04-30  8:43 ` [Patch net-next v7 1/6] vxlan: defer vxlan init as late as possible Cong Wang
                   ` (6 more replies)
  0 siblings, 7 replies; 23+ messages in thread
From: Cong Wang @ 2013-04-30  8:43 UTC (permalink / raw)
  To: netdev; +Cc: Cong Wang

v7: respect disable_ipv6 flag
    back to ipv4 only when ipv6 is not supported

v6: use a stub for IPv6 mcast functions
    split a few more long lines
    rebased on the latest net-next

v5: make David happy on the names of the fields
    fix my mistake during rebasing the patches
    drop the scope_id patch, because it is broken
    export in6addr_loopback
    fix a udp checksum bug
    rebased on the latest net-next

v4: rename ->sin to ->va_sin
    rename ->sin6 to ->va_sin6
    rename ->family to ->va_sa
    support ll addr
    fix more ugly #ifdef
    rebased on the latest net-next

v3: fix many coding style issues
    fix some ugly #ifdef
    rename vxlan_ip to vxlan_addr
    rename ->proto to ->family
    rename ->ip4/->ip6 to ->sin/->sin6

v2: fix some compile error when !CONFIG_IPV6
    improve some code based on Stephen's comments
    use sockaddr suggested by David

Cong Wang (6):
  vxlan: defer vxlan init as late as possible
  ipv6: export a stub for ipv6_sock_mc_join and ipv6_sock_mc_drop
  ipv6: export in6addr_loopback to modules
  vxlan: add ipv6 support
  vxlan: respect disable_ipv6 sysctl
  ipv6: Add generic UDP Tunnel segmentation

 drivers/net/vxlan.c          |  662 +++++++++++++++++++++++++++++++++---------
 include/net/addrconf.h       |    9 +
 include/uapi/linux/if_link.h |    2 +
 net/ipv6/addrconf.c          |    9 -
 net/ipv6/addrconf_core.c     |   13 +
 net/ipv6/ip6_offload.c       |    4 +-
 net/ipv6/mcast.c             |    7 +
 net/ipv6/udp_offload.c       |  153 +++++++---
 8 files changed, 664 insertions(+), 195 deletions(-)

-- 
1.7.7.6

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [Patch net-next v7 1/6] vxlan: defer vxlan init as late as possible
  2013-04-30  8:43 [Patch net-next v7 0/6] vxlan: add ipv6 support Cong Wang
@ 2013-04-30  8:43 ` Cong Wang
  2013-04-30  8:43 ` [Patch net-next v7 2/6] ipv6: export a stub for ipv6_sock_mc_join and ipv6_sock_mc_drop Cong Wang
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 23+ messages in thread
From: Cong Wang @ 2013-04-30  8:43 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger, David S. Miller, Cong Wang

From: Cong Wang <amwang@redhat.com>

When vxlan is compiled as builtin, its init code
runs before IPv6 init, this could cause problems
if we create IPv6 socket in the latter patch.

Cc: Stephen Hemminger <stephen@networkplumber.org>
Cc: David S. Miller <davem@davemloft.net>
Signed-off-by: Cong Wang <amwang@redhat.com>
---
 drivers/net/vxlan.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index ba81f3c..c1258c6 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -1662,7 +1662,7 @@ out2:
 out1:
 	return rc;
 }
-module_init(vxlan_init_module);
+late_initcall(vxlan_init_module);
 
 static void __exit vxlan_cleanup_module(void)
 {
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Patch net-next v7 2/6] ipv6: export a stub for ipv6_sock_mc_join and ipv6_sock_mc_drop
  2013-04-30  8:43 [Patch net-next v7 0/6] vxlan: add ipv6 support Cong Wang
  2013-04-30  8:43 ` [Patch net-next v7 1/6] vxlan: defer vxlan init as late as possible Cong Wang
@ 2013-04-30  8:43 ` Cong Wang
  2013-04-30  8:43 ` [Patch net-next v7 3/6] ipv6: export in6addr_loopback to modules Cong Wang
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 23+ messages in thread
From: Cong Wang @ 2013-04-30  8:43 UTC (permalink / raw)
  To: netdev
  Cc: Ben Hutchings, Bjørn Mork, Stephen Hemminger,
	David S. Miller, Cong Wang

From: Cong Wang <amwang@redhat.com>

In case IPv6 is compiled as a module, introduce a stub
for ipv6_sock_mc_join and ipv6_sock_mc_drop. It will be used
by vxlan module. Suggested by Ben.

Cc: Ben Hutchings <bhutchings@solarflare.com>
Cc: Bjørn Mork <bjorn@mork.no>
Cc: Stephen Hemminger <stephen@networkplumber.org>
Cc: David S. Miller <davem@davemloft.net>
Signed-off-by: Cong Wang <amwang@redhat.com>
---
 include/net/addrconf.h   |    9 +++++++++
 net/ipv6/addrconf_core.c |    3 +++
 net/ipv6/mcast.c         |    7 +++++++
 3 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index 84a6440..c82e00f 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -140,6 +140,15 @@ extern bool inet6_mc_check(struct sock *sk,
 			   const struct in6_addr *mc_addr,
 			   const struct in6_addr *src_addr);
 
+/* A stub used by vxlan module */
+struct ipv6_mcast_ops {
+	int (*ipv6_sock_mc_join)(struct sock *sk, int ifindex,
+				 const struct in6_addr *addr);
+	int (*ipv6_sock_mc_drop)(struct sock *sk, int ifindex,
+				 const struct in6_addr *addr);
+};
+extern const struct ipv6_mcast_ops *ipv6_mcast_ops __read_mostly;
+
 extern int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr);
 extern int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr);
 extern int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr);
diff --git a/net/ipv6/addrconf_core.c b/net/ipv6/addrconf_core.c
index 7210456..8c7cb63 100644
--- a/net/ipv6/addrconf_core.c
+++ b/net/ipv6/addrconf_core.c
@@ -97,3 +97,6 @@ int inet6addr_notifier_call_chain(unsigned long val, void *v)
 	return atomic_notifier_call_chain(&inet6addr_chain, val, v);
 }
 EXPORT_SYMBOL(inet6addr_notifier_call_chain);
+
+const struct ipv6_mcast_ops *ipv6_mcast_ops __read_mostly;
+EXPORT_SYMBOL_GPL(ipv6_mcast_ops);
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index bfa6cc3..cfa31d2 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -2665,12 +2665,19 @@ static struct pernet_operations igmp6_net_ops = {
 	.exit = igmp6_net_exit,
 };
 
+static const struct ipv6_mcast_ops ipv6_mcast_ops_impl = {
+	.ipv6_sock_mc_join = ipv6_sock_mc_join,
+	.ipv6_sock_mc_drop = ipv6_sock_mc_drop,
+};
+
 int __init igmp6_init(void)
 {
+	ipv6_mcast_ops = &ipv6_mcast_ops_impl;
 	return register_pernet_subsys(&igmp6_net_ops);
 }
 
 void igmp6_cleanup(void)
 {
+	ipv6_mcast_ops = NULL;
 	unregister_pernet_subsys(&igmp6_net_ops);
 }
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Patch net-next v7 3/6] ipv6: export in6addr_loopback to modules
  2013-04-30  8:43 [Patch net-next v7 0/6] vxlan: add ipv6 support Cong Wang
  2013-04-30  8:43 ` [Patch net-next v7 1/6] vxlan: defer vxlan init as late as possible Cong Wang
  2013-04-30  8:43 ` [Patch net-next v7 2/6] ipv6: export a stub for ipv6_sock_mc_join and ipv6_sock_mc_drop Cong Wang
@ 2013-04-30  8:43 ` Cong Wang
  2013-04-30  8:43 ` [Patch net-next v7 4/6] vxlan: add ipv6 support Cong Wang
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 23+ messages in thread
From: Cong Wang @ 2013-04-30  8:43 UTC (permalink / raw)
  To: netdev; +Cc: David S. Miller, Mike Rapoport, Cong Wang

From: Cong Wang <amwang@redhat.com>

It is needed by vxlan module.

Cc: David S. Miller <davem@davemloft.net>
Cc: Mike Rapoport <mike.rapoport@ravellosystems.com>
Signed-off-by: Cong Wang <amwang@redhat.com>
---
 net/ipv6/addrconf.c      |    9 ---------
 net/ipv6/addrconf_core.c |   10 ++++++++++
 2 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index d1ab6ab..650a109 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -238,15 +238,6 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
 	.accept_dad		= 1,
 };
 
-/* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */
-const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
-const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
-const struct in6_addr in6addr_linklocal_allnodes = IN6ADDR_LINKLOCAL_ALLNODES_INIT;
-const struct in6_addr in6addr_linklocal_allrouters = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
-const struct in6_addr in6addr_interfacelocal_allnodes = IN6ADDR_INTERFACELOCAL_ALLNODES_INIT;
-const struct in6_addr in6addr_interfacelocal_allrouters = IN6ADDR_INTERFACELOCAL_ALLROUTERS_INIT;
-const struct in6_addr in6addr_sitelocal_allrouters = IN6ADDR_SITELOCAL_ALLROUTERS_INIT;
-
 /* Check if a valid qdisc is available */
 static inline bool addrconf_qdisc_ok(const struct net_device *dev)
 {
diff --git a/net/ipv6/addrconf_core.c b/net/ipv6/addrconf_core.c
index 8c7cb63..8155cd2 100644
--- a/net/ipv6/addrconf_core.c
+++ b/net/ipv6/addrconf_core.c
@@ -98,5 +98,15 @@ int inet6addr_notifier_call_chain(unsigned long val, void *v)
 }
 EXPORT_SYMBOL(inet6addr_notifier_call_chain);
 
+/* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */
+const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
+EXPORT_SYMBOL(in6addr_loopback);
+const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
+const struct in6_addr in6addr_linklocal_allnodes = IN6ADDR_LINKLOCAL_ALLNODES_INIT;
+const struct in6_addr in6addr_linklocal_allrouters = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
+const struct in6_addr in6addr_interfacelocal_allnodes = IN6ADDR_INTERFACELOCAL_ALLNODES_INIT;
+const struct in6_addr in6addr_interfacelocal_allrouters = IN6ADDR_INTERFACELOCAL_ALLROUTERS_INIT;
+const struct in6_addr in6addr_sitelocal_allrouters = IN6ADDR_SITELOCAL_ALLROUTERS_INIT;
+
 const struct ipv6_mcast_ops *ipv6_mcast_ops __read_mostly;
 EXPORT_SYMBOL_GPL(ipv6_mcast_ops);
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Patch net-next v7 4/6] vxlan: add ipv6 support
  2013-04-30  8:43 [Patch net-next v7 0/6] vxlan: add ipv6 support Cong Wang
                   ` (2 preceding siblings ...)
  2013-04-30  8:43 ` [Patch net-next v7 3/6] ipv6: export in6addr_loopback to modules Cong Wang
@ 2013-04-30  8:43 ` Cong Wang
  2013-04-30  9:17   ` Bjørn Mork
  2013-04-30  8:43 ` [Patch net-next v7 5/6] vxlan: respect disable_ipv6 sysctl Cong Wang
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 23+ messages in thread
From: Cong Wang @ 2013-04-30  8:43 UTC (permalink / raw)
  To: netdev; +Cc: David Stevens, Stephen Hemminger, David S. Miller, Cong Wang

From: Cong Wang <amwang@redhat.com>

This patch adds IPv6 support to vxlan device, as the new version
RFC already mentions it:

   http://tools.ietf.org/html/draft-mahalingam-dutt-dcops-vxlan-03

Cc: David Stevens <dlstevens@us.ibm.com>
Cc: Stephen Hemminger <stephen@networkplumber.org>
Cc: David S. Miller <davem@davemloft.net>
Signed-off-by: Cong Wang <amwang@redhat.com>
---
 drivers/net/vxlan.c          |  648 +++++++++++++++++++++++++++++++++---------
 include/uapi/linux/if_link.h |    2 +
 2 files changed, 514 insertions(+), 136 deletions(-)

diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index c1258c6..bb39e67 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -6,9 +6,6 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * TODO
- *  - IPv6 (not in RFC)
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -41,6 +38,11 @@
 #include <net/inet_ecn.h>
 #include <net/net_namespace.h>
 #include <net/netns/generic.h>
+#if IS_ENABLED(CONFIG_IPV6)
+#include <net/addrconf.h>
+#include <net/ip6_route.h>
+#include <net/ip6_tunnel.h>
+#endif
 
 #define VXLAN_VERSION	"0.1"
 
@@ -55,6 +57,8 @@
 #define VXLAN_VID_MASK	(VXLAN_N_VID - 1)
 /* IP header + UDP + VXLAN + Ethernet header */
 #define VXLAN_HEADROOM (20 + 8 + 8 + 14)
+/* IPv6 header + UDP + VXLAN + Ethernet header */
+#define VXLAN6_HEADROOM (40 + 8 + 8 + 14)
 
 #define VXLAN_FLAGS 0x08000000	/* struct vxlanhdr.vx_flags required value. */
 
@@ -76,6 +80,10 @@ static bool log_ecn_error = true;
 module_param(log_ecn_error, bool, 0644);
 MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN");
 
+#if IS_ENABLED(CONFIG_IPV6)
+static bool ipv6_disabled = false;
+#endif
+
 /* per-net private data for this module */
 static unsigned int vxlan_net_id;
 struct vxlan_net {
@@ -83,9 +91,15 @@ struct vxlan_net {
 	struct hlist_head vni_list[VNI_HASH_SIZE];
 };
 
+union vxlan_addr {
+	struct sockaddr_in	sin;
+	struct sockaddr_in6	sin6;
+	struct sockaddr		sa;
+};
+
 struct vxlan_rdst {
 	struct rcu_head		 rcu;
-	__be32			 remote_ip;
+	union vxlan_addr	 remote_ip;
 	__be16			 remote_port;
 	u32			 remote_vni;
 	u32			 remote_ifindex;
@@ -109,7 +123,7 @@ struct vxlan_dev {
 	struct hlist_node hlist;
 	struct net_device *dev;
 	struct vxlan_rdst default_dst;	/* default destination */
-	__be32		  saddr;	/* source address */
+	union vxlan_addr  saddr;	/* source address */
 	__be16		  dst_port;
 	__u16		  port_min;	/* source port range */
 	__u16		  port_max;
@@ -132,6 +146,69 @@ struct vxlan_dev {
 #define VXLAN_F_L2MISS	0x08
 #define VXLAN_F_L3MISS	0x10
 
+static inline
+bool vxlan_addr_equal(const union vxlan_addr *a, const union vxlan_addr *b)
+{
+#if IS_ENABLED(CONFIG_IPV6)
+	if (a->sa.sa_family != b->sa.sa_family)
+		return false;
+	if (a->sa.sa_family == AF_INET6)
+		return ipv6_addr_equal(&a->sin6.sin6_addr, &b->sin6.sin6_addr);
+	else
+#endif
+		return a->sin.sin_addr.s_addr == b->sin.sin_addr.s_addr;
+}
+
+static inline bool vxlan_addr_any(const union vxlan_addr *ipa)
+{
+#if IS_ENABLED(CONFIG_IPV6)
+	if (ipa->sa.sa_family == AF_INET6)
+		return ipv6_addr_any(&ipa->sin6.sin6_addr);
+	else
+#endif
+		return ipa->sin.sin_addr.s_addr == htonl(INADDR_ANY);
+}
+
+static inline bool vxlan_addr_multicast(const union vxlan_addr *ipa)
+{
+#if IS_ENABLED(CONFIG_IPV6)
+	if (ipa->sa.sa_family == AF_INET6)
+		return ipv6_addr_is_multicast(&ipa->sin6.sin6_addr);
+	else
+#endif
+		return IN_MULTICAST(ntohl(ipa->sin.sin_addr.s_addr));
+}
+
+static int vxlan_nla_get_addr(union vxlan_addr *ip, struct nlattr *nla)
+{
+	if (nla_len(nla) >= sizeof(struct in6_addr)) {
+#if IS_ENABLED(CONFIG_IPV6)
+		nla_memcpy(&ip->sin6.sin6_addr, nla, sizeof(struct in6_addr));
+		ip->sa.sa_family = AF_INET6;
+		return 0;
+#else
+		return -EAFNOSUPPORT;
+#endif
+	} else if (nla_len(nla) >= sizeof(__be32)) {
+		ip->sin.sin_addr.s_addr = nla_get_be32(nla);
+		ip->sa.sa_family = AF_INET;
+		return 0;
+	} else {
+		return -EAFNOSUPPORT;
+	}
+}
+
+static int vxlan_nla_put_addr(struct sk_buff *skb, int attr,
+			      const union vxlan_addr *ip)
+{
+#if IS_ENABLED(CONFIG_IPV6)
+	if (ip->sa.sa_family == AF_INET6)
+		return nla_put(skb, attr, sizeof(struct in6_addr), &ip->sin6.sin6_addr);
+	else
+#endif
+		return nla_put_be32(skb, attr, ip->sin.sin_addr.s_addr);
+}
+
 /* salt for hash table */
 static u32 vxlan_salt __read_mostly;
 
@@ -178,7 +255,7 @@ static int vxlan_fdb_info(struct sk_buff *skb, struct vxlan_dev *vxlan,
 
 	if (type == RTM_GETNEIGH) {
 		ndm->ndm_family	= AF_INET;
-		send_ip = rdst->remote_ip != htonl(INADDR_ANY);
+		send_ip = !vxlan_addr_any(&rdst->remote_ip);
 		send_eth = !is_zero_ether_addr(fdb->eth_addr);
 	} else
 		ndm->ndm_family	= AF_BRIDGE;
@@ -190,7 +267,7 @@ static int vxlan_fdb_info(struct sk_buff *skb, struct vxlan_dev *vxlan,
 	if (send_eth && nla_put(skb, NDA_LLADDR, ETH_ALEN, &fdb->eth_addr))
 		goto nla_put_failure;
 
-	if (send_ip && nla_put_be32(skb, NDA_DST, rdst->remote_ip))
+	if (send_ip && vxlan_nla_put_addr(skb, NDA_DST, &rdst->remote_ip))
 		goto nla_put_failure;
 
 	if (rdst->remote_port && rdst->remote_port != vxlan->dst_port &&
@@ -222,7 +299,7 @@ static inline size_t vxlan_nlmsg_size(void)
 {
 	return NLMSG_ALIGN(sizeof(struct ndmsg))
 		+ nla_total_size(ETH_ALEN) /* NDA_LLADDR */
-		+ nla_total_size(sizeof(__be32)) /* NDA_DST */
+		+ nla_total_size(sizeof(struct in6_addr)) /* NDA_DST */
 		+ nla_total_size(sizeof(__be16)) /* NDA_PORT */
 		+ nla_total_size(sizeof(__be32)) /* NDA_VNI */
 		+ nla_total_size(sizeof(__u32)) /* NDA_IFINDEX */
@@ -255,14 +332,14 @@ errout:
 		rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
 }
 
-static void vxlan_ip_miss(struct net_device *dev, __be32 ipa)
+static void vxlan_ip_miss(struct net_device *dev, union vxlan_addr *ipa)
 {
 	struct vxlan_dev *vxlan = netdev_priv(dev);
 	struct vxlan_fdb f;
 
 	memset(&f, 0, sizeof f);
 	f.state = NUD_STALE;
-	f.remote.remote_ip = ipa; /* goes to NDA_DST */
+	f.remote.remote_ip = *ipa; /* goes to NDA_DST */
 	f.remote.remote_vni = VXLAN_N_VID;
 
 	vxlan_fdb_notify(vxlan, &f, RTM_GETNEIGH);
@@ -317,14 +394,14 @@ static struct vxlan_fdb *vxlan_find_mac(struct vxlan_dev *vxlan,
 }
 
 /* Add/update destinations for multicast */
-static int vxlan_fdb_append(struct vxlan_fdb *f,
-			    __be32 ip, __be16 port, __u32 vni, __u32 ifindex)
+static int vxlan_fdb_append(struct vxlan_fdb *f, union vxlan_addr *ip,
+			    __be16 port, __u32 vni, __u32 ifindex)
 {
 	struct vxlan_rdst *rd_prev, *rd;
 
 	rd_prev = NULL;
 	for (rd = &f->remote; rd; rd = rd->remote_next) {
-		if (rd->remote_ip == ip &&
+		if (vxlan_addr_equal(&rd->remote_ip, ip) &&
 		    rd->remote_port == port &&
 		    rd->remote_vni == vni &&
 		    rd->remote_ifindex == ifindex)
@@ -334,7 +411,7 @@ static int vxlan_fdb_append(struct vxlan_fdb *f,
 	rd = kmalloc(sizeof(*rd), GFP_ATOMIC);
 	if (rd == NULL)
 		return -ENOBUFS;
-	rd->remote_ip = ip;
+	rd->remote_ip = *ip;
 	rd->remote_port = port;
 	rd->remote_vni = vni;
 	rd->remote_ifindex = ifindex;
@@ -345,7 +422,7 @@ static int vxlan_fdb_append(struct vxlan_fdb *f,
 
 /* Add new entry to forwarding table -- assumes lock held */
 static int vxlan_fdb_create(struct vxlan_dev *vxlan,
-			    const u8 *mac, __be32 ip,
+			    const u8 *mac, union vxlan_addr *ip,
 			    __u16 state, __u16 flags,
 			    __be16 port, __u32 vni, __u32 ifindex,
 			    __u8 ndm_flags)
@@ -385,13 +462,20 @@ static int vxlan_fdb_create(struct vxlan_dev *vxlan,
 		if (vxlan->addrmax && vxlan->addrcnt >= vxlan->addrmax)
 			return -ENOSPC;
 
-		netdev_dbg(vxlan->dev, "add %pM -> %pI4\n", mac, &ip);
+#if IS_ENABLED(CONFIG_IPV6)
+		if (ip->sa.sa_family == AF_INET6)
+			netdev_dbg(vxlan->dev, "add %pM -> %pI6\n", mac,
+				   &ip->sin6.sin6_addr);
+		else
+#endif
+			netdev_dbg(vxlan->dev, "add %pM -> %pI4\n", mac,
+				   &ip->sin.sin_addr.s_addr);
 		f = kmalloc(sizeof(*f), GFP_ATOMIC);
 		if (!f)
 			return -ENOMEM;
 
 		notify = 1;
-		f->remote.remote_ip = ip;
+		f->remote.remote_ip = *ip;
 		f->remote.remote_port = port;
 		f->remote.remote_vni = vni;
 		f->remote.remote_ifindex = ifindex;
@@ -444,7 +528,7 @@ static int vxlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
 {
 	struct vxlan_dev *vxlan = netdev_priv(dev);
 	struct net *net = dev_net(vxlan->dev);
-	__be32 ip;
+	union vxlan_addr ip;
 	__be16 port;
 	u32 vni, ifindex;
 	int err;
@@ -458,10 +542,9 @@ static int vxlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
 	if (tb[NDA_DST] == NULL)
 		return -EINVAL;
 
-	if (nla_len(tb[NDA_DST]) != sizeof(__be32))
-		return -EAFNOSUPPORT;
-
-	ip = nla_get_be32(tb[NDA_DST]);
+	err = vxlan_nla_get_addr(&ip, tb[NDA_DST]);
+	if (err)
+		return err;
 
 	if (tb[NDA_PORT]) {
 		if (nla_len(tb[NDA_PORT]) != sizeof(__be16))
@@ -491,7 +574,7 @@ static int vxlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
 		ifindex = 0;
 
 	spin_lock_bh(&vxlan->hash_lock);
-	err = vxlan_fdb_create(vxlan, addr, ip, ndm->ndm_state, flags,
+	err = vxlan_fdb_create(vxlan, addr, &ip, ndm->ndm_state, flags,
 			       port, vni, ifindex, ndm->ndm_flags);
 	spin_unlock_bh(&vxlan->hash_lock);
 
@@ -555,7 +638,7 @@ skip:
  * and Tunnel endpoint.
  */
 static void vxlan_snoop(struct net_device *dev,
-			__be32 src_ip, const u8 *src_mac)
+			union vxlan_addr *src_ip, const u8 *src_mac)
 {
 	struct vxlan_dev *vxlan = netdev_priv(dev);
 	struct vxlan_fdb *f;
@@ -564,15 +647,25 @@ static void vxlan_snoop(struct net_device *dev,
 	f = vxlan_find_mac(vxlan, src_mac);
 	if (likely(f)) {
 		f->used = jiffies;
-		if (likely(f->remote.remote_ip == src_ip))
+		if (likely(vxlan_addr_equal(&f->remote.remote_ip, src_ip)))
 			return;
 
-		if (net_ratelimit())
-			netdev_info(dev,
-				    "%pM migrated from %pI4 to %pI4\n",
-				    src_mac, &f->remote.remote_ip, &src_ip);
+		if (net_ratelimit()) {
+#if IS_ENABLED(CONFIG_IPV6)
+			if (src_ip->sa.sa_family == AF_INET6)
+				netdev_info(dev,
+					    "%pM migrated from %pI6 to %pI6\n",
+					    src_mac, &f->remote.remote_ip.sin6.sin6_addr,
+					    &src_ip->sin6.sin6_addr);
+			else
+#endif
+				netdev_info(dev,
+					    "%pM migrated from %pI4 to %pI4\n",
+					    src_mac, &f->remote.remote_ip.sin.sin_addr.s_addr,
+					    &src_ip->sin.sin_addr.s_addr);
+		}
 
-		f->remote.remote_ip = src_ip;
+		f->remote.remote_ip = *src_ip;
 		f->updated = jiffies;
 	} else {
 		/* learned new entry */
@@ -603,7 +696,8 @@ static bool vxlan_group_used(struct vxlan_net *vn,
 			if (!netif_running(vxlan->dev))
 				continue;
 
-			if (vxlan->default_dst.remote_ip == this->default_dst.remote_ip)
+			if (vxlan_addr_equal(&vxlan->default_dst.remote_ip,
+					     &this->default_dst.remote_ip))
 				return true;
 		}
 
@@ -616,8 +710,9 @@ static int vxlan_join_group(struct net_device *dev)
 	struct vxlan_dev *vxlan = netdev_priv(dev);
 	struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id);
 	struct sock *sk = vn->sock->sk;
+	union vxlan_addr *ip = &vxlan->default_dst.remote_ip;
 	struct ip_mreqn mreq = {
-		.imr_multiaddr.s_addr	= vxlan->default_dst.remote_ip,
+		.imr_multiaddr.s_addr	= ip->sin.sin_addr.s_addr,
 		.imr_ifindex		= vxlan->default_dst.remote_ifindex,
 	};
 	int err;
@@ -629,7 +724,13 @@ static int vxlan_join_group(struct net_device *dev)
 	/* Need to drop RTNL to call multicast join */
 	rtnl_unlock();
 	lock_sock(sk);
-	err = ip_mc_join_group(sk, &mreq);
+#if IS_ENABLED(CONFIG_IPV6)
+	if (vxlan->default_dst.remote_ip.sa.sa_family == AF_INET6)
+		err = ipv6_mcast_ops->ipv6_sock_mc_join(sk, vxlan->default_dst.remote_ifindex,
+							&ip->sin6.sin6_addr);
+	else
+#endif
+		err = ip_mc_join_group(sk, &mreq);
 	release_sock(sk);
 	rtnl_lock();
 
@@ -644,8 +745,9 @@ static int vxlan_leave_group(struct net_device *dev)
 	struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id);
 	int err = 0;
 	struct sock *sk = vn->sock->sk;
+	union vxlan_addr *ip = &vxlan->default_dst.remote_ip;
 	struct ip_mreqn mreq = {
-		.imr_multiaddr.s_addr	= vxlan->default_dst.remote_ip,
+		.imr_multiaddr.s_addr	= ip->sin.sin_addr.s_addr,
 		.imr_ifindex		= vxlan->default_dst.remote_ifindex,
 	};
 
@@ -656,7 +758,13 @@ static int vxlan_leave_group(struct net_device *dev)
 	/* Need to drop RTNL to call multicast leave */
 	rtnl_unlock();
 	lock_sock(sk);
-	err = ip_mc_leave_group(sk, &mreq);
+#if IS_ENABLED(CONFIG_IPV6)
+	if (vxlan->default_dst.remote_ip.sa.sa_family == AF_INET6)
+		err = ipv6_mcast_ops->ipv6_sock_mc_drop(sk, vxlan->default_dst.remote_ifindex,
+							&ip->sin6.sin6_addr);
+	else
+#endif
+		err = ip_mc_leave_group(sk, &mreq);
 	release_sock(sk);
 	rtnl_lock();
 
@@ -666,12 +774,16 @@ static int vxlan_leave_group(struct net_device *dev)
 /* Callback from net/ipv4/udp.c to receive packets */
 static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
 {
-	struct iphdr *oip;
+	struct iphdr *oip = NULL;
+#if IS_ENABLED(CONFIG_IPV6)
+	struct ipv6hdr *oip6 = NULL;
+#endif
 	struct vxlanhdr *vxh;
 	struct vxlan_dev *vxlan;
 	struct pcpu_tstats *stats;
+	union vxlan_addr src_ip;
 	__u32 vni;
-	int err;
+	int err = 0;
 
 	/* pop off outer UDP header */
 	__skb_pull(skb, sizeof(struct udphdr));
@@ -708,7 +820,13 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
 	skb_reset_mac_header(skb);
 
 	/* Re-examine inner Ethernet packet */
-	oip = ip_hdr(skb);
+	if (skb->protocol == htons(ETH_P_IP))
+		oip = ip_hdr(skb);
+#if IS_ENABLED(CONFIG_IPV6)
+	if (skb->protocol == htons(ETH_P_IPV6))
+		oip6 = ipv6_hdr(skb);
+#endif
+
 	skb->protocol = eth_type_trans(skb, vxlan->dev);
 
 	/* Ignore packet loops (and multicast echo) */
@@ -716,8 +834,19 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
 			       vxlan->dev->dev_addr) == 0)
 		goto drop;
 
-	if (vxlan->flags & VXLAN_F_LEARN)
-		vxlan_snoop(skb->dev, oip->saddr, eth_hdr(skb)->h_source);
+	if (vxlan->flags & VXLAN_F_LEARN) {
+		if (oip) {
+			src_ip.sin.sin_addr.s_addr = oip->saddr;
+			src_ip.sa.sa_family = AF_INET;
+		}
+#if IS_ENABLED(CONFIG_IPV6)
+		if (oip6) {
+			src_ip.sin6.sin6_addr = oip6->saddr;
+			src_ip.sa.sa_family = AF_INET6;
+		}
+#endif
+		vxlan_snoop(skb->dev, &src_ip, eth_hdr(skb)->h_source);
+	}
 
 	__skb_tunnel_rx(skb, vxlan->dev);
 	skb_reset_network_header(skb);
@@ -733,11 +862,24 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
 
 	skb->encapsulation = 0;
 
-	err = IP_ECN_decapsulate(oip, skb);
+#if IS_ENABLED(CONFIG_IPV6)
+	if (oip6)
+		err = IP6_ECN_decapsulate(oip6, skb);
+#endif
+	if (oip)
+		err = IP_ECN_decapsulate(oip, skb);
+
 	if (unlikely(err)) {
-		if (log_ecn_error)
-			net_info_ratelimited("non-ECT from %pI4 with TOS=%#x\n",
-					     &oip->saddr, oip->tos);
+		if (log_ecn_error) {
+#if IS_ENABLED(CONFIG_IPV6)
+			if (oip6)
+				net_info_ratelimited("non-ECT from %pI6\n",
+						     &oip6->saddr);
+#endif
+			if (oip)
+				net_info_ratelimited("non-ECT from %pI4 with TOS=%#x\n",
+						     &oip->saddr, oip->tos);
+		}
 		if (err > 1) {
 			++vxlan->dev->stats.rx_frame_errors;
 			++vxlan->dev->stats.rx_errors;
@@ -772,6 +914,7 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb)
 	u8 *arpptr, *sha;
 	__be32 sip, tip;
 	struct neighbour *n;
+	union vxlan_addr ipa;
 
 	if (dev->flags & IFF_NOARP)
 		goto out;
@@ -813,7 +956,7 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb)
 		}
 
 		f = vxlan_find_mac(vxlan, n->ha);
-		if (f && f->remote.remote_ip == htonl(INADDR_ANY)) {
+		if (f && vxlan_addr_any(&f->remote.remote_ip)) {
 			/* bridge-local neighbor */
 			neigh_release(n);
 			goto out;
@@ -831,8 +974,11 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb)
 
 		if (netif_rx_ni(reply) == NET_RX_DROP)
 			dev->stats.rx_dropped++;
-	} else if (vxlan->flags & VXLAN_F_L3MISS)
-		vxlan_ip_miss(dev, tip);
+	} else if (vxlan->flags & VXLAN_F_L3MISS) {
+		ipa.sin.sin_addr.s_addr = tip;
+		ipa.sa.sa_family = AF_INET;
+		vxlan_ip_miss(dev, &ipa);
+	}
 out:
 	consume_skb(skb);
 	return NETDEV_TX_OK;
@@ -854,6 +1000,14 @@ static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb)
 			return false;
 		pip = ip_hdr(skb);
 		n = neigh_lookup(&arp_tbl, &pip->daddr, dev);
+		if (!n && vxlan->flags & VXLAN_F_L3MISS) {
+			union vxlan_addr ipa;
+			ipa.sin.sin_addr.s_addr = pip->daddr;
+			ipa.sa.sa_family = AF_INET;
+			vxlan_ip_miss(dev, &ipa);
+			return false;
+		}
+
 		break;
 	default:
 		return false;
@@ -870,8 +1024,8 @@ static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb)
 		}
 		neigh_release(n);
 		return diff;
-	} else if (vxlan->flags & VXLAN_F_L3MISS)
-		vxlan_ip_miss(dev, pip->daddr);
+	}
+
 	return false;
 }
 
@@ -930,15 +1084,26 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
 {
 	struct pcpu_tstats *tx_stats = this_cpu_ptr(src_vxlan->dev->tstats);
 	struct pcpu_tstats *rx_stats = this_cpu_ptr(dst_vxlan->dev->tstats);
+	union vxlan_addr loopback;
 
 	skb->pkt_type = PACKET_HOST;
 	skb->encapsulation = 0;
 	skb->dev = dst_vxlan->dev;
 	__skb_pull(skb, skb_network_offset(skb));
 
+	if (dst_vxlan->default_dst.remote_ip.sa.sa_family == AF_INET) {
+		loopback.sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+		loopback.sa.sa_family =  AF_INET;
+	}
+#if IS_ENABLED(CONFIG_IPV6)
+	else {
+		loopback.sin6.sin6_addr = in6addr_loopback;
+		loopback.sa.sa_family =  AF_INET6;
+	}
+#endif
+
 	if (dst_vxlan->flags & VXLAN_F_LEARN)
-		vxlan_snoop(skb->dev, htonl(INADDR_LOOPBACK),
-			    eth_hdr(skb)->h_source);
+		vxlan_snoop(skb->dev, &loopback, eth_hdr(skb)->h_source);
 
 	u64_stats_update_begin(&tx_stats->syncp);
 	tx_stats->tx_packets++;
@@ -960,12 +1125,19 @@ static netdev_tx_t vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
 {
 	struct vxlan_dev *vxlan = netdev_priv(dev);
 	struct rtable *rt;
-	const struct iphdr *old_iph;
+	const struct iphdr *old_iph = NULL;
 	struct iphdr *iph;
 	struct vxlanhdr *vxh;
 	struct udphdr *uh;
 	struct flowi4 fl4;
-	__be32 dst;
+#if IS_ENABLED(CONFIG_IPV6)
+	struct flowi6 fl6;
+	struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id);
+	struct sock *sk = vn->sock->sk;
+	struct ipv6hdr *ip6h;
+#endif
+	const union vxlan_addr *dst;
+	struct dst_entry *ndst = NULL;
 	__be16 src_port, dst_port;
         u32 vni;
 	__be16 df = 0;
@@ -973,9 +1145,9 @@ static netdev_tx_t vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
 
 	dst_port = rdst->remote_port ? rdst->remote_port : vxlan->dst_port;
 	vni = rdst->remote_vni;
-	dst = rdst->remote_ip;
+	dst = &rdst->remote_ip;
 
-	if (!dst) {
+	if (vxlan_addr_any(dst)) {
 		if (did_rsc) {
 			/* short-circuited back to local bridge */
 			vxlan_encap_bypass(skb, vxlan, vxlan);
@@ -989,60 +1161,119 @@ static netdev_tx_t vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
 		skb->encapsulation = 1;
 	}
 
-	/* Need space for new headers (invalidates iph ptr) */
-	if (skb_cow_head(skb, VXLAN_HEADROOM))
-		goto drop;
+	ttl = vxlan->ttl;
+	tos = vxlan->tos;
+	if (dst->sa.sa_family == AF_INET) {
+		/* Need space for new headers (invalidates iph ptr) */
+		if (skb_cow_head(skb, VXLAN_HEADROOM))
+			goto drop;
 
-	old_iph = ip_hdr(skb);
+		old_iph = ip_hdr(skb);
+		if (!ttl && IN_MULTICAST(ntohl(dst->sin.sin_addr.s_addr)))
+			ttl = 1;
 
-	ttl = vxlan->ttl;
-	if (!ttl && IN_MULTICAST(ntohl(dst)))
-		ttl = 1;
+		if (tos == 1)
+			tos = ip_tunnel_get_dsfield(old_iph, skb);
 
-	tos = vxlan->tos;
-	if (tos == 1)
-		tos = ip_tunnel_get_dsfield(old_iph, skb);
-
-	src_port = vxlan_src_port(vxlan, skb);
-
-	memset(&fl4, 0, sizeof(fl4));
-	fl4.flowi4_oif = rdst->remote_ifindex;
-	fl4.flowi4_tos = RT_TOS(tos);
-	fl4.daddr = dst;
-	fl4.saddr = vxlan->saddr;
-
-	rt = ip_route_output_key(dev_net(dev), &fl4);
-	if (IS_ERR(rt)) {
-		netdev_dbg(dev, "no route to %pI4\n", &dst);
-		dev->stats.tx_carrier_errors++;
-		goto tx_error;
-	}
+		src_port = vxlan_src_port(vxlan, skb);
 
-	if (rt->dst.dev == dev) {
-		netdev_dbg(dev, "circular route to %pI4\n", &dst);
-		ip_rt_put(rt);
-		dev->stats.collisions++;
-		goto tx_error;
-	}
+		memset(&fl4, 0, sizeof(fl4));
+		fl4.flowi4_oif = rdst->remote_ifindex;
+		fl4.flowi4_tos = RT_TOS(tos);
+		fl4.daddr = dst->sin.sin_addr.s_addr;
+		fl4.saddr = vxlan->saddr.sin.sin_addr.s_addr;
 
-	/* Bypass encapsulation if the destination is local */
-	if (rt->rt_flags & RTCF_LOCAL &&
-	    !(rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))) {
-		struct vxlan_dev *dst_vxlan;
+		rt = ip_route_output_key(dev_net(dev), &fl4);
+		if (IS_ERR(rt)) {
+			netdev_dbg(dev, "no route to %pI4\n",
+				   &dst->sin.sin_addr.s_addr);
+			dev->stats.tx_carrier_errors++;
+			goto tx_error;
+		}
 
-		ip_rt_put(rt);
-		dst_vxlan = vxlan_find_vni(dev_net(dev), vni);
-		if (!dst_vxlan)
+		if (rt->dst.dev == dev) {
+			netdev_dbg(dev, "circular route to %pI4\n",
+				   &dst->sin.sin_addr.s_addr);
+			ip_rt_put(rt);
+			dev->stats.collisions++;
 			goto tx_error;
-		vxlan_encap_bypass(skb, vxlan, dst_vxlan);
-		return NETDEV_TX_OK;
+		}
+
+		/* Bypass encapsulation if the destination is local */
+		if (rt->rt_flags & RTCF_LOCAL &&
+		    !(rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))) {
+			struct vxlan_dev *dst_vxlan;
+
+			ip_rt_put(rt);
+			dst_vxlan = vxlan_find_vni(dev_net(dev), vni);
+			if (!dst_vxlan)
+				goto tx_error;
+			vxlan_encap_bypass(skb, vxlan, dst_vxlan);
+			return NETDEV_TX_OK;
+		}
+
+		ndst = &rt->dst;
+	} else {
+#if IS_ENABLED(CONFIG_IPV6)
+		const struct ipv6hdr *old_iph6;
+		u32 flags;
+
+		/* Need space for new headers (invalidates ipv6h ptr) */
+		if (skb_cow_head(skb, VXLAN6_HEADROOM))
+			goto drop;
+
+		old_iph6 = ipv6_hdr(skb);
+		if (!ttl && ipv6_addr_is_multicast(&dst->sin6.sin6_addr))
+			ttl = 1;
+
+		if (tos == 1)
+			tos = ipv6_get_dsfield(old_iph6);
+
+		src_port = vxlan_src_port(vxlan, skb);
+
+		memset(&fl6, 0, sizeof(fl6));
+		fl6.flowi6_oif = rdst->remote_ifindex;
+		fl6.flowi6_tos = RT_TOS(tos);
+		fl6.daddr = dst->sin6.sin6_addr;
+		fl6.saddr = vxlan->saddr.sin6.sin6_addr;
+		fl6.flowi6_proto = skb->protocol;
+
+		if (ip6_dst_lookup(sk, &ndst, &fl6)) {
+			netdev_dbg(dev, "no route to %pI6\n",
+				   &dst->sin6.sin6_addr);
+			dev->stats.tx_carrier_errors++;
+			goto tx_error;
+		}
+
+		if (ndst->dev == dev) {
+			netdev_dbg(dev, "circular route to %pI6\n",
+				   &dst->sin6.sin6_addr);
+			dst_release(ndst);
+			dev->stats.collisions++;
+			goto tx_error;
+		}
+
+		/* Bypass encapsulation if the destination is local */
+		flags = ((struct rt6_info *)ndst)->rt6i_flags;
+		if (flags & RTF_LOCAL &&
+		    !(flags & (RTCF_BROADCAST | RTCF_MULTICAST))) {
+			struct vxlan_dev *dst_vxlan;
+
+			dst_release(ndst);
+			dst_vxlan = vxlan_find_vni(dev_net(dev), vni);
+			if (!dst_vxlan)
+				goto tx_error;
+			vxlan_encap_bypass(skb, vxlan, dst_vxlan);
+			return NETDEV_TX_OK;
+		}
+#endif
 	}
 
 	memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
 	IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED |
 			      IPSKB_REROUTED);
 	skb_dst_drop(skb);
-	skb_dst_set(skb, &rt->dst);
+	skb_dst_set(skb, ndst);
 
 	vxh = (struct vxlanhdr *) __skb_push(skb, sizeof(*vxh));
 	vxh->vx_flags = htonl(VXLAN_FLAGS);
@@ -1058,27 +1289,63 @@ static netdev_tx_t vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
 	uh->len = htons(skb->len);
 	uh->check = 0;
 
-	__skb_push(skb, sizeof(*iph));
-	skb_reset_network_header(skb);
-	iph		= ip_hdr(skb);
-	iph->version	= 4;
-	iph->ihl	= sizeof(struct iphdr) >> 2;
-	iph->frag_off	= df;
-	iph->protocol	= IPPROTO_UDP;
-	iph->tos	= ip_tunnel_ecn_encap(tos, old_iph, skb);
-	iph->daddr	= dst;
-	iph->saddr	= fl4.saddr;
-	iph->ttl	= ttl ? : ip4_dst_hoplimit(&rt->dst);
-	tunnel_ip_select_ident(skb, old_iph, &rt->dst);
-
-	nf_reset(skb);
+	if (dst->sa.sa_family == AF_INET) {
+		__skb_push(skb, sizeof(*iph));
+		skb_reset_network_header(skb);
+		iph		= ip_hdr(skb);
+		iph->version	= 4;
+		iph->ihl	= sizeof(struct iphdr) >> 2;
+		iph->frag_off	= df;
+		iph->protocol	= IPPROTO_UDP;
+		iph->tos	= ip_tunnel_ecn_encap(tos, old_iph, skb);
+		iph->daddr	= dst->sin.sin_addr.s_addr;
+		iph->saddr	= fl4.saddr;
+		iph->ttl	= ttl ? : ip4_dst_hoplimit(ndst);
+		tunnel_ip_select_ident(skb, old_iph, ndst);
+	} else {
+#if IS_ENABLED(CONFIG_IPV6)
+		if (!skb_is_gso(skb) && !(ndst->dev->features & NETIF_F_IPV6_CSUM)) {
+			__wsum csum = skb_checksum(skb, 0, skb->len, 0);
+			skb->ip_summed = CHECKSUM_UNNECESSARY;
+			uh->check = csum_ipv6_magic(&fl6.saddr, &fl6.daddr, skb->len,
+						    IPPROTO_UDP, csum);
+			if (uh->check == 0)
+				uh->check = CSUM_MANGLED_0;
+		} else {
+			skb->ip_summed = CHECKSUM_PARTIAL;
+			skb->csum_start = skb_transport_header(skb) - skb->head;
+			skb->csum_offset = offsetof(struct udphdr, check);
+			uh->check = ~csum_ipv6_magic(&fl6.saddr, &fl6.daddr,
+						     skb->len, IPPROTO_UDP, 0);
+		}
+
+		__skb_push(skb, sizeof(*ip6h));
+		skb_reset_network_header(skb);
+		ip6h		  = ipv6_hdr(skb);
+		ip6h->version	  = 6;
+		ip6h->priority	  = 0;
+		ip6h->flow_lbl[0] = 0;
+		ip6h->flow_lbl[1] = 0;
+		ip6h->flow_lbl[2] = 0;
+		ip6h->payload_len = htons(skb->len);
+		ip6h->nexthdr     = IPPROTO_UDP;
+		ip6h->hop_limit   = ttl ? : ip6_dst_hoplimit(ndst);
+		ip6h->daddr	  = fl6.daddr;
+		ip6h->saddr	  = fl6.saddr;
+#endif
+	}
 
 	vxlan_set_owner(dev, skb);
 
 	if (handle_offloads(skb))
 		goto drop;
 
-	iptunnel_xmit(skb, dev);
+#if IS_ENABLED(CONFIG_IPV6)
+	if (dst->sa.sa_family == AF_INET6)
+		ip6tunnel_xmit(skb, dev);
+	else
+#endif
+		iptunnel_xmit(skb, dev);
 	return NETDEV_TX_OK;
 
 drop:
@@ -1126,7 +1393,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
 	if (f == NULL) {
 		rdst0 = &vxlan->default_dst;
 
-		if (rdst0->remote_ip == htonl(INADDR_ANY) &&
+		if (vxlan_addr_any(&rdst0->remote_ip) &&
 		    (vxlan->flags & VXLAN_F_L2MISS) &&
 		    !is_multicast_ether_addr(eth->h_dest))
 			vxlan_fdb_miss(vxlan, eth->h_dest);
@@ -1204,7 +1471,7 @@ static int vxlan_open(struct net_device *dev)
 	struct vxlan_dev *vxlan = netdev_priv(dev);
 	int err;
 
-	if (IN_MULTICAST(ntohl(vxlan->default_dst.remote_ip))) {
+	if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip)) {
 		err = vxlan_join_group(dev);
 		if (err)
 			return err;
@@ -1238,7 +1505,7 @@ static int vxlan_stop(struct net_device *dev)
 {
 	struct vxlan_dev *vxlan = netdev_priv(dev);
 
-	if (IN_MULTICAST(ntohl(vxlan->default_dst.remote_ip)))
+	if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip))
 		vxlan_leave_group(dev);
 
 	del_timer_sync(&vxlan->age_timer);
@@ -1288,7 +1555,12 @@ static void vxlan_setup(struct net_device *dev)
 
 	eth_hw_addr_random(dev);
 	ether_setup(dev);
-	dev->hard_header_len = ETH_HLEN + VXLAN_HEADROOM;
+#if IS_ENABLED(CONFIG_IPV6)
+	if (vxlan->default_dst.remote_ip.sa.sa_family == AF_INET6)
+		dev->hard_header_len = ETH_HLEN + VXLAN6_HEADROOM;
+	else
+#endif
+		dev->hard_header_len = ETH_HLEN + VXLAN_HEADROOM;
 
 	dev->netdev_ops = &vxlan_netdev_ops;
 	dev->destructor = vxlan_free;
@@ -1326,8 +1598,10 @@ static void vxlan_setup(struct net_device *dev)
 static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = {
 	[IFLA_VXLAN_ID]		= { .type = NLA_U32 },
 	[IFLA_VXLAN_GROUP]	= { .len = FIELD_SIZEOF(struct iphdr, daddr) },
+	[IFLA_VXLAN_GROUP6]	= { .len = sizeof(struct in6_addr) },
 	[IFLA_VXLAN_LINK]	= { .type = NLA_U32 },
 	[IFLA_VXLAN_LOCAL]	= { .len = FIELD_SIZEOF(struct iphdr, saddr) },
+	[IFLA_VXLAN_LOCAL6]	= { .len = sizeof(struct in6_addr) },
 	[IFLA_VXLAN_TOS]	= { .type = NLA_U8 },
 	[IFLA_VXLAN_TTL]	= { .type = NLA_U8 },
 	[IFLA_VXLAN_LEARNING]	= { .type = NLA_U8 },
@@ -1408,11 +1682,35 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
 	}
 	dst->remote_vni = vni;
 
-	if (data[IFLA_VXLAN_GROUP])
-		dst->remote_ip = nla_get_be32(data[IFLA_VXLAN_GROUP]);
+	if (data[IFLA_VXLAN_GROUP]) {
+		dst->remote_ip.sin.sin_addr.s_addr = nla_get_be32(data[IFLA_VXLAN_GROUP]);
+		dst->remote_ip.sa.sa_family = AF_INET;
+	} else if (data[IFLA_VXLAN_GROUP6]) {
+#if IS_ENABLED(CONFIG_IPV6)
+		if (ipv6_disabled)
+			return -EPFNOSUPPORT;
+		nla_memcpy(&dst->remote_ip.sin6.sin6_addr, data[IFLA_VXLAN_GROUP6],
+			   sizeof(struct in6_addr));
+		dst->remote_ip.sa.sa_family = AF_INET6;
+#else
+		return -EPFNOSUPPORT;
+#endif
+	}
 
-	if (data[IFLA_VXLAN_LOCAL])
-		vxlan->saddr = nla_get_be32(data[IFLA_VXLAN_LOCAL]);
+	if (data[IFLA_VXLAN_LOCAL]) {
+		vxlan->saddr.sin.sin_addr.s_addr = nla_get_be32(data[IFLA_VXLAN_LOCAL]);
+		vxlan->saddr.sa.sa_family = AF_INET;
+	} else if (data[IFLA_VXLAN_LOCAL6]) {
+#if IS_ENABLED(CONFIG_IPV6)
+		if (ipv6_disabled)
+			return -EPFNOSUPPORT;
+		nla_memcpy(&vxlan->saddr.sin6.sin6_addr, data[IFLA_VXLAN_LOCAL6],
+			   sizeof(struct in6_addr));
+		vxlan->saddr.sa.sa_family = AF_INET6;
+#else
+		return -EPFNOSUPPORT;
+#endif
+	}
 
 	if (data[IFLA_VXLAN_LINK] &&
 	    (dst->remote_ifindex = nla_get_u32(data[IFLA_VXLAN_LINK]))) {
@@ -1493,9 +1791,9 @@ static size_t vxlan_get_size(const struct net_device *dev)
 {
 
 	return nla_total_size(sizeof(__u32)) +	/* IFLA_VXLAN_ID */
-		nla_total_size(sizeof(__be32)) +/* IFLA_VXLAN_GROUP */
+		nla_total_size(sizeof(struct in6_addr)) + /* IFLA_VXLAN_GROUP{6} */
 		nla_total_size(sizeof(__u32)) +	/* IFLA_VXLAN_LINK */
-		nla_total_size(sizeof(__be32))+	/* IFLA_VXLAN_LOCAL */
+		nla_total_size(sizeof(struct in6_addr)) + /* IFLA_VXLAN_LOCAL{6} */
 		nla_total_size(sizeof(__u8)) +	/* IFLA_VXLAN_TTL */
 		nla_total_size(sizeof(__u8)) +	/* IFLA_VXLAN_TOS */
 		nla_total_size(sizeof(__u8)) +	/* IFLA_VXLAN_LEARNING */
@@ -1522,14 +1820,34 @@ static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev)
 	if (nla_put_u32(skb, IFLA_VXLAN_ID, dst->remote_vni))
 		goto nla_put_failure;
 
-	if (dst->remote_ip && nla_put_be32(skb, IFLA_VXLAN_GROUP, dst->remote_ip))
-		goto nla_put_failure;
+	if (!vxlan_addr_any(&dst->remote_ip)) {
+		if (dst->remote_ip.sa.sa_family == AF_INET) {
+			if (nla_put_be32(skb, IFLA_VXLAN_GROUP, dst->remote_ip.sin.sin_addr.s_addr))
+				goto nla_put_failure;
+		} else {
+#if IS_ENABLED(CONFIG_IPV6)
+			if (nla_put(skb, IFLA_VXLAN_GROUP6, sizeof(struct in6_addr),
+				    &dst->remote_ip.sin6.sin6_addr))
+				goto nla_put_failure;
+#endif
+		}
+	}
 
 	if (dst->remote_ifindex && nla_put_u32(skb, IFLA_VXLAN_LINK, dst->remote_ifindex))
 		goto nla_put_failure;
 
-	if (vxlan->saddr && nla_put_be32(skb, IFLA_VXLAN_LOCAL, vxlan->saddr))
-		goto nla_put_failure;
+	if (!vxlan_addr_any(&vxlan->saddr)) {
+		if (vxlan->saddr.sa.sa_family == AF_INET) {
+			if (nla_put_be32(skb, IFLA_VXLAN_LOCAL, vxlan->saddr.sin.sin_addr.s_addr))
+				goto nla_put_failure;
+		} else {
+#if IS_ENABLED(CONFIG_IPV6)
+			if (nla_put(skb, IFLA_VXLAN_LOCAL6, sizeof(struct in6_addr),
+				    &vxlan->saddr.sin6.sin6_addr))
+				goto nla_put_failure;
+#endif
+		}
+	}
 
 	if (nla_put_u8(skb, IFLA_VXLAN_TTL, vxlan->ttl) ||
 	    nla_put_u8(skb, IFLA_VXLAN_TOS, vxlan->tos) ||
@@ -1569,39 +1887,94 @@ static struct rtnl_link_ops vxlan_link_ops __read_mostly = {
 	.fill_info	= vxlan_fill_info,
 };
 
-static __net_init int vxlan_init_net(struct net *net)
+static __net_init int create_v4_sock(struct net *net, struct sock **sk)
 {
 	struct vxlan_net *vn = net_generic(net, vxlan_net_id);
-	struct sock *sk;
 	struct sockaddr_in vxlan_addr = {
 		.sin_family = AF_INET,
+		.sin_port = htons(vxlan_port),
 		.sin_addr.s_addr = htonl(INADDR_ANY),
 	};
 	int rc;
-	unsigned h;
 
-	/* Create UDP socket for encapsulation receive. */
 	rc = sock_create_kern(AF_INET, SOCK_DGRAM, IPPROTO_UDP, &vn->sock);
 	if (rc < 0) {
 		pr_debug("UDP socket create failed\n");
 		return rc;
 	}
 	/* Put in proper namespace */
-	sk = vn->sock->sk;
-	sk_change_net(sk, net);
+	*sk = vn->sock->sk;
+	sk_change_net(*sk, net);
 
-	vxlan_addr.sin_port = htons(vxlan_port);
-
-	rc = kernel_bind(vn->sock, (struct sockaddr *) &vxlan_addr,
-			 sizeof(vxlan_addr));
+	rc = kernel_bind(vn->sock, (struct sockaddr *)&vxlan_addr,
+			 sizeof(struct sockaddr_in));
 	if (rc < 0) {
 		pr_debug("bind for UDP socket %pI4:%u (%d)\n",
 			 &vxlan_addr.sin_addr, ntohs(vxlan_addr.sin_port), rc);
-		sk_release_kernel(sk);
+		sk_release_kernel(*sk);
+		vn->sock = NULL;
+		return rc;
+	}
+	return 0;
+}
+
+/* Create UDP socket for encapsulation receive. AF_INET6 socket
+ * could be used for both IPv4 and IPv6 communications.
+ */
+#if IS_ENABLED(CONFIG_IPV6)
+static __net_init int create_sock(struct net *net, struct sock **sk)
+{
+	struct vxlan_net *vn = net_generic(net, vxlan_net_id);
+	struct sockaddr_in6 vxlan_addr = {
+		.sin6_family = AF_INET6,
+		.sin6_port = htons(vxlan_port),
+	};
+	int rc;
+
+	rc = sock_create_kern(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, &vn->sock);
+	if (rc < 0) {
+		pr_debug("UDP IPv6 socket create failed\n");
+		ipv6_disabled = true;
+		return create_v4_sock(net, sk);
+	}
+	/* Put in proper namespace */
+	*sk = vn->sock->sk;
+	sk_change_net(*sk, net);
+
+	rc = kernel_bind(vn->sock, (struct sockaddr *)&vxlan_addr,
+			 sizeof(struct sockaddr_in6));
+	if (rc < 0) {
+		pr_debug("bind for UDP socket %pI6:%u (%d)\n",
+			 &vxlan_addr.sin6_addr, ntohs(vxlan_addr.sin6_port), rc);
+		sk_release_kernel(*sk);
 		vn->sock = NULL;
 		return rc;
 	}
 
+	/* At this point, IPv6 module should have been loaded in
+	 * sock_create_kern().
+	 */
+	BUG_ON(!ipv6_mcast_ops);
+	return 0;
+}
+#else
+static __net_init int create_sock(struct net *net, struct sock **sk)
+{
+	return create_v4_sock(net, sk);
+}
+#endif
+
+static __net_init int vxlan_init_net(struct net *net)
+{
+	struct vxlan_net *vn = net_generic(net, vxlan_net_id);
+	struct sock *sk;
+	int rc;
+	unsigned h;
+
+	rc = create_sock(net, &sk);
+	if (rc < 0)
+		return rc;
+
 	/* Disable multicast loopback */
 	inet_sk(sk)->mc_loop = 0;
 
@@ -1609,6 +1982,9 @@ static __net_init int vxlan_init_net(struct net *net)
 	udp_sk(sk)->encap_type = 1;
 	udp_sk(sk)->encap_rcv = vxlan_udp_encap_recv;
 	udp_encap_enable();
+#if IS_ENABLED(CONFIG_IPV6)
+	udpv6_encap_enable();
+#endif
 
 	for (h = 0; h < VNI_HASH_SIZE; ++h)
 		INIT_HLIST_HEAD(&vn->vni_list[h]);
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index b05823c..f7bed18 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -311,6 +311,8 @@ enum {
 	IFLA_VXLAN_L2MISS,
 	IFLA_VXLAN_L3MISS,
 	IFLA_VXLAN_PORT,	/* destination port */
+	IFLA_VXLAN_GROUP6,
+	IFLA_VXLAN_LOCAL6,
 	__IFLA_VXLAN_MAX
 };
 #define IFLA_VXLAN_MAX	(__IFLA_VXLAN_MAX - 1)
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Patch net-next v7 5/6] vxlan: respect disable_ipv6 sysctl
  2013-04-30  8:43 [Patch net-next v7 0/6] vxlan: add ipv6 support Cong Wang
                   ` (3 preceding siblings ...)
  2013-04-30  8:43 ` [Patch net-next v7 4/6] vxlan: add ipv6 support Cong Wang
@ 2013-04-30  8:43 ` Cong Wang
  2013-04-30 12:27   ` Sergei Shtylyov
  2013-04-30  8:43 ` [Patch net-next v7 6/6] ipv6: Add generic UDP Tunnel segmentation Cong Wang
  2013-04-30 19:00 ` [Patch net-next v7 0/6] vxlan: add ipv6 support David Miller
  6 siblings, 1 reply; 23+ messages in thread
From: Cong Wang @ 2013-04-30  8:43 UTC (permalink / raw)
  To: netdev; +Cc: David Miller, Cong Wang

From: Cong Wang <amwang@redhat.com>

When disable_ipv6 is set, we should not allow IPv6 vxlan
device to be created on top of it.

Cc: David Miller <davem@davemloft.net>
Signed-off-by: Cong Wang <amwang@redhat.com>
---
 drivers/net/vxlan.c |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index bb39e67..ec1007a 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -1671,6 +1671,7 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
 	struct vxlan_rdst *dst = &vxlan->default_dst;
 	__u32 vni;
 	int err;
+	bool use_ipv6 = false;
 
 	if (!data[IFLA_VXLAN_ID])
 		return -EINVAL;
@@ -1692,6 +1693,7 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
 		nla_memcpy(&dst->remote_ip.sin6.sin6_addr, data[IFLA_VXLAN_GROUP6],
 			   sizeof(struct in6_addr));
 		dst->remote_ip.sa.sa_family = AF_INET6;
+		use_ipv6 = true;
 #else
 		return -EPFNOSUPPORT;
 #endif
@@ -1707,6 +1709,7 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
 		nla_memcpy(&vxlan->saddr.sin6.sin6_addr, data[IFLA_VXLAN_LOCAL6],
 			   sizeof(struct in6_addr));
 		vxlan->saddr.sa.sa_family = AF_INET6;
+		use_ipv6 = true;
 #else
 		return -EPFNOSUPPORT;
 #endif
@@ -1722,6 +1725,15 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
 			return -ENODEV;
 		}
 
+#if IS_ENABLED(CONFIG_IPV6)
+		if (use_ipv6) {
+			struct inet6_dev *idev = in6_dev_get(lowerdev);
+			if (idev && idev->cnf.disable_ipv6)
+					return -EPERM;
+		}
+#else
+		BUG_ON(use_ipv6);
+#endif
 		if (!tb[IFLA_MTU])
 			dev->mtu = lowerdev->mtu - VXLAN_HEADROOM;
 
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [Patch net-next v7 6/6] ipv6: Add generic UDP Tunnel segmentation
  2013-04-30  8:43 [Patch net-next v7 0/6] vxlan: add ipv6 support Cong Wang
                   ` (4 preceding siblings ...)
  2013-04-30  8:43 ` [Patch net-next v7 5/6] vxlan: respect disable_ipv6 sysctl Cong Wang
@ 2013-04-30  8:43 ` Cong Wang
  2013-04-30 19:00 ` [Patch net-next v7 0/6] vxlan: add ipv6 support David Miller
  6 siblings, 0 replies; 23+ messages in thread
From: Cong Wang @ 2013-04-30  8:43 UTC (permalink / raw)
  To: netdev
  Cc: Jesse Gross, Pravin B Shelar, Stephen Hemminger, David S. Miller,
	Cong Wang

From: Cong Wang <amwang@redhat.com>

Similar to commit 731362674580cb0c696cd1b1a03d8461a10cf90a
(tunneling: Add generic Tunnel segmentation)

This patch adds generic tunneling offloading support for IPv6-UDP
based tunnels.

This can be used by tunneling protocols like VXLAN.

Cc: Jesse Gross <jesse@nicira.com>
Cc: Pravin B Shelar <pshelar@nicira.com>
Cc: Stephen Hemminger <stephen@networkplumber.org>
Cc: David S. Miller <davem@davemloft.net>
Signed-off-by: Cong Wang <amwang@redhat.com>
---
 net/ipv6/ip6_offload.c |    4 +-
 net/ipv6/udp_offload.c |  153 +++++++++++++++++++++++++++++++++---------------
 2 files changed, 108 insertions(+), 49 deletions(-)

diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
index 71b766e..87fbf2e 100644
--- a/net/ipv6/ip6_offload.c
+++ b/net/ipv6/ip6_offload.c
@@ -91,6 +91,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
 	unsigned int unfrag_ip6hlen;
 	u8 *prevhdr;
 	int offset = 0;
+	bool tunnel;
 
 	if (unlikely(skb_shinfo(skb)->gso_type &
 		     ~(SKB_GSO_UDP |
@@ -105,6 +106,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
 	if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h))))
 		goto out;
 
+	tunnel = skb->encapsulation;
 	ipv6h = ipv6_hdr(skb);
 	__skb_pull(skb, sizeof(*ipv6h));
 	segs = ERR_PTR(-EPROTONOSUPPORT);
@@ -125,7 +127,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
 		ipv6h = ipv6_hdr(skb);
 		ipv6h->payload_len = htons(skb->len - skb->mac_len -
 					   sizeof(*ipv6h));
-		if (proto == IPPROTO_UDP) {
+		if (!tunnel && proto == IPPROTO_UDP) {
 			unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr);
 			fptr = (struct frag_hdr *)(skb_network_header(skb) +
 				unfrag_ip6hlen);
diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c
index 3bb3a89..2c3fa3b 100644
--- a/net/ipv6/udp_offload.c
+++ b/net/ipv6/udp_offload.c
@@ -21,26 +21,79 @@ static int udp6_ufo_send_check(struct sk_buff *skb)
 	const struct ipv6hdr *ipv6h;
 	struct udphdr *uh;
 
-	/* UDP Tunnel offload on ipv6 is not yet supported. */
-	if (skb->encapsulation)
-		return -EINVAL;
-
 	if (!pskb_may_pull(skb, sizeof(*uh)))
 		return -EINVAL;
 
-	ipv6h = ipv6_hdr(skb);
-	uh = udp_hdr(skb);
+	if (likely(!skb->encapsulation)) {
+		ipv6h = ipv6_hdr(skb);
+		uh = udp_hdr(skb);
+
+		uh->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, skb->len,
+					     IPPROTO_UDP, 0);
+		skb->csum_start = skb_transport_header(skb) - skb->head;
+		skb->csum_offset = offsetof(struct udphdr, check);
+		skb->ip_summed = CHECKSUM_PARTIAL;
+	}
 
-	uh->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, skb->len,
-				     IPPROTO_UDP, 0);
-	skb->csum_start = skb_transport_header(skb) - skb->head;
-	skb->csum_offset = offsetof(struct udphdr, check);
-	skb->ip_summed = CHECKSUM_PARTIAL;
 	return 0;
 }
 
+static struct sk_buff *skb_udp6_tunnel_segment(struct sk_buff *skb,
+					       netdev_features_t features)
+{
+	struct sk_buff *segs = ERR_PTR(-EINVAL);
+	int mac_len = skb->mac_len;
+	int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb);
+	int outer_hlen;
+	netdev_features_t enc_features;
+
+	if (unlikely(!pskb_may_pull(skb, tnl_hlen)))
+		goto out;
+
+	skb->encapsulation = 0;
+	__skb_pull(skb, tnl_hlen);
+	skb_reset_mac_header(skb);
+	skb_set_network_header(skb, skb_inner_network_offset(skb));
+	skb->mac_len = skb_inner_network_offset(skb);
+
+	/* segment inner packet. */
+	enc_features = skb->dev->hw_enc_features & netif_skb_features(skb);
+	segs = skb_mac_gso_segment(skb, enc_features);
+	if (!segs || IS_ERR(segs))
+		goto out;
+
+	outer_hlen = skb_tnl_header_len(skb);
+	skb = segs;
+	do {
+		struct udphdr *uh;
+		struct ipv6hdr *ipv6h;
+		int udp_offset = outer_hlen - tnl_hlen;
+		u32 len;
+
+		skb->mac_len = mac_len;
+
+		skb_push(skb, outer_hlen);
+		skb_reset_mac_header(skb);
+		skb_set_network_header(skb, mac_len);
+		skb_set_transport_header(skb, udp_offset);
+		uh = udp_hdr(skb);
+		uh->len = htons(skb->len - udp_offset);
+		ipv6h = ipv6_hdr(skb);
+		len = skb->len - udp_offset;
+
+		uh->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr,
+					     len, IPPROTO_UDP, 0);
+		uh->check = csum_fold(skb_checksum(skb, udp_offset, len, 0));
+		if (uh->check == 0)
+			uh->check = CSUM_MANGLED_0;
+		skb->ip_summed = CHECKSUM_NONE;
+	} while ((skb = skb->next));
+out:
+	return segs;
+}
+
 static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
-	netdev_features_t features)
+					 netdev_features_t features)
 {
 	struct sk_buff *segs = ERR_PTR(-EINVAL);
 	unsigned int mss;
@@ -73,43 +126,47 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
 		goto out;
 	}
 
-	/* Do software UFO. Complete and fill in the UDP checksum as HW cannot
-	 * do checksum of UDP packets sent as multiple IP fragments.
-	 */
-	offset = skb_checksum_start_offset(skb);
-	csum = skb_checksum(skb, offset, skb->len - offset, 0);
-	offset += skb->csum_offset;
-	*(__sum16 *)(skb->data + offset) = csum_fold(csum);
-	skb->ip_summed = CHECKSUM_NONE;
-
-	/* Check if there is enough headroom to insert fragment header. */
-	if ((skb_mac_header(skb) < skb->head + frag_hdr_sz) &&
-	    pskb_expand_head(skb, frag_hdr_sz, 0, GFP_ATOMIC))
-		goto out;
+	if (skb->encapsulation && skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL)
+		segs = skb_udp6_tunnel_segment(skb, features);
+	else {
+		/* Do software UFO. Complete and fill in the UDP checksum as HW cannot
+		 * do checksum of UDP packets sent as multiple IP fragments.
+		 */
+		offset = skb_checksum_start_offset(skb);
+		csum = skb_checksum(skb, offset, skb->len - offset, 0);
+		offset += skb->csum_offset;
+		*(__sum16 *)(skb->data + offset) = csum_fold(csum);
+		skb->ip_summed = CHECKSUM_NONE;
+
+		/* Check if there is enough headroom to insert fragment header. */
+		if ((skb_mac_header(skb) < skb->head + frag_hdr_sz) &&
+		    pskb_expand_head(skb, frag_hdr_sz, 0, GFP_ATOMIC))
+			goto out;
 
-	/* Find the unfragmentable header and shift it left by frag_hdr_sz
-	 * bytes to insert fragment header.
-	 */
-	unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr);
-	nexthdr = *prevhdr;
-	*prevhdr = NEXTHDR_FRAGMENT;
-	unfrag_len = skb_network_header(skb) - skb_mac_header(skb) +
-		     unfrag_ip6hlen;
-	mac_start = skb_mac_header(skb);
-	memmove(mac_start-frag_hdr_sz, mac_start, unfrag_len);
-
-	skb->mac_header -= frag_hdr_sz;
-	skb->network_header -= frag_hdr_sz;
-
-	fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen);
-	fptr->nexthdr = nexthdr;
-	fptr->reserved = 0;
-	ipv6_select_ident(fptr, (struct rt6_info *)skb_dst(skb));
-
-	/* Fragment the skb. ipv6 header and the remaining fields of the
-	 * fragment header are updated in ipv6_gso_segment()
-	 */
-	segs = skb_segment(skb, features);
+		/* Find the unfragmentable header and shift it left by frag_hdr_sz
+		 * bytes to insert fragment header.
+		 */
+		unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr);
+		nexthdr = *prevhdr;
+		*prevhdr = NEXTHDR_FRAGMENT;
+		unfrag_len = skb_network_header(skb) - skb_mac_header(skb) +
+			     unfrag_ip6hlen;
+		mac_start = skb_mac_header(skb);
+		memmove(mac_start-frag_hdr_sz, mac_start, unfrag_len);
+
+		skb->mac_header -= frag_hdr_sz;
+		skb->network_header -= frag_hdr_sz;
+
+		fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen);
+		fptr->nexthdr = nexthdr;
+		fptr->reserved = 0;
+		ipv6_select_ident(fptr, (struct rt6_info *)skb_dst(skb));
+
+		/* Fragment the skb. ipv6 header and the remaining fields of the
+		 * fragment header are updated in ipv6_gso_segment()
+		 */
+		segs = skb_segment(skb, features);
+	}
 
 out:
 	return segs;
-- 
1.7.7.6

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [Patch net-next v7 4/6] vxlan: add ipv6 support
  2013-04-30  8:43 ` [Patch net-next v7 4/6] vxlan: add ipv6 support Cong Wang
@ 2013-04-30  9:17   ` Bjørn Mork
  2013-04-30  9:25     ` Cong Wang
                       ` (2 more replies)
  0 siblings, 3 replies; 23+ messages in thread
From: Bjørn Mork @ 2013-04-30  9:17 UTC (permalink / raw)
  To: Cong Wang; +Cc: netdev, David Stevens, Stephen Hemminger, David S. Miller

Cong Wang <amwang@redhat.com> writes:

> +/* Create UDP socket for encapsulation receive. AF_INET6 socket
> + * could be used for both IPv4 and IPv6 communications.
> + */

This is not necessarily true as mentioned by David Stevens, and acked by
you here: http://www.spinics.net/lists/netdev/msg234151.html

Please take your time to clean up your todo-list and *test* the result
with different runtime and buildtime settings. There is no need to rush
this, and people may get tired of looking at the same shortcomings over
and over again.



Bjørn

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Patch net-next v7 4/6] vxlan: add ipv6 support
  2013-04-30  9:17   ` Bjørn Mork
@ 2013-04-30  9:25     ` Cong Wang
  2013-04-30 10:33       ` Bjørn Mork
  2013-04-30 19:05       ` David Miller
  2013-04-30  9:38     ` Cong Wang
  2013-04-30 19:04     ` David Miller
  2 siblings, 2 replies; 23+ messages in thread
From: Cong Wang @ 2013-04-30  9:25 UTC (permalink / raw)
  To: Bjørn Mork; +Cc: netdev, David Stevens, Stephen Hemminger, David S. Miller

On Tue, 2013-04-30 at 11:17 +0200, Bjørn Mork wrote:
> Please take your time to clean up your todo-list and *test* the result
> with different runtime and buildtime settings. There is no need to rush
> this, and people may get tired of looking at the same shortcomings over
> and over again.
> 

So, why do you expect it is perfect?

It is extremely normal that a new feature is not perfect initially, and
takes more time to make it perfect. If you need a real example, netlink
mmap is exactly one, the initial version merged into net-next even
doesn't compile for some case.

And, why do you want to rely on me to fix them all?

I am *not* at all an expert on IPv6. If this patchset could be merged
early, many other IPv6 expert can help me to fix the rest issues.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Patch net-next v7 4/6] vxlan: add ipv6 support
  2013-04-30  9:17   ` Bjørn Mork
  2013-04-30  9:25     ` Cong Wang
@ 2013-04-30  9:38     ` Cong Wang
  2013-04-30 18:58       ` David Miller
  2013-04-30 19:04     ` David Miller
  2 siblings, 1 reply; 23+ messages in thread
From: Cong Wang @ 2013-04-30  9:38 UTC (permalink / raw)
  To: Bjørn Mork; +Cc: netdev, David Stevens, Stephen Hemminger, David S. Miller

On Tue, 2013-04-30 at 11:17 +0200, Bjørn Mork wrote:
> There is no need to rush
> this, and people may get tired of looking at the same shortcomings
> over
> and over again. 

The sooner it gets merged, the less maintaining pains I have. I have to
solve many conflicts _every time_ I rebase it on to the latest net-next.

What's more, I _do_ have some specific reason to push it soon. Please
don't judge it by your own standard, you are not the one who is being
pushed.

At last, you can just read the changelog in the cover letter, don't have
to look at them over and over again at all.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Patch net-next v7 4/6] vxlan: add ipv6 support
  2013-04-30  9:25     ` Cong Wang
@ 2013-04-30 10:33       ` Bjørn Mork
  2013-04-30 19:06         ` David Miller
  2013-05-02  8:05         ` Cong Wang
  2013-04-30 19:05       ` David Miller
  1 sibling, 2 replies; 23+ messages in thread
From: Bjørn Mork @ 2013-04-30 10:33 UTC (permalink / raw)
  To: Cong Wang; +Cc: netdev, David Stevens, Stephen Hemminger, David S. Miller

Cong Wang <amwang@redhat.com> writes:
> On Tue, 2013-04-30 at 11:17 +0200, Bjørn Mork wrote:
>> Please take your time to clean up your todo-list and *test* the result
>> with different runtime and buildtime settings. There is no need to rush
>> this, and people may get tired of looking at the same shortcomings over
>> and over again.
>> 
>
> So, why do you expect it is perfect?

No, I do not expect anything to be perfect.  But I do expect that you,
when adding IPv6 support, don't *knowingly* break existing IPv4
installations.

> It is extremely normal that a new feature is not perfect initially, and
> takes more time to make it perfect. If you need a real example, netlink
> mmap is exactly one, the initial version merged into net-next even
> doesn't compile for some case.
>
> And, why do you want to rely on me to fix them all?
>
> I am *not* at all an expert on IPv6. If this patchset could be merged
> early, many other IPv6 expert can help me to fix the rest issues.

Well, you have been told that your proposed new feature breaks IPv4
support with specific settings.  I do not think that you are speeding up
anything here by ignoring that fact.  On the contrary.

And net-next was already closed for new features when you sent the last
version, so I really, really do not understand why you are in such a
hurry.  Sorry.

Note that I'm neither an expert or anything else here.  This is just my
personal view. Feel free to ignore it, but please think about it for a
second or two first.



Bjørn

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Patch net-next v7 5/6] vxlan: respect disable_ipv6 sysctl
  2013-04-30  8:43 ` [Patch net-next v7 5/6] vxlan: respect disable_ipv6 sysctl Cong Wang
@ 2013-04-30 12:27   ` Sergei Shtylyov
  0 siblings, 0 replies; 23+ messages in thread
From: Sergei Shtylyov @ 2013-04-30 12:27 UTC (permalink / raw)
  To: Cong Wang; +Cc: netdev, David Miller

Hello.

On 30-04-2013 12:43, Cong Wang wrote:

> From: Cong Wang <amwang@redhat.com>

> When disable_ipv6 is set, we should not allow IPv6 vxlan
> device to be created on top of it.

> Cc: David Miller <davem@davemloft.net>
> Signed-off-by: Cong Wang <amwang@redhat.com>
> ---
>   drivers/net/vxlan.c |   12 ++++++++++++
>   1 files changed, 12 insertions(+), 0 deletions(-)

> diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
> index bb39e67..ec1007a 100644
> --- a/drivers/net/vxlan.c
> +++ b/drivers/net/vxlan.c
[...]
> @@ -1722,6 +1725,15 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
>   			return -ENODEV;
>   		}
>
> +#if IS_ENABLED(CONFIG_IPV6)
> +		if (use_ipv6) {
> +			struct inet6_dev *idev = in6_dev_get(lowerdev);

    Empty line wouldn't hurt here, after declaration.

> +			if (idev && idev->cnf.disable_ipv6)
> +					return -EPERM;
> +		}
> +#else
> +		BUG_ON(use_ipv6);
> +#endif

WBR, Sergei

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Patch net-next v7 4/6] vxlan: add ipv6 support
  2013-04-30  9:38     ` Cong Wang
@ 2013-04-30 18:58       ` David Miller
  0 siblings, 0 replies; 23+ messages in thread
From: David Miller @ 2013-04-30 18:58 UTC (permalink / raw)
  To: amwang; +Cc: bjorn, netdev, dlstevens, stephen

From: Cong Wang <amwang@redhat.com>
Date: Tue, 30 Apr 2013 17:38:14 +0800

> On Tue, 2013-04-30 at 11:17 +0200, Bjørn Mork wrote:
>> There is no need to rush
>> this, and people may get tired of looking at the same shortcomings
>> over
>> and over again. 
> 
> The sooner it gets merged, the less maintaining pains I have. I have to
> solve many conflicts _every time_ I rebase it on to the latest net-next.

You can't force a feature to be ready, when it isn't.  And your
complaints about merge conflicts are falling on deaf ears.

If you're frustrated, it's entirely a self inflicted wound.  And I
absolutely will not stop the people doing work that is ready just
because you have this patch series which conflicts, but isn't ready.

You have to understand that if this patch series didn't have so many
shortcomings every single submission, it would have been merged weeks
ago.

But that's not what happened, and therefore you're going to miss this
merge window, and you're going to have to be at peace with that.

net-next is closed, I said it's closed, and I even was nicer than
usual by merging in stuff that came in on the last day.

You have no basis upon which to justify merging vxlan ipv6 support in
this merge window, none.

So the earliest you'll be able to resubmit this feature is about two
weeks from now when I re-open net-next.  That gives you plenty of time
to correct all of the bugs and semantic problems, rather than trying
to "rush" it into my tree.  Rush is synonymous with buggy and not well
cared for, two things I'd like to avoid.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Patch net-next v7 0/6] vxlan: add ipv6 support
  2013-04-30  8:43 [Patch net-next v7 0/6] vxlan: add ipv6 support Cong Wang
                   ` (5 preceding siblings ...)
  2013-04-30  8:43 ` [Patch net-next v7 6/6] ipv6: Add generic UDP Tunnel segmentation Cong Wang
@ 2013-04-30 19:00 ` David Miller
  2013-05-02  7:02   ` Cong Wang
  6 siblings, 1 reply; 23+ messages in thread
From: David Miller @ 2013-04-30 19:00 UTC (permalink / raw)
  To: amwang; +Cc: netdev


Please read:

	http://marc.info/?l=linux-netdev&m=136730964130303&w=2

It is a very bad idea to ignore my announcements about what is, and
what is not, appropriate to submit at a given time.

Your changes weren't ready in time for the merge window, please do
not try and force the matter, you'll only make me angry.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Patch net-next v7 4/6] vxlan: add ipv6 support
  2013-04-30  9:17   ` Bjørn Mork
  2013-04-30  9:25     ` Cong Wang
  2013-04-30  9:38     ` Cong Wang
@ 2013-04-30 19:04     ` David Miller
  2 siblings, 0 replies; 23+ messages in thread
From: David Miller @ 2013-04-30 19:04 UTC (permalink / raw)
  To: bjorn; +Cc: amwang, netdev, dlstevens, stephen

From: Bjørn Mork <bjorn@mork.no>
Date: Tue, 30 Apr 2013 11:17:43 +0200

> Cong Wang <amwang@redhat.com> writes:
> 
>> +/* Create UDP socket for encapsulation receive. AF_INET6 socket
>> + * could be used for both IPv4 and IPv6 communications.
>> + */
> 
> This is not necessarily true as mentioned by David Stevens, and acked by
> you here: http://www.spinics.net/lists/netdev/msg234151.html
> 
> Please take your time to clean up your todo-list and *test* the result
> with different runtime and buildtime settings. There is no need to rush
> this, and people may get tired of looking at the same shortcomings over
> and over again.

+1

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Patch net-next v7 4/6] vxlan: add ipv6 support
  2013-04-30  9:25     ` Cong Wang
  2013-04-30 10:33       ` Bjørn Mork
@ 2013-04-30 19:05       ` David Miller
  2013-05-02  7:55         ` Cong Wang
  1 sibling, 1 reply; 23+ messages in thread
From: David Miller @ 2013-04-30 19:05 UTC (permalink / raw)
  To: amwang; +Cc: bjorn, netdev, dlstevens, stephen

From: Cong Wang <amwang@redhat.com>
Date: Tue, 30 Apr 2013 17:25:56 +0800

> On Tue, 2013-04-30 at 11:17 +0200, Bjørn Mork wrote:
>> Please take your time to clean up your todo-list and *test* the result
>> with different runtime and buildtime settings. There is no need to rush
>> this, and people may get tired of looking at the same shortcomings over
>> and over again.
>> 
> 
> So, why do you expect it is perfect?

Your patch has had large, major, shortcomings every single iteration.

It isn't ready yet, and now that the net-next tree is closed, you have
time to work on the patch series slowly, and carefully, instead of
trying to rush things and making several mistakes.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Patch net-next v7 4/6] vxlan: add ipv6 support
  2013-04-30 10:33       ` Bjørn Mork
@ 2013-04-30 19:06         ` David Miller
  2013-05-02  8:05         ` Cong Wang
  1 sibling, 0 replies; 23+ messages in thread
From: David Miller @ 2013-04-30 19:06 UTC (permalink / raw)
  To: bjorn; +Cc: amwang, netdev, dlstevens, stephen

From: Bjørn Mork <bjorn@mork.no>
Date: Tue, 30 Apr 2013 12:33:49 +0200

> And net-next was already closed for new features when you sent the last
> version, so I really, really do not understand why you are in such a
> hurry.  Sorry.

+1

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Patch net-next v7 0/6] vxlan: add ipv6 support
  2013-04-30 19:00 ` [Patch net-next v7 0/6] vxlan: add ipv6 support David Miller
@ 2013-05-02  7:02   ` Cong Wang
  0 siblings, 0 replies; 23+ messages in thread
From: Cong Wang @ 2013-05-02  7:02 UTC (permalink / raw)
  To: David Miller; +Cc: netdev

On Tue, 2013-04-30 at 15:00 -0400, David Miller wrote:
> Please read:
> 
> 	http://marc.info/?l=linux-netdev&m=136730964130303&w=2
> 
> It is a very bad idea to ignore my announcements about what is, and
> what is not, appropriate to submit at a given time.
> 
> Your changes weren't ready in time for the merge window, please do
> not try and force the matter, you'll only make me angry.

Sorry that I saw your email after I sent this patchset, because I don't
subscribe netdev list with my redhat account. (I use gmail to read
external mailing lists.)

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Patch net-next v7 4/6] vxlan: add ipv6 support
  2013-04-30 19:05       ` David Miller
@ 2013-05-02  7:55         ` Cong Wang
  0 siblings, 0 replies; 23+ messages in thread
From: Cong Wang @ 2013-05-02  7:55 UTC (permalink / raw)
  To: David Miller; +Cc: bjorn, netdev, dlstevens, stephen

On Tue, 2013-04-30 at 15:05 -0400, David Miller wrote:
> Your patch has had large, major, shortcomings every single iteration.

This is due to people including you only point out one problem per
iteration, for some reason I don't understand...

For example, you pointed out IPv6=M issue in v5, and then pointed out
disable_ipv6 issue in v6. Until you pointed them out, I even wasn't
aware of them. All the problems I have fixed, except the naming of
struct fields which I still don't agree, exist in v1, there is no
regression since v1.

As always, it is _highly_ appreciated if all of you can point as many
issues as you can in a single iteration, so that I can fix them all in
one update (if I can fix), this also saves me _a lot_ of time,
obviously.

So, I even don't understand what you are complaining about. :) I am
trying my best to address all the issues you pointed out including the
one that I don't agree at all, except the one I can't fix right now
(scope id). If anything I can improve on my side, please explicitly let
me know.

Again, I am _not_ an IPv6 expert, I am sure there are still some other
issues like disable_ipv6 that I am still not aware of, so please don't
expect me to be able to fix all bugs alone at one time, I am trying to
fix them one by one, and this is the best that I can do.

Thanks.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Patch net-next v7 4/6] vxlan: add ipv6 support
  2013-04-30 10:33       ` Bjørn Mork
  2013-04-30 19:06         ` David Miller
@ 2013-05-02  8:05         ` Cong Wang
  2013-05-02  8:10           ` David Miller
  2013-05-02 12:45           ` Bjørn Mork
  1 sibling, 2 replies; 23+ messages in thread
From: Cong Wang @ 2013-05-02  8:05 UTC (permalink / raw)
  To: Bjørn Mork; +Cc: netdev, David Stevens, Stephen Hemminger, David S. Miller

On Tue, 2013-04-30 at 12:33 +0200, Bjørn Mork wrote:
> 
> Well, you have been told that your proposed new feature breaks IPv4
> support with specific settings.  I do not think that you are speeding
> up
> anything here by ignoring that fact.  On the contrary. 

It is obviously a corner case which is not deserved such a high priority
(as high as a kernel panic or a compile error). bindv6only is default to
be 0, I even wasn't aware of such sysctl until David pointed it out.

So, please give me a reason why we should let such a corner case block
the inclusion? I think there are still other such corner cases too (and
maybe many), which neither you nor me are aware of.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Patch net-next v7 4/6] vxlan: add ipv6 support
  2013-05-02  8:05         ` Cong Wang
@ 2013-05-02  8:10           ` David Miller
  2013-05-02 12:45           ` Bjørn Mork
  1 sibling, 0 replies; 23+ messages in thread
From: David Miller @ 2013-05-02  8:10 UTC (permalink / raw)
  To: amwang; +Cc: bjorn, netdev, dlstevens, stephen

From: Cong Wang <amwang@redhat.com>
Date: Thu, 02 May 2013 16:05:53 +0800

> bindv6only is default to be 0

Distributions have set it by default to '1' in /etc/sysctl.conf at one
time or another.  Debian is one such example.

Many people set disable_ipv6.

So neither are corner cases.

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Patch net-next v7 4/6] vxlan: add ipv6 support
  2013-05-02  8:05         ` Cong Wang
  2013-05-02  8:10           ` David Miller
@ 2013-05-02 12:45           ` Bjørn Mork
  2013-05-03  3:02             ` Cong Wang
  1 sibling, 1 reply; 23+ messages in thread
From: Bjørn Mork @ 2013-05-02 12:45 UTC (permalink / raw)
  To: Cong Wang; +Cc: netdev, David Stevens, Stephen Hemminger, David S. Miller

Cong Wang <amwang@redhat.com> writes:
> On Tue, 2013-04-30 at 12:33 +0200, Bjørn Mork wrote:
>> 
>> Well, you have been told that your proposed new feature breaks IPv4
>> support with specific settings.  I do not think that you are speeding
>> up
>> anything here by ignoring that fact.  On the contrary. 
>
> It is obviously a corner case which is not deserved such a high priority
> (as high as a kernel panic or a compile error). bindv6only is default to
> be 0, I even wasn't aware of such sysctl until David pointed it out.

It's a regression. Regressions trump new features. No need to argue
about the relative importance here.  Fix it.

> So, please give me a reason why we should let such a corner case block
> the inclusion? I think there are still other such corner cases too (and
> maybe many), which neither you nor me are aware of.

Yes, I am pretty sure of that as well.  That's why I ask you to *test*
your code with assorted settings before resubmitting it.  I'm not going
to.

I note that you claim you are not an expert.  Neither am I.  And luckily
I believe that is not required around here. Anyone can contribute, and
all contributions are very welcome.  At least that is the impression
I've got.

But only the experts can get away with limited testing. The less of an
expert you are, the more time you need to spend trying out every small
codepath you added using every possible input combination.  Doing
different combinations of buildtime and runtime IPv6 enable/disable is
an obvious requirement when you add code which has some sort of "if IPv6
is enabled" conditionals.  IMHO.



Bjørn

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [Patch net-next v7 4/6] vxlan: add ipv6 support
  2013-05-02 12:45           ` Bjørn Mork
@ 2013-05-03  3:02             ` Cong Wang
  0 siblings, 0 replies; 23+ messages in thread
From: Cong Wang @ 2013-05-03  3:02 UTC (permalink / raw)
  To: Bjørn Mork; +Cc: netdev, David Stevens, Stephen Hemminger, David S. Miller

On Thu, 2013-05-02 at 14:45 +0200, Bjørn Mork wrote:
> Yes, I am pretty sure of that as well.  That's why I ask you to *test*
> your code with assorted settings before resubmitting it.  I'm not
> going
> to. 

I have two scripts to test my patch, one for IPv4 and one for IPv6. Both
use the default configuration on Fedora.

That is chicken-and-egg problem, if I wasn't aware of such sysctl's, how
possible could I test it with different settings? Please don't doubt I
have tested it as much as I can, I just didn't know some IPv6 specific
sysctl's exist.

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2013-05-03  3:02 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-04-30  8:43 [Patch net-next v7 0/6] vxlan: add ipv6 support Cong Wang
2013-04-30  8:43 ` [Patch net-next v7 1/6] vxlan: defer vxlan init as late as possible Cong Wang
2013-04-30  8:43 ` [Patch net-next v7 2/6] ipv6: export a stub for ipv6_sock_mc_join and ipv6_sock_mc_drop Cong Wang
2013-04-30  8:43 ` [Patch net-next v7 3/6] ipv6: export in6addr_loopback to modules Cong Wang
2013-04-30  8:43 ` [Patch net-next v7 4/6] vxlan: add ipv6 support Cong Wang
2013-04-30  9:17   ` Bjørn Mork
2013-04-30  9:25     ` Cong Wang
2013-04-30 10:33       ` Bjørn Mork
2013-04-30 19:06         ` David Miller
2013-05-02  8:05         ` Cong Wang
2013-05-02  8:10           ` David Miller
2013-05-02 12:45           ` Bjørn Mork
2013-05-03  3:02             ` Cong Wang
2013-04-30 19:05       ` David Miller
2013-05-02  7:55         ` Cong Wang
2013-04-30  9:38     ` Cong Wang
2013-04-30 18:58       ` David Miller
2013-04-30 19:04     ` David Miller
2013-04-30  8:43 ` [Patch net-next v7 5/6] vxlan: respect disable_ipv6 sysctl Cong Wang
2013-04-30 12:27   ` Sergei Shtylyov
2013-04-30  8:43 ` [Patch net-next v7 6/6] ipv6: Add generic UDP Tunnel segmentation Cong Wang
2013-04-30 19:00 ` [Patch net-next v7 0/6] vxlan: add ipv6 support David Miller
2013-05-02  7:02   ` Cong Wang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).