FD.io VPP  v21.06-3-gbb25fbf28
Vector Packet Processing
nsh_pop.c
Go to the documentation of this file.
1 /*
2  * nsh_pop.c - nsh POP only processing
3  *
4  * Copyright (c) 2017 Cisco and/or its affiliates.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include <vnet/vnet.h>
19 #include <vnet/plugin/plugin.h>
20 #include <nsh/nsh.h>
21 #include <vnet/gre/packet.h>
22 #include <vnet/vxlan/vxlan.h>
24 #include <vnet/l2/l2_classify.h>
25 
26 #include <vlibapi/api.h>
27 #include <vlibmemory/api.h>
28 
30 
31 extern u8 * format_nsh_header (u8 * s, va_list * args);
32 extern u8 * format_nsh_node_map_trace (u8 * s, va_list * args);
33 extern u8 * format_nsh_pop_header (u8 * s, va_list * args);
34 extern u8 * format_nsh_pop_node_map_trace (u8 * s, va_list * args);
35 
36 static uword
40 {
41  u32 n_left_from, next_index, *from, *to_next;
42  nsh_main_t * nm = &nsh_main;
43 
45  n_left_from = from_frame->n_vectors;
46 
47  next_index = node->cached_next_index;
48 
49  while (n_left_from > 0)
50  {
51  u32 n_left_to_next;
52 
53  vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
54 
55  while (n_left_from >= 4 && n_left_to_next >= 2)
56  {
57  u32 bi0, bi1;
58  vlib_buffer_t * b0, *b1;
59  u32 next0 = NSH_NODE_NEXT_DROP, next1 = NSH_NODE_NEXT_DROP;
60  uword * entry0, *entry1;
61  nsh_base_header_t * hdr0 = 0, *hdr1 = 0;
62  u32 header_len0 = 0, header_len1 = 0;
63  u32 nsp_nsi0, nsp_nsi1;
64  u32 error0, error1;
65  nsh_map_t * map0 = 0, *map1 = 0;
66 
67  /* Prefetch next iteration. */
68  {
69  vlib_buffer_t * p2, *p3;
70 
71  p2 = vlib_get_buffer(vm, from[2]);
72  p3 = vlib_get_buffer(vm, from[3]);
73 
76 
79  }
80 
81  bi0 = from[0];
82  bi1 = from[1];
83  to_next[0] = bi0;
84  to_next[1] = bi1;
85  from += 2;
86  to_next += 2;
87  n_left_from -= 2;
88  n_left_to_next -= 2;
89 
90  error0 = 0;
91  error1 = 0;
92 
93  b0 = vlib_get_buffer(vm, bi0);
94  b1 = vlib_get_buffer(vm, bi1);
95  hdr0 = vlib_buffer_get_current(b0);
96  nsp_nsi0 = hdr0->nsp_nsi;
97  header_len0 = hdr0->length * 4;
98 
99  hdr1 = vlib_buffer_get_current(b1);
100  nsp_nsi1 = hdr1->nsp_nsi;
101  header_len1 = hdr1->length * 4;
102 
103  /* Process packet 0 */
104  entry0 = hash_get_mem(nm->nsh_mapping_by_key, &nsp_nsi0);
105  if (PREDICT_FALSE(entry0 == 0))
106  {
107  error0 = NSH_NODE_ERROR_NO_MAPPING;
108  goto trace0;
109  }
110 
111  /* Entry should point to a mapping ...*/
112  map0 = pool_elt_at_index(nm->nsh_mappings, entry0[0]);
113 
114  /* set up things for next node to transmit ie which node to handle it and where */
115  next0 = map0->next_node;
116  //vnet_buffer(b0)->sw_if_index[VLIB_TX] = map0->sw_if_index;
117 
119  {
120  /* Manipulate MD2 */
121  if(PREDICT_FALSE(hdr0->md_type == 2))
122  {
123  if (PREDICT_FALSE(next0 == NSH_NODE_NEXT_DROP))
124  {
125  error0 = NSH_NODE_ERROR_INVALID_OPTIONS;
126  goto trace0;
127  }
128  //vnet_buffer(b0)->sw_if_index[VLIB_RX] = map0->sw_if_index;
129  }
130 
131  /* Pop NSH header */
132  vlib_buffer_advance(b0, (word)header_len0);
133  goto trace0;
134  }
135 
136  entry0 = hash_get_mem(nm->nsh_entry_by_key, &map0->mapped_nsp_nsi);
137  if (PREDICT_FALSE(entry0 == 0))
138  {
139  error0 = NSH_NODE_ERROR_NO_ENTRY;
140  goto trace0;
141  }
142 
143  trace0: b0->error = error0 ? node->errors[error0] : 0;
144 
145  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
146  {
147  nsh_input_trace_t *tr = vlib_add_trace(vm, node, b0, sizeof(*tr));
148  clib_memcpy_fast ( &(tr->trace_data), hdr0, (hdr0->length*4) );
149  }
150 
151  /* Process packet 1 */
152  entry1 = hash_get_mem(nm->nsh_mapping_by_key, &nsp_nsi1);
153  if (PREDICT_FALSE(entry1 == 0))
154  {
155  error1 = NSH_NODE_ERROR_NO_MAPPING;
156  goto trace1;
157  }
158 
159  /* Entry should point to a mapping ...*/
160  map1 = pool_elt_at_index(nm->nsh_mappings, entry1[0]);
161 
162  /* set up things for next node to transmit ie which node to handle it and where */
163  next1 = map1->next_node;
164  //vnet_buffer(b1)->sw_if_index[VLIB_TX] = map1->sw_if_index;
165 
166  if(PREDICT_FALSE(map1->nsh_action == NSH_ACTION_POP))
167  {
168  /* Manipulate MD2 */
169  if(PREDICT_FALSE(hdr1->md_type == 2))
170  {
171  if (PREDICT_FALSE(next1 == NSH_NODE_NEXT_DROP))
172  {
173  error1 = NSH_NODE_ERROR_INVALID_OPTIONS;
174  goto trace1;
175  }
176  //vnet_buffer(b1)->sw_if_index[VLIB_RX] = map1->sw_if_index;
177  }
178 
179  /* Pop NSH header */
180  vlib_buffer_advance(b1, (word)header_len1);
181  goto trace1;
182  }
183 
184  entry1 = hash_get_mem(nm->nsh_entry_by_key, &map1->mapped_nsp_nsi);
185  if (PREDICT_FALSE(entry1 == 0))
186  {
187  error1 = NSH_NODE_ERROR_NO_ENTRY;
188  goto trace1;
189  }
190 
191 
192  trace1: b1->error = error1 ? node->errors[error1] : 0;
193 
194  if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
195  {
196  nsh_input_trace_t *tr = vlib_add_trace(vm, node, b1, sizeof(*tr));
197  clib_memcpy_fast ( &(tr->trace_data), hdr1, (hdr1->length*4) );
198  }
199 
201  n_left_to_next, bi0, bi1, next0, next1);
202 
203  }
204 
205  while (n_left_from > 0 && n_left_to_next > 0)
206  {
207  u32 bi0 = 0;
208  vlib_buffer_t * b0 = NULL;
209  u32 next0 = NSH_NODE_NEXT_DROP;
210  uword * entry0;
211  nsh_base_header_t * hdr0 = 0;
212  u32 header_len0 = 0;
213  u32 nsp_nsi0;
214  u32 error0;
215  nsh_map_t * map0 = 0;
216 
217  bi0 = from[0];
218  to_next[0] = bi0;
219  from += 1;
220  to_next += 1;
221  n_left_from -= 1;
222  n_left_to_next -= 1;
223  error0 = 0;
224 
225  b0 = vlib_get_buffer(vm, bi0);
226  hdr0 = vlib_buffer_get_current(b0);
227 
228  nsp_nsi0 = hdr0->nsp_nsi;
229  header_len0 = hdr0->length * 4;
230 
231  entry0 = hash_get_mem(nm->nsh_mapping_by_key, &nsp_nsi0);
232 
233  if (PREDICT_FALSE(entry0 == 0))
234  {
235  error0 = NSH_NODE_ERROR_NO_MAPPING;
236  goto trace00;
237  }
238 
239  /* Entry should point to a mapping ...*/
240  map0 = pool_elt_at_index(nm->nsh_mappings, entry0[0]);
241 
242 
243  /* set up things for next node to transmit ie which node to handle it and where */
244  next0 = map0->next_node;
245  //vnet_buffer(b0)->sw_if_index[VLIB_TX] = map0->sw_if_index;
246 
248  {
249  /* Manipulate MD2 */
250  if(PREDICT_FALSE(hdr0->md_type == 2))
251  {
252  if (PREDICT_FALSE(next0 == NSH_NODE_NEXT_DROP))
253  {
254  error0 = NSH_NODE_ERROR_INVALID_OPTIONS;
255  goto trace00;
256  }
257  //vnet_buffer(b0)->sw_if_index[VLIB_RX] = map0->sw_if_index;
258  }
259 
260  /* Pop NSH header */
261  vlib_buffer_advance(b0, (word)header_len0);
262  goto trace00;
263  }
264 
265  entry0 = hash_get_mem(nm->nsh_entry_by_key, &map0->mapped_nsp_nsi);
266  if (PREDICT_FALSE(entry0 == 0))
267  {
268  error0 = NSH_NODE_ERROR_NO_ENTRY;
269  goto trace00;
270  }
271 
272  trace00: b0->error = error0 ? node->errors[error0] : 0;
273 
274  if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
275  {
276  nsh_input_trace_t *tr = vlib_add_trace(vm, node, b0, sizeof(*tr));
277  clib_memcpy_fast ( &(tr->trace_data[0]), hdr0, (hdr0->length*4) );
278  }
279 
281  n_left_to_next, bi0, next0);
282  }
283 
284  vlib_put_next_frame(vm, node, next_index, n_left_to_next);
285 
286  }
287 
288  return from_frame->n_vectors;
289 }
290 
291 /**
292  * @brief Graph processing dispatch function for NSH Input
293  *
294  * @node nsh_input
295  * @param *vm
296  * @param *node
297  * @param *from_frame
298  *
299  * @return from_frame->n_vectors
300  *
301  */
304 {
305  return nsh_pop_inline (vm, node, from_frame);
306 }
307 
308 static char * nsh_pop_node_error_strings[] = {
309 #define _(sym,string) string,
311 #undef _
312 };
313 
314 /* register nsh-input node */
316  .name = "nsh-pop",
317  .vector_size = sizeof (u32),
318  .format_trace = format_nsh_pop_node_map_trace,
319  .format_buffer = format_nsh_pop_header,
321 
323  .error_strings = nsh_pop_node_error_strings,
324 
325  .n_next_nodes = NSH_NODE_N_NEXT,
326 
327  .next_nodes = {
328 #define _(s,n) [NSH_NODE_NEXT_##s] = n,
330 #undef _
331  },
332 };
333 
api.h
vxlan.h
vlib_prefetch_buffer_header
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:231
NSH_ACTION_POP
@ NSH_ACTION_POP
Definition: nsh.h:231
next_index
nat44_ei_hairpin_src_next_t next_index
Definition: nat44_ei_hairpinning.c:412
vlib_get_buffer
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:111
nsh_input_trace_t::trace_data
u8 trace_data[256]
Definition: nsh.h:176
pool_elt_at_index
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:553
VLIB_NODE_TYPE_INTERNAL
@ VLIB_NODE_TYPE_INTERNAL
Definition: node.h:72
node
vlib_main_t vlib_node_runtime_t * node
Definition: nat44_ei.c:3047
u16
unsigned short u16
Definition: types.h:57
vm
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
api.h
from_frame
vlib_main_t vlib_node_runtime_t vlib_frame_t * from_frame
Definition: esp_encrypt.c:1328
vlib_frame_t
Definition: node.h:372
format_nsh_node_map_trace
u8 * format_nsh_node_map_trace(u8 *s, va_list *args)
Definition: nsh_cli.c:594
format_nsh_pop_header
u8 * format_nsh_pop_header(u8 *s, va_list *args)
Definition: nsh_cli.c:25
clib_memcpy_fast
static_always_inline void * clib_memcpy_fast(void *restrict dst, const void *restrict src, size_t n)
Definition: string.h:92
nsh_main_t
Definition: nsh.h:105
vxlan_gpe.h
VXLAN GPE definitions.
CLIB_PREFETCH
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:80
vlib_buffer_advance
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:276
vlib_buffer_t::error
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:145
VLIB_NODE_FN
#define VLIB_NODE_FN(node)
Definition: node.h:202
nsh_input_trace_t
Definition: nsh.h:175
nsh_md2_lookup_option
nsh_option_map_t * nsh_md2_lookup_option(u16 class, u8 type)
Definition: nsh.c:88
PREDICT_FALSE
#define PREDICT_FALSE(x)
Definition: clib.h:124
nsh_map_t::next_node
u32 next_node
Definition: nsh.h:84
ARRAY_LEN
#define ARRAY_LEN(x)
Definition: clib.h:70
vlib_frame_vector_args
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:301
nsh_pop_node
vlib_node_registration_t nsh_pop_node
(constructor) VLIB_REGISTER_NODE (nsh_pop_node)
Definition: nsh_pop.c:315
nsh_pop_node_error_strings
static char * nsh_pop_node_error_strings[]
Definition: nsh_pop.c:308
packet.h
uword
u64 uword
Definition: types.h:112
nsh_map_t
Definition: nsh.h:59
nsh_map_t::nsh_action
u32 nsh_action
Definition: nsh.h:74
CLIB_CACHE_LINE_BYTES
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
vlib_node_registration_t
struct _vlib_node_registration vlib_node_registration_t
plugin.h
vlib_validate_buffer_enqueue_x1
#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:224
hash_get_mem
#define hash_get_mem(h, key)
Definition: hash.h:269
nsh_main
nsh_main_t nsh_main
Definition: nsh.c:28
nsh_pop_inline
static uword nsh_pop_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Definition: nsh_pop.c:37
nsh.h
vlib_put_next_frame
vlib_put_next_frame(vm, node, next_index, 0)
u32
unsigned int u32
Definition: types.h:88
l2_classify.h
nm
nat44_ei_main_t * nm
Definition: nat44_ei_hairpinning.c:413
vlib_main_t
Definition: main.h:102
vlib_add_trace
void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace.c:628
u8
unsigned char u8
Definition: types.h:56
vlib_buffer_get_current
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:257
vlib_buffer_t::data
u8 data[]
Packet data.
Definition: buffer.h:204
format_nsh_header
u8 * format_nsh_header(u8 *s, va_list *args)
Definition: nsh_cli.c:509
nsh_map_t::mapped_nsp_nsi
u32 mapped_nsp_nsi
Key for nsh_header_t entry to map to.
Definition: nsh.h:72
foreach_nsh_node_next
#define foreach_nsh_node_next
Definition: nsh.h:208
foreach_nsh_node_error
#define foreach_nsh_node_error
Definition: nsh.h:191
word
i64 word
Definition: types.h:111
NSH_NODE_N_NEXT
@ NSH_NODE_N_NEXT
Definition: nsh.h:225
vlib_validate_buffer_enqueue_x2
#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
nsh_option_map_t
Definition: nsh.h:28
vnet.h
vlib_node_runtime_t
Definition: node.h:454
format_nsh_pop_node_map_trace
u8 * format_nsh_pop_node_map_trace(u8 *s, va_list *args)
Definition: nsh_cli.c:31
from
from
Definition: nat44_ei_hairpinning.c:415
vlib_get_next_frame
#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:395
n_left_from
n_left_from
Definition: nat44_ei_hairpinning.c:416
type
vl_api_fib_path_type_t type
Definition: fib_types.api:123
vlib_buffer_t::flags
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index,...
Definition: buffer.h:133
vlib_buffer_t
VLIB buffer representation.
Definition: buffer.h:111
VLIB_REGISTER_NODE
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169