Skip to content

Create tunnel to peer switch when a packet to unresolved neighbor is received #2134

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

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
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
24 changes: 20 additions & 4 deletions neighsyncd/neighsync.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ NeighSync::NeighSync(RedisPipeline *pipelineAppDB, DBConnector *stateDb, DBConne
m_stateNeighRestoreTable(stateDb, STATE_NEIGH_RESTORE_TABLE_NAME),
m_cfgInterfaceTable(cfgDb, CFG_INTF_TABLE_NAME),
m_cfgLagInterfaceTable(cfgDb, CFG_LAG_INTF_TABLE_NAME),
m_cfgVlanInterfaceTable(cfgDb, CFG_VLAN_INTF_TABLE_NAME)
m_cfgVlanInterfaceTable(cfgDb, CFG_VLAN_INTF_TABLE_NAME),
m_cfgPeerSwitchTable(cfgDb, CFG_PEER_SWITCH_TABLE_NAME)
{
m_AppRestartAssist = new AppRestartAssist(pipelineAppDB, "neighsyncd", "swss", DEFAULT_NEIGHSYNC_WARMSTART_TIMER);
if (m_AppRestartAssist)
Expand Down Expand Up @@ -98,14 +99,29 @@ void NeighSync::onMsg(int nlmsg_type, struct nl_object *obj)
return;
}

std::vector<std::string> peerSwitchKeys;
bool delete_key = false;
if ((nlmsg_type == RTM_DELNEIGH) || (state == NUD_INCOMPLETE) ||
(state == NUD_FAILED))
bool use_zero_mac = false;
m_cfgPeerSwitchTable.getKeys(peerSwitchKeys);
bool is_dualtor = peerSwitchKeys.size() > 0;
if (is_dualtor && (state == NUD_INCOMPLETE || state == NUD_FAILED))
{
use_zero_mac = true;
}
else if ((nlmsg_type == RTM_DELNEIGH) ||
(state == NUD_INCOMPLETE) || (state == NUD_FAILED))
{
delete_key = true;
}

nl_addr2str(rtnl_neigh_get_lladdr(neigh), macStr, MAX_ADDR_SIZE);
if (use_zero_mac)
{
strncpy(macStr, "00:00:00:00:00:00", ETHER_ADDR_LEN);
}
else
{
nl_addr2str(rtnl_neigh_get_lladdr(neigh), macStr, MAX_ADDR_SIZE);
}

/* Ignore neighbor entries with Broadcast Mac - Trigger for directed broadcast */
if (!delete_key && (MacAddress(macStr) == MacAddress("ff:ff:ff:ff:ff:ff")))
Expand Down
2 changes: 1 addition & 1 deletion neighsyncd/neighsync.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class NeighSync : public NetMsg
Table m_stateNeighRestoreTable;
ProducerStateTable m_neighTable;
AppRestartAssist *m_AppRestartAssist;
Table m_cfgVlanInterfaceTable, m_cfgLagInterfaceTable, m_cfgInterfaceTable;
Table m_cfgVlanInterfaceTable, m_cfgLagInterfaceTable, m_cfgInterfaceTable, m_cfgPeerSwitchTable;

bool isLinkLocalEnabled(const std::string &port);
};
Expand Down
7 changes: 7 additions & 0 deletions orchagent/neighorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ extern Directory<Orch*> gDirectory;
extern string gMySwitchType;
extern int32_t gVoqMySwitchId;

#define MUX_TUNNEL "MuxTunnel0"

const int neighorch_pri = 30;

