FD.io VPP  v19.01.3-6-g70449b9b9
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
132 {
133  gbp_route_domain_t *grd;
134  index_t grdi;
135 
136  grdi = gbp_route_domain_find (rd_id);
137 
138  if (INDEX_INVALID == grdi)
139  {
140  fib_protocol_t fproto;
141 
142  pool_get_zero (gbp_route_domain_pool, grd);
143 
144  grd->grd_id = rd_id;
149 
150  FOR_EACH_FIB_IP_PROTOCOL (fproto)
151  {
152  grd->grd_fib_index[fproto] =
154  grd->grd_table_id[fproto],
156 
157  if (~0 != grd->grd_uu_sw_if_index[fproto])
158  {
159  ethernet_header_t *eth;
160  u8 *rewrite;
161 
162  rewrite = NULL;
163  vec_validate (rewrite, sizeof (*eth) - 1);
164  eth = (ethernet_header_t *) rewrite;
165 
166  eth->type = clib_host_to_net_u16 ((fproto == FIB_PROTOCOL_IP4 ?
167  ETHERNET_TYPE_IP4 :
168  ETHERNET_TYPE_IP6));
169 
171  eth->src_address);
173  eth->src_address);
174 
175  /*
176  * create an adjacency out of the uu-fwd interfaces that will
177  * be used when adding subnet routes.
178  */
179  grd->grd_adj[fproto] =
181  fib_proto_to_link (fproto),
183  grd->grd_uu_sw_if_index[fproto],
184  rewrite);
185  }
186  else
187  {
188  grd->grd_adj[fproto] = INDEX_INVALID;
189  }
190  }
191 
193  }
194  else
195  {
196  grd = gbp_route_domain_get (grdi);
197  }
198 
199  grd->grd_locks++;
200  GBP_BD_DBG ("add: %U", format_gbp_route_domain, grd);
201 
202  return (0);
203 }
204 
205 void
207 {
208  gbp_route_domain_t *grd;
209 
210  grd = gbp_route_domain_get (index);
211 
212  grd->grd_locks--;
213 
214  if (0 == grd->grd_locks)
215  {
216  fib_protocol_t fproto;
217 
218  GBP_BD_DBG ("destroy: %U", format_gbp_route_domain, grd);
219 
220  FOR_EACH_FIB_IP_PROTOCOL (fproto)
221  {
222  fib_table_unlock (grd->grd_fib_index[fproto],
223  fproto, FIB_SOURCE_PLUGIN_HI);
224  if (INDEX_INVALID != grd->grd_adj[fproto])
225  adj_unlock (grd->grd_adj[fproto]);
226  }
227 
229 
230  pool_put (gbp_route_domain_pool, grd);
231  }
232 }
233 
234 u32
236 {
237  gbp_route_domain_t *grd;
238 
239  grd = gbp_route_domain_get (grdi);
240 
241  return (grd->grd_id);
242 }
243 
244 int
246 {
247  index_t grdi;
248 
249  GBP_BD_DBG ("del: %d", rd_id);
250  grdi = gbp_route_domain_find (rd_id);
251 
252  if (INDEX_INVALID != grdi)
253  {
255  gbp_route_domain_get (grdi));
257 
258  return (0);
259  }
260 
261  return (VNET_API_ERROR_NO_SUCH_ENTRY);
262 }
263 
264 const mac_address_t *
266 {
267  return (&GBP_ROUTED_SRC_MAC);
268 }
269 
270 const mac_address_t *
272 {
273  return (&GBP_ROUTED_DST_MAC);
274 }
275 
276 void
278 {
279  gbp_route_domain_t *gbpe;
280 
281  /* *INDENT-OFF* */
282  pool_foreach(gbpe, gbp_route_domain_pool,
283  {
284  if (!cb(gbpe, ctx))
285  break;
286  });
287  /* *INDENT-ON* */
288 }
289 
290 static clib_error_t *
292  unformat_input_t * input, vlib_cli_command_t * cmd)
293 {
294  vnet_main_t *vnm = vnet_get_main ();
295  u32 ip4_uu_sw_if_index = ~0;
296  u32 ip6_uu_sw_if_index = ~0;
297  u32 ip4_table_id = ~0;
298  u32 ip6_table_id = ~0;
299  u32 rd_id = ~0;
300  u8 add = 1;
301 
303  {
304  if (unformat (input, "ip4-uu %U", unformat_vnet_sw_interface,
305  vnm, &ip4_uu_sw_if_index))
306  ;
307  else if (unformat (input, "ip6-uu %U", unformat_vnet_sw_interface,
308  vnm, &ip6_uu_sw_if_index))
309  ;
310  else if (unformat (input, "ip4-table-id %d", &ip4_table_id))
311  ;
312  else if (unformat (input, "ip6-table-id %d", &ip6_table_id))
313  ;
314  else if (unformat (input, "add"))
315  add = 1;
316  else if (unformat (input, "del"))
317  add = 0;
318  else if (unformat (input, "rd %d", &rd_id))
319  ;
320  else
321  break;
322  }
323 
324  if (~0 == rd_id)
325  return clib_error_return (0, "RD-ID must be specified");
326 
327  if (add)
328  {
329  if (~0 == ip4_table_id)
330  return clib_error_return (0, "IP4 table-ID must be specified");
331  if (~0 == ip6_table_id)
332  return clib_error_return (0, "IP6 table-ID must be specified");
333 
334  gbp_route_domain_add_and_lock (rd_id, ip4_table_id,
335  ip6_table_id,
336  ip4_uu_sw_if_index, ip6_uu_sw_if_index);
337  }
338  else
339  gbp_route_domain_delete (rd_id);
340 
341  return (NULL);
342 }
343 
344 /*?
345  * Configure a GBP route-domain
346  *
347  * @cliexpar
348  * @cliexstart{set gbp route-domain [del] bd <ID> bvi <interface> uu-flood <interface>}
349  * @cliexend
350  ?*/
351 /* *INDENT-OFF* */
352 VLIB_CLI_COMMAND (gbp_route_domain_cli_node, static) = {
353  .path = "gbp route-domain",
354  .short_help = "gbp route-domain [del] epg bd <ID> bvi <interface> uu-flood <interface>",
355  .function = gbp_route_domain_cli,
356 };
357 
358 u8 *
359 format_gbp_route_domain (u8 * s, va_list * args)
360 {
361  gbp_route_domain_t *grd = va_arg (*args, gbp_route_domain_t*);
362  vnet_main_t *vnm = vnet_get_main ();
363 
364  if (NULL != grd)
365  s = format (s, "[%d] rd:%d ip4-uu:%U ip6-uu:%U locks:%d",
366  grd - gbp_route_domain_pool,
367  grd->grd_id,
370  grd->grd_locks);
371  else
372  s = format (s, "NULL");
373 
374  return (s);
375 }
376 
377 static int
379 {
380  vlib_main_t *vm;
381 
382  vm = ctx;
384 
385  return (1);
386 }
387 
388 static clib_error_t *
390  unformat_input_t * input, vlib_cli_command_t * cmd)
391 {
392  vlib_cli_output (vm, "Route-Domains:");
394 
395  return (NULL);
396 }
397 
398 /*?
399  * Show Group Based Policy Route_Domains and derived information
400  *
401  * @cliexpar
402  * @cliexstart{show gbp route_domain}
403  * @cliexend
404  ?*/
405 /* *INDENT-OFF* */
406 VLIB_CLI_COMMAND (gbp_route_domain_show_node, static) = {
407  .path = "show gbp route-domain",
408  .short_help = "show gbp route-domain\n",
409  .function = gbp_route_domain_show,
410 };
411 /* *INDENT-ON* */
412 
413 static clib_error_t *
415 {
416  grd_logger = vlib_log_register_class ("gbp", "rd");
417 
418  return (NULL);
419 }
420 
422 
423 /*
424  * fd.io coding-style-patch-verification: ON
425  *
426  * Local Variables:
427  * eval: (c-set-style "gnu")
428  * End:
429  */
vlib_log_class_t vlib_log_register_class(char *class, char *subclass)
Definition: log.c:227
#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)
u32 vlib_log_class_t
Definition: log.h:21
#define hash_set(h, key, value)
Definition: hash.h:255
u32 ip6_table_id
Definition: gbp.api:63
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:65
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
#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(...)
#define NULL
Definition: clib.h:58
int gbp_route_domain_add_and_lock(u32 rd_id, u32 ip4_table_id, u32 ip6_table_id, u32 ip4_uu_sw_if_index, u32 ip6_uu_sw_if_index)
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:261
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
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.
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:490
static_always_inline void mac_address_to_bytes(const mac_address_t *mac, u8 *bytes)
Definition: mac_address.h:47
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:163
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:62
#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:318
unsigned int u32
Definition: types.h:88
#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:511
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:1237
static int gbp_route_domain_show_one(gbp_route_domain_t *gb, void *ctx)
static clib_error_t * gbp_route_domain_init(vlib_main_t *vm)
#define UNFORMAT_END_OF_INPUT
Definition: format.h:144
vlib_main_t * vm
Definition: buffer.c:301
index_t gbp_route_domain_find(u32 rd_id)
u32 ip4_table_id
Definition: gbp.api:62
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:155
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:1123
const mac_address_t * gbp_route_domain_get_remote_mac(void)
u32 ip4_uu_sw_if_index
Definition: gbp.api:64
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:271
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