X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fip%2Fip6_forward.c;h=06c473b1495cc67997b9d0fbcc011fa0f3a6078d;hb=2f4586d9b3507243918c11ce99b9d151d5bde7a0;hp=4cb7608d0b4039a2229b56909402dac49a974320;hpb=cbe25aab3be72154f2c706c39eeba6a77f34450f;p=vpp.git diff --git a/src/vnet/ip/ip6_forward.c b/src/vnet/ip/ip6_forward.c index 4cb7608d0b4..06c473b1495 100644 --- a/src/vnet/ip/ip6_forward.c +++ b/src/vnet/ip/ip6_forward.c @@ -48,7 +48,10 @@ #include #include #include +#include #include +#include +#include #ifndef CLIB_MARCH_VARIANT #include @@ -68,7 +71,6 @@ ip6_add_interface_prefix_routes (ip6_main_t * im, ip_lookup_main_t *lm = &im->lookup_main; ip_interface_prefix_t *if_prefix; - /* *INDENT-OFF* */ ip_interface_prefix_key_t key = { .prefix = { .fp_len = address_length, @@ -82,7 +84,6 @@ ip6_add_interface_prefix_routes (ip6_main_t * im, }, .sw_if_index = sw_if_index, }; - /* *INDENT-ON* */ /* If prefix already set on interface, just increment ref count & return */ if_prefix = ip_get_interface_prefix (lm, &key); @@ -175,7 +176,6 @@ ip6_del_interface_prefix_routes (ip6_main_t * im, ip_lookup_main_t *lm = &im->lookup_main; ip_interface_prefix_t *if_prefix; - /* *INDENT-OFF* */ ip_interface_prefix_key_t key = { .prefix = { .fp_len = address_length, @@ -189,13 +189,12 @@ ip6_del_interface_prefix_routes (ip6_main_t * im, }, .sw_if_index = sw_if_index, }; - /* *INDENT-ON* */ if_prefix = ip_get_interface_prefix (lm, &key); if (!if_prefix) { clib_warning ("Prefix not found while deleting %U", - format_ip4_address_and_length, address, address_length); + format_ip6_address_and_length, address, address_length); return; } @@ -238,6 +237,8 @@ void ip6_sw_interface_enable_disable (u32 sw_if_index, u32 is_enable) { ip6_main_t *im = &ip6_main; + vnet_main_t *vnm = vnet_get_main (); + vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm, sw_if_index); vec_validate_init_empty (im->ip_enabled_by_sw_if_index, sw_if_index, 0); @@ -263,6 +264,11 @@ ip6_sw_interface_enable_disable (u32 sw_if_index, u32 is_enable) vnet_feature_enable_disable ("ip6-multicast", "ip6-not-enabled", sw_if_index, !is_enable, 0, 0); + + if (is_enable) + hi->l3_if_count++; + else if (hi->l3_if_count) + hi->l3_if_count--; } /* get first interface address */ @@ -273,7 +279,6 @@ ip6_interface_first_address (ip6_main_t * im, u32 sw_if_index) ip_interface_address_t *ia = 0; ip6_address_t *result = 0; - /* *INDENT-OFF* */ foreach_ip_interface_address (lm, ia, sw_if_index, 1 /* honor unnumbered */, ({ @@ -281,7 +286,6 @@ ip6_interface_first_address (ip6_main_t * im, u32 sw_if_index) result = a; break; })); - /* *INDENT-ON* */ return result; } @@ -294,16 +298,16 @@ ip6_add_del_interface_address (vlib_main_t * vm, vnet_main_t *vnm = vnet_get_main (); ip6_main_t *im = &ip6_main; ip_lookup_main_t *lm = &im->lookup_main; - clib_error_t *error; + clib_error_t *error = NULL; u32 if_address_index; ip6_address_fib_t ip6_af, *addr_fib = 0; const ip6_address_t *ll_addr; - /* local0 interface doesn't support IP addressing */ - if (sw_if_index == 0) + error = vnet_sw_interface_supports_addressing (vnm, sw_if_index); + if (error) { - return - clib_error_create ("local0 interface doesn't support IP addressing"); + vnm->api_errno = VNET_API_ERROR_UNSUPPORTED; + return error; } if (ip6_address_is_link_local_unicast (address)) @@ -319,7 +323,7 @@ ip6_add_del_interface_address (vlib_main_t * vm, { int rv; - rv = ip6_set_link_local_address (sw_if_index, address); + rv = ip6_link_set_local_address (sw_if_index, address); if (rv) { @@ -341,16 +345,14 @@ ip6_add_del_interface_address (vlib_main_t * vm, return clib_error_create ("address not found"); } } - } - vec_validate (im->fib_index_by_sw_if_index, sw_if_index); - vec_validate (im->mfib_index_by_sw_if_index, sw_if_index); + return (NULL); + } ip6_addr_fib_init (&ip6_af, address, vec_elt (im->fib_index_by_sw_if_index, sw_if_index)); vec_add1 (addr_fib, ip6_af); - /* *INDENT-OFF* */ if (!is_del) { /* When adding an address check that it does not conflict @@ -358,8 +360,8 @@ ip6_add_del_interface_address (vlib_main_t * vm, ip_interface_address_t *ia; vnet_sw_interface_t *sif; - pool_foreach(sif, vnm->interface_main.sw_interfaces, - ({ + pool_foreach (sif, vnm->interface_main.sw_interfaces) + { if (im->fib_index_by_sw_if_index[sw_if_index] == im->fib_index_by_sw_if_index[sif->sw_if_index]) { @@ -370,6 +372,7 @@ ip6_add_del_interface_address (vlib_main_t * vm, ip6_address_t * x = ip_interface_address_get_address (&im->lookup_main, ia); + if (ip6_destination_matches_route (im, address, x, ia->address_length) || ip6_destination_matches_route (im, @@ -383,10 +386,17 @@ ip6_add_del_interface_address (vlib_main_t * vm, !ip6_address_is_equal (x, address)) continue; + if (ia->flags & IP_INTERFACE_ADDRESS_FLAG_STALE) + /* if the address we're comparing against is stale + * then the CP has not added this one back yet, maybe + * it never will, so we have to assume it won't and + * ignore it. if it does add it back, then it will fail + * because this one is now present */ + continue; + /* error if the length or intf was different */ vnm->api_errno = VNET_API_ERROR_DUPLICATE_IF_ADDRESS; - return - clib_error_create + error = clib_error_create ("failed to add %U which conflicts with %U for interface %U", format_ip6_address_and_length, address, address_length, @@ -394,29 +404,85 @@ ip6_add_del_interface_address (vlib_main_t * vm, ia->address_length, format_vnet_sw_if_index_name, vnm, sif->sw_if_index); + goto done; } })); } - })); + } } - /* *INDENT-ON* */ - { - uword elts_before = pool_elts (lm->if_address_pool); + if_address_index = ip_interface_address_find (lm, addr_fib, address_length); - error = ip_interface_address_add_del - (lm, sw_if_index, addr_fib, address_length, is_del, &if_address_index); - if (error) - goto done; + if (is_del) + { + if (~0 == if_address_index) + { + vnm->api_errno = VNET_API_ERROR_ADDRESS_NOT_FOUND_FOR_INTERFACE; + error = clib_error_create ("%U not found for interface %U", + lm->format_address_and_length, + addr_fib, address_length, + format_vnet_sw_if_index_name, vnm, + sw_if_index); + goto done; + } - /* Pool did not grow: add duplicate address. */ - if (elts_before == pool_elts (lm->if_address_pool)) - goto done; - } + error = ip_interface_address_del (lm, vnm, if_address_index, addr_fib, + address_length, sw_if_index); + if (error) + goto done; + } + else + { + if (~0 != if_address_index) + { + ip_interface_address_t *ia; + + ia = pool_elt_at_index (lm->if_address_pool, if_address_index); + + if (ia->flags & IP_INTERFACE_ADDRESS_FLAG_STALE) + { + if (ia->sw_if_index == sw_if_index) + { + /* re-adding an address during the replace action. + * consdier this the update. clear the flag and + * we're done */ + ia->flags &= ~IP_INTERFACE_ADDRESS_FLAG_STALE; + goto done; + } + else + { + /* The prefix is moving from one interface to another. + * delete the stale and add the new */ + ip6_add_del_interface_address (vm, + ia->sw_if_index, + address, address_length, 1); + ia = NULL; + error = ip_interface_address_add (lm, sw_if_index, + addr_fib, address_length, + &if_address_index); + } + } + else + { + vnm->api_errno = VNET_API_ERROR_DUPLICATE_IF_ADDRESS; + error = clib_error_create + ("Prefix %U already found on interface %U", + lm->format_address_and_length, addr_fib, address_length, + format_vnet_sw_if_index_name, vnm, ia->sw_if_index); + } + } + else + error = ip_interface_address_add (lm, sw_if_index, + addr_fib, address_length, + &if_address_index); + } + + if (error) + goto done; ip6_sw_interface_enable_disable (sw_if_index, !is_del); if (!is_del) - ip6_link_enable (sw_if_index); + ip6_link_enable (sw_if_index, NULL); /* intf addr routes are added/deleted on admin up/down */ if (vnet_sw_interface_is_admin_up (vnm, sw_if_index)) @@ -431,12 +497,12 @@ ip6_add_del_interface_address (vlib_main_t * vm, pool_elt_at_index (lm->if_address_pool, if_address_index)); } - { - ip6_add_del_interface_address_callback_t *cb; - vec_foreach (cb, im->add_del_interface_address_callbacks) - cb->function (im, cb->function_opaque, sw_if_index, - address, address_length, if_address_index, is_del); - } + + ip6_add_del_interface_address_callback_t *cb; + vec_foreach (cb, im->add_del_interface_address_callbacks) + cb->function (im, cb->function_opaque, sw_if_index, + address, address_length, if_address_index, is_del); + if (is_del) ip6_link_disable (sw_if_index); @@ -455,9 +521,6 @@ ip6_sw_interface_admin_up_down (vnet_main_t * vnm, u32 sw_if_index, u32 flags) ip6_address_t *a; u32 is_admin_up, fib_index; - /* Fill in lookup tables with default table (0). */ - vec_validate (im->fib_index_by_sw_if_index, sw_if_index); - vec_validate_init_empty (im-> lookup_main.if_address_pool_index_by_sw_if_index, sw_if_index, ~0); @@ -466,7 +529,6 @@ ip6_sw_interface_admin_up_down (vnet_main_t * vnm, u32 sw_if_index, u32 flags) fib_index = vec_elt (im->fib_index_by_sw_if_index, sw_if_index); - /* *INDENT-OFF* */ foreach_ip_interface_address (&im->lookup_main, ia, sw_if_index, 0 /* honor unnumbered */, ({ @@ -479,7 +541,6 @@ ip6_sw_interface_admin_up_down (vnet_main_t * vnm, u32 sw_if_index, u32 flags) ip6_del_interface_routes (sw_if_index, im, fib_index, a, ia->address_length); })); - /* *INDENT-ON* */ return 0; } @@ -487,7 +548,6 @@ ip6_sw_interface_admin_up_down (vnet_main_t * vnm, u32 sw_if_index, u32 flags) VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (ip6_sw_interface_admin_up_down); /* Built-in ip6 unicast rx feature path definition */ -/* *INDENT-OFF* */ VNET_FEATURE_ARC_INIT (ip6_unicast, static) = { .arc_name = "ip6-unicast", @@ -612,17 +672,22 @@ VNET_FEATURE_INIT (ip6_interface_output, static) = { .node_name = "interface-output", .runs_before = 0, /* not before any other features */ }; -/* *INDENT-ON* */ static clib_error_t * ip6_sw_interface_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_add) { ip6_main_t *im = &ip6_main; - vec_validate (im->fib_index_by_sw_if_index, sw_if_index); - vec_validate (im->mfib_index_by_sw_if_index, sw_if_index); + vec_validate_init_empty (im->fib_index_by_sw_if_index, sw_if_index, ~0); + vec_validate_init_empty (im->mfib_index_by_sw_if_index, sw_if_index, ~0); - if (!is_add) + if (is_add) + { + /* Fill in lookup tables with default table (0). */ + im->fib_index_by_sw_if_index[sw_if_index] = 0; + im->mfib_index_by_sw_if_index[sw_if_index] = 0; + } + else { /* Ensure that IPv6 is disabled */ ip6_main_t *im6 = &ip6_main; @@ -632,14 +697,21 @@ ip6_sw_interface_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_add) vlib_main_t *vm = vlib_get_main (); vnet_sw_interface_update_unnumbered (sw_if_index, ~0, 0); - /* *INDENT-OFF* */ foreach_ip_interface_address (lm6, ia, sw_if_index, 0, ({ address = ip_interface_address_get_address (lm6, ia); ip6_add_del_interface_address(vm, sw_if_index, address, ia->address_length, 1); })); - /* *INDENT-ON* */ ip6_mfib_interface_enable_disable (sw_if_index, 0); + + if (0 != im6->fib_index_by_sw_if_index[sw_if_index]) + fib_table_bind (FIB_PROTOCOL_IP6, sw_if_index, 0); + if (0 != im6->mfib_index_by_sw_if_index[sw_if_index]) + mfib_table_bind (FIB_PROTOCOL_IP6, sw_if_index, 0); + + /* Erase the lookup tables just in case */ + im6->fib_index_by_sw_if_index[sw_if_index] = ~0; + im6->mfib_index_by_sw_if_index[sw_if_index] = ~0; } vnet_feature_enable_disable ("ip6-unicast", "ip6-not-enabled", sw_if_index, @@ -662,7 +734,6 @@ VLIB_NODE_FN (ip6_lookup_node) (vlib_main_t * vm, static u8 *format_ip6_lookup_trace (u8 * s, va_list * args); -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (ip6_lookup_node) = { .name = "ip6-lookup", @@ -671,7 +742,6 @@ VLIB_REGISTER_NODE (ip6_lookup_node) = .n_next_nodes = IP6_LOOKUP_N_NEXT, .next_nodes = IP6_LOOKUP_NEXT_NODES, }; -/* *INDENT-ON* */ VLIB_NODE_FN (ip6_load_balance_node) (vlib_main_t * vm, vlib_node_runtime_t * node, @@ -849,7 +919,6 @@ VLIB_NODE_FN (ip6_load_balance_node) (vlib_main_t * vm, return frame->n_vectors; } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (ip6_load_balance_node) = { .name = "ip6-load-balance", @@ -857,7 +926,6 @@ VLIB_REGISTER_NODE (ip6_load_balance_node) = .sibling_of = "ip6-lookup", .format_trace = format_ip6_lookup_trace, }; -/* *INDENT-ON* */ typedef struct { @@ -880,7 +948,10 @@ format_ip6_forward_next_trace (u8 * s, va_list * args) ip6_forward_next_trace_t *t = va_arg (*args, ip6_forward_next_trace_t *); u32 indent = format_get_indent (s); - s = format (s, "%U%U", + s = format (s, "%Ufib:%d adj:%d flow:%d", + format_white_space, indent, + t->fib_index, t->adj_index, t->flow_hash); + s = format (s, "\n%U%U", format_white_space, indent, format_ip6_header, t->packet_data, sizeof (t->packet_data)); return s; @@ -1020,31 +1091,23 @@ u16 ip6_tcp_udp_icmp_compute_checksum (vlib_main_t * vm, vlib_buffer_t * p0, ip6_header_t * ip0, int *bogus_lengthp) { - ip_csum_t sum0; - u16 payload_length_host_byte_order; + ip_csum_t sum0 = 0; + u16 payload_length, payload_length_host_byte_order; u32 i; u32 headers_size = sizeof (ip0[0]); u8 *data_this_buffer; + u8 next_hdr = ip0->protocol; ASSERT (bogus_lengthp); *bogus_lengthp = 0; - /* Initialize checksum with ip header. */ - sum0 = ip0->payload_length + clib_host_to_net_u16 (ip0->protocol); payload_length_host_byte_order = clib_net_to_host_u16 (ip0->payload_length); data_this_buffer = (u8 *) (ip0 + 1); - - for (i = 0; i < ARRAY_LEN (ip0->src_address.as_uword); i++) - { - sum0 = ip_csum_with_carry - (sum0, clib_mem_unaligned (&ip0->src_address.as_uword[i], uword)); - sum0 = ip_csum_with_carry - (sum0, clib_mem_unaligned (&ip0->dst_address.as_uword[i], uword)); - } + payload_length = ip0->payload_length; /* some icmp packets may come with a "router alert" hop-by-hop extension header (e.g., mldv2 packets) * or UDP-Ping packets */ - if (PREDICT_FALSE (ip0->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)) + if (PREDICT_FALSE (next_hdr == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)) { u32 skip_bytes; ip6_hop_by_hop_ext_t *ext_hdr = @@ -1059,6 +1122,24 @@ ip6_tcp_udp_icmp_compute_checksum (vlib_main_t * vm, vlib_buffer_t * p0, payload_length_host_byte_order -= skip_bytes; headers_size += skip_bytes; + + /* pseudo-header adjustments: + * exclude ext header bytes from payload length + * use payload IP proto rather than ext header IP proto + */ + payload_length = clib_host_to_net_u16 (payload_length_host_byte_order); + next_hdr = ext_hdr->next_hdr; + } + + /* Initialize checksum with ip pseudo-header. */ + sum0 = payload_length + clib_host_to_net_u16 (next_hdr); + + for (i = 0; i < ARRAY_LEN (ip0->src_address.as_uword); i++) + { + sum0 = ip_csum_with_carry + (sum0, clib_mem_unaligned (&ip0->src_address.as_uword[i], uword)); + sum0 = ip_csum_with_carry + (sum0, clib_mem_unaligned (&ip0->dst_address.as_uword[i], uword)); } if (p0) @@ -1128,23 +1209,17 @@ always_inline u8 ip6_next_proto_is_tcp_udp (vlib_buffer_t * p0, ip6_header_t * ip0, u32 * udp_offset0) { - u32 proto0; - proto0 = ip6_locate_header (p0, ip0, IP_PROTOCOL_UDP, udp_offset0); - if (proto0 != IP_PROTOCOL_UDP) - { - proto0 = ip6_locate_header (p0, ip0, IP_PROTOCOL_TCP, udp_offset0); - proto0 = (proto0 == IP_PROTOCOL_TCP) ? proto0 : 0; - } - return proto0; + int nh = ip6_locate_header (p0, ip0, -1, udp_offset0); + if (nh > 0) + if (nh == IP_PROTOCOL_UDP || nh == IP_PROTOCOL_TCP) + return nh; + return 0; } -/* *INDENT-OFF* */ -VNET_FEATURE_ARC_INIT (ip6_local) = -{ - .arc_name = "ip6-local", - .start_nodes = VNET_FEATURES ("ip6-local"), +VNET_FEATURE_ARC_INIT (ip6_local) = { + .arc_name = "ip6-local", + .start_nodes = VNET_FEATURES ("ip6-local", "ip6-receive"), }; -/* *INDENT-ON* */ static_always_inline u8 ip6_tcp_udp_icmp_bad_length (vlib_main_t * vm, vlib_buffer_t * p0) @@ -1181,7 +1256,7 @@ ip6_tcp_udp_icmp_bad_length (vlib_main_t * vm, vlib_buffer_t * p0) } n_bytes_left -= n_this_buffer; - n_bytes_left -= p0->total_length_not_including_first_buffer; + n_bytes_left -= vlib_buffer_length_in_chain (vm, p0) - p0->current_length; if (n_bytes_left == 0) return 0; @@ -1189,10 +1264,10 @@ ip6_tcp_udp_icmp_bad_length (vlib_main_t * vm, vlib_buffer_t * p0) return 1; } - always_inline uword -ip6_local_inline (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_frame_t * frame, int head_of_feature_arc) +ip6_local_inline (vlib_main_t *vm, vlib_node_runtime_t *node, + vlib_frame_t *frame, int head_of_feature_arc, + int is_receive_dpo) { ip6_main_t *im = &ip6_main; ip_lookup_main_t *lm = &im->lookup_main; @@ -1224,7 +1299,7 @@ ip6_local_inline (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_prefetch_buffer_data (b[3], LOAD); } - u8 error[2]; + vl_counter_ip6_enum_t error[2]; error[0] = IP6_ERROR_UNKNOWN_PROTOCOL; error[1] = IP6_ERROR_UNKNOWN_PROTOCOL; @@ -1245,15 +1320,23 @@ ip6_local_inline (vlib_main_t * vm, vlib_node_runtime_t * node, flags[0] = b[0]->flags; flags[1] = b[1]->flags; + vnet_buffer_oflags_t oflags[2]; + oflags[0] = vnet_buffer (b[0])->oflags; + oflags[1] = vnet_buffer (b[1])->oflags; + + u32 l4_offload[2]; + l4_offload[0] = (flags[0] & VNET_BUFFER_F_OFFLOAD) && + (oflags[0] & (VNET_BUFFER_OFFLOAD_F_TCP_CKSUM | + VNET_BUFFER_OFFLOAD_F_UDP_CKSUM)); + l4_offload[1] = (flags[1] & VNET_BUFFER_F_OFFLOAD) && + (oflags[1] & (VNET_BUFFER_OFFLOAD_F_TCP_CKSUM | + VNET_BUFFER_OFFLOAD_F_UDP_CKSUM)); + 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); + (flags[0] & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) | l4_offload[0]; good_l4_csum[1] = - flags[1] & (VNET_BUFFER_F_L4_CHECKSUM_CORRECT | - VNET_BUFFER_F_OFFLOAD_TCP_CKSUM | - VNET_BUFFER_F_OFFLOAD_UDP_CKSUM); + (flags[1] & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) | l4_offload[1]; u32 udp_offset[2] = { }; u8 is_tcp_udp[2]; @@ -1372,6 +1455,23 @@ ip6_local_inline (vlib_main_t * vm, vlib_node_runtime_t * node, 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; + + vnet_buffer (b[0])->ip.rx_sw_if_index = + vnet_buffer (b[0])->sw_if_index[VLIB_RX]; + vnet_buffer (b[1])->ip.rx_sw_if_index = + vnet_buffer (b[1])->sw_if_index[VLIB_RX]; + if (is_receive_dpo) + { + const receive_dpo_t *rd0, *rd1; + rd0 = + receive_dpo_get (vnet_buffer (b[0])->ip.adj_index[VLIB_TX]); + rd1 = + receive_dpo_get (vnet_buffer (b[1])->ip.adj_index[VLIB_TX]); + if (rd0->rd_sw_if_index != ~0) + vnet_buffer (b[0])->ip.rx_sw_if_index = rd0->rd_sw_if_index; + if (rd1->rd_sw_if_index != ~0) + vnet_buffer (b[1])->ip.rx_sw_if_index = rd1->rd_sw_if_index; + } } /* head_of_feature_arc */ next[0] = lm->local_next_by_ip_protocol[ip[0]->protocol]; @@ -1381,8 +1481,8 @@ ip6_local_inline (vlib_main_t * vm, vlib_node_runtime_t * node, next[1] = error[1] != IP6_ERROR_UNKNOWN_PROTOCOL ? IP_LOCAL_NEXT_DROP : next[1]; - b[0]->error = error_node->errors[0]; - b[1]->error = error_node->errors[1]; + b[0]->error = error_node->errors[error[0]]; + b[1]->error = error_node->errors[error[1]]; if (head_of_feature_arc) { @@ -1393,16 +1493,16 @@ ip6_local_inline (vlib_main_t * vm, vlib_node_runtime_t * node, { u32 next32 = next[0]; vnet_feature_arc_start (arc_index, - vnet_buffer (b[0])->sw_if_index - [VLIB_RX], &next32, b[0]); + vnet_buffer (b[0])->ip.rx_sw_if_index, + &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]); + vnet_buffer (b[1])->ip.rx_sw_if_index, + &next32, b[1]); next[1] = next32; } } @@ -1427,11 +1527,15 @@ ip6_local_inline (vlib_main_t * vm, vlib_node_runtime_t * node, u8 type = lm->builtin_protocol_by_ip_protocol[ip->protocol]; u32 flags = b[0]->flags; - u32 good_l4_csum = - flags & (VNET_BUFFER_F_L4_CHECKSUM_CORRECT | - VNET_BUFFER_F_OFFLOAD_TCP_CKSUM | - VNET_BUFFER_F_OFFLOAD_UDP_CKSUM); + vnet_buffer_oflags_t oflags = vnet_buffer (b[0])->oflags; + + u32 l4_offload = (flags & VNET_BUFFER_F_OFFLOAD) && + (oflags & (VNET_BUFFER_OFFLOAD_F_TCP_CKSUM | + VNET_BUFFER_OFFLOAD_F_UDP_CKSUM)); + + u32 good_l4_csum = + (flags & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) | l4_offload; u32 udp_offset; i16 len_diff = 0; u8 is_tcp_udp = ip6_next_proto_is_tcp_udp (b[0], ip, &udp_offset); @@ -1451,8 +1555,9 @@ ip6_local_inline (vlib_main_t * vm, vlib_node_runtime_t * node, good_l4_csum |= type == IP_BUILTIN_PROTOCOL_UNKNOWN; len_diff = type == IP_BUILTIN_PROTOCOL_UDP ? len_diff : 0; - u8 need_csum = type != IP_BUILTIN_PROTOCOL_UNKNOWN && !good_l4_csum - && !(flags & VNET_BUFFER_F_L4_CHECKSUM_COMPUTED); + u8 need_csum = type != IP_BUILTIN_PROTOCOL_UNKNOWN && + !good_l4_csum && + !(flags & VNET_BUFFER_F_L4_CHECKSUM_COMPUTED); if (PREDICT_FALSE (need_csum)) { flags = ip6_tcp_udp_icmp_validate_checksum (vm, b[0]); @@ -1468,7 +1573,6 @@ ip6_local_inline (vlib_main_t * vm, vlib_node_runtime_t * node, error = len_diff < 0 ? IP6_ERROR_UDP_LENGTH : error; - STATIC_ASSERT (IP6_ERROR_UDP_CHECKSUM + IP_BUILTIN_PROTOCOL_UDP == IP6_ERROR_UDP_CHECKSUM, "Wrong IP6 errors constants"); @@ -1495,13 +1599,23 @@ ip6_local_inline (vlib_main_t * vm, vlib_node_runtime_t * node, 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[0])->ip.rx_sw_if_index = + vnet_buffer (b[0])->sw_if_index[VLIB_RX]; + if (is_receive_dpo) + { + receive_dpo_t *rd; + rd = receive_dpo_get (vnet_buffer (b[0])->ip.adj_index[VLIB_TX]); + if (rd->rd_sw_if_index != ~0) + vnet_buffer (b[0])->ip.rx_sw_if_index = rd->rd_sw_if_index; + } } /* head_of_feature_arc */ next[0] = lm->local_next_by_ip_protocol[ip->protocol]; next[0] = error != IP6_ERROR_UNKNOWN_PROTOCOL ? IP_LOCAL_NEXT_DROP : next[0]; - b[0]->error = error_node->errors[0]; + b[0]->error = error_node->errors[error]; if (head_of_feature_arc) { @@ -1509,8 +1623,8 @@ ip6_local_inline (vlib_main_t * vm, vlib_node_runtime_t * node, { u32 next32 = next[0]; vnet_feature_arc_start (arc_index, - vnet_buffer (b[0])->sw_if_index - [VLIB_RX], &next32, b[0]); + vnet_buffer (b[0])->ip.rx_sw_if_index, + &next32, b[0]); next[0] = next32; } } @@ -1528,15 +1642,17 @@ ip6_local_inline (vlib_main_t * vm, vlib_node_runtime_t * node, VLIB_NODE_FN (ip6_local_node) (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { - return ip6_local_inline (vm, node, frame, 1 /* head of feature arc */ ); + return ip6_local_inline (vm, node, frame, 1 /* head of feature arc */, + 0 /* ip6_local_inline */); } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (ip6_local_node) = { .name = "ip6-local", .vector_size = sizeof (u32), .format_trace = format_ip6_forward_next_trace, + .n_errors = IP6_N_ERROR, + .error_counters = ip6_error_counters, .n_next_nodes = IP_LOCAL_N_NEXT, .next_nodes = { @@ -1544,19 +1660,32 @@ VLIB_REGISTER_NODE (ip6_local_node) = [IP_LOCAL_NEXT_PUNT] = "ip6-punt", [IP_LOCAL_NEXT_UDP_LOOKUP] = "ip6-udp-lookup", [IP_LOCAL_NEXT_ICMP] = "ip6-icmp-input", - [IP_LOCAL_NEXT_REASSEMBLY] = "ip6-full-reassembly", + [IP_LOCAL_NEXT_REASSEMBLY] = "ip6-local-full-reassembly", }, }; -/* *INDENT-ON* */ + +VLIB_NODE_FN (ip6_receive_local_node) +(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame) +{ + return ip6_local_inline (vm, node, frame, 1 /* head of feature arc */, + 1 /* is_receive_dpo */); +} + +VLIB_REGISTER_NODE (ip6_receive_local_node) = { + .name = "ip6-receive", + .vector_size = sizeof (u32), + .format_trace = format_ip6_forward_next_trace, + .sibling_of = "ip6-local" +}; VLIB_NODE_FN (ip6_local_end_of_arc_node) (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { - return ip6_local_inline (vm, node, frame, 0 /* head of feature arc */ ); + return ip6_local_inline (vm, node, frame, 0 /* head of feature arc */, + 0 /* ip6_local_inline */); } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (ip6_local_end_of_arc_node) = { .name = "ip6-local-end-of-arc", .vector_size = sizeof (u32), @@ -1570,7 +1699,6 @@ VNET_FEATURE_INIT (ip6_local_end_of_arc, static) = { .node_name = "ip6-local-end-of-arc", .runs_before = 0, /* not before any other features */ }; -/* *INDENT-ON* */ #ifdef CLIB_MARCH_VARIANT extern vlib_node_registration_t ip6_local_node; @@ -1679,8 +1807,8 @@ ip6_rewrite_inline_with_gso (vlib_main_t * vm, vlib_prefetch_buffer_header (p2, LOAD); vlib_prefetch_buffer_header (p3, LOAD); - CLIB_PREFETCH (p2->pre_data, 32, STORE); - CLIB_PREFETCH (p3->pre_data, 32, STORE); + clib_prefetch_store (p2->pre_data); + clib_prefetch_store (p3->pre_data); CLIB_PREFETCH (p2->data, sizeof (ip0[0]), STORE); CLIB_PREFETCH (p3->data, sizeof (ip0[0]), STORE); @@ -1733,10 +1861,7 @@ ip6_rewrite_inline_with_gso (vlib_main_t * vm, 0); } } - else - { - p0->flags &= ~VNET_BUFFER_F_LOCALLY_ORIGINATED; - } + is_locally_originated1 = p1->flags & VNET_BUFFER_F_LOCALLY_ORIGINATED; if (PREDICT_TRUE (!is_locally_originated1)) @@ -1764,10 +1889,7 @@ ip6_rewrite_inline_with_gso (vlib_main_t * vm, 0); } } - else - { - p1->flags &= ~VNET_BUFFER_F_LOCALLY_ORIGINATED; - } + adj0 = adj_get (adj_index0); adj1 = adj_get (adj_index1); @@ -1800,8 +1922,6 @@ ip6_rewrite_inline_with_gso (vlib_main_t * vm, if (p1->flags & VNET_BUFFER_F_GSO) ip1_len = gso_mtu_sz (p1); - - ip6_mtu_check (p0, ip0_len, adj0[0].rewrite_header.max_l3_packet_bytes, is_locally_originated0, &next0, is_midchain, @@ -1810,22 +1930,20 @@ ip6_rewrite_inline_with_gso (vlib_main_t * vm, adj1[0].rewrite_header.max_l3_packet_bytes, is_locally_originated1, &next1, is_midchain, &error1); - /* Don't adjust the buffer for hop count issue; icmp-error node * wants to see the IP header */ if (PREDICT_TRUE (error0 == IP6_ERROR_NONE)) { p0->current_data -= rw_len0; p0->current_length += rw_len0; - tx_sw_if_index0 = adj0[0].rewrite_header.sw_if_index; vnet_buffer (p0)->sw_if_index[VLIB_TX] = tx_sw_if_index0; next0 = adj0[0].rewrite_header.next_index; - if (PREDICT_FALSE (adj0[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES)) - vnet_feature_arc_start (lm->output_feature_arc_index, - tx_sw_if_index0, &next0, p0); + vnet_feature_arc_start_w_cfg_index + (lm->output_feature_arc_index, tx_sw_if_index0, &next0, p0, + adj0->ia_cfg_index); } else { @@ -1842,8 +1960,9 @@ ip6_rewrite_inline_with_gso (vlib_main_t * vm, if (PREDICT_FALSE (adj1[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES)) - vnet_feature_arc_start (lm->output_feature_arc_index, - tx_sw_if_index1, &next1, p1); + vnet_feature_arc_start_w_cfg_index + (lm->output_feature_arc_index, tx_sw_if_index1, &next1, p1, + adj1->ia_cfg_index); } else { @@ -1852,15 +1971,14 @@ ip6_rewrite_inline_with_gso (vlib_main_t * vm, if (is_midchain) { - /* before we paint on the next header, update the L4 - * checksums if required, since there's no offload on a tunnel */ - calc_checksums (vm, p0); - calc_checksums (vm, p1); + /* Guess we are only writing on ipv6 header. */ + vnet_rewrite_two_headers (adj0[0], adj1[0], + ip0, ip1, sizeof (ip6_header_t)); } - - /* Guess we are only writing on simple Ethernet header. */ - vnet_rewrite_two_headers (adj0[0], adj1[0], - ip0, ip1, sizeof (ethernet_header_t)); + else + /* Guess we are only writing on simple Ethernet header. */ + vnet_rewrite_two_headers (adj0[0], adj1[0], + ip0, ip1, sizeof (ethernet_header_t)); if (is_midchain) { @@ -1943,18 +2061,16 @@ ip6_rewrite_inline_with_gso (vlib_main_t * vm, 0); } } - else - { - p0->flags &= ~VNET_BUFFER_F_LOCALLY_ORIGINATED; - } if (is_midchain) { - calc_checksums (vm, p0); + /* Guess we are only writing on ip6 header. */ + vnet_rewrite_one_header (adj0[0], ip0, sizeof (ip6_header_t)); } - - /* Guess we are only writing on simple Ethernet header. */ - vnet_rewrite_one_header (adj0[0], ip0, sizeof (ethernet_header_t)); + else + /* Guess we are only writing on simple Ethernet header. */ + vnet_rewrite_one_header (adj0[0], ip0, + sizeof (ethernet_header_t)); /* Update packet buffer attributes/set output interface. */ rw_len0 = adj0[0].rewrite_header.data_bytes; @@ -1979,7 +2095,6 @@ ip6_rewrite_inline_with_gso (vlib_main_t * vm, adj0[0].rewrite_header.max_l3_packet_bytes, is_locally_originated0, &next0, is_midchain, &error0); - /* Don't adjust the buffer for hop count issue; icmp-error node * wants to see the IP header */ if (PREDICT_TRUE (error0 == IP6_ERROR_NONE)) @@ -1994,8 +2109,9 @@ ip6_rewrite_inline_with_gso (vlib_main_t * vm, if (PREDICT_FALSE (adj0[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES)) - vnet_feature_arc_start (lm->output_feature_arc_index, - tx_sw_if_index0, &next0, p0); + vnet_feature_arc_start_w_cfg_index + (lm->output_feature_arc_index, tx_sw_if_index0, &next0, p0, + adj0->ia_cfg_index); } else { @@ -2097,14 +2213,12 @@ VLIB_NODE_FN (ip6_mcast_midchain_node) (vlib_main_t * vm, return ip6_rewrite_inline (vm, node, frame, 0, 1, 1); } -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (ip6_midchain_node) = -{ +VLIB_REGISTER_NODE (ip6_midchain_node) = { .name = "ip6-midchain", .vector_size = sizeof (u32), .format_trace = format_ip6_forward_next_trace, .sibling_of = "ip6-rewrite", - }; +}; VLIB_REGISTER_NODE (ip6_rewrite_node) = { @@ -2145,7 +2259,6 @@ VLIB_REGISTER_NODE (ip6_mcast_midchain_node) = .sibling_of = "ip6-rewrite", }; -/* *INDENT-ON* */ /* * Hop-by-Hop handling @@ -2159,7 +2272,6 @@ _(PROCESSED, "pkts with ip6 hop-by-hop options") \ _(FORMAT, "incorrectly formatted hop-by-hop options") \ _(UNKNOWN_OPTION, "unknown ip6 hop-by-hop options") -/* *INDENT-OFF* */ typedef enum { #define _(sym,str) IP6_HOP_BY_HOP_ERROR_##sym, @@ -2167,7 +2279,6 @@ typedef enum #undef _ IP6_HOP_BY_HOP_N_ERROR, } ip6_hop_by_hop_error_t; -/* *INDENT-ON* */ /* * Primary h-b-h handler trace support @@ -2197,7 +2308,6 @@ format_ip6_hop_by_hop_ext_hdr (u8 * s, va_list * args) ip6_hop_by_hop_option_t *opt0, *limit0; ip6_hop_by_hop_main_t *hm = &ip6_hop_by_hop_main; u8 type0; - s = format (s, "IP6_HOP_BY_HOP: next protocol %d len %d total %d", hbh0->protocol, (hbh0->length + 1) << 3, total_len); @@ -2220,9 +2330,8 @@ format_ip6_hop_by_hop_ext_hdr (u8 * s, va_list * args) } else { - s = - format (s, "\n unrecognized option %d length %d", type0, - opt0->length); + s = format (s, "\n unrecognized option %d length %d", type0, + opt0->length); } opt0 = (ip6_hop_by_hop_option_t *) (((u8 *) opt0) + opt0->length + @@ -2270,9 +2379,8 @@ format_ip6_hop_by_hop_trace (u8 * s, va_list * args) } else { - s = - format (s, "\n unrecognized option %d length %d", type0, - opt0->length); + s = format (s, "\n unrecognized option %d length %d", type0, + opt0->length); } opt0 = (ip6_hop_by_hop_option_t *) (((u8 *) opt0) + opt0->length + @@ -2597,7 +2705,6 @@ VLIB_NODE_FN (ip6_hop_by_hop_node) (vlib_main_t * vm, return frame->n_vectors; } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (ip6_hop_by_hop_node) = { .name = "ip6-hop-by-hop", @@ -2609,7 +2716,6 @@ VLIB_REGISTER_NODE (ip6_hop_by_hop_node) = .error_strings = ip6_hop_by_hop_error_strings, .n_next_nodes = 0, }; -/* *INDENT-ON* */ static clib_error_t * ip6_hop_by_hop_init (vlib_main_t * vm) @@ -2719,24 +2825,6 @@ ip6_lookup_init (vlib_main_t * vm) ip_lookup_init (&im->lookup_main, /* is_ip6 */ 1); - if (im->lookup_table_nbuckets == 0) - im->lookup_table_nbuckets = IP6_FIB_DEFAULT_HASH_NUM_BUCKETS; - - im->lookup_table_nbuckets = 1 << max_log2 (im->lookup_table_nbuckets); - - if (im->lookup_table_size == 0) - im->lookup_table_size = IP6_FIB_DEFAULT_HASH_MEMORY_SIZE; - - clib_bihash_init_24_8 (&(im->ip6_table[IP6_FIB_TABLE_FWDING].ip6_hash), - "ip6 FIB fwding table", - im->lookup_table_nbuckets, im->lookup_table_size); - clib_bihash_init_24_8 (&im->ip6_table[IP6_FIB_TABLE_NON_FWDING].ip6_hash, - "ip6 FIB non-fwding table", - im->lookup_table_nbuckets, im->lookup_table_size); - clib_bihash_init_40_8 (&im->ip6_mtable.ip6_mhash, - "ip6 mFIB table", - im->lookup_table_nbuckets, im->lookup_table_size); - /* Create FIB with index 0 and table id of 0. */ fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, 0, FIB_SOURCE_DEFAULT_ROUTE); @@ -2757,24 +2845,6 @@ ip6_lookup_init (vlib_main_t * vm) VLIB_INIT_FUNCTION (ip6_lookup_init); -#ifndef CLIB_MARCH_VARIANT -int -vnet_set_ip6_flow_hash (u32 table_id, u32 flow_hash_config) -{ - u32 fib_index; - - fib_index = fib_table_find (FIB_PROTOCOL_IP6, table_id); - - if (~0 == fib_index) - return VNET_API_ERROR_NO_SUCH_FIB; - - fib_table_set_flow_hash_config (fib_index, FIB_PROTOCOL_IP6, - flow_hash_config); - - return 0; -} -#endif - static clib_error_t * set_ip6_flow_hash_command_fn (vlib_main_t * vm, unformat_input_t * input, @@ -2789,8 +2859,12 @@ set_ip6_flow_hash_command_fn (vlib_main_t * vm, { if (unformat (input, "table %d", &table_id)) matched = 1; -#define _(a,v) \ - else if (unformat (input, #a)) { flow_hash_config |= v; matched=1;} +#define _(a, b, v) \ + else if (unformat (input, #a)) \ + { \ + flow_hash_config |= v; \ + matched = 1; \ + } foreach_flow_hash_bit #undef _ else @@ -2801,7 +2875,7 @@ set_ip6_flow_hash_command_fn (vlib_main_t * vm, return clib_error_return (0, "unknown input `%U'", format_unformat_error, input); - rv = vnet_set_ip6_flow_hash (table_id, flow_hash_config); + rv = ip_flow_hash_set (AF_IP6, table_id, flow_hash_config); switch (rv) { case 0: @@ -2893,15 +2967,12 @@ set_ip6_flow_hash_command_fn (vlib_main_t * vm, * @cliexend * @endparblock ?*/ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (set_ip6_flow_hash_command, static) = -{ +VLIB_CLI_COMMAND (set_ip6_flow_hash_command, static) = { .path = "set ip6 flow-hash", - .short_help = - "set ip6 flow-hash table [src] [dst] [sport] [dport] [proto] [reverse]", + .short_help = "set ip6 flow-hash table [src] [dst] [sport] " + "[dport] [proto] [reverse] [flowlabel]", .function = set_ip6_flow_hash_command_fn, }; -/* *INDENT-ON* */ static clib_error_t * show_ip6_local_command_fn (vlib_main_t * vm, @@ -2942,19 +3013,16 @@ show_ip6_local_command_fn (vlib_main_t * vm, * 115 * @cliexend ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (show_ip6_local, static) = { .path = "show ip6 local", .function = show_ip6_local_command_fn, .short_help = "show ip6 local", }; -/* *INDENT-ON* */ #ifndef CLIB_MARCH_VARIANT int -vnet_set_ip6_classify_intfc (vlib_main_t * vm, u32 sw_if_index, - u32 table_index) +vnet_set_ip6_classify_intfc (vlib_main_t *vm, u32 sw_if_index, u32 table_index) { vnet_main_t *vnm = vnet_get_main (); vnet_interface_main_t *im = &vnm->interface_main; @@ -2985,17 +3053,13 @@ vnet_set_ip6_classify_intfc (vlib_main_t * vm, u32 sw_if_index, fib_index = fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4, sw_if_index); - - if (table_index != (u32) ~ 0) { dpo_id_t dpo = DPO_INVALID; - dpo_set (&dpo, DPO_CLASSIFY, DPO_PROTO_IP6, classify_dpo_create (DPO_PROTO_IP6, table_index)); - fib_table_entry_special_dpo_add (fib_index, &pfx, FIB_SOURCE_CLASSIFY, @@ -3066,7 +3130,6 @@ set_ip6_classify_command_fn (vlib_main_t * vm, * Example of how to assign a classification table to an interface: * @cliexcmd{set ip6 classify intfc GigabitEthernet2/0/0 table-index 1} ?*/ -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (set_ip6_classify_command, static) = { .path = "set ip6 classify", @@ -3074,35 +3137,6 @@ VLIB_CLI_COMMAND (set_ip6_classify_command, static) = "set ip6 classify intfc table-index ", .function = set_ip6_classify_command_fn, }; -/* *INDENT-ON* */ - -static clib_error_t * -ip6_config (vlib_main_t * vm, unformat_input_t * input) -{ - ip6_main_t *im = &ip6_main; - uword heapsize = 0; - u32 tmp; - u32 nbuckets = 0; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "hash-buckets %d", &tmp)) - nbuckets = tmp; - else if (unformat (input, "heap-size %U", - unformat_memory_size, &heapsize)) - ; - else - return clib_error_return (0, "unknown input '%U'", - format_unformat_error, input); - } - - im->lookup_table_nbuckets = nbuckets; - im->lookup_table_size = heapsize; - - return 0; -} - -VLIB_EARLY_CONFIG_FUNCTION (ip6_config, "ip6"); /* * fd.io coding-style-patch-verification: ON