diff options
Diffstat (limited to 'src/vnet')
-rw-r--r-- | src/vnet/adj/adj.h | 10 | ||||
-rw-r--r-- | src/vnet/adj/adj_dp.h | 26 | ||||
-rw-r--r-- | src/vnet/adj/adj_midchain.c | 60 | ||||
-rw-r--r-- | src/vnet/adj/rewrite.h | 5 | ||||
-rw-r--r-- | src/vnet/ip/ip4_forward.c | 8 |
5 files changed, 78 insertions, 31 deletions
diff --git a/src/vnet/adj/adj.h b/src/vnet/adj/adj.h index b29b1b0c225..44bb2bd981b 100644 --- a/src/vnet/adj/adj.h +++ b/src/vnet/adj/adj.h @@ -185,6 +185,12 @@ typedef enum adj_attr_t_ * the fixup function is standard IP4o4 header */ ADJ_ATTR_MIDCHAIN_FIXUP_IP4O4_HDR, + /** + * the fixup function performs the flow hash + * this means the flow hash is performed on the inner + * header, where the entropy is higher. + */ + ADJ_ATTR_MIDCHAIN_FIXUP_FLOW_HASH, } adj_attr_t; #define ADJ_ATTR_NAMES { \ @@ -193,11 +199,12 @@ typedef enum adj_attr_t_ [ADJ_ATTR_MIDCHAIN_IP_STACK] = "midchain-ip-stack", \ [ADJ_ATTR_MIDCHAIN_LOOPED] = "midchain-looped", \ [ADJ_ATTR_MIDCHAIN_FIXUP_IP4O4_HDR] = "midchain-ip4o4-hdr-fixup", \ + [ADJ_ATTR_MIDCHAIN_FIXUP_FLOW_HASH] = "midchain-flow-hash", \ } #define FOR_EACH_ADJ_ATTR(_attr) \ for (_attr = ADJ_ATTR_SYNC_WALK_ACTIVE; \ - _attr <= ADJ_ATTR_MIDCHAIN_FIXUP_IP4O4_HDR; \ + _attr <= ADJ_ATTR_MIDCHAIN_FIXUP_FLOW_HASH; \ _attr++) /** @@ -211,6 +218,7 @@ typedef enum adj_flags_t_ ADJ_FLAG_MIDCHAIN_IP_STACK = (1 << ADJ_ATTR_MIDCHAIN_IP_STACK), ADJ_FLAG_MIDCHAIN_LOOPED = (1 << ADJ_ATTR_MIDCHAIN_LOOPED), ADJ_FLAG_MIDCHAIN_FIXUP_IP4O4_HDR = (1 << ADJ_ATTR_MIDCHAIN_FIXUP_IP4O4_HDR), + ADJ_FLAG_MIDCHAIN_FIXUP_FLOW_HASH = (1 << ADJ_ATTR_MIDCHAIN_FIXUP_FLOW_HASH), } __attribute__ ((packed)) adj_flags_t; /** diff --git a/src/vnet/adj/adj_dp.h b/src/vnet/adj/adj_dp.h index 27c0581fcfb..aff1a2b1f43 100644 --- a/src/vnet/adj/adj_dp.h +++ b/src/vnet/adj/adj_dp.h @@ -18,6 +18,9 @@ #include <vnet/adj/adj.h> #include <vnet/tunnel/tunnel_dp.h> +#include <vnet/ip/ip4_inlines.h> +#include <vnet/ip/ip6_inlines.h> +#include <vnet/mpls/mpls_lookup.h> static_always_inline void adj_midchain_ipip44_fixup (vlib_main_t * vm, @@ -54,13 +57,32 @@ adj_midchain_ipip44_fixup (vlib_main_t * vm, static_always_inline void adj_midchain_fixup (vlib_main_t *vm, const ip_adjacency_t *adj, - vlib_buffer_t * b) + vlib_buffer_t * b, + vnet_link_t lt) { - if (PREDICT_TRUE(adj->rewrite_header.flags & VNET_REWRITE_FIXUP_IP4_O_4)) + if (PREDICT_TRUE(adj->rewrite_header.flags & + VNET_REWRITE_FIXUP_IP4_O_4)) adj_midchain_ipip44_fixup (vm, adj, b); else if (adj->sub_type.midchain.fixup_func) adj->sub_type.midchain.fixup_func (vm, adj, b, adj->sub_type.midchain.fixup_data); + + if (PREDICT_FALSE(adj->rewrite_header.flags & + VNET_REWRITE_FIXUP_FLOW_HASH)) + { + if (VNET_LINK_IP4 == lt) + vnet_buffer (b)->ip.flow_hash = + ip4_compute_flow_hash (vlib_buffer_get_current (b) + adj->rewrite_header.data_bytes, + IP_FLOW_HASH_DEFAULT); + else if (VNET_LINK_IP6 == lt) + vnet_buffer (b)->ip.flow_hash = + ip6_compute_flow_hash (vlib_buffer_get_current (b) + adj->rewrite_header.data_bytes, + IP_FLOW_HASH_DEFAULT); + else if (VNET_LINK_MPLS == lt) + vnet_buffer (b)->ip.flow_hash = + mpls_compute_flow_hash (vlib_buffer_get_current (b) + adj->rewrite_header.data_bytes, + IP_FLOW_HASH_DEFAULT); + } } #endif diff --git a/src/vnet/adj/adj_midchain.c b/src/vnet/adj/adj_midchain.c index 15fef866c1b..93cfb550e3e 100644 --- a/src/vnet/adj/adj_midchain.c +++ b/src/vnet/adj/adj_midchain.c @@ -403,6 +403,10 @@ adj_midchain_setup (adj_index_t adj_index, { adj->rewrite_header.flags &= ~VNET_REWRITE_FIXUP_IP4_O_4; } + if (!(flags & ADJ_FLAG_MIDCHAIN_FIXUP_FLOW_HASH)) + { + adj->rewrite_header.flags &= ~VNET_REWRITE_FIXUP_FLOW_HASH; + } tx_node = adj_nbr_midchain_get_tx_node(adj); @@ -582,39 +586,47 @@ adj_nbr_midchain_stack_on_fib_entry (adj_index_t ai, { fib_entry_contribute_forwarding (fei, fct, &tmp); - if ((adj->ia_flags & ADJ_FLAG_MIDCHAIN_IP_STACK) && - (DPO_LOAD_BALANCE == tmp.dpoi_type)) + if (DPO_LOAD_BALANCE == tmp.dpoi_type) { - /* - * do that hash now and stack on the choice. - * If the choice is an incomplete adj then we will need a poke when - * it becomes complete. This happens since the adj update walk propagates - * as far a recursive paths. - */ - const dpo_id_t *choice; load_balance_t *lb; - int hash; lb = load_balance_get (tmp.dpoi_index); - if (FIB_FORW_CHAIN_TYPE_UNICAST_IP4 == fct) + if ((adj->ia_flags & ADJ_FLAG_MIDCHAIN_IP_STACK) || + lb->lb_n_buckets == 1) { - hash = ip4_compute_flow_hash ((ip4_header_t *) adj_get_rewrite (ai), - lb->lb_hash_config); + /* + * do that hash now and stack on the choice. + * If the choice is an incomplete adj then we will need a poke when + * it becomes complete. This happens since the adj update walk propagates + * as far a recursive paths. + */ + const dpo_id_t *choice; + int hash; + + if (FIB_FORW_CHAIN_TYPE_UNICAST_IP4 == fct) + { + hash = ip4_compute_flow_hash ((ip4_header_t *) adj_get_rewrite (ai), + lb->lb_hash_config); + } + else if (FIB_FORW_CHAIN_TYPE_UNICAST_IP6 == fct) + { + hash = ip6_compute_flow_hash ((ip6_header_t *) adj_get_rewrite (ai), + lb->lb_hash_config); + } + else + { + hash = 0; + ASSERT(0); + } + + choice = load_balance_get_bucket_i (lb, hash & lb->lb_n_buckets_minus_1); + dpo_copy (&tmp, choice); } - else if (FIB_FORW_CHAIN_TYPE_UNICAST_IP6 == fct) + else if (adj->ia_flags & ADJ_FLAG_MIDCHAIN_FIXUP_FLOW_HASH) { - hash = ip6_compute_flow_hash ((ip6_header_t *) adj_get_rewrite (ai), - lb->lb_hash_config); + adj->rewrite_header.flags |= VNET_REWRITE_FIXUP_FLOW_HASH; } - else - { - hash = 0; - ASSERT(0); - } - - choice = load_balance_get_bucket_i (lb, hash & lb->lb_n_buckets_minus_1); - dpo_copy (&tmp, choice); } } adj_nbr_midchain_stack (ai, &tmp); diff --git a/src/vnet/adj/rewrite.h b/src/vnet/adj/rewrite.h index c23edbe1f60..496bb149bc4 100644 --- a/src/vnet/adj/rewrite.h +++ b/src/vnet/adj/rewrite.h @@ -60,6 +60,11 @@ typedef enum vnet_rewrite_flags_t_ * this adj performs IP4 over IP4 fixup */ VNET_REWRITE_FIXUP_IP4_O_4 = (1 << 1), + + /** + * this adj performs the flow hash fixup + */ + VNET_REWRITE_FIXUP_FLOW_HASH = (1 << 2), } __attribute__ ((packed)) vnet_rewrite_flags_t; typedef struct vnet_rewrite_header_t_ diff --git a/src/vnet/ip/ip4_forward.c b/src/vnet/ip/ip4_forward.c index 5903ef892ca..fdc92ca16f8 100644 --- a/src/vnet/ip/ip4_forward.c +++ b/src/vnet/ip/ip4_forward.c @@ -2265,9 +2265,9 @@ ip4_rewrite_inline_with_gso (vlib_main_t * vm, if (is_midchain) { if (error0 == IP4_ERROR_NONE) - adj_midchain_fixup (vm, adj0, b[0]); + adj_midchain_fixup (vm, adj0, b[0], VNET_LINK_IP4); if (error1 == IP4_ERROR_NONE) - adj_midchain_fixup (vm, adj1, b[1]); + adj_midchain_fixup (vm, adj1, b[1], VNET_LINK_IP4); } if (is_mcast) @@ -2399,7 +2399,7 @@ ip4_rewrite_inline_with_gso (vlib_main_t * vm, b[0]) + rw_len0); if (is_midchain) - adj_midchain_fixup (vm, adj0, b[0]); + adj_midchain_fixup (vm, adj0, b[0], VNET_LINK_IP4); if (is_mcast) /* copy bytes from the IP address into the MAC rewrite */ @@ -2502,7 +2502,7 @@ ip4_rewrite_inline_with_gso (vlib_main_t * vm, vlib_buffer_length_in_chain (vm, b[0]) + rw_len0); if (is_midchain) - adj_midchain_fixup (vm, adj0, b[0]); + adj_midchain_fixup (vm, adj0, b[0], VNET_LINK_IP4); if (is_mcast) /* copy bytes from the IP address into the MAC rewrite */ |