[quagga-dev 10854] [Design] OSPF unnumbered interfaces

James Li jli at cumulusnetworks.com
Thu Oct 24 23:57:38 BST 2013


Some design notes I had to accompany the unnumbered patch. The work was 
based on 0.99.21, so part of it, the SPF nexthop changes, was already in 
master via this patch 
https://github.com/fweimer/quagga/commit/f2b53dac4c72811c06779c596c6162b994eb427a. 
I include it anyways for completeness.

1. Definitions

Numbered interface: is an interface with a unique IP address. Each 
router has
to have at least 1 numbered interface.

Unnumbered interface: is an interface that does NOT have its own unique IP
address. Instead, it borrows the IP address of a numbered interface.

RFC 1812, section 10.2.1 specifies that a router interface must be
EXPLICITLY CONFIGURED to be either numbered or unnumbered. A router MUST NOT
assume that an unconfigured interface is an unnumbered interface. [1]

2. Configuration

On a Quagga + Linux system, there are 2 user interfaces -- Quagga CLI 
and linux
commands. So in terms of configuring unnumbered interfaces, we have 3 
options.

2.1  Reference IP address via linux commands

On linux, an unnumbered interface is *explictly* configured by 
configuring the
interface with an IP address that is already on another interface. For 
example
with these 2 commands:

ifconfig eth7 103.0.0.1/24
ifconfig eth8 103.0.0.1/24

eth7 is a numbered interface with IP address 103.0.0.1, and eth8 is an 
unnumbered
interface. For the sake of discussion let's call eth7 the anchor 
interface, and
eth8 the unnumbered interface.

2.2 Reference IP address via Quagga CLI

interface eth7
   ip address 103.0.0.1/24
interface eth8
   ip address 103.0.0.1/24

Same thing here, eth7 is anchor, numbered, and eth8 is unnumbered.

2.3 Reference interface name via Quagga CLI

interface eth8
   ip address unnumbered eth7

This is similiar to cisco CLI. eth7 is the anchor, numbered, and eth8
is unnumbered.

The 3 options of configuration can coexist, although in the first patch
only one of them will be supported. The first option, via linux command is
chosen since no extra CLI work is needed.

3. Data structures

3.1. New flag in "struct interface"

A new flag ZEBRA_INTERFACE_UNNUMBERED is introduced to mark an interface
as unnumbered in "struct interface" in common if.c.

3.2 IP address based interface lookup table (IP-IF table)

The key of this table is unique IP addresses, and the table entry is an
anchor interface plus a list of unnumbered interfaces. The main job of
this table is to help us set or unset flag ZEBRA_INTERFACE_UNNUMBERED
on interfaces based on kernel notifications.

3.3 ifIndex based Interface lookup table (IFID-IF table)

The key of this table is unique interface index (ifIndex), and the table
entry is a Zebra "struct interface". This table is used in the nexthop
calculation in SPF.

4. Algorithm

4.1 Identifying unnumbered interfaces

This should be implemented in Zebra to be protocol independent.

When kernel notification of a new IP address comes to Zebra, a lookup is 
done
in IP-IF table. If an entry is found, there is already an anchor 
interface, so
the interface in the notification should be marked as unnumbered and 
added to
the list. If an entry is not found, this interface is the anchor 
interface and
is considered numbered.

An interface can change from unnumbered to numbered, and vice versa. The 
events that
can trigger this include:

For config option 1 and 2,
   * Change an unnumbered interface IP address to a unique IP address, 
or change an
     numbered interface IP address to the IP address of an anchor interface.
   * Change/Delete an anchor interface IP address, resulting in an 
unnumbered
     interface (the first one on the list off that anchor) being promoted to
     the anchor interface, hence becoming numbered
For config option 3,
   * Change "ip address unnumbered eth7" to "ip address x.x.x.x", or 
vice versa.

 From OSPF protocol's point of view, the handling of this kind of mode 
change is no
different from the handling of a unique IP address change of a numbered 
interface.
We just need to set or unset the ZEBRA_INTERFACE_UNNUMBERED flag, and 
trigger the
same chain of events like an IP address change.

4.2 OSPF protocol

4.2.1 IP address in protocol packets

On point to point networks, the destination IP address of protocol 
packets is
AllSPFRouters. The source IP address for packets going out of the unnumbered
interface should be the IP address of the anchor interface.

The HELLO packet contains the IP address mask of the attached network. On
unnumbered point to point networks, this field should be set to 0.0.0.0.
[RFC 2328, 9.5, pg 77]

4.2.2 Router LSA format

In router LSA, a Type 1 link to unnumbered interface should be added, with
link ID = neighbor router ID, and link data = local ifIndex. For 
numbered point
to point network, a Type 3 link (stub network) should be added; This stub
network link should not be added for unnumbered. The purpose of the stub
network link is to gain reachability to the 2 IP addresses of the 2 end 
points
of a point to point network, while for unnumbered interfaces there are no
IP addresses to reach. [RFC 2328, 12.4.1, pg 126]

