I was looking into configuring IP V6 on my z/OS running on zPDT running on Linux. I could not understand why configuring the IP V6 link between Linux and z/OS was so difficult.
IP V6 address for use within a connection are like fe80::b0b6:daff:fe64:77f5 where b0b6:daff:fe64:77f5 is based on the MAC(hwaddr). On many systems, this value does not change across IPLs – and so most of the documentation uses the “constant” value.
The connection between Linux and z/OS is a “tap” interface (a kernel virtual device) which looks like an OSA adapter to z/OS.
I found a comment
Each TAP device has a random MAC address that is used as source address.
This explains why the connection was getting a different IP address every time I ipled.
On z/OS you defined a route using this IP address, for example
BEGINRoutes
ROUTE 2001:db8::7/128 fe80::3f:67ff:fe08:51dc IFPORTCP6 MTU 5000
ENDRoutes
To get round this problem you need to explicitly define an address on Linux
sudo ip -6 addr add fec0::cccc/64 dev tap1
where cccc is for my initials!
You then put this address into the z/OS routing statements.
BEGINRoutes
ROUTE 2001:db8::7/128 fe80::cccc IFPORTCP6 MTU 5000
ENDRoutes
As part of understanding how IP V6 dynamic routing works, I managed to get my little home network to talk using IP V6.
Privacy
There are sites which can give you your geographic location from your IP V6 address. One site gave me the top part of my post code, the latitude and longitude of my garage, and my ISP provider. So instead of giving real IP addresses, Ive used xxxx:xxxx:xxxx:xxxx for the IP V6 address provided by my Internet Service Provider, and using the 2001:db8::/64 address which is assigned for documentation use.
My network for the easy bit
I have 2 Laptops and a Server all running Linux.
From my internet router I could see the information for LT2
Where GUA is the Global address (known outside of my network).
On Linux I can use the ip -6 addr command to display the address of the connection. A connector can have more than one address.
On the server machine, the addresses were
wlxd037450ab7ac: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000
inet6 xxxx:xxxx:xxxx:xxxx:7694:3711:8f98:7271/64 scope global temporary dynamic...
inet6 xxxx:xxxx:xxxx:xxxx:a5e4:61a:b3b2:9d8b/64 scope global dynamic mngtmpaddr noprefixroute ...
inet6 fe80::216a:2b1d:c908:eb39/64 scope link noprefixroute
Every time I rebooted, the xxxx… was the same, but the rest of the address was different.
The global address share the same prefix xxxx:xxxx:xxxx:xxxx/64, which is the address my Internet Service Provider allocated to my home.
The Link-Local fe80:: is only used within the use of its interface. The address should be stable across reboots, but may change if you change the configuration.
Talking between the Linux systems.
On LT2 I could issue ping xxxx:xxxx:xxxx:xxxx:7694:3711:8f98:7271 to the Server, and this worked.
Create your own addresses
The string xxxx:xxxx:xxxx:xxxx:7694:3711:8f98:7271 is very long, and changes every time I restart Linux. This means I had to manually type the long address in when trying to use it This was tedious for ping, and if I used ssh to logon to the box, every time it asked me about the authentication of the host.
You can create your own address for an interface.
sudo ip -6 addr add xxxx:xxxx:xxxx:xxxx::cccc dev wlxd037450ab7ac
It has to use the same 64 left bits xxxx:xxxx:xxxx:xxxx,;the remaining bits can be almost anything. I like nice short ::4 or ::cccc type values
I issued that command on the server, and I was able to successfully ping that address from my laptop. How does that work?
On my laptop I issued the ping command. Linux did not have any routing information for it, so it was sent using the default route to the wireless router.
The wireless router did not know about the address, so issued a multicast address to all(3) systems connected to it. “Does any one have xxxx:xxxx:xxxx:xxxx::cccc”.
Laptop1 got the request – and as it did not have the address – it ignored the request.
The Server got the request – and as it did have the address – it replied “I have xxxx:xxxx:xxxx:xxxx::cccc”.
The wireless router then forwards the ping request to the server, and cached the routing information.
If you look at the response times of the ping you can see the first request takes a long time
colinpaice@colinpaice:~$ ping xxxx:xxxx:xxxx:xxxx::cccc
PING xxxx:xxxx:xxxx:xxxx::cccc(xxxx:xxxx:xxxx:xxxx::cccc) 56 data bytes
64 bytes from xxxx:xxxx:xxxx:xxxx::cccc: icmp_seq=1 ttl=64 time=383 ms
64 bytes from xxxx:xxxx:xxxx:xxxx::cccc: icmp_seq=2 ttl=64 time=74.5 ms
64 bytes from xxxx:xxxx:xxxx:xxxx::cccc: icmp_seq=3 ttl=64 time=6.95 ms
This information is cached on the Linux, and in the router.
For example ip -6 neigh gives
xxxx:xxxx:xxxx:xxxx::88 dev wlp4s0 lladdr 00:24:d6:5e:2e:d2 REACHABLE
After a few minutes the output is
xxxx:xxxx:xxxx:xxxx::88 dev wlp4s0 lladdr 00:24:d6:5e:2e:d2 STALE
The time for an entry to become stale is based on /proc/sys/net/ipv6/neigh/…/base_reachable_time. On my Linux system this is 30 seconds.
The above was the easy bit….
A more complex example – adding in a host without wireless access.
Laptop to z/OS
This configuration is the same as the first example with the addition of an Ethernet connection going to z/OS.
For z/OS to work with the Laptops, the wireless router needs to be told about the IP addresses on z/OS
One of the addresses for z/OS on the Ethernet-like connection from the server is 2001:db8:e::9. There are no 2a00… (xxxx…) addresses on z/OS because z/OS is not attached to the wireless network.
If I ping the 2001:db8:e::9 address from a laptop, it does not complete successfully. Looking at the traffic from the wireless router to the server, there is no traffic for 2001:db8:…
I had to use radvd on the Server to act as a router. The radvd configuration for the wireless router was
The route…{} says I (the Linux system) know about this IP address range.
When this was activated, I could see a router advertisement of 2001:db8:e::/64 being sent to the wireless router. After this, there was traffic from the wireless router down to the server.
Ping to 2001:db8:1::9 on z/OS was successful. I stopped the radvd process on the server, and after about 3 minutes ping stopped working. This is because the information sent from radvd into wireless router gets stale and eventually deleted. Typically the radvd tasks sends the information regularly, so the wireless router has up to date routing information.
The source of the ping was xxxx:xxxx:xxxx:xxxx:84ce:f350:1dce:b4bf, the Laptop end of the wireless connection.
On z/OS this was routed through via the default route, xxxx:xxxx:xxxx:xxxx:84ce:f350:1dce:b4bf which was the Server end of the connection from z/OS.
The server either knew the route to my laptop, or it used the default to send it view the wireless router, which knew to send it to the laptop.
Pinging from z/OS
From z/OS I could successfully ping xxxx:xxxx:xxxx:xxxx:84ce:f350:1dce:b4bf. The request went via the z/OS default route to the server, and then via the wireless router to the laptop.
The reply (destination 2001:db8:1::9) went via the route described in laptop to z/OS above.
An even more complex example – doing it without using defaults.
I had this situation because the wireless dongle on the server was not very reliable and kept dropping the connection. This made it very hard to diagnose problem, as sometimes a ping would work – and a short while later, it would not work – and I assumed it was the configuration changes I was making.
Now that I understand more about Dynamic Routing and Neighbor Discovery, setting this up was remarkably easy. I’m sure there must be something I have missed.
Usually when I used ping on my laptop, it used the IP address I had created, 2008::5. I could see this in the Wireshark trace going to z/OS. When playing around with the wireless adapter, sometimes ping used the wireless address, and the ping failed, because z/OS did not know how to route back to the wireless address. Ping gave me a warning Warning: source address might be selected on device other than: enp0s31f6.
sudo ip -6 route add 2001:0db8:1::9/64 dev tap1
sudo ip -6 route del 2001:0db8:1::9/64 dev tap1
sudo ip -6 route flush 2001:0db8:1::9/64 dev tap1
sudo ip -6 -statistics route flush 2001:0db8:1::9/64 dev tap1
Some information may be stored in the neighbour cache so you may need to use commands like:
sudo ip -6 neigh flush to 2001:db8:1::9
sudo ip -6 neigh flush dev tap1
z/OS
You define static routes between BEGINRoutes and ENDRoutes. If you want to change one entry, you have to replace all entries. You cannot add or remove individual entries.
You cannot have an empty BEGINRoute… ENDRoute. If used, it has to have at least one entry. You can create a dummy entry that will never be used.
You can change this file, and use the OBEY command to activate it
v tcpip,tcpip,obeyfile,USER.Z24C.TCPPARMS(routefc)
To delete an entry, remove it from the file, and activate the file.
Dynamic routes
Dynamic routes are created from facilities like radvd on Linux. This defines capability available on an interface.
Query Neighbor cache for 2001:db8:1:0:8024:bff:fe45:840c
IntfName: IFPORTCP6 IntfType: IPAQENET6
LinkLayerAddr: 82240B45840C State: Reachable
Type: Router AdvDfltRtr: No
Query Neighbor cache for fe80::8024:bff:fe45:840c
IntfName: IFPORTCP6 IntfType: IPAQENET6
LinkLayerAddr: 82240B45840C State: Reachable
Type: Router AdvDfltRtr: No
Query Neighbor cache for fe80::9863:1eff:fe13:1408
IntfName: JFPORTCP6 IntfType: IPAQENET6
LinkLayerAddr: 9A631E131408 State: Reachable
Type: Router AdvDfltRtr: No
On Linux the
ip -6 addr
command gave me
tap1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UNKNOWN qlen 1000
inet6 2001:db8:1:0:b0fd:f92b:8362:577b/64 ...
inet6 2001:db8:1:0:8024:bff:fe45:840c/64 ...
inet6 fe80::8024:bff:fe45:840c/64 ...
tap2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UNKNOWN qlen 1000
inet6 fe80::9863:1eff:fe13:1408/64 ...
The TSO output means
Query Neighbor cache for 2001:db8:1:0:8024:bff:fe45:840c. The address is one of the addresses on the remote end of the connection. There is an entry because some traffic came via the address.
IntfName: IFPORTCP6 The z/OS Interface name used to create the defintion
IntfType: IPAQENET6 the OSA-Express QDIO interfaces statement
LinkLayerAddr: 82240B45840C
State: Reachable Other options can include stale, which means z/OS has not heard anything from this address for a while
Type: Router
AdvDfltRtr: No. The information passed in the Router Advertisement, said this was connection does not Advertise a DefaultRouter(AdvDfltRtr).
From the NETSTAT ND output we can see data has been received from
IFPORTCP6:2001:db8:1:0:8024:bff:fe45:840c
IFPORTCP6:fe80::8024:bff:fe45:840c
JFPORTCP6:fe80::9863:1eff:fe13:1408
To get data to flow down the 2001…. address I had to use
As one of the many problems I had trying to get IPV6 routing to work, I found that I could run a configuration script, and it would all work successfully (including a ping) – then a few seconds later, a manual ping would not work.
I had a shell script to display all my IP configuration information, to display the route information all in one line… including
ROUTE ::1 dev lo proto kernel metric 256 pref medium
ROUTE 2001:db8::/64 dev enp0s31f6 proto ra metric 100 pref medium
ROUTE 2001:db8::/64 dev enp0s31f6 proto kernel metric 256 expires 86395sec pref medium
ROUTE 2001:db99::/64 dev enp0s31f6 proto ra metric 100 pref medium
ROUTE 2a00:23c5:978f:6e01::/64 dev wlp4s0 proto ra metric 600 pref medium
ROUTE fe80::/64 dev enp0s31f6 proto kernel metric 100 pref medium
ROUTE fe80::/64 dev wlp4s0 proto kernel metric 600 pref medium
ROUTE default via fe80::966a:b0ff:fe85:54a7 dev wlp4s0 proto ra metric 600 pref medium
ROUTE default via fe80::a2f0:9936:ddfd:95fa dev enp0s31f6 proto ra metric 1024 expires 132sec hoplimit 64 pref medium
ROUTE default via fe80::a2f0:9936:ddfd:95fa dev enp0s31f6 proto ra metric 20100 pref medium
Some interesting information in this display (see the man page here)
ROUTE 2001:db8::/64 dev enp0s31f6 proto ra metric 100 pref medium
2001:db8::/64, this is the prefix of length 64 bits so 2001:db8:0:0. It is the address range 2001:0db8:0000:0000…. where …. is 0000:0000:0000:0000 to ffff:ffff:ffff:ffff
dev enp0s31f6 is the device (also known as the interface)
proto ra. The protocol was installed by Router Discovery protocol
metric 100. When there is a choice of valid routes, the lower the metric, the more it is favoured.
pref medium. Preference medium (out of high, medium, low).
Another interesting one is
ROUTE default via fe80::a2f0:9936:ddfd:95fa dev enp0s31f6 proto ra metric 20100 pref medium
If no other routes are found use the default, route, via enp0s31f6, installed by router discovery protocol(ra).
The metric is 20100 – so a low priority value.
A short while later, when ping failed, there was an additional route
ROUTE default via fe80::966a:b0ff:fe85:54a7 dev wlp4s0 proto ra metric 600 pref medium
With this the metric is 600 – which is lower than 20100 from before, so packets were sent to the wireless interface – which did not know what to do with them, and dropped them!
Solution
I used
sudo ip -6 route replace default via fe80::a2f0:9936:ddfd:95fa dev enp0s31f6 proto ra metric 200 pref medium
where the metric value was lower than the metric value for the wireless connection, and ping worked.
The above solution worked, but the IP v6 address changed from day to day. The following worked better as it has a permanent global address.
sudo ip -6 route replace default via 2001:db8::2 dev enp0s31f6 proto ra metric 200 pref medium
where 2001:db8::2 is the IP address of the connection on the remote, server, machine. This was done using
For me this was an epic journey, taking weeks to get working. It was like a magical combination lock, which will not open unless all of the parameters are correct, today has an ‘r’ in the month, and you are standing on one leg. Once you know the secrets, it is easy.
With IP V6 there is a technology called dynamic discovery which is meant to make configuring your IP network much easier. Each node asks the adjacent nodes what IP addresses they have, and so your connection to the next box magically works. I could not get this to work, and thought I would do the simpler task of static configuration – this had similar problems – but they were smaller problems.
There were twothree fourfivesix seven key things that were needed to get ping to work in my setup:
The key things
Allow forwarding between interfaces
On Linux
sudo sysctl -w net.ipv6.conf.all.forwarding=1
The documentationsays “… conf/all/forwarding – Enable global IPv6 forwarding between all interfaces”.
Clearing the cache
Routing and neighbourhood definitions are cached for a period. If you change a definition, and activate it, an old definition may still be used. I found I got different results if I rebooted, re-ipled, or went for a cup of tea; it worked – then next time I tried it with the same definitions, it did not work. Clearing the routing and neighbourhood cache made it more consistent.
On z/OS use V TCPIP,,PURGECACHE,IFPORTCP6
On Linux use sudo ip -6 neigh flush all
Put a delay between creating definitions and using them.
I had a 2 second delay between creating a definition, and using it, which helped getting it to work. I think data is propagated between the system, and issuing a ping or other command immediately after a definition, was too fast for it,
A timing window
I had scripts to clear and redefine the definitions. Some times if I ran the laptop script then the server script, then ping would not work. If I reran the laptop script, then usually ping worked. Sometimes I had to rerun the server script.
The default route would often change.
The wireless connection to the server was unreliable. There would be a route from my laptop to the server via the wireless. Then a few minutes later the connection to the server would stop, and so alternate routes had to be used, because traffic via the wireless would be dropped.
I got around this problem, by explicit coding of the routes and not needing to use the default definitions. (Also disabled the wireless connection while debugging)
The correct route syntax
I found I was getting “Neigbor Solicitation” instead of the static routing. To prevent this the route on the laptop needed the via…
sudo ip -6 route add 2001:db8:1::9/128 via 2001:db8::2 dev enp0s31f6
and not
sudo ip -6 route add 2001:db8:1::9/128 dev enp0s31f6
BEGINRoutes
; Destination FirstHop LinkName Size
ROUTE default6 2001:db8:99::3 IF2 MTU 1492
ROUTE 2001:db8:99::/64 2001:db8:99::3 IF2 MTU 5000
ROUTE 2001:db8::/64 2001:db8:1::3 IFPORTCP6 MTU 5000
ROUTE 2001:db8:1::/64 2001:db8:1::3 IFPORTCP6 MTU 5000
ENDRoutes
Where
default6 says if no other routes match, then send the traffic down IF2 connection. At the remote end of the IF2 connection, it has IP address 2001:db8:99::3.
Traffic for 2001:db8:99::/64 should be sent down interface IF2 – which has an address 2001:db8:99::3 at the remote end
Traffic for 2001:db8::/64 (2001:db8:0::/64) should be sent down interface IFPORTCP6 which has address 2001:db8:1::3 at the remote end.
Traffic for 2001:db8:1::/64 should be sent down interface IFPORTCP6 which has address 2001:db8:1::3 at the remote end.
I needed a route for both 2001:db8::/64 and 2001:db8:1::/64 as one was the route to the laptop, the other was the route to the Linux server.
Linux Server machine
On my Linux machine I had
from ip -6 addr
tap1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UNKNOWN qlen 1000
inet6 2001:db8:1::3/64 scope global
valid_lft forever preferred_lft forever
inet6 2001:db8::3/64 scope global
valid_lft forever preferred_lft forever
inet6 fe80::e852:31ff:fe0f:81da/64 scope link
valid_lft forever preferred_lft forever
I used the global address 2001:db8:1::3 in my z/OS routing statement.
The documentation implies I should use the link-local address fe80::e852:31ff:fe0f:81da in my static z/OS definitions, but I could not see how to use this, as it changed every time I ipled my z/OS. This means I need to explicitly define an address on Linux for this connection ( 2001:db8:1::3).
Linux Server definitions
On my Linux server I defined static definitions.
sudo sysctl -w net.ipv6.conf.all.forwarding=1
# clear the state every time
sudo ip -6 route flush root 2001:db8:1::/64
sudo ip -6 route flush root 2001:db8::/64
sudo ip -6 neigh flush all
# define the interface to z/OS
sudo ip -6 addr del 2001:db8:1::3/64 dev tap1
sudo ip -6 addr add 2001:db8:1::3/64 dev tap1
sudo ip -6 addr del 2001:db8::2/64 dev eno1
sudo ip -6 addr add 2001:db8::2/64 dev eno1
sudo ip -6 route del 2001:db8::/64 dev eno1
sudo ip -6 route add 2001:db8::/64 dev eno1
sudo ip -6 route del 2001:db8:1::9 dev tap1
sudo ip -6 route add 2001:db8:1::/64 dev tap1
# sudo traceroute -d -m 2 -n -q 1 -I 2001:db8::7
# ping 2001:db8::7 -c 1 -r
# ping 2001:db8:1::9 -c 1 -r
This script grew as I added all of the options to get it to work.
The statements are
sudo sysctl -w net.ipv6.conf.all.forwarding=1
This enables the cross interface traffic.
sudo ip -6 route flush root 2001:db8:1::/64 sudo ip -6 route flush root 2001:db8::/64 sudo ip -6 neigh flush all
These clear the routing for the two addresses, and for the neighbourhood cache. I do not know if these are required, without them the results were not consistent.
#give the interface to z/OS an explicit address sudo ip -6 addr del 2001:db8:1::3/64 dev tap1 sudo ip -6 addr add 2001:db8:1::3/64 dev tap1
#give the connection to the Laptop an explicit address sudo ip -6 addr del 2001:db8::2/64 dev eno1 sudo ip -6 addr add 2001:db8::2/64 dev eno1
These deleted then created global addresses for the server end of the interfaces.
sudo ip -6 route del 2001:db8::/64 dev eno1 sudo ip -6 route add 2001:db8::/64 dev eno1
sudo ip -6 route del 2001:db8:1:: dev tap1 sudo ip -6 route add 2001:db8:1:: dev tap1
These deleted and created routes the traffic to the interfaces. I could have used route rep…
Linux Laptop definitions
#Give the ethernet connection to the server an explicit address sudo ip -6 addr add 2001:db8::19 dev enp0s31f6
#create the route to the server using the via sudo ip -6 route del 2001:db8:1::/64 dev enp0s31f6 sudo ip -6 route add 2001:db8:1::/64 via 2001:db8::2 dev enp0s31f6
I needed to specify
an explicit to the address of the interface to the server, so it could be used as a destination from z/OS.
the route to get to the server. I needed to specify the via, so the static route was used directly. Without the via, it tried to use Neighbourhood discovery.
If I pinged 2001:db8:1::9 (z/OS) from the Linux server (the end of the IFPORTCP6 connection) the traffic came from address 2001:db8:1::3, The reply was sent back using the matching 2001:db8:1::/64 definitions.
If I pinged 2001:db8:1::9 (z/OS) from my laptop, through the Linux server to z/OS, the traffic came from address 2001:db8::7. The reply was sent back using the matching 2001:db8::/64 definitions.
If I pinged 2001:db8::7 (laptop) from z/OS it was sent back using the matching 2001:db8::/64 definitions.
An IP V4 address is like 192.6.24.56, where each number is between 0 and 255 inclusive (8 bits). You see routing statements like 192.6.24.9/24 which means the left 24 bits are significant for routing. 192.6.24.99/24 is routed the same as 192.6.24.22/24 because 192.6.24.n/24 refers to the range 192.6.24.0 to 192.6.24.255.
IP V6 addressing
IP V6 addresses are like abcd:efgh:ijkl:mnop:qrst:uvwx:yzab:cdef – or 8 groups of 4 hex digits.
Within each group leading zeros can be dropped.
The longest sequence of consecutive all-zero fields is replaced with two colons (::).
fe80:0000:0000:0000:11ad:b884:0000:0084 can be written fe80:0:0:0:11ad:b884:0:84 which can be written fe80::11ad:b884:0:84, which is a more manageable number to use.
I tend to use addresses like fe00::4 because they are short!
IP V6 prefixes
An Internet Service Provider (ISP) provides connectivity to its users. Each enterprise customer, or end user, is allocated a prefix, usually 48 digits long, and you have 16 digits for routers (the subnet) within your organisation. Normally the total prefix length is 64.
At home with a wireless router, my laptops address is 2a00:dddd:ffff:1111:65fa:229:f923:84b8. 2a00:dddd:ffff from my ISP and my subnet is 1111 within my organisation.
An address like 2001:db8::/64 is the range 2001:db8:0:0:0:0:0:0 to 2001:db8:0:0:ffff:ffff:ffff:ffff.
An address like 2001:db8::9/128 is the single address 2001:db8:0:0:0:0:0:9, because all digits are significant.
There are different levels of IP V6 addresses
Addresses starting with fe80::, called link-local addresses, are assigned to interfaces for communication on the attached link. If you think of lots of machines on an Ethernet connection, they have a fe80… address. They tend to be used internally by Dynamic Routing. I haven’t explicitly used one.
“global” addresses – or not on an Ethernet cable.
fc00::/7 Unique Local Addresses (ULA) – also known as “Private” IPv6 addresses. They are only valid within an enterprise.
2…::/16 Global Unique Addresses (GUA) – Routable IPv6 addresses. These addresses allow you to access resources, such as web sites, outside of your domain. My ISP provides me with an address 2a00:abcd:….
Reserved addresses
Some addresses are reserved, for example
2001:db8::/32 is reserved for documentation, these addresses do not leave your enterprise.
fe80::/10 Addresses in the link-local prefix. These are allocated to the “cable” or connection between two nodes. Two different “network cables” can have the same fe80… address because they are on different cables.
fc00/12 are addresses which are within your enterprise. Routers will not send these addresses out of its domain.
ff02::1 Multicast, all nodes in the link-local
ff02::2 Muticast, all routers in the link-local
ff05::2 All routers in the site-local (in your machine)
If I define an address for connection (on Linux) I can use
sudo ip -6 addr add 2001::99 dev tap1, this is one address. When displayed this gives 2001::99/128
sudo ip -6 addr add 2001::999/64 dev tap1, this is an address, and when used in routing, use the left 64 bits. When displayed this gives 2001::999/64
Routing
It is important to understand how the prefix affects the routing behaviour.
If I have two Ethernet connections(interfaces) into my laptop. I want traffic for 2001::a:0:0:0 to go via interface A, and traffic for 2001::b:0:0:0 to go via interface B.
If I use
sudo ip -6 route add 2001::a:0:0:0/64 dev A
sudo ip -6 route add 2001::b:0:0:0/64 dev B
then this will not always work. With 2001::a:0:0:0/64 the prefix is 2001:0:0:0:a:0:0:0/64. When comparing a packet with address 2001::b:0:0:0 with each route; both routes are available, because 2001:0:0:0 matches both, and if the packet gets sent to 2001::b:0:0:0 it will be lost.
You either need to move the a/b to make them significant, 2001:0:0:a::/64 and 2001:0:0:b::/64 or use 2001:0:0:0:a::/80 and 2001:0:0:0:b::/80 in the routing statements.
The system needs to be able to route traffic to the correct interface, so you need to be careful how you set up the routing.
Does this make sense?
Specifying
sudo ip -6 route add 2001:db8::99/64 dev eno1 metric 1024 pref medium
is the same as
sudo ip -6 route add 2001:db8::/64 dev eno1 metric 1024 pref medium
because the routing only looks at the left 64 bits. The ::99 is ignored.
Having the :99 makes it a bit more confusing for those stumbling about trying to understand this topic. I’ve had to rewrite some of my blog posts where I use 2001:db8::99/64 in the routing.
In the case of
sudo ip -6 route add 2001:db8::99/128 dev eno1 metric 1024 pref medium
the ::99 is relevant. A packet for 2001:db8::98 would not be routed down this definition because all 128 bits of the route definition are relevant.
My two day project to deploy IP V6 dynamic routing, turned into an eight week project before I got it to work.
I am documenting a lot of what I learned – today’s experience is understanding what radvd is and what the configuration options mean. I found a lot of documentation – most of which either assumed you know a lot, or only provided an incomplete description.
High level view of what radvd provides
There are several ways of providing configuration to TCPIP. One way is using radvd (on Linux).
In a configuration file you give
An interface name
Which IP addresses (and address ranges) are available at the remote end of the connection.
Which IP addresses (and address ranges) are available at the local end of the connection
From the information about the local end, the remote end can build its routing tables.
Background IP routing
With IP you can have
static routing, where you explicitly give the routes to a destination – such as to get to a.b.c.d – go via xyz interface. You have to do a lot of administration defining the addresses of each end of an interface (think Ethernet cable)
dynamic routing, and neighbourhood discovery, where the system automatically finds the neighbours and there is less work for an administrator to do.
With IPv6 you have
global addresses with IP addresses like 2001:db8:1:16…..
link-local addresses. These are specific to an interface. An Ethernet connection can have many terminals hanging off ‘the bus’. The link-local address is only used within the connection. A different Ethernet cable can use the same address. There is no problem as the addresses are only used with the cable.
Neighbour Discovery. Rather than specify every thing as you do with static routing, IP V6 supports Neighbour Discovery, where each node can tell connected nodes, what routes and IP addresses it knows about. This is documented in the specification. This supports
Router Advertisement (RA), (“Hello, I’m a router, I know about the following addresses and routes”),
Router Solicitation (RS), (“Hello, I’ve just started up, are there any routers out there?”),
Neighbour Solicitation(NS) (“Does anyone have this IP address?”), and
Neighbour Advertisement (Usually in response to a Neighbour Solicitation, “I have this address”).
What is radvd?
The radvd program is a Router Advertisment Daemon (RADvd) which provides fakes router information – but is not a router.
You specify a configuration file. The syntax is defined here.
You can specify that this interface provides a “default” route. See here.
Example definition
I have a Linux Server, and a laptop running Linux connected by an Ethernet cable.
2001:ccc::/64 is the ipv6 address range or, to say it another way, ipv6 addresses with the left 64 bits beginning with 2001:0ccc:0000:0000. In IP V6 this is known as the prefix.
Basically this prefix statement means “this interface is a route to the specified prefix”.
This creates some addresses on the server for the connection.
eno1 inet6 2001:ccc::e02a:943b:3642:1d73/64 scope global temporary dynamic...
eno1 inet6 2001:ccc::dbf:5c90:61a6:20ae/64 scope global dynamic mngtmpaddr...
eno1 inet6 2001:ccc::c48b:e8f1:495c:5b52/64 scope global temporary dynamic ...
eno1 inet6 2001:ccc::2d8:61ff:fee9:312a/64 scope global dynamic mngtmpaddr ...
create routes
The prefix statement creates a route on the server to get to the laptop
2001:ccc::/64 dev eno1 proto ra metric 100 pref medium
2001:ccc::/64 dev eno1 proto kernel metric 256 ...
This says that on the server, if there is a request for an address in the range 2001:ccc::/64 send it via device eno1.
route 2001:ff99::/64 statement.
This passes information to the remote end of the connection, see below. It says “I (the server) know how to route to 2001:ff99::/64”.
It the routing address does not show up in any ip -6 commands on the server.
Polling
The radvd code periodically sends information along the connection to the other end, at an interval you specify. See radvdump below on how to display it.
At the other end of the connection…
At the remote (laptop) end of the connection, using WiresShark to display the data received, shows a Router Advertisement with
Internet Protocol Version 6, Src: fe80::a2f0:9936:ddfd:95fa, Dst: ff02::1
Internet Control Message Protocol v6
Type: Router Advertisement (134)
...
ICMPv6 Option (Prefix information : 2001:ccc::/64)
ICMPv6 Option (Route Information : Medium 2001:ff99::/64)
ICMPv6 Option (Source link-layer address : 00:d8:61:e9:31:2a)
Where
fe80::a2f0:9936:ddfd:95fa is the link-local address on the server machine
ff02::1 the multicast address “All nodes” on a link (link-local scope)”
Prefix information : 2001:ccc::7/64 the prefix of the IP address 2001:ccc:0:0…
Route Information : Medium 2001:ff99::/64 This is from the “route” in the radvd configuration file on the Linux Server. It tells the laptop that this connection knows about routing to 2001:ccc::/64 .
From the route information it dynamically creates a route on the laptop to the server.
2001:ff99::/64 via fe80::a2f0:9936:ddfd:95fa dev enp0s31f6 proto ra metric 100 ...
This creates a route to 2001:ff99::/64 via the IP address fe80::….95fa, from the laptop end of the Ethernet connection with name enp0s31f6 to where-ever the connection goes to (in this example it goes to my server).
If I ping 2001:ffcc::9 from the laptop, it will use this route on its way to the z/OS server.
Connection to z/OS
Within the radvd.conf file is the definition to get to z/OS. This interface looks like an Ethernet (the ip -6 link command gives link/ether). This is for a different radvd configuration file to the earlier example.
This says there are IP addresses in the range 2001:db8:1::/64 via this connection. z/OS reads the Router Advertisement and creates a route for them. TSO Netstat route gives
In UHD, the U says the interface is Up, the H says this is for a host (a specific end point), and the D says this is dynamically created.
If you try to ping 2001:db8:1::99 from the server, a Neighbour Solicitation request is sent from the server to z/OS, asking “do you have 2001:db8:1:99?”. My z/OS did not have that defined and so did not respond.
When I defined this address on z/OS TCPIP using the obeyfile
After this, the ping was successful because there was a neighbour solicitation for 2001:db8:1::99, and z/OS replied with Neighbour Advertisement of 2001:db8:1::9 saying I have it.
Create a default route
If you specify AdvDefaultLifetime 0 on the interface, this indicates that the router is not a default router and should not appear on the default router list in the Router Advertiser broadcasts. If the value is non zero, the recipient, can use this connection as a default route, for example there is no existing default route. A statically defined default will be used in preference to a dynamically defined one.
Use radvdump to display what it sent in the RA
You can use sudo radvdump to display what is being sent in the Router Advertiser message broadcast over multicast. It looks just like the radvd.conf file.
and so have data sets based on the invoked job name. This means you can simplify your started task procedures, and may not need the user to specify overrides on the start command.
Note: If you move to using JOBNAME= instead of specifying a .identifier, you may need to change other definitions. For example TCPIP defines port 520 with jobname OMPROUTE. If you switch to using OMPROUTE,JOBNAME=OMP1 this jobname will need to change to OMP1.
&SYSJOBID
gives a value like STC08460 for a started task.
&SYSUID
gives the userid like IBMUSER
&JOBNAME
gives the job assigned to the address space in which the JCL is converted, so JES2 for me.