[link-detect] Try to get BSD link-detect to work properly.
2008-01-10 Ingo Flaschberger <if@xip.at>
* configure.ac: Define HAVE_BSD_LINK_DETECT if <net/if_media.h> is
present.
* lib/zebra.h: If HAVE_BSD_LINK_DETECT is defined,
include <net/if_media.h>.
* zebra/ioctl.c: (if_get_flags) If HAVE_BSD_LINK_DETECT, use the
SIOCGIFMEDIA ioctl to ascertain link state.
* zebra/kernel_socket.c: (bsd_linkdetect_translate) New function to
map the ifm_data.ifi_link_state value into the IFF_RUNNING flag.
(ifm_read) Call bsd_linkdetect_translate to fix the IFF_RUNNING
flag before calling if_flags_update.
diff --git a/zebra/ChangeLog b/zebra/ChangeLog
index 3457c78..ba6d307 100644
--- a/zebra/ChangeLog
+++ b/zebra/ChangeLog
@@ -1,3 +1,12 @@
+2008-01-10 Ingo Flaschberger <if@xip.at>
+
+ * ioctl.c: (if_get_flags) If HAVE_BSD_LINK_DETECT, use the SIOCGIFMEDIA
+ ioctl to ascertain link state.
+ * kernel_socket.c: (bsd_linkdetect_translate) New function to
+ map the ifm_data.ifi_link_state value into the IFF_RUNNING flag.
+ (ifm_read) Call bsd_linkdetect_translate to fix the IFF_RUNNING
+ flag before calling if_flags_update.
+
2008-01-08 Michael Larson <mike@vyatta.com>
* zebra_rib.c: (nexthop_active_check) Replace if_is_up with
diff --git a/zebra/ioctl.c b/zebra/ioctl.c
index c9ec8d5..4f99a6c 100644
--- a/zebra/ioctl.c
+++ b/zebra/ioctl.c
@@ -344,6 +344,9 @@
{
int ret;
struct ifreq ifreq;
+#ifdef HAVE_BSD_LINK_DETECT
+ struct ifmediareq ifmr;
+#endif /* HAVE_BSD_LINK_DETECT */
ifreq_set_name (&ifreq, ifp);
@@ -353,6 +356,36 @@
zlog_err("if_ioctl(SIOCGIFFLAGS) failed: %s", safe_strerror(errno));
return;
}
+#ifdef HAVE_BSD_LINK_DETECT /* Detect BSD link-state at start-up */
+ (void) memset(&ifmr, 0, sizeof(ifmr));
+ strncpy (&ifmr.ifm_name, ifp->name, IFNAMSIZ);
+ if (if_ioctl(SIOCGIFMEDIA, (caddr_t) &ifmr) < 0)
+ {
+ zlog_err("if_ioctl(SIOCGIFMEDIA) failed: %s", safe_strerror(errno));
+ return;
+ }
+ if (ifmr.ifm_status & IFM_AVALID) /* Link state is valid */
+ {
+ if (ifmr.ifm_status & IFM_ACTIVE)
+ {
+ SET_FLAG(ifreq.ifr_flags, IFF_RUNNING);
+ zlog_debug("%s: BSD link state to up at interface %s, ifindex %d",
+ __func__, ifp->name, ifp->ifindex);
+ }
+ else
+ {
+ UNSET_FLAG(ifreq.ifr_flags, IFF_RUNNING);
+ zlog_debug("%s: BSD link state to down at interface %s, ifindex %d",
+ __func__, ifp->name, ifp->ifindex);
+ }
+ }
+ else /* Force always up */
+ {
+ SET_FLAG(ifreq.ifr_flags, IFF_RUNNING);
+ zlog_debug("%s: BSD link state invalid, forced up at interface %s, ifindex %d",
+ __func__, ifp->name, ifp->ifindex);
+ }
+#endif /* HAVE_BSD_LINK_DETECT */
if_flags_update (ifp, (ifreq.ifr_flags & 0x0000ffff));
}
diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c
index a91d76f..cd30631 100644
--- a/zebra/kernel_socket.c
+++ b/zebra/kernel_socket.c
@@ -295,6 +295,18 @@
}
#endif /* RTM_IFANNOUNCE */
+#ifdef HAVE_BSD_LINK_DETECT
+/* BSD link detect translation */
+static void
+bsd_linkdetect_translate (struct if_msghdr *ifm)
+{
+ if (ifm->ifm_data.ifi_link_state >= LINK_STATE_UP)
+ SET_FLAG(ifm->ifm_flags, IFF_RUNNING);
+ else
+ UNSET_FLAG(ifm->ifm_flags, IFF_RUNNING);
+}
+#endif /* HAVE_BSD_LINK_DETECT */
+
/*
* Handle struct if_msghdr obtained from reading routing socket or
* sysctl (from interface_list). There may or may not be sockaddrs
@@ -426,6 +438,11 @@
* structure with ifindex IFINDEX_INTERNAL.
*/
ifp->ifindex = ifm->ifm_index;
+
+#ifdef HAVE_BSD_LINK_DETECT /* translate BSD kernel msg for link-state */
+ bsd_linkdetect_translate(ifm);
+#endif /* HAVE_BSD_LINK_DETECT */
+
if_flags_update (ifp, ifm->ifm_flags);
#if defined(__bsdi__)
if_kvm_get_mtu (ifp);
@@ -453,6 +470,10 @@
return -1;
}
+#ifdef HAVE_BSD_LINK_DETECT /* translate BSD kernel msg for link-state */
+ bsd_linkdetect_translate(ifm);
+#endif /* HAVE_BSD_LINK_DETECT */
+
/* update flags and handle operative->inoperative transition, if any */
if_flags_update (ifp, ifm->ifm_flags);