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 *
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;

View File

@ -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)
{

View File

@ -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 +

View File

@ -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 *);

View File

@ -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);

View File

@ -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) {

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_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;
}

View File

@ -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:

View File

@ -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 *);