gbp: Add support for flow hash profile 79/16079/7
authorMohsin Kazmi <sykazmi@cisco.com>
Wed, 21 Nov 2018 09:46:57 +0000 (10:46 +0100)
committerNeale Ranns <nranns@cisco.com>
Thu, 29 Nov 2018 12:33:54 +0000 (12:33 +0000)
Change-Id: Ibea87f21b3403045cc0d865903b94396fe670e79
Signed-off-by: Mohsin Kazmi <sykazmi@cisco.com>
src/plugins/gbp/gbp_contract.c
src/plugins/gbp/gbp_contract.h
test/test_gbp.py

index ec54569..ee12a76 100644 (file)
@@ -48,6 +48,7 @@ gbp_rule_alloc (gbp_rule_action_t action,
 
   pool_get_zero (gbp_rule_pool, gu);
 
+  gu->gu_hash_mode = hash_mode;
   gu->gu_nhs = nhs;
   gu->gu_action = action;
 
@@ -158,9 +159,9 @@ format_gbp_rule_action (u8 * s, va_list * args)
 static u8 *
 format_gbp_hash_mode (u8 * s, va_list * args)
 {
-  gbp_hash_mode_t action = va_arg (*args, gbp_hash_mode_t);
+  gbp_hash_mode_t hash_mode = va_arg (*args, gbp_hash_mode_t);
 
-  switch (action)
+  switch (hash_mode)
     {
 #define _(v,a) case GBP_HASH_MODE_##v: return (format (s, "%s", a));
       foreach_gbp_hash_mode
@@ -261,6 +262,23 @@ gbp_contract_mk_adj (gbp_next_hop_t * gnh, fib_protocol_t fproto)
   adj_unlock (old_ai);
 }
 
+static flow_hash_config_t
+gbp_contract_mk_lb_hp (gbp_hash_mode_t gu_hash_mode)
+{
+  switch (gu_hash_mode)
+    {
+    case GBP_HASH_MODE_SRC_IP:
+      return IP_FLOW_HASH_SRC_ADDR;
+    case GBP_HASH_MODE_DST_IP:
+      return IP_FLOW_HASH_DST_ADDR;
+    case GBP_HASH_MODE_SYMMETRIC:
+      return (IP_FLOW_HASH_SRC_ADDR | IP_FLOW_HASH_DST_ADDR |
+             IP_FLOW_HASH_PROTO | IP_FLOW_HASH_SYMMETRIC);
+    }
+
+  return 0;
+}
+
 static void
 gbp_contract_mk_lb (index_t gui, fib_protocol_t fproto)
 {
@@ -307,16 +325,17 @@ gbp_contract_mk_lb (index_t gui, fib_protocol_t fproto)
               dproto, gnh->gnh_ai[fproto]);
     }
 
-    // FIXME get algo and sticky bit from contract LB algo
     if (!dpo_id_is_valid (&gu->gu_dpo[pnode][fproto]))
       {
        dpo_id_t dpo = DPO_INVALID;
 
        dpo_set (&dpo, DPO_LOAD_BALANCE, dproto,
                 load_balance_create (vec_len (paths),
-                                     dproto, IP_FLOW_HASH_DEFAULT));
-       dpo_stack_from_node (policy_nodes[pnode],
-                            &gu->gu_dpo[pnode][fproto], &dpo);
+                                     dproto,
+                                     gbp_contract_mk_lb_hp
+                                     (gu->gu_hash_mode)));
+       dpo_stack_from_node (policy_nodes[pnode], &gu->gu_dpo[pnode][fproto],
+                            &dpo);
        dpo_reset (&dpo);
       }
 
index 21e7265..bd7d833 100644 (file)
@@ -50,8 +50,8 @@ typedef struct gbp_next_hop_t_
   index_t gnh_ai[FIB_PROTOCOL_IP_MAX];
 } gbp_next_hop_t;
 
-#define foreach_gbp_hash_mode   \
-  _(SRC_IP, "src-ip")           \
+#define foreach_gbp_hash_mode  \
+  _(SRC_IP, "src-ip")          \
   _(DST_IP, "dst-ip")          \
   _(SYMMETRIC, "symmetric")
 
index 2cceba6..68bbfe4 100644 (file)
@@ -380,11 +380,10 @@ class VppGbpContractNextHop():
 
 
 class VppGbpContractRule():
-    def __init__(self, action, nhs=[]):
+    def __init__(self, action, hash_mode, nhs=[]):
         self.action = action
