]>
git.proxmox.com Git - mirror_frr.git/blob - ldpd/lde_lib.c
4 * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
5 * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
30 static __inline
int fec_compare(const struct fec
*, const struct fec
*);
31 static int lde_nbr_is_nexthop(struct fec_node
*,
33 static void fec_free(void *);
34 static struct fec_node
*fec_add(struct fec
*fec
);
35 static struct fec_nh
*fec_nh_add(struct fec_node
*, int, union ldpd_addr
*,
36 ifindex_t
, uint8_t, unsigned short);
37 static void fec_nh_del(struct fec_nh
*);
39 RB_GENERATE(fec_tree
, fec
, entry
, fec_compare
)
41 struct fec_tree ft
= RB_INITIALIZER(&ft
);
42 struct thread
*gc_timer
;
44 /* FEC tree functions */
46 fec_init(struct fec_tree
*fh
)
48 RB_INIT(fec_tree
, fh
);
52 fec_compare(const struct fec
*a
, const struct fec
*b
)
54 if (a
->type
< b
->type
)
56 if (a
->type
> b
->type
)
61 if (ntohl(a
->u
.ipv4
.prefix
.s_addr
) <
62 ntohl(b
->u
.ipv4
.prefix
.s_addr
))
64 if (ntohl(a
->u
.ipv4
.prefix
.s_addr
) >
65 ntohl(b
->u
.ipv4
.prefix
.s_addr
))
67 if (a
->u
.ipv4
.prefixlen
< b
->u
.ipv4
.prefixlen
)
69 if (a
->u
.ipv4
.prefixlen
> b
->u
.ipv4
.prefixlen
)
73 if (memcmp(&a
->u
.ipv6
.prefix
, &b
->u
.ipv6
.prefix
,
74 sizeof(struct in6_addr
)) < 0)
76 if (memcmp(&a
->u
.ipv6
.prefix
, &b
->u
.ipv6
.prefix
,
77 sizeof(struct in6_addr
)) > 0)
79 if (a
->u
.ipv6
.prefixlen
< b
->u
.ipv6
.prefixlen
)
81 if (a
->u
.ipv6
.prefixlen
> b
->u
.ipv6
.prefixlen
)
85 if (a
->u
.pwid
.type
< b
->u
.pwid
.type
)
87 if (a
->u
.pwid
.type
> b
->u
.pwid
.type
)
89 if (a
->u
.pwid
.pwid
< b
->u
.pwid
.pwid
)
91 if (a
->u
.pwid
.pwid
> b
->u
.pwid
.pwid
)
93 if (ntohl(a
->u
.pwid
.lsr_id
.s_addr
) <
94 ntohl(b
->u
.pwid
.lsr_id
.s_addr
))
96 if (ntohl(a
->u
.pwid
.lsr_id
.s_addr
) >
97 ntohl(b
->u
.pwid
.lsr_id
.s_addr
))
106 fec_find(struct fec_tree
*fh
, struct fec
*f
)
108 return (RB_FIND(fec_tree
, fh
, f
));
112 fec_insert(struct fec_tree
*fh
, struct fec
*f
)
114 if (RB_INSERT(fec_tree
, fh
, f
) != NULL
)
120 fec_remove(struct fec_tree
*fh
, struct fec
*f
)
122 if (RB_REMOVE(fec_tree
, fh
, f
) == NULL
) {
123 log_warnx("%s failed for %s", __func__
, log_fec(f
));
130 fec_clear(struct fec_tree
*fh
, void (*free_cb
)(void *))
134 while (!RB_EMPTY(fec_tree
, fh
)) {
135 f
= RB_ROOT(fec_tree
, fh
);
142 /* routing table functions */
144 lde_nbr_is_nexthop(struct fec_node
*fn
, struct lde_nbr
*ln
)
148 LIST_FOREACH(fnh
, &fn
->nexthops
, entry
)
149 if (lde_address_find(ln
, fnh
->af
, &fnh
->nexthop
))
161 static struct ctl_rt rtctl
;
163 RB_FOREACH(f
, fec_tree
, &ft
) {
164 fn
= (struct fec_node
*)f
;
165 if (fn
->local_label
== NO_LABEL
&&
166 RB_EMPTY(lde_map_head
, &fn
->downstream
))
169 memset(&rtctl
, 0, sizeof(rtctl
));
170 switch (fn
->fec
.type
) {
173 rtctl
.prefix
.v4
= fn
->fec
.u
.ipv4
.prefix
;
174 rtctl
.prefixlen
= fn
->fec
.u
.ipv4
.prefixlen
;
178 rtctl
.prefix
.v6
= fn
->fec
.u
.ipv6
.prefix
;
179 rtctl
.prefixlen
= fn
->fec
.u
.ipv6
.prefixlen
;
185 rtctl
.local_label
= fn
->local_label
;
186 if (RB_EMPTY(lde_map_head
, &fn
->downstream
)) {
188 rtctl
.nexthop
.s_addr
= INADDR_ANY
;
189 rtctl
.remote_label
= NO_LABEL
;
190 rtctl
.no_downstream
= 1;
192 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB_BEGIN
, 0, pid
, &rtctl
,
195 RB_FOREACH(me
, lde_map_head
, &fn
->upstream
) {
196 rtctl
.nexthop
= me
->nexthop
->id
;
197 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB_SENT
, 0, pid
,
198 &rtctl
, sizeof(rtctl
));
201 RB_FOREACH(me
, lde_map_head
, &fn
->downstream
) {
202 rtctl
.in_use
= lde_nbr_is_nexthop(fn
, me
->nexthop
);
203 rtctl
.nexthop
= me
->nexthop
->id
;
204 rtctl
.remote_label
= me
->map
.label
;
205 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB_RCVD
, 0, pid
,
206 &rtctl
, sizeof(rtctl
));
208 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB_END
, 0, pid
, &rtctl
,
214 fec_snap(struct lde_nbr
*ln
)
219 RB_FOREACH(f
, fec_tree
, &ft
) {
220 fn
= (struct fec_node
*)f
;
221 if (fn
->local_label
== NO_LABEL
)
224 lde_send_labelmapping(ln
, fn
, 0);
227 lde_imsg_compose_ldpe(IMSG_MAPPING_ADD_END
, ln
->peerid
, 0, NULL
, 0);
233 struct fec_node
*fn
= arg
;
236 while ((fnh
= LIST_FIRST(&fn
->nexthops
))) {
238 assert(fnh
!= LIST_FIRST(&fn
->nexthops
));
240 if (!RB_EMPTY(lde_map_head
, &fn
->downstream
))
241 log_warnx("%s: fec %s downstream list not empty", __func__
,
243 if (!RB_EMPTY(lde_map_head
, &fn
->upstream
))
244 log_warnx("%s: fec %s upstream list not empty", __func__
,
253 fec_clear(&ft
, fec_free
);
256 static struct fec_node
*
257 fec_add(struct fec
*fec
)
261 fn
= calloc(1, sizeof(*fn
));
266 fn
->local_label
= NO_LABEL
;
267 RB_INIT(lde_map_head
, &fn
->upstream
);
268 RB_INIT(lde_map_head
, &fn
->downstream
);
269 LIST_INIT(&fn
->nexthops
);
271 if (fec
->type
== FEC_TYPE_PWID
)
272 fn
->pw_remote_status
= PW_FORWARDING
;
274 if (fec_insert(&ft
, &fn
->fec
))
275 log_warnx("failed to add %s to ft tree",
282 fec_nh_find(struct fec_node
*fn
, int af
, union ldpd_addr
*nexthop
,
283 ifindex_t ifindex
, uint8_t route_type
, unsigned short route_instance
)
287 LIST_FOREACH(fnh
, &fn
->nexthops
, entry
)
289 ldp_addrcmp(af
, &fnh
->nexthop
, nexthop
) == 0 &&
290 fnh
->ifindex
== ifindex
&&
291 fnh
->route_type
== route_type
&&
292 fnh
->route_instance
== route_instance
)
298 static struct fec_nh
*
299 fec_nh_add(struct fec_node
*fn
, int af
, union ldpd_addr
*nexthop
,
300 ifindex_t ifindex
, uint8_t route_type
, unsigned short route_instance
)
304 fnh
= calloc(1, sizeof(*fnh
));
309 fnh
->nexthop
= *nexthop
;
310 fnh
->ifindex
= ifindex
;
311 fnh
->remote_label
= NO_LABEL
;
312 fnh
->route_type
= route_type
;
313 fnh
->route_instance
= route_instance
;
314 LIST_INSERT_HEAD(&fn
->nexthops
, fnh
, entry
);
320 fec_nh_del(struct fec_nh
*fnh
)
322 LIST_REMOVE(fnh
, entry
);
327 lde_kernel_insert(struct fec
*fec
, int af
, union ldpd_addr
*nexthop
,
328 ifindex_t ifindex
, uint8_t route_type
, unsigned short route_instance
,
329 int connected
, void *data
)
335 fn
= (struct fec_node
*)fec_find(&ft
, fec
);
341 fnh
= fec_nh_find(fn
, af
, nexthop
, ifindex
, route_type
, route_instance
);
343 fnh
= fec_nh_add(fn
, af
, nexthop
, ifindex
, route_type
,
346 * Ordered Control: if not a connected route and not a route
347 * learned over an interface not running LDP and not a PW
348 * then mark to wait until we receive labelmap msg before
349 * installing in kernel and sending to peer
351 iface
= if_lookup(ldeconf
, ifindex
);
352 if ((ldeconf
->flags
& F_LDPD_ORDERED_CONTROL
) &&
353 !connected
&& iface
!= NULL
&& fec
->type
!= FEC_TYPE_PWID
)
354 fnh
->flags
|= F_FEC_NH_DEFER
;
357 fnh
->flags
|= F_FEC_NH_NEW
;
359 fnh
->flags
|= F_FEC_NH_CONNECTED
;
363 lde_kernel_remove(struct fec
*fec
, int af
, union ldpd_addr
*nexthop
,
364 ifindex_t ifindex
, uint8_t route_type
, unsigned short route_instance
)
369 fn
= (struct fec_node
*)fec_find(&ft
, fec
);
373 fnh
= fec_nh_find(fn
, af
, nexthop
, ifindex
, route_type
, route_instance
);
378 lde_send_delete_klabel(fn
, fnh
);
383 * Whenever a route is changed, zebra advertises its new version without
384 * withdrawing the old one. So, after processing a ZEBRA_REDISTRIBUTE_IPV[46]_ADD
385 * message, we need to check for nexthops that were removed and, for each of
386 * them (if any), withdraw the associated labels from zebra.
389 lde_kernel_update(struct fec
*fec
)
392 struct fec_nh
*fnh
, *safe
;
397 fn
= (struct fec_node
*)fec_find(&ft
, fec
);
401 LIST_FOREACH_SAFE(fnh
, &fn
->nexthops
, entry
, safe
) {
402 if (fnh
->flags
& F_FEC_NH_NEW
) {
403 fnh
->flags
&= ~F_FEC_NH_NEW
;
405 * if LDP configured on interface or a static route
406 * clear flag else treat fec as a connected route
408 if (ldeconf
->flags
& F_LDPD_ENABLED
) {
409 iface
= if_lookup(ldeconf
,fnh
->ifindex
);
410 if (fnh
->flags
& F_FEC_NH_CONNECTED
||
412 fnh
->route_type
== ZEBRA_ROUTE_STATIC
)
413 fnh
->flags
&=~F_FEC_NH_NO_LDP
;
415 fnh
->flags
|= F_FEC_NH_NO_LDP
;
417 fnh
->flags
|= F_FEC_NH_NO_LDP
;
419 lde_send_delete_klabel(fn
, fnh
);
424 if (LIST_EMPTY(&fn
->nexthops
)) {
425 RB_FOREACH(ln
, nbr_tree
, &lde_nbrs
)
426 lde_send_labelwithdraw(ln
, fn
, NULL
, NULL
);
430 * Do not deallocate the local label now, do that only in the
431 * LIB garbage collector. This will prevent ldpd from changing
432 * the input label of some prefixes too often when running on
433 * an unstable network. Also, restart the garbage collector
434 * timer so that labels are deallocated only when the network
437 lde_gc_start_timer();
439 fn
->local_label
= lde_update_label(fn
);
440 if (fn
->local_label
!= NO_LABEL
)
441 /* FEC.1: perform lsr label distribution procedure */
442 RB_FOREACH(ln
, nbr_tree
, &lde_nbrs
)
443 lde_send_labelmapping(ln
, fn
, 1);
446 /* if no label created yet then don't try to program labeled route */
447 if (fn
->local_label
== NO_LABEL
)
450 LIST_FOREACH(fnh
, &fn
->nexthops
, entry
) {
451 lde_send_change_klabel(fn
, fnh
);
453 switch (fn
->fec
.type
) {
456 ln
= lde_nbr_find_by_addr(fnh
->af
, &fnh
->nexthop
);
459 ln
= lde_nbr_find_by_lsrid(fn
->fec
.u
.pwid
.lsr_id
);
468 me
= (struct lde_map
*)fec_find(&ln
->recv_map
, &fn
->fec
);
471 lde_check_mapping(&me
->map
, ln
, 0);
477 lde_check_mapping(struct map
*map
, struct lde_nbr
*ln
, int rcvd_label_mapping
)
485 bool send_map
= false;
487 lde_map2fec(map
, ln
->id
, &fec
);
491 if (lde_acl_check(ldeconf
->ipv4
.acl_label_accept_from
,
492 AF_INET
, (union ldpd_addr
*)&ln
->id
, 32) != FILTER_PERMIT
)
494 if (lde_acl_check(ldeconf
->ipv4
.acl_label_accept_for
,
495 AF_INET
, (union ldpd_addr
*)&fec
.u
.ipv4
.prefix
,
496 fec
.u
.ipv4
.prefixlen
) != FILTER_PERMIT
)
500 if (lde_acl_check(ldeconf
->ipv6
.acl_label_accept_from
,
501 AF_INET
, (union ldpd_addr
*)&ln
->id
, 32) != FILTER_PERMIT
)
503 if (lde_acl_check(ldeconf
->ipv6
.acl_label_accept_for
,
504 AF_INET6
, (union ldpd_addr
*)&fec
.u
.ipv6
.prefix
,
505 fec
.u
.ipv6
.prefixlen
) != FILTER_PERMIT
)
512 fn
= (struct fec_node
*)fec_find(&ft
, &fec
);
516 /* LMp.1: first check if we have a pending request running */
517 lre
= (struct lde_req
*)fec_find(&ln
->sent_req
, &fn
->fec
);
519 /* LMp.2: delete record of outstanding label request */
520 lde_req_del(ln
, lre
, 1);
522 /* RFC 4447 control word and status tlv negotiation */
523 if (map
->type
== MAP_TYPE_PWID
&& l2vpn_pw_negotiate(ln
, fn
, map
)) {
524 if (rcvd_label_mapping
&& map
->flags
& F_MAP_PW_STATUS
)
525 fn
->pw_remote_status
= map
->pw_status
;
531 * LMp.3 - LMp.8: loop detection - unnecessary for frame-mode
536 me
= (struct lde_map
*)fec_find(&ln
->recv_map
, &fn
->fec
);
539 if (me
->map
.label
!= map
->label
&& lre
== NULL
) {
541 lde_send_labelrelease(ln
, fn
, NULL
, me
->map
.label
);
544 * Can not use lde_nbr_find_by_addr() because there's
545 * the possibility of multipath.
547 LIST_FOREACH(fnh
, &fn
->nexthops
, entry
) {
548 if (lde_address_find(ln
, fnh
->af
,
549 &fnh
->nexthop
) == NULL
)
552 lde_send_delete_klabel(fn
, fnh
);
553 fnh
->remote_label
= NO_LABEL
;
559 * LMp.11 - 12: consider multiple nexthops in order to
562 LIST_FOREACH(fnh
, &fn
->nexthops
, entry
) {
563 /* LMp.15: install FEC in FIB */
567 if (!lde_address_find(ln
, fnh
->af
, &fnh
->nexthop
))
571 * Ordered Control: labelmap msg received from
572 * NH so clear flag and send labelmap msg to
575 if (ldeconf
->flags
& F_LDPD_ORDERED_CONTROL
) {
577 fnh
->flags
&= ~F_FEC_NH_DEFER
;
579 fnh
->remote_label
= map
->label
;
580 if (fn
->local_label
!= NO_LABEL
)
581 lde_send_change_klabel(fn
, fnh
);
584 pw
= (struct l2vpn_pw
*) fn
->data
;
588 pw
->remote_group
= map
->fec
.pwid
.group_id
;
589 if (map
->flags
& F_MAP_PW_IFMTU
)
590 pw
->remote_mtu
= map
->fec
.pwid
.ifmtu
;
591 if (rcvd_label_mapping
&& map
->flags
& F_MAP_PW_STATUS
) {
592 pw
->remote_status
= map
->pw_status
;
593 fn
->pw_remote_status
= map
->pw_status
;
596 pw
->remote_status
= PW_FORWARDING
;
597 fnh
->remote_label
= map
->label
;
598 if (l2vpn_pw_ok(pw
, fnh
))
599 lde_send_change_klabel(fn
, fnh
);
606 /* Update RLFA clients. */
607 lde_rlfa_update_clients(&fec
, ln
, map
->label
);
609 /* LMp.13 & LMp.16: Record the mapping from this peer */
611 me
= lde_map_add(ln
, fn
, 0);
615 * LMp.17 - LMp.27 are unnecessary since we don't need to implement
616 * loop detection. LMp.28 - LMp.30 are unnecessary because we are
621 * Ordered Control: just received a labelmap for this fec from NH so
622 * need to send labelmap to all peers
623 * LMp.20 - LMp21 Execute procedure to send Label Mapping
625 if (send_map
&& fn
->local_label
!= NO_LABEL
)
626 RB_FOREACH(ln
, nbr_tree
, &lde_nbrs
)
627 lde_send_labelmapping(ln
, fn
, 1);
631 lde_check_request(struct map
*map
, struct lde_nbr
*ln
)
638 /* wildcard label request */
639 if (map
->type
== MAP_TYPE_TYPED_WCARD
) {
640 lde_check_request_wcard(map
, ln
);
644 /* LRq.1: skip loop detection (not necessary) */
646 /* LRq.2: is there a next hop for fec? */
647 lde_map2fec(map
, ln
->id
, &fec
);
648 fn
= (struct fec_node
*)fec_find(&ft
, &fec
);
649 if (fn
== NULL
|| LIST_EMPTY(&fn
->nexthops
)) {
650 /* LRq.5: send No Route notification */
651 lde_send_notification(ln
, S_NO_ROUTE
, map
->msg_id
,
652 htons(MSG_TYPE_LABELREQUEST
));
656 /* LRq.3: is MsgSource the next hop? */
657 LIST_FOREACH(fnh
, &fn
->nexthops
, entry
) {
661 if (!lde_address_find(ln
, fnh
->af
, &fnh
->nexthop
))
664 /* LRq.4: send Loop Detected notification */
665 lde_send_notification(ln
, S_LOOP_DETECTED
, map
->msg_id
,
666 htons(MSG_TYPE_LABELREQUEST
));
673 /* LRq.6: first check if we have a pending request running */
674 lre
= (struct lde_req
*)fec_find(&ln
->recv_req
, &fn
->fec
);
676 /* LRq.7: duplicate request */
679 /* LRq.8: record label request */
680 lre
= lde_req_add(ln
, &fn
->fec
, 0);
682 lre
->msg_id
= ntohl(map
->msg_id
);
684 /* LRq.9: perform LSR label distribution */
685 lde_send_labelmapping(ln
, fn
, 1);
688 * LRq.10: do nothing (Request Never) since we use liberal
690 * LRq.11 - 12 are unnecessary since we are merging capable.
695 lde_check_request_wcard(struct map
*map
, struct lde_nbr
*ln
)
701 RB_FOREACH(f
, fec_tree
, &ft
) {
702 fn
= (struct fec_node
*)f
;
704 /* only a typed wildcard is possible here */
705 if (lde_wildcard_apply(map
, &fn
->fec
, NULL
) == 0)
708 /* LRq.2: is there a next hop for fec? */
709 if (LIST_EMPTY(&fn
->nexthops
))
712 /* LRq.6: first check if we have a pending request running */
713 lre
= (struct lde_req
*)fec_find(&ln
->recv_req
, &fn
->fec
);
715 /* LRq.7: duplicate request */
718 /* LRq.8: record label request */
719 lre
= lde_req_add(ln
, &fn
->fec
, 0);
721 lre
->msg_id
= ntohl(map
->msg_id
);
723 /* LRq.9: perform LSR label distribution */
724 lde_send_labelmapping(ln
, fn
, 1);
729 lde_check_release(struct map
*map
, struct lde_nbr
*ln
)
733 struct lde_wdraw
*lw
;
735 struct fec
*pending_map
;
737 /* wildcard label release */
738 if (map
->type
== MAP_TYPE_WILDCARD
||
739 map
->type
== MAP_TYPE_TYPED_WCARD
||
740 (map
->type
== MAP_TYPE_PWID
&& !(map
->flags
& F_MAP_PW_ID
))) {
741 lde_check_release_wcard(map
, ln
);
745 lde_map2fec(map
, ln
->id
, &fec
);
746 fn
= (struct fec_node
*)fec_find(&ft
, &fec
);
747 /* LRl.1: does FEC match a known FEC? */
751 /* LRl.6: check sent map list and remove it if available */
752 me
= (struct lde_map
*)fec_find(&ln
->sent_map
, &fn
->fec
);
753 if (me
&& (map
->label
== NO_LABEL
|| map
->label
== me
->map
.label
))
754 lde_map_del(ln
, me
, 1);
756 /* LRl.3: first check if we have a pending withdraw running */
757 lw
= (struct lde_wdraw
*)fec_find(&ln
->sent_wdraw
, &fn
->fec
);
758 if (lw
&& (map
->label
== NO_LABEL
|| map
->label
== lw
->label
)) {
759 /* LRl.4: delete record of outstanding label withdraw */
760 lde_wdraw_del(ln
, lw
);
762 /* send pending label mapping if any */
763 pending_map
= fec_find(&ln
->sent_map_pending
, &fn
->fec
);
765 lde_send_labelmapping(ln
, fn
, 1);
766 lde_map_pending_del(ln
, pending_map
);
771 * LRl.11 - 13 are unnecessary since we remove the label from
772 * forwarding/switching as soon as the FEC is unreachable.
777 lde_check_release_wcard(struct map
*map
, struct lde_nbr
*ln
)
781 struct lde_wdraw
*lw
;
783 struct fec
*pending_map
;
785 RB_FOREACH(f
, fec_tree
, &ft
) {
786 fn
= (struct fec_node
*)f
;
787 me
= (struct lde_map
*)fec_find(&ln
->sent_map
, &fn
->fec
);
789 /* LRl.1: does FEC match a known FEC? */
790 if (lde_wildcard_apply(map
, &fn
->fec
, me
) == 0)
793 /* LRl.6: check sent map list and remove it if available */
795 (map
->label
== NO_LABEL
|| map
->label
== me
->map
.label
))
796 lde_map_del(ln
, me
, 1);
798 /* LRl.3: first check if we have a pending withdraw running */
799 lw
= (struct lde_wdraw
*)fec_find(&ln
->sent_wdraw
, &fn
->fec
);
800 if (lw
&& (map
->label
== NO_LABEL
|| map
->label
== lw
->label
)) {
801 /* LRl.4: delete record of outstanding lbl withdraw */
802 lde_wdraw_del(ln
, lw
);
804 /* send pending label mapping if any */
805 pending_map
= fec_find(&ln
->sent_map_pending
, &fn
->fec
);
807 lde_send_labelmapping(ln
, fn
, 1);
808 lde_map_pending_del(ln
, pending_map
);
813 * LRl.11 - 13 are unnecessary since we remove the label from
814 * forwarding/switching as soon as the FEC is unreachable.
820 lde_check_withdraw(struct map
*map
, struct lde_nbr
*ln
)
827 struct lde_nbr
*lnbr
;
829 /* wildcard label withdraw */
830 if (map
->type
== MAP_TYPE_WILDCARD
||
831 map
->type
== MAP_TYPE_TYPED_WCARD
||
832 (map
->type
== MAP_TYPE_PWID
&& !(map
->flags
& F_MAP_PW_ID
))) {
833 lde_check_withdraw_wcard(map
, ln
);
837 lde_map2fec(map
, ln
->id
, &fec
);
838 fn
= (struct fec_node
*)fec_find(&ft
, &fec
);
842 /* LWd.1: remove label from forwarding/switching use */
843 LIST_FOREACH(fnh
, &fn
->nexthops
, entry
) {
847 if (!lde_address_find(ln
, fnh
->af
, &fnh
->nexthop
))
851 pw
= (struct l2vpn_pw
*) fn
->data
;
854 pw
->remote_status
= PW_NOT_FORWARDING
;
859 if (map
->label
!= NO_LABEL
&& map
->label
!= fnh
->remote_label
)
862 lde_send_delete_klabel(fn
, fnh
);
863 fnh
->remote_label
= NO_LABEL
;
866 /* Update RLFA clients. */
867 lde_rlfa_update_clients(&fec
, ln
, MPLS_INVALID_LABEL
);
869 /* LWd.2: send label release */
870 lde_send_labelrelease(ln
, fn
, NULL
, map
->label
);
872 /* LWd.3: check previously received label mapping */
873 me
= (struct lde_map
*)fec_find(&ln
->recv_map
, &fn
->fec
);
874 if (me
&& (map
->label
== NO_LABEL
|| map
->label
== me
->map
.label
))
875 /* LWd.4: remove record of previously received lbl mapping */
876 lde_map_del(ln
, me
, 0);
881 /* Ordered Control: additional withdraw steps */
882 if (ldeconf
->flags
& F_LDPD_ORDERED_CONTROL
) {
883 /* LWd.8: for each neighbor other that src of withdraw msg */
884 RB_FOREACH(lnbr
, nbr_tree
, &lde_nbrs
) {
885 if (ln
->peerid
== lnbr
->peerid
)
888 /* LWd.9: check if previously sent a label mapping */
889 me
= (struct lde_map
*)fec_find(&lnbr
->sent_map
,
893 * LWd.10: does label sent to peer "map" to withdraw
896 if (me
&& lde_nbr_is_nexthop(fn
, lnbr
))
897 /* LWd.11: send label withdraw */
898 lde_send_labelwithdraw(lnbr
, fn
, NULL
, NULL
);
905 lde_check_withdraw_wcard(struct map
*map
, struct lde_nbr
*ln
)
912 struct lde_nbr
*lnbr
;
914 /* LWd.2: send label release */
915 lde_send_labelrelease(ln
, NULL
, map
, map
->label
);
917 RB_FOREACH(f
, fec_tree
, &ft
) {
918 fn
= (struct fec_node
*)f
;
919 me
= (struct lde_map
*)fec_find(&ln
->recv_map
, &fn
->fec
);
921 if (lde_wildcard_apply(map
, &fn
->fec
, me
) == 0)
924 /* LWd.1: remove label from forwarding/switching use */
925 LIST_FOREACH(fnh
, &fn
->nexthops
, entry
) {
929 if (!lde_address_find(ln
, fnh
->af
,
934 if (f
->u
.pwid
.lsr_id
.s_addr
!= ln
->id
.s_addr
)
936 pw
= (struct l2vpn_pw
*) fn
->data
;
938 pw
->remote_status
= PW_NOT_FORWARDING
;
943 if (map
->label
!= NO_LABEL
&& map
->label
!=
947 lde_send_delete_klabel(fn
, fnh
);
948 fnh
->remote_label
= NO_LABEL
;
951 /* Update RLFA clients. */
952 lde_rlfa_update_clients(f
, ln
, MPLS_INVALID_LABEL
);
954 /* LWd.3: check previously received label mapping */
955 if (me
&& (map
->label
== NO_LABEL
||
956 map
->label
== me
->map
.label
))
958 * LWd.4: remove record of previously received
961 lde_map_del(ln
, me
, 0);
966 /* Ordered Control: additional withdraw steps */
967 if (ldeconf
->flags
& F_LDPD_ORDERED_CONTROL
) {
969 * LWd.8: for each neighbor other that src of
972 RB_FOREACH(lnbr
, nbr_tree
, &lde_nbrs
) {
973 if (ln
->peerid
== lnbr
->peerid
)
976 /* LWd.9: check if previously sent a label
979 me
= (struct lde_map
*)fec_find(
980 &lnbr
->sent_map
, &fn
->fec
);
982 * LWd.10: does label sent to peer "map" to
985 if (me
&& lde_nbr_is_nexthop(fn
, lnbr
))
986 /* LWd.11: send label withdraw */
987 lde_send_labelwithdraw(lnbr
, fn
, NULL
,
995 lde_wildcard_apply(struct map
*wcard
, struct fec
*fec
, struct lde_map
*me
)
997 switch (wcard
->type
) {
998 case MAP_TYPE_WILDCARD
:
1001 case MAP_TYPE_TYPED_WCARD
:
1002 switch (wcard
->fec
.twcard
.type
) {
1003 case MAP_TYPE_PREFIX
:
1004 if (wcard
->fec
.twcard
.u
.prefix_af
== AF_INET
&&
1005 fec
->type
!= FEC_TYPE_IPV4
)
1007 if (wcard
->fec
.twcard
.u
.prefix_af
== AF_INET6
&&
1008 fec
->type
!= FEC_TYPE_IPV6
)
1012 if (fec
->type
!= FEC_TYPE_PWID
)
1014 if (wcard
->fec
.twcard
.u
.pw_type
!= PW_TYPE_WILDCARD
&&
1015 wcard
->fec
.twcard
.u
.pw_type
!= fec
->u
.pwid
.type
)
1019 fatalx("lde_wildcard_apply: unexpected fec type");
1023 /* RFC4447 pw-id group wildcard */
1024 if (fec
->type
!= FEC_TYPE_PWID
)
1026 if (fec
->u
.pwid
.type
!= wcard
->fec
.pwid
.type
)
1028 if (me
== NULL
|| (me
->map
.fec
.pwid
.group_id
!=
1029 wcard
->fec
.pwid
.group_id
))
1033 fatalx("lde_wildcard_apply: unexpected fec type");
1037 /* gabage collector timer: timer to remove dead entries from the LIB */
1041 lde_gc_timer(struct thread
*thread
)
1043 struct fec
*fec
, *safe
;
1044 struct fec_node
*fn
;
1047 RB_FOREACH_SAFE(fec
, fec_tree
, &ft
, safe
) {
1048 fn
= (struct fec_node
*) fec
;
1050 if (!LIST_EMPTY(&fn
->nexthops
) ||
1051 !RB_EMPTY(lde_map_head
, &fn
->downstream
) ||
1052 !RB_EMPTY(lde_map_head
, &fn
->upstream
))
1055 if (fn
->local_label
!= NO_LABEL
)
1056 lde_free_label(fn
->local_label
);
1058 fec_remove(&ft
, &fn
->fec
);
1064 log_debug("%s: %u entries removed", __func__
, count
);
1066 lde_gc_start_timer();
1072 lde_gc_start_timer(void)
1074 thread_cancel(&gc_timer
);
1076 thread_add_timer(master
, lde_gc_timer
, NULL
, LDE_GC_INTERVAL
,
1081 lde_gc_stop_timer(void)
1083 thread_cancel(&gc_timer
);