lwtunnel: per route ipv6 support for vxlan
Subsystems (7)
v3 cover lwtunnel: per route ipv6 support for vxlan
v3: Moved LWTUNNEL_ENCAP_IP6 definition in patch 13.
v2: Fixed issues in patch 4 pointed out by Alexei.
This series enables IPv6 tunnels based on lwtunnel infrastructure. Only vxlan is supported for now.
Tested in all combinations of IPv4 over IPv6, IPv6 over IPv4 and IPv6 over IPv6.
Jiri Benc (13):
ip_tunnels: remove custom alignment and packing
ip_tunnels: use u8/u16/u32
ip_tunnels: use offsetofend
ip_tunnels: add IPv6 addresses to ip_tunnel_key
ip_tunnels: use tos and ttl fields also for IPv6
route: move lwtunnel state to dst_entry
ipv6: drop metadata dst in ip6_route_input
ipv6: ndisc: inherit metadata dst when creating ndisc requests
vxlan: provide access function for vxlan socket address family
vxlan: do not shadow flags variable
vxlan: metadata based tunneling for IPv6
ipv6: route: extend flow representation with tunnel key
ipv6: route: per route IP tunnel metadata via lightweight tunnel
drivers/net/vrf.c | 1 - drivers/net/vxlan.c | 89 +++++++++++++++++-------------- include/net/dst.h | 3 +- include/net/dst_metadata.h | 15 ++---- include/net/flow.h | 1 + include/net/ip6_fib.h | 1 - include/net/ip_tunnels.h | 50 ++++++++++------- include/net/lwtunnel.h | 12 ----- include/net/ndisc.h | 3 +- include/net/route.h | 1 - include/net/vxlan.h | 5 ++ include/uapi/linux/lwtunnel.h | 16 ++++++ net/core/dst.c | 3 ++ net/core/filter.c | 6 +-- net/core/lwtunnel.c | 70 ++++-------------------- net/ipv4/ip_gre.c | 20 +++---- net/ipv4/ip_tunnel_core.c | 118 ++++++++++++++++++++++++++++++++++++++--- net/ipv4/route.c | 20 +++---- net/ipv6/addrconf.c | 2 +- net/ipv6/ila.c | 14 ++--- net/ipv6/ip6_fib.c | 1 - net/ipv6/ndisc.c | 10 ++-- net/ipv6/route.c | 29 ++++++---- net/mpls/mpls_iptunnel.c | 7 +-- net/openvswitch/flow_netlink.c | 28 +++++----- net/openvswitch/flow_table.c | 2 +- net/openvswitch/vport-geneve.c | 4 +- net/openvswitch/vport-netdev.c | 2 +- net/openvswitch/vport.c | 6 +-- net/openvswitch/vport.h | 6 +-- 30 files changed, 312 insertions(+), 233 deletions(-)
Signature · 1 line
1.8.3.1
PATCH v3 1/13 ip_tunnels: remove custom alignment and packing
The custom alignment of struct ip_tunnel_key is unnecessary. In struct sw_flow_key, it starts at offset 256, in struct ip_tunnel_info it's the first field.
The structure is also packed even without the __packed keyword.
--- include/net/ip_tunnels.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/net/ip_tunnels.h +1 -1
@@ -36,7 +36,7 @@ struct ip_tunnel_key {__u8 ipv4_ttl;__be16 tp_src;__be16 tp_dst; -} __packed__aligned(4) ;/* Minimize padding. */ +};/* Indicates whether the tunnel info structure represents receive * or transmit tunnel parameters.
Signature · 1 line
1.8.3.1
PATCH v3 2/13 ip_tunnels: use u8/u16/u32
In reply to Jiri BencThe ip_tunnels.h include file uses mixture of __u16 and u16 (etc.) types. Unify it to the non-underscore variants.
--- include/net/ip_tunnels.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
include/net/ip_tunnels.h +8 -8
@@ -32,8 +32,8 @@ struct ip_tunnel_key {__be32 ipv4_src;__be32 ipv4_dst;__be16 tun_flags; -__u8 ipv4_tos; -__u8 ipv4_ttl; +u8 ipv4_tos; +u8 ipv4_ttl;__be16 tp_src;__be16 tp_dst; };
@@ -64,8 +64,8 @@ struct ip_tunnel_6rd_parm {#endif struct ip_tunnel_encap { -__u16 type; -__u16 flags; +u16 type; +u16 flags;__be16 sport;__be16 dport; };
@@ -95,8 +95,8 @@ struct ip_tunnel {* arrived */ /* These four fields used only by GRE */ -__u32 i_seqno;/* The last seen seqno */ -__u32 o_seqno;/* The last output seqno */ +u32 i_seqno;/* The last seen seqno */ +u32 o_seqno;/* The last output seqno */ int tun_hlen;/* Precalculated header length */ int mlink;
@@ -273,8 +273,8 @@ static inline u8 ip_tunnel_ecn_encap(u8 tos, const struct iphdr *iph,int iptunnel_pull_header (struct sk_buff *skb,int hdr_len,__be16 inner_proto);int iptunnel_xmit (struct sock *sk,struct rtable *rt,struct sk_buff *skb, -__be32 src,__be32 dst,__u8 proto, -__u8 tos,__u8 ttl,__be16 df,bool xnet); +__be32 src,__be32 dst,u8 proto, +u8 tos,u8 ttl,__be16 df,bool xnet);struct sk_buff *iptunnel_handle_offloads (struct sk_buff *skb,bool gre_csum,int gso_type_mask);
Signature · 1 line
1.8.3.1
PATCH v3 3/13 ip_tunnels: use offsetofend
In reply to Jiri Benc--- include/net/ip_tunnels.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
include/net/ip_tunnels.h +1 -3
@@ -23,9 +23,7 @@#define IPTUNNEL_ERR_TIMEO (30*HZ)/* Used to memset ip_tunnel padding. */ -#define IP_TUNNEL_KEY_SIZE \ - (offsetof(struct ip_tunnel_key, tp_dst) + \ - FIELD_SIZEOF(struct ip_tunnel_key, tp_dst)) +#define IP_TUNNEL_KEY_SIZE offsetofend(struct ip_tunnel_key, tp_dst)struct ip_tunnel_key {__be64 tun_id;
Signature · 1 line
1.8.3.1
PATCH v3 4/13 ip_tunnels: add IPv6 addresses to ip_tunnel_key
In reply to Jiri BencAdd the IPv6 addresses as an union with IPv4 ones. When using IPv4, the newly introduced padding after the IPv4 addresses needs to be zeroed out.
---v1->v2: Fix incorrect IP_TUNNEL_KEY_IPV4_PAD_LEN calculation, thanks to Alexei.
--- drivers/net/vxlan.c | 6 +++--- include/net/ip_tunnels.h | 24 ++++++++++++++++++++---- net/core/filter.c | 4 ++-- net/ipv4/ip_gre.c | 10 +++++----- net/ipv4/ip_tunnel_core.c | 8 ++++---- net/openvswitch/flow_netlink.c | 18 +++++++++--------- net/openvswitch/flow_table.c | 2 +- net/openvswitch/vport-geneve.c | 2 +- net/openvswitch/vport.c | 2 +- net/openvswitch/vport.h | 4 ++-- 10 files changed, 48 insertions(+), 32 deletions(-)
drivers/net/vxlan.c +3 -3
@@ -1276,8 +1276,8 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb) goto drop; info = &tun_dst->u.tun_info; - info->key.ipv4_src = iph->saddr; - info->key.ipv4_dst = iph->daddr; + info->key.u.ipv4.src = iph->saddr; + info->key.u.ipv4.dst = iph->daddr; info->key.ipv4_tos = iph->tos; info->key.ipv4_ttl = iph->ttl; info->key.tp_src =udp_hdr (skb)->source;
@@ -1925,7 +1925,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, dst_port = info->key.tp_dst ? : vxlan->cfg.dst_port; vni =be64_to_cpu (info->key.tun_id); remote_ip.sin.sin_family =AF_INET ; - remote_ip.sin.sin_addr.s_addr = info->key.ipv4_dst; + remote_ip.sin.sin_addr.s_addr = info->key.u.ipv4.dst; dst = &remote_ip; }
include/net/ip_tunnels.h +20 -4
@@ -25,10 +25,24 @@/* Used to memset ip_tunnel padding. */ #define IP_TUNNEL_KEY_SIZE offsetofend(struct ip_tunnel_key, tp_dst) +/* Used to memset ipv4 address padding. */ +#define IP_TUNNEL_KEY_IPV4_PAD offsetofend(struct ip_tunnel_key, u.ipv4.dst) +#define IP_TUNNEL_KEY_IPV4_PAD_LEN \ + (FIELD_SIZEOF(struct ip_tunnel_key, u) - \ + FIELD_SIZEOF(struct ip_tunnel_key, u.ipv4)) +struct ip_tunnel_key {__be64 tun_id; -__be32 ipv4_src; -__be32 ipv4_dst; +union { +struct { +__be32 src; +__be32 dst; + } ipv4; +struct { +struct in6_addr src; +struct in6_addr dst; + } ipv6; + } u;__be16 tun_flags;u8 ipv4_tos;u8 ipv4_ttl;
@@ -177,8 +191,10 @@ static inline void __ip_tunnel_info_init(struct ip_tunnel_info *tun_info, const void *opts, u8 opts_len) { tun_info->key.tun_id = tun_id; - tun_info->key.ipv4_src = saddr; - tun_info->key.ipv4_dst = daddr; + tun_info->key.u.ipv4.src = saddr; + tun_info->key.u.ipv4.dst = daddr; +memset ((unsigned char *)&tun_info->key +IP_TUNNEL_KEY_IPV4_PAD , +0 ,IP_TUNNEL_KEY_IPV4_PAD_LEN ); tun_info->key.ipv4_tos = tos; tun_info->key.ipv4_ttl = ttl; tun_info->key.tun_flags = tun_flags;
net/core/filter.c +2 -2
@@ -1495,7 +1495,7 @@ static u64 bpf_skb_get_tunnel_key(u64 r1, u64 r2, u64 size, u64 flags, u64 r5)return -EINVAL ; to->tunnel_id =be64_to_cpu (info->key.tun_id); - to->remote_ipv4 =be32_to_cpu (info->key.ipv4_src); + to->remote_ipv4 =be32_to_cpu (info->key.u.ipv4.src);return 0 ; }
@@ -1529,7 +1529,7 @@ static u64 bpf_skb_set_tunnel_key(u64 r1, u64 r2, u64 size, u64 flags, u64 r5) info = &md->u.tun_info; info->mode =IP_TUNNEL_INFO_TX ; info->key.tun_id =cpu_to_be64 (from->tunnel_id); - info->key.ipv4_dst =cpu_to_be32 (from->remote_ipv4); + info->key.u.ipv4.dst =cpu_to_be32 (from->remote_ipv4);return 0 ; }
net/ipv4/ip_gre.c +5 -5
@@ -407,8 +407,8 @@ static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi)return PACKET_REJECT ; info = &tun_dst->u.tun_info; - info->key.ipv4_src = iph->saddr; - info->key.ipv4_dst = iph->daddr; + info->key.u.ipv4.src = iph->saddr; + info->key.u.ipv4.dst = iph->daddr; info->key.ipv4_tos = iph->tos; info->key.ipv4_ttl = iph->ttl;
@@ -527,8 +527,8 @@ static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev) key = &tun_info->key;memset (&fl,0 ,sizeof (fl)); - fl.daddr = key->ipv4_dst; - fl.saddr = key->ipv4_src; + fl.daddr = key->u.ipv4.dst; + fl.saddr = key->u.ipv4.src; fl.flowi4_tos =RT_TOS (key->ipv4_tos); fl.flowi4_mark = skb->mark; fl.flowi4_proto =IPPROTO_GRE ;
@@ -564,7 +564,7 @@ static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev) df = key->tun_flags &TUNNEL_DONT_FRAGMENT ?htons (IP_DF ) :0 ; err =iptunnel_xmit (skb->sk, rt, skb, fl.saddr, - key->ipv4_dst,IPPROTO_GRE , + key->u.ipv4.dst,IPPROTO_GRE , key->ipv4_tos, key->ipv4_ttl, df, false);iptunnel_xmit_stats (err, &dev->stats, dev->tstats);return ;
net/ipv4/ip_tunnel_core.c +4 -4
@@ -227,10 +227,10 @@ static int ip_tun_build_state(struct net_device *dev, struct nlattr *attr, tun_info->key.tun_id =nla_get_u64 (tb[LWTUNNEL_IP_ID ]);if (tb[LWTUNNEL_IP_DST ]) - tun_info->key.ipv4_dst =nla_get_be32 (tb[LWTUNNEL_IP_DST ]); + tun_info->key.u.ipv4.dst =nla_get_be32 (tb[LWTUNNEL_IP_DST ]);if (tb[LWTUNNEL_IP_SRC ]) - tun_info->key.ipv4_src =nla_get_be32 (tb[LWTUNNEL_IP_SRC ]); + tun_info->key.u.ipv4.src =nla_get_be32 (tb[LWTUNNEL_IP_SRC ]);if (tb[LWTUNNEL_IP_TTL ]) tun_info->key.ipv4_ttl =nla_get_u8 (tb[LWTUNNEL_IP_TTL ]);
@@ -262,8 +262,8 @@ static int ip_tun_fill_encap_info(struct sk_buff *skb,struct ip_tunnel_info *tun_info =lwt_tun_info (lwtstate); if (nla_put_u64(skb, LWTUNNEL_IP_ID, tun_info->key.tun_id) || - nla_put_be32(skb, LWTUNNEL_IP_DST, tun_info->key.ipv4_dst) || - nla_put_be32(skb, LWTUNNEL_IP_SRC, tun_info->key.ipv4_src) || + nla_put_be32(skb, LWTUNNEL_IP_DST, tun_info->key.u.ipv4.dst) || + nla_put_be32(skb, LWTUNNEL_IP_SRC, tun_info->key.u.ipv4.src) || nla_put_u8(skb, LWTUNNEL_IP_TOS, tun_info->key.ipv4_tos) || nla_put_u8(skb, LWTUNNEL_IP_TTL, tun_info->key.ipv4_ttl) || nla_put_u16(skb, LWTUNNEL_IP_SPORT, tun_info->key.tp_src) ||
net/openvswitch/flow_netlink.c +9 -9
@@ -534,11 +534,11 @@ static int ipv4_tun_from_nlattr(const struct nlattr *attr, tun_flags |=TUNNEL_KEY ;break ;case OVS_TUNNEL_KEY_ATTR_IPV4_SRC : -SW_FLOW_KEY_PUT (match, tun_key.ipv4_src, +SW_FLOW_KEY_PUT (match, tun_key.u.ipv4.src,nla_get_in_addr (a), is_mask);break ;case OVS_TUNNEL_KEY_ATTR_IPV4_DST : -SW_FLOW_KEY_PUT (match, tun_key.ipv4_dst, +SW_FLOW_KEY_PUT (match, tun_key.u.ipv4.dst,nla_get_in_addr (a), is_mask);break ;case OVS_TUNNEL_KEY_ATTR_TOS :
@@ -609,7 +609,7 @@ static int ipv4_tun_from_nlattr(const struct nlattr *attr, }if (!is_mask) { -if (!match->key->tun_key.ipv4_dst) { +if (!match->key->tun_key.u.ipv4.dst) {OVS_NLERR (log,"IPv4 tunnel dst address is zero" );return -EINVAL ; }
@@ -647,13 +647,13 @@ static int __ipv4_tun_to_nlattr(struct sk_buff *skb,if (output->tun_flags &TUNNEL_KEY &&nla_put_be64 (skb,OVS_TUNNEL_KEY_ATTR_ID , output->tun_id))return -EMSGSIZE ; -if (output->ipv4_src && +if (output->u.ipv4.src &&nla_put_in_addr (skb,OVS_TUNNEL_KEY_ATTR_IPV4_SRC , - output->ipv4_src)) + output->u.ipv4.src))return -EMSGSIZE ; -if (output->ipv4_dst && +if (output->u.ipv4.dst &&nla_put_in_addr (skb,OVS_TUNNEL_KEY_ATTR_IPV4_DST , - output->ipv4_dst)) + output->u.ipv4.dst))return -EMSGSIZE ;if (output->ipv4_tos &&nla_put_u8 (skb,OVS_TUNNEL_KEY_ATTR_TOS , output->ipv4_tos))
@@ -1116,7 +1116,7 @@ int ovs_nla_get_match(struct sw_flow_match *match,/* The userspace does not send tunnel attributes that * are 0, but we should not wildcard them nonetheless. */ -if (match->key->tun_key.ipv4_dst) +if (match->key->tun_key.u.ipv4.dst)SW_FLOW_KEY_MEMSET_FIELD (match, tun_key,0xff , true);
@@ -1287,7 +1287,7 @@ static int __ovs_nla_put_key(const struct sw_flow_key *swkey,if (nla_put_u32 (skb,OVS_KEY_ATTR_PRIORITY , output->phy.priority)) goto nla_put_failure; -if ((swkey->tun_key.ipv4_dst || is_mask)) { +if ((swkey->tun_key.u.ipv4.dst || is_mask)) {const void *opts =NULL ;if (output->tun_key.tun_flags &TUNNEL_OPTIONS_PRESENT )
net/openvswitch/flow_table.c +1 -1
@@ -426,7 +426,7 @@ static u32 flow_hash(const struct sw_flow_key *key,static int flow_key_start (const struct sw_flow_key *key) { -if (key->tun_key.ipv4_dst) +if (key->tun_key.u.ipv4.dst)return 0 ;else return rounddown(offsetof(struct sw_flow_key, phy),
net/openvswitch/vport-geneve.c +1 -1
@@ -203,7 +203,7 @@ static int geneve_tnl_send(struct vport *vport, struct sk_buff *skb) } err =geneve_xmit_skb (geneve_port->gs, rt, skb, fl.saddr, - tun_key->ipv4_dst, tun_key->ipv4_tos, + tun_key->u.ipv4.dst, tun_key->ipv4_tos, tun_key->ipv4_ttl, df, sport, dport, tun_key->tun_flags, vni, opts_len, opts, !!(tun_key->tun_flags &TUNNEL_CSUM ), false);
net/openvswitch/vport.c +1 -1
@@ -603,7 +603,7 @@ int ovs_tunnel_get_egress_info(struct ip_tunnel_info *egress_tun_info,* saddr, tp_src and tp_dst */ __ip_tunnel_info_init(egress_tun_info, - fl.saddr, tun_key->ipv4_dst, + fl.saddr, tun_key->u.ipv4.dst, tun_key->ipv4_tos, tun_key->ipv4_ttl, tp_src, tp_dst,
net/openvswitch/vport.h +2 -2
@@ -254,8 +254,8 @@ static inline struct rtable *ovs_tunnel_route_lookup(struct net *net,struct rtable *rt;memset (fl,0 ,sizeof (*fl)); - fl->daddr = key->ipv4_dst; - fl->saddr = key->ipv4_src; + fl->daddr = key->u.ipv4.dst; + fl->saddr = key->u.ipv4.src; fl->flowi4_tos =RT_TOS (key->ipv4_tos); fl->flowi4_mark = mark; fl->flowi4_proto = protocol;
Signature · 1 line
1.8.3.1
PATCH v3 5/13 ip_tunnels: use tos and ttl fields also for IPv6
In reply to Jiri BencRename the ipv4_tos and ipv4_ttl fields to just 'tos' and 'ttl', as they'll be used with IPv6 tunnels, too.
--- drivers/net/vxlan.c | 8 ++++---- include/net/ip_tunnels.h | 8 ++++---- net/ipv4/ip_gre.c | 8 ++++---- net/ipv4/ip_tunnel_core.c | 8 ++++---- net/openvswitch/flow_netlink.c | 10 +++++----- net/openvswitch/vport-geneve.c | 4 ++-- net/openvswitch/vport.c | 4 ++-- net/openvswitch/vport.h | 2 +- 8 files changed, 26 insertions(+), 26 deletions(-)
drivers/net/vxlan.c +4 -4
@@ -1278,8 +1278,8 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb) info = &tun_dst->u.tun_info; info->key.u.ipv4.src = iph->saddr; info->key.u.ipv4.dst = iph->daddr; - info->key.ipv4_tos = iph->tos; - info->key.ipv4_ttl = iph->ttl; + info->key.tos = iph->tos; + info->key.ttl = iph->ttl; info->key.tp_src =udp_hdr (skb)->source; info->key.tp_dst =udp_hdr (skb)->dest;
@@ -1960,8 +1960,8 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,else flags &= ~VXLAN_F_UDP_CSUM ; - ttl = info->key.ipv4_ttl; - tos = info->key.ipv4_tos; + ttl = info->key.ttl; + tos = info->key.tos;if (info->options_len) md =ip_tunnel_info_opts (info,sizeof (*md));
include/net/ip_tunnels.h +4 -4
@@ -44,8 +44,8 @@ struct ip_tunnel_key { } ipv6; } u;__be16 tun_flags; -u8 ipv4_tos; -u8 ipv4_ttl; +u8 tos;/* TOS for IPv4, TC for IPv6 */ +u8 ttl;/* TTL for IPv4, HL for IPv6 */ __be16 tp_src;__be16 tp_dst; };
@@ -195,8 +195,8 @@ static inline void __ip_tunnel_info_init(struct ip_tunnel_info *tun_info, tun_info->key.u.ipv4.dst = daddr;memset ((unsigned char *)&tun_info->key +IP_TUNNEL_KEY_IPV4_PAD ,0 ,IP_TUNNEL_KEY_IPV4_PAD_LEN ); - tun_info->key.ipv4_tos = tos; - tun_info->key.ipv4_ttl = ttl; + tun_info->key.tos = tos; + tun_info->key.ttl = ttl; tun_info->key.tun_flags = tun_flags;/* For the tunnel types on the top of IPsec, the tp_src and tp_dst of
net/ipv4/ip_gre.c +4 -4
@@ -409,8 +409,8 @@ static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi) info = &tun_dst->u.tun_info; info->key.u.ipv4.src = iph->saddr; info->key.u.ipv4.dst = iph->daddr; - info->key.ipv4_tos = iph->tos; - info->key.ipv4_ttl = iph->ttl; + info->key.tos = iph->tos; + info->key.ttl = iph->ttl; info->mode =IP_TUNNEL_INFO_RX ; info->key.tun_flags = tpi->flags &
@@ -529,7 +529,7 @@ static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev)memset (&fl,0 ,sizeof (fl)); fl.daddr = key->u.ipv4.dst; fl.saddr = key->u.ipv4.src; - fl.flowi4_tos =RT_TOS (key->ipv4_tos); + fl.flowi4_tos =RT_TOS (key->tos); fl.flowi4_mark = skb->mark; fl.flowi4_proto =IPPROTO_GRE ;
@@ -565,7 +565,7 @@ static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev) df = key->tun_flags &TUNNEL_DONT_FRAGMENT ?htons (IP_DF ) :0 ; err =iptunnel_xmit (skb->sk, rt, skb, fl.saddr, key->u.ipv4.dst,IPPROTO_GRE , - key->ipv4_tos, key->ipv4_ttl, df, false); + key->tos, key->ttl, df, false);iptunnel_xmit_stats (err, &dev->stats, dev->tstats);return ;
net/ipv4/ip_tunnel_core.c +4 -4
@@ -233,10 +233,10 @@ static int ip_tun_build_state(struct net_device *dev, struct nlattr *attr, tun_info->key.u.ipv4.src =nla_get_be32 (tb[LWTUNNEL_IP_SRC ]);if (tb[LWTUNNEL_IP_TTL ]) - tun_info->key.ipv4_ttl =nla_get_u8 (tb[LWTUNNEL_IP_TTL ]); + tun_info->key.ttl =nla_get_u8 (tb[LWTUNNEL_IP_TTL ]);if (tb[LWTUNNEL_IP_TOS ]) - tun_info->key.ipv4_tos =nla_get_u8 (tb[LWTUNNEL_IP_TOS ]); + tun_info->key.tos =nla_get_u8 (tb[LWTUNNEL_IP_TOS ]);if (tb[LWTUNNEL_IP_SPORT ]) tun_info->key.tp_src =nla_get_be16 (tb[LWTUNNEL_IP_SPORT ]);
@@ -264,8 +264,8 @@ static int ip_tun_fill_encap_info(struct sk_buff *skb,if (nla_put_u64 (skb,LWTUNNEL_IP_ID , tun_info->key.tun_id) ||nla_put_be32 (skb,LWTUNNEL_IP_DST , tun_info->key.u.ipv4.dst) ||nla_put_be32 (skb,LWTUNNEL_IP_SRC , tun_info->key.u.ipv4.src) || -nla_put_u8 (skb,LWTUNNEL_IP_TOS , tun_info->key.ipv4_tos) || -nla_put_u8 (skb,LWTUNNEL_IP_TTL , tun_info->key.ipv4_ttl) || +nla_put_u8 (skb,LWTUNNEL_IP_TOS , tun_info->key.tos) || +nla_put_u8 (skb,LWTUNNEL_IP_TTL , tun_info->key.ttl) ||nla_put_u16 (skb,LWTUNNEL_IP_SPORT , tun_info->key.tp_src) ||nla_put_u16 (skb,LWTUNNEL_IP_DPORT , tun_info->key.tp_dst) ||nla_put_u16 (skb,LWTUNNEL_IP_FLAGS , tun_info->key.tun_flags))
net/openvswitch/flow_netlink.c +5 -5
@@ -542,11 +542,11 @@ static int ipv4_tun_from_nlattr(const struct nlattr *attr, nla_get_in_addr(a), is_mask);break ;case OVS_TUNNEL_KEY_ATTR_TOS : -SW_FLOW_KEY_PUT (match, tun_key.ipv4_tos, +SW_FLOW_KEY_PUT (match, tun_key.tos,nla_get_u8 (a), is_mask);break ;case OVS_TUNNEL_KEY_ATTR_TTL : -SW_FLOW_KEY_PUT (match, tun_key.ipv4_ttl, +SW_FLOW_KEY_PUT (match, tun_key.ttl,nla_get_u8 (a), is_mask); ttl = true;break ;
@@ -655,10 +655,10 @@ static int __ipv4_tun_to_nlattr(struct sk_buff *skb,nla_put_in_addr (skb,OVS_TUNNEL_KEY_ATTR_IPV4_DST , output->u.ipv4.dst)) return -EMSGSIZE; -if (output->ipv4_tos && -nla_put_u8 (skb,OVS_TUNNEL_KEY_ATTR_TOS , output->ipv4_tos)) +if (output->tos && +nla_put_u8 (skb,OVS_TUNNEL_KEY_ATTR_TOS , output->tos))return -EMSGSIZE ; -if (nla_put_u8 (skb,OVS_TUNNEL_KEY_ATTR_TTL , output->ipv4_ttl)) +if (nla_put_u8 (skb,OVS_TUNNEL_KEY_ATTR_TTL , output->ttl))return -EMSGSIZE ;if ((output->tun_flags &TUNNEL_DONT_FRAGMENT ) &&nla_put_flag (skb,OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT ))
net/openvswitch/vport-geneve.c +2 -2
@@ -203,8 +203,8 @@ static int geneve_tnl_send(struct vport *vport, struct sk_buff *skb) } err =geneve_xmit_skb (geneve_port->gs, rt, skb, fl.saddr, - tun_key->u.ipv4.dst, tun_key->ipv4_tos, - tun_key->ipv4_ttl, df, sport, dport, + tun_key->u.ipv4.dst, tun_key->tos, + tun_key->ttl, df, sport, dport, tun_key->tun_flags, vni, opts_len, opts, !!(tun_key->tun_flags &TUNNEL_CSUM ), false);if (err <0 )
net/openvswitch/vport.c +2 -2
@@ -604,8 +604,8 @@ int ovs_tunnel_get_egress_info(struct ip_tunnel_info *egress_tun_info,*/ __ip_tunnel_info_init(egress_tun_info, fl.saddr, tun_key->u.ipv4.dst, - tun_key->ipv4_tos, - tun_key->ipv4_ttl, + tun_key->tos, + tun_key->ttl, tp_src, tp_dst, tun_key->tun_id, tun_key->tun_flags,
net/openvswitch/vport.h +1 -1
@@ -256,7 +256,7 @@ static inline struct rtable *ovs_tunnel_route_lookup(struct net *net,memset (fl,0 ,sizeof (*fl)); fl->daddr = key->u.ipv4.dst; fl->saddr = key->u.ipv4.src; - fl->flowi4_tos =RT_TOS (key->ipv4_tos); + fl->flowi4_tos =RT_TOS (key->tos); fl->flowi4_mark = mark; fl->flowi4_proto = protocol;
Signature · 1 line
1.8.3.1
PATCH v3 6/13 route: move lwtunnel state to dst_entry
In reply to Jiri BencCurrently, the lwtunnel state resides in per-protocol data. This is a problem if we encapsulate ipv6 traffic in an ipv4 tunnel (or vice versa). The xmit function of the tunnel does not know whether the packet has been routed to it by ipv4 or ipv6, yet it needs the lwtstate data. Moving the lwtstate data to dst_entry makes such inter-protocol tunneling possible.
As a bonus, this brings a nice diffstat.
--- drivers/net/vrf.c | 1 - drivers/net/vxlan.c | 4 +-- include/net/dst.h | 3 +- include/net/dst_metadata.h | 15 +++------ include/net/ip6_fib.h | 1 - include/net/lwtunnel.h | 12 -------- include/net/route.h | 1 - net/core/dst.c | 3 ++ net/core/filter.c | 2 +- net/core/lwtunnel.c | 70 ++++++------------------------------------ net/ipv4/ip_gre.c | 2 +- net/ipv4/route.c | 20 +++++------- net/ipv6/ila.c | 14 +++------ net/ipv6/ip6_fib.c | 1 - net/ipv6/route.c | 20 ++++++------ net/mpls/mpls_iptunnel.c | 7 ++--- net/openvswitch/vport-netdev.c | 2 +- 17 files changed, 48 insertions(+), 130 deletions(-)
drivers/net/vrf.c +0 -1
@@ -288,7 +288,6 @@ static struct rtable *vrf_rtable_create(struct net_device *dev) rth->rt_uses_gateway =0 ;INIT_LIST_HEAD (&rth->rt_uncached); rth->rt_uncached_list =NULL ; - rth->rt_lwtstate =NULL ; }return rth;
drivers/net/vxlan.c +2 -2
@@ -1909,7 +1909,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,u32 flags = vxlan->flags;/* FIXME: Support IPv6 */ - info =skb_tunnel_info (skb,AF_INET ); + info =skb_tunnel_info (skb);if (rdst) { dst_port = rdst->remote_port ? rdst->remote_port : vxlan->cfg.dst_port;
@@ -2105,7 +2105,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)struct vxlan_fdb *f;/* FIXME: Support IPv6 */ - info =skb_tunnel_info (skb,AF_INET ); + info =skb_tunnel_info (skb);skb_reset_mac_header (skb); eth =eth_hdr (skb);
include/net/dst.h +2 -1
@@ -44,6 +44,7 @@ struct dst_entry {#else void *__pad1;#endif +struct lwtunnel_state *lwtstate;int (*input)(struct sk_buff *);int (*output)(struct sock *sk,struct sk_buff *skb);
@@ -89,7 +90,7 @@ struct dst_entry {* (L1_CACHE_SIZE would be too much) */ #ifdef CONFIG_64BIT -long __pad_to_align_refcnt[2 ]; +long __pad_to_align_refcnt[1 ];#endif /* * __refcnt wants to be on a different cache line from
include/net/dst_metadata.h +5 -10
@@ -23,22 +23,17 @@ static inline struct metadata_dst *skb_metadata_dst(struct sk_buff *skb)return NULL ; } -static inline struct ip_tunnel_info *skb_tunnel_info (struct sk_buff *skb, -int family) +static inline struct ip_tunnel_info *skb_tunnel_info (struct sk_buff *skb) {struct metadata_dst *md_dst =skb_metadata_dst (skb); -struct rtable *rt; +struct dst_entry *dst;if (md_dst)return &md_dst->u.tun_info; -switch (family) { -case AF_INET : - rt = (struct rtable *)skb_dst (skb); -if (rt && rt->rt_lwtstate) -return lwt_tun_info (rt->rt_lwtstate); -break ; - } + dst =skb_dst (skb); +if (dst && dst->lwtstate) +return lwt_tun_info (dst->lwtstate);return NULL ; }
include/net/ip6_fib.h +0 -1
@@ -133,7 +133,6 @@ struct rt6_info {/* more non-fragment space at head required */ unsigned short rt6i_nfheader_len;u8 rt6i_protocol; -struct lwtunnel_state *rt6i_lwtstate; };static inline struct inet6_dev *ip6_dst_idev (struct dst_entry *dst)
include/net/lwtunnel.h +0 -12
@@ -87,9 +87,7 @@ int lwtunnel_get_encap_size(struct lwtunnel_state *lwtstate);struct lwtunnel_state *lwtunnel_state_alloc (int hdr_len);int lwtunnel_cmp_encap (struct lwtunnel_state *a,struct lwtunnel_state *b);int lwtunnel_output (struct sock *sk,struct sk_buff *skb); -int lwtunnel_output6 (struct sock *sk,struct sk_buff *skb);int lwtunnel_input (struct sk_buff *skb); -int lwtunnel_input6 (struct sk_buff *skb);#else
@@ -164,21 +162,11 @@ static inline int lwtunnel_output(struct sock *sk, struct sk_buff *skb)return -EOPNOTSUPP ; } -static inline int lwtunnel_output6 (struct sock *sk,struct sk_buff *skb) -{ -return -EOPNOTSUPP ; -} -static inline int lwtunnel_input (struct sk_buff *skb) {return -EOPNOTSUPP ; } -static inline int lwtunnel_input6 (struct sk_buff *skb) -{ -return -EOPNOTSUPP ; -} -#endif #endif /* __NET_LWTUNNEL_H */
include/net/route.h +0 -1
@@ -66,7 +66,6 @@ struct rtable {struct list_head rt_uncached;struct uncached_list *rt_uncached_list; -struct lwtunnel_state *rt_lwtstate; };static inline bool rt_is_input_route (const struct rtable *rt)
net/core/dst.c +3 -0
@@ -20,6 +20,7 @@#include <net/net_namespace.h> #include <linux/sched.h> #include <linux/prefetch.h> +#include <net/lwtunnel.h> #include <net/dst.h> #include <net/dst_metadata.h>
@@ -184,6 +185,7 @@ void dst_init(struct dst_entry *dst, struct dst_ops *ops,#ifdef CONFIG_IP_ROUTE_CLASSID dst->tclassid =0 ;#endif + dst->lwtstate =NULL ;atomic_set (&dst->__refcnt, initial_ref); dst->__use =0 ; dst->lastuse = jiffies;
@@ -264,6 +266,7 @@ again:kfree (dst); else kmem_cache_free(dst->ops->kmem_cachep, dst); +lwtstate_put (dst->lwtstate); dst = child;if (dst) {
net/core/filter.c +1 -1
@@ -1489,7 +1489,7 @@ static u64 bpf_skb_get_tunnel_key(u64 r1, u64 r2, u64 size, u64 flags, u64 r5) {struct sk_buff *skb = (struct sk_buff *) (long ) r1;struct bpf_tunnel_key *to = (struct bpf_tunnel_key *) (long ) r2; -struct ip_tunnel_info *info =skb_tunnel_info (skb,AF_INET ); +struct ip_tunnel_info *info =skb_tunnel_info (skb);if (unlikely (size !=sizeof (struct bpf_tunnel_key ) || flags || !info))return -EINVAL ;
net/core/lwtunnel.c +10 -60
98 lines not on this page · raw message
net/ipv4/ip_gre.c +1 -1
@@ -521,7 +521,7 @@ static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev)__be16 df, flags;int err; - tun_info =skb_tunnel_info (skb,AF_INET ); + tun_info =skb_tunnel_info (skb);if (unlikely (!tun_info || tun_info->mode !=IP_TUNNEL_INFO_TX )) goto err_free_skb;
net/ipv4/route.c +7 -13
@@ -1359,7 +1359,6 @@ static void ipv4_dst_destroy(struct dst_entry *dst)list_del (&rt->rt_uncached);spin_unlock_bh (&ul->lock); } -lwtstate_put (rt->rt_lwtstate); }void rt_flush_dev (struct net_device *dev)
@@ -1408,7 +1407,7 @@ static void rt_set_nexthop(struct rtable *rt, __be32 daddr,#ifdef CONFIG_IP_ROUTE_CLASSID rt->dst.tclassid = nh->nh_tclassid;#endif - rt->rt_lwtstate =lwtstate_get (nh->nh_lwtstate); + rt->dst.lwtstate =lwtstate_get (nh->nh_lwtstate);if (unlikely (fnhe)) cached =rt_bind_exception (rt, fnhe, daddr);else if (!(rt->dst.flags &DST_NOCACHE ))
@@ -1494,7 +1493,6 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, rth->rt_gateway =0 ; rth->rt_uses_gateway =0 ;INIT_LIST_HEAD (&rth->rt_uncached); - rth->rt_lwtstate =NULL ;if (our) { rth->dst.input= ip_local_deliver; rth->rt_flags |=RTCF_LOCAL ;
@@ -1624,19 +1622,18 @@ static int __mkroute_input(struct sk_buff *skb, rth->rt_gateway =0 ; rth->rt_uses_gateway =0 ;INIT_LIST_HEAD (&rth->rt_uncached); - rth->rt_lwtstate =NULL ;RT_CACHE_STAT_INC (in_slow_tot); rth->dst.input = ip_forward; rth->dst.output = ip_output;rt_set_nexthop (rth, daddr, res, fnhe, res->fi, res->type, itag); -if (lwtunnel_output_redirect (rth->rt_lwtstate)) { - rth->rt_lwtstate->orig_output = rth->dst.output; +if (lwtunnel_output_redirect (rth->dst.lwtstate)) { + rth->dst.lwtstate->orig_output = rth->dst.output; rth->dst.output = lwtunnel_output; } -if (lwtunnel_input_redirect (rth->rt_lwtstate)) { - rth->rt_lwtstate->orig_input = rth->dst.input; +if (lwtunnel_input_redirect (rth->dst.lwtstate)) { + rth->dst.lwtstate->orig_input = rth->dst.input; rth->dst.input = lwtunnel_input; }skb_dst_set (skb, &rth->dst);
@@ -1695,7 +1692,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,by fib_lookup. */ - tun_info =skb_tunnel_info (skb,AF_INET ); + tun_info =skb_tunnel_info (skb);if (tun_info && tun_info->mode ==IP_TUNNEL_INFO_RX ) fl4.flowi4_tun_key.tun_id = tun_info->key.tun_id;else
@@ -1815,7 +1812,6 @@ local_input: rth->rt_gateway =0 ; rth->rt_uses_gateway =0 ;INIT_LIST_HEAD (&rth->rt_uncached); - rth->rt_lwtstate =NULL ;RT_CACHE_STAT_INC (in_slow_tot);if (res.type ==RTN_UNREACHABLE ) {
@@ -2006,7 +2002,6 @@ add: rth->rt_gateway =0 ; rth->rt_uses_gateway =0 ;INIT_LIST_HEAD (&rth->rt_uncached); - rth->rt_lwtstate =NULL ;RT_CACHE_STAT_INC (out_slow_tot);if (flags &RTCF_LOCAL )
@@ -2029,7 +2024,7 @@ add: }rt_set_nexthop (rth, fl4->daddr, res, fnhe, fi, type,0 ); -if (lwtunnel_output_redirect (rth->rt_lwtstate)) +if (lwtunnel_output_redirect (rth->dst.lwtstate)) rth->dst.output = lwtunnel_output;return rth;
@@ -2293,7 +2288,6 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or rt->rt_uses_gateway = ort->rt_uses_gateway;INIT_LIST_HEAD (&rt->rt_uncached); - rt->rt_lwtstate =NULL ;dst_free (new); }
net/ipv6/ila.c +4 -10
@@ -89,16 +89,13 @@ static void update_ipv6_locator(struct sk_buff *skb, struct ila_params *p)static int ila_output (struct sock *sk,struct sk_buff *skb) {struct dst_entry *dst =skb_dst (skb); -struct rt6_info *rt6 =NULL ;if (skb->protocol !=htons (ETH_P_IPV6 )) goto drop; - rt6 = (struct rt6_info *)dst; +update_ipv6_locator (skb,ila_params_lwtunnel (dst->lwtstate)); -update_ipv6_locator (skb,ila_params_lwtunnel (rt6->rt6i_lwtstate)); - -return rt6->rt6i_lwtstate->orig_output (sk, skb); +return dst->lwtstate->orig_output (sk, skb); drop:kfree_skb (skb);
@@ -108,16 +105,13 @@ drop:static int ila_input (struct sk_buff *skb) {struct dst_entry *dst =skb_dst (skb); -struct rt6_info *rt6 =NULL ;if (skb->protocol !=htons (ETH_P_IPV6 )) goto drop; - rt6 = (struct rt6_info *)dst; - -update_ipv6_locator (skb,ila_params_lwtunnel (rt6->rt6i_lwtstate)); +update_ipv6_locator (skb,ila_params_lwtunnel (dst->lwtstate)); -return rt6->rt6i_lwtstate->orig_input (skb); +return dst->lwtstate->orig_input (skb); drop:kfree_skb (skb);
net/ipv6/ip6_fib.c +0 -1
@@ -178,7 +178,6 @@ static void rt6_free_pcpu(struct rt6_info *non_pcpu_rt)static void rt6_release (struct rt6_info *rt) {if (atomic_dec_and_test (&rt->rt6i_ref)) { -lwtstate_put (rt->rt6i_lwtstate);rt6_free_pcpu (rt);dst_free (&rt->dst); }
net/ipv6/route.c +10 -10
@@ -1784,14 +1784,14 @@ int ip6_route_add(struct fib6_config *cfg) cfg->fc_encap, &lwtstate);if (err) goto out; - rt->rt6i_lwtstate =lwtstate_get (lwtstate); -if (lwtunnel_output_redirect (rt->rt6i_lwtstate)) { - rt->rt6i_lwtstate->orig_output = rt->dst.output; - rt->dst.output = lwtunnel_output6; + rt->dst.lwtstate =lwtstate_get (lwtstate); +if (lwtunnel_output_redirect (rt->dst.lwtstate)) { + rt->dst.lwtstate->orig_output = rt->dst.output; + rt->dst.output = lwtunnel_output; } -if (lwtunnel_input_redirect (rt->rt6i_lwtstate)) { - rt->rt6i_lwtstate->orig_input = rt->dst.input; - rt->dst.input = lwtunnel_input6; +if (lwtunnel_input_redirect (rt->dst.lwtstate)) { + rt->dst.lwtstate->orig_input = rt->dst.input; + rt->dst.input = lwtunnel_input; } }
@@ -2174,7 +2174,7 @@ static void ip6_rt_copy_init(struct rt6_info *rt, struct rt6_info *ort)#endif rt->rt6i_prefsrc = ort->rt6i_prefsrc; rt->rt6i_table = ort->rt6i_table; - rt->rt6i_lwtstate =lwtstate_get (ort->rt6i_lwtstate); + rt->dst.lwtstate =lwtstate_get (ort->dst.lwtstate); }#ifdef CONFIG_IPV6_ROUTE_INFO
@@ -2838,7 +2838,7 @@ static inline size_t rt6_nlmsg_size(struct rt6_info *rt) +nla_total_size (sizeof (struct rta_cacheinfo )) +nla_total_size (TCP_CA_NAME_MAX )/* RTAX_CC_ALGO */ +nla_total_size (1 )/* RTA_PREF */ - +lwtunnel_get_encap_size (rt->rt6i_lwtstate); + +lwtunnel_get_encap_size (rt->dst.lwtstate); } static int rt6_fill_node(struct net *net,
@@ -2991,7 +2991,7 @@ static int rt6_fill_node(struct net *net,if (nla_put_u8 (skb,RTA_PREF ,IPV6_EXTRACT_PREF (rt->rt6i_flags))) goto nla_put_failure; -lwtunnel_fill_encap (skb, rt->rt6i_lwtstate); +lwtunnel_fill_encap (skb, rt->dst.lwtstate);nlmsg_end (skb, nlh);return 0 ;
net/mpls/mpls_iptunnel.c +2 -5
@@ -48,7 +48,6 @@ int mpls_output(struct sock *sk, struct sk_buff *skb)struct dst_entry *dst =skb_dst (skb);struct rtable *rt =NULL ;struct rt6_info *rt6 =NULL ; -struct lwtunnel_state *lwtstate =NULL ;int err =0 ;bool bos;int i;
@@ -58,11 +57,9 @@ int mpls_output(struct sock *sk, struct sk_buff *skb)if (skb->protocol ==htons (ETH_P_IP )) { ttl =ip_hdr (skb)->ttl; rt = (struct rtable *)dst; - lwtstate = rt->rt_lwtstate; }else if (skb->protocol ==htons (ETH_P_IPV6 )) { ttl =ipv6_hdr (skb)->hop_limit; rt6 = (struct rt6_info *)dst; - lwtstate = rt6->rt6i_lwtstate; }else { goto drop; }
@@ -72,12 +69,12 @@ int mpls_output(struct sock *sk, struct sk_buff *skb)/* Find the output device */ out_dev = dst->dev;if (!mpls_output_possible (out_dev) || - !lwtstate ||skb_warn_if_lro (skb)) + !dst->lwtstate ||skb_warn_if_lro (skb)) goto drop;skb_forward_csum (skb); - tun_encap_info =mpls_lwtunnel_encap (lwtstate); + tun_encap_info =mpls_lwtunnel_encap (dst->lwtstate);/* Verify the destination can hold the packet */ new_header_size =mpls_encap_size (tun_encap_info);
net/openvswitch/vport-netdev.c +1 -1
@@ -57,7 +57,7 @@ static void netdev_port_receive(struct vport *vport, struct sk_buff *skb)skb_push (skb,ETH_HLEN );ovs_skb_postpush_rcsum (skb, skb->data,ETH_HLEN ); -ovs_vport_receive (vport, skb,skb_tunnel_info (skb,AF_INET )); +ovs_vport_receive (vport, skb,skb_tunnel_info (skb));return ; error:
Signature · 1 line
1.8.3.1
PATCH v3 7/13 ipv6: drop metadata dst in ip6_route_input
In reply to Jiri BencThe fix in commit 48fb6b554501 is incomplete, as now ip6_route_input can be called with non-NULL dst if it's a metadata dst and the reference is leaked. Drop the reference.
--- net/ipv6/route.c | 1 + 1 file changed, 1 insertion(+)
net/ipv6/route.c +1 -0
@@ -1140,6 +1140,7 @@ void ip6_route_input(struct sk_buff *skb) .flowi6_proto = iph->nexthdr, }; +skb_dst_drop (skb);skb_dst_set (skb,ip6_route_input_lookup (net, skb->dev, &fl6, flags)); }
Signature · 1 line
1.8.3.1
PATCH v3 8/13 ipv6: ndisc: inherit metadata dst when creating ndisc requests
In reply to Jiri BencIf output device wants to see the dst, inherit the dst of the original skb in the ndisc request.
This is an IPv6 counterpart of commit 0accfc268f4d ("arp: Inherit metadata dst when creating ARP requests").
--- include/net/ndisc.h | 3 ++- net/ipv6/addrconf.c | 2 +- net/ipv6/ndisc.c | 10 +++++++--- net/ipv6/route.c | 2 +- 4 files changed, 11 insertions(+), 6 deletions(-)
include/net/ndisc.h +2 -1
@@ -182,7 +182,8 @@ int ndisc_rcv(struct sk_buff *skb);void ndisc_send_ns (struct net_device *dev,struct neighbour *neigh,const struct in6_addr *solicit, -const struct in6_addr *daddr,const struct in6_addr *saddr); +const struct in6_addr *daddr,const struct in6_addr *saddr, +struct sk_buff *oskb);void ndisc_send_rs (struct net_device *dev,const struct in6_addr *saddr,const struct in6_addr *daddr);
net/ipv6/addrconf.c +1 -1
@@ -3656,7 +3656,7 @@ static void addrconf_dad_work(struct work_struct *w)/* send a neighbour solicitation for our addr */ addrconf_addr_solict_mult (&ifp->addr, &mcaddr); -ndisc_send_ns (ifp->idev->dev,NULL , &ifp->addr, &mcaddr, &in6addr_any); +ndisc_send_ns (ifp->idev->dev,NULL , &ifp->addr, &mcaddr, &in6addr_any,NULL ); out:in6_ifa_put (ifp);rtnl_unlock ();
net/ipv6/ndisc.c +7 -3
@@ -553,7 +553,8 @@ static void ndisc_send_unsol_na(struct net_device *dev)void ndisc_send_ns (struct net_device *dev,struct neighbour *neigh,const struct in6_addr *solicit, -const struct in6_addr *daddr,const struct in6_addr *saddr) +const struct in6_addr *daddr,const struct in6_addr *saddr, +struct sk_buff *oskb) {struct sk_buff *skb;struct in6_addr addr_buf;
@@ -589,6 +590,9 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,ndisc_fill_addr_option (skb,ND_OPT_SOURCE_LL_ADDR , dev->dev_addr); +if (!(dev->priv_flags &IFF_XMIT_DST_RELEASE ) && oskb) +skb_dst_copy (skb, oskb); +ndisc_send_skb (skb, daddr, saddr); }
@@ -675,12 +679,12 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb)"%s: trying to ucast probe in NUD_INVALID: %pI6\n" , __func__, target); } -ndisc_send_ns (dev, neigh, target, target, saddr); +ndisc_send_ns (dev, neigh, target, target, saddr, skb); }else if ((probes -=NEIGH_VAR (neigh->parms,APP_PROBES )) <0 ) {neigh_app_ns (neigh); }else {addrconf_addr_solict_mult (target, &mcaddr); -ndisc_send_ns (dev,NULL , target, &mcaddr, saddr); +ndisc_send_ns (dev,NULL , target, &mcaddr, saddr, skb); } }
net/ipv6/route.c +1 -1
@@ -538,7 +538,7 @@ static void rt6_probe_deferred(struct work_struct *w) container_of(w, struct __rt6_probe_work, work);addrconf_addr_solict_mult (&work->target, &mcaddr); -ndisc_send_ns (work->dev,NULL , &work->target, &mcaddr,NULL ); +ndisc_send_ns (work->dev,NULL , &work->target, &mcaddr,NULL ,NULL );dev_put (work->dev);kfree (work); }
Signature · 1 line
1.8.3.1
PATCH v3 9/13 vxlan: provide access function for vxlan socket address family
In reply to Jiri Benc--- drivers/net/vxlan.c | 8 ++++---- include/net/vxlan.h | 5 +++++ 2 files changed, 9 insertions(+), 4 deletions(-)
drivers/net/vxlan.c +4 -4
@@ -236,7 +236,7 @@ static struct vxlan_sock *vxlan_find_sock(struct net *net, sa_family_t family,hlist_for_each_entry_rcu (vs,vs_head (net, port), hlist) {if (inet_sk (vs->sock->sk)->inet_sport == port && -inet_sk (vs->sock->sk)->sk.sk_family == family && +vxlan_get_sk_family (vs) == family && vs->flags == flags)return vs; }
@@ -625,7 +625,7 @@ static void vxlan_notify_add_rx_port(struct vxlan_sock *vs)struct net_device *dev;struct sock *sk = vs->sock->sk;struct net *net =sock_net (sk); -sa_family_t sa_family = sk->sk_family; +sa_family_t sa_family =vxlan_get_sk_family (vs);__be16 port =inet_sk (sk)->inet_sport;int err;
@@ -650,7 +650,7 @@ static void vxlan_notify_del_rx_port(struct vxlan_sock *vs)struct net_device *dev;struct sock *sk = vs->sock->sk;struct net *net =sock_net (sk); -sa_family_t sa_family = sk->sk_family; +sa_family_t sa_family =vxlan_get_sk_family (vs);__be16 port =inet_sk (sk)->inet_sport;rcu_read_lock ();
@@ -2390,7 +2390,7 @@ void vxlan_get_rx_port(struct net_device *dev)for (i =0 ; i <PORT_HASH_SIZE ; ++i) {hlist_for_each_entry_rcu (vs, &vn->sock_list[i], hlist) { port =inet_sk (vs->sock->sk)->inet_sport; - sa_family = vs->sock->sk->sk_family; + sa_family =vxlan_get_sk_family (vs); dev->netdev_ops->ndo_add_vxlan_port (dev, sa_family, port); }
include/net/vxlan.h +5 -0
@@ -241,3 +241,8 @@ static inline void vxlan_get_rx_port(struct net_device *netdev) }#endif #endif + +static inline unsigned short vxlan_get_sk_family (struct vxlan_sock *vs) +{ +return vs->sock->sk->sk_family; +}
Signature · 1 line
1.8.3.1
PATCH v3 10/13 vxlan: do not shadow flags variable
In reply to Jiri BencThe 'flags' variable is already defined in the outer scope.
--- drivers/net/vxlan.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/net/vxlan.c +4 -4
@@ -2025,7 +2025,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, }else {struct dst_entry *ndst;struct flowi6 fl6; -u32 flags; +u32 rt6i_flags;memset (&fl6,0 ,sizeof (fl6)); fl6.flowi6_oif = rdst ? rdst->remote_ifindex :0 ;
@@ -2050,9 +2050,9 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, }/* Bypass encapsulation if the destination is local */ - flags = ((struct rt6_info *)ndst)->rt6i_flags; -if (flags &RTF_LOCAL && - !(flags & (RTCF_BROADCAST |RTCF_MULTICAST ))) { + rt6i_flags = ((struct rt6_info *)ndst)->rt6i_flags; +if (rt6i_flags &RTF_LOCAL && + !(rt6i_flags & (RTCF_BROADCAST |RTCF_MULTICAST ))) {struct vxlan_dev *dst_vxlan;dst_release (ndst);
Signature · 1 line
1.8.3.1
PATCH v3 11/13 vxlan: metadata based tunneling for IPv6
In reply to Jiri BencSupport metadata based (formerly flow based) tunneling also for IPv6. This complements commit ee122c79d422 ("vxlan: Flow based tunneling").
--- drivers/net/vxlan.c | 69 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 29 deletions(-)
drivers/net/vxlan.c +40 -29
@@ -1269,17 +1269,27 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb) }if (vxlan_collect_metadata (vs)) { -const struct iphdr *iph =ip_hdr (skb); - tun_dst =metadata_dst_alloc (sizeof (*md),GFP_ATOMIC );if (!tun_dst) goto drop; info = &tun_dst->u.tun_info; - info->key.u.ipv4.src = iph->saddr; - info->key.u.ipv4.dst = iph->daddr; - info->key.tos = iph->tos; - info->key.ttl = iph->ttl; +if (vxlan_get_sk_family (vs) ==AF_INET ) { +const struct iphdr *iph =ip_hdr (skb); + + info->key.u.ipv4.src = iph->saddr; + info->key.u.ipv4.dst = iph->daddr; + info->key.tos = iph->tos; + info->key.ttl = iph->ttl; + }else { +const struct ipv6hdr *ip6h =ipv6_hdr (skb); + + info->key.u.ipv6.src = ip6h->saddr; + info->key.u.ipv6.dst = ip6h->daddr; + info->key.tos =ipv6_get_dsfield (ip6h); + info->key.ttl = ip6h->hop_limit; + } + info->key.tp_src =udp_hdr (skb)->source; info->key.tp_dst =udp_hdr (skb)->dest;
@@ -1894,6 +1904,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,struct ip_tunnel_info *info;struct vxlan_dev *vxlan =netdev_priv (dev);struct sock *sk = vxlan->vn_sock->sock->sk; +unsigned short family =vxlan_get_sk_family (vxlan->vn_sock);struct rtable *rt =NULL ;const struct iphdr *old_iph;struct flowi4 fl4;
@@ -1908,7 +1919,6 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,int err;u32 flags = vxlan->flags; -/* FIXME: Support IPv6 */ info =skb_tunnel_info (skb);if (rdst) {
@@ -1924,8 +1934,11 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, dst_port = info->key.tp_dst ? : vxlan->cfg.dst_port; vni =be64_to_cpu (info->key.tun_id); - remote_ip.sin.sin_family =AF_INET ; - remote_ip.sin.sin_addr.s_addr = info->key.u.ipv4.dst; + remote_ip.sa.sa_family = family; +if (family ==AF_INET ) + remote_ip.sin.sin_addr.s_addr = info->key.u.ipv4.dst; +else + remote_ip.sin6.sin6_addr = info->key.u.ipv6.dst; dst = &remote_ip; }
@@ -1951,23 +1964,24 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, src_port =udp_flow_src_port (dev_net (dev), skb, vxlan->cfg.port_min, vxlan->cfg.port_max, true); +if (info) { +if (info->key.tun_flags &TUNNEL_CSUM ) + flags |=VXLAN_F_UDP_CSUM ; +else + flags &= ~VXLAN_F_UDP_CSUM ; + + ttl = info->key.ttl; + tos = info->key.tos; + +if (info->options_len) + md =ip_tunnel_info_opts (info,sizeof (*md)); + }else { + md->gbp = skb->mark; + } +if (dst->sa.sa_family ==AF_INET ) { -if (info) { -if (info->key.tun_flags &TUNNEL_DONT_FRAGMENT ) - df =htons (IP_DF ); -if (info->key.tun_flags &TUNNEL_CSUM ) - flags |=VXLAN_F_UDP_CSUM ; -else - flags &= ~VXLAN_F_UDP_CSUM ; - - ttl = info->key.ttl; - tos = info->key.tos; - -if (info->options_len) - md =ip_tunnel_info_opts (info,sizeof (*md)); - }else { - md->gbp = skb->mark; - } +if (info && (info->key.tun_flags &TUNNEL_DONT_FRAGMENT )) + df =htons (IP_DF );memset (&fl4,0 ,sizeof (fl4)); fl4.flowi4_oif = rdst ? rdst->remote_ifindex :0 ;
@@ -2066,12 +2080,10 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, } ttl = ttl ? :ip6_dst_hoplimit (ndst); - md->gbp = skb->mark; - err =vxlan6_xmit_skb (ndst, sk, skb, dev, &fl6.saddr, &fl6.daddr,0 , ttl, src_port, dst_port,htonl (vni <<8 ), md, !net_eq (vxlan->net,dev_net (vxlan->dev)), - vxlan->flags); + flags);#endif }
@@ -2104,7 +2116,6 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)struct vxlan_rdst *rdst, *fdst =NULL ;struct vxlan_fdb *f; -/* FIXME: Support IPv6 */ info =skb_tunnel_info (skb);skb_reset_mac_header (skb);
Signature · 1 line
1.8.3.1
PATCH v3 12/13 ipv6: route: extend flow representation with tunnel key
In reply to Jiri BencUse flowi_tunnel in flowi6 similarly to what is done with IPv4. This complements commit 1b7179d3adff ("route: Extend flow representation with tunnel key").
--- include/net/flow.h | 1 + net/ipv6/route.c | 6 ++++++ 2 files changed, 7 insertions(+)
include/net/flow.h +1 -0
@@ -130,6 +130,7 @@ struct flowi6 {#define flowi6_proto __fl_common.flowic_proto#define flowi6_flags __fl_common.flowic_flags#define flowi6_secid __fl_common.flowic_secid +#define flowi6_tun_key __fl_common.flowic_tun_keystruct in6_addr daddr;struct in6_addr saddr;__be32 flowlabel;
net/ipv6/route.c +6 -0
@@ -54,11 +54,13 @@#include <net/tcp.h> #include <linux/rtnetlink.h> #include <net/dst.h> +#include <net/dst_metadata.h> #include <net/xfrm.h> #include <net/netevent.h> #include <net/netlink.h> #include <net/nexthop.h> #include <net/lwtunnel.h> +#include <net/ip_tunnels.h> #include <asm/uaccess.h>
@@ -1131,6 +1133,7 @@ void ip6_route_input(struct sk_buff *skb)const struct ipv6hdr *iph =ipv6_hdr (skb);struct net *net =dev_net (skb->dev);int flags =RT6_LOOKUP_F_HAS_SADDR ; +struct ip_tunnel_info *tun_info;struct flowi6 fl6 = { .flowi6_iif = skb->dev->ifindex, .daddr = iph->daddr,
@@ -1140,6 +1143,9 @@ void ip6_route_input(struct sk_buff *skb) .flowi6_proto = iph->nexthdr, }; + tun_info =skb_tunnel_info (skb); +if (tun_info && tun_info->mode ==IP_TUNNEL_INFO_RX ) + fl6.flowi6_tun_key.tun_id = tun_info->key.tun_id;skb_dst_drop (skb);skb_dst_set (skb,ip6_route_input_lookup (net, skb->dev, &fl6, flags)); }
Signature · 1 line
1.8.3.1
PATCH v3 13/13 ipv6: route: per route IP tunnel metadata via lightweight tunnel
In reply to Jiri BencAllow specification of per route IP tunnel instructions also for IPv6. This complements commit 3093fbe7ff4b ("route: Per route IP tunnel metadata via lightweight tunnel").
---v2->v3: Moved LWTUNNEL_ENCAP_IP6 to the end of the enum.
--- include/uapi/linux/lwtunnel.h | 16 +++++++ net/ipv4/ip_tunnel_core.c | 102 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+)
include/uapi/linux/lwtunnel.h +16 -0
@@ -8,6 +8,7 @@ enum lwtunnel_encap_types {LWTUNNEL_ENCAP_MPLS ,LWTUNNEL_ENCAP_IP ,LWTUNNEL_ENCAP_ILA , +LWTUNNEL_ENCAP_IP6 , __LWTUNNEL_ENCAP_MAX, };
@@ -28,4 +29,19 @@ enum lwtunnel_ip_t {#define LWTUNNEL_IP_MAX (__LWTUNNEL_IP_MAX - 1) +enum lwtunnel_ip6_t { +LWTUNNEL_IP6_UNSPEC , +LWTUNNEL_IP6_ID , +LWTUNNEL_IP6_DST , +LWTUNNEL_IP6_SRC , +LWTUNNEL_IP6_HOPLIMIT , +LWTUNNEL_IP6_TC , +LWTUNNEL_IP6_SPORT , +LWTUNNEL_IP6_DPORT , +LWTUNNEL_IP6_FLAGS , + __LWTUNNEL_IP6_MAX, +}; + +#define LWTUNNEL_IP6_MAX (__LWTUNNEL_IP6_MAX - 1) +#endif /* _UAPI_LWTUNNEL_H_ */
net/ipv4/ip_tunnel_core.c +102 -0
111 lines not on this page · raw message
Signature · 1 line
1.8.3.1
David Miller
maintainerFrom: Jiri Benc <[email protected]>
Date: Thu, 20 Aug 2015 13:56:19 +0200
Quoted 8 lines
v3: Moved
LWTUNNEL_ENCAP_IP6definition in patch 13.
v2: Fixed issues in patch 4 pointed out by Alexei.This series enables IPv6 tunnels based on lwtunnel infrastructure. Only vxlan is supported for now.
Tested in all combinations of IPv4 over IPv6, IPv6 over IPv4 and IPv6 over IPv6.
Looks good, series applied, thanks!