Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Initial agent changes for fat flow enhancements for R5.1
  - Data structure changes
  - Validation of config
  - Storing config in VmInterface object
  - Unit test cases

Change-Id: Ie84e5ff38253aa4b53a86bda8d7d91b74951ea22
Partial-Bug: #1752618
  • Loading branch information
anandrao79 committed Sep 8, 2018
1 parent 385d087 commit fce65a4
Show file tree
Hide file tree
Showing 7 changed files with 540 additions and 85 deletions.
329 changes: 281 additions & 48 deletions src/vnsw/agent/oper/test/test_intf.cc

Large diffs are not rendered by default.

122 changes: 121 additions & 1 deletion src/vnsw/agent/oper/vm_interface.cc
Expand Up @@ -716,9 +716,115 @@ bool VmInterface::SecurityGroupEntry::DeleteL3(const Agent *agent,
// any new states
/////////////////////////////////////////////////////////////////////////////
VmInterface::FatFlowEntry::FatFlowEntry(const uint8_t proto, const uint16_t p,
std::string ignore_addr_value) :
std::string ignore_addr_value,
FatFlowPrefixAggregateType in_prefix_aggregate,
IpAddress in_src_prefix, uint8_t in_src_prefix_mask,
uint8_t in_src_aggregate_plen,
IpAddress in_dst_prefix, uint8_t in_dst_prefix_mask,
uint8_t in_dst_aggregate_plen) :
protocol(proto), port(p) {
ignore_address = fatflow_ignore_addr_map_.find(ignore_addr_value)->second;
prefix_aggregate = in_prefix_aggregate;
src_prefix = in_src_prefix;
src_prefix_mask = in_src_prefix_mask;
src_aggregate_plen = in_src_aggregate_plen;
dst_prefix = in_dst_prefix;
dst_prefix_mask = in_dst_prefix_mask;
dst_aggregate_plen = in_dst_aggregate_plen;
}


VmInterface::FatFlowEntry
VmInterface::FatFlowEntry::MakeFatFlowEntry(const std::string &proto, const int &port,
const std::string &ignore_addr_str,
const std::string &in_src_prefix_str, const int &in_src_prefix_mask,
const int &in_src_aggregate_plen,
const std::string &in_dst_prefix_str, const int &in_dst_prefix_mask,
const int &in_dst_aggregate_plen) {
uint8_t protocol = (uint8_t) Agent::ProtocolStringToInt(proto);
IpAddress src_prefix;
uint8_t src_prefix_mask = 0, src_aggregate_plen = 0;
IpAddress dst_prefix, empty_prefix;
uint8_t dst_prefix_mask = 0, dst_aggregate_plen = 0;
FatFlowPrefixAggregateType prefix_aggregate = AGGREGATE_NONE;
FatFlowIgnoreAddressType ignore_address =
fatflow_ignore_addr_map_.find(ignore_addr_str)->second;

if (in_src_prefix_str.length() > 0) {
src_prefix = IpAddress::from_string(in_src_prefix_str);
src_prefix_mask = in_src_prefix_mask;
src_aggregate_plen = in_src_aggregate_plen;
if (src_prefix.is_v4()) {
prefix_aggregate = AGGREGATE_SRC_IPV4;
} else {
prefix_aggregate = AGGREGATE_SRC_IPV6;
}
}
if (in_dst_prefix_str.length() > 0) {
dst_prefix = IpAddress::from_string(in_dst_prefix_str);
dst_prefix_mask = in_dst_prefix_mask;
dst_aggregate_plen = in_dst_aggregate_plen;
if (prefix_aggregate == AGGREGATE_NONE) {
if (dst_prefix.is_v4()) {
prefix_aggregate = AGGREGATE_DST_IPV4;
} else {
prefix_aggregate = AGGREGATE_DST_IPV6;
}
} else {
if (dst_prefix.is_v4()) {
prefix_aggregate = AGGREGATE_SRC_DST_IPV4;
} else {
prefix_aggregate = AGGREGATE_SRC_DST_IPV6;
}
}
}
if (ignore_address == IGNORE_SOURCE) {
if ((prefix_aggregate == AGGREGATE_SRC_IPV4) || (prefix_aggregate == AGGREGATE_SRC_IPV6)) {
src_prefix = empty_prefix;
src_prefix_mask = 0;
src_aggregate_plen = 0;
prefix_aggregate = AGGREGATE_NONE;
} else if (prefix_aggregate == AGGREGATE_SRC_DST_IPV4) {
src_prefix = empty_prefix;
src_prefix_mask = 0;
src_aggregate_plen = 0;
prefix_aggregate = AGGREGATE_DST_IPV4;
} else if (prefix_aggregate == AGGREGATE_SRC_DST_IPV6) {
src_prefix = empty_prefix;
src_prefix_mask = 0;
src_aggregate_plen = 0;
prefix_aggregate = AGGREGATE_DST_IPV6;
}
} else if (ignore_address == IGNORE_DESTINATION) {
if ((prefix_aggregate == AGGREGATE_DST_IPV4) || (prefix_aggregate == AGGREGATE_DST_IPV6)) {
dst_prefix = empty_prefix;
dst_prefix_mask = 0;
dst_aggregate_plen = 0;
prefix_aggregate = AGGREGATE_NONE;
} else if (prefix_aggregate == AGGREGATE_SRC_DST_IPV4) {
dst_prefix = empty_prefix;
dst_prefix_mask = 0;
dst_aggregate_plen = 0;
prefix_aggregate = AGGREGATE_SRC_IPV4;
} else if (prefix_aggregate == AGGREGATE_SRC_DST_IPV6) {
dst_prefix = empty_prefix;
dst_prefix_mask = 0;
dst_aggregate_plen = 0;
prefix_aggregate = AGGREGATE_SRC_IPV6;
}
}

VmInterface::FatFlowEntry entry(protocol, port,
ignore_addr_str, prefix_aggregate, src_prefix, src_prefix_mask,
src_aggregate_plen, dst_prefix, dst_prefix_mask, dst_aggregate_plen);
return entry;
}

