summaryrefslogtreecommitdiffstats
path: root/vnet
diff options
context:
space:
mode:
authorAkshayaNadahalli <anadahal@cisco.com>2016-08-09 13:38:04 +0530
committerDave Barach <openvpp@barachs.net>2016-11-03 11:44:21 +0000
commited4a2fdd4d62c46a2237157cd3a72bda16fceb6a (patch)
tree1fa59d681435a39f3b7f840b60229f8c3edf4f19 /vnet
parent273c26a531bf031b3426588041bad67fe7f0a246 (diff)
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 <anadahal@cisco.com>
Diffstat (limited to 'vnet')
-rw-r--r--vnet/vnet/buffer.h2
-rw-r--r--vnet/vnet/ip/ip6.h4
-rw-r--r--vnet/vnet/ip/ip6_forward.c12
-rw-r--r--vnet/vnet/ip/ip6_hop_by_hop.c279
-rw-r--r--vnet/vnet/ip/ip6_hop_by_hop.h102
5 files changed, 330 insertions, 69 deletions
diff --git a/vnet/vnet/buffer.h b/vnet/vnet/buffer.h
index 6385f19142c..fafb318104e 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 f6008d71ea1..8b3b9973bf4 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 4493cb4cff3..53d13db2be3 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 72490b915e4..e8bc8906335 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 <vnet/ip/ip6_hop_by_hop.h>
#include <vnet/fib/ip6_fib.h>
+#include <vnet/classify/vnet_classify.h>
/**
* @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 <encap|decap|none>]",
+ .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 dae58619e24..7d157cf55e7 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 <vnet/ip/ip6_hop_by_hop.h>
#include <vnet/ip/ip6_hop_by_hop_packet.h>
#include <vnet/ip/ip.h>
+
+#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__ */