[Ns-developers] TCP and UDP layer refactoring
Mathieu Lacage
mathieu.lacage at sophia.inria.fr
Mon Jul 7 10:28:24 PDT 2008
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.
> - 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.
> 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}.
>
> 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 ?
regards,
Mathieu
More information about the Ns-developers
mailing list