[Ns-developers] TCP and UDP layer refactoring

Sébastien Vincent vincent at clarinet.u-strasbg.fr
Tue Jul 8 06:25:48 PDT 2008


Mathieu Lacage wrote:
> On Fri, 2008-07-04 at 13:22 +0200, Sébastien Vincent wrote:
>
>   
>> 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)).
>>     
>
> I think that, generally, if the address is really needed in a couple of
> places, passing it as explicit arguments is cleaner than storing it in a
> hidden tag.
>
>   
Ok so we will have InternetL4Protocol::Receive(Address src, Address dst);

For the "incomingInterface" issue, we filter at socket level ?
This will need to add a *dst* parameter in *SocketImpl::Forward() and 
then compare it to m_endPoint->GetLocalAddress()

Am I right ?

>> - 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.
>>     
>
> Another way to do this would be to do what tom suggested and use Address
> and test for its type before calling one of these functions. If you find
> yourself writing this test code over and over again, you can also push
> it to a couple of helper internal functions such as:
>
> void Inet4SetPort (Address &address, uint16_t port);
> ...
>
>   
>> 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.
>>     
>
> We (I) have learned the hard way that adding more (and multiple)
> implicit conversion operators on a single class is a really bad idea so,
> let's forget this, please: I don't want to have to debug this later.
>
>
>   

OK, as Tom suggested, use Address should be sufficient.

>> 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*.
>>
>> 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.
>>     
>
> ok. But, at this point, I have to ask: is there really some code shared
> in this class after you have done all that ? I mean, it looks like
> everything in this class is going to be if (ipv4) {do} else if (ipv6)
> {do}.
>   

I think we will see better with a prototype version.

>   
>> 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;
>>     
>
> I am worried that the above is a bit too far away from the behavior of a
> real socket. i.e., when I create a socket with the 'socket' system call,
> I specify a family (AF_INET or AF_INET6). If so, what happens if I
> create a socket with AF_INET and give an inet6 address to bind ?
>   

Like the real implementation, syscall returns -1 and set errno : Bad 
address or something like that.

> regards,
> Mathieu
>
>
>   

Tomorrow I will begin a prototype version for UDP/TCP refactoring with 
the ideas of the comments.

--
Sebastien Vincent
Network and Protocol Team - University of Strasbourg, France


More information about the Ns-developers mailing list