# HG changeset patch # User Tommaso Pecorella # Date 1449099335 -3600 # Node ID 710f305a22c9a9829362da61a120091c5c34b801 # Parent a745117e5dff125ae2c6d46cfb2f627d882bc680 Bug 2234 - Ipv6L3Protocol should trash multicast packets not interesting for the node diff -r a745117e5dff -r 710f305a22c9 RELEASE_NOTES --- a/RELEASE_NOTES Wed Dec 02 23:37:23 2015 +0100 +++ b/RELEASE_NOTES Thu Dec 03 00:35:35 2015 +0100 @@ -44,6 +44,9 @@ packets directed to the host. - (internet) Ipv6 can now reject packets directed to an address not configured on the interface they are received from (Strong End System Model, RFC 1222). +- (internet) UDP and Ipv6 RAW sockets can now join Ipv6 multicast groups. + Incomin packets will be filtered according to if there's a socket listening to + that group. Source filtering is left to the application. Bugs fixed ---------- @@ -67,6 +70,7 @@ - Bug 2211 - Ipv{4,6}EndPoint can cause memory corruption - Bug 2219 - SixLowPanNetDevice hangs trying to decode a IPv6 Fragment extension header - Bug 2233 - Implement RFC 1222 - Strong End System Model +- Bug 2234 - Ipv6L3Protocol should trash multicast packets not interesting for the node - Bug 2238 - Ipv6 routing reorganization Known issues diff -r a745117e5dff -r 710f305a22c9 src/internet/model/ipv6-interface.cc --- a/src/internet/model/ipv6-interface.cc Wed Dec 02 23:37:23 2015 +0100 +++ b/src/internet/model/ipv6-interface.cc Thu Dec 03 00:35:35 2015 +0100 @@ -94,16 +94,19 @@ { Ipv6InterfaceAddress ifaddr = Ipv6InterfaceAddress (Ipv6Address::MakeAutoconfiguredLinkLocalAddress (Mac64Address::ConvertFrom (addr)), Ipv6Prefix (64)); AddAddress (ifaddr); + m_linkLocalAddress = ifaddr; } else if (Mac48Address::IsMatchingType (addr)) { Ipv6InterfaceAddress ifaddr = Ipv6InterfaceAddress (Ipv6Address::MakeAutoconfiguredLinkLocalAddress (Mac48Address::ConvertFrom (addr)), Ipv6Prefix (64)); AddAddress (ifaddr); + m_linkLocalAddress = ifaddr; } else if (Mac16Address::IsMatchingType (addr)) { Ipv6InterfaceAddress ifaddr = Ipv6InterfaceAddress (Ipv6Address::MakeAutoconfiguredLinkLocalAddress (Mac16Address::ConvertFrom (addr)), Ipv6Prefix (64)); AddAddress (ifaddr); + m_linkLocalAddress = ifaddr; } else { @@ -213,13 +216,14 @@ { for (Ipv6InterfaceAddressListCI it = m_addresses.begin (); it != m_addresses.end (); ++it) { - if ((*it).GetAddress () == addr) + if (it->first.GetAddress () == addr) { return false; } } - m_addresses.push_back (iface); + Ipv6Address solicited = Ipv6Address::MakeSolicitedAddress (iface.GetAddress ()); + m_addresses.push_back (std::make_pair (iface, solicited)); if (!addr.IsAny () || !addr.IsLocalhost ()) { @@ -249,16 +253,23 @@ /* IPv6 interface has always at least one IPv6 link-local address */ NS_LOG_FUNCTION_NOARGS (); + return m_linkLocalAddress; +} + +bool Ipv6Interface::IsSolicitedMulticastAddress (Ipv6Address address) const +{ + /* IPv6 interface has always at least one IPv6 Solicited Multicast address */ + NS_LOG_FUNCTION (this << address); + for (Ipv6InterfaceAddressListCI it = m_addresses.begin (); it != m_addresses.end (); ++it) - { - if ((*it).GetAddress ().IsLinkLocal ()) - { - return (*it); - } - } - NS_ASSERT_MSG (false, "No link-local address on interface " << this); - Ipv6InterfaceAddress addr; - return addr; /* quiet compiler */ + { + if (it->second == address) + { + return true; + } + } + + return false; } Ipv6InterfaceAddress Ipv6Interface::GetAddress (uint32_t index) const @@ -272,7 +283,7 @@ { if (i == index) { - return (*it); + return it->first; } i++; } @@ -303,7 +314,7 @@ { if (i == index) { - Ipv6InterfaceAddress iface = (*it); + Ipv6InterfaceAddress iface = it->first; m_addresses.erase (it); return iface; } @@ -329,9 +340,9 @@ for (Ipv6InterfaceAddressListI it = m_addresses.begin (); it != m_addresses.end (); ++it) { - if((*it).GetAddress() == address) + if(it->first.GetAddress () == address) { - Ipv6InterfaceAddress iface = (*it); + Ipv6InterfaceAddress iface = it->first; m_addresses.erase(it); return iface; } @@ -345,7 +356,7 @@ for (Ipv6InterfaceAddressList::const_iterator it = m_addresses.begin (); it != m_addresses.end (); ++it) { - Ipv6InterfaceAddress ifaddr = (*it); + Ipv6InterfaceAddress ifaddr = it->first; if (ifaddr.GetPrefix ().IsMatch (ifaddr.GetAddress (), dst)) { @@ -381,7 +392,7 @@ /* check if destination is for one of our interface */ for (Ipv6InterfaceAddressListCI it = m_addresses.begin (); it != m_addresses.end (); ++it) { - if (dest == (*it).GetAddress ()) + if (dest == it->first.GetAddress ()) { ipv6->Receive (m_device, p, Ipv6L3Protocol::PROT_NUMBER, m_device->GetBroadcast (), @@ -483,9 +494,9 @@ for (Ipv6InterfaceAddressListI it = m_addresses.begin (); it != m_addresses.end (); ++it) { - if ((*it).GetAddress () == address) + if (it->first.GetAddress () == address) { - (*it).SetState (state); + it->first.SetState (state); return; } } @@ -498,9 +509,9 @@ for (Ipv6InterfaceAddressListI it = m_addresses.begin (); it != m_addresses.end (); ++it) { - if ((*it).GetAddress () == address) + if (it->first.GetAddress () == address) { - (*it).SetNsDadUid (uid); + it->first.SetNsDadUid (uid); return; } } diff -r a745117e5dff -r 710f305a22c9 src/internet/model/ipv6-interface.h --- a/src/internet/model/ipv6-interface.h Wed Dec 02 23:37:23 2015 +0100 +++ b/src/internet/model/ipv6-interface.h Thu Dec 03 00:35:35 2015 +0100 @@ -201,6 +201,13 @@ Ipv6InterfaceAddress GetLinkLocalAddress () const; /** + * \brief Checks if the address is a Solicited Multicast address for this interface. + * \param address the address to check. + * \return true if it is a solicited multicast address. + */ + bool IsSolicitedMulticastAddress (Ipv6Address address) const; + + /** * \brief Get an address from IPv6 interface. * \param index index * \return Ipv6InterfaceAddress address whose index is i @@ -266,17 +273,17 @@ /** * \brief Container for the Ipv6InterfaceAddresses. */ - typedef std::list Ipv6InterfaceAddressList; + typedef std::list > Ipv6InterfaceAddressList; /** * \brief Container Iterator for the Ipv6InterfaceAddresses. */ - typedef std::list::iterator Ipv6InterfaceAddressListI; + typedef std::list >::iterator Ipv6InterfaceAddressListI; /** * \brief Const Container Iterator for the Ipv6InterfaceAddresses. */ - typedef std::list::const_iterator Ipv6InterfaceAddressListCI; + typedef std::list >::const_iterator Ipv6InterfaceAddressListCI; /** * \brief Initialize interface. @@ -289,6 +296,11 @@ Ipv6InterfaceAddressList m_addresses; /** + * \brief The link-local addresses assigned to this interface. + */ + Ipv6InterfaceAddress m_linkLocalAddress; + + /** * \brief The state of this interface. */ bool m_ifup; diff -r a745117e5dff -r 710f305a22c9 src/internet/model/ipv6-l3-protocol.cc --- a/src/internet/model/ipv6-l3-protocol.cc Wed Dec 02 23:37:23 2015 +0100 +++ b/src/internet/model/ipv6-l3-protocol.cc Thu Dec 03 00:35:35 2015 +0100 @@ -534,7 +534,7 @@ } else { - NS_LOG_LOGIC ("Interface " << int(i) << " is set to be down for IPv6. Reason: not respecting minimum IPv6 MTU (1280 octects)"); + NS_LOG_LOGIC ("Interface " << int(i) << " is set to be down for IPv6. Reason: not respecting minimum IPv6 MTU (1280 octets)"); } } @@ -1006,14 +1006,28 @@ } } - // \todo At the moment, forward up any multicast packet. - // This is wrong. We should only forward up what the node is interested into - // and try to route anything other than ff01 or ff02. - if (hdr.GetDestinationAddress ().IsLinkLocalMulticast ()) + if (hdr.GetDestinationAddress ().IsAllNodesMulticast ()) + { + LocalDeliver (packet, hdr, interface); + return; + } + else if (hdr.GetDestinationAddress ().IsAllRoutersMulticast() && ipv6Interface->IsForwarding ()) { LocalDeliver (packet, hdr, interface); return; } + else if (hdr.GetDestinationAddress ().IsMulticast ()) + { + bool isSolicited = ipv6Interface->IsSolicitedMulticastAddress (hdr.GetDestinationAddress ()); + bool isRegisteredOnInterface = IsRegisteredMulticastAddress (hdr.GetDestinationAddress (), interface); + bool isRegisteredGlobally = IsRegisteredMulticastAddress (hdr.GetDestinationAddress ()); + if (isSolicited || isRegisteredGlobally || isRegisteredOnInterface) + { + LocalDeliver (packet, hdr, interface); + // do not return, the packet could be handled by a routing protocol + } + } + for (uint32_t j = 0; j < GetNInterfaces (); j++) { @@ -1494,5 +1508,83 @@ m_dropTrace (ipHeader, p, dropReason, m_node->GetObject (), 0); } +void Ipv6L3Protocol::AddMulticastAddress (Ipv6Address address, uint32_t interface) +{ + NS_LOG_FUNCTION (address << interface); + + if (!address.IsMulticast ()) + { + NS_LOG_WARN ("Not adding a non-multicast address " << address); + return; + } + + Ipv6RegisteredMulticastAddressKey_t key = std::make_pair (address, interface); + m_multicastAddresses[key]++; +} + +void Ipv6L3Protocol::AddMulticastAddress (Ipv6Address address) +{ + NS_LOG_FUNCTION (address); + + if (!address.IsMulticast ()) + { + NS_LOG_WARN ("Not adding a non-multicast address " << address); + return; + } + + m_multicastAddressesNoInterface[address]++; +} + +void Ipv6L3Protocol::RemoveMulticastAddress (Ipv6Address address, uint32_t interface) +{ + NS_LOG_FUNCTION (address << interface); + + Ipv6RegisteredMulticastAddressKey_t key = std::make_pair (address, interface); + + m_multicastAddresses[key]--; + if (m_multicastAddresses[key] == 0) + { + m_multicastAddresses.erase (key); + } +} + +void Ipv6L3Protocol::RemoveMulticastAddress (Ipv6Address address) +{ + NS_LOG_FUNCTION (address); + + m_multicastAddressesNoInterface[address]--; + if (m_multicastAddressesNoInterface[address] == 0) + { + m_multicastAddressesNoInterface.erase (address); + } +} + +bool Ipv6L3Protocol::IsRegisteredMulticastAddress (Ipv6Address address, uint32_t interface) const +{ + NS_LOG_FUNCTION (address << interface); + + Ipv6RegisteredMulticastAddressKey_t key = std::make_pair (address, interface); + Ipv6RegisteredMulticastAddressCIter_t iter = m_multicastAddresses.find (key); + + if (iter == m_multicastAddresses.end ()) + { + return false; + } + return true; +} + +bool Ipv6L3Protocol::IsRegisteredMulticastAddress (Ipv6Address address) const +{ + NS_LOG_FUNCTION (address); + + Ipv6RegisteredMulticastAddressNoInterfaceCIter_t iter = m_multicastAddressesNoInterface.find (address); + + if (iter == m_multicastAddressesNoInterface.end ()) + { + return false; + } + return true; +} + } /* namespace ns3 */ diff -r a745117e5dff -r 710f305a22c9 src/internet/model/ipv6-l3-protocol.h --- a/src/internet/model/ipv6-l3-protocol.h Wed Dec 02 23:37:23 2015 +0100 +++ b/src/internet/model/ipv6-l3-protocol.h Thu Dec 03 00:35:35 2015 +0100 @@ -454,7 +454,48 @@ (const Ipv6Header & header, Ptr packet, DropReason reason, Ptr ipv6, uint32_t interface); - + + /** + * Adds a multicast address to the list of addresses to pass to local deliver. + * \param address the address. + */ + void AddMulticastAddress (Ipv6Address address); + + /** + * Adds a multicast address to the list of addresses to pass to local deliver. + * \param address the address. + * \param interface the incoming interface. + */ + void AddMulticastAddress (Ipv6Address address, uint32_t interface); + + /** + * Removes a multicast address from the list of addresses to pass to local deliver. + * \param address the address. + */ + void RemoveMulticastAddress (Ipv6Address address); + + /** + * Removes a multicast address from the list of addresses to pass to local deliver. + * \param address the address. + * \param interface the incoming interface. + */ + void RemoveMulticastAddress (Ipv6Address address, uint32_t interface); + + /** + * Checks if the address has been registered. + * \param address the address. + * \return true if the address is registered. + */ + bool IsRegisteredMulticastAddress (Ipv6Address address) const; + + /** + * Checks if the address has been registered for a specific interface. + * \param address the address. + * \param interface the incoming interface. + * \return true if the address is registered. + */ + bool IsRegisteredMulticastAddress (Ipv6Address address, uint32_t interface) const; + protected: /** * \brief Dispose object. @@ -718,6 +759,51 @@ * \brief Allow ICMPv6 Redirect sending state */ bool m_sendIcmpv6Redirect; + + /** + * \brief IPv6 multicast addresses / interface key. + */ + typedef std::pair Ipv6RegisteredMulticastAddressKey_t; + + /** + * \brief Container of the IPv6 multicast addresses. + */ + typedef std::map Ipv6RegisteredMulticastAddress_t; + + /** + * \brief Container Iterator of the IPv6 multicast addresses. + */ + typedef std::map::iterator Ipv6RegisteredMulticastAddressIter_t; + + /** + * \brief Container Const Iterator of the IPv6 multicast addresses. + */ + typedef std::map::const_iterator Ipv6RegisteredMulticastAddressCIter_t; + + /** + * \brief Container of the IPv6 multicast addresses. + */ + typedef std::map Ipv6RegisteredMulticastAddressNoInterface_t; + + /** + * \brief Container Iterator of the IPv6 multicast addresses. + */ + typedef std::map::iterator Ipv6RegisteredMulticastAddressNoInterfaceIter_t; + + /** + * \brief Container Const Iterator of the IPv6 multicast addresses. + */ + typedef std::map::const_iterator Ipv6RegisteredMulticastAddressNoInterfaceCIter_t; + + /** + * \brief List of multicast IP addresses of interest, divided per interface. + */ + Ipv6RegisteredMulticastAddress_t m_multicastAddresses; + + /** + * \brief List of multicast IP addresses of interest for all the interfaces. + */ + Ipv6RegisteredMulticastAddressNoInterface_t m_multicastAddressesNoInterface; }; } /* namespace ns3 */ diff -r a745117e5dff -r 710f305a22c9 src/internet/model/ipv6-raw-socket-impl.cc --- a/src/internet/model/ipv6-raw-socket-impl.cc Wed Dec 02 23:37:23 2015 +0100 +++ b/src/internet/model/ipv6-raw-socket-impl.cc Thu Dec 03 00:35:35 2015 +0100 @@ -139,6 +139,7 @@ NS_LOG_FUNCTION_NOARGS (); Ptr ipv6 = m_node->GetObject (); + Ipv6LeaveGroup (); if (ipv6) { ipv6->DeleteRawSocket (this); @@ -297,6 +298,54 @@ return data.packet; } +void +Ipv6RawSocketImpl::Ipv6JoinGroup (Ipv6Address address, Socket::Ipv6MulticastFilterMode filterMode, std::vector sourceAddresses) +{ + NS_LOG_FUNCTION (this << address << &filterMode << &sourceAddresses); + + // We can join only one multicast group (or change its params) + NS_ASSERT_MSG ((m_ipv6MulticastGroupAddress == address || m_ipv6MulticastGroupAddress.IsAny ()), "Can join only one IPv6 multicast group."); + + if (!m_ipv6MulticastGroupAddress.IsAny ()) + { + Ipv6LeaveGroup (); + } + m_ipv6MulticastGroupAddress = address; + + Ptr ipv6l3 = m_node->GetObject (); + if (ipv6l3) + { + if (filterMode == INCLUDE && sourceAddresses.empty ()) + { + // it is a leave + if (m_boundnetdevice) + { + int32_t index = ipv6l3->GetInterfaceForDevice (m_boundnetdevice); + NS_ASSERT_MSG (index >= 0, "Interface without a valid index"); + ipv6l3->RemoveMulticastAddress (address, index); + } + else + { + ipv6l3->RemoveMulticastAddress (address); + } + } + else + { + // it is a join or a modification + if (m_boundnetdevice) + { + int32_t index = ipv6l3->GetInterfaceForDevice (m_boundnetdevice); + NS_ASSERT_MSG (index >= 0, "Interface without a valid index"); + ipv6l3->AddMulticastAddress (address, index); + } + else + { + ipv6l3->AddMulticastAddress (address); + } + } + } +} + uint32_t Ipv6RawSocketImpl::GetTxAvailable () const { NS_LOG_FUNCTION_NOARGS (); diff -r a745117e5dff -r 710f305a22c9 src/internet/model/ipv6-raw-socket-impl.h --- a/src/internet/model/ipv6-raw-socket-impl.h Wed Dec 02 23:37:23 2015 +0100 +++ b/src/internet/model/ipv6-raw-socket-impl.h Thu Dec 03 00:35:35 2015 +0100 @@ -107,6 +107,7 @@ virtual int SendTo (Ptr p, uint32_t flags, const Address& toAddress); virtual Ptr Recv (uint32_t maxSize, uint32_t flags); virtual Ptr RecvFrom (uint32_t maxSize, uint32_t flags, Address& fromAddress); + virtual void Ipv6JoinGroup (Ipv6Address address, Socket::Ipv6MulticastFilterMode filterMode, std::vector sourceAddresses); /** * \brief Set protocol field. diff -r a745117e5dff -r 710f305a22c9 src/internet/model/ripng.cc --- a/src/internet/model/ripng.cc Wed Dec 02 23:37:23 2015 +0100 +++ b/src/internet/model/ripng.cc Thu Dec 03 00:35:35 2015 +0100 @@ -119,6 +119,7 @@ if (m_interfaceExclusions.find (i) == m_interfaceExclusions.end ()) { activeInterface = true; + m_ipv6->SetForwarding (i, true); } for (uint32_t j = 0; j < m_ipv6->GetNAddresses (i); j++) @@ -290,6 +291,7 @@ if (m_interfaceExclusions.find (i) == m_interfaceExclusions.end ()) { activeInterface = true; + m_ipv6->SetForwarding (i, true); } for (uint32_t j = 0; j < m_ipv6->GetNAddresses (i); j++) diff -r a745117e5dff -r 710f305a22c9 src/internet/model/udp-socket-impl.cc --- a/src/internet/model/udp-socket-impl.cc Wed Dec 02 23:37:23 2015 +0100 +++ b/src/internet/model/udp-socket-impl.cc Thu Dec 03 00:35:35 2015 +0100 @@ -26,6 +26,7 @@ #include "ns3/ipv6-route.h" #include "ns3/ipv4.h" #include "ns3/ipv6.h" +#include "ns3/ipv6-l3-protocol.h" #include "ns3/ipv4-header.h" #include "ns3/ipv4-routing-protocol.h" #include "ns3/ipv6-routing-protocol.h" @@ -305,6 +306,14 @@ m_errno = port ? ERROR_ADDRINUSE : ERROR_ADDRNOTAVAIL; return -1; } + if (ipv6.IsMulticast ()) + { + Ptr ipv6l3 = m_node->GetObject (); + if (ipv6l3) + { + ipv6l3->AddMulticastAddress (ipv6); + } + } } else { @@ -349,6 +358,7 @@ m_errno = Socket::ERROR_BADF; return -1; } + Ipv6LeaveGroup (); m_shutdownRecv = true; m_shutdownSend = true; DeallocateEndPoint (); @@ -955,6 +965,18 @@ NS_ASSERT (m_endPoint6 != 0); } m_endPoint6->BindToNetDevice (netdevice); + + if (m_endPoint6->GetLocalAddress ().IsMulticast ()) + { + Ptr ipv6l3 = m_node->GetObject (); + if (ipv6l3) + { + uint32_t index = ipv6l3->GetInterfaceForDevice (netdevice); + ipv6l3->RemoveMulticastAddress (m_endPoint6->GetLocalAddress ()); + ipv6l3->AddMulticastAddress (m_endPoint6->GetLocalAddress (), index); + } + } + return; } @@ -1169,5 +1191,52 @@ return m_allowBroadcast; } +void +UdpSocketImpl::Ipv6JoinGroup (Ipv6Address address, Socket::Ipv6MulticastFilterMode filterMode, std::vector sourceAddresses) +{ + NS_LOG_FUNCTION (this << address << &filterMode << &sourceAddresses); + + // We can join only one multicast group (or change its params) + NS_ASSERT_MSG ((m_ipv6MulticastGroupAddress == address || m_ipv6MulticastGroupAddress.IsAny ()), "Can join only one IPv6 multicast group."); + + if (!m_ipv6MulticastGroupAddress.IsAny ()) + { + Ipv6LeaveGroup (); + } + m_ipv6MulticastGroupAddress = address; + + Ptr ipv6l3 = m_node->GetObject (); + if (ipv6l3) + { + if (filterMode == INCLUDE && sourceAddresses.empty ()) + { + // it is a leave + if (m_boundnetdevice) + { + int32_t index = ipv6l3->GetInterfaceForDevice (m_boundnetdevice); + NS_ASSERT_MSG (index >= 0, "Interface without a valid index"); + ipv6l3->RemoveMulticastAddress (address, index); + } + else + { + ipv6l3->RemoveMulticastAddress (address); + } + } + else + { + // it is a join or a modification + if (m_boundnetdevice) + { + int32_t index = ipv6l3->GetInterfaceForDevice (m_boundnetdevice); + NS_ASSERT_MSG (index >= 0, "Interface without a valid index"); + ipv6l3->AddMulticastAddress (address, index); + } + else + { + ipv6l3->AddMulticastAddress (address); + } + } + } +} } // namespace ns3 diff -r a745117e5dff -r 710f305a22c9 src/internet/model/udp-socket-impl.h --- a/src/internet/model/udp-socket-impl.h Wed Dec 02 23:37:23 2015 +0100 +++ b/src/internet/model/udp-socket-impl.h Thu Dec 03 00:35:35 2015 +0100 @@ -98,6 +98,7 @@ virtual void BindToNetDevice (Ptr netdevice); virtual bool SetAllowBroadcast (bool allowBroadcast); virtual bool GetAllowBroadcast () const; + virtual void Ipv6JoinGroup (Ipv6Address address, Socket::Ipv6MulticastFilterMode filterMode, std::vector sourceAddresses); private: // Attributes set through UdpSocket base class diff -r a745117e5dff -r 710f305a22c9 src/internet/test/ipv6-ripng-test.cc --- a/src/internet/test/ipv6-ripng-test.cc Wed Dec 02 23:37:23 2015 +0100 +++ b/src/internet/test/ipv6-ripng-test.cc Thu Dec 03 00:35:35 2015 +0100 @@ -613,6 +613,7 @@ Ptr rxSocketFactory = listener->GetObject (); Ptr rxSocket = rxSocketFactory->CreateSocket (); NS_TEST_EXPECT_MSG_EQ (rxSocket->Bind (Inet6SocketAddress (Ipv6Address ("ff02::9"), 521)), 0, "trivial"); + rxSocket->BindToNetDevice (listenerDev); rxSocket->SetRecvCallback (MakeCallback (&Ipv6RipngSplitHorizonStrategyTest::ReceivePktProbe, this)); // ------ Now the tests ------------ diff -r a745117e5dff -r 710f305a22c9 src/network/model/socket.cc --- a/src/network/model/socket.cc Wed Dec 02 23:37:23 2015 +0100 +++ b/src/network/model/socket.cc Thu Dec 03 00:35:35 2015 +0100 @@ -510,6 +510,38 @@ return m_ipv6RecvHopLimit; } +void +Socket::Ipv6JoinGroup (Ipv6Address address, Ipv6MulticastFilterMode filterMode, std::vector sourceAddresses) +{ + NS_LOG_FUNCTION (this< sourceAddresses; + Ipv6JoinGroup (address, EXCLUDE, sourceAddresses); +} + +void +Socket::Ipv6LeaveGroup (void) +{ + NS_LOG_FUNCTION (this); + if(m_ipv6MulticastGroupAddress.IsAny () ) + { + NS_LOG_INFO (" The socket was not bound to any group."); + return; + } + // Leave Group. Note that joining a group with no sources means leaving it. + std::vector sourceAddresses; + Ipv6JoinGroup (m_ipv6MulticastGroupAddress, INCLUDE, sourceAddresses); + m_ipv6MulticastGroupAddress = Ipv6Address::GetAny (); +} + /*************************************************************** * Socket Tags ***************************************************************/ diff -r a745117e5dff -r 710f305a22c9 src/network/model/socket.h --- a/src/network/model/socket.h Wed Dec 02 23:37:23 2015 +0100 +++ b/src/network/model/socket.h Thu Dec 03 00:35:35 2015 +0100 @@ -109,6 +109,23 @@ }; /** + * \enum Ipv6MulticastFilterMode + * \brief Enumeration of the possible filter of a socket. + * + * A socket can have filters on specific sources to include only + * packets incoming from them, or to exclude packets incoming + * from specific sources. + * Moreover, inclusion and exclusion also works as a leave, + * since "joining" a group without allowed sources is equivalent + * to leaving it. + */ + enum Ipv6MulticastFilterMode + { + INCLUDE=1, + EXCLUDE + }; + + /** * This method wraps the creation of sockets that is performed * on a given node by a SocketFactory specified by TypeId. * @@ -817,6 +834,35 @@ */ bool IsIpv6RecvHopLimit (void) const; + /** + * \brief Joins a IPv6 multicast group. + * + * Based on the filter mode and source addresses this can be interpreted as a + * join, leave, or modification to source filtering on a multicast group. + * + * Mind that a socket can join only one multicast group. Any attempt to join another group will remove the old one. + * + * + * \param address Requested multicast address. + * \param filterMode Socket filtering mode (INCLUDE | EXCLUDE). + * \param sourceAddresses All the source addresses on which socket is interested or not interested. + */ + virtual void Ipv6JoinGroup (Ipv6Address address, Ipv6MulticastFilterMode filterMode, std::vector sourceAddresses); + + /** + * \brief Joins a IPv6 multicast group without filters. + * + * A socket can join only one multicast group. Any attempt to join another group will remove the old one. + * + * \param address Group address on which socket wants to join. + */ + virtual void Ipv6JoinGroup (Ipv6Address address); + + /** + * \brief Leaves IPv6 multicast group this socket is joined to. + */ + virtual void Ipv6LeaveGroup (void); + protected: /** * \brief Notify through the callback (if set) that the connection has been @@ -913,6 +959,7 @@ Ptr m_boundnetdevice; //!< the device this socket is bound to (might be null). bool m_recvPktInfo; //!< if the socket should add packet info tags to the packet forwarded to L4. + Ipv6Address m_ipv6MulticastGroupAddress; //!< IPv6 multicast group address. private: Callback > m_connectionSucceeded; //!< connection succeeded callback