4.3 SPF

4.3.1 Current implementation study

Let's first take a look at how the current Quagga OSPF uses the IP address
of a point to point network in its SPF.

The IP address is used in the nexthop calculation step of the SPF. This is
the case of RFC 2328 16.1.1 para 4, which is quoted here:

"In the first case, the parent vertex (V) is the
root (the calculating router itself).  This means that the
destination is either a directly connected network or directly
connected router.  The outgoing interface in this case is simply
the OSPF interface connecting to the destination network/router."

V = parent vertex = calculating router
W = destination router
l = Type 1 link from V to W
l2 = link from W to V

As unnumbered interface is only applicable to point to point network, we are
not interested in W being a transit network, and we are not interested
in the link l if it's not (Type 1) point to point.

The current implementation uses the link data in l to look up a local 
interface.
For numbered interfaces, the link data is the IP address. This lookup 
function is
ospf_if_is_configured().

If the ospf_interface (oi) is found and is point to point, the current code
does something seemingly questionable -- It tries to find the matching link
of l from W's links (matching link = IP in same subnet). The code looks like
this (ospf_spf.c: ospf_nexthop_calculation):

                   /* l is a regular point-to-point link.
                      Look for a link from W to V.
                    */
                   while ((l2 = ospf_get_next_link (w, v, l2)))
                     {
                       oi = ospf_if_is_configured (area->ospf,
&(l2->link_data));

                       if (oi == NULL)
                         continue;

                       if (!IPV4_ADDR_SAME (&oi->address->u.prefix4,
                                            &l->link_data))
                         continue;

                       break;
                     }

First impression I got reading this code is, that the logic is trying to 
make
sure there is a matching link on the adjacent router. Upon looking carefully
into RFC 2328, this is unnecessary. RFC says: "The outgoing interface in
this case is simply the OSPF interface connecting to the destination
network/router". So all is required here for nexthop is the interface, which
has been found already via ospf_if_is_configured(). The bidirectional
requirement has been satisfied earlier by the caller of 
ospf_nexthop_calculation.

So what's the purpose of finding the matching link on adjacent router? 
It's for
RFC 5309 style point to point connection over LAN. This feature is supported
in Quagga via this command:

Interface Command: ip ospf network point-to-point

This command results in a LAN interface to become type
OSPF_IFTYPE_POINTOPOINT in Quagga OSPF, and it will be treated as
a point to point interface in the protocol machinery.

For real point to point interface, there is no need for a nexthop IP
address for packet forwarding. All that is needed is the outgoing interface.
For a LAN interface, however, even if it's configured as a point to point,
for packet fowarding a nexthop IP address is needed. This nexthop IP address
is used to resolve to a MAC address. So what the code really tries to do is
to find the matching link l2 first, then use link data of l2 as the next hop
IP address.

So in summary, for nexthop calculation of numbered interfaces, the code

a) maps calculating router's router LSA link data into local interfaces. 
this
    is a lookup of local IP addresses in local IP-IF table.

b) maps destination router's router LSA link data into a matching link, 
by checking
    if local IP and remote IP addresses are on the same subnet.

c) Use the destination router's matching link data as the nexthop IP 
address.

4.3.2 On to unnumbered

Now to support unnumbered,

a) with unnumbered, the calculating router's router LSA link data is ifIndex
    instead of IP address. a lookup in local IFID-IF table is used to find
    the local interfaces (as opposed to IP-IF).

b) since no IP addresses are carried in the router LSA links, there is 
no way
    to do subnet matching. For unnumbered interfaces, we will skip the 
subnet
    matching.

c) Without a matching link, we still need a nexthop IP address. "The IP 
nexthop
    address has to be a valid interface or internal address on the adjacent
    router". In this design we propose to use the source IP address 
(field src)
    from the "struct ospf_neighbor". This address is saved when the neighbor
    was created from the hello packet source address. We just need to 
find the
    ospf_neighbor based on (oi + W->lsa->data->adv_router).

    Now looking back, this logic should work for numbered interface as 
well. It's
    much more efficient than iterating all W's router LSA links. So we 
will use
    the same logic for numbered interface too as part of this project.

Appendix:

[1] RFC 1812 -- Requirements for IP Version 4 Routers

10.2.1 Minimum Router Configuration

    There exists a minimum set of conditions that must be satisfied
    before a router may forward packets.  A router MUST NOT enable
    forwarding on any physical interface unless either:

    (1) The router knows the IP address and associated subnet mask or
         network prefix length of at least one logical interface
         associated with that physical interface, or

    (2) The router knows that the interface is an unnumbered interface
         and knows its router-id.

    These parameters MUST be explicitly configured:

    o A router MUST NOT use factory-configured default values for its IP
       addresses, prefix lengths, or router-id, and

    o A router MUST NOT assume that an unconfigured interface is an
       unnumbered interface.

<END>





More information about the Quagga-dev mailing list