add ipv4 methods, remove source multicast route requirement, fix udp socket source address prob
--- a/examples/csma-multicast.cc Fri Aug 24 13:29:51 2007 -0700
+++ b/examples/csma-multicast.cc Fri Aug 24 16:57:54 2007 -0700
@@ -84,6 +84,21 @@
DebugComponentEnable("ArpIpv4Interface");
DebugComponentEnable("Ipv4LoopbackInterface");
#endif
+
+ DebugComponentEnable("Channel");
+ DebugComponentEnable("CsmaChannel");
+ DebugComponentEnable("CsmaMulticast");
+ DebugComponentEnable("CsmaNetDevice");
+ DebugComponentEnable("OnOffApplication");
+ DebugComponentEnable("PacketSocket");
+ DebugComponentEnable("UdpSocket");
+ DebugComponentEnable("UdpL4Protocol");
+ DebugComponentEnable("Ipv4L3Protocol");
+ DebugComponentEnable("Ipv4StaticRouting");
+ DebugComponentEnable("Ipv4Interface");
+ DebugComponentEnable("ArpIpv4Interface");
+ DebugComponentEnable("Ipv4LoopbackInterface");
+
//
// Set up default values for the simulation. Use the DefaultValue::Bind()
// technique to tell the system what subclass of Queue to use. The Bind
@@ -151,56 +166,32 @@
// We've got the "hardware" in place. Now we need to add IP addresses.
//
NS_DEBUG("Assign IP Addresses.");
-//
-// XXX BUGBUG
-// Need a better way to get the interface index. The point-to-point topology
-// as implemented can't return the index since it creates interfaces on both
-// sides (i.e., it does AddIpv4Addresses, not AddIpv4Address). We need a
-// method on Ipv4 to find the interface index corresponding to a given ipv4
-// address.
+
+ CsmaIpv4Topology::AddIpv4Address (n0, nd0, Ipv4Address ("10.1.1.1"),
+ Ipv4Mask ("255.255.255.0"));
+
+ CsmaIpv4Topology::AddIpv4Address (n1, nd1, Ipv4Address ("10.1.1.2"),
+ Ipv4Mask ("255.255.255.0"));
+
//
-// First, assign IP addresses to the net devices and associated interfaces
-// on Lan0. The AddIpv4Address method returns an Ipv4 interface index.
-// Interpret ifIndexNd0 as the interface index to use to reference the
-// net device we created on node zero when coming in from the Ipv4 interface.
-// Net device numbers and interface indices are distinct. Interpret
-// ifIndexNd2Lan0 as the interface index to use to reference the
-// net device we created that connects node two to lan zero.
+// We'll need these addresses later
//
- uint32_t ifIndexNd0 = CsmaIpv4Topology::AddIpv4Address (n0, nd0,
- Ipv4Address ("10.1.1.1"), Ipv4Mask ("255.255.255.0"));
+ Ipv4Address n2Lan0Addr ("10.1.1.3");
+ Ipv4Address n2Lan1Addr ("10.1.2.1");
- uint32_t ifIndexNd1 = CsmaIpv4Topology::AddIpv4Address (n1, nd1,
- Ipv4Address ("10.1.1.2"), Ipv4Mask ("255.255.255.0"));
-
- uint32_t ifIndexNd2Lan0 = CsmaIpv4Topology::AddIpv4Address (n2, nd2Lan0,
- Ipv4Address ("10.1.1.3"), Ipv4Mask ("255.255.255.0"));
+ CsmaIpv4Topology::AddIpv4Address (n2, nd2Lan0, n2Lan0Addr,
+ Ipv4Mask ("255.255.255.0"));
//
// Assign IP addresses to the net devices and associated interfaces on Lan1
//
- uint32_t ifIndexNd2Lan1 = CsmaIpv4Topology::AddIpv4Address (n2, nd2Lan1,
- Ipv4Address ("10.1.2.1"), Ipv4Mask ("255.255.255.0"));
-
- uint32_t ifIndexNd3 = CsmaIpv4Topology::AddIpv4Address (n3, nd1,
- Ipv4Address ("10.1.2.2"), Ipv4Mask ("255.255.255.0"));
-
- uint32_t ifIndexNd4 = CsmaIpv4Topology::AddIpv4Address (n4, nd4,
- Ipv4Address ("10.1.2.3"), Ipv4Mask ("255.255.255.0"));
+ CsmaIpv4Topology::AddIpv4Address (n2, nd2Lan1, n2Lan1Addr,
+ Ipv4Mask ("255.255.255.0"));
- NS_DEBUG ("ifIndexNd0 = " << ifIndexNd0);
- NS_DEBUG ("ifIndexNd1 = " << ifIndexNd1);
- NS_DEBUG ("ifIndexNd2Lan0 = " << ifIndexNd2Lan0);
- NS_DEBUG ("ifIndexNd2Lan1 = " << ifIndexNd2Lan1);
- NS_DEBUG ("ifIndexNd3 = " << ifIndexNd3);
- NS_DEBUG ("ifIndexNd4 = " << ifIndexNd4);
-//
-// A little silliness to let optimized code work while still printing all
-// results in debug code (without attribute).
-//
- nd3 = nd3;
- ifIndexNd1 = ifIndexNd1;
- ifIndexNd3 = ifIndexNd3;
- ifIndexNd4 = ifIndexNd4;
+ CsmaIpv4Topology::AddIpv4Address (n3, nd1, Ipv4Address ("10.1.2.2"),
+ Ipv4Mask ("255.255.255.0"));
+
+ CsmaIpv4Topology::AddIpv4Address (n4, nd4, Ipv4Address ("10.1.2.3"),
+ Ipv4Mask ("255.255.255.0"));
NS_DEBUG("Configure multicasting.");
//
@@ -216,34 +207,35 @@
//
// We are going to manually configure multicast routing. This means telling
// node two that it should expect multicast data coming from IP address
-// 10.1.1.1 over its IP interface connected to Lan0. These are called
-// multicastSource and ifIndexNd2Lan0 respectively. When node two receives
-// these packets, they should be forwarded out the interface that connects it
-// to Lan1 which is called ifIndexNd2Lan1. All we need to do is to call the
-// AddMulticastRoute method on node two's Ipv4 interface and provide this
-// information. (Note: the vector of output interfaces is in case there are
-// multiple net devices on a node).
+// 10.1.1.1 originally. It should expect these data coming in over its IP
+// interface connected to Lan0. When node two receives these packets, they
+// should be forwarded out the interface that connects it to Lan1.
+//
+// We're going to need the interface indices on node two corresponding to
+// these interfaces, which we call ifIndexLan0 and ifIndexLan1. The most
+// general way to get these interfaces is to look them up by IP address.
+// Looking back to the topology creation calls above, we saved the addresses
+// assigned to the interface connecting node two to Lan0 and Lan1. Now is
+// a fine time to find the interface indices on node two.
//
Ptr<Ipv4> ipv4;
ipv4 = n2->QueryInterface<Ipv4> (Ipv4::iid);
- std::vector<uint32_t> outputInterfaces (1);
- outputInterfaces[0] = ifIndexNd2Lan1;
-
- ipv4->AddMulticastRoute (multicastSource, multicastGroup, ifIndexNd2Lan0,
- outputInterfaces);
+ uint32_t ifIndexLan0 = ipv4->FindInterfaceForAddr(n2Lan0Addr);
+ uint32_t ifIndexLan1 = ipv4->FindInterfaceForAddr(n2Lan1Addr);
//
-// We also need to explain to the node zero forwarding code that when it sees
-// a packet destined for the multicast group it needs to send it out its
-// one and only interface. The 0xffffffff in the call means that the input
-// interface qualification is not applicable in this case (the packet has
-// not been received over an interface, it has been created locally).
+// Now, we need to do is to call the AddMulticastRoute () method on node
+// two's Ipv4 interface and tell it that whenever it receives a packet on
+// the interface from Lan0, with the packet from the multicast source,
+// destined for the multicast group, it should forward these packets down
+// the interface connecting it to Lan1. (Note: the vector of output
+// interfaces is in case there are multiple net devices on a node -- not
+// true in this case).
//
- ipv4 = n0->QueryInterface<Ipv4> (Ipv4::iid);
+ std::vector<uint32_t> outputInterfaces (1);
+ outputInterfaces[0] = ifIndexLan1;
- outputInterfaces[0] = ifIndexNd0;;
-
- ipv4->AddMulticastRoute (multicastSource, multicastGroup, 0xffffffff,
+ ipv4->AddMulticastRoute (multicastSource, multicastGroup, ifIndexLan0,
outputInterfaces);
//
// As described above, node four will be the only node listening for the
--- a/src/internet-node/ipv4-impl.cc Fri Aug 24 13:29:51 2007 -0700
+++ b/src/internet-node/ipv4-impl.cc Fri Aug 24 16:57:54 2007 -0700
@@ -136,11 +136,25 @@
{
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);
+}
+
Ptr<NetDevice>
Ipv4Impl::GetNetDevice (uint32_t i)
{
--- a/src/internet-node/ipv4-impl.h Fri Aug 24 13:29:51 2007 -0700
+++ b/src/internet-node/ipv4-impl.h Fri Aug 24 16:57:54 2007 -0700
@@ -72,6 +72,11 @@
virtual uint32_t AddInterface (Ptr<NetDevice> device);
virtual uint32_t GetNInterfaces (void);
+
+ virtual uint32_t FindInterfaceForAddr (Ipv4Address addr) const;
+ virtual uint32_t FindInterfaceForAddr (Ipv4Address addr,
+ Ipv4Mask mask) const;
+
virtual Ptr<NetDevice> GetNetDevice(uint32_t i);
virtual void JoinMulticastGroup (Ipv4Address origin, Ipv4Address group);
--- a/src/internet-node/ipv4-l3-protocol.cc Fri Aug 24 13:29:51 2007 -0700
+++ b/src/internet-node/ipv4-l3-protocol.cc Fri Aug 24 16:57:54 2007 -0700
@@ -278,6 +278,33 @@
return;
}
+ if (ipHeader.GetDestination ().IsMulticast () &&
+ ifIndex == Ipv4RoutingProtocol::IF_INDEX_ANY)
+ {
+ NS_DEBUG ("Ipv4L3Protocol::Lookup (): "
+ "Multicast destination with local source");
+//
+// We have a multicast packet originating from the current node. We didn't
+// want to force users to construct a route in order to get packets out of a
+// node, so there will have been no route found and it is left to us to send
+// the packet. What we'll do is to send the multicast out all of the
+// interfaces on this node.
+//
+ NS_DEBUG ("Ipv4StaticRouting::Lookup (): "
+ "Local source. Flooding multicast packet");
+
+ for (uint32_t i = 0; i < GetNInterfaces (); ++i)
+ {
+ Packet p = packet;
+ Ipv4Header h = ipHeader;
+ Ipv4Route route =
+ Ipv4Route::CreateHostRouteTo(h.GetDestination (), i);
+ NS_DEBUG ("Ipv4StaticRouting::Lookup (): "
+ "Send via interface " << i);
+ routeReply (true, route, p, h);
+ }
+ return;
+ }
// No route found
routeReply (false, Ipv4Route (), packet, ipHeader);
}
@@ -399,6 +426,49 @@
return m_nInterfaces;
}
+uint32_t
+Ipv4L3Protocol::FindInterfaceForAddr (Ipv4Address addr) const
+{
+ NS_DEBUG("Ipv4L3Protocol::FindInterfaceForAddr (" << addr << ")");
+
+ uint32_t ifIndex = 0;
+ for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
+ i != m_interfaces.end ();
+ i++, ifIndex++)
+ {
+ if ((*i)->GetAddress () == addr)
+ {
+ return ifIndex;
+ }
+ }
+
+ NS_ASSERT_MSG(false, "Ipv4L3Protocol::FindInterfaceForAddr (): "
+ "Interface not found for IP address");
+ return 0;
+}
+
+uint32_t
+Ipv4L3Protocol::FindInterfaceForAddr (Ipv4Address addr, Ipv4Mask mask) const
+{
+ NS_DEBUG("Ipv4L3Protocol::FindInterfaceForAddr (" << addr << ", " <<
+ mask << ")");
+
+ uint32_t ifIndex = 0;
+ for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
+ i != m_interfaces.end ();
+ i++, ifIndex++)
+ {
+ if ((*i)->GetAddress ().CombineMask (mask) == addr.CombineMask (mask))
+ {
+ return ifIndex;
+ }
+ }
+
+ NS_ASSERT_MSG(false, "Ipv4L3Protocol::FindInterfaceForAddr (): "
+ "Interface not found for masked IP address");
+ return 0;
+}
+
Ipv4Interface *
Ipv4L3Protocol::FindInterfaceForDevice (Ptr<const NetDevice> device)
{
@@ -713,7 +783,40 @@
return true;
}
}
- return false;
+//
+// If there's no routing table entry telling us what single interface will be
+// used to send a packet to this destination, we'll have to just pick one.
+// If there's only one interface on this node, a good answer isn't very hard
+// to come up with. Before jumping to any conclusions, remember that the
+// zeroth interface is the loopback interface, so what we actually want is
+// a situation where there are exactly two interfaces on the node, in which
+// case interface one is the "single" interface.
+//
+ if (GetNInterfaces () == 2)
+ {
+ NS_DEBUG("Ipv4L3Protocol::GetIfIndexForDestination (): "
+ "One Interface. Using interface 1.");
+ ifIndex = 1;
+ return true;
+ }
+//
+// If we fall through to here, we have a node with multiple interfaces and
+// no routes to guide us in determining what interface to choose. The last
+// choice is to use the one set in the default route.
+//
+ NS_DEBUG("Ipv4L3Protocol::GetIfIndexForDestination (): "
+ "Using default route");
+ Ipv4Route *route = m_staticRouting->GetDefaultRoute ();
+
+ NS_ASSERT_MSG(route,
+ "Ipv4L3Protocol::GetIfIndexForDestination (): "
+ "Unable to determine outbound interface. No default route set");
+
+ ifIndex = route->GetInterface ();
+
+ NS_DEBUG("Ipv4L3Protocol::GetIfIndexForDestination (): "
+ "Default route specifies interface " << ifIndex);
+ return true;
}
uint16_t
--- a/src/internet-node/ipv4-l3-protocol.h Fri Aug 24 13:29:51 2007 -0700
+++ b/src/internet-node/ipv4-l3-protocol.h Fri Aug 24 16:57:54 2007 -0700
@@ -174,9 +174,12 @@
uint32_t AddInterface (Ptr<NetDevice> device);
Ipv4Interface * GetInterface (uint32_t i) const;
uint32_t GetNInterfaces (void) const;
+
+ uint32_t FindInterfaceForAddr (Ipv4Address addr) const;
+ uint32_t FindInterfaceForAddr (Ipv4Address addr, Ipv4Mask mask) const;
- virtual void JoinMulticastGroup (Ipv4Address origin, Ipv4Address group);
- virtual void LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group);
+ void JoinMulticastGroup (Ipv4Address origin, Ipv4Address group);
+ void LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group);
void SetAddress (uint32_t i, Ipv4Address address);
void SetNetworkMask (uint32_t i, Ipv4Mask mask);
--- a/src/internet-node/ipv4-static-routing.cc Fri Aug 24 13:29:51 2007 -0700
+++ b/src/internet-node/ipv4-static-routing.cc Fri Aug 24 16:57:54 2007 -0700
@@ -230,6 +230,20 @@
n += m_networkRoutes.size ();
return n;
}
+
+Ipv4Route *
+Ipv4StaticRouting::GetDefaultRoute ()
+{
+ if (m_defaultRoute != 0)
+ {
+ return m_defaultRoute;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
Ipv4Route *
Ipv4StaticRouting::GetRoute (uint32_t index)
{
@@ -331,14 +345,37 @@
NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): destination = " <<
ipHeader.GetDestination ());
-//
-// 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.
-//
+
if (ipHeader.GetDestination ().IsMulticast ())
{
NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): Multicast destination");
-
+//
+// We have a multicast packet we're going to send. There are two distinct
+// cases we need to support. The first is if the current node is the source
+// of the packet. In that case, we don't want to have to consult multicast
+// routing tables (nor build them) in order to send multicasts. The interface
+// index (ifIndex) is Ipv4RoutingProtocol::IF_INDEX_ANY if we're the source.
+//
+// The second case is if the current packet has gotten to us by being
+// received over one of our interfaces. In this case, ifIndex is set to the
+// index over which we received the packet. For these packets, we need to
+// consult the multicast routing table for a disposition.
+//
+// So, first let's see if we're the source. In this case, we don't consult
+// the routing tables, but just return false and let the caller (up in
+// ipv4-l3-protocol) flood the multicast packet out of all of its interfaces.
+// We can't really do it here even if we wanted to since we have no easy way
+// to get to the Ipv4 interface which we would need.
+//
+ if (ifIndex == Ipv4RoutingProtocol::IF_INDEX_ANY)
+ {
+ return false;
+ }
+//
+// If we fall through to this point, we have a multicast packet that has
+// not originated at this node. We need to deal with forwarding. Let's
+// see if we have a route, and if so go ahead and forward this puppy.
+//
Ipv4MulticastRoute *mRoute = LookupStatic(ipHeader.GetSource (),
ipHeader.GetDestination (), ifIndex);
@@ -349,14 +386,15 @@
for (uint32_t i = 0; i < mRoute->GetNOutputInterfaces (); ++i)
{
Packet p = packet;
+ Ipv4Header h = ipHeader;
Ipv4Route route =
- Ipv4Route::CreateHostRouteTo(ipHeader.GetDestination (),
+ Ipv4Route::CreateHostRouteTo(h.GetDestination (),
mRoute->GetOutputInterface(i));
NS_DEBUG ("Ipv4StaticRouting::RequestRoute (): "
"Send via interface " << mRoute->GetOutputInterface(i));
- routeReply (true, route, p, ipHeader);
- return true;
+ routeReply (true, route, p, h);
}
+ return true;
}
return false; // Let other routing protocols try to handle this
}
--- a/src/internet-node/ipv4-static-routing.h Fri Aug 24 13:29:51 2007 -0700
+++ b/src/internet-node/ipv4-static-routing.h Fri Aug 24 16:57:54 2007 -0700
@@ -74,6 +74,7 @@
void SetDefaultRoute (Ipv4Address nextHop,
uint32_t interface);
uint32_t GetNRoutes (void);
+ Ipv4Route *GetDefaultRoute (void);
Ipv4Route *GetRoute (uint32_t i);
void RemoveRoute (uint32_t i);
--- a/src/internet-node/udp-socket.cc Fri Aug 24 13:29:51 2007 -0700
+++ b/src/internet-node/udp-socket.cc Fri Aug 24 16:57:54 2007 -0700
@@ -182,10 +182,11 @@
NotifyConnectionSucceeded ();
m_connected = true;
+ NS_DEBUG ("UdpSocket::Connect (): Updating local address");
Ptr<Ipv4> ipv4;
ipv4 = m_node->QueryInterface<Ipv4> (Ipv4::iid);
m_endPoint->SetLocalAddress (ipv4->GetSourceAddress(m_defaultAddress));
- NS_DEBUG ("UdpSocket::Connect (): Local address is" <<
+ NS_DEBUG ("UdpSocket::Connect (): Local address is " <<
m_endPoint->GetLocalAddress());
return 0;
}
@@ -214,9 +215,9 @@
}
int
-UdpSocket::DoSendTo (const Packet &p, Ipv4Address ipv4, uint16_t port)
+UdpSocket::DoSendTo (const Packet &p, Ipv4Address addr, uint16_t port)
{
- NS_DEBUG("UdpSocket::DoSendTo (" << &p << ", " << ipv4 << ", " <<
+ NS_DEBUG("UdpSocket::DoSendTo (" << &p << ", " << addr << ", " <<
port << ")");
if (m_endPoint == 0)
@@ -234,9 +235,16 @@
return -1;
}
+ NS_DEBUG ("UdpSocket::DoSendTo (): Finding source address");
+ Ptr<Ipv4> ipv4;
+ ipv4 = m_node->QueryInterface<Ipv4> (Ipv4::iid);
+
+ Ipv4Address source = ipv4->GetSourceAddress(m_defaultAddress);
+ NS_DEBUG ("UdpSocket::DoSendTo (): Source address is " << source);
+
NS_DEBUG("UdpSocket::DoSendTo (): Send to UDP");
- m_udp->Send (p, m_endPoint->GetLocalAddress (), ipv4,
- m_endPoint->GetLocalPort (), port);
+ m_udp->Send (p, source, addr, m_endPoint->GetLocalPort (), port);
+
NotifyDataSent (p.GetSize ());
return 0;
}
@@ -245,11 +253,13 @@
UdpSocket::SendTo(const Address &address, const Packet &p)
{
NS_DEBUG("UdpSocket::SendTo (" << address << ", " << &p << ")");
+#if 0
if (m_connected)
{
m_errno = ERROR_ISCONN;
return -1;
}
+#endif
InetSocketAddress transport = InetSocketAddress::ConvertFrom (address);
Ipv4Address ipv4 = transport.GetIpv4 ();
uint16_t port = transport.GetPort ();
--- a/src/node/ipv4.h Fri Aug 24 13:29:51 2007 -0700
+++ b/src/node/ipv4.h Fri Aug 24 16:57:54 2007 -0700
@@ -275,6 +275,36 @@
virtual uint32_t GetNInterfaces (void) = 0;
/**
+ * \brief Find and return the interface ID of the interface that has been
+ * assigned the specified IP address.
+ * \param addr The IP address assigned to the interface of interest.
+ * \returns The index of the ipv4 interface with the given address.
+ *
+ * Each IP interface has an IP address associated with it. It is often
+ * useful to search the list of interfaces for one that corresponds to
+ * a known IP Address. This call takes an IP address as a parameter and
+ * returns the interface index of the first interface that has been assigned
+ * that address. If the address is not found, this function asserts.
+ */
+ virtual uint32_t FindInterfaceForAddr (Ipv4Address addr) const = 0;
+
+ /**
+ * \brief Find and return the interface ID of the interface that has been
+ * assigned the specified (masked) IP address.
+ * \param addr The IP address assigned to the interface of interest.
+ * \param mask The address mask to be used in address matching.
+ * \returns The index of the ipv4 interface with the given address.
+ *
+ * Each IP interface has an IP address associated with it. It is often
+ * useful to search the list of interfaces for one that corresponds to
+ * a known IP Address. This call takes an IP address and an IP address
+ * mask as parameters and returns the interface index of the first interface
+ * that matches the masked IP address.
+ */
+ virtual uint32_t FindInterfaceForAddr (Ipv4Address addr,
+ Ipv4Mask mask) const = 0;
+
+ /**
* \param i index of ipv4 interface
* \returns the NetDevice associated with the ipv4 interface index
*/