1 #include <vppinfra/types.h>
2 #include <vlibmemory/api.h>
4 #include <vlib/buffer.h>
5 #include <vnet/ip/format.h>
6 #include <vnet/ethernet/packet.h>
7 #include <vnet/ip/udp_packet.h>
8 #include <vnet/ip/lookup.h>
9 #include <vnet/ip/icmp46_packet.h>
10 #include <vnet/ip/ip4.h>
11 #include <vnet/ip/ip6.h>
12 #include <vnet/ip/udp.h>
13 #include <vnet/ip/ip6_packet.h>
14 #include <vnet/adj/adj.h>
15 #include <vnet/adj/adj_nbr.h>
16 #include <vnet/bfd/bfd_debug.h>
17 #include <vnet/bfd/bfd_udp.h>
18 #include <vnet/bfd/bfd_main.h>
19 #include <vnet/bfd/bfd_api.h>
24 /* hashmap - bfd session index by bfd key - used for CLI/API lookup, where
25 * discriminator is unknown */
26 mhash_t bfd_session_idx_by_bfd_key;
29 static vlib_node_registration_t bfd_udp4_input_node;
30 static vlib_node_registration_t bfd_udp6_input_node;
32 bfd_udp_main_t bfd_udp_main;
35 bfd_add_udp4_transport (vlib_main_t * vm, vlib_buffer_t * b,
36 bfd_udp_session_t * bus)
38 const bfd_udp_key_t *key = &bus->key;
40 b->flags |= VNET_BUFFER_LOCALLY_ORIGINATED;
41 vnet_buffer (b)->ip.adj_index[VLIB_RX] = bus->adj_index;
42 vnet_buffer (b)->ip.adj_index[VLIB_TX] = bus->adj_index;
48 ip4_udp_headers *headers = vlib_buffer_get_current (b);
49 vlib_buffer_advance (b, -sizeof (*headers));
50 headers = vlib_buffer_get_current (b);
51 memset (headers, 0, sizeof (*headers));
52 headers->ip4.ip_version_and_header_length = 0x45;
53 headers->ip4.ttl = 255;
54 headers->ip4.protocol = IP_PROTOCOL_UDP;
55 headers->ip4.src_address.as_u32 = key->local_addr.ip4.as_u32;
56 headers->ip4.dst_address.as_u32 = key->peer_addr.ip4.as_u32;
58 headers->udp.src_port = clib_host_to_net_u16 (50000); /* FIXME */
59 headers->udp.dst_port = clib_host_to_net_u16 (UDP_DST_PORT_bfd4);
61 /* fix ip length, checksum and udp length */
62 const u16 ip_length = vlib_buffer_length_in_chain (vm, b);
64 headers->ip4.length = clib_host_to_net_u16 (ip_length);
65 headers->ip4.checksum = ip4_header_checksum (&headers->ip4);
67 const u16 udp_length = ip_length - (sizeof (headers->ip4));
68 headers->udp.length = clib_host_to_net_u16 (udp_length);
72 bfd_add_udp6_transport (vlib_main_t * vm, vlib_buffer_t * b,
73 bfd_udp_session_t * bus)
75 const bfd_udp_key_t *key = &bus->key;
77 b->flags |= VNET_BUFFER_LOCALLY_ORIGINATED;
78 vnet_buffer (b)->ip.adj_index[VLIB_RX] = bus->adj_index;
79 vnet_buffer (b)->ip.adj_index[VLIB_TX] = bus->adj_index;
85 vlib_buffer_advance (b, -sizeof (ip6_udp_headers));
86 ip6_udp_headers *headers = vlib_buffer_get_current (b);
87 memset (headers, 0, sizeof (*headers));
88 headers->ip6.ip_version_traffic_class_and_flow_label =
89 clib_host_to_net_u32 (0x6 << 28);
90 headers->ip6.hop_limit = 255;
91 headers->ip6.protocol = IP_PROTOCOL_UDP;
92 clib_memcpy (&headers->ip6.src_address, &key->local_addr.ip6,
93 sizeof (headers->ip6.src_address));
94 clib_memcpy (&headers->ip6.dst_address, &key->peer_addr.ip6,
95 sizeof (headers->ip6.dst_address));
97 headers->udp.src_port = clib_host_to_net_u16 (50000); /* FIXME */
98 headers->udp.dst_port = clib_host_to_net_u16 (UDP_DST_PORT_bfd6);
100 /* fix ip payload length and udp length */
101 const u16 udp_length =
102 vlib_buffer_length_in_chain (vm, b) - (sizeof (headers->ip6));
103 headers->udp.length = clib_host_to_net_u16 (udp_length);
104 headers->ip6.payload_length = headers->udp.length;
106 /* IPv6 UDP checksum is mandatory */
108 headers->udp.checksum =
109 ip6_tcp_udp_icmp_compute_checksum (vm, b, &headers->ip6, &bogus);
111 if (headers->udp.checksum == 0)
113 headers->udp.checksum = 0xffff;
117 static bfd_session_t *
118 bfd_lookup_session (bfd_udp_main_t * bum, const bfd_udp_key_t * key)
120 uword *p = mhash_get (&bum->bfd_session_idx_by_bfd_key, key);
123 return bfd_find_session_by_idx (bum->bfd_main, *p);
128 static vnet_api_error_t
129 bfd_udp_add_session_internal (bfd_udp_main_t * bum, u32 sw_if_index,
130 u32 desired_min_tx_us, u32 required_min_rx_us,
132 const ip46_address_t * local_addr,
133 const ip46_address_t * peer_addr,
136 vnet_sw_interface_t *sw_if =
137 vnet_get_sw_interface (vnet_get_main (), sw_if_index);
138 /* get a pool entry and if we end up not needing it, give it back */
139 bfd_transport_t t = BFD_TRANSPORT_UDP4;
140 if (!ip46_address_is_ip4 (local_addr))
142 t = BFD_TRANSPORT_UDP6;
144 bfd_session_t *bs = bfd_get_session (bum->bfd_main, t);
145 bfd_udp_session_t *bus = &bs->udp;
146 memset (bus, 0, sizeof (*bus));
147 bfd_udp_key_t *key = &bus->key;
148 key->sw_if_index = sw_if->sw_if_index;
149 key->local_addr.as_u64[0] = local_addr->as_u64[0];
150 key->local_addr.as_u64[1] = local_addr->as_u64[1];
151 key->peer_addr.as_u64[0] = peer_addr->as_u64[0];
152 key->peer_addr.as_u64[1] = peer_addr->as_u64[1];
153 const bfd_session_t *tmp = bfd_lookup_session (bum, key);
156 BFD_ERR ("duplicate bfd-udp session, existing bs_idx=%d", tmp->bs_idx);
157 bfd_put_session (bum->bfd_main, bs);
158 return VNET_API_ERROR_BFD_EEXIST;
160 key->sw_if_index = sw_if->sw_if_index;
161 mhash_set (&bum->bfd_session_idx_by_bfd_key, key, bs->bs_idx, NULL);
162 BFD_DBG ("session created, bs_idx=%u, sw_if_index=%d, local=%U, peer=%U",
163 bs->bs_idx, key->sw_if_index, format_ip46_address,
164 &key->local_addr, IP46_TYPE_ANY, format_ip46_address,
165 &key->peer_addr, IP46_TYPE_ANY);
166 if (BFD_TRANSPORT_UDP4 == t)
168 bus->adj_index = adj_nbr_add_or_lock (FIB_PROTOCOL_IP4, VNET_LINK_IP4,
171 BFD_DBG ("adj_nbr_add_or_lock(FIB_PROTOCOL_IP4, VNET_LINK_IP4, %U, %d) "
172 "returns %d", format_ip46_address, &key->peer_addr,
173 IP46_TYPE_ANY, key->sw_if_index, bus->adj_index);
177 bus->adj_index = adj_nbr_add_or_lock (FIB_PROTOCOL_IP6, VNET_LINK_IP6,
180 BFD_DBG ("adj_nbr_add_or_lock(FIB_PROTOCOL_IP6, VNET_LINK_IP6, %U, %d) "
181 "returns %d", format_ip46_address, &key->peer_addr,
182 IP46_TYPE_ANY, key->sw_if_index, bus->adj_index);
184 bs->config_desired_min_tx_us = desired_min_tx_us;
185 bs->required_min_rx_us = required_min_rx_us;
186 bs->required_min_echo_rx_us = required_min_rx_us; /* FIXME */
187 bs->local_detect_mult = detect_mult;
188 bfd_session_start (bum->bfd_main, bs);
189 *bs_index = bs->bs_idx;
193 static vnet_api_error_t
194 bfd_udp_validate_api_input (u32 sw_if_index,
195 const ip46_address_t * local_addr,
196 const ip46_address_t * peer_addr)
198 vnet_sw_interface_t *sw_if =
199 vnet_get_sw_interface (vnet_get_main (), sw_if_index);
200 u8 local_ip_valid = 0;
201 ip_interface_address_t *ia = NULL;
204 BFD_ERR ("got NULL sw_if");
205 return VNET_API_ERROR_INVALID_SW_IF_INDEX;
207 if (ip46_address_is_ip4 (local_addr))
209 if (!ip46_address_is_ip4 (peer_addr))
211 BFD_ERR ("IP family mismatch");
212 return VNET_API_ERROR_INVALID_ARGUMENT;
214 ip4_main_t *im = &ip4_main;
217 foreach_ip_interface_address (
218 &im->lookup_main, ia, sw_if_index, 0 /* honor unnumbered */, ({
220 ip_interface_address_get_address (&im->lookup_main, ia);
221 if (x->as_u32 == local_addr->ip4.as_u32)
223 /* valid address for this interface */
232 if (ip46_address_is_ip4 (peer_addr))
234 BFD_ERR ("IP family mismatch");
235 return VNET_API_ERROR_INVALID_ARGUMENT;
237 ip6_main_t *im = &ip6_main;
239 foreach_ip_interface_address (
240 &im->lookup_main, ia, sw_if_index, 0 /* honor unnumbered */, ({
242 ip_interface_address_get_address (&im->lookup_main, ia);
243 if (local_addr->ip6.as_u64[0] == x->as_u64[0] &&
244 local_addr->ip6.as_u64[1] == x->as_u64[1])
246 /* valid address for this interface */
256 BFD_ERR ("address not found on interface");
257 return VNET_API_ERROR_ADDRESS_NOT_FOUND_FOR_INTERFACE;
264 bfd_udp_add_session (u32 sw_if_index, u32 desired_min_tx_us,
265 u32 required_min_rx_us, u8 detect_mult,
266 const ip46_address_t * local_addr,
267 const ip46_address_t * peer_addr, u32 * bs_index)
269 vnet_api_error_t rv =
270 bfd_udp_validate_api_input (sw_if_index, local_addr, peer_addr);
277 BFD_ERR ("detect_mult < 1");
278 return VNET_API_ERROR_INVALID_ARGUMENT;
280 if (desired_min_tx_us < 1)
282 BFD_ERR ("desired_min_tx_us < 1");
283 return VNET_API_ERROR_INVALID_ARGUMENT;
285 return bfd_udp_add_session_internal (&bfd_udp_main, sw_if_index,
286 desired_min_tx_us, required_min_rx_us,
287 detect_mult, local_addr, peer_addr,
292 bfd_udp_del_session (u32 sw_if_index,
293 const ip46_address_t * local_addr,
294 const ip46_address_t * peer_addr)
296 vnet_api_error_t rv =
297 bfd_udp_validate_api_input (sw_if_index, local_addr, peer_addr);
302 bfd_udp_main_t *bum = &bfd_udp_main;
303 vnet_sw_interface_t *sw_if =
304 vnet_get_sw_interface (vnet_get_main (), sw_if_index);
306 memset (&key, 0, sizeof (key));
307 key.sw_if_index = sw_if->sw_if_index;
308 key.local_addr.as_u64[0] = local_addr->as_u64[0];
309 key.local_addr.as_u64[1] = local_addr->as_u64[1];
310 key.peer_addr.as_u64[0] = peer_addr->as_u64[0];
311 key.peer_addr.as_u64[1] = peer_addr->as_u64[1];
312 bfd_session_t *tmp = bfd_lookup_session (bum, &key);
315 BFD_DBG ("free bfd-udp session, bs_idx=%d", tmp->bs_idx);
316 mhash_unset (&bum->bfd_session_idx_by_bfd_key, &key, NULL);
317 adj_unlock (tmp->udp.adj_index);
318 bfd_put_session (bum->bfd_main, tmp);
322 BFD_ERR ("no such session");
323 return VNET_API_ERROR_BFD_NOENT;
330 BFD_UDP_INPUT_NEXT_NORMAL,
331 BFD_UDP_INPUT_NEXT_REPLY,
332 BFD_UDP_INPUT_N_NEXT,
333 } bfd_udp_input_next_t;
335 /* Packet counters */
336 #define foreach_bfd_udp_error(F) \
337 F (NONE, "good bfd packets (processed)") \
338 F (BAD, "invalid bfd packets") \
339 F (DISABLED, "bfd packets received on disabled interfaces")
341 #define F(sym, string) static char BFD_UDP_ERR_##sym##_STR[] = string;
342 foreach_bfd_udp_error (F);
345 static char *bfd_udp_error_strings[] = {
346 #define F(sym, string) BFD_UDP_ERR_##sym##_STR,
347 foreach_bfd_udp_error (F)
353 #define F(sym, str) BFD_UDP_ERROR_##sym,
354 foreach_bfd_udp_error (F)
360 bfd_udp4_find_headers (vlib_buffer_t * b, const ip4_header_t ** ip4,
361 const udp_header_t ** udp)
363 /* sanity check first */
364 const i32 start = vnet_buffer (b)->ip.start_of_ip_header;
365 if (start < 0 && start < sizeof (b->pre_data))
367 BFD_ERR ("Start of ip header is before pre_data, ignoring");
372 *ip4 = (ip4_header_t *) (b->data + start);
373 if ((u8 *) * ip4 > (u8 *) vlib_buffer_get_current (b))
375 BFD_ERR ("Start of ip header is beyond current data, ignoring");
380 *udp = (udp_header_t *) ((*ip4) + 1);
383 static bfd_udp_error_t
384 bfd_udp4_verify_transport (const ip4_header_t * ip4,
385 const udp_header_t * udp, const bfd_session_t * bs)
387 const bfd_udp_session_t *bus = &bs->udp;
388 const bfd_udp_key_t *key = &bus->key;
389 if (ip4->src_address.as_u32 != key->peer_addr.ip4.as_u32)
391 BFD_ERR ("IPv4 src addr mismatch, got %U, expected %U",
392 format_ip4_address, ip4->src_address.as_u8, format_ip4_address,
393 key->peer_addr.ip4.as_u8);
394 return BFD_UDP_ERROR_BAD;
396 if (ip4->dst_address.as_u32 != key->local_addr.ip4.as_u32)
398 BFD_ERR ("IPv4 dst addr mismatch, got %U, expected %U",
399 format_ip4_address, ip4->dst_address.as_u8, format_ip4_address,
400 key->local_addr.ip4.as_u8);
401 return BFD_UDP_ERROR_BAD;
403 const u8 expected_ttl = 255;
404 if (ip4->ttl != expected_ttl)
406 BFD_ERR ("IPv4 unexpected TTL value %u, expected %u", ip4->ttl,
408 return BFD_UDP_ERROR_BAD;
410 if (clib_net_to_host_u16 (udp->src_port) < 49152 ||
411 clib_net_to_host_u16 (udp->src_port) > 65535)
413 BFD_ERR ("Invalid UDP src port %u, out of range <49152,65535>",
416 return BFD_UDP_ERROR_NONE;
426 bfd_rpc_update_session_cb (const bfd_rpc_update_t * a)
428 bfd_consume_pkt (bfd_udp_main.bfd_main, &a->pkt, a->bs_idx);
432 bfd_rpc_update_session (u32 bs_idx, const bfd_pkt_t * pkt)
434 /* packet length was already verified to be correct by the caller */
435 const u32 data_size = sizeof (bfd_rpc_update_t) -
436 STRUCT_SIZE_OF (bfd_rpc_update_t, pkt) + pkt->head.length;
438 bfd_rpc_update_t *update = (bfd_rpc_update_t *) data;
439 update->bs_idx = bs_idx;
440 clib_memcpy (&update->pkt, pkt, pkt->head.length);
441 vl_api_rpc_call_main_thread (bfd_rpc_update_session_cb, data, data_size);
444 static bfd_udp_error_t
445 bfd_udp4_scan (vlib_main_t * vm, vlib_node_runtime_t * rt,
446 vlib_buffer_t * b, bfd_session_t ** bs_out)
448 const bfd_pkt_t *pkt = vlib_buffer_get_current (b);
449 if (sizeof (*pkt) > b->current_length)
452 ("Payload size %d too small to hold bfd packet of minimum size %d",
453 b->current_length, sizeof (*pkt));
454 return BFD_UDP_ERROR_BAD;
456 const ip4_header_t *ip4;
457 const udp_header_t *udp;
458 bfd_udp4_find_headers (b, &ip4, &udp);
461 BFD_ERR ("Couldn't find ip4 or udp header");
462 return BFD_UDP_ERROR_BAD;
464 if (!bfd_verify_pkt_common (pkt))
466 return BFD_UDP_ERROR_BAD;
468 bfd_session_t *bs = NULL;
471 BFD_DBG ("Looking up BFD session using discriminator %u",
473 bs = bfd_find_session_by_disc (bfd_udp_main.bfd_main, pkt->your_disc);
478 memset (&key, 0, sizeof (key));
479 key.sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
480 key.local_addr.ip4.as_u32 = ip4->dst_address.as_u32;
481 key.peer_addr.ip4.as_u32 = ip4->src_address.as_u32;
482 BFD_DBG ("Looking up BFD session using key (sw_if_index=%u, local=%U, "
484 key.sw_if_index, format_ip4_address, key.local_addr.ip4.as_u8,
485 format_ip4_address, key.peer_addr.ip4.as_u8);
486 bs = bfd_lookup_session (&bfd_udp_main, &key);
490 BFD_ERR ("BFD session lookup failed - no session matches BFD pkt");
491 return BFD_UDP_ERROR_BAD;
493 BFD_DBG ("BFD session found, bs_idx=%u", bs->bs_idx);
494 if (!bfd_verify_pkt_session (pkt, b->current_length, bs))
496 return BFD_UDP_ERROR_BAD;
499 if (BFD_UDP_ERROR_NONE != (err = bfd_udp4_verify_transport (ip4, udp, bs)))
503 bfd_rpc_update_session (bs->bs_idx, pkt);
505 return BFD_UDP_ERROR_NONE;
509 bfd_udp6_find_headers (vlib_buffer_t * b, const ip6_header_t ** ip6,
510 const udp_header_t ** udp)
512 /* sanity check first */
513 const i32 start = vnet_buffer (b)->ip.start_of_ip_header;
514 if (start < 0 && start < sizeof (b->pre_data))
516 BFD_ERR ("Start of ip header is before pre_data, ignoring");
521 *ip6 = (ip6_header_t *) (b->data + start);
522 if ((u8 *) * ip6 > (u8 *) vlib_buffer_get_current (b))
524 BFD_ERR ("Start of ip header is beyond current data, ignoring");
529 /* FIXME skip extra headers when searching for UDP ? */
530 if ((*ip6)->protocol != IP_PROTOCOL_UDP)
532 BFD_ERR ("Unexpected protocol in IPv6 header '%u', expected '%u' (== "
533 "IP_PROTOCOL_UDP)" (*ip6)->protocol, IP_PROTOCOL_UDP);
538 *udp = (udp_header_t *) ((*ip6) + 1);
541 static bfd_udp_error_t
542 bfd_udp6_verify_transport (const ip6_header_t * ip6,
543 const udp_header_t * udp, const bfd_session_t * bs)
545 const bfd_udp_session_t *bus = &bs->udp;
546 const bfd_udp_key_t *key = &bus->key;
547 if (ip6->src_address.as_u64[0] != key->peer_addr.ip6.as_u64[0] &&
548 ip6->src_address.as_u64[1] != key->peer_addr.ip6.as_u64[1])
550 BFD_ERR ("IP src addr mismatch, got %U, expected %U",
551 format_ip6_address, ip6, format_ip6_address,
552 &key->peer_addr.ip6);
553 return BFD_UDP_ERROR_BAD;
555 if (ip6->dst_address.as_u64[0] != key->local_addr.ip6.as_u64[0] &&
556 ip6->dst_address.as_u64[1] != key->local_addr.ip6.as_u64[1])
558 BFD_ERR ("IP dst addr mismatch, got %U, expected %U",
559 format_ip6_address, ip6, format_ip6_address,
560 &key->local_addr.ip6);
561 return BFD_UDP_ERROR_BAD;
563 const u8 expected_hop_limit = 255;
564 if (ip6->hop_limit != expected_hop_limit)
566 BFD_ERR ("IPv6 unexpected hop-limit value %u, expected %u",
567 ip6->hop_limit, expected_hop_limit);
568 return BFD_UDP_ERROR_BAD;
570 if (clib_net_to_host_u16 (udp->src_port) < 49152 ||
571 clib_net_to_host_u16 (udp->src_port) > 65535)
573 BFD_ERR ("Invalid UDP src port %u, out of range <49152,65535>",
576 return BFD_UDP_ERROR_NONE;
579 static bfd_udp_error_t
580 bfd_udp6_scan (vlib_main_t * vm, vlib_node_runtime_t * rt,
581 vlib_buffer_t * b, bfd_session_t ** bs_out)
583 const bfd_pkt_t *pkt = vlib_buffer_get_current (b);
584 if (sizeof (*pkt) > b->current_length)
587 ("Payload size %d too small to hold bfd packet of minimum size %d",
588 b->current_length, sizeof (*pkt));
589 return BFD_UDP_ERROR_BAD;
591 const ip6_header_t *ip6;
592 const udp_header_t *udp;
593 bfd_udp6_find_headers (b, &ip6, &udp);
596 BFD_ERR ("Couldn't find ip6 or udp header");
597 return BFD_UDP_ERROR_BAD;
599 if (!bfd_verify_pkt_common (pkt))
601 return BFD_UDP_ERROR_BAD;
603 bfd_session_t *bs = NULL;
606 BFD_DBG ("Looking up BFD session using discriminator %u",
608 bs = bfd_find_session_by_disc (bfd_udp_main.bfd_main, pkt->your_disc);
613 memset (&key, 0, sizeof (key));
614 key.sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
615 key.local_addr.ip6.as_u64[0] = ip6->dst_address.as_u64[0];
616 key.local_addr.ip6.as_u64[1] = ip6->dst_address.as_u64[1];
617 key.peer_addr.ip6.as_u64[0] = ip6->src_address.as_u64[0];
618 key.peer_addr.ip6.as_u64[1] = ip6->src_address.as_u64[1];
619 BFD_DBG ("Looking up BFD session using key (sw_if_index=%u, local=%U, "
620 "peer=%U)", key.sw_if_index, format_ip6_address,
621 &key.local_addr, format_ip6_address, &key.peer_addr);
622 bs = bfd_lookup_session (&bfd_udp_main, &key);
626 BFD_ERR ("BFD session lookup failed - no session matches BFD pkt");
627 return BFD_UDP_ERROR_BAD;
629 BFD_DBG ("BFD session found, bs_idx=%u", bs->bs_idx);
630 if (!bfd_verify_pkt_session (pkt, b->current_length, bs))
632 return BFD_UDP_ERROR_BAD;
635 if (BFD_UDP_ERROR_NONE != (err = bfd_udp6_verify_transport (ip6, udp, bs)))
639 bfd_rpc_update_session (bs->bs_idx, pkt);
641 return BFD_UDP_ERROR_NONE;
645 * Process a frame of bfd packets
646 * Expect 1 packet / frame
649 bfd_udp_input (vlib_main_t * vm, vlib_node_runtime_t * rt,
650 vlib_frame_t * f, int is_ipv6)
652 u32 n_left_from, *from;
653 bfd_input_trace_t *t0;
655 from = vlib_frame_vector_args (f); /* array of buffer indices */
656 n_left_from = f->n_vectors; /* number of buffer indices */
658 while (n_left_from > 0)
665 b0 = vlib_get_buffer (vm, bi0);
667 bfd_session_t *bs = NULL;
669 /* If this pkt is traced, snapshot the data */
670 if (b0->flags & VLIB_BUFFER_IS_TRACED)
673 t0 = vlib_add_trace (vm, rt, b0, sizeof (*t0));
674 len = (b0->current_length < sizeof (t0->data)) ? b0->current_length
677 clib_memcpy (t0->data, vlib_buffer_get_current (b0), len);
680 /* scan this bfd pkt. error0 is the counter index to bmp */
683 error0 = bfd_udp6_scan (vm, rt, b0, &bs);
687 error0 = bfd_udp4_scan (vm, rt, b0, &bs);
689 b0->error = rt->errors[error0];
691 next0 = BFD_UDP_INPUT_NEXT_NORMAL;
692 if (BFD_UDP_ERROR_NONE == error0)
695 * if everything went fine, check for poll bit, if present, re-use
696 * the buffer and based on (now updated) session parameters, send
697 * the final packet back
699 const bfd_pkt_t *pkt = vlib_buffer_get_current (b0);
700 if (bfd_pkt_get_poll (pkt))
702 bfd_send_final (vm, b0, bs);
705 vlib_node_increment_counter (vm, bfd_udp6_input_node.index,
710 vlib_node_increment_counter (vm, bfd_udp4_input_node.index,
713 next0 = BFD_UDP_INPUT_NEXT_REPLY;
716 vlib_set_next_frame_buffer (vm, rt, next0, bi0);
726 bfd_udp4_input (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
728 return bfd_udp_input (vm, rt, f, 0);
732 * bfd input graph node declaration
735 VLIB_REGISTER_NODE (bfd_udp4_input_node, static) = {
736 .function = bfd_udp4_input,
737 .name = "bfd-udp4-input",
738 .vector_size = sizeof (u32),
739 .type = VLIB_NODE_TYPE_INTERNAL,
741 .n_errors = BFD_UDP_N_ERROR,
742 .error_strings = bfd_udp_error_strings,
744 .format_trace = bfd_input_format_trace,
746 .n_next_nodes = BFD_UDP_INPUT_N_NEXT,
749 [BFD_UDP_INPUT_NEXT_NORMAL] = "error-drop",
750 [BFD_UDP_INPUT_NEXT_REPLY] = "ip4-lookup",
756 bfd_udp6_input (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
758 return bfd_udp_input (vm, rt, f, 1);
762 VLIB_REGISTER_NODE (bfd_udp6_input_node, static) = {
763 .function = bfd_udp6_input,
764 .name = "bfd-udp6-input",
765 .vector_size = sizeof (u32),
766 .type = VLIB_NODE_TYPE_INTERNAL,
768 .n_errors = BFD_UDP_N_ERROR,
769 .error_strings = bfd_udp_error_strings,
771 .format_trace = bfd_input_format_trace,
773 .n_next_nodes = BFD_UDP_INPUT_N_NEXT,
776 [BFD_UDP_INPUT_NEXT_NORMAL] = "error-drop",
777 [BFD_UDP_INPUT_NEXT_REPLY] = "ip6-lookup",
782 static clib_error_t *
783 bfd_sw_interface_up_down (vnet_main_t * vnm, u32 sw_if_index, u32 flags)
785 // vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
786 if (!(flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP))
793 VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (bfd_sw_interface_up_down);
795 static clib_error_t *
796 bfd_hw_interface_up_down (vnet_main_t * vnm, u32 hw_if_index, u32 flags)
798 if (flags & VNET_HW_INTERFACE_FLAG_LINK_UP)
805 VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION (bfd_hw_interface_up_down);
810 static clib_error_t *
811 bfd_udp_init (vlib_main_t * vm)
813 mhash_init (&bfd_udp_main.bfd_session_idx_by_bfd_key, sizeof (uword),
814 sizeof (bfd_udp_key_t));
815 bfd_udp_main.bfd_main = &bfd_main;
816 udp_register_dst_port (vm, UDP_DST_PORT_bfd4, bfd_udp4_input_node.index, 1);
817 udp_register_dst_port (vm, UDP_DST_PORT_bfd6, bfd_udp6_input_node.index, 0);
821 VLIB_INIT_FUNCTION (bfd_udp_init);
824 * fd.io coding-style-patch-verification: ON
827 * eval: (c-set-style "gnu")