+        self.hash_mode = hash_mode
         self.nhs = nhs
-        e = VppEnum.vl_api_gbp_hash_mode_t
-        self.hash_mode = e.GBP_API_HASH_MODE_SRC_IP
 
     def encode(self):
         nhs = []
@@ -2575,16 +2574,16 @@ class TestGBP(VppTestCase):
                IP(src=ep1.ip4.address, dst=ep3.ip4.address) /
                UDP(sport=1234, dport=1234) /
                Raw('\xa5' * 100)),
-              (Ether(src=ep1.mac, dst=ep3.mac) /
-               IP(src=ep1.ip4.address, dst=ep3.ip4.address) /
-               UDP(sport=1234, dport=1235) /
+              (Ether(src=ep3.mac, dst=ep1.mac) /
+               IP(src=ep3.ip4.address, dst=ep1.ip4.address) /
+               UDP(sport=1234, dport=1234) /
                Raw('\xa5' * 100))]
         p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
                IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
                UDP(sport=1234, dport=1234) /
                Raw('\xa5' * 100)),
-              (Ether(src=ep1.mac, dst=ep3.mac) /
-               IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
+              (Ether(src=ep3.mac, dst=ep1.mac) /
+               IPv6(src=ep3.ip6.address, dst=ep1.ip6.address) /
                UDP(sport=1234, dport=1230) /
                Raw('\xa5' * 100))]
 
@@ -2601,41 +2600,64 @@ class TestGBP(VppTestCase):
         rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
         acl_index = acl.add_vpp_config([rule4, rule6])
 
+        #
+        # test the src-ip hash mode
+        #
         c1 = VppGbpContract(
             self, 220, 222, acl_index,
             [VppGbpContractRule(
                 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
+                VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
                 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
                                        sep1.ip4, sep1.epg.rd),
                  VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
                                        sep2.ip4, sep2.epg.rd)]),
              VppGbpContractRule(
                  VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
+                 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
                  [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
                                         sep3.ip6, sep3.epg.rd),
                   VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
                                         sep4.ip6, sep4.epg.rd)])])
         c1.add_vpp_config()
 
+        c2 = VppGbpContract(
+            self, 222, 220, acl_index,
+            [VppGbpContractRule(
+                VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
+                VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
+                [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
+                                       sep1.ip4, sep1.epg.rd),
+                 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
+                                       sep2.ip4, sep2.epg.rd)]),
+             VppGbpContractRule(
+                 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
+                 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
+                 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
+                                        sep3.ip6, sep3.epg.rd),
+                  VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
+                                        sep4.ip6, sep4.epg.rd)])])
+        c2.add_vpp_config()
+
         #
         # send again with the contract preset, now packets arrive
         # at SEP1 or SEP2 depending on the hashing
         #
-        rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep2.itf)
+        rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
 
         for rx in rxs:
             self.assertEqual(rx[Ether].src, routed_src_mac)
-            self.assertEqual(rx[Ether].dst, sep2.mac)
+            self.assertEqual(rx[Ether].dst, sep1.mac)
             self.assertEqual(rx[IP].src, ep1.ip4.address)
             self.assertEqual(rx[IP].dst, ep3.ip4.address)
 
-        rxs = self.send_and_expect(self.pg0, p4[1] * 17, sep1.itf)
+        rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
 
         for rx in rxs:
             self.assertEqual(rx[Ether].src, routed_src_mac)
-            self.assertEqual(rx[Ether].dst, sep1.mac)
-            self.assertEqual(rx[IP].src, ep1.ip4.address)
-            self.assertEqual(rx[IP].dst, ep3.ip4.address)
+            self.assertEqual(rx[Ether].dst, sep2.mac)
+            self.assertEqual(rx[IP].src, ep3.ip4.address)
+            self.assertEqual(rx[IP].dst, ep1.ip4.address)
 
         rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
 
@@ -2658,13 +2680,13 @@ class TestGBP(VppTestCase):
             self.assertEqual(inner[IPv6].src, ep1.ip6.address)
             self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
 
-        rxs = self.send_and_expect(self.pg0, p6[1] * 17, sep3.itf)
+        rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
 
         for rx in rxs:
             self.assertEqual(rx[Ether].src, routed_src_mac)
             self.assertEqual(rx[Ether].dst, sep3.mac)
