FD.io VPP  v17.10-9-gd594711
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/ip.h>
18 #include <vnet/mpls/mpls.h>
19 
20 /*
21  * pool of all MPLS Label DPOs
22  */
24 
25 static mpls_disp_dpo_t *
27 {
28  mpls_disp_dpo_t *mdd;
29 
30  pool_get_aligned(mpls_disp_dpo_pool, mdd, CLIB_CACHE_LINE_BYTES);
31  memset(mdd, 0, sizeof(*mdd));
32 
33  dpo_reset(&mdd->mdd_dpo);
34 
35  return (mdd);
36 }
37 
38 static index_t
40 {
41  return (mdd - mpls_disp_dpo_pool);
42 }
43 
44 index_t
46  fib_rpf_id_t rpf_id,
47  const dpo_id_t *dpo)
48 {
49  mpls_disp_dpo_t *mdd;
50 
51  mdd = mpls_disp_dpo_alloc();
52 
53  mdd->mdd_payload_proto = payload_proto;
54  mdd->mdd_rpf_id = rpf_id;
55 
57  mdd->mdd_payload_proto,
58  &mdd->mdd_dpo,
59  dpo);
60 
61  return (mpls_disp_dpo_get_index(mdd));
62 }
63 
64 u8*
65 format_mpls_disp_dpo (u8 *s, va_list *args)
66 {
67  index_t index = va_arg (*args, index_t);
68  u32 indent = va_arg (*args, u32);
69  mpls_disp_dpo_t *mdd;
70 
71  mdd = mpls_disp_dpo_get(index);
72 
73  s = format(s, "mpls-disposition:[%d]:[%U]",
74  index,
76 
77  s = format(s, "\n%U", format_white_space, indent);
78  s = format(s, "%U", format_dpo_id, &mdd->mdd_dpo, indent+2);
79 
80  return (s);
81 }
82 
83 static void
85 {
86  mpls_disp_dpo_t *mdd;
87 
88  mdd = mpls_disp_dpo_get(dpo->dpoi_index);
89 
90  mdd->mdd_locks++;
91 }
92 
93 static void
95 {
96  mpls_disp_dpo_t *mdd;
97 
98  mdd = mpls_disp_dpo_get(dpo->dpoi_index);
99 
100  mdd->mdd_locks--;
101 
102  if (0 == mdd->mdd_locks)
103  {
104  dpo_reset(&mdd->mdd_dpo);
105  pool_put(mpls_disp_dpo_pool, mdd);
106  }
107 }
108 
109 /**
110  * @brief A struct to hold tracing information for the MPLS label disposition
111  * node.
112  */
114 {
117 
120  vlib_node_runtime_t * node,
121  vlib_frame_t * from_frame,
122  u8 payload_is_ip4,
123  u8 payload_is_ip6)
124 {
125  u32 n_left_from, next_index, * from, * to_next;
126 
127  from = vlib_frame_vector_args (from_frame);
128  n_left_from = from_frame->n_vectors;
129 
130  next_index = node->cached_next_index;
131 
132  while (n_left_from > 0)
133  {
134  u32 n_left_to_next;
135 
136  vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
137 
138  while (n_left_from >= 4 && n_left_to_next >= 2)
139  {
140  mpls_disp_dpo_t *mdd0, *mdd1;
141  u32 bi0, mddi0, bi1, mddi1;
142  vlib_buffer_t * b0, *b1;
143  u32 next0, next1;
144 
145  bi0 = to_next[0] = from[0];
146  bi1 = to_next[1] = from[1];
147 
148  /* Prefetch next iteration. */
149  {
150  vlib_buffer_t * p2, * p3;
151 
152  p2 = vlib_get_buffer (vm, from[2]);
153  p3 = vlib_get_buffer (vm, from[3]);
154 
155  vlib_prefetch_buffer_header (p2, STORE);
156  vlib_prefetch_buffer_header (p3, STORE);
157 
158  CLIB_PREFETCH (p2->data, sizeof (ip6_header_t), STORE);
159  CLIB_PREFETCH (p3->data, sizeof (ip6_header_t), STORE);
160  }
161 
162  from += 2;
163  to_next += 2;
164  n_left_from -= 2;
165  n_left_to_next -= 2;
166 
167  b0 = vlib_get_buffer (vm, bi0);
168  b1 = vlib_get_buffer (vm, bi1);
169 
170  /* dst lookup was done by ip4 lookup */
171  mddi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
172  mddi1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
173  mdd0 = mpls_disp_dpo_get(mddi0);
174  mdd1 = mpls_disp_dpo_get(mddi1);
175 
176  if (payload_is_ip4)
177  {
178  /*
179  * decrement the TTL on ingress to the LSP
180  */
181  }
182  else if (payload_is_ip6)
183  {
184  /*
185  * decrement the TTL on ingress to the LSP
186  */
187  }
188 
189  next0 = mdd0->mdd_dpo.dpoi_next_node;
190  next1 = mdd1->mdd_dpo.dpoi_next_node;
191  vnet_buffer(b0)->ip.adj_index[VLIB_TX] = mdd0->mdd_dpo.dpoi_index;
192  vnet_buffer(b1)->ip.adj_index[VLIB_TX] = mdd1->mdd_dpo.dpoi_index;
193  vnet_buffer(b0)->ip.rpf_id = mdd0->mdd_rpf_id;
194  vnet_buffer(b1)->ip.rpf_id = mdd1->mdd_rpf_id;
195 
197  {
199  vlib_add_trace (vm, node, b0, sizeof (*tr));
200 
201  tr->mdd = mddi0;
202  }
204  {
206  vlib_add_trace (vm, node, b1, sizeof (*tr));
207  tr->mdd = mddi1;
208  }
209 
210  vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next,
211  n_left_to_next,
212  bi0, bi1, next0, next1);
213  }
214 
215  while (n_left_from > 0 && n_left_to_next > 0)
216  {
217  mpls_disp_dpo_t *mdd0;
218  vlib_buffer_t * b0;
219  u32 bi0, mddi0;
220  u32 next0;
221 
222  bi0 = from[0];
223  to_next[0] = bi0;
224  from += 1;
225  to_next += 1;
226  n_left_from -= 1;
227  n_left_to_next -= 1;
228 
229  b0 = vlib_get_buffer (vm, bi0);
230 
231  /* dst lookup was done by ip4 lookup */
232  mddi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
233  mdd0 = mpls_disp_dpo_get(mddi0);
234 
235  if (payload_is_ip4)
236  {
237  /*
238  * decrement the TTL on ingress to the LSP
239  */
240  }
241  else if (payload_is_ip6)
242  {
243  /*
244  * decrement the TTL on ingress to the LSP
245  */
246  }
247  else
248  {
249  }
250 
251  next0 = mdd0->mdd_dpo.dpoi_next_node;
252  vnet_buffer(b0)->ip.adj_index[VLIB_TX] = mdd0->mdd_dpo.dpoi_index;
253  vnet_buffer(b0)->ip.rpf_id = mdd0->mdd_rpf_id;
254 
256  {
258  vlib_add_trace (vm, node, b0, sizeof (*tr));
259  tr->mdd = mddi0;
260  }
261 
262  vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
263  n_left_to_next, bi0, next0);
264  }
265  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
266  }
267  return from_frame->n_vectors;
268 }
269 
270 static u8 *
272 {
273  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
274  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
276 
277  t = va_arg (*args, mpls_label_disposition_trace_t *);
278 
279  s = format(s, "disp:%d", t->mdd);
280  return (s);
281 }
282 
283 static uword
285  vlib_node_runtime_t * node,
286  vlib_frame_t * frame)
287 {
288  return (mpls_label_disposition_inline(vm, node, frame, 1, 0));
289 }
290 
292  .function = ip4_mpls_label_disposition,
293  .name = "ip4-mpls-label-disposition",
294  .vector_size = sizeof (u32),
295 
296  .format_trace = format_mpls_label_disposition_trace,
297  .n_next_nodes = 1,
298  .next_nodes = {
299  [0] = "ip4-drop",
300  }
301 };
304 
305 static uword
306 ip6_mpls_label_disposition (vlib_main_t * vm,
307  vlib_node_runtime_t * node,
308  vlib_frame_t * frame)
309 {
310  return (mpls_label_disposition_inline(vm, node, frame, 0, 1));
311 }
312 
314  .function = ip6_mpls_label_disposition,
315  .name = "ip6-mpls-label-disposition",
316  .vector_size = sizeof (u32),
317 
318  .format_trace = format_mpls_label_disposition_trace,
319  .n_next_nodes = 1,
320  .next_nodes = {
321  [0] = "ip6-drop",
322  }
323 };
325  ip6_mpls_label_disposition)
326 
327 static void
328 mpls_disp_dpo_mem_show (void)
329 {
330  fib_show_memory_usage("MPLS label",
331  pool_elts(mpls_disp_dpo_pool),
332  pool_len(mpls_disp_dpo_pool),
333  sizeof(mpls_disp_dpo_t));
334 }
335 
336 const static dpo_vft_t mdd_vft = {
338  .dv_unlock = mpls_disp_dpo_unlock,
339  .dv_format = format_mpls_disp_dpo,
340  .dv_mem_show = mpls_disp_dpo_mem_show,
341 };
342 
343 const static char* const mpls_label_disp_ip4_nodes[] =
344 {
345  "ip4-mpls-label-disposition",
346  NULL,
347 };
348 const static char* const mpls_label_disp_ip6_nodes[] =
349 {
350  "ip6-mpls-label-disposition",
351  NULL,
352 };
353 const static char* const * const mpls_label_disp_nodes[DPO_PROTO_NUM] =
354 {
357 };
358 
359 
360 void
362 {
364 }
dpo_lock_fn_t dv_lock
A reference counting lock function.
Definition: dpo.h:350
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:345
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
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:303
#define always_inline
Definition: clib.h:84
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:169
dpo_proto_t mdd_payload_proto
The protocol of the payload/packets that are being encapped.
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:221
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:150
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:270
VLIB_NODE_FUNCTION_MULTIARCH(ip4_mpls_label_disposition_node, ip4_mpls_label_disposition)
#define PREDICT_FALSE(x)
Definition: clib.h:97
#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:216
#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
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[]
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:93
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)
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:315
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:143
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:69
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:166
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:171
#define vnet_buffer(b)
Definition: buffer.h:306
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
u8 data[0]
Packet data.
Definition: buffer.h:157
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:225
u16 dpoi_next_node
The next VLIB node to follow.
Definition: dpo.h:162
#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:456
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128