aboutsummaryrefslogtreecommitdiffstats
path: root/vnet/vnet/lib-scv/scv_util.h
diff options
context:
space:
mode:
Diffstat (limited to 'vnet/vnet/lib-scv/scv_util.h')
-rw-r--r--vnet/vnet/lib-scv/scv_util.h278
1 files changed, 278 insertions, 0 deletions
diff --git a/vnet/vnet/lib-scv/scv_util.h b/vnet/vnet/lib-scv/scv_util.h
new file mode 100644
index 00000000000..fc0c73f47b1
--- /dev/null
+++ b/vnet/vnet/lib-scv/scv_util.h
@@ -0,0 +1,278 @@
+/*
+ * 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_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