From f25cb0ef9f6341648513e793a3162b32fc250d2b Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Thu, 11 Nov 2010 10:03:02 +0100 Subject: [PATCH] Implements link state detection. Also changes some symbol names (IFF_ADMIN_DOWN -> IFF_SHUTDOWN, IFF_LINK_UP -> IFF_ADMIN_UP). --- nest/iface.c | 26 ++++++++++++++++---------- nest/iface.h | 8 +++++--- sysdep/bsd/krt-sock.c | 4 +++- sysdep/linux/netlink/netlink.c | 14 ++++++++++++-- sysdep/unix/krt-iface.c | 4 ++-- 5 files changed, 38 insertions(+), 18 deletions(-) diff --git a/nest/iface.c b/nest/iface.c index 4d0cf04c..8e459363 100644 --- a/nest/iface.c +++ b/nest/iface.c @@ -67,13 +67,13 @@ if_dump(struct iface *i) struct ifa *a; debug("IF%d: %s", i->index, i->name); - if (i->flags & IF_ADMIN_DOWN) - debug(" ADMIN-DOWN"); + if (i->flags & IF_SHUTDOWN) + debug(" SHUTDOWN"); if (i->flags & IF_UP) debug(" UP"); else debug(" DOWN"); - if (i->flags & IF_LINK_UP) + if (i->flags & IF_ADMIN_UP) debug(" LINK-UP"); if (i->flags & IF_MULTIACCESS) debug(" MA"); @@ -117,12 +117,14 @@ if_what_changed(struct iface *i, struct iface *j) { unsigned c; - if (((i->flags ^ j->flags) & ~(IF_UP | IF_ADMIN_DOWN | IF_UPDATED | IF_LINK_UP | IF_TMP_DOWN | IF_JUST_CREATED)) + if (((i->flags ^ j->flags) & ~(IF_UP | IF_SHUTDOWN | IF_UPDATED | IF_ADMIN_UP | IF_TMP_DOWN | IF_JUST_CREATED)) || i->index != j->index) return IF_CHANGE_TOO_MUCH; c = 0; if ((i->flags ^ j->flags) & IF_UP) c |= (i->flags & IF_UP) ? IF_CHANGE_DOWN : IF_CHANGE_UP; + if ((i->flags ^ j->flags) & IF_LINK_UP) + c |= IF_CHANGE_LINK; if (i->mtu != j->mtu) c |= IF_CHANGE_MTU; return c; @@ -169,6 +171,7 @@ if_send_notify(struct proto *p, unsigned c, struct iface *i) (c & IF_CHANGE_UP) ? "goes up" : (c & IF_CHANGE_DOWN) ? "goes down" : (c & IF_CHANGE_MTU) ? "changes MTU" : + (c & IF_CHANGE_LINK) ? "changes link" : (c & IF_CHANGE_CREATE) ? "created" : "sends unknown event"); p->if_notify(p, c, i); @@ -217,8 +220,8 @@ if_notify_change(unsigned c, struct iface *i) static unsigned if_recalc_flags(struct iface *i, unsigned flags) { - if ((flags & (IF_ADMIN_DOWN | IF_TMP_DOWN)) || - !(flags & IF_LINK_UP) || + if ((flags & (IF_SHUTDOWN | IF_TMP_DOWN)) || + !(flags & IF_ADMIN_UP) || !i->addr) flags &= ~IF_UP; else @@ -325,7 +328,7 @@ if_end_update(void) WALK_LIST(i, iface_list) { if (!(i->flags & IF_UPDATED)) - if_change_flags(i, (i->flags & ~IF_LINK_UP) | IF_ADMIN_DOWN); + if_change_flags(i, (i->flags & ~IF_ADMIN_UP) | IF_SHUTDOWN); else { WALK_LIST_DELSAFE(a, b, i->addrs) @@ -535,8 +538,8 @@ auto_router_id(void) j = NULL; WALK_LIST(i, iface_list) - if ((i->flags & IF_LINK_UP) && - !(i->flags & (IF_IGNORE | IF_ADMIN_DOWN)) && + if ((i->flags & IF_ADMIN_UP) && + !(i->flags & (IF_IGNORE | IF_SHUTDOWN)) && i->addr && !(i->addr->flags & IA_UNNUMBERED) && (!j || ipa_to_u32(i->addr->ip) < ipa_to_u32(j->addr->ip))) @@ -694,6 +697,9 @@ if_show(void) WALK_LIST(i, iface_list) { + if (i->flags & IF_SHUTDOWN) + continue; + cli_msg(-1001, "%s %s (index=%d)", i->name, (i->flags & IF_UP) ? "up" : "DOWN", i->index); if (!(i->flags & IF_MULTIACCESS)) type = "PtP"; @@ -703,7 +709,7 @@ if_show(void) type, (i->flags & IF_BROADCAST) ? " Broadcast" : "", (i->flags & IF_MULTICAST) ? " Multicast" : "", - (i->flags & IF_ADMIN_DOWN) ? "Down" : "Up", + (i->flags & IF_ADMIN_UP) ? "Up" : "Down", (i->flags & IF_LINK_UP) ? "Up" : "Down", (i->flags & IF_LOOPBACK) ? " Loopback" : "", (i->flags & IF_IGNORE) ? " Ignored" : "", diff --git a/nest/iface.h b/nest/iface.h index c116db8b..471625f2 100644 --- a/nest/iface.h +++ b/nest/iface.h @@ -39,14 +39,15 @@ struct iface { list neighbors; /* All neighbors on this interface */ }; -#define IF_UP 1 /* IF_LINK_UP and IP address known */ +#define IF_UP 1 /* IF_ADMIN_UP and IP address known */ #define IF_MULTIACCESS 2 #define IF_BROADCAST 4 #define IF_MULTICAST 8 -#define IF_ADMIN_DOWN 0x10 +#define IF_SHUTDOWN 0x10 /* Interface disappeared */ #define IF_LOOPBACK 0x20 #define IF_IGNORE 0x40 /* Not to be used by routing protocols (loopbacks etc.) */ -#define IF_LINK_UP 0x80 +#define IF_ADMIN_UP 0x80 /* Administrative up (e.q. IFF_UP in Linux) */ +#define IF_LINK_UP 0x100 /* Link available (e.q. IFF_LOWER_UP in Linux) */ #define IA_PRIMARY 0x10000 /* This address is primary */ #define IA_SECONDARY 0x20000 /* This address has been reported as secondary by the kernel */ @@ -63,6 +64,7 @@ struct iface { #define IF_CHANGE_DOWN 2 #define IF_CHANGE_MTU 4 #define IF_CHANGE_CREATE 8 /* Seen this interface for the first time */ +#define IF_CHANGE_LINK 0x10 #define IF_CHANGE_TOO_MUCH 0x40000000 /* Used internally */ void if_init(void); diff --git a/sysdep/bsd/krt-sock.c b/sysdep/bsd/krt-sock.c index 9ae658d6..53b30ca4 100644 --- a/sysdep/bsd/krt-sock.c +++ b/sysdep/bsd/krt-sock.c @@ -456,7 +456,9 @@ krt_read_ifinfo(struct ks_msg *msg) f.flags = 0; if (fl & IFF_UP) - f.flags |= IF_LINK_UP; + f.flags |= IF_ADMIN_UP; + if (ifm->ifm_data.ifi_link_state != LINK_STATE_DOWN) + f.flags |= IF_LINK_UP; /* up or unknown */ if (fl & IFF_LOOPBACK) /* Loopback */ f.flags |= IF_MULTIACCESS | IF_LOOPBACK | IF_IGNORE; else if (fl & IFF_POINTOPOINT) /* PtP */ diff --git a/sysdep/linux/netlink/netlink.c b/sysdep/linux/netlink/netlink.c index 2dd0359b..79f7210a 100644 --- a/sysdep/linux/netlink/netlink.c +++ b/sysdep/linux/netlink/netlink.c @@ -8,7 +8,6 @@ #include #include -#include #include #include #include @@ -27,6 +26,7 @@ #include "conf/conf.h" #include +#include #include #include @@ -34,6 +34,10 @@ #define MSG_TRUNC 0x20 #endif +#ifndef IFF_LOWER_UP +#define IFF_LOWER_UP 0x10000 +#endif + /* * Synchronous Netlink interface */ @@ -281,6 +285,8 @@ nl_parse_link(struct nlmsghdr *h, int scan) u32 mtu; unsigned int fl; + debug("nl_parse_link %d\n", new); + if (!(i = nl_checkin(h, sizeof(*i))) || !nl_parse_attrs(IFLA_RTA(i), a, sizeof(a))) return; if (!a[IFLA_IFNAME] || RTA_PAYLOAD(a[IFLA_IFNAME]) < 2 || @@ -293,6 +299,8 @@ nl_parse_link(struct nlmsghdr *h, int scan) name = RTA_DATA(a[IFLA_IFNAME]); memcpy(&mtu, RTA_DATA(a[IFLA_MTU]), sizeof(u32)); + debug("nl_parse_link name %s index %d flags %x\n", name, i->ifi_index, i->ifi_flags); + ifi = if_find_by_index(i->ifi_index); if (!new) { @@ -300,7 +308,7 @@ nl_parse_link(struct nlmsghdr *h, int scan) if (ifi && !scan) { memcpy(&f, ifi, sizeof(struct iface)); - f.flags |= IF_ADMIN_DOWN; + f.flags |= IF_SHUTDOWN; if_update(&f); } } @@ -319,6 +327,8 @@ nl_parse_link(struct nlmsghdr *h, int scan) f.flags = 0; fl = i->ifi_flags; if (fl & IFF_UP) + f.flags |= IF_ADMIN_UP; + if (fl & IFF_LOWER_UP) f.flags |= IF_LINK_UP; if (fl & IFF_LOOPBACK) /* Loopback */ f.flags |= IF_MULTIACCESS | IF_LOOPBACK | IF_IGNORE; diff --git a/sysdep/unix/krt-iface.c b/sysdep/unix/krt-iface.c index 5fda0d1d..c305d27a 100644 --- a/sysdep/unix/krt-iface.c +++ b/sysdep/unix/krt-iface.c @@ -78,12 +78,12 @@ scan_ifs(struct ifreq *r, int cnt) faulty: log(L_ERR "%s(%s): %m", err, i.name); bad: - i.flags = (i.flags & ~IF_LINK_UP) | IF_ADMIN_DOWN; + i.flags = (i.flags & ~IF_ADMIN_UP) | IF_SHUTDOWN; continue; } fl = r->ifr_flags; if (fl & IFF_UP) - i.flags |= IF_LINK_UP; + i.flags |= IF_ADMIN_UP; if (ioctl(if_scan_sock, SIOCGIFNETMASK, r) < 0) { err = "SIOCGIFNETMASK"; goto faulty; }