EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  <20142015  2016  2017  2018  2019  2020  2021  2022  2023  2024  Index 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  <20142015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
<== Date ==> <== Thread ==>

Subject: Re: Binding an IOC to a single network interface
From: Andrew Johnson <[email protected]>
To: Till Straumann <[email protected]>, "[email protected]" <[email protected]>
Date: Tue, 11 Feb 2014 17:07:18 -0600
Hi Till,

On 02/11/2014 11:52 AM, Till Straumann wrote:
> I actually don't think it's the concurrency problems that are hard to
> tackle.

I agree, but whoever does this should look at the concurrency question
to make sure there aren't any issues.

> Freddie's patch modifies the cast_server() and req_server().
> 
> The former is already designed to run as a separate task. cast_server()
> could easily be parametrized cast_server(bind_addr) and a separate task be
> spawned for each address.
>
> Multiple sockets bound to different addresses can be handled by
> req_server() via good-ole 'select'.

I agree that both routines would need changes along those lines. Thread
synchronization at startup & shutdown would need fixing too.

> There are other problems, though - which AFAIK haven't been mentioned yet:
> 
> The identity of the TCP server is stored in global variables
> 'ca_server_addr', 'ca_server_port'
> which are used when answering search replies:
>   ca_server_addr is set from the EPICS_CAS_ADDR env-var (0 if unset)
>   ca_server_port is set from EPICS_CAS_SERVER_PORT or
> EPICS_CA_SERVER_PORT or  CA_SERVER_PORT.

I don't know where you're getting that 'ca_server_addr' global variable
from, no variable by that name appears in my copies of the 3.13.10, 3.14
or 3.15 source code, nor is there an EPICS_CAS_ADDR environment
variable. Are you looking at some SLAC-specific version of Base?

> If binding of the TCP socket to ca_server_port fails (EADDRINUSE) then
> this socket is bound to an
> arbitrary port (0) and ca_server_port read back from the system.
> 
> The problem now is that if there are multiple TCP sockets bound to
> different  ports then there is no easy way to know which one to use.
> 'ca_server_port' would have to be expanded into a list (one for each
> configured socket address) and corresponding lookup logic would have
> to be implemented and built into the handling of search replies.

The RSRV search reply code does not insert the server's IP address into
the reply message at all, although it does set m_dataType to the TCP
port number. If we parametrize the cast_server() thread start-up as
you've described above we can pass in that port number. The client sees
SID=0xffffffff in the response message and takes the server IP address
from the source IP of that response message.

> Finally, there is another issue to resolve if we want to be compatible
> with CAS:
> 
> When you list an interface address in EPICS_CAS_INTF_ADDR_LIST and bind
> the UDP socket to this address then this socket will not receive
> broadcasts (you could list the IF's broadcast address instead but then
> the socket wouldn't receive unicasts).
> CAS handles this by automatically creating a second socket bound to
> the IF's broadcast address. This is used to receive UDP messages.
> However, a comment mentions an additional problem: apparently under
> solaris (no idea if this is still true) when you send from the socket
> bound to the broadcast address then the broadcast address will be used
> as the sender's address (rather than the IF address through which the
> datagram leaves). In order to work around this problem, CAS uses two
> sockets (for each IF): one bound to the broadcast address (for
> reception) and another one bound to the unicast address (for reception
> on the unicast address and for sending replies).

Interesting, thanks. We could test a recent version of Solaris to see
whether the duplication is still needed, but I suspect we should just
implement that model anyway since some sites are still running old
versions of Solaris.

> Given that, I would argue that the approach taken by the existing patch
> gives a considerable gain for a small effort whereas the effort required
> for the 'clean' solution is considerable yielding only a small
> additional gain (I don't think that there are that many use cases where
> you would really need a interface list with multiple entries) and thus
> restricting the list to one entry is reasonable.
>
> The remaining cases (restricting CA to a subset of IFs with multiple
> members) can always be addressed with administrative means (e.g.,
> firewall rules).

That seems like a reasonable argument, any objections or comments from
other people?

Freddie's patch does print an error message if you put more than one IP
address in EPICS_CAS_INTF_ADDR_LIST; actually it gives the error twice,
because both tasks print it:

Starting iocInit
############################################################################
## EPICS R3.14.12.4-DEV $$Date$$
## EPICS Base built Jan  8 2014
############################################################################
CAS: Error parsing EPICS_CAS_INTF_ADDR_LIST 'localhost 164.54.9.24'
CAS: Error parsing EPICS_CAS_INTF_ADDR_LIST 'localhost 164.54.9.24'
iocRun: All initialization complete

I will probably remove one of those reports and may make the error
message a bit more explicit if we do go ahead and merge these changes
(which being new functionality will go into 3.15 BTW, not 3.14).

> PS:
> Another approach (albeit deviating from what CAS does) would be just
> limiting the address(es) the UDP server binds to. The TCP server would
> still use the wildcard address. However, CA searches would only be
> satisfied when targeting one of the addresses where the UDP server
> listens. This would be a little easier to implement but still face
> some of the problems mentioned above (listen on uni- + bcst- sockets,
> solaris hack...)

I think that would be somewhat confusing to someone reading the code at
a later date, so I think I'd prefer the full implementation since it's
not that much more to do.

- Andrew
-- 
Advertising may be described as the science of arresting the human
intelligence long enough to get money from it. -- Stephen Leacock

References:
Binding an IOC to a single network interface freddie.akeroyd
Re: Binding an IOC to a single network interface J. Lewis Muir
Re: Binding an IOC to a single network interface Ralph Lange
Re: Binding an IOC to a single network interface Andrew Johnson
Re: Binding an IOC to a single network interface Till Straumann

Navigate by Date:
Prev: Re: Binding an IOC to a single network interface Till Straumann
Next: Channel Access Link Antonio Borondo
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  <20142015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
Navigate by Thread:
Prev: Re: Binding an IOC to a single network interface Till Straumann
Next: Re: Binding an IOC to a single network interface J. Lewis Muir
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  <20142015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
ANJ, 17 Dec 2015 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·