diff options
Diffstat (limited to 'src/vnet/srv6')
-rw-r--r--[-rwxr-xr-x] | src/vnet/srv6/dir.dox | 0 | ||||
-rw-r--r-- | src/vnet/srv6/sr.api | 116 | ||||
-rw-r--r-- | src/vnet/srv6/sr.h | 18 | ||||
-rw-r--r-- | src/vnet/srv6/sr_api.c | 256 | ||||
-rw-r--r-- | src/vnet/srv6/sr_localsid.c | 22 | ||||
-rw-r--r-- | src/vnet/srv6/sr_packet.h | 18 | ||||
-rw-r--r-- | src/vnet/srv6/sr_policy_rewrite.c | 180 | ||||
-rw-r--r-- | src/vnet/srv6/sr_pt.api | 59 | ||||
-rw-r--r-- | src/vnet/srv6/sr_pt.c | 281 | ||||
-rw-r--r-- | src/vnet/srv6/sr_pt.h | 89 | ||||
-rw-r--r-- | src/vnet/srv6/sr_pt_api.c | 97 | ||||
-rw-r--r-- | src/vnet/srv6/sr_pt_node.c | 175 | ||||
-rw-r--r-- | src/vnet/srv6/sr_steering.c | 13 | ||||
-rw-r--r-- | src/vnet/srv6/sr_test.c | 23 |
14 files changed, 1213 insertions, 134 deletions
diff --git a/src/vnet/srv6/dir.dox b/src/vnet/srv6/dir.dox index 3f539a58ef1..3f539a58ef1 100755..100644 --- a/src/vnet/srv6/dir.dox +++ b/src/vnet/srv6/dir.dox diff --git a/src/vnet/srv6/sr.api b/src/vnet/srv6/sr.api index 6190a8c7ff5..4766ce3ba11 100644 --- a/src/vnet/srv6/sr.api +++ b/src/vnet/srv6/sr.api @@ -14,7 +14,7 @@ * limitations under the License. */ -option version = "2.0.0"; +option version = "2.1.0"; import "vnet/interface_types.api"; import "vnet/ip/ip_types.api"; @@ -109,6 +109,65 @@ autoreply define sr_policy_mod vl_api_srv6_sid_list_t sids; }; +enum sr_policy_type : u8 +{ + SR_API_POLICY_TYPE_DEFAULT = 0, + SR_API_POLICY_TYPE_SPRAY = 1, + SR_API_POLICY_TYPE_TEF = 2, +}; + +/** \brief IPv6 SR policy add + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param bsid is the bindingSID of the SR Policy + @param weight is the weight of the sid list. optional. + @param is_encap is the behavior of the SR policy. (0.SRH insert // 1.Encapsulation) + @param type is the SR policy param. (0.Default // 1.Spray // 2.Tef) + @param fib_table is the VRF where to install the FIB entry for the BSID + @param sids is a srv6_sid_list object + @param encap_src is a encaps IPv6 source addr. optional. +*/ +autoreply define sr_policy_add_v2 +{ + u32 client_index; + u32 context; + vl_api_ip6_address_t bsid_addr; + u32 weight; + bool is_encap; + vl_api_sr_policy_type_t type [default=0x0]; + u32 fib_table; + vl_api_srv6_sid_list_t sids; + vl_api_ip6_address_t encap_src; + option status="in_progress"; +}; + +/** \brief IPv6 SR policy modification + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param bsid is the bindingSID of the SR Policy + @param sr_policy_index is the index of the SR policy + @param fib_table is the VRF where to install the FIB entry for the BSID + @param operation is the operation to perform (among the top ones) + @param sl_index is the index of the Segment List to modify/delete + @param weight is the weight of the sid list. optional. + @param sids is a srv6_sid_list object + @param encap_src is a encaps IPv6 source addr. optional. +*/ +autoreply define sr_policy_mod_v2 +{ + u32 client_index; + u32 context; + vl_api_ip6_address_t bsid_addr; + u32 sr_policy_index; + u32 fib_table; + vl_api_sr_policy_op_t operation; + u32 sl_index; + u32 weight; + vl_api_srv6_sid_list_t sids; + vl_api_ip6_address_t encap_src; + option status="in_progress"; +}; + /** \brief IPv6 SR policy deletion @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request @@ -195,12 +254,45 @@ define sr_localsids_details u32 xconnect_iface_or_vrf_table; }; + +/** \brief Dump the list of SR LocalSIDs along with packet statistics + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request +*/ +define sr_localsids_with_packet_stats_dump +{ + u32 client_index; + u32 context; + option status="in_progress"; +}; + +define sr_localsids_with_packet_stats_details +{ + u32 context; + vl_api_ip6_address_t addr; + bool end_psp; + vl_api_sr_behavior_t behavior; + u32 fib_table; + u32 vlan_index; + vl_api_address_t xconnect_nh_addr; + u32 xconnect_iface_or_vrf_table; + u64 good_traffic_bytes; + u64 good_traffic_pkt_count; + u64 bad_traffic_bytes; + u64 bad_traffic_pkt_count; + option status="in_progress"; +}; + + + /** \brief Dump the list of SR policies @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request */ define sr_policies_dump { + option deprecated; + u32 client_index; u32 context; }; @@ -217,6 +309,28 @@ define sr_policies_details vl_api_srv6_sid_list_t sid_lists[num_sid_lists]; }; +/** \brief Dump the list of SR policies v2 + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request +*/ +define sr_policies_v2_dump +{ + u32 client_index; + u32 context; +}; + +define sr_policies_v2_details +{ + u32 context; + vl_api_ip6_address_t bsid; + vl_api_ip6_address_t encap_src; + vl_api_sr_policy_type_t type; + bool is_encap; + u32 fib_table; + u8 num_sid_lists; + vl_api_srv6_sid_list_t sid_lists[num_sid_lists]; +}; + /** \brief Dump the list of SR policies along with actual segment list index on VPP @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request diff --git a/src/vnet/srv6/sr.h b/src/vnet/srv6/sr.h index ea9ff709feb..c2867eb7508 100644 --- a/src/vnet/srv6/sr.h +++ b/src/vnet/srv6/sr.h @@ -56,13 +56,11 @@ #define SR_SEGMENT_LIST_WEIGHT_DEFAULT 1 -/* *INDENT-OFF* */ typedef struct { ip6_header_t ip; ip6_sr_header_t sr; } __attribute__ ((packed)) ip6srv_combo_header_t; -/* *INDENT-ON* */ /** * @brief SR Segment List (SID list) @@ -90,6 +88,7 @@ typedef struct /* SR policy types */ #define SR_POLICY_TYPE_DEFAULT 0 #define SR_POLICY_TYPE_SPRAY 1 +#define SR_POLICY_TYPE_TEF 2 /** * @brief SR Policy */ @@ -111,6 +110,8 @@ typedef struct u8 is_encap; /**< Mode (0 is SRH insert, 1 Encaps) */ + ip6_address_t encap_src; + u16 plugin; void *plugin_mem; } ip6_sr_policy_t; @@ -128,7 +129,7 @@ typedef struct char end_psp; /**< Combined with End.PSP? */ - u16 behavior; /**< Behavior associated to this localsid */ + u8 behavior; /**< Behavior associated to this localsid */ union { @@ -344,11 +345,12 @@ sr_policy_register_function (vlib_main_t * vm, u8 * fn_name, sr_p_plugin_callback_t * removal_fn); extern int sr_policy_add (ip6_address_t *bsid, ip6_address_t *segments, - u32 weight, u8 type, u32 fib_table, u8 is_encap, - u16 plugin, void *plugin_mem); -extern int sr_policy_mod (ip6_address_t * bsid, u32 index, u32 fib_table, - u8 operation, ip6_address_t * segments, - u32 sl_index, u32 weight); + ip6_address_t *encap_src, u32 weight, u8 type, + u32 fib_table, u8 is_encap, u16 plugin, + void *plugin_mem); +extern int sr_policy_mod (ip6_address_t *bsid, u32 index, u32 fib_table, + u8 operation, ip6_address_t *segments, + ip6_address_t *encap_src, u32 sl_index, u32 weight); extern int sr_policy_del (ip6_address_t * bsid, u32 index); extern int diff --git a/src/vnet/srv6/sr_api.c b/src/vnet/srv6/sr_api.c index c68b355922b..a44c3098112 100644 --- a/src/vnet/srv6/sr_api.c +++ b/src/vnet/srv6/sr_api.c @@ -82,17 +82,16 @@ vl_api_sr_policy_add_t_handler (vl_api_sr_policy_add_t * mp) ip6_address_decode (mp->bsid_addr, &bsid_addr); -/* - * sr_policy_add (ip6_address_t *bsid, ip6_address_t *segments, - * u32 weight, u8 behavior, u32 fib_table, u8 is_encap, - * u16 behavior, void *plugin_mem) - */ + /* + * sr_policy_add (ip6_address_t *bsid, ip6_address_t *segments, + * ip6_address_t *encap_src, + * u32 weight, u8 behavior, u32 fib_table, u8 is_encap, + * u16 behavior, void *plugin_mem) + */ int rv = 0; - rv = sr_policy_add (&bsid_addr, - segments, - ntohl (mp->sids.weight), - mp->is_spray, ntohl (mp->fib_table), mp->is_encap, 0, - NULL); + rv = + sr_policy_add (&bsid_addr, segments, NULL, ntohl (mp->sids.weight), + mp->is_spray, ntohl (mp->fib_table), mp->is_encap, 0, NULL); vec_free (segments); REPLY_MACRO (VL_API_SR_POLICY_ADD_REPLY); @@ -115,18 +114,93 @@ vl_api_sr_policy_mod_t_handler (vl_api_sr_policy_mod_t * mp) ip6_address_decode (mp->bsid_addr, &bsid_addr); int rv = 0; -/* - * int - * sr_policy_mod(ip6_address_t *bsid, u32 index, u32 fib_table, - * u8 operation, ip6_address_t *segments, u32 sl_index, - * u32 weight, u8 is_encap) - */ - rv = sr_policy_mod (&bsid_addr, - ntohl (mp->sr_policy_index), - ntohl (mp->fib_table), - mp->operation, - segments, ntohl (mp->sl_index), - ntohl (mp->sids.weight)); + /* + * int + * sr_policy_mod(ip6_address_t *bsid, u32 index, u32 fib_table, + * u8 operation, ip6_address_t *segments, + * ip6_address_t *encap_src, u32 sl_index, + * u32 weight, u8 is_encap) + */ + rv = sr_policy_mod (&bsid_addr, ntohl (mp->sr_policy_index), + ntohl (mp->fib_table), mp->operation, segments, NULL, + ntohl (mp->sl_index), ntohl (mp->sids.weight)); + vec_free (segments); + + REPLY_MACRO (VL_API_SR_POLICY_MOD_REPLY); +} + +static void +vl_api_sr_policy_add_v2_t_handler (vl_api_sr_policy_add_v2_t *mp) +{ + vl_api_sr_policy_add_v2_reply_t *rmp; + ip6_address_t *segments = 0, *seg; + ip6_address_t bsid_addr; + ip6_address_t encap_src; + + int i; + for (i = 0; i < mp->sids.num_sids; i++) + { + vec_add2 (segments, seg, 1); + ip6_address_decode (mp->sids.sids[i], seg); + } + + ip6_address_decode (mp->bsid_addr, &bsid_addr); + ip6_address_decode (mp->encap_src, &encap_src); + + if (ip6_address_is_zero (&encap_src)) + { + encap_src = *sr_get_encaps_source (); + } + /* + * sr_policy_add (ip6_address_t *bsid, ip6_address_t *segments, + * ip6_address_t *encap_src, + * u32 weight, u8 behavior, u32 fib_table, u8 is_encap, + * u16 behavior, void *plugin_mem) + */ + int rv = 0; + rv = + sr_policy_add (&bsid_addr, segments, &encap_src, ntohl (mp->sids.weight), + mp->type, ntohl (mp->fib_table), mp->is_encap, 0, NULL); + vec_free (segments); + + REPLY_MACRO (VL_API_SR_POLICY_ADD_V2_REPLY); +} + +static void +vl_api_sr_policy_mod_v2_t_handler (vl_api_sr_policy_mod_v2_t *mp) +{ + vl_api_sr_policy_mod_v2_reply_t *rmp; + ip6_address_t *segments = 0, *seg; + ip6_address_t bsid_addr; + ip6_address_t encap_src; + + int i; + for (i = 0; i < mp->sids.num_sids; i++) + { + vec_add2 (segments, seg, 1); + ip6_address_decode (mp->sids.sids[i], seg); + } + + ip6_address_decode (mp->bsid_addr, &bsid_addr); + ip6_address_decode (mp->encap_src, &encap_src); + + if (ip6_address_is_zero (&encap_src)) + { + encap_src = *sr_get_encaps_source (); + } + + int rv = 0; + /* + * int + * sr_policy_mod(ip6_address_t *bsid, u32 index, u32 fib_table, + * u8 operation, ip6_address_t *segments, + * ip6_address_t *encap_src, u32 sl_index, + * u32 weight, u8 is_encap) + */ + rv = + sr_policy_mod (&bsid_addr, ntohl (mp->sr_policy_index), + ntohl (mp->fib_table), mp->operation, segments, &encap_src, + ntohl (mp->sl_index), ntohl (mp->sids.weight)); vec_free (segments); REPLY_MACRO (VL_API_SR_POLICY_MOD_REPLY); @@ -217,7 +291,7 @@ static void send_sr_localsid_details rmp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_SR_LOCALSIDS_DETAILS); ip6_address_encode (&t->localsid, rmp->addr); rmp->end_psp = t->end_psp; - rmp->behavior = htons (t->behavior); + rmp->behavior = t->behavior; rmp->fib_table = htonl (t->fib_table); rmp->vlan_index = htonl (t->vlan_index); ip_address_encode (&t->next_hop, IP46_TYPE_ANY, &rmp->xconnect_nh_addr); @@ -247,12 +321,77 @@ static void vl_api_sr_localsids_dump_t_handler if (!reg) return; - /* *INDENT-OFF* */ pool_foreach (t, sm->localsids) { send_sr_localsid_details(t, reg, mp->context); } - /* *INDENT-ON* */ +} + +static void +send_sr_localsid_with_packet_stats_details (int local_sid_index, + ip6_sr_localsid_t *t, + vl_api_registration_t *reg, + u32 context) +{ + vl_api_sr_localsids_with_packet_stats_details_t *rmp; + vlib_counter_t good_traffic, bad_traffic; + ip6_sr_main_t *sm = &sr_main; + + rmp = vl_msg_api_alloc (sizeof (*rmp)); + clib_memset (rmp, 0, sizeof (*rmp)); + rmp->_vl_msg_id = + ntohs (REPLY_MSG_ID_BASE + VL_API_SR_LOCALSIDS_WITH_PACKET_STATS_DETAILS); + ip6_address_encode (&t->localsid, rmp->addr); + rmp->end_psp = t->end_psp; + rmp->behavior = t->behavior; + rmp->fib_table = htonl (t->fib_table); + rmp->vlan_index = htonl (t->vlan_index); + ip_address_encode (&t->next_hop, IP46_TYPE_ANY, &rmp->xconnect_nh_addr); + + if (t->behavior == SR_BEHAVIOR_T || t->behavior == SR_BEHAVIOR_DT6) + rmp->xconnect_iface_or_vrf_table = + htonl (fib_table_get_table_id (t->sw_if_index, FIB_PROTOCOL_IP6)); + else if (t->behavior == SR_BEHAVIOR_DT4) + rmp->xconnect_iface_or_vrf_table = + htonl (fib_table_get_table_id (t->sw_if_index, FIB_PROTOCOL_IP4)); + else + rmp->xconnect_iface_or_vrf_table = htonl (t->sw_if_index); + + rmp->context = context; + vlib_get_combined_counter (&(sm->sr_ls_valid_counters), local_sid_index, + &good_traffic); + vlib_get_combined_counter (&(sm->sr_ls_invalid_counters), local_sid_index, + &bad_traffic); + rmp->good_traffic_bytes = clib_host_to_net_u64 (good_traffic.bytes); + rmp->good_traffic_pkt_count = clib_host_to_net_u64 (good_traffic.packets); + rmp->bad_traffic_bytes = clib_host_to_net_u64 (bad_traffic.bytes); + rmp->bad_traffic_pkt_count = clib_host_to_net_u64 (bad_traffic.packets); + vl_api_send_msg (reg, (u8 *) rmp); +} + +static void +vl_api_sr_localsids_with_packet_stats_dump_t_handler ( + vl_api_sr_localsids_with_packet_stats_dump_t *mp) +{ + vl_api_registration_t *reg; + ip6_sr_main_t *sm = &sr_main; + ip6_sr_localsid_t **localsid_list = 0; + ip6_sr_localsid_t *t; + int i; + + reg = vl_api_client_index_to_registration (mp->client_index); + if (!reg) + return; + + pool_foreach (t, sm->localsids) + { + vec_add1 (localsid_list, t); + } + for (i = 0; i < vec_len (localsid_list); i++) + { + t = localsid_list[i]; + send_sr_localsid_with_packet_stats_details (i, t, reg, mp->context); + } } static void send_sr_policies_details @@ -312,15 +451,74 @@ vl_api_sr_policies_dump_t_handler (vl_api_sr_policies_dump_t * mp) if (!reg) return; - /* *INDENT-OFF* */ pool_foreach (t, sm->sr_policies) { send_sr_policies_details(t, reg, mp->context); } - /* *INDENT-ON* */ } +static void +send_sr_policies_v2_details (ip6_sr_policy_t *t, vl_api_registration_t *reg, + u32 context) +{ + vl_api_sr_policies_v2_details_t *rmp; + ip6_sr_main_t *sm = &sr_main; + + u32 *sl_index, slidx = 0; + ip6_sr_sl_t *segment_list = 0; + ip6_address_t *segment; + vl_api_srv6_sid_list_t *api_sid_list; + + rmp = vl_msg_api_alloc (sizeof (*rmp) + vec_len (t->segments_lists) * + sizeof (vl_api_srv6_sid_list_t)); + clib_memset (rmp, 0, + (sizeof (*rmp) + vec_len (t->segments_lists) * + sizeof (vl_api_srv6_sid_list_t))); + + rmp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_SR_POLICIES_V2_DETAILS); + ip6_address_encode (&t->bsid, rmp->bsid); + ip6_address_encode (&t->encap_src, rmp->encap_src); + rmp->is_encap = t->is_encap; + rmp->type = t->type; + rmp->fib_table = htonl (t->fib_table); + rmp->num_sid_lists = vec_len (t->segments_lists); + + /* Fill in all the segments lists */ + vec_foreach (sl_index, t->segments_lists) + { + segment_list = pool_elt_at_index (sm->sid_lists, *sl_index); + + api_sid_list = &rmp->sid_lists[sl_index - t->segments_lists]; + + api_sid_list->num_sids = vec_len (segment_list->segments); + api_sid_list->weight = htonl (segment_list->weight); + slidx = 0; + vec_foreach (segment, segment_list->segments) + { + ip6_address_encode (segment, api_sid_list->sids[slidx++]); + } + } + + rmp->context = context; + vl_api_send_msg (reg, (u8 *) rmp); +} + +static void +vl_api_sr_policies_v2_dump_t_handler (vl_api_sr_policies_v2_dump_t *mp) +{ + vl_api_registration_t *reg; + ip6_sr_main_t *sm = &sr_main; + ip6_sr_policy_t *t; + reg = vl_api_client_index_to_registration (mp->client_index); + if (!reg) + return; + + pool_foreach (t, sm->sr_policies) + { + send_sr_policies_v2_details (t, reg, mp->context); + } +} static void send_sr_policies_details_with_sl_index (ip6_sr_policy_t * t, vl_api_registration_t * reg, u32 context) @@ -381,12 +579,10 @@ static void if (!reg) return; - /* *INDENT-OFF* */ pool_foreach (t, sm->sr_policies) { send_sr_policies_details_with_sl_index(t, reg, mp->context); } - /* *INDENT-ON* */ } static void send_sr_steering_pol_details @@ -428,12 +624,10 @@ static void vl_api_sr_steering_pol_dump_t_handler if (!reg) return; - /* *INDENT-OFF* */ pool_foreach (t, sm->steer_policies) { send_sr_steering_pol_details(t, reg, mp->context); } - /* *INDENT-ON* */ } #include <vnet/srv6/sr.api.c> diff --git a/src/vnet/srv6/sr_localsid.c b/src/vnet/srv6/sr_localsid.c index a055c923be9..12349bb95e8 100644 --- a/src/vnet/srv6/sr_localsid.c +++ b/src/vnet/srv6/sr_localsid.c @@ -396,12 +396,10 @@ 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* */ vec_foreach (plugin_it, vec_plugins) { @@ -506,7 +504,6 @@ sr_cli_localsid_command_fn (vlib_main_t * vm, unformat_input_t * input, return 0; } -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (sr_localsid_command, static) = { .path = "sr localsid", .short_help = "sr localsid (del) address XX:XX::YY:YY" @@ -534,7 +531,6 @@ VLIB_CLI_COMMAND (sr_localsid_command, static) = { "\t\tParameters: '<ip4_fib_table>'\n", .function = sr_cli_localsid_command_fn, }; -/* *INDENT-ON* */ /** * @brief CLI function to 'show' all SR LocalSIDs on console. @@ -551,9 +547,7 @@ show_sr_localsid_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_output (vm, "SRv6 - My LocalSID Table:"); vlib_cli_output (vm, "========================="); - /* *INDENT-OFF* */ pool_foreach (ls, sm->localsids) { vec_add1 (localsid_list, ls); } - /* *INDENT-ON* */ for (i = 0; i < vec_len (localsid_list); i++) { ls = localsid_list[i]; @@ -676,13 +670,11 @@ show_sr_localsid_command_fn (vlib_main_t * vm, unformat_input_t * input, return 0; } -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (show_sr_localsid_command, static) = { .path = "show sr localsids", .short_help = "show sr localsids", .function = show_sr_localsid_command_fn, }; -/* *INDENT-ON* */ /** * @brief Function to 'clear' ALL SR localsid counters @@ -700,13 +692,11 @@ clear_sr_localsid_counters_command_fn (vlib_main_t * vm, return 0; } -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (clear_sr_localsid_counters_command, static) = { .path = "clear sr localsid-counters", .short_help = "clear sr localsid-counters", .function = clear_sr_localsid_counters_command_fn, }; -/* *INDENT-ON* */ /************************ SR LocalSID graphs node ****************************/ /** @@ -1438,7 +1428,6 @@ sr_localsid_d_fn (vlib_main_t * vm, vlib_node_runtime_t * node, return from_frame->n_vectors; } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (sr_localsid_d_node) = { .function = sr_localsid_d_fn, .name = "sr-localsid-d", @@ -1454,7 +1443,6 @@ VLIB_REGISTER_NODE (sr_localsid_d_node) = { #undef _ }, }; -/* *INDENT-ON* */ /** * @brief SR LocalSID graph node. Supports all default SR Endpoint without decaps @@ -1748,7 +1736,6 @@ sr_localsid_fn (vlib_main_t * vm, vlib_node_runtime_t * node, return from_frame->n_vectors; } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (sr_localsid_node) = { .function = sr_localsid_fn, .name = "sr-localsid", @@ -1764,7 +1751,6 @@ VLIB_REGISTER_NODE (sr_localsid_node) = { #undef _ }, }; -/* *INDENT-ON* */ /** * @brief SR LocalSID uN graph node. Supports all default SR Endpoint without decaps @@ -2058,7 +2044,6 @@ sr_localsid_un_fn (vlib_main_t * vm, vlib_node_runtime_t * node, return from_frame->n_vectors; } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (sr_localsid_un_node) = { .function = sr_localsid_un_fn, .name = "sr-localsid-un", @@ -2074,7 +2059,6 @@ VLIB_REGISTER_NODE (sr_localsid_un_node) = { #undef _ }, }; -/* *INDENT-ON* */ static uword sr_localsid_un_perf_fn (vlib_main_t * vm, vlib_node_runtime_t * node, @@ -2270,7 +2254,6 @@ sr_localsid_un_perf_fn (vlib_main_t * vm, vlib_node_runtime_t * node, return from_frame->n_vectors; } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (sr_localsid_un_perf_node) = { .function = sr_localsid_un_perf_fn, .name = "sr-localsid-un-perf", @@ -2286,7 +2269,6 @@ VLIB_REGISTER_NODE (sr_localsid_un_perf_node) = { #undef _ }, }; -/* *INDENT-ON* */ static u8 * format_sr_dpo (u8 * s, va_list * args) @@ -2406,10 +2388,8 @@ show_sr_localsid_behaviors_command_fn (vlib_main_t * vm, vlib_cli_output (vm, "SR LocalSIDs behaviors:\n-----------------------\n\n"); - /* *INDENT-OFF* */ pool_foreach (plugin, sm->plugin_functions) { vec_add1 (plugins_vec, plugin); } - /* *INDENT-ON* */ /* Print static behaviors */ vlib_cli_output (vm, "Default behaviors:\n" @@ -2439,13 +2419,11 @@ show_sr_localsid_behaviors_command_fn (vlib_main_t * vm, return 0; } -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (show_sr_localsid_behaviors_command, static) = { .path = "show sr localsids behaviors", .short_help = "show sr localsids behaviors", .function = show_sr_localsid_behaviors_command_fn, }; -/* *INDENT-ON* */ /** * @brief SR LocalSID initialization diff --git a/src/vnet/srv6/sr_packet.h b/src/vnet/srv6/sr_packet.h index dda776b4037..cf9fcb70bcc 100644 --- a/src/vnet/srv6/sr_packet.h +++ b/src/vnet/srv6/sr_packet.h @@ -116,6 +116,9 @@ #define ROUTING_HEADER_TYPE_SR 4 +#define IP6_SRH_PT_TLV_TYPE 128 +#define IP6_SRH_PT_TLV_LEN 14 + typedef struct { /* Protocol for next header. */ @@ -156,6 +159,21 @@ typedef struct u8 value[0]; } __attribute__ ((packed)) ip6_sr_tlv_t; +typedef struct +{ + u32 sec; + u32 nsec; +} __attribute__ ((packed)) timestamp_64_t; + +typedef struct +{ + u8 type; + u8 length; + u16 id_ld; + timestamp_64_t t64; + u16 session_id; + u16 seq_num; +} __attribute__ ((packed)) ip6_sr_pt_tlv_t; /* * fd.io coding-style-patch-verification: ON * diff --git a/src/vnet/srv6/sr_policy_rewrite.c b/src/vnet/srv6/sr_policy_rewrite.c index 500772e8065..0aa88cc273e 100644 --- a/src/vnet/srv6/sr_policy_rewrite.c +++ b/src/vnet/srv6/sr_policy_rewrite.c @@ -47,7 +47,9 @@ #include <vnet/fib/ip6_fib.h> #include <vnet/dpo/dpo.h> #include <vnet/dpo/replicate_dpo.h> +#include <vnet/srv6/sr_pt.h> +#include <vppinfra/byte_order.h> #include <vppinfra/error.h> #include <vppinfra/elog.h> @@ -140,13 +142,11 @@ set_sr_src_command_fn (vlib_main_t * vm, unformat_input_t * input, return clib_error_return (0, "No address specified"); } -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (set_sr_src_command, static) = { .path = "set sr encaps source", .short_help = "set sr encaps source addr <ip6_addr>", .function = set_sr_src_command_fn, }; -/* *INDENT-ON* */ /******************** SR rewrite set encaps IPv6 hop-limit ********************/ @@ -178,34 +178,40 @@ set_sr_hop_limit_command_fn (vlib_main_t * vm, unformat_input_t * input, return 0; } -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (set_sr_hop_limit_command, static) = { .path = "set sr encaps hop-limit", .short_help = "set sr encaps hop-limit <value>", .function = set_sr_hop_limit_command_fn, }; -/* *INDENT-ON* */ /*********************** SR rewrite string computation ************************/ /** * @brief SR rewrite string computation for IPv6 encapsulation (inline) * * @param sl is a vector of IPv6 addresses composing the Segment List + * @param src_v6addr is a encaps IPv6 source addr * * @return precomputed rewrite string for encapsulation */ static inline u8 * -compute_rewrite_encaps (ip6_address_t *sl, u8 type) +compute_rewrite_encaps (ip6_address_t *sl, ip6_address_t *src_v6addr, u8 type) { ip6_header_t *iph; ip6_sr_header_t *srh; + ip6_sr_pt_tlv_t *srh_pt_tlv; ip6_address_t *addrp, *this_address; u32 header_length = 0; u8 *rs = NULL; header_length = 0; header_length += IPv6_DEFAULT_HEADER_LENGTH; - if (vec_len (sl) > 1) + if (type == SR_POLICY_TYPE_TEF) + { + header_length += sizeof (ip6_sr_header_t); + header_length += vec_len (sl) * sizeof (ip6_address_t); + header_length += sizeof (ip6_sr_pt_tlv_t); + } + else if (vec_len (sl) > 1) { header_length += sizeof (ip6_sr_header_t); header_length += vec_len (sl) * sizeof (ip6_address_t); @@ -216,13 +222,39 @@ compute_rewrite_encaps (ip6_address_t *sl, u8 type) iph = (ip6_header_t *) rs; iph->ip_version_traffic_class_and_flow_label = clib_host_to_net_u32 (0 | ((6 & 0xF) << 28)); - iph->src_address.as_u64[0] = sr_pr_encaps_src.as_u64[0]; - iph->src_address.as_u64[1] = sr_pr_encaps_src.as_u64[1]; + iph->src_address.as_u64[0] = src_v6addr->as_u64[0]; + iph->src_address.as_u64[1] = src_v6addr->as_u64[1]; iph->payload_length = header_length - IPv6_DEFAULT_HEADER_LENGTH; iph->protocol = IP_PROTOCOL_IPV6; iph->hop_limit = sr_pr_encaps_hop_limit; - if (vec_len (sl) > 1) + if (type == SR_POLICY_TYPE_TEF) + { + srh = (ip6_sr_header_t *) (iph + 1); + iph->protocol = IP_PROTOCOL_IPV6_ROUTE; + srh->protocol = IP_PROTOCOL_IPV6; + srh->type = ROUTING_HEADER_TYPE_SR; + srh->flags = 0x00; + srh->tag = 0x0000; + srh->segments_left = vec_len (sl) - 1; + srh->last_entry = vec_len (sl) - 1; + srh->length = + ((sizeof (ip6_sr_header_t) + (vec_len (sl) * sizeof (ip6_address_t)) + + sizeof (ip6_sr_pt_tlv_t)) / + 8) - + 1; + addrp = srh->segments + vec_len (sl) - 1; + vec_foreach (this_address, sl) + { + clib_memcpy_fast (addrp->as_u8, this_address->as_u8, + sizeof (ip6_address_t)); + addrp--; + } + srh_pt_tlv = (ip6_sr_pt_tlv_t *) (srh->segments + vec_len (sl)); + srh_pt_tlv->type = IP6_SRH_PT_TLV_TYPE; + srh_pt_tlv->length = IP6_SRH_PT_TLV_LEN; + } + else if (vec_len (sl) > 1) { srh = (ip6_sr_header_t *) (iph + 1); iph->protocol = IP_PROTOCOL_IPV6_ROUTE; @@ -335,18 +367,20 @@ compute_rewrite_bsid (ip6_address_t * sl) * * @param sr_policy is the SR policy where the SL will be added * @param sl is a vector of IPv6 addresses composing the Segment List + * @param encap_src is a encaps IPv6 source addr. optional. * @param weight is the weight of the SegmentList (for load-balancing purposes) * @param is_encap represents the mode (SRH insertion vs Encapsulation) * * @return pointer to the just created segment list */ static inline ip6_sr_sl_t * -create_sl (ip6_sr_policy_t * sr_policy, ip6_address_t * sl, u32 weight, - u8 is_encap) +create_sl (ip6_sr_policy_t *sr_policy, ip6_address_t *sl, + ip6_address_t *encap_src, u32 weight, u8 is_encap) { ip6_sr_main_t *sm = &sr_main; ip6_sr_sl_t *segment_list; sr_policy_fn_registration_t *plugin = 0; + ip6_address_t encap_srcv6 = sr_pr_encaps_src; pool_get (sm->sid_lists, segment_list); clib_memset (segment_list, 0, sizeof (*segment_list)); @@ -365,8 +399,14 @@ create_sl (ip6_sr_policy_t * sr_policy, ip6_address_t * sl, u32 weight, if (is_encap) { - segment_list->rewrite = compute_rewrite_encaps (sl, sr_policy->type); + if (encap_src) + { + clib_memcpy_fast (&encap_srcv6, encap_src, sizeof (ip6_address_t)); + } + segment_list->rewrite = + compute_rewrite_encaps (sl, &encap_srcv6, sr_policy->type); segment_list->rewrite_bsid = segment_list->rewrite; + sr_policy->encap_src = encap_srcv6; } else { @@ -625,17 +665,19 @@ update_replicate (ip6_sr_policy_t * sr_policy) * * @param bsid is the bindingSID of the SR Policy * @param segments is a vector of IPv6 address composing the segment list + * @param encap_src is a encaps IPv6 source addr. optional. * @param weight is the weight of the sid list. optional. * @param behavior is the behavior of the SR policy. (default//spray) * @param fib_table is the VRF where to install the FIB entry for the BSID - * @param is_encap (bool) whether SR policy should behave as Encap/SRH Insertion + * @param is_encap (bool) whether SR policy should behave as Encap/SRH + * Insertion * * @return 0 if correct, else error */ int -sr_policy_add (ip6_address_t *bsid, ip6_address_t *segments, u32 weight, - u8 type, u32 fib_table, u8 is_encap, u16 plugin, - void *ls_plugin_mem) +sr_policy_add (ip6_address_t *bsid, ip6_address_t *segments, + ip6_address_t *encap_src, u32 weight, u8 type, u32 fib_table, + u8 is_encap, u16 plugin, void *ls_plugin_mem) { ip6_sr_main_t *sm = &sr_main; ip6_sr_policy_t *sr_policy = 0; @@ -691,7 +733,7 @@ sr_policy_add (ip6_address_t *bsid, ip6_address_t *segments, u32 weight, NULL); /* Create a segment list and add the index to the SR policy */ - create_sl (sr_policy, segments, weight, is_encap); + create_sl (sr_policy, segments, encap_src, weight, is_encap); /* If FIB doesnt exist, create them */ if (sm->fib_table_ip6 == (u32) ~ 0) @@ -705,7 +747,8 @@ sr_policy_add (ip6_address_t *bsid, ip6_address_t *segments, u32 weight, } /* Create IPv6 FIB for the BindingSID attached to the DPO of the only SL */ - if (sr_policy->type == SR_POLICY_TYPE_DEFAULT) + if (sr_policy->type == SR_POLICY_TYPE_DEFAULT || + sr_policy->type == SR_POLICY_TYPE_TEF) update_lb (sr_policy); else if (sr_policy->type == SR_POLICY_TYPE_SPRAY) update_replicate (sr_policy); @@ -740,8 +783,6 @@ sr_policy_del (ip6_address_t * bsid, u32 index) else { sr_policy = pool_elt_at_index (sm->sr_policies, index); - if (!sr_policy) - return -1; } /* Remove BindingSID FIB entry */ @@ -822,6 +863,7 @@ sr_policy_del (ip6_address_t * bsid, u32 index) * @param fib_table is the VRF where to install the FIB entry for the BSID * @param operation is the operation to perform (among the top ones) * @param segments is a vector of IPv6 address composing the segment list + * @param encap_src is a encaps IPv6 source addr. optional. * @param sl_index is the index of the Segment List to modify/delete * @param weight is the weight of the sid list. optional. * @param is_encap Mode. Encapsulation or SRH insertion. @@ -829,8 +871,8 @@ sr_policy_del (ip6_address_t * bsid, u32 index) * @return 0 if correct, else error */ int -sr_policy_mod (ip6_address_t * bsid, u32 index, u32 fib_table, - u8 operation, ip6_address_t * segments, u32 sl_index, +sr_policy_mod (ip6_address_t *bsid, u32 index, u32 fib_table, u8 operation, + ip6_address_t *segments, ip6_address_t *encap_src, u32 sl_index, u32 weight) { ip6_sr_main_t *sm = &sr_main; @@ -850,15 +892,13 @@ sr_policy_mod (ip6_address_t * bsid, u32 index, u32 fib_table, else { sr_policy = pool_elt_at_index (sm->sr_policies, index); - if (!sr_policy) - return -1; } if (operation == 1) /* Add SR List to an existing SR policy */ { /* Create the new SL */ - segment_list = - create_sl (sr_policy, segments, weight, sr_policy->is_encap); + segment_list = create_sl (sr_policy, segments, encap_src, weight, + sr_policy->is_encap); /* Create a new LB DPO */ if (sr_policy->type == SR_POLICY_TYPE_DEFAULT) @@ -931,7 +971,7 @@ sr_policy_command_fn (vlib_main_t * vm, unformat_input_t * input, int rv = -1; char is_del = 0, is_add = 0, is_mod = 0; char policy_set = 0; - ip6_address_t bsid, next_address; + ip6_address_t bsid, next_address, src_v6addr; u32 sr_policy_index = (u32) ~ 0, sl_index = (u32) ~ 0; u32 weight = (u32) ~ 0, fib_table = (u32) ~ 0; ip6_address_t *segments = 0, *this_seg; @@ -940,6 +980,7 @@ sr_policy_command_fn (vlib_main_t * vm, unformat_input_t * input, u8 type = SR_POLICY_TYPE_DEFAULT; u16 behavior = 0; void *ls_plugin_mem = 0; + ip6_address_t *encap_src = 0; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { @@ -963,6 +1004,10 @@ sr_policy_command_fn (vlib_main_t * vm, unformat_input_t * input, clib_memcpy_fast (this_seg->as_u8, next_address.as_u8, sizeof (*this_seg)); } + else if (unformat (input, "v6src %U", unformat_ip6_address, &src_v6addr)) + { + encap_src = &src_v6addr; + } else if (unformat (input, "add sl")) operation = 1; else if (unformat (input, "del sl index %d", &sl_index)) @@ -977,17 +1022,17 @@ sr_policy_command_fn (vlib_main_t * vm, unformat_input_t * input, is_encap = 0; else if (unformat (input, "spray")) type = SR_POLICY_TYPE_SPRAY; + else if (unformat (input, "tef")) + type = SR_POLICY_TYPE_TEF; else if (!behavior && unformat (input, "behavior")) { sr_policy_fn_registration_t *plugin = 0, **vec_plugins = 0; sr_policy_fn_registration_t **plugin_it = 0; - /* *INDENT-OFF* */ pool_foreach (plugin, sm->policy_plugin_functions) { vec_add1 (vec_plugins, plugin); } - /* *INDENT-ON* */ vec_foreach (plugin_it, vec_plugins) { @@ -1025,8 +1070,8 @@ sr_policy_command_fn (vlib_main_t * vm, unformat_input_t * input, if (vec_len (segments) == 0) return clib_error_return (0, "No Segment List specified"); - rv = sr_policy_add (&bsid, segments, weight, type, fib_table, is_encap, - behavior, ls_plugin_mem); + rv = sr_policy_add (&bsid, segments, encap_src, weight, type, fib_table, + is_encap, behavior, ls_plugin_mem); vec_free (segments); } @@ -1044,9 +1089,9 @@ sr_policy_command_fn (vlib_main_t * vm, unformat_input_t * input, if (operation == 3 && weight == (u32) ~ 0) return clib_error_return (0, "No new weight for the SL specified"); - rv = sr_policy_mod ((sr_policy_index != (u32) ~ 0 ? NULL : &bsid), + rv = sr_policy_mod ((sr_policy_index != (u32) ~0 ? NULL : &bsid), sr_policy_index, fib_table, operation, segments, - sl_index, weight); + encap_src, sl_index, weight); if (segments) vec_free (segments); @@ -1082,7 +1127,6 @@ sr_policy_command_fn (vlib_main_t * vm, unformat_input_t * input, return 0; } -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (sr_policy_command, static) = { .path = "sr policy", .short_help = "sr policy [add||del||mod] [bsid 2001::1||index 5] " @@ -1102,7 +1146,6 @@ VLIB_CLI_COMMAND (sr_policy_command, static) = { "SID lists.\n", .function = sr_policy_command_fn, }; -/* *INDENT-ON* */ /** * @brief CLI to display onscreen all the SR policies @@ -1122,10 +1165,8 @@ show_sr_policies_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_output (vm, "SR policies:"); - /* *INDENT-OFF* */ pool_foreach (sr_policy, sm->sr_policies) {vec_add1 (vec_policies, sr_policy); } - /* *INDENT-ON* */ vec_foreach_index (i, vec_policies) { @@ -1136,11 +1177,20 @@ show_sr_policies_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_output (vm, "\tBehavior: %s", (sr_policy->is_encap ? "Encapsulation" : "SRH insertion")); + if (sr_policy->is_encap) + { + vlib_cli_output (vm, "\tEncapSrcIP: %U", format_ip6_address, + &sr_policy->encap_src); + } switch (sr_policy->type) { case SR_POLICY_TYPE_SPRAY: vlib_cli_output (vm, "\tType: %s", "Spray"); break; + case SR_POLICY_TYPE_TEF: + vlib_cli_output (vm, "\tType: %s", + "TEF (Timestamp, Encapsulate, and Forward)"); + break; default: vlib_cli_output (vm, "\tType: %s", "Default"); break; @@ -1168,13 +1218,11 @@ show_sr_policies_command_fn (vlib_main_t * vm, unformat_input_t * input, return 0; } -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (show_sr_policies_command, static) = { .path = "show sr policies", .short_help = "show sr policies", .function = show_sr_policies_command_fn, }; -/* *INDENT-ON* */ /** * @brief CLI to display onscreen the SR encaps source addr @@ -1189,13 +1237,11 @@ show_sr_encaps_source_command_fn (vlib_main_t * vm, unformat_input_t * input, return 0; } -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (show_sr_encaps_source_command, static) = { .path = "show sr encaps source addr", .short_help = "show sr encaps source addr", .function = show_sr_encaps_source_command_fn, }; -/* *INDENT-ON* */ /** * @brief CLI to display onscreen the hop-limit value used for SRv6 encapsulation @@ -1210,13 +1256,11 @@ show_sr_encaps_hop_limit_command_fn (vlib_main_t * vm, return 0; } -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (show_sr_encaps_hop_limit_command, static) = { .path = "show sr encaps hop-limit", .short_help = "show sr encaps hop-limit", .function = show_sr_encaps_hop_limit_command_fn, }; -/* *INDENT-ON* */ /*************************** SR rewrite graph node ****************************/ /** @@ -1236,6 +1280,36 @@ format_sr_policy_rewrite_trace (u8 * s, va_list * args) return s; } +/** + * @brief SRv6 TEF (Timestamp, Encapsulate, and Forward) behavior + */ +static_always_inline void +srv6_tef_behavior (vlib_node_runtime_t *node, vlib_buffer_t *b0, + ip6_header_t *ip0) +{ + ip6_sr_header_t *srh; + ip6_sr_pt_tlv_t *srh_pt_tlv; + timestamp_64_t ts; + sr_pt_iface_t *ls = 0; + u16 id_ld = 0; + srh = (ip6_sr_header_t *) (ip0 + 1); + + srh_pt_tlv = + (ip6_sr_pt_tlv_t *) ((u8 *) ip0 + sizeof (ip6_header_t) + + sizeof (ip6_sr_header_t) + + sizeof (ip6_address_t) * (srh->last_entry + 1)); + + unix_time_now_nsec_fraction (&ts.sec, &ts.nsec); + srh_pt_tlv->t64.sec = clib_host_to_net_u32 (ts.sec); + srh_pt_tlv->t64.nsec = clib_host_to_net_u32 (ts.nsec); + ls = sr_pt_find_iface (vnet_buffer (b0)->sw_if_index[VLIB_RX]); + if (ls) + { + id_ld = ls->id << 4; + id_ld |= ls->ingress_load; + srh_pt_tlv->id_ld = clib_host_to_net_u16 (id_ld); + } +} /** * @brief IPv6 encapsulation processing as per RFC2473 @@ -1261,6 +1335,8 @@ encaps_processing_v6 (vlib_node_runtime_t *node, vlib_buffer_t *b0, ip0_encap->ip_version_traffic_class_and_flow_label) & 0xfff00000) | (flow_label & 0x0000ffff)); + if (policy_type == SR_POLICY_TYPE_TEF) + srv6_tef_behavior (node, b0, ip0); } /** @@ -1502,7 +1578,6 @@ sr_policy_rewrite_encaps (vlib_main_t * vm, vlib_node_runtime_t * node, return from_frame->n_vectors; } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (sr_policy_rewrite_encaps_node) = { .function = sr_policy_rewrite_encaps, .name = "sr-pl-rewrite-encaps", @@ -1518,7 +1593,6 @@ VLIB_REGISTER_NODE (sr_policy_rewrite_encaps_node) = { #undef _ }, }; -/* *INDENT-ON* */ /** * @brief IPv4 encapsulation processing as per RFC2473 @@ -1795,7 +1869,6 @@ sr_policy_rewrite_encaps_v4 (vlib_main_t * vm, vlib_node_runtime_t * node, return from_frame->n_vectors; } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (sr_policy_rewrite_encaps_v4_node) = { .function = sr_policy_rewrite_encaps_v4, .name = "sr-pl-rewrite-encaps-v4", @@ -1811,7 +1884,6 @@ VLIB_REGISTER_NODE (sr_policy_rewrite_encaps_v4_node) = { #undef _ }, }; -/* *INDENT-ON* */ always_inline u32 ip_flow_hash (void *data) @@ -2237,7 +2309,6 @@ sr_policy_rewrite_encaps_l2 (vlib_main_t * vm, vlib_node_runtime_t * node, return from_frame->n_vectors; } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (sr_policy_rewrite_encaps_l2_node) = { .function = sr_policy_rewrite_encaps_l2, .name = "sr-pl-rewrite-encaps-l2", @@ -2253,7 +2324,6 @@ VLIB_REGISTER_NODE (sr_policy_rewrite_encaps_l2_node) = { #undef _ }, }; -/* *INDENT-ON* */ /** * @brief Graph node for applying a SR policy into a packet. SRH insertion. @@ -2659,7 +2729,6 @@ sr_policy_rewrite_insert (vlib_main_t * vm, vlib_node_runtime_t * node, return from_frame->n_vectors; } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (sr_policy_rewrite_insert_node) = { .function = sr_policy_rewrite_insert, .name = "sr-pl-rewrite-insert", @@ -2675,7 +2744,6 @@ VLIB_REGISTER_NODE (sr_policy_rewrite_insert_node) = { #undef _ }, }; -/* *INDENT-ON* */ /** * @brief Graph node for applying a SR policy into a packet. BSID - SRH insertion. @@ -3070,7 +3138,6 @@ sr_policy_rewrite_b_insert (vlib_main_t * vm, vlib_node_runtime_t * node, return from_frame->n_vectors; } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (sr_policy_rewrite_b_insert_node) = { .function = sr_policy_rewrite_b_insert, .name = "sr-pl-rewrite-b-insert", @@ -3086,7 +3153,6 @@ VLIB_REGISTER_NODE (sr_policy_rewrite_b_insert_node) = { #undef _ }, }; -/* *INDENT-ON* */ /** * @brief Function BSID encapsulation @@ -3112,6 +3178,8 @@ end_bsid_encaps_srh_processing (vlib_node_runtime_t *node, vlib_buffer_t *b0, ip0->dst_address.as_u64[1] = new_dst0->as_u64[1]; return; } + else if (sr0->segments_left == 0 && policy_type == SR_POLICY_TYPE_TEF) + return; } error_bsid_encaps: @@ -3379,7 +3447,6 @@ sr_policy_rewrite_b_encaps (vlib_main_t * vm, vlib_node_runtime_t * node, return from_frame->n_vectors; } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (sr_policy_rewrite_b_encaps_node) = { .function = sr_policy_rewrite_b_encaps, .name = "sr-pl-rewrite-b-encaps", @@ -3395,7 +3462,6 @@ VLIB_REGISTER_NODE (sr_policy_rewrite_b_encaps_node) = { #undef _ }, }; -/* *INDENT-ON* */ /*************************** SR Policy plugins ******************************/ /** @@ -3463,10 +3529,8 @@ show_sr_policy_behaviors_command_fn (vlib_main_t * vm, vlib_cli_output (vm, "SR Policy behaviors:\n-----------------------\n\n"); - /* *INDENT-OFF* */ pool_foreach (plugin, sm->policy_plugin_functions) { vec_add1 (plugins_vec, plugin); } - /* *INDENT-ON* */ vlib_cli_output (vm, "Plugin behaviors:\n"); for (i = 0; i < vec_len (plugins_vec); i++) @@ -3479,13 +3543,11 @@ show_sr_policy_behaviors_command_fn (vlib_main_t * vm, return 0; } -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (show_sr_policy_behaviors_command, static) = { .path = "show sr policy behaviors", .short_help = "show sr policy behaviors", .function = show_sr_policy_behaviors_command_fn, }; -/* *INDENT-ON* */ /*************************** SR Segment Lists DPOs ****************************/ static u8 * diff --git a/src/vnet/srv6/sr_pt.api b/src/vnet/srv6/sr_pt.api new file mode 100644 index 00000000000..e86359b421f --- /dev/null +++ b/src/vnet/srv6/sr_pt.api @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright(c) 2022 Cisco Systems, Inc. + */ + +option version = "1.0.0"; + +import "vnet/interface_types.api"; + +/** \brief SR PT iface dump request + @param client_index - opaque cookie to identifty the sender + @param context - sender context, to match reply w/ request +*/ +define sr_pt_iface_dump +{ + u32 client_index; + u32 context; +}; + +define sr_pt_iface_details +{ + u32 context; + vl_api_interface_index_t sw_if_index; + u16 id; + u8 ingress_load; + u8 egress_load; + u8 tts_template; +}; + +/** \brief SR PT iface add request + @param client_index - opaque cookie to identifty the sender + @param context - sender context, to match reply w/ request + @param sw_if_index - index of the interface to add to SR PT + @param id - SR PT interface id + @param ingress_load - incoming interface load + @param egress_load - outgoing interface load + @param tts_template - truncated timestamp template to use +*/ +autoreply define sr_pt_iface_add +{ + u32 client_index; + u32 context; + vl_api_interface_index_t sw_if_index; + u16 id; + u8 ingress_load; + u8 egress_load; + u8 tts_template; +}; + +/** \brief SR PT iface del request + @param client_index - opaque cookie to identifty the sender + @param context - sender context, to match reply w/ request + @param sw_if_index - index of the interface to delete from SR PT +*/ +autoreply define sr_pt_iface_del +{ + u32 client_index; + u32 context; + vl_api_interface_index_t sw_if_index; +};
\ No newline at end of file diff --git a/src/vnet/srv6/sr_pt.c b/src/vnet/srv6/sr_pt.c new file mode 100644 index 00000000000..6299faa84ab --- /dev/null +++ b/src/vnet/srv6/sr_pt.c @@ -0,0 +1,281 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright(c) 2022 Cisco Systems, Inc. + */ + +/** + * @file + * @brief SR Path Tracing (PT) + * + * SR PT CLI + * + */ + +#include <vlib/vlib.h> +#include <vnet/vnet.h> +#include <vnet/srv6/sr.h> +#include <vnet/ip/ip.h> +#include <vnet/srv6/sr_packet.h> +#include <vnet/ip/ip6_packet.h> +#include <vnet/fib/ip6_fib.h> +#include <vnet/dpo/dpo.h> +#include <vnet/adj/adj.h> +#include <vnet/srv6/sr_pt.h> + +#include <vppinfra/error.h> +#include <vppinfra/elog.h> + +sr_pt_main_t sr_pt_main; + +void * +sr_pt_find_iface (u32 iface) +{ + sr_pt_main_t *sr_pt = &sr_pt_main; + uword *p; + + /* Search for the item */ + p = mhash_get (&sr_pt->sr_pt_iface_index_hash, &iface); + if (p) + { + /* Retrieve sr_pt_iface */ + return pool_elt_at_index (sr_pt->sr_pt_iface, p[0]); + } + return NULL; +} + +int +sr_pt_add_iface (u32 iface, u16 id, u8 ingress_load, u8 egress_load, + u8 tts_template) +{ + sr_pt_main_t *sr_pt = &sr_pt_main; + uword *p; + + sr_pt_iface_t *ls = 0; + + if (iface == (u32) ~0) + return SR_PT_ERR_IFACE_INVALID; + + /* Search for the item */ + p = mhash_get (&sr_pt->sr_pt_iface_index_hash, &iface); + + if (p) + return SR_PT_ERR_EXIST; + + if (id > SR_PT_ID_MAX) + return SR_PT_ERR_ID_INVALID; + + if (ingress_load > SR_PT_LOAD_MAX || egress_load > SR_PT_LOAD_MAX) + return SR_PT_ERR_LOAD_INVALID; + + if (tts_template > SR_PT_TTS_TEMPLATE_MAX) + return SR_PT_ERR_TTS_TEMPLATE_INVALID; + + vnet_feature_enable_disable ("ip6-output", "pt", iface, 1, 0, 0); + + /* Create a new sr_pt_iface */ + pool_get_zero (sr_pt->sr_pt_iface, ls); + ls->iface = iface; + ls->id = id; + ls->ingress_load = ingress_load; + ls->egress_load = egress_load; + ls->tts_template = tts_template; + + /* Set hash key for searching sr_pt_iface by iface */ + mhash_set (&sr_pt->sr_pt_iface_index_hash, &iface, ls - sr_pt->sr_pt_iface, + NULL); + return 0; +} + +int +sr_pt_del_iface (u32 iface) +{ + sr_pt_main_t *sr_pt = &sr_pt_main; + uword *p; + + sr_pt_iface_t *ls = 0; + + if (iface == (u32) ~0) + return SR_PT_ERR_IFACE_INVALID; + + /* Search for the item */ + p = mhash_get (&sr_pt->sr_pt_iface_index_hash, &iface); + + if (p) + { + /* Retrieve sr_pt_iface */ + ls = pool_elt_at_index (sr_pt->sr_pt_iface, p[0]); + vnet_feature_enable_disable ("ip6-output", "pt", iface, 0, 0, 0); + /* Delete sr_pt_iface */ + pool_put (sr_pt->sr_pt_iface, ls); + mhash_unset (&sr_pt->sr_pt_iface_index_hash, &iface, NULL); + } + else + { + return SR_PT_ERR_NOENT; + } + return 0; +} + +/** + * @brief "sr pt add iface" CLI function. + * + * @see sr_pt_add_iface + */ +static clib_error_t * +sr_pt_add_iface_command_fn (vlib_main_t *vm, unformat_input_t *input, + vlib_cli_command_t *cmd) +{ + vnet_main_t *vnm = vnet_get_main (); + u32 iface = (u32) ~0; + u32 id = (u32) ~0; + u32 ingress_load = 0; + u32 egress_load = 0; + u32 tts_template = SR_PT_TTS_TEMPLATE_DEFAULT; + + int rv; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "%U", unformat_vnet_sw_interface, vnm, &iface)) + ; + else if (unformat (input, "id %u", &id)) + ; + else if (unformat (input, "ingress-load %u", &ingress_load)) + ; + else if (unformat (input, "egress-load %u", &egress_load)) + ; + else if (unformat (input, "tts-template %u", &tts_template)) + ; + else + break; + } + + rv = sr_pt_add_iface (iface, id, ingress_load, egress_load, tts_template); + + switch (rv) + { + case 0: + break; + case SR_PT_ERR_EXIST: + return clib_error_return (0, "Error: Identical iface already exists."); + case SR_PT_ERR_IFACE_INVALID: + return clib_error_return (0, "Error: The iface name invalid."); + case SR_PT_ERR_ID_INVALID: + return clib_error_return (0, "Error: The iface id value invalid."); + case SR_PT_ERR_LOAD_INVALID: + return clib_error_return ( + 0, "Error: The iface ingress or egress load value invalid."); + case SR_PT_ERR_TTS_TEMPLATE_INVALID: + return clib_error_return ( + 0, "Error: The iface TTS Template value invalid."); + default: + return clib_error_return (0, "Error: unknown error."); + } + return 0; +} + +/** + * @brief "sr pt del iface" CLI function. + * + * @see sr_pt_del_iface + */ +static clib_error_t * +sr_pt_del_iface_command_fn (vlib_main_t *vm, unformat_input_t *input, + vlib_cli_command_t *cmd) +{ + vnet_main_t *vnm = vnet_get_main (); + u32 iface = (u32) ~0; + + int rv; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "%U", unformat_vnet_sw_interface, vnm, &iface)) + ; + else + break; + } + + rv = sr_pt_del_iface (iface); + + switch (rv) + { + case 0: + break; + case SR_PT_ERR_NOENT: + return clib_error_return (0, "Error: No such iface."); + case SR_PT_ERR_IFACE_INVALID: + return clib_error_return (0, "Error: The iface name is not valid."); + default: + return clib_error_return (0, "Error: unknown error."); + } + return 0; +} + +/** + * @brief CLI function to show all SR PT interfcaes + */ +static clib_error_t * +sr_pt_show_iface_command_fn (vlib_main_t *vm, unformat_input_t *input, + vlib_cli_command_t *cmd) +{ + vnet_main_t *vnm = vnet_get_main (); + sr_pt_main_t *sr_pt = &sr_pt_main; + sr_pt_iface_t **sr_pt_iface_list = 0; + sr_pt_iface_t *ls; + int i; + + vlib_cli_output (vm, "SR PT Interfaces"); + vlib_cli_output (vm, "=================================="); + + pool_foreach (ls, sr_pt->sr_pt_iface) + { + vec_add1 (sr_pt_iface_list, ls); + }; + + for (i = 0; i < vec_len (sr_pt_iface_list); i++) + { + ls = sr_pt_iface_list[i]; + vlib_cli_output ( + vm, + "\tiface : \t%U\n\tid : \t%d\n\tingress-load: " + "\t%d\n\tegress-load : \t%d\n\ttts-template: \t%d ", + format_vnet_sw_if_index_name, vnm, ls->iface, ls->id, ls->ingress_load, + ls->egress_load, ls->tts_template); + vlib_cli_output (vm, "--------------------------------"); + } + + return 0; +} + +VLIB_CLI_COMMAND (sr_pt_add_iface_command, static) = { + .path = "sr pt add iface", + .short_help = "sr pt add iface <iface-name> id <pt-iface-id> ingress-load " + "<ingress-load-value> egress-load <egress-load-value> " + "tts-template <tts-template-value>", + .function = sr_pt_add_iface_command_fn, +}; + +VLIB_CLI_COMMAND (sr_pt_del_iface_command, static) = { + .path = "sr pt del iface", + .short_help = "sr pt del iface <iface-name>", + .function = sr_pt_del_iface_command_fn, +}; + +VLIB_CLI_COMMAND (sr_pt_show_iface_command, static) = { + .path = "sr pt show iface", + .short_help = "sr pt show iface", + .function = sr_pt_show_iface_command_fn, +}; + +/** + * * @brief SR PT initialization + * */ +clib_error_t * +sr_pt_init (vlib_main_t *vm) +{ + sr_pt_main_t *pt = &sr_pt_main; + mhash_init (&pt->sr_pt_iface_index_hash, sizeof (uword), sizeof (u32)); + return 0; +} + +VLIB_INIT_FUNCTION (sr_pt_init);
\ No newline at end of file diff --git a/src/vnet/srv6/sr_pt.h b/src/vnet/srv6/sr_pt.h new file mode 100644 index 00000000000..53001e10ac7 --- /dev/null +++ b/src/vnet/srv6/sr_pt.h @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright(c) 2022 Cisco Systems, Inc. + */ + +/** + * @file + * @brief SR Path Tracing data structures definitions + * + */ + +#ifndef included_vnet_sr_pt_h +#define included_vnet_sr_pt_h + +#define IP6_HBH_PT_TYPE 50 + +/*SR PT error codes*/ +#define SR_PT_ERR_NOENT -1 /* No such entry*/ +#define SR_PT_ERR_EXIST -2 /* Entry exists */ +#define SR_PT_ERR_IFACE_INVALID -3 /* IFACE invalid */ +#define SR_PT_ERR_ID_INVALID -4 /* ID invalid */ +#define SR_PT_ERR_LOAD_INVALID -5 /* LOAD invalid*/ +#define SR_PT_ERR_TTS_TEMPLATE_INVALID -6 /* TTS Template invalid */ + +/*SR PT paramters max values*/ +#define SR_PT_ID_MAX 4095 +#define SR_PT_LOAD_MAX 15 +#define SR_PT_TTS_TEMPLATE_MAX 3 + +/*SR PT TTS Templates*/ +#define SR_PT_TTS_TEMPLATE_0 0 +#define SR_PT_TTS_TEMPLATE_1 1 +#define SR_PT_TTS_TEMPLATE_2 2 +#define SR_PT_TTS_TEMPLATE_3 3 +#define SR_PT_TTS_TEMPLATE_DEFAULT 2 + +/*SR PT TTS Template shift value*/ +#define SR_PT_TTS_SHIFT_TEMPLATE_0 8 +#define SR_PT_TTS_SHIFT_TEMPLATE_1 12 +#define SR_PT_TTS_SHIFT_TEMPLATE_2 16 +#define SR_PT_TTS_SHIFT_TEMPLATE_3 20 + +/*PT node behaviors*/ +#define PT_BEHAVIOR_SRC 0 +#define PT_BEHAVIOR_MID 1 +#define PT_BEHAVIOR_SNK 2 + +typedef struct +{ + u32 iface; /**< Interface */ + u16 id; /**< Interface ID */ + u8 ingress_load; /**< Interface Ingress Load */ + u8 egress_load; /**< Interface Egress Load */ + u8 tts_template; /**< Interface TTS Template */ +} sr_pt_iface_t; + +typedef struct +{ + u16 oif_oil; + u8 tts; +} __clib_packed sr_pt_cmd_t; + +typedef struct +{ + sr_pt_cmd_t cmd_stack[12]; +} __clib_packed ip6_hop_by_hop_option_pt_t; + +/** + * @brief SR Path Tracing main datastructure + */ +typedef struct +{ + /* Pool of sr_pt_iface instances */ + sr_pt_iface_t *sr_pt_iface; + + /* Hash table for sr_pt_iface parameters */ + mhash_t sr_pt_iface_index_hash; + + /* convenience */ + u16 msg_id_base; +} sr_pt_main_t; + +extern sr_pt_main_t sr_pt_main; +extern vlib_node_registration_t sr_pt_node; +extern int sr_pt_add_iface (u32 iface, u16 id, u8 ingress_load, u8 egress_load, + u8 tts_template); +extern int sr_pt_del_iface (u32 iface); +extern void *sr_pt_find_iface (u32 iface); + +#endif /* included_vnet_sr_pt_h */
\ No newline at end of file diff --git a/src/vnet/srv6/sr_pt_api.c b/src/vnet/srv6/sr_pt_api.c new file mode 100644 index 00000000000..b0b67a210fb --- /dev/null +++ b/src/vnet/srv6/sr_pt_api.c @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright(c) 2022 Cisco Systems, Inc. + */ + +#include <vnet/vnet.h> +#include <vlibmemory/api.h> +#include <vnet/srv6/sr_pt.h> + +#include <vnet/interface.h> +#include <vnet/api_errno.h> + +#include <vnet/srv6/sr_pt.api_enum.h> +#include <vnet/srv6/sr_pt.api_types.h> + +#define REPLY_MSG_ID_BASE sr_pt_main.msg_id_base +#include <vlibapi/api_helper_macros.h> + +static void +send_sr_pt_iface_details (sr_pt_iface_t *t, vl_api_registration_t *reg, + u32 context) +{ + vl_api_sr_pt_iface_details_t *rmp; + + rmp = vl_msg_api_alloc (sizeof (*rmp)); + clib_memset (rmp, 0, sizeof (*rmp)); + rmp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_SR_PT_IFACE_DETAILS); + + rmp->sw_if_index = ntohl (t->iface); + rmp->id = ntohs (t->id); + rmp->ingress_load = t->ingress_load; + rmp->egress_load = t->egress_load; + rmp->tts_template = t->tts_template; + + rmp->context = context; + + vl_api_send_msg (reg, (u8 *) rmp); +} + +static void +vl_api_sr_pt_iface_dump_t_handler (vl_api_sr_pt_iface_dump_t *mp) +{ + vl_api_registration_t *reg; + sr_pt_main_t *pt = &sr_pt_main; + sr_pt_iface_t *t; + + reg = vl_api_client_index_to_registration (mp->client_index); + if (!reg) + return; + + pool_foreach (t, pt->sr_pt_iface) + { + send_sr_pt_iface_details (t, reg, mp->context); + } +} + +static void +vl_api_sr_pt_iface_add_t_handler (vl_api_sr_pt_iface_add_t *mp) +{ + vl_api_sr_pt_iface_add_reply_t *rmp; + int rv = 0; + + VALIDATE_SW_IF_INDEX (mp); + + rv = sr_pt_add_iface (ntohl (mp->sw_if_index), ntohs (mp->id), + mp->ingress_load, mp->egress_load, mp->tts_template); + + BAD_SW_IF_INDEX_LABEL; + REPLY_MACRO (VL_API_SR_PT_IFACE_ADD_REPLY); +} + +static void +vl_api_sr_pt_iface_del_t_handler (vl_api_sr_pt_iface_del_t *mp) +{ + vl_api_sr_pt_iface_del_reply_t *rmp; + int rv = 0; + + VALIDATE_SW_IF_INDEX (mp); + + rv = sr_pt_del_iface (ntohl (mp->sw_if_index)); + + BAD_SW_IF_INDEX_LABEL; + REPLY_MACRO (VL_API_SR_PT_IFACE_DEL_REPLY); +} + +#include <vnet/srv6/sr_pt.api.c> +static clib_error_t * +sr_pt_api_hookup (vlib_main_t *vm) +{ + /* + * Set up the (msg_name, crc, message-id) table + */ + REPLY_MSG_ID_BASE = setup_message_id_table (); + + return 0; +} + +VLIB_API_INIT_FUNCTION (sr_pt_api_hookup);
\ No newline at end of file diff --git a/src/vnet/srv6/sr_pt_node.c b/src/vnet/srv6/sr_pt_node.c new file mode 100644 index 00000000000..fa8b1f69b57 --- /dev/null +++ b/src/vnet/srv6/sr_pt_node.c @@ -0,0 +1,175 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright(c) 2022 Cisco Systems, Inc. + */ + +#include <vnet/fib/ip6_fib.h> +#include <vnet/dpo/load_balance.h> +#include <vnet/l2/feat_bitmap.h> +#include <vnet/fib/fib_table.h> +#include <vnet/srv6/sr.h> +#include <vnet/srv6/sr_pt.h> + +/** + * @brief PT node trace + */ +typedef struct +{ + u32 iface; + u16 id; + u8 load; + timestamp_64_t t64; + u8 tts_template; + u8 tts; + u8 behavior; +} pt_trace_t; + +static u8 * +format_pt_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 *); + pt_trace_t *t = va_arg (*args, pt_trace_t *); + switch (t->behavior) + { + case PT_BEHAVIOR_MID: + s = format ( + s, + "Behavior Midpoint, outgoing interface %U, outgoing interface id %u, " + "outgoing interface load %u, t64_sec %u, t64_nsec %u, tts_template " + "%u, tts %u", + format_vnet_sw_if_index_name, vnet_get_main (), t->iface, t->id, + t->load, clib_host_to_net_u32 (t->t64.sec), + clib_host_to_net_u32 (t->t64.nsec), t->tts_template, t->tts); + break; + default: + break; + } + return s; +} + +static_always_inline void +pt_midpoint_processing (vlib_main_t *vm, vlib_node_runtime_t *node, + vlib_buffer_t *b0, ip6_header_t *ip0, + sr_pt_iface_t *ls, timestamp_64_t t64) +{ + ip6_hop_by_hop_header_t *hbh; + ip6_hop_by_hop_option_t *hbh_opt; + ip6_hop_by_hop_option_pt_t *hbh_opt_pt; + + if (ip0->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS) + { + hbh = (void *) (ip0 + 1); + hbh_opt = (void *) (hbh + 1); + if (hbh_opt->type == IP6_HBH_PT_TYPE) + { + hbh_opt_pt = (void *) (hbh_opt + 1); + clib_memcpy_fast (&hbh_opt_pt->cmd_stack[1], + &hbh_opt_pt->cmd_stack[0], 33); + hbh_opt_pt->cmd_stack[0].oif_oil = + clib_host_to_net_u16 (ls->id << 4); + hbh_opt_pt->cmd_stack[0].oif_oil |= ls->egress_load; + switch (ls->tts_template) + { + case SR_PT_TTS_TEMPLATE_0: + hbh_opt_pt->cmd_stack[0].tts = + t64.nsec >> SR_PT_TTS_SHIFT_TEMPLATE_0; + break; + case SR_PT_TTS_TEMPLATE_1: + hbh_opt_pt->cmd_stack[0].tts = + t64.nsec >> SR_PT_TTS_SHIFT_TEMPLATE_1; + break; + case SR_PT_TTS_TEMPLATE_2: + hbh_opt_pt->cmd_stack[0].tts = + t64.nsec >> SR_PT_TTS_SHIFT_TEMPLATE_2; + break; + case SR_PT_TTS_TEMPLATE_3: + hbh_opt_pt->cmd_stack[0].tts = + t64.nsec >> SR_PT_TTS_SHIFT_TEMPLATE_0; + break; + default: + break; + } + } + } + return; +} + +VLIB_NODE_FN (sr_pt_node) +(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame) +{ + u32 n_left_from, next_index, *from, *to_next; + from = vlib_frame_vector_args (from_frame); + n_left_from = from_frame->n_vectors; + next_index = node->cached_next_index; + u8 pt_behavior = ~(u8) 0; + sr_pt_iface_t *ls = 0; + while (n_left_from > 0) + { + u32 n_left_to_next; + vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); + + // Getting the timestamp (one for each batch of packets) + timestamp_64_t t64 = {}; + unix_time_now_nsec_fraction (&t64.sec, &t64.nsec); + + // Single loop for potentially the last three packets + while (n_left_from > 0 && n_left_to_next > 0) + { + u32 bi0; + u32 iface; + vlib_buffer_t *b0; + u32 next0 = 0; + ethernet_header_t *en0; + ip6_header_t *ip0 = 0; + bi0 = from[0]; + to_next[0] = bi0; + from += 1; + to_next += 1; + n_left_from -= 1; + n_left_to_next -= 1; + + b0 = vlib_get_buffer (vm, bi0); + iface = vnet_buffer (b0)->sw_if_index[VLIB_TX]; + ls = sr_pt_find_iface (iface); + if (ls) + { + en0 = vlib_buffer_get_current (b0); + ip0 = (void *) (en0 + 1); + pt_midpoint_processing (vm, node, b0, ip0, ls, t64); + pt_behavior = PT_BEHAVIOR_MID; + } + if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) + { + pt_trace_t *tr = vlib_add_trace (vm, node, b0, sizeof (*tr)); + tr->iface = iface; + tr->id = ls->id; + tr->load = ls->egress_load; + tr->tts_template = ls->tts_template; + tr->t64.sec = t64.sec; + tr->t64.nsec = t64.nsec; + tr->tts = t64.nsec >> 20; + tr->behavior = pt_behavior; + } + vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, + n_left_to_next, bi0, next0); + } + vlib_put_next_frame (vm, node, next_index, n_left_to_next); + } + + return from_frame->n_vectors; +} + +VLIB_REGISTER_NODE (sr_pt_node) = { + .name = "pt", + .vector_size = sizeof (u32), + .format_trace = format_pt_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = 0, + .n_next_nodes = 1, + .next_nodes = { [0] = "interface-output" }, +}; + +VNET_FEATURE_INIT (sr_pt_node, static) = { + .arc_name = "ip6-output", + .node_name = "pt", +};
\ No newline at end of file diff --git a/src/vnet/srv6/sr_steering.c b/src/vnet/srv6/sr_steering.c index cb1d81742eb..94c3d67a27a 100644 --- a/src/vnet/srv6/sr_steering.c +++ b/src/vnet/srv6/sr_steering.c @@ -184,9 +184,6 @@ sr_steering_policy (int is_del, ip6_address_t * bsid, u32 sr_policy_index, else sr_policy = pool_elt_at_index (sm->sr_policies, sr_policy_index); - if (!sr_policy) - return -2; - steer_pl->sr_policy = sr_policy - sm->sr_policies; /* Remove old FIB/hw redirection and create a new one */ @@ -459,7 +456,6 @@ sr_steer_policy_command_fn (vlib_main_t * vm, unformat_input_t * input, return 0; } -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (sr_steer_policy_command, static) = { .path = "sr steer", .short_help = "sr steer (del) [l3 <ip_addr/mask>|l2 <sf_if>] " @@ -474,7 +470,6 @@ VLIB_CLI_COMMAND (sr_steer_policy_command, static) = { "\t\tsr steer del l3 2001::/64 via sr_policy index 5\n", .function = sr_steer_policy_command_fn, }; -/* *INDENT-ON* */ static clib_error_t * show_sr_steering_policies_command_fn (vlib_main_t * vm, @@ -491,9 +486,7 @@ show_sr_steering_policies_command_fn (vlib_main_t * vm, int i; vlib_cli_output (vm, "SR steering policies:"); - /* *INDENT-OFF* */ pool_foreach (steer_pl, sm->steer_policies) {vec_add1(steer_policies, steer_pl);} - /* *INDENT-ON* */ vlib_cli_output (vm, "Traffic\t\tSR policy BSID"); for (i = 0; i < vec_len (steer_policies); i++) { @@ -526,13 +519,11 @@ show_sr_steering_policies_command_fn (vlib_main_t * vm, return 0; } -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (show_sr_steering_policies_command, static) = { .path = "show sr steering-policies", .short_help = "show sr steering-policies", .function = show_sr_steering_policies_command_fn, }; -/* *INDENT-ON* */ clib_error_t * sr_steering_init (vlib_main_t * vm) @@ -550,18 +541,14 @@ sr_steering_init (vlib_main_t * vm) return 0; } -/* *INDENT-OFF* */ VLIB_INIT_FUNCTION (sr_steering_init); -/* *INDENT-ON* */ -/* *INDENT-OFF* */ VNET_FEATURE_INIT (sr_pl_rewrite_encaps_l2, static) = { .arc_name = "device-input", .node_name = "sr-pl-rewrite-encaps-l2", .runs_before = VNET_FEATURES ("ethernet-input"), }; -/* *INDENT-ON* */ /* * fd.io coding-style-patch-verification: ON diff --git a/src/vnet/srv6/sr_test.c b/src/vnet/srv6/sr_test.c index 85f64e1e230..be898599e96 100644 --- a/src/vnet/srv6/sr_test.c +++ b/src/vnet/srv6/sr_test.c @@ -80,6 +80,18 @@ api_sr_policy_add (vat_main_t *vam) } static int +api_sr_policy_mod_v2 (vat_main_t *vam) +{ + return -1; +} + +static int +api_sr_policy_add_v2 (vat_main_t *vam) +{ + return -1; +} + +static int api_sr_localsids_dump (vat_main_t *vam) { return -1; @@ -92,6 +104,12 @@ api_sr_policies_dump (vat_main_t *vam) } static int +api_sr_policies_v2_dump (vat_main_t *vam) +{ + return -1; +} + +static int api_sr_policies_with_sl_index_dump (vat_main_t *vam) { return -1; @@ -109,6 +127,11 @@ vl_api_sr_policies_details_t_handler (vl_api_sr_policies_details_t *mp) } static void +vl_api_sr_policies_v2_details_t_handler (vl_api_sr_policies_v2_details_t *mp) +{ +} + +static void vl_api_sr_localsids_details_t_handler (vl_api_sr_localsids_details_t *mp) { } |