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