diff --git a/examples/csma-bridge-one-hop.cc b/examples/csma-bridge-one-hop.cc index fac58fa4f..812b1dd7c 100644 --- a/examples/csma-bridge-one-hop.cc +++ b/examples/csma-bridge-one-hop.cc @@ -176,7 +176,8 @@ main (int argc, char *argv[]) // // Create router nodes, initialize routing database and set up the routing - // tables in the nodes. + // tables in the nodes. We excuse the bridge nodes from having to serve as + // routers, since they don't even have internet stacks on them. // NodeContainer routerNodes (n0, n1, n2, n3, n4); GlobalRouteManager::PopulateRoutingTables (routerNodes); diff --git a/src/routing/global-routing/global-router-interface.cc b/src/routing/global-routing/global-router-interface.cc index 27a463bed..9c8db191e 100644 --- a/src/routing/global-routing/global-router-interface.cc +++ b/src/routing/global-routing/global-router-interface.cc @@ -530,6 +530,7 @@ GlobalRouter::DiscoverLSAs (void) // bridge devices also take up an "extra" net device. // uint32_t numDevices = node->GetNDevices(); + NS_LOG_LOGIC ("*************************"); NS_LOG_LOGIC ("numDevices = " << numDevices); // @@ -538,18 +539,16 @@ GlobalRouter::DiscoverLSAs (void) // the "everything else" class of devices. // // To do this, we wander through all of the devices on the node looking for -// bridge net devices. We then add any net devices associated to a bridge -// to a list of bridged devices. These devices will not be treated as stand- -// alone devices later. +// bridge net devices. We then add any net devices associated with each bridge +// to a list of bridged devices. These devices will be treated as a special +// case later. // std::vector > bridgedDevices; - NS_LOG_LOGIC ("*************************"); - - NS_LOG_LOGIC ("numDevices = " << numDevices); for (uint32_t i = 0; i < numDevices; ++i) { Ptr nd = node->GetDevice(i); + if (nd->IsBridge ()) { NS_LOG_LOGIC ("**** Net device " << nd << "is a bridge"); @@ -597,7 +596,7 @@ GlobalRouter::DiscoverLSAs (void) // // Check to see if the net device we just got has a corresponding IP - // interface (could be a pure L2 NetDevice). + // interface (could be a pure L2 NetDevice that is not a bridge). // bool isIp = false; for (uint32_t i = 0; i < ipv4Local->GetNInterfaces (); ++i ) @@ -615,6 +614,11 @@ GlobalRouter::DiscoverLSAs (void) continue; } +// +// We have a net device that we need to check out. If it suports broadcast and +// is not a point-point link, then it will be either a stub network or a transit +// network depending on the number of routers. +// if (ndLocal->IsBroadcast () && !ndLocal->IsPointToPoint () ) { NS_LOG_LOGIC ("**** Broadcast link"); @@ -636,21 +640,26 @@ GlobalRouter::DiscoverLSAs (void) NS_LOG_LOGIC ("Working with local address " << addrLocal); uint16_t metricLocal = ipv4Local->GetMetric (ifIndexLocal); // -// 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. +// Check to see if the net device is connected to a channel/network that has +// another router on it. If there is no other router on the link (but us) then +// this is a stub network. If we find another router, then what we have here +// is a transit network. // - Ptr ch = ndLocal->GetChannel(); - uint32_t nDevices = ch->GetNDevices(); - if (nDevices == 1) + if (AnotherRouterOnLink (ndLocal) == false) { - // This is a stub broadcast interface - NS_LOG_LOGIC("**** Router-LSA stub broadcast link"); - // XXX in future, need to consider if >1 includes other routers + // + // This is a net device connected to a stub network + // + NS_LOG_LOGIC("**** Router-LSA Stub Network"); plr->SetLinkType (GlobalRoutingLinkRecord::StubNetwork); - // Link ID is IP network number of attached network + // + // According to OSPF, the Link ID is the IP network number of + // the attached network. + // plr->SetLinkId (addrLocal.CombineMask(maskLocal)); - // Link Data is network mask; convert to Ipv4Address + // + // and the Link Data is the network mask; converted to Ipv4Address + // Ipv4Address maskLocalAddr; maskLocalAddr.Set(maskLocal.Get ()); plr->SetLinkData (maskLocalAddr); @@ -661,20 +670,28 @@ GlobalRouter::DiscoverLSAs (void) } else { - NS_LOG_LOGIC ("**** Router-LSA Broadcast link"); - // multiple routers on a broadcast interface - // lowest IP address is designated router + // + // We have multiple routers on a broadcast interface, so this is + // a transit network. + // + NS_LOG_LOGIC ("**** Router-LSA Transit Network"); plr->SetLinkType (GlobalRoutingLinkRecord::TransitNetwork); - // Link ID is IP interface address of designated router - Ipv4Address desigRtr = - FindDesignatedRouterForLink (node, ndLocal); + // + // By definition, the router with the lowest IP address is the + // designated router for the network. OSPF says that the Link ID + // gets the IP interface address of the designated router in this + // case. + // + Ipv4Address desigRtr = FindDesignatedRouterForLink (ndLocal); if (desigRtr == addrLocal) { listOfDRInterfaces.push_back (ndLocal); NS_LOG_LOGIC (node->GetId () << " is a DR"); } plr->SetLinkId (desigRtr); - // Link Data is router's own IP address + // + // OSPF says that the Link Data is this router's own IP address. + // plr->SetLinkData (addrLocal); plr->SetMetric (metricLocal); pLSA->AddLinkRecord (plr); @@ -787,6 +804,7 @@ GlobalRouter::DiscoverLSAs (void) // kinds of advertisements (than Router LSAs). // m_LSAs.push_back (pLSA); + NS_LOG_LOGIC ("========== Link State Advertisement for node " << node->GetId () << " =========="); NS_LOG_LOGIC (*pLSA); // @@ -795,20 +813,16 @@ GlobalRouter::DiscoverLSAs (void) // if (listOfDRInterfaces.size () > 0) { + NS_LOG_LOGIC ("Build Network LSA"); for (std::list >::iterator i = listOfDRInterfaces.begin (); i != listOfDRInterfaces.end (); i++) { // -// Build one NetworkLSA for each interface that is a DR +// Build one NetworkLSA for each net device talking to a netwok that we are the +// designated router for. // Ptr ndLocal = *i; - // - // We are working with a list of net devices off of the local node - // on which we found a designated router. We assume there must be - // an associated ipv4 interface index. - // - uint32_t ifIndexLocal; bool rc = FindIfIndexForDevice(node, ndLocal, ifIndexLocal); NS_ABORT_MSG_IF (rc == false, "GlobalRouter::DiscoverLSAs (): No interface index associated with device"); @@ -823,11 +837,9 @@ GlobalRouter::DiscoverLSAs (void) pLSA->SetNetworkLSANetworkMask (maskLocal); pLSA->SetStatus (GlobalRoutingLSA::LSA_SPF_NOT_EXPLORED); // -// XXX Doesn't deal with bridging -// // Build a list of AttachedRouters by walking the devices in the channel -// and, if we find an IPv4 interface associated with that device, we -// call it an attached router. +// and, if we find a node with a GlobalRouter interface and an IPv4 +// interface associated with that device, we call it an attached router. // Ptr ch = ndLocal->GetChannel(); uint32_t nDevices = ch->GetNDevices(); @@ -837,15 +849,27 @@ GlobalRouter::DiscoverLSAs (void) Ptr tempNd = ch->GetDevice (i); NS_ASSERT (tempNd); Ptr tempNode = tempNd->GetNode (); +// +// Does the node in question have a GlobalRouter interface? If not it can +// hardly be considered an attached router. +// + Ptr rtr = tempNode->GetObject (); + if (rtr == 0) + { + continue; + } + +// +// Does the attached node have an ipv4 interface for the device we're probing? +// If not, it can't play router. +// uint32_t tempIfIndex; if (FindIfIndexForDevice (tempNode, tempNd, tempIfIndex)) { - Ptr tempIpv4 = tempNode->GetObject (); NS_ASSERT (tempIpv4); Ipv4Address tempAddr = tempIpv4->GetAddress(tempIfIndex); pLSA->AddAttachedRouter (tempAddr); - } } m_LSAs.push_back (pLSA); @@ -857,82 +881,108 @@ GlobalRouter::DiscoverLSAs (void) } // -// Given a node and an attached net device, we need to walk the channel to which -// the net device is attached and look for the lowest IP address on all of the -// devices attached to that channel. This process is complicated by the fact -// there may be bridge devices associated with any of the net devices attached -// to the channel. +// Given a local net device, we need to walk the channel to which the net device is +// attached and look for nodes with GlobalRouter interfaces on them (one of them +// will be us). Of these, the router with the lowest IP address on the net device +// connecting to the channel becomes the designated router for the link. // Ipv4Address - GlobalRouter::FindDesignatedRouterForLink (Ptr node, Ptr ndLocal) const +GlobalRouter::FindDesignatedRouterForLink (Ptr ndLocal) const { NS_LOG_FUNCTION_NOARGS (); - NS_LOG_LOGIC("**** For node " << node->GetId () << " for net device " << ndLocal ); - - uint32_t ifIndexLocal; - bool rc = FindIfIndexForDevice(node, ndLocal, ifIndexLocal); - NS_ABORT_MSG_IF (rc == false, "GlobalRouter::DiscoverLSAs (): No interface index associated with device"); - - Ptr ipv4Local = GetObject (); - NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::FindDesignatedRouterForLink(): GetObject for interface failed" - " on node " << node->GetId ()); - - Ipv4Address addrLocal = ipv4Local->GetAddress(ifIndexLocal); - Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(ifIndexLocal); Ptr ch = ndLocal->GetChannel(); uint32_t nDevices = ch->GetNDevices(); NS_ASSERT (nDevices); - NS_LOG_LOGIC("**** channel " << ch << " has " << nDevices << " net devices"); - - // - // We now have the channel associated with the net device in question. We - // need to iterate over all of the net devices attached to that channel. - // - - Ipv4Address lowest = addrLocal; + Ipv4Address addr ("255.255.255.255"); for (uint32_t i = 0; i < nDevices; i++) { - Ptr ndTemp = ch->GetDevice (i); - NS_ASSERT_MSG (ndTemp, "GlobalRouter::FindDesignatedRouterForLink(): Null device attached to channel"); + Ptr currentNd = ch->GetDevice (i); + NS_ASSERT (currentNd); - if (ndTemp == ndLocal) + Ptr currentNode = currentNd->GetNode (); + NS_ASSERT (currentNode); + // + // We require a designated router to have a GlobalRouter interface and + // an internet stack that includes the Ipv4 interface. + // + Ptr rtr = currentNode->GetObject (); + Ptr ipv4 = currentNode->GetObject (); + if (rtr == 0 || ipv4 == 0 ) { continue; } - Ptr nodeTemp = ndTemp->GetNode (); - - NS_LOG_LOGIC("**** channel connects to node " << nodeTemp->GetId () << " with net device " << ndTemp); - // - // XXX doesn't admit the possibility of a bridge + // This node could be a designated router, so we can check and see if + // it has a lower IP address than the one we have. In order to have + // an IP address, it needs to have an interface index. If it doesen't + // have an interface index directly, it's probably part of a bridge + // net device XXX which is not yet handled. // - // If the remote device doesn't have an ipv4 interface index associated - // with it, it cannot be a designated router. - // - uint32_t ifIndexTemp; - bool rc = FindIfIndexForDevice(nodeTemp, ndTemp, ifIndexTemp); + uint32_t currentIfIndex; + bool rc = FindIfIndexForDevice(currentNode, currentNd, currentIfIndex); if (rc == false) { continue; } - Ptr ipv4Temp = nodeTemp->GetObject (); - NS_ASSERT_MSG (ipv4Temp, "GlobalRouter::FindDesignatedRouterForLink(): GetObject for interface failed" - " on node " << node->GetId ()); + // + // Okay, get the IP address corresponding to the interface we're + // examining and if it's the lowest so far, remember it. + // + Ipv4Address currentAddr = ipv4->GetAddress(currentIfIndex); - Ipv4Address addrTemp = ipv4Temp->GetAddress(ifIndexTemp); - - NS_LOG_LOGIC("**** net device " << ndTemp << " has Ipv4Address " << addrTemp); - if (addrTemp < addrLocal) + if (currentAddr < addr) { - addrLocal = addrTemp; + addr = currentAddr; } } - return addrLocal; + + // + // Return the lowest IP address found, which will become the designated router + // for the link. + // + NS_ASSERT_MSG (addr.IsBroadcast() == false, "GlobalRouter::FindDesignatedRouterForLink(): Bogus address"); + return addr; +} + +// +// Given a node and an attached net device, take a look off in the channel to +// which the net device is attached and look for a node on the other side +// that has a GlobalRouter interface aggregated. +// + bool +GlobalRouter::AnotherRouterOnLink (Ptr nd) const +{ + NS_LOG_FUNCTION_NOARGS (); + + Ptr ch = nd->GetChannel(); + uint32_t nDevices = ch->GetNDevices(); + NS_ASSERT (nDevices); + + for (uint32_t i = 0; i < nDevices; i++) + { + Ptr ndTemp = ch->GetDevice (i); + NS_ASSERT (ndTemp); + + if (ndTemp == nd) + { + continue; + } + + Ptr nodeTemp = ndTemp->GetNode (); + NS_ASSERT (nodeTemp); + + Ptr rtr = nodeTemp->GetObject (); + if (rtr) + { + return true; + } + } + return false; } uint32_t diff --git a/src/routing/global-routing/global-router-interface.h b/src/routing/global-routing/global-router-interface.h index e2e42d400..c56f0c0c6 100644 --- a/src/routing/global-routing/global-router-interface.h +++ b/src/routing/global-routing/global-router-interface.h @@ -640,8 +640,8 @@ private: Ptr GetAdjacent(Ptr nd, Ptr ch) const; bool FindIfIndexForDevice(Ptr node, Ptr nd, uint32_t &index) const; - Ipv4Address FindDesignatedRouterForLink (Ptr node, - Ptr ndLocal) const; + Ipv4Address FindDesignatedRouterForLink (Ptr ndLocal) const; + bool AnotherRouterOnLink (Ptr nd) const; typedef std::list ListOfLSAs_t; ListOfLSAs_t m_LSAs;