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 <equinox@opensourcerouting.org>
This commit is contained in:
Renato Westphal 2016-06-22 09:59:28 -03:00 committed by Donald Sharp
parent 271327b121
commit b67c140b30
2 changed files with 93 additions and 63 deletions

View File

@ -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_sockets(int);
static void main_imsg_send_net_socket(int, enum socket_type); static void main_imsg_send_net_socket(int, enum socket_type);
static int main_imsg_send_config(struct ldpd_conf *); static int main_imsg_send_config(struct ldpd_conf *);
static void ldp_config_normalize(struct ldpd_conf *); static void ldp_config_normalize(struct ldpd_conf *, void **);
static void ldp_config_reset_main(struct ldpd_conf *); static void ldp_config_reset_main(struct ldpd_conf *, void **);
static void ldp_config_reset_af(struct ldpd_conf *, int); 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_global(struct ldpd_conf *, struct ldpd_conf *);
static void merge_af(int, struct ldpd_af_conf *, static void merge_af(int, struct ldpd_af_conf *,
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_iface_af(struct iface_af *, struct iface_af *);
static void merge_tnbrs(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 *); static void merge_nbrps(struct ldpd_conf *, struct ldpd_conf *, void **);
static void merge_l2vpns(struct ldpd_conf *, struct ldpd_conf *); static void merge_l2vpns(struct ldpd_conf *, struct ldpd_conf *, void **);
static void merge_l2vpn(struct ldpd_conf *, struct l2vpn *, static void merge_l2vpn(struct ldpd_conf *, struct l2vpn *,
struct l2vpn *); struct l2vpn *, void **);
struct ldpd_global global; struct ldpd_global global;
struct ldpd_conf *ldpd_conf; struct ldpd_conf *ldpd_conf;
@ -320,7 +321,7 @@ main(int argc, char *argv[])
/* Get configuration file. */ /* Get configuration file. */
ldpd_conf = config_new_empty(); 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); vty_read_config(config_file, config_default);
/* Start execution only if not in dry-run mode */ /* Start execution only if not in dry-run mode */
@ -884,31 +885,37 @@ main_imsg_send_config(struct ldpd_conf *xconf)
} }
int 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) if (main_imsg_send_config(xconf) == -1)
return (-1); return (-1);
merge_config(ldpd_conf, xconf); merge_config_ref(ldpd_conf, xconf, ref);
return (0); return (0);
} }
int
ldp_reload(struct ldpd_conf *xconf)
{
return ldp_reload_ref(xconf, NULL);
}
static void static void
ldp_config_normalize(struct ldpd_conf *xconf) ldp_config_normalize(struct ldpd_conf *xconf, void **ref)
{ {
struct l2vpn *l2vpn; struct l2vpn *l2vpn;
struct l2vpn_pw *pw; struct l2vpn_pw *pw;
if (!(xconf->flags & F_LDPD_ENABLED)) if (!(xconf->flags & F_LDPD_ENABLED))
ldp_config_reset_main(xconf); ldp_config_reset_main(xconf, ref);
else { else {
if (!(xconf->ipv4.flags & F_LDPD_AF_ENABLED)) 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)) 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) { LIST_FOREACH(l2vpn, &xconf->l2vpn_list, entry) {
@ -930,24 +937,28 @@ ldp_config_normalize(struct ldpd_conf *xconf)
} }
static void static void
ldp_config_reset_main(struct ldpd_conf *conf) ldp_config_reset_main(struct ldpd_conf *conf, void **ref)
{ {
struct iface *iface; struct iface *iface;
struct nbr_params *nbrp; struct nbr_params *nbrp;
while ((iface = LIST_FIRST(&conf->iface_list)) != NULL) { while ((iface = LIST_FIRST(&conf->iface_list)) != NULL) {
if (ref && *ref == iface)
*ref = NULL;
LIST_REMOVE(iface, entry); LIST_REMOVE(iface, entry);
free(iface); free(iface);
} }
while ((nbrp = LIST_FIRST(&conf->nbrp_list)) != NULL) { while ((nbrp = LIST_FIRST(&conf->nbrp_list)) != NULL) {
if (ref && *ref == nbrp)
*ref = NULL;
LIST_REMOVE(nbrp, entry); LIST_REMOVE(nbrp, entry);
free(nbrp); free(nbrp);
} }
conf->rtr_id.s_addr = INADDR_ANY; conf->rtr_id.s_addr = INADDR_ANY;
ldp_config_reset_af(conf, AF_INET); ldp_config_reset_af(conf, AF_INET, ref);
ldp_config_reset_af(conf, AF_INET6); ldp_config_reset_af(conf, AF_INET6, ref);
conf->lhello_holdtime = LINK_DFLT_HOLDTIME; conf->lhello_holdtime = LINK_DFLT_HOLDTIME;
conf->lhello_interval = DEFAULT_HELLO_INTERVAL; conf->lhello_interval = DEFAULT_HELLO_INTERVAL;
conf->thello_holdtime = TARGETED_DFLT_HOLDTIME; conf->thello_holdtime = TARGETED_DFLT_HOLDTIME;
@ -957,7 +968,7 @@ ldp_config_reset_main(struct ldpd_conf *conf)
} }
static void 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 ldpd_af_conf *af_conf;
struct iface *iface; struct iface *iface;
@ -973,6 +984,8 @@ ldp_config_reset_af(struct ldpd_conf *conf, int af)
if (tnbr->af != af) if (tnbr->af != af)
continue; continue;
if (ref && *ref == tnbr)
*ref = NULL;
LIST_REMOVE(tnbr, entry); LIST_REMOVE(tnbr, entry);
free(tnbr); free(tnbr);
} }
@ -988,7 +1001,7 @@ ldp_config_reset_af(struct ldpd_conf *conf, int af)
} }
struct ldpd_conf * 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 ldpd_conf *xconf;
struct iface *iface, *xi; struct iface *iface, *xi;
@ -998,75 +1011,68 @@ ldp_dup_config(struct ldpd_conf *conf)
struct l2vpn_if *lif, *xf; struct l2vpn_if *lif, *xf;
struct l2vpn_pw *pw, *xp; struct l2vpn_pw *pw, *xp;
xconf = malloc(sizeof(*xconf)); #define COPY(a, b) do { \
*xconf = *conf; 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->iface_list);
LIST_INIT(&xconf->tnbr_list); LIST_INIT(&xconf->tnbr_list);
LIST_INIT(&xconf->nbrp_list); LIST_INIT(&xconf->nbrp_list);
LIST_INIT(&xconf->l2vpn_list); LIST_INIT(&xconf->l2vpn_list);
LIST_FOREACH(iface, &conf->iface_list, entry) { LIST_FOREACH(iface, &conf->iface_list, entry) {
xi = calloc(1, sizeof(*xi)); COPY(xi, iface);
if (xi == NULL)
fatal(__func__);
*xi = *iface;
xi->ipv4.iface = xi; xi->ipv4.iface = xi;
xi->ipv6.iface = xi; xi->ipv6.iface = xi;
LIST_INSERT_HEAD(&xconf->iface_list, xi, entry); LIST_INSERT_HEAD(&xconf->iface_list, xi, entry);
} }
LIST_FOREACH(tnbr, &conf->tnbr_list, entry) { LIST_FOREACH(tnbr, &conf->tnbr_list, entry) {
xt = calloc(1, sizeof(*xt)); COPY(xt, tnbr);
if (xt == NULL)
fatal(__func__);
*xt = *tnbr;
LIST_INSERT_HEAD(&xconf->tnbr_list, xt, entry); LIST_INSERT_HEAD(&xconf->tnbr_list, xt, entry);
} }
LIST_FOREACH(nbrp, &conf->nbrp_list, entry) { LIST_FOREACH(nbrp, &conf->nbrp_list, entry) {
xn = calloc(1, sizeof(*xn)); COPY(xn, nbrp);
if (xn == NULL)
fatal(__func__);
*xn = *nbrp;
LIST_INSERT_HEAD(&xconf->nbrp_list, xn, entry); LIST_INSERT_HEAD(&xconf->nbrp_list, xn, entry);
} }
LIST_FOREACH(l2vpn, &conf->l2vpn_list, entry) { LIST_FOREACH(l2vpn, &conf->l2vpn_list, entry) {
xl = calloc(1, sizeof(*xl)); COPY(xl, l2vpn);
if (xl == NULL)
fatal(__func__);
*xl = *l2vpn;
LIST_INIT(&xl->if_list); LIST_INIT(&xl->if_list);
LIST_INIT(&xl->pw_list); LIST_INIT(&xl->pw_list);
LIST_INIT(&xl->pw_inactive_list); LIST_INIT(&xl->pw_inactive_list);
LIST_INSERT_HEAD(&xconf->l2vpn_list, xl, entry); LIST_INSERT_HEAD(&xconf->l2vpn_list, xl, entry);
LIST_FOREACH(lif, &l2vpn->if_list, entry) { LIST_FOREACH(lif, &l2vpn->if_list, entry) {
xf = calloc(1, sizeof(*xf)); COPY(xf, lif);
if (xf == NULL)
fatal(__func__);
*xf = *lif;
xf->l2vpn = xl; xf->l2vpn = xl;
LIST_INSERT_HEAD(&xl->if_list, xf, entry); LIST_INSERT_HEAD(&xl->if_list, xf, entry);
} }
LIST_FOREACH(pw, &l2vpn->pw_list, entry) { LIST_FOREACH(pw, &l2vpn->pw_list, entry) {
xp = calloc(1, sizeof(*xp)); COPY(xp, pw);
if (xp == NULL)
fatal(__func__);
*xp = *pw;
xp->l2vpn = xl; xp->l2vpn = xl;
LIST_INSERT_HEAD(&xl->pw_list, xp, entry); LIST_INSERT_HEAD(&xl->pw_list, xp, entry);
} }
LIST_FOREACH(pw, &l2vpn->pw_inactive_list, entry) { LIST_FOREACH(pw, &l2vpn->pw_inactive_list, entry) {
xp = calloc(1, sizeof(*xp)); COPY(xp, pw);
if (xp == NULL)
fatal(__func__);
*xp = *pw;
xp->l2vpn = xl; xp->l2vpn = xl;
LIST_INSERT_HEAD(&xl->pw_inactive_list, xp, entry); LIST_INSERT_HEAD(&xl->pw_inactive_list, xp, entry);
} }
} }
#undef COPY
return (xconf); return (xconf);
} }
struct ldpd_conf *
ldp_dup_config(struct ldpd_conf *conf)
{
return ldp_dup_config_ref(conf, NULL);
}
void void
ldp_clear_config(struct ldpd_conf *xconf) ldp_clear_config(struct ldpd_conf *xconf)
{ {
@ -1095,19 +1101,27 @@ ldp_clear_config(struct ldpd_conf *xconf)
free(xconf); free(xconf);
} }
void static void
merge_config(struct ldpd_conf *conf, struct ldpd_conf *xconf) merge_config_ref(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref)
{ {
merge_global(conf, xconf); merge_global(conf, xconf);
merge_af(AF_INET, &conf->ipv4, &xconf->ipv4); merge_af(AF_INET, &conf->ipv4, &xconf->ipv4);
merge_af(AF_INET6, &conf->ipv6, &xconf->ipv6); merge_af(AF_INET6, &conf->ipv6, &xconf->ipv6);
merge_ifaces(conf, xconf); merge_ifaces(conf, xconf, ref);
merge_tnbrs(conf, xconf); merge_tnbrs(conf, xconf, ref);
merge_nbrps(conf, xconf); merge_nbrps(conf, xconf, ref);
merge_l2vpns(conf, xconf); merge_l2vpns(conf, xconf, ref);
if (ref && *ref == xconf)
*ref = conf;
free(xconf); free(xconf);
} }
void
merge_config(struct ldpd_conf *conf, struct ldpd_conf *xconf)
{
merge_config_ref(conf, xconf, NULL);
}
static void static void
merge_global(struct ldpd_conf *conf, struct ldpd_conf *xconf) 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 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; 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->ipv4, &xi->ipv4);
merge_iface_af(&iface->ipv6, &xi->ipv6); merge_iface_af(&iface->ipv6, &xi->ipv6);
LIST_REMOVE(xi, entry); LIST_REMOVE(xi, entry);
if (ref && *ref == xi)
*ref = iface;
free(xi); free(xi);
} }
} }
@ -1252,7 +1268,7 @@ merge_iface_af(struct iface_af *ia, struct iface_af *xi)
} }
static void 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; 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)) if (!(tnbr->flags & F_TNBR_CONFIGURED))
tnbr->flags |= F_TNBR_CONFIGURED; tnbr->flags |= F_TNBR_CONFIGURED;
LIST_REMOVE(xt, entry); LIST_REMOVE(xt, entry);
if (ref && *ref == xt)
*ref = tnbr;
free(xt); free(xt);
} }
} }
static void 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_params *nbrp, *ntmp, *xn;
struct nbr *nbr; struct nbr *nbr;
@ -1385,12 +1403,14 @@ merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf)
} }
} }
LIST_REMOVE(xn, entry); LIST_REMOVE(xn, entry);
if (ref && *ref == xn)
*ref = nbrp;
free(xn); free(xn);
} }
} }
static void 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; struct l2vpn *l2vpn, *ltmp, *xl;
@ -1432,14 +1452,16 @@ merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf)
} }
/* update existing l2vpns */ /* update existing l2vpns */
merge_l2vpn(conf, l2vpn, xl); merge_l2vpn(conf, l2vpn, xl, ref);
LIST_REMOVE(xl, entry); LIST_REMOVE(xl, entry);
if (ref && *ref == xl)
*ref = l2vpn;
free(xl); free(xl);
} }
} }
static void 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_if *lif, *ftmp, *xf;
struct l2vpn_pw *pw, *ptmp, *xp; 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); LIST_REMOVE(xf, entry);
if (ref && *ref == xf)
*ref = lif;
free(xf); free(xf);
} }
@ -1597,6 +1621,8 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl)
} }
LIST_REMOVE(xp, entry); LIST_REMOVE(xp, entry);
if (ref && *ref == xp)
*ref = pw;
free(xp); free(xp);
} }
@ -1645,6 +1671,8 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl)
} }
LIST_REMOVE(xp, entry); LIST_REMOVE(xp, entry);
if (ref && *ref == xp)
*ref = pw;
free(xp); free(xp);
} }

View File

@ -602,6 +602,8 @@ struct ldpd_af_global *ldp_af_global_get(struct ldpd_global *, int);
int ldp_is_dual_stack(struct ldpd_conf *); int ldp_is_dual_stack(struct ldpd_conf *);
in_addr_t ldp_rtr_id_get(struct ldpd_conf *); in_addr_t ldp_rtr_id_get(struct ldpd_conf *);
int ldp_reload(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 *); struct ldpd_conf *ldp_dup_config(struct ldpd_conf *);
void ldp_clear_config(struct ldpd_conf *); void ldp_clear_config(struct ldpd_conf *);
void merge_config(struct ldpd_conf *, struct ldpd_conf *); void merge_config(struct ldpd_conf *, struct ldpd_conf *);