NeighOrch::NeighOrch(DBConnector *appDb, string tableName, IntfsOrch *intfsOrch, FdbOrch *fdbOrch, PortsOrch *portsOrch, DBConnector *chassisAppDb) :
Expand Down Expand Up @@ -728,6 +730,11 @@ void NeighOrch::doTask(Consumer &consumer)
if (m_syncdNeighbors.find(neighbor_entry) == m_syncdNeighbors.end()
|| m_syncdNeighbors[neighbor_entry].mac != mac_address)
{
if (mac_address == MacAddress("00:00:00:00:00:00"))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like there is more change here and the muxorch changes.

{
MuxOrch* mux_orch = gDirectory.get<MuxOrch*>();
mux_orch->createNextHopTunnel(MUX_TUNNEL, neighbor_entry.ip_address);
}
if (addNeighbor(neighbor_entry, mac_address))
{
it = consumer.m_toSync.erase(it);
Expand Down
48 changes: 48 additions & 0 deletions tests/test_mux.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class TestMuxTunnelBase(object):
ASIC_NEIGH_TABLE = "ASIC_STATE:SAI_OBJECT_TYPE_NEIGHBOR_ENTRY"
ASIC_NEXTHOP_TABLE = "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP"
ASIC_ROUTE_TABLE = "ASIC_STATE:SAI_OBJECT_TYPE_ROUTE_ENTRY"
ASIC_FDB_TABLE = "ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY"
CONFIG_MUX_CABLE = "MUX_CABLE"

SERV1_IPV4 = "192.168.0.100"
Expand Down Expand Up @@ -664,6 +665,45 @@ def remove_and_test_tunnel(self, db, asicdb, tunnel_name):
assert not self.check_interface_exists_in_asicdb(asicdb, overlay_infs_id)


def remove_link_and_test_tunnel_create(self, appdb, asicdb, confdb, dvs):
self.create_vlan_interface(confdb, asicdb, dvs)
self.create_mux_cable(confdb)
self.create_and_test_tunnel(appdb, asicdb, tunnel_name="MuxTunnel0", tunnel_type="IPINIP",
dst_ip="10.1.0.32", dscp_mode="uniform",
ecn_mode="standard", ttl_mode="pipe")

peer_attrs = {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add the following tests as well:

  1. Add a FAILED neighbor before configuring peer_switch. There should not be a tunnel route
  2. Do mux status changes after resolving the entry and verify neighbor, and tunnel route
  3. Add a FAILED entry and delete the entry. Make sure the tunnel route is removed as well.

"address_ipv4": "10.1.0.32"
}
confdb.create_entry("PEER_SWITCH", "peer", peer_attrs)

dvs.runcmd("ping -c 10 192.168.0.99")
route = None
routes = asicdb.get_keys(self.ASIC_ROUTE_TABLE)
for r in routes:
t = json.loads(r)
if t["dest"] == "192.168.0.99/32":
route = r
assert json.loads(route)["dest"] == "192.168.0.99/32"

fvs1 = asicdb.get_entry(self.ASIC_ROUTE_TABLE, route)
oid = fvs1["SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID"]
fvs2 = asicdb.get_entry(self.ASIC_NEXTHOP_TABLE, oid)
assert fvs2["SAI_NEXT_HOP_ATTR_IP"] == "10.1.0.32"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use function dvs_route.check_asicdb_route_entries for checking asic_db


fdb = asicdb.get_keys(self.ASIC_FDB_TABLE)
mac = json.loads(fdb[0])["mac"]
dvs.runcmd("ip -4 neigh replace 192.168.0.99 lladdr "+mac+" dev Vlan1000")
time.sleep(10)
route = None
routes = asicdb.get_keys(self.ASIC_ROUTE_TABLE)
for r in routes:
t = json.loads(r)
if t["dest"] == "192.168.0.99/32":
route = r
assert route == None


def cleanup_left_over(self, db, asicdb):
""" Cleanup APP and ASIC tables """

Expand Down Expand Up @@ -750,6 +790,14 @@ def test_mux_metrics(self, dvs, testlog):

self.create_and_test_metrics(appdb, statedb, dvs)

def test_neighbor_miss(self, dvs, testlog):
""" test IP tunnel to Active for missing neighbor """
appdb = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0)
asicdb = dvs.get_asic_db()
confdb = dvs.get_config_db()

self.remove_link_and_test_tunnel_create(appdb, asicdb, confdb, dvs)


# Add Dummy always-pass test at end as workaroud
# for issue when Flaky fail on final test it invokes module tear-down before retrying
Expand Down