diff options
-rw-r--r-- | vnet/vnet/handoff.c | 20 | ||||
-rw-r--r-- | vnet/vnet/handoff.h | 66 |
2 files changed, 84 insertions, 2 deletions
diff --git a/vnet/vnet/handoff.c b/vnet/vnet/handoff.c index 22d2ea98df7..9f3c93b4b70 100644 --- a/vnet/vnet/handoff.c +++ b/vnet/vnet/handoff.c @@ -40,6 +40,8 @@ typedef struct /* convenience variables */ vlib_main_t *vlib_main; vnet_main_t *vnet_main; + + u64 (*hash_fn) (ethernet_header_t *); } handoff_main_t; handoff_main_t handoff_main; @@ -123,7 +125,7 @@ worker_handoff_node_fn (vlib_main_t * vm, */ /* Compute ingress LB hash */ - hash_key = eth_get_key ((ethernet_header_t *) b0->data); + hash_key = hm->hash_fn ((ethernet_header_t *) b0->data); hash = (u32) clib_xxhash (hash_key); /* if input node did not specify next index, then packet @@ -283,9 +285,11 @@ set_interface_handoff_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { + handoff_main_t *hm = &handoff_main; u32 sw_if_index = ~0; int enable_disable = 1; uword *bitmap = 0; + u32 sym = ~0; int rv = 0; @@ -298,6 +302,10 @@ set_interface_handoff_command_fn (vlib_main_t * vm, else if (unformat (input, "%U", unformat_vnet_sw_interface, vnet_get_main (), &sw_if_index)) ; + else if (unformat (input, "symmetrical")) + sym = 1; + else if (unformat (input, "asymmetrical")) + sym = 0; else break; } @@ -333,6 +341,12 @@ set_interface_handoff_command_fn (vlib_main_t * vm, default: return clib_error_return (0, "unknown return value %d", rv); } + + if (sym == 1) + hm->hash_fn = eth_get_sym_key; + else if (sym == 0) + hm->hash_fn = eth_get_key; + return 0; } @@ -340,7 +354,7 @@ set_interface_handoff_command_fn (vlib_main_t * vm, VLIB_CLI_COMMAND (set_interface_handoff_command, static) = { .path = "set interface handoff", .short_help = - "set interface handoff <interface-name> workers <workers-list>", + "set interface handoff <interface-name> workers <workers-list> [symmetrical|asymmetrical]", .function = set_interface_handoff_command_fn, }; /* *INDENT-ON* */ @@ -559,6 +573,8 @@ handoff_init (vlib_main_t * vm) } } + hm->hash_fn = eth_get_key; + hm->vlib_main = vm; hm->vnet_main = &vnet_main; diff --git a/vnet/vnet/handoff.h b/vnet/vnet/handoff.h index 4fefb369475..815206a9f8c 100644 --- a/vnet/vnet/handoff.h +++ b/vnet/vnet/handoff.h @@ -130,6 +130,72 @@ bottom_lbl_found: } +static inline u64 +eth_get_sym_key (ethernet_header_t * h0) +{ + u64 hash_key; + + if (PREDICT_TRUE (h0->type) == clib_host_to_net_u16 (ETHERNET_TYPE_IP4)) + { + ip4_header_t *ip = (ip4_header_t *) (h0 + 1); + hash_key = + (u64) (ip->src_address.as_u32 ^ + ip->dst_address.as_u32 ^ ip->protocol); + } + else if (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_IP6)) + { + ip6_header_t *ip = (ip6_header_t *) (h0 + 1); + hash_key = (u64) (ip->src_address.as_u64[0] ^ + ip->src_address.as_u64[1] ^ + ip->dst_address.as_u64[0] ^ + ip->dst_address.as_u64[1] ^ ip->protocol); + } + else if (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_MPLS_UNICAST)) + { + hash_key = mpls_get_key ((mpls_unicast_header_t *) (h0 + 1)); + } + else + if (PREDICT_FALSE + ((h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_VLAN)) + || (h0->type == clib_host_to_net_u16 (ETHERNET_TYPE_DOT1AD)))) + { + ethernet_vlan_header_t *outer = (ethernet_vlan_header_t *) (h0 + 1); + + outer = (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_VLAN)) ? + outer + 1 : outer; + if (PREDICT_TRUE (outer->type) == + clib_host_to_net_u16 (ETHERNET_TYPE_IP4)) + { + ip4_header_t *ip = (ip4_header_t *) (outer + 1); + hash_key = + (u64) (ip->src_address.as_u32 ^ + ip->dst_address.as_u32 ^ ip->protocol); + } + else if (outer->type == clib_host_to_net_u16 (ETHERNET_TYPE_IP6)) + { + ip6_header_t *ip = (ip6_header_t *) (outer + 1); + hash_key = + (u64) (ip->src_address.as_u64[0] ^ ip->src_address.as_u64[1] ^ + ip->dst_address.as_u64[0] ^ + ip->dst_address.as_u64[1] ^ ip->protocol); + } + else if (outer->type == + clib_host_to_net_u16 (ETHERNET_TYPE_MPLS_UNICAST)) + { + hash_key = mpls_get_key ((mpls_unicast_header_t *) (outer + 1)); + } + else + { + hash_key = outer->type; + } + } + else + { + hash_key = 0; + } + + return hash_key; +} static inline u64 eth_get_key (ethernet_header_t * h0) |