Skip to content

Commit

Permalink
ECMP load balance configuration agent changes.
Browse files Browse the repository at this point in the history
ECMP load balance parameters can be configured at global, vn and interface level.
Priority (highest to lowest)- Interface, VN, Global.
This config is stored in path. When path is exported to controller, fields in
load-balance-fields are populated using the same. Agent currently provides field
based hashing only. So every controller message will have load-balance-type set
to field-hash. Similarly reflected routes from CN will be used to extract fields
to be used for hashing and populated in respective path.
Agent by default will use all fields.

Closes-bug: 1498765

Conflicts:
	src/vnsw/agent/controller/controller_peer.cc
	src/vnsw/agent/openstack/instance_service_server.cc
	src/vnsw/agent/oper/inet_unicast_route.cc
	src/vnsw/agent/oper/metadata_ip.cc
	src/vnsw/agent/oper/vm_interface.cc
	src/vnsw/agent/test/test_util.cc

Change-Id: I652f65b5b6b56fe20e26a0a0bb7cdf6799b98811
  • Loading branch information
manishsing committed Jan 18, 2016
1 parent ac0ac8a commit f6dd3dc
Show file tree
Hide file tree
Showing 29 changed files with 585 additions and 81 deletions.
14 changes: 8 additions & 6 deletions src/schema/vnc_cfg.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -807,9 +807,6 @@ targetNamespace="http://www.contrailsystems.com/2012/VNC-CONFIG/0">
<xsd:element name='forwarding-mode' type='ForwardingModeType'/>
<!-- Enable or disable unicast RPF for virtual-network -->
<xsd:element name='rpf' type='RpfModeType'/>
<!-- Ecmp nexthop load balance criterias -->
<xsd:element name='ecmp-hashing-include-fields'
type='EcmpHashingIncludeFields'/>
</xsd:all>
</xsd:complexType>

Expand All @@ -833,6 +830,10 @@ targetNamespace="http://www.contrailsystems.com/2012/VNC-CONFIG/0">
<!--#IFMAP-SEMANTICS-IDL
Property('virtual-network-properties', 'virtual-network') -->

<!-- Ecmp nexthop load balance criterias -->
<!--#IFMAP-SEMANTICS-IDL
Property('ecmp-hashing-include-fields', 'virtual-network') -->

<xsd:element name="provider-properties" type="ProviderDetails"/>
<!--#IFMAP-SEMANTICS-IDL
Property('provider-properties', 'virtual-network') -->
Expand Down Expand Up @@ -1054,9 +1055,6 @@ targetNamespace="http://www.contrailsystems.com/2012/VNC-CONFIG/0">
<xsd:element name='interface-mirror' type="InterfaceMirrorType"/>
<xsd:element name="local-preference" type="xsd:integer"/>
<xsd:element name="sub-interface-vlan-tag" type="xsd:integer"/>
<!-- Ecmp nexthop load balance criterias -->
<xsd:element name='ecmp-hashing-include-fields'
type='EcmpHashingIncludeFields'/>
</xsd:all>
</xsd:complexType>

Expand All @@ -1077,6 +1075,10 @@ targetNamespace="http://www.contrailsystems.com/2012/VNC-CONFIG/0">
</xsd:all>
</xsd:complexType>

<!-- Ecmp nexthop load balance criterias -->
<!--#IFMAP-SEMANTICS-IDL
Property('ecmp-hashing-include-fields', 'virtual-machine-interface') -->

<xsd:element name="virtual-machine-interface-properties"
type="VirtualMachineInterfacePropertiesType"/>
<!--#IFMAP-SEMANTICS-IDL
Expand Down
10 changes: 8 additions & 2 deletions src/vnsw/agent/controller/controller_export.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <boost/uuid/uuid_io.hpp>

