click: align Ipv4L3ClickProtocol with ae25cc3a0f89

this commit also fixes a bug uncovered by the more strict parsing
of Ipv4Address strings.  In Ipv4ClickRouting::RouteOutput(), it is
possible for the string from the click routing table to contain
just a single entry, but the code was assuming a space-delimited
pair.  If only a single entry is returned, the destination is now
set to "0.0.0.0".
This commit is contained in:
Tom Henderson
2016-02-08 23:06:43 -08:00
parent 4b3323ead4
commit 44c93c49ab
3 changed files with 193 additions and 42 deletions

View File

@@ -483,12 +483,26 @@ Ipv4ClickRouting::RouteOutput (Ptr<Packet> p, const Ipv4Header &header, Ptr<NetD
header.GetDestination ().Print (addr);
// Probe the Click Routing Table for the required IP
// This returns a string of the form "InterfaceID GatewayAddr"
NS_LOG_DEBUG ("Probe click routing table for " << addr.str ());
std::string s = ReadHandler (m_clickRoutingTableElement, addr.str ());
NS_LOG_DEBUG ("string from click routing table: " << s);
int pos = s.find (" ");
int interfaceId = atoi (s.substr (0, pos).c_str ());
Ipv4Address destination (s.substr (pos + 1).c_str ());
size_t pos = s.find (" ");
Ipv4Address destination;
int interfaceId;
if (pos == std::string::npos)
{
// Only an interface ID is found
destination = Ipv4Address ("0.0.0.0");
interfaceId = atoi (s.c_str ());
NS_LOG_DEBUG ("case 1: destination " << destination << " interfaceId " << interfaceId);
}
else
{
interfaceId = atoi (s.substr (0, pos).c_str ());
Ipv4Address destination (s.substr (pos + 1).c_str ());
NS_LOG_DEBUG ("case 2: destination " << destination << " interfaceId " << interfaceId);
}
if (interfaceId != -1)
{

View File

@@ -80,7 +80,7 @@ Ipv4L3ClickProtocol::DoDispose (void)
NS_LOG_FUNCTION (this);
for (L4List_t::iterator i = m_protocols.begin (); i != m_protocols.end (); ++i)
{
*i = 0;
i->second = 0;
}
m_protocols.clear ();
@@ -89,6 +89,8 @@ Ipv4L3ClickProtocol::DoDispose (void)
*i = 0;
}
m_interfaces.clear ();
m_reverseInterfacesContainer.clear ();
m_sockets.clear ();
m_node = 0;
m_routingProtocol = 0;
@@ -197,15 +199,10 @@ Ipv4L3ClickProtocol::GetInterfaceForDevice (
{
NS_LOG_FUNCTION (this << device->GetIfIndex ());
int32_t interface = 0;
for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
i != m_interfaces.end ();
i++, interface++)
Ipv4InterfaceReverseContainer::const_iterator iter = m_reverseInterfacesContainer.find (device);
if (iter != m_reverseInterfacesContainer.end ())
{
if ((*i)->GetDevice () == device)
{
return interface;
}
return (*iter).second;
}
return -1;
@@ -458,6 +455,33 @@ Ipv4L3ClickProtocol::RemoveAddress (uint32_t i, Ipv4Address address)
return false;
}
Ipv4Address
Ipv4L3ClickProtocol::SourceAddressSelection (uint32_t interfaceIdx, Ipv4Address dest)
{
NS_LOG_FUNCTION (this << interfaceIdx << " " << dest);
if (GetNAddresses (interfaceIdx) == 1) // common case
{
return GetAddress (interfaceIdx, 0).GetLocal ();
}
// no way to determine the scope of the destination, so adopt the
// following rule: pick the first available address (index 0) unless
// a subsequent address is on link (in which case, pick the primary
// address if there are multiple)
Ipv4Address candidate = GetAddress (interfaceIdx, 0).GetLocal ();
for (uint32_t i = 0; i < GetNAddresses (interfaceIdx); i++)
{
Ipv4InterfaceAddress test = GetAddress (interfaceIdx, i);
if (test.GetLocal ().CombineMask (test.GetMask ()) == dest.CombineMask (test.GetMask ()))
{
if (test.IsSecondary () == false)
{
return test.GetLocal ();
}
}
}
return candidate;
}
Ipv4Address
Ipv4L3ClickProtocol::SelectSourceAddress (Ptr<const NetDevice> device,
Ipv4Address dst, Ipv4InterfaceAddress::InterfaceAddressScope_e scope)
@@ -630,6 +654,7 @@ Ipv4L3ClickProtocol::AddIpv4Interface (Ptr<Ipv4Interface>interface)
NS_LOG_FUNCTION (this << interface);
uint32_t index = m_interfaces.size ();
m_interfaces.push_back (interface);
m_reverseInterfacesContainer[interface->GetDevice ()] = index;
return index;
}
@@ -757,29 +782,20 @@ Ipv4L3ClickProtocol::Receive ( Ptr<NetDevice> device, Ptr<const Packet> p, uint1
{
NS_LOG_FUNCTION (this << device << p << from << to);
NS_LOG_LOGIC ("Packet from " << from << " received on node " <<
m_node->GetId ());
// Forward packet to raw sockets, if any
if (protocol == Ipv4L3ClickProtocol::PROT_NUMBER && m_sockets.size () > 0)
{
Ptr<Packet> packetForRawSocket = p->Copy ();
uint32_t interface = 0;
Ptr<Ipv4Interface> ipv4Interface;
for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
i != m_interfaces.end ();
i++, interface++)
int32_t interface = GetInterfaceForDevice(device);
NS_ASSERT_MSG (interface != -1, "Received a packet from an interface that is not known to IPv4");
Ptr<Ipv4Interface> ipv4Interface = m_interfaces[interface];
if (!ipv4Interface->IsUp ())
{
ipv4Interface = *i;
if (ipv4Interface->GetDevice () == device)
{
if (ipv4Interface->IsUp ())
{
break;
}
else
{
NS_LOG_LOGIC ("Dropping received packet -- interface is down");
return;
}
}
NS_LOG_LOGIC ("Dropping received packet -- interface is down");
return;
}
Ipv4Header ipHeader;
@@ -878,22 +894,97 @@ Ipv4L3ClickProtocol::GetIcmp (void) const
void
Ipv4L3ClickProtocol::Insert (Ptr<IpL4Protocol> protocol)
{
m_protocols.push_back (protocol);
NS_LOG_FUNCTION (this << protocol);
L4ListKey_t key = std::make_pair (protocol->GetProtocolNumber (), -1);
if (m_protocols.find (key) != m_protocols.end ())
{
NS_LOG_WARN ("Overwriting default protocol " << int(protocol->GetProtocolNumber ()));
}
m_protocols[key] = protocol;
}
void
Ipv4L3ClickProtocol::Insert (Ptr<IpL4Protocol> protocol, uint32_t interfaceIndex)
{
NS_LOG_FUNCTION (this << protocol << interfaceIndex);
L4ListKey_t key = std::make_pair (protocol->GetProtocolNumber (), interfaceIndex);
if (m_protocols.find (key) != m_protocols.end ())
{
NS_LOG_WARN ("Overwriting protocol " << int(protocol->GetProtocolNumber ()) << " on interface " << int(interfaceIndex));
}
m_protocols[key] = protocol;
}
void
Ipv4L3ClickProtocol::Remove (Ptr<IpL4Protocol> protocol)
{
NS_LOG_FUNCTION (this << protocol);
L4ListKey_t key = std::make_pair (protocol->GetProtocolNumber (), -1);
L4List_t::iterator iter = m_protocols.find (key);
if (iter == m_protocols.end ())
{
NS_LOG_WARN ("Trying to remove an non-existent default protocol " << int(protocol->GetProtocolNumber ()));
}
else
{
m_protocols.erase (key);
}
}
void
Ipv4L3ClickProtocol::Remove (Ptr<IpL4Protocol> protocol, uint32_t interfaceIndex)
{
NS_LOG_FUNCTION (this << protocol << interfaceIndex);
L4ListKey_t key = std::make_pair (protocol->GetProtocolNumber (), interfaceIndex);
L4List_t::iterator iter = m_protocols.find (key);
if (iter == m_protocols.end ())
{
NS_LOG_WARN ("Trying to remove an non-existent protocol " << int(protocol->GetProtocolNumber ()) << " on interface " << int(interfaceIndex));
}
else
{
m_protocols.erase (key);
}
}
Ptr<IpL4Protocol>
Ipv4L3ClickProtocol::GetProtocol (int protocolNumber) const
{
for (L4List_t::const_iterator i = m_protocols.begin (); i != m_protocols.end (); ++i)
{
if ((*i)->GetProtocolNumber () == protocolNumber)
{
return *i;
}
}
return 0;
NS_LOG_FUNCTION (this << protocolNumber);
return GetProtocol (protocolNumber, -1);
}
Ptr<IpL4Protocol>
Ipv4L3ClickProtocol::GetProtocol (int protocolNumber, int32_t interfaceIndex) const
{
NS_LOG_FUNCTION (this << protocolNumber << interfaceIndex);
L4ListKey_t key;
L4List_t::const_iterator i;
if (interfaceIndex >= 0)
{
// try the interface-specific protocol.
key = std::make_pair (protocolNumber, interfaceIndex);
i = m_protocols.find (key);
if (i != m_protocols.end ())
{
return i->second;
}
}
// try the generic protocol.
key = std::make_pair (protocolNumber, -1);
i = m_protocols.find (key);
if (i != m_protocols.end ())
{
return i->second;
}
return 0;
}
} // namespace ns3

View File

@@ -84,6 +84,36 @@ public:
*/
void Insert (Ptr<IpL4Protocol> protocol);
/**
* \brief Add a L4 protocol to a specific interface.
*
* This may be called multiple times for multiple interfaces for the same
* protocol. To insert for all interfaces, use the separate
* Insert (Ptr<IpL4Protocol> protocol) method.
*
* Setting a protocol on a specific interface will overwrite the
* previously bound protocol.
*
* \param protocol L4 protocol.
* \param interfaceIndex interface index.
*/
void Insert (Ptr<IpL4Protocol> protocol, uint32_t interfaceIndex);
/**
* \param protocol protocol to remove from this demux.
*
* The input value to this method should be the value
* returned from the Ipv4L4Protocol::Insert method.
*/
void Remove (Ptr<IpL4Protocol> protocol);
/**
* \brief Remove a L4 protocol from a specific interface.
* \param protocol L4 protocol to remove.
* \param interfaceIndex interface index.
*/
void Remove (Ptr<IpL4Protocol> protocol, uint32_t interfaceIndex);
/**
* \param protocolNumber number of protocol to lookup
* in this L4 Demux
@@ -92,7 +122,11 @@ public:
* This method is typically called by lower layers
* to forward packets up the stack to the right protocol.
*/
Ptr<IpL4Protocol> GetProtocol (int protocolNumber) const;
virtual Ptr<IpL4Protocol> GetProtocol (int protocolNumber) const;
virtual Ptr<IpL4Protocol> GetProtocol (int protocolNumber, int32_t interfaceIndex) const;
virtual Ipv4Address SourceAddressSelection (uint32_t interface, Ipv4Address dest);
/**
* \param ttl default ttl to use
@@ -251,14 +285,26 @@ private:
virtual bool GetWeakEsModel (void) const;
typedef std::vector<Ptr<Ipv4Interface> > Ipv4InterfaceList;
/**
* \brief Container of NetDevices registered to IPv4 and their interface indexes.
*/
typedef std::map<Ptr<const NetDevice>, uint32_t > Ipv4InterfaceReverseContainer;
typedef std::list<Ptr<Ipv4RawSocketImpl> > SocketList;
typedef std::list<Ptr<IpL4Protocol> > L4List_t;
/**
* \brief Container of the IPv4 L4 keys: protocol number, interface index
*/
typedef std::pair<int, int32_t> L4ListKey_t;
/**
* \brief Container of the IPv4 L4 instances.
*/
typedef std::map<L4ListKey_t, Ptr<IpL4Protocol> > L4List_t;
Ptr<Ipv4RoutingProtocol> m_routingProtocol;
bool m_ipForward;
bool m_weakEsModel;
L4List_t m_protocols;
Ipv4InterfaceList m_interfaces;
Ipv4InterfaceReverseContainer m_reverseInterfacesContainer; //!< Container of NetDevice / Interface index associations.
uint8_t m_defaultTtl;
uint16_t m_identification;