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