4 * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
5 * Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org>
6 * Copyright (c) 2004 Esben Norby <norby@openbsd.org>
7 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
29 #include "ldp_debug.h"
36 #include <lib/linklist.h>
41 static void lde_shutdown(void);
42 static int lde_dispatch_imsg(struct thread
*);
43 static int lde_dispatch_parent(struct thread
*);
44 static __inline
int lde_nbr_compare(struct lde_nbr
*,
46 static struct lde_nbr
*lde_nbr_new(uint32_t, struct lde_nbr
*);
47 static void lde_nbr_del(struct lde_nbr
*);
48 static struct lde_nbr
*lde_nbr_find(uint32_t);
49 static void lde_nbr_clear(void);
50 static void lde_nbr_addr_update(struct lde_nbr
*,
51 struct lde_addr
*, int);
52 static __inline
int lde_map_compare(struct lde_map
*, struct lde_map
*);
53 static void lde_map_free(void *);
54 static int lde_address_add(struct lde_nbr
*, struct lde_addr
*);
55 static int lde_address_del(struct lde_nbr
*, struct lde_addr
*);
56 static void lde_address_list_free(struct lde_nbr
*);
57 static void zclient_sync_init(u_short instance
);
58 static void lde_label_list_init(void);
59 static int lde_get_label_chunk(void);
60 static void on_get_label_chunk_response(uint32_t start
, uint32_t end
);
61 static uint32_t lde_get_next_label(void);
63 RB_GENERATE(nbr_tree
, lde_nbr
, entry
, lde_nbr_compare
)
64 RB_GENERATE(lde_map_head
, lde_map
, entry
, lde_map_compare
)
66 struct ldpd_conf
*ldeconf
;
67 struct nbr_tree lde_nbrs
= RB_INITIALIZER(&lde_nbrs
);
69 static struct imsgev
*iev_ldpe
;
70 static struct imsgev
*iev_main
, *iev_main_sync
;
72 /* Master of threads. */
73 struct thread_master
*master
;
76 static zebra_capabilities_t _caps_p
[] =
81 static struct zebra_privs_t lde_privs
=
83 #if defined(VTY_GROUP)
84 .vty_group
= VTY_GROUP
,
87 .cap_num_p
= array_size(_caps_p
),
91 /* List of chunks of labels externally assigned by Zebra */
92 static struct list
*label_chunk_list
;
93 static struct listnode
*current_label_chunk
;
95 /* Synchronous zclient to request labels */
96 static struct zclient
*zclient_sync
;
98 /* SIGINT / SIGTERM handler. */
105 static struct quagga_signal_t lde_signals
[] =
121 /* label decision engine */
125 struct thread thread
;
127 #ifdef HAVE_SETPROCTITLE
128 setproctitle("label decision engine");
130 ldpd_process
= PROC_LDE_ENGINE
;
131 log_procname
= log_procnames
[PROC_LDE_ENGINE
];
133 master
= thread_master_create();
135 /* setup signal handler */
136 signal_init(master
, array_size(lde_signals
), lde_signals
);
138 /* setup pipes and event handlers to the parent process */
139 if ((iev_main
= calloc(1, sizeof(struct imsgev
))) == NULL
)
141 imsg_init(&iev_main
->ibuf
, LDPD_FD_ASYNC
);
142 iev_main
->handler_read
= lde_dispatch_parent
;
143 iev_main
->ev_read
= NULL
;
144 thread_add_read(master
, iev_main
->handler_read
, iev_main
, iev_main
->ibuf
.fd
,
146 iev_main
->handler_write
= ldp_write_handler
;
148 if ((iev_main_sync
= calloc(1, sizeof(struct imsgev
))) == NULL
)
150 imsg_init(&iev_main_sync
->ibuf
, LDPD_FD_SYNC
);
152 /* create base configuration */
153 ldeconf
= config_new_empty();
155 /* Fetch next active thread. */
156 while (thread_fetch(master
, &thread
))
157 thread_call(&thread
);
161 lde_init(struct ldpd_init
*init
)
163 /* drop privileges */
164 lde_privs
.user
= init
->user
;
165 lde_privs
.group
= init
->group
;
166 zprivs_init(&lde_privs
);
169 if (pledge("stdio recvfd unix", NULL
) == -1)
173 /* start the LIB garbage collector */
174 lde_gc_start_timer();
176 /* Init synchronous zclient and label list */
177 zclient_serv_path_set(init
->zclient_serv_path
);
178 zclient_sync_init(init
->instance
);
179 lde_label_list_init();
187 msgbuf_clear(&iev_ldpe
->ibuf
.w
);
188 close(iev_ldpe
->ibuf
.fd
);
190 msgbuf_clear(&iev_main
->ibuf
.w
);
191 close(iev_main
->ibuf
.fd
);
192 msgbuf_clear(&iev_main_sync
->ibuf
.w
);
193 close(iev_main_sync
->ibuf
.fd
);
199 config_clear(ldeconf
);
206 log_info("label decision engine exiting");
212 lde_imsg_compose_parent(int type
, pid_t pid
, void *data
, uint16_t datalen
)
214 return (imsg_compose_event(iev_main
, type
, 0, pid
, -1, data
, datalen
));
218 lde_imsg_compose_parent_sync(int type
, pid_t pid
, void *data
, uint16_t datalen
)
220 imsg_compose_event(iev_main_sync
, type
, 0, pid
, -1, data
, datalen
);
221 imsg_flush(&iev_main_sync
->ibuf
);
225 lde_imsg_compose_ldpe(int type
, uint32_t peerid
, pid_t pid
, void *data
,
228 return (imsg_compose_event(iev_ldpe
, type
, peerid
, pid
,
234 lde_dispatch_imsg(struct thread
*thread
)
236 struct imsgev
*iev
= THREAD_ARG(thread
);
237 struct imsgbuf
*ibuf
= &iev
->ibuf
;
241 struct lde_addr
*lde_addr
;
242 struct notify_msg
*nm
;
248 if ((n
= imsg_read(ibuf
)) == -1 && errno
!= EAGAIN
)
249 fatal("imsg_read error");
250 if (n
== 0) /* connection closed */
254 if ((n
= imsg_get(ibuf
, &imsg
)) == -1)
255 fatal("lde_dispatch_imsg: imsg_get error");
259 switch (imsg
.hdr
.type
) {
260 case IMSG_LABEL_MAPPING_FULL
:
261 ln
= lde_nbr_find(imsg
.hdr
.peerid
);
263 log_debug("%s: cannot find lde neighbor",
270 case IMSG_LABEL_MAPPING
:
271 case IMSG_LABEL_REQUEST
:
272 case IMSG_LABEL_RELEASE
:
273 case IMSG_LABEL_WITHDRAW
:
274 case IMSG_LABEL_ABORT
:
275 if (imsg
.hdr
.len
- IMSG_HEADER_SIZE
!=
277 fatalx("lde_dispatch_imsg: wrong imsg len");
280 ln
= lde_nbr_find(imsg
.hdr
.peerid
);
282 log_debug("%s: cannot find lde neighbor",
287 switch (imsg
.hdr
.type
) {
288 case IMSG_LABEL_MAPPING
:
289 lde_check_mapping(map
, ln
);
291 case IMSG_LABEL_REQUEST
:
292 lde_check_request(map
, ln
);
294 case IMSG_LABEL_RELEASE
:
295 lde_check_release(map
, ln
);
297 case IMSG_LABEL_WITHDRAW
:
298 lde_check_withdraw(map
, ln
);
300 case IMSG_LABEL_ABORT
:
305 case IMSG_ADDRESS_ADD
:
306 if (imsg
.hdr
.len
- IMSG_HEADER_SIZE
!=
307 sizeof(struct lde_addr
))
308 fatalx("lde_dispatch_imsg: wrong imsg len");
309 lde_addr
= imsg
.data
;
311 ln
= lde_nbr_find(imsg
.hdr
.peerid
);
313 log_debug("%s: cannot find lde neighbor",
317 if (lde_address_add(ln
, lde_addr
) < 0) {
318 log_debug("%s: cannot add address %s, it "
319 "already exists", __func__
,
320 log_addr(lde_addr
->af
, &lde_addr
->addr
));
323 case IMSG_ADDRESS_DEL
:
324 if (imsg
.hdr
.len
- IMSG_HEADER_SIZE
!=
325 sizeof(struct lde_addr
))
326 fatalx("lde_dispatch_imsg: wrong imsg len");
327 lde_addr
= imsg
.data
;
329 ln
= lde_nbr_find(imsg
.hdr
.peerid
);
331 log_debug("%s: cannot find lde neighbor",
335 if (lde_address_del(ln
, lde_addr
) < 0) {
336 log_debug("%s: cannot delete address %s, it "
337 "does not exist", __func__
,
338 log_addr(lde_addr
->af
, &lde_addr
->addr
));
341 case IMSG_NOTIFICATION
:
342 if (imsg
.hdr
.len
- IMSG_HEADER_SIZE
!=
343 sizeof(struct notify_msg
))
344 fatalx("lde_dispatch_imsg: wrong imsg len");
347 ln
= lde_nbr_find(imsg
.hdr
.peerid
);
349 log_debug("%s: cannot find lde neighbor",
354 switch (nm
->status_code
) {
356 l2vpn_recv_pw_status(ln
, nm
);
360 * Do nothing for now. Should be useful in
361 * the future when we implement LDP-IGP
362 * Synchronization (RFC 5443) and Graceful
363 * Restart (RFC 3478).
369 case IMSG_NEIGHBOR_UP
:
370 if (imsg
.hdr
.len
- IMSG_HEADER_SIZE
!=
371 sizeof(struct lde_nbr
))
372 fatalx("lde_dispatch_imsg: wrong imsg len");
374 if (lde_nbr_find(imsg
.hdr
.peerid
))
375 fatalx("lde_dispatch_imsg: "
376 "neighbor already exists");
377 lde_nbr_new(imsg
.hdr
.peerid
, imsg
.data
);
379 case IMSG_NEIGHBOR_DOWN
:
380 lde_nbr_del(lde_nbr_find(imsg
.hdr
.peerid
));
382 case IMSG_CTL_SHOW_LIB
:
383 rt_dump(imsg
.hdr
.pid
);
385 lde_imsg_compose_ldpe(IMSG_CTL_END
, 0,
386 imsg
.hdr
.pid
, NULL
, 0);
388 case IMSG_CTL_SHOW_L2VPN_PW
:
389 l2vpn_pw_ctl(imsg
.hdr
.pid
);
391 lde_imsg_compose_ldpe(IMSG_CTL_END
, 0,
392 imsg
.hdr
.pid
, NULL
, 0);
394 case IMSG_CTL_SHOW_L2VPN_BINDING
:
395 l2vpn_binding_ctl(imsg
.hdr
.pid
);
397 lde_imsg_compose_ldpe(IMSG_CTL_END
, 0,
398 imsg
.hdr
.pid
, NULL
, 0);
401 log_debug("%s: unexpected imsg %d", __func__
,
410 /* this pipe is dead, so remove the event handlers and exit */
411 THREAD_READ_OFF(iev
->ev_read
);
412 THREAD_WRITE_OFF(iev
->ev_write
);
421 lde_dispatch_parent(struct thread
*thread
)
423 static struct ldpd_conf
*nconf
;
424 struct iface
*iface
, *niface
;
426 struct nbr_params
*nnbrp
;
427 static struct l2vpn
*l2vpn
, *nl2vpn
;
428 struct l2vpn_if
*lif
, *nlif
;
429 struct l2vpn_pw
*pw
, *npw
;
433 int fd
= THREAD_FD(thread
);
434 struct imsgev
*iev
= THREAD_ARG(thread
);
435 struct imsgbuf
*ibuf
= &iev
->ibuf
;
442 if ((n
= imsg_read(ibuf
)) == -1 && errno
!= EAGAIN
)
443 fatal("imsg_read error");
444 if (n
== 0) /* connection closed */
448 if ((n
= imsg_get(ibuf
, &imsg
)) == -1)
449 fatal("lde_dispatch_parent: imsg_get error");
453 switch (imsg
.hdr
.type
) {
455 if (imsg
.hdr
.len
!= IMSG_HEADER_SIZE
+
457 fatalx("IFSTATUS imsg with wrong len");
460 iface
= if_lookup_name(ldeconf
, kif
->ifname
);
462 if_update_info(iface
, kif
);
466 RB_FOREACH(l2vpn
, l2vpn_head
, &ldeconf
->l2vpn_tree
) {
467 lif
= l2vpn_if_find(l2vpn
, kif
->ifname
);
469 l2vpn_if_update_info(lif
, kif
);
472 pw
= l2vpn_pw_find(l2vpn
, kif
->ifname
);
474 l2vpn_pw_update_info(pw
, kif
);
479 case IMSG_NETWORK_ADD
:
480 case IMSG_NETWORK_UPDATE
:
481 if (imsg
.hdr
.len
!= IMSG_HEADER_SIZE
+
482 sizeof(struct kroute
)) {
483 log_warnx("%s: wrong imsg len", __func__
);
490 fec
.type
= FEC_TYPE_IPV4
;
491 fec
.u
.ipv4
.prefix
= kr
->prefix
.v4
;
492 fec
.u
.ipv4
.prefixlen
= kr
->prefixlen
;
495 fec
.type
= FEC_TYPE_IPV6
;
496 fec
.u
.ipv6
.prefix
= kr
->prefix
.v6
;
497 fec
.u
.ipv6
.prefixlen
= kr
->prefixlen
;
500 fatalx("lde_dispatch_parent: unknown af");
503 switch (imsg
.hdr
.type
) {
504 case IMSG_NETWORK_ADD
:
505 lde_kernel_insert(&fec
, kr
->af
, &kr
->nexthop
,
506 kr
->ifindex
, kr
->priority
,
507 kr
->flags
& F_CONNECTED
, NULL
);
509 case IMSG_NETWORK_UPDATE
:
510 lde_kernel_update(&fec
);
514 case IMSG_SOCKET_IPC
:
516 log_warnx("%s: received unexpected imsg fd "
517 "to ldpe", __func__
);
520 if ((fd
= imsg
.fd
) == -1) {
521 log_warnx("%s: expected to receive imsg fd to "
522 "ldpe but didn't receive any", __func__
);
526 if ((iev_ldpe
= malloc(sizeof(struct imsgev
))) == NULL
)
528 imsg_init(&iev_ldpe
->ibuf
, fd
);
529 iev_ldpe
->handler_read
= lde_dispatch_imsg
;
530 iev_ldpe
->ev_read
= NULL
;
531 thread_add_read(master
, iev_ldpe
->handler_read
, iev_ldpe
, iev_ldpe
->ibuf
.fd
,
533 iev_ldpe
->handler_write
= ldp_write_handler
;
534 iev_ldpe
->ev_write
= NULL
;
537 if (imsg
.hdr
.len
!= IMSG_HEADER_SIZE
+
538 sizeof(struct ldpd_init
))
539 fatalx("INIT imsg with wrong len");
541 memcpy(&init
, imsg
.data
, sizeof(init
));
544 case IMSG_RECONF_CONF
:
545 if ((nconf
= malloc(sizeof(struct ldpd_conf
))) ==
548 memcpy(nconf
, imsg
.data
, sizeof(struct ldpd_conf
));
550 RB_INIT(&nconf
->iface_tree
);
551 RB_INIT(&nconf
->tnbr_tree
);
552 RB_INIT(&nconf
->nbrp_tree
);
553 RB_INIT(&nconf
->l2vpn_tree
);
555 case IMSG_RECONF_IFACE
:
556 if ((niface
= malloc(sizeof(struct iface
))) == NULL
)
558 memcpy(niface
, imsg
.data
, sizeof(struct iface
));
560 RB_INSERT(iface_head
, &nconf
->iface_tree
, niface
);
562 case IMSG_RECONF_TNBR
:
563 if ((ntnbr
= malloc(sizeof(struct tnbr
))) == NULL
)
565 memcpy(ntnbr
, imsg
.data
, sizeof(struct tnbr
));
567 RB_INSERT(tnbr_head
, &nconf
->tnbr_tree
, ntnbr
);
569 case IMSG_RECONF_NBRP
:
570 if ((nnbrp
= malloc(sizeof(struct nbr_params
))) == NULL
)
572 memcpy(nnbrp
, imsg
.data
, sizeof(struct nbr_params
));
574 RB_INSERT(nbrp_head
, &nconf
->nbrp_tree
, nnbrp
);
576 case IMSG_RECONF_L2VPN
:
577 if ((nl2vpn
= malloc(sizeof(struct l2vpn
))) == NULL
)
579 memcpy(nl2vpn
, imsg
.data
, sizeof(struct l2vpn
));
581 RB_INIT(&nl2vpn
->if_tree
);
582 RB_INIT(&nl2vpn
->pw_tree
);
583 RB_INIT(&nl2vpn
->pw_inactive_tree
);
585 RB_INSERT(l2vpn_head
, &nconf
->l2vpn_tree
, nl2vpn
);
587 case IMSG_RECONF_L2VPN_IF
:
588 if ((nlif
= malloc(sizeof(struct l2vpn_if
))) == NULL
)
590 memcpy(nlif
, imsg
.data
, sizeof(struct l2vpn_if
));
592 RB_INSERT(l2vpn_if_head
, &nl2vpn
->if_tree
, nlif
);
594 case IMSG_RECONF_L2VPN_PW
:
595 if ((npw
= malloc(sizeof(struct l2vpn_pw
))) == NULL
)
597 memcpy(npw
, imsg
.data
, sizeof(struct l2vpn_pw
));
599 RB_INSERT(l2vpn_pw_head
, &nl2vpn
->pw_tree
, npw
);
601 case IMSG_RECONF_L2VPN_IPW
:
602 if ((npw
= malloc(sizeof(struct l2vpn_pw
))) == NULL
)
604 memcpy(npw
, imsg
.data
, sizeof(struct l2vpn_pw
));
606 RB_INSERT(l2vpn_pw_head
, &nl2vpn
->pw_inactive_tree
, npw
);
608 case IMSG_RECONF_END
:
609 merge_config(ldeconf
, nconf
);
610 ldp_clear_config(nconf
);
613 case IMSG_DEBUG_UPDATE
:
614 if (imsg
.hdr
.len
!= IMSG_HEADER_SIZE
+
616 log_warnx("%s: wrong imsg len", __func__
);
619 memcpy(&ldp_debug
, imsg
.data
, sizeof(ldp_debug
));
622 log_debug("%s: unexpected imsg %d", __func__
,
631 /* this pipe is dead, so remove the event handlers and exit */
632 THREAD_READ_OFF(iev
->ev_read
);
633 THREAD_WRITE_OFF(iev
->ev_write
);
641 lde_acl_check(char *acl_name
, int af
, union ldpd_addr
*addr
, uint8_t prefixlen
)
643 return ldp_acl_request(iev_main_sync
, acl_name
, af
, addr
, prefixlen
);
647 lde_update_label(struct fec_node
*fn
)
652 LIST_FOREACH(fnh
, &fn
->nexthops
, entry
) {
653 if (fnh
->flags
& F_FEC_NH_CONNECTED
) {
659 /* should we allocate a label for this fec? */
660 switch (fn
->fec
.type
) {
662 if ((ldeconf
->ipv4
.flags
& F_LDPD_AF_ALLOCHOSTONLY
) &&
663 fn
->fec
.u
.ipv4
.prefixlen
!= 32)
665 if (lde_acl_check(ldeconf
->ipv4
.acl_label_allocate_for
,
666 AF_INET
, (union ldpd_addr
*)&fn
->fec
.u
.ipv4
.prefix
,
667 fn
->fec
.u
.ipv4
.prefixlen
) != FILTER_PERMIT
)
671 if ((ldeconf
->ipv6
.flags
& F_LDPD_AF_ALLOCHOSTONLY
) &&
672 fn
->fec
.u
.ipv6
.prefixlen
!= 128)
674 if (lde_acl_check(ldeconf
->ipv6
.acl_label_allocate_for
,
675 AF_INET6
, (union ldpd_addr
*)&fn
->fec
.u
.ipv6
.prefix
,
676 fn
->fec
.u
.ipv6
.prefixlen
) != FILTER_PERMIT
)
684 /* choose implicit or explicit-null depending on configuration */
685 switch (fn
->fec
.type
) {
687 if (!(ldeconf
->ipv4
.flags
& F_LDPD_AF_EXPNULL
))
688 return (MPLS_LABEL_IMPLNULL
);
689 if (lde_acl_check(ldeconf
->ipv4
.acl_label_expnull_for
,
690 AF_INET
, (union ldpd_addr
*)&fn
->fec
.u
.ipv4
.prefix
,
691 fn
->fec
.u
.ipv4
.prefixlen
) != FILTER_PERMIT
)
692 return (MPLS_LABEL_IMPLNULL
);
693 return (MPLS_LABEL_IPV4NULL
);
695 if (!(ldeconf
->ipv6
.flags
& F_LDPD_AF_EXPNULL
))
696 return (MPLS_LABEL_IMPLNULL
);
697 if (lde_acl_check(ldeconf
->ipv6
.acl_label_expnull_for
,
698 AF_INET6
, (union ldpd_addr
*)&fn
->fec
.u
.ipv6
.prefix
,
699 fn
->fec
.u
.ipv6
.prefixlen
) != FILTER_PERMIT
)
700 return (MPLS_LABEL_IMPLNULL
);
701 return (MPLS_LABEL_IPV6NULL
);
703 fatalx("lde_update_label: unexpected fec type");
708 /* preserve current label if there's no need to update it */
709 if (fn
->local_label
!= NO_LABEL
&&
710 fn
->local_label
> MPLS_LABEL_RESERVED_MAX
)
711 return (fn
->local_label
);
713 return (lde_get_next_label());
717 lde_send_change_klabel(struct fec_node
*fn
, struct fec_nh
*fnh
)
723 switch (fn
->fec
.type
) {
725 memset(&kr
, 0, sizeof(kr
));
727 kr
.prefix
.v4
= fn
->fec
.u
.ipv4
.prefix
;
728 kr
.prefixlen
= fn
->fec
.u
.ipv4
.prefixlen
;
729 kr
.nexthop
.v4
= fnh
->nexthop
.v4
;
730 kr
.ifindex
= fnh
->ifindex
;
731 kr
.local_label
= fn
->local_label
;
732 kr
.remote_label
= fnh
->remote_label
;
733 kr
.priority
= fnh
->priority
;
735 lde_imsg_compose_parent(IMSG_KLABEL_CHANGE
, 0, &kr
,
739 memset(&kr
, 0, sizeof(kr
));
741 kr
.prefix
.v6
= fn
->fec
.u
.ipv6
.prefix
;
742 kr
.prefixlen
= fn
->fec
.u
.ipv6
.prefixlen
;
743 kr
.nexthop
.v6
= fnh
->nexthop
.v6
;
744 kr
.ifindex
= fnh
->ifindex
;
745 kr
.local_label
= fn
->local_label
;
746 kr
.remote_label
= fnh
->remote_label
;
747 kr
.priority
= fnh
->priority
;
749 lde_imsg_compose_parent(IMSG_KLABEL_CHANGE
, 0, &kr
,
753 if (fn
->local_label
== NO_LABEL
||
754 fnh
->remote_label
== NO_LABEL
)
757 pw
= (struct l2vpn_pw
*) fn
->data
;
758 pw
->flags
|= F_PW_STATUS_UP
;
760 memset(&kpw
, 0, sizeof(kpw
));
761 kpw
.ifindex
= pw
->ifindex
;
762 kpw
.pw_type
= fn
->fec
.u
.pwid
.type
;
764 kpw
.nexthop
= pw
->addr
;
765 kpw
.local_label
= fn
->local_label
;
766 kpw
.remote_label
= fnh
->remote_label
;
767 kpw
.flags
= pw
->flags
;
769 lde_imsg_compose_parent(IMSG_KPWLABEL_CHANGE
, 0, &kpw
,
776 lde_send_delete_klabel(struct fec_node
*fn
, struct fec_nh
*fnh
)
782 switch (fn
->fec
.type
) {
784 memset(&kr
, 0, sizeof(kr
));
786 kr
.prefix
.v4
= fn
->fec
.u
.ipv4
.prefix
;
787 kr
.prefixlen
= fn
->fec
.u
.ipv4
.prefixlen
;
788 kr
.nexthop
.v4
= fnh
->nexthop
.v4
;
789 kr
.ifindex
= fnh
->ifindex
;
790 kr
.local_label
= fn
->local_label
;
791 kr
.remote_label
= fnh
->remote_label
;
792 kr
.priority
= fnh
->priority
;
794 lde_imsg_compose_parent(IMSG_KLABEL_DELETE
, 0, &kr
,
798 memset(&kr
, 0, sizeof(kr
));
800 kr
.prefix
.v6
= fn
->fec
.u
.ipv6
.prefix
;
801 kr
.prefixlen
= fn
->fec
.u
.ipv6
.prefixlen
;
802 kr
.nexthop
.v6
= fnh
->nexthop
.v6
;
803 kr
.ifindex
= fnh
->ifindex
;
804 kr
.local_label
= fn
->local_label
;
805 kr
.remote_label
= fnh
->remote_label
;
806 kr
.priority
= fnh
->priority
;
808 lde_imsg_compose_parent(IMSG_KLABEL_DELETE
, 0, &kr
,
812 pw
= (struct l2vpn_pw
*) fn
->data
;
813 if (!(pw
->flags
& F_PW_STATUS_UP
))
815 pw
->flags
&= ~F_PW_STATUS_UP
;
817 memset(&kpw
, 0, sizeof(kpw
));
818 kpw
.ifindex
= pw
->ifindex
;
819 kpw
.pw_type
= fn
->fec
.u
.pwid
.type
;
821 kpw
.nexthop
= pw
->addr
;
822 kpw
.local_label
= fn
->local_label
;
823 kpw
.remote_label
= fnh
->remote_label
;
824 kpw
.flags
= pw
->flags
;
826 lde_imsg_compose_parent(IMSG_KPWLABEL_DELETE
, 0, &kpw
,
833 lde_fec2map(struct fec
*fec
, struct map
*map
)
835 memset(map
, 0, sizeof(*map
));
839 map
->type
= MAP_TYPE_PREFIX
;
840 map
->fec
.prefix
.af
= AF_INET
;
841 map
->fec
.prefix
.prefix
.v4
= fec
->u
.ipv4
.prefix
;
842 map
->fec
.prefix
.prefixlen
= fec
->u
.ipv4
.prefixlen
;
845 map
->type
= MAP_TYPE_PREFIX
;
846 map
->fec
.prefix
.af
= AF_INET6
;
847 map
->fec
.prefix
.prefix
.v6
= fec
->u
.ipv6
.prefix
;
848 map
->fec
.prefix
.prefixlen
= fec
->u
.ipv6
.prefixlen
;
851 map
->type
= MAP_TYPE_PWID
;
852 map
->fec
.pwid
.type
= fec
->u
.pwid
.type
;
853 map
->fec
.pwid
.group_id
= 0;
854 map
->flags
|= F_MAP_PW_ID
;
855 map
->fec
.pwid
.pwid
= fec
->u
.pwid
.pwid
;
861 lde_map2fec(struct map
*map
, struct in_addr lsr_id
, struct fec
*fec
)
863 memset(fec
, 0, sizeof(*fec
));
866 case MAP_TYPE_PREFIX
:
867 switch (map
->fec
.prefix
.af
) {
869 fec
->type
= FEC_TYPE_IPV4
;
870 fec
->u
.ipv4
.prefix
= map
->fec
.prefix
.prefix
.v4
;
871 fec
->u
.ipv4
.prefixlen
= map
->fec
.prefix
.prefixlen
;
874 fec
->type
= FEC_TYPE_IPV6
;
875 fec
->u
.ipv6
.prefix
= map
->fec
.prefix
.prefix
.v6
;
876 fec
->u
.ipv6
.prefixlen
= map
->fec
.prefix
.prefixlen
;
879 fatalx("lde_map2fec: unknown af");
884 fec
->type
= FEC_TYPE_PWID
;
885 fec
->u
.pwid
.type
= map
->fec
.pwid
.type
;
886 fec
->u
.pwid
.pwid
= map
->fec
.pwid
.pwid
;
887 fec
->u
.pwid
.lsr_id
= lsr_id
;
893 lde_send_labelmapping(struct lde_nbr
*ln
, struct fec_node
*fn
, int single
)
895 struct lde_wdraw
*lw
;
902 * We shouldn't send a new label mapping if we have a pending
903 * label release to receive. In this case, schedule to send a
904 * label mapping as soon as a label release is received.
906 lw
= (struct lde_wdraw
*)fec_find(&ln
->sent_wdraw
, &fn
->fec
);
908 if (!fec_find(&ln
->sent_map_pending
, &fn
->fec
))
909 lde_map_pending_add(ln
, fn
);
914 * This function skips SL.1 - 3 and SL.9 - 14 because the label
915 * allocation is done way earlier (because of the merging nature of
919 lde_fec2map(&fn
->fec
, &map
);
920 switch (fn
->fec
.type
) {
924 if (lde_acl_check(ldeconf
->ipv4
.acl_label_advertise_to
,
925 AF_INET
, (union ldpd_addr
*)&ln
->id
, 32) != FILTER_PERMIT
)
927 if (lde_acl_check(ldeconf
->ipv4
.acl_label_advertise_for
,
928 AF_INET
, (union ldpd_addr
*)&fn
->fec
.u
.ipv4
.prefix
,
929 fn
->fec
.u
.ipv4
.prefixlen
) != FILTER_PERMIT
)
935 if (lde_acl_check(ldeconf
->ipv6
.acl_label_advertise_to
,
936 AF_INET
, (union ldpd_addr
*)&ln
->id
, 32) != FILTER_PERMIT
)
938 if (lde_acl_check(ldeconf
->ipv6
.acl_label_advertise_for
,
939 AF_INET6
, (union ldpd_addr
*)&fn
->fec
.u
.ipv6
.prefix
,
940 fn
->fec
.u
.ipv6
.prefixlen
) != FILTER_PERMIT
)
944 pw
= (struct l2vpn_pw
*) fn
->data
;
945 if (pw
== NULL
|| pw
->lsr_id
.s_addr
!= ln
->id
.s_addr
)
946 /* not the remote end of the pseudowire */
949 map
.flags
|= F_MAP_PW_IFMTU
;
950 map
.fec
.pwid
.ifmtu
= pw
->l2vpn
->mtu
;
951 if (pw
->flags
& F_PW_CWORD
)
952 map
.flags
|= F_MAP_PW_CWORD
;
953 if (pw
->flags
& F_PW_STATUSTLV
) {
954 map
.flags
|= F_MAP_PW_STATUS
;
955 /* VPLS are always up */
956 map
.pw_status
= PW_FORWARDING
;
960 map
.label
= fn
->local_label
;
962 /* SL.6: is there a pending request for this mapping? */
963 lre
= (struct lde_req
*)fec_find(&ln
->recv_req
, &fn
->fec
);
965 /* set label request msg id in the mapping response. */
966 map
.requestid
= lre
->msg_id
;
967 map
.flags
= F_MAP_REQ_ID
;
969 /* SL.7: delete record of pending request */
970 lde_req_del(ln
, lre
, 0);
973 /* SL.4: send label mapping */
974 lde_imsg_compose_ldpe(IMSG_MAPPING_ADD
, ln
->peerid
, 0,
977 lde_imsg_compose_ldpe(IMSG_MAPPING_ADD_END
, ln
->peerid
, 0,
980 /* SL.5: record sent label mapping */
981 me
= (struct lde_map
*)fec_find(&ln
->sent_map
, &fn
->fec
);
983 me
= lde_map_add(ln
, fn
, 1);
988 lde_send_labelwithdraw(struct lde_nbr
*ln
, struct fec_node
*fn
,
989 struct map
*wcard
, struct status_tlv
*st
)
991 struct lde_wdraw
*lw
;
997 lde_fec2map(&fn
->fec
, &map
);
998 switch (fn
->fec
.type
) {
1000 if (!ln
->v4_enabled
)
1004 if (!ln
->v6_enabled
)
1008 pw
= (struct l2vpn_pw
*) fn
->data
;
1009 if (pw
== NULL
|| pw
->lsr_id
.s_addr
!= ln
->id
.s_addr
)
1010 /* not the remote end of the pseudowire */
1013 if (pw
->flags
& F_PW_CWORD
)
1014 map
.flags
|= F_MAP_PW_CWORD
;
1017 map
.label
= fn
->local_label
;
1019 memcpy(&map
, wcard
, sizeof(map
));
1022 map
.st
.status_code
= st
->status_code
;
1023 map
.st
.msg_id
= st
->msg_id
;
1024 map
.st
.msg_type
= st
->msg_type
;
1025 map
.flags
|= F_MAP_STATUS
;
1028 /* SWd.1: send label withdraw. */
1029 lde_imsg_compose_ldpe(IMSG_WITHDRAW_ADD
, ln
->peerid
, 0,
1031 lde_imsg_compose_ldpe(IMSG_WITHDRAW_ADD_END
, ln
->peerid
, 0, NULL
, 0);
1033 /* SWd.2: record label withdraw. */
1035 lw
= (struct lde_wdraw
*)fec_find(&ln
->sent_wdraw
, &fn
->fec
);
1037 lw
= lde_wdraw_add(ln
, fn
);
1038 lw
->label
= map
.label
;
1042 RB_FOREACH(f
, fec_tree
, &ft
) {
1043 fn
= (struct fec_node
*)f
;
1044 me
= (struct lde_map
*)fec_find(&ln
->sent_map
, &fn
->fec
);
1045 if (lde_wildcard_apply(wcard
, &fn
->fec
, me
) == 0)
1048 lw
= (struct lde_wdraw
*)fec_find(&ln
->sent_wdraw
,
1051 lw
= lde_wdraw_add(ln
, fn
);
1052 lw
->label
= map
.label
;
1058 lde_send_labelwithdraw_wcard(struct lde_nbr
*ln
, uint32_t label
)
1062 memset(&wcard
, 0, sizeof(wcard
));
1063 wcard
.type
= MAP_TYPE_WILDCARD
;
1064 wcard
.label
= label
;
1065 lde_send_labelwithdraw(ln
, NULL
, &wcard
, NULL
);
1069 lde_send_labelwithdraw_twcard_prefix(struct lde_nbr
*ln
, uint16_t af
,
1074 memset(&wcard
, 0, sizeof(wcard
));
1075 wcard
.type
= MAP_TYPE_TYPED_WCARD
;
1076 wcard
.fec
.twcard
.type
= MAP_TYPE_PREFIX
;
1077 wcard
.fec
.twcard
.u
.prefix_af
= af
;
1078 wcard
.label
= label
;
1079 lde_send_labelwithdraw(ln
, NULL
, &wcard
, NULL
);
1083 lde_send_labelwithdraw_twcard_pwid(struct lde_nbr
*ln
, uint16_t pw_type
,
1088 memset(&wcard
, 0, sizeof(wcard
));
1089 wcard
.type
= MAP_TYPE_TYPED_WCARD
;
1090 wcard
.fec
.twcard
.type
= MAP_TYPE_PWID
;
1091 wcard
.fec
.twcard
.u
.pw_type
= pw_type
;
1092 wcard
.label
= label
;
1093 lde_send_labelwithdraw(ln
, NULL
, &wcard
, NULL
);
1097 lde_send_labelwithdraw_pwid_wcard(struct lde_nbr
*ln
, uint16_t pw_type
,
1102 memset(&wcard
, 0, sizeof(wcard
));
1103 wcard
.type
= MAP_TYPE_PWID
;
1104 wcard
.fec
.pwid
.type
= pw_type
;
1105 wcard
.fec
.pwid
.group_id
= group_id
;
1106 /* we can not append a Label TLV when using PWid group wildcards. */
1107 wcard
.label
= NO_LABEL
;
1108 lde_send_labelwithdraw(ln
, NULL
, &wcard
, NULL
);
1112 lde_send_labelrelease(struct lde_nbr
*ln
, struct fec_node
*fn
,
1113 struct map
*wcard
, uint32_t label
)
1116 struct l2vpn_pw
*pw
;
1119 lde_fec2map(&fn
->fec
, &map
);
1120 switch (fn
->fec
.type
) {
1122 if (!ln
->v4_enabled
)
1126 if (!ln
->v6_enabled
)
1130 pw
= (struct l2vpn_pw
*) fn
->data
;
1131 if (pw
== NULL
|| pw
->lsr_id
.s_addr
!= ln
->id
.s_addr
)
1132 /* not the remote end of the pseudowire */
1135 if (pw
->flags
& F_PW_CWORD
)
1136 map
.flags
|= F_MAP_PW_CWORD
;
1140 memcpy(&map
, wcard
, sizeof(map
));
1143 lde_imsg_compose_ldpe(IMSG_RELEASE_ADD
, ln
->peerid
, 0,
1145 lde_imsg_compose_ldpe(IMSG_RELEASE_ADD_END
, ln
->peerid
, 0, NULL
, 0);
1149 lde_send_notification(struct lde_nbr
*ln
, uint32_t status_code
, uint32_t msg_id
,
1152 struct notify_msg nm
;
1154 memset(&nm
, 0, sizeof(nm
));
1155 nm
.status_code
= status_code
;
1156 /* 'msg_id' and 'msg_type' should be in network byte order */
1158 nm
.msg_type
= msg_type
;
1160 lde_imsg_compose_ldpe(IMSG_NOTIFICATION_SEND
, ln
->peerid
, 0,
1165 lde_send_notification_eol_prefix(struct lde_nbr
*ln
, int af
)
1167 struct notify_msg nm
;
1169 memset(&nm
, 0, sizeof(nm
));
1170 nm
.status_code
= S_ENDOFLIB
;
1171 nm
.fec
.type
= MAP_TYPE_TYPED_WCARD
;
1172 nm
.fec
.fec
.twcard
.type
= MAP_TYPE_PREFIX
;
1173 nm
.fec
.fec
.twcard
.u
.prefix_af
= af
;
1174 nm
.flags
|= F_NOTIF_FEC
;
1176 lde_imsg_compose_ldpe(IMSG_NOTIFICATION_SEND
, ln
->peerid
, 0,
1181 lde_send_notification_eol_pwid(struct lde_nbr
*ln
, uint16_t pw_type
)
1183 struct notify_msg nm
;
1185 memset(&nm
, 0, sizeof(nm
));
1186 nm
.status_code
= S_ENDOFLIB
;
1187 nm
.fec
.type
= MAP_TYPE_TYPED_WCARD
;
1188 nm
.fec
.fec
.twcard
.type
= MAP_TYPE_PWID
;
1189 nm
.fec
.fec
.twcard
.u
.pw_type
= pw_type
;
1190 nm
.flags
|= F_NOTIF_FEC
;
1192 lde_imsg_compose_ldpe(IMSG_NOTIFICATION_SEND
, ln
->peerid
, 0,
1197 lde_nbr_compare(struct lde_nbr
*a
, struct lde_nbr
*b
)
1199 return (a
->peerid
- b
->peerid
);
1202 static struct lde_nbr
*
1203 lde_nbr_new(uint32_t peerid
, struct lde_nbr
*new)
1207 if ((ln
= calloc(1, sizeof(*ln
))) == NULL
)
1211 ln
->v4_enabled
= new->v4_enabled
;
1212 ln
->v6_enabled
= new->v6_enabled
;
1213 ln
->flags
= new->flags
;
1214 ln
->peerid
= peerid
;
1215 fec_init(&ln
->recv_map
);
1216 fec_init(&ln
->sent_map
);
1217 fec_init(&ln
->sent_map_pending
);
1218 fec_init(&ln
->recv_req
);
1219 fec_init(&ln
->sent_req
);
1220 fec_init(&ln
->sent_wdraw
);
1222 TAILQ_INIT(&ln
->addr_list
);
1224 if (RB_INSERT(nbr_tree
, &lde_nbrs
, ln
) != NULL
)
1225 fatalx("lde_nbr_new: RB_INSERT failed");
1231 lde_nbr_del(struct lde_nbr
*ln
)
1234 struct fec_node
*fn
;
1236 struct l2vpn_pw
*pw
;
1241 /* uninstall received mappings */
1242 RB_FOREACH(f
, fec_tree
, &ft
) {
1243 fn
= (struct fec_node
*)f
;
1245 LIST_FOREACH(fnh
, &fn
->nexthops
, entry
) {
1249 if (!lde_address_find(ln
, fnh
->af
,
1254 if (f
->u
.pwid
.lsr_id
.s_addr
!= ln
->id
.s_addr
)
1256 pw
= (struct l2vpn_pw
*) fn
->data
;
1264 lde_send_delete_klabel(fn
, fnh
);
1265 fnh
->remote_label
= NO_LABEL
;
1269 lde_address_list_free(ln
);
1271 fec_clear(&ln
->recv_map
, lde_map_free
);
1272 fec_clear(&ln
->sent_map
, lde_map_free
);
1273 fec_clear(&ln
->sent_map_pending
, free
);
1274 fec_clear(&ln
->recv_req
, free
);
1275 fec_clear(&ln
->sent_req
, free
);
1276 fec_clear(&ln
->sent_wdraw
, free
);
1278 RB_REMOVE(nbr_tree
, &lde_nbrs
, ln
);
1283 static struct lde_nbr
*
1284 lde_nbr_find(uint32_t peerid
)
1290 return (RB_FIND(nbr_tree
, &lde_nbrs
, &ln
));
1294 lde_nbr_find_by_lsrid(struct in_addr addr
)
1298 RB_FOREACH(ln
, nbr_tree
, &lde_nbrs
)
1299 if (ln
->id
.s_addr
== addr
.s_addr
)
1306 lde_nbr_find_by_addr(int af
, union ldpd_addr
*addr
)
1310 RB_FOREACH(ln
, nbr_tree
, &lde_nbrs
)
1311 if (lde_address_find(ln
, af
, addr
) != NULL
)
1322 while ((ln
= RB_ROOT(&lde_nbrs
)) != NULL
)
1327 lde_nbr_addr_update(struct lde_nbr
*ln
, struct lde_addr
*lde_addr
, int removed
)
1330 struct fec_node
*fn
;
1334 RB_FOREACH(fec
, fec_tree
, &ln
->recv_map
) {
1335 fn
= (struct fec_node
*)fec_find(&ft
, fec
);
1336 switch (fec
->type
) {
1338 if (lde_addr
->af
!= AF_INET
)
1342 if (lde_addr
->af
!= AF_INET6
)
1349 LIST_FOREACH(fnh
, &fn
->nexthops
, entry
) {
1350 if (ldp_addrcmp(fnh
->af
, &fnh
->nexthop
,
1355 lde_send_delete_klabel(fn
, fnh
);
1356 fnh
->remote_label
= NO_LABEL
;
1358 me
= (struct lde_map
*)fec
;
1359 fnh
->remote_label
= me
->map
.label
;
1360 lde_send_change_klabel(fn
, fnh
);
1368 lde_map_compare(struct lde_map
*a
, struct lde_map
*b
)
1370 return (ldp_addrcmp(AF_INET
, (union ldpd_addr
*)&a
->nexthop
->id
,
1371 (union ldpd_addr
*)&b
->nexthop
->id
));
1375 lde_map_add(struct lde_nbr
*ln
, struct fec_node
*fn
, int sent
)
1379 me
= calloc(1, sizeof(*me
));
1387 RB_INSERT(lde_map_head
, &fn
->upstream
, me
);
1388 me
->head
= &fn
->upstream
;
1389 if (fec_insert(&ln
->sent_map
, &me
->fec
))
1390 log_warnx("failed to add %s to sent map",
1392 /* XXX on failure more cleanup is needed */
1394 RB_INSERT(lde_map_head
, &fn
->downstream
, me
);
1395 me
->head
= &fn
->downstream
;
1396 if (fec_insert(&ln
->recv_map
, &me
->fec
))
1397 log_warnx("failed to add %s to recv map",
1405 lde_map_del(struct lde_nbr
*ln
, struct lde_map
*me
, int sent
)
1408 fec_remove(&ln
->sent_map
, &me
->fec
);
1410 fec_remove(&ln
->recv_map
, &me
->fec
);
1416 lde_map_free(void *ptr
)
1418 struct lde_map
*map
= ptr
;
1420 RB_REMOVE(lde_map_head
, map
->head
, map
);
1425 lde_map_pending_add(struct lde_nbr
*ln
, struct fec_node
*fn
)
1429 map
= calloc(1, sizeof(*map
));
1434 if (fec_insert(&ln
->sent_map_pending
, map
))
1435 log_warnx("failed to add %s to sent map (pending)",
1442 lde_map_pending_del(struct lde_nbr
*ln
, struct fec
*map
)
1444 fec_remove(&ln
->sent_map_pending
, map
);
1449 lde_req_add(struct lde_nbr
*ln
, struct fec
*fec
, int sent
)
1452 struct lde_req
*lre
;
1454 t
= sent
? &ln
->sent_req
: &ln
->recv_req
;
1456 lre
= calloc(1, sizeof(*lre
));
1460 if (fec_insert(t
, &lre
->fec
)) {
1461 log_warnx("failed to add %s to %s req",
1462 log_fec(&lre
->fec
), sent
? "sent" : "recv");
1472 lde_req_del(struct lde_nbr
*ln
, struct lde_req
*lre
, int sent
)
1475 fec_remove(&ln
->sent_req
, &lre
->fec
);
1477 fec_remove(&ln
->recv_req
, &lre
->fec
);
1483 lde_wdraw_add(struct lde_nbr
*ln
, struct fec_node
*fn
)
1485 struct lde_wdraw
*lw
;
1487 lw
= calloc(1, sizeof(*lw
));
1493 if (fec_insert(&ln
->sent_wdraw
, &lw
->fec
))
1494 log_warnx("failed to add %s to sent wdraw",
1501 lde_wdraw_del(struct lde_nbr
*ln
, struct lde_wdraw
*lw
)
1503 fec_remove(&ln
->sent_wdraw
, &lw
->fec
);
1508 lde_change_egress_label(int af
)
1512 struct fec_node
*fn
;
1514 /* explicitly withdraw all null labels */
1515 RB_FOREACH(ln
, nbr_tree
, &lde_nbrs
) {
1516 lde_send_labelwithdraw_wcard(ln
, MPLS_LABEL_IMPLNULL
);
1518 lde_send_labelwithdraw_wcard(ln
, MPLS_LABEL_IPV4NULL
);
1520 lde_send_labelwithdraw_wcard(ln
, MPLS_LABEL_IPV6NULL
);
1523 /* update label of connected routes */
1524 RB_FOREACH(f
, fec_tree
, &ft
) {
1525 fn
= (struct fec_node
*)f
;
1526 if (fn
->local_label
> MPLS_LABEL_RESERVED_MAX
)
1531 if (fn
->fec
.type
!= FEC_TYPE_IPV4
)
1535 if (fn
->fec
.type
!= FEC_TYPE_IPV6
)
1539 fatalx("lde_change_egress_label: unknown af");
1542 fn
->local_label
= lde_update_label(fn
);
1543 if (fn
->local_label
!= NO_LABEL
)
1544 RB_FOREACH(ln
, nbr_tree
, &lde_nbrs
)
1545 lde_send_labelmapping(ln
, fn
, 0);
1547 RB_FOREACH(ln
, nbr_tree
, &lde_nbrs
)
1548 lde_imsg_compose_ldpe(IMSG_MAPPING_ADD_END
, ln
->peerid
, 0,
1553 lde_address_add(struct lde_nbr
*ln
, struct lde_addr
*lde_addr
)
1555 struct lde_addr
*new;
1557 if (lde_address_find(ln
, lde_addr
->af
, &lde_addr
->addr
) != NULL
)
1560 if ((new = calloc(1, sizeof(*new))) == NULL
)
1563 new->af
= lde_addr
->af
;
1564 new->addr
= lde_addr
->addr
;
1565 TAILQ_INSERT_TAIL(&ln
->addr_list
, new, entry
);
1567 /* reevaluate the previously received mappings from this neighbor */
1568 lde_nbr_addr_update(ln
, lde_addr
, 0);
1574 lde_address_del(struct lde_nbr
*ln
, struct lde_addr
*lde_addr
)
1576 lde_addr
= lde_address_find(ln
, lde_addr
->af
, &lde_addr
->addr
);
1577 if (lde_addr
== NULL
)
1580 /* reevaluate the previously received mappings from this neighbor */
1581 lde_nbr_addr_update(ln
, lde_addr
, 1);
1583 TAILQ_REMOVE(&ln
->addr_list
, lde_addr
, entry
);
1590 lde_address_find(struct lde_nbr
*ln
, int af
, union ldpd_addr
*addr
)
1592 struct lde_addr
*lde_addr
;
1594 TAILQ_FOREACH(lde_addr
, &ln
->addr_list
, entry
)
1595 if (lde_addr
->af
== af
&&
1596 ldp_addrcmp(af
, &lde_addr
->addr
, addr
) == 0)
1603 lde_address_list_free(struct lde_nbr
*ln
)
1605 struct lde_addr
*lde_addr
;
1607 while ((lde_addr
= TAILQ_FIRST(&ln
->addr_list
)) != NULL
) {
1608 TAILQ_REMOVE(&ln
->addr_list
, lde_addr
, entry
);
1614 zclient_sync_init(u_short instance
)
1616 /* Initialize special zclient for synchronous message exchanges. */
1617 log_debug("Initializing synchronous zclient for label manager");
1618 zclient_sync
= zclient_new(master
);
1619 zclient_sync
->sock
= -1;
1620 zclient_sync
->redist_default
= ZEBRA_ROUTE_LDP
;
1621 zclient_sync
->instance
= instance
;
1622 while (zclient_socket_connect(zclient_sync
) < 0) {
1623 log_warnx("Error connecting synchronous zclient!");
1627 /* Connect to label manager */
1628 while (lm_label_manager_connect(zclient_sync
) != 0) {
1629 log_warnx("Error connecting to label manager!");
1635 lde_del_label_chunk(void *val
)
1641 lde_get_label_chunk(void)
1644 uint32_t start
, end
;
1646 log_debug("Getting label chunk");
1647 ret
= lm_get_label_chunk(zclient_sync
, 0, CHUNK_SIZE
, &start
, &end
);
1649 log_warnx("Error getting label chunk!");
1650 close(zclient_sync
->sock
);
1651 zclient_sync
->sock
= -1;
1655 on_get_label_chunk_response(start
, end
);
1661 lde_label_list_init(void)
1663 label_chunk_list
= list_new();
1664 label_chunk_list
->del
= lde_del_label_chunk
;
1666 /* get first chunk */
1667 while (lde_get_label_chunk () != 0) {
1668 log_warnx("Error getting first label chunk!");
1674 on_get_label_chunk_response(uint32_t start
, uint32_t end
)
1676 struct label_chunk
*new_label_chunk
;
1678 log_debug("Label Chunk assign: %u - %u", start
, end
);
1680 new_label_chunk
= calloc(1, sizeof(struct label_chunk
));
1681 if (!new_label_chunk
) {
1682 log_warn("Error trying to allocate label chunk %u - %u", start
, end
);
1686 new_label_chunk
->start
= start
;
1687 new_label_chunk
->end
= end
;
1688 new_label_chunk
->used_mask
= 0;
1690 listnode_add(label_chunk_list
, (void *)new_label_chunk
);
1692 /* let's update current if needed */
1693 if (!current_label_chunk
)
1694 current_label_chunk
= listtail(label_chunk_list
);
1698 lde_get_next_label(void)
1700 struct label_chunk
*label_chunk
;
1701 uint32_t i
, pos
, size
;
1702 uint32_t label
= NO_LABEL
;
1704 while (current_label_chunk
) {
1705 label_chunk
= listgetdata(current_label_chunk
);
1709 /* try to get next free label in currently used label chunk */
1710 size
= label_chunk
->end
- label_chunk
->start
+ 1;
1711 for (i
= 0, pos
= 1; i
< size
; i
++, pos
<<= 1) {
1712 if (!(pos
& label_chunk
->used_mask
)) {
1713 label_chunk
->used_mask
|= pos
;
1714 label
= label_chunk
->start
+ i
;
1718 current_label_chunk
= listnextnode(current_label_chunk
);
1722 /* we moved till the last chunk, or were not able to find a label,
1723 so let's ask for another one */
1724 if (!current_label_chunk
||
1725 current_label_chunk
== listtail(label_chunk_list
) ||
1726 label
== NO_LABEL
) {
1727 if (lde_get_label_chunk() != 0)
1728 log_warn("%s: Error getting label chunk!", __func__
);