GBP: add allowed ethertypes to contracts

Change-Id: I74782d3b9b71a071bb500c34866a017b8ee15767
Signed-off-by: Neale Ranns <nranns@cisco.com>
This commit is contained in:
Neale Ranns
2018-12-20 12:03:59 -08:00
parent fc7344f9be
commit 1c17e2ecac
13 changed files with 323 additions and 179 deletions

View File

@ -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();
}
}

View File

@ -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
*/

View File

@ -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;

View File

@ -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;
};
/**

View File

@ -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
{

View File

@ -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;

View File

@ -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

View File

@ -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),

View File

@ -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);
}

View File

@ -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,

View File

@ -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;
}
}
}
}

View File

@ -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)

View File

@ -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 """