Re: [PATCH v7 1/3] geneve: implement support for IPv6-based tunnels

2015-10-29 Thread David Miller
From: "John W. Linville" 
Date: Mon, 26 Oct 2015 17:01:44 -0400

> NOTE: Link-local IPv6 addresses for remote endpoints are not supported,
> since the driver currently has no capacity for binding a geneve
> interface to a specific link.
> 
> Signed-off-by: John W. Linville 
> Reviewed-by: Jesse Gross 

Applied.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v7 1/3] geneve: implement support for IPv6-based tunnels

2015-10-26 Thread John W. Linville
NOTE: Link-local IPv6 addresses for remote endpoints are not supported,
since the driver currently has no capacity for binding a geneve
interface to a specific link.

Signed-off-by: John W. Linville 
Reviewed-by: Jesse Gross 
---
v7:
- rebase on top of commit fc4099f17240 ("openvswitch: Fix egress tunnel info.")
- revise error handling in ipv6 tx path to match ipv4 tx path (as above)
- Added Reviewed-by from Jesse based on v6 review -- changes above are minor

v6:
- fix a typo (missing {}'s)

v5:
- wrap declaration of sock6 in geneve_dev with IS_ENABLED(CONFIG_IPV6)
- remove superfluous '!!' when assigning geneve->collect_md to bool
- use skb_scrub_packet in IPv4 tx path as well 
- check for NULL ip_tunnel_info pointer in geneve[6]_xmit_skb
- use ipv6_addr_equal for comparing IPv6 addresses
- more use of IS_ENABLED(CONFIG_IPV6) for preserving build integrity
- reject link-local ipv6 address for remote tunnel endpoint

v4:
- treat mode field of ip_tunnel_info as flags
- add a missing IS_ENABLED(CONFIG_IPV6) to geneve_rx
- remove unneeded flags field in geneve_dev
- NULL-check parameter for __geneve_sock_release
- check remote socket family for AF_UNSPEC in geneve_configure
- rename geneve_get_{rt,dst} as geneve_get_{v4_rt,v6_dst}
- refactor some error handling in the xmit paths

v3:
- declare geneve_remote_unspec as static

v2:
- do not require remote address for tx on metadata tunnels
- pass correct sockaddr family to udp_tun_rx_dst in geneve_rx
- accommodate both ipv4 and ipv6 sockets open on same tunnel
- move declaration of geneve_get_dst for aesthetic purposes

 drivers/net/geneve.c | 473 +++
 include/uapi/linux/if_link.h |   1 +
 2 files changed, 395 insertions(+), 79 deletions(-)

diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
index 445071c163cb..393b0bddf7cf 100644
--- a/drivers/net/geneve.c
+++ b/drivers/net/geneve.c
@@ -46,16 +46,27 @@ struct geneve_net {
 
 static int geneve_net_id;
 
+union geneve_addr {
+   struct sockaddr_in sin;
+   struct sockaddr_in6 sin6;
+   struct sockaddr sa;
+};
+
+static union geneve_addr geneve_remote_unspec = { .sa.sa_family = AF_UNSPEC, };
+
 /* Pseudo network device */
 struct geneve_dev {
struct hlist_node  hlist;   /* vni hash table */
struct net *net;/* netns for packet i/o */
struct net_device  *dev;/* netdev for geneve tunnel */
-   struct geneve_sock *sock;   /* socket used for geneve tunnel */
+   struct geneve_sock *sock4;  /* IPv4 socket used for geneve tunnel */
+#if IS_ENABLED(CONFIG_IPV6)
+   struct geneve_sock *sock6;  /* IPv6 socket used for geneve tunnel */
+#endif
u8 vni[3];  /* virtual network ID for tunnel */
u8 ttl; /* TTL override */
u8 tos; /* TOS override */
-   struct sockaddr_in remote;  /* IPv4 address for link partner */
+   union geneve_addr  remote;  /* IP address for link partner */
struct list_head   next;/* geneve's per namespace list */
__be16 dst_port;
bool   collect_md;
@@ -103,11 +114,31 @@ static struct geneve_dev *geneve_lookup(struct 
geneve_sock *gs,
vni_list_head = >vni_list[hash];
hlist_for_each_entry_rcu(geneve, vni_list_head, hlist) {
if (!memcmp(vni, geneve->vni, sizeof(geneve->vni)) &&
-   addr == geneve->remote.sin_addr.s_addr)
+   addr == geneve->remote.sin.sin_addr.s_addr)
+   return geneve;
+   }
+   return NULL;
+}
+
+#if IS_ENABLED(CONFIG_IPV6)
+static struct geneve_dev *geneve6_lookup(struct geneve_sock *gs,
+struct in6_addr addr6, u8 vni[])
+{
+   struct hlist_head *vni_list_head;
+   struct geneve_dev *geneve;
+   __u32 hash;
+
+   /* Find the device for this VNI */
+   hash = geneve_net_vni_hash(vni);
+   vni_list_head = >vni_list[hash];
+   hlist_for_each_entry_rcu(geneve, vni_list_head, hlist) {
+   if (!memcmp(vni, geneve->vni, sizeof(geneve->vni)) &&
+   ipv6_addr_equal(, >remote.sin6.sin6_addr))
return geneve;
}
return NULL;
 }
+#endif
 
 static inline struct genevehdr *geneve_hdr(const struct sk_buff *skb)
 {
@@ -121,24 +152,49 @@ static void geneve_rx(struct geneve_sock *gs, struct 
sk_buff *skb)
struct metadata_dst *tun_dst = NULL;
struct geneve_dev *geneve = NULL;
struct pcpu_sw_netstats *stats;
-   struct iphdr *iph;
-   u8 *vni;
+   struct iphdr *iph = NULL;
__be32 addr;
-   int err;
+   static u8 zero_vni[3];
+   u8 *vni;
+   int err = 0;
+   sa_family_t sa_family;
+#if IS_ENABLED(CONFIG_IPV6)
+   struct ipv6hdr *ip6h = NULL;
+   struct in6_addr addr6;
+