-            self.assertEqual(rx[IPv6].src, ep1.ip6.address)
-            self.assertEqual(rx[IPv6].dst, ep3.ip6.address)
+            self.assertEqual(rx[IPv6].src, ep3.ip6.address)
+            self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
 
         #
         # programme the unknown EP
@@ -2705,6 +2727,68 @@ class TestGBP(VppTestCase):
             self.assertEqual(inner[IPv6].src, ep1.ip6.address)
             self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
 
+        c1.remove_vpp_config()
+        c2.remove_vpp_config()
+
+        #
+        # test the symmetric hash mode
+        #
+        c1 = VppGbpContract(
+            self, 220, 222, acl_index,
+            [VppGbpContractRule(
+                VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
+                VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
+                [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
+                                       sep1.ip4, sep1.epg.rd),
+                 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
+                                       sep2.ip4, sep2.epg.rd)]),
+             VppGbpContractRule(
+                 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
+                 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
+                 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
+                                        sep3.ip6, sep3.epg.rd),
+                  VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
+                                        sep4.ip6, sep4.epg.rd)])])
+        c1.add_vpp_config()
+
+        c2 = VppGbpContract(
+            self, 222, 220, acl_index,
+            [VppGbpContractRule(
+                VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
+                VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
+                [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
+                                       sep1.ip4, sep1.epg.rd),
+                 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
+                                       sep2.ip4, sep2.epg.rd)]),
+             VppGbpContractRule(
+                 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
+                 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
+                 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
+                                        sep3.ip6, sep3.epg.rd),
+                  VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
+                                        sep4.ip6, sep4.epg.rd)])])
+        c2.add_vpp_config()
+
+        #
+        # send again with the contract preset, now packets arrive
+        # at SEP1 for both directions
+        #
+        rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
+
+        for rx in rxs:
+            self.assertEqual(rx[Ether].src, routed_src_mac)
+            self.assertEqual(rx[Ether].dst, sep1.mac)
+            self.assertEqual(rx[IP].src, ep1.ip4.address)
+            self.assertEqual(rx[IP].dst, ep3.ip4.address)
+
+        rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
+
+        for rx in rxs:
+            self.assertEqual(rx[Ether].src, routed_src_mac)
+            self.assertEqual(rx[Ether].dst, sep1.mac)
+            self.assertEqual(rx[IP].src, ep3.ip4.address)
+            self.assertEqual(rx[IP].dst, ep1.ip4.address)
+
         #
         # programme the unknown EP for the L3 tests
         #
@@ -2718,40 +2802,42 @@ class TestGBP(VppTestCase):
                IP(src=ep1.ip4.address, dst=ep2.ip4.address) /
                UDP(sport=1234, dport=1234) /
                Raw('\xa5' * 100)),
-              (Ether(src=ep1.mac, dst=self.router_mac.address) /
-               IP(src=ep1.ip4.address, dst=ep2.ip4.address) /
-               UDP(sport=1234, dport=1235) /
+              (Ether(src=ep2.mac, dst=self.router_mac.address) /
+               IP(src=ep2.ip4.address, dst=ep1.ip4.address) /
+               UDP(sport=1234, dport=1234) /
                Raw('\xa5' * 100))]
         p6 = [(Ether(src=ep1.mac, dst=self.router_mac.address) /
                IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
                UDP(sport=1234, dport=1234) /
                Raw('\xa5' * 100)),
-              (Ether(src=ep1.mac, dst=self.router_mac.address) /
-               IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
-               UDP(sport=1234, dport=1230) /
+              (Ether(src=ep2.mac, dst=self.router_mac.address) /
+               IPv6(src=ep2.ip6.address, dst=ep1.ip6.address) /
+               UDP(sport=1234, dport=1234) /
                Raw('\xa5' * 100))]
 
-        c2 = VppGbpContract(
-            self, 220, 221, acl_index,
-            [VppGbpContractRule(
-                VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
-                [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
-                                       sep1.ip4, sep1.epg.rd),
-                 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
-                                       sep2.ip4, sep2.epg.rd)]),
-             VppGbpContractRule(
+        c3 = VppGbpContract(
+             self, 220, 221, acl_index,
+             [VppGbpContractRule(
                  VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
-                 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
-                                        sep3.ip6, sep3.epg.rd),
-                  VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
-                                        sep4.ip6, sep4.epg.rd)])])
-        c2.add_vpp_config()
+                 VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
+                 [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
+                                        sep1.ip4, sep1.epg.rd),
+                  VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
+                                        sep2.ip4, sep2.epg.rd)]),
+              VppGbpContractRule(
+                  VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
+                  VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
+                  [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
+                                         sep3.ip6, sep3.epg.rd),
+                   VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
+                                         sep4.ip6, sep4.epg.rd)])])
+        c3.add_vpp_config()
 
