On Sun, Feb 23, 2014 at 12:09:11PM +0100, Vincent Bernat wrote:
>  ??? 23 février 2014 10:31 CET, Willy Tarreau <[email protected]> :
> 
> >> > It depends if you have some servers in common or not. The system will
> >> > always allow multiple outgoing connections to share the same local
> >> > source ip:port as long as they don't go to the same destination ip:ports
> >> > since a connection is defined by (proto,srcip,sport,dstip,dport).
> >> 
> >> Are you sure? I was thinking the same thing until I looked at the
> >> sources. It seems that for an outgoing connection, only the source
> >> address and source port are considered (see inet_csk_get_port() and
> >> inet_csk_bind_conflict()).
> >
> > No, if you bind it yourself it's always OK. That's exactly why we
> > introduced the port range in the source statement, to allow certain
> > sites to reach 1M connections by having 64k per server. However, if
> > you let the system choose a port for you, it totally depends on the
> > kernel version, the algorithm has changed many times between something
> > like 2.6.37 and 3.5. In earlier kernels it's exactly what you describe.
> > I believe that 3.2 might be the first one capable of picking a port
> > which is already used for another destination.
> 
> I suppose this is in combination with SO_REUSEADDR (otherwise, bind()
> would fail). It's good to know:
> 
> tcp    ESTAB      0      0          192.168.116.1:37544    74.125.132.104:80  
>   
> tcp    ESTAB      0      0          192.168.116.1:37544    74.125.132.106:80  
>   

You don't even need SO_REUSEADDR nor SO_REUSEPORT for this. This is
standard. For example, FTP servers in active mode all need to bind
to source port 20 and connect to the remote.

> As for getting the same stuff without explictely use bind(), I just
> tried with a 3.2 and I am able to get in the same situation without
> bind() nor SO_REUSEADDR option:
> 
> tcp    ESTAB      0      0           10.234.78.65:61000      10.234.78.67:80  
>   
> tcp    ESTAB      0      0           10.234.78.65:61000      10.234.78.66:80  
>   

OK so it confirms that it's really 3.2 which first worked on this.

> That's a relief ;-)

Yes, but in order for all of this to work much better, in a more
flexible way and faster, we'd really need to reinvent the sockets
API and get rid of the old BSD one. If we were able to pass the
source address to listen() and connect(), we woudln't need bind()
anymore and it wouldn't be forced to run into horrible tricks in
the kernel to try to guess whether we're trying to bind for a listen
or for a connect! After all, we already have accept4() on Linux,
maybe we'll end up with listen4(), connect4(), and sendto6(), who
knows...

Willy


Reply via email to