void VmInterface::FatFlowEntry::print(void) {
LOG(ERROR, "Protocol:" << (int) protocol << " Port:" << port << " IgnoreAddr:" << ignore_address
<< " PrefixAggr:" << prefix_aggregate << " SrcPrefix:" << src_prefix.to_string() << "/" << (int) src_prefix_mask
<< " SrcAggrPlen:" << (int) src_aggregate_plen << " DstPrefix:" << dst_prefix.to_string() << "/" << (int) dst_prefix_mask
<< " DstAggrPlen:" << (int) dst_aggregate_plen);
}

void VmInterface::FatFlowList::Insert(const FatFlowEntry *rhs) {
Expand All @@ -728,12 +834,26 @@ void VmInterface::FatFlowList::Insert(const FatFlowEntry *rhs) {
*/
if (ret.second == false) {
ret.first->ignore_address = rhs->ignore_address;
ret.first->prefix_aggregate = rhs->prefix_aggregate;
ret.first->src_prefix = rhs->src_prefix;
ret.first->src_prefix_mask = rhs->src_prefix_mask;
ret.first->src_aggregate_plen = rhs->src_aggregate_plen;
ret.first->dst_prefix = rhs->dst_prefix;
ret.first->dst_prefix_mask = rhs->dst_prefix_mask;
ret.first->dst_aggregate_plen = rhs->dst_aggregate_plen;
}
}

void VmInterface::FatFlowList::Update(const FatFlowEntry *lhs,
const FatFlowEntry *rhs) {
lhs->ignore_address = rhs->ignore_address;
lhs->prefix_aggregate = rhs->prefix_aggregate;
lhs->src_prefix = rhs->src_prefix;
lhs->src_prefix_mask = rhs->src_prefix_mask;
lhs->src_aggregate_plen = rhs->src_aggregate_plen;
lhs->dst_prefix = rhs->dst_prefix;
lhs->dst_prefix_mask = rhs->dst_prefix_mask;
lhs->dst_aggregate_plen = rhs->dst_aggregate_plen;
}

void VmInterface::FatFlowList::Remove(FatFlowEntrySet::iterator &it) {
Expand Down
67 changes: 60 additions & 7 deletions src/vnsw/agent/oper/vm_interface.h
Expand Up @@ -425,6 +425,27 @@ class VmInterface : public Interface {
IGNORE_DESTINATION
};

enum FatFlowPrefixAggregateType {
AGGREGATE_NONE = 0,
AGGREGATE_SRC_IPV4,
AGGREGATE_SRC_IPV6,
AGGREGATE_DST_IPV4,
AGGREGATE_DST_IPV6,
AGGREGATE_SRC_DST_IPV4,
AGGREGATE_SRC_DST_IPV6
};

struct FatFlowLkupResult {
FatFlowIgnoreAddressType ignore_address;
FatFlowPrefixAggregateType prefix_aggregate;
IpAddress src_prefix;
uint8_t src_prefix_mask;
uint8_t src_aggregate_plen;
IpAddress dst_prefix;
uint8_t dst_prefix_mask;
uint8_t dst_aggregate_plen;
};

typedef std::map<Ip4Address, MetaDataIp*> MetaDataIpMap;
typedef std::set<HealthCheckInstanceBase *> HealthCheckInstanceSet;

Expand Down Expand Up @@ -916,19 +937,43 @@ class VmInterface : public Interface {

struct FatFlowEntry : ListEntry {
FatFlowEntry(): protocol(0), port(0),
ignore_address(IGNORE_NONE) {}
ignore_address(IGNORE_NONE), prefix_aggregate(AGGREGATE_NONE),
src_prefix(), src_prefix_mask(0), src_aggregate_plen(0),
dst_prefix(), dst_prefix_mask(0), dst_aggregate_plen(0) {}

FatFlowEntry(const FatFlowEntry &rhs):
protocol(rhs.protocol), port(rhs.port),
ignore_address(rhs.ignore_address) {}
ignore_address(rhs.ignore_address), prefix_aggregate(rhs.prefix_aggregate),
src_prefix(rhs.src_prefix), src_prefix_mask(rhs.src_prefix_mask), src_aggregate_plen(rhs.src_aggregate_plen),
dst_prefix(rhs.dst_prefix), dst_prefix_mask(rhs.dst_prefix_mask), dst_aggregate_plen(rhs.dst_aggregate_plen) {}

FatFlowEntry(const uint8_t proto, const uint16_t p) :
protocol(proto), port(p),
ignore_address(IGNORE_NONE) {}
ignore_address(IGNORE_NONE),
prefix_aggregate(AGGREGATE_NONE),
src_prefix(), src_prefix_mask(0), src_aggregate_plen(0),
dst_prefix(), dst_prefix_mask(0), dst_aggregate_plen(0) { }

FatFlowEntry(const uint8_t proto, const uint16_t p,
std::string ignore_addr);
std::string ignore_addr, FatFlowPrefixAggregateType prefix_aggregate,
IpAddress src_prefix, uint8_t src_prefix_mask, uint8_t src_aggregate_plen,
IpAddress dst_prefix, uint8_t dst_prefix_mask, uint8_t dst_aggregate_plen);

static FatFlowEntry MakeFatFlowEntry(const std::string &protocol, const int &port,
const std::string &ignore_addr_str,
const std::string &src_prefix_str, const int &src_prefix_mask,
const int &src_aggregate_plen,
const std::string &dst_prefix_str, const int &dst_prefix_mask,
const int &dst_aggregate_plen);

virtual ~FatFlowEntry(){}
bool operator == (const FatFlowEntry &rhs) const {
return (rhs.protocol == protocol && rhs.port == port &&
rhs.ignore_address == ignore_address);
rhs.ignore_address == ignore_address && rhs.prefix_aggregate == prefix_aggregate &&
rhs.src_prefix == src_prefix && rhs.src_prefix_mask == src_prefix_mask &&
rhs.src_aggregate_plen == src_aggregate_plen &&
rhs.dst_prefix == dst_prefix && rhs.dst_prefix_mask == dst_prefix_mask &&
rhs.dst_aggregate_plen == dst_aggregate_plen);
}

bool operator() (const FatFlowEntry &lhs,
Expand All @@ -942,9 +987,18 @@ class VmInterface : public Interface {
}
return port < rhs->port;
}
void print(void);

uint8_t protocol;
uint16_t port;
mutable FatFlowIgnoreAddressType ignore_address;
mutable FatFlowPrefixAggregateType prefix_aggregate;
mutable IpAddress src_prefix;
mutable uint8_t src_prefix_mask;
mutable uint8_t src_aggregate_plen;
mutable IpAddress dst_prefix;
mutable uint8_t dst_prefix_mask;
mutable uint8_t dst_aggregate_plen;
};
typedef std::set<FatFlowEntry, FatFlowEntry> FatFlowEntrySet;

Expand Down Expand Up @@ -1244,8 +1298,7 @@ class VmInterface : public Interface {
const FatFlowList &fat_flow_list() const {
return fat_flow_list_;
}
bool IsFatFlow(uint8_t protocol, uint16_t port,
VmInterface::FatFlowIgnoreAddressType *ignore_addr) const;
bool IsFatFlow(uint8_t protocol, uint16_t port, FatFlowLkupResult *) const;
bool ExcludeFromFatFlow(Address::Family family, const IpAddress &sip,
const IpAddress &dip) const;

Expand Down
64 changes: 53 additions & 11 deletions src/vnsw/agent/oper/vm_interface_config.cc
Expand Up @@ -537,16 +537,53 @@ static void BuildProxyArpFlags(Agent *agent, VmInterfaceConfigData *data,
data->proxy_arp_mode_ = VmInterface::PROXY_ARP_UNRESTRICTED;
}

static void BuildFatFlowTable(Agent *agent, VmInterfaceConfigData *data,
IFMapNode *node) {
static bool ValidateFatFlowCfg(const boost::uuids::uuid &u, const ProtocolType *pt)
{
if (pt->source_prefix.ip_prefix.length() > 0) {
if (pt->source_aggregate_prefix_length < pt->source_prefix.ip_prefix_len) {
LOG(ERROR, "FatFlowCfg validation failed for VMI uuid:" << u << " Protocol:" << pt->protocol
<< " Port:" << pt->port << " src aggr plen is less than src mask\n");
return false;
}
}
if (pt->destination_prefix.ip_prefix.length() > 0) {
if (pt->destination_aggregate_prefix_length < pt->destination_prefix.ip_prefix_len) {
LOG(ERROR, "FatFlowCfg validation failed for VMI uuid:" << u << " Protocol:" << pt->protocol
<< " Port:" << pt->port << " dst aggr plen is less than dst mask\n");
return false;
}
}
if ((pt->source_prefix.ip_prefix.length() > 0) &&
(pt->destination_prefix.ip_prefix.length() > 0)) {
IpAddress ip_src = IpAddress::from_string(pt->source_prefix.ip_prefix);
IpAddress ip_dst = IpAddress::from_string(pt->destination_prefix.ip_prefix);
if ((ip_src.is_v4() && ip_dst.is_v6()) ||
(ip_src.is_v6() && ip_dst.is_v4())) {
LOG(ERROR, "FatFlowCfg validation failed for VMI uuid:" << u << " Protocol:" << pt->protocol
<< " Port:" << pt->port << " src and dst addr family mismatch\n");
return false;
}
}
return true;
}

static void BuildFatFlowTable(Agent *agent, const boost::uuids::uuid &u,
VmInterfaceConfigData *data, IFMapNode *node) {
VirtualMachineInterface *cfg = static_cast <VirtualMachineInterface *>
(node->GetObject());

for (FatFlowProtocols::const_iterator it = cfg->fat_flow_protocols().begin();
it != cfg->fat_flow_protocols().end(); it++) {
uint16_t protocol = Agent::ProtocolStringToInt(it->protocol);
VmInterface::FatFlowEntry entry(protocol, it->port,
it->ignore_address);
data->fat_flow_list_.Insert(&entry);
if (!ValidateFatFlowCfg(u, &(*it))) {
continue;
}
VmInterface::FatFlowEntry e = VmInterface::FatFlowEntry::MakeFatFlowEntry(it->protocol, it->port,
it->ignore_address, it->source_prefix.ip_prefix,
it->source_prefix.ip_prefix_len,
it->source_aggregate_prefix_length, it->destination_prefix.ip_prefix,
it->destination_prefix.ip_prefix_len,
it->destination_aggregate_prefix_length);
data->fat_flow_list_.Insert(&e);
}
}

Expand Down Expand Up @@ -945,10 +982,15 @@ static void BuildVn(VmInterfaceConfigData *data,
/* Copy fat-flow configured at VN level */
for (FatFlowProtocols::const_iterator it = vn->fat_flow_protocols().begin();
it != vn->fat_flow_protocols().end(); it++) {
uint16_t protocol = Agent::ProtocolStringToInt(it->protocol);
VmInterface::FatFlowEntry fentry(protocol, it->port,
it->ignore_address);
data->fat_flow_list_.Insert(&fentry);
if (!ValidateFatFlowCfg(u, &(*it))) {
continue;
}
VmInterface::FatFlowEntry e = VmInterface::FatFlowEntry::MakeFatFlowEntry(it->protocol, it->port, it->ignore_address,
it->source_prefix.ip_prefix, it->source_prefix.ip_prefix_len,
it->source_aggregate_prefix_length, it->destination_prefix.ip_prefix,
it->destination_prefix.ip_prefix_len,
it->destination_aggregate_prefix_length);
data->fat_flow_list_.Insert(&e);
}
IFMapAgentTable *table = static_cast<IFMapAgentTable *>(node->table());
for (DBGraphVertex::adjacency_iterator iter =
Expand Down Expand Up @@ -1643,7 +1685,7 @@ bool InterfaceTable::VmiProcessConfig(IFMapNode *node, DBRequest &req,
agent_->oper_db()->bgp_as_a_service()->ProcessConfig
(data->vrf_name_, bgp_router_node_list, bgp_as_a_service_node_list, u);
UpdateAttributes(agent_, data);
BuildFatFlowTable(agent_, data, node);
BuildFatFlowTable(agent_, u, data, node);

// Get DHCP enable flag from subnet
if (vn_node && data->addr_.to_ulong()) {
Expand Down
12 changes: 9 additions & 3 deletions src/vnsw/agent/oper/vm_interface_utils.cc
Expand Up @@ -838,13 +838,19 @@ const Peer *VmInterface::peer() const {
return peer_.get();
}

bool VmInterface::IsFatFlow(uint8_t protocol, uint16_t port,
VmInterface::FatFlowIgnoreAddressType *ignore_addr)
bool VmInterface::IsFatFlow(uint8_t protocol, uint16_t port, FatFlowLkupResult *res)
const {
FatFlowEntrySet::iterator it = fat_flow_list_.list_.
find(FatFlowEntry(protocol, port));
if (it != fat_flow_list_.list_.end()) {
*ignore_addr = it->ignore_address;
res->ignore_address = it->ignore_address;
res->prefix_aggregate = it->prefix_aggregate;
res->src_prefix = it->src_prefix;
res->src_prefix_mask = it->src_prefix_mask;
res->src_aggregate_plen = it->src_aggregate_plen;
res->dst_prefix = it->dst_prefix;
res->dst_prefix_mask = it->dst_prefix_mask;
res->dst_aggregate_plen = it->dst_aggregate_plen;
return true;
}
return false;
Expand Down
6 changes: 3 additions & 3 deletions src/vnsw/agent/pkt/pkt_flow_info.cc
Expand Up @@ -784,14 +784,14 @@ void PktFlowInfo::ProcessHealthCheckFatFlow(const VmInterface *vmi,
const PktInfo *pkt,
PktControlInfo *in,
PktControlInfo *out) {
VmInterface::FatFlowIgnoreAddressType ignore_addr;
VmInterface::FatFlowLkupResult res;

// Health check valid for IPv4 only
if (pkt->ip_daddr.is_v4() == false || pkt->ip_saddr.is_v4() == false)
return;

// Ensure fat-flow is configured for the port first
if (vmi->IsFatFlow(pkt->ip_proto, pkt->sport, &ignore_addr) ==
false)
if (vmi->IsFatFlow(pkt->ip_proto, pkt->sport, &res) == false)
return;

// Look for health-check rule
Expand Down

0 comments on commit fce65a4

Please sign in to comment.