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