[Ns-developers] TCP and UDP layer refactoring

Sébastien Vincent vincent at clarinet.u-strasbg.fr
Fri Jul 4 04:43:02 PDT 2008


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.
>
> 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.
>
> 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.
>
> 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.
>
>
> 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.
>
>
> 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));
> - 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*.
I forgot one thing :
In *L4Protocol::Allocate(void) and *L4Protocol::Allocate(uint16_t port) 
we could not determine which L3 protocol we want and set the according 
Ipv*EndPointDemux (to allocate).

Two solutions to solve the problem :

1)
Have the following prototypes instead :
EndPoint *L4Protocol::Allocate(Ipv4Address addr = Ipv4Address::Any());
EndPoint *L4Protocol::Allocate(uint16_t port, Ipv4Address addr = 
Ipv4Address::Any());
EndPoint *L4Protocol::Allocate(Ipv6Address addr = Ipv6Address::Any());
EndPoint *L4Protocol::Allocate(uint16_t port, Ipv6Address addr = 
Ipv6Address::Any());

Not very aesthetic!

2)
Don't use Allocate(void) and Allocate(uint16_t port).
Replace them in the *SocketImpl code by Allocate(Ipv*Address::Any()) and 
Allocate(Ipv*Address::Any(), port).
Remove Ipv*EndPointDemux::Allocate (void).

Easy to do!

>
> 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;
> - Have a single InternetL4Protocol class and remove Ipv6L4Protocol and 
> Ipv4L4Protocol (since the ::Receive method signature will not have 
> Ipv*Interface).
>
> What do you think ?
>
> I hope together, we can find a good solution for this issue.
>
> Regards,
> -- 
> Sebastien Vincent
> Network and Protocol Team, University of Strasbourg, France
>
>



More information about the Ns-developers mailing list