FD.io VPP  v20.05-21-gb1500e9ff
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/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 =
86  vnet_get_sw_interface_or_null (bfd_udp_main.vnet_main, sw_if_index);
87  if (sw_if)
88  {
89  bfd_udp_main.echo_source_sw_if_index = sw_if_index;
90  bfd_udp_main.echo_source_is_set = 1;
91  return 0;
92  }
93  return VNET_API_ERROR_BFD_ENOENT;
94 }
95 
98 {
99  bfd_udp_main.echo_source_sw_if_index = ~0;
100  bfd_udp_main.echo_source_is_set = 0;
101  return 0;
102 }
103 
104 int
106 {
107  if (!bfd_udp_main.echo_source_is_set)
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 =
119  bfd_udp_main.echo_source_sw_if_index);
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* */
128  bfd_udp_main.echo_source_sw_if_index,
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* */
143  bfd_udp_main.echo_source_sw_if_index,
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 {
174  if (!bfd_udp_main.echo_source_is_set)
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 {
208  if (!bfd_udp_main.echo_source_is_set)
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 {
239  if (bfd_udp_main.echo_source_is_set)
240  {
241  *is_set = 1;
242  *sw_if_index = bfd_udp_main.echo_source_sw_if_index;
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;
258  vlib_buffer_t *b = vlib_get_buffer (vm, bi);
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;
313  vlib_buffer_t *b = vlib_get_buffer (vm, bi);
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 {
464  uword *p = mhash_get (&bum->bfd_session_idx_by_bfd_key, key);
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 =
570  vnet_get_sw_interface_or_null (bfd_udp_main.vnet_main, sw_if_index);
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 {
661  vnet_api_error_t rv =
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 {
693  vnet_api_error_t rv =
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 
751  vnet_api_error_t rv =
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 =
759  bfd_udp_add_session_internal (vlib_get_main (), &bfd_udp_main,
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 #if WITH_LIBSSL > 0
767  rv = bfd_auth_activate (bs, conf_key_id, bfd_key_id,
768  0 /* is not delayed */ );
769 #else
770  vlib_log_err (bfd_udp_main.log_class,
771  "SSL missing, cannot add authenticated BFD session");
772  rv = VNET_API_ERROR_BFD_NOTSUPP;
773 #endif
774  if (rv)
775  {
777  }
778  }
779  if (!rv)
780  {
781  bfd_session_start (bfd_udp_main.bfd_main, bs);
782  }
783 
784  bfd_unlock (bm);
785  return rv;
786 }
787 
790  const ip46_address_t * local_addr,
791  const ip46_address_t * peer_addr,
792  u32 desired_min_tx_usec,
793  u32 required_min_rx_usec, u8 detect_mult)
794 {
795  bfd_session_t *bs = NULL;
796  bfd_main_t *bm = &bfd_main;
797  vnet_api_error_t error;
798  bfd_lock (bm);
799  vnet_api_error_t rv =
800  bfd_udp_find_session_by_api_input (sw_if_index, local_addr, peer_addr,
801  &bs);
802  if (rv)
803  {
804  bfd_unlock (bm);
805  return rv;
806  }
807 
808  error = bfd_session_set_params (bfd_udp_main.bfd_main, bs,
809  desired_min_tx_usec, required_min_rx_usec,
810  detect_mult);
811  bfd_unlock (bm);
812  return error;
813 }
814 
817  const ip46_address_t * local_addr,
818  const ip46_address_t * peer_addr)
819 {
820  bfd_session_t *bs = NULL;
821  bfd_main_t *bm = &bfd_main;
822  bfd_lock (bm);
823  vnet_api_error_t rv =
824  bfd_udp_find_session_by_api_input (sw_if_index, local_addr, peer_addr,
825  &bs);
826  if (rv)
827  {
828  bfd_unlock (bm);
829  return rv;
830  }
832  bfd_unlock (bm);
833  return 0;
834 }
835 
838  const ip46_address_t * local_addr,
839  const ip46_address_t * peer_addr, u8 admin_up_down)
840 {
841  bfd_session_t *bs = NULL;
842  bfd_main_t *bm = &bfd_main;
843  bfd_lock (bm);
844  vnet_api_error_t rv =
845  bfd_udp_find_session_by_api_input (sw_if_index, local_addr, peer_addr,
846  &bs);
847  if (rv)
848  {
849  bfd_unlock (bm);
850  return rv;
851  }
852  bfd_session_set_flags (vm, bs, admin_up_down);
853  bfd_unlock (bm);
854  return 0;
855 }
856 
859  const ip46_address_t * local_addr,
860  const ip46_address_t * peer_addr,
861  u32 conf_key_id, u8 key_id, u8 is_delayed)
862 {
863  bfd_main_t *bm = &bfd_main;
864  bfd_lock (bm);
865  vnet_api_error_t error;
866 
867 #if WITH_LIBSSL > 0
868  bfd_session_t *bs = NULL;
869  vnet_api_error_t rv =
870  bfd_udp_find_session_by_api_input (sw_if_index, local_addr, peer_addr,
871  &bs);
872  if (rv)
873  {
874  bfd_unlock (bm);
875  return rv;
876  }
877  error = bfd_auth_activate (bs, conf_key_id, key_id, is_delayed);
878  bfd_unlock (bm);
879  return error;
880 #else
881  vlib_log_err (bfd_udp_main->log_class,
882  "SSL missing, cannot activate BFD authentication");
883  bfd_unlock (bm);
884  return VNET_API_ERROR_BFD_NOTSUPP;
885 #endif
886 }
887 
890  const ip46_address_t * local_addr,
891  const ip46_address_t * peer_addr, u8 is_delayed)
892 {
893  bfd_main_t *bm = &bfd_main;
894  vnet_api_error_t error;
895  bfd_lock (bm);
896  bfd_session_t *bs = NULL;
897  vnet_api_error_t rv =
898  bfd_udp_find_session_by_api_input (sw_if_index, local_addr, peer_addr,
899  &bs);
900  if (rv)
901  {
902  bfd_unlock (bm);
903  return rv;
904  }
905  error = bfd_auth_deactivate (bs, is_delayed);
906  bfd_unlock (bm);
907  return error;
908 }
909 
910 typedef enum
911 {
918 
919 /* Packet counters - BFD control frames */
920 #define foreach_bfd_udp_error(F) \
921  F (NONE, "good bfd packets (processed)") \
922  F (BAD, "invalid bfd packets")
923 
924 #define F(sym, string) static char BFD_UDP_ERR_##sym##_STR[] = string;
926 #undef F
927 
928 static char *bfd_udp_error_strings[] = {
929 #define F(sym, string) BFD_UDP_ERR_##sym##_STR,
931 #undef F
932 };
933 
934 typedef enum
935 {
936 #define F(sym, str) BFD_UDP_ERROR_##sym,
938 #undef F
939  BFD_UDP_N_ERROR,
941 
942 typedef enum
943 {
949 
950 /* Packet counters - BFD ECHO packets */
951 #define foreach_bfd_udp_echo_error(F) \
952  F (NONE, "good bfd echo packets (processed)") \
953  F (BAD, "invalid bfd echo packets")
954 
955 #define F(sym, string) static char BFD_UDP_ECHO_ERR_##sym##_STR[] = string;
957 #undef F
958 
959 static char *bfd_udp_echo_error_strings[] = {
960 #define F(sym, string) BFD_UDP_ECHO_ERR_##sym##_STR,
962 #undef F
963 };
964 
965 typedef enum
966 {
967 #define F(sym, str) BFD_UDP_ECHO_ERROR_##sym,
969 #undef F
970  BFD_UDP_ECHO_N_ERROR,
972 
973 static void
975  udp_header_t ** udp)
976 {
977  /* sanity check first */
978  const i32 start = vnet_buffer (b)->l3_hdr_offset;
979  if (start < 0 && start < sizeof (b->pre_data))
980  {
981  BFD_ERR ("Start of ip header is before pre_data, ignoring");
982  *ip4 = NULL;
983  *udp = NULL;
984  return;
985  }
986  *ip4 = (ip4_header_t *) (b->data + start);
987  if ((u8 *) * ip4 > (u8 *) vlib_buffer_get_current (b))
988  {
989  BFD_ERR ("Start of ip header is beyond current data, ignoring");
990  *ip4 = NULL;
991  *udp = NULL;
992  return;
993  }
994  *udp = (udp_header_t *) ((*ip4) + 1);
995 }
996 
997 static bfd_udp_error_t
999  const udp_header_t * udp, const bfd_session_t * bs)
1000 {
1001  const bfd_udp_session_t *bus = &bs->udp;
1002  const bfd_udp_key_t *key = &bus->key;
1003  if (ip4->src_address.as_u32 != key->peer_addr.ip4.as_u32)
1004  {
1005  BFD_ERR ("IPv4 src addr mismatch, got %U, expected %U",
1007  key->peer_addr.ip4.as_u8);
1008  return BFD_UDP_ERROR_BAD;
1009  }
1010  if (ip4->dst_address.as_u32 != key->local_addr.ip4.as_u32)
1011  {
1012  BFD_ERR ("IPv4 dst addr mismatch, got %U, expected %U",
1014  key->local_addr.ip4.as_u8);
1015  return BFD_UDP_ERROR_BAD;
1016  }
1017  const u8 expected_ttl = 255;
1018  if (ip4->ttl != expected_ttl)
1019  {
1020  BFD_ERR ("IPv4 unexpected TTL value %u, expected %u", ip4->ttl,
1021  expected_ttl);
1022  return BFD_UDP_ERROR_BAD;
1023  }
1024  if (clib_net_to_host_u16 (udp->src_port) < 49152)
1025  {
1026  BFD_ERR ("Invalid UDP src port %u, out of range <49152,65535>",
1027  udp->src_port);
1028  }
1029  return BFD_UDP_ERROR_NONE;
1030 }
1031 
1032 typedef struct
1033 {
1035  bfd_pkt_t pkt;
1037 
1038 static void
1039 bfd_rpc_update_session (vlib_main_t * vm, u32 bs_idx, const bfd_pkt_t * pkt)
1040 {
1041  bfd_main_t *bm = &bfd_main;
1042  bfd_lock (bm);
1043  bfd_consume_pkt (vm, bm, pkt, bs_idx);
1044  bfd_unlock (bm);
1045 }
1046 
1047 static bfd_udp_error_t
1049  vlib_buffer_t * b, bfd_session_t ** bs_out)
1050 {
1051  const bfd_pkt_t *pkt = vlib_buffer_get_current (b);
1052  if (sizeof (*pkt) > b->current_length)
1053  {
1054  BFD_ERR
1055  ("Payload size %d too small to hold bfd packet of minimum size %d",
1056  b->current_length, sizeof (*pkt));
1057  return BFD_UDP_ERROR_BAD;
1058  }
1059  ip4_header_t *ip4;
1060  udp_header_t *udp;
1061  bfd_udp4_find_headers (b, &ip4, &udp);
1062  if (!ip4 || !udp)
1063  {
1064  BFD_ERR ("Couldn't find ip4 or udp header");
1065  return BFD_UDP_ERROR_BAD;
1066  }
1067  const u32 udp_payload_length = udp->length - sizeof (*udp);
1068  if (pkt->head.length > udp_payload_length)
1069  {
1070  BFD_ERR
1071  ("BFD packet length is larger than udp payload length (%u > %u)",
1072  pkt->head.length, udp_payload_length);
1073  return BFD_UDP_ERROR_BAD;
1074  }
1075  if (!bfd_verify_pkt_common (pkt))
1076  {
1077  return BFD_UDP_ERROR_BAD;
1078  }
1079  bfd_session_t *bs = NULL;
1080  if (pkt->your_disc)
1081  {
1082  BFD_DBG ("Looking up BFD session using discriminator %u",
1083  pkt->your_disc);
1084  bs = bfd_find_session_by_disc (bfd_udp_main.bfd_main, pkt->your_disc);
1085  }
1086  else
1087  {
1088  bfd_udp_key_t key;
1089  clib_memset (&key, 0, sizeof (key));
1090  key.sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
1091  key.local_addr.ip4.as_u32 = ip4->dst_address.as_u32;
1092  key.peer_addr.ip4.as_u32 = ip4->src_address.as_u32;
1093  BFD_DBG ("Looking up BFD session using key (sw_if_index=%u, local=%U, "
1094  "peer=%U)",
1095  key.sw_if_index, format_ip4_address, key.local_addr.ip4.as_u8,
1096  format_ip4_address, key.peer_addr.ip4.as_u8);
1097  bs = bfd_lookup_session (&bfd_udp_main, &key);
1098  }
1099  if (!bs)
1100  {
1101  BFD_ERR ("BFD session lookup failed - no session matches BFD pkt");
1102  return BFD_UDP_ERROR_BAD;
1103  }
1104  BFD_DBG ("BFD session found, bs_idx=%u", bs->bs_idx);
1105  if (!bfd_verify_pkt_auth (vm, pkt, b->current_length, bs))
1106  {
1107  BFD_ERR ("Packet verification failed, dropping packet");
1108  return BFD_UDP_ERROR_BAD;
1109  }
1110  bfd_udp_error_t err;
1111  if (BFD_UDP_ERROR_NONE != (err = bfd_udp4_verify_transport (ip4, udp, bs)))
1112  {
1113  return err;
1114  }
1115  bfd_rpc_update_session (vm, bs->bs_idx, pkt);
1116  *bs_out = bs;
1117  return BFD_UDP_ERROR_NONE;
1118 }
1119 
1120 static void
1122  udp_header_t ** udp)
1123 {
1124  /* sanity check first */
1125  const i32 start = vnet_buffer (b)->l3_hdr_offset;
1126  if (start < 0 && start < sizeof (b->pre_data))
1127  {
1128  BFD_ERR ("Start of ip header is before pre_data, ignoring");
1129  *ip6 = NULL;
1130  *udp = NULL;
1131  return;
1132  }
1133  *ip6 = (ip6_header_t *) (b->data + start);
1134  if ((u8 *) * ip6 > (u8 *) vlib_buffer_get_current (b))
1135  {
1136  BFD_ERR ("Start of ip header is beyond current data, ignoring");
1137  *ip6 = NULL;
1138  *udp = NULL;
1139  return;
1140  }
1141  if ((*ip6)->protocol != IP_PROTOCOL_UDP)
1142  {
1143  BFD_ERR ("Unexpected protocol in IPv6 header '%u', expected '%u' (== "
1144  "IP_PROTOCOL_UDP)", (*ip6)->protocol, IP_PROTOCOL_UDP);
1145  *ip6 = NULL;
1146  *udp = NULL;
1147  return;
1148  }
1149  *udp = (udp_header_t *) ((*ip6) + 1);
1150 }
1151 
1152 static bfd_udp_error_t
1154  const udp_header_t * udp, const bfd_session_t * bs)
1155 {
1156  const bfd_udp_session_t *bus = &bs->udp;
1157  const bfd_udp_key_t *key = &bus->key;
1158  if (ip6->src_address.as_u64[0] != key->peer_addr.ip6.as_u64[0] &&
1159  ip6->src_address.as_u64[1] != key->peer_addr.ip6.as_u64[1])
1160  {
1161  BFD_ERR ("IP src addr mismatch, got %U, expected %U",
1163  &key->peer_addr.ip6);
1164  return BFD_UDP_ERROR_BAD;
1165  }
1166  if (ip6->dst_address.as_u64[0] != key->local_addr.ip6.as_u64[0] &&
1167  ip6->dst_address.as_u64[1] != key->local_addr.ip6.as_u64[1])
1168  {
1169  BFD_ERR ("IP dst addr mismatch, got %U, expected %U",
1171  &key->local_addr.ip6);
1172  return BFD_UDP_ERROR_BAD;
1173  }
1174  const u8 expected_hop_limit = 255;
1175  if (ip6->hop_limit != expected_hop_limit)
1176  {
1177  BFD_ERR ("IPv6 unexpected hop-limit value %u, expected %u",
1178  ip6->hop_limit, expected_hop_limit);
1179  return BFD_UDP_ERROR_BAD;
1180  }
1181  if (clib_net_to_host_u16 (udp->src_port) < 49152)
1182  {
1183  BFD_ERR ("Invalid UDP src port %u, out of range <49152,65535>",
1184  udp->src_port);
1185  }
1186  return BFD_UDP_ERROR_NONE;
1187 }
1188 
1189 static bfd_udp_error_t
1191  vlib_buffer_t * b, bfd_session_t ** bs_out)
1192 {
1193  const bfd_pkt_t *pkt = vlib_buffer_get_current (b);
1194  if (sizeof (*pkt) > b->current_length)
1195  {
1196  BFD_ERR
1197  ("Payload size %d too small to hold bfd packet of minimum size %d",
1198  b->current_length, sizeof (*pkt));
1199  return BFD_UDP_ERROR_BAD;
1200  }
1201  ip6_header_t *ip6;
1202  udp_header_t *udp;
1203  bfd_udp6_find_headers (b, &ip6, &udp);
1204  if (!ip6 || !udp)
1205  {
1206  BFD_ERR ("Couldn't find ip6 or udp header");
1207  return BFD_UDP_ERROR_BAD;
1208  }
1209  const u32 udp_payload_length = udp->length - sizeof (*udp);
1210  if (pkt->head.length > udp_payload_length)
1211  {
1212  BFD_ERR
1213  ("BFD packet length is larger than udp payload length (%u > %u)",
1214  pkt->head.length, udp_payload_length);
1215  return BFD_UDP_ERROR_BAD;
1216  }
1217  if (!bfd_verify_pkt_common (pkt))
1218  {
1219  return BFD_UDP_ERROR_BAD;
1220  }
1221  bfd_session_t *bs = NULL;
1222  if (pkt->your_disc)
1223  {
1224  BFD_DBG ("Looking up BFD session using discriminator %u",
1225  pkt->your_disc);
1226  bs = bfd_find_session_by_disc (bfd_udp_main.bfd_main, pkt->your_disc);
1227  }
1228  else
1229  {
1230  bfd_udp_key_t key;
1231  clib_memset (&key, 0, sizeof (key));
1232  key.sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
1233  key.local_addr.ip6.as_u64[0] = ip6->dst_address.as_u64[0];
1234  key.local_addr.ip6.as_u64[1] = ip6->dst_address.as_u64[1];
1235  key.peer_addr.ip6.as_u64[0] = ip6->src_address.as_u64[0];
1236  key.peer_addr.ip6.as_u64[1] = ip6->src_address.as_u64[1];
1237  BFD_DBG ("Looking up BFD session using key (sw_if_index=%u, local=%U, "
1238  "peer=%U)",
1239  key.sw_if_index, format_ip6_address, &key.local_addr,
1240  format_ip6_address, &key.peer_addr);
1241  bs = bfd_lookup_session (&bfd_udp_main, &key);
1242  }
1243  if (!bs)
1244  {
1245  BFD_ERR ("BFD session lookup failed - no session matches BFD pkt");
1246  return BFD_UDP_ERROR_BAD;
1247  }
1248  BFD_DBG ("BFD session found, bs_idx=%u", bs->bs_idx);
1249  if (!bfd_verify_pkt_auth (vm, pkt, b->current_length, bs))
1250  {
1251  BFD_ERR ("Packet verification failed, dropping packet");
1252  return BFD_UDP_ERROR_BAD;
1253  }
1254  bfd_udp_error_t err;
1255  if (BFD_UDP_ERROR_NONE != (err = bfd_udp6_verify_transport (ip6, udp, bs)))
1256  {
1257  return err;
1258  }
1259  bfd_rpc_update_session (vm, bs->bs_idx, pkt);
1260  *bs_out = bs;
1261  return BFD_UDP_ERROR_NONE;
1262 }
1263 
1264 /*
1265  * Process a frame of bfd packets
1266  * Expect 1 packet / frame
1267  */
1268 static uword
1270  vlib_frame_t * f, int is_ipv6)
1271 {
1272  u32 n_left_from, *from;
1273  bfd_input_trace_t *t0;
1274  bfd_main_t *bm = &bfd_main;
1275 
1276  from = vlib_frame_vector_args (f); /* array of buffer indices */
1277  n_left_from = f->n_vectors; /* number of buffer indices */
1278 
1279  while (n_left_from > 0)
1280  {
1281  u32 bi0;
1282  vlib_buffer_t *b0;
1283  u32 next0, error0;
1284 
1285  bi0 = from[0];
1286  b0 = vlib_get_buffer (vm, bi0);
1287 
1288  bfd_session_t *bs = NULL;
1289 
1290  /* If this pkt is traced, snapshot the data */
1291  if (b0->flags & VLIB_BUFFER_IS_TRACED)
1292  {
1293  int len;
1294  t0 = vlib_add_trace (vm, rt, b0, sizeof (*t0));
1295  len = (b0->current_length < sizeof (t0->data)) ? b0->current_length
1296  : sizeof (t0->data);
1297  t0->len = len;
1299  }
1300 
1301  /* scan this bfd pkt. error0 is the counter index to bmp */
1302  bfd_lock (bm);
1303  if (is_ipv6)
1304  {
1305  error0 = bfd_udp6_scan (vm, rt, b0, &bs);
1306  }
1307  else
1308  {
1309  error0 = bfd_udp4_scan (vm, rt, b0, &bs);
1310  }
1311  b0->error = rt->errors[error0];
1312 
1313  next0 = BFD_UDP_INPUT_NEXT_NORMAL;
1314  if (BFD_UDP_ERROR_NONE == error0)
1315  {
1316  /*
1317  * if everything went fine, check for poll bit, if present, re-use
1318  * the buffer and based on (now updated) session parameters, send
1319  * the final packet back
1320  */
1321  const bfd_pkt_t *pkt = vlib_buffer_get_current (b0);
1322  if (bfd_pkt_get_poll (pkt))
1323  {
1324  b0->current_data = 0;
1325  b0->current_length = 0;
1326  bfd_init_final_control_frame (vm, b0, bfd_udp_main.bfd_main, bs,
1327  0);
1328  if (is_ipv6)
1329  {
1331  b0->error, 1);
1332  }
1333  else
1334  {
1336  b0->error, 1);
1337  }
1338  const bfd_udp_session_t *bus = &bs->udp;
1339  ip_adjacency_t *adj = adj_get (bus->adj_index);
1340  switch (adj->lookup_next_index)
1341  {
1342  case IP_LOOKUP_NEXT_ARP:
1344  break;
1347  break;
1350  break;
1351  default:
1352  /* drop */
1353  break;
1354  }
1355  }
1356  }
1357  bfd_unlock (bm);
1358  vlib_set_next_frame_buffer (vm, rt, next0, bi0);
1359 
1360  from += 1;
1361  n_left_from -= 1;
1362  }
1363 
1364  return f->n_vectors;
1365 }
1366 
1367 static uword
1369 {
1370  return bfd_udp_input (vm, rt, f, 0);
1371 }
1372 
1373 /*
1374  * bfd input graph node declaration
1375  */
1376 /* *INDENT-OFF* */
1378  .function = bfd_udp4_input,
1379  .name = "bfd-udp4-input",
1380  .vector_size = sizeof (u32),
1382 
1383  .n_errors = BFD_UDP_N_ERROR,
1384  .error_strings = bfd_udp_error_strings,
1385 
1386  .format_trace = bfd_input_format_trace,
1387 
1388  .n_next_nodes = BFD_UDP_INPUT_N_NEXT,
1389  .next_nodes =
1390  {
1391  [BFD_UDP_INPUT_NEXT_NORMAL] = "error-drop",
1392  [BFD_UDP_INPUT_NEXT_REPLY_ARP] = "ip4-arp",
1393  [BFD_UDP_INPUT_NEXT_REPLY_REWRITE] = "ip4-lookup",
1394  [BFD_UDP_INPUT_NEXT_REPLY_MIDCHAIN] = "ip4-midchain",
1395  },
1396 };
1397 /* *INDENT-ON* */
1398 
1399 static uword
1401 {
1402  return bfd_udp_input (vm, rt, f, 1);
1403 }
1404 
1405 /* *INDENT-OFF* */
1407  .function = bfd_udp6_input,
1408  .name = "bfd-udp6-input",
1409  .vector_size = sizeof (u32),
1411 
1412  .n_errors = BFD_UDP_N_ERROR,
1413  .error_strings = bfd_udp_error_strings,
1414 
1415  .format_trace = bfd_input_format_trace,
1416 
1417  .n_next_nodes = BFD_UDP_INPUT_N_NEXT,
1418  .next_nodes =
1419  {
1420  [BFD_UDP_INPUT_NEXT_NORMAL] = "error-drop",
1421  [BFD_UDP_INPUT_NEXT_REPLY_ARP] = "ip6-discover-neighbor",
1422  [BFD_UDP_INPUT_NEXT_REPLY_REWRITE] = "ip6-lookup",
1423  [BFD_UDP_INPUT_NEXT_REPLY_MIDCHAIN] = "ip6-midchain",
1424  },
1425 };
1426 /* *INDENT-ON* */
1427 
1428 /*
1429  * Process a frame of bfd echo packets
1430  * Expect 1 packet / frame
1431  */
1432 static uword
1434  vlib_frame_t * f, int is_ipv6)
1435 {
1436  u32 n_left_from, *from;
1437  bfd_input_trace_t *t0;
1438  bfd_main_t *bm = &bfd_main;
1439 
1440  from = vlib_frame_vector_args (f); /* array of buffer indices */
1441  n_left_from = f->n_vectors; /* number of buffer indices */
1442 
1443  while (n_left_from > 0)
1444  {
1445  u32 bi0;
1446  vlib_buffer_t *b0;
1447  u32 next0;
1448 
1449  bi0 = from[0];
1450  b0 = vlib_get_buffer (vm, bi0);
1451 
1452  /* If this pkt is traced, snapshot the data */
1453  if (b0->flags & VLIB_BUFFER_IS_TRACED)
1454  {
1455  int len;
1456  t0 = vlib_add_trace (vm, rt, b0, sizeof (*t0));
1457  len = (b0->current_length < sizeof (t0->data)) ? b0->current_length
1458  : sizeof (t0->data);
1459  t0->len = len;
1461  }
1462 
1463  bfd_lock (bm);
1464  if (bfd_consume_echo_pkt (vm, bfd_udp_main.bfd_main, b0))
1465  {
1466  b0->error = rt->errors[BFD_UDP_ERROR_NONE];
1468  }
1469  else
1470  {
1471  /* loop back the packet */
1472  b0->error = rt->errors[BFD_UDP_ERROR_NONE];
1473  if (is_ipv6)
1474  {
1476  b0->error, 1);
1477  }
1478  else
1479  {
1481  b0->error, 1);
1482  }
1484  }
1485 
1486  bfd_unlock (bm);
1487  vlib_set_next_frame_buffer (vm, rt, next0, bi0);
1488 
1489  from += 1;
1490  n_left_from -= 1;
1491  }
1492 
1493  return f->n_vectors;
1494 }
1495 
1496 static uword
1498  vlib_frame_t * f)
1499 {
1500  return bfd_udp_echo_input (vm, rt, f, 0);
1501 }
1502 
1503 u8 *
1504 bfd_echo_input_format_trace (u8 * s, va_list * args)
1505 {
1506  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1507  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
1508  const bfd_udp_echo_input_trace_t *t =
1509  va_arg (*args, bfd_udp_echo_input_trace_t *);
1510  if (t->len > STRUCT_SIZE_OF (bfd_pkt_t, head))
1511  {
1512  s = format (s, "BFD ECHO:\n");
1513  s = format (s, " data: %U", format_hexdump, t->data, t->len);
1514  }
1515 
1516  return s;
1517 }
1518 
1519 /*
1520  * bfd input graph node declaration
1521  */
1522 /* *INDENT-OFF* */
1524  .function = bfd_udp_echo4_input,
1525  .name = "bfd-udp-echo4-input",
1526  .vector_size = sizeof (u32),
1528 
1529  .n_errors = BFD_UDP_ECHO_N_ERROR,
1530  .error_strings = bfd_udp_error_strings,
1531 
1532  .format_trace = bfd_echo_input_format_trace,
1533 
1534  .n_next_nodes = BFD_UDP_ECHO_INPUT_N_NEXT,
1535  .next_nodes =
1536  {
1537  [BFD_UDP_ECHO_INPUT_NEXT_NORMAL] = "error-drop",
1538  [BFD_UDP_ECHO_INPUT_NEXT_REPLY_ARP] = "ip4-arp",
1539  [BFD_UDP_ECHO_INPUT_NEXT_REPLY_REWRITE] = "ip4-lookup",
1540  },
1541 };
1542 /* *INDENT-ON* */
1543 
1544 static uword
1546  vlib_frame_t * f)
1547 {
1548  return bfd_udp_echo_input (vm, rt, f, 1);
1549 }
1550 
1551 /* *INDENT-OFF* */
1553  .function = bfd_udp_echo6_input,
1554  .name = "bfd-udp-echo6-input",
1555  .vector_size = sizeof (u32),
1557 
1558  .n_errors = BFD_UDP_ECHO_N_ERROR,
1559  .error_strings = bfd_udp_echo_error_strings,
1560 
1561  .format_trace = bfd_echo_input_format_trace,
1562 
1563  .n_next_nodes = BFD_UDP_ECHO_INPUT_N_NEXT,
1564  .next_nodes =
1565  {
1566  [BFD_UDP_ECHO_INPUT_NEXT_NORMAL] = "error-drop",
1567  [BFD_UDP_ECHO_INPUT_NEXT_REPLY_ARP] = "ip6-discover-neighbor",
1568  [BFD_UDP_ECHO_INPUT_NEXT_REPLY_REWRITE] = "ip6-lookup",
1569  },
1570 };
1571 
1572 /* *INDENT-ON* */
1573 
1574 static clib_error_t *
1576 {
1577  bfd_session_t **to_be_freed = NULL;
1578  bfd_udp_main_t *bum = &bfd_udp_main;
1579  BFD_DBG ("sw_if_add_del called, sw_if_index=%u, is_create=%u", sw_if_index,
1580  is_create);
1581  if (!is_create)
1582  {
1583  bfd_session_t *bs;
1584  pool_foreach (bs, bfd_udp_main.bfd_main->sessions,
1585  {
1586  if (bs->transport != BFD_TRANSPORT_UDP4 &&
1587  bs->transport != BFD_TRANSPORT_UDP6)
1588  {
1589  continue;}
1590  if (bs->udp.key.sw_if_index != sw_if_index)
1591  {
1592  continue;}
1593  vec_add1 (to_be_freed, bs);}
1594  );
1595  }
1596  bfd_session_t **bs;
1597  vec_foreach (bs, to_be_freed)
1598  {
1599  vlib_log_notice (bum->log_class,
1600  "removal of sw_if_index=%u forces removal of bfd session "
1601  "with bs_idx=%u", sw_if_index, (*bs)->bs_idx);
1602  bfd_session_set_flags (vlib_get_main (), *bs, 0);
1604  }
1605  return 0;
1606 }
1607 
1609 
1610 /*
1611  * setup function
1612  */
1613 static clib_error_t *
1615 {
1616  bfd_udp_main.udp4_sessions_count = 0;
1617  bfd_udp_main.udp6_sessions_count = 0;
1618  mhash_init (&bfd_udp_main.bfd_session_idx_by_bfd_key, sizeof (uword),
1619  sizeof (bfd_udp_key_t));
1620  bfd_udp_main.bfd_main = &bfd_main;
1621  bfd_udp_main.vnet_main = vnet_get_main ();
1622  vlib_node_t *node = vlib_get_node_by_name (vm, (u8 *) "ip4-arp");
1623  ASSERT (node);
1624  bfd_udp_main.ip4_arp_idx = node->index;
1625  node = vlib_get_node_by_name (vm, (u8 *) "ip6-discover-neighbor");
1626  ASSERT (node);
1627  bfd_udp_main.ip6_ndp_idx = node->index;
1628  node = vlib_get_node_by_name (vm, (u8 *) "ip4-rewrite");
1629  ASSERT (node);
1630  bfd_udp_main.ip4_rewrite_idx = node->index;
1631  node = vlib_get_node_by_name (vm, (u8 *) "ip6-rewrite");
1632  ASSERT (node);
1633  bfd_udp_main.ip6_rewrite_idx = node->index;
1634  node = vlib_get_node_by_name (vm, (u8 *) "ip4-midchain");
1635  ASSERT (node);
1636  bfd_udp_main.ip4_midchain_idx = node->index;
1637  node = vlib_get_node_by_name (vm, (u8 *) "ip6-midchain");
1638  ASSERT (node);
1639  bfd_udp_main.ip6_midchain_idx = node->index;
1640 
1641  bfd_udp_main.log_class = vlib_log_register_class ("bfd", "udp");
1642  vlib_log_debug (bfd_udp_main.log_class, "initialized");
1643  return 0;
1644 }
1645 
1647 
1648 /*
1649  * fd.io coding-style-patch-verification: ON
1650  *
1651  * Local Variables:
1652  * eval: (c-set-style "gnu")
1653  * End:
1654  */
vlib_log_class_t vlib_log_register_class(char *class, char *subclass)
Definition: log.c:209
static clib_error_t * bfd_udp_init(vlib_main_t *vm)
Definition: bfd_udp.c:1614
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:858
static uword vnet_sw_interface_is_up(vnet_main_t *vnm, u32 sw_if_index)
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:124
static uword bfd_udp_input(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f, int is_ipv6)
Definition: bfd_udp.c:1269
Definition: mhash.h:46
bfd_session_t * bfd_get_session(bfd_main_t *bm, bfd_transport_e t)
Definition: bfd_main.c:1368
static char * bfd_udp_echo_error_strings[]
Definition: bfd_udp.c:959
vnet_api_error_t
Definition: api_errno.h:160
static void bfd_rpc_update_session(vlib_main_t *vm, u32 bs_idx, const bfd_pkt_t *pkt)
Definition: bfd_udp.c:1039
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
vnet_main_t * vnet_main
Definition: bfd_udp.c:50
bfd_udp_echo_error_t
Definition: bfd_udp.c:965
#define CLIB_UNUSED(x)
Definition: clib.h:86
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:1545
bfd_main_t bfd_main
Definition: bfd_main.c:2288
static void vlib_set_next_frame_buffer(vlib_main_t *vm, vlib_node_runtime_t *node, u32 next_index, u32 buffer_index)
Definition: node_funcs.h:371
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
#define BFD_ERR(...)
Definition: bfd_debug.h:72
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:110
bfd_main_t * bfd_main
Definition: bfd_udp.c:45
bfd_session_t * bfd_find_session_by_disc(bfd_main_t *bm, u32 disc)
Definition: bfd_main.c:1434
Definitions for all things IP (v4|v6) unicast and multicast lookup related.
#define clib_memcpy_fast(a, b, c)
Definition: string.h:81
uword mhash_unset(mhash_t *h, void *key, uword *old_value)
Definition: mhash.c:346
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
u32 index
Definition: node.h:282
IP unicast adjacency.
Definition: adj.h:227
int bfd_verify_pkt_common(const bfd_pkt_t *pkt)
verify bfd packet - common checks
Definition: bfd_main.c:1453
u32 ip4_arp_idx
Definition: bfd_udp.c:56
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:113
This packet is to be rewritten and forwarded to the next processing node.
Definition: adj.h:73
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:590
static vlib_node_registration_t bfd_udp4_input_node
(constructor) VLIB_REGISTER_NODE (bfd_udp4_input_node)
Definition: bfd_udp.c:75
void bfd_put_session(bfd_main_t *bm, bfd_session_t *bs)
Definition: bfd_main.c:1402
ip_lookup_main_t lookup_main
Definition: ip4.h:108
static vlib_node_registration_t bfd_udp6_input_node
(constructor) VLIB_REGISTER_NODE (bfd_udp6_input_node)
Definition: bfd_udp.c:76
static void bfd_unlock(bfd_main_t *bm)
Definition: bfd_main.h:385
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
static bfd_udp_error_t bfd_udp6_scan(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_buffer_t *b, bfd_session_t **bs_out)
Definition: bfd_udp.c:1190
#define foreach_bfd_udp_error(F)
Definition: bfd_udp.c:920
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:1039
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:1368
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:472
static u8 ip46_address_is_ip4(const ip46_address_t *ip46)
Definition: ip46_address.h:55
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:402
u32 echo_source_sw_if_index
Definition: bfd_udp.c:54
vhost_vring_addr_t addr
Definition: vhost_user.h:254
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
ip6_address_t src_address
Definition: ip6_packet.h:310
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:1433
u32 udp4_sessions_count
Definition: bfd_udp.c:70
bfd_udp_error_t
Definition: bfd_udp.c:934
int bfd_add_udp4_transport(vlib_main_t *vm, u32 bi, const bfd_session_t *bs, int is_echo)
Definition: bfd_udp.c:253
#define foreach_bfd_udp_echo_error(F)
Definition: bfd_udp.c:951
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
void bfd_session_set_flags(vlib_main_t *vm, bfd_session_t *bs, u8 admin_up_down)
Definition: bfd_main.c:468
vnet_api_error_t bfd_auth_deactivate(bfd_session_t *bs, u8 is_delayed)
Definition: bfd_main.c:2089
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:837
mhash_t bfd_session_idx_by_bfd_key
Definition: bfd_udp.c:48
format_function_t format_ip4_address
Definition: format.h:73
static ip_adjacency_t * adj_get(adj_index_t adj_index)
Get a pointer to an adjacency object from its index.
Definition: adj.h:459
vnet_api_error_t bfd_udp_del_echo_source(u32 sw_if_index)
Definition: bfd_udp.c:97
u32 vlib_log_class_t
Definition: vlib.h:51
static char * bfd_udp_error_strings[]
Definition: bfd_udp.c:928
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:513
static void bfd_udp_del_session_internal(vlib_main_t *vm, bfd_session_t *bs)
Definition: bfd_udp.c:713
static void bfd_udp6_find_headers(vlib_buffer_t *b, ip6_header_t **ip6, udp_header_t **udp)
Definition: bfd_udp.c:1121
vl_api_interface_index_t sw_if_index
Definition: gre.api:53
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
vnet_api_error_t bfd_udp_mod_session(u32 sw_if_index, const ip46_address_t *local_addr, const ip46_address_t *peer_addr, u32 desired_min_tx_usec, u32 required_min_rx_usec, u8 detect_mult)
modify existing session
Definition: bfd_udp.c:789
vl_api_ip6_address_t ip6
Definition: one.api:424
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:974
static bfd_session_t * bfd_lookup_session(bfd_udp_main_t *bum, const bfd_udp_key_t *key)
Definition: bfd_udp.c:462
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
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:182
UDP transport specific data embedded in bfd_session&#39;s union.
Definition: bfd_udp.h:44
void adj_unlock(adj_index_t adj_index)
Release a reference counting lock on the adjacency.
Definition: adj.c:325
unsigned int u32
Definition: types.h:88
#define vlib_log_debug(...)
Definition: log.h:109
bfd_session_t * bfd_find_session_by_idx(bfd_main_t *bm, uword bs_idx)
Definition: bfd_main.c:1423
vl_api_fib_path_type_t type
Definition: fib_types.api:123
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:136
static vnet_api_error_t bfd_udp_find_session_by_api_input(u32 sw_if_index, const ip46_address_t *local_addr, const ip46_address_t *peer_addr, bfd_session_t **bs_out)
Definition: bfd_udp.c:656
bfd_session_t * sessions
pool of bfd sessions context data
Definition: bfd_main.h:285
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:236
bfd_pkt_t pkt
Definition: bfd_udp.c:1035
vlib_node_t * vlib_get_node_by_name(vlib_main_t *vm, u8 *name)
Definition: node.c:45
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
vnet_api_error_t bfd_udp_set_echo_source(u32 sw_if_index)
set echo-source interface
Definition: bfd_udp.c:83
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:216
static vlib_node_registration_t bfd_udp_echo4_input_node
(constructor) VLIB_REGISTER_NODE (bfd_udp_echo4_input_node)
Definition: bfd_udp.c:77
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:229
BFD global declarations.
u8 * bfd_echo_input_format_trace(u8 *s, va_list *args)
Definition: bfd_udp.c:1504
vnet_sw_interface_flags_t flags
Definition: interface.h:724
vl_api_ip4_address_t ip4
Definition: one.api:376
ip6_main_t ip6_main
Definition: ip6_forward.c:2784
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
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:1048
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
bfd_udp_session_t udp
Definition: bfd_main.h:241
vlib_main_t * vm
Definition: in2out_ed.c:1599
u32 ip6_rewrite_idx
Definition: bfd_udp.c:62
int bfd_add_udp6_transport(vlib_main_t *vm, u32 bi, const bfd_session_t *bs, int is_echo)
Definition: bfd_udp.c:308
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1150
u8 len
Definition: ip_types.api:92
format_function_t format_ip46_address
Definition: ip46_address.h:50
void bfd_session_start(bfd_main_t *bm, bfd_session_t *bs)
Definition: bfd_main.c:455
u32 udp6_sessions_count
Definition: bfd_udp.c:72
int bfd_udp_get_echo_src_ip6(ip6_address_t *addr)
Definition: bfd_udp.c:206
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:60
#define F(sym, string)
Definition: bfd_udp.c:967
void mhash_init(mhash_t *h, uword n_value_bytes, uword n_key_bytes)
Definition: mhash.c:168
u16 n_vectors
Definition: node.h:399
bfd_udp_input_next_t
Definition: bfd_udp.c:910
format_function_t format_ip6_address
Definition: format.h:91
vlib_log_class_t log_class
Definition: bfd_udp.c:68
void udp_unregister_dst_port(vlib_main_t *vm, udp_dst_port_t dst_port, u8 is_ip4)
Definition: udp_local.c:506
static void bfd_create_frame_to_next_node(vlib_main_t *vm, u32 bi, u32 next_node)
Definition: bfd_udp.c:375
static uword bfd_udp6_input(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
Definition: bfd_udp.c:1400
u8 data[]
Packet data.
Definition: buffer.h:181
u8 * format_bfd_session(u8 *s, va_list *args)
Definition: bfd_main.c:1982
u8 * format_hexdump(u8 *s, va_list *va)
Definition: std-formats.c:297
vnet_api_error_t bfd_auth_activate(bfd_session_t *bs, u32 conf_key_id, u8 bfd_key_id, u8 is_delayed)
Definition: bfd_main.c:2040
BFD global declarations.
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:1575
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1599
u8 * bfd_input_format_trace(u8 *s, va_list *args)
Definition: bfd_main.c:495
#define BFD_DBG(...)
Definition: bfd_debug.h:71
int bfd_udp_get_echo_src_ip4(ip4_address_t *addr)
Definition: bfd_udp.c:172
This packets follow a mid-chain adjacency.
Definition: adj.h:76
u16 ip6_tcp_udp_icmp_compute_checksum(vlib_main_t *vm, vlib_buffer_t *p0, ip6_header_t *ip0, int *bogus_lengthp)
Definition: ip6_forward.c:1095
signed int i32
Definition: types.h:77
vlib buffer structure definition and a few select access methods.
u32 ip4_midchain_idx
Definition: bfd_udp.c:64
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:1153
#define ASSERT(truth)
int echo_source_is_set
Definition: bfd_udp.c:52
u8 pre_data[VLIB_BUFFER_PRE_DATA_SIZE]
Space for inserting data before buffer start.
Definition: buffer.h:178
static uword * mhash_get(mhash_t *h, const void *key)
Definition: mhash.h:110
ip_lookup_main_t lookup_main
Definition: ip6.h:181
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
IPv4 main type.
Definition: ip4.h:106
int bfd_consume_echo_pkt(vlib_main_t *vm, bfd_main_t *bm, vlib_buffer_t *b)
Definition: bfd_main.c:1946
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:998
adj_index_t adj_index
adjacency index returned from adj lock call
Definition: bfd_udp.h:49
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:248
static vlib_node_registration_t bfd_udp_echo6_input_node
(constructor) VLIB_REGISTER_NODE (bfd_udp_echo6_input_node)
Definition: bfd_udp.c:78
static uword ip6_address_is_link_local_unicast(const ip6_address_t *a)
Definition: ip6_packet.h:253
static uword ip6_address_is_equal(const ip6_address_t *a, const ip6_address_t *b)
Definition: ip6_packet.h:167
bfd_udp_main_t bfd_udp_main
Definition: bfd_udp.c:80
static u16 bfd_udp_bs_idx_to_sport(u32 bs_idx)
Definition: bfd_udp.c:158
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
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:2131
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace_funcs.h:55
typedef key
Definition: ipsec_types.api:85
struct _vlib_node_registration vlib_node_registration_t
bfd_udp_echo_input_next_t
Definition: bfd_udp.c:942
Definition: defs.h:47
BFD UDP transport layer declarations.
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:1733
BFD API declarations.
ip_lookup_next_t lookup_next_index
Next hop after ip4-lookup.
Definition: adj.h:329
int bfd_udp_calc_next_node(const struct bfd_session_s *bs, u32 *next_node)
Definition: bfd_udp.c:385
#define foreach_ip_interface_address(lm, a, sw_if_index, loop, body)
Definition: ip_interface.h:57
VLIB buffer representation.
Definition: buffer.h:102
#define vlib_log_info(...)
Definition: log.h:108
u64 uword
Definition: types.h:112
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:244
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:816
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:417
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1144
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
#define STRUCT_SIZE_OF(t, f)
Definition: clib.h:71
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:217
#define vec_foreach(var, vec)
Vector iterator.
u32 ip6_ndp_idx
Definition: bfd_udp.c:58
#define vlib_log_err(...)
Definition: log.h:105
bfd packet trace capture
Definition: bfd_main.h:342
bool is_ipv6
Definition: dhcp.api:202
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:468
u8 bus
Definition: pci_types.api:21
void bfd_consume_pkt(vlib_main_t *vm, bfd_main_t *bm, const bfd_pkt_t *pkt, u32 bs_idx)
Definition: bfd_main.c:1812
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:889
static uword bfd_udp_echo4_input(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
Definition: bfd_udp.c:1497
static vnet_sw_interface_t * vnet_get_sw_interface_or_null(vnet_main_t *vnm, u32 sw_if_index)
u32 ip6_midchain_idx
Definition: bfd_udp.c:66
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:85
static u16 ip4_header_checksum(ip4_header_t *i)
Definition: ip4_packet.h:247
Definition: defs.h:46
static void bfd_lock(bfd_main_t *bm)
Definition: bfd_main.h:368
bfd_transport_e
Definition: bfd_api.h:30
ip6_address_t dst_address
Definition: ip6_packet.h:310
#define vlib_log_notice(...)
Definition: log.h:107