FD.io VPP  v16.06
Vector Packet Processing
scv_util.h
Go to the documentation of this file.
1 /*
2  * scv_util.h -- Service chain validation/Proof Of Transit Utility Header
3  *
4  * Copyright (c) 2015 Cisco and/or its affiliates.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #ifndef include_vnet_scv_util_h
19 #define include_vnet_scv_util_h
20 
21 #include <vnet/ip/ip6_hop_by_hop.h>
22 #define MAXDEGREE 1024
23 #define MAXTOKENLEN 128
24 #define debug_ioam debug_ioam_fn
25 #define MAX_SERVICE_NODES 10
26 /* Dont change this size 256. This is there across multiple components */
27 #define PATH_NAME_SIZE 256
28 
29 /* Ring size. this should be same as the one in ODL. Do not change this
30  without change in ODL. */
31 #define MAX_SERVICE_PROFILES 16
32 
33 /**
34  * Usage:
35  *
36  * On any [service] node that participates in Service / Path verfication:
37  *
38  * Step 1: Initialize this library by calling scv_init()
39  * Step 2: Setup a Service chain validation profile that contains all the parameters needed to compute cumulative:
40  * Call these functions:
41  * scv_profile_find
42  * scv_profile_create
43  * scv_profile_set_bit_mask - To setup how large we want the numbers used in the computation and random number <= 64 bits
44  * Step 2a: For validator do this:
45  * scv_set_validator
46  * Step 3a: At the initial Service node to generate Random number that will be read by all other nodes:
47  * scv_generate_random
48  * Step 3b: At all service nodes including initial and verifier call this to compute cumulative:
49  * scv_update_cumulative
50  * Step 4: At the verifier:
51  * scv_validate
52  *
53  */
54 
55 typedef struct scv_profile_
56 {
68  double primeinv;
69  // struct hlist_node my_hash_list; when this gets added to hashtbale
70 } scv_profile;
71 
72 extern scv_profile *pow_profile;
73 extern u16 pow_profile_index;
78 extern f64 next_time_to_send;
79 extern u32 time_exponent;
80 
81 /*
82  * Initialize Service chain
83  */
84 void scv_init(u8 * path_name, u8 max, u8 indx);
85 
86 /*
87  * Get maximum number of profiles configured for this chain.
88  */
90 
91 /*
92  * Find a SC profile by ID
93  */
95 
96 static inline u16 scv_profile_get_id(scv_profile * profile)
97 {
98  if (profile)
99  {
100  return (profile->id);
101  }
102  return (0);
103 }
104 
105 /* setup and clean up profile */
106 void scv_profile_create(scv_profile * profile, u64 prime,
107  u64 poly2, u64 lpc, u64 secret_share, u64 validity);
108 /*
109  * Setup profile as a validator
110  */
111 void scv_set_validator(scv_profile * profile, u64 key);
112 void scv_profile_cleanup(scv_profile * profile);
113 
114 /*
115  * Setup max bits to be used for random number generation
116  */
117 #define MAX_BITS 64
118 void scv_profile_set_bit_mask(scv_profile * profile, u16 bits);
119 
120 /*
121  * Given a random and cumulative compute the new cumulative for a given profile
122  */
123 u64 scv_update_cumulative(scv_profile * profile, u64 cumulative, u64 random);
124 
125 /*
126  * return True if the cumulative matches secret from a profile
127  */
128 u8 scv_validate(scv_profile * profile, u64 cumulative, u64 random);
129 
130 /*
131  * Utility function to get random number per pack
132  */
134 
135 int scv_profile_to_str(scv_profile * profile, char *buf, int n);
136 
137 extern void clear_ioam_scv_profiles();
138 
139 static inline u8 scv_get_profile_in_use(void)
140 {
141  return pow_profile_index;
142 }
143 
144 static inline
145  void scv_notification_reset(u16 start_index_recvd, u8 num_profiles_recvd)
146 {
147  /* Profiles recevied w/o notn. Nothing to do. */
149  return;
150 
151  /* Most likely case. Got all requested profiles */
152  if (PREDICT_TRUE(num_profiles_recvd == number_of_invalid_profiles &&
153  start_index_recvd == invalid_profile_start_index))
154  {
157  return;
158  }
159 
160  /* Received partial list */
161  if (num_profiles_recvd < number_of_invalid_profiles)
162  {
163  ASSERT(start_index_recvd == invalid_profile_start_index);
164  invalid_profile_start_index = (start_index_recvd + num_profiles_recvd)
166  number_of_invalid_profiles -= num_profiles_recvd;
167  }
168 
169  return;
170 }
171 
172 int __attribute__ ((weak)) scv_profile_renew(u8 * path_name,
173  u8 start_index, u8 num_profiles);
174 int __attribute__ ((weak)) scv_profile_refresh(u8 * path_name,
175  u8 start_index, u8 num_profiles);
176 
177 static inline u8 scv_is_decap(scv_profile * p)
178 {
179  return (p->validator == 1);
180 }
181 
183 {
184  int next_id, num_profiles = 0;
185  scv_profile *p;
186  u8 max;
187 
188  max = scv_get_max_profiles();
189 
190  next_id = id;
191 
192  /* Check for new profile in the ring buffer until a valid one. Exclude
193  checking for the one already in use. */
194  for (num_profiles = 0; num_profiles < max - 1; num_profiles++)
195  {
196  next_id = (next_id + 1) % max;
197  p = scv_profile_find(next_id);
198  if (p->validity != 0)
199  {
200  vlib_cli_output(vm, "Current id: %d, New id: %d\n", id, next_id);
201  return (next_id);
202  }
203  }
204 
205  return (id);
206 }
207 
208 static inline void
210  u16 id, u8 is_encap)
211 {
212  scv_profile *p = scv_profile_find(id);
213  int rc;
214  u8 max;
215  f64 now = 0;
216 
217  p->validity = 0;
218 
219  /* If there are alredy profiles waiting. If so, use existing start_index.
220  */
223 
224  max = scv_get_max_profiles();
225 
226  /* Check whether the id is already included in existing list */
227  if (!(id >= invalid_profile_start_index &&
229  number_of_invalid_profiles - 1) % max))
230  {
232  }
233 
236 
237  now = (f64) (((f64) hm->unix_time_0) +
238  (vlib_time_now(hm->vlib_main) - hm->vlib_time_0));
239  if (now <= next_time_to_send)
240  return;
241 
242  if (is_encap)
243  {
246  if (rc != 0)
247  vlib_cli_output(vm,
248  "Renew notification- id start:%d, num %d failed. rc: %d\n",
249  invalid_profile_start_index, number_of_invalid_profiles, rc);
250  else
251  vlib_cli_output(vm,
252  "Renew notification- id start:%d num %d sent. \n",
253  invalid_profile_start_index, number_of_invalid_profiles);
254 
255  }
256  else
257  {
258  /* Non encap node. Send refresh notification for now. Later set a
259  timer and if there is no profile even after the timeout send
260  refresh notification. */
263  if (rc != 0)
264  vlib_cli_output(vm,
265  "Refresh notification- id start:%d, num %d failed. rc: %d\n",
266  invalid_profile_start_index, number_of_invalid_profiles, rc);
267  else
268  vlib_cli_output(vm,
269  "Refresh notification- id start:%d num %d sent. \n",
270  invalid_profile_start_index, number_of_invalid_profiles);
271  }
273  time_exponent <<= 1; /* backoff time is power of 2 seconds */
274 
275  return;
276 }
277 
278 #endif
u16 pow_profile_index
Definition: scv_util.c:24
u64 validity
Definition: scv_util.h:67
void scv_profile_create(scv_profile *profile, u64 prime, u64 poly2, u64 lpc, u64 secret_share, u64 validity)
Definition: scv_util.c:92
u8 chain_path_name[PATH_NAME_SIZE]
Definition: scv_util.c:26
#define PREDICT_TRUE(x)
Definition: clib.h:98
u8 scv_validate(scv_profile *profile, u64 cumulative, u64 random)
Definition: scv_util.c:168
u8 validator
Definition: scv_util.h:59
void clear_ioam_scv_profiles()
scv_profile * scv_profile_find(u16 id)
Definition: scv_util.c:52
u64 total_pkts_using_this_profile
Definition: scv_util.c:25
void scv_profile_cleanup(scv_profile *profile)
Definition: scv_util.c:84
f64 next_time_to_send
Definition: scv_util.c:31
u32 time_exponent
Definition: scv_util.c:32
ip6_hop_by_hop_main_t * hm
u64 scv_generate_random(scv_profile *profile)
Definition: scv_util.c:181
unsigned long u64
Definition: types.h:89
u16 invalid_profile_start_index
Definition: scv_util.c:29
u64 secret_share
Definition: scv_util.h:61
u8 number_of_invalid_profiles
Definition: scv_util.c:30
u64 random
Definition: scv_util.h:58
double primeinv
Definition: scv_util.h:68
u64 secret_key
Definition: scv_util.h:60
#define PATH_NAME_SIZE
Definition: scv_util.h:27
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:538
u64 poly_pre_eval
Definition: scv_util.h:64
static u16 scv_get_next_profile_id(vlib_main_t *vm, u16 id)
Definition: scv_util.h:182
void scv_init(u8 *path_name, u8 max, u8 indx)
Definition: scv_util.c:64
static void scv_notification_reset(u16 start_index_recvd, u8 num_profiles_recvd)
Definition: scv_util.h:145
Usage:
Definition: scv_util.h:55
static u8 scv_get_profile_in_use(void)
Definition: scv_util.h:139
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
scv_profile * pow_profile
Definition: scv_util.c:23
static u16 scv_profile_get_id(scv_profile *profile)
Definition: scv_util.h:96
u64 bit_mask
Definition: scv_util.h:65
static void scv_profile_invalidate(vlib_main_t *vm, ip6_hop_by_hop_main_t *hm, u16 id, u8 is_encap)
Definition: scv_util.h:209
void scv_profile_set_bit_mask(scv_profile *profile, u16 bits)
Definition: scv_util.c:211
vlib_main_t * vlib_main
unsigned short u16
Definition: types.h:57
u8 scv_get_max_profiles(void)
Definition: scv_util.c:47
int scv_profile_renew(u8 *path_name, u8 start_index, u8 num_profiles)
double f64
Definition: types.h:140
unsigned char u8
Definition: types.h:56
int scv_profile_refresh(u8 *path_name, u8 start_index, u8 num_profiles)
struct scv_profile_ scv_profile
Usage:
int scv_profile_to_str(scv_profile *profile, char *buf, int n)
u64 scv_update_cumulative(scv_profile *profile, u64 cumulative, u64 random)
Definition: scv_util.c:140
always_inline f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:182
static u8 scv_is_decap(scv_profile *p)
Definition: scv_util.h:177
void scv_set_validator(scv_profile *profile, u64 key)
Definition: scv_util.c:109