GBP: add allowed ethertypes to contracts
Change-Id: I74782d3b9b71a071bb500c34866a017b8ee15767 Signed-off-by: Neale Ranns <nranns@cisco.com>
This commit is contained in:
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,12 +106,6 @@ gbp_contract::to_string() const
|
||||
return (s.str());
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -41,12 +41,19 @@ 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
|
||||
@ -184,6 +186,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
|
||||
*/
|
||||
|
@ -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;
|
||||
uint32_t ii = 0;
|
||||
payload.contract.n_rules = n_rules;
|
||||
|
||||
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();
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
|
||||
++it;
|
||||
++ii;
|
||||
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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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),
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
{
|
||||
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;
|
||||
fa_5tuple_opaque_t pkt_5tuple0;
|
||||
u32 acl_pos_p0, acl_match_p0;
|
||||
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));
|
||||
ether_type0 = *(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)
|
||||
if (!gbp_policy_is_ethertype_allowed (gc0, ether_type0))
|
||||
{
|
||||
gbp_rule_t *gu;
|
||||
/*
|
||||
* black list model so drop
|
||||
*/
|
||||
goto trace;
|
||||
}
|
||||
|
||||
vnet_buffer2 (b0)->gbp.flags |= VXLAN_GBP_GPFLAGS_A;
|
||||
gu = gbp_rule_get (gc0->gc_rules[rule_match_p0]);
|
||||
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);
|
||||
|
||||
switch (gu->gu_action)
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
@ -1170,6 +1175,15 @@ class TestGBP(VppTestCase):
|
||||
pkt_inter_epg_221_to_220 * 65,
|
||||
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)
|
||||
|
@ -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 """
|
||||
|
Reference in New Issue
Block a user