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