VPP-76:APIs for Proof of transit feature added to iOAM
Moved Proof of Transit utility as a plugin Moved Proof of Transit option as a plugin Change-Id: Idc9897205eb8ec80c5dea47b428e6209ac938c32 Signed-off-by: Shwetha <shwethab@cisco.com>
This commit is contained in:
@ -27,9 +27,40 @@ BUILT_SOURCES =
|
||||
|
||||
lib_LTLIBRARIES = libsixrd_plugin.la
|
||||
|
||||
########################################
|
||||
# iOAM Proof of Transit
|
||||
########################################
|
||||
|
||||
ioam_pot_plugin_la_SOURCES = plugins/ioam/lib-pot/pot_util.c plugins/ioam/encap/ip6_ioam_pot.c \
|
||||
plugins/ioam/lib-pot/pot_util.h plugins/ioam/lib-pot/math64.h plugins/ioam/lib-pot/pot_api.c
|
||||
ioam_pot_plugin_la_LDFLAGS = -module
|
||||
|
||||
BUILT_SOURCES = plugins/ioam/lib-pot/pot.api.h
|
||||
SUFFIXES = .api.h .api
|
||||
|
||||
%.api.h: %.api
|
||||
mkdir -p `dirname $@` ; \
|
||||
$(CC) $(CPPFLAGS) -E -P -C -x c $^ \
|
||||
| vppapigen --input - --output $@ --show-name $@
|
||||
|
||||
nobase_include_HEADERS = \
|
||||
plugins/ioam/lib-pot/pot_all_api_h.h \
|
||||
plugins/ioam/lib-pot/pot_msg_enum.h \
|
||||
plugins/ioam/lib-pot/pot.api.h \
|
||||
plugins/ioam/lib-pot/pot_util.h \
|
||||
plugins/ioam/lib-pot/math64.h
|
||||
|
||||
ioam_pot_test_plugin_la_SOURCES = plugins/ioam/lib-pot/pot_test.c plugins/ioam/lib-pot/pot_plugin.api.h
|
||||
ioam_pot_test_plugin_la_LDFLAGS = -module
|
||||
|
||||
lib_LTLIBRARIES += ioam_pot_plugin.la ioam_pot_test_plugin.la
|
||||
|
||||
if WITH_PLUGIN_TOOLKIT
|
||||
install-data-hook:
|
||||
mkdir /usr/lib/vpp_plugins || true
|
||||
mkdir /usr/lib/vpp_api_test_plugins || true
|
||||
cp $(prefix)/lib/sixrd_plugin.so.*.*.* /usr/lib/vpp_plugins
|
||||
cp $(prefix)/lib/ioam_pot_plugin.so.*.*.* /usr/lib/vpp_plugins
|
||||
cp $(prefix)/lib/ioam_pot_test_plugin.so.*.*.* \
|
||||
/usr/lib/vpp_api_test_plugins
|
||||
endif
|
||||
|
282
plugins/plugins/ioam/encap/ip6_ioam_pot.c
Normal file
282
plugins/plugins/ioam/encap/ip6_ioam_pot.c
Normal file
@ -0,0 +1,282 @@
|
||||
/*
|
||||
* 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:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <vlib/vlib.h>
|
||||
#include <vnet/vnet.h>
|
||||
#include <vnet/pg/pg.h>
|
||||
#include <vppinfra/error.h>
|
||||
|
||||
#include <vnet/ip/ip6.h>
|
||||
#include <vnet/ip/ip6_hop_by_hop.h>
|
||||
#include <vnet/ip/ip6_hop_by_hop_packet.h>
|
||||
|
||||
#include <vppinfra/hash.h>
|
||||
#include <vppinfra/error.h>
|
||||
#include <vppinfra/elog.h>
|
||||
|
||||
#include <lib-pot/pot_util.h>
|
||||
|
||||
typedef CLIB_PACKED(struct {
|
||||
ip6_hop_by_hop_option_t hdr;
|
||||
u8 pot_type;
|
||||
#define PROFILE_ID_MASK 0xF
|
||||
u8 reserved_profile_id; /* 4 bits reserved, 4 bits to carry profile id */
|
||||
u64 random;
|
||||
u64 cumulative;
|
||||
}) ioam_pot_option_t;
|
||||
|
||||
#define foreach_ip6_hop_by_hop_ioam_pot_stats \
|
||||
_(PROCESSED, "Pkts with ip6 hop-by-hop pot options") \
|
||||
_(PROFILE_MISS, "Pkts with ip6 hop-by-hop pot options but no profile set") \
|
||||
_(PASSED, "Pkts with POT in Policy") \
|
||||
_(FAILED, "Pkts with POT out of Policy")
|
||||
|
||||
static char * ip6_hop_by_hop_ioam_pot_stats_strings[] = {
|
||||
#define _(sym,string) string,
|
||||
foreach_ip6_hop_by_hop_ioam_pot_stats
|
||||
#undef _
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
#define _(sym,str) IP6_IOAM_POT_##sym,
|
||||
foreach_ip6_hop_by_hop_ioam_pot_stats
|
||||
#undef _
|
||||
IP6_IOAM_POT_N_STATS,
|
||||
} ip6_ioam_pot_stats_t;
|
||||
|
||||
typedef struct {
|
||||
/* stats */
|
||||
u64 counters[ARRAY_LEN(ip6_hop_by_hop_ioam_pot_stats_strings)];
|
||||
|
||||
/* convenience */
|
||||
vlib_main_t * vlib_main;
|
||||
vnet_main_t * vnet_main;
|
||||
} ip6_hop_by_hop_ioam_pot_main_t;
|
||||
|
||||
ip6_hop_by_hop_ioam_pot_main_t ip6_hop_by_hop_ioam_pot_main;
|
||||
|
||||
always_inline void
|
||||
ip6_ioam_stats_increment_counter (u32 counter_index, u64 increment)
|
||||
{
|
||||
ip6_hop_by_hop_ioam_pot_main_t *hm = &ip6_hop_by_hop_ioam_pot_main;
|
||||
|
||||
hm->counters[counter_index] += increment;
|
||||
}
|
||||
|
||||
|
||||
static u8 * format_ioam_pot (u8 * s, va_list * args)
|
||||
{
|
||||
ioam_pot_option_t * pot0 = va_arg (*args, ioam_pot_option_t *);
|
||||
u64 random, cumulative;
|
||||
random = cumulative = 0;
|
||||
if (pot0)
|
||||
{
|
||||
random = clib_net_to_host_u64 (pot0->random);
|
||||
cumulative = clib_net_to_host_u64 (pot0->cumulative);
|
||||
}
|
||||
|
||||
s = format (s, "random = 0x%Lx, Cumulative = 0x%Lx, Index = 0x%x",
|
||||
random, cumulative, pot0->reserved_profile_id);
|
||||
return s;
|
||||
}
|
||||
|
||||
u8 *
|
||||
ip6_hbh_ioam_proof_of_transit_trace_handler (u8 *s, ip6_hop_by_hop_option_t *opt)
|
||||
{
|
||||
ioam_pot_option_t *pot;
|
||||
|
||||
s = format (s, " POT opt present\n");
|
||||
pot = (ioam_pot_option_t *) opt;
|
||||
s = format (s, " %U\n", format_ioam_pot, pot);
|
||||
return (s);
|
||||
}
|
||||
|
||||
int
|
||||
ip6_hbh_ioam_proof_of_transit_handler (vlib_buffer_t *b,
|
||||
ip6_header_t *ip,
|
||||
ip6_hop_by_hop_option_t *opt0)
|
||||
{
|
||||
ioam_pot_option_t * pot0;
|
||||
u64 random = 0, cumulative = 0;
|
||||
int rv = 0;
|
||||
u8 pot_profile_index;
|
||||
pot_profile *pot_profile = 0, *new_profile = 0;
|
||||
u8 pot_encap = 0;
|
||||
|
||||
pot0 = (ioam_pot_option_t *) opt0;
|
||||
pot_encap = (pot0->random == 0);
|
||||
pot_profile_index = pot_profile_get_active_id();
|
||||
pot_profile = pot_profile_get_active();
|
||||
if (pot_encap && PREDICT_FALSE(!pot_profile))
|
||||
{
|
||||
ip6_ioam_stats_increment_counter (IP6_IOAM_POT_PROFILE_MISS, 1);
|
||||
return(-1);
|
||||
}
|
||||
if (pot_encap)
|
||||
{
|
||||
pot0->reserved_profile_id =
|
||||
pot_profile_index & PROFILE_ID_MASK;
|
||||
pot_profile_incr_usage_stats(pot_profile);
|
||||
}
|
||||
else
|
||||
{ /* Non encap node */
|
||||
if (PREDICT_FALSE(pot0->reserved_profile_id !=
|
||||
pot_profile_index || pot_profile == 0))
|
||||
{
|
||||
/* New profile announced by encap node. */
|
||||
new_profile =
|
||||
pot_profile_find(pot0->reserved_profile_id);
|
||||
if (PREDICT_FALSE(new_profile == 0 ||
|
||||
new_profile->valid == 0))
|
||||
{
|
||||
ip6_ioam_stats_increment_counter (IP6_IOAM_POT_PROFILE_MISS, 1);
|
||||
return(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
pot_profile_index = pot0->reserved_profile_id;
|
||||
pot_profile = new_profile;
|
||||
pot_profile_set_active(pot_profile_index);
|
||||
pot_profile_reset_usage_stats(pot_profile);
|
||||
}
|
||||
}
|
||||
pot_profile_incr_usage_stats(pot_profile);
|
||||
}
|
||||
|
||||
if (pot0->random == 0)
|
||||
{
|
||||
pot0->random = clib_host_to_net_u64(pot_generate_random(pot_profile));
|
||||
pot0->cumulative = 0;
|
||||
}
|
||||
random = clib_net_to_host_u64(pot0->random);
|
||||
cumulative = clib_net_to_host_u64(pot0->cumulative);
|
||||
pot0->cumulative = clib_host_to_net_u64(
|
||||
pot_update_cumulative(pot_profile,
|
||||
cumulative,
|
||||
random));
|
||||
ip6_ioam_stats_increment_counter (IP6_IOAM_POT_PROCESSED, 1);
|
||||
|
||||
return (rv);
|
||||
}
|
||||
|
||||
int
|
||||
ip6_hbh_ioam_proof_of_transit_pop_handler (ip6_header_t *ip,
|
||||
ip6_hop_by_hop_option_t *opt0)
|
||||
{
|
||||
ioam_pot_option_t * pot0;
|
||||
u64 random = 0;
|
||||
u64 cumulative = 0;
|
||||
int rv = 0;
|
||||
pot_profile *pot_profile = 0;
|
||||
u8 result = 0;
|
||||
|
||||
pot0 = (ioam_pot_option_t *) opt0;
|
||||
random = clib_net_to_host_u64(pot0->random);
|
||||
cumulative = clib_net_to_host_u64(pot0->cumulative);
|
||||
pot_profile = pot_profile_get_active();
|
||||
result = pot_validate (pot_profile,
|
||||
cumulative, random);
|
||||
|
||||
if (result == 1)
|
||||
{
|
||||
ip6_ioam_stats_increment_counter (IP6_IOAM_POT_PASSED, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
ip6_ioam_stats_increment_counter (IP6_IOAM_POT_FAILED, 1);
|
||||
}
|
||||
return (rv);
|
||||
}
|
||||
|
||||
int ip6_hop_by_hop_ioam_pot_rewrite_handler (u8 *rewrite_string, u8 rewrite_size)
|
||||
{
|
||||
ioam_pot_option_t * pot_option;
|
||||
if (rewrite_string && rewrite_size == sizeof(ioam_pot_option_t))
|
||||
{
|
||||
pot_option = (ioam_pot_option_t *)rewrite_string;
|
||||
pot_option->hdr.type = HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT
|
||||
| HBH_OPTION_TYPE_DATA_CHANGE_ENROUTE;
|
||||
pot_option->hdr.length = sizeof (ioam_pot_option_t) -
|
||||
sizeof (ip6_hop_by_hop_option_t);
|
||||
return(0);
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
static clib_error_t *
|
||||
ip6_show_ioam_pot_cmd_fn (vlib_main_t * vm,
|
||||
unformat_input_t * input,
|
||||
vlib_cli_command_t * cmd)
|
||||
{
|
||||
ip6_hop_by_hop_ioam_pot_main_t *hm = &ip6_hop_by_hop_ioam_pot_main;
|
||||
u8 *s = 0;
|
||||
int i = 0;
|
||||
|
||||
for ( i = 0; i < IP6_IOAM_POT_N_STATS; i++)
|
||||
{
|
||||
s = format(s, " %s - %lu\n", ip6_hop_by_hop_ioam_pot_stats_strings[i],
|
||||
hm->counters[i]);
|
||||
}
|
||||
|
||||
vlib_cli_output(vm, "%v", s);
|
||||
vec_free(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
VLIB_CLI_COMMAND (ip6_show_ioam_pot_cmd, static) = {
|
||||
.path = "show ioam pot",
|
||||
.short_help = "iOAM pot statistics",
|
||||
.function = ip6_show_ioam_pot_cmd_fn,
|
||||
};
|
||||
|
||||
|
||||
static clib_error_t *
|
||||
ip6_hop_by_hop_ioam_pot_init (vlib_main_t * vm)
|
||||
{
|
||||
ip6_hop_by_hop_ioam_pot_main_t * hm = &ip6_hop_by_hop_ioam_pot_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));
|
||||
|
||||
if (ip6_hbh_register_option(HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT, ip6_hbh_ioam_proof_of_transit_handler,
|
||||
ip6_hbh_ioam_proof_of_transit_trace_handler) < 0)
|
||||
return (clib_error_create("registration of HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT failed"));
|
||||
|
||||
if (ip6_hbh_add_register_option(HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT,
|
||||
sizeof(ioam_pot_option_t),
|
||||
ip6_hop_by_hop_ioam_pot_rewrite_handler) < 0)
|
||||
return (clib_error_create("registration of HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT for rewrite failed"));
|
||||
|
||||
if (ip6_hbh_pop_register_option(HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT,
|
||||
ip6_hbh_ioam_proof_of_transit_pop_handler) < 0)
|
||||
return (clib_error_create("registration of HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT POP failed"));
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
VLIB_INIT_FUNCTION (ip6_hop_by_hop_ioam_pot_init);
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Hence this header to combine add/multiply followed by modulo of u64 integrers
|
||||
* always resulting in u64.
|
||||
*
|
||||
* 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:
|
97
plugins/plugins/ioam/lib-pot/pot.api
Normal file
97
plugins/plugins/ioam/lib-pot/pot.api
Normal file
@ -0,0 +1,97 @@
|
||||
/* Hey Emacs use -*- mode: C -*- */
|
||||
/*
|
||||
* 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:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
/** \brief Proof of Transit(POT): Set POT profile
|
||||
@param id - id of the profile
|
||||
@param validator - True/False to indicate if this is verifier
|
||||
@param secret_key - Verification key
|
||||
@param secret_share - Share of the 1st polynomial
|
||||
@param prime - Prime number used for modulo operation
|
||||
@param max_bits - Max bits to be used for Random number generation
|
||||
@param lpc - Lagrange basis polynomial
|
||||
@param polynomial_public - pre-evaluated public polynomial
|
||||
@param list_name_len - length of the name of this profile list
|
||||
@param list_name - name of this profile list
|
||||
*/
|
||||
define pot_profile_add {
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
u8 id;
|
||||
u8 validator;
|
||||
u64 secret_key;
|
||||
u64 secret_share;
|
||||
u64 prime;
|
||||
u8 max_bits;
|
||||
u64 lpc;
|
||||
u64 polynomial_public;
|
||||
u8 list_name_len;
|
||||
u8 list_name[0];
|
||||
};
|
||||
|
||||
/** \brief Proof of Transit profile add / del response
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param retval - return value for request
|
||||
*/
|
||||
define pot_profile_add_reply {
|
||||
u32 context;
|
||||
i32 retval;
|
||||
};
|
||||
|
||||
|
||||
/** \brief Proof of Transit(POT): Activate POT profile in the list
|
||||
@param id - id of the profile
|
||||
@param list_name_len - length of the name of this profile list
|
||||
@param list_name - name of this profile list
|
||||
*/
|
||||
define pot_profile_activate {
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
u8 id;
|
||||
u8 list_name_len;
|
||||
u8 list_name[0];
|
||||
};
|
||||
|
||||
/** \brief Proof of Transit profile activate response
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param retval - return value for request
|
||||
*/
|
||||
define pot_profile_activate_reply {
|
||||
u32 context;
|
||||
i32 retval;
|
||||
};
|
||||
|
||||
/** \brief Delete POT Profile
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param list_name_len - length of the name of the profile list
|
||||
@param list_name - name of profile list to delete
|
||||
*/
|
||||
define pot_profile_del {
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
u8 list_name_len;
|
||||
u8 list_name[0];
|
||||
};
|
||||
|
||||
/** \brief Proof of Transit profile add / del response
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param retval - return value for request
|
||||
*/
|
||||
define pot_profile_del_reply {
|
||||
u32 context;
|
||||
i32 retval;
|
||||
};
|
16
plugins/plugins/ioam/lib-pot/pot_all_api_h.h
Normal file
16
plugins/plugins/ioam/lib-pot/pot_all_api_h.h
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* 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:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/* Include the generated file, see BUILT_SOURCES in Makefile.am */
|
||||
#include <lib-pot/pot.api.h>
|
230
plugins/plugins/ioam/lib-pot/pot_api.c
Normal file
230
plugins/plugins/ioam/lib-pot/pot_api.c
Normal file
@ -0,0 +1,230 @@
|
||||
/*
|
||||
* 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:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/*
|
||||
*------------------------------------------------------------------
|
||||
* pot_api.c - Proof of Transit related APIs to create
|
||||
* and maintain profiles
|
||||
*------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <vnet/vnet.h>
|
||||
#include <vnet/plugin/plugin.h>
|
||||
#include <lib-pot/pot_util.h>
|
||||
|
||||
#include <vlibapi/api.h>
|
||||
#include <vlibmemory/api.h>
|
||||
#include <vlibsocket/api.h>
|
||||
|
||||
/* define message IDs */
|
||||
#include <lib-pot/pot_msg_enum.h>
|
||||
|
||||
/* define message structures */
|
||||
#define vl_typedefs
|
||||
#include <lib-pot/pot_all_api_h.h>
|
||||
#undef vl_typedefs
|
||||
|
||||
/* define generated endian-swappers */
|
||||
#define vl_endianfun
|
||||
#include <lib-pot/pot_all_api_h.h>
|
||||
#undef vl_endianfun
|
||||
|
||||
/* instantiate all the print functions we know about */
|
||||
#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
|
||||
#define vl_printfun
|
||||
#include <lib-pot/pot_all_api_h.h>
|
||||
#undef vl_printfun
|
||||
|
||||
/* Get the API version number */
|
||||
#define vl_api_version(n,v) static u32 api_version=(v);
|
||||
#include <lib-pot/pot_all_api_h.h>
|
||||
#undef vl_api_version
|
||||
|
||||
/*
|
||||
* A handy macro to set up a message reply.
|
||||
* Assumes that the following variables are available:
|
||||
* mp - pointer to request message
|
||||
* rmp - pointer to reply message type
|
||||
* rv - return value
|
||||
*/
|
||||
|
||||
#define REPLY_MACRO(t) \
|
||||
do { \
|
||||
unix_shared_memory_queue_t * q = \
|
||||
vl_api_client_index_to_input_queue (mp->client_index); \
|
||||
if (!q) \
|
||||
return; \
|
||||
\
|
||||
rmp = vl_msg_api_alloc (sizeof (*rmp)); \
|
||||
rmp->_vl_msg_id = ntohs((t)+sm->msg_id_base); \
|
||||
rmp->context = mp->context; \
|
||||
rmp->retval = ntohl(rv); \
|
||||
\
|
||||
vl_msg_api_send_shmem (q, (u8 *)&rmp); \
|
||||
} while(0);
|
||||
|
||||
#define REPLY_MACRO2(t, body) \
|
||||
do { \
|
||||
unix_shared_memory_queue_t * q; \
|
||||
rv = vl_msg_api_pd_handler (mp, rv); \
|
||||
q = vl_api_client_index_to_input_queue (mp->client_index); \
|
||||
if (!q) \
|
||||
return; \
|
||||
\
|
||||
rmp = vl_msg_api_alloc (sizeof (*rmp)); \
|
||||
rmp->_vl_msg_id = ntohs((t)); \
|
||||
rmp->context = mp->context; \
|
||||
rmp->retval = ntohl(rv); \
|
||||
do {body;} while (0); \
|
||||
vl_msg_api_send_shmem (q, (u8 *)&rmp); \
|
||||
} while(0);
|
||||
|
||||
/* List of message types that this plugin understands */
|
||||
|
||||
#define foreach_pot_plugin_api_msg \
|
||||
_(POT_PROFILE_ADD, pot_profile_add) \
|
||||
_(POT_PROFILE_ACTIVATE, pot_profile_activate) \
|
||||
_(POT_PROFILE_DEL, pot_profile_del) \
|
||||
|
||||
static void vl_api_pot_profile_add_t_handler
|
||||
(vl_api_pot_profile_add_t *mp)
|
||||
{
|
||||
pot_main_t * sm = &pot_main;
|
||||
int rv = 0;
|
||||
vl_api_pot_profile_add_reply_t * rmp;
|
||||
u8 id;
|
||||
pot_profile *profile = NULL;
|
||||
u8 *name = 0;
|
||||
|
||||
if (mp->list_name_len)
|
||||
name = format(0, "%s", mp->list_name);
|
||||
|
||||
pot_profile_list_init(name);
|
||||
id = mp->id;
|
||||
profile = pot_profile_find(id);
|
||||
if (profile) {
|
||||
rv = pot_profile_create(profile,
|
||||
clib_net_to_host_u64(mp->prime),
|
||||
clib_net_to_host_u64(mp->polynomial_public),
|
||||
clib_net_to_host_u64(mp->lpc),
|
||||
clib_net_to_host_u64(mp->secret_share));
|
||||
if (rv != 0)
|
||||
goto ERROROUT;
|
||||
if (1 == mp->validator)
|
||||
(void)pot_set_validator(profile, clib_net_to_host_u64(mp->secret_key));
|
||||
(void)pot_profile_set_bit_mask(profile, mp->max_bits);
|
||||
} else {
|
||||
rv = -3;
|
||||
}
|
||||
ERROROUT:
|
||||
vec_free(name);
|
||||
REPLY_MACRO(VL_API_POT_PROFILE_ADD_REPLY);
|
||||
}
|
||||
|
||||
static void vl_api_pot_profile_activate_t_handler
|
||||
(vl_api_pot_profile_activate_t *mp)
|
||||
{
|
||||
pot_main_t * sm = &pot_main;
|
||||
int rv = 0;
|
||||
vl_api_pot_profile_add_reply_t * rmp;
|
||||
u8 id;
|
||||
u8 *name = NULL;
|
||||
|
||||
if (mp->list_name_len)
|
||||
name = format(0, "%s", mp->list_name);
|
||||
if (!pot_profile_list_is_enabled(name)) {
|
||||
rv = -1;
|
||||
} else {
|
||||
id = mp->id;
|
||||
rv = pot_profile_set_active(id);
|
||||
}
|
||||
|
||||
vec_free(name);
|
||||
REPLY_MACRO(VL_API_POT_PROFILE_ACTIVATE_REPLY);
|
||||
}
|
||||
|
||||
|
||||
static void vl_api_pot_profile_del_t_handler
|
||||
(vl_api_pot_profile_del_t *mp)
|
||||
{
|
||||
pot_main_t * sm = &pot_main;
|
||||
int rv = 0;
|
||||
vl_api_pot_profile_del_reply_t * rmp;
|
||||
|
||||
clear_pot_profiles();
|
||||
|
||||
REPLY_MACRO(VL_API_POT_PROFILE_DEL_REPLY);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This routine exists to convince the vlib plugin framework that
|
||||
* we haven't accidentally copied a random .dll into the plugin directory.
|
||||
*
|
||||
* Also collects global variable pointers passed from the vpp engine
|
||||
*/
|
||||
|
||||
clib_error_t *
|
||||
vlib_plugin_register (vlib_main_t * vm, vnet_plugin_handoff_t * h,
|
||||
int from_early_init)
|
||||
{
|
||||
pot_main_t * sm = &pot_main;
|
||||
clib_error_t * error = 0;
|
||||
|
||||
sm->vlib_main = vm;
|
||||
sm->vnet_main = h->vnet_main;
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Set up the API message handling tables */
|
||||
static clib_error_t *
|
||||
pot_plugin_api_hookup (vlib_main_t *vm)
|
||||
{
|
||||
pot_main_t * sm = &pot_main;
|
||||
#define _(N,n) \
|
||||
vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base), \
|
||||
#n, \
|
||||
vl_api_##n##_t_handler, \
|
||||
vl_noop_handler, \
|
||||
vl_api_##n##_t_endian, \
|
||||
vl_api_##n##_t_print, \
|
||||
sizeof(vl_api_##n##_t), 1);
|
||||
foreach_pot_plugin_api_msg;
|
||||
#undef _
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static clib_error_t * pot_init (vlib_main_t * vm)
|
||||
{
|
||||
pot_main_t * sm = &pot_main;
|
||||
clib_error_t * error = 0;
|
||||
u8 * name;
|
||||
|
||||
bzero(sm, sizeof(pot_main));
|
||||
(void)pot_util_init();
|
||||
name = format (0, "pot_%08x%c", api_version, 0);
|
||||
|
||||
/* Ask for a correctly-sized block of API message decode slots */
|
||||
sm->msg_id_base = vl_msg_api_get_msg_ids
|
||||
((char *) name, VL_MSG_FIRST_AVAILABLE);
|
||||
|
||||
error = pot_plugin_api_hookup (vm);
|
||||
|
||||
vec_free(name);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
VLIB_INIT_FUNCTION (pot_init);
|
28
plugins/plugins/ioam/lib-pot/pot_msg_enum.h
Normal file
28
plugins/plugins/ioam/lib-pot/pot_msg_enum.h
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef included_pot_msg_enum_h
|
||||
#define included_pot_msg_enum_h
|
||||
|
||||
#include <vppinfra/byte_order.h>
|
||||
|
||||
#define vl_msg_id(n,h) n,
|
||||
typedef enum {
|
||||
#include <lib-pot/pot_all_api_h.h>
|
||||
/* We'll want to know how many messages IDs we need... */
|
||||
VL_MSG_FIRST_AVAILABLE,
|
||||
} vl_msg_id_t;
|
||||
#undef vl_msg_id
|
||||
|
||||
#endif /* included_pot_msg_enum_h */
|
313
plugins/plugins/ioam/lib-pot/pot_test.c
Normal file
313
plugins/plugins/ioam/lib-pot/pot_test.c
Normal file
File diff suppressed because it is too large
Load Diff
446
plugins/plugins/ioam/lib-pot/pot_util.c
Normal file
446
plugins/plugins/ioam/lib-pot/pot_util.c
Normal file
File diff suppressed because it is too large
Load Diff
195
plugins/plugins/ioam/lib-pot/pot_util.h
Normal file
195
plugins/plugins/ioam/lib-pot/pot_util.h
Normal file
@ -0,0 +1,195 @@
|
||||
/*
|
||||
* pot_util.h -- Proof Of Transit Utility Header
|
||||
*
|
||||
* 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:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef include_vnet_pot_util_h
|
||||
#define include_vnet_pot_util_h
|
||||
|
||||
#include <vnet/ip/ip6_hop_by_hop.h>
|
||||
#define debug_ioam debug_ioam_fn
|
||||
/* Dont change this size 256. This is there across multiple components */
|
||||
#define PATH_NAME_SIZE 256
|
||||
|
||||
/* Ring size. this should be same as the one in ODL. Do not change this
|
||||
without change in ODL. */
|
||||
#define MAX_POT_PROFILES 2
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
*
|
||||
* On any node that participates in Proof of Transit:
|
||||
*
|
||||
* Step 1: Initialize this library by calling pot_init()
|
||||
* Step 2: Setup a proof of transit profile that contains all the parameters needed to compute cumulative:
|
||||
* Call these functions:
|
||||
* pot_profile_find
|
||||
* pot_profile_create
|
||||
* pot_profile_set_bit_mask - To setup how large we want the numbers used in the computation and random number <= 64 bits
|
||||
* Step 2a: For validator do this:
|
||||
* pot_set_validator
|
||||
* Step 2b: On initial node enable the profile to be used:
|
||||
* pot_profile_set_active / pot_profile_get_active will return the profile
|
||||
* Step 3a: At the initial node to generate Random number that will be read by all other nodes:
|
||||
* pot_generate_random
|
||||
* Step 3b: At all nodes including initial and verifier call this to compute cumulative:
|
||||
* pot_update_cumulative
|
||||
* Step 4: At the verifier:
|
||||
* pot_validate
|
||||
*
|
||||
*/
|
||||
|
||||
typedef struct pot_profile_
|
||||
{
|
||||
u8 id : 1;
|
||||
u8 valid : 1;
|
||||
u8 in_use : 1;
|
||||
u64 random;
|
||||
u8 validator;
|
||||
u64 secret_key;
|
||||
u64 secret_share;
|
||||
u64 prime;
|
||||
u64 lpc;
|
||||
u64 poly_pre_eval;
|
||||
u64 bit_mask;
|
||||
u64 limit;
|
||||
double primeinv;
|
||||
u64 total_pkts_using_this_profile;
|
||||
} pot_profile;
|
||||
|
||||
typedef struct {
|
||||
/* Name of the default profile list in use*/
|
||||
u8 *profile_list_name;
|
||||
pot_profile profile_list[MAX_POT_PROFILES];
|
||||
/* number of profiles in the list */
|
||||
u8 active_profile_id : 1;
|
||||
|
||||
/* API message ID base */
|
||||
u16 msg_id_base;
|
||||
|
||||
/* convenience */
|
||||
vlib_main_t * vlib_main;
|
||||
vnet_main_t * vnet_main;
|
||||
} pot_main_t;
|
||||
|
||||
extern pot_main_t pot_main;
|
||||
|
||||
/*
|
||||
* Initialize proof of transit
|
||||
*/
|
||||
int pot_util_init(void);
|
||||
void pot_profile_list_init(u8 * name);
|
||||
|
||||
|
||||
/*
|
||||
* Find a pot profile by ID
|
||||
*/
|
||||
pot_profile *pot_profile_find(u8 id);
|
||||
|
||||
static inline u16 pot_profile_get_id(pot_profile * profile)
|
||||
{
|
||||
if (profile)
|
||||
{
|
||||
return (profile->id);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* setup and clean up profile */
|
||||
int pot_profile_create(pot_profile * profile, u64 prime,
|
||||
u64 poly2, u64 lpc, u64 secret_share);
|
||||
/*
|
||||
* Setup profile as a validator
|
||||
*/
|
||||
int pot_set_validator(pot_profile * profile, u64 key);
|
||||
|
||||
/*
|
||||
* Setup max bits to be used for random number generation
|
||||
*/
|
||||
#define MAX_BITS 64
|
||||
int pot_profile_set_bit_mask(pot_profile * profile, u16 bits);
|
||||
|
||||
/*
|
||||
* Given a random and cumulative compute the new cumulative for a given profile
|
||||
*/
|
||||
u64 pot_update_cumulative(pot_profile * profile, u64 cumulative, u64 random);
|
||||
|
||||
/*
|
||||
* return True if the cumulative matches secret from a profile
|
||||
*/
|
||||
u8 pot_validate(pot_profile * profile, u64 cumulative, u64 random);
|
||||
|
||||
/*
|
||||
* Utility function to get random number per pack
|
||||
*/
|
||||
u64 pot_generate_random(pot_profile * profile);
|
||||
|
||||
|
||||
extern void clear_pot_profiles();
|
||||
extern int pot_profile_list_is_enabled(u8 *name);
|
||||
|
||||
static inline u8 pot_is_decap(pot_profile * p)
|
||||
{
|
||||
return (p->validator == 1);
|
||||
}
|
||||
|
||||
static inline int pot_profile_set_active (u8 id)
|
||||
{
|
||||
pot_main_t *sm = &pot_main;
|
||||
pot_profile *profile = NULL;
|
||||
pot_profile *current_active_prof = NULL;
|
||||
|
||||
current_active_prof = pot_profile_find(sm->active_profile_id);
|
||||
profile = pot_profile_find(id);
|
||||
if (profile && profile->valid) {
|
||||
sm->active_profile_id = id;
|
||||
current_active_prof->in_use = 0;
|
||||
profile->in_use = 1;
|
||||
return(0);
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
static inline u8 pot_profile_get_active_id (void)
|
||||
{
|
||||
pot_main_t *sm = &pot_main;
|
||||
return (sm->active_profile_id);
|
||||
}
|
||||
|
||||
static inline pot_profile * pot_profile_get_active (void)
|
||||
{
|
||||
pot_main_t *sm = &pot_main;
|
||||
pot_profile *profile = NULL;
|
||||
profile = pot_profile_find(sm->active_profile_id);
|
||||
if (profile && profile->in_use)
|
||||
return(profile);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static inline void pot_profile_reset_usage_stats (pot_profile *pow)
|
||||
{
|
||||
if (pow) {
|
||||
pow->total_pkts_using_this_profile = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void pot_profile_incr_usage_stats (pot_profile *pow)
|
||||
{
|
||||
if (pow) {
|
||||
pow->total_pkts_using_this_profile++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
@ -717,16 +717,6 @@ libvnetplugin_la_SOURCES += \
|
||||
nobase_include_HEADERS += \
|
||||
vnet/plugin/plugin.h
|
||||
|
||||
########################################
|
||||
# Service Chain verification util
|
||||
########################################
|
||||
libvnet_la_SOURCES += \
|
||||
vnet/lib-scv/scv_util.c
|
||||
|
||||
nobase_include_HEADERS += \
|
||||
vnet/lib-scv/scv_util.h \
|
||||
vnet/lib-scv/math64.h
|
||||
|
||||
lib_LTLIBRARIES = libvnet.la libvnetplugin.la
|
||||
|
||||
dpdk_libs =
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -45,8 +45,8 @@ typedef struct {
|
||||
u32 node_id;
|
||||
u32 app_data;
|
||||
|
||||
/* PoW option */
|
||||
u8 has_pow_option;
|
||||
/* Pot option */
|
||||
u8 has_pot_option;
|
||||
|
||||
#define PPC_NONE 0
|
||||
#define PPC_ENCAP 1
|
||||
@ -59,7 +59,12 @@ typedef struct {
|
||||
#define TSP_NANOSECONDS 3
|
||||
/* Time stamp precision. This is enumerated to above four options */
|
||||
u32 trace_tsp;
|
||||
|
||||
|
||||
/* 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);
|
||||
|
||||
/* convenience */
|
||||
vlib_main_t * vlib_main;
|
||||
vnet_main_t * vnet_main;
|
||||
@ -70,7 +75,7 @@ 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_trace_profile_set(u32 trace_option_elts, u32 trace_type, u32 node_id,
|
||||
u32 app_data, int has_pow_option, u32 trace_tsp,
|
||||
u32 app_data, int has_pot_option, u32 trace_tsp,
|
||||
int has_e2e_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);
|
||||
@ -103,5 +108,14 @@ static inline u8 is_zero_ip6_address (ip6_address_t *a)
|
||||
return ((a->as_u64[0] == 0) && (a->as_u64[1] == 0));
|
||||
}
|
||||
|
||||
extern ip6_hop_by_hop_ioam_main_t * hm;
|
||||
int ip6_hbh_add_register_option (u8 option,
|
||||
u8 size,
|
||||
int rewrite_options(u8 *rewrite_string, u8 size));
|
||||
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 ip6_hbh_pop_unregister_option (u8 option);
|
||||
|
||||
|
||||
#endif /* __included_ip6_hop_by_hop_ioam_h__ */
|
||||
|
@ -40,7 +40,7 @@ typedef struct {
|
||||
|
||||
/* $$$$ IANA banana constants */
|
||||
#define HBH_OPTION_TYPE_IOAM_TRACE_DATA_LIST 59 /* Third highest bit set (change en-route) */
|
||||
#define HBH_OPTION_TYPE_IOAM_PROOF_OF_WORK 60 /* Third highest bit set (change en-route) */
|
||||
#define HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT 60 /* Third highest bit set (change en-route) */
|
||||
#define HBH_OPTION_TYPE_IOAM_EDGE_TO_EDGE 29
|
||||
|
||||
/*
|
||||
@ -171,14 +171,6 @@ typedef CLIB_PACKED(struct {
|
||||
u32 elts[0]; /* Variable type. So keep it generic */
|
||||
}) ioam_trace_option_t;
|
||||
|
||||
typedef CLIB_PACKED(struct {
|
||||
ip6_hop_by_hop_option_t hdr;
|
||||
u8 pow_type;
|
||||
#define PROFILE_ID_MASK 0xF
|
||||
u8 reserved_profile_id; /* 4 bits reserved, 4 bits to carry profile id */
|
||||
u64 random;
|
||||
u64 cumulative;
|
||||
}) ioam_pow_option_t;
|
||||
|
||||
typedef CLIB_PACKED(struct {
|
||||
ip6_hop_by_hop_option_t hdr;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,278 +0,0 @@
|
||||
/*
|
||||
* scv_util.h -- Service chain validation/Proof Of Transit Utility Header
|
||||
*
|
||||
* Copyright (c) 2015 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:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef include_vnet_scv_util_h
|
||||
#define include_vnet_scv_util_h
|
||||
|
||||
#include <vnet/ip/ip6_hop_by_hop.h>
|
||||
#define MAXDEGREE 1024
|
||||
#define MAXTOKENLEN 128
|
||||
#define debug_ioam debug_ioam_fn
|
||||
#define MAX_SERVICE_NODES 10
|
||||
/* Dont change this size 256. This is there across multiple components */
|
||||
#define PATH_NAME_SIZE 256
|
||||
|
||||
/* Ring size. this should be same as the one in ODL. Do not change this
|
||||
without change in ODL. */
|
||||
#define MAX_SERVICE_PROFILES 16
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
*
|
||||
* On any [service] node that participates in Service / Path verfication:
|
||||
*
|
||||
* Step 1: Initialize this library by calling scv_init()
|
||||
* Step 2: Setup a Service chain validation profile that contains all the parameters needed to compute cumulative:
|
||||
* Call these functions:
|
||||
* scv_profile_find
|
||||
* scv_profile_create
|
||||
* scv_profile_set_bit_mask - To setup how large we want the numbers used in the computation and random number <= 64 bits
|
||||
* Step 2a: For validator do this:
|
||||
* scv_set_validator
|
||||
* Step 3a: At the initial Service node to generate Random number that will be read by all other nodes:
|
||||
* scv_generate_random
|
||||
* Step 3b: At all service nodes including initial and verifier call this to compute cumulative:
|
||||
* scv_update_cumulative
|
||||
* Step 4: At the verifier:
|
||||
* scv_validate
|
||||
*
|
||||
*/
|
||||
|
||||
typedef struct scv_profile_
|
||||
{
|
||||
u16 id;
|
||||
u64 random;
|
||||
u8 validator;
|
||||
u64 secret_key;
|
||||
u64 secret_share;
|
||||
u64 prime;
|
||||
u64 lpc;
|
||||
u64 poly_pre_eval;
|
||||
u64 bit_mask;
|
||||
u64 limit;
|
||||
u64 validity;
|
||||
double primeinv;
|
||||
// struct hlist_node my_hash_list; when this gets added to hashtbale
|
||||
} scv_profile;
|
||||
|
||||
extern scv_profile *pow_profile;
|
||||
extern u16 pow_profile_index;
|
||||
extern u64 total_pkts_using_this_profile;
|
||||
extern u8 chain_path_name[PATH_NAME_SIZE];
|
||||
extern u16 invalid_profile_start_index;
|
||||
extern u8 number_of_invalid_profiles;
|
||||
extern f64 next_time_to_send;
|
||||
extern u32 time_exponent;
|
||||
|
||||
/*
|
||||
* Initialize Service chain
|
||||
*/
|
||||
void scv_init(u8 * path_name, u8 max, u8 indx);
|
||||
|
||||
/*
|
||||
* Get maximum number of profiles configured for this chain.
|
||||
*/
|
||||
u8 scv_get_max_profiles(void);
|
||||
|
||||
/*
|
||||
* Find a SC profile by ID
|
||||
*/
|
||||
scv_profile *scv_profile_find(u16 id);
|
||||
|
||||
static inline u16 scv_profile_get_id(scv_profile * profile)
|
||||
{
|
||||
if (profile)
|
||||
{
|
||||
return (profile->id);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* setup and clean up profile */
|
||||
void scv_profile_create(scv_profile * profile, u64 prime,
|
||||
u64 poly2, u64 lpc, u64 secret_share, u64 validity);
|
||||
/*
|
||||
* Setup profile as a validator
|
||||
*/
|
||||
void scv_set_validator(scv_profile * profile, u64 key);
|
||||
void scv_profile_cleanup(scv_profile * profile);
|
||||
|
||||
/*
|
||||
* Setup max bits to be used for random number generation
|
||||
*/
|
||||
#define MAX_BITS 64
|
||||
void scv_profile_set_bit_mask(scv_profile * profile, u16 bits);
|
||||
|
||||
/*
|
||||
* Given a random and cumulative compute the new cumulative for a given profile
|
||||
*/
|
||||
u64 scv_update_cumulative(scv_profile * profile, u64 cumulative, u64 random);
|
||||
|
||||
/*
|
||||
* return True if the cumulative matches secret from a profile
|
||||
*/
|
||||
u8 scv_validate(scv_profile * profile, u64 cumulative, u64 random);
|
||||
|
||||
/*
|
||||
* Utility function to get random number per pack
|
||||
*/
|
||||
u64 scv_generate_random(scv_profile * profile);
|
||||
|
||||
int scv_profile_to_str(scv_profile * profile, char *buf, int n);
|
||||
|
||||
extern void clear_ioam_scv_profiles();
|
||||
|
||||
static inline u8 scv_get_profile_in_use(void)
|
||||
{
|
||||
return pow_profile_index;
|
||||
}
|
||||
|
||||
static inline
|
||||
void scv_notification_reset(u16 start_index_recvd, u8 num_profiles_recvd)
|
||||
{
|
||||
/* Profiles recevied w/o notn. Nothing to do. */
|
||||
if (number_of_invalid_profiles == 0)
|
||||
return;
|
||||
|
||||
/* Most likely case. Got all requested profiles */
|
||||
if (PREDICT_TRUE(num_profiles_recvd == number_of_invalid_profiles &&
|
||||
start_index_recvd == invalid_profile_start_index))
|
||||
{
|
||||
number_of_invalid_profiles = 0;
|
||||
invalid_profile_start_index = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Received partial list */
|
||||
if (num_profiles_recvd < number_of_invalid_profiles)
|
||||
{
|
||||
ASSERT(start_index_recvd == invalid_profile_start_index);
|
||||
invalid_profile_start_index = (start_index_recvd + num_profiles_recvd)
|
||||
% scv_get_max_profiles();
|
||||
number_of_invalid_profiles -= num_profiles_recvd;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int __attribute__ ((weak)) scv_profile_renew(u8 * path_name,
|
||||
u8 start_index, u8 num_profiles);
|
||||
int __attribute__ ((weak)) scv_profile_refresh(u8 * path_name,
|
||||
u8 start_index, u8 num_profiles);
|
||||
|
||||
static inline u8 scv_is_decap(scv_profile * p)
|
||||
{
|
||||
return (p->validator == 1);
|
||||
}
|
||||
|
||||
static inline u16 scv_get_next_profile_id(vlib_main_t * vm, u16 id)
|
||||
{
|
||||
int next_id, num_profiles = 0;
|
||||
scv_profile *p;
|
||||
u8 max;
|
||||
|
||||
max = scv_get_max_profiles();
|
||||
|
||||
next_id = id;
|
||||
|
||||
/* Check for new profile in the ring buffer until a valid one. Exclude
|
||||
checking for the one already in use. */
|
||||
for (num_profiles = 0; num_profiles < max - 1; num_profiles++)
|
||||
{
|
||||
next_id = (next_id + 1) % max;
|
||||
p = scv_profile_find(next_id);
|
||||
if (p->validity != 0)
|
||||
{
|
||||
vlib_cli_output(vm, "Current id: %d, New id: %d\n", id, next_id);
|
||||
return (next_id);
|
||||
}
|
||||
}
|
||||
|
||||
return (id);
|
||||
}
|
||||
|
||||
static inline void
|
||||
scv_profile_invalidate(vlib_main_t * vm, ip6_hop_by_hop_ioam_main_t * hm,
|
||||
u16 id, u8 is_encap)
|
||||
{
|
||||
scv_profile *p = scv_profile_find(id);
|
||||
int rc;
|
||||
u8 max;
|
||||
f64 now = 0;
|
||||
|
||||
p->validity = 0;
|
||||
|
||||
/* If there are alredy profiles waiting. If so, use existing start_index.
|
||||
*/
|
||||
if (!number_of_invalid_profiles)
|
||||
invalid_profile_start_index = id;
|
||||
|
||||
max = scv_get_max_profiles();
|
||||
|
||||
/* Check whether the id is already included in existing list */
|
||||
if (!(id >= invalid_profile_start_index &&
|
||||
id <= (invalid_profile_start_index +
|
||||
number_of_invalid_profiles - 1) % max))
|
||||
{
|
||||
number_of_invalid_profiles++;
|
||||
}
|
||||
|
||||
if (number_of_invalid_profiles > scv_get_max_profiles())
|
||||
number_of_invalid_profiles = scv_get_max_profiles();
|
||||
|
||||
now = (f64) (((f64) hm->unix_time_0) +
|
||||
(vlib_time_now(hm->vlib_main) - hm->vlib_time_0));
|
||||
if (now <= next_time_to_send)
|
||||
return;
|
||||
|
||||
if (is_encap)
|
||||
{
|
||||
rc = scv_profile_renew(chain_path_name,
|
||||
(u8) invalid_profile_start_index, number_of_invalid_profiles);
|
||||
if (rc != 0)
|
||||
vlib_cli_output(vm,
|
||||
"Renew notification- id start:%d, num %d failed. rc: %d\n",
|
||||
invalid_profile_start_index, number_of_invalid_profiles, rc);
|
||||
else
|
||||
vlib_cli_output(vm,
|
||||
"Renew notification- id start:%d num %d sent. \n",
|
||||
invalid_profile_start_index, number_of_invalid_profiles);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Non encap node. Send refresh notification for now. Later set a
|
||||
timer and if there is no profile even after the timeout send
|
||||
refresh notification. */
|
||||
rc = scv_profile_refresh(chain_path_name,
|
||||
(u8) invalid_profile_start_index, number_of_invalid_profiles);
|
||||
if (rc != 0)
|
||||
vlib_cli_output(vm,
|
||||
"Refresh notification- id start:%d, num %d failed. rc: %d\n",
|
||||
invalid_profile_start_index, number_of_invalid_profiles, rc);
|
||||
else
|
||||
vlib_cli_output(vm,
|
||||
"Refresh notification- id start:%d num %d sent. \n",
|
||||
invalid_profile_start_index, number_of_invalid_profiles);
|
||||
}
|
||||
next_time_to_send = now + time_exponent;
|
||||
time_exponent <<= 1; /* backoff time is power of 2 seconds */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user