Skip to content

Commit

Permalink
* Agent changes to support fat flow
Browse files Browse the repository at this point in the history
* Maintain a list of protocol and port specified as fat flow
  Ignore flow matching protocol + port combination.
Closes-bug:#1518234

Conflicts:
	src/vnsw/agent/oper/test/test_intf.cc
	src/vnsw/agent/oper/vm_interface.cc

Change-Id: Iaa9b14f74276ca011906bff89b03841049acd4f4
  • Loading branch information
naveen-n authored and haripk committed Nov 27, 2015
1 parent a316f05 commit 6722f56
Show file tree
Hide file tree
Showing 13 changed files with 320 additions and 6 deletions.
21 changes: 21 additions & 0 deletions src/vnsw/agent/cmn/agent.cc
Expand Up @@ -655,6 +655,27 @@ void Agent::SetAgentMcastLabelRange(uint8_t idx) {
label_range_[idx] = str.str();
}

uint16_t
Agent::ProtocolStringToInt(const std::string &proto) {
if (proto == "tcp" || proto == "TCP") {
return IPPROTO_TCP;
}

if (proto == "udp" || proto == "UDP") {
return IPPROTO_UDP;
}

if (proto == "sctp" || proto == "SCTP") {
return IPPROTO_SCTP;
}

if (proto =="icmp" || proto == "ICMP") {
return IPPROTO_ICMP;
}

return atoi(proto.c_str());
}

Agent::ForwardingMode Agent::TranslateForwardingMode
(const std::string &mode) const {
if (mode == "l2")
Expand Down
2 changes: 2 additions & 0 deletions src/vnsw/agent/cmn/agent.h
Expand Up @@ -7,6 +7,7 @@

#include <vector>
#include <stdint.h>
#include <string>
#include <net/ethernet.h>
#include <boost/intrusive_ptr.hpp>
#include <cmn/agent_cmn.h>
Expand Down Expand Up @@ -916,6 +917,7 @@ class Agent {
flow_stats_req_handler_ = req;
}

static uint16_t ProtocolStringToInt(const std::string &str);
private:

AgentParam *params_;
Expand Down
41 changes: 41 additions & 0 deletions src/vnsw/agent/oper/test/test_intf.cc
Expand Up @@ -165,6 +165,19 @@ class IntfTest : public ::testing::Test {
client->WaitForIdle();
}

void AddFatFlow(struct PortInfo *input, std::string protocol, int port) {

ostringstream str;

str << "<virtual-machine-interface-fat-flow-protocols>"
"<fat-flow-protocol>"
"<protocol>" << protocol << "</protocol>"
"<port>" << port << "</port>"
"</fat-flow-protocol>"
"</virtual-machine-interface-fat-flow-protocols>";
AddNode("virtual-machine-interface", input[0].name, input[0].intf_id,
str.str().c_str());
}

unsigned int intf_count;
Agent *agent;
Expand Down Expand Up @@ -3248,6 +3261,34 @@ TEST_F(IntfTest, IntfAddDel) {
client->Reset();
}

TEST_F(IntfTest, FatFlow) {
struct PortInfo input[] = {
{"vnet1", 1, "1.1.1.1", "00:00:00:00:00:01", 1, 1},
};

CreateVmportEnv(input, 1);
client->WaitForIdle();
EXPECT_TRUE(VmPortFind(1));

const VmInterface *intf = static_cast<const VmInterface *>(VmPortGet(1));
EXPECT_TRUE(intf->fat_flow_list().list_.size() == 0);

AddFatFlow(input, "udp", 53);
client->WaitForIdle();
EXPECT_TRUE(intf->fat_flow_list().list_.size() == 1);
EXPECT_TRUE(intf->IsFatFlow(IPPROTO_UDP, 53) == true);
EXPECT_TRUE(intf->IsFatFlow(IPPROTO_UDP, 0) == false);

DelNode("virtual-machine-interface", "vnet1");
client->WaitForIdle();
EXPECT_TRUE(intf->fat_flow_list().list_.size() == 0);

DeleteVmportEnv(input, 1, true);
client->WaitForIdle();
EXPECT_FALSE(VmPortFind(1));
client->Reset();
}

int main(int argc, char **argv) {
GETUSERARGS();

Expand Down
61 changes: 58 additions & 3 deletions src/vnsw/agent/oper/vm_interface.cc
Expand Up @@ -60,7 +60,7 @@ VmInterface::VmInterface(const boost::uuids::uuid &uuid) :
tx_vlan_id_(kInvalidVlanId), rx_vlan_id_(kInvalidVlanId), parent_(NULL),
local_preference_(VmInterface::INVALID), oper_dhcp_options_(),
sg_list_(), floating_ip_list_(), service_vlan_list_(), static_route_list_(),
allowed_address_pair_list_(), vrf_assign_rule_list_(),
allowed_address_pair_list_(), fat_flow_list_(), vrf_assign_rule_list_(),
vrf_assign_acl_(NULL), vm_ip_gw_addr_(0), vm_ip6_gw_addr_(),
device_type_(VmInterface::DEVICE_TYPE_INVALID),
vmi_type_(VmInterface::VMI_TYPE_INVALID),
Expand Down Expand Up @@ -408,6 +408,18 @@ static void BuildVrfAndServiceVlanInfo(Agent *agent,
return;
}

static void BuildFatFlowTable(Agent *agent, 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);
data->fat_flow_list_.list_.insert(VmInterface::FatFlowEntry(protocol,
it->port));
}
}

