2 * nsh_node.c - nsh nodes
4 * Copyright (c) 2013 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:
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include <vnet/vnet.h>
19 #include <vnet/plugin/plugin.h>
23 nsh_md2_encap (vlib_buffer_t * b, nsh_base_header_t * hdr,
24 nsh_entry_t * nsh_entry)
26 nsh_main_t *nm = &nsh_main;
27 nsh_base_header_t *nsh_base;
28 nsh_tlv_header_t *opt0;
29 nsh_tlv_header_t *limit0;
30 nsh_tlv_header_t *nsh_md2;
31 nsh_option_map_t *nsh_option;
32 u8 old_option_size = 0;
33 u8 new_option_size = 0;
35 /* Populate the NSH Header */
36 opt0 = (nsh_tlv_header_t *) (nsh_entry->tlvs_data);
37 limit0 = (nsh_tlv_header_t *) (nsh_entry->tlvs_data + nsh_entry->tlvs_len);
39 nsh_md2 = (nsh_tlv_header_t *) ((u8 *) hdr /*nsh_entry->rewrite */ +
40 sizeof (nsh_base_header_t));
41 nsh_entry->rewrite_size = sizeof (nsh_base_header_t);
43 /* Scan the set of variable metadata, process ones that we understand */
46 old_option_size = sizeof (nsh_tlv_header_t) + opt0->length;
48 old_option_size = ((old_option_size + 3) >> 2) << 2;
50 nsh_option = nsh_md2_lookup_option (opt0->class, opt0->type);
51 if (nsh_option == NULL)
56 if (nm->options[nsh_option->option_id])
58 if ((*nm->options[nsh_option->option_id]) (b, nsh_md2))
63 /* option length may be varied */
64 new_option_size = sizeof (nsh_tlv_header_t) + nsh_md2->length;
66 new_option_size = ((new_option_size + 3) >> 2) << 2;
67 nsh_entry->rewrite_size += new_option_size;
69 nsh_md2 = (nsh_tlv_header_t *) (((u8 *) nsh_md2) + new_option_size);
70 opt0 = (nsh_tlv_header_t *) (((u8 *) opt0) + old_option_size);
76 opt0 = (nsh_tlv_header_t *) (((u8 *) opt0) + old_option_size);
80 /* update nsh header's length */
81 nsh_base = (nsh_base_header_t *) nsh_entry->rewrite;
82 nsh_base->length = (nsh_base->length & NSH_TTL_L2_MASK) |
83 ((nsh_entry->rewrite_size >> 2) & NSH_LEN_MASK);
88 nsh_md2_swap (vlib_buffer_t * b,
89 nsh_base_header_t * hdr,
91 nsh_entry_t * nsh_entry, u32 * next, u32 drop_node_val)
93 nsh_main_t *nm = &nsh_main;
94 nsh_base_header_t *nsh_base;
95 nsh_tlv_header_t *opt0;
96 nsh_tlv_header_t *limit0;
97 nsh_tlv_header_t *nsh_md2;
98 nsh_option_map_t *nsh_option;
99 u8 old_option_size = 0;
100 u8 new_option_size = 0;
102 /* Populate the NSH Header */
103 opt0 = (nsh_md2_data_t *) (hdr + 1);
104 limit0 = (nsh_md2_data_t *) ((u8 *) hdr + header_len);
107 (nsh_tlv_header_t *) (nsh_entry->rewrite + sizeof (nsh_base_header_t));
108 nsh_entry->rewrite_size = sizeof (nsh_base_header_t);
110 /* Scan the set of variable metadata, process ones that we understand */
111 while (opt0 < limit0)
113 old_option_size = sizeof (nsh_tlv_header_t) + opt0->length;
114 /* round to 4-byte */
115 old_option_size = ((old_option_size + 3) >> 2) << 2;
117 nsh_option = nsh_md2_lookup_option (opt0->class, opt0->type);
118 if (nsh_option == NULL)
123 if (nm->swap_options[nsh_option->option_id])
125 if ((*nm->swap_options[nsh_option->option_id]) (b, opt0, nsh_md2))
130 /* option length may be varied */
131 new_option_size = sizeof (nsh_tlv_header_t) + nsh_md2->length;
132 /* round to 4-byte */
133 new_option_size = ((new_option_size + 3) >> 2) << 2;
134 nsh_entry->rewrite_size += new_option_size;
135 nsh_md2 = (nsh_tlv_header_t *) (((u8 *) nsh_md2) + new_option_size);
137 opt0 = (nsh_tlv_header_t *) (((u8 *) opt0) + old_option_size);
143 opt0 = (nsh_tlv_header_t *) (((u8 *) opt0) + old_option_size);
147 /* update nsh header's length */
148 nsh_base = (nsh_base_header_t *) nsh_entry->rewrite;
149 nsh_base->length = (nsh_base->length & NSH_TTL_L2_MASK) |
150 ((nsh_entry->rewrite_size >> 2) & NSH_LEN_MASK);
155 nsh_md2_decap (vlib_buffer_t * b,
156 nsh_base_header_t * hdr,
157 u32 * header_len, u32 * next, u32 drop_node_val)
159 nsh_main_t *nm = &nsh_main;
160 nsh_md2_data_t *opt0;
161 nsh_md2_data_t *limit0;
162 nsh_option_map_t *nsh_option;
165 /* Populate the NSH Header */
166 opt0 = (nsh_md2_data_t *) (hdr + 1);
167 limit0 = (nsh_md2_data_t *) ((u8 *) hdr + *header_len);
169 /* Scan the set of variable metadata, process ones that we understand */
170 while (opt0 < limit0)
172 nsh_option = nsh_md2_lookup_option (opt0->class, opt0->type);
173 if (nsh_option == NULL)
175 *next = drop_node_val;
179 if (nm->pop_options[nsh_option->option_id])
181 if ((*nm->pop_options[nsh_option->option_id]) (b, opt0))
183 *next = drop_node_val;
187 /* round to 4-byte */
188 option_len = ((opt0->length + 3) >> 2) << 2;
190 (nsh_md2_data_t *) (((u8 *) opt0) + sizeof (nsh_md2_data_t) +
193 (nm->decap_v4_next_override) ? (nm->decap_v4_next_override) : (*next);
194 *header_len = (nm->decap_v4_next_override) ? 0 : (*header_len);
201 nsh_input_map (vlib_main_t * vm,
202 vlib_node_runtime_t * node,
203 vlib_frame_t * from_frame, u32 node_type)
205 u32 n_left_from, next_index, *from, *to_next;
206 nsh_main_t *nm = &nsh_main;
208 from = vlib_frame_vector_args (from_frame);
209 n_left_from = from_frame->n_vectors;
211 next_index = node->cached_next_index;
213 while (n_left_from > 0)
217 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
219 while (n_left_from >= 4 && n_left_to_next >= 2)
222 vlib_buffer_t *b0, *b1;
223 u32 next0 = NSH_NODE_NEXT_DROP, next1 = NSH_NODE_NEXT_DROP;
224 uword *entry0, *entry1;
225 nsh_base_header_t *hdr0 = 0, *hdr1 = 0;
226 u32 header_len0 = 0, header_len1 = 0;
227 u32 nsp_nsi0, nsp_nsi1;
230 nsh_map_t *map0 = 0, *map1 = 0;
231 nsh_entry_t *nsh_entry0 = 0, *nsh_entry1 = 0;
232 nsh_base_header_t *encap_hdr0 = 0, *encap_hdr1 = 0;
233 u32 encap_hdr_len0 = 0, encap_hdr_len1 = 0;
234 nsh_proxy_session_by_key_t key0, key1;
236 nsh_proxy_session_t *proxy0, *proxy1;
237 u32 sw_if_index0 = 0, sw_if_index1 = 0;
238 ethernet_header_t placeholder_eth0, placeholder_eth1;
240 /* Prefetch next iteration. */
242 vlib_buffer_t *p2, *p3;
244 p2 = vlib_get_buffer (vm, from[2]);
245 p3 = vlib_get_buffer (vm, from[3]);
247 vlib_prefetch_buffer_header (p2, LOAD);
248 vlib_prefetch_buffer_header (p3, LOAD);
250 CLIB_PREFETCH (p2->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
251 CLIB_PREFETCH (p3->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
266 b0 = vlib_get_buffer (vm, bi0);
267 b1 = vlib_get_buffer (vm, bi1);
268 hdr0 = vlib_buffer_get_current (b0);
269 hdr1 = vlib_buffer_get_current (b1);
271 /* Process packet 0 */
272 if (node_type == NSH_INPUT_TYPE)
274 nsp_nsi0 = hdr0->nsp_nsi;
275 header_len0 = (hdr0->length & NSH_LEN_MASK) * 4;
276 ttl0 = (hdr0->ver_o_c & NSH_TTL_H4_MASK) << 2 |
277 (hdr0->length & NSH_TTL_L2_MASK) >> 6;
279 if (PREDICT_FALSE (ttl0 == 0))
281 error0 = NSH_NODE_ERROR_INVALID_TTL;
285 else if (node_type == NSH_CLASSIFIER_TYPE)
288 clib_host_to_net_u32 (vnet_buffer (b0)->
289 l2_classify.opaque_index);
291 else if (node_type == NSH_AWARE_VNF_PROXY_TYPE)
293 /* Push placeholder Eth header */
294 char placeholder_dst_address[6] =
295 { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 };
296 char placeholder_src_address[6] =
297 { 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc };
298 clib_memcpy_fast (placeholder_eth0.dst_address,
299 placeholder_dst_address, 6);
300 clib_memcpy_fast (placeholder_eth0.src_address,
301 placeholder_src_address, 6);
302 placeholder_eth0.type = 0x0800;
303 vlib_buffer_advance (b0, -(word) sizeof (ethernet_header_t));
304 hdr0 = vlib_buffer_get_current (b0);
305 clib_memcpy_fast (hdr0, &placeholder_eth0,
306 (word) sizeof (ethernet_header_t));
308 sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_TX];
309 nsp_nsi0 = nm->tunnel_index_by_sw_if_index[sw_if_index0];
313 clib_memset (&key0, 0, sizeof (key0));
314 key0.transport_type = NSH_NODE_NEXT_ENCAP_VXLAN4;
315 key0.transport_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
317 p0 = hash_get_mem (nm->nsh_proxy_session_by_key, &key0);
318 if (PREDICT_FALSE (p0 == 0))
320 error0 = NSH_NODE_ERROR_NO_PROXY;
324 proxy0 = pool_elt_at_index (nm->nsh_proxy_sessions, p0[0]);
325 if (PREDICT_FALSE (proxy0 == 0))
327 error0 = NSH_NODE_ERROR_NO_PROXY;
330 nsp_nsi0 = proxy0->nsp_nsi;
333 entry0 = hash_get_mem (nm->nsh_mapping_by_key, &nsp_nsi0);
334 if (PREDICT_FALSE (entry0 == 0))
336 error0 = NSH_NODE_ERROR_NO_MAPPING;
340 /* Entry should point to a mapping ... */
341 map0 = pool_elt_at_index (nm->nsh_mappings, entry0[0]);
342 if (PREDICT_FALSE (map0 == 0))
344 error0 = NSH_NODE_ERROR_NO_MAPPING;
348 /* set up things for next node to transmit ie which node to handle it and where */
349 next0 = map0->next_node;
350 vnet_buffer (b0)->sw_if_index[VLIB_TX] = map0->sw_if_index;
351 vnet_buffer (b0)->ip.adj_index[VLIB_TX] = map0->adj_index;
353 if (PREDICT_FALSE (map0->nsh_action == NSH_ACTION_POP))
356 if (PREDICT_FALSE (hdr0->md_type == 2))
358 nsh_md2_decap (b0, hdr0, &header_len0, &next0,
360 if (PREDICT_FALSE (next0 == NSH_NODE_NEXT_DROP))
362 error0 = NSH_NODE_ERROR_INVALID_OPTIONS;
365 vnet_buffer (b0)->sw_if_index[VLIB_RX] =
366 map0->rx_sw_if_index;
370 vlib_buffer_advance (b0, (word) header_len0);
374 entry0 = hash_get_mem (nm->nsh_entry_by_key, &map0->mapped_nsp_nsi);
375 if (PREDICT_FALSE (entry0 == 0))
377 error0 = NSH_NODE_ERROR_NO_ENTRY;
382 (nsh_entry_t *) pool_elt_at_index (nm->nsh_entries, entry0[0]);
383 encap_hdr0 = (nsh_base_header_t *) (nsh_entry0->rewrite);
384 /* rewrite_size should equal to (encap_hdr0->length * 4) */
385 encap_hdr_len0 = nsh_entry0->rewrite_size;
387 if (PREDICT_TRUE (map0->nsh_action == NSH_ACTION_SWAP))
390 if (PREDICT_FALSE (hdr0->md_type == 2))
392 nsh_md2_swap (b0, hdr0, header_len0, nsh_entry0,
393 &next0, NSH_NODE_NEXT_DROP);
394 if (PREDICT_FALSE (next0 == NSH_NODE_NEXT_DROP))
396 error0 = NSH_NODE_ERROR_INVALID_OPTIONS;
401 /* Pop old NSH header */
402 vlib_buffer_advance (b0, (word) header_len0);
404 /* After processing, md2's length may be varied */
405 encap_hdr_len0 = nsh_entry0->rewrite_size;
406 /* Push new NSH header */
407 vlib_buffer_advance (b0, -(word) encap_hdr_len0);
408 hdr0 = vlib_buffer_get_current (b0);
409 clib_memcpy_fast (hdr0, encap_hdr0, (word) encap_hdr_len0);
414 if (PREDICT_TRUE (map0->nsh_action == NSH_ACTION_PUSH))
416 /* After processing, md2's length may be varied */
417 encap_hdr_len0 = nsh_entry0->rewrite_size;
418 /* Push new NSH header */
419 vlib_buffer_advance (b0, -(word) encap_hdr_len0);
420 hdr0 = vlib_buffer_get_current (b0);
421 clib_memcpy_fast (hdr0, encap_hdr0, (word) encap_hdr_len0);
424 if (PREDICT_FALSE (nsh_entry0->nsh_base.md_type == 2))
426 nsh_md2_encap (b0, hdr0, nsh_entry0);
432 b0->error = error0 ? node->errors[error0] : 0;
434 if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
436 nsh_input_trace_t *tr =
437 vlib_add_trace (vm, node, b0, sizeof (*tr));
438 clib_memcpy_fast (&(tr->trace_data), hdr0,
439 ((hdr0->length & NSH_LEN_MASK) * 4));
442 /* Process packet 1 */
443 if (node_type == NSH_INPUT_TYPE)
445 nsp_nsi1 = hdr1->nsp_nsi;
446 header_len1 = (hdr1->length & NSH_LEN_MASK) * 4;
447 ttl1 = (hdr1->ver_o_c & NSH_TTL_H4_MASK) << 2 |
448 (hdr1->length & NSH_TTL_L2_MASK) >> 6;
450 if (PREDICT_FALSE (ttl1 == 0))
452 error1 = NSH_NODE_ERROR_INVALID_TTL;
456 else if (node_type == NSH_CLASSIFIER_TYPE)
459 clib_host_to_net_u32 (vnet_buffer (b1)->
460 l2_classify.opaque_index);
462 else if (node_type == NSH_AWARE_VNF_PROXY_TYPE)
464 /* Push placeholder Eth header */
465 char placeholder_dst_address[6] =
466 { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 };
467 char placeholder_src_address[6] =
468 { 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc };
469 clib_memcpy_fast (placeholder_eth1.dst_address,
470 placeholder_dst_address, 6);
471 clib_memcpy_fast (placeholder_eth1.src_address,
472 placeholder_src_address, 6);
473 placeholder_eth1.type = 0x0800;
474 vlib_buffer_advance (b1, -(word) sizeof (ethernet_header_t));
475 hdr1 = vlib_buffer_get_current (b1);
476 clib_memcpy_fast (hdr1, &placeholder_eth1,
477 (word) sizeof (ethernet_header_t));
479 sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_TX];
480 nsp_nsi1 = nm->tunnel_index_by_sw_if_index[sw_if_index1];
484 clib_memset (&key1, 0, sizeof (key1));
485 key1.transport_type = NSH_NODE_NEXT_ENCAP_VXLAN4;
486 key1.transport_index = vnet_buffer (b1)->sw_if_index[VLIB_RX];
488 p1 = hash_get_mem (nm->nsh_proxy_session_by_key, &key1);
489 if (PREDICT_FALSE (p1 == 0))
491 error1 = NSH_NODE_ERROR_NO_PROXY;
495 proxy1 = pool_elt_at_index (nm->nsh_proxy_sessions, p1[0]);
496 if (PREDICT_FALSE (proxy1 == 0))
498 error1 = NSH_NODE_ERROR_NO_PROXY;
501 nsp_nsi1 = proxy1->nsp_nsi;
504 entry1 = hash_get_mem (nm->nsh_mapping_by_key, &nsp_nsi1);
505 if (PREDICT_FALSE (entry1 == 0))
507 error1 = NSH_NODE_ERROR_NO_MAPPING;
511 /* Entry should point to a mapping ... */
512 map1 = pool_elt_at_index (nm->nsh_mappings, entry1[0]);
513 if (PREDICT_FALSE (map1 == 0))
515 error1 = NSH_NODE_ERROR_NO_MAPPING;
519 /* set up things for next node to transmit ie which node to handle it and where */
520 next1 = map1->next_node;
521 vnet_buffer (b1)->sw_if_index[VLIB_TX] = map1->sw_if_index;
522 vnet_buffer (b1)->ip.adj_index[VLIB_TX] = map1->adj_index;
524 if (PREDICT_FALSE (map1->nsh_action == NSH_ACTION_POP))
527 if (PREDICT_FALSE (hdr1->md_type == 2))
529 nsh_md2_decap (b1, hdr1, &header_len1, &next1,
531 if (PREDICT_FALSE (next1 == NSH_NODE_NEXT_DROP))
533 error1 = NSH_NODE_ERROR_INVALID_OPTIONS;
536 vnet_buffer (b1)->sw_if_index[VLIB_RX] =
537 map1->rx_sw_if_index;
541 vlib_buffer_advance (b1, (word) header_len1);
545 entry1 = hash_get_mem (nm->nsh_entry_by_key, &map1->mapped_nsp_nsi);
546 if (PREDICT_FALSE (entry1 == 0))
548 error1 = NSH_NODE_ERROR_NO_ENTRY;
553 (nsh_entry_t *) pool_elt_at_index (nm->nsh_entries, entry1[0]);
554 encap_hdr1 = (nsh_base_header_t *) (nsh_entry1->rewrite);
555 /* rewrite_size should equal to (encap_hdr0->length * 4) */
556 encap_hdr_len1 = nsh_entry1->rewrite_size;
558 if (PREDICT_TRUE (map1->nsh_action == NSH_ACTION_SWAP))
561 if (PREDICT_FALSE (hdr1->md_type == 2))
563 nsh_md2_swap (b1, hdr1, header_len1, nsh_entry1,
564 &next1, NSH_NODE_NEXT_DROP);
565 if (PREDICT_FALSE (next1 == NSH_NODE_NEXT_DROP))
567 error1 = NSH_NODE_ERROR_INVALID_OPTIONS;
572 /* Pop old NSH header */
573 vlib_buffer_advance (b1, (word) header_len1);
575 /* After processing, md2's length may be varied */
576 encap_hdr_len1 = nsh_entry1->rewrite_size;
577 /* Push new NSH header */
578 vlib_buffer_advance (b1, -(word) encap_hdr_len1);
579 hdr1 = vlib_buffer_get_current (b1);
580 clib_memcpy_fast (hdr1, encap_hdr1, (word) encap_hdr_len1);
585 if (PREDICT_FALSE (map1->nsh_action == NSH_ACTION_PUSH))
587 /* After processing, md2's length may be varied */
588 encap_hdr_len1 = nsh_entry1->rewrite_size;
589 /* Push new NSH header */
590 vlib_buffer_advance (b1, -(word) encap_hdr_len1);
591 hdr1 = vlib_buffer_get_current (b1);
592 clib_memcpy_fast (hdr1, encap_hdr1, (word) encap_hdr_len1);
595 if (PREDICT_FALSE (nsh_entry1->nsh_base.md_type == 2))
597 nsh_md2_encap (b1, hdr1, nsh_entry1);
603 b1->error = error1 ? node->errors[error1] : 0;
605 if (PREDICT_FALSE (b1->flags & VLIB_BUFFER_IS_TRACED))
607 nsh_input_trace_t *tr =
608 vlib_add_trace (vm, node, b1, sizeof (*tr));
609 clib_memcpy_fast (&(tr->trace_data), hdr1,
610 ((hdr1->length & NSH_LEN_MASK) * 4));
613 vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
614 n_left_to_next, bi0, bi1, next0,
619 while (n_left_from > 0 && n_left_to_next > 0)
622 vlib_buffer_t *b0 = NULL;
623 u32 next0 = NSH_NODE_NEXT_DROP;
625 nsh_base_header_t *hdr0 = 0;
631 nsh_entry_t *nsh_entry0 = 0;
632 nsh_base_header_t *encap_hdr0 = 0;
633 u32 encap_hdr_len0 = 0;
634 nsh_proxy_session_by_key_t key0;
636 nsh_proxy_session_t *proxy0 = 0;
637 u32 sw_if_index0 = 0;
638 ethernet_header_t placeholder_eth0;
648 b0 = vlib_get_buffer (vm, bi0);
649 hdr0 = vlib_buffer_get_current (b0);
651 if (node_type == NSH_INPUT_TYPE)
653 nsp_nsi0 = hdr0->nsp_nsi;
654 header_len0 = (hdr0->length & NSH_LEN_MASK) * 4;
655 ttl0 = (hdr0->ver_o_c & NSH_TTL_H4_MASK) << 2 |
656 (hdr0->length & NSH_TTL_L2_MASK) >> 6;
658 if (PREDICT_FALSE (ttl0 == 0))
660 error0 = NSH_NODE_ERROR_INVALID_TTL;
664 else if (node_type == NSH_CLASSIFIER_TYPE)
667 clib_host_to_net_u32 (vnet_buffer (b0)->
668 l2_classify.opaque_index);
670 else if (node_type == NSH_AWARE_VNF_PROXY_TYPE)
672 /* Push placeholder Eth header */
673 char placeholder_dst_address[6] =
674 { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 };
675 char placeholder_src_address[6] =
676 { 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc };
677 clib_memcpy_fast (placeholder_eth0.dst_address,
678 placeholder_dst_address, 6);
679 clib_memcpy_fast (placeholder_eth0.src_address,
680 placeholder_src_address, 6);
681 placeholder_eth0.type = 0x0800;
682 vlib_buffer_advance (b0, -(word) sizeof (ethernet_header_t));
683 hdr0 = vlib_buffer_get_current (b0);
684 clib_memcpy_fast (hdr0, &placeholder_eth0,
685 (word) sizeof (ethernet_header_t));
687 sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_TX];
688 nsp_nsi0 = nm->tunnel_index_by_sw_if_index[sw_if_index0];
692 clib_memset (&key0, 0, sizeof (key0));
693 key0.transport_type = NSH_NODE_NEXT_ENCAP_VXLAN4;
694 key0.transport_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
696 p0 = hash_get_mem (nm->nsh_proxy_session_by_key, &key0);
697 if (PREDICT_FALSE (p0 == 0))
699 error0 = NSH_NODE_ERROR_NO_PROXY;
703 proxy0 = pool_elt_at_index (nm->nsh_proxy_sessions, p0[0]);
704 if (PREDICT_FALSE (proxy0 == 0))
706 error0 = NSH_NODE_ERROR_NO_PROXY;
709 nsp_nsi0 = proxy0->nsp_nsi;
712 entry0 = hash_get_mem (nm->nsh_mapping_by_key, &nsp_nsi0);
714 if (PREDICT_FALSE (entry0 == 0))
716 error0 = NSH_NODE_ERROR_NO_MAPPING;
720 /* Entry should point to a mapping ... */
721 map0 = pool_elt_at_index (nm->nsh_mappings, entry0[0]);
723 if (PREDICT_FALSE (map0 == 0))
725 error0 = NSH_NODE_ERROR_NO_MAPPING;
729 /* set up things for next node to transmit ie which node to handle it and where */
730 next0 = map0->next_node;
731 vnet_buffer (b0)->sw_if_index[VLIB_TX] = map0->sw_if_index;
732 vnet_buffer (b0)->ip.adj_index[VLIB_TX] = map0->adj_index;
733 vnet_buffer (b0)->sw_if_index[VLIB_RX] = map0->nsh_sw_if;
735 if (PREDICT_FALSE (map0->nsh_action == NSH_ACTION_POP))
738 if (PREDICT_FALSE (hdr0->md_type == 2))
740 nsh_md2_decap (b0, hdr0, &header_len0, &next0,
742 if (PREDICT_FALSE (next0 == NSH_NODE_NEXT_DROP))
744 error0 = NSH_NODE_ERROR_INVALID_OPTIONS;
747 vnet_buffer (b0)->sw_if_index[VLIB_RX] =
748 map0->rx_sw_if_index;
752 vlib_buffer_advance (b0, (word) header_len0);
756 entry0 = hash_get_mem (nm->nsh_entry_by_key, &map0->mapped_nsp_nsi);
757 if (PREDICT_FALSE (entry0 == 0))
759 error0 = NSH_NODE_ERROR_NO_ENTRY;
764 (nsh_entry_t *) pool_elt_at_index (nm->nsh_entries, entry0[0]);
765 encap_hdr0 = (nsh_base_header_t *) (nsh_entry0->rewrite);
766 /* rewrite_size should equal to (encap_hdr0->length * 4) */
767 encap_hdr_len0 = nsh_entry0->rewrite_size;
769 if (PREDICT_TRUE (map0->nsh_action == NSH_ACTION_SWAP))
772 if (PREDICT_FALSE (hdr0->md_type == 2))
774 nsh_md2_swap (b0, hdr0, header_len0, nsh_entry0,
775 &next0, NSH_NODE_NEXT_DROP);
776 if (PREDICT_FALSE (next0 == NSH_NODE_NEXT_DROP))
778 error0 = NSH_NODE_ERROR_INVALID_OPTIONS;
783 /* Pop old NSH header */
784 vlib_buffer_advance (b0, (word) header_len0);
786 /* After processing, md2's length may be varied */
787 encap_hdr_len0 = nsh_entry0->rewrite_size;
788 /* Push new NSH header */
789 vlib_buffer_advance (b0, -(word) encap_hdr_len0);
790 hdr0 = vlib_buffer_get_current (b0);
791 clib_memcpy_fast (hdr0, encap_hdr0, (word) encap_hdr_len0);
796 if (PREDICT_TRUE (map0->nsh_action == NSH_ACTION_PUSH))
798 /* After processing, md2's length may be varied */
799 encap_hdr_len0 = nsh_entry0->rewrite_size;
800 /* Push new NSH header */
801 vlib_buffer_advance (b0, -(word) encap_hdr_len0);
802 hdr0 = vlib_buffer_get_current (b0);
803 clib_memcpy_fast (hdr0, encap_hdr0, (word) encap_hdr_len0);
805 if (PREDICT_FALSE (nsh_entry0->nsh_base.md_type == 2))
807 nsh_md2_encap (b0, hdr0, nsh_entry0);
812 trace00:b0->error = error0 ? node->errors[error0] : 0;
814 if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
816 nsh_input_trace_t *tr =
817 vlib_add_trace (vm, node, b0, sizeof (*tr));
818 clib_memcpy_fast (&(tr->trace_data[0]), hdr0,
819 ((hdr0->length & NSH_LEN_MASK) * 4));
822 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
823 n_left_to_next, bi0, next0);
826 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
830 return from_frame->n_vectors;
834 * @brief Graph processing dispatch function for NSH Input
841 * @return from_frame->n_vectors
844 VLIB_NODE_FN (nsh_input_node) (vlib_main_t * vm, vlib_node_runtime_t * node,
845 vlib_frame_t * from_frame)
847 return nsh_input_map (vm, node, from_frame, NSH_INPUT_TYPE);
851 * @brief Graph processing dispatch function for NSH-Proxy
858 * @return from_frame->n_vectors
861 VLIB_NODE_FN (nsh_proxy_node) (vlib_main_t * vm, vlib_node_runtime_t * node,
862 vlib_frame_t * from_frame)
864 return nsh_input_map (vm, node, from_frame, NSH_PROXY_TYPE);
868 * @brief Graph processing dispatch function for NSH Classifier
870 * @node nsh_classifier
875 * @return from_frame->n_vectors
878 VLIB_NODE_FN (nsh_classifier_node) (vlib_main_t * vm,
879 vlib_node_runtime_t * node,
880 vlib_frame_t * from_frame)
882 return nsh_input_map (vm, node, from_frame, NSH_CLASSIFIER_TYPE);
886 * @brief Graph processing dispatch function for NSH-AWARE-VNF-PROXY
888 * @node nsh_aware_vnf_proxy
893 * @return from_frame->n_vectors
896 VLIB_NODE_FN (nsh_aware_vnf_proxy_node) (vlib_main_t * vm,
897 vlib_node_runtime_t * node,
898 vlib_frame_t * from_frame)
900 return nsh_input_map (vm, node, from_frame, NSH_AWARE_VNF_PROXY_TYPE);
903 static char *nsh_node_error_strings[] = {
904 #define _(sym,string) string,
905 foreach_nsh_node_error
911 /* register nsh-input node */
912 VLIB_REGISTER_NODE (nsh_input_node) = {
914 .vector_size = sizeof (u32),
915 .format_trace = format_nsh_node_map_trace,
916 .format_buffer = format_nsh_header,
917 .type = VLIB_NODE_TYPE_INTERNAL,
918 .n_errors = ARRAY_LEN (nsh_node_error_strings),
919 .error_strings = nsh_node_error_strings,
920 .n_next_nodes = NSH_NODE_N_NEXT,
922 #define _(s,n) [NSH_NODE_NEXT_##s] = n,
923 foreach_nsh_node_next
928 /* register nsh-proxy node */
929 VLIB_REGISTER_NODE (nsh_proxy_node) =
932 .vector_size = sizeof (u32),
933 .format_trace = format_nsh_node_map_trace,
934 .format_buffer = format_nsh_header,
935 .type = VLIB_NODE_TYPE_INTERNAL,
936 .n_errors = ARRAY_LEN (nsh_node_error_strings),
937 .error_strings = nsh_node_error_strings,
938 .n_next_nodes = NSH_NODE_N_NEXT,
940 #define _(s,n) [NSH_NODE_NEXT_##s] = n,
941 foreach_nsh_node_next
946 /* register nsh-classifier node */
947 VLIB_REGISTER_NODE (nsh_classifier_node) =
949 .name = "nsh-classifier",
950 .vector_size = sizeof (u32),
951 .format_trace = format_nsh_node_map_trace,
952 .format_buffer = format_nsh_header,
953 .type = VLIB_NODE_TYPE_INTERNAL,
954 .n_errors = ARRAY_LEN (nsh_node_error_strings),
955 .error_strings = nsh_node_error_strings,
956 .n_next_nodes = NSH_NODE_N_NEXT,
958 #define _(s,n) [NSH_NODE_NEXT_##s] = n,
959 foreach_nsh_node_next
964 /* register nsh-aware-vnf-proxy node */
965 VLIB_REGISTER_NODE (nsh_aware_vnf_proxy_node) =
967 .name = "nsh-aware-vnf-proxy",
968 .vector_size = sizeof (u32),
969 .format_trace = format_nsh_node_map_trace,
970 .format_buffer = format_nsh_header,
971 .type = VLIB_NODE_TYPE_INTERNAL,
972 .n_errors = ARRAY_LEN (nsh_node_error_strings),
973 .error_strings = nsh_node_error_strings,
974 .n_next_nodes = NSH_NODE_N_NEXT,
976 #define _(s,n) [NSH_NODE_NEXT_##s] = n,
977 foreach_nsh_node_next
984 * fd.io coding-style-patch-verification: ON
987 * eval: (c-set-style "gnu")