From: Renato Westphal Date: Wed, 22 Jun 2016 12:59:28 +0000 (-0300) Subject: ldpd: merge/dup/reload void **ref support X-Git-Tag: frr-2.0-rc1~180 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=b67c140b301f66241df15228e6dc35c8cf07ffc1;p=matthieu%2Ffrr.git ldpd: merge/dup/reload void **ref support Extend configuration duplication-merge mechanism to allow keeping track of a single specific object. A "void **" pointer is passed in; the "void *" pointer it points to is updated with the new address of the object it points to. Signed-off-by: David Lamparter --- diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index 1eaa7df4a5..ca503e0d6a 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -50,19 +50,20 @@ static int main_imsg_send_ipc_sockets(struct imsgbuf *, static void main_imsg_send_net_sockets(int); static void main_imsg_send_net_socket(int, enum socket_type); static int main_imsg_send_config(struct ldpd_conf *); -static void ldp_config_normalize(struct ldpd_conf *); -static void ldp_config_reset_main(struct ldpd_conf *); -static void ldp_config_reset_af(struct ldpd_conf *, int); +static void ldp_config_normalize(struct ldpd_conf *, void **); +static void ldp_config_reset_main(struct ldpd_conf *, void **); +static void ldp_config_reset_af(struct ldpd_conf *, int, void **); +static void merge_config_ref(struct ldpd_conf *, struct ldpd_conf *, void **); static void merge_global(struct ldpd_conf *, struct ldpd_conf *); static void merge_af(int, struct ldpd_af_conf *, struct ldpd_af_conf *); -static void merge_ifaces(struct ldpd_conf *, struct ldpd_conf *); +static void merge_ifaces(struct ldpd_conf *, struct ldpd_conf *, void **); static void merge_iface_af(struct iface_af *, struct iface_af *); -static void merge_tnbrs(struct ldpd_conf *, struct ldpd_conf *); -static void merge_nbrps(struct ldpd_conf *, struct ldpd_conf *); -static void merge_l2vpns(struct ldpd_conf *, struct ldpd_conf *); +static void merge_tnbrs(struct ldpd_conf *, struct ldpd_conf *, void **); +static void merge_nbrps(struct ldpd_conf *, struct ldpd_conf *, void **); +static void merge_l2vpns(struct ldpd_conf *, struct ldpd_conf *, void **); static void merge_l2vpn(struct ldpd_conf *, struct l2vpn *, - struct l2vpn *); + struct l2vpn *, void **); struct ldpd_global global; struct ldpd_conf *ldpd_conf; @@ -320,7 +321,7 @@ main(int argc, char *argv[]) /* Get configuration file. */ ldpd_conf = config_new_empty(); - ldp_config_reset_main(ldpd_conf); + ldp_config_reset_main(ldpd_conf, NULL); vty_read_config(config_file, config_default); /* Start execution only if not in dry-run mode */ @@ -884,31 +885,37 @@ main_imsg_send_config(struct ldpd_conf *xconf) } int -ldp_reload(struct ldpd_conf *xconf) +ldp_reload_ref(struct ldpd_conf *xconf, void **ref) { - ldp_config_normalize(xconf); + ldp_config_normalize(xconf, ref); if (main_imsg_send_config(xconf) == -1) return (-1); - merge_config(ldpd_conf, xconf); + merge_config_ref(ldpd_conf, xconf, ref); return (0); } +int +ldp_reload(struct ldpd_conf *xconf) +{ + return ldp_reload_ref(xconf, NULL); +} + static void -ldp_config_normalize(struct ldpd_conf *xconf) +ldp_config_normalize(struct ldpd_conf *xconf, void **ref) { struct l2vpn *l2vpn; struct l2vpn_pw *pw; if (!(xconf->flags & F_LDPD_ENABLED)) - ldp_config_reset_main(xconf); + ldp_config_reset_main(xconf, ref); else { if (!(xconf->ipv4.flags & F_LDPD_AF_ENABLED)) - ldp_config_reset_af(xconf, AF_INET); + ldp_config_reset_af(xconf, AF_INET, ref); if (!(xconf->ipv6.flags & F_LDPD_AF_ENABLED)) - ldp_config_reset_af(xconf, AF_INET6); + ldp_config_reset_af(xconf, AF_INET6, ref); } LIST_FOREACH(l2vpn, &xconf->l2vpn_list, entry) { @@ -930,24 +937,28 @@ ldp_config_normalize(struct ldpd_conf *xconf) } static void -ldp_config_reset_main(struct ldpd_conf *conf) +ldp_config_reset_main(struct ldpd_conf *conf, void **ref) { struct iface *iface; struct nbr_params *nbrp; while ((iface = LIST_FIRST(&conf->iface_list)) != NULL) { + if (ref && *ref == iface) + *ref = NULL; LIST_REMOVE(iface, entry); free(iface); } while ((nbrp = LIST_FIRST(&conf->nbrp_list)) != NULL) { + if (ref && *ref == nbrp) + *ref = NULL; LIST_REMOVE(nbrp, entry); free(nbrp); } conf->rtr_id.s_addr = INADDR_ANY; - ldp_config_reset_af(conf, AF_INET); - ldp_config_reset_af(conf, AF_INET6); + ldp_config_reset_af(conf, AF_INET, ref); + ldp_config_reset_af(conf, AF_INET6, ref); conf->lhello_holdtime = LINK_DFLT_HOLDTIME; conf->lhello_interval = DEFAULT_HELLO_INTERVAL; conf->thello_holdtime = TARGETED_DFLT_HOLDTIME; @@ -957,7 +968,7 @@ ldp_config_reset_main(struct ldpd_conf *conf) } static void -ldp_config_reset_af(struct ldpd_conf *conf, int af) +ldp_config_reset_af(struct ldpd_conf *conf, int af, void **ref) { struct ldpd_af_conf *af_conf; struct iface *iface; @@ -973,6 +984,8 @@ ldp_config_reset_af(struct ldpd_conf *conf, int af) if (tnbr->af != af) continue; + if (ref && *ref == tnbr) + *ref = NULL; LIST_REMOVE(tnbr, entry); free(tnbr); } @@ -988,7 +1001,7 @@ ldp_config_reset_af(struct ldpd_conf *conf, int af) } struct ldpd_conf * -ldp_dup_config(struct ldpd_conf *conf) +ldp_dup_config_ref(struct ldpd_conf *conf, void **ref) { struct ldpd_conf *xconf; struct iface *iface, *xi; @@ -998,75 +1011,68 @@ ldp_dup_config(struct ldpd_conf *conf) struct l2vpn_if *lif, *xf; struct l2vpn_pw *pw, *xp; - xconf = malloc(sizeof(*xconf)); - *xconf = *conf; +#define COPY(a, b) do { \ + a = calloc(1, sizeof(*a)); \ + if (a == NULL) \ + fatal(__func__); \ + *a = *b; \ + if (ref && *ref == b) *ref = a; \ + } while (0) + + COPY(xconf, conf); LIST_INIT(&xconf->iface_list); LIST_INIT(&xconf->tnbr_list); LIST_INIT(&xconf->nbrp_list); LIST_INIT(&xconf->l2vpn_list); LIST_FOREACH(iface, &conf->iface_list, entry) { - xi = calloc(1, sizeof(*xi)); - if (xi == NULL) - fatal(__func__); - *xi = *iface; + COPY(xi, iface); xi->ipv4.iface = xi; xi->ipv6.iface = xi; LIST_INSERT_HEAD(&xconf->iface_list, xi, entry); } LIST_FOREACH(tnbr, &conf->tnbr_list, entry) { - xt = calloc(1, sizeof(*xt)); - if (xt == NULL) - fatal(__func__); - *xt = *tnbr; + COPY(xt, tnbr); LIST_INSERT_HEAD(&xconf->tnbr_list, xt, entry); } LIST_FOREACH(nbrp, &conf->nbrp_list, entry) { - xn = calloc(1, sizeof(*xn)); - if (xn == NULL) - fatal(__func__); - *xn = *nbrp; + COPY(xn, nbrp); LIST_INSERT_HEAD(&xconf->nbrp_list, xn, entry); } LIST_FOREACH(l2vpn, &conf->l2vpn_list, entry) { - xl = calloc(1, sizeof(*xl)); - if (xl == NULL) - fatal(__func__); - *xl = *l2vpn; + COPY(xl, l2vpn); LIST_INIT(&xl->if_list); LIST_INIT(&xl->pw_list); LIST_INIT(&xl->pw_inactive_list); LIST_INSERT_HEAD(&xconf->l2vpn_list, xl, entry); LIST_FOREACH(lif, &l2vpn->if_list, entry) { - xf = calloc(1, sizeof(*xf)); - if (xf == NULL) - fatal(__func__); - *xf = *lif; + COPY(xf, lif); xf->l2vpn = xl; LIST_INSERT_HEAD(&xl->if_list, xf, entry); } LIST_FOREACH(pw, &l2vpn->pw_list, entry) { - xp = calloc(1, sizeof(*xp)); - if (xp == NULL) - fatal(__func__); - *xp = *pw; + COPY(xp, pw); xp->l2vpn = xl; LIST_INSERT_HEAD(&xl->pw_list, xp, entry); } LIST_FOREACH(pw, &l2vpn->pw_inactive_list, entry) { - xp = calloc(1, sizeof(*xp)); - if (xp == NULL) - fatal(__func__); - *xp = *pw; + COPY(xp, pw); xp->l2vpn = xl; LIST_INSERT_HEAD(&xl->pw_inactive_list, xp, entry); } } +#undef COPY return (xconf); } +struct ldpd_conf * +ldp_dup_config(struct ldpd_conf *conf) +{ + return ldp_dup_config_ref(conf, NULL); +} + void ldp_clear_config(struct ldpd_conf *xconf) { @@ -1095,19 +1101,27 @@ ldp_clear_config(struct ldpd_conf *xconf) free(xconf); } -void -merge_config(struct ldpd_conf *conf, struct ldpd_conf *xconf) +static void +merge_config_ref(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref) { merge_global(conf, xconf); merge_af(AF_INET, &conf->ipv4, &xconf->ipv4); merge_af(AF_INET6, &conf->ipv6, &xconf->ipv6); - merge_ifaces(conf, xconf); - merge_tnbrs(conf, xconf); - merge_nbrps(conf, xconf); - merge_l2vpns(conf, xconf); + merge_ifaces(conf, xconf, ref); + merge_tnbrs(conf, xconf, ref); + merge_nbrps(conf, xconf, ref); + merge_l2vpns(conf, xconf, ref); + if (ref && *ref == xconf) + *ref = conf; free(xconf); } +void +merge_config(struct ldpd_conf *conf, struct ldpd_conf *xconf) +{ + merge_config_ref(conf, xconf, NULL); +} + static void merge_global(struct ldpd_conf *conf, struct ldpd_conf *xconf) { @@ -1206,7 +1220,7 @@ merge_af(int af, struct ldpd_af_conf *af_conf, struct ldpd_af_conf *xa) } static void -merge_ifaces(struct ldpd_conf *conf, struct ldpd_conf *xconf) +merge_ifaces(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref) { struct iface *iface, *itmp, *xi; @@ -1235,6 +1249,8 @@ merge_ifaces(struct ldpd_conf *conf, struct ldpd_conf *xconf) merge_iface_af(&iface->ipv4, &xi->ipv4); merge_iface_af(&iface->ipv6, &xi->ipv6); LIST_REMOVE(xi, entry); + if (ref && *ref == xi) + *ref = iface; free(xi); } } @@ -1252,7 +1268,7 @@ merge_iface_af(struct iface_af *ia, struct iface_af *xi) } static void -merge_tnbrs(struct ldpd_conf *conf, struct ldpd_conf *xconf) +merge_tnbrs(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref) { struct tnbr *tnbr, *ttmp, *xt; @@ -1286,12 +1302,14 @@ merge_tnbrs(struct ldpd_conf *conf, struct ldpd_conf *xconf) if (!(tnbr->flags & F_TNBR_CONFIGURED)) tnbr->flags |= F_TNBR_CONFIGURED; LIST_REMOVE(xt, entry); + if (ref && *ref == xt) + *ref = tnbr; free(xt); } } static void -merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf) +merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref) { struct nbr_params *nbrp, *ntmp, *xn; struct nbr *nbr; @@ -1385,12 +1403,14 @@ merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf) } } LIST_REMOVE(xn, entry); + if (ref && *ref == xn) + *ref = nbrp; free(xn); } } static void -merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf) +merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref) { struct l2vpn *l2vpn, *ltmp, *xl; @@ -1432,14 +1452,16 @@ merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf) } /* update existing l2vpns */ - merge_l2vpn(conf, l2vpn, xl); + merge_l2vpn(conf, l2vpn, xl, ref); LIST_REMOVE(xl, entry); + if (ref && *ref == xl) + *ref = l2vpn; free(xl); } } static void -merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) +merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl, void **ref) { struct l2vpn_if *lif, *ftmp, *xf; struct l2vpn_pw *pw, *ptmp, *xp; @@ -1469,6 +1491,8 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) } LIST_REMOVE(xf, entry); + if (ref && *ref == xf) + *ref = lif; free(xf); } @@ -1597,6 +1621,8 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) } LIST_REMOVE(xp, entry); + if (ref && *ref == xp) + *ref = pw; free(xp); } @@ -1645,6 +1671,8 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) } LIST_REMOVE(xp, entry); + if (ref && *ref == xp) + *ref = pw; free(xp); } diff --git a/ldpd/ldpd.h b/ldpd/ldpd.h index b94794208a..d04614d37a 100644 --- a/ldpd/ldpd.h +++ b/ldpd/ldpd.h @@ -602,6 +602,8 @@ struct ldpd_af_global *ldp_af_global_get(struct ldpd_global *, int); int ldp_is_dual_stack(struct ldpd_conf *); in_addr_t ldp_rtr_id_get(struct ldpd_conf *); int ldp_reload(struct ldpd_conf *); +int ldp_reload_ref(struct ldpd_conf *, void **); +struct ldpd_conf *ldp_dup_config_ref(struct ldpd_conf *, void **ref); struct ldpd_conf *ldp_dup_config(struct ldpd_conf *); void ldp_clear_config(struct ldpd_conf *); void merge_config(struct ldpd_conf *, struct ldpd_conf *);