#include <cmn/agent_cmn.h>
#include <oper/ecmp_load_balance.h>
#include <oper/route_common.h>
#include <oper/peer.h>
#include <oper/nexthop.h>
Expand All @@ -22,7 +23,7 @@ RouteExport::State::State() :
DBState(), exported_(false), fabric_multicast_exported_(false),
force_chg_(false), label_(MplsTable::kInvalidLabel), vn_(), sg_list_(),
tunnel_type_(TunnelType::INVALID), path_preference_(),
destination_(), source_() {
destination_(), source_(), ecmp_load_balance_() {
}

bool RouteExport::State::Changed(const AgentRoute *route, const AgentPath *path) const {
Expand Down Expand Up @@ -51,6 +52,9 @@ bool RouteExport::State::Changed(const AgentRoute *route, const AgentPath *path)
if (path_preference_ != path->path_preference())
return true;

if(ecmp_load_balance_ != path->ecmp_load_balance())
return true;

return false;
}

Expand All @@ -62,6 +66,7 @@ void RouteExport::State::Update(const AgentRoute *route, const AgentPath *path)
communities_ = path->communities();
tunnel_type_ = path->tunnel_type();
path_preference_ = path->path_preference();
ecmp_load_balance_ = path->ecmp_load_balance();
}

RouteExport::RouteExport(AgentRouteTable *rt_table):
Expand Down Expand Up @@ -180,7 +185,8 @@ void RouteExport::UnicastNotify(AgentXmppChannel *bgp_xmpp_peer,
path->NexthopIp(table->agent()), vn_list,
state->label_, path->GetTunnelBmap(),
&path->sg_list(), &path->communities(),
type, state->path_preference_);
type, state->path_preference_,
state->ecmp_load_balance_);
}
} else {
if (state->exported_ == true) {
Expand Down
2 changes: 2 additions & 0 deletions src/vnsw/agent/controller/controller_export.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <oper/agent_path.h>

class AgentPath;
class EcmpLoadBalance;

class RouteExport {
public:
Expand All @@ -32,6 +33,7 @@ class RouteExport {
//destination and source are valid for tunnel NH.
std::string destination_;
std::string source_;
EcmpLoadBalance ecmp_load_balance_;

bool Changed(const AgentRoute *route, const AgentPath *path) const;
void Update(const AgentRoute *route, const AgentPath *path);
Expand Down
70 changes: 64 additions & 6 deletions src/vnsw/agent/controller/controller_peer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "oper/peer.h"
#include "oper/vxlan.h"
#include "oper/agent_path.h"
#include "oper/ecmp_load_balance.h"
#include "cmn/agent_stats.h"
#include <pugixml/pugixml.hpp>
#include "xml/xml_pugi.h"
Expand Down Expand Up @@ -604,9 +605,45 @@ void AgentXmppChannel::ReceiveV4V6Update(XmlPugi *pugi) {
}
}

static void GetEcmpHashFieldsToUse(ItemType *item,
EcmpLoadBalance &ecmp_load_balance) {
if (item->entry.load_balance.load_balance_decision.empty() ||
item->entry.load_balance.load_balance_decision !=
LoadBalanceDecision)
ecmp_load_balance.SetAll();

uint8_t field_list_size = item->entry.
load_balance.load_balance_fields.load_balance_field_list.size();
if (field_list_size == 0)
ecmp_load_balance.SetAll();

for (uint32_t i = 0; i < field_list_size; i++) {
std::string field_type = item->entry.
load_balance.load_balance_fields.load_balance_field_list[i];
if (field_type == ecmp_load_balance.source_mac_str())
ecmp_load_balance.set_source_mac();
if (field_type == ecmp_load_balance.destination_mac_str())
ecmp_load_balance.set_destination_mac();
if (field_type == ecmp_load_balance.source_ip_str())
ecmp_load_balance.set_source_ip();
if (field_type == ecmp_load_balance.destination_ip_str())
ecmp_load_balance.set_destination_ip();
if (field_type == ecmp_load_balance.ip_protocol_str())
ecmp_load_balance.set_ip_protocol();
if (field_type == ecmp_load_balance.source_port_str())
ecmp_load_balance.set_source_port();
if (field_type == ecmp_load_balance.destination_port_str())
ecmp_load_balance.set_destination_port();
}
}

void AgentXmppChannel::AddEcmpRoute(string vrf_name, IpAddress prefix_addr,
uint32_t prefix_len, ItemType *item,
const VnListType &vn_list) {
//Extract the load balancer fields.
EcmpLoadBalance ecmp_load_balance;
GetEcmpHashFieldsToUse(item, ecmp_load_balance);

PathPreference::Preference preference = PathPreference::LOW;
TunnelType::TypeBmap encap = TunnelType::MplsType(); //default
if (item->entry.local_preference == PathPreference::HIGH) {
Expand Down Expand Up @@ -690,7 +727,7 @@ void AgentXmppChannel::AddEcmpRoute(string vrf_name, IpAddress prefix_addr,
new ControllerEcmpRoute(bgp_peer_id(), prefix_addr, prefix_len,
vn_list, -1, false, vrf_name,
item->entry.security_group_list.security_group,
rp, encap, nh_req);
rp, encap, ecmp_load_balance, nh_req);

//ECMP create component NH
rt_table->AddRemoteVmRouteReq(bgp_peer_id(), vrf_name,
Expand Down Expand Up @@ -902,6 +939,8 @@ void AgentXmppChannel::AddEvpnRoute(const std::string &vrf_name,
ControllerLocalVmRoute *local_vm_route = NULL;
VnListType vn_list;
vn_list.insert(item->entry.virtual_network);
EcmpLoadBalance ecmp_load_balance;

if (encap == TunnelType::VxlanType()) {
local_vm_route =
new ControllerLocalVmRoute(intf_key,
Expand All @@ -910,6 +949,7 @@ void AgentXmppChannel::AddEvpnRoute(const std::string &vrf_name,
InterfaceNHFlags::BRIDGE,
sg_list, path_preference,
unicast_sequence_number(),
ecmp_load_balance,
this);
} else {
local_vm_route =
Expand All @@ -920,6 +960,7 @@ void AgentXmppChannel::AddEvpnRoute(const std::string &vrf_name,
InterfaceNHFlags::BRIDGE,
sg_list, path_preference,
unicast_sequence_number(),
ecmp_load_balance,
this);
}
rt_table->AddLocalVmRouteReq(bgp_peer_id(), vrf_name, mac,
Expand Down Expand Up @@ -990,6 +1031,7 @@ void AgentXmppChannel::AddRemoteRoute(string vrf_name, IpAddress prefix_addr,

VmInterfaceKey intf_key(AgentKey::ADD_DEL_CHANGE,
intf_nh->GetIfUuid(), "");
EcmpLoadBalance ecmp_load_balance;
BgpPeer *bgp_peer = bgp_peer_id();
if (interface->type() == Interface::VM_INTERFACE) {
ControllerLocalVmRoute *local_vm_route =
Expand All @@ -1000,6 +1042,7 @@ void AgentXmppChannel::AddRemoteRoute(string vrf_name, IpAddress prefix_addr,
item->entry.security_group_list.security_group,
path_preference,
unicast_sequence_number(),
ecmp_load_balance,
this);
rt_table->AddLocalVmRouteReq(bgp_peer, vrf_name,
prefix_addr, prefix_len,
Expand Down Expand Up @@ -1750,6 +1793,17 @@ bool AgentXmppChannel::ControllerSendSubscribe(AgentXmppChannel *peer,
return true;
}

void PopulateEcmpHashFieldsToUse(ItemType &item,
const EcmpLoadBalance &ecmp_load_balance) {
item.entry.load_balance.load_balance_decision = LoadBalanceDecision;

if (ecmp_load_balance.AllSet())
return;

ecmp_load_balance.GetStringVector(
item.entry.load_balance.load_balance_fields.load_balance_field_list);
}

bool AgentXmppChannel::ControllerSendV4V6UnicastRouteCommon(AgentRoute *route,
const VnListType &vn_list,
const SecurityGroupList *sg_list,
Expand All @@ -1758,7 +1812,8 @@ bool AgentXmppChannel::ControllerSendV4V6UnicastRouteCommon(AgentRoute *route,
TunnelType::TypeBmap bmap,
const PathPreference &path_preference,
bool associate,
Agent::RouteTableType type) {
Agent::RouteTableType type,
const EcmpLoadBalance &ecmp_load_balance) {

static int id = 0;
ItemType item;
Expand All @@ -1781,6 +1836,7 @@ bool AgentXmppChannel::ControllerSendV4V6UnicastRouteCommon(AgentRoute *route,

string rtr(agent_->router_id().to_string());

PopulateEcmpHashFieldsToUse(item, ecmp_load_balance);
autogen::NextHopType nh;
nh.af = BgpAf::IPv4;
nh.address = rtr;
Expand Down Expand Up @@ -2412,8 +2468,8 @@ bool AgentXmppChannel::ControllerSendRouteAdd(AgentXmppChannel *peer,
const SecurityGroupList *sg_list,
const CommunityList *communities,
Agent::RouteTableType type,
const PathPreference
&path_preference)
const PathPreference &path_preference,
const EcmpLoadBalance &ecmp_load_balance)
{
if (!peer) return false;

Expand All @@ -2428,7 +2484,7 @@ bool AgentXmppChannel::ControllerSendRouteAdd(AgentXmppChannel *peer,
ret = peer->ControllerSendV4V6UnicastRouteCommon(route, vn_list,
sg_list, communities, label,
bmap, path_preference, true,
type);
type, ecmp_load_balance);
}
if (type == Agent::EVPN) {
std::string vn = *vn_list.begin();
Expand Down Expand Up @@ -2461,13 +2517,15 @@ bool AgentXmppChannel::ControllerSendRouteDelete(AgentXmppChannel *peer,
bool ret = false;
if (((type == Agent::INET4_UNICAST) || (type == Agent::INET6_UNICAST)) &&
(peer->agent()->simulate_evpn_tor() == false)) {
EcmpLoadBalance ecmp_load_balance;
ret = peer->ControllerSendV4V6UnicastRouteCommon(route, vn_list,
sg_list, communities,
label,
bmap,
path_preference,
false,
type);
type,
ecmp_load_balance);
}
if (type == Agent::EVPN) {
Ip4Address nh_ip(0);
Expand Down
7 changes: 5 additions & 2 deletions src/vnsw/agent/controller/controller_peer.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class VrfEntry;
class XmlPugi;
class PathPreference;
class AgentPath;
class EcmpLoadBalance;

class AgentXmppChannel {
public:
Expand Down Expand Up @@ -73,7 +74,8 @@ class AgentXmppChannel {
const SecurityGroupList *sg_list,
const CommunityList *communities,
Agent::RouteTableType type,
const PathPreference &path_preference);
const PathPreference &path_preference,
const EcmpLoadBalance &ecmp_load_balance);
static bool ControllerSendEvpnRouteAdd(AgentXmppChannel *peer,
AgentRoute *route,
const Ip4Address *nexthop_ip,
Expand Down Expand Up @@ -189,7 +191,8 @@ class AgentXmppChannel {
uint32_t tunnel_bmap,
const PathPreference &path_preference,
bool associate,
Agent::RouteTableType type);
Agent::RouteTableType type,
const EcmpLoadBalance &ecmp_load_balance);
bool BuildTorMulticastMessage(autogen::EnetItemType &item,
std::stringstream &node_id,
AgentRoute *route,
Expand Down
5 changes: 4 additions & 1 deletion src/vnsw/agent/controller/controller_route_path.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <route/route.h>

#include <cmn/agent_cmn.h>
#include <oper/ecmp_load_balance.h>
#include <oper/route_common.h>
#include <oper/vrf.h>
#include <oper/tunnel_nh.h>
Expand Down Expand Up @@ -72,6 +73,7 @@ bool ControllerEcmpRoute::AddChangePath(Agent *agent, AgentPath *path,
vrf_name_, sg_list_,
path_preference_,
tunnel_bmap_,
ecmp_load_balance_,
nh_req_, agent, path);
}

Expand Down Expand Up @@ -249,10 +251,11 @@ ControllerLocalVmRoute::ControllerLocalVmRoute(const VmInterfaceKey &intf,
const SecurityGroupList &sg_list,
const PathPreference &path_preference,
uint64_t sequence_number,
const EcmpLoadBalance &ecmp_load_balance,
const AgentXmppChannel *channel) :
LocalVmRoute(intf, mpls_label, vxlan_id, force_policy, vn_list, flags, sg_list,
CommunityList(),
path_preference, Ip4Address(0)),
path_preference, Ip4Address(0), ecmp_load_balance),
sequence_number_(sequence_number), channel_(channel) { }

bool ControllerLocalVmRoute::IsPeerValid(const AgentRouteKey *key) const {
Expand Down
7 changes: 6 additions & 1 deletion src/vnsw/agent/controller/controller_route_path.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
//Forward declaration
class AgentXmppChannel;
class AgentRouteData;
class EcmpLoadBalance;
class Peer;
class BgpPeer;
class TunnelNHKey;
Expand Down Expand Up @@ -127,11 +128,13 @@ class ControllerEcmpRoute : public ControllerPeerPath {
const string &vrf_name, SecurityGroupList sg_list,
const PathPreference &path_preference,
TunnelType::TypeBmap tunnel_bmap,
const EcmpLoadBalance &ecmp_load_balance,
DBRequest &nh_req) :
ControllerPeerPath(peer), dest_addr_(dest_addr), plen_(plen),
vn_list_(vn_list), label_(label), local_ecmp_nh_(local_ecmp_nh),
vrf_name_(vrf_name), sg_list_(sg_list),
path_preference_(path_preference), tunnel_bmap_(tunnel_bmap)
path_preference_(path_preference), tunnel_bmap_(tunnel_bmap),
ecmp_load_balance_(ecmp_load_balance)
{nh_req_.Swap(&nh_req);}

virtual ~ControllerEcmpRoute() { }
Expand All @@ -150,6 +153,7 @@ class ControllerEcmpRoute : public ControllerPeerPath {
SecurityGroupList sg_list_;
PathPreference path_preference_;
TunnelType::TypeBmap tunnel_bmap_;
EcmpLoadBalance ecmp_load_balance_;
DBRequest nh_req_;
DISALLOW_COPY_AND_ASSIGN(ControllerEcmpRoute);
};
Expand All @@ -167,6 +171,7 @@ class ControllerLocalVmRoute : public LocalVmRoute {
const SecurityGroupList &sg_list,
const PathPreference &path_preference,
uint64_t sequence_number,
const EcmpLoadBalance &ecmp_load_balance,
const AgentXmppChannel *channel);
virtual ~ControllerLocalVmRoute() { }
virtual bool IsPeerValid(const AgentRouteKey *key) const;
Expand Down
5 changes: 4 additions & 1 deletion src/vnsw/agent/openstack/instance_service_server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <oper/vm.h>
#include <oper/vn.h>
#include <oper/mirror_table.h>
#include <oper/ecmp_load_balance.h>
#include <cfg/cfg_types.h>
#include <openstack/instance_service_server.h>
#include <base/contrail_ports.h>
Expand Down Expand Up @@ -422,11 +423,13 @@ InstanceServiceAsyncHandler::AddLocalVmRoute(const std::string& ip_address,

VnListType vn_list;
vn_list.insert("instance-service");
EcmpLoadBalance ecmp_load_balance;
agent_->fabric_inet4_unicast_table()->
AddLocalVmRouteReq(novaPeer_.get(), vrf, ip.to_v4(), 32, intf_uuid,
vn_list, mpls_label, SecurityGroupList(),
CommunityList(),
false, PathPreference(), Ip4Address(0));
false, PathPreference(), Ip4Address(0),
ecmp_load_balance);
return true;
}

Expand Down

0 comments on commit f6dd3dc

Please sign in to comment.