diff --git a/neighsyncd/neighsync.cpp b/neighsyncd/neighsync.cpp index c1f83c3aac4a..a4967c050249 100644 --- a/neighsyncd/neighsync.cpp +++ b/neighsyncd/neighsync.cpp @@ -61,9 +61,7 @@ void NeighSync::onMsg(int nlmsg_type, struct nl_object *obj) key+= ":"; nl_addr2str(rtnl_neigh_get_dst(neigh), ipStr, MAX_ADDR_SIZE); - /* Ignore IPv6 link-local addresses as neighbors */ - if (family == IPV6_NAME && IN6_IS_ADDR_LINKLOCAL(nl_addr_get_binary_addr(rtnl_neigh_get_dst(neigh)))) - return; + /* Ignore IPv6 multicast link-local addresses as neighbors */ if (family == IPV6_NAME && IN6_IS_ADDR_MC_LINKLOCAL(nl_addr_get_binary_addr(rtnl_neigh_get_dst(neigh)))) return; diff --git a/orchagent/routeorch.cpp b/orchagent/routeorch.cpp index a75b321158ae..bff955b60dae 100644 --- a/orchagent/routeorch.cpp +++ b/orchagent/routeorch.cpp @@ -104,6 +104,91 @@ RouteOrch::RouteOrch(DBConnector *db, string tableName, NeighOrch *neighOrch) : m_syncdRoutes[v6_default_ip_prefix] = IpAddresses(); SWSS_LOG_NOTICE("Create IPv6 default route with packet action drop"); + + /* All the interfaces have the same MAC address and hence the same + * auto-generated link-local ipv6 address with eui64 interface-id. + * Hence add a single /128 route entry for the link-local interface + * address pointing to the CPU port. + */ + IpPrefix linklocal_prefix = getLinkLocalEui64Addr(); + + addLinkLocalRouteToMe(gVirtualRouterId, linklocal_prefix); + + /* Add fe80::/10 subnet route to forward all link-local packets + * destined to us, to CPU */ + IpPrefix default_link_local_prefix("fe80::/10"); + + addLinkLocalRouteToMe(gVirtualRouterId, default_link_local_prefix); + + /* TODO: Add the link-local fe80::/10 route to cpu in every VRF created from + * vrforch::addOperation. */ +} + +std::string RouteOrch::getLinkLocalEui64Addr(void) +{ + SWSS_LOG_ENTER(); + + string ip_prefix; + const uint8_t *gmac = gMacAddress.getMac(); + + uint8_t eui64_interface_id[EUI64_INTF_ID_LEN]; + char ipv6_ll_addr[INET6_ADDRSTRLEN] = {0}; + + /* Link-local IPv6 address autogenerated by kernel with eui64 interface-id + * derived from the MAC address of the host interface. + */ + eui64_interface_id[0] = gmac[0] ^ 0x02; + eui64_interface_id[1] = gmac[1]; + eui64_interface_id[2] = gmac[2]; + eui64_interface_id[3] = 0xff; + eui64_interface_id[4] = 0xfe; + eui64_interface_id[5] = gmac[3]; + eui64_interface_id[6] = gmac[4]; + eui64_interface_id[7] = gmac[5]; + + snprintf(ipv6_ll_addr, INET6_ADDRSTRLEN, "fe80::%02x%02x:%02x%02x:%02x%02x:%02x%02x", + eui64_interface_id[0], eui64_interface_id[1], eui64_interface_id[2], + eui64_interface_id[3], eui64_interface_id[4], eui64_interface_id[5], + eui64_interface_id[6], eui64_interface_id[7]); + + ip_prefix = string(ipv6_ll_addr); + + return ip_prefix; +} + +void RouteOrch::addLinkLocalRouteToMe(sai_object_id_t vrf_id, IpPrefix linklocal_prefix) +{ + sai_route_entry_t unicast_route_entry; + unicast_route_entry.switch_id = gSwitchId; + unicast_route_entry.vr_id = vrf_id; + copy(unicast_route_entry.destination, linklocal_prefix); + subnet(unicast_route_entry.destination, unicast_route_entry.destination); + + sai_attribute_t attr; + vector attrs; + + attr.id = SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION; + attr.value.s32 = SAI_PACKET_ACTION_FORWARD; + attrs.push_back(attr); + + Port cpu_port; + gPortsOrch->getCpuPort(cpu_port); + + attr.id = SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID; + attr.value.oid = cpu_port.m_port_id; + attrs.push_back(attr); + + sai_status_t status = sai_route_api->create_route_entry(&unicast_route_entry, (uint32_t)attrs.size(), attrs.data()); + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Failed to create link local ipv6 route %s to cpu, rv:%d", + linklocal_prefix.getIp().to_string().c_str(), status); + throw runtime_error("Failed to create link local ipv6 route to cpu."); + } + + gCrmOrch->incCrmResUsedCounter(CrmResourceType::CRM_IPV6_ROUTE); + + SWSS_LOG_NOTICE("Created link local ipv6 route %s to cpu", linklocal_prefix.to_string().c_str()); } bool RouteOrch::hasNextHopGroup(const IpAddresses& ipAddresses) const diff --git a/orchagent/routeorch.h b/orchagent/routeorch.h index b4d87b695863..310e93cd87ce 100644 --- a/orchagent/routeorch.h +++ b/orchagent/routeorch.h @@ -15,6 +15,9 @@ /* Maximum next hop group number */ #define NHGRP_MAX_SIZE 128 +/* Length of the Interface Id value in EUI64 format */ +#define EUI64_INTF_ID_LEN 8 + typedef std::map NextHopGroupMembers; struct NextHopGroupEntry @@ -84,6 +87,9 @@ class RouteOrch : public Orch, public Subject bool addRoute(IpPrefix, IpAddresses); bool removeRoute(IpPrefix); + std::string getLinkLocalEui64Addr(void); + void addLinkLocalRouteToMe(sai_object_id_t vrf_id, IpPrefix linklocal_prefix); + void doTask(Consumer& consumer); };