FD.io VPP  v20.01-48-g3e0dafb74
Vector Packet Processing
gbp_route_domain.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 
18 
19 #include <vnet/dpo/dvr_dpo.h>
20 #include <vnet/fib/fib_table.h>
21 
22 /**
23  * A fixed MAC address to use as the source MAC for packets L3 switched
24  * onto the routed uu-fwd interfaces.
25  * Magic values - origin lost to the mists of time...
26  */
27 /* *INDENT-OFF* */
28 const static mac_address_t GBP_ROUTED_SRC_MAC = {
29  .bytes = {
30  0x0, 0x22, 0xBD, 0xF8, 0x19, 0xFF,
31  }
32 };
33 
34 const static mac_address_t GBP_ROUTED_DST_MAC = {
35  .bytes = {
36  00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
37  }
38 };
39 /* *INDENT-ON* */
40 
41 /**
42  * Pool of GBP route_domains
43  */
45 
46 /**
47  * DB of route_domains
48  */
49 typedef struct gbp_route_domain_db_t
50 {
53 
56 
57 /**
58  * logger
59  */
61 
62 #define GBP_BD_DBG(...) \
63  vlib_log_debug (grd_logger, __VA_ARGS__);
64 
65 index_t
67 {
68  return (grd - gbp_route_domain_pool);
69 }
70 
73 {
74  return (pool_elt_at_index (gbp_route_domain_pool, i));
75 }
76 
77 static void
79 {
80  gbp_route_domain_t *grd;
81 
82  grd = gbp_route_domain_get (i);
83  grd->grd_locks++;
84 }
85 
86 index_t
88 {
89  uword *p;
90 
91  p = hash_get (gbp_route_domain_db.gbd_by_rd_id, rd_id);
92 
93  if (NULL != p)
94  return p[0];
95 
96  return (INDEX_INVALID);
97 }
98 
99 index_t
101 {
102  index_t grdi;
103 
104  grdi = gbp_route_domain_find (rd_id);
105 
106  if (INDEX_INVALID != grdi)
107  {
108  gbp_route_domain_lock (grdi);
109  }
110  return (grdi);
111 }
112 
113 static void
115 {
116  index_t grdi = grd - gbp_route_domain_pool;
117 
118  hash_set (gbp_route_domain_db.gbd_by_rd_id, grd->grd_id, grdi);
119 }
120 
121 static void
123 {
124  hash_unset (gbp_route_domain_db.gbd_by_rd_id, grd->grd_id);
125 }
126 
127 int
133 {
134  gbp_route_domain_t *grd;
135  index_t grdi;
136 
137  grdi = gbp_route_domain_find (rd_id);
138 
139  if (INDEX_INVALID == grdi)
140  {
141  fib_protocol_t fproto;
142 
143  pool_get_zero (gbp_route_domain_pool, grd);
144 
145  grd->grd_id = rd_id;
146  grd->grd_scope = scope;
151 
152  FOR_EACH_FIB_IP_PROTOCOL (fproto)
153  {
154  grd->grd_fib_index[fproto] =
156  grd->grd_table_id[fproto],
158 
159  if (~0 != grd->grd_uu_sw_if_index[fproto])
160  {
161  ethernet_header_t *eth;
162  u8 *rewrite;
163 
164  rewrite = NULL;
165  vec_validate (rewrite, sizeof (*eth) - 1);
166  eth = (ethernet_header_t *) rewrite;
167 
168  eth->type = clib_host_to_net_u16 ((fproto == FIB_PROTOCOL_IP4 ?
169  ETHERNET_TYPE_IP4 :
170  ETHERNET_TYPE_IP6));
171 
173  eth->src_address);
175  eth->dst_address);
176 
177  /*
178  * create an adjacency out of the uu-fwd interfaces that will
179  * be used when adding subnet routes.
180  */
181  grd->grd_adj[fproto] =
183  fib_proto_to_link (fproto),
185  grd->grd_uu_sw_if_index[fproto],
186  rewrite);
187  }
188  else
189  {
190  grd->grd_adj[fproto] = INDEX_INVALID;
191  }
192  }
193 
195  }
196  else
197  {
198  grd = gbp_route_domain_get (grdi);
199  }
200 
201  grd->grd_locks++;
202  GBP_BD_DBG ("add: %U", format_gbp_route_domain, grd);
203 
204  return (0);
205 }
206 
207 void
209 {
210  gbp_route_domain_t *grd;
211 
212  grd = gbp_route_domain_get (index);
213 
214  grd->grd_locks--;
215 
216  if (0 == grd->grd_locks)
217  {
218  fib_protocol_t fproto;
219 
220  GBP_BD_DBG ("destroy: %U", format_gbp_route_domain, grd);
221 
222  FOR_EACH_FIB_IP_PROTOCOL (fproto)
223  {
224  fib_table_unlock (grd->grd_fib_index[fproto], fproto, gbp_fib_source);
225  if (INDEX_INVALID != grd->grd_adj[fproto])
226  adj_unlock (grd->grd_adj[fproto]);
227  }
228 
230 
231  pool_put (gbp_route_domain_pool, grd);
232  }
233 }
234 
235 u32
237 {
238  gbp_route_domain_t *grd;
239 
240  grd = gbp_route_domain_get (grdi);
241 
242  return (grd->grd_id);
243 }
244 
247 {
248  gbp_route_domain_t *grd;
249 
250  grd = gbp_route_domain_get (grdi);
251 
252  return (grd->grd_scope);
253 }
254 
255 int
257 {
258  index_t grdi;
259 
260  GBP_BD_DBG ("del: %d", rd_id);
261  grdi = gbp_route_domain_find (rd_id);
262 
263  if (INDEX_INVALID != grdi)
264  {
266  gbp_route_domain_get (grdi));
268 
269  return (0);
270  }
271 
272  return (VNET_API_ERROR_NO_SUCH_ENTRY);
273 }
274 
275 const mac_address_t *
277 {
278  return (&GBP_ROUTED_SRC_MAC);
279 }
280 
281 const mac_address_t *
283 {
284  return (&GBP_ROUTED_DST_MAC);
285 }
286 
287 void
289 {
290  gbp_route_domain_t *gbpe;
291 
292  /* *INDENT-OFF* */
293  pool_foreach(gbpe, gbp_route_domain_pool,
294  {
295  if (!cb(gbpe, ctx))
296  break;
297  });
298  /* *INDENT-ON* */
299 }
300 
301 static clib_error_t *
303  unformat_input_t * input, vlib_cli_command_t * cmd)
304 {
305  vnet_main_t *vnm = vnet_get_main ();
306  u32 ip4_uu_sw_if_index = ~0;
307  u32 ip6_uu_sw_if_index = ~0;
308  u32 ip4_table_id = ~0;
309  u32 ip6_table_id = ~0;
310  u32 scope = ~0;
311  u32 rd_id = ~0;
312  u8 add = 1;
313 
315  {
316  if (unformat (input, "ip4-uu %U", unformat_vnet_sw_interface,
317  vnm, &ip4_uu_sw_if_index))
318  ;
319  else if (unformat (input, "ip6-uu %U", unformat_vnet_sw_interface,
320  vnm, &ip6_uu_sw_if_index))
321  ;
322  else if (unformat (input, "ip4-table-id %d", &ip4_table_id))
323  ;
324  else if (unformat (input, "ip6-table-id %d", &ip6_table_id))
325  ;
326  else if (unformat (input, "add"))
327  add = 1;
328  else if (unformat (input, "del"))
329  add = 0;
330  else if (unformat (input, "rd %d", &rd_id))
331  ;
332  else if (unformat (input, "scope %d", &scope))
333  ;
334  else
335  break;
336  }
337 
338  if (~0 == rd_id)
339  return clib_error_return (0, "RD-ID must be specified");
340 
341  if (add)
342  {
343  if (~0 == ip4_table_id)
344  return clib_error_return (0, "IP4 table-ID must be specified");
345  if (~0 == ip6_table_id)
346  return clib_error_return (0, "IP6 table-ID must be specified");
347 
348  gbp_route_domain_add_and_lock (rd_id, scope,
349  ip4_table_id,
350  ip6_table_id,
351  ip4_uu_sw_if_index, ip6_uu_sw_if_index);
352  }
353  else
354  gbp_route_domain_delete (rd_id);
355 
356  return (NULL);
357 }
358 
359 /*?
360  * Configure a GBP route-domain
361  *
362  * @cliexpar
363  * @cliexstart{gbp route-domain [del] rd <ID> ip4-table-id <ID> ip6-table-id <ID> [ip4-uu <interface>] [ip6-uu <interface>]}
364  * @cliexend
365  ?*/
366 /* *INDENT-OFF* */
367 VLIB_CLI_COMMAND (gbp_route_domain_cli_node, static) = {
368  .path = "gbp route-domain",
369  .short_help = "gbp route-domain [del] rd <ID> ip4-table-id <ID> ip6-table-id <ID> [ip4-uu <interface>] [ip6-uu <interface>]",
370  .function = gbp_route_domain_cli,
371 };
372 
373 u8 *
374 format_gbp_route_domain (u8 * s, va_list * args)
375 {
376  gbp_route_domain_t *grd = va_arg (*args, gbp_route_domain_t*);
377  vnet_main_t *vnm = vnet_get_main ();
378 
379  if (NULL != grd)
380  s = format (s, "[%d] rd:%d ip4-uu:%U ip6-uu:%U locks:%d",
381  grd - gbp_route_domain_pool,
382  grd->grd_id,
385  grd->grd_locks);
386  else
387  s = format (s, "NULL");
388 
389  return (s);
390 }
391 
392 static int
394 {
395  vlib_main_t *vm;
396 
397  vm = ctx;
399 
400  return (1);
401 }
402 
403 static clib_error_t *
405  unformat_input_t * input, vlib_cli_command_t * cmd)
406 {
407  vlib_cli_output (vm, "Route-Domains:");
409 
410  return (NULL);
411 }
412 
413 /*?
414  * Show Group Based Policy Route_Domains and derived information
415  *
416  * @cliexpar
417  * @cliexstart{show gbp route_domain}
418  * @cliexend
419  ?*/
420 /* *INDENT-OFF* */
421 VLIB_CLI_COMMAND (gbp_route_domain_show_node, static) = {
422  .path = "show gbp route-domain",
423  .short_help = "show gbp route-domain\n",
424  .function = gbp_route_domain_show,
425 };
426 /* *INDENT-ON* */
427 
428 static clib_error_t *
430 {
431  grd_logger = vlib_log_register_class ("gbp", "rd");
435 
436  return (NULL);
437 }
438 
440 
441 /*
442  * fd.io coding-style-patch-verification: ON
443  *
444  * Local Variables:
445  * eval: (c-set-style "gnu")
446  * End:
447  */
vlib_log_class_t vlib_log_register_class(char *class, char *subclass)
Definition: log.c:176
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:440
vlib_log_class_t grd_logger
logger
enum fib_source_t_ fib_source_t
The different sources that can create a route.
u32 grd_table_id[FIB_PROTOCOL_IP_MAX]
void gbp_route_domain_unlock(index_t index)
#define hash_set(h, key, value)
Definition: hash.h:255
If your adding a new source from a plugin pick one of these.
Definition: fib_source.h:201
u32 ip6_table_id
Definition: gbp.api:71
const mac_address_t * gbp_route_domain_get_local_mac(void)
#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:240
static void gbp_route_domain_db_remove(gbp_route_domain_t *grd)
#define GBP_BD_DBG(...)
#define NULL
Definition: clib.h:58
u8 src_address[6]
Definition: packet.h:56
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
int i
u32 rd_id
Definition: gbp.api:35
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
unformat_function_t unformat_vnet_sw_interface
static clib_error_t * gbp_route_domain_show(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
u32 grd_adj[FIB_PROTOCOL_IP_MAX]
adjacencies on the UU interfaces.
DB of route_domains.
index_t gbp_route_domain_index(const gbp_route_domain_t *grd)
adj_index_t adj_nbr_add_or_lock_w_rewrite(fib_protocol_t nh_proto, vnet_link_t link_type, const ip46_address_t *nh_addr, u32 sw_if_index, u8 *rewrite)
Add (and lock) a new or lock an existing neighbour adjacency.
Definition: adj_nbr.c:264
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.
vl_api_interface_index_t ip4_uu_sw_if_index
Definition: gbp.api:72
u32 vlib_log_class_t
Definition: vlib.h:51
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:498
static_always_inline void mac_address_to_bytes(const mac_address_t *mac, u8 *bytes)
Definition: mac_address.h:99
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
u8 dst_address[6]
Definition: packet.h:55
void gbp_route_domain_walk(gbp_route_domain_cb_t cb, void *ctx)
u16 gbp_scope_t
Definition: gbp_types.h:24
#define clib_error_return(e, args...)
Definition: error.h:99
void adj_unlock(adj_index_t adj_index)
Release a reference counting lock on the adjacency.
Definition: adj.c:324
unsigned int u32
Definition: types.h:88
gbp_scope_t gbp_route_domain_get_scope(index_t grdi)
fib_source_t fib_source_allocate(const char *name, fib_source_priority_t prio, fib_source_behaviour_t bh)
Definition: fib_source.c:118
#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:519
#define FIB_SOURCE_PRIORITY_HI
Some priority values that plugins might use when they are not to concerned where in the list they&#39;ll ...
Definition: fib_source.h:273
int gbp_route_domain_delete(u32 rd_id)
long ctx[MAX_CONNS]
Definition: main.c:144
struct _unformat_input_t unformat_input_t
static void gbp_route_domain_lock(index_t i)
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:287
u8 * format_gbp_route_domain(u8 *s, va_list *args)
struct gbp_route_domain_db_t gbp_route_domain_db_t
DB of route_domains.
u32 grd_uu_sw_if_index[FIB_PROTOCOL_IP_MAX]
The interfaces on which to send packets to unnknown EPs.
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:1291
vlib_main_t * vm
Definition: in2out_ed.c:1810
static int gbp_route_domain_show_one(gbp_route_domain_t *gb, void *ctx)
int gbp_route_domain_add_and_lock(u32 rd_id, gbp_scope_t scope, u32 ip4_table_id, u32 ip6_table_id, u32 ip4_uu_sw_if_index, u32 ip6_uu_sw_if_index)
static clib_error_t * gbp_route_domain_init(vlib_main_t *vm)
#define UNFORMAT_END_OF_INPUT
Definition: format.h:145
index_t gbp_route_domain_find(u32 rd_id)
u32 ip4_table_id
Definition: gbp.api:70
u32 grd_fib_index[FIB_PROTOCOL_IP_MAX]
static fib_source_t gbp_fib_source
static void gbp_route_domain_db_add(gbp_route_domain_t *grd)
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:152
gbp_route_domain_t * gbp_route_domain_get(index_t i)
vl_api_interface_index_t ip6_uu_sw_if_index
Definition: gbp.api:73
u32 fib_table_find_or_create_and_lock(fib_protocol_t proto, u32 table_id, fib_source_t src)
Get the index of the FIB for a Table-ID.
Definition: fib_table.c:1156
const mac_address_t * gbp_route_domain_get_remote_mac(void)
static clib_error_t * gbp_route_domain_cli(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
int(* gbp_route_domain_cb_t)(gbp_route_domain_t *gb, void *ctx)
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
u32 gbp_route_domain_get_rd_id(index_t grdi)
u64 uword
Definition: types.h:112
#define FOR_EACH_FIB_IP_PROTOCOL(_item)
Definition: fib_types.h:70
static gbp_route_domain_db_t gbp_route_domain_db
gbp_route_domain_t * gbp_route_domain_pool
Pool of GBP route_domains.
u32 grd_id
Route-domain ID.
vnet_link_t fib_proto_to_link(fib_protocol_t proto)
Convert from a protocol to a link type.
Definition: fib_types.c:294
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:689
vl_api_gbp_scope_t scope
Definition: gbp.api:74
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: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