From 753def9f7e6003e083ff13dc02a902515969748b Mon Sep 17 00:00:00 2001 From: F5 Date: Wed, 30 Nov 2022 13:47:49 +0000 Subject: [PATCH] internet: Add per-flow ECMP routing --- src/internet/model/ipv4-global-routing.cc | 31 ++++++++++++++++++++--- src/internet/model/ipv4-global-routing.h | 5 +++- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/internet/model/ipv4-global-routing.cc b/src/internet/model/ipv4-global-routing.cc index 67db6e177..e3f180990 100644 --- a/src/internet/model/ipv4-global-routing.cc +++ b/src/internet/model/ipv4-global-routing.cc @@ -28,6 +28,7 @@ #include "ns3/ipv4-routing-table-entry.h" #include "ns3/boolean.h" #include "ns3/node.h" +#include "ipv4-queue-disc-item.h" #include "ipv4-global-routing.h" #include "global-route-manager.h" @@ -48,6 +49,11 @@ Ipv4GlobalRouting::GetTypeId (void) BooleanValue (false), MakeBooleanAccessor (&Ipv4GlobalRouting::m_randomEcmpRouting), MakeBooleanChecker ()) + .AddAttribute ("FlowEcmpRouting", + "Set to true if flows are randomly routed among ECMP; set to false for using only one route consistently", + BooleanValue (false), + MakeBooleanAccessor (&Ipv4GlobalRouting::m_flowEcmpRouting), + MakeBooleanChecker ()) .AddAttribute ("RespondToInterfaceEvents", "Set to true if you want to dynamically recompute the global routes upon Interface notification events (up/down, or add/remove address)", BooleanValue (false), @@ -137,7 +143,7 @@ Ipv4GlobalRouting::AddASExternalRouteTo (Ipv4Address network, Ptr -Ipv4GlobalRouting::LookupGlobal (Ipv4Address dest, Ptr oif) +Ipv4GlobalRouting::LookupGlobal (Ipv4Address dest, uint32_t flowHash, Ptr oif) { NS_LOG_FUNCTION (this << dest << oif); NS_LOG_LOGIC ("Looking for route for destination " << dest); @@ -220,7 +226,11 @@ Ipv4GlobalRouting::LookupGlobal (Ipv4Address dest, Ptr oif) // ECMP routing is enabled, or always select the first route // consistently if random ECMP routing is disabled uint32_t selectIndex; - if (m_randomEcmpRouting) + if (m_flowEcmpRouting) + { + selectIndex = flowHash % allRoutes.size (); + } + else if (m_randomEcmpRouting) { selectIndex = m_rand->GetInteger (0, allRoutes.size ()-1); } @@ -462,6 +472,12 @@ Ptr Ipv4GlobalRouting::RouteOutput (Ptr p, const Ipv4Header &header, Ptr oif, Socket::SocketErrno &sockerr) { NS_LOG_FUNCTION (this << p << &header << oif << &sockerr); + + uint32_t flowHash = 0; + if (m_flowEcmpRouting) + { + flowHash = Ipv4QueueDiscItem (p, Address (), header.GetProtocol (), header).Hash (0); + } // // First, see if this is a multicast packet we have a route for. If we // have a route, then send the packet down each of the specified interfaces. @@ -475,7 +491,7 @@ Ipv4GlobalRouting::RouteOutput (Ptr p, const Ipv4Header &header, Ptr rtentry = LookupGlobal (header.GetDestination (), oif); + Ptr rtentry = LookupGlobal (header.GetDestination (), flowHash, oif); if (rtentry) { sockerr = Socket::ERROR_NOTERROR; @@ -492,6 +508,13 @@ Ipv4GlobalRouting::RouteInput (Ptr p, const Ipv4Header &header, P LocalDeliverCallback lcb, ErrorCallback ecb) { NS_LOG_FUNCTION (this << p << header << header.GetSource () << header.GetDestination () << idev << &lcb << &ecb); + + uint32_t flowHash = 0; + if (m_flowEcmpRouting) + { + flowHash = Ipv4QueueDiscItem (p->Copy (), Address (), header.GetProtocol (), header).Hash (0); + } + // Check if input device supports IP NS_ASSERT (m_ipv4->GetInterfaceForDevice (idev) >= 0); uint32_t iif = m_ipv4->GetInterfaceForDevice (idev); @@ -524,7 +547,7 @@ Ipv4GlobalRouting::RouteInput (Ptr p, const Ipv4Header &header, P } // Next, try to find a route NS_LOG_LOGIC ("Unicast destination- looking up global route"); - Ptr rtentry = LookupGlobal (header.GetDestination ()); + Ptr rtentry = LookupGlobal (header.GetDestination (), flowHash); if (rtentry != 0) { NS_LOG_LOGIC ("Found unicast destination- calling unicast callback"); diff --git a/src/internet/model/ipv4-global-routing.h b/src/internet/model/ipv4-global-routing.h index d58c1b6ef..a8b843a9e 100644 --- a/src/internet/model/ipv4-global-routing.h +++ b/src/internet/model/ipv4-global-routing.h @@ -234,6 +234,8 @@ protected: private: /// Set to true if packets are randomly routed among ECMP; set to false for using only one route consistently bool m_randomEcmpRouting; + /// Set to true if flows are randomly routed among ECMP; set to false for using only one route consistently + bool m_flowEcmpRouting; /// Set to true if this interface should respond to interface events by globallly recomputing routes bool m_respondToInterfaceEvents; /// A uniform random number generator for randomly routing packets among ECMP @@ -263,10 +265,11 @@ private: /** * \brief Lookup in the forwarding table for destination. * \param dest destination address + * \param flowHash flow hash for per-flow ECMP routing * \param oif output interface if any (put 0 otherwise) * \return Ipv4Route to route the packet to reach dest address */ - Ptr LookupGlobal (Ipv4Address dest, Ptr oif = 0); + Ptr LookupGlobal (Ipv4Address dest, uint32_t flowHash = 0, Ptr oif = 0); HostRoutes m_hostRoutes; //!< Routes to hosts NetworkRoutes m_networkRoutes; //!< Routes to networks