diff options
-rw-r--r-- | src/plugins/gbp/gbp_endpoint.c | 18 | ||||
-rw-r--r-- | src/plugins/gbp/gbp_endpoint_group.c | 7 | ||||
-rw-r--r-- | src/plugins/gbp/gbp_learn_node.c | 30 | ||||
-rw-r--r-- | test/test_gbp.py | 66 |
4 files changed, 103 insertions, 18 deletions
diff --git a/src/plugins/gbp/gbp_endpoint.c b/src/plugins/gbp/gbp_endpoint.c index 836930accbe..611e3444e49 100644 --- a/src/plugins/gbp/gbp_endpoint.c +++ b/src/plugins/gbp/gbp_endpoint.c @@ -498,18 +498,12 @@ gbp_endpoint_loc_update (const gbp_endpoint_t * ge, gbp_endpoint_n_learned (is_learnt - was_learnt); - if (INDEX_INVALID == gel->gel_epg) - { - gel->gel_epg = ggi; - if (INDEX_INVALID != gel->gel_epg) - { - gbp_endpoint_group_lock (gel->gel_epg); - } - } - else - { - ASSERT (gel->gel_epg == ggi); - } + /* + * update the EPG + */ + gbp_endpoint_group_lock (ggi); + gbp_endpoint_group_unlock (gel->gel_epg); + gel->gel_epg = ggi; if (gel->gel_flags & GBP_ENDPOINT_FLAG_REMOTE) { diff --git a/src/plugins/gbp/gbp_endpoint_group.c b/src/plugins/gbp/gbp_endpoint_group.c index 19c05f93ce2..92bad373c32 100644 --- a/src/plugins/gbp/gbp_endpoint_group.c +++ b/src/plugins/gbp/gbp_endpoint_group.c @@ -52,11 +52,14 @@ gbp_endpoint_group_get (index_t i) } void -gbp_endpoint_group_lock (index_t i) +gbp_endpoint_group_lock (index_t ggi) { gbp_endpoint_group_t *gg; - gg = gbp_endpoint_group_get (i); + if (INDEX_INVALID == ggi) + return; + + gg = gbp_endpoint_group_get (ggi); gg->gg_locks++; } diff --git a/src/plugins/gbp/gbp_learn_node.c b/src/plugins/gbp/gbp_learn_node.c index 113969a526b..a6c54971956 100644 --- a/src/plugins/gbp/gbp_learn_node.c +++ b/src/plugins/gbp/gbp_learn_node.c @@ -179,6 +179,28 @@ gbp_learn_get_outer (const ethernet_header_t * eh0, *outer_dst = ip0->dst_address; } +always_inline int +gbp_endpoint_update_required (const gbp_endpoint_t * ge0, + u32 rx_sw_if_index, sclass_t sclass) +{ + /* Conditions for [re]learning this EP */ + + /* 1. it doesn't have a dataplane source */ + if (!gbp_endpoint_is_learnt (ge0)) + return (!0); + + /* 2. has the input interface changed */ + if (gbp_itf_get_sw_if_index (ge0->ge_fwd.gef_itf) != rx_sw_if_index) + return (!0); + + /* 3. has the sclass changed */ + if (sclass != ge0->ge_fwd.gef_sclass) + return (!0); + + /* otherwise it's unchanged */ + return (0); +} + VLIB_NODE_FN (gbp_learn_l2_node) (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) @@ -246,7 +268,7 @@ VLIB_NODE_FN (gbp_learn_l2_node) (vlib_main_t * vm, * check for new EP or a moved EP */ if (NULL == ge0 || - gbp_itf_get_sw_if_index (ge0->ge_fwd.gef_itf) != sw_if_index0) + gbp_endpoint_update_required (ge0, sw_if_index0, sclass0)) { /* * use the last 4 bytes of the mac address as the hash for the EP @@ -543,7 +565,8 @@ gbp_learn_l3 (vlib_main_t * vm, ge0 = gbp_endpoint_find_ip6 (&ip6_0->src_address, fib_index0); - if ((NULL == ge0) || !gbp_endpoint_is_learnt (ge0)) + if ((NULL == ge0) || + gbp_endpoint_update_required (ge0, sw_if_index0, sclass0)) { t0 = throttle_check (&glm->gl_l3_throttle, thread_index, @@ -576,7 +599,8 @@ gbp_learn_l3 (vlib_main_t * vm, gbp_learn_get_outer (eth0, &outer_src, &outer_dst); ge0 = gbp_endpoint_find_ip4 (&ip4_0->src_address, fib_index0); - if ((NULL == ge0) || !gbp_endpoint_is_learnt (ge0)) + if ((NULL == ge0) || + gbp_endpoint_update_required (ge0, sw_if_index0, sclass0)) { t0 = throttle_check (&glm->gl_l3_throttle, thread_index, ip4_0->src_address.as_u32, seed); diff --git a/test/test_gbp.py b/test/test_gbp.py index 9cf1817b296..f6bded6bc90 100644 --- a/test/test_gbp.py +++ b/test/test_gbp.py @@ -35,7 +35,8 @@ except NameError: NUM_PKTS = 67 -def find_gbp_endpoint(test, sw_if_index=None, ip=None, mac=None, tep=None): +def find_gbp_endpoint(test, sw_if_index=None, ip=None, mac=None, + tep=None, sclass=None): if ip: vip = VppIpAddress(ip) if mac: @@ -52,6 +53,9 @@ def find_gbp_endpoint(test, sw_if_index=None, ip=None, mac=None, tep=None): if sw_if_index: if ep.endpoint.sw_if_index != sw_if_index: continue + if sclass: + if ep.endpoint.sclass != sclass: + continue if ip: for eip in ep.endpoint.ips: if vip == eip: @@ -2089,6 +2093,7 @@ class TestGBP(VppTestCase): self.assertTrue(find_gbp_endpoint( self, vx_tun_l2_1.sw_if_index, + sclass=113, mac=l['mac'], tep=[self.pg2.local_ip4, self.pg2.remote_hosts[2].ip4])) @@ -2118,6 +2123,65 @@ class TestGBP(VppTestCase): self.assertEqual(rx[IPv6].dst, l['ip6']) # + # EP changes sclass + # + for l in learnt: + # a packet with an sclass from a known EPG + p = (Ether(src=self.pg2.remote_mac, + dst=self.pg2.local_mac) / + IP(src=self.pg2.remote_hosts[2].ip4, + dst=self.pg2.local_ip4) / + UDP(sport=1234, dport=48879) / + VXLAN(vni=99, gpid=112, flags=0x88) / + Ether(src=l['mac'], dst=ep.mac) / + IPv6(src=l['ip6'], dst=ep.ip6.address) / + UDP(sport=1234, dport=1234) / + Raw('\xa5' * 100)) + + rx = self.send_and_expect(self.pg2, p * 1, self.pg0) + rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0) + + self.assertTrue(find_gbp_endpoint( + self, + vx_tun_l2_1.sw_if_index, + mac=l['mac'], + sclass=112, + tep=[self.pg2.local_ip4, + self.pg2.remote_hosts[2].ip4])) + + # + # check reachability and contract intra-epg + # + allow_intra_class = self.statistics.get_err_counter( + '/err/gbp-policy-mac/allow-intra-sclass') + + for l in learnt: + p = (Ether(src=ep.mac, dst=l['mac']) / + IPv6(dst=l['ip6'], src=ep.ip6.address) / + UDP(sport=1234, dport=1234) / + Raw('\xa5' * 100)) + + rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2) + + for rx in rxs: + self.assertEqual(rx[IP].src, self.pg2.local_ip4) + self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4) + self.assertEqual(rx[UDP].dport, 48879) + self.assertEqual(rx[VXLAN].gpid, 112) + self.assertEqual(rx[VXLAN].vni, 99) + self.assertTrue(rx[VXLAN].flags.G) + self.assertTrue(rx[VXLAN].flags.Instance) + self.assertTrue(rx[VXLAN].gpflags.A) + self.assertFalse(rx[VXLAN].gpflags.D) + self.assertEqual(rx[IPv6].dst, l['ip6']) + + allow_intra_class += NUM_PKTS + + self.assert_error_counter_equal( + '/err/gbp-policy-mac/allow-intra-sclass', + allow_intra_class) + + # # clean up # for l in learnt: |