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