aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--extras/vom/vom/gbp_contract.cpp79
-rw-r--r--extras/vom/vom/gbp_contract.hpp19
-rw-r--r--extras/vom/vom/gbp_contract_cmds.cpp95
-rw-r--r--extras/vom/vom/gbp_contract_cmds.hpp4
-rw-r--r--extras/vom/vom/gbp_rule.cpp23
-rw-r--r--extras/vom/vom/gbp_rule.hpp11
-rw-r--r--src/plugins/gbp/gbp.api2
-rw-r--r--src/plugins/gbp/gbp_api.c26
-rw-r--r--src/plugins/gbp/gbp_contract.c17
-rw-r--r--src/plugins/gbp/gbp_contract.h8
-rw-r--r--src/plugins/gbp/gbp_policy.c131
-rw-r--r--test/test_gbp.py90
-rw-r--r--test/vpp_papi_provider.py7
13 files changed, 328 insertions, 184 deletions
diff --git a/extras/vom/vom/gbp_contract.cpp b/extras/vom/vom/gbp_contract.cpp
index 87b5ed8ff0a..6cd2fad43f2 100644
--- a/extras/vom/vom/gbp_contract.cpp
+++ b/extras/vom/vom/gbp_contract.cpp
@@ -26,11 +26,15 @@ gbp_contract::event_handler gbp_contract::m_evh;
gbp_contract::gbp_contract(epg_id_t src_epg_id,
epg_id_t dst_epg_id,
- const ACL::l3_list& acl)
+ const ACL::l3_list& acl,
+ const gbp_rules_t& rules,
+ const ethertype_set_t& allowed_ethertypes)
: m_hw(false)
, m_src_epg_id(src_epg_id)
, m_dst_epg_id(dst_epg_id)
, m_acl(acl.singular())
+ , m_gbp_rules(rules)
+ , m_allowed_ethertypes(allowed_ethertypes)
{
}
@@ -39,6 +43,8 @@ gbp_contract::gbp_contract(const gbp_contract& gbpc)
, m_src_epg_id(gbpc.m_src_epg_id)
, m_dst_epg_id(gbpc.m_dst_epg_id)
, m_acl(gbpc.m_acl)
+ , m_gbp_rules(gbpc.m_gbp_rules)
+ , m_allowed_ethertypes(gbpc.m_allowed_ethertypes)
{
}
@@ -77,7 +83,8 @@ gbp_contract::replay()
{
if (m_hw) {
HW::enqueue(new gbp_contract_cmds::create_cmd(
- m_hw, m_src_epg_id, m_dst_epg_id, m_acl->handle(), m_gbp_rules));
+ m_hw, m_src_epg_id, m_dst_epg_id, m_acl->handle(), m_gbp_rules,
+ m_allowed_ethertypes));
}
}
@@ -100,12 +107,6 @@ gbp_contract::to_string() const
}
void
-gbp_contract::set_gbp_rules(const gbp_contract::gbp_rules_t& gbp_rules)
-{
- m_gbp_rules = gbp_rules;
-}
-
-void
gbp_contract::update(const gbp_contract& r)
{
/*
@@ -113,7 +114,8 @@ gbp_contract::update(const gbp_contract& r)
*/
if (rc_t::OK != m_hw.rc()) {
HW::enqueue(new gbp_contract_cmds::create_cmd(
- m_hw, m_src_epg_id, m_dst_epg_id, m_acl->handle(), m_gbp_rules));
+ m_hw, m_src_epg_id, m_dst_epg_id, m_acl->handle(), m_gbp_rules,
+ m_allowed_ethertypes));
}
}
@@ -169,31 +171,44 @@ gbp_contract::event_handler::handle_populate(const client_db::key_t& key)
ACL::l3_list::find(payload.contract.acl_index);
if (acl) {
- gbp_contract gbpc(payload.contract.src_epg, payload.contract.dst_epg,
- *acl);
- OM::commit(key, gbpc);
- if (payload.contract.n_rules) {
- gbp_contract::gbp_rules_t rules;
- for (u8 i = 0; i < payload.contract.n_rules; i++) {
- const gbp_rule::action_t action =
- gbp_rule::action_t::from_int(payload.contract.rules[i].action);
- const gbp_rule::hash_mode_t hm = gbp_rule::hash_mode_t::from_int(
- payload.contract.rules[i].nh_set.hash_mode);
- gbp_rule::next_hops_t nhs;
- for (u8 j = 0; j < payload.contract.rules[i].nh_set.n_nhs; j++) {
- gbp_rule::next_hop_t nh(
- from_api(payload.contract.rules[i].nh_set.nhs[j].ip),
- from_api(payload.contract.rules[i].nh_set.nhs[j].mac),
- payload.contract.rules[i].nh_set.nhs[j].bd_id,
- payload.contract.rules[i].nh_set.nhs[j].rd_id);
- nhs.insert(nh);
- }
- gbp_rule::next_hop_set_t next_hop_set(hm, nhs);
- gbp_rule gr(i, next_hop_set, action);
- rules.insert(gr);
+ gbp_contract::gbp_rules_t rules;
+
+ for (uint8_t i = 0; i < payload.contract.n_rules; i++) {
+ const gbp_rule::action_t action =
+ gbp_rule::action_t::from_int(payload.contract.rules[i].action);
+ const gbp_rule::hash_mode_t hm = gbp_rule::hash_mode_t::from_int(
+ payload.contract.rules[i].nh_set.hash_mode);
+ gbp_rule::next_hops_t nhs;
+ for (u8 j = 0; j < payload.contract.rules[i].nh_set.n_nhs; j++) {
+ gbp_rule::next_hop_t nh(
+ from_api(payload.contract.rules[i].nh_set.nhs[j].ip),
+ from_api(payload.contract.rules[i].nh_set.nhs[j].mac),
+ payload.contract.rules[i].nh_set.nhs[j].bd_id,
+ payload.contract.rules[i].nh_set.nhs[j].rd_id);
+ nhs.insert(nh);
}
- gbpc.set_gbp_rules(rules);
+ gbp_rule::next_hop_set_t next_hop_set(hm, nhs);
+ gbp_rule gr(i, next_hop_set, action);
+ rules.insert(gr);
+ }
+
+ ethertype_set_t allowed_ethertypes;
+ u8 *data, n_et;
+ u16* et;
+
+ data = (((u8*)&payload.contract.n_ether_types) +
+ (sizeof(payload.contract.rules[0]) * payload.contract.n_rules));
+ n_et = *data;
+ et = (u16*)(++data);
+
+ for (uint8_t i = 0; i < n_et; i++) {
+ allowed_ethertypes.insert(ethertype_t::from_numeric_val(et[i]));
}
+
+ gbp_contract gbpc(payload.contract.src_epg, payload.contract.dst_epg,
+ *acl, rules, allowed_ethertypes);
+ OM::commit(key, gbpc);
+
VOM_LOG(log_level_t::DEBUG) << "read: " << gbpc.to_string();
}
}
diff --git a/extras/vom/vom/gbp_contract.hpp b/extras/vom/vom/gbp_contract.hpp
index 53f8f3659ec..e517a3d6428 100644
--- a/extras/vom/vom/gbp_contract.hpp
+++ b/extras/vom/vom/gbp_contract.hpp
@@ -42,11 +42,18 @@ public:
typedef std::pair<epg_id_t, epg_id_t> key_t;
/**
+ * A set of allowed ethertypes
+ */
+ typedef std::set<ethertype_t> ethertype_set_t;
+
+ /**
* Construct a GBP contract
*/
gbp_contract(epg_id_t src_epg_id,
epg_id_t dst_epg_id,
- const ACL::l3_list& acl);
+ const ACL::l3_list& acl,
+ const gbp_rules_t& gpb_rules,
+ const ethertype_set_t& allowed_ethertypes);
/**
* Copy Construct
@@ -93,11 +100,6 @@ public:
*/
std::string to_string() const;
- /**
- * Set gbp_rules in case of Redirect Contract
- */
- void set_gbp_rules(const gbp_rules_t& gbp_rules);
-
private:
/**
* Class definition for listeners to OM events
@@ -185,6 +187,11 @@ private:
gbp_rules_t m_gbp_rules;
/**
+ * the set of Ether-types allowed by this contract
+ */
+ ethertype_set_t m_allowed_ethertypes;
+
+ /**
* A map of all bridge_domains
*/
static singular_db<key_t, gbp_contract> m_db;
diff --git a/extras/vom/vom/gbp_contract_cmds.cpp b/extras/vom/vom/gbp_contract_cmds.cpp
index 8b15e8cb519..7c42fc6bc4e 100644
--- a/extras/vom/vom/gbp_contract_cmds.cpp
+++ b/extras/vom/vom/gbp_contract_cmds.cpp
@@ -23,12 +23,14 @@ create_cmd::create_cmd(HW::item<bool>& item,
epg_id_t src_epg_id,
epg_id_t dst_epg_id,
const handle_t& acl,
- const gbp_contract::gbp_rules_t& gbp_rules)
+ const gbp_contract::gbp_rules_t& gbp_rules,
+ const gbp_contract::ethertype_set_t& allowed_ethertypes)
: rpc_cmd(item)
, m_src_epg_id(src_epg_id)
, m_dst_epg_id(dst_epg_id)
, m_acl(acl)
, m_gbp_rules(gbp_rules)
+ , m_allowed_ethertypes(allowed_ethertypes)
{
}
@@ -37,58 +39,69 @@ create_cmd::operator==(const create_cmd& other) const
{
return ((m_acl == other.m_acl) && (m_src_epg_id == other.m_src_epg_id) &&
(m_dst_epg_id == other.m_dst_epg_id) &&
- (m_gbp_rules == other.m_gbp_rules));
+ (m_gbp_rules == other.m_gbp_rules) &&
+ (m_allowed_ethertypes == other.m_allowed_ethertypes));
}
rc_t
create_cmd::issue(connection& con)
{
- u8 size = m_gbp_rules.empty() ? 1 : m_gbp_rules.size();
- msg_t req(con.ctx(), size, std::ref(*this));
+ size_t n_rules = m_gbp_rules.size();
+ size_t n_et_rules = 0;
+
+ msg_t req(con.ctx(), n_rules, n_et_rules, std::ref(*this));
auto& payload = req.get_request().get_payload();
payload.is_add = 1;
payload.contract.acl_index = m_acl.value();
payload.contract.src_epg = m_src_epg_id;
payload.contract.dst_epg = m_dst_epg_id;
- if (size > 1) {
- u32 ii = 0;
- auto it = m_gbp_rules.cbegin();
- payload.contract.n_rules = m_gbp_rules.size();
- while (it != m_gbp_rules.cend()) {
- if (it->action() == gbp_rule::action_t::REDIRECT)
- payload.contract.rules[ii].action = GBP_API_RULE_REDIRECT;
- else if (it->action() == gbp_rule::action_t::PERMIT)
- payload.contract.rules[ii].action = GBP_API_RULE_PERMIT;
- else
- payload.contract.rules[ii].action = GBP_API_RULE_DENY;
-
- if (it->nhs().getHashMode() == gbp_rule::hash_mode_t::SYMMETRIC)
- payload.contract.rules[ii].nh_set.hash_mode =
- GBP_API_HASH_MODE_SYMMETRIC;
- else if (it->nhs().getHashMode() == gbp_rule::hash_mode_t::SRC_IP)
- payload.contract.rules[ii].nh_set.hash_mode = GBP_API_HASH_MODE_SRC_IP;
- else
- payload.contract.rules[ii].nh_set.hash_mode = GBP_API_HASH_MODE_DST_IP;
-
- const gbp_rule::next_hops_t& next_hops = it->nhs().getNextHops();
- u8 jj = 0, nh_size = (next_hops.size() > 8) ? 8 : next_hops.size();
- auto nh_it = next_hops.cbegin();
-
- payload.contract.rules[ii].nh_set.n_nhs = nh_size;
- while (jj < nh_size) {
- to_api(nh_it->getIp(), payload.contract.rules[ii].nh_set.nhs[jj].ip);
- to_api(nh_it->getMac(), payload.contract.rules[ii].nh_set.nhs[jj].mac);
- payload.contract.rules[ii].nh_set.nhs[jj].bd_id = nh_it->getBdId();
- payload.contract.rules[ii].nh_set.nhs[jj].rd_id = nh_it->getRdId();
- ++nh_it;
- ++jj;
- }
-
- ++it;
- ++ii;
+
+ uint32_t ii = 0;
+ payload.contract.n_rules = n_rules;
+
+ for (auto rule : m_gbp_rules) {
+ if (rule.action() == gbp_rule::action_t::REDIRECT)
+ payload.contract.rules[ii].action = GBP_API_RULE_REDIRECT;
+ else if (rule.action() == gbp_rule::action_t::PERMIT)
+ payload.contract.rules[ii].action = GBP_API_RULE_PERMIT;
+ else
+ payload.contract.rules[ii].action = GBP_API_RULE_DENY;
+
+ if (rule.nhs().hash_mode() == gbp_rule::hash_mode_t::SYMMETRIC)
+ payload.contract.rules[ii].nh_set.hash_mode = GBP_API_HASH_MODE_SYMMETRIC;
+ else if (rule.nhs().hash_mode() == gbp_rule::hash_mode_t::SRC_IP)
+ payload.contract.rules[ii].nh_set.hash_mode = GBP_API_HASH_MODE_SRC_IP;
+ else
+ payload.contract.rules[ii].nh_set.hash_mode = GBP_API_HASH_MODE_DST_IP;
+
+ const gbp_rule::next_hops_t& next_hops = rule.nhs().next_hops();
+ uint8_t jj = 0, nh_size = (next_hops.size() > 8) ? 8 : next_hops.size();
+
+ payload.contract.rules[ii].nh_set.n_nhs = nh_size;
+ for (auto nh : next_hops) {
+ to_api(nh.getIp(), payload.contract.rules[ii].nh_set.nhs[jj].ip);
+ to_api(nh.getMac(), payload.contract.rules[ii].nh_set.nhs[jj].mac);
+ payload.contract.rules[ii].nh_set.nhs[jj].bd_id = nh.getBdId();
+ payload.contract.rules[ii].nh_set.nhs[jj].rd_id = nh.getRdId();
+ jj++;
}
+ ++ii;
}
+
+ u8* data;
+ u16* et;
+
+ data = (((u8*)&payload.contract.n_ether_types) +
+ (sizeof(payload.contract.rules[0]) * payload.contract.n_rules));
+ *data = m_allowed_ethertypes.size();
+ et = (u16*)(++data);
+ ii = 0;
+ for (auto tt : m_allowed_ethertypes) {
+ et[ii] = tt.value();
+ ii++;
+ }
+
VAPI_CALL(req.execute());
return (wait());
@@ -124,7 +137,7 @@ delete_cmd::operator==(const delete_cmd& other) const
rc_t
delete_cmd::issue(connection& con)
{
- msg_t req(con.ctx(), 1, std::ref(*this));
+ msg_t req(con.ctx(), 0, 0, std::ref(*this));
auto& payload = req.get_request().get_payload();
payload.is_add = 0;
diff --git a/extras/vom/vom/gbp_contract_cmds.hpp b/extras/vom/vom/gbp_contract_cmds.hpp
index 4f921f6da94..476a594ae3e 100644
--- a/extras/vom/vom/gbp_contract_cmds.hpp
+++ b/extras/vom/vom/gbp_contract_cmds.hpp
@@ -37,7 +37,8 @@ public:
epg_id_t src_epg_id,
epg_id_t dst_epg_id,
const handle_t& acl,
- const gbp_contract::gbp_rules_t& gbp_rules);
+ const gbp_contract::gbp_rules_t& gbp_rules,
+ const gbp_contract::ethertype_set_t& allowed_ethertypes);
/**
* Issue the command to VPP/HW
@@ -59,6 +60,7 @@ private:
const epg_id_t m_dst_epg_id;
const handle_t m_acl;
const gbp_contract::gbp_rules_t& m_gbp_rules;
+ const gbp_contract::ethertype_set_t& m_allowed_ethertypes;
};
/**
diff --git a/extras/vom/vom/gbp_rule.cpp b/extras/vom/vom/gbp_rule.cpp
index 7aa799029ff..48c59b14c2b 100644
--- a/extras/vom/vom/gbp_rule.cpp
+++ b/extras/vom/vom/gbp_rule.cpp
@@ -105,6 +105,12 @@ gbp_rule::next_hop_set_t::next_hop_set_t(const gbp_rule::hash_mode_t& hm,
{
}
+gbp_rule::next_hop_set_t::next_hop_set_t(const hash_mode_t& hm)
+ : m_hm(hm)
+ , m_nhs()
+{
+}
+
std::string
gbp_rule::next_hop_set_t::to_string() const
{
@@ -128,13 +134,13 @@ gbp_rule::next_hop_set_t::operator==(const next_hop_set_t& nhs) const
}
const gbp_rule::hash_mode_t&
-gbp_rule::next_hop_set_t::getHashMode() const
+gbp_rule::next_hop_set_t::hash_mode() const
{
return m_hm;
}
const gbp_rule::next_hops_t&
-gbp_rule::next_hop_set_t::getNextHops() const
+gbp_rule::next_hop_set_t::next_hops() const
{
return m_nhs;
}
@@ -168,6 +174,13 @@ gbp_rule::gbp_rule(uint32_t priority,
{
}
+gbp_rule::gbp_rule(uint32_t priority, const gbp_rule::action_t& a)
+ : m_priority(priority)
+ , m_nhs()
+ , m_action(a)
+{
+}
+
bool
gbp_rule::operator<(const gbp_rule& other) const
{
@@ -193,12 +206,6 @@ gbp_rule::to_string() const
return (s.str());
}
-uint32_t
-gbp_rule::priority() const
-{
- return m_priority;
-}
-
const gbp_rule::action_t&
gbp_rule::action() const
{
diff --git a/extras/vom/vom/gbp_rule.hpp b/extras/vom/vom/gbp_rule.hpp
index bda040939fb..04301da79e9 100644
--- a/extras/vom/vom/gbp_rule.hpp
+++ b/extras/vom/vom/gbp_rule.hpp
@@ -147,6 +147,7 @@ public:
* Constructor for next_hop_set_t
*/
next_hop_set_t(const hash_mode_t& hm, next_hops_t& nhs);
+ next_hop_set_t(const hash_mode_t& hm = hash_mode_t::SYMMETRIC);
/**
* Destructor for next_hop_set_t
@@ -166,12 +167,12 @@ public:
/**
* get the hash mode
*/
- const hash_mode_t& getHashMode(void) const;
+ const hash_mode_t& hash_mode(void) const;
/**
* get the set of next hops
*/
- const next_hops_t& getNextHops(void) const;
+ const next_hops_t& next_hops(void) const;
private:
/**
@@ -218,6 +219,7 @@ public:
* Construct a new object matching the desried state
*/
gbp_rule(uint32_t priority, const next_hop_set_t& nhs, const action_t& a);
+ gbp_rule(uint32_t priority, const action_t& a);
/**
* Copy Constructor
@@ -235,8 +237,8 @@ public:
std::string to_string() const;
/**
- * less-than operator
- */
+ * less-than operator
+ */
bool operator<(const gbp_rule& rule) const;
/**
@@ -247,7 +249,6 @@ public:
/**
* Getters
*/
- uint32_t priority() const;
const next_hop_set_t& nhs() const;
const action_t& action() const;
diff --git a/src/plugins/gbp/gbp.api b/src/plugins/gbp/gbp.api
index bf7c167a42f..e96cb508387 100644
--- a/src/plugins/gbp/gbp.api
+++ b/src/plugins/gbp/gbp.api
@@ -295,6 +295,8 @@ typedef gbp_contract
u32 acl_index;
u8 n_rules;
vl_api_gbp_rule_t rules[n_rules];
+ u8 n_ether_types;
+ u16 allowed_ethertypes[n_ether_types];
};
autoreply define gbp_contract_add_del
diff --git a/src/plugins/gbp/gbp_api.c b/src/plugins/gbp/gbp_api.c
index 74355d1c033..8ea5a0e6d0a 100644
--- a/src/plugins/gbp/gbp_api.c
+++ b/src/plugins/gbp/gbp_api.c
@@ -924,8 +924,11 @@ static void
vl_api_gbp_contract_add_del_t_handler (vl_api_gbp_contract_add_del_t * mp)
{
vl_api_gbp_contract_add_del_reply_t *rmp;
+ u16 *allowed_ethertypes;
index_t *rules;
- int rv = 0;
+ int ii, rv = 0;
+ u8 *data, n_et;
+ u16 *et;
if (mp->is_add)
{
@@ -934,9 +937,28 @@ vl_api_gbp_contract_add_del_t_handler (vl_api_gbp_contract_add_del_t * mp)
if (0 != rv)
goto out;
+ allowed_ethertypes = NULL;
+
+ /*
+ * move past the variable legnth array of rules to get to the
+ * allowed ether types
+ */
+ data = (((u8 *) & mp->contract.n_ether_types) +
+ (sizeof (mp->contract.rules[0]) * mp->contract.n_rules));
+ n_et = *data;
+ et = (u16 *) (++data);
+ vec_validate (allowed_ethertypes, n_et - 1);
+
+ for (ii = 0; ii < n_et; ii++)
+ {
+ /* leave the ether types in network order */
+ allowed_ethertypes[ii] = et[ii];
+ }
+
rv = gbp_contract_update (ntohs (mp->contract.src_epg),
ntohs (mp->contract.dst_epg),
- ntohl (mp->contract.acl_index), rules);
+ ntohl (mp->contract.acl_index),
+ rules, allowed_ethertypes);
}
else
rv = gbp_contract_delete (ntohs (mp->contract.src_epg),
diff --git a/src/plugins/gbp/gbp_contract.c b/src/plugins/gbp/gbp_contract.c
index ee12a760f4b..f7b8b6474c5 100644
--- a/src/plugins/gbp/gbp_contract.c
+++ b/src/plugins/gbp/gbp_contract.c
@@ -434,7 +434,8 @@ gbp_contract_mk_lbs (index_t * guis)
int
gbp_contract_update (epg_id_t src_epg,
- epg_id_t dst_epg, u32 acl_index, index_t * rules)
+ epg_id_t dst_epg,
+ u32 acl_index, index_t * rules, u16 * allowed_ethertypes)
{
gbp_main_t *gm = &gbp_main;
u32 *acl_vec = NULL;
@@ -462,6 +463,7 @@ gbp_contract_update (epg_id_t src_epg,
gbp_contract_rules_free (gc->gc_rules);
gbp_main.acl_plugin.put_lookup_context_index (gc->gc_lc_index);
gc->gc_rules = NULL;
+ vec_free (gc->gc_allowed_ethertypes);
}
else
{
@@ -474,6 +476,7 @@ gbp_contract_update (epg_id_t src_epg,
GBP_CONTRACT_DBG ("update: %U", format_gbp_contract, gci);
gc->gc_rules = rules;
+ gc->gc_allowed_ethertypes = allowed_ethertypes;
gbp_contract_resolve (gc->gc_rules);
gbp_contract_mk_lbs (gc->gc_rules);
@@ -506,6 +509,7 @@ gbp_contract_delete (epg_id_t src_epg, epg_id_t dst_epg)
gbp_contract_rules_free (gc->gc_rules);
gbp_main.acl_plugin.put_lookup_context_index (gc->gc_lc_index);
+ vec_free (gc->gc_allowed_ethertypes);
hash_unset (gbp_contract_db.gc_hash, key.as_u32);
pool_put (gbp_contract_pool, gc);
@@ -561,7 +565,7 @@ gbp_contract_cli (vlib_main_t * vm,
if (add)
{
- gbp_contract_update (src_epg_id, dst_epg_id, acl_index, NULL);
+ gbp_contract_update (src_epg_id, dst_epg_id, acl_index, NULL, NULL);
}
else
{
@@ -604,6 +608,7 @@ format_gbp_contract (u8 * s, va_list * args)
index_t gci = va_arg (*args, index_t);
gbp_contract_t *gc;
index_t *gui;
+ u16 *et;
gc = gbp_contract_get (gci);
@@ -615,6 +620,14 @@ format_gbp_contract (u8 * s, va_list * args)
s = format (s, "\n %d: %U", *gui, format_gbp_rule, *gui);
}
+ s = format (s, "\n allowed-ethertypes:[");
+ vec_foreach (et, gc->gc_allowed_ethertypes)
+ {
+ int host_et = clib_net_to_host_u16 (*et);
+ s = format (s, "0x%x, ", host_et);
+ }
+ s = format (s, "]");
+
return (s);
}
diff --git a/src/plugins/gbp/gbp_contract.h b/src/plugins/gbp/gbp_contract.h
index bd7d8339e21..876c10f3702 100644
--- a/src/plugins/gbp/gbp_contract.h
+++ b/src/plugins/gbp/gbp_contract.h
@@ -120,6 +120,11 @@ typedef struct gbp_contract_t_
* The ACL to apply for packets from the source to the destination EPG
*/
index_t *gc_rules;
+
+ /**
+ * An ethertype whitelist
+ */
+ u16 *gc_allowed_ethertypes;
} gbp_contract_t;
/**
@@ -135,7 +140,8 @@ typedef struct gbp_contract_db_t_
extern int gbp_contract_update (epg_id_t src_epg,
epg_id_t dst_epg,
- u32 acl_index, index_t * rules);
+ u32 acl_index,
+ index_t * rules, u16 * allowed_ethertypes);
extern int gbp_contract_delete (epg_id_t src_epg, epg_id_t dst_epg);
extern index_t gbp_rule_alloc (gbp_rule_action_t action,
diff --git a/src/plugins/gbp/gbp_policy.c b/src/plugins/gbp/gbp_policy.c
index 3b204ff4da8..174223e09f7 100644
--- a/src/plugins/gbp/gbp_policy.c
+++ b/src/plugins/gbp/gbp_policy.c
@@ -106,6 +106,19 @@ gbp_rule_l2_redirect (const gbp_rule_t * gu, vlib_buffer_t * b0)
return (dpo->dpoi_next_node);
}
+always_inline u8
+gbp_policy_is_ethertype_allowed (const gbp_contract_t * gc0, u16 ethertype)
+{
+ u16 *et;
+
+ vec_foreach (et, gc0->gc_allowed_ethertypes)
+ {
+ if (*et == ethertype)
+ return (1);
+ }
+ return (0);
+}
+
static uword
gbp_policy_inline (vlib_main_t * vm,
vlib_node_runtime_t * node,
@@ -130,9 +143,9 @@ gbp_policy_inline (vlib_main_t * vm,
{
const ethernet_header_t *h0;
const gbp_endpoint_t *ge0;
+ const gbp_contract_t *gc0;
gbp_policy_next_t next0;
gbp_contract_key_t key0;
- gbp_contract_t *gc0;
u32 bi0, sw_if_index0;
vlib_buffer_t *b0;
index_t gci0;
@@ -204,66 +217,84 @@ gbp_policy_inline (vlib_main_t * vm,
if (INDEX_INVALID != gci0)
{
+ u32 rule_match_p0, trace_bitmap0;
fa_5tuple_opaque_t pkt_5tuple0;
- u8 action0 = 0;
u32 acl_pos_p0, acl_match_p0;
- u32 rule_match_p0, trace_bitmap0;
- u8 *h0, l2_len0;
+ u8 is_ip60, l2_len0, action0;
+ const gbp_rule_t *gu;
u16 ether_type0;
- u8 is_ip60 = 0;
+ const u8 *h0;
+ action0 = 0;
gc0 = gbp_contract_get (gci0);
l2_len0 = vnet_buffer (b0)->l2.l2_len;
h0 = vlib_buffer_get_current (b0);
- ether_type0 =
- clib_net_to_host_u16 (*(u16 *) (h0 + l2_len0 - 2));
-
- is_ip60 = (ether_type0 == ETHERNET_TYPE_IP6) ? 1 : 0;
- /*
- * tests against the ACL
- */
- acl_plugin_fill_5tuple_inline (gm->
- acl_plugin.p_acl_main,
- gc0->gc_lc_index, b0,
- is_ip60,
- /* is_input */ 0,
- /* is_l2_path */ 1,
- &pkt_5tuple0);
- acl_plugin_match_5tuple_inline (gm->
- acl_plugin.p_acl_main,
- gc0->gc_lc_index,
- &pkt_5tuple0, is_ip60,
- &action0, &acl_pos_p0,
- &acl_match_p0,
- &rule_match_p0,
- &trace_bitmap0);
-
- if (action0 > 0)
- {
- gbp_rule_t *gu;
+ ether_type0 = *(u16 *) (h0 + l2_len0 - 2);
- vnet_buffer2 (b0)->gbp.flags |= VXLAN_GBP_GPFLAGS_A;
- gu = gbp_rule_get (gc0->gc_rules[rule_match_p0]);
+ if (!gbp_policy_is_ethertype_allowed (gc0, ether_type0))
+ {
+ /*
+ * black list model so drop
+ */
+ goto trace;
+ }
- switch (gu->gu_action)
+ if ((ether_type0 ==
+ clib_net_to_host_u16 (ETHERNET_TYPE_IP6))
+ || (ether_type0 ==
+ clib_net_to_host_u16 (ETHERNET_TYPE_IP4)))
+ {
+ is_ip60 =
+ (ether_type0 ==
+ clib_net_to_host_u16 (ETHERNET_TYPE_IP6)) ? 1 :
+ 0;
+ /*
+ * tests against the ACL
+ */
+ acl_plugin_fill_5tuple_inline (gm->
+ acl_plugin.p_acl_main,
+ gc0->gc_lc_index, b0,
+ is_ip60,
+ /* is_input */ 0,
+ /* is_l2_path */ 1,
+ &pkt_5tuple0);
+ acl_plugin_match_5tuple_inline (gm->
+ acl_plugin.p_acl_main,
+ gc0->gc_lc_index,
+ &pkt_5tuple0,
+ is_ip60, &action0,
+ &acl_pos_p0,
+ &acl_match_p0,
+ &rule_match_p0,
+ &trace_bitmap0);
+
+ if (action0 > 0)
{
- case GBP_RULE_PERMIT:
- next0 = vnet_l2_feature_next
- (b0,
- gpm->l2_output_feat_next
- [is_port_based],
- (is_port_based ?
- L2OUTPUT_FEAT_GBP_POLICY_PORT :
- L2OUTPUT_FEAT_GBP_POLICY_MAC));
- break;
- case GBP_RULE_DENY:
- ASSERT (0);
- next0 = 0;
- break;
- case GBP_RULE_REDIRECT:
- next0 = gbp_rule_l2_redirect (gu, b0);
- break;
+ vnet_buffer2 (b0)->gbp.flags |=
+ VXLAN_GBP_GPFLAGS_A;
+ gu =
+ gbp_rule_get (gc0->gc_rules[rule_match_p0]);
+
+ switch (gu->gu_action)
+ {
+ case GBP_RULE_PERMIT:
+ next0 = vnet_l2_feature_next
+ (b0,
+ gpm->l2_output_feat_next
+ [is_port_based],
+ (is_port_based ?
+ L2OUTPUT_FEAT_GBP_POLICY_PORT :
+ L2OUTPUT_FEAT_GBP_POLICY_MAC));
+ break;
+ case GBP_RULE_DENY:
+ ASSERT (0);
+ next0 = 0;
+ break;
+ case GBP_RULE_REDIRECT:
+ next0 = gbp_rule_l2_redirect (gu, b0);
+ break;
+ }
}
}
}
diff --git a/test/test_gbp.py b/test/test_gbp.py
index 2297c49ffa1..718bbb4d4c9 100644
--- a/test/test_gbp.py
+++ b/test/test_gbp.py
@@ -24,6 +24,7 @@ from scapy.layers.inet6 import IPv6, ICMPv6ND_NS, ICMPv6NDOptSrcLLAddr, \
ICMPv6ND_NA
from scapy.utils6 import in6_getnsma, in6_getnsmac
from scapy.layers.vxlan import VXLAN
+from scapy.data import ETH_P_IP, ETH_P_IPV6
from socket import AF_INET, AF_INET6
from scapy.utils import inet_pton, inet_ntop
@@ -438,12 +439,14 @@ class VppGbpContract(VppObject):
GBP Contract
"""
- def __init__(self, test, src_epg, dst_epg, acl_index, rules=[]):
+ def __init__(self, test, src_epg, dst_epg, acl_index,
+ rules, allowed_ethertypes):
self._test = test
self.acl_index = acl_index
self.src_epg = src_epg
self.dst_epg = dst_epg
self.rules = rules
+ self.allowed_ethertypes = allowed_ethertypes
def add_vpp_config(self):
rules = []
@@ -454,7 +457,8 @@ class VppGbpContract(VppObject):
self.src_epg,
self.dst_epg,
self.acl_index,
- rules)
+ rules,
+ self.allowed_ethertypes)
self._test.registry.register(self, self._test.logger)
def remove_vpp_config(self):
@@ -463,7 +467,7 @@ class VppGbpContract(VppObject):
self.src_epg,
self.dst_epg,
self.acl_index,
- [])
+ [], [])
def __str__(self):
return self.object_id()
@@ -1140,7 +1144,8 @@ class TestGBP(VppTestCase):
[]),
VppGbpContractRule(
VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- [])])
+ [])],
+ [ETH_P_IP, ETH_P_IPV6])
c1.add_vpp_config()
self.send_and_expect_bridged(eps[0].itf,
@@ -1159,8 +1164,8 @@ class TestGBP(VppTestCase):
[]),
VppGbpContractRule(
VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- [])])
-
+ [])],
+ [ETH_P_IP, ETH_P_IPV6])
c2.add_vpp_config()
self.send_and_expect_bridged(eps[0].itf,
@@ -1171,6 +1176,15 @@ class TestGBP(VppTestCase):
eps[0].itf)
#
+ # the contract does not allow non-IP
+ #
+ pkt_non_ip_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
+ dst=self.pg2.remote_mac) /
+ ARP())
+ self.send_and_assert_no_replies(eps[0].itf,
+ pkt_non_ip_inter_epg_220_to_221 * 17)
+
+ #
# check that inter group is still disabled for the groups
# not in the contract.
#
@@ -1187,8 +1201,8 @@ class TestGBP(VppTestCase):
[]),
VppGbpContractRule(
VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- [])])
-
+ [])],
+ [ETH_P_IP, ETH_P_IPV6])
c3.add_vpp_config()
self.logger.info(self.vapi.cli("sh gbp contract"))
@@ -1292,8 +1306,8 @@ class TestGBP(VppTestCase):
[]),
VppGbpContractRule(
VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- [])])
-
+ [])],
+ [ETH_P_IP, ETH_P_IPV6])
c4.add_vpp_config()
self.send_and_expect_natted(eps[0].itf,
@@ -1333,8 +1347,8 @@ class TestGBP(VppTestCase):
[]),
VppGbpContractRule(
VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- [])])
-
+ [])],
+ [ETH_P_IP, ETH_P_IPV6])
c5.add_vpp_config()
self.send_and_expect_unnatted(self.pg7,
@@ -1739,8 +1753,8 @@ class TestGBP(VppTestCase):
[]),
VppGbpContractRule(
VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- [])])
-
+ [])],
+ [ETH_P_IP, ETH_P_IPV6])
c1.add_vpp_config()
for l in learnt:
@@ -2654,7 +2668,8 @@ class TestGBP(VppTestCase):
[VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
sep3.ip6, sep3.epg.rd),
VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
- sep4.ip6, sep4.epg.rd)])])
+ sep4.ip6, sep4.epg.rd)])],
+ [ETH_P_IP, ETH_P_IPV6])
c1.add_vpp_config()
c2 = VppGbpContract(
@@ -2672,7 +2687,8 @@ class TestGBP(VppTestCase):
[VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
sep3.ip6, sep3.epg.rd),
VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
- sep4.ip6, sep4.epg.rd)])])
+ sep4.ip6, sep4.epg.rd)])],
+ [ETH_P_IP, ETH_P_IPV6])
c2.add_vpp_config()
#
@@ -2784,7 +2800,8 @@ class TestGBP(VppTestCase):
[VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
sep3.ip6, sep3.epg.rd),
VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
- sep4.ip6, sep4.epg.rd)])])
+ sep4.ip6, sep4.epg.rd)])],
+ [ETH_P_IP, ETH_P_IPV6])
c1.add_vpp_config()
c2 = VppGbpContract(
@@ -2802,7 +2819,8 @@ class TestGBP(VppTestCase):
[VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
sep3.ip6, sep3.epg.rd),
VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
- sep4.ip6, sep4.epg.rd)])])
+ sep4.ip6, sep4.epg.rd)])],
+ [ETH_P_IP, ETH_P_IPV6])
c2.add_vpp_config()
#
@@ -2852,21 +2870,22 @@ class TestGBP(VppTestCase):
Raw('\xa5' * 100))]
c3 = VppGbpContract(
- self, 220, 221, acl_index,
- [VppGbpContractRule(
+ self, 220, 221, acl_index,
+ [VppGbpContractRule(
+ VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
+ VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
+ [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
+ sep1.ip4, sep1.epg.rd),
+ VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
+ sep2.ip4, sep2.epg.rd)]),
+ VppGbpContractRule(
VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
- [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
- sep1.ip4, sep1.epg.rd),
- VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
- sep2.ip4, sep2.epg.rd)]),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
- [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
- sep3.ip6, sep3.epg.rd),
- VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
- sep4.ip6, sep4.epg.rd)])])
+ [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
+ sep3.ip6, sep3.epg.rd),
+ VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
+ sep4.ip6, sep4.epg.rd)])],
+ [ETH_P_IP, ETH_P_IPV6])
c3.add_vpp_config()
rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
@@ -2892,7 +2911,8 @@ class TestGBP(VppTestCase):
[]),
VppGbpContractRule(
VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- [])])
+ [])],
+ [ETH_P_IP, ETH_P_IPV6])
c4.add_vpp_config()
p = (Ether(src=self.pg7.remote_mac,
@@ -2977,7 +2997,8 @@ class TestGBP(VppTestCase):
[VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
sep3.ip6, sep3.epg.rd),
VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
- sep4.ip6, sep4.epg.rd)])])
+ sep4.ip6, sep4.epg.rd)])],
+ [ETH_P_IP, ETH_P_IPV6])
c5.add_vpp_config()
rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
@@ -3273,7 +3294,8 @@ class TestGBP(VppTestCase):
[]),
VppGbpContractRule(
VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- [])])
+ [])],
+ [ETH_P_IP, ETH_P_IPV6])
c1.add_vpp_config()
rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
diff --git a/test/vpp_papi_provider.py b/test/vpp_papi_provider.py
index 55bf7ed39cb..828f0302db1 100644
--- a/test/vpp_papi_provider.py
+++ b/test/vpp_papi_provider.py
@@ -3713,7 +3713,8 @@ class VppPapiProvider(object):
return self.api(self.papi.gbp_subnet_dump,
{'_no_type_conversion': True})
- def gbp_contract_add_del(self, is_add, src_epg, dst_epg, acl_index, rules):
+ def gbp_contract_add_del(self, is_add, src_epg, dst_epg, acl_index,
+ rules, allowed_ethertypes):
""" GBP contract Add/Del """
return self.api(self.papi.gbp_contract_add_del,
{'is_add': is_add,
@@ -3722,7 +3723,9 @@ class VppPapiProvider(object):
'src_epg': src_epg,
'dst_epg': dst_epg,
'n_rules': len(rules),
- 'rules': rules}})
+ 'rules': rules,
+ 'n_ether_types': len(allowed_ethertypes),
+ 'allowed_ethertypes': allowed_ethertypes}})
def gbp_contract_dump(self):
""" GBP contract Dump """