Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Mux] Neighbor handling based on FDB entry #1631

Merged
merged 3 commits into from
Feb 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);

prsunny marked this conversation as resolved.
Show resolved Hide resolved
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'",
gechiang marked this conversation as resolved.
Show resolved Hide resolved
nbr.to_string().c_str(), mac.to_string().c_str());
return true;
}

if (!port.empty() && isMuxExists(port))
{
MuxCable* ptr = getMuxCable(port);
gechiang marked this conversation as resolved.
Show resolved Hide resolved
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))
prsunny marked this conversation as resolved.
Show resolved Hide resolved
{
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;
gechiang marked this conversation as resolved.
Show resolved Hide resolved
}
}

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
gechiang marked this conversation as resolved.
Show resolved Hide resolved
{
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