FD.io VPP  v19.08-27-gf4dcae4
Vector Packet Processing
pw_cw.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/dpo/pw_cw.h>
17 #include <vnet/fib/fib_node.h>
18 
19 #ifndef CLIB_MARCH_VARIANT
20 
21 /*
22  * pool of all MPLS Label DPOs
23  */
25 
26 static pw_cw_dpo_t *
28 {
29  pw_cw_dpo_t *pwcw;
30 
31  pool_get_aligned_zero(pw_cw_dpo_pool, pwcw, 8);
32 
33  return (pwcw);
34 }
35 
36 static index_t
38 {
39  return (pwcw - pw_cw_dpo_pool);
40 }
41 
42 void
43 pw_cw_dpo_create (const dpo_id_t *parent,
44  dpo_id_t *dpo)
45 {
46  pw_cw_dpo_t *pwcw;
47 
48  pwcw = pw_cw_dpo_alloc();
49 
50  /*
51  * stack this disposition object on the parent given
52  */
54  parent->dpoi_proto,
55  &pwcw->pwcw_parent,
56  parent);
57 
58  /*
59  * set up the return DPO to refer to this object
60  */
61  dpo_set(dpo,
62  DPO_PW_CW,
63  parent->dpoi_proto,
64  pw_cw_dpo_get_index(pwcw));
65 }
66 
67 u8*
68 format_pw_cw_dpo (u8 *s, va_list *args)
69 {
70  index_t pwcwi = va_arg (*args, index_t);
71  u32 indent = va_arg (*args, u32);
72  pw_cw_dpo_t *pwcw;
73 
74  if (pool_is_free_index(pw_cw_dpo_pool, pwcwi))
75  {
76  /*
77  * the packet trace can be printed after the DPO has been deleted
78  */
79  return (format(s, "pw-cw[???,%d]:", pwcwi));
80  }
81 
82  pwcw = pw_cw_dpo_get(pwcwi);
83  s = format(s, "pw-cw[%d]:", pwcwi);
84 
85  s = format(s, "\n%U", format_white_space, indent);
86  s = format(s, "%U", format_dpo_id, &pwcw->pwcw_parent, indent+2);
87 
88  return (s);
89 }
90 
91 static void
93 {
94  pw_cw_dpo_t *pwcw;
95 
96  pwcw = pw_cw_dpo_get(dpo->dpoi_index);
97 
98  pwcw->pwcw_locks++;
99 }
100 
101 static void
103 {
104  pw_cw_dpo_t *pwcw;
105 
106  pwcw = pw_cw_dpo_get(dpo->dpoi_index);
107 
108  pwcw->pwcw_locks--;
109 
110  if (0 == pwcw->pwcw_locks)
111  {
112  dpo_reset(&pwcw->pwcw_parent);
113  pool_put(pw_cw_dpo_pool, pwcw);
114  }
115 }
116 #endif /* CLIB_MARCH_VARIANT */
117 
118 /**
119  * @brief A struct to hold tracing information for the MPLS label imposition
120  * node.
121  */
122 typedef struct pw_cw_trace_t_
123 {
124  /**
125  * The CW popped
126  */
128 } pw_cw_trace_t;
129 
132  vlib_node_runtime_t * node,
133  vlib_frame_t * from_frame)
134 {
135  u32 n_left_from, next_index, * from, * to_next;
136 
137  from = vlib_frame_vector_args(from_frame);
138  n_left_from = from_frame->n_vectors;
139  next_index = node->cached_next_index;
140 
141  while (n_left_from > 0)
142  {
143  u32 n_left_to_next;
144 
145  vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
146 
147  while (n_left_from >= 4 && n_left_to_next >= 2)
148  {
149  pw_cw_dpo_t *pwcw0, *pwcw1;
150  u32 bi0, pwcwi0, bi1, pwcwi1;
151  vlib_buffer_t * b0, *b1;
152  u32 next0, next1;
153 
154  bi0 = to_next[0] = from[0];
155  bi1 = to_next[1] = from[1];
156 
157  /* Prefetch next iteration. */
158  {
159  vlib_buffer_t * p2, * p3;
160 
161  p2 = vlib_get_buffer(vm, from[2]);
162  p3 = vlib_get_buffer(vm, from[3]);
163 
164  vlib_prefetch_buffer_header(p2, STORE);
165  vlib_prefetch_buffer_header(p3, STORE);
166 
167  CLIB_PREFETCH(p2->data, sizeof(pw_cw_t), STORE);
168  CLIB_PREFETCH(p3->data, sizeof(pw_cw_t), STORE);
169  }
170 
171  from += 2;
172  to_next += 2;
173  n_left_from -= 2;
174  n_left_to_next -= 2;
175 
176  b0 = vlib_get_buffer(vm, bi0);
177  b1 = vlib_get_buffer(vm, bi1);
178 
179  /* get the next parent DPO for the next pop */
180  pwcwi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
181  pwcwi1 = vnet_buffer(b1)->ip.adj_index[VLIB_TX];
182  pwcw0 = pw_cw_dpo_get(pwcwi0);
183  pwcw1 = pw_cw_dpo_get(pwcwi1);
184 
185  next0 = pwcw0->pwcw_parent.dpoi_next_node;
186  next1 = pwcw1->pwcw_parent.dpoi_next_node;
187 
188  vnet_buffer(b0)->ip.adj_index[VLIB_TX] = pwcw0->pwcw_parent.dpoi_index;
189  vnet_buffer(b1)->ip.adj_index[VLIB_TX] = pwcw1->pwcw_parent.dpoi_index;
190 
191  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
192  {
193  pw_cw_trace_t *tr = vlib_add_trace(vm, node, b0, sizeof(*tr));
194 
195  tr->cw = *((pw_cw_t*) vlib_buffer_get_current(b0));
196  }
197  if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
198  {
199  pw_cw_trace_t *tr = vlib_add_trace(vm, node, b1, sizeof(*tr));
200 
201  tr->cw = *((pw_cw_t*) vlib_buffer_get_current(b1));
202  }
203 
204  /* pop the PW CW */
205  vlib_buffer_advance (b0, sizeof(pw_cw_t));
206  vlib_buffer_advance (b1, sizeof(pw_cw_t));
207 
208  vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next,
209  n_left_to_next,
210  bi0, bi1, next0, next1);
211  }
212 
213  while (n_left_from > 0 && n_left_to_next > 0)
214  {
215  pw_cw_dpo_t *pwcw0;
216  vlib_buffer_t * b0;
217  u32 bi0, pwcwi0;
218  u32 next0;
219 
220  bi0 = from[0];
221  to_next[0] = bi0;
222  from += 1;
223  to_next += 1;
224  n_left_from -= 1;
225  n_left_to_next -= 1;
226 
227  b0 = vlib_get_buffer(vm, bi0);
228 
229  pwcwi0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX];
230  pwcw0 = pw_cw_dpo_get(pwcwi0);
231  next0 = pwcw0->pwcw_parent.dpoi_next_node;
232  vnet_buffer(b0)->ip.adj_index[VLIB_TX] = pwcw0->pwcw_parent.dpoi_index;
233 
234  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
235  {
236  pw_cw_trace_t *tr = vlib_add_trace(vm, node, b0, sizeof(*tr));
237 
238  tr->cw = *((pw_cw_t*) vlib_buffer_get_current(b0));
239  }
240 
241  vlib_buffer_advance (b0, sizeof(pw_cw_t));
242 
243  vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
244  n_left_to_next, bi0, next0);
245  }
246  vlib_put_next_frame(vm, node, next_index, n_left_to_next);
247  }
248  return from_frame->n_vectors;
249 }
250 
251 static u8 *
252 format_pw_cw_trace (u8 * s, va_list * args)
253 {
254  CLIB_UNUSED(vlib_main_t * vm) = va_arg(*args, vlib_main_t *);
255  CLIB_UNUSED(vlib_node_t * node) = va_arg(*args, vlib_node_t *);
257 
258  t = va_arg(*args, pw_cw_trace_t *);
259 
260  s = format(s, "cw:0x%x", t->cw);
261 
262  return (s);
263 }
264 
266  vlib_node_runtime_t * node,
267  vlib_frame_t * frame)
268 {
269  return (pw_cw_pop_inline(vm, node, frame));
270 }
271 
273  .name = "pw-cw-pop",
274  .vector_size = sizeof(u32),
275  .format_trace = format_pw_cw_trace,
276 };
277 
278 #ifndef CLIB_MARCH_VARIANT
279 static void
281 {
282  fib_show_memory_usage("PW-CW",
283  pool_elts(pw_cw_dpo_pool),
284  pool_len(pw_cw_dpo_pool),
285  sizeof(pw_cw_dpo_t));
286 }
287 
288 const static dpo_vft_t pwcw_vft = {
290  .dv_unlock = pw_cw_dpo_unlock,
291  .dv_format = format_pw_cw_dpo,
292  .dv_mem_show = pw_cw_dpo_mem_show,
293 };
294 
295 const static char* const pw_cw_proto_nodes[] =
296 {
297  "pw-cw-pop",
298  NULL,
299 };
300 
301 const static char* const * const pw_cw_nodes[DPO_PROTO_NUM] =
302 {
307 };
308 
309 void
311 {
312  dpo_register(DPO_PW_CW, &pwcw_vft, pw_cw_nodes);
313 }
314 
315 #endif /* CLIB_MARCH_VARIANT */
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:124
dpo_lock_fn_t dv_lock
A reference counting lock function.
Definition: dpo.h:406
void pw_cw_dpo_create(const dpo_id_t *parent, dpo_id_t *dpo)
Create an PW CW pop.
Definition: pw_cw.c:43
#define CLIB_UNUSED(x)
Definition: clib.h:82
A virtual function table regisitered for a DPO type.
Definition: dpo.h:401
u32 cw
The CW popped.
Definition: pw_cw.c:127
static pw_cw_dpo_t * pw_cw_dpo_get(index_t index)
Definition: pw_cw.h:73
static void pw_cw_dpo_unlock(dpo_id_t *dpo)
Definition: pw_cw.c:102
#define NULL
Definition: clib.h:58
dpo_proto_t dpoi_proto
the data-path protocol of the type.
Definition: dpo.h:178
u8 data[0]
Packet data.
Definition: buffer.h:181
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:424
#define VLIB_NODE_FN(node)
Definition: node.h:201
unsigned char u8
Definition: types.h:56
#define pool_len(p)
Number of elements in pool vector.
Definition: pool.h:140
static void pw_cw_dpo_mem_show(void)
Definition: pw_cw.c:280
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:322
#define always_inline
Definition: clib.h:98
static u8 * format_pw_cw_trace(u8 *s, va_list *args)
Definition: pw_cw.c:252
static pw_cw_dpo_t * pw_cw_dpo_alloc(void)
Definition: pw_cw.c:27
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:129
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:203
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
unsigned int u32
Definition: types.h:88
A representation of a Psuedo Wire Control Word pop DPO.
Definition: pw_cw.h:31
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:170
static index_t pw_cw_dpo_get_index(pw_cw_dpo_t *pwcw)
Definition: pw_cw.c:37
static uword pw_cw_pop_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: pw_cw.c:131
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:229
pw_cw_dpo_t * pw_cw_dpo_pool
Definition: pw_cw.c:24
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:286
#define PREDICT_FALSE(x)
Definition: clib.h:111
static const char *const *const pw_cw_nodes[DPO_PROTO_NUM]
Definition: pw_cw.c:301
#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:233
dpo_id_t pwcw_parent
Next DPO in the graph.
Definition: pw_cw.h:36
#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:338
u16 pwcw_locks
Number of locks/users of the label.
Definition: pw_cw.h:41
u8 * format_pw_cw_dpo(u8 *s, va_list *args)
Definition: pw_cw.c:68
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
u16 n_vectors
Definition: node.h:395
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:80
vlib_main_t * vm
Definition: buffer.c:312
vlib_node_registration_t pw_cw_node
(constructor) VLIB_REGISTER_NODE (pw_cw_node)
Definition: pw_cw.c:272
A struct to hold tracing information for the MPLS label imposition node.
Definition: pw_cw.c:122
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:283
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:458
void dpo_set(dpo_id_t *dpo, dpo_type_t type, dpo_proto_t proto, index_t index)
Set/create a DPO ID The DPO will be locked.
Definition: dpo.c:186
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:513
struct pw_cw_trace_t_ pw_cw_trace_t
A struct to hold tracing information for the MPLS label imposition node.
static const char *const pw_cw_proto_nodes[]
Definition: pw_cw.c:295
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:248
u8 * format_dpo_id(u8 *s, va_list *args)
Format a DPO_id_t oject
Definition: dpo.c:148
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
#define DPO_PROTO_NUM
Definition: dpo.h:70
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:186
Definition: dpo.h:127
VLIB buffer representation.
Definition: buffer.h:102
u64 uword
Definition: types.h:112
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:244
u32 pw_cw_t
A Psuedo Wire Control Word is 4 bytes.
Definition: pw_cw.h:26
void pw_cw_dpo_module_init(void)
Definition: pw_cw.c:310
#define vnet_buffer(b)
Definition: buffer.h:361
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:232
u16 dpoi_next_node
The next VLIB node to follow.
Definition: dpo.h:182
static void pw_cw_dpo_lock(dpo_id_t *dpo)
Definition: pw_cw.c:92
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:85
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:516
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128