Difference between revisions of "How to Make Channel Access Reach Multiple Soft IOCs on a Linux Host"
RalphLange (talk | contribs) (Created page with "= How to Make Channel Access Reach Multiple Soft IOCs on a Linux Host = == UDP Name Resolution: Broadcast vs. Unicast == Running multiple IOCs on one host has an annoying side ...") |
(No difference)
|
Revision as of 09:26, 1 April 2014
How to Make Channel Access Reach Multiple Soft IOCs on a Linux Host
UDP Name Resolution: Broadcast vs. Unicast
Running multiple IOCs on one host has an annoying side effect: Clients that are using that host's IP address in their EPICS_CA_ADDR_LIST with EPICS_CA_AUTO_ADDR_LIST=NO will only reach one of the IOCs - usually the one that was started last. All clients have to use broadcasts to reach all IOCs.
The same is true for CA Gateway machines that are set up in a way that makes multiple Gateway processes serve channels into the same network.
The reason is that the kernel delivers UDP broadcasts to all processes that are listening to the IP port, while UDP unicast messages will only be delivered to one of those processes.
Fix Using iptables
Here's a little helper (for Linux hosts) that I recently was playing around with - based on an idea by Rodrigo Bongers (CNPEM, Brazil).
If you drop the right script in the right place (depending on your Linux distribution, see further down), it will automatically create/delete an iptables rule that replaces the destination address of all incoming CA UDP traffic on each interface with the broadcast address of that interface.
A simple and effective trick: the kernel will see all incoming name resolution requests as broadcasts, and delivers them to all IOCs instead of one.
Note: This will not work for clients on the same host. (Adding that feature makes things a lot more complicated, and I like things to be simple.)
If you need connections between IOCs on one host, I would suggest adding the broadcast address of the loopback interface (usually 127.255.255.255) to each IOC's EPICS_CA_ADDR_LIST setting.
Debian and Derivatives
Drop/link the following script into /etc/network/if-up.d/ and /etc/network/if-down.d/.
#!/bin/sh -e # Called when an interface goes up / down # Author: Ralph Lange <[email protected]> # Make any incoming Channel Access name resolution queries go to the broadcast address # (to hit all IOCs on this host) # Change this if you run CA on a non-standard port PORT=5064 [ "$METHOD" != "none" ] || exit 0 [ "$IFACE" != "lo" ] || exit 0 line=`ifconfig $IFACE | grep "inet addr"` addr=`echo $line | sed -e 's/.*inet addr:\([0-9\.]*\).*/\1/'` bcast=`echo $line | sed -e 's/.*Bcast:\([0-9\.]*\).*/\1/'` if [ "$MODE" = "start" ] then iptables -t nat -A PREROUTING -d $addr -p udp --dport $PORT -j DNAT --to-destination $bcast elif [ "$MODE" = "stop" ] then iptables -t nat -D PREROUTING -d $addr -p udp --dport $PORT -j DNAT --to-destination $bcast fi exit 0
RedHat and Derivatives
On systems using NetworkManager, drop the following script into /etc/NetworkManager/dispatcher.d/.
#!/bin/sh -e # Called when an interface goes up / down # Author: Ralph Lange <[email protected]> # Make any incoming Channel Access name resolution queries go to the broadcast address # (to hit all IOCs on this host) # Change this if you run CA on a non-standard port PORT=5064 IFACE=$1 MODE=$2 [ "$IFACE" != "lo" ] || exit 0 line=`ifconfig $IFACE | grep "inet "` addr=`echo $line | sed -e 's/.*inet \([0-9.]*\).*/\1/'` bcast=`echo $line | sed -e 's/.*broadcast \([0-9.]*\).*/\1/'` if [ "$MODE" = "up" ] then iptables -t nat -A PREROUTING -d $addr -p udp --dport $PORT -j DNAT --to-destination $bcast elif [ "$MODE" = "down" ] then iptables -t nat -D PREROUTING -d $addr -p udp --dport $PORT -j DNAT --to-destination $bcast fi exit 0