VPP-76:APIs for Proof of transit feature added to iOAM 73/1573/5
authorShwetha <shwethab@cisco.com>
Wed, 15 Jun 2016 15:34:16 +0000 (16:34 +0100)
committerOle Trøan <ot@cisco.com>
Fri, 17 Jun 2016 09:43:40 +0000 (09:43 +0000)
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>
16 files changed:
plugins/Makefile.am
plugins/plugins/ioam/encap/ip6_ioam_pot.c [new file with mode: 0644]
plugins/plugins/ioam/lib-pot/math64.h [moved from vnet/vnet/lib-scv/math64.h with 98% similarity]
plugins/plugins/ioam/lib-pot/pot.api [new file with mode: 0644]
plugins/plugins/ioam/lib-pot/pot_all_api_h.h [new file with mode: 0644]
plugins/plugins/ioam/lib-pot/pot_api.c [new file with mode: 0644]
plugins/plugins/ioam/lib-pot/pot_msg_enum.h [new file with mode: 0644]
plugins/plugins/ioam/lib-pot/pot_test.c [new file with mode: 0644]
plugins/plugins/ioam/lib-pot/pot_util.c [new file with mode: 0644]
plugins/plugins/ioam/lib-pot/pot_util.h [new file with mode: 0644]
vnet/Makefile.am
vnet/vnet/ip/ip6_hop_by_hop.c
vnet/vnet/ip/ip6_hop_by_hop.h
vnet/vnet/ip/ip6_hop_by_hop_packet.h
vnet/vnet/lib-scv/scv_util.c [deleted file]
vnet/vnet/lib-scv/scv_util.h [deleted file]

