Skip to content

Commit

Permalink
Merge "Support for Ecmp configured hash in Agent"
Browse files Browse the repository at this point in the history
  • Loading branch information
Zuul authored and opencontrail-ci-admin committed Oct 25, 2016
2 parents c33a9ee + 2748209 commit bd89e2c
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
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
Expand Up @@ -1401,3 +1401,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
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
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
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
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
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
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 bd89e2c

Please sign in to comment.