FD.io VPP  v20.09-64-g4f7b92f0a
Vector Packet Processing
gbp_endpoint_group.c
Go to the documentation of this file.
1 /*
2  * gbp.h : Group Based Policy
3  *
4  * Copyright (c) 2018 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 
22 #include <plugins/gbp/gbp_itf.h>
23 
24 #include <vnet/dpo/dvr_dpo.h>
25 #include <vnet/fib/fib_table.h>
26 #include <vnet/l2/l2_input.h>
27 
28 /**
29  * Pool of GBP endpoint_groups
30  */
32 
33 /**
34  * DB of endpoint_groups
35  */
37 
38 /**
39  * Map sclass to EPG
40  */
42 
44 
45 #define GBP_EPG_DBG(...) \
46  vlib_log_debug (gg_logger, __VA_ARGS__);
47 
50 {
51  return (pool_elt_at_index (gbp_endpoint_group_pool, i));
52 }
53 
54 void
56 {
58 
59  if (INDEX_INVALID == ggi)
60  return;
61 
62  gg = gbp_endpoint_group_get (ggi);
63  gg->gg_locks++;
64 }
65 
66 index_t
68 {
69  uword *p;
70 
71  p = hash_get (gbp_endpoint_group_db.gg_hash_sclass, sclass);
72 
73  if (NULL != p)
74  return p[0];
75 
76  return (INDEX_INVALID);
77 }
78 
79 int
81  u16 sclass,
82  u32 bd_id,
83  u32 rd_id,
86 {
88  index_t ggi;
89 
90  ggi = gbp_endpoint_group_find (sclass);
91 
92  if (INDEX_INVALID == ggi)
93  {
94  fib_protocol_t fproto;
95  index_t gbi, grdi;
96 
97  gbi = gbp_bridge_domain_find_and_lock (bd_id);
98 
99  if (~0 == gbi)
100  return (VNET_API_ERROR_BD_NOT_MODIFIABLE);
101 
102  grdi = gbp_route_domain_find_and_lock (rd_id);
103 
104  if (~0 == grdi)
105  {
107  return (VNET_API_ERROR_NO_SUCH_FIB);
108  }
109 
110  pool_get_zero (gbp_endpoint_group_pool, gg);
111 
112  gg->gg_vnid = vnid;
113  gg->gg_rd = grdi;
114  gg->gg_gbd = gbi;
115 
118  gg->gg_locks = 1;
119  gg->gg_sclass = sclass;
120  gg->gg_retention = *retention;
121 
122  if (SCLASS_INVALID != gg->gg_sclass)
124 
125  /*
126  * an egress DVR dpo for internal subnets to use when sending
127  * on the uplink interface
128  */
129  if (~0 != gg->gg_uplink_sw_if_index)
130  {
131  FOR_EACH_FIB_IP_PROTOCOL (fproto)
132  {
133  dvr_dpo_add_or_lock (uplink_sw_if_index,
134  fib_proto_to_dpo (fproto),
135  &gg->gg_dpo[fproto]);
136  }
137 
138  /*
139  * Add the uplink to the BD
140  * packets direct from the uplink have had policy applied
141  */
142  gg->gg_uplink_itf =
144 
146  L2INPUT_FEAT_GBP_NULL_CLASSIFY);
147  }
148 
149  hash_set (gbp_endpoint_group_db.gg_hash_sclass,
150  gg->gg_sclass, gg - gbp_endpoint_group_pool);
151  }
152  else
153  {
154  gg = gbp_endpoint_group_get (ggi);
155  gg->gg_locks++;
156  }
157 
158  GBP_EPG_DBG ("add: %U", format_gbp_endpoint_group, gg);
159 
160  return (0);
161 }
162 
163 void
165 {
167 
168  if (INDEX_INVALID == ggi)
169  return;
170 
171  gg = gbp_endpoint_group_get (ggi);
172 
173  gg->gg_locks--;
174 
175  if (0 == gg->gg_locks)
176  {
177  fib_protocol_t fproto;
178 
179  gg = pool_elt_at_index (gbp_endpoint_group_pool, ggi);
180 
182 
183  FOR_EACH_FIB_IP_PROTOCOL (fproto)
184  {
185  dpo_reset (&gg->gg_dpo[fproto]);
186  }
189 
190  if (SCLASS_INVALID != gg->gg_sclass)
192  hash_unset (gbp_endpoint_group_db.gg_hash_sclass, gg->gg_sclass);
193 
194  pool_put (gbp_endpoint_group_pool, gg);
195  }
196 }
197 
198 int
200 {
201  index_t ggi;
202 
203  ggi = gbp_endpoint_group_find (sclass);
204 
205  if (INDEX_INVALID != ggi)
206  {
208  gbp_endpoint_group_get (ggi));
210 
211  return (0);
212  }
213 
214  return (VNET_API_ERROR_NO_SUCH_ENTRY);
215 }
216 
217 u32
219 {
220  const gbp_bridge_domain_t *gb;
221 
222  gb = gbp_bridge_domain_get (gg->gg_gbd);
223 
224  return (gb->gb_bd_id);
225 }
226 
227 index_t
229  fib_protocol_t fproto)
230 {
231  const gbp_route_domain_t *grd;
232 
233  grd = gbp_route_domain_get (gg->gg_rd);
234 
235  return (grd->grd_fib_index[fproto]);
236 }
237 
238 void
240 {
241  gbp_endpoint_group_t *gbpe;
242 
243  /* *INDENT-OFF* */
244  pool_foreach(gbpe, gbp_endpoint_group_pool,
245  {
246  if (!cb(gbpe, ctx))
247  break;
248  });
249  /* *INDENT-ON* */
250 }
251 
252 static clib_error_t *
254  unformat_input_t * input, vlib_cli_command_t * cmd)
255 {
257  vnid_t vnid = VNID_INVALID, sclass;
258  vnet_main_t *vnm = vnet_get_main ();
259  u32 uplink_sw_if_index = ~0;
260  u32 bd_id = ~0;
261  u32 rd_id = ~0;
262  u8 add = 1;
263 
265  {
266  if (unformat (input, "%U", unformat_vnet_sw_interface,
267  vnm, &uplink_sw_if_index))
268  ;
269  else if (unformat (input, "add"))
270  add = 1;
271  else if (unformat (input, "del"))
272  add = 0;
273  else if (unformat (input, "epg %d", &vnid))
274  ;
275  else if (unformat (input, "sclass %d", &sclass))
276  ;
277  else if (unformat (input, "bd %d", &bd_id))
278  ;
279  else if (unformat (input, "rd %d", &rd_id))
280  ;
281  else
282  break;
283  }
284 
285  if (VNID_INVALID == vnid)
286  return clib_error_return (0, "EPG-ID must be specified");
287 
288  if (add)
289  {
290  if (~0 == bd_id)
291  return clib_error_return (0, "Bridge-domain must be specified");
292  if (~0 == rd_id)
293  return clib_error_return (0, "route-domain must be specified");
294 
295  gbp_endpoint_group_add_and_lock (vnid, sclass, bd_id, rd_id,
296  uplink_sw_if_index, &retention);
297  }
298  else
300 
301  return (NULL);
302 }
303 
304 /*?
305  * Configure a GBP Endpoint Group
306  *
307  * @cliexpar
308  * @cliexstart{gbp endpoint-group [del] epg <ID> bd <ID> rd <ID> [sclass <ID>] [<interface>]}
309  * @cliexend
310  ?*/
311 /* *INDENT-OFF* */
312 VLIB_CLI_COMMAND (gbp_endpoint_group_cli_node, static) = {
313  .path = "gbp endpoint-group",
314  .short_help = "gbp endpoint-group [del] epg <ID> bd <ID> rd <ID> [sclass <ID>] [<interface>]",
315  .function = gbp_endpoint_group_cli,
316 };
317 
318 static u8 *
319 format_gbp_endpoint_retention (u8 * s, va_list * args)
320 {
321  gbp_endpoint_retention_t *rt = va_arg (*args, gbp_endpoint_retention_t*);
322 
323  s = format (s, "[remote-EP-timeout:%d]", rt->remote_ep_timeout);
324 
325  return (s);
326 }
327 
328 u8 *
329 format_gbp_endpoint_group (u8 * s, va_list * args)
330 {
331  gbp_endpoint_group_t *gg = va_arg (*args, gbp_endpoint_group_t*);
332 
333  if (NULL != gg)
334  s = format (s, "[%d] %d, sclass:%d bd:%d rd:%d uplink:%U retention:%U locks:%d",
335  gg - gbp_endpoint_group_pool,
336  gg->gg_vnid,
337  gg->gg_sclass,
338  gg->gg_gbd,
339  gg->gg_rd,
342  gg->gg_locks);
343  else
344  s = format (s, "NULL");
345 
346  return (s);
347 }
348 
349 static int
351 {
352  vlib_main_t *vm;
353 
354  vm = ctx;
356 
357  return (1);
358 }
359 
360 static clib_error_t *
362  unformat_input_t * input, vlib_cli_command_t * cmd)
363 {
364  vlib_cli_output (vm, "Endpoint-Groups:");
366 
367  return (NULL);
368 }
369 
370 
371 /*?
372  * Show Group Based Policy Endpoint_Groups and derived information
373  *
374  * @cliexpar
375  * @cliexstart{show gbp endpoint_group}
376  * @cliexend
377  ?*/
378 /* *INDENT-OFF* */
379 VLIB_CLI_COMMAND (gbp_endpoint_group_show_node, static) = {
380  .path = "show gbp endpoint-group",
381  .short_help = "show gbp endpoint-group\n",
382  .function = gbp_endpoint_group_show,
383 };
384 /* *INDENT-ON* */
385 
386 static clib_error_t *
388 {
389  gg_logger = vlib_log_register_class ("gbp", "epg");
390 
391  return (NULL);
392 }
393 
395 
396 /*
397  * fd.io coding-style-patch-verification: ON
398  *
399  * Local Variables:
400  * eval: (c-set-style "gnu")
401  * End:
402  */
vlib_log_class_t vlib_log_register_class(char *class, char *subclass)
Definition: log.c:209
EPG DB, key&#39;d on EGP-ID.
void gbp_route_domain_unlock(index_t index)
#define hash_set(h, key, value)
Definition: hash.h:255
u16 sclass_t
Definition: gbp_types.h:25
#define hash_unset(h, key)
Definition: hash.h:261
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:255
void gbp_itf_unlock(gbp_itf_hdl_t *gh)
Definition: gbp_itf.c:286
A bridge Domain Representation.
int gbp_endpoint_group_delete(sclass_t sclass)
u8 * format_gbp_endpoint_group(u8 *s, va_list *args)
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 rd_id
Definition: gbp.api:35
vlib_main_t * vm
Definition: in2out_ed.c:1582
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
unformat_function_t unformat_vnet_sw_interface
index_t gg_rd
route-domain/IP-table ID the EPG is in
Endpoint Retnetion Policy.
static gbp_bridge_domain_t * gbp_bridge_domain_get(index_t i)
vlib_log_class_t gg_logger
unsigned char u8
Definition: types.h:56
enum fib_protocol_t_ fib_protocol_t
Protocol Type.
void gbp_bridge_domain_unlock(index_t gbdi)
u32 vlib_log_class_t
Definition: vlib.h:51
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:513
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
gbp_endpoint_group_t * gbp_endpoint_group_get(index_t i)
#define clib_error_return(e, args...)
Definition: error.h:99
static u8 * format_gbp_endpoint_retention(u8 *s, va_list *args)
unsigned int u32
Definition: types.h:88
int(* gbp_endpoint_group_cb_t)(gbp_endpoint_group_t *gbpe, void *ctx)
#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:534
long ctx[MAX_CONNS]
Definition: main.c:144
u32 bd_id
Definition: gbp.api:188
struct _unformat_input_t unformat_input_t
unsigned short u16
Definition: types.h:57
int gbp_endpoint_group_add_and_lock(vnid_t vnid, u16 sclass, u32 bd_id, u32 rd_id, u32 uplink_sw_if_index, const gbp_endpoint_retention_t *retention)
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:302
u16 sclass
Definition: gbp.api:131
u32 remote_ep_timeout
Aging timeout for remote endpoints.
#define SCLASS_INVALID
Definition: gbp_types.h:26
u32 gb_bd_id
Bridge-domain ID.
gbp_endpoint_group_db_t gbp_endpoint_group_db
DB of endpoint_groups.
An Endpoint Group representation.
void dvr_dpo_add_or_lock(u32 sw_if_index, dpo_proto_t dproto, dpo_id_t *dpo)
Definition: dvr_dpo.c:91
void gbp_itf_hdl_reset(gbp_itf_hdl_t *gh)
Definition: gbp_itf.c:108
#define UNFORMAT_END_OF_INPUT
Definition: format.h:145
gbp_itf_hdl_t gbp_itf_l2_add_and_lock(u32 sw_if_index, index_t gbi)
Definition: gbp_itf.c:196
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
static clib_error_t * gbp_endpoint_group_show(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
vl_api_gbp_endpoint_retention_t retention
Definition: gbp.api:191
u32 grd_fib_index[FIB_PROTOCOL_IP_MAX]
void gbp_endpoint_group_lock(index_t ggi)
u32 gg_locks
Locks/references to this EPG.
u32 vnid_t
Definition: gbp_types.h:21
index_t gbp_bridge_domain_find_and_lock(u32 bd_id)
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:158
uword * gbp_epg_sclass_db
Map sclass to EPG.
gbp_route_domain_t * gbp_route_domain_get(index_t i)
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:696
static int gbp_endpoint_group_show_one(gbp_endpoint_group_t *gg, void *ctx)
u8 * format_gbp_itf_hdl(u8 *s, va_list *args)
Definition: gbp_itf.c:520
dpo_id_t gg_dpo[FIB_PROTOCOL_IP_MAX]
The DPO used in the L3 path for forwarding internal subnets.
void gbp_endpoint_group_unlock(index_t ggi)
#define GBP_EPG_DBG(...)
gbp_endpoint_retention_t gg_retention
EP retention policy.
dpo_proto_t fib_proto_to_dpo(fib_protocol_t fib_proto)
Definition: fib_types.c:324
static clib_error_t * gbp_endpoint_group_cli(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
static clib_error_t * gbp_endpoint_group_init(vlib_main_t *vm)
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.
u32 gg_uplink_sw_if_index
the uplink interface dedicated to the EPG
#define INDEX_INVALID
Invalid index - used when no index is known blazoned capitals INVALID speak volumes where ~0 does not...
Definition: dpo.h:47
vl_api_interface_index_t uplink_sw_if_index
Definition: gbp.api:190
u64 uword
Definition: types.h:112
#define FOR_EACH_FIB_IP_PROTOCOL(_item)
Definition: fib_types.h:70
index_t gbp_endpoint_group_find(sclass_t sclass)
u32 gbp_endpoint_group_get_bd_id(const gbp_endpoint_group_t *gg)
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:232
gbp_endpoint_group_t * gbp_endpoint_group_pool
Pool of GBP endpoint_groups.
index_t gbp_endpoint_group_get_fib_index(const gbp_endpoint_group_t *gg, fib_protocol_t fproto)
#define VNID_INVALID
Definition: gbp_types.h:22
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
index_t gbp_route_domain_find_and_lock(u32 rd_id)
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:171
index_t gg_gbd
Bridge-domain ID the EPG is in.
void gbp_endpoint_group_walk(gbp_endpoint_group_cb_t cb, void *ctx)