summaryrefslogtreecommitdiffstats
path: root/vnet
diff options
context:
space:
mode:
Diffstat (limited to 'vnet')
-rw-r--r--vnet/vnet/handoff.c20
-rw-r--r--vnet/vnet/handoff.h66
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)