-        rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep2.itf)
+        rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
 
         for rx in rxs:
             self.assertEqual(rx[Ether].src, routed_src_mac)
-            self.assertEqual(rx[Ether].dst, sep2.mac)
+            self.assertEqual(rx[Ether].dst, sep1.mac)
             self.assertEqual(rx[IP].src, ep1.ip4.address)
             self.assertEqual(rx[IP].dst, ep2.ip4.address)
 
@@ -2763,7 +2849,7 @@ class TestGBP(VppTestCase):
             VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3)
         vx_tun_l3.add_vpp_config()
 
-        c3 = VppGbpContract(
+        c4 = VppGbpContract(
             self, 221, 220, acl_index,
             [VppGbpContractRule(
                 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
@@ -2771,7 +2857,7 @@ class TestGBP(VppTestCase):
              VppGbpContractRule(
                  VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
                  [])])
-        c3.add_vpp_config()
+        c4.add_vpp_config()
 
         p = (Ether(src=self.pg7.remote_mac,
                    dst=self.pg7.local_mac) /
@@ -2815,29 +2901,13 @@ class TestGBP(VppTestCase):
         p4 = [(Ether(src=ep1.mac, dst=self.router_mac.address) /
                IP(src=ep1.ip4.address, dst="10.0.0.88") /
                UDP(sport=1234, dport=1234) /
-               Raw('\xa5' * 100)),
-              (Ether(src=ep1.mac, dst=self.router_mac.address) /
-               IP(src=ep1.ip4.address, dst="10.0.0.88") /
-               UDP(sport=1234, dport=1235) /
                Raw('\xa5' * 100))]
         p6 = [(Ether(src=ep1.mac, dst=self.router_mac.address) /
                IPv6(src=ep1.ip6.address, dst="2001:10::88") /
                UDP(sport=1234, dport=1234) /
-               Raw('\xa5' * 100)),
-              (Ether(src=ep1.mac, dst=self.router_mac.address) /
-               IPv6(src=ep1.ip6.address, dst="2001:10::88") /
-               UDP(sport=1234, dport=123) /
                Raw('\xa5' * 100))]
 
-        rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep2.itf)
-
-        for rx in rxs:
-            self.assertEqual(rx[Ether].src, routed_src_mac)
-            self.assertEqual(rx[Ether].dst, sep2.mac)
-            self.assertEqual(rx[IP].src, ep1.ip4.address)
-            self.assertEqual(rx[IP].dst, "10.0.0.88")
-
-        rxs = self.send_and_expect(self.pg0, p4[1] * 17, sep1.itf)
+        rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
 
         for rx in rxs:
             self.assertEqual(rx[Ether].src, routed_src_mac)
@@ -2853,7 +2923,36 @@ class TestGBP(VppTestCase):
             self.assertEqual(rx[IPv6].src, ep1.ip6.address)
             self.assertEqual(rx[IPv6].dst, "2001:10::88")
 
-        rxs = self.send_and_expect(self.pg0, p6[1] * 17, sep3.itf)
+        #
+        # test the dst-ip hash mode
+        #
+        c5 = VppGbpContract(
+            self, 220, 221, acl_index,
+            [VppGbpContractRule(
+                VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
+                VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
+                [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
+                                       sep1.ip4, sep1.epg.rd),
+                 VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
+                                       sep2.ip4, sep2.epg.rd)]),
+             VppGbpContractRule(
+                 VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
+                VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
+                 [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
+                                        sep3.ip6, sep3.epg.rd),
+                  VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
+                                        sep4.ip6, sep4.epg.rd)])])
+        c5.add_vpp_config()
+
+        rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
+
+        for rx in rxs:
+            self.assertEqual(rx[Ether].src, routed_src_mac)
+            self.assertEqual(rx[Ether].dst, sep1.mac)
+            self.assertEqual(rx[IP].src, ep1.ip4.address)
+            self.assertEqual(rx[IP].dst, "10.0.0.88")
+
+        rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
 
         for rx in rxs:
             self.assertEqual(rx[Ether].src, routed_src_mac)