diff --git a/debian/changelog b/debian/changelog index 2d2dba5fc1..be24b1de98 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,9 @@ sonic (1.0.0) stable; urgency=medium + * next-hop key add ifname + + -- Tyler Li Thu, 19 Sep 2019 04:00:00 -0700 + * Initial release. -- Shuotian Cheng Wed, 09 Mar 2016 12:00:00 -0800 diff --git a/doc/swss-schema.md b/doc/swss-schema.md index ac7e25ce5e..b58d7cc81f 100644 --- a/doc/swss-schema.md +++ b/doc/swss-schema.md @@ -456,8 +456,10 @@ Stores rules associated with a specific ACL table on the switch. ; it could be: : name of physical port. Example: "Ethernet10" : name of LAG port Example: "PortChannel5" - : next-hop ip address Example: "10.0.0.1" - : next-hop group set of addresses Example: "10.0.0.1,10.0.0.3" + : next-hop ip address (in global) Example: "10.0.0.1" + : next-hop ip address and vrf Example: "10.0.0.2@Vrf2" + : next-hop ip address and ifname Example: "10.0.0.3@Ethernet1" + : next-hop group set of next-hop Example: "10.0.0.1,10.0.0.3@Ethernet1" redirect_action = 1*255CHAR ; redirect parameter ; This parameter defines a destination for redirected packets diff --git a/fpmsyncd/routesync.cpp b/fpmsyncd/routesync.cpp index 6f45372965..9e7a9adf4e 100644 --- a/fpmsyncd/routesync.cpp +++ b/fpmsyncd/routesync.cpp @@ -334,6 +334,17 @@ string RouteSync::getNextHopGw(struct rtnl_route *route_obj) nl_addr2str(addr, gw_ip, MAX_ADDR_SIZE); result += gw_ip; } + else + { + if (rtnl_route_get_family(route_obj) == AF_INET) + { + result += "0.0.0.0"; + } + else + { + result += "::"; + } + } if (i + 1 < rtnl_route_get_nnexthops(route_obj)) { diff --git a/orchagent/aclorch.cpp b/orchagent/aclorch.cpp index 21496c05fd..24104fd484 100644 --- a/orchagent/aclorch.cpp +++ b/orchagent/aclorch.cpp @@ -546,12 +546,12 @@ void AclRule::decreaseNextHopRefCount() { if (!m_redirect_target_next_hop.empty()) { - m_pAclOrch->m_neighOrch->decreaseNextHopRefCount(IpAddress(m_redirect_target_next_hop)); + m_pAclOrch->m_neighOrch->decreaseNextHopRefCount(NextHopKey(m_redirect_target_next_hop)); m_redirect_target_next_hop.clear(); } if (!m_redirect_target_next_hop_group.empty()) { - IpAddresses target = IpAddresses(m_redirect_target_next_hop_group); + NextHopGroupKey target = NextHopGroupKey(m_redirect_target_next_hop_group); m_pAclOrch->m_routeOrch->decreaseNextHopRefCount(target); // remove next hop group in case it's not used by anything else if (m_pAclOrch->m_routeOrch->isRefCounterZero(target)) @@ -880,44 +880,44 @@ sai_object_id_t AclRuleL3::getRedirectObjectId(const string& redirect_value) } } - // Try to parse nexthop ip address + // Try to parse nexthop ip address and interface name try { - IpAddress ip(target); - if (!m_pAclOrch->m_neighOrch->hasNextHop(ip)) + NextHopKey nh(target); + if (!m_pAclOrch->m_neighOrch->hasNextHop(nh)) { - SWSS_LOG_ERROR("ACL Redirect action target next hop ip: '%s' doesn't exist on the switch", ip.to_string().c_str()); + SWSS_LOG_ERROR("ACL Redirect action target next hop ip: '%s' doesn't exist on the switch", nh.to_string().c_str()); return SAI_NULL_OBJECT_ID; } m_redirect_target_next_hop = target; - m_pAclOrch->m_neighOrch->increaseNextHopRefCount(ip); - return m_pAclOrch->m_neighOrch->getNextHopId(ip); + m_pAclOrch->m_neighOrch->increaseNextHopRefCount(nh); + return m_pAclOrch->m_neighOrch->getNextHopId(nh); } catch (...) { // no error, just try next variant } - // try to parse nh group ip addresses + // try to parse nh group the set of try { - IpAddresses ips(target); - if (!m_pAclOrch->m_routeOrch->hasNextHopGroup(ips)) + NextHopGroupKey nhg(target); + if (!m_pAclOrch->m_routeOrch->hasNextHopGroup(nhg)) { - SWSS_LOG_INFO("ACL Redirect action target next hop group: '%s' doesn't exist on the switch. Creating it.", ips.to_string().c_str()); + SWSS_LOG_INFO("ACL Redirect action target next hop group: '%s' doesn't exist on the switch. Creating it.", nhg.to_string().c_str()); - if (!m_pAclOrch->m_routeOrch->addNextHopGroup(ips)) + if (!m_pAclOrch->m_routeOrch->addNextHopGroup(nhg)) { - SWSS_LOG_ERROR("Can't create required target next hop group '%s'", ips.to_string().c_str()); + SWSS_LOG_ERROR("Can't create required target next hop group '%s'", nhg.to_string().c_str()); return SAI_NULL_OBJECT_ID; } - SWSS_LOG_DEBUG("Created acl redirect target next hop group '%s'", ips.to_string().c_str()); + SWSS_LOG_DEBUG("Created acl redirect target next hop group '%s'", nhg.to_string().c_str()); } m_redirect_target_next_hop_group = target; - m_pAclOrch->m_routeOrch->increaseNextHopRefCount(ips); - return m_pAclOrch->m_routeOrch->getNextHopGroupId(ips); + m_pAclOrch->m_routeOrch->increaseNextHopRefCount(nhg); + return m_pAclOrch->m_routeOrch->getNextHopGroupId(nhg); } catch (...) { diff --git a/orchagent/intfsorch.cpp b/orchagent/intfsorch.cpp index c36e6757c9..cf6a926cfd 100644 --- a/orchagent/intfsorch.cpp +++ b/orchagent/intfsorch.cpp @@ -79,10 +79,35 @@ sai_object_id_t IntfsOrch::getRouterIntfsId(const string &alias) { Port port; gPortsOrch->getPort(alias, port); - assert(port.m_rif_id); return port.m_rif_id; } +string IntfsOrch::getRouterIntfsAlias(const IpAddress &ip, const string &vrf_name) +{ + sai_object_id_t vrf_id = gVirtualRouterId; + + if (!vrf_name.empty()) + { + vrf_id = m_vrfOrch->getVRFid(vrf_name); + } + + for (const auto &it_intfs: m_syncdIntfses) + { + if (it_intfs.second.vrf_id != vrf_id) + { + continue; + } + for (const auto &prefixIt: it_intfs.second.ip_addresses) + { + if (prefixIt.isAddressInSubnet(ip)) + { + return it_intfs.first; + } + } + } + return string(); +} + void IntfsOrch::increaseRouterIntfsRefCount(const string &alias) { SWSS_LOG_ENTER(); @@ -154,6 +179,7 @@ bool IntfsOrch::setIntf(const string& alias, sai_object_id_t vrf_id, const IpPre gPortsOrch->increasePortRefCount(alias); IntfsEntry intfs_entry; intfs_entry.ref_count = 0; + intfs_entry.vrf_id = vrf_id; m_syncdIntfses[alias] = intfs_entry; } else @@ -328,6 +354,7 @@ void IntfsOrch::doTask(Consumer &consumer) IntfsEntry intfs_entry; intfs_entry.ref_count = 0; + intfs_entry.vrf_id = vrf_id; intfs_entry.ip_addresses.insert(ip_prefix); m_syncdIntfses[alias] = intfs_entry; addIp2Me = true; @@ -629,7 +656,7 @@ void IntfsOrch::addSubnetRoute(const Port &port, const IpPrefix &ip_prefix) gCrmOrch->incCrmResUsedCounter(CrmResourceType::CRM_IPV6_ROUTE); } - gRouteOrch->notifyNextHopChangeObservers(ip_prefix, IpAddresses(), true); + gRouteOrch->notifyNextHopChangeObservers(ip_prefix, NextHopGroupKey(), true); } void IntfsOrch::removeSubnetRoute(const Port &port, const IpPrefix &ip_prefix) @@ -661,7 +688,7 @@ void IntfsOrch::removeSubnetRoute(const Port &port, const IpPrefix &ip_prefix) gCrmOrch->decCrmResUsedCounter(CrmResourceType::CRM_IPV6_ROUTE); } - gRouteOrch->notifyNextHopChangeObservers(ip_prefix, IpAddresses(), false); + gRouteOrch->notifyNextHopChangeObservers(ip_prefix, NextHopGroupKey(), false); } void IntfsOrch::addIp2MeRoute(sai_object_id_t vrf_id, const IpPrefix &ip_prefix) diff --git a/orchagent/intfsorch.h b/orchagent/intfsorch.h index 9030186387..acf1276a62 100644 --- a/orchagent/intfsorch.h +++ b/orchagent/intfsorch.h @@ -22,6 +22,7 @@ struct IntfsEntry { std::set ip_addresses; int ref_count; + sai_object_id_t vrf_id; }; typedef map IntfsTable; @@ -32,6 +33,7 @@ class IntfsOrch : public Orch IntfsOrch(DBConnector *db, string tableName, VRFOrch *vrf_orch); sai_object_id_t getRouterIntfsId(const string&); + string getRouterIntfsAlias(const IpAddress &ip, const string &vrf_name = ""); void increaseRouterIntfsRefCount(const string&); void decreaseRouterIntfsRefCount(const string&); diff --git a/orchagent/mirrororch.cpp b/orchagent/mirrororch.cpp index 91b07aa81a..23e1a881bf 100644 --- a/orchagent/mirrororch.cpp +++ b/orchagent/mirrororch.cpp @@ -60,7 +60,7 @@ MirrorEntry::MirrorEntry(const string& platform) : } nexthopInfo.prefix = IpPrefix("0.0.0.0/0"); - nexthopInfo.nexthop = IpAddress("0.0.0.0"); + nexthopInfo.nexthop = NextHopKey("0.0.0.0", ""); } MirrorOrch::MirrorOrch(TableConnector stateDbConnector, TableConnector confDbConnector, @@ -456,7 +456,7 @@ bool MirrorOrch::getNeighborInfo(const string& name, MirrorEntry& session) // 3) Otherwise, return false. if (!m_neighOrch->getNeighborEntry(session.dstIp, session.neighborInfo.neighbor, session.neighborInfo.mac) && - (session.nexthopInfo.nexthop.isZero() || + (session.nexthopInfo.nexthop.ip_address.isZero() || !m_neighOrch->getNeighborEntry(session.nexthopInfo.nexthop, session.neighborInfo.neighbor, session.neighborInfo.mac))) { @@ -894,8 +894,8 @@ void MirrorOrch::updateNextHop(const NextHopUpdate& update) // This is the ECMP scenario that the new next hop group contains the previous // next hop. There is no need to update this session's monitor port. - if (update.nexthopGroup != IpAddresses() && - update.nexthopGroup.getIpAddresses().count(session.nexthopInfo.nexthop)) + if (update.nexthopGroup != NextHopGroupKey() && + update.nexthopGroup.getNextHops().count(session.nexthopInfo.nexthop)) { continue; @@ -904,18 +904,18 @@ void MirrorOrch::updateNextHop(const NextHopUpdate& update) SWSS_LOG_NOTICE("Updating mirror session %s with route %s", name.c_str(), update.prefix.to_string().c_str()); - if (update.nexthopGroup != IpAddresses()) + if (update.nexthopGroup != NextHopGroupKey()) { SWSS_LOG_NOTICE(" next hop IPs: %s", update.nexthopGroup.to_string().c_str()); // Recover the session based on the state database information if (m_recoverySessionMap.find(name) != m_recoverySessionMap.end()) { - IpAddress nexthop = IpAddress(tokenize(m_recoverySessionMap[name], + NextHopKey nexthop = NextHopKey(tokenize(m_recoverySessionMap[name], state_db_key_delimiter, 1)[1]); // Check if recovered next hop IP is within the update's next hop IPs - if (update.nexthopGroup.getIpAddresses().count(nexthop)) + if (update.nexthopGroup.getNextHops().count(nexthop)) { SWSS_LOG_NOTICE("Recover mirror session %s with next hop %s", name.c_str(), nexthop.to_string().c_str()); @@ -927,18 +927,18 @@ void MirrorOrch::updateNextHop(const NextHopUpdate& update) SWSS_LOG_NOTICE("Correct mirror session %s next hop from %s to %s", name.c_str(), session.nexthopInfo.nexthop.to_string().c_str(), nexthop.to_string().c_str()); - session.nexthopInfo.nexthop = *update.nexthopGroup.getIpAddresses().begin(); + session.nexthopInfo.nexthop = *update.nexthopGroup.getNextHops().begin(); } } else { // Pick the first one from the next hop group - session.nexthopInfo.nexthop = *update.nexthopGroup.getIpAddresses().begin(); + session.nexthopInfo.nexthop = *update.nexthopGroup.getNextHops().begin(); } } else { - session.nexthopInfo.nexthop = IpAddress(0); + session.nexthopInfo.nexthop = NextHopKey("0.0.0.0", ""); } // Resolve the neighbor of the new next hop @@ -960,7 +960,7 @@ void MirrorOrch::updateNeighbor(const NeighborUpdate& update) // Check if the session's destination IP matches the neighbor's update IP // or if the session's next hop IP matches the neighbor's update IP if (session.dstIp != update.entry.ip_address && - session.nexthopInfo.nexthop != update.entry.ip_address) + session.nexthopInfo.nexthop.ip_address != update.entry.ip_address) { continue; } diff --git a/orchagent/mirrororch.h b/orchagent/mirrororch.h index 1635012a18..b367e4fba8 100644 --- a/orchagent/mirrororch.h +++ b/orchagent/mirrororch.h @@ -36,7 +36,7 @@ struct MirrorEntry struct { IpPrefix prefix; - IpAddress nexthop; + NextHopKey nexthop; } nexthopInfo; struct diff --git a/orchagent/neighorch.cpp b/orchagent/neighorch.cpp index f416841800..5f81e4ba73 100644 --- a/orchagent/neighorch.cpp +++ b/orchagent/neighorch.cpp @@ -21,12 +21,12 @@ NeighOrch::NeighOrch(DBConnector *db, string tableName, IntfsOrch *intfsOrch) : SWSS_LOG_ENTER(); } -bool NeighOrch::hasNextHop(IpAddress ipAddress) +bool NeighOrch::hasNextHop(const NextHopKey &nexthop) { - return m_syncdNextHops.find(ipAddress) != m_syncdNextHops.end(); + return m_syncdNextHops.find(nexthop) != m_syncdNextHops.end(); } -bool NeighOrch::addNextHop(IpAddress ipAddress, string alias) +bool NeighOrch::addNextHop(const IpAddress &ipAddress, const string &alias) { SWSS_LOG_ENTER(); @@ -38,7 +38,8 @@ bool NeighOrch::addNextHop(IpAddress ipAddress, string alias) return false; } - assert(!hasNextHop(ipAddress)); + NextHopKey nexthop = { ipAddress, alias }; + assert(!hasNextHop(nexthop)); sai_object_id_t rif_id = m_intfsOrch->getRouterIntfsId(alias); vector next_hop_attrs; @@ -72,8 +73,7 @@ bool NeighOrch::addNextHop(IpAddress ipAddress, string alias) next_hop_entry.next_hop_id = next_hop_id; next_hop_entry.ref_count = 0; next_hop_entry.nh_flags = 0; - next_hop_entry.if_alias = alias; - m_syncdNextHops[ipAddress] = next_hop_entry; + m_syncdNextHops[nexthop] = next_hop_entry; m_intfsOrch->increaseRouterIntfsRefCount(alias); @@ -92,7 +92,7 @@ bool NeighOrch::addNextHop(IpAddress ipAddress, string alias) // is processed after incoming port is down. if (p.m_oper_status == SAI_PORT_OPER_STATUS_DOWN) { - if (setNextHopFlag(ipAddress, NHFLAGS_IFDOWN) == false) + if (setNextHopFlag(nexthop, NHFLAGS_IFDOWN) == false) { SWSS_LOG_WARN("Failed to set NHFLAGS_IFDOWN on nexthop %s for interface %s", ipAddress.to_string().c_str(), alias.c_str()); @@ -101,11 +101,11 @@ bool NeighOrch::addNextHop(IpAddress ipAddress, string alias) return true; } -bool NeighOrch::setNextHopFlag(const IpAddress &ipaddr, const uint32_t nh_flag) +bool NeighOrch::setNextHopFlag(const NextHopKey &nexthop, const uint32_t nh_flag) { SWSS_LOG_ENTER(); - auto nhop = m_syncdNextHops.find(ipaddr); + auto nhop = m_syncdNextHops.find(nexthop); bool rc = false; assert(nhop != m_syncdNextHops.end()); @@ -120,7 +120,7 @@ bool NeighOrch::setNextHopFlag(const IpAddress &ipaddr, const uint32_t nh_flag) switch (nh_flag) { case NHFLAGS_IFDOWN: - rc = gRouteOrch->invalidnexthopinNextHopGroup(ipaddr); + rc = gRouteOrch->invalidnexthopinNextHopGroup(nexthop); break; default: assert(0); @@ -130,11 +130,11 @@ bool NeighOrch::setNextHopFlag(const IpAddress &ipaddr, const uint32_t nh_flag) return rc; } -bool NeighOrch::clearNextHopFlag(const IpAddress &ipaddr, const uint32_t nh_flag) +bool NeighOrch::clearNextHopFlag(const NextHopKey &nexthop, const uint32_t nh_flag) { SWSS_LOG_ENTER(); - auto nhop = m_syncdNextHops.find(ipaddr); + auto nhop = m_syncdNextHops.find(nexthop); bool rc = false; assert(nhop != m_syncdNextHops.end()); @@ -149,7 +149,7 @@ bool NeighOrch::clearNextHopFlag(const IpAddress &ipaddr, const uint32_t nh_flag switch (nh_flag) { case NHFLAGS_IFDOWN: - rc = gRouteOrch->validnexthopinNextHopGroup(ipaddr); + rc = gRouteOrch->validnexthopinNextHopGroup(nexthop); break; default: assert(0); @@ -159,11 +159,11 @@ bool NeighOrch::clearNextHopFlag(const IpAddress &ipaddr, const uint32_t nh_flag return rc; } -bool NeighOrch::isNextHopFlagSet(const IpAddress &ipaddr, const uint32_t nh_flag) +bool NeighOrch::isNextHopFlagSet(const NextHopKey &nexthop, const uint32_t nh_flag) { SWSS_LOG_ENTER(); - auto nhop = m_syncdNextHops.find(ipaddr); + auto nhop = m_syncdNextHops.find(nexthop); assert(nhop != m_syncdNextHops.end()); @@ -182,7 +182,7 @@ bool NeighOrch::ifChangeInformNextHop(const string &alias, bool if_up) for (auto nhop = m_syncdNextHops.begin(); nhop != m_syncdNextHops.end(); ++nhop) { - if (nhop->second.if_alias != alias) + if (nhop->first.alias != alias) { continue; } @@ -209,58 +209,59 @@ bool NeighOrch::ifChangeInformNextHop(const string &alias, bool if_up) return rc; } -bool NeighOrch::removeNextHop(IpAddress ipAddress, string alias) +bool NeighOrch::removeNextHop(const IpAddress &ipAddress, const string &alias) { SWSS_LOG_ENTER(); - assert(hasNextHop(ipAddress)); + NextHopKey nexthop = { ipAddress, alias }; + assert(hasNextHop(nexthop)); - if (m_syncdNextHops[ipAddress].ref_count > 0) + if (m_syncdNextHops[nexthop].ref_count > 0) { SWSS_LOG_ERROR("Failed to remove still referenced next hop %s on %s", ipAddress.to_string().c_str(), alias.c_str()); return false; } - m_syncdNextHops.erase(ipAddress); + m_syncdNextHops.erase(nexthop); m_intfsOrch->decreaseRouterIntfsRefCount(alias); return true; } -sai_object_id_t NeighOrch::getNextHopId(const IpAddress &ipAddress) +sai_object_id_t NeighOrch::getNextHopId(const NextHopKey &nexthop) { - assert(hasNextHop(ipAddress)); - return m_syncdNextHops[ipAddress].next_hop_id; + assert(hasNextHop(nexthop)); + return m_syncdNextHops[nexthop].next_hop_id; } -int NeighOrch::getNextHopRefCount(const IpAddress &ipAddress) +int NeighOrch::getNextHopRefCount(const NextHopKey &nexthop) { - assert(hasNextHop(ipAddress)); - return m_syncdNextHops[ipAddress].ref_count; + assert(hasNextHop(nexthop)); + return m_syncdNextHops[nexthop].ref_count; } -void NeighOrch::increaseNextHopRefCount(const IpAddress &ipAddress) +void NeighOrch::increaseNextHopRefCount(const NextHopKey &nexthop) { - assert(hasNextHop(ipAddress)); - m_syncdNextHops[ipAddress].ref_count ++; + assert(hasNextHop(nexthop)); + m_syncdNextHops[nexthop].ref_count ++; } -void NeighOrch::decreaseNextHopRefCount(const IpAddress &ipAddress) +void NeighOrch::decreaseNextHopRefCount(const NextHopKey &nexthop) { - assert(hasNextHop(ipAddress)); - m_syncdNextHops[ipAddress].ref_count --; + assert(hasNextHop(nexthop)); + m_syncdNextHops[nexthop].ref_count --; } -bool NeighOrch::getNeighborEntry(const IpAddress &ipAddress, NeighborEntry &neighborEntry, MacAddress &macAddress) +bool NeighOrch::getNeighborEntry(const NextHopKey &nexthop, NeighborEntry &neighborEntry, MacAddress &macAddress) { - if (!hasNextHop(ipAddress)) + if (!hasNextHop(nexthop)) { return false; } for (const auto &entry : m_syncdNeighbors) { - if (entry.first.ip_address == ipAddress) + if (entry.first.ip_address == nexthop.ip_address && entry.first.alias == nexthop.alias) { neighborEntry = entry.first; macAddress = entry.second; @@ -271,6 +272,18 @@ bool NeighOrch::getNeighborEntry(const IpAddress &ipAddress, NeighborEntry &neig return false; } +bool NeighOrch::getNeighborEntry(const IpAddress &ipAddress, NeighborEntry &neighborEntry, MacAddress &macAddress) +{ + string alias = m_intfsOrch->getRouterIntfsAlias(ipAddress); + if (alias.empty()) + { + return false; + } + + NextHopKey nexthop(ipAddress, alias); + return getNeighborEntry(nexthop, neighborEntry, macAddress); +} + void NeighOrch::doTask(Consumer &consumer) { SWSS_LOG_ENTER(); @@ -369,7 +382,7 @@ void NeighOrch::doTask(Consumer &consumer) } } -bool NeighOrch::addNeighbor(NeighborEntry neighborEntry, MacAddress macAddress) +bool NeighOrch::addNeighbor(const NeighborEntry &neighborEntry, const MacAddress &macAddress) { SWSS_LOG_ENTER(); @@ -378,6 +391,11 @@ bool NeighOrch::addNeighbor(NeighborEntry neighborEntry, MacAddress macAddress) string alias = neighborEntry.alias; sai_object_id_t rif_id = m_intfsOrch->getRouterIntfsId(alias); + if (rif_id == SAI_NULL_OBJECT_ID) + { + SWSS_LOG_INFO("Failed to get rif_id for %s", alias.c_str()); + return false; + } sai_neighbor_entry_t neighbor_entry; neighbor_entry.rif_id = rif_id; @@ -463,20 +481,21 @@ bool NeighOrch::addNeighbor(NeighborEntry neighborEntry, MacAddress macAddress) return true; } -bool NeighOrch::removeNeighbor(NeighborEntry neighborEntry) +bool NeighOrch::removeNeighbor(const NeighborEntry &neighborEntry) { SWSS_LOG_ENTER(); sai_status_t status; IpAddress ip_address = neighborEntry.ip_address; string alias = neighborEntry.alias; + NextHopKey nexthop = { ip_address, alias }; if (m_syncdNeighbors.find(neighborEntry) == m_syncdNeighbors.end()) { return true; } - if (m_syncdNextHops[ip_address].ref_count > 0) + if (m_syncdNextHops[nexthop].ref_count > 0) { SWSS_LOG_INFO("Failed to remove still referenced neighbor %s on %s", m_syncdNeighbors[neighborEntry].to_string().c_str(), alias.c_str()); @@ -490,7 +509,7 @@ bool NeighOrch::removeNeighbor(NeighborEntry neighborEntry) neighbor_entry.switch_id = gSwitchId; copy(neighbor_entry.ip_address, ip_address); - sai_object_id_t next_hop_id = m_syncdNextHops[ip_address].next_hop_id; + sai_object_id_t next_hop_id = m_syncdNextHops[nexthop].next_hop_id; status = sai_next_hop_api->remove_next_hop(next_hop_id); if (status != SAI_STATUS_SUCCESS) { diff --git a/orchagent/neighorch.h b/orchagent/neighorch.h index 71257d1415..60c40f9053 100644 --- a/orchagent/neighorch.h +++ b/orchagent/neighorch.h @@ -7,42 +7,23 @@ #include "intfsorch.h" #include "ipaddress.h" +#include "nexthopkey.h" #define NHFLAGS_IFDOWN 0x1 // nexthop's outbound i/f is down -struct NeighborEntry -{ - IpAddress ip_address; // neighbor IP address - string alias; // incoming interface alias - - bool operator<(const NeighborEntry &o) const - { - return tie(ip_address, alias) < tie(o.ip_address, o.alias); - } - - bool operator==(const NeighborEntry &o) const - { - return (ip_address == o.ip_address) && (alias == o.alias); - } - - bool operator!=(const NeighborEntry &o) const - { - return !(*this == o); - } -}; +typedef NextHopKey NeighborEntry; struct NextHopEntry { sai_object_id_t next_hop_id; // next hop id int ref_count; // reference count uint32_t nh_flags; // flags - string if_alias; // i/f name alias }; /* NeighborTable: NeighborEntry, neighbor MAC address */ typedef map NeighborTable; -/* NextHopTable: next hop IP address, NextHopEntry */ -typedef map NextHopTable; +/* NextHopTable: NextHopKey, NextHopEntry */ +typedef map NextHopTable; struct NeighborUpdate { @@ -56,18 +37,19 @@ class NeighOrch : public Orch, public Subject public: NeighOrch(DBConnector *db, string tableName, IntfsOrch *intfsOrch); - bool hasNextHop(IpAddress); + bool hasNextHop(const NextHopKey&); - sai_object_id_t getNextHopId(const IpAddress&); - int getNextHopRefCount(const IpAddress&); + sai_object_id_t getNextHopId(const NextHopKey&); + int getNextHopRefCount(const NextHopKey&); - void increaseNextHopRefCount(const IpAddress&); - void decreaseNextHopRefCount(const IpAddress&); + void increaseNextHopRefCount(const NextHopKey&); + void decreaseNextHopRefCount(const NextHopKey&); + bool getNeighborEntry(const NextHopKey&, NeighborEntry&, MacAddress&); bool getNeighborEntry(const IpAddress&, NeighborEntry&, MacAddress&); bool ifChangeInformNextHop(const string &, bool); - bool isNextHopFlagSet(const IpAddress &, const uint32_t); + bool isNextHopFlagSet(const NextHopKey &, const uint32_t); private: IntfsOrch *m_intfsOrch; @@ -75,14 +57,14 @@ class NeighOrch : public Orch, public Subject NeighborTable m_syncdNeighbors; NextHopTable m_syncdNextHops; - bool addNextHop(IpAddress, string); - bool removeNextHop(IpAddress, string); + bool addNextHop(const IpAddress&, const string&); + bool removeNextHop(const IpAddress&, const string&); - bool addNeighbor(NeighborEntry, MacAddress); - bool removeNeighbor(NeighborEntry); + bool addNeighbor(const NeighborEntry&, const MacAddress&); + bool removeNeighbor(const NeighborEntry&); - bool setNextHopFlag(const IpAddress &, const uint32_t); - bool clearNextHopFlag(const IpAddress &, const uint32_t); + bool setNextHopFlag(const NextHopKey &, const uint32_t); + bool clearNextHopFlag(const NextHopKey &, const uint32_t); void doTask(Consumer &consumer); }; diff --git a/orchagent/nexthopgroupkey.h b/orchagent/nexthopgroupkey.h new file mode 100644 index 0000000000..6e90845d90 --- /dev/null +++ b/orchagent/nexthopgroupkey.h @@ -0,0 +1,126 @@ +#ifndef SWSS_NEXTHOPGROUPKEY_H +#define SWSS_NEXTHOPGROUPKEY_H + +#include "nexthopkey.h" + +class NextHopGroupKey +{ +public: + NextHopGroupKey() = default; + + /* ip_string@if_alias separated by ',' */ + NextHopGroupKey(const std::string &nexthops) + { + auto nhv = tokenize(nexthops, NHG_DELIMITER); + for (const auto &nh : nhv) + { + m_nexthops.insert(nh); + } + } + + inline const std::set &getNextHops() const + { + return m_nexthops; + } + + inline size_t getSize() const + { + return m_nexthops.size(); + } + + inline bool operator<(const NextHopGroupKey &o) const + { + return m_nexthops < o.m_nexthops; + } + + inline bool operator==(const NextHopGroupKey &o) const + { + return m_nexthops == o.m_nexthops; + } + + inline bool operator!=(const NextHopGroupKey &o) const + { + return !(*this == o); + } + + void add(const std::string &ip, const std::string &alias) + { + m_nexthops.emplace(ip, alias); + } + + void add(const std::string &nh) + { + m_nexthops.insert(nh); + } + + void add(const NextHopKey &nh) + { + m_nexthops.insert(nh); + } + + bool contains(const std::string &ip, const std::string &alias) const + { + NextHopKey nh(ip, alias); + return m_nexthops.find(nh) != m_nexthops.end(); + } + + bool contains(const std::string &nh) const + { + return m_nexthops.find(nh) != m_nexthops.end(); + } + + bool contains(const NextHopKey &nh) const + { + return m_nexthops.find(nh) != m_nexthops.end(); + } + + bool contains(const NextHopGroupKey &nhs) const + { + for (const auto &nh : nhs.getNextHops()) + { + if (!contains(nh)) + { + return false; + } + } + return true; + } + + void remove(const std::string &ip, const std::string &alias) + { + NextHopKey nh(ip, alias); + m_nexthops.erase(nh); + } + + void remove(const std::string &nh) + { + m_nexthops.erase(nh); + } + + void remove(const NextHopKey &nh) + { + m_nexthops.erase(nh); + } + + const std::string to_string() const + { + string nhs_str; + + for (auto it = m_nexthops.begin(); it != m_nexthops.end(); ++it) + { + if (it != m_nexthops.begin()) + { + nhs_str += NHG_DELIMITER; + } + + nhs_str += it->to_string(); + } + + return nhs_str; + } + +private: + std::set m_nexthops; +}; + +#endif /* SWSS_NEXTHOPGROUPKEY_H */ diff --git a/orchagent/nexthopkey.h b/orchagent/nexthopkey.h new file mode 100644 index 0000000000..a86aac2cc1 --- /dev/null +++ b/orchagent/nexthopkey.h @@ -0,0 +1,69 @@ +#ifndef SWSS_NEXTHOPKEY_H +#define SWSS_NEXTHOPKEY_H + +#include "ipaddress.h" +#include "tokenize.h" + +#define NH_DELIMITER '@' +#define NHG_DELIMITER ',' +#define VRF_PREFIX "Vrf" +extern IntfsOrch *gIntfsOrch; + +struct NextHopKey +{ + IpAddress ip_address; // neighbor IP address + string alias; // incoming interface alias + + NextHopKey() = default; + NextHopKey(const std::string &ipstr, const std::string &alias) : ip_address(ipstr), alias(alias) {} + NextHopKey(const IpAddress &ip, const std::string &alias) : ip_address(ip), alias(alias) {} + NextHopKey(const std::string &str) + { + if (str.find(NHG_DELIMITER) != string::npos) + { + std::string err = "Error converting " + str + " to NextHop"; + throw std::invalid_argument(err); + } + auto keys = tokenize(str, NH_DELIMITER); + if (keys.size() == 1) + { + ip_address = keys[0]; + alias = gIntfsOrch->getRouterIntfsAlias(ip_address); + } + else if (keys.size() == 2) + { + ip_address = keys[0]; + alias = keys[1]; + if (!alias.compare(0, strlen(VRF_PREFIX), VRF_PREFIX)) + { + alias = gIntfsOrch->getRouterIntfsAlias(ip_address, alias); + } + } + else + { + std::string err = "Error converting " + str + " to NextHop"; + throw std::invalid_argument(err); + } + } + const std::string to_string() const + { + return ip_address.to_string() + NH_DELIMITER + alias; + } + + bool operator<(const NextHopKey &o) const + { + return tie(ip_address, alias) < tie(o.ip_address, o.alias); + } + + bool operator==(const NextHopKey &o) const + { + return (ip_address == o.ip_address) && (alias == o.alias); + } + + bool operator!=(const NextHopKey &o) const + { + return !(*this == o); + } +}; + +#endif /* SWSS_NEXTHOPKEY_H */ diff --git a/orchagent/routeorch.cpp b/orchagent/routeorch.cpp index bff955b60d..1b611ca890 100644 --- a/orchagent/routeorch.cpp +++ b/orchagent/routeorch.cpp @@ -82,7 +82,7 @@ RouteOrch::RouteOrch(DBConnector *db, string tableName, NeighOrch *neighOrch) : gCrmOrch->incCrmResUsedCounter(CrmResourceType::CRM_IPV4_ROUTE); /* Add default IPv4 route into the m_syncdRoutes */ - m_syncdRoutes[default_ip_prefix] = IpAddresses(); + m_syncdRoutes[default_ip_prefix] = NextHopGroupKey(); SWSS_LOG_NOTICE("Create IPv4 default route with packet action drop"); @@ -101,7 +101,7 @@ RouteOrch::RouteOrch(DBConnector *db, string tableName, NeighOrch *neighOrch) : gCrmOrch->incCrmResUsedCounter(CrmResourceType::CRM_IPV6_ROUTE); /* Add default IPv6 route into the m_syncdRoutes */ - m_syncdRoutes[v6_default_ip_prefix] = IpAddresses(); + m_syncdRoutes[v6_default_ip_prefix] = NextHopGroupKey(); SWSS_LOG_NOTICE("Create IPv6 default route with packet action drop"); @@ -191,15 +191,15 @@ void RouteOrch::addLinkLocalRouteToMe(sai_object_id_t vrf_id, IpPrefix linklocal SWSS_LOG_NOTICE("Created link local ipv6 route %s to cpu", linklocal_prefix.to_string().c_str()); } -bool RouteOrch::hasNextHopGroup(const IpAddresses& ipAddresses) const +bool RouteOrch::hasNextHopGroup(const NextHopGroupKey& nexthops) const { - return m_syncdNextHopGroups.find(ipAddresses) != m_syncdNextHopGroups.end(); + return m_syncdNextHopGroups.find(nexthops) != m_syncdNextHopGroups.end(); } -sai_object_id_t RouteOrch::getNextHopGroupId(const IpAddresses& ipAddresses) +sai_object_id_t RouteOrch::getNextHopGroupId(const NextHopGroupKey& nexthops) { - assert(hasNextHopGroup(ipAddresses)); - return m_syncdNextHopGroups[ipAddresses].next_hop_group_id; + assert(hasNextHopGroup(nexthops)); + return m_syncdNextHopGroups[nexthops].next_hop_group_id; } void RouteOrch::attach(Observer *observer, const IpAddress& dstAddr) @@ -234,7 +234,7 @@ void RouteOrch::attach(Observer *observer, const IpAddress& dstAddr) if (prefix.isAddressInSubnet(dstAddr)) { observerEntry->second.routeTable.emplace( - prefix, IpAddresses()); + prefix, NextHopGroupKey()); } } } @@ -290,7 +290,7 @@ void RouteOrch::detach(Observer *observer, const IpAddress& dstAddr) } } -bool RouteOrch::validnexthopinNextHopGroup(const IpAddress &ipaddr) +bool RouteOrch::validnexthopinNextHopGroup(const NextHopKey &nexthop) { SWSS_LOG_ENTER(); @@ -301,7 +301,7 @@ bool RouteOrch::validnexthopinNextHopGroup(const IpAddress &ipaddr) nhopgroup != m_syncdNextHopGroups.end(); ++nhopgroup) { - if (!(nhopgroup->first.contains(ipaddr))) + if (!(nhopgroup->first.contains(nexthop))) { continue; } @@ -314,7 +314,7 @@ bool RouteOrch::validnexthopinNextHopGroup(const IpAddress &ipaddr) nhgm_attrs.push_back(nhgm_attr); nhgm_attr.id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID; - nhgm_attr.value.oid = m_neighOrch->getNextHopId(ipaddr); + nhgm_attr.value.oid = m_neighOrch->getNextHopId(nexthop); nhgm_attrs.push_back(nhgm_attr); status = sai_next_hop_group_api->create_next_hop_group_member(&nexthop_id, gSwitchId, @@ -329,13 +329,13 @@ bool RouteOrch::validnexthopinNextHopGroup(const IpAddress &ipaddr) } gCrmOrch->incCrmResUsedCounter(CrmResourceType::CRM_NEXTHOP_GROUP_MEMBER); - nhopgroup->second.nhopgroup_members[ipaddr] = nexthop_id; + nhopgroup->second.nhopgroup_members[nexthop] = nexthop_id; } return true; } -bool RouteOrch::invalidnexthopinNextHopGroup(const IpAddress &ipaddr) +bool RouteOrch::invalidnexthopinNextHopGroup(const NextHopKey &nexthop) { SWSS_LOG_ENTER(); @@ -346,12 +346,12 @@ bool RouteOrch::invalidnexthopinNextHopGroup(const IpAddress &ipaddr) nhopgroup != m_syncdNextHopGroups.end(); ++nhopgroup) { - if (!(nhopgroup->first.contains(ipaddr))) + if (!(nhopgroup->first.contains(nexthop))) { continue; } - nexthop_id = nhopgroup->second.nhopgroup_members[ipaddr]; + nexthop_id = nhopgroup->second.nhopgroup_members[nexthop]; status = sai_next_hop_group_api->remove_next_hop_group_member(nexthop_id); if (status != SAI_STATUS_SUCCESS) @@ -426,28 +426,32 @@ void RouteOrch::doTask(Consumer& consumer) if (op == SET_COMMAND) { - IpAddresses ip_addresses; - string alias; + string ips; + string aliases; + bool excp_intfs_flag = false; for (auto i : kfvFieldsValues(t)) { if (fvField(i) == "nexthop") - ip_addresses = IpAddresses(fvValue(i)); + ips = fvValue(i); if (fvField(i) == "ifname") - alias = fvValue(i); + aliases = fvValue(i); } + vector ipv = tokenize(ips, ','); + vector alsv = tokenize(aliases, ','); - // TODO: set to blackhold if nexthop is empty? - if (ip_addresses.getSize() == 0) + for (auto alias : alsv) { - it = consumer.m_toSync.erase(it); - continue; + if (alias == "eth0" || alias == "lo" || alias == "docker0") + { + excp_intfs_flag = true; + break; + } } // TODO: cannot trust m_portsOrch->getPortIdByAlias because sometimes alias is empty - // TODO: need to split aliases with ',' and verify the next hops? - if (alias == "eth0" || alias == "lo" || alias == "docker0") + if (excp_intfs_flag) { /* If any existing routes are updated to point to the * above interfaces, remove them from the ASIC. */ @@ -463,9 +467,23 @@ void RouteOrch::doTask(Consumer& consumer) continue; } - if (m_syncdRoutes.find(ip_prefix) == m_syncdRoutes.end() || m_syncdRoutes[ip_prefix] != ip_addresses) + string nhg_str = ipv[0] + NH_DELIMITER + alsv[0]; + for (uint32_t i = 1; i < ipv.size(); i++) + { + nhg_str += NHG_DELIMITER + ipv[i] + NH_DELIMITER + alsv[i]; + } + + NextHopGroupKey nhg(nhg_str); + + if (ipv.size() == 1 && IpAddress(ipv[0]).isZero()) { - if (addRoute(ip_prefix, ip_addresses)) + it = consumer.m_toSync.erase(it); + continue; + } + + if (m_syncdRoutes.find(ip_prefix) == m_syncdRoutes.end() || m_syncdRoutes[ip_prefix] != nhg) + { + if (addRoute(ip_prefix, nhg)) it = consumer.m_toSync.erase(it); else it++; @@ -495,7 +513,7 @@ void RouteOrch::doTask(Consumer& consumer) } } -void RouteOrch::notifyNextHopChangeObservers(IpPrefix prefix, IpAddresses nexthops, bool add) +void RouteOrch::notifyNextHopChangeObservers(const IpPrefix &prefix, const NextHopGroupKey &nexthops, bool add) { SWSS_LOG_ENTER(); @@ -576,57 +594,56 @@ void RouteOrch::notifyNextHopChangeObservers(IpPrefix prefix, IpAddresses nextho } } -void RouteOrch::increaseNextHopRefCount(IpAddresses ipAddresses) +void RouteOrch::increaseNextHopRefCount(const NextHopGroupKey &nexthops) { /* Return when there is no next hop (dropped) */ - if (ipAddresses.getSize() == 0) + if (nexthops.getSize() == 0) { return; } - else if (ipAddresses.getSize() == 1) + else if (nexthops.getSize() == 1) { - IpAddress ip_address(ipAddresses.to_string()); - m_neighOrch->increaseNextHopRefCount(ip_address); + NextHopKey nexthop(nexthops.to_string()); + m_neighOrch->increaseNextHopRefCount(nexthop); } else { - m_syncdNextHopGroups[ipAddresses].ref_count ++; + m_syncdNextHopGroups[nexthops].ref_count ++; } } -void RouteOrch::decreaseNextHopRefCount(IpAddresses ipAddresses) +void RouteOrch::decreaseNextHopRefCount(const NextHopGroupKey &nexthops) { /* Return when there is no next hop (dropped) */ - if (ipAddresses.getSize() == 0) + if (nexthops.getSize() == 0) { return; } - else if (ipAddresses.getSize() == 1) + else if (nexthops.getSize() == 1) { - IpAddress ip_address(ipAddresses.to_string()); - - m_neighOrch->decreaseNextHopRefCount(ip_address); + NextHopKey nexthop(nexthops.to_string()); + m_neighOrch->decreaseNextHopRefCount(nexthop); } else { - m_syncdNextHopGroups[ipAddresses].ref_count --; + m_syncdNextHopGroups[nexthops].ref_count --; } } -bool RouteOrch::isRefCounterZero(const IpAddresses& ipAddresses) const +bool RouteOrch::isRefCounterZero(const NextHopGroupKey &nexthops) const { - if (!hasNextHopGroup(ipAddresses)) + if (!hasNextHopGroup(nexthops)) { return true; } - return m_syncdNextHopGroups.at(ipAddresses).ref_count == 0; + return m_syncdNextHopGroups.at(nexthops).ref_count == 0; } -bool RouteOrch::addNextHopGroup(IpAddresses ipAddresses) +bool RouteOrch::addNextHopGroup(const NextHopGroupKey &nexthops) { SWSS_LOG_ENTER(); - assert(!hasNextHopGroup(ipAddresses)); + assert(!hasNextHopGroup(nexthops)); if (m_nextHopGroupCount >= m_maxNextHopGroupCount) { @@ -636,8 +653,8 @@ bool RouteOrch::addNextHopGroup(IpAddresses ipAddresses) } vector next_hop_ids; - set next_hop_set = ipAddresses.getIpAddresses(); - std::map nhopgroup_members_set; + set next_hop_set = nexthops.getNextHops(); + std::map nhopgroup_members_set; /* Assert each IP address exists in m_syncdNextHops table, * and add the corresponding next_hop_id to next_hop_ids. */ @@ -646,7 +663,7 @@ bool RouteOrch::addNextHopGroup(IpAddresses ipAddresses) if (!m_neighOrch->hasNextHop(it)) { SWSS_LOG_INFO("Failed to get next hop %s in %s", - it.to_string().c_str(), ipAddresses.to_string().c_str()); + it.to_string().c_str(), nexthops.to_string().c_str()); return false; } @@ -671,12 +688,12 @@ bool RouteOrch::addNextHopGroup(IpAddresses ipAddresses) if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Failed to create next hop group %s, rv:%d", - ipAddresses.to_string().c_str(), status); + nexthops.to_string().c_str(), status); return false; } m_nextHopGroupCount ++; - SWSS_LOG_NOTICE("Create next hop group %s", ipAddresses.to_string().c_str()); + SWSS_LOG_NOTICE("Create next hop group %s", nexthops.to_string().c_str()); gCrmOrch->incCrmResUsedCounter(CrmResourceType::CRM_NEXTHOP_GROUP); @@ -732,18 +749,18 @@ bool RouteOrch::addNextHopGroup(IpAddresses ipAddresses) * count will increase once the route is successfully syncd. */ next_hop_group_entry.ref_count = 0; - m_syncdNextHopGroups[ipAddresses] = next_hop_group_entry; + m_syncdNextHopGroups[nexthops] = next_hop_group_entry; return true; } -bool RouteOrch::removeNextHopGroup(IpAddresses ipAddresses) +bool RouteOrch::removeNextHopGroup(const NextHopGroupKey &nexthops) { SWSS_LOG_ENTER(); sai_object_id_t next_hop_group_id; - auto next_hop_group_entry = m_syncdNextHopGroups.find(ipAddresses); + auto next_hop_group_entry = m_syncdNextHopGroups.find(nexthops); sai_status_t status; assert(next_hop_group_entry != m_syncdNextHopGroups.end()); @@ -754,7 +771,7 @@ bool RouteOrch::removeNextHopGroup(IpAddresses ipAddresses) } next_hop_group_id = next_hop_group_entry->second.next_hop_group_id; - SWSS_LOG_NOTICE("Delete next hop group %s", ipAddresses.to_string().c_str()); + SWSS_LOG_NOTICE("Delete next hop group %s", nexthops.to_string().c_str()); for (auto nhop = next_hop_group_entry->second.nhopgroup_members.begin(); nhop != next_hop_group_entry->second.nhopgroup_members.end();) @@ -789,21 +806,21 @@ bool RouteOrch::removeNextHopGroup(IpAddresses ipAddresses) m_nextHopGroupCount --; gCrmOrch->decCrmResUsedCounter(CrmResourceType::CRM_NEXTHOP_GROUP); - set ip_address_set = ipAddresses.getIpAddresses(); - for (auto it : ip_address_set) + set next_hop_set = nexthops.getNextHops(); + for (auto it : next_hop_set) { m_neighOrch->decreaseNextHopRefCount(it); } - m_syncdNextHopGroups.erase(ipAddresses); + m_syncdNextHopGroups.erase(nexthops); return true; } -void RouteOrch::addTempRoute(IpPrefix ipPrefix, IpAddresses nextHops) +void RouteOrch::addTempRoute(const IpPrefix &ipPrefix, const NextHopGroupKey &nextHops) { SWSS_LOG_ENTER(); - auto next_hop_set = nextHops.getIpAddresses(); + auto next_hop_set = nextHops.getNextHops(); /* Remove next hops that are not in m_syncdNextHops */ for (auto it = next_hop_set.begin(); it != next_hop_set.end();) @@ -827,11 +844,11 @@ void RouteOrch::addTempRoute(IpPrefix ipPrefix, IpAddresses nextHops) advance(it, rand() % next_hop_set.size()); /* Set the route's temporary next hop to be the randomly picked one */ - IpAddresses tmp_next_hop((*it).to_string()); + NextHopGroupKey tmp_next_hop((*it).to_string()); addRoute(ipPrefix, tmp_next_hop); } -bool RouteOrch::addRoute(IpPrefix ipPrefix, IpAddresses nextHops) +bool RouteOrch::addRoute(const IpPrefix &ipPrefix, const NextHopGroupKey &nextHops) { SWSS_LOG_ENTER(); @@ -842,10 +859,10 @@ bool RouteOrch::addRoute(IpPrefix ipPrefix, IpAddresses nextHops) /* The route is pointing to a next hop */ if (nextHops.getSize() == 1) { - IpAddress ip_address(nextHops.to_string()); - if (m_neighOrch->hasNextHop(ip_address)) + NextHopKey nexthop(nextHops.to_string()); + if (m_neighOrch->hasNextHop(nexthop)) { - next_hop_id = m_neighOrch->getNextHopId(ip_address); + next_hop_id = m_neighOrch->getNextHopId(nexthop); } else { @@ -869,8 +886,8 @@ bool RouteOrch::addRoute(IpPrefix ipPrefix, IpAddresses nextHops) * then return false and no need to add another temporary route. */ if (it_route != m_syncdRoutes.end() && it_route->second.getSize() == 1) { - IpAddress ip_address(it_route->second.to_string()); - if (nextHops.contains(ip_address)) + NextHopKey nexthop(it_route->second.to_string()); + if (nextHops.contains(nexthop)) { return false; } @@ -985,7 +1002,7 @@ bool RouteOrch::addRoute(IpPrefix ipPrefix, IpAddresses nextHops) return true; } -bool RouteOrch::removeRoute(IpPrefix ipPrefix) +bool RouteOrch::removeRoute(const IpPrefix &ipPrefix) { SWSS_LOG_ENTER(); @@ -1065,7 +1082,7 @@ bool RouteOrch::removeRoute(IpPrefix ipPrefix) if (ipPrefix.isDefaultRoute()) { - m_syncdRoutes[ipPrefix] = IpAddresses(); + m_syncdRoutes[ipPrefix] = NextHopGroupKey(); /* Notify about default route next hop change */ notifyNextHopChangeObservers(ipPrefix, m_syncdRoutes[ipPrefix], true); @@ -1075,7 +1092,7 @@ bool RouteOrch::removeRoute(IpPrefix ipPrefix) m_syncdRoutes.erase(ipPrefix); /* Notify about the route next hop removal */ - notifyNextHopChangeObservers(ipPrefix, IpAddresses(), false); + notifyNextHopChangeObservers(ipPrefix, NextHopGroupKey(), false); } return true; diff --git a/orchagent/routeorch.h b/orchagent/routeorch.h index 310e93cd87..e00223245c 100644 --- a/orchagent/routeorch.h +++ b/orchagent/routeorch.h @@ -9,37 +9,37 @@ #include "ipaddress.h" #include "ipaddresses.h" #include "ipprefix.h" +#include "nexthopgroupkey.h" #include /* 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; +typedef std::map NextHopGroupMembers; struct NextHopGroupEntry { sai_object_id_t next_hop_group_id; // next hop group id int ref_count; // reference count - NextHopGroupMembers nhopgroup_members; // ids of members indexed by ip address + NextHopGroupMembers nhopgroup_members; // ids of members indexed by }; struct NextHopUpdate { IpAddress destination; IpPrefix prefix; - IpAddresses nexthopGroup; + NextHopGroupKey nexthopGroup; }; struct NextHopObserverEntry; -/* NextHopGroupTable: next hop group IP addersses, NextHopGroupEntry */ -typedef std::map NextHopGroupTable; -/* RouteTable: destination network, next hop IP address(es) */ -typedef std::map RouteTable; +/* NextHopGroupTable: NextHopGroupKey, NextHopGroupEntry */ +typedef std::map NextHopGroupTable; +/* RouteTable: destination network, NextHopGroupKey */ +typedef std::map RouteTable; /* NextHopObserverTable: Destination IP address, next hop observer entry */ typedef std::map NextHopObserverTable; @@ -54,23 +54,23 @@ class RouteOrch : public Orch, public Subject public: RouteOrch(DBConnector *db, string tableName, NeighOrch *neighOrch); - bool hasNextHopGroup(const IpAddresses&) const; - sai_object_id_t getNextHopGroupId(const IpAddresses&); + bool hasNextHopGroup(const NextHopGroupKey&) const; + sai_object_id_t getNextHopGroupId(const NextHopGroupKey&); void attach(Observer *, const IpAddress&); void detach(Observer *, const IpAddress&); - void increaseNextHopRefCount(IpAddresses); - void decreaseNextHopRefCount(IpAddresses); - bool isRefCounterZero(const IpAddresses&) const; + void increaseNextHopRefCount(const NextHopGroupKey&); + void decreaseNextHopRefCount(const NextHopGroupKey&); + bool isRefCounterZero(const NextHopGroupKey&) const; - bool addNextHopGroup(IpAddresses); - bool removeNextHopGroup(IpAddresses); + bool addNextHopGroup(const NextHopGroupKey&); + bool removeNextHopGroup(const NextHopGroupKey&); - bool validnexthopinNextHopGroup(const IpAddress &); - bool invalidnexthopinNextHopGroup(const IpAddress &); + bool validnexthopinNextHopGroup(const NextHopKey&); + bool invalidnexthopinNextHopGroup(const NextHopKey&); - void notifyNextHopChangeObservers(IpPrefix, IpAddresses, bool); + void notifyNextHopChangeObservers(const IpPrefix&, const NextHopGroupKey&, bool); private: NeighOrch *m_neighOrch; @@ -83,9 +83,9 @@ class RouteOrch : public Orch, public Subject NextHopObserverTable m_nextHopObservers; - void addTempRoute(IpPrefix, IpAddresses); - bool addRoute(IpPrefix, IpAddresses); - bool removeRoute(IpPrefix); + void addTempRoute(const IpPrefix&, const NextHopGroupKey&); + bool addRoute(const IpPrefix&, const NextHopGroupKey&); + bool removeRoute(const IpPrefix&); std::string getLinkLocalEui64Addr(void); void addLinkLocalRouteToMe(sai_object_id_t vrf_id, IpPrefix linklocal_prefix); diff --git a/orchagent/vnetorch.cpp b/orchagent/vnetorch.cpp index b1122f366e..9346ba1a58 100644 --- a/orchagent/vnetorch.cpp +++ b/orchagent/vnetorch.cpp @@ -1165,7 +1165,7 @@ bool VNetBitmapObject::addRoute(IpPrefix& ipPrefix, nextHop& nh) Port port; RouteInfo routeInfo; - bool is_subnet = (!nh.ips.getSize()) ? true : false; + bool is_subnet = (!nh.ips.getSize() || nh.ips.contains("0.0.0.0")) ? true : false; if (is_subnet && (!gPortsOrch->getPort(nh.ifname, port) || (port.m_rif_id == SAI_NULL_OBJECT_ID))) { @@ -1199,15 +1199,15 @@ bool VNetBitmapObject::addRoute(IpPrefix& ipPrefix, nextHop& nh) } else if (nh.ips.getSize() == 1) { - IpAddress ip_address(nh.ips.to_string()); - if (gNeighOrch->hasNextHop(ip_address)) + NextHopKey nexthop(nh.ips.to_string(), nh.ifname); + if (gNeighOrch->hasNextHop(nexthop)) { - nh_id = gNeighOrch->getNextHopId(ip_address); + nh_id = gNeighOrch->getNextHopId(nexthop); } else { SWSS_LOG_INFO("Failed to get next hop %s for %s", - ip_address.to_string().c_str(), ipPrefix.to_string().c_str()); + nexthop.to_string().c_str(), ipPrefix.to_string().c_str()); return false; } @@ -1721,7 +1721,7 @@ bool VNetRouteOrch::doRouteTask(const string& vnet, IpPrefix& ipP return true; } - bool is_subnet = (!nh.ips.getSize())?true:false; + bool is_subnet = (!nh.ips.getSize() || nh.ips.contains("0.0.0.0")) ? true : false; Port port; if (is_subnet && (!gPortsOrch->getPort(nh.ifname, port) || (port.m_rif_id == SAI_NULL_OBJECT_ID))) @@ -1778,15 +1778,15 @@ bool VNetRouteOrch::doRouteTask(const string& vnet, IpPrefix& ipP } else if (nh.ips.getSize() == 1) { - IpAddress ip_address(nh.ips.to_string()); - if (gNeighOrch->hasNextHop(ip_address)) + NextHopKey nexthop(nh.ips.to_string(), nh.ifname); + if (gNeighOrch->hasNextHop(nexthop)) { - nh_id = gNeighOrch->getNextHopId(ip_address); + nh_id = gNeighOrch->getNextHopId(nexthop); } else { SWSS_LOG_INFO("Failed to get next hop %s for %s", - ip_address.to_string().c_str(), ipPrefix.to_string().c_str()); + nexthop.to_string().c_str(), ipPrefix.to_string().c_str()); return false; } }