[OLSR-users] Running two insances of olsr

Cyrille Chepelov (spam-protected)
Tue Jun 22 14:24:51 CEST 2004


Le Tue, Jun 22, 2004, à 01:46:54PM -0800, Andreas Tønnesen a écrit:
> Hi,
> 
> the quick-and-dirty way of doing this is to use different UDP ports
> for the two instances. E.g. you change the definition of OLSRPORT
> in src/olsr_protocol.h from the IANA assigned port 698 to some
> port in the "private" port space for all IPv6 olsr daemons.
> If trying to use the same port the socket binding will crash.
> 
> I was under the understanding that UDP ports were different entities
> when using IPv6 from IPv4... but this seems not to be the case. I guess
> since UDP is above IP in the layered model, the IPversion is actually
> transparent to the transport layer? If this is the case, then no
> services can run instances in both IPv4 and IPv6 binding to the same
> port...
> Please clarify if I'm wrong.

Actually, the whole ipv4 address space is embedded within the ipv6
address space, at ::ffff/96.  
If you're listening to ::/0, UDP port 698, then you're
going to see both incoming ipv6 and ipv4 connections (if at least one of
the interfaces has an ipv4-reachable address). 
One typical example is exim4, which binds to ::/0 port tcp/25, and gets
both inbound ipv4 and ipv6 connections (and IIRC, it's transparent).

So, two scenarios can happen:
	1. olsrd for v4 starts first
* olsrd/ipv4 binds to udp/698, as a v4 socket. No ipv6 traffic can come in.
* olsrd/ipv6 then starts, and fails to bind.
* when an ipv6 peer tries to bind to udp/698, it fails as there's only an 
ipv4 host.
	2. olsrd for v6 starts first
* olsrd/ipv6 binds to udp/698, as a v6 socket. Theoretically, v4 peers
can reach that socket (provided there is at least one v4-accessible
address on one of the interfaces)
* olsrd/ipv4 then starts, and fails to bind.
* when an ipv4 peer tries to bind to udp/698, it succeeds BUT ???

where ??? = likely, since olsr/ipv6 "knows" it runs in ipv6 mode, it
can't parse messages originating from ipv4 peers, and hopefully discards
them (though I don't see why it shouldn't do horrible things with them
instead... it might be a good idea to throw a single olsrd-ipv6 running
under valgrind into a large ipv4 network, to check what happens. Hmmm,
tried, not too terrible, just a good way to receive garbage routes).

The problem is that you can't filter ipv4 and ipv6 traffic even though
you need it (unlike exim4), as you are using one broad socket per
interface.

IMHO, a good way to get out of this trap is to perform the following
change:
	* instead of creating one socket per network device, enumerate
the list of all network interfaces and all their possible addresses
(remember v6 can have more than one address per interface), 
skipping 127.0.0.1 and ::1, and then start filtering based on the
configuration file. ipv6 disabled? skip ipv6 interfaces. Global ipv6
addresses disabled? skip the address if it's not at most site-local.
Etc.
At the end, you have a list of addresses, which you know whether they're
v4 or v6; in my case, I'd end up with something like:

10.255.255.1/24, v4, eth0
2001:7a8:29d4:0:2a0:24ff:fea6:57a0/64, v6, eth0
2001:7a8:29d4::1/64, v6, eth0
## fe80::2a0:24ff:fea6:57a0/64, v6, eth0 ##skipped: link-local
## 127.0.0.1/8, v4, lo ## skipped: loopback
## ::1/128, v6, lo ## skipped: loopback
## fe80::2e0:98ff:feb5:18df/64, v6, eth1 ##skipped: link-local
	# (yes, my eth1 is not used right now: just got around to
	# checking that it's a prism54 and that's all I had the time to
	# do)

Now, for each of the specific three addresses above, create a listening
socket. Have exactly one ipv6 per physical interface join the multicast
group and send broadcast messages? Not sure. Initially we might just
leave duplicate traffic, maybe we'd better have one ipv6 address per network 
perform multicast duties. Or maybe the RFC covers this already.
As you now know for each socket, whether it's supposed to receive v4 or
v6 traffic, you can run the correct packet parser.


Yes, the global "ipversion" variable must die, that's the unpleasant
part. It now must live in struct olsr_socket_entry. The more pleasant
part is that you already have a good deal of the infrastructure in
place, it seems that you need to split olsr_input() into olsr_input_v4()
and olsr_input_v6() siblings -- it may even be easy to do it the quick
and dirty way, by passing ipversion as a parameter to olsr_input(), and
making the _v4() and _v6() simple wrappers around that.

I'm really sorry I'm pontificating here without offering patches, but
right now my available time is near zero (but I'll be willing,
eventually).

	-- Cyrille
	
-- 



More information about the Olsr-users mailing list