FD.io VPP  v16.09
Vector Packet Processing
ila.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 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 
16 #include <ila/ila.h>
17 #include <vnet/plugin/plugin.h>
18 #include <vnet/ip/lookup.h>
19 
21 
22 #define ILA_TABLE_DEFAULT_HASH_NUM_BUCKETS (64 * 1024)
23 #define ILA_TABLE_DEFAULT_HASH_MEMORY_SIZE (32<<20)
24 
25 #define foreach_ila_error \
26  _(NONE, "valid ILA packets")
27 
28 typedef enum
29 {
30 #define _(sym,str) ILA_ERROR_##sym,
32 #undef _
34 } ila_error_t;
35 
36 static char *ila_error_strings[] = {
37 #define _(sym,string) string,
39 #undef _
40 };
41 
42 typedef enum
43 {
48 
49 typedef struct
50 {
55 
56 static ila_entry_t ila_sir2ila_default_entry = {
57  .csum_mode = ILA_CSUM_MODE_NO_ACTION,
58  .type = ILA_TYPE_IID,
59  .dir = ILA_DIR_ILA2SIR, //Will pass the packet with no
60 };
61 
62 u8 *
63 format_half_ip6_address (u8 * s, va_list * va)
64 {
65  u64 v = clib_net_to_host_u64 (va_arg (*va, u64));
66 
67  return format (s, "%04x:%04x:%04x:%04x",
68  v >> 48, (v >> 32) & 0xffff, (v >> 16) & 0xffff, v & 0xffff);
69 
70 }
71 
72 u8 *
73 format_ila_direction (u8 * s, va_list * args)
74 {
75  ila_direction_t t = va_arg (*args, ila_direction_t);
76 #define _(i,n,st) \
77  if (t == ILA_DIR_##i) \
78  return format(s, st);
80 #undef _
81  return format (s, "invalid_ila_direction");
82 }
83 
84 u8 *
85 format_ila_csum_mode (u8 * s, va_list * va)
86 {
87  ila_csum_mode_t csum_mode = va_arg (*va, ila_csum_mode_t);
88  char *txt;
89 
90  switch (csum_mode)
91  {
92 #define _(i,n,st) \
93  case ILA_CSUM_MODE_##i: \
94  txt = st; \
95  break;
97 #undef _
98  default:
99  txt = "invalid_ila_csum_mode";
100  break;
101  }
102  return format (s, txt);
103 }
104 
105 u8 *
106 format_ila_type (u8 * s, va_list * args)
107 {
108  ila_type_t t = va_arg (*args, ila_type_t);
109 #define _(i,n,st) \
110  if (t == ILA_TYPE_##i) \
111  return format(s, st);
113 #undef _
114  return format (s, "invalid_ila_type");
115 }
116 
117 static u8 *
118 format_ila_entry (u8 * s, va_list * va)
119 {
120  vnet_main_t *vnm = va_arg (*va, vnet_main_t *);
121  ila_entry_t *e = va_arg (*va, ila_entry_t *);
122 
123  if (!e)
124  {
125  return format (s, "%-15s%=40s%=40s%+16s%+18s%+11s", "Type",
126  "SIR Address", "ILA Address", "Adjacency Index",
127  "Checksum Mode", "Direction");
128 
129  }
130  else if (vnm)
131  {
132  if (e->ila_adj_index == ~0)
133  {
134  return format (s, "%-15U%=40U%=40U%16s%18U%11U",
135  format_ila_type, e->type,
138  "n/a", format_ila_csum_mode, e->csum_mode,
140  }
141  else
142  {
143  return format (s, "%-15U%=40U%=40U%16d%18U%11U",
144  format_ila_type, e->type,
149  }
150  }
151 
152  return NULL;
153 }
154 
155 u8 *
156 format_ila_ila2sir_trace (u8 * s, va_list * args)
157 {
158  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
159  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
160  ila_ila2sir_trace_t *t = va_arg (*args, ila_ila2sir_trace_t *);
161  return format (s,
162  "ILA -> SIR adj index: %d entry index: %d initial_dst: %U",
164  &t->initial_dst);
165 }
166 
167 static uword
168 unformat_ila_direction (unformat_input_t * input, va_list * args)
169 {
170  ila_direction_t *result = va_arg (*args, ila_direction_t *);
171 #define _(i,n,s) \
172  if (unformat(input, s)) \
173  { \
174  *result = ILA_DIR_##i; \
175  return 1;\
176  }
177 
179 #undef _
180  return 0;
181 }
182 
183 static uword
184 unformat_ila_type (unformat_input_t * input, va_list * args)
185 {
186  ila_type_t *result = va_arg (*args, ila_type_t *);
187 #define _(i,n,s) \
188  if (unformat(input, s)) \
189  { \
190  *result = ILA_TYPE_##i; \
191  return 1;\
192  }
193 
195 #undef _
196  return 0;
197 }
198 
199 static uword
200 unformat_ila_csum_mode (unformat_input_t * input, va_list * args)
201 {
202  ila_csum_mode_t *result = va_arg (*args, ila_csum_mode_t *);
203  if (unformat (input, "none") || unformat (input, "no-action"))
204  {
205  *result = ILA_CSUM_MODE_NO_ACTION;
206  return 1;
207  }
208  if (unformat (input, "neutral-map"))
209  {
210  *result = ILA_CSUM_MODE_NEUTRAL_MAP;
211  return 1;
212  }
213  if (unformat (input, "adjust-transport"))
214  {
215  *result = ILA_CSUM_MODE_ADJUST_TRANSPORT;
216  return 1;
217  }
218  return 0;
219 }
220 
221 static uword
223 {
224  u64 *result = va_arg (*args, u64 *);
225  u32 a[4];
226 
227  if (!unformat (input, "%x:%x:%x:%x", &a[0], &a[1], &a[2], &a[3]))
228  return 0;
229 
230  if (a[0] > 0xFFFF || a[1] > 0xFFFF || a[2] > 0xFFFF || a[3] > 0xFFFF)
231  return 0;
232 
233  *result = clib_host_to_net_u64 ((((u64) a[0]) << 48) |
234  (((u64) a[1]) << 32) |
235  (((u64) a[2]) << 16) | (((u64) a[3])));
236 
237  return 1;
238 }
239 
241 
242 static uword
244  vlib_node_runtime_t * node, vlib_frame_t * frame)
245 {
246  ip6_main_t *im = &ip6_main;
247  ip_lookup_main_t *lm = &im->lookup_main;
248  u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
249  ila_main_t *ilm = &ila_main;
250 
251  from = vlib_frame_vector_args (frame);
252  n_left_from = frame->n_vectors;
253  next_index = node->cached_next_index;
254 
255  while (n_left_from > 0)
256  {
257  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
258 
259  while (n_left_from >= 4 && n_left_to_next >= 2)
260  {
261  u32 pi0, pi1;
262  vlib_buffer_t *p0, *p1;
263  ip_adjacency_t *adj0, *adj1;
264  ila_entry_t *ie0, *ie1;
265  ip6_header_t *ip60, *ip61;
266  ila_adj_data_t *ad0, *ad1;
267  ip6_address_t *sir_address0, *sir_address1;
268 
269  {
270  vlib_buffer_t *p2, *p3;
271 
272  p2 = vlib_get_buffer (vm, from[2]);
273  p3 = vlib_get_buffer (vm, from[3]);
274 
275  vlib_prefetch_buffer_header (p2, LOAD);
276  vlib_prefetch_buffer_header (p3, LOAD);
277  CLIB_PREFETCH (p2->data, sizeof (ip6_header_t), LOAD);
278  CLIB_PREFETCH (p3->data, sizeof (ip6_header_t), LOAD);
279  }
280 
281  pi0 = to_next[0] = from[0];
282  pi1 = to_next[1] = from[1];
283  from += 2;
284  n_left_from -= 2;
285  to_next += 2;
286  n_left_to_next -= 2;
287 
288  p0 = vlib_get_buffer (vm, pi0);
289  p1 = vlib_get_buffer (vm, pi1);
290  ip60 = vlib_buffer_get_current (p0);
291  ip61 = vlib_buffer_get_current (p1);
292  sir_address0 = &ip60->dst_address;
293  sir_address1 = &ip61->dst_address;
294  adj0 =
295  ip_get_adjacency (lm, vnet_buffer (p0)->ip.adj_index[VLIB_TX]);
296  adj1 =
297  ip_get_adjacency (lm, vnet_buffer (p1)->ip.adj_index[VLIB_TX]);
298  ad0 = (ila_adj_data_t *) & adj0->opaque;
299  ad1 = (ila_adj_data_t *) & adj1->opaque;
300  ie0 = pool_elt_at_index (ilm->entries, ad0->entry_index);
301  ie1 = pool_elt_at_index (ilm->entries, ad1->entry_index);
302 
304  {
305  ila_ila2sir_trace_t *tr =
306  vlib_add_trace (vm, node, p0, sizeof (*tr));
307  tr->ila_index = ie0 - ilm->entries;
308  tr->initial_dst = ip60->dst_address;
309  tr->adj_index = vnet_buffer (p0)->ip.adj_index[VLIB_TX];
310  }
311 
313  {
314  ila_ila2sir_trace_t *tr =
315  vlib_add_trace (vm, node, p1, sizeof (*tr));
316  tr->ila_index = ie1 - ilm->entries;
317  tr->initial_dst = ip61->dst_address;
318  tr->adj_index = vnet_buffer (p1)->ip.adj_index[VLIB_TX];
319  }
320 
321  sir_address0 =
322  (ie0->dir != ILA_DIR_SIR2ILA) ? &ie0->sir_address : sir_address0;
323  sir_address1 =
324  (ie1->dir != ILA_DIR_SIR2ILA) ? &ie1->sir_address : sir_address1;
325  ip60->dst_address.as_u64[0] = sir_address0->as_u64[0];
326  ip60->dst_address.as_u64[1] = sir_address0->as_u64[1];
327  ip61->dst_address.as_u64[0] = sir_address1->as_u64[0];
328  ip61->dst_address.as_u64[1] = sir_address1->as_u64[1];
329 
330  vnet_buffer (p0)->ip.adj_index[VLIB_TX] = ie0->ila_adj_index;
331  vnet_buffer (p1)->ip.adj_index[VLIB_TX] = ie1->ila_adj_index;
332 
333  vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
334  n_left_to_next, pi0, pi1,
337  }
338 
339  /* Single loop */
340  while (n_left_from > 0 && n_left_to_next > 0)
341  {
342  u32 pi0;
343  vlib_buffer_t *p0;
344  ip_adjacency_t *adj0;
345  ila_adj_data_t *ad0;
346  ila_entry_t *ie0;
347  ip6_header_t *ip60;
348  ip6_address_t *sir_address0;
349 
350  pi0 = to_next[0] = from[0];
351  from += 1;
352  n_left_from -= 1;
353  to_next += 1;
354  n_left_to_next -= 1;
355 
356  p0 = vlib_get_buffer (vm, pi0);
357  ip60 = vlib_buffer_get_current (p0);
358  sir_address0 = &ip60->dst_address;
359  adj0 =
360  ip_get_adjacency (lm, vnet_buffer (p0)->ip.adj_index[VLIB_TX]);
361  ad0 = (ila_adj_data_t *) & adj0->opaque;
362  ie0 = pool_elt_at_index (ilm->entries, ad0->entry_index);
363 
365  {
366  ila_ila2sir_trace_t *tr =
367  vlib_add_trace (vm, node, p0, sizeof (*tr));
368  tr->ila_index = ie0 ? (ie0 - ilm->entries) : ~0;
369  tr->initial_dst = ip60->dst_address;
370  tr->adj_index = vnet_buffer (p0)->ip.adj_index[VLIB_TX];
371  }
372 
373  sir_address0 =
374  (ie0->dir != ILA_DIR_SIR2ILA) ? &ie0->sir_address : sir_address0;
375  ip60->dst_address.as_u64[0] = sir_address0->as_u64[0];
376  ip60->dst_address.as_u64[1] = sir_address0->as_u64[1];
377  vnet_buffer (p0)->ip.adj_index[VLIB_TX] = ie0->ila_adj_index;
378 
379  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
380  n_left_to_next, pi0,
382  }
383  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
384  }
385 
386  return frame->n_vectors;
387 }
388 
390 {
391  .function = ila_ila2sir,.name = "ila-to-sir",.vector_size =
392  sizeof (u32),.format_trace = format_ila_ila2sir_trace,.n_errors =
393  ILA_N_ERROR,.error_strings = ila_error_strings,.n_next_nodes =
394  ILA_ILA2SIR_N_NEXT,.next_nodes =
395  {
396  [ILA_ILA2SIR_NEXT_IP6_REWRITE] = "ip6-rewrite",
397  [ILA_ILA2SIR_NEXT_DROP] = "error-drop"}
398 ,};
399 
400 typedef enum
401 {
405 
406 typedef struct
407 {
411 
412 u8 *
413 format_ila_sir2ila_trace (u8 * s, va_list * args)
414 {
415  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
416  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
417  ila_sir2ila_trace_t *t = va_arg (*args, ila_sir2ila_trace_t *);
418 
419  return format (s, "SIR -> ILA entry index: %d initial_dst: %U",
421 }
422 
424 
425 static uword
427  vlib_node_runtime_t * node, vlib_frame_t * frame)
428 {
429  ip6_main_t *im = &ip6_main;
430  ip_lookup_main_t *lm = &im->lookup_main;
432  u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
433  ila_main_t *ilm = &ila_main;
434 
435  from = vlib_frame_vector_args (frame);
436  n_left_from = frame->n_vectors;
437  next_index = node->cached_next_index;
438 
439  while (n_left_from > 0)
440  {
441  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
442 
443  while (n_left_from >= 4 && n_left_to_next >= 2)
444  {
445  u32 pi0, pi1;
446  vlib_buffer_t *p0, *p1;
447  ip6_header_t *ip60, *ip61;
448  u32 next0 = ILA_SIR2ILA_NEXT_DROP;
449  u32 next1 = ILA_SIR2ILA_NEXT_DROP;
450  BVT (clib_bihash_kv) kv0, value0;
451  BVT (clib_bihash_kv) kv1, value1;
454  ip6_address_t *ila_address0, *ila_address1;
455 
456  {
457  vlib_buffer_t *p2, *p3;
458 
459  p2 = vlib_get_buffer (vm, from[2]);
460  p3 = vlib_get_buffer (vm, from[3]);
461 
462  vlib_prefetch_buffer_header (p2, LOAD);
463  vlib_prefetch_buffer_header (p3, LOAD);
464  CLIB_PREFETCH (p2->data, sizeof (ip6_header_t), LOAD);
465  CLIB_PREFETCH (p3->data, sizeof (ip6_header_t), LOAD);
466  }
467 
468  pi0 = to_next[0] = from[0];
469  pi1 = to_next[1] = from[1];
470  from += 2;
471  n_left_from -= 2;
472  to_next += 2;
473  n_left_to_next -= 2;
474 
475  p0 = vlib_get_buffer (vm, pi0);
476  p1 = vlib_get_buffer (vm, pi1);
477  ip60 = vlib_buffer_get_current (p0);
478  ip61 = vlib_buffer_get_current (p1);
479  ila_address0 = &ip60->dst_address;
480  ila_address1 = &ip61->dst_address;
481  kv0.key[0] = ip60->dst_address.as_u64[0];
482  kv0.key[1] = ip60->dst_address.as_u64[1];
483  kv0.key[2] = 0;
484  kv1.key[0] = ip61->dst_address.as_u64[0];
485  kv1.key[1] = ip61->dst_address.as_u64[1];
486  kv1.key[2] = 0;
487 
489  (&ilm->id_to_entry_table, &kv0, &value0)) == 0))
490  {
491  ie0 = &ilm->entries[value0.value];
492  ila_address0 =
493  (ie0->dir !=
494  ILA_DIR_ILA2SIR) ? &ie0->ila_address : ila_address0;
495  }
496 
497  if ((BV (clib_bihash_search)
498  (&ilm->id_to_entry_table, &kv1, &value1)) == 0)
499  {
500  ie1 = &ilm->entries[value1.value];
501  ila_address1 =
502  (ie1->dir !=
503  ILA_DIR_ILA2SIR) ? &ie1->ila_address : ila_address1;
504  }
505 
507  {
508  ila_sir2ila_trace_t *tr =
509  vlib_add_trace (vm, node, p0, sizeof (*tr));
510  tr->ila_index =
511  (ie0 !=
512  &ila_sir2ila_default_entry) ? (ie0 - ilm->entries) : ~0;
513  tr->initial_dst = ip60->dst_address;
514  }
515 
517  {
518  ila_sir2ila_trace_t *tr =
519  vlib_add_trace (vm, node, p1, sizeof (*tr));
520  tr->ila_index =
521  (ie1 !=
522  &ila_sir2ila_default_entry) ? (ie1 - ilm->entries) : ~0;
523  tr->initial_dst = ip61->dst_address;
524  }
525 
526  ip60->dst_address.as_u64[0] = ila_address0->as_u64[0];
527  ip60->dst_address.as_u64[1] = ila_address0->as_u64[1];
528  ip61->dst_address.as_u64[0] = ila_address1->as_u64[0];
529  ip61->dst_address.as_u64[1] = ila_address1->as_u64[1];
530 
532  &p0->current_config_index, &next0, 0);
533 
535  &p1->current_config_index, &next1, 0);
536 
537  vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
538  n_left_to_next, pi0, pi1, next0,
539  next1);
540  }
541 
542  /* Single loop */
543  while (n_left_from > 0 && n_left_to_next > 0)
544  {
545  u32 pi0;
546  vlib_buffer_t *p0;
547  ip6_header_t *ip60;
548  u32 next0 = ILA_SIR2ILA_NEXT_DROP;
549  BVT (clib_bihash_kv) kv0, value0;
551  ip6_address_t *ila_address0;
552 
553  pi0 = to_next[0] = from[0];
554  from += 1;
555  n_left_from -= 1;
556  to_next += 1;
557  n_left_to_next -= 1;
558 
559  p0 = vlib_get_buffer (vm, pi0);
560  ip60 = vlib_buffer_get_current (p0);
561  ila_address0 = &ip60->dst_address;
562 
563  kv0.key[0] = ip60->dst_address.as_u64[0];
564  kv0.key[1] = ip60->dst_address.as_u64[1];
565  kv0.key[2] = 0;
566 
568  (&ilm->id_to_entry_table, &kv0, &value0)) == 0))
569  {
570  ie0 = &ilm->entries[value0.value];
571  ila_address0 =
572  (ie0->dir !=
573  ILA_DIR_ILA2SIR) ? &ie0->ila_address : ila_address0;
574  }
575 
577  {
578  ila_sir2ila_trace_t *tr =
579  vlib_add_trace (vm, node, p0, sizeof (*tr));
580  tr->ila_index =
581  (ie0 !=
582  &ila_sir2ila_default_entry) ? (ie0 - ilm->entries) : ~0;
583  tr->initial_dst = ip60->dst_address;
584  }
585 
586  //This operation should do everything for any type (except vnid4 obviously)
587  ip60->dst_address.as_u64[0] = ila_address0->as_u64[0];
588  ip60->dst_address.as_u64[1] = ila_address0->as_u64[1];
589 
591  &p0->current_config_index, &next0, 0);
592 
593  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
594  n_left_to_next, pi0, next0);
595  }
596  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
597  }
598 
599  return frame->n_vectors;
600 }
601 
603 {
604  .function = ila_sir2ila,.name = "sir-to-ila",.vector_size =
605  sizeof (u32),.format_trace = format_ila_sir2ila_trace,.n_errors =
606  ILA_N_ERROR,.error_strings = ila_error_strings,.n_next_nodes =
607  ILA_SIR2ILA_N_NEXT,.next_nodes =
608  {
609  [ILA_SIR2ILA_NEXT_DROP] = "error-drop"}
610 ,};
611 
613 {
614  .node_name = "sir-to-ila",.runs_before =
615  {
616 "ip6-lookup", 0},.feature_index = &ila_main.ila_sir2ila_feature_index,};
617 
618 int
620 {
621  ila_main_t *ilm = &ila_main;
622  ip6_main_t *im6 = &ip6_main;
623  BVT (clib_bihash_kv) kv, value;
624 
625  //Sanity check
626  if (args->type == ILA_TYPE_IID || args->type == ILA_TYPE_LUID)
627  {
628  if ((args->sir_address.as_u8[8] >> 5) != args->type)
629  {
630  clib_warning ("Incorrect SIR address (ILA type mismatch %d %d)",
631  args->sir_address.as_u8[8] >> 1, args->type);
632  return -1;
633  }
634  if (args->sir_address.as_u8[8] & 0x10)
635  {
636  clib_warning ("Checksum bit should not be set in SIR address");
637  return -1;
638  }
639  }
640  else if (args->type == ILA_TYPE_VNIDM)
641  {
642  if (args->sir_address.as_u8[0] != 0xff ||
643  (args->sir_address.as_u8[1] & 0xf0) != 0xf0)
644  {
645  clib_warning ("SIR multicast address must start with fff");
646  return -1;
647  }
648  if (args->sir_address.as_u16[1] || args->sir_address.as_u16[2] ||
649  args->sir_address.as_u16[3] || args->sir_address.as_u16[4] ||
650  args->sir_address.as_u16[5] || (args->sir_address.as_u8[12] & 0xf0))
651  {
652  clib_warning ("SIR multicast address must start with fff");
653  return -1;
654  }
655  }
656 
657  if (!args->is_del)
658  {
659  kv.key[0] = args->sir_address.as_u64[0];
660  kv.key[1] = args->sir_address.as_u64[1];
661  kv.key[2] = 0;
662 
663  if ((BV (clib_bihash_search) (&ilm->id_to_entry_table, &kv, &value) >=
664  0))
665  {
666  clib_warning ("Entry already exists");
667  return -1;
668  }
669 
670  ila_entry_t *e;
671  pool_get (ilm->entries, e);
672  e->type = args->type;
673  e->sir_address = args->sir_address;
674  e->ila_adj_index = args->local_adj_index;
675  e->csum_mode = args->csum_mode;
676  e->dir = args->dir;
677 
678  //Construct ILA address
679  switch (e->type)
680  {
681  case ILA_TYPE_IID:
682  e->ila_address = e->sir_address;
683  break;
684  case ILA_TYPE_LUID:
685  e->ila_address.as_u64[0] = args->locator;
686  e->ila_address.as_u64[1] = args->sir_address.as_u64[1];
687  break;
688  case ILA_TYPE_VNID6:
689  e->ila_address.as_u64[0] = args->locator;
690  e->ila_address.as_u8[8] = (ILA_TYPE_VNID6 << 1);
691  e->ila_address.as_u32[2] |= args->vnid;
692  e->ila_address.as_u32[3] = args->sir_address.as_u32[3];
693  break;
694  case ILA_TYPE_VNIDM:
695  e->ila_address.as_u64[0] = args->locator;
696  e->ila_address.as_u8[8] = (ILA_TYPE_VNIDM << 1);
697  e->ila_address.as_u32[2] |= args->vnid;
698  e->ila_address.as_u32[3] = args->sir_address.as_u32[3];
699  e->ila_address.as_u8[12] |= args->sir_address.as_u8[2] << 4;
700  break;
701  case ILA_TYPE_VNID4:
702  clib_warning ("ILA type '%U' is not supported", format_ila_type,
703  e->type);
704  return -1;
705  }
706 
707  //Modify ILA checksum if necessary
708  if (e->csum_mode == ILA_CSUM_MODE_NEUTRAL_MAP)
709  {
710  ip_csum_t csum = e->ila_address.as_u16[7];
711  int i;
712  for (i = 0; i < 4; i++)
713  {
714  csum = ip_csum_sub_even (csum, e->sir_address.as_u32[i]);
715  csum = ip_csum_add_even (csum, e->ila_address.as_u32[i]);
716  }
717  csum = ip_csum_add_even (csum, clib_host_to_net_u16 (0x1000));
718  e->ila_address.as_u16[7] = ip_csum_fold (csum);
719  e->ila_address.as_u8[8] |= 0x10;
720  }
721 
722  //Create entry with the sir address
723  kv.value = e - ilm->entries;
724  BV (clib_bihash_add_del) (&ilm->id_to_entry_table, &kv,
725  1 /* is_add */ );
726 
727  if (e->ila_adj_index != ~0)
728  {
729  //This is a local entry - let's create a local adjacency
730  ip_adjacency_t adj;
731  ip6_add_del_route_args_t route_args;
732  ila_adj_data_t *ad;
733 
734  //Adjacency
735  memset (&adj, 0, sizeof (adj));
736  adj.explicit_fib_index = ~0;
738  ad = (ila_adj_data_t *) & adj.opaque;
739  ad->entry_index = e - ilm->entries;
740 
741  //Route
742  memset (&route_args, 0, sizeof (route_args));
743  route_args.table_index_or_table_id = 0;
744  route_args.flags = IP6_ROUTE_FLAG_ADD;
745  route_args.dst_address = e->ila_address;
746  route_args.dst_address_length = 128;
747  route_args.adj_index = ~0;
748  route_args.add_adj = &adj;
749  route_args.n_add_adj = 1;
750 
751  ip6_add_del_route (im6, &route_args);
752  }
753  }
754  else
755  {
756  ila_entry_t *e;
757  kv.key[0] = args->sir_address.as_u64[0];
758  kv.key[1] = args->sir_address.as_u64[1];
759  kv.key[2] = 0;
760 
761  if ((BV (clib_bihash_search) (&ilm->id_to_entry_table, &kv, &value) <
762  0))
763  {
764  return -1;
765  }
766 
767  e = &ilm->entries[value.value];
768 
769  if (e->ila_adj_index != ~0)
770  {
771  //Delete that route - Associated adjacency will be deleted too
772  ip6_add_del_route_args_t route_args;
773  memset (&route_args, 0, sizeof (route_args));
774  route_args.table_index_or_table_id = 0;
775  route_args.flags = IP6_ROUTE_FLAG_DEL;
776  route_args.dst_address = e->ila_address;
777  route_args.dst_address_length = 128;
778  route_args.adj_index = ~0;
779  route_args.add_adj = NULL;
780  route_args.n_add_adj = 0;
781 
782  ip6_add_del_route (im6, &route_args);
783  }
784 
785  BV (clib_bihash_add_del) (&ilm->id_to_entry_table, &kv,
786  0 /* is_add */ );
787  pool_put (ilm->entries, e);
788  }
789  return 0;
790 }
791 
792 int
793 ila_interface (u32 sw_if_index, u8 disable)
794 {
795  vlib_main_t *vm = vlib_get_main ();
796  ila_main_t *ilm = &ila_main;
797  ip6_main_t *im = &ip6_main;
798  ip_lookup_main_t *lm = &im->lookup_main;
800  vnet_config_main_t *vcm = &cm->config_main;
801  u32 ci, feature_index;
802 
804  ci = cm->config_index_by_sw_if_index[sw_if_index];
805  feature_index = ilm->ila_sir2ila_feature_index;
806 
808  (vm, vcm, ci, feature_index,
809  /* config data */ 0,
810  /* # bytes of config data */ 0);
811 
812  cm->config_index_by_sw_if_index[sw_if_index] = ci;
813  return 0;
814 }
815 
816 clib_error_t *
818  int from_early_init)
819 {
820  clib_error_t *error = 0;
821 
822  return error;
823 }
824 
825 u8 *
826 ila_format_adjacency (u8 * s, va_list * va)
827 {
828  ila_main_t *ilm = &ila_main;
829  __attribute ((unused)) ip_lookup_main_t *lm =
830  va_arg (*va, ip_lookup_main_t *);
831  ip_adjacency_t *adj = va_arg (*va, ip_adjacency_t *);
832  ila_adj_data_t *ad = (ila_adj_data_t *) & adj->opaque;
834  return format (s, "idx:%d sir:%U", ad->entry_index, format_ip6_address,
835  &ie->sir_address);
836 }
837 
838 clib_error_t *
840 {
841  ila_main_t *ilm = &ila_main;
842  ilm->entries = NULL;
843 
845 
849 
851  "ila id to entry index table",
853 
854  return NULL;
855 }
856 
857 VNET_IP6_REGISTER_ADJACENCY (ila2sir) =
858 {
859 .node_name = "ila-to-sir",.fn = ila_format_adjacency,.next_index =
860  &ila_main.ip6_lookup_next_index};
861 
863 
864 static clib_error_t *
866  unformat_input_t * input, vlib_cli_command_t * cmd)
867 {
868  unformat_input_t _line_input, *line_input = &_line_input;
869  ila_add_del_entry_args_t args = { 0 };
870  ip6_address_t next_hop;
871  u8 next_hop_set = 0;
872  ip6_main_t *im6 = &ip6_main;
873  int ret;
874 
875  args.type = ILA_TYPE_IID;
876  args.csum_mode = ILA_CSUM_MODE_NO_ACTION;
877  args.local_adj_index = ~0;
878  args.dir = ILA_DIR_BIDIR;
879 
880  if (!unformat_user (input, unformat_line_input, line_input))
881  return 0;
882 
883  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
884  {
885  if (unformat (line_input, "type %U", unformat_ila_type, &args.type))
886  ;
887  else
888  if (unformat
889  (line_input, "sir-address %U", unformat_ip6_address,
890  &args.sir_address))
891  ;
892  else
893  if (unformat
894  (line_input, "locator %U", unformat_half_ip6_address,
895  &args.locator))
896  ;
897  else if (unformat (line_input, "adj-index %u", &args.local_adj_index))
898  ;
899  else
900  if (unformat
901  (line_input, "csum-mode %U", unformat_ila_csum_mode,
902  &args.csum_mode))
903  ;
904  else if (unformat (line_input, "vnid %x", &args.vnid))
905  ;
906  else
907  if (unformat
908  (line_input, "next-hop %U", unformat_ip6_address, &next_hop))
909  next_hop_set = 1;
910  else if (unformat
911  (line_input, "direction %U", unformat_ila_direction,
912  &args.dir))
913  ;
914  else if (unformat (line_input, "del"))
915  args.is_del = 1;
916  else
917  return clib_error_return (0, "parse error: '%U'",
918  format_unformat_error, line_input);
919  }
920 
921  unformat_free (line_input);
922 
923  if (next_hop_set)
924  {
925  if (args.local_adj_index != ~0)
926  return clib_error_return (0,
927  "Specified both next hop and adjacency index");
928 
929  u32 ai = ip6_get_route (im6, 0, 0, &next_hop, 128);
930  if (ai == 0)
931  return clib_error_return (0, "No route to next-hop %U",
932  format_ip6_address, &next_hop);
933 
935  ip_adjacency_t *adj6 = ip_get_adjacency (lm6, ai);
937  {
938  return clib_error_return (0,
939  "Next-Hop route has to be a rewrite route");
940  }
941  args.local_adj_index = ai;
942  }
943 
944  if ((ret = ila_add_del_entry (&args)))
945  return clib_error_return (0, "ila_add_del_entry returned error %d", ret);
946 
947  return NULL;
948 }
949 
950 /* *INDENT-OFF* */
951 /* Note VPP-417; this initializer has been modified temporarily to
952  * avoid macro expansion that the siphon CLI documentation parser
953  * doesn't understand.
954  * Removed macros: ila_type_list, ila_csum_list and ila_direction_list.
955  */
956 VLIB_CLI_COMMAND (ila_entry_command, static) =
957 {
958  .path = "ila entry",
959  .short_help = "ila entry [type (" "iid,luid,vnid-ip4,vnid-ip6,vnid-multicast" ")]"
960  " [sir-address <address>] [locator <locator>] [vnid <hex-vnid>]"
961  " [adj-index <adj-index>] [next-hop <next-hop>]"
962  " [direction (" "bidir,sir2ila,ila2sir" ")]"
963  " [csum-mode (" "no-action,neutral-map,adjust-transport" ")] [del]",
964  .function = ila_entry_command_fn,
965 };
966 /* *INDENT-ON* */
967 
968 static clib_error_t *
970  unformat_input_t * input, vlib_cli_command_t * cmd)
971 {
972  vnet_main_t *vnm = vnet_get_main ();
973  u32 sw_if_index = ~0;
974  u8 disable = 0;
975 
976  if (!unformat (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
977  {
978  return clib_error_return (0, "Invalid interface name");
979  }
980 
981  if (unformat (input, "disable"))
982  {
983  disable = 1;
984  }
985 
986  int ret;
987  if ((ret = ila_interface (sw_if_index, disable)))
988  return clib_error_return (0, "ila_interface returned error %d", ret);
989 
990  return NULL;
991 }
992 
993 VLIB_CLI_COMMAND (ila_interface_command, static) =
994 {
995 .path = "ila interface",.short_help =
996  "ila interface <interface-name> [disable]",.function =
998 
999 static clib_error_t *
1001  unformat_input_t * input,
1002  vlib_cli_command_t * cmd)
1003 {
1004  vnet_main_t *vnm = vnet_get_main ();
1005  ila_main_t *ilm = &ila_main;
1006  ila_entry_t *e;
1007 
1008  vlib_cli_output (vm, " %U\n", format_ila_entry, vnm, NULL);
1009  pool_foreach (e, ilm->entries, (
1010  {
1011  vlib_cli_output (vm, " %U\n",
1012  format_ila_entry, vnm, e);
1013  }));
1014 
1015  return NULL;
1016 }
1017 
1018 VLIB_CLI_COMMAND (ila_show_entries_command, static) =
1019 {
1020 .path = "show ila entries",.short_help = "show ila entries",.function =
u32 entry_index
Definition: ila.h:82
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:457
static u8 * format_ila_entry(u8 *s, va_list *va)
Definition: ila.c:118
ila_direction_t dir
Definition: ila.h:77
ip6_address_t initial_dst
Definition: ila.c:52
clib_bihash_24_8_t id_to_entry_table
Definition: ila.h:91
ila_direction_t dir
Definition: ila.h:107
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
#define CLIB_UNUSED(x)
Definition: clib.h:79
u32 * config_index_by_sw_if_index
Definition: lookup.h:369
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:966
ila_sir2ila_next_t
Definition: ila.c:400
ip6_address_t initial_dst
Definition: ila.c:409
a
Definition: bitmap.h:516
u32 current_config_index
Used by feature subgraph arcs to visit enabled feature nodes.
Definition: buffer.h:121
format_function_t format_ip6_address
Definition: format.h:87
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
u8 * format_half_ip6_address(u8 *s, va_list *va)
Definition: ila.c:63
ip_lookup_next_t lookup_next_index
Definition: lookup.h:180
#define PREDICT_TRUE(x)
Definition: clib.h:98
u8 as_u8[16]
Definition: ip6_packet.h:47
u64 as_u64[2]
Definition: ip6_packet.h:50
IP unicast adjacency.
Definition: lookup.h:164
Definitions for all things IP (v4|v6) unicast and multicast lookup related.
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
u8 * format_ila_sir2ila_trace(u8 *s, va_list *args)
Definition: ila.c:413
#define NULL
Definition: clib.h:55
u32 vnet_config_del_feature(vlib_main_t *vm, vnet_config_main_t *cm, u32 config_string_heap_index, u32 feature_index, void *feature_config, u32 n_feature_config_bytes)
Definition: config.c:300
Definition: ila.h:99
ip_config_main_t rx_config_mains[VNET_N_CAST]
rx/tx interface/feature configuration.
Definition: lookup.h:452
static uword unformat_ila_type(unformat_input_t *input, va_list *args)
Definition: ila.c:184
ip6_address_t ila_address
Definition: ila.h:74
struct _vlib_node_registration vlib_node_registration_t
uword ip_csum_t
Definition: ip_packet.h:86
static ila_main_t ila_main
Definition: ila.c:20
unformat_function_t unformat_vnet_sw_interface
u8 opaque[IP_ADJACENCY_OPAQUE_SZ]
Definition: lookup.h:204
ila_csum_mode_t
Definition: ila.h:48
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:200
clib_error_t * ila_init(vlib_main_t *vm)
Definition: ila.c:839
ip6_address_t sir_address
Definition: ila.h:73
int ila_add_del_entry(ila_add_del_entry_args_t *args)
Definition: ila.c:619
u8 * ila_format_adjacency(u8 *s, va_list *va)
Definition: ila.c:826
static clib_error_t * ila_entry_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ila.c:865
ila_ila2sir_next_t
Definition: ila.c:42
vnet_main_t * vnet_get_main(void)
Definition: misc.c:45
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:348
ila_type_t type
Definition: ila.h:72
int clib_bihash_add_del(clib_bihash *h, clib_bihash_kv *add_v, int is_add)
Add or delete a (key,value) pair from a bi-hash table.
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
#define ILA_TABLE_DEFAULT_HASH_NUM_BUCKETS
Definition: ila.c:22
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:187
u8 is_del
Definition: ila.h:108
static uword unformat_ila_direction(unformat_input_t *input, va_list *args)
Definition: ila.c:168
static void unformat_free(unformat_input_t *i)
Definition: format.h:161
#define clib_warning(format, args...)
Definition: error.h:59
u32 table_index_or_table_id
Definition: ip6.h:367
unsigned long u64
Definition: types.h:89
static ila_entry_t ila_sir2ila_default_entry
Definition: ila.c:56
u32 local_adj_index
Definition: ila.h:105
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:977
ila_direction_t
Definition: ila.h:63
static char * ila_error_strings[]
Definition: ila.c:36
void ip6_add_del_route(ip6_main_t *im, ip6_add_del_route_args_t *args)
Definition: ip6_forward.c:208
u64 lookup_table_nbuckets
Definition: ila.h:89
static uword unformat_half_ip6_address(unformat_input_t *input, va_list *args)
Definition: ila.c:222
static vlib_node_registration_t ila_ila2sir_node
(constructor) VLIB_REGISTER_NODE (ila_ila2sir_node)
Definition: ila.c:240
ip6_address_t dst_address
Definition: ip6.h:370
#define ila_csum_foreach_type
Definition: ila.h:41
Definition: ila.h:70
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:369
u32 vnid
Definition: ila.h:104
ip_adjacency_t * add_adj
Definition: ip6.h:379
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:214
static void * vnet_get_config_data(vnet_config_main_t *cm, u32 *config_index, u32 *next_index, u32 n_data_bytes)
Definition: config.h:122
u8 * format_ila_csum_mode(u8 *s, va_list *va)
Definition: ila.c:85
#define PREDICT_FALSE(x)
Definition: clib.h:97
ila_csum_mode_t csum_mode
Definition: ila.h:106
u32 ip6_get_route(ip6_main_t *im, u32 fib_index_or_table_id, u32 flags, ip6_address_t *address, u32 address_length)
Definition: ip6_forward.c:572
static clib_error_t * ila_show_entries_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ila.c:1000
#define vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next, n_left_to_next, bi0, bi1, next0, next1)
Finish enqueueing two buffers forward in the graph.
Definition: buffer_node.h:70
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
Definition: buffer_node.h:130
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:348
void clib_bihash_init(clib_bihash *h, char *name, u32 nbuckets, uword memory_size)
initialize a bounded index extensible hash table
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:575
u8 * format_ila_direction(u8 *s, va_list *args)
Definition: ila.c:73
unformat_function_t unformat_ip6_address
Definition: format.h:86
static vlib_node_registration_t ila_sir2ila_node
(constructor) VLIB_REGISTER_NODE (ila_sir2ila_node)
Definition: ila.c:423
BVT(clib_bihash)
Definition: l2_fib.c:577
u32 as_u32[4]
Definition: ip6_packet.h:49
ila_entry_t * entries
Definition: ila.h:87
u16 n_vectors
Definition: node.h:344
VNET_IP6_REGISTER_ADJACENCY(ila2sir)
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:82
u8 * format_ila_ila2sir_trace(u8 *s, va_list *args)
Definition: ila.c:156
#define IP6_ROUTE_FLAG_DEL
Definition: ip6.h:352
static uword ila_ila2sir(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ila.c:243
static clib_error_t * ila_interface_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ila.c:969
ila_type_t type
Definition: ila.h:101
u16 cached_next_index
Definition: node.h:462
u32 ila_sir2ila_feature_index
Definition: ila.h:93
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
#define vnet_buffer(b)
Definition: buffer.h:335
ip6_main_t ip6_main
Definition: ip6_forward.c:2955
ip_lookup_main_t lookup_main
Definition: ip6.h:110
int clib_bihash_search(clib_bihash *h, clib_bihash_kv *search_v, clib_bihash_kv *return_v)
Search a bi-hash table.
u64 lookup_table_size
Definition: ila.h:90
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:418
static ip_csum_t ip_csum_sub_even(ip_csum_t c, ip_csum_t x)
Definition: ip_packet.h:113
ip6_address_t sir_address
Definition: ila.h:102
Definition: ila.h:85
clib_error_t * vlib_plugin_register(vlib_main_t *vm, vnet_plugin_handoff_t *h, int from_early_init)
Definition: ila.c:817
u32 ila_adj_index
Definition: ila.h:75
u32 vnet_config_add_feature(vlib_main_t *vm, vnet_config_main_t *cm, u32 config_string_heap_index, u32 feature_index, void *feature_config, u32 n_feature_config_bytes)
Definition: config.c:239
u32 ip6_lookup_next_index
Definition: ila.h:95
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:93
u64 uword
Definition: types.h:112
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace_funcs.h:55
Definition: defs.h:47
VLIB_CLI_COMMAND(set_interface_ip_source_and_port_range_check_command, static)
unsigned char u8
Definition: types.h:56
static uword max_log2(uword x)
Definition: clib.h:222
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:251
#define IP_ADJACENCY_OPAQUE_SZ
Definition: lookup.h:160
u64 locator
Definition: ila.h:103
VNET_IP6_UNICAST_FEATURE_INIT(ila_sir2ila, static)
ila_error_t
Definition: ila.c:28
ila_csum_mode_t csum_mode
Definition: ila.h:76
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:163
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
u8 data[0]
Packet data.
Definition: buffer.h:151
This packet is to be rewritten and forwarded to the next processing node.
Definition: lookup.h:78
#define IP6_ROUTE_FLAG_ADD
Definition: ip6.h:351
ila_type_t
Definition: ila.h:34
i16 explicit_fib_index
Force re-lookup in a different FIB.
Definition: lookup.h:185
u16 as_u16[8]
Definition: ip6_packet.h:48
#define clib_error_return(e, args...)
Definition: error.h:111
struct _unformat_input_t unformat_input_t
#define foreach_ila_error
Definition: ila.c:25
static uword unformat_ila_csum_mode(unformat_input_t *input, va_list *args)
Definition: ila.c:200
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header, unspecified alignment)
Definition: vec.h:445
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:85
static uword ila_sir2ila(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ila.c:426
unformat_function_t unformat_line_input
Definition: format.h:281
u8 * format_ila_type(u8 *s, va_list *args)
Definition: ila.c:106
int ila_interface(u32 sw_if_index, u8 disable)
Definition: ila.c:793
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:69
#define ILA_TABLE_DEFAULT_HASH_MEMORY_SIZE
Definition: ila.c:23
vnet_config_main_t config_main
Definition: lookup.h:367
static u16 ip_csum_fold(ip_csum_t c)
Definition: ip_packet.h:138
static ip_csum_t ip_csum_add_even(ip_csum_t c, ip_csum_t x)
Definition: ip_packet.h:97
ip6_address_t dst_address
Definition: ip6_packet.h:298
static ip_adjacency_t * ip_get_adjacency(ip_lookup_main_t *lm, u32 adj_index)
Definition: lookup.h:480