]> git.proxmox.com Git - mirror_frr.git/blame - ldpd/lde_lib.c
lib: use traditional yacc empty statement
[mirror_frr.git] / ldpd / lde_lib.c
CommitLineData
8429abe0
RW
1/* $OpenBSD$ */
2
3/*
4 * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
5 * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
6 *
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.
10 *
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.
18 */
19
eac6e3f0 20#include <zebra.h>
8429abe0
RW
21
22#include "ldpd.h"
23#include "lde.h"
24#include "log.h"
25
eac6e3f0
RW
26#include "mpls.h"
27
8429abe0
RW
28static __inline int fec_compare(struct fec *, struct fec *);
29static int lde_nbr_is_nexthop(struct fec_node *,
30 struct lde_nbr *);
31static void fec_free(void *);
32static struct fec_node *fec_add(struct fec *fec);
33static struct fec_nh *fec_nh_add(struct fec_node *, int, union ldpd_addr *,
34 uint8_t priority);
35static void fec_nh_del(struct fec_nh *);
36
37RB_GENERATE(fec_tree, fec, entry, fec_compare)
38
39struct fec_tree ft = RB_INITIALIZER(&ft);
eac6e3f0 40struct thread *gc_timer;
8429abe0
RW
41
42/* FEC tree functions */
43void
44fec_init(struct fec_tree *fh)
45{
46 RB_INIT(fh);
47}
48
49static __inline int
50fec_compare(struct fec *a, struct fec *b)
51{
52 if (a->type < b->type)
53 return (-1);
54 if (a->type > b->type)
55 return (1);
56
57 switch (a->type) {
58 case FEC_TYPE_IPV4:
59 if (ntohl(a->u.ipv4.prefix.s_addr) <
60 ntohl(b->u.ipv4.prefix.s_addr))
61 return (-1);
62 if (ntohl(a->u.ipv4.prefix.s_addr) >
63 ntohl(b->u.ipv4.prefix.s_addr))
64 return (1);
65 if (a->u.ipv4.prefixlen < b->u.ipv4.prefixlen)
66 return (-1);
67 if (a->u.ipv4.prefixlen > b->u.ipv4.prefixlen)
68 return (1);
69 return (0);
70 case FEC_TYPE_IPV6:
71 if (memcmp(&a->u.ipv6.prefix, &b->u.ipv6.prefix,
72 sizeof(struct in6_addr)) < 0)
73 return (-1);
74 if (memcmp(&a->u.ipv6.prefix, &b->u.ipv6.prefix,
75 sizeof(struct in6_addr)) > 0)
76 return (1);
77 if (a->u.ipv6.prefixlen < b->u.ipv6.prefixlen)
78 return (-1);
79 if (a->u.ipv6.prefixlen > b->u.ipv6.prefixlen)
80 return (1);
81 return (0);
82 case FEC_TYPE_PWID:
83 if (a->u.pwid.type < b->u.pwid.type)
84 return (-1);
85 if (a->u.pwid.type > b->u.pwid.type)
86 return (1);
87 if (a->u.pwid.pwid < b->u.pwid.pwid)
88 return (-1);
89 if (a->u.pwid.pwid > b->u.pwid.pwid)
90 return (1);
91 if (ntohl(a->u.pwid.lsr_id.s_addr) <
92 ntohl(b->u.pwid.lsr_id.s_addr))
93 return (-1);
94 if (ntohl(a->u.pwid.lsr_id.s_addr) >
95 ntohl(b->u.pwid.lsr_id.s_addr))
96 return (1);
97 return (0);
98 }
99
100 return (-1);
101}
102
103struct fec *
104fec_find(struct fec_tree *fh, struct fec *f)
105{
106 return (RB_FIND(fec_tree, fh, f));
107}
108
109int
110fec_insert(struct fec_tree *fh, struct fec *f)
111{
112 if (RB_INSERT(fec_tree, fh, f) != NULL)
113 return (-1);
114 return (0);
115}
116
117int
118fec_remove(struct fec_tree *fh, struct fec *f)
119{
120 if (RB_REMOVE(fec_tree, fh, f) == NULL) {
121 log_warnx("%s failed for %s", __func__, log_fec(f));
122 return (-1);
123 }
124 return (0);
125}
126
127void
128fec_clear(struct fec_tree *fh, void (*free_cb)(void *))
129{
130 struct fec *f;
131
132 while ((f = RB_ROOT(fh)) != NULL) {
133 fec_remove(fh, f);
134 free_cb(f);
135 }
136}
137
138/* routing table functions */
139static int
140lde_nbr_is_nexthop(struct fec_node *fn, struct lde_nbr *ln)
141{
142 struct fec_nh *fnh;
143
144 LIST_FOREACH(fnh, &fn->nexthops, entry)
145 if (lde_address_find(ln, fnh->af, &fnh->nexthop))
146 return (1);
147
148 return (0);
149}
150
151void
152rt_dump(pid_t pid)
153{
154 struct fec *f;
155 struct fec_node *fn;
156 struct lde_map *me;
157 static struct ctl_rt rtctl;
158
159 RB_FOREACH(f, fec_tree, &ft) {
160 fn = (struct fec_node *)f;
161 if (fn->local_label == NO_LABEL &&
162 LIST_EMPTY(&fn->downstream))
163 continue;
164
eac6e3f0 165 rtctl.first = 1;
8429abe0
RW
166 switch (fn->fec.type) {
167 case FEC_TYPE_IPV4:
168 rtctl.af = AF_INET;
169 rtctl.prefix.v4 = fn->fec.u.ipv4.prefix;
170 rtctl.prefixlen = fn->fec.u.ipv4.prefixlen;
171 break;
172 case FEC_TYPE_IPV6:
173 rtctl.af = AF_INET6;
174 rtctl.prefix.v6 = fn->fec.u.ipv6.prefix;
175 rtctl.prefixlen = fn->fec.u.ipv6.prefixlen;
176 break;
177 default:
178 continue;
179 }
180
181 rtctl.local_label = fn->local_label;
182 LIST_FOREACH(me, &fn->downstream, entry) {
183 rtctl.in_use = lde_nbr_is_nexthop(fn, me->nexthop);
184 rtctl.nexthop = me->nexthop->id;
185 rtctl.remote_label = me->map.label;
186
187 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB, 0, pid,
188 &rtctl, sizeof(rtctl));
eac6e3f0 189 rtctl.first = 0;
8429abe0
RW
190 }
191 if (LIST_EMPTY(&fn->downstream)) {
192 rtctl.in_use = 0;
193 rtctl.nexthop.s_addr = INADDR_ANY;
194 rtctl.remote_label = NO_LABEL;
195
196 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB, 0, pid,
197 &rtctl, sizeof(rtctl));
198 }
199 }
200}
201
202void
203fec_snap(struct lde_nbr *ln)
204{
205 struct fec *f;
206 struct fec_node *fn;
207
208 RB_FOREACH(f, fec_tree, &ft) {
209 fn = (struct fec_node *)f;
210 if (fn->local_label == NO_LABEL)
211 continue;
212
213 lde_send_labelmapping(ln, fn, 0);
214 }
215
216 lde_imsg_compose_ldpe(IMSG_MAPPING_ADD_END, ln->peerid, 0, NULL, 0);
217}
218
219static void
220fec_free(void *arg)
221{
222 struct fec_node *fn = arg;
223 struct fec_nh *fnh;
224
225 while ((fnh = LIST_FIRST(&fn->nexthops)))
226 fec_nh_del(fnh);
227 if (!LIST_EMPTY(&fn->downstream))
228 log_warnx("%s: fec %s downstream list not empty", __func__,
229 log_fec(&fn->fec));
230 if (!LIST_EMPTY(&fn->upstream))
231 log_warnx("%s: fec %s upstream list not empty", __func__,
232 log_fec(&fn->fec));
233
234 free(fn);
235}
236
237void
238fec_tree_clear(void)
239{
240 fec_clear(&ft, fec_free);
241}
242
243static struct fec_node *
244fec_add(struct fec *fec)
245{
246 struct fec_node *fn;
247
248 fn = calloc(1, sizeof(*fn));
249 if (fn == NULL)
250 fatal(__func__);
251
252 fn->fec = *fec;
253 fn->local_label = NO_LABEL;
254 LIST_INIT(&fn->upstream);
255 LIST_INIT(&fn->downstream);
256 LIST_INIT(&fn->nexthops);
257
258 if (fec_insert(&ft, &fn->fec))
259 log_warnx("failed to add %s to ft tree",
260 log_fec(&fn->fec));
261
262 return (fn);
263}
264
265struct fec_nh *
266fec_nh_find(struct fec_node *fn, int af, union ldpd_addr *nexthop,
267 uint8_t priority)
268{
269 struct fec_nh *fnh;
270
271 LIST_FOREACH(fnh, &fn->nexthops, entry)
272 if (fnh->af == af &&
273 ldp_addrcmp(af, &fnh->nexthop, nexthop) == 0 &&
274 fnh->priority == priority)
275 return (fnh);
276
277 return (NULL);
278}
279
280static struct fec_nh *
281fec_nh_add(struct fec_node *fn, int af, union ldpd_addr *nexthop,
282 uint8_t priority)
283{
284 struct fec_nh *fnh;
285
286 fnh = calloc(1, sizeof(*fnh));
287 if (fnh == NULL)
288 fatal(__func__);
289
290 fnh->af = af;
291 fnh->nexthop = *nexthop;
292 fnh->remote_label = NO_LABEL;
293 fnh->priority = priority;
294 LIST_INSERT_HEAD(&fn->nexthops, fnh, entry);
295
296 return (fnh);
297}
298
299static void
300fec_nh_del(struct fec_nh *fnh)
301{
302 LIST_REMOVE(fnh, entry);
303 free(fnh);
304}
305
306uint32_t
307egress_label(enum fec_type fec_type)
308{
309 switch (fec_type) {
310 case FEC_TYPE_IPV4:
311 if (ldeconf->ipv4.flags & F_LDPD_AF_EXPNULL)
312 return (MPLS_LABEL_IPV4NULL);
313 break;
314 case FEC_TYPE_IPV6:
315 if (ldeconf->ipv6.flags & F_LDPD_AF_EXPNULL)
316 return (MPLS_LABEL_IPV6NULL);
317 break;
318 default:
319 fatalx("egress_label: unexpected fec type");
320 }
321
322 return (MPLS_LABEL_IMPLNULL);
323}
324
325void
326lde_kernel_insert(struct fec *fec, int af, union ldpd_addr *nexthop,
327 uint8_t priority, int connected, void *data)
328{
329 struct fec_node *fn;
330 struct fec_nh *fnh;
331 struct lde_map *me;
332 struct lde_nbr *ln;
333
334 fn = (struct fec_node *)fec_find(&ft, fec);
335 if (fn == NULL)
336 fn = fec_add(fec);
134970a2
RW
337 fnh = fec_nh_find(fn, af, nexthop, priority);
338 if (fnh != NULL) {
daca38ae 339 lde_send_change_klabel(fn, fnh);
134970a2 340 fnh->flags |= F_FEC_NH_NEW;
8429abe0 341 return;
134970a2 342 }
8429abe0 343
8429abe0
RW
344 if (fn->fec.type == FEC_TYPE_PWID)
345 fn->data = data;
346
347 if (fn->local_label == NO_LABEL) {
348 if (connected)
349 fn->local_label = egress_label(fn->fec.type);
350 else
351 fn->local_label = lde_assign_label();
352
353 /* FEC.1: perform lsr label distribution procedure */
354 RB_FOREACH(ln, nbr_tree, &lde_nbrs)
355 lde_send_labelmapping(ln, fn, 1);
356 }
357
358 fnh = fec_nh_add(fn, af, nexthop, priority);
134970a2 359 fnh->flags |= F_FEC_NH_NEW;
8429abe0
RW
360 lde_send_change_klabel(fn, fnh);
361
362 switch (fn->fec.type) {
363 case FEC_TYPE_IPV4:
364 case FEC_TYPE_IPV6:
365 ln = lde_nbr_find_by_addr(af, &fnh->nexthop);
366 break;
367 case FEC_TYPE_PWID:
368 ln = lde_nbr_find_by_lsrid(fn->fec.u.pwid.lsr_id);
369 break;
370 default:
371 ln = NULL;
372 break;
373 }
374
375 if (ln) {
376 /* FEC.2 */
377 me = (struct lde_map *)fec_find(&ln->recv_map, &fn->fec);
378 if (me)
379 /* FEC.5 */
380 lde_check_mapping(&me->map, ln);
381 }
382}
383
384void
385lde_kernel_remove(struct fec *fec, int af, union ldpd_addr *nexthop,
386 uint8_t priority)
387{
388 struct fec_node *fn;
389 struct fec_nh *fnh;
390
391 fn = (struct fec_node *)fec_find(&ft, fec);
392 if (fn == NULL)
393 /* route lost */
394 return;
395 fnh = fec_nh_find(fn, af, nexthop, priority);
396 if (fnh == NULL)
397 /* route lost */
398 return;
399
8429abe0
RW
400 lde_send_delete_klabel(fn, fnh);
401 fec_nh_del(fnh);
402 if (LIST_EMPTY(&fn->nexthops)) {
403 lde_send_labelwithdraw_all(fn, NO_LABEL);
404 fn->local_label = NO_LABEL;
405 if (fn->fec.type == FEC_TYPE_PWID)
406 fn->data = NULL;
407 }
408}
409
134970a2
RW
410/*
411 * Whenever a route is changed, zebra advertises its new version without
412 * withdrawing the old one. So, after processing a ZEBRA_REDISTRIBUTE_IPV[46]_ADD
413 * message, we need to check for nexthops that were removed and, for each of
414 * them (if any), withdraw the associated labels from zebra.
415 */
416void
417lde_kernel_reevaluate(struct fec *fec)
418{
419 struct fec_node *fn;
420 struct fec_nh *fnh, *safe;
421
422 fn = (struct fec_node *)fec_find(&ft, fec);
423 if (fn == NULL)
424 return;
425
426 LIST_FOREACH_SAFE(fnh, &fn->nexthops, entry, safe) {
427 if (fnh->flags & F_FEC_NH_NEW)
428 fnh->flags &= ~F_FEC_NH_NEW;
429 else
430 lde_kernel_remove(fec, fnh->af, &fnh->nexthop,
431 fnh->priority);
432 }
433}
434
8429abe0
RW
435void
436lde_check_mapping(struct map *map, struct lde_nbr *ln)
437{
438 struct fec fec;
439 struct fec_node *fn;
440 struct fec_nh *fnh;
441 struct lde_req *lre;
442 struct lde_map *me;
443 struct l2vpn_pw *pw;
444 int msgsource = 0;
445
446 lde_map2fec(map, ln->id, &fec);
447 fn = (struct fec_node *)fec_find(&ft, &fec);
448 if (fn == NULL)
449 fn = fec_add(&fec);
450
451 /* LMp.1: first check if we have a pending request running */
452 lre = (struct lde_req *)fec_find(&ln->sent_req, &fn->fec);
453 if (lre)
454 /* LMp.2: delete record of outstanding label request */
455 lde_req_del(ln, lre, 1);
456
457 /* RFC 4447 control word and status tlv negotiation */
458 if (map->type == MAP_TYPE_PWID && l2vpn_pw_negotiate(ln, fn, map))
459 return;
460
461 /*
462 * LMp.3 - LMp.8: loop detection - unnecessary for frame-mode
463 * mpls networks.
464 */
465
466 /* LMp.9 */
467 me = (struct lde_map *)fec_find(&ln->recv_map, &fn->fec);
468 if (me) {
469 /* LMp.10 */
470 if (me->map.label != map->label && lre == NULL) {
471 /* LMp.10a */
472 lde_send_labelrelease(ln, fn, me->map.label);
473
474 /*
475 * Can not use lde_nbr_find_by_addr() because there's
476 * the possibility of multipath.
477 */
478 LIST_FOREACH(fnh, &fn->nexthops, entry) {
479 if (lde_address_find(ln, fnh->af,
480 &fnh->nexthop) == NULL)
481 continue;
482
483 lde_send_delete_klabel(fn, fnh);
484 fnh->remote_label = NO_LABEL;
485 }
486 }
487 }
488
489 /*
490 * LMp.11 - 12: consider multiple nexthops in order to
491 * support multipath
492 */
493 LIST_FOREACH(fnh, &fn->nexthops, entry) {
494 /* LMp.15: install FEC in FIB */
495 switch (fec.type) {
496 case FEC_TYPE_IPV4:
497 case FEC_TYPE_IPV6:
498 if (!lde_address_find(ln, fnh->af, &fnh->nexthop))
499 continue;
500
501 fnh->remote_label = map->label;
502 lde_send_change_klabel(fn, fnh);
503 break;
504 case FEC_TYPE_PWID:
505 pw = (struct l2vpn_pw *) fn->data;
506 if (pw == NULL)
507 continue;
508
509 pw->remote_group = map->fec.pwid.group_id;
510 if (map->flags & F_MAP_PW_IFMTU)
511 pw->remote_mtu = map->fec.pwid.ifmtu;
512 if (map->flags & F_MAP_PW_STATUS)
513 pw->remote_status = map->pw_status;
514 fnh->remote_label = map->label;
515 if (l2vpn_pw_ok(pw, fnh))
516 lde_send_change_klabel(fn, fnh);
517 break;
518 default:
519 break;
520 }
521
522 msgsource = 1;
523 }
524 /* LMp.13 & LMp.16: Record the mapping from this peer */
525 if (me == NULL)
526 me = lde_map_add(ln, fn, 0);
527 me->map = *map;
528
529 if (msgsource == 0)
530 /* LMp.13: just return since we use liberal lbl retention */
531 return;
532
533 /*
534 * LMp.17 - LMp.27 are unnecessary since we don't need to implement
535 * loop detection. LMp.28 - LMp.30 are unnecessary because we are
536 * merging capable.
537 */
538}
539
540void
541lde_check_request(struct map *map, struct lde_nbr *ln)
542{
543 struct fec fec;
544 struct lde_req *lre;
545 struct fec_node *fn;
546 struct fec_nh *fnh;
547
548 /* LRq.1: skip loop detection (not necessary) */
549
550 /* LRq.2: is there a next hop for fec? */
551 lde_map2fec(map, ln->id, &fec);
552 fn = (struct fec_node *)fec_find(&ft, &fec);
553 if (fn == NULL || LIST_EMPTY(&fn->nexthops)) {
554 /* LRq.5: send No Route notification */
555 lde_send_notification(ln->peerid, S_NO_ROUTE, map->msg_id,
556 htons(MSG_TYPE_LABELREQUEST));
557 return;
558 }
559
560 /* LRq.3: is MsgSource the next hop? */
561 LIST_FOREACH(fnh, &fn->nexthops, entry) {
562 switch (fec.type) {
563 case FEC_TYPE_IPV4:
564 case FEC_TYPE_IPV6:
565 if (!lde_address_find(ln, fnh->af, &fnh->nexthop))
566 continue;
567
568 /* LRq.4: send Loop Detected notification */
569 lde_send_notification(ln->peerid, S_LOOP_DETECTED,
570 map->msg_id, htons(MSG_TYPE_LABELREQUEST));
571 return;
572 default:
573 break;
574 }
575 }
576
577 /* LRq.6: first check if we have a pending request running */
578 lre = (struct lde_req *)fec_find(&ln->recv_req, &fn->fec);
579 if (lre != NULL)
580 /* LRq.7: duplicate request */
581 return;
582
583 /* LRq.8: record label request */
584 lre = lde_req_add(ln, &fn->fec, 0);
585 if (lre != NULL)
586 lre->msg_id = ntohl(map->msg_id);
587
588 /* LRq.9: perform LSR label distribution */
589 lde_send_labelmapping(ln, fn, 1);
590
591 /*
592 * LRq.10: do nothing (Request Never) since we use liberal
593 * label retention.
594 * LRq.11 - 12 are unnecessary since we are merging capable.
595 */
596}
597
598void
599lde_check_release(struct map *map, struct lde_nbr *ln)
600{
601 struct fec fec;
602 struct fec_node *fn;
603 struct lde_wdraw *lw;
604 struct lde_map *me;
605
606 /* TODO group wildcard */
607 if (map->type == MAP_TYPE_PWID && !(map->flags & F_MAP_PW_ID))
608 return;
609
610 lde_map2fec(map, ln->id, &fec);
611 fn = (struct fec_node *)fec_find(&ft, &fec);
612 /* LRl.1: does FEC match a known FEC? */
613 if (fn == NULL)
614 return;
615
616 /* LRl.3: first check if we have a pending withdraw running */
617 lw = (struct lde_wdraw *)fec_find(&ln->sent_wdraw, &fn->fec);
618 if (lw && (map->label == NO_LABEL ||
619 (lw->label != NO_LABEL && map->label == lw->label))) {
620 /* LRl.4: delete record of outstanding label withdraw */
621 lde_wdraw_del(ln, lw);
622 }
623
624 /* LRl.6: check sent map list and remove it if available */
625 me = (struct lde_map *)fec_find(&ln->sent_map, &fn->fec);
626 if (me && (map->label == NO_LABEL || map->label == me->map.label))
627 lde_map_del(ln, me, 1);
628
629 /*
630 * LRl.11 - 13 are unnecessary since we remove the label from
631 * forwarding/switching as soon as the FEC is unreachable.
632 */
633}
634
635void
636lde_check_release_wcard(struct map *map, struct lde_nbr *ln)
637{
638 struct fec *f;
639 struct fec_node *fn;
640 struct lde_wdraw *lw;
641 struct lde_map *me;
642
643 RB_FOREACH(f, fec_tree, &ft) {
644 fn = (struct fec_node *)f;
645
646 /* LRl.3: first check if we have a pending withdraw running */
647 lw = (struct lde_wdraw *)fec_find(&ln->sent_wdraw, &fn->fec);
648 if (lw && (map->label == NO_LABEL ||
649 (lw->label != NO_LABEL && map->label == lw->label))) {
650 /* LRl.4: delete record of outstanding lbl withdraw */
651 lde_wdraw_del(ln, lw);
652 }
653
654 /* LRl.6: check sent map list and remove it if available */
655 me = (struct lde_map *)fec_find(&ln->sent_map, &fn->fec);
656 if (me &&
657 (map->label == NO_LABEL || map->label == me->map.label))
658 lde_map_del(ln, me, 1);
659
660 /*
661 * LRl.11 - 13 are unnecessary since we remove the label from
662 * forwarding/switching as soon as the FEC is unreachable.
663 */
664 }
665}
666
667void
668lde_check_withdraw(struct map *map, struct lde_nbr *ln)
669{
670 struct fec fec;
671 struct fec_node *fn;
672 struct fec_nh *fnh;
673 struct lde_map *me;
674 struct l2vpn_pw *pw;
675
676 /* TODO group wildcard */
677 if (map->type == MAP_TYPE_PWID && !(map->flags & F_MAP_PW_ID))
678 return;
679
680 lde_map2fec(map, ln->id, &fec);
681 fn = (struct fec_node *)fec_find(&ft, &fec);
682 if (fn == NULL)
683 fn = fec_add(&fec);
684
685 /* LWd.1: remove label from forwarding/switching use */
686 LIST_FOREACH(fnh, &fn->nexthops, entry) {
687 switch (fec.type) {
688 case FEC_TYPE_IPV4:
689 case FEC_TYPE_IPV6:
690 if (!lde_address_find(ln, fnh->af, &fnh->nexthop))
691 continue;
692 break;
693 case FEC_TYPE_PWID:
694 pw = (struct l2vpn_pw *) fn->data;
695 if (pw == NULL)
696 continue;
697 break;
698 default:
699 break;
700 }
701 lde_send_delete_klabel(fn, fnh);
702 fnh->remote_label = NO_LABEL;
703 }
704
705 /* LWd.2: send label release */
706 lde_send_labelrelease(ln, fn, map->label);
707
708 /* LWd.3: check previously received label mapping */
709 me = (struct lde_map *)fec_find(&ln->recv_map, &fn->fec);
710 if (me && (map->label == NO_LABEL || map->label == me->map.label))
711 /* LWd.4: remove record of previously received lbl mapping */
712 lde_map_del(ln, me, 0);
713}
714
715void
716lde_check_withdraw_wcard(struct map *map, struct lde_nbr *ln)
717{
718 struct fec *f;
719 struct fec_node *fn;
720 struct fec_nh *fnh;
721 struct lde_map *me;
722
723 /* LWd.2: send label release */
724 lde_send_labelrelease(ln, NULL, map->label);
725
726 RB_FOREACH(f, fec_tree, &ft) {
727 fn = (struct fec_node *)f;
728
729 /* LWd.1: remove label from forwarding/switching use */
730 LIST_FOREACH(fnh, &fn->nexthops, entry) {
731 switch (f->type) {
732 case FEC_TYPE_IPV4:
733 case FEC_TYPE_IPV6:
734 if (!lde_address_find(ln, fnh->af,
735 &fnh->nexthop))
736 continue;
737 break;
738 case FEC_TYPE_PWID:
739 if (f->u.pwid.lsr_id.s_addr != ln->id.s_addr)
740 continue;
741 break;
742 default:
743 break;
744 }
745 lde_send_delete_klabel(fn, fnh);
746 fnh->remote_label = NO_LABEL;
747 }
748
749 /* LWd.3: check previously received label mapping */
750 me = (struct lde_map *)fec_find(&ln->recv_map, &fn->fec);
751 if (me && (map->label == NO_LABEL ||
752 map->label == me->map.label))
753 /*
754 * LWd.4: remove record of previously received
755 * label mapping
756 */
757 lde_map_del(ln, me, 0);
758 }
759}
760
761/* gabage collector timer: timer to remove dead entries from the LIB */
762
763/* ARGSUSED */
eac6e3f0
RW
764int
765lde_gc_timer(struct thread *thread)
8429abe0
RW
766{
767 struct fec *fec, *safe;
768 struct fec_node *fn;
769 int count = 0;
770
771 RB_FOREACH_SAFE(fec, fec_tree, &ft, safe) {
772 fn = (struct fec_node *) fec;
773
774 if (!LIST_EMPTY(&fn->nexthops) ||
775 !LIST_EMPTY(&fn->downstream) ||
776 !LIST_EMPTY(&fn->upstream))
777 continue;
778
779 fec_remove(&ft, &fn->fec);
780 free(fn);
781 count++;
782 }
783
784 if (count > 0)
785 log_debug("%s: %u entries removed", __func__, count);
786
787 lde_gc_start_timer();
eac6e3f0
RW
788
789 return (0);
8429abe0
RW
790}
791
792void
793lde_gc_start_timer(void)
794{
eac6e3f0
RW
795 THREAD_TIMER_OFF(gc_timer);
796 gc_timer = thread_add_timer(master, lde_gc_timer, NULL,
797 LDE_GC_INTERVAL);
8429abe0
RW
798}
799
800void
801lde_gc_stop_timer(void)
802{
eac6e3f0 803 THREAD_TIMER_OFF(gc_timer);
8429abe0 804}