[Ns-developers] TCP and UDP layer refactoring
vincent at clarinet.u-strasbg.fr
Mon Jul 7 01:21:39 PDT 2008
Tom Henderson wrote:
> Hi Sebastien, some questions below.
> Sébastien Vincent wrote:
>> 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?
Yes reuse existing transport code logic.
>> 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.
OK so we could remove all code that use this parameter in ::Lookup ?
> 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
>> - 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:
> 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?
I try to be generic but if you don't plan to add other network layer, we
could do this way.
>> 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.
>> -> 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 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?
I have the same idea.
>> - Remove Ipv*Address in ::Receive signature, use tag instead (added
>> in Ipv*L3Protocol);
>> - Remove Ipv*Address in ::Send() signature, use tag instead (added in
>> - 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.
Ok so if I summarize :
- Remove incomingInterface from EndPointDemux::Lookup() and associate code.
- One EndPointDemux with a ::Lookup() function for each address family
(IPv4 and IPv6).
- *L4Protocol and *SocketImpl use Address and test with
- Have a single tag called SocketAddressesTag with Address parameters
and test as usual (*Address::IsMatchingType).
If you are OK with this, I can begin something this week.
Network and Protocol Team, University of Strasbourg, France
More information about the Ns-developers