FD.io VPP  v21.06-3-gbb25fbf28
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 
188  l3xc_db_remove (l3xc->l3xc_sw_if_index, fproto);
190  }
191 
192  return (0);
193 }
194 
195 static clib_error_t *
197  unformat_input_t * main_input, vlib_cli_command_t * cmd)
198 {
199  unformat_input_t _line_input, *line_input = &_line_input;
200  fib_route_path_t *rpaths = NULL, rpath;
201  u32 sw_if_index, is_del, is_ip6;
202  dpo_proto_t payload_proto;
203  vnet_main_t *vnm;
204  int rv = 0;
205 
206  is_ip6 = is_del = 0;
207  sw_if_index = ~0;
208  vnm = vnet_get_main ();
209 
210  /* Get a line of input. */
211  if (!unformat_user (main_input, unformat_line_input, line_input))
212  return 0;
213 
214  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
215  {
216  if (unformat
217  (line_input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
218  ;
219  else if (unformat (line_input, "ip6"))
220  is_ip6 = 1;
221  else if (unformat (line_input, "ip4"))
222  is_ip6 = 0;
223  else if (unformat (line_input, "del"))
224  is_del = 1;
225  else if (unformat (line_input, "add"))
226  is_del = 0;
227  else if (unformat (line_input, "via %U",
228  unformat_fib_route_path, &rpath, &payload_proto))
229  vec_add1 (rpaths, rpath);
230  else
231  return (clib_error_return (0, "unknown input '%U'",
232  format_unformat_error, line_input));
233  }
234 
235  if (~0 == sw_if_index)
236  {
237  vlib_cli_output (vm, "Specify an input interface");
238  goto out;
239  }
240  if (vec_len (rpaths) == 0)
241  {
242  vlib_cli_output (vm, "Specify some paths");
243  goto out;
244  }
245 
246  if (!is_del)
247  {
248  rv = l3xc_update (sw_if_index, is_ip6, rpaths);
249 
250  if (rv)
251  {
252  vlib_cli_output (vm, "Failed: %d", rv);
253  goto out;
254  }
255  }
256  else
257  {
259  }
260 
261 out:
262  unformat_free (line_input);
263  return (NULL);
264 }
265 
266 /* *INDENT-OFF* */
267 /**
268  * Create an L3XC policy.
269  */
271  .path = "l3xc",
272  .function = l3xc_cmd,
273  .short_help = "l3xc [add|del] <INTERFACE> via ...",
274  .is_mp_safe = 1,
275 };
276 /* *INDENT-ON* */
277 
278 static u8 *
279 format_l3xc (u8 * s, va_list * args)
280 {
281  l3xc_t *l3xc = va_arg (*args, l3xc_t *);
282  vnet_main_t *vnm = vnet_get_main ();
283 
284  s = format (s, "l3xc:[%d]: %U",
286  vnm, l3xc->l3xc_sw_if_index);
287  s = format (s, "\n");
288  if (FIB_NODE_INDEX_INVALID == l3xc->l3xc_pl)
289  {
290  s = format (s, "no forwarding");
291  }
292  else
293  {
294  s = fib_path_list_format (l3xc->l3xc_pl, s);
295 
296  s = format (s, "\n %U", format_dpo_id, &l3xc->l3xc_dpo, 4);
297  }
298 
299  return (s);
300 }
301 
302 void
304 {
305  u32 l3xci;
306 
307  /* *INDENT-OFF* */
309  {
310  if (!cb(l3xci, ctx))
311  break;
312  }
313  /* *INDENT-ON* */
314 }
315 
316 static clib_error_t *
318  unformat_input_t * input, vlib_cli_command_t * cmd)
319 {
320  l3xc_t *l3xc;
321 
322  /* *INDENT-OFF* */
324  {
326  }
327  /* *INDENT-ON* */
328 
329  return (NULL);
330 }
331 
332 /* *INDENT-OFF* */
334  .path = "show l3xc",
335  .function = l3xc_show_cmd,
336  .short_help = "show l3xc",
337  .is_mp_safe = 1,
338 };
339 /* *INDENT-ON* */
340 
341 static fib_node_t *
343 {
344  l3xc_t *l3xc = l3xc_get (index);
345  return (&(l3xc->l3xc_node));
346 }
347 
348 static l3xc_t *
350 {
351  return ((l3xc_t *) (((char *) node) -
352  STRUCT_OFFSET_OF (l3xc_t, l3xc_node)));
353 }
354 
355 static void
357 {
358 }
359 
360 /*
361  * A back walk has reached this L3XC policy
362  */
365 {
367 
369 }
370 
371 /*
372  * The BIER fmask's graph node virtual function table
373  */
374 static const fib_node_vft_t l3xc_vft = {
376  .fnv_last_lock = l3xc_last_lock_gone,
377  .fnv_back_walk = l3xc_back_walk_notify,
378 };
379 
380 static clib_error_t *
382 {
384 
385  return (NULL);
386 }
387 
389 
390 /*
391  * fd.io coding-style-patch-verification: ON
392  *
393  * Local Variables:
394  * eval: (c-set-style "gnu")
395  * End:
396  */
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:374
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:356
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:364
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:333
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:270
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:303
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:59
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:349
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:576
format_vnet_sw_if_index_name
format_function_t format_vnet_sw_if_index_name
Definition: interface_funcs.h:455
unformat_vnet_sw_interface
unformat_function_t unformat_vnet_sw_interface
Definition: interface_funcs.h:459
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:342
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:279
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:196
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:381
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:317