diff options
Diffstat (limited to 'src/vnet')
-rw-r--r-- | src/vnet/ip/ip6_forward.c | 206 |
1 files changed, 134 insertions, 72 deletions
diff --git a/src/vnet/ip/ip6_forward.c b/src/vnet/ip/ip6_forward.c index a7886e630bf..bef2234976d 100644 --- a/src/vnet/ip/ip6_forward.c +++ b/src/vnet/ip/ip6_forward.c @@ -1116,74 +1116,108 @@ ip6_local_inline (vlib_main_t * vm, vlib_node_runtime_t * node, b = bufs; next = nexts; -#define N 2 -#define xN for (int n=0; n<N; n++) - - while (n_left_from > N) + while (n_left_from > 2) { /* Prefetch next iteration. */ - if (n_left_from >= 3 * N) + if (n_left_from >= 6) { - xN vlib_prefetch_buffer_header (b[2 * N + n], STORE); - xN vlib_prefetch_buffer_data (b[1 * N + n], LOAD); + vlib_prefetch_buffer_header (b[4], STORE); + vlib_prefetch_buffer_header (b[5], STORE); + vlib_prefetch_buffer_data (b[2], LOAD); + vlib_prefetch_buffer_data (b[3], LOAD); } - u8 error[N]; - xN error[n] = IP6_ERROR_UNKNOWN_PROTOCOL; + u8 error[2]; + error[0] = IP6_ERROR_UNKNOWN_PROTOCOL; + error[1] = IP6_ERROR_UNKNOWN_PROTOCOL; - ip6_header_t *ip[N]; - xN ip[n] = vlib_buffer_get_current (b[n]); + ip6_header_t *ip[2]; + ip[0] = vlib_buffer_get_current (b[0]); + ip[1] = vlib_buffer_get_current (b[1]); if (head_of_feature_arc) { - xN vnet_buffer (b[n])->l3_hdr_offset = b[n]->current_data; + vnet_buffer (b[0])->l3_hdr_offset = b[0]->current_data; + vnet_buffer (b[1])->l3_hdr_offset = b[1]->current_data; - u8 type[N]; - xN type[n] = lm->builtin_protocol_by_ip_protocol[ip[n]->protocol]; + u8 type[2]; + type[0] = lm->builtin_protocol_by_ip_protocol[ip[0]->protocol]; + type[1] = lm->builtin_protocol_by_ip_protocol[ip[1]->protocol]; - u32 flags[N]; - xN flags[n] = b[n]->flags; + u32 flags[2]; + flags[0] = b[0]->flags; + flags[1] = b[1]->flags; - u32 good_l4_csum[N]; - xN good_l4_csum[n] = - flags[n] & (VNET_BUFFER_F_L4_CHECKSUM_CORRECT | + u32 good_l4_csum[2]; + good_l4_csum[0] = + flags[0] & (VNET_BUFFER_F_L4_CHECKSUM_CORRECT | + VNET_BUFFER_F_OFFLOAD_TCP_CKSUM | + VNET_BUFFER_F_OFFLOAD_UDP_CKSUM); + good_l4_csum[1] = + flags[1] & (VNET_BUFFER_F_L4_CHECKSUM_CORRECT | VNET_BUFFER_F_OFFLOAD_TCP_CKSUM | VNET_BUFFER_F_OFFLOAD_UDP_CKSUM); - u32 udp_offset[N]; - u8 is_tcp_udp[N]; - xN is_tcp_udp[n] = - ip6_next_proto_is_tcp_udp (b[n], ip[n], &udp_offset[n]); - i16 len_diff[N] = { 0 }; - xN if (PREDICT_TRUE (is_tcp_udp[n])) + u32 udp_offset[2]; + u8 is_tcp_udp[2]; + is_tcp_udp[0] = + ip6_next_proto_is_tcp_udp (b[0], ip[0], &udp_offset[0]); + is_tcp_udp[1] = + ip6_next_proto_is_tcp_udp (b[1], ip[1], &udp_offset[1]); + i16 len_diff[2] = { 0 }; + if (PREDICT_TRUE (is_tcp_udp[0])) + { + udp_header_t *udp = + (udp_header_t *) ((u8 *) ip[0] + udp_offset[0]); + good_l4_csum[0] |= type[0] == IP_BUILTIN_PROTOCOL_UDP + && udp->checksum == 0; + /* optimistically verify UDP length. */ + u16 ip_len, udp_len; + ip_len = clib_net_to_host_u16 (ip[0]->payload_length); + udp_len = clib_net_to_host_u16 (udp->length); + len_diff[0] = ip_len - udp_len; + } + if (PREDICT_TRUE (is_tcp_udp[1])) { udp_header_t *udp = - (udp_header_t *) ((u8 *) ip[n] + udp_offset[n]); - good_l4_csum[n] |= type[n] == IP_BUILTIN_PROTOCOL_UDP + (udp_header_t *) ((u8 *) ip[1] + udp_offset[1]); + good_l4_csum[1] |= type[1] == IP_BUILTIN_PROTOCOL_UDP && udp->checksum == 0; /* optimistically verify UDP length. */ u16 ip_len, udp_len; - ip_len = clib_net_to_host_u16 (ip[n]->payload_length); + ip_len = clib_net_to_host_u16 (ip[1]->payload_length); udp_len = clib_net_to_host_u16 (udp->length); - len_diff[n] = ip_len - udp_len; + len_diff[1] = ip_len - udp_len; } - xN good_l4_csum[n] |= type[n] == IP_BUILTIN_PROTOCOL_UNKNOWN; - xN len_diff[n] = - type[n] == IP_BUILTIN_PROTOCOL_UDP ? len_diff[n] : 0; + good_l4_csum[0] |= type[0] == IP_BUILTIN_PROTOCOL_UNKNOWN; + good_l4_csum[1] |= type[1] == IP_BUILTIN_PROTOCOL_UNKNOWN; + + len_diff[0] = type[0] == IP_BUILTIN_PROTOCOL_UDP ? len_diff[0] : 0; + len_diff[1] = type[1] == IP_BUILTIN_PROTOCOL_UDP ? len_diff[1] : 0; - u8 need_csum[N]; - xN need_csum[n] = type[n] != IP_BUILTIN_PROTOCOL_UNKNOWN - && !good_l4_csum[n] - && !(flags[n] & VNET_BUFFER_F_L4_CHECKSUM_COMPUTED); - xN if (PREDICT_FALSE (need_csum[n])) + u8 need_csum[2]; + need_csum[0] = type[0] != IP_BUILTIN_PROTOCOL_UNKNOWN + && !good_l4_csum[0] + && !(flags[0] & VNET_BUFFER_F_L4_CHECKSUM_COMPUTED); + need_csum[1] = type[1] != IP_BUILTIN_PROTOCOL_UNKNOWN + && !good_l4_csum[1] + && !(flags[1] & VNET_BUFFER_F_L4_CHECKSUM_COMPUTED); + if (PREDICT_FALSE (need_csum[0])) { - flags[n] = ip6_tcp_udp_icmp_validate_checksum (vm, b[n]); - good_l4_csum[n] = flags[n] & VNET_BUFFER_F_L4_CHECKSUM_CORRECT; + flags[0] = ip6_tcp_udp_icmp_validate_checksum (vm, b[0]); + good_l4_csum[0] = flags[0] & VNET_BUFFER_F_L4_CHECKSUM_CORRECT; + } + if (PREDICT_FALSE (need_csum[1])) + { + flags[1] = ip6_tcp_udp_icmp_validate_checksum (vm, b[1]); + good_l4_csum[1] = flags[1] & VNET_BUFFER_F_L4_CHECKSUM_CORRECT; } - xN error[n] = IP6_ERROR_UNKNOWN_PROTOCOL; - xN error[n] = len_diff[n] < 0 ? IP6_ERROR_UDP_LENGTH : error[n]; + error[0] = IP6_ERROR_UNKNOWN_PROTOCOL; + error[0] = len_diff[0] < 0 ? IP6_ERROR_UDP_LENGTH : error[0]; + error[1] = IP6_ERROR_UNKNOWN_PROTOCOL; + error[1] = len_diff[1] < 0 ? IP6_ERROR_UDP_LENGTH : error[1]; STATIC_ASSERT (IP6_ERROR_UDP_CHECKSUM + IP_BUILTIN_PROTOCOL_UDP == IP6_ERROR_UDP_CHECKSUM, @@ -1192,56 +1226,84 @@ ip6_local_inline (vlib_main_t * vm, vlib_node_runtime_t * node, IP6_ERROR_ICMP_CHECKSUM, "Wrong IP6 errors constants"); - xN error[n] = - !good_l4_csum[n] ? IP6_ERROR_UDP_CHECKSUM + type[n] : error[n]; + error[0] = + !good_l4_csum[0] ? IP6_ERROR_UDP_CHECKSUM + type[0] : error[0]; + error[1] = + !good_l4_csum[1] ? IP6_ERROR_UDP_CHECKSUM + type[1] : error[1]; /* Drop packets from unroutable hosts. */ /* If this is a neighbor solicitation (ICMP), skip source RPF check */ - u8 unroutable[N]; - xN unroutable[n] = error[n] == IP6_ERROR_UNKNOWN_PROTOCOL - && type[n] != IP_BUILTIN_PROTOCOL_ICMP - && !ip6_address_is_link_local_unicast (&ip[n]->src_address); - xN if (PREDICT_FALSE (unroutable[n])) + u8 unroutable[2]; + unroutable[0] = error[0] == IP6_ERROR_UNKNOWN_PROTOCOL + && type[0] != IP_BUILTIN_PROTOCOL_ICMP + && !ip6_address_is_link_local_unicast (&ip[0]->src_address); + unroutable[1] = error[1] == IP6_ERROR_UNKNOWN_PROTOCOL + && type[1] != IP_BUILTIN_PROTOCOL_ICMP + && !ip6_address_is_link_local_unicast (&ip[1]->src_address); + if (PREDICT_FALSE (unroutable[0])) { - error[n] = - !ip6_urpf_loose_check (im, b[n], - ip[n]) ? IP6_ERROR_SRC_LOOKUP_MISS - : error[n]; + error[0] = + !ip6_urpf_loose_check (im, b[0], + ip[0]) ? IP6_ERROR_SRC_LOOKUP_MISS + : error[0]; + } + if (PREDICT_FALSE (unroutable[1])) + { + error[1] = + !ip6_urpf_loose_check (im, b[1], + ip[1]) ? IP6_ERROR_SRC_LOOKUP_MISS + : error[1]; } - xN vnet_buffer (b[n])->ip.fib_index = - vnet_buffer (b[n])->sw_if_index[VLIB_TX] != ~0 ? - vnet_buffer (b[n])->sw_if_index[VLIB_TX] : - vnet_buffer (b[n])->ip.fib_index; + vnet_buffer (b[0])->ip.fib_index = + vnet_buffer (b[0])->sw_if_index[VLIB_TX] != ~0 ? + vnet_buffer (b[0])->sw_if_index[VLIB_TX] : + vnet_buffer (b[0])->ip.fib_index; + vnet_buffer (b[1])->ip.fib_index = + vnet_buffer (b[1])->sw_if_index[VLIB_TX] != ~0 ? + vnet_buffer (b[1])->sw_if_index[VLIB_TX] : + vnet_buffer (b[1])->ip.fib_index; } /* head_of_feature_arc */ - xN next[n] = lm->local_next_by_ip_protocol[ip[n]->protocol]; - xN next[n] = - error[n] != IP6_ERROR_UNKNOWN_PROTOCOL ? IP_LOCAL_NEXT_DROP : next[n]; + next[0] = lm->local_next_by_ip_protocol[ip[0]->protocol]; + next[0] = + error[0] != IP6_ERROR_UNKNOWN_PROTOCOL ? IP_LOCAL_NEXT_DROP : next[0]; + next[1] = lm->local_next_by_ip_protocol[ip[1]->protocol]; + next[1] = + error[1] != IP6_ERROR_UNKNOWN_PROTOCOL ? IP_LOCAL_NEXT_DROP : next[1]; - xN b[n]->error = error_node->errors[n]; + b[0]->error = error_node->errors[0]; + b[1]->error = error_node->errors[1]; if (head_of_feature_arc) { - u8 ip6_unknown[N]; - xN ip6_unknown[n] = error[n] == (u8) IP6_ERROR_UNKNOWN_PROTOCOL; - xN if (PREDICT_TRUE (ip6_unknown[n])) + u8 ip6_unknown[2]; + ip6_unknown[0] = error[0] == (u8) IP6_ERROR_UNKNOWN_PROTOCOL; + ip6_unknown[1] = error[1] == (u8) IP6_ERROR_UNKNOWN_PROTOCOL; + if (PREDICT_TRUE (ip6_unknown[0])) { - u32 next32 = next[n]; + u32 next32 = next[0]; vnet_feature_arc_start (arc_index, - vnet_buffer (b[n])->sw_if_index - [VLIB_RX], &next32, b[n]); - next[n] = next32; + vnet_buffer (b[0])->sw_if_index + [VLIB_RX], &next32, b[0]); + next[0] = next32; + } + if (PREDICT_TRUE (ip6_unknown[1])) + { + u32 next32 = next[1]; + vnet_feature_arc_start (arc_index, + vnet_buffer (b[1])->sw_if_index + [VLIB_RX], &next32, b[1]); + next[1] = next32; } } /* next */ - b += N; - next += N; - n_left_from -= N; + b += 2; + next += 2; + n_left_from -= 2; } -#undef xN -#undef N + while (n_left_from) { u8 error; |