[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(ð_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(ð_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(ð_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