diff --git a/examples/simple-static-routing.cc b/examples/simple-static-routing.cc index bb9dcf21e..7a366f736 100644 --- a/examples/simple-static-routing.cc +++ b/examples/simple-static-routing.cc @@ -81,8 +81,8 @@ int main (int argc, char *argv[]) DebugComponentEnable("Channel"); DebugComponentEnable("PointToPointChannel"); DebugComponentEnable("PointToPointNetDevice"); -#endif DebugComponentEnable("StaticRouter"); +#endif // Set up some default values for the simulation. Use the Bind() // technique to tell the system what subclass of Queue to use, diff --git a/src/routing/routing-environment.cc b/src/routing/routing-environment.cc index 160bd8668..73e936ca8 100644 --- a/src/routing/routing-environment.cc +++ b/src/routing/routing-environment.cc @@ -29,11 +29,18 @@ namespace RoutingEnvironment { BooleanDefaultValue g_doStaticRoutingDefaultValue ("DoStaticRouting", "Enable global static routing", false); - bool + bool StaticRoutingEnabled(void) { return g_doStaticRoutingDefaultValue.GetValue(); } + uint32_t +AllocateRouterId(void) +{ + static uint32_t routerId = 0; + return ++routerId; +} + } // namespace RoutingEnvironment } // namespace ns3 diff --git a/src/routing/routing-environment.h b/src/routing/routing-environment.h index abf9da4d8..51ee61f2b 100644 --- a/src/routing/routing-environment.h +++ b/src/routing/routing-environment.h @@ -25,6 +25,7 @@ namespace ns3 { namespace RoutingEnvironment { bool StaticRoutingEnabled(void); +uint32_t AllocateRouterId(void); } // namespace RoutingEnvironment } // namespace ns3 diff --git a/src/routing/static-route-manager.cc b/src/routing/static-route-manager.cc index 3c3cf14d6..393128967 100644 --- a/src/routing/static-route-manager.cc +++ b/src/routing/static-route-manager.cc @@ -85,7 +85,18 @@ StaticRouteManager::BuildStaticRoutingDatabase () NS_ASSERT_MSG(rtr, "QI for interface failed"); uint32_t numLSAs = rtr->GetNumLSAs(); - NS_DEBUG_UNCOND (numLSAs << "LSAs"); + NS_DEBUG_UNCOND ("Found " << numLSAs << " LSAs"); + + for (uint32_t j = 0; j < numLSAs; ++j) + { + StaticRouterLSA lsa; + rtr->GetLSA(j, lsa); + NS_DEBUG_UNCOND ("LSA " << j); + NS_DEBUG_UNCOND ("----------------------------------------"); + NS_DEBUG_UNCOND("m_linkStateId = " << lsa.m_linkStateId); + NS_DEBUG_UNCOND("m_advertisingRtr = " << lsa.m_advertisingRtr); + NS_DEBUG_UNCOND ("----------------------------------------"); + } } } diff --git a/src/routing/static-router.cc b/src/routing/static-router.cc index b76565b9f..fa72622e4 100644 --- a/src/routing/static-router.cc +++ b/src/routing/static-router.cc @@ -35,15 +35,57 @@ StaticRouterLSA::StaticRouterLSA() NS_DEBUG("StaticRouterLSA::StaticRouterLSA ()"); } +// +// Copy constructor for StaticRouterLSA +// +StaticRouterLSA::StaticRouterLSA (StaticRouterLSA& lsa) + : m_linkStateId(lsa.m_linkStateId), m_advertisingRtr(lsa.m_advertisingRtr) +{ + NS_DEBUG("StaticRouterLSA Copy Constructor"); + NS_ASSERT_MSG(IsEmpty(), "The LSA must be empty before copy"); + + for ( ListOfLinkRecords_t::iterator i = lsa.m_linkRecords.begin (); + i != lsa.m_linkRecords.end (); + i++) + { + StaticRouterLinkRecord *pSrc = *i; + StaticRouterLinkRecord *pDst = new StaticRouterLinkRecord; + pDst->m_linkId = pSrc->m_linkId; + pDst->m_linkData = pSrc->m_linkData; + m_linkRecords.push_back(pDst); + pDst = 0; + } +} + +// +// Assignment operator for StaticRouterLSA +// +// This uses the non-obvious trick of taking the source LSA passed by +// value instead of by reference. This causes the copy constructor to be +// invoked (where the real work is done -- see above). All we have to do +// here is to return the newly constructed LSA. +// + StaticRouterLSA& +StaticRouterLSA::operator= (StaticRouterLSA lsa) +{ + NS_DEBUG("StaticRouterLSA Operator ="); + return *this; +} + StaticRouterLSA::~StaticRouterLSA() { NS_DEBUG("StaticRouterLSA::~StaticRouterLSA ()"); + ClearLinkRecords (); +} + void +StaticRouterLSA::ClearLinkRecords(void) +{ for ( ListOfLinkRecords_t::iterator i = m_linkRecords.begin (); i != m_linkRecords.end (); i++) { - NS_DEBUG("StaticRouterLSA::~StaticRouterLSA (): free link record"); + NS_DEBUG("StaticRouterLSA::ClearLinkRecords (): free link record"); StaticRouterLinkRecord *p = *i; delete p; @@ -51,7 +93,7 @@ StaticRouterLSA::~StaticRouterLSA() *i = 0; } - NS_DEBUG("StaticRouterLSA::~StaticRouterLSA (): clear list"); + NS_DEBUG("StaticRouterLSA::ClearLinkRecords(): clear list"); m_linkRecords.clear(); } @@ -62,19 +104,77 @@ StaticRouterLSA::AddLinkRecord (StaticRouterLinkRecord* lr) return m_linkRecords.size (); } + bool +StaticRouterLSA::IsEmpty (void) +{ + return m_linkRecords.size () == 0; +} + + void +StaticRouterLSA::Print (std::ostream &os) +{ + os << "m_linkStateId = " << m_linkStateId << std::endl << + "m_advertisingRtr = " << m_advertisingRtr << std::endl; + + for ( ListOfLinkRecords_t::iterator i = m_linkRecords.begin (); + i != m_linkRecords.end (); + i++) + { + StaticRouterLinkRecord *p = *i; + os << "----------" << std::endl; + os << "m_linkId = " << p->m_linkId << std::endl; + os << "m_linkData = " << p->m_linkData << std::endl; + } +} + +std::ostream& operator<< (std::ostream& os, StaticRouterLSA& lsa) +{ + lsa.Print (os); + return os; +} + const InterfaceId StaticRouter::iid = MakeInterfaceId ("StaticRouter", Object::iid); StaticRouter::StaticRouter (Ptr node) - : m_node(node), m_numLSAs(0) + : m_node(node), m_LSAs() { NS_DEBUG("StaticRouter::StaticRouter ()"); SetInterfaceId (StaticRouter::iid); + m_routerId.Set(RoutingEnvironment::AllocateRouterId()); } StaticRouter::~StaticRouter () { NS_DEBUG("StaticRouter::~StaticRouter ()"); + ClearLSAs(); +} + + void +StaticRouter::ClearLSAs () +{ + NS_DEBUG("StaticRouter::ClearLSAs ()"); + + for ( ListOfLSAs_t::iterator i = m_LSAs.begin (); + i != m_LSAs.end (); + i++) + { + NS_DEBUG("StaticRouter::ClearLSAs (): free LSA"); + + StaticRouterLSA *p = *i; + delete p; + p = 0; + + *i = 0; + } + NS_DEBUG("StaticRouter::ClearLSAs (): clear list"); + m_LSAs.clear(); +} + + Ipv4Address + StaticRouter::GetRouterId (void) +{ + return m_routerId; } // @@ -85,6 +185,7 @@ StaticRouter::GetNumLSAs (void) { NS_DEBUG("StaticRouter::GetNumLSAs ()"); NS_ASSERT_MSG(m_node, " interface not set"); + ClearLSAs (); // // We're aggregated to a node. We need to ask the node for a pointer to its // Ipv4 interface. This is where the information regarding the attached @@ -93,29 +194,24 @@ StaticRouter::GetNumLSAs (void) Ptr ipv4Local = m_node->QueryInterface (Ipv4::iid); NS_ASSERT_MSG(ipv4Local, "QI for interface failed"); // -// Now, we need to ask Ipv4 for the number of interfaces attached to this -// node. This isn't necessarily equal to the number of links to adjacent -// nodes (other routers); the number of interfaces may include interfaces -// connected to stub networks (e.g., ethernets, etc.). So we have to walk -// through the list of net devices and see if they are directly connected -// to another router. +// We need to ask the node for the number of net devices attached. This isn't +// necessarily equal to the number of links to adjacent nodes (other routers) +// as the number of devices may include those for stub networks (e.g., +// ethernets, etc.). So we have to walk through the list of net devices and +// pay attention to those that are directly connected to another router through +// a point-to-point channel. // -// We'll start out at the maximum possible number of LSAs and reduce that -// number if we discover a link that's not actually connected to another -// router. -// - m_numLSAs = 0; uint32_t numDevices = m_node->GetNDevices(); NS_DEBUG("StaticRouter::GetNumLSAs (): numDevices = " << numDevices); // // Loop through the devices looking for those connected to a point-to-point -// channel. These are the ones that are used to route packets. +// channel. // for (uint32_t i = 0; i < numDevices; ++i) { - Ptr nd = m_node->GetDevice(i); + Ptr ndLocal = m_node->GetDevice(i); - if (!nd->IsPointToPoint ()) + if (!ndLocal->IsPointToPoint ()) { NS_DEBUG("StaticRouter::GetNumLSAs (): non-point-to-point device"); continue; @@ -124,11 +220,11 @@ StaticRouter::GetNumLSAs (void) NS_DEBUG("StaticRouter::GetNumLSAs (): Point-to-point device"); // // Now, we have to find the Ipv4 interface whose netdevice is the one we -// just found. This is the IP on the local side of the channel. There is -// a function to do this used down in the guts of the stack, but its not +// just found. This is still the IP on the local side of the channel. There +// is a function to do this used down in the guts of the stack, but it's not // exported so we had to whip up an equivalent. // - uint32_t ifIndexLocal = FindIfIndexForDevice(m_node, nd); + uint32_t ifIndexLocal = FindIfIndexForDevice(m_node, ndLocal); // // Now that we have the Ipv4 interface index, we can get the address and mask // we need. @@ -137,12 +233,12 @@ StaticRouter::GetNumLSAs (void) Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(ifIndexLocal); NS_DEBUG("Working with local address " << addrLocal); // -// Now, we're going to link to the remote net device on the other end of the -// point-to-point channel we know we have. This is where our adjacent router -// (to use OSPF lingo) is running. +// Now, we're going to walk over to the remote net device on the other end of +// the point-to-point channel we now know we have. This is where our adjacent +// router (to use OSPF lingo) is running. // - Ptr ch = nd->GetChannel(); - Ptr ndRemote = GetAdjacent(nd, ch); + Ptr ch = ndLocal->GetChannel(); + Ptr ndRemote = GetAdjacent(ndLocal, ch); // // The adjacent net device is aggregated to a node. We need to ask that net // device for its node, then ask that node for its Ipv4 interface. @@ -151,6 +247,15 @@ StaticRouter::GetNumLSAs (void) Ptr ipv4Remote = nodeRemote->QueryInterface (Ipv4::iid); NS_ASSERT_MSG(ipv4Remote, "QI for remote interface failed"); // +// Per the OSPF spec, we're going to need the remote router ID, so we might as +// well get it now. +// + Ptr srRemote = + nodeRemote->QueryInterface (StaticRouter::iid); + NS_ASSERT_MSG(srRemote, "QI for remote failed"); + Ipv4Address rtrIdRemote = srRemote->GetRouterId(); + NS_DEBUG("Working with remote router " << rtrIdRemote); +// // Now, just like we did above, we need to get the IP interface index for the // net device on the other end of the point-to-point channel. // @@ -162,15 +267,51 @@ StaticRouter::GetNumLSAs (void) Ipv4Address addrRemote = ipv4Remote->GetAddress(ifIndexRemote); Ipv4Mask maskRemote = ipv4Remote->GetNetworkMask(ifIndexRemote); NS_DEBUG("Working with remote address " << addrRemote); - ++m_numLSAs; +// +// Now we can fill out the link state advertisement for this link. +// + StaticRouterLSA *pLSA = new StaticRouterLSA; + pLSA->m_linkStateId = m_routerId; + pLSA->m_advertisingRtr = m_routerId; + + StaticRouterLinkRecord *plr = new StaticRouterLinkRecord; + plr->m_linkType = StaticRouterLinkRecord::PointToPoint; + plr->m_linkId = rtrIdRemote; + plr->m_linkData = addrLocal; + pLSA->AddLinkRecord(plr); + plr = 0; + + plr = new StaticRouterLinkRecord; + plr->m_linkType = StaticRouterLinkRecord::StubNetwork; + plr->m_linkId = addrRemote; + plr->m_linkData.Set(maskRemote.GetHostOrder()); // Frown + pLSA->AddLinkRecord(plr); + plr = 0; + + m_LSAs.push_back (pLSA); + NS_DEBUG(*pLSA); } - return m_numLSAs; + return m_LSAs.size (); } bool StaticRouter::GetLSA (uint32_t n, StaticRouterLSA &lsa) { + NS_ASSERT_MSG(lsa.IsEmpty(), "Must pass empty LSA"); + + ListOfLSAs_t::iterator i = m_LSAs.begin (); + uint32_t j = 0; + + for (; i != m_LSAs.end (); i++, j++) + { + if (j == n) + { + StaticRouterLSA *p = *i; + lsa = *p; + return true; + } + } return false; } diff --git a/src/routing/static-router.h b/src/routing/static-router.h index a3d56001e..5ed6b3e79 100644 --- a/src/routing/static-router.h +++ b/src/routing/static-router.h @@ -23,6 +23,7 @@ #include "ns3/node.h" #include "ns3/channel.h" #include "ns3/ipv4-address.h" +#include "ns3/routing-environment.h" namespace ns3 { @@ -70,17 +71,26 @@ class StaticRouterLSA { public: StaticRouterLSA(); + StaticRouterLSA (StaticRouterLSA& lsa); ~StaticRouterLSA(); - uint32_t AddLinkRecord (StaticRouterLinkRecord* lr); + StaticRouterLSA& operator= (StaticRouterLSA lsa); - Ipv4Address m_linkStateId; // set to the NodeId - Ipv4Address m_advertisingRtr; // set to the NodeId + uint32_t AddLinkRecord (StaticRouterLinkRecord* lr); + void ClearLinkRecords(void); + bool IsEmpty(void); + + void Print (std::ostream &os); + + Ipv4Address m_linkStateId; + Ipv4Address m_advertisingRtr; typedef std::list ListOfLinkRecords_t; ListOfLinkRecords_t m_linkRecords; }; +std::ostream& operator<< (std::ostream& os, StaticRouterLSA& lsa); + /** * \brief An interface aggregated to a node to provide static routing info * @@ -96,18 +106,24 @@ public: static const InterfaceId iid; StaticRouter (Ptr node); + Ipv4Address GetRouterId(void); uint32_t GetNumLSAs (void); bool GetLSA (uint32_t n, StaticRouterLSA &lsa); protected: virtual ~StaticRouter (); - - Ptr m_node; - uint32_t m_numLSAs; + void ClearLSAs (void); Ptr GetAdjacent(Ptr nd, Ptr ch); uint32_t FindIfIndexForDevice(Ptr node, Ptr nd); + Ptr m_node; + + typedef std::list ListOfLSAs_t; + ListOfLSAs_t m_LSAs; + + Ipv4Address m_routerId; + private: };