[quagga-dev 4431] Re: [quagga-users 7613] Re: FW: Unicast routing with OSPF
Andrew J. Schorr
aschorr at telemetry-investments.com
Wed Oct 11 16:33:49 BST 2006
On Fri, Oct 06, 2006 at 07:52:24PM +0100, Paul Jakma wrote:
> On Wed, 4 Oct 2006, Andrew J. Schorr wrote:
> >Have you tried using a CVS 0.99 snapshot with my PtP over ethernet
> >patch (attached)? This may help...
> Looks good.
Thanks for the feedback. And sorry I'm so slow to respond, we just
moved offices this past Saturday, so everything is still in boxes...
> - Do we really need the more lax 'CONNECTED_ID'? Why would the local
> address be unique if its in same subnet? If the local address has a
> range > 1, then why use PtP addressing? Shouldn't we just have
> 'CONNECTED_PREFIX' everywhere?
I agree that this is the ugliest aspect of the patch, and I put this
in only very reluctantly. If you look in the tree, you will see
that CONNECTED_ID is used in only 3 places. If I could find a way to
eliminate those 3 uses, I would be happy to do so. But I do believe
that all uses of CONNECTED_ID in the patch are consistent with the code's
So why is CONNECTED_ID required? The basic idea is that there may
be some situations in which you want to try to identify a particular
'struct connected' by a single associated address. In general, this is
not possible, but there are nonetheless places in the code that call
for this. So if you had to try to select an address that you could
use for identification, what would it be? Well, if there's no peer
address assigned, then clearly you would just choose the local IP address.
But if there is a peer address, you must choose between the two. In the
typical case where the peer address is a /32, then you want to use
the peer address as the identifier. But there's one corner case in
which the user has assigned both a local and a peer address, and they
both live in the same subnet. For example, suppose the local
address is 192.168.1.1/30, and the peer address is 192.168.1.2/30.
In principle, there was probably no need to specify the peer address in such
a case, since the subnet assignment makes it clear enough what needs to be
done. But certainly linux, and I guess probably other platforms as well,
do not stop you from assigning a peer address in the same subnet. And in
such a case, I think you most likely want to use 192.168.1.1 as
the identifier, not 192.168.1.2.
OK, so where are the 3 places in the quagga code that actually require
such an identifier?
1. In ripd/rip_interface.c:rip_interface_multicast_set, we have this
addr = CONNECTED_ID(connected)->u.prefix4;
if (setsockopt_multicast_ipv4 (sock, IP_MULTICAST_IF, addr, 0,
connected->ifp->ifindex) < 0)
So which address should we pass to setsockopt_multicast_ipv4? If we're
lucky, we're on a platform that can use connected->ifp->ifindex to
identify the interface to the kernel. But if we're not on such a platform,
we need to try to select the address that the kernel would use to identify
the interface. Would it be OK always to use the peer address if it
exists (and ignore the strange case where peer and local are in the
same subnet)? Perhaps, I couldn't say without going through all the
kernel code. In linux, the relevant logic seems to be in
net/ipv4/fib_frontend.c:ip_dev_find where it calls
ip_fib_local_table->tb_lookup(address), but it's not obvious to me which
address we need. But if I conduct the following test:
bash$ modprobe ip_gre
bash$ ip tunnel add ptp0 mode gre remote 192.168.50.31 local 192.168.20.93
bash$ ip link set ptp0 up multicast on
bash$ ip addr add 192.168.52.1/30 peer 192.168.52.2/30 brd + dev ptp0
bash$ ip route ls table all | fgrep .52.
192.168.52.0/30 dev ptp0 proto kernel scope link src 192.168.52.1
broadcast 192.168.52.0 dev ptp0 table local proto kernel scope link src 192.168.52.1
local 192.168.52.1 dev ptp0 table local proto kernel scope host src 192.168.52.1
broadcast 192.168.52.3 dev ptp0 table local proto kernel scope link src 192.168.52.1
I get the impression that I need the 192.168.52.1 address in this case
(since there is no mention of 192.168.52.2 in the routing table), but
I certainly have doubts and am open to other opinions.
2. In ospfd/ospf_snmp.c:ospf_snmp_if_update, it needs an address
to use to identify the interface. As discussed above, CONNECTED_ID
is my best guess as to what that address should be (and should give
consistent behavior with the current code).
3. In ospfd/ospfd.c:ospf_network_run. This is the most complicated
case. But first off, let me again note that using CONNECTED_ID will
be consistent with the current behavior, since the patch looks like this:
- if (CONNECTED_POINTOPOINT_HOST(co))
- addr = co->destination;
- addr = co->address;
+ addr = CONNECTED_ID(co);
So the old code (part of my previous PtP patch) was ugly to begin with. :-)
So what is the 'addr' variable used for? It's used in one spot, where
this call is made: ospf_if_is_configured(ospf, &(addr->u.prefix4)).
We then have to look at ospf_interface.c:ospf_if_is_configured to see
what it expects as an argument. If oi->type is OSPF_IFTYPE_POINTOPOINT,
then the CONNECTED_ID address should match fine (since CONNECTED_PREFIX
should always match CONNECTED_ID). And it seems very unlikely
that there would be a peer address if the interface type is
not set to OSPF_IFTYPE_POINTOPOINT, so I don't think we really need
to worry about the other case very much. So I think we could possibly
use CONNECTED_PREFIX in this place instead of CONNECTED_ID,
if you prefer. But it might break some strange case where the
admin assigned a peer address, but did not set the interface
type to OSPF_IFTYPE_POINTOPOINT...
By the way, this raises the whole question of what the ospf_interface
'address' field is supposed to represent. Currently, it is set
to the struct connected 'address' field, but that's arguably not
very meaningful for a PtP /32 interface. But the code seems to work
at the moment, so I didn't muck with this. I'm not sure what happens
if you set it to CONNECTED_PREFIX instead, but that seems like
a more useful value to me (in the abstract).
Sorry to go on at such length, but this issue is a bit complicated...
> - The OSPF 'network' command needs to retain its 'greedy' matching
> behaviour, on both local and peer (if present) :)
Understood. And I think the current patch's behavior (where COMPATIBILITY_MODE
is defined by default) should give the same 'greedy' behavior that you desire.
I still personally think that the greedy behavior is inelegant, but I
certainly cannot impose my view on others...
More information about the Quagga-dev