FD.io VPP  v20.01-48-g3e0dafb74
Vector Packet Processing
adj_bfd.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <vnet/bfd/bfd_main.h>
17 
18 #include <vnet/adj/adj_delegate.h>
19 #include <vnet/adj/adj_nbr.h>
20 #include <vnet/fib/fib_walk.h>
21 
22 /**
23  * Distillation of the BFD session states into a go/no-go for using
24  * the associated tracked adjacency
25  */
26 typedef enum adj_bfd_state_t_
27 {
31 
32 #define ADJ_BFD_STATES { \
33  [ADJ_BFD_STATE_DOWN] = "down", \
34  [ADJ_BFD_STATE_UP] = "up", \
35 }
36 
37 static const char *adj_bfd_state_names[] = ADJ_BFD_STATES;
38 
39 /**
40  * BFD delegate daa
41  */
42 typedef struct adj_bfd_delegate_t_
43 {
44  /**
45  * BFD session state
46  */
48 
49  /**
50  * BFD session index
51  */
54 
55 /**
56  * Pool of delegates
57 */
59 
60 static inline adj_bfd_delegate_t*
62 {
63  if (NULL != ad)
64  {
65  return (pool_elt_at_index(abd_pool, ad->ad_index));
66  }
67  return (NULL);
68 }
69 
70 static inline const adj_bfd_delegate_t*
72 {
73  if (NULL != ad)
74  {
75  return (pool_elt_at_index(abd_pool, ad->ad_index));
76  }
77  return (NULL);
78 }
79 
80 static adj_bfd_state_t
82 {
83  switch (bstate)
84  {
85  case BFD_STATE_up:
86  return (ADJ_BFD_STATE_UP);
87  case BFD_STATE_down:
88  case BFD_STATE_admin_down:
89  case BFD_STATE_init:
90  return (ADJ_BFD_STATE_DOWN);
91  }
92  return (ADJ_BFD_STATE_DOWN);
93 }
94 
95 static void
97 {
98  /*
99  * initiate a backwalk of dependent children
100  * to notify of the state change of this adj.
101  */
103  .fnbw_reason = FIB_NODE_BW_REASON_FLAG_ADJ_UPDATE,
104  };
105  fib_walk_sync(FIB_NODE_TYPE_ADJ, ai, &ctx);
106 }
107 
108 /**
109  * @brief Callback function registered with BFD module to receive notifications
110  * of the CRUD of BFD sessions
111  * would be static but for the fact it's called from the unit-tests
112  */
113 void
115  const bfd_session_t *session)
116 {
117  const bfd_udp_key_t *key;
118  adj_bfd_delegate_t *abd;
119  fib_protocol_t fproto;
120  adj_delegate_t *aed;
121  adj_index_t ai;
122 
123  if (BFD_HOP_TYPE_SINGLE != session->hop_type)
124  {
125  /*
126  * multi-hop BFD sessions attach directly to the FIB entry
127  * single-hop adj to the associate adjacency.
128  */
129  return;
130  }
131 
132  key = &session->udp.key;
133 
134  fproto = (ip46_address_is_ip4 (&key->peer_addr) ?
137 
138  /*
139  * find the adj that corresponds to the BFD session.
140  */
141  ai = adj_nbr_add_or_lock(fproto,
142  fib_proto_to_link(fproto),
143  &key->peer_addr,
144  key->sw_if_index);
145 
146  switch (event)
147  {
148  case BFD_LISTEN_EVENT_CREATE:
149  /*
150  * The creation of a new session
151  */
152  if ((ADJ_INDEX_INVALID != ai) &&
153  (aed = adj_delegate_get(adj_get(ai),
155  {
156  /*
157  * already got state for this adj
158  */
159  }
160  else
161  {
162  /*
163  * lock the adj. add the delegate.
164  * Locking the adj prevents it being removed and thus maintains
165  * the BFD derived states
166  */
167  adj_lock(ai);
168 
169  /*
170  * allocate and init a new delegate struct
171  */
172  pool_get(abd_pool, abd);
173 
174  /*
175  * it would be best here if we could ignore this create and just
176  * wait for the first update, but this is not possible because
177  * BFD sessions are created in the down state, and can remain this
178  * way without transitioning to another state if the peer is
179  * unresponsive. So we have to assume down and wait for up.
180  */
182  abd->abd_index = session->bs_idx;
183 
184  adj_delegate_add(adj_get(ai), ADJ_DELEGATE_BFD, abd - abd_pool);
186  }
187  break;
188 
189  case BFD_LISTEN_EVENT_UPDATE:
190  /*
191  * state change up/down and
192  */
194 
195  if (NULL != abd)
196  {
199  }
200  /*
201  * else
202  * not an adj with BFD state
203  */
204  break;
205 
206  case BFD_LISTEN_EVENT_DELETE:
207  /*
208  * session has been removed.
209  */
211 
212  if (NULL != abd)
213  {
214  /*
215  * has an associated BFD tracking delegate
216  * remove the BFD tracking delegate, update children, then
217  * unlock the adj
218  */
220  pool_put(abd_pool, abd);
221 
223  adj_unlock(ai);
224  }
225  /*
226  * else
227  * no BFD associated state
228  */
229  break;
230  }
231 
232  /*
233  * unlock match of the add-or-lock at the start
234  */
235  adj_unlock(ai);
236 }
237 
238 int
240 {
241  const adj_bfd_delegate_t *abd;
242 
244 
245  if (NULL == abd)
246  {
247  /*
248  * no BFD tracking - resolved
249  */
250  return (!0);
251  }
252  else
253  {
254  /*
255  * defer to the state of the BFD tracking
256  */
257  return (ADJ_BFD_STATE_UP == abd->abd_state);
258  }
259 }
260 
261 /**
262  * Print a delegate that represents BFD tracking
263  */
264 static u8 *
266 {
268 
269  s = format(s, "BFD:[state:%s index:%d]",
271  abd->abd_index);
272 
273  return (s);
274 }
275 
276 const static adj_delegate_vft_t adj_delegate_vft = {
278 };
279 
280 static clib_error_t *
282 {
284 
285  adj_delegate_register_type (ADJ_DELEGATE_BFD, &adj_delegate_vft);
286 
287  return (0);
288 }
289 
290 /* *INDENT-OFF* */
292 {
293  .runs_after = VLIB_INITS("bfd_main_init"),
294 };
295 /* *INDENT-ON* */
static const adj_bfd_delegate_t * adj_bfd_from_const_base(const adj_delegate_t *ad)
Definition: adj_bfd.c:71
void adj_lock(adj_index_t adj_index)
Take a reference counting lock on the adjacency.
Definition: adj.c:307
#define NULL
Definition: clib.h:58
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
static u8 ip46_address_is_ip4(const ip46_address_t *ip46)
Definition: ip46_address.h:55
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:237
unsigned char u8
Definition: types.h:56
enum fib_protocol_t_ fib_protocol_t
Protocol Type.
static ip_adjacency_t * adj_get(adj_index_t adj_index)
Get a pointer to an adjacency object from its index.
Definition: adj.h:431
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
adj_bfd_state_t_
Distillation of the BFD session states into a go/no-go for using the associated tracked adjacency...
Definition: adj_bfd.c:26
void fib_walk_sync(fib_node_type_t parent_type, fib_node_index_t parent_index, fib_node_back_walk_ctx_t *ctx)
Back walk all the children of a FIB node.
Definition: fib_walk.c:745
void adj_unlock(adj_index_t adj_index)
Release a reference counting lock on the adjacency.
Definition: adj.c:324
Adj delegate.
Definition: adj_delegate.h:50
int adj_bfd_is_up(adj_index_t ai)
Definition: adj_bfd.c:239
unsigned int u32
Definition: types.h:88
static adj_bfd_state_t adj_bfd_bfd_state_to_fib(bfd_state_e bstate)
Definition: adj_bfd.c:81
struct adj_bfd_delegate_t_ adj_bfd_delegate_t
BFD delegate daa.
bfd_udp_key_t key
key identifying this session
Definition: bfd_udp.h:47
#define ADJ_INDEX_INVALID
Invalid ADJ index - used when no adj is known likewise blazoned capitals INVALID speak volumes where ...
Definition: adj_types.h:36
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:519
enum adj_bfd_state_t_ adj_bfd_state_t
Distillation of the BFD session states into a go/no-go for using the associated tracked adjacency...
int adj_delegate_add(ip_adjacency_t *adj, adj_delegate_type_t adt, index_t adi)
Add a delegate to an adjacency.
Definition: adj_delegate.c:107
long ctx[MAX_CONNS]
Definition: main.c:144
BFD global declarations.
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:287
static void adj_bfd_update_walk(adj_index_t ai)
Definition: adj_bfd.c:96
bfd_udp_session_t udp
Definition: bfd_main.h:238
vlib_main_t * vm
Definition: in2out_ed.c:1810
index_t ad_index
The index passed by the provider to identify its delegate instance.
Definition: adj_delegate.h:66
static clib_error_t * adj_bfd_main_init(vlib_main_t *vm)
Definition: adj_bfd.c:281
u32 adj_index_t
An index for adjacencies.
Definition: adj_types.h:30
bfd_state_e
Definition: bfd_protocol.h:195
Context passed between object during a back walk.
Definition: fib_node.h:208
BFD session state.
Definition: adj_delegate.h:38
void adj_delegate_register_type(adj_delegate_type_t type, const adj_delegate_vft_t *vft)
adj_delegate_register_type
Definition: adj_delegate.c:185
static const char * adj_bfd_state_names[]
Definition: adj_bfd.c:37
adj_delegate_t * adj_delegate_get(const ip_adjacency_t *adj, adj_delegate_type_t type)
Get a delegate from an adjacency.
Definition: adj_delegate.c:58
adj_delegate_format_t adv_format
Definition: adj_delegate.h:89
bfd_hop_type_e hop_type
BFD hop type.
Definition: bfd_main.h:97
static adj_bfd_delegate_t * adj_bfd_from_base(adj_delegate_t *ad)
Definition: adj_bfd.c:61
static u8 * adj_delegate_fmt_bfd(const adj_delegate_t *aed, u8 *s)
Print a delegate that represents BFD tracking.
Definition: adj_bfd.c:265
bfd_state_e local_state
session state
Definition: bfd_main.h:91
typedef key
Definition: ipsec_types.api:83
static adj_bfd_delegate_t * abd_pool
Pool of delegates.
Definition: adj_bfd.c:58
void bfd_register_listener(bfd_notify_fn_t fn)
Register a callback function to receive session notifications.
Definition: bfd_main.c:1294
BFD delegate daa.
Definition: adj_bfd.c:42
An ADJ delegate virtual function table.
Definition: adj_delegate.h:88
u32 bs_idx
index in bfd_main.sessions pool
Definition: bfd_main.h:88
adj_index_t adj_nbr_add_or_lock(fib_protocol_t nh_proto, vnet_link_t link_type, const ip46_address_t *nh_addr, u32 sw_if_index)
Neighbour Adjacency sub-type.
Definition: adj_nbr.c:218
adj_bfd_state_t abd_state
BFD session state.
Definition: adj_bfd.c:47
vnet_link_t fib_proto_to_link(fib_protocol_t proto)
Convert from a protocol to a link type.
Definition: fib_types.c:294
#define ADJ_BFD_STATES
Definition: adj_bfd.c:32
void adj_bfd_notify(bfd_listen_event_e event, const bfd_session_t *session)
Callback function registered with BFD module to receive notifications of the CRUD of BFD sessions wou...
Definition: adj_bfd.c:114
#define VLIB_INITS(...)
Definition: init.h:344
void adj_delegate_remove(adj_index_t ai, adj_delegate_type_t type)
Remove a delegate from an adjacency.
Definition: adj_delegate.c:65
bfd_listen_event_e
Definition: bfd_main.h:250
u32 abd_index
BFD session index.
Definition: adj_bfd.c:52