handoff - allow symmetrical dispatch 62/3862/3
authorGabriel Ganne <gabriel.ganne@qosmos.com>
Wed, 16 Nov 2016 15:57:00 +0000 (16:57 +0100)
committerDamjan Marion <dmarion.lists@gmail.com>
Fri, 18 Nov 2016 13:40:10 +0000 (13:40 +0000)
update cli cmd with symmetrical|asymmetrical flag
(asymetrical by default)

Change-Id: I8186506413a3ba0aa0561c0448b5e06e6d6e7ece
Signed-off-by: Gabriel Ganne <gabriel.ganne@qosmos.com>
vnet/vnet/handoff.c
vnet/vnet/handoff.h

index 22d2ea9..9f3c93b 100644 (file)
@@ -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;
 
index 4fefb36..815206a 100644 (file)
@@ -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)