From ed4a2fdd4d62c46a2237157cd3a72bda16fceb6a Mon Sep 17 00:00:00 2001 From: AkshayaNadahalli Date: Tue, 9 Aug 2016 13:38:04 +0530 Subject: Adding Sequence Number - Per Packet Counter(PPC) support for iOAM6. - Added support in classifier session to identify a flow to be iOAM6 encap/decap - Sequence number as part of iOAM6 E2E header is created as a plugin. Change-Id: Ib7605de45aecff25d684d099b525f8dc96ee7038 Signed-off-by: AkshayaNadahalli --- vnet/vnet/buffer.h | 2 +- vnet/vnet/ip/ip6.h | 4 +- vnet/vnet/ip/ip6_forward.c | 12 +- vnet/vnet/ip/ip6_hop_by_hop.c | 279 +++++++++++++++++++++++++++++++++++------- vnet/vnet/ip/ip6_hop_by_hop.h | 102 ++++++++++++--- 5 files changed, 330 insertions(+), 69 deletions(-) (limited to 'vnet') diff --git a/vnet/vnet/buffer.h b/vnet/vnet/buffer.h index 6385f191..fafb3181 100644 --- a/vnet/vnet/buffer.h +++ b/vnet/vnet/buffer.h @@ -182,8 +182,8 @@ typedef struct struct { u64 pad; - u32 opaque_index; u32 table_index; + u32 opaque_index; u64 hash; } l2_classify; diff --git a/vnet/vnet/ip/ip6.h b/vnet/vnet/ip/ip6.h index f6008d71..8b3b9973 100644 --- a/vnet/vnet/ip/ip6.h +++ b/vnet/vnet/ip/ip6.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Cisco and/or its affiliates. + * Copyright (c) 2016 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -521,6 +521,6 @@ int ip6_hbh_unregister_option (u8 option); void ip6_hbh_set_next_override (uword next); /* Flag used by IOAM code. Classifier sets it pop-hop-by-hop checks it */ -#define OI_DECAP 100 +#define OI_DECAP 0x80000000 #endif /* included_ip_ip6_h */ diff --git a/vnet/vnet/ip/ip6_forward.c b/vnet/vnet/ip/ip6_forward.c index 4493cb4c..53d13db2 100644 --- a/vnet/vnet/ip/ip6_forward.c +++ b/vnet/vnet/ip/ip6_forward.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Cisco and/or its affiliates. + * Copyright (c) 2016 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -2459,12 +2459,12 @@ ip6_hop_by_hop (vlib_main_t * vm, outdual: /* Has the classifier flagged this buffer for special treatment? */ - if ((error0 == 0) && (vnet_buffer(b0)->l2_classify.opaque_index == OI_DECAP)) - next0 = hm->next_override; + if (PREDICT_FALSE((error0 == 0) && (vnet_buffer(b0)->l2_classify.opaque_index & OI_DECAP))) + next0 = hm->next_override; /* Has the classifier flagged this buffer for special treatment? */ - if ((error1 == 0) && (vnet_buffer(b1)->l2_classify.opaque_index == OI_DECAP)) - next1 = hm->next_override; + if (PREDICT_FALSE((error1 == 0) && (vnet_buffer(b1)->l2_classify.opaque_index & OI_DECAP))) + next1 = hm->next_override; if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE))) { @@ -2542,7 +2542,7 @@ ip6_hop_by_hop (vlib_main_t * vm, out0: /* Has the classifier flagged this buffer for special treatment? */ - if ((error0 == 0) && (vnet_buffer(b0)->l2_classify.opaque_index == OI_DECAP)) + if (PREDICT_FALSE((error0 == 0) && (vnet_buffer(b0)->l2_classify.opaque_index & OI_DECAP))) next0 = hm->next_override; if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) { diff --git a/vnet/vnet/ip/ip6_hop_by_hop.c b/vnet/vnet/ip/ip6_hop_by_hop.c index 72490b91..e8bc8906 100644 --- a/vnet/vnet/ip/ip6_hop_by_hop.c +++ b/vnet/vnet/ip/ip6_hop_by_hop.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Cisco and/or its affiliates. + * Copyright (c) 2016 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -25,6 +25,7 @@ #include #include +#include /** * @file @@ -40,8 +41,6 @@ * in-band OAM can be enabled for IPv6 traffic. */ -char *ppc_state[] = { "None", "Encap", "Decap" }; - ip6_hop_by_hop_ioam_main_t ip6_hop_by_hop_ioam_main; #define foreach_ip6_hbyh_ioam_input_next \ @@ -58,6 +57,68 @@ typedef enum } ip6_hbyh_ioam_input_next_t; +u32 +ioam_flow_add (u8 encap, u8 * flow_name) +{ + ip6_hop_by_hop_ioam_main_t *hm = &ip6_hop_by_hop_ioam_main; + flow_data_t *flow = 0; + u32 index = 0; + u8 i; + + pool_get (hm->flows, flow); + memset (flow, 0, sizeof (flow_data_t)); + + index = flow - hm->flows; + strncpy ((char *) flow->flow_name, (char *) flow_name, 31); + + if (!encap) + IOAM_SET_DECAP (index); + + for (i = 0; i < 255; i++) + { + if (hm->flow_handler[i]) + flow->ctx[i] = hm->flow_handler[i] (index, 1); + } + return (index); +} + +static uword +unformat_opaque_ioam (unformat_input_t * input, va_list * args) +{ + u64 *opaquep = va_arg (*args, u64 *); + u8 *flow_name = NULL; + uword ret = 0; + + if (unformat (input, "ioam-encap %s", &flow_name)) + { + *opaquep = ioam_flow_add (1, flow_name); + ret = 1; + } + else if (unformat (input, "ioam-decap %s", &flow_name)) + { + *opaquep = ioam_flow_add (0, flow_name); + ret = 1; + } + + vec_free (flow_name); + return ret; +} + +u8 * +get_flow_name_from_flow_ctx (u32 flow_ctx) +{ + flow_data_t *flow = NULL; + ip6_hop_by_hop_ioam_main_t *hm = &ip6_hop_by_hop_ioam_main; + u32 index; + + index = IOAM_MASK_DECAP_BIT (flow_ctx); + + if (pool_is_free_index (hm->flows, index)) + return NULL; + + flow = pool_elt_at_index (hm->flows, index); + return (flow->flow_name); +} /* The main h-b-h tracer will be invoked, no need to do much here */ int @@ -96,6 +157,72 @@ ip6_hbh_add_unregister_option (u8 option) return (0); } +/* Config handler registration */ +int +ip6_hbh_config_handler_register (u8 option, + int config_handler (void *data, u8 disable)) +{ + ip6_hop_by_hop_ioam_main_t *hm = &ip6_hop_by_hop_ioam_main; + + ASSERT (option < ARRAY_LEN (hm->config_handler)); + + /* Already registered */ + if (hm->config_handler[option]) + return (VNET_API_ERROR_INVALID_REGISTRATION); + + hm->config_handler[option] = config_handler; + + return (0); +} + +int +ip6_hbh_config_handler_unregister (u8 option) +{ + ip6_hop_by_hop_ioam_main_t *hm = &ip6_hop_by_hop_ioam_main; + + ASSERT (option < ARRAY_LEN (hm->config_handler)); + + /* Not registered */ + if (!hm->config_handler[option]) + return (VNET_API_ERROR_INVALID_REGISTRATION); + + hm->config_handler[option] = NULL; + return (0); +} + +/* Flow handler registration */ +int +ip6_hbh_flow_handler_register (u8 option, + u32 ioam_flow_handler (u32 flow_ctx, u8 add)) +{ + ip6_hop_by_hop_ioam_main_t *hm = &ip6_hop_by_hop_ioam_main; + + ASSERT (option < ARRAY_LEN (hm->flow_handler)); + + /* Already registered */ + if (hm->flow_handler[option]) + return (VNET_API_ERROR_INVALID_REGISTRATION); + + hm->flow_handler[option] = ioam_flow_handler; + + return (0); +} + +int +ip6_hbh_flow_handler_unregister (u8 option) +{ + ip6_hop_by_hop_ioam_main_t *hm = &ip6_hop_by_hop_ioam_main; + + ASSERT (option < ARRAY_LEN (hm->flow_handler)); + + /* Not registered */ + if (!hm->flow_handler[option]) + return (VNET_API_ERROR_INVALID_REGISTRATION); + + hm->flow_handler[option] = NULL; + return (0); +} + typedef struct { u32 next_index; @@ -374,7 +501,8 @@ VLIB_NODE_FUNCTION_MULTIARCH (ip6_add_hop_by_hop_node, int ip6_hbh_pop_register_option (u8 option, - int options (ip6_header_t * ip, + int options (vlib_buffer_t * b, + ip6_header_t * ip, ip6_hop_by_hop_option_t * opt)) { ip6_hop_by_hop_ioam_main_t *hm = &ip6_hop_by_hop_ioam_main; @@ -429,7 +557,8 @@ static char *ip6_pop_hop_by_hop_error_strings[] = { static inline void ioam_pop_hop_by_hop_processing (vlib_main_t * vm, ip6_header_t * ip0, - ip6_hop_by_hop_header_t * hbh0) + ip6_hop_by_hop_header_t * hbh0, + vlib_buffer_t * b) { ip6_hop_by_hop_ioam_main_t *hm = &ip6_hop_by_hop_ioam_main; ip6_hop_by_hop_option_t *opt0, *limit0; @@ -456,7 +585,7 @@ ioam_pop_hop_by_hop_processing (vlib_main_t * vm, default: if (hm->pop_options[type0]) { - if ((*hm->pop_options[type0]) (ip0, opt0) < 0) + if ((*hm->pop_options[type0]) (b, ip0, opt0) < 0) { vlib_node_increment_counter (vm, ip6_pop_hop_by_hop_node.index, @@ -543,8 +672,8 @@ ip6_pop_hop_by_hop_node_fn (vlib_main_t * vm, hbh0 = (ip6_hop_by_hop_header_t *) (ip0 + 1); hbh1 = (ip6_hop_by_hop_header_t *) (ip1 + 1); - ioam_pop_hop_by_hop_processing (vm, ip0, hbh0); - ioam_pop_hop_by_hop_processing (vm, ip1, hbh1); + ioam_pop_hop_by_hop_processing (vm, ip0, hbh0, b0); + ioam_pop_hop_by_hop_processing (vm, ip1, hbh1, b1); vlib_buffer_advance (b0, (hbh0->length + 1) << 3); vlib_buffer_advance (b1, (hbh1->length + 1) << 3); @@ -632,7 +761,7 @@ ip6_pop_hop_by_hop_node_fn (vlib_main_t * vm, hbh0 = (ip6_hop_by_hop_header_t *) (ip0 + 1); /* TODO:Temporarily doing it here.. do this validation in end_of_path_cb */ - ioam_pop_hop_by_hop_processing (vm, ip0, hbh0); + ioam_pop_hop_by_hop_processing (vm, ip0, hbh0, b0); /* Pop the trace data */ vlib_buffer_advance (b0, (hbh0->length + 1) << 3); new_l0 = clib_net_to_host_u16 (ip0->payload_length) - @@ -690,8 +819,15 @@ VLIB_NODE_FUNCTION_MULTIARCH (ip6_pop_hop_by_hop_node, ip6_pop_hop_by_hop_node_fn) static clib_error_t *ip6_hop_by_hop_ioam_init (vlib_main_t * vm) { + clib_error_t *error; ip6_hop_by_hop_ioam_main_t *hm = &ip6_hop_by_hop_ioam_main; + if ((error = vlib_call_init_function (vm, ip_main_init))) + return (error); + + if ((error = vlib_call_init_function (vm, ip6_lookup_init))) + return error; + hm->vlib_main = vm; hm->vnet_main = vnet_get_main (); hm->unix_time_0 = (u32) time (0); /* Store starting time */ @@ -701,6 +837,8 @@ VLIB_NODE_FUNCTION_MULTIARCH (ip6_pop_hop_by_hop_node, memset (hm->pop_options, 0, sizeof (hm->pop_options)); memset (hm->options_size, 0, sizeof (hm->options_size)); + vnet_classify_register_unformat_opaque_index_fn (unformat_opaque_ioam); + return (0); } @@ -708,15 +846,15 @@ VLIB_INIT_FUNCTION (ip6_hop_by_hop_ioam_init); int ip6_ioam_set_rewrite (u8 ** rwp, int has_trace_option, - int has_pot_option, int has_ppc_option) + int has_pot_option, int has_seqno_option) { ip6_hop_by_hop_ioam_main_t *hm = &ip6_hop_by_hop_ioam_main; - u8 *rewrite = 0; + u8 *rewrite = NULL; u32 size, rnd_size; ip6_hop_by_hop_header_t *hbh; u8 *current; - u8 trace_data_size = 0; - u8 pot_data_size = 0; + u8 *trace_data_size = NULL; + u8 *pot_data_size = NULL; vec_free (*rwp); @@ -730,16 +868,19 @@ ip6_ioam_set_rewrite (u8 ** rwp, int has_trace_option, if (has_trace_option && hm->options_size[HBH_OPTION_TYPE_IOAM_TRACE_DATA_LIST] != 0) { - size += sizeof (ip6_hop_by_hop_option_t); size += hm->options_size[HBH_OPTION_TYPE_IOAM_TRACE_DATA_LIST]; } if (has_pot_option && hm->add_options[HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT] != 0) { - size += sizeof (ip6_hop_by_hop_option_t); size += hm->options_size[HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT]; } + if (has_seqno_option) + { + size += hm->options_size[HBH_OPTION_TYPE_IOAM_EDGE_TO_EDGE]; + } + /* Round to a multiple of 8 octets */ rnd_size = (size + 7) & ~7; @@ -757,22 +898,32 @@ ip6_ioam_set_rewrite (u8 ** rwp, int has_trace_option, if (0 != (hm->options_size[HBH_OPTION_TYPE_IOAM_TRACE_DATA_LIST])) { trace_data_size = - hm->options_size[HBH_OPTION_TYPE_IOAM_TRACE_DATA_LIST]; + &hm->options_size[HBH_OPTION_TYPE_IOAM_TRACE_DATA_LIST]; if (0 == hm->add_options[HBH_OPTION_TYPE_IOAM_TRACE_DATA_LIST] (current, - &trace_data_size)) - current += hm->options_size[HBH_OPTION_TYPE_IOAM_TRACE_DATA_LIST]; + trace_data_size)) + current += *trace_data_size; } } if (has_pot_option && hm->add_options[HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT] != 0) { - pot_data_size = hm->options_size[HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT]; + pot_data_size = + &hm->options_size[HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT]; if (0 == hm->add_options[HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT] (current, - &pot_data_size)) - current += - sizeof (hm->options_size[HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT]); + pot_data_size)) + current += *pot_data_size; + } + + if (has_seqno_option && + (hm->add_options[HBH_OPTION_TYPE_IOAM_EDGE_TO_EDGE] != 0)) + { + if (0 == hm->add_options[HBH_OPTION_TYPE_IOAM_EDGE_TO_EDGE] (current, + & + (hm->options_size + [HBH_OPTION_TYPE_IOAM_EDGE_TO_EDGE]))) + current += hm->options_size[HBH_OPTION_TYPE_IOAM_EDGE_TO_EDGE]; } *rwp = rewrite; @@ -788,7 +939,20 @@ clear_ioam_rewrite_fn (void) hm->rewrite = 0; hm->has_trace_option = 0; hm->has_pot_option = 0; - hm->has_ppc_option = 0; + hm->has_seqno_option = 0; + hm->has_analyse_option = 0; + if (hm->config_handler[HBH_OPTION_TYPE_IOAM_TRACE_DATA_LIST]) + hm->config_handler[HBH_OPTION_TYPE_IOAM_TRACE_DATA_LIST] (NULL, 1); + + if (hm->config_handler[HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT]) + hm->config_handler[HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT] (NULL, 1); + + if (hm->config_handler[HBH_OPTION_TYPE_IOAM_EDGE_TO_EDGE]) + { + hm->config_handler[HBH_OPTION_TYPE_IOAM_EDGE_TO_EDGE] ((void *) + &hm->has_analyse_option, + 1); + } return 0; } @@ -819,19 +983,43 @@ VLIB_CLI_COMMAND (ip6_clear_ioam_rewrite_cmd, static) = { /* *INDENT-ON* */ clib_error_t * -ip6_ioam_enable (int has_trace_option, int has_pot_option, int has_ppc_option) +ip6_ioam_enable (int has_trace_option, int has_pot_option, + int has_seqno_option, int has_analyse_option) { int rv; ip6_hop_by_hop_ioam_main_t *hm = &ip6_hop_by_hop_ioam_main; rv = ip6_ioam_set_rewrite (&hm->rewrite, has_trace_option, - has_pot_option, has_ppc_option); + has_pot_option, has_seqno_option); switch (rv) { case 0: - hm->has_trace_option = has_trace_option; - hm->has_pot_option = has_pot_option; - hm->has_ppc_option = has_ppc_option; + if (has_trace_option) + { + hm->has_trace_option = has_trace_option; + if (hm->config_handler[HBH_OPTION_TYPE_IOAM_TRACE_DATA_LIST]) + hm->config_handler[HBH_OPTION_TYPE_IOAM_TRACE_DATA_LIST] (NULL, + 0); + } + + if (has_pot_option) + { + hm->has_pot_option = has_pot_option; + if (hm->config_handler[HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT]) + hm->config_handler[HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT] (NULL, + 0); + } + hm->has_analyse_option = has_analyse_option; + if (has_seqno_option) + { + hm->has_seqno_option = has_seqno_option; + if (hm->config_handler[HBH_OPTION_TYPE_IOAM_EDGE_TO_EDGE]) + { + hm->config_handler[HBH_OPTION_TYPE_IOAM_EDGE_TO_EDGE] ((void *) + &has_analyse_option, + 0); + } + } break; default: @@ -850,7 +1038,8 @@ ip6_set_ioam_rewrite_command_fn (vlib_main_t * vm, { int has_trace_option = 0; int has_pot_option = 0; - int has_ppc_option = 0; + int has_seqno_option = 0; + int has_analyse_option = 0; clib_error_t *rv = 0; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) @@ -859,18 +1048,17 @@ ip6_set_ioam_rewrite_command_fn (vlib_main_t * vm, has_trace_option = 1; else if (unformat (input, "pot")) has_pot_option = 1; - else if (unformat (input, "ppc encap")) - has_ppc_option = PPC_ENCAP; - else if (unformat (input, "ppc decap")) - has_ppc_option = PPC_DECAP; - else if (unformat (input, "ppc none")) - has_ppc_option = PPC_NONE; + else if (unformat (input, "seqno")) + has_seqno_option = 1; + else if (unformat (input, "analyse")) + has_analyse_option = 1; else break; } - rv = ip6_ioam_enable (has_trace_option, has_pot_option, has_ppc_option); + rv = ip6_ioam_enable (has_trace_option, has_pot_option, + has_seqno_option, has_analyse_option); return rv; } @@ -896,7 +1084,7 @@ ip6_set_ioam_rewrite_command_fn (vlib_main_t * vm, /* *INDENT-OFF* */ VLIB_CLI_COMMAND (ip6_set_ioam_rewrite_cmd, static) = { .path = "set ioam rewrite", - .short_help = "set ioam rewrite [trace] [pot] [ppc ]", + .short_help = "set ioam [trace] [pot] [seqno] [analyse]", .function = ip6_set_ioam_rewrite_command_fn, }; /* *INDENT-ON* */ @@ -945,14 +1133,15 @@ ip6_show_ioam_summary_cmd_fn (vlib_main_t * vm, format (s, "Try 'show ioam pot and show pot profile' for more information\n"); - s = format (s, " EDGE TO EDGE - PPC OPTION - %d (%s)\n", - hm->has_ppc_option, ppc_state[hm->has_ppc_option]); -#if 0 - /* 'show ioam ppc' command does not exist. Not sure if it was removed */ - /* or yet to be added. Comment out for now. */ - if (hm->has_ppc_option) - s = format (s, "Try 'show ioam ppc' for more information\n"); -#endif + s = format (s, " EDGE TO EDGE - SeqNo OPTION - %d (%s)\n", + hm->has_seqno_option, + hm->has_seqno_option ? "Enabled" : "Disabled"); + if (hm->has_seqno_option) + s = format (s, "Try 'show ioam e2e' for more information\n"); + + s = format (s, " iOAM Analyse OPTION - %d (%s)\n", + hm->has_analyse_option, + hm->has_analyse_option ? "Enabled" : "Disabled"); vlib_cli_output (vm, "%v", s); vec_free (s); diff --git a/vnet/vnet/ip/ip6_hop_by_hop.h b/vnet/vnet/ip/ip6_hop_by_hop.h index dae58619..7d157cf5 100644 --- a/vnet/vnet/ip/ip6_hop_by_hop.h +++ b/vnet/vnet/ip/ip6_hop_by_hop.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Cisco and/or its affiliates. + * Copyright (c) 2016 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -15,10 +15,30 @@ #ifndef __included_ip6_hop_by_hop_ioam_h__ #define __included_ip6_hop_by_hop_ioam_h__ -#include #include #include + +#define MAX_IP6_HBH_OPTION 256 + +/* To determine whether a node is decap MS bit is set */ +#define IOAM_DECAP_BIT 0x80000000 + +#define IOAM_DEAP_ENABLED(opaque_data) (opaque_data & IOAM_DECAP_BIT) + +#define IOAM_SET_DECAP(opaque_data) \ + (opaque_data |= IOAM_DECAP_BIT) + +#define IOAM_MASK_DECAP_BIT(x) (x & ~IOAM_DECAP_BIT) + +/* + * Stores the run time flow data of hbh options + */ +typedef struct { + u32 ctx[MAX_IP6_HBH_OPTION]; + u8 flow_name[64]; +} flow_data_t; + typedef struct { /* The current rewrite we're using */ u8 * rewrite; @@ -43,10 +63,11 @@ typedef struct { /* Pot option */ u8 has_pot_option; -#define PPC_NONE 0 -#define PPC_ENCAP 1 -#define PPC_DECAP 2 - u8 has_ppc_option; + /* Per Packet Counter option */ + u8 has_seqno_option; + + /* Enabling analyis of iOAM data on decap node */ + u8 has_analyse_option; #define TSP_SECONDS 0 #define TSP_MILLISECONDS 1 @@ -54,11 +75,16 @@ typedef struct { #define TSP_NANOSECONDS 3 /* Array of function pointers to ADD and POP HBH option handling routines */ - u8 options_size[256]; - int (*add_options[256])(u8 *rewrite_string, u8 *rewrite_size); - int (*pop_options[256])(ip6_header_t *ip, ip6_hop_by_hop_option_t *opt); - int (*get_sizeof_options[256])(u32 *rewrite_size); - + u8 options_size[MAX_IP6_HBH_OPTION]; + int (*add_options[MAX_IP6_HBH_OPTION])(u8 *rewrite_string, u8 *rewrite_size); + int (*pop_options[MAX_IP6_HBH_OPTION])(vlib_buffer_t *b, ip6_header_t *ip, ip6_hop_by_hop_option_t *opt); + int (*get_sizeof_options[MAX_IP6_HBH_OPTION])(u32 *rewrite_size); + int (*config_handler[MAX_IP6_HBH_OPTION]) (void *data, u8 disable); + + /* Array of function pointers to handle hbh options being used with classifier */ + u32 (*flow_handler[MAX_IP6_HBH_OPTION])(u32 flow_ctx, u8 add); + flow_data_t *flows; + /* convenience */ vlib_main_t * vlib_main; vnet_main_t * vnet_main; @@ -67,9 +93,11 @@ typedef struct { extern ip6_hop_by_hop_ioam_main_t ip6_hop_by_hop_ioam_main; extern u8 * format_path_map(u8 * s, va_list * args); + extern clib_error_t * ip6_ioam_enable(int has_trace_option, int has_pot_option, - int has_e2e_option); + int has_seqno_option, int has_analyse_option); + extern int ip6_ioam_set_destination (ip6_address_t *addr, u32 mask_width, u32 vrf_id, int is_add, int is_pop, int is_none); @@ -107,7 +135,8 @@ int ip6_hbh_add_register_option (u8 option, int ip6_hbh_add_unregister_option (u8 option); int ip6_hbh_pop_register_option (u8 option, - int options(ip6_header_t *ip, ip6_hop_by_hop_option_t *opt)); + int options(vlib_buffer_t *b, + ip6_header_t *ip, ip6_hop_by_hop_option_t *opt)); int ip6_hbh_pop_unregister_option (u8 option); int @@ -115,6 +144,49 @@ ip6_hbh_get_sizeof_register_option (u8 option, int get_sizeof_hdr_options(u32 *rewrite_size)); int -ip6_ioam_set_rewrite (u8 ** rwp, int has_trace_option, - int has_pot_option, int has_ppc_option); +ip6_ioam_set_rewrite (u8 **rwp, int has_trace_option, + int has_pot_option, int has_seq_no); + +int +ip6_hbh_config_handler_register (u8 option, + int config_handler(void *data, u8 disable)); + +int ip6_hbh_config_handler_unregister (u8 option); + +int ip6_hbh_flow_handler_register(u8 option, + u32 ioam_flow_handler(u32 flow_ctx, u8 add)); + +int ip6_hbh_flow_handler_unregister(u8 option); + +u8 * get_flow_name_from_flow_ctx(u32 flow_ctx); + +static inline flow_data_t * get_flow (u32 index) +{ + flow_data_t *flow = NULL; + ip6_hop_by_hop_ioam_main_t * hm = &ip6_hop_by_hop_ioam_main; + + if (pool_is_free_index (hm->flows, index)) + return NULL; + + flow = pool_elt_at_index (hm->flows, index); + return flow; +} + +static inline u32 get_flow_data_from_flow_ctx (u32 flow_ctx, u8 option) +{ + flow_data_t *flow = NULL; + ip6_hop_by_hop_ioam_main_t * hm = &ip6_hop_by_hop_ioam_main; + u32 index; + + index = IOAM_MASK_DECAP_BIT(flow_ctx); + //flow = pool_elt_at_index (hm->flows, index); + flow = &hm->flows[index]; + return (flow->ctx[option]); +} + +static inline u8 is_seqno_enabled (void) +{ + return (ip6_hop_by_hop_ioam_main.has_seqno_option); +} + #endif /* __included_ip6_hop_by_hop_ioam_h__ */ -- cgit 1.2.3-korg