-/**
- * Action function for adding an NSH entry
- * nsh_add_del_entry_args_t *a: host order
- */
-
-int
-nsh_add_del_entry (nsh_add_del_entry_args_t * a, u32 * entry_indexp)
-{
- nsh_main_t *nm = &nsh_main;
- nsh_entry_t *nsh_entry = 0;
- u32 key, *key_copy;
- uword *entry_id;
- hash_pair_t *hp;
- u32 entry_index = ~0;
- u8 tlvs_len = 0;
- u8 *data = 0;
-
- /* host order, because nsh map table stores nsp_nsi in host order */
- key = a->nsh_entry.nsh_base.nsp_nsi;
-
- entry_id = hash_get_mem (nm->nsh_entry_by_key, &key);
-
- if (a->is_add)
- {
- /* adding an entry, must not already exist */
- if (entry_id)
- return -1; // TODO VNET_API_ERROR_INVALID_VALUE;
-
- pool_get_aligned (nm->nsh_entries, nsh_entry, CLIB_CACHE_LINE_BYTES);
- memset (nsh_entry, 0, sizeof (*nsh_entry));
-
- /* copy from arg structure */
-#define _(x) nsh_entry->nsh_base.x = a->nsh_entry.nsh_base.x;
- foreach_copy_nsh_base_hdr_field;
-#undef _
-
- if (a->nsh_entry.nsh_base.md_type == 1)
- {
- nsh_entry->md.md1_data.c1 = a->nsh_entry.md.md1_data.c1;
- nsh_entry->md.md1_data.c2 = a->nsh_entry.md.md1_data.c2;
- nsh_entry->md.md1_data.c3 = a->nsh_entry.md.md1_data.c3;
- nsh_entry->md.md1_data.c4 = a->nsh_entry.md.md1_data.c4;
- }
- else if (a->nsh_entry.nsh_base.md_type == 2)
- {
- vec_free (nsh_entry->tlvs_data);
- tlvs_len = a->nsh_entry.tlvs_len;
- vec_validate_aligned (data, tlvs_len - 1, CLIB_CACHE_LINE_BYTES);
-
- clib_memcpy (data, a->nsh_entry.tlvs_data, tlvs_len);
- nsh_entry->tlvs_data = data;
- nsh_entry->tlvs_len = tlvs_len;
- vec_free (a->nsh_entry.tlvs_data);
- }
-
- nsh_header_rewrite (nsh_entry);
-
- key_copy = clib_mem_alloc (sizeof (*key_copy));
- clib_memcpy (key_copy, &key, sizeof (*key_copy));
-
- hash_set_mem (nm->nsh_entry_by_key, key_copy,
- nsh_entry - nm->nsh_entries);
- entry_index = nsh_entry - nm->nsh_entries;
- }
- else
- {
- if (!entry_id)
- return -2; //TODO API_ERROR_NO_SUCH_ENTRY;
-
- nsh_entry = pool_elt_at_index (nm->nsh_entries, entry_id[0]);
- hp = hash_get_pair (nm->nsh_entry_by_key, &key);
- key_copy = (void *) (hp->key);
- hash_unset_mem (nm->nsh_entry_by_key, &key);
- clib_mem_free (key_copy);
-
- vec_free (nsh_entry->tlvs_data);
- vec_free (nsh_entry->rewrite);
- pool_put (nm->nsh_entries, nsh_entry);
- }
-
- if (entry_indexp)
- *entry_indexp = entry_index;
-
- return 0;
-}
-
-
-/**
- * CLI command for adding NSH entry
- */
-
-static clib_error_t *
-nsh_add_del_entry_command_fn (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- unformat_input_t _line_input, *line_input = &_line_input;
- u8 is_add = 1;
- u8 ver_o_c = 0;
- u8 ttl = 63;
- u8 length = 0;
- u8 md_type = 0;
- u8 next_protocol = 1; /* default: ip4 */
- u32 nsp;
- u8 nsp_set = 0;
- u32 nsi;
- u8 nsi_set = 0;
- u32 nsp_nsi;
- u32 c1 = 0;
- u32 c2 = 0;
- u32 c3 = 0;
- u32 c4 = 0;
- u8 *data = 0;
- nsh_tlv_header_t tlv_header;
- u8 cur_len = 0, tlvs_len = 0;
- u8 *current;
- nsh_main_t *nm = &nsh_main;
- nsh_option_map_t _nsh_option, *nsh_option = &_nsh_option;
- u8 option_size = 0;
- u32 tmp;
- int rv;
- u32 entry_index;
- nsh_add_del_entry_args_t _a, *a = &_a;
- u8 has_ioam_trace_option = 0;
-
- /* Get a line of input. */
- if (!unformat_user (input, unformat_line_input, line_input))
- return 0;
-
- while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (line_input, "del"))
- is_add = 0;
- else if (unformat (line_input, "version %d", &tmp))
- ver_o_c |= (tmp & 3) << 6;
- else if (unformat (line_input, "o-bit %d", &tmp))
- ver_o_c |= (tmp & 1) << 5;
- else if (unformat (line_input, "c-bit %d", &tmp))
- ver_o_c |= (tmp & 1) << 4;
- else if (unformat (line_input, "ttl %d", &ttl))
- ver_o_c |= (ttl & NSH_LEN_MASK) >> 2;
- else if (unformat (line_input, "md-type %d", &tmp))
- md_type = tmp;
- else if (unformat (line_input, "next-ip4"))
- next_protocol = 1;
- else if (unformat (line_input, "next-ip6"))
- next_protocol = 2;
- else if (unformat (line_input, "next-ethernet"))
- next_protocol = 3;
- else if (unformat (line_input, "c1 %d", &c1))
- ;
- else if (unformat (line_input, "c2 %d", &c2))
- ;
- else if (unformat (line_input, "c3 %d", &c3))
- ;
- else if (unformat (line_input, "c4 %d", &c4))
- ;
- else if (unformat (line_input, "nsp %d", &nsp))
- nsp_set = 1;
- else if (unformat (line_input, "nsi %d", &nsi))
- nsi_set = 1;
- else if (unformat (line_input, "tlv-ioam-trace"))
- has_ioam_trace_option = 1;
- else
- return clib_error_return (0, "parse error: '%U'",
- format_unformat_error, line_input);
- }
-
- unformat_free (line_input);
-
- if (nsp_set == 0)
- return clib_error_return (0, "nsp not specified");
-
- if (nsi_set == 0)
- return clib_error_return (0, "nsi not specified");
-
- if (md_type == 1 && has_ioam_trace_option == 1)
- return clib_error_return (0, "Invalid MD Type");
-
- nsp_nsi = (nsp << 8) | nsi;
-
- memset (a, 0, sizeof (*a));
- a->is_add = is_add;
-
- if (md_type == 1)
- {
- a->nsh_entry.md.md1_data.c1 = c1;
- a->nsh_entry.md.md1_data.c2 = c2;
- a->nsh_entry.md.md1_data.c3 = c3;
- a->nsh_entry.md.md1_data.c4 = c4;
- length = (sizeof (nsh_base_header_t) + sizeof (nsh_md1_data_t)) >> 2;
- }
- else if (md_type == 2)
- {
- length = sizeof (nsh_base_header_t) >> 2;
-
- vec_free (a->nsh_entry.tlvs_data);
- tlvs_len = (MAX_METADATA_LEN << 2);
- vec_validate_aligned (data, tlvs_len - 1, CLIB_CACHE_LINE_BYTES);
- a->nsh_entry.tlvs_data = data;
- current = data;
-
- if (has_ioam_trace_option)
- {
- tlv_header.class = clib_host_to_net_u16 (NSH_MD2_IOAM_CLASS);
- tlv_header.type = NSH_MD2_IOAM_OPTION_TYPE_TRACE;
- /* Uses network order's class and type to lookup */
- nsh_option =
- nsh_md2_lookup_option (tlv_header.class, tlv_header.type);
- if (nsh_option == NULL)
- return clib_error_return (0, "iOAM Trace not registered");
-
- if (nm->add_options[nsh_option->option_id] != NULL)
- {
- if (0 != nm->add_options[nsh_option->option_id] ((u8 *) current,
- &option_size))
- {
- return clib_error_return (0, "Invalid MD Type");
- }
- }
-
- nm->options_size[nsh_option->option_id] = option_size;
- /* round to 4-byte */
- option_size = (((option_size + 3) >> 2) << 2);
-
- cur_len += option_size;
- current = data + option_size;
- }
-
- /* Add more options' parsing */
-
- a->nsh_entry.tlvs_len = cur_len;
- length += (cur_len >> 2);
- }
- length = (length & NSH_LEN_MASK) | ((ttl & 0x3) << 6);
-
-#define _(x) a->nsh_entry.nsh_base.x = x;
- foreach_copy_nsh_base_hdr_field;
-#undef _
-
- rv = nsh_add_del_entry (a, &entry_index);
-
- switch (rv)
- {
- case 0:
- break;
- default:
- return clib_error_return (0, "nsh_add_del_entry returned %d", rv);
- }
-
- return 0;
-}
-
-VLIB_CLI_COMMAND (create_nsh_entry_command, static) =
-{
-.path = "create nsh entry",.short_help =
- "create nsh entry {nsp <nn> nsi <nn>} [ttl <nn>] [md-type <nn>]"
- " [c1 <nn> c2 <nn> c3 <nn> c4 <nn>] [tlv-ioam-trace] [del]\n",.function
- = nsh_add_del_entry_command_fn,};
-
-/** API message handler */
-static void vl_api_nsh_add_del_entry_t_handler
- (vl_api_nsh_add_del_entry_t * mp)
-{
- vl_api_nsh_add_del_entry_reply_t *rmp;
- nsh_main_t *nm = &nsh_main;
- int rv;
- nsh_add_del_entry_args_t _a, *a = &_a;
- u32 entry_index = ~0;
- u8 tlvs_len = 0;
- u8 *data = 0;
-
- a->is_add = mp->is_add;
- a->nsh_entry.nsh_base.ver_o_c =
- (mp->ver_o_c & 0xF0) | ((mp->ttl & NSH_LEN_MASK) >> 2);
- a->nsh_entry.nsh_base.length =
- (mp->length & NSH_LEN_MASK) | ((mp->ttl & 0x3) << 6);
- a->nsh_entry.nsh_base.md_type = mp->md_type;
- a->nsh_entry.nsh_base.next_protocol = mp->next_protocol;
- a->nsh_entry.nsh_base.nsp_nsi = ntohl (mp->nsp_nsi);
- if (mp->md_type == 1)
- {
- a->nsh_entry.md.md1_data.c1 = ntohl (mp->c1);
- a->nsh_entry.md.md1_data.c2 = ntohl (mp->c2);
- a->nsh_entry.md.md1_data.c3 = ntohl (mp->c3);
- a->nsh_entry.md.md1_data.c4 = ntohl (mp->c4);
- }
- else if (mp->md_type == 2)
- {
- tlvs_len = mp->tlv_length;
- vec_validate_aligned (data, tlvs_len - 1, CLIB_CACHE_LINE_BYTES);
-
- clib_memcpy (data, mp->tlv, tlvs_len);
- a->nsh_entry.tlvs_data = data;
- a->nsh_entry.tlvs_len = tlvs_len;
- }
-
- rv = nsh_add_del_entry (a, &entry_index);
-
- REPLY_MACRO2 (VL_API_NSH_ADD_DEL_ENTRY_REPLY, (
- {
- rmp->entry_index =
- htonl (entry_index);
- }
- ));
-}
-
-static void send_nsh_entry_details
- (nsh_entry_t * t, unix_shared_memory_queue_t * q, u32 context)
-{
- vl_api_nsh_entry_details_t *rmp;
- nsh_main_t *nm = &nsh_main;
-
- rmp = vl_msg_api_alloc (sizeof (*rmp));
- memset (rmp, 0, sizeof (*rmp));
-
- rmp->_vl_msg_id = ntohs ((VL_API_NSH_ENTRY_DETAILS) + nm->msg_id_base);
- rmp->ver_o_c = t->nsh_base.ver_o_c;
- rmp->ttl = (t->nsh_base.ver_o_c & NSH_TTL_H4_MASK) << 2 |
- (t->nsh_base.length & NSH_TTL_L2_MASK) >> 6;
- rmp->length = t->nsh_base.length & NSH_LEN_MASK;
- rmp->md_type = t->nsh_base.md_type;
- rmp->next_protocol = t->nsh_base.next_protocol;
- rmp->nsp_nsi = htonl (t->nsh_base.nsp_nsi);
-
- if (t->nsh_base.md_type == 1)
- {
- rmp->tlv_length = 4;
- rmp->c1 = htonl (t->md.md1_data.c1);
- rmp->c2 = htonl (t->md.md1_data.c2);
- rmp->c3 = htonl (t->md.md1_data.c3);
- rmp->c4 = htonl (t->md.md1_data.c4);
- }
- else if (t->nsh_base.md_type == 2)
- {
- rmp->tlv_length = t->tlvs_len;
- clib_memcpy (rmp->tlv, t->tlvs_data, t->tlvs_len);
- }
-
- rmp->context = context;
-
- vl_msg_api_send_shmem (q, (u8 *) & rmp);
-}
-
-static void
-vl_api_nsh_entry_dump_t_handler (vl_api_nsh_entry_dump_t * mp)
-{
- unix_shared_memory_queue_t *q;
- nsh_main_t *nm = &nsh_main;
- nsh_entry_t *t;
- u32 entry_index;
-
- q = vl_api_client_index_to_input_queue (mp->client_index);
- if (q == 0)
- {
- return;
- }
-
- entry_index = ntohl (mp->entry_index);
-
- if (~0 == entry_index)
- {
- pool_foreach (t, nm->nsh_entries, (
- {
- send_nsh_entry_details (t, q,
- mp->context);
- }
- ));
- }
- else
- {
- if (entry_index >= vec_len (nm->nsh_entries))
- {
- return;
- }
- t = &nm->nsh_entries[entry_index];
- send_nsh_entry_details (t, q, mp->context);
- }
-}
-
-static void send_nsh_map_details
- (nsh_map_t * t, unix_shared_memory_queue_t * q, u32 context)
-{
- vl_api_nsh_map_details_t *rmp;
- nsh_main_t *nm = &nsh_main;
-
- rmp = vl_msg_api_alloc (sizeof (*rmp));
- memset (rmp, 0, sizeof (*rmp));
-
- rmp->_vl_msg_id = ntohs ((VL_API_NSH_MAP_DETAILS) + nm->msg_id_base);
- rmp->nsp_nsi = htonl (t->nsp_nsi);
- rmp->mapped_nsp_nsi = htonl (t->mapped_nsp_nsi);
- rmp->nsh_action = htonl (t->nsh_action);
- rmp->sw_if_index = htonl (t->sw_if_index);
- rmp->rx_sw_if_index = htonl (t->rx_sw_if_index);
- rmp->next_node = htonl (t->next_node);
-
- rmp->context = context;
-
- vl_msg_api_send_shmem (q, (u8 *) & rmp);
-}
-
-static void
-vl_api_nsh_map_dump_t_handler (vl_api_nsh_map_dump_t * mp)
-{
- unix_shared_memory_queue_t *q;
- nsh_main_t *nm = &nsh_main;
- nsh_map_t *t;
- u32 map_index;
-
- q = vl_api_client_index_to_input_queue (mp->client_index);
- if (q == 0)
- {
- return;
- }
-
- map_index = ntohl (mp->map_index);
-
- if (~0 == map_index)
- {
- pool_foreach (t, nm->nsh_mappings, (
- {
- send_nsh_map_details (t, q,
- mp->context);
- }
- ));
- }
- else
- {
- if (map_index >= vec_len (nm->nsh_mappings))
- {
- return;
- }
- t = &nm->nsh_mappings[map_index];
- send_nsh_map_details (t, q, mp->context);
- }
-}
-
-static clib_error_t *
-show_nsh_entry_command_fn (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
-{
- nsh_main_t *nm = &nsh_main;
- nsh_entry_t *nsh_entry;
-
- if (pool_elts (nm->nsh_entries) == 0)
- vlib_cli_output (vm, "No nsh entries configured.");
-
- pool_foreach (nsh_entry, nm->nsh_entries, (
- {
- vlib_cli_output (vm, "%U",
- format_nsh_header,
- nsh_entry->rewrite);
- vlib_cli_output (vm,
- " rewrite_size: %d bytes",
- nsh_entry->rewrite_size);
- }
- ));
-
- return 0;
-}
-
-VLIB_CLI_COMMAND (show_nsh_entry_command, static) =
-{
-.path = "show nsh entry",.function = show_nsh_entry_command_fn,};
-
-
-/* Set up the API message handling tables */
-static clib_error_t *
-nsh_plugin_api_hookup (vlib_main_t * vm)
-{
- nsh_main_t *nm __attribute__ ((unused)) = &nsh_main;
-#define _(N,n) \
- vl_msg_api_set_handlers((VL_API_##N + nm->msg_id_base), \
- #n, \
- vl_api_##n##_t_handler, \
- vl_noop_handler, \
- vl_api_##n##_t_endian, \
- vl_api_##n##_t_print, \
- sizeof(vl_api_##n##_t), 1);
- foreach_nsh_plugin_api_msg;
-#undef _
-
- return 0;
-}
-
-static void
-setup_message_id_table (nsh_main_t * nm, api_main_t * am)
-{
-#define _(id,n,crc) \
- vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id + nm->msg_id_base);
- foreach_vl_msg_name_crc_nsh;
-#undef _
-}
-
-always_inline void
-nsh_md2_encap (vlib_buffer_t * b, nsh_base_header_t * hdr,
- nsh_entry_t * nsh_entry)
-{
- nsh_main_t *nm = &nsh_main;
- nsh_base_header_t *nsh_base;
- nsh_tlv_header_t *opt0;
- nsh_tlv_header_t *limit0;
- nsh_tlv_header_t *nsh_md2;
- nsh_option_map_t *nsh_option;
- u8 old_option_size = 0;
- u8 new_option_size = 0;
-
- /* Populate the NSH Header */
- opt0 = (nsh_tlv_header_t *) (nsh_entry->tlvs_data);
- limit0 = (nsh_tlv_header_t *) (nsh_entry->tlvs_data + nsh_entry->tlvs_len);
-
- nsh_md2 = (nsh_tlv_header_t *) ((u8 *) hdr /*nsh_entry->rewrite */ +
- sizeof (nsh_base_header_t));
- nsh_entry->rewrite_size = sizeof (nsh_base_header_t);
-
- /* Scan the set of variable metadata, process ones that we understand */
- while (opt0 < limit0)
- {
- old_option_size = sizeof (nsh_tlv_header_t) + opt0->length;
- /* round to 4-byte */
- old_option_size = ((old_option_size + 3) >> 2) << 2;
-
- nsh_option = nsh_md2_lookup_option (opt0->class, opt0->type);
- if (nsh_option == NULL)
- {
- goto next_tlv_md2;
- }
-
- if (nm->options[nsh_option->option_id])
- {
- if ((*nm->options[nsh_option->option_id]) (b, nsh_md2))
- {
- goto next_tlv_md2;
- }
-
- /* option length may be varied */
- new_option_size = sizeof (nsh_tlv_header_t) + nsh_md2->length;
- /* round to 4-byte */
- new_option_size = ((new_option_size + 3) >> 2) << 2;
- nsh_entry->rewrite_size += new_option_size;
-
- nsh_md2 = (nsh_tlv_header_t *) (((u8 *) nsh_md2) + new_option_size);
- opt0 = (nsh_tlv_header_t *) (((u8 *) opt0) + old_option_size);
-
- }
- else
- {
- next_tlv_md2:
- opt0 = (nsh_tlv_header_t *) (((u8 *) opt0) + old_option_size);
- }
- }
-
- /* update nsh header's length */
- nsh_base = (nsh_base_header_t *) nsh_entry->rewrite;
- nsh_base->length = (nsh_base->length & NSH_TTL_L2_MASK) |
- ((nsh_entry->rewrite_size >> 2) & NSH_LEN_MASK);
- return;
-}
-
-always_inline void
-nsh_md2_swap (vlib_buffer_t * b,
- nsh_base_header_t * hdr,
- u32 header_len,
- nsh_entry_t * nsh_entry, u32 * next, u32 drop_node_val)
-{
- nsh_main_t *nm = &nsh_main;
- nsh_base_header_t *nsh_base;
- nsh_tlv_header_t *opt0;
- nsh_tlv_header_t *limit0;
- nsh_tlv_header_t *nsh_md2;
- nsh_option_map_t *nsh_option;
- u8 old_option_size = 0;
- u8 new_option_size = 0;
-
- /* Populate the NSH Header */
- opt0 = (nsh_md2_data_t *) (hdr + 1);
- limit0 = (nsh_md2_data_t *) ((u8 *) hdr + header_len);
-
- nsh_md2 =
- (nsh_tlv_header_t *) (nsh_entry->rewrite + sizeof (nsh_base_header_t));
- nsh_entry->rewrite_size = sizeof (nsh_base_header_t);
-
- /* Scan the set of variable metadata, process ones that we understand */
- while (opt0 < limit0)
- {
- old_option_size = sizeof (nsh_tlv_header_t) + opt0->length;
- /* round to 4-byte */
- old_option_size = ((old_option_size + 3) >> 2) << 2;
-
- nsh_option = nsh_md2_lookup_option (opt0->class, opt0->type);
- if (nsh_option == NULL)
- {
- goto next_tlv_md2;
- }
-
- if (nm->swap_options[nsh_option->option_id])
- {
- if ((*nm->swap_options[nsh_option->option_id]) (b, opt0, nsh_md2))
- {
- goto next_tlv_md2;
- }
-
- /* option length may be varied */
- new_option_size = sizeof (nsh_tlv_header_t) + nsh_md2->length;
- /* round to 4-byte */
- new_option_size = ((new_option_size + 3) >> 2) << 2;
- nsh_entry->rewrite_size += new_option_size;
- nsh_md2 = (nsh_tlv_header_t *) (((u8 *) nsh_md2) + new_option_size);
-
- opt0 = (nsh_tlv_header_t *) (((u8 *) opt0) + old_option_size);
-
- }
- else
- {
- next_tlv_md2:
- opt0 = (nsh_tlv_header_t *) (((u8 *) opt0) + old_option_size);
- }
- }
-
- /* update nsh header's length */
- nsh_base = (nsh_base_header_t *) nsh_entry->rewrite;
- nsh_base->length = (nsh_base->length & NSH_TTL_L2_MASK) |
- ((nsh_entry->rewrite_size >> 2) & NSH_LEN_MASK);
- return;
-}
-
-always_inline void
-nsh_md2_decap (vlib_buffer_t * b,
- nsh_base_header_t * hdr,
- u32 * header_len, u32 * next, u32 drop_node_val)
-{
- nsh_main_t *nm = &nsh_main;
- nsh_md2_data_t *opt0;
- nsh_md2_data_t *limit0;
- nsh_option_map_t *nsh_option;
- u8 option_len = 0;
-
- /* Populate the NSH Header */
- opt0 = (nsh_md2_data_t *) (hdr + 1);
- limit0 = (nsh_md2_data_t *) ((u8 *) hdr + *header_len);
-
- /* Scan the set of variable metadata, process ones that we understand */
- while (opt0 < limit0)
- {
- nsh_option = nsh_md2_lookup_option (opt0->class, opt0->type);
- if (nsh_option == NULL)
- {
- *next = drop_node_val;
- return;
- }
-
- if (nm->pop_options[nsh_option->option_id])
- {
- if ((*nm->pop_options[nsh_option->option_id]) (b, opt0))
- {
- *next = drop_node_val;
- return;
- }
- }
- /* round to 4-byte */
- option_len = ((opt0->length + 3) >> 2) << 2;
- opt0 =
- (nsh_md2_data_t *) (((u8 *) opt0) + sizeof (nsh_md2_data_t) +
- option_len);
- *next =
- (nm->decap_v4_next_override) ? (nm->decap_v4_next_override) : (*next);
- *header_len = (nm->decap_v4_next_override) ? 0 : (*header_len);
- }
-
- return;
-}
-
-static uword
-nsh_input_map (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- vlib_frame_t * from_frame, u32 node_type)
-{
- u32 n_left_from, next_index, *from, *to_next;
- nsh_main_t *nm = &nsh_main;
-
- from = vlib_frame_vector_args (from_frame);
- n_left_from = from_frame->n_vectors;
-
- next_index = node->cached_next_index;
-
- while (n_left_from > 0)
- {
- u32 n_left_to_next;
-
- vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
-
- while (n_left_from >= 4 && n_left_to_next >= 2)
- {
- u32 bi0, bi1;
- vlib_buffer_t *b0, *b1;
- u32 next0 = NSH_NODE_NEXT_DROP, next1 = NSH_NODE_NEXT_DROP;
- uword *entry0, *entry1;
- nsh_base_header_t *hdr0 = 0, *hdr1 = 0;
- u32 header_len0 = 0, header_len1 = 0;
- u32 nsp_nsi0, nsp_nsi1;
- u32 ttl0, ttl1;
- u32 error0, error1;
- nsh_map_t *map0 = 0, *map1 = 0;
- nsh_entry_t *nsh_entry0 = 0, *nsh_entry1 = 0;
- nsh_base_header_t *encap_hdr0 = 0, *encap_hdr1 = 0;
- u32 encap_hdr_len0 = 0, encap_hdr_len1 = 0;
- nsh_proxy_session_by_key_t key0, key1;
- uword *p0, *p1;
- nsh_proxy_session_t *proxy0, *proxy1;
- u32 sw_if_index0 = 0, sw_if_index1 = 0;
- ethernet_header_t dummy_eth0, dummy_eth1;
-
- /* Prefetch next iteration. */
- {
- vlib_buffer_t *p2, *p3;
-
- p2 = vlib_get_buffer (vm, from[2]);
- p3 = vlib_get_buffer (vm, from[3]);
-
- vlib_prefetch_buffer_header (p2, LOAD);
- vlib_prefetch_buffer_header (p3, LOAD);
-
- CLIB_PREFETCH (p2->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
- CLIB_PREFETCH (p3->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
- }
-
- bi0 = from[0];
- bi1 = from[1];
- to_next[0] = bi0;
- to_next[1] = bi1;
- from += 2;
- to_next += 2;
- n_left_from -= 2;
- n_left_to_next -= 2;
-
- error0 = 0;
- error1 = 0;
-
- b0 = vlib_get_buffer (vm, bi0);
- b1 = vlib_get_buffer (vm, bi1);
- hdr0 = vlib_buffer_get_current (b0);
- hdr1 = vlib_buffer_get_current (b1);
-
- /* Process packet 0 */
- if (node_type == NSH_INPUT_TYPE)
- {
- nsp_nsi0 = hdr0->nsp_nsi;
- header_len0 = (hdr0->length & NSH_LEN_MASK) * 4;
- ttl0 = (hdr0->ver_o_c & NSH_TTL_H4_MASK) << 2 |
- (hdr0->length & NSH_TTL_L2_MASK) >> 6;
- ttl0 = ttl0 - 1;
- if (PREDICT_FALSE (ttl0 == 0))
- {
- error0 = NSH_NODE_ERROR_INVALID_TTL;
- goto trace0;
- }
- }
- else if (node_type == NSH_CLASSIFIER_TYPE)
- {
- nsp_nsi0 =
- clib_host_to_net_u32 (vnet_buffer (b0)->
- l2_classify.opaque_index);
- }
- else if (node_type == NSH_AWARE_VNF_PROXY_TYPE)
- {
- /* Push dummy Eth header */
- clib_memcpy (dummy_eth0.dst_address, dummy_dst_address, 6);
- clib_memcpy (dummy_eth0.src_address, dummy_src_address, 6);
- dummy_eth0.type = 0x0800;
- vlib_buffer_advance (b0, -(word) sizeof (ethernet_header_t));
- hdr0 = vlib_buffer_get_current (b0);
- clib_memcpy (hdr0, &dummy_eth0,
- (word) sizeof (ethernet_header_t));
-
- sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_TX];
- nsp_nsi0 = nm->tunnel_index_by_sw_if_index[sw_if_index0];
- }
- else
- {
- memset (&key0, 0, sizeof (key0));
- key0.transport_type = NSH_NODE_NEXT_ENCAP_VXLAN4;
- key0.transport_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
-
- p0 = hash_get_mem (nm->nsh_proxy_session_by_key, &key0);
- if (PREDICT_FALSE (p0 == 0))
- {
- error0 = NSH_NODE_ERROR_NO_PROXY;
- goto trace0;
- }
-
- proxy0 = pool_elt_at_index (nm->nsh_proxy_sessions, p0[0]);
- if (PREDICT_FALSE (proxy0 == 0))
- {
- error0 = NSH_NODE_ERROR_NO_PROXY;
- goto trace0;
- }
- nsp_nsi0 = proxy0->nsp_nsi;
- }
-
- entry0 = hash_get_mem (nm->nsh_mapping_by_key, &nsp_nsi0);
- if (PREDICT_FALSE (entry0 == 0))
- {
- error0 = NSH_NODE_ERROR_NO_MAPPING;
- goto trace0;
- }
-
- /* Entry should point to a mapping ... */
- map0 = pool_elt_at_index (nm->nsh_mappings, entry0[0]);
- if (PREDICT_FALSE (map0 == 0))
- {
- error0 = NSH_NODE_ERROR_NO_MAPPING;
- goto trace0;
- }
-
- /* set up things for next node to transmit ie which node to handle it and where */
- next0 = map0->next_node;
- vnet_buffer (b0)->sw_if_index[VLIB_TX] = map0->sw_if_index;
- vnet_buffer (b0)->ip.adj_index[VLIB_TX] = map0->adj_index;
-
- if (PREDICT_FALSE (map0->nsh_action == NSH_ACTION_POP))
- {
- /* Manipulate MD2 */
- if (PREDICT_FALSE (hdr0->md_type == 2))
- {
- nsh_md2_decap (b0, hdr0, &header_len0, &next0,
- NSH_NODE_NEXT_DROP);
- if (PREDICT_FALSE (next0 == NSH_NODE_NEXT_DROP))
- {
- error0 = NSH_NODE_ERROR_INVALID_OPTIONS;
- goto trace0;
- }
- vnet_buffer (b0)->sw_if_index[VLIB_RX] =
- map0->rx_sw_if_index;
- }
-
- /* Pop NSH header */
- vlib_buffer_advance (b0, (word) header_len0);
- goto trace0;
- }
-
- entry0 = hash_get_mem (nm->nsh_entry_by_key, &map0->mapped_nsp_nsi);
- if (PREDICT_FALSE (entry0 == 0))
- {
- error0 = NSH_NODE_ERROR_NO_ENTRY;
- goto trace0;
- }
-
- nsh_entry0 =
- (nsh_entry_t *) pool_elt_at_index (nm->nsh_entries, entry0[0]);
- encap_hdr0 = (nsh_base_header_t *) (nsh_entry0->rewrite);
- /* rewrite_size should equal to (encap_hdr0->length * 4) */
- encap_hdr_len0 = nsh_entry0->rewrite_size;
-
- if (PREDICT_TRUE (map0->nsh_action == NSH_ACTION_SWAP))
- {
- /* Manipulate MD2 */
- if (PREDICT_FALSE (hdr0->md_type == 2))
- {
- nsh_md2_swap (b0, hdr0, header_len0, nsh_entry0,
- &next0, NSH_NODE_NEXT_DROP);
- if (PREDICT_FALSE (next0 == NSH_NODE_NEXT_DROP))
- {
- error0 = NSH_NODE_ERROR_INVALID_OPTIONS;
- goto trace0;
- }
- }
-
- /* Pop old NSH header */
- vlib_buffer_advance (b0, (word) header_len0);
-
- /* After processing, md2's length may be varied */
- encap_hdr_len0 = nsh_entry0->rewrite_size;
- /* Push new NSH header */
- vlib_buffer_advance (b0, -(word) encap_hdr_len0);
- hdr0 = vlib_buffer_get_current (b0);
- clib_memcpy (hdr0, encap_hdr0, (word) encap_hdr_len0);
-
- goto trace0;
- }
-
- if (PREDICT_TRUE (map0->nsh_action == NSH_ACTION_PUSH))
- {
- /* After processing, md2's length may be varied */
- encap_hdr_len0 = nsh_entry0->rewrite_size;
- /* Push new NSH header */
- vlib_buffer_advance (b0, -(word) encap_hdr_len0);
- hdr0 = vlib_buffer_get_current (b0);
- clib_memcpy (hdr0, encap_hdr0, (word) encap_hdr_len0);
-
- /* Manipulate MD2 */
- if (PREDICT_FALSE (nsh_entry0->nsh_base.md_type == 2))
- {
- nsh_md2_encap (b0, hdr0, nsh_entry0);
- }
-
- }
-
- trace0:
- b0->error = error0 ? node->errors[error0] : 0;
-
- if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
- {
- nsh_input_trace_t *tr =
- vlib_add_trace (vm, node, b0, sizeof (*tr));
- clib_memcpy (&(tr->trace_data), hdr0,
- ((hdr0->length & NSH_LEN_MASK) * 4));
- }
-
- /* Process packet 1 */
- if (node_type == NSH_INPUT_TYPE)
- {
- nsp_nsi1 = hdr1->nsp_nsi;
- header_len1 = (hdr1->length & NSH_LEN_MASK) * 4;
- ttl1 = (hdr1->ver_o_c & NSH_TTL_H4_MASK) << 2 |
- (hdr1->length & NSH_TTL_L2_MASK) >> 6;
- ttl1 = ttl1 - 1;
- if (PREDICT_FALSE (ttl1 == 0))
- {
- error1 = NSH_NODE_ERROR_INVALID_TTL;
- goto trace1;
- }
- }
- else if (node_type == NSH_CLASSIFIER_TYPE)
- {
- nsp_nsi1 =
- clib_host_to_net_u32 (vnet_buffer (b1)->
- l2_classify.opaque_index);
- }
- else if (node_type == NSH_AWARE_VNF_PROXY_TYPE)
- {
- /* Push dummy Eth header */
- clib_memcpy (dummy_eth1.dst_address, dummy_dst_address, 6);
- clib_memcpy (dummy_eth1.src_address, dummy_src_address, 6);
- dummy_eth1.type = 0x0800;
- vlib_buffer_advance (b1, -(word) sizeof (ethernet_header_t));
- hdr1 = vlib_buffer_get_current (b1);
- clib_memcpy (hdr1, &dummy_eth1,
- (word) sizeof (ethernet_header_t));
-
- sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_TX];
- nsp_nsi1 = nm->tunnel_index_by_sw_if_index[sw_if_index1];
- }
- else
- {
- memset (&key1, 0, sizeof (key1));
- key1.transport_type = NSH_NODE_NEXT_ENCAP_VXLAN4;
- key1.transport_index = vnet_buffer (b1)->sw_if_index[VLIB_RX];
-
- p1 = hash_get_mem (nm->nsh_proxy_session_by_key, &key1);
- if (PREDICT_FALSE (p1 == 0))
- {
- error1 = NSH_NODE_ERROR_NO_PROXY;
- goto trace1;
- }
-
- proxy1 = pool_elt_at_index (nm->nsh_proxy_sessions, p1[0]);
- if (PREDICT_FALSE (proxy1 == 0))
- {
- error1 = NSH_NODE_ERROR_NO_PROXY;
- goto trace1;
- }
- nsp_nsi1 = proxy1->nsp_nsi;
- }
-
- entry1 = hash_get_mem (nm->nsh_mapping_by_key, &nsp_nsi1);
- if (PREDICT_FALSE (entry1 == 0))
- {
- error1 = NSH_NODE_ERROR_NO_MAPPING;
- goto trace1;
- }
-
- /* Entry should point to a mapping ... */
- map1 = pool_elt_at_index (nm->nsh_mappings, entry1[0]);
- if (PREDICT_FALSE (map1 == 0))
- {
- error1 = NSH_NODE_ERROR_NO_MAPPING;
- goto trace1;
- }
-
- /* set up things for next node to transmit ie which node to handle it and where */
- next1 = map1->next_node;
- vnet_buffer (b1)->sw_if_index[VLIB_TX] = map1->sw_if_index;
- vnet_buffer (b1)->ip.adj_index[VLIB_TX] = map1->adj_index;
-
- if (PREDICT_FALSE (map1->nsh_action == NSH_ACTION_POP))
- {
- /* Manipulate MD2 */
- if (PREDICT_FALSE (hdr1->md_type == 2))
- {
- nsh_md2_decap (b1, hdr1, &header_len1, &next1,
- NSH_NODE_NEXT_DROP);
- if (PREDICT_FALSE (next1 == NSH_NODE_NEXT_DROP))
- {
- error1 = NSH_NODE_ERROR_INVALID_OPTIONS;
- goto trace1;
- }
- vnet_buffer (b1)->sw_if_index[VLIB_RX] =
- map1->rx_sw_if_index;
- }
-
- /* Pop NSH header */
- vlib_buffer_advance (b1, (word) header_len1);
- goto trace1;
- }
-
- entry1 = hash_get_mem (nm->nsh_entry_by_key, &map1->mapped_nsp_nsi);
- if (PREDICT_FALSE (entry1 == 0))
- {
- error1 = NSH_NODE_ERROR_NO_ENTRY;
- goto trace1;
- }
-
- nsh_entry1 =
- (nsh_entry_t *) pool_elt_at_index (nm->nsh_entries, entry1[0]);
- encap_hdr1 = (nsh_base_header_t *) (nsh_entry1->rewrite);
- /* rewrite_size should equal to (encap_hdr0->length * 4) */
- encap_hdr_len1 = nsh_entry1->rewrite_size;
-
- if (PREDICT_TRUE (map1->nsh_action == NSH_ACTION_SWAP))
- {
- /* Manipulate MD2 */
- if (PREDICT_FALSE (hdr1->md_type == 2))
- {
- nsh_md2_swap (b1, hdr1, header_len1, nsh_entry1,
- &next1, NSH_NODE_NEXT_DROP);
- if (PREDICT_FALSE (next1 == NSH_NODE_NEXT_DROP))
- {
- error1 = NSH_NODE_ERROR_INVALID_OPTIONS;
- goto trace1;
- }
- }
-
- /* Pop old NSH header */
- vlib_buffer_advance (b1, (word) header_len1);
-
- /* After processing, md2's length may be varied */
- encap_hdr_len1 = nsh_entry1->rewrite_size;
- /* Push new NSH header */
- vlib_buffer_advance (b1, -(word) encap_hdr_len1);
- hdr1 = vlib_buffer_get_current (b1);
- clib_memcpy (hdr1, encap_hdr1, (word) encap_hdr_len1);
-
- goto trace1;
- }
-
- if (PREDICT_FALSE (map1->nsh_action == NSH_ACTION_PUSH))
- {
- /* After processing, md2's length may be varied */
- encap_hdr_len1 = nsh_entry1->rewrite_size;
- /* Push new NSH header */
- vlib_buffer_advance (b1, -(word) encap_hdr_len1);
- hdr1 = vlib_buffer_get_current (b1);
- clib_memcpy (hdr1, encap_hdr1, (word) encap_hdr_len1);
-
- /* Manipulate MD2 */
- if (PREDICT_FALSE (nsh_entry1->nsh_base.md_type == 2))
- {
- nsh_md2_encap (b1, hdr1, nsh_entry1);
- }
-
- }
-
- trace1:
- b1->error = error1 ? node->errors[error1] : 0;
-
- if (PREDICT_FALSE (b1->flags & VLIB_BUFFER_IS_TRACED))
- {
- nsh_input_trace_t *tr =
- vlib_add_trace (vm, node, b1, sizeof (*tr));
- clib_memcpy (&(tr->trace_data), hdr1,
- ((hdr1->length & NSH_LEN_MASK) * 4));
- }
-
- vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
- n_left_to_next, bi0, bi1, next0,
- next1);
-
- }
-
- while (n_left_from > 0 && n_left_to_next > 0)
- {
- u32 bi0 = 0;
- vlib_buffer_t *b0 = NULL;
- u32 next0 = NSH_NODE_NEXT_DROP;
- uword *entry0;
- nsh_base_header_t *hdr0 = 0;
- u32 header_len0 = 0;
- u32 nsp_nsi0;
- u32 ttl0;
- u32 error0;
- nsh_map_t *map0 = 0;
- nsh_entry_t *nsh_entry0 = 0;
- nsh_base_header_t *encap_hdr0 = 0;
- u32 encap_hdr_len0 = 0;
- nsh_proxy_session_by_key_t key0;
- uword *p0;
- nsh_proxy_session_t *proxy0 = 0;
- u32 sw_if_index0 = 0;
- ethernet_header_t dummy_eth0;
-
- bi0 = from[0];
- to_next[0] = bi0;
- from += 1;
- to_next += 1;
- n_left_from -= 1;
- n_left_to_next -= 1;
- error0 = 0;
-
- b0 = vlib_get_buffer (vm, bi0);
- hdr0 = vlib_buffer_get_current (b0);
-
- if (node_type == NSH_INPUT_TYPE)
- {
- nsp_nsi0 = hdr0->nsp_nsi;
- header_len0 = (hdr0->length & NSH_LEN_MASK) * 4;
- ttl0 = (hdr0->ver_o_c & NSH_TTL_H4_MASK) << 2 |
- (hdr0->length & NSH_TTL_L2_MASK) >> 6;
- ttl0 = ttl0 - 1;
- if (PREDICT_FALSE (ttl0 == 0))
- {
- error0 = NSH_NODE_ERROR_INVALID_TTL;
- goto trace00;
- }
- }
- else if (node_type == NSH_CLASSIFIER_TYPE)
- {
- nsp_nsi0 =
- clib_host_to_net_u32 (vnet_buffer (b0)->
- l2_classify.opaque_index);
- }
- else if (node_type == NSH_AWARE_VNF_PROXY_TYPE)
- {
- /* Push dummy Eth header */
- clib_memcpy (dummy_eth0.dst_address, dummy_dst_address, 6);
- clib_memcpy (dummy_eth0.src_address, dummy_src_address, 6);
- dummy_eth0.type = 0x0800;
- vlib_buffer_advance (b0, -(word) sizeof (ethernet_header_t));
- hdr0 = vlib_buffer_get_current (b0);
- clib_memcpy (hdr0, &dummy_eth0,
- (word) sizeof (ethernet_header_t));
-
- sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_TX];
- nsp_nsi0 = nm->tunnel_index_by_sw_if_index[sw_if_index0];
- }
- else
- {
- memset (&key0, 0, sizeof (key0));
- key0.transport_type = NSH_NODE_NEXT_ENCAP_VXLAN4;
- key0.transport_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
-
- p0 = hash_get_mem (nm->nsh_proxy_session_by_key, &key0);
- if (PREDICT_FALSE (p0 == 0))
- {
- error0 = NSH_NODE_ERROR_NO_PROXY;
- goto trace00;
- }
-
- proxy0 = pool_elt_at_index (nm->nsh_proxy_sessions, p0[0]);
- if (PREDICT_FALSE (proxy0 == 0))
- {
- error0 = NSH_NODE_ERROR_NO_PROXY;
- goto trace00;
- }
- nsp_nsi0 = proxy0->nsp_nsi;
- }
-
- entry0 = hash_get_mem (nm->nsh_mapping_by_key, &nsp_nsi0);
-
- if (PREDICT_FALSE (entry0 == 0))
- {
- error0 = NSH_NODE_ERROR_NO_MAPPING;
- goto trace00;
- }
-
- /* Entry should point to a mapping ... */
- map0 = pool_elt_at_index (nm->nsh_mappings, entry0[0]);
-
- if (PREDICT_FALSE (map0 == 0))
- {
- error0 = NSH_NODE_ERROR_NO_MAPPING;
- goto trace00;
- }
-
- /* set up things for next node to transmit ie which node to handle it and where */
- next0 = map0->next_node;
- vnet_buffer (b0)->sw_if_index[VLIB_TX] = map0->sw_if_index;
- vnet_buffer (b0)->ip.adj_index[VLIB_TX] = map0->adj_index;
- vnet_buffer (b0)->sw_if_index[VLIB_RX] = map0->nsh_sw_if;
-
- if (PREDICT_FALSE (map0->nsh_action == NSH_ACTION_POP))
- {
- /* Manipulate MD2 */
- if (PREDICT_FALSE (hdr0->md_type == 2))
- {
- nsh_md2_decap (b0, hdr0, &header_len0, &next0,
- NSH_NODE_NEXT_DROP);
- if (PREDICT_FALSE (next0 == NSH_NODE_NEXT_DROP))
- {
- error0 = NSH_NODE_ERROR_INVALID_OPTIONS;
- goto trace00;
- }
- vnet_buffer (b0)->sw_if_index[VLIB_RX] =
- map0->rx_sw_if_index;
- }
-
- /* Pop NSH header */
- vlib_buffer_advance (b0, (word) header_len0);
- goto trace00;
- }
-
- entry0 = hash_get_mem (nm->nsh_entry_by_key, &map0->mapped_nsp_nsi);
- if (PREDICT_FALSE (entry0 == 0))
- {
- error0 = NSH_NODE_ERROR_NO_ENTRY;
- goto trace00;
- }
-
- nsh_entry0 =
- (nsh_entry_t *) pool_elt_at_index (nm->nsh_entries, entry0[0]);
- encap_hdr0 = (nsh_base_header_t *) (nsh_entry0->rewrite);
- /* rewrite_size should equal to (encap_hdr0->length * 4) */
- encap_hdr_len0 = nsh_entry0->rewrite_size;
-
- if (PREDICT_TRUE (map0->nsh_action == NSH_ACTION_SWAP))
- {
- /* Manipulate MD2 */
- if (PREDICT_FALSE (hdr0->md_type == 2))
- {
- nsh_md2_swap (b0, hdr0, header_len0, nsh_entry0,
- &next0, NSH_NODE_NEXT_DROP);
- if (PREDICT_FALSE (next0 == NSH_NODE_NEXT_DROP))
- {
- error0 = NSH_NODE_ERROR_INVALID_OPTIONS;
- goto trace00;
- }
- }
-
- /* Pop old NSH header */
- vlib_buffer_advance (b0, (word) header_len0);
-
- /* After processing, md2's length may be varied */
- encap_hdr_len0 = nsh_entry0->rewrite_size;
- /* Push new NSH header */
- vlib_buffer_advance (b0, -(word) encap_hdr_len0);
- hdr0 = vlib_buffer_get_current (b0);
- clib_memcpy (hdr0, encap_hdr0, (word) encap_hdr_len0);
-
- goto trace00;
- }
-
- if (PREDICT_TRUE (map0->nsh_action == NSH_ACTION_PUSH))
- {
- /* After processing, md2's length may be varied */
- encap_hdr_len0 = nsh_entry0->rewrite_size;
- /* Push new NSH header */
- vlib_buffer_advance (b0, -(word) encap_hdr_len0);
- hdr0 = vlib_buffer_get_current (b0);
- clib_memcpy (hdr0, encap_hdr0, (word) encap_hdr_len0);
- /* Manipulate MD2 */
- if (PREDICT_FALSE (nsh_entry0->nsh_base.md_type == 2))
- {
- nsh_md2_encap (b0, hdr0, nsh_entry0);
- }
-
- }
-
- trace00:b0->error = error0 ? node->errors[error0] : 0;
-
- if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
- {
- nsh_input_trace_t *tr =
- vlib_add_trace (vm, node, b0, sizeof (*tr));
- clib_memcpy (&(tr->trace_data[0]), hdr0,
- ((hdr0->length & NSH_LEN_MASK) * 4));
- }
-
- vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
- n_left_to_next, bi0, next0);
- }
-
- vlib_put_next_frame (vm, node, next_index, n_left_to_next);
-
- }
-
- return from_frame->n_vectors;
-}
-
-/**
- * @brief Graph processing dispatch function for NSH Input
- *
- * @node nsh_input
- * @param *vm
- * @param *node
- * @param *from_frame
- *
- * @return from_frame->n_vectors
- *
- */
-static uword
-nsh_input (vlib_main_t * vm, vlib_node_runtime_t * node,
- vlib_frame_t * from_frame)
-{
- return nsh_input_map (vm, node, from_frame, NSH_INPUT_TYPE);
-}
-
-/**
- * @brief Graph processing dispatch function for NSH-Proxy
- *
- * @node nsh_proxy
- * @param *vm
- * @param *node
- * @param *from_frame
- *
- * @return from_frame->n_vectors
- *
- */
-static uword
-nsh_proxy (vlib_main_t * vm, vlib_node_runtime_t * node,
- vlib_frame_t * from_frame)
-{
- return nsh_input_map (vm, node, from_frame, NSH_PROXY_TYPE);
-}
-
-/**
- * @brief Graph processing dispatch function for NSH Classifier
- *
- * @node nsh_classifier
- * @param *vm
- * @param *node
- * @param *from_frame
- *
- * @return from_frame->n_vectors
- *
- */
-static uword
-nsh_classifier (vlib_main_t * vm, vlib_node_runtime_t * node,
- vlib_frame_t * from_frame)
-{
- return nsh_input_map (vm, node, from_frame, NSH_CLASSIFIER_TYPE);
-}
-
-/**
- * @brief Graph processing dispatch function for NSH-AWARE-VNF-PROXY
- *
- * @node nsh_aware_vnf_proxy
- * @param *vm
- * @param *node
- * @param *from_frame
- *
- * @return from_frame->n_vectors
- *
- */
-static uword
-nsh_aware_vnf_proxy (vlib_main_t * vm, vlib_node_runtime_t * node,
- vlib_frame_t * from_frame)
-{
- return nsh_input_map (vm, node, from_frame, NSH_AWARE_VNF_PROXY_TYPE);
-}
-
-static char *nsh_node_error_strings[] = {
-#define _(sym,string) string,
- foreach_nsh_node_error
-#undef _
-};
-
-/* register nsh-input node */
-VLIB_REGISTER_NODE (nsh_input_node) =
-{
- .function = nsh_input,.name = "nsh-input",.vector_size =
- sizeof (u32),.format_trace = format_nsh_node_map_trace,.format_buffer =
- format_nsh_header,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors =
- ARRAY_LEN (nsh_node_error_strings),.error_strings =
- nsh_node_error_strings,.n_next_nodes = NSH_NODE_N_NEXT,.next_nodes =
- {
-#define _(s,n) [NSH_NODE_NEXT_##s] = n,
- foreach_nsh_node_next
-#undef _
- }
-,};
-
-VLIB_NODE_FUNCTION_MULTIARCH (nsh_input_node, nsh_input);
-
-/* register nsh-proxy node */
-VLIB_REGISTER_NODE (nsh_proxy_node) =
-{
- .function = nsh_proxy,.name = "nsh-proxy",.vector_size =
- sizeof (u32),.format_trace = format_nsh_node_map_trace,.format_buffer =
- format_nsh_header,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors =
- ARRAY_LEN (nsh_node_error_strings),.error_strings =
- nsh_node_error_strings,.n_next_nodes = NSH_NODE_N_NEXT,.next_nodes =
- {
-#define _(s,n) [NSH_NODE_NEXT_##s] = n,
- foreach_nsh_node_next
-#undef _
- }
-,};
-
-VLIB_NODE_FUNCTION_MULTIARCH (nsh_proxy_node, nsh_proxy);
-
-/* register nsh-classifier node */
-VLIB_REGISTER_NODE (nsh_classifier_node) =
-{
- .function = nsh_classifier,.name = "nsh-classifier",.vector_size =
- sizeof (u32),.format_trace = format_nsh_node_map_trace,.format_buffer =
- format_nsh_header,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors =
- ARRAY_LEN (nsh_node_error_strings),.error_strings =
- nsh_node_error_strings,.n_next_nodes = NSH_NODE_N_NEXT,.next_nodes =
- {
-#define _(s,n) [NSH_NODE_NEXT_##s] = n,
- foreach_nsh_node_next
-#undef _
- }
-,};
-
-VLIB_NODE_FUNCTION_MULTIARCH (nsh_classifier_node, nsh_classifier);
-
-/* register nsh-aware-vnf-proxy node */
-VLIB_REGISTER_NODE (nsh_aware_vnf_proxy_node) =
-{
- .function = nsh_aware_vnf_proxy,.name = "nsh-aware-vnf-proxy",.vector_size =
- sizeof (u32),.format_trace = format_nsh_node_map_trace,.format_buffer =
- format_nsh_header,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors =
- ARRAY_LEN (nsh_node_error_strings),.error_strings =
- nsh_node_error_strings,.n_next_nodes = NSH_NODE_N_NEXT,.next_nodes =
- {
-#define _(s,n) [NSH_NODE_NEXT_##s] = n,
- foreach_nsh_node_next
-#undef _
- }
-,};
-
-VLIB_NODE_FUNCTION_MULTIARCH (nsh_aware_vnf_proxy_node, nsh_aware_vnf_proxy);
-
-void
-nsh_md2_set_next_ioam_export_override (uword next)
-{
- nsh_main_t *hm = &nsh_main;
- hm->decap_v4_next_override = next;
- return;
-}
-
-
-clib_error_t *
-nsh_init (vlib_main_t * vm)
-{
- nsh_main_t *nm = &nsh_main;
- clib_error_t *error = 0;
- u8 *name;
- uword next_node;
-
- /* Init the main structures from VPP */
- nm->vlib_main = vm;
- nm->vnet_main = vnet_get_main ();
-
- /* Various state maintenance mappings */
- nm->nsh_mapping_by_key = hash_create_mem (0, sizeof (u32), sizeof (uword));
-
- nm->nsh_mapping_by_mapped_key
- = hash_create_mem (0, sizeof (u32), sizeof (uword));
-
- nm->nsh_entry_by_key = hash_create_mem (0, sizeof (u32), sizeof (uword));
-
- nm->nsh_proxy_session_by_key
- =
- hash_create_mem (0, sizeof (nsh_proxy_session_by_key_t), sizeof (uword));
-
- nm->nsh_option_map_by_key
- = hash_create_mem (0, sizeof (nsh_option_map_by_key_t), sizeof (uword));
-
- name = format (0, "nsh_%08x%c", api_version, 0);
-
- /* Set up the API */
- nm->msg_id_base = vl_msg_api_get_msg_ids
- ((char *) name, VL_MSG_FIRST_AVAILABLE);
-
- error = nsh_plugin_api_hookup (vm);
-
- /* Add our API messages to the global name_crc hash table */
- setup_message_id_table (nm, &api_main);
-
- /* Add dispositions to nodes that feed nsh-input */
- //alagalah - validate we don't really need to use the node value
- next_node =
- vlib_node_add_next (vm, vxlan4_gpe_input_node.index,
- nsh_input_node.index);
- vlib_node_add_next (vm, vxlan4_gpe_input_node.index, nsh_proxy_node.index);
- vlib_node_add_next (vm, vxlan4_gpe_input_node.index,
- nsh_aware_vnf_proxy_node.index);
- vxlan_gpe_register_decap_protocol (VXLAN_GPE_PROTOCOL_NSH, next_node);
-
- vlib_node_add_next (vm, vxlan6_gpe_input_node.index, nsh_input_node.index);
- vlib_node_add_next (vm, vxlan6_gpe_input_node.index, nsh_proxy_node.index);
- vlib_node_add_next (vm, vxlan6_gpe_input_node.index,
- nsh_aware_vnf_proxy_node.index);
-
- vlib_node_add_next (vm, gre4_input_node.index, nsh_input_node.index);
- vlib_node_add_next (vm, gre4_input_node.index, nsh_proxy_node.index);
- vlib_node_add_next (vm, gre4_input_node.index,
- nsh_aware_vnf_proxy_node.index);
-
- vlib_node_add_next (vm, gre6_input_node.index, nsh_input_node.index);
- vlib_node_add_next (vm, gre6_input_node.index, nsh_proxy_node.index);
- vlib_node_add_next (vm, gre6_input_node.index,
- nsh_aware_vnf_proxy_node.index);
-
- /* Add NSH-Proxy support */
- vlib_node_add_next (vm, vxlan4_input_node.index, nsh_proxy_node.index);
- vlib_node_add_next (vm, vxlan6_input_node.index, nsh_proxy_node.index);
-
- /* Add NSH-Classifier support */
- vlib_node_add_next (vm, ip4_classify_node.index, nsh_classifier_node.index);
- vlib_node_add_next (vm, ip6_classify_node.index, nsh_classifier_node.index);
- vlib_node_add_next (vm, l2_input_classify_node.index,
- nsh_classifier_node.index);