From c0a93143412b4be7bba087bf633855aeeaee7c56 Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Wed, 5 Sep 2018 15:42:26 -0700 Subject: [PATCH] GBP Endpoint Updates - common types on the API - endpoints keyed in various ways for DP lookup - conparison functions for VPP IP address types Change-Id: If7ec0bbc5cea71fd0983fe78987d147ec1bd7ec8 Signed-off-by: Neale Ranns --- extras/vom/vom/gbp_endpoint.cpp | 59 ++-- extras/vom/vom/gbp_endpoint.hpp | 9 +- extras/vom/vom/gbp_endpoint_cmds.cpp | 65 ++-- extras/vom/vom/gbp_endpoint_cmds.hpp | 19 +- extras/vom/vom/gbp_subnet.cpp | 4 +- extras/vom/vom/gbp_subnet_cmds.cpp | 7 +- extras/vom/vom/prefix.hpp | 5 +- src/plugins/gbp/gbp.api | 34 +- src/plugins/gbp/gbp_api.c | 117 +++---- src/plugins/gbp/gbp_classify.c | 4 +- src/plugins/gbp/gbp_endpoint.c | 602 ++++++++++++++++++++++++----------- src/plugins/gbp/gbp_endpoint.h | 108 ++++--- src/plugins/gbp/gbp_endpoint_group.c | 2 +- src/plugins/gbp/gbp_policy.c | 4 +- src/plugins/gbp/gbp_recirc.c | 5 +- src/plugins/gbp/gbp_recirc.h | 4 + src/vnet/ip/ip6_packet.h | 7 + test/test_abf.py | 3 +- test/test_bfd.py | 3 +- test/test_bier.py | 3 +- test/test_gbp.py | 490 ++++++++++++++-------------- test/test_gre.py | 3 +- test/test_ip6.py | 3 +- test/test_ip_mcast.py | 3 +- test/test_ipip.py | 3 +- test/test_map.py | 3 +- test/test_mpls.py | 3 +- test/test_mtu.py | 3 +- test/test_p2p_ethernet.py | 3 +- test/test_qos.py | 3 +- test/test_reassembly.py | 3 +- test/test_sixrd.py | 3 +- test/test_srmpls.py | 5 +- test/test_srv6_ad.py | 3 +- test/vpp_ip.py | 134 ++++++-- test/vpp_ip_route.py | 10 +- test/vpp_mac.py | 24 ++ test/vpp_papi_provider.py | 28 +- test/vpp_udp_encap.py | 6 +- 39 files changed, 1120 insertions(+), 677 deletions(-) create mode 100644 test/vpp_mac.py diff --git a/extras/vom/vom/gbp_endpoint.cpp b/extras/vom/vom/gbp_endpoint.cpp index 9762a91429a..236a961ae20 100644 --- a/extras/vom/vom/gbp_endpoint.cpp +++ b/extras/vom/vom/gbp_endpoint.cpp @@ -14,6 +14,7 @@ */ #include "vom/gbp_endpoint.hpp" +#include "vom/api_types.hpp" #include "vom/gbp_endpoint_cmds.hpp" #include "vom/singular_db_funcs.hpp" @@ -23,22 +24,23 @@ singular_db gbp_endpoint::m_db; gbp_endpoint::event_handler gbp_endpoint::m_evh; -gbp_endpoint::gbp_endpoint(const interface& itf, - const boost::asio::ip::address& ip_addr, - const mac_address_t& mac, - const gbp_endpoint_group& epg) - : m_hw(false) +gbp_endpoint::gbp_endpoint( + const interface& itf, + const std::vector& ip_addrs, + const mac_address_t& mac, + const gbp_endpoint_group& epg) + : m_hdl(handle_t::INVALID) , m_itf(itf.singular()) - , m_ip(ip_addr) + , m_ips(ip_addrs) , m_mac(mac) , m_epg(epg.singular()) { } gbp_endpoint::gbp_endpoint(const gbp_endpoint& gbpe) - : m_hw(gbpe.m_hw) + : m_hdl(gbpe.m_hdl) , m_itf(gbpe.m_itf) - , m_ip(gbpe.m_ip) + , m_ips(gbpe.m_ips) , m_mac(gbpe.m_mac) , m_epg(gbpe.m_epg) { @@ -53,7 +55,7 @@ gbp_endpoint::~gbp_endpoint() const gbp_endpoint::key_t gbp_endpoint::key() const { - return (std::make_pair(m_itf->key(), m_ip)); + return (std::make_pair(m_itf->key(), m_mac)); } bool @@ -65,8 +67,8 @@ gbp_endpoint::operator==(const gbp_endpoint& gbpe) const void gbp_endpoint::sweep() { - if (m_hw) { - HW::enqueue(new gbp_endpoint_cmds::delete_cmd(m_hw, m_itf->handle(), m_ip)); + if (m_hdl) { + HW::enqueue(new gbp_endpoint_cmds::delete_cmd(m_hdl)); } HW::write(); } @@ -74,8 +76,8 @@ gbp_endpoint::sweep() void gbp_endpoint::replay() { - if (m_hw) { - HW::enqueue(new gbp_endpoint_cmds::create_cmd(m_hw, m_itf->handle(), m_ip, + if (m_hdl) { + HW::enqueue(new gbp_endpoint_cmds::create_cmd(m_hdl, m_itf->handle(), m_ips, m_mac, m_epg->id())); } } @@ -84,8 +86,12 @@ std::string gbp_endpoint::to_string() const { std::ostringstream s; - s << "gbp-endpoint:[" << m_itf->to_string() << ", " << m_ip.to_string() - << ", " << m_mac.to_string() << ", epg:" << m_epg->to_string() << "]"; + s << "gbp-endpoint:[" << m_itf->to_string() << ", ips:["; + + for (auto ip : m_ips) + s << ip.to_string(); + + s << "], " << m_mac.to_string() << ", epg:" << m_epg->to_string() << "]"; return (s.str()); } @@ -93,8 +99,8 @@ gbp_endpoint::to_string() const void gbp_endpoint::update(const gbp_endpoint& r) { - if (rc_t::OK != m_hw.rc()) { - HW::enqueue(new gbp_endpoint_cmds::create_cmd(m_hw, m_itf->handle(), m_ip, + if (rc_t::OK != m_hdl.rc()) { + HW::enqueue(new gbp_endpoint_cmds::create_cmd(m_hdl, m_itf->handle(), m_ips, m_mac, m_epg->id())); } } @@ -147,18 +153,20 @@ gbp_endpoint::event_handler::handle_populate(const client_db::key_t& key) for (auto& record : *cmd) { auto& payload = record.get_payload(); - boost::asio::ip::address address = - from_bytes(payload.endpoint.is_ip6, payload.endpoint.address); + std::vector addresses; + + for (uint8_t n = 0; n < payload.endpoint.n_ips; n++) + addresses.push_back(from_api(payload.endpoint.ips[n])); std::shared_ptr itf = interface::find(payload.endpoint.sw_if_index); std::shared_ptr epg = gbp_endpoint_group::find(payload.endpoint.epg_id); - mac_address_t mac(payload.endpoint.mac); + mac_address_t mac = from_api(payload.endpoint.mac); VOM_LOG(log_level_t::DEBUG) << "data: " << payload.endpoint.sw_if_index; if (itf && epg) { - gbp_endpoint gbpe(*itf, address, mac, *epg); + gbp_endpoint gbpe(*itf, addresses, mac, *epg); OM::commit(key, gbpe); VOM_LOG(log_level_t::DEBUG) << "read: " << gbpe.to_string(); @@ -177,6 +185,15 @@ gbp_endpoint::event_handler::show(std::ostream& os) { db_dump(m_db, os); } + +std::ostream& +operator<<(std::ostream& os, const gbp_endpoint::key_t& key) +{ + os << key.first << "," << key.second; + + return os; +} + } // namespace VOM /* diff --git a/extras/vom/vom/gbp_endpoint.hpp b/extras/vom/vom/gbp_endpoint.hpp index f6466a6077d..d27ad90a4df 100644 --- a/extras/vom/vom/gbp_endpoint.hpp +++ b/extras/vom/vom/gbp_endpoint.hpp @@ -17,6 +17,7 @@ #define __VOM_GBP_ENDPOINT_H__ #include +#include #include "vom/gbp_endpoint_group.hpp" #include "vom/interface.hpp" @@ -32,13 +33,13 @@ public: /** * The key for a GBP endpoint; interface and IP */ - typedef std::pair key_t; + typedef std::pair key_t; /** * Construct a GBP endpoint */ gbp_endpoint(const interface& itf, - const boost::asio::ip::address& ip_addr, + const std::vector& ip_addr, const mac_address_t& mac, const gbp_endpoint_group& epg); @@ -151,7 +152,7 @@ private: /** * HW configuration for the result of creating the endpoint */ - HW::item m_hw; + HW::item m_hdl; /** * The interface the endpoint is attached to. @@ -161,7 +162,7 @@ private: /** * The IP address of the endpoint */ - boost::asio::ip::address m_ip; + std::vector m_ips; /** * The MAC address of the endpoint diff --git a/extras/vom/vom/gbp_endpoint_cmds.cpp b/extras/vom/vom/gbp_endpoint_cmds.cpp index 1f9078f9b7f..8d44c91ec61 100644 --- a/extras/vom/vom/gbp_endpoint_cmds.cpp +++ b/extras/vom/vom/gbp_endpoint_cmds.cpp @@ -14,20 +14,21 @@ */ #include "vom/gbp_endpoint_cmds.hpp" +#include "vom/api_types.hpp" DEFINE_VAPI_MSG_IDS_GBP_API_JSON; namespace VOM { namespace gbp_endpoint_cmds { -create_cmd::create_cmd(HW::item& item, +create_cmd::create_cmd(HW::item& item, const handle_t& itf, - const boost::asio::ip::address& ip_addr, + const std::vector& ip_addrs, const mac_address_t& mac, epg_id_t epg_id) : rpc_cmd(item) , m_itf(itf) - , m_ip_addr(ip_addr) + , m_ip_addrs(ip_addrs) , m_mac(mac) , m_epg_id(epg_id) { @@ -36,50 +37,76 @@ create_cmd::create_cmd(HW::item& item, bool create_cmd::operator==(const create_cmd& other) const { - return ((m_itf == other.m_itf) && (m_ip_addr == other.m_ip_addr) && + return ((m_itf == other.m_itf) && (m_ip_addrs == other.m_ip_addrs) && (m_mac == other.m_mac) && (m_epg_id == other.m_epg_id)); } rc_t create_cmd::issue(connection& con) { - msg_t req(con.ctx(), std::ref(*this)); + msg_t req(con.ctx(), m_ip_addrs.size() * sizeof(vapi_type_address), + std::ref(*this)); + uint8_t n; auto& payload = req.get_request().get_payload(); - payload.is_add = 1; payload.endpoint.sw_if_index = m_itf.value(); payload.endpoint.epg_id = m_epg_id; - to_bytes(m_ip_addr, &payload.endpoint.is_ip6, payload.endpoint.address); - m_mac.to_bytes(payload.endpoint.mac, 6); + payload.endpoint.n_ips = m_ip_addrs.size(); + + for (n = 0; n < payload.endpoint.n_ips; n++) { + payload.endpoint.ips[n] = to_api(m_ip_addrs[n]); + } + payload.endpoint.mac = to_api(m_mac); VAPI_CALL(req.execute()); return (wait()); } +vapi_error_e +create_cmd::operator()(vapi::Gbp_endpoint_add& reply) +{ + int handle = reply.get_response().get_payload().handle; + int retval = reply.get_response().get_payload().retval; + + VOM_LOG(log_level_t::DEBUG) << this->to_string() << " " << retval; + + rc_t rc = rc_t::from_vpp_retval(retval); + handle_t hdl = handle_t::INVALID; + + if (rc_t::OK == rc) { + hdl = handle; + } + + this->fulfill(HW::item(hdl, rc)); + + return (VAPI_OK); +} + std::string create_cmd::to_string() const { std::ostringstream s; s << "gbp-endpoint-create: " << m_hw_item.to_string() << " itf:" << m_itf - << " ip:" << m_ip_addr.to_string() << " epg-id:" << m_epg_id; + << " ips:["; + for (auto ip : m_ip_addrs) + s << ip.to_string(); + + s << "] mac:" << m_mac; + s << " epg-id:" << m_epg_id; return (s.str()); } -delete_cmd::delete_cmd(HW::item& item, - const handle_t& itf, - const boost::asio::ip::address& ip_addr) +delete_cmd::delete_cmd(HW::item& item) : rpc_cmd(item) - , m_itf(itf) - , m_ip_addr(ip_addr) { } bool delete_cmd::operator==(const delete_cmd& other) const { - return ((m_itf == other.m_itf) && (m_ip_addr == other.m_ip_addr)); + return (m_hw_item == other.m_hw_item); } rc_t @@ -88,10 +115,7 @@ delete_cmd::issue(connection& con) msg_t req(con.ctx(), std::ref(*this)); auto& payload = req.get_request().get_payload(); - payload.is_add = 0; - payload.endpoint.sw_if_index = m_itf.value(); - payload.endpoint.epg_id = ~0; - to_bytes(m_ip_addr, &payload.endpoint.is_ip6, payload.endpoint.address); + payload.handle = m_hw_item.data().value(); VAPI_CALL(req.execute()); @@ -102,8 +126,7 @@ std::string delete_cmd::to_string() const { std::ostringstream s; - s << "gbp-endpoint-delete: " << m_hw_item.to_string() << " itf:" << m_itf - << " ip:" << m_ip_addr.to_string(); + s << "gbp-endpoint-delete: " << m_hw_item.to_string(); return (s.str()); } diff --git a/extras/vom/vom/gbp_endpoint_cmds.hpp b/extras/vom/vom/gbp_endpoint_cmds.hpp index dea4c2c5605..e90fb66f04a 100644 --- a/extras/vom/vom/gbp_endpoint_cmds.hpp +++ b/extras/vom/vom/gbp_endpoint_cmds.hpp @@ -27,15 +27,15 @@ namespace gbp_endpoint_cmds { /** * A command class that creates or updates the GBP endpoint */ -class create_cmd : public rpc_cmd, vapi::Gbp_endpoint_add_del> +class create_cmd : public rpc_cmd, vapi::Gbp_endpoint_add> { public: /** * Constructor */ - create_cmd(HW::item& item, + create_cmd(HW::item& item, const handle_t& itf, - const boost::asio::ip::address& ip_addr, + const std::vector& ip_addrs, const mac_address_t& mac, epg_id_t epg_id); @@ -49,6 +49,8 @@ public: */ std::string to_string() const; + virtual vapi_error_e operator()(vapi::Gbp_endpoint_add& reply); + /** * Comparison operator - only used for UT */ @@ -56,7 +58,7 @@ public: private: const handle_t m_itf; - const boost::asio::ip::address m_ip_addr; + const std::vector m_ip_addrs; const mac_address_t m_mac; const epg_id_t m_epg_id; }; @@ -64,15 +66,13 @@ private: /** * A cmd class that deletes a GBP endpoint */ -class delete_cmd : public rpc_cmd, vapi::Gbp_endpoint_add_del> +class delete_cmd : public rpc_cmd, vapi::Gbp_endpoint_del> { public: /** * Constructor */ - delete_cmd(HW::item& item, - const handle_t& itf, - const boost::asio::ip::address& ip_addr); + delete_cmd(HW::item& item); /** * Issue the command to VPP/HW @@ -90,8 +90,7 @@ public: bool operator==(const delete_cmd& i) const; private: - const handle_t m_itf; - const boost::asio::ip::address m_ip_addr; + const handle_t m_hdl; }; /** diff --git a/extras/vom/vom/gbp_subnet.cpp b/extras/vom/vom/gbp_subnet.cpp index 1a9ee86e06b..1bc024da854 100644 --- a/extras/vom/vom/gbp_subnet.cpp +++ b/extras/vom/vom/gbp_subnet.cpp @@ -14,6 +14,7 @@ */ #include "vom/gbp_subnet.hpp" +#include "vom/api_types.hpp" #include "vom/gbp_subnet_cmds.hpp" #include "vom/singular_db_funcs.hpp" @@ -190,8 +191,7 @@ gbp_subnet::event_handler::handle_populate(const client_db::key_t& key) for (auto& record : *cmd) { auto& payload = record.get_payload(); - route::prefix_t pfx(payload.subnet.is_ip6, payload.subnet.address, - payload.subnet.address_length); + route::prefix_t pfx = from_api(payload.subnet.prefix); std::shared_ptr rd = route_domain::find(payload.subnet.table_id); diff --git a/extras/vom/vom/gbp_subnet_cmds.cpp b/extras/vom/vom/gbp_subnet_cmds.cpp index 3816a596e6d..79fdf175ee1 100644 --- a/extras/vom/vom/gbp_subnet_cmds.cpp +++ b/extras/vom/vom/gbp_subnet_cmds.cpp @@ -14,6 +14,7 @@ */ #include "vom/gbp_subnet_cmds.hpp" +#include "vom/api_types.hpp" namespace VOM { namespace gbp_subnet_cmds { @@ -52,8 +53,7 @@ create_cmd::issue(connection& con) payload.subnet.table_id = m_rd; payload.subnet.sw_if_index = m_itf.value(); payload.subnet.epg_id = m_epg_id; - m_prefix.to_vpp(&payload.subnet.is_ip6, payload.subnet.address, - &payload.subnet.address_length); + payload.subnet.prefix = to_api(m_prefix); VAPI_CALL(req.execute()); @@ -94,8 +94,7 @@ delete_cmd::issue(connection& con) auto& payload = req.get_request().get_payload(); payload.is_add = 0; payload.subnet.table_id = m_rd; - m_prefix.to_vpp(&payload.subnet.is_ip6, payload.subnet.address, - &payload.subnet.address_length); + payload.subnet.prefix = to_api(m_prefix); payload.subnet.is_internal = 0; payload.subnet.sw_if_index = ~0; diff --git a/extras/vom/vom/prefix.hpp b/extras/vom/vom/prefix.hpp index 3950f6fd036..836554123f5 100644 --- a/extras/vom/vom/prefix.hpp +++ b/extras/vom/vom/prefix.hpp @@ -16,9 +16,8 @@ #ifndef __VOM_PREFIX_H__ #define __VOM_PREFIX_H__ -#include - #include "vom/enum_base.hpp" +#include namespace VOM { /** @@ -111,10 +110,12 @@ public: * Constructor with string and length */ prefix_t(const std::string& s, uint8_t len); + /** * Copy Constructor */ prefix_t(const prefix_t&); + /** * Constructor with VPP API prefix representation */ diff --git a/src/plugins/gbp/gbp.api b/src/plugins/gbp/gbp.api index 3e27abbb88a..d7c6d83c3b7 100644 --- a/src/plugins/gbp/gbp.api +++ b/src/plugins/gbp/gbp.api @@ -14,30 +14,46 @@ * limitations under the License. */ -option version = "1.0.0"; +option version = "2.0.0"; + +import "vnet/ip/ip_types.api"; +import "vnet/ethernet/ethernet_types.api"; /** \brief Endpoint @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request */ -typeonly define gbp_endpoint +typedef gbp_endpoint { u32 sw_if_index; u16 epg_id; - u8 is_ip6; - u8 address[16]; - u8 mac[6]; + vl_api_mac_address_t mac; + u8 n_ips; + vl_api_address_t ips[n_ips]; }; -autoreply define gbp_endpoint_add_del +define gbp_endpoint_add { u32 client_index; u32 context; - u8 is_add; vl_api_gbp_endpoint_t endpoint; }; +define gbp_endpoint_add_reply +{ + u32 context; + i32 retval; + u32 handle; +}; + +autoreply define gbp_endpoint_del +{ + u32 client_index; + u32 context; + u32 handle; +}; + define gbp_endpoint_dump { u32 client_index; @@ -111,10 +127,8 @@ typeonly define gbp_subnet u32 table_id; u32 sw_if_index; u16 epg_id; - u8 is_ip6; u8 is_internal; - u8 address_length; - u8 address[16]; + vl_api_prefix_t prefix; }; autoreply define gbp_subnet_add_del diff --git a/src/plugins/gbp/gbp_api.c b/src/plugins/gbp/gbp_api.c index f487695bdf3..a541d96e0f6 100644 --- a/src/plugins/gbp/gbp_api.c +++ b/src/plugins/gbp/gbp_api.c @@ -20,6 +20,8 @@ #include #include +#include +#include #include #include @@ -52,7 +54,8 @@ #include #define foreach_gbp_api_msg \ - _(GBP_ENDPOINT_ADD_DEL, gbp_endpoint_add_del) \ + _(GBP_ENDPOINT_ADD, gbp_endpoint_add) \ + _(GBP_ENDPOINT_DEL, gbp_endpoint_del) \ _(GBP_ENDPOINT_DUMP, gbp_endpoint_dump) \ _(GBP_SUBNET_ADD_DEL, gbp_subnet_add_del) \ _(GBP_SUBNET_DUMP, gbp_subnet_dump) \ @@ -70,39 +73,55 @@ static u16 msg_id_base; #define GBP_MSG_BASE msg_id_base static void -vl_api_gbp_endpoint_add_del_t_handler (vl_api_gbp_endpoint_add_del_t * mp) +vl_api_gbp_endpoint_add_t_handler (vl_api_gbp_endpoint_add_t * mp) { - vl_api_gbp_endpoint_add_del_reply_t *rmp; - ip46_address_t ip = { }; - u32 sw_if_index; - int rv = 0; + vl_api_gbp_endpoint_add_reply_t *rmp; + u32 sw_if_index, handle; + ip46_address_t *ips; + mac_address_t mac; + int rv = 0, ii; + + VALIDATE_SW_IF_INDEX (&(mp->endpoint)); sw_if_index = ntohl (mp->endpoint.sw_if_index); - if (!vnet_sw_if_index_is_api_valid (sw_if_index)) - goto bad_sw_if_index; - if (mp->endpoint.is_ip6) - { - clib_memcpy (&ip.ip6, mp->endpoint.address, sizeof (ip.ip6)); - } - else - { - clib_memcpy (&ip.ip4, mp->endpoint.address, sizeof (ip.ip4)); - } + ips = NULL; - if (mp->is_add) - { - rv = - gbp_endpoint_update (sw_if_index, &ip, ntohs (mp->endpoint.epg_id)); - } - else + if (mp->endpoint.n_ips) { - gbp_endpoint_delete (sw_if_index, &ip); + vec_validate (ips, mp->endpoint.n_ips - 1); + + vec_foreach_index (ii, ips) + { + ip_address_decode (&mp->endpoint.ips[ii], &ips[ii]); + } } + mac_address_decode (&mp->endpoint.mac, &mac); + + rv = gbp_endpoint_update (sw_if_index, ips, &mac, + ntohs (mp->endpoint.epg_id), &handle); + + vec_free (ips); BAD_SW_IF_INDEX_LABEL; - REPLY_MACRO (VL_API_GBP_ENDPOINT_ADD_DEL_REPLY + GBP_MSG_BASE); + /* *INDENT-OFF* */ + REPLY_MACRO2 (VL_API_GBP_ENDPOINT_ADD_REPLY + GBP_MSG_BASE, + ({ + rmp->handle = htonl (handle); + })); + /* *INDENT-ON* */ +} + +static void +vl_api_gbp_endpoint_del_t_handler (vl_api_gbp_endpoint_del_t * mp) +{ + vl_api_gbp_endpoint_del_reply_t *rmp; + int rv = 0; + + gbp_endpoint_delete (ntohl (mp->handle)); + + REPLY_MACRO (VL_API_GBP_ENDPOINT_DEL_REPLY + GBP_MSG_BASE); } typedef struct gbp_walk_ctx_t_ @@ -111,14 +130,16 @@ typedef struct gbp_walk_ctx_t_ u32 context; } gbp_walk_ctx_t; -static int +static walk_rc_t gbp_endpoint_send_details (gbp_endpoint_t * gbpe, void *args) { vl_api_gbp_endpoint_details_t *mp; gbp_walk_ctx_t *ctx; + u8 n_ips, ii; ctx = args; - mp = vl_msg_api_alloc (sizeof (*mp)); + n_ips = vec_len (gbpe->ge_ips); + mp = vl_msg_api_alloc (sizeof (*mp) + (sizeof (*mp->endpoint.ips) * n_ips)); if (!mp) return 1; @@ -126,22 +147,20 @@ gbp_endpoint_send_details (gbp_endpoint_t * gbpe, void *args) mp->_vl_msg_id = ntohs (VL_API_GBP_ENDPOINT_DETAILS + GBP_MSG_BASE); mp->context = ctx->context; - mp->endpoint.sw_if_index = ntohl (gbpe->ge_key->gek_sw_if_index); - mp->endpoint.is_ip6 = !ip46_address_is_ip4 (&gbpe->ge_key->gek_ip); - if (mp->endpoint.is_ip6) - clib_memcpy (&mp->endpoint.address, - &gbpe->ge_key->gek_ip.ip6, - sizeof (gbpe->ge_key->gek_ip.ip6)); - else - clib_memcpy (&mp->endpoint.address, - &gbpe->ge_key->gek_ip.ip4, - sizeof (gbpe->ge_key->gek_ip.ip4)); - + mp->endpoint.sw_if_index = ntohl (gbpe->ge_sw_if_index); mp->endpoint.epg_id = ntohs (gbpe->ge_epg_id); + mp->endpoint.n_ips = n_ips; + mac_address_encode (&gbpe->ge_mac, &mp->endpoint.mac); + + vec_foreach_index (ii, gbpe->ge_ips) + { + ip_address_encode (&gbpe->ge_ips[ii], IP46_TYPE_ANY, + &mp->endpoint.ips[ii]); + } vl_api_send_msg (ctx->reg, (u8 *) mp); - return (1); + return (WALK_CONTINUE); } static void @@ -195,18 +214,10 @@ static void vl_api_gbp_subnet_add_del_t_handler (vl_api_gbp_subnet_add_del_t * mp) { vl_api_gbp_subnet_add_del_reply_t *rmp; + fib_prefix_t pfx; int rv = 0; - fib_prefix_t pfx = { - .fp_len = mp->subnet.address_length, - .fp_proto = (mp->subnet.is_ip6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4), - }; - if (mp->subnet.is_ip6) - clib_memcpy (&pfx.fp_addr.ip6, mp->subnet.address, - sizeof (pfx.fp_addr.ip6)); - else - clib_memcpy (&pfx.fp_addr.ip4, mp->subnet.address, - sizeof (pfx.fp_addr.ip4)); + ip_prefix_decode (&mp->subnet.prefix, &pfx); rv = gbp_subnet_add_del (ntohl (mp->subnet.table_id), &pfx, @@ -238,16 +249,8 @@ gbp_subnet_send_details (u32 table_id, mp->subnet.is_internal = is_internal; mp->subnet.sw_if_index = ntohl (sw_if_index); mp->subnet.epg_id = ntohs (epg); - mp->subnet.is_ip6 = (pfx->fp_proto == FIB_PROTOCOL_IP6); - mp->subnet.address_length = pfx->fp_len; mp->subnet.table_id = ntohl (table_id); - if (mp->subnet.is_ip6) - clib_memcpy (&mp->subnet.address, - &pfx->fp_addr.ip6, sizeof (pfx->fp_addr.ip6)); - else - clib_memcpy (&mp->subnet.address, - &pfx->fp_addr.ip4, sizeof (pfx->fp_addr.ip4)); - + ip_prefix_encode (pfx, &mp->subnet.prefix); vl_api_send_msg (ctx->reg, (u8 *) mp); diff --git a/src/plugins/gbp/gbp_classify.c b/src/plugins/gbp/gbp_classify.c index fdb1e9f6776..53389f5a0e3 100644 --- a/src/plugins/gbp/gbp_classify.c +++ b/src/plugins/gbp/gbp_classify.c @@ -75,6 +75,7 @@ gbp_classify_inline (vlib_main_t * vm, while (n_left_from > 0 && n_left_to_next > 0) { u32 next0, bi0, src_epg, sw_if_index0; + const gbp_endpoint_t *gep0; vlib_buffer_t *b0; bi0 = from[0]; @@ -97,7 +98,8 @@ gbp_classify_inline (vlib_main_t * vm, } else { - src_epg = gbp_port_to_epg (sw_if_index0); + gep0 = gbp_endpoint_get_itf (sw_if_index0); + src_epg = gep0->ge_epg_id; if (is_l3) { /* diff --git a/src/plugins/gbp/gbp_endpoint.c b/src/plugins/gbp/gbp_endpoint.c index 0522f613f7d..a261527a177 100644 --- a/src/plugins/gbp/gbp_endpoint.c +++ b/src/plugins/gbp/gbp_endpoint.c @@ -23,200 +23,340 @@ #include #include -/** - * IP4 destintion address to destination EPG mapping table - */ -typedef struct gbp_ip4_to_epg_db_t_ -{ - /** - * use a simple hash table - */ - uword *g4ie_hash; -} gbp_ip4_to_epg_db_t; - -static gbp_ip4_to_epg_db_t gbp_ip4_to_epg_db; +gbp_ep_by_itf_db_t gbp_ep_by_itf_db; +gbp_ep_by_mac_itf_db_t gbp_ep_by_mac_itf_db; +gbp_ep_by_ip_itf_db_t gbp_ep_by_ip_itf_db; /** - * IP6 destintion address to destination EPG mapping table + * Pool of GBP endpoints */ -typedef struct gbp_ip6_to_epg_db_t_ +gbp_endpoint_t *gbp_endpoint_pool; + +/* void */ +/* gbp_itf_epg_update (u32 sw_if_index, epg_id_t src_epg, u8 do_policy) */ +/* { */ +/* vec_validate_init_empty (gbp_itf_to_epg_db.gte_vec, */ +/* sw_if_index, ITF_INVALID); */ + +/* if (0 == gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_ref_count) */ +/* { */ +/* l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_GBP_SRC_CLASSIFY, */ +/* 1); */ +/* l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_GBP_FWD, 1); */ +/* if (do_policy) */ +/* l2output_intf_bitmap_enable (sw_if_index, L2OUTPUT_FEAT_GBP_POLICY, */ +/* 1); */ +/* } */ +/* gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_epg = src_epg; */ +/* gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_ref_count++; */ +/* } */ + +/* void */ +/* gbp_itf_epg_delete (u32 sw_if_index) */ +/* { */ +/* if (vec_len (gbp_itf_to_epg_db.gte_vec) <= sw_if_index) */ +/* return; */ + +/* if (1 == gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_ref_count) */ +/* { */ +/* gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_epg = EPG_INVALID; */ + +/* l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_GBP_SRC_CLASSIFY, */ +/* 0); */ +/* l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_GBP_FWD, 0); */ +/* l2output_intf_bitmap_enable (sw_if_index, L2OUTPUT_FEAT_GBP_POLICY, 0); */ +/* } */ +/* gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_ref_count--; */ +/* } */ + +static void +gbp_endpoint_mk_key_mac_itf (const mac_address_t * mac, + u32 sw_if_index, clib_bihash_kv_16_8_t * key) { - /** - * use a memroy hash table - */ - uword *g6ie_hash; -} gbp_ip6_to_epg_db_t; + key->key[0] = mac_address_as_u64 (mac); + key->key[1] = sw_if_index; +} -static gbp_ip6_to_epg_db_t gbp_ip6_to_epg_db; +static void +gbp_endpoint_extract_key_mac_itf (const clib_bihash_kv_16_8_t * key, + mac_address_t * mac, u32 * sw_if_index) +{ + mac_address_from_u64 (key->key[0], mac); + *sw_if_index = key->key[1]; +} +gbp_endpoint_t * +gbp_endpoint_find_mac_itf (const mac_address_t * mac, u32 sw_if_index) +{ + clib_bihash_kv_16_8_t key, value; + int rv; -const static gbp_itf_t ITF_INVALID = { - .gi_epg = EPG_INVALID, - .gi_ref_count = 0, -}; + gbp_endpoint_mk_key_mac_itf (mac, sw_if_index, &key); -gbp_itf_to_epg_db_t gbp_itf_to_epg_db; + rv = + clib_bihash_search_16_8 (&gbp_ep_by_mac_itf_db.gte_table, &key, &value); -/** - * Pool of GBP endpoints - */ -static gbp_endpoint_t *gbp_endpoint_pool; + if (0 != rv) + return NULL; -/** - * DB of endpoints - */ -static uword *gbp_endpoint_db; + return (gbp_endpoint_get (value.value)); +} static void -gbp_ip_epg_update (const ip46_address_t * ip, epg_id_t epg_id) +gbp_endpoint_mk_key_ip_itf (const ip46_address_t * ip, + u32 sw_if_index, clib_bihash_kv_24_8_t * key) { - /* - * we are dealing only with addresses here so this limited - * is_ip4 check is ok - */ - if (ip46_address_is_ip4 (ip)) - { - hash_set (gbp_ip4_to_epg_db.g4ie_hash, ip->ip4.as_u32, epg_id); - } - else - { - hash_set_mem (gbp_ip6_to_epg_db.g6ie_hash, &ip->ip6, epg_id); - } + key->key[0] = ip->as_u64[0]; + key->key[1] = ip->as_u64[1]; + key->key[2] = sw_if_index; } static void -gbp_ip_epg_delete (const ip46_address_t * ip) +gbp_endpoint_extract_key_ip_itf (const clib_bihash_kv_24_8_t * key, + ip46_address_t * ip, u32 * sw_if_index) { - if (ip46_address_is_ip4 (ip)) - { - hash_unset (gbp_ip4_to_epg_db.g4ie_hash, ip->ip4.as_u32); - } - else - { - hash_unset_mem (gbp_ip6_to_epg_db.g6ie_hash, &ip->ip6); - } + ip->as_u64[0] = key->key[0]; + ip->as_u64[1] = key->key[1]; + *sw_if_index = key->key[2]; } -void -gbp_itf_epg_update (u32 sw_if_index, epg_id_t src_epg, u8 do_policy) +gbp_endpoint_t * +gbp_endpoint_find_ip_itf (const ip46_address_t * ip, u32 sw_if_index) { - vec_validate_init_empty (gbp_itf_to_epg_db.gte_vec, - sw_if_index, ITF_INVALID); + clib_bihash_kv_24_8_t key, value; + int rv; + + gbp_endpoint_mk_key_ip_itf (ip, sw_if_index, &key); + + rv = clib_bihash_search_24_8 (&gbp_ep_by_ip_itf_db.gte_table, &key, &value); + + if (0 != rv) + return NULL; + + return (gbp_endpoint_get (value.value)); +} + +gbp_endpoint_t * +gbp_endpoint_find_itf (u32 sw_if_index) +{ + /* if (vec_len(gbp_ep_by_itf_db.gte_vec) >= sw_if_index) */ + /* return NULL; */ + + /* vec_search(gbp_ep_by_itf_db.gte_vec[sw_if_index], */ + /* return (gbp_endpoint_get(gbp_ep_by_itf_db.gte_vec[sw_if_index][0])); */ + return (NULL); +} + +static bool +gbp_endpoint_add_mac_itf (const mac_address_t * mac, + u32 sw_if_index, index_t gbpei) +{ + clib_bihash_kv_16_8_t key; + int rv; + + gbp_endpoint_mk_key_mac_itf (mac, sw_if_index, &key); + key.value = gbpei; - if (0 == gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_ref_count) + rv = clib_bihash_add_del_16_8 (&gbp_ep_by_mac_itf_db.gte_table, &key, 1); + + return (0 == rv); +} + +static bool +gbp_endpoint_add_ip_itf (const ip46_address_t * ip, + u32 sw_if_index, index_t gbpei) +{ + clib_bihash_kv_24_8_t key; + int rv; + + gbp_endpoint_mk_key_ip_itf (ip, sw_if_index, &key); + key.value = gbpei; + + rv = clib_bihash_add_del_24_8 (&gbp_ep_by_ip_itf_db.gte_table, &key, 1); + + return (0 == rv); +} + +static void +gbp_endpoint_add_itf (u32 sw_if_index, index_t gbpei) +{ + vec_validate_init_empty (gbp_ep_by_itf_db.gte_vec, sw_if_index, + INDEX_INVALID); + + if (INDEX_INVALID == gbp_ep_by_itf_db.gte_vec[sw_if_index]) { l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_GBP_SRC_CLASSIFY, 1); l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_GBP_FWD, 1); - if (do_policy) - l2output_intf_bitmap_enable (sw_if_index, L2OUTPUT_FEAT_GBP_POLICY, - 1); + l2output_intf_bitmap_enable (sw_if_index, L2OUTPUT_FEAT_GBP_POLICY, 1); } - gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_epg = src_epg; - gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_ref_count++; + gbp_ep_by_itf_db.gte_vec[sw_if_index] = gbpei; } -void -gbp_itf_epg_delete (u32 sw_if_index) +static void +gbp_endpoint_del_mac_itf (const mac_address_t * mac, u32 sw_if_index) +{ + clib_bihash_kv_16_8_t key; + + gbp_endpoint_mk_key_mac_itf (mac, sw_if_index, &key); + + clib_bihash_add_del_16_8 (&gbp_ep_by_mac_itf_db.gte_table, &key, 0); +} + +static void +gbp_endpoint_del_ip_itf (const ip46_address_t * ip, u32 sw_if_index) +{ + clib_bihash_kv_24_8_t key; + + gbp_endpoint_mk_key_ip_itf (ip, sw_if_index, &key); + + clib_bihash_add_del_24_8 (&gbp_ep_by_ip_itf_db.gte_table, &key, 0); +} + +static void +gbp_endpoint_del_itf (u32 sw_if_index) { - if (vec_len (gbp_itf_to_epg_db.gte_vec) <= sw_if_index) + if (vec_len (gbp_ep_by_itf_db.gte_vec) <= sw_if_index) return; - if (1 == gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_ref_count) - { - gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_epg = EPG_INVALID; + l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_GBP_SRC_CLASSIFY, 0); + l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_GBP_FWD, 0); + l2output_intf_bitmap_enable (sw_if_index, L2OUTPUT_FEAT_GBP_POLICY, 0); - l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_GBP_SRC_CLASSIFY, - 0); - l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_GBP_FWD, 0); - l2output_intf_bitmap_enable (sw_if_index, L2OUTPUT_FEAT_GBP_POLICY, 0); - } - gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_ref_count--; + gbp_ep_by_itf_db.gte_vec[sw_if_index] = INDEX_INVALID; +} + +static index_t +gbp_endpoint_index (const gbp_endpoint_t * gbpe) +{ + return (gbpe - gbp_endpoint_pool); } int gbp_endpoint_update (u32 sw_if_index, - const ip46_address_t * ip, epg_id_t epg_id) + const ip46_address_t * ips, + const mac_address_t * mac, epg_id_t epg_id, u32 * handle) { - gbp_endpoint_key_t key = { - .gek_ip = *ip, - .gek_sw_if_index = sw_if_index, - }; gbp_endpoint_group_t *gepg; + const ip46_address_t *ip; gbp_endpoint_t *gbpe; - uword *p; + gbpe = NULL; gepg = gbp_endpoint_group_find (epg_id); if (NULL == gepg) return (VNET_API_ERROR_NO_SUCH_ENTRY); - p = hash_get_mem (gbp_endpoint_db, &key); - - if (p) + /* + * find an existing endpoint matching one of the key types + */ + if (NULL != mac) { - gbpe = pool_elt_at_index (gbp_endpoint_pool, p[0]); + gbpe = gbp_endpoint_find_mac_itf (mac, sw_if_index); } - else + if (NULL == gbpe && NULL != ips) { - pool_get (gbp_endpoint_pool, gbpe); - - gbpe->ge_key = clib_mem_alloc (sizeof (gbp_endpoint_key_t)); - clib_memcpy (gbpe->ge_key, &key, sizeof (gbp_endpoint_key_t)); + vec_foreach (ip, ips) + { + gbpe = gbp_endpoint_find_ip_itf (ip, sw_if_index); - hash_set_mem (gbp_endpoint_db, gbpe->ge_key, gbpe - gbp_endpoint_pool); + if (NULL != gbpe) + break; + } + } + if (NULL == gbpe) + { + gbpe = gbp_endpoint_find_itf (sw_if_index); } - gbpe->ge_epg_id = epg_id; - - gbp_itf_epg_update (gbpe->ge_key->gek_sw_if_index, gbpe->ge_epg_id, 1); - - if (!ip46_address_is_zero (&gbpe->ge_key->gek_ip)) - gbp_ip_epg_update (&gbpe->ge_key->gek_ip, gbpe->ge_epg_id); - - /* - * send a gratuitous ARP on the EPG's uplink. this is done so that if - * this EP has moved from some other place in the 'fabric', upstream - * devices are informed - */ - if (ip46_address_is_ip4 (&gbpe->ge_key->gek_ip)) - send_ip4_garp_w_addr (vlib_get_main (), - &gbpe->ge_key->gek_ip.ip4, - gepg->gepg_uplink_sw_if_index); + if (NULL == gbpe) + { + index_t gbpei; + u32 ii; + /* + * new entry + */ + pool_get (gbp_endpoint_pool, gbpe); + gbpei = gbp_endpoint_index (gbpe); + + gbpe->ge_epg_id = epg_id; + gbpe->ge_sw_if_index = sw_if_index; + gbp_endpoint_add_itf (gbpe->ge_sw_if_index, gbpei); + + if (NULL != mac) + { + gbpe->ge_mac = *mac; + + // FIXME ERROR + gbp_endpoint_add_mac_itf (mac, sw_if_index, gbpei); + } + + if (NULL != ips) + { + vec_validate (gbpe->ge_ips, vec_len (ips) - 1); + vec_foreach_index (ii, ips) + { + ip46_address_copy (&gbpe->ge_ips[ii], &ips[ii]); + + // FIXME ERROR + gbp_endpoint_add_ip_itf (&ips[ii], sw_if_index, gbpei); + + /* + * send a gratuitous ARP on the EPG's uplink. this is done so + * that if this EP has moved from some other place in the + * 'fabric', upstream devices are informed + */ + if (ip46_address_is_ip4 (&ips[ii])) + send_ip4_garp_w_addr (vlib_get_main (), + &ips[ii].ip4, + gepg->gepg_uplink_sw_if_index); + else + send_ip6_na_w_addr (vlib_get_main (), + &ips[ii].ip6, + gepg->gepg_uplink_sw_if_index); + } + } + } else - send_ip6_na_w_addr (vlib_get_main (), - &gbpe->ge_key->gek_ip.ip6, - gepg->gepg_uplink_sw_if_index); + { + /* + * update existing entry.. + */ + ASSERT (0); + } + + *handle = (gbpe - gbp_endpoint_pool); return (0); } void -gbp_endpoint_delete (u32 sw_if_index, const ip46_address_t * ip) +gbp_endpoint_delete (u32 handle) { - gbp_endpoint_key_t key = { - .gek_ip = *ip, - .gek_sw_if_index = sw_if_index, - }; gbp_endpoint_t *gbpe; - uword *p; - p = hash_get_mem (gbp_endpoint_db, &key); + if (pool_is_free_index (gbp_endpoint_pool, handle)) + return; - if (p) - { - gbpe = pool_elt_at_index (gbp_endpoint_pool, p[0]); + gbpe = pool_elt_at_index (gbp_endpoint_pool, handle); - hash_unset_mem (gbp_endpoint_db, gbpe->ge_key); + gbp_endpoint_del_itf (gbpe->ge_sw_if_index); - gbp_itf_epg_delete (gbpe->ge_key->gek_sw_if_index); - if (!ip46_address_is_zero (&gbpe->ge_key->gek_ip)) - gbp_ip_epg_delete (&gbpe->ge_key->gek_ip); + if (!mac_address_is_zero (&gbpe->ge_mac)) + { + gbp_endpoint_del_mac_itf (&gbpe->ge_mac, gbpe->ge_sw_if_index); + } - clib_mem_free (gbpe->ge_key); + if (NULL != gbpe->ge_ips) + { + const ip46_address_t *ip; - pool_put (gbp_endpoint_pool, gbpe); + vec_foreach (ip, gbpe->ge_ips) + { + gbp_endpoint_del_ip_itf (ip, gbpe->ge_sw_if_index); + } } + pool_put (gbp_endpoint_pool, gbpe); } void @@ -237,14 +377,19 @@ static clib_error_t * gbp_endpoint_cli (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { + ip46_address_t ip = ip46_address_initializer, *ips = NULL; + mac_address_t mac = ZERO_MAC_ADDRESS; vnet_main_t *vnm = vnet_get_main (); epg_id_t epg_id = EPG_INVALID; - ip46_address_t ip = { }; + u32 handle = INDEX_INVALID; u32 sw_if_index = ~0; u8 add = 1; + int rv; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { + ip46_address_reset (&ip); + if (unformat (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index)) ; @@ -254,25 +399,41 @@ gbp_endpoint_cli (vlib_main_t * vm, add = 0; else if (unformat (input, "epg %d", &epg_id)) ; - else if (unformat (input, "ip %U", unformat_ip4_address, &ip.ip4)) + else if (unformat (input, "handle %d", &handle)) ; + else if (unformat (input, "ip %U", unformat_ip4_address, &ip.ip4)) + vec_add1 (ips, ip); else if (unformat (input, "ip %U", unformat_ip6_address, &ip.ip6)) + vec_add1 (ips, ip); + else if (unformat (input, "mac %U", unformat_mac_address, &mac)) ; else break; } - if (~0 == sw_if_index) - return clib_error_return (0, "interface must be specified"); - if (EPG_INVALID == epg_id) - return clib_error_return (0, "EPG-ID must be specified"); - if (ip46_address_is_zero (&ip)) - return clib_error_return (0, "IP address must be specified"); - if (add) - gbp_endpoint_update (sw_if_index, &ip, epg_id); + { + if (~0 == sw_if_index) + return clib_error_return (0, "interface must be specified"); + if (EPG_INVALID == epg_id) + return clib_error_return (0, "EPG-ID must be specified"); + + rv = gbp_endpoint_update (sw_if_index, ips, &mac, epg_id, &handle); + + if (rv) + return clib_error_return (0, "GBP Endpoint update returned %d", rv); + else + vlib_cli_output (vm, "handle %d\n", handle); + } else - gbp_endpoint_delete (sw_if_index, &ip); + { + if (INDEX_INVALID == handle) + return clib_error_return (0, "handle must be specified"); + + gbp_endpoint_delete (handle); + } + + vec_free (ips); return (NULL); } @@ -288,75 +449,132 @@ gbp_endpoint_cli (vlib_main_t * vm, /* *INDENT-OFF* */ VLIB_CLI_COMMAND (gbp_endpoint_cli_node, static) = { .path = "gbp endpoint", - .short_help = "gbp endpoint [del] epg ip ", + .short_help = "gbp endpoint [del] epg ip mac ", .function = gbp_endpoint_cli, }; /* *INDENT-ON* */ -static int -gbp_endpoint_show_one (gbp_endpoint_t * gbpe, void *ctx) +u8 * +format_gbp_endpoint (u8 * s, va_list * args) { + index_t gbpei = va_arg (*args, index_t); vnet_main_t *vnm = vnet_get_main (); + const ip46_address_t *ip; + gbp_endpoint_t *gbpe; + + gbpe = gbp_endpoint_get (gbpei); + + s = format (s, "[@%d] ", gbpei); + s = + format (s, "%U", format_vnet_sw_if_index_name, vnm, gbpe->ge_sw_if_index); + s = format (s, ", IPs:["); + + vec_foreach (ip, gbpe->ge_ips) + { + s = format (s, "%U, ", format_ip46_address, ip, IP46_TYPE_ANY); + } + s = format (s, "]"); + + s = format (s, " MAC:%U", format_mac_address_t, &gbpe->ge_mac); + s = format (s, " EPG-ID:%d", gbpe->ge_epg_id); + + return s; +} + +static walk_rc_t +gbp_endpoint_show_one (gbp_endpoint_t * gbpe, void *ctx) +{ vlib_main_t *vm; vm = ctx; - vlib_cli_output (vm, " {%U, %U} -> %d", - format_vnet_sw_if_index_name, vnm, - gbpe->ge_key->gek_sw_if_index, - format_ip46_address, &gbpe->ge_key->gek_ip, IP46_TYPE_ANY, - gbpe->ge_epg_id); + vlib_cli_output (vm, " %U", format_gbp_endpoint, gbp_endpoint_index (gbpe)); - return (1); + return (WALK_CONTINUE); } -static clib_error_t * -gbp_endpoint_show (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) +static void +gbp_endpoint_walk_ip_itf (const clib_bihash_kv_24_8_t * kvp, void *arg) { - vnet_main_t *vnm = vnet_get_main (); - ip46_address_t ip, *ipp; - epg_id_t epg_id; + ip46_address_t ip; + vlib_main_t *vm; u32 sw_if_index; - vlib_cli_output (vm, "Endpoints:"); - gbp_endpoint_walk (gbp_endpoint_show_one, vm); + vm = arg; - vlib_cli_output (vm, "\nSource interface to EPG:"); + gbp_endpoint_extract_key_ip_itf (kvp, &ip, &sw_if_index); - vec_foreach_index (sw_if_index, gbp_itf_to_epg_db.gte_vec) - { - if (EPG_INVALID != gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_epg) - { - vlib_cli_output (vm, " %U -> %d", - format_vnet_sw_if_index_name, vnm, sw_if_index, - gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_epg); - } - } + vlib_cli_output (vm, " {%U, %U} -> %d", + format_ip46_address, &ip, IP46_TYPE_ANY, + format_vnet_sw_if_index_name, vnet_get_main (), + sw_if_index, kvp->value); +} - vlib_cli_output (vm, "\nDestination IP4 to EPG:"); +static void +gbp_endpoint_walk_mac_itf (const clib_bihash_kv_16_8_t * kvp, void *arg) +{ + mac_address_t mac; + vlib_main_t *vm; + u32 sw_if_index; - /* *INDENT-OFF* */ - hash_foreach (ip.ip4.as_u32, epg_id, gbp_ip4_to_epg_db.g4ie_hash, - { - vlib_cli_output (vm, " %U -> %d", format_ip46_address, &ip, - IP46_TYPE_IP4, epg_id); - }); - /* *INDENT-ON* */ + vm = arg; - vlib_cli_output (vm, "\nDestination IP6 to EPG:"); + gbp_endpoint_extract_key_mac_itf (kvp, &mac, &sw_if_index); - /* *INDENT-OFF* */ - hash_foreach_mem (ipp, epg_id, gbp_ip6_to_epg_db.g6ie_hash, - { - vlib_cli_output (vm, " %U -> %d", format_ip46_address, ipp, - IP46_TYPE_IP6, epg_id); - }); - /* *INDENT-ON* */ + vlib_cli_output (vm, " {%U, %U} -> %d", + format_mac_address_t, &mac, + format_vnet_sw_if_index_name, vnet_get_main (), + sw_if_index, kvp->value); +} + +static clib_error_t * +gbp_endpoint_show (vlib_main_t * vm, + unformat_input_t * input, vlib_cli_command_t * cmd) +{ + u32 sw_if_index, show_dbs, handle; + + handle = INDEX_INVALID; + show_dbs = 0; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "%d", &handle)) + ; + else if (unformat (input, "db", &handle)) + show_dbs = 1; + else + break; + } + + if (INDEX_INVALID != handle) + { + vlib_cli_output (vm, "%U", format_gbp_endpoint, handle); + } + else if (show_dbs) + { + vlib_cli_output (vm, "\nDatabases:"); + clib_bihash_foreach_key_value_pair_24_8 (&gbp_ep_by_ip_itf_db.gte_table, + gbp_endpoint_walk_ip_itf, vm); + clib_bihash_foreach_key_value_pair_16_8 + (&gbp_ep_by_mac_itf_db.gte_table, gbp_endpoint_walk_mac_itf, vm); + + vec_foreach_index (sw_if_index, gbp_ep_by_itf_db.gte_vec) + { + if (INDEX_INVALID != gbp_ep_by_itf_db.gte_vec[sw_if_index]) + vlib_cli_output (vm, " {%U} -> %d", + format_vnet_sw_if_index_name, vnet_get_main (), + sw_if_index, + gbp_ep_by_itf_db.gte_vec[sw_if_index]); + } + } + else + { + vlib_cli_output (vm, "Endpoints:"); + gbp_endpoint_walk (gbp_endpoint_show_one, vm); + } return (NULL); } - /*? * Show Group Based Policy Endpoints and derived information * @@ -372,15 +590,21 @@ VLIB_CLI_COMMAND (gbp_endpoint_show_node, static) = { }; /* *INDENT-ON* */ +#define GBP_EP_HASH_NUM_BUCKETS (2 * 1024) +#define GBP_EP_HASH_MEMORY_SIZE (1 << 20) + static clib_error_t * gbp_endpoint_init (vlib_main_t * vm) { - gbp_endpoint_db = hash_create_mem (0, - sizeof (gbp_endpoint_key_t), - sizeof (u32)); - gbp_ip6_to_epg_db.g6ie_hash = - hash_create_mem (0, sizeof (ip6_address_t), sizeof (u32)); - return 0; + clib_bihash_init_24_8 (&gbp_ep_by_ip_itf_db.gte_table, + "GBP Endpoints - IP/Interface", + GBP_EP_HASH_NUM_BUCKETS, GBP_EP_HASH_MEMORY_SIZE); + + clib_bihash_init_16_8 (&gbp_ep_by_mac_itf_db.gte_table, + "GBP Endpoints - MAC/Interface", + GBP_EP_HASH_NUM_BUCKETS, GBP_EP_HASH_MEMORY_SIZE); + + return (NULL); } VLIB_INIT_FUNCTION (gbp_endpoint_init); diff --git a/src/plugins/gbp/gbp_endpoint.h b/src/plugins/gbp/gbp_endpoint.h index 000c211cfa1..275897dd0e3 100644 --- a/src/plugins/gbp/gbp_endpoint.h +++ b/src/plugins/gbp/gbp_endpoint.h @@ -18,86 +18,110 @@ #include #include +#include + +#include +#include +#include +#include /** - * The key for an Endpoint + * Flags for each endpoint */ -typedef struct gbp_endpoint_key_t_ +typedef enum gbp_endpoint_flags_t_ +{ + GBP_ENDPOINT_FLAG_NONE = 0, + GBP_ENDPOINT_FLAG_BOUNCE = (1 << 0), + GBP_ENDPOINT_FLAG_DYNAMIC = (1 << 1), +} gbp_endpoint_flags_t; + +/** + * A Group Based Policy Endpoint. + * This is typcially a VM or container. If the endpoint is local (i.e. on + * the smae compute node as VPP) then there is one interface per-endpoint. + * If the EP is remote,e.g. reachable onver a [vxlan] tunnel, then there + * will be multiple EPs reachable over the tunnel and they can be distingusihed + * via either their MAC or IP Address[es]. + */ +typedef struct gbp_endpoint_t_ { /** * The interface on which the EP is connected */ - u32 gek_sw_if_index; + u32 ge_sw_if_index; /** - * The IP[46] address of the endpoint + * A vector of ip addresses that below to the endpoint */ - ip46_address_t gek_ip; -} gbp_endpoint_key_t; + ip46_address_t *ge_ips; -/** - * A Group Based Policy Endpoint. - * This is typcially a VM on the local compute node for which policy must be - * locally applied - */ -typedef struct gbp_endpoint_t_ -{ /** - * The endpoint's interface and IP address + * MAC address of the endpoint */ - gbp_endpoint_key_t *ge_key; + mac_address_t ge_mac; /** * The endpoint's designated EPG */ epg_id_t ge_epg_id; + + /** + * Endpoint flags + */ + gbp_endpoint_flags_t ge_flags; } gbp_endpoint_t; -/** - * Result of a interface to EPG mapping. - * multiple Endpoints can occur on the same interface, so this - * mapping needs to be reference counted. - */ -typedef struct gbp_itf_t_ -{ - epg_id_t gi_epg; - u32 gi_ref_count; -} gbp_itf_t; +extern u8 *format_gbp_endpoint (u8 * s, va_list * args); /** * Interface to source EPG DB - a per-interface vector */ -typedef struct gbp_itf_to_epg_db_t_ +typedef struct gbp_ep_by_itf_db_t_ { - gbp_itf_t *gte_vec; -} gbp_itf_to_epg_db_t; + index_t *gte_vec; +} gbp_ep_by_itf_db_t; + +typedef struct gbp_ep_by_ip_itf_db_t_ +{ + clib_bihash_24_8_t gte_table; +} gbp_ep_by_ip_itf_db_t; + +typedef struct gbp_ep_by_mac_itf_db_t_ +{ + clib_bihash_16_8_t gte_table; +} gbp_ep_by_mac_itf_db_t; extern int gbp_endpoint_update (u32 sw_if_index, - const ip46_address_t * ip, epg_id_t epg_id); -extern void gbp_endpoint_delete (u32 sw_if_index, const ip46_address_t * ip); + const ip46_address_t * ip, + const mac_address_t * mac, + epg_id_t epg_id, u32 * handle); +extern void gbp_endpoint_delete (u32 handle); -typedef int (*gbp_endpoint_cb_t) (gbp_endpoint_t * gbpe, void *ctx); +typedef walk_rc_t (*gbp_endpoint_cb_t) (gbp_endpoint_t * gbpe, void *ctx); extern void gbp_endpoint_walk (gbp_endpoint_cb_t cb, void *ctx); -/** - * Port to EPG mapping management - */ -extern void gbp_itf_epg_update (u32 sw_if_index, epg_id_t src_epg, - u8 do_policy); -extern void gbp_itf_epg_delete (u32 sw_if_index); /** * DP functions and databases */ -extern gbp_itf_to_epg_db_t gbp_itf_to_epg_db; +extern gbp_ep_by_itf_db_t gbp_ep_by_itf_db; +extern gbp_ep_by_mac_itf_db_t gbp_ep_by_mac_itf_db; +extern gbp_ep_by_ip_itf_db_t gbp_ep_by_ip_itf_db; +extern gbp_endpoint_t *gbp_endpoint_pool; /** - * Get the source EPG for a port/interface + * Get the endpoint from a port/interface */ -always_inline u32 -gbp_port_to_epg (u32 sw_if_index) +always_inline gbp_endpoint_t * +gbp_endpoint_get (index_t gbpei) +{ + return (pool_elt_at_index (gbp_endpoint_pool, gbpei)); +} + +always_inline gbp_endpoint_t * +gbp_endpoint_get_itf (u32 sw_if_index) { - return (gbp_itf_to_epg_db.gte_vec[sw_if_index].gi_epg); + return (gbp_endpoint_get (gbp_ep_by_itf_db.gte_vec[sw_if_index])); } #endif diff --git a/src/plugins/gbp/gbp_endpoint_group.c b/src/plugins/gbp/gbp_endpoint_group.c index c5c06660f94..27d404e09dd 100644 --- a/src/plugins/gbp/gbp_endpoint_group.c +++ b/src/plugins/gbp/gbp_endpoint_group.c @@ -209,7 +209,7 @@ gbp_endpoint_group_cli (vlib_main_t * vm, /* *INDENT-OFF* */ VLIB_CLI_COMMAND (gbp_endpoint_group_cli_node, static) = { .path = "gbp endpoint-group", - .short_help = "gbp endpoint-group [del] epg bd ", + .short_help = "gbp endpoint-group [del] epg bd rd ", .function = gbp_endpoint_group_cli, }; diff --git a/src/plugins/gbp/gbp_policy.c b/src/plugins/gbp/gbp_policy.c index c0a8866e1ee..f57aa07a853 100644 --- a/src/plugins/gbp/gbp_policy.c +++ b/src/plugins/gbp/gbp_policy.c @@ -85,6 +85,7 @@ gbp_policy (vlib_main_t * vm, while (n_left_from > 0 && n_left_to_next > 0) { + const gbp_endpoint_t *gep0; gbp_policy_next_t next0; gbp_contract_key_t key0; gbp_contract_value_t value0 = { @@ -107,7 +108,8 @@ gbp_policy (vlib_main_t * vm, * determine the src and dst EPG */ sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_TX]; - key0.gck_dst = gbp_port_to_epg (sw_if_index0); + gep0 = gbp_endpoint_get_itf (sw_if_index0); + key0.gck_dst = gep0->ge_epg_id; key0.gck_src = vnet_buffer2 (b0)->gbp.src_epg; if (EPG_INVALID != key0.gck_src) diff --git a/src/plugins/gbp/gbp_recirc.c b/src/plugins/gbp/gbp_recirc.c index 1debbe406f3..c44fc2137c3 100644 --- a/src/plugins/gbp/gbp_recirc.c +++ b/src/plugins/gbp/gbp_recirc.c @@ -85,7 +85,8 @@ gbp_recirc_add (u32 sw_if_index, epg_id_t epg_id, u8 is_ext) * the external EPG, these are classified to the NAT EPG * based on its port */ - gbp_itf_epg_update (gr->gr_sw_if_index, gr->gr_epg, 0); + gbp_endpoint_update (gr->gr_sw_if_index, + NULL, NULL, gr->gr_epg, &gr->gr_ep); vnet_feature_enable_disable ("ip4-unicast", "ip4-gbp-src-classify", gr->gr_sw_if_index, 1, 0, 0); @@ -128,7 +129,7 @@ gbp_recirc_delete (u32 sw_if_index) if (gr->gr_is_ext) { - gbp_itf_epg_delete (gr->gr_sw_if_index); + gbp_endpoint_delete (gr->gr_ep); vnet_feature_enable_disable ("ip4-unicast", "ip4-gbp-src-classify", gr->gr_sw_if_index, 0, 0, 0); diff --git a/src/plugins/gbp/gbp_recirc.h b/src/plugins/gbp/gbp_recirc.h index 10f3da631c1..04a2378dcae 100644 --- a/src/plugins/gbp/gbp_recirc.h +++ b/src/plugins/gbp/gbp_recirc.h @@ -44,6 +44,10 @@ typedef struct gpb_recirc_t_ */ u32 gr_sw_if_index; + /** + * The endpoint created to represent the reric interface + */ + index_t gr_ep; } gbp_recirc_t; extern int gbp_recirc_add (u32 sw_if_index, epg_id_t epg_id, u8 is_ext); diff --git a/src/vnet/ip/ip6_packet.h b/src/vnet/ip/ip6_packet.h index b1c9be4d199..620740061c1 100644 --- a/src/vnet/ip/ip6_packet.h +++ b/src/vnet/ip/ip6_packet.h @@ -93,6 +93,13 @@ typedef CLIB_PACKED (union { #define ip46_address_is_zero(ip46) (((ip46)->as_u64[0] == 0) && ((ip46)->as_u64[1] == 0)) #define ip46_address_is_equal(a1, a2) (((a1)->as_u64[0] == (a2)->as_u64[0]) \ && ((a1)->as_u64[1] == (a2)->as_u64[1])) +static_always_inline void +ip46_address_copy (ip46_address_t * dst, const ip46_address_t * src) +{ + dst->as_u64[0] = src->as_u64[0]; + dst->as_u64[1] = src->as_u64[1]; +} + #define ip46_address_initializer {{{ 0 }}} always_inline ip46_address_t diff --git a/test/test_abf.py b/test/test_abf.py index ce53e53fc98..fb30fc3018c 100644 --- a/test/test_abf.py +++ b/test/test_abf.py @@ -2,7 +2,8 @@ from framework import VppTestCase, VppTestRunner from vpp_udp_encap import * -from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable, DpoProto +from vpp_ip import DpoProto +from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable from scapy.packet import Raw from scapy.layers.l2 import Ether, ARP diff --git a/test/test_bfd.py b/test/test_bfd.py index b3ac6356d2f..f14ff71b341 100644 --- a/test/test_bfd.py +++ b/test/test_bfd.py @@ -20,7 +20,8 @@ from vpp_pg_interface import CaptureTimeoutError, is_ipv6_misc from vpp_lo_interface import VppLoInterface from util import ppp from vpp_papi_provider import UnexpectedApiReturnValueError -from vpp_ip_route import VppIpRoute, VppRoutePath, DpoProto +from vpp_ip import DpoProto +from vpp_ip_route import VppIpRoute, VppRoutePath USEC_IN_SEC = 1000000 diff --git a/test/test_bier.py b/test/test_bier.py index c4f64bdbddd..0276f95c4fc 100644 --- a/test/test_bier.py +++ b/test/test_bier.py @@ -4,9 +4,10 @@ import unittest import socket from framework import VppTestCase, VppTestRunner, running_extended_tests +from vpp_ip import DpoProto from vpp_ip_route import VppIpRoute, VppRoutePath, VppMplsRoute, \ VppMplsTable, VppIpMRoute, VppMRoutePath, VppIpTable, \ - MRouteEntryFlags, MRouteItfFlags, MPLS_LABEL_INVALID, DpoProto, \ + MRouteEntryFlags, MRouteItfFlags, MPLS_LABEL_INVALID, \ VppMplsLabel from vpp_bier import * from vpp_udp_encap import * diff --git a/test/test_gbp.py b/test/test_gbp.py index 894690b216d..0d5dd154be7 100644 --- a/test/test_gbp.py +++ b/test/test_gbp.py @@ -5,7 +5,10 @@ import unittest from framework import VppTestCase, VppTestRunner from vpp_object import VppObject from vpp_neighbor import VppNeighbor -from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable, DpoProto +from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable + +from vpp_ip import * +from vpp_mac import * from scapy.packet import Raw from scapy.layers.l2 import Ether, ARP @@ -19,6 +22,19 @@ from scapy.utils import inet_pton, inet_ntop from util import mactobinary +def find_gbp_endpoint(test, sw_if_index, ip=None, mac=None): + vip = VppIpAddress(ip) + + eps = test.vapi.gbp_endpoint_dump() + for ep in eps: + if ep.endpoint.sw_if_index != sw_if_index: + continue + for eip in ep.endpoint.ips: + if vip == eip: + return True + return False + + class VppGbpEndpoint(VppObject): """ GBP Endpoint @@ -32,64 +48,67 @@ class VppGbpEndpoint(VppObject): def mac(self): return self.itf.remote_mac - def __init__(self, test, itf, epg, recirc, ip, fip, is_ip6=False): + @property + def ip4(self): + return self._ip4 + + @property + def fip4(self): + return self._fip4 + + @property + def ip6(self): + return self._ip6 + + @property + def fip6(self): + return self._fip6 + + @property + def ips(self): + return [self.ip4, self.ip6] + + @property + def fips(self): + return [self.fip4, self.fip6] + + def __init__(self, test, itf, epg, recirc, ip4, fip4, ip6, fip6): self._test = test self.itf = itf self.epg = epg self.recirc = recirc - self.ip = ip - self.floating_ip = fip - self.is_ip6 = is_ip6 - if is_ip6: - self.proto = DpoProto.DPO_PROTO_IP6 - self.af = AF_INET6 - self.is_ip6 = True - self.ip_len = 128 - else: - self.proto = DpoProto.DPO_PROTO_IP4 - self.af = AF_INET - self.is_ip6 = False - self.ip_len = 32 - self.ip_n = inet_pton(self.af, ip) - self.floating_ip_n = inet_pton(self.af, fip) + + self._ip4 = VppIpAddress(ip4) + self._fip4 = VppIpAddress(fip4) + self._ip6 = VppIpAddress(ip6) + self._fip6 = VppIpAddress(fip6) + + self.vmac = VppMacAddress(self.itf.remote_mac) def add_vpp_config(self): - self._test.vapi.gbp_endpoint_add_del( - 1, + res = self._test.vapi.gbp_endpoint_add( self.itf.sw_if_index, - self.ip_n, - self.is_ip6, + [self.ip4.encode(), self.ip6.encode()], + self.vmac.encode(), self.epg.epg) + self.handle = res.handle self._test.registry.register(self, self._test.logger) def remove_vpp_config(self): - self._test.vapi.gbp_endpoint_add_del( - 0, - self.itf.sw_if_index, - self.ip_n, - self.is_ip6, - self.epg.epg) + self._test.vapi.gbp_endpoint_del(self.handle) def __str__(self): return self.object_id() def object_id(self): return "gbp-endpoint;[%d:%s:%d]" % (self.itf.sw_if_index, - self.ip, + self.ip4.address, self.epg.epg) def query_vpp_config(self): - eps = self._test.vapi.gbp_endpoint_dump() - for ep in eps: - if self.is_ip6: - if ep.endpoint.address == self.ip_n \ - and ep.endpoint.sw_if_index == self.itf.sw_if_index: - return True - else: - if ep.endpoint.address[:4] == self.ip_n \ - and ep.endpoint.sw_if_index == self.itf.sw_if_index: - return True - return False + return find_gbp_endpoint(self._test, + self.itf.sw_if_index, + self.ip4.address) class VppGbpRecirc(VppObject): @@ -138,17 +157,11 @@ class VppGbpSubnet(VppObject): """ def __init__(self, test, table_id, address, address_len, - is_internal=True, is_ip6=False, + is_internal=True, sw_if_index=None, epg=None): self._test = test self.table_id = table_id - self.address = address - self.address_len = address_len - self.is_ip6 = is_ip6 - if is_ip6: - self.address_n = inet_pton(AF_INET6, address) - else: - self.address_n = inet_pton(AF_INET, address) + self.prefix = VppIpPrefix(address, address_len) self.is_internal = is_internal self.sw_if_index = sw_if_index self.epg = epg @@ -158,11 +171,9 @@ class VppGbpSubnet(VppObject): 1, self.table_id, self.is_internal, - self.address_n, - self.address_len, + self.prefix.encode(), sw_if_index=self.sw_if_index if self.sw_if_index else 0xffffffff, - epg_id=self.epg if self.epg else 0xffff, - is_ip6=self.is_ip6) + epg_id=self.epg if self.epg else 0xffff) self._test.registry.register(self, self._test.logger) def remove_vpp_config(self): @@ -170,30 +181,21 @@ class VppGbpSubnet(VppObject): 0, self.table_id, self.is_internal, - self.address_n, - self.address_len, - is_ip6=self.is_ip6) + self.prefix.encode()) def __str__(self): return self.object_id() def object_id(self): - return "gbp-subnet;[%d:%s/%d]" % (self.table_id, - self.address, - self.address_len) + return "gbp-subnet;[%d-%s]" % (self.table_id, + self.prefix) def query_vpp_config(self): ss = self._test.vapi.gbp_subnet_dump() for s in ss: if s.subnet.table_id == self.table_id and \ - s.subnet.address_length == self.address_len and \ - s.subnet.is_ip6 == self.is_ip6: - if self.is_ip6: - if s.subnet.address == self.address_n: - return True - else: - if s.subnet.address[:4] == self.address_n: - return True + s.subnet.prefix == self.prefix: + return True return False @@ -481,43 +483,38 @@ class TestGBP(VppTestCase): # # 3 EPGs, 2 of which share a BD. - # - epgs = [] - recircs = [] - epgs.append(VppGbpEndpointGroup(self, 220, 0, 1, self.pg4, - self.loop0, - "10.0.0.128", - "2001:10::128")) - recircs.append(VppGbpRecirc(self, epgs[0], - self.loop3)) - epgs.append(VppGbpEndpointGroup(self, 221, 0, 1, self.pg5, - self.loop0, - "10.0.1.128", - "2001:10:1::128")) - recircs.append(VppGbpRecirc(self, epgs[1], - self.loop4)) - epgs.append(VppGbpEndpointGroup(self, 222, 0, 2, self.pg6, - self.loop1, - "10.0.2.128", - "2001:10:2::128")) - recircs.append(VppGbpRecirc(self, epgs[2], - self.loop5)) - - # # 2 NAT EPGs, one for floating-IP subnets, the other for internet # - epgs.append(VppGbpEndpointGroup(self, 333, 20, 20, self.pg7, - self.loop2, - "11.0.0.128", - "3001::128")) - recircs.append(VppGbpRecirc(self, epgs[3], - self.loop6, is_ext=True)) - epgs.append(VppGbpEndpointGroup(self, 444, 20, 20, self.pg8, - self.loop2, - "11.0.0.129", - "3001::129")) - recircs.append(VppGbpRecirc(self, epgs[4], - self.loop8, is_ext=True)) + epgs = [VppGbpEndpointGroup(self, 220, 0, 1, self.pg4, + self.loop0, + "10.0.0.128", + "2001:10::128"), + VppGbpEndpointGroup(self, 221, 0, 1, self.pg5, + self.loop0, + "10.0.1.128", + "2001:10:1::128"), + VppGbpEndpointGroup(self, 222, 0, 2, self.pg6, + self.loop1, + "10.0.2.128", + "2001:10:2::128"), + VppGbpEndpointGroup(self, 333, 20, 20, self.pg7, + self.loop2, + "11.0.0.128", + "3001::128"), + VppGbpEndpointGroup(self, 444, 20, 20, self.pg8, + self.loop2, + "11.0.0.129", + "3001::129")] + recircs = [VppGbpRecirc(self, epgs[0], + self.loop3), + VppGbpRecirc(self, epgs[1], + self.loop4), + VppGbpRecirc(self, epgs[2], + self.loop5), + VppGbpRecirc(self, epgs[3], + self.loop6, is_ext=True), + VppGbpRecirc(self, epgs[4], + self.loop8, is_ext=True)] epg_nat = epgs[3] recirc_nat = recircs[3] @@ -525,43 +522,22 @@ class TestGBP(VppTestCase): # # 4 end-points, 2 in the same subnet, 3 in the same BD # - eps = [] - eps.append(VppGbpEndpoint(self, self.pg0, - epgs[0], recircs[0], - "10.0.0.1", - "11.0.0.1")) - eps.append(VppGbpEndpoint(self, self.pg1, - epgs[0], recircs[0], - "10.0.0.2", - "11.0.0.2")) - eps.append(VppGbpEndpoint(self, self.pg2, - epgs[1], recircs[1], - "10.0.1.1", - "11.0.0.3")) - eps.append(VppGbpEndpoint(self, self.pg3, - epgs[2], recircs[2], - "10.0.2.1", - "11.0.0.4")) - eps.append(VppGbpEndpoint(self, self.pg0, - epgs[0], recircs[0], - "2001:10::1", - "3001::1", - is_ip6=True)) - eps.append(VppGbpEndpoint(self, self.pg1, - epgs[0], recircs[0], - "2001:10::2", - "3001::2", - is_ip6=True)) - eps.append(VppGbpEndpoint(self, self.pg2, - epgs[1], recircs[1], - "2001:10:1::1", - "3001::3", - is_ip6=True)) - eps.append(VppGbpEndpoint(self, self.pg3, - epgs[2], recircs[2], - "2001:10:2::1", - "3001::4", - is_ip6=True)) + eps = [VppGbpEndpoint(self, self.pg0, + epgs[0], recircs[0], + "10.0.0.1", "11.0.0.1", + "2001:10::1", "3001::1"), + VppGbpEndpoint(self, self.pg1, + epgs[0], recircs[0], + "10.0.0.2", "11.0.0.2", + "2001:10::2", "3001::2"), + VppGbpEndpoint(self, self.pg2, + epgs[1], recircs[1], + "10.0.1.1", "11.0.0.3", + "2001:10:1::1", "3001::3"), + VppGbpEndpoint(self, self.pg3, + epgs[2], recircs[2], + "10.0.2.1", "11.0.0.4", + "2001:10:2::1", "3001::4")] # # Config related to each of the EPGs @@ -653,83 +629,91 @@ class TestGBP(VppTestCase): # adj-fibs due to the fact the the BVI address has /32 and # the subnet is not attached. # - r = VppIpRoute(self, ep.ip, ep.ip_len, - [VppRoutePath(ep.ip, - ep.epg.bvi.sw_if_index, - proto=ep.proto)], - is_ip6=ep.is_ip6) - r.add_vpp_config() - ep_routes.append(r) - - # - # ARP entries for the endpoints - # - a = VppNeighbor(self, - ep.epg.bvi.sw_if_index, - ep.itf.remote_mac, - ep.ip, af=ep.af) - a.add_vpp_config() - ep_arps.append(a) + for (ip, fip) in zip(ep.ips, ep.fips): + r = VppIpRoute(self, ip.address, ip.length, + [VppRoutePath(ip.address, + ep.epg.bvi.sw_if_index, + proto=ip.dpo_proto)], + is_ip6=ip.is_ip6) + r.add_vpp_config() + ep_routes.append(r) + + # + # ARP entries for the endpoints + # + a = VppNeighbor(self, + ep.epg.bvi.sw_if_index, + ep.itf.remote_mac, + ip.address, + af=ip.af) + a.add_vpp_config() + ep_arps.append(a) + + # add the BD ARP termination entry + self.vapi.bd_ip_mac_add_del(bd_id=ep.epg.bd, + mac=ep.bin_mac, + ip=ip.bytes, + is_ipv6=ip.is_ip6, + is_add=1) + + # Add static mappings for each EP from the 10/8 to 11/8 network + if ip.af == AF_INET: + self.vapi.nat44_add_del_static_mapping(ip.bytes, + fip.bytes, + vrf_id=0, + addr_only=1) + else: + self.vapi.nat66_add_del_static_mapping(ip.bytes, + fip.bytes, + vrf_id=0) # add each EP itf to the its BD self.vapi.sw_interface_set_l2_bridge(ep.itf.sw_if_index, ep.epg.bd) - # add the BD ARP termination entry - self.vapi.bd_ip_mac_add_del(bd_id=ep.epg.bd, - mac=ep.bin_mac, - ip=ep.ip_n, - is_ipv6=0, - is_add=1) - # L2 FIB entry self.vapi.l2fib_add_del(ep.mac, ep.epg.bd, ep.itf.sw_if_index, is_add=1) - # Add static mappings for each EP from the 10/8 to 11/8 network - if ep.af == AF_INET: - self.vapi.nat44_add_del_static_mapping(ep.ip_n, - ep.floating_ip_n, - vrf_id=0, - addr_only=1) - else: - self.vapi.nat66_add_del_static_mapping(ep.ip_n, - ep.floating_ip_n, - vrf_id=0) - # VPP EP create ... ep.add_vpp_config() + self.logger.info(self.vapi.cli("sh gbp endpoint")) + # ... results in a Gratuitous ARP/ND on the EPG's uplink - rx = ep.epg.uplink.get_capture(1, timeout=0.2) + rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2) - if ep.is_ip6: - self.assertTrue(rx[0].haslayer(ICMPv6ND_NA)) - self.assertEqual(rx[0][ICMPv6ND_NA].tgt, ep.ip) - else: - self.assertTrue(rx[0].haslayer(ARP)) - self.assertEqual(rx[0][ARP].psrc, ep.ip) - self.assertEqual(rx[0][ARP].pdst, ep.ip) + for ii, ip in enumerate(ep.ips): + p = rx[ii] - # add the BD ARP termination entry for floating IP - self.vapi.bd_ip_mac_add_del(bd_id=epg_nat.bd, - mac=ep.bin_mac, - ip=ep.floating_ip_n, - is_ipv6=ep.is_ip6, - is_add=1) + if ip.is_ip6: + self.assertTrue(p.haslayer(ICMPv6ND_NA)) + self.assertEqual(p[ICMPv6ND_NA].tgt, ip.address) + else: + self.assertTrue(p.haslayer(ARP)) + self.assertEqual(p[ARP].psrc, ip.address) + self.assertEqual(p[ARP].pdst, ip.address) - # floating IPs route via EPG recirc - r = VppIpRoute(self, ep.floating_ip, ep.ip_len, - [VppRoutePath(ep.floating_ip, - ep.recirc.recirc.sw_if_index, - is_dvr=1, - proto=ep.proto)], - table_id=20, - is_ip6=ep.is_ip6) - r.add_vpp_config() - ep_routes.append(r) + # add the BD ARP termination entry for floating IP + for fip in ep.fips: + self.vapi.bd_ip_mac_add_del(bd_id=epg_nat.bd, + mac=ep.bin_mac, + ip=fip.bytes, + is_ipv6=fip.is_ip6, + is_add=1) + + # floating IPs route via EPG recirc + r = VppIpRoute(self, fip.address, fip.length, + [VppRoutePath(fip.address, + ep.recirc.recirc.sw_if_index, + is_dvr=1, + proto=fip.dpo_proto)], + table_id=20, + is_ip6=fip.is_ip6) + r.add_vpp_config() + ep_routes.append(r) # L2 FIB entries in the NAT EPG BD to bridge the packets from # the outside direct to the internal EPG @@ -760,14 +744,14 @@ class TestGBP(VppTestCase): hwdst="ff:ff:ff:ff:ff:ff", hwsrc=self.pg0.remote_mac, pdst=epgs[0].bvi_ip4, - psrc=eps[0].ip)) + psrc=eps[0].ip4.address)) self.send_and_expect(self.pg0, [pkt_arp], self.pg0) - nsma = in6_getnsma(inet_pton(AF_INET6, eps[4].ip)) + nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6.address)) d = inet_ntop(AF_INET6, nsma) pkt_nd = (Ether(dst=in6_getnsmac(nsma)) / - IPv6(dst=d, src=eps[4].ip) / + IPv6(dst=d, src=eps[0].ip6.address) / ICMPv6ND_NS(tgt=epgs[0].bvi_ip6) / ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac)) self.send_and_expect(self.pg0, [pkt_nd], self.pg0) @@ -777,7 +761,7 @@ class TestGBP(VppTestCase): # pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / - IP(src=eps[0].ip, dst="232.1.1.1") / + IP(src=eps[0].ip4.address, dst="232.1.1.1") / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) @@ -797,12 +781,14 @@ class TestGBP(VppTestCase): # pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac, dst=self.router_mac) / - IP(src=eps[0].ip, dst="10.0.0.99") / + IP(src=eps[0].ip4.address, + dst="10.0.0.99") / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac, dst=self.router_mac) / - IP(src=eps[0].ip, dst="10.0.1.99") / + IP(src=eps[0].ip4.address, + dst="10.0.1.99") / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) @@ -810,7 +796,8 @@ class TestGBP(VppTestCase): pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac, dst=self.router_mac) / - IPv6(src=eps[4].ip, dst="2001:10::99") / + IPv6(src=eps[0].ip6.address, + dst="2001:10::99") / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_222_ip6 * 65) @@ -824,9 +811,9 @@ class TestGBP(VppTestCase): s41.add_vpp_config() s42.add_vpp_config() s43.add_vpp_config() - s61 = VppGbpSubnet(self, 0, "2001:10::1", 64, is_ip6=True) - s62 = VppGbpSubnet(self, 0, "2001:10:1::1", 64, is_ip6=True) - s63 = VppGbpSubnet(self, 0, "2001:10:2::1", 64, is_ip6=True) + s61 = VppGbpSubnet(self, 0, "2001:10::1", 64) + s62 = VppGbpSubnet(self, 0, "2001:10:1::1", 64) + s63 = VppGbpSubnet(self, 0, "2001:10:2::1", 64) s61.add_vpp_config() s62.add_vpp_config() s63.add_vpp_config() @@ -856,7 +843,8 @@ class TestGBP(VppTestCase): # pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac, dst="00:00:00:33:44:55") / - IP(src=eps[0].ip, dst="10.0.0.99") / + IP(src=eps[0].ip4.address, + dst="10.0.0.99") / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) @@ -869,7 +857,8 @@ class TestGBP(VppTestCase): pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac, dst="00:00:00:33:44:66") / - IP(src=eps[0].ip, dst="10.0.0.99") / + IP(src=eps[0].ip4.address, + dst="10.0.0.99") / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) @@ -882,7 +871,8 @@ class TestGBP(VppTestCase): # pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55", dst=self.pg0.remote_mac) / - IP(src=eps[0].ip, dst="10.0.0.99") / + IP(src=eps[0].ip4.address, + dst="10.0.0.99") / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) @@ -896,7 +886,8 @@ class TestGBP(VppTestCase): # pkt_intra_epg = (Ether(src=self.pg0.remote_mac, dst=self.pg1.remote_mac) / - IP(src=eps[0].ip, dst=eps[1].ip) / + IP(src=eps[0].ip4.address, + dst=eps[1].ip4.address) / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) @@ -908,17 +899,20 @@ class TestGBP(VppTestCase): # pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac, dst=self.pg2.remote_mac) / - IP(src=eps[0].ip, dst=eps[2].ip) / + IP(src=eps[0].ip4.address, + dst=eps[2].ip4.address) / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac, dst=self.pg0.remote_mac) / - IP(src=eps[2].ip, dst=eps[0].ip) / + IP(src=eps[2].ip4.address, + dst=eps[0].ip4.address) / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac, dst=self.router_mac) / - IP(src=eps[0].ip, dst=eps[3].ip) / + IP(src=eps[0].ip4.address, + dst=eps[3].ip4.address) / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) @@ -1008,8 +1002,7 @@ class TestGBP(VppTestCase): se16 = VppGbpSubnet(self, 0, "::", 0, is_internal=False, sw_if_index=recirc_nat.recirc.sw_if_index, - epg=epg_nat.epg, - is_ip6=True) + epg=epg_nat.epg) se16.add_vpp_config() # in the NAT RD an external subnet via the NAT EPG's uplink se3 = VppGbpSubnet(self, 20, "0.0.0.0", 0, @@ -1019,8 +1012,7 @@ class TestGBP(VppTestCase): se36 = VppGbpSubnet(self, 20, "::", 0, is_internal=False, sw_if_index=epg_nat.uplink.sw_if_index, - epg=epg_nat.epg, - is_ip6=True) + epg=epg_nat.epg) se4 = VppGbpSubnet(self, 20, "11.0.0.0", 8, is_internal=False, sw_if_index=epg_nat.uplink.sw_if_index, @@ -1033,14 +1025,15 @@ class TestGBP(VppTestCase): self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1")) self.logger.info(self.vapi.cli("sh ip6 fib ::/0")) self.logger.info(self.vapi.cli("sh ip6 fib %s" % - eps[4].floating_ip)) + eps[0].fip6)) # # From an EP to an outside addess: IN2OUT # pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac, dst=self.router_mac) / - IP(src=eps[0].ip, dst="1.1.1.1") / + IP(src=eps[0].ip4.address, + dst="1.1.1.1") / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) @@ -1062,25 +1055,26 @@ class TestGBP(VppTestCase): self.send_and_expect_natted(self.pg0, pkt_inter_epg_220_to_global * 65, self.pg7, - eps[0].floating_ip) + eps[0].fip4.address) pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac, dst=self.router_mac) / - IPv6(src=eps[4].ip, dst="6001::1") / + IPv6(src=eps[0].ip6.address, + dst="6001::1") / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) self.send_and_expect_natted6(self.pg0, pkt_inter_epg_220_to_global * 65, self.pg7, - eps[4].floating_ip) + eps[0].fip6.address) # # From a global address to an EP: OUT2IN # pkt_inter_epg_220_from_global = (Ether(src=self.router_mac, dst=self.pg0.remote_mac) / - IP(dst=eps[0].floating_ip, + IP(dst=eps[0].fip4.address, src="1.1.1.1") / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) @@ -1094,19 +1088,19 @@ class TestGBP(VppTestCase): self.send_and_expect_unnatted(self.pg7, pkt_inter_epg_220_from_global * 65, eps[0].itf, - eps[0].ip) + eps[0].ip4.address) pkt_inter_epg_220_from_global = (Ether(src=self.router_mac, dst=self.pg0.remote_mac) / - IPv6(dst=eps[4].floating_ip, + IPv6(dst=eps[0].fip6.address, src="6001::1") / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) self.send_and_expect_unnatted6(self.pg7, pkt_inter_epg_220_from_global * 65, - eps[4].itf, - eps[4].ip) + eps[0].itf, + eps[0].ip6.address) # # From a local VM to another local VM using resp. public addresses: @@ -1114,46 +1108,44 @@ class TestGBP(VppTestCase): # pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac, dst=self.router_mac) / - IP(src=eps[0].ip, - dst=eps[1].floating_ip) / + IP(src=eps[0].ip4.address, + dst=eps[1].fip4.address) / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) self.send_and_expect_double_natted(eps[0].itf, pkt_intra_epg_220_global * 65, eps[1].itf, - eps[0].floating_ip, - eps[1].ip) + eps[0].fip4.address, + eps[1].ip4.address) - pkt_intra_epg_220_global = (Ether(src=self.pg4.remote_mac, + pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac, dst=self.router_mac) / - IPv6(src=eps[4].ip, - dst=eps[5].floating_ip) / + IPv6(src=eps[0].ip6.address, + dst=eps[1].fip6.address) / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) - self.send_and_expect_double_natted6(eps[4].itf, + self.send_and_expect_double_natted6(eps[0].itf, pkt_intra_epg_220_global * 65, - eps[5].itf, - eps[4].floating_ip, - eps[5].ip) + eps[1].itf, + eps[0].fip6.address, + eps[1].ip6.address) # # cleanup # for ep in eps: # del static mappings for each EP from the 10/8 to 11/8 network - if ep.af == AF_INET: - self.vapi.nat44_add_del_static_mapping(ep.ip_n, - ep.floating_ip_n, - vrf_id=0, - addr_only=1, - is_add=0) - else: - self.vapi.nat66_add_del_static_mapping(ep.ip_n, - ep.floating_ip_n, - vrf_id=0, - is_add=0) + self.vapi.nat44_add_del_static_mapping(ep.ip4.bytes, + ep.fip4.bytes, + vrf_id=0, + addr_only=1, + is_add=0) + self.vapi.nat66_add_del_static_mapping(ep.ip6.bytes, + ep.fip6.bytes, + vrf_id=0, + is_add=0) for epg in epgs: # IP config on the BVI interfaces diff --git a/test/test_gre.py b/test/test_gre.py index 2559381b1f4..4d40b3b64a1 100644 --- a/test/test_gre.py +++ b/test/test_gre.py @@ -6,7 +6,8 @@ from logging import * from framework import VppTestCase, VppTestRunner from vpp_sub_interface import VppDot1QSubint from vpp_gre_interface import VppGreInterface, VppGre6Interface -from vpp_ip_route import VppIpRoute, VppRoutePath, DpoProto, VppIpTable +from vpp_ip import DpoProto +from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable from vpp_papi_provider import L2_VTR_OP from scapy.packet import Raw diff --git a/test/test_ip6.py b/test/test_ip6.py index 9a0c752ebfd..95f9229ea5a 100644 --- a/test/test_ip6.py +++ b/test/test_ip6.py @@ -7,9 +7,10 @@ from framework import VppTestCase, VppTestRunner from util import ppp, ip6_normalize from vpp_sub_interface import VppSubInterface, VppDot1QSubint from vpp_pg_interface import is_ipv6_misc +from vpp_ip import DpoProto from vpp_ip_route import VppIpRoute, VppRoutePath, find_route, VppIpMRoute, \ VppMRoutePath, MRouteItfFlags, MRouteEntryFlags, VppMplsIpBind, \ - VppMplsRoute, DpoProto, VppMplsTable, VppIpTable + VppMplsRoute, VppMplsTable, VppIpTable from vpp_neighbor import find_nbr, VppNeighbor from scapy.packet import Raw diff --git a/test/test_ip_mcast.py b/test/test_ip_mcast.py index 9c216d5657d..64eb304a29e 100644 --- a/test/test_ip_mcast.py +++ b/test/test_ip_mcast.py @@ -3,8 +3,9 @@ import unittest from framework import VppTestCase, VppTestRunner +from vpp_ip import DpoProto from vpp_ip_route import VppIpMRoute, VppMRoutePath, VppMFibSignal, \ - MRouteItfFlags, MRouteEntryFlags, VppIpTable, DpoProto + MRouteItfFlags, MRouteEntryFlags, VppIpTable from scapy.packet import Raw from scapy.layers.l2 import Ether diff --git a/test/test_ipip.py b/test/test_ipip.py index 5754bd0366b..350eae0fded 100644 --- a/test/test_ipip.py +++ b/test/test_ipip.py @@ -5,7 +5,8 @@ import unittest from scapy.layers.inet6 import IPv6, Ether, IP, UDP from scapy.all import fragment, RandShort from framework import VppTestCase, VppTestRunner -from vpp_ip_route import VppIpRoute, VppRoutePath, DpoProto, VppIpTable +from vpp_ip import DpoProto +from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable from socket import AF_INET, AF_INET6, inet_pton import StringIO diff --git a/test/test_map.py b/test/test_map.py index c5e193a975f..1a53492f136 100644 --- a/test/test_map.py +++ b/test/test_map.py @@ -4,7 +4,8 @@ import unittest import socket from framework import VppTestCase, VppTestRunner -from vpp_ip_route import VppIpRoute, VppRoutePath, DpoProto +from vpp_ip import DpoProto +from vpp_ip_route import VppIpRoute, VppRoutePath from scapy.layers.l2 import Ether, Raw from scapy.layers.inet import IP, UDP, ICMP diff --git a/test/test_mpls.py b/test/test_mpls.py index 33fed680dbe..d943f8281e9 100644 --- a/test/test_mpls.py +++ b/test/test_mpls.py @@ -4,9 +4,10 @@ import unittest import socket from framework import VppTestCase, VppTestRunner +from vpp_ip import DpoProto from vpp_ip_route import VppIpRoute, VppRoutePath, VppMplsRoute, \ VppMplsIpBind, VppIpMRoute, VppMRoutePath, \ - MRouteItfFlags, MRouteEntryFlags, DpoProto, VppIpTable, VppMplsTable, \ + MRouteItfFlags, MRouteEntryFlags, VppIpTable, VppMplsTable, \ VppMplsLabel, MplsLspMode from vpp_mpls_tunnel_interface import VppMPLSTunnelInterface diff --git a/test/test_mtu.py b/test/test_mtu.py index d6be2e2afb5..a70d5135c17 100644 --- a/test/test_mtu.py +++ b/test/test_mtu.py @@ -12,7 +12,8 @@ import unittest from scapy.layers.inet6 import IPv6, Ether, IP, UDP, ICMPv6PacketTooBig from scapy.layers.inet import ICMP from framework import VppTestCase, VppTestRunner -from vpp_ip_route import VppIpRoute, VppRoutePath, DpoProto +from vpp_ip import DpoProto +from vpp_ip_route import VppIpRoute, VppRoutePath from socket import AF_INET, AF_INET6, inet_pton import StringIO diff --git a/test/test_p2p_ethernet.py b/test/test_p2p_ethernet.py index d6d5c5071c4..c901eeac39c 100644 --- a/test/test_p2p_ethernet.py +++ b/test/test_p2p_ethernet.py @@ -11,7 +11,8 @@ from scapy.layers.inet6 import IPv6 from framework import VppTestCase, VppTestRunner from vpp_sub_interface import VppP2PSubint -from vpp_ip_route import VppIpRoute, VppRoutePath, DpoProto +from vpp_ip import DpoProto +from vpp_ip_route import VppIpRoute, VppRoutePath from util import mactobinary diff --git a/test/test_qos.py b/test/test_qos.py index 76fa8a11b6e..49165502bd7 100644 --- a/test/test_qos.py +++ b/test/test_qos.py @@ -5,8 +5,9 @@ import unittest from framework import VppTestCase, VppTestRunner from vpp_papi_provider import QOS_SOURCE from vpp_sub_interface import VppDot1QSubint +from vpp_ip import DpoProto from vpp_ip_route import VppIpRoute, VppRoutePath, VppMplsRoute, \ - VppMplsLabel, VppMplsTable, DpoProto + VppMplsLabel, VppMplsTable from scapy.packet import Raw from scapy.layers.l2 import Ether, Dot1Q diff --git a/test/test_reassembly.py b/test/test_reassembly.py index 76aabcb3fb7..b2c271decac 100644 --- a/test/test_reassembly.py +++ b/test/test_reassembly.py @@ -11,7 +11,8 @@ from util import ppp, fragment_rfc791, fragment_rfc8200 from scapy.layers.inet6 import IPv6, IPv6ExtHdrFragment, ICMPv6ParamProblem,\ ICMPv6TimeExceeded from vpp_gre_interface import VppGreInterface, VppGre6Interface -from vpp_ip_route import VppIpRoute, VppRoutePath, DpoProto +from vpp_ip import DpoProto +from vpp_ip_route import VppIpRoute, VppRoutePath test_packet_count = 257 diff --git a/test/test_sixrd.py b/test/test_sixrd.py index 7656c3f4e7c..a469ac5bab6 100644 --- a/test/test_sixrd.py +++ b/test/test_sixrd.py @@ -6,7 +6,8 @@ from scapy.layers.inet import IP, UDP, Ether from scapy.layers.inet6 import IPv6 from scapy.packet import Raw from framework import VppTestCase, VppTestRunner -from vpp_ip_route import VppIpRoute, VppRoutePath, DpoProto, VppIpTable +from vpp_ip import DpoProto +from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable from socket import AF_INET, AF_INET6, inet_pton """ Test6rd is a subclass of VPPTestCase classes. diff --git a/test/test_srmpls.py b/test/test_srmpls.py index ded4a71fa40..756405ab6d7 100644 --- a/test/test_srmpls.py +++ b/test/test_srmpls.py @@ -4,10 +4,9 @@ import unittest import socket from framework import VppTestCase, VppTestRunner +from vpp_ip import DpoProto from vpp_ip_route import VppIpRoute, VppRoutePath, VppMplsRoute, \ - VppMplsIpBind, VppIpMRoute, VppMRoutePath, \ - MRouteItfFlags, MRouteEntryFlags, DpoProto, VppIpTable, VppMplsTable, \ - VppMplsLabel, MplsLspMode + VppIpTable, VppMplsTable, VppMplsLabel from vpp_mpls_tunnel_interface import VppMPLSTunnelInterface from scapy.packet import Raw diff --git a/test/test_srv6_ad.py b/test/test_srv6_ad.py index 75d9d12da48..299f34315e5 100644 --- a/test/test_srv6_ad.py +++ b/test/test_srv6_ad.py @@ -5,7 +5,8 @@ import binascii from socket import AF_INET6 from framework import VppTestCase, VppTestRunner -from vpp_ip_route import VppIpRoute, VppRoutePath, DpoProto, VppIpTable +from vpp_ip import DpoProto +from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable from vpp_srv6 import SRv6LocalSIDBehaviors, VppSRv6LocalSID, VppSRv6Policy, \ SRv6PolicyType, VppSRv6Steering, SRv6PolicySteeringTypes diff --git a/test/vpp_ip.py b/test/vpp_ip.py index 912d8430d81..e44e6b56e30 100644 --- a/test/vpp_ip.py +++ b/test/vpp_ip.py @@ -4,6 +4,7 @@ """ from ipaddress import ip_address +from socket import AF_INET, AF_INET6 class IpAddressFamily: @@ -11,17 +12,16 @@ class IpAddressFamily: ADDRESS_IP6 = 1 -INVALID_INDEX = 0xffffffff +class DpoProto: + DPO_PROTO_IP4 = 0 + DPO_PROTO_IP6 = 1 + DPO_PROTO_MPLS = 2 + DPO_PROTO_ETHERNET = 3 + DPO_PROTO_BIER = 4 + DPO_PROTO_NSH = 5 -def compare_ip_address(api_address, py_address): - if 4 is py_address.version: - if py_address.packed == api_address.ip4.address: - return True - else: - if py_address.packed == api_address.ip6.address: - return True - return False +INVALID_INDEX = 0xffffffff class VppIpAddressUnion(): @@ -29,16 +29,8 @@ class VppIpAddressUnion(): self.addr = addr self.ip_addr = ip_address(unicode(self.addr)) - @property - def version(self): - return self.ip_addr.version - - @property - def address(self): - return self.addr - def encode(self): - if self.ip_addr.version is 6: + if self.version is 6: return { 'ip6': { 'address': self.ip_addr.packed @@ -51,6 +43,41 @@ class VppIpAddressUnion(): }, } + @property + def version(self): + return self.ip_addr.version + + @property + def address(self): + return self.addr + + @property + def length(self): + if self.version is 6: + return 128 + else: + return 32 + + @property + def bytes(self): + return self.ip_addr.packed + + def __eq__(self, other): + if isinstance(other, self.__class__): + return self.ip_addr == other.ip_addr + elif hasattr(other, "ip4") and hasattr(other, "ip6"): + # vl_api_address_union_t + if 4 is self.version: + return self.ip_addr.packed == other.ip4.address + else: + return self.ip_addr.packed == other.ip6.address + else: + raise Exception("Comparing VppIpAddresUnions:%s" + " with unknown type: %s" % + (self, other)) + + return False + class VppIpAddress(): def __init__(self, addr): @@ -68,10 +95,62 @@ class VppIpAddress(): 'un': self.addr.encode() } + def __eq__(self, other): + if isinstance(other, self.__class__): + return self.addr == other.addr + elif hasattr(other, "af") and hasattr(other, "un"): + # a vp_api_address_t + if 4 is self.version: + return other.af == IpAddressFamily.ADDRESS_IP4 and \ + other.un == self.addr + else: + return other.af == IpAddressFamily.ADDRESS_IP6 and \ + other.un == self.addr + else: + raise Exception("Comparing VppIpAddress:%s with unknown type: %s" % + (self, other)) + return False + + def __ne__(self, other): + return not (self == other) + + def __str__(self): + return self.address + + @property + def bytes(self): + return self.addr.bytes + @property def address(self): return self.addr.address + @property + def length(self): + return self.addr.length + + @property + def version(self): + return self.addr.version + + @property + def is_ip6(self): + return (self.version == 6) + + @property + def af(self): + if self.version == 6: + return AF_INET6 + else: + return AF_INET + + @property + def dpo_proto(self): + if self.version is 6: + return DpoProto.DPO_PROTO_IP6 + else: + return DpoProto.DPO_PROTO_IP4 + class VppIpPrefix(): def __init__(self, addr, len): @@ -91,6 +170,25 @@ class VppIpPrefix(): def address(self): return self.addr.address + @property + def length(self): + return self.len + + def __str__(self): + return "%s/%d" % (self.address, self.length) + + def __eq__(self, other): + if isinstance(other, self.__class__): + return (self.len == other.len and self.addr == other.addr) + elif hasattr(other, "address") and hasattr(other, "address_length"): + # vl_api_prefix_t + return self.len == other.address_length and \ + self.addr == other.address + else: + raise Exception("Comparing VppIpPrefix:%s with unknown type: %s" % + (self, other)) + return False + class VppIpMPrefix(): def __init__(self, saddr, gaddr, len): diff --git a/test/vpp_ip_route.py b/test/vpp_ip_route.py index 216f5c7b2c1..9d6bfb77d93 100644 --- a/test/vpp_ip_route.py +++ b/test/vpp_ip_route.py @@ -6,6 +6,7 @@ from vpp_object import * from socket import inet_pton, inet_ntop, AF_INET, AF_INET6 +from vpp_ip import * # from vnet/vnet/mpls/mpls_types.h MPLS_IETF_MAX_LABEL = 0xfffff @@ -29,15 +30,6 @@ class MRouteEntryFlags: MFIB_ENTRY_FLAG_INHERIT_ACCEPT = 8 -class DpoProto: - DPO_PROTO_IP4 = 0 - DPO_PROTO_IP6 = 1 - DPO_PROTO_MPLS = 2 - DPO_PROTO_ETHERNET = 3 - DPO_PROTO_BIER = 4 - DPO_PROTO_NSH = 5 - - class MplsLspMode: PIPE = 0 UNIFORM = 1 diff --git a/test/vpp_mac.py b/test/vpp_mac.py new file mode 100644 index 00000000000..c9ee11e6658 --- /dev/null +++ b/test/vpp_mac.py @@ -0,0 +1,24 @@ +""" + MAC Types + +""" + +from util import mactobinary + + +class VppMacAddress(): + def __init__(self, addr): + self.address = addr + + def encode(self): + return { + 'bytes': self.bytes + } + + @property + def bytes(self): + return mactobinary(self.address) + + @property + def address(self): + return self.addr.address diff --git a/test/vpp_papi_provider.py b/test/vpp_papi_provider.py index b575b8ad6ac..3028a25b70b 100644 --- a/test/vpp_papi_provider.py +++ b/test/vpp_papi_provider.py @@ -3432,15 +3432,20 @@ class VppPapiProvider(object): 'enable_ip6': 1 if enable_ip6 else 0, }) - def gbp_endpoint_add_del(self, is_add, sw_if_index, addr, is_ip6, epg): - """ GBP endpoint Add/Del """ - return self.api(self.papi.gbp_endpoint_add_del, - {'is_add': is_add, - 'endpoint': { - 'is_ip6': is_ip6, - 'sw_if_index': sw_if_index, - 'address': addr, - 'epg_id': epg}}) + def gbp_endpoint_add(self, sw_if_index, ips, mac, epg): + """ GBP endpoint Add """ + return self.api(self.papi.gbp_endpoint_add, + {'endpoint': { + 'sw_if_index': sw_if_index, + 'ips': ips, + 'n_ips': len(ips), + 'mac': mac, + 'epg_id': epg}}) + + def gbp_endpoint_del(self, handle): + """ GBP endpoint Del """ + return self.api(self.papi.gbp_endpoint_del, + {'handle': handle}) def gbp_endpoint_dump(self): """ GBP endpoint Dump """ @@ -3479,7 +3484,7 @@ class VppPapiProvider(object): def gbp_subnet_add_del(self, is_add, table_id, is_internal, - addr, addr_len, + prefix, sw_if_index=0xffffffff, epg_id=0xffff, is_ip6=False): @@ -3491,8 +3496,7 @@ class VppPapiProvider(object): 'is_ip6': is_ip6, 'sw_if_index': sw_if_index, 'epg_id': epg_id, - 'address': addr, - 'address_length': addr_len, + 'prefix': prefix, 'table_id': table_id}}) def gbp_subnet_dump(self): diff --git a/test/vpp_udp_encap.py b/test/vpp_udp_encap.py index 002f9f4023a..826378b4de8 100644 --- a/test/vpp_udp_encap.py +++ b/test/vpp_udp_encap.py @@ -12,10 +12,8 @@ def find_udp_encap(test, ue): encaps = test.vapi.udp_encap_dump() for e in encaps: if ue.id == e.udp_encap.id \ - and compare_ip_address(e.udp_encap.src_ip.un, - ue.src_ip.addr.ip_addr) \ - and compare_ip_address(e.udp_encap.dst_ip.un, - ue.dst_ip.addr.ip_addr) \ + and ue.src_ip == e.udp_encap.src_ip \ + and ue.dst_ip == e.udp_encap.dst_ip \ and e.udp_encap.dst_port == ue.dst_port \ and e.udp_encap.src_port == ue.src_port: return True -- 2.16.6