summaryrefslogtreecommitdiffstats
path: root/plugins
diff options
context:
space:
mode:
authorNeale Ranns <nranns@cisco.com>2016-08-25 15:29:12 +0100
committerDamjan Marion <dmarion.lists@gmail.com>2016-09-21 17:37:39 +0000
commit0bfe5d8c792abcdbcf27bfcc7b7b353fba04aee2 (patch)
treed600b0e2e693e766e722936744930d3bebac493c /plugins
parent60537f3d83e83d0ce10a620ca99aad4eddf85f5e (diff)
A Protocol Independent Hierarchical FIB (VPP-352)
Main Enhancements: - Protocol Independent FIB API - Hierarchical FIB entries. Dynamic recursive route resolution. - Extranet Support. - Integration of IP and MPLS forwarding. - Separation of FIB and Adjacency databases. - Data-Plane Object forwarding model. Change-Id: I52dc815c0d0aa8b493e3cf6b978568f3cc82296c Signed-off-by: Neale Ranns <nranns@cisco.com>
Diffstat (limited to 'plugins')
-rw-r--r--plugins/ila-plugin/ila/ila.c390
-rw-r--r--plugins/ila-plugin/ila/ila.h27
-rw-r--r--plugins/lb-plugin/lb/lb.c214
-rw-r--r--plugins/lb-plugin/lb/node.c58
-rw-r--r--plugins/sixrd-plugin/Makefile.am4
-rw-r--r--plugins/sixrd-plugin/sixrd/sixrd.c218
-rw-r--r--plugins/sixrd-plugin/sixrd/sixrd.h55
-rw-r--r--plugins/sixrd-plugin/sixrd/sixrd_dpo.c132
-rw-r--r--plugins/sixrd-plugin/sixrd/sixrd_dpo.h61
-rw-r--r--plugins/vcgn-plugin/vcgn/vcgn_classify.c2
10 files changed, 734 insertions, 427 deletions
diff --git a/plugins/ila-plugin/ila/ila.c b/plugins/ila-plugin/ila/ila.c
index 99d1db8a047..029dd219467 100644
--- a/plugins/ila-plugin/ila/ila.c
+++ b/plugins/ila-plugin/ila/ila.c
@@ -16,6 +16,8 @@
#include <ila/ila.h>
#include <vnet/plugin/plugin.h>
#include <vnet/ip/lookup.h>
+#include <vnet/dpo/dpo.h>
+#include <vnet/fib/fib_table.h>
static ila_main_t ila_main;
@@ -39,7 +41,6 @@ static char *ila_error_strings[] = {
};
typedef enum {
- ILA_ILA2SIR_NEXT_IP6_REWRITE,
ILA_ILA2SIR_NEXT_DROP,
ILA_ILA2SIR_N_NEXT,
} ila_ila2sir_next_t;
@@ -56,6 +57,16 @@ static ila_entry_t ila_sir2ila_default_entry = {
.dir = ILA_DIR_ILA2SIR, //Will pass the packet with no
};
+/**
+ * @brief Dynamically registered DPO Type for ILA
+ */
+static dpo_type_t ila_dpo_type;
+
+/**
+ * @brief Dynamically registered FIB node type for ILA
+ */
+static fib_node_type_t ila_fib_node_type;
+
u8 *
format_half_ip6_address (u8 * s, va_list * va)
{
@@ -120,28 +131,29 @@ format_ila_entry (u8 * s, va_list * va)
if (!e)
{
return format (s, "%-15s%=40s%=40s%+16s%+18s%+11s", "Type", "SIR Address",
- "ILA Address", "Adjacency Index", "Checksum Mode", "Direction");
-
+ "ILA Address", "Checksum Mode", "Direction", "Next DPO");
}
else if (vnm)
{
- if (e->ila_adj_index == ~0)
+ if (ip6_address_is_zero(&e->next_hop))
{
- return format (s, "%-15U%=40U%=40U%16s%18U%11U",
+ return format (s, "%-15U%=40U%=40U%18U%11U%s",
format_ila_type, e->type,
format_ip6_address, &e->sir_address,
format_ip6_address, &e->ila_address,
- "n/a", format_csum_mode, e->csum_mode,
- format_ila_direction, e->dir);
+ format_csum_mode, e->csum_mode,
+ format_ila_direction, e->dir,
+ "n/a");
}
else
{
- return format (s, "%-15U%=40U%=40U%16d%18U%11U",
+ return format (s, "%-15U%=40U%=40U%18U%11U%U",
format_ila_type, e->type,
format_ip6_address, &e->sir_address,
format_ip6_address, &e->ila_address,
- e->ila_adj_index, format_csum_mode, e->csum_mode,
- format_ila_direction, e->dir);
+ format_csum_mode, e->csum_mode,
+ format_ila_direction, e->dir,
+ format_dpo_id, &e->ila_dpo, 0);
}
}
@@ -239,8 +251,6 @@ static uword
ila_ila2sir (vlib_main_t * vm,
vlib_node_runtime_t * node, vlib_frame_t * frame)
{
- ip6_main_t *im = &ip6_main;
- ip_lookup_main_t *lm = &im->lookup_main;
u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
ila_main_t *ilm = &ila_main;
@@ -256,10 +266,8 @@ ila_ila2sir (vlib_main_t * vm,
{
u32 pi0, pi1;
vlib_buffer_t *p0, *p1;
- ip_adjacency_t *adj0, *adj1;
ila_entry_t *ie0, *ie1;
ip6_header_t *ip60, *ip61;
- ila_adj_data_t *ad0, *ad1;
ip6_address_t *sir_address0, *sir_address1;
{
@@ -287,14 +295,10 @@ ila_ila2sir (vlib_main_t * vm,
ip61 = vlib_buffer_get_current (p1);
sir_address0 = &ip60->dst_address;
sir_address1 = &ip61->dst_address;
- adj0 =
- ip_get_adjacency (lm, vnet_buffer (p0)->ip.adj_index[VLIB_TX]);
- adj1 =
- ip_get_adjacency (lm, vnet_buffer (p1)->ip.adj_index[VLIB_TX]);
- ad0 = (ila_adj_data_t *) & adj0->opaque;
- ad1 = (ila_adj_data_t *) & adj1->opaque;
- ie0 = pool_elt_at_index (ilm->entries, ad0->entry_index);
- ie1 = pool_elt_at_index (ilm->entries, ad1->entry_index);
+ ie0 = pool_elt_at_index (ilm->entries,
+ vnet_buffer (p0)->ip.adj_index[VLIB_TX]);
+ ie1 = pool_elt_at_index (ilm->entries,
+ vnet_buffer (p1)->ip.adj_index[VLIB_TX]);
if (PREDICT_FALSE (p0->flags & VLIB_BUFFER_IS_TRACED))
{
@@ -321,13 +325,13 @@ ila_ila2sir (vlib_main_t * vm,
ip61->dst_address.as_u64[0] = sir_address1->as_u64[0];
ip61->dst_address.as_u64[1] = sir_address1->as_u64[1];
- vnet_buffer (p0)->ip.adj_index[VLIB_TX] = ie0->ila_adj_index;
- vnet_buffer (p1)->ip.adj_index[VLIB_TX] = ie1->ila_adj_index;
+ vnet_buffer (p0)->ip.adj_index[VLIB_TX] = ie0->ila_dpo.dpoi_index;
+ vnet_buffer (p1)->ip.adj_index[VLIB_TX] = ie1->ila_dpo.dpoi_index;
vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
n_left_to_next, pi0, pi1,
- ILA_ILA2SIR_NEXT_IP6_REWRITE,
- ILA_ILA2SIR_NEXT_IP6_REWRITE);
+ ie0->ila_dpo.dpoi_next_node,
+ ie1->ila_dpo.dpoi_next_node);
}
/* Single loop */
@@ -335,8 +339,6 @@ ila_ila2sir (vlib_main_t * vm,
{
u32 pi0;
vlib_buffer_t *p0;
- ip_adjacency_t *adj0;
- ila_adj_data_t *ad0;
ila_entry_t *ie0;
ip6_header_t *ip60;
ip6_address_t *sir_address0;
@@ -350,10 +352,8 @@ ila_ila2sir (vlib_main_t * vm,
p0 = vlib_get_buffer (vm, pi0);
ip60 = vlib_buffer_get_current (p0);
sir_address0 = &ip60->dst_address;
- adj0 =
- ip_get_adjacency (lm, vnet_buffer (p0)->ip.adj_index[VLIB_TX]);
- ad0 = (ila_adj_data_t *) & adj0->opaque;
- ie0 = pool_elt_at_index (ilm->entries, ad0->entry_index);
+ ie0 = pool_elt_at_index (ilm->entries,
+ vnet_buffer (p0)->ip.adj_index[VLIB_TX]);
if (PREDICT_FALSE (p0->flags & VLIB_BUFFER_IS_TRACED))
{
@@ -367,11 +367,11 @@ ila_ila2sir (vlib_main_t * vm,
sir_address0 = (ie0->dir != ILA_DIR_SIR2ILA) ? &ie0->sir_address : sir_address0;
ip60->dst_address.as_u64[0] = sir_address0->as_u64[0];
ip60->dst_address.as_u64[1] = sir_address0->as_u64[1];
- vnet_buffer (p0)->ip.adj_index[VLIB_TX] = ie0->ila_adj_index;
+ vnet_buffer (p0)->ip.adj_index[VLIB_TX] = ie0->ila_dpo.dpoi_index;
vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
n_left_to_next, pi0,
- ILA_ILA2SIR_NEXT_IP6_REWRITE);
+ ie0->ila_dpo.dpoi_next_node);
}
vlib_put_next_frame (vm, node, next_index, n_left_to_next);
}
@@ -379,16 +379,22 @@ ila_ila2sir (vlib_main_t * vm,
return frame->n_vectors;
}
+/** *INDENT-OFF* */
VLIB_REGISTER_NODE (ila_ila2sir_node, static) =
{
- .function = ila_ila2sir,.name = "ila-to-sir",.vector_size =
- sizeof (u32),.format_trace = format_ila_ila2sir_trace,.n_errors =
- ILA_N_ERROR,.error_strings = ila_error_strings,.n_next_nodes =
- ILA_ILA2SIR_N_NEXT,.next_nodes =
+ .function = ila_ila2sir,
+ .name = "ila-to-sir",
+ .vector_size = sizeof (u32),
+ .format_trace = format_ila_ila2sir_trace,
+ .n_errors = ILA_N_ERROR,
+ .error_strings = ila_error_strings,
+ .n_next_nodes = ILA_ILA2SIR_N_NEXT,
+ .next_nodes =
{
- [ILA_ILA2SIR_NEXT_IP6_REWRITE] = "ip6-rewrite",
- [ILA_ILA2SIR_NEXT_DROP] = "error-drop"}
-,};
+ [ILA_ILA2SIR_NEXT_DROP] = "error-drop"
+ },
+};
+/** *INDENT-ON* */
typedef enum
{
@@ -580,28 +586,48 @@ ila_sir2ila (vlib_main_t * vm,
return frame->n_vectors;
}
+/** *INDENT-OFF* */
VLIB_REGISTER_NODE (ila_sir2ila_node, static) =
{
- .function = ila_sir2ila,.name = "sir-to-ila",.vector_size =
- sizeof (u32),.format_trace = format_ila_sir2ila_trace,.n_errors =
- ILA_N_ERROR,.error_strings = ila_error_strings,.n_next_nodes =
- ILA_SIR2ILA_N_NEXT,.next_nodes =
+ .function = ila_sir2ila,.name = "sir-to-ila",
+ .vector_size = sizeof (u32),
+ .format_trace = format_ila_sir2ila_trace,
+ .n_errors = ILA_N_ERROR,
+ .error_strings = ila_error_strings,
+ .n_next_nodes = ILA_SIR2ILA_N_NEXT,
+ .next_nodes =
{
- [ILA_SIR2ILA_NEXT_DROP] = "error-drop"}
-,};
+ [ILA_SIR2ILA_NEXT_DROP] = "error-drop"
+ },
+};
+/** *INDENT-ON* */
+/** *INDENT-OFF* */
VNET_IP6_UNICAST_FEATURE_INIT (ila_sir2ila, static) =
{
.node_name = "sir-to-ila",
.runs_before = ORDER_CONSTRAINTS{"ip6-lookup", 0},
.feature_index = &ila_main.ila_sir2ila_feature_index,
};
+/** *INDENT-ON* */
+
+static void
+ila_entry_stack (ila_entry_t *ie)
+{
+ /*
+ * restack on the next-hop's FIB entry
+ */
+ dpo_stack(ila_dpo_type,
+ DPO_PROTO_IP6,
+ &ie->ila_dpo,
+ fib_entry_contribute_ip_forwarding(
+ ie->next_hop_fib_entry_index));
+}
int
ila_add_del_entry (ila_add_del_entry_args_t * args)
{
ila_main_t *ilm = &ila_main;
- ip6_main_t *im6 = &ip6_main;
BVT (clib_bihash_kv) kv, value;
//Sanity check
@@ -642,7 +668,7 @@ ila_add_del_entry (ila_add_del_entry_args_t * args)
pool_get (ilm->entries, e);
e->type = args->type;
e->sir_address = args->sir_address;
- e->ila_adj_index = args->local_adj_index;
+ e->next_hop = args->next_hop_address;
e->csum_mode = args->csum_mode;
e->dir = args->dir;
@@ -698,31 +724,56 @@ ila_add_del_entry (ila_add_del_entry_args_t * args)
BV (clib_bihash_add_del) (&ilm->id_to_entry_table, &kv,
1 /* is_add */ );
- if (e->ila_adj_index != ~0)
+ if (!ip6_address_is_zero(&e->next_hop))
{
- //This is a local entry - let's create a local adjacency
- ip_adjacency_t adj;
- ip6_add_del_route_args_t route_args;
- ila_adj_data_t *ad;
-
- //Adjacency
- memset (&adj, 0, sizeof (adj));
- adj.explicit_fib_index = ~0;
- adj.lookup_next_index = ilm->ip6_lookup_next_index;
- ad = (ila_adj_data_t *) & adj.opaque;
- ad->entry_index = e - ilm->entries;
-
- //Route
- memset (&route_args, 0, sizeof (route_args));
- route_args.table_index_or_table_id = 0;
- route_args.flags = IP6_ROUTE_FLAG_ADD;
- route_args.dst_address = e->ila_address;
- route_args.dst_address_length = 128;
- route_args.adj_index = ~0;
- route_args.add_adj = &adj;
- route_args.n_add_adj = 1;
-
- ip6_add_del_route (im6, &route_args);
+ /*
+ * become a child of the FIB netry for the next-hop
+ * so we are informed when its forwarding changes
+ */
+ fib_prefix_t next_hop = {
+ .fp_addr = {
+ .ip6 = e->next_hop,
+ },
+ .fp_len = 128,
+ .fp_proto = FIB_PROTOCOL_IP6,
+ };
+
+ e->next_hop_fib_entry_index =
+ fib_table_entry_special_add(0,
+ &next_hop,
+ FIB_SOURCE_RR,
+ FIB_ENTRY_FLAG_NONE,
+ ADJ_INDEX_INVALID);
+ e->next_hop_child_index =
+ fib_entry_child_add(e->next_hop_fib_entry_index,
+ ila_fib_node_type,
+ e - ilm->entries);
+
+ /*
+ * Create a route that results in the ILA entry
+ */
+ dpo_id_t dpo = DPO_NULL;
+ fib_prefix_t pfx = {
+ .fp_addr = {
+ .ip6 = e->ila_address,
+ },
+ .fp_len = 128,
+ .fp_proto = FIB_PROTOCOL_IP6,
+ };
+
+ dpo_set(&dpo, ila_dpo_type, DPO_PROTO_IP6, e - ilm->entries);
+
+ fib_table_entry_special_dpo_add(0,
+ &pfx,
+ FIB_SOURCE_PLUGIN_HI,
+ FIB_ENTRY_FLAG_EXCLUSIVE,
+ &dpo);
+ dpo_reset(&dpo);
+
+ /*
+ * finally stack the ILA entry so it will forward to the next-hop
+ */
+ ila_entry_stack (e);
}
}
else
@@ -740,21 +791,27 @@ ila_add_del_entry (ila_add_del_entry_args_t * args)
e = &ilm->entries[value.value];
- if (e->ila_adj_index != ~0)
+ if (!ip6_address_is_zero(&e->next_hop))
{
- //Delete that route - Associated adjacency will be deleted too
- ip6_add_del_route_args_t route_args;
- memset (&route_args, 0, sizeof (route_args));
- route_args.table_index_or_table_id = 0;
- route_args.flags = IP6_ROUTE_FLAG_DEL;
- route_args.dst_address = e->ila_address;
- route_args.dst_address_length = 128;
- route_args.adj_index = ~0;
- route_args.add_adj = NULL;
- route_args.n_add_adj = 0;
-
- ip6_add_del_route (im6, &route_args);
+ fib_prefix_t pfx = {
+ .fp_addr = {
+ .ip6 = e->ila_address,
+ },
+ .fp_len = 128,
+ .fp_proto = FIB_PROTOCOL_IP6,
+ };
+
+ fib_table_entry_special_remove(0, &pfx, FIB_SOURCE_PLUGIN_HI);
+ /*
+ * remove this ILA entry as child of the FIB netry for the next-hop
+ */
+ fib_entry_child_remove(e->next_hop_fib_entry_index,
+ e->next_hop_child_index);
+ fib_table_entry_delete_index(e->next_hop_fib_entry_index,
+ FIB_SOURCE_RR);
+ e->next_hop_fib_entry_index = FIB_NODE_INDEX_INVALID;
}
+ dpo_reset (&e->ila_dpo);
BV (clib_bihash_add_del) (&ilm->id_to_entry_table, &kv,
0 /* is_add */ );
@@ -796,24 +853,103 @@ vlib_plugin_register (vlib_main_t * vm, vnet_plugin_handoff_t * h,
return error;
}
-u8 *ila_format_adjacency(u8 * s, va_list * va)
+u8 *format_ila_dpo (u8 * s, va_list * va)
{
+ index_t index = va_arg (*va, index_t);
+ CLIB_UNUSED(u32 indent) = va_arg (*va, u32);
ila_main_t *ilm = &ila_main;
- __attribute((unused)) ip_lookup_main_t *lm = va_arg (*va, ip_lookup_main_t *);
- ip_adjacency_t *adj = va_arg (*va, ip_adjacency_t *);
- ila_adj_data_t * ad = (ila_adj_data_t *) & adj->opaque;
- ila_entry_t *ie = pool_elt_at_index (ilm->entries, ad->entry_index);
- return format(s, "idx:%d sir:%U", ad->entry_index, format_ip6_address, &ie->sir_address);
+ ila_entry_t *ie = pool_elt_at_index (ilm->entries, index);
+ return format(s, "ILA: idx:%d sir:%U",
+ index,
+ format_ip6_address, &ie->sir_address);
+}
+
+/**
+ * @brief no-op lock function.
+ * The lifetime of the ILA entry is managed by the control plane
+ */
+static void
+ila_dpo_lock (dpo_id_t *dpo)
+{
}
+/**
+ * @brief no-op unlock function.
+ * The lifetime of the ILA entry is managed by the control plane
+ */
+static void
+ila_dpo_unlock (dpo_id_t *dpo)
+{
+}
+
+const static dpo_vft_t ila_vft = {
+ .dv_lock = ila_dpo_lock,
+ .dv_unlock = ila_dpo_unlock,
+ .dv_format = format_ila_dpo,
+};
+const static char* const ila_ip6_nodes[] =
+{
+ "ila-to-sir",
+ NULL,
+};
+const static char* const * const ila_nodes[DPO_PROTO_NUM] =
+{
+ [DPO_PROTO_IP6] = ila_ip6_nodes,
+};
+
+static fib_node_t *
+ila_fib_node_get_node (fib_node_index_t index)
+{
+ ila_main_t *ilm = &ila_main;
+ ila_entry_t *ie = pool_elt_at_index (ilm->entries, index);
+
+ return (&ie->ila_fib_node);
+}
+
+/**
+ * @brief no-op unlock function.
+ * The lifetime of the ILA entry is managed by the control plane
+ */
+static void
+ila_fib_node_last_lock_gone (fib_node_t *node)
+{
+}
+
+static ila_entry_t *
+ila_entry_from_fib_node (fib_node_t *node)
+{
+ return ((ila_entry_t*)(((char*)node) -
+ STRUCT_OFFSET_OF(ila_entry_t, ila_fib_node)));
+}
+
+/**
+ * @brief
+ * Callback function invoked when the forwarding changes for the ILA next-hop
+ */
+static fib_node_back_walk_rc_t
+ila_fib_node_back_walk_notify (fib_node_t *node,
+ fib_node_back_walk_ctx_t *ctx)
+{
+ ila_entry_stack(ila_entry_from_fib_node(node));
+
+ return (FIB_NODE_BACK_WALK_CONTINUE);
+}
+
+/*
+ * ILA's FIB graph node virtual function table
+ */
+static const fib_node_vft_t ila_fib_node_vft = {
+ .fnv_get = ila_fib_node_get_node,
+ .fnv_last_lock = ila_fib_node_last_lock_gone,
+ .fnv_back_walk = ila_fib_node_back_walk_notify,
+};
+
clib_error_t *
ila_init (vlib_main_t * vm)
{
ila_main_t *ilm = &ila_main;
ilm->entries = NULL;
- ASSERT (sizeof (ila_adj_data_t) < IP_ADJACENCY_OPAQUE_SZ);
-
ilm->lookup_table_nbuckets = ILA_TABLE_DEFAULT_HASH_NUM_BUCKETS;
ilm->lookup_table_nbuckets = 1 << max_log2 (ilm->lookup_table_nbuckets);
ilm->lookup_table_size = ILA_TABLE_DEFAULT_HASH_MEMORY_SIZE;
@@ -822,15 +958,12 @@ ila_init (vlib_main_t * vm)
"ila id to entry index table",
ilm->lookup_table_nbuckets, ilm->lookup_table_size);
+ ila_dpo_type = dpo_register_new_type(&ila_vft, ila_nodes);
+ ila_fib_node_type = fib_node_register_new_type(&ila_fib_node_vft);
+
return NULL;
}
-VNET_IP6_REGISTER_ADJACENCY(ila2sir) = {
- .node_name = "ila-to-sir",
- .fn = ila_format_adjacency,
- .next_index = &ila_main.ip6_lookup_next_index
-};
-
VLIB_INIT_FUNCTION (ila_init);
static clib_error_t *
@@ -839,9 +972,7 @@ ila_entry_command_fn (vlib_main_t * vm,
{
unformat_input_t _line_input, *line_input = &_line_input;
ila_add_del_entry_args_t args = { 0 };
- ip6_address_t next_hop;
u8 next_hop_set = 0;
- ip6_main_t *im6 = &ip6_main;
int ret;
args.type = ILA_TYPE_IID;
@@ -856,32 +987,27 @@ ila_entry_command_fn (vlib_main_t * vm,
{
if (unformat (line_input, "type %U", unformat_ila_type, &args.type))
;
- else
- if (unformat
- (line_input, "sir-address %U", unformat_ip6_address,
- &args.sir_address))
- ;
- else
- if (unformat
- (line_input, "locator %U", unformat_half_ip6_address,
- &args.locator))
+ else if (unformat
+ (line_input, "sir-address %U", unformat_ip6_address,
+ &args.sir_address))
;
- else if (unformat (line_input, "adj-index %u", &args.local_adj_index))
+ else if (unformat
+ (line_input, "locator %U", unformat_half_ip6_address,
+ &args.locator))
;
- else
- if (unformat
- (line_input, "csum-mode %U", unformat_ila_csum_mode,
- &args.csum_mode))
+ else if (unformat
+ (line_input, "csum-mode %U", unformat_ila_csum_mode,
+ &args.csum_mode))
;
else if (unformat (line_input, "vnid %x", &args.vnid))
;
- else
- if (unformat
- (line_input, "next-hop %U", unformat_ip6_address, &next_hop))
- next_hop_set = 1;
+ else if (unformat
+ (line_input, "next-hop %U", unformat_ip6_address,
+ &args.next_hop_address))
+ ;
else if (unformat
(line_input, "direction %U", unformat_ila_direction, &args.dir))
- ;
+ next_hop_set = 1;
else if (unformat (line_input, "del"))
args.is_del = 1;
else
@@ -891,26 +1017,8 @@ ila_entry_command_fn (vlib_main_t * vm,
unformat_free (line_input);
- if (next_hop_set)
- {
- if (args.local_adj_index != ~0)
- return clib_error_return (0,
- "Specified both next hop and adjacency index");
-
- u32 ai = ip6_get_route (im6, 0, 0, &next_hop, 128);
- if (ai == 0)
- return clib_error_return (0, "No route to next-hop %U",
- format_ip6_address, &next_hop);
-
- ip_lookup_main_t *lm6 = &ip6_main.lookup_main;
- ip_adjacency_t *adj6 = ip_get_adjacency (lm6, ai);
- if (adj6->lookup_next_index != IP_LOOKUP_NEXT_REWRITE)
- {
- return clib_error_return (0,
- "Next-Hop route has to be a rewrite route");
- }
- args.local_adj_index = ai;
- }
+ if (!next_hop_set)
+ return clib_error_return (0, "Specified a next hop");
if ((ret = ila_add_del_entry (&args)))
return clib_error_return (0, "ila_add_del_entry returned error %d", ret);
diff --git a/plugins/ila-plugin/ila/ila.h b/plugins/ila-plugin/ila/ila.h
index b800fdd7b7a..657511f00f2 100644
--- a/plugins/ila-plugin/ila/ila.h
+++ b/plugins/ila-plugin/ila/ila.h
@@ -18,6 +18,7 @@
#include <vnet/vnet.h>
#include <vnet/ip/ip.h>
+#include <vnet/fib/fib_node.h>
#include <vppinfra/bihash_24_8.h>
#include <vppinfra/bihash_template.h>
@@ -59,17 +60,32 @@ typedef enum {
} ila_direction_t;
typedef struct {
+ /**
+ * Fib Node base class
+ */
+ fib_node_t ila_fib_node;
ila_type_t type;
ip6_address_t sir_address;
ip6_address_t ila_address;
- u32 ila_adj_index;
+ ip6_address_t next_hop;
ila_csum_mode_t csum_mode;
ila_direction_t dir;
-} ila_entry_t;
-typedef struct {
- u32 entry_index;
-} ila_adj_data_t;
+ /**
+ * The FIB entry index for the next-hop
+ */
+ fib_node_index_t next_hop_fib_entry_index;
+
+ /**
+ * The child index on the FIB entry
+ */
+ u32 next_hop_child_index;
+
+ /**
+ * The next DPO in the grpah to follow
+ */
+ dpo_id_t ila_dpo;
+} ila_entry_t;
typedef struct {
ila_entry_t *entries; //Pool of ILA entries
@@ -87,6 +103,7 @@ typedef struct {
typedef struct {
ila_type_t type;
ip6_address_t sir_address;
+ ip6_address_t next_hop_address;
u64 locator;
u32 vnid;
u32 local_adj_index;
diff --git a/plugins/lb-plugin/lb/lb.c b/plugins/lb-plugin/lb/lb.c
index e91bdf0bc10..140c221a438 100644
--- a/plugins/lb-plugin/lb/lb.c
+++ b/plugins/lb-plugin/lb/lb.c
@@ -537,54 +537,54 @@ int lb_vip_del_ass(u32 vip_index, ip46_address_t *addresses, u32 n)
int lb_as_lookup_bypass(u32 vip_index, ip46_address_t *address, u8 is_disable)
{
- lb_get_writer_lock();
- lb_main_t *lbm = &lb_main;
- u32 as_index;
- lb_as_t *as;
- lb_vip_t *vip;
-
- if (!(vip = lb_vip_get_by_index(vip_index)) ||
- lb_as_find_index_vip(vip, address, &as_index)) {
- lb_put_writer_lock();
- return VNET_API_ERROR_NO_SUCH_ENTRY;
- }
-
- as = &lbm->ass[as_index];
-
- if (is_disable) {
- as->adj_index = ~0;
- } else if (lb_vip_is_gre4(vip)) {
- uword *p = ip4_get_route (&ip4_main, 0, 0, as->address.ip4.as_u8, 32);
- if (p == 0) {
- lb_put_writer_lock();
- return VNET_API_ERROR_NO_SUCH_ENTRY;
- }
- u32 ai = (u32)p[0];
- ip_lookup_main_t *lm4 = &ip4_main.lookup_main;
- ip_adjacency_t *adj4 = ip_get_adjacency (lm4, ai);
- if (adj4->lookup_next_index != IP_LOOKUP_NEXT_REWRITE) {
- lb_put_writer_lock();
- return VNET_API_ERROR_INCORRECT_ADJACENCY_TYPE;
- }
-
- as->adj_index = ai;
- } else {
- u32 ai = ip6_get_route (&ip6_main, 0, 0, &as->address.ip6, 128);
- if (ai == 0) {
- lb_put_writer_lock();
- return VNET_API_ERROR_NO_SUCH_ENTRY;
- }
-
- ip_lookup_main_t *lm6 = &ip6_main.lookup_main;
- ip_adjacency_t *adj6 = ip_get_adjacency (lm6, ai);
- if (adj6->lookup_next_index != IP_LOOKUP_NEXT_REWRITE) {
- lb_put_writer_lock();
- return VNET_API_ERROR_INCORRECT_ADJACENCY_TYPE;
- }
-
- as->adj_index = ai;
- }
- lb_put_writer_lock();
+ /* lb_get_writer_lock(); */
+ /* lb_main_t *lbm = &lb_main; */
+ /* u32 as_index; */
+ /* lb_as_t *as; */
+ /* lb_vip_t *vip; */
+
+ /* if (!(vip = lb_vip_get_by_index(vip_index)) || */
+ /* lb_as_find_index_vip(vip, address, &as_index)) { */
+ /* lb_put_writer_lock(); */
+ /* return VNET_API_ERROR_NO_SUCH_ENTRY; */
+ /* } */
+
+ /* as = &lbm->ass[as_index]; */
+
+ /* if (is_disable) { */
+ /* as->adj_index = ~0; */
+ /* } else if (lb_vip_is_gre4(vip)) { */
+ /* uword *p = ip4_get_route (&ip4_main, 0, 0, as->address.ip4.as_u8, 32); */
+ /* if (p == 0) { */
+ /* lb_put_writer_lock(); */
+ /* return VNET_API_ERROR_NO_SUCH_ENTRY; */
+ /* } */
+ /* u32 ai = (u32)p[0]; */
+ /* ip_lookup_main_t *lm4 = &ip4_main.lookup_main; */
+ /* ip_adjacency_t *adj4 = ip_get_adjacency (lm4, ai); */
+ /* if (adj4->lookup_next_index != IP_LOOKUP_NEXT_REWRITE) { */
+ /* lb_put_writer_lock(); */
+ /* return VNET_API_ERROR_INCORRECT_ADJACENCY_TYPE; */
+ /* } */
+
+ /* as->adj_index = ai; */
+ /* } else { */
+ /* u32 ai = ip6_get_route (&ip6_main, 0, 0, &as->address.ip6, 128); */
+ /* if (ai == 0) { */
+ /* lb_put_writer_lock(); */
+ /* return VNET_API_ERROR_NO_SUCH_ENTRY; */
+ /* } */
+
+ /* ip_lookup_main_t *lm6 = &ip6_main.lookup_main; */
+ /* ip_adjacency_t *adj6 = ip_get_adjacency (lm6, ai); */
+ /* if (adj6->lookup_next_index != IP_LOOKUP_NEXT_REWRITE) { */
+ /* lb_put_writer_lock(); */
+ /* return VNET_API_ERROR_INCORRECT_ADJACENCY_TYPE; */
+ /* } */
+
+ /* as->adj_index = ai; */
+ /* } */
+ /* lb_put_writer_lock(); */
return 0;
}
@@ -594,41 +594,41 @@ int lb_as_lookup_bypass(u32 vip_index, ip46_address_t *address, u8 is_disable)
*/
static void lb_vip_add_adjacency(lb_main_t *lbm, lb_vip_t *vip)
{
- ip_adjacency_t adj;
- //Adjacency
- memset (&adj, 0, sizeof (adj));
- adj.explicit_fib_index = ~0;
- lb_adj_data_t *ad = (lb_adj_data_t *) &adj.opaque;
- ad->vip_index = vip - lbm->vips;
-
- ASSERT (lbm->writer_lock[0]); //This must be called with the lock owned
- u32 lookup_next_index = lbm->ip_lookup_next_index[vip->type];
-
- if (lb_vip_is_ip4(vip)) {
- adj.lookup_next_index = lookup_next_index;
- ip4_add_del_route_args_t route_args = {};
- ip4_main_t *im4 = &ip4_main;
- route_args.table_index_or_table_id = 0;
- route_args.flags = IP4_ROUTE_FLAG_ADD;
- route_args.dst_address = vip->prefix.ip4;
- route_args.dst_address_length = vip->plen - 96;
- route_args.adj_index = ~0;
- route_args.add_adj = &adj;
- route_args.n_add_adj = 1;
- ip4_add_del_route (im4, &route_args);
- } else {
- adj.lookup_next_index = lookup_next_index;
- ip6_add_del_route_args_t route_args = {};
- ip6_main_t *im6 = &ip6_main;
- route_args.table_index_or_table_id = 0;
- route_args.flags = IP6_ROUTE_FLAG_ADD;
- route_args.dst_address = vip->prefix.ip6;
- route_args.dst_address_length = vip->plen;
- route_args.adj_index = ~0;
- route_args.add_adj = &adj;
- route_args.n_add_adj = 1;
- ip6_add_del_route (im6, &route_args);
- }
+ /* ip_adjacency_t adj; */
+ /* //Adjacency */
+ /* memset (&adj, 0, sizeof (adj)); */
+ /* adj.explicit_fib_index = ~0; */
+ /* lb_adj_data_t *ad = (lb_adj_data_t *) &adj.opaque; */
+ /* ad->vip_index = vip - lbm->vips; */
+
+ /* ASSERT (lbm->writer_lock[0]); //This must be called with the lock owned */
+ /* u32 lookup_next_index = lbm->ip_lookup_next_index[vip->type]; */
+
+ /* if (lb_vip_is_ip4(vip)) { */
+ /* adj.lookup_next_index = lookup_next_index; */
+ /* ip4_add_del_route_args_t route_args = {}; */
+ /* ip4_main_t *im4 = &ip4_main; */
+ /* route_args.table_index_or_table_id = 0; */
+ /* route_args.flags = IP4_ROUTE_FLAG_ADD; */
+ /* route_args.dst_address = vip->prefix.ip4; */
+ /* route_args.dst_address_length = vip->plen - 96; */
+ /* route_args.adj_index = ~0; */
+ /* route_args.add_adj = &adj; */
+ /* route_args.n_add_adj = 1; */
+ /* ip4_add_del_route (im4, &route_args); */
+ /* } else { */
+ /* adj.lookup_next_index = lookup_next_index; */
+ /* ip6_add_del_route_args_t route_args = {}; */
+ /* ip6_main_t *im6 = &ip6_main; */
+ /* route_args.table_index_or_table_id = 0; */
+ /* route_args.flags = IP6_ROUTE_FLAG_ADD; */
+ /* route_args.dst_address = vip->prefix.ip6; */
+ /* route_args.dst_address_length = vip->plen; */
+ /* route_args.adj_index = ~0; */
+ /* route_args.add_adj = &adj; */
+ /* route_args.n_add_adj = 1; */
+ /* ip6_add_del_route (im6, &route_args); */
+ /* } */
}
/**
@@ -636,30 +636,30 @@ static void lb_vip_add_adjacency(lb_main_t *lbm, lb_vip_t *vip)
*/
static void lb_vip_del_adjacency(lb_main_t *lbm, lb_vip_t *vip)
{
- ASSERT (lbm->writer_lock[0]); //This must be called with the lock owned
- if (lb_vip_is_ip4(vip)) {
- ip4_main_t *im4 = &ip4_main;
- ip4_add_del_route_args_t route_args = {};
- route_args.table_index_or_table_id = 0;
- route_args.flags = IP4_ROUTE_FLAG_DEL;
- route_args.dst_address = vip->prefix.ip4;
- route_args.dst_address_length = vip->plen - 96;
- route_args.adj_index = ~0;
- route_args.add_adj = NULL;
- route_args.n_add_adj = 0;
- ip4_add_del_route (im4, &route_args);
- } else {
- ip6_main_t *im6 = &ip6_main;
- ip6_add_del_route_args_t route_args = {};
- route_args.table_index_or_table_id = 0;
- route_args.flags = IP6_ROUTE_FLAG_DEL;
- route_args.dst_address = vip->prefix.ip6;
- route_args.dst_address_length = vip->plen;
- route_args.adj_index = ~0;
- route_args.add_adj = NULL;
- route_args.n_add_adj = 0;
- ip6_add_del_route (im6, &route_args);
- }
+ /* ASSERT (lbm->writer_lock[0]); //This must be called with the lock owned */
+ /* if (lb_vip_is_ip4(vip)) { */
+ /* ip4_main_t *im4 = &ip4_main; */
+ /* ip4_add_del_route_args_t route_args = {}; */
+ /* route_args.table_index_or_table_id = 0; */
+ /* route_args.flags = IP4_ROUTE_FLAG_DEL; */
+ /* route_args.dst_address = vip->prefix.ip4; */
+ /* route_args.dst_address_length = vip->plen - 96; */
+ /* route_args.adj_index = ~0; */
+ /* route_args.add_adj = NULL; */
+ /* route_args.n_add_adj = 0; */
+ /* ip4_add_del_route (im4, &route_args); */
+ /* } else { */
+ /* ip6_main_t *im6 = &ip6_main; */
+ /* ip6_add_del_route_args_t route_args = {}; */
+ /* route_args.table_index_or_table_id = 0; */
+ /* route_args.flags = IP6_ROUTE_FLAG_DEL; */
+ /* route_args.dst_address = vip->prefix.ip6; */
+ /* route_args.dst_address_length = vip->plen; */
+ /* route_args.adj_index = ~0; */
+ /* route_args.add_adj = NULL; */
+ /* route_args.n_add_adj = 0; */
+ /* ip6_add_del_route (im6, &route_args); */
+ /* } */
}
int lb_vip_add(ip46_address_t *prefix, u8 plen, lb_vip_type_t type, u32 new_length, u32 *vip_index)
diff --git a/plugins/lb-plugin/lb/node.c b/plugins/lb-plugin/lb/node.c
index 8df462c0853..4f71616120e 100644
--- a/plugins/lb-plugin/lb/node.c
+++ b/plugins/lb-plugin/lb/node.c
@@ -48,15 +48,15 @@ typedef struct {
u32 as_index;
} lb_trace_t;
-u8 *lb_format_adjacency(u8 * s, va_list * va)
-{
- lb_main_t *lbm = &lb_main;
- __attribute((unused)) ip_lookup_main_t *lm = va_arg (*va, ip_lookup_main_t *);
- ip_adjacency_t *adj = va_arg (*va, ip_adjacency_t *);
- lb_adj_data_t *ad = (lb_adj_data_t *) &adj->opaque;
- __attribute__((unused)) lb_vip_t *vip = pool_elt_at_index (lbm->vips, ad->vip_index);
- return format(s, "vip idx:%d", ad->vip_index);
-}
+/* u8 *lb_format_adjacency(u8 * s, va_list * va) */
+/* { */
+/* lb_main_t *lbm = &lb_main; */
+/* __attribute((unused)) ip_lookup_main_t *lm = va_arg (*va, ip_lookup_main_t *); */
+/* ip_adjacency_t *adj = va_arg (*va, ip_adjacency_t *); */
+/* lb_adj_data_t *ad = (lb_adj_data_t *) &adj->opaque; */
+/* __attribute__((unused)) lb_vip_t *vip = pool_elt_at_index (lbm->vips, ad->vip_index); */
+/* return format(s, "vip idx:%d", ad->vip_index); */
+/* } */
u8 *
format_lb_trace (u8 * s, va_list * args)
@@ -319,11 +319,11 @@ VLIB_REGISTER_NODE (lb6_gre6_node) =
},
};
-VNET_IP6_REGISTER_ADJACENCY(lb6_gre6) = {
- .node_name = "lb6-gre6",
- .fn = lb_format_adjacency,
- .next_index = &lb_main.ip_lookup_next_index[LB_VIP_TYPE_IP6_GRE6]
-};
+/* VNET_IP6_REGISTER_ADJACENCY(lb6_gre6) = { */
+/* .node_name = "lb6-gre6", */
+/* .fn = lb_format_adjacency, */
+/* .next_index = &lb_main.ip_lookup_next_index[LB_VIP_TYPE_IP6_GRE6] */
+/* }; */
VLIB_REGISTER_NODE (lb6_gre4_node) =
{
@@ -344,11 +344,11 @@ VLIB_REGISTER_NODE (lb6_gre4_node) =
},
};
-VNET_IP6_REGISTER_ADJACENCY(lb6_gre4) = {
- .node_name = "lb6-gre4",
- .fn = lb_format_adjacency,
- .next_index = &lb_main.ip_lookup_next_index[LB_VIP_TYPE_IP6_GRE4]
-};
+/* VNET_IP6_REGISTER_ADJACENCY(lb6_gre4) = { */
+/* .node_name = "lb6-gre4", */
+/* .fn = lb_format_adjacency, */
+/* .next_index = &lb_main.ip_lookup_next_index[LB_VIP_TYPE_IP6_GRE4] */
+/* }; */
VLIB_REGISTER_NODE (lb4_gre6_node) =
{
@@ -369,11 +369,11 @@ VLIB_REGISTER_NODE (lb4_gre6_node) =
},
};
-VNET_IP4_REGISTER_ADJACENCY(lb4_gre6) = {
- .node_name = "lb4-gre6",
- .fn = lb_format_adjacency,
- .next_index = &lb_main.ip_lookup_next_index[LB_VIP_TYPE_IP4_GRE6]
-};
+/* VNET_IP4_REGISTER_ADJACENCY(lb4_gre6) = { */
+/* .node_name = "lb4-gre6", */
+/* .fn = lb_format_adjacency, */
+/* .next_index = &lb_main.ip_lookup_next_index[LB_VIP_TYPE_IP4_GRE6] */
+/* }; */
VLIB_REGISTER_NODE (lb4_gre4_node) =
{
@@ -394,8 +394,8 @@ VLIB_REGISTER_NODE (lb4_gre4_node) =
},
};
-VNET_IP4_REGISTER_ADJACENCY(lb4_gre4) = {
- .node_name = "lb4-gre4",
- .fn = lb_format_adjacency,
- .next_index = &lb_main.ip_lookup_next_index[LB_VIP_TYPE_IP4_GRE4]
-};
+/* VNET_IP4_REGISTER_ADJACENCY(lb4_gre4) = { */
+/* .node_name = "lb4-gre4", */
+/* .fn = lb_format_adjacency, */
+/* .next_index = &lb_main.ip_lookup_next_index[LB_VIP_TYPE_IP4_GRE4] */
+/* }; */
diff --git a/plugins/sixrd-plugin/Makefile.am b/plugins/sixrd-plugin/Makefile.am
index 71c8da48420..eb0d806aa6a 100644
--- a/plugins/sixrd-plugin/Makefile.am
+++ b/plugins/sixrd-plugin/Makefile.am
@@ -18,11 +18,13 @@ AM_LDFLAGS = -module -shared -avoid-version
libsixrd_plugin_la_SOURCES = \
sixrd/sixrd.c \
+ sixrd/sixrd_dpo.c \
sixrd/ip4_sixrd.c \
sixrd/ip6_sixrd.c
noinst_HEADERS = \
- sixrd/sixrd.h
+ sixrd/sixrd.h \
+ sixrd/sixrd_dpo.h
BUILT_SOURCES =
diff --git a/plugins/sixrd-plugin/sixrd/sixrd.c b/plugins/sixrd-plugin/sixrd/sixrd.c
index e842d49aa0a..65d353a4592 100644
--- a/plugins/sixrd-plugin/sixrd/sixrd.c
+++ b/plugins/sixrd-plugin/sixrd/sixrd.c
@@ -16,6 +16,10 @@
#include "sixrd.h"
#include <vnet/plugin/plugin.h>
+#include <vnet/fib/fib_table.h>
+#include <vnet/fib/ip6_fib.h>
+#include <vnet/adj/adj.h>
+
/*
* This code supports the following sixrd modes:
*
@@ -29,21 +33,17 @@
int
sixrd_create_domain (ip6_address_t *ip6_prefix,
- u8 ip6_prefix_len,
- ip4_address_t *ip4_prefix,
- u8 ip4_prefix_len,
- ip4_address_t *ip4_src,
- u32 *sixrd_domain_index,
+ u8 ip6_prefix_len,
+ ip4_address_t *ip4_prefix,
+ u8 ip4_prefix_len,
+ ip4_address_t *ip4_src,
+ u32 *sixrd_domain_index,
u16 mtu)
{
+ dpo_id_t dpo_v6 = DPO_NULL, dpo_v4 = DPO_NULL;
sixrd_main_t *mm = &sixrd_main;
- ip4_main_t *im4 = &ip4_main;
- ip6_main_t *im6 = &ip6_main;
+ fib_node_index_t fei;
sixrd_domain_t *d;
- ip_adjacency_t adj;
- ip4_add_del_route_args_t args4;
- ip6_add_del_route_args_t args6;
- u32 *p;
/* Get domain index */
pool_get_aligned(mm->domains, d, CLIB_CACHE_LINE_BYTES);
@@ -61,55 +61,79 @@ sixrd_create_domain (ip6_address_t *ip6_prefix,
if (ip4_prefix_len < 32)
d->shift = 64 - ip6_prefix_len + (32 - ip4_prefix_len);
- /* Init IP adjacency */
- memset(&adj, 0, sizeof(adj));
- adj.explicit_fib_index = ~0;
- p = (u32 *)&adj.rewrite_data[0];
- *p = (u32) (*sixrd_domain_index);
-
- /* Create ip6 adjacency */
- memset(&args6, 0, sizeof(args6));
- args6.table_index_or_table_id = 0;
- args6.flags = IP6_ROUTE_FLAG_ADD;
- args6.dst_address.as_u64[0] = ip6_prefix->as_u64[0];
- args6.dst_address.as_u64[1] = ip6_prefix->as_u64[1];
- args6.dst_address_length = ip6_prefix_len;
- args6.adj_index = ~0;
- args6.add_adj = &adj;
- args6.n_add_adj = 1;
- adj.lookup_next_index = mm->ip6_lookup_next_index;
- ip6_add_del_route(im6, &args6);
-
- /* Multiple SIXRD domains may share same source IPv4 TEP */
- uword *q = ip4_get_route(im4, 0, 0, (u8 *)ip4_src, 32);
- if (q) {
- u32 ai = q[0];
- ip_lookup_main_t *lm4 = &ip4_main.lookup_main;
- ip_adjacency_t *adj4 = ip_get_adjacency(lm4, ai);
- if (adj4->lookup_next_index != mm->ip4_lookup_next_index) {
- clib_warning("BR source address already assigned: %U", format_ip4_address, ip4_src);
- pool_put(mm->domains, d);
- return -1;
- }
- /* Shared source */
- p = (u32 *)&adj4->rewrite_data[0];
- p[0] = ~0;
-
- /* Add refcount, so we don't accidentially delete the route underneath someone */
- p[1]++;
- } else {
- /* Create ip4 adjacency. */
- memset(&args4, 0, sizeof(args4));
- args4.table_index_or_table_id = 0;
- args4.flags = IP4_ROUTE_FLAG_ADD;
- args4.dst_address.as_u32 = ip4_src->as_u32;
- args4.dst_address_length = 32;
- args4.adj_index = ~0;
- args4.add_adj = &adj;
- args4.n_add_adj = 1;
- adj.lookup_next_index = mm->ip4_lookup_next_index;
- ip4_add_del_route(im4, &args4);
+ /* Create IPv6 route/adjacency */
+ fib_prefix_t pfx6 = {
+ .fp_proto = FIB_PROTOCOL_IP6,
+ .fp_len = d->ip6_prefix_len,
+ .fp_addr = {
+ .ip6 = d->ip6_prefix,
+ },
+ };
+ sixrd_dpo_create(FIB_PROTOCOL_IP6,
+ *sixrd_domain_index,
+ &dpo_v6);
+ fib_table_entry_special_dpo_add(0, &pfx6,
+ FIB_SOURCE_SIXRD,
+ FIB_ENTRY_FLAG_EXCLUSIVE,
+ &dpo_v6);
+ dpo_reset (&dpo_v6);
+
+ /*
+ * Multiple SIXRD domains may share same source IPv4 TEP
+ * In this case the route will exist and be SixRD sourced.
+ * Find the adj (if any) already contributed and modify it
+ */
+ fib_prefix_t pfx4 = {
+ .fp_proto = FIB_PROTOCOL_IP6,
+ .fp_len = 32,
+ .fp_addr = {
+ .ip4 = d->ip4_src,
+ },
+ };
+ fei = fib_table_lookup_exact_match(0, &pfx4);
+
+ if (FIB_NODE_INDEX_INVALID != fei)
+ {
+ dpo_id_t dpo = DPO_NULL;
+
+ if (fib_entry_get_dpo_for_source (fei, FIB_SOURCE_SIXRD, &dpo))
+ {
+ /*
+ * modify the existing adj to indicate it's shared
+ * skip to route add.
+ * It is locked to pair with the unlock below.
+ */
+ const dpo_id_t *sd_dpo;
+ sixrd_dpo_t *sd;
+
+ ASSERT(DPO_LOAD_BALANCE == dpo.dpoi_type);
+
+ sd_dpo = load_balance_get_bucket(dpo.dpoi_index, 0);
+ sd = sixrd_dpo_get (sd_dpo->dpoi_index);
+
+ sd->sd_domain = ~0;
+ dpo_copy (&dpo_v4, sd_dpo);
+ dpo_reset (&dpo);
+
+ goto route_add;
+ }
}
+ /* first time addition of the route */
+ sixrd_dpo_create(FIB_PROTOCOL_IP4,
+ *sixrd_domain_index,
+ &dpo_v4);
+
+route_add:
+ /*
+ * Create ip4 route. This is a reference counted add. If the prefix
+ * already exists and is SixRD sourced, it is now SixRD source n+1 times
+ * and will need to be removed n+1 times.
+ */
+ fib_table_entry_special_dpo_add(0, &pfx4,
+ FIB_SOURCE_SIXRD,
+ FIB_ENTRY_FLAG_EXCLUSIVE,
+ &dpo_v4);
+ dpo_reset (&dpo_v4);
return 0;
}
@@ -121,57 +145,33 @@ int
sixrd_delete_domain (u32 sixrd_domain_index)
{
sixrd_main_t *mm = &sixrd_main;
- ip4_main_t *im4 = &ip4_main;
- ip6_main_t *im6 = &ip6_main;
sixrd_domain_t *d;
- ip_adjacency_t adj;
- ip4_add_del_route_args_t args4;
- ip6_add_del_route_args_t args6;
if (pool_is_free_index(mm->domains, sixrd_domain_index)) {
- clib_warning("SIXRD domain delete: domain does not exist: %d", sixrd_domain_index);
+ clib_warning("SIXRD domain delete: domain does not exist: %d",
+ sixrd_domain_index);
return -1;
}
d = pool_elt_at_index(mm->domains, sixrd_domain_index);
- memset(&adj, 0, sizeof(adj));
- adj.explicit_fib_index = ~0;
-
- /* Delete ip6 adjacency */
- memset(&args6, 0, sizeof (args6));
- args6.table_index_or_table_id = 0;
- args6.flags = IP6_ROUTE_FLAG_DEL;
- args6.dst_address.as_u64[0] = d->ip6_prefix.as_u64[0];
- args6.dst_address.as_u64[1] = d->ip6_prefix.as_u64[1];
- args6.dst_address_length = d->ip6_prefix_len;
- args6.adj_index = 0;
- args6.add_adj = &adj;
- args6.n_add_adj = 0;
- ip6_add_del_route(im6, &args6);
-
- /* Delete ip4 adjacency */
- uword *q = ip4_get_route(im4, 0, 0, (u8 *)&d->ip4_src, 32);
- if (q) {
- u32 ai = q[0];
- ip_lookup_main_t *lm4 = &ip4_main.lookup_main;
- ip_adjacency_t *adj4 = ip_get_adjacency(lm4, ai);
-
- u32 *p = (u32 *)&adj4->rewrite_data[0];
- /* Delete route when no other domains use this source */
- if (p[1] == 0) {
- memset(&args4, 0, sizeof(args4));
- args4.table_index_or_table_id = 0;
- args4.flags = IP4_ROUTE_FLAG_DEL;
- args4.dst_address.as_u32 = d->ip4_prefix.as_u32;
- args4.dst_address_length = d->ip4_prefix_len;
- args4.adj_index = 0;
- args4.add_adj = &adj;
- args4.n_add_adj = 0;
- ip4_add_del_route(im4, &args4);
- }
- p[1]--;
- }
+ fib_prefix_t pfx = {
+ .fp_proto = FIB_PROTOCOL_IP4,
+ .fp_len = 32,
+ .fp_addr = {
+ .ip4 = d->ip4_src,
+ },
+ };
+ fib_table_entry_special_remove(0, &pfx, FIB_SOURCE_SIXRD);
+
+ fib_prefix_t pfx6 = {
+ .fp_proto = FIB_PROTOCOL_IP6,
+ .fp_len = d->ip6_prefix_len,
+ .fp_addr = {
+ .ip6 = d->ip6_prefix,
+ },
+ };
+ fib_table_entry_special_remove(0, &pfx6, FIB_SOURCE_SIXRD);
pool_put(mm->domains, d);
@@ -361,19 +361,9 @@ vlib_plugin_register (vlib_main_t * vm, vnet_plugin_handoff_t * h,
static clib_error_t * sixrd_init (vlib_main_t * vm)
{
- clib_error_t * error = 0;
- sixrd_main_t *mm = &sixrd_main;
+ sixrd_dpo_module_init ();
- vlib_node_t * ip6_lookup_node = vlib_get_node_by_name(vm, (u8 *)"ip6-lookup");
- vlib_node_t * ip4_lookup_node = vlib_get_node_by_name(vm, (u8 *)"ip4-lookup");
- vlib_node_t * ip6_sixrd_node = vlib_get_node_by_name(vm, (u8 *)"ip6-sixrd");
- vlib_node_t * ip4_sixrd_node = vlib_get_node_by_name(vm, (u8 *)"ip4-sixrd");
- ASSERT(ip6_lookup_node && ip4_lookup_node && ip6_sixrd_node && ip4_sixrd_node);
-
- mm->ip6_lookup_next_index = vlib_node_add_next(vm, ip6_lookup_node->index, ip6_sixrd_node->index);
- mm->ip4_lookup_next_index = vlib_node_add_next(vm, ip4_lookup_node->index, ip4_sixrd_node->index);
-
- return error;
+ return (NULL);
}
VLIB_INIT_FUNCTION (sixrd_init);
diff --git a/plugins/sixrd-plugin/sixrd/sixrd.h b/plugins/sixrd-plugin/sixrd/sixrd.h
index 2f0912f0626..56714c9e3bd 100644
--- a/plugins/sixrd-plugin/sixrd/sixrd.h
+++ b/plugins/sixrd-plugin/sixrd/sixrd.h
@@ -17,6 +17,9 @@
#include <vppinfra/error.h>
#include <vnet/vnet.h>
#include <vnet/ip/ip.h>
+#include <vnet/fib/ip6_fib.h>
+
+#include "sixrd_dpo.h"
int sixrd_create_domain(ip6_address_t *ip6_prefix, u8 ip6_prefix_len,
ip4_address_t *ip4_prefix, u8 ip4_prefix_len,
@@ -44,9 +47,6 @@ typedef struct {
/* convenience */
vlib_main_t *vlib_main;
vnet_main_t *vnet_main;
-
- u32 ip4_lookup_next_index;
- u32 ip6_lookup_next_index;
} sixrd_main_t;
#define foreach_sixrd_error \
@@ -99,16 +99,16 @@ sixrd_get_addr (sixrd_domain_t *d, u64 dal)
* Get the SIXRD domain from an IPv6 lookup adjacency.
*/
static_always_inline sixrd_domain_t *
-ip6_sixrd_get_domain (u32 adj_index, u32 *sixrd_domain_index)
+ip6_sixrd_get_domain (u32 sdi, u32 *sixrd_domain_index)
{
sixrd_main_t *mm = &sixrd_main;
- ip_lookup_main_t *lm = &ip6_main.lookup_main;
- ip_adjacency_t *adj = ip_get_adjacency(lm, adj_index);
- ASSERT(adj);
- uword *p = (uword *)adj->rewrite_data;
- ASSERT(p);
- *sixrd_domain_index = p[0];
- return pool_elt_at_index(mm->domains, p[0]);
+ sixrd_dpo_t *sd;
+
+ sd = sixrd_dpo_get(sdi);
+
+ ASSERT(sd);
+ *sixrd_domain_index = sd->sd_domain;
+ return pool_elt_at_index(mm->domains, *sixrd_domain_index);
}
/*
@@ -117,28 +117,25 @@ ip6_sixrd_get_domain (u32 adj_index, u32 *sixrd_domain_index)
* The IPv6 address is used otherwise.
*/
static_always_inline sixrd_domain_t *
-ip4_sixrd_get_domain (u32 adj_index, ip6_address_t *addr,
+ip4_sixrd_get_domain (u32 sdi, ip6_address_t *addr,
u32 *sixrd_domain_index, u8 *error)
{
sixrd_main_t *mm = &sixrd_main;
- ip6_main_t *im6 = &ip6_main;
- ip_lookup_main_t *lm4 = &ip4_main.lookup_main;
- ip_lookup_main_t *lm6 = &ip6_main.lookup_main;
- ip_adjacency_t *adj = ip_get_adjacency(lm4, adj_index);
- ASSERT(adj);
- uword *p = (uword *)adj->rewrite_data;
- ASSERT(p);
- *sixrd_domain_index = p[0];
- if (p[0] != ~0)
- return pool_elt_at_index(mm->domains, p[0]);
-
- u32 ai = ip6_fib_lookup_with_table(im6, 0, addr);
- ip_adjacency_t *adj6 = ip_get_adjacency (lm6, ai);
- if (PREDICT_TRUE(adj6->lookup_next_index == mm->ip6_lookup_next_index)) {
- uword *p = (uword *)adj6->rewrite_data;
- *sixrd_domain_index = p[0];
+ sixrd_dpo_t *sd;
+
+ sd = sixrd_dpo_get(sdi);
+ *sixrd_domain_index = sd->sd_domain;
+ if (*sixrd_domain_index != ~0)
return pool_elt_at_index(mm->domains, *sixrd_domain_index);
- }
+
+ u32 lbi = ip6_fib_table_fwding_lookup(&ip6_main, 0, addr);
+ const dpo_id_t *dpo = load_balance_get_bucket(lbi, 0);
+ if (PREDICT_TRUE(dpo->dpoi_type == sixrd_dpo_type))
+ {
+ sd = sixrd_dpo_get(dpo->dpoi_index);
+ *sixrd_domain_index = sd->sd_domain;
+ return pool_elt_at_index(mm->domains, *sixrd_domain_index);
+ }
*error = SIXRD_ERROR_NO_DOMAIN;
return NULL;
}
diff --git a/plugins/sixrd-plugin/sixrd/sixrd_dpo.c b/plugins/sixrd-plugin/sixrd/sixrd_dpo.c
new file mode 100644
index 00000000000..88a079350a3
--- /dev/null
+++ b/plugins/sixrd-plugin/sixrd/sixrd_dpo.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "sixrd_dpo.h"
+#include <vnet/ip/ip.h>
+
+/**
+ * pool of all MPLS Label DPOs
+ */
+sixrd_dpo_t *sixrd_dpo_pool;
+
+/**
+ * The register SIXRD DPO type
+ */
+dpo_type_t sixrd_dpo_type;
+
+static sixrd_dpo_t *
+sixrd_dpo_alloc (void)
+{
+ sixrd_dpo_t *sd;
+
+ pool_get_aligned(sixrd_dpo_pool, sd, CLIB_CACHE_LINE_BYTES);
+ memset(sd, 0, sizeof(*sd));
+
+ return (sd);
+}
+
+static index_t
+sixrd_dpo_get_index (sixrd_dpo_t *sd)
+{
+ return (sd - sixrd_dpo_pool);
+}
+
+void
+sixrd_dpo_create (dpo_proto_t dproto,
+ u32 domain_index,
+ dpo_id_t *dpo)
+{
+ sixrd_dpo_t *sd;
+
+ sd = sixrd_dpo_alloc();
+ sd->sd_domain = domain_index;
+ sd->sd_proto = dproto;
+
+ dpo_set(dpo,
+ sixrd_dpo_type,
+ dproto,
+ sixrd_dpo_get_index(sd));
+}
+
+u8*
+format_sixrd_dpo (u8 *s, va_list *args)
+{
+ index_t index = va_arg (*args, index_t);
+ CLIB_UNUSED(u32 indent) = va_arg (*args, u32);
+ sixrd_dpo_t *sd;
+
+ sd = sixrd_dpo_get(index);
+
+ return (format(s, "sixrd:[%d]:%U domain:%d",
+ index,
+ format_dpo_proto, sd->sd_proto,
+ sd->sd_domain));
+}
+
+
+static void
+sixrd_dpo_lock (dpo_id_t *dpo)
+{
+ sixrd_dpo_t *sd;
+
+ sd = sixrd_dpo_get(dpo->dpoi_index);
+
+ sd->sd_locks++;
+}
+
+static void
+sixrd_dpo_unlock (dpo_id_t *dpo)
+{
+ sixrd_dpo_t *sd;
+
+ sd = sixrd_dpo_get(dpo->dpoi_index);
+
+ sd->sd_locks--;
+
+ if (0 == sd->sd_locks)
+ {
+ pool_put(sixrd_dpo_pool, sd);
+ }
+}
+
+const static dpo_vft_t sd_vft = {
+ .dv_lock = sixrd_dpo_lock,
+ .dv_unlock = sixrd_dpo_unlock,
+ .dv_format = format_sixrd_dpo,
+};
+
+const static char* const sixrd_ip4_nodes[] =
+{
+ "ip4-sixrd",
+ NULL,
+};
+const static char* const sixrd_ip6_nodes[] =
+{
+ "ip6-sixrd",
+ NULL,
+};
+
+const static char* const * const sixrd_nodes[DPO_PROTO_NUM] =
+{
+ [DPO_PROTO_IP4] = sixrd_ip4_nodes,
+ [DPO_PROTO_IP6] = sixrd_ip6_nodes,
+ [DPO_PROTO_MPLS] = NULL,
+};
+
+void
+sixrd_dpo_module_init (void)
+{
+ sixrd_dpo_type = dpo_register_new_type(&sd_vft, sixrd_nodes);
+}
diff --git a/plugins/sixrd-plugin/sixrd/sixrd_dpo.h b/plugins/sixrd-plugin/sixrd/sixrd_dpo.h
new file mode 100644
index 00000000000..17142288451
--- /dev/null
+++ b/plugins/sixrd-plugin/sixrd/sixrd_dpo.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __SIXRD_DPO_H__
+#define __SIXRD_DPO_H__
+
+#include <vnet/vnet.h>
+#include <vnet/dpo/dpo.h>
+
+/**
+ * A representation of a 6RD DPO
+ */
+typedef struct sixrd_dpo_t
+{
+ /**
+ * The dat-plane protocol
+ */
+ dpo_proto_t sd_proto;
+
+ /**
+ * the SIXRD domain index
+ */
+ u32 sd_domain;
+
+ /**
+ * Number of locks/users of the label
+ */
+ u16 sd_locks;
+} sixrd_dpo_t;
+
+extern void sixrd_dpo_create (dpo_proto_t dproto,
+ u32 domain_index,
+ dpo_id_t *dpo);
+
+/*
+ * Encapsulation violation for fast data-path access
+ */
+extern sixrd_dpo_t *sixrd_dpo_pool;
+extern dpo_type_t sixrd_dpo_type;
+
+static inline sixrd_dpo_t *
+sixrd_dpo_get (index_t index)
+{
+ return (pool_elt_at_index(sixrd_dpo_pool, index));
+}
+
+extern void sixrd_dpo_module_init(void);
+
+#endif
diff --git a/plugins/vcgn-plugin/vcgn/vcgn_classify.c b/plugins/vcgn-plugin/vcgn/vcgn_classify.c
index 18cc4ba0d1e..b9917df65ea 100644
--- a/plugins/vcgn-plugin/vcgn/vcgn_classify.c
+++ b/plugins/vcgn-plugin/vcgn/vcgn_classify.c
@@ -384,7 +384,7 @@ VLIB_REGISTER_NODE (vcgn_classify_node) = {
.next_nodes = {
[VCGN_CLASSIFY_NEXT_IP4_INPUT] = "ip4-input",
[VCGN_CLASSIFY_NEXT_IP6_INPUT] = "ip6-input",
- [VCGN_CLASSIFY_NEXT_MPLS_INPUT] = "mpls-gre-input",
+ [VCGN_CLASSIFY_NEXT_MPLS_INPUT] = "mpls-input",
[VCGN_CLASSIFY_NEXT_ETHERNET_INPUT] = "ethernet-input",
[VCGN_CLASSIFY_NEXT_UDP_INSIDE] = "vcgn-v4-udp-i2o",
[VCGN_CLASSIFY_NEXT_UDP_OUTSIDE] = "vcgn-v4-udp-o2i",