[ovs-dev] [PATCH 13/15] ofproto-dpif-xlate: Support IPv6 when sending to tunnel

Flavio Leitner fbl at sysclose.org
Thu Nov 12 04:30:13 UTC 2015


On Thu, Oct 22, 2015 at 03:29:06PM -0200, Thadeu Lima de Souza Cascardo wrote:
> When doing push/pop and building tunnel header, do IPv6 route lookups and send
> Neighbor Solicitations if needed.
> 
> Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo at redhat.com>
> ---
>  lib/packets.h                |  22 +++++++
>  ofproto/ofproto-dpif-xlate.c | 136 +++++++++++++++++++++++++++++++++----------
>  2 files changed, 126 insertions(+), 32 deletions(-)
> 
> diff --git a/lib/packets.h b/lib/packets.h
> index 2b01d9d..9dbbe4c 100644
> --- a/lib/packets.h
> +++ b/lib/packets.h
> @@ -918,6 +918,28 @@ static inline bool ipv6_addr_is_multicast(const struct in6_addr *ip) {
>  }
>  
>  static inline void
> +in6_addr_solicited_node(struct in6_addr *addr, const struct in6_addr *ip6)
> +{
> +    union ovs_16aligned_in6_addr *taddr = (void *) addr;
> +    memset(taddr->be16, 0, sizeof(taddr->be16));
> +    taddr->be16[0] = htons(0xff02);
> +    taddr->be16[5] = htons(0x1);
> +    taddr->be16[6] = htons(0xff00);
> +    memcpy(&addr->s6_addr[13], &ip6->s6_addr[13], 3);
> +}
> +
> +static inline void
> +ipv6_multicast_to_ethernet(struct eth_addr *eth, const struct in6_addr *ip6)
> +{
> +    eth->ea[0] = 0x33;
> +    eth->ea[1] = 0x33;
> +    eth->ea[2] = ip6->s6_addr[12];
> +    eth->ea[3] = ip6->s6_addr[13];
> +    eth->ea[4] = ip6->s6_addr[14];
> +    eth->ea[5] = ip6->s6_addr[15];
> +}
> +
> +static inline void
>  in6_addr_set_mapped_ipv4(struct in6_addr *addr, ovs_be32 ip4)
>  {
>      union ovs_16aligned_in6_addr *taddr = (void *) addr;
> diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
> index 8552396..5b47a20 100644
> --- a/ofproto/ofproto-dpif-xlate.c
> +++ b/ofproto/ofproto-dpif-xlate.c
> @@ -21,6 +21,7 @@
>  #include <net/if.h>
>  #include <sys/socket.h>
>  #include <netinet/in.h>
> +#include <netinet/icmp6.h>
>  
>  #include "tnl-arp-cache.h"
>  #include "bfd.h"
> @@ -54,6 +55,7 @@
>  #include "ofproto/ofproto-dpif-sflow.h"
>  #include "ofproto/ofproto-dpif.h"
>  #include "ofproto/ofproto-provider.h"
> +#include "packets.h"
>  #include "ovs-router.h"
>  #include "tnl-ports.h"
>  #include "tunnel.h"
> @@ -2659,21 +2661,24 @@ process_special(struct xlate_ctx *ctx, const struct xport *xport)
>  
>  static int
>  tnl_route_lookup_flow(const struct flow *oflow,
> -                      ovs_be32 *ip, struct xport **out_port)
> +                      struct in6_addr *ip, struct xport **out_port)
>  {
>      char out_dev[IFNAMSIZ];
>      struct xbridge *xbridge;
>      struct xlate_cfg *xcfg;
> -    ovs_be32 gw;
> +    struct in6_addr gw;
> +    struct in6_addr dst;
>  
> -    if (!ovs_router_lookup4(oflow->tunnel.ip_dst, out_dev, &gw)) {
> +    dst = flow_tnl_dst(&oflow->tunnel);
> +    if (!ovs_router_lookup(&dst, out_dev, &gw)) {
>          return -ENOENT;
>      }
>  
> -    if (gw) {
> +    if (ipv6_addr_is_set(&gw) &&
> +        (!IN6_IS_ADDR_V4MAPPED(&gw) || in6_addr_get_mapped_ipv4(&gw))) {
>          *ip = gw;
>      } else {
> -        *ip = oflow->tunnel.ip_dst;
> +        *ip = dst;
>      }
>  
>      xcfg = ovsrcu_get(struct xlate_cfg *, &xcfgp);
> @@ -2714,6 +2719,44 @@ compose_table_xlate(struct xlate_ctx *ctx, const struct xport *out_dev,
>  }
>  
>  static void
> +tnl_send_nd_request(struct xlate_ctx *ctx, const struct xport *out_dev,
> +                     const struct eth_addr eth_src,
> +                     struct in6_addr * ipv6_src, struct in6_addr * ipv6_dst)
> +{
> +    struct dp_packet packet;
> +    struct in6_addr sn_addr;
> +    struct eth_addr eth_dst;
> +    struct ovs_nd_msg *ns;
> +    struct ovs_nd_opt *nd_opt;
> +
> +    in6_addr_solicited_node(&sn_addr, ipv6_dst);
> +    ipv6_multicast_to_ethernet(&eth_dst, &sn_addr);
> +
> +    dp_packet_init(&packet, 0);
> +    dp_packet_clear(&packet);
> +
> +    eth_compose(&packet, eth_dst, eth_src, ETH_TYPE_IPV6,
> +                IPV6_HEADER_LEN + ICMP6_HEADER_LEN + ND_OPT_LEN);
> +    packet_set_ipv6(&packet, IPPROTO_ICMPV6,
> +                    ALIGNED_CAST(ovs_be32 *, ipv6_src->s6_addr),
> +                    ALIGNED_CAST(ovs_be32 *, sn_addr.s6_addr),
> +                    0, 0, 255);
> +
> +    ns = dp_packet_l4(&packet);
> +    nd_opt = &ns->options[0];
> +
> +    ns->icmph.icmp6_type = ND_NEIGHBOR_SOLICIT;
> +    ns->icmph.icmp6_code = 0;
> +
> +    nd_opt->nd_opt_type = ND_OPT_SOURCE_LINKADDR;
> +    packet_set_nd(&packet, ALIGNED_CAST(ovs_be32 *, ipv6_dst->s6_addr),
> +                  eth_src, eth_addr_zero);
> +
> +    compose_table_xlate(ctx, out_dev, &packet);
> +    dp_packet_uninit(&packet);
> +}
> +
> +static void

Looks like it could build ND in packet.c
(not tested)

diff --git a/lib/packets.c b/lib/packets.c
index 25fdbd3..1432f4a 100644
--- a/lib/packets.c
+++ b/lib/packets.c
@@ -1119,6 +1119,39 @@ compose_arp(struct dp_packet *b, uint16_t arp_op,
     dp_packet_set_l3(b, arp);
 }
 
+void
+compose_nd(struct dp_packet *b, const struct eth_addr eth_src,
+           struct in6_addr * ipv6_src, struct in6_addr * ipv6_dst)
+{
+    struct in6_addr sn_addr;
+    struct eth_addr eth_dst;
+    struct ovs_nd_msg *ns;
+    struct ovs_nd_opt *nd_opt;
+
+    in6_addr_solicited_node(&sn_addr, ipv6_dst);
+    ipv6_multicast_to_ethernet(&eth_dst, &sn_addr);
+
+    dp_packet_init(b, 0);
+    dp_packet_clear(b);
+
+    eth_compose(b, eth_dst, eth_src, ETH_TYPE_IPV6,
+                IPV6_HEADER_LEN + ICMP6_HEADER_LEN + ND_OPT_LEN);
+    packet_set_ipv6(b, IPPROTO_ICMPV6,
+                    ALIGNED_CAST(ovs_be32 *, ipv6_src->s6_addr),
+                    ALIGNED_CAST(ovs_be32 *, ipv6_dst->s6_addr),
+                    0, 0, 255);
+ 
+    ns = dp_packet_l4(b);
+    nd_opt = &ns->options[0];
+
+    ns->icmph.icmp6_type = ND_NEIGHBOR_SOLICIT;
+    ns->icmph.icmp6_code = 0;
+
+    nd_opt->nd_opt_type = ND_OPT_SOURCE_LINKADDR;
+    packet_set_nd(b, ALIGNED_CAST(ovs_be32 *, ipv6_dst->s6_addr),
+                  eth_src, eth_addr_zero);
+}
+
 uint32_t
 packet_csum_pseudoheader(const struct ip_header *ip)
 {
diff --git a/lib/packets.h b/lib/packets.h
index f43648d..818bd03 100644
--- a/lib/packets.h
+++ b/lib/packets.h
@@ -1025,6 +1025,8 @@ void compose_arp(struct dp_packet *, uint16_t arp_op,
                  const struct eth_addr arp_sha,
                  const struct eth_addr arp_tha, bool broadcast,
                  ovs_be32 arp_spa, ovs_be32 arp_tpa);
+void compose_nd(struct dp_packet *, const struct eth_addr eth_src,
+                struct in6_addr *, struct in6_addr *);
 uint32_t packet_csum_pseudoheader(const struct ip_header *);
 
 #endif /* packets.h */
diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
index 0381c8a..baa5ad1 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -21,7 +21,6 @@
 #include <net/if.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
-#include <netinet/icmp6.h>
 
 #include "tnl-arp-cache.h"
 #include "bfd.h"
@@ -2724,34 +2723,9 @@ tnl_send_nd_request(struct xlate_ctx *ctx, const struct xport *out_dev,
                      struct in6_addr * ipv6_src, struct in6_addr * ipv6_dst)
 {
     struct dp_packet packet;
-    struct in6_addr sn_addr;
-    struct eth_addr eth_dst;
-    struct ovs_nd_msg *ns;
-    struct ovs_nd_opt *nd_opt;
-
-    in6_addr_solicited_node(&sn_addr, ipv6_dst);
-    ipv6_multicast_to_ethernet(&eth_dst, &sn_addr);
 
     dp_packet_init(&packet, 0);
-    dp_packet_clear(&packet);
-
-    eth_compose(&packet, eth_dst, eth_src, ETH_TYPE_IPV6,
-                IPV6_HEADER_LEN + ICMP6_HEADER_LEN + ND_OPT_LEN);
-    packet_set_ipv6(&packet, IPPROTO_ICMPV6,
-                    ALIGNED_CAST(ovs_be32 *, ipv6_src->s6_addr),
-                    ALIGNED_CAST(ovs_be32 *, sn_addr.s6_addr),
-                    0, 0, 255);
-
-    ns = dp_packet_l4(&packet);
-    nd_opt = &ns->options[0];
-
-    ns->icmph.icmp6_type = ND_NEIGHBOR_SOLICIT;
-    ns->icmph.icmp6_code = 0;
-
-    nd_opt->nd_opt_type = ND_OPT_SOURCE_LINKADDR;
-    packet_set_nd(&packet, ALIGNED_CAST(ovs_be32 *, ipv6_dst->s6_addr),
-                  eth_src, eth_addr_zero);
-
+    compose_nd(&packet, eth_src, ipv6_src, ipv6_dst);
     compose_table_xlate(ctx, out_dev, &packet);
     dp_packet_uninit(&packet);
 }


fbl




More information about the dev mailing list