5
5
#include < unordered_set>
6
6
#include < exception>
7
7
#include < inttypes.h>
8
+ #include < algorithm>
8
9
9
10
#include " sai.h"
10
11
#include " saiextensions.h"
@@ -1911,6 +1912,15 @@ bool VNetRouteOrch::handleRoutes(const Request& request)
1911
1912
1912
1913
SWSS_LOG_INFO (" VNET-RT '%s' op '%s' for ip %s" , vnet_name.c_str (),
1913
1914
op.c_str (), ip_pfx.to_string ().c_str ());
1915
+
1916
+ if (op == SET_COMMAND)
1917
+ {
1918
+ addRoute (vnet_name, ip_pfx, nh);
1919
+ }
1920
+ else
1921
+ {
1922
+ delRoute (ip_pfx);
1923
+ }
1914
1924
1915
1925
if (vnet_orch_->isVnetExecVrf ())
1916
1926
{
@@ -1924,6 +1934,191 @@ bool VNetRouteOrch::handleRoutes(const Request& request)
1924
1934
return true ;
1925
1935
}
1926
1936
1937
+ void VNetRouteOrch::attach (Observer* observer, const IpAddress& dstAddr)
1938
+ {
1939
+ SWSS_LOG_ENTER ();
1940
+
1941
+ auto insert_result = next_hop_observers_.emplace (dstAddr, VNetNextHopObserverEntry ());
1942
+ auto observerEntry = insert_result.first ;
1943
+ /* Create a new observer entry if no current observer is observing this
1944
+ * IP address */
1945
+ if (insert_result.second )
1946
+ {
1947
+ /* Find the prefixes that cover the destination IP */
1948
+ for (auto route : syncd_routes_)
1949
+ {
1950
+ if (route.first .isAddressInSubnet (dstAddr))
1951
+ {
1952
+ SWSS_LOG_INFO (" Prefix %s covers destination address" ,
1953
+ route.first .to_string ().c_str ());
1954
+
1955
+ observerEntry->second .routeTable .emplace (
1956
+ route.first ,
1957
+ route.second
1958
+ );
1959
+ }
1960
+ }
1961
+ }
1962
+
1963
+ observerEntry->second .observers .push_back (observer);
1964
+
1965
+ auto bestRoute = observerEntry->second .routeTable .rbegin ();
1966
+ if (bestRoute != observerEntry->second .routeTable .rend ())
1967
+ {
1968
+ SWSS_LOG_NOTICE (" Attached next hop observer of route %s for destination IP %s" ,
1969
+ bestRoute->first .to_string ().c_str (),
1970
+ dstAddr.to_string ().c_str ());
1971
+ for (auto vnetEntry : bestRoute->second )
1972
+ {
1973
+ VNetNextHopUpdate update =
1974
+ {
1975
+ SET_COMMAND,
1976
+ vnetEntry.first , // vnet name
1977
+ dstAddr, // destination
1978
+ bestRoute->first , // prefix
1979
+ vnetEntry.second // nexthop
1980
+ };
1981
+ observer->update (SUBJECT_TYPE_NEXTHOP_CHANGE, reinterpret_cast <void *>(&update));
1982
+ }
1983
+ }
1984
+ }
1985
+
1986
+ void VNetRouteOrch::detach (Observer* observer, const IpAddress& dstAddr)
1987
+ {
1988
+ SWSS_LOG_ENTER ();
1989
+ auto observerEntry = next_hop_observers_.find (dstAddr);
1990
+
1991
+ if (observerEntry == next_hop_observers_.end ())
1992
+ {
1993
+ SWSS_LOG_ERROR (" Failed to detach observer for %s. Entry not found." , dstAddr.to_string ().c_str ());
1994
+ assert (false );
1995
+ return ;
1996
+ }
1997
+
1998
+ auto iter = std::find (
1999
+ observerEntry->second .observers .begin (),
2000
+ observerEntry->second .observers .end (),
2001
+ observer);
2002
+ if (iter == observerEntry->second .observers .end ())
2003
+ {
2004
+ SWSS_LOG_ERROR (" Failed to detach observer for %s. Observer not found." , dstAddr.to_string ().c_str ());
2005
+ assert (false );
2006
+ return ;
2007
+ }
2008
+
2009
+ auto bestRoute = observerEntry->second .routeTable .rbegin ();
2010
+ if (bestRoute != observerEntry->second .routeTable .rend ())
2011
+ {
2012
+ for (auto vnetEntry : bestRoute->second )
2013
+ {
2014
+ VNetNextHopUpdate update =
2015
+ {
2016
+ DEL_COMMAND,
2017
+ vnetEntry.first , // vnet name
2018
+ dstAddr, // destination
2019
+ bestRoute->first , // prefix
2020
+ vnetEntry.second // nexthop
2021
+ };
2022
+ observer->update (SUBJECT_TYPE_NEXTHOP_CHANGE, reinterpret_cast <void *>(&update));
2023
+ }
2024
+ }
2025
+ next_hop_observers_.erase (observerEntry);
2026
+ }
2027
+
2028
+ void VNetRouteOrch::addRoute (const std::string& vnet, const IpPrefix& ipPrefix, const nextHop& nh)
2029
+ {
2030
+ SWSS_LOG_ENTER ();
2031
+ for (auto & next_hop_observer : next_hop_observers_)
2032
+ {
2033
+ if (ipPrefix.isAddressInSubnet (next_hop_observer.first ))
2034
+ {
2035
+ auto route_insert_result = next_hop_observer.second .routeTable .emplace (ipPrefix, VNetEntry ());
2036
+
2037
+ auto vnet_result_result = route_insert_result.first ->second .emplace (vnet, nh);
2038
+ if (!vnet_result_result.second )
2039
+ {
2040
+ if (vnet_result_result.first ->second .ips == nh.ips
2041
+ && vnet_result_result.first ->second .ifname == nh.ifname )
2042
+ {
2043
+ continue ;
2044
+ }
2045
+ vnet_result_result.first ->second = nh;
2046
+ }
2047
+
2048
+ // If the inserted route is the best route. (Table should not be empty. Because we inserted a new entry above)
2049
+ if (route_insert_result.first == --next_hop_observer.second .routeTable .end ())
2050
+ {
2051
+ VNetNextHopUpdate update =
2052
+ {
2053
+ SET_COMMAND,
2054
+ vnet, // vnet name
2055
+ next_hop_observer.first , // destination
2056
+ ipPrefix, // prefix
2057
+ nh // nexthop
2058
+ };
2059
+ for (auto & observer : next_hop_observer.second .observers )
2060
+ {
2061
+ observer->update (SUBJECT_TYPE_NEXTHOP_CHANGE, reinterpret_cast <void *>(&update));
2062
+ }
2063
+ }
2064
+ }
2065
+ }
2066
+ syncd_routes_.emplace (ipPrefix, VNetEntry ()).first ->second [vnet] = nh;
2067
+ }
2068
+
2069
+ void VNetRouteOrch::delRoute (const IpPrefix& ipPrefix)
2070
+ {
2071
+ SWSS_LOG_ENTER ();
2072
+
2073
+ auto route_itr = syncd_routes_.find (ipPrefix);
2074
+ if (route_itr == syncd_routes_.end ())
2075
+ {
2076
+ SWSS_LOG_ERROR (" Failed to find route %s." , ipPrefix.to_string ().c_str ());
2077
+ assert (false );
2078
+ return ;
2079
+ }
2080
+ auto next_hop_observer = next_hop_observers_.begin ();
2081
+ while (next_hop_observer != next_hop_observers_.end ())
2082
+ {
2083
+ if (ipPrefix.isAddressInSubnet (next_hop_observer->first ))
2084
+ {
2085
+ auto itr = next_hop_observer->second .routeTable .find (ipPrefix);
2086
+ if ( itr == next_hop_observer->second .routeTable .end ())
2087
+ {
2088
+ SWSS_LOG_ERROR (
2089
+ " Failed to find any ip(%s) belong to this route(%s)." ,
2090
+ next_hop_observer->first .to_string ().c_str (),
2091
+ ipPrefix.to_string ().c_str ());
2092
+ assert (false );
2093
+ continue ;
2094
+ }
2095
+ if (itr->second .empty ())
2096
+ {
2097
+ continue ;
2098
+ }
2099
+ for (auto & observer : next_hop_observer->second .observers )
2100
+ {
2101
+ VNetNextHopUpdate update = {
2102
+ DEL_COMMAND,
2103
+ itr->second .rbegin ()->first , // vnet name
2104
+ next_hop_observer->first , // destination
2105
+ itr->first , // prefix
2106
+ itr->second .rbegin ()->second // nexthop
2107
+ };
2108
+ observer->update (SUBJECT_TYPE_NEXTHOP_CHANGE, reinterpret_cast <void *>(&update));
2109
+ }
2110
+ next_hop_observer->second .routeTable .erase (itr);
2111
+ if (next_hop_observer->second .routeTable .empty ())
2112
+ {
2113
+ next_hop_observer = next_hop_observers_.erase (next_hop_observer);
2114
+ continue ;
2115
+ }
2116
+ }
2117
+ next_hop_observer++;
2118
+ }
2119
+ syncd_routes_.erase (route_itr);
2120
+ }
2121
+
1927
2122
bool VNetRouteOrch::handleTunnel (const Request& request)
1928
2123
{
1929
2124
SWSS_LOG_ENTER ();
0 commit comments