FD.io VPP  v21.01.1
Vector Packet Processing
gbp_itf.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018 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 <plugins/gbp/gbp_itf.h>
19 
20 #include <vnet/ip/ip.h>
21 
22 #define foreach_gbp_itf_mode \
23  _(L2, "l2") \
24  _(L3, "L3")
25 
26 typedef enum gbp_ift_mode_t_
27 {
28 #define _(s,v) GBP_ITF_MODE_##s,
30 #undef _
32 
33 /**
34  * Attributes and configurations attached to interfaces by GBP
35  */
36 typedef struct gbp_itf_t_
37 {
38  /**
39  * Number of references to this interface
40  */
42 
43  /**
44  * The interface this wrapper is managing
45  */
47 
48  /**
49  * The mode of the interface
50  */
52 
53  /**
54  * Users of this interface - this is encoded in the user's handle
55  */
57 
58  /**
59  * L2/L3 Features configured by each user
60  */
65 
66  /**
67  * function to call when the interface is deleted.
68  */
70 
71  union
72  {
73  /**
74  * GBP BD or RD index
75  */
78  };
79 } gbp_itf_t;
80 
82 static uword *gbp_itf_db;
83 
84 static const char *gbp_itf_feat_bit_pos_to_arc[] = {
85 #define _(s,v,a) [GBP_ITF_L3_FEAT_POS_##s] = a,
87 #undef _
88 };
89 
90 static const char *gbp_itf_feat_bit_pos_to_feat[] = {
91 #define _(s,v,a) [GBP_ITF_L3_FEAT_POS_##s] = v,
93 #undef _
94 };
95 
96 u8 *
97 format_gbp_itf_l3_feat (u8 * s, va_list * args)
98 {
99  gbp_itf_l3_feat_t flags = va_arg (*args, gbp_itf_l3_feat_t);
100 
101 #define _(a, b, c) \
102  if (flags & GBP_ITF_L3_FEAT_##a) \
103  s = format (s, "%s ", b);
105 #undef _
106  return (s);
107 }
108 
109 void
111 {
112  *gh = GBP_ITF_HDL_INVALID;
113 }
114 
115 bool
117 {
118  return (gh.gh_which != GBP_ITF_HDL_INVALID.gh_which);
119 }
120 
121 static gbp_itf_t *
123 {
124  if (pool_is_free_index (gbp_itf_pool, gii))
125  return (NULL);
126 
127  return (pool_elt_at_index (gbp_itf_pool, gii));
128 }
129 
130 static gbp_itf_t *
132 {
133  uword *p;
134 
135  p = hash_get (gbp_itf_db, sw_if_index);
136 
137  if (NULL != p)
138  return (gbp_itf_get (p[0]));
139 
140  return (NULL);
141 }
142 
143 static gbp_itf_t *
145 {
146  return (gbp_itf_find (gh.gh_which));
147 }
148 
149 u32
151 {
152  return (hdl.gh_which);
153 }
154 
155 static gbp_itf_hdl_t
157 {
158  gbp_itf_hdl_t gh;
159  u32 *useri;
160 
161  pool_get (gi->gi_users, useri);
162  *useri = 0;
163 
164  gh.gh_who = useri - gi->gi_users;
165  gh.gh_which = gi->gi_sw_if_index;
166 
167  return (gh);
168 }
169 
170 static gbp_itf_hdl_t
172 {
173  gbp_itf_t *gi;
174 
175  gi = gbp_itf_find (sw_if_index);
176 
177  if (NULL == gi)
178  {
179  pool_get_zero (gbp_itf_pool, gi);
180 
182  gi->gi_gbi = gbi;
183  gi->gi_mode = GBP_ITF_MODE_L2;
184  gi->gi_free_fn = ff;
185 
188 
189  hash_set (gbp_itf_db, gi->gi_sw_if_index, gi - gbp_itf_pool);
190  }
191 
192  gi->gi_locks++;
193 
194  return (gbp_itf_mk_hdl (gi));
195 }
196 
199 {
200  return (gbp_itf_l2_add_and_lock_i (sw_if_index, gbi, NULL));
201 }
202 
205  index_t gbi, gbp_itf_free_fn_t ff)
206 {
207  return (gbp_itf_l2_add_and_lock_i (sw_if_index, gbi, ff));
208 }
209 
212 {
213  gbp_itf_t *gi;
214 
215  gi = gbp_itf_find (sw_if_index);
216 
217  if (NULL == gi)
218  {
219  const gbp_route_domain_t *grd;
220  fib_protocol_t fproto;
221 
222  pool_get_zero (gbp_itf_pool, gi);
223 
225  gi->gi_mode = GBP_ITF_MODE_L3;
226  gi->gi_gri = gri;
227  gi->gi_free_fn = ff;
228 
229  grd = gbp_route_domain_get (gi->gi_gri);
230 
233 
234  FOR_EACH_FIB_IP_PROTOCOL (fproto)
235  ip_table_bind (fproto, gi->gi_sw_if_index,
236  grd->grd_table_id[fproto], 1);
237 
238  hash_set (gbp_itf_db, gi->gi_sw_if_index, gi - gbp_itf_pool);
239  }
240 
241  gi->gi_locks++;
242 
243  return (gbp_itf_mk_hdl (gi));
244 }
245 
248 {
249  return (gbp_itf_l3_add_and_lock_i (sw_if_index, gri, NULL));
250 }
251 
254  index_t gri, gbp_itf_free_fn_t ff)
255 {
256  return (gbp_itf_l3_add_and_lock_i (sw_if_index, gri, ff));
257 }
258 
259 void
261 {
262  gbp_itf_t *gi;
263 
264  if (!gbp_itf_hdl_is_valid (gh))
265  return;
266 
267  gi = gbp_itf_find_hdl (gh);
268 
269  gi->gi_locks++;
270 }
271 
274 {
275  gbp_itf_t *gi;
276 
277  if (!gbp_itf_hdl_is_valid (gh))
278  return (GBP_ITF_HDL_INVALID);
279 
280  gi = gbp_itf_find_hdl (gh);
281 
282  gi->gi_locks++;
283 
284  return (gbp_itf_mk_hdl (gi));
285 }
286 
287 void
289 {
290  gbp_itf_t *gi;
291 
292  if (!gbp_itf_hdl_is_valid (*gh))
293  return;
294 
295  gi = gbp_itf_find_hdl (*gh);
296  ASSERT (gi->gi_locks > 0);
297  gi->gi_locks--;
298 
299  if (0 == gi->gi_locks)
300  {
301  if (GBP_ITF_MODE_L2 == gi->gi_mode)
302  {
306  gi->gi_sw_if_index,
308  }
309  else
310  {
311  fib_protocol_t fproto;
312 
314  FOR_EACH_FIB_IP_PROTOCOL (fproto)
315  ip_table_bind (fproto, gi->gi_sw_if_index, 0, 0);
316 
319  }
320 
322 
323  if (gi->gi_free_fn)
324  gi->gi_free_fn (gi->gi_sw_if_index);
325 
326  pool_free (gi->gi_users);
327  vec_free (gi->gi_input_fbs);
328  vec_free (gi->gi_output_fbs);
329 
330  memset (gi, 0, sizeof (*gi));
331  }
332 
333  gbp_itf_hdl_reset (gh);
334 }
335 
336 void
338 {
339  u32 diff_fb, new_fb, *fb, feat;
340  gbp_itf_t *gi;
341 
342  gi = gbp_itf_find_hdl (gh);
343 
344  if (NULL == gi || GBP_ITF_MODE_L3 != gi->gi_mode)
345  return;
346 
347  vec_validate (gi->gi_input_fbs, gh.gh_who);
348  gi->gi_input_fbs[gh.gh_who] = feats;
349 
350  new_fb = 0;
351  vec_foreach (fb, gi->gi_input_fbs)
352  {
353  new_fb |= *fb;
354  }
355 
356  /* add new features */
357  diff_fb = (gi->gi_input_fb ^ new_fb) & new_fb;
358 
359  /* *INDENT-OFF* */
360  foreach_set_bit (feat, diff_fb,
361  ({
364  gi->gi_sw_if_index, 1, 0, 0);
365  }));
366  /* *INDENT-ON* */
367 
368  /* remove unneeded features */
369  diff_fb = (gi->gi_input_fb ^ new_fb) & gi->gi_input_fb;
370 
371  /* *INDENT-OFF* */
372  foreach_set_bit (feat, diff_fb,
373  ({
376  gi->gi_sw_if_index, 0, 0, 0);
377  }));
378  /* *INDENT-ON* */
379 
380  gi->gi_input_fb = new_fb;
381 }
382 
383 void
385 {
386  u32 diff_fb, new_fb, *fb, feat;
387  gbp_itf_t *gi;
388 
389  gi = gbp_itf_find_hdl (gh);
390 
391  if (NULL == gi || GBP_ITF_MODE_L2 != gi->gi_mode)
392  {
393  ASSERT (0);
394  return;
395  }
396 
397  vec_validate (gi->gi_input_fbs, gh.gh_who);
398  gi->gi_input_fbs[gh.gh_who] = feats;
399 
400  new_fb = 0;
401  vec_foreach (fb, gi->gi_input_fbs)
402  {
403  new_fb |= *fb;
404  }
405 
406  /* add new features */
407  diff_fb = (gi->gi_input_fb ^ new_fb) & new_fb;
408 
409  /* *INDENT-OFF* */
410  foreach_set_bit (feat, diff_fb,
411  ({
412  l2input_intf_bitmap_enable (gi->gi_sw_if_index, (1 << feat), 1);
413  }));
414  /* *INDENT-ON* */
415 
416  /* remove unneeded features */
417  diff_fb = (gi->gi_input_fb ^ new_fb) & gi->gi_input_fb;
418 
419  /* *INDENT-OFF* */
420  foreach_set_bit (feat, diff_fb,
421  ({
422  l2input_intf_bitmap_enable (gi->gi_sw_if_index, (1 << feat), 0);
423  }));
424  /* *INDENT-ON* */
425 
426  gi->gi_input_fb = new_fb;
427 }
428 
429 void
431 {
432  u32 diff_fb, new_fb, *fb, feat;
433  gbp_itf_t *gi;
434 
435  gi = gbp_itf_find_hdl (gh);
436 
437  if (NULL == gi || GBP_ITF_MODE_L2 != gi->gi_mode)
438  {
439  ASSERT (0);
440  return;
441  }
442 
444  gi->gi_output_fbs[gh.gh_who] = feats;
445 
446  new_fb = 0;
447  vec_foreach (fb, gi->gi_output_fbs)
448  {
449  new_fb |= *fb;
450  }
451 
452  /* add new features */
453  diff_fb = (gi->gi_output_fb ^ new_fb) & new_fb;
454 
455  /* *INDENT-OFF* */
456  foreach_set_bit (feat, diff_fb,
457  ({
458  l2output_intf_bitmap_enable (gi->gi_sw_if_index, (1 << feat), 1);
459  }));
460  /* *INDENT-ON* */
461 
462  /* remove unneeded features */
463  diff_fb = (gi->gi_output_fb ^ new_fb) & gi->gi_output_fb;
464 
465  /* *INDENT-OFF* */
466  foreach_set_bit (feat, diff_fb,
467  ({
468  l2output_intf_bitmap_enable (gi->gi_sw_if_index, (1 << feat), 0);
469  }));
470  /* *INDENT-ON* */
471 
472  gi->gi_output_fb = new_fb;
473 }
474 
475 static u8 *
476 format_gbp_itf_mode (u8 * s, va_list * args)
477 {
478  gbp_itf_mode_t mode = va_arg (*args, gbp_itf_mode_t);
479 
480  switch (mode)
481  {
482 #define _(a,v) \
483  case GBP_ITF_MODE_##a: \
484  return format(s, "%s", v);
486 #undef _
487  }
488  return (s);
489 }
490 
491 static u8 *
492 format_gbp_itf (u8 * s, va_list * args)
493 {
494  index_t gii = va_arg (*args, index_t);
495  gbp_itf_t *gi;
496 
497  if (INDEX_INVALID == gii)
498  return (format (s, "unset"));
499 
500  gi = gbp_itf_get (gii);
501 
502  s = format (s, "%U locks:%d mode:%U ",
504  gi->gi_sw_if_index, gi->gi_locks,
506 
507  if (GBP_ITF_MODE_L2 == gi->gi_mode)
508  s = format (s, "gbp-bd:%d input-feats:[%U] output-feats:[%U]",
509  gi->gi_gbi,
512  else
513  s = format (s, "gbp-rd:%d input-feats:[%U] output-feats:[%U]",
514  gi->gi_gbi,
517 
518  return (s);
519 }
520 
521 u8 *
522 format_gbp_itf_hdl (u8 * s, va_list * args)
523 {
524  gbp_itf_hdl_t gh = va_arg (*args, gbp_itf_hdl_t);
525  gbp_itf_t *gi;
526 
527  gi = gbp_itf_find_hdl (gh);
528 
529  if (NULL == gi)
530  return format (s, "INVALID");
531 
532  return (format (s, "%U", format_gbp_itf, gi - gbp_itf_pool));
533 }
534 
535 static clib_error_t *
537  unformat_input_t * input, vlib_cli_command_t * cmd)
538 {
539  u32 gii;
540 
541  vlib_cli_output (vm, "Interfaces:");
542 
543  /* *INDENT-OFF* */
544  pool_foreach_index (gii, gbp_itf_pool)
545  {
546  vlib_cli_output (vm, " [%d] %U", gii, format_gbp_itf, gii);
547  }
548  /* *INDENT-ON* */
549 
550  return (NULL);
551 }
552 
553 /*?
554  * Show Group Based Interfaces
555  *
556  * @cliexpar
557  * @cliexstart{show gbp contract}
558  * @cliexend
559  ?*/
560 /* *INDENT-OFF* */
561 VLIB_CLI_COMMAND (gbp_contract_show_node, static) = {
562  .path = "show gbp interface",
563  .short_help = "show gbp interface\n",
564  .function = gbp_itf_show,
565 };
566 /* *INDENT-ON* */
567 
568 
569 /*
570  * fd.io coding-style-patch-verification: ON
571  *
572  * Local Variables:
573  * eval: (c-set-style "gnu")
574  * End:
575  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:509
u8 * format_l2_input_features(u8 *s, va_list *args)
Definition: l2_input.c:98
void gbp_bridge_domain_itf_add(index_t gbdi, u32 sw_if_index, l2_bd_port_type_t type)
void gbp_bridge_domain_itf_del(index_t gbdi, u32 sw_if_index, l2_bd_port_type_t type)
u32 grd_table_id[FIB_PROTOCOL_IP_MAX]
u32 gh_which
Definition: gbp_itf.h:52
#define hash_set(h, key, value)
Definition: hash.h:255
#define pool_foreach_index(i, v)
Definition: pool.h:569
void(* gbp_itf_free_fn_t)(u32 sw_if_index)
Definition: gbp_itf.h:63
#define hash_unset(h, key)
Definition: hash.h:261
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:105
static gbp_itf_hdl_t gbp_itf_mk_hdl(gbp_itf_t *gi)
Definition: gbp_itf.c:156
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
gbp_itf_hdl_t gbp_itf_l3_add_and_lock(u32 sw_if_index, index_t gri)
Definition: gbp_itf.c:247
u8 * format_l2_output_features(u8 *s, va_list *args)
Definition: l2_output.c:44
#define pool_get_zero(P, E)
Allocate an object E from a pool P and zero it.
Definition: pool.h:254
void gbp_itf_l2_set_output_feature(gbp_itf_hdl_t gh, l2output_feat_masks_t feats)
Definition: gbp_itf.c:430
u32 gi_sw_if_index
The interface this wrapper is managing.
Definition: gbp_itf.c:46
static gbp_itf_t * gbp_itf_pool
Definition: gbp_itf.c:81
gbp_itf_mode_t gi_mode
The mode of the interface.
Definition: gbp_itf.c:51
void gbp_itf_unlock(gbp_itf_hdl_t *gh)
Definition: gbp_itf.c:288
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
u32 gi_output_fb
Definition: gbp_itf.c:64
vlib_main_t * vm
Definition: in2out_ed.c:1580
enum gbp_itf_l3_feat_t_ gbp_itf_l3_feat_t
static gbp_itf_hdl_t gbp_itf_l2_add_and_lock_i(u32 sw_if_index, index_t gbi, gbp_itf_free_fn_t ff)
Definition: gbp_itf.c:171
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:251
static const char * gbp_itf_feat_bit_pos_to_arc[]
Definition: gbp_itf.c:84
static u8 * format_gbp_itf_mode(u8 *s, va_list *args)
Definition: gbp_itf.c:476
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.
u32 * gi_output_fbs
Definition: gbp_itf.c:63
#define foreach_set_bit(var, mask, body)
Definition: bitops.h:166
u32 gbp_itf_get_sw_if_index(gbp_itf_hdl_t hdl)
Definition: gbp_itf.c:150
int ip_table_bind(fib_protocol_t fproto, u32 sw_if_index, u32 table_id, u8 is_api)
struct gbp_itf_t_ gbp_itf_t
Attributes and configurations attached to interfaces by GBP.
u8 * format_gbp_itf_l3_feat(u8 *s, va_list *args)
Definition: gbp_itf.c:97
description fragment has unexpected format
Definition: map.api:433
#define foreach_gbp_itf_mode
Definition: gbp_itf.c:22
unsigned int u32
Definition: types.h:88
u32 gi_locks
Number of references to this interface.
Definition: gbp_itf.c:41
#define hash_get(h, key)
Definition: hash.h:249
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:546
void ip4_sw_interface_enable_disable(u32 sw_if_index, u32 is_enable)
Definition: ip4_forward.c:601
static gbp_itf_t * gbp_itf_find_hdl(gbp_itf_hdl_t gh)
Definition: gbp_itf.c:144
u32 * gi_input_fbs
L2/L3 Features configured by each user.
Definition: gbp_itf.c:61
gbp_itf_hdl_t gbp_itf_l2_add_and_lock_w_free(u32 sw_if_index, index_t gbi, gbp_itf_free_fn_t ff)
Definition: gbp_itf.c:204
struct _unformat_input_t unformat_input_t
static uword * gbp_itf_db
Definition: gbp_itf.c:82
u32 gi_input_fb
Definition: gbp_itf.c:62
static gbp_itf_t * gbp_itf_get(index_t gii)
Definition: gbp_itf.c:122
l2input_feat_masks_t
Definition: l2_input.h:169
void l2output_intf_bitmap_enable(u32 sw_if_index, l2output_feat_masks_t feature_bitmap, u32 enable)
Enable (or disable) the feature in the bitmap for the given interface.
Definition: l2_output.c:625
vl_api_tunnel_mode_t mode
Definition: gre.api:48
u32 gi_gbi
GBP BD or RD index.
Definition: gbp_itf.c:76
void gbp_itf_hdl_reset(gbp_itf_hdl_t *gh)
Definition: gbp_itf.c:110
bool gbp_itf_hdl_is_valid(gbp_itf_hdl_t gh)
Definition: gbp_itf.c:116
#define pool_free(p)
Free a pool.
Definition: pool.h:440
index_t gi_gri
Definition: gbp_itf.c:77
gbp_itf_hdl_t gbp_itf_l3_add_and_lock_w_free(u32 sw_if_index, index_t gri, gbp_itf_free_fn_t ff)
Definition: gbp_itf.c:253
Attributes and configurations attached to interfaces by GBP.
Definition: gbp_itf.c:36
gbp_itf_hdl_t gbp_itf_l2_add_and_lock(u32 sw_if_index, index_t gbi)
Definition: gbp_itf.c:198
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:380
gbp_ift_mode_t_
Definition: gbp_itf.c:26
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:298
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:158
#define ASSERT(truth)
gbp_route_domain_t * gbp_route_domain_get(index_t i)
l2output_feat_masks_t
Definition: l2_output.h:111
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:696
void gbp_itf_lock(gbp_itf_hdl_t gh)
Definition: gbp_itf.c:260
u8 * format_gbp_itf_hdl(u8 *s, va_list *args)
Definition: gbp_itf.c:522
static const char * gbp_itf_feat_bit_pos_to_feat[]
Definition: gbp_itf.c:90
gbp_itf_hdl_t gbp_itf_l3_add_and_lock_i(u32 sw_if_index, index_t gri, gbp_itf_free_fn_t ff)
Definition: gbp_itf.c:211
static clib_error_t * gbp_itf_show(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: gbp_itf.c:536
u32 l2input_intf_bitmap_enable(u32 sw_if_index, l2input_feat_masks_t feature_bitmap, u32 enable)
Enable (or disable) the feature in the bitmap for the given interface.
Definition: l2_input.c:177
void gbp_itf_l3_set_input_feature(gbp_itf_hdl_t gh, gbp_itf_l3_feat_t feats)
Definition: gbp_itf.c:337
void gbp_itf_l2_set_input_feature(gbp_itf_hdl_t gh, l2input_feat_masks_t feats)
Definition: gbp_itf.c:384
A route Domain Representation.
#define INDEX_INVALID
Invalid index - used when no index is known blazoned capitals INVALID speak volumes where ~0 does not...
Definition: dpo.h:47
static u8 * format_gbp_itf(u8 *s, va_list *args)
Definition: gbp_itf.c:492
u64 uword
Definition: types.h:112
gbp_itf_hdl_t gbp_itf_clone_and_lock(gbp_itf_hdl_t gh)
Definition: gbp_itf.c:273
#define FOR_EACH_FIB_IP_PROTOCOL(_item)
Definition: fib_types.h:69
static const gbp_itf_hdl_t GBP_ITF_HDL_INVALID
Definition: gbp_itf.h:58
#define vec_foreach(var, vec)
Vector iterator.
gbp_itf_free_fn_t gi_free_fn
function to call when the interface is deleted.
Definition: gbp_itf.c:69
u32 * gi_users
Users of this interface - this is encoded in the user&#39;s handle.
Definition: gbp_itf.c:56
void ip6_sw_interface_enable_disable(u32 sw_if_index, u32 is_enable)
Definition: ip6_forward.c:240
enum gbp_ift_mode_t_ gbp_itf_mode_t
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
int vnet_feature_enable_disable(const char *arc_name, const char *node_name, u32 sw_if_index, int enable_disable, void *feature_config, u32 n_feature_config_bytes)
Definition: feature.c:303
static gbp_itf_t * gbp_itf_find(u32 sw_if_index)
Definition: gbp_itf.c:131