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