From 621e40bce8707e16caea8028aa8de66f194d66c2 Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Wed, 8 Apr 2009 13:35:02 -0700 Subject: [PATCH 01/22] File for documenting API changes of this repo --- README.api | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 README.api diff --git a/README.api b/README.api new file mode 100644 index 000000000..c027791b6 --- /dev/null +++ b/README.api @@ -0,0 +1,43 @@ +1. Changeset: + +Synopsis: +-------- +- deconflict NetDevice::ifIndex and Ipv4::ifIndex (bug 85) + +Changed public API (src/node) +-------- + +All function parameters named "ifIndex" that refer to an Ipv4 interface +are instead named "interface". + +- static const uint32_t Ipv4RoutingProtocol::IF_INDEX_ANY = 0xffffffff; ++ static const uint32_t Ipv4RoutingProtocol::INTERFACE_ANY = 0xffffffff; + +- bool Ipv4RoutingProtocol::RequestIfIndex (Ipv4Address destination, uint32_t& ifIndex); ++ bool Ipv4RoutingProtocol::RequestInterface (Ipv4Address destination, uint32_t& interface); +(N.B. this particular function will be later renamed to RouteOutput() in the +proposed IPv4 routing refactoring) + +- uint32_t Ipv4::GetIfIndexByAddress (Ipv4Address addr, Ipv4Mask mask); ++ int_32t Ipv4::GetInterfaceForAddress (Ipv4Address address, Ipv4Mask mask) const; + +- bool Ipv4::GetIfIndexForDestination (Ipv4Address dest, uint32_t &ifIndex) const; ++ bool Ipv4::GetInterfaceForDestination (Ipv4Address dest, uint32_t &interface) const; +(N.B. this function is not needed in the proposed Ipv4 routing refactoring) + + +New public API or classes (src/node) +-------- + +None. + +Changed private API (src/internet-node) +-------- + +New private API or classes (src/internet-node) +-------- + +None. + +Changeset: +- allow multiple IPv4 addresses to be assigned to an interface (bug 188) From 0528a56c4dd9abcc1905b2121fbc7beeccb24ad7 Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Wed, 8 Apr 2009 13:35:34 -0700 Subject: [PATCH 02/22] Ipv4::ifIndex -> Ipv4::interface --- doc/manual/routing.texi | 4 +- src/helper/ipv4-address-helper.cc | 18 ++-- src/helper/static-multicast-route-helper.cc | 14 +-- src/internet-stack/icmpv4-l4-protocol.cc | 2 +- src/internet-stack/ipv4-global-routing.cc | 10 +-- src/internet-stack/ipv4-global-routing.h | 14 +-- src/internet-stack/ipv4-impl.cc | 10 +-- src/internet-stack/ipv4-impl.h | 4 +- src/internet-stack/ipv4-l3-protocol.cc | 66 +++++++------- src/internet-stack/ipv4-l3-protocol.h | 10 +-- src/internet-stack/ipv4-raw-socket-impl.cc | 6 +- src/internet-stack/ipv4-static-routing.cc | 30 +++---- src/internet-stack/ipv4-static-routing.h | 24 +++--- src/internet-stack/tcp-socket-impl.cc | 16 ++-- src/internet-stack/udp-socket-impl.cc | 6 +- src/node/ipv4.cc | 4 +- src/node/ipv4.h | 26 +++--- .../global-route-manager-impl.cc | 4 +- .../global-routing/global-router-interface.cc | 86 +++++++++---------- .../global-routing/global-router-interface.h | 2 +- src/routing/olsr/olsr-routing-table.cc | 8 +- src/routing/olsr/olsr-routing-table.h | 6 +- 22 files changed, 185 insertions(+), 185 deletions(-) diff --git a/doc/manual/routing.texi b/doc/manual/routing.texi index 275a76fef..f7fc6d076 100644 --- a/doc/manual/routing.texi +++ b/doc/manual/routing.texi @@ -76,7 +76,7 @@ The main function that must be supported by these protocols is called * immediately after the IP header, although most routing do not * insert any extra header. */ - virtual bool RequestRoute (uint32_t ifIndex, + virtual bool RequestRoute (uint32_t interface, const Ipv4Header &ipHeader, Ptr packet, RouteReplyCallback routeReply) = 0; @@ -118,7 +118,7 @@ routing, insert it with priority less than 0; e.g.: The main function for obtaining a route is shown below: @verbatim Ipv4L3Protocol::Lookup ( - uint32_t ifIndex, + uint32_t interface, Ipv4Header const &ipHeader, Ptr packet, Ipv4RoutingProtocol::RouteReplyCallback routeReply) diff --git a/src/helper/ipv4-address-helper.cc b/src/helper/ipv4-address-helper.cc index ebdd11da4..65d72b7ed 100644 --- a/src/helper/ipv4-address-helper.cc +++ b/src/helper/ipv4-address-helper.cc @@ -131,19 +131,19 @@ Ipv4AddressHelper::Assign (const NetDeviceContainer &c) Ptr ipv4 = node->GetObject (); NS_ASSERT_MSG (ipv4, "Ipv4AddressHelper::Allocate(): Bad ipv4"); - int32_t ifIndex = ipv4->FindInterfaceForDevice (device); - if (ifIndex == -1) + int32_t interface = ipv4->FindInterfaceForDevice (device); + if (interface == -1) { - ifIndex = ipv4->AddInterface (device); + interface = ipv4->AddInterface (device); } - NS_ASSERT_MSG (ifIndex >= 0, "Ipv4AddressHelper::Allocate(): " + NS_ASSERT_MSG (interface >= 0, "Ipv4AddressHelper::Allocate(): " "Interface index not found"); - ipv4->SetAddress (ifIndex, NewAddress ()); - ipv4->SetNetworkMask (ifIndex, m_mask); - ipv4->SetMetric (ifIndex, 1); - ipv4->SetUp (ifIndex); - retval.Add (ipv4, ifIndex); + ipv4->SetAddress (interface, NewAddress ()); + ipv4->SetNetworkMask (interface, m_mask); + ipv4->SetMetric (interface, 1); + ipv4->SetUp (interface); + retval.Add (ipv4, interface); } return retval; } diff --git a/src/helper/static-multicast-route-helper.cc b/src/helper/static-multicast-route-helper.cc index a069d5834..3517b532a 100644 --- a/src/helper/static-multicast-route-helper.cc +++ b/src/helper/static-multicast-route-helper.cc @@ -42,16 +42,16 @@ StaticMulticastRouteHelper::AddMulticastRoute ( { Ptr ipv4 = n->GetObject (); - // We need to convert the NetDeviceContainer to an array of ifIndex + // We need to convert the NetDeviceContainer to an array of interface std::vector outputInterfaces; for (NetDeviceContainer::Iterator i = output.Begin (); i != output.End (); ++i) { Ptr nd = *i; - uint32_t oifIndex = ipv4->FindInterfaceForDevice (nd); - outputInterfaces.push_back(oifIndex); + uint32_t ointerface = ipv4->FindInterfaceForDevice (nd); + outputInterfaces.push_back(ointerface); } - uint32_t iifIndex = ipv4->FindInterfaceForDevice (input); - ipv4->AddMulticastRoute (source, group, iifIndex, outputInterfaces); + uint32_t iinterface = ipv4->FindInterfaceForDevice (input); + ipv4->AddMulticastRoute (source, group, iinterface, outputInterfaces); } void @@ -97,8 +97,8 @@ StaticMulticastRouteHelper::SetDefaultMulticastRoute ( Ptr nd) { Ptr ipv4 = n->GetObject (); - uint32_t ifIndexSrc = ipv4->FindInterfaceForDevice (nd); - ipv4->SetDefaultMulticastRoute (ifIndexSrc); + uint32_t interfaceSrc = ipv4->FindInterfaceForDevice (nd); + ipv4->SetDefaultMulticastRoute (interfaceSrc); } void diff --git a/src/internet-stack/icmpv4-l4-protocol.cc b/src/internet-stack/icmpv4-l4-protocol.cc index 751024695..8b22fe813 100644 --- a/src/internet-stack/icmpv4-l4-protocol.cc +++ b/src/internet-stack/icmpv4-l4-protocol.cc @@ -63,7 +63,7 @@ Icmpv4L4Protocol::SendMessage (Ptr packet, Ipv4Address dest, uint8_t typ { Ptr ipv4 = m_node->GetObject (); uint32_t i; - if (!ipv4->GetIfIndexForDestination (dest, i)) + if (!ipv4->GetInterfaceForDestination (dest, i)) { NS_LOG_WARN ("drop icmp message"); return; diff --git a/src/internet-stack/ipv4-global-routing.cc b/src/internet-stack/ipv4-global-routing.cc index f659c8ecf..11a177a42 100644 --- a/src/internet-stack/ipv4-global-routing.cc +++ b/src/internet-stack/ipv4-global-routing.cc @@ -209,12 +209,12 @@ Ipv4GlobalRouting::RemoveRoute (uint32_t index) bool Ipv4GlobalRouting::RequestRoute ( - uint32_t ifIndex, + uint32_t interface, Ipv4Header const &ipHeader, Ptr packet, RouteReplyCallback routeReply) { - NS_LOG_FUNCTION (this << ifIndex << &ipHeader << packet << &routeReply); + NS_LOG_FUNCTION (this << interface << &ipHeader << packet << &routeReply); NS_LOG_LOGIC ("source = " << ipHeader.GetSource ()); @@ -243,9 +243,9 @@ Ipv4GlobalRouting::RequestRoute ( } bool -Ipv4GlobalRouting::RequestIfIndex (Ipv4Address destination, uint32_t& ifIndex) +Ipv4GlobalRouting::RequestInterface (Ipv4Address destination, uint32_t& interface) { - NS_LOG_FUNCTION (this << destination << &ifIndex); + NS_LOG_FUNCTION (this << destination << &interface); // // 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. @@ -262,7 +262,7 @@ Ipv4GlobalRouting::RequestIfIndex (Ipv4Address destination, uint32_t& ifIndex) Ipv4Route *route = LookupGlobal (destination); if (route) { - ifIndex = route->GetInterface (); + interface = route->GetInterface (); return true; } else diff --git a/src/internet-stack/ipv4-global-routing.h b/src/internet-stack/ipv4-global-routing.h index b30a8bf3d..9be7a03e5 100644 --- a/src/internet-stack/ipv4-global-routing.h +++ b/src/internet-stack/ipv4-global-routing.h @@ -92,9 +92,9 @@ public: * If the destination address is a multicast, then the method will return * false. * - * @param ifIndex The network interface index over which the packed was - * received. If the packet is from a local source, ifIndex will be set to - * Ipv4RoutingProtocol::IF_INDEX_ANY. + * @param interface The network interface index over which the packed was + * received. If the packet is from a local source, interface will be set to + * Ipv4RoutingProtocol::INTERFACE_INDEX_ANY. * @param ipHeader the Ipv4Header containing the source and destination IP * addresses for the packet. * @param packet The packet to be sent if a route is found. @@ -107,7 +107,7 @@ public: * @see Ipv4GlobalRouting * @see Ipv4RoutingProtocol */ - virtual bool RequestRoute (uint32_t ifIndex, + virtual bool RequestRoute (uint32_t interface, Ipv4Header const &ipHeader, Ptr packet, RouteReplyCallback routeReply); @@ -126,14 +126,14 @@ public: * given destination. * * If there are multiple paths out of the node, the resolution is performed - * by Ipv4L3Protocol::GetIfIndexforDestination which has access to more + * by Ipv4L3Protocol::GetInterfaceforDestination which has access to more * contextual information that is useful for making a determination. * * This method will return false on a multicast address. * * @param destination The Ipv4Address if the destination of a hypothetical * packet. This may be a multicast group address. - * @param ifIndex A reference to the interface index over which a packet + * @param interface A reference to the interface index over which a packet * sent to this destination would be sent. * @return Returns true if a route is found to the destination that involves * a single output interface index, otherwise returns false indicating that @@ -143,7 +143,7 @@ public: * @see Ipv4RoutingProtocol * @see Ipv4L3Protocol */ - virtual bool RequestIfIndex (Ipv4Address destination, uint32_t& ifIndex); + virtual bool RequestInterface (Ipv4Address destination, uint32_t& interface); /** * @brief Add a host route to the global routing table. diff --git a/src/internet-stack/ipv4-impl.cc b/src/internet-stack/ipv4-impl.cc index 3fd0884a5..fb3e0a48b 100644 --- a/src/internet-stack/ipv4-impl.cc +++ b/src/internet-stack/ipv4-impl.cc @@ -224,21 +224,21 @@ Ipv4Impl::GetMetric (uint32_t i) const } bool -Ipv4Impl::GetIfIndexForDestination (Ipv4Address dest, uint32_t &ifIndex) const +Ipv4Impl::GetInterfaceForDestination (Ipv4Address dest, uint32_t &interface) const { - return m_ipv4->GetIfIndexForDestination (dest, ifIndex); + return m_ipv4->GetInterfaceForDestination (dest, interface); } Ipv4Address Ipv4Impl::GetSourceAddress (Ipv4Address destination) const { - uint32_t ifIndex = 0xffffffff; + uint32_t interface = 0xffffffff; - bool result = m_ipv4->GetIfIndexForDestination (destination, ifIndex); + bool result = m_ipv4->GetInterfaceForDestination (destination, interface); if (result) { - return m_ipv4->GetAddress (ifIndex); + return m_ipv4->GetAddress (interface); } else { diff --git a/src/internet-stack/ipv4-impl.h b/src/internet-stack/ipv4-impl.h index 094884caf..ed5f2e7f6 100644 --- a/src/internet-stack/ipv4-impl.h +++ b/src/internet-stack/ipv4-impl.h @@ -94,8 +94,8 @@ public: virtual void SetMetric (uint32_t i, uint16_t metric); virtual uint16_t GetMetric (uint32_t i) const; virtual Ipv4Address GetSourceAddress (Ipv4Address destination) const; - virtual bool GetIfIndexForDestination (Ipv4Address dest, - uint32_t &ifIndex) const; + virtual bool GetInterfaceForDestination (Ipv4Address dest, + uint32_t &interface) const; virtual uint16_t GetMtu (uint32_t i) const; virtual bool IsUp (uint32_t i) const; diff --git a/src/internet-stack/ipv4-l3-protocol.cc b/src/internet-stack/ipv4-l3-protocol.cc index 05adfab64..429efece9 100644 --- a/src/internet-stack/ipv4-l3-protocol.cc +++ b/src/internet-stack/ipv4-l3-protocol.cc @@ -242,17 +242,17 @@ Ipv4L3Protocol::Lookup ( { NS_LOG_FUNCTION (this << &ipHeader << packet << &routeReply); - Lookup (Ipv4RoutingProtocol::IF_INDEX_ANY, ipHeader, packet, routeReply); + Lookup (Ipv4RoutingProtocol::INTERFACE_ANY, ipHeader, packet, routeReply); } void Ipv4L3Protocol::Lookup ( - uint32_t ifIndex, + uint32_t interface, Ipv4Header const &ipHeader, Ptr packet, Ipv4RoutingProtocol::RouteReplyCallback routeReply) { - NS_LOG_FUNCTION (this << ifIndex << &ipHeader << packet << &routeReply); + NS_LOG_FUNCTION (this << interface << &ipHeader << packet << &routeReply); for (Ipv4RoutingProtocolList::const_iterator rprotoIter = m_routingProtocols.begin (); @@ -260,13 +260,13 @@ Ipv4L3Protocol::Lookup ( rprotoIter++) { NS_LOG_LOGIC ("Requesting route"); - if ((*rprotoIter).second->RequestRoute (ifIndex, ipHeader, packet, + if ((*rprotoIter).second->RequestRoute (interface, ipHeader, packet, routeReply)) return; } if (ipHeader.GetDestination ().IsMulticast () && - ifIndex == Ipv4RoutingProtocol::IF_INDEX_ANY) + interface == Ipv4RoutingProtocol::INTERFACE_ANY) { NS_LOG_LOGIC ("Multicast destination with local source"); // @@ -432,14 +432,14 @@ Ipv4L3Protocol::FindInterfaceForAddr (Ipv4Address addr) const { NS_LOG_FUNCTION (this << addr); - uint32_t ifIndex = 0; + uint32_t interface = 0; for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); - i++, ifIndex++) + i++, interface++) { if ((*i)->GetAddress () == addr) { - return ifIndex; + return interface; } } @@ -453,14 +453,14 @@ Ipv4L3Protocol::FindInterfaceForAddr (Ipv4Address addr, Ipv4Mask mask) const { NS_LOG_FUNCTION (this << addr << mask); - uint32_t ifIndex = 0; + uint32_t interface = 0; for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); - i++, ifIndex++) + i++, interface++) { if ((*i)->GetAddress ().CombineMask (mask) == addr.CombineMask (mask)) { - return ifIndex; + return interface; } } @@ -474,14 +474,14 @@ Ipv4L3Protocol::FindInterfaceIndexForDevice (Ptr device) const { NS_LOG_FUNCTION (this << device); - uint32_t ifIndex = 0; + uint32_t interface = 0; for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); - i++, ifIndex++) + i++, interface++) { if ((*i)->GetDevice () == device) { - return ifIndex; + return interface; } } @@ -777,12 +777,12 @@ Ipv4L3Protocol::SendRealOut (bool found, bool Ipv4L3Protocol::Forwarding ( - uint32_t ifIndex, + uint32_t interface, Ptr packet, Ipv4Header &ipHeader, Ptr device) { - NS_LOG_FUNCTION (ifIndex << packet << &ipHeader<< device); + NS_LOG_FUNCTION (interface << packet << &ipHeader<< device); NS_LOG_LOGIC ("Forwarding logic for node: " << m_node->GetId ()); for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); @@ -835,26 +835,26 @@ Ipv4L3Protocol::Forwarding ( // We forward with a packet copy, since forwarding may change // the packet, affecting our local delivery NS_LOG_LOGIC ("Forwarding (multicast)."); - DoForward (ifIndex, packet->Copy (), ipHeader); + DoForward (interface, packet->Copy (), ipHeader); return false; } } - DoForward (ifIndex, packet, ipHeader); + DoForward (interface, packet, ipHeader); return true; } void -Ipv4L3Protocol::DoForward (uint32_t ifIndex, +Ipv4L3Protocol::DoForward (uint32_t interface, Ptr packet, Ipv4Header ipHeader) { - NS_LOG_FUNCTION (this << ifIndex << packet << ipHeader); + NS_LOG_FUNCTION (this << interface << packet << ipHeader); ipHeader.SetTtl (ipHeader.GetTtl () - 1); if (ipHeader.GetTtl () == 0) { - if (IsUnicast (ipHeader.GetDestination (), GetInterface (ifIndex)->GetNetworkMask ())) + if (IsUnicast (ipHeader.GetDestination (), GetInterface (interface)->GetNetworkMask ())) { Ptr icmp = GetIcmp (); icmp->SendTimeExceededTtl (ipHeader, packet); @@ -864,7 +864,7 @@ Ipv4L3Protocol::DoForward (uint32_t ifIndex, return; } NS_LOG_LOGIC ("Not for me, forwarding."); - Lookup (ifIndex, ipHeader, packet, + Lookup (interface, ipHeader, packet, MakeCallback (&Ipv4L3Protocol::SendRealOut, this)); } @@ -972,10 +972,10 @@ Ipv4L3Protocol::GetMetric (uint32_t i) const } bool -Ipv4L3Protocol::GetIfIndexForDestination ( - Ipv4Address destination, uint32_t& ifIndex) const +Ipv4L3Protocol::GetInterfaceForDestination ( + Ipv4Address destination, uint32_t& interface) const { - NS_LOG_FUNCTION (this << destination << &ifIndex); + NS_LOG_FUNCTION (this << destination << &interface); // // The first thing we do in trying to determine a source address is to // consult the routing protocols. These will also check for a default route @@ -986,12 +986,12 @@ Ipv4L3Protocol::GetIfIndexForDestination ( i++) { NS_LOG_LOGIC ("Requesting Source Address"); - uint32_t ifIndexTmp; + uint32_t interfaceTmp; - if ((*i).second->RequestIfIndex (destination, ifIndexTmp)) + if ((*i).second->RequestInterface (destination, interfaceTmp)) { - NS_LOG_LOGIC ("Found ifIndex " << ifIndexTmp); - ifIndex = ifIndexTmp; + NS_LOG_LOGIC ("Found interface " << interfaceTmp); + interface = interfaceTmp; return true; } } @@ -1007,7 +1007,7 @@ Ipv4L3Protocol::GetIfIndexForDestination ( if (GetNInterfaces () == 2) { NS_LOG_LOGIC ("One Interface. Using interface 1."); - ifIndex = 1; + interface = 1; return true; } // @@ -1030,14 +1030,14 @@ Ipv4L3Protocol::GetIfIndexForDestination ( if (route == NULL) { - NS_LOG_LOGIC ("Ipv4L3Protocol::GetIfIndexForDestination (): " + NS_LOG_LOGIC ("Ipv4L3Protocol::GetInterfaceForDestination (): " "Unable to determine outbound interface. No default route set"); return false; } - ifIndex = route->GetInterface (); + interface = route->GetInterface (); - NS_LOG_LOGIC ("Default route specifies interface " << ifIndex); + NS_LOG_LOGIC ("Default route specifies interface " << interface); return true; } diff --git a/src/internet-stack/ipv4-l3-protocol.h b/src/internet-stack/ipv4-l3-protocol.h index 6218eb8d4..00cfd8c91 100644 --- a/src/internet-stack/ipv4-l3-protocol.h +++ b/src/internet-stack/ipv4-l3-protocol.h @@ -193,8 +193,8 @@ public: Ipv4Address GetAddress (uint32_t i) const; void SetMetric (uint32_t i, uint16_t metric); uint16_t GetMetric (uint32_t i) const; - bool GetIfIndexForDestination (Ipv4Address destination, - uint32_t& ifIndex) const; + bool GetInterfaceForDestination (Ipv4Address destination, + uint32_t& interface) const; uint16_t GetMtu (uint32_t i) const; bool IsUp (uint32_t i) const; void SetUp (uint32_t i); @@ -210,7 +210,7 @@ protected: private: Ipv4L3Protocol(const Ipv4L3Protocol &); Ipv4L3Protocol &operator = (const Ipv4L3Protocol &); - void Lookup (uint32_t ifIndex, + void Lookup (uint32_t interface, Ipv4Header const &ipHeader, Ptr packet, Ipv4RoutingProtocol::RouteReplyCallback routeReply); @@ -219,7 +219,7 @@ private: Ipv4Route const &route, Ptr packet, Ipv4Header const &ipHeader); - bool Forwarding (uint32_t ifIndex, + bool Forwarding (uint32_t interface, Ptr packet, Ipv4Header &ipHeader, Ptr device); @@ -228,7 +228,7 @@ private: void SetupLoopback (void); Ptr GetIcmp (void) const; bool IsUnicast (Ipv4Address ad, Ipv4Mask interfaceMask) const; - void DoForward (uint32_t ifIndex, + void DoForward (uint32_t interface, Ptr packet, Ipv4Header ipHeader); diff --git a/src/internet-stack/ipv4-raw-socket-impl.cc b/src/internet-stack/ipv4-raw-socket-impl.cc index e99f2addd..7bca1a91e 100644 --- a/src/internet-stack/ipv4-raw-socket-impl.cc +++ b/src/internet-stack/ipv4-raw-socket-impl.cc @@ -170,10 +170,10 @@ Ipv4RawSocketImpl::SendTo (Ptr p, uint32_t flags, InetSocketAddress ad = InetSocketAddress::ConvertFrom (toAddress); Ptr ipv4 = m_node->GetObject (); Ipv4Address dst = ad.GetIpv4 (); - uint32_t localIfIndex; - if (ipv4->GetIfIndexForDestination(dst, localIfIndex)) + uint32_t localInterface; + if (ipv4->GetInterfaceForDestination(dst, localInterface)) { - ipv4->Send (p, ipv4->GetAddress (localIfIndex), dst, m_protocol); + ipv4->Send (p, ipv4->GetAddress (localInterface), dst, m_protocol); } else { diff --git a/src/internet-stack/ipv4-static-routing.cc b/src/internet-stack/ipv4-static-routing.cc index ba3f27c35..744c3bc99 100644 --- a/src/internet-stack/ipv4-static-routing.cc +++ b/src/internet-stack/ipv4-static-routing.cc @@ -111,7 +111,7 @@ Ipv4StaticRouting::SetDefaultMulticastRoute(uint32_t outputInterface) NS_LOG_FUNCTION_NOARGS (); Ipv4Address origin = Ipv4Address::GetAny (); Ipv4Address group = Ipv4Address::GetAny (); - uint32_t inputInterface = Ipv4RoutingProtocol::IF_INDEX_ANY; + uint32_t inputInterface = Ipv4RoutingProtocol::INTERFACE_ANY; std::vector outputInterfaces (1); outputInterfaces[0] = outputInterface; @@ -296,7 +296,7 @@ Ipv4MulticastRoute * Ipv4StaticRouting::LookupStatic ( Ipv4Address origin, Ipv4Address group, - uint32_t ifIndex) + uint32_t interface) { NS_LOG_FUNCTION_NOARGS (); // @@ -317,12 +317,12 @@ Ipv4StaticRouting::LookupStatic ( // // The first case is the restrictive case where the origin, group and index // matches. This picks up exact routes during forwarded and exact routes from -// the local node (in which case the ifIndex is a wildcard). +// the local node (in which case the interface is a wildcard). // if (origin == route->GetOrigin () && group == route->GetGroup ()) { - if (ifIndex == Ipv4RoutingProtocol::IF_INDEX_ANY || - ifIndex == route->GetInputInterface ()) + if (interface == Ipv4RoutingProtocol::INTERFACE_ANY || + interface == route->GetInputInterface ()) { return *i; } @@ -334,7 +334,7 @@ Ipv4StaticRouting::LookupStatic ( // just happily forward packets we don't really know what to do with. // Multicast storms are not generally considered a good thing. // - if (ifIndex != Ipv4RoutingProtocol::IF_INDEX_ANY) + if (interface != Ipv4RoutingProtocol::INTERFACE_ANY) { return 0; } @@ -515,12 +515,12 @@ Ipv4StaticRouting::RemoveRoute (uint32_t index) bool Ipv4StaticRouting::RequestRoute ( - uint32_t ifIndex, + uint32_t interface, Ipv4Header const &ipHeader, Ptr packet, RouteReplyCallback routeReply) { - NS_LOG_FUNCTION (this << ifIndex << &ipHeader << packet << &routeReply); + NS_LOG_FUNCTION (this << interface << &ipHeader << packet << &routeReply); NS_LOG_LOGIC ("source = " << ipHeader.GetSource ()); @@ -531,7 +531,7 @@ Ipv4StaticRouting::RequestRoute ( NS_LOG_LOGIC ("Multicast destination"); Ipv4MulticastRoute *mRoute = LookupStatic(ipHeader.GetSource (), - ipHeader.GetDestination (), ifIndex); + ipHeader.GetDestination (), interface); if (mRoute) { @@ -570,9 +570,9 @@ Ipv4StaticRouting::RequestRoute ( } bool -Ipv4StaticRouting::RequestIfIndex (Ipv4Address destination, uint32_t& ifIndex) +Ipv4StaticRouting::RequestInterface (Ipv4Address destination, uint32_t& interface) { - NS_LOG_FUNCTION (this << destination << &ifIndex); + NS_LOG_FUNCTION (this << destination << &interface); // // 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. @@ -582,7 +582,7 @@ Ipv4StaticRouting::RequestIfIndex (Ipv4Address destination, uint32_t& ifIndex) NS_LOG_LOGIC ("Multicast destination"); Ipv4MulticastRoute *mRoute = LookupStatic(Ipv4Address::GetAny (), - destination, Ipv4RoutingProtocol::IF_INDEX_ANY); + destination, Ipv4RoutingProtocol::INTERFACE_ANY); if (mRoute) { @@ -594,8 +594,8 @@ Ipv4StaticRouting::RequestIfIndex (Ipv4Address destination, uint32_t& ifIndex) return false; } - ifIndex = mRoute->GetOutputInterface(0); - NS_LOG_LOGIC ("Found ifIndex " << ifIndex); + interface = mRoute->GetOutputInterface(0); + NS_LOG_LOGIC ("Found interface " << interface); return true; } return false; // Let other routing protocols try to handle this @@ -607,7 +607,7 @@ Ipv4StaticRouting::RequestIfIndex (Ipv4Address destination, uint32_t& ifIndex) Ipv4Route *route = LookupStatic (destination); if (route) { - ifIndex = route->GetInterface (); + interface = route->GetInterface (); return true; } else diff --git a/src/internet-stack/ipv4-static-routing.h b/src/internet-stack/ipv4-static-routing.h index 1a17d2095..128fc7d2d 100644 --- a/src/internet-stack/ipv4-static-routing.h +++ b/src/internet-stack/ipv4-static-routing.h @@ -102,10 +102,10 @@ public: * * If the destination address is a multicast, then the exact processing steps * depend on whether or not the packet has been sourced locally. This is - * determined by the parameter ifIndex. This is the interface index over which + * determined by the parameter interface. This is the interface index over which * this packet was received. If the packet has not been received over a * network interface, this index will be set to - * Ipv4RoutingProtocol::IF_INDEX_ANY (a very large number). In that case, + * Ipv4RoutingProtocol::INTERFACE_INDEX_ANY (a very large number). In that case, * we want to avoid the requirement that an explicit route out of each node * must be set, so we don't do anything here. * @@ -118,9 +118,9 @@ public: * packet out of as many interfaces as required using the provided callback * (think of it as a pre-packaged send call). * - * @param ifIndex The network interface index over which the packed was - * received. If the packet is from a local source, ifIndex will be set to - * Ipv4RoutingProtocol::IF_INDEX_ANY. + * @param interface The network interface index over which the packed was + * received. If the packet is from a local source, interface will be set to + * Ipv4RoutingProtocol::INTERFACE_ANY. * @param ipHeader the Ipv4Header containing the source and destination IP * addresses for the packet. * @param packet The packet to be sent if a route is found. @@ -134,7 +134,7 @@ public: * @see Ipv4StaticRouting * @see Ipv4RoutingProtocol */ - virtual bool RequestRoute (uint32_t ifIndex, + virtual bool RequestRoute (uint32_t interface, Ipv4Header const &ipHeader, Ptr packet, RouteReplyCallback routeReply); @@ -157,12 +157,12 @@ public: * that includeds multiple output interfaces, that route cannot be used. * * If there are multiple paths out of the node, the resolution is performed - * by Ipv4L3Protocol::GetIfIndexforDestination which has access to more + * by Ipv4L3Protocol::GetInterfaceforDestination which has access to more * contextual information that is useful for making a determination. * * @param destination The Ipv4Address if the destination of a hypothetical * packet. This may be a multicast group address. - * @param ifIndex A reference to the interface index over which a packet + * @param interface A reference to the interface index over which a packet * sent to this destination would be sent. * @return Returns true if a route is found to the destination that involves * a single output interface index, otherwise returns false indicating that @@ -173,7 +173,7 @@ public: * @see Ipv4RoutingProtocol * @see Ipv4L3Protocol */ - virtual bool RequestIfIndex (Ipv4Address destination, uint32_t& ifIndex); + virtual bool RequestInterface (Ipv4Address destination, uint32_t& interface); /** * @brief Add a host route to the static routing table. @@ -323,7 +323,7 @@ public: * of a local node. The difference is in the input interface. Routes for * forwarding will always have an explicit input interface specified. Routes * off of a node will always set the input interface to a wildcard specified - * by the index Ipv4RoutingProtocol::IF_INDEX_ANY. + * by the index Ipv4RoutingProtocol::INTERFACE_ANY. * * For routes off of a local node wildcards may be used in the origin and * multicast group addresses. The wildcard used for Ipv4Adresses is that @@ -346,7 +346,7 @@ public: * @param group The Ipv4Address of the multicast group or this route. * @param inputInterface The input network interface index over which to * expect packets destined for this route. May be - * Ipv4RoutingProtocol::IF_INDEX_ANY for packets of local origin. + * Ipv4RoutingProtocol::INTERFACE_ANY for packets of local origin. * @param outputInterfaces A vector of network interface indices used to specify * how to send packets to the destination(s). * @@ -492,7 +492,7 @@ private: Ipv4Route *LookupStatic (Ipv4Address dest); Ipv4MulticastRoute *LookupStatic (Ipv4Address origin, Ipv4Address group, - uint32_t ifIndex); + uint32_t interface); HostRoutes m_hostRoutes; NetworkRoutes m_networkRoutes; diff --git a/src/internet-stack/tcp-socket-impl.cc b/src/internet-stack/tcp-socket-impl.cc index 9630a4596..d0522f444 100644 --- a/src/internet-stack/tcp-socket-impl.cc +++ b/src/internet-stack/tcp-socket-impl.cc @@ -340,12 +340,12 @@ TcpSocketImpl::Connect (const Address & address) m_remoteAddress = transport.GetIpv4 (); m_remotePort = transport.GetPort (); - uint32_t localIfIndex; + uint32_t localInterface; Ptr ipv4 = m_node->GetObject (); - if (ipv4->GetIfIndexForDestination (m_remoteAddress, localIfIndex)) + if (ipv4->GetInterfaceForDestination (m_remoteAddress, localInterface)) { - m_endPoint->SetLocalAddress (ipv4->GetAddress (localIfIndex)); + m_endPoint->SetLocalAddress (ipv4->GetAddress (localInterface)); } else { @@ -794,7 +794,7 @@ bool TcpSocketImpl::ProcessPacketAction (Actions_t a, Ptr p, const Address& fromAddress) { NS_LOG_FUNCTION (this << a << p << fromAddress); - uint32_t localIfIndex; + uint32_t localInterface; Ptr ipv4 = m_node->GetObject (); switch (a) { @@ -809,9 +809,9 @@ bool TcpSocketImpl::ProcessPacketAction (Actions_t a, Ptr p, NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action SYN_ACK_TX"); // m_remotePort = InetSocketAddress::ConvertFrom (fromAddress).GetPort (); // m_remoteAddress = InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (); -// if (ipv4->GetIfIndexForDestination (m_remoteAddress, localIfIndex)) +// if (ipv4->GetInterfaceForDestination (m_remoteAddress, localInterface)) // { -// m_localAddress = ipv4->GetAddress (localIfIndex); +// m_localAddress = ipv4->GetAddress (localInterface); // } if (m_state == LISTEN) //this means we should fork a new TcpSocketImpl { @@ -830,9 +830,9 @@ bool TcpSocketImpl::ProcessPacketAction (Actions_t a, Ptr p, // This is the cloned endpoint NS_ASSERT (m_state == SYN_RCVD); m_endPoint->SetPeer (m_remoteAddress, m_remotePort); - if (ipv4->GetIfIndexForDestination (m_remoteAddress, localIfIndex)) + if (ipv4->GetInterfaceForDestination (m_remoteAddress, localInterface)) { - m_localAddress = ipv4->GetAddress (localIfIndex); + m_localAddress = ipv4->GetAddress (localInterface); m_endPoint->SetLocalAddress (m_localAddress); // Leave local addr in the portmap to any, as the path from // remote can change and packets can arrive on different interfaces diff --git a/src/internet-stack/udp-socket-impl.cc b/src/internet-stack/udp-socket-impl.cc index f58d3c659..358e5e255 100644 --- a/src/internet-stack/udp-socket-impl.cc +++ b/src/internet-stack/udp-socket-impl.cc @@ -308,7 +308,7 @@ UdpSocketImpl::DoSendTo (Ptr p, Ipv4Address dest, uint16_t port) return -1; } - uint32_t localIfIndex; + uint32_t localInterface; Ptr ipv4 = m_node->GetObject (); // Locally override the IP TTL for this socket @@ -389,10 +389,10 @@ UdpSocketImpl::DoSendTo (Ptr p, Ipv4Address dest, uint16_t port) NS_LOG_LOGIC ("Limited broadcast end."); return p->GetSize(); } - else if (ipv4->GetIfIndexForDestination(dest, localIfIndex)) + else if (ipv4->GetInterfaceForDestination(dest, localInterface)) { NS_LOG_LOGIC ("Route exists"); - m_udp->Send (p->Copy (), ipv4->GetAddress (localIfIndex), dest, + m_udp->Send (p->Copy (), ipv4->GetAddress (localInterface), dest, m_endPoint->GetLocalPort (), port); NotifyDataSent (p->GetSize ()); NotifySend (GetTxAvailable ()); diff --git a/src/node/ipv4.cc b/src/node/ipv4.cc index 6bc054c9e..731a0c484 100644 --- a/src/node/ipv4.cc +++ b/src/node/ipv4.cc @@ -41,7 +41,7 @@ Ipv4::~Ipv4 () {} uint32_t -Ipv4::GetIfIndexByAddress (Ipv4Address addr, Ipv4Mask mask) +Ipv4::GetInterfaceByAddress (Ipv4Address addr, Ipv4Mask mask) { for (uint32_t i = 0; i < GetNInterfaces (); i++) { @@ -51,7 +51,7 @@ Ipv4::GetIfIndexByAddress (Ipv4Address addr, Ipv4Mask mask) } } // Mapping not found - NS_ASSERT_MSG (false, "Ipv4::GetIfIndexByAddress failed"); + NS_ASSERT_MSG (false, "Ipv4::GetInterfaceByAddress failed"); return 0; } diff --git a/src/node/ipv4.h b/src/node/ipv4.h index f6ccec45e..7febbdcc2 100644 --- a/src/node/ipv4.h +++ b/src/node/ipv4.h @@ -76,7 +76,7 @@ public: /** * \brief Request that a packet be routed. * - * \param ifIndex The interface index on which the packet was received. + * \param interface 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 @@ -111,7 +111,7 @@ public: * destination will be serviced by cloning the packet and calling the * route reply callback once for each outgoing interface in the route. */ - virtual bool RequestRoute (uint32_t ifIndex, + virtual bool RequestRoute (uint32_t interface, const Ipv4Header &ipHeader, Ptr packet, RouteReplyCallback routeReply) = 0; @@ -134,12 +134,12 @@ public: * that includeds multiple output interfaces, that route cannot be used. * * If there are multiple paths out of the node, the resolution is performed - * by Ipv4L3Protocol::GetIfIndexforDestination which has access to more + * by Ipv4L3Protocol::GetInterfaceforDestination which has access to more * contextual information that is useful for making a determination. * * \param destination The Ipv4Address if the destination of a hypothetical * packet. This may be a multicast group address. - * \param ifIndex A reference to the interface index over which a packet + * \param interface A reference to the interface index over which a packet * sent to this destination would be sent. * \return Returns true if a route is found to the destination that involves * a single output interface index, otherwise false. @@ -148,10 +148,10 @@ public: * \see Ipv4RoutingProtocol * \see Ipv4L3Protocol */ - virtual bool RequestIfIndex (Ipv4Address destination, - uint32_t& ifIndex) = 0; + virtual bool RequestInterface (Ipv4Address destination, + uint32_t& interface) = 0; - static const uint32_t IF_INDEX_ANY = 0xffffffff; + static const uint32_t INTERFACE_ANY = 0xffffffff; }; /** @@ -447,12 +447,12 @@ public: /** * \param dest The IP address of a hypothetical destination. - * \param ifIndex filled in with the interface index that will be used to + * \param interface filled in with the interface index that will be used to * send a packet to the hypothetical destination. * \returns true if a single interface can be identified, false otherwise. */ - virtual bool GetIfIndexForDestination (Ipv4Address dest, - uint32_t &ifIndex) const = 0; + virtual bool GetInterfaceForDestination (Ipv4Address dest, + uint32_t &interface) const = 0; /** * \param i index of ipv4 interface @@ -485,14 +485,14 @@ public: virtual void SetDown (uint32_t i) = 0; /** - * \brief Convenience function to return the ifIndex corresponding + * \brief Convenience function to return the interface corresponding * to the Ipv4Address provided * * \param addr Ipv4Address * \param mask corresponding Ipv4Mask - * \returns ifIndex corresponding to a/amask + * \returns interface corresponding to a/amask */ - virtual uint32_t GetIfIndexByAddress (Ipv4Address addr, + virtual uint32_t GetInterfaceByAddress (Ipv4Address addr, Ipv4Mask mask = Ipv4Mask("255.255.255.255")); }; diff --git a/src/routing/global-routing/global-route-manager-impl.cc b/src/routing/global-routing/global-route-manager-impl.cc index 7b5f8fce8..2735d5ecf 100644 --- a/src/routing/global-routing/global-route-manager-impl.cc +++ b/src/routing/global-routing/global-route-manager-impl.cc @@ -1352,7 +1352,7 @@ GlobalRouteManagerImpl::SPFIntraAddStub (GlobalRoutingLinkRecord *l, SPFVertex* // // Return the interface index corresponding to a given IP address -// This is a wrapper around GetIfIndexByIpv4Address(), but we first +// This is a wrapper around GetInterfaceByIpv4Address(), but we first // have to find the right node pointer to pass to that function. // uint32_t @@ -1406,7 +1406,7 @@ GlobalRouteManagerImpl::FindOutgoingInterfaceId (Ipv4Address a, Ipv4Mask amask) // we're looking for. If we find one, return the corresponding interface // index. // - return (ipv4->GetIfIndexByAddress (a, amask) ); + return (ipv4->GetInterfaceByAddress (a, amask) ); } } // diff --git a/src/routing/global-routing/global-router-interface.cc b/src/routing/global-routing/global-router-interface.cc index 6c22dbadf..7b81dd735 100644 --- a/src/routing/global-routing/global-router-interface.cc +++ b/src/routing/global-routing/global-router-interface.cc @@ -594,8 +594,8 @@ GlobalRouter::DiscoverLSAs (void) // if (NetDeviceIsBridged (ndLocal)) { - uint32_t ifIndexBridge; - bool rc = FindIfIndexForDevice(node, ndLocal, ifIndexBridge); + uint32_t interfaceBridge; + bool rc = FindInterfaceForDevice(node, ndLocal, interfaceBridge); NS_ABORT_MSG_IF (rc, "GlobalRouter::DiscoverLSAs(): Bridge ports must not have an IPv4 interface index"); } @@ -697,17 +697,17 @@ GlobalRouter::ProcessSingleBroadcastLink (Ptr nd, GlobalRoutingLSA *p // Ptr node = nd->GetNode (); - uint32_t ifIndexLocal; - bool rc = FindIfIndexForDevice(node, nd, ifIndexLocal); + uint32_t interfaceLocal; + bool rc = FindInterfaceForDevice(node, nd, interfaceLocal); NS_ABORT_MSG_IF (rc == false, "GlobalRouter::ProcessSingleBroadcastLink(): No interface index associated with device"); Ptr ipv4Local = node->GetObject (); NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::ProcessSingleBroadcastLink (): GetObject for interface failed"); - Ipv4Address addrLocal = ipv4Local->GetAddress(ifIndexLocal); - Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(ifIndexLocal); + Ipv4Address addrLocal = ipv4Local->GetAddress(interfaceLocal); + Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(interfaceLocal); NS_LOG_LOGIC ("Working with local address " << addrLocal); - uint16_t metricLocal = ipv4Local->GetMetric (ifIndexLocal); + uint16_t metricLocal = ipv4Local->GetMetric (interfaceLocal); // // Check to see if the net device is connected to a channel/network that has @@ -813,17 +813,17 @@ GlobalRouter::ProcessBridgedBroadcastLink (Ptr nd, GlobalRoutingLSA * // Ptr node = nd->GetNode (); - uint32_t ifIndexLocal; - bool rc = FindIfIndexForDevice(node, nd, ifIndexLocal); + uint32_t interfaceLocal; + bool rc = FindInterfaceForDevice(node, nd, interfaceLocal); NS_ABORT_MSG_IF (rc == false, "GlobalRouter::ProcessBridgedBroadcastLink(): No interface index associated with device"); Ptr ipv4Local = node->GetObject (); NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::ProcessBridgedBroadcastLink (): GetObject for interface failed"); - Ipv4Address addrLocal = ipv4Local->GetAddress(ifIndexLocal); - Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(ifIndexLocal); + Ipv4Address addrLocal = ipv4Local->GetAddress(interfaceLocal); + Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(interfaceLocal); NS_LOG_LOGIC ("Working with local address " << addrLocal); - uint16_t metricLocal = ipv4Local->GetMetric (ifIndexLocal); + uint16_t metricLocal = ipv4Local->GetMetric (interfaceLocal); // // We need to handle a bridge on the router. This means that we have been @@ -955,17 +955,17 @@ GlobalRouter::ProcessPointToPointLink (Ptr ndLocal, GlobalRoutingLSA // Ptr nodeLocal = ndLocal->GetNode (); - uint32_t ifIndexLocal; - bool rc = FindIfIndexForDevice(nodeLocal, ndLocal, ifIndexLocal); + uint32_t interfaceLocal; + bool rc = FindInterfaceForDevice(nodeLocal, ndLocal, interfaceLocal); NS_ABORT_MSG_IF (rc == false, "GlobalRouter::ProcessPointToPointLink (): No interface index associated with device"); Ptr ipv4Local = nodeLocal->GetObject (); NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::ProcessPointToPointLink (): GetObject for interface failed"); - Ipv4Address addrLocal = ipv4Local->GetAddress(ifIndexLocal); - Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(ifIndexLocal); + Ipv4Address addrLocal = ipv4Local->GetAddress(interfaceLocal); + Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(interfaceLocal); NS_LOG_LOGIC ("Working with local address " << addrLocal); - uint16_t metricLocal = ipv4Local->GetMetric (ifIndexLocal); + uint16_t metricLocal = ipv4Local->GetMetric (interfaceLocal); // // Now, we're going to walk over to the remote net device on the other end of @@ -1010,16 +1010,16 @@ GlobalRouter::ProcessPointToPointLink (Ptr ndLocal, GlobalRoutingLSA // 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. // - uint32_t ifIndexRemote; - rc = FindIfIndexForDevice(nodeRemote, ndRemote, ifIndexRemote); + uint32_t interfaceRemote; + rc = FindInterfaceForDevice(nodeRemote, ndRemote, interfaceRemote); NS_ABORT_MSG_IF (rc == false, "GlobalRouter::ProcessPointToPointLinks(): No interface index associated with remote device"); // // Now that we have the Ipv4 interface, we can get the (remote) address and // mask we need. // - Ipv4Address addrRemote = ipv4Remote->GetAddress(ifIndexRemote); - Ipv4Mask maskRemote = ipv4Remote->GetNetworkMask(ifIndexRemote); + Ipv4Address addrRemote = ipv4Remote->GetAddress(interfaceRemote); + Ipv4Mask maskRemote = ipv4Remote->GetNetworkMask(interfaceRemote); NS_LOG_LOGIC ("Working with remote address " << addrRemote); // @@ -1028,9 +1028,9 @@ GlobalRouter::ProcessPointToPointLink (Ptr ndLocal, GlobalRoutingLSA // the second is a stub network record with the network number. // GlobalRoutingLinkRecord *plr; - if (ipv4Remote->IsUp (ifIndexRemote)) + if (ipv4Remote->IsUp (interfaceRemote)) { - NS_LOG_LOGIC ("Remote side interface " << ifIndexRemote << " is up-- add a type 1 link"); + NS_LOG_LOGIC ("Remote side interface " << interfaceRemote << " is up-- add a type 1 link"); plr = new GlobalRoutingLinkRecord; NS_ABORT_MSG_IF (plr == 0, "GlobalRouter::ProcessPointToPointLink(): Can't alloc link record"); @@ -1069,15 +1069,15 @@ GlobalRouter::BuildNetworkLSAs (NetDeviceContainer c) Ptr ndLocal = c.Get (i); Ptr node = ndLocal->GetNode (); - uint32_t ifIndexLocal; - bool rc = FindIfIndexForDevice(node, ndLocal, ifIndexLocal); + uint32_t interfaceLocal; + bool rc = FindInterfaceForDevice(node, ndLocal, interfaceLocal); NS_ABORT_MSG_IF (rc == false, "GlobalRouter::BuildNetworkLSAs (): No interface index associated with device"); Ptr ipv4Local = node->GetObject (); NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::ProcessPointToPointLink (): GetObject for interface failed"); - Ipv4Address addrLocal = ipv4Local->GetAddress(ifIndexLocal); - Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(ifIndexLocal); + Ipv4Address addrLocal = ipv4Local->GetAddress(interfaceLocal); + Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(interfaceLocal); GlobalRoutingLSA *pLSA = new GlobalRoutingLSA; NS_ABORT_MSG_IF (pLSA == 0, "GlobalRouter::BuildNetworkLSAs(): Can't alloc link record"); @@ -1117,18 +1117,18 @@ GlobalRouter::BuildNetworkLSAs (NetDeviceContainer c) // 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)) + uint32_t tempInterface; + if (FindInterfaceForDevice (tempNode, tempNd, tempInterface)) { Ptr tempIpv4 = tempNode->GetObject (); NS_ASSERT (tempIpv4); - if (!tempIpv4->IsUp (tempIfIndex)) + if (!tempIpv4->IsUp (tempInterface)) { - NS_LOG_LOGIC ("Remote side interface " << tempIfIndex << " not up"); + NS_LOG_LOGIC ("Remote side interface " << tempInterface << " not up"); } else { - Ipv4Address tempAddr = tempIpv4->GetAddress(tempIfIndex); + Ipv4Address tempAddr = tempIpv4->GetAddress(tempInterface); pLSA->AddAttachedRouter (tempAddr); } } @@ -1197,16 +1197,16 @@ GlobalRouter::FindDesignatedRouterForLink (Ptr ndLocal, bool allowRec Ptr ipv4 = nodeOther->GetObject (); if (rtr && ipv4) { - uint32_t ifIndexOther; - if (FindIfIndexForDevice(nodeOther, bnd, ifIndexOther)) + uint32_t interfaceOther; + if (FindInterfaceForDevice(nodeOther, bnd, interfaceOther)) { NS_LOG_LOGIC ("Found router on bridge net device " << bnd); - if (!ipv4->IsUp (ifIndexOther)) + if (!ipv4->IsUp (interfaceOther)) { - NS_LOG_LOGIC ("Remote side interface " << ifIndexOther << " not up"); + NS_LOG_LOGIC ("Remote side interface " << interfaceOther << " not up"); continue; } - Ipv4Address addrOther = ipv4->GetAddress (ifIndexOther); + Ipv4Address addrOther = ipv4->GetAddress (interfaceOther); desigRtr = addrOther < desigRtr ? addrOther : desigRtr; NS_LOG_LOGIC ("designated router now " << desigRtr); } @@ -1246,16 +1246,16 @@ GlobalRouter::FindDesignatedRouterForLink (Ptr ndLocal, bool allowRec Ptr ipv4 = nodeOther->GetObject (); if (rtr && ipv4) { - uint32_t ifIndexOther; - if (FindIfIndexForDevice(nodeOther, ndOther, ifIndexOther)) + uint32_t interfaceOther; + if (FindInterfaceForDevice(nodeOther, ndOther, interfaceOther)) { - if (!ipv4->IsUp (ifIndexOther)) + if (!ipv4->IsUp (interfaceOther)) { - NS_LOG_LOGIC ("Remote side interface " << ifIndexOther << " not up"); + NS_LOG_LOGIC ("Remote side interface " << interfaceOther << " not up"); continue; } NS_LOG_LOGIC ("Found router on net device " << ndOther); - Ipv4Address addrOther = ipv4->GetAddress (ifIndexOther); + Ipv4Address addrOther = ipv4->GetAddress (interfaceOther); desigRtr = addrOther < desigRtr ? addrOther : desigRtr; NS_LOG_LOGIC ("designated router now " << desigRtr); } @@ -1441,7 +1441,7 @@ GlobalRouter::GetAdjacent (Ptr nd, Ptr ch) const // is bridged, there will not be an interface associated directly with the device. // bool -GlobalRouter::FindIfIndexForDevice (Ptr node, Ptr nd, uint32_t &index) const +GlobalRouter::FindInterfaceForDevice (Ptr node, Ptr nd, uint32_t &index) const { NS_LOG_FUNCTION_NOARGS (); NS_LOG_LOGIC("For node " << node->GetId () << " for net device " << nd ); diff --git a/src/routing/global-routing/global-router-interface.h b/src/routing/global-routing/global-router-interface.h index 80116172a..6c5895296 100644 --- a/src/routing/global-routing/global-router-interface.h +++ b/src/routing/global-routing/global-router-interface.h @@ -644,7 +644,7 @@ private: void ClearLSAs (void); Ptr GetAdjacent(Ptr nd, Ptr ch) const; - bool FindIfIndexForDevice(Ptr node, Ptr nd, uint32_t &index) const; + bool FindInterfaceForDevice(Ptr node, Ptr nd, uint32_t &index) const; Ipv4Address FindDesignatedRouterForLink (Ptr ndLocal, bool allowRecursion) const; bool AnotherRouterOnLink (Ptr nd, bool allowRecursion) const; void ProcessBroadcastLink (Ptr nd, GlobalRoutingLSA *pLSA, NetDeviceContainer &c); diff --git a/src/routing/olsr/olsr-routing-table.cc b/src/routing/olsr/olsr-routing-table.cc index 296a69745..d3d63e226 100644 --- a/src/routing/olsr/olsr-routing-table.cc +++ b/src/routing/olsr/olsr-routing-table.cc @@ -105,7 +105,7 @@ RoutingTable::FindSendEntry (RoutingTableEntry const &entry, bool -RoutingTable::RequestRoute (uint32_t ifIndex, +RoutingTable::RequestRoute (uint32_t interface, const Ipv4Header &ipHeader, Ptr packet, RouteReplyCallback routeReply) @@ -148,8 +148,8 @@ RoutingTable::RequestRoute (uint32_t ifIndex, } bool -RoutingTable::RequestIfIndex (Ipv4Address destination, - uint32_t& ifIndex) +RoutingTable::RequestInterface (Ipv4Address destination, + uint32_t& interface) { RoutingTableEntry entry1, entry2; if (Lookup (destination, entry1)) @@ -157,7 +157,7 @@ RoutingTable::RequestIfIndex (Ipv4Address destination, bool foundSendEntry = FindSendEntry (entry1, entry2); if (!foundSendEntry) NS_FATAL_ERROR ("FindSendEntry failure"); - ifIndex = entry2.interface; + interface = entry2.interface; return true; } else diff --git a/src/routing/olsr/olsr-routing-table.h b/src/routing/olsr/olsr-routing-table.h index bbd20a2bc..69fe45d94 100644 --- a/src/routing/olsr/olsr-routing-table.h +++ b/src/routing/olsr/olsr-routing-table.h @@ -98,12 +98,12 @@ public: RoutingTableEntry &outEntry) const; // From Ipv4RoutingProtocol - virtual bool RequestRoute (uint32_t ifIndex, + virtual bool RequestRoute (uint32_t interface, const Ipv4Header &ipHeader, Ptr packet, RouteReplyCallback routeReply); - virtual bool RequestIfIndex (Ipv4Address destination, - uint32_t& ifIndex); + virtual bool RequestInterface (Ipv4Address destination, + uint32_t& interface); }; From a1f5b19c5aad4cc2256058018e0e67bba3fa5932 Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Wed, 8 Apr 2009 16:07:34 -0700 Subject: [PATCH 03/22] implementation and plumbing of Ipv4InterfaceAddress class --- src/internet-stack/ipv4-impl.cc | 18 +++ src/internet-stack/ipv4-impl.h | 4 + src/internet-stack/ipv4-interface.cc | 59 ++++++++++ src/internet-stack/ipv4-interface.h | 28 +++++ src/internet-stack/ipv4-l3-protocol.cc | 24 ++++ src/internet-stack/ipv4-l3-protocol.h | 4 + src/node/ipv4-interface-address.cc | 156 +++++++++++++++++++++++++ src/node/ipv4-interface-address.h | 84 +++++++++++++ src/node/ipv4.h | 21 ++++ src/node/wscript | 2 + 10 files changed, 400 insertions(+) create mode 100644 src/node/ipv4-interface-address.cc create mode 100644 src/node/ipv4-interface-address.h diff --git a/src/internet-stack/ipv4-impl.cc b/src/internet-stack/ipv4-impl.cc index fb3e0a48b..0959dd3d2 100644 --- a/src/internet-stack/ipv4-impl.cc +++ b/src/internet-stack/ipv4-impl.cc @@ -189,6 +189,24 @@ Ipv4Impl::LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group) m_ipv4->LeaveMulticastGroup(origin, group); } +uint32_t +Ipv4Impl::AddAddress (uint32_t i, Ipv4InterfaceAddress address) +{ + return m_ipv4->AddAddress (i, address); +} + +Ipv4InterfaceAddress +Ipv4Impl::GetAddress (uint32_t interfaceIndex, uint32_t addressIndex) const +{ + return m_ipv4->GetAddress (interfaceIndex, addressIndex); +} + +uint32_t +Ipv4Impl::GetNAddresses (uint32_t interface) const +{ + return m_ipv4->GetNAddresses (interface); +} + void Ipv4Impl::SetAddress (uint32_t i, Ipv4Address address) { diff --git a/src/internet-stack/ipv4-impl.h b/src/internet-stack/ipv4-impl.h index ed5f2e7f6..25b3a6d08 100644 --- a/src/internet-stack/ipv4-impl.h +++ b/src/internet-stack/ipv4-impl.h @@ -87,6 +87,10 @@ public: virtual void JoinMulticastGroup (Ipv4Address origin, Ipv4Address group); virtual void LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group); + uint32_t AddAddress (uint32_t i, Ipv4InterfaceAddress address); + Ipv4InterfaceAddress GetAddress (uint32_t interfaceIndex, uint32_t addressIndex) const; + uint32_t GetNAddresses (uint32_t interface) const; + virtual void SetAddress (uint32_t i, Ipv4Address address); virtual void SetNetworkMask (uint32_t i, Ipv4Mask mask); virtual Ipv4Mask GetNetworkMask (uint32_t t) const; diff --git a/src/internet-stack/ipv4-interface.cc b/src/internet-stack/ipv4-interface.cc index dbbf92beb..e735ae0fe 100644 --- a/src/internet-stack/ipv4-interface.cc +++ b/src/internet-stack/ipv4-interface.cc @@ -170,5 +170,64 @@ Ipv4Interface::Send(Ptr p, Ipv4Address dest) } } +uint32_t +Ipv4Interface::GetNAddresses (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + return m_ifaddrs.size(); +} + +uint32_t +Ipv4Interface::AddAddress (Ipv4InterfaceAddress addr) +{ + NS_LOG_FUNCTION_NOARGS (); + uint32_t index = m_ifaddrs.size (); + m_ifaddrs.push_back (addr); + return index; +} + +Ipv4InterfaceAddress +Ipv4Interface::GetAddress (uint32_t index) const +{ + NS_LOG_FUNCTION_NOARGS (); + if (index < m_ifaddrs.size ()) + { + uint32_t tmp = 0; + for (Ipv4InterfaceAddressListCI i = m_ifaddrs.begin (); i!= m_ifaddrs.end (); i++) + { + if (tmp == index) + { + return *i; + } + ++tmp; + } + } + NS_ASSERT (false); // Assert if not found + Ipv4InterfaceAddress addr; + return (addr); // quiet compiler +} + +void +Ipv4Interface::RemoveAddress (uint32_t index) +{ + NS_LOG_FUNCTION_NOARGS (); + if (index >= m_ifaddrs.size ()) + { + NS_ASSERT_MSG (false, "Bug in Ipv4Interface::RemoveAddress"); + } + Ipv4InterfaceAddressListI i = m_ifaddrs.begin (); + uint32_t tmp = 0; + while (i != m_ifaddrs.end ()) + { + if (tmp == index) + { + m_ifaddrs.erase (i); + return; + } + ++tmp; + } + NS_ASSERT_MSG (false, "Address " << index << " not found"); +} + }; // namespace ns3 diff --git a/src/internet-stack/ipv4-interface.h b/src/internet-stack/ipv4-interface.h index 74007b09e..2cf27ed8c 100644 --- a/src/internet-stack/ipv4-interface.h +++ b/src/internet-stack/ipv4-interface.h @@ -24,6 +24,7 @@ #include #include "ns3/ipv4-address.h" +#include "ns3/ipv4-interface-address.h" #include "ns3/ptr.h" #include "ns3/object.h" @@ -142,6 +143,28 @@ public: */ void Send(Ptr p, Ipv4Address dest); + /** + * \param address The Ipv4InterfaceAddress to add to the interface + * \returns The index of the newly-added Ipv4InterfaceAddress + */ + uint32_t AddAddress (Ipv4InterfaceAddress address); + + /** + * \param i Index of Ipv4InterfaceAddress to return + * \returns The Ipv4InterfaceAddress address whose index is i + */ + Ipv4InterfaceAddress GetAddress (uint32_t index) const; + + /** + * \returns the number of Ipv4InterfaceAddresss stored on this interface + */ + uint32_t GetNAddresses (void) const; + + /** + * \param i index of Ipv4InterfaceAddress to remove from address list. + */ + void RemoveAddress (uint32_t index); + protected: virtual void DoDispose (void); private: @@ -150,6 +173,11 @@ private: Ipv4Address m_address; Ipv4Mask m_netmask; uint16_t m_metric; + + typedef std::list Ipv4InterfaceAddressList; + typedef std::list::const_iterator Ipv4InterfaceAddressListCI; + typedef std::list::iterator Ipv4InterfaceAddressListI; + Ipv4InterfaceAddressList m_ifaddrs; }; }; // namespace ns3 diff --git a/src/internet-stack/ipv4-l3-protocol.cc b/src/internet-stack/ipv4-l3-protocol.cc index 429efece9..46a44c3e1 100644 --- a/src/internet-stack/ipv4-l3-protocol.cc +++ b/src/internet-stack/ipv4-l3-protocol.cc @@ -923,6 +923,30 @@ Ipv4L3Protocol::LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group) } } +uint32_t +Ipv4L3Protocol::AddAddress (uint32_t i, Ipv4InterfaceAddress address) +{ + NS_LOG_FUNCTION (this << i << address); + Ptr interface = GetInterface (i); + return interface->AddAddress (address); +} + +Ipv4InterfaceAddress +Ipv4L3Protocol::GetAddress (uint32_t interfaceIndex, uint32_t addressIndex) const +{ + NS_LOG_FUNCTION (this << interfaceIndex << addressIndex); + Ptr interface = GetInterface (interfaceIndex); + return interface->GetAddress (addressIndex); +} + +uint32_t +Ipv4L3Protocol::GetNAddresses (uint32_t interface) const +{ + NS_LOG_FUNCTION (this << interface); + Ptr iface = GetInterface (interface); + return iface->GetNAddresses (); +} + void Ipv4L3Protocol::SetAddress (uint32_t i, Ipv4Address address) { diff --git a/src/internet-stack/ipv4-l3-protocol.h b/src/internet-stack/ipv4-l3-protocol.h index 00cfd8c91..d3bac94de 100644 --- a/src/internet-stack/ipv4-l3-protocol.h +++ b/src/internet-stack/ipv4-l3-protocol.h @@ -187,6 +187,10 @@ public: void JoinMulticastGroup (Ipv4Address origin, Ipv4Address group); void LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group); + uint32_t AddAddress (uint32_t i, Ipv4InterfaceAddress address); + Ipv4InterfaceAddress GetAddress (uint32_t interfaceIndex, uint32_t addressIndex) const; + uint32_t GetNAddresses (uint32_t interface) const; + void SetAddress (uint32_t i, Ipv4Address address); void SetNetworkMask (uint32_t i, Ipv4Mask mask); Ipv4Mask GetNetworkMask (uint32_t t) const; diff --git a/src/node/ipv4-interface-address.cc b/src/node/ipv4-interface-address.cc new file mode 100644 index 000000000..4eb302386 --- /dev/null +++ b/src/node/ipv4-interface-address.cc @@ -0,0 +1,156 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2005 INRIA + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Mathieu Lacage + */ + +#include "ns3/log.h" +#include "ns3/assert.h" +#include "ipv4-interface-address.h" + +NS_LOG_COMPONENT_DEFINE("Ipv4InterfaceAddress"); + +namespace ns3 { + +Ipv4InterfaceAddress::Ipv4InterfaceAddress () + : m_scope (GLOBAL), + m_secondary (false) +{ + NS_LOG_FUNCTION (this); +} + +Ipv4InterfaceAddress::Ipv4InterfaceAddress (Ipv4Address local, Ipv4Mask mask) + : m_scope (GLOBAL), + m_secondary (false) +{ + NS_LOG_FUNCTION (this); + m_local = local; + m_mask = mask; + m_broadcast = Ipv4Address (local.Get () | (~mask.Get ())); +} + +Ipv4InterfaceAddress::Ipv4InterfaceAddress (const Ipv4InterfaceAddress &o) + : m_local (o.m_local), + m_peer (o.m_peer), + m_mask (o.m_mask), + m_broadcast (o.m_broadcast), + m_scope (o.m_scope), + m_secondary (o.m_secondary) +{ + NS_LOG_FUNCTION (this); +} + +void +Ipv4InterfaceAddress::SetLocal (Ipv4Address local) +{ + NS_LOG_FUNCTION_NOARGS (); + m_local = local; +} + +Ipv4Address +Ipv4InterfaceAddress::GetLocal (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + return m_local; +} + +void +Ipv4InterfaceAddress::SetPeer (Ipv4Address peer) +{ + NS_LOG_FUNCTION_NOARGS (); + m_peer = peer; +} + +Ipv4Address +Ipv4InterfaceAddress::GetPeer (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + return m_peer; +} + +void +Ipv4InterfaceAddress::SetMask (Ipv4Mask mask) +{ + NS_LOG_FUNCTION_NOARGS (); + m_mask = mask; +} + +Ipv4Mask +Ipv4InterfaceAddress::GetMask (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + return m_mask; +} + +void +Ipv4InterfaceAddress::SetBroadcast (Ipv4Address broadcast) +{ + NS_LOG_FUNCTION_NOARGS (); + m_broadcast = broadcast; +} + +Ipv4Address +Ipv4InterfaceAddress::GetBroadcast (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + return m_broadcast; +} + +void +Ipv4InterfaceAddress::SetScope (Ipv4InterfaceAddress::InterfaceAddressScope_e scope) +{ + NS_LOG_FUNCTION_NOARGS (); + m_scope = scope; +} + +Ipv4InterfaceAddress::InterfaceAddressScope_e +Ipv4InterfaceAddress::GetScope (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + return m_scope; +} + +bool +Ipv4InterfaceAddress::IsSecondary (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + return m_secondary; +} + +void +Ipv4InterfaceAddress::SetSecondary (void) +{ + NS_LOG_FUNCTION_NOARGS (); + m_secondary = true; +} + +void +Ipv4InterfaceAddress::SetPrimary (void) +{ + NS_LOG_FUNCTION_NOARGS (); + m_secondary = false; +} + +std::ostream& operator<< (std::ostream& os, const Ipv4InterfaceAddress &addr) +{ + os << "m_local=" << addr.GetLocal () << "; m_peer=" << addr.GetPeer () << "; m_mask=" << + addr.GetMask () << "; m_broadcast=" << addr.GetBroadcast () << "; m_scope=" << addr.GetScope() << + "; m_secondary=" << addr.IsSecondary (); + return os; +} + +} // namespace ns3 diff --git a/src/node/ipv4-interface-address.h b/src/node/ipv4-interface-address.h new file mode 100644 index 000000000..d8a4ff27b --- /dev/null +++ b/src/node/ipv4-interface-address.h @@ -0,0 +1,84 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2008 University of Washington + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef IPV4_INTERFACE_ADDRESS_H +#define IPV4_INTERFACE_ADDRESS_H + +#include +#include +#include "ipv4-address.h" + +namespace ns3 { + +/** + * \brief a class to store IPv4 address information on an interface + * + * Corresponds to Linux struct in_ifaddr. A list of these addresses + * is stored in Ipv4Interface. This class is modelled after how current + * Linux handles IP aliasing for IPv4. Notably, aliasing of IPv4 + * interfaces (e.g., "eth0:1") is not used, and instead an interface + * is assigned possibly multiple addresses, with each address being + * classified as being primary and secondary. See the iproute2 + * documentation for this distinction. + */ +class Ipv4InterfaceAddress +{ +public: + enum InterfaceAddressScope_e { + HOST, + LINK, + GLOBAL + }; + + Ipv4InterfaceAddress (); + // Configure m_local, m_mask, and m_broadcast from the below constructor + Ipv4InterfaceAddress (Ipv4Address local, Ipv4Mask mask); + Ipv4InterfaceAddress (const Ipv4InterfaceAddress &o); + + void SetLocal (Ipv4Address local); + Ipv4Address GetLocal (void) const; + void SetPeer (Ipv4Address peer); + Ipv4Address GetPeer (void) const; + void SetMask (Ipv4Mask mask); + Ipv4Mask GetMask (void) const; + void SetBroadcast (Ipv4Address broadcast); + Ipv4Address GetBroadcast (void) const; + + void SetScope (Ipv4InterfaceAddress::InterfaceAddressScope_e scope); + Ipv4InterfaceAddress::InterfaceAddressScope_e GetScope (void) const; + + bool IsSecondary (void) const; + void SetSecondary (void); + void SetPrimary (void); + +private: + Ipv4Address m_local; // Interface address + Ipv4Address m_peer; // Peer destination address (in Linux: m_address) + Ipv4Mask m_mask; // Network mask + Ipv4Address m_broadcast; // Broadcast address + + InterfaceAddressScope_e m_scope; + bool m_secondary; // For use in multihoming +}; + +std::ostream& operator<< (std::ostream& os, const Ipv4InterfaceAddress &addr); + +} // namespace ns3 + +#endif /* IPV4_ADDRESS_H */ diff --git a/src/node/ipv4.h b/src/node/ipv4.h index 7febbdcc2..6929da076 100644 --- a/src/node/ipv4.h +++ b/src/node/ipv4.h @@ -22,6 +22,7 @@ #include #include "ns3/ipv4-address.h" +#include "ns3/ipv4-interface-address.h" #include "ns3/object.h" #include "ns3/callback.h" #include "ipv4-route.h" @@ -390,6 +391,26 @@ public: */ virtual void LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group) = 0; + /** + * \param interface Interface number of an Ipv4 interface + * \param address Ipv4InterfaceAddress address to associate with the underlying Ipv4 interface + * \returns The address index of the newly-added address + */ + virtual uint32_t AddAddress (uint32_t interface, Ipv4InterfaceAddress address) = 0; + + /** + * \param interface Interface number of an Ipv4 interface + * \returns the number of Ipv4InterfaceAddress entries for the interface. + */ + virtual uint32_t GetNAddresses (uint32_t interface) const = 0; + + /** + * \param interface Interface number of an Ipv4 interface + * \param addressIndex index of Ipv4InterfaceAddress + * \returns the Ipv4InterfaceAddress associated to the interface and addresIndex + */ + virtual Ipv4InterfaceAddress GetAddress (uint32_t interface, uint32_t addressIndex) const = 0; + /** * \param i index of ipv4 interface * \param address address to associate to the underlying ipv4 interface diff --git a/src/node/wscript b/src/node/wscript index cf318b0f2..8ed3c8c64 100644 --- a/src/node/wscript +++ b/src/node/wscript @@ -10,6 +10,7 @@ def build(bld): 'packet-socket-address.cc', 'node.cc', 'ipv4-address.cc', + 'ipv4-interface-address.cc', 'ipv4-address-generator.cc', 'ipv4-header.cc', 'net-device.cc', @@ -47,6 +48,7 @@ def build(bld): 'mac48-address.h', 'mac64-address.h', 'inet-socket-address.h', + 'ipv4-interface-address.h', 'packet-socket-address.h', 'node.h', 'ipv4-address.h', From 13140ee899ffcb86c2a0636cade791654b506be2 Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Wed, 8 Apr 2009 22:32:44 -0700 Subject: [PATCH 04/22] update documentation --- README.api | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/README.api b/README.api index c027791b6..77826a5ae 100644 --- a/README.api +++ b/README.api @@ -1,4 +1,4 @@ -1. Changeset: +1. Changeset: d99061f1167c Synopsis: -------- @@ -34,10 +34,69 @@ None. Changed private API (src/internet-node) -------- +(similar API changes to the IPv4 implementation classes instantiating +the above public API) + New private API or classes (src/internet-node) -------- None. -Changeset: + +======================================================================== + +2. Changeset: e493e80274bd (implementation added in parallel) + Changeset: TBD (cut over of client code, remove old code) + +Synopsis: +-------- - allow multiple IPv4 addresses to be assigned to an interface (bug 188) + +Changed public API: +-------- + +We now have a new class and methods to account for the possibility of having +multiple IP addresses on an interface: + ++ virtual uint32_t AddAddress (uint32_t interface, Ipv4InterfaceAddress address) = 0; ++ virtual Ipv4InterfaceAddress GetAddress (uint32_t interface, uint32_t addressIndex) const = 0; ++ virtual uint32_t GetNAddresses (uint32_t interface) const = 0; + +This convenience function was removed: +- virtual uint32_t GetIfIndexByAddress (Ipv4Address addr, +- Ipv4Mask mask = Ipv4Mask("255.255.255.255")); + +A few public methods were renamed because they were poorly named: +- virtual uint32_t FindInterfaceForAddr (Ipv4Address addr, ++ virtual int32_t GetInterfaceForAddress (Ipv4Address address, + Ipv4Mask mask) const = 0; +- virtual int32_t FindInterfaceForDevice(Ptr nd) const = 0; ++ virtual int32_t GetInterfaceForDevice (Ptr device) const = 0; + + +New public API or classes (src/node) +-------- + +class Ipv4InterfaceAddress: This is a new class to parallel Linux +struct in_ifaddr. It holds IP addressing information, including mask, +broadcast address, scope, whether primary or secondary, etc. + + +======================================================================== + +3. Changeset: TBD + +Synopsis: +-------- +- Remove class Ipv4Impl from src/internet-stack + +Changed public API: +-------- + +None + +Changed private API +--------- + +Remove class Ipv4Impl; class Ipv4L3Protocol now inherits from class Ipv4 +allow multiple IPv4 addresses to be assigned to an interface (bug 188) From 5c3fa90caca18c21ccc7cfb4166f9309e8565909 Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Sun, 12 Apr 2009 22:13:49 -0700 Subject: [PATCH 05/22] Implementation cut over to use Ipv4InterfaceAddress --- examples/global-routing-slash32.cc | 10 +- examples/mixed-wireless.cc | 2 +- examples/static-routing-slash32.cc | 10 +- src/devices/tap-bridge/tap-bridge.cc | 8 +- src/helper/ipv4-address-helper.cc | 4 +- src/helper/ipv4-interface-container.cc | 5 +- src/helper/ipv4-interface-container.h | 11 +- src/internet-stack/arp-ipv4-interface.cc | 7 +- src/internet-stack/arp-l3-protocol.cc | 21 +-- src/internet-stack/icmpv4-l4-protocol.cc | 3 +- src/internet-stack/ipv4-end-point-demux.cc | 5 +- src/internet-stack/ipv4-impl.cc | 38 +---- src/internet-stack/ipv4-impl.h | 4 - src/internet-stack/ipv4-interface.cc | 38 ----- src/internet-stack/ipv4-interface.h | 23 ---- src/internet-stack/ipv4-l3-protocol.cc | 130 ++++++++++-------- src/internet-stack/ipv4-l3-protocol.h | 5 +- src/internet-stack/ipv4-raw-socket-impl.cc | 2 +- src/internet-stack/nsc-tcp-l4-protocol.cc | 5 +- src/internet-stack/tcp-socket-impl.cc | 8 +- src/internet-stack/udp-socket-impl.cc | 24 ++-- src/node/ipv4.cc | 8 +- src/node/ipv4.h | 29 ---- .../global-routing/global-router-interface.cc | 58 ++++++-- src/routing/olsr/olsr-agent-impl.cc | 9 +- src/routing/olsr/olsr-routing-table.cc | 9 +- 26 files changed, 213 insertions(+), 263 deletions(-) diff --git a/examples/global-routing-slash32.cc b/examples/global-routing-slash32.cc index 06dfed1b8..e3f671613 100644 --- a/examples/global-routing-slash32.cc +++ b/examples/global-routing-slash32.cc @@ -87,13 +87,13 @@ main (int argc, char *argv[]) int32_t ifIndexA = ipv4A->AddInterface (deviceA); int32_t ifIndexC = ipv4C->AddInterface (deviceC); - ipv4A->SetAddress (ifIndexA, Ipv4Address ("172.16.1.1")); - ipv4A->SetNetworkMask (ifIndexA, Ipv4Mask ("255.255.255.255")); + Ipv4InterfaceAddress ifInAddrA = Ipv4InterfaceAddress (Ipv4Address ("172.16.1.1"), Ipv4Mask ("255.255.255.255")); + ipv4A->AddAddress (ifIndexA, ifInAddrA); ipv4A->SetMetric (ifIndexA, 1); ipv4A->SetUp (ifIndexA); - ipv4C->SetAddress (ifIndexC, Ipv4Address ("192.168.1.1")); - ipv4C->SetNetworkMask (ifIndexC, Ipv4Mask ("255.255.255.255")); + Ipv4InterfaceAddress ifInAddrC = Ipv4InterfaceAddress (Ipv4Address ("192.168.1.1"), Ipv4Mask ("255.255.255.255")); + ipv4C->AddAddress (ifIndexC, ifInAddrC); ipv4C->SetMetric (ifIndexC, 1); ipv4C->SetUp (ifIndexC); @@ -105,7 +105,7 @@ main (int argc, char *argv[]) // 210 bytes at a rate of 448 Kb/s uint16_t port = 9; // Discard port (RFC 863) OnOffHelper onoff ("ns3::UdpSocketFactory", - Address (InetSocketAddress (Ipv4Address("192.168.1.1"), port))); + Address (InetSocketAddress (ifInAddrC.GetLocal(), port))); onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1))); onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0))); onoff.SetAttribute ("DataRate", DataRateValue (DataRate (6000))); diff --git a/examples/mixed-wireless.cc b/examples/mixed-wireless.cc index 164fdc6d7..355dfa344 100644 --- a/examples/mixed-wireless.cc +++ b/examples/mixed-wireless.cc @@ -353,7 +353,7 @@ main (int argc, char *argv[]) uint32_t lastNodeIndex = backboneNodes + backboneNodes*(lanNodes - 1) + backboneNodes*(infraNodes - 1) - 1; Ptr appSink = NodeList::GetNode (lastNodeIndex); // Let's fetch the IP address of the last node, which is on Ipv4Interface 1 - Ipv4Address remoteAddr = appSink->GetObject ()->GetAddress(1); + Ipv4Address remoteAddr = appSink->GetObject ()->GetAddress(1, 0).GetLocal (); OnOffHelper onoff ("ns3::UdpSocketFactory", Address (InetSocketAddress (remoteAddr, port))); diff --git a/examples/static-routing-slash32.cc b/examples/static-routing-slash32.cc index e535a29f3..91329ae91 100644 --- a/examples/static-routing-slash32.cc +++ b/examples/static-routing-slash32.cc @@ -87,13 +87,13 @@ main (int argc, char *argv[]) int32_t ifIndexA = ipv4A->AddInterface (deviceA); int32_t ifIndexC = ipv4C->AddInterface (deviceC); - ipv4A->SetAddress (ifIndexA, Ipv4Address ("172.16.1.1")); - ipv4A->SetNetworkMask (ifIndexA, Ipv4Mask ("255.255.255.255")); + Ipv4InterfaceAddress ifInAddrA = Ipv4InterfaceAddress (Ipv4Address ("172.16.1.1"), Ipv4Mask ("255.255.255.255")); + ipv4A->AddAddress (ifIndexA, ifInAddrA); ipv4A->SetMetric (ifIndexA, 1); ipv4A->SetUp (ifIndexA); - ipv4C->SetAddress (ifIndexC, Ipv4Address ("192.168.1.1")); - ipv4C->SetNetworkMask (ifIndexC, Ipv4Mask ("255.255.255.255")); + Ipv4InterfaceAddress ifInAddrC = Ipv4InterfaceAddress (Ipv4Address ("192.168.1.1"), Ipv4Mask ("255.255.255.255")); + ipv4C->AddAddress (ifIndexC, ifInAddrC); ipv4C->SetMetric (ifIndexC, 1); ipv4C->SetUp (ifIndexC); @@ -107,7 +107,7 @@ main (int argc, char *argv[]) // 210 bytes at a rate of 448 Kb/s uint16_t port = 9; // Discard port (RFC 863) OnOffHelper onoff ("ns3::UdpSocketFactory", - Address (InetSocketAddress (Ipv4Address("192.168.1.1"), port))); + Address (InetSocketAddress (ifInAddrC.GetLocal (), port))); onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1))); onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0))); onoff.SetAttribute ("DataRate", DataRateValue (DataRate (6000))); diff --git a/src/devices/tap-bridge/tap-bridge.cc b/src/devices/tap-bridge/tap-bridge.cc index fa14796a9..f149dc385 100644 --- a/src/devices/tap-bridge/tap-bridge.cc +++ b/src/devices/tap-bridge/tap-bridge.cc @@ -343,12 +343,16 @@ TapBridge::CreateTap (void) Ptr n = nd->GetNode (); Ptr ipv4 = n->GetObject (); uint32_t index = ipv4->FindInterfaceForDevice (nd); - Ipv4Address ipv4Address = ipv4->GetAddress (index); + if (ipv4->GetNAddresses (index) > 1) + { + NS_LOG_WARN ("Underlying bridged NetDevice has multiple IP addresses; using first one."); + } + Ipv4Address ipv4Address = ipv4->GetAddress (index, 0).GetLocal (); // // The net mask is sitting right there next to the ipv4 address. // - Ipv4Mask ipv4Mask = ipv4->GetNetworkMask (index); + Ipv4Mask ipv4Mask = ipv4->GetAddress (index, 0).GetMask (); // // The MAC address should also already be assigned and waiting for us in diff --git a/src/helper/ipv4-address-helper.cc b/src/helper/ipv4-address-helper.cc index 65d72b7ed..d3c8b95b8 100644 --- a/src/helper/ipv4-address-helper.cc +++ b/src/helper/ipv4-address-helper.cc @@ -139,8 +139,8 @@ Ipv4AddressHelper::Assign (const NetDeviceContainer &c) NS_ASSERT_MSG (interface >= 0, "Ipv4AddressHelper::Allocate(): " "Interface index not found"); - ipv4->SetAddress (interface, NewAddress ()); - ipv4->SetNetworkMask (interface, m_mask); + Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (NewAddress (), m_mask); + ipv4->AddAddress (interface, ipv4Addr); ipv4->SetMetric (interface, 1); ipv4->SetUp (interface); retval.Add (ipv4, interface); diff --git a/src/helper/ipv4-interface-container.cc b/src/helper/ipv4-interface-container.cc index 6d2b5b011..1666e5ae3 100644 --- a/src/helper/ipv4-interface-container.cc +++ b/src/helper/ipv4-interface-container.cc @@ -23,12 +23,13 @@ Ipv4InterfaceContainer::GetN (void) const } Ipv4Address -Ipv4InterfaceContainer::GetAddress (uint32_t i) const +Ipv4InterfaceContainer::GetAddress (uint32_t i, uint32_t j) const { Ptr ipv4 = m_interfaces[i].first; uint32_t interface = m_interfaces[i].second; - return ipv4->GetAddress (interface); + return ipv4->GetAddress (interface, j).GetLocal (); } + void Ipv4InterfaceContainer::SetMetric (uint32_t i, uint16_t metric) { diff --git a/src/helper/ipv4-interface-container.h b/src/helper/ipv4-interface-container.h index ce728784e..143582f2e 100644 --- a/src/helper/ipv4-interface-container.h +++ b/src/helper/ipv4-interface-container.h @@ -30,7 +30,16 @@ public: */ uint32_t GetN (void) const; - Ipv4Address GetAddress (uint32_t i) const; + /** + * \returns the IPv4 address of the j'th address of the interface + * corresponding to index i. + * + * If the second parameter is omitted, the zeroth indexed address of + * the interface is returned. Unless IP aliaising is being used on + * the interface, the second parameter may typically be omitted. + */ + Ipv4Address GetAddress (uint32_t i, uint32_t j = 0) const; + void SetMetric (uint32_t i, uint16_t metric); void Add (Ptr ipv4, uint32_t interface); diff --git a/src/internet-stack/arp-ipv4-interface.cc b/src/internet-stack/arp-ipv4-interface.cc index 4eaeb177e..2c5a0c87a 100644 --- a/src/internet-stack/arp-ipv4-interface.cc +++ b/src/internet-stack/arp-ipv4-interface.cc @@ -106,7 +106,8 @@ ArpIpv4Interface::SendTo (Ptr p, Ipv4Address dest) NS_LOG_FUNCTION (this << p << dest); NS_ASSERT (GetDevice () != 0); - if (dest == GetAddress ()) + // XXX multi-address case + if (dest == GetAddress (0).GetLocal ()) { Ptr ipv4 = m_node->GetObject (); @@ -124,9 +125,9 @@ ArpIpv4Interface::SendTo (Ptr p, Ipv4Address dest) m_node->GetObject (); Address hardwareDestination; bool found; - + // XXX multi-address case if (dest.IsBroadcast () || - dest.IsSubnetDirectedBroadcast (GetNetworkMask ()) ) + dest.IsSubnetDirectedBroadcast (GetAddress (0).GetMask ()) ) { NS_LOG_LOGIC ("IsBroadcast"); hardwareDestination = GetDevice ()->GetBroadcast (); diff --git a/src/internet-stack/arp-l3-protocol.cc b/src/internet-stack/arp-l3-protocol.cc index 0c867dbec..9f8e7787c 100644 --- a/src/internet-stack/arp-l3-protocol.cc +++ b/src/internet-stack/arp-l3-protocol.cc @@ -142,28 +142,29 @@ ArpL3Protocol::Receive(Ptr device, Ptr p, uint16_t prot NS_LOG_LOGIC ("ARP: Cannot remove ARP header"); return; } - + // XXX multi-address case NS_LOG_LOGIC ("ARP: received "<< (arp.IsRequest ()? "request" : "reply") << " node="<GetId ()<<", got request from " << arp.GetSourceIpv4Address () << " for address " << arp.GetDestinationIpv4Address () << "; we have address " << - cache->GetInterface ()->GetAddress ()); + cache->GetInterface ()->GetAddress (0).GetLocal ()); /** * Note: we do not update the ARP cache when we receive an ARP request * from an unknown node. See bug #107 */ - + // XXX multi-address case if (arp.IsRequest () && - arp.GetDestinationIpv4Address () == cache->GetInterface ()->GetAddress ()) + arp.GetDestinationIpv4Address () == cache->GetInterface ()->GetAddress (0).GetLocal ()) { NS_LOG_LOGIC ("node="<GetId () <<", got request from " << arp.GetSourceIpv4Address () << " -- send reply"); SendArpReply (cache, arp.GetSourceIpv4Address (), arp.GetSourceHardwareAddress ()); } + // XXX multi-address case else if (arp.IsReply () && - arp.GetDestinationIpv4Address ().IsEqual (cache->GetInterface ()->GetAddress ()) && + arp.GetDestinationIpv4Address ().IsEqual (cache->GetInterface ()->GetAddress (0).GetLocal ()) && arp.GetDestinationHardwareAddress () == device->GetAddress ()) { Ipv4Address from = arp.GetSourceIpv4Address (); @@ -284,11 +285,12 @@ ArpL3Protocol::SendArpRequest (Ptr cache, Ipv4Address to) ArpHeader arp; NS_LOG_LOGIC ("ARP: sending request from node "<GetId ()<< " || src: " << cache->GetDevice ()->GetAddress () << - " / " << cache->GetInterface ()->GetAddress () << + " / " << cache->GetInterface ()->GetAddress (0).GetLocal () << " || dst: " << cache->GetDevice ()->GetBroadcast () << " / " << to); + // XXX multi-address case arp.SetRequest (cache->GetDevice ()->GetAddress (), - cache->GetInterface ()->GetAddress (), + cache->GetInterface ()->GetAddress (0).GetLocal (), cache->GetDevice ()->GetBroadcast (), to); Ptr packet = Create (); @@ -303,10 +305,11 @@ ArpL3Protocol::SendArpReply (Ptr cache, Ipv4Address toIp, Addres ArpHeader arp; NS_LOG_LOGIC ("ARP: sending reply from node "<GetId ()<< "|| src: " << cache->GetDevice ()->GetAddress () << - " / " << cache->GetInterface ()->GetAddress () << + " / " << cache->GetInterface ()->GetAddress (0).GetLocal () << " || dst: " << toMac << " / " << toIp); + // XXX multi-address case arp.SetReply (cache->GetDevice ()->GetAddress (), - cache->GetInterface ()->GetAddress (), + cache->GetInterface ()->GetAddress (0).GetLocal (), toMac, toIp); Ptr packet = Create (); packet->AddHeader (arp); diff --git a/src/internet-stack/icmpv4-l4-protocol.cc b/src/internet-stack/icmpv4-l4-protocol.cc index 8b22fe813..8ee8cbc57 100644 --- a/src/internet-stack/icmpv4-l4-protocol.cc +++ b/src/internet-stack/icmpv4-l4-protocol.cc @@ -68,7 +68,8 @@ Icmpv4L4Protocol::SendMessage (Ptr packet, Ipv4Address dest, uint8_t typ NS_LOG_WARN ("drop icmp message"); return; } - Ipv4Address source = ipv4->GetAddress (i); + // XXX handle multi-address case + Ipv4Address source = ipv4->GetAddress (i, 0).GetLocal (); SendMessage (packet, source, dest, type, code); } diff --git a/src/internet-stack/ipv4-end-point-demux.cc b/src/internet-stack/ipv4-end-point-demux.cc index 2c2ab838e..ad98ede4b 100644 --- a/src/internet-stack/ipv4-end-point-demux.cc +++ b/src/internet-stack/ipv4-end-point-demux.cc @@ -219,10 +219,11 @@ Ipv4EndPointDemux::Lookup (Ipv4Address daddr, uint16_t dport, << " does not match packet dport " << dport); continue; } + // XXX handle multi-address case bool isBroadcast = (daddr.IsBroadcast () || daddr.IsSubnetDirectedBroadcast ( - incomingInterface->GetNetworkMask ())); - Ipv4Address incomingInterfaceAddr = incomingInterface->GetAddress (); + incomingInterface->GetAddress (0).GetMask ())); + Ipv4Address incomingInterfaceAddr = incomingInterface->GetAddress (0).GetLocal (); NS_LOG_DEBUG ("dest addr " << daddr << " broadcast? " << isBroadcast); bool localAddressMatchesWildCard = endP->GetLocalAddress() == Ipv4Address::GetAny(); diff --git a/src/internet-stack/ipv4-impl.cc b/src/internet-stack/ipv4-impl.cc index 0959dd3d2..e23b87cdd 100644 --- a/src/internet-stack/ipv4-impl.cc +++ b/src/internet-stack/ipv4-impl.cc @@ -207,28 +207,6 @@ Ipv4Impl::GetNAddresses (uint32_t interface) const return m_ipv4->GetNAddresses (interface); } -void -Ipv4Impl::SetAddress (uint32_t i, Ipv4Address address) -{ - m_ipv4->SetAddress (i, address); -} -void -Ipv4Impl::SetNetworkMask (uint32_t i, Ipv4Mask mask) -{ - m_ipv4->SetNetworkMask (i, mask); -} -Ipv4Mask -Ipv4Impl::GetNetworkMask (uint32_t i) const -{ - return m_ipv4->GetNetworkMask (i); -} - -Ipv4Address -Ipv4Impl::GetAddress (uint32_t i) const -{ - return m_ipv4->GetAddress (i); -} - void Ipv4Impl::SetMetric (uint32_t i, uint16_t metric) { @@ -250,21 +228,7 @@ Ipv4Impl::GetInterfaceForDestination (Ipv4Address dest, uint32_t &interface) con Ipv4Address Ipv4Impl::GetSourceAddress (Ipv4Address destination) const { - uint32_t interface = 0xffffffff; - - bool result = m_ipv4->GetInterfaceForDestination (destination, interface); - - if (result) - { - return m_ipv4->GetAddress (interface); - } - else - { -// -// If we can't find any address, just leave it 0.0.0.0 -// - return Ipv4Address::GetAny (); - } + return m_ipv4->GetSourceAddress (destination); } uint16_t diff --git a/src/internet-stack/ipv4-impl.h b/src/internet-stack/ipv4-impl.h index 25b3a6d08..3cfedf0ef 100644 --- a/src/internet-stack/ipv4-impl.h +++ b/src/internet-stack/ipv4-impl.h @@ -91,10 +91,6 @@ public: Ipv4InterfaceAddress GetAddress (uint32_t interfaceIndex, uint32_t addressIndex) const; uint32_t GetNAddresses (uint32_t interface) const; - virtual void SetAddress (uint32_t i, Ipv4Address address); - virtual void SetNetworkMask (uint32_t i, Ipv4Mask mask); - virtual Ipv4Mask GetNetworkMask (uint32_t t) const; - virtual Ipv4Address GetAddress (uint32_t i) const; virtual void SetMetric (uint32_t i, uint16_t metric); virtual uint16_t GetMetric (uint32_t i) const; virtual Ipv4Address GetSourceAddress (Ipv4Address destination) const; diff --git a/src/internet-stack/ipv4-interface.cc b/src/internet-stack/ipv4-interface.cc index e735ae0fe..1bba30f39 100644 --- a/src/internet-stack/ipv4-interface.cc +++ b/src/internet-stack/ipv4-interface.cc @@ -62,37 +62,6 @@ Ipv4Interface::DoDispose (void) Object::DoDispose (); } -void -Ipv4Interface::SetAddress (Ipv4Address a) -{ - NS_LOG_FUNCTION (this << a); - m_address = a; -} - -void -Ipv4Interface::SetNetworkMask (Ipv4Mask mask) -{ - NS_LOG_FUNCTION (this << mask); - m_netmask = mask; -} - -Ipv4Address -Ipv4Interface::GetBroadcast (void) const -{ - NS_LOG_FUNCTION_NOARGS (); - uint32_t mask = m_netmask.Get (); - uint32_t address = m_address.Get (); - Ipv4Address broadcast = Ipv4Address (address | (~mask)); - return broadcast; -} - -Ipv4Mask -Ipv4Interface::GetNetworkMask (void) const -{ - NS_LOG_FUNCTION_NOARGS (); - return m_netmask; -} - void Ipv4Interface::SetMetric (uint16_t metric) { @@ -107,13 +76,6 @@ Ipv4Interface::GetMetric (void) const return m_metric; } -Ipv4Address -Ipv4Interface::GetAddress (void) const -{ - NS_LOG_FUNCTION_NOARGS (); - return m_address; -} - uint16_t Ipv4Interface::GetMtu (void) const { diff --git a/src/internet-stack/ipv4-interface.h b/src/internet-stack/ipv4-interface.h index 2cf27ed8c..f41ff7583 100644 --- a/src/internet-stack/ipv4-interface.h +++ b/src/internet-stack/ipv4-interface.h @@ -75,23 +75,6 @@ public: */ virtual Ptr GetDevice (void) const = 0; - /** - * \param a set the ipv4 address of this interface. - */ - void SetAddress (Ipv4Address a); - /** - * \param mask set the ipv4 netmask of this interface. - */ - void SetNetworkMask (Ipv4Mask mask); - - /** - * \returns the broadcast ipv4 address associated to this interface - */ - Ipv4Address GetBroadcast (void) const; - /** - * \returns the ipv4 netmask of this interface - */ - Ipv4Mask GetNetworkMask (void) const; /** * \param metric configured routing metric (cost) of this interface */ @@ -100,10 +83,6 @@ public: * \returns configured routing metric (cost) of this interface */ uint16_t GetMetric (void) const; - /** - * \returns the ipv4 address of this interface - */ - Ipv4Address GetAddress (void) const; /** * This function a pass-through to NetDevice GetMtu, modulo @@ -170,8 +149,6 @@ protected: private: virtual void SendTo (Ptr p, Ipv4Address dest) = 0; bool m_ifup; - Ipv4Address m_address; - Ipv4Mask m_netmask; uint16_t m_metric; typedef std::list Ipv4InterfaceAddressList; diff --git a/src/internet-stack/ipv4-l3-protocol.cc b/src/internet-stack/ipv4-l3-protocol.cc index 46a44c3e1..dd536eed3 100644 --- a/src/internet-stack/ipv4-l3-protocol.cc +++ b/src/internet-stack/ipv4-l3-protocol.cc @@ -175,8 +175,8 @@ Ipv4L3Protocol::SetupLoopback (void) Ptr interface = CreateObject (); interface->SetNode (m_node); - interface->SetAddress (Ipv4Address::GetLoopback ()); - interface->SetNetworkMask (Ipv4Mask::GetLoopback ()); + Ipv4InterfaceAddress ifaceAddr = Ipv4InterfaceAddress (Ipv4Address::GetLoopback (), Ipv4Mask::GetLoopback ()); + interface->AddAddress (ifaceAddr); uint32_t index = AddIpv4Interface (interface); AddHostRouteTo (Ipv4Address::GetLoopback (), index); interface->SetUp (); @@ -437,9 +437,12 @@ Ipv4L3Protocol::FindInterfaceForAddr (Ipv4Address addr) const i != m_interfaces.end (); i++, interface++) { - if ((*i)->GetAddress () == addr) + for (uint32_t j = 0; j < (*i)->GetNAddresses (); j++) { - return interface; + if ((*i)->GetAddress (j).GetLocal () == addr) + { + return interface; + } } } @@ -458,9 +461,12 @@ Ipv4L3Protocol::FindInterfaceForAddr (Ipv4Address addr, Ipv4Mask mask) const i != m_interfaces.end (); i++, interface++) { - if ((*i)->GetAddress ().CombineMask (mask) == addr.CombineMask (mask)) + for (uint32_t j = 0; j < (*i)->GetNAddresses (); j++) { - return interface; + if ((*i)->GetAddress (j).GetLocal ().CombineMask (mask) == addr.CombineMask (mask)) + { + return interface; + } } } @@ -642,11 +648,15 @@ Ipv4L3Protocol::Send (Ptr packet, ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++) { Ptr outInterface = *ifaceIter; - if (destination.IsSubnetDirectedBroadcast ( - outInterface->GetNetworkMask ())) - { - ipHeader.SetTtl (1); - } + // XXX this logic might not be completely correct for multi-addressed interface + for (uint32_t j = 0; j < outInterface->GetNAddresses(); j++) + { + if (destination.IsSubnetDirectedBroadcast ( + outInterface->GetAddress (j).GetMask ())) + { + ipHeader.SetTtl (1); + } + } } } if (destination.IsBroadcast ()) @@ -659,9 +669,10 @@ Ipv4L3Protocol::Send (Ptr packet, Ptr packetCopy = packet->Copy (); packetCopy->AddHeader (ipHeader); + // XXX Handle multiple address on interface if (packetCopy->GetSize () > outInterface->GetMtu () && ipHeader.IsDontFragment () && - IsUnicast (ipHeader.GetDestination (), outInterface->GetNetworkMask ())) + IsUnicast (ipHeader.GetDestination (), outInterface->GetAddress (0).GetMask ())) { Ptr icmp = GetIcmp (); NS_ASSERT (icmp != 0); @@ -723,9 +734,10 @@ Ipv4L3Protocol::SendRealOut (bool found, NS_LOG_LOGIC ("Send via interface " << route.GetInterface ()); Ptr outInterface = GetInterface (route.GetInterface ()); + // XXX handle multiple address on interface if (packet->GetSize () > outInterface->GetMtu () && ipHeader.IsDontFragment () && - IsUnicast (ipHeader.GetDestination (), outInterface->GetNetworkMask ())) + IsUnicast (ipHeader.GetDestination (), outInterface->GetAddress (0).GetMask ())) { NS_LOG_LOGIC ("Too big: need fragmentation but not allowed"); Ptr icmp = GetIcmp (); @@ -788,10 +800,13 @@ Ipv4L3Protocol::Forwarding ( for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++) { - if ((*i)->GetAddress ().IsEqual (ipHeader.GetDestination ())) + for (uint32_t j = 0; j < (*i)->GetNAddresses (); j++) { - NS_LOG_LOGIC ("For me (destination match)"); - return false; + if ((*i)->GetAddress (j).GetLocal ().IsEqual (ipHeader.GetDestination ())) + { + NS_LOG_LOGIC ("For me (destination match)"); + return false; + } } } @@ -801,7 +816,8 @@ Ipv4L3Protocol::Forwarding ( Ptr interface = *i; if (interface->GetDevice () == device) { - if (ipHeader.GetDestination ().IsEqual (interface->GetBroadcast ())) + // XXX multi-address case + if (ipHeader.GetDestination ().IsEqual (interface->GetAddress (0).GetBroadcast ())) { NS_LOG_LOGIC ("For me (interface broadcast address)"); return false; @@ -852,9 +868,10 @@ Ipv4L3Protocol::DoForward (uint32_t interface, NS_LOG_FUNCTION (this << interface << packet << ipHeader); ipHeader.SetTtl (ipHeader.GetTtl () - 1); + // XXX handle multi-interfaces if (ipHeader.GetTtl () == 0) { - if (IsUnicast (ipHeader.GetDestination (), GetInterface (interface)->GetNetworkMask ())) + if (IsUnicast (ipHeader.GetDestination (), GetInterface (interface)->GetAddress (0).GetMask ())) { Ptr icmp = GetIcmp (); icmp->SendTimeExceededTtl (ipHeader, packet); @@ -889,7 +906,8 @@ Ipv4L3Protocol::ForwardUp (Ptr p, Ipv4Header const&ip, case Ipv4L4Protocol::RX_CSUM_FAILED: break; case Ipv4L4Protocol::RX_ENDPOINT_UNREACH: - if (IsUnicast (ip.GetDestination (), incomingInterface->GetNetworkMask ())) + // XXX handle multi-interface case + if (IsUnicast (ip.GetDestination (), incomingInterface->GetAddress (0).GetMask ())) { GetIcmp ()->SendDestUnreachPort (ip, copy); } @@ -947,38 +965,6 @@ Ipv4L3Protocol::GetNAddresses (uint32_t interface) const return iface->GetNAddresses (); } -void -Ipv4L3Protocol::SetAddress (uint32_t i, Ipv4Address address) -{ - NS_LOG_FUNCTION (this << i << address); - Ptr interface = GetInterface (i); - interface->SetAddress (address); -} - -void -Ipv4L3Protocol::SetNetworkMask (uint32_t i, Ipv4Mask mask) -{ - NS_LOG_FUNCTION (this << i << mask); - Ptr interface = GetInterface (i); - interface->SetNetworkMask (mask); -} - -Ipv4Mask -Ipv4L3Protocol::GetNetworkMask (uint32_t i) const -{ - NS_LOG_FUNCTION (this << i); - Ptr interface = GetInterface (i); - return interface->GetNetworkMask (); -} - -Ipv4Address -Ipv4L3Protocol::GetAddress (uint32_t i) const -{ - NS_LOG_FUNCTION (this << i); - Ptr interface = GetInterface (i); - return interface->GetAddress (); -} - void Ipv4L3Protocol::SetMetric (uint32_t i, uint16_t metric) { @@ -1091,11 +1077,13 @@ Ipv4L3Protocol::SetUp (uint32_t i) // If interface address and network mask have been set, add a route // to the network of the interface (like e.g. ifconfig does on a // Linux box) - if (((interface->GetAddress ()) != (Ipv4Address ())) - && (interface->GetNetworkMask ()) != (Ipv4Mask ())) + for (uint32_t j = 0; j < interface->GetNAddresses (); j++) { - AddNetworkRouteTo (interface->GetAddress ().CombineMask (interface->GetNetworkMask ()), - interface->GetNetworkMask (), i); + if (((interface->GetAddress (j).GetLocal ()) != (Ipv4Address ())) + && (interface->GetAddress (j).GetMask ()) != (Ipv4Mask ())) + { + AddNetworkRouteTo (interface->GetAddress (j).GetLocal ().CombineMask (interface->GetAddress (j).GetMask ()), interface->GetAddress (j).GetMask (), i); + } } } @@ -1124,4 +1112,36 @@ Ipv4L3Protocol::SetDown (uint32_t ifaceIndex) } } +// Note: This method will be removed in Ipv4 routing work +Ipv4Address +Ipv4L3Protocol::GetSourceAddress (Ipv4Address destination) const +{ + uint32_t interface = 0xffffffff; + + bool result = GetInterfaceForDestination (destination, interface); + + if (result) + { + // if multiple addresses exist, search for the first one on the same subnet + for (uint32_t i = 0; i < GetNAddresses (interface); i++) + { + Ipv4InterfaceAddress ipv4InAddr = GetAddress (interface, i); + if (ipv4InAddr.GetLocal().CombineMask(ipv4InAddr.GetMask ()) == destination.CombineMask (ipv4InAddr.GetMask ())) + { + return ipv4InAddr.GetLocal (); + } + } + // Destination is off-link, so return first address. + return GetAddress (interface, 0).GetLocal (); + } + else + { +// +// If we can't find any address, just leave it 0.0.0.0 +// + return Ipv4Address::GetAny (); + } +} + + }//namespace ns3 diff --git a/src/internet-stack/ipv4-l3-protocol.h b/src/internet-stack/ipv4-l3-protocol.h index d3bac94de..58d72cdaa 100644 --- a/src/internet-stack/ipv4-l3-protocol.h +++ b/src/internet-stack/ipv4-l3-protocol.h @@ -191,12 +191,9 @@ public: Ipv4InterfaceAddress GetAddress (uint32_t interfaceIndex, uint32_t addressIndex) const; uint32_t GetNAddresses (uint32_t interface) const; - void SetAddress (uint32_t i, Ipv4Address address); - void SetNetworkMask (uint32_t i, Ipv4Mask mask); - Ipv4Mask GetNetworkMask (uint32_t t) const; - Ipv4Address GetAddress (uint32_t i) const; void SetMetric (uint32_t i, uint16_t metric); uint16_t GetMetric (uint32_t i) const; + Ipv4Address GetSourceAddress (Ipv4Address destination) const; bool GetInterfaceForDestination (Ipv4Address destination, uint32_t& interface) const; uint16_t GetMtu (uint32_t i) const; diff --git a/src/internet-stack/ipv4-raw-socket-impl.cc b/src/internet-stack/ipv4-raw-socket-impl.cc index 7bca1a91e..bb1014eed 100644 --- a/src/internet-stack/ipv4-raw-socket-impl.cc +++ b/src/internet-stack/ipv4-raw-socket-impl.cc @@ -173,7 +173,7 @@ Ipv4RawSocketImpl::SendTo (Ptr p, uint32_t flags, uint32_t localInterface; if (ipv4->GetInterfaceForDestination(dst, localInterface)) { - ipv4->Send (p, ipv4->GetAddress (localInterface), dst, m_protocol); + ipv4->Send (p, ipv4->GetSourceAddress (dst), dst, m_protocol); } else { diff --git a/src/internet-stack/nsc-tcp-l4-protocol.cc b/src/internet-stack/nsc-tcp-l4-protocol.cc index ba030fffa..b22e0670d 100644 --- a/src/internet-stack/nsc-tcp-l4-protocol.cc +++ b/src/internet-stack/nsc-tcp-l4-protocol.cc @@ -344,8 +344,9 @@ void NscTcpL4Protocol::AddInterface(void) // how things _should_ be (once nsc can deal with multiple interfaces...) for (uint32_t i = 1; i < nInterfaces; i++) { - Ipv4Address addr = ip->GetAddress(i); - Ipv4Mask mask = ip->GetNetworkMask(i); + Ipv4InterfaceAddress ifAddr = ip->GetAddress (i, 0); + Ipv4Address addr = ifAddr.GetLocal (); + Ipv4Mask mask = ifAddr.GetMask (); uint16_t mtu = ip->GetMtu (i); std::ostringstream addrOss, maskOss; diff --git a/src/internet-stack/tcp-socket-impl.cc b/src/internet-stack/tcp-socket-impl.cc index d0522f444..27349cc18 100644 --- a/src/internet-stack/tcp-socket-impl.cc +++ b/src/internet-stack/tcp-socket-impl.cc @@ -345,7 +345,7 @@ TcpSocketImpl::Connect (const Address & address) if (ipv4->GetInterfaceForDestination (m_remoteAddress, localInterface)) { - m_endPoint->SetLocalAddress (ipv4->GetAddress (localInterface)); + m_endPoint->SetLocalAddress (ipv4->GetSourceAddress (m_remoteAddress)); } else { @@ -832,7 +832,7 @@ bool TcpSocketImpl::ProcessPacketAction (Actions_t a, Ptr p, m_endPoint->SetPeer (m_remoteAddress, m_remotePort); if (ipv4->GetInterfaceForDestination (m_remoteAddress, localInterface)) { - m_localAddress = ipv4->GetAddress (localInterface); + m_localAddress = ipv4->GetSourceAddress (m_remoteAddress); m_endPoint->SetLocalAddress (m_localAddress); // Leave local addr in the portmap to any, as the path from // remote can change and packets can arrive on different interfaces @@ -1930,8 +1930,8 @@ TcpSocketImplTest::AddSimpleNetDevice (Ptr node, const char* ipaddr, const node->AddDevice (dev); Ptr ipv4 = node->GetObject (); uint32_t ndid = ipv4->AddInterface (dev); - ipv4->SetAddress (ndid, Ipv4Address (ipaddr)); - ipv4->SetNetworkMask (ndid, Ipv4Mask (netmask)); + Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (Ipv4Address (ipaddr), Ipv4Mask (netmask)); + ipv4->AddAddress (ndid, ipv4Addr); ipv4->SetUp (ndid); return dev; } diff --git a/src/internet-stack/udp-socket-impl.cc b/src/internet-stack/udp-socket-impl.cc index 358e5e255..d3cd35a42 100644 --- a/src/internet-stack/udp-socket-impl.cc +++ b/src/internet-stack/udp-socket-impl.cc @@ -362,8 +362,10 @@ UdpSocketImpl::DoSendTo (Ptr p, Ipv4Address dest, uint16_t port) NS_LOG_LOGIC ("Limited broadcast start."); for (uint32_t i = 0; i < ipv4->GetNInterfaces (); i++ ) { - Ipv4Address addri = ipv4->GetAddress (i); - Ipv4Mask maski = ipv4->GetNetworkMask (i); + // Get the primary address + Ipv4InterfaceAddress iaddr = ipv4->GetAddress (i, 0); + Ipv4Address addri = iaddr.GetLocal (); + Ipv4Mask maski = iaddr.GetMask (); if (maski == Ipv4Mask::GetOnes ()) { // if the network mask is 255.255.255.255, do not convert dest @@ -392,7 +394,7 @@ UdpSocketImpl::DoSendTo (Ptr p, Ipv4Address dest, uint16_t port) else if (ipv4->GetInterfaceForDestination(dest, localInterface)) { NS_LOG_LOGIC ("Route exists"); - m_udp->Send (p->Copy (), ipv4->GetAddress (localInterface), dest, + m_udp->Send (p->Copy (), ipv4->GetSourceAddress (dest), dest, m_endPoint->GetLocalPort (), port); NotifyDataSent (p->GetSize ()); NotifySend (GetTxAvailable ()); @@ -666,8 +668,8 @@ UdpSocketImplTest::RunTests (void) rxNode->AddDevice (rxDev1); Ptr ipv4 = rxNode->GetObject (); uint32_t netdev_idx = ipv4->AddInterface (rxDev1); - ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.0.1")); - ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U)); + Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (Ipv4Address ("10.0.0.1"), Ipv4Mask (0xffff0000U)); + ipv4->AddAddress (netdev_idx, ipv4Addr); ipv4->SetUp (netdev_idx); } @@ -677,8 +679,8 @@ UdpSocketImplTest::RunTests (void) rxNode->AddDevice (rxDev2); Ptr ipv4 = rxNode->GetObject (); uint32_t netdev_idx = ipv4->AddInterface (rxDev2); - ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.1.1")); - ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U)); + Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (Ipv4Address ("10.0.1.1"), Ipv4Mask (0xffff0000U)); + ipv4->AddAddress (netdev_idx, ipv4Addr); ipv4->SetUp (netdev_idx); } @@ -692,8 +694,8 @@ UdpSocketImplTest::RunTests (void) txNode->AddDevice (txDev1); Ptr ipv4 = txNode->GetObject (); uint32_t netdev_idx = ipv4->AddInterface (txDev1); - ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.0.2")); - ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U)); + Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (Ipv4Address ("10.0.0.2"), Ipv4Mask (0xffff0000U)); + ipv4->AddAddress (netdev_idx, ipv4Addr); ipv4->SetUp (netdev_idx); } Ptr txDev2; @@ -703,8 +705,8 @@ UdpSocketImplTest::RunTests (void) txNode->AddDevice (txDev2); Ptr ipv4 = txNode->GetObject (); uint32_t netdev_idx = ipv4->AddInterface (txDev2); - ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.1.2")); - ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U)); + Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (Ipv4Address ("10.0.1.2"), Ipv4Mask (0xffff0000U)); + ipv4->AddAddress (netdev_idx, ipv4Addr); ipv4->SetUp (netdev_idx); } diff --git a/src/node/ipv4.cc b/src/node/ipv4.cc index 731a0c484..c1139c1b6 100644 --- a/src/node/ipv4.cc +++ b/src/node/ipv4.cc @@ -45,9 +45,13 @@ Ipv4::GetInterfaceByAddress (Ipv4Address addr, Ipv4Mask mask) { for (uint32_t i = 0; i < GetNInterfaces (); i++) { - if (GetAddress (i).CombineMask(mask) == addr.CombineMask(mask) ) + for (uint32_t j = 0; j < GetNAddresses (i); j++) { - return i; + Ipv4InterfaceAddress ipv4InAddr = GetAddress (i, j); + if (ipv4InAddr.GetLocal ().CombineMask(mask) == addr.CombineMask(mask) ) + { + return i; + } } } // Mapping not found diff --git a/src/node/ipv4.h b/src/node/ipv4.h index 6929da076..bc7dd3f92 100644 --- a/src/node/ipv4.h +++ b/src/node/ipv4.h @@ -411,24 +411,6 @@ public: */ virtual Ipv4InterfaceAddress GetAddress (uint32_t interface, uint32_t addressIndex) const = 0; - /** - * \param i index of ipv4 interface - * \param address address to associate to the underlying ipv4 interface - */ - virtual void SetAddress (uint32_t i, Ipv4Address address) = 0; - - /** - * \param i index of ipv4 interface - * \param mask mask to associate to the underlying ipv4 interface - */ - virtual void SetNetworkMask (uint32_t i, Ipv4Mask mask) = 0; - - /** - * \param i index of ipv4 interface - * \returns the mask associated to the underlying ipv4 interface - */ - virtual Ipv4Mask GetNetworkMask (uint32_t i) const = 0; - /** * \param i index of ipv4 interface * \param metric routing metric (cost) associated to the underlying @@ -443,17 +425,6 @@ public: */ virtual uint16_t GetMetric (uint32_t i) const = 0; - /** - * \param i index of ipv4 interface - * \returns the address associated to the underlying ipv4 interface - * - * Note that the broadcast address for this interface may be fetched - * from the Ipv4Address object returned here using - * Ipv4Address::GetSubnetDirectedBroadcast(mask), where the mask for - * the interface may be retrived using Ipv4::GetNetworkMask(i). - */ - virtual Ipv4Address GetAddress (uint32_t i) const = 0; - /** * \param destination The IP address of a hypothetical destination. * \returns The IP address assigned to the interface that will be used diff --git a/src/routing/global-routing/global-router-interface.cc b/src/routing/global-routing/global-router-interface.cc index 7b81dd735..9c1832ade 100644 --- a/src/routing/global-routing/global-router-interface.cc +++ b/src/routing/global-routing/global-router-interface.cc @@ -704,8 +704,12 @@ GlobalRouter::ProcessSingleBroadcastLink (Ptr nd, GlobalRoutingLSA *p Ptr ipv4Local = node->GetObject (); NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::ProcessSingleBroadcastLink (): GetObject for interface failed"); - Ipv4Address addrLocal = ipv4Local->GetAddress(interfaceLocal); - Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(interfaceLocal); + if (ipv4Local->GetNAddresses (interfaceLocal) > 1) + { + NS_LOG_WARN ("Warning, interface has multiple IP addresses; using only the primary one"); + } + Ipv4Address addrLocal = ipv4Local->GetAddress (interfaceLocal, 0).GetLocal (); + Ipv4Mask maskLocal = ipv4Local->GetAddress (interfaceLocal, 0).GetMask (); NS_LOG_LOGIC ("Working with local address " << addrLocal); uint16_t metricLocal = ipv4Local->GetMetric (interfaceLocal); @@ -820,8 +824,12 @@ GlobalRouter::ProcessBridgedBroadcastLink (Ptr nd, GlobalRoutingLSA * Ptr ipv4Local = node->GetObject (); NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::ProcessBridgedBroadcastLink (): GetObject for interface failed"); - Ipv4Address addrLocal = ipv4Local->GetAddress(interfaceLocal); - Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(interfaceLocal); + if (ipv4Local->GetNAddresses (interfaceLocal) > 1) + { + NS_LOG_WARN ("Warning, interface has multiple IP addresses; using only the primary one"); + } + Ipv4Address addrLocal = ipv4Local->GetAddress (interfaceLocal, 0).GetLocal (); + Ipv4Mask maskLocal = ipv4Local->GetAddress (interfaceLocal, 0).GetMask ();; NS_LOG_LOGIC ("Working with local address " << addrLocal); uint16_t metricLocal = ipv4Local->GetMetric (interfaceLocal); @@ -962,8 +970,12 @@ GlobalRouter::ProcessPointToPointLink (Ptr ndLocal, GlobalRoutingLSA Ptr ipv4Local = nodeLocal->GetObject (); NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::ProcessPointToPointLink (): GetObject for interface failed"); - Ipv4Address addrLocal = ipv4Local->GetAddress(interfaceLocal); - Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(interfaceLocal); + if (ipv4Local->GetNAddresses (interfaceLocal) > 1) + { + NS_LOG_WARN ("Warning, interface has multiple IP addresses; using only the primary one"); + } + Ipv4Address addrLocal = ipv4Local->GetAddress (interfaceLocal, 0).GetLocal (); + Ipv4Mask maskLocal = ipv4Local->GetAddress (interfaceLocal, 0).GetMask (); NS_LOG_LOGIC ("Working with local address " << addrLocal); uint16_t metricLocal = ipv4Local->GetMetric (interfaceLocal); @@ -1018,8 +1030,12 @@ GlobalRouter::ProcessPointToPointLink (Ptr ndLocal, GlobalRoutingLSA // Now that we have the Ipv4 interface, we can get the (remote) address and // mask we need. // - Ipv4Address addrRemote = ipv4Remote->GetAddress(interfaceRemote); - Ipv4Mask maskRemote = ipv4Remote->GetNetworkMask(interfaceRemote); + if (ipv4Remote->GetNAddresses (interfaceRemote) > 1) + { + NS_LOG_WARN ("Warning, interface has multiple IP addresses; using only the primary one"); + } + Ipv4Address addrRemote = ipv4Remote->GetAddress (interfaceRemote, 0).GetLocal (); + Ipv4Mask maskRemote = ipv4Remote->GetAddress (interfaceRemote, 0).GetMask (); NS_LOG_LOGIC ("Working with remote address " << addrRemote); // @@ -1076,8 +1092,12 @@ GlobalRouter::BuildNetworkLSAs (NetDeviceContainer c) Ptr ipv4Local = node->GetObject (); NS_ABORT_MSG_UNLESS (ipv4Local, "GlobalRouter::ProcessPointToPointLink (): GetObject for interface failed"); - Ipv4Address addrLocal = ipv4Local->GetAddress(interfaceLocal); - Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(interfaceLocal); + if (ipv4Local->GetNAddresses (interfaceLocal) > 1) + { + NS_LOG_WARN ("Warning, interface has multiple IP addresses; using only the primary one"); + } + Ipv4Address addrLocal = ipv4Local->GetAddress (interfaceLocal, 0).GetLocal (); + Ipv4Mask maskLocal = ipv4Local->GetAddress (interfaceLocal, 0).GetMask (); GlobalRoutingLSA *pLSA = new GlobalRoutingLSA; NS_ABORT_MSG_IF (pLSA == 0, "GlobalRouter::BuildNetworkLSAs(): Can't alloc link record"); @@ -1128,7 +1148,11 @@ GlobalRouter::BuildNetworkLSAs (NetDeviceContainer c) } else { - Ipv4Address tempAddr = tempIpv4->GetAddress(tempInterface); + if (tempIpv4->GetNAddresses (tempInterface) > 1) + { + NS_LOG_WARN ("Warning, interface has multiple IP addresses; using only the primary one"); + } + Ipv4Address tempAddr = tempIpv4->GetAddress(tempInterface, 0).GetLocal (); pLSA->AddAttachedRouter (tempAddr); } } @@ -1206,7 +1230,11 @@ GlobalRouter::FindDesignatedRouterForLink (Ptr ndLocal, bool allowRec NS_LOG_LOGIC ("Remote side interface " << interfaceOther << " not up"); continue; } - Ipv4Address addrOther = ipv4->GetAddress (interfaceOther); + if (ipv4->GetNAddresses (interfaceOther) > 1) + { + NS_LOG_WARN ("Warning, interface has multiple IP addresses; using only the primary one"); + } + Ipv4Address addrOther = ipv4->GetAddress (interfaceOther, 0).GetLocal (); desigRtr = addrOther < desigRtr ? addrOther : desigRtr; NS_LOG_LOGIC ("designated router now " << desigRtr); } @@ -1255,7 +1283,11 @@ GlobalRouter::FindDesignatedRouterForLink (Ptr ndLocal, bool allowRec continue; } NS_LOG_LOGIC ("Found router on net device " << ndOther); - Ipv4Address addrOther = ipv4->GetAddress (interfaceOther); + if (ipv4->GetNAddresses (interfaceOther) > 1) + { + NS_LOG_WARN ("Warning, interface has multiple IP addresses; using only the primary one"); + } + Ipv4Address addrOther = ipv4->GetAddress (interfaceOther, 0).GetLocal (); desigRtr = addrOther < desigRtr ? addrOther : desigRtr; NS_LOG_LOGIC ("designated router now " << desigRtr); } diff --git a/src/routing/olsr/olsr-agent-impl.cc b/src/routing/olsr/olsr-agent-impl.cc index 6252f984d..65ddde048 100644 --- a/src/routing/olsr/olsr-agent-impl.cc +++ b/src/routing/olsr/olsr-agent-impl.cc @@ -237,7 +237,8 @@ void AgentImpl::Start () Ipv4Address loopback ("127.0.0.1"); for (uint32_t i = 0; i < m_ipv4->GetNInterfaces (); i++) { - Ipv4Address addr = m_ipv4->GetAddress (i); + // Use primary address, if multiple + Ipv4Address addr = m_ipv4->GetAddress (i, 0).GetLocal (); if (addr != loopback) { m_mainAddress = addr; @@ -260,7 +261,7 @@ void AgentImpl::Start () Ipv4Address loopback ("127.0.0.1"); for (uint32_t i = 0; i < m_ipv4->GetNInterfaces (); i++) { - Ipv4Address addr = m_ipv4->GetAddress (i); + Ipv4Address addr = m_ipv4->GetAddress (i, 0).GetLocal (); if (addr == loopback) continue; @@ -297,7 +298,7 @@ void AgentImpl::Start () void AgentImpl::SetMainInterface (uint32_t interface) { - m_mainAddress = m_ipv4->GetAddress (interface); + m_mainAddress = m_ipv4->GetAddress (interface, 0).GetLocal (); } @@ -1556,7 +1557,7 @@ AgentImpl::SendMid () Ipv4Address loopback ("127.0.0.1"); for (uint32_t i = 0; i < m_ipv4->GetNInterfaces (); i++) { - Ipv4Address addr = m_ipv4->GetAddress (i); + Ipv4Address addr = m_ipv4->GetAddress (i, 0).GetLocal (); if (addr != m_mainAddress && addr != loopback) mid.interfaceAddresses.push_back (addr); } diff --git a/src/routing/olsr/olsr-routing-table.cc b/src/routing/olsr/olsr-routing-table.cc index d3d63e226..f1559d389 100644 --- a/src/routing/olsr/olsr-routing-table.cc +++ b/src/routing/olsr/olsr-routing-table.cc @@ -210,10 +210,13 @@ RoutingTable::AddEntry (Ipv4Address const &dest, RoutingTableEntry entry; for (uint32_t i = 0; i < m_ipv4->GetNInterfaces (); i++) { - if (m_ipv4->GetAddress (i) == interfaceAddress) + for (uint32_t j = 0; j < m_ipv4->GetNAddresses (i); j++) { - AddEntry (dest, next, i, distance); - return; + if (m_ipv4->GetAddress (i,j).GetLocal () == interfaceAddress) + { + AddEntry (dest, next, i, distance); + return; + } } } NS_ASSERT (false); // should not be reached From 20e82987c9f7513ffa043eaa38481e0b642d1713 Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Sun, 12 Apr 2009 22:14:34 -0700 Subject: [PATCH 06/22] Update README --- README.api | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/README.api b/README.api index 77826a5ae..5703a5786 100644 --- a/README.api +++ b/README.api @@ -1,3 +1,6 @@ +This repository handles changes to the Ipv4 interface class and Ipv4Impl +class. + 1. Changeset: d99061f1167c Synopsis: @@ -46,7 +49,7 @@ None. ======================================================================== 2. Changeset: e493e80274bd (implementation added in parallel) - Changeset: TBD (cut over of client code, remove old code) + Changeset: db81fdcb06e7 (cut over of client code, remove old code) Synopsis: -------- @@ -62,16 +65,26 @@ multiple IP addresses on an interface: + virtual Ipv4InterfaceAddress GetAddress (uint32_t interface, uint32_t addressIndex) const = 0; + virtual uint32_t GetNAddresses (uint32_t interface) const = 0; -This convenience function was removed: -- virtual uint32_t GetIfIndexByAddress (Ipv4Address addr, -- Ipv4Mask mask = Ipv4Mask("255.255.255.255")); +Regarding legacy API usage, typically where you once did the following, +using the public Ipv4 class interface (e.g.): -A few public methods were renamed because they were poorly named: -- virtual uint32_t FindInterfaceForAddr (Ipv4Address addr, -+ virtual int32_t GetInterfaceForAddress (Ipv4Address address, - Ipv4Mask mask) const = 0; -- virtual int32_t FindInterfaceForDevice(Ptr nd) const = 0; -+ virtual int32_t GetInterfaceForDevice (Ptr device) const = 0; + ipv4A->SetAddress (ifIndexA, Ipv4Address ("172.16.1.1")); + ipv4A->SetNetworkMask (ifIndexA, Ipv4Mask ("255.255.255.255")); + +you now do: + + Ipv4InterfaceAddress ipv4IfAddrA = Ipv4InterfaceAddress (Ipv4Address ("172.16.1.1"), Ipv4Mask ("255.255.255.255")); + ipv4A->AddAddress (ifIndexA, ipv4IfAddrA); + + +At the helper API level, one often gets an address from an interface +container. We preserve the legacy GetAddress (uint32_t i) but it +is documented that this will return only the first (address index 0) +address on the interface, if there are multiple such addresses. +We provide also an overloaded variant for the multi-address case: + +Ipv4Address Ipv4InterfaceContainer::GetAddress (uint32_t i) ++ Ipv4Address Ipv4InterfaceContainer::GetAddress (uint32_t i, uint32_t j) New public API or classes (src/node) @@ -81,6 +94,7 @@ class Ipv4InterfaceAddress: This is a new class to parallel Linux struct in_ifaddr. It holds IP addressing information, including mask, broadcast address, scope, whether primary or secondary, etc. +Location: src/node/ipv4-interface-address.h ======================================================================== From ce3e1d31a6bcb74c2e3f7c9cdbf942ba1e4f0ecb Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Sun, 12 Apr 2009 22:40:31 -0700 Subject: [PATCH 07/22] Remove class Ipv4Impl --- src/internet-stack/internet-stack.cc | 4 - src/internet-stack/ipv4-impl.cc | 255 ------------------------- src/internet-stack/ipv4-impl.h | 112 ----------- src/internet-stack/ipv4-l3-protocol.cc | 25 ++- src/internet-stack/ipv4-l3-protocol.h | 12 +- src/internet-stack/wscript | 1 - src/node/ipv4.h | 2 +- 7 files changed, 24 insertions(+), 387 deletions(-) delete mode 100644 src/internet-stack/ipv4-impl.cc delete mode 100644 src/internet-stack/ipv4-impl.h diff --git a/src/internet-stack/internet-stack.cc b/src/internet-stack/internet-stack.cc index 0e32c5cb6..e02f24286 100644 --- a/src/internet-stack/internet-stack.cc +++ b/src/internet-stack/internet-stack.cc @@ -29,7 +29,6 @@ #include "arp-l3-protocol.h" #include "udp-socket-factory-impl.h" #include "tcp-socket-factory-impl.h" -#include "ipv4-impl.h" #include "ipv4-raw-socket-factory-impl.h" #include "icmpv4-l4-protocol.h" #ifdef NETWORK_SIMULATION_CRADLE @@ -94,9 +93,6 @@ AddIpv4Stack(Ptr node) Ptr ipv4 = CreateObject (); ipv4->SetNode (node); node->AggregateObject (ipv4); - Ptr ipv4Impl = CreateObject (); - ipv4Impl->SetIpv4 (ipv4); - node->AggregateObject (ipv4Impl); } void diff --git a/src/internet-stack/ipv4-impl.cc b/src/internet-stack/ipv4-impl.cc deleted file mode 100644 index e23b87cdd..000000000 --- a/src/internet-stack/ipv4-impl.cc +++ /dev/null @@ -1,255 +0,0 @@ -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (c) 2007 INRIA - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Mathieu Lacage - */ -#include "ipv4-impl.h" -#include "ipv4-l3-protocol.h" -#include "ipv4-interface.h" -#include "ns3/assert.h" -#include "ns3/net-device.h" - -namespace ns3 { - -Ipv4Impl::Ipv4Impl () - : m_ipv4 (0) -{} -Ipv4Impl::~Ipv4Impl () -{ - NS_ASSERT (m_ipv4 == 0); -} -void -Ipv4Impl::SetIpv4 (Ptr ipv4) -{ - m_ipv4 = ipv4; -} -void -Ipv4Impl::DoDispose (void) -{ - m_ipv4 = 0; -} - -void -Ipv4Impl::AddRoutingProtocol (Ptr routingProtocol, - int16_t priority) -{ - m_ipv4->AddRoutingProtocol (routingProtocol, priority); -} - -void -Ipv4Impl::AddHostRouteTo (Ipv4Address dest, - Ipv4Address nextHop, - uint32_t interface) -{ - m_ipv4->AddHostRouteTo (dest, nextHop, interface); -} -void -Ipv4Impl::AddHostRouteTo (Ipv4Address dest, - uint32_t interface) -{ - m_ipv4->AddHostRouteTo (dest, interface); -} -void -Ipv4Impl::AddNetworkRouteTo (Ipv4Address network, - Ipv4Mask networkMask, - Ipv4Address nextHop, - uint32_t interface) -{ - m_ipv4->AddNetworkRouteTo (network, networkMask, nextHop, interface); -} -void -Ipv4Impl::AddNetworkRouteTo (Ipv4Address network, - Ipv4Mask networkMask, - uint32_t interface) -{ - m_ipv4->AddNetworkRouteTo (network, networkMask, interface); -} -void -Ipv4Impl::SetDefaultRoute (Ipv4Address nextHop, - uint32_t interface) -{ - m_ipv4->SetDefaultRoute (nextHop, interface); -} -uint32_t -Ipv4Impl::GetNRoutes (void) -{ - return m_ipv4->GetNRoutes (); -} -Ipv4Route -Ipv4Impl::GetRoute (uint32_t i) -{ - return *m_ipv4->GetRoute (i); -} -void -Ipv4Impl::RemoveRoute (uint32_t i) -{ - return m_ipv4->RemoveRoute (i); -} - -void -Ipv4Impl::AddMulticastRoute (Ipv4Address origin, - Ipv4Address group, - uint32_t inputInterface, - std::vector outputInterfaces) -{ - m_ipv4->AddMulticastRoute (origin, group, inputInterface, outputInterfaces); -} - -void -Ipv4Impl::SetDefaultMulticastRoute (uint32_t outputInterface) -{ - m_ipv4->SetDefaultMulticastRoute (outputInterface); -} - -uint32_t -Ipv4Impl::GetNMulticastRoutes (void) const -{ - return m_ipv4->GetNMulticastRoutes (); -} - -Ipv4MulticastRoute -Ipv4Impl::GetMulticastRoute (uint32_t i) const -{ - return *m_ipv4->GetMulticastRoute (i); -} - -void -Ipv4Impl::RemoveMulticastRoute (Ipv4Address origin, - Ipv4Address group, - uint32_t inputInterface) -{ - m_ipv4->RemoveMulticastRoute (origin, group, inputInterface); -} - -void -Ipv4Impl::RemoveMulticastRoute (uint32_t i) -{ - return m_ipv4->RemoveMulticastRoute (i); -} - -uint32_t -Ipv4Impl::AddInterface (Ptr device) -{ - return m_ipv4->AddInterface (device); -} - -uint32_t -Ipv4Impl::GetNInterfaces (void) -{ - return m_ipv4->GetNInterfaces (); -} - -uint32_t -Ipv4Impl::FindInterfaceForAddr (Ipv4Address addr) const -{ - return m_ipv4->FindInterfaceForAddr (addr); -} - -uint32_t -Ipv4Impl::FindInterfaceForAddr (Ipv4Address addr, Ipv4Mask mask) const -{ - return m_ipv4->FindInterfaceForAddr (addr, mask); -} - -int32_t -Ipv4Impl::FindInterfaceForDevice (Ptr device) const -{ - return m_ipv4->FindInterfaceIndexForDevice (device); -} - -Ptr -Ipv4Impl::GetNetDevice (uint32_t i) -{ - return m_ipv4->GetInterface (i)-> GetDevice (); -} - -void -Ipv4Impl::JoinMulticastGroup (Ipv4Address origin, Ipv4Address group) -{ - m_ipv4->JoinMulticastGroup(origin, group); -} - -void -Ipv4Impl::LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group) -{ - m_ipv4->LeaveMulticastGroup(origin, group); -} - -uint32_t -Ipv4Impl::AddAddress (uint32_t i, Ipv4InterfaceAddress address) -{ - return m_ipv4->AddAddress (i, address); -} - -Ipv4InterfaceAddress -Ipv4Impl::GetAddress (uint32_t interfaceIndex, uint32_t addressIndex) const -{ - return m_ipv4->GetAddress (interfaceIndex, addressIndex); -} - -uint32_t -Ipv4Impl::GetNAddresses (uint32_t interface) const -{ - return m_ipv4->GetNAddresses (interface); -} - -void -Ipv4Impl::SetMetric (uint32_t i, uint16_t metric) -{ - m_ipv4->SetMetric (i, metric); -} - -uint16_t -Ipv4Impl::GetMetric (uint32_t i) const -{ - return m_ipv4->GetMetric (i); -} - -bool -Ipv4Impl::GetInterfaceForDestination (Ipv4Address dest, uint32_t &interface) const -{ - return m_ipv4->GetInterfaceForDestination (dest, interface); -} - -Ipv4Address -Ipv4Impl::GetSourceAddress (Ipv4Address destination) const -{ - return m_ipv4->GetSourceAddress (destination); -} - -uint16_t -Ipv4Impl::GetMtu (uint32_t i) const -{ - return m_ipv4->GetMtu (i); -} -bool -Ipv4Impl::IsUp (uint32_t i) const -{ - return m_ipv4->IsUp (i); -} -void -Ipv4Impl::SetUp (uint32_t i) -{ - m_ipv4->SetUp (i); -} -void -Ipv4Impl::SetDown (uint32_t i) -{ - m_ipv4->SetDown (i); -} - -}//namespace ns3 diff --git a/src/internet-stack/ipv4-impl.h b/src/internet-stack/ipv4-impl.h deleted file mode 100644 index 3cfedf0ef..000000000 --- a/src/internet-stack/ipv4-impl.h +++ /dev/null @@ -1,112 +0,0 @@ -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (c) 2007 INRIA - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Mathieu Lacage - */ -#ifndef IPV4_IMPL_H -#define IPV4_IMPL_H - -#include "ns3/ipv4.h" -#include "ns3/ptr.h" - -namespace ns3 { - -class Ipv4L3Protocol; - -class Ipv4Impl : public Ipv4 -{ -public: - Ipv4Impl (); - - virtual ~Ipv4Impl (); - - void SetIpv4 (Ptr ipv4); - - virtual void AddRoutingProtocol (Ptr routingProtocol, - int16_t priority); - - virtual void AddHostRouteTo (Ipv4Address dest, - Ipv4Address nextHop, - uint32_t interface); - virtual void AddHostRouteTo (Ipv4Address dest, - uint32_t interface); - virtual void AddNetworkRouteTo (Ipv4Address network, - Ipv4Mask networkMask, - Ipv4Address nextHop, - uint32_t interface); - virtual void AddNetworkRouteTo (Ipv4Address network, - Ipv4Mask networkMask, - uint32_t interface); - virtual void SetDefaultRoute (Ipv4Address nextHop, - uint32_t interface); - virtual uint32_t GetNRoutes (void); - virtual Ipv4Route GetRoute (uint32_t i); - virtual void RemoveRoute (uint32_t i); - - - virtual void AddMulticastRoute (Ipv4Address origin, - Ipv4Address group, - uint32_t inputInterface, - std::vector outputInterfaces); - - virtual void SetDefaultMulticastRoute (uint32_t outputInterface); - - virtual uint32_t GetNMulticastRoutes (void) const; - virtual Ipv4MulticastRoute GetMulticastRoute (uint32_t i) const; - - virtual void RemoveMulticastRoute (Ipv4Address origin, - Ipv4Address group, - uint32_t inputInterface); - virtual void RemoveMulticastRoute (uint32_t i); - - virtual uint32_t AddInterface (Ptr device); - virtual uint32_t GetNInterfaces (void); - - virtual uint32_t FindInterfaceForAddr (Ipv4Address addr) const; - virtual uint32_t FindInterfaceForAddr (Ipv4Address addr, - Ipv4Mask mask) const; - - virtual int32_t FindInterfaceForDevice (Ptr device) const; - - virtual Ptr GetNetDevice(uint32_t i); - - virtual void JoinMulticastGroup (Ipv4Address origin, Ipv4Address group); - virtual void LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group); - - uint32_t AddAddress (uint32_t i, Ipv4InterfaceAddress address); - Ipv4InterfaceAddress GetAddress (uint32_t interfaceIndex, uint32_t addressIndex) const; - uint32_t GetNAddresses (uint32_t interface) const; - - virtual void SetMetric (uint32_t i, uint16_t metric); - virtual uint16_t GetMetric (uint32_t i) const; - virtual Ipv4Address GetSourceAddress (Ipv4Address destination) const; - virtual bool GetInterfaceForDestination (Ipv4Address dest, - uint32_t &interface) const; - - virtual uint16_t GetMtu (uint32_t i) const; - virtual bool IsUp (uint32_t i) const; - virtual void SetUp (uint32_t i); - virtual void SetDown (uint32_t i); -protected: - virtual void DoDispose (void); -private: - Ptr m_ipv4; -}; - -} // namespace ns3 - -#endif /* IPV4_IMPL_H */ diff --git a/src/internet-stack/ipv4-l3-protocol.cc b/src/internet-stack/ipv4-l3-protocol.cc index dd536eed3..d28c3a9df 100644 --- a/src/internet-stack/ipv4-l3-protocol.cc +++ b/src/internet-stack/ipv4-l3-protocol.cc @@ -53,7 +53,7 @@ TypeId Ipv4L3Protocol::GetTypeId (void) { static TypeId tid = TypeId ("ns3::Ipv4L3Protocol") - .SetParent () + .SetParent () .AddConstructor () .AddAttribute ("DefaultTtl", "The TTL value set by default on all outgoing packets generated on this node.", UintegerValue (64), @@ -298,7 +298,7 @@ Ipv4L3Protocol::Lookup ( void Ipv4L3Protocol::AddRoutingProtocol (Ptr routingProtocol, - int priority) + int16_t priority) { NS_LOG_FUNCTION (this << &routingProtocol << priority); m_routingProtocols.push_back @@ -313,11 +313,11 @@ Ipv4L3Protocol::GetNRoutes (void) return m_staticRouting->GetNRoutes (); } -Ipv4Route * +Ipv4Route Ipv4L3Protocol::GetRoute (uint32_t index) { NS_LOG_FUNCTION_NOARGS (); - return m_staticRouting->GetRoute (index); + return *m_staticRouting->GetRoute (index); } void @@ -354,11 +354,11 @@ Ipv4L3Protocol::GetNMulticastRoutes (void) const return m_staticRouting->GetNMulticastRoutes (); } -Ipv4MulticastRoute * +Ipv4MulticastRoute Ipv4L3Protocol::GetMulticastRoute (uint32_t index) const { NS_LOG_FUNCTION (this << index); - return m_staticRouting->GetMulticastRoute (index); + return *m_staticRouting->GetMulticastRoute (index); } void @@ -476,7 +476,7 @@ Ipv4L3Protocol::FindInterfaceForAddr (Ipv4Address addr, Ipv4Mask mask) const } int32_t -Ipv4L3Protocol::FindInterfaceIndexForDevice (Ptr device) const +Ipv4L3Protocol::FindInterfaceForDevice (Ptr device) const { NS_LOG_FUNCTION (this << device); @@ -1101,8 +1101,8 @@ Ipv4L3Protocol::SetDown (uint32_t ifaceIndex) modified = false; for (uint32_t i = 0; i < GetNRoutes (); i++) { - Ipv4Route *route = GetRoute (i); - if (route->GetInterface () == ifaceIndex) + Ipv4Route route = GetRoute (i); + if (route.GetInterface () == ifaceIndex) { RemoveRoute (i); modified = true; @@ -1143,5 +1143,12 @@ Ipv4L3Protocol::GetSourceAddress (Ipv4Address destination) const } } +Ptr +Ipv4L3Protocol::GetNetDevice (uint32_t i) +{ + return GetInterface (i)-> GetDevice (); +} + + }//namespace ns3 diff --git a/src/internet-stack/ipv4-l3-protocol.h b/src/internet-stack/ipv4-l3-protocol.h index 58d72cdaa..943e816b9 100644 --- a/src/internet-stack/ipv4-l3-protocol.h +++ b/src/internet-stack/ipv4-l3-protocol.h @@ -53,7 +53,7 @@ class Icmpv4L4Protocol; * This is the actual implementation of IP. It contains APIs to send and * receive packets at the IP layer, as well as APIs for IP routing. */ -class Ipv4L3Protocol : public Object +class Ipv4L3Protocol : public Ipv4 { public: static TypeId GetTypeId (void); @@ -158,7 +158,7 @@ public: Ipv4RoutingProtocol::RouteReplyCallback routeReply); uint32_t GetNRoutes (void); - Ipv4Route *GetRoute (uint32_t i); + Ipv4Route GetRoute (uint32_t i); void RemoveRoute (uint32_t i); void AddMulticastRoute (Ipv4Address origin, @@ -169,7 +169,7 @@ public: void SetDefaultMulticastRoute (uint32_t onputInterface); uint32_t GetNMulticastRoutes (void) const; - Ipv4MulticastRoute *GetMulticastRoute (uint32_t i) const; + Ipv4MulticastRoute GetMulticastRoute (uint32_t i) const; void RemoveMulticastRoute (Ipv4Address origin, Ipv4Address group, @@ -182,7 +182,7 @@ public: uint32_t FindInterfaceForAddr (Ipv4Address addr) const; uint32_t FindInterfaceForAddr (Ipv4Address addr, Ipv4Mask mask) const; - int32_t FindInterfaceIndexForDevice (Ptr device) const; + int32_t FindInterfaceForDevice (Ptr device) const; void JoinMulticastGroup (Ipv4Address origin, Ipv4Address group); void LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group); @@ -201,8 +201,10 @@ public: void SetUp (uint32_t i); void SetDown (uint32_t i); + Ptr GetNetDevice (uint32_t i); + void AddRoutingProtocol (Ptr routingProtocol, - int priority); + int16_t priority); protected: diff --git a/src/internet-stack/wscript b/src/internet-stack/wscript index 5718723db..0a48079fe 100644 --- a/src/internet-stack/wscript +++ b/src/internet-stack/wscript @@ -92,7 +92,6 @@ def build(bld): 'udp-socket-impl.cc', 'tcp-socket-impl.cc', 'ipv4-end-point-demux.cc', - 'ipv4-impl.cc', 'udp-socket-factory-impl.cc', 'tcp-socket-factory-impl.cc', 'pending-data.cc', diff --git a/src/node/ipv4.h b/src/node/ipv4.h index bc7dd3f92..95972770d 100644 --- a/src/node/ipv4.h +++ b/src/node/ipv4.h @@ -320,7 +320,7 @@ public: /** * \returns the number of interfaces added by the user. */ - virtual uint32_t GetNInterfaces (void) = 0; + virtual uint32_t GetNInterfaces (void) const = 0; /** * \brief Find and return the interface ID of the interface that has been From 3dab88580ec8084453ea1f40109051eb34e6a9a1 Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Sun, 12 Apr 2009 22:41:33 -0700 Subject: [PATCH 08/22] update api documentation --- README.api | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.api b/README.api index 5703a5786..5d395f563 100644 --- a/README.api +++ b/README.api @@ -98,7 +98,7 @@ Location: src/node/ipv4-interface-address.h ======================================================================== -3. Changeset: TBD +3. Changeset: 2a05a47dba22 Synopsis: -------- From 12f755079e58c8d2c9d49931a1741708ff9b2fad Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Fri, 17 Apr 2009 15:10:23 -0700 Subject: [PATCH 09/22] fix merge issues --- src/routing/olsr/olsr-routing-protocol.cc | 11 +++++++---- src/routing/olsr/olsr-routing-protocol.h | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/routing/olsr/olsr-routing-protocol.cc b/src/routing/olsr/olsr-routing-protocol.cc index 02b70c78e..f7625072c 100644 --- a/src/routing/olsr/olsr-routing-protocol.cc +++ b/src/routing/olsr/olsr-routing-protocol.cc @@ -2591,7 +2591,7 @@ RoutingProtocol::RequestRoute (uint32_t ifIndex, } bool -RoutingProtocol::RequestIfIndex (Ipv4Address destination, +RoutingProtocol::RequestInterface (Ipv4Address destination, uint32_t& ifIndex) { RoutingTableEntry entry1, entry2; @@ -2653,10 +2653,13 @@ RoutingProtocol::AddEntry (Ipv4Address const &dest, RoutingTableEntry entry; for (uint32_t i = 0; i < m_ipv4->GetNInterfaces (); i++) { - if (m_ipv4->GetAddress (i) == interfaceAddress) + for (uint32_t j = 0; j < m_ipv4->GetNAddresses (i); j++) { - AddEntry (dest, next, i, distance); - return; + if (m_ipv4->GetAddress (i,j).GetLocal () == interfaceAddress) + { + AddEntry (dest, next, i, distance); + return; + } } } NS_ASSERT (false); // should not be reached diff --git a/src/routing/olsr/olsr-routing-protocol.h b/src/routing/olsr/olsr-routing-protocol.h index cf7a606d1..0cf742789 100644 --- a/src/routing/olsr/olsr-routing-protocol.h +++ b/src/routing/olsr/olsr-routing-protocol.h @@ -125,7 +125,7 @@ private: const Ipv4Header &ipHeader, Ptr packet, RouteReplyCallback routeReply); - virtual bool RequestIfIndex (Ipv4Address destination, + virtual bool RequestInterface (Ipv4Address destination, uint32_t& ifIndex); From eb56a55000c3b019568bedf14b5c6610bd2261bc Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Fri, 17 Apr 2009 15:38:53 -0700 Subject: [PATCH 10/22] Remove m_peer from Ipv4InterfaceAddress class (unused member) --- src/node/ipv4-interface-address.cc | 17 +---------------- src/node/ipv4-interface-address.h | 8 +++++--- 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/src/node/ipv4-interface-address.cc b/src/node/ipv4-interface-address.cc index 4eb302386..e2cf0bc7d 100644 --- a/src/node/ipv4-interface-address.cc +++ b/src/node/ipv4-interface-address.cc @@ -45,7 +45,6 @@ Ipv4InterfaceAddress::Ipv4InterfaceAddress (Ipv4Address local, Ipv4Mask mask) Ipv4InterfaceAddress::Ipv4InterfaceAddress (const Ipv4InterfaceAddress &o) : m_local (o.m_local), - m_peer (o.m_peer), m_mask (o.m_mask), m_broadcast (o.m_broadcast), m_scope (o.m_scope), @@ -68,20 +67,6 @@ Ipv4InterfaceAddress::GetLocal (void) const return m_local; } -void -Ipv4InterfaceAddress::SetPeer (Ipv4Address peer) -{ - NS_LOG_FUNCTION_NOARGS (); - m_peer = peer; -} - -Ipv4Address -Ipv4InterfaceAddress::GetPeer (void) const -{ - NS_LOG_FUNCTION_NOARGS (); - return m_peer; -} - void Ipv4InterfaceAddress::SetMask (Ipv4Mask mask) { @@ -147,7 +132,7 @@ Ipv4InterfaceAddress::SetPrimary (void) std::ostream& operator<< (std::ostream& os, const Ipv4InterfaceAddress &addr) { - os << "m_local=" << addr.GetLocal () << "; m_peer=" << addr.GetPeer () << "; m_mask=" << + os << "m_local=" << addr.GetLocal () << "; m_mask=" << addr.GetMask () << "; m_broadcast=" << addr.GetBroadcast () << "; m_scope=" << addr.GetScope() << "; m_secondary=" << addr.IsSecondary (); return os; diff --git a/src/node/ipv4-interface-address.h b/src/node/ipv4-interface-address.h index d8a4ff27b..8d9301eae 100644 --- a/src/node/ipv4-interface-address.h +++ b/src/node/ipv4-interface-address.h @@ -27,6 +27,8 @@ namespace ns3 { /** + * \ingroup address + * * \brief a class to store IPv4 address information on an interface * * Corresponds to Linux struct in_ifaddr. A list of these addresses @@ -53,8 +55,6 @@ public: void SetLocal (Ipv4Address local); Ipv4Address GetLocal (void) const; - void SetPeer (Ipv4Address peer); - Ipv4Address GetPeer (void) const; void SetMask (Ipv4Mask mask); Ipv4Mask GetMask (void) const; void SetBroadcast (Ipv4Address broadcast); @@ -68,8 +68,10 @@ public: void SetPrimary (void); private: + Ipv4Address m_local; // Interface address - Ipv4Address m_peer; // Peer destination address (in Linux: m_address) + // Note: m_peer may be added in future when necessary + // Ipv4Address m_peer; // Peer destination address (in Linux: m_address) Ipv4Mask m_mask; // Network mask Ipv4Address m_broadcast; // Broadcast address From f9bb69ba63c655f523ac23de6a7bd968db960390 Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Fri, 17 Apr 2009 15:46:01 -0700 Subject: [PATCH 11/22] rescan bindings --- bindings/python/ns3_module_core.py | 8 +- bindings/python/ns3_module_helper.py | 4 +- bindings/python/ns3_module_internet_stack.py | 10 +- bindings/python/ns3_module_mobility.py | 8 ++ bindings/python/ns3_module_node.py | 128 ++++++++++++++----- bindings/python/ns3_module_olsr.py | 4 +- bindings/python/ns3_module_wifi.py | 70 +++++----- 7 files changed, 152 insertions(+), 80 deletions(-) diff --git a/bindings/python/ns3_module_core.py b/bindings/python/ns3_module_core.py index e108eba13..f92b4d19a 100644 --- a/bindings/python/ns3_module_core.py +++ b/bindings/python/ns3_module_core.py @@ -2028,7 +2028,7 @@ def register_Ns3TracedValue__Unsigned_int_methods(root_module, cls): cls.add_method('ConnectWithoutContext', 'void', [param('ns3::CallbackBase const &', 'cb')]) - ## traced-value.h: void ns3::TracedValue::Connect(ns3::CallbackBase const & cb, std::string path) [member function] + ## traced-value.h: void ns3::TracedValue::Connect(ns3::CallbackBase const & cb, std::basic_string,std::allocator > path) [member function] cls.add_method('Connect', 'void', [param('ns3::CallbackBase const &', 'cb'), param('std::string', 'path')]) @@ -2036,7 +2036,7 @@ def register_Ns3TracedValue__Unsigned_int_methods(root_module, cls): cls.add_method('DisconnectWithoutContext', 'void', [param('ns3::CallbackBase const &', 'cb')]) - ## traced-value.h: void ns3::TracedValue::Disconnect(ns3::CallbackBase const & cb, std::string path) [member function] + ## traced-value.h: void ns3::TracedValue::Disconnect(ns3::CallbackBase const & cb, std::basic_string,std::allocator > path) [member function] cls.add_method('Disconnect', 'void', [param('ns3::CallbackBase const &', 'cb'), param('std::string', 'path')]) @@ -2184,7 +2184,7 @@ def register_functions(root_module): module.add_function('TypeNameGet', 'std::string', [], - template_parameters=['long long']) + template_parameters=['long']) ## type-name.h: extern std::string ns3::TypeNameGet() [free function] module.add_function('TypeNameGet', 'std::string', @@ -2204,7 +2204,7 @@ def register_functions(root_module): module.add_function('TypeNameGet', 'std::string', [], - template_parameters=['unsigned long long']) + template_parameters=['unsigned long']) ## type-name.h: extern std::string ns3::TypeNameGet() [free function] module.add_function('TypeNameGet', 'std::string', diff --git a/bindings/python/ns3_module_helper.py b/bindings/python/ns3_module_helper.py index 583c388bf..770173eda 100644 --- a/bindings/python/ns3_module_helper.py +++ b/bindings/python/ns3_module_helper.py @@ -482,10 +482,10 @@ def register_Ns3Ipv4InterfaceContainer_methods(root_module, cls): 'uint32_t', [], is_const=True) - ## ipv4-interface-container.h: ns3::Ipv4Address ns3::Ipv4InterfaceContainer::GetAddress(uint32_t i) const [member function] + ## ipv4-interface-container.h: ns3::Ipv4Address ns3::Ipv4InterfaceContainer::GetAddress(uint32_t i, uint32_t j=0) const [member function] cls.add_method('GetAddress', 'ns3::Ipv4Address', - [param('uint32_t', 'i')], + [param('uint32_t', 'i'), param('uint32_t', 'j', default_value='0')], is_const=True) ## ipv4-interface-container.h: void ns3::Ipv4InterfaceContainer::SetMetric(uint32_t i, uint16_t metric) [member function] cls.add_method('SetMetric', diff --git a/bindings/python/ns3_module_internet_stack.py b/bindings/python/ns3_module_internet_stack.py index a0e616c94..329cbede6 100644 --- a/bindings/python/ns3_module_internet_stack.py +++ b/bindings/python/ns3_module_internet_stack.py @@ -518,15 +518,15 @@ def register_Ns3Ipv4GlobalRouting_methods(root_module, cls): is_static=True) ## ipv4-global-routing.h: ns3::Ipv4GlobalRouting::Ipv4GlobalRouting() [constructor] cls.add_constructor([]) - ## ipv4-global-routing.h: bool ns3::Ipv4GlobalRouting::RequestRoute(uint32_t ifIndex, ns3::Ipv4Header const & ipHeader, ns3::Ptr packet, ns3::Callback,const ns3::Ipv4Header&,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty> routeReply) [member function] + ## ipv4-global-routing.h: bool ns3::Ipv4GlobalRouting::RequestRoute(uint32_t interface, ns3::Ipv4Header const & ipHeader, ns3::Ptr packet, ns3::Callback,const ns3::Ipv4Header&,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty> routeReply) [member function] cls.add_method('RequestRoute', 'bool', - [param('uint32_t', 'ifIndex'), param('ns3::Ipv4Header const &', 'ipHeader'), param('ns3::Ptr< ns3::Packet >', 'packet'), param('ns3::Callback< void, bool, ns3::Ipv4Route const &, ns3::Ptr< ns3::Packet >, ns3::Ipv4Header const &, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'routeReply')], + [param('uint32_t', 'interface'), param('ns3::Ipv4Header const &', 'ipHeader'), param('ns3::Ptr< ns3::Packet >', 'packet'), param('ns3::Callback< void, bool, ns3::Ipv4Route const &, ns3::Ptr< ns3::Packet >, ns3::Ipv4Header const &, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'routeReply')], is_virtual=True) - ## ipv4-global-routing.h: bool ns3::Ipv4GlobalRouting::RequestIfIndex(ns3::Ipv4Address destination, uint32_t & ifIndex) [member function] - cls.add_method('RequestIfIndex', + ## ipv4-global-routing.h: bool ns3::Ipv4GlobalRouting::RequestInterface(ns3::Ipv4Address destination, uint32_t & interface) [member function] + cls.add_method('RequestInterface', 'bool', - [param('ns3::Ipv4Address', 'destination'), param('uint32_t &', 'ifIndex')], + [param('ns3::Ipv4Address', 'destination'), param('uint32_t &', 'interface')], is_virtual=True) ## ipv4-global-routing.h: void ns3::Ipv4GlobalRouting::AddHostRouteTo(ns3::Ipv4Address dest, ns3::Ipv4Address nextHop, uint32_t interface) [member function] cls.add_method('AddHostRouteTo', diff --git a/bindings/python/ns3_module_mobility.py b/bindings/python/ns3_module_mobility.py index c519ee0b0..ef884b178 100644 --- a/bindings/python/ns3_module_mobility.py +++ b/bindings/python/ns3_module_mobility.py @@ -707,6 +707,14 @@ def register_Ns3HierarchicalMobilityModel_methods(root_module, cls): 'ns3::Ptr< ns3::MobilityModel >', [], is_const=True) + ## hierarchical-mobility-model.h: void ns3::HierarchicalMobilityModel::SetChild(ns3::Ptr model) [member function] + cls.add_method('SetChild', + 'void', + [param('ns3::Ptr< ns3::MobilityModel >', 'model')]) + ## hierarchical-mobility-model.h: void ns3::HierarchicalMobilityModel::SetParent(ns3::Ptr model) [member function] + cls.add_method('SetParent', + 'void', + [param('ns3::Ptr< ns3::MobilityModel >', 'model')]) ## hierarchical-mobility-model.h: ns3::Vector ns3::HierarchicalMobilityModel::DoGetPosition() const [member function] cls.add_method('DoGetPosition', 'ns3::Vector', diff --git a/bindings/python/ns3_module_node.py b/bindings/python/ns3_module_node.py index 5b08a1038..122afc8f7 100644 --- a/bindings/python/ns3_module_node.py +++ b/bindings/python/ns3_module_node.py @@ -23,6 +23,10 @@ def register_types(module): root_module['ns3::Ipv4Address'].implicitly_converts_to(root_module['ns3::Address']) ## ipv4-address-generator.h: ns3::Ipv4AddressGenerator [class] module.add_class('Ipv4AddressGenerator') + ## ipv4-interface-address.h: ns3::Ipv4InterfaceAddress [class] + module.add_class('Ipv4InterfaceAddress') + ## ipv4-interface-address.h: ns3::Ipv4InterfaceAddress::InterfaceAddressScope_e [enumeration] + module.add_enum('InterfaceAddressScope_e', ['HOST', 'LINK', 'GLOBAL'], outer_class=root_module['ns3::Ipv4InterfaceAddress']) ## ipv4-address.h: ns3::Ipv4Mask [class] module.add_class('Ipv4Mask') ## ipv4-route.h: ns3::Ipv4MulticastRoute [class] @@ -182,6 +186,7 @@ def register_methods(root_module): register_Ns3InetSocketAddress_methods(root_module, root_module['ns3::InetSocketAddress']) register_Ns3Ipv4Address_methods(root_module, root_module['ns3::Ipv4Address']) register_Ns3Ipv4AddressGenerator_methods(root_module, root_module['ns3::Ipv4AddressGenerator']) + register_Ns3Ipv4InterfaceAddress_methods(root_module, root_module['ns3::Ipv4InterfaceAddress']) register_Ns3Ipv4Mask_methods(root_module, root_module['ns3::Ipv4Mask']) register_Ns3Ipv4MulticastRoute_methods(root_module, root_module['ns3::Ipv4MulticastRoute']) register_Ns3Ipv4Route_methods(root_module, root_module['ns3::Ipv4Route']) @@ -542,6 +547,65 @@ def register_Ns3Ipv4AddressGenerator_methods(root_module, cls): is_static=True) return +def register_Ns3Ipv4InterfaceAddress_methods(root_module, cls): + cls.add_output_stream_operator() + ## ipv4-interface-address.h: ns3::Ipv4InterfaceAddress::Ipv4InterfaceAddress() [constructor] + cls.add_constructor([]) + ## ipv4-interface-address.h: ns3::Ipv4InterfaceAddress::Ipv4InterfaceAddress(ns3::Ipv4Address local, ns3::Ipv4Mask mask) [constructor] + cls.add_constructor([param('ns3::Ipv4Address', 'local'), param('ns3::Ipv4Mask', 'mask')]) + ## ipv4-interface-address.h: ns3::Ipv4InterfaceAddress::Ipv4InterfaceAddress(ns3::Ipv4InterfaceAddress const & o) [copy constructor] + cls.add_constructor([param('ns3::Ipv4InterfaceAddress const &', 'o')]) + ## ipv4-interface-address.h: ns3::Ipv4Address ns3::Ipv4InterfaceAddress::GetBroadcast() const [member function] + cls.add_method('GetBroadcast', + 'ns3::Ipv4Address', + [], + is_const=True) + ## ipv4-interface-address.h: ns3::Ipv4Address ns3::Ipv4InterfaceAddress::GetLocal() const [member function] + cls.add_method('GetLocal', + 'ns3::Ipv4Address', + [], + is_const=True) + ## ipv4-interface-address.h: ns3::Ipv4Mask ns3::Ipv4InterfaceAddress::GetMask() const [member function] + cls.add_method('GetMask', + 'ns3::Ipv4Mask', + [], + is_const=True) + ## ipv4-interface-address.h: ns3::Ipv4InterfaceAddress::InterfaceAddressScope_e ns3::Ipv4InterfaceAddress::GetScope() const [member function] + cls.add_method('GetScope', + 'ns3::Ipv4InterfaceAddress::InterfaceAddressScope_e', + [], + is_const=True) + ## ipv4-interface-address.h: bool ns3::Ipv4InterfaceAddress::IsSecondary() const [member function] + cls.add_method('IsSecondary', + 'bool', + [], + is_const=True) + ## ipv4-interface-address.h: void ns3::Ipv4InterfaceAddress::SetBroadcast(ns3::Ipv4Address broadcast) [member function] + cls.add_method('SetBroadcast', + 'void', + [param('ns3::Ipv4Address', 'broadcast')]) + ## ipv4-interface-address.h: void ns3::Ipv4InterfaceAddress::SetLocal(ns3::Ipv4Address local) [member function] + cls.add_method('SetLocal', + 'void', + [param('ns3::Ipv4Address', 'local')]) + ## ipv4-interface-address.h: void ns3::Ipv4InterfaceAddress::SetMask(ns3::Ipv4Mask mask) [member function] + cls.add_method('SetMask', + 'void', + [param('ns3::Ipv4Mask', 'mask')]) + ## ipv4-interface-address.h: void ns3::Ipv4InterfaceAddress::SetPrimary() [member function] + cls.add_method('SetPrimary', + 'void', + []) + ## ipv4-interface-address.h: void ns3::Ipv4InterfaceAddress::SetScope(ns3::Ipv4InterfaceAddress::InterfaceAddressScope_e scope) [member function] + cls.add_method('SetScope', + 'void', + [param('ns3::Ipv4InterfaceAddress::InterfaceAddressScope_e', 'scope')]) + ## ipv4-interface-address.h: void ns3::Ipv4InterfaceAddress::SetSecondary() [member function] + cls.add_method('SetSecondary', + 'void', + []) + return + def register_Ns3Ipv4Mask_methods(root_module, cls): cls.add_binary_comparison_operator('!=') cls.add_output_stream_operator() @@ -1870,6 +1934,11 @@ def register_Ns3Socket_methods(root_module, cls): 'void', [], visibility='protected') + ## socket.h: void ns3::Socket::DoDispose() [member function] + cls.add_method('DoDispose', + 'void', + [], + visibility='protected', is_virtual=True) return def register_Ns3SocketAddressTag_methods(root_module, cls): @@ -2597,11 +2666,11 @@ def register_Ns3Ipv4_methods(root_module, cls): 'uint32_t', [param('ns3::Ptr< ns3::NetDevice >', 'device')], is_pure_virtual=True, is_virtual=True) - ## ipv4.h: uint32_t ns3::Ipv4::GetNInterfaces() [member function] + ## ipv4.h: uint32_t ns3::Ipv4::GetNInterfaces() const [member function] cls.add_method('GetNInterfaces', 'uint32_t', [], - is_pure_virtual=True, is_virtual=True) + is_pure_virtual=True, is_const=True, is_virtual=True) ## ipv4.h: uint32_t ns3::Ipv4::FindInterfaceForAddr(ns3::Ipv4Address addr) const [member function] cls.add_method('FindInterfaceForAddr', 'uint32_t', @@ -2632,20 +2701,20 @@ def register_Ns3Ipv4_methods(root_module, cls): 'void', [param('ns3::Ipv4Address', 'origin'), param('ns3::Ipv4Address', 'group')], is_pure_virtual=True, is_virtual=True) - ## ipv4.h: void ns3::Ipv4::SetAddress(uint32_t i, ns3::Ipv4Address address) [member function] - cls.add_method('SetAddress', - 'void', - [param('uint32_t', 'i'), param('ns3::Ipv4Address', 'address')], + ## ipv4.h: uint32_t ns3::Ipv4::AddAddress(uint32_t interface, ns3::Ipv4InterfaceAddress address) [member function] + cls.add_method('AddAddress', + 'uint32_t', + [param('uint32_t', 'interface'), param('ns3::Ipv4InterfaceAddress', 'address')], is_pure_virtual=True, is_virtual=True) - ## ipv4.h: void ns3::Ipv4::SetNetworkMask(uint32_t i, ns3::Ipv4Mask mask) [member function] - cls.add_method('SetNetworkMask', - 'void', - [param('uint32_t', 'i'), param('ns3::Ipv4Mask', 'mask')], - is_pure_virtual=True, is_virtual=True) - ## ipv4.h: ns3::Ipv4Mask ns3::Ipv4::GetNetworkMask(uint32_t i) const [member function] - cls.add_method('GetNetworkMask', - 'ns3::Ipv4Mask', - [param('uint32_t', 'i')], + ## ipv4.h: uint32_t ns3::Ipv4::GetNAddresses(uint32_t interface) const [member function] + cls.add_method('GetNAddresses', + 'uint32_t', + [param('uint32_t', 'interface')], + is_pure_virtual=True, is_const=True, is_virtual=True) + ## ipv4.h: ns3::Ipv4InterfaceAddress ns3::Ipv4::GetAddress(uint32_t interface, uint32_t addressIndex) const [member function] + cls.add_method('GetAddress', + 'ns3::Ipv4InterfaceAddress', + [param('uint32_t', 'interface'), param('uint32_t', 'addressIndex')], is_pure_virtual=True, is_const=True, is_virtual=True) ## ipv4.h: void ns3::Ipv4::SetMetric(uint32_t i, uint16_t metric) [member function] cls.add_method('SetMetric', @@ -2657,20 +2726,15 @@ def register_Ns3Ipv4_methods(root_module, cls): 'uint16_t', [param('uint32_t', 'i')], is_pure_virtual=True, is_const=True, is_virtual=True) - ## ipv4.h: ns3::Ipv4Address ns3::Ipv4::GetAddress(uint32_t i) const [member function] - cls.add_method('GetAddress', - 'ns3::Ipv4Address', - [param('uint32_t', 'i')], - is_pure_virtual=True, is_const=True, is_virtual=True) ## ipv4.h: ns3::Ipv4Address ns3::Ipv4::GetSourceAddress(ns3::Ipv4Address destination) const [member function] cls.add_method('GetSourceAddress', 'ns3::Ipv4Address', [param('ns3::Ipv4Address', 'destination')], is_pure_virtual=True, is_const=True, is_virtual=True) - ## ipv4.h: bool ns3::Ipv4::GetIfIndexForDestination(ns3::Ipv4Address dest, uint32_t & ifIndex) const [member function] - cls.add_method('GetIfIndexForDestination', + ## ipv4.h: bool ns3::Ipv4::GetInterfaceForDestination(ns3::Ipv4Address dest, uint32_t & interface) const [member function] + cls.add_method('GetInterfaceForDestination', 'bool', - [param('ns3::Ipv4Address', 'dest'), param('uint32_t &', 'ifIndex')], + [param('ns3::Ipv4Address', 'dest'), param('uint32_t &', 'interface')], is_pure_virtual=True, is_const=True, is_virtual=True) ## ipv4.h: uint16_t ns3::Ipv4::GetMtu(uint32_t i) const [member function] cls.add_method('GetMtu', @@ -2692,8 +2756,8 @@ def register_Ns3Ipv4_methods(root_module, cls): 'void', [param('uint32_t', 'i')], is_pure_virtual=True, is_virtual=True) - ## ipv4.h: uint32_t ns3::Ipv4::GetIfIndexByAddress(ns3::Ipv4Address addr, ns3::Ipv4Mask mask=ns3::Ipv4Mask(((const char*)"255.255.255.255"))) [member function] - cls.add_method('GetIfIndexByAddress', + ## ipv4.h: uint32_t ns3::Ipv4::GetInterfaceByAddress(ns3::Ipv4Address addr, ns3::Ipv4Mask mask=ns3::Ipv4Mask(((const char*)"255.255.255.255"))) [member function] + cls.add_method('GetInterfaceByAddress', 'uint32_t', [param('ns3::Ipv4Address', 'addr'), param('ns3::Ipv4Mask', 'mask', default_value='ns3::Ipv4Mask(((const char*)"255.255.255.255"))')], is_virtual=True) @@ -2712,21 +2776,21 @@ def register_Ns3Ipv4RawSocketFactory_methods(root_module, cls): return def register_Ns3Ipv4RoutingProtocol_methods(root_module, cls): - ## ipv4.h: ns3::Ipv4RoutingProtocol::IF_INDEX_ANY [variable] - cls.add_static_attribute('IF_INDEX_ANY', 'uint32_t const', is_const=True) + ## ipv4.h: ns3::Ipv4RoutingProtocol::INTERFACE_ANY [variable] + cls.add_static_attribute('INTERFACE_ANY', 'uint32_t const', is_const=True) ## ipv4.h: ns3::Ipv4RoutingProtocol::Ipv4RoutingProtocol(ns3::Ipv4RoutingProtocol const & arg0) [copy constructor] cls.add_constructor([param('ns3::Ipv4RoutingProtocol const &', 'arg0')]) ## ipv4.h: ns3::Ipv4RoutingProtocol::Ipv4RoutingProtocol() [constructor] cls.add_constructor([]) - ## ipv4.h: bool ns3::Ipv4RoutingProtocol::RequestRoute(uint32_t ifIndex, ns3::Ipv4Header const & ipHeader, ns3::Ptr packet, ns3::Callback,const ns3::Ipv4Header&,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty> routeReply) [member function] + ## ipv4.h: bool ns3::Ipv4RoutingProtocol::RequestRoute(uint32_t interface, ns3::Ipv4Header const & ipHeader, ns3::Ptr packet, ns3::Callback,const ns3::Ipv4Header&,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty> routeReply) [member function] cls.add_method('RequestRoute', 'bool', - [param('uint32_t', 'ifIndex'), param('ns3::Ipv4Header const &', 'ipHeader'), param('ns3::Ptr< ns3::Packet >', 'packet'), param('ns3::Callback< void, bool, ns3::Ipv4Route const &, ns3::Ptr< ns3::Packet >, ns3::Ipv4Header const &, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'routeReply')], + [param('uint32_t', 'interface'), param('ns3::Ipv4Header const &', 'ipHeader'), param('ns3::Ptr< ns3::Packet >', 'packet'), param('ns3::Callback< void, bool, ns3::Ipv4Route const &, ns3::Ptr< ns3::Packet >, ns3::Ipv4Header const &, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'routeReply')], is_pure_virtual=True, is_virtual=True) - ## ipv4.h: bool ns3::Ipv4RoutingProtocol::RequestIfIndex(ns3::Ipv4Address destination, uint32_t & ifIndex) [member function] - cls.add_method('RequestIfIndex', + ## ipv4.h: bool ns3::Ipv4RoutingProtocol::RequestInterface(ns3::Ipv4Address destination, uint32_t & interface) [member function] + cls.add_method('RequestInterface', 'bool', - [param('ns3::Ipv4Address', 'destination'), param('uint32_t &', 'ifIndex')], + [param('ns3::Ipv4Address', 'destination'), param('uint32_t &', 'interface')], is_pure_virtual=True, is_virtual=True) return diff --git a/bindings/python/ns3_module_olsr.py b/bindings/python/ns3_module_olsr.py index 7e7b633cd..a4f946822 100644 --- a/bindings/python/ns3_module_olsr.py +++ b/bindings/python/ns3_module_olsr.py @@ -745,8 +745,8 @@ def register_Ns3OlsrRoutingProtocol_methods(root_module, cls): 'bool', [param('uint32_t', 'ifIndex'), param('ns3::Ipv4Header const &', 'ipHeader'), param('ns3::Ptr< ns3::Packet >', 'packet'), param('ns3::Callback< void, bool, ns3::Ipv4Route const &, ns3::Ptr< ns3::Packet >, ns3::Ipv4Header const &, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'routeReply')], visibility='private', is_virtual=True) - ## olsr-routing-protocol.h: bool ns3::olsr::RoutingProtocol::RequestIfIndex(ns3::Ipv4Address destination, uint32_t & ifIndex) [member function] - cls.add_method('RequestIfIndex', + ## olsr-routing-protocol.h: bool ns3::olsr::RoutingProtocol::RequestInterface(ns3::Ipv4Address destination, uint32_t & ifIndex) [member function] + cls.add_method('RequestInterface', 'bool', [param('ns3::Ipv4Address', 'destination'), param('uint32_t &', 'ifIndex')], visibility='private', is_virtual=True) diff --git a/bindings/python/ns3_module_wifi.py b/bindings/python/ns3_module_wifi.py index 383402cb2..4d9546dd0 100644 --- a/bindings/python/ns3_module_wifi.py +++ b/bindings/python/ns3_module_wifi.py @@ -605,41 +605,6 @@ def register_Ns3WifiRemoteStation_methods(root_module, cls): cls.add_method('GetAckMode', 'ns3::WifiMode', [param('ns3::WifiMode', 'dataMode')]) - ## wifi-remote-station-manager.h: void ns3::WifiRemoteStation::DoReportRtsFailed() [member function] - cls.add_method('DoReportRtsFailed', - 'void', - [], - is_pure_virtual=True, visibility='protected', is_virtual=True) - ## wifi-remote-station-manager.h: void ns3::WifiRemoteStation::DoReportDataFailed() [member function] - cls.add_method('DoReportDataFailed', - 'void', - [], - is_pure_virtual=True, visibility='protected', is_virtual=True) - ## wifi-remote-station-manager.h: void ns3::WifiRemoteStation::DoReportRtsOk(double ctsSnr, ns3::WifiMode ctsMode, double rtsSnr) [member function] - cls.add_method('DoReportRtsOk', - 'void', - [param('double', 'ctsSnr'), param('ns3::WifiMode', 'ctsMode'), param('double', 'rtsSnr')], - is_pure_virtual=True, visibility='protected', is_virtual=True) - ## wifi-remote-station-manager.h: void ns3::WifiRemoteStation::DoReportDataOk(double ackSnr, ns3::WifiMode ackMode, double dataSnr) [member function] - cls.add_method('DoReportDataOk', - 'void', - [param('double', 'ackSnr'), param('ns3::WifiMode', 'ackMode'), param('double', 'dataSnr')], - is_pure_virtual=True, visibility='protected', is_virtual=True) - ## wifi-remote-station-manager.h: void ns3::WifiRemoteStation::DoReportFinalRtsFailed() [member function] - cls.add_method('DoReportFinalRtsFailed', - 'void', - [], - is_pure_virtual=True, visibility='protected', is_virtual=True) - ## wifi-remote-station-manager.h: void ns3::WifiRemoteStation::DoReportFinalDataFailed() [member function] - cls.add_method('DoReportFinalDataFailed', - 'void', - [], - is_pure_virtual=True, visibility='protected', is_virtual=True) - ## wifi-remote-station-manager.h: void ns3::WifiRemoteStation::DoReportRxOk(double rxSnr, ns3::WifiMode txMode) [member function] - cls.add_method('DoReportRxOk', - 'void', - [param('double', 'rxSnr'), param('ns3::WifiMode', 'txMode')], - is_pure_virtual=True, visibility='protected', is_virtual=True) ## wifi-remote-station-manager.h: uint32_t ns3::WifiRemoteStation::GetNSupportedModes() const [member function] cls.add_method('GetNSupportedModes', 'uint32_t', @@ -665,6 +630,41 @@ def register_Ns3WifiRemoteStation_methods(root_module, cls): 'ns3::WifiMode', [], is_pure_virtual=True, visibility='private', is_virtual=True) + ## wifi-remote-station-manager.h: void ns3::WifiRemoteStation::DoReportRtsFailed() [member function] + cls.add_method('DoReportRtsFailed', + 'void', + [], + is_pure_virtual=True, visibility='private', is_virtual=True) + ## wifi-remote-station-manager.h: void ns3::WifiRemoteStation::DoReportDataFailed() [member function] + cls.add_method('DoReportDataFailed', + 'void', + [], + is_pure_virtual=True, visibility='private', is_virtual=True) + ## wifi-remote-station-manager.h: void ns3::WifiRemoteStation::DoReportRtsOk(double ctsSnr, ns3::WifiMode ctsMode, double rtsSnr) [member function] + cls.add_method('DoReportRtsOk', + 'void', + [param('double', 'ctsSnr'), param('ns3::WifiMode', 'ctsMode'), param('double', 'rtsSnr')], + is_pure_virtual=True, visibility='private', is_virtual=True) + ## wifi-remote-station-manager.h: void ns3::WifiRemoteStation::DoReportDataOk(double ackSnr, ns3::WifiMode ackMode, double dataSnr) [member function] + cls.add_method('DoReportDataOk', + 'void', + [param('double', 'ackSnr'), param('ns3::WifiMode', 'ackMode'), param('double', 'dataSnr')], + is_pure_virtual=True, visibility='private', is_virtual=True) + ## wifi-remote-station-manager.h: void ns3::WifiRemoteStation::DoReportFinalRtsFailed() [member function] + cls.add_method('DoReportFinalRtsFailed', + 'void', + [], + is_pure_virtual=True, visibility='private', is_virtual=True) + ## wifi-remote-station-manager.h: void ns3::WifiRemoteStation::DoReportFinalDataFailed() [member function] + cls.add_method('DoReportFinalDataFailed', + 'void', + [], + is_pure_virtual=True, visibility='private', is_virtual=True) + ## wifi-remote-station-manager.h: void ns3::WifiRemoteStation::DoReportRxOk(double rxSnr, ns3::WifiMode txMode) [member function] + cls.add_method('DoReportRxOk', + 'void', + [param('double', 'rxSnr'), param('ns3::WifiMode', 'txMode')], + is_pure_virtual=True, visibility='private', is_virtual=True) return def register_Ns3AmrrWifiRemoteStation_methods(root_module, cls): From 1643605078320c32948e84bf6deb564ba30e6602 Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Sun, 19 Apr 2009 14:51:51 +0100 Subject: [PATCH 12/22] Make the --enable-sudo option work correctly again --- wscript | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/wscript b/wscript index f47c67b67..5135eaa99 100644 --- a/wscript +++ b/wscript @@ -174,7 +174,7 @@ def _check_compilation_flag(conf, flag): try: retval = conf.run_c_code(code='#include \nint main() { return 0; }\n', env=env, compile_filename='test.cc', - compile_mode='cxx',type='program', execute=False) + compile_mode='cxx',type='cprogram', execute=False) except Configure.ConfigurationError: ok = False else: @@ -296,10 +296,11 @@ class SuidBuildTask(Task.TaskBase): after = 'cxx_link cc_link' maxjobs = 1 def __init__(self, bld, program): + self.bld = bld self.m_display = 'build-suid' self.__program = program self.__env = bld.env.copy () - super(SuidBuildTask, self).__init__() + super(SuidBuildTask, self).__init__(generator=self) try: program_obj = wutils.find_program(self.__program.target, self.__env) except ValueError, ex: From 21914357fb10b8d062a2fadd04bee82996e5ec23 Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Mon, 20 Apr 2009 17:39:54 +0100 Subject: [PATCH 13/22] Upgrade to WAF 1.5.5 --- src/contrib/wscript | 2 +- src/core/wscript | 2 +- src/simulator/wscript | 2 +- src/wscript | 2 +- waf | Bin 84472 -> 85131 bytes wscript | 2 +- 6 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/contrib/wscript b/src/contrib/wscript index 067e36e8e..806e433c3 100644 --- a/src/contrib/wscript +++ b/src/contrib/wscript @@ -16,7 +16,7 @@ def configure(conf): "library 'libxml-2.0 >= 2.7' not found") conf.sub_config('stats') - conf.write_config_header('ns3/contrib-config.h') + conf.write_config_header('ns3/contrib-config.h', project_root_relative=True) def build(bld): module = bld.create_ns3_module('contrib', ['simulator', 'common']) diff --git a/src/core/wscript b/src/core/wscript index faa028cdc..60a63aff5 100644 --- a/src/core/wscript +++ b/src/core/wscript @@ -41,7 +41,7 @@ int main () conf.env['ENABLE_THREADING'], " include not detected") - conf.write_config_header('ns3/core-config.h') + conf.write_config_header('ns3/core-config.h', project_root_relative=True) def build(bld): core = bld.create_ns3_module('core') diff --git a/src/simulator/wscript b/src/simulator/wscript index e4ae5c0b8..a14cf2480 100644 --- a/src/simulator/wscript +++ b/src/simulator/wscript @@ -31,7 +31,7 @@ def configure(conf): conf.check(header_name='sys/inttypes.h', define_name='HAVE_SYS_INT_TYPES_H') - conf.write_config_header('ns3/simulator-config.h') + conf.write_config_header('ns3/simulator-config.h', project_root_relative=True) if not conf.check(lib='rt', uselib='RT', define_name='HAVE_RT'): conf.report_optional_feature("RealTime", "Real Time Simulator", diff --git a/src/wscript b/src/wscript index b9192858a..166d9eaa2 100644 --- a/src/wscript +++ b/src/wscript @@ -67,7 +67,7 @@ def configure(conf): def create_ns3_module(bld, name, dependencies=()): - module = bld.new_task_gen('cxx', 'objects') + module = bld.new_task_gen('cxx') module.name = 'ns3-' + name module.target = module.name module.add_objects = ['ns3-' + dep for dep in dependencies] diff --git a/waf b/waf index 25ac3fc18a19c49be7d2eafa7b0f4f8fb8bd57f2..fc98af278a5a2f006826d8d4b7229841607c9822 100755 GIT binary patch delta 82081 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 z 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 diff --git a/wscript b/wscript index 5135eaa99..163ee4fbd 100644 --- a/wscript +++ b/wscript @@ -499,7 +499,7 @@ def check(bld): "run the NS-3 unit tests" Scripting.build(bld) ## generate the trace sources list docs - env = bld.env + env = wutils.bld.env proc_env = wutils.get_proc_env() try: program_obj = wutils.find_program('print-introspected-doxygen', env) From 1edb42fee9a2dfbbd8f61d73ca3e6207f853e9f7 Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Mon, 20 Apr 2009 19:08:41 +0100 Subject: [PATCH 14/22] Fix a build script bug --- wscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wscript b/wscript index 163ee4fbd..d5d8e4aca 100644 --- a/wscript +++ b/wscript @@ -515,7 +515,7 @@ def check(bld): out.close() print "-- Running NS-3 C++ core unit tests..." - wutils.run_program('run-tests', wutils.get_command_template(env)) + wutils.run_program('run-tests', env, wutils.get_command_template(env)) if env['ENABLE_PYTHON_BINDINGS']: print "-- Running NS-3 Python bindings unit tests..." From f55e4e0f587b2d07474a69323627ac29b2f6e431 Mon Sep 17 00:00:00 2001 From: Craig Dowell Date: Mon, 20 Apr 2009 19:36:31 -0700 Subject: [PATCH 15/22] put DeviceName Attribute back in emu net device --- src/devices/emu/emu-net-device.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/devices/emu/emu-net-device.cc b/src/devices/emu/emu-net-device.cc index 7d3e451eb..6b57baf53 100644 --- a/src/devices/emu/emu-net-device.cc +++ b/src/devices/emu/emu-net-device.cc @@ -68,6 +68,11 @@ EmuNetDevice::GetTypeId (void) Mac48AddressValue (Mac48Address ("ff:ff:ff:ff:ff:ff")), MakeMac48AddressAccessor (&EmuNetDevice::m_address), MakeMac48AddressChecker ()) + .AddAttribute ("DeviceName", + "The name of the underlying real device (e.g. eth1).", + StringValue ("eth1"), + MakeStringAccessor (&EmuNetDevice::m_deviceName), + MakeStringChecker ()) .AddAttribute ("Start", "The simulation time at which to spin up the device thread.", TimeValue (Seconds (0.)), From a2d89754b91d522b2055b93820c7a3e8759ea62c Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Mon, 20 Apr 2009 20:15:17 -0700 Subject: [PATCH 16/22] remove temporary README.api --- README.api | 116 ----------------------------------------------------- 1 file changed, 116 deletions(-) delete mode 100644 README.api diff --git a/README.api b/README.api deleted file mode 100644 index 5d395f563..000000000 --- a/README.api +++ /dev/null @@ -1,116 +0,0 @@ -This repository handles changes to the Ipv4 interface class and Ipv4Impl -class. - -1. Changeset: d99061f1167c - -Synopsis: --------- -- deconflict NetDevice::ifIndex and Ipv4::ifIndex (bug 85) - -Changed public API (src/node) --------- - -All function parameters named "ifIndex" that refer to an Ipv4 interface -are instead named "interface". - -- static const uint32_t Ipv4RoutingProtocol::IF_INDEX_ANY = 0xffffffff; -+ static const uint32_t Ipv4RoutingProtocol::INTERFACE_ANY = 0xffffffff; - -- bool Ipv4RoutingProtocol::RequestIfIndex (Ipv4Address destination, uint32_t& ifIndex); -+ bool Ipv4RoutingProtocol::RequestInterface (Ipv4Address destination, uint32_t& interface); -(N.B. this particular function will be later renamed to RouteOutput() in the -proposed IPv4 routing refactoring) - -- uint32_t Ipv4::GetIfIndexByAddress (Ipv4Address addr, Ipv4Mask mask); -+ int_32t Ipv4::GetInterfaceForAddress (Ipv4Address address, Ipv4Mask mask) const; - -- bool Ipv4::GetIfIndexForDestination (Ipv4Address dest, uint32_t &ifIndex) const; -+ bool Ipv4::GetInterfaceForDestination (Ipv4Address dest, uint32_t &interface) const; -(N.B. this function is not needed in the proposed Ipv4 routing refactoring) - - -New public API or classes (src/node) --------- - -None. - -Changed private API (src/internet-node) --------- - -(similar API changes to the IPv4 implementation classes instantiating -the above public API) - -New private API or classes (src/internet-node) --------- - -None. - - -======================================================================== - -2. Changeset: e493e80274bd (implementation added in parallel) - Changeset: db81fdcb06e7 (cut over of client code, remove old code) - -Synopsis: --------- -- allow multiple IPv4 addresses to be assigned to an interface (bug 188) - -Changed public API: --------- - -We now have a new class and methods to account for the possibility of having -multiple IP addresses on an interface: - -+ virtual uint32_t AddAddress (uint32_t interface, Ipv4InterfaceAddress address) = 0; -+ virtual Ipv4InterfaceAddress GetAddress (uint32_t interface, uint32_t addressIndex) const = 0; -+ virtual uint32_t GetNAddresses (uint32_t interface) const = 0; - -Regarding legacy API usage, typically where you once did the following, -using the public Ipv4 class interface (e.g.): - - ipv4A->SetAddress (ifIndexA, Ipv4Address ("172.16.1.1")); - ipv4A->SetNetworkMask (ifIndexA, Ipv4Mask ("255.255.255.255")); - -you now do: - - Ipv4InterfaceAddress ipv4IfAddrA = Ipv4InterfaceAddress (Ipv4Address ("172.16.1.1"), Ipv4Mask ("255.255.255.255")); - ipv4A->AddAddress (ifIndexA, ipv4IfAddrA); - - -At the helper API level, one often gets an address from an interface -container. We preserve the legacy GetAddress (uint32_t i) but it -is documented that this will return only the first (address index 0) -address on the interface, if there are multiple such addresses. -We provide also an overloaded variant for the multi-address case: - -Ipv4Address Ipv4InterfaceContainer::GetAddress (uint32_t i) -+ Ipv4Address Ipv4InterfaceContainer::GetAddress (uint32_t i, uint32_t j) - - -New public API or classes (src/node) --------- - -class Ipv4InterfaceAddress: This is a new class to parallel Linux -struct in_ifaddr. It holds IP addressing information, including mask, -broadcast address, scope, whether primary or secondary, etc. - -Location: src/node/ipv4-interface-address.h - -======================================================================== - -3. Changeset: 2a05a47dba22 - -Synopsis: --------- -- Remove class Ipv4Impl from src/internet-stack - -Changed public API: --------- - -None - -Changed private API ---------- - -Remove class Ipv4Impl; class Ipv4L3Protocol now inherits from class Ipv4 -allow multiple IPv4 addresses to be assigned to an interface (bug 188) From b5b4532e9fe575d82da3a5773edcf257da48c460 Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Mon, 20 Apr 2009 20:52:51 -0700 Subject: [PATCH 17/22] update CHANGES.html --- CHANGES.html | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/CHANGES.html b/CHANGES.html index 8e9f45398..45a26e499 100644 --- a/CHANGES.html +++ b/CHANGES.html @@ -43,10 +43,79 @@ the cracks, unfortunately. If you, as a user, can suggest improvements to this file based on your experience, please contribute a patch or drop us a note on ns-developers mailing list.

+
+

Changes from ns-3.4 to ns-3.5

+ +

Changes to build system:

+
    +
+ +

New API:

+
    +
+ +

Changes to existing API:

+
    +
  • deconflict NetDevice::ifIndex and Ipv4::ifIndex (bug 85). All function parameters named "ifIndex" that refer +to an Ipv4 interface are instead named "interface". +
    +- static const uint32_t Ipv4RoutingProtocol::IF_INDEX_ANY = 0xffffffff;
    ++ static const uint32_t Ipv4RoutingProtocol::INTERFACE_ANY = 0xffffffff;
    +
    +- bool Ipv4RoutingProtocol::RequestIfIndex (Ipv4Address destination, uint32_t& ifIndex);
    ++ bool Ipv4RoutingProtocol::RequestInterface (Ipv4Address destination, uint32_t& interface);
    +(N.B. this particular function is planned to be renamed to RouteOutput() in the
    +proposed IPv4 routing refactoring)
    +
    +- uint32_t Ipv4::GetIfIndexByAddress (Ipv4Address addr, Ipv4Mask mask);
    ++ int_32t Ipv4::GetInterfaceForAddress (Ipv4Address address, Ipv4Mask mask) const;
    +
    +- bool Ipv4::GetIfIndexForDestination (Ipv4Address dest, uint32_t &ifIndex) const;
    ++ bool Ipv4::GetInterfaceForDestination (Ipv4Address dest, uint32_t &interface) const;
    +(N.B. this function is not needed in the proposed Ipv4 routing refactoring)
    +
    +
  • allow multiple IPv4 addresses to be assigned to an interface (bug 188). +
      +
    • Add class Ipv4InterfaceAddress: +This is a new class to resemble Linux's struct in_ifaddr. It holds IP addressing information, including mask, +broadcast address, scope, whether primary or secondary, etc. +
      ++  virtual uint32_t AddAddress (uint32_t interface, Ipv4InterfaceAddress address) = 0;
      ++  virtual Ipv4InterfaceAddress GetAddress (uint32_t interface, uint32_t addressIndex) const = 0;
      ++  virtual uint32_t GetNAddresses (uint32_t interface) const = 0;
      +
      +
    • Regarding legacy API usage, typically where you once did the following, +using the public Ipv4 class interface (e.g.): +
      +  ipv4A->SetAddress (ifIndexA, Ipv4Address ("172.16.1.1"));
      +  ipv4A->SetNetworkMask (ifIndexA, Ipv4Mask ("255.255.255.255"));
      +
      +you now do: +
      +  Ipv4InterfaceAddress ipv4IfAddrA = Ipv4InterfaceAddress (Ipv4Address ("172.16.1.1"), Ipv4Mask ("255.255.255.255"));
      +  ipv4A->AddAddress (ifIndexA, ipv4IfAddrA);
      +
      +
    • At the helper API level, one often gets an address from an interface +container. We preserve the legacy GetAddress (uint32_t i) but it +is documented that this will return only the first (address index 0) +address on the interface, if there are multiple such addresses. +We provide also an overloaded variant for the multi-address case: + +
      +Ipv4Address Ipv4InterfaceContainer::GetAddress (uint32_t i)
      ++ Ipv4Address Ipv4InterfaceContainer::GetAddress (uint32_t i, uint32_t j)
      +
      +
    +
+ +

Changed behavior:

+
    +
+

Changes from ns-3.3 to ns-3.4

-

Changes to build system

+

Changes to build system:

  • A major option regarding the downloading and building of ns-3 has been added for ns-3.4 -- the ns-3-allinone feature. This allows a user to From 7004b72781ee2e353c26e95317258543ee7d6138 Mon Sep 17 00:00:00 2001 From: Gustavo Carneiro Date: Tue, 21 Apr 2009 09:58:58 +0200 Subject: [PATCH 18/22] bug 553: Running code built with a special gcc --- wscript | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/wscript b/wscript index d5d8e4aca..bcbc00864 100644 --- a/wscript +++ b/wscript @@ -251,6 +251,11 @@ def configure(conf): env.append_value("LINKFLAGS", "-Wl,--enable-runtime-pseudo-reloc") elif sys.platform == 'cygwin': env.append_value("LINKFLAGS", "-Wl,--enable-auto-import") + cxx, = env['CXX'] + p = subprocess.Popen([cxx, '-print-file-name=libstdc++.so'], stdout=subprocess.PIPE) + libstdcxx = p.stdout.read().strip() + p.wait() + conf.env.append_value('NS3_MODULE_PATH', os.path.dirname(libstdcxx)) conf.sub_config('src') conf.sub_config('utils') From 44afc7b4133089721054acb5f4446ea97b878bb6 Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Tue, 21 Apr 2009 11:18:05 +0200 Subject: [PATCH 19/22] remove dead code --- src/wscript | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/wscript b/src/wscript index 166d9eaa2..d4ee847bd 100644 --- a/src/wscript +++ b/src/wscript @@ -82,10 +82,6 @@ def create_obj(bld, *args): return bld.new_task_gen(*args) def build(bld): - #Object.register('ns3header', Ns3Header) - #Action.Action('ns3header', func=_ns3_headers_inst, color='BLUE') - #Object.register('ns3-module-header', Ns3ModuleHeader) - #Action.Action('gen-ns3-module-header', func=gen_ns3_module_header, color='BLUE') bld.create_ns3_module = types.MethodType(create_ns3_module, bld) bld.create_obj = types.MethodType(create_obj, bld) From 168515d84240a4fe0d7583f2dcca51d4ea9e3cdc Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Tue, 21 Apr 2009 10:55:07 +0100 Subject: [PATCH 20/22] Make sure the 'g++ -print-file-name' code does not break if gcc doesn't know anything about the libstdc++.so file. --- wscript | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/wscript b/wscript index bcbc00864..255804d93 100644 --- a/wscript +++ b/wscript @@ -253,9 +253,10 @@ def configure(conf): env.append_value("LINKFLAGS", "-Wl,--enable-auto-import") cxx, = env['CXX'] p = subprocess.Popen([cxx, '-print-file-name=libstdc++.so'], stdout=subprocess.PIPE) - libstdcxx = p.stdout.read().strip() + libstdcxx_location = os.path.dirname(p.stdout.read().strip()) p.wait() - conf.env.append_value('NS3_MODULE_PATH', os.path.dirname(libstdcxx)) + if libstdcxx_location: + conf.env.append_value('NS3_MODULE_PATH', libstdcxx_location) conf.sub_config('src') conf.sub_config('utils') From ba5c9355f6008919a9428036357f5d9b867dbaed Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Tue, 21 Apr 2009 11:13:19 +0100 Subject: [PATCH 21/22] Force valgrind to not be used for Python tests --- regression.py | 4 ++-- wscript | 3 ++- wutils.py | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/regression.py b/regression.py index 653731cc5..4ec4fba85 100644 --- a/regression.py +++ b/regression.py @@ -159,7 +159,7 @@ class regression_test_task(Task.TaskBase): script = os.path.abspath(os.path.join('..', *os.path.split(program))) argv = [self.env['PYTHON'], script] + arguments try: - wutils.run_argv(argv, self.env, cwd=trace_output_path) + wutils.run_argv(argv, self.env, cwd=trace_output_path, force_no_valgrind=True) except Utils.WafError, ex: print >> sys.stderr, ex return 1 @@ -191,7 +191,7 @@ class regression_test_task(Task.TaskBase): script = os.path.abspath(os.path.join('..', *os.path.split(program))) argv = [self.env['PYTHON'], script] + arguments try: - retval = wutils.run_argv(argv, self.env, cwd=trace_output_path) + retval = wutils.run_argv(argv, self.env, cwd=trace_output_path, force_no_valgrind=True) except Utils.WafError, ex: print >> sys.stderr, ex return 1 diff --git a/wscript b/wscript index 255804d93..0b91d8a67 100644 --- a/wscript +++ b/wscript @@ -525,7 +525,8 @@ def check(bld): if env['ENABLE_PYTHON_BINDINGS']: print "-- Running NS-3 Python bindings unit tests..." - wutils.run_argv([env['PYTHON'], os.path.join("utils", "python-unit-tests.py")], env, proc_env) + wutils.run_argv([env['PYTHON'], os.path.join("utils", "python-unit-tests.py")], + env, proc_env, force_no_valgrind=True) else: print "-- Skipping NS-3 Python bindings unit tests: Python bindings not enabled." diff --git a/wutils.py b/wutils.py index d82fe305d..094c82322 100644 --- a/wutils.py +++ b/wutils.py @@ -114,9 +114,9 @@ def get_proc_env(os_env=None): return proc_env -def run_argv(argv, env, os_env=None, cwd=None): +def run_argv(argv, env, os_env=None, cwd=None, force_no_valgrind=False): proc_env = get_proc_env(os_env) - if Options.options.valgrind: + if Options.options.valgrind and not force_no_valgrind: if Options.options.command_template: raise Utils.WafError("Options --command-template and --valgrind are conflicting") if not env['VALGRIND']: From b317ef997a65503d493051d921d0c5877f6e8c48 Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Tue, 21 Apr 2009 12:32:05 +0200 Subject: [PATCH 22/22] don't link the tap-creator helper into the ns3 library --- src/devices/tap-bridge/wscript | 1 - 1 file changed, 1 deletion(-) diff --git a/src/devices/tap-bridge/wscript b/src/devices/tap-bridge/wscript index 81db5e4ba..0939c1a98 100644 --- a/src/devices/tap-bridge/wscript +++ b/src/devices/tap-bridge/wscript @@ -27,7 +27,6 @@ def build(bld): module.source.extend([ 'tap-bridge.cc', 'tap-encode-decode.cc', - 'tap-creator.cc', ]) headers.source.extend([ 'tap-bridge.h',