Skip to content

Commit

Permalink
[Mux] Neighbor handling based on FDB entry (#1631)
Browse files Browse the repository at this point in the history
* Mux neighbor handling based on FDB entry
  • Loading branch information
prsunny authored and daall committed Feb 16, 2021
1 parent 66e0016 commit e36e4c9
Show file tree
Hide file tree
Showing 5 changed files with 189 additions and 23 deletions.
188 changes: 173 additions & 15 deletions orchagent/muxorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "portsorch.h"
#include "aclorch.h"
#include "routeorch.h"
#include "fdborch.h"

/* Global variables */
extern Directory<Orch*> gDirectory;
Expand All @@ -27,6 +28,7 @@ extern NeighOrch *gNeighOrch;
extern RouteOrch *gRouteOrch;
extern AclOrch *gAclOrch;
extern PortsOrch *gPortsOrch;
extern FdbOrch *gFdbOrch;

extern sai_object_id_t gVirtualRouterId;
extern sai_object_id_t gUnderlayIfId;
Expand Down Expand Up @@ -196,6 +198,10 @@ static sai_object_id_t create_tunnel(const IpAddress* p_dst_ip, const IpAddress*
attr.value.s32 = SAI_TUNNEL_PEER_MODE_P2P;
tunnel_attrs.push_back(attr);

attr.id = SAI_TUNNEL_ATTR_ENCAP_TTL_MODE;
attr.value.s32 = SAI_TUNNEL_TTL_MODE_PIPE_MODEL;
tunnel_attrs.push_back(attr);

if (p_src_ip != nullptr)
{
attr.id = SAI_TUNNEL_ATTR_ENCAP_SRC_IP;
Expand Down Expand Up @@ -474,7 +480,7 @@ void MuxCable::updateNeighbor(NextHopKey nh, bool add)
{
mux_orch_->addNexthop(nh, mux_name_);
}
else
else if (mux_name_ == mux_orch_->getNexthopMuxName(nh))
{
mux_orch_->removeNexthop(nh);
}
Expand Down Expand Up @@ -507,9 +513,11 @@ void MuxNbrHandler::update(NextHopKey nh, sai_object_id_t tunnelId, bool add, Mu
break;
case MuxState::MUX_STATE_ACTIVE:
neighbors_[nh.ip_address] = gNeighOrch->getLocalNextHopId(nh);
gNeighOrch->enableNeighbor(nh);
break;
case MuxState::MUX_STATE_STANDBY:
neighbors_[nh.ip_address] = tunnelId;
gNeighOrch->disableNeighbor(nh);
mux_cb_orch->addTunnelRoute(nh);
create_route(pfx, tunnelId);
break;
Expand Down Expand Up @@ -806,7 +814,6 @@ sai_object_id_t MuxOrch::getNextHopTunnelId(std::string tunnelKey, IpAddress& ip
return it->second.nh_id;
}


MuxCable* MuxOrch::findMuxCableInSubnet(IpAddress ip)
{
for (auto it = mux_cable_tb_.begin(); it != mux_cable_tb_.end(); it++)
Expand All @@ -821,28 +828,159 @@ MuxCable* MuxOrch::findMuxCableInSubnet(IpAddress ip)
return nullptr;
}

bool MuxOrch::isNeighborActive(IpAddress nbr, string alias)
bool MuxOrch::isNeighborActive(const IpAddress& nbr, const MacAddress& mac, string& alias)
{
if (mux_cable_tb_.empty())
{
return true;
}

MuxCable* ptr = findMuxCableInSubnet(nbr);

if (ptr)
{
return ptr->isActive();
}

string port;
if (!getMuxPort(mac, alias, port))
{
SWSS_LOG_INFO("Mux get port from FDB failed for '%s' mac '%s'",
nbr.to_string().c_str(), mac.to_string().c_str());
return true;
}

if (!port.empty() && isMuxExists(port))
{
MuxCable* ptr = getMuxCable(port);
return ptr->isActive();
}

return true;
}

bool MuxOrch::getMuxPort(const MacAddress& mac, const string& alias, string& portName)
{
portName = std::string();
Port rif, port;

if (!gPortsOrch->getPort(alias, rif))
{
SWSS_LOG_ERROR("Interface '%s' not found in port table", alias.c_str());
return false;
}

if (rif.m_type != Port::VLAN)
{
SWSS_LOG_DEBUG("Interface type for '%s' is not Vlan, type %d", alias.c_str(), rif.m_type);
return false;
}

if (!gFdbOrch->getPort(mac, rif.m_vlan_info.vlan_id, port))
{
SWSS_LOG_INFO("FDB entry not found: Vlan %s, mac %s", alias.c_str(), mac.to_string().c_str());
return true;
}

portName = port.m_alias;
return true;
}

void MuxOrch::updateFdb(const FdbUpdate& update)
{
if (!update.add)
{
/*
* For Mac aging, flush events, skip updating mux neighbors.
* Instead, wait for neighbor update events
*/
return;
}

NeighborEntry neigh;
MacAddress mac;
MuxCable* ptr;
for (auto nh = mux_nexthop_tb_.begin(); nh != mux_nexthop_tb_.end(); ++nh)
{
auto res = neigh_orch_->getNeighborEntry(nh->first, neigh, mac);
if (!res || update.entry.mac != mac)
{
continue;
}

if (nh->second != update.entry.port_name)
{
if (!nh->second.empty() && isMuxExists(nh->second))
{
ptr = getMuxCable(nh->second);
if (ptr->isIpInSubnet(nh->first.ip_address))
{
continue;
}
nh->second = update.entry.port_name;
ptr->updateNeighbor(nh->first, false);
}

if (isMuxExists(update.entry.port_name))
{
ptr = getMuxCable(update.entry.port_name);
ptr->updateNeighbor(nh->first, true);
}
}
}
}

void MuxOrch::updateNeighbor(const NeighborUpdate& update)
{
if (mux_cable_tb_.empty())
{
return;
}

for (auto it = mux_cable_tb_.begin(); it != mux_cable_tb_.end(); it++)
{
MuxCable* ptr = it->second.get();
if (ptr->isIpInSubnet(update.entry.ip_address))
{
ptr->updateNeighbor(update.entry, update.add);
return;
}
}

string port, old_port;
if (update.add && !getMuxPort(update.mac, update.entry.alias, port))
{
return;
}
else if (update.add)
{
/* Check if the neighbor already exists */
old_port = getNexthopMuxName(update.entry);
addNexthop(update.entry);
}
else
{
auto it = mux_nexthop_tb_.find(update.entry);
if (it != mux_nexthop_tb_.end())
{
port = it->second;
removeNexthop(update.entry);
}
}

MuxCable* ptr;
if (!old_port.empty() && old_port != port && isMuxExists(old_port))
{
ptr = getMuxCable(old_port);
ptr->updateNeighbor(update.entry, false);
addNexthop(update.entry);
}

if (!port.empty() && isMuxExists(port))
{
ptr = getMuxCable(port);
ptr->updateNeighbor(update.entry, update.add);
}
}

void MuxOrch::addNexthop(NextHopKey nh, string muxName)
Expand All @@ -855,6 +993,16 @@ void MuxOrch::removeNexthop(NextHopKey nh)
mux_nexthop_tb_.erase(nh);
}

string MuxOrch::getNexthopMuxName(NextHopKey nh)
{
if (mux_nexthop_tb_.find(nh) == mux_nexthop_tb_.end())
{
return std::string();
}

return mux_nexthop_tb_[nh];
}

sai_object_id_t MuxOrch::getNextHopId(const NextHopKey &nh)
{
if (mux_nexthop_tb_.find(nh) == mux_nexthop_tb_.end())
Expand All @@ -865,7 +1013,8 @@ sai_object_id_t MuxOrch::getNextHopId(const NextHopKey &nh)
auto mux_name = mux_nexthop_tb_[nh];
if (!isMuxExists(mux_name))
{
SWSS_LOG_WARN("Mux entry for port '%s' doesn't exist", mux_name.c_str());
SWSS_LOG_INFO("Mux entry for nh '%s' port '%s' doesn't exist",
nh.ip_address.to_string().c_str(), mux_name.c_str());
return SAI_NULL_OBJECT_ID;
}

Expand All @@ -888,6 +1037,12 @@ void MuxOrch::update(SubjectType type, void *cntx)
updateNeighbor(*update);
break;
}
case SUBJECT_TYPE_FDB_CHANGE:
{
FdbUpdate *update = static_cast<FdbUpdate *>(cntx);
updateFdb(*update);
break;
}
default:
/* Received update in which we are not interested
* Ignore it
Expand All @@ -896,15 +1051,18 @@ void MuxOrch::update(SubjectType type, void *cntx)
}
}

MuxOrch::MuxOrch(DBConnector *db, const std::vector<std::string> &tables, TunnelDecapOrch* decapOrch, NeighOrch* neighOrch) :
MuxOrch::MuxOrch(DBConnector *db, const std::vector<std::string> &tables,
TunnelDecapOrch* decapOrch, NeighOrch* neighOrch, FdbOrch* fdbOrch) :
Orch2(db, tables, request_),
decap_orch_(decapOrch),
neigh_orch_(neighOrch)
neigh_orch_(neighOrch),
fdb_orch_(fdbOrch)
{
handler_map_.insert(handler_pair(CFG_MUX_CABLE_TABLE_NAME, &MuxOrch::handleMuxCfg));
handler_map_.insert(handler_pair(CFG_PEER_SWITCH_TABLE_NAME, &MuxOrch::handlePeerSwitch));

neigh_orch_->attach(this);
fdb_orch_->attach(this);
}

bool MuxOrch::handleMuxCfg(const Request& request)
Expand All @@ -921,13 +1079,13 @@ bool MuxOrch::handleMuxCfg(const Request& request)
{
if(isMuxExists(port_name))
{
SWSS_LOG_ERROR("Mux for port '%s' already exists", port_name.c_str());
SWSS_LOG_INFO("Mux for port '%s' already exists", port_name.c_str());
return true;
}

if (mux_peer_switch_.isZero())
{
SWSS_LOG_ERROR("Peer switch addr not yet configured, port '%s'", port_name.c_str());
SWSS_LOG_INFO("Mux Peer switch addr not yet configured, port '%s'", port_name.c_str());
return false;
}

Expand Down Expand Up @@ -998,7 +1156,7 @@ bool MuxOrch::addOperation(const Request& request)
auto& tn = request.getTableName();
if (handler_map_.find(tn) == handler_map_.end())
{
SWSS_LOG_ERROR(" %s handler is not initialized", tn.c_str());
SWSS_LOG_ERROR("Mux %s handler is not initialized", tn.c_str());
return true;
}

Expand All @@ -1022,7 +1180,7 @@ bool MuxOrch::delOperation(const Request& request)
auto& tn = request.getTableName();
if (handler_map_.find(tn) == handler_map_.end())
{
SWSS_LOG_ERROR(" %s handler is not initialized", tn.c_str());
SWSS_LOG_ERROR("Mux %s handler is not initialized", tn.c_str());
return true;
}

Expand Down Expand Up @@ -1099,7 +1257,7 @@ bool MuxCableOrch::addOperation(const Request& request)
MuxOrch* mux_orch = gDirectory.get<MuxOrch*>();
if (!mux_orch->isMuxExists(port_name))
{
SWSS_LOG_WARN("Mux entry for port '%s' doesn't exist", port_name.c_str());
SWSS_LOG_INFO("Mux entry for port '%s' doesn't exist", port_name.c_str());
return false;
}

Expand All @@ -1112,7 +1270,7 @@ bool MuxCableOrch::addOperation(const Request& request)
}
catch(const std::runtime_error& error)
{
SWSS_LOG_ERROR("Error setting state %s for port %s. Error: %s",
SWSS_LOG_ERROR("Mux Error setting state %s for port %s. Error: %s",
state.c_str(), port_name.c_str(), error.what());
return false;
}
Expand Down Expand Up @@ -1171,13 +1329,13 @@ bool MuxStateOrch::addOperation(const Request& request)
}
catch(const std::runtime_error& error)
{
SWSS_LOG_ERROR("Error getting state for port %s Error: %s", port_name.c_str(), error.what());
SWSS_LOG_ERROR("Mux error getting state for port %s Error: %s", port_name.c_str(), error.what());
return false;
}

if (mux_obj->isStateChangeInProgress())
{
SWSS_LOG_NOTICE("Mux state change for port '%s' is in-progress", port_name.c_str());
SWSS_LOG_INFO("Mux state change for port '%s' is in-progress", port_name.c_str());
return false;
}

Expand All @@ -1186,7 +1344,7 @@ bool MuxStateOrch::addOperation(const Request& request)
mux_state = MUX_HW_STATE_UNKNOWN;
}

SWSS_LOG_NOTICE("Setting State DB entry (hw state %s, mux state %s) for port %s",
SWSS_LOG_NOTICE("Mux setting State DB entry (hw state %s, mux state %s) for port %s",
hw_state.c_str(), mux_state.c_str(), port_name.c_str());

updateMuxState(port_name, mux_state);
Expand Down
Loading

0 comments on commit e36e4c9

Please sign in to comment.