Skip to content

Commit

Permalink
Support for Ecmp configured hash in Agent
Browse files Browse the repository at this point in the history
Ecmp hash fields are consolidated after going through all the routes
pointing to ECMP Nexthop.
The fields are selected based on most common fields pointing to ECMP
Next hop by all the routes.
After selecting the fields same will be used for configuring the
Vrouter.

Change-Id: I47092af68e95dd8491c0f8ac511c85971de945f7
partial-bug: #1616814
  • Loading branch information
jayaramsatya committed Oct 24, 2016
1 parent 1319ca0 commit 2748209
Show file tree
Hide file tree
Showing 12 changed files with 392 additions and 9 deletions.
6 changes: 6 additions & 0 deletions src/vnsw/agent/controller/controller_route_path.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ bool ControllerEcmpRoute::AddChangePath(Agent *agent, AgentPath *path,
if (!comp_nh_policy) {
comp_key->SetPolicy(new_comp_nh_policy);
}

if (path->ecmp_load_balance() != ecmp_load_balance_) {
path->UpdateEcmpHashFields(agent, ecmp_load_balance_,
nh_req_);
}

return InetUnicastRouteEntry::ModifyEcmpPath(dest_addr_, plen_, vn_list_,
label_, local_ecmp_nh_,
vrf_name_, sg_list_,
Expand Down
24 changes: 24 additions & 0 deletions src/vnsw/agent/oper/agent_path.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1399,3 +1399,27 @@ bool MacVmBindingPathData::AddChangePath(Agent *agent, AgentPath *path,

return ret;
}

void AgentPath::UpdateEcmpHashFields(const Agent *agent,
const EcmpLoadBalance &ecmp_load_balance,
DBRequest &nh_req) {

NextHop *nh = NULL;
nh = static_cast<NextHop *>(agent->nexthop_table()->
FindActiveEntry(nh_req.key.get()));
CompositeNH *cnh = dynamic_cast< CompositeNH *>(nh);
if (cnh) {
ecmp_hash_fields_.CalculateChangeInEcmpFields(ecmp_load_balance,
cnh->CompEcmpHashFields());
} else {
agent->nexthop_table()->Process(nh_req);
nh = static_cast<NextHop *>(agent->nexthop_table()->
FindActiveEntry(nh_req.key.get()));
CompositeNH *cnh = static_cast< CompositeNH *>(nh);
if (cnh) {
ecmp_hash_fields_.CalculateChangeInEcmpFields(ecmp_load_balance,
cnh->CompEcmpHashFields());
}
}
}

8 changes: 7 additions & 1 deletion src/vnsw/agent/oper/agent_path.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
#include <oper/agent_route.h>
#include <oper/mpls.h>
#include <oper/vxlan.h>

//Forward declaration
class AgentXmppChannel;
class InterfaceKey;
Expand Down Expand Up @@ -304,6 +303,10 @@ class AgentPath : public Path {
is_health_check_service_ = val;
}

void UpdateEcmpHashFields(const Agent *agent,
const EcmpLoadBalance &ecmp_load_balance,
DBRequest &nh_req);

private:
PeerConstPtr peer_;
// Nexthop for route. Not used for gateway routes
Expand Down Expand Up @@ -377,6 +380,9 @@ class AgentPath : public Path {
// TODO(prabhjot) need to find more genric solution for marking proxy arp
// to move all the logic of identifing proxy arp in one place
bool is_health_check_service_;
// These Ecmp fields will hold the corresponding composite nh ecmp fields reference
// if the path's ecmp load balance field is not set
EcmpHashFields ecmp_hash_fields_;
DISALLOW_COPY_AND_ASSIGN(AgentPath);
};

Expand Down
5 changes: 4 additions & 1 deletion src/vnsw/agent/oper/agent_route.cc
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,6 @@ void AgentRouteTable::DeletePathFromPeer(DBTablePartBase *part,
if (rt == NULL) {
return;
}

bool deleted_path_was_active_path = (rt->GetActivePath() == path);
RouteInfo rt_info;
rt->FillTrace(rt_info, AgentRoute::DELETE_PATH, path);
Expand All @@ -249,10 +248,14 @@ void AgentRouteTable::DeletePathFromPeer(DBTablePartBase *part,
}

const Peer *peer = path->peer();
CompositeNH *cnh = dynamic_cast<CompositeNH *>(path->nexthop());
//Recompute paths since one is going off before deleting.
rt->ReComputePathDeletion(path);
// Remove path from the route
rt->RemovePath(path);
if (cnh) {
cnh->UpdateEcmpHashFieldsUponRouteDelete(agent_, vrf_name());
}
// Local path(non BGP type) is going away and so will route.
// For active peers reflector will remove the route but for
// non active peers explicitly squash the paths.
Expand Down
115 changes: 114 additions & 1 deletion src/vnsw/agent/oper/ecmp_load_balance.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

#ifndef vnsw_agent_ecmp_load_balance_hpp
#define vnsw_agent_ecmp_load_balance_hpp

#include <boost/intrusive_ptr.hpp>
#include <vnc_cfg_types.h>

using namespace boost::uuids;
Expand Down Expand Up @@ -219,4 +219,117 @@ class VmiEcmpLoadBalance : public EcmpLoadBalance {
bool use_global_vrouter_;
};

class EcmpField {
public:
EcmpField() {
ref_count_= 0;
}

uint32_t RefCount() const {
return ref_count_;
}
private:
friend void intrusive_ptr_add_ref(EcmpField* ptr);
friend void intrusive_ptr_release(EcmpField* ptr);
mutable tbb::atomic<uint32_t> ref_count_;
};

inline void intrusive_ptr_add_ref(EcmpField* ptr) {
ptr->ref_count_.fetch_and_increment();
}

inline void intrusive_ptr_release(EcmpField* ptr) {
uint32_t prev = ptr->ref_count_.fetch_and_decrement();
if (prev == 1) {
delete ptr;
}
}

class EcmpHashFields {
public:
typedef boost::intrusive_ptr<EcmpField> EcmpFieldPtr;

EcmpHashFields() {
}

EcmpHashFields(const uint8_t hash_fields_to_use ) {
hash_fields_to_use_ = hash_fields_to_use;
}
void operator = (const uint8_t hash_fields_to_use) {
hash_fields_to_use_ = hash_fields_to_use;
}

void AllocateEcmpFields() {
sip_ = new EcmpField;
dip_ = new EcmpField;
proto_ = new EcmpField;
sport_ = new EcmpField;
dport_ = new EcmpField;
}

uint8_t HashFieldsToUse() const {
return hash_fields_to_use_;
}

void SetHashFieldtoUse(EcmpField *ptr, uint8_t key) {
if (ptr && ptr->RefCount() == 1) {
comp_hash_fields_to_use_ |= 1 << key;
}
}
// If the field is not set create intrusive pointer
// else release the pointer.
void SetChangeInHashField(bool is_field_set, EcmpFieldPtr& fieldPtr,
EcmpFieldPtr &objFieldPtr) {
if (!is_field_set) {
if (!objFieldPtr.get()) {
objFieldPtr = fieldPtr;
}
} else {
objFieldPtr.reset();
}
}
// This function will be called to ge intersection of ecmp fields
uint8_t CalculateHashFieldsToUse() {
comp_hash_fields_to_use_ = 0;
SetHashFieldtoUse(sip_.get(), EcmpLoadBalance::SOURCE_IP);
SetHashFieldtoUse(dip_.get(), EcmpLoadBalance::DESTINATION_IP);
SetHashFieldtoUse(proto_.get(), EcmpLoadBalance::IP_PROTOCOL);
SetHashFieldtoUse(sport_.get(), EcmpLoadBalance::SOURCE_PORT);
SetHashFieldtoUse(dport_.get(), EcmpLoadBalance::DESTINATION_PORT);
return comp_hash_fields_to_use_;
}
//This function used to calculate the Change in ecmp fields
void CalculateChangeInEcmpFields(const EcmpLoadBalance &ecmp_load_balance,
EcmpHashFields& ecmp_hash_fields) {
SetChangeInHashField(ecmp_load_balance.is_source_ip_set(),
ecmp_hash_fields.sip_, sip_);
SetChangeInHashField(ecmp_load_balance.is_destination_ip_set(),
ecmp_hash_fields.dip_, dip_);
SetChangeInHashField(ecmp_load_balance.is_ip_protocol_set(),
ecmp_hash_fields.proto_, proto_);
SetChangeInHashField(ecmp_load_balance.is_source_port_set(),
ecmp_hash_fields.sport_, sport_);
SetChangeInHashField(ecmp_load_balance.is_destination_port_set(),
ecmp_hash_fields.dport_, dport_);
}

bool IsFieldsInUseChanged() {
return hash_fields_to_use_ != CalculateHashFieldsToUse();
}

void SetHashFieldstoUse() {
hash_fields_to_use_ = comp_hash_fields_to_use_;
}

private:
// This will have latest computed value
uint8_t comp_hash_fields_to_use_;
uint8_t hash_fields_to_use_;
EcmpFieldPtr sip_;
EcmpFieldPtr dip_;
EcmpFieldPtr proto_;
EcmpFieldPtr sport_;
EcmpFieldPtr dport_;
DISALLOW_COPY_AND_ASSIGN(EcmpHashFields);
};
#endif
17 changes: 17 additions & 0 deletions src/vnsw/agent/oper/nexthop.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1469,6 +1469,10 @@ bool CompositeNH::Change(const DBRequest* req) {
changed = true;
}

if (comp_ecmp_hash_fields_.IsFieldsInUseChanged()) {
comp_ecmp_hash_fields_.SetHashFieldstoUse();
changed = true;
}
component_nh_list_ = component_nh_list;
return changed;
}
Expand Down Expand Up @@ -1778,6 +1782,19 @@ uint32_t CompositeNH::GetRemoteLabel(const Ip4Address &ip) const {
return -1;
}

void CompositeNH::UpdateEcmpHashFieldsUponRouteDelete(Agent *agent,
const string &vrf_name) {
if (comp_ecmp_hash_fields_.IsFieldsInUseChanged()) {
DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
DBEntryBase::KeyPtr key = GetDBRequestKey();
NextHopKey *nh_key = static_cast<NextHopKey *>(key.get());
nh_key->sub_op_ = AgentKey::RESYNC;
nh_req.key = key;
nh_req.data.reset(NULL);
agent->nexthop_table()->Process(nh_req);
}
}

void CompositeNHKey::CreateTunnelNH(Agent *agent) {
BOOST_FOREACH(ComponentNHKeyPtr component_nh_key, component_nh_key_list_) {
if (component_nh_key.get() &&
Expand Down
9 changes: 8 additions & 1 deletion src/vnsw/agent/oper/nexthop.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

#include <oper/interface_common.h>
#include <oper/vrf.h>
#include <oper/ecmp_load_balance.h>

using namespace boost::uuids;
using namespace std;
Expand Down Expand Up @@ -1356,6 +1357,7 @@ class CompositeNH : public NextHop {
const ComponentNHKeyList &component_nh_key_list, VrfEntry *vrf):
NextHop(COMPOSITE, policy), composite_nh_type_(type),
component_nh_key_list_(component_nh_key_list), vrf_(vrf, this) {
comp_ecmp_hash_fields_.AllocateEcmpFields();
}

virtual ~CompositeNH() { };
Expand Down Expand Up @@ -1458,7 +1460,11 @@ class CompositeNH : public NextHop {
virtual bool MatchEgressData(const NextHop *nh) const {
return false;
}

uint8_t EcmpHashFieldInUse() const {
return comp_ecmp_hash_fields_.HashFieldsToUse();
}
EcmpHashFields& CompEcmpHashFields() { return comp_ecmp_hash_fields_; }
void UpdateEcmpHashFieldsUponRouteDelete(Agent *agent, const string &vrf_name);
private:
void CreateComponentNH(Agent *agent, TunnelType::Type type) const;
void ChangeComponentNHKeyTunnelType(ComponentNHKeyList &component_nh_list,
Expand All @@ -1467,6 +1473,7 @@ class CompositeNH : public NextHop {
ComponentNHKeyList component_nh_key_list_;
ComponentNHList component_nh_list_;
VrfEntryRef vrf_;
EcmpHashFields comp_ecmp_hash_fields_;
DISALLOW_COPY_AND_ASSIGN(CompositeNH);
};

Expand Down
4 changes: 4 additions & 0 deletions src/vnsw/agent/test/test_cmn_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,10 @@ bool EcmpTunnelRouteAdd(const Peer *peer, const string &vrf_name, const Ip4Addre
uint8_t plen, ComponentNHKeyList &comp_nh_list,
bool local_ecmp, const string &vn_name, const SecurityGroupList &sg,
const PathPreference &path_preference);
bool EcmpTunnelRouteAdd(const Peer *peer, const string &vrf_name, const Ip4Address &vm_ip,
uint8_t plen, ComponentNHKeyList &comp_nh_list,
bool local_ecmp, const string &vn_name, const SecurityGroupList &sg,
const PathPreference &path_preference, EcmpLoadBalance& ecmp_load_balnce);
bool EcmpTunnelRouteAdd(Agent *agent, const Peer *peer, const string &vrf_name,
const string &prefix, uint8_t plen,
const string &remote_server_1, uint32_t label1,
Expand Down

0 comments on commit 2748209

Please sign in to comment.