#include "zclient.h"
#include "stream.h"
#include "network.h"
+#include "libfrr.h"
static void lde_shutdown(void);
static int lde_dispatch_imsg(struct thread *);
static int lde_dispatch_parent(struct thread *);
-static __inline int lde_nbr_compare(struct lde_nbr *,
- struct lde_nbr *);
+static __inline int lde_nbr_compare(const struct lde_nbr *,
+ const struct lde_nbr *);
static struct lde_nbr *lde_nbr_new(uint32_t, struct lde_nbr *);
static void lde_nbr_del(struct lde_nbr *);
static struct lde_nbr *lde_nbr_find(uint32_t);
static void lde_nbr_clear(void);
static void lde_nbr_addr_update(struct lde_nbr *,
struct lde_addr *, int);
-static __inline int lde_map_compare(struct lde_map *, struct lde_map *);
+static __inline int lde_map_compare(const struct lde_map *,
+ const struct lde_map *);
static void lde_map_free(void *);
static int lde_address_add(struct lde_nbr *, struct lde_addr *);
static int lde_address_del(struct lde_nbr *, struct lde_addr *);
static void lde_address_list_free(struct lde_nbr *);
-static void zclient_sync_init (u_short instance);
+static void zclient_sync_init(u_short instance);
static void lde_label_list_init(void);
-static int lde_get_label_chunk (void);
+static int lde_get_label_chunk(void);
static void on_get_label_chunk_response(uint32_t start, uint32_t end);
static uint32_t lde_get_next_label(void);
static struct zebra_privs_t lde_privs =
{
-#if defined(FRR_USER) && defined(FRR_GROUP)
- .user = FRR_USER,
- .group = FRR_GROUP,
-#endif
#if defined(VTY_GROUP)
.vty_group = VTY_GROUP,
#endif
};
/* List of chunks of labels externally assigned by Zebra */
-struct list *label_chunk_list;
-struct listnode *current_label_chunk;
+static struct list *label_chunk_list;
+static struct listnode *current_label_chunk;
+
+/* Synchronous zclient to request labels */
+static struct zclient *zclient_sync;
/* SIGINT / SIGTERM handler. */
static void
},
};
-struct zclient *zclient_sync = NULL;
-static void
-zclient_sync_init(u_short instance)
-{
- /* Initialize special zclient for synchronous message exchanges. */
- log_debug("Initializing synchronous zclient for label manager");
- zclient_sync = zclient_new(master);
- zclient_sync->sock = -1;
- zclient_sync->redist_default = ZEBRA_ROUTE_LDP;
- zclient_sync->instance = instance;
- while (zclient_socket_connect (zclient_sync) < 0) {
- log_warnx("Error connecting synchronous zclient!");
- sleep(1);
- }
- /* make socket non-blocking */
- sock_set_nonblock(zclient_sync->sock);
-
- /* Connect to label manager */
- while (lm_label_manager_connect (zclient_sync) != 0) {
- log_warnx("Error connecting to label manager!");
- sleep(1);
- }
-}
-
/* label decision engine */
void
lde(void)
ldpd_process = PROC_LDE_ENGINE;
log_procname = log_procnames[PROC_LDE_ENGINE];
- master = thread_master_create();
+ master = thread_master_create(NULL);
/* setup signal handler */
signal_init(master, array_size(lde_signals), lde_signals);
fatal(NULL);
imsg_init(&iev_main->ibuf, LDPD_FD_ASYNC);
iev_main->handler_read = lde_dispatch_parent;
- iev_main->ev_read = thread_add_read(master, iev_main->handler_read,
- iev_main, iev_main->ibuf.fd);
+ iev_main->ev_read = NULL;
+ thread_add_read(master, iev_main->handler_read, iev_main, iev_main->ibuf.fd,
+ &iev_main->ev_read);
iev_main->handler_write = ldp_write_handler;
if ((iev_main_sync = calloc(1, sizeof(struct imsgev))) == NULL)
lde_init(struct ldpd_init *init)
{
/* drop privileges */
- if (init->user)
- lde_privs.user = init->user;
- if (init->group)
- lde_privs.group = init->group;
+ lde_privs.user = init->user;
+ lde_privs.group = init->group;
zprivs_init(&lde_privs);
-#ifdef HAVE_PLEDGE
- if (pledge("stdio recvfd unix", NULL) == -1)
- fatal("pledge");
-#endif
-
/* start the LIB garbage collector */
lde_gc_start_timer();
/* Init synchronous zclient and label list */
- zclient_serv_path_set(init->zclient_serv_path);
+ frr_zclient_addr(&zclient_addr, &zclient_addr_len,
+ init->zclient_serv_path);
zclient_sync_init(init->instance);
lde_label_list_init();
}
fatal(NULL);
imsg_init(&iev_ldpe->ibuf, fd);
iev_ldpe->handler_read = lde_dispatch_imsg;
- iev_ldpe->ev_read = thread_add_read(master,
- iev_ldpe->handler_read, iev_ldpe, iev_ldpe->ibuf.fd);
+ iev_ldpe->ev_read = NULL;
+ thread_add_read(master, iev_ldpe->handler_read, iev_ldpe, iev_ldpe->ibuf.fd,
+ &iev_ldpe->ev_read);
iev_ldpe->handler_write = ldp_write_handler;
iev_ldpe->ev_write = NULL;
break;
fatal(NULL);
memcpy(nconf, imsg.data, sizeof(struct ldpd_conf));
- RB_INIT(&nconf->iface_tree);
- RB_INIT(&nconf->tnbr_tree);
- RB_INIT(&nconf->nbrp_tree);
- RB_INIT(&nconf->l2vpn_tree);
+ RB_INIT(iface_head, &nconf->iface_tree);
+ RB_INIT(tnbr_head, &nconf->tnbr_tree);
+ RB_INIT(nbrp_head, &nconf->nbrp_tree);
+ RB_INIT(l2vpn_head, &nconf->l2vpn_tree);
break;
case IMSG_RECONF_IFACE:
if ((niface = malloc(sizeof(struct iface))) == NULL)
fatal(NULL);
memcpy(nl2vpn, imsg.data, sizeof(struct l2vpn));
- RB_INIT(&nl2vpn->if_tree);
- RB_INIT(&nl2vpn->pw_tree);
- RB_INIT(&nl2vpn->pw_inactive_tree);
+ RB_INIT(l2vpn_if_head, &nl2vpn->if_tree);
+ RB_INIT(l2vpn_pw_head, &nl2vpn->pw_tree);
+ RB_INIT(l2vpn_pw_head, &nl2vpn->pw_inactive_tree);
RB_INSERT(l2vpn_head, &nconf->l2vpn_tree, nl2vpn);
break;
fn->local_label > MPLS_LABEL_RESERVED_MAX)
return (fn->local_label);
- return lde_get_next_label ();
+ return (lde_get_next_label());
}
void
void
lde_send_labelmapping(struct lde_nbr *ln, struct fec_node *fn, int single)
{
- struct lde_req *lre;
- struct lde_map *me;
- struct map map;
- struct l2vpn_pw *pw;
+ struct lde_wdraw *lw;
+ struct lde_map *me;
+ struct lde_req *lre;
+ struct map map;
+ struct l2vpn_pw *pw;
+
+ /*
+ * We shouldn't send a new label mapping if we have a pending
+ * label release to receive. In this case, schedule to send a
+ * label mapping as soon as a label release is received.
+ */
+ lw = (struct lde_wdraw *)fec_find(&ln->sent_wdraw, &fn->fec);
+ if (lw) {
+ if (!fec_find(&ln->sent_map_pending, &fn->fec))
+ lde_map_pending_add(ln, fn);
+ return;
+ }
/*
* This function skips SL.1 - 3 and SL.9 - 14 because the label
}
static __inline int
-lde_nbr_compare(struct lde_nbr *a, struct lde_nbr *b)
+lde_nbr_compare(const struct lde_nbr *a, const struct lde_nbr *b)
{
return (a->peerid - b->peerid);
}
ln->peerid = peerid;
fec_init(&ln->recv_map);
fec_init(&ln->sent_map);
+ fec_init(&ln->sent_map_pending);
fec_init(&ln->recv_req);
fec_init(&ln->sent_req);
fec_init(&ln->sent_wdraw);
fec_clear(&ln->recv_map, lde_map_free);
fec_clear(&ln->sent_map, lde_map_free);
+ fec_clear(&ln->sent_map_pending, free);
fec_clear(&ln->recv_req, free);
fec_clear(&ln->sent_req, free);
fec_clear(&ln->sent_wdraw, free);
{
struct lde_nbr *ln;
- while ((ln = RB_ROOT(&lde_nbrs)) != NULL)
+ while ((ln = RB_ROOT(nbr_tree, &lde_nbrs)) != NULL)
lde_nbr_del(ln);
}
struct lde_map *me;
RB_FOREACH(fec, fec_tree, &ln->recv_map) {
- fn = (struct fec_node *)fec_find(&ft, fec);
switch (fec->type) {
case FEC_TYPE_IPV4:
if (lde_addr->af != AF_INET)
continue;
}
+ fn = (struct fec_node *)fec_find(&ft, fec);
+ if (fn == NULL)
+ /* shouldn't happen */
+ continue;
+
LIST_FOREACH(fnh, &fn->nexthops, entry) {
if (ldp_addrcmp(fnh->af, &fnh->nexthop,
&lde_addr->addr))
}
static __inline int
-lde_map_compare(struct lde_map *a, struct lde_map *b)
+lde_map_compare(const struct lde_map *a, const struct lde_map *b)
{
return (ldp_addrcmp(AF_INET, (union ldpd_addr *)&a->nexthop->id,
(union ldpd_addr *)&b->nexthop->id));
free(map);
}
+struct fec *
+lde_map_pending_add(struct lde_nbr *ln, struct fec_node *fn)
+{
+ struct fec *map;
+
+ map = calloc(1, sizeof(*map));
+ if (map == NULL)
+ fatal(__func__);
+
+ *map = fn->fec;
+ if (fec_insert(&ln->sent_map_pending, map))
+ log_warnx("failed to add %s to sent map (pending)",
+ log_fec(map));
+
+ return (map);
+}
+
+void
+lde_map_pending_del(struct lde_nbr *ln, struct fec *map)
+{
+ fec_remove(&ln->sent_map_pending, map);
+ free(map);
+}
+
struct lde_req *
lde_req_add(struct lde_nbr *ln, struct fec *fec, int sent)
{
}
}
+static void
+zclient_sync_init(u_short instance)
+{
+ /* Initialize special zclient for synchronous message exchanges. */
+ log_debug("Initializing synchronous zclient for label manager");
+ zclient_sync = zclient_new(master);
+ zclient_sync->sock = -1;
+ zclient_sync->redist_default = ZEBRA_ROUTE_LDP;
+ zclient_sync->instance = instance;
+ while (zclient_socket_connect(zclient_sync) < 0) {
+ log_warnx("Error connecting synchronous zclient!");
+ sleep(1);
+ }
+ /* make socket non-blocking */
+ sock_set_nonblock(zclient_sync->sock);
+
+ /* Connect to label manager */
+ while (lm_label_manager_connect(zclient_sync) != 0) {
+ log_warnx("Error connecting to label manager!");
+ sleep(1);
+ }
+}
+
static void
lde_del_label_chunk(void *val)
{
free(val);
}
+
static int
lde_get_label_chunk(void)
{
- int ret;
- uint32_t start, end;
+ int ret;
+ uint32_t start, end;
log_debug("Getting label chunk");
ret = lm_get_label_chunk(zclient_sync, 0, CHUNK_SIZE, &start, &end);
- if (ret < 0)
- {
+ if (ret < 0) {
log_warnx("Error getting label chunk!");
return -1;
}
on_get_label_chunk_response(start, end);
- return 0;
+ return (0);
}
+
static void
lde_label_list_init(void)
{
static uint32_t
lde_get_next_label(void)
{
- struct label_chunk *label_chunk;
- uint32_t i, pos, size;
- uint32_t label = NO_LABEL;
+ struct label_chunk *label_chunk;
+ uint32_t i, pos, size;
+ uint32_t label = NO_LABEL;
while (current_label_chunk) {
label_chunk = listgetdata(current_label_chunk);
end:
/* we moved till the last chunk, or were not able to find a label,
so let's ask for another one */
- if (!current_label_chunk || current_label_chunk == listtail(label_chunk_list)
- || label == NO_LABEL) {
+ if (!current_label_chunk ||
+ current_label_chunk == listtail(label_chunk_list) ||
+ label == NO_LABEL) {
if (lde_get_label_chunk() != 0)
log_warn("%s: Error getting label chunk!", __func__);
}
- return label;
+ return (label);
}