From 0bfe5d8c792abcdbcf27bfcc7b7b353fba04aee2 Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Thu, 25 Aug 2016 15:29:12 +0100 Subject: 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 --- plugins/ila-plugin/ila/ila.c | 390 ++++++++++++++++++++----------- plugins/ila-plugin/ila/ila.h | 27 ++- plugins/lb-plugin/lb/lb.c | 214 ++++++++--------- plugins/lb-plugin/lb/node.c | 58 ++--- plugins/sixrd-plugin/Makefile.am | 4 +- plugins/sixrd-plugin/sixrd/sixrd.c | 218 +++++++++-------- plugins/sixrd-plugin/sixrd/sixrd.h | 55 +++-- plugins/sixrd-plugin/sixrd/sixrd_dpo.c | 132 +++++++++++ plugins/sixrd-plugin/sixrd/sixrd_dpo.h | 61 +++++ plugins/vcgn-plugin/vcgn/vcgn_classify.c | 2 +- 10 files changed, 734 insertions(+), 427 deletions(-) create mode 100644 plugins/sixrd-plugin/sixrd/sixrd_dpo.c create mode 100644 plugins/sixrd-plugin/sixrd/sixrd_dpo.h (limited to 'plugins') 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 #include #include +#include +#include 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 #include +#include #include #include @@ -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 +#include +#include +#include + /* * 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 #include #include +#include + +#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 + +/** + * 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 +#include + +/** + * 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", -- cgit 1.2.3-korg