Skip to content

Commit 8f7ea14

Browse files
Code changes to support IPv6 Link local enhancements (sonic-net#1463)
* Code changes to support IPv6 Link local enchancements - Changes to handle the "ipv6_use_link_local_only" option on a interface which is added/deleted based on Global Config or Interface config. - Adds/Deletes the RIF for an interface in the absence of IPv6 global address on a interface based on "ipv6_use_link_local_only". - Allow the ipv6 link-local address as neighbors. - Allow adding the IPv6 routes with link-local nexthops. - Skip Ipv4LL neighbor add in Orchagent for RFC5549. Signed-off-by: Akhilesh Samineni <[email protected]>
1 parent 8674b3c commit 8f7ea14

File tree

8 files changed

+358
-17
lines changed

8 files changed

+358
-17
lines changed

cfgmgr/intfmgr.cpp

+18-6
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,7 @@ bool IntfMgr::doIntfGeneralTask(const vector<string>& keys,
476476
string proxy_arp = "";
477477
string grat_arp = "";
478478
string mpls = "";
479+
string ipv6_link_local_mode = "";
479480

480481
for (auto idx : data)
481482
{
@@ -506,11 +507,14 @@ bool IntfMgr::doIntfGeneralTask(const vector<string>& keys,
506507
{
507508
mpls = value;
508509
}
509-
510-
if (field == "nat_zone")
510+
else if (field == "nat_zone")
511511
{
512512
nat_zone = value;
513513
}
514+
else if (field == "ipv6_use_link_local_only")
515+
{
516+
ipv6_link_local_mode = value;
517+
}
514518
}
515519

516520
if (op == SET_COMMAND)
@@ -551,6 +555,7 @@ bool IntfMgr::doIntfGeneralTask(const vector<string>& keys,
551555
FieldValueTuple fvTuple("nat_zone", nat_zone);
552556
data.push_back(fvTuple);
553557
}
558+
554559
/* Set mpls */
555560
if (!setIntfMpls(alias, mpls))
556561
{
@@ -562,6 +567,13 @@ bool IntfMgr::doIntfGeneralTask(const vector<string>& keys,
562567
FieldValueTuple fvTuple("mpls", mpls);
563568
data.push_back(fvTuple);
564569
}
570+
571+
/* Set ipv6 mode */
572+
if (!ipv6_link_local_mode.empty())
573+
{
574+
FieldValueTuple fvTuple("ipv6_use_link_local_only", ipv6_link_local_mode);
575+
data.push_back(fvTuple);
576+
}
565577
}
566578

567579
if (!parentAlias.empty())
@@ -731,8 +743,8 @@ bool IntfMgr::doIntfAddrTask(const vector<string>& keys,
731743
std::vector<FieldValueTuple> fvVector;
732744
FieldValueTuple f("family", ip_prefix.isV4() ? IPV4_NAME : IPV6_NAME);
733745

734-
// Don't send link local config to AppDB and Orchagent
735-
if (ip_prefix.getIp().getAddrScope() != IpAddress::AddrScope::LINK_SCOPE)
746+
// Don't send ipv4 link local config to AppDB and Orchagent
747+
if ((ip_prefix.isV4() == false) || (ip_prefix.getIp().getAddrScope() != IpAddress::AddrScope::LINK_SCOPE))
736748
{
737749
FieldValueTuple s("scope", "global");
738750
fvVector.push_back(s);
@@ -745,8 +757,8 @@ bool IntfMgr::doIntfAddrTask(const vector<string>& keys,
745757
{
746758
setIntfIp(alias, "del", ip_prefix);
747759

748-
// Don't send link local config to AppDB and Orchagent
749-
if (ip_prefix.getIp().getAddrScope() != IpAddress::AddrScope::LINK_SCOPE)
760+
// Don't send ipv4 link local config to AppDB and Orchagent
761+
if ((ip_prefix.isV4() == false) || (ip_prefix.getIp().getAddrScope() != IpAddress::AddrScope::LINK_SCOPE))
750762
{
751763
m_appIntfTableProducer.del(appKey);
752764
m_stateIntfTable.del(keys[0] + state_db_key_delimiter + keys[1]);

neighsyncd/neighsync.cpp

+64-4
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,17 @@
1313

1414
#include "neighsync.h"
1515
#include "warm_restart.h"
16+
#include <algorithm>
1617

1718
using namespace std;
1819
using namespace swss;
1920

20-
NeighSync::NeighSync(RedisPipeline *pipelineAppDB, DBConnector *stateDb) :
21+
NeighSync::NeighSync(RedisPipeline *pipelineAppDB, DBConnector *stateDb, DBConnector *cfgDb) :
2122
m_neighTable(pipelineAppDB, APP_NEIGH_TABLE_NAME),
22-
m_stateNeighRestoreTable(stateDb, STATE_NEIGH_RESTORE_TABLE_NAME)
23+
m_stateNeighRestoreTable(stateDb, STATE_NEIGH_RESTORE_TABLE_NAME),
24+
m_cfgInterfaceTable(cfgDb, CFG_INTF_TABLE_NAME),
25+
m_cfgLagInterfaceTable(cfgDb, CFG_LAG_INTF_TABLE_NAME),
26+
m_cfgVlanInterfaceTable(cfgDb, CFG_VLAN_INTF_TABLE_NAME)
2327
{
2428
m_AppRestartAssist = new AppRestartAssist(pipelineAppDB, "neighsyncd", "swss", DEFAULT_NEIGHSYNC_WARMSTART_TIMER);
2529
if (m_AppRestartAssist)
@@ -57,6 +61,7 @@ void NeighSync::onMsg(int nlmsg_type, struct nl_object *obj)
5761
struct rtnl_neigh *neigh = (struct rtnl_neigh *)obj;
5862
string key;
5963
string family;
64+
string intfName;
6065

6166
if ((nlmsg_type != RTM_NEWNEIGH) && (nlmsg_type != RTM_GETNEIGH) &&
6267
(nlmsg_type != RTM_DELNEIGH))
@@ -70,12 +75,18 @@ void NeighSync::onMsg(int nlmsg_type, struct nl_object *obj)
7075
return;
7176

7277
key+= LinkCache::getInstance().ifindexToName(rtnl_neigh_get_ifindex(neigh));
78+
intfName = key;
7379
key+= ":";
7480

7581
nl_addr2str(rtnl_neigh_get_dst(neigh), ipStr, MAX_ADDR_SIZE);
76-
/* Ignore IPv6 link-local addresses as neighbors */
82+
/* Ignore IPv6 link-local addresses as neighbors, if ipv6 link local mode is disabled */
7783
if (family == IPV6_NAME && IN6_IS_ADDR_LINKLOCAL(nl_addr_get_binary_addr(rtnl_neigh_get_dst(neigh))))
78-
return;
84+
{
85+
if (isLinkLocalEnabled(intfName) == false)
86+
{
87+
return;
88+
}
89+
}
7990
/* Ignore IPv6 multicast link-local addresses as neighbors */
8091
if (family == IPV6_NAME && IN6_IS_ADDR_MC_LINKLOCAL(nl_addr_get_binary_addr(rtnl_neigh_get_dst(neigh))))
8192
return;
@@ -124,3 +135,52 @@ void NeighSync::onMsg(int nlmsg_type, struct nl_object *obj)
124135
m_neighTable.set(key, fvVector);
125136
}
126137
}
138+
139+
/* To check the ipv6 link local is enabled on a given port */
140+
bool NeighSync::isLinkLocalEnabled(const string &port)
141+
{
142+
vector<FieldValueTuple> values;
143+
144+
if (!port.compare(0, strlen("Vlan"), "Vlan"))
145+
{
146+
if (!m_cfgVlanInterfaceTable.get(port, values))
147+
{
148+
SWSS_LOG_INFO("IPv6 Link local is not enabled on %s", port.c_str());
149+
return false;
150+
}
151+
}
152+
else if (!port.compare(0, strlen("PortChannel"), "PortChannel"))
153+
{
154+
if (!m_cfgLagInterfaceTable.get(port, values))
155+
{
156+
SWSS_LOG_INFO("IPv6 Link local is not enabled on %s", port.c_str());
157+
return false;
158+
}
159+
}
160+
else if (!port.compare(0, strlen("Ethernet"), "Ethernet"))
161+
{
162+
if (!m_cfgInterfaceTable.get(port, values))
163+
{
164+
SWSS_LOG_INFO("IPv6 Link local is not enabled on %s", port.c_str());
165+
return false;
166+
}
167+
}
168+
else
169+
{
170+
SWSS_LOG_INFO("IPv6 Link local is not supported for %s ", port.c_str());
171+
return false;
172+
}
173+
174+
auto it = std::find_if(values.begin(), values.end(), [](const FieldValueTuple& t){ return t.first == "ipv6_use_link_local_only";});
175+
if (it != values.end())
176+
{
177+
if (it->second == "enable")
178+
{
179+
SWSS_LOG_INFO("IPv6 Link local is enabled on %s", port.c_str());
180+
return true;
181+
}
182+
}
183+
184+
SWSS_LOG_INFO("IPv6 Link local is not enabled on %s", port.c_str());
185+
return false;
186+
}

neighsyncd/neighsync.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class NeighSync : public NetMsg
2323
public:
2424
enum { MAX_ADDR_SIZE = 64 };
2525

26-
NeighSync(RedisPipeline *pipelineAppDB, DBConnector *stateDb);
26+
NeighSync(RedisPipeline *pipelineAppDB, DBConnector *stateDb, DBConnector *cfgDb);
2727
~NeighSync();
2828

2929
virtual void onMsg(int nlmsg_type, struct nl_object *obj);
@@ -39,6 +39,9 @@ class NeighSync : public NetMsg
3939
Table m_stateNeighRestoreTable;
4040
ProducerStateTable m_neighTable;
4141
AppRestartAssist *m_AppRestartAssist;
42+
Table m_cfgVlanInterfaceTable, m_cfgLagInterfaceTable, m_cfgInterfaceTable;
43+
44+
bool isLinkLocalEnabled(const std::string &port);
4245
};
4346

4447
}

neighsyncd/neighsyncd.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ int main(int argc, char **argv)
1818
DBConnector appDb("APPL_DB", 0);
1919
RedisPipeline pipelineAppDB(&appDb);
2020
DBConnector stateDb("STATE_DB", 0);
21+
DBConnector cfgDb("CONFIG_DB", 0);
2122

22-
NeighSync sync(&pipelineAppDB, &stateDb);
23+
NeighSync sync(&pipelineAppDB, &stateDb, &cfgDb);
2324

2425
NetDispatcher::getInstance().registerMessageHandler(RTM_NEWNEIGH, &sync);
2526
NetDispatcher::getInstance().registerMessageHandler(RTM_DELNEIGH, &sync);

orchagent/neighorch.cpp

+13
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,19 @@ void NeighOrch::doTask(Consumer &consumer)
671671

672672
IpAddress ip_address(key.substr(found+1));
673673

674+
/* Verify Ipv4 LinkLocal and skip neighbor entry added for RFC5549 */
675+
if ((ip_address.getAddrScope() == IpAddress::LINK_SCOPE) && (ip_address.isV4()))
676+
{
677+
/* Check if this prefix is not a configured ip, if so allow */
678+
IpPrefix ipll_prefix(ip_address.getV4Addr(), 16);
679+
if (!m_intfsOrch->isPrefixSubnet (ipll_prefix, alias))
680+
{
681+
SWSS_LOG_NOTICE("Skip IPv4LL neighbor %s, Intf:%s op: %s ", ip_address.to_string().c_str(), alias.c_str(), op.c_str());
682+
it = consumer.m_toSync.erase(it);
683+
continue;
684+
}
685+
}
686+
674687
NeighborEntry neighbor_entry = { ip_address, alias };
675688

676689
if (op == SET_COMMAND)

orchagent/routeorch.cpp

+23-2
Original file line numberDiff line numberDiff line change
@@ -127,15 +127,15 @@ RouteOrch::RouteOrch(DBConnector *db, vector<table_name_with_pri_t> &tableNames,
127127
IpPrefix linklocal_prefix = getLinkLocalEui64Addr();
128128

129129
addLinkLocalRouteToMe(gVirtualRouterId, linklocal_prefix);
130+
SWSS_LOG_NOTICE("Created link local ipv6 route %s to cpu", linklocal_prefix.to_string().c_str());
130131

131132
/* Add fe80::/10 subnet route to forward all link-local packets
132133
* destined to us, to CPU */
133134
IpPrefix default_link_local_prefix("fe80::/10");
134135

135136
addLinkLocalRouteToMe(gVirtualRouterId, default_link_local_prefix);
137+
SWSS_LOG_NOTICE("Created link local ipv6 route %s to cpu", default_link_local_prefix.to_string().c_str());
136138

137-
/* TODO: Add the link-local fe80::/10 route to cpu in every VRF created from
138-
* vrforch::addOperation. */
139139
}
140140

141141
std::string RouteOrch::getLinkLocalEui64Addr(void)
@@ -205,6 +205,27 @@ void RouteOrch::addLinkLocalRouteToMe(sai_object_id_t vrf_id, IpPrefix linklocal
205205
SWSS_LOG_NOTICE("Created link local ipv6 route %s to cpu", linklocal_prefix.to_string().c_str());
206206
}
207207

208+
void RouteOrch::delLinkLocalRouteToMe(sai_object_id_t vrf_id, IpPrefix linklocal_prefix)
209+
{
210+
sai_route_entry_t unicast_route_entry;
211+
unicast_route_entry.switch_id = gSwitchId;
212+
unicast_route_entry.vr_id = vrf_id;
213+
copy(unicast_route_entry.destination, linklocal_prefix);
214+
subnet(unicast_route_entry.destination, unicast_route_entry.destination);
215+
216+
sai_status_t status = sai_route_api->remove_route_entry(&unicast_route_entry);
217+
if (status != SAI_STATUS_SUCCESS)
218+
{
219+
SWSS_LOG_ERROR("Failed to delete link local ipv6 route %s to cpu, rv:%d",
220+
linklocal_prefix.getIp().to_string().c_str(), status);
221+
return;
222+
}
223+
224+
gCrmOrch->decCrmResUsedCounter(CrmResourceType::CRM_IPV6_ROUTE);
225+
226+
SWSS_LOG_NOTICE("Deleted link local ipv6 route %s to cpu", linklocal_prefix.to_string().c_str());
227+
}
228+
208229
bool RouteOrch::hasNextHopGroup(const NextHopGroupKey& nexthops) const
209230
{
210231
return m_syncdNextHopGroups.find(nexthops) != m_syncdNextHopGroups.end();

orchagent/routeorch.h

+4-3
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,10 @@ class RouteOrch : public Orch, public Subject
152152
bool createFineGrainedNextHopGroup(sai_object_id_t &next_hop_group_id, vector<sai_attribute_t> &nhg_attrs);
153153
bool removeFineGrainedNextHopGroup(sai_object_id_t &next_hop_group_id);
154154

155+
void addLinkLocalRouteToMe(sai_object_id_t vrf_id, IpPrefix linklocal_prefix);
156+
void delLinkLocalRouteToMe(sai_object_id_t vrf_id, IpPrefix linklocal_prefix);
157+
std::string getLinkLocalEui64Addr(void);
158+
155159
private:
156160
SwitchOrch *m_switchOrch;
157161
NeighOrch *m_neighOrch;
@@ -188,9 +192,6 @@ class RouteOrch : public Orch, public Subject
188192
bool addLabelRoutePost(const LabelRouteBulkContext& ctx, const NextHopGroupKey &nextHops);
189193
bool removeLabelRoutePost(const LabelRouteBulkContext& ctx);
190194

191-
std::string getLinkLocalEui64Addr(void);
192-
void addLinkLocalRouteToMe(sai_object_id_t vrf_id, IpPrefix linklocal_prefix);
193-
194195
void doTask(Consumer& consumer);
195196
void doLabelTask(Consumer& consumer);
196197
};

0 commit comments

Comments
 (0)