FD.io VPP  v21.10.1-2-g0a485f517
Vector Packet Processing
l3xc.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/l3xc/l3xc.h>
17 
18 #include <vlib/vlib.h>
19 #include <vnet/plugin/plugin.h>
20 #include <vnet/fib/fib_path_list.h>
21 
22 /**
23  * FIB node type the attachment is registered
24  */
26 
27 /**
28  * Pool of L3XC objects
29  */
31 
32 /**
33  * DB of L3XC objects
34  */
36 
37 index_t
39 {
40  if (vec_len (l3xc_db[fproto]) <= sw_if_index)
41  return ~0;
42 
43  return (l3xc_db[fproto][sw_if_index]);
44 }
45 
46 static void
48 {
50 
51  l3xc_db[fproto][sw_if_index] = l3xci;
52 }
53 
54 static void
56 {
58 
59  l3xc_db[fproto][sw_if_index] = ~0;
60 }
61 
62 static void
64 {
65  /*
66  * stack the DPO on the forwarding contributed by the path-list
67  */
68  dpo_id_t via_dpo = DPO_INVALID;
69 
71  (FIB_PROTOCOL_IP4 == l3xc->l3xc_proto ?
74  FIB_PATH_LIST_FWD_FLAG_NONE, &via_dpo);
75 
76  dpo_stack_from_node ((FIB_PROTOCOL_IP4 == l3xc->l3xc_proto ?
77  l3xc_ip4_node.index :
78  l3xc_ip6_node.index), &l3xc->l3xc_dpo, &via_dpo);
79  dpo_reset (&via_dpo);
80 }
81 
82 int
84 {
85  fib_protocol_t fproto;
86  l3xc_t *l3xc;
87  u32 l3xci;
88 
90 
91  l3xci = l3xc_find (sw_if_index, fproto);
92 
93  if (INDEX_INVALID == l3xci)
94  {
95  /*
96  * create a new x-connect
97  */
99 
100  l3xci = l3xc - l3xc_pool;
101  fib_node_init (&l3xc->l3xc_node, l3xc_fib_node_type);
102  l3xc->l3xc_sw_if_index = sw_if_index;
103  l3xc->l3xc_proto = fproto;
104 
105  /*
106  * create and become a child of a path list so we get poked when
107  * the forwarding changes and stack on the DPO the path-list provides
108  */
111  rpaths);
112  l3xc->l3xc_sibling = fib_path_list_child_add (l3xc->l3xc_pl,
114  l3xci);
115  l3xc_stack (l3xc);
116 
117  /*
118  * add this new policy to the DB and enable the feature on input interface
119  */
120  l3xc_db_add (sw_if_index, fproto, l3xci);
121 
123  "ip4-unicast" :
124  "ip6-unicast"),
125  (FIB_PROTOCOL_IP4 == fproto ?
126  "l3xc-input-ip4" :
127  "l3xc-input-ip6"),
128  l3xc->l3xc_sw_if_index,
129  1, &l3xci, sizeof (l3xci));
130  }
131  else
132  {
133  /*
134  * update an existing x-connect.
135  * - add the path to the path-list and swap our ancestry
136  */
137  l3xc = l3xc_get (l3xci);
138 
139  if (FIB_NODE_INDEX_INVALID != l3xc->l3xc_pl)
140  {
141  fib_path_list_child_remove (l3xc->l3xc_pl, l3xc->l3xc_sibling);
142  }
143 
146  rpaths);
147 
148  l3xc->l3xc_sibling = fib_path_list_child_add (l3xc->l3xc_pl,
150  l3xci);
151  }
152  return (0);
153 }
154 
155 int
157 {
158  fib_protocol_t fproto;
159  l3xc_t *l3xc;
160  u32 l3xci;
161 
163 
164  l3xci = l3xc_find (sw_if_index, fproto);
165 
166  if (INDEX_INVALID == l3xci)
167  {
168  /*
169  * no such policy
170  */
171  return (VNET_API_ERROR_INVALID_VALUE);
172  }
173  else
174  {
175  l3xc = l3xc_get (l3xci);
176 
178  "ip4-unicast" :
179  "ip6-unicast"),
180  (FIB_PROTOCOL_IP4 == fproto ?
181  "l3xc-input-ip4" :
182  "l3xc-input-ip6"),
183  l3xc->l3xc_sw_if_index,
184  0, &l3xci, sizeof (l3xci));
185 
186  fib_path_list_child_remove (l3xc->l3xc_pl, l3xc->l3xc_sibling);
187  dpo_reset (&l3xc->l3xc_dpo);
188 
189  l3xc_db_remove (l3xc->l3xc_sw_if_index, fproto);
191  }
192 
193  return (0);
194 }
195 
196 static clib_error_t *
198  unformat_input_t * main_input, vlib_cli_command_t * cmd)
199 {
200  unformat_input_t _line_input, *line_input = &_line_input;
201  fib_route_path_t *rpaths = NULL, rpath;
202  u32 sw_if_index, is_del, is_ip6;
203  dpo_proto_t payload_proto;
204  vnet_main_t *vnm;
205  int rv = 0;
206 
207  is_ip6 = is_del = 0;
208  sw_if_index = ~0;
209  vnm = vnet_get_main ();
210 
211  /* Get a line of input. */
212  if (!unformat_user (main_input, unformat_line_input, line_input))
213  return 0;
214 
215  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
216  {
217  if (unformat
218  (line_input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
219  ;
220  else if (unformat (line_input, "ip6"))
221  is_ip6 = 1;
222  else if (unformat (line_input, "ip4"))
223  is_ip6 = 0;
224  else if (unformat (line_input, "del"))
225  is_del = 1;
226  else if (unformat (line_input, "add"))
227  is_del = 0;
228  else if (unformat (line_input, "via %U",
229  unformat_fib_route_path, &rpath, &payload_proto))
230  vec_add1 (rpaths, rpath);
231  else
232  return (clib_error_return (0, "unknown input '%U'",
233  format_unformat_error, line_input));
234  }
235 
236  if (~0 == sw_if_index)
237  {
238  vlib_cli_output (vm, "Specify an input interface");
239  goto out;
240  }
241  if (vec_len (rpaths) == 0)
242  {
243  vlib_cli_output (vm, "Specify some paths");
244  goto out;
245  }
246 
247  if (!is_del)
248  {
249  rv = l3xc_update (sw_if_index, is_ip6, rpaths);
250 
251  if (rv)
252  {
253  vlib_cli_output (vm, "Failed: %d", rv);
254  goto out;
255  }
256  }
257  else
258  {
260  }
261 
262 out:
263  unformat_free (line_input);
264  return (NULL);
265 }
266 
267 /* *INDENT-OFF* */
268 /**
269  * Create an L3XC policy.
270  */
272  .path = "l3xc",
273  .function = l3xc_cmd,
274  .short_help = "l3xc [add|del] <INTERFACE> via ...",
275  .is_mp_safe = 1,
276 };
277 /* *INDENT-ON* */
278 
279 static u8 *
280 format_l3xc (u8 * s, va_list * args)
281 {
282  l3xc_t *l3xc = va_arg (*args, l3xc_t *);
283  vnet_main_t *vnm = vnet_get_main ();
284 
285  s = format (s, "l3xc:[%d]: %U",
287  vnm, l3xc->l3xc_sw_if_index);
288  s = format (s, "\n");
289  if (FIB_NODE_INDEX_INVALID == l3xc->l3xc_pl)
290  {
291  s = format (s, "no forwarding");
292  }
293  else
294  {
295  s = fib_path_list_format (l3xc->l3xc_pl, s);
296 
297  s = format (s, "\n %U", format_dpo_id, &l3xc->l3xc_dpo, 4);
298  }
299 
300  return (s);
301 }
302 
303 void
305 {
306  u32 l3xci;
307 
308  /* *INDENT-OFF* */
310  {
311  if (!cb(l3xci, ctx))
312  break;
313  }
314  /* *INDENT-ON* */
315 }
316 
317 static clib_error_t *
319  unformat_input_t * input, vlib_cli_command_t * cmd)
320 {
321  l3xc_t *l3xc;
322 
323  /* *INDENT-OFF* */
325  {
327  }
328  /* *INDENT-ON* */
329 
330  return (NULL);
331 }
332 
333 /* *INDENT-OFF* */
335  .path = "show l3xc",
336  .function = l3xc_show_cmd,
337  .short_help = "show l3xc",
338  .is_mp_safe = 1,
339 };
340 /* *INDENT-ON* */
341 
342 static fib_node_t *
344 {
345  l3xc_t *l3xc = l3xc_get (index);
346  return (&(l3xc->l3xc_node));
347 }
348 
349 static l3xc_t *
351 {
352  return ((l3xc_t *) (((char *) node) -
353  STRUCT_OFFSET_OF (l3xc_t, l3xc_node)));
354 }
355 
356 static void
358 {
359 }
360 
361 /*
362  * A back walk has reached this L3XC policy
363  */
366 {
368 
370 }
371 
372 /*
373  * The BIER fmask's graph node virtual function table
374  */
375 static const fib_node_vft_t l3xc_vft = {
377  .fnv_last_lock = l3xc_last_lock_gone,
378  .fnv_back_walk = l3xc_back_walk_notify,
379 };
380 
381 static clib_error_t *
383 {
385 
386  return (NULL);
387 }
388 
390 
391 /*
392  * fd.io coding-style-patch-verification: ON
393  *
394  * Local Variables:
395  * eval: (c-set-style "gnu")
396  * End:
397  */
vlib.h
l3xc_delete
int l3xc_delete(u32 sw_if_index, u8 is_ip6)
Delete an L3XC.
Definition: l3xc.c:156
l3xc_vft
static const fib_node_vft_t l3xc_vft
Definition: l3xc.c:375
l3xc.h
DPO_INVALID
#define DPO_INVALID
An initialiser for DPOs declared on the stack.
Definition: dpo.h:204
unformat_user
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:989
l3xc_last_lock_gone
static void l3xc_last_lock_gone(fib_node_t *node)
Definition: l3xc.c:357
fib_node_back_walk_rc_t
enum fib_node_back_walk_rc_t_ fib_node_back_walk_rc_t
Return code from a back walk function.
pool_get_aligned_zero
#define pool_get_aligned_zero(P, E, A)
Allocate an object E from a pool P with alignment A and zero it.
Definition: pool.h:252
dpo_proto_t
enum dpo_proto_t_ dpo_proto_t
Data path protocol.
l3xc_back_walk_notify
static fib_node_back_walk_rc_t l3xc_back_walk_notify(fib_node_t *node, fib_node_back_walk_ctx_t *ctx)
Definition: l3xc.c:365
unformat_line_input
unformat_function_t unformat_line_input
Definition: format.h:275
fib_path_list_format
u8 * fib_path_list_format(fib_node_index_t path_list_index, u8 *s)
Definition: fib_path_list.c:165
node
vlib_main_t vlib_node_runtime_t * node
Definition: nat44_ei.c:3047
fib_node_vft_t_
A FIB graph nodes virtual function table.
Definition: fib_node.h:288
clib_error_return
#define clib_error_return(e, args...)
Definition: error.h:99
vlib_cli_command_t::path
char * path
Definition: cli.h:96
FIB_NODE_INDEX_INVALID
#define FIB_NODE_INDEX_INVALID
Definition: fib_types.h:30
pool_put
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:305
vm
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
unformat_input_t
struct _unformat_input_t unformat_input_t
l3xc_show_cmd_node
static vlib_cli_command_t l3xc_show_cmd_node
(constructor) VLIB_CLI_COMMAND (l3xc_show_cmd_node)
Definition: l3xc.c:334
fib_node_type_t
enum fib_node_type_t_ fib_node_type_t
The types of nodes in a FIB graph.
l3xc_walk_cb_t
int(* l3xc_walk_cb_t)(index_t l3xci, void *ctx)
Callback function invoked during a walk of all policies.
Definition: l3xc.h:86
l3xc_cmd_node
static vlib_cli_command_t l3xc_cmd_node
Create an L3XC policy.
Definition: l3xc.c:271
unformat
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
FIB_FORW_CHAIN_TYPE_UNICAST_IP4
@ FIB_FORW_CHAIN_TYPE_UNICAST_IP4
Contribute an object that is to be used to forward IP4 packets.
Definition: fib_types.h:108
STRUCT_OFFSET_OF
#define STRUCT_OFFSET_OF(t, f)
Definition: clib.h:73
pool_foreach
#define pool_foreach(VAR, POOL)
Iterate through pool.
Definition: pool.h:534
vec_len
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
Definition: vec_bootstrap.h:142
unformat_free
static void unformat_free(unformat_input_t *i)
Definition: format.h:155
l3xc_fib_node_type
fib_node_type_t l3xc_fib_node_type
FIB node type the attachment is registered.
Definition: l3xc.c:25
l3xc_ip6_node
vlib_node_registration_t l3xc_ip6_node
(constructor) VLIB_REGISTER_NODE (l3xc_ip6_node)
Definition: l3xc_node.c:219
vec_add1
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:606
l3xc_walk
void l3xc_walk(l3xc_walk_cb_t cb, void *ctx)
Walk/visit each of the L3XC policies.
Definition: l3xc.c:304
FIB_PROTOCOL_IP_MAX
#define FIB_PROTOCOL_IP_MAX
Definition outside of enum so it does not need to be included in non-defaulted switch statements.
Definition: fib_types.h:57
vnet_get_main
vnet_main_t * vnet_get_main(void)
Definition: pnat_test_stubs.h:56
l3xc_pool
l3xc_t * l3xc_pool
Pool of L3XC objects.
Definition: l3xc.c:30
FIB_PATH_LIST_FLAG_SHARED
@ FIB_PATH_LIST_FLAG_SHARED
Definition: fib_path_list.h:81
unformat_check_input
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:163
index_t
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:43
fib_node_index_t
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:29
l3xc_db_remove
static void l3xc_db_remove(u32 sw_if_index, fib_protocol_t fproto)
Definition: l3xc.c:55
format_unformat_error
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
l3xc_get
static_always_inline l3xc_t * l3xc_get(u32 index)
Definition: l3xc.h:104
VLIB_CLI_COMMAND
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:163
dpo_stack_from_node
void dpo_stack_from_node(u32 child_node_index, dpo_id_t *dpo, const dpo_id_t *parent)
Stack one DPO object on another, and thus establish a child parent relationship.
Definition: dpo.c:550
fib_protocol_t
enum fib_protocol_t_ fib_protocol_t
Protocol Type.
fib_path_list_child_add
u32 fib_path_list_child_add(fib_node_index_t path_list_index, fib_node_type_t child_type, fib_node_index_t child_index)
Definition: fib_path_list.c:1296
fib_path_list_contribute_forwarding
void fib_path_list_contribute_forwarding(fib_node_index_t path_list_index, fib_forward_chain_type_t fct, fib_path_list_fwd_flags_t flags, dpo_id_t *dpo)
Definition: fib_path_list.c:1211
FIB_PROTOCOL_IP4
@ FIB_PROTOCOL_IP4
Definition: fib_types.h:36
CLIB_CACHE_LINE_BYTES
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:58
FIB_NODE_BACK_WALK_CONTINUE
@ FIB_NODE_BACK_WALK_CONTINUE
Definition: fib_node.h:259
vlib_cli_output
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:716
format_dpo_id
u8 * format_dpo_id(u8 *s, va_list *args)
Format a DPO_id_t oject.
Definition: dpo.c:150
l3xc_get_from_node
static l3xc_t * l3xc_get_from_node(fib_node_t *node)
Definition: l3xc.c:350
plugin.h
is_ip6
bool is_ip6
Definition: ip.api:43
l3xc
typedef l3xc
A description of an L3XC policy.
Definition: l3xc.api:55
vnet_main_t
Definition: vnet.h:76
index
u32 index
Definition: flow_types.api:221
fib_path_list.h
pool_foreach_index
#define pool_foreach_index(i, v)
Definition: pool.h:572
format_vnet_sw_if_index_name
format_function_t format_vnet_sw_if_index_name
Definition: interface_funcs.h:458
unformat_vnet_sw_interface
unformat_function_t unformat_vnet_sw_interface
Definition: interface_funcs.h:462
format
description fragment has unexpected format
Definition: map.api:433
l3xc_update
int l3xc_update(u32 sw_if_index, u8 is_ip6, const fib_route_path_t *rpaths)
Create or update an L3XC Policy.
Definition: l3xc.c:83
vec_validate_init_empty
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header,...
Definition: vec.h:570
u32
unsigned int u32
Definition: types.h:88
VLIB_INIT_FUNCTION
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:172
l3xc_get_node
static fib_node_t * l3xc_get_node(fib_node_index_t index)
Definition: l3xc.c:343
FIB_PROTOCOL_IP6
@ FIB_PROTOCOL_IP6
Definition: fib_types.h:37
fib_route_path_t_
A representation of a path as described by a route producer.
Definition: fib_types.h:500
ctx
long ctx[MAX_CONNS]
Definition: main.c:144
format_l3xc
static u8 * format_l3xc(u8 *s, va_list *args)
Definition: l3xc.c:280
l3xc_ip4_node
vlib_node_registration_t l3xc_ip4_node
(constructor) VLIB_REGISTER_NODE (l3xc_ip4_node)
Definition: l3xc_node.c:203
fib_path_list_child_remove
void fib_path_list_child_remove(fib_node_index_t path_list_index, u32 si)
Definition: fib_path_list.c:1335
vnet_feature_enable_disable
int vnet_feature_enable_disable(const char *arc_name, const char *node_name, u32 sw_if_index, int enable_disable, void *feature_config, u32 n_feature_config_bytes)
Definition: pnat_test_stubs.h:50
fib_node_t_
An node in the FIB graph.
Definition: fib_node.h:301
l3xc_stack
static void l3xc_stack(l3xc_t *l3xc)
Definition: l3xc.c:63
vlib_main_t
Definition: main.h:102
fib_node_init
void fib_node_init(fib_node_t *node, fib_node_type_t type)
Definition: fib_node.c:185
u8
unsigned char u8
Definition: types.h:56
clib_error_t
Definition: clib_error.h:21
l3xc_cmd
static clib_error_t * l3xc_cmd(vlib_main_t *vm, unformat_input_t *main_input, vlib_cli_command_t *cmd)
Definition: l3xc.c:197
vlib_init_function_t
clib_error_t *() vlib_init_function_t(struct vlib_main_t *vm)
Definition: init.h:51
l3xc_db_add
static void l3xc_db_add(u32 sw_if_index, fib_protocol_t fproto, index_t l3xci)
Definition: l3xc.c:47
FIB_PATH_LIST_FWD_FLAG_NONE
@ FIB_PATH_LIST_FWD_FLAG_NONE
Definition: fib_path_list.h:142
FIB_PATH_LIST_FLAG_NO_URPF
@ FIB_PATH_LIST_FLAG_NO_URPF
Definition: fib_path_list.h:88
l3xc_t_
Definition: l3xc.h:33
fib_node_back_walk_ctx_t_
Context passed between object during a back walk.
Definition: fib_node.h:214
fib_node_vft_t_::fnv_get
fib_node_get_t fnv_get
Definition: fib_node.h:289
dpo_id_t_
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:172
rv
int __clib_unused rv
Definition: application.c:491
FIB_FORW_CHAIN_TYPE_UNICAST_IP6
@ FIB_FORW_CHAIN_TYPE_UNICAST_IP6
Contribute an object that is to be used to forward IP6 packets.
Definition: fib_types.h:112
l3xc_find
index_t l3xc_find(u32 sw_if_index, fib_protocol_t fproto)
Find a L3 XC object from an interface and FIB protocol.
Definition: l3xc.c:38
l3xc_init
static clib_error_t * l3xc_init(vlib_main_t *vm)
Definition: l3xc.c:382
vlib_cli_command_t
Definition: cli.h:92
INDEX_INVALID
#define INDEX_INVALID
Invalid index - used when no index is known blazoned capitals INVALID speak volumes where ~0 does not...
Definition: dpo.h:49
l3xc_db
static u32 * l3xc_db[FIB_PROTOCOL_IP_MAX]
DB of L3XC objects.
Definition: l3xc.c:35
sw_if_index
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
fib_path_list_create
fib_node_index_t fib_path_list_create(fib_path_list_flags_t flags, const fib_route_path_t *rpaths)
Definition: fib_path_list.c:682
dpo_reset
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:234
fib_node_register_new_type
fib_node_type_t fib_node_register_new_type(const fib_node_vft_t *vft)
Create a new FIB node type and Register the function table for it.
Definition: fib_node.c:80
unformat_fib_route_path
uword unformat_fib_route_path(unformat_input_t *input, va_list *args)
Unformat a fib_route_path_t from CLI input.
Definition: fib_types.c:540
UNFORMAT_END_OF_INPUT
#define UNFORMAT_END_OF_INPUT
Definition: format.h:137
l3xc_show_cmd
static clib_error_t * l3xc_show_cmd(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: l3xc.c:318