]>
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.
28 static __inline
int fec_compare(const struct fec
*, const struct fec
*);
29 static int lde_nbr_is_nexthop(struct fec_node
*,
31 static void fec_free(void *);
32 static struct fec_node
*fec_add(struct fec
*fec
);
33 static struct fec_nh
*fec_nh_add(struct fec_node
*, int, union ldpd_addr
*,
35 static void fec_nh_del(struct fec_nh
*);
37 RB_GENERATE(fec_tree
, fec
, entry
, fec_compare
)
39 struct fec_tree ft
= RB_INITIALIZER(&ft
);
40 struct thread
*gc_timer
;
42 /* FEC tree functions */
44 fec_init(struct fec_tree
*fh
)
46 RB_INIT(fec_tree
, fh
);
50 fec_compare(const struct fec
*a
, const struct fec
*b
)
52 if (a
->type
< b
->type
)
54 if (a
->type
> b
->type
)
59 if (ntohl(a
->u
.ipv4
.prefix
.s_addr
) <
60 ntohl(b
->u
.ipv4
.prefix
.s_addr
))
62 if (ntohl(a
->u
.ipv4
.prefix
.s_addr
) >
63 ntohl(b
->u
.ipv4
.prefix
.s_addr
))
65 if (a
->u
.ipv4
.prefixlen
< b
->u
.ipv4
.prefixlen
)
67 if (a
->u
.ipv4
.prefixlen
> b
->u
.ipv4
.prefixlen
)
71 if (memcmp(&a
->u
.ipv6
.prefix
, &b
->u
.ipv6
.prefix
,
72 sizeof(struct in6_addr
)) < 0)
74 if (memcmp(&a
->u
.ipv6
.prefix
, &b
->u
.ipv6
.prefix
,
75 sizeof(struct in6_addr
)) > 0)
77 if (a
->u
.ipv6
.prefixlen
< b
->u
.ipv6
.prefixlen
)
79 if (a
->u
.ipv6
.prefixlen
> b
->u
.ipv6
.prefixlen
)
83 if (a
->u
.pwid
.type
< b
->u
.pwid
.type
)
85 if (a
->u
.pwid
.type
> b
->u
.pwid
.type
)
87 if (a
->u
.pwid
.pwid
< b
->u
.pwid
.pwid
)
89 if (a
->u
.pwid
.pwid
> b
->u
.pwid
.pwid
)
91 if (ntohl(a
->u
.pwid
.lsr_id
.s_addr
) <
92 ntohl(b
->u
.pwid
.lsr_id
.s_addr
))
94 if (ntohl(a
->u
.pwid
.lsr_id
.s_addr
) >
95 ntohl(b
->u
.pwid
.lsr_id
.s_addr
))
104 fec_find(struct fec_tree
*fh
, struct fec
*f
)
106 return (RB_FIND(fec_tree
, fh
, f
));
110 fec_insert(struct fec_tree
*fh
, struct fec
*f
)
112 if (RB_INSERT(fec_tree
, fh
, f
) != NULL
)
118 fec_remove(struct fec_tree
*fh
, struct fec
*f
)
120 if (RB_REMOVE(fec_tree
, fh
, f
) == NULL
) {
121 log_warnx("%s failed for %s", __func__
, log_fec(f
));
128 fec_clear(struct fec_tree
*fh
, void (*free_cb
)(void *))
132 while (!RB_EMPTY(fec_tree
, fh
)) {
133 f
= RB_ROOT(fec_tree
, fh
);
140 /* routing table functions */
142 lde_nbr_is_nexthop(struct fec_node
*fn
, struct lde_nbr
*ln
)
146 LIST_FOREACH(fnh
, &fn
->nexthops
, entry
)
147 if (lde_address_find(ln
, fnh
->af
, &fnh
->nexthop
))
159 static struct ctl_rt rtctl
;
161 RB_FOREACH(f
, fec_tree
, &ft
) {
162 fn
= (struct fec_node
*)f
;
163 if (fn
->local_label
== NO_LABEL
&&
164 RB_EMPTY(lde_map_head
, &fn
->downstream
))
167 memset(&rtctl
, 0, sizeof(rtctl
));
168 switch (fn
->fec
.type
) {
171 rtctl
.prefix
.v4
= fn
->fec
.u
.ipv4
.prefix
;
172 rtctl
.prefixlen
= fn
->fec
.u
.ipv4
.prefixlen
;
176 rtctl
.prefix
.v6
= fn
->fec
.u
.ipv6
.prefix
;
177 rtctl
.prefixlen
= fn
->fec
.u
.ipv6
.prefixlen
;
183 rtctl
.local_label
= fn
->local_label
;
184 if (RB_EMPTY(lde_map_head
, &fn
->downstream
)) {
186 rtctl
.nexthop
.s_addr
= INADDR_ANY
;
187 rtctl
.remote_label
= NO_LABEL
;
188 rtctl
.no_downstream
= 1;
190 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB_BEGIN
, 0, pid
, &rtctl
,
193 RB_FOREACH(me
, lde_map_head
, &fn
->upstream
) {
194 rtctl
.nexthop
= me
->nexthop
->id
;
195 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB_SENT
, 0, pid
,
196 &rtctl
, sizeof(rtctl
));
199 RB_FOREACH(me
, lde_map_head
, &fn
->downstream
) {
200 rtctl
.in_use
= lde_nbr_is_nexthop(fn
, me
->nexthop
);
201 rtctl
.nexthop
= me
->nexthop
->id
;
202 rtctl
.remote_label
= me
->map
.label
;
203 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB_RCVD
, 0, pid
,
204 &rtctl
, sizeof(rtctl
));
206 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB_END
, 0, pid
, &rtctl
,
212 fec_snap(struct lde_nbr
*ln
)
217 RB_FOREACH(f
, fec_tree
, &ft
) {
218 fn
= (struct fec_node
*)f
;
219 if (fn
->local_label
== NO_LABEL
)
222 lde_send_labelmapping(ln
, fn
, 0);
225 lde_imsg_compose_ldpe(IMSG_MAPPING_ADD_END
, ln
->peerid
, 0, NULL
, 0);
231 struct fec_node
*fn
= arg
;
234 while ((fnh
= LIST_FIRST(&fn
->nexthops
))) {
236 assert(fnh
!= LIST_FIRST(&fn
->nexthops
));
238 if (!RB_EMPTY(lde_map_head
, &fn
->downstream
))
239 log_warnx("%s: fec %s downstream list not empty", __func__
,
241 if (!RB_EMPTY(lde_map_head
, &fn
->upstream
))
242 log_warnx("%s: fec %s upstream list not empty", __func__
,
251 fec_clear(&ft
, fec_free
);
254 static struct fec_node
*
255 fec_add(struct fec
*fec
)
259 fn
= calloc(1, sizeof(*fn
));
264 fn
->local_label
= NO_LABEL
;
265 RB_INIT(lde_map_head
, &fn
->upstream
);
266 RB_INIT(lde_map_head
, &fn
->downstream
);
267 LIST_INIT(&fn
->nexthops
);
269 if (fec_insert(&ft
, &fn
->fec
))
270 log_warnx("failed to add %s to ft tree",
277 fec_nh_find(struct fec_node
*fn
, int af
, union ldpd_addr
*nexthop
,
278 ifindex_t ifindex
, uint8_t priority
)
282 LIST_FOREACH(fnh
, &fn
->nexthops
, entry
)
284 ldp_addrcmp(af
, &fnh
->nexthop
, nexthop
) == 0 &&
285 fnh
->ifindex
== ifindex
&&
286 fnh
->priority
== priority
)
292 static struct fec_nh
*
293 fec_nh_add(struct fec_node
*fn
, int af
, union ldpd_addr
*nexthop
,
294 ifindex_t ifindex
, uint8_t priority
)
298 fnh
= calloc(1, sizeof(*fnh
));
303 fnh
->nexthop
= *nexthop
;
304 fnh
->ifindex
= ifindex
;
305 fnh
->remote_label
= NO_LABEL
;
306 fnh
->priority
= priority
;
307 LIST_INSERT_HEAD(&fn
->nexthops
, fnh
, entry
);
313 fec_nh_del(struct fec_nh
*fnh
)
315 LIST_REMOVE(fnh
, entry
);
320 lde_kernel_insert(struct fec
*fec
, int af
, union ldpd_addr
*nexthop
,
321 ifindex_t ifindex
, uint8_t priority
, int connected
, void *data
)
326 fn
= (struct fec_node
*)fec_find(&ft
, fec
);
332 fnh
= fec_nh_find(fn
, af
, nexthop
, ifindex
, priority
);
334 fnh
= fec_nh_add(fn
, af
, nexthop
, ifindex
, priority
);
335 fnh
->flags
|= F_FEC_NH_NEW
;
337 fnh
->flags
|= F_FEC_NH_CONNECTED
;
341 lde_kernel_remove(struct fec
*fec
, int af
, union ldpd_addr
*nexthop
,
342 ifindex_t ifindex
, uint8_t priority
)
347 fn
= (struct fec_node
*)fec_find(&ft
, fec
);
351 fnh
= fec_nh_find(fn
, af
, nexthop
, ifindex
, priority
);
356 lde_send_delete_klabel(fn
, fnh
);
361 * Whenever a route is changed, zebra advertises its new version without
362 * withdrawing the old one. So, after processing a ZEBRA_REDISTRIBUTE_IPV[46]_ADD
363 * message, we need to check for nexthops that were removed and, for each of
364 * them (if any), withdraw the associated labels from zebra.
367 lde_kernel_update(struct fec
*fec
)
370 struct fec_nh
*fnh
, *safe
;
374 fn
= (struct fec_node
*)fec_find(&ft
, fec
);
378 LIST_FOREACH_SAFE(fnh
, &fn
->nexthops
, entry
, safe
) {
379 if (fnh
->flags
& F_FEC_NH_NEW
)
380 fnh
->flags
&= ~F_FEC_NH_NEW
;
382 lde_send_delete_klabel(fn
, fnh
);
387 if (LIST_EMPTY(&fn
->nexthops
)) {
388 RB_FOREACH(ln
, nbr_tree
, &lde_nbrs
)
389 lde_send_labelwithdraw(ln
, fn
, NULL
, NULL
);
393 * Do not deallocate the local label now, do that only in the
394 * LIB garbage collector. This will prevent ldpd from changing
395 * the input label of some prefixes too often when running on
396 * an unstable network. Also, restart the garbage collector
397 * timer so that labels are deallocated only when the network
400 lde_gc_start_timer();
402 fn
->local_label
= lde_update_label(fn
);
403 if (fn
->local_label
!= NO_LABEL
)
404 /* FEC.1: perform lsr label distribution procedure */
405 RB_FOREACH(ln
, nbr_tree
, &lde_nbrs
)
406 lde_send_labelmapping(ln
, fn
, 1);
409 LIST_FOREACH(fnh
, &fn
->nexthops
, entry
) {
410 lde_send_change_klabel(fn
, fnh
);
412 switch (fn
->fec
.type
) {
415 ln
= lde_nbr_find_by_addr(fnh
->af
, &fnh
->nexthop
);
418 ln
= lde_nbr_find_by_lsrid(fn
->fec
.u
.pwid
.lsr_id
);
427 me
= (struct lde_map
*)fec_find(&ln
->recv_map
, &fn
->fec
);
430 lde_check_mapping(&me
->map
, ln
);
436 lde_check_mapping(struct map
*map
, struct lde_nbr
*ln
)
445 lde_map2fec(map
, ln
->id
, &fec
);
449 if (lde_acl_check(ldeconf
->ipv4
.acl_label_accept_from
,
450 AF_INET
, (union ldpd_addr
*)&ln
->id
, 32) != FILTER_PERMIT
)
452 if (lde_acl_check(ldeconf
->ipv4
.acl_label_accept_for
,
453 AF_INET
, (union ldpd_addr
*)&fec
.u
.ipv4
.prefix
,
454 fec
.u
.ipv4
.prefixlen
) != FILTER_PERMIT
)
458 if (lde_acl_check(ldeconf
->ipv6
.acl_label_accept_from
,
459 AF_INET
, (union ldpd_addr
*)&ln
->id
, 32) != FILTER_PERMIT
)
461 if (lde_acl_check(ldeconf
->ipv6
.acl_label_accept_for
,
462 AF_INET6
, (union ldpd_addr
*)&fec
.u
.ipv6
.prefix
,
463 fec
.u
.ipv6
.prefixlen
) != FILTER_PERMIT
)
470 fn
= (struct fec_node
*)fec_find(&ft
, &fec
);
474 /* LMp.1: first check if we have a pending request running */
475 lre
= (struct lde_req
*)fec_find(&ln
->sent_req
, &fn
->fec
);
477 /* LMp.2: delete record of outstanding label request */
478 lde_req_del(ln
, lre
, 1);
480 /* RFC 4447 control word and status tlv negotiation */
481 if (map
->type
== MAP_TYPE_PWID
&& l2vpn_pw_negotiate(ln
, fn
, map
))
485 * LMp.3 - LMp.8: loop detection - unnecessary for frame-mode
490 me
= (struct lde_map
*)fec_find(&ln
->recv_map
, &fn
->fec
);
493 if (me
->map
.label
!= map
->label
&& lre
== NULL
) {
495 lde_send_labelrelease(ln
, fn
, NULL
, me
->map
.label
);
498 * Can not use lde_nbr_find_by_addr() because there's
499 * the possibility of multipath.
501 LIST_FOREACH(fnh
, &fn
->nexthops
, entry
) {
502 if (lde_address_find(ln
, fnh
->af
,
503 &fnh
->nexthop
) == NULL
)
506 lde_send_delete_klabel(fn
, fnh
);
507 fnh
->remote_label
= NO_LABEL
;
513 * LMp.11 - 12: consider multiple nexthops in order to
516 LIST_FOREACH(fnh
, &fn
->nexthops
, entry
) {
517 /* LMp.15: install FEC in FIB */
521 if (!lde_address_find(ln
, fnh
->af
, &fnh
->nexthop
))
524 fnh
->remote_label
= map
->label
;
525 lde_send_change_klabel(fn
, fnh
);
528 pw
= (struct l2vpn_pw
*) fn
->data
;
532 pw
->remote_group
= map
->fec
.pwid
.group_id
;
533 if (map
->flags
& F_MAP_PW_IFMTU
)
534 pw
->remote_mtu
= map
->fec
.pwid
.ifmtu
;
535 if (map
->flags
& F_MAP_PW_STATUS
)
536 pw
->remote_status
= map
->pw_status
;
538 pw
->remote_status
= PW_FORWARDING
;
539 fnh
->remote_label
= map
->label
;
540 if (l2vpn_pw_ok(pw
, fnh
))
541 lde_send_change_klabel(fn
, fnh
);
547 /* LMp.13 & LMp.16: Record the mapping from this peer */
549 me
= lde_map_add(ln
, fn
, 0);
553 * LMp.17 - LMp.27 are unnecessary since we don't need to implement
554 * loop detection. LMp.28 - LMp.30 are unnecessary because we are
560 lde_check_request(struct map
*map
, struct lde_nbr
*ln
)
567 /* wildcard label request */
568 if (map
->type
== MAP_TYPE_TYPED_WCARD
) {
569 lde_check_request_wcard(map
, ln
);
573 /* LRq.1: skip loop detection (not necessary) */
575 /* LRq.2: is there a next hop for fec? */
576 lde_map2fec(map
, ln
->id
, &fec
);
577 fn
= (struct fec_node
*)fec_find(&ft
, &fec
);
578 if (fn
== NULL
|| LIST_EMPTY(&fn
->nexthops
)) {
579 /* LRq.5: send No Route notification */
580 lde_send_notification(ln
, S_NO_ROUTE
, map
->msg_id
,
581 htons(MSG_TYPE_LABELREQUEST
));
585 /* LRq.3: is MsgSource the next hop? */
586 LIST_FOREACH(fnh
, &fn
->nexthops
, entry
) {
590 if (!lde_address_find(ln
, fnh
->af
, &fnh
->nexthop
))
593 /* LRq.4: send Loop Detected notification */
594 lde_send_notification(ln
, S_LOOP_DETECTED
, map
->msg_id
,
595 htons(MSG_TYPE_LABELREQUEST
));
602 /* LRq.6: first check if we have a pending request running */
603 lre
= (struct lde_req
*)fec_find(&ln
->recv_req
, &fn
->fec
);
605 /* LRq.7: duplicate request */
608 /* LRq.8: record label request */
609 lre
= lde_req_add(ln
, &fn
->fec
, 0);
611 lre
->msg_id
= ntohl(map
->msg_id
);
613 /* LRq.9: perform LSR label distribution */
614 lde_send_labelmapping(ln
, fn
, 1);
617 * LRq.10: do nothing (Request Never) since we use liberal
619 * LRq.11 - 12 are unnecessary since we are merging capable.
624 lde_check_request_wcard(struct map
*map
, struct lde_nbr
*ln
)
630 RB_FOREACH(f
, fec_tree
, &ft
) {
631 fn
= (struct fec_node
*)f
;
633 /* only a typed wildcard is possible here */
634 if (lde_wildcard_apply(map
, &fn
->fec
, NULL
) == 0)
637 /* LRq.2: is there a next hop for fec? */
638 if (LIST_EMPTY(&fn
->nexthops
))
641 /* LRq.6: first check if we have a pending request running */
642 lre
= (struct lde_req
*)fec_find(&ln
->recv_req
, &fn
->fec
);
644 /* LRq.7: duplicate request */
647 /* LRq.8: record label request */
648 lre
= lde_req_add(ln
, &fn
->fec
, 0);
650 lre
->msg_id
= ntohl(map
->msg_id
);
652 /* LRq.9: perform LSR label distribution */
653 lde_send_labelmapping(ln
, fn
, 1);
658 lde_check_release(struct map
*map
, struct lde_nbr
*ln
)
662 struct lde_wdraw
*lw
;
664 struct fec
*pending_map
;
666 /* wildcard label release */
667 if (map
->type
== MAP_TYPE_WILDCARD
||
668 map
->type
== MAP_TYPE_TYPED_WCARD
||
669 (map
->type
== MAP_TYPE_PWID
&& !(map
->flags
& F_MAP_PW_ID
))) {
670 lde_check_release_wcard(map
, ln
);
674 lde_map2fec(map
, ln
->id
, &fec
);
675 fn
= (struct fec_node
*)fec_find(&ft
, &fec
);
676 /* LRl.1: does FEC match a known FEC? */
680 /* LRl.6: check sent map list and remove it if available */
681 me
= (struct lde_map
*)fec_find(&ln
->sent_map
, &fn
->fec
);
682 if (me
&& (map
->label
== NO_LABEL
|| map
->label
== me
->map
.label
))
683 lde_map_del(ln
, me
, 1);
685 /* LRl.3: first check if we have a pending withdraw running */
686 lw
= (struct lde_wdraw
*)fec_find(&ln
->sent_wdraw
, &fn
->fec
);
687 if (lw
&& (map
->label
== NO_LABEL
|| map
->label
== lw
->label
)) {
688 /* LRl.4: delete record of outstanding label withdraw */
689 lde_wdraw_del(ln
, lw
);
691 /* send pending label mapping if any */
692 pending_map
= fec_find(&ln
->sent_map_pending
, &fn
->fec
);
694 lde_send_labelmapping(ln
, fn
, 1);
695 lde_map_pending_del(ln
, pending_map
);
700 * LRl.11 - 13 are unnecessary since we remove the label from
701 * forwarding/switching as soon as the FEC is unreachable.
706 lde_check_release_wcard(struct map
*map
, struct lde_nbr
*ln
)
710 struct lde_wdraw
*lw
;
712 struct fec
*pending_map
;
714 RB_FOREACH(f
, fec_tree
, &ft
) {
715 fn
= (struct fec_node
*)f
;
716 me
= (struct lde_map
*)fec_find(&ln
->sent_map
, &fn
->fec
);
718 /* LRl.1: does FEC match a known FEC? */
719 if (lde_wildcard_apply(map
, &fn
->fec
, me
) == 0)
722 /* LRl.6: check sent map list and remove it if available */
724 (map
->label
== NO_LABEL
|| map
->label
== me
->map
.label
))
725 lde_map_del(ln
, me
, 1);
727 /* LRl.3: first check if we have a pending withdraw running */
728 lw
= (struct lde_wdraw
*)fec_find(&ln
->sent_wdraw
, &fn
->fec
);
729 if (lw
&& (map
->label
== NO_LABEL
|| map
->label
== lw
->label
)) {
730 /* LRl.4: delete record of outstanding lbl withdraw */
731 lde_wdraw_del(ln
, lw
);
733 /* send pending label mapping if any */
734 pending_map
= fec_find(&ln
->sent_map_pending
, &fn
->fec
);
736 lde_send_labelmapping(ln
, fn
, 1);
737 lde_map_pending_del(ln
, pending_map
);
742 * LRl.11 - 13 are unnecessary since we remove the label from
743 * forwarding/switching as soon as the FEC is unreachable.
749 lde_check_withdraw(struct map
*map
, struct lde_nbr
*ln
)
757 /* wildcard label withdraw */
758 if (map
->type
== MAP_TYPE_WILDCARD
||
759 map
->type
== MAP_TYPE_TYPED_WCARD
||
760 (map
->type
== MAP_TYPE_PWID
&& !(map
->flags
& F_MAP_PW_ID
))) {
761 lde_check_withdraw_wcard(map
, ln
);
765 lde_map2fec(map
, ln
->id
, &fec
);
766 fn
= (struct fec_node
*)fec_find(&ft
, &fec
);
770 /* LWd.1: remove label from forwarding/switching use */
771 LIST_FOREACH(fnh
, &fn
->nexthops
, entry
) {
775 if (!lde_address_find(ln
, fnh
->af
, &fnh
->nexthop
))
779 pw
= (struct l2vpn_pw
*) fn
->data
;
782 pw
->remote_status
= PW_NOT_FORWARDING
;
787 if (map
->label
!= NO_LABEL
&& map
->label
!= fnh
->remote_label
)
790 lde_send_delete_klabel(fn
, fnh
);
791 fnh
->remote_label
= NO_LABEL
;
794 /* LWd.2: send label release */
795 lde_send_labelrelease(ln
, fn
, NULL
, map
->label
);
797 /* LWd.3: check previously received label mapping */
798 me
= (struct lde_map
*)fec_find(&ln
->recv_map
, &fn
->fec
);
799 if (me
&& (map
->label
== NO_LABEL
|| map
->label
== me
->map
.label
))
800 /* LWd.4: remove record of previously received lbl mapping */
801 lde_map_del(ln
, me
, 0);
805 lde_check_withdraw_wcard(struct map
*map
, struct lde_nbr
*ln
)
813 /* LWd.2: send label release */
814 lde_send_labelrelease(ln
, NULL
, map
, map
->label
);
816 RB_FOREACH(f
, fec_tree
, &ft
) {
817 fn
= (struct fec_node
*)f
;
818 me
= (struct lde_map
*)fec_find(&ln
->recv_map
, &fn
->fec
);
820 if (lde_wildcard_apply(map
, &fn
->fec
, me
) == 0)
823 /* LWd.1: remove label from forwarding/switching use */
824 LIST_FOREACH(fnh
, &fn
->nexthops
, entry
) {
828 if (!lde_address_find(ln
, fnh
->af
,
833 if (f
->u
.pwid
.lsr_id
.s_addr
!= ln
->id
.s_addr
)
835 pw
= (struct l2vpn_pw
*) fn
->data
;
837 pw
->remote_status
= PW_NOT_FORWARDING
;
842 if (map
->label
!= NO_LABEL
&& map
->label
!=
846 lde_send_delete_klabel(fn
, fnh
);
847 fnh
->remote_label
= NO_LABEL
;
850 /* LWd.3: check previously received label mapping */
851 if (me
&& (map
->label
== NO_LABEL
||
852 map
->label
== me
->map
.label
))
854 * LWd.4: remove record of previously received
857 lde_map_del(ln
, me
, 0);
862 lde_wildcard_apply(struct map
*wcard
, struct fec
*fec
, struct lde_map
*me
)
864 switch (wcard
->type
) {
865 case MAP_TYPE_WILDCARD
:
868 case MAP_TYPE_TYPED_WCARD
:
869 switch (wcard
->fec
.twcard
.type
) {
870 case MAP_TYPE_PREFIX
:
871 if (wcard
->fec
.twcard
.u
.prefix_af
== AF_INET
&&
872 fec
->type
!= FEC_TYPE_IPV4
)
874 if (wcard
->fec
.twcard
.u
.prefix_af
== AF_INET6
&&
875 fec
->type
!= FEC_TYPE_IPV6
)
879 if (fec
->type
!= FEC_TYPE_PWID
)
881 if (wcard
->fec
.twcard
.u
.pw_type
!= PW_TYPE_WILDCARD
&&
882 wcard
->fec
.twcard
.u
.pw_type
!= fec
->u
.pwid
.type
)
886 fatalx("lde_wildcard_apply: unexpected fec type");
890 /* RFC4447 pw-id group wildcard */
891 if (fec
->type
!= FEC_TYPE_PWID
)
893 if (fec
->u
.pwid
.type
!= wcard
->fec
.pwid
.type
)
895 if (me
== NULL
|| (me
->map
.fec
.pwid
.group_id
!=
896 wcard
->fec
.pwid
.group_id
))
900 fatalx("lde_wildcard_apply: unexpected fec type");
904 /* gabage collector timer: timer to remove dead entries from the LIB */
908 lde_gc_timer(struct thread
*thread
)
910 struct fec
*fec
, *safe
;
914 RB_FOREACH_SAFE(fec
, fec_tree
, &ft
, safe
) {
915 fn
= (struct fec_node
*) fec
;
917 if (!LIST_EMPTY(&fn
->nexthops
) ||
918 !RB_EMPTY(lde_map_head
, &fn
->downstream
) ||
919 !RB_EMPTY(lde_map_head
, &fn
->upstream
))
922 if (fn
->local_label
!= NO_LABEL
)
923 lde_free_label(fn
->local_label
);
925 fec_remove(&ft
, &fn
->fec
);
931 log_debug("%s: %u entries removed", __func__
, count
);
933 lde_gc_start_timer();
939 lde_gc_start_timer(void)
941 THREAD_TIMER_OFF(gc_timer
);
943 thread_add_timer(master
, lde_gc_timer
, NULL
, LDE_GC_INTERVAL
,
948 lde_gc_stop_timer(void)
950 THREAD_TIMER_OFF(gc_timer
);