mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-03 22:37:49 +00:00
Unnumbered interface support.
This commit is contained in:
parent
c8a1cb5c9d
commit
525c183906
30
lib/if.c
30
lib/if.c
@ -315,6 +315,36 @@ if_lookup_address (struct in_addr src)
|
||||
return match;
|
||||
}
|
||||
|
||||
/* Lookup anchor interface by IPv4 address. */
|
||||
struct connected *
|
||||
if_anchor_lookup_by_address (struct in_addr src)
|
||||
{
|
||||
struct listnode *node;
|
||||
struct listnode *cnode;
|
||||
struct interface *ifp;
|
||||
struct prefix *p;
|
||||
struct connected *c;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
|
||||
{
|
||||
for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
|
||||
{
|
||||
if (CHECK_FLAG(c->flags, ZEBRA_IFA_UNNUMBERED) ||
|
||||
!CHECK_FLAG(c->conf, ZEBRA_IFC_REAL))
|
||||
continue;
|
||||
|
||||
p = c->address;
|
||||
|
||||
if (p && p->family == AF_INET)
|
||||
{
|
||||
if (IPV4_ADDR_SAME (&p->u.prefix4, &src))
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Lookup interface by prefix */
|
||||
struct interface *
|
||||
if_lookup_prefix (struct prefix *prefix)
|
||||
|
10
lib/if.h
10
lib/if.h
@ -90,7 +90,7 @@ struct interface
|
||||
#define ZEBRA_INTERFACE_ACTIVE (1 << 0)
|
||||
#define ZEBRA_INTERFACE_SUB (1 << 1)
|
||||
#define ZEBRA_INTERFACE_LINKDETECTION (1 << 2)
|
||||
|
||||
|
||||
/* Interface flags. */
|
||||
uint64_t flags;
|
||||
|
||||
@ -173,6 +173,7 @@ struct connected
|
||||
u_char flags;
|
||||
#define ZEBRA_IFA_SECONDARY (1 << 0)
|
||||
#define ZEBRA_IFA_PEER (1 << 1)
|
||||
#define ZEBRA_IFA_UNNUMBERED (1 << 2)
|
||||
/* N.B. the ZEBRA_IFA_PEER flag should be set if and only if
|
||||
a peer address has been configured. If this flag is set,
|
||||
the destination field must contain the peer address.
|
||||
@ -187,6 +188,12 @@ struct connected
|
||||
Note: destination may be NULL if ZEBRA_IFA_PEER is not set. */
|
||||
struct prefix *destination;
|
||||
|
||||
/* A list of unnumbered IFCs borrowing the address from me */
|
||||
struct list *unnumbered;
|
||||
|
||||
/* Pointer to the anchor IFC if I'm unnumbered */
|
||||
struct connected *anchor;
|
||||
|
||||
/* Label for Linux 2.2.X and upper. */
|
||||
char *label;
|
||||
};
|
||||
@ -262,6 +269,7 @@ extern struct interface *if_lookup_by_index (unsigned int);
|
||||
extern struct interface *if_lookup_exact_address (struct in_addr);
|
||||
extern struct interface *if_lookup_address (struct in_addr);
|
||||
extern struct interface *if_lookup_prefix (struct prefix *prefix);
|
||||
extern struct connected *if_anchor_lookup_by_address (struct in_addr src);
|
||||
|
||||
/* These 2 functions are to be used when the ifname argument is terminated
|
||||
by a '\0' character: */
|
||||
|
@ -482,6 +482,7 @@ extern const char *zserv_command_string (unsigned int command);
|
||||
#define ZEBRA_FLAG_CHANGED 0x20
|
||||
#define ZEBRA_FLAG_STATIC 0x40
|
||||
#define ZEBRA_FLAG_REJECT 0x80
|
||||
#define ZEBRA_FLAG_SCOPE_LINK 0x100
|
||||
|
||||
/* Zebra nexthop flags. */
|
||||
#define ZEBRA_NEXTHOP_IFINDEX 1
|
||||
|
@ -353,7 +353,12 @@ ospf_if_is_configured (struct ospf *ospf, struct in_addr *address)
|
||||
for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
|
||||
if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
|
||||
{
|
||||
if (oi->type == OSPF_IFTYPE_POINTOPOINT)
|
||||
if (CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED))
|
||||
{
|
||||
if (htonl(oi->ifp->ifindex) == address->s_addr)
|
||||
return oi;
|
||||
}
|
||||
else if (oi->type == OSPF_IFTYPE_POINTOPOINT)
|
||||
{
|
||||
/* special leniency: match if addr is anywhere on peer subnet */
|
||||
if (prefix_match(CONNECTED_PREFIX(oi->connected),
|
||||
@ -477,8 +482,10 @@ ospf_if_lookup_recv_if (struct ospf *ospf, struct in_addr src,
|
||||
if (if_is_loopback (oi->ifp))
|
||||
continue;
|
||||
|
||||
if (prefix_match (CONNECTED_PREFIX(oi->connected),
|
||||
(struct prefix *) &addr))
|
||||
if (CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED))
|
||||
match = oi;
|
||||
else if (prefix_match (CONNECTED_PREFIX(oi->connected),
|
||||
(struct prefix *) &addr))
|
||||
{
|
||||
if ( (match == NULL) ||
|
||||
(match->address->prefixlen < oi->address->prefixlen)
|
||||
|
@ -532,7 +532,7 @@ lsa_link_ptop_set (struct stream *s, struct ospf_interface *oi)
|
||||
{
|
||||
int links = 0;
|
||||
struct ospf_neighbor *nbr;
|
||||
struct in_addr id, mask;
|
||||
struct in_addr id, mask, data;
|
||||
u_int16_t cost = ospf_link_cost (oi);
|
||||
|
||||
if (IS_DEBUG_OSPF (lsa, LSA_GENERATE))
|
||||
@ -541,19 +541,34 @@ lsa_link_ptop_set (struct stream *s, struct ospf_interface *oi)
|
||||
if ((nbr = ospf_nbr_lookup_ptop (oi)))
|
||||
if (nbr->state == NSM_Full)
|
||||
{
|
||||
/* For unnumbered point-to-point networks, the Link Data field
|
||||
should specify the interface's MIB-II ifIndex value. */
|
||||
links += link_info_set (s, nbr->router_id, oi->address->u.prefix4,
|
||||
LSA_LINK_TYPE_POINTOPOINT, 0, cost);
|
||||
if (CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED))
|
||||
{
|
||||
/* For unnumbered point-to-point networks, the Link Data field
|
||||
should specify the interface's MIB-II ifIndex value. */
|
||||
data.s_addr = htonl(oi->ifp->ifindex);
|
||||
links += link_info_set (s, nbr->router_id, data,
|
||||
LSA_LINK_TYPE_POINTOPOINT, 0, cost);
|
||||
}
|
||||
else
|
||||
{
|
||||
links += link_info_set (s, nbr->router_id,
|
||||
oi->address->u.prefix4,
|
||||
LSA_LINK_TYPE_POINTOPOINT, 0, cost);
|
||||
}
|
||||
}
|
||||
|
||||
/* Regardless of the state of the neighboring router, we must
|
||||
add a Type 3 link (stub network).
|
||||
N.B. Options 1 & 2 share basically the same logic. */
|
||||
masklen2ip (oi->address->prefixlen, &mask);
|
||||
id.s_addr = CONNECTED_PREFIX(oi->connected)->u.prefix4.s_addr & mask.s_addr;
|
||||
links += link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0,
|
||||
oi->output_cost);
|
||||
/* no need for a stub link for unnumbered interfaces */
|
||||
if (!CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED))
|
||||
{
|
||||
/* Regardless of the state of the neighboring router, we must
|
||||
add a Type 3 link (stub network).
|
||||
N.B. Options 1 & 2 share basically the same logic. */
|
||||
masklen2ip (oi->address->prefixlen, &mask);
|
||||
id.s_addr = CONNECTED_PREFIX(oi->connected)->u.prefix4.s_addr & mask.s_addr;
|
||||
links += link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0,
|
||||
oi->output_cost);
|
||||
}
|
||||
|
||||
return links;
|
||||
}
|
||||
|
||||
|
@ -611,6 +611,8 @@ ospf_intra_add_stub (struct route_table *rt, struct router_lsa_link *link,
|
||||
path = ospf_path_new ();
|
||||
path->nexthop.s_addr = 0;
|
||||
path->ifindex = oi->ifp->ifindex;
|
||||
if (CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED))
|
||||
path->unnumbered = 1;
|
||||
listnode_add (or->paths, path);
|
||||
}
|
||||
else
|
||||
@ -783,6 +785,8 @@ ospf_route_copy_nexthops_from_vertex (struct ospf_route *to,
|
||||
path = ospf_path_new ();
|
||||
path->nexthop = nexthop->router;
|
||||
path->ifindex = nexthop->oi->ifp->ifindex;
|
||||
if (CHECK_FLAG(nexthop->oi->connected->flags, ZEBRA_IFA_UNNUMBERED))
|
||||
path->unnumbered = 1;
|
||||
listnode_add (to->paths, path);
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ struct ospf_path
|
||||
struct in_addr nexthop;
|
||||
struct in_addr adv_router;
|
||||
unsigned int ifindex;
|
||||
unsigned char unnumbered;
|
||||
};
|
||||
|
||||
/* Below is the structure linked to every
|
||||
|
@ -2889,30 +2889,37 @@ show_ip_ospf_interface_sub (struct vty *vty, struct ospf *ospf,
|
||||
if (oi == NULL)
|
||||
continue;
|
||||
|
||||
/* Show OSPF interface information. */
|
||||
vty_out (vty, " Internet Address %s/%d,",
|
||||
inet_ntoa (oi->address->u.prefix4), oi->address->prefixlen);
|
||||
|
||||
if (oi->connected->destination || oi->type == OSPF_IFTYPE_VIRTUALLINK)
|
||||
if (CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED))
|
||||
{
|
||||
struct in_addr *dest;
|
||||
const char *dstr;
|
||||
|
||||
if (CONNECTED_PEER(oi->connected)
|
||||
|| oi->type == OSPF_IFTYPE_VIRTUALLINK)
|
||||
dstr = "Peer";
|
||||
else
|
||||
dstr = "Broadcast";
|
||||
|
||||
/* For Vlinks, showing the peer address is probably more
|
||||
* informative than the local interface that is being used
|
||||
*/
|
||||
if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
|
||||
dest = &oi->vl_data->peer_addr;
|
||||
else
|
||||
dest = &oi->connected->destination->u.prefix4;
|
||||
|
||||
vty_out (vty, " %s %s,", dstr, inet_ntoa (*dest));
|
||||
vty_out (vty, " This interface is UNNUMBERED,");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Show OSPF interface information. */
|
||||
vty_out (vty, " Internet Address %s/%d,",
|
||||
inet_ntoa (oi->address->u.prefix4), oi->address->prefixlen);
|
||||
|
||||
if (oi->connected->destination || oi->type == OSPF_IFTYPE_VIRTUALLINK)
|
||||
{
|
||||
struct in_addr *dest;
|
||||
const char *dstr;
|
||||
|
||||
if (CONNECTED_PEER(oi->connected)
|
||||
|| oi->type == OSPF_IFTYPE_VIRTUALLINK)
|
||||
dstr = "Peer";
|
||||
else
|
||||
dstr = "Broadcast";
|
||||
|
||||
/* For Vlinks, showing the peer address is probably more
|
||||
* informative than the local interface that is being used
|
||||
*/
|
||||
if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
|
||||
dest = &oi->vl_data->peer_addr;
|
||||
else
|
||||
dest = &oi->connected->destination->u.prefix4;
|
||||
|
||||
vty_out (vty, " %s %s,", dstr, inet_ntoa (*dest));
|
||||
}
|
||||
}
|
||||
|
||||
vty_out (vty, " Area %s%s", ospf_area_desc_string (oi->area),
|
||||
@ -2964,7 +2971,7 @@ show_ip_ospf_interface_sub (struct vty *vty, struct ospf *ospf,
|
||||
inet_ntoa (nbr->address.u.prefix4), VTY_NEWLINE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Next network-LSA sequence number we'll use, if we're elected DR */
|
||||
if (oi->params && ntohl (oi->params->network_lsa_seqnum)
|
||||
!= OSPF_INITIAL_SEQUENCE_NUMBER)
|
||||
|
@ -383,6 +383,9 @@ ospf_zebra_add (struct prefix_ipv4 *p, struct ospf_route *or)
|
||||
struct stream *s;
|
||||
struct ospf_path *path;
|
||||
struct listnode *node;
|
||||
#ifdef HAVE_NETLINK
|
||||
int ol_cnt = 0, not_ol_cnt = 0;
|
||||
#endif /* HAVE_NETLINK */
|
||||
|
||||
if (zclient->redist[ZEBRA_ROUTE_OSPF])
|
||||
{
|
||||
@ -426,6 +429,40 @@ ospf_zebra_add (struct prefix_ipv4 *p, struct ospf_route *or)
|
||||
/* Nexthop, ifindex, distance and metric information. */
|
||||
for (ALL_LIST_ELEMENTS_RO (or->paths, node, path))
|
||||
{
|
||||
#ifdef HAVE_NETLINK
|
||||
if (path->unnumbered)
|
||||
{
|
||||
stream_putc (s, ZEBRA_NEXTHOP_IPV4_ONLINK);
|
||||
stream_put_in_addr (s, &path->nexthop);
|
||||
if (path->ifindex)
|
||||
stream_putl (s, path->ifindex);
|
||||
else
|
||||
stream_putl (s, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (path->nexthop.s_addr != INADDR_ANY &&
|
||||
path->ifindex != 0)
|
||||
{
|
||||
stream_putc (s, ZEBRA_NEXTHOP_IPV4_IFINDEX);
|
||||
stream_put_in_addr (s, &path->nexthop);
|
||||
stream_putl (s, path->ifindex);
|
||||
}
|
||||
else if (path->nexthop.s_addr != INADDR_ANY)
|
||||
{
|
||||
stream_putc (s, ZEBRA_NEXTHOP_IPV4);
|
||||
stream_put_in_addr (s, &path->nexthop);
|
||||
}
|
||||
else
|
||||
{
|
||||
stream_putc (s, ZEBRA_NEXTHOP_IFINDEX);
|
||||
if (path->ifindex)
|
||||
stream_putl (s, path->ifindex);
|
||||
else
|
||||
stream_putl (s, 0);
|
||||
}
|
||||
}
|
||||
#else /* HAVE_NETLINK */
|
||||
if (path->nexthop.s_addr != INADDR_ANY &&
|
||||
path->ifindex != 0)
|
||||
{
|
||||
@ -446,16 +483,18 @@ ospf_zebra_add (struct prefix_ipv4 *p, struct ospf_route *or)
|
||||
else
|
||||
stream_putl (s, 0);
|
||||
}
|
||||
#endif /* HAVE_NETLINK */
|
||||
|
||||
if (IS_DEBUG_OSPF (zebra, ZEBRA_REDISTRIBUTE))
|
||||
{
|
||||
char buf[2][INET_ADDRSTRLEN];
|
||||
zlog_debug("Zebra: Route add %s/%d nexthop %s",
|
||||
zlog_debug("Zebra: Route add %s/%d nexthop %s, ifindex=%d",
|
||||
inet_ntop(AF_INET, &p->prefix,
|
||||
buf[0], sizeof(buf[0])),
|
||||
p->prefixlen,
|
||||
inet_ntop(AF_INET, &path->nexthop,
|
||||
buf[1], sizeof(buf[1])));
|
||||
buf[1], sizeof(buf[1])),
|
||||
path->ifindex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -77,7 +77,23 @@ connected_announce (struct interface *ifp, struct connected *ifc)
|
||||
{
|
||||
if (!ifc)
|
||||
return;
|
||||
|
||||
|
||||
if (ifc->address->family == AF_INET)
|
||||
{
|
||||
if (ifc->anchor = if_anchor_lookup_by_address(ifc->address->u.prefix4))
|
||||
{
|
||||
/* found an anchor, so I'm unnumbered */
|
||||
SET_FLAG (ifc->flags, ZEBRA_IFA_UNNUMBERED);
|
||||
listnode_add (ifc->anchor->unnumbered, ifc);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* I'm numbered */
|
||||
UNSET_FLAG (ifc->flags, ZEBRA_IFA_UNNUMBERED);
|
||||
ifc->unnumbered = list_new();
|
||||
}
|
||||
}
|
||||
|
||||
listnode_add (ifp->connected, ifc);
|
||||
|
||||
/* Update interface address information to protocol daemon. */
|
||||
@ -314,6 +330,42 @@ connected_down_ipv4 (struct interface *ifp, struct connected *ifc)
|
||||
rib_update ();
|
||||
}
|
||||
|
||||
void
|
||||
connected_delete_ipv4_unnumbered (struct connected *ifc)
|
||||
{
|
||||
struct connected *new_anchor, *iter;
|
||||
struct listnode *node;
|
||||
|
||||
if (CHECK_FLAG (ifc->flags, ZEBRA_IFA_UNNUMBERED))
|
||||
{
|
||||
listnode_delete (ifc->anchor->unnumbered, ifc);
|
||||
ifc->anchor = NULL;
|
||||
}
|
||||
else /* I'm a numbered interface */
|
||||
{
|
||||
if (!list_isempty (ifc->unnumbered))
|
||||
{
|
||||
new_anchor = listgetdata (listhead (ifc->unnumbered));
|
||||
new_anchor->unnumbered = ifc->unnumbered;
|
||||
listnode_delete (new_anchor->unnumbered, new_anchor);
|
||||
new_anchor->anchor = NULL;
|
||||
|
||||
/* new_anchor changed from unnumbered to numbered, notify clients */
|
||||
zebra_interface_address_delete_update (new_anchor->ifp, new_anchor);
|
||||
UNSET_FLAG (new_anchor->flags, ZEBRA_IFA_UNNUMBERED);
|
||||
zebra_interface_address_add_update (new_anchor->ifp, new_anchor);
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(new_anchor->unnumbered, node, iter))
|
||||
iter->anchor = new_anchor;
|
||||
}
|
||||
else
|
||||
{
|
||||
list_free (ifc->unnumbered);
|
||||
ifc->unnumbered = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Delete connected IPv4 route to the interface. */
|
||||
void
|
||||
connected_delete_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
|
||||
@ -330,7 +382,9 @@ connected_delete_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
|
||||
ifc = connected_check (ifp, (struct prefix *) &p);
|
||||
if (! ifc)
|
||||
return;
|
||||
|
||||
|
||||
connected_delete_ipv4_unnumbered (ifc);
|
||||
|
||||
connected_withdraw (ifc);
|
||||
|
||||
rib_update();
|
||||
|
@ -35,6 +35,9 @@ extern void
|
||||
connected_delete_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
|
||||
u_char prefixlen, struct in_addr *broad);
|
||||
|
||||
extern void
|
||||
connected_delete_ipv4_unnumbered (struct connected *ifc);
|
||||
|
||||
extern void connected_up_ipv4 (struct interface *, struct connected *);
|
||||
extern void connected_down_ipv4 (struct interface *, struct connected *);
|
||||
|
||||
|
@ -472,6 +472,7 @@ if_delete_update (struct interface *ifp)
|
||||
|
||||
UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
|
||||
UNSET_FLAG (ifc->conf, ZEBRA_IFC_QUEUED);
|
||||
connected_delete_ipv4_unnumbered(ifc);
|
||||
|
||||
/* Remove from subnet chain. */
|
||||
list_delete_node (addr_list, anode);
|
||||
@ -654,6 +655,9 @@ connected_dump_vty (struct vty *vty, struct connected *connected)
|
||||
if (CHECK_FLAG (connected->flags, ZEBRA_IFA_SECONDARY))
|
||||
vty_out (vty, " secondary");
|
||||
|
||||
if (CHECK_FLAG (connected->flags, ZEBRA_IFA_UNNUMBERED))
|
||||
vty_out (vty, " unnumbered");
|
||||
|
||||
if (connected->label)
|
||||
vty_out (vty, " %s", connected->label);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user