FD.io VPP  v17.01.1-3-gc6833f8
Vector Packet Processing
sixrd.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 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 "sixrd.h"
17 #include <vnet/plugin/plugin.h>
18 
19 #include <vnet/fib/fib_table.h>
20 #include <vnet/fib/ip6_fib.h>
21 #include <vnet/adj/adj.h>
22 
23 /*
24  * This code supports the following sixrd modes:
25  *
26  * 32 EA bits (Complete IPv4 address is embedded):
27  * ea_bits_len = 32
28  * IPv4 suffix is embedded:
29  * ea_bits_len = < 32
30  * No embedded address bits (1:1 mode):
31  * ea_bits_len = 0
32  */
33 
34 int
36  u8 ip6_prefix_len,
37  ip4_address_t *ip4_prefix,
38  u8 ip4_prefix_len,
39  ip4_address_t *ip4_src,
40  u32 *sixrd_domain_index,
41  u16 mtu)
42 {
43  dpo_id_t dpo_v6 = DPO_INVALID, dpo_v4 = DPO_INVALID;
44  sixrd_main_t *mm = &sixrd_main;
45  fib_node_index_t fei;
46  sixrd_domain_t *d;
47 
48  /* Get domain index */
50  memset(d, 0, sizeof (*d));
51  *sixrd_domain_index = d - mm->domains;
52 
53  /* Init domain struct */
54  d->ip4_prefix.as_u32 = ip4_prefix->as_u32;
55  d->ip4_prefix_len = ip4_prefix_len;
56  d->ip6_prefix = *ip6_prefix;
57  d->ip6_prefix_len = ip6_prefix_len;
58  d->ip4_src = *ip4_src;
59  d->mtu = mtu;
60 
61  if (ip4_prefix_len < 32)
62  d->shift = 64 - ip6_prefix_len + (32 - ip4_prefix_len);
63 
64  /* Create IPv6 route/adjacency */
65  fib_prefix_t pfx6 = {
67  .fp_len = d->ip6_prefix_len,
68  .fp_addr = {
69  .ip6 = d->ip6_prefix,
70  },
71  };
73  *sixrd_domain_index,
74  &dpo_v6);
78  &dpo_v6);
79  dpo_reset (&dpo_v6);
80 
81  /*
82  * Multiple SIXRD domains may share same source IPv4 TEP
83  * In this case the route will exist and be SixRD sourced.
84  * Find the adj (if any) already contributed and modify it
85  */
86  fib_prefix_t pfx4 = {
88  .fp_len = 32,
89  .fp_addr = {
90  .ip4 = d->ip4_src,
91  },
92  };
93  fei = fib_table_lookup_exact_match(0, &pfx4);
94 
95  if (FIB_NODE_INDEX_INVALID != fei)
96  {
97  dpo_id_t dpo = DPO_INVALID;
98 
100  {
101  /*
102  * modify the existing adj to indicate it's shared
103  * skip to route add.
104  * It is locked to pair with the unlock below.
105  */
106  const dpo_id_t *sd_dpo;
107  sixrd_dpo_t *sd;
108 
110 
111  sd_dpo = load_balance_get_bucket(dpo.dpoi_index, 0);
112  sd = sixrd_dpo_get (sd_dpo->dpoi_index);
113 
114  sd->sd_domain = ~0;
115  dpo_copy (&dpo_v4, sd_dpo);
116  dpo_reset (&dpo);
117 
118  goto route_add;
119  }
120  }
121  /* first time addition of the route */
123  *sixrd_domain_index,
124  &dpo_v4);
125 
126 route_add:
127  /*
128  * Create ip4 route. This is a reference counted add. If the prefix
129  * already exists and is SixRD sourced, it is now SixRD source n+1 times
130  * and will need to be removed n+1 times.
131  */
135  &dpo_v4);
136  dpo_reset (&dpo_v4);
137 
138  return 0;
139 }
140 
141 /*
142  * sixrd_delete_domain
143  */
144 int
145 sixrd_delete_domain (u32 sixrd_domain_index)
146 {
147  sixrd_main_t *mm = &sixrd_main;
148  sixrd_domain_t *d;
149 
150  if (pool_is_free_index(mm->domains, sixrd_domain_index)) {
151  clib_warning("SIXRD domain delete: domain does not exist: %d",
152  sixrd_domain_index);
153  return -1;
154  }
155 
156  d = pool_elt_at_index(mm->domains, sixrd_domain_index);
157 
158  fib_prefix_t pfx = {
160  .fp_len = 32,
161  .fp_addr = {
162  .ip4 = d->ip4_src,
163  },
164  };
166 
167  fib_prefix_t pfx6 = {
169  .fp_len = d->ip6_prefix_len,
170  .fp_addr = {
171  .ip6 = d->ip6_prefix,
172  },
173  };
175 
176  pool_put(mm->domains, d);
177 
178  return 0;
179 }
180 
181 static clib_error_t *
183  unformat_input_t *input,
184  vlib_cli_command_t *cmd)
185 {
186  unformat_input_t _line_input, *line_input = &_line_input;
187  ip4_address_t ip4_prefix;
188  ip6_address_t ip6_prefix;
189  ip4_address_t ip4_src;
190  u32 ip6_prefix_len=0, ip4_prefix_len=0, sixrd_domain_index;
191  u32 num_m_args = 0;
192  /* Optional arguments */
193  u32 mtu = 0;
194 
195  /* Get a line of input. */
196  if (!unformat_user(input, unformat_line_input, line_input))
197  return 0;
198  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) {
199  if (unformat(line_input, "ip6-pfx %U/%d", unformat_ip6_address, &ip6_prefix, &ip6_prefix_len))
200  num_m_args++;
201  else if (unformat(line_input, "ip4-pfx %U/%d", unformat_ip4_address, &ip4_prefix, &ip4_prefix_len))
202  num_m_args++;
203  else if (unformat(line_input, "ip4-src %U", unformat_ip4_address, &ip4_src))
204  num_m_args++;
205  else if (unformat(line_input, "mtu %d", &mtu))
206  num_m_args++;
207  else
208  return clib_error_return(0, "unknown input `%U'",
209  format_unformat_error, input);
210  }
211  unformat_free(line_input);
212 
213  if (num_m_args < 3)
214  return clib_error_return(0, "mandatory argument(s) missing");
215 
216  sixrd_create_domain(&ip6_prefix, ip6_prefix_len, &ip4_prefix, ip4_prefix_len,
217  &ip4_src, &sixrd_domain_index, mtu);
218 
219  return 0;
220 }
221 
222 static clib_error_t *
224  unformat_input_t *input,
225  vlib_cli_command_t *cmd)
226 {
227  unformat_input_t _line_input, *line_input = &_line_input;
228  u32 num_m_args = 0;
229  u32 sixrd_domain_index;
230 
231  /* Get a line of input. */
232  if (! unformat_user(input, unformat_line_input, line_input))
233  return 0;
234 
235  while (unformat_check_input(line_input) != UNFORMAT_END_OF_INPUT) {
236  if (unformat(line_input, "index %d", &sixrd_domain_index))
237  num_m_args++;
238  else
239  return clib_error_return(0, "unknown input `%U'",
240  format_unformat_error, input);
241  }
242  unformat_free(line_input);
243 
244  if (num_m_args != 1)
245  return clib_error_return(0, "mandatory argument(s) missing");
246 
247  sixrd_delete_domain(sixrd_domain_index);
248 
249  return 0;
250 }
251 
252 static u8 *
253 format_sixrd_domain (u8 *s, va_list *args)
254 {
255  sixrd_domain_t *d = va_arg(*args, sixrd_domain_t *);
256  sixrd_main_t *mm = &sixrd_main;
257 
258  s = format(s,
259  "[%d] ip6-pfx %U/%d ip4-pfx %U/%d ip4-src %U mtu %d",
260  d - mm->domains,
263  format_ip4_address, &d->ip4_src, d->mtu);
264 
265  return s;
266 }
267 
268 static clib_error_t *
270 {
271  sixrd_main_t *mm = &sixrd_main;
272  sixrd_domain_t *d;
273 
274  if (pool_elts(mm->domains) == 0)
275  vlib_cli_output(vm, "No SIXRD domains are configured...");
276 
277  pool_foreach(d, mm->domains, ({vlib_cli_output(vm, "%U", format_sixrd_domain, d);}));
278 
279  return 0;
280 
281 }
282 
283 static clib_error_t *
285 {
286  sixrd_main_t *mm = &sixrd_main;
287  sixrd_domain_t *d;
288  int domains = 0, domaincount = 0;
289  if (pool_elts (mm->domains) == 0)
290  vlib_cli_output (vm, "No SIXRD domains are configured...");
291 
292  pool_foreach(d, mm->domains, ({
293  domains += sizeof(*d);
294  domaincount++;
295  }));
296 
297  vlib_cli_output(vm, "SIXRD domains structure: %d\n", sizeof (sixrd_domain_t));
298  vlib_cli_output(vm, "SIXRD domains: %d (%d bytes)\n", domaincount, domains);
299 
300  return 0;
301 }
302 
303 /*
304  * packet trace format function
305  */
306 u8 *
307 format_sixrd_trace (u8 *s, va_list *args)
308 {
309  CLIB_UNUSED(vlib_main_t *vm) = va_arg (*args, vlib_main_t *);
310  CLIB_UNUSED(vlib_node_t *node) = va_arg (*args, vlib_node_t *);
311  sixrd_trace_t *t = va_arg (*args, sixrd_trace_t *);
312  u32 sixrd_domain_index = t->sixrd_domain_index;
313 
314  s = format(s, "SIXRD domain index: %d", sixrd_domain_index);
315 
316  return s;
317 }
318 
319 VLIB_CLI_COMMAND(sixrd_add_domain_command, static) = {
320  .path = "sixrd add domain",
321  .short_help =
322  "sixrd add domain ip6-pfx <ip6-pfx> ip4-pfx <ip4-pfx> ip4-src <ip4-addr>",
323  .function = sixrd_add_domain_command_fn,
324 };
325 
326 VLIB_CLI_COMMAND(sixrd_del_command, static) = {
327  .path = "sixrd del domain",
328  .short_help =
329  "sixrd del domain index <domain>",
330  .function = sixrd_del_domain_command_fn,
331 };
332 
333 VLIB_CLI_COMMAND(show_sixrd_domain_command, static) = {
334  .path = "show sixrd domain",
335  .function = show_sixrd_domain_command_fn,
336 };
337 
338 VLIB_CLI_COMMAND(show_sixrd_stats_command, static) = {
339  .path = "show sixrd stats",
340  .function = show_sixrd_stats_command_fn,
341 };
342 
343 /*
344  * This routine exists to convince the vlib plugin framework that
345  * we haven't accidentally copied a random .dll into the plugin directory.
346  *
347  * Also collects global variable pointers passed from the vpp engine
348  */
349 clib_error_t *
351  int from_early_init)
352 {
353  clib_error_t * error = 0;
354  sixrd_main_t *mm = &sixrd_main;
355 
356  mm->vnet_main = vnet_get_main();
357  mm->vlib_main = vm;
358 
359  return error;
360 }
361 
363 {
365 
366  return (NULL);
367 }
368 
ip4_address_t ip4_src
Definition: sixrd.h:33
fib_protocol_t fp_proto
protocol type
Definition: fib_types.h:154
vlib_main_t * vlib_main
Definition: sixrd.h:48
#define CLIB_UNUSED(x)
Definition: clib.h:79
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:966
fib_node_index_t fib_table_lookup_exact_match(u32 fib_index, const fib_prefix_t *prefix)
Perfom an exact match in the non-forwarding table.
Definition: fib_table.c:95
void sixrd_dpo_create(dpo_proto_t dproto, u32 domain_index, dpo_id_t *dpo)
Definition: sixrd_dpo.c:47
format_function_t format_ip6_address
Definition: format.h:95
static clib_error_t * show_sixrd_stats_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: sixrd.c:284
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
#define NULL
Definition: clib.h:55
static u8 * format_sixrd_domain(u8 *s, va_list *args)
Definition: sixrd.c:253
void dpo_copy(dpo_id_t *dst, const dpo_id_t *src)
atomic copy a data-plane object.
Definition: dpo.c:221
static clib_error_t * sixrd_add_domain_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: sixrd.c:182
format_function_t format_ip4_address
Definition: format.h:79
SIXRD.
Definition: fib_entry.h:78
u8 ip4_prefix_len
Definition: sixrd.h:35
u32 sd_domain
the SIXRD domain index
Definition: sixrd_dpo.h:35
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:348
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
void fib_table_entry_special_remove(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source)
Remove a &#39;special&#39; entry from the FIB.
Definition: fib_table.c:399
vnet_main_t * vnet_main
Definition: sixrd.h:49
Aggregrate type for a prefix.
Definition: fib_types.h:145
static void unformat_free(unformat_input_t *i)
Definition: format.h:161
#define clib_warning(format, args...)
Definition: error.h:59
ip4_address_t ip4_prefix
Definition: sixrd.h:32
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:977
const int fib_entry_get_dpo_for_source(fib_node_index_t fib_entry_index, fib_source_t source, dpo_id_t *dpo)
unformat_function_t unformat_ip4_address
Definition: format.h:76
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:138
Definition: fib_entry.h:220
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:369
static clib_error_t * show_sixrd_domain_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: sixrd.c:269
clib_error_t * vlib_plugin_register(vlib_main_t *vm, vnet_plugin_handoff_t *h, int from_early_init)
Definition: sixrd.c:350
dpo_type_t dpoi_type
the type
Definition: dpo.h:142
static clib_error_t * sixrd_del_domain_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: sixrd.c:223
load-balancing over a choice of [un]equal cost paths
Definition: dpo.h:102
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:214
static sixrd_dpo_t * sixrd_dpo_get(index_t index)
Definition: sixrd_dpo.h:54
sixrd_main_t sixrd_main
Definition: sixrd.h:82
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:576
const dpo_id_t * load_balance_get_bucket(index_t lbi, u32 bucket)
Definition: load_balance.c:271
unformat_function_t unformat_ip6_address
Definition: format.h:94
#define pool_get_aligned(P, E, A)
Allocate an object E from a pool P (general version).
Definition: pool.h:169
int sixrd_delete_domain(u32 sixrd_domain_index)
Definition: sixrd.c:145
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:28
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:211
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
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:288
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
ip6_address_t ip6_prefix
Definition: sixrd.h:31
static clib_error_t * sixrd_init(vlib_main_t *vm)
Definition: sixrd.c:362
sixrd_domain_t * domains
Definition: sixrd.h:45
u32 sixrd_domain_index
Definition: sixrd.h:79
u8 * format_sixrd_trace(u8 *s, va_list *args)
Definition: sixrd.c:307
unsigned short u16
Definition: types.h:57
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:154
#define FIB_NODE_INDEX_INVALID
Definition: fib_types.h:29
unsigned char u8
Definition: types.h:56
int sixrd_create_domain(ip6_address_t *ip6_prefix, u8 ip6_prefix_len, ip4_address_t *ip4_prefix, u8 ip4_prefix_len, ip4_address_t *ip4_src, u32 *sixrd_domain_index, u16 mtu)
Definition: sixrd.c:35
#define DPO_INVALID
An initialiser for DPOs declared on the stack.
Definition: dpo.h:165
A representation of a 6RD DPO.
Definition: sixrd_dpo.h:25
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
u8 ip6_prefix_len
Definition: sixrd.h:34
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:418
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:191
#define clib_error_return(e, args...)
Definition: error.h:111
struct _unformat_input_t unformat_input_t
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
unformat_function_t unformat_line_input
Definition: format.h:281
void sixrd_dpo_module_init(void)
Definition: sixrd_dpo.c:129
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:109