changeset: 10555:f10e3d7e0dc3 user: Tom Goff date: Fri Jan 03 16:57:59 2014 -0800 files: src/internet/model/ipv4-l3-protocol.cc src/internet/model/ipv6-l3-protocol.cc src/internet/model/udp-socket-impl.cc src/network/model/socket.cc src/network/model/socket.h description: Implement IP multicast loopback. Loopback is controlled by the UdpSocket IpMulticastLoop attribute. diff --git a/src/internet/model/ipv4-l3-protocol.cc b/src/internet/model/ipv4-l3-protocol.cc --- a/src/internet/model/ipv4-l3-protocol.cc +++ b/src/internet/model/ipv4-l3-protocol.cc @@ -573,6 +573,22 @@ tos = ipTosTag.GetTos (); } + if (destination.IsMulticast ()) + { + SocketIpMulticastLoopTag ipMulticastLoopTag; + found = packet->RemovePacketTag (ipMulticastLoopTag); + if (found && ipMulticastLoopTag.IsEnabled ()) + { + Ptr rtentry = Create (); + rtentry->SetSource (source); + rtentry->SetDestination (destination); + rtentry->SetGateway (Ipv4Address::GetAny ()); + rtentry->SetOutputDevice (m_node->GetLoopbackDevice ()); + + SendRealOut (rtentry, packet->Copy (), BuildHeader (source, destination, protocol, packet->GetSize (), ttl, tos, mayFragment)); + } + } + // Handle a few cases: // 1) packet is destined to limited broadcast address // 2) packet is destined to a subnet-directed broadcast address diff --git a/src/internet/model/ipv6-l3-protocol.cc b/src/internet/model/ipv6-l3-protocol.cc --- a/src/internet/model/ipv6-l3-protocol.cc +++ b/src/internet/model/ipv6-l3-protocol.cc @@ -720,6 +720,22 @@ tclass = tclassTag.GetTclass (); } + if (destination.IsMulticast ()) + { + SocketIpMulticastLoopTag ipMulticastLoopTag; + found = packet->RemovePacketTag (ipMulticastLoopTag); + if (found && ipMulticastLoopTag.IsEnabled ()) + { + Ptr rtentry = Create (); + rtentry->SetSource (source); + rtentry->SetDestination (destination); + rtentry->SetGateway (Ipv6Address::GetAny ()); + rtentry->SetOutputDevice (m_node->GetLoopbackDevice ()); + + SendRealOut (rtentry, packet->Copy (), BuildHeader (source, destination, protocol, packet->GetSize (), ttl, tclass)); + } + } + /* Handle 3 cases: * 1) Packet is passed in with a route entry * 2) Packet is passed in with a route entry but route->GetGateway is not set (e.g., same network) diff --git a/src/internet/model/udp-socket-impl.cc b/src/internet/model/udp-socket-impl.cc --- a/src/internet/model/udp-socket-impl.cc +++ b/src/internet/model/udp-socket-impl.cc @@ -519,6 +519,14 @@ p->AddPacketTag (tag); } } + + if (dest.IsMulticast () && m_ipMulticastLoop) + { + SocketIpMulticastLoopTag tag; + tag.Enable (); + p->AddPacketTag (tag); + } + // // If dest is set to the limited broadcast address (all ones), // convert it to send a copy of the packet out of every @@ -698,6 +706,14 @@ tag.SetHopLimit (GetIpv6HopLimit ()); p->AddPacketTag (tag); } + + if (dest.IsMulticast () && m_ipMulticastLoop) + { + SocketIpMulticastLoopTag tag; + tag.Enable (); + p->AddPacketTag (tag); + } + // There is no analgous to an IPv4 broadcast address in IPv6. // Instead, we use a set of link-local, site-local, and global // multicast addresses. The Ipv6 routing layers should all diff --git a/src/network/model/socket.cc b/src/network/model/socket.cc --- a/src/network/model/socket.cc +++ b/src/network/model/socket.cc @@ -868,4 +868,68 @@ os << "IPV6_TCLASS = " << m_ipv6Tclass; } +SocketIpMulticastLoopTag::SocketIpMulticastLoopTag () : + m_multicastLoop (false) +{ + NS_LOG_FUNCTION (this); +} +void +SocketIpMulticastLoopTag::Enable (void) +{ + NS_LOG_FUNCTION (this); + m_multicastLoop = true; +} +void +SocketIpMulticastLoopTag::Disable (void) +{ + NS_LOG_FUNCTION (this); + m_multicastLoop = false; +} +bool +SocketIpMulticastLoopTag::IsEnabled (void) const +{ + NS_LOG_FUNCTION (this); + return m_multicastLoop; +} + +NS_OBJECT_ENSURE_REGISTERED (SocketIpMulticastLoopTag); + +TypeId +SocketIpMulticastLoopTag::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::SocketIpMulticastLoopTag") + .SetParent () + .AddConstructor (); + return tid; +} +TypeId +SocketIpMulticastLoopTag::GetInstanceTypeId (void) const +{ + return GetTypeId (); +} +uint32_t +SocketIpMulticastLoopTag::GetSerializedSize (void) const +{ + NS_LOG_FUNCTION (this); + return 1; +} +void +SocketIpMulticastLoopTag::Serialize (TagBuffer i) const +{ + NS_LOG_FUNCTION (this << &i); + i.WriteU8 (m_multicastLoop ? 1 : 0); +} +void +SocketIpMulticastLoopTag::Deserialize (TagBuffer i) +{ + NS_LOG_FUNCTION (this << &i); + m_multicastLoop = (i.ReadU8 () == 1) ? true : false; +} +void +SocketIpMulticastLoopTag::Print (std::ostream &os) const +{ + NS_LOG_FUNCTION (this << &os); + os << (m_multicastLoop ? "true" : "false"); +} + } // namespace ns3 diff --git a/src/network/model/socket.h b/src/network/model/socket.h --- a/src/network/model/socket.h +++ b/src/network/model/socket.h @@ -1229,6 +1229,28 @@ uint8_t m_ipv6Tclass; //!< the Tclass carried by the tag }; +/** + * \brief indicated whether multicast packets should be looped back to + * local sockets. + */ +class SocketIpMulticastLoopTag : public Tag +{ +public: + SocketIpMulticastLoopTag (); + void Enable (void); + void Disable (void); + bool IsEnabled (void) const; + + static TypeId GetTypeId (void); + virtual TypeId GetInstanceTypeId (void) const; + virtual uint32_t GetSerializedSize (void) const; + virtual void Serialize (TagBuffer i) const; + virtual void Deserialize (TagBuffer i); + virtual void Print (std::ostream &os) const; +private: + bool m_multicastLoop; +}; + } // namespace ns3 #endif /* NS3_SOCKET_H */ changeset: 10554:aba3e6283d45 user: Tom Goff date: Fri Jan 03 16:25:58 2014 -0800 files: src/internet/model/ipv4-interface.cc src/internet/model/ipv4-l3-protocol.cc src/internet/model/ipv6-interface.cc src/internet/model/ipv6-l3-protocol.cc src/internet/model/loopback-net-device.cc src/internet/model/loopback-net-device.h src/internet/wscript src/network/model/loopback-net-device.cc src/network/model/loopback-net-device.h src/network/model/node.cc src/network/model/node.h src/network/wscript copies: src/network/model/loopback-net-device.cc (src/internet/model/loopback-net-device.cc) src/network/model/loopback-net-device.h (src/internet/model/loopback-net-device.h) description: Add a Node::GetLoopbackDevice() method. This also moves loopback network device support from the internet to network module. diff --git a/src/internet/model/ipv4-interface.cc b/src/internet/model/ipv4-interface.cc --- a/src/internet/model/ipv4-interface.cc +++ b/src/internet/model/ipv4-interface.cc @@ -19,7 +19,7 @@ */ #include "ipv4-interface.h" -#include "loopback-net-device.h" +#include "ns3/loopback-net-device.h" #include "ns3/ipv4-address.h" #include "ipv4-l3-protocol.h" #include "arp-l3-protocol.h" diff --git a/src/internet/model/ipv4-l3-protocol.cc b/src/internet/model/ipv4-l3-protocol.cc --- a/src/internet/model/ipv4-l3-protocol.cc +++ b/src/internet/model/ipv4-l3-protocol.cc @@ -33,7 +33,6 @@ #include "ns3/boolean.h" #include "ns3/ipv4-routing-table-entry.h" -#include "loopback-net-device.h" #include "arp-l3-protocol.h" #include "ipv4-l3-protocol.h" #include "icmpv4-l4-protocol.h" @@ -241,20 +240,7 @@ NS_LOG_FUNCTION (this); Ptr interface = CreateObject (); - Ptr device = 0; - // First check whether an existing LoopbackNetDevice exists on the node - for (uint32_t i = 0; i < m_node->GetNDevices (); i++) - { - if ((device = DynamicCast (m_node->GetDevice (i)))) - { - break; - } - } - if (device == 0) - { - device = CreateObject (); - m_node->AddDevice (device); - } + Ptr device = m_node->GetLoopbackDevice (); interface->SetDevice (device); interface->SetNode (m_node); Ipv4InterfaceAddress ifaceAddr = Ipv4InterfaceAddress (Ipv4Address::GetLoopback (), Ipv4Mask::GetLoopback ()); diff --git a/src/internet/model/ipv6-interface.cc b/src/internet/model/ipv6-interface.cc --- a/src/internet/model/ipv6-interface.cc +++ b/src/internet/model/ipv6-interface.cc @@ -24,7 +24,7 @@ #include "ipv6-interface.h" #include "ns3/net-device.h" -#include "loopback-net-device.h" +#include "ns3/loopback-net-device.h" #include "ns3/mac16-address.h" #include "ns3/mac64-address.h" #include "ipv6-l3-protocol.h" diff --git a/src/internet/model/ipv6-l3-protocol.cc b/src/internet/model/ipv6-l3-protocol.cc --- a/src/internet/model/ipv6-l3-protocol.cc +++ b/src/internet/model/ipv6-l3-protocol.cc @@ -30,8 +30,8 @@ #include "ns3/ipv6-route.h" #include "ns3/mac16-address.h" #include "ns3/mac64-address.h" +#include "ns3/mac48-address.h" -#include "loopback-net-device.h" #include "ipv6-l3-protocol.h" #include "ipv6-interface.h" #include "ipv6-raw-socket-impl.h" @@ -523,23 +523,7 @@ { NS_LOG_FUNCTION_NOARGS (); Ptr interface = CreateObject (); - Ptr device = 0; - uint32_t i = 0; - - /* see if we have already an loopback NetDevice */ - for (i = 0; i < m_node->GetNDevices (); i++) - { - if ((device = DynamicCast (m_node->GetDevice (i)))) - { - break; - } - } - - if (device == 0) - { - device = CreateObject (); - m_node->AddDevice (device); - } + Ptr device = m_node->GetLoopbackDevice (); interface->SetDevice (device); interface->SetNode (m_node); diff --git a/src/internet/wscript b/src/internet/wscript --- a/src/internet/wscript +++ b/src/internet/wscript @@ -120,7 +120,6 @@ 'model/ipv4-raw-socket-impl.cc', 'model/icmpv4.cc', 'model/icmpv4-l4-protocol.cc', - 'model/loopback-net-device.cc', 'model/ndisc-cache.cc', 'model/ipv6-interface.cc', 'model/icmpv6-header.cc', @@ -247,7 +246,6 @@ 'model/icmpv6-l4-protocol.h', 'model/ipv6-interface.h', 'model/ndisc-cache.h', - 'model/loopback-net-device.h', 'model/ipv4-packet-info-tag.h', 'model/ipv6-packet-info-tag.h', 'model/ipv4-interface-address.h', diff --git a/src/internet/model/loopback-net-device.cc b/src/network/model/loopback-net-device.cc rename from src/internet/model/loopback-net-device.cc rename to src/network/model/loopback-net-device.cc diff --git a/src/internet/model/loopback-net-device.h b/src/network/model/loopback-net-device.h rename from src/internet/model/loopback-net-device.h rename to src/network/model/loopback-net-device.h diff --git a/src/network/model/node.cc b/src/network/model/node.cc --- a/src/network/model/node.cc +++ b/src/network/model/node.cc @@ -21,6 +21,7 @@ #include "node.h" #include "node-list.h" #include "net-device.h" +#include "loopback-net-device.h" #include "application.h" #include "ns3/packet.h" #include "ns3/simulator.h" @@ -142,6 +143,18 @@ NS_LOG_FUNCTION (this); return m_devices.size (); } +Ptr +Node::GetLoopbackDevice () +{ + NS_LOG_FUNCTION (this); + if (!m_loopbackDevice) + { + Ptr device = CreateObject (); + AddDevice (device); + m_loopbackDevice = device; + } + return m_loopbackDevice; +} uint32_t Node::AddApplication (Ptr application) diff --git a/src/network/model/node.h b/src/network/model/node.h --- a/src/network/model/node.h +++ b/src/network/model/node.h @@ -100,6 +100,10 @@ * to this Node. */ uint32_t GetNDevices (void) const; + /** + * \returns the LoopbackNetDevice associated with this Node. + */ + Ptr GetLoopbackDevice (); /** * \param application Application to associate to this node. @@ -224,6 +228,7 @@ uint32_t m_id; // Node id for this node uint32_t m_sid; // System id for this node + Ptr m_loopbackDevice; std::vector > m_devices; std::vector > m_applications; ProtocolHandlerList m_handlers; diff --git a/src/network/wscript b/src/network/wscript --- a/src/network/wscript +++ b/src/network/wscript @@ -15,6 +15,7 @@ 'model/node.cc', 'model/node-list.cc', 'model/net-device.cc', + 'model/loopback-net-device.cc', 'model/packet.cc', 'model/packet-metadata.cc', 'model/packet-tag-list.cc', @@ -89,6 +90,7 @@ 'model/chunk.h', 'model/header.h', 'model/net-device.h', + 'model/loopback-net-device.h', 'model/nix-vector.h', 'model/node.h', 'model/node-list.h',