[Ns-developers] TCP and UDP layer refactoring

Tom Henderson tomh at tomh.org
Fri Jul 4 21:05:37 PDT 2008


Hi Sebastien,  some questions below.

Sébastien Vincent wrote:
> Hi,
> 
> Here is one solution for a design about the refactoring UDP/TCP layer. 
> It will be decomposed in several part.

To clarify, is your goal to achieve the minimally intrusive refactoring 
to allow v6 protocols to reuse the existing transport code logic, or 
more refactoring or goals than that?

> 
> I) Tags
> 
> Add the following tags :
> 
> - Ipv6SocketAddressesTag
>    -> Ipv6Address src;
>    -> Ipv6Address dst;
> 
> - Ipv4SocketAddressesTag
>    -> Ipv4Address src;
>    -> Ipv4Address dst;
> 
> - LocalIpv6InterfaceTag
>    -> Ipv6Address addr;
>    -> Ipv6Prefix mask;
> 
> - LocalIpv4InterfaceTag
>    -> Ipv4Address addr;
>    -> Ipv4Mask mask;
>    -> uint32_t ifIndex ???;
> 
> The LocaIpv*InterfaceTag will be used to avoid having the 
> Ptr<Ipv*Interface> in *L4Protocol::Receive.
> In facts in the *EndPointDemux::Lookup, we use the interface to get its 
> address and netmask.

I think that we could probably get away without carrying around the 
incomingInterface as an explicit parameter.

The FreeBSD socket demux code I've looked at before does not need to 
carry this parameter.  Has anyone considered porting the logic for 
socket wildcard matching from Linux or BSD to this demux function?  This 
is not a trivial demux to implement.

> 
> II) Independant EndPoint
> 
> - Have a single class EndPoint (and remove Ipv6EndPoint and Ipv4EndPoint).
> - The members m_localAddr an m_peerAddress will be stored as Address
> - Remove Ipv4Address argument from m_rxCallBack and SetRxCallback (see 
> VI)).
> - Add a AfType (AF_INET or AF_INET6) to know the type of address.

Can't Address::IsMatchingType be used to learn the type of the address?

Would it be sufficient and appropriate to just have logic something like:

Endpoints::Lookup
{
   if (InetSocketAddress::IsMatchingType (address))
     {
       // do Ipv4-based lookup
     }
   else if (Inet6SocketAddress::IsMatchingType (address))
     {
       // do Ipv6-based lookup
     }
}

this begs the question:  more generally than this lookup function, since 
we have just two address families, would it suffice to handle most of 
these address family issues by just passing class Address around, and 
having the method first check whether the address is Ipv4 or Ipv6?

> 
> III) StorageSocketAddress
> 
> Some functions in *SocketImpl use InetSocketAddress or 
> Inet6SocketAddress. We can avoid this by having a class that have the 
> same methods
> than InetSocketAddress but with Address attributes called 
> StorageSocketAddress. This is similar to the "struct sockaddr_storage" 
> in C.
> 
> StorageSocketAddress
>    -> AfType type
>    -> Address addr
>    -> uint16_t port
>    -> ConvertToInetSocketAddress (???)
>    -> ConvertToInet6SocketAddress (???)
> 
> The InetSocketAddress and Inet6SocketAddress should have a operator 
> StorageSocketAddress() to map automatically its contents to a 
> StorageSocketAddress and set the AfType.
> -> No changes to existing applications.
> 
> OR
> 
> we can also remove InetSocketAddress and Inet6SocketAddress and use only 
> StorageSocketAddress.

Again, I would ask here whether class Address suffices.

> 
> 
> IV) *SocketImpl
> 
> - Use StorageSocketAddress;
> - Use Address instead of Ipv*Address;
> - In DoSendTo (Ptr<Packet> p, Address daddr, uint16_t dport), after
> 
>  if (m_endPoint == 0)
>    {
>      if (Bind () == -1)
>  {
>          NS_ASSERT (m_endPoint == 0);
>    return -1;
>  }
>      NS_ASSERT (m_endPoint != 0);
>    }
>  if (m_shutdownSend)
>    {
>      m_errno = ERROR_SHUTDOWN;
>      return -1;
>    }
> 
> check m_endPoint->GetAfType() and do IPv6 or IPv4 stuff;
> 
> - Add Ipv*SocketAddressesTag before sending to UdpL4Protocol.

Regarding using tags to carry addresses between layers (if I understand 
the intention correctly), I think it is clearer, if the address is a 
mandatory parameter to pass, to just put it in the function signature.

> 
> 
> V) Ipv*L3Protocol
> 
> - Add the Ipv*SocketAddressesTag in ::ForwardUp();
> - Add Ipv*InterfaceTag in ::ForwardUp().
> 
> VI) *L4Protocol
> 
> - Have Ipv6EndPointDemux and Ipv4EndPointDemux or one EndPointDemux (see 
> VII));

one EndPointDemux could check address type and call the right Ipv4 or 
Ipv6 EndpointDemux function?

> - Remove Ipv*Address in ::Receive signature, use tag instead (added in 
> Ipv*L3Protocol);
> - Remove Ipv*Address in ::Send() signature, use tag instead (added in 
> *SocketImpl::DoSendTo());
> - Check tag (if/else) in ::Receive, and do appropriate behavior 
> (checksum, *EndPointDemux);
> - Check tag (if/else) in ::Send, and do appropriate behavior (checksum, 
> send to the right L3 stack);
> - Remove Ipv*Address in ::ForwardUp() signature, check 
> Ipv*SocketAddressesTag and get the source addresse, create a 
> StorageSocketAddress, and put in SocketAddressTag;
> - Allocate() method takes Address arguments and return EndPoint*.
> 
> VII) Ipv*EndPointDemux
> 
> First solution :
> - Keep Ipv6EndPointDemux and Ipv4EndPointDemux;
> - In ::Lookup(), get the Ipv*InterfaceTag, remove incomingInterface and 
> do stuff as usual with the address/netmask in the tag.
> 
> Second solution
> - Have a single EndPointDemux;
> - Overload Lookup function (one for IPv6 and one for IPv4);
> - Two set of EndPoints list (one for IPv6 and one for IPv4);
> - Have a AllocateEphemeralPort() and AllocateEphemeralPort6() (because a 
> service can be associated for a distinct IPv4 socket and a IPv6 socket);
> - Remove Ipv6EndPointDemux and Ipv4EndPointDemux.
> 
> VIII) Other
> 
> - When we *L4Protocol::CreateSocket(), it will give a socket that could 
> be bound in IPv4 or IPv6 so no need to add Udp6/Tcp6SocketFactory;

this is an interesting point, I think.  The SocketImpl classes can't 
have any explicit address family dependency because they are created 
before the family is known.  So I agree with your point.

> - Have a single InternetL4Protocol class and remove Ipv6L4Protocol and 
> Ipv4L4Protocol (since the ::Receive method signature will not have 
> Ipv*Interface).
> 

seems like a logical conclusion to the task of making L4 protocols 
generic across address families.

> What do you think ?
> 
> I hope together, we can find a good solution for this issue.

Yes, thanks for taking these issues up.  By the way, I put some flow 
diagrams of how a packet traverses the current stack in section 6 of the 
manual:
http://www.nsnam.org/docs/manual.html#SEC71  (figures 6.2 and 6.3)

These might be helpful for some context to some readers.

Tom


More information about the Ns-developers mailing list