diff options
Diffstat (limited to 'hicn-plugin/src/faces/udp/iface_udp_node.c')
-rwxr-xr-x | hicn-plugin/src/faces/udp/iface_udp_node.c | 894 |
1 files changed, 894 insertions, 0 deletions
diff --git a/hicn-plugin/src/faces/udp/iface_udp_node.c b/hicn-plugin/src/faces/udp/iface_udp_node.c new file mode 100755 index 000000000..ddea31b4c --- /dev/null +++ b/hicn-plugin/src/faces/udp/iface_udp_node.c @@ -0,0 +1,894 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "iface_udp_node.h" +#include "dpo_udp.h" +#include "../face.h" + +#include "../../infra.h" +#include "../../hicn.h" + +/** + * @File + * + * Definition of the nodes for udp incomplete faces. + */ + +vlib_node_registration_t hicn_iface_udp4_input_node; +vlib_node_registration_t hicn_iface_udp6_input_node; +vlib_node_registration_t hicn_iface_udp4_output_node; +vlib_node_registration_t hicn_iface_udp6_output_node; + +u32 data_fwd_face_udp4_vlib_edge; +u32 data_fwd_face_udp6_vlib_edge; + +void +hicn_iface_udp_init (vlib_main_t * vm) +{ + data_fwd_face_udp4_vlib_edge = vlib_node_add_next (vm, + hicn_data_fwd_node.index, + hicn_iface_udp4_output_node. + index); + + data_fwd_face_udp6_vlib_edge = vlib_node_add_next (vm, + hicn_data_fwd_node.index, + hicn_iface_udp6_output_node. + index); + + u32 temp_index4 = vlib_node_add_next (vm, + hicn_interest_hitcs_node.index, + hicn_iface_udp4_output_node.index); + u32 temp_index6 = vlib_node_add_next (vm, + hicn_interest_hitcs_node.index, + hicn_iface_udp6_output_node.index); + + ASSERT (temp_index4 == data_fwd_face_udp4_vlib_edge); + ASSERT (temp_index6 == data_fwd_face_udp6_vlib_edge); +} + +static char *hicn_iface_udp4_input_error_strings[] = { +#define _(sym, string) string, + foreach_hicnfwd_error +#undef _ +}; + +static char *hicn_iface_udp6_input_error_strings[] = { +#define _(sym, string) string, + foreach_hicnfwd_error +#undef _ +}; + +u32 +get_face_udp4_output_node (void) +{ + return data_fwd_face_udp4_vlib_edge; +} + +u32 +get_face_udp6_output_node (void) +{ + return data_fwd_face_udp6_vlib_edge; +} + +/* Trace context struct */ +typedef struct +{ + u32 next_index; + u32 sw_if_index; + u8 pkt_type; +} hicn_iface_udp4_input_trace_t; + +typedef enum +{ + HICN_IFACE_UDP4_INPUT_NEXT_INTEREST, + HICN_IFACE_UDP4_INPUT_NEXT_MAPME, + HICN_IFACE_UDP4_INPUT_NEXT_ERROR_DROP, + HICN_IFACE_UDP4_INPUT_N_NEXT, +} hicn_iface_udp4_input_next_t; + +/* Trace context struct */ +typedef struct +{ + u32 next_index; + u32 sw_if_index; + u8 pkt_type; +} hicn_iface_udp6_input_trace_t; + +typedef enum +{ + HICN_IFACE_UDP6_INPUT_NEXT_INTEREST, + HICN_IFACE_UDP6_INPUT_NEXT_MAPME, + HICN_IFACE_UDP6_INPUT_NEXT_ERROR_DROP, + HICN_IFACE_UDP6_INPUT_N_NEXT, +} hicn_iface_udp6_input_next_t; + +#define ERROR_INPUT_UDP4 HICN_IFACE_UDP4_INPUT_NEXT_ERROR_DROP +#define ERROR_INPUT_UDP6 HICN_IFACE_UDP6_INPUT_NEXT_ERROR_DROP + +#define IP_HEADER_4 ip4_header_t +#define IP_HEADER_6 ip6_header_t + +#define NEXT_MAPME_UDP4 HICN_IFACE_UDP4_INPUT_NEXT_MAPME +#define NEXT_MAPME_UDP6 HICN_IFACE_UDP6_INPUT_NEXT_MAPME + +#define NEXT_INTEREST_UDP4 HICN_IFACE_UDP4_INPUT_NEXT_INTEREST +#define NEXT_INTEREST_UDP6 HICN_IFACE_UDP6_INPUT_NEXT_INTEREST + +#define HICN_IFACE_UDP_ADD_LOCK_IP4 hicn_dpo_udp4_add_and_lock +#define HICN_IFACE_UDP_ADD_LOCK_IP6 hicn_dpo_udp6_add_and_lock + +#define GET_FACE_UDP4 get_face_udp4_output_node +#define GET_FACE_UDP6 get_face_udp6_output_node + +#define TRACE_INPUT_PKT_UDP4 hicn_iface_udp4_input_trace_t +#define TRACE_INPUT_PKT_UDP6 hicn_iface_udp6_input_trace_t + +#define iface_input_x1(ipv) \ + do { \ + vlib_buffer_t *b0; \ + u32 bi0; \ + u32 next0 = ERROR_INPUT_UDP##ipv; \ + IP_HEADER_##ipv * ip_hdr = NULL; \ + u8 * inner_ip_hdr = NULL; \ + udp_header_t * udp_hdr = NULL; \ + hicn_buffer_t * hicnb0; \ + /* Prefetch for next iteration. */ \ + if (n_left_from > 1) \ + { \ + vlib_buffer_t *b1; \ + b1 = vlib_get_buffer (vm, from[1]); \ + CLIB_PREFETCH (b1, CLIB_CACHE_LINE_BYTES, STORE); \ + CLIB_PREFETCH (b1->data, CLIB_CACHE_LINE_BYTES , LOAD); \ + } \ + /* Dequeue a packet buffer */ \ + bi0 = from[0]; \ + from += 1; \ + n_left_from -= 1; \ + to_next[0] = bi0; \ + to_next += 1; \ + n_left_to_next -= 1; \ + \ + b0 = vlib_get_buffer (vm, bi0); \ + ip_hdr = (IP_HEADER_##ipv *) vlib_buffer_get_current(b0); \ + udp_hdr = (udp_header_t *) (ip_hdr + 1); \ + hicnb0 = hicn_get_buffer(b0); \ + \ + stats.pkts_interest_count += 1; \ + \ + inner_ip_hdr = (u8 *)(udp_hdr + 1); \ + u8 is_v6 = ((inner_ip_hdr[0] & 2) >> 1); \ + u8 is_icmp = is_v6*(inner_ip_hdr[7] == IPPROTO_ICMPV6) + \ + (1 - is_v6)*(inner_ip_hdr[10] == IPPROTO_ICMPV4); \ + \ + next0 = is_icmp*NEXT_MAPME_UDP##ipv + \ + (1-is_icmp)*NEXT_INTEREST_UDP##ipv; \ + \ + HICN_IFACE_UDP_ADD_LOCK_IP##ipv \ + (&(hicnb0->face_dpo_id), \ + &(ip_hdr->dst_address), \ + &(ip_hdr->src_address), \ + udp_hdr->dst_port, \ + udp_hdr->src_port, \ + GET_FACE_UDP##ipv \ + (), \ + &hicnb0->is_appface); \ + \ + vlib_buffer_advance(b0, sizeof(IP_HEADER_##ipv) + \ + sizeof(udp_header_t)); \ + \ + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && \ + (b0->flags & VLIB_BUFFER_IS_TRACED))) \ + { \ + TRACE_INPUT_PKT_UDP##ipv *t = \ + vlib_add_trace (vm, node, b0, sizeof (*t)); \ + t->pkt_type = HICN_PKT_TYPE_INTEREST; \ + t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; \ + t->next_index = next0; \ + } \ + \ + \ + /* Verify speculative enqueue, maybe switch current next frame */ \ + vlib_validate_buffer_enqueue_x1 (vm, node, next_index, \ + to_next, n_left_to_next, \ + bi0, next0); \ + }while(0) + + +#define iface_input_x2(ipv) \ + do { \ + vlib_buffer_t *b0, *b1; \ + u32 bi0, bi1; \ + u32 next0, next1 = ERROR_INPUT_UDP##ipv; \ + IP_HEADER_##ipv * ip_hdr0 = NULL, *ip_hdr1 = NULL; \ + u8 * inner_ip_hdr0 = NULL, *inner_ip_hdr1 = NULL; \ + udp_header_t * udp_hdr0 = NULL, *udp_hdr1 = NULL; \ + hicn_buffer_t * hicnb0, *hicnb1; \ + \ + /* Prefetch for next iteration. */ \ + { \ + vlib_buffer_t *b2, *b3; \ + b2 = vlib_get_buffer (vm, from[2]); \ + b3 = vlib_get_buffer (vm, from[3]); \ + CLIB_PREFETCH (b2, CLIB_CACHE_LINE_BYTES, STORE); \ + CLIB_PREFETCH (b3, CLIB_CACHE_LINE_BYTES, STORE); \ + CLIB_PREFETCH (b2->data, CLIB_CACHE_LINE_BYTES , LOAD); \ + CLIB_PREFETCH (b3->data, CLIB_CACHE_LINE_BYTES , LOAD); \ + } \ + \ + /* Dequeue a packet buffer */ \ + bi0 = from[0]; \ + bi1 = from[1]; \ + from += 2; \ + n_left_from -= 2; \ + to_next[0] = bi0; \ + to_next[1] = bi1; \ + to_next += 2; \ + n_left_to_next -= 2; \ + \ + b0 = vlib_get_buffer (vm, bi0); \ + b1 = vlib_get_buffer (vm, bi1); \ + ip_hdr0 = (IP_HEADER_##ipv *) vlib_buffer_get_current(b0); \ + ip_hdr1 = (IP_HEADER_##ipv *) vlib_buffer_get_current(b1); \ + udp_hdr0 = (udp_header_t *) (ip_hdr0 + 1); \ + udp_hdr1 = (udp_header_t *) (ip_hdr1 + 1); \ + hicnb0 = hicn_get_buffer(b0); \ + hicnb1 = hicn_get_buffer(b1); \ + \ + stats.pkts_interest_count += 2; \ + \ + inner_ip_hdr0 = (u8 *)(udp_hdr0 + 1); \ + inner_ip_hdr1 = (u8 *)(udp_hdr1 + 1); \ + u8 is_v6_0 = ((inner_ip_hdr0[0] & 2) >> 1); \ + u8 is_v6_1 = ((inner_ip_hdr1[0] & 2) >> 1); \ + u8 is_icmp0 = is_v6_0*(inner_ip_hdr0[7] == IPPROTO_ICMPV6) + \ + (1 - is_v6_0)*(inner_ip_hdr0[10] == IPPROTO_ICMPV4); \ + u8 is_icmp1 = is_v6_1*(inner_ip_hdr1[7] == IPPROTO_ICMPV6) + \ + (1 - is_v6_1)*(inner_ip_hdr1[10] == IPPROTO_ICMPV4); \ + \ + next0 = is_icmp0*NEXT_MAPME_UDP##ipv + \ + (1-is_icmp0)*NEXT_INTEREST_UDP##ipv; \ + next1 = is_icmp1*NEXT_MAPME_UDP##ipv + \ + (1-is_icmp1)*NEXT_INTEREST_UDP##ipv; \ + \ + HICN_IFACE_UDP_ADD_LOCK_IP##ipv \ + (&(hicnb0->face_dpo_id), \ + &(ip_hdr0->dst_address), \ + &(ip_hdr0->src_address), \ + udp_hdr0->dst_port, \ + udp_hdr0->src_port, \ + GET_FACE_UDP##ipv \ + (), \ + &hicnb0->is_appface); \ + \ + \ + HICN_IFACE_UDP_ADD_LOCK_IP##ipv \ + (&(hicnb1->face_dpo_id), \ + &(ip_hdr1->dst_address), \ + &(ip_hdr1->src_address), \ + udp_hdr1->dst_port, \ + udp_hdr1->src_port, \ + GET_FACE_UDP##ipv \ + (), \ + &hicnb1->is_appface); \ + \ + vlib_buffer_advance(b0, sizeof(IP_HEADER_##ipv) + \ + sizeof(udp_header_t)); \ + \ + vlib_buffer_advance(b1, sizeof(IP_HEADER_##ipv) + \ + sizeof(udp_header_t)); \ + \ + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && \ + (b0->flags & VLIB_BUFFER_IS_TRACED))) \ + { \ + TRACE_INPUT_PKT_UDP##ipv *t = \ + vlib_add_trace (vm, node, b0, sizeof (*t)); \ + t->pkt_type = HICN_PKT_TYPE_INTEREST; \ + t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; \ + t->next_index = next0; \ + } \ + \ + \ + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && \ + (b1->flags & VLIB_BUFFER_IS_TRACED))) \ + { \ + TRACE_INPUT_PKT_UDP##ipv *t = \ + vlib_add_trace (vm, node, b1, sizeof (*t)); \ + t->pkt_type = HICN_PKT_TYPE_INTEREST; \ + t->sw_if_index = vnet_buffer (b1)->sw_if_index[VLIB_RX]; \ + t->next_index = next1; \ + } \ + \ + \ + /* Verify speculative enqueue, maybe switch current next frame */ \ + vlib_validate_buffer_enqueue_x2 (vm, node, next_index, \ + to_next, n_left_to_next, \ + bi0, bi1, next0, next1); \ + }while(0) + + +static uword +hicn_iface_udp4_input_node_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + u32 n_left_from, *from, *to_next, next_index; + vl_api_hicn_api_node_stats_get_reply_t stats = { 0 }; + + from = vlib_frame_vector_args (frame); + n_left_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); + + /* Dual loop, X2 */ + while (n_left_from >= 4 && n_left_to_next >= 2) + { + iface_input_x2 (4); + } + + /* Dual loop, X1 */ + while (n_left_from > 0 && n_left_to_next > 0) + { + iface_input_x1 (4); + } + vlib_put_next_frame (vm, node, next_index, n_left_to_next); + } + + vlib_node_increment_counter (vm, node->node_index, + HICNFWD_ERROR_INTERESTS, + stats.pkts_interest_count); + + return (frame->n_vectors); +} + +/* packet trace format function */ +static u8 * +hicn_iface_udp4_input_format_trace (u8 * s, va_list * args) +{ + CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); + CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); + hicn_iface_udp4_input_trace_t *t = + va_arg (*args, hicn_iface_udp4_input_trace_t *); + + s = format (s, "IFACE_UDP4_INPUT: pkt: %d, sw_if_index %d, next index %d", + (int) t->pkt_type, t->sw_if_index, t->next_index); + return (s); +} + +/* + * Node registration for the interest forwarder node + */ +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (hicn_iface_udp4_input_node) = + +{ + .function = hicn_iface_udp4_input_node_fn, + .name = "hicn-iface-udp4-input", + .vector_size = sizeof (u32), + .format_trace = hicn_iface_udp4_input_format_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = ARRAY_LEN (hicn_iface_udp4_input_error_strings), + .error_strings = hicn_iface_udp4_input_error_strings, + .n_next_nodes = HICN_IFACE_UDP4_INPUT_N_NEXT, + .next_nodes = + { + [HICN_IFACE_UDP4_INPUT_NEXT_INTEREST] = "hicn-interest-pcslookup", + [HICN_IFACE_UDP4_INPUT_NEXT_MAPME] = "hicn-mapme-ctrl", + [HICN_IFACE_UDP4_INPUT_NEXT_ERROR_DROP] = "error-drop", + }, +}; +/* *INDENT-ON* */ + + +static uword +hicn_iface_udp6_input_node_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + u32 n_left_from, *from, *to_next, next_index; + vl_api_hicn_api_node_stats_get_reply_t stats = { 0 }; + + + from = vlib_frame_vector_args (frame); + n_left_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); + + /* Dual loop, X2 */ + while (n_left_from >= 4 && n_left_to_next >= 2) + { + iface_input_x2 (6); + } + + /* Dual loop, X1 */ + while (n_left_from > 0 && n_left_to_next > 0) + { + iface_input_x1 (6); + } + vlib_put_next_frame (vm, node, next_index, n_left_to_next); + } + + vlib_node_increment_counter (vm, node->node_index, + HICNFWD_ERROR_INTERESTS, + stats.pkts_interest_count); + + return (frame->n_vectors); +} + +/* packet trace format function */ +static u8 * +hicn_iface_udp6_input_format_trace (u8 * s, va_list * args) +{ + CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); + CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); + hicn_iface_udp6_input_trace_t *t = + va_arg (*args, hicn_iface_udp6_input_trace_t *); + + s = format (s, "IFACE_UDP6_INPUT: pkt: %d, sw_if_index %d, next index %d", + (int) t->pkt_type, t->sw_if_index, t->next_index); + return (s); +} + +/* + * Node registration for the interest forwarder node + */ +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (hicn_iface_udp6_input_node) = +{ + .function = hicn_iface_udp6_input_node_fn, + .name = "hicn-iface-udp6-input", + .vector_size = sizeof (u32), + .format_trace = hicn_iface_udp6_input_format_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = ARRAY_LEN (hicn_iface_udp6_input_error_strings), + .error_strings = hicn_iface_udp6_input_error_strings, + .n_next_nodes = HICN_IFACE_UDP6_INPUT_N_NEXT, + .next_nodes = + { + [HICN_IFACE_UDP6_INPUT_NEXT_INTEREST] = "hicn-interest-pcslookup", + [HICN_IFACE_UDP6_INPUT_NEXT_MAPME] = "hicn-mapme-ctrl", + [HICN_IFACE_UDP6_INPUT_NEXT_ERROR_DROP] = "error-drop", + }, +}; +/* *INDENT-ON* */ + +/******* Iface Output *******/ + +always_inline void +hicn_iface_udp4_encap (vlib_main_t * vm, + vlib_buffer_t * b0, hicn_face_t * face) +{ + u16 new_l0 = 0; + ip4_header_t *ip0; + udp_header_t *udp0; + hicn_face_udp_t *face_udp = (hicn_face_udp_t *) face->data; + + /* Adjust vlib buffers */ + /* Set the right length on the header buffer */ + /* Move the next buffer current data pointer back to the ip+tcp header (hicn header) */ + int offset = sizeof (ip4_header_t) + sizeof (udp_header_t); + b0->current_data -= offset; + b0->current_length += offset; + + /* ip */ + ip0 = vlib_buffer_get_current (b0); + clib_memcpy (ip0, &(face_udp->hdrs.ip4.ip), sizeof (ip4_header_t) + + sizeof (udp_header_t)); + + /* Fix UDP length */ + udp0 = (udp_header_t *) (ip0 + 1); + + new_l0 = + clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0) - + sizeof (*ip0)); + udp0->length = new_l0; + + ip0->length = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0)); + ip0->checksum = ip4_header_checksum (ip0); +} + +always_inline void +hicn_iface_udp6_encap (vlib_main_t * vm, + vlib_buffer_t * b0, hicn_face_t * face) +{ + int bogus0; + u16 new_l0; + ip6_header_t *ip0; + udp_header_t *udp0; + hicn_face_udp_t *face_udp = (hicn_face_udp_t *) face->data; + + /* Adjust vlib buffer */ + int offset = sizeof (ip6_header_t) + sizeof (udp_header_t); + b0->current_data -= offset; + b0->current_length += offset; + + /* ip */ + ip0 = vlib_buffer_get_current (b0); + clib_memcpy (ip0, &(face_udp->hdrs.ip6.ip), sizeof (ip6_header_t) + + sizeof (udp_header_t)); + + new_l0 = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0) + - sizeof (*ip0)); + + ip0->payload_length = new_l0; + + /* Fix UDP length */ + udp0 = (udp_header_t *) (ip0 + 1); + udp0->length = new_l0; + + udp0->checksum = ip6_tcp_udp_icmp_compute_checksum (vm, b0, ip0, &bogus0); + + ASSERT (bogus0 == 0); + + if (udp0->checksum == 0) + udp0->checksum = 0xffff; +} + +static char *hicn_iface_udp4_output_error_strings[] = { +#define _(sym, string) string, + foreach_hicnfwd_error +#undef _ +}; + +static char *hicn_iface_udp6_output_error_strings[] = { +#define _(sym, string) string, + foreach_hicnfwd_error +#undef _ +}; + +/* Trace context struct */ +typedef struct +{ + u32 next_index; + u32 sw_if_index; + u8 pkt_type; +} hicn_iface_udp4_output_trace_t; + +typedef enum +{ + HICN_IFACE_UDP4_OUTPUT_NEXT_LOOKUP, + HICN_IFACE_UDP4_OUTPUT_NEXT_ERROR_DROP, + HICN_IFACE_UDP4_OUTPUT_N_NEXT, +} hicn_iface_udp4_output_next_t; + +/* Trace context struct */ +typedef struct +{ + u32 next_index; + u32 sw_if_index; + u8 pkt_type; +} hicn_iface_udp6_output_trace_t; + +typedef enum +{ + HICN_IFACE_UDP6_OUTPUT_NEXT_LOOKUP, + HICN_IFACE_UDP6_OUTPUT_NEXT_ERROR_DROP, + HICN_IFACE_UDP6_OUTPUT_N_NEXT, +} hicn_iface_udp6_output_next_t; + +#define ERROR_OUTPUT_UDP4 HICN_IFACE_UDP4_OUTPUT_NEXT_ERROR_DROP +#define ERROR_OUTPUT_UDP6 HICN_IFACE_UDP6_OUTPUT_NEXT_ERROR_DROP + +#define IP_HEADER_4 ip4_header_t +#define IP_HEADER_6 ip6_header_t + +#define NEXT_LOOKUP_UDP4 HICN_IFACE_UDP4_OUTPUT_NEXT_LOOKUP +#define NEXT_LOOKUP_UDP6 HICN_IFACE_UDP6_OUTPUT_NEXT_LOOKUP + +#define HICN_IFACE_UDP_ADD_LOCK_IP4 hicn_dpo_udp4_add_and_lock +#define HICN_IFACE_UDP_ADD_LOCK_IP6 hicn_dpo_udp6_add_and_lock + +#define HICN_FACE_UDP_ENCAP_IP4 hicn_iface_udp4_encap +#define HICN_FACE_UDP_ENCAP_IP6 hicn_iface_udp6_encap + +#define TRACE_OUTPUT_PKT_UDP4 hicn_iface_udp4_output_trace_t +#define TRACE_OUTPUT_PKT_UDP6 hicn_iface_udp6_output_trace_t + +#define iface_output_x1(ipv) \ + do { \ + vlib_buffer_t *b0; \ + u32 bi0; \ + u32 next0 = ERROR_OUTPUT_UDP##ipv; \ + hicn_face_t * face; \ + \ + /* Prefetch for next iteration. */ \ + if (n_left_from > 1) \ + { \ + vlib_buffer_t *b1; \ + b1 = vlib_get_buffer (vm, from[1]); \ + CLIB_PREFETCH (b1, CLIB_CACHE_LINE_BYTES, STORE); \ + CLIB_PREFETCH (b1->data, CLIB_CACHE_LINE_BYTES , LOAD); \ + } \ + /* Dequeue a packet buffer */ \ + bi0 = from[0]; \ + from += 1; \ + n_left_from -= 1; \ + to_next[0] = bi0; \ + to_next += 1; \ + n_left_to_next -= 1; \ + \ + b0 = vlib_get_buffer (vm, bi0); \ + \ + face = \ + hicn_dpoi_get_from_idx(vnet_buffer (b0)->ip.adj_index[VLIB_TX]); \ + \ + if (PREDICT_TRUE(face != NULL)) \ + { \ + HICN_FACE_UDP_ENCAP_IP##ipv \ + (vm, b0, face); \ + next0 = NEXT_LOOKUP_UDP##ipv; \ + stats.pkts_data_count += 1; \ + } \ + \ + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && \ + (b0->flags & VLIB_BUFFER_IS_TRACED))) \ + { \ + TRACE_OUTPUT_PKT_UDP##ipv *t = \ + vlib_add_trace (vm, node, b0, sizeof (*t)); \ + t->pkt_type = HICN_PKT_TYPE_INTEREST; \ + t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; \ + t->next_index = next0; \ + } \ + \ + \ + /* Verify speculative enqueue, maybe switch current next frame */ \ + vlib_validate_buffer_enqueue_x1 (vm, node, next_index, \ + to_next, n_left_to_next, \ + bi0, next0); \ + } while(0) + +#define iface_output_x2(ipv) \ + do { \ + vlib_buffer_t *b0, *b1; \ + u32 bi0, bi1; \ + u32 next0 = ERROR_OUTPUT_UDP##ipv, next1 = ERROR_OUTPUT_UDP##ipv; \ + hicn_face_t *face0, *face1; \ + \ + /* Prefetch for next iteration. */ \ + { \ + vlib_buffer_t *b2, *b3; \ + b2 = vlib_get_buffer (vm, from[2]); \ + b3 = vlib_get_buffer (vm, from[3]); \ + CLIB_PREFETCH (b2, CLIB_CACHE_LINE_BYTES, STORE); \ + CLIB_PREFETCH (b3, CLIB_CACHE_LINE_BYTES, STORE); \ + CLIB_PREFETCH (b2->data, CLIB_CACHE_LINE_BYTES , LOAD); \ + CLIB_PREFETCH (b3->data, CLIB_CACHE_LINE_BYTES , LOAD); \ + } \ + \ + /* Dequeue packets buffers */ \ + bi0 = from[0]; \ + bi1 = from[1]; \ + from += 2; \ + n_left_from -= 2; \ + to_next[0] = bi0; \ + to_next[1] = bi1; \ + to_next += 2; \ + n_left_to_next -= 2; \ + \ + b0 = vlib_get_buffer (vm, bi0); \ + b1 = vlib_get_buffer (vm, bi1); \ + \ + face0 = \ + hicn_dpoi_get_from_idx(vnet_buffer (b0)->ip.adj_index[VLIB_TX]); \ + face1 = \ + hicn_dpoi_get_from_idx(vnet_buffer (b0)->ip.adj_index[VLIB_TX]); \ + \ + if (PREDICT_TRUE(face0 != NULL)) \ + { \ + HICN_FACE_UDP_ENCAP_IP##ipv \ + (vm, b0, face0); \ + next0 = NEXT_LOOKUP_UDP##ipv; \ + stats.pkts_data_count += 1; \ + } \ + \ + if (PREDICT_TRUE(face1 != NULL)) \ + { \ + HICN_FACE_UDP_ENCAP_IP##ipv \ + (vm, b1, face1); \ + next0 = NEXT_LOOKUP_UDP##ipv; \ + stats.pkts_data_count += 1; \ + } \ + \ + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && \ + (b0->flags & VLIB_BUFFER_IS_TRACED))) \ + { \ + TRACE_OUTPUT_PKT_UDP##ipv *t = \ + vlib_add_trace (vm, node, b0, sizeof (*t)); \ + t->pkt_type = HICN_PKT_TYPE_INTEREST; \ + t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; \ + t->next_index = next0; \ + } \ + \ + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && \ + (b1->flags & VLIB_BUFFER_IS_TRACED))) \ + { \ + TRACE_OUTPUT_PKT_UDP##ipv *t = \ + vlib_add_trace (vm, node, b1, sizeof (*t)); \ + t->pkt_type = HICN_PKT_TYPE_INTEREST; \ + t->sw_if_index = vnet_buffer (b1)->sw_if_index[VLIB_RX]; \ + t->next_index = next1; \ + } \ + \ + \ + /* Verify speculative enqueue, maybe switch current next frame */ \ + vlib_validate_buffer_enqueue_x2 (vm, node, next_index, \ + to_next, n_left_to_next, \ + bi0, bi1, next0, next1); \ + } while(0) + + +static uword +hicn_iface_udp4_output_node_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + u32 n_left_from, *from, *to_next, next_index; + vl_api_hicn_api_node_stats_get_reply_t stats = { 0 }; + + from = vlib_frame_vector_args (frame); + n_left_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) + { + iface_output_x2 (4); + } + + while (n_left_from > 0 && n_left_to_next > 0) + { + iface_output_x1 (4); + } + + vlib_put_next_frame (vm, node, next_index, n_left_to_next); + } + + vlib_node_increment_counter (vm, node->node_index, + HICNFWD_ERROR_DATAS, stats.pkts_data_count); + + return (frame->n_vectors); +} + +/* packet trace format function */ +static u8 * +hicn_iface_udp4_output_format_trace (u8 * s, va_list * args) +{ + CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); + CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); + hicn_iface_udp4_output_trace_t *t = + va_arg (*args, hicn_iface_udp4_output_trace_t *); + + s = format (s, "IFACE_UDP4_OUTPUT: pkt: %d, sw_if_index %d, next index %d", + (int) t->pkt_type, t->sw_if_index, t->next_index); + return (s); +} + + +/* + * Node registration for the interest forwarder node + */ +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (hicn_iface_udp4_output_node) = +{ + .function = hicn_iface_udp4_output_node_fn, + .name = "hicn-iface-udp4-output", + .vector_size = sizeof (u32), + .format_trace = hicn_iface_udp4_output_format_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = ARRAY_LEN (hicn_iface_udp4_output_error_strings), + .error_strings = hicn_iface_udp4_output_error_strings, + .n_next_nodes = HICN_IFACE_UDP4_OUTPUT_N_NEXT, + /* edit / add dispositions here */ + .next_nodes = + { + [HICN_IFACE_UDP4_OUTPUT_NEXT_LOOKUP] = "ip4-lookup", + [HICN_IFACE_UDP4_OUTPUT_NEXT_ERROR_DROP] = "error-drop", + }, +}; +/* *INDENT-ON* */ + + +static uword +hicn_iface_udp6_output_node_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + u32 n_left_from, *from, *to_next, next_index; + vl_api_hicn_api_node_stats_get_reply_t stats = { 0 }; + + from = vlib_frame_vector_args (frame); + n_left_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) + { + iface_output_x2 (6); + } + + while (n_left_from > 0 && n_left_to_next > 0) + { + iface_output_x1 (6); + } + + vlib_put_next_frame (vm, node, next_index, n_left_to_next); + } + + vlib_node_increment_counter (vm, node->node_index, + HICNFWD_ERROR_DATAS, stats.pkts_data_count); + + return (frame->n_vectors); + +} + +/* packet trace format function */ +static u8 * +hicn_iface_udp6_output_format_trace (u8 * s, va_list * args) +{ + CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); + CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); + hicn_iface_udp6_output_trace_t *t = + va_arg (*args, hicn_iface_udp6_output_trace_t *); + + s = format (s, "IFACE_UDP6_OUTPUT: pkt: %d, sw_if_index %d, next index %d", + (int) t->pkt_type, t->sw_if_index, t->next_index); + return (s); +} + +/* + * Node registration for the interest forwarder node + */ +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (hicn_iface_udp6_output_node) = +{ + .function = hicn_iface_udp6_output_node_fn, + .name = "hicn-iface-udp6-output", + .vector_size = sizeof (u32), + .format_trace = hicn_iface_udp6_output_format_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = ARRAY_LEN (hicn_iface_udp6_output_error_strings), + .error_strings = hicn_iface_udp6_output_error_strings, + .n_next_nodes = HICN_IFACE_UDP6_OUTPUT_N_NEXT, + /* edit / add dispositions here */ + .next_nodes = + { + [HICN_IFACE_UDP6_OUTPUT_NEXT_LOOKUP] = "ip6-lookup", + [HICN_IFACE_UDP6_OUTPUT_NEXT_ERROR_DROP] = "error-drop", + }, +}; +/* *INDENT-ON* */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ |