From e567af9b24e78a2b58c7044399af2b2bd89d8eef Mon Sep 17 00:00:00 2001 From: Craig Dowell Date: Mon, 13 Aug 2007 12:08:01 -0700 Subject: [PATCH] more multicast plumbing --- examples/csma-multicast.cc | 84 ++++++++++++++---------- src/applications/onoff-application.cc | 7 +- src/devices/csma/csma-ipv4-topology.cc | 28 ++++---- src/devices/csma/csma-ipv4-topology.h | 23 ++++--- src/internet-node/arp-ipv4-interface.cc | 8 +++ src/internet-node/ipv4-l3-protocol.cc | 45 +++++++++---- src/internet-node/ipv4-l3-protocol.h | 9 ++- src/internet-node/ipv4-static-routing.cc | 51 +++++++++----- src/internet-node/ipv4-static-routing.h | 6 +- src/node/ipv4-address.cc | 7 +- src/node/ipv4.h | 6 +- 11 files changed, 177 insertions(+), 97 deletions(-) diff --git a/examples/csma-multicast.cc b/examples/csma-multicast.cc index 207d611b9..3af6fc937 100644 --- a/examples/csma-multicast.cc +++ b/examples/csma-multicast.cc @@ -65,7 +65,7 @@ main (int argc, char *argv[]) { // Users may find it convenient to turn on explicit debugging // for selected modules; the below lines suggest how to do this -#if 0 +#if 0 DebugComponentEnable("Me"); DebugComponentEnable("Object"); DebugComponentEnable("Queue"); @@ -87,16 +87,9 @@ main (int argc, char *argv[]) #endif DebugComponentEnable("Me"); - DebugComponentEnable("OnOffApplication"); - DebugComponentEnable("UdpSocket"); - DebugComponentEnable("UdpL4Protocol"); - DebugComponentEnable("Ipv4L3Protocol"); - DebugComponentEnable("Ipv4StaticRouting"); - DebugComponentEnable("CsmaNetDevice"); DebugComponentEnable("CsmaChannel"); - DebugComponentEnable("Ipv4Interface"); - DebugComponentEnable("ArpIpv4Interface"); - DebugComponentEnable("Ipv4LoopbackInterface"); + DebugComponentEnable("CsmaNetDevice"); + DebugComponentEnable("UdpL4Protocol"); // Set up some default values for the simulation. Use the Bind() // technique to tell the system what subclass of Queue to use, @@ -125,29 +118,47 @@ main (int argc, char *argv[]) DataRate(5000000), MilliSeconds(2)); NS_DEBUG("Build Topology."); - uint32_t n0ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n0, channel0, - Eui48Address("10:54:23:54:23:50")); - uint32_t n1ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n1, channel0, - Eui48Address("10:54:23:54:23:51")); - uint32_t n2ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n2, channel0, - Eui48Address("10:54:23:54:23:52")); - uint32_t n3ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n3, channel0, - Eui48Address("10:54:23:54:23:53")); + uint32_t netDeviceNumberNode0 = CsmaIpv4Topology::AddIpv4CsmaNode (n0, + channel0, Eui48Address("10:54:23:54:23:50")); + uint32_t netDeviceNumberNode1 = CsmaIpv4Topology::AddIpv4CsmaNode (n1, + channel0, Eui48Address("10:54:23:54:23:51")); + uint32_t netDeviceNumberNode2 = CsmaIpv4Topology::AddIpv4CsmaNode (n2, + channel0, Eui48Address("10:54:23:54:23:52")); + uint32_t netDeviceNumberNode3 = CsmaIpv4Topology::AddIpv4CsmaNode (n3, + channel0, Eui48Address("10:54:23:54:23:53")); + + NS_DEBUG ("netDeviceNumberNode0 = " << netDeviceNumberNode0); + NS_DEBUG ("netDeviceNumberNode1 = " << netDeviceNumberNode1); + NS_DEBUG ("netDeviceNumberNode2 = " << netDeviceNumberNode2); + NS_DEBUG ("netDeviceNumberNode3 = " << netDeviceNumberNode3); // Later, we add IP addresses. NS_DEBUG("Assign IP Addresses."); + // XXX BUGBUG + // Need a better way to get the interface index. The point-to-point topology + // as implemented can't return the index since it creates interfaces on both + // sides (i.e., AddIpv4Addresses, not AddIpv4Address). Need a method on + // Ipv4 to find the interface index corresponding to a given ipv4 address. + uint32_t ifIndexNode0 = CsmaIpv4Topology::AddIpv4Address (n0, + netDeviceNumberNode0, Ipv4Address ("10.1.1.1"), + Ipv4Mask ("255.255.255.0")); - CsmaIpv4Topology::AddIpv4Address ( - n0, n0ifIndex, Ipv4Address("10.1.1.1"), Ipv4Mask("255.255.255.0")); + uint32_t ifIndexNode1 = CsmaIpv4Topology::AddIpv4Address (n1, + netDeviceNumberNode1, Ipv4Address ("10.1.1.2"), + Ipv4Mask ("255.255.255.0")); - CsmaIpv4Topology::AddIpv4Address ( - n1, n1ifIndex, Ipv4Address("10.1.1.2"), Ipv4Mask("255.255.255.0")); - - CsmaIpv4Topology::AddIpv4Address ( - n2, n2ifIndex, Ipv4Address("10.1.1.3"), Ipv4Mask("255.255.255.0")); + uint32_t ifIndexNode2 = CsmaIpv4Topology::AddIpv4Address (n2, + netDeviceNumberNode2, Ipv4Address ("10.1.1.3"), + Ipv4Mask ("255.255.255.0")); - CsmaIpv4Topology::AddIpv4Address ( - n3, n3ifIndex, Ipv4Address("10.1.1.4"), Ipv4Mask("255.255.255.0")); + uint32_t ifIndexNode3 = CsmaIpv4Topology::AddIpv4Address (n3, + netDeviceNumberNode3, Ipv4Address ("10.1.1.4"), + Ipv4Mask ("255.255.255.0")); + + NS_DEBUG ("ifIndexNode0 = " << ifIndexNode0); + NS_DEBUG ("ifIndexNode1 = " << ifIndexNode1); + NS_DEBUG ("ifIndexNode2 = " << ifIndexNode2); + NS_DEBUG ("ifIndexNode3 = " << ifIndexNode3); // Configure multicasting NS_DEBUG("Configure multicasting."); @@ -158,22 +169,21 @@ main (int argc, char *argv[]) ipv4 = n0->QueryInterface (Ipv4::iid); std::vector outputInterfaces (1); - outputInterfaces[0] = n0ifIndex; + outputInterfaces[0] = ifIndexNode0; ipv4->AddMulticastRoute (multicastSource, multicastGroup, 0, outputInterfaces); ipv4 = n1->QueryInterface (Ipv4::iid); - ipv4->JoinMulticastGroup (multicastSource, multicastGroup); + // ipv4->JoinMulticastGroup (multicastSource, multicastGroup); ipv4 = n2->QueryInterface (Ipv4::iid); - ipv4->JoinMulticastGroup (multicastSource, multicastGroup); + // ipv4->JoinMulticastGroup (multicastSource, multicastGroup); ipv4 = n3->QueryInterface (Ipv4::iid); - ipv4->JoinMulticastGroup (multicastSource, multicastGroup); + // ipv4->JoinMulticastGroup (multicastSource, multicastGroup); - // Create the OnOff application to send UDP datagrams of size - // 210 bytes at a rate of 448 Kb/s + // Create the OnOff application to send UDP datagrams // from n0 to the multicast group NS_DEBUG("Create Applications."); Ptr ooff = Create ( @@ -181,10 +191,12 @@ main (int argc, char *argv[]) InetSocketAddress (multicastGroup, 80), "Udp", ConstantVariable(1), - ConstantVariable(0)); + ConstantVariable(0), + DataRate ("128b/s"), + 128); // Start the application - ooff->Start(Seconds(1.0)); - ooff->Stop (Seconds(10.0)); + ooff->Start(Seconds(1.)); + ooff->Stop (Seconds(10.)); // Configure tracing of all enqueue, dequeue, and NetDevice receive events // Trace output will be sent to the csma-one-subnet.tr file diff --git a/src/applications/onoff-application.cc b/src/applications/onoff-application.cc index 297d57e3e..9df4274bc 100644 --- a/src/applications/onoff-application.cc +++ b/src/applications/onoff-application.cc @@ -199,9 +199,12 @@ void OnOffApplication::ScheduleNextTx() if (m_totBytes < m_maxBytes) { uint32_t bits = m_pktSize * 8 - m_residualBits; + NS_DEBUG("OnOffApplication::ScheduleNextTx (): bits = " << bits); Time nextTime(Seconds (bits / static_cast(m_cbrRate.GetBitRate()))); // Time till next packet - m_sendEvent = Simulator::Schedule(nextTime, &OnOffApplication::SendPacket, this); + NS_DEBUG("OnOffApplication::ScheduleNextTx (): nextTime = " << nextTime); + m_sendEvent = Simulator::Schedule(nextTime, + &OnOffApplication::SendPacket, this); } else { // All done, cancel any pending events @@ -214,6 +217,8 @@ void OnOffApplication::ScheduleStartEvent() NS_DEBUG("OnOffApplication::ScheduleStartEvent ()"); Time offInterval = Seconds(m_offTime->GetValue()); + NS_DEBUG("OnOffApplication::ScheduleStartEvent (): " + "start at " << offInterval); m_startStopEvent = Simulator::Schedule(offInterval, &OnOffApplication::StartSending, this); } diff --git a/src/devices/csma/csma-ipv4-topology.cc b/src/devices/csma/csma-ipv4-topology.cc index 8e102af0b..ff36b5502 100644 --- a/src/devices/csma/csma-ipv4-topology.cc +++ b/src/devices/csma/csma-ipv4-topology.cc @@ -91,24 +91,22 @@ CsmaIpv4Topology::AddIpv4RawCsmaNode(Ptr n1, nd1->Attach (ch); } -void -CsmaIpv4Topology::AddIpv4Address(Ptr n1, - int ndNum, - const Ipv4Address& addr1, - const Ipv4Mask& netmask1) +uint32_t +CsmaIpv4Topology::AddIpv4Address( + Ptr node, + uint32_t netDeviceNumber, + const Ipv4Address address, + const Ipv4Mask mask) { - // Duplex link is assumed to be subnetted as a /30 - // May run this unnumbered in the future? - Ipv4Mask netmask(netmask1); + Ptr nd = node->GetDevice(netDeviceNumber); - Ptr nd1 = n1->GetDevice(ndNum); + Ptr ipv4 = node->QueryInterface (Ipv4::iid); + uint32_t ifIndex = ipv4->AddInterface (nd); - Ptr ip1 = n1->QueryInterface (Ipv4::iid); - uint32_t index1 = ip1->AddInterface (nd1); - - ip1->SetAddress (index1, addr1); - ip1->SetNetworkMask (index1, netmask); - ip1->SetUp (index1); + ipv4->SetAddress (ifIndex, address); + ipv4->SetNetworkMask (ifIndex, mask); + ipv4->SetUp (ifIndex); + return ifIndex; } void diff --git a/src/devices/csma/csma-ipv4-topology.h b/src/devices/csma/csma-ipv4-topology.h index 37f546118..ca4aa982b 100644 --- a/src/devices/csma/csma-ipv4-topology.h +++ b/src/devices/csma/csma-ipv4-topology.h @@ -94,18 +94,23 @@ public: /** - * \param n1 Node - * \param ndNum NetDevice number with which to associate address - * \param addr1 Ipv4 Address for ndNum of n1 - * \param network network mask for ndNum of node n1 + * \brief Create an Ipv4 interface for a net device and assign an + * Ipv4Address to that interface. + * + * \param node The node to which to add the new address and corresponding + * interface. + * \param netDeviceNumber The NetDevice index number with which to associate + * the address. + * \param address The Ipv4 Address for the interface. + * \param network The network mask for the interface * * Add an Ipv4Address to the Ipv4 interface associated with the - * ndNum CsmaIpv4NetDevices on the provided - * CsmaIpv4Channel + * ndNum CsmaIpv4NetDevices on the provided CsmaIpv4Channel */ - static void AddIpv4Address(Ptr n1, int ndNum, - const Ipv4Address& addr1, - const Ipv4Mask& netmask1); + static uint32_t AddIpv4Address(Ptr node, + uint32_t netDeviceNumber, + const Ipv4Address address, + const Ipv4Mask mask); /** * \param nd1 Node diff --git a/src/internet-node/arp-ipv4-interface.cc b/src/internet-node/arp-ipv4-interface.cc index 2e9d375b7..b5f87f0b6 100644 --- a/src/internet-node/arp-ipv4-interface.cc +++ b/src/internet-node/arp-ipv4-interface.cc @@ -81,6 +81,14 @@ ArpIpv4Interface::SendTo (Packet p, Ipv4Address dest) hardwareDestination = GetDevice ()->GetBroadcast (); found = true; } + else if (dest.IsMulticast ()) + { + NS_DEBUG ("ArpIpv4Interface::SendTo (): IsMulticast"); + // XXX BUGBUG + // Need real multicast addresses + hardwareDestination = GetDevice ()->GetBroadcast (); + found = true; + } else { NS_DEBUG ("ArpIpv4Interface::SendTo (): ARP Lookup"); diff --git a/src/internet-node/ipv4-l3-protocol.cc b/src/internet-node/ipv4-l3-protocol.cc index d140febe0..2326d1021 100644 --- a/src/internet-node/ipv4-l3-protocol.cc +++ b/src/internet-node/ipv4-l3-protocol.cc @@ -246,12 +246,26 @@ Ipv4L3Protocol::SetDefaultRoute (Ipv4Address nextHop, } void -Ipv4L3Protocol::Lookup (Ipv4Header const &ipHeader, - Packet packet, - Ipv4RoutingProtocol::RouteReplyCallback routeReply) +Ipv4L3Protocol::Lookup ( + Ipv4Header const &ipHeader, + Packet packet, + Ipv4RoutingProtocol::RouteReplyCallback routeReply) { - NS_DEBUG("Ipv4L3Protocol::Lookup (" << &ipHeader << ", " << &packet << - &routeReply << ")"); + NS_DEBUG("Ipv4L3Protocol::Lookup (" << &ipHeader << + ", " << &packet << &routeReply << ")"); + + Lookup (Ipv4RoutingProtocol::IF_INDEX_ANY, ipHeader, packet, routeReply); +} + +void +Ipv4L3Protocol::Lookup ( + uint32_t ifIndex, + Ipv4Header const &ipHeader, + Packet packet, + Ipv4RoutingProtocol::RouteReplyCallback routeReply) +{ + NS_DEBUG("Ipv4L3Protocol::Lookup (" << ifIndex << ", " << &ipHeader << + ", " << &packet << &routeReply << ")"); for (Ipv4RoutingProtocolList::const_iterator rprotoIter = m_routingProtocols.begin (); @@ -259,7 +273,8 @@ Ipv4L3Protocol::Lookup (Ipv4Header const &ipHeader, rprotoIter++) { NS_DEBUG("Ipv4L3Protocol::Lookup (): Requesting route"); - if ((*rprotoIter).second->RequestRoute (ipHeader, packet, routeReply)) + if ((*rprotoIter).second->RequestRoute (ifIndex, ipHeader, packet, + routeReply)) return; } @@ -405,7 +420,9 @@ Ipv4L3Protocol::Receive( Ptr device, const Packet& p, uint16_t protoc protocol << ", " << from << ")"); uint32_t index = 0; - for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++) + for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); + i != m_interfaces.end (); + i++) { if ((*i)->GetDevice () == device) { @@ -423,7 +440,7 @@ Ipv4L3Protocol::Receive( Ptr device, const Packet& p, uint16_t protoc return; } - if (Forwarding (packet, ipHeader, device)) + if (Forwarding (index, packet, ipHeader, device)) { return; } @@ -521,10 +538,14 @@ Ipv4L3Protocol::SendRealOut (bool found, } bool -Ipv4L3Protocol::Forwarding (Packet const &packet, Ipv4Header &ipHeader, Ptr device) +Ipv4L3Protocol::Forwarding ( + uint32_t ifIndex, + Packet const &packet, + Ipv4Header &ipHeader, + Ptr device) { - NS_DEBUG("Ipv4L3Protocol::Forwarding (" << &packet << ", " << &ipHeader << - ", " << device << ")"); + NS_DEBUG("Ipv4L3Protocol::Forwarding (" << ifIndex << ", " << &packet << + ", " << &ipHeader << ", " << device << ")"); for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++) @@ -579,7 +600,7 @@ Ipv4L3Protocol::Forwarding (Packet const &packet, Ipv4Header &ipHeader, Ptr device); + bool Forwarding (uint32_t ifIndex, + Packet const &packet, + Ipv4Header &ipHeader, + Ptr device); void ForwardUp (Packet p, Ipv4Header const&ip); uint32_t AddIpv4Interface (Ipv4Interface *interface); void SetupLoopback (void); diff --git a/src/internet-node/ipv4-static-routing.cc b/src/internet-node/ipv4-static-routing.cc index 785e817ff..e6e67b516 100644 --- a/src/internet-node/ipv4-static-routing.cc +++ b/src/internet-node/ipv4-static-routing.cc @@ -196,7 +196,8 @@ Ipv4StaticRouting::LookupStatic (Ipv4Address dest) Ipv4MulticastRoute * Ipv4StaticRouting::LookupStatic ( Ipv4Address origin, - Ipv4Address group) + Ipv4Address group, + uint32_t ifIndex) { for (MulticastRoutesI i = m_multicastRoutes.begin (); i != m_multicastRoutes.end (); @@ -207,7 +208,11 @@ Ipv4StaticRouting::LookupStatic ( origin == Ipv4Address::GetAny ()) && group == route->GetGroup ()) { - return *i; + if (ifIndex == Ipv4RoutingProtocol::IF_INDEX_ANY || + ifIndex == route->GetInputInterface ()) + { + return *i; + } } } return 0; @@ -312,9 +317,11 @@ Ipv4StaticRouting::RemoveRoute (uint32_t index) } bool -Ipv4StaticRouting::RequestRoute (Ipv4Header const &ipHeader, - Packet packet, - RouteReplyCallback routeReply) +Ipv4StaticRouting::RequestRoute ( + uint32_t ifIndex, + Ipv4Header const &ipHeader, + Packet packet, + RouteReplyCallback routeReply) { NS_DEBUG ("Ipv4StaticRouting::RequestRoute (" << &ipHeader << ", " << &packet << ", " << &routeReply << ")"); @@ -328,27 +335,35 @@ Ipv4StaticRouting::RequestRoute (Ipv4Header const &ipHeader, // 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. // - Ipv4MulticastRoute *mRoute = LookupStatic(ipHeader.GetSource (), - ipHeader.GetDestination ()); - if (mRoute) + if (ipHeader.GetDestination ().IsMulticast ()) { - NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): Multicast route"); - for (uint32_t i = 0; i < mRoute->GetNOutputInterfaces (); ++i) + NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): Multicast destination"); + + Ipv4MulticastRoute *mRoute = LookupStatic(ipHeader.GetSource (), + ipHeader.GetDestination (), ifIndex); + + if (mRoute) { - Packet p = packet; - Ipv4Route route = - Ipv4Route::CreateHostRouteTo(ipHeader.GetDestination (), - mRoute->GetOutputInterface(i)); NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): " - "Send via interface " << mRoute->GetOutputInterface(i)); - routeReply (true, route, p, ipHeader); - return true; + "Multicast route found"); + for (uint32_t i = 0; i < mRoute->GetNOutputInterfaces (); ++i) + { + Packet p = packet; + Ipv4Route route = + Ipv4Route::CreateHostRouteTo(ipHeader.GetDestination (), + mRoute->GetOutputInterface(i)); + NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): " + "Send via interface " << mRoute->GetOutputInterface(i)); + routeReply (true, route, p, ipHeader); + return true; + } } + return false; // Let other routing protocols try to handle this } // // See if this is a unicast packet we have a route for. // - NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): Unicast route"); + NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): Unicast destination"); Ipv4Route *route = LookupStatic (ipHeader.GetDestination ()); if (route != 0) { diff --git a/src/internet-node/ipv4-static-routing.h b/src/internet-node/ipv4-static-routing.h index 24a228048..76bb80c40 100644 --- a/src/internet-node/ipv4-static-routing.h +++ b/src/internet-node/ipv4-static-routing.h @@ -51,7 +51,8 @@ class Ipv4StaticRouting : public Ipv4RoutingProtocol public: Ipv4StaticRouting () : m_defaultRoute (0) {} - virtual bool RequestRoute (Ipv4Header const &ipHeader, + virtual bool RequestRoute (uint32_t ifIndex, + Ipv4Header const &ipHeader, Packet packet, RouteReplyCallback routeReply); @@ -105,7 +106,8 @@ private: typedef std::list::iterator MulticastRoutesI; Ipv4Route *LookupStatic (Ipv4Address dest); - Ipv4MulticastRoute *LookupStatic (Ipv4Address origin, Ipv4Address group); + Ipv4MulticastRoute *LookupStatic (Ipv4Address origin, Ipv4Address group, + uint32_t ifIndex); HostRoutes m_hostRoutes; NetworkRoutes m_networkRoutes; diff --git a/src/node/ipv4-address.cc b/src/node/ipv4-address.cc index 34b15372d..4e1e344c5 100644 --- a/src/node/ipv4-address.cc +++ b/src/node/ipv4-address.cc @@ -171,8 +171,11 @@ Ipv4Address::IsBroadcast (void) const bool Ipv4Address::IsMulticast (void) const { - // XXX - return false; +// +// Multicast addresses are defined as ranging from 224.0.0.0 through +// 239.255.255.255 (which is E0000000 through EFFFFFFF in hex). +// + return (m_address >= 0xe0000000 && m_address <= 0xefffffff); } uint32_t diff --git a/src/node/ipv4.h b/src/node/ipv4.h index 06cf5c130..d56a70c70 100644 --- a/src/node/ipv4.h +++ b/src/node/ipv4.h @@ -70,6 +70,7 @@ public: /** * \brief Asynchronously requests a route for a given packet and IP header * + * \param ifIndex The interface index on which the packet was received. * \param ipHeader IP header of the packet * \param packet packet that is being sent or forwarded * \param routeReply callback that will receive the route reply @@ -99,9 +100,12 @@ public: * immediately after the IP header, although most routing do not * insert any extra header. */ - virtual bool RequestRoute (const Ipv4Header &ipHeader, + virtual bool RequestRoute (uint32_t ifIndex, + const Ipv4Header &ipHeader, Packet packet, RouteReplyCallback routeReply) = 0; + + static const uint32_t IF_INDEX_ANY = 0xffffffff; }; /**