FD.io VPP  v18.01-8-g0eacf49
Vector Packet Processing
mpls_disposition.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 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 <vnet/ip/ip4_input.h>
17 #include <vnet/ip/ip6_input.h>
19 #include <vnet/mpls/mpls.h>
20 
21 /*
22  * pool of all MPLS Label DPOs
23  */
25 
26 static mpls_disp_dpo_t *
28 {
29  mpls_disp_dpo_t *mdd;
30 
31  pool_get_aligned(mpls_disp_dpo_pool, mdd, CLIB_CACHE_LINE_BYTES);
32  memset(mdd, 0, sizeof(*mdd));
33 
34  dpo_reset(&mdd->mdd_dpo);
35 
36  return (mdd);
37 }
38 
39 static index_t
41 {
42  return (mdd - mpls_disp_dpo_pool);
43 }
44 
45 index_t
47  fib_rpf_id_t rpf_id,
48  const dpo_id_t *dpo)
49 {
50  mpls_disp_dpo_t *mdd;
51 
52  mdd = mpls_disp_dpo_alloc();
53 
54  mdd->mdd_payload_proto = payload_proto;
55  mdd->mdd_rpf_id = rpf_id;
56 
58  mdd->mdd_payload_proto,
59  &mdd->mdd_dpo,
60  dpo);
61 
62  return (mpls_disp_dpo_get_index(mdd));
63 }
64 
65 u8*
66 format_mpls_disp_dpo (u8 *s, va_list *args)
67 {
68  index_t index = va_arg (*args, index_t);
69  u32 indent = va_arg (*args, u32);
70  mpls_disp_dpo_t *mdd;
71 
72  mdd = mpls_disp_dpo_get(index);
73 
74  s = format(s, "mpls-disposition:[%d]:[%U]",
75  index,
77 
78  s = format(s, "\n%U", format_white_space, indent);
79  s = format(s, "%U", format_dpo_id, &mdd->mdd_dpo, indent+2);
80 
81  return (s);
82 }
83 
84 static void
86 {
87  mpls_disp_dpo_t *mdd;
88 
89  mdd = mpls_disp_dpo_get(dpo->dpoi_index);
90 
91  mdd->mdd_locks++;
92 }
93 
94 static void
96 {
97  mpls_disp_dpo_t *mdd;
98 
99  mdd = mpls_disp_dpo_get(dpo->dpoi_index);
100 
101  mdd->mdd_locks--;
102 
103  if (0 == mdd->mdd_locks)
104  {
105  dpo_reset(&mdd->mdd_dpo);
106  pool_put(mpls_disp_dpo_pool, mdd);
107  }
108 }
109 
110 /**
111  * @brief A struct to hold tracing information for the MPLS label disposition
112  * node.
113  */
115 {
118 
121 
124  vlib_node_runtime_t * node,
125  vlib_frame_t * from_frame,
126  u8 payload_is_ip4,
127  u8 payload_is_ip6)
128 {
129  u32 n_left_from, next_index, * from, * to_next;
130  vlib_node_runtime_t *error_node;
131 
132  if (payload_is_ip4)
134  else
136 
137  from = vlib_frame_vector_args (from_frame);
138  n_left_from = from_frame->n_vectors;
139 
140  next_index = node->cached_next_index;
141 
142  while (n_left_from > 0)
143  {
144  u32 n_left_to_next;
145 
146  vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
147 
148  while (n_left_from >= 4 && n_left_to_next >= 2)
149  {
150  mpls_disp_dpo_t *mdd0, *mdd1;
151  u32 bi0, mddi0, bi1, mddi1;
152  vlib_buffer_t * b0, *b1;
153  u32 next0, next1;
154 
155  bi0 = to_next[0] = from[0];
156  bi1 = to_next[1] = from[1];
157 
158  /* Prefetch next iteration. */
159  {
160  vlib_buffer_t * p2, * p3;
161 
162  p2 = vlib_get_buffer (vm, from[2]);
163  p3 = vlib_get_buffer (vm, from[3]);
164 
165  vlib_prefetch_buffer_header (p2, STORE);
166  vlib_prefetch_buffer_header (p3, STORE);
167 
168  CLIB_PREFETCH (p2->data, sizeof (ip6_header_t), STORE);
169  CLIB_PREFETCH (p3->data, sizeof (ip6_header_t), STORE);
170  }
171 
172  from += 2;
173  to_next += 2;
174  n_left_from -= 2;
175  n_left_to_next -= 2;
176 
177  b0 = vlib_get_buffer (vm, bi0);
178  b1 = vlib_get_buffer (vm, bi1);
179 
180  /* dst lookup was done by ip4 lookup */
181  mddi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
182  mddi1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
183  mdd0 = mpls_disp_dpo_get(mddi0);
184  mdd1 = mpls_disp_dpo_get(mddi1);
185 
186  next0 = mdd0->mdd_dpo.dpoi_next_node;
187  next1 = mdd1->mdd_dpo.dpoi_next_node;
188 
189  if (payload_is_ip4)
190  {
191  ip4_header_t *ip0, *ip1;
192 
193  ip0 = vlib_buffer_get_current (b0);
194  ip1 = vlib_buffer_get_current (b1);
195 
196  /*
197  * IPv4 input checks on the exposed IP header
198  * including checksum
199  */
200  ip4_input_check_x2 (vm, error_node,
201  b0, b1, ip0, ip1,
202  &next0, &next1, 1);
203  }
204  else if (payload_is_ip6)
205  {
206  ip6_header_t *ip0, *ip1;
207 
208  ip0 = vlib_buffer_get_current (b0);
209  ip1 = vlib_buffer_get_current (b1);
210 
211  /*
212  * IPv6 input checks on the exposed IP header
213  */
214  ip6_input_check_x2 (vm, error_node,
215  b0, b1, ip0, ip1,
216  &next0, &next1);
217  }
218 
219  vnet_buffer(b0)->ip.adj_index[VLIB_TX] = mdd0->mdd_dpo.dpoi_index;
220  vnet_buffer(b1)->ip.adj_index[VLIB_TX] = mdd1->mdd_dpo.dpoi_index;
221  vnet_buffer(b0)->ip.rpf_id = mdd0->mdd_rpf_id;
222  vnet_buffer(b1)->ip.rpf_id = mdd1->mdd_rpf_id;
223 
225  {
227  vlib_add_trace (vm, node, b0, sizeof (*tr));
228 
229  tr->mdd = mddi0;
230  }
232  {
234  vlib_add_trace (vm, node, b1, sizeof (*tr));
235  tr->mdd = mddi1;
236  }
237 
238  vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next,
239  n_left_to_next,
240  bi0, bi1, next0, next1);
241  }
242 
243  while (n_left_from > 0 && n_left_to_next > 0)
244  {
245  mpls_disp_dpo_t *mdd0;
246  vlib_buffer_t * b0;
247  u32 bi0, mddi0;
248  u32 next0;
249 
250  bi0 = from[0];
251  to_next[0] = bi0;
252  from += 1;
253  to_next += 1;
254  n_left_from -= 1;
255  n_left_to_next -= 1;
256 
257  b0 = vlib_get_buffer (vm, bi0);
258 
259  /* dst lookup was done by ip4 lookup */
260  mddi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
261  mdd0 = mpls_disp_dpo_get(mddi0);
262  next0 = mdd0->mdd_dpo.dpoi_next_node;
263 
264  if (payload_is_ip4)
265  {
266  ip4_header_t *ip0;
267 
268  ip0 = vlib_buffer_get_current (b0);
269 
270  /*
271  * IPv4 input checks on the exposed IP header
272  * including checksum
273  */
274  ip4_input_check_x1 (vm, error_node, b0, ip0, &next0, 1);
275  }
276  else if (payload_is_ip6)
277  {
278  ip6_header_t *ip0;
279 
280  ip0 = vlib_buffer_get_current (b0);
281 
282  /*
283  * IPv6 input checks on the exposed IP header
284  */
285  ip6_input_check_x1 (vm, error_node, b0, ip0, &next0);
286  }
287 
288  vnet_buffer(b0)->ip.adj_index[VLIB_TX] = mdd0->mdd_dpo.dpoi_index;
289  vnet_buffer(b0)->ip.rpf_id = mdd0->mdd_rpf_id;
290 
292  {
294  vlib_add_trace (vm, node, b0, sizeof (*tr));
295  tr->mdd = mddi0;
296  }
297 
298  vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
299  n_left_to_next, bi0, next0);
300  }
301  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
302  }
303  return from_frame->n_vectors;
304 }
305 
306 static u8 *
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 *);
312 
313  t = va_arg (*args, mpls_label_disposition_trace_t *);
314 
315  s = format(s, "disp:%d", t->mdd);
316  return (s);
317 }
318 
319 static uword
321  vlib_node_runtime_t * node,
322  vlib_frame_t * frame)
323 {
324  return (mpls_label_disposition_inline(vm, node, frame, 1, 0));
325 }
326 
328  .function = ip4_mpls_label_disposition,
329  .name = "ip4-mpls-label-disposition",
330  .vector_size = sizeof (u32),
331 
332  .format_trace = format_mpls_label_disposition_trace,
333  .sibling_of = "ip4-input",
334  .n_errors = IP4_N_ERROR,
335  .error_strings = ip4_error_strings,
336 };
339 
340 static uword
341 ip6_mpls_label_disposition (vlib_main_t * vm,
342  vlib_node_runtime_t * node,
343  vlib_frame_t * frame)
344 {
345  return (mpls_label_disposition_inline(vm, node, frame, 0, 1));
346 }
347 
349  .function = ip6_mpls_label_disposition,
350  .name = "ip6-mpls-label-disposition",
351  .vector_size = sizeof (u32),
352 
353  .format_trace = format_mpls_label_disposition_trace,
354  .sibling_of = "ip6-input",
355  .n_errors = IP6_N_ERROR,
356  .error_strings = ip6_error_strings,
357 };
359  ip6_mpls_label_disposition)
360 
361 static void
362 mpls_disp_dpo_mem_show (void)
363 {
364  fib_show_memory_usage("MPLS label",
365  pool_elts(mpls_disp_dpo_pool),
366  pool_len(mpls_disp_dpo_pool),
367  sizeof(mpls_disp_dpo_t));
368 }
369 
370 const static dpo_vft_t mdd_vft = {
372  .dv_unlock = mpls_disp_dpo_unlock,
373  .dv_format = format_mpls_disp_dpo,
374  .dv_mem_show = mpls_disp_dpo_mem_show,
375 };
376 
377 const static char* const mpls_label_disp_ip4_nodes[] =
378 {
379  "ip4-mpls-label-disposition",
380  NULL,
381 };
382 const static char* const mpls_label_disp_ip6_nodes[] =
383 {
384  "ip6-mpls-label-disposition",
385  NULL,
386 };
387 const static char* const * const mpls_label_disp_nodes[DPO_PROTO_NUM] =
388 {
391 };
392 
393 
394 void
396 {
398 }
dpo_lock_fn_t dv_lock
A reference counting lock function.
Definition: dpo.h:382
u16 mdd_locks
Number of locks/users of the label.
A struct to hold tracing information for the MPLS label disposition node.
#define CLIB_UNUSED(x)
Definition: clib.h:79
A virtual function table regisitered for a DPO type.
Definition: dpo.h:377
static void mpls_disp_dpo_lock(dpo_id_t *dpo)
#define NULL
Definition: clib.h:55
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
struct _vlib_node_registration vlib_node_registration_t
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
#define pool_len(p)
Number of elements in pool vector.
Definition: pool.h:140
static index_t mpls_disp_dpo_get_index(mpls_disp_dpo_t *mdd)
static mpls_disp_dpo_t * mpls_disp_dpo_alloc(void)
void dpo_register(dpo_type_t type, const dpo_vft_t *vft, const char *const *const *nodes)
For a given DPO type Register:
Definition: dpo.c:306
#define always_inline
Definition: clib.h:92
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:113
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:171
char * ip4_error_strings[]
Definition: ip4_input.c:270
dpo_proto_t mdd_payload_proto
The protocol of the payload/packets that are being encapped.
static void ip4_input_check_x1(vlib_main_t *vm, vlib_node_runtime_t *error_node, vlib_buffer_t *p0, ip4_header_t *ip0, u32 *next0, int verify_checksum)
Definition: ip4_input.h:155
void fib_show_memory_usage(const char *name, u32 in_use_elts, u32 allocd_elts, size_t size_elt)
Show the memory usage for a type.
Definition: fib_node.c:220
static const char *const *const mpls_label_disp_nodes[DPO_PROTO_NUM]
fib_rpf_id_t mdd_rpf_id
RPF-ID (if this is an mcast disposition)
enum dpo_proto_t_ dpo_proto_t
Data path protocol.
static void mpls_disp_dpo_unlock(dpo_id_t *dpo)
static const char *const mpls_label_disp_ip6_nodes[]
static uword ip4_mpls_label_disposition(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:166
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:195
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:271
VLIB_NODE_FUNCTION_MULTIARCH(ip4_mpls_label_disposition_node, ip4_mpls_label_disposition)
#define PREDICT_FALSE(x)
Definition: clib.h:105
#define vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next, n_left_to_next, bi0, bi1, next0, next1)
Finish enqueueing two buffers forward in the graph.
Definition: buffer_node.h:70
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
Definition: buffer_node.h:218
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:364
static void ip6_input_check_x2(vlib_main_t *vm, vlib_node_runtime_t *error_node, vlib_buffer_t *p0, vlib_buffer_t *p1, ip6_header_t *ip0, ip6_header_t *ip1, u32 *next0, u32 *next1)
Definition: ip6_input.h:57
mpls_disp_dpo_t * mpls_disp_dpo_pool
#define pool_get_aligned(P, E, A)
Allocate an object E from a pool P (general version).
Definition: pool.h:188
u16 n_vectors
Definition: node.h:344
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:82
vlib_main_t * vm
Definition: buffer.c:283
static const char *const mpls_label_disp_ip4_nodes[]
static void ip6_input_check_x1(vlib_main_t *vm, vlib_node_runtime_t *error_node, vlib_buffer_t *p0, ip6_header_t *ip0, u32 *next0)
Definition: ip6_input.h:121
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:93
static vlib_node_runtime_t * vlib_node_get_runtime(vlib_main_t *vm, u32 node_index)
Get node runtime by node index.
Definition: node_funcs.h:89
struct mpls_label_disposition_trace_t_ mpls_label_disposition_trace_t
A struct to hold tracing information for the MPLS label disposition node.
u8 * format_mpls_disp_dpo(u8 *s, va_list *args)
char * ip6_error_strings[]
Definition: ip6_input.c:221
index_t mpls_disp_dpo_create(dpo_proto_t payload_proto, fib_rpf_id_t rpf_id, const dpo_id_t *dpo)
Create an MPLS label object.
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:454
void mpls_disp_dpo_module_init(void)
u32 fib_rpf_id_t
An RPF-ID is numerical value that is used RPF validate.
Definition: fib_types.h:356
A representation of an MPLS label for imposition in the data-path.
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:456
unsigned int u32
Definition: types.h:88
u8 * format_dpo_id(u8 *s, va_list *args)
Format a DPO_id_t oject
Definition: dpo.c:146
dpo_id_t mdd_dpo
Next DPO in the graph.
u64 uword
Definition: types.h:112
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace_funcs.h:55
Definition: defs.h:47
static mpls_disp_dpo_t * mpls_disp_dpo_get(index_t index)
static uword mpls_label_disposition_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame, u8 payload_is_ip4, u8 payload_is_ip6)
#define DPO_PROTO_NUM
Definition: dpo.h:70
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:182
static void ip4_input_check_x2(vlib_main_t *vm, vlib_node_runtime_t *error_node, vlib_buffer_t *p0, vlib_buffer_t *p1, ip4_header_t *ip0, ip4_header_t *ip1, u32 *next0, u32 *next1, int verify_checksum)
Definition: ip4_input.h:59
unsigned char u8
Definition: types.h:56
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:267
vlib_node_registration_t ip6_mpls_label_disposition_node
(constructor) VLIB_REGISTER_NODE (ip6_mpls_label_disposition_node)
u8 * format_dpo_proto(u8 *s, va_list *args)
format a DPO protocol
Definition: dpo.c:174
#define vnet_buffer(b)
Definition: buffer.h:326
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
u8 data[0]
Packet data.
Definition: buffer.h:159
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:228
u16 dpoi_next_node
The next VLIB node to follow.
Definition: dpo.h:178
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:75
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:57
vlib_node_registration_t ip4_mpls_label_disposition_node
(constructor) VLIB_REGISTER_NODE (ip4_mpls_label_disposition_node)
static u8 * format_mpls_label_disposition_trace(u8 *s, va_list *args)
void dpo_stack(dpo_type_t child_type, dpo_proto_t child_proto, 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:470
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128