X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fplugins%2Fioam%2Fencap%2Fip6_ioam_trace.c;h=234485757987c22e1c762f3f1d3baafbef2cda6c;hb=954c707972bf7efcd227e26d9679544813a78115;hp=a836dfe817bfd0d68d0644e8b22417b7fe713064;hpb=3b46cba8f4e909bc363403c6c92215159abb2f11;p=vpp.git diff --git a/src/plugins/ioam/encap/ip6_ioam_trace.c b/src/plugins/ioam/encap/ip6_ioam_trace.c index a836dfe817b..23448575798 100644 --- a/src/plugins/ioam/encap/ip6_ioam_trace.c +++ b/src/plugins/ioam/encap/ip6_ioam_trace.c @@ -28,6 +28,11 @@ #include #include +#include +#include +#include +#include +#include /* Timestamp precision multipliers for seconds, milliseconds, microseconds * and nanoseconds respectively. @@ -40,16 +45,6 @@ typedef union u32 as_u32[2]; } time_u64_t; -/* *INDENT-OFF* */ -typedef CLIB_PACKED(struct { - ip6_hop_by_hop_option_t hdr; - u8 ioam_trace_type; - u8 data_list_elts_left; - u32 elts[0]; /* Variable type. So keep it generic */ -}) ioam_trace_option_t; -/* *INDENT-ON* */ - - extern ip6_hop_by_hop_ioam_main_t ip6_hop_by_hop_ioam_main; extern ip6_main_t ip6_main; @@ -57,7 +52,9 @@ extern ip6_main_t ip6_main; _(PROCESSED, "Pkts with ip6 hop-by-hop trace options") \ _(PROFILE_MISS, "Pkts with ip6 hop-by-hop trace options but no profile set") \ _(UPDATED, "Pkts with trace updated") \ - _(FULL, "Pkts with trace options but no space") + _(FULL, "Pkts with trace options but no space") \ + _(LOOPBACK, "Pkts with trace options Loopback") \ + _(LOOPBACK_REPLY, "Pkts with trace options Loopback Reply") static char *ip6_hop_by_hop_ioam_trace_stats_strings[] = { #define _(sym,string) string, @@ -201,26 +198,69 @@ ip6_hop_by_hop_ioam_trace_rewrite_handler (u8 * rewrite_string, HBH_OPTION_TYPE_DATA_CHANGE_ENROUTE; trace_option->hdr.length = 2 /*ioam_trace_type,data_list_elts_left */ + trace_option_elts * trace_data_size; - trace_option->ioam_trace_type = profile->trace_type & TRACE_TYPE_MASK; - trace_option->data_list_elts_left = trace_option_elts; + trace_option->trace_hdr.ioam_trace_type = + profile->trace_type & TRACE_TYPE_MASK; + trace_option->trace_hdr.data_list_elts_left = trace_option_elts; *rewrite_size = sizeof (ioam_trace_option_t) + (trace_option_elts * trace_data_size); return 0; } +always_inline void +ip6_hbh_ioam_loopback_handler (vlib_buffer_t * b, ip6_header_t * ip, + ioam_trace_option_t * trace) +{ + u32 buf_index; + ip6_hop_by_hop_ioam_main_t *hm = &ip6_hop_by_hop_ioam_main; + vlib_buffer_t *b0; + vlib_frame_t *nf = 0; + u32 *to_next; + vlib_node_t *next_node; + ip6_header_t *ip6; + ip6_hop_by_hop_header_t *hbh; + ioam_trace_option_t *opt; + udp_ping_t *udp; + + b0 = vlib_buffer_copy (hm->vlib_main, b); + if (b0 == NULL) + return; + + buf_index = vlib_get_buffer_index (hm->vlib_main, b0); + next_node = vlib_get_node_by_name (hm->vlib_main, (u8 *) "ip6-lookup"); + nf = vlib_get_frame_to_node (hm->vlib_main, next_node->index); + nf->n_vectors = 0; + to_next = vlib_frame_vector_args (nf); + + vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0; + vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0; + + ip6 = vlib_buffer_get_current (b0); + hbh = (ip6_hop_by_hop_header_t *) (ip6 + 1); + opt = (ioam_trace_option_t *) + ip6_hbh_get_option (hbh, HBH_OPTION_TYPE_IOAM_TRACE_DATA_LIST); + + udp = (udp_ping_t *) ((u8 *) hbh + ((hbh->length + 1) << 3)); + udp_ping_create_reply_from_probe_ip6 (ip6, hbh, udp); + ip6_hbh_ioam_trace_set_bit (opt, BIT_LOOPBACK_REPLY); + + *to_next = buf_index; + nf->n_vectors++; + to_next++; + + vlib_put_frame_to_node (hm->vlib_main, next_node->index, nf); + ip6_ioam_trace_stats_increment_counter (IP6_IOAM_TRACE_LOOPBACK, 1); +} int ip6_hbh_ioam_trace_data_list_handler (vlib_buffer_t * b, ip6_header_t * ip, ip6_hop_by_hop_option_t * opt) { - ip6_main_t *im = &ip6_main; - ip_lookup_main_t *lm = &im->lookup_main; ip6_hop_by_hop_ioam_main_t *hm = &ip6_hop_by_hop_ioam_main; u8 elt_index = 0; ioam_trace_option_t *trace = (ioam_trace_option_t *) opt; u32 adj_index = vnet_buffer (b)->ip.adj_index[VLIB_TX]; - ip_adjacency_t *adj = ip_get_adjacency (lm, adj_index); + ip_adjacency_t *adj = adj_get (adj_index); time_u64_t time_u64; u32 *elt; int rv = 0; @@ -235,27 +275,34 @@ ip6_hbh_ioam_trace_data_list_handler (vlib_buffer_t * b, ip6_header_t * ip, return (-1); } + /* Don't trace loopback reply packets */ + if (trace->trace_hdr.ioam_trace_type & BIT_LOOPBACK_REPLY) + { + ip6_ioam_trace_stats_increment_counter (IP6_IOAM_TRACE_LOOPBACK_REPLY, + 1); + return rv; + } time_u64.as_u64 = 0; - if (PREDICT_TRUE (trace->data_list_elts_left)) + if (PREDICT_TRUE (trace->trace_hdr.data_list_elts_left)) { - trace->data_list_elts_left--; + trace->trace_hdr.data_list_elts_left--; /* fetch_trace_data_size returns in bytes. Convert it to 4-bytes * to skip to this node's location. */ elt_index = - trace->data_list_elts_left * - fetch_trace_data_size (trace->ioam_trace_type) / 4; - elt = &trace->elts[elt_index]; - if (trace->ioam_trace_type & BIT_TTL_NODEID) + trace->trace_hdr.data_list_elts_left * + fetch_trace_data_size (trace->trace_hdr.ioam_trace_type) / 4; + elt = &trace->trace_hdr.elts[elt_index]; + if (trace->trace_hdr.ioam_trace_type & BIT_TTL_NODEID) { *elt = clib_host_to_net_u32 ((ip->hop_limit << 24) | profile->node_id); elt++; } - if (trace->ioam_trace_type & BIT_ING_INTERFACE) + if (trace->trace_hdr.ioam_trace_type & BIT_ING_INTERFACE) { *elt = (vnet_buffer (b)->sw_if_index[VLIB_RX] & 0xFFFF) << 16 | @@ -264,7 +311,7 @@ ip6_hbh_ioam_trace_data_list_handler (vlib_buffer_t * b, ip6_header_t * ip, elt++; } - if (trace->ioam_trace_type & BIT_TIMESTAMP) + if (trace->trace_hdr.ioam_trace_type & BIT_TIMESTAMP) { /* Send least significant 32 bits */ f64 time_f64 = @@ -276,12 +323,21 @@ ip6_hbh_ioam_trace_data_list_handler (vlib_buffer_t * b, ip6_header_t * ip, elt++; } - if (trace->ioam_trace_type & BIT_APPDATA) + if (trace->trace_hdr.ioam_trace_type & BIT_APPDATA) { /* $$$ set elt0->app_data */ *elt = clib_host_to_net_u32 (profile->app_data); elt++; } + + + if (PREDICT_FALSE (trace->trace_hdr.ioam_trace_type & BIT_LOOPBACK)) + { + /* if loopback flag set then copy the packet + * and send it back to source */ + ip6_hbh_ioam_loopback_handler (b, ip, trace); + } + ip6_ioam_trace_stats_increment_counter (IP6_IOAM_TRACE_UPDATED, 1); } else @@ -302,17 +358,19 @@ ip6_hbh_ioam_trace_data_list_trace_handler (u8 * s, trace = (ioam_trace_option_t *) opt; s = - format (s, " Trace Type 0x%x , %d elts left\n", trace->ioam_trace_type, - trace->data_list_elts_left); + format (s, " Trace Type 0x%x , %d elts left\n", + trace->trace_hdr.ioam_trace_type, + trace->trace_hdr.data_list_elts_left); trace_data_size_in_words = - fetch_trace_data_size (trace->ioam_trace_type) / 4; - elt = &trace->elts[0]; - while ((u8 *) elt < ((u8 *) (&trace->elts[0]) + trace->hdr.length - 2 - /* -2 accounts for ioam_trace_type,elts_left */ )) + fetch_trace_data_size (trace->trace_hdr.ioam_trace_type) / 4; + elt = &trace->trace_hdr.elts[0]; + while ((u8 *) elt < + ((u8 *) (&trace->trace_hdr.elts[0]) + trace->hdr.length - 2 + /* -2 accounts for ioam_trace_type,elts_left */ )) { s = format (s, " [%d] %U\n", elt_index, format_ioam_data_list_element, - elt, &trace->ioam_trace_type); + elt, &trace->trace_hdr.ioam_trace_type); elt_index++; elt += trace_data_size_in_words; } @@ -353,6 +411,7 @@ VLIB_CLI_COMMAND (ip6_show_ioam_trace_cmd, static) = { /* *INDENT-OFF* */ VLIB_PLUGIN_REGISTER () = { .version = VPP_BUILD_VER, + .description = "Inbound Operations, Administration, and Maintenance (OAM)", }; /* *INDENT-ON* */ @@ -360,20 +419,10 @@ static clib_error_t * ip6_hop_by_hop_ioam_trace_init (vlib_main_t * vm) { ip6_hop_by_hop_ioam_trace_main_t *hm = &ip6_hop_by_hop_ioam_trace_main; - clib_error_t *error; - - if ((error = vlib_call_init_function (vm, ip_main_init))) - return (error); - - if ((error = vlib_call_init_function (vm, ip6_lookup_init))) - return error; - - if ((error = vlib_call_init_function (vm, ip6_hop_by_hop_ioam_init))) - return (error); hm->vlib_main = vm; hm->vnet_main = vnet_get_main (); - memset (hm->counters, 0, sizeof (hm->counters)); + clib_memset (hm->counters, 0, sizeof (hm->counters)); if (ip6_hbh_register_option @@ -395,6 +444,14 @@ ip6_hop_by_hop_ioam_trace_init (vlib_main_t * vm) return (0); } +/* *INDENT-OFF* */ +VLIB_INIT_FUNCTION (ip6_hop_by_hop_ioam_trace_init) = +{ + .runs_after = VLIB_INITS ("ip_main_init", "ip6_lookup_init", + "ip6_hop_by_hop_ioam_init"), +}; +/* *INDENT-ON* */ + int ip6_trace_profile_cleanup (void) { @@ -433,9 +490,6 @@ ip6_trace_profile_setup (void) return (0); } - -VLIB_INIT_FUNCTION (ip6_hop_by_hop_ioam_trace_init); - /* * fd.io coding-style-patch-verification: ON *