From 52b530fc64355933d428e2b88591cbf926b85bc8 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 30 Mar 2017 21:58:47 -0300 Subject: [PATCH] ldpd: fix configuration of non-existing VPLS interfaces and pseudowires If we don't know the ifindex, flags, etc of an interface at the time it's configured, we should make sure that once this information is available the appropriate structures are updated. Signed-off-by: Renato Westphal --- ldpd/interface.c | 7 ++--- ldpd/l2vpn.c | 25 ++++++++++----- ldpd/lde.c | 34 +++++++++++++++++--- ldpd/lde.h | 6 ++-- ldpd/ldp_vty_conf.c | 75 ++++----------------------------------------- ldpd/ldp_zebra.c | 6 ++-- ldpd/ldpd.c | 11 +++++-- ldpd/ldpe.c | 13 +++++--- ldpd/ldpe.h | 2 +- 9 files changed, 80 insertions(+), 99 deletions(-) diff --git a/ldpd/interface.c b/ldpd/interface.c index 17b3237b37..11bce12b09 100644 --- a/ldpd/interface.c +++ b/ldpd/interface.c @@ -49,17 +49,14 @@ iface_compare(struct iface *a, struct iface *b) } struct iface * -if_new(struct kif *kif) +if_new(const char *name) { struct iface *iface; if ((iface = calloc(1, sizeof(*iface))) == NULL) fatal("if_new: calloc"); - strlcpy(iface->name, kif->ifname, sizeof(iface->name)); - LIST_INIT(&iface->addr_list); - if (kif->ifindex) - if_update_info(iface, kif); + strlcpy(iface->name, name, sizeof(iface->name)); /* ipv4 */ iface->ipv4.af = AF_INET; diff --git a/ldpd/l2vpn.c b/ldpd/l2vpn.c index bdfcd420eb..92d865210a 100644 --- a/ldpd/l2vpn.c +++ b/ldpd/l2vpn.c @@ -117,7 +117,7 @@ l2vpn_if_compare(struct l2vpn_if *a, struct l2vpn_if *b) } struct l2vpn_if * -l2vpn_if_new(struct l2vpn *l2vpn, struct kif *kif) +l2vpn_if_new(struct l2vpn *l2vpn, const char *ifname) { struct l2vpn_if *lif; @@ -125,9 +125,7 @@ l2vpn_if_new(struct l2vpn *l2vpn, struct kif *kif) fatal("l2vpn_if_new: calloc"); lif->l2vpn = l2vpn; - strlcpy(lif->ifname, kif->ifname, sizeof(lif->ifname)); - lif->ifindex = kif->ifindex; - lif->flags = kif->flags; + strlcpy(lif->ifname, ifname, sizeof(lif->ifname)); return (lif); } @@ -140,6 +138,14 @@ l2vpn_if_find(struct l2vpn *l2vpn, const char *ifname) return (RB_FIND(l2vpn_if_head, &l2vpn->if_tree, &lif)); } +void +l2vpn_if_update_info(struct l2vpn_if *lif, struct kif *kif) +{ + lif->ifindex = kif->ifindex; + lif->flags = kif->flags; + memcpy(lif->mac, kif->mac, sizeof(lif->mac)); +} + void l2vpn_if_update(struct l2vpn_if *lif) { @@ -174,7 +180,7 @@ l2vpn_pw_compare(struct l2vpn_pw *a, struct l2vpn_pw *b) } struct l2vpn_pw * -l2vpn_pw_new(struct l2vpn *l2vpn, struct kif *kif) +l2vpn_pw_new(struct l2vpn *l2vpn, const char *ifname) { struct l2vpn_pw *pw; @@ -182,8 +188,7 @@ l2vpn_pw_new(struct l2vpn *l2vpn, struct kif *kif) fatal("l2vpn_pw_new: calloc"); pw->l2vpn = l2vpn; - strlcpy(pw->ifname, kif->ifname, sizeof(pw->ifname)); - pw->ifindex = kif->ifindex; + strlcpy(pw->ifname, ifname, sizeof(pw->ifname)); return (pw); } @@ -219,6 +224,12 @@ l2vpn_pw_find_inactive(struct l2vpn *l2vpn, const char *ifname) return (RB_FIND(l2vpn_pw_head, &l2vpn->pw_inactive_tree, &s)); } +void +l2vpn_pw_update_info(struct l2vpn_pw *pw, struct kif *kif) +{ + pw->ifindex = kif->ifindex; +} + void l2vpn_pw_init(struct l2vpn_pw *pw) { diff --git a/ldpd/lde.c b/ldpd/lde.c index bc808e6841..607a9f7b14 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -439,13 +439,14 @@ static int lde_dispatch_parent(struct thread *thread) { static struct ldpd_conf *nconf; - struct iface *niface; + struct iface *iface, *niface; struct tnbr *ntnbr; struct nbr_params *nnbrp; - static struct l2vpn *nl2vpn; - struct l2vpn_if *nlif; - struct l2vpn_pw *npw; + static struct l2vpn *l2vpn, *nl2vpn; + struct l2vpn_if *lif, *nlif; + struct l2vpn_pw *pw, *npw; struct imsg imsg; + struct kif *kif; struct kroute *kr; int fd = THREAD_FD(thread); struct imsgev *iev = THREAD_ARG(thread); @@ -468,6 +469,31 @@ lde_dispatch_parent(struct thread *thread) break; switch (imsg.hdr.type) { + case IMSG_IFSTATUS: + if (imsg.hdr.len != IMSG_HEADER_SIZE + + sizeof(struct kif)) + fatalx("IFSTATUS imsg with wrong len"); + kif = imsg.data; + + iface = if_lookup_name(ldeconf, kif->ifname); + if (iface) { + if_update_info(iface, kif); + break; + } + + RB_FOREACH(l2vpn, l2vpn_head, &ldeconf->l2vpn_tree) { + lif = l2vpn_if_find(l2vpn, kif->ifname); + if (lif) { + l2vpn_if_update_info(lif, kif); + break; + } + pw = l2vpn_pw_find(l2vpn, kif->ifname); + if (pw) { + l2vpn_pw_update_info(pw, kif); + break; + } + } + break; case IMSG_NETWORK_ADD: case IMSG_NETWORK_UPDATE: if (imsg.hdr.len != IMSG_HEADER_SIZE + diff --git a/ldpd/lde.h b/ldpd/lde.h index 8ee62b02d3..57791cd1b0 100644 --- a/ldpd/lde.h +++ b/ldpd/lde.h @@ -212,13 +212,15 @@ struct l2vpn *l2vpn_find(struct ldpd_conf *, const char *); void l2vpn_del(struct l2vpn *); void l2vpn_init(struct l2vpn *); void l2vpn_exit(struct l2vpn *); -struct l2vpn_if *l2vpn_if_new(struct l2vpn *, struct kif *); +struct l2vpn_if *l2vpn_if_new(struct l2vpn *, const char *); struct l2vpn_if *l2vpn_if_find(struct l2vpn *, const char *); +void l2vpn_if_update_info(struct l2vpn_if *, struct kif *); void l2vpn_if_update(struct l2vpn_if *); -struct l2vpn_pw *l2vpn_pw_new(struct l2vpn *, struct kif *); +struct l2vpn_pw *l2vpn_pw_new(struct l2vpn *, const char *); struct l2vpn_pw *l2vpn_pw_find(struct l2vpn *, const char *); struct l2vpn_pw *l2vpn_pw_find_active(struct l2vpn *, const char *); struct l2vpn_pw *l2vpn_pw_find_inactive(struct l2vpn *, const char *); +void l2vpn_pw_update_info(struct l2vpn_pw *, struct kif *); void l2vpn_pw_init(struct l2vpn_pw *); void l2vpn_pw_exit(struct l2vpn_pw *); void l2vpn_pw_reset(struct l2vpn_pw *); diff --git a/ldpd/ldp_vty_conf.c b/ldpd/ldp_vty_conf.c index dcf5f52436..4c6cfcd4a3 100644 --- a/ldpd/ldp_vty_conf.c +++ b/ldpd/ldp_vty_conf.c @@ -907,8 +907,6 @@ ldp_vty_interface(struct vty *vty, struct vty_arg *args[]) int af; struct iface *iface; struct iface_af *ia; - struct interface *ifp; - struct kif kif; const char *ifname; int disable; @@ -940,23 +938,12 @@ ldp_vty_interface(struct vty *vty, struct vty_arg *args[]) return (CMD_SUCCESS); } - ifp = if_lookup_by_name(ifname, VRF_DEFAULT); - memset(&kif, 0, sizeof(kif)); - strlcpy(kif.ifname, ifname, sizeof(kif.ifname)); - if (ifp) { - kif.ifindex = ifp->ifindex; - kif.flags = ifp->flags; - } - iface = if_new(&kif); - + iface = if_new(ifname); ia = iface_af_get(iface, af); ia->enabled = 1; RB_INSERT(iface_head, &vty_conf->iface_tree, iface); ldp_reload(vty_conf); } else { - memset(&kif, 0, sizeof(kif)); - strlcpy(kif.ifname, ifname, sizeof(kif.ifname)); - ia = iface_af_get(iface, af); if (!ia->enabled) { ia->enabled = 1; @@ -1505,8 +1492,6 @@ ldp_vty_l2vpn_interface(struct vty *vty, struct vty_arg *args[]) { struct l2vpn *l2vpn; struct l2vpn_if *lif; - struct interface *ifp; - struct kif kif; const char *ifname; int disable; @@ -1535,15 +1520,7 @@ ldp_vty_l2vpn_interface(struct vty *vty, struct vty_arg *args[]) return (CMD_SUCCESS); } - ifp = if_lookup_by_name(ifname, VRF_DEFAULT); - memset(&kif, 0, sizeof(kif)); - strlcpy(kif.ifname, ifname, sizeof(kif.ifname)); - if (ifp) { - kif.ifindex = ifp->ifindex; - kif.flags = ifp->flags; - } - - lif = l2vpn_if_new(l2vpn, &kif); + lif = l2vpn_if_new(l2vpn, ifname); RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, lif); ldp_reload(vty_conf); @@ -1556,8 +1533,6 @@ ldp_vty_l2vpn_pseudowire(struct vty *vty, struct vty_arg *args[]) { struct l2vpn *l2vpn; struct l2vpn_pw *pw; - struct interface *ifp; - struct kif kif; const char *ifname; int disable; @@ -1588,15 +1563,7 @@ ldp_vty_l2vpn_pseudowire(struct vty *vty, struct vty_arg *args[]) return (CMD_SUCCESS); } - ifp = if_lookup_by_name(ifname, VRF_DEFAULT); - memset(&kif, 0, sizeof(kif)); - strlcpy(kif.ifname, ifname, sizeof(kif.ifname)); - if (ifp) { - kif.ifindex = ifp->ifindex; - kif.flags = ifp->flags; - } - - pw = l2vpn_pw_new(l2vpn, &kif); + pw = l2vpn_pw_new(l2vpn, ifname); pw->flags = F_PW_STATUSTLV_CONF|F_PW_CWORD_CONF; RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); @@ -1771,21 +1738,11 @@ iface_new_api(struct ldpd_conf *conf, const char *name) { const char *ifname = name; struct iface *iface; - struct interface *ifp; - struct kif kif; if (ldp_iface_is_configured(conf, ifname)) return NULL; - memset(&kif, 0, sizeof(kif)); - strlcpy(kif.ifname, ifname, sizeof(kif.ifname)); - ifp = if_lookup_by_name(ifname, VRF_DEFAULT); - if (ifp) { - kif.ifindex = ifp->ifindex; - kif.flags = ifp->flags; - } - - iface = if_new(&kif); + iface = if_new(name); RB_INSERT(iface_head, &conf->iface_tree, iface); return (iface); } @@ -1882,21 +1839,11 @@ l2vpn_if_new_api(struct ldpd_conf *conf, struct l2vpn *l2vpn, const char *ifname) { struct l2vpn_if *lif; - struct interface *ifp; - struct kif kif; if (ldp_iface_is_configured(conf, ifname)) return (NULL); - memset(&kif, 0, sizeof(kif)); - strlcpy(kif.ifname, ifname, sizeof(kif.ifname)); - ifp = if_lookup_by_name(ifname, VRF_DEFAULT); - if (ifp) { - kif.ifindex = ifp->ifindex; - kif.flags = ifp->flags; - } - - lif = l2vpn_if_new(l2vpn, &kif); + lif = l2vpn_if_new(l2vpn, ifname); RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, lif); return (lif); } @@ -1913,21 +1860,11 @@ l2vpn_pw_new_api(struct ldpd_conf *conf, struct l2vpn *l2vpn, const char *ifname) { struct l2vpn_pw *pw; - struct interface *ifp; - struct kif kif; if (ldp_iface_is_configured(conf, ifname)) return (NULL); - memset(&kif, 0, sizeof(kif)); - strlcpy(kif.ifname, ifname, sizeof(kif.ifname)); - ifp = if_lookup_by_name(ifname, VRF_DEFAULT); - if (ifp) { - kif.ifindex = ifp->ifindex; - kif.flags = ifp->flags; - } - - pw = l2vpn_pw_new(l2vpn, &kif); + pw = l2vpn_pw_new(l2vpn, ifname); pw->flags = F_PW_STATUSTLV_CONF|F_PW_CWORD_CONF; RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); return (pw); diff --git a/ldpd/ldp_zebra.c b/ldpd/ldp_zebra.c index c41a0dbd91..702b5c5eaa 100644 --- a/ldpd/ldp_zebra.c +++ b/ldpd/ldp_zebra.c @@ -180,7 +180,7 @@ kif_redistribute(const char *ifname) continue; ifp2kif(ifp, &kif); - main_imsg_compose_ldpe(IMSG_IFSTATUS, 0, &kif, sizeof(kif)); + main_imsg_compose_both(IMSG_IFSTATUS, &kif, sizeof(kif)); for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, ifc)) { ifc2kaddr(ifp, ifc, &ka); @@ -222,7 +222,7 @@ ldp_interface_add(int command, struct zclient *zclient, zebra_size_t length, ifp->ifindex, ifp->mtu); ifp2kif(ifp, &kif); - main_imsg_compose_ldpe(IMSG_IFSTATUS, 0, &kif, sizeof(kif)); + main_imsg_compose_both(IMSG_IFSTATUS, &kif, sizeof(kif)); return (0); } @@ -270,7 +270,7 @@ ldp_interface_status_change(int command, struct zclient *zclient, debug_zebra_in("interface %s state update", ifp->name); ifp2kif(ifp, &kif); - main_imsg_compose_ldpe(IMSG_IFSTATUS, 0, &kif, sizeof(kif)); + main_imsg_compose_both(IMSG_IFSTATUS, &kif, sizeof(kif)); link_new = (ifp->flags & IFF_UP) && (ifp->flags & IFF_RUNNING); if (link_new) { diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index 3b3a07c28c..6c888c534c 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -1660,8 +1660,10 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) RB_REMOVE(l2vpn_if_head, &xl->if_tree, xf); RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, xf); xf->l2vpn = l2vpn; - if (ldpd_process == PROC_MAIN) - QOBJ_REG (xf, l2vpn_if); + if (ldpd_process == PROC_MAIN) { + QOBJ_REG(xf, l2vpn_if); + kif_redistribute(xf->ifname); + } continue; } @@ -1705,6 +1707,7 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) break; case PROC_MAIN: QOBJ_REG (xp, l2vpn_pw); + kif_redistribute(xp->ifname); break; } continue; @@ -1792,8 +1795,10 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) RB_REMOVE(l2vpn_pw_head, &xl->pw_inactive_tree, xp); RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, xp); xp->l2vpn = l2vpn; - if (ldpd_process == PROC_MAIN) + if (ldpd_process == PROC_MAIN) { QOBJ_REG (xp, l2vpn_pw); + kif_redistribute(xp->ifname); + } continue; } diff --git a/ldpd/ldpe.c b/ldpd/ldpe.c index 96a7052ec6..f8e9abab02 100644 --- a/ldpd/ldpe.c +++ b/ldpd/ldpe.c @@ -256,8 +256,8 @@ ldpe_dispatch_main(struct thread *thread) struct tnbr *ntnbr; struct nbr_params *nnbrp; static struct l2vpn *l2vpn, *nl2vpn; - struct l2vpn_if *lif = NULL, *nlif; - struct l2vpn_pw *npw; + struct l2vpn_if *lif, *nlif; + struct l2vpn_pw *pw, *npw; struct imsg imsg; int fd = THREAD_FD(thread); struct imsgev *iev = THREAD_ARG(thread); @@ -305,12 +305,15 @@ ldpe_dispatch_main(struct thread *thread) RB_FOREACH(l2vpn, l2vpn_head, &leconf->l2vpn_tree) { lif = l2vpn_if_find(l2vpn, kif->ifname); if (lif) { - lif->flags = kif->flags; - memcpy(lif->mac, kif->mac, - sizeof(lif->mac)); + l2vpn_if_update_info(lif, kif); l2vpn_if_update(lif); break; } + pw = l2vpn_pw_find(l2vpn, kif->ifname); + if (pw) { + l2vpn_pw_update_info(pw, kif); + break; + } } break; case IMSG_NEWADDR: diff --git a/ldpd/ldpe.h b/ldpd/ldpe.h index 8215d08407..e4b8394aa0 100644 --- a/ldpd/ldpe.h +++ b/ldpd/ldpe.h @@ -214,7 +214,7 @@ void mapping_list_add(struct mapping_head *, struct map *); void mapping_list_clr(struct mapping_head *); /* interface.c */ -struct iface *if_new(struct kif *); +struct iface *if_new(const char *); void if_exit(struct iface *); struct iface *if_lookup(struct ldpd_conf *, unsigned short); struct iface *if_lookup_name(struct ldpd_conf *, const char *);