From 8da9fc659badc016e409f772673002f021c0cc4a Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Mon, 4 Mar 2019 14:08:11 -0800 Subject: [PATCH] GBP: learn from ARP and L2 packets Change-Id: I8af7bca566ec7c9bd2b72529d49e04c6e649b44a Signed-off-by: Neale Ranns --- extras/vom/vom/gbp_vxlan.cpp | 36 +++++++---- extras/vom/vom/gbp_vxlan.hpp | 9 ++- extras/vom/vom/gbp_vxlan_cmds.cpp | 4 ++ extras/vom/vom/gbp_vxlan_cmds.hpp | 2 + src/plugins/gbp/gbp.api | 1 + src/plugins/gbp/gbp_api.c | 4 +- src/plugins/gbp/gbp_bridge_domain.c | 5 +- src/plugins/gbp/gbp_bridge_domain.h | 6 +- src/plugins/gbp/gbp_endpoint.c | 23 ++++++- src/plugins/gbp/gbp_learn_node.c | 29 ++++++--- src/plugins/gbp/gbp_vxlan.c | 9 ++- src/plugins/gbp/gbp_vxlan.h | 9 ++- src/vnet/vxlan-gbp/vxlan_gbp.h | 2 - test/test_gbp.py | 117 +++++++++++++++++++++++++++++++++--- test/vpp_papi_provider.py | 5 +- 15 files changed, 216 insertions(+), 45 deletions(-) diff --git a/extras/vom/vom/gbp_vxlan.cpp b/extras/vom/vom/gbp_vxlan.cpp index af4467abfbb..76826c2a3d6 100644 --- a/extras/vom/vom/gbp_vxlan.cpp +++ b/extras/vom/vom/gbp_vxlan.cpp @@ -14,6 +14,7 @@ */ #include "vom/gbp_vxlan.hpp" +#include "vom/api_types.hpp" #include "vom/gbp_vxlan_cmds.hpp" #include "vom/interface.hpp" #include "vom/singular_db_funcs.hpp" @@ -29,22 +30,28 @@ singular_db gbp_vxlan::m_db; gbp_vxlan::event_handler gbp_vxlan::m_evh; -gbp_vxlan::gbp_vxlan(uint32_t vni, const gbp_route_domain& grd) +gbp_vxlan::gbp_vxlan(uint32_t vni, + const gbp_route_domain& grd, + const boost::asio::ip::address_v4& src) : interface(mk_name(vni), interface::type_t::UNKNOWN, interface::admin_state_t::UP) , m_vni(vni) , m_gbd() , m_grd(grd.singular()) + , m_src(src) { } -gbp_vxlan::gbp_vxlan(uint32_t vni, const gbp_bridge_domain& gbd) +gbp_vxlan::gbp_vxlan(uint32_t vni, + const gbp_bridge_domain& gbd, + const boost::asio::ip::address_v4& src) : interface(mk_name(vni), interface::type_t::UNKNOWN, interface::admin_state_t::UP) , m_vni(vni) , m_gbd(gbd.singular()) , m_grd() + , m_src(src) { } @@ -53,6 +60,7 @@ gbp_vxlan::gbp_vxlan(const gbp_vxlan& vt) , m_vni(vt.m_vni) , m_gbd(vt.m_gbd) , m_grd(vt.m_grd) + , m_src(vt.m_src) { } @@ -75,7 +83,7 @@ gbp_vxlan::key() const bool gbp_vxlan::operator==(const gbp_vxlan& vt) const { - return (m_vni == vt.m_vni); + return (m_vni == vt.m_vni && m_src == vt.m_src); } void @@ -92,11 +100,11 @@ gbp_vxlan::replay() { if (rc_t::OK == m_hdl) { if (m_grd) - HW::enqueue(new gbp_vxlan_cmds::create_cmd(m_hdl, name(), m_vni, false, - m_grd->id())); + HW::enqueue(new gbp_vxlan_cmds::create_cmd(m_hdl, name(), m_src, m_vni, + false, m_grd->id())); else if (m_gbd) - HW::enqueue(new gbp_vxlan_cmds::create_cmd(m_hdl, name(), m_vni, true, - m_gbd->id())); + HW::enqueue(new gbp_vxlan_cmds::create_cmd(m_hdl, name(), m_src, m_vni, + true, m_gbd->id())); } } @@ -129,11 +137,11 @@ gbp_vxlan::update(const gbp_vxlan& desired) */ if (rc_t::OK != m_hdl) { if (m_grd) - HW::enqueue(new gbp_vxlan_cmds::create_cmd(m_hdl, name(), m_vni, false, - m_grd->id())); + HW::enqueue(new gbp_vxlan_cmds::create_cmd(m_hdl, name(), m_src, m_vni, + false, m_grd->id())); else if (m_gbd) - HW::enqueue(new gbp_vxlan_cmds::create_cmd(m_hdl, name(), m_vni, true, - m_gbd->id())); + HW::enqueue(new gbp_vxlan_cmds::create_cmd(m_hdl, name(), m_src, m_vni, + true, m_gbd->id())); } } @@ -176,11 +184,13 @@ gbp_vxlan::event_handler::handle_populate(const client_db::key_t& key) for (auto& record : *cmd) { auto& payload = record.get_payload(); + boost::asio::ip::address_v4 src = from_api(payload.tunnel.src); + if (GBP_VXLAN_TUNNEL_MODE_L3 == payload.tunnel.mode) { auto rd = gbp_route_domain::find(payload.tunnel.bd_rd_id); if (rd) { - gbp_vxlan vt(payload.tunnel.vni, *rd); + gbp_vxlan vt(payload.tunnel.vni, *rd, src); OM::commit(key, vt); VOM_LOG(log_level_t::DEBUG) << "dump: " << vt.to_string(); } @@ -188,7 +198,7 @@ gbp_vxlan::event_handler::handle_populate(const client_db::key_t& key) auto bd = gbp_bridge_domain::find(payload.tunnel.bd_rd_id); if (bd) { - gbp_vxlan vt(payload.tunnel.vni, *bd); + gbp_vxlan vt(payload.tunnel.vni, *bd, src); OM::commit(key, vt); VOM_LOG(log_level_t::DEBUG) << "dump: " << vt.to_string(); } diff --git a/extras/vom/vom/gbp_vxlan.hpp b/extras/vom/vom/gbp_vxlan.hpp index cae67d8ad17..8aa4b6b6b6e 100644 --- a/extras/vom/vom/gbp_vxlan.hpp +++ b/extras/vom/vom/gbp_vxlan.hpp @@ -38,8 +38,12 @@ public: /** * Construct a new object matching the desried state */ - gbp_vxlan(uint32_t vni, const gbp_bridge_domain& gbd); - gbp_vxlan(uint32_t vni, const gbp_route_domain& grd); + gbp_vxlan(uint32_t vni, + const gbp_bridge_domain& gbd, + const boost::asio::ip::address_v4& src); + gbp_vxlan(uint32_t vni, + const gbp_route_domain& grd, + const boost::asio::ip::address_v4& src); /* * Destructor @@ -161,6 +165,7 @@ private: uint32_t m_vni; std::shared_ptr m_gbd; std::shared_ptr m_grd; + boost::asio::ip::address_v4 m_src; /** * A map of all VLAN tunnela against thier key diff --git a/extras/vom/vom/gbp_vxlan_cmds.cpp b/extras/vom/vom/gbp_vxlan_cmds.cpp index a3565902b5d..86b61c14f06 100644 --- a/extras/vom/vom/gbp_vxlan_cmds.cpp +++ b/extras/vom/vom/gbp_vxlan_cmds.cpp @@ -14,15 +14,18 @@ */ #include "vom/gbp_vxlan_cmds.hpp" +#include "vom/api_types.hpp" namespace VOM { namespace gbp_vxlan_cmds { create_cmd::create_cmd(HW::item& item, const std::string& name, + const boost::asio::ip::address_v4& src, uint32_t vni, bool is_l2, uint32_t bd_rd) : interface::create_cmd(item, name) + , m_src(src) , m_vni(vni) , m_is_l2(is_l2) , m_bd_rd(bd_rd) @@ -42,6 +45,7 @@ create_cmd::issue(connection& con) payload.tunnel.mode = GBP_VXLAN_TUNNEL_MODE_L2; else payload.tunnel.mode = GBP_VXLAN_TUNNEL_MODE_L3; + to_api(m_src, payload.tunnel.src); VAPI_CALL(req.execute()); diff --git a/extras/vom/vom/gbp_vxlan_cmds.hpp b/extras/vom/vom/gbp_vxlan_cmds.hpp index a42a6531f20..642235731bb 100644 --- a/extras/vom/vom/gbp_vxlan_cmds.hpp +++ b/extras/vom/vom/gbp_vxlan_cmds.hpp @@ -35,6 +35,7 @@ public: */ create_cmd(HW::item& item, const std::string& name, + const boost::asio::ip::address_v4& src, uint32_t vni, bool is_l2, uint32_t bd_rd); @@ -54,6 +55,7 @@ public: bool operator==(const create_cmd& i) const; private: + boost::asio::ip::address_v4 m_src; uint32_t m_vni; bool m_is_l2; uint32_t m_bd_rd; diff --git a/src/plugins/gbp/gbp.api b/src/plugins/gbp/gbp.api index 347855197d7..8343e228f19 100644 --- a/src/plugins/gbp/gbp.api +++ b/src/plugins/gbp/gbp.api @@ -344,6 +344,7 @@ typedef gbp_vxlan_tunnel u32 vni; vl_api_gbp_vxlan_tunnel_mode_t mode; u32 bd_rd_id; + vl_api_ip4_address_t src; }; define gbp_vxlan_tunnel_add diff --git a/src/plugins/gbp/gbp_api.c b/src/plugins/gbp/gbp_api.c index 7c36da6829a..ffdae2869bf 100644 --- a/src/plugins/gbp/gbp_api.c +++ b/src/plugins/gbp/gbp_api.c @@ -1036,9 +1036,11 @@ vl_api_gbp_vxlan_tunnel_add_t_handler (vl_api_gbp_vxlan_tunnel_add_t * mp) { vl_api_gbp_vxlan_tunnel_add_reply_t *rmp; gbp_vxlan_tunnel_layer_t layer; + ip4_address_t src; u32 sw_if_index; int rv = 0; + ip4_address_decode (mp->tunnel.src, &src); rv = gbp_vxlan_tunnel_mode_2_layer (mp->tunnel.mode, &layer); if (0 != rv) @@ -1046,7 +1048,7 @@ vl_api_gbp_vxlan_tunnel_add_t_handler (vl_api_gbp_vxlan_tunnel_add_t * mp) rv = gbp_vxlan_tunnel_add (ntohl (mp->tunnel.vni), layer, - ntohl (mp->tunnel.bd_rd_id), &sw_if_index); + ntohl (mp->tunnel.bd_rd_id), &src, &sw_if_index); out: /* *INDENT-OFF* */ diff --git a/src/plugins/gbp/gbp_bridge_domain.c b/src/plugins/gbp/gbp_bridge_domain.c index 261b5683903..24bfb254ad4 100644 --- a/src/plugins/gbp/gbp_bridge_domain.c +++ b/src/plugins/gbp/gbp_bridge_domain.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -125,7 +126,7 @@ format_gbp_bridge_domain_flags (u8 * s, va_list * args) } else { - s = format (s, "noe"); + s = format (s, "none"); } return (s); } @@ -218,6 +219,7 @@ gbp_bridge_domain_add_and_lock (u32 bd_id, MODE_L2_BRIDGE, gb->gb_bm_flood_sw_if_index, bd_index, L2_BD_PORT_TYPE_NORMAL, 0, 0); gbp_sclass_enable_l2 (gb->gb_bm_flood_sw_if_index); + gbp_learn_enable (gb->gb_bm_flood_sw_if_index, GBP_LEARN_MODE_L2); } /* @@ -275,6 +277,7 @@ gbp_bridge_domain_unlock (index_t index) MODE_L3, gb->gb_bm_flood_sw_if_index, gb->gb_bd_index, L2_BD_PORT_TYPE_NORMAL, 0, 0); gbp_sclass_disable_l2 (gb->gb_bm_flood_sw_if_index); + gbp_learn_enable (gb->gb_bm_flood_sw_if_index, GBP_LEARN_MODE_L2); } gbp_bridge_domain_db_remove (gb); diff --git a/src/plugins/gbp/gbp_bridge_domain.h b/src/plugins/gbp/gbp_bridge_domain.h index 25498eee5fe..8e6146c7955 100644 --- a/src/plugins/gbp/gbp_bridge_domain.h +++ b/src/plugins/gbp/gbp_bridge_domain.h @@ -63,10 +63,10 @@ typedef struct gbp_bridge_domain_t_ u32 gb_bm_flood_sw_if_index; /** - * The BD's VNI interface on which packets from unkown endpoints - * arrive + * The index of the BD's VNI interface on which packets from + * unkown endpoints arrive */ - u32 gb_vni_sw_if_index; + u32 gb_vni; /** * locks/references to the BD so it does not get deleted (from the API) diff --git a/src/plugins/gbp/gbp_endpoint.c b/src/plugins/gbp/gbp_endpoint.c index 9cae2ab9421..4bd726fec31 100644 --- a/src/plugins/gbp/gbp_endpoint.c +++ b/src/plugins/gbp/gbp_endpoint.c @@ -32,6 +32,7 @@ #include #include #include +#include static const char *gbp_endpoint_attr_names[] = GBP_ENDPOINT_ATTR_NAMES; @@ -473,6 +474,7 @@ gbp_endpoint_n_learned (int n) static void gbp_endpoint_loc_update (gbp_endpoint_loc_t * gel, + const gbp_bridge_domain_t * gb, u32 sw_if_index, index_t ggi, gbp_endpoint_flags_t flags, @@ -508,6 +510,24 @@ gbp_endpoint_loc_update (gbp_endpoint_loc_t * gel, if (NULL != tun_dst) ip46_address_copy (&gel->tun.gel_dst, tun_dst); + if (ip46_address_is_multicast (&gel->tun.gel_src)) + { + /* + * we learnt the EP from the multicast tunnel. + * Create a unicast TEP from the packet's source + * and the fixed address of the BD's parent tunnel + */ + const gbp_vxlan_tunnel_t *gt; + + gt = gbp_vxlan_tunnel_get (gb->gb_vni); + + if (NULL != gt) + { + ip46_address_copy (&gel->tun.gel_src, >->gt_src); + sw_if_index = gt->gt_sw_if_index; + } + } + /* * the input interface may be the parent GBP-vxlan interface, * create a child vlxan-gbp tunnel and use that as the endpoint's @@ -862,7 +882,8 @@ gbp_endpoint_update_and_lock (gbp_endpoint_src_t src, gei = gbp_endpoint_index (ge); gel = gbp_endpoint_loc_find_or_add (ge, src); - gbp_endpoint_loc_update (gel, sw_if_index, ggi, flags, tun_src, tun_dst); + gbp_endpoint_loc_update (gel, gbd, sw_if_index, ggi, flags, tun_src, + tun_dst); if (src <= best) { diff --git a/src/plugins/gbp/gbp_learn_node.c b/src/plugins/gbp/gbp_learn_node.c index ebb121716b2..461d209e0a6 100644 --- a/src/plugins/gbp/gbp_learn_node.c +++ b/src/plugins/gbp/gbp_learn_node.c @@ -22,6 +22,7 @@ #include #include #include +#include #define GBP_LEARN_DBG(...) \ vlib_log_debug (gbp_learn_main.gl_logger, __VA_ARGS__); @@ -72,10 +73,8 @@ gbp_learn_l2_cp (const gbp_learn_l2_t * gl2) format_mac_address_t, &gl2->mac, format_ip46_address, &gl2->ip, IP46_TYPE_ANY, gl2->epg); - vec_add1 (ips, gl2->ip); - - ASSERT (!ip46_address_is_zero (&gl2->outer_src)); - ASSERT (!ip46_address_is_zero (&gl2->outer_dst)); + if (!ip46_address_is_zero (&gl2->ip)) + vec_add1 (ips, gl2->ip); /* * flip the source and dst, since that's how it was received, this API @@ -107,9 +106,6 @@ gbp_learn_l2_ip4_dp (const u8 * mac, const ip4_address_t * ip, }; mac_address_from_bytes (&gl2.mac, mac); - ASSERT (!ip46_address_is_zero (&gl2.outer_src)); - ASSERT (!ip46_address_is_zero (&gl2.outer_dst)); - vl_api_rpc_call_main_thread (gbp_learn_l2_cp, (u8 *) & gl2, sizeof (gl2)); } @@ -260,6 +256,12 @@ VLIB_NODE_FN (gbp_learn_l2_node) (vlib_main_t * vm, { gbp_learn_get_outer (eh0, &outer_src, &outer_dst); + if (outer_src.as_u32 == 0 || outer_dst.as_u32 == 0) + { + t0 = 2; + goto trace; + } + switch (clib_net_to_host_u16 (eh0->type)) { case ETHERNET_TYPE_IP4: @@ -290,6 +292,19 @@ VLIB_NODE_FN (gbp_learn_l2_node) (vlib_main_t * vm, break; } + case ETHERNET_TYPE_ARP: + { + const ethernet_arp_header_t *arp0; + + arp0 = (ethernet_arp_header_t *) (eh0 + 1); + + gbp_learn_l2_ip4_dp (eh0->src_address, + &arp0->ip4_over_ethernet[0].ip4, + vnet_buffer (b0)->l2.bd_index, + sw_if_index0, epg0, + &outer_src, &outer_dst); + break; + } default: gbp_learn_l2_dp (eh0->src_address, vnet_buffer (b0)->l2.bd_index, diff --git a/src/plugins/gbp/gbp_vxlan.c b/src/plugins/gbp/gbp_vxlan.c index 846ea0fa6ff..c0e88fdda8e 100644 --- a/src/plugins/gbp/gbp_vxlan.c +++ b/src/plugins/gbp/gbp_vxlan.c @@ -465,7 +465,8 @@ VNET_HW_INTERFACE_CLASS (gbp_vxlan_hw_interface_class) = { int gbp_vxlan_tunnel_add (u32 vni, gbp_vxlan_tunnel_layer_t layer, - u32 bd_rd_id, u32 * sw_if_indexp) + u32 bd_rd_id, + const ip4_address_t * src, u32 * sw_if_indexp) { gbp_vxlan_tunnel_t *gt; index_t gti; @@ -512,6 +513,7 @@ gbp_vxlan_tunnel_add (u32 vni, gbp_vxlan_tunnel_layer_t layer, gt->gt_vni = vni; gt->gt_layer = layer; gt->gt_bd_rd_id = bd_rd_id; + gt->gt_src.ip4.as_u32 = src->as_u32; gt->gt_hw_if_index = vnet_register_interface (vnm, gbp_vxlan_device_class.index, gti, @@ -534,7 +536,7 @@ gbp_vxlan_tunnel_add (u32 vni, gbp_vxlan_tunnel_layer_t layer, gt->gt_gbd = gbi; gt->gt_bd_index = gb->gb_bd_index; - gb->gb_vni_sw_if_index = gt->gt_sw_if_index; + gb->gb_vni = gti; /* set it up as a GBP interface */ gt->gt_itf = gbp_itf_add_and_lock (gt->gt_sw_if_index, gt->gt_bd_index); @@ -571,7 +573,8 @@ gbp_vxlan_tunnel_add (u32 vni, gbp_vxlan_tunnel_layer_t layer, */ hash_set (gv_db, vni, gti); - vec_validate (gbp_vxlan_tunnel_db, gt->gt_sw_if_index); + vec_validate_init_empty (gbp_vxlan_tunnel_db, + gt->gt_sw_if_index, INDEX_INVALID); gbp_vxlan_tunnel_db[gt->gt_sw_if_index] = gti; if (sw_if_indexp) diff --git a/src/plugins/gbp/gbp_vxlan.h b/src/plugins/gbp/gbp_vxlan.h index acf5f4b1c7c..908abc2990e 100644 --- a/src/plugins/gbp/gbp_vxlan.h +++ b/src/plugins/gbp/gbp_vxlan.h @@ -82,6 +82,11 @@ typedef struct gbp_vxlan_tunnel_t_ * list of child vxlan-gbp tunnels built from this template */ index_t *gt_tuns; + + /** + * The source address to use for child tunnels + */ + ip46_address_t gt_src; } gbp_vxlan_tunnel_t; /** @@ -103,7 +108,9 @@ typedef enum gbp_vxlan_tunnel_type_t_ } gbp_vxlan_tunnel_type_t; extern int gbp_vxlan_tunnel_add (u32 vni, gbp_vxlan_tunnel_layer_t layer, - u32 bd_rd_id, u32 * sw_if_indexp); + u32 bd_rd_id, + const ip4_address_t * src, + u32 * sw_if_indexp); extern int gbp_vxlan_tunnel_del (u32 vni); extern gbp_vxlan_tunnel_type_t gbp_vxlan_tunnel_get_type (u32 sw_if_index); diff --git a/src/vnet/vxlan-gbp/vxlan_gbp.h b/src/vnet/vxlan-gbp/vxlan_gbp.h index 66f0cffd772..6dc62256a41 100644 --- a/src/vnet/vxlan-gbp/vxlan_gbp.h +++ b/src/vnet/vxlan-gbp/vxlan_gbp.h @@ -221,8 +221,6 @@ int vnet_vxlan_gbp_tunnel_del (u32 sw_if_indexp); void vnet_int_vxlan_gbp_bypass_mode (u32 sw_if_index, u8 is_ip6, u8 is_enable); -u32 vnet_vxlan_gbp_get_tunnel_index (u32 sw_if_index); - #endif /* included_vnet_vxlan_gbp_h */ /* diff --git a/test/test_gbp.py b/test/test_gbp.py index d716ab2668b..1b23cfffbe9 100644 --- a/test/test_gbp.py +++ b/test/test_gbp.py @@ -505,18 +505,20 @@ class VppGbpVxlanTunnel(VppInterface): GBP VXLAN tunnel """ - def __init__(self, test, vni, bd_rd_id, mode): + def __init__(self, test, vni, bd_rd_id, mode, src): super(VppGbpVxlanTunnel, self).__init__(test) self._test = test self.vni = vni self.bd_rd_id = bd_rd_id self.mode = mode + self.src = src def add_vpp_config(self): r = self._test.vapi.gbp_vxlan_tunnel_add( self.vni, self.bd_rd_id, - self.mode) + self.mode, + self.src) self.set_sw_if_index(r.sw_if_index) self._test.registry.register(self, self._test.logger) @@ -527,7 +529,7 @@ class VppGbpVxlanTunnel(VppInterface): return self.object_id() def object_id(self): - return "gbp-vxlan:%d" % (self.vni) + return "gbp-vxlan:%d" % (self.sw_if_index) def query_vpp_config(self): return find_gbp_vxlan(self._test, self.vni) @@ -1538,7 +1540,8 @@ class TestGBP(VppTestCase): # vx_tun_l2_1 = VppGbpVxlanTunnel( self, 99, bd1.bd_id, - VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2) + VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2, + self.pg2.local_ip4) vx_tun_l2_1.add_vpp_config() # @@ -1580,6 +1583,9 @@ class TestGBP(VppTestCase): # epg is not learnt, becasue the EPG is unknwon self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1) + # + # Learn new EPs from IP packets + # for ii, l in enumerate(learnt): # a packet with an sclass from a knwon EPG # arriving on an unknown TEP @@ -1617,7 +1623,7 @@ class TestGBP(VppTestCase): self.logger.info(self.vapi.cli("show gbp endpoint")) self.logger.info(self.vapi.cli("show gbp vxlan")) - self.logger.info(self.vapi.cli("show vxlan-gbp tunnel")) + self.logger.info(self.vapi.cli("show ip mfib")) # # If we sleep for the threshold time, the learnt endpoints should @@ -1627,6 +1633,95 @@ class TestGBP(VppTestCase): self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index, mac=l['mac']) + # + # Learn new EPs from GARP packets received on the BD's mcast tunnel + # + for ii, l in enumerate(learnt): + # a packet with an sclass from a knwon EPG + # arriving on an unknown TEP + p = (Ether(src=self.pg2.remote_mac, + dst=self.pg2.local_mac) / + IP(src=self.pg2.remote_hosts[1].ip4, + dst="239.1.1.1") / + UDP(sport=1234, dport=48879) / + VXLAN(vni=88, gpid=112, flags=0x88) / + Ether(src=l['mac'], dst="ff:ff:ff:ff:ff:ff") / + ARP(op="who-has", + psrc=l['ip'], pdst=l['ip'], + hwsrc=l['mac'], hwdst="ff:ff:ff:ff:ff:ff")) + + rx = self.send_and_expect(self.pg4, [p], self.pg0) + + # the new TEP + tep1_sw_if_index = find_vxlan_gbp_tunnel( + self, + self.pg2.local_ip4, + self.pg2.remote_hosts[1].ip4, + 99) + self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index) + + # + # the EP is learnt via the learnt TEP + # both from its MAC and its IP + # + self.assertTrue(find_gbp_endpoint(self, + vx_tun_l2_1.sw_if_index, + mac=l['mac'])) + self.assertTrue(find_gbp_endpoint(self, + vx_tun_l2_1.sw_if_index, + ip=l['ip'])) + + # + # wait for the learnt endpoints to age out + # + for l in learnt: + self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index, + mac=l['mac']) + + # + # Learn new EPs from L2 packets + # + for ii, l in enumerate(learnt): + # a packet with an sclass from a knwon EPG + # arriving on an unknown TEP + p = (Ether(src=self.pg2.remote_mac, + dst=self.pg2.local_mac) / + IP(src=self.pg2.remote_hosts[1].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) / + Raw('\xa5' * 100)) + + rx = self.send_and_expect(self.pg2, [p], self.pg0) + + # the new TEP + tep1_sw_if_index = find_vxlan_gbp_tunnel( + self, + self.pg2.local_ip4, + self.pg2.remote_hosts[1].ip4, + 99) + self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index) + + # + # the EP is learnt via the learnt TEP + # both from its MAC and its IP + # + self.assertTrue(find_gbp_endpoint(self, + vx_tun_l2_1.sw_if_index, + mac=l['mac'])) + + self.logger.info(self.vapi.cli("show gbp endpoint")) + self.logger.info(self.vapi.cli("show gbp vxlan")) + self.logger.info(self.vapi.cli("show vxlan-gbp tunnel")) + + # + # wait for the learnt endpoints to age out + # + for l in learnt: + self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index, + mac=l['mac']) + # # repeat. the do not learn bit is set so the EPs are not learnt # @@ -1934,7 +2029,8 @@ class TestGBP(VppTestCase): # vx_tun_l2_1 = VppGbpVxlanTunnel( self, 99, bd1.bd_id, - VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2) + VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2, + self.pg2.local_ip4) vx_tun_l2_1.add_vpp_config() # @@ -2109,7 +2205,8 @@ class TestGBP(VppTestCase): # vx_tun_l3 = VppGbpVxlanTunnel( self, 101, rd1.rd_id, - VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3) + VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3, + self.pg2.local_ip4) vx_tun_l3.add_vpp_config() # @@ -2905,7 +3002,8 @@ class TestGBP(VppTestCase): # vx_tun_l3 = VppGbpVxlanTunnel( self, 444, rd1.rd_id, - VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3) + VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3, + self.pg2.local_ip4) vx_tun_l3.add_vpp_config() c4 = VppGbpContract( @@ -3114,7 +3212,8 @@ class TestGBP(VppTestCase): # vx_tun_l3 = VppGbpVxlanTunnel( self, 444, rd1.rd_id, - VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3) + VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3, + self.pg2.local_ip4) vx_tun_l3.add_vpp_config() # diff --git a/test/vpp_papi_provider.py b/test/vpp_papi_provider.py index 2188ed3c041..9955518b2ef 100644 --- a/test/vpp_papi_provider.py +++ b/test/vpp_papi_provider.py @@ -3715,14 +3715,15 @@ class VppPapiProvider(object): """ GBP contract Dump """ return self.api(self.papi.gbp_contract_dump, {}) - def gbp_vxlan_tunnel_add(self, vni, bd_rd_id, mode): + def gbp_vxlan_tunnel_add(self, vni, bd_rd_id, mode, src): """ GBP VXLAN tunnel add """ return self.api(self.papi.gbp_vxlan_tunnel_add, { 'tunnel': { 'vni': vni, 'mode': mode, - 'bd_rd_id': bd_rd_id + 'bd_rd_id': bd_rd_id, + 'src': src } }) -- 2.16.6