X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=vnet%2Fvnet%2Fip%2Fip6_forward.c;h=f3cd640a841ab29a68f17fa619139a8e7469313c;hb=7a91b46e03f8d67d2669050fdb890ef11c31de79;hp=899203c84b363d3a63ce137d33899b06829d1c73;hpb=8b3191e6d715760deefe550b59c7d92be4b5cda9;p=vpp.git diff --git a/vnet/vnet/ip/ip6_forward.c b/vnet/vnet/ip/ip6_forward.c index 899203c84b3..f3cd640a841 100644 --- a/vnet/vnet/ip/ip6_forward.c +++ b/vnet/vnet/ip/ip6_forward.c @@ -498,6 +498,8 @@ ip6_add_del_interface_address (vlib_main_t * vm, goto done; } + ip6_sw_interface_enable_disable(sw_if_index, !is_del); + if (is_del) ip6_del_interface_routes (im, ip6_af.fib_index, address, address_length); @@ -647,6 +649,12 @@ VNET_FEATURE_ARC_INIT (ip6_output, static) = .arc_index_ptr = &ip6_main.lookup_main.output_feature_arc_index, }; +VNET_FEATURE_INIT (ip6_ipsec_output, static) = { + .arc_name = "ip6-output", + .node_name = "ipsec-output-ip6", + .runs_before = VNET_FEATURES ("interface-output"), +}; + VNET_FEATURE_INIT (ip6_interface_output, static) = { .arc_name = "ip6-output", .node_name = "interface-output", @@ -697,8 +705,8 @@ VLIB_NODE_FUNCTION_MULTIARCH (ip6_lookup_node, ip6_lookup) always_inline uword ip6_load_balance (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) + vlib_node_runtime_t * node, + vlib_frame_t * frame) { vlib_combined_counter_main_t * cm = &load_balance_main.lbm_via_counters; u32 n_left_from, n_left_to_next, * from, * to_next; @@ -716,63 +724,172 @@ ip6_load_balance (vlib_main_t * vm, while (n_left_from > 0) { vlib_get_next_frame (vm, node, next, - to_next, n_left_to_next); - + to_next, n_left_to_next); - while (n_left_from > 0 && n_left_to_next > 0) - { - ip_lookup_next_t next0; - const load_balance_t *lb0; - vlib_buffer_t * p0; - u32 pi0, lbi0, hc0; - const ip6_header_t *ip0; - const dpo_id_t *dpo0; - pi0 = from[0]; - to_next[0] = pi0; + while (n_left_from >= 4 && n_left_to_next >= 2) + { + ip_lookup_next_t next0, next1; + const load_balance_t *lb0, *lb1; + vlib_buffer_t * p0, *p1; + u32 pi0, lbi0, hc0, pi1, lbi1, hc1; + const ip6_header_t *ip0, *ip1; + const dpo_id_t *dpo0, *dpo1; + + /* 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, STORE); + vlib_prefetch_buffer_header (p3, STORE); + + CLIB_PREFETCH (p2->data, sizeof (ip0[0]), STORE); + CLIB_PREFETCH (p3->data, sizeof (ip0[0]), STORE); + } + + pi0 = to_next[0] = from[0]; + pi1 = to_next[1] = from[1]; + + from += 2; + n_left_from -= 2; + to_next += 2; + n_left_to_next -= 2; + + p0 = vlib_get_buffer (vm, pi0); + p1 = vlib_get_buffer (vm, pi1); + + ip0 = vlib_buffer_get_current (p0); + ip1 = vlib_buffer_get_current (p1); + lbi0 = vnet_buffer (p0)->ip.adj_index[VLIB_TX]; + lbi1 = vnet_buffer (p1)->ip.adj_index[VLIB_TX]; + + lb0 = load_balance_get(lbi0); + lb1 = load_balance_get(lbi1); + + /* + * this node is for via FIBs we can re-use the hash value from the + * to node if present. + * We don't want to use the same hash value at each level in the recursion + * graph as that would lead to polarisation + */ + hc0 = vnet_buffer (p0)->ip.flow_hash = 0; + hc1 = vnet_buffer (p1)->ip.flow_hash = 0; + + if (PREDICT_FALSE (lb0->lb_n_buckets > 1)) + { + if (PREDICT_TRUE (vnet_buffer(p0)->ip.flow_hash)) + { + hc0 = vnet_buffer(p0)->ip.flow_hash = vnet_buffer(p0)->ip.flow_hash >> 1; + } + else + { + hc0 = vnet_buffer(p0)->ip.flow_hash = ip6_compute_flow_hash(ip0, hc0); + } + } + if (PREDICT_FALSE (lb1->lb_n_buckets > 1)) + { + if (PREDICT_TRUE (vnet_buffer(p1)->ip.flow_hash)) + { + hc1 = vnet_buffer(p1)->ip.flow_hash = vnet_buffer(p1)->ip.flow_hash >> 1; + } + else + { + hc1 = vnet_buffer(p1)->ip.flow_hash = ip6_compute_flow_hash(ip1, hc1); + } + } + + dpo0 = load_balance_get_bucket_i(lb0, hc0 & (lb0->lb_n_buckets_minus_1)); + dpo1 = load_balance_get_bucket_i(lb1, hc1 & (lb1->lb_n_buckets_minus_1)); + + next0 = dpo0->dpoi_next_node; + next1 = dpo1->dpoi_next_node; + + /* Only process the HBH Option Header if explicitly configured to do so */ + if (PREDICT_FALSE(ip0->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)) + { + next0 = (dpo_is_adj(dpo0) && im->hbh_enabled) ? + (ip_lookup_next_t) IP6_LOOKUP_NEXT_HOP_BY_HOP : next0; + } + /* Only process the HBH Option Header if explicitly configured to do so */ + if (PREDICT_FALSE(ip1->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)) + { + next1 = (dpo_is_adj(dpo1) && im->hbh_enabled) ? + (ip_lookup_next_t) IP6_LOOKUP_NEXT_HOP_BY_HOP : next1; + } - p0 = vlib_get_buffer (vm, pi0); + vnet_buffer (p0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index; + vnet_buffer (p1)->ip.adj_index[VLIB_TX] = dpo1->dpoi_index; - ip0 = vlib_buffer_get_current (p0); - lbi0 = vnet_buffer (p0)->ip.adj_index[VLIB_TX]; + vlib_increment_combined_counter + (cm, cpu_index, lbi0, 1, + vlib_buffer_length_in_chain (vm, p0)); + vlib_increment_combined_counter + (cm, cpu_index, lbi1, 1, + vlib_buffer_length_in_chain (vm, p1)); - lb0 = load_balance_get(lbi0); - hc0 = lb0->lb_hash_config; - vnet_buffer(p0)->ip.flow_hash = ip6_compute_flow_hash(ip0, hc0); + vlib_validate_buffer_enqueue_x2 (vm, node, next, + to_next, n_left_to_next, + pi0, pi1, next0, next1); + } - dpo0 = load_balance_get_bucket_i(lb0, - vnet_buffer(p0)->ip.flow_hash & - (lb0->lb_n_buckets - 1)); - next0 = dpo0->dpoi_next_node; - /* Only process the HBH Option Header if explicitly configured to do so */ - if (PREDICT_FALSE(ip0->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)) - { - next0 = (dpo_is_adj(dpo0) && im->hbh_enabled) ? - (ip_lookup_next_t) IP6_LOOKUP_NEXT_HOP_BY_HOP : next0; - } - vnet_buffer (p0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index; + while (n_left_from > 0 && n_left_to_next > 0) + { + ip_lookup_next_t next0; + const load_balance_t *lb0; + vlib_buffer_t * p0; + u32 pi0, lbi0, hc0; + const ip6_header_t *ip0; + const dpo_id_t *dpo0; + + pi0 = from[0]; + to_next[0] = pi0; + from += 1; + to_next += 1; + n_left_to_next -= 1; + n_left_from -= 1; + + p0 = vlib_get_buffer (vm, pi0); + + ip0 = vlib_buffer_get_current (p0); + lbi0 = vnet_buffer (p0)->ip.adj_index[VLIB_TX]; + + lb0 = load_balance_get(lbi0); + + hc0 = vnet_buffer (p0)->ip.flow_hash = 0; + if (PREDICT_FALSE (lb0->lb_n_buckets > 1)) + { + if (PREDICT_TRUE (vnet_buffer(p0)->ip.flow_hash)) + { + hc0 = vnet_buffer(p0)->ip.flow_hash = vnet_buffer(p0)->ip.flow_hash >> 1; + } + else + { + hc0 = vnet_buffer(p0)->ip.flow_hash = ip6_compute_flow_hash(ip0, hc0); + } + } + dpo0 = load_balance_get_bucket_i(lb0, hc0 & (lb0->lb_n_buckets_minus_1)); + + next0 = dpo0->dpoi_next_node; + vnet_buffer (p0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index; + + /* Only process the HBH Option Header if explicitly configured to do so */ + if (PREDICT_FALSE(ip0->protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)) + { + next0 = (dpo_is_adj(dpo0) && im->hbh_enabled) ? + (ip_lookup_next_t) IP6_LOOKUP_NEXT_HOP_BY_HOP : next0; + } - vlib_increment_combined_counter + vlib_increment_combined_counter (cm, cpu_index, lbi0, 1, vlib_buffer_length_in_chain (vm, p0)); - from += 1; - to_next += 1; - n_left_to_next -= 1; - n_left_from -= 1; - - if (PREDICT_FALSE (next0 != next)) - { - n_left_to_next += 1; - vlib_put_next_frame (vm, node, next, n_left_to_next); - next = next0; - vlib_get_next_frame (vm, node, next, - to_next, n_left_to_next); - to_next[0] = pi0; - to_next += 1; - n_left_to_next -= 1; - } - } + vlib_validate_buffer_enqueue_x1 (vm, node, next, + to_next, n_left_to_next, + pi0, next0); + } vlib_put_next_frame (vm, node, next, n_left_to_next); } @@ -785,8 +902,8 @@ VLIB_REGISTER_NODE (ip6_load_balance_node) = { .name = "ip6-load-balance", .vector_size = sizeof (u32), .sibling_of = "ip6-lookup", + .format_trace = format_ip6_lookup_trace, - .n_next_nodes = 0, }; VLIB_NODE_FUNCTION_MULTIARCH (ip6_load_balance_node, ip6_load_balance) @@ -1060,35 +1177,6 @@ u16 ip6_tcp_udp_icmp_compute_checksum (vlib_main_t * vm, vlib_buffer_t * p0, ip6 } n_bytes_left = n_this_buffer = payload_length_host_byte_order; -#if DPDK > 0 - if (p0 && n_this_buffer + headers_size > p0->current_length) - { - struct rte_mbuf *mb = rte_mbuf_from_vlib_buffer(p0); - u8 nb_segs = mb->nb_segs; - - n_this_buffer = (p0->current_length > headers_size ? - p0->current_length - headers_size : 0); - while (n_bytes_left) - { - sum0 = ip_incremental_checksum (sum0, data_this_buffer, n_this_buffer); - n_bytes_left -= n_this_buffer; - - mb = mb->next; - nb_segs--; - if ((nb_segs == 0) || (mb == 0)) - break; - - data_this_buffer = rte_ctrlmbuf_data(mb); - n_this_buffer = mb->data_len; - } - if (n_bytes_left || nb_segs) - { - *bogus_lengthp = 1; - return 0xfefe; - } - } - else sum0 = ip_incremental_checksum (sum0, data_this_buffer, n_this_buffer); -#else if (p0 && n_this_buffer + headers_size > p0->current_length) n_this_buffer = p0->current_length > headers_size ? p0->current_length - headers_size : 0; while (1) @@ -1107,7 +1195,6 @@ u16 ip6_tcp_udp_icmp_compute_checksum (vlib_main_t * vm, vlib_buffer_t * p0, ip6 data_this_buffer = vlib_buffer_get_current (p0); n_this_buffer = p0->current_length; } -#endif /* DPDK */ sum16 = ~ ip_csum_fold (sum0);