From d40c3e652d487f0f165d5e595864c4ccd464de3b Mon Sep 17 00:00:00 2001 From: Mohsin Kazmi Date: Wed, 21 Nov 2018 10:46:57 +0100 Subject: [PATCH] gbp: Add support for flow hash profile Change-Id: Ibea87f21b3403045cc0d865903b94396fe670e79 Signed-off-by: Mohsin Kazmi --- src/plugins/gbp/gbp_contract.c | 31 ++++-- src/plugins/gbp/gbp_contract.h | 4 +- test/test_gbp.py | 217 ++++++++++++++++++++++++++++++----------- 3 files changed, 185 insertions(+), 67 deletions(-) diff --git a/src/plugins/gbp/gbp_contract.c b/src/plugins/gbp/gbp_contract.c index ec545693dd3..ee12a760f4b 100644 --- a/src/plugins/gbp/gbp_contract.c +++ b/src/plugins/gbp/gbp_contract.c @@ -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); } diff --git a/src/plugins/gbp/gbp_contract.h b/src/plugins/gbp/gbp_contract.h index 21e7265a82f..bd7d8339e21 100644 --- a/src/plugins/gbp/gbp_contract.h +++ b/src/plugins/gbp/gbp_contract.h @@ -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") diff --git a/test/test_gbp.py b/test/test_gbp.py index 2cceba6b906..68bbfe4a7c9 100644 --- a/test/test_gbp.py +++ b/test/test_gbp.py @@ -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) -- 2.16.6