FD.io VPP  v16.09
Vector Packet Processing
interface.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 <vppinfra/error.h>
17 #include <vppinfra/hash.h>
18 #include <vnet/vnet.h>
19 #include <vnet/ip/ip.h>
20 #include <vnet/ip/udp.h>
21 #include <vnet/ethernet/ethernet.h>
22 #include <vnet/lisp-gpe/lisp_gpe.h>
23 
24 #define foreach_lisp_gpe_tx_next \
25  _(DROP, "error-drop") \
26  _(IP4_LOOKUP, "ip4-lookup") \
27  _(IP6_LOOKUP, "ip6-lookup")
28 
29 typedef enum
30 {
31 #define _(sym,str) LISP_GPE_TX_NEXT_##sym,
33 #undef _
36 
37 typedef struct
38 {
41 
42 u8 *
43 format_lisp_gpe_tx_trace (u8 * s, va_list * args)
44 {
45  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
46  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
47  lisp_gpe_tx_trace_t *t = va_arg (*args, lisp_gpe_tx_trace_t *);
48 
49  s = format (s, "LISP-GPE-TX: tunnel %d", t->tunnel_index);
50  return s;
51 }
52 
53 always_inline void
55  lisp_gpe_tunnel_t ** t0, u8 is_v4)
56 {
57  u32 adj_index0, tunnel_index0;
58  ip_adjacency_t *adj0;
59 
60  /* Get adjacency and from it the tunnel_index */
61  adj_index0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX];
62 
63  if (is_v4)
64  adj0 = ip_get_adjacency (lgm->lm4, adj_index0);
65  else
66  adj0 = ip_get_adjacency (lgm->lm6, adj_index0);
67 
68  tunnel_index0 = adj0->if_address_index;
69  t0[0] = pool_elt_at_index (lgm->tunnels, tunnel_index0);
70 
71  ASSERT (t0[0] != 0);
72 }
73 
74 always_inline void
76  lisp_gpe_tunnel_t * t0, u32 * next0)
77 {
78  ASSERT (sizeof (ip4_udp_lisp_gpe_header_t) == 36);
79  ASSERT (sizeof (ip6_udp_lisp_gpe_header_t) == 56);
80 
82  u32 *sti0;
83 
85  vnet_buffer (b0)->ip.flow_hash %
87  st0 = vec_elt_at_index (t0->sub_tunnels, sti0[0]);
88  if (st0->is_ip4)
89  {
90  ip_udp_encap_one (lgm->vlib_main, b0, st0->rewrite, 36, 1);
91  next0[0] = LISP_GPE_TX_NEXT_IP4_LOOKUP;
92  }
93  else
94  {
95  ip_udp_encap_one (lgm->vlib_main, b0, st0->rewrite, 56, 0);
96  next0[0] = LISP_GPE_TX_NEXT_IP6_LOOKUP;
97  }
98 
99  /* Reset to look up tunnel partner in the configured FIB */
100  vnet_buffer (b0)->sw_if_index[VLIB_TX] = t0->encap_fib_index;
101 }
102 
103 always_inline void
105  vlib_buffer_t * b1, lisp_gpe_tunnel_t ** t0,
106  lisp_gpe_tunnel_t ** t1, u8 is_v4)
107 {
108  u32 adj_index0, adj_index1, tunnel_index0, tunnel_index1;
109  ip_adjacency_t *adj0, *adj1;
110 
111  /* Get adjacency and from it the tunnel_index */
112  adj_index0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX];
113  adj_index1 = vnet_buffer (b1)->ip.adj_index[VLIB_TX];
114 
115  if (is_v4)
116  {
117  adj0 = ip_get_adjacency (lgm->lm4, adj_index0);
118  adj1 = ip_get_adjacency (lgm->lm4, adj_index1);
119  }
120  else
121  {
122  adj0 = ip_get_adjacency (lgm->lm6, adj_index0);
123  adj1 = ip_get_adjacency (lgm->lm6, adj_index1);
124  }
125 
126  tunnel_index0 = adj0->if_address_index;
127  tunnel_index1 = adj1->if_address_index;
128 
129  t0[0] = pool_elt_at_index (lgm->tunnels, tunnel_index0);
130  t1[0] = pool_elt_at_index (lgm->tunnels, tunnel_index1);
131 
132  ASSERT (t0[0] != 0);
133  ASSERT (t1[0] != 0);
134 }
135 
136 always_inline void
138  vlib_buffer_t * b1, lisp_gpe_tunnel_t * t0,
139  lisp_gpe_tunnel_t * t1, u32 * next0, u32 * next1)
140 {
141  ASSERT (sizeof (ip4_udp_lisp_gpe_header_t) == 36);
142  ASSERT (sizeof (ip6_udp_lisp_gpe_header_t) == 56);
143 
144  lisp_gpe_sub_tunnel_t *st0, *st1;
145  u32 *sti0, *sti1;
146  sti0 = vec_elt_at_index (t0->sub_tunnels_lbv,
147  vnet_buffer (b0)->ip.flow_hash %
149  sti1 =
151  vnet_buffer (b1)->ip.flow_hash %
153  st0 = vec_elt_at_index (t0->sub_tunnels, sti0[0]);
154  st1 = vec_elt_at_index (t1->sub_tunnels, sti1[0]);
155 
156  if (PREDICT_TRUE (st0->is_ip4 == st1->is_ip4))
157  {
158  if (st0->is_ip4)
159  {
160  ip_udp_encap_one (lgm->vlib_main, b0, st0->rewrite, 36, 1);
161  ip_udp_encap_one (lgm->vlib_main, b1, st1->rewrite, 36, 1);
162  next0[0] = next1[0] = LISP_GPE_TX_NEXT_IP4_LOOKUP;
163  }
164  else
165  {
166  ip_udp_encap_one (lgm->vlib_main, b0, st0->rewrite, 56, 0);
167  ip_udp_encap_one (lgm->vlib_main, b1, st1->rewrite, 56, 0);
168  next0[0] = next1[0] = LISP_GPE_TX_NEXT_IP6_LOOKUP;
169  }
170  }
171  else
172  {
173  if (st0->is_ip4)
174  {
175  ip_udp_encap_one (lgm->vlib_main, b0, st0->rewrite, 36, 1);
176  ip_udp_encap_one (lgm->vlib_main, b1, st1->rewrite, 56, 1);
177  next0[0] = LISP_GPE_TX_NEXT_IP4_LOOKUP;
178  next1[0] = LISP_GPE_TX_NEXT_IP6_LOOKUP;
179  }
180  else
181  {
182  ip_udp_encap_one (lgm->vlib_main, b0, st0->rewrite, 56, 1);
183  ip_udp_encap_one (lgm->vlib_main, b1, st1->rewrite, 36, 1);
184  next0[0] = LISP_GPE_TX_NEXT_IP6_LOOKUP;
185  next1[0] = LISP_GPE_TX_NEXT_IP4_LOOKUP;
186  }
187  }
188 
189  /* Reset to look up tunnel partner in the configured FIB */
190  vnet_buffer (b0)->sw_if_index[VLIB_TX] = t0->encap_fib_index;
191  vnet_buffer (b1)->sw_if_index[VLIB_TX] = t1->encap_fib_index;
192 }
193 
194 #define is_v4_packet(_h) ((*(u8*) _h) & 0xF0) == 0x40
195 
196 static uword
198  vlib_frame_t * from_frame)
199 {
200  u32 n_left_from, next_index, *from, *to_next;
202 
203  from = vlib_frame_vector_args (from_frame);
204  n_left_from = from_frame->n_vectors;
205 
206  next_index = node->cached_next_index;
207 
208  while (n_left_from > 0)
209  {
210  u32 n_left_to_next;
211 
212  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
213 
214  while (n_left_from >= 4 && n_left_to_next >= 2)
215  {
216  u32 bi0, bi1;
217  vlib_buffer_t *b0, *b1;
218  u32 next0, next1;
219  lisp_gpe_tunnel_t *t0 = 0, *t1 = 0;
220  u8 is_v4_eid0, is_v4_eid1;
221 
222  next0 = next1 = LISP_GPE_TX_NEXT_IP4_LOOKUP;
223 
224  /* Prefetch next iteration. */
225  {
226  vlib_buffer_t *p2, *p3;
227 
228  p2 = vlib_get_buffer (vm, from[2]);
229  p3 = vlib_get_buffer (vm, from[3]);
230 
231  vlib_prefetch_buffer_header (p2, LOAD);
232  vlib_prefetch_buffer_header (p3, LOAD);
233 
234  CLIB_PREFETCH (p2->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
235  CLIB_PREFETCH (p3->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
236  }
237 
238  bi0 = from[0];
239  bi1 = from[1];
240  to_next[0] = bi0;
241  to_next[1] = bi1;
242  from += 2;
243  to_next += 2;
244  n_left_to_next -= 2;
245  n_left_from -= 2;
246 
247  b0 = vlib_get_buffer (vm, bi0);
248  b1 = vlib_get_buffer (vm, bi1);
249 
250  is_v4_eid0 = is_v4_packet (vlib_buffer_get_current (b0));
251  is_v4_eid1 = is_v4_packet (vlib_buffer_get_current (b1));
252 
253  if (PREDICT_TRUE (is_v4_eid0 == is_v4_eid1))
254  {
255  get_two_tunnels_inline (lgm, b0, b1, &t0, &t1,
256  is_v4_eid0 ? 1 : 0);
257  }
258  else
259  {
260  get_one_tunnel_inline (lgm, b0, &t0, is_v4_eid0 ? 1 : 0);
261  get_one_tunnel_inline (lgm, b1, &t1, is_v4_eid1 ? 1 : 0);
262  }
263 
264  encap_two_inline (lgm, b0, b1, t0, t1, &next0, &next1);
265 
267  {
268  lisp_gpe_tx_trace_t *tr = vlib_add_trace (vm, node, b0,
269  sizeof (*tr));
270  tr->tunnel_index = t0 - lgm->tunnels;
271  }
273  {
274  lisp_gpe_tx_trace_t *tr = vlib_add_trace (vm, node, b1,
275  sizeof (*tr));
276  tr->tunnel_index = t1 - lgm->tunnels;
277  }
278 
279  vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
280  n_left_to_next, bi0, bi1, next0,
281  next1);
282  }
283 
284  while (n_left_from > 0 && n_left_to_next > 0)
285  {
286  vlib_buffer_t *b0;
287  u32 bi0, next0 = LISP_GPE_TX_NEXT_IP4_LOOKUP;
288  lisp_gpe_tunnel_t *t0 = 0;
289  u8 is_v4_0;
290 
291  bi0 = from[0];
292  to_next[0] = bi0;
293  from += 1;
294  to_next += 1;
295  n_left_from -= 1;
296  n_left_to_next -= 1;
297 
298  b0 = vlib_get_buffer (vm, bi0);
299 
300  is_v4_0 = is_v4_packet (vlib_buffer_get_current (b0));
301  get_one_tunnel_inline (lgm, b0, &t0, is_v4_0 ? 1 : 0);
302 
303  encap_one_inline (lgm, b0, t0, &next0);
304 
306  {
307  lisp_gpe_tx_trace_t *tr = vlib_add_trace (vm, node, b0,
308  sizeof (*tr));
309  tr->tunnel_index = t0 - lgm->tunnels;
310  }
311  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
312  n_left_to_next, bi0, next0);
313  }
314 
315  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
316  }
317 
318  return from_frame->n_vectors;
319 }
320 
321 static u8 *
322 format_lisp_gpe_name (u8 * s, va_list * args)
323 {
324  u32 dev_instance = va_arg (*args, u32);
325  return format (s, "lisp_gpe%d", dev_instance);
326 }
327 
328 /* *INDENT-OFF* */
329 VNET_DEVICE_CLASS (lisp_gpe_device_class,static) = {
330  .name = "LISP_GPE",
331  .format_device_name = format_lisp_gpe_name,
332  .format_tx_trace = format_lisp_gpe_tx_trace,
333  .tx_function = lisp_gpe_interface_tx,
334  .no_flatten_output_chains = 1,
335 };
336 /* *INDENT-ON* */
337 
338 static uword
339 dummy_set_rewrite (vnet_main_t * vnm, u32 sw_if_index, u32 l3_type,
340  void *dst_address, void *rewrite, uword max_rewrite_bytes)
341 {
342  return 0;
343 }
344 
345 u8 *
347 {
348  lisp_gpe_header_t *h = va_arg (*args, lisp_gpe_header_t *);
349  u32 max_header_bytes = va_arg (*args, u32);
350  u32 header_bytes;
351 
352  header_bytes = sizeof (h[0]);
353  if (max_header_bytes != 0 && header_bytes > max_header_bytes)
354  return format (s, "lisp-gpe header truncated");
355 
356  s = format (s, "flags: ");
357 #define _(n,v) if (h->flags & v) s = format (s, "%s ", #n);
359 #undef _
360 
361  s = format (s, "\n ver_res %d res %d next_protocol %d iid %d(%x)",
362  h->ver_res, h->res, h->next_protocol,
363  clib_net_to_host_u32 (h->iid), clib_net_to_host_u32 (h->iid));
364  return s;
365 }
366 
367 /* *INDENT-OFF* */
368 VNET_HW_INTERFACE_CLASS (lisp_gpe_hw_class) = {
369  .name = "LISP_GPE",
370  .format_header = format_lisp_gpe_header_with_length,
371  .set_rewrite = dummy_set_rewrite,
372 };
373 /* *INDENT-ON* */
374 
375 int
376 add_del_ip_prefix_route (ip_prefix_t * dst_prefix, u32 table_id,
377  ip_adjacency_t * add_adj, u8 is_add, u32 * adj_index)
378 {
379  uword *p;
380 
381  if (ip_prefix_version (dst_prefix) == IP4)
382  {
383  ip4_main_t *im4 = &ip4_main;
385  ip4_address_t addr = ip_prefix_v4 (dst_prefix);
386 
387  memset (&a, 0, sizeof (a));
389  a.table_index_or_table_id = table_id;
390  a.adj_index = ~0;
391  a.dst_address_length = ip_prefix_len (dst_prefix);
392  a.dst_address = addr;
394  a.add_adj = add_adj;
395  a.n_add_adj = is_add ? 1 : 0;
396 
397  ip4_add_del_route (im4, &a);
398 
399  if (is_add)
400  {
401  p = ip4_get_route (im4, table_id, 0, addr.as_u8,
402  ip_prefix_len (dst_prefix));
403  if (p == 0)
404  {
405  clib_warning ("Failed to insert route for eid %U!",
407  ip_prefix_len (dst_prefix));
408  return -1;
409  }
410  adj_index[0] = p[0];
411  }
412  }
413  else
414  {
415  ip6_main_t *im6 = &ip6_main;
417  ip6_address_t addr = ip_prefix_v6 (dst_prefix);
418 
419  memset (&a, 0, sizeof (a));
421  a.table_index_or_table_id = table_id;
422  a.adj_index = ~0;
423  a.dst_address_length = ip_prefix_len (dst_prefix);
424  a.dst_address = addr;
426  a.add_adj = add_adj;
427  a.n_add_adj = is_add ? 1 : 0;
428 
429  ip6_add_del_route (im6, &a);
430 
431  if (is_add)
432  {
433  adj_index[0] = ip6_get_route (im6, table_id, 0, &addr,
434  ip_prefix_len (dst_prefix));
435  if (adj_index[0] == 0)
436  {
437  clib_warning ("Failed to insert route for eid %U!",
439  ip_prefix_len (dst_prefix));
440  return -1;
441  }
442  }
443  }
444  return 0;
445 }
446 
447 static void
448 add_del_lisp_gpe_default_route (u32 table_id, u8 is_v4, u8 is_add)
449 {
451  ip_adjacency_t adj;
452  ip_prefix_t prefix;
453  u32 adj_index = 0;
454 
455  /* setup adjacency */
456  memset (&adj, 0, sizeof (adj));
457 
458  adj.n_adj = 1;
459  adj.explicit_fib_index = ~0;
462  /* default route has tunnel_index ~0 */
463  adj.rewrite_header.sw_if_index = ~0;
464 
465  /* set prefix to 0/0 */
466  memset (&prefix, 0, sizeof (prefix));
467  ip_prefix_version (&prefix) = is_v4 ? IP4 : IP6;
468 
469  /* add/delete route for prefix */
470  add_del_ip_prefix_route (&prefix, table_id, &adj, is_add, &adj_index);
471 }
472 
473 static void
474 lisp_gpe_iface_set_table (u32 sw_if_index, u32 table_id, u8 is_ip4)
475 {
476  if (is_ip4)
477  {
478  ip4_main_t *im4 = &ip4_main;
479  ip4_fib_t *fib;
480  fib = find_ip4_fib_by_table_index_or_id (im4, table_id,
482 
483  /* fib's created if it doesn't exist */
484  ASSERT (fib != 0);
485 
486  vec_validate (im4->fib_index_by_sw_if_index, sw_if_index);
487  im4->fib_index_by_sw_if_index[sw_if_index] = fib->index;
488  }
489  else
490  {
491  ip6_main_t *im6 = &ip6_main;
492  ip6_fib_t *fib;
493  fib = find_ip6_fib_by_table_index_or_id (im6, table_id,
495 
496  /* fib's created if it doesn't exist */
497  ASSERT (fib != 0);
498 
499  vec_validate (im6->fib_index_by_sw_if_index, sw_if_index);
500  im6->fib_index_by_sw_if_index[sw_if_index] = fib->index;
501  }
502 }
503 
504 #define foreach_l2_lisp_gpe_tx_next \
505  _(DROP, "error-drop") \
506  _(IP4_LOOKUP, "ip4-lookup") \
507  _(IP6_LOOKUP, "ip6-lookup") \
508  _(LISP_CP_LOOKUP, "lisp-cp-lookup")
509 
510 typedef enum
511 {
512 #define _(sym,str) L2_LISP_GPE_TX_NEXT_##sym,
514 #undef _
517 
518 typedef struct
519 {
522 
523 u8 *
524 format_l2_lisp_gpe_tx_trace (u8 * s, va_list * args)
525 {
526  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
527  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
528  l2_lisp_gpe_tx_trace_t *t = va_arg (*args, l2_lisp_gpe_tx_trace_t *);
529 
530  s = format (s, "L2-LISP-GPE-TX: tunnel %d", t->tunnel_index);
531  return s;
532 }
533 
534 always_inline void
536 {
537  if (LISP_SEND_MAP_REQUEST == action)
538  {
539  next0[0] = L2_LISP_GPE_TX_NEXT_LISP_CP_LOOKUP;
540  vnet_buffer (b0)->lisp.overlay_afi = LISP_AFI_MAC;
541  }
542  else
543  {
544  next0[0] = L2_LISP_GPE_TX_NEXT_DROP;
545  }
546 }
547 
549 ip_flow_hash (void *data)
550 {
551  ip4_header_t *iph = (ip4_header_t *) data;
552 
553  if ((iph->ip_version_and_header_length & 0xF0) == 0x40)
555  else
557 }
558 
561 {
562  ethernet_header_t *eh;
563  u64 a, b, c;
564  uword is_ip, eh_size;
565  u16 eh_type;
566 
567  eh = vlib_buffer_get_current (b0);
568  eh_type = clib_net_to_host_u16 (eh->type);
569  eh_size = ethernet_buffer_header_size (b0);
570 
571  is_ip = (eh_type == ETHERNET_TYPE_IP4 || eh_type == ETHERNET_TYPE_IP6);
572 
573  /* since we have 2 cache lines, use them */
574  if (is_ip)
575  a = ip_flow_hash ((u8 *) vlib_buffer_get_current (b0) + eh_size);
576  else
577  a = eh->type;
578 
579  b = mac_to_u64 ((u8 *) eh->dst_address);
580  c = mac_to_u64 ((u8 *) eh->src_address);
581  hash_mix64 (a, b, c);
582 
583  return (u32) c;
584 }
585 
586 always_inline void
588  u32 * next0)
589 {
590  lisp_gpe_tunnel_t *t0;
591 
592  t0 = pool_elt_at_index (lgm->tunnels, ti0);
593  ASSERT (0 != t0);
594 
595  if (PREDICT_TRUE (LISP_NO_ACTION == t0->action))
596  {
597  /* compute 'flow' hash */
598  if (PREDICT_TRUE (t0->sub_tunnels_lbv_count > 1))
599  vnet_buffer (b0)->ip.flow_hash = l2_flow_hash (b0);
600  encap_one_inline (lgm, b0, t0, next0);
601  }
602  else
603  {
604  l2_process_tunnel_action (b0, t0->action, next0);
605  }
606 }
607 
608 always_inline void
610  u32 ti0, u32 ti1, u32 * next0, u32 * next1)
611 {
612  lisp_gpe_tunnel_t *t0, *t1;
613 
614  t0 = pool_elt_at_index (lgm->tunnels, ti0);
615  t1 = pool_elt_at_index (lgm->tunnels, ti1);
616 
617  ASSERT (0 != t0 && 0 != t1);
618 
620  && LISP_NO_ACTION == t1->action))
621  {
622  if (PREDICT_TRUE (t0->sub_tunnels_lbv_count > 1))
623  vnet_buffer (b0)->ip.flow_hash = l2_flow_hash (b0);
624  if (PREDICT_TRUE (t1->sub_tunnels_lbv_count > 1))
625  vnet_buffer (b1)->ip.flow_hash = l2_flow_hash (b1);
626  encap_two_inline (lgm, b0, b1, t0, t1, next0, next1);
627  }
628  else
629  {
630  if (LISP_NO_ACTION == t0->action)
631  {
632  if (PREDICT_TRUE (t0->sub_tunnels_lbv_count > 1))
633  vnet_buffer (b0)->ip.flow_hash = l2_flow_hash (b0);
634  encap_one_inline (lgm, b0, t0, next0);
635  l2_process_tunnel_action (b1, t1->action, next1);
636  }
637  else if (LISP_NO_ACTION == t1->action)
638  {
639  if (PREDICT_TRUE (t1->sub_tunnels_lbv_count > 1))
640  vnet_buffer (b1)->ip.flow_hash = l2_flow_hash (b1);
641  encap_one_inline (lgm, b1, t1, next1);
642  l2_process_tunnel_action (b0, t0->action, next0);
643  }
644  else
645  {
646  l2_process_tunnel_action (b0, t0->action, next0);
647  l2_process_tunnel_action (b1, t1->action, next1);
648  }
649  }
650 }
651 
652 static uword
654  vlib_frame_t * from_frame)
655 {
656  u32 n_left_from, next_index, *from, *to_next;
658 
659  from = vlib_frame_vector_args (from_frame);
660  n_left_from = from_frame->n_vectors;
661 
662  next_index = node->cached_next_index;
663 
664  while (n_left_from > 0)
665  {
666  u32 n_left_to_next;
667 
668  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
669 
670  while (n_left_from >= 4 && n_left_to_next >= 2)
671  {
672  u32 bi0, bi1;
673  vlib_buffer_t *b0, *b1;
674  u32 next0, next1, ti0, ti1;
675  lisp_gpe_tunnel_t *t0 = 0, *t1 = 0;
676  ethernet_header_t *e0, *e1;
677 
678  next0 = next1 = L2_LISP_GPE_TX_NEXT_LISP_CP_LOOKUP;
679 
680  /* Prefetch next iteration. */
681  {
682  vlib_buffer_t *p2, *p3;
683 
684  p2 = vlib_get_buffer (vm, from[2]);
685  p3 = vlib_get_buffer (vm, from[3]);
686 
687  vlib_prefetch_buffer_header (p2, LOAD);
688  vlib_prefetch_buffer_header (p3, LOAD);
689 
690  CLIB_PREFETCH (p2->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
691  CLIB_PREFETCH (p3->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
692  }
693 
694  bi0 = from[0];
695  bi1 = from[1];
696  to_next[0] = bi0;
697  to_next[1] = bi1;
698  from += 2;
699  to_next += 2;
700  n_left_to_next -= 2;
701  n_left_from -= 2;
702 
703  b0 = vlib_get_buffer (vm, bi0);
704  b1 = vlib_get_buffer (vm, bi1);
705 
706  e0 = vlib_buffer_get_current (b0);
707  e1 = vlib_buffer_get_current (b1);
708 
709  /* lookup dst + src mac */
710  ti0 = lisp_l2_fib_lookup (lgm, vnet_buffer (b0)->l2.bd_index,
711  e0->src_address, e0->dst_address);
712  ti1 = lisp_l2_fib_lookup (lgm, vnet_buffer (b1)->l2.bd_index,
713  e1->src_address, e1->dst_address);
714 
715  if (PREDICT_TRUE ((u32) ~ 0 != ti0) && (u32) ~ 0 != ti1)
716  {
717  /* process both tunnels */
718  l2_process_two (lgm, b0, b1, ti0, ti1, &next0, &next1);
719  }
720  else
721  {
722  if ((u32) ~ 0 != ti0)
723  {
724  /* process tunnel for b0 */
725  l2_process_one (lgm, b0, ti0, &next0);
726 
727  /* no tunnel found for b1, send to control plane */
728  next1 = L2_LISP_GPE_TX_NEXT_LISP_CP_LOOKUP;
729  vnet_buffer (b1)->lisp.overlay_afi = LISP_AFI_MAC;
730  }
731  else if ((u32) ~ 0 != ti1)
732  {
733  /* process tunnel for b1 */
734  l2_process_one (lgm, b1, ti1, &next1);
735 
736  /* no tunnel found b0, send to control plane */
737  next0 = L2_LISP_GPE_TX_NEXT_LISP_CP_LOOKUP;
738  vnet_buffer (b0)->lisp.overlay_afi = LISP_AFI_MAC;
739  }
740  else
741  {
742  /* no tunnels found */
743  next0 = L2_LISP_GPE_TX_NEXT_LISP_CP_LOOKUP;
744  vnet_buffer (b0)->lisp.overlay_afi = LISP_AFI_MAC;
745  next1 = L2_LISP_GPE_TX_NEXT_LISP_CP_LOOKUP;
746  vnet_buffer (b1)->lisp.overlay_afi = LISP_AFI_MAC;
747  }
748  }
749 
751  {
752  l2_lisp_gpe_tx_trace_t *tr = vlib_add_trace (vm, node, b0,
753  sizeof (*tr));
754  tr->tunnel_index = t0 - lgm->tunnels;
755  }
757  {
758  l2_lisp_gpe_tx_trace_t *tr = vlib_add_trace (vm, node, b1,
759  sizeof (*tr));
760  tr->tunnel_index = t1 - lgm->tunnels;
761  }
762 
763  vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
764  n_left_to_next, bi0, bi1, next0,
765  next1);
766  }
767 
768  while (n_left_from > 0 && n_left_to_next > 0)
769  {
770  vlib_buffer_t *b0;
771  u32 bi0, ti0, next0 = L2_LISP_GPE_TX_NEXT_LISP_CP_LOOKUP;
772  ethernet_header_t *e0;
773 
774  bi0 = from[0];
775  to_next[0] = bi0;
776  from += 1;
777  to_next += 1;
778  n_left_from -= 1;
779  n_left_to_next -= 1;
780 
781  b0 = vlib_get_buffer (vm, bi0);
782  e0 = vlib_buffer_get_current (b0);
783 
784  /* lookup dst + src mac */
785  ti0 = lisp_l2_fib_lookup (lgm, vnet_buffer (b0)->l2.bd_index,
786  e0->src_address, e0->dst_address);
787 
788  if (PREDICT_TRUE ((u32) ~ 0 != ti0))
789  {
790  l2_process_one (lgm, b0, ti0, &next0);
791  }
792  else
793  {
794  /* no tunnel found send to control plane */
795  next0 = L2_LISP_GPE_TX_NEXT_LISP_CP_LOOKUP;
796  vnet_buffer (b0)->lisp.overlay_afi = LISP_AFI_MAC;
797  }
798 
800  {
801  l2_lisp_gpe_tx_trace_t *tr = vlib_add_trace (vm, node, b0,
802  sizeof (*tr));
803  tr->tunnel_index = ti0 ? ti0 : ~0;
804  }
805  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
806  n_left_to_next, bi0, next0);
807  }
808 
809  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
810  }
811 
812  return from_frame->n_vectors;
813 }
814 
815 static u8 *
816 format_l2_lisp_gpe_name (u8 * s, va_list * args)
817 {
818  u32 dev_instance = va_arg (*args, u32);
819  return format (s, "l2_lisp_gpe%d", dev_instance);
820 }
821 
822 /* *INDENT-OFF* */
823 VNET_DEVICE_CLASS (l2_lisp_gpe_device_class,static) = {
824  .name = "L2_LISP_GPE",
825  .format_device_name = format_l2_lisp_gpe_name,
826  .format_tx_trace = format_lisp_gpe_tx_trace,
827  .tx_function = l2_lisp_gpe_interface_tx,
828  .no_flatten_output_chains = 1,
829 };
830 /* *INDENT-ON* */
831 
832 static vnet_hw_interface_t *
834  vnet_device_class_t * dev_class,
835  tunnel_lookup_t * tuns)
836 {
837  u32 flen;
838  u32 hw_if_index = ~0;
839  u8 *new_name;
841  vnet_main_t *vnm = lgm->vnet_main;
842 
843  /* create hw lisp_gpeX iface if needed, otherwise reuse existing */
844  flen = vec_len (lgm->free_tunnel_hw_if_indices);
845  if (flen > 0)
846  {
847  hw_if_index = lgm->free_tunnel_hw_if_indices[flen - 1];
848  _vec_len (lgm->free_tunnel_hw_if_indices) -= 1;
849 
850  hi = vnet_get_hw_interface (vnm, hw_if_index);
851 
852  /* rename interface */
853  new_name = format (0, "%U", dev_class->format_device_name, vni);
854 
855  vec_add1 (new_name, 0);
856  vnet_rename_interface (vnm, hw_if_index, (char *) new_name);
857  vec_free (new_name);
858 
859  /* clear old stats of freed interface before reuse */
864  hi->sw_if_index);
867  hi->sw_if_index);
870  hi->sw_if_index);
872  }
873  else
874  {
875  hw_if_index = vnet_register_interface (vnm, dev_class->index, vni,
876  lisp_gpe_hw_class.index, 0);
877  hi = vnet_get_hw_interface (vnm, hw_if_index);
878  }
879 
880  hash_set (tuns->hw_if_index_by_dp_table, dp_table, hw_if_index);
881 
882  /* set tunnel termination: post decap, packets are tagged as having been
883  * originated by lisp-gpe interface */
884  hash_set (tuns->sw_if_index_by_vni, vni, hi->sw_if_index);
885  hash_set (tuns->vni_by_sw_if_index, hi->sw_if_index, vni);
886 
887  return hi;
888 }
889 
890 static void
891 remove_lisp_gpe_iface (lisp_gpe_main_t * lgm, u32 hi_index, u32 dp_table,
892  tunnel_lookup_t * tuns)
893 {
894  vnet_main_t *vnm = lgm->vnet_main;
896  uword *vnip;
897 
898  hi = vnet_get_hw_interface (vnm, hi_index);
899 
900  /* disable interface */
901  vnet_sw_interface_set_flags (vnm, hi->sw_if_index, 0 /* down */ );
902  vnet_hw_interface_set_flags (vnm, hi->hw_if_index, 0 /* down */ );
903  hash_unset (tuns->hw_if_index_by_dp_table, dp_table);
905 
906  /* clean tunnel termination and vni to sw_if_index binding */
907  vnip = hash_get (tuns->vni_by_sw_if_index, hi->sw_if_index);
908  if (0 == vnip)
909  {
910  clib_warning ("No vni associated to interface %d", hi->sw_if_index);
911  return;
912  }
913  hash_unset (tuns->sw_if_index_by_vni, vnip[0]);
915 }
916 
917 static int
920 {
921  vnet_main_t *vnm = lgm->vnet_main;
922  tunnel_lookup_t *l3_ifaces = &lgm->l3_ifaces;
924  u32 lookup_next_index4, lookup_next_index6;
925  uword *hip, *si;
926 
927  hip = hash_get (l3_ifaces->hw_if_index_by_dp_table, a->table_id);
928 
929  if (a->is_add)
930  {
931  if (hip)
932  {
933  clib_warning ("vrf %d already mapped to a vni", a->table_id);
934  return -1;
935  }
936 
937  si = hash_get (l3_ifaces->sw_if_index_by_vni, a->vni);
938  if (si)
939  {
940  clib_warning ("Interface for vni %d already exists", a->vni);
941  return -1;
942  }
943 
944  /* create lisp iface and populate tunnel tables */
945  hi = create_lisp_gpe_iface (lgm, a->vni, a->table_id,
946  &lisp_gpe_device_class, l3_ifaces);
947 
948  /* set ingress arc from lgpe_ipX_lookup */
949  lookup_next_index4 = vlib_node_add_next (lgm->vlib_main,
950  lgpe_ip4_lookup_node.index,
951  hi->output_node_index);
952  lookup_next_index6 = vlib_node_add_next (lgm->vlib_main,
953  lgpe_ip6_lookup_node.index,
954  hi->output_node_index);
956  lookup_next_index4);
958  lookup_next_index6);
959 
960  /* insert default routes that point to lgpe-ipx-lookup */
961  add_del_lisp_gpe_default_route (a->table_id, /* is_v4 */ 1, 1);
962  add_del_lisp_gpe_default_route (a->table_id, /* is_v4 */ 0, 1);
963 
964  /* set egress arcs */
965 #define _(sym,str) vlib_node_add_named_next_with_slot (vnm->vlib_main, \
966  hi->tx_node_index, str, LISP_GPE_TX_NEXT_##sym);
968 #undef _
969  /* set interface in appropriate v4 and v6 FIBs */
972 
973  /* enable interface */
978  }
979  else
980  {
981  if (hip == 0)
982  {
983  clib_warning ("The interface for vrf %d doesn't exist",
984  a->table_id);
985  return -1;
986  }
987 
988  remove_lisp_gpe_iface (lgm, hip[0], a->table_id, &lgm->l3_ifaces);
989 
990  /* unset default routes */
991  add_del_lisp_gpe_default_route (a->table_id, /* is_v4 */ 1, 0);
992  add_del_lisp_gpe_default_route (a->table_id, /* is_v4 */ 0, 0);
993  }
994 
995  return 0;
996 }
997 
998 static int
1001 {
1002  vnet_main_t *vnm = lgm->vnet_main;
1003  tunnel_lookup_t *l2_ifaces = &lgm->l2_ifaces;
1005  uword *hip, *si;
1006  u16 bd_index;
1007 
1008  bd_index = bd_find_or_add_bd_index (&bd_main, a->bd_id);
1009  hip = hash_get (l2_ifaces->hw_if_index_by_dp_table, bd_index);
1010 
1011  if (a->is_add)
1012  {
1013  if (hip)
1014  {
1015  clib_warning ("bridge domain %d already mapped to a vni", a->bd_id);
1016  return -1;
1017  }
1018 
1019  si = hash_get (l2_ifaces->sw_if_index_by_vni, a->vni);
1020  if (si)
1021  {
1022  clib_warning ("Interface for vni %d already exists", a->vni);
1023  return -1;
1024  }
1025 
1026  /* create lisp iface and populate tunnel tables */
1027  hi = create_lisp_gpe_iface (lgm, a->vni, bd_index,
1028  &l2_lisp_gpe_device_class, &lgm->l2_ifaces);
1029 
1030  /* add iface to l2 bridge domain */
1032  bd_index, 0, 0, 0);
1033 
1034  /* set egress arcs */
1035 #define _(sym,str) vlib_node_add_named_next_with_slot (vnm->vlib_main, \
1036  hi->tx_node_index, str, L2_LISP_GPE_TX_NEXT_##sym);
1038 #undef _
1039  /* enable interface */
1044  }
1045  else
1046  {
1047  if (hip == 0)
1048  {
1049  clib_warning ("The interface for bridge domain %d doesn't exist",
1050  a->bd_id);
1051  return -1;
1052  }
1053  remove_lisp_gpe_iface (lgm, hip[0], bd_index, &lgm->l2_ifaces);
1054  }
1055 
1056  return 0;
1057 }
1058 
1059 int
1061  u32 * hw_if_indexp)
1062 {
1064 
1066  {
1067  clib_warning ("LISP is disabled!");
1068  return VNET_API_ERROR_LISP_DISABLED;
1069  }
1070 
1071  if (!a->is_l2)
1072  return lisp_gpe_add_del_l3_iface (lgm, a);
1073  else
1074  return lisp_gpe_add_del_l2_iface (lgm, a);
1075 }
1076 
1077 static clib_error_t *
1079  vlib_cli_command_t * cmd)
1080 {
1081  unformat_input_t _line_input, *line_input = &_line_input;
1082  u8 is_add = 1;
1083  clib_error_t *error = 0;
1084  int rv = 0;
1085  u32 table_id, vni, bd_id;
1086  u8 vni_is_set = 0, vrf_is_set = 0, bd_index_is_set = 0;
1087 
1089 
1090  /* Get a line of input. */
1091  if (!unformat_user (input, unformat_line_input, line_input))
1092  return 0;
1093 
1094  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1095  {
1096  if (unformat (line_input, "add"))
1097  is_add = 1;
1098  else if (unformat (line_input, "del"))
1099  is_add = 0;
1100  else if (unformat (line_input, "vrf %d", &table_id))
1101  {
1102  vrf_is_set = 1;
1103  }
1104  else if (unformat (line_input, "vni %d", &vni))
1105  {
1106  vni_is_set = 1;
1107  }
1108  else if (unformat (line_input, "bd %d", &bd_id))
1109  {
1110  bd_index_is_set = 1;
1111  }
1112  else
1113  {
1114  return clib_error_return (0, "parse error: '%U'",
1115  format_unformat_error, line_input);
1116  }
1117  }
1118 
1119  if (vrf_is_set && bd_index_is_set)
1120  return clib_error_return (0,
1121  "Cannot set both vrf and brdige domain index!");
1122 
1123  if (!vni_is_set)
1124  return clib_error_return (0, "vni must be set!");
1125 
1126  if (!vrf_is_set && !bd_index_is_set)
1127  return clib_error_return (0, "vrf or bridge domain index must be set!");
1128 
1129  a->is_add = is_add;
1130  a->dp_table = vrf_is_set ? table_id : bd_id;
1131  a->vni = vni;
1132  a->is_l2 = bd_index_is_set;
1133 
1134  rv = vnet_lisp_gpe_add_del_iface (a, 0);
1135  if (0 != rv)
1136  {
1137  error = clib_error_return (0, "failed to %s gpe iface!",
1138  is_add ? "add" : "delete");
1139  }
1140 
1141  return error;
1142 }
1143 
1144 /* *INDENT-OFF* */
1145 VLIB_CLI_COMMAND (add_del_lisp_gpe_iface_command, static) = {
1146  .path = "lisp gpe iface",
1147  .short_help = "lisp gpe iface add/del vni <vni> vrf <vrf>",
1149 };
1150 /* *INDENT-ON* */
1151 
1152 /*
1153  * fd.io coding-style-patch-verification: ON
1154  *
1155  * Local Variables:
1156  * eval: (c-set-style "gnu")
1157  * End:
1158  */
#define ip_prefix_v4(_a)
Definition: lisp_types.h:61
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:396
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
#define is_v4_packet(_h)
Definition: interface.c:194
ip4_fib_t * find_ip4_fib_by_table_index_or_id(ip4_main_t *im, u32 table_index_or_id, u32 flags)
Get or create an IPv4 fib.
Definition: ip4_forward.c:120
u32 * free_tunnel_hw_if_indices
Definition: lisp_gpe.h:181
vmrglw vmrglh hi
static void add_del_lisp_gpe_default_route(u32 table_id, u8 is_v4, u8 is_add)
Definition: interface.c:448
static u32 l2_flow_hash(vlib_buffer_t *b0)
Definition: interface.c:560
#define hash_set(h, key, value)
Definition: hash.h:254
#define CLIB_UNUSED(x)
Definition: clib.h:79
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:966
u32 ip4_lookup_next_lgpe_ip4_lookup
Definition: lisp_gpe.h:199
clib_error_t * vnet_hw_interface_set_flags(vnet_main_t *vnm, u32 hw_if_index, u32 flags)
Definition: interface.c:513
#define foreach_l2_lisp_gpe_tx_next
Definition: interface.c:504
#define hash_unset(h, key)
Definition: hash.h:260
a
Definition: bitmap.h:516
u8 vnet_lisp_gpe_enable_disable_status(void)
Definition: lisp_gpe.c:789
#define foreach_lisp_gpe_tx_next
Definition: interface.c:24
u16 n_adj
Number of adjecencies in block.
Definition: lookup.h:176
vnet_interface_main_t interface_main
Definition: vnet.h:64
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
IP unicast adjacency.
Definition: lookup.h:164
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
lisp_gpe_tunnel_t * tunnels
Definition: lisp_gpe.h:175
#define ethernet_buffer_header_size(b)
Determine the size of the Ethernet headers of the current frame in the buffer.
Definition: ethernet.h:358
u8 src_address[6]
Definition: packet.h:54
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
#define ip_prefix_len(_a)
Definition: lisp_types.h:60
static clib_error_t * lisp_gpe_add_del_iface_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: interface.c:1078
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:482
static u8 * format_lisp_gpe_name(u8 *s, va_list *args)
Definition: interface.c:322
u32 * fib_index_by_sw_if_index
Table index indexed by software interface.
Definition: ip4.h:123
#define VNET_HW_INTERFACE_FLAG_LINK_UP
Definition: interface.h:273
uword * lgpe_ip6_lookup_next_index_by_table_id
Definition: lisp_gpe.h:196
struct _vnet_device_class vnet_device_class_t
uword * vni_by_sw_if_index
Definition: lisp_gpe.h:169
#define ip_prefix_version(_a)
Definition: lisp_types.h:59
static uword vlib_node_add_next(vlib_main_t *vm, uword node, uword next_node)
Definition: node_funcs.h:1061
static vnet_hw_interface_t * create_lisp_gpe_iface(lisp_gpe_main_t *lgm, u32 vni, u32 dp_table, vnet_device_class_t *dev_class, tunnel_lookup_t *tuns)
Definition: interface.c:833
u8 * format_lisp_gpe_tx_trace(u8 *s, va_list *args)
Definition: interface.c:43
u32 index
Definition: ip4.h:62
vlib_main_t * vlib_main
Definition: lisp_gpe.h:211
u8 * format_l2_lisp_gpe_tx_trace(u8 *s, va_list *args)
Definition: interface.c:524
#define always_inline
Definition: clib.h:84
#define MODE_L2_BRIDGE
Definition: l2_input.h:216
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:187
vlib_combined_counter_main_t * combined_sw_if_counters
Definition: interface.h:501
u8 dst_address[6]
Definition: packet.h:53
ip6_fib_t * find_ip6_fib_by_table_index_or_id(ip6_main_t *im, u32 table_index_or_id, u32 flags)
Get or create an IPv6 fib.
Definition: ip6_forward.c:185
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
static foreach_gid_address_type_fcns u64 mac_to_u64(u8 *m)
Definition: lisp_types.h:242
#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
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:977
static int lisp_gpe_add_del_l3_iface(lisp_gpe_main_t *lgm, vnet_lisp_gpe_add_del_iface_args_t *a)
Definition: interface.c:918
static int lisp_gpe_add_del_l2_iface(lisp_gpe_main_t *lgm, vnet_lisp_gpe_add_del_iface_args_t *a)
Definition: interface.c:999
u32 vnet_register_interface(vnet_main_t *vnm, u32 dev_class_index, u32 dev_instance, u32 hw_class_index, u32 hw_instance)
Definition: interface.c:650
u8 * format_lisp_gpe_header_with_length(u8 *s, va_list *args)
Definition: interface.c:346
void ip6_add_del_route(ip6_main_t *im, ip6_add_del_route_args_t *args)
Definition: ip6_forward.c:208
u32 set_int_l2_mode(vlib_main_t *vm, vnet_main_t *vnet_main, u32 mode, u32 sw_if_index, u32 bd_index, u32 bvi, u32 shg, u32 xc_sw_if_index)
Set the subinterface to run in l2 or l3 mode.
Definition: l2_input.c:542
static void l2_process_one(lisp_gpe_main_t *lgm, vlib_buffer_t *b0, u32 ti0, u32 *next0)
Definition: interface.c:587
static void lisp_gpe_iface_set_table(u32 sw_if_index, u32 table_id, u8 is_ip4)
Definition: interface.c:474
ip6_address_t dst_address
Definition: ip6.h:370
#define hash_get(h, key)
Definition: hash.h:248
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:369
static void vlib_zero_combined_counter(vlib_combined_counter_main_t *cm, u32 index)
Clear a combined counter Clears the set of per-thread u16 counters, and the shared vlib_counter_t...
Definition: counter.h:321
u32 * sub_tunnels_lbv
Definition: lisp_gpe.h:87
u32 lisp_l2_fib_lookup(lisp_gpe_main_t *lgm, u16 bd_index, u8 src_mac[6], u8 dst_mac[6])
Definition: lisp_gpe.c:458
void * ip4_get_route(ip4_main_t *im, u32 fib_index_or_table_id, u32 flags, u8 *address, u32 address_length)
Definition: ip4_forward.c:537
#define ip_prefix_v6(_a)
Definition: lisp_types.h:62
ip_adjacency_t * add_adj
Definition: ip6.h:379
static u32 ip6_compute_flow_hash(ip6_header_t *ip, u32 flow_hash_config)
Definition: ip6.h:526
u32 ip6_lookup_next_lgpe_ip6_lookup
Definition: lisp_gpe.h:200
#define PREDICT_FALSE(x)
Definition: clib.h:97
static void get_two_tunnels_inline(lisp_gpe_main_t *lgm, vlib_buffer_t *b0, vlib_buffer_t *b1, lisp_gpe_tunnel_t **t0, lisp_gpe_tunnel_t **t1, u8 is_v4)
Definition: interface.c:104
static uword dummy_set_rewrite(vnet_main_t *vnm, u32 sw_if_index, u32 l3_type, void *dst_address, void *rewrite, uword max_rewrite_bytes)
Definition: interface.c:339
u32 index
Definition: ip6.h:69
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 void encap_two_inline(lisp_gpe_main_t *lgm, vlib_buffer_t *b0, vlib_buffer_t *b1, lisp_gpe_tunnel_t *t0, lisp_gpe_tunnel_t *t1, u32 *next0, u32 *next1)
Definition: interface.c:137
vlib_simple_counter_main_t * sw_if_counters
Definition: interface.h:500
static void ip_udp_encap_one(vlib_main_t *vm, vlib_buffer_t *b0, u8 *ec0, word ec_len, u8 is_ip4)
Definition: udp.h:118
#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
ip_adjacency_t * add_adj
Definition: ip4.h:337
uword * sw_if_index_by_vni
Definition: lisp_gpe.h:168
clib_error_t * vnet_rename_interface(vnet_main_t *vnm, u32 hw_if_index, char *new_name)
Definition: interface.c:1208
static void get_one_tunnel_inline(lisp_gpe_main_t *lgm, vlib_buffer_t *b0, lisp_gpe_tunnel_t **t0, u8 is_v4)
Definition: interface.c:54
u32 sub_tunnels_lbv_count
Definition: lisp_gpe.h:90
VNET_HW_INTERFACE_CLASS(ethernet_hw_interface_class)
#define hash_mix64(a0, b0, c0)
Definition: hash.h:496
svmdb_client_t * c
u16 n_vectors
Definition: node.h:344
vlib_node_registration_t lgpe_ip4_lookup_node
(constructor) VLIB_REGISTER_NODE (lgpe_ip4_lookup_node)
Definition: ip_forward.c:1029
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:82
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:300
static void l2_process_tunnel_action(vlib_buffer_t *b0, u8 action, u32 *next0)
Definition: interface.c:535
Definition: ip6.h:64
tunnel_lookup_t l2_ifaces
Definition: lisp_gpe.h:208
vnet_main_t * vnet_main
Definition: lisp_gpe.h:212
Definition: ip4.h:48
#define IP6_ROUTE_FLAG_DEL
Definition: ip6.h:352
static void vnet_interface_counter_unlock(vnet_interface_main_t *im)
Definition: interface.h:524
int vnet_lisp_gpe_add_del_iface(vnet_lisp_gpe_add_del_iface_args_t *a, u32 *hw_if_indexp)
Definition: interface.c:1060
lisp_gpe_main_t lisp_gpe_main
Definition: lisp_gpe.c:19
#define IP4_ROUTE_FLAG_DEL
Definition: ip4.h:309
static void vnet_interface_counter_lock(vnet_interface_main_t *im)
Definition: interface.h:516
u16 cached_next_index
Definition: node.h:462
#define VNET_SW_INTERFACE_FLAG_ADMIN_UP
Definition: interface.h:415
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
ip4_address_t dst_address
Definition: ip4.h:328
#define vnet_buffer(b)
Definition: buffer.h:335
#define IP4_ROUTE_FLAG_ADD
Definition: ip4.h:308
ip6_main_t ip6_main
Definition: ip6_forward.c:2955
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:418
IPv4 main type.
Definition: ip4.h:114
uword * hw_if_index_by_dp_table
Definition: lisp_gpe.h:165
vlib_node_registration_t lgpe_ip6_lookup_node
(constructor) VLIB_REGISTER_NODE (lgpe_ip6_lookup_node)
Definition: ip_forward.c:1323
static void vlib_zero_simple_counter(vlib_simple_counter_main_t *cm, u32 index)
Clear a simple counter Clears the set of per-thread u16 counters, and the u64 counter.
Definition: counter.h:143
#define IP_FLOW_HASH_DEFAULT
Default: 5-tuple without the "reverse" bit.
Definition: lookup.h:150
int add_del_ip_prefix_route(ip_prefix_t *dst_prefix, u32 table_id, ip_adjacency_t *add_adj, u8 is_add, u32 *adj_index)
Definition: interface.c:376
#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
static u32 ip_flow_hash(void *data)
Definition: interface.c:549
static uword l2_lisp_gpe_interface_tx(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: interface.c:653
Definition: defs.h:47
unsigned short u16
Definition: types.h:57
format_function_t format_ip6_address_and_length
Definition: format.h:88
VLIB_CLI_COMMAND(set_interface_ip_source_and_port_range_check_command, static)
u32 bd_find_or_add_bd_index(bd_main_t *bdm, u32 bd_id)
Get or create a bridge domain.
Definition: l2_bd.c:54
ip_lookup_main_t * lm4
Definition: lisp_gpe.h:215
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
tunnel_lookup_t l3_ifaces
Definition: lisp_gpe.h:192
static void l2_process_two(lisp_gpe_main_t *lgm, vlib_buffer_t *b0, vlib_buffer_t *b1, u32 ti0, u32 ti1, u32 *next0, u32 *next1)
Definition: interface.c:609
static void encap_one_inline(lisp_gpe_main_t *lgm, vlib_buffer_t *b0, lisp_gpe_tunnel_t *t0, u32 *next0)
Definition: interface.c:75
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:251
u32 table_index_or_table_id
Definition: ip4.h:325
Definition: lisp_types.h:24
static u32 ip4_compute_flow_hash(ip4_header_t *ip, u32 flow_hash_config)
Definition: ip4.h:452
#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
static uword lisp_gpe_interface_tx(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: interface.c:197
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1578
#define IP4_ROUTE_FLAG_TABLE_ID
Definition: ip4.h:310
u8 data[0]
Packet data.
Definition: buffer.h:151
#define IP6_ROUTE_FLAG_ADD
Definition: ip6.h:351
u32 if_address_index
Interface address index for this local/arp adjacency.
Definition: lookup.h:172
static void remove_lisp_gpe_iface(lisp_gpe_main_t *lgm, u32 hi_index, u32 dp_table, tunnel_lookup_t *tuns)
Definition: interface.c:891
i16 explicit_fib_index
Force re-lookup in a different FIB.
Definition: lookup.h:185
clib_error_t * vnet_sw_interface_set_flags(vnet_main_t *vnm, u32 sw_if_index, u32 flags)
Definition: interface.c:521
static u8 * format_l2_lisp_gpe_name(u8 *s, va_list *args)
Definition: interface.c:816
vhost_vring_addr_t addr
Definition: vhost-user.h:82
#define clib_error_return(e, args...)
Definition: error.h:111
VNET_DEVICE_CLASS(ethernet_simulated_device_class)
u8 ip_version_and_header_length
Definition: ip4_packet.h:108
#define IP6_ROUTE_FLAG_TABLE_ID
Definition: ip6.h:353
struct _unformat_input_t unformat_input_t
void ip4_add_del_route(ip4_main_t *im, ip4_add_del_route_args_t *args)
Definition: ip4_forward.c:228
ip_lookup_main_t * lm6
Definition: lisp_gpe.h:216
Definition: lisp_types.h:25
bd_main_t bd_main
Definition: l2_bd.c:35
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
format_function_t format_ip4_address_and_length
Definition: format.h:72
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:85
l2_lisp_gpe_tx_next_t
Definition: interface.c:510
lisp_gpe_tx_next_t
Definition: interface.c:29
unformat_function_t unformat_line_input
Definition: format.h:281
u32 * fib_index_by_sw_if_index
Definition: ip6.h:123
uword * lgpe_ip4_lookup_next_index_by_table_id
Definition: lisp_gpe.h:195
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
static ip_adjacency_t * ip_get_adjacency(ip_lookup_main_t *lm, u32 adj_index)
Definition: lookup.h:480
lisp_gpe_sub_tunnel_t * sub_tunnels
Definition: lisp_gpe.h:83