summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/gbp/gbp_endpoint.c18
-rw-r--r--src/plugins/gbp/gbp_endpoint_group.c7
-rw-r--r--src/plugins/gbp/gbp_learn_node.c30
-rw-r--r--test/test_gbp.py66
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: