Skip to content

Commit

Permalink
Merge decfaf2 into 9ebd841
Browse files Browse the repository at this point in the history
  • Loading branch information
tboegi committed May 13, 2022
2 parents 9ebd841 + decfaf2 commit 7f2f23f
Show file tree
Hide file tree
Showing 58 changed files with 3,445 additions and 861 deletions.
106 changes: 106 additions & 0 deletions documentation/ipv6-caRepeater.txt
@@ -0,0 +1,106 @@
Case study, how the repeater works:
(Compile EPICS base with NETDEBUG enabled in osiSock.h
to see what is going on)

killall caRepeater ; EPICS_CA_AUTO_ADDR_LIST=46 caRepeater -v

We have 2 physical interfaces on this machine.
"eno1" and "wlp1s0" which have IPv4 addresses:
192.168.88.153 and 192.168.11.115

First of all, the repeater opens 2 sockets to listen for registrations,
one for IPv4 and on for IPv6.

socket #3 is bound to 0.0.0.0:5065
socket #4 is bound to [::1]:5065

socket #3 will recieve both IPv4 beacons and registrations via IPv4
socket #4 will receive registrations of IPv6 enabled clients

To receive IPv6 beacons we must open 2 more sockets,
and let them join their multicast group.

socket #5 is bound to [ff02::1%eno1]:5065
socket #6 is bound to [ff02::1%wlps0]:5065
Both join their multicast group, and receive beacons.

(old) clients that register via IPv4 will not see any IPv6 beacons,
fanout() will skip forwarding IPv6 beacons to IPv4 clients.

==================================
The message format:

The channel access header looks like this:
ca_uint16_t m_cmmd; /* operation to be performed */
ca_uint16_t m_postsize; /* size of payload */
ca_uint16_t m_dataType; /* operation data type */
ca_uint16_t m_count; /* operation data count */
ca_uint32_t m_cid; /* channel identifier */
ca_uint32_t m_available; /* protocol stub dependent */

All fields are in network byte order.

For an IPv4 beacon we see:
m_cmmd CA_PROTO_RSRV_IS_UP
m_postsize 0 for IPv4
m_dataType CA_MINOR_PROTOCOL_REVISION
m_count ca_server_port
m_cid beaconCounter++
m_available IPv4 address of the server

For an IPv6 beacon a longer message is used:
m_cmmd CA_PROTO_RSRV_IS_UP
m_postsize IPv6 see below
m_dataType CA_MINOR_PROTOCOL_REVISION
m_count ca_server_port
m_cid beaconCounter++
m_available 0
struct ca_ext_IPv6_RSRV_IS_UP_type {
ca_uint32_t m_size; /* size of this struct, net byte order */
ca_uint8_t m_typ_magic[4]; /* 'I' 'P' 'v' '6' */
ca_uint32_t m_sin6_scope_id;/* scope id, host byte order */
ca_uint8_t m_s6_addr[16]; /* IPV6 address */
}

Bote that the "m_available" and "ca_ext_IPv6_RSRV_IS_UP_type"
are filled in by the repeater.
Those values are determined by recvfrom().

The "scope id" is only valid on this host; that is OK since the repeater
and the client are running on the same host.

The IPv6 address is typically link-local ("fe80:"),
we will not see any global IPv6 addresses here.

Note that we haven't implemented code to translate link-local
addresses into host names.
The (local) DNS server does not maintain any link-local addresses.
Getting the hostname is possible via ICMP requests,
may be, investigations needed.

I am tempted to add another extension that carries the host name
inside the beacon messages.
It needs to be determined only once, and then it is fixed.
See .../modules/database/src/ioc/rsrv/online_notify.c

Alternative solution for beacon messages ( do we need it ?)

Use a different (and new defined) message type instead of
changing CA_PROTO_RSRV_IS_UP.
May be CA_PROTO_RSRV_IS_UP_IPV6 or so.


Alternative solution for registration messages:
Today old and "IPv4 only" clients register on IPv4,
"new and IPv6" capable clients register via IPv6.

The IPv4 version alternates between 0.0.0.0 and the first IPv4
address of the machine (due to legacy).
It would be nice to make things more elegant, an IPV6 client should
be able to register via IPv4 or IPv6.

Possible solution:
Use a longer message for REPEATER_REGISTER.
Would this break any old servers ?


171 changes: 171 additions & 0 deletions documentation/ipv6-howto.txt
@@ -0,0 +1,171 @@
Start using IPv6:
Using global IPv6 addresses:
caget, camonitor can work via IPV6 like this:
$ export EPICS_CA_AUTO_ADDR_LIST=NO
$ export EPICS_CA_ADDR_LIST='[2001:db8:1:0:0:1:2:3]'
cainfo IOC:m1

Using IPv6 with link local addresses:
# On the IOC
# Disable IPv4:
$ export EPICS_CA_AUTO_ADDR_LIST=NO
# enable IPv6:
$ export EPICS_CAS_AUTO_BEACON_ADDR_LIST=6
# start the IOC:
$ st.cmd

# On the client, use something like this:
$ export EPICS_CA_AUTO_ADDR_LIST=NO
$ export EPICS_CA_AUTO_ADDR_LIST=6
$ cainfo IOC:m1

Running an IOC with IPv4 and IPv6:
$ export EPICS_CAS_AUTO_BEACON_ADDR_LIST=46
This sends out beacons on all IPv4 and IPv6 interfaces


########################################################
Further reading:
Running IOCs:
- Run IPv4 (this is the default)
When your platform has support for IPv6, you should see
one line in the ioc log.
$ st.cmd
[]
cast_server: EPICS_CA_AUTO_ADDR_LIST='YES' EPICS_CAS_AUTO_BEACON_ADDR_LIST='' useIPv4=1 useIPv6=0
[]
- Enable IPv6, IPv6 beacons and IPv4 and IPv4 beacons in parallel:
$ export EPICS_CAS_AUTO_BEACON_ADDR_LIST=46
$ st.cmd
[]
cast_server: EPICS_CA_AUTO_ADDR_LIST='YES' EPICS_CAS_AUTO_BEACON_ADDR_LIST='46' useIPv4=1 useIPv6=1
[]

- Enable IPv6 with beacons, Disable IPv4
$ export EPICS_CA_AUTO_ADDR_LIST=6
$ export EPICS_CAS_AUTO_BEACON_ADDR_LIST=6
$ st.cmd
[]
cast_server: EPICS_CA_AUTO_ADDR_LIST='6' EPICS_CAS_AUTO_BEACON_ADDR_LIST='6' useIPv4=0 useIPv6=1
[]

- Enable IPv6 without beacons, Disable IPv4
$ export EPICS_CA_AUTO_ADDR_LIST=6
$ export EPICS_CAS_AUTO_BEACON_ADDR_LIST=NO
$ st.cmd
[]
cast_server: EPICS_CA_AUTO_ADDR_LIST='6' EPICS_CAS_AUTO_BEACON_ADDR_LIST='NO' useIPv4=0 useIPv6=1
[]

########################################
Further reading:
Using clients:
- Use both IPv6 and IPv4:
$ EPI
CS_CA_AUTO_ADDR_LIST=46 camonitor IOC:m1

- Use both IPv6 and IPv4:
$ EPICS_CA_AUTO_ADDR_LIST=46 camonitor IOC:m1
(In my test setup, you get this:)
CA.Client.Exception...............................................
Warning: "Identical process variable names on multiple servers"
Context: "Channel: "IOC:m1", Connecting to: 192.168.88.154:5064, Ignored: [fe80:0:0:0:cdc:863f:2e6e:b4c7%2]:5064"
Source File: ../cac.cpp line 1331
Current Time: Wed Jan 26 2022 16:42:14.093087755

- Use both IPv6 and IPv4:
$ EPICS_CA_AUTO_ADDR_LIST=4 camonitor IOC:m1
(In my test setup, you get this:)
CA.Client.Exception...............................................
Warning: "Identical process variable names on multiple servers"
Context: "Channel: "IOC:m1", Connecting to: 192.168.88.154:5064, Ignored: [fe80:0:0:0:cdc:863f:2e6e:b4c7%2]:5064"
Source File: ../cac.cpp line 1331
Current Time: Wed Jan 26 2022 16:42:14.093087755
- Use only IPv4:
$ EPICS_CA_AUTO_ADDR_LIST=4 cainfo IOC:m1
(which is the same as)
$ EPICS_CA_AUTO_ADDR_LIST=YES cainfo IOC:m1
(which is the same as)
$ cainfo IOC:m1
IOC:m1
State: connected
Host: 192.168.88.154:5064
Access: read, write
Native data type: DBF_DOUBLE
Request type: DBR_DOUBLE
Element count: 1

- Use only IPv6:
$ EPICS_CA_AUTO_ADDR_LIST=6 cainfo IOC:m1
IOC:m1
State: connected
Host: [fe80:0:0:0:cdc:863f:2e6e:b4c7%2]:5064
Access: read, write
Native data type: DBF_DOUBLE
Request type: DBR_DOUBLE
Element count: 1
##################
#
# Multihomed
# Assume that the IOC and the client both have 2 interfaces
# (ethernet and wireless)
# The ethernet interfaces are connected to the same switch
# The wireless interafaces are connected to the same WLAN
# WLAN and ethernet are using different IP networks.
# So, here we go:
#
EPICS_CA_AUTO_ADDR_LIST=6 camonitor IOC:m1
IOC:m1 2022-01-26 16:42:10.382339 99.99 STATE MAJOR
CA.Client.Exception...............................................
Warning: "Identical process variable names on multiple servers"
Context: "Channel: "IOC:m1", Connecting to: [fe80:0:0:0:cdc:863f:2e6e:b4c7%2]:5064, Ignored: [fe80:0:0:0:1882:ede9:32db:e952%3]:5064"
Source File: ../cac.cpp line 1331
Current Time: Wed Jan 26 2022 16:49:00.410159895
..................................................................
##################
That is good, but too much.
- Restrict searched to ethernet, "eno1"
$ EPICS_CA_AUTO_ADDR_LIST=NO EPICS_CA_ADDR_LIST='[ff02::1%eno1]' camonitor IOC:m1
IOC:m1 2022-01-26 16:42:10.382339 99.99 STATE MAJOR
- Restrict search to wireless, "wlp1s0"
$ EPICS_CA_AUTO_ADDR_LIST=NO EPICS_CA_ADDR_LIST='[ff02::1%wlp1s0]' camonitor IOC:m1
IOC:m1 2022-01-26 16:42:10.382339 99.99 STATE MAJOR
####
#
# Use cainfo
#
- Using ethernet:
$ EPICS_CA_AUTO_ADDR_LIST=NO EPICS_CA_ADDR_LIST='[ff02::1%eno1]' cainfo IOC:m1
IOC:m1
State: connected
Host: [fe80:0:0:0:cdc:863f:2e6e:b4c7%2]:5064
Access: read, write
Native data type: DBF_DOUBLE
Request type: DBR_DOUBLE
Element count: 1

- Using the wireless:
$ EPICS_CA_AUTO_ADDR_LIST=NO EPICS_CA_ADDR_LIST='[ff02::1%wlp1s0]' cainfo IOC:m1
IOC:m1
State: connected
Host: [fe80:0:0:0:1882:ede9:32db:e952%3]:5064
Access: read, write
Native data type: DBF_DOUBLE
Request type: DBR_DOUBLE
Element count: 1
#
# So what does this all mean ?
#





Windows (Mingw)
More investigations are needed.
Which version of Windows do we want to support ?
XP ? Vista ? Windows 10 ?


Further reading:
https://datatracker.ietf.org/doc/html/rfc3493
53 changes: 53 additions & 0 deletions documentation/ipv6-status-and-todo.txt
@@ -0,0 +1,53 @@
Status and to do of EPICS base:

- Channel Access:
- Cannel name resolution:
working: using link-local IPv6 addresses or global IPv6 addresses.
todo: test with a DNS name (AAAA record)
- beacons:
Are send out via IPv6 link local addresses if configured
with EPICS_CAS_AUTO_BEACON_ADDR_LIST=6 (or 46)
The beacons use an extended message for CA_PROTO_RSRV_IS_UP
- Revers name resolution
aToIPAddr does not handle IPv6 (and needs to be replaced)
Some problems to convert interface index into a name
(The #%en0" part of the IPv6 address)
Needs to be investigated (may be not thread-save ?)
- Channel access via TCP/IPv6
working
- Mixed usage of IPv4 and IPv6 in the network:
In general, this should work out of the box.
Start the repeater like this:
`killall caRepeater ; EPICS_CA_AUTO_ADDR_LIST=46 caRepeater`
For IOCs and clients using IPv4, IPv6 or both see ipv6-howto.txt

- pvAccess:
Nothing done yet.
Probably we can steal/reuse code from channel access.
However, I would like to see channel access more tested before starting
with pvAccess
- Other modules:
pcas:
Work ongoing. Added patches so that pcas be compiled against latest base
Support for IPv6 must be added.

- Linux, MacOs, Windows, vxWorks, RTEMS, BSD
Testing on Linux and Mac looks good. Need to re-run FreeBSD.
Windows: (Which "Windows" ? Visual Studio ? cygwin (seems obsolete) Mingw
vxWorks, RTEMS: Testing needed.

- pyepics (with the latest ca library)
First tests look good ("PYEPICS_LIBCA" is your friend)

- pvapy: to be done
- JCA: to be done
- EPICS gateways: to be done
- asyn:
Prototype working.
It seems that asyn can support IPv6 independent of EPICS base,
there is not really any common code.

Other todo (unorderedd)
- Clean up the debug printing
- More code review
- write automated tests
11 changes: 8 additions & 3 deletions modules/ca/src/client/CAref.html
Expand Up @@ -269,13 +269,13 @@ <h3><a name="EPICS">EPICS Environment Variables</a></h3>
<th>Default</th>
</tr>
<tr>
<td>EPICS_CA_ADDR_LIST</td>
<td>{N.N.N.N N.N.N.N:P ...}</td>
<td>EPICS_CA_ADDR_LIST (IPv6 must use[])</td>
<td>{N.N.N.N N.N.N.N:P [ipv6] [ipv6local%en0]...}</td>
<td>&lt;none&gt;</td>
</tr>
<tr>
<td>EPICS_CA_AUTO_ADDR_LIST</td>
<td>{YES, NO}</td>
<td>{YES, NO, 4, 6, 46}</td>
<td>YES</td>
</tr>
<tr>
Expand Down Expand Up @@ -499,6 +499,11 @@ <h3><a name="Environmen">WAN Environment</a></h3>
"no" or "NO". The typical default is to enable network interface introspection
driven initialization with EPICS_CA_AUTO_ADDR_LIST set to "YES" or "yes".</p>

<p>Using IPv6:
Set EPICS_CA_AUTO_ADDR_LIST to "46" to use both IPv4 and IPv6 in parallel.
Set EPICS_CA_AUTO_ADDR_LIST to "6" to use only IPv6.
Set EPICS_CA_AUTO_ADDR_LIST to "4" to use only IPv4, this is the same as "YES".</p>

<p>Following network interface introspection, any IP addresses specified in the
EPICS environment variable EPICS_CA_ADDR_LIST are added to the list of
destination addresses for CA client name resolution requests. In an EPICS
Expand Down
2 changes: 1 addition & 1 deletion modules/ca/src/client/SearchDest.h
Expand Up @@ -27,7 +27,7 @@ struct SearchDest :
virtual ~Callback () {};
virtual void notify (
const caHdr & msg, const void * pPayload,
const osiSockAddr & addr, const epicsTime & ) = 0;
const osiSockAddr46 & addr46, const epicsTime & ) = 0;
virtual void show (
epicsGuard < epicsMutex > &, unsigned level ) const = 0;
};
Expand Down
2 changes: 1 addition & 1 deletion modules/ca/src/client/access.cpp
Expand Up @@ -309,7 +309,7 @@ int epicsStdCall ca_create_channel (
}
}
if ( pFunc ) {
( *pFunc ) ( pArg, pcac->sock, true );
( *pFunc ) ( pArg, pcac->sock46, true );
}
}

Expand Down
13 changes: 13 additions & 0 deletions modules/ca/src/client/caProto.h
Expand Up @@ -181,6 +181,19 @@ struct mon_info {
ca_uint16_t m_pad; /* extend to 32 bits */
};

typedef struct ca_ext_IPv6_RSRV_IS_UP_type {
ca_uint32_t m_size; /* size of this struct, net byte order */
ca_uint8_t m_typ_magic[4]; /* 'I' 'P' 'v' '6' */
ca_uint32_t m_sin6_scope_id;/* scope id, host byte order */
ca_uint8_t m_s6_addr[16]; /* IPV6 address */
} ca_ext_IPv6_RSRV_IS_UP_type;

typedef struct ca_msg_IPv6_RSRV_IS_UP_type {
caHdr hdr;
ca_ext_IPv6_RSRV_IS_UP_type ca_ext_IPv6_RSRV_IS_UP;
} ca_msg_IPv6_RSRV_IS_UP_type;


/*
* PV names greater than this length assumed to be invalid
*/
Expand Down

0 comments on commit 7f2f23f

Please sign in to comment.