blob: e835eac4a13339d4ced1c506733f2d9b8036270a [file] [log] [blame]
Klement Sekera2bce0332017-02-09 06:03:46 +01001/*
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 */
Klement Sekerab16bfe32017-02-28 11:56:48 +010015/**
16 * @file
17 * @brief BFD UDP transport layer implementation
18 */
Klement Sekera0e3c0de2016-09-29 14:43:44 +020019#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>
Florin Corasb040f982020-10-20 14:59:43 -070025#include <vnet/udp/udp_local.h>
Dave Barach68b0fb02017-02-28 15:15:56 -050026#include <vnet/udp/udp_packet.h>
Klement Sekera0e3c0de2016-09-29 14:43:44 +020027#include <vnet/ip/lookup.h>
28#include <vnet/ip/icmp46_packet.h>
29#include <vnet/ip/ip4.h>
30#include <vnet/ip/ip6.h>
Klement Sekera0e3c0de2016-09-29 14:43:44 +020031#include <vnet/ip/ip6_packet.h>
Neale Rannscbe25aa2019-09-30 10:53:31 +000032#include <vnet/ip/ip6_link.h>
Klement Sekera0e3c0de2016-09-29 14:43:44 +020033#include <vnet/adj/adj.h>
34#include <vnet/adj/adj_nbr.h>
Klement Sekera239790f2017-02-16 10:53:53 +010035#include <vnet/dpo/receive_dpo.h>
36#include <vnet/fib/fib_entry.h>
37#include <vnet/fib/fib_table.h>
Damjan Marion8973b072022-03-01 15:51:18 +010038#include <vlib/stats/stats.h>
Klement Sekera0e3c0de2016-09-29 14:43:44 +020039#include <vnet/bfd/bfd_debug.h>
40#include <vnet/bfd/bfd_udp.h>
41#include <vnet/bfd/bfd_main.h>
42#include <vnet/bfd/bfd_api.h>
43
44typedef struct
45{
46 bfd_main_t *bfd_main;
47 /* hashmap - bfd session index by bfd key - used for CLI/API lookup, where
48 * discriminator is unknown */
49 mhash_t bfd_session_idx_by_bfd_key;
Klement Sekera239790f2017-02-16 10:53:53 +010050 /* convenience variable */
51 vnet_main_t *vnet_main;
52 /* flag indicating whether echo_source_sw_if_index holds a valid value */
53 int echo_source_is_set;
54 /* loopback interface used to get echo source ip */
55 u32 echo_source_sw_if_index;
Klement Sekerae50e8562017-04-04 16:19:48 +020056 /* node index of "ip4-arp" node */
57 u32 ip4_arp_idx;
58 /* node index of "ip6-discover-neighbor" node */
59 u32 ip6_ndp_idx;
60 /* node index of "ip4-rewrite" node */
61 u32 ip4_rewrite_idx;
62 /* node index of "ip6-rewrite" node */
63 u32 ip6_rewrite_idx;
Matthew G Smith2f260142019-05-22 14:49:24 -050064 /* node index of "ip4-midchain" node */
65 u32 ip4_midchain_idx;
66 /* node index of "ip6-midchain" node */
67 u32 ip6_midchain_idx;
Damjan Marion07a38572018-01-21 06:44:18 -080068 /* log class */
69 vlib_log_class_t log_class;
Klement Sekera88aec652019-03-11 14:04:19 +010070 /* number of active udp4 sessions */
71 u32 udp4_sessions_count;
Klement Sekeracdaf0d82022-02-14 20:20:22 +000072 u32 udp4_sessions_count_stat_seg_entry;
Klement Sekera88aec652019-03-11 14:04:19 +010073 /* number of active udp6 sessions */
74 u32 udp6_sessions_count;
Klement Sekeracdaf0d82022-02-14 20:20:22 +000075 u32 udp6_sessions_count_stat_seg_entry;
Klement Sekera0e3c0de2016-09-29 14:43:44 +020076} bfd_udp_main_t;
77
Klement Sekerae4504c62016-12-08 10:16:41 +010078static vlib_node_registration_t bfd_udp4_input_node;
79static vlib_node_registration_t bfd_udp6_input_node;
Klement Sekeraaeeac3b2017-02-14 07:11:52 +010080static vlib_node_registration_t bfd_udp_echo4_input_node;
81static vlib_node_registration_t bfd_udp_echo6_input_node;
Klement Sekerae4504c62016-12-08 10:16:41 +010082
Klement Sekera0e3c0de2016-09-29 14:43:44 +020083bfd_udp_main_t bfd_udp_main;
84
Klement Sekeracdaf0d82022-02-14 20:20:22 +000085void
86bfd_udp_update_stat_segment_entry (u32 entry, u64 value)
87{
Damjan Marion8973b072022-03-01 15:51:18 +010088 vlib_stats_segment_lock ();
89 vlib_stats_set_gauge (entry, value);
90 vlib_stats_segment_unlock ();
Klement Sekeracdaf0d82022-02-14 20:20:22 +000091}
92
Klement Sekera239790f2017-02-16 10:53:53 +010093vnet_api_error_t
94bfd_udp_set_echo_source (u32 sw_if_index)
95{
96 vnet_sw_interface_t *sw_if =
Dave Barach3940de32019-07-23 16:28:36 -040097 vnet_get_sw_interface_or_null (bfd_udp_main.vnet_main, sw_if_index);
Klement Sekera239790f2017-02-16 10:53:53 +010098 if (sw_if)
99 {
100 bfd_udp_main.echo_source_sw_if_index = sw_if_index;
101 bfd_udp_main.echo_source_is_set = 1;
102 return 0;
103 }
104 return VNET_API_ERROR_BFD_ENOENT;
105}
106
107vnet_api_error_t
Klement Sekeracdaf0d82022-02-14 20:20:22 +0000108bfd_udp_del_echo_source ()
Klement Sekera239790f2017-02-16 10:53:53 +0100109{
110 bfd_udp_main.echo_source_sw_if_index = ~0;
111 bfd_udp_main.echo_source_is_set = 0;
112 return 0;
113}
114
115int
116bfd_udp_is_echo_available (bfd_transport_e transport)
117{
118 if (!bfd_udp_main.echo_source_is_set)
119 {
Klement Sekera73884482017-02-23 09:26:30 +0100120 BFD_DBG ("UDP echo source not set - echo not available");
Klement Sekera239790f2017-02-16 10:53:53 +0100121 return 0;
122 }
123 /*
124 * for the echo to work, we need a loopback interface with at least one
125 * address with netmask length at most 31 (ip4) or 127 (ip6) so that we can
126 * pick an unused address from that subnet
127 */
128 vnet_sw_interface_t *sw_if =
Dave Barach3940de32019-07-23 16:28:36 -0400129 vnet_get_sw_interface_or_null (bfd_udp_main.vnet_main,
130 bfd_udp_main.echo_source_sw_if_index);
Klement Sekera239790f2017-02-16 10:53:53 +0100131 if (sw_if && sw_if->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)
132 {
133 if (BFD_TRANSPORT_UDP4 == transport)
134 {
135 ip4_main_t *im = &ip4_main;
136 ip_interface_address_t *ia = NULL;
137 /* *INDENT-OFF* */
138 foreach_ip_interface_address (&im->lookup_main, ia,
139 bfd_udp_main.echo_source_sw_if_index,
140 0 /* honor unnumbered */, ({
141 if (ia->address_length <= 31)
142 {
143 return 1;
144 }
145 }));
146 /* *INDENT-ON* */
147 }
148 else if (BFD_TRANSPORT_UDP6 == transport)
149 {
150 ip6_main_t *im = &ip6_main;
151 ip_interface_address_t *ia = NULL;
152 /* *INDENT-OFF* */
153 foreach_ip_interface_address (&im->lookup_main, ia,
154 bfd_udp_main.echo_source_sw_if_index,
155 0 /* honor unnumbered */, ({
156 if (ia->address_length <= 127)
157 {
158 return 1;
159 }
160 }));
161 /* *INDENT-ON* */
162 }
163 }
Klement Sekera73884482017-02-23 09:26:30 +0100164 BFD_DBG ("No usable IP address for UDP echo - echo not available");
Klement Sekera239790f2017-02-16 10:53:53 +0100165 return 0;
166}
167
Klement Sekera2bce0332017-02-09 06:03:46 +0100168static u16
169bfd_udp_bs_idx_to_sport (u32 bs_idx)
170{
171 /* The source port MUST be in the range 49152 through 65535. The same UDP
172 * source port number MUST be used for all BFD Control packets associated
173 * with a particular session. The source port number SHOULD be unique among
174 * all BFD sessions on the system. If more than 16384 BFD sessions are
175 * simultaneously active, UDP source port numbers MAY be reused on
176 * multiple sessions, but the number of distinct uses of the same UDP
177 * source port number SHOULD be minimized.
178 */
179 return 49152 + bs_idx % (65535 - 49152 + 1);
180}
181
Klement Sekera239790f2017-02-16 10:53:53 +0100182int
183bfd_udp_get_echo_src_ip4 (ip4_address_t * addr)
184{
185 if (!bfd_udp_main.echo_source_is_set)
186 {
187 BFD_ERR ("cannot find ip4 address, echo source not set");
188 return 0;
189 }
190 ip_interface_address_t *ia = NULL;
191 ip4_main_t *im = &ip4_main;
192
193 /* *INDENT-OFF* */
194 foreach_ip_interface_address (
195 &im->lookup_main, ia, bfd_udp_main.echo_source_sw_if_index,
196 0 /* honor unnumbered */, ({
197 ip4_address_t *x =
198 ip_interface_address_get_address (&im->lookup_main, ia);
199 if (ia->address_length <= 31)
200 {
201 addr->as_u32 = clib_host_to_net_u32 (x->as_u32);
Klement Sekeraf3bcdbf2017-05-02 07:38:01 +0200202 /*
203 * flip the last bit to get a different address, might be network,
204 * we don't care ...
205 */
206 addr->as_u32 ^= 1;
Klement Sekera239790f2017-02-16 10:53:53 +0100207 addr->as_u32 = clib_net_to_host_u32 (addr->as_u32);
208 return 1;
209 }
210 }));
211 /* *INDENT-ON* */
212 BFD_ERR ("cannot find ip4 address, no usable address found");
213 return 0;
214}
215
216int
217bfd_udp_get_echo_src_ip6 (ip6_address_t * addr)
218{
219 if (!bfd_udp_main.echo_source_is_set)
220 {
221 BFD_ERR ("cannot find ip6 address, echo source not set");
222 return 0;
223 }
224 ip_interface_address_t *ia = NULL;
225 ip6_main_t *im = &ip6_main;
226
227 /* *INDENT-OFF* */
228 foreach_ip_interface_address (
229 &im->lookup_main, ia, bfd_udp_main.echo_source_sw_if_index,
230 0 /* honor unnumbered */, ({
231 ip6_address_t *x =
232 ip_interface_address_get_address (&im->lookup_main, ia);
233 if (ia->address_length <= 127)
234 {
235 *addr = *x;
236 addr->as_u8[15] ^= 1; /* flip the last bit of the address */
Klement Sekera239790f2017-02-16 10:53:53 +0100237 return 1;
238 }
239 }));
240 /* *INDENT-ON* */
241 BFD_ERR ("cannot find ip6 address, no usable address found");
242 return 0;
243}
244
Klement Sekera73884482017-02-23 09:26:30 +0100245void
Klement Sekeraf3bcdbf2017-05-02 07:38:01 +0200246bfd_udp_get_echo_source (int *is_set, u32 * sw_if_index,
247 int *have_usable_ip4, ip4_address_t * ip4,
248 int *have_usable_ip6, ip6_address_t * ip6)
Klement Sekera73884482017-02-23 09:26:30 +0100249{
250 if (bfd_udp_main.echo_source_is_set)
251 {
252 *is_set = 1;
253 *sw_if_index = bfd_udp_main.echo_source_sw_if_index;
254 *have_usable_ip4 = bfd_udp_get_echo_src_ip4 (ip4);
255 *have_usable_ip6 = bfd_udp_get_echo_src_ip6 (ip6);
256 }
257 else
258 {
259 *is_set = 0;
260 }
261}
262
Klement Sekera239790f2017-02-16 10:53:53 +0100263int
Klement Sekeraf3bcdbf2017-05-02 07:38:01 +0200264bfd_add_udp4_transport (vlib_main_t * vm, u32 bi, const bfd_session_t * bs,
265 int is_echo)
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200266{
Klement Sekera2bce0332017-02-09 06:03:46 +0100267 const bfd_udp_session_t *bus = &bs->udp;
Klement Sekera46a87ad2017-01-02 08:22:23 +0100268 const bfd_udp_key_t *key = &bus->key;
Klement Sekerae50e8562017-04-04 16:19:48 +0200269 vlib_buffer_t *b = vlib_get_buffer (vm, bi);
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200270
Damjan Marion213b5aa2017-07-13 21:19:27 +0200271 b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200272 vnet_buffer (b)->ip.adj_index[VLIB_RX] = bus->adj_index;
273 vnet_buffer (b)->ip.adj_index[VLIB_TX] = bus->adj_index;
Klement Sekerae50e8562017-04-04 16:19:48 +0200274 vnet_buffer (b)->sw_if_index[VLIB_RX] = 0;
275 vnet_buffer (b)->sw_if_index[VLIB_TX] = ~0;
Klement Sekera402ed312017-01-18 09:44:36 +0100276 typedef struct
277 {
278 ip4_header_t ip4;
279 udp_header_t udp;
280 } ip4_udp_headers;
Klement Sekerab17dd962017-01-09 07:43:48 +0100281 ip4_udp_headers *headers = NULL;
Klement Sekera402ed312017-01-18 09:44:36 +0100282 vlib_buffer_advance (b, -sizeof (*headers));
283 headers = vlib_buffer_get_current (b);
Dave Barachb7b92992018-10-17 10:38:51 -0400284 clib_memset (headers, 0, sizeof (*headers));
Klement Sekera402ed312017-01-18 09:44:36 +0100285 headers->ip4.ip_version_and_header_length = 0x45;
286 headers->ip4.ttl = 255;
287 headers->ip4.protocol = IP_PROTOCOL_UDP;
Klement Sekera2bce0332017-02-09 06:03:46 +0100288 headers->udp.src_port =
289 clib_host_to_net_u16 (bfd_udp_bs_idx_to_sport (bs->bs_idx));
Klement Sekera239790f2017-02-16 10:53:53 +0100290 if (is_echo)
291 {
292 int rv;
293 if (!(rv = bfd_udp_get_echo_src_ip4 (&headers->ip4.src_address)))
294 {
295 return rv;
296 }
297 headers->ip4.dst_address.as_u32 = key->local_addr.ip4.as_u32;
298 headers->udp.dst_port = clib_host_to_net_u16 (UDP_DST_PORT_bfd_echo4);
299 }
300 else
301 {
302 headers->ip4.src_address.as_u32 = key->local_addr.ip4.as_u32;
303 headers->ip4.dst_address.as_u32 = key->peer_addr.ip4.as_u32;
304 headers->udp.dst_port = clib_host_to_net_u16 (UDP_DST_PORT_bfd4);
305 }
Klement Sekera46a87ad2017-01-02 08:22:23 +0100306
307 /* fix ip length, checksum and udp length */
308 const u16 ip_length = vlib_buffer_length_in_chain (vm, b);
309
Klement Sekera402ed312017-01-18 09:44:36 +0100310 headers->ip4.length = clib_host_to_net_u16 (ip_length);
311 headers->ip4.checksum = ip4_header_checksum (&headers->ip4);
Klement Sekera46a87ad2017-01-02 08:22:23 +0100312
Klement Sekera402ed312017-01-18 09:44:36 +0100313 const u16 udp_length = ip_length - (sizeof (headers->ip4));
314 headers->udp.length = clib_host_to_net_u16 (udp_length);
Klement Sekera239790f2017-02-16 10:53:53 +0100315 return 1;
Klement Sekera46a87ad2017-01-02 08:22:23 +0100316}
317
Klement Sekera239790f2017-02-16 10:53:53 +0100318int
Klement Sekeraf3bcdbf2017-05-02 07:38:01 +0200319bfd_add_udp6_transport (vlib_main_t * vm, u32 bi, const bfd_session_t * bs,
320 int is_echo)
Klement Sekera46a87ad2017-01-02 08:22:23 +0100321{
Klement Sekera2bce0332017-02-09 06:03:46 +0100322 const bfd_udp_session_t *bus = &bs->udp;
Klement Sekera46a87ad2017-01-02 08:22:23 +0100323 const bfd_udp_key_t *key = &bus->key;
Klement Sekerae50e8562017-04-04 16:19:48 +0200324 vlib_buffer_t *b = vlib_get_buffer (vm, bi);
Klement Sekera46a87ad2017-01-02 08:22:23 +0100325
Damjan Marion213b5aa2017-07-13 21:19:27 +0200326 b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
Klement Sekera46a87ad2017-01-02 08:22:23 +0100327 vnet_buffer (b)->ip.adj_index[VLIB_RX] = bus->adj_index;
328 vnet_buffer (b)->ip.adj_index[VLIB_TX] = bus->adj_index;
Klement Sekerae50e8562017-04-04 16:19:48 +0200329 vnet_buffer (b)->sw_if_index[VLIB_RX] = 0;
330 vnet_buffer (b)->sw_if_index[VLIB_TX] = 0;
Klement Sekera402ed312017-01-18 09:44:36 +0100331 typedef struct
332 {
333 ip6_header_t ip6;
334 udp_header_t udp;
335 } ip6_udp_headers;
Klement Sekerab17dd962017-01-09 07:43:48 +0100336 ip6_udp_headers *headers = NULL;
337 vlib_buffer_advance (b, -sizeof (*headers));
338 headers = vlib_buffer_get_current (b);
Dave Barachb7b92992018-10-17 10:38:51 -0400339 clib_memset (headers, 0, sizeof (*headers));
Klement Sekera402ed312017-01-18 09:44:36 +0100340 headers->ip6.ip_version_traffic_class_and_flow_label =
Klement Sekerac5fccc02017-01-18 09:56:00 +0100341 clib_host_to_net_u32 (0x6 << 28);
Klement Sekera402ed312017-01-18 09:44:36 +0100342 headers->ip6.hop_limit = 255;
343 headers->ip6.protocol = IP_PROTOCOL_UDP;
Klement Sekera2bce0332017-02-09 06:03:46 +0100344 headers->udp.src_port =
345 clib_host_to_net_u16 (bfd_udp_bs_idx_to_sport (bs->bs_idx));
Klement Sekera239790f2017-02-16 10:53:53 +0100346 if (is_echo)
347 {
348 int rv;
349 if (!(rv = bfd_udp_get_echo_src_ip6 (&headers->ip6.src_address)))
350 {
351 return rv;
352 }
Dave Barach178cf492018-11-13 16:34:13 -0500353 clib_memcpy_fast (&headers->ip6.dst_address, &key->local_addr.ip6,
354 sizeof (headers->ip6.dst_address));
Klement Sekera239790f2017-02-16 10:53:53 +0100355
356 headers->udp.dst_port = clib_host_to_net_u16 (UDP_DST_PORT_bfd_echo6);
357 }
358 else
359 {
Dave Barach178cf492018-11-13 16:34:13 -0500360 clib_memcpy_fast (&headers->ip6.src_address, &key->local_addr.ip6,
361 sizeof (headers->ip6.src_address));
362 clib_memcpy_fast (&headers->ip6.dst_address, &key->peer_addr.ip6,
363 sizeof (headers->ip6.dst_address));
Klement Sekera239790f2017-02-16 10:53:53 +0100364 headers->udp.dst_port = clib_host_to_net_u16 (UDP_DST_PORT_bfd6);
365 }
Klement Sekera46a87ad2017-01-02 08:22:23 +0100366
367 /* fix ip payload length and udp length */
Klement Sekerac5fccc02017-01-18 09:56:00 +0100368 const u16 udp_length =
Klement Sekera402ed312017-01-18 09:44:36 +0100369 vlib_buffer_length_in_chain (vm, b) - (sizeof (headers->ip6));
370 headers->udp.length = clib_host_to_net_u16 (udp_length);
371 headers->ip6.payload_length = headers->udp.length;
Klement Sekera46a87ad2017-01-02 08:22:23 +0100372
373 /* IPv6 UDP checksum is mandatory */
374 int bogus = 0;
Klement Sekera402ed312017-01-18 09:44:36 +0100375 headers->udp.checksum =
376 ip6_tcp_udp_icmp_compute_checksum (vm, b, &headers->ip6, &bogus);
Klement Sekera46a87ad2017-01-02 08:22:23 +0100377 ASSERT (bogus == 0);
Klement Sekera402ed312017-01-18 09:44:36 +0100378 if (headers->udp.checksum == 0)
Klement Sekera46a87ad2017-01-02 08:22:23 +0100379 {
Klement Sekera402ed312017-01-18 09:44:36 +0100380 headers->udp.checksum = 0xffff;
Klement Sekera46a87ad2017-01-02 08:22:23 +0100381 }
Klement Sekera239790f2017-02-16 10:53:53 +0100382 return 1;
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200383}
384
Klement Sekerae50e8562017-04-04 16:19:48 +0200385static void
Klement Sekeracdaf0d82022-02-14 20:20:22 +0000386bfd_create_frame_to_next_node (vlib_main_t *vm, bfd_main_t *bm,
387 const bfd_session_t *bs, u32 bi, u32 next_node,
388 vlib_combined_counter_main_t *tx_counter)
Klement Sekerae50e8562017-04-04 16:19:48 +0200389{
390 vlib_frame_t *f = vlib_get_frame_to_node (vm, next_node);
391 u32 *to_next = vlib_frame_vector_args (f);
392 to_next[0] = bi;
393 f->n_vectors = 1;
394 vlib_put_frame_to_node (vm, next_node, f);
Klement Sekeracdaf0d82022-02-14 20:20:22 +0000395 vlib_buffer_t *b = vlib_get_buffer (vm, bi);
396 vlib_increment_combined_counter (tx_counter, vm->thread_index, bs->bs_idx, 1,
397 vlib_buffer_length_in_chain (vm, b));
Klement Sekerae50e8562017-04-04 16:19:48 +0200398}
399
400int
401bfd_udp_calc_next_node (const struct bfd_session_s *bs, u32 * next_node)
402{
Matthew G Smith2f260142019-05-22 14:49:24 -0500403 vnet_main_t *vnm = vnet_get_main ();
Klement Sekerae50e8562017-04-04 16:19:48 +0200404 const bfd_udp_session_t *bus = &bs->udp;
405 ip_adjacency_t *adj = adj_get (bus->adj_index);
Matthew G Smith2f260142019-05-22 14:49:24 -0500406
407 /* don't try to send the buffer if the interface is not up */
408 if (!vnet_sw_interface_is_up (vnm, bus->key.sw_if_index))
409 return 0;
410
Klement Sekerae50e8562017-04-04 16:19:48 +0200411 switch (adj->lookup_next_index)
412 {
413 case IP_LOOKUP_NEXT_ARP:
414 switch (bs->transport)
415 {
416 case BFD_TRANSPORT_UDP4:
417 *next_node = bfd_udp_main.ip4_arp_idx;
418 return 1;
419 case BFD_TRANSPORT_UDP6:
420 *next_node = bfd_udp_main.ip6_ndp_idx;
421 return 1;
422 }
423 break;
424 case IP_LOOKUP_NEXT_REWRITE:
425 switch (bs->transport)
426 {
427 case BFD_TRANSPORT_UDP4:
428 *next_node = bfd_udp_main.ip4_rewrite_idx;
429 return 1;
430 case BFD_TRANSPORT_UDP6:
431 *next_node = bfd_udp_main.ip6_rewrite_idx;
432 return 1;
433 }
434 break;
Matthew G Smith2f260142019-05-22 14:49:24 -0500435 case IP_LOOKUP_NEXT_MIDCHAIN:
436 switch (bs->transport)
437 {
438 case BFD_TRANSPORT_UDP4:
439 *next_node = bfd_udp_main.ip4_midchain_idx;
440 return 1;
441 case BFD_TRANSPORT_UDP6:
442 *next_node = bfd_udp_main.ip6_midchain_idx;
443 return 1;
444 }
445 break;
Klement Sekerae50e8562017-04-04 16:19:48 +0200446 default:
447 /* drop */
448 break;
449 }
450 return 0;
451}
452
453int
Klement Sekeracdaf0d82022-02-14 20:20:22 +0000454bfd_transport_udp4 (vlib_main_t *vm, u32 bi, const struct bfd_session_s *bs,
455 int is_echo)
Klement Sekerae50e8562017-04-04 16:19:48 +0200456{
457 u32 next_node;
458 int rv = bfd_udp_calc_next_node (bs, &next_node);
Klement Sekeracdaf0d82022-02-14 20:20:22 +0000459 bfd_main_t *bm = bfd_udp_main.bfd_main;
Klement Sekerae50e8562017-04-04 16:19:48 +0200460 if (rv)
461 {
Klement Sekeracdaf0d82022-02-14 20:20:22 +0000462 bfd_create_frame_to_next_node (vm, bm, bs, bi, next_node,
463 is_echo ? &bm->tx_echo_counter :
464 &bm->tx_counter);
Klement Sekerae50e8562017-04-04 16:19:48 +0200465 }
466 return rv;
467}
468
469int
Klement Sekeracdaf0d82022-02-14 20:20:22 +0000470bfd_transport_udp6 (vlib_main_t *vm, u32 bi, const struct bfd_session_s *bs,
471 int is_echo)
Klement Sekerae50e8562017-04-04 16:19:48 +0200472{
473 u32 next_node;
474 int rv = bfd_udp_calc_next_node (bs, &next_node);
Klement Sekeracdaf0d82022-02-14 20:20:22 +0000475 bfd_main_t *bm = bfd_udp_main.bfd_main;
Klement Sekerae50e8562017-04-04 16:19:48 +0200476 if (rv)
477 {
Klement Sekeracdaf0d82022-02-14 20:20:22 +0000478 bfd_create_frame_to_next_node (
479 vm, bfd_udp_main.bfd_main, bs, bi, next_node,
480 is_echo ? &bm->tx_echo_counter : &bm->tx_counter);
Klement Sekerae50e8562017-04-04 16:19:48 +0200481 }
482 return 1;
483}
484
Klement Sekerac5fccc02017-01-18 09:56:00 +0100485static bfd_session_t *
486bfd_lookup_session (bfd_udp_main_t * bum, const bfd_udp_key_t * key)
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200487{
488 uword *p = mhash_get (&bum->bfd_session_idx_by_bfd_key, key);
489 if (p)
490 {
491 return bfd_find_session_by_idx (bum->bfd_main, *p);
492 }
493 return 0;
494}
495
Klement Sekerab17dd962017-01-09 07:43:48 +0100496static void
497bfd_udp_key_init (bfd_udp_key_t * key, u32 sw_if_index,
498 const ip46_address_t * local_addr,
499 const ip46_address_t * peer_addr)
500{
Dave Barachb7b92992018-10-17 10:38:51 -0400501 clib_memset (key, 0, sizeof (*key));
Klement Sekerab17dd962017-01-09 07:43:48 +0100502 key->sw_if_index = sw_if_index;
503 key->local_addr.as_u64[0] = local_addr->as_u64[0];
504 key->local_addr.as_u64[1] = local_addr->as_u64[1];
505 key->peer_addr.as_u64[0] = peer_addr->as_u64[0];
506 key->peer_addr.as_u64[1] = peer_addr->as_u64[1];
507}
508
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200509static vnet_api_error_t
Klement Sekera88aec652019-03-11 14:04:19 +0100510bfd_udp_add_session_internal (vlib_main_t * vm, bfd_udp_main_t * bum,
511 u32 sw_if_index, u32 desired_min_tx_usec,
Klement Sekeraa57a9702017-02-02 06:58:07 +0100512 u32 required_min_rx_usec, u8 detect_mult,
Klement Sekerac5fccc02017-01-18 09:56:00 +0100513 const ip46_address_t * local_addr,
514 const ip46_address_t * peer_addr,
Klement Sekerab17dd962017-01-09 07:43:48 +0100515 bfd_session_t ** bs_out)
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200516{
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200517 /* get a pool entry and if we end up not needing it, give it back */
Klement Sekera239790f2017-02-16 10:53:53 +0100518 bfd_transport_e t = BFD_TRANSPORT_UDP4;
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200519 if (!ip46_address_is_ip4 (local_addr))
520 {
521 t = BFD_TRANSPORT_UDP6;
522 }
523 bfd_session_t *bs = bfd_get_session (bum->bfd_main, t);
Klement Sekera239790f2017-02-16 10:53:53 +0100524 if (!bs)
525 {
Klement Sekera239790f2017-02-16 10:53:53 +0100526 return VNET_API_ERROR_BFD_EAGAIN;
527 }
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200528 bfd_udp_session_t *bus = &bs->udp;
Dave Barachb7b92992018-10-17 10:38:51 -0400529 clib_memset (bus, 0, sizeof (*bus));
Neale Ranns32fd89b2022-02-15 08:28:19 +0000530 bus->adj_index = ADJ_INDEX_INVALID;
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200531 bfd_udp_key_t *key = &bus->key;
Klement Sekerab17dd962017-01-09 07:43:48 +0100532 bfd_udp_key_init (key, sw_if_index, local_addr, peer_addr);
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200533 const bfd_session_t *tmp = bfd_lookup_session (bum, key);
534 if (tmp)
535 {
Damjan Marion07a38572018-01-21 06:44:18 -0800536 vlib_log_err (bum->log_class,
537 "duplicate bfd-udp session, existing bs_idx=%d",
Klement Sekerab17dd962017-01-09 07:43:48 +0100538 tmp->bs_idx);
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200539 bfd_put_session (bum->bfd_main, bs);
540 return VNET_API_ERROR_BFD_EEXIST;
541 }
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200542 mhash_set (&bum->bfd_session_idx_by_bfd_key, key, bs->bs_idx, NULL);
543 BFD_DBG ("session created, bs_idx=%u, sw_if_index=%d, local=%U, peer=%U",
Klement Sekerac5fccc02017-01-18 09:56:00 +0100544 bs->bs_idx, key->sw_if_index, format_ip46_address,
545 &key->local_addr, IP46_TYPE_ANY, format_ip46_address,
546 &key->peer_addr, IP46_TYPE_ANY);
Damjan Marion07a38572018-01-21 06:44:18 -0800547 vlib_log_info (bum->log_class, "create BFD session: %U",
548 format_bfd_session, bs);
Neale Ranns558a3542022-02-15 08:24:48 +0000549 const ip46_address_t *peer =
550 (vnet_sw_interface_is_p2p (vnet_get_main (), key->sw_if_index) ?
551 &zero_addr :
552 &key->peer_addr);
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200553 if (BFD_TRANSPORT_UDP4 == t)
554 {
555 bus->adj_index = adj_nbr_add_or_lock (FIB_PROTOCOL_IP4, VNET_LINK_IP4,
Neale Ranns558a3542022-02-15 08:24:48 +0000556 peer, key->sw_if_index);
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200557 BFD_DBG ("adj_nbr_add_or_lock(FIB_PROTOCOL_IP4, VNET_LINK_IP4, %U, %d) "
Neale Ranns558a3542022-02-15 08:24:48 +0000558 "returns %d",
559 format_ip46_address, peer, IP46_TYPE_ANY, key->sw_if_index,
560 bus->adj_index);
Klement Sekera88aec652019-03-11 14:04:19 +0100561 ++bum->udp4_sessions_count;
Klement Sekeracdaf0d82022-02-14 20:20:22 +0000562 bfd_udp_update_stat_segment_entry (
563 bum->udp4_sessions_count_stat_seg_entry, bum->udp4_sessions_count);
Klement Sekera88aec652019-03-11 14:04:19 +0100564 if (1 == bum->udp4_sessions_count)
565 {
566 udp_register_dst_port (vm, UDP_DST_PORT_bfd4,
567 bfd_udp4_input_node.index, 1);
568 udp_register_dst_port (vm, UDP_DST_PORT_bfd_echo4,
569 bfd_udp_echo4_input_node.index, 1);
570 }
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200571 }
572 else
573 {
574 bus->adj_index = adj_nbr_add_or_lock (FIB_PROTOCOL_IP6, VNET_LINK_IP6,
Neale Ranns558a3542022-02-15 08:24:48 +0000575 peer, key->sw_if_index);
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200576 BFD_DBG ("adj_nbr_add_or_lock(FIB_PROTOCOL_IP6, VNET_LINK_IP6, %U, %d) "
Neale Ranns558a3542022-02-15 08:24:48 +0000577 "returns %d",
578 format_ip46_address, peer, IP46_TYPE_ANY, key->sw_if_index,
579 bus->adj_index);
Klement Sekera88aec652019-03-11 14:04:19 +0100580 ++bum->udp6_sessions_count;
Klement Sekeracdaf0d82022-02-14 20:20:22 +0000581 bfd_udp_update_stat_segment_entry (
582 bum->udp6_sessions_count_stat_seg_entry, bum->udp6_sessions_count);
Klement Sekera88aec652019-03-11 14:04:19 +0100583 if (1 == bum->udp6_sessions_count)
584 {
585 udp_register_dst_port (vm, UDP_DST_PORT_bfd6,
586 bfd_udp6_input_node.index, 0);
587 udp_register_dst_port (vm, UDP_DST_PORT_bfd_echo6,
588 bfd_udp_echo6_input_node.index, 0);
589 }
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200590 }
Klement Sekerab17dd962017-01-09 07:43:48 +0100591 *bs_out = bs;
Klement Sekeraa57a9702017-02-02 06:58:07 +0100592 return bfd_session_set_params (bum->bfd_main, bs, desired_min_tx_usec,
593 required_min_rx_usec, detect_mult);
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200594}
595
596static vnet_api_error_t
Klement Sekerac5fccc02017-01-18 09:56:00 +0100597bfd_udp_validate_api_input (u32 sw_if_index,
598 const ip46_address_t * local_addr,
599 const ip46_address_t * peer_addr)
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200600{
Damjan Marion07a38572018-01-21 06:44:18 -0800601 bfd_udp_main_t *bum = &bfd_udp_main;
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200602 vnet_sw_interface_t *sw_if =
Dave Barach3940de32019-07-23 16:28:36 -0400603 vnet_get_sw_interface_or_null (bfd_udp_main.vnet_main, sw_if_index);
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200604 if (!sw_if)
605 {
Damjan Marion07a38572018-01-21 06:44:18 -0800606 vlib_log_err (bum->log_class,
607 "got NULL sw_if when getting interface by index %u",
608 sw_if_index);
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200609 return VNET_API_ERROR_INVALID_SW_IF_INDEX;
610 }
611 if (ip46_address_is_ip4 (local_addr))
612 {
613 if (!ip46_address_is_ip4 (peer_addr))
Klement Sekerac5fccc02017-01-18 09:56:00 +0100614 {
Damjan Marion07a38572018-01-21 06:44:18 -0800615 vlib_log_err (bum->log_class,
616 "IP family mismatch (local is ipv4, peer is ipv6)");
Klement Sekerac5fccc02017-01-18 09:56:00 +0100617 return VNET_API_ERROR_INVALID_ARGUMENT;
618 }
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200619 }
620 else
621 {
622 if (ip46_address_is_ip4 (peer_addr))
Klement Sekerac5fccc02017-01-18 09:56:00 +0100623 {
Damjan Marion07a38572018-01-21 06:44:18 -0800624 vlib_log_err (bum->log_class,
625 "IP family mismatch (local is ipv6, peer is ipv4)");
Klement Sekerac5fccc02017-01-18 09:56:00 +0100626 return VNET_API_ERROR_INVALID_ARGUMENT;
627 }
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200628 }
629
630 return 0;
631}
632
Klement Sekerab17dd962017-01-09 07:43:48 +0100633static vnet_api_error_t
634bfd_udp_find_session_by_api_input (u32 sw_if_index,
635 const ip46_address_t * local_addr,
636 const ip46_address_t * peer_addr,
637 bfd_session_t ** bs_out)
638{
639 vnet_api_error_t rv =
640 bfd_udp_validate_api_input (sw_if_index, local_addr, peer_addr);
641 if (!rv)
642 {
643 bfd_udp_main_t *bum = &bfd_udp_main;
644 bfd_udp_key_t key;
645 bfd_udp_key_init (&key, sw_if_index, local_addr, peer_addr);
646 bfd_session_t *bs = bfd_lookup_session (bum, &key);
647 if (bs)
648 {
649 *bs_out = bs;
650 }
651 else
652 {
Damjan Marion07a38572018-01-21 06:44:18 -0800653 vlib_log_err (bum->log_class,
654 "BFD session not found, sw_if_index=%u, local=%U, peer=%U",
655 sw_if_index, format_ip46_address, local_addr,
656 IP46_TYPE_ANY, format_ip46_address, peer_addr,
657 IP46_TYPE_ANY);
Klement Sekerab17dd962017-01-09 07:43:48 +0100658 return VNET_API_ERROR_BFD_ENOENT;
659 }
660 }
661 return rv;
662}
663
664static vnet_api_error_t
Klement Sekeraa57a9702017-02-02 06:58:07 +0100665bfd_api_verify_common (u32 sw_if_index, u32 desired_min_tx_usec,
Klement Sekerab59f63b2022-02-14 20:19:28 +0000666 u8 detect_mult, const ip46_address_t *local_addr,
667 const ip46_address_t *peer_addr)
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200668{
Damjan Marion07a38572018-01-21 06:44:18 -0800669 bfd_udp_main_t *bum = &bfd_udp_main;
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200670 vnet_api_error_t rv =
Klement Sekerac5fccc02017-01-18 09:56:00 +0100671 bfd_udp_validate_api_input (sw_if_index, local_addr, peer_addr);
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200672 if (rv)
673 {
674 return rv;
675 }
676 if (detect_mult < 1)
677 {
Damjan Marion07a38572018-01-21 06:44:18 -0800678 vlib_log_err (bum->log_class, "detect_mult < 1");
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200679 return VNET_API_ERROR_INVALID_ARGUMENT;
680 }
Klement Sekeraa57a9702017-02-02 06:58:07 +0100681 if (desired_min_tx_usec < 1)
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200682 {
Damjan Marion07a38572018-01-21 06:44:18 -0800683 vlib_log_err (bum->log_class, "desired_min_tx_usec < 1");
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200684 return VNET_API_ERROR_INVALID_ARGUMENT;
685 }
Klement Sekerab17dd962017-01-09 07:43:48 +0100686 return 0;
687}
688
689static void
Klement Sekera88aec652019-03-11 14:04:19 +0100690bfd_udp_del_session_internal (vlib_main_t * vm, bfd_session_t * bs)
Klement Sekerab17dd962017-01-09 07:43:48 +0100691{
692 bfd_udp_main_t *bum = &bfd_udp_main;
693 BFD_DBG ("free bfd-udp session, bs_idx=%d", bs->bs_idx);
Neale Ranns32fd89b2022-02-15 08:28:19 +0000694 bfd_session_stop (bum->bfd_main, bs);
Klement Sekerab17dd962017-01-09 07:43:48 +0100695 mhash_unset (&bum->bfd_session_idx_by_bfd_key, &bs->udp.key, NULL);
696 adj_unlock (bs->udp.adj_index);
Klement Sekera88aec652019-03-11 14:04:19 +0100697 switch (bs->transport)
698 {
699 case BFD_TRANSPORT_UDP4:
700 --bum->udp4_sessions_count;
Klement Sekeracdaf0d82022-02-14 20:20:22 +0000701 bfd_udp_update_stat_segment_entry (
702 bum->udp4_sessions_count_stat_seg_entry, bum->udp4_sessions_count);
Klement Sekera88aec652019-03-11 14:04:19 +0100703 if (!bum->udp4_sessions_count)
704 {
705 udp_unregister_dst_port (vm, UDP_DST_PORT_bfd4, 1);
706 udp_unregister_dst_port (vm, UDP_DST_PORT_bfd_echo4, 1);
707 }
708 break;
709 case BFD_TRANSPORT_UDP6:
710 --bum->udp6_sessions_count;
Klement Sekeracdaf0d82022-02-14 20:20:22 +0000711 bfd_udp_update_stat_segment_entry (
712 bum->udp6_sessions_count_stat_seg_entry, bum->udp6_sessions_count);
Klement Sekera88aec652019-03-11 14:04:19 +0100713 if (!bum->udp6_sessions_count)
714 {
715 udp_unregister_dst_port (vm, UDP_DST_PORT_bfd6, 0);
716 udp_unregister_dst_port (vm, UDP_DST_PORT_bfd_echo6, 0);
717 }
718 break;
719 }
Klement Sekerab17dd962017-01-09 07:43:48 +0100720 bfd_put_session (bum->bfd_main, bs);
721}
722
Neale Ranns63f2c7d2022-02-09 13:47:29 +0000723static vnet_api_error_t
724bfd_udp_add_and_start_session (u32 sw_if_index,
725 const ip46_address_t *local_addr,
726 const ip46_address_t *peer_addr,
727 u32 desired_min_tx_usec,
728 u32 required_min_rx_usec, u8 detect_mult,
729 u8 is_authenticated, u32 conf_key_id,
730 u8 bfd_key_id)
731{
732 bfd_session_t *bs = NULL;
733 vnet_api_error_t rv;
734
735 rv = bfd_udp_add_session_internal (
736 vlib_get_main (), &bfd_udp_main, sw_if_index, desired_min_tx_usec,
737 required_min_rx_usec, detect_mult, local_addr, peer_addr, &bs);
738
739 if (!rv && is_authenticated)
740 {
741 rv = bfd_auth_activate (bs, conf_key_id, bfd_key_id,
742 0 /* is not delayed */);
743 if (rv)
744 {
745 bfd_udp_del_session_internal (vlib_get_main (), bs);
746 }
747 }
748 if (!rv)
749 {
750 bfd_session_start (bfd_udp_main.bfd_main, bs);
751 }
752
753 return rv;
754}
755
Klement Sekerab17dd962017-01-09 07:43:48 +0100756vnet_api_error_t
757bfd_udp_add_session (u32 sw_if_index, const ip46_address_t * local_addr,
Klement Sekeraa57a9702017-02-02 06:58:07 +0100758 const ip46_address_t * peer_addr,
759 u32 desired_min_tx_usec, u32 required_min_rx_usec,
760 u8 detect_mult, u8 is_authenticated, u32 conf_key_id,
761 u8 bfd_key_id)
Klement Sekerab17dd962017-01-09 07:43:48 +0100762{
Dave Barach1e3417f2018-07-25 08:30:27 -0400763 bfd_main_t *bm = &bfd_main;
764 bfd_lock (bm);
765
Klement Sekerab59f63b2022-02-14 20:19:28 +0000766 vnet_api_error_t rv = bfd_api_verify_common (
767 sw_if_index, desired_min_tx_usec, detect_mult, local_addr, peer_addr);
Neale Ranns63f2c7d2022-02-09 13:47:29 +0000768
769 if (!rv)
770 rv = bfd_udp_add_and_start_session (
771 sw_if_index, local_addr, peer_addr, desired_min_tx_usec,
772 required_min_rx_usec, detect_mult, is_authenticated, conf_key_id,
773 bfd_key_id);
774
775 bfd_unlock (bm);
776 return rv;
777}
778
779vnet_api_error_t
780bfd_udp_upd_session (u32 sw_if_index, const ip46_address_t *local_addr,
781 const ip46_address_t *peer_addr, u32 desired_min_tx_usec,
782 u32 required_min_rx_usec, u8 detect_mult,
783 u8 is_authenticated, u32 conf_key_id, u8 bfd_key_id)
784{
785 bfd_main_t *bm = &bfd_main;
786 bfd_lock (bm);
787
788 vnet_api_error_t rv = bfd_api_verify_common (
Klement Sekerab59f63b2022-02-14 20:19:28 +0000789 sw_if_index, desired_min_tx_usec, detect_mult, local_addr, peer_addr);
Klement Sekerab17dd962017-01-09 07:43:48 +0100790 if (!rv)
791 {
Neale Ranns63f2c7d2022-02-09 13:47:29 +0000792 bfd_session_t *bs = NULL;
793
794 rv = bfd_udp_find_session_by_api_input (sw_if_index, local_addr,
795 peer_addr, &bs);
796 if (VNET_API_ERROR_BFD_ENOENT == rv)
797 rv = bfd_udp_add_and_start_session (
798 sw_if_index, local_addr, peer_addr, desired_min_tx_usec,
799 required_min_rx_usec, detect_mult, is_authenticated, conf_key_id,
800 bfd_key_id);
801 else
802 rv = bfd_session_set_params (bfd_udp_main.bfd_main, bs,
803 desired_min_tx_usec, required_min_rx_usec,
804 detect_mult);
Klement Sekerab17dd962017-01-09 07:43:48 +0100805 }
806
Dave Barach1e3417f2018-07-25 08:30:27 -0400807 bfd_unlock (bm);
Klement Sekerab17dd962017-01-09 07:43:48 +0100808 return rv;
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200809}
810
Klement Sekerac5fccc02017-01-18 09:56:00 +0100811vnet_api_error_t
Neale Ranns63f2c7d2022-02-09 13:47:29 +0000812bfd_udp_mod_session (u32 sw_if_index, const ip46_address_t *local_addr,
813 const ip46_address_t *peer_addr, u32 desired_min_tx_usec,
Klement Sekeraa57a9702017-02-02 06:58:07 +0100814 u32 required_min_rx_usec, u8 detect_mult)
815{
816 bfd_session_t *bs = NULL;
Dave Barach1e3417f2018-07-25 08:30:27 -0400817 bfd_main_t *bm = &bfd_main;
818 vnet_api_error_t error;
819 bfd_lock (bm);
Klement Sekeraa57a9702017-02-02 06:58:07 +0100820 vnet_api_error_t rv =
821 bfd_udp_find_session_by_api_input (sw_if_index, local_addr, peer_addr,
822 &bs);
823 if (rv)
824 {
Dave Barach1e3417f2018-07-25 08:30:27 -0400825 bfd_unlock (bm);
Klement Sekeraa57a9702017-02-02 06:58:07 +0100826 return rv;
827 }
828
Dave Barach1e3417f2018-07-25 08:30:27 -0400829 error = bfd_session_set_params (bfd_udp_main.bfd_main, bs,
830 desired_min_tx_usec, required_min_rx_usec,
831 detect_mult);
832 bfd_unlock (bm);
833 return error;
Klement Sekeraa57a9702017-02-02 06:58:07 +0100834}
835
836vnet_api_error_t
Klement Sekerac5fccc02017-01-18 09:56:00 +0100837bfd_udp_del_session (u32 sw_if_index,
838 const ip46_address_t * local_addr,
839 const ip46_address_t * peer_addr)
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200840{
Klement Sekerab17dd962017-01-09 07:43:48 +0100841 bfd_session_t *bs = NULL;
Dave Barach1e3417f2018-07-25 08:30:27 -0400842 bfd_main_t *bm = &bfd_main;
843 bfd_lock (bm);
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200844 vnet_api_error_t rv =
Klement Sekerab17dd962017-01-09 07:43:48 +0100845 bfd_udp_find_session_by_api_input (sw_if_index, local_addr, peer_addr,
846 &bs);
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200847 if (rv)
848 {
Dave Barach1e3417f2018-07-25 08:30:27 -0400849 bfd_unlock (bm);
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200850 return rv;
851 }
Klement Sekera88aec652019-03-11 14:04:19 +0100852 bfd_udp_del_session_internal (vlib_get_main (), bs);
Dave Barach1e3417f2018-07-25 08:30:27 -0400853 bfd_unlock (bm);
Klement Sekerab17dd962017-01-09 07:43:48 +0100854 return 0;
855}
856
857vnet_api_error_t
Klement Sekeraa3167442020-02-10 11:49:52 +0000858bfd_udp_session_set_flags (vlib_main_t * vm, u32 sw_if_index,
Klement Sekerab17dd962017-01-09 07:43:48 +0100859 const ip46_address_t * local_addr,
860 const ip46_address_t * peer_addr, u8 admin_up_down)
861{
862 bfd_session_t *bs = NULL;
Dave Barach1e3417f2018-07-25 08:30:27 -0400863 bfd_main_t *bm = &bfd_main;
864 bfd_lock (bm);
Klement Sekerab17dd962017-01-09 07:43:48 +0100865 vnet_api_error_t rv =
866 bfd_udp_find_session_by_api_input (sw_if_index, local_addr, peer_addr,
867 &bs);
868 if (rv)
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200869 {
Dave Barach1e3417f2018-07-25 08:30:27 -0400870 bfd_unlock (bm);
Klement Sekerab17dd962017-01-09 07:43:48 +0100871 return rv;
872 }
Klement Sekeraa3167442020-02-10 11:49:52 +0000873 bfd_session_set_flags (vm, bs, admin_up_down);
Dave Barach1e3417f2018-07-25 08:30:27 -0400874 bfd_unlock (bm);
Klement Sekerab17dd962017-01-09 07:43:48 +0100875 return 0;
876}
877
878vnet_api_error_t
Klement Sekerab17dd962017-01-09 07:43:48 +0100879bfd_udp_auth_activate (u32 sw_if_index,
880 const ip46_address_t * local_addr,
881 const ip46_address_t * peer_addr,
882 u32 conf_key_id, u8 key_id, u8 is_delayed)
883{
Dave Barach1e3417f2018-07-25 08:30:27 -0400884 bfd_main_t *bm = &bfd_main;
885 bfd_lock (bm);
886 vnet_api_error_t error;
887
Klement Sekerab17dd962017-01-09 07:43:48 +0100888 bfd_session_t *bs = NULL;
889 vnet_api_error_t rv =
890 bfd_udp_find_session_by_api_input (sw_if_index, local_addr, peer_addr,
891 &bs);
892 if (rv)
893 {
Dave Barach1e3417f2018-07-25 08:30:27 -0400894 bfd_unlock (bm);
Klement Sekerab17dd962017-01-09 07:43:48 +0100895 return rv;
896 }
Dave Barach1e3417f2018-07-25 08:30:27 -0400897 error = bfd_auth_activate (bs, conf_key_id, key_id, is_delayed);
898 bfd_unlock (bm);
899 return error;
Klement Sekerab17dd962017-01-09 07:43:48 +0100900}
901
902vnet_api_error_t
903bfd_udp_auth_deactivate (u32 sw_if_index,
904 const ip46_address_t * local_addr,
905 const ip46_address_t * peer_addr, u8 is_delayed)
906{
Dave Barach1e3417f2018-07-25 08:30:27 -0400907 bfd_main_t *bm = &bfd_main;
908 vnet_api_error_t error;
909 bfd_lock (bm);
Klement Sekerab17dd962017-01-09 07:43:48 +0100910 bfd_session_t *bs = NULL;
911 vnet_api_error_t rv =
912 bfd_udp_find_session_by_api_input (sw_if_index, local_addr, peer_addr,
913 &bs);
914 if (rv)
915 {
Dave Barach1e3417f2018-07-25 08:30:27 -0400916 bfd_unlock (bm);
Klement Sekerab17dd962017-01-09 07:43:48 +0100917 return rv;
918 }
Dave Barach1e3417f2018-07-25 08:30:27 -0400919 error = bfd_auth_deactivate (bs, is_delayed);
920 bfd_unlock (bm);
921 return error;
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200922}
923
Klement Sekerac5fccc02017-01-18 09:56:00 +0100924typedef enum
925{
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200926 BFD_UDP_INPUT_NEXT_NORMAL,
Klement Sekerae50e8562017-04-04 16:19:48 +0200927 BFD_UDP_INPUT_NEXT_REPLY_ARP,
928 BFD_UDP_INPUT_NEXT_REPLY_REWRITE,
Matthew G Smith2f260142019-05-22 14:49:24 -0500929 BFD_UDP_INPUT_NEXT_REPLY_MIDCHAIN,
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200930 BFD_UDP_INPUT_N_NEXT,
931} bfd_udp_input_next_t;
932
Klement Sekeraaeeac3b2017-02-14 07:11:52 +0100933/* Packet counters - BFD control frames */
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200934#define foreach_bfd_udp_error(F) \
935 F (NONE, "good bfd packets (processed)") \
Klement Sekeraaeeac3b2017-02-14 07:11:52 +0100936 F (BAD, "invalid bfd packets")
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200937
938#define F(sym, string) static char BFD_UDP_ERR_##sym##_STR[] = string;
939foreach_bfd_udp_error (F);
940#undef F
941
942static char *bfd_udp_error_strings[] = {
943#define F(sym, string) BFD_UDP_ERR_##sym##_STR,
944 foreach_bfd_udp_error (F)
945#undef F
946};
947
Klement Sekerac5fccc02017-01-18 09:56:00 +0100948typedef enum
949{
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200950#define F(sym, str) BFD_UDP_ERROR_##sym,
951 foreach_bfd_udp_error (F)
952#undef F
Klement Sekerac5fccc02017-01-18 09:56:00 +0100953 BFD_UDP_N_ERROR,
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200954} bfd_udp_error_t;
955
Matthew G Smith2f260142019-05-22 14:49:24 -0500956typedef enum
957{
958 BFD_UDP_ECHO_INPUT_NEXT_NORMAL,
959 BFD_UDP_ECHO_INPUT_NEXT_REPLY_ARP,
960 BFD_UDP_ECHO_INPUT_NEXT_REPLY_REWRITE,
961 BFD_UDP_ECHO_INPUT_N_NEXT,
962} bfd_udp_echo_input_next_t;
963
Klement Sekeraaeeac3b2017-02-14 07:11:52 +0100964/* Packet counters - BFD ECHO packets */
965#define foreach_bfd_udp_echo_error(F) \
966 F (NONE, "good bfd echo packets (processed)") \
967 F (BAD, "invalid bfd echo packets")
968
969#define F(sym, string) static char BFD_UDP_ECHO_ERR_##sym##_STR[] = string;
970foreach_bfd_udp_echo_error (F);
971#undef F
972
973static char *bfd_udp_echo_error_strings[] = {
974#define F(sym, string) BFD_UDP_ECHO_ERR_##sym##_STR,
975 foreach_bfd_udp_echo_error (F)
976#undef F
977};
978
979typedef enum
980{
981#define F(sym, str) BFD_UDP_ECHO_ERROR_##sym,
982 foreach_bfd_udp_echo_error (F)
983#undef F
984 BFD_UDP_ECHO_N_ERROR,
985} bfd_udp_echo_error_t;
986
Klement Sekerac5fccc02017-01-18 09:56:00 +0100987static void
Klement Sekeraaeeac3b2017-02-14 07:11:52 +0100988bfd_udp4_find_headers (vlib_buffer_t * b, ip4_header_t ** ip4,
989 udp_header_t ** udp)
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200990{
Klement Sekera0c1519b2016-12-08 05:03:32 +0100991 /* sanity check first */
Damjan Marion072401e2017-07-13 18:53:27 +0200992 const i32 start = vnet_buffer (b)->l3_hdr_offset;
Klement Sekerab59f63b2022-02-14 20:19:28 +0000993 if (start < -(signed) sizeof (b->pre_data))
Klement Sekera0c1519b2016-12-08 05:03:32 +0100994 {
995 BFD_ERR ("Start of ip header is before pre_data, ignoring");
996 *ip4 = NULL;
997 *udp = NULL;
998 return;
999 }
Klement Sekerac5fccc02017-01-18 09:56:00 +01001000 *ip4 = (ip4_header_t *) (b->data + start);
1001 if ((u8 *) * ip4 > (u8 *) vlib_buffer_get_current (b))
Klement Sekera0c1519b2016-12-08 05:03:32 +01001002 {
1003 BFD_ERR ("Start of ip header is beyond current data, ignoring");
1004 *ip4 = NULL;
1005 *udp = NULL;
1006 return;
1007 }
Klement Sekerac5fccc02017-01-18 09:56:00 +01001008 *udp = (udp_header_t *) ((*ip4) + 1);
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001009}
1010
Klement Sekerac5fccc02017-01-18 09:56:00 +01001011static bfd_udp_error_t
1012bfd_udp4_verify_transport (const ip4_header_t * ip4,
1013 const udp_header_t * udp, const bfd_session_t * bs)
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001014{
1015 const bfd_udp_session_t *bus = &bs->udp;
1016 const bfd_udp_key_t *key = &bus->key;
1017 if (ip4->src_address.as_u32 != key->peer_addr.ip4.as_u32)
1018 {
Klement Sekera46a87ad2017-01-02 08:22:23 +01001019 BFD_ERR ("IPv4 src addr mismatch, got %U, expected %U",
Klement Sekerac5fccc02017-01-18 09:56:00 +01001020 format_ip4_address, ip4->src_address.as_u8, format_ip4_address,
1021 key->peer_addr.ip4.as_u8);
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001022 return BFD_UDP_ERROR_BAD;
1023 }
1024 if (ip4->dst_address.as_u32 != key->local_addr.ip4.as_u32)
1025 {
Klement Sekera46a87ad2017-01-02 08:22:23 +01001026 BFD_ERR ("IPv4 dst addr mismatch, got %U, expected %U",
Klement Sekerac5fccc02017-01-18 09:56:00 +01001027 format_ip4_address, ip4->dst_address.as_u8, format_ip4_address,
1028 key->local_addr.ip4.as_u8);
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001029 return BFD_UDP_ERROR_BAD;
1030 }
1031 const u8 expected_ttl = 255;
1032 if (ip4->ttl != expected_ttl)
1033 {
Klement Sekera46a87ad2017-01-02 08:22:23 +01001034 BFD_ERR ("IPv4 unexpected TTL value %u, expected %u", ip4->ttl,
Klement Sekerac5fccc02017-01-18 09:56:00 +01001035 expected_ttl);
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001036 return BFD_UDP_ERROR_BAD;
1037 }
Klement Sekera6f966492017-02-08 07:42:08 +01001038 if (clib_net_to_host_u16 (udp->src_port) < 49152)
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001039 {
Klement Sekera46a87ad2017-01-02 08:22:23 +01001040 BFD_ERR ("Invalid UDP src port %u, out of range <49152,65535>",
Klement Sekerac5fccc02017-01-18 09:56:00 +01001041 udp->src_port);
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001042 }
1043 return BFD_UDP_ERROR_NONE;
1044}
1045
1046typedef struct
1047{
1048 u32 bs_idx;
1049 bfd_pkt_t pkt;
1050} bfd_rpc_update_t;
1051
Klement Sekerac5fccc02017-01-18 09:56:00 +01001052static void
Klement Sekeraa3167442020-02-10 11:49:52 +00001053bfd_rpc_update_session (vlib_main_t * vm, u32 bs_idx, const bfd_pkt_t * pkt)
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001054{
Dave Barach1e3417f2018-07-25 08:30:27 -04001055 bfd_main_t *bm = &bfd_main;
1056 bfd_lock (bm);
Klement Sekeraa3167442020-02-10 11:49:52 +00001057 bfd_consume_pkt (vm, bm, pkt, bs_idx);
Dave Barach1e3417f2018-07-25 08:30:27 -04001058 bfd_unlock (bm);
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001059}
1060
Klement Sekerac5fccc02017-01-18 09:56:00 +01001061static bfd_udp_error_t
Klement Sekerab59f63b2022-02-14 20:19:28 +00001062bfd_udp4_scan (vlib_main_t *vm, vlib_buffer_t *b, bfd_session_t **bs_out)
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001063{
1064 const bfd_pkt_t *pkt = vlib_buffer_get_current (b);
1065 if (sizeof (*pkt) > b->current_length)
1066 {
Klement Sekerac5fccc02017-01-18 09:56:00 +01001067 BFD_ERR
1068 ("Payload size %d too small to hold bfd packet of minimum size %d",
1069 b->current_length, sizeof (*pkt));
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001070 return BFD_UDP_ERROR_BAD;
1071 }
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001072 ip4_header_t *ip4;
1073 udp_header_t *udp;
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001074 bfd_udp4_find_headers (b, &ip4, &udp);
1075 if (!ip4 || !udp)
1076 {
1077 BFD_ERR ("Couldn't find ip4 or udp header");
1078 return BFD_UDP_ERROR_BAD;
1079 }
Klement Sekerab17dd962017-01-09 07:43:48 +01001080 const u32 udp_payload_length = udp->length - sizeof (*udp);
1081 if (pkt->head.length > udp_payload_length)
1082 {
1083 BFD_ERR
1084 ("BFD packet length is larger than udp payload length (%u > %u)",
1085 pkt->head.length, udp_payload_length);
1086 return BFD_UDP_ERROR_BAD;
1087 }
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001088 if (!bfd_verify_pkt_common (pkt))
1089 {
1090 return BFD_UDP_ERROR_BAD;
1091 }
1092 bfd_session_t *bs = NULL;
1093 if (pkt->your_disc)
1094 {
1095 BFD_DBG ("Looking up BFD session using discriminator %u",
Klement Sekerac5fccc02017-01-18 09:56:00 +01001096 pkt->your_disc);
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001097 bs = bfd_find_session_by_disc (bfd_udp_main.bfd_main, pkt->your_disc);
1098 }
1099 else
1100 {
1101 bfd_udp_key_t key;
Dave Barachb7b92992018-10-17 10:38:51 -04001102 clib_memset (&key, 0, sizeof (key));
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001103 key.sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
1104 key.local_addr.ip4.as_u32 = ip4->dst_address.as_u32;
1105 key.peer_addr.ip4.as_u32 = ip4->src_address.as_u32;
1106 BFD_DBG ("Looking up BFD session using key (sw_if_index=%u, local=%U, "
Klement Sekerac5fccc02017-01-18 09:56:00 +01001107 "peer=%U)",
1108 key.sw_if_index, format_ip4_address, key.local_addr.ip4.as_u8,
1109 format_ip4_address, key.peer_addr.ip4.as_u8);
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001110 bs = bfd_lookup_session (&bfd_udp_main, &key);
1111 }
1112 if (!bs)
1113 {
1114 BFD_ERR ("BFD session lookup failed - no session matches BFD pkt");
1115 return BFD_UDP_ERROR_BAD;
1116 }
Klement Sekera637b9c42016-12-08 05:19:14 +01001117 BFD_DBG ("BFD session found, bs_idx=%u", bs->bs_idx);
Klement Sekeraa3167442020-02-10 11:49:52 +00001118 if (!bfd_verify_pkt_auth (vm, pkt, b->current_length, bs))
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001119 {
Klement Sekerab17dd962017-01-09 07:43:48 +01001120 BFD_ERR ("Packet verification failed, dropping packet");
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001121 return BFD_UDP_ERROR_BAD;
1122 }
1123 bfd_udp_error_t err;
1124 if (BFD_UDP_ERROR_NONE != (err = bfd_udp4_verify_transport (ip4, udp, bs)))
1125 {
1126 return err;
1127 }
Klement Sekeraa3167442020-02-10 11:49:52 +00001128 bfd_rpc_update_session (vm, bs->bs_idx, pkt);
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001129 *bs_out = bs;
1130 return BFD_UDP_ERROR_NONE;
1131}
1132
Klement Sekerac5fccc02017-01-18 09:56:00 +01001133static void
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001134bfd_udp6_find_headers (vlib_buffer_t * b, ip6_header_t ** ip6,
1135 udp_header_t ** udp)
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001136{
Klement Sekera46a87ad2017-01-02 08:22:23 +01001137 /* sanity check first */
Damjan Marion072401e2017-07-13 18:53:27 +02001138 const i32 start = vnet_buffer (b)->l3_hdr_offset;
Klement Sekerab59f63b2022-02-14 20:19:28 +00001139 if (start < -(signed) sizeof (b->pre_data))
Klement Sekera46a87ad2017-01-02 08:22:23 +01001140 {
1141 BFD_ERR ("Start of ip header is before pre_data, ignoring");
1142 *ip6 = NULL;
1143 *udp = NULL;
1144 return;
1145 }
Klement Sekerac5fccc02017-01-18 09:56:00 +01001146 *ip6 = (ip6_header_t *) (b->data + start);
1147 if ((u8 *) * ip6 > (u8 *) vlib_buffer_get_current (b))
Klement Sekera46a87ad2017-01-02 08:22:23 +01001148 {
1149 BFD_ERR ("Start of ip header is beyond current data, ignoring");
1150 *ip6 = NULL;
1151 *udp = NULL;
1152 return;
1153 }
Klement Sekera402ed312017-01-18 09:44:36 +01001154 if ((*ip6)->protocol != IP_PROTOCOL_UDP)
1155 {
1156 BFD_ERR ("Unexpected protocol in IPv6 header '%u', expected '%u' (== "
Klement Sekerab17dd962017-01-09 07:43:48 +01001157 "IP_PROTOCOL_UDP)", (*ip6)->protocol, IP_PROTOCOL_UDP);
Klement Sekera402ed312017-01-18 09:44:36 +01001158 *ip6 = NULL;
1159 *udp = NULL;
1160 return;
1161 }
Klement Sekerac5fccc02017-01-18 09:56:00 +01001162 *udp = (udp_header_t *) ((*ip6) + 1);
Klement Sekera46a87ad2017-01-02 08:22:23 +01001163}
1164
Klement Sekerac5fccc02017-01-18 09:56:00 +01001165static bfd_udp_error_t
1166bfd_udp6_verify_transport (const ip6_header_t * ip6,
1167 const udp_header_t * udp, const bfd_session_t * bs)
Klement Sekera46a87ad2017-01-02 08:22:23 +01001168{
1169 const bfd_udp_session_t *bus = &bs->udp;
1170 const bfd_udp_key_t *key = &bus->key;
1171 if (ip6->src_address.as_u64[0] != key->peer_addr.ip6.as_u64[0] &&
1172 ip6->src_address.as_u64[1] != key->peer_addr.ip6.as_u64[1])
1173 {
Klement Sekerac5fccc02017-01-18 09:56:00 +01001174 BFD_ERR ("IP src addr mismatch, got %U, expected %U",
1175 format_ip6_address, ip6, format_ip6_address,
1176 &key->peer_addr.ip6);
Klement Sekera46a87ad2017-01-02 08:22:23 +01001177 return BFD_UDP_ERROR_BAD;
1178 }
1179 if (ip6->dst_address.as_u64[0] != key->local_addr.ip6.as_u64[0] &&
1180 ip6->dst_address.as_u64[1] != key->local_addr.ip6.as_u64[1])
1181 {
Klement Sekerac5fccc02017-01-18 09:56:00 +01001182 BFD_ERR ("IP dst addr mismatch, got %U, expected %U",
1183 format_ip6_address, ip6, format_ip6_address,
1184 &key->local_addr.ip6);
Klement Sekera46a87ad2017-01-02 08:22:23 +01001185 return BFD_UDP_ERROR_BAD;
1186 }
1187 const u8 expected_hop_limit = 255;
1188 if (ip6->hop_limit != expected_hop_limit)
1189 {
1190 BFD_ERR ("IPv6 unexpected hop-limit value %u, expected %u",
Klement Sekerac5fccc02017-01-18 09:56:00 +01001191 ip6->hop_limit, expected_hop_limit);
Klement Sekera46a87ad2017-01-02 08:22:23 +01001192 return BFD_UDP_ERROR_BAD;
1193 }
Klement Sekera6f966492017-02-08 07:42:08 +01001194 if (clib_net_to_host_u16 (udp->src_port) < 49152)
Klement Sekera46a87ad2017-01-02 08:22:23 +01001195 {
1196 BFD_ERR ("Invalid UDP src port %u, out of range <49152,65535>",
Klement Sekerac5fccc02017-01-18 09:56:00 +01001197 udp->src_port);
Klement Sekera46a87ad2017-01-02 08:22:23 +01001198 }
1199 return BFD_UDP_ERROR_NONE;
1200}
1201
Klement Sekerac5fccc02017-01-18 09:56:00 +01001202static bfd_udp_error_t
Klement Sekerab59f63b2022-02-14 20:19:28 +00001203bfd_udp6_scan (vlib_main_t *vm, vlib_buffer_t *b, bfd_session_t **bs_out)
Klement Sekera46a87ad2017-01-02 08:22:23 +01001204{
1205 const bfd_pkt_t *pkt = vlib_buffer_get_current (b);
1206 if (sizeof (*pkt) > b->current_length)
1207 {
Klement Sekerac5fccc02017-01-18 09:56:00 +01001208 BFD_ERR
1209 ("Payload size %d too small to hold bfd packet of minimum size %d",
1210 b->current_length, sizeof (*pkt));
Klement Sekera46a87ad2017-01-02 08:22:23 +01001211 return BFD_UDP_ERROR_BAD;
1212 }
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001213 ip6_header_t *ip6;
1214 udp_header_t *udp;
Klement Sekera46a87ad2017-01-02 08:22:23 +01001215 bfd_udp6_find_headers (b, &ip6, &udp);
1216 if (!ip6 || !udp)
1217 {
1218 BFD_ERR ("Couldn't find ip6 or udp header");
1219 return BFD_UDP_ERROR_BAD;
1220 }
Klement Sekerab17dd962017-01-09 07:43:48 +01001221 const u32 udp_payload_length = udp->length - sizeof (*udp);
1222 if (pkt->head.length > udp_payload_length)
1223 {
1224 BFD_ERR
1225 ("BFD packet length is larger than udp payload length (%u > %u)",
1226 pkt->head.length, udp_payload_length);
1227 return BFD_UDP_ERROR_BAD;
1228 }
Klement Sekera46a87ad2017-01-02 08:22:23 +01001229 if (!bfd_verify_pkt_common (pkt))
1230 {
1231 return BFD_UDP_ERROR_BAD;
1232 }
1233 bfd_session_t *bs = NULL;
1234 if (pkt->your_disc)
1235 {
1236 BFD_DBG ("Looking up BFD session using discriminator %u",
Klement Sekerac5fccc02017-01-18 09:56:00 +01001237 pkt->your_disc);
Klement Sekera46a87ad2017-01-02 08:22:23 +01001238 bs = bfd_find_session_by_disc (bfd_udp_main.bfd_main, pkt->your_disc);
1239 }
1240 else
1241 {
1242 bfd_udp_key_t key;
Dave Barachb7b92992018-10-17 10:38:51 -04001243 clib_memset (&key, 0, sizeof (key));
Klement Sekera46a87ad2017-01-02 08:22:23 +01001244 key.sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
1245 key.local_addr.ip6.as_u64[0] = ip6->dst_address.as_u64[0];
1246 key.local_addr.ip6.as_u64[1] = ip6->dst_address.as_u64[1];
1247 key.peer_addr.ip6.as_u64[0] = ip6->src_address.as_u64[0];
1248 key.peer_addr.ip6.as_u64[1] = ip6->src_address.as_u64[1];
1249 BFD_DBG ("Looking up BFD session using key (sw_if_index=%u, local=%U, "
Klement Sekerab17dd962017-01-09 07:43:48 +01001250 "peer=%U)",
1251 key.sw_if_index, format_ip6_address, &key.local_addr,
1252 format_ip6_address, &key.peer_addr);
Klement Sekera46a87ad2017-01-02 08:22:23 +01001253 bs = bfd_lookup_session (&bfd_udp_main, &key);
1254 }
1255 if (!bs)
1256 {
1257 BFD_ERR ("BFD session lookup failed - no session matches BFD pkt");
1258 return BFD_UDP_ERROR_BAD;
1259 }
1260 BFD_DBG ("BFD session found, bs_idx=%u", bs->bs_idx);
Klement Sekeraa3167442020-02-10 11:49:52 +00001261 if (!bfd_verify_pkt_auth (vm, pkt, b->current_length, bs))
Klement Sekera46a87ad2017-01-02 08:22:23 +01001262 {
Klement Sekerab17dd962017-01-09 07:43:48 +01001263 BFD_ERR ("Packet verification failed, dropping packet");
Klement Sekera46a87ad2017-01-02 08:22:23 +01001264 return BFD_UDP_ERROR_BAD;
1265 }
1266 bfd_udp_error_t err;
1267 if (BFD_UDP_ERROR_NONE != (err = bfd_udp6_verify_transport (ip6, udp, bs)))
1268 {
1269 return err;
1270 }
Klement Sekeraa3167442020-02-10 11:49:52 +00001271 bfd_rpc_update_session (vm, bs->bs_idx, pkt);
Klement Sekera46a87ad2017-01-02 08:22:23 +01001272 *bs_out = bs;
1273 return BFD_UDP_ERROR_NONE;
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001274}
1275
1276/*
1277 * Process a frame of bfd packets
1278 * Expect 1 packet / frame
1279 */
Klement Sekerac5fccc02017-01-18 09:56:00 +01001280static uword
1281bfd_udp_input (vlib_main_t * vm, vlib_node_runtime_t * rt,
1282 vlib_frame_t * f, int is_ipv6)
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001283{
1284 u32 n_left_from, *from;
1285 bfd_input_trace_t *t0;
Dave Barach1e3417f2018-07-25 08:30:27 -04001286 bfd_main_t *bm = &bfd_main;
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001287
Klement Sekerac5fccc02017-01-18 09:56:00 +01001288 from = vlib_frame_vector_args (f); /* array of buffer indices */
1289 n_left_from = f->n_vectors; /* number of buffer indices */
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001290
1291 while (n_left_from > 0)
1292 {
1293 u32 bi0;
1294 vlib_buffer_t *b0;
1295 u32 next0, error0;
1296
1297 bi0 = from[0];
1298 b0 = vlib_get_buffer (vm, bi0);
1299
1300 bfd_session_t *bs = NULL;
1301
1302 /* If this pkt is traced, snapshot the data */
1303 if (b0->flags & VLIB_BUFFER_IS_TRACED)
Klement Sekerac5fccc02017-01-18 09:56:00 +01001304 {
Klement Sekerab59f63b2022-02-14 20:19:28 +00001305 u64 len;
Klement Sekerac5fccc02017-01-18 09:56:00 +01001306 t0 = vlib_add_trace (vm, rt, b0, sizeof (*t0));
1307 len = (b0->current_length < sizeof (t0->data)) ? b0->current_length
1308 : sizeof (t0->data);
1309 t0->len = len;
Dave Barach178cf492018-11-13 16:34:13 -05001310 clib_memcpy_fast (t0->data, vlib_buffer_get_current (b0), len);
Klement Sekerac5fccc02017-01-18 09:56:00 +01001311 }
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001312
1313 /* scan this bfd pkt. error0 is the counter index to bmp */
Dave Barach1e3417f2018-07-25 08:30:27 -04001314 bfd_lock (bm);
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001315 if (is_ipv6)
Klement Sekerac5fccc02017-01-18 09:56:00 +01001316 {
Klement Sekerab59f63b2022-02-14 20:19:28 +00001317 error0 = bfd_udp6_scan (vm, b0, &bs);
Klement Sekerac5fccc02017-01-18 09:56:00 +01001318 }
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001319 else
Klement Sekerac5fccc02017-01-18 09:56:00 +01001320 {
Klement Sekerab59f63b2022-02-14 20:19:28 +00001321 error0 = bfd_udp4_scan (vm, b0, &bs);
Klement Sekerac5fccc02017-01-18 09:56:00 +01001322 }
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001323 b0->error = rt->errors[error0];
1324
1325 next0 = BFD_UDP_INPUT_NEXT_NORMAL;
1326 if (BFD_UDP_ERROR_NONE == error0)
Klement Sekerac5fccc02017-01-18 09:56:00 +01001327 {
Klement Sekeracdaf0d82022-02-14 20:20:22 +00001328 vlib_increment_combined_counter (
1329 &bm->rx_counter, vm->thread_index, bs->bs_idx, 1,
1330 vlib_buffer_length_in_chain (vm, b0));
Klement Sekera402ed312017-01-18 09:44:36 +01001331 /*
1332 * if everything went fine, check for poll bit, if present, re-use
1333 * the buffer and based on (now updated) session parameters, send
1334 * the final packet back
1335 */
Klement Sekerac5fccc02017-01-18 09:56:00 +01001336 const bfd_pkt_t *pkt = vlib_buffer_get_current (b0);
1337 if (bfd_pkt_get_poll (pkt))
1338 {
Klement Sekerae50e8562017-04-04 16:19:48 +02001339 b0->current_data = 0;
1340 b0->current_length = 0;
Klement Sekerab59f63b2022-02-14 20:19:28 +00001341 bfd_init_final_control_frame (vm, b0, bs);
Klement Sekerac5fccc02017-01-18 09:56:00 +01001342 if (is_ipv6)
1343 {
1344 vlib_node_increment_counter (vm, bfd_udp6_input_node.index,
1345 b0->error, 1);
1346 }
1347 else
1348 {
1349 vlib_node_increment_counter (vm, bfd_udp4_input_node.index,
1350 b0->error, 1);
1351 }
Klement Sekerae50e8562017-04-04 16:19:48 +02001352 const bfd_udp_session_t *bus = &bs->udp;
1353 ip_adjacency_t *adj = adj_get (bus->adj_index);
1354 switch (adj->lookup_next_index)
1355 {
1356 case IP_LOOKUP_NEXT_ARP:
1357 next0 = BFD_UDP_INPUT_NEXT_REPLY_ARP;
1358 break;
1359 case IP_LOOKUP_NEXT_REWRITE:
1360 next0 = BFD_UDP_INPUT_NEXT_REPLY_REWRITE;
1361 break;
Matthew G Smith2f260142019-05-22 14:49:24 -05001362 case IP_LOOKUP_NEXT_MIDCHAIN:
1363 next0 = BFD_UDP_INPUT_NEXT_REPLY_MIDCHAIN;
1364 break;
Klement Sekerae50e8562017-04-04 16:19:48 +02001365 default:
1366 /* drop */
1367 break;
1368 }
Klement Sekerac5fccc02017-01-18 09:56:00 +01001369 }
1370 }
Dave Barach1e3417f2018-07-25 08:30:27 -04001371 bfd_unlock (bm);
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001372 vlib_set_next_frame_buffer (vm, rt, next0, bi0);
1373
1374 from += 1;
1375 n_left_from -= 1;
1376 }
1377
1378 return f->n_vectors;
1379}
1380
Klement Sekerac5fccc02017-01-18 09:56:00 +01001381static uword
1382bfd_udp4_input (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001383{
1384 return bfd_udp_input (vm, rt, f, 0);
1385}
1386
1387/*
1388 * bfd input graph node declaration
1389 */
1390/* *INDENT-OFF* */
1391VLIB_REGISTER_NODE (bfd_udp4_input_node, static) = {
1392 .function = bfd_udp4_input,
1393 .name = "bfd-udp4-input",
1394 .vector_size = sizeof (u32),
1395 .type = VLIB_NODE_TYPE_INTERNAL,
1396
1397 .n_errors = BFD_UDP_N_ERROR,
1398 .error_strings = bfd_udp_error_strings,
1399
1400 .format_trace = bfd_input_format_trace,
1401
1402 .n_next_nodes = BFD_UDP_INPUT_N_NEXT,
1403 .next_nodes =
1404 {
1405 [BFD_UDP_INPUT_NEXT_NORMAL] = "error-drop",
Klement Sekerae50e8562017-04-04 16:19:48 +02001406 [BFD_UDP_INPUT_NEXT_REPLY_ARP] = "ip4-arp",
1407 [BFD_UDP_INPUT_NEXT_REPLY_REWRITE] = "ip4-lookup",
Matthew G Smith2f260142019-05-22 14:49:24 -05001408 [BFD_UDP_INPUT_NEXT_REPLY_MIDCHAIN] = "ip4-midchain",
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001409 },
1410};
1411/* *INDENT-ON* */
1412
Klement Sekerac5fccc02017-01-18 09:56:00 +01001413static uword
1414bfd_udp6_input (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001415{
1416 return bfd_udp_input (vm, rt, f, 1);
1417}
1418
1419/* *INDENT-OFF* */
1420VLIB_REGISTER_NODE (bfd_udp6_input_node, static) = {
1421 .function = bfd_udp6_input,
1422 .name = "bfd-udp6-input",
1423 .vector_size = sizeof (u32),
1424 .type = VLIB_NODE_TYPE_INTERNAL,
1425
1426 .n_errors = BFD_UDP_N_ERROR,
1427 .error_strings = bfd_udp_error_strings,
1428
1429 .format_trace = bfd_input_format_trace,
1430
1431 .n_next_nodes = BFD_UDP_INPUT_N_NEXT,
1432 .next_nodes =
1433 {
1434 [BFD_UDP_INPUT_NEXT_NORMAL] = "error-drop",
Klement Sekerae50e8562017-04-04 16:19:48 +02001435 [BFD_UDP_INPUT_NEXT_REPLY_ARP] = "ip6-discover-neighbor",
1436 [BFD_UDP_INPUT_NEXT_REPLY_REWRITE] = "ip6-lookup",
Matthew G Smith2f260142019-05-22 14:49:24 -05001437 [BFD_UDP_INPUT_NEXT_REPLY_MIDCHAIN] = "ip6-midchain",
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001438 },
1439};
1440/* *INDENT-ON* */
1441
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001442/*
1443 * Process a frame of bfd echo packets
1444 * Expect 1 packet / frame
1445 */
1446static uword
1447bfd_udp_echo_input (vlib_main_t * vm, vlib_node_runtime_t * rt,
1448 vlib_frame_t * f, int is_ipv6)
1449{
1450 u32 n_left_from, *from;
1451 bfd_input_trace_t *t0;
Dave Barach1e3417f2018-07-25 08:30:27 -04001452 bfd_main_t *bm = &bfd_main;
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001453
1454 from = vlib_frame_vector_args (f); /* array of buffer indices */
1455 n_left_from = f->n_vectors; /* number of buffer indices */
1456
1457 while (n_left_from > 0)
1458 {
1459 u32 bi0;
1460 vlib_buffer_t *b0;
1461 u32 next0;
1462
1463 bi0 = from[0];
1464 b0 = vlib_get_buffer (vm, bi0);
1465
1466 /* If this pkt is traced, snapshot the data */
1467 if (b0->flags & VLIB_BUFFER_IS_TRACED)
1468 {
Klement Sekerab59f63b2022-02-14 20:19:28 +00001469 u64 len;
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001470 t0 = vlib_add_trace (vm, rt, b0, sizeof (*t0));
1471 len = (b0->current_length < sizeof (t0->data)) ? b0->current_length
1472 : sizeof (t0->data);
1473 t0->len = len;
Dave Barach178cf492018-11-13 16:34:13 -05001474 clib_memcpy_fast (t0->data, vlib_buffer_get_current (b0), len);
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001475 }
1476
Klement Sekeracdaf0d82022-02-14 20:20:22 +00001477 bfd_session_t *bs = NULL;
Dave Barach1e3417f2018-07-25 08:30:27 -04001478 bfd_lock (bm);
Klement Sekeracdaf0d82022-02-14 20:20:22 +00001479 if ((bs = bfd_consume_echo_pkt (vm, bfd_udp_main.bfd_main, b0)))
Klement Sekera239790f2017-02-16 10:53:53 +01001480 {
1481 b0->error = rt->errors[BFD_UDP_ERROR_NONE];
Matthew G Smith2f260142019-05-22 14:49:24 -05001482 next0 = BFD_UDP_ECHO_INPUT_NEXT_NORMAL;
Klement Sekera239790f2017-02-16 10:53:53 +01001483 }
1484 else
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001485 {
1486 /* loop back the packet */
1487 b0->error = rt->errors[BFD_UDP_ERROR_NONE];
1488 if (is_ipv6)
1489 {
1490 vlib_node_increment_counter (vm, bfd_udp_echo6_input_node.index,
1491 b0->error, 1);
1492 }
1493 else
1494 {
1495 vlib_node_increment_counter (vm, bfd_udp_echo4_input_node.index,
1496 b0->error, 1);
1497 }
Matthew G Smith2f260142019-05-22 14:49:24 -05001498 next0 = BFD_UDP_ECHO_INPUT_NEXT_REPLY_REWRITE;
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001499 }
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001500
Dave Barach1e3417f2018-07-25 08:30:27 -04001501 bfd_unlock (bm);
Klement Sekeracdaf0d82022-02-14 20:20:22 +00001502
1503 if (bs)
1504 {
1505 vlib_increment_combined_counter (
1506 &bm->rx_echo_counter, vm->thread_index, bs->bs_idx, 1,
1507 vlib_buffer_length_in_chain (vm, b0));
1508 }
1509
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001510 vlib_set_next_frame_buffer (vm, rt, next0, bi0);
1511
1512 from += 1;
1513 n_left_from -= 1;
1514 }
1515
1516 return f->n_vectors;
1517}
1518
1519static uword
1520bfd_udp_echo4_input (vlib_main_t * vm, vlib_node_runtime_t * rt,
1521 vlib_frame_t * f)
1522{
1523 return bfd_udp_echo_input (vm, rt, f, 0);
1524}
1525
1526u8 *
1527bfd_echo_input_format_trace (u8 * s, va_list * args)
1528{
1529 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1530 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
1531 const bfd_udp_echo_input_trace_t *t =
1532 va_arg (*args, bfd_udp_echo_input_trace_t *);
1533 if (t->len > STRUCT_SIZE_OF (bfd_pkt_t, head))
1534 {
1535 s = format (s, "BFD ECHO:\n");
1536 s = format (s, " data: %U", format_hexdump, t->data, t->len);
1537 }
1538
1539 return s;
1540}
1541
1542/*
1543 * bfd input graph node declaration
1544 */
1545/* *INDENT-OFF* */
1546VLIB_REGISTER_NODE (bfd_udp_echo4_input_node, static) = {
1547 .function = bfd_udp_echo4_input,
1548 .name = "bfd-udp-echo4-input",
1549 .vector_size = sizeof (u32),
1550 .type = VLIB_NODE_TYPE_INTERNAL,
1551
1552 .n_errors = BFD_UDP_ECHO_N_ERROR,
1553 .error_strings = bfd_udp_error_strings,
1554
1555 .format_trace = bfd_echo_input_format_trace,
1556
Matthew G Smith2f260142019-05-22 14:49:24 -05001557 .n_next_nodes = BFD_UDP_ECHO_INPUT_N_NEXT,
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001558 .next_nodes =
1559 {
Matthew G Smith2f260142019-05-22 14:49:24 -05001560 [BFD_UDP_ECHO_INPUT_NEXT_NORMAL] = "error-drop",
1561 [BFD_UDP_ECHO_INPUT_NEXT_REPLY_ARP] = "ip4-arp",
1562 [BFD_UDP_ECHO_INPUT_NEXT_REPLY_REWRITE] = "ip4-lookup",
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001563 },
1564};
1565/* *INDENT-ON* */
1566
1567static uword
1568bfd_udp_echo6_input (vlib_main_t * vm, vlib_node_runtime_t * rt,
1569 vlib_frame_t * f)
1570{
1571 return bfd_udp_echo_input (vm, rt, f, 1);
1572}
1573
1574/* *INDENT-OFF* */
1575VLIB_REGISTER_NODE (bfd_udp_echo6_input_node, static) = {
1576 .function = bfd_udp_echo6_input,
1577 .name = "bfd-udp-echo6-input",
1578 .vector_size = sizeof (u32),
1579 .type = VLIB_NODE_TYPE_INTERNAL,
1580
1581 .n_errors = BFD_UDP_ECHO_N_ERROR,
1582 .error_strings = bfd_udp_echo_error_strings,
1583
1584 .format_trace = bfd_echo_input_format_trace,
1585
Matthew G Smith2f260142019-05-22 14:49:24 -05001586 .n_next_nodes = BFD_UDP_ECHO_INPUT_N_NEXT,
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001587 .next_nodes =
1588 {
Matthew G Smith2f260142019-05-22 14:49:24 -05001589 [BFD_UDP_ECHO_INPUT_NEXT_NORMAL] = "error-drop",
1590 [BFD_UDP_ECHO_INPUT_NEXT_REPLY_ARP] = "ip6-discover-neighbor",
1591 [BFD_UDP_ECHO_INPUT_NEXT_REPLY_REWRITE] = "ip6-lookup",
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001592 },
1593};
1594
1595/* *INDENT-ON* */
1596
Klement Sekerac5fccc02017-01-18 09:56:00 +01001597static clib_error_t *
Klement Sekerab59f63b2022-02-14 20:19:28 +00001598bfd_udp_sw_if_add_del (CLIB_UNUSED (vnet_main_t *vnm), u32 sw_if_index,
1599 u32 is_create)
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001600{
Klement Sekerab59f63b2022-02-14 20:19:28 +00001601 u32 *to_be_freed = NULL;
Damjan Marion07a38572018-01-21 06:44:18 -08001602 bfd_udp_main_t *bum = &bfd_udp_main;
Klement Sekeraf3bcdbf2017-05-02 07:38:01 +02001603 BFD_DBG ("sw_if_add_del called, sw_if_index=%u, is_create=%u", sw_if_index,
1604 is_create);
1605 if (!is_create)
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001606 {
Klement Sekeraf3bcdbf2017-05-02 07:38:01 +02001607 bfd_session_t *bs;
Klement Sekerab59f63b2022-02-14 20:19:28 +00001608 pool_foreach (bs, bum->bfd_main->sessions)
1609 {
1610 if (bs->transport != BFD_TRANSPORT_UDP4 &&
1611 bs->transport != BFD_TRANSPORT_UDP6)
1612 {
1613 continue;
1614 }
1615 if (bs->udp.key.sw_if_index != sw_if_index)
1616 {
1617 continue;
1618 }
1619 vec_add1 (to_be_freed, bs->bs_idx);
1620 }
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001621 }
Klement Sekerab59f63b2022-02-14 20:19:28 +00001622 u32 *bs_idx;
1623 vec_foreach (bs_idx, to_be_freed)
1624 {
1625 bfd_session_t *bs = pool_elt_at_index (bum->bfd_main->sessions, *bs_idx);
1626 vlib_log_notice (bum->log_class,
1627 "removal of sw_if_index=%u forces removal of bfd "
1628 "session with bs_idx=%u",
1629 sw_if_index, bs->bs_idx);
1630 bfd_session_set_flags (vlib_get_main (), bs, 0);
1631 bfd_udp_del_session_internal (vlib_get_main (), bs);
1632 }
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001633 return 0;
1634}
1635
Klement Sekeraf3bcdbf2017-05-02 07:38:01 +02001636VNET_SW_INTERFACE_ADD_DEL_FUNCTION (bfd_udp_sw_if_add_del);
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001637
Klement Sekeracdaf0d82022-02-14 20:20:22 +00001638clib_error_t *
1639bfd_udp_stats_init (bfd_udp_main_t *bum)
1640{
1641 const char *name4 = "/bfd/udp4/sessions";
Damjan Marion8973b072022-03-01 15:51:18 +01001642 bum->udp4_sessions_count_stat_seg_entry = vlib_stats_add_gauge ("%s", name4);
Klement Sekeracdaf0d82022-02-14 20:20:22 +00001643
Damjan Marion8973b072022-03-01 15:51:18 +01001644 vlib_stats_set_gauge (bum->udp4_sessions_count_stat_seg_entry, 0);
Klement Sekeracdaf0d82022-02-14 20:20:22 +00001645 if (~0 == bum->udp4_sessions_count_stat_seg_entry)
1646 {
1647 return clib_error_return (
1648 0, "Could not create stat segment entry for %s", name4);
1649 }
1650 const char *name6 = "/bfd/udp6/sessions";
Damjan Marion8973b072022-03-01 15:51:18 +01001651 bum->udp6_sessions_count_stat_seg_entry = vlib_stats_add_gauge ("%s", name6);
Klement Sekeracdaf0d82022-02-14 20:20:22 +00001652
Damjan Marion8973b072022-03-01 15:51:18 +01001653 vlib_stats_set_gauge (bum->udp6_sessions_count_stat_seg_entry, 0);
Klement Sekeracdaf0d82022-02-14 20:20:22 +00001654 if (~0 == bum->udp6_sessions_count_stat_seg_entry)
1655 {
1656 return clib_error_return (
1657 0, "Could not create stat segment entry for %s", name6);
1658 }
1659
1660 return 0;
1661}
1662
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001663/*
1664 * setup function
1665 */
Klement Sekerac5fccc02017-01-18 09:56:00 +01001666static clib_error_t *
1667bfd_udp_init (vlib_main_t * vm)
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001668{
Klement Sekera88aec652019-03-11 14:04:19 +01001669 bfd_udp_main.udp4_sessions_count = 0;
1670 bfd_udp_main.udp6_sessions_count = 0;
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001671 mhash_init (&bfd_udp_main.bfd_session_idx_by_bfd_key, sizeof (uword),
Klement Sekerac5fccc02017-01-18 09:56:00 +01001672 sizeof (bfd_udp_key_t));
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001673 bfd_udp_main.bfd_main = &bfd_main;
Klement Sekera239790f2017-02-16 10:53:53 +01001674 bfd_udp_main.vnet_main = vnet_get_main ();
Klement Sekerae50e8562017-04-04 16:19:48 +02001675 vlib_node_t *node = vlib_get_node_by_name (vm, (u8 *) "ip4-arp");
1676 ASSERT (node);
1677 bfd_udp_main.ip4_arp_idx = node->index;
1678 node = vlib_get_node_by_name (vm, (u8 *) "ip6-discover-neighbor");
1679 ASSERT (node);
1680 bfd_udp_main.ip6_ndp_idx = node->index;
1681 node = vlib_get_node_by_name (vm, (u8 *) "ip4-rewrite");
1682 ASSERT (node);
1683 bfd_udp_main.ip4_rewrite_idx = node->index;
1684 node = vlib_get_node_by_name (vm, (u8 *) "ip6-rewrite");
1685 ASSERT (node);
1686 bfd_udp_main.ip6_rewrite_idx = node->index;
Matthew G Smith2f260142019-05-22 14:49:24 -05001687 node = vlib_get_node_by_name (vm, (u8 *) "ip4-midchain");
1688 ASSERT (node);
1689 bfd_udp_main.ip4_midchain_idx = node->index;
1690 node = vlib_get_node_by_name (vm, (u8 *) "ip6-midchain");
1691 ASSERT (node);
1692 bfd_udp_main.ip6_midchain_idx = node->index;
Klement Sekerae50e8562017-04-04 16:19:48 +02001693
Klement Sekeracdaf0d82022-02-14 20:20:22 +00001694 bfd_udp_stats_init (&bfd_udp_main);
1695
Damjan Marion07a38572018-01-21 06:44:18 -08001696 bfd_udp_main.log_class = vlib_log_register_class ("bfd", "udp");
1697 vlib_log_debug (bfd_udp_main.log_class, "initialized");
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001698 return 0;
1699}
1700
1701VLIB_INIT_FUNCTION (bfd_udp_init);
Klement Sekerac5fccc02017-01-18 09:56:00 +01001702
1703/*
1704 * fd.io coding-style-patch-verification: ON
1705 *
1706 * Local Variables:
1707 * eval: (c-set-style "gnu")
1708 * End:
1709 */