summaryrefslogtreecommitdiffstats
path: root/src/vnet/gre/gre.c
diff options
context:
space:
mode:
authorNeale Ranns <nranns@cisco.com>2019-04-18 10:23:56 +0000
committerOle Trøan <otroan@employees.org>2019-12-04 22:45:11 +0000
commit5f8f6173328f8d77feea5fd100e150c3094c11f0 (patch)
tree16849c6e7619b227a93ce9846f344da2cc96ef2d /src/vnet/gre/gre.c
parent79619c10142e15754e2f0b2ba26c20d415e7c36f (diff)
gre: Multi-point interfaces
Type: feature Change-Id: I0129ad6ace44a50a8a3b26db8e445cd06b2b49e8 Signed-off-by: Neale Ranns <nranns@cisco.com>
Diffstat (limited to 'src/vnet/gre/gre.c')
-rw-r--r--src/vnet/gre/gre.c61
1 files changed, 57 insertions, 4 deletions
diff --git a/src/vnet/gre/gre.c b/src/vnet/gre/gre.c
index 4f16b5db387..f06f19fab2a 100644
--- a/src/vnet/gre/gre.c
+++ b/src/vnet/gre/gre.c
@@ -18,6 +18,7 @@
#include <vnet/vnet.h>
#include <vnet/gre/gre.h>
#include <vnet/adj/adj_midchain.h>
+#include <vnet/nhrp/nhrp.h>
extern gre_main_t gre_main;
@@ -213,6 +214,7 @@ gre_build_rewrite (vnet_main_t * vnm,
vnet_link_t link_type, const void *dst_address)
{
gre_main_t *gm = &gre_main;
+ const ip46_address_t *dst;
ip4_and_gre_header_t *h4;
ip6_and_gre_header_t *h6;
gre_header_t *gre;
@@ -221,6 +223,7 @@ gre_build_rewrite (vnet_main_t * vnm,
u32 ti;
u8 is_ipv6;
+ dst = dst_address;
ti = gm->tunnel_index_by_sw_if_index[sw_if_index];
if (~0 == ti)
@@ -241,7 +244,7 @@ gre_build_rewrite (vnet_main_t * vnm,
h4->ip4.protocol = IP_PROTOCOL_GRE;
/* fixup ip4 header length and checksum after-the-fact */
h4->ip4.src_address.as_u32 = t->tunnel_src.ip4.as_u32;
- h4->ip4.dst_address.as_u32 = t->tunnel_dst.fp_addr.ip4.as_u32;
+ h4->ip4.dst_address.as_u32 = dst->ip4.as_u32;
h4->ip4.checksum = ip4_header_checksum (&h4->ip4);
}
else
@@ -256,8 +259,8 @@ gre_build_rewrite (vnet_main_t * vnm,
/* fixup ip6 header length and checksum after-the-fact */
h6->ip6.src_address.as_u64[0] = t->tunnel_src.ip6.as_u64[0];
h6->ip6.src_address.as_u64[1] = t->tunnel_src.ip6.as_u64[1];
- h6->ip6.dst_address.as_u64[0] = t->tunnel_dst.fp_addr.ip6.as_u64[0];
- h6->ip6.dst_address.as_u64[1] = t->tunnel_dst.fp_addr.ip6.as_u64[1];
+ h6->ip6.dst_address.as_u64[0] = dst->ip6.as_u64[0];
+ h6->ip6.dst_address.as_u64[1] = dst->ip6.as_u64[1];
}
if (PREDICT_FALSE (t->type == GRE_TUNNEL_TYPE_ERSPAN))
@@ -322,10 +325,51 @@ gre_update_adj (vnet_main_t * vnm, u32 sw_if_index, adj_index_t ai)
adj_nbr_midchain_update_rewrite
(ai, !is_ipv6 ? gre4_fixup : gre6_fixup, NULL, af,
- gre_build_rewrite (vnm, sw_if_index, adj_get_link_type (ai), NULL));
+ gre_build_rewrite (vnm, sw_if_index, adj_get_link_type (ai),
+ &t->tunnel_dst.fp_addr));
gre_tunnel_stack (ai);
}
+
+static adj_walk_rc_t
+mgre_mk_complete_walk (adj_index_t ai, void *ctx)
+{
+ nhrp_entry_adj_stack (ctx, ai);
+
+ return (ADJ_WALK_RC_CONTINUE);
+}
+
+void
+mgre_update_adj (vnet_main_t * vnm, u32 sw_if_index, adj_index_t ai)
+{
+ gre_main_t *gm = &gre_main;
+ ip_adjacency_t *adj;
+ nhrp_entry_t *ne;
+ gre_tunnel_t *t;
+ adj_flags_t af;
+ u8 is_ipv6;
+ u32 ti;
+
+ adj = adj_get (ai);
+ ti = gm->tunnel_index_by_sw_if_index[sw_if_index];
+ t = pool_elt_at_index (gm->tunnels, ti);
+ is_ipv6 = t->tunnel_dst.fp_proto == FIB_PROTOCOL_IP6 ? 1 : 0;
+ af = ADJ_FLAG_MIDCHAIN_IP_STACK;
+
+ adj_nbr_midchain_update_rewrite
+ (ai, !is_ipv6 ? gre4_fixup : gre6_fixup, NULL, af,
+ gre_build_rewrite (vnm, sw_if_index, adj_get_link_type (ai),
+ &adj->sub_type.nbr.next_hop));
+
+ ne = nhrp_entry_find (sw_if_index, &adj->sub_type.nbr.next_hop);
+
+ if (NULL == ne)
+ // no NHRP entry to provide the next-hop
+ return;
+
+ adj_nbr_walk_nh (sw_if_index, t->tunnel_dst.fp_proto,
+ &adj->sub_type.nbr.next_hop, mgre_mk_complete_walk, ne);
+}
#endif /* CLIB_MARCH_VARIANT */
typedef enum
@@ -574,6 +618,15 @@ VNET_HW_INTERFACE_CLASS (gre_hw_interface_class) = {
.update_adjacency = gre_update_adj,
.flags = VNET_HW_INTERFACE_CLASS_FLAG_P2P,
};
+
+VNET_HW_INTERFACE_CLASS (mgre_hw_interface_class) = {
+ .name = "mGRE",
+ .format_header = format_gre_header_with_length,
+ .unformat_header = unformat_gre_header,
+ .build_rewrite = gre_build_rewrite,
+ .update_adjacency = mgre_update_adj,
+ .flags = VNET_HW_INTERFACE_CLASS_FLAG_NBMA,
+};
/* *INDENT-ON* */
#endif /* CLIB_MARCH_VARIANT */