static void BuildInstanceIp(Agent *agent, VmInterfaceConfigData *data,
IFMapNode *node) {
InstanceIp *ip = static_cast<InstanceIp *>(node->GetObject());
Expand Down Expand Up @@ -798,6 +810,14 @@ bool VmInterface::IsConfigurerSet(VmInterface::Configurer type) {
return ((configurer_ & (1 << type)) != 0);
}

bool VmInterface::IsFatFlow(uint8_t protocol, uint16_t port) const {
if (fat_flow_list_.list_.find(FatFlowEntry(protocol, port)) !=
fat_flow_list_.list_.end()) {
return true;
}
return false;
}

static bool DeleteVmi(InterfaceTable *table, const uuid &u, DBRequest *req) {
int type = table->GetVmiToVmiType(u);
if (type <= (int)VmInterface::VMI_TYPE_INVALID)
Expand Down Expand Up @@ -903,6 +923,7 @@ bool InterfaceTable::VmiProcessConfig(IFMapNode *node, DBRequest &req) {
}

UpdateAttributes(agent_, data);
BuildFatFlowTable(agent_, data, node);

// Get DHCP enable flag from subnet
if (vn_node && data->addr_.to_ulong()) {
Expand Down Expand Up @@ -1331,10 +1352,12 @@ void VmInterface::ApplyConfigCommon(const VrfEntry *old_vrf,
//DHCP MAC IP binding
ApplyMacVmBindingConfig(old_vrf, old_l2_active, old_dhcp_enable);
//Security Group update
if (IsActive())
if (IsActive()) {
UpdateSecurityGroup();
else
} else {
DeleteSecurityGroup();
DeleteFatFlow();
}

}

Expand Down Expand Up @@ -1729,6 +1752,16 @@ bool VmInterface::CopyConfig(const InterfaceTable *table,
ret = true;
}

FatFlowEntrySet &old_fat_flow_entry_list = fat_flow_list_.list_;
const FatFlowEntrySet &new_fat_flow_entry_list =
data->fat_flow_list_.list_;
if (AuditList<FatFlowList, FatFlowEntrySet::iterator>
(fat_flow_list_, old_fat_flow_entry_list.begin(),
old_fat_flow_entry_list.end(), new_fat_flow_entry_list.begin(),
new_fat_flow_entry_list.end())) {
ret = true;
}

InstanceIpSet &old_ipv4_list = instance_ipv4_list_.list_;
InstanceIpSet new_ipv4_list = data->instance_ipv4_list_.list_;
//Native ip of instance should be advertised even if
Expand Down Expand Up @@ -2916,6 +2949,16 @@ void VmInterface::DeleteSecurityGroup() {
}
}

void VmInterface::DeleteFatFlow() {
FatFlowEntrySet::iterator it = fat_flow_list_.list_.begin();
while (it != fat_flow_list_.list_.end()) {
FatFlowEntrySet::iterator prev = it++;
if (prev->del_pending_) {
fat_flow_list_.list_.erase(prev);
}
}
}

void VmInterface::UpdateL2TunnelId(bool force_update, bool policy_change) {
AllocL2MplsLabel(force_update, policy_change);
}
Expand Down Expand Up @@ -3298,6 +3341,18 @@ void VmInterface::InstanceIpList::Remove(InstanceIpSet::iterator &it) {
it->set_del_pending(true);
}

void VmInterface::FatFlowList::Insert(const FatFlowEntry *rhs) {
list_.insert(*rhs);
}

void VmInterface::FatFlowList::Update(const FatFlowEntry *lhs,
const FatFlowEntry *rhs) {
}

void VmInterface::FatFlowList::Remove(FatFlowEntrySet::iterator &it) {
it->set_del_pending(true);
}

/////////////////////////////////////////////////////////////////////////////
// FloatingIp routines
/////////////////////////////////////////////////////////////////////////////
Expand Down
45 changes: 45 additions & 0 deletions src/vnsw/agent/oper/vm_interface.h
Expand Up @@ -354,6 +354,43 @@ class VmInterface : public Interface {
InstanceIpSet list_;
};

struct FatFlowEntry : ListEntry {
FatFlowEntry(): protocol(0), port(0) {}
FatFlowEntry(const FatFlowEntry &rhs):
protocol(rhs.protocol), port(rhs.port) {}
FatFlowEntry(const uint8_t proto, const uint16_t p):
protocol(proto), port(p) {}
virtual ~FatFlowEntry(){}
bool operator == (const FatFlowEntry &rhs) const {
return (rhs.protocol == protocol && rhs.port == port);
}

bool operator() (const FatFlowEntry &lhs,
const FatFlowEntry &rhs) const {
return lhs.IsLess(&rhs);
}

bool IsLess(const FatFlowEntry *rhs) const {
if (protocol != rhs->protocol) {
return protocol < rhs->protocol;
}
return port < rhs->port;
}
uint8_t protocol;
uint16_t port;
};
typedef std::set<FatFlowEntry, FatFlowEntry> FatFlowEntrySet;

struct FatFlowList {
FatFlowList(): list_() {}
~FatFlowList() {};
void Insert(const FatFlowEntry *rhs);
void Update(const FatFlowEntry *lhs, const FatFlowEntry *rhs);
void Remove(FatFlowEntrySet::iterator &it);

FatFlowEntrySet list_;
};

enum Trace {
ADD,
DELETE,
Expand Down Expand Up @@ -471,6 +508,11 @@ class VmInterface : public Interface {
return instance_ipv6_list_;
}

const FatFlowList &fat_flow_list() const {
return fat_flow_list_;
}

bool IsFatFlow(uint8_t protocol, uint16_t port) const;
void set_vxlan_id(int vxlan_id) { vxlan_id_ = vxlan_id; }
void set_subnet_bcast_addr(const Ip4Address &addr) {
subnet_bcast_addr_ = addr;
Expand Down Expand Up @@ -685,6 +727,7 @@ class VmInterface : public Interface {
void DeleteAllowedAddressPair(bool l2);
void UpdateSecurityGroup();
void DeleteSecurityGroup();
void DeleteFatFlow();
void UpdateL2TunnelId(bool force_update, bool policy_change);
void DeleteL2TunnelId();
void DeleteL2InterfaceRoute(bool old_l2_active, VrfEntry *old_vrf,
Expand Down Expand Up @@ -754,6 +797,7 @@ class VmInterface : public Interface {
AllowedAddressPairList allowed_address_pair_list_;
InstanceIpList instance_ipv4_list_;
InstanceIpList instance_ipv6_list_;
FatFlowList fat_flow_list_;

// Peer for interface routes
std::auto_ptr<LocalVmPortPeer> peer_;
Expand Down Expand Up @@ -914,6 +958,7 @@ struct VmInterfaceConfigData : public VmInterfaceData {
VmInterface::AllowedAddressPairList allowed_address_pair_list_;
VmInterface::InstanceIpList instance_ipv4_list_;
VmInterface::InstanceIpList instance_ipv6_list_;
VmInterface::FatFlowList fat_flow_list_;
VmInterface::DeviceType device_type_;
VmInterface::VmiType vmi_type_;
// Parent physical-interface. Used in VMWare/ ToR logical-interface
Expand Down
48 changes: 48 additions & 0 deletions src/vnsw/agent/pkt/pkt_flow_info.cc
Expand Up @@ -1018,6 +1018,7 @@ void PktFlowInfo::IngressProcess(const PktInfo *pkt, PktControlInfo *in,
return;
}

CalculatePort(pkt, in->intf_);
// We always expect route for source-ip for ingress flows.
// If route not present, return from here so that a short flow is added
UpdateRoute(&in->rt_, in->vrf_, pkt->ip_saddr, pkt->smac,
Expand Down Expand Up @@ -1150,6 +1151,7 @@ void PktFlowInfo::EgressProcess(const PktInfo *pkt, PktControlInfo *in,
}

if (out->intf_ && out->intf_->type() == Interface::VM_INTERFACE) {
CalculatePort(pkt, out->intf_);
const VmInterface *vm_intf = static_cast<const VmInterface *>(out->intf_);
if (vm_intf->IsFloatingIp(pkt->ip_daddr)) {
pkt->l3_forwarding = true;
Expand Down Expand Up @@ -1338,11 +1340,57 @@ bool PktFlowInfo::Process(const PktInfo *pkt, PktControlInfo *in,
return true;
}

//Mask source port or destination port if a port has fat flow
//configuration. If both source port and destination port are
//present in configuration then the lowest of the port takes
//priority
void PktFlowInfo::CalculatePort(const PktInfo *cpkt, const Interface *in) {
const VmInterface *intf = NULL;
PktInfo *pkt = const_cast<PktInfo *>(cpkt);

if (in == NULL || in->type() != Interface::VM_INTERFACE) {
return;
}

intf = static_cast<const VmInterface *>(in);
if (intf->fat_flow_list().list_.size() == 0) {
return;
}

uint16_t sport = pkt->sport;
if (pkt->ip_proto == IPPROTO_ICMP) {
sport = 0;
}
if (pkt->sport < pkt->dport) {
if (intf->IsFatFlow(pkt->ip_proto, sport)) {
pkt->dport = 0;
return;
}

if (intf->IsFatFlow(pkt->ip_proto, pkt->dport)) {
pkt->sport = 0;
return;
}
return;
}

if (intf->IsFatFlow(pkt->ip_proto, pkt->dport)) {
pkt->sport = 0;
return;
}

if (intf->IsFatFlow(pkt->ip_proto, sport)) {
pkt->dport = 0;
return;
}
}

void PktFlowInfo::Add(const PktInfo *pkt, PktControlInfo *in,
PktControlInfo *out) {
FlowKey key(in->nh_, pkt->ip_saddr, pkt->ip_daddr, pkt->ip_proto,
pkt->sport, pkt->dport);
FlowEntryPtr flow;

if (pkt->type != PktType::MESSAGE) {
flow = Agent::GetInstance()->pkt()->flow_table()->Allocate(key);
} else {
Expand Down
3 changes: 1 addition & 2 deletions src/vnsw/agent/pkt/pkt_flow_info.h
Expand Up @@ -90,13 +90,12 @@ class PktFlowInfo {
bool UnknownUnicastFlow(const PktInfo *p,
const PktControlInfo *in_info,
const PktControlInfo *out_info);

public:
void UpdateRoute(const AgentRoute **rt, const VrfEntry *vrf,
const IpAddress &addr, const MacAddress &mac,
FlowRouteRefMap &ref_map);
uint8_t RouteToPrefixLen(const AgentRoute *route);

void CalculatePort(const PktInfo *p, const Interface *intf);
bool l3_flow;
Address::Family family;
boost::shared_ptr<PktInfo> pkt;
Expand Down

0 comments on commit 6722f56

Please sign in to comment.