diff --git a/src/click/model/ipv4-click-routing.cc b/src/click/model/ipv4-click-routing.cc index 9594988b7..0d93e7a8a 100644 --- a/src/click/model/ipv4-click-routing.cc +++ b/src/click/model/ipv4-click-routing.cc @@ -483,12 +483,26 @@ Ipv4ClickRouting::RouteOutput (Ptr p, const Ipv4Header &header, Ptrsecond = 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 device, Ipv4Address dst, Ipv4InterfaceAddress::InterfaceAddressScope_e scope) @@ -630,6 +654,7 @@ Ipv4L3ClickProtocol::AddIpv4Interface (Ptrinterface) 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 device, Ptr 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 packetForRawSocket = p->Copy (); - uint32_t interface = 0; - Ptr 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 = 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 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 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 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 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 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 +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 diff --git a/src/click/model/ipv4-l3-click-protocol.h b/src/click/model/ipv4-l3-click-protocol.h index b83ff0bbf..2e7cdd09d 100644 --- a/src/click/model/ipv4-l3-click-protocol.h +++ b/src/click/model/ipv4-l3-click-protocol.h @@ -84,6 +84,36 @@ public: */ void Insert (Ptr 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 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 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 protocol); + + /** + * \brief Remove a L4 protocol from a specific interface. + * \param protocol L4 protocol to remove. + * \param interfaceIndex interface index. + */ + void Remove (Ptr 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 GetProtocol (int protocolNumber) const; + virtual Ptr GetProtocol (int protocolNumber) const; + + virtual Ptr 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 > Ipv4InterfaceList; + /** + * \brief Container of NetDevices registered to IPv4 and their interface indexes. + */ + typedef std::map, uint32_t > Ipv4InterfaceReverseContainer; typedef std::list > SocketList; - typedef std::list > L4List_t; + /** + * \brief Container of the IPv4 L4 keys: protocol number, interface index + */ + typedef std::pair L4ListKey_t; + /** + * \brief Container of the IPv4 L4 instances. + */ + typedef std::map > L4List_t; Ptr 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;