FD.io VPP  v19.01.3-6-g70449b9b9
Vector Packet Processing
gbp_subnet.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.h>
20 
21 #include <vnet/fib/fib_table.h>
22 #include <vnet/dpo/load_balance.h>
23 
24 /**
25  * a key for the DB
26  */
27 typedef struct gbp_subnet_key_t_
28 {
32 
33 /**
34  * Subnet
35  */
36 typedef struct gbp_subnet_t_
37 {
41 
42  union
43  {
44  struct
45  {
48  } gs_stitched_external;
49  struct
50  {
51  epg_id_t gs_epg;
52  } gs_l3_out;
53  };
54 
56 } gbp_subnet_t;
57 
58 /**
59  * A DB of the subnets; key={pfx,fib-index}
60  */
62 
63 /**
64  * pool of subnets
65  */
67 
68 static index_t
69 gbp_subnet_db_find (u32 fib_index, const fib_prefix_t * pfx)
70 {
71  gbp_subnet_key_t key = {
72  .gsk_pfx = *pfx,
73  .gsk_fib_index = fib_index,
74  };
75  uword *p;
76 
77  p = hash_get_mem (gbp_subnet_db, &key);
78 
79  if (NULL != p)
80  return p[0];
81 
82  return (INDEX_INVALID);
83 }
84 
85 static void
86 gbp_subnet_db_add (u32 fib_index, const fib_prefix_t * pfx, gbp_subnet_t * gs)
87 {
88  gbp_subnet_key_t *key;
89 
90  key = clib_mem_alloc (sizeof (*key));
91 
92  clib_memcpy (&(key->gsk_pfx), pfx, sizeof (*pfx));
93  key->gsk_fib_index = fib_index;
94 
95  hash_set_mem (gbp_subnet_db, key, (gs - gbp_subnet_pool));
96 
97  gs->gs_key = key;
98 }
99 
100 static void
102 {
104 
105  clib_mem_free (gs->gs_key);
106  gs->gs_key = NULL;
107 }
108 
109 
110 static int
112 {
113  dpo_id_t gfd = DPO_INVALID;
114  gbp_route_domain_t *grd;
115  fib_protocol_t fproto;
116 
117  fproto = gs->gs_key->gsk_pfx.fp_proto;
118  grd = gbp_route_domain_get (gs->gs_rd);
119 
121  &gs->gs_key->gsk_pfx,
124  fib_proto_to_dpo (fproto),
126  grd->grd_uu_sw_if_index
127  [fproto], ~0, 1, NULL,
129 
130  dpo_reset (&gfd);
131 
132  return (0);
133 }
134 
135 static int
137 {
138  dpo_id_t gfd = DPO_INVALID;
139 
141  &gfd);
142 
144  &gs->gs_key->gsk_pfx,
147  &gfd);
148 
149  dpo_reset (&gfd);
150 
151  return (0);
152 }
153 
154 static int
156 {
157  dpo_id_t gpd = DPO_INVALID;
158 
159  gs->gs_stitched_external.gs_epg = epg;
160  gs->gs_stitched_external.gs_sw_if_index = sw_if_index;
161 
163  gs->gs_stitched_external.gs_epg,
164  gs->gs_stitched_external.gs_sw_if_index, &gpd);
165 
167  &gs->gs_key->gsk_pfx,
171  &gpd);
172 
173  dpo_reset (&gpd);
174 
175  return (0);
176 }
177 
178 static int
180 {
181  dpo_id_t gpd = DPO_INVALID;
182 
183  gs->gs_l3_out.gs_epg = epg;
184 
186  gs->gs_l3_out.gs_epg, ~0, &gpd);
187 
189  &gs->gs_key->gsk_pfx,
192  &gpd);
193 
194  dpo_reset (&gpd);
195 
196  return (0);
197 }
198 
199 int
201 {
202  gbp_route_domain_t *grd;
203  index_t gsi, grdi;
204  gbp_subnet_t *gs;
205  u32 fib_index;
206 
207  grdi = gbp_route_domain_find (rd_id);
208 
209  if (~0 == grdi)
210  return (VNET_API_ERROR_NO_SUCH_FIB);
211 
212  grd = gbp_route_domain_get (grdi);
213  fib_index = grd->grd_fib_index[pfx->fp_proto];
214 
215  gsi = gbp_subnet_db_find (fib_index, pfx);
216 
217  if (INDEX_INVALID == gsi)
218  return (VNET_API_ERROR_NO_SUCH_ENTRY);
219 
220  gs = pool_elt_at_index (gbp_subnet_pool, gsi);
221 
222  if (GBP_SUBNET_L3_OUT == gs->gs_type)
223  fib_table_entry_delete (fib_index, pfx, FIB_SOURCE_SPECIAL);
224  else
226 
227  gbp_subnet_db_del (gs);
229 
230  pool_put (gbp_subnet_pool, gs);
231 
232  return (0);
233 }
234 
235 int
237  const fib_prefix_t * pfx,
239 {
240  gbp_route_domain_t *grd;
241  index_t grdi, gsi;
242  gbp_subnet_t *gs;
243  u32 fib_index;
244  int rv;
245 
246  grdi = gbp_route_domain_find_and_lock (rd_id);
247 
248  if (~0 == grdi)
249  return (VNET_API_ERROR_NO_SUCH_FIB);
250 
251  grd = gbp_route_domain_get (grdi);
252  fib_index = grd->grd_fib_index[pfx->fp_proto];
253 
254  gsi = gbp_subnet_db_find (fib_index, pfx);
255 
256  if (INDEX_INVALID != gsi)
257  return (VNET_API_ERROR_ENTRY_ALREADY_EXISTS);
258 
259  rv = -2;
260 
261  pool_get (gbp_subnet_pool, gs);
262 
263  gs->gs_type = type;
264  gs->gs_rd = grdi;
265  gbp_subnet_db_add (fib_index, pfx, gs);
266 
267  switch (type)
268  {
270  rv = gbp_subnet_internal_add (gs);
271  break;
273  rv = gbp_subnet_external_add (gs, sw_if_index, epg);
274  break;
276  rv = gbp_subnet_transport_add (gs);
277  break;
278  case GBP_SUBNET_L3_OUT:
279  rv = gbp_subnet_l3_out_add (gs, sw_if_index, epg);
280  break;
281  }
282 
283  return (rv);
284 }
285 
286 void
288 {
289  gbp_route_domain_t *grd;
290  gbp_subnet_t *gs;
292  epg_id_t epg;
293 
294  epg = EPG_INVALID;
295  sw_if_index = ~0;
296 
297  /* *INDENT-OFF* */
298  pool_foreach (gs, gbp_subnet_pool,
299  ({
300  grd = gbp_route_domain_get(gs->gs_rd);
301 
302  switch (gs->gs_type)
303  {
306  /* use defaults above */
307  break;
309  sw_if_index = gs->gs_stitched_external.gs_sw_if_index;
310  epg = gs->gs_stitched_external.gs_epg;
311  break;
312  case GBP_SUBNET_L3_OUT:
313  epg = gs->gs_l3_out.gs_epg;
314  break;
315  }
316 
317  if (WALK_STOP == cb (grd->grd_id, &gs->gs_key->gsk_pfx,
318  gs->gs_type, sw_if_index, epg, ctx))
319  break;
320  }));
321  /* *INDENT-ON* */
322 }
323 
325 {
329 
330 static u8 *
331 format_gbp_subnet_type (u8 * s, va_list * args)
332 {
333  gbp_subnet_type_t type = va_arg (*args, gbp_subnet_type_t);
334 
335  switch (type)
336  {
338  return (format (s, "stitched-internal"));
340  return (format (s, "stitched-external"));
342  return (format (s, "transport"));
343  case GBP_SUBNET_L3_OUT:
344  return (format (s, "l3-out"));
345  }
346 
347  return (format (s, "unknown"));
348 }
349 
350 u8 *
351 format_gbp_subnet (u8 * s, va_list * args)
352 {
353  index_t gsi = va_arg (*args, index_t);
355  gbp_subnet_t *gs;
356  u32 table_id;
357 
358  gs = pool_elt_at_index (gbp_subnet_pool, gsi);
359 
361  gs->gs_key->gsk_pfx.fp_proto);
362 
363  s = format (s, "[%d] tbl:%d %U %U", gsi, table_id,
366 
367  switch (gs->gs_type)
368  {
371  break;
373  s = format (s, " {epg:%d %U}", gs->gs_stitched_external.gs_epg,
375  vnet_get_main (), gs->gs_stitched_external.gs_sw_if_index);
376  break;
377  case GBP_SUBNET_L3_OUT:
378  s = format (s, " {epg:%d}", gs->gs_l3_out.gs_epg);
379  break;
380  }
381 
382  switch (flags)
383  {
385  {
386  s = format (s, "\n %U", format_fib_entry, gs->gs_fei,
388  }
390  break;
391  }
392  return (s);
393 }
394 
395 static clib_error_t *
397  unformat_input_t * input, vlib_cli_command_t * cmd)
398 {
399  u32 gsi;
400 
401  gsi = INDEX_INVALID;
402 
404  {
405  if (unformat (input, "%d", &gsi))
406  ;
407  else
408  break;
409  }
410 
411  if (INDEX_INVALID != gsi)
412  {
413  vlib_cli_output (vm, "%U", format_gbp_subnet, gsi,
415  }
416  else
417  {
418  /* *INDENT-OFF* */
419  pool_foreach_index(gsi, gbp_subnet_pool,
420  ({
421  vlib_cli_output (vm, "%U", format_gbp_subnet, gsi,
423  }));
424  /* *INDENT-ON* */
425  }
426 
427  return (NULL);
428 }
429 
430 /*?
431  * Show Group Based Policy Subnets
432  *
433  * @cliexpar
434  * @cliexstart{show gbp subnet}
435  * @cliexend
436  ?*/
437 /* *INDENT-OFF* */
438 VLIB_CLI_COMMAND (gbp_subnet_show_node, static) = {
439  .path = "show gbp subnet",
440  .short_help = "show gbp subnet\n",
441  .function = gbp_subnet_show,
442 };
443 /* *INDENT-ON* */
444 
445 static clib_error_t *
447 {
449  sizeof (gbp_subnet_key_t), sizeof (u32));
450 
451  return (NULL);
452 }
453 
455 
456 /*
457  * fd.io coding-style-patch-verification: ON
458  *
459  * Local Variables:
460  * eval: (c-set-style "gnu")
461  * End:
462  */
fib_protocol_t fp_proto
protocol type
Definition: fib_types.h:212
u8 * format_fib_entry(u8 *s, va_list *args)
Definition: fib_entry.c:139
a key for the DB
Definition: gbp_subnet.c:27
void gbp_subnet_walk(gbp_subnet_cb_t cb, void *ctx)
Definition: gbp_subnet.c:287
void gbp_route_domain_unlock(index_t index)
u32 flags
Definition: vhost_user.h:115
u16 epg_id_t
Definition: gbp_types.h:21
fib_prefix_t gsk_pfx
Definition: gbp_subnet.c:29
epg_id_t gs_epg
Definition: gbp_subnet.c:46
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
gbp_subnet_key_t * gs_key
Definition: gbp_subnet.c:38
static u8 * format_gbp_subnet_type(u8 *s, va_list *args)
Definition: gbp_subnet.c:331
#define FIB_ENTRY_FORMAT_DETAIL
Definition: fib_entry.h:517
Definition: fib_entry.h:286
struct gbp_subnet_t_::@428::@430 gs_stitched_external
#define NULL
Definition: clib.h:58
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
static void gbp_subnet_db_del(gbp_subnet_t *gs)
Definition: gbp_subnet.c:101
u32 rd_id
Definition: gbp.api:261
#define hash_set_mem(h, key, value)
Definition: hash.h:275
index_t gs_rd
Definition: gbp_subnet.c:40
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
static int gbp_subnet_transport_add(gbp_subnet_t *gs)
Definition: gbp_subnet.c:111
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:236
int gbp_subnet_del(u32 rd_id, const fib_prefix_t *pfx)
Definition: gbp_subnet.c:200
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.
#define clib_memcpy(d, s, n)
Definition: string.h:180
fib_node_index_t fib_table_entry_update_one_path(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)
Update the entry to have just one path.
Definition: fib_table.c:772
int gbp_subnet_add(u32 rd_id, const fib_prefix_t *pfx, gbp_subnet_type_t type, u32 sw_if_index, epg_id_t epg)
Definition: gbp_subnet.c:236
static clib_error_t * gbp_subnet_init(vlib_main_t *vm)
Definition: gbp_subnet.c:446
Definition: fib_entry.h:283
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:490
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:163
u32 sw_if_index
Definition: vxlan_gbp.api:37
static int gbp_subnet_internal_add(gbp_subnet_t *gs)
Definition: gbp_subnet.c:136
u8 * format_fib_prefix(u8 *s, va_list *args)
Definition: fib_types.c:177
A high priority source a plugin can use.
Definition: fib_entry.h:62
Aggregrate type for a prefix.
Definition: fib_types.h:203
static int gbp_subnet_l3_out_add(gbp_subnet_t *gs, u32 sw_if_index, epg_id_t epg)
Definition: gbp_subnet.c:179
enum gsb_subnet_show_flags_t_ gsb_subnet_show_flags_t
unsigned int u32
Definition: types.h:88
gbp_subnet_t * gbp_subnet_pool
pool of subnets
Definition: gbp_subnet.c:66
static index_t gbp_subnet_db_find(u32 fib_index, const fib_prefix_t *pfx)
Definition: gbp_subnet.c:69
Definition: fib_entry.h:275
u32 gs_sw_if_index
Definition: gbp_subnet.c:47
walk_rc_t(* gbp_subnet_cb_t)(u32 rd_id, const fib_prefix_t *pfx, gbp_subnet_type_t type, u32 sw_if_index, epg_id_t epg, void *ctx)
Definition: gbp_subnet.h:36
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:168
#define hash_create_mem(elts, key_bytes, value_bytes)
Definition: hash.h:661
Definition: fib_entry.h:279
gbp_subnet_type_t gs_type
Definition: gbp_subnet.c:39
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:511
#define hash_unset_mem(h, key)
Definition: hash.h:291
enum gbp_subnet_type_t_ gbp_subnet_type_t
long ctx[MAX_CONNS]
Definition: main.c:144
Subnet.
Definition: gbp_subnet.c:36
struct _unformat_input_t unformat_input_t
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:286
u32 grd_uu_sw_if_index[FIB_PROTOCOL_IP_MAX]
The interfaces on which to send packets to unnknown EPs.
uword * gbp_subnet_db
A DB of the subnets; key={pfx,fib-index}.
Definition: gbp_subnet.c:61
fib_node_index_t fib_table_entry_special_dpo_update(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags, const dpo_id_t *dpo)
Update a &#39;special&#39; entry to the FIB that links to the DPO passed A special entry is an entry that the...
Definition: fib_table.c:346
#define UNFORMAT_END_OF_INPUT
Definition: format.h:144
vlib_main_t * vm
Definition: buffer.c:301
void gbp_policy_dpo_add_or_lock(dpo_proto_t dproto, epg_id_t epg, u32 sw_if_index, dpo_id_t *dpo)
index_t gbp_route_domain_find(u32 rd_id)
void fib_table_entry_delete(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source)
Delete a FIB entry.
Definition: fib_table.c:853
u32 grd_fib_index[FIB_PROTOCOL_IP_MAX]
void gbp_fwd_dpo_add_or_lock(dpo_proto_t dproto, dpo_id_t *dpo)
Definition: gbp_fwd_dpo.c:86
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:30
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:155
fib_node_index_t fib_table_entry_special_dpo_add(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags, const dpo_id_t *dpo)
Add a &#39;special&#39; entry to the FIB that links to the DPO passed A special entry is an entry that the FI...
Definition: fib_table.c:307
fib_node_index_t gs_fei
Definition: gbp_subnet.c:55
gbp_route_domain_t * gbp_route_domain_get(index_t i)
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:1053
#define EPG_INVALID
Definition: gbp_types.h:22
static void clib_mem_free(void *p)
Definition: mem.h:205
u8 * format_gbp_subnet(u8 *s, va_list *args)
Definition: gbp_subnet.c:351
dpo_proto_t fib_proto_to_dpo(fib_protocol_t fib_proto)
Definition: fib_types.c:237
struct gbp_subnet_t_::@428::@431 gs_l3_out
static void * clib_mem_alloc(uword size)
Definition: mem.h:132
struct gbp_subnet_t_ gbp_subnet_t
Subnet.
struct gbp_subnet_key_t_ gbp_subnet_key_t
a key for the DB
gsb_subnet_show_flags_t_
Definition: gbp_subnet.c:324
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
u64 uword
Definition: types.h:112
static clib_error_t * gbp_subnet_show(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: gbp_subnet.c:396
#define DPO_INVALID
An initialiser for DPOs declared on the stack.
Definition: dpo.h:195
Special sources.
Definition: fib_entry.h:40
#define hash_get_mem(h, key)
Definition: hash.h:269
static void gbp_subnet_db_add(u32 fib_index, const fib_prefix_t *pfx, gbp_subnet_t *gs)
Definition: gbp_subnet.c:86
u32 grd_id
Route-domain ID.
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:231
static int gbp_subnet_external_add(gbp_subnet_t *gs, u32 sw_if_index, epg_id_t epg)
Definition: gbp_subnet.c:155
#define pool_foreach_index(i, v, body)
Iterate pool by index.
Definition: pool.h:535
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:762
const ip46_address_t ADJ_BCAST_ADDR
The special broadcast address (to construct a broadcast adjacency.
Definition: adj.c:41
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
index_t gbp_route_domain_find_and_lock(u32 rd_id)
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:170