Pawel Tyll wrote: >> This is OK. Imported shows just number of routes propagated to directly >> connected table, while preferred count shows cummulative number of >> routes originated by that protocol in all tables where these routes are >> preferred. > Hm, personally I would prefer to receive information only about [some > BGP protocol] when asking for information about [some BGP protocol] - > this way I'll have 23857286917 preferred prefixes in no time, think > about it yourself: how useful is that number? :) > >> So you removed it? Or renamed? > I removed it, so another interface took it's interface id, but bird > kept associating previous name (vlan's) with this id. - renaming fails > in principally the same way: bird keeps previous name ;) > >> It is supposed to work (it is handled as removing and readding the >> interface), >> but probably not tested. > Well, I was supposed to be awfully rich by now, but it wasn't tested, > hence it didn't work :> Attached patch seems to work on FreeBSD. For OpenBSD rtsock events seems to be the same (and interface renaming is not supported there at all). I don't have any NetBSD instance to test on, unfortunately
Patch is not finished: interface renaming has to be handled in appropriate protocols. In OSPF, for example, it is a bit tricky due to the fact that interface can belong to several areas > >
>From 9e53a3dfc29c77b4eb73116101f37243484d8429 Mon Sep 17 00:00:00 2001 From: Alexander V. Chernikov <[email protected]> Date: Thu, 19 Jan 2012 15:28:06 +0000 Subject: [PATCH 1/1] * Handle interface removal and renaming correctly on BSD --- nest/iface.c | 44 ++++++++++++++++++++++++++++++++++ nest/iface.h | 1 + proto/ospf/iface.c | 9 +++++++ sysdep/bsd/krt-sock.c | 60 +++++++++++++++++++++++++++++++++++++++++++++- sysdep/unix/krt-iface.c | 13 +++++++--- 5 files changed, 121 insertions(+), 6 deletions(-) diff --git a/nest/iface.c b/nest/iface.c index b8b214e..4dae928 100644 --- a/nest/iface.c +++ b/nest/iface.c @@ -127,6 +127,10 @@ if_what_changed(struct iface *i, struct iface *j) c |= IF_CHANGE_LINK; if (i->mtu != j->mtu) c |= IF_CHANGE_MTU; + if (strcmp(i->name, j->name)) + c |= IF_CHANGE_NAME; + + log(L_ERR "Interface %s changed: %X", i->name, c); return c; } @@ -179,6 +183,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_NAME) ? "changes name" : (c & IF_CHANGE_LINK) ? "changes link" : (c & IF_CHANGE_CREATE) ? "created" : "sends unknown event"); @@ -253,6 +258,40 @@ if_change_flags(struct iface *i, unsigned flags) } /** + * if_destroy - destroy given interface + * @i: interface to be removed + */ +static void +if_destroy(struct iface *i) +{ + struct ifa *a, *a_next; + + i->flags &= ~IF_UP; + i->flags |= IF_TMP_DOWN; + if_notify_change(IF_CHANGE_DOWN, i); + + /* + * all protocols are notified about ifa's going down (sockets became invalid) + * neighbor cache is cleared for this itnerface + */ + + /* Remove all addresses */ + WALK_LIST_DELSAFE(a, a_next, i->addrs) + mb_free(a); + + rem_node(&i->n); + + if (!EMPTY_LIST(i->neighbors)) + { + log(L_ERR "Error: neighbors cache for interface %s is not empty", i->name); + memset(i, 0, sizeof(struct iface)); + return; + } + + mb_free(i); +} + +/** * if_update - update interface status * @new: new interface status * @@ -282,6 +321,11 @@ if_update(struct iface *new) c = if_what_changed(i, new); if (c & IF_CHANGE_TOO_MUCH) /* Changed a lot, convert it to down/up */ { + if (new->flags & IF_SHUTDOWN) + { + if_destroy(i); + return NULL; + } DBG("Interface %s changed too much -- forcing down/up transition\n", i->name); if_change_flags(i, i->flags | IF_TMP_DOWN); rem_node(&i->n); diff --git a/nest/iface.h b/nest/iface.h index d6d58ff..cadf5c9 100644 --- a/nest/iface.h +++ b/nest/iface.h @@ -79,6 +79,7 @@ struct iface { #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_NAME 0x20 /* Interface is renamed */ #define IF_CHANGE_TOO_MUCH 0x40000000 /* Used internally */ void if_init(void); diff --git a/proto/ospf/iface.c b/proto/ospf/iface.c index cced710..73f44c1 100644 --- a/proto/ospf/iface.c +++ b/proto/ospf/iface.c @@ -1025,6 +1025,12 @@ ospf_ifaces_reconfigure(struct ospf_area *oa, struct ospf_area_config *nac) #endif static void +ospf_iface_rename(struct proto_ospf *po, struct iface *iface) +{ +} + + +static void ospf_iface_change_mtu(struct proto_ospf *po, struct ospf_iface *ifa) { struct proto *p = &po->proto; @@ -1081,6 +1087,9 @@ ospf_if_notify(struct proto *p, unsigned flags, struct iface *iface) if (flags & IF_CHANGE_UP) return; + if (flags & IF_CHANGE_NAME) + ospf_iface_rename(po, iface); + struct ospf_iface *ifa, *ifx; WALK_LIST_DELSAFE(ifa, ifx, po->iface_list) if ((ifa->type != OSPF_IT_VLINK) && (ifa->iface == iface)) diff --git a/sysdep/bsd/krt-sock.c b/sysdep/bsd/krt-sock.c index 4bf6600..9371e21 100644 --- a/sysdep/bsd/krt-sock.c +++ b/sysdep/bsd/krt-sock.c @@ -276,7 +276,7 @@ krt_read_rt(struct ks_msg *msg, struct krt_proto *p, int scan) if (sa_family_check(&dst)) get_sockaddr(&dst, &idst, NULL, NULL, 0); else - SKIP("invalid DST"); + SKIP("invalid DST\n"); /* We will check later whether we have valid gateway addr */ if (sa_family_check(&gate)) @@ -410,6 +410,60 @@ krt_read_rt(struct ks_msg *msg, struct krt_proto *p, int scan) } static void +krt_read_ifannounce(struct ks_msg *msg) +{ + struct iface *iface, f; + struct if_announcemsghdr *ifam = (struct if_announcemsghdr *)&msg->rtm; + + iface = if_find_by_index(ifam->ifan_index); + + if (ifam->ifan_what == IFAN_DEPARTURE) + { + /* Interface is destroyed */ + if (!iface) + { + DBG("KRT: unknown interface (%s, #%d) going down. Ignoring\n", ifam->ifan_name, ifam->ifan_index); + return; + } + + /* + * If interface is still up this means interface is renamed. Do nothing + * and update interface name on interface arrival event + */ + if (iface->flags & IF_UP) + return; + + /* Prepare fake structure without IF_UP flag */ + bzero(&f, sizeof(f)); + f.index = ifam->ifan_index; + f.flags = IF_SHUTDOWN; + memcpy(f.name, ifam->ifan_name, sizeof(f.name) - 1); + + if_update(&f); + return; + } + + if (ifam->ifan_what == IFAN_ARRIVAL) + { + /* New interface. Check if it already exists */ + if (!iface) + return; + + /* Interface is renamed. */ + if (strcmp(iface->name, ifam->ifan_name)) + { + DBG("KRT: Interface %s renamed to %s\n", iface->name, ifam->ifan_name); + memcpy(&f, iface, sizeof(struct iface)); + /* Assume both strings are IFNAMSIZ length */ + memcpy(f.name, ifam->ifan_name, IFNAMSIZ); + if_update(&f); + } + } + + DBG("KRT: IFANNOUNCE what: %d index %d name %s\n", ifam->ifan_what, ifam->ifan_index, ifam->ifan_name); +} + +static void krt_read_ifinfo(struct ks_msg *msg) { struct if_msghdr *ifm = (struct if_msghdr *)&msg->rtm; @@ -448,7 +502,7 @@ krt_read_ifinfo(struct ks_msg *msg) bzero(&f, sizeof(f)); f.index = ifm->ifm_index; memcpy(f.name, dl->sdl_data, MIN(sizeof(f.name)-1, dl->sdl_nlen)); - DBG("New interface '%s' found", f.name); + DBG("New interface '%s' found\n", f.name); } else { @@ -588,6 +642,8 @@ krt_read_msg(struct proto *p, struct ks_msg *msg, int scan) case RTM_DELETE: krt_read_rt(msg, (struct krt_proto *)p, scan); break; + case RTM_IFANNOUNCE: + krt_read_ifannounce(msg); case RTM_IFINFO: krt_read_ifinfo(msg); break; diff --git a/sysdep/unix/krt-iface.c b/sysdep/unix/krt-iface.c index 69048ae..0866e08 100644 --- a/sysdep/unix/krt-iface.c +++ b/sysdep/unix/krt-iface.c @@ -177,10 +177,15 @@ scan_ifs(struct ifreq *r, int cnt) a.flags |= IA_SECONDARY; pi = if_find_by_index(i.index); } - if (!pi) - pi = if_update(&i); - a.iface = pi; - ifa_update(&a); + if ((!pi) && (pi = if_update(&i))) + { + /* + * if_update() CAN return NULL for updates + * with IF_SHUTDOWN flag + */ + a.iface = pi; + ifa_update(&a); + } } if_end_update(); } -- 1.7.3.2
