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 <renato@opensourcerouting.org>
This commit is contained in:
Renato Westphal 2017-03-30 21:58:47 -03:00
parent 308252d06d
commit 52b530fc64
9 changed files with 80 additions and 99 deletions

View File

@ -49,17 +49,14 @@ iface_compare(struct iface *a, struct iface *b)
} }
struct iface * struct iface *
if_new(struct kif *kif) if_new(const char *name)
{ {
struct iface *iface; struct iface *iface;
if ((iface = calloc(1, sizeof(*iface))) == NULL) if ((iface = calloc(1, sizeof(*iface))) == NULL)
fatal("if_new: calloc"); fatal("if_new: calloc");
strlcpy(iface->name, kif->ifname, sizeof(iface->name)); strlcpy(iface->name, name, sizeof(iface->name));
LIST_INIT(&iface->addr_list);
if (kif->ifindex)
if_update_info(iface, kif);
/* ipv4 */ /* ipv4 */
iface->ipv4.af = AF_INET; iface->ipv4.af = AF_INET;

View File

@ -117,7 +117,7 @@ l2vpn_if_compare(struct l2vpn_if *a, struct l2vpn_if *b)
} }
struct l2vpn_if * 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; struct l2vpn_if *lif;
@ -125,9 +125,7 @@ l2vpn_if_new(struct l2vpn *l2vpn, struct kif *kif)
fatal("l2vpn_if_new: calloc"); fatal("l2vpn_if_new: calloc");
lif->l2vpn = l2vpn; lif->l2vpn = l2vpn;
strlcpy(lif->ifname, kif->ifname, sizeof(lif->ifname)); strlcpy(lif->ifname, ifname, sizeof(lif->ifname));
lif->ifindex = kif->ifindex;
lif->flags = kif->flags;
return (lif); 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)); 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 void
l2vpn_if_update(struct l2vpn_if *lif) 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 * 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; struct l2vpn_pw *pw;
@ -182,8 +188,7 @@ l2vpn_pw_new(struct l2vpn *l2vpn, struct kif *kif)
fatal("l2vpn_pw_new: calloc"); fatal("l2vpn_pw_new: calloc");
pw->l2vpn = l2vpn; pw->l2vpn = l2vpn;
strlcpy(pw->ifname, kif->ifname, sizeof(pw->ifname)); strlcpy(pw->ifname, ifname, sizeof(pw->ifname));
pw->ifindex = kif->ifindex;
return (pw); 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)); 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 void
l2vpn_pw_init(struct l2vpn_pw *pw) l2vpn_pw_init(struct l2vpn_pw *pw)
{ {

View File

@ -439,13 +439,14 @@ static int
lde_dispatch_parent(struct thread *thread) lde_dispatch_parent(struct thread *thread)
{ {
static struct ldpd_conf *nconf; static struct ldpd_conf *nconf;
struct iface *niface; struct iface *iface, *niface;
struct tnbr *ntnbr; struct tnbr *ntnbr;
struct nbr_params *nnbrp; struct nbr_params *nnbrp;
static struct l2vpn *nl2vpn; static struct l2vpn *l2vpn, *nl2vpn;
struct l2vpn_if *nlif; struct l2vpn_if *lif, *nlif;
struct l2vpn_pw *npw; struct l2vpn_pw *pw, *npw;
struct imsg imsg; struct imsg imsg;
struct kif *kif;
struct kroute *kr; struct kroute *kr;
int fd = THREAD_FD(thread); int fd = THREAD_FD(thread);
struct imsgev *iev = THREAD_ARG(thread); struct imsgev *iev = THREAD_ARG(thread);
@ -468,6 +469,31 @@ lde_dispatch_parent(struct thread *thread)
break; break;
switch (imsg.hdr.type) { 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_ADD:
case IMSG_NETWORK_UPDATE: case IMSG_NETWORK_UPDATE:
if (imsg.hdr.len != IMSG_HEADER_SIZE + if (imsg.hdr.len != IMSG_HEADER_SIZE +

View File

@ -212,13 +212,15 @@ struct l2vpn *l2vpn_find(struct ldpd_conf *, const char *);
void l2vpn_del(struct l2vpn *); void l2vpn_del(struct l2vpn *);
void l2vpn_init(struct l2vpn *); void l2vpn_init(struct l2vpn *);
void l2vpn_exit(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 *); 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 *); 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(struct l2vpn *, const char *);
struct l2vpn_pw *l2vpn_pw_find_active(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 *); 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_init(struct l2vpn_pw *);
void l2vpn_pw_exit(struct l2vpn_pw *); void l2vpn_pw_exit(struct l2vpn_pw *);
void l2vpn_pw_reset(struct l2vpn_pw *); void l2vpn_pw_reset(struct l2vpn_pw *);

View File

@ -907,8 +907,6 @@ ldp_vty_interface(struct vty *vty, struct vty_arg *args[])
int af; int af;
struct iface *iface; struct iface *iface;
struct iface_af *ia; struct iface_af *ia;
struct interface *ifp;
struct kif kif;
const char *ifname; const char *ifname;
int disable; int disable;
@ -940,23 +938,12 @@ ldp_vty_interface(struct vty *vty, struct vty_arg *args[])
return (CMD_SUCCESS); return (CMD_SUCCESS);
} }
ifp = if_lookup_by_name(ifname, VRF_DEFAULT); iface = if_new(ifname);
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);
ia = iface_af_get(iface, af); ia = iface_af_get(iface, af);
ia->enabled = 1; ia->enabled = 1;
RB_INSERT(iface_head, &vty_conf->iface_tree, iface); RB_INSERT(iface_head, &vty_conf->iface_tree, iface);
ldp_reload(vty_conf); ldp_reload(vty_conf);
} else { } else {
memset(&kif, 0, sizeof(kif));
strlcpy(kif.ifname, ifname, sizeof(kif.ifname));
ia = iface_af_get(iface, af); ia = iface_af_get(iface, af);
if (!ia->enabled) { if (!ia->enabled) {
ia->enabled = 1; ia->enabled = 1;
@ -1505,8 +1492,6 @@ ldp_vty_l2vpn_interface(struct vty *vty, struct vty_arg *args[])
{ {
struct l2vpn *l2vpn; struct l2vpn *l2vpn;
struct l2vpn_if *lif; struct l2vpn_if *lif;
struct interface *ifp;
struct kif kif;
const char *ifname; const char *ifname;
int disable; int disable;
@ -1535,15 +1520,7 @@ ldp_vty_l2vpn_interface(struct vty *vty, struct vty_arg *args[])
return (CMD_SUCCESS); return (CMD_SUCCESS);
} }
ifp = if_lookup_by_name(ifname, VRF_DEFAULT); lif = l2vpn_if_new(l2vpn, ifname);
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);
RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, lif); RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, lif);
ldp_reload(vty_conf); ldp_reload(vty_conf);
@ -1556,8 +1533,6 @@ ldp_vty_l2vpn_pseudowire(struct vty *vty, struct vty_arg *args[])
{ {
struct l2vpn *l2vpn; struct l2vpn *l2vpn;
struct l2vpn_pw *pw; struct l2vpn_pw *pw;
struct interface *ifp;
struct kif kif;
const char *ifname; const char *ifname;
int disable; int disable;
@ -1588,15 +1563,7 @@ ldp_vty_l2vpn_pseudowire(struct vty *vty, struct vty_arg *args[])
return (CMD_SUCCESS); return (CMD_SUCCESS);
} }
ifp = if_lookup_by_name(ifname, VRF_DEFAULT); pw = l2vpn_pw_new(l2vpn, ifname);
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->flags = F_PW_STATUSTLV_CONF|F_PW_CWORD_CONF; pw->flags = F_PW_STATUSTLV_CONF|F_PW_CWORD_CONF;
RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); 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; const char *ifname = name;
struct iface *iface; struct iface *iface;
struct interface *ifp;
struct kif kif;
if (ldp_iface_is_configured(conf, ifname)) if (ldp_iface_is_configured(conf, ifname))
return NULL; return NULL;
memset(&kif, 0, sizeof(kif)); iface = if_new(name);
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);
RB_INSERT(iface_head, &conf->iface_tree, iface); RB_INSERT(iface_head, &conf->iface_tree, iface);
return (iface); return (iface);
} }
@ -1882,21 +1839,11 @@ l2vpn_if_new_api(struct ldpd_conf *conf, struct l2vpn *l2vpn,
const char *ifname) const char *ifname)
{ {
struct l2vpn_if *lif; struct l2vpn_if *lif;
struct interface *ifp;
struct kif kif;
if (ldp_iface_is_configured(conf, ifname)) if (ldp_iface_is_configured(conf, ifname))
return (NULL); return (NULL);
memset(&kif, 0, sizeof(kif)); lif = l2vpn_if_new(l2vpn, ifname);
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);
RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, lif); RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, lif);
return (lif); return (lif);
} }
@ -1913,21 +1860,11 @@ l2vpn_pw_new_api(struct ldpd_conf *conf, struct l2vpn *l2vpn,
const char *ifname) const char *ifname)
{ {
struct l2vpn_pw *pw; struct l2vpn_pw *pw;
struct interface *ifp;
struct kif kif;
if (ldp_iface_is_configured(conf, ifname)) if (ldp_iface_is_configured(conf, ifname))
return (NULL); return (NULL);
memset(&kif, 0, sizeof(kif)); pw = l2vpn_pw_new(l2vpn, ifname);
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->flags = F_PW_STATUSTLV_CONF|F_PW_CWORD_CONF; pw->flags = F_PW_STATUSTLV_CONF|F_PW_CWORD_CONF;
RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
return (pw); return (pw);

View File

@ -180,7 +180,7 @@ kif_redistribute(const char *ifname)
continue; continue;
ifp2kif(ifp, &kif); 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)) { for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, ifc)) {
ifc2kaddr(ifp, ifc, &ka); ifc2kaddr(ifp, ifc, &ka);
@ -222,7 +222,7 @@ ldp_interface_add(int command, struct zclient *zclient, zebra_size_t length,
ifp->ifindex, ifp->mtu); ifp->ifindex, ifp->mtu);
ifp2kif(ifp, &kif); ifp2kif(ifp, &kif);
main_imsg_compose_ldpe(IMSG_IFSTATUS, 0, &kif, sizeof(kif)); main_imsg_compose_both(IMSG_IFSTATUS, &kif, sizeof(kif));
return (0); return (0);
} }
@ -270,7 +270,7 @@ ldp_interface_status_change(int command, struct zclient *zclient,
debug_zebra_in("interface %s state update", ifp->name); debug_zebra_in("interface %s state update", ifp->name);
ifp2kif(ifp, &kif); 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); link_new = (ifp->flags & IFF_UP) && (ifp->flags & IFF_RUNNING);
if (link_new) { if (link_new) {

View File

@ -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_REMOVE(l2vpn_if_head, &xl->if_tree, xf);
RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, xf); RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, xf);
xf->l2vpn = l2vpn; xf->l2vpn = l2vpn;
if (ldpd_process == PROC_MAIN) if (ldpd_process == PROC_MAIN) {
QOBJ_REG (xf, l2vpn_if); QOBJ_REG(xf, l2vpn_if);
kif_redistribute(xf->ifname);
}
continue; continue;
} }
@ -1705,6 +1707,7 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl)
break; break;
case PROC_MAIN: case PROC_MAIN:
QOBJ_REG (xp, l2vpn_pw); QOBJ_REG (xp, l2vpn_pw);
kif_redistribute(xp->ifname);
break; break;
} }
continue; 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_REMOVE(l2vpn_pw_head, &xl->pw_inactive_tree, xp);
RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, xp); RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, xp);
xp->l2vpn = l2vpn; xp->l2vpn = l2vpn;
if (ldpd_process == PROC_MAIN) if (ldpd_process == PROC_MAIN) {
QOBJ_REG (xp, l2vpn_pw); QOBJ_REG (xp, l2vpn_pw);
kif_redistribute(xp->ifname);
}
continue; continue;
} }