index e72b863..fee7493 100644 (file)
@@ -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
diff --git a/plugins/plugins/ioam/encap/ip6_ioam_pot.c b/plugins/plugins/ioam/encap/ip6_ioam_pot.c
new file mode 100644 (file)
index 0000000..e90a664
--- /dev/null
@@ -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);
+
+
similarity index 98%
rename from vnet/vnet/lib-scv/math64.h
rename to plugins/plugins/ioam/lib-pot/math64.h
index 9ee6e43..4c608a3 100644 (file)
@@ -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:
diff --git a/plugins/plugins/ioam/lib-pot/pot.api b/plugins/plugins/ioam/lib-pot/pot.api
new file mode 100644 (file)
index 0000000..7fd06b5
--- /dev/null
@@ -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;
+};
diff --git a/plugins/plugins/ioam/lib-pot/pot_all_api_h.h b/plugins/plugins/ioam/lib-pot/pot_all_api_h.h
new file mode 100644 (file)
index 0000000..574b897
--- /dev/null
@@ -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>
diff --git a/plugins/plugins/ioam/lib-pot/pot_api.c b/plugins/plugins/ioam/lib-pot/pot_api.c
new file mode 100644 (file)
index 0000000..6566263
--- /dev/null
@@ -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);
diff --git a/plugins/plugins/ioam/lib-pot/pot_msg_enum.h b/plugins/plugins/ioam/lib-pot/pot_msg_enum.h
new file mode 100644 (file)
index 0000000..bcd7159
--- /dev/null
@@ -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 */
diff --git a/plugins/plugins/ioam/lib-pot/pot_test.c b/plugins/plugins/ioam/lib-pot/pot_test.c
new file mode 100644 (file)
index 0000000..706be44
--- /dev/null
@@ -0,0 +1,313 @@
+/*
+ * 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_test.c - test harness for pot plugin
+ *------------------------------------------------------------------
+ */
+
+#include <vat/vat.h>
+#include <vlibapi/api.h>
+#include <vlibmemory/api.h>
+#include <vlibsocket/api.h>
+#include <vppinfra/error.h>
+
+/* Declare 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
+
+/* declare message handlers for each api */
+
+#define vl_endianfun             /* define message structures */
+#include <lib-pot/pot_all_api_h.h> 
+#undef vl_endianfun
+
+/* instantiate all the print functions we know about */
+#define vl_print(handle, ...)
+#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
+
+
+typedef struct {
+    /* API message ID base */
+    u16 msg_id_base;
+    vat_main_t *vat_main;
+} pot_test_main_t;
+
+pot_test_main_t pot_test_main;
+
+#define foreach_standard_reply_retval_handler     \
+_(pot_profile_add_reply)                          \
+_(pot_profile_activate_reply)                     \
+_(pot_profile_del_reply)
+
+#define _(n)                                            \
+    static void vl_api_##n##_t_handler                  \
+    (vl_api_##n##_t * mp)                               \
+    {                                                   \
+        vat_main_t * vam = pot_test_main.vat_main;   \
+        i32 retval = ntohl(mp->retval);                 \
+        if (vam->async_mode) {                          \
+            vam->async_errors += (retval < 0);          \
+        } else {                                        \
+            vam->retval = retval;                       \
+            vam->result_ready = 1;                      \
+        }                                               \
+    }
+foreach_standard_reply_retval_handler;
+#undef _
+
+/* 
+ * Table of message reply handlers, must include boilerplate handlers
+ * we just generated
+ */
+#define foreach_vpe_api_reply_msg                                       \
+_(POT_PROFILE_ADD_REPLY, pot_profile_add_reply)                         \
+_(POT_PROFILE_ACTIVATE_REPLY, pot_profile_activate_reply)               \
+_(POT_PROFILE_DEL_REPLY, pot_profile_del_reply)                         \
+
+
+/* M: construct, but don't yet send a message */
+
+#define M(T,t)                                                  \
+do {                                                            \
+    vam->result_ready = 0;                                      \
+    mp = vl_msg_api_alloc(sizeof(*mp));                         \
+    memset (mp, 0, sizeof (*mp));                               \
+    mp->_vl_msg_id = ntohs (VL_API_##T + sm->msg_id_base);      \
+    mp->client_index = vam->my_client_index;                    \
+} while(0);
+
+#define M2(T,t,n)                                               \
+do {                                                            \
+    vam->result_ready = 0;                                      \
+    mp = vl_msg_api_alloc(sizeof(*mp)+(n));                     \
+    memset (mp, 0, sizeof (*mp));                               \
+    mp->_vl_msg_id = ntohs (VL_API_##T + sm->msg_id_base);      \
+    mp->client_index = vam->my_client_index;                    \
+} while(0);
+
+/* S: send a message */
+#define S (vl_msg_api_send_shmem (vam->vl_input_queue, (u8 *)&mp))
+
+/* W: wait for results, with timeout */
+#define W                                       \
+do {                                            \
+    timeout = vat_time_now (vam) + 1.0;         \
+                                                \
+    while (vat_time_now (vam) < timeout) {      \
+        if (vam->result_ready == 1) {           \
+            return (vam->retval);               \
+        }                                       \
+    }                                           \
+    return -99;                                 \
+} while(0);
+
+
+static int api_pot_profile_add (vat_main_t *vam)
+{
+#define MAX_BITS 64
+    pot_test_main_t * sm = &pot_test_main;
+    unformat_input_t *input = vam->input;
+    vl_api_pot_profile_add_t *mp;
+    u8 *name = NULL;
+    u64 prime = 0;
+    u64 secret_share = 0;
+    u64 secret_key = 0;
+    u32  bits = MAX_BITS;
+    u64 lpc = 0, poly2 = 0;
+    f64 timeout;
+    u8 id = 0;
+    int rv = 0;
+
+    while (unformat_check_input(input) != UNFORMAT_END_OF_INPUT)
+      {
+        if (unformat(input, "name %s", &name))
+         ;
+       else if(unformat(input, "id %d", &id))
+         ;
+        else if (unformat(input, "validator-key 0x%Lx", &secret_key))
+          ;
+        else if (unformat(input, "prime-number 0x%Lx", &prime))
+          ;
+        else if (unformat(input, "secret-share 0x%Lx", &secret_share))
+          ;
+        else if (unformat(input, "polynomial-public 0x%Lx", &poly2))
+          ;
+        else if (unformat(input, "lpc 0x%Lx", &lpc))
+          ;
+        else if (unformat(input, "bits-in-random %u", &bits))
+         {
+           if (bits > MAX_BITS)
+             bits = MAX_BITS;
+         }
+        else
+       break;
+      }
+
+    if (!name)
+      {
+        errmsg ("name required\n");
+        rv = -99;
+        goto OUT;
+      }
+    
+    M2(POT_PROFILE_ADD, pot_profile_add, vec_len(name));
+
+    mp->list_name_len = vec_len(name);
+    clib_memcpy(mp->list_name, name, mp->list_name_len);
+    mp->secret_share = clib_host_to_net_u64(secret_share);
+    mp->polynomial_public = clib_host_to_net_u64(poly2);
+    mp->lpc = clib_host_to_net_u64(lpc);
+    mp->prime = clib_host_to_net_u64(prime);
+    if (secret_key != 0)
+      {
+        mp->secret_key = clib_host_to_net_u64(secret_key);
+        mp->validator = 1;
+      }
+    else
+      {
+       mp->validator = 0;
+      }
+    mp->id = id;
+    mp->max_bits = bits;
+      
+    S; W;
+  
+OUT:
+    vec_free(name);
+    return(rv);
+}
+
+static int api_pot_profile_activate (vat_main_t *vam)
+{
+#define MAX_BITS 64
+    pot_test_main_t * sm = &pot_test_main;  
+    unformat_input_t *input = vam->input;
+    vl_api_pot_profile_activate_t *mp;
+    u8 *name = NULL;
+    u8 id = 0;
+    int rv = 0;
+    f64 timeout;
+    
+    while (unformat_check_input(input) != UNFORMAT_END_OF_INPUT)
+      {
+        if (unformat(input, "name %s", &name))
+         ;
+       else if(unformat(input, "id %d", &id))
+         ;
+        else
+       break;
+      }
+
+    if (!name)
+      {
+        errmsg ("name required\n");
+        rv = -99;
+        goto OUT;
+      }
+    
+    M2(POT_PROFILE_ACTIVATE, pot_profile_activate, vec_len(name));
+
+    mp->list_name_len = vec_len(name);
+    clib_memcpy(mp->list_name, name, mp->list_name_len);
+    mp->id = id;
+      
+    S; W;
+  
+OUT:
+    vec_free(name);
+    return(rv);
+}
+
+
+static int api_pot_profile_del (vat_main_t *vam)
+{
+    pot_test_main_t * sm = &pot_test_main;
+    vl_api_pot_profile_del_t *mp;
+    f64 timeout;
+   
+    M(POT_PROFILE_DEL, pot_profile_del);
+    mp->list_name_len = 0;
+    S; W;
+    return 0;
+}
+
+/* 
+ * List of messages that the api test plugin sends,
+ * and that the data plane plugin processes
+ */
+#define foreach_vpe_api_msg \
+_(pot_profile_add, "name <name> id [0-1] "                              \
+  "prime-number <0xu64> bits-in-random [0-64] "                         \
+  "secret-share <0xu64> lpc <0xu64> polynomial-public <0xu64> "         \
+  "[validator-key <0xu64>] [validity <0xu64>]")                         \
+_(pot_profile_activate, "name <name> id [0-1] ")                       \
+_(pot_profile_del, "[id <nn>]")                                         \
+
+
+void vat_api_hookup (vat_main_t *vam)
+{
+    pot_test_main_t * sm = &pot_test_main;
+    /* Hook up handlers for replies from the data plane plug-in */
+#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_vpe_api_reply_msg;
+#undef _
+
+    /* API messages we can send */
+#define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
+    foreach_vpe_api_msg;
+#undef _    
+    
+    /* Help strings */
+#define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
+    foreach_vpe_api_msg;
+#undef _
+}
+
+clib_error_t * vat_plugin_register (vat_main_t *vam)
+{
+  pot_test_main_t * sm = &pot_test_main;
+  u8 * name;
+
+  sm->vat_main = vam;
+
+  name = format (0, "pot_%08x%c", api_version, 0);
+  sm->msg_id_base = vl_client_get_first_plugin_msg_id ((char *) name);
+
+  if (sm->msg_id_base != (u16) ~0)
+    vat_api_hookup (vam);
+  
+  vec_free(name);
+  
+  return 0;
+}
diff --git a/plugins/plugins/ioam/lib-pot/pot_util.c b/plugins/plugins/ioam/lib-pot/pot_util.c
new file mode 100644 (file)
index 0000000..0309cbe
--- /dev/null
@@ -0,0 +1,446 @@
+/* 
+ * 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 <vnet/vnet.h>
+#include <stdint.h>
+#include <time.h>
+#include <string.h>
+#include <vppinfra/mem.h>
+#include "math64.h"
+#include "pot_util.h"
+
+pot_main_t pot_main;
+
+static void pot_profile_cleanup(pot_profile *profile);
+
+static void pot_main_profiles_reset (void)
+{
+    pot_main_t *sm = &pot_main;
+    int i = 0;
+
+    for (i = 0; i < MAX_POT_PROFILES; i++)
+    {
+      pot_profile_cleanup(&(sm->profile_list[i]));
+    }
+    sm->active_profile_id = 0;
+    if (sm->profile_list_name)
+       vec_free(sm->profile_list_name);
+    sm->profile_list_name = NULL;
+}
+
+int pot_util_init (void)
+{
+    pot_main_profiles_reset();
+    
+    return(0);
+}
+
+static void pot_profile_init(pot_profile * new, u8 id)
+{
+    if (new)
+    {
+        memset(new, 0, sizeof(pot_profile));
+        new->id = id;
+    }
+}
+
+pot_profile *pot_profile_find(u8 id)
+{
+    pot_main_t *sm = &pot_main;
+
+    if (id >= 0 && id < MAX_POT_PROFILES)
+    {
+        return (&(sm->profile_list[id]));
+    }
+    return (NULL);
+}
+static int pot_profile_name_equal (u8 *name0, u8 *name1)
+{
+    int len0, len1;
+
+    len0 = vec_len (name0);
+    len1 = vec_len (name1);
+    if (len0 != len1)
+        return(0);
+    return (0==strncmp ((char *) name0, (char *)name1, len0));
+}
+
+int pot_profile_list_is_enabled (u8 *name)
+{
+    pot_main_t *sm = &pot_main;
+    return (pot_profile_name_equal(sm->profile_list_name, name));
+}
+
+void pot_profile_list_init(u8 * profile_list_name)
+{
+    pot_main_t *sm = &pot_main;
+    int i = 0;
+
+    /* If it is the same profile list skip reset */
+    if (pot_profile_name_equal(sm->profile_list_name, profile_list_name))
+    {
+      return;
+    }
+
+    pot_main_profiles_reset();
+    if (vec_len(profile_list_name))
+      sm->profile_list_name = (u8 *)vec_dup(profile_list_name);
+    else
+      sm->profile_list_name = 0;
+    sm->active_profile_id = 0;
+    
+    for (i = 0; i < MAX_POT_PROFILES; i++)
+    {
+      pot_profile_init(&(sm->profile_list[i]), i);
+    }
+}
+
+static void pot_profile_cleanup(pot_profile * profile)
+{
+    u16 id = profile->id;
+
+    memset(profile, 0, sizeof(pot_profile));
+    profile->id = id;           /* Restore id alone */
+}
+
+int pot_profile_create(pot_profile * profile, u64 prime,
+    u64 poly2, u64 lpc, u64 secret_share)
+{
+    if (profile && !profile->in_use)
+    {
+        pot_profile_cleanup(profile);
+        profile->prime = prime;
+        profile->primeinv = 1.0 / prime;
+        profile->lpc = lpc;
+        profile->poly_pre_eval = poly2;
+        profile->secret_share = secret_share;
+       profile->total_pkts_using_this_profile = 0;
+        profile->valid = 1;
+       return(0);
+    }
+    
+    return(-1);
+}
+
+int pot_set_validator(pot_profile * profile, u64 key)
+{
+    if (profile && !profile->in_use)
+    {
+        profile->validator = 1;
+        profile->secret_key = key;
+       return(0);
+    }
+    return(-1);
+}
+
+always_inline u64 pot_update_cumulative_inline(u64 cumulative, u64 random,
+    u64 secret_share, u64 prime, u64 lpc, u64 pre_split, double prime_inv)
+{
+    u64 share_random = 0;
+    u64 cumulative_new = 0;
+
+    /* 
+     * calculate split share for random
+     */
+    share_random = add64_mod(pre_split, random, prime, prime_inv);
+
+    /* 
+     * lpc * (share_secret + share_random)
+     */
+    share_random = add64_mod(share_random, secret_share, prime, prime_inv);
+    share_random = mul64_mod(share_random, lpc, prime, prime_inv);
+
+    cumulative_new = add64_mod(cumulative, share_random, prime, prime_inv);
+
+    return (cumulative_new);
+}
+
+u64 pot_update_cumulative(pot_profile * profile, u64 cumulative, u64 random)
+{
+    if (profile && profile->valid != 0)
+    {
+        return (pot_update_cumulative_inline(cumulative, random, profile->secret_share,
+                profile->prime, profile->lpc, profile->poly_pre_eval,
+                profile->primeinv));
+    }
+    return (0);
+}
+
+always_inline u8 pot_validate_inline(u64 secret, u64 prime, double prime_inv,
+    u64 cumulative, u64 random)
+{
+    if (cumulative == (random + secret))
+    {
+        return (1);
+    }
+    else if (cumulative == add64_mod(random, secret, prime, prime_inv))
+    {
+        return (1);
+    }
+    return (0);
+}
+
+/* 
+ * return True if the cumulative matches secret from a profile
+ */
+u8 pot_validate(pot_profile * profile, u64 cumulative, u64 random)
+{
+    if (profile && profile->validator)
+    {
+        return (pot_validate_inline(profile->secret_key, profile->prime,
+                profile->primeinv, cumulative, random));
+    }
+    return (0);
+}
+
+/* 
+ * Utility function to get random number per pack
+ */
+u64 pot_generate_random(pot_profile * profile)
+{
+    u64 random = 0;
+    int32_t second_half;
+    static u32 seed = 0;
+
+    if (PREDICT_FALSE(!seed))
+        seed = random_default_seed();
+
+    /* 
+     * Upper 4 bytes seconds
+     */
+    random = (u64) time(NULL);
+
+    random &= 0xffffffff;
+    random = random << 32;
+    /* 
+     * Lower 4 bytes random number
+     */
+    second_half = random_u32(&seed);
+
+    random |= second_half;
+
+    if (PREDICT_TRUE(profile != NULL))
+    {
+        random &= profile->bit_mask;
+    }
+    return (random);
+}
+
+int pot_profile_set_bit_mask(pot_profile * profile, u16 bits)
+{
+    int sizeInBits;
+
+    if (profile && !profile->in_use)
+    {
+        sizeInBits = sizeof(profile->bit_mask) * 8;
+        profile->bit_mask =
+            (bits >=
+            sizeInBits ? (u64) - 1 : (u64) ((u64) 1 << (u64) bits) - 1);
+       return(0);
+    }
+    return(-1);
+}
+
+clib_error_t *clear_pot_profile_command_fn(vlib_main_t * vm,
+    unformat_input_t * input, vlib_cli_command_t * cmd)
+{
+
+    pot_main_profiles_reset();
+    
+    return 0;
+}
+
+void clear_pot_profiles()
+{
+    clear_pot_profile_command_fn(0, 0, 0);
+}
+
+VLIB_CLI_COMMAND(clear_pot_profile_command) =
+{
+.path = "clear pot profile",
+.short_help = "clear pot profile [<index>|all]",
+.function = clear_pot_profile_command_fn,
+};
+
+static clib_error_t *set_pot_profile_command_fn(vlib_main_t * vm,
+    unformat_input_t * input, vlib_cli_command_t * cmd)
+{
+    u64 prime;
+    u64 secret_share;
+    u64 secret_key;
+    u8 validator = 0;
+    u32 profile_id;
+    u32 bits;
+    u64 lpc = 0, poly2 = 0;
+    pot_profile *profile = NULL;
+    u8 *profile_list_name = NULL;
+    
+    bits = MAX_BITS;
+
+    while (unformat_check_input(input) != UNFORMAT_END_OF_INPUT)
+    {
+        if (unformat(input, "name %s",
+                    &profile_list_name));
+        else if (unformat(input, "id %d", &profile_id))
+            ;
+        else if (unformat(input, "validate-key 0x%Lx", &secret_key))
+            validator = 1;
+        else if (unformat(input, "prime-number 0x%Lx", &prime))
+            ;
+        else if (unformat(input, "secret_share 0x%Lx", &secret_share))
+            ;
+        else if (unformat(input, "polynomial2 0x%Lx", &poly2))
+            ;
+        else if (unformat(input, "lpc 0x%Lx", &lpc))
+            ;
+        else if (unformat(input, "bits-in-random %d", &bits))
+        {
+            if (bits > MAX_BITS)
+                bits = MAX_BITS;
+        }
+        else
+            return clib_error_return(0, "unknown input `%U'",
+                format_unformat_error, input);
+    }
+    if (profile_list_name == 0)
+    {
+        return clib_error_return(0, "Name cannot be null");
+    }  
+    pot_profile_list_init(profile_list_name);
+    profile = pot_profile_find(profile_id);
+
+    if (profile)
+    {
+        pot_profile_create(profile, prime, poly2, lpc, secret_share);
+        if (validator)
+            pot_set_validator(profile, secret_key);
+        pot_profile_set_bit_mask(profile, bits);
+    }
+    vec_free(profile_list_name);
+    return 0;
+}
+
+VLIB_CLI_COMMAND(set_pot_profile_command) =
+{
+.path = "set pot profile",
+.short_help = "set pot profile name <string> id [0-1] [validator-key 0xu64] \
+                  prime-number 0xu64 secret_share 0xu64 lpc 0xu64 \
+                  polynomial2 0xu64 bits-in-random [0-64] ",
+.function = set_pot_profile_command_fn,
+};
+
+static clib_error_t *set_pot_profile_activate_command_fn(vlib_main_t * vm,
+    unformat_input_t * input, vlib_cli_command_t * cmd)
+{
+    pot_main_t *sm = &pot_main;
+    u8 *profile_list_name = NULL;
+    u32 id = 0;
+    clib_error_t *result = NULL;
+    
+    while (unformat_check_input(input) != UNFORMAT_END_OF_INPUT)
+    {
+        if (unformat(input, "name %s",
+                    &profile_list_name));
+        else if (unformat(input, "id %d", &id))
+            ;
+        else
+            return clib_error_return(0, "unknown input `%U'",
+                format_unformat_error, input);
+    }
+    if (profile_list_name == 0)
+    {
+        return clib_error_return(0, "Name cannot be null");
+    }
+
+    if (!pot_profile_list_is_enabled(profile_list_name)) {
+        result = clib_error_return(0, "%s list is not enabled, profile in use %s",
+                                profile_list_name, sm->profile_list_name);
+    } else if (0 != pot_profile_set_active((u8)id)) {
+        result = clib_error_return(0, "Profile %d not defined in %s",
+                                id, sm->profile_list_name);
+    }
+    vec_free(profile_list_name);
+    return result;
+}
+
+VLIB_CLI_COMMAND(set_pot_profile_activate_command) =
+{
+.path = "set pot profile-active",
+.short_help = "set pot profile-active name <string> id [0-1]",
+.function = set_pot_profile_activate_command_fn,
+};
+
+static clib_error_t *show_pot_profile_command_fn(vlib_main_t * vm,
+    unformat_input_t * input, vlib_cli_command_t * cmd)
+{
+    pot_main_t *sm = &pot_main;
+    pot_profile *p = NULL;
+    u16 i;
+    u8 *s = 0;
+
+    if (vec_len(sm->profile_list_name) == 0)
+    {
+        s = format(s, "POT Profiles not configured\n");
+        vlib_cli_output(vm, "%v", s);
+        return 0;
+    }
+    s = format(s, "Profile list in use  : %s\n",sm->profile_list_name);
+    for (i = 0; i < MAX_POT_PROFILES; i++)
+    {
+        p = pot_profile_find(i);
+        if (p->valid == 0)
+            continue;
+        s = format(s, "POT Profile at index: %d\n", i);
+        s = format(s, "                 Id : %d\n", p->id);
+        s = format(s, "          Validator : %s (%d)\n",
+            (p->validator) ? "True" : "False", p->validator);
+        if (p->validator == 1)
+            s = format(s, "         Secret key : 0x%Lx (%Ld)\n",
+                p->secret_key, p->secret_key);
+        s = format(s, "       Secret share : 0x%Lx (%Ld)\n",
+            p->secret_share, p->secret_share);
+        s = format(s, "       Prime number : 0x%Lx (%Ld)\n",
+            p->prime, p->prime);
+        s = format(s, "2nd polynomial(eval) : 0x%Lx (%Ld)\n",
+            p->poly_pre_eval, p->poly_pre_eval);
+        s = format(s, "                 LPC : 0x%Lx (%Ld)\n", p->lpc, p->lpc);
+
+        s = format(s, "           Bit mask : 0x%Lx (%Ld)\n",
+            p->bit_mask, p->bit_mask);
+    }
+
+    p = pot_profile_find(sm->active_profile_id);
+
+    if (p && p->valid && p->in_use) {
+        s = format(s, "\nProfile index in use: %d\n", sm->active_profile_id);
+        s = format(s, "Pkts passed : 0x%Lx (%Ld)\n",
+                  p->total_pkts_using_this_profile,
+                  p->total_pkts_using_this_profile);
+        if (pot_is_decap(p))
+            s = format(s, "  This is Decap node.  \n");
+    } else {
+        s = format(s, "\nProfile index in use: None\n");
+    }
+    vlib_cli_output(vm, "%v", s);
+    vec_free(s);
+
+    return 0;
+}
+
+VLIB_CLI_COMMAND(show_pot_profile_command) =
+{
+.path = "show pot profile",
+.short_help = "show pot profile",
+.function = show_pot_profile_command_fn,
+};
diff --git a/plugins/plugins/ioam/lib-pot/pot_util.h b/plugins/plugins/ioam/lib-pot/pot_util.h
new file mode 100644 (file)
index 0000000..9df31fa
--- /dev/null
@@ -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
index b758c7f..61a1998 100644 (file)
@@ -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 = 
index df0dae5..f6e10f0 100644 (file)
@@ -25,8 +25,6 @@
 
 #include <vnet/ip/ip6_hop_by_hop.h>
 
-#include <vnet/lib-scv/scv_util.h>
-
 /* Timestamp precision multipliers for seconds, milliseconds, microseconds
  * and nanoseconds respectively.
  */
@@ -115,22 +113,6 @@ static u8 * format_ioam_data_list_element (u8 * s, va_list * args)
   return s;
 }
 
-static u8 * format_ioam_pow (u8 * s, va_list * args)
-{
-  ioam_pow_option_t * pow0 = va_arg (*args, ioam_pow_option_t *);
-  u64 random, cumulative;
-  random = cumulative = 0;
-  if (pow0) 
-    { 
-      random = clib_net_to_host_u64 (pow0->random);
-      cumulative = clib_net_to_host_u64 (pow0->cumulative);
-    }
-
-  s = format (s, "random = 0x%Lx, Cumulative = 0x%Lx, Index = 0x%x", 
-             random, cumulative, pow0->reserved_profile_id);
-  return s;
-}
-
 u8 *
 ip6_hbh_ioam_trace_data_list_trace_handler (u8 *s, ip6_hop_by_hop_option_t *opt)
 {
@@ -158,17 +140,6 @@ ip6_hbh_ioam_trace_data_list_trace_handler (u8 *s, ip6_hop_by_hop_option_t *opt)
   return (s);
 }
 
-u8 *
-ip6_hbh_ioam_proof_of_work_trace_handler (u8 *s, ip6_hop_by_hop_option_t *opt)
-{
-  ioam_pow_option_t *pow;
-
-  s = format (s, "    POW opt present\n");
-  pow = (ioam_pow_option_t *) opt;
-  s = format (s, "         %U\n", format_ioam_pow, pow);
-  return (s);
-}
-
 int
 ip6_hbh_ioam_trace_data_list_handler (vlib_buffer_t *b, ip6_header_t *ip, ip6_hop_by_hop_option_t *opt)
 {
@@ -221,76 +192,42 @@ ip6_hbh_ioam_trace_data_list_handler (vlib_buffer_t *b, ip6_header_t *ip, ip6_ho
   return (rv);
 }
 
+/* The main h-b-h tracer will be invoked, no need to do much here */
 int
-ip6_hbh_ioam_proof_of_work_handler (vlib_buffer_t *b, ip6_header_t *ip, ip6_hop_by_hop_option_t *opt)
+ip6_hbh_add_register_option (u8 option,
+                            u8 size,
+                            int rewrite_options(u8 *rewrite_string, u8 rewrite_size))
 {
   ip6_hop_by_hop_ioam_main_t * hm = &ip6_hop_by_hop_ioam_main;
-  ioam_pow_option_t * pow;
-  u64 random = 0, cumulative = 0;
-  int rv = 0;
 
-  pow_profile = scv_profile_find(pow_profile_index);
-  if (PREDICT_FALSE(!pow_profile)) {
+  ASSERT (option < ARRAY_LEN (hm->add_options));
+
+  /* Already registered */
+  if (hm->add_options[option])
     return (-1);
-  }
 
-  pow = (ioam_pow_option_t *) opt;
-
-  u8 pow_encap = (pow->random == 0);
-  if (pow_encap) {
-    if (PREDICT_FALSE(total_pkts_using_this_profile >= pow_profile->validity)) {
-      /* Choose a new profile */
-      u16 new_profile_index;
-      new_profile_index = scv_get_next_profile_id(hm->vlib_main, pow_profile_index);
-      if (new_profile_index != pow_profile_index) {
-       /* Got a new profile */
-       scv_profile_invalidate(hm->vlib_main, hm,
-                              pow_profile_index,
-                              pow_encap);
-       pow_profile_index = new_profile_index;
-       pow_profile = scv_profile_find(pow_profile_index);
-       total_pkts_using_this_profile = 0;
-      } else {
-       scv_profile_invalidate(hm->vlib_main, hm, pow_profile_index, pow_encap);
-      }
-    }
-    pow->reserved_profile_id = pow_profile_index & PROFILE_ID_MASK;
-    total_pkts_using_this_profile++;
-  } else { /* Non encap node */
-    if (PREDICT_FALSE(pow->reserved_profile_id != pow_profile_index)) {
-      /* New profile announced by encap node. */
-      scv_profile *new_profile = 0;
-      new_profile = scv_profile_find(pow->reserved_profile_id);
-      if (PREDICT_FALSE(new_profile == 0 || new_profile->validity == 0)) {
-       /* Profile is invalid. Use old profile*/
-       rv = -1;
-       scv_profile_invalidate(hm->vlib_main, hm,
-                              pow->reserved_profile_id,
-                              pow_encap);
-      } else {
-       scv_profile_invalidate(hm->vlib_main, hm,
-                              pow_profile_index,
-                              pow_encap);
-       pow_profile_index = pow->reserved_profile_id;
-       pow_profile = new_profile;
-       total_pkts_using_this_profile = 0;
-      }
-    }
-    total_pkts_using_this_profile++;
-  }
+  hm->add_options[option] = rewrite_options;
+  hm->options_size[option] = size;
+  
+  return (0);
+}
 
-  if (pow->random == 0) {
-    pow->random = clib_host_to_net_u64(scv_generate_random(pow_profile));
-    pow->cumulative = 0;
-  }
-  random = clib_net_to_host_u64(pow->random);
-  cumulative = clib_net_to_host_u64(pow->cumulative);
-  pow->cumulative = clib_host_to_net_u64(scv_update_cumulative(pow_profile, cumulative, random));
+int
+ip6_hbh_add_unregister_option (u8 option)
+{
+  ip6_hop_by_hop_ioam_main_t * hm = &ip6_hop_by_hop_ioam_main;
 
-  return (rv);
+  ASSERT (option < ARRAY_LEN (hm->add_options));
+
+  /* Not registered */
+  if (!hm->add_options[option])
+    return (-1);
+
+  hm->add_options[option] = NULL;
+  hm->options_size[option] = 0;
+  return (0);
 }
 
-/* The main h-b-h tracer will be invoked, no need to do much here */
 typedef struct {
   u32 next_index;
 } ip6_add_hop_by_hop_trace_t;
@@ -530,13 +467,44 @@ static u8 * format_ip6_pop_hop_by_hop_trace (u8 * s, va_list * args)
   return s;
 }
 
+int
+ip6_hbh_pop_register_option (u8 option,
+                            int options(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;
+
+  ASSERT (option < ARRAY_LEN (hm->pop_options));
+
+  /* Already registered */
+  if (hm->pop_options[option])
+    return (-1);
+
+  hm->pop_options[option] = options;
+
+  return (0);
+}
+
+int
+ip6_hbh_pop_unregister_option (u8 option)
+{
+  ip6_hop_by_hop_ioam_main_t * hm = &ip6_hop_by_hop_ioam_main;
+
+  ASSERT (option < ARRAY_LEN (hm->pop_options));
+
+  /* Not registered */
+  if (!hm->pop_options[option])
+    return (-1);
+
+  hm->pop_options[option] = NULL;
+  return (0);
+}
+
 vlib_node_registration_t ip6_pop_hop_by_hop_node;
 
 #define foreach_ip6_pop_hop_by_hop_error                \
 _(PROCESSED, "Pkts w/ removed ip6 hop-by-hop options")  \
-_(NO_HOHO, "Pkts w/ no ip6 hop-by-hop options") \
-_(SCV_PASSED, "Pkts with SCV in Policy") \
-_(SCV_FAILED, "Pkts with SCV out of Policy") 
+_(NO_HOHO, "Pkts w/ no ip6 hop-by-hop options")         \
+_(OPTION_FAILED, "ip6 pop hop-by-hop failed to process")
 
 typedef enum {
 #define _(sym,str) IP6_POP_HOP_BY_HOP_ERROR_##sym,
@@ -551,16 +519,13 @@ static char * ip6_pop_hop_by_hop_error_strings[] = {
 #undef _
 };
 
-static inline void ioam_end_of_path_validation (vlib_main_t * vm,
+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_ioam_main_t * hm = &ip6_hop_by_hop_ioam_main;
   ip6_hop_by_hop_option_t *opt0, *limit0;
-  ioam_pow_option_t * pow0;
   u8 type0;
-  u64 final_cumulative = 0;
-  u64 random = 0;
-  u8 result = 0;
 
   if (!hbh0 || !ip0) return;
 
@@ -573,64 +538,37 @@ static inline void ioam_end_of_path_validation (vlib_main_t * vm,
     {
       type0 = opt0->type;
       switch (type0)
-        {
-        case HBH_OPTION_TYPE_IOAM_EDGE_TO_EDGE:
-        case HBH_OPTION_TYPE_IOAM_TRACE_DATA_LIST:
-          opt0 = (ip6_hop_by_hop_option_t *)
-            (((u8 *)opt0) + opt0->length
-             + sizeof (ip6_hop_by_hop_option_t));
-          break;
-        case HBH_OPTION_TYPE_IOAM_PROOF_OF_WORK:
-          pow0 = (ioam_pow_option_t *) opt0;
-          random = clib_net_to_host_u64(pow0->random);
-          final_cumulative = clib_net_to_host_u64(pow0->cumulative);
-          result =  scv_validate (pow_profile,
-                                       final_cumulative, random);
-         
-          if (result == 1) 
-            {
-              vlib_node_increment_counter (vm, ip6_pop_hop_by_hop_node.index,
-                                        IP6_POP_HOP_BY_HOP_ERROR_SCV_PASSED, result);
-            }
-          else 
-            {
-             vlib_node_increment_counter (vm, ip6_pop_hop_by_hop_node.index,
-                                        IP6_POP_HOP_BY_HOP_ERROR_SCV_FAILED, 1);
-            }
-         /* TODO: notify the scv failure*/
-          opt0 = (ip6_hop_by_hop_option_t *)
-            (((u8 *)opt0) + sizeof (ioam_pow_option_t));
-          break;
-
-        case 0: /* Pad */
-          opt0 = (ip6_hop_by_hop_option_t *) ((u8 *)opt0) + 1;
-          break;
-
-        default:
-           format(0, "Something is wrong\n"); 
-           break;
-        }
+       {
+       case 0: /* Pad1 */
+         opt0 = (ip6_hop_by_hop_option_t *) ((u8 *)opt0) + 1;
+         continue;
+       case 1: /* PadN */
+         break;
+       default:
+         if (hm->pop_options[type0])
+           {
+             if ((*hm->pop_options[type0])(ip0, opt0) < 0)
+             {
+               vlib_node_increment_counter (vm, ip6_pop_hop_by_hop_node.index, 
+                               IP6_POP_HOP_BY_HOP_ERROR_OPTION_FAILED, 1);
+             }
+           }
+       }
+       opt0 = (ip6_hop_by_hop_option_t *) (((u8 *)opt0) + opt0->length + sizeof (ip6_hop_by_hop_option_t));
     }
 }
 
-
 static uword
 ip6_pop_hop_by_hop_node_fn (vlib_main_t * vm,
                  vlib_node_runtime_t * node,
                  vlib_frame_t * frame)
 {
-  ip6_hop_by_hop_ioam_main_t * hm = &ip6_hop_by_hop_ioam_main;
   ip6_main_t * im = &ip6_main;
   ip_lookup_main_t * lm = &im->lookup_main;
   u32 n_left_from, * from, * to_next;
   ip_lookup_next_t next_index;
   u32 processed = 0;
   u32 no_header = 0;
-  u32 (*ioam_end_of_path_cb) (vlib_main_t *, vlib_node_runtime_t *,
-                              vlib_buffer_t *, ip6_header_t *, 
-                              ip_adjacency_t *);
-  
-  ioam_end_of_path_cb = hm->ioam_end_of_path_cb;
   
   from = vlib_frame_vector_args (frame);
   n_left_from = frame->n_vectors;
@@ -748,11 +686,8 @@ ip6_pop_hop_by_hop_node_fn (vlib_main_t * vm,
           /* Perfectly normal to end up here w/ out h-b-h header */
          hbh0 = (ip6_hop_by_hop_header_t *)(ip0+1);
           
-         /* Collect data from trace via callback */
-         next0 = ioam_end_of_path_cb ? ioam_end_of_path_cb (vm, node, b0, ip0, adj0) : next0;
-
          /* TODO:Temporarily doing it here.. do this validation in end_of_path_cb */
-         ioam_end_of_path_validation(vm, ip0, hbh0);
+         ioam_pop_hop_by_hop_processing(vm, ip0, hbh0);
          /* Pop the trace data */
          vlib_buffer_advance (b0, (hbh0->length+1)<<3);
          new_l0 = clib_net_to_host_u16 (ip0->payload_length) -
@@ -820,6 +755,9 @@ ip6_hop_by_hop_ioam_init (vlib_main_t * vm)
   hm->vlib_time_0 = vlib_time_now (vm);
   hm->ioam_flag = IOAM_HBYH_MOD;
   hm->trace_tsp = TSP_MICROSECONDS; /* Micro seconds */
+  memset(hm->add_options, 0, sizeof(hm->add_options));
+  memset(hm->pop_options, 0, sizeof(hm->pop_options));
+  memset(hm->options_size, 0, sizeof(hm->options_size));
 
   /*
    * Register the handlers
@@ -828,9 +766,6 @@ ip6_hop_by_hop_ioam_init (vlib_main_t * vm)
   if (ip6_hbh_register_option(HBH_OPTION_TYPE_IOAM_TRACE_DATA_LIST, ip6_hbh_ioam_trace_data_list_handler,
                              ip6_hbh_ioam_trace_data_list_trace_handler) < 0)
     return (clib_error_create("registration of HBH_OPTION_TYPE_IOAM_TRACE_DATA_LIST failed"));
-  if (ip6_hbh_register_option(HBH_OPTION_TYPE_IOAM_PROOF_OF_WORK, ip6_hbh_ioam_proof_of_work_handler,
-                             ip6_hbh_ioam_proof_of_work_trace_handler) < 0)
-    return (clib_error_create("registration of HBH_OPTION_TYPE_IOAM_PROOF_OF_WORK failed"));
 
   return (0);
 }
@@ -838,19 +773,19 @@ ip6_hop_by_hop_ioam_init (vlib_main_t * vm)
 VLIB_INIT_FUNCTION (ip6_hop_by_hop_ioam_init);
 
 int ip6_ioam_set_rewrite (u8 **rwp, u32 trace_type, u32 trace_option_elts, 
-                          int has_pow_option, int has_ppc_option)
+                          int has_pot_option, int has_ppc_option)
 {
+  ip6_hop_by_hop_ioam_main_t * hm = &ip6_hop_by_hop_ioam_main;  
   u8 *rewrite = 0;
   u32 size, rnd_size;
   ip6_hop_by_hop_header_t *hbh;
   ioam_trace_option_t * trace_option;
-  ioam_pow_option_t * pow_option;
   u8 *current;
   u8 trace_data_size = 0;  
 
   vec_free (*rwp);
 
-  if (trace_option_elts == 0 && has_pow_option == 0)
+  if (trace_option_elts == 0 && has_pot_option == 0)
     return -1;
 
   /* Work out how much space we need */
@@ -869,10 +804,10 @@ int ip6_ioam_set_rewrite (u8 **rwp, u32 trace_type, u32 trace_option_elts,
   
       size += trace_option_elts * trace_data_size;
     }
-  if (has_pow_option)
+  if (has_pot_option && hm->add_options[HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT] != 0)
     {
       size += sizeof (ip6_hop_by_hop_option_t);
-      size += sizeof (ioam_pow_option_t);
+      size += hm->options_size[HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT];
     }
 
   /* Round to a multiple of 8 octets */
@@ -899,14 +834,11 @@ int ip6_ioam_set_rewrite (u8 **rwp, u32 trace_type, u32 trace_option_elts,
       current += sizeof (ioam_trace_option_t) + 
         trace_option_elts * trace_data_size;
     }
-  if (has_pow_option)
+  if (has_pot_option && hm->add_options[HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT] != 0)
     {
-      pow_option = (ioam_pow_option_t *)current;
-      pow_option->hdr.type = HBH_OPTION_TYPE_IOAM_PROOF_OF_WORK
-        | HBH_OPTION_TYPE_DATA_CHANGE_ENROUTE;
-      pow_option->hdr.length = sizeof (ioam_pow_option_t) - 
-        sizeof (ip6_hop_by_hop_option_t);
-      current += sizeof (ioam_pow_option_t);
+      if (0 == hm->add_options[HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT](current,
+                                       hm->options_size[HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT]))
+         current += sizeof (hm->options_size[HBH_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT]);
     }
   
   *rwp = rewrite;
@@ -924,7 +856,7 @@ clear_ioam_rewrite_fn(void)
   hm->app_data = 0;
   hm->trace_type = 0;
   hm->trace_option_elts = 0;
-  hm->has_pow_option = 0;
+  hm->has_pot_option = 0;
   hm->has_ppc_option = 0;
   hm->trace_tsp = TSP_MICROSECONDS; 
 
@@ -946,13 +878,13 @@ VLIB_CLI_COMMAND (ip6_clear_ioam_trace_cmd, static) = {
 
 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_ppc_option)
 {
   int rv;
   ip6_hop_by_hop_ioam_main_t *hm = &ip6_hop_by_hop_ioam_main;
   rv = ip6_ioam_set_rewrite (&hm->rewrite, trace_type, trace_option_elts,
-                             has_pow_option, has_ppc_option);
+                             has_pot_option, has_ppc_option);
 
   switch (rv)
     {
@@ -961,7 +893,7 @@ ip6_ioam_trace_profile_set(u32 trace_option_elts, u32 trace_type, u32 node_id,
       hm->app_data = app_data;
       hm->trace_type = trace_type;
       hm->trace_option_elts = trace_option_elts;
-      hm->has_pow_option = has_pow_option;
+      hm->has_pot_option = has_pot_option;
       hm->has_ppc_option = has_ppc_option;
       hm->trace_tsp = trace_tsp;
       break;
@@ -982,7 +914,7 @@ ip6_set_ioam_rewrite_command_fn (vlib_main_t * vm,
   u32 trace_option_elts = 0;
   u32 trace_type = 0, node_id = 0; 
   u32 app_data = 0, trace_tsp = TSP_MICROSECONDS;
-  int has_pow_option = 0;
+  int has_pot_option = 0;
   int has_ppc_option = 0;
   clib_error_t * rv = 0;
   
@@ -993,8 +925,8 @@ ip6_set_ioam_rewrite_command_fn (vlib_main_t * vm,
                       &trace_type, &trace_option_elts, &trace_tsp,
                       &node_id, &app_data))
             ;
-      else if (unformat (input, "pow"))
-        has_pow_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"))
@@ -1007,7 +939,7 @@ ip6_set_ioam_rewrite_command_fn (vlib_main_t * vm,
   
     
     rv = ip6_ioam_trace_profile_set(trace_option_elts, trace_type, node_id,
-                           app_data, has_pow_option, trace_tsp, has_ppc_option);
+                           app_data, has_pot_option, trace_tsp, has_ppc_option);
 
     return rv;
 }
@@ -1015,7 +947,7 @@ ip6_set_ioam_rewrite_command_fn (vlib_main_t * vm,
 
 VLIB_CLI_COMMAND (ip6_set_ioam_rewrite_cmd, static) = {
   .path = "set ioam rewrite",
-  .short_help = "set ioam rewrite trace-type <0x1f|0x3|0x9|0x11|0x19> trace-elts <nn> trace-tsp <0|1|2|3> node-id <node id in hex> app-data <app_data in hex> [pow] [ppc <encap|decap>]",
+  .short_help = "set ioam rewrite trace-type <0x1f|0x3|0x9|0x11|0x19> trace-elts <nn> trace-tsp <0|1|2|3> node-id <node id in hex> app-data <app_data in hex> [pot] [ppc <encap|decap>]",
   .function = ip6_set_ioam_rewrite_command_fn,
 };
   
@@ -1063,10 +995,10 @@ ip6_show_ioam_summary_cmd_fn (vlib_main_t * vm,
   s = format(s, " HOP BY HOP OPTIONS - TRACE CONFIG - Not configured\n");
   }
 
-  s = format(s, "                        POW OPTION - %d (%s)\n", 
-          hm->has_pow_option, (hm->has_pow_option?"Enabled":"Disabled"));
-  if (hm->has_pow_option)
-    s = format(s, "Try 'show ioam sc-profile' for more information\n");
+  s = format(s, "                        POT OPTION - %d (%s)\n", 
+          hm->has_pot_option, (hm->has_pot_option?"Enabled":"Disabled"));
+  if (hm->has_pot_option)
+    s = 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]);
index 50a14a9..0ee24b3 100644 (file)
@@ -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__ */
index 708275a..0a2c3d0 100644 (file)
@@ -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;
diff --git a/vnet/vnet/lib-scv/scv_util.c b/vnet/vnet/lib-scv/scv_util.c
deleted file mode 100644 (file)
index e69c883..0000000
+++ /dev/null
@@ -1,486 +0,0 @@
-/* 
- * 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.
- */
-#include <vnet/vnet.h>
-#include <stdint.h>
-#include <time.h>
-#include <string.h>
-#include <vppinfra/mem.h>
-#include "math64.h"
-#include "scv_util.h"
-
-scv_profile *pow_profile = NULL;
-u16 pow_profile_index = 0;
-u64 total_pkts_using_this_profile = 0;
-u8 chain_path_name[PATH_NAME_SIZE];
-scv_profile profile_list[MAX_SERVICE_PROFILES];
-u8 max_profiles = 0;
-u16 invalid_profile_start_index = 0;
-u8 number_of_invalid_profiles = 0;
-f64 next_time_to_send = 0;
-u32 time_exponent = 1;
-vlib_main_t *gvm = 0;
-
-static void scv_profile_init(scv_profile * new, u16 id)
-{
-    if (new)
-    {
-        memset(new, 0, sizeof(scv_profile));
-        new->id = id;
-    }
-}
-
-/* 
- * Get maximum number of profiles configured for this chain.
- */
-u8 scv_get_max_profiles(void)
-{
-    return max_profiles;
-}
-
-scv_profile *scv_profile_find(u16 id)
-{
-    u8 max = scv_get_max_profiles();
-
-    if (id >= 0 && id < max)
-    {
-        return (&profile_list[id]);
-    }
-    return (NULL);
-}
-
-u8 sc_init_done = 0;
-void scv_init(u8 * path_name, u8 max, u8 indx)
-{
-    int i = 0;
-
-    if (sc_init_done)
-    {
-        return;
-    }
-    memcpy(chain_path_name, path_name, strlen((const char *)path_name) + 1);
-    max_profiles = max;
-    pow_profile_index = indx;
-
-    for (i = 0; i < max_profiles; i++)
-    {
-        scv_profile_init(&profile_list[i], i);
-    }
-
-    sc_init_done = 1;
-}
-
-void scv_profile_cleanup(scv_profile * profile)
-{
-    u16 id = profile->id;
-
-    memset(profile, 0, sizeof(scv_profile));
-    profile->id = id;           /* Restore id alone */
-}
-
-void scv_profile_create(scv_profile * profile, u64 prime,
-    u64 poly2, u64 lpc, u64 secret_share, u64 validity)
-{
-    if (profile)
-    {
-        scv_profile_cleanup(profile);
-        profile->prime = prime;
-        profile->primeinv = 1.0 / prime;
-        profile->lpc = lpc;
-        profile->poly_pre_eval = poly2;
-        profile->secret_share = secret_share;
-        profile->validity = validity;
-        time_exponent = 1;      /* Got a new profile. Reset backoff */
-        next_time_to_send = 0;  /* and send next request with no delay */
-    }
-}
-
-void scv_set_validator(scv_profile * profile, u64 key)
-{
-    if (profile)
-    {
-        profile->validator = 1;
-        profile->secret_key = key;
-    }
-}
-
-static inline u64 sc_update_cumulative(u64 cumulative, u64 random,
-    u64 secret_share, u64 prime, u64 lpc, u64 pre_split, double prime_inv)
-{
-    u64 share_random = 0;
-    u64 cumulative_new = 0;
-
-    /* 
-     * calculate split share for random
-     */
-    share_random = add64_mod(pre_split, random, prime, prime_inv);
-
-    /* 
-     * lpc * (share_secret + share_random)
-     */
-    share_random = add64_mod(share_random, secret_share, prime, prime_inv);
-    share_random = mul64_mod(share_random, lpc, prime, prime_inv);
-
-    cumulative_new = add64_mod(cumulative, share_random, prime, prime_inv);
-
-    return (cumulative_new);
-}
-
-u64 scv_update_cumulative(scv_profile * profile, u64 cumulative, u64 random)
-{
-    if (profile && profile->validity != 0)
-    {
-        return (sc_update_cumulative(cumulative, random, profile->secret_share,
-                profile->prime, profile->lpc, profile->poly_pre_eval,
-                profile->primeinv));
-    }
-    return (0);
-}
-
-static u8 sc_validate(u64 secret, u64 prime, double prime_inv,
-    u64 cumulative, u64 random)
-{
-    if (cumulative == (random + secret))
-    {
-        return (1);
-    }
-    else if (cumulative == add64_mod(random, secret, prime, prime_inv))
-    {
-        return (1);
-    }
-    return (0);
-}
-
-/* 
- * return True if the cumulative matches secret from a profile
- */
-u8 scv_validate(scv_profile * profile, u64 cumulative, u64 random)
-{
-    if (profile && profile->validator)
-    {
-        return (sc_validate(profile->secret_key, profile->prime,
-                profile->primeinv, cumulative, random));
-    }
-    return (0);
-}
-
-/* 
- * Utility function to get random number per pack
- */
-u64 scv_generate_random(scv_profile * profile)
-{
-    u64 random = 0;
-    int32_t second_half;
-    static u32 seed = 0;
-
-    if (PREDICT_FALSE(!seed))
-        seed = random_default_seed();
-
-    /* 
-     * Upper 4 bytes seconds
-     */
-    random = (u64) time(NULL);
-
-    random &= 0xffffffff;
-    random = random << 32;
-    /* 
-     * Lower 4 bytes random number
-     */
-    second_half = random_u32(&seed);
-
-    random |= second_half;
-
-    if (PREDICT_TRUE(profile != NULL))
-    {
-        random &= profile->bit_mask;
-    }
-    return (random);
-}
-
-void scv_profile_set_bit_mask(scv_profile * profile, u16 bits)
-{
-    int sizeInBits;
-
-    if (profile)
-    {
-        sizeInBits = sizeof(profile->bit_mask) * 8;
-        profile->bit_mask =
-            (bits >=
-            sizeInBits ? (u64) - 1 : (u64) ((u64) 1 << (u64) bits) - 1);
-    }
-}
-
-/* 
- * TODO: Use vector buffers and hash tables
- */
-#define MAX_SERVICES 16
-
-clib_error_t *clear_scv_profile_command_fn(vlib_main_t * vm,
-    unformat_input_t * input, vlib_cli_command_t * cmd)
-{
-    int i = 0;
-
-    if (!sc_init_done)
-        return 0;
-
-    for (i = 0; i < max_profiles; i++)
-    {
-        scv_profile_cleanup(&profile_list[i]);
-    }
-    pow_profile = NULL;
-    pow_profile_index = 0;
-    total_pkts_using_this_profile = 0;
-    memset(chain_path_name, 0, PATH_NAME_SIZE);
-    max_profiles = 0;
-    invalid_profile_start_index = 0;
-    number_of_invalid_profiles = 0;
-    next_time_to_send = 0;
-    time_exponent = 1;
-    sc_init_done = 0;
-
-    return 0;
-}
-
-void clear_scv_profiles()
-{
-    clear_scv_profile_command_fn(0, 0, 0);
-}
-
-VLIB_CLI_COMMAND(clear_scv_profile_command) =
-{
-.path = "clear scv profile",
-.short_help = "clear scv profile [<index>|all]",
-.function = clear_scv_profile_command_fn,
-};
-
-static clib_error_t *set_scv_profile_command_fn(vlib_main_t * vm,
-    unformat_input_t * input, vlib_cli_command_t * cmd)
-{
-    u64 prime;
-    u64 secret_share, validity;
-    u64 secret_key;
-    u8 validator = 0;
-    u16 profile_id;
-    u32 bits;
-    u64 lpc = 0, poly2 = 0;
-    scv_profile *profile = NULL;
-
-    bits = MAX_BITS;
-
-    while (unformat_check_input(input) != UNFORMAT_END_OF_INPUT)
-    {
-        if (unformat(input, "id %d", &profile_id))
-            ;
-        else if (unformat(input, "validate-key 0x%Lx", &secret_key))
-            validator = 1;
-        else if (unformat(input, "prime-number 0x%Lx", &prime))
-            ;
-        else if (unformat(input, "secret_share 0x%Lx", &secret_share))
-            ;
-        else if (unformat(input, "polynomial2 0x%Lx", &poly2))
-            ;
-        else if (unformat(input, "lpc 0x%Lx", &lpc))
-            ;
-        else if (unformat(input, "validity 0x%Lx", &validity))
-            ;
-        else if (unformat(input, "bits-in-random %d", &bits))
-        {
-            if (bits > MAX_BITS)
-                bits = MAX_BITS;
-        }
-        else
-            return clib_error_return(0, "unknown input `%U'",
-                format_unformat_error, input);
-    }
-
-    scv_init((u8 *) "TEST", MAX_SERVICE_PROFILES, 0 /* start index */ );
-    profile = scv_profile_find(profile_id);
-
-    if (profile)
-    {
-        scv_profile_create(profile, prime, poly2, lpc, secret_share, validity);
-        if (validator)
-            scv_set_validator(profile, secret_key);
-        scv_profile_set_bit_mask(profile, bits);
-    }
-
-    return 0;
-}
-
-VLIB_CLI_COMMAND(set_scv_profile_command) =
-{
-.path = "set scv profile",
-.short_help = "set scv profile id [0-16] [validator-key 0xu64] \
-                  prime-number 0xu64 secret_share 0xu64 lpc 0xu64 \
-                  polynomial2 0xu64 bits-in-random [0-64] ",
-.function = set_scv_profile_command_fn,
-};
-
-static clib_error_t *show_scv_profile_command_fn(vlib_main_t * vm,
-    unformat_input_t * input, vlib_cli_command_t * cmd)
-{
-    scv_profile *p = NULL;
-    u16 i;
-    u8 *s = 0;
-
-    if (sc_init_done == 0)
-    {
-        s = format(s, "SCV Profiles not configured\n");
-        vlib_cli_output(vm, "%v", s);
-        return 0;
-    }
-
-    for (i = 0; i < max_profiles; i++)
-    {
-        p = scv_profile_find(i);
-        if (p->validity == 0)
-            continue;
-        s = format(s, "SCV Profile at index: %d\n", i);
-        s = format(s, "                 Id : %d\n", p->id);
-        s = format(s, "          Validator : %s (%d)\n",
-            (p->validator) ? "True" : "False", p->validator);
-        if (p->validator == 1)
-            s = format(s, "         Secret key : 0x%Lx (%Ld)\n",
-                p->secret_key, p->secret_key);
-        s = format(s, "       Secret share : 0x%Lx (%Ld)\n",
-            p->secret_share, p->secret_share);
-        s = format(s, "       Prime number : 0x%Lx (%Ld)\n",
-            p->prime, p->prime);
-        s = format(s, "2nd polynomial(eval) : 0x%Lx (%Ld)\n",
-            p->poly_pre_eval, p->poly_pre_eval);
-        s = format(s, "                 LPC : 0x%Lx (%Ld)\n", p->lpc, p->lpc);
-
-        s = format(s, "           Bit mask : 0x%Lx (%Ld)\n",
-            p->bit_mask, p->bit_mask);
-        s = format(s, "           Validity : 0x%Lx (%Ld)\n",
-            p->validity, p->validity);
-    }
-
-    if (max_profiles)
-    {
-        p = scv_profile_find(pow_profile_index);
-
-        s = format(s, "\nInvalid profiles start : %d Number : %d\n",
-            invalid_profile_start_index, number_of_invalid_profiles);
-
-        if (next_time_to_send)
-            s = format(s, "\nNext time to send : %U, time_exponent:%ld\n",
-                format_time_interval, "d:h:m:s:f:u",
-                next_time_to_send, time_exponent);
-        else
-            s = format(s, "\nNext time to send : Immediate\n");
-        s = format(s, "\nPath name : %s\n", chain_path_name);
-        s = format(s, "\nProfile index in use: %d\n", pow_profile_index);
-        s = format(s, "Pkts passed : 0x%Lx (validity:0x%Lx)\n",
-            total_pkts_using_this_profile, p->validity);
-        if (scv_is_decap(p))
-            s = format(s, "  This is Decap node.  \n");
-        vlib_cli_output(vm, "%v", s);
-    }
-    vec_free(s);
-
-    return 0;
-}
-
-VLIB_CLI_COMMAND(show_scv_profile_command) =
-{
-.path = "show scv profile",
-.short_help = "show scv profile",
-.function = show_scv_profile_command_fn,
-};
-
-static clib_error_t *test_profile_renew_refresh_fn(vlib_main_t * vm,
-    unformat_input_t * input, vlib_cli_command_t * cmd)
-{
-    u8 renew_or_refresh = 0;
-
-#define TEST_PROFILE_RENEW 1
-#define TEST_PROFILE_REFRESH 2
-    u8 *path_name = 0;
-    u32 start_index = 0, num_profiles = 0;
-    int rc = 0;
-
-    while (unformat_check_input(input) != UNFORMAT_END_OF_INPUT)
-    {
-        if (unformat(input, "path-name %s start-index %d num-profiles %d",
-                &path_name, &start_index, &num_profiles))
-            ;
-        else if (unformat(input, "renew"))
-            renew_or_refresh = TEST_PROFILE_RENEW;
-        else if (unformat(input, "refresh"))
-            renew_or_refresh = TEST_PROFILE_REFRESH;
-        else
-            break;
-    }
-
-    if (renew_or_refresh == TEST_PROFILE_RENEW)
-    {
-       
-        rc = scv_profile_renew(path_name, (u8) start_index, (u8) num_profiles);
-    }
-    else if (renew_or_refresh == TEST_PROFILE_REFRESH)
-    {
-       
-        rc = scv_profile_refresh(path_name, (u8) start_index,
-            (u8) num_profiles);
-    }
-    else
-    {
-        vec_free(path_name);
-        return clib_error_return(0, "Enter renew or refresh");
-    }
-
-    vlib_cli_output(vm, "%s notification %s. rc = %d\n",
-        (renew_or_refresh == TEST_PROFILE_RENEW) ? "Renew" : "Refresh",
-        (rc != 0) ? "failed" : "sent", (u32) rc);
-
-    vec_free(path_name);
-
-    return 0;
-}
-
-VLIB_CLI_COMMAND(test_ioam_profile_renew_refresh_cmd, static) =
-{
-.path = "test ioam profile-notification  ",
-.short_help =
-        "test ioam profile-notification path-name <string> start-index <index> num-profiles <number> <renew|refresh>",
-.function = test_profile_renew_refresh_fn,
-};
-
-static clib_error_t *set_scv_init_fn(vlib_main_t * vm,
-    unformat_input_t * input, vlib_cli_command_t * cmd)
-{
-    u8 *path_name = 0;
-    u32 start_index = 0, num_profiles = 0;
-
-    while (unformat_check_input(input) != UNFORMAT_END_OF_INPUT)
-    {
-        if (unformat(input, "path-name %s start-index %d num-profiles %d",
-                &path_name, &start_index, &num_profiles))
-            scv_init(path_name, num_profiles, start_index);
-        else
-            return clib_error_return(0, "unknown input `%U'",
-                format_unformat_error, input);
-    }
-    vec_free(path_name);
-    return 0;
-}
-
-VLIB_CLI_COMMAND(set_ioam_sc_init_command, static) =
-{
-.path = "set scv-init ",
-.short_help =
-        "set scv-init path-name <string> start-index <index> num-profiles <number>",
-.function = set_scv_init_fn,
-};
diff --git a/vnet/vnet/lib-scv/scv_util.h b/vnet/vnet/lib-scv/scv_util.h
deleted file mode 100644 (file)
index 5c304e9..0000000
+++ /dev/null
@@ -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