FD.io VPP  v16.09
Vector Packet Processing
buffer_node.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 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  * buffer_node.h: VLIB buffer handling node helper macros/inlines
17  *
18  * Copyright (c) 2008 Eliot Dresselhaus
19  *
20  * Permission is hereby granted, free of charge, to any person obtaining
21  * a copy of this software and associated documentation files (the
22  * "Software"), to deal in the Software without restriction, including
23  * without limitation the rights to use, copy, modify, merge, publish,
24  * distribute, sublicense, and/or sell copies of the Software, and to
25  * permit persons to whom the Software is furnished to do so, subject to
26  * the following conditions:
27  *
28  * The above copyright notice and this permission notice shall be
29  * included in all copies or substantial portions of the Software.
30  *
31  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38  */
39 
40 #ifndef included_vlib_buffer_node_h
41 #define included_vlib_buffer_node_h
42 
43 /** \file
44  vlib buffer/node functions
45 */
46 
47 /** \brief Finish enqueueing two buffers forward in the graph.
48  Standard dual loop boilerplate element. This is a MACRO,
49  with MULTIPLE SIDE EFFECTS. In the ideal case,
50  <code>next_index == next0 == next1</code>,
51  which means that the speculative enqueue at the top of the dual loop
52  has correctly dealt with both packets. In that case, the macro does
53  nothing at all.
54 
55  @param vm vlib_main_t pointer, varies by thread
56  @param node current node vlib_node_runtime_t pointer
57  @param next_index speculated next index used for both packets
58  @param to_next speculated vector pointer used for both packets
59  @param n_left_to_next number of slots left in speculated vector
60  @param bi0 first buffer index
61  @param bi1 second buffer index
62  @param next0 actual next index to be used for the first packet
63  @param next1 actual next index to be used for the second packet
64 
65  @return @c next_index -- speculative next index to be used for future packets
66  @return @c to_next -- speculative frame to be used for future packets
67  @return @c n_left_to_next -- number of slots left in speculative frame
68 */
69 
70 #define vlib_validate_buffer_enqueue_x2(vm,node,next_index,to_next,n_left_to_next,bi0,bi1,next0,next1) \
71 do { \
72  int enqueue_code = (next0 != next_index) + 2*(next1 != next_index); \
73  \
74  if (PREDICT_FALSE (enqueue_code != 0)) \
75  { \
76  switch (enqueue_code) \
77  { \
78  case 1: \
79  /* A B A */ \
80  to_next[-2] = bi1; \
81  to_next -= 1; \
82  n_left_to_next += 1; \
83  vlib_set_next_frame_buffer (vm, node, next0, bi0); \
84  break; \
85  \
86  case 2: \
87  /* A A B */ \
88  to_next -= 1; \
89  n_left_to_next += 1; \
90  vlib_set_next_frame_buffer (vm, node, next1, bi1); \
91  break; \
92  \
93  case 3: \
94  /* A B B or A B C */ \
95  to_next -= 2; \
96  n_left_to_next += 2; \
97  vlib_set_next_frame_buffer (vm, node, next0, bi0); \
98  vlib_set_next_frame_buffer (vm, node, next1, bi1); \
99  if (next0 == next1) \
100  { \
101  vlib_put_next_frame (vm, node, next_index, \
102  n_left_to_next); \
103  next_index = next1; \
104  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); \
105  } \
106  } \
107  } \
108 } while (0)
109 
110 /** \brief Finish enqueueing one buffer forward in the graph.
111  Standard single loop boilerplate element. This is a MACRO,
112  with MULTIPLE SIDE EFFECTS. In the ideal case,
113  <code>next_index == next0</code>,
114  which means that the speculative enqueue at the top of the single loop
115  has correctly dealt with the packet in hand. In that case, the macro does
116  nothing at all.
117 
118  @param vm vlib_main_t pointer, varies by thread
119  @param node current node vlib_node_runtime_t pointer
120  @param next_index speculated next index used for both packets
121  @param to_next speculated vector pointer used for both packets
122  @param n_left_to_next number of slots left in speculated vector
123  @param bi0 first buffer index
124  @param next0 actual next index to be used for the first packet
125 
126  @return @c next_index -- speculative next index to be used for future packets
127  @return @c to_next -- speculative frame to be used for future packets
128  @return @c n_left_to_next -- number of slots left in speculative frame
129 */
130 #define vlib_validate_buffer_enqueue_x1(vm,node,next_index,to_next,n_left_to_next,bi0,next0) \
131 do { \
132  if (PREDICT_FALSE (next0 != next_index)) \
133  { \
134  vlib_put_next_frame (vm, node, next_index, n_left_to_next + 1); \
135  next_index = next0; \
136  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); \
137  \
138  to_next[0] = bi0; \
139  to_next += 1; \
140  n_left_to_next -= 1; \
141  } \
142 } while (0)
143 
146  vlib_node_runtime_t * node,
147  vlib_frame_t * frame,
148  uword sizeof_trace,
149  void *opaque1,
150  uword opaque2,
151  void (*two_buffers) (vlib_main_t * vm,
152  void *opaque1,
153  uword opaque2,
154  vlib_buffer_t * b0,
155  vlib_buffer_t * b1,
156  u32 * next0, u32 * next1),
157  void (*one_buffer) (vlib_main_t * vm,
158  void *opaque1, uword opaque2,
159  vlib_buffer_t * b0,
160  u32 * next0))
161 {
162  u32 n_left_from, *from, *to_next;
163  u32 next_index;
164 
165  from = vlib_frame_vector_args (frame);
166  n_left_from = frame->n_vectors;
167  next_index = node->cached_next_index;
168 
169  if (node->flags & VLIB_NODE_FLAG_TRACE)
170  vlib_trace_frame_buffers_only (vm, node, from, frame->n_vectors,
171  /* stride */ 1, sizeof_trace);
172 
173  while (n_left_from > 0)
174  {
175  u32 n_left_to_next;
176 
177  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
178 
179  while (n_left_from >= 4 && n_left_to_next >= 2)
180  {
181  vlib_buffer_t *p0, *p1;
182  u32 pi0, next0;
183  u32 pi1, next1;
184 
185  /* Prefetch next iteration. */
186  {
187  vlib_buffer_t *p2, *p3;
188 
189  p2 = vlib_get_buffer (vm, from[2]);
190  p3 = vlib_get_buffer (vm, from[3]);
191 
192  vlib_prefetch_buffer_header (p2, LOAD);
193  vlib_prefetch_buffer_header (p3, LOAD);
194 
195  CLIB_PREFETCH (p2->data, 64, LOAD);
196  CLIB_PREFETCH (p3->data, 64, LOAD);
197  }
198 
199  pi0 = to_next[0] = from[0];
200  pi1 = to_next[1] = from[1];
201  from += 2;
202  to_next += 2;
203  n_left_from -= 2;
204  n_left_to_next -= 2;
205 
206  p0 = vlib_get_buffer (vm, pi0);
207  p1 = vlib_get_buffer (vm, pi1);
208 
209  two_buffers (vm, opaque1, opaque2, p0, p1, &next0, &next1);
210 
211  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
212  to_next, n_left_to_next,
213  pi0, pi1, next0, next1);
214  }
215 
216  while (n_left_from > 0 && n_left_to_next > 0)
217  {
218  vlib_buffer_t *p0;
219  u32 pi0, next0;
220 
221  pi0 = from[0];
222  to_next[0] = pi0;
223  from += 1;
224  to_next += 1;
225  n_left_from -= 1;
226  n_left_to_next -= 1;
227 
228  p0 = vlib_get_buffer (vm, pi0);
229 
230  one_buffer (vm, opaque1, opaque2, p0, &next0);
231 
232  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
233  to_next, n_left_to_next,
234  pi0, next0);
235  }
236 
237  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
238  }
239 
240  return frame->n_vectors;
241 }
242 
243 #endif /* included_vlib_buffer_node_h */
244 
245 /*
246  * fd.io coding-style-patch-verification: ON
247  *
248  * Local Variables:
249  * eval: (c-set-style "gnu")
250  * End:
251  */
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:457
#define always_inline
Definition: clib.h:84
#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:130
#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:348
u16 n_vectors
Definition: node.h:344
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:82
u16 cached_next_index
Definition: node.h:462
unsigned int u32
Definition: types.h:88
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:259
static uword generic_buffer_node_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, uword sizeof_trace, void *opaque1, uword opaque2, void(*two_buffers)(vlib_main_t *vm, void *opaque1, uword opaque2, vlib_buffer_t *b0, vlib_buffer_t *b1, u32 *next0, u32 *next1), void(*one_buffer)(vlib_main_t *vm, void *opaque1, uword opaque2, vlib_buffer_t *b0, u32 *next0))
Definition: buffer_node.h:145
u64 uword
Definition: types.h:112
void vlib_trace_frame_buffers_only(vlib_main_t *vm, vlib_node_runtime_t *node, u32 *buffers, uword n_buffers, uword next_buffer_stride, uword n_buffer_data_bytes_in_trace)
Definition: trace.c:45
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:251
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:163
u8 data[0]
Packet data.
Definition: buffer.h:151
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:69