FD.io VPP  v19.08-23-g4b943d6
Vector Packet Processing
bfd_udp.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011-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  * @file
17  * @brief BFD UDP transport layer implementation
18  */
19 #include <vppinfra/types.h>
20 #include <vlibmemory/api.h>
21 #include <vlib/vlib.h>
22 #include <vlib/buffer.h>
23 #include <vnet/ip/format.h>
24 #include <vnet/ethernet/packet.h>
25 #include <vnet/udp/udp_packet.h>
26 #include <vnet/udp/udp.h>
27 #include <vnet/ip/lookup.h>
28 #include <vnet/ip/icmp46_packet.h>
29 #include <vnet/ip/ip4.h>
30 #include <vnet/ip/ip6.h>
31 #include <vnet/ip/ip6_packet.h>
32 #include <vnet/adj/adj.h>
33 #include <vnet/adj/adj_nbr.h>
34 #include <vnet/dpo/receive_dpo.h>
35 #include <vnet/fib/fib_entry.h>
36 #include <vnet/fib/fib_table.h>
37 #include <vnet/bfd/bfd_debug.h>
38 #include <vnet/bfd/bfd_udp.h>
39 #include <vnet/bfd/bfd_main.h>
40 #include <vnet/bfd/bfd_api.h>
41 
42 typedef struct
43 {
45  /* hashmap - bfd session index by bfd key - used for CLI/API lookup, where
46  * discriminator is unknown */
48  /* convenience variable */
50  /* flag indicating whether echo_source_sw_if_index holds a valid value */
52  /* loopback interface used to get echo source ip */
54  /* node index of "ip4-arp" node */
56  /* node index of "ip6-discover-neighbor" node */
58  /* node index of "ip4-rewrite" node */
60  /* node index of "ip6-rewrite" node */
62  /* node index of "ip4-midchain" node */
64  /* node index of "ip6-midchain" node */
66  /* log class */
68  /* number of active udp4 sessions */
70  /* number of active udp6 sessions */
73 
78 
80 
83 {
84  vnet_sw_interface_t *sw_if =
85  vnet_get_sw_interface_or_null (bfd_udp_main.vnet_main, sw_if_index);
86  if (sw_if)
87  {
88  bfd_udp_main.echo_source_sw_if_index = sw_if_index;
89  bfd_udp_main.echo_source_is_set = 1;
90  return 0;
91  }
92  return VNET_API_ERROR_BFD_ENOENT;
93 }
94 
97 {
98  bfd_udp_main.echo_source_sw_if_index = ~0;
99  bfd_udp_main.echo_source_is_set = 0;
100  return 0;
101 }
102 
103 int
105 {
106  if (!bfd_udp_main.echo_source_is_set)
107  {
108  BFD_DBG ("UDP echo source not set - echo not available");
109  return 0;
110  }
111  /*
112  * for the echo to work, we need a loopback interface with at least one
113  * address with netmask length at most 31 (ip4) or 127 (ip6) so that we can
114  * pick an unused address from that subnet
115  */
116  vnet_sw_interface_t *sw_if =
118  bfd_udp_main.echo_source_sw_if_index);
119  if (sw_if && sw_if->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)
120  {
121  if (BFD_TRANSPORT_UDP4 == transport)
122  {
123  ip4_main_t *im = &ip4_main;
125  /* *INDENT-OFF* */
127  bfd_udp_main.echo_source_sw_if_index,
128  0 /* honor unnumbered */, ({
129  if (ia->address_length <= 31)
130  {
131  return 1;
132  }
133  }));
134  /* *INDENT-ON* */
135  }
136  else if (BFD_TRANSPORT_UDP6 == transport)
137  {
138  ip6_main_t *im = &ip6_main;
140  /* *INDENT-OFF* */
142  bfd_udp_main.echo_source_sw_if_index,
143  0 /* honor unnumbered */, ({
144  if (ia->address_length <= 127)
145  {
146  return 1;
147  }
148  }));
149  /* *INDENT-ON* */
150  }
151  }
152  BFD_DBG ("No usable IP address for UDP echo - echo not available");
153  return 0;
154 }
155 
156 static u16
158 {
159  /* The source port MUST be in the range 49152 through 65535. The same UDP
160  * source port number MUST be used for all BFD Control packets associated
161  * with a particular session. The source port number SHOULD be unique among
162  * all BFD sessions on the system. If more than 16384 BFD sessions are
163  * simultaneously active, UDP source port numbers MAY be reused on
164  * multiple sessions, but the number of distinct uses of the same UDP
165  * source port number SHOULD be minimized.
166  */
167  return 49152 + bs_idx % (65535 - 49152 + 1);
168 }
169 
170 int
172 {
173  if (!bfd_udp_main.echo_source_is_set)
174  {
175  BFD_ERR ("cannot find ip4 address, echo source not set");
176  return 0;
177  }
179  ip4_main_t *im = &ip4_main;
180 
181  /* *INDENT-OFF* */
183  &im->lookup_main, ia, bfd_udp_main.echo_source_sw_if_index,
184  0 /* honor unnumbered */, ({
185  ip4_address_t *x =
186  ip_interface_address_get_address (&im->lookup_main, ia);
187  if (ia->address_length <= 31)
188  {
189  addr->as_u32 = clib_host_to_net_u32 (x->as_u32);
190  /*
191  * flip the last bit to get a different address, might be network,
192  * we don't care ...
193  */
194  addr->as_u32 ^= 1;
195  addr->as_u32 = clib_net_to_host_u32 (addr->as_u32);
196  return 1;
197  }
198  }));
199  /* *INDENT-ON* */
200  BFD_ERR ("cannot find ip4 address, no usable address found");
201  return 0;
202 }
203 
204 int
206 {
207  if (!bfd_udp_main.echo_source_is_set)
208  {
209  BFD_ERR ("cannot find ip6 address, echo source not set");
210  return 0;
211  }
213  ip6_main_t *im = &ip6_main;
214 
215  /* *INDENT-OFF* */
217  &im->lookup_main, ia, bfd_udp_main.echo_source_sw_if_index,
218  0 /* honor unnumbered */, ({
219  ip6_address_t *x =
220  ip_interface_address_get_address (&im->lookup_main, ia);
221  if (ia->address_length <= 127)
222  {
223  *addr = *x;
224  addr->as_u8[15] ^= 1; /* flip the last bit of the address */
225  return 1;
226  }
227  }));
228  /* *INDENT-ON* */
229  BFD_ERR ("cannot find ip6 address, no usable address found");
230  return 0;
231 }
232 
233 void
235  int *have_usable_ip4, ip4_address_t * ip4,
236  int *have_usable_ip6, ip6_address_t * ip6)
237 {
238  if (bfd_udp_main.echo_source_is_set)
239  {
240  *is_set = 1;
241  *sw_if_index = bfd_udp_main.echo_source_sw_if_index;
242  *have_usable_ip4 = bfd_udp_get_echo_src_ip4 (ip4);
243  *have_usable_ip6 = bfd_udp_get_echo_src_ip6 (ip6);
244  }
245  else
246  {
247  *is_set = 0;
248  }
249 }
250 
251 int
253  int is_echo)
254 {
255  const bfd_udp_session_t *bus = &bs->udp;
256  const bfd_udp_key_t *key = &bus->key;
257  vlib_buffer_t *b = vlib_get_buffer (vm, bi);
258 
259  b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
260  vnet_buffer (b)->ip.adj_index[VLIB_RX] = bus->adj_index;
261  vnet_buffer (b)->ip.adj_index[VLIB_TX] = bus->adj_index;
262  vnet_buffer (b)->sw_if_index[VLIB_RX] = 0;
263  vnet_buffer (b)->sw_if_index[VLIB_TX] = ~0;
264  typedef struct
265  {
266  ip4_header_t ip4;
267  udp_header_t udp;
268  } ip4_udp_headers;
269  ip4_udp_headers *headers = NULL;
270  vlib_buffer_advance (b, -sizeof (*headers));
271  headers = vlib_buffer_get_current (b);
272  clib_memset (headers, 0, sizeof (*headers));
273  headers->ip4.ip_version_and_header_length = 0x45;
274  headers->ip4.ttl = 255;
275  headers->ip4.protocol = IP_PROTOCOL_UDP;
276  headers->udp.src_port =
277  clib_host_to_net_u16 (bfd_udp_bs_idx_to_sport (bs->bs_idx));
278  if (is_echo)
279  {
280  int rv;
281  if (!(rv = bfd_udp_get_echo_src_ip4 (&headers->ip4.src_address)))
282  {
283  return rv;
284  }
285  headers->ip4.dst_address.as_u32 = key->local_addr.ip4.as_u32;
286  headers->udp.dst_port = clib_host_to_net_u16 (UDP_DST_PORT_bfd_echo4);
287  }
288  else
289  {
290  headers->ip4.src_address.as_u32 = key->local_addr.ip4.as_u32;
291  headers->ip4.dst_address.as_u32 = key->peer_addr.ip4.as_u32;
292  headers->udp.dst_port = clib_host_to_net_u16 (UDP_DST_PORT_bfd4);
293  }
294 
295  /* fix ip length, checksum and udp length */
296  const u16 ip_length = vlib_buffer_length_in_chain (vm, b);
297 
298  headers->ip4.length = clib_host_to_net_u16 (ip_length);
299  headers->ip4.checksum = ip4_header_checksum (&headers->ip4);
300 
301  const u16 udp_length = ip_length - (sizeof (headers->ip4));
302  headers->udp.length = clib_host_to_net_u16 (udp_length);
303  return 1;
304 }
305 
306 int
308  int is_echo)
309 {
310  const bfd_udp_session_t *bus = &bs->udp;
311  const bfd_udp_key_t *key = &bus->key;
312  vlib_buffer_t *b = vlib_get_buffer (vm, bi);
313 
314  b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
315  vnet_buffer (b)->ip.adj_index[VLIB_RX] = bus->adj_index;
316  vnet_buffer (b)->ip.adj_index[VLIB_TX] = bus->adj_index;
317  vnet_buffer (b)->sw_if_index[VLIB_RX] = 0;
318  vnet_buffer (b)->sw_if_index[VLIB_TX] = 0;
319  typedef struct
320  {
321  ip6_header_t ip6;
322  udp_header_t udp;
323  } ip6_udp_headers;
324  ip6_udp_headers *headers = NULL;
325  vlib_buffer_advance (b, -sizeof (*headers));
326  headers = vlib_buffer_get_current (b);
327  clib_memset (headers, 0, sizeof (*headers));
328  headers->ip6.ip_version_traffic_class_and_flow_label =
329  clib_host_to_net_u32 (0x6 << 28);
330  headers->ip6.hop_limit = 255;
331  headers->ip6.protocol = IP_PROTOCOL_UDP;
332  headers->udp.src_port =
333  clib_host_to_net_u16 (bfd_udp_bs_idx_to_sport (bs->bs_idx));
334  if (is_echo)
335  {
336  int rv;
337  if (!(rv = bfd_udp_get_echo_src_ip6 (&headers->ip6.src_address)))
338  {
339  return rv;
340  }
341  clib_memcpy_fast (&headers->ip6.dst_address, &key->local_addr.ip6,
342  sizeof (headers->ip6.dst_address));
343 
344  headers->udp.dst_port = clib_host_to_net_u16 (UDP_DST_PORT_bfd_echo6);
345  }
346  else
347  {
348  clib_memcpy_fast (&headers->ip6.src_address, &key->local_addr.ip6,
349  sizeof (headers->ip6.src_address));
350  clib_memcpy_fast (&headers->ip6.dst_address, &key->peer_addr.ip6,
351  sizeof (headers->ip6.dst_address));
352  headers->udp.dst_port = clib_host_to_net_u16 (UDP_DST_PORT_bfd6);
353  }
354 
355  /* fix ip payload length and udp length */
356  const u16 udp_length =
357  vlib_buffer_length_in_chain (vm, b) - (sizeof (headers->ip6));
358  headers->udp.length = clib_host_to_net_u16 (udp_length);
359  headers->ip6.payload_length = headers->udp.length;
360 
361  /* IPv6 UDP checksum is mandatory */
362  int bogus = 0;
363  headers->udp.checksum =
364  ip6_tcp_udp_icmp_compute_checksum (vm, b, &headers->ip6, &bogus);
365  ASSERT (bogus == 0);
366  if (headers->udp.checksum == 0)
367  {
368  headers->udp.checksum = 0xffff;
369  }
370  return 1;
371 }
372 
373 static void
375 {
376  vlib_frame_t *f = vlib_get_frame_to_node (vm, next_node);
377  u32 *to_next = vlib_frame_vector_args (f);
378  to_next[0] = bi;
379  f->n_vectors = 1;
380  vlib_put_frame_to_node (vm, next_node, f);
381 }
382 
383 int
384 bfd_udp_calc_next_node (const struct bfd_session_s *bs, u32 * next_node)
385 {
386  vnet_main_t *vnm = vnet_get_main ();
387  const bfd_udp_session_t *bus = &bs->udp;
388  ip_adjacency_t *adj = adj_get (bus->adj_index);
389 
390  /* don't try to send the buffer if the interface is not up */
391  if (!vnet_sw_interface_is_up (vnm, bus->key.sw_if_index))
392  return 0;
393 
394  switch (adj->lookup_next_index)
395  {
396  case IP_LOOKUP_NEXT_ARP:
397  switch (bs->transport)
398  {
399  case BFD_TRANSPORT_UDP4:
400  *next_node = bfd_udp_main.ip4_arp_idx;
401  return 1;
402  case BFD_TRANSPORT_UDP6:
403  *next_node = bfd_udp_main.ip6_ndp_idx;
404  return 1;
405  }
406  break;
408  switch (bs->transport)
409  {
410  case BFD_TRANSPORT_UDP4:
411  *next_node = bfd_udp_main.ip4_rewrite_idx;
412  return 1;
413  case BFD_TRANSPORT_UDP6:
414  *next_node = bfd_udp_main.ip6_rewrite_idx;
415  return 1;
416  }
417  break;
419  switch (bs->transport)
420  {
421  case BFD_TRANSPORT_UDP4:
422  *next_node = bfd_udp_main.ip4_midchain_idx;
423  return 1;
424  case BFD_TRANSPORT_UDP6:
425  *next_node = bfd_udp_main.ip6_midchain_idx;
426  return 1;
427  }
428  break;
429  default:
430  /* drop */
431  break;
432  }
433  return 0;
434 }
435 
436 int
438 {
439  u32 next_node;
440  int rv = bfd_udp_calc_next_node (bs, &next_node);
441  if (rv)
442  {
443  bfd_create_frame_to_next_node (vm, bi, next_node);
444  }
445  return rv;
446 }
447 
448 int
450 {
451  u32 next_node;
452  int rv = bfd_udp_calc_next_node (bs, &next_node);
453  if (rv)
454  {
455  bfd_create_frame_to_next_node (vm, bi, next_node);
456  }
457  return 1;
458 }
459 
460 static bfd_session_t *
461 bfd_lookup_session (bfd_udp_main_t * bum, const bfd_udp_key_t * key)
462 {
463  uword *p = mhash_get (&bum->bfd_session_idx_by_bfd_key, key);
464  if (p)
465  {
466  return bfd_find_session_by_idx (bum->bfd_main, *p);
467  }
468  return 0;
469 }
470 
471 static void
473  const ip46_address_t * local_addr,
474  const ip46_address_t * peer_addr)
475 {
476  clib_memset (key, 0, sizeof (*key));
477  key->sw_if_index = sw_if_index;
478  key->local_addr.as_u64[0] = local_addr->as_u64[0];
479  key->local_addr.as_u64[1] = local_addr->as_u64[1];
480  key->peer_addr.as_u64[0] = peer_addr->as_u64[0];
481  key->peer_addr.as_u64[1] = peer_addr->as_u64[1];
482 }
483 
484 static vnet_api_error_t
486  u32 sw_if_index, u32 desired_min_tx_usec,
487  u32 required_min_rx_usec, u8 detect_mult,
488  const ip46_address_t * local_addr,
489  const ip46_address_t * peer_addr,
490  bfd_session_t ** bs_out)
491 {
492  /* get a pool entry and if we end up not needing it, give it back */
493  bfd_transport_e t = BFD_TRANSPORT_UDP4;
494  if (!ip46_address_is_ip4 (local_addr))
495  {
496  t = BFD_TRANSPORT_UDP6;
497  }
498  bfd_session_t *bs = bfd_get_session (bum->bfd_main, t);
499  if (!bs)
500  {
501  return VNET_API_ERROR_BFD_EAGAIN;
502  }
503  bfd_udp_session_t *bus = &bs->udp;
504  clib_memset (bus, 0, sizeof (*bus));
505  bfd_udp_key_t *key = &bus->key;
506  bfd_udp_key_init (key, sw_if_index, local_addr, peer_addr);
507  const bfd_session_t *tmp = bfd_lookup_session (bum, key);
508  if (tmp)
509  {
510  vlib_log_err (bum->log_class,
511  "duplicate bfd-udp session, existing bs_idx=%d",
512  tmp->bs_idx);
513  bfd_put_session (bum->bfd_main, bs);
514  return VNET_API_ERROR_BFD_EEXIST;
515  }
516  mhash_set (&bum->bfd_session_idx_by_bfd_key, key, bs->bs_idx, NULL);
517  BFD_DBG ("session created, bs_idx=%u, sw_if_index=%d, local=%U, peer=%U",
518  bs->bs_idx, key->sw_if_index, format_ip46_address,
519  &key->local_addr, IP46_TYPE_ANY, format_ip46_address,
520  &key->peer_addr, IP46_TYPE_ANY);
521  vlib_log_info (bum->log_class, "create BFD session: %U",
522  format_bfd_session, bs);
523  if (BFD_TRANSPORT_UDP4 == t)
524  {
526  &key->peer_addr,
527  key->sw_if_index);
528  BFD_DBG ("adj_nbr_add_or_lock(FIB_PROTOCOL_IP4, VNET_LINK_IP4, %U, %d) "
529  "returns %d", format_ip46_address, &key->peer_addr,
530  IP46_TYPE_ANY, key->sw_if_index, bus->adj_index);
531  ++bum->udp4_sessions_count;
532  if (1 == bum->udp4_sessions_count)
533  {
534  udp_register_dst_port (vm, UDP_DST_PORT_bfd4,
535  bfd_udp4_input_node.index, 1);
536  udp_register_dst_port (vm, UDP_DST_PORT_bfd_echo4,
537  bfd_udp_echo4_input_node.index, 1);
538  }
539  }
540  else
541  {
543  &key->peer_addr,
544  key->sw_if_index);
545  BFD_DBG ("adj_nbr_add_or_lock(FIB_PROTOCOL_IP6, VNET_LINK_IP6, %U, %d) "
546  "returns %d", format_ip46_address, &key->peer_addr,
547  IP46_TYPE_ANY, key->sw_if_index, bus->adj_index);
548  ++bum->udp6_sessions_count;
549  if (1 == bum->udp6_sessions_count)
550  {
551  udp_register_dst_port (vm, UDP_DST_PORT_bfd6,
552  bfd_udp6_input_node.index, 0);
553  udp_register_dst_port (vm, UDP_DST_PORT_bfd_echo6,
554  bfd_udp_echo6_input_node.index, 0);
555  }
556  }
557  *bs_out = bs;
558  return bfd_session_set_params (bum->bfd_main, bs, desired_min_tx_usec,
559  required_min_rx_usec, detect_mult);
560 }
561 
562 static vnet_api_error_t
564  const ip46_address_t * local_addr,
565  const ip46_address_t * peer_addr)
566 {
568  vnet_sw_interface_t *sw_if =
569  vnet_get_sw_interface_or_null (bfd_udp_main.vnet_main, sw_if_index);
570  u8 local_ip_valid = 0;
572  if (!sw_if)
573  {
574  vlib_log_err (bum->log_class,
575  "got NULL sw_if when getting interface by index %u",
576  sw_if_index);
577  return VNET_API_ERROR_INVALID_SW_IF_INDEX;
578  }
579  if (ip46_address_is_ip4 (local_addr))
580  {
581  if (!ip46_address_is_ip4 (peer_addr))
582  {
583  vlib_log_err (bum->log_class,
584  "IP family mismatch (local is ipv4, peer is ipv6)");
585  return VNET_API_ERROR_INVALID_ARGUMENT;
586  }
587  ip4_main_t *im = &ip4_main;
588 
589  /* *INDENT-OFF* */
591  &im->lookup_main, ia, sw_if_index, 0 /* honor unnumbered */, ({
592  ip4_address_t *x =
593  ip_interface_address_get_address (&im->lookup_main, ia);
594  if (x->as_u32 == local_addr->ip4.as_u32)
595  {
596  /* valid address for this interface */
597  local_ip_valid = 1;
598  break;
599  }
600  }));
601  /* *INDENT-ON* */
602  }
603  else
604  {
605  if (ip46_address_is_ip4 (peer_addr))
606  {
607  vlib_log_err (bum->log_class,
608  "IP family mismatch (local is ipv6, peer is ipv4)");
609  return VNET_API_ERROR_INVALID_ARGUMENT;
610  }
611  ip6_main_t *im = &ip6_main;
612  /* *INDENT-OFF* */
614  &im->lookup_main, ia, sw_if_index, 0 /* honor unnumbered */, ({
615  ip6_address_t *x =
616  ip_interface_address_get_address (&im->lookup_main, ia);
617  if (local_addr->ip6.as_u64[0] == x->as_u64[0] &&
618  local_addr->ip6.as_u64[1] == x->as_u64[1])
619  {
620  /* valid address for this interface */
621  local_ip_valid = 1;
622  break;
623  }
624  }));
625  /* *INDENT-ON* */
626  }
627 
628  if (!local_ip_valid)
629  {
630  vlib_log_err (bum->log_class,
631  "local address %U not found on interface with index %u",
632  format_ip46_address, local_addr, IP46_TYPE_ANY,
633  sw_if_index);
634  return VNET_API_ERROR_ADDRESS_NOT_FOUND_FOR_INTERFACE;
635  }
636 
637  return 0;
638 }
639 
640 static vnet_api_error_t
642  const ip46_address_t * local_addr,
643  const ip46_address_t * peer_addr,
644  bfd_session_t ** bs_out)
645 {
646  vnet_api_error_t rv =
647  bfd_udp_validate_api_input (sw_if_index, local_addr, peer_addr);
648  if (!rv)
649  {
651  bfd_udp_key_t key;
652  bfd_udp_key_init (&key, sw_if_index, local_addr, peer_addr);
653  bfd_session_t *bs = bfd_lookup_session (bum, &key);
654  if (bs)
655  {
656  *bs_out = bs;
657  }
658  else
659  {
660  vlib_log_err (bum->log_class,
661  "BFD session not found, sw_if_index=%u, local=%U, peer=%U",
662  sw_if_index, format_ip46_address, local_addr,
664  IP46_TYPE_ANY);
665  return VNET_API_ERROR_BFD_ENOENT;
666  }
667  }
668  return rv;
669 }
670 
671 static vnet_api_error_t
672 bfd_api_verify_common (u32 sw_if_index, u32 desired_min_tx_usec,
673  u32 required_min_rx_usec, u8 detect_mult,
674  const ip46_address_t * local_addr,
675  const ip46_address_t * peer_addr)
676 {
678  vnet_api_error_t rv =
679  bfd_udp_validate_api_input (sw_if_index, local_addr, peer_addr);
680  if (rv)
681  {
682  return rv;
683  }
684  if (detect_mult < 1)
685  {
686  vlib_log_err (bum->log_class, "detect_mult < 1");
687  return VNET_API_ERROR_INVALID_ARGUMENT;
688  }
689  if (desired_min_tx_usec < 1)
690  {
691  vlib_log_err (bum->log_class, "desired_min_tx_usec < 1");
692  return VNET_API_ERROR_INVALID_ARGUMENT;
693  }
694  return 0;
695 }
696 
697 static void
699 {
701  BFD_DBG ("free bfd-udp session, bs_idx=%d", bs->bs_idx);
703  adj_unlock (bs->udp.adj_index);
704  switch (bs->transport)
705  {
706  case BFD_TRANSPORT_UDP4:
707  --bum->udp4_sessions_count;
708  if (!bum->udp4_sessions_count)
709  {
710  udp_unregister_dst_port (vm, UDP_DST_PORT_bfd4, 1);
711  udp_unregister_dst_port (vm, UDP_DST_PORT_bfd_echo4, 1);
712  }
713  break;
714  case BFD_TRANSPORT_UDP6:
715  --bum->udp6_sessions_count;
716  if (!bum->udp6_sessions_count)
717  {
718  udp_unregister_dst_port (vm, UDP_DST_PORT_bfd6, 0);
719  udp_unregister_dst_port (vm, UDP_DST_PORT_bfd_echo6, 0);
720  }
721  break;
722  }
723  bfd_put_session (bum->bfd_main, bs);
724 }
725 
727 bfd_udp_add_session (u32 sw_if_index, const ip46_address_t * local_addr,
728  const ip46_address_t * peer_addr,
729  u32 desired_min_tx_usec, u32 required_min_rx_usec,
730  u8 detect_mult, u8 is_authenticated, u32 conf_key_id,
731  u8 bfd_key_id)
732 {
733  bfd_main_t *bm = &bfd_main;
734  bfd_lock (bm);
735 
736  vnet_api_error_t rv =
737  bfd_api_verify_common (sw_if_index, desired_min_tx_usec,
738  required_min_rx_usec, detect_mult,
739  local_addr, peer_addr);
740  bfd_session_t *bs = NULL;
741  if (!rv)
742  {
743  rv =
744  bfd_udp_add_session_internal (vlib_get_main (), &bfd_udp_main,
745  sw_if_index, desired_min_tx_usec,
746  required_min_rx_usec, detect_mult,
747  local_addr, peer_addr, &bs);
748  }
749  if (!rv && is_authenticated)
750  {
751 #if WITH_LIBSSL > 0
752  rv = bfd_auth_activate (bs, conf_key_id, bfd_key_id,
753  0 /* is not delayed */ );
754 #else
755  vlib_log_err (bfd_udp_main.log_class,
756  "SSL missing, cannot add authenticated BFD session");
757  rv = VNET_API_ERROR_BFD_NOTSUPP;
758 #endif
759  if (rv)
760  {
762  }
763  }
764  if (!rv)
765  {
766  bfd_session_start (bfd_udp_main.bfd_main, bs);
767  }
768 
769  bfd_unlock (bm);
770  return rv;
771 }
772 
775  const ip46_address_t * local_addr,
776  const ip46_address_t * peer_addr,
777  u32 desired_min_tx_usec,
778  u32 required_min_rx_usec, u8 detect_mult)
779 {
780  bfd_session_t *bs = NULL;
781  bfd_main_t *bm = &bfd_main;
782  vnet_api_error_t error;
783  bfd_lock (bm);
784  vnet_api_error_t rv =
785  bfd_udp_find_session_by_api_input (sw_if_index, local_addr, peer_addr,
786  &bs);
787  if (rv)
788  {
789  bfd_unlock (bm);
790  return rv;
791  }
792 
793  error = bfd_session_set_params (bfd_udp_main.bfd_main, bs,
794  desired_min_tx_usec, required_min_rx_usec,
795  detect_mult);
796  bfd_unlock (bm);
797  return error;
798 }
799 
802  const ip46_address_t * local_addr,
803  const ip46_address_t * peer_addr)
804 {
805  bfd_session_t *bs = NULL;
806  bfd_main_t *bm = &bfd_main;
807  bfd_lock (bm);
808  vnet_api_error_t rv =
809  bfd_udp_find_session_by_api_input (sw_if_index, local_addr, peer_addr,
810  &bs);
811  if (rv)
812  {
813  bfd_unlock (bm);
814  return rv;
815  }
817  bfd_unlock (bm);
818  return 0;
819 }
820 
823  const ip46_address_t * local_addr,
824  const ip46_address_t * peer_addr, u8 admin_up_down)
825 {
826  bfd_session_t *bs = NULL;
827  bfd_main_t *bm = &bfd_main;
828  bfd_lock (bm);
829  vnet_api_error_t rv =
830  bfd_udp_find_session_by_api_input (sw_if_index, local_addr, peer_addr,
831  &bs);
832  if (rv)
833  {
834  bfd_unlock (bm);
835  return rv;
836  }
837  bfd_session_set_flags (bs, admin_up_down);
838  bfd_unlock (bm);
839  return 0;
840 }
841 
844  const ip46_address_t * local_addr,
845  const ip46_address_t * peer_addr,
846  u32 conf_key_id, u8 key_id, u8 is_delayed)
847 {
848  bfd_main_t *bm = &bfd_main;
849  bfd_lock (bm);
850  vnet_api_error_t error;
851 
852 #if WITH_LIBSSL > 0
853  bfd_session_t *bs = NULL;
854  vnet_api_error_t rv =
855  bfd_udp_find_session_by_api_input (sw_if_index, local_addr, peer_addr,
856  &bs);
857  if (rv)
858  {
859  bfd_unlock (bm);
860  return rv;
861  }
862  error = bfd_auth_activate (bs, conf_key_id, key_id, is_delayed);
863  bfd_unlock (bm);
864  return error;
865 #else
866  vlib_log_err (bfd_udp_main->log_class,
867  "SSL missing, cannot activate BFD authentication");
868  bfd_unlock (bm);
869  return VNET_API_ERROR_BFD_NOTSUPP;
870 #endif
871 }
872 
875  const ip46_address_t * local_addr,
876  const ip46_address_t * peer_addr, u8 is_delayed)
877 {
878  bfd_main_t *bm = &bfd_main;
879  vnet_api_error_t error;
880  bfd_lock (bm);
881  bfd_session_t *bs = NULL;
882  vnet_api_error_t rv =
883  bfd_udp_find_session_by_api_input (sw_if_index, local_addr, peer_addr,
884  &bs);
885  if (rv)
886  {
887  bfd_unlock (bm);
888  return rv;
889  }
890  error = bfd_auth_deactivate (bs, is_delayed);
891  bfd_unlock (bm);
892  return error;
893 }
894 
895 typedef enum
896 {
903 
904 /* Packet counters - BFD control frames */
905 #define foreach_bfd_udp_error(F) \
906  F (NONE, "good bfd packets (processed)") \
907  F (BAD, "invalid bfd packets")
908 
909 #define F(sym, string) static char BFD_UDP_ERR_##sym##_STR[] = string;
911 #undef F
912 
913 static char *bfd_udp_error_strings[] = {
914 #define F(sym, string) BFD_UDP_ERR_##sym##_STR,
916 #undef F
917 };
918 
919 typedef enum
920 {
921 #define F(sym, str) BFD_UDP_ERROR_##sym,
923 #undef F
924  BFD_UDP_N_ERROR,
926 
927 typedef enum
928 {
934 
935 /* Packet counters - BFD ECHO packets */
936 #define foreach_bfd_udp_echo_error(F) \
937  F (NONE, "good bfd echo packets (processed)") \
938  F (BAD, "invalid bfd echo packets")
939 
940 #define F(sym, string) static char BFD_UDP_ECHO_ERR_##sym##_STR[] = string;
942 #undef F
943 
944 static char *bfd_udp_echo_error_strings[] = {
945 #define F(sym, string) BFD_UDP_ECHO_ERR_##sym##_STR,
947 #undef F
948 };
949 
950 typedef enum
951 {
952 #define F(sym, str) BFD_UDP_ECHO_ERROR_##sym,
954 #undef F
955  BFD_UDP_ECHO_N_ERROR,
957 
958 static void
960  udp_header_t ** udp)
961 {
962  /* sanity check first */
963  const i32 start = vnet_buffer (b)->l3_hdr_offset;
964  if (start < 0 && start < sizeof (b->pre_data))
965  {
966  BFD_ERR ("Start of ip header is before pre_data, ignoring");
967  *ip4 = NULL;
968  *udp = NULL;
969  return;
970  }
971  *ip4 = (ip4_header_t *) (b->data + start);
972  if ((u8 *) * ip4 > (u8 *) vlib_buffer_get_current (b))
973  {
974  BFD_ERR ("Start of ip header is beyond current data, ignoring");
975  *ip4 = NULL;
976  *udp = NULL;
977  return;
978  }
979  *udp = (udp_header_t *) ((*ip4) + 1);
980 }
981 
982 static bfd_udp_error_t
984  const udp_header_t * udp, const bfd_session_t * bs)
985 {
986  const bfd_udp_session_t *bus = &bs->udp;
987  const bfd_udp_key_t *key = &bus->key;
988  if (ip4->src_address.as_u32 != key->peer_addr.ip4.as_u32)
989  {
990  BFD_ERR ("IPv4 src addr mismatch, got %U, expected %U",
992  key->peer_addr.ip4.as_u8);
993  return BFD_UDP_ERROR_BAD;
994  }
995  if (ip4->dst_address.as_u32 != key->local_addr.ip4.as_u32)
996  {
997  BFD_ERR ("IPv4 dst addr mismatch, got %U, expected %U",
999  key->local_addr.ip4.as_u8);
1000  return BFD_UDP_ERROR_BAD;
1001  }
1002  const u8 expected_ttl = 255;
1003  if (ip4->ttl != expected_ttl)
1004  {
1005  BFD_ERR ("IPv4 unexpected TTL value %u, expected %u", ip4->ttl,
1006  expected_ttl);
1007  return BFD_UDP_ERROR_BAD;
1008  }
1009  if (clib_net_to_host_u16 (udp->src_port) < 49152)
1010  {
1011  BFD_ERR ("Invalid UDP src port %u, out of range <49152,65535>",
1012  udp->src_port);
1013  }
1014  return BFD_UDP_ERROR_NONE;
1015 }
1016 
1017 typedef struct
1018 {
1020  bfd_pkt_t pkt;
1022 
1023 static void
1024 bfd_rpc_update_session (u32 bs_idx, const bfd_pkt_t * pkt)
1025 {
1026  bfd_main_t *bm = &bfd_main;
1027  bfd_lock (bm);
1028  bfd_consume_pkt (bm, pkt, bs_idx);
1029  bfd_unlock (bm);
1030 }
1031 
1032 static bfd_udp_error_t
1034  vlib_buffer_t * b, bfd_session_t ** bs_out)
1035 {
1036  const bfd_pkt_t *pkt = vlib_buffer_get_current (b);
1037  if (sizeof (*pkt) > b->current_length)
1038  {
1039  BFD_ERR
1040  ("Payload size %d too small to hold bfd packet of minimum size %d",
1041  b->current_length, sizeof (*pkt));
1042  return BFD_UDP_ERROR_BAD;
1043  }
1044  ip4_header_t *ip4;
1045  udp_header_t *udp;
1046  bfd_udp4_find_headers (b, &ip4, &udp);
1047  if (!ip4 || !udp)
1048  {
1049  BFD_ERR ("Couldn't find ip4 or udp header");
1050  return BFD_UDP_ERROR_BAD;
1051  }
1052  const u32 udp_payload_length = udp->length - sizeof (*udp);
1053  if (pkt->head.length > udp_payload_length)
1054  {
1055  BFD_ERR
1056  ("BFD packet length is larger than udp payload length (%u > %u)",
1057  pkt->head.length, udp_payload_length);
1058  return BFD_UDP_ERROR_BAD;
1059  }
1060  if (!bfd_verify_pkt_common (pkt))
1061  {
1062  return BFD_UDP_ERROR_BAD;
1063  }
1064  bfd_session_t *bs = NULL;
1065  if (pkt->your_disc)
1066  {
1067  BFD_DBG ("Looking up BFD session using discriminator %u",
1068  pkt->your_disc);
1069  bs = bfd_find_session_by_disc (bfd_udp_main.bfd_main, pkt->your_disc);
1070  }
1071  else
1072  {
1073  bfd_udp_key_t key;
1074  clib_memset (&key, 0, sizeof (key));
1075  key.sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
1076  key.local_addr.ip4.as_u32 = ip4->dst_address.as_u32;
1077  key.peer_addr.ip4.as_u32 = ip4->src_address.as_u32;
1078  BFD_DBG ("Looking up BFD session using key (sw_if_index=%u, local=%U, "
1079  "peer=%U)",
1080  key.sw_if_index, format_ip4_address, key.local_addr.ip4.as_u8,
1081  format_ip4_address, key.peer_addr.ip4.as_u8);
1082  bs = bfd_lookup_session (&bfd_udp_main, &key);
1083  }
1084  if (!bs)
1085  {
1086  BFD_ERR ("BFD session lookup failed - no session matches BFD pkt");
1087  return BFD_UDP_ERROR_BAD;
1088  }
1089  BFD_DBG ("BFD session found, bs_idx=%u", bs->bs_idx);
1090  if (!bfd_verify_pkt_auth (pkt, b->current_length, bs))
1091  {
1092  BFD_ERR ("Packet verification failed, dropping packet");
1093  return BFD_UDP_ERROR_BAD;
1094  }
1095  bfd_udp_error_t err;
1096  if (BFD_UDP_ERROR_NONE != (err = bfd_udp4_verify_transport (ip4, udp, bs)))
1097  {
1098  return err;
1099  }
1100  bfd_rpc_update_session (bs->bs_idx, pkt);
1101  *bs_out = bs;
1102  return BFD_UDP_ERROR_NONE;
1103 }
1104 
1105 static void
1107  udp_header_t ** udp)
1108 {
1109  /* sanity check first */
1110  const i32 start = vnet_buffer (b)->l3_hdr_offset;
1111  if (start < 0 && start < sizeof (b->pre_data))
1112  {
1113  BFD_ERR ("Start of ip header is before pre_data, ignoring");
1114  *ip6 = NULL;
1115  *udp = NULL;
1116  return;
1117  }
1118  *ip6 = (ip6_header_t *) (b->data + start);
1119  if ((u8 *) * ip6 > (u8 *) vlib_buffer_get_current (b))
1120  {
1121  BFD_ERR ("Start of ip header is beyond current data, ignoring");
1122  *ip6 = NULL;
1123  *udp = NULL;
1124  return;
1125  }
1126  if ((*ip6)->protocol != IP_PROTOCOL_UDP)
1127  {
1128  BFD_ERR ("Unexpected protocol in IPv6 header '%u', expected '%u' (== "
1129  "IP_PROTOCOL_UDP)", (*ip6)->protocol, IP_PROTOCOL_UDP);
1130  *ip6 = NULL;
1131  *udp = NULL;
1132  return;
1133  }
1134  *udp = (udp_header_t *) ((*ip6) + 1);
1135 }
1136 
1137 static bfd_udp_error_t
1139  const udp_header_t * udp, const bfd_session_t * bs)
1140 {
1141  const bfd_udp_session_t *bus = &bs->udp;
1142  const bfd_udp_key_t *key = &bus->key;
1143  if (ip6->src_address.as_u64[0] != key->peer_addr.ip6.as_u64[0] &&
1144  ip6->src_address.as_u64[1] != key->peer_addr.ip6.as_u64[1])
1145  {
1146  BFD_ERR ("IP src addr mismatch, got %U, expected %U",
1148  &key->peer_addr.ip6);
1149  return BFD_UDP_ERROR_BAD;
1150  }
1151  if (ip6->dst_address.as_u64[0] != key->local_addr.ip6.as_u64[0] &&
1152  ip6->dst_address.as_u64[1] != key->local_addr.ip6.as_u64[1])
1153  {
1154  BFD_ERR ("IP dst addr mismatch, got %U, expected %U",
1156  &key->local_addr.ip6);
1157  return BFD_UDP_ERROR_BAD;
1158  }
1159  const u8 expected_hop_limit = 255;
1160  if (ip6->hop_limit != expected_hop_limit)
1161  {
1162  BFD_ERR ("IPv6 unexpected hop-limit value %u, expected %u",
1163  ip6->hop_limit, expected_hop_limit);
1164  return BFD_UDP_ERROR_BAD;
1165  }
1166  if (clib_net_to_host_u16 (udp->src_port) < 49152)
1167  {
1168  BFD_ERR ("Invalid UDP src port %u, out of range <49152,65535>",
1169  udp->src_port);
1170  }
1171  return BFD_UDP_ERROR_NONE;
1172 }
1173 
1174 static bfd_udp_error_t
1176  vlib_buffer_t * b, bfd_session_t ** bs_out)
1177 {
1178  const bfd_pkt_t *pkt = vlib_buffer_get_current (b);
1179  if (sizeof (*pkt) > b->current_length)
1180  {
1181  BFD_ERR
1182  ("Payload size %d too small to hold bfd packet of minimum size %d",
1183  b->current_length, sizeof (*pkt));
1184  return BFD_UDP_ERROR_BAD;
1185  }
1186  ip6_header_t *ip6;
1187  udp_header_t *udp;
1188  bfd_udp6_find_headers (b, &ip6, &udp);
1189  if (!ip6 || !udp)
1190  {
1191  BFD_ERR ("Couldn't find ip6 or udp header");
1192  return BFD_UDP_ERROR_BAD;
1193  }
1194  const u32 udp_payload_length = udp->length - sizeof (*udp);
1195  if (pkt->head.length > udp_payload_length)
1196  {
1197  BFD_ERR
1198  ("BFD packet length is larger than udp payload length (%u > %u)",
1199  pkt->head.length, udp_payload_length);
1200  return BFD_UDP_ERROR_BAD;
1201  }
1202  if (!bfd_verify_pkt_common (pkt))
1203  {
1204  return BFD_UDP_ERROR_BAD;
1205  }
1206  bfd_session_t *bs = NULL;
1207  if (pkt->your_disc)
1208  {
1209  BFD_DBG ("Looking up BFD session using discriminator %u",
1210  pkt->your_disc);
1211  bs = bfd_find_session_by_disc (bfd_udp_main.bfd_main, pkt->your_disc);
1212  }
1213  else
1214  {
1215  bfd_udp_key_t key;
1216  clib_memset (&key, 0, sizeof (key));
1217  key.sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
1218  key.local_addr.ip6.as_u64[0] = ip6->dst_address.as_u64[0];
1219  key.local_addr.ip6.as_u64[1] = ip6->dst_address.as_u64[1];
1220  key.peer_addr.ip6.as_u64[0] = ip6->src_address.as_u64[0];
1221  key.peer_addr.ip6.as_u64[1] = ip6->src_address.as_u64[1];
1222  BFD_DBG ("Looking up BFD session using key (sw_if_index=%u, local=%U, "
1223  "peer=%U)",
1224  key.sw_if_index, format_ip6_address, &key.local_addr,
1225  format_ip6_address, &key.peer_addr);
1226  bs = bfd_lookup_session (&bfd_udp_main, &key);
1227  }
1228  if (!bs)
1229  {
1230  BFD_ERR ("BFD session lookup failed - no session matches BFD pkt");
1231  return BFD_UDP_ERROR_BAD;
1232  }
1233  BFD_DBG ("BFD session found, bs_idx=%u", bs->bs_idx);
1234  if (!bfd_verify_pkt_auth (pkt, b->current_length, bs))
1235  {
1236  BFD_ERR ("Packet verification failed, dropping packet");
1237  return BFD_UDP_ERROR_BAD;
1238  }
1239  bfd_udp_error_t err;
1240  if (BFD_UDP_ERROR_NONE != (err = bfd_udp6_verify_transport (ip6, udp, bs)))
1241  {
1242  return err;
1243  }
1244  bfd_rpc_update_session (bs->bs_idx, pkt);
1245  *bs_out = bs;
1246  return BFD_UDP_ERROR_NONE;
1247 }
1248 
1249 /*
1250  * Process a frame of bfd packets
1251  * Expect 1 packet / frame
1252  */
1253 static uword
1255  vlib_frame_t * f, int is_ipv6)
1256 {
1257  u32 n_left_from, *from;
1258  bfd_input_trace_t *t0;
1259  bfd_main_t *bm = &bfd_main;
1260 
1261  from = vlib_frame_vector_args (f); /* array of buffer indices */
1262  n_left_from = f->n_vectors; /* number of buffer indices */
1263 
1264  while (n_left_from > 0)
1265  {
1266  u32 bi0;
1267  vlib_buffer_t *b0;
1268  u32 next0, error0;
1269 
1270  bi0 = from[0];
1271  b0 = vlib_get_buffer (vm, bi0);
1272 
1273  bfd_session_t *bs = NULL;
1274 
1275  /* If this pkt is traced, snapshot the data */
1276  if (b0->flags & VLIB_BUFFER_IS_TRACED)
1277  {
1278  int len;
1279  t0 = vlib_add_trace (vm, rt, b0, sizeof (*t0));
1280  len = (b0->current_length < sizeof (t0->data)) ? b0->current_length
1281  : sizeof (t0->data);
1282  t0->len = len;
1284  }
1285 
1286  /* scan this bfd pkt. error0 is the counter index to bmp */
1287  bfd_lock (bm);
1288  if (is_ipv6)
1289  {
1290  error0 = bfd_udp6_scan (vm, rt, b0, &bs);
1291  }
1292  else
1293  {
1294  error0 = bfd_udp4_scan (vm, rt, b0, &bs);
1295  }
1296  b0->error = rt->errors[error0];
1297 
1298  next0 = BFD_UDP_INPUT_NEXT_NORMAL;
1299  if (BFD_UDP_ERROR_NONE == error0)
1300  {
1301  /*
1302  * if everything went fine, check for poll bit, if present, re-use
1303  * the buffer and based on (now updated) session parameters, send
1304  * the final packet back
1305  */
1306  const bfd_pkt_t *pkt = vlib_buffer_get_current (b0);
1307  if (bfd_pkt_get_poll (pkt))
1308  {
1309  b0->current_data = 0;
1310  b0->current_length = 0;
1311  bfd_init_final_control_frame (vm, b0, bfd_udp_main.bfd_main, bs,
1312  0);
1313  if (is_ipv6)
1314  {
1316  b0->error, 1);
1317  }
1318  else
1319  {
1321  b0->error, 1);
1322  }
1323  const bfd_udp_session_t *bus = &bs->udp;
1324  ip_adjacency_t *adj = adj_get (bus->adj_index);
1325  switch (adj->lookup_next_index)
1326  {
1327  case IP_LOOKUP_NEXT_ARP:
1329  break;
1332  break;
1335  break;
1336  default:
1337  /* drop */
1338  break;
1339  }
1340  }
1341  }
1342  bfd_unlock (bm);
1343  vlib_set_next_frame_buffer (vm, rt, next0, bi0);
1344 
1345  from += 1;
1346  n_left_from -= 1;
1347  }
1348 
1349  return f->n_vectors;
1350 }
1351 
1352 static uword
1354 {
1355  return bfd_udp_input (vm, rt, f, 0);
1356 }
1357 
1358 /*
1359  * bfd input graph node declaration
1360  */
1361 /* *INDENT-OFF* */
1363  .function = bfd_udp4_input,
1364  .name = "bfd-udp4-input",
1365  .vector_size = sizeof (u32),
1367 
1368  .n_errors = BFD_UDP_N_ERROR,
1369  .error_strings = bfd_udp_error_strings,
1370 
1371  .format_trace = bfd_input_format_trace,
1372 
1373  .n_next_nodes = BFD_UDP_INPUT_N_NEXT,
1374  .next_nodes =
1375  {
1376  [BFD_UDP_INPUT_NEXT_NORMAL] = "error-drop",
1377  [BFD_UDP_INPUT_NEXT_REPLY_ARP] = "ip4-arp",
1378  [BFD_UDP_INPUT_NEXT_REPLY_REWRITE] = "ip4-lookup",
1379  [BFD_UDP_INPUT_NEXT_REPLY_MIDCHAIN] = "ip4-midchain",
1380  },
1381 };
1382 /* *INDENT-ON* */
1383 
1384 static uword
1386 {
1387  return bfd_udp_input (vm, rt, f, 1);
1388 }
1389 
1390 /* *INDENT-OFF* */
1392  .function = bfd_udp6_input,
1393  .name = "bfd-udp6-input",
1394  .vector_size = sizeof (u32),
1396 
1397  .n_errors = BFD_UDP_N_ERROR,
1398  .error_strings = bfd_udp_error_strings,
1399 
1400  .format_trace = bfd_input_format_trace,
1401 
1402  .n_next_nodes = BFD_UDP_INPUT_N_NEXT,
1403  .next_nodes =
1404  {
1405  [BFD_UDP_INPUT_NEXT_NORMAL] = "error-drop",
1406  [BFD_UDP_INPUT_NEXT_REPLY_ARP] = "ip6-discover-neighbor",
1407  [BFD_UDP_INPUT_NEXT_REPLY_REWRITE] = "ip6-lookup",
1408  [BFD_UDP_INPUT_NEXT_REPLY_MIDCHAIN] = "ip6-midchain",
1409  },
1410 };
1411 /* *INDENT-ON* */
1412 
1413 /*
1414  * Process a frame of bfd echo packets
1415  * Expect 1 packet / frame
1416  */
1417 static uword
1419  vlib_frame_t * f, int is_ipv6)
1420 {
1421  u32 n_left_from, *from;
1422  bfd_input_trace_t *t0;
1423  bfd_main_t *bm = &bfd_main;
1424 
1425  from = vlib_frame_vector_args (f); /* array of buffer indices */
1426  n_left_from = f->n_vectors; /* number of buffer indices */
1427 
1428  while (n_left_from > 0)
1429  {
1430  u32 bi0;
1431  vlib_buffer_t *b0;
1432  u32 next0;
1433 
1434  bi0 = from[0];
1435  b0 = vlib_get_buffer (vm, bi0);
1436 
1437  /* If this pkt is traced, snapshot the data */
1438  if (b0->flags & VLIB_BUFFER_IS_TRACED)
1439  {
1440  int len;
1441  t0 = vlib_add_trace (vm, rt, b0, sizeof (*t0));
1442  len = (b0->current_length < sizeof (t0->data)) ? b0->current_length
1443  : sizeof (t0->data);
1444  t0->len = len;
1446  }
1447 
1448  bfd_lock (bm);
1449  if (bfd_consume_echo_pkt (bfd_udp_main.bfd_main, b0))
1450  {
1451  b0->error = rt->errors[BFD_UDP_ERROR_NONE];
1453  }
1454  else
1455  {
1456  /* loop back the packet */
1457  b0->error = rt->errors[BFD_UDP_ERROR_NONE];
1458  if (is_ipv6)
1459  {
1461  b0->error, 1);
1462  }
1463  else
1464  {
1466  b0->error, 1);
1467  }
1469  }
1470 
1471  bfd_unlock (bm);
1472  vlib_set_next_frame_buffer (vm, rt, next0, bi0);
1473 
1474  from += 1;
1475  n_left_from -= 1;
1476  }
1477 
1478  return f->n_vectors;
1479 }
1480 
1481 static uword
1483  vlib_frame_t * f)
1484 {
1485  return bfd_udp_echo_input (vm, rt, f, 0);
1486 }
1487 
1488 u8 *
1489 bfd_echo_input_format_trace (u8 * s, va_list * args)
1490 {
1491  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1492  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
1493  const bfd_udp_echo_input_trace_t *t =
1494  va_arg (*args, bfd_udp_echo_input_trace_t *);
1495  if (t->len > STRUCT_SIZE_OF (bfd_pkt_t, head))
1496  {
1497  s = format (s, "BFD ECHO:\n");
1498  s = format (s, " data: %U", format_hexdump, t->data, t->len);
1499  }
1500 
1501  return s;
1502 }
1503 
1504 /*
1505  * bfd input graph node declaration
1506  */
1507 /* *INDENT-OFF* */
1509  .function = bfd_udp_echo4_input,
1510  .name = "bfd-udp-echo4-input",
1511  .vector_size = sizeof (u32),
1513 
1514  .n_errors = BFD_UDP_ECHO_N_ERROR,
1515  .error_strings = bfd_udp_error_strings,
1516 
1517  .format_trace = bfd_echo_input_format_trace,
1518 
1519  .n_next_nodes = BFD_UDP_ECHO_INPUT_N_NEXT,
1520  .next_nodes =
1521  {
1522  [BFD_UDP_ECHO_INPUT_NEXT_NORMAL] = "error-drop",
1523  [BFD_UDP_ECHO_INPUT_NEXT_REPLY_ARP] = "ip4-arp",
1524  [BFD_UDP_ECHO_INPUT_NEXT_REPLY_REWRITE] = "ip4-lookup",
1525  },
1526 };
1527 /* *INDENT-ON* */
1528 
1529 static uword
1531  vlib_frame_t * f)
1532 {
1533  return bfd_udp_echo_input (vm, rt, f, 1);
1534 }
1535 
1536 /* *INDENT-OFF* */
1538  .function = bfd_udp_echo6_input,
1539  .name = "bfd-udp-echo6-input",
1540  .vector_size = sizeof (u32),
1542 
1543  .n_errors = BFD_UDP_ECHO_N_ERROR,
1544  .error_strings = bfd_udp_echo_error_strings,
1545 
1546  .format_trace = bfd_echo_input_format_trace,
1547 
1548  .n_next_nodes = BFD_UDP_ECHO_INPUT_N_NEXT,
1549  .next_nodes =
1550  {
1551  [BFD_UDP_ECHO_INPUT_NEXT_NORMAL] = "error-drop",
1552  [BFD_UDP_ECHO_INPUT_NEXT_REPLY_ARP] = "ip6-discover-neighbor",
1553  [BFD_UDP_ECHO_INPUT_NEXT_REPLY_REWRITE] = "ip6-lookup",
1554  },
1555 };
1556 
1557 /* *INDENT-ON* */
1558 
1559 static clib_error_t *
1561 {
1562  bfd_session_t **to_be_freed = NULL;
1563  bfd_udp_main_t *bum = &bfd_udp_main;
1564  BFD_DBG ("sw_if_add_del called, sw_if_index=%u, is_create=%u", sw_if_index,
1565  is_create);
1566  if (!is_create)
1567  {
1568  bfd_session_t *bs;
1569  pool_foreach (bs, bfd_udp_main.bfd_main->sessions,
1570  {
1571  if (bs->transport != BFD_TRANSPORT_UDP4 &&
1572  bs->transport != BFD_TRANSPORT_UDP6)
1573  {
1574  continue;}
1575  if (bs->udp.key.sw_if_index != sw_if_index)
1576  {
1577  continue;}
1578  vec_add1 (to_be_freed, bs);}
1579  );
1580  }
1581  bfd_session_t **bs;
1582  vec_foreach (bs, to_be_freed)
1583  {
1584  vlib_log_notice (bum->log_class,
1585  "removal of sw_if_index=%u forces removal of bfd session "
1586  "with bs_idx=%u", sw_if_index, (*bs)->bs_idx);
1587  bfd_session_set_flags (*bs, 0);
1589  }
1590  return 0;
1591 }
1592 
1594 
1595 /*
1596  * setup function
1597  */
1598 static clib_error_t *
1600 {
1601  bfd_udp_main.udp4_sessions_count = 0;
1602  bfd_udp_main.udp6_sessions_count = 0;
1603  mhash_init (&bfd_udp_main.bfd_session_idx_by_bfd_key, sizeof (uword),
1604  sizeof (bfd_udp_key_t));
1605  bfd_udp_main.bfd_main = &bfd_main;
1606  bfd_udp_main.vnet_main = vnet_get_main ();
1607  vlib_node_t *node = vlib_get_node_by_name (vm, (u8 *) "ip4-arp");
1608  ASSERT (node);
1609  bfd_udp_main.ip4_arp_idx = node->index;
1610  node = vlib_get_node_by_name (vm, (u8 *) "ip6-discover-neighbor");
1611  ASSERT (node);
1612  bfd_udp_main.ip6_ndp_idx = node->index;
1613  node = vlib_get_node_by_name (vm, (u8 *) "ip4-rewrite");
1614  ASSERT (node);
1615  bfd_udp_main.ip4_rewrite_idx = node->index;
1616  node = vlib_get_node_by_name (vm, (u8 *) "ip6-rewrite");
1617  ASSERT (node);
1618  bfd_udp_main.ip6_rewrite_idx = node->index;
1619  node = vlib_get_node_by_name (vm, (u8 *) "ip4-midchain");
1620  ASSERT (node);
1621  bfd_udp_main.ip4_midchain_idx = node->index;
1622  node = vlib_get_node_by_name (vm, (u8 *) "ip6-midchain");
1623  ASSERT (node);
1624  bfd_udp_main.ip6_midchain_idx = node->index;
1625 
1626  bfd_udp_main.log_class = vlib_log_register_class ("bfd", "udp");
1627  vlib_log_debug (bfd_udp_main.log_class, "initialized");
1628  return 0;
1629 }
1630 
1632 
1633 /*
1634  * fd.io coding-style-patch-verification: ON
1635  *
1636  * Local Variables:
1637  * eval: (c-set-style "gnu")
1638  * End:
1639  */
vlib_log_class_t vlib_log_register_class(char *class, char *subclass)
Definition: log.c:176
static clib_error_t * bfd_udp_init(vlib_main_t *vm)
Definition: bfd_udp.c:1599
vnet_api_error_t bfd_udp_auth_activate(u32 sw_if_index, const ip46_address_t *local_addr, const ip46_address_t *peer_addr, u32 conf_key_id, u8 key_id, u8 is_delayed)
activate authentication for existing session
Definition: bfd_udp.c:843
#define foreach_ip_interface_address(lm, a, sw_if_index, loop, body)
Definition: lookup.h:182
static uword vnet_sw_interface_is_up(vnet_main_t *vnm, u32 sw_if_index)
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:124
static uword bfd_udp_input(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f, int is_ipv6)
Definition: bfd_udp.c:1254
Definition: mhash.h:46
bfd_session_t * bfd_get_session(bfd_main_t *bm, bfd_transport_e t)
Definition: bfd_main.c:1337
static char * bfd_udp_echo_error_strings[]
Definition: bfd_udp.c:944
vnet_api_error_t
Definition: api_errno.h:154
static vnet_api_error_t bfd_api_verify_common(u32 sw_if_index, u32 desired_min_tx_usec, u32 required_min_rx_usec, u8 detect_mult, const ip46_address_t *local_addr, const ip46_address_t *peer_addr)
Definition: bfd_udp.c:672
vnet_main_t * vnet_main
Definition: bfd_udp.c:49
bfd_udp_echo_error_t
Definition: bfd_udp.c:950
void bfd_consume_pkt(bfd_main_t *bm, const bfd_pkt_t *pkt, u32 bs_idx)
Definition: bfd_main.c:1781
#define CLIB_UNUSED(x)
Definition: clib.h:82
bfd udp echo packet trace capture
Definition: bfd_udp.h:53
ip4_address_t src_address
Definition: ip4_packet.h:170
static uword bfd_udp_echo6_input(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
Definition: bfd_udp.c:1530
bfd_main_t bfd_main
Definition: bfd_main.c:2258
static void vlib_set_next_frame_buffer(vlib_main_t *vm, vlib_node_runtime_t *node, u32 next_index, u32 buffer_index)
Definition: node_funcs.h:371
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
#define BFD_ERR(...)
Definition: bfd_debug.h:75
u64 as_u64[2]
Definition: ip6_packet.h:51
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:110
bfd_main_t * bfd_main
Definition: bfd_udp.c:44
bfd_session_t * bfd_find_session_by_disc(bfd_main_t *bm, u32 disc)
Definition: bfd_main.c:1403
Definitions for all things IP (v4|v6) unicast and multicast lookup related.
#define clib_memcpy_fast(a, b, c)
Definition: string.h:81
#define NULL
Definition: clib.h:58
uword mhash_unset(mhash_t *h, void *key, uword *old_value)
Definition: mhash.c:346
u32 index
Definition: node.h:279
IP unicast adjacency.
Definition: adj.h:221
int bfd_verify_pkt_common(const bfd_pkt_t *pkt)
verify bfd packet - common checks
Definition: bfd_main.c:1422
u32 ip4_arp_idx
Definition: bfd_udp.c:55
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:113
This packet is to be rewritten and forwarded to the next processing node.
Definition: adj.h:73
u8 data[0]
Packet data.
Definition: buffer.h:181
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:522
static vlib_node_registration_t bfd_udp4_input_node
(constructor) VLIB_REGISTER_NODE (bfd_udp4_input_node)
Definition: bfd_udp.c:74
void bfd_put_session(bfd_main_t *bm, bfd_session_t *bs)
Definition: bfd_main.c:1371
format_function_t format_ip46_address
Definition: format.h:61
clib_memset(h->entries, 0, sizeof(h->entries[0])*entries)
ip_lookup_main_t lookup_main
Definition: ip4.h:107
static vlib_node_registration_t bfd_udp6_input_node
(constructor) VLIB_REGISTER_NODE (bfd_udp6_input_node)
Definition: bfd_udp.c:75
static void bfd_unlock(bfd_main_t *bm)
Definition: bfd_main.h:385
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
static bfd_udp_error_t bfd_udp6_scan(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_buffer_t *b, bfd_session_t **bs_out)
Definition: bfd_udp.c:1175
#define foreach_bfd_udp_error(F)
Definition: bfd_udp.c:905
void bfd_init_final_control_frame(vlib_main_t *vm, vlib_buffer_t *b, bfd_main_t *bm, bfd_session_t *bs, int is_local)
Definition: bfd_main.c:1027
VNET_SW_INTERFACE_ADD_DEL_FUNCTION(bfd_udp_sw_if_add_del)
static uword bfd_udp4_input(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
Definition: bfd_udp.c:1353
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:468
static uword vlib_buffer_length_in_chain(vlib_main_t *vm, vlib_buffer_t *b)
Get length in bytes of the buffer chain.
Definition: buffer_funcs.h:366
u32 echo_source_sw_if_index
Definition: bfd_udp.c:53
vhost_vring_addr_t addr
Definition: vhost_user.h:147
static vnet_api_error_t bfd_udp_validate_api_input(u32 sw_if_index, const ip46_address_t *local_addr, const ip46_address_t *peer_addr)
Definition: bfd_udp.c:563
ip6_address_t src_address
Definition: ip6_packet.h:383
unsigned char u8
Definition: types.h:56
static uword bfd_udp_echo_input(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f, int is_ipv6)
Definition: bfd_udp.c:1418
u32 udp4_sessions_count
Definition: bfd_udp.c:69
bfd_udp_error_t
Definition: bfd_udp.c:919
int bfd_add_udp4_transport(vlib_main_t *vm, u32 bi, const bfd_session_t *bs, int is_echo)
Definition: bfd_udp.c:252
#define foreach_bfd_udp_echo_error(F)
Definition: bfd_udp.c:936
void bfd_udp_get_echo_source(int *is_set, u32 *sw_if_index, int *have_usable_ip4, ip4_address_t *ip4, int *have_usable_ip6, ip6_address_t *ip6)
get echo source information - used by CLI
Definition: bfd_udp.c:234
vnet_api_error_t bfd_auth_deactivate(bfd_session_t *bs, u8 is_delayed)
Definition: bfd_main.c:2058
mhash_t bfd_session_idx_by_bfd_key
Definition: bfd_udp.c:47
format_function_t format_ip4_address
Definition: format.h:75
static ip_adjacency_t * adj_get(adj_index_t adj_index)
Get a pointer to an adjacency object from its index.
Definition: adj.h:433
vnet_api_error_t bfd_udp_del_echo_source(u32 sw_if_index)
Definition: bfd_udp.c:96
u32 vlib_log_class_t
Definition: vlib.h:51
static char * bfd_udp_error_strings[]
Definition: bfd_udp.c:913
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:493
static void bfd_udp_del_session_internal(vlib_main_t *vm, bfd_session_t *bs)
Definition: bfd_udp.c:698
static void bfd_udp6_find_headers(vlib_buffer_t *b, ip6_header_t **ip6, udp_header_t **udp)
Definition: bfd_udp.c:1106
vl_api_interface_index_t sw_if_index
Definition: gre.api:50
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
vnet_api_error_t bfd_udp_mod_session(u32 sw_if_index, const ip46_address_t *local_addr, const ip46_address_t *peer_addr, u32 desired_min_tx_usec, u32 required_min_rx_usec, u8 detect_mult)
modify existing session
Definition: bfd_udp.c:774
ip4_address_t dst_address
Definition: ip4_packet.h:170
static void bfd_udp4_find_headers(vlib_buffer_t *b, ip4_header_t **ip4, udp_header_t **udp)
Definition: bfd_udp.c:959
static bfd_session_t * bfd_lookup_session(bfd_udp_main_t *bum, const bfd_udp_key_t *key)
Definition: bfd_udp.c:461
int bfd_transport_udp4(vlib_main_t *vm, u32 bi, const struct bfd_session_s *bs)
transport packet over udpv4
Definition: bfd_udp.c:437
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:187
UDP transport specific data embedded in bfd_session&#39;s union.
Definition: bfd_udp.h:44
void adj_unlock(adj_index_t adj_index)
Release a reference counting lock on the adjacency.
Definition: adj.c:318
unsigned int u32
Definition: types.h:88
#define vlib_log_debug(...)
Definition: log.h:106
bfd_session_t * bfd_find_session_by_idx(bfd_main_t *bm, uword bs_idx)
Definition: bfd_main.c:1392
vl_api_fib_path_type_t type
Definition: fib_types.api:123
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:136
static vnet_api_error_t bfd_udp_find_session_by_api_input(u32 sw_if_index, const ip46_address_t *local_addr, const ip46_address_t *peer_addr, bfd_session_t **bs_out)
Definition: bfd_udp.c:641
bfd_session_t * sessions
pool of bfd sessions context data
Definition: bfd_main.h:282
bfd_udp_key_t key
key identifying this session
Definition: bfd_udp.h:47
bfd_transport_e transport
transport type for this session
Definition: bfd_main.h:233
bfd_pkt_t pkt
Definition: bfd_udp.c:1020
static vnet_api_error_t bfd_udp_add_session_internal(vlib_main_t *vm, bfd_udp_main_t *bum, u32 sw_if_index, u32 desired_min_tx_usec, u32 required_min_rx_usec, u8 detect_mult, const ip46_address_t *local_addr, const ip46_address_t *peer_addr, bfd_session_t **bs_out)
Definition: bfd_udp.c:485
vnet_api_error_t bfd_udp_set_echo_source(u32 sw_if_index)
set echo-source interface
Definition: bfd_udp.c:82
unsigned short u16
Definition: types.h:57
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:196
static vlib_node_registration_t bfd_udp_echo4_input_node
(constructor) VLIB_REGISTER_NODE (bfd_udp_echo4_input_node)
Definition: bfd_udp.c:76
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:229
BFD global declarations.
u8 * bfd_echo_input_format_trace(u8 *s, va_list *args)
Definition: bfd_udp.c:1489
vnet_sw_interface_flags_t flags
Definition: interface.h:699
vnet_api_error_t bfd_udp_add_session(u32 sw_if_index, const ip46_address_t *local_addr, const ip46_address_t *peer_addr, u32 desired_min_tx_usec, u32 required_min_rx_usec, u8 detect_mult, u8 is_authenticated, u32 conf_key_id, u8 bfd_key_id)
create a new bfd session
Definition: bfd_udp.c:727
static uword mhash_set(mhash_t *h, void *key, uword new_value, uword *old_value)
Definition: mhash.h:117
static bfd_udp_error_t bfd_udp4_scan(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_buffer_t *b, bfd_session_t **bs_out)
Definition: bfd_udp.c:1033
int bfd_transport_udp6(vlib_main_t *vm, u32 bi, const struct bfd_session_s *bs)
transport packet over udpv6
Definition: bfd_udp.c:449
bfd_udp_session_t udp
Definition: bfd_main.h:238
u32 ip6_rewrite_idx
Definition: bfd_udp.c:61
int bfd_add_udp6_transport(vlib_main_t *vm, u32 bi, const bfd_session_t *bs, int is_echo)
Definition: bfd_udp.c:307
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1150
u8 len
Definition: ip_types.api:90
void bfd_session_start(bfd_main_t *bm, bfd_session_t *bs)
Definition: bfd_main.c:435
#define ip46_address_is_ip4(ip46)
Definition: ip6_packet.h:88
u32 udp6_sessions_count
Definition: bfd_udp.c:71
int bfd_udp_get_echo_src_ip6(ip6_address_t *addr)
Definition: bfd_udp.c:205
This packet matches an "incomplete adjacency" and packets need to be passed to ARP to find rewrite st...
Definition: adj.h:63
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
u32 ip4_rewrite_idx
Definition: bfd_udp.c:59
#define F(sym, string)
Definition: bfd_udp.c:952
void mhash_init(mhash_t *h, uword n_value_bytes, uword n_key_bytes)
Definition: mhash.c:168
u16 n_vectors
Definition: node.h:395
bfd_udp_input_next_t
Definition: bfd_udp.c:895
format_function_t format_ip6_address
Definition: format.h:93
vlib_main_t * vm
Definition: buffer.c:312
vlib_log_class_t log_class
Definition: bfd_udp.c:67
void udp_unregister_dst_port(vlib_main_t *vm, udp_dst_port_t dst_port, u8 is_ip4)
Definition: udp_local.c:509
static void bfd_create_frame_to_next_node(vlib_main_t *vm, u32 bi, u32 next_node)
Definition: bfd_udp.c:374
static uword bfd_udp6_input(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
Definition: bfd_udp.c:1385
u8 * format_bfd_session(u8 *s, va_list *args)
Definition: bfd_main.c:1951
u8 * format_hexdump(u8 *s, va_list *va)
Definition: std-formats.c:297
vnet_api_error_t bfd_auth_activate(bfd_session_t *bs, u32 conf_key_id, u8 bfd_key_id, u8 is_delayed)
Definition: bfd_main.c:2009
BFD global declarations.
vlib_node_t * vlib_get_node_by_name(vlib_main_t *vm, u8 *name)
Definition: node.c:45
static clib_error_t * bfd_udp_sw_if_add_del(vnet_main_t *vnm, u32 sw_if_index, u32 is_create)
Definition: bfd_udp.c:1560
u8 * bfd_input_format_trace(u8 *s, va_list *args)
Definition: bfd_main.c:476
#define BFD_DBG(...)
Definition: bfd_debug.h:74
int bfd_udp_get_echo_src_ip4(ip4_address_t *addr)
Definition: bfd_udp.c:171
This packets follow a mid-chain adjacency.
Definition: adj.h:76
u16 ip6_tcp_udp_icmp_compute_checksum(vlib_main_t *vm, vlib_buffer_t *p0, ip6_header_t *ip0, int *bogus_lengthp)
Definition: ip6_forward.c:906
signed int i32
Definition: types.h:77
vlib buffer structure definition and a few select access methods.
u32 ip4_midchain_idx
Definition: bfd_udp.c:63
static bfd_udp_error_t bfd_udp6_verify_transport(const ip6_header_t *ip6, const udp_header_t *udp, const bfd_session_t *bs)
Definition: bfd_udp.c:1138
#define ASSERT(truth)
int echo_source_is_set
Definition: bfd_udp.c:51
u8 pre_data[VLIB_BUFFER_PRE_DATA_SIZE]
Space for inserting data before buffer start.
Definition: buffer.h:178
static uword * mhash_get(mhash_t *h, const void *key)
Definition: mhash.h:110
ip6_main_t ip6_main
Definition: ip6_forward.c:2671
ip_lookup_main_t lookup_main
Definition: ip6.h:179
int bfd_udp_is_echo_available(bfd_transport_e transport)
check if the bfd udp layer is echo-capable at this time
Definition: bfd_udp.c:104
IPv4 main type.
Definition: ip4.h:105
static bfd_udp_error_t bfd_udp4_verify_transport(const ip4_header_t *ip4, const udp_header_t *udp, const bfd_session_t *bs)
Definition: bfd_udp.c:983
adj_index_t adj_index
adjacency index returned from adj lock call
Definition: bfd_udp.h:49
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:248
static vlib_node_registration_t bfd_udp_echo6_input_node
(constructor) VLIB_REGISTER_NODE (bfd_udp_echo6_input_node)
Definition: bfd_udp.c:77
bfd_udp_main_t bfd_udp_main
Definition: bfd_udp.c:79
static u16 bfd_udp_bs_idx_to_sport(u32 bs_idx)
Definition: bfd_udp.c:157
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
vnet_api_error_t bfd_udp_session_set_flags(u32 sw_if_index, const ip46_address_t *local_addr, const ip46_address_t *peer_addr, u8 admin_up_down)
set session admin down/up
Definition: bfd_udp.c:822
int bfd_consume_echo_pkt(bfd_main_t *bm, vlib_buffer_t *b)
Definition: bfd_main.c:1915
vnet_api_error_t bfd_session_set_params(bfd_main_t *bm, bfd_session_t *bs, u32 desired_min_tx_usec, u32 required_min_rx_usec, u8 detect_mult)
Definition: bfd_main.c:2100
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
struct _vlib_node_registration vlib_node_registration_t
bfd_udp_echo_input_next_t
Definition: bfd_udp.c:927
Definition: defs.h:47
BFD UDP transport layer declarations.
BFD API declarations.
ip_lookup_next_t lookup_next_index
Next hop after ip4-lookup.
Definition: adj.h:236
int bfd_udp_calc_next_node(const struct bfd_session_s *bs, u32 *next_node)
Definition: bfd_udp.c:384
VLIB buffer representation.
Definition: buffer.h:102
#define vlib_log_info(...)
Definition: log.h:105
u64 uword
Definition: types.h:112
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:244
typedef key
Definition: ipsec.api:245
vnet_api_error_t bfd_udp_del_session(u32 sw_if_index, const ip46_address_t *local_addr, const ip46_address_t *peer_addr)
delete existing session
Definition: bfd_udp.c:801
u8 bfd_pkt_get_poll(const bfd_pkt_t *pkt)
Definition: bfd_protocol.c:60
u32 bs_idx
index in bfd_main.sessions pool
Definition: bfd_main.h:88
#define vnet_buffer(b)
Definition: buffer.h:361
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:921
static void bfd_udp_key_init(bfd_udp_key_t *key, u32 sw_if_index, const ip46_address_t *local_addr, const ip46_address_t *peer_addr)
Definition: bfd_udp.c:472
#define STRUCT_SIZE_OF(t, f)
Definition: clib.h:67
adj_index_t adj_nbr_add_or_lock(fib_protocol_t nh_proto, vnet_link_t link_type, const ip46_address_t *nh_addr, u32 sw_if_index)
Neighbour Adjacency sub-type.
Definition: adj_nbr.c:218
#define vec_foreach(var, vec)
Vector iterator.
u32 ip6_ndp_idx
Definition: bfd_udp.c:57
#define vlib_log_err(...)
Definition: log.h:102
bfd packet trace capture
Definition: bfd_main.h:342
int bfd_verify_pkt_auth(const bfd_pkt_t *pkt, u16 pkt_size, bfd_session_t *bs)
verify bfd packet - authentication
Definition: bfd_main.c:1703
void udp_register_dst_port(vlib_main_t *vm, udp_dst_port_t dst_port, u32 node_index, u8 is_ip4)
Definition: udp_local.c:471
static void bfd_rpc_update_session(u32 bs_idx, const bfd_pkt_t *pkt)
Definition: bfd_udp.c:1024
vnet_api_error_t bfd_udp_auth_deactivate(u32 sw_if_index, const ip46_address_t *local_addr, const ip46_address_t *peer_addr, u8 is_delayed)
deactivate authentication for existing session
Definition: bfd_udp.c:874
static uword bfd_udp_echo4_input(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
Definition: bfd_udp.c:1482
static vnet_sw_interface_t * vnet_get_sw_interface_or_null(vnet_main_t *vnm, u32 sw_if_index)
u32 ip6_midchain_idx
Definition: bfd_udp.c:65
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:85
static u16 ip4_header_checksum(ip4_header_t *i)
Definition: ip4_packet.h:247
Definition: defs.h:46
static void bfd_lock(bfd_main_t *bm)
Definition: bfd_main.h:368
bfd_transport_e
Definition: bfd_api.h:30
ip6_address_t dst_address
Definition: ip6_packet.h:383
void bfd_session_set_flags(bfd_session_t *bs, u8 admin_up_down)
Definition: bfd_main.c:449
#define vlib_log_notice(...)
Definition: log.h:104