FD.io VPP  v16.06
Vector Packet Processing
scv_util.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include <vnet/vnet.h>
16 #include <stdint.h>
17 #include <time.h>
18 #include <string.h>
19 #include <vppinfra/mem.h>
20 #include "math64.h"
21 #include "scv_util.h"
22 
23 scv_profile *pow_profile = NULL;
33 vlib_main_t *gvm = 0;
34 
35 static void scv_profile_init(scv_profile * new, u16 id)
36 {
37  if (new)
38  {
39  memset(new, 0, sizeof(scv_profile));
40  new->id = id;
41  }
42 }
43 
44 /*
45  * Get maximum number of profiles configured for this chain.
46  */
48 {
49  return max_profiles;
50 }
51 
53 {
54  u8 max = scv_get_max_profiles();
55 
56  if (id >= 0 && id < max)
57  {
58  return (&profile_list[id]);
59  }
60  return (NULL);
61 }
62 
64 void scv_init(u8 * path_name, u8 max, u8 indx)
65 {
66  int i = 0;
67 
68  if (sc_init_done)
69  {
70  return;
71  }
72  memcpy(chain_path_name, path_name, strlen((const char *)path_name) + 1);
73  max_profiles = max;
74  pow_profile_index = indx;
75 
76  for (i = 0; i < max_profiles; i++)
77  {
78  scv_profile_init(&profile_list[i], i);
79  }
80 
81  sc_init_done = 1;
82 }
83 
85 {
86  u16 id = profile->id;
87 
88  memset(profile, 0, sizeof(scv_profile));
89  profile->id = id; /* Restore id alone */
90 }
91 
92 void scv_profile_create(scv_profile * profile, u64 prime,
93  u64 poly2, u64 lpc, u64 secret_share, u64 validity)
94 {
95  if (profile)
96  {
97  scv_profile_cleanup(profile);
98  profile->prime = prime;
99  profile->primeinv = 1.0 / prime;
100  profile->lpc = lpc;
101  profile->poly_pre_eval = poly2;
102  profile->secret_share = secret_share;
103  profile->validity = validity;
104  time_exponent = 1; /* Got a new profile. Reset backoff */
105  next_time_to_send = 0; /* and send next request with no delay */
106  }
107 }
108 
109 void scv_set_validator(scv_profile * profile, u64 key)
110 {
111  if (profile)
112  {
113  profile->validator = 1;
114  profile->secret_key = key;
115  }
116 }
117 
118 static inline u64 sc_update_cumulative(u64 cumulative, u64 random,
119  u64 secret_share, u64 prime, u64 lpc, u64 pre_split, double prime_inv)
120 {
121  u64 share_random = 0;
122  u64 cumulative_new = 0;
123 
124  /*
125  * calculate split share for random
126  */
127  share_random = add64_mod(pre_split, random, prime, prime_inv);
128 
129  /*
130  * lpc * (share_secret + share_random)
131  */
132  share_random = add64_mod(share_random, secret_share, prime, prime_inv);
133  share_random = mul64_mod(share_random, lpc, prime, prime_inv);
134 
135  cumulative_new = add64_mod(cumulative, share_random, prime, prime_inv);
136 
137  return (cumulative_new);
138 }
139 
140 u64 scv_update_cumulative(scv_profile * profile, u64 cumulative, u64 random)
141 {
142  if (profile && profile->validity != 0)
143  {
144  return (sc_update_cumulative(cumulative, random, profile->secret_share,
145  profile->prime, profile->lpc, profile->poly_pre_eval,
146  profile->primeinv));
147  }
148  return (0);
149 }
150 
151 static u8 sc_validate(u64 secret, u64 prime, double prime_inv,
152  u64 cumulative, u64 random)
153 {
154  if (cumulative == (random + secret))
155  {
156  return (1);
157  }
158  else if (cumulative == add64_mod(random, secret, prime, prime_inv))
159  {
160  return (1);
161  }
162  return (0);
163 }
164 
165 /*
166  * return True if the cumulative matches secret from a profile
167  */
168 u8 scv_validate(scv_profile * profile, u64 cumulative, u64 random)
169 {
170  if (profile && profile->validator)
171  {
172  return (sc_validate(profile->secret_key, profile->prime,
173  profile->primeinv, cumulative, random));
174  }
175  return (0);
176 }
177 
178 /*
179  * Utility function to get random number per pack
180  */
182 {
183  u64 random = 0;
184  int32_t second_half;
185  static u32 seed = 0;
186 
187  if (PREDICT_FALSE(!seed))
188  seed = random_default_seed();
189 
190  /*
191  * Upper 4 bytes seconds
192  */
193  random = (u64) time(NULL);
194 
195  random &= 0xffffffff;
196  random = random << 32;
197  /*
198  * Lower 4 bytes random number
199  */
200  second_half = random_u32(&seed);
201 
202  random |= second_half;
203 
204  if (PREDICT_TRUE(profile != NULL))
205  {
206  random &= profile->bit_mask;
207  }
208  return (random);
209 }
210 
212 {
213  int sizeInBits;
214 
215  if (profile)
216  {
217  sizeInBits = sizeof(profile->bit_mask) * 8;
218  profile->bit_mask =
219  (bits >=
220  sizeInBits ? (u64) - 1 : (u64) ((u64) 1 << (u64) bits) - 1);
221  }
222 }
223 
224 /*
225  * TODO: Use vector buffers and hash tables
226  */
227 #define MAX_SERVICES 16
228 
230  unformat_input_t * input, vlib_cli_command_t * cmd)
231 {
232  int i = 0;
233 
234  if (!sc_init_done)
235  return 0;
236 
237  for (i = 0; i < max_profiles; i++)
238  {
239  scv_profile_cleanup(&profile_list[i]);
240  }
241  pow_profile = NULL;
242  pow_profile_index = 0;
244  memset(chain_path_name, 0, PATH_NAME_SIZE);
245  max_profiles = 0;
248  next_time_to_send = 0;
249  time_exponent = 1;
250  sc_init_done = 0;
251 
252  return 0;
253 }
254 
256 {
258 }
259 
260 VLIB_CLI_COMMAND(clear_scv_profile_command) =
261 {
262 .path = "clear scv profile",
263 .short_help = "clear scv profile [<index>|all]",
264 .function = clear_scv_profile_command_fn,
265 };
266 
268  unformat_input_t * input, vlib_cli_command_t * cmd)
269 {
270  u64 prime;
271  u64 secret_share, validity;
272  u64 secret_key;
273  u8 validator = 0;
274  u16 profile_id;
275  u32 bits;
276  u64 lpc = 0, poly2 = 0;
277  scv_profile *profile = NULL;
278 
279  bits = MAX_BITS;
280 
282  {
283  if (unformat(input, "id %d", &profile_id))
284  ;
285  else if (unformat(input, "validate-key 0x%Lx", &secret_key))
286  validator = 1;
287  else if (unformat(input, "prime-number 0x%Lx", &prime))
288  ;
289  else if (unformat(input, "secret_share 0x%Lx", &secret_share))
290  ;
291  else if (unformat(input, "polynomial2 0x%Lx", &poly2))
292  ;
293  else if (unformat(input, "lpc 0x%Lx", &lpc))
294  ;
295  else if (unformat(input, "validity 0x%Lx", &validity))
296  ;
297  else if (unformat(input, "bits-in-random %d", &bits))
298  {
299  if (bits > MAX_BITS)
300  bits = MAX_BITS;
301  }
302  else
303  return clib_error_return(0, "unknown input `%U'",
304  format_unformat_error, input);
305  }
306 
307  scv_init((u8 *) "TEST", MAX_SERVICE_PROFILES, 0 /* start index */ );
308  profile = scv_profile_find(profile_id);
309 
310  if (profile)
311  {
312  scv_profile_create(profile, prime, poly2, lpc, secret_share, validity);
313  if (validator)
314  scv_set_validator(profile, secret_key);
315  scv_profile_set_bit_mask(profile, bits);
316  }
317 
318  return 0;
319 }
320 
321 VLIB_CLI_COMMAND(set_scv_profile_command) =
322 {
323 .path = "set scv profile",
324 .short_help = "set scv profile id [0-16] [validator-key 0xu64] \
325  prime-number 0xu64 secret_share 0xu64 lpc 0xu64 \
326  polynomial2 0xu64 bits-in-random [0-64] ",
327 .function = set_scv_profile_command_fn,
328 };
329 
331  unformat_input_t * input, vlib_cli_command_t * cmd)
332 {
333  scv_profile *p = NULL;
334  u16 i;
335  u8 *s = 0;
336 
337  if (sc_init_done == 0)
338  {
339  s = format(s, "SCV Profiles not configured\n");
340  vlib_cli_output(vm, "%v", s);
341  return 0;
342  }
343 
344  for (i = 0; i < max_profiles; i++)
345  {
346  p = scv_profile_find(i);
347  if (p->validity == 0)
348  continue;
349  s = format(s, "SCV Profile at index: %d\n", i);
350  s = format(s, " Id : %d\n", p->id);
351  s = format(s, " Validator : %s (%d)\n",
352  (p->validator) ? "True" : "False", p->validator);
353  if (p->validator == 1)
354  s = format(s, " Secret key : 0x%Lx (%Ld)\n",
355  p->secret_key, p->secret_key);
356  s = format(s, " Secret share : 0x%Lx (%Ld)\n",
357  p->secret_share, p->secret_share);
358  s = format(s, " Prime number : 0x%Lx (%Ld)\n",
359  p->prime, p->prime);
360  s = format(s, "2nd polynomial(eval) : 0x%Lx (%Ld)\n",
362  s = format(s, " LPC : 0x%Lx (%Ld)\n", p->lpc, p->lpc);
363 
364  s = format(s, " Bit mask : 0x%Lx (%Ld)\n",
365  p->bit_mask, p->bit_mask);
366  s = format(s, " Validity : 0x%Lx (%Ld)\n",
367  p->validity, p->validity);
368  }
369 
370  if (max_profiles)
371  {
373 
374  s = format(s, "\nInvalid profiles start : %d Number : %d\n",
376 
377  if (next_time_to_send)
378  s = format(s, "\nNext time to send : %U, time_exponent:%ld\n",
379  format_time_interval, "d:h:m:s:f:u",
381  else
382  s = format(s, "\nNext time to send : Immediate\n");
383  s = format(s, "\nPath name : %s\n", chain_path_name);
384  s = format(s, "\nProfile index in use: %d\n", pow_profile_index);
385  s = format(s, "Pkts passed : 0x%Lx (validity:0x%Lx)\n",
387  if (scv_is_decap(p))
388  s = format(s, " This is Decap node. \n");
389  vlib_cli_output(vm, "%v", s);
390  }
391  vec_free(s);
392 
393  return 0;
394 }
395 
396 VLIB_CLI_COMMAND(show_scv_profile_command) =
397 {
398 .path = "show scv profile",
399 .short_help = "show scv profile",
400 .function = show_scv_profile_command_fn,
401 };
402 
404  unformat_input_t * input, vlib_cli_command_t * cmd)
405 {
406  u8 renew_or_refresh = 0;
407 
408 #define TEST_PROFILE_RENEW 1
409 #define TEST_PROFILE_REFRESH 2
410  u8 *path_name = 0;
411  u32 start_index = 0, num_profiles = 0;
412  int rc = 0;
413 
415  {
416  if (unformat(input, "path-name %s start-index %d num-profiles %d",
417  &path_name, &start_index, &num_profiles))
418  ;
419  else if (unformat(input, "renew"))
420  renew_or_refresh = TEST_PROFILE_RENEW;
421  else if (unformat(input, "refresh"))
422  renew_or_refresh = TEST_PROFILE_REFRESH;
423  else
424  break;
425  }
426 
427  if (renew_or_refresh == TEST_PROFILE_RENEW)
428  {
429 
430  rc = scv_profile_renew(path_name, (u8) start_index, (u8) num_profiles);
431  }
432  else if (renew_or_refresh == TEST_PROFILE_REFRESH)
433  {
434 
435  rc = scv_profile_refresh(path_name, (u8) start_index,
436  (u8) num_profiles);
437  }
438  else
439  {
440  vec_free(path_name);
441  return clib_error_return(0, "Enter renew or refresh");
442  }
443 
444  vlib_cli_output(vm, "%s notification %s. rc = %d\n",
445  (renew_or_refresh == TEST_PROFILE_RENEW) ? "Renew" : "Refresh",
446  (rc != 0) ? "failed" : "sent", (u32) rc);
447 
448  vec_free(path_name);
449 
450  return 0;
451 }
452 
453 VLIB_CLI_COMMAND(test_ioam_profile_renew_refresh_cmd, static) =
454 {
455 .path = "test ioam profile-notification ",
456 .short_help =
457  "test ioam profile-notification path-name <string> start-index <index> num-profiles <number> <renew|refresh>",
459 };
460 
462  unformat_input_t * input, vlib_cli_command_t * cmd)
463 {
464  u8 *path_name = 0;
465  u32 start_index = 0, num_profiles = 0;
466 
468  {
469  if (unformat(input, "path-name %s start-index %d num-profiles %d",
470  &path_name, &start_index, &num_profiles))
471  scv_init(path_name, num_profiles, start_index);
472  else
473  return clib_error_return(0, "unknown input `%U'",
474  format_unformat_error, input);
475  }
476  vec_free(path_name);
477  return 0;
478 }
479 
480 VLIB_CLI_COMMAND(set_ioam_sc_init_command, static) =
481 {
482 .path = "set scv-init ",
483 .short_help =
484  "set scv-init path-name <string> start-index <index> num-profiles <number>",
485 .function = set_scv_init_fn,
486 };
scv_profile * scv_profile_find(u16 id)
Definition: scv_util.c:52
static void scv_profile_init(scv_profile *new, u16 id)
Definition: scv_util.c:35
#define MAX_SERVICE_PROFILES
Definition: scv_util.h:31
void scv_profile_cleanup(scv_profile *profile)
Definition: scv_util.c:84
f64 next_time_to_send
Definition: scv_util.c:31
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:267
u8 sc_init_done
Definition: scv_util.c:63
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:942
u64 validity
Definition: scv_util.h:67
#define PREDICT_TRUE(x)
Definition: clib.h:98
#define UNFORMAT_END_OF_INPUT
Definition: format.h:142
#define NULL
Definition: clib.h:55
u8 validator
Definition: scv_util.h:59
void scv_init(u8 *path_name, u8 max, u8 indx)
Definition: scv_util.c:64
static u64 mul64_mod(u64 a, u64 b, u64 p, double pi)
Definition: math64.h:151
static u64 add64_mod(u64 a, u64 b, u64 p, double pi)
Definition: math64.h:140
clib_error_t * clear_scv_profile_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: scv_util.c:229
u8 scv_get_max_profiles(void)
Definition: scv_util.c:47
always_inline uword unformat_check_input(unformat_input_t *i)
Definition: format.h:168
u64 scv_update_cumulative(scv_profile *profile, u64 cumulative, u64 random)
Definition: scv_util.c:140
static clib_error_t * show_scv_profile_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: scv_util.c:330
u8 scv_validate(scv_profile *profile, u64 cumulative, u64 random)
Definition: scv_util.c:168
void scv_set_validator(scv_profile *profile, u64 key)
Definition: scv_util.c:109
unsigned long u64
Definition: types.h:89
always_inline u32 random_u32(u32 *seed)
32-bit random number generator
Definition: random.h:68
u64 secret_share
Definition: scv_util.h:61
static u64 sc_update_cumulative(u64 cumulative, u64 random, u64 secret_share, u64 prime, u64 lpc, u64 pre_split, double prime_inv)
Definition: scv_util.c:118
static clib_error_t * set_scv_init_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: scv_util.c:461
double primeinv
Definition: scv_util.h:68
always_inline uword random_default_seed(void)
Default random seed (unix/linux user-mode)
Definition: random.h:85
u64 secret_key
Definition: scv_util.h:60
#define PREDICT_FALSE(x)
Definition: clib.h:97
#define PATH_NAME_SIZE
Definition: scv_util.h:27
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:538
void scv_profile_set_bit_mask(scv_profile *profile, u16 bits)
Definition: scv_util.c:211
u64 poly_pre_eval
Definition: scv_util.h:64
Usage:
Definition: scv_util.h:55
u64 scv_generate_random(scv_profile *profile)
Definition: scv_util.c:181
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:298
void clear_scv_profiles()
Definition: scv_util.c:255
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:150
u16 pow_profile_index
Definition: scv_util.c:24
unsigned int u32
Definition: types.h:88
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:87
void scv_profile_create(scv_profile *profile, u64 prime, u64 poly2, u64 lpc, u64 secret_share, u64 validity)
Definition: scv_util.c:92
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:405
u64 bit_mask
Definition: scv_util.h:65
u16 invalid_profile_start_index
Definition: scv_util.c:29
unsigned short u16
Definition: types.h:57
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)
u64 total_pkts_using_this_profile
Definition: scv_util.c:25
u8 * format_time_interval(u8 *s, va_list *args)
Definition: std-formats.c:115
static clib_error_t * test_profile_renew_refresh_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: scv_util.c:403
static clib_error_t * set_scv_profile_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: scv_util.c:267
u8 chain_path_name[PATH_NAME_SIZE]
Definition: scv_util.c:26
u32 time_exponent
Definition: scv_util.c:32
#define TEST_PROFILE_REFRESH
u8 max_profiles
Definition: scv_util.c:28
static u8 scv_is_decap(scv_profile *p)
Definition: scv_util.h:177
#define TEST_PROFILE_RENEW
#define clib_error_return(e, args...)
Definition: error.h:112
struct _unformat_input_t unformat_input_t
static u8 sc_validate(u64 secret, u64 prime, double prime_inv, u64 cumulative, u64 random)
Definition: scv_util.c:151
#define MAX_BITS
Definition: scv_util.h:117
u8 number_of_invalid_profiles
Definition: scv_util.c:30