Skip to content

Commit 12c29b4

Browse files
kirankellayxieca
authored andcommitted
Cannot ping to link-local ipv6 interface address of the switch. (sonic-net#774)
* Cannot ping to link-local ipv6 interface address of the switch. Fixes: 1. Packets destined to the switch's routing interface link-local ipv6 address are not coming to CPU. Hence the ping fails. Since all interfaces have the same link-local ipv6 address, all we need is a single ip2me /128 route corresponding to this address added in the hardware. We don't need fe80 ip2me route added to hardware for every interface. Hence the address overlap issue won't arise for the link-local interface address. 2. Fixed another issue as part of this PR. Where the link-local ipv6 neighbors are not learned via netlink by neighsync. As a result, we could not add an ipv6 route via link-local nexthop. Allow neighsync to learn the link-local neighbors too. Signed-off-by: [email protected] * Incremental change to the code changes. * Incremental change to the code changes. * Incorporated review comments. * Incorporated review comments. * Add fe80::/10 route to CPU to forward all locally destined link-local ipv6 packets to CPU. * Retain fe80.../128 ip2me route in the hardware along with fe80::/10 subnet route. Signed-off-by: Kiran Kella <[email protected]>
1 parent 4d8e08d commit 12c29b4

File tree

3 files changed

+92
-3
lines changed

3 files changed

+92
-3
lines changed

neighsyncd/neighsync.cpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,7 @@ void NeighSync::onMsg(int nlmsg_type, struct nl_object *obj)
6161
key+= ":";
6262

6363
nl_addr2str(rtnl_neigh_get_dst(neigh), ipStr, MAX_ADDR_SIZE);
64-
/* Ignore IPv6 link-local addresses as neighbors */
65-
if (family == IPV6_NAME && IN6_IS_ADDR_LINKLOCAL(nl_addr_get_binary_addr(rtnl_neigh_get_dst(neigh))))
66-
return;
64+
6765
/* Ignore IPv6 multicast link-local addresses as neighbors */
6866
if (family == IPV6_NAME && IN6_IS_ADDR_MC_LINKLOCAL(nl_addr_get_binary_addr(rtnl_neigh_get_dst(neigh))))
6967
return;

orchagent/routeorch.cpp

+85
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,91 @@ RouteOrch::RouteOrch(DBConnector *db, string tableName, NeighOrch *neighOrch) :
104104
m_syncdRoutes[v6_default_ip_prefix] = IpAddresses();
105105

106106
SWSS_LOG_NOTICE("Create IPv6 default route with packet action drop");
107+
108+
/* All the interfaces have the same MAC address and hence the same
109+
* auto-generated link-local ipv6 address with eui64 interface-id.
110+
* Hence add a single /128 route entry for the link-local interface
111+
* address pointing to the CPU port.
112+
*/
113+
IpPrefix linklocal_prefix = getLinkLocalEui64Addr();
114+
115+
addLinkLocalRouteToMe(gVirtualRouterId, linklocal_prefix);
116+
117+
/* Add fe80::/10 subnet route to forward all link-local packets
118+
* destined to us, to CPU */
119+
IpPrefix default_link_local_prefix("fe80::/10");
120+
121+
addLinkLocalRouteToMe(gVirtualRouterId, default_link_local_prefix);
122+
123+
/* TODO: Add the link-local fe80::/10 route to cpu in every VRF created from
124+
* vrforch::addOperation. */
125+
}
126+
127+
std::string RouteOrch::getLinkLocalEui64Addr(void)
128+
{
129+
SWSS_LOG_ENTER();
130+
131+
string ip_prefix;
132+
const uint8_t *gmac = gMacAddress.getMac();
133+
134+
uint8_t eui64_interface_id[EUI64_INTF_ID_LEN];
135+
char ipv6_ll_addr[INET6_ADDRSTRLEN] = {0};
136+
137+
/* Link-local IPv6 address autogenerated by kernel with eui64 interface-id
138+
* derived from the MAC address of the host interface.
139+
*/
140+
eui64_interface_id[0] = gmac[0] ^ 0x02;
141+
eui64_interface_id[1] = gmac[1];
142+
eui64_interface_id[2] = gmac[2];
143+
eui64_interface_id[3] = 0xff;
144+
eui64_interface_id[4] = 0xfe;
145+
eui64_interface_id[5] = gmac[3];
146+
eui64_interface_id[6] = gmac[4];
147+
eui64_interface_id[7] = gmac[5];
148+
149+
snprintf(ipv6_ll_addr, INET6_ADDRSTRLEN, "fe80::%02x%02x:%02x%02x:%02x%02x:%02x%02x",
150+
eui64_interface_id[0], eui64_interface_id[1], eui64_interface_id[2],
151+
eui64_interface_id[3], eui64_interface_id[4], eui64_interface_id[5],
152+
eui64_interface_id[6], eui64_interface_id[7]);
153+
154+
ip_prefix = string(ipv6_ll_addr);
155+
156+
return ip_prefix;
157+
}
158+
159+
void RouteOrch::addLinkLocalRouteToMe(sai_object_id_t vrf_id, IpPrefix linklocal_prefix)
160+
{
161+
sai_route_entry_t unicast_route_entry;
162+
unicast_route_entry.switch_id = gSwitchId;
163+
unicast_route_entry.vr_id = vrf_id;
164+
copy(unicast_route_entry.destination, linklocal_prefix);
165+
subnet(unicast_route_entry.destination, unicast_route_entry.destination);
166+
167+
sai_attribute_t attr;
168+
vector<sai_attribute_t> attrs;
169+
170+
attr.id = SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION;
171+
attr.value.s32 = SAI_PACKET_ACTION_FORWARD;
172+
attrs.push_back(attr);
173+
174+
Port cpu_port;
175+
gPortsOrch->getCpuPort(cpu_port);
176+
177+
attr.id = SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID;
178+
attr.value.oid = cpu_port.m_port_id;
179+
attrs.push_back(attr);
180+
181+
sai_status_t status = sai_route_api->create_route_entry(&unicast_route_entry, (uint32_t)attrs.size(), attrs.data());
182+
if (status != SAI_STATUS_SUCCESS)
183+
{
184+
SWSS_LOG_ERROR("Failed to create link local ipv6 route %s to cpu, rv:%d",
185+
linklocal_prefix.getIp().to_string().c_str(), status);
186+
throw runtime_error("Failed to create link local ipv6 route to cpu.");
187+
}
188+
189+
gCrmOrch->incCrmResUsedCounter(CrmResourceType::CRM_IPV6_ROUTE);
190+
191+
SWSS_LOG_NOTICE("Created link local ipv6 route %s to cpu", linklocal_prefix.to_string().c_str());
107192
}
108193

109194
bool RouteOrch::hasNextHopGroup(const IpAddresses& ipAddresses) const

orchagent/routeorch.h

+6
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
/* Maximum next hop group number */
1616
#define NHGRP_MAX_SIZE 128
1717

18+
/* Length of the Interface Id value in EUI64 format */
19+
#define EUI64_INTF_ID_LEN 8
20+
1821
typedef std::map<IpAddress, sai_object_id_t> NextHopGroupMembers;
1922

2023
struct NextHopGroupEntry
@@ -84,6 +87,9 @@ class RouteOrch : public Orch, public Subject
8487
bool addRoute(IpPrefix, IpAddresses);
8588
bool removeRoute(IpPrefix);
8689

90+
std::string getLinkLocalEui64Addr(void);
91+
void addLinkLocalRouteToMe(sai_object_id_t vrf_id, IpPrefix linklocal_prefix);
92+
8793
void doTask(Consumer& consumer);
8894
};
8995

0 commit comments

Comments
 (0)