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