]> git.proxmox.com Git - mirror_frr.git/blame - ldpd/lde_lib.c
*: remove THREAD_ON macros, add nullity check
[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 *,
88d88a9c 34 ifindex_t, uint8_t);
8429abe0
RW
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 &&
d3e1887a 162 RB_EMPTY(&fn->downstream))
8429abe0
RW
163 continue;
164
0f7b5df9 165 memset(&rtctl, 0, sizeof(rtctl));
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;
d3e1887a 182 if (RB_EMPTY(&fn->downstream)) {
8429abe0
RW
183 rtctl.in_use = 0;
184 rtctl.nexthop.s_addr = INADDR_ANY;
185 rtctl.remote_label = NO_LABEL;
0f7b5df9
RW
186 rtctl.no_downstream = 1;
187 }
188 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB_BEGIN, 0, pid, &rtctl,
189 sizeof(rtctl));
8429abe0 190
0f7b5df9
RW
191 RB_FOREACH(me, lde_map_head, &fn->upstream) {
192 rtctl.nexthop = me->nexthop->id;
193 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB_SENT, 0, pid,
194 &rtctl, sizeof(rtctl));
195 }
196
197 RB_FOREACH(me, lde_map_head, &fn->downstream) {
198 rtctl.in_use = lde_nbr_is_nexthop(fn, me->nexthop);
199 rtctl.nexthop = me->nexthop->id;
200 rtctl.remote_label = me->map.label;
201 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB_RCVD, 0, pid,
8429abe0
RW
202 &rtctl, sizeof(rtctl));
203 }
0f7b5df9
RW
204 lde_imsg_compose_ldpe(IMSG_CTL_SHOW_LIB_END, 0, pid, &rtctl,
205 sizeof(rtctl));
8429abe0
RW
206 }
207}
208
209void
210fec_snap(struct lde_nbr *ln)
211{
212 struct fec *f;
213 struct fec_node *fn;
214
215 RB_FOREACH(f, fec_tree, &ft) {
216 fn = (struct fec_node *)f;
217 if (fn->local_label == NO_LABEL)
218 continue;
219
220 lde_send_labelmapping(ln, fn, 0);
221 }
222
223 lde_imsg_compose_ldpe(IMSG_MAPPING_ADD_END, ln->peerid, 0, NULL, 0);
224}
225
226static void
227fec_free(void *arg)
228{
229 struct fec_node *fn = arg;
230 struct fec_nh *fnh;
231
232 while ((fnh = LIST_FIRST(&fn->nexthops)))
233 fec_nh_del(fnh);
d3e1887a 234 if (!RB_EMPTY(&fn->downstream))
8429abe0
RW
235 log_warnx("%s: fec %s downstream list not empty", __func__,
236 log_fec(&fn->fec));
d3e1887a 237 if (!RB_EMPTY(&fn->upstream))
8429abe0
RW
238 log_warnx("%s: fec %s upstream list not empty", __func__,
239 log_fec(&fn->fec));
240
241 free(fn);
242}
243
244void
245fec_tree_clear(void)
246{
247 fec_clear(&ft, fec_free);
248}
249
250static struct fec_node *
251fec_add(struct fec *fec)
252{
253 struct fec_node *fn;
254
255 fn = calloc(1, sizeof(*fn));
256 if (fn == NULL)
257 fatal(__func__);
258
259 fn->fec = *fec;
260 fn->local_label = NO_LABEL;
d3e1887a
RW
261 RB_INIT(&fn->upstream);
262 RB_INIT(&fn->downstream);
8429abe0
RW
263 LIST_INIT(&fn->nexthops);
264
265 if (fec_insert(&ft, &fn->fec))
266 log_warnx("failed to add %s to ft tree",
267 log_fec(&fn->fec));
268
269 return (fn);
270}
271
272struct fec_nh *
273fec_nh_find(struct fec_node *fn, int af, union ldpd_addr *nexthop,
88d88a9c 274 ifindex_t ifindex, uint8_t priority)
8429abe0
RW
275{
276 struct fec_nh *fnh;
277
278 LIST_FOREACH(fnh, &fn->nexthops, entry)
279 if (fnh->af == af &&
280 ldp_addrcmp(af, &fnh->nexthop, nexthop) == 0 &&
88d88a9c 281 fnh->ifindex == ifindex &&
8429abe0
RW
282 fnh->priority == priority)
283 return (fnh);
284
285 return (NULL);
286}
287
288static struct fec_nh *
289fec_nh_add(struct fec_node *fn, int af, union ldpd_addr *nexthop,
88d88a9c 290 ifindex_t ifindex, uint8_t priority)
8429abe0
RW
291{
292 struct fec_nh *fnh;
293
294 fnh = calloc(1, sizeof(*fnh));
295 if (fnh == NULL)
296 fatal(__func__);
297
298 fnh->af = af;
299 fnh->nexthop = *nexthop;
88d88a9c 300 fnh->ifindex = ifindex;
8429abe0
RW
301 fnh->remote_label = NO_LABEL;
302 fnh->priority = priority;
303 LIST_INSERT_HEAD(&fn->nexthops, fnh, entry);
304
305 return (fnh);
306}
307
308static void
309fec_nh_del(struct fec_nh *fnh)
310{
311 LIST_REMOVE(fnh, entry);
312 free(fnh);
313}
314
8429abe0
RW
315void
316lde_kernel_insert(struct fec *fec, int af, union ldpd_addr *nexthop,
88d88a9c 317 ifindex_t ifindex, uint8_t priority, int connected, void *data)
8429abe0
RW
318{
319 struct fec_node *fn;
320 struct fec_nh *fnh;
8429abe0
RW
321
322 fn = (struct fec_node *)fec_find(&ft, fec);
323 if (fn == NULL)
324 fn = fec_add(fec);
8cb1fc45 325 if (data)
8429abe0
RW
326 fn->data = data;
327
8cb1fc45
RW
328 fnh = fec_nh_find(fn, af, nexthop, ifindex, priority);
329 if (fnh == NULL)
330 fnh = fec_nh_add(fn, af, nexthop, ifindex, priority);
134970a2 331 fnh->flags |= F_FEC_NH_NEW;
8cb1fc45
RW
332 if (connected)
333 fnh->flags |= F_FEC_NH_CONNECTED;
8429abe0
RW
334}
335
336void
337lde_kernel_remove(struct fec *fec, int af, union ldpd_addr *nexthop,
88d88a9c 338 ifindex_t ifindex, uint8_t priority)
8429abe0
RW
339{
340 struct fec_node *fn;
341 struct fec_nh *fnh;
342
343 fn = (struct fec_node *)fec_find(&ft, fec);
344 if (fn == NULL)
345 /* route lost */
346 return;
88d88a9c 347 fnh = fec_nh_find(fn, af, nexthop, ifindex, priority);
8429abe0
RW
348 if (fnh == NULL)
349 /* route lost */
350 return;
351
8429abe0
RW
352 lde_send_delete_klabel(fn, fnh);
353 fec_nh_del(fnh);
8429abe0
RW
354}
355
134970a2
RW
356/*
357 * Whenever a route is changed, zebra advertises its new version without
358 * withdrawing the old one. So, after processing a ZEBRA_REDISTRIBUTE_IPV[46]_ADD
359 * message, we need to check for nexthops that were removed and, for each of
360 * them (if any), withdraw the associated labels from zebra.
361 */
362void
8cb1fc45 363lde_kernel_update(struct fec *fec)
134970a2
RW
364{
365 struct fec_node *fn;
366 struct fec_nh *fnh, *safe;
8cb1fc45
RW
367 struct lde_nbr *ln;
368 struct lde_map *me;
134970a2
RW
369
370 fn = (struct fec_node *)fec_find(&ft, fec);
371 if (fn == NULL)
372 return;
373
374 LIST_FOREACH_SAFE(fnh, &fn->nexthops, entry, safe) {
375 if (fnh->flags & F_FEC_NH_NEW)
376 fnh->flags &= ~F_FEC_NH_NEW;
8cb1fc45
RW
377 else {
378 lde_send_delete_klabel(fn, fnh);
379 fec_nh_del(fnh);
380 }
381 }
382
383 if (LIST_EMPTY(&fn->nexthops)) {
0bcc2916
RW
384 RB_FOREACH(ln, nbr_tree, &lde_nbrs)
385 lde_send_labelwithdraw(ln, fn, NULL, NULL);
8cb1fc45 386 fn->data = NULL;
8cb1fc45 387
095f12f9
RW
388 /*
389 * Do not deallocate the local label now, do that only in the
390 * LIB garbage collector. This will prevent ldpd from changing
391 * the input label of some prefixes too often when running on
392 * an unstable network. Also, restart the garbage collector
393 * timer so that labels are deallocated only when the network
394 * is stabilized.
395 */
396 lde_gc_start_timer();
397 } else {
8cb1fc45 398 fn->local_label = lde_update_label(fn);
095f12f9 399 if (fn->local_label != NO_LABEL && RB_EMPTY(&fn->upstream))
8cb1fc45
RW
400 /* FEC.1: perform lsr label distribution procedure */
401 RB_FOREACH(ln, nbr_tree, &lde_nbrs)
402 lde_send_labelmapping(ln, fn, 1);
8cb1fc45
RW
403 }
404
405 LIST_FOREACH(fnh, &fn->nexthops, entry) {
406 lde_send_change_klabel(fn, fnh);
407
408 switch (fn->fec.type) {
409 case FEC_TYPE_IPV4:
410 case FEC_TYPE_IPV6:
411 ln = lde_nbr_find_by_addr(fnh->af, &fnh->nexthop);
412 break;
413 case FEC_TYPE_PWID:
414 ln = lde_nbr_find_by_lsrid(fn->fec.u.pwid.lsr_id);
415 break;
416 default:
417 ln = NULL;
418 break;
419 }
420
421 if (ln) {
422 /* FEC.2 */
423 me = (struct lde_map *)fec_find(&ln->recv_map, &fn->fec);
424 if (me)
425 /* FEC.5 */
426 lde_check_mapping(&me->map, ln);
427 }
134970a2
RW
428 }
429}
430
8429abe0
RW
431void
432lde_check_mapping(struct map *map, struct lde_nbr *ln)
433{
434 struct fec fec;
435 struct fec_node *fn;
436 struct fec_nh *fnh;
437 struct lde_req *lre;
438 struct lde_map *me;
439 struct l2vpn_pw *pw;
440 int msgsource = 0;
441
442 lde_map2fec(map, ln->id, &fec);
45a8eba9
RW
443
444 switch (fec.type) {
445 case FEC_TYPE_IPV4:
446 if (lde_acl_check(ldeconf->ipv4.acl_label_accept_from,
447 AF_INET, (union ldpd_addr *)&ln->id, 32) != FILTER_PERMIT)
448 return;
449 if (lde_acl_check(ldeconf->ipv4.acl_label_accept_for,
450 AF_INET, (union ldpd_addr *)&fec.u.ipv4.prefix,
451 fec.u.ipv4.prefixlen) != FILTER_PERMIT)
452 return;
453 break;
454 case FEC_TYPE_IPV6:
455 if (lde_acl_check(ldeconf->ipv6.acl_label_accept_from,
456 AF_INET, (union ldpd_addr *)&ln->id, 32) != FILTER_PERMIT)
457 return;
458 if (lde_acl_check(ldeconf->ipv6.acl_label_accept_for,
459 AF_INET6, (union ldpd_addr *)&fec.u.ipv6.prefix,
460 fec.u.ipv6.prefixlen) != FILTER_PERMIT)
461 return;
462 break;
463 default:
464 break;
465 }
466
8429abe0
RW
467 fn = (struct fec_node *)fec_find(&ft, &fec);
468 if (fn == NULL)
469 fn = fec_add(&fec);
470
471 /* LMp.1: first check if we have a pending request running */
472 lre = (struct lde_req *)fec_find(&ln->sent_req, &fn->fec);
473 if (lre)
474 /* LMp.2: delete record of outstanding label request */
475 lde_req_del(ln, lre, 1);
476
477 /* RFC 4447 control word and status tlv negotiation */
478 if (map->type == MAP_TYPE_PWID && l2vpn_pw_negotiate(ln, fn, map))
479 return;
480
481 /*
482 * LMp.3 - LMp.8: loop detection - unnecessary for frame-mode
483 * mpls networks.
484 */
485
486 /* LMp.9 */
487 me = (struct lde_map *)fec_find(&ln->recv_map, &fn->fec);
488 if (me) {
489 /* LMp.10 */
490 if (me->map.label != map->label && lre == NULL) {
491 /* LMp.10a */
0bcc2916 492 lde_send_labelrelease(ln, fn, NULL, me->map.label);
8429abe0
RW
493
494 /*
495 * Can not use lde_nbr_find_by_addr() because there's
496 * the possibility of multipath.
497 */
498 LIST_FOREACH(fnh, &fn->nexthops, entry) {
499 if (lde_address_find(ln, fnh->af,
500 &fnh->nexthop) == NULL)
501 continue;
502
503 lde_send_delete_klabel(fn, fnh);
504 fnh->remote_label = NO_LABEL;
505 }
506 }
507 }
508
509 /*
510 * LMp.11 - 12: consider multiple nexthops in order to
511 * support multipath
512 */
513 LIST_FOREACH(fnh, &fn->nexthops, entry) {
514 /* LMp.15: install FEC in FIB */
515 switch (fec.type) {
516 case FEC_TYPE_IPV4:
517 case FEC_TYPE_IPV6:
518 if (!lde_address_find(ln, fnh->af, &fnh->nexthop))
519 continue;
520
521 fnh->remote_label = map->label;
522 lde_send_change_klabel(fn, fnh);
523 break;
524 case FEC_TYPE_PWID:
525 pw = (struct l2vpn_pw *) fn->data;
526 if (pw == NULL)
527 continue;
528
529 pw->remote_group = map->fec.pwid.group_id;
530 if (map->flags & F_MAP_PW_IFMTU)
531 pw->remote_mtu = map->fec.pwid.ifmtu;
532 if (map->flags & F_MAP_PW_STATUS)
533 pw->remote_status = map->pw_status;
534 fnh->remote_label = map->label;
535 if (l2vpn_pw_ok(pw, fnh))
536 lde_send_change_klabel(fn, fnh);
537 break;
538 default:
539 break;
540 }
541
542 msgsource = 1;
543 }
544 /* LMp.13 & LMp.16: Record the mapping from this peer */
545 if (me == NULL)
546 me = lde_map_add(ln, fn, 0);
547 me->map = *map;
548
549 if (msgsource == 0)
550 /* LMp.13: just return since we use liberal lbl retention */
551 return;
552
553 /*
554 * LMp.17 - LMp.27 are unnecessary since we don't need to implement
555 * loop detection. LMp.28 - LMp.30 are unnecessary because we are
556 * merging capable.
557 */
558}
559
560void
561lde_check_request(struct map *map, struct lde_nbr *ln)
562{
563 struct fec fec;
564 struct lde_req *lre;
565 struct fec_node *fn;
566 struct fec_nh *fnh;
567
d4afb819
RW
568 /* wildcard label request */
569 if (map->type == MAP_TYPE_TYPED_WCARD) {
570 lde_check_request_wcard(map, ln);
571 return;
572 }
573
8429abe0
RW
574 /* LRq.1: skip loop detection (not necessary) */
575
576 /* LRq.2: is there a next hop for fec? */
577 lde_map2fec(map, ln->id, &fec);
578 fn = (struct fec_node *)fec_find(&ft, &fec);
579 if (fn == NULL || LIST_EMPTY(&fn->nexthops)) {
580 /* LRq.5: send No Route notification */
05aac414 581 lde_send_notification(ln, S_NO_ROUTE, map->msg_id,
8429abe0
RW
582 htons(MSG_TYPE_LABELREQUEST));
583 return;
584 }
585
586 /* LRq.3: is MsgSource the next hop? */
587 LIST_FOREACH(fnh, &fn->nexthops, entry) {
588 switch (fec.type) {
589 case FEC_TYPE_IPV4:
590 case FEC_TYPE_IPV6:
591 if (!lde_address_find(ln, fnh->af, &fnh->nexthop))
592 continue;
593
594 /* LRq.4: send Loop Detected notification */
05aac414
RW
595 lde_send_notification(ln, S_LOOP_DETECTED, map->msg_id,
596 htons(MSG_TYPE_LABELREQUEST));
8429abe0
RW
597 return;
598 default:
599 break;
600 }
601 }
602
603 /* LRq.6: first check if we have a pending request running */
604 lre = (struct lde_req *)fec_find(&ln->recv_req, &fn->fec);
605 if (lre != NULL)
606 /* LRq.7: duplicate request */
607 return;
608
609 /* LRq.8: record label request */
610 lre = lde_req_add(ln, &fn->fec, 0);
611 if (lre != NULL)
612 lre->msg_id = ntohl(map->msg_id);
613
614 /* LRq.9: perform LSR label distribution */
615 lde_send_labelmapping(ln, fn, 1);
616
617 /*
618 * LRq.10: do nothing (Request Never) since we use liberal
619 * label retention.
620 * LRq.11 - 12 are unnecessary since we are merging capable.
621 */
622}
623
d4afb819
RW
624void
625lde_check_request_wcard(struct map *map, struct lde_nbr *ln)
626{
627 struct fec *f;
628 struct fec_node *fn;
629 struct lde_req *lre;
630
631 RB_FOREACH(f, fec_tree, &ft) {
632 fn = (struct fec_node *)f;
633
634 /* only a typed wildcard is possible here */
635 if (lde_wildcard_apply(map, &fn->fec, NULL) == 0)
636 continue;
637
638 /* LRq.2: is there a next hop for fec? */
639 if (LIST_EMPTY(&fn->nexthops))
640 continue;
641
642 /* LRq.6: first check if we have a pending request running */
643 lre = (struct lde_req *)fec_find(&ln->recv_req, &fn->fec);
644 if (lre != NULL)
645 /* LRq.7: duplicate request */
646 continue;
647
648 /* LRq.8: record label request */
649 lre = lde_req_add(ln, &fn->fec, 0);
650 if (lre != NULL)
651 lre->msg_id = ntohl(map->msg_id);
652
653 /* LRq.9: perform LSR label distribution */
654 lde_send_labelmapping(ln, fn, 1);
655 }
656}
657
8429abe0
RW
658void
659lde_check_release(struct map *map, struct lde_nbr *ln)
660{
661 struct fec fec;
662 struct fec_node *fn;
663 struct lde_wdraw *lw;
664 struct lde_map *me;
7c2abbd7 665 struct fec *pending_map;
8429abe0 666
0bcc2916
RW
667 /* wildcard label release */
668 if (map->type == MAP_TYPE_WILDCARD ||
d4afb819 669 map->type == MAP_TYPE_TYPED_WCARD ||
0bcc2916
RW
670 (map->type == MAP_TYPE_PWID && !(map->flags & F_MAP_PW_ID))) {
671 lde_check_release_wcard(map, ln);
8429abe0 672 return;
0bcc2916 673 }
8429abe0
RW
674
675 lde_map2fec(map, ln->id, &fec);
676 fn = (struct fec_node *)fec_find(&ft, &fec);
677 /* LRl.1: does FEC match a known FEC? */
678 if (fn == NULL)
679 return;
680
7c2abbd7
RW
681 /* LRl.6: check sent map list and remove it if available */
682 me = (struct lde_map *)fec_find(&ln->sent_map, &fn->fec);
683 if (me && (map->label == NO_LABEL || map->label == me->map.label))
684 lde_map_del(ln, me, 1);
685
8429abe0
RW
686 /* LRl.3: first check if we have a pending withdraw running */
687 lw = (struct lde_wdraw *)fec_find(&ln->sent_wdraw, &fn->fec);
be8e0d31 688 if (lw && (map->label == NO_LABEL || map->label == lw->label)) {
8429abe0
RW
689 /* LRl.4: delete record of outstanding label withdraw */
690 lde_wdraw_del(ln, lw);
8429abe0 691
7c2abbd7
RW
692 /* send pending label mapping if any */
693 pending_map = fec_find(&ln->sent_map_pending, &fn->fec);
694 if (pending_map) {
695 lde_send_labelmapping(ln, fn, 1);
696 lde_map_pending_del(ln, pending_map);
697 }
698 }
8429abe0
RW
699
700 /*
701 * LRl.11 - 13 are unnecessary since we remove the label from
702 * forwarding/switching as soon as the FEC is unreachable.
703 */
704}
705
706void
707lde_check_release_wcard(struct map *map, struct lde_nbr *ln)
708{
709 struct fec *f;
710 struct fec_node *fn;
711 struct lde_wdraw *lw;
712 struct lde_map *me;
7c2abbd7 713 struct fec *pending_map;
8429abe0
RW
714
715 RB_FOREACH(f, fec_tree, &ft) {
716 fn = (struct fec_node *)f;
0bcc2916
RW
717 me = (struct lde_map *)fec_find(&ln->sent_map, &fn->fec);
718
719 /* LRl.1: does FEC match a known FEC? */
720 if (lde_wildcard_apply(map, &fn->fec, me) == 0)
721 continue;
8429abe0 722
7c2abbd7
RW
723 /* LRl.6: check sent map list and remove it if available */
724 if (me &&
725 (map->label == NO_LABEL || map->label == me->map.label))
726 lde_map_del(ln, me, 1);
727
8429abe0
RW
728 /* LRl.3: first check if we have a pending withdraw running */
729 lw = (struct lde_wdraw *)fec_find(&ln->sent_wdraw, &fn->fec);
be8e0d31 730 if (lw && (map->label == NO_LABEL || map->label == lw->label)) {
8429abe0
RW
731 /* LRl.4: delete record of outstanding lbl withdraw */
732 lde_wdraw_del(ln, lw);
8429abe0 733
7c2abbd7
RW
734 /* send pending label mapping if any */
735 pending_map = fec_find(&ln->sent_map_pending, &fn->fec);
736 if (pending_map) {
737 lde_send_labelmapping(ln, fn, 1);
738 lde_map_pending_del(ln, pending_map);
739 }
740 }
8429abe0
RW
741
742 /*
743 * LRl.11 - 13 are unnecessary since we remove the label from
744 * forwarding/switching as soon as the FEC is unreachable.
745 */
746 }
747}
748
749void
750lde_check_withdraw(struct map *map, struct lde_nbr *ln)
751{
752 struct fec fec;
753 struct fec_node *fn;
754 struct fec_nh *fnh;
755 struct lde_map *me;
756 struct l2vpn_pw *pw;
757
0bcc2916
RW
758 /* wildcard label withdraw */
759 if (map->type == MAP_TYPE_WILDCARD ||
d4afb819 760 map->type == MAP_TYPE_TYPED_WCARD ||
0bcc2916
RW
761 (map->type == MAP_TYPE_PWID && !(map->flags & F_MAP_PW_ID))) {
762 lde_check_withdraw_wcard(map, ln);
8429abe0 763 return;
0bcc2916 764 }
8429abe0
RW
765
766 lde_map2fec(map, ln->id, &fec);
767 fn = (struct fec_node *)fec_find(&ft, &fec);
768 if (fn == NULL)
769 fn = fec_add(&fec);
770
771 /* LWd.1: remove label from forwarding/switching use */
772 LIST_FOREACH(fnh, &fn->nexthops, entry) {
773 switch (fec.type) {
774 case FEC_TYPE_IPV4:
775 case FEC_TYPE_IPV6:
776 if (!lde_address_find(ln, fnh->af, &fnh->nexthop))
777 continue;
778 break;
779 case FEC_TYPE_PWID:
780 pw = (struct l2vpn_pw *) fn->data;
781 if (pw == NULL)
782 continue;
783 break;
784 default:
785 break;
786 }
be8e0d31
RW
787 if (map->label != NO_LABEL && map->label != fnh->remote_label)
788 continue;
789
8429abe0
RW
790 lde_send_delete_klabel(fn, fnh);
791 fnh->remote_label = NO_LABEL;
792 }
793
794 /* LWd.2: send label release */
0bcc2916 795 lde_send_labelrelease(ln, fn, NULL, map->label);
8429abe0
RW
796
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);
802}
803
804void
805lde_check_withdraw_wcard(struct map *map, struct lde_nbr *ln)
806{
807 struct fec *f;
808 struct fec_node *fn;
809 struct fec_nh *fnh;
810 struct lde_map *me;
811
812 /* LWd.2: send label release */
0bcc2916 813 lde_send_labelrelease(ln, NULL, map, map->label);
8429abe0
RW
814
815 RB_FOREACH(f, fec_tree, &ft) {
816 fn = (struct fec_node *)f;
0bcc2916
RW
817 me = (struct lde_map *)fec_find(&ln->recv_map, &fn->fec);
818
819 if (lde_wildcard_apply(map, &fn->fec, me) == 0)
820 continue;
8429abe0
RW
821
822 /* LWd.1: remove label from forwarding/switching use */
823 LIST_FOREACH(fnh, &fn->nexthops, entry) {
824 switch (f->type) {
825 case FEC_TYPE_IPV4:
826 case FEC_TYPE_IPV6:
827 if (!lde_address_find(ln, fnh->af,
828 &fnh->nexthop))
829 continue;
830 break;
831 case FEC_TYPE_PWID:
832 if (f->u.pwid.lsr_id.s_addr != ln->id.s_addr)
833 continue;
834 break;
835 default:
836 break;
837 }
be8e0d31
RW
838 if (map->label != NO_LABEL && map->label !=
839 fnh->remote_label)
840 continue;
841
8429abe0
RW
842 lde_send_delete_klabel(fn, fnh);
843 fnh->remote_label = NO_LABEL;
844 }
845
846 /* LWd.3: check previously received label mapping */
8429abe0
RW
847 if (me && (map->label == NO_LABEL ||
848 map->label == me->map.label))
849 /*
850 * LWd.4: remove record of previously received
851 * label mapping
852 */
853 lde_map_del(ln, me, 0);
854 }
855}
856
0bcc2916
RW
857int
858lde_wildcard_apply(struct map *wcard, struct fec *fec, struct lde_map *me)
859{
860 switch (wcard->type) {
861 case MAP_TYPE_WILDCARD:
862 /* full wildcard */
863 return (1);
d4afb819
RW
864 case MAP_TYPE_TYPED_WCARD:
865 switch (wcard->fec.twcard.type) {
866 case MAP_TYPE_PREFIX:
867 if (wcard->fec.twcard.u.prefix_af == AF_INET &&
868 fec->type != FEC_TYPE_IPV4)
869 return (0);
870 if (wcard->fec.twcard.u.prefix_af == AF_INET6 &&
871 fec->type != FEC_TYPE_IPV6)
872 return (0);
873 return (1);
aba50a83
RW
874 case MAP_TYPE_PWID:
875 if (fec->type != FEC_TYPE_PWID)
876 return (0);
877 if (wcard->fec.twcard.u.pw_type != PW_TYPE_WILDCARD &&
878 wcard->fec.twcard.u.pw_type != fec->u.pwid.type)
879 return (0);
880 return (1);
d4afb819
RW
881 default:
882 fatalx("lde_wildcard_apply: unexpected fec type");
883 }
884 break;
0bcc2916
RW
885 case MAP_TYPE_PWID:
886 /* RFC4447 pw-id group wildcard */
887 if (fec->type != FEC_TYPE_PWID)
888 return (0);
889 if (fec->u.pwid.type != wcard->fec.pwid.type)
890 return (0);
891 if (me == NULL || (me->map.fec.pwid.group_id !=
892 wcard->fec.pwid.group_id))
893 return (0);
894 return (1);
895 default:
896 fatalx("lde_wildcard_apply: unexpected fec type");
897 }
898}
899
8429abe0
RW
900/* gabage collector timer: timer to remove dead entries from the LIB */
901
902/* ARGSUSED */
eac6e3f0
RW
903int
904lde_gc_timer(struct thread *thread)
8429abe0
RW
905{
906 struct fec *fec, *safe;
907 struct fec_node *fn;
908 int count = 0;
909
910 RB_FOREACH_SAFE(fec, fec_tree, &ft, safe) {
911 fn = (struct fec_node *) fec;
912
913 if (!LIST_EMPTY(&fn->nexthops) ||
d3e1887a
RW
914 !RB_EMPTY(&fn->downstream) ||
915 !RB_EMPTY(&fn->upstream))
8429abe0
RW
916 continue;
917
918 fec_remove(&ft, &fn->fec);
919 free(fn);
920 count++;
921 }
922
923 if (count > 0)
924 log_debug("%s: %u entries removed", __func__, count);
925
926 lde_gc_start_timer();
eac6e3f0
RW
927
928 return (0);
8429abe0
RW
929}
930
931void
932lde_gc_start_timer(void)
933{
eac6e3f0
RW
934 THREAD_TIMER_OFF(gc_timer);
935 gc_timer = thread_add_timer(master, lde_gc_timer, NULL,
ffa2c898 936 LDE_GC_INTERVAL, NULL);
8429abe0
RW
937}
938
939void
940lde_gc_stop_timer(void)
941{
eac6e3f0 942 THREAD_TIMER_OFF(gc_timer);
8429abe0 943}