FD.io VPP  v21.01.1
Vector Packet Processing
teib.c
Go to the documentation of this file.
1 /*
2  * teib.h: Tunnel Endpoint Information Base
3  *
4  * Copyright (c) 2020 Cisco and/or its affiliates.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 
19 #include <vnet/teib/teib.h>
20 #include <vnet/fib/fib_table.h>
21 #include <vnet/adj/adj_midchain.h>
22 #include <vnet/ip/ip6_ll_table.h>
23 
24 typedef struct teib_key_t_
25 {
27  u8 __pad[3];
29 } __clib_packed teib_key_t;
30 
32 
34 {
38 };
39 
40 typedef struct teib_db_t_
41 {
42  u32 td_n_entries[N_AF];
44 } teib_db_t;
45 
50 
51 #define TEIB_NOTIFY(_te, _fn) { \
52  teib_vft_t *_vft; \
53  vec_foreach(_vft, teib_vfts) { \
54  if (_vft->_fn) { \
55  _vft->_fn(_te); \
56  } \
57  } \
58 }
59 
60 #define TEIB_DBG(...) \
61  vlib_log_debug (teib_logger, __VA_ARGS__);
62 
63 #define TEIB_INFO(...) \
64  vlib_log_notice (teib_logger, __VA_ARGS__);
65 
66 #define TEIB_TE_DBG(_te, _fmt, _args...) \
67  vlib_log_debug (teib_logger, "[%U]: " _fmt, format_teib_entry, _te - teib_pool, ##_args)
68 #define TEIB_TE_INFO(_te, _fmt, _args...) \
69  vlib_log_notice (teib_logger, "[%U]: " _fmt, format_teib_entry, _te - teib_pool, ##_args)
70 
71 u32
73 {
74  return (te->te_key->tk_sw_if_index);
75 }
76 
79 {
80  return (ip_addr_version (&te->te_key->tk_peer));
81 }
82 
83 u32
85 {
86  return (te->te_fib_index);
87 }
88 
89 const ip_address_t *
91 {
92  return (&te->te_key->tk_peer);
93 }
94 
95 const fib_prefix_t *
97 {
98  return (&te->te_nh);
99 }
100 
101 void
103 {
105 }
106 
107 teib_entry_t *
109 {
110  return pool_elt_at_index (teib_pool, tei);
111 }
112 
113 teib_entry_t *
115 {
116  teib_key_t nk = {
117  .tk_peer = *peer,
118  .tk_sw_if_index = sw_if_index,
119  };
120  uword *p;
121 
122  p = hash_get_mem (teib_db.td_db, &nk);
123 
124  if (NULL != p)
125  return teib_entry_get (p[0]);
126 
127  return (NULL);
128 }
129 
130 teib_entry_t *
132  fib_protocol_t fproto, const ip46_address_t * peer)
133 {
135 
136  ip_address_from_46 (peer, fproto, &ip);
137 
138  return (teib_entry_find (sw_if_index, &ip));
139 }
140 
141 static void
143 {
144  if (AF_IP6 == ip_addr_version (ip) &&
146  {
147  ip6_ll_prefix_t pfx = {
148  .ilp_addr = ip_addr_v6 (ip),
149  .ilp_sw_if_index = sw_if_index,
150  };
152  }
153  else
154  {
155  fib_prefix_t pfx;
156 
157  ip_address_to_fib_prefix (ip, &pfx);
158  fib_table_entry_path_add (fib_index, &pfx, FIB_SOURCE_ADJ,
161  &pfx.fp_addr,
162  sw_if_index,
163  ~0, 1, NULL, FIB_ROUTE_PATH_FLAG_NONE);
164 
165 
166  if (0 == teib_db.td_n_entries[ip_addr_version (ip)]++)
167  fib_table_lock (fib_index, pfx.fp_proto, FIB_SOURCE_ADJ);
168  }
169 }
170 
171 static void
173 {
174  if (AF_IP6 == ip_addr_version (ip) &&
176  {
177  ip6_ll_prefix_t pfx = {
178  .ilp_addr = ip_addr_v6 (ip),
179  .ilp_sw_if_index = sw_if_index,
180  };
182  }
183  else
184  {
185  fib_prefix_t pfx;
186 
187  ip_address_to_fib_prefix (ip, &pfx);
190  &pfx.fp_addr,
191  sw_if_index,
192  ~0, 1, FIB_ROUTE_PATH_FLAG_NONE);
193 
194  if (0 == --teib_db.td_n_entries[ip_addr_version (ip)])
195  fib_table_unlock (fib_index, pfx.fp_proto, FIB_SOURCE_ADJ);
196  }
197 }
198 
199 int
201  const ip_address_t * peer,
202  u32 nh_table_id, const ip_address_t * nh)
203 {
204  fib_protocol_t nh_proto;
205  teib_entry_t *te;
206  u32 fib_index;
207  index_t tei;
208 
209  nh_proto = (AF_IP4 == ip_addr_version (nh) ?
211 
212  fib_index = fib_table_find (nh_proto, nh_table_id);
213 
214  if (~0 == fib_index)
215  {
216  return (VNET_API_ERROR_NO_SUCH_FIB);
217  }
218 
219  te = teib_entry_find (sw_if_index, peer);
220 
221  if (NULL == te)
222  {
223  teib_key_t nk = {
224  .tk_peer = *peer,
225  .tk_sw_if_index = sw_if_index,
226  };
227  teib_entry_t *te;
228  u32 fib_index;
229 
230  fib_index = fib_table_get_index_for_sw_if_index (nh_proto, sw_if_index);
231 
232  pool_get_zero (teib_pool, te);
233 
234  tei = te - teib_pool;
235  te->te_key = clib_mem_alloc (sizeof (*te->te_key));
236  clib_memcpy (te->te_key, &nk, sizeof (*te->te_key));
237 
238  ip_address_to_fib_prefix (nh, &te->te_nh);
239  te->te_fib_index = fib_index;
240 
241  hash_set_mem (teib_db.td_db, te->te_key, tei);
242 
243  /* we how have a /32 in the overlay, add an adj-fib */
244  teib_adj_fib_add (&te->te_key->tk_peer, sw_if_index, fib_index);
245 
246  TEIB_NOTIFY (te, nv_added);
247  TEIB_TE_INFO (te, "created");
248  }
249  else
250  {
251  TEIB_TE_INFO (te, "exists");
252  return (VNET_API_ERROR_ENTRY_ALREADY_EXISTS);
253  }
254  return 0;
255 }
256 
257 int
259 {
260  teib_entry_t *te;
261 
262  te = teib_entry_find (sw_if_index, peer);
263 
264  if (te != NULL)
265  {
266  TEIB_TE_INFO (te, "removed");
267 
268  u32 fib_index;
269 
272  sw_if_index);
273 
274  teib_adj_fib_remove (&te->te_key->tk_peer, sw_if_index, fib_index);
275 
276  hash_unset_mem (teib_db.td_db, te->te_key);
277 
278  TEIB_NOTIFY (te, nv_deleted);
279 
280  clib_mem_free (te->te_key);
281  pool_put (teib_pool, te);
282  }
283  else
284  {
285  TEIB_INFO ("no such entry: %U, %U, %U",
287  vnet_get_main (), sw_if_index, format_ip_address, peer);
288  return (VNET_API_ERROR_NO_SUCH_ENTRY);
289  }
290  return 0;
291 }
292 
293 u8 *
294 format_teib_entry (u8 * s, va_list * args)
295 {
296  index_t tei = va_arg (*args, index_t);
297  vnet_main_t *vnm = vnet_get_main ();
298  teib_entry_t *te;
299 
300  te = teib_entry_get (tei);
301 
302  s = format (s, "[%d] ", tei);
303  s = format (s, "%U:", format_vnet_sw_if_index_name,
304  vnm, te->te_key->tk_sw_if_index);
305  s = format (s, "%U", format_ip_address,
306  &te->te_key->tk_peer, IP46_TYPE_ANY);
307  s = format (s, " via [%d]:%U",
309  format_fib_prefix, &te->te_nh);
310 
311  return (s);
312 }
313 
314 void
316 {
317  index_t tei;
318 
319  /* *INDENT-OFF* */
320  pool_foreach_index (tei, teib_pool)
321  {
322  fn(tei, ctx);
323  }
324  /* *INDENT-ON* */
325 }
326 
327 void
329 {
330  index_t tei;
331 
332  /* *INDENT-OFF* */
333  pool_foreach_index (tei, teib_pool)
334  {
335  if (sw_if_index == teib_entry_get_sw_if_index(teib_entry_get(tei)))
336  fn(tei, ctx);
337  }
338  /* *INDENT-ON* */
339 }
340 
341 static void
343  ip_address_family_t af, teib_walk_cb_t fn, void *ctx)
344 {
345  index_t tei;
346 
347  /* *INDENT-OFF* */
348  pool_foreach_index (tei, teib_pool)
349  {
350  if (sw_if_index == teib_entry_get_sw_if_index(teib_entry_get(tei)) &&
351  af == teib_entry_get_af(teib_entry_get(tei)))
352  fn(tei, ctx);
353  }
354  /* *INDENT-ON* */
355 }
356 
358 {
362 
363 static walk_rc_t
365 {
366  teib_table_bind_ctx_t *ctx = arg;
367  teib_entry_t *te;
368 
369  te = teib_entry_get (tei);
370 
371  TEIB_TE_INFO (te, "bind: %d -> %d", ctx->old_fib_index, ctx->new_fib_index);
372 
374  te->te_key->tk_sw_if_index, ctx->old_fib_index);
376  te->te_key->tk_sw_if_index, ctx->new_fib_index);
377 
378  return (WALK_CONTINUE);
379 }
380 
381 static void
383  uword opaque,
384  u32 sw_if_index, u32 new_fib_index, u32 old_fib_index)
385 {
387  .old_fib_index = old_fib_index,
388  .new_fib_index = new_fib_index,
389  };
390 
391  teib_walk_itf_proto (sw_if_index, AF_IP4, teib_walk_table_bind, &ctx);
392 }
393 
394 static void
396  uword opaque,
397  u32 sw_if_index, u32 new_fib_index, u32 old_fib_index)
398 {
400  .old_fib_index = old_fib_index,
401  .new_fib_index = new_fib_index,
402  };
403 
404  teib_walk_itf_proto (sw_if_index, AF_IP6, teib_walk_table_bind, &ctx);
405 }
406 
407 void
409 {
410  vec_add1 (teib_vfts, *vft);
411 }
412 
413 static clib_error_t *
415 {
416  teib_db.td_db = hash_create_mem (0, sizeof (teib_key_t), sizeof (u32));
417 
420  };
422 
425  };
427 
428  teib_logger = vlib_log_register_class ("teib", "teib");
429 
430  return (NULL);
431 }
432 
434 
435 /*
436  * fd.io coding-style-patch-verification: ON
437  *
438  * Local Variables:
439  * eval: (c-set-style "gnu")
440  * End:
441  */
vlib_log_class_t vlib_log_register_class(char *class, char *subclass)
Definition: log.c:338
fib_protocol_t fp_proto
protocol type
Definition: fib_types.h:211
fib_node_index_t fib_table_entry_path_add(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags, dpo_proto_t next_hop_proto, const ip46_address_t *next_hop, u32 next_hop_sw_if_index, u32 next_hop_fib_index, u32 next_hop_weight, fib_mpls_label_t *next_hop_labels, fib_route_path_flags_t path_flags)
Add one path to an entry (aka route) in the FIB.
Definition: fib_table.c:558
u32 te_fib_index
Definition: teib.c:37
#define ip_addr_v6(_a)
Definition: ip_types.h:92
u32 tk_sw_if_index
Definition: teib.c:28
ip4_table_bind_function_t * function
Definition: ip4.h:94
#define pool_foreach_index(i, v)
Definition: pool.h:569
teib_entry_t * teib_entry_get(index_t tei)
Definition: teib.c:108
int teib_entry_del(u32 sw_if_index, const ip_address_t *peer)
Definition: teib.c:258
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
#define pool_get_zero(P, E)
Allocate an object E from a pool P and zero it.
Definition: pool.h:254
static void teib_table_bind_v4(ip4_main_t *im, uword opaque, u32 sw_if_index, u32 new_fib_index, u32 old_fib_index)
Definition: teib.c:382
vl_api_fib_path_nh_t nh
Definition: fib_types.api:126
void teib_walk(teib_walk_cb_t fn, void *ctx)
Definition: teib.c:315
struct teib_key_t_ teib_key_t
void adj_midchain_delegate_stack(adj_index_t ai, u32 fib_index, const fib_prefix_t *pfx)
create/attach a midchain delegate and stack it on the prefix passed
u32 fib_table_get_index_for_sw_if_index(fib_protocol_t proto, u32 sw_if_index)
Get the index of the FIB bound to the interface.
Definition: fib_table.c:998
u32 index_t
A Data-Path Object is an object that represents actions that are applied to packets are they are swit...
Definition: dpo.h:41
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:592
static clib_error_t * teib_init(vlib_main_t *vm)
Definition: teib.c:414
STATIC_ASSERT_SIZEOF(teib_key_t, 24)
#define hash_set_mem(h, key, value)
Definition: hash.h:275
vlib_main_t * vm
Definition: in2out_ed.c:1580
teib_key_t * te_key
Definition: teib.c:35
fib_prefix_t te_nh
Definition: teib.c:36
#define ip_addr_version(_a)
Definition: ip_types.h:93
Definition: fib_entry.h:114
format_function_t format_vnet_sw_if_index_name
unsigned char u8
Definition: types.h:56
enum fib_protocol_t_ fib_protocol_t
Protocol Type.
static void teib_adj_fib_add(const ip_address_t *ip, u32 sw_if_index, u32 fib_index)
Definition: teib.c:142
void teib_walk_itf(u32 sw_if_index, teib_walk_cb_t fn, void *ctx)
Definition: teib.c:328
u8 * format_teib_entry(u8 *s, va_list *args)
Definition: teib.c:294
#define clib_memcpy(d, s, n)
Definition: string.h:180
ip_address_t tk_peer
Definition: teib.c:26
u32 teib_entry_get_fib_index(const teib_entry_t *te)
Definition: teib.c:84
enum walk_rc_t_ walk_rc_t
Walk return code.
u32 vlib_log_class_t
Definition: vlib.h:51
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
static walk_rc_t teib_walk_table_bind(index_t tei, void *arg)
Definition: teib.c:364
description fragment has unexpected format
Definition: map.api:433
u8 * format_fib_prefix(u8 *s, va_list *args)
Definition: fib_types.c:283
Aggregate type for a prefix.
Definition: fib_types.h:202
void ip_address_to_fib_prefix(const ip_address_t *addr, fib_prefix_t *prefix)
convert from a IP address to a FIB prefix
Definition: ip_types.c:271
unsigned int u32
Definition: types.h:88
static void teib_walk_itf_proto(u32 sw_if_index, ip_address_family_t af, teib_walk_cb_t fn, void *ctx)
Definition: teib.c:342
u32 fib_table_find(fib_protocol_t proto, u32 table_id)
Get the index of the FIB for a Table-ID.
Definition: fib_table.c:1106
uword * td_db
Definition: teib.c:43
#define hash_create_mem(elts, key_bytes, value_bytes)
Definition: hash.h:661
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:546
#define hash_unset_mem(h, key)
Definition: hash.h:291
void ip_address_from_46(const ip46_address_t *nh, fib_protocol_t fproto, ip_address_t *ip)
Definition: ip_types.c:260
ip46_address_t fp_addr
The address type is not deriveable from the fp_addr member.
Definition: fib_types.h:225
u32 teib_entry_get_sw_if_index(const teib_entry_t *te)
accessors for the opaque struct
Definition: teib.c:72
walk_rc_t(* teib_walk_cb_t)(index_t nei, void *ctx)
Definition: teib.h:61
long ctx[MAX_CONNS]
Definition: main.c:144
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:301
ip6_table_bind_callback_t * table_bind_callbacks
Functions to call when interface to table biding changes.
Definition: ip6.h:151
static teib_db_t teib_db
Definition: teib.c:46
ip6_main_t ip6_main
Definition: ip6_forward.c:2785
Adjacency source.
Definition: fib_source.h:102
void fib_table_unlock(u32 fib_index, fib_protocol_t proto, fib_source_t source)
Take a reference counting lock on the table.
Definition: fib_table.c:1300
vl_api_address_t peer
Definition: teib.api:28
void teib_entry_adj_stack(const teib_entry_t *te, adj_index_t ai)
Definition: teib.c:102
static void teib_table_bind_v6(ip6_main_t *im, uword opaque, u32 sw_if_index, u32 new_fib_index, u32 old_fib_index)
Definition: teib.c:395
static teib_entry_t * teib_pool
Definition: teib.c:47
int teib_entry_add(u32 sw_if_index, const ip_address_t *peer, u32 nh_table_id, const ip_address_t *nh)
Create a new TEIB entry.
Definition: teib.c:200
Definition: teib.c:33
teib_entry_t * teib_entry_find(u32 sw_if_index, const ip_address_t *peer)
Definition: teib.c:114
const ip_address_t * teib_entry_get_peer(const teib_entry_t *te)
Definition: teib.c:90
u8 * format_ip_address(u8 *s, va_list *args)
Definition: ip_types.c:21
u32 adj_index_t
An index for adjacencies.
Definition: adj_types.h:30
fib_protocol_t ip_address_family_to_fib_proto(ip_address_family_t af)
Definition: ip_types.c:224
u32 td_n_entries[N_AF]
Definition: teib.c:42
ip6_address_t ilp_addr
the IP6 address
Definition: ip6_ll_types.h:34
void fib_table_lock(u32 fib_index, fib_protocol_t proto, fib_source_t source)
Release a reference counting lock on the table.
Definition: fib_table.c:1319
u32 fib_table_get_table_id(u32 fib_index, fib_protocol_t proto)
Get the Table-ID of the FIB from protocol and index.
Definition: fib_table.c:1095
IPv4 main type.
Definition: ip4.h:107
static void clib_mem_free(void *p)
Definition: mem.h:311
#define TEIB_TE_INFO(_te, _fmt, _args...)
Definition: teib.c:68
Aggregate type for a prefix in the IPv6 Link-local table.
Definition: ip6_ll_types.h:24
dpo_proto_t fib_proto_to_dpo(fib_protocol_t fib_proto)
Definition: fib_types.c:343
static uword ip6_address_is_link_local_unicast(const ip6_address_t *a)
Definition: ip6_packet.h:253
void fib_table_entry_path_remove(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, dpo_proto_t next_hop_proto, const ip46_address_t *next_hop, u32 next_hop_sw_if_index, u32 next_hop_fib_index, u32 next_hop_weight, fib_route_path_flags_t path_flags)
remove one path to an entry (aka route) in the FIB.
Definition: fib_table.c:731
static void * clib_mem_alloc(uword size)
Definition: mem.h:253
enum ip_address_family_t_ ip_address_family_t
#define TEIB_NOTIFY(_te, _fn)
Definition: teib.c:51
ip4_table_bind_callback_t * table_bind_callbacks
Functions to call when interface to table biding changes.
Definition: ip4.h:148
static ip_address_family_t teib_entry_get_af(const teib_entry_t *te)
Definition: teib.c:78
struct teib_db_t_ teib_db_t
#define N_AF
Definition: ip_types.h:27
vl_api_address_t ip
Definition: l2.api:501
teib_entry_t * teib_entry_find_46(u32 sw_if_index, fib_protocol_t fproto, const ip46_address_t *peer)
Definition: teib.c:131
static teib_vft_t * teib_vfts
Definition: teib.c:48
u64 uword
Definition: types.h:112
static void teib_adj_fib_remove(ip_address_t *ip, u32 sw_if_index, u32 fib_index)
Definition: teib.c:172
#define TEIB_INFO(...)
Definition: teib.c:63
ip6_table_bind_function_t * function
Definition: ip6.h:106
void ip6_ll_table_entry_delete(const ip6_ll_prefix_t *ilp)
Delete a IP6 link-local entry.
Definition: ip6_ll_table.c:140
#define hash_get_mem(h, key)
Definition: hash.h:269
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1105
static vlib_log_class_t teib_logger
Definition: teib.c:49
struct teib_table_bind_ctx_t_ teib_table_bind_ctx_t
fib_node_index_t ip6_ll_table_entry_update(const ip6_ll_prefix_t *ilp, fib_route_path_flags_t flags)
Update an entry in the table.
Definition: ip6_ll_table.c:106
void teib_register(const teib_vft_t *vft)
Definition: teib.c:408
u32 nh_table_id
Definition: teib.api:30
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
const fib_prefix_t * teib_entry_get_nh(const teib_entry_t *te)
Definition: teib.c:96