View File

@ -256,8 +256,8 @@ ldpe_dispatch_main(struct thread *thread)
struct tnbr *ntnbr; struct tnbr *ntnbr;
struct nbr_params *nnbrp; struct nbr_params *nnbrp;
static struct l2vpn *l2vpn, *nl2vpn; static struct l2vpn *l2vpn, *nl2vpn;
struct l2vpn_if *lif = NULL, *nlif; struct l2vpn_if *lif, *nlif;
struct l2vpn_pw *npw; struct l2vpn_pw *pw, *npw;
struct imsg imsg; struct imsg imsg;
int fd = THREAD_FD(thread); int fd = THREAD_FD(thread);
struct imsgev *iev = THREAD_ARG(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) { RB_FOREACH(l2vpn, l2vpn_head, &leconf->l2vpn_tree) {
lif = l2vpn_if_find(l2vpn, kif->ifname); lif = l2vpn_if_find(l2vpn, kif->ifname);
if (lif) { if (lif) {
lif->flags = kif->flags; l2vpn_if_update_info(lif, kif);
memcpy(lif->mac, kif->mac,
sizeof(lif->mac));
l2vpn_if_update(lif); l2vpn_if_update(lif);
break; break;
} }
pw = l2vpn_pw_find(l2vpn, kif->ifname);
if (pw) {
l2vpn_pw_update_info(pw, kif);
break;
}
} }
break; break;
case IMSG_NEWADDR: case IMSG_NEWADDR:

View File

@ -214,7 +214,7 @@ void mapping_list_add(struct mapping_head *, struct map *);
void mapping_list_clr(struct mapping_head *); void mapping_list_clr(struct mapping_head *);
/* interface.c */ /* interface.c */
struct iface *if_new(struct kif *); struct iface *if_new(const char *);
void if_exit(struct iface *); void if_exit(struct iface *);
struct iface *if_lookup(struct ldpd_conf *, unsigned short); struct iface *if_lookup(struct ldpd_conf *, unsigned short);
struct iface *if_lookup_name(struct ldpd_conf *, const char *); struct iface *if_lookup_name(struct ldpd_conf *, const char *);