When setting the sysctl-variable net.inet.tcp.nolocaltimewait to 1, a TCP endpoint does not enter the TIME-WAIT state, when the communication is local. This can result in sending RST-segments without any error situation. By setting the sysctl-variable net.inet.tcp.nolocaltimewait to 0, this does not occur, and the behavior is compliant with the TCP specification. But there is no reason to stay in the TIME-WAIT state for two time the value of the sysctl-variable net.inet.tcp.msl, if the communication is local. Therefore provide a separate sysctl- variable net.inet.tcp.msl_local, which controls how long an TCP end-point stays in the TIME-WAIT state, if the communication is local. The default value is 10 ms.
Details
- Reviewers
glebius rrs rscheff peter.lei_ieee.org lstewart - Group Reviewers
transport - Commits
- rG5fb4b091e835: tcp: allow specifying a MSL for local communications
Diff Detail
- Repository
- rG FreeBSD src repository
- Lint
Lint Not Applicable - Unit
Tests Not Applicable
Event Timeline
share/man/man4/tcp.4 | ||
---|---|---|
785 | Should this reference nolocaltimewait to be explicit - i.e. msl_local is only used if nolocaltimewait is zero for local endpoints ? |
Thanks Michael! IMHO, modification of the old nolocaltimewait should print an obsolete message and set local_msl to 0. This can be done separately. I can add this.
I wanted to obsolete the old nolocaltimewait in a follow-up commit after discussing the details of that procedure on the fortnightly transport VC.
share/man/man4/tcp.4 | ||
---|---|---|
785 | Fixed. |
Great! I will not attend the call tomorrow. I think just throwing
gone_in(16, "The net.inet.tcp.nolocaltimewait is obsolete. Use net.inet.tcp.local_msl instead.")
in the sysctl handler should be fine. Note that I got review that will make gone_in() print a message only once.
sys/netinet/tcp_timer.h | ||
---|---|---|
77 | Would be a bug if hz < 100. Not sure we support that, though. |
sys/netinet/tcp_timewait.c | ||
---|---|---|
100–112 | Can we move this piece of code into an individual function, like this? static bool is_ip_local(struct inpcb *inp) { #ifdef INET6 bool isipv6 = inp->inp_inc.inc_flags & INC_ISIPV6; #endif return ( #ifdef INET6 isipv6 ? in6_localip(&inp->in6p_faddr) : #endif #ifdef INET in_localip(inp->inp_faddr)); #else false); #endif } And then use is_ip_local() in this tcp_msl() function. | |
151–158 | First, I think we shall use in6_localip(), instead of in6_localaddr(). Second, we can cleanup and re-use the proposed is_ip_local() from my comment above. |
sys/netinet/tcp_timewait.c | ||
---|---|---|
100–112 | I don't agree with this suggestion. A single time use function decreases readability. Also, suggested function works on a higher level structure inpcb, so logically belongs to in_pcb.c namespace. But if we move it there it can't be inlined neither optimized. | |
151–158 |
You raise a good point here. The current use of in6_localaddr() was copied from net.inet.tcp.nolocaltimewait code, which I created without using much analysis of which function should I use to tell a local IPv6 address. Now, comparing these two functions I'm a bit lost. What's the principal difference between them? The difference should be reflected at least in comments. P.S. The IPv6 local address database definitely needs to get rid of rmlock(9), it shall already be protected by the epoch. |
sys/netinet/tcp_timewait.c | ||
---|---|---|
151–158 | Good catch! There are a couple of places, in which we use incorrectly in6_localaddr() instead of in6_localip().
in6_localaddr() corresponds to in_localaddr() and in6_localip() corresponds to in_localip(). |
sys/netinet/tcp_timewait.c | ||
---|---|---|
151–158 | The patch is now using in6_localip(). |
sys/netinet/tcp_timewait.c | ||
---|---|---|
100–112 | The plan is to remove the nolocaltimewait functionality in the long term. Then there is no reuse of the function. So I agree with glebius. |
sys/netinet/tcp_timer.h | ||
---|---|---|
77 | Thanks! |