X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fsrv6%2Fsr_localsid.c;h=2e8b10d2987a30996b5a373c01240c09d1e40a5e;hb=79bfd272546dd436a4d12f0ac98571194965dab0;hp=bdc66386f32e6227fcffa2bf9f35b5ad6bd20607;hpb=5d73eecd63018db69b10bf56adeec9cc5cf92790;p=vpp.git diff --git a/src/vnet/srv6/sr_localsid.c b/src/vnet/srv6/sr_localsid.c index bdc66386f32..2e8b10d2987 100755 --- a/src/vnet/srv6/sr_localsid.c +++ b/src/vnet/srv6/sr_localsid.c @@ -64,12 +64,15 @@ static dpo_type_t sr_localsid_d_dpo_type; */ int sr_cli_localsid (char is_del, ip6_address_t * localsid_addr, - char end_psp, u8 behavior, u32 sw_if_index, u32 vlan_index, - u32 fib_table, ip46_address_t * nh_addr, void *ls_plugin_mem) + u16 localsid_prefix_len, char end_psp, u8 behavior, + u32 sw_if_index, u32 vlan_index, u32 fib_table, + ip46_address_t * nh_addr, void *ls_plugin_mem) { ip6_sr_main_t *sm = &sr_main; uword *p; int rv; + u8 pref_length = 128; + sr_localsid_fn_registration_t *plugin = 0; ip6_sr_localsid_t *ls = 0; @@ -84,18 +87,30 @@ sr_cli_localsid (char is_del, ip6_address_t * localsid_addr, { /* Retrieve localsid */ ls = pool_elt_at_index (sm->localsids, p[0]); + if (ls->behavior >= SR_BEHAVIOR_LAST) + { + plugin = pool_elt_at_index (sm->plugin_functions, + ls->behavior - SR_BEHAVIOR_LAST); + pref_length = plugin->prefix_length; + } + + if (localsid_prefix_len != 0) + { + pref_length = localsid_prefix_len; + } + /* Delete FIB entry */ fib_prefix_t pfx = { .fp_proto = FIB_PROTOCOL_IP6, - .fp_len = 128, + .fp_len = pref_length, .fp_addr = { .ip6 = *localsid_addr, } }; - fib_table_entry_delete (fib_table_find (FIB_PROTOCOL_IP6, - fib_table), - &pfx, FIB_SOURCE_SR); + fib_table_entry_delete (fib_table_find + (FIB_PROTOCOL_IP6, fib_table), &pfx, + FIB_SOURCE_SR); /* In case it is a Xconnect iface remove the (OIF, NHOP) adj */ if (ls->behavior == SR_BEHAVIOR_X || ls->behavior == SR_BEHAVIOR_DX6 @@ -104,10 +119,6 @@ sr_cli_localsid (char is_del, ip6_address_t * localsid_addr, if (ls->behavior >= SR_BEHAVIOR_LAST) { - sr_localsid_fn_registration_t *plugin = 0; - plugin = pool_elt_at_index (sm->plugin_functions, - ls->behavior - SR_BEHAVIOR_LAST); - /* Callback plugin removal function */ rv = plugin->removal (ls); } @@ -115,7 +126,7 @@ sr_cli_localsid (char is_del, ip6_address_t * localsid_addr, /* Delete localsid registry */ pool_put (sm->localsids, ls); mhash_unset (&sm->sr_localsids_index_hash, localsid_addr, NULL); - return 1; + return 0; } else /* create with function already existing; complain */ return -1; @@ -125,15 +136,28 @@ sr_cli_localsid (char is_del, ip6_address_t * localsid_addr, if (is_del) return -2; + if (behavior >= SR_BEHAVIOR_LAST) + { + sr_localsid_fn_registration_t *plugin = 0; + plugin = + pool_elt_at_index (sm->plugin_functions, behavior - SR_BEHAVIOR_LAST); + pref_length = plugin->prefix_length; + } + /* Check whether there exists a FIB entry with such address */ fib_prefix_t pfx = { .fp_proto = FIB_PROTOCOL_IP6, - .fp_len = 128, + .fp_len = pref_length, }; pfx.fp_addr.as_u64[0] = localsid_addr->as_u64[0]; pfx.fp_addr.as_u64[1] = localsid_addr->as_u64[1]; + if (pref_length != 0) + { + pfx.fp_len = pref_length; + } + /* Lookup the FIB index associated to the table id provided */ u32 fib_index = fib_table_find (FIB_PROTOCOL_IP6, fib_table); if (fib_index == ~0) @@ -146,9 +170,10 @@ sr_cli_localsid (char is_del, ip6_address_t * localsid_addr, /* Create a new localsid registry */ pool_get (sm->localsids, ls); - memset (ls, 0, sizeof (*ls)); + clib_memset (ls, 0, sizeof (*ls)); clib_memcpy (&ls->localsid, localsid_addr, sizeof (ip6_address_t)); + ls->localsid_prefix_len = pref_length; ls->end_psp = end_psp; ls->behavior = behavior; ls->nh_adj = (u32) ~ 0; @@ -161,6 +186,9 @@ sr_cli_localsid (char is_del, ip6_address_t * localsid_addr, ls->sw_if_index = sw_if_index; clib_memcpy (&ls->next_hop.ip6, &nh_addr->ip6, sizeof (ip6_address_t)); break; + case SR_BEHAVIOR_T: + ls->vrf_index = fib_table_find (FIB_PROTOCOL_IP6, sw_if_index); + break; case SR_BEHAVIOR_DX4: ls->sw_if_index = sw_if_index; clib_memcpy (&ls->next_hop.ip4, &nh_addr->ip4, sizeof (ip4_address_t)); @@ -170,7 +198,10 @@ sr_cli_localsid (char is_del, ip6_address_t * localsid_addr, clib_memcpy (&ls->next_hop.ip6, &nh_addr->ip6, sizeof (ip6_address_t)); break; case SR_BEHAVIOR_DT6: - ls->vrf_index = sw_if_index; + ls->vrf_index = fib_table_find (FIB_PROTOCOL_IP6, sw_if_index); + break; + case SR_BEHAVIOR_DT4: + ls->vrf_index = fib_table_find (FIB_PROTOCOL_IP4, sw_if_index); break; case SR_BEHAVIOR_DX2: ls->sw_if_index = sw_if_index; @@ -204,7 +235,8 @@ sr_cli_localsid (char is_del, ip6_address_t * localsid_addr, } /* Set DPO */ - if (ls->behavior == SR_BEHAVIOR_END || ls->behavior == SR_BEHAVIOR_X) + if (ls->behavior == SR_BEHAVIOR_END || ls->behavior == SR_BEHAVIOR_X + || ls->behavior == SR_BEHAVIOR_T) dpo_set (&dpo, sr_localsid_dpo_type, DPO_PROTO_IP6, ls - sm->localsids); else if (ls->behavior > SR_BEHAVIOR_D_FIRST && ls->behavior < SR_BEHAVIOR_LAST) @@ -260,6 +292,7 @@ sr_cli_localsid_command_fn (vlib_main_t * vm, unformat_input_t * input, vnet_main_t *vnm = vnet_get_main (); ip6_sr_main_t *sm = &sr_main; u32 sw_if_index = (u32) ~ 0, vlan_index = (u32) ~ 0, fib_index = 0; + u16 prefix_len = 0; int is_del = 0; int end_psp = 0; ip6_address_t resulting_address; @@ -270,13 +303,17 @@ sr_cli_localsid_command_fn (vlib_main_t * vm, unformat_input_t * input, int rv; - memset (&resulting_address, 0, sizeof (ip6_address_t)); + clib_memset (&resulting_address, 0, sizeof (ip6_address_t)); ip46_address_reset (&next_hop); while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "del")) is_del = 1; + else if (!address_set + && unformat (input, "address %U/%u", unformat_ip6_address, + &resulting_address, &prefix_len)) + address_set = 1; else if (!address_set && unformat (input, "address %U", unformat_ip6_address, &resulting_address)) @@ -294,6 +331,8 @@ sr_cli_localsid_command_fn (vlib_main_t * vm, unformat_input_t * input, unformat_vnet_sw_interface, vnm, &sw_if_index, unformat_ip6_address, &next_hop.ip6)) behavior = SR_BEHAVIOR_X; + else if (unformat (input, "end.t %u", &sw_if_index)) + behavior = SR_BEHAVIOR_T; else if (unformat (input, "end.dx6 %U %U", unformat_vnet_sw_interface, vnm, &sw_if_index, unformat_ip6_address, &next_hop.ip6)) @@ -316,12 +355,12 @@ sr_cli_localsid_command_fn (vlib_main_t * vm, unformat_input_t * input, sr_localsid_fn_registration_t **plugin_it = 0; /* Create a vector out of the plugin pool as recommended */ - /* *INDENT-OFF* */ - pool_foreach (plugin, sm->plugin_functions, - { - vec_add1 (vec_plugins, plugin); - }); - /* *INDENT-ON* */ + /* *INDENT-OFF* */ + pool_foreach (plugin, sm->plugin_functions, + { + vec_add1 (vec_plugins, plugin); + }); + /* *INDENT-ON* */ vec_foreach (plugin_it, vec_plugins) { @@ -364,9 +403,10 @@ sr_cli_localsid_command_fn (vlib_main_t * vm, unformat_input_t * input, return clib_error_return (0, "Error: SRv6 PSP only compatible with End and End.X"); - rv = sr_cli_localsid (is_del, &resulting_address, end_psp, behavior, - sw_if_index, vlan_index, fib_index, &next_hop, - ls_plugin_mem); + rv = + sr_cli_localsid (is_del, &resulting_address, prefix_len, end_psp, + behavior, sw_if_index, vlan_index, fib_index, &next_hop, + ls_plugin_mem); switch (rv) { @@ -450,39 +490,53 @@ show_sr_localsid_command_fn (vlib_main_t * vm, unformat_input_t * input, switch (ls->behavior) { case SR_BEHAVIOR_END: - vlib_cli_output (vm, "\tAddress: \t%U\n\tBehavior: \tEnd", - format_ip6_address, &ls->localsid); + vlib_cli_output (vm, "\tAddress: \t%U/%u\n\tBehavior: \tEnd", + format_ip6_address, &ls->localsid, + ls->localsid_prefix_len); break; case SR_BEHAVIOR_X: vlib_cli_output (vm, - "\tAddress: \t%U\n\tBehavior: \tX (Endpoint with Layer-3 cross-connect)" + "\tAddress: \t%U/%u\n\tBehavior: \tX (Endpoint with Layer-3 cross-connect)" "\n\tIface: \t%U\n\tNext hop: \t%U", format_ip6_address, &ls->localsid, + ls->localsid_prefix_len, format_vnet_sw_if_index_name, vnm, ls->sw_if_index, format_ip6_address, &ls->next_hop.ip6); break; + case SR_BEHAVIOR_T: + vlib_cli_output (vm, + "\tAddress: \t%U/%u\n\tBehavior: \tT (Endpoint with specific IPv6 table lookup)" + "\n\tTable: \t%u", + format_ip6_address, &ls->localsid, + ls->localsid_prefix_len, + fib_table_get_table_id (ls->vrf_index, + FIB_PROTOCOL_IP6)); + break; case SR_BEHAVIOR_DX4: vlib_cli_output (vm, - "\tAddress: \t%U\n\tBehavior: \tDX4 (Endpoint with decapsulation and IPv4 cross-connect)" + "\tAddress: \t%U/%u\n\tBehavior: \tDX4 (Endpoint with decapsulation and IPv4 cross-connect)" "\n\tIface: \t%U\n\tNext hop: \t%U", format_ip6_address, &ls->localsid, + ls->localsid_prefix_len, format_vnet_sw_if_index_name, vnm, ls->sw_if_index, format_ip4_address, &ls->next_hop.ip4); break; case SR_BEHAVIOR_DX6: vlib_cli_output (vm, - "\tAddress: \t%U\n\tBehavior: \tDX6 (Endpoint with decapsulation and IPv6 cross-connect)" + "\tAddress: \t%U/%u\n\tBehavior: \tDX6 (Endpoint with decapsulation and IPv6 cross-connect)" "\n\tIface: \t%U\n\tNext hop: \t%U", format_ip6_address, &ls->localsid, + ls->localsid_prefix_len, format_vnet_sw_if_index_name, vnm, ls->sw_if_index, format_ip6_address, &ls->next_hop.ip6); break; case SR_BEHAVIOR_DX2: if (ls->vlan_index == (u32) ~ 0) vlib_cli_output (vm, - "\tAddress: \t%U\n\tBehavior: \tDX2 (Endpoint with decapulation and Layer-2 cross-connect)" + "\tAddress: \t%U/%u\n\tBehavior: \tDX2 (Endpoint with decapulation and Layer-2 cross-connect)" "\n\tIface: \t%U", format_ip6_address, - &ls->localsid, format_vnet_sw_if_index_name, vnm, + &ls->localsid, ls->localsid_prefix_len, + format_vnet_sw_if_index_name, vnm, ls->sw_if_index); else vlib_cli_output (vm, @@ -490,15 +544,19 @@ show_sr_localsid_command_fn (vlib_main_t * vm, unformat_input_t * input, break; case SR_BEHAVIOR_DT6: vlib_cli_output (vm, - "\tAddress: \t%U\n\tBehavior: \tDT6 (Endpoint with decapsulation and specific IPv6 table lookup)" + "\tAddress: \t%U/%u\n\tBehavior: \tDT6 (Endpoint with decapsulation and specific IPv6 table lookup)" "\n\tTable: %u", format_ip6_address, &ls->localsid, - ls->fib_table); + ls->localsid_prefix_len, + fib_table_get_table_id (ls->vrf_index, + FIB_PROTOCOL_IP6)); break; case SR_BEHAVIOR_DT4: vlib_cli_output (vm, - "\tAddress: \t%U\n\tBehavior: \tDT4 (Endpoint with decapsulation and specific IPv4 table lookup)" + "\tAddress: \t%U/%u\n\tBehavior: \tDT4 (Endpoint with decapsulation and specific IPv4 table lookup)" "\n\tTable: \t%u", format_ip6_address, - &ls->localsid, ls->fib_table); + &ls->localsid, ls->localsid_prefix_len, + fib_table_get_table_id (ls->vrf_index, + FIB_PROTOCOL_IP4)); break; default: if (ls->behavior >= SR_BEHAVIOR_LAST) @@ -507,11 +565,12 @@ show_sr_localsid_command_fn (vlib_main_t * vm, unformat_input_t * input, pool_elt_at_index (sm->plugin_functions, ls->behavior - SR_BEHAVIOR_LAST); - vlib_cli_output (vm, "\tAddress: \t%U\n" + vlib_cli_output (vm, "\tAddress: \t%U/%u\n" "\tBehavior: \t%s (%s)\n\t%U", format_ip6_address, &ls->localsid, - plugin->keyword_str, plugin->def_str, - plugin->ls_format, ls->plugin_mem); + ls->localsid_prefix_len, plugin->keyword_str, + plugin->def_str, plugin->ls_format, + ls->plugin_mem); } else //Should never get here... @@ -560,8 +619,8 @@ clear_sr_localsid_counters_command_fn (vlib_main_t * vm, /* *INDENT-OFF* */ VLIB_CLI_COMMAND (clear_sr_localsid_counters_command, static) = { - .path = "clear sr localsid counters", - .short_help = "clear sr localsid counters", + .path = "clear sr localsid-counters", + .short_help = "clear sr localsid-counters", .function = clear_sr_localsid_counters_command_fn, }; /* *INDENT-ON* */ @@ -572,12 +631,11 @@ VLIB_CLI_COMMAND (clear_sr_localsid_counters_command, static) = { */ typedef struct { - u32 localsid_index; - ip6_address_t src, out_dst; + ip6_address_t localsid; + u16 behavior; u8 sr[256]; u8 num_segments; u8 segments_left; - //With SRv6 header update include flags here. } sr_localsid_trace_t; #define foreach_sr_localsid_error \ @@ -628,16 +686,12 @@ format_sr_localsid_trace (u8 * s, va_list * args) { CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); - ip6_sr_main_t *sm = &sr_main; sr_localsid_trace_t *t = va_arg (*args, sr_localsid_trace_t *); - ip6_sr_localsid_t *ls = - pool_elt_at_index (sm->localsids, t->localsid_index); - s = format (s, "SR-LOCALSID:\n\tLocalsid: %U\n", format_ip6_address, - &ls->localsid); - switch (ls->behavior) + &t->localsid); + switch (t->behavior) { case SR_BEHAVIOR_END: s = format (s, "\tBehavior: End\n"); @@ -651,6 +705,9 @@ format_sr_localsid_trace (u8 * s, va_list * args) case SR_BEHAVIOR_X: s = format (s, "\tBehavior: IPv6 L3 xconnect\n"); break; + case SR_BEHAVIOR_T: + s = format (s, "\tBehavior: IPv6 specific table lookup\n"); + break; case SR_BEHAVIOR_DT6: s = format (s, "\tBehavior: Decapsulation with IPv6 Table lookup\n"); break; @@ -668,7 +725,7 @@ format_sr_localsid_trace (u8 * s, va_list * args) { if (t->num_segments > 0) { - s = format (s, "\tSegments left: %d\n", t->num_segments); + s = format (s, "\tSegments left: %d\n", t->segments_left); s = format (s, "\tSID list: [in ietf order]"); int i = 0; for (i = 0; i < t->num_segments; i++) @@ -690,13 +747,64 @@ end_srh_processing (vlib_node_runtime_t * node, vlib_buffer_t * b0, ip6_header_t * ip0, ip6_sr_header_t * sr0, - ip6_sr_localsid_t * ls0, u32 * next0) + ip6_sr_localsid_t * ls0, + u32 * next0, u8 psp, ip6_ext_header_t * prev0) { ip6_address_t *new_dst0; - if (PREDICT_TRUE (sr0->type == ROUTING_HEADER_TYPE_SR)) + if (PREDICT_TRUE (sr0 && sr0->type == ROUTING_HEADER_TYPE_SR)) { - if (PREDICT_TRUE (sr0->segments_left != 0)) + if (sr0->segments_left == 1 && psp) + { + u32 new_l0, sr_len; + u64 *copy_dst0, *copy_src0; + u32 copy_len_u64s0 = 0; + + ip0->dst_address.as_u64[0] = sr0->segments->as_u64[0]; + ip0->dst_address.as_u64[1] = sr0->segments->as_u64[1]; + + /* Remove the SRH taking care of the rest of IPv6 ext header */ + if (prev0) + prev0->next_hdr = sr0->protocol; + else + ip0->protocol = sr0->protocol; + + sr_len = ip6_ext_header_len (sr0); + vlib_buffer_advance (b0, sr_len); + new_l0 = clib_net_to_host_u16 (ip0->payload_length) - sr_len; + ip0->payload_length = clib_host_to_net_u16 (new_l0); + copy_src0 = (u64 *) ip0; + copy_dst0 = copy_src0 + (sr0->length + 1); + /* number of 8 octet units to copy + * By default in absence of extension headers it is equal to length of ip6 header + * With extension headers it number of 8 octet units of ext headers preceding + * SR header + */ + copy_len_u64s0 = + (((u8 *) sr0 - (u8 *) ip0) - sizeof (ip6_header_t)) >> 3; + copy_dst0[4 + copy_len_u64s0] = copy_src0[4 + copy_len_u64s0]; + copy_dst0[3 + copy_len_u64s0] = copy_src0[3 + copy_len_u64s0]; + copy_dst0[2 + copy_len_u64s0] = copy_src0[2 + copy_len_u64s0]; + copy_dst0[1 + copy_len_u64s0] = copy_src0[1 + copy_len_u64s0]; + copy_dst0[0 + copy_len_u64s0] = copy_src0[0 + copy_len_u64s0]; + + int i; + for (i = copy_len_u64s0 - 1; i >= 0; i--) + { + copy_dst0[i] = copy_src0[i]; + } + + if (ls0->behavior == SR_BEHAVIOR_X) + { + vnet_buffer (b0)->ip.adj_index[VLIB_TX] = ls0->nh_adj; + *next0 = SR_LOCALSID_NEXT_IP6_REWRITE; + } + else if (ls0->behavior == SR_BEHAVIOR_T) + { + vnet_buffer (b0)->sw_if_index[VLIB_TX] = ls0->vrf_index; + } + } + else if (PREDICT_TRUE (sr0->segments_left > 0)) { sr0->segments_left -= 1; new_dst0 = (ip6_address_t *) (sr0->segments); @@ -709,6 +817,10 @@ end_srh_processing (vlib_node_runtime_t * node, vnet_buffer (b0)->ip.adj_index[VLIB_TX] = ls0->nh_adj; *next0 = SR_LOCALSID_NEXT_IP6_REWRITE; } + else if (ls0->behavior == SR_BEHAVIOR_T) + { + vnet_buffer (b0)->sw_if_index[VLIB_TX] = ls0->vrf_index; + } } else { @@ -727,7 +839,6 @@ end_srh_processing (vlib_node_runtime_t * node, /* * @brief Function doing SRH processing for D* variants */ -//FixME. I must crosscheck that next_proto matches the localsid static_always_inline void end_decaps_srh_processing (vlib_node_runtime_t * node, vlib_buffer_t * b0, @@ -772,7 +883,7 @@ end_decaps_srh_processing (vlib_node_runtime_t * node, else if (ls0->behavior == SR_BEHAVIOR_DT6) { vlib_buffer_advance (b0, total_size); - vnet_buffer (b0)->sw_if_index[VLIB_TX] = ls0->fib_table; + vnet_buffer (b0)->sw_if_index[VLIB_TX] = ls0->vrf_index; return; } break; @@ -788,12 +899,12 @@ end_decaps_srh_processing (vlib_node_runtime_t * node, else if (ls0->behavior == SR_BEHAVIOR_DT4) { vlib_buffer_advance (b0, total_size); - vnet_buffer (b0)->sw_if_index[VLIB_TX] = ls0->fib_table; + vnet_buffer (b0)->sw_if_index[VLIB_TX] = ls0->vrf_index; *next0 = SR_LOCALSID_NEXT_IP4_LOOKUP; return; } break; - case IP_PROTOCOL_IP6_NONXT: + case IP_PROTOCOL_IP6_ETHERNET: /* L2 encaps */ if (ls0->behavior == SR_BEHAVIOR_DX2) { @@ -810,73 +921,7 @@ end_decaps_srh_processing (vlib_node_runtime_t * node, } /** - * @brief Function doing End processing with PSP - */ -static_always_inline void -end_psp_srh_processing (vlib_node_runtime_t * node, - vlib_buffer_t * b0, - ip6_header_t * ip0, - ip6_ext_header_t * prev0, - ip6_sr_header_t * sr0, - ip6_sr_localsid_t * ls0, u32 * next0) -{ - u32 new_l0, sr_len; - u64 *copy_dst0, *copy_src0; - u32 copy_len_u64s0 = 0; - int i; - - if (PREDICT_TRUE (sr0->type == ROUTING_HEADER_TYPE_SR)) - { - if (PREDICT_TRUE (sr0->segments_left == 1)) - { - ip0->dst_address.as_u64[0] = sr0->segments->as_u64[0]; - ip0->dst_address.as_u64[1] = sr0->segments->as_u64[1]; - - /* Remove the SRH taking care of the rest of IPv6 ext header */ - if (prev0) - prev0->next_hdr = sr0->protocol; - else - ip0->protocol = sr0->protocol; - - sr_len = ip6_ext_header_len (sr0); - vlib_buffer_advance (b0, sr_len); - new_l0 = clib_net_to_host_u16 (ip0->payload_length) - sr_len; - ip0->payload_length = clib_host_to_net_u16 (new_l0); - copy_src0 = (u64 *) ip0; - copy_dst0 = copy_src0 + (sr0->length + 1); - /* number of 8 octet units to copy - * By default in absence of extension headers it is equal to length of ip6 header - * With extension headers it number of 8 octet units of ext headers preceding - * SR header - */ - copy_len_u64s0 = - (((u8 *) sr0 - (u8 *) ip0) - sizeof (ip6_header_t)) >> 3; - copy_dst0[4 + copy_len_u64s0] = copy_src0[4 + copy_len_u64s0]; - copy_dst0[3 + copy_len_u64s0] = copy_src0[3 + copy_len_u64s0]; - copy_dst0[2 + copy_len_u64s0] = copy_src0[2 + copy_len_u64s0]; - copy_dst0[1 + copy_len_u64s0] = copy_src0[1 + copy_len_u64s0]; - copy_dst0[0 + copy_len_u64s0] = copy_src0[0 + copy_len_u64s0]; - - for (i = copy_len_u64s0 - 1; i >= 0; i--) - { - copy_dst0[i] = copy_src0[i]; - } - - if (ls0->behavior == SR_BEHAVIOR_X) - { - vnet_buffer (b0)->ip.adj_index[VLIB_TX] = ls0->nh_adj; - *next0 = SR_LOCALSID_NEXT_IP6_REWRITE; - } - return; - } - } - /* Error. Routing header of type != SR */ - *next0 = SR_LOCALSID_NEXT_ERROR; - b0->error = node->errors[SR_LOCALSID_ERROR_NO_PSP]; -} - -/** - * @brief SR LocalSID graph node. Supports all default SR Endpoint variants + * @brief SR LocalSID graph node. Supports all default SR Endpoint variants with decaps */ static uword sr_localsid_d_fn (vlib_main_t * vm, vlib_node_runtime_t * node, @@ -887,7 +932,7 @@ sr_localsid_d_fn (vlib_main_t * vm, vlib_node_runtime_t * node, from = vlib_frame_vector_args (from_frame); n_left_from = from_frame->n_vectors; next_index = node->cached_next_index; - u32 thread_index = vlib_get_thread_index (); + u32 thread_index = vm->thread_index; while (n_left_from > 0) { @@ -900,7 +945,6 @@ sr_localsid_d_fn (vlib_main_t * vm, vlib_node_runtime_t * node, u32 bi0, bi1, bi2, bi3; vlib_buffer_t *b0, *b1, *b2, *b3; ip6_header_t *ip0, *ip1, *ip2, *ip3; - ip6_ext_header_t *prev0, *prev1, *prev2, *prev3; ip6_sr_header_t *sr0, *sr1, *sr2, *sr3; u32 next0, next1, next2, next3; next0 = next1 = next2 = next3 = SR_LOCALSID_NEXT_IP6_LOOKUP; @@ -946,30 +990,124 @@ sr_localsid_d_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vnet_buffer (b0)->ip.adj_index[VLIB_TX]); ls1 = pool_elt_at_index (sm->localsids, - vnet_buffer (b0)->ip.adj_index[VLIB_TX]); + vnet_buffer (b1)->ip.adj_index[VLIB_TX]); ls2 = pool_elt_at_index (sm->localsids, - vnet_buffer (b0)->ip.adj_index[VLIB_TX]); + vnet_buffer (b2)->ip.adj_index[VLIB_TX]); ls3 = pool_elt_at_index (sm->localsids, - vnet_buffer (b0)->ip.adj_index[VLIB_TX]); + vnet_buffer (b3)->ip.adj_index[VLIB_TX]); ip0 = vlib_buffer_get_current (b0); ip1 = vlib_buffer_get_current (b1); ip2 = vlib_buffer_get_current (b2); ip3 = vlib_buffer_get_current (b3); - ip6_ext_header_find_t (ip0, prev0, sr0, IP_PROTOCOL_IPV6_ROUTE); - ip6_ext_header_find_t (ip1, prev1, sr1, IP_PROTOCOL_IPV6_ROUTE); - ip6_ext_header_find_t (ip2, prev2, sr2, IP_PROTOCOL_IPV6_ROUTE); - ip6_ext_header_find_t (ip3, prev3, sr3, IP_PROTOCOL_IPV6_ROUTE); + sr0 = + ip6_ext_header_find (vm, b0, ip0, IP_PROTOCOL_IPV6_ROUTE, NULL); + sr1 = + ip6_ext_header_find (vm, b1, ip1, IP_PROTOCOL_IPV6_ROUTE, NULL); + sr2 = + ip6_ext_header_find (vm, b2, ip2, IP_PROTOCOL_IPV6_ROUTE, NULL); + sr3 = + ip6_ext_header_find (vm, b3, ip3, IP_PROTOCOL_IPV6_ROUTE, NULL); end_decaps_srh_processing (node, b0, ip0, sr0, ls0, &next0); end_decaps_srh_processing (node, b1, ip1, sr1, ls1, &next1); end_decaps_srh_processing (node, b2, ip2, sr2, ls2, &next2); end_decaps_srh_processing (node, b3, ip3, sr3, ls3, &next3); - //TODO: trace. + if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) + { + sr_localsid_trace_t *tr = + vlib_add_trace (vm, node, b0, sizeof (*tr)); + tr->num_segments = 0; + clib_memcpy (tr->localsid.as_u8, ls0->localsid.as_u8, + sizeof (tr->localsid.as_u8)); + tr->behavior = ls0->behavior; + if (ip0 == vlib_buffer_get_current (b0)) + { + if (ip0->protocol == IP_PROTOCOL_IPV6_ROUTE + && sr0->type == ROUTING_HEADER_TYPE_SR) + { + clib_memcpy (tr->sr, sr0->segments, sr0->length * 8); + tr->num_segments = + sr0->length * 8 / sizeof (ip6_address_t); + tr->segments_left = sr0->segments_left; + } + } + else + tr->num_segments = 0xFF; + } + + if (PREDICT_FALSE (b1->flags & VLIB_BUFFER_IS_TRACED)) + { + sr_localsid_trace_t *tr = + vlib_add_trace (vm, node, b1, sizeof (*tr)); + tr->num_segments = 0; + clib_memcpy (tr->localsid.as_u8, ls1->localsid.as_u8, + sizeof (tr->localsid.as_u8)); + tr->behavior = ls1->behavior; + if (ip1 == vlib_buffer_get_current (b1)) + { + if (ip1->protocol == IP_PROTOCOL_IPV6_ROUTE + && sr1->type == ROUTING_HEADER_TYPE_SR) + { + clib_memcpy (tr->sr, sr1->segments, sr1->length * 8); + tr->num_segments = + sr1->length * 8 / sizeof (ip6_address_t); + tr->segments_left = sr1->segments_left; + } + } + else + tr->num_segments = 0xFF; + } + + if (PREDICT_FALSE (b2->flags & VLIB_BUFFER_IS_TRACED)) + { + sr_localsid_trace_t *tr = + vlib_add_trace (vm, node, b2, sizeof (*tr)); + tr->num_segments = 0; + clib_memcpy (tr->localsid.as_u8, ls2->localsid.as_u8, + sizeof (tr->localsid.as_u8)); + tr->behavior = ls2->behavior; + if (ip2 == vlib_buffer_get_current (b2)) + { + if (ip2->protocol == IP_PROTOCOL_IPV6_ROUTE + && sr2->type == ROUTING_HEADER_TYPE_SR) + { + clib_memcpy (tr->sr, sr2->segments, sr2->length * 8); + tr->num_segments = + sr2->length * 8 / sizeof (ip6_address_t); + tr->segments_left = sr2->segments_left; + } + } + else + tr->num_segments = 0xFF; + } + + if (PREDICT_FALSE (b3->flags & VLIB_BUFFER_IS_TRACED)) + { + sr_localsid_trace_t *tr = + vlib_add_trace (vm, node, b3, sizeof (*tr)); + tr->num_segments = 0; + clib_memcpy (tr->localsid.as_u8, ls3->localsid.as_u8, + sizeof (tr->localsid.as_u8)); + tr->behavior = ls3->behavior; + if (ip3 == vlib_buffer_get_current (b3)) + { + if (ip3->protocol == IP_PROTOCOL_IPV6_ROUTE + && sr3->type == ROUTING_HEADER_TYPE_SR) + { + clib_memcpy (tr->sr, sr3->segments, sr3->length * 8); + tr->num_segments = + sr3->length * 8 / sizeof (ip6_address_t); + tr->segments_left = sr3->segments_left; + } + } + else + tr->num_segments = 0xFF; + } vlib_increment_combined_counter (((next0 == @@ -1006,7 +1144,6 @@ sr_localsid_d_fn (vlib_main_t * vm, vlib_node_runtime_t * node, u32 bi0; vlib_buffer_t *b0; ip6_header_t *ip0; - ip6_ext_header_t *prev0; ip6_sr_header_t *sr0; u32 next0 = SR_LOCALSID_NEXT_IP6_LOOKUP; ip6_sr_localsid_t *ls0; @@ -1027,7 +1164,8 @@ sr_localsid_d_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vnet_buffer (b0)->ip.adj_index[VLIB_TX]); /* Find SRH as well as previous header */ - ip6_ext_header_find_t (ip0, prev0, sr0, IP_PROTOCOL_IPV6_ROUTE); + sr0 = + ip6_ext_header_find (vm, b0, ip0, IP_PROTOCOL_IPV6_ROUTE, NULL); /* SRH processing and End variants */ end_decaps_srh_processing (node, b0, ip0, sr0, ls0, &next0); @@ -1037,14 +1175,11 @@ sr_localsid_d_fn (vlib_main_t * vm, vlib_node_runtime_t * node, sr_localsid_trace_t *tr = vlib_add_trace (vm, node, b0, sizeof (*tr)); tr->num_segments = 0; - tr->localsid_index = ls0 - sm->localsids; - + clib_memcpy (tr->localsid.as_u8, ls0->localsid.as_u8, + sizeof (tr->localsid.as_u8)); + tr->behavior = ls0->behavior; if (ip0 == vlib_buffer_get_current (b0)) { - clib_memcpy (tr->src.as_u8, ip0->src_address.as_u8, - sizeof (tr->src.as_u8)); - clib_memcpy (tr->out_dst.as_u8, ip0->dst_address.as_u8, - sizeof (tr->out_dst.as_u8)); if (ip0->protocol == IP_PROTOCOL_IPV6_ROUTE && sr0->type == ROUTING_HEADER_TYPE_SR) { @@ -1092,7 +1227,7 @@ VLIB_REGISTER_NODE (sr_localsid_d_node) = { /* *INDENT-ON* */ /** - * @brief SR LocalSID graph node. Supports all default SR Endpoint variants + * @brief SR LocalSID graph node. Supports all default SR Endpoint without decaps */ static uword sr_localsid_fn (vlib_main_t * vm, vlib_node_runtime_t * node, @@ -1103,7 +1238,7 @@ sr_localsid_fn (vlib_main_t * vm, vlib_node_runtime_t * node, from = vlib_frame_vector_args (from_frame); n_left_from = from_frame->n_vectors; next_index = node->cached_next_index; - u32 thread_index = vlib_get_thread_index (); + u32 thread_index = vm->thread_index; while (n_left_from > 0) { @@ -1162,45 +1297,128 @@ sr_localsid_fn (vlib_main_t * vm, vlib_node_runtime_t * node, ip2 = vlib_buffer_get_current (b2); ip3 = vlib_buffer_get_current (b3); - ip6_ext_header_find_t (ip0, prev0, sr0, IP_PROTOCOL_IPV6_ROUTE); - ip6_ext_header_find_t (ip1, prev1, sr1, IP_PROTOCOL_IPV6_ROUTE); - ip6_ext_header_find_t (ip2, prev2, sr2, IP_PROTOCOL_IPV6_ROUTE); - ip6_ext_header_find_t (ip3, prev3, sr3, IP_PROTOCOL_IPV6_ROUTE); + sr0 = + ip6_ext_header_find (vm, b0, ip0, IP_PROTOCOL_IPV6_ROUTE, &prev0); + sr1 = + ip6_ext_header_find (vm, b1, ip1, IP_PROTOCOL_IPV6_ROUTE, &prev1); + sr2 = + ip6_ext_header_find (vm, b2, ip2, IP_PROTOCOL_IPV6_ROUTE, &prev2); + sr3 = + ip6_ext_header_find (vm, b3, ip3, IP_PROTOCOL_IPV6_ROUTE, &prev3); ls0 = pool_elt_at_index (sm->localsids, vnet_buffer (b0)->ip.adj_index[VLIB_TX]); ls1 = pool_elt_at_index (sm->localsids, - vnet_buffer (b0)->ip.adj_index[VLIB_TX]); + vnet_buffer (b1)->ip.adj_index[VLIB_TX]); ls2 = pool_elt_at_index (sm->localsids, - vnet_buffer (b0)->ip.adj_index[VLIB_TX]); + vnet_buffer (b2)->ip.adj_index[VLIB_TX]); ls3 = pool_elt_at_index (sm->localsids, - vnet_buffer (b0)->ip.adj_index[VLIB_TX]); + vnet_buffer (b3)->ip.adj_index[VLIB_TX]); - if (ls0->end_psp) - end_psp_srh_processing (node, b0, ip0, prev0, sr0, ls0, &next0); - else - end_srh_processing (node, b0, ip0, sr0, ls0, &next0); + end_srh_processing (node, b0, ip0, sr0, ls0, &next0, ls0->end_psp, + prev0); + end_srh_processing (node, b1, ip1, sr1, ls1, &next1, ls1->end_psp, + prev1); + end_srh_processing (node, b2, ip2, sr2, ls2, &next2, ls2->end_psp, + prev2); + end_srh_processing (node, b3, ip3, sr3, ls3, &next3, ls3->end_psp, + prev3); - if (ls1->end_psp) - end_psp_srh_processing (node, b1, ip1, prev1, sr1, ls1, &next1); - else - end_srh_processing (node, b1, ip1, sr1, ls1, &next1); + if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) + { + sr_localsid_trace_t *tr = + vlib_add_trace (vm, node, b0, sizeof (*tr)); + tr->num_segments = 0; + clib_memcpy (tr->localsid.as_u8, ls0->localsid.as_u8, + sizeof (tr->localsid.as_u8)); + tr->behavior = ls0->behavior; + if (ip0 == vlib_buffer_get_current (b0)) + { + if (ip0->protocol == IP_PROTOCOL_IPV6_ROUTE + && sr0->type == ROUTING_HEADER_TYPE_SR) + { + clib_memcpy (tr->sr, sr0->segments, sr0->length * 8); + tr->num_segments = + sr0->length * 8 / sizeof (ip6_address_t); + tr->segments_left = sr0->segments_left; + } + } + else + tr->num_segments = 0xFF; + } - if (ls2->end_psp) - end_psp_srh_processing (node, b2, ip2, prev2, sr2, ls2, &next2); - else - end_srh_processing (node, b2, ip2, sr2, ls2, &next2); + if (PREDICT_FALSE (b1->flags & VLIB_BUFFER_IS_TRACED)) + { + sr_localsid_trace_t *tr = + vlib_add_trace (vm, node, b1, sizeof (*tr)); + tr->num_segments = 0; + clib_memcpy (tr->localsid.as_u8, ls1->localsid.as_u8, + sizeof (tr->localsid.as_u8)); + tr->behavior = ls1->behavior; + if (ip1 == vlib_buffer_get_current (b1)) + { + if (ip1->protocol == IP_PROTOCOL_IPV6_ROUTE + && sr1->type == ROUTING_HEADER_TYPE_SR) + { + clib_memcpy (tr->sr, sr1->segments, sr1->length * 8); + tr->num_segments = + sr1->length * 8 / sizeof (ip6_address_t); + tr->segments_left = sr1->segments_left; + } + } + else + tr->num_segments = 0xFF; + } - if (ls3->end_psp) - end_psp_srh_processing (node, b3, ip3, prev3, sr3, ls3, &next3); - else - end_srh_processing (node, b3, ip3, sr3, ls3, &next3); + if (PREDICT_FALSE (b2->flags & VLIB_BUFFER_IS_TRACED)) + { + sr_localsid_trace_t *tr = + vlib_add_trace (vm, node, b2, sizeof (*tr)); + tr->num_segments = 0; + clib_memcpy (tr->localsid.as_u8, ls2->localsid.as_u8, + sizeof (tr->localsid.as_u8)); + tr->behavior = ls2->behavior; + if (ip2 == vlib_buffer_get_current (b2)) + { + if (ip2->protocol == IP_PROTOCOL_IPV6_ROUTE + && sr2->type == ROUTING_HEADER_TYPE_SR) + { + clib_memcpy (tr->sr, sr2->segments, sr2->length * 8); + tr->num_segments = + sr2->length * 8 / sizeof (ip6_address_t); + tr->segments_left = sr2->segments_left; + } + } + else + tr->num_segments = 0xFF; + } - //TODO: proper trace. + if (PREDICT_FALSE (b3->flags & VLIB_BUFFER_IS_TRACED)) + { + sr_localsid_trace_t *tr = + vlib_add_trace (vm, node, b3, sizeof (*tr)); + tr->num_segments = 0; + clib_memcpy (tr->localsid.as_u8, ls3->localsid.as_u8, + sizeof (tr->localsid.as_u8)); + tr->behavior = ls3->behavior; + if (ip3 == vlib_buffer_get_current (b3)) + { + if (ip3->protocol == IP_PROTOCOL_IPV6_ROUTE + && sr3->type == ROUTING_HEADER_TYPE_SR) + { + clib_memcpy (tr->sr, sr3->segments, sr3->length * 8); + tr->num_segments = + sr3->length * 8 / sizeof (ip6_address_t); + tr->segments_left = sr3->segments_left; + } + } + else + tr->num_segments = 0xFF; + } vlib_increment_combined_counter (((next0 == @@ -1251,7 +1469,8 @@ sr_localsid_fn (vlib_main_t * vm, vlib_node_runtime_t * node, b0 = vlib_get_buffer (vm, bi0); ip0 = vlib_buffer_get_current (b0); - ip6_ext_header_find_t (ip0, prev0, sr0, IP_PROTOCOL_IPV6_ROUTE); + sr0 = + ip6_ext_header_find (vm, b0, ip0, IP_PROTOCOL_IPV6_ROUTE, &prev0); /* Lookup the SR End behavior based on IP DA (adj) */ ls0 = @@ -1259,24 +1478,19 @@ sr_localsid_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vnet_buffer (b0)->ip.adj_index[VLIB_TX]); /* SRH processing */ - if (ls0->end_psp) - end_psp_srh_processing (node, b0, ip0, prev0, sr0, ls0, &next0); - else - end_srh_processing (node, b0, ip0, sr0, ls0, &next0); + end_srh_processing (node, b0, ip0, sr0, ls0, &next0, ls0->end_psp, + prev0); if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) { sr_localsid_trace_t *tr = vlib_add_trace (vm, node, b0, sizeof (*tr)); tr->num_segments = 0; - tr->localsid_index = ls0 - sm->localsids; - + clib_memcpy (tr->localsid.as_u8, ls0->localsid.as_u8, + sizeof (tr->localsid.as_u8)); + tr->behavior = ls0->behavior; if (ip0 == vlib_buffer_get_current (b0)) { - clib_memcpy (tr->src.as_u8, ip0->src_address.as_u8, - sizeof (tr->src.as_u8)); - clib_memcpy (tr->out_dst.as_u8, ip0->dst_address.as_u8, - sizeof (tr->out_dst.as_u8)); if (ip0->protocol == IP_PROTOCOL_IPV6_ROUTE && sr0->type == ROUTING_HEADER_TYPE_SR) { @@ -1287,9 +1501,7 @@ sr_localsid_fn (vlib_main_t * vm, vlib_node_runtime_t * node, } } else - { - tr->num_segments = 0xFF; - } + tr->num_segments = 0xFF; } vlib_increment_combined_counter @@ -1365,7 +1577,8 @@ const static char *const *const sr_loc_d_nodes[DPO_PROTO_NUM] = { int sr_localsid_register_function (vlib_main_t * vm, u8 * fn_name, u8 * keyword_str, u8 * def_str, - u8 * params_str, dpo_type_t * dpo, + u8 * params_str, u8 prefix_length, + dpo_type_t * dpo, format_function_t * ls_format, unformat_function_t * ls_unformat, sr_plugin_callback_t * creation_fn, @@ -1390,10 +1603,11 @@ sr_localsid_register_function (vlib_main_t * vm, u8 * fn_name, plugin - sm->plugin_functions); } - memset (plugin, 0, sizeof (*plugin)); + clib_memset (plugin, 0, sizeof (*plugin)); plugin->sr_localsid_function_number = (plugin - sm->plugin_functions); plugin->sr_localsid_function_number += SR_BEHAVIOR_LAST; + plugin->prefix_length = prefix_length; plugin->ls_format = ls_format; plugin->ls_unformat = ls_unformat; plugin->creation = creation_fn; @@ -1431,8 +1645,10 @@ show_sr_localsid_behaviors_command_fn (vlib_main_t * vm, /* Print static behaviors */ vlib_cli_output (vm, "Default behaviors:\n" "\tEnd\t-> Endpoint.\n" - "\tEnd.X\t-> Endpoint with decapsulation and Layer-3 cross-connect.\n" + "\tEnd.X\t-> Endpoint with Layer-3 cross-connect.\n" "\t\tParameters: ' '\n" + "\tEnd.T\t-> Endpoint with specific IPv6 table lookup.\n" + "\t\tParameters: ''\n" "\tEnd.DX2\t-> Endpoint with decapsulation and Layer-2 cross-connect.\n" "\t\tParameters: ''\n" "\tEnd.DX6\t-> Endpoint with decapsulation and IPv6 cross-connect.\n"