FD.io VPP  v19.08.3-2-gbabecb413
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 #include <vnet/ip/ip_neighbor.h>
22 
23 /**
24  * A fixed MAC address to use as the source MAC for packets L3 switched
25  * onto the routed uu-fwd interfaces.
26  * Magic values - origin lost to the mists of time...
27  */
28 /* *INDENT-OFF* */
29 const static mac_address_t GBP_ROUTED_SRC_MAC = {
30  .bytes = {
31  0x0, 0x22, 0xBD, 0xF8, 0x19, 0xFF,
32  }
33 };
34 
35 const static mac_address_t GBP_ROUTED_DST_MAC = {
36  .bytes = {
37  00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
38  }
39 };
40 /* *INDENT-ON* */
41 
42 /**
43  * Pool of GBP route_domains
44  */
46 
47 /**
48  * DB of route_domains
49  */
50 typedef struct gbp_route_domain_db_t
51 {
54 
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],
225  fproto, FIB_SOURCE_PLUGIN_HI);
226  if (INDEX_INVALID != grd->grd_adj[fproto])
227  adj_unlock (grd->grd_adj[fproto]);
228  }
229 
231 
232  pool_put (gbp_route_domain_pool, grd);
233  }
234 }
235 
236 u32
238 {
239  gbp_route_domain_t *grd;
240 
241  grd = gbp_route_domain_get (grdi);
242 
243  return (grd->grd_id);
244 }
245 
248 {
249  gbp_route_domain_t *grd;
250 
251  grd = gbp_route_domain_get (grdi);
252 
253  return (grd->grd_scope);
254 }
255 
256 int
258 {
259  index_t grdi;
260 
261  GBP_BD_DBG ("del: %d", rd_id);
262  grdi = gbp_route_domain_find (rd_id);
263 
264  if (INDEX_INVALID != grdi)
265  {
267  gbp_route_domain_get (grdi));
269 
270  return (0);
271  }
272 
273  return (VNET_API_ERROR_NO_SUCH_ENTRY);
274 }
275 
276 const mac_address_t *
278 {
279  return (&GBP_ROUTED_SRC_MAC);
280 }
281 
282 const mac_address_t *
284 {
285  return (&GBP_ROUTED_DST_MAC);
286 }
287 
288 void
290 {
291  gbp_route_domain_t *gbpe;
292 
293  /* *INDENT-OFF* */
294  pool_foreach(gbpe, gbp_route_domain_pool,
295  {
296  if (!cb(gbpe, ctx))
297  break;
298  });
299  /* *INDENT-ON* */
300 }
301 
302 static clib_error_t *
304  unformat_input_t * input, vlib_cli_command_t * cmd)
305 {
306  vnet_main_t *vnm = vnet_get_main ();
307  u32 ip4_uu_sw_if_index = ~0;
308  u32 ip6_uu_sw_if_index = ~0;
309  u32 ip4_table_id = ~0;
310  u32 ip6_table_id = ~0;
311  u32 scope = ~0;
312  u32 rd_id = ~0;
313  u8 add = 1;
314 
316  {
317  if (unformat (input, "ip4-uu %U", unformat_vnet_sw_interface,
318  vnm, &ip4_uu_sw_if_index))
319  ;
320  else if (unformat (input, "ip6-uu %U", unformat_vnet_sw_interface,
321  vnm, &ip6_uu_sw_if_index))
322  ;
323  else if (unformat (input, "ip4-table-id %d", &ip4_table_id))
324  ;
325  else if (unformat (input, "ip6-table-id %d", &ip6_table_id))
326  ;
327  else if (unformat (input, "add"))
328  add = 1;
329  else if (unformat (input, "del"))
330  add = 0;
331  else if (unformat (input, "rd %d", &rd_id))
332  ;
333  else if (unformat (input, "scope %d", &scope))
334  ;
335  else
336  break;
337  }
338 
339  if (~0 == rd_id)
340  return clib_error_return (0, "RD-ID must be specified");
341 
342  if (add)
343  {
344  if (~0 == ip4_table_id)
345  return clib_error_return (0, "IP4 table-ID must be specified");
346  if (~0 == ip6_table_id)
347  return clib_error_return (0, "IP6 table-ID must be specified");
348 
349  gbp_route_domain_add_and_lock (rd_id, scope,
350  ip4_table_id,
351  ip6_table_id,
352  ip4_uu_sw_if_index, ip6_uu_sw_if_index);
353  }
354  else
355  gbp_route_domain_delete (rd_id);
356 
357  return (NULL);
358 }
359 
360 /*?
361  * Configure a GBP route-domain
362  *
363  * @cliexpar
364  * @cliexstart{gbp route-domain [del] rd <ID> ip4-table-id <ID> ip6-table-id <ID> [ip4-uu <interface>] [ip6-uu <interface>]}
365  * @cliexend
366  ?*/
367 /* *INDENT-OFF* */
368 VLIB_CLI_COMMAND (gbp_route_domain_cli_node, static) = {
369  .path = "gbp route-domain",
370  .short_help = "gbp route-domain [del] rd <ID> ip4-table-id <ID> ip6-table-id <ID> [ip4-uu <interface>] [ip6-uu <interface>]",
371  .function = gbp_route_domain_cli,
372 };
373 
374 u8 *
375 format_gbp_route_domain (u8 * s, va_list * args)
376 {
377  gbp_route_domain_t *grd = va_arg (*args, gbp_route_domain_t*);
378  vnet_main_t *vnm = vnet_get_main ();
379 
380  if (NULL != grd)
381  s = format (s, "[%d] rd:%d ip4-uu:%U ip6-uu:%U locks:%d",
382  grd - gbp_route_domain_pool,
383  grd->grd_id,
386  grd->grd_locks);
387  else
388  s = format (s, "NULL");
389 
390  return (s);
391 }
392 
393 static int
395 {
396  vlib_main_t *vm;
397 
398  vm = ctx;
400 
401  return (1);
402 }
403 
404 static clib_error_t *
406  unformat_input_t * input, vlib_cli_command_t * cmd)
407 {
408  vlib_cli_output (vm, "Route-Domains:");
410 
411  return (NULL);
412 }
413 
414 /*?
415  * Show Group Based Policy Route_Domains and derived information
416  *
417  * @cliexpar
418  * @cliexstart{show gbp route_domain}
419  * @cliexend
420  ?*/
421 /* *INDENT-OFF* */
422 VLIB_CLI_COMMAND (gbp_route_domain_show_node, static) = {
423  .path = "show gbp route-domain",
424  .short_help = "show gbp route-domain\n",
425  .function = gbp_route_domain_show,
426 };
427 /* *INDENT-ON* */
428 
429 static clib_error_t *
431 {
432  grd_logger = vlib_log_register_class ("gbp", "rd");
433 
434  return (NULL);
435 }
436 
438 
439 /*
440  * fd.io coding-style-patch-verification: ON
441  *
442  * Local Variables:
443  * eval: (c-set-style "gnu")
444  * End:
445  */
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:439
vlib_log_class_t grd_logger
logger
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
u32 ip6_table_id
Definition: gbp.api:70
const mac_address_t * gbp_route_domain_get_local_mac(void)
#define hash_unset(h, key)
Definition: hash.h:261
u32 ip6_uu_sw_if_index
Definition: gbp.api:72
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:239
static void gbp_route_domain_db_remove(gbp_route_domain_t *grd)
#define GBP_BD_DBG(...)
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:34
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:263
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 vlib_log_class_t
Definition: vlib.h:51
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:493
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)
A high priority source a plugin can use.
Definition: fib_entry.h:67
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:347
unsigned int u32
Definition: types.h:88
gbp_scope_t gbp_route_domain_get_scope(index_t grdi)
#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
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:286
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:1253
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
vlib_main_t * vm
Definition: buffer.c:323
index_t gbp_route_domain_find(u32 rd_id)
u32 ip4_table_id
Definition: gbp.api:69
u32 grd_fib_index[FIB_PROTOCOL_IP_MAX]
static void gbp_route_domain_db_add(gbp_route_domain_t *grd)
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:161
gbp_route_domain_t * gbp_route_domain_get(index_t i)
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:1139
const mac_address_t * gbp_route_domain_get_remote_mac(void)
u32 ip4_uu_sw_if_index
Definition: gbp.api:71
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:281
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:772
vl_api_gbp_scope_t scope
Definition: gbp.api:73
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