[quagga-dev 10854] [Design] OSPF unnumbered interfaces
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
I include it anyways for completeness.
Numbered interface: is an interface with a unique IP address. Each
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. 
On a Quagga + Linux system, there are 2 user interfaces -- Quagga CLI
commands. So in terms of configuring unnumbered interfaces, we have 3
2.1 Reference IP address via linux commands
On linux, an unnumbered interface is *explictly* configured by
interface with an IP address that is already on another interface. For
with these 2 commands:
ifconfig eth7 126.96.36.199/24
ifconfig eth8 188.8.131.52/24
eth7 is a numbered interface with IP address 184.108.40.206, and eth8 is an
interface. For the sake of discussion let's call eth7 the anchor
eth8 the unnumbered interface.
2.2 Reference IP address via Quagga CLI
ip address 220.127.116.11/24
ip address 18.104.22.168/24
Same thing here, eth7 is anchor, numbered, and eth8 is unnumbered.
2.3 Reference interface name via Quagga CLI
ip address unnumbered eth7
This is similiar to cisco CLI. eth7 is the anchor, numbered, and eth8
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.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
in IP-IF table. If an entry is found, there is already an anchor
the interface in the notification should be marked as unnumbered and
the list. If an entry is not found, this interface is the anchor
is considered numbered.
An interface can change from unnumbered to numbered, and vice versa. The
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
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
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
We just need to set or unset the ZEBRA_INTERFACE_UNNUMBERED flag, and
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
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
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
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.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
For numbered interfaces, the link data is the IP address. This lookup
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,
if (oi == NULL)
if (!IPV4_ADDR_SAME (&oi->address->u.prefix4,
First impression I got reading this code is, that the logic is trying to
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
So what's the purpose of finding the matching link on adjacent router?
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
So in summary, for nexthop calculation of numbered interfaces, the code
a) maps calculating router's router LSA link data into local interfaces.
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,
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
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
to do subnet matching. For unnumbered interfaces, we will skip the
c) Without a matching link, we still need a nexthop IP address. "The IP
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
from the "struct ospf_neighbor". This address is saved when the neighbor
was created from the hello packet source address. We just need to
ospf_neighbor based on (oi + W->lsa->data->adv_router).
Now looking back, this logic should work for numbered interface as
much more efficient than iterating all W's router LSA links. So we
the same logic for numbered interface too as part of this project.
 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
More information about the Quagga-dev