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