]>
git.proxmox.com Git - mirror_frr.git/blob - ldpd/lde_lib.c
1 // SPDX-License-Identifier: ISC
5 * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
6 * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
19 static __inline
int fec_compare(const struct fec
*, const struct fec
*);
20 static int lde_nbr_is_nexthop(struct fec_node
*, struct lde_nbr
*);
21 static void fec_free(void *);
22 static struct fec_node
*fec_add(struct fec
*fec
);
23 static struct fec_nh
*fec_nh_add(struct fec_node
*, int, union ldpd_addr
*,
24 ifindex_t
, uint8_t, unsigned short);
25 static void fec_nh_del(struct fec_nh
*);
27 RB_GENERATE(fec_tree
, fec
, entry
, fec_compare
)
29 struct fec_tree ft
= RB_INITIALIZER(&ft
);
30 struct event
*gc_timer
;
32 /* FEC tree functions */
34 fec_init(struct fec_tree
*fh
)
36 RB_INIT(fec_tree
, fh
);
40 fec_compare(const struct fec
*a
, const struct fec
*b
)
42 if (a
->type
< b
->type
)
44 if (a
->type
> b
->type
)
49 if (ntohl(a
->u
.ipv4
.prefix
.s_addr
) < ntohl(b
->u
.ipv4
.prefix
.s_addr
))
51 if (ntohl(a
->u
.ipv4
.prefix
.s_addr
) > ntohl(b
->u
.ipv4
.prefix
.s_addr
))
53 if (a
->u
.ipv4
.prefixlen
< b
->u
.ipv4
.prefixlen
)
55 if (a
->u
.ipv4
.prefixlen
> b
->u
.ipv4
.prefixlen
)
59 if (memcmp(&a
->u
.ipv6
.prefix
, &b
->u
.ipv6
.prefix
,
60 sizeof(struct in6_addr
)) < 0)
62 if (memcmp(&a
->u
.ipv6
.prefix
, &b
->u
.ipv6
.prefix
,
63 sizeof(struct in6_addr
)) > 0)
65 if (a
->u
.ipv6
.prefixlen
< b
->u
.ipv6
.prefixlen
)
67 if (a
->u
.ipv6
.prefixlen
> b
->u
.ipv6
.prefixlen
)
71 if (a
->u
.pwid
.type
< b
->u
.pwid
.type
)
73 if (a
->u
.pwid
.type
> b
->u
.pwid
.type
)
75 if (a
->u
.pwid
.pwid
< b
->u
.pwid
.pwid
)
77 if (a
->u
.pwid
.pwid
> b
->u
.pwid
.pwid
)
79 if (ntohl(a
->u
.pwid
.lsr_id
.s_addr
) < ntohl(b
->u
.pwid
.lsr_id
.s_addr
))
81 if (ntohl(a
->u
.pwid
.lsr_id
.s_addr
) > ntohl(b
->u
.pwid
.lsr_id
.s_addr
))
90 fec_find(struct fec_tree
*fh
, struct fec
*f
)
92 return (RB_FIND(fec_tree
, fh
, f
));
96 fec_insert(struct fec_tree
*fh
, struct fec
*f
)
98 if (RB_INSERT(fec_tree
, fh
, f
) != NULL
)
104 fec_remove(struct fec_tree
*fh
, struct fec
*f
)
106 if (RB_REMOVE(fec_tree
, fh
, f
) == NULL
) {
107 log_warnx("%s failed for %s", __func__
, log_fec(f
));
114 fec_clear(struct fec_tree
*fh
, void (*free_cb
)(void *))
118 while (!RB_EMPTY(fec_tree
, fh
)) {
119 f
= RB_ROOT(fec_tree
, fh
);
126 /* routing table functions */
128 lde_nbr_is_nexthop(struct fec_node
*fn
, struct lde_nbr
*ln
)
132 LIST_FOREACH(fnh
, &fn
->nexthops
, entry
)
133 if (lde_address_find(ln
, fnh
->af
, &fnh
->nexthop
))
145 static struct ctl_rt rtctl
;
147 RB_FOREACH(f
, fec_tree
, &ft
) {
148 fn
= (struct fec_node
*)f
;
149 if (fn
->local_label
== NO_LABEL
&&
150 RB_EMPTY(lde_map_head
, &fn
->downstream
))
153 memset(&rtctl
, 0, sizeof(rtctl
));
154 switch (fn
->fec
.type
) {
157 rtctl
.prefix
.v4
= fn
->fec
.u
.ipv4
.prefix
;
158 rtctl
.prefixlen
= fn
->fec
.u
.ipv4
.prefixlen
;
162 rtctl
.prefix
.v6
= fn
->fec
.u
.ipv6
.prefix
;
163 rtctl
.prefixlen
= fn
->fec
.u
.ipv6
.prefixlen
;
169 rtctl
.local_label
= fn
->local_label
;
170 if (RB_EMPTY(lde_map_head
, &fn
->downstream
)) {
172 rtctl
.nexthop
.s_addr
= INADDR_ANY
;
173 rtctl
.remote_label
= NO_LABEL
;
174 rtctl
.no_downstream
= 1;
176 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB_BEGIN
, 0, pid
, &rtctl
,
179 RB_FOREACH(me
, lde_map_head
, &fn
->upstream
) {
180 rtctl
.nexthop
= me
->nexthop
->id
;
181 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB_SENT
, 0, pid
,
182 &rtctl
, sizeof(rtctl
));
185 RB_FOREACH(me
, lde_map_head
, &fn
->downstream
) {
186 rtctl
.in_use
= lde_nbr_is_nexthop(fn
, me
->nexthop
);
187 rtctl
.nexthop
= me
->nexthop
->id
;
188 rtctl
.remote_label
= me
->map
.label
;
189 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB_RCVD
, 0, pid
,
190 &rtctl
, sizeof(rtctl
));
192 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB_END
, 0, pid
, &rtctl
,
198 fec_snap(struct lde_nbr
*ln
)
203 RB_FOREACH(f
, fec_tree
, &ft
) {
204 fn
= (struct fec_node
*)f
;
205 if (fn
->local_label
== NO_LABEL
)
208 lde_send_labelmapping(ln
, fn
, 0);
211 lde_imsg_compose_ldpe(IMSG_MAPPING_ADD_END
, ln
->peerid
, 0, NULL
, 0);
217 struct fec_node
*fn
= arg
;
220 while ((fnh
= LIST_FIRST(&fn
->nexthops
))) {
222 assert(fnh
!= LIST_FIRST(&fn
->nexthops
));
224 if (!RB_EMPTY(lde_map_head
, &fn
->downstream
))
225 log_warnx("%s: fec %s downstream list not empty", __func__
,
227 if (!RB_EMPTY(lde_map_head
, &fn
->upstream
))
228 log_warnx("%s: fec %s upstream list not empty", __func__
,
237 fec_clear(&ft
, fec_free
);
240 static struct fec_node
*
241 fec_add(struct fec
*fec
)
245 fn
= calloc(1, sizeof(*fn
));
250 fn
->local_label
= NO_LABEL
;
251 RB_INIT(lde_map_head
, &fn
->upstream
);
252 RB_INIT(lde_map_head
, &fn
->downstream
);
253 LIST_INIT(&fn
->nexthops
);
255 if (fec
->type
== FEC_TYPE_PWID
)
256 fn
->pw_remote_status
= PW_FORWARDING
;
258 if (fec_insert(&ft
, &fn
->fec
))
259 log_warnx("failed to add %s to ft tree", log_fec(&fn
->fec
));
265 fec_nh_find(struct fec_node
*fn
, int af
, union ldpd_addr
*nexthop
,
266 ifindex_t ifindex
, uint8_t route_type
, unsigned short route_instance
)
270 LIST_FOREACH(fnh
, &fn
->nexthops
, entry
)
272 ldp_addrcmp(af
, &fnh
->nexthop
, nexthop
) == 0 &&
273 fnh
->ifindex
== ifindex
&&
274 fnh
->route_type
== route_type
&&
275 fnh
->route_instance
== route_instance
)
281 static struct fec_nh
*
282 fec_nh_add(struct fec_node
*fn
, int af
, union ldpd_addr
*nexthop
,
283 ifindex_t ifindex
, uint8_t route_type
, unsigned short route_instance
)
287 fnh
= calloc(1, sizeof(*fnh
));
292 fnh
->nexthop
= *nexthop
;
293 fnh
->ifindex
= ifindex
;
294 fnh
->remote_label
= NO_LABEL
;
295 fnh
->route_type
= route_type
;
296 fnh
->route_instance
= route_instance
;
297 LIST_INSERT_HEAD(&fn
->nexthops
, fnh
, entry
);
303 fec_nh_del(struct fec_nh
*fnh
)
305 LIST_REMOVE(fnh
, entry
);
310 lde_kernel_insert(struct fec
*fec
, int af
, union ldpd_addr
*nexthop
,
311 ifindex_t ifindex
, uint8_t route_type
, unsigned short route_instance
,
312 int connected
, void *data
)
318 fn
= (struct fec_node
*)fec_find(&ft
, fec
);
324 fnh
= fec_nh_find(fn
, af
, nexthop
, ifindex
, route_type
, route_instance
);
326 fnh
= fec_nh_add(fn
, af
, nexthop
, ifindex
, route_type
,
329 * Ordered Control: if not a connected route and not a route
330 * learned over an interface not running LDP and not a PW
331 * then mark to wait until we receive labelmap msg before
332 * installing in kernel and sending to peer
334 iface
= if_lookup(ldeconf
, ifindex
);
335 if (CHECK_FLAG(ldeconf
->flags
, F_LDPD_ORDERED_CONTROL
) &&
336 !connected
&& iface
!= NULL
&& fec
->type
!= FEC_TYPE_PWID
)
337 SET_FLAG(fnh
->flags
, F_FEC_NH_DEFER
);
340 SET_FLAG(fnh
->flags
, F_FEC_NH_NEW
);
342 SET_FLAG(fnh
->flags
, F_FEC_NH_CONNECTED
);
346 lde_kernel_remove(struct fec
*fec
, int af
, union ldpd_addr
*nexthop
,
347 ifindex_t ifindex
, uint8_t route_type
, unsigned short route_instance
)
352 fn
= (struct fec_node
*)fec_find(&ft
, fec
);
356 fnh
= fec_nh_find(fn
, af
, nexthop
, ifindex
, route_type
, route_instance
);
361 lde_send_delete_klabel(fn
, fnh
);
366 * Whenever a route is changed, zebra advertises its new version without
367 * withdrawing the old one. So, after processing a ZEBRA_REDISTRIBUTE_IPV[46]_ADD
368 * message, we need to check for nexthops that were removed and, for each of
369 * them (if any), withdraw the associated labels from zebra.
372 lde_kernel_update(struct fec
*fec
)
375 struct fec_nh
*fnh
, *safe
;
380 fn
= (struct fec_node
*)fec_find(&ft
, fec
);
384 LIST_FOREACH_SAFE(fnh
, &fn
->nexthops
, entry
, safe
) {
385 if (CHECK_FLAG(fnh
->flags
, F_FEC_NH_NEW
)) {
386 UNSET_FLAG(fnh
->flags
, F_FEC_NH_NEW
);
388 * if LDP configured on interface or a static route
389 * clear flag else treat fec as a connected route
391 if (CHECK_FLAG(ldeconf
->flags
, F_LDPD_ENABLED
)) {
392 iface
= if_lookup(ldeconf
,fnh
->ifindex
);
393 if (CHECK_FLAG(fnh
->flags
, F_FEC_NH_CONNECTED
) ||
395 fnh
->route_type
== ZEBRA_ROUTE_STATIC
)
396 UNSET_FLAG(fnh
->flags
, F_FEC_NH_NO_LDP
);
398 SET_FLAG(fnh
->flags
, F_FEC_NH_NO_LDP
);
400 SET_FLAG(fnh
->flags
, F_FEC_NH_NO_LDP
);
402 lde_send_delete_klabel(fn
, fnh
);
407 if (LIST_EMPTY(&fn
->nexthops
)) {
408 RB_FOREACH(ln
, nbr_tree
, &lde_nbrs
)
409 lde_send_labelwithdraw(ln
, fn
, NULL
, NULL
);
413 * Do not deallocate the local label now, do that only in the
414 * LIB garbage collector. This will prevent ldpd from changing
415 * the input label of some prefixes too often when running on
416 * an unstable network. Also, restart the garbage collector
417 * timer so that labels are deallocated only when the network
420 lde_gc_start_timer();
422 fn
->local_label
= lde_update_label(fn
);
423 if (fn
->local_label
!= NO_LABEL
)
424 /* FEC.1: perform lsr label distribution procedure */
425 RB_FOREACH(ln
, nbr_tree
, &lde_nbrs
)
426 lde_send_labelmapping(ln
, fn
, 1);
429 /* if no label created yet then don't try to program labeled route */
430 if (fn
->local_label
== NO_LABEL
)
433 LIST_FOREACH(fnh
, &fn
->nexthops
, entry
) {
434 lde_send_change_klabel(fn
, fnh
);
436 switch (fn
->fec
.type
) {
439 ln
= lde_nbr_find_by_addr(fnh
->af
, &fnh
->nexthop
);
442 ln
= lde_nbr_find_by_lsrid(fn
->fec
.u
.pwid
.lsr_id
);
451 me
= (struct lde_map
*)fec_find(&ln
->recv_map
, &fn
->fec
);
454 lde_check_mapping(&me
->map
, ln
, 0);
460 lde_check_mapping(struct map
*map
, struct lde_nbr
*ln
, int rcvd_label_mapping
)
468 bool send_map
= false;
470 lde_map2fec(map
, ln
->id
, &fec
);
474 if (lde_acl_check(ldeconf
->ipv4
.acl_label_accept_from
,
475 AF_INET
, (union ldpd_addr
*)&ln
->id
, 32) != FILTER_PERMIT
)
477 if (lde_acl_check(ldeconf
->ipv4
.acl_label_accept_for
,
478 AF_INET
, (union ldpd_addr
*)&fec
.u
.ipv4
.prefix
,
479 fec
.u
.ipv4
.prefixlen
) != FILTER_PERMIT
)
483 if (lde_acl_check(ldeconf
->ipv6
.acl_label_accept_from
,
484 AF_INET
, (union ldpd_addr
*)&ln
->id
, 32) != FILTER_PERMIT
)
486 if (lde_acl_check(ldeconf
->ipv6
.acl_label_accept_for
,
487 AF_INET6
, (union ldpd_addr
*)&fec
.u
.ipv6
.prefix
,
488 fec
.u
.ipv6
.prefixlen
) != FILTER_PERMIT
)
495 fn
= (struct fec_node
*)fec_find(&ft
, &fec
);
499 /* LMp.1: first check if we have a pending request running */
500 lre
= (struct lde_req
*)fec_find(&ln
->sent_req
, &fn
->fec
);
502 /* LMp.2: delete record of outstanding label request */
503 lde_req_del(ln
, lre
, 1);
505 /* RFC 4447 control word and status tlv negotiation */
506 if (map
->type
== MAP_TYPE_PWID
&& l2vpn_pw_negotiate(ln
, fn
, map
)) {
507 if (rcvd_label_mapping
&& CHECK_FLAG(map
->flags
, F_MAP_PW_STATUS
))
508 fn
->pw_remote_status
= map
->pw_status
;
514 * LMp.3 - LMp.8: loop detection - unnecessary for frame-mode
519 me
= (struct lde_map
*)fec_find(&ln
->recv_map
, &fn
->fec
);
522 if (me
->map
.label
!= map
->label
&& lre
== NULL
) {
524 lde_send_labelrelease(ln
, fn
, NULL
, me
->map
.label
);
527 * Can not use lde_nbr_find_by_addr() because there's
528 * the possibility of multipath.
530 LIST_FOREACH(fnh
, &fn
->nexthops
, entry
) {
531 if (lde_address_find(ln
, fnh
->af
, &fnh
->nexthop
) == NULL
)
534 lde_send_delete_klabel(fn
, fnh
);
535 fnh
->remote_label
= NO_LABEL
;
541 * LMp.11 - 12: consider multiple nexthops in order to
544 LIST_FOREACH(fnh
, &fn
->nexthops
, entry
) {
545 /* LMp.15: install FEC in FIB */
549 if (!lde_address_find(ln
, fnh
->af
, &fnh
->nexthop
))
553 * Ordered Control: labelmap msg received from
554 * NH so clear flag and send labelmap msg to
557 if (CHECK_FLAG(ldeconf
->flags
, F_LDPD_ORDERED_CONTROL
)) {
559 UNSET_FLAG(fnh
->flags
, F_FEC_NH_DEFER
);
561 fnh
->remote_label
= map
->label
;
562 if (fn
->local_label
!= NO_LABEL
)
563 lde_send_change_klabel(fn
, fnh
);
566 pw
= (struct l2vpn_pw
*) fn
->data
;
570 pw
->remote_group
= map
->fec
.pwid
.group_id
;
571 if (CHECK_FLAG(map
->flags
, F_MAP_PW_IFMTU
))
572 pw
->remote_mtu
= map
->fec
.pwid
.ifmtu
;
573 if (rcvd_label_mapping
&& CHECK_FLAG(map
->flags
, F_MAP_PW_STATUS
)) {
574 pw
->remote_status
= map
->pw_status
;
575 fn
->pw_remote_status
= map
->pw_status
;
578 pw
->remote_status
= PW_FORWARDING
;
579 fnh
->remote_label
= map
->label
;
580 if (l2vpn_pw_ok(pw
, fnh
))
581 lde_send_change_klabel(fn
, fnh
);
588 /* Update RLFA clients. */
589 lde_rlfa_update_clients(&fec
, ln
, map
->label
);
591 /* LMp.13 & LMp.16: Record the mapping from this peer */
593 me
= lde_map_add(ln
, fn
, 0);
597 * LMp.17 - LMp.27 are unnecessary since we don't need to implement
598 * loop detection. LMp.28 - LMp.30 are unnecessary because we are
603 * Ordered Control: just received a labelmap for this fec from NH so
604 * need to send labelmap to all peers
605 * LMp.20 - LMp21 Execute procedure to send Label Mapping
607 if (send_map
&& fn
->local_label
!= NO_LABEL
)
608 RB_FOREACH(ln
, nbr_tree
, &lde_nbrs
)
609 lde_send_labelmapping(ln
, fn
, 1);
613 lde_check_request(struct map
*map
, struct lde_nbr
*ln
)
620 /* wildcard label request */
621 if (map
->type
== MAP_TYPE_TYPED_WCARD
) {
622 lde_check_request_wcard(map
, ln
);
626 /* LRq.1: skip loop detection (not necessary) */
628 /* LRq.2: is there a next hop for fec? */
629 lde_map2fec(map
, ln
->id
, &fec
);
630 fn
= (struct fec_node
*)fec_find(&ft
, &fec
);
631 if (fn
== NULL
|| LIST_EMPTY(&fn
->nexthops
)) {
632 /* LRq.5: send No Route notification */
633 lde_send_notification(ln
, S_NO_ROUTE
, map
->msg_id
,
634 htons(MSG_TYPE_LABELREQUEST
));
638 /* LRq.3: is MsgSource the next hop? */
639 LIST_FOREACH(fnh
, &fn
->nexthops
, entry
) {
643 if (!lde_address_find(ln
, fnh
->af
, &fnh
->nexthop
))
646 /* LRq.4: send Loop Detected notification */
647 lde_send_notification(ln
, S_LOOP_DETECTED
, map
->msg_id
,
648 htons(MSG_TYPE_LABELREQUEST
));
655 /* LRq.6: first check if we have a pending request running */
656 lre
= (struct lde_req
*)fec_find(&ln
->recv_req
, &fn
->fec
);
658 /* LRq.7: duplicate request */
661 /* LRq.8: record label request */
662 lre
= lde_req_add(ln
, &fn
->fec
, 0);
664 lre
->msg_id
= ntohl(map
->msg_id
);
666 /* LRq.9: perform LSR label distribution */
667 lde_send_labelmapping(ln
, fn
, 1);
670 * LRq.10: do nothing (Request Never) since we use liberal
672 * LRq.11 - 12 are unnecessary since we are merging capable.
677 lde_check_request_wcard(struct map
*map
, struct lde_nbr
*ln
)
683 RB_FOREACH(f
, fec_tree
, &ft
) {
684 fn
= (struct fec_node
*)f
;
686 /* only a typed wildcard is possible here */
687 if (lde_wildcard_apply(map
, &fn
->fec
, NULL
) == 0)
690 /* LRq.2: is there a next hop for fec? */
691 if (LIST_EMPTY(&fn
->nexthops
))
694 /* LRq.6: first check if we have a pending request running */
695 lre
= (struct lde_req
*)fec_find(&ln
->recv_req
, &fn
->fec
);
697 /* LRq.7: duplicate request */
700 /* LRq.8: record label request */
701 lre
= lde_req_add(ln
, &fn
->fec
, 0);
703 lre
->msg_id
= ntohl(map
->msg_id
);
705 /* LRq.9: perform LSR label distribution */
706 lde_send_labelmapping(ln
, fn
, 1);
711 lde_check_release(struct map
*map
, struct lde_nbr
*ln
)
715 struct lde_wdraw
*lw
;
717 struct fec
*pending_map
;
719 /* wildcard label release */
720 if (map
->type
== MAP_TYPE_WILDCARD
||
721 map
->type
== MAP_TYPE_TYPED_WCARD
||
722 (map
->type
== MAP_TYPE_PWID
&& !CHECK_FLAG(map
->flags
, F_MAP_PW_ID
))) {
723 lde_check_release_wcard(map
, ln
);
727 lde_map2fec(map
, ln
->id
, &fec
);
728 fn
= (struct fec_node
*)fec_find(&ft
, &fec
);
729 /* LRl.1: does FEC match a known FEC? */
733 /* LRl.6: check sent map list and remove it if available */
734 me
= (struct lde_map
*)fec_find(&ln
->sent_map
, &fn
->fec
);
735 if (me
&& (map
->label
== NO_LABEL
|| map
->label
== me
->map
.label
))
736 lde_map_del(ln
, me
, 1);
738 /* LRl.3: first check if we have a pending withdraw running */
739 lw
= (struct lde_wdraw
*)fec_find(&ln
->sent_wdraw
, &fn
->fec
);
740 if (lw
&& (map
->label
== NO_LABEL
|| map
->label
== lw
->label
)) {
741 /* LRl.4: delete record of outstanding label withdraw */
742 lde_wdraw_del(ln
, lw
);
744 /* send pending label mapping if any */
745 pending_map
= fec_find(&ln
->sent_map_pending
, &fn
->fec
);
747 lde_send_labelmapping(ln
, fn
, 1);
748 lde_map_pending_del(ln
, pending_map
);
753 * LRl.11 - 13 are unnecessary since we remove the label from
754 * forwarding/switching as soon as the FEC is unreachable.
759 lde_check_release_wcard(struct map
*map
, struct lde_nbr
*ln
)
763 struct lde_wdraw
*lw
;
765 struct fec
*pending_map
;
767 RB_FOREACH(f
, fec_tree
, &ft
) {
768 fn
= (struct fec_node
*)f
;
769 me
= (struct lde_map
*)fec_find(&ln
->sent_map
, &fn
->fec
);
771 /* LRl.1: does FEC match a known FEC? */
772 if (lde_wildcard_apply(map
, &fn
->fec
, me
) == 0)
775 /* LRl.6: check sent map list and remove it if available */
777 (map
->label
== NO_LABEL
|| map
->label
== me
->map
.label
))
778 lde_map_del(ln
, me
, 1);
780 /* LRl.3: first check if we have a pending withdraw running */
781 lw
= (struct lde_wdraw
*)fec_find(&ln
->sent_wdraw
, &fn
->fec
);
782 if (lw
&& (map
->label
== NO_LABEL
|| map
->label
== lw
->label
)) {
783 /* LRl.4: delete record of outstanding lbl withdraw */
784 lde_wdraw_del(ln
, lw
);
786 /* send pending label mapping if any */
787 pending_map
= fec_find(&ln
->sent_map_pending
, &fn
->fec
);
789 lde_send_labelmapping(ln
, fn
, 1);
790 lde_map_pending_del(ln
, pending_map
);
795 * LRl.11 - 13 are unnecessary since we remove the label from
796 * forwarding/switching as soon as the FEC is unreachable.
802 lde_check_withdraw(struct map
*map
, struct lde_nbr
*ln
)
809 struct lde_nbr
*lnbr
;
811 /* wildcard label withdraw */
812 if (map
->type
== MAP_TYPE_WILDCARD
||
813 map
->type
== MAP_TYPE_TYPED_WCARD
||
814 (map
->type
== MAP_TYPE_PWID
&& !CHECK_FLAG(map
->flags
, F_MAP_PW_ID
))) {
815 lde_check_withdraw_wcard(map
, ln
);
819 lde_map2fec(map
, ln
->id
, &fec
);
820 fn
= (struct fec_node
*)fec_find(&ft
, &fec
);
824 /* LWd.1: remove label from forwarding/switching use */
825 LIST_FOREACH(fnh
, &fn
->nexthops
, entry
) {
829 if (!lde_address_find(ln
, fnh
->af
, &fnh
->nexthop
))
833 pw
= (struct l2vpn_pw
*) fn
->data
;
836 pw
->remote_status
= PW_NOT_FORWARDING
;
841 if (map
->label
!= NO_LABEL
&& map
->label
!= fnh
->remote_label
)
844 lde_send_delete_klabel(fn
, fnh
);
845 fnh
->remote_label
= NO_LABEL
;
848 /* Update RLFA clients. */
849 lde_rlfa_update_clients(&fec
, ln
, MPLS_INVALID_LABEL
);
851 /* LWd.2: send label release */
852 lde_send_labelrelease(ln
, fn
, NULL
, map
->label
);
854 /* LWd.3: check previously received label mapping */
855 me
= (struct lde_map
*)fec_find(&ln
->recv_map
, &fn
->fec
);
856 if (me
&& (map
->label
== NO_LABEL
|| map
->label
== me
->map
.label
))
857 /* LWd.4: remove record of previously received lbl mapping */
858 lde_map_del(ln
, me
, 0);
863 /* Ordered Control: additional withdraw steps */
864 if (CHECK_FLAG(ldeconf
->flags
, F_LDPD_ORDERED_CONTROL
)) {
865 /* LWd.8: for each neighbor other that src of withdraw msg */
866 RB_FOREACH(lnbr
, nbr_tree
, &lde_nbrs
) {
867 if (ln
->peerid
== lnbr
->peerid
)
870 /* LWd.9: check if previously sent a label mapping */
871 me
= (struct lde_map
*)fec_find(&lnbr
->sent_map
, &fn
->fec
);
874 * LWd.10: does label sent to peer "map" to withdraw
877 if (me
&& lde_nbr_is_nexthop(fn
, lnbr
))
878 /* LWd.11: send label withdraw */
879 lde_send_labelwithdraw(lnbr
, fn
, NULL
, NULL
);
886 lde_check_withdraw_wcard(struct map
*map
, struct lde_nbr
*ln
)
893 struct lde_nbr
*lnbr
;
895 /* LWd.2: send label release */
896 lde_send_labelrelease(ln
, NULL
, map
, map
->label
);
898 RB_FOREACH(f
, fec_tree
, &ft
) {
899 fn
= (struct fec_node
*)f
;
900 me
= (struct lde_map
*)fec_find(&ln
->recv_map
, &fn
->fec
);
902 if (lde_wildcard_apply(map
, &fn
->fec
, me
) == 0)
905 /* LWd.1: remove label from forwarding/switching use */
906 LIST_FOREACH(fnh
, &fn
->nexthops
, entry
) {
910 if (!lde_address_find(ln
, fnh
->af
, &fnh
->nexthop
))
914 if (f
->u
.pwid
.lsr_id
.s_addr
!= ln
->id
.s_addr
)
916 pw
= (struct l2vpn_pw
*) fn
->data
;
918 pw
->remote_status
= PW_NOT_FORWARDING
;
923 if (map
->label
!= NO_LABEL
&& map
->label
!= fnh
->remote_label
)
926 lde_send_delete_klabel(fn
, fnh
);
927 fnh
->remote_label
= NO_LABEL
;
930 /* Update RLFA clients. */
931 lde_rlfa_update_clients(f
, ln
, MPLS_INVALID_LABEL
);
933 /* LWd.3: check previously received label mapping */
934 if (me
&& (map
->label
== NO_LABEL
|| map
->label
== me
->map
.label
))
936 * LWd.4: remove record of previously received
939 lde_map_del(ln
, me
, 0);
944 /* Ordered Control: additional withdraw steps */
945 if (CHECK_FLAG(ldeconf
->flags
, F_LDPD_ORDERED_CONTROL
)) {
947 * LWd.8: for each neighbor other that src of
950 RB_FOREACH(lnbr
, nbr_tree
, &lde_nbrs
) {
951 if (ln
->peerid
== lnbr
->peerid
)
954 /* LWd.9: check if previously sent a label
957 me
= (struct lde_map
*)fec_find(&lnbr
->sent_map
, &fn
->fec
);
959 * LWd.10: does label sent to peer "map" to
962 if (me
&& lde_nbr_is_nexthop(fn
, lnbr
))
963 /* LWd.11: send label withdraw */
964 lde_send_labelwithdraw(lnbr
, fn
, NULL
, NULL
);
971 lde_wildcard_apply(struct map
*wcard
, struct fec
*fec
, struct lde_map
*me
)
973 switch (wcard
->type
) {
974 case MAP_TYPE_WILDCARD
:
977 case MAP_TYPE_TYPED_WCARD
:
978 switch (wcard
->fec
.twcard
.type
) {
979 case MAP_TYPE_PREFIX
:
980 if (wcard
->fec
.twcard
.u
.prefix_af
== AF_INET
&&
981 fec
->type
!= FEC_TYPE_IPV4
)
983 if (wcard
->fec
.twcard
.u
.prefix_af
== AF_INET6
&&
984 fec
->type
!= FEC_TYPE_IPV6
)
988 if (fec
->type
!= FEC_TYPE_PWID
)
990 if (wcard
->fec
.twcard
.u
.pw_type
!= PW_TYPE_WILDCARD
&&
991 wcard
->fec
.twcard
.u
.pw_type
!= fec
->u
.pwid
.type
)
995 fatalx("lde_wildcard_apply: unexpected fec type");
999 /* RFC4447 pw-id group wildcard */
1000 if (fec
->type
!= FEC_TYPE_PWID
)
1002 if (fec
->u
.pwid
.type
!= wcard
->fec
.pwid
.type
)
1004 if (me
== NULL
|| (me
->map
.fec
.pwid
.group_id
!=
1005 wcard
->fec
.pwid
.group_id
))
1009 fatalx("lde_wildcard_apply: unexpected fec type");
1013 /* gabage collector timer: timer to remove dead entries from the LIB */
1016 void lde_gc_timer(struct event
*thread
)
1018 struct fec
*fec
, *safe
;
1019 struct fec_node
*fn
;
1022 RB_FOREACH_SAFE(fec
, fec_tree
, &ft
, safe
) {
1023 fn
= (struct fec_node
*) fec
;
1025 if (!LIST_EMPTY(&fn
->nexthops
) ||
1026 !RB_EMPTY(lde_map_head
, &fn
->downstream
) ||
1027 !RB_EMPTY(lde_map_head
, &fn
->upstream
))
1030 if (fn
->local_label
!= NO_LABEL
)
1031 lde_free_label(fn
->local_label
);
1033 fec_remove(&ft
, &fn
->fec
);
1039 log_debug("%s: %u entries removed", __func__
, count
);
1041 lde_gc_start_timer();
1045 lde_gc_start_timer(void)
1047 EVENT_OFF(gc_timer
);
1048 event_add_timer(master
, lde_gc_timer
, NULL
, LDE_GC_INTERVAL
, &gc_timer
);
1052 lde_gc_stop_timer(void)
1054 EVENT_OFF(gc_timer
);