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);
.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",
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;
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);
}
.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)
}
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)
data_this_buffer = vlib_buffer_get_current (p0);
n_this_buffer = p0->current_length;
}
-#endif /* DPDK */
sum16 = ~ ip_csum_fold (sum0);