zebra link state detection support
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 3e5cdd2..aef888b 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -208,7 +208,7 @@
bgp_if_update (ifc->ifp);
- if (if_is_up (ifc->ifp))
+ if (if_is_operative (ifc->ifp))
bgp_connected_add (ifc);
return 0;
@@ -227,7 +227,7 @@
bgp_if_update (ifc->ifp);
- if (if_is_up (ifc->ifp))
+ if (if_is_operative (ifc->ifp))
bgp_connected_delete (ifc);
connected_free (ifc);
diff --git a/lib/if.c b/lib/if.c
index 0934e40..ce3595d 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -270,6 +270,22 @@
return ifp->flags & IFF_UP;
}
+/* Is interface running? */
+int
+if_is_running (struct interface *ifp)
+{
+ return ifp->flags & IFF_RUNNING;
+}
+
+/* Is the interface operative, eg. either UP & RUNNING
+ or UP & !ZEBRA_INTERFACE_LINK_DETECTION */
+int
+if_is_operative (struct interface *ifp)
+{
+ return ((ifp->flags & IFF_UP) &&
+ (ifp->flags & IFF_RUNNING || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)));
+}
+
/* Is this loopback interface ? */
int
if_is_loopback (struct interface *ifp)
diff --git a/lib/if.h b/lib/if.h
index 55337fc..554126f 100644
--- a/lib/if.h
+++ b/lib/if.h
@@ -85,6 +85,7 @@
u_char status;
#define ZEBRA_INTERFACE_ACTIVE (1 << 0)
#define ZEBRA_INTERFACE_SUB (1 << 1)
+#define ZEBRA_INTERFACE_LINKDETECTION (1 << 2)
/* Interface flags. */
unsigned long flags;
@@ -188,6 +189,8 @@
struct interface *if_get_by_name (char *);
void if_delete (struct interface *);
int if_is_up (struct interface *);
+int if_is_running (struct interface *);
+int if_is_operative (struct interface *);
int if_is_loopback (struct interface *);
int if_is_broadcast (struct interface *);
int if_is_pointopoint (struct interface *);
diff --git a/lib/zclient.c b/lib/zclient.c
index 5e37154..c1b286f 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -564,6 +564,7 @@
ifp->ifindex = stream_getl (s);
/* Read interface's value. */
+ ifp->status = stream_getc (s);
ifp->flags = stream_getl (s);
ifp->metric = stream_getl (s);
ifp->mtu = stream_getl (s);
@@ -600,6 +601,7 @@
ifp->ifindex = stream_getl (s);
/* Read interface's value. */
+ ifp->status = stream_getc (s);
ifp->flags = stream_getl (s);
ifp->metric = stream_getl (s);
ifp->mtu = stream_getl (s);
diff --git a/ospfd/ospf_ase.c b/ospfd/ospf_ase.c
index 9194c56..b60aa07 100644
--- a/ospfd/ospf_ase.c
+++ b/ospfd/ospf_ase.c
@@ -154,7 +154,7 @@
for (ifn = listhead (ospf_top->oiflist); ifn; nextnode (ifn))
if ((oi = getdata (ifn)) != NULL)
- if (if_is_up (oi->ifp))
+ if (if_is_operative (oi->ifp))
if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
if (IPV4_ADDR_SAME (&oi->address->u.prefix4, &fwd_addr))
return 0;
diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c
index 6d7af05..a4495e9 100644
--- a/ospfd/ospf_lsa.c
+++ b/ospfd/ospf_lsa.c
@@ -640,7 +640,7 @@
struct interface *ifp = oi->ifp;
/* Check interface is up, OSPF is enable. */
- if (if_is_up (ifp))
+ if (if_is_operative (ifp))
{
if (oi->state != ISM_Down)
{
@@ -1391,7 +1391,7 @@
{
struct ospf_interface *oi = getdata (n1);
- if (if_is_up (oi->ifp))
+ if (if_is_operative (oi->ifp))
if (oi->address->family == AF_INET)
if (prefix_match (oi->address, &nh))
return nexthop;
@@ -1412,7 +1412,7 @@
fwd.s_addr = 0;
- if (if_is_up (oi->ifp))
+ if (if_is_operative (oi->ifp))
return oi->address->u.prefix4;
return fwd;
@@ -1432,7 +1432,7 @@
{
struct ospf_interface *oi = getdata (n1);
- if (if_is_up (oi->ifp))
+ if (if_is_operative (oi->ifp))
if (oi->area->external_routing == OSPF_AREA_NSSA)
if (oi->address && oi->address->family == AF_INET)
return (oi->address->u.prefix4 );
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index 73215fa..accf7a8 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -2526,12 +2526,11 @@
oi_count = ospf_oi_count (ifp);
/* Is interface up? */
- if (if_is_up (ifp))
- vty_out (vty, "%s is up, line protocol is up%s", ifp->name, VTY_NEWLINE);
- else
- {
- vty_out (vty, "%s is down, line protocol is down%s", ifp->name,
- VTY_NEWLINE);
+ if (if_is_operative (ifp)) {
+ vty_out (vty, "%s is up%s", ifp->name, VTY_NEWLINE);
+ } else
+ {
+ vty_out (vty, "%s is down%s", ifp->name, VTY_NEWLINE);
if (oi_count == 0)
diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c
index 1ad31f2..72ffe76 100644
--- a/ospfd/ospf_zebra.c
+++ b/ospfd/ospf_zebra.c
@@ -154,6 +154,7 @@
ifp->ifindex = stream_getl (s);
/* Read interface's value. */
+ ifp->status = stream_getc (s);
ifp->flags = stream_getl (s);
ifp->metric = stream_getl (s);
ifp->mtu = stream_getl (s);
@@ -175,7 +176,7 @@
return 0;
/* Interface is already up. */
- if (if_is_up (ifp))
+ if (if_is_operative (ifp))
{
/* Temporarily keep ifp values. */
memcpy (&if_tmp, ifp, sizeof (struct interface));
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index e7de8ea..e8bd360 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -761,7 +761,7 @@
ospf_area_add_if (oi->area, oi);
- if (if_is_up (ifp))
+ if (if_is_operative (ifp))
ospf_if_up (oi);
break;
diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c
index 06d4416..bdfca57 100644
--- a/ripd/rip_interface.c
+++ b/ripd/rip_interface.c
@@ -248,7 +248,7 @@
return;
/* If interface is down, don't send RIP packet. */
- if (! if_is_up (ifp))
+ if (! if_is_operative (ifp))
return;
/* Fetch RIP interface information. */
@@ -311,7 +311,7 @@
{
listnode cnode;
- if (if_is_up (ifp) && if_is_multicast (ifp))
+ if (if_is_operative (ifp) && if_is_multicast (ifp))
{
if (IS_RIP_DEBUG_EVENT)
zlog_info ("multicast join at %s", ifp->name);
@@ -705,7 +705,7 @@
{
/* All redistributed routes but static and system */
if ((rinfo->ifindex == ifp->ifindex) &&
- (rinfo->type != ZEBRA_ROUTE_STATIC) &&
+ /* (rinfo->type != ZEBRA_ROUTE_STATIC) && */
(rinfo->type != ZEBRA_ROUTE_SYSTEM))
rip_redistribute_delete (rinfo->type,rinfo->sub_type,
(struct prefix_ipv4 *)&rp->p,
@@ -1008,7 +1008,7 @@
if (if_is_loopback (ifp))
return;
- if (! if_is_up (ifp))
+ if (! if_is_operative (ifp))
return;
ri = ifp->info;
diff --git a/ripd/ripd.c b/ripd/ripd.c
index 3c55479..c63bf10 100644
--- a/ripd/ripd.c
+++ b/ripd/ripd.c
@@ -2231,7 +2231,7 @@
if (if_is_loopback (ifp))
continue;
- if (! if_is_up (ifp))
+ if (! if_is_operative (ifp))
continue;
/* Fetch RIP interface information. */
diff --git a/zebra/interface.c b/zebra/interface.c
index 9846805..ac06499 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -147,7 +147,7 @@
zebra_interface_address_add_update (ifp, ifc);
- if (if_is_up(ifp))
+ if (if_is_operative(ifp))
connected_up_ipv4 (ifp, ifc);
}
#ifdef HAVE_IPV6
@@ -170,7 +170,7 @@
zebra_interface_address_add_update (ifp, ifc);
- if (if_is_up(ifp))
+ if (if_is_operative(ifp))
connected_up_ipv6 (ifp, ifc);
}
#endif /* HAVE_IPV6 */
@@ -334,16 +334,16 @@
void
if_refresh (struct interface *ifp)
{
- if (if_is_up (ifp))
+ if (if_is_operative (ifp))
{
if_get_flags (ifp);
- if (! if_is_up (ifp))
+ if (! if_is_operative (ifp))
if_down (ifp);
}
else
{
if_get_flags (ifp);
- if (if_is_up (ifp))
+ if (if_is_operative (ifp))
if_up (ifp);
}
}
@@ -479,8 +479,22 @@
struct connected *connected;
listnode node;
- vty_out (vty, "Interface %s%s", ifp->name,
- VTY_NEWLINE);
+ vty_out (vty, "Interface %s is ", ifp->name);
+ if (if_is_up(ifp)) {
+ vty_out (vty, "up, line protocol ");
+
+ if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) {
+ if (if_is_running(ifp))
+ vty_out (vty, "is up%s", VTY_NEWLINE);
+ else
+ vty_out (vty, "is down%s", VTY_NEWLINE);
+ } else {
+ vty_out (vty, "detection is disabled%s", VTY_NEWLINE);
+ }
+ } else {
+ vty_out (vty, "down%s", VTY_NEWLINE);
+ }
+
if (ifp->desc)
vty_out (vty, " Description: %s%s", ifp->desc,
VTY_NEWLINE);
@@ -790,6 +804,51 @@
return CMD_SUCCESS;
}
+DEFUN (linkdetect,
+ linkdetect_cmd,
+ "link-detect",
+ "Enable link detection on interface\n")
+{
+ int ret;
+ struct interface *ifp;
+ int if_was_operative;
+
+ ifp = (struct interface *) vty->index;
+ if_was_operative = if_is_operative(ifp);
+ SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
+
+ /* When linkdetection is enabled, if might come down */
+ if (!if_is_operative(ifp) && if_was_operative) if_down(ifp);
+
+ /* FIXME: Will defer status change forwarding if interface
+ does not come down! */
+
+ return CMD_SUCCESS;
+}
+
+
+DEFUN (no_linkdetect,
+ no_linkdetect_cmd,
+ "no link-detect",
+ NO_STR
+ "Disable link detection on interface\n")
+{
+ int ret;
+ struct interface *ifp;
+ int if_was_operative;
+
+ ifp = (struct interface *) vty->index;
+ if_was_operative = if_is_operative(ifp);
+ UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
+
+ /* Interface may come up after disabling link detection */
+ if (if_is_operative(ifp) && !if_was_operative) if_up(ifp);
+
+ /* FIXME: see linkdetect_cmd */
+
+ return CMD_SUCCESS;
+}
+
DEFUN (shutdown_if,
shutdown_if_cmd,
"shutdown",
@@ -859,7 +918,7 @@
ifp->bandwidth = bandwidth;
/* force protocols to recalculate routes due to cost change */
- if (if_is_up (ifp))
+ if (if_is_operative (ifp))
zebra_interface_up_update (ifp);
return CMD_SUCCESS;
@@ -878,7 +937,7 @@
ifp->bandwidth = 0;
/* force protocols to recalculate routes due to cost change */
- if (if_is_up (ifp))
+ if (if_is_operative (ifp))
zebra_interface_up_update (ifp);
return CMD_SUCCESS;
@@ -971,7 +1030,7 @@
zebra_interface_address_add_update (ifp, ifc);
/* If interface is up register connected route. */
- if (if_is_up(ifp))
+ if (if_is_operative(ifp))
connected_up_ipv4 (ifp, ifc);
}
@@ -1179,7 +1238,7 @@
zebra_interface_address_add_update (ifp, ifc);
/* If interface is up register connected route. */
- if (if_is_up(ifp))
+ if (if_is_operative(ifp))
connected_up_ipv6 (ifp, ifc);
}
@@ -1315,6 +1374,9 @@
if (ifp->bandwidth != 0)
vty_out(vty, " bandwidth %u%s", ifp->bandwidth, VTY_NEWLINE);
+ if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION))
+ vty_out(vty, " link-detect%s", VTY_NEWLINE);
+
for (addrnode = listhead (ifp->connected); addrnode; nextnode (addrnode))
{
ifc = getdata (addrnode);
@@ -1377,6 +1439,8 @@
install_element (INTERFACE_NODE, &no_interface_desc_cmd);
install_element (INTERFACE_NODE, &multicast_cmd);
install_element (INTERFACE_NODE, &no_multicast_cmd);
+ install_element (INTERFACE_NODE, &linkdetect_cmd);
+ install_element (INTERFACE_NODE, &no_linkdetect_cmd);
install_element (INTERFACE_NODE, &shutdown_if_cmd);
install_element (INTERFACE_NODE, &no_shutdown_if_cmd);
install_element (INTERFACE_NODE, &bandwidth_if_cmd);
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index baca175..fa4dc54 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -787,16 +787,16 @@
ifp->mtu = *(int *)RTA_DATA (tb[IFLA_MTU]);
ifp->metric = 1;
- if (if_is_up (ifp))
+ if (if_is_operative (ifp))
{
ifp->flags = ifi->ifi_flags & 0x0000fffff;
- if (! if_is_up (ifp))
+ if (! if_is_operative (ifp))
if_down (ifp);
}
else
{
ifp->flags = ifi->ifi_flags & 0x0000fffff;
- if (if_is_up (ifp))
+ if (if_is_operative (ifp))
if_up (ifp);
}
}
diff --git a/zebra/zserv.c b/zebra/zserv.c
index 47114ab..d447d06 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -96,6 +96,7 @@
/* Interface information. */
stream_put (s, ifp->name, INTERFACE_NAMSIZ);
stream_putl (s, ifp->ifindex);
+ stream_putc (s, ifp->status);
stream_putl (s, ifp->flags);
stream_putl (s, ifp->metric);
stream_putl (s, ifp->mtu);
@@ -134,6 +135,7 @@
stream_putc (s, ZEBRA_INTERFACE_DELETE);
stream_put (s, ifp->name, INTERFACE_NAMSIZ);
stream_putl (s, ifp->ifindex);
+ stream_putc (s, ifp->status);
stream_putl (s, ifp->flags);
stream_putl (s, ifp->metric);
stream_putl (s, ifp->mtu);
@@ -256,6 +258,7 @@
/* Interface information. */
stream_put (s, ifp->name, INTERFACE_NAMSIZ);
stream_putl (s, ifp->ifindex);
+ stream_putc (s, ifp->status);
stream_putl (s, ifp->flags);
stream_putl (s, ifp->metric);
stream_putl (s, ifp->mtu);
@@ -288,6 +291,7 @@
/* Interface information. */
stream_put (s, ifp->name, INTERFACE_NAMSIZ);
stream_putl (s, ifp->ifindex);
+ stream_putc (s, ifp->status);
stream_putl (s, ifp->flags);
stream_putl (s, ifp->metric);
stream_putl (s, ifp->mtu);