Bug 2234 - Ipv6L3Protocol should trash multicast packets not interesting for the node
--- 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
--- 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;
}
}
--- 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<Ipv6InterfaceAddress> Ipv6InterfaceAddressList;
+ typedef std::list<std::pair<Ipv6InterfaceAddress, Ipv6Address> > Ipv6InterfaceAddressList;
/**
* \brief Container Iterator for the Ipv6InterfaceAddresses.
*/
- typedef std::list<Ipv6InterfaceAddress>::iterator Ipv6InterfaceAddressListI;
+ typedef std::list<std::pair<Ipv6InterfaceAddress, Ipv6Address> >::iterator Ipv6InterfaceAddressListI;
/**
* \brief Const Container Iterator for the Ipv6InterfaceAddresses.
*/
- typedef std::list<Ipv6InterfaceAddress>::const_iterator Ipv6InterfaceAddressListCI;
+ typedef std::list<std::pair<Ipv6InterfaceAddress, Ipv6Address> >::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;
--- 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<Ipv6> (), 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 */
--- 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<const Packet> packet,
DropReason reason, Ptr<Ipv6> 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<Ipv6Address, uint64_t> Ipv6RegisteredMulticastAddressKey_t;
+
+ /**
+ * \brief Container of the IPv6 multicast addresses.
+ */
+ typedef std::map<Ipv6RegisteredMulticastAddressKey_t, uint32_t> Ipv6RegisteredMulticastAddress_t;
+
+ /**
+ * \brief Container Iterator of the IPv6 multicast addresses.
+ */
+ typedef std::map<Ipv6RegisteredMulticastAddressKey_t, uint32_t>::iterator Ipv6RegisteredMulticastAddressIter_t;
+
+ /**
+ * \brief Container Const Iterator of the IPv6 multicast addresses.
+ */
+ typedef std::map<Ipv6RegisteredMulticastAddressKey_t, uint32_t>::const_iterator Ipv6RegisteredMulticastAddressCIter_t;
+
+ /**
+ * \brief Container of the IPv6 multicast addresses.
+ */
+ typedef std::map<Ipv6Address, uint32_t> Ipv6RegisteredMulticastAddressNoInterface_t;
+
+ /**
+ * \brief Container Iterator of the IPv6 multicast addresses.
+ */
+ typedef std::map<Ipv6Address, uint32_t>::iterator Ipv6RegisteredMulticastAddressNoInterfaceIter_t;
+
+ /**
+ * \brief Container Const Iterator of the IPv6 multicast addresses.
+ */
+ typedef std::map<Ipv6Address, uint32_t>::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 */
--- 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<Ipv6L3Protocol> ipv6 = m_node->GetObject<Ipv6L3Protocol> ();
+ Ipv6LeaveGroup ();
if (ipv6)
{
ipv6->DeleteRawSocket (this);
@@ -297,6 +298,54 @@
return data.packet;
}
+void
+Ipv6RawSocketImpl::Ipv6JoinGroup (Ipv6Address address, Socket::Ipv6MulticastFilterMode filterMode, std::vector<Ipv6Address> 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<Ipv6L3Protocol> ipv6l3 = m_node->GetObject <Ipv6L3Protocol> ();
+ 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 ();
--- 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<Packet> p, uint32_t flags, const Address& toAddress);
virtual Ptr<Packet> Recv (uint32_t maxSize, uint32_t flags);
virtual Ptr<Packet> RecvFrom (uint32_t maxSize, uint32_t flags, Address& fromAddress);
+ virtual void Ipv6JoinGroup (Ipv6Address address, Socket::Ipv6MulticastFilterMode filterMode, std::vector<Ipv6Address> sourceAddresses);
/**
* \brief Set protocol field.
--- 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++)
--- 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<Ipv6L3Protocol> ipv6l3 = m_node->GetObject <Ipv6L3Protocol> ();
+ 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<Ipv6L3Protocol> ipv6l3 = m_node->GetObject <Ipv6L3Protocol> ();
+ 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<Ipv6Address> 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<Ipv6L3Protocol> ipv6l3 = m_node->GetObject <Ipv6L3Protocol> ();
+ 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
--- 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> netdevice);
virtual bool SetAllowBroadcast (bool allowBroadcast);
virtual bool GetAllowBroadcast () const;
+ virtual void Ipv6JoinGroup (Ipv6Address address, Socket::Ipv6MulticastFilterMode filterMode, std::vector<Ipv6Address> sourceAddresses);
private:
// Attributes set through UdpSocket base class
--- 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<SocketFactory> rxSocketFactory = listener->GetObject<UdpSocketFactory> ();
Ptr<Socket> 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 ------------
--- 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<Ipv6Address> sourceAddresses)
+{
+ NS_LOG_FUNCTION (this<<address<<&filterMode<<&sourceAddresses);
+ NS_ASSERT_MSG (false,"Ipv6JoinGroup not implemented on this socket");
+}
+
+void
+Socket::Ipv6JoinGroup (Ipv6Address address)
+{
+ NS_LOG_FUNCTION (this<<address);
+
+ // Join Group. Note that joining a group with no sources means joining without source restrictions.
+ std::vector<Ipv6Address> 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<Ipv6Address> sourceAddresses;
+ Ipv6JoinGroup (m_ipv6MulticastGroupAddress, INCLUDE, sourceAddresses);
+ m_ipv6MulticastGroupAddress = Ipv6Address::GetAny ();
+}
+
/***************************************************************
* Socket Tags
***************************************************************/
--- 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<Ipv6Address> 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<NetDevice> 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<void, Ptr<Socket> > m_connectionSucceeded; //!< connection succeeded callback