aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--extras/vom/vom/gbp_endpoint.cpp59
-rw-r--r--extras/vom/vom/gbp_endpoint.hpp9
-rw-r--r--extras/vom/vom/gbp_endpoint_cmds.cpp65
-rw-r--r--extras/vom/vom/gbp_endpoint_cmds.hpp19
-rw-r--r--extras/vom/vom/gbp_subnet.cpp4
-rw-r--r--extras/vom/vom/gbp_subnet_cmds.cpp7
-rw-r--r--extras/vom/vom/prefix.hpp5
-rw-r--r--src/plugins/gbp/gbp.api34
-rw-r--r--src/plugins/gbp/gbp_api.c117
-rw-r--r--src/plugins/gbp/gbp_classify.c4
-rw-r--r--src/plugins/gbp/gbp_endpoint.c602
-rw-r--r--src/plugins/gbp/gbp_endpoint.h108
-rw-r--r--src/plugins/gbp/gbp_endpoint_group.c2
-rw-r--r--src/plugins/gbp/gbp_policy.c4
-rw-r--r--src/plugins/gbp/gbp_recirc.c5
-rw-r--r--src/plugins/gbp/gbp_recirc.h4
-rw-r--r--src/vnet/ip/ip6_packet.h7
-rw-r--r--test/test_abf.py3
-rw-r--r--test/test_bfd.py3
-rw-r--r--test/test_bier.py3
-rw-r--r--test/test_gbp.py490
-rw-r--r--test/test_gre.py3
-rw-r--r--test/test_ip6.py3
-rw-r--r--test/test_ip_mcast.py3
-rw-r--r--test/test_ipip.py3
-rw-r--r--test/test_map.py3
-rw-r--r--test/test_mpls.py3
-rw-r--r--test/test_mtu.py3
-rw-r--r--test/test_p2p_ethernet.py3
-rw-r--r--test/test_qos.py3
-rw-r--r--test/test_reassembly.py3
-rw-r--r--test/test_sixrd.py3
-rw-r--r--test/test_srmpls.py5
-rw-r--r--test/test_srv6_ad.py3
-rw-r--r--test/vpp_ip.py134
-rw-r--r--test/vpp_ip_route.py10
-rw-r--r--test/vpp_mac.py24
-rw-r--r--test/vpp_papi_provider.py28
-rw-r--r--test/vpp_udp_encap.py6
39 files changed, 1120 insertions, 677 deletions
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::key_t, gbp_endpoint> 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<boost::asio::ip::address>& 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<boost::asio::ip::address> addresses;
+
+ for (uint8_t n = 0; n < payload.endpoint.n_ips; n++)
+ addresses.push_back(from_api(payload.endpoint.ips[n]));
std::shared_ptr<interface> itf =
interface::find(payload.endpoint.sw_if_index);
std::shared_ptr<gbp_endpoint_group> 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 <ostream>
+#include <vector>
#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<interface::key_t, boost::asio::ip::address> key_t;
+ typedef std::pair<interface::key_t, mac_address_t> key_t;
/**
* Construct a GBP endpoint
*/
gbp_endpoint(const interface& itf,
- const boost::asio::ip::address& ip_addr,
+ const std::vector<boost::asio::ip::address>& 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<bool> m_hw;
+ HW::item<handle_t> 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<boost::asio::ip::address> 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<bool>& item,
+create_cmd::create_cmd(HW::item<handle_t>& item,
const handle_t& itf,
- const boost::asio::ip::address& ip_addr,
+ const std::vector<boost::asio::ip::address>& 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<bool>& 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<handle_t>(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<bool>& item,
- const handle_t& itf,
- const boost::asio::ip::address& ip_addr)
+delete_cmd::delete_cmd(HW::item<handle_t>& 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<HW::item<bool>, vapi::Gbp_endpoint_add_del>
+class create_cmd : public rpc_cmd<HW::item<handle_t>, vapi::Gbp_endpoint_add>
{
public:
/**
* Constructor
*/
- create_cmd(HW::item<bool>& item,
+ create_cmd(HW::item<handle_t>& item,
const handle_t& itf,
- const boost::asio::ip::address& ip_addr,
+ const std::vector<boost::asio::ip::address>& 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<boost::asio::ip::address> 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<HW::item<bool>, vapi::Gbp_endpoint_add_del>
+class delete_cmd : public rpc_cmd<HW::item<handle_t>, vapi::Gbp_endpoint_del>
{
public:
/**
* Constructor
*/
- delete_cmd(HW::item<bool>& item,
- const handle_t& itf,
- const boost::asio::ip::address& ip_addr);
+ delete_cmd(HW::item<handle_t>& 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<route_domain> 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 <boost/asio/ip/address.hpp>
-
#include "vom/enum_base.hpp"
+#include <boost/asio/ip/address.hpp>
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 <vnet/interface.h>
#include <vnet/api_errno.h>
+#include <vnet/ip/ip_types_api.h>
+#include <vnet/ethernet/ethernet_types_api.h>
#include <vpp/app/version.h>
#include <gbp/gbp.h>
@@ -52,7 +54,8 @@
#include <vlibapi/api_helper_macros.h>
#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 <vnet/l2/l2_output.h>
#include <vnet/l2/feat_bitmap.h>
-/**
- * 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] <interface> epg <ID> ip <IP>",
+ .short_help = "gbp endpoint [del] <interface> epg <ID> ip <IP> mac <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 <plugins/gbp/gbp_types.h>
#include <vnet/ip/ip.h>
+#include <vnet/ethernet/mac_address.h>
+
+#include <vppinfra/bihash_16_8.h>
+#include <vppinfra/bihash_template.h>
+#include <vppinfra/bihash_24_8.h>
+#include <vppinfra/bihash_template.h>
/**
- * 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 <ID> bd <ID> <interface>",
+ .short_help = "gbp endpoint-group [del] epg <ID> bd <ID> rd <ID> <interface>",
.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