Return to iface.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / bird / proto / ospf |
1.1 ! misho 1: /* ! 2: * BIRD -- OSPF ! 3: * ! 4: * (c) 1999--2005 Ondrej Filip <feela@network.cz> ! 5: * (c) 2009--2014 Ondrej Zajicek <santiago@crfreenet.org> ! 6: * (c) 2009--2014 CZ.NIC z.s.p.o. ! 7: * ! 8: * Can be freely distributed and used under the terms of the GNU GPL. ! 9: */ ! 10: ! 11: #include "ospf.h" ! 12: #include "nest/password.h" ! 13: ! 14: ! 15: const char *ospf_is_names[] = { ! 16: "Down", "Loopback", "Waiting", "PtP", "DROther", "Backup", "DR" ! 17: }; ! 18: ! 19: const char *ospf_ism_names[] = { ! 20: "InterfaceUp", "WaitTimer", "BackupSeen", "NeighborChange", ! 21: "LoopInd", "UnloopInd", "InterfaceDown" ! 22: }; ! 23: ! 24: const char *ospf_it[] = { "broadcast", "nbma", "ptp", "ptmp", "virtual link" }; ! 25: ! 26: ! 27: static void ! 28: poll_timer_hook(timer * timer) ! 29: { ! 30: ospf_send_hello(timer->data, OHS_POLL, NULL); ! 31: } ! 32: ! 33: static void ! 34: hello_timer_hook(timer * timer) ! 35: { ! 36: ospf_send_hello(timer->data, OHS_HELLO, NULL); ! 37: } ! 38: ! 39: static void ! 40: wait_timer_hook(timer * timer) ! 41: { ! 42: struct ospf_iface *ifa = (struct ospf_iface *) timer->data; ! 43: struct ospf_proto *p = ifa->oa->po; ! 44: ! 45: OSPF_TRACE(D_EVENTS, "Wait timer fired on %s", ifa->ifname); ! 46: ospf_iface_sm(ifa, ISM_WAITF); ! 47: } ! 48: ! 49: static inline uint ! 50: ifa_tx_length(struct ospf_iface *ifa) ! 51: { ! 52: return ifa->cf->tx_length ?: ifa->iface->mtu; ! 53: } ! 54: ! 55: static inline uint ! 56: ifa_tx_hdrlen(struct ospf_iface *ifa) ! 57: { ! 58: uint hlen = SIZE_OF_IP_HEADER; ! 59: ! 60: /* Relevant just for OSPFv2 */ ! 61: if (ifa->autype == OSPF_AUTH_CRYPT) ! 62: hlen += max_mac_length(ifa->passwords); ! 63: ! 64: return hlen; ! 65: } ! 66: ! 67: static inline uint ! 68: ifa_bufsize(struct ospf_iface *ifa) ! 69: { ! 70: uint bsize = ifa->cf->rx_buffer ?: ifa->iface->mtu; ! 71: return MAX(bsize, ifa->tx_length); ! 72: } ! 73: ! 74: static inline uint ! 75: ifa_flood_queue_size(struct ospf_iface *ifa) ! 76: { ! 77: return ifa->tx_length / 24; ! 78: } ! 79: ! 80: int ! 81: ospf_iface_assure_bufsize(struct ospf_iface *ifa, uint plen) ! 82: { ! 83: plen += ifa->tx_hdrlen; ! 84: ! 85: if (plen <= ifa->sk->tbsize) ! 86: return 0; ! 87: ! 88: if (ifa->cf->rx_buffer || (plen > 0xffff)) ! 89: return -1; ! 90: ! 91: plen = BIRD_ALIGN(plen, 1024); ! 92: plen = MIN(plen, 0xffff); ! 93: sk_set_tbsize(ifa->sk, plen); ! 94: return 1; ! 95: } ! 96: ! 97: ! 98: struct nbma_node * ! 99: find_nbma_node_(list *nnl, ip_addr ip) ! 100: { ! 101: struct nbma_node *nn; ! 102: ! 103: WALK_LIST(nn, *nnl) ! 104: if (ipa_equal(nn->ip, ip)) ! 105: return nn; ! 106: ! 107: return NULL; ! 108: } ! 109: ! 110: ! 111: static int ! 112: ospf_sk_open(struct ospf_iface *ifa) ! 113: { ! 114: struct ospf_proto *p = ifa->oa->po; ! 115: ! 116: sock *sk = sk_new(ifa->pool); ! 117: sk->type = SK_IP; ! 118: sk->dport = OSPF_PROTO; ! 119: sk->saddr = ifa->addr->ip; ! 120: sk->iface = ifa->iface; ! 121: ! 122: sk->tos = ifa->cf->tx_tos; ! 123: sk->priority = ifa->cf->tx_priority; ! 124: sk->rx_hook = ospf_rx_hook; ! 125: // sk->tx_hook = ospf_tx_hook; ! 126: sk->err_hook = ospf_err_hook; ! 127: sk->rbsize = sk->tbsize = ifa_bufsize(ifa); ! 128: sk->data = (void *) ifa; ! 129: sk->flags = SKF_LADDR_RX | (ifa->check_ttl ? SKF_TTL_RX : 0); ! 130: sk->ttl = ifa->cf->ttl_security ? 255 : 1; ! 131: ! 132: if (sk_open(sk) < 0) ! 133: goto err; ! 134: ! 135: /* 12 is an offset of the checksum in an OSPFv3 packet */ ! 136: if (ospf_is_v3(p)) ! 137: if (sk_set_ipv6_checksum(sk, 12) < 0) ! 138: goto err; ! 139: ! 140: if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_PTP)) ! 141: { ! 142: if (ifa->cf->real_bcast) ! 143: { ! 144: ifa->all_routers = ifa->addr->brd; ! 145: ifa->des_routers = IPA_NONE; ! 146: ! 147: if (sk_setup_broadcast(sk) < 0) ! 148: goto err; ! 149: } ! 150: else ! 151: { ! 152: ifa->all_routers = ospf_is_v2(p) ? IP4_OSPF_ALL_ROUTERS : IP6_OSPF_ALL_ROUTERS; ! 153: ifa->des_routers = ospf_is_v2(p) ? IP4_OSPF_DES_ROUTERS : IP6_OSPF_DES_ROUTERS; ! 154: ! 155: if (sk_setup_multicast(sk) < 0) ! 156: goto err; ! 157: ! 158: if (sk_join_group(sk, ifa->all_routers) < 0) ! 159: goto err; ! 160: } ! 161: } ! 162: ! 163: ifa->sk = sk; ! 164: ifa->sk_dr = 0; ! 165: return 1; ! 166: ! 167: err: ! 168: sk_log_error(sk, p->p.name); ! 169: rfree(sk); ! 170: return 0; ! 171: } ! 172: ! 173: static inline void ! 174: ospf_sk_join_dr(struct ospf_iface *ifa) ! 175: { ! 176: if (ifa->sk_dr) ! 177: return; ! 178: ! 179: if (sk_join_group(ifa->sk, ifa->des_routers) < 0) ! 180: sk_log_error(ifa->sk, ifa->oa->po->p.name); ! 181: ! 182: ifa->sk_dr = 1; ! 183: } ! 184: ! 185: static inline void ! 186: ospf_sk_leave_dr(struct ospf_iface *ifa) ! 187: { ! 188: if (!ifa->sk_dr) ! 189: return; ! 190: ! 191: if (sk_leave_group(ifa->sk, ifa->des_routers) < 0) ! 192: sk_log_error(ifa->sk, ifa->oa->po->p.name); ! 193: ! 194: ifa->sk_dr = 0; ! 195: } ! 196: ! 197: void ! 198: ospf_open_vlink_sk(struct ospf_proto *p) ! 199: { ! 200: sock *sk = sk_new(p->p.pool); ! 201: sk->type = SK_IP; ! 202: sk->dport = OSPF_PROTO; ! 203: ! 204: /* FIXME: configurable tos/priority ? */ ! 205: sk->tos = IP_PREC_INTERNET_CONTROL; ! 206: sk->priority = sk_priority_control; ! 207: sk->err_hook = ospf_verr_hook; ! 208: ! 209: sk->rbsize = 0; ! 210: sk->tbsize = ospf_is_v2(p) ? IP4_MIN_MTU : IP6_MIN_MTU; ! 211: sk->data = (void *) p; ! 212: sk->flags = 0; ! 213: ! 214: if (sk_open(sk) < 0) ! 215: goto err; ! 216: ! 217: /* 12 is an offset of the checksum in an OSPFv3 packet */ ! 218: if (ospf_is_v3(p)) ! 219: if (sk_set_ipv6_checksum(sk, 12) < 0) ! 220: goto err; ! 221: ! 222: p->vlink_sk = sk; ! 223: return; ! 224: ! 225: err: ! 226: sk_log_error(sk, p->p.name); ! 227: log(L_ERR "%s: Cannot open virtual link socket", p->p.name); ! 228: rfree(sk); ! 229: } ! 230: ! 231: static void ! 232: ospf_iface_down(struct ospf_iface *ifa) ! 233: { ! 234: struct ospf_proto *p = ifa->oa->po; ! 235: struct ospf_neighbor *n, *nx; ! 236: struct ospf_iface *iff; ! 237: ! 238: if (ifa->type != OSPF_IT_VLINK) ! 239: { ! 240: if (ospf_is_v3(ifa->oa->po)) ! 241: OSPF_TRACE(D_EVENTS, "Removing interface %s (IID %d) from area %R", ! 242: ifa->ifname, ifa->instance_id, ifa->oa->areaid); ! 243: else if (ifa->addr->flags & IA_PEER) ! 244: OSPF_TRACE(D_EVENTS, "Removing interface %s (peer %I) from area %R", ! 245: ifa->ifname, ifa->addr->opposite, ifa->oa->areaid); ! 246: else ! 247: OSPF_TRACE(D_EVENTS, "Removing interface %s (%I/%d) from area %R", ! 248: ifa->ifname, ifa->addr->prefix, ifa->addr->pxlen, ifa->oa->areaid); ! 249: ! 250: /* First of all kill all the related vlinks */ ! 251: WALK_LIST(iff, p->iface_list) ! 252: { ! 253: if ((iff->type == OSPF_IT_VLINK) && (iff->vifa == ifa)) ! 254: ospf_iface_sm(iff, ISM_DOWN); ! 255: } ! 256: } ! 257: ! 258: WALK_LIST_DELSAFE(n, nx, ifa->neigh_list) ! 259: ospf_neigh_sm(n, INM_KILLNBR); ! 260: ! 261: if (ifa->hello_timer) ! 262: tm_stop(ifa->hello_timer); ! 263: ! 264: if (ifa->poll_timer) ! 265: tm_stop(ifa->poll_timer); ! 266: ! 267: if (ifa->wait_timer) ! 268: tm_stop(ifa->wait_timer); ! 269: ! 270: ospf_flush2_lsa(p, &ifa->link_lsa); ! 271: ospf_flush2_lsa(p, &ifa->net_lsa); ! 272: ospf_flush2_lsa(p, &ifa->pxn_lsa); ! 273: ! 274: if (ifa->type == OSPF_IT_VLINK) ! 275: { ! 276: ifa->vifa = NULL; ! 277: ifa->addr = NULL; ! 278: ifa->cost = 0; ! 279: ifa->vip = IPA_NONE; ! 280: } ! 281: ! 282: ifa->rt_pos_beg = 0; ! 283: ifa->rt_pos_end = 0; ! 284: ifa->px_pos_beg = 0; ! 285: ifa->px_pos_end = 0; ! 286: } ! 287: ! 288: ! 289: void ! 290: ospf_iface_remove(struct ospf_iface *ifa) ! 291: { ! 292: struct ospf_proto *p = ifa->oa->po; ! 293: int i; ! 294: ! 295: if (ifa->type == OSPF_IT_VLINK) ! 296: OSPF_TRACE(D_EVENTS, "Removing vlink to %R via area %R", ifa->vid, ifa->voa->areaid); ! 297: ! 298: /* Release LSAs from flood queue */ ! 299: if (!ifa->stub) ! 300: for (i = 0; i < ifa->flood_queue_used; i++) ! 301: ifa->flood_queue[i]->ret_count--; ! 302: ! 303: ospf_iface_sm(ifa, ISM_DOWN); ! 304: rem_node(NODE ifa); ! 305: rfree(ifa->pool); ! 306: } ! 307: ! 308: void ! 309: ospf_iface_shutdown(struct ospf_iface *ifa) ! 310: { ! 311: if (ifa->state > OSPF_IS_DOWN) ! 312: ospf_send_hello(ifa, OHS_SHUTDOWN, NULL); ! 313: } ! 314: ! 315: /** ! 316: * ospf_iface_chstate - handle changes of interface state ! 317: * @ifa: OSPF interface ! 318: * @state: new state ! 319: * ! 320: * Many actions must be taken according to interface state changes. New network ! 321: * LSAs must be originated, flushed, new multicast sockets to listen for messages for ! 322: * %ALLDROUTERS have to be opened, etc. ! 323: */ ! 324: void ! 325: ospf_iface_chstate(struct ospf_iface *ifa, u8 state) ! 326: { ! 327: struct ospf_proto *p = ifa->oa->po; ! 328: u8 oldstate = ifa->state; ! 329: ! 330: if (state == oldstate) ! 331: return; ! 332: ! 333: OSPF_TRACE(D_EVENTS, "Interface %s changed state from %s to %s", ! 334: ifa->ifname, ospf_is_names[oldstate], ospf_is_names[state]); ! 335: ! 336: ifa->state = state; ! 337: ! 338: if ((ifa->type == OSPF_IT_BCAST) && ipa_nonzero(ifa->des_routers) && ifa->sk) ! 339: { ! 340: if ((state == OSPF_IS_BACKUP) || (state == OSPF_IS_DR)) ! 341: ospf_sk_join_dr(ifa); ! 342: else ! 343: ospf_sk_leave_dr(ifa); ! 344: } ! 345: ! 346: if ((oldstate > OSPF_IS_LOOP) && (state <= OSPF_IS_LOOP)) ! 347: ospf_iface_down(ifa); ! 348: ! 349: /* RFC 2328 12.4 Event 2 - iface state change */ ! 350: ospf_notify_rt_lsa(ifa->oa); ! 351: ! 352: /* RFC 5340 4.4.3 Event 1 - iface state change */ ! 353: ospf_notify_link_lsa(ifa); ! 354: ! 355: /* RFC 2328 12.4 Event 3 - iface enters/leaves DR state */ ! 356: ospf_notify_net_lsa(ifa); ! 357: } ! 358: ! 359: /** ! 360: * ospf_iface_sm - OSPF interface state machine ! 361: * @ifa: OSPF interface ! 362: * @event: event comming to state machine ! 363: * ! 364: * This fully respects 9.3 of RFC 2328 except we have slightly ! 365: * different handling of %DOWN and %LOOP state. We remove intefaces ! 366: * that are %DOWN. %DOWN state is used when an interface is waiting ! 367: * for a lock. %LOOP state is used when an interface does not have a ! 368: * link. ! 369: */ ! 370: void ! 371: ospf_iface_sm(struct ospf_iface *ifa, int event) ! 372: { ! 373: DBG("SM on %s. Event is '%s'\n", ifa->ifname, ospf_ism_names[event]); ! 374: ! 375: switch (event) ! 376: { ! 377: case ISM_UP: ! 378: if (ifa->state <= OSPF_IS_LOOP) ! 379: { ! 380: /* Now, nothing should be adjacent */ ! 381: if ((ifa->type == OSPF_IT_PTP) || ! 382: (ifa->type == OSPF_IT_PTMP) || ! 383: (ifa->type == OSPF_IT_VLINK)) ! 384: { ! 385: ospf_iface_chstate(ifa, OSPF_IS_PTP); ! 386: } ! 387: else ! 388: { ! 389: if (ifa->priority == 0) ! 390: ospf_iface_chstate(ifa, OSPF_IS_DROTHER); ! 391: else ! 392: { ! 393: ospf_iface_chstate(ifa, OSPF_IS_WAITING); ! 394: if (ifa->wait_timer) ! 395: tm_start(ifa->wait_timer, ifa->waitint); ! 396: } ! 397: } ! 398: ! 399: if (ifa->hello_timer) ! 400: tm_start(ifa->hello_timer, ifa->helloint); ! 401: ! 402: if (ifa->poll_timer) ! 403: tm_start(ifa->poll_timer, ifa->pollint); ! 404: ! 405: ospf_send_hello(ifa, OHS_HELLO, NULL); ! 406: } ! 407: break; ! 408: ! 409: case ISM_BACKS: ! 410: case ISM_WAITF: ! 411: if (ifa->state == OSPF_IS_WAITING) ! 412: ospf_dr_election(ifa); ! 413: break; ! 414: ! 415: case ISM_NEICH: ! 416: if (ifa->state >= OSPF_IS_DROTHER) ! 417: ospf_dr_election(ifa); ! 418: break; ! 419: ! 420: case ISM_LOOP: ! 421: if ((ifa->state > OSPF_IS_LOOP) && ifa->check_link) ! 422: ospf_iface_chstate(ifa, OSPF_IS_LOOP); ! 423: break; ! 424: ! 425: case ISM_UNLOOP: ! 426: /* Immediate go UP */ ! 427: if (ifa->state == OSPF_IS_LOOP) ! 428: ospf_iface_sm(ifa, ISM_UP); ! 429: break; ! 430: ! 431: case ISM_DOWN: ! 432: ospf_iface_chstate(ifa, OSPF_IS_DOWN); ! 433: break; ! 434: ! 435: default: ! 436: bug("OSPF_I_SM - Unknown event?"); ! 437: break; ! 438: } ! 439: ! 440: } ! 441: ! 442: static u8 ! 443: ospf_iface_classify_(struct iface *ifa, struct ifa *addr) ! 444: { ! 445: if (ipa_nonzero(addr->opposite)) ! 446: return (ifa->flags & IF_MULTICAST) ? OSPF_IT_PTP : OSPF_IT_PTMP; ! 447: ! 448: if ((ifa->flags & (IF_MULTIACCESS | IF_MULTICAST)) == ! 449: (IF_MULTIACCESS | IF_MULTICAST)) ! 450: return OSPF_IT_BCAST; ! 451: ! 452: if ((ifa->flags & (IF_MULTIACCESS | IF_MULTICAST)) == IF_MULTIACCESS) ! 453: return OSPF_IT_NBMA; ! 454: ! 455: return OSPF_IT_PTP; ! 456: } ! 457: ! 458: static inline u8 ! 459: ospf_iface_classify(u8 type, struct ifa *addr) ! 460: { ! 461: return (type != OSPF_IT_UNDEF) ? type : ospf_iface_classify_(addr->iface, addr); ! 462: } ! 463: ! 464: ! 465: struct ospf_iface * ! 466: ospf_iface_find(struct ospf_proto *p, struct iface *what) ! 467: { ! 468: struct ospf_iface *ifa; ! 469: ! 470: WALK_LIST(ifa, p->iface_list) ! 471: if ((ifa->iface == what) && (ifa->type != OSPF_IT_VLINK)) ! 472: return ifa; ! 473: ! 474: return NULL; ! 475: } ! 476: ! 477: static void ! 478: ospf_iface_add(struct object_lock *lock) ! 479: { ! 480: struct ospf_iface *ifa = lock->data; ! 481: struct ospf_proto *p = ifa->oa->po; ! 482: ! 483: /* Open socket if interface is not stub */ ! 484: if (! ifa->stub && ! ospf_sk_open(ifa)) ! 485: { ! 486: log(L_ERR "%s: Cannot open socket for %s, declaring as stub", p->p.name, ifa->ifname); ! 487: ifa->ioprob = OSPF_I_SK; ! 488: ifa->stub = 1; ! 489: } ! 490: ! 491: if (! ifa->stub) ! 492: { ! 493: ifa->hello_timer = tm_new_set(ifa->pool, hello_timer_hook, ifa, 0, ifa->helloint); ! 494: ! 495: if (ifa->type == OSPF_IT_NBMA) ! 496: ifa->poll_timer = tm_new_set(ifa->pool, poll_timer_hook, ifa, 0, ifa->pollint); ! 497: ! 498: if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA)) ! 499: ifa->wait_timer = tm_new_set(ifa->pool, wait_timer_hook, ifa, 0, 0); ! 500: ! 501: ifa->flood_queue_size = ifa_flood_queue_size(ifa); ! 502: ifa->flood_queue = mb_allocz(ifa->pool, ifa->flood_queue_size * sizeof(void *)); ! 503: } ! 504: ! 505: /* Do iface UP, unless there is no link (then wait in LOOP state) */ ! 506: if (!ifa->check_link || (ifa->iface->flags & IF_LINK_UP)) ! 507: ospf_iface_sm(ifa, ISM_UP); ! 508: else ! 509: ospf_iface_chstate(ifa, OSPF_IS_LOOP); ! 510: } ! 511: ! 512: static inline void ! 513: add_nbma_node(struct ospf_iface *ifa, struct nbma_node *src, int found) ! 514: { ! 515: struct nbma_node *n = mb_alloc(ifa->pool, sizeof(struct nbma_node)); ! 516: add_tail(&ifa->nbma_list, NODE n); ! 517: n->ip = src->ip; ! 518: n->eligible = src->eligible; ! 519: n->found = found; ! 520: } ! 521: ! 522: static int ! 523: ospf_iface_stubby(struct ospf_iface_patt *ip, struct ifa *addr) ! 524: { ! 525: /* a host address */ ! 526: if (addr->flags & IA_HOST) ! 527: return 1; ! 528: ! 529: /* a loopback iface */ ! 530: if (addr->iface->flags & IF_LOOPBACK) ! 531: return 1; ! 532: ! 533: /* ! 534: * For compatibility reasons on BSD systems, we force OSPF ! 535: * interfaces with non-primary IP prefixes to be stub. ! 536: */ ! 537: #if defined(OSPFv2) && !defined(CONFIG_MC_PROPER_SRC) ! 538: if (!ip->bsd_secondary && !(addr->flags & IA_PRIMARY)) ! 539: return 1; ! 540: #endif ! 541: ! 542: return ip->stub; ! 543: } ! 544: ! 545: void ! 546: ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *ip) ! 547: { ! 548: struct ospf_proto *p = oa->po; ! 549: struct iface *iface = addr->iface; ! 550: struct ospf_iface *ifa; ! 551: struct pool *pool; ! 552: ! 553: if (ospf_is_v3(p)) ! 554: OSPF_TRACE(D_EVENTS, "Adding interface %s (IID %d) to area %R", ! 555: iface->name, ip->instance_id, oa->areaid); ! 556: else if (addr->flags & IA_PEER) ! 557: OSPF_TRACE(D_EVENTS, "Adding interface %s (peer %I) to area %R", ! 558: iface->name, addr->opposite, oa->areaid); ! 559: else ! 560: OSPF_TRACE(D_EVENTS, "Adding interface %s (%I/%d) to area %R", ! 561: iface->name, addr->prefix, addr->pxlen, oa->areaid); ! 562: ! 563: pool = rp_new(p->p.pool, "OSPF Interface"); ! 564: ifa = mb_allocz(pool, sizeof(struct ospf_iface)); ! 565: ifa->iface = iface; ! 566: ifa->addr = addr; ! 567: ifa->oa = oa; ! 568: ifa->cf = ip; ! 569: ifa->pool = pool; ! 570: ! 571: ifa->iface_id = iface->index; ! 572: ifa->ifname = iface->name; ! 573: ! 574: ifa->cost = ip->cost; ! 575: ifa->rxmtint = ip->rxmtint; ! 576: ifa->inftransdelay = ip->inftransdelay; ! 577: ifa->priority = ip->priority; ! 578: ifa->helloint = ip->helloint; ! 579: ifa->pollint = ip->pollint; ! 580: ifa->strictnbma = ip->strictnbma; ! 581: ifa->waitint = ip->waitint; ! 582: ifa->deadint = ip->deadint; ! 583: ifa->stub = ospf_iface_stubby(ip, addr); ! 584: ifa->ioprob = OSPF_I_OK; ! 585: ifa->tx_length = ifa_tx_length(ifa); ! 586: ifa->tx_hdrlen = ifa_tx_hdrlen(ifa); ! 587: ifa->check_link = ip->check_link; ! 588: ifa->ecmp_weight = ip->ecmp_weight; ! 589: ifa->check_ttl = (ip->ttl_security == 1); ! 590: ifa->bfd = ip->bfd; ! 591: ifa->autype = ip->autype; ! 592: ifa->passwords = ip->passwords; ! 593: ifa->instance_id = ip->instance_id; ! 594: ! 595: ifa->ptp_netmask = !(addr->flags & IA_PEER); ! 596: if (ip->ptp_netmask < 2) ! 597: ifa->ptp_netmask = ip->ptp_netmask; ! 598: ! 599: ! 600: ifa->type = ospf_iface_classify(ip->type, addr); ! 601: ! 602: /* Check validity of interface type */ ! 603: int old_type = ifa->type; ! 604: u32 if_multi_flag = ip->real_bcast ? IF_BROADCAST : IF_MULTICAST; ! 605: ! 606: if (ospf_is_v2(p) && (ifa->type == OSPF_IT_BCAST) && (addr->flags & IA_PEER)) ! 607: ifa->type = OSPF_IT_PTP; ! 608: ! 609: if (ospf_is_v2(p) && (ifa->type == OSPF_IT_NBMA) && (addr->flags & IA_PEER)) ! 610: ifa->type = OSPF_IT_PTMP; ! 611: ! 612: if ((ifa->type == OSPF_IT_BCAST) && !(iface->flags & if_multi_flag) && !ifa->stub) ! 613: ifa->type = OSPF_IT_NBMA; ! 614: ! 615: if ((ifa->type == OSPF_IT_PTP) && !(iface->flags & if_multi_flag) && !ifa->stub) ! 616: ifa->type = OSPF_IT_PTMP; ! 617: ! 618: if (ifa->type != old_type) ! 619: log(L_WARN "%s: Cannot use interface %s as %s, forcing %s", ! 620: p->p.name, iface->name, ospf_it[old_type], ospf_it[ifa->type]); ! 621: ! 622: ! 623: if ((ifa->type == OSPF_IT_PTP) || (ifa->type == OSPF_IT_PTMP)) ! 624: ifa->link_lsa_suppression = ip->link_lsa_suppression; ! 625: ! 626: ifa->state = OSPF_IS_DOWN; ! 627: init_list(&ifa->neigh_list); ! 628: init_list(&ifa->nbma_list); ! 629: ! 630: struct nbma_node *nb; ! 631: WALK_LIST(nb, ip->nbma_list) ! 632: { ! 633: /* In OSPFv3, addr is link-local while configured neighbors could ! 634: have global IP (although RFC 5340 C.5 says link-local addresses ! 635: should be used). Because OSPFv3 iface is not subnet-specific, ! 636: there is no need for ipa_in_net() check */ ! 637: ! 638: if (ospf_is_v2(p) && !ipa_in_net(nb->ip, addr->prefix, addr->pxlen)) ! 639: continue; ! 640: ! 641: if (ospf_is_v3(p) && !ipa_is_link_local(nb->ip)) ! 642: log(L_WARN "%s: Configured neighbor address (%I) should be link-local", ! 643: p->p.name, nb->ip); ! 644: ! 645: add_nbma_node(ifa, nb, 0); ! 646: } ! 647: ! 648: add_tail(&oa->po->iface_list, NODE ifa); ! 649: ! 650: struct object_lock *lock = olock_new(pool); ! 651: lock->addr = ospf_is_v2(p) ? ifa->addr->prefix : IPA_NONE; ! 652: lock->type = OBJLOCK_IP; ! 653: lock->port = OSPF_PROTO; ! 654: lock->inst = ifa->instance_id; ! 655: lock->iface = iface; ! 656: lock->data = ifa; ! 657: lock->hook = ospf_iface_add; ! 658: ! 659: olock_acquire(lock); ! 660: } ! 661: ! 662: void ! 663: ospf_iface_new_vlink(struct ospf_proto *p, struct ospf_iface_patt *ip) ! 664: { ! 665: struct ospf_iface *ifa; ! 666: struct pool *pool; ! 667: ! 668: if (!p->vlink_sk) ! 669: return; ! 670: ! 671: OSPF_TRACE(D_EVENTS, "Adding vlink to %R via area %R", ip->vid, ip->voa); ! 672: ! 673: /* Vlink ifname is stored just after the ospf_iface structure */ ! 674: ! 675: pool = rp_new(p->p.pool, "OSPF Vlink"); ! 676: ifa = mb_allocz(pool, sizeof(struct ospf_iface) + 16); ! 677: ifa->oa = p->backbone; ! 678: ifa->cf = ip; ! 679: ifa->pool = pool; ! 680: ! 681: /* Assign iface ID, for vlinks, this is ugly hack */ ! 682: u32 vlink_id = p->last_vlink_id++; ! 683: ifa->iface_id = vlink_id + OSPF_VLINK_ID_OFFSET; ! 684: ifa->ifname = (void *) (ifa + 1); ! 685: bsprintf(ifa->ifname, "vlink%d", vlink_id); ! 686: ! 687: ifa->voa = ospf_find_area(p, ip->voa); ! 688: ifa->vid = ip->vid; ! 689: ifa->sk = p->vlink_sk; ! 690: ! 691: ifa->helloint = ip->helloint; ! 692: ifa->rxmtint = ip->rxmtint; ! 693: ifa->waitint = ip->waitint; ! 694: ifa->deadint = ip->deadint; ! 695: ifa->inftransdelay = ip->inftransdelay; ! 696: ifa->tx_length = ospf_is_v2(p) ? IP4_MIN_MTU : IP6_MIN_MTU; ! 697: ifa->tx_hdrlen = ifa_tx_hdrlen(ifa); ! 698: ifa->autype = ip->autype; ! 699: ifa->passwords = ip->passwords; ! 700: ifa->instance_id = ip->instance_id; ! 701: ! 702: ifa->type = OSPF_IT_VLINK; ! 703: ! 704: ifa->state = OSPF_IS_DOWN; ! 705: init_list(&ifa->neigh_list); ! 706: init_list(&ifa->nbma_list); ! 707: ! 708: add_tail(&p->iface_list, NODE ifa); ! 709: ! 710: ifa->hello_timer = tm_new_set(ifa->pool, hello_timer_hook, ifa, 0, ifa->helloint); ! 711: ! 712: ifa->flood_queue_size = ifa_flood_queue_size(ifa); ! 713: ifa->flood_queue = mb_allocz(ifa->pool, ifa->flood_queue_size * sizeof(void *)); ! 714: } ! 715: ! 716: static void ! 717: ospf_iface_change_timer(timer *tm, uint val) ! 718: { ! 719: if (!tm) ! 720: return; ! 721: ! 722: tm->recurrent = val; ! 723: ! 724: if (tm->expires) ! 725: tm_start(tm, val); ! 726: } ! 727: ! 728: static inline void ! 729: ospf_iface_update_flood_queue_size(struct ospf_iface *ifa) ! 730: { ! 731: uint old_size = ifa->flood_queue_size; ! 732: uint new_size = ifa_flood_queue_size(ifa); ! 733: ! 734: if (new_size <= old_size) ! 735: return; ! 736: ! 737: ifa->flood_queue_size = new_size; ! 738: ifa->flood_queue = mb_realloc(ifa->flood_queue, new_size * sizeof(void *)); ! 739: bzero(ifa->flood_queue + old_size, (new_size - old_size) * sizeof(void *)); ! 740: } ! 741: ! 742: int ! 743: ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new) ! 744: { ! 745: struct ospf_proto *p = ifa->oa->po; ! 746: struct ospf_iface_patt *old = ifa->cf; ! 747: char *ifname = ifa->ifname; ! 748: ! 749: /* Type could be changed in ospf_iface_new(), ! 750: but if config values are same then also results are same */ ! 751: int old_type = ospf_iface_classify(old->type, ifa->addr); ! 752: int new_type = ospf_iface_classify(new->type, ifa->addr); ! 753: if (old_type != new_type) ! 754: return 0; ! 755: ! 756: int new_stub = ospf_iface_stubby(new, ifa->addr); ! 757: if (ifa->stub != new_stub) ! 758: return 0; ! 759: ! 760: /* Change of these options would require to reset the iface socket */ ! 761: if ((new->real_bcast != old->real_bcast) || ! 762: (new->tx_tos != old->tx_tos) || ! 763: (new->tx_priority != old->tx_priority) || ! 764: (new->ttl_security != old->ttl_security)) ! 765: return 0; ! 766: ! 767: ifa->cf = new; ! 768: ifa->marked = 0; ! 769: ! 770: ! 771: /* HELLO TIMER */ ! 772: if (ifa->helloint != new->helloint) ! 773: { ! 774: OSPF_TRACE(D_EVENTS, "Changing hello interval of %s from %d to %d", ! 775: ifname, ifa->helloint, new->helloint); ! 776: ! 777: ifa->helloint = new->helloint; ! 778: ospf_iface_change_timer(ifa->hello_timer, ifa->helloint); ! 779: } ! 780: ! 781: /* RXMT TIMER */ ! 782: if (ifa->rxmtint != new->rxmtint) ! 783: { ! 784: OSPF_TRACE(D_EVENTS, "Changing retransmit interval of %s from %d to %d", ! 785: ifname, ifa->rxmtint, new->rxmtint); ! 786: ! 787: ifa->rxmtint = new->rxmtint; ! 788: /* FIXME: Update neighbors' timers */ ! 789: } ! 790: ! 791: /* POLL TIMER */ ! 792: if (ifa->pollint != new->pollint) ! 793: { ! 794: OSPF_TRACE(D_EVENTS, "Changing poll interval of %s from %d to %d", ! 795: ifname, ifa->pollint, new->pollint); ! 796: ! 797: ifa->pollint = new->pollint; ! 798: ospf_iface_change_timer(ifa->poll_timer, ifa->pollint); ! 799: } ! 800: ! 801: /* WAIT TIMER */ ! 802: if (ifa->waitint != new->waitint) ! 803: { ! 804: OSPF_TRACE(D_EVENTS, "Changing wait interval of %s from %d to %d", ! 805: ifname, ifa->waitint, new->waitint); ! 806: ! 807: ifa->waitint = new->waitint; ! 808: if (ifa->wait_timer && ifa->wait_timer->expires) ! 809: tm_start(ifa->wait_timer, ifa->waitint); ! 810: } ! 811: ! 812: /* DEAD TIMER */ ! 813: if (ifa->deadint != new->deadint) ! 814: { ! 815: OSPF_TRACE(D_EVENTS, "Changing dead interval of %s from %d to %d", ! 816: ifname, ifa->deadint, new->deadint); ! 817: ifa->deadint = new->deadint; ! 818: } ! 819: ! 820: /* INFTRANS */ ! 821: if (ifa->inftransdelay != new->inftransdelay) ! 822: { ! 823: OSPF_TRACE(D_EVENTS, "Changing transmit delay of %s from %d to %d", ! 824: ifname, ifa->inftransdelay, new->inftransdelay); ! 825: ifa->inftransdelay = new->inftransdelay; ! 826: } ! 827: ! 828: /* AUTHENTICATION */ ! 829: if (ifa->autype != new->autype) ! 830: { ! 831: OSPF_TRACE(D_EVENTS, "Changing authentication type of %s", ifname); ! 832: ifa->autype = new->autype; ! 833: } ! 834: ! 835: /* Update passwords */ ! 836: ifa->passwords = new->passwords; ! 837: ! 838: /* Update header length */ ! 839: ifa->tx_hdrlen = ifa_tx_hdrlen(ifa); ! 840: ! 841: /* Remaining options are just for proper interfaces */ ! 842: if (ifa->type == OSPF_IT_VLINK) ! 843: return 1; ! 844: ! 845: ! 846: /* COST */ ! 847: if (ifa->cost != new->cost) ! 848: { ! 849: OSPF_TRACE(D_EVENTS, "Changing cost of %s from %d to %d", ! 850: ifname, ifa->cost, new->cost); ! 851: ! 852: ifa->cost = new->cost; ! 853: } ! 854: ! 855: /* PRIORITY */ ! 856: if (ifa->priority != new->priority) ! 857: { ! 858: OSPF_TRACE(D_EVENTS, "Changing priority of %s from %d to %d", ! 859: ifname, ifa->priority, new->priority); ! 860: ! 861: ifa->priority = new->priority; ! 862: ospf_notify_link_lsa(ifa); ! 863: } ! 864: ! 865: /* STRICT NBMA */ ! 866: if (ifa->strictnbma != new->strictnbma) ! 867: { ! 868: OSPF_TRACE(D_EVENTS, "Changing NBMA strictness of %s from %d to %d", ! 869: ifname, ifa->strictnbma, new->strictnbma); ! 870: ifa->strictnbma = new->strictnbma; ! 871: } ! 872: ! 873: struct nbma_node *nb, *nbx; ! 874: ! 875: /* NBMA LIST - remove or update old */ ! 876: WALK_LIST_DELSAFE(nb, nbx, ifa->nbma_list) ! 877: { ! 878: struct nbma_node *nb2 = find_nbma_node_(&new->nbma_list, nb->ip); ! 879: if (nb2) ! 880: { ! 881: if (nb->eligible != nb2->eligible) ! 882: { ! 883: OSPF_TRACE(D_EVENTS, "Changing eligibility of NBMA neighbor %I on %s", ! 884: nb->ip, ifname); ! 885: nb->eligible = nb2->eligible; ! 886: } ! 887: } ! 888: else ! 889: { ! 890: OSPF_TRACE(D_EVENTS, "Removing NBMA neighbor %I on %s", ! 891: nb->ip, ifname); ! 892: rem_node(NODE nb); ! 893: mb_free(nb); ! 894: } ! 895: } ! 896: ! 897: /* NBMA LIST - add new */ ! 898: WALK_LIST(nb, new->nbma_list) ! 899: { ! 900: /* See related note in ospf_iface_new() */ ! 901: if (ospf_is_v2(p) && !ipa_in_net(nb->ip, ifa->addr->prefix, ifa->addr->pxlen)) ! 902: continue; ! 903: ! 904: if (ospf_is_v3(p) && !ipa_is_link_local(nb->ip)) ! 905: log(L_WARN "%s: Configured neighbor address (%I) should be link-local", ! 906: p->p.name, nb->ip); ! 907: ! 908: if (! find_nbma_node(ifa, nb->ip)) ! 909: { ! 910: OSPF_TRACE(D_EVENTS, "Adding NBMA neighbor %I on %s", ! 911: nb->ip, ifname); ! 912: add_nbma_node(ifa, nb, !!find_neigh_by_ip(ifa, nb->ip)); ! 913: } ! 914: } ! 915: ! 916: int update_buffers = 0; ! 917: ! 918: /* TX LENGTH */ ! 919: if (old->tx_length != new->tx_length) ! 920: { ! 921: OSPF_TRACE(D_EVENTS, "Changing TX length of %s from %d to %d", ! 922: ifname, old->tx_length, new->tx_length); ! 923: ! 924: /* ifa cannot be vlink */ ! 925: ifa->tx_length = ifa_tx_length(ifa); ! 926: update_buffers = 1; ! 927: ! 928: if (!ifa->stub) ! 929: ospf_iface_update_flood_queue_size(ifa); ! 930: } ! 931: ! 932: /* RX BUFFER */ ! 933: if (old->rx_buffer != new->rx_buffer) ! 934: { ! 935: OSPF_TRACE(D_EVENTS, "Changing buffer size of %s from %d to %d", ! 936: ifname, old->rx_buffer, new->rx_buffer); ! 937: ! 938: /* ifa cannot be vlink */ ! 939: update_buffers = 1; ! 940: } ! 941: ! 942: /* Buffer size depends on both tx_length and rx_buffer options */ ! 943: if (update_buffers && ifa->sk) ! 944: { ! 945: uint bsize = ifa_bufsize(ifa); ! 946: sk_set_rbsize(ifa->sk, bsize); ! 947: sk_set_tbsize(ifa->sk, bsize); ! 948: } ! 949: ! 950: /* LINK */ ! 951: if (ifa->check_link != new->check_link) ! 952: { ! 953: OSPF_TRACE(D_EVENTS, "%s link check for %s", ! 954: new->check_link ? "Enabling" : "Disabling", ifname); ! 955: ifa->check_link = new->check_link; ! 956: ! 957: /* ifa cannot be vlink */ ! 958: if (!(ifa->iface->flags & IF_LINK_UP)) ! 959: ospf_iface_sm(ifa, ifa->check_link ? ISM_LOOP : ISM_UNLOOP); ! 960: } ! 961: ! 962: /* ECMP weight */ ! 963: if (ifa->ecmp_weight != new->ecmp_weight) ! 964: { ! 965: OSPF_TRACE(D_EVENTS, "Changing ECMP weight of %s from %d to %d", ! 966: ifname, (int)ifa->ecmp_weight + 1, (int)new->ecmp_weight + 1); ! 967: ifa->ecmp_weight = new->ecmp_weight; ! 968: } ! 969: ! 970: /* Link LSA suppression */ ! 971: if (((ifa->type == OSPF_IT_PTP) || (ifa->type == OSPF_IT_PTMP)) && ! 972: (ifa->link_lsa_suppression != new->link_lsa_suppression)) ! 973: { ! 974: OSPF_TRACE(D_EVENTS, "Changing link LSA suppression of %s from %d to %d", ! 975: ifname, ifa->link_lsa_suppression, new->link_lsa_suppression); ! 976: ! 977: ifa->link_lsa_suppression = new->link_lsa_suppression; ! 978: ospf_notify_link_lsa(ifa); ! 979: } ! 980: ! 981: /* BFD */ ! 982: if (ifa->bfd != new->bfd) ! 983: { ! 984: OSPF_TRACE(D_EVENTS, "%s BFD for %s", ! 985: new->bfd ? "Enabling" : "Disabling", ifname); ! 986: ifa->bfd = new->bfd; ! 987: ! 988: struct ospf_neighbor *n; ! 989: WALK_LIST(n, ifa->neigh_list) ! 990: ospf_neigh_update_bfd(n, ifa->bfd); ! 991: } ! 992: ! 993: ! 994: /* instance_id is not updated - it is part of key */ ! 995: ! 996: return 1; ! 997: } ! 998: ! 999: ! 1000: /* ! 1001: * State for matching iface pattterns walk ! 1002: * ! 1003: * This is significantly different in OSPFv2 and OSPFv3. ! 1004: * In OSPFv2, OSPF ifaces are created for each IP prefix (struct ifa) ! 1005: * In OSPFv3, OSPF ifaces are created based on real iface (struct iface) ! 1006: * We support instance_id for both OSPFv2 (RFC 6549) and OSPFv3. ! 1007: * ! 1008: * We process one ifa/iface and match it for all configured instance IDs. We ! 1009: * maintain bitfields to track whether given instance ID was already matched. ! 1010: * We have two bitfields, one global (active) and one per area (ignore), to ! 1011: * detect misconfigured cases where one iface with one instance ID matches in ! 1012: * multiple areas. ! 1013: */ ! 1014: ! 1015: struct ospf_mip_walk { ! 1016: u32 active[8]; /* Bitfield of active instance IDs */ ! 1017: u32 ignore[8]; /* Bitfield of instance IDs matched in current area */ ! 1018: struct ospf_area *oa; /* Current area */ ! 1019: struct ospf_iface_patt *ip; /* Current iface pattern */ ! 1020: struct iface *iface; /* Specified iface (input) */ ! 1021: struct ifa *a; /* Specified ifa (input) */ ! 1022: int warn; /* Whether iface matched in multiple areas */ ! 1023: }; ! 1024: ! 1025: static int ! 1026: ospf_walk_matching_iface_patts(struct ospf_proto *p, struct ospf_mip_walk *s) ! 1027: { ! 1028: int id; ! 1029: ! 1030: if (s->ip) ! 1031: goto step; ! 1032: ! 1033: WALK_LIST(s->oa, p->area_list) ! 1034: { ! 1035: if (s->oa->marked) ! 1036: continue; ! 1037: ! 1038: WALK_LIST(s->ip, s->oa->ac->patt_list) ! 1039: { ! 1040: id = s->ip->instance_id; ! 1041: if (BIT32_TEST(s->ignore, id)) ! 1042: continue; ! 1043: ! 1044: if (iface_patt_match(&s->ip->i, s->iface, s->a)) ! 1045: { ! 1046: /* Now we matched ifa/iface/instance_id for the first time in current area */ ! 1047: BIT32_SET(s->ignore, id); ! 1048: ! 1049: /* If we already found it in previous areas, ignore it and add warning */ ! 1050: if (BIT32_TEST(s->active, id)) ! 1051: { s->warn = 1; continue; } ! 1052: ! 1053: BIT32_SET(s->active, id); ! 1054: return 1; ! 1055: step: ! 1056: ; ! 1057: } ! 1058: } ! 1059: BIT32_ZERO(s->ignore, 256); ! 1060: } ! 1061: ! 1062: if (s->warn) ! 1063: log(L_WARN "%s: Interface %s matches for multiple areas", p->p.name, s->iface->name); ! 1064: ! 1065: return 0; ! 1066: } ! 1067: ! 1068: ! 1069: static struct ospf_iface * ! 1070: ospf_iface_find_by_key(struct ospf_proto *p, struct ifa *a, int instance_id) ! 1071: { ! 1072: struct ospf_iface *ifa; ! 1073: ! 1074: WALK_LIST(ifa, p->iface_list) ! 1075: if ((ifa->addr == a) && (ifa->instance_id == instance_id) && ! 1076: (ifa->type != OSPF_IT_VLINK)) ! 1077: return ifa; ! 1078: ! 1079: return NULL; ! 1080: } ! 1081: ! 1082: ! 1083: void ! 1084: ospf_ifa_notify2(struct proto *P, uint flags, struct ifa *a) ! 1085: { ! 1086: struct ospf_proto *p = (struct ospf_proto *) P; ! 1087: ! 1088: if (a->flags & IA_SECONDARY) ! 1089: return; ! 1090: ! 1091: if (a->scope <= SCOPE_LINK) ! 1092: return; ! 1093: ! 1094: /* In OSPFv2, we create OSPF iface for each address. */ ! 1095: if (flags & IF_CHANGE_UP) ! 1096: { ! 1097: struct ospf_mip_walk s = { .iface = a->iface, .a = a }; ! 1098: while (ospf_walk_matching_iface_patts(p, &s)) ! 1099: ospf_iface_new(s.oa, a, s.ip); ! 1100: } ! 1101: ! 1102: if (flags & IF_CHANGE_DOWN) ! 1103: { ! 1104: struct ospf_iface *ifa, *ifx; ! 1105: WALK_LIST_DELSAFE(ifa, ifx, p->iface_list) ! 1106: if ((ifa->type != OSPF_IT_VLINK) && (ifa->addr == a)) ! 1107: ospf_iface_remove(ifa); ! 1108: /* See a note in ospf_iface_notify() */ ! 1109: } ! 1110: } ! 1111: ! 1112: void ! 1113: ospf_ifa_notify3(struct proto *P, uint flags, struct ifa *a) ! 1114: { ! 1115: struct ospf_proto *p = (struct ospf_proto *) P; ! 1116: ! 1117: if (a->flags & IA_SECONDARY) ! 1118: return; ! 1119: ! 1120: if (a->scope < SCOPE_LINK) ! 1121: return; ! 1122: ! 1123: /* In OSPFv3, we create OSPF iface for link-local address, ! 1124: other addresses are used for link-LSA. */ ! 1125: if (a->scope == SCOPE_LINK) ! 1126: { ! 1127: if (flags & IF_CHANGE_UP) ! 1128: { ! 1129: struct ospf_mip_walk s = { .iface = a->iface }; ! 1130: while (ospf_walk_matching_iface_patts(p, &s)) ! 1131: ospf_iface_new(s.oa, a, s.ip); ! 1132: } ! 1133: ! 1134: if (flags & IF_CHANGE_DOWN) ! 1135: { ! 1136: struct ospf_iface *ifa, *ifx; ! 1137: WALK_LIST_DELSAFE(ifa, ifx, p->iface_list) ! 1138: if ((ifa->addr == a) && (ifa->type != OSPF_IT_VLINK)) ! 1139: ospf_iface_remove(ifa); ! 1140: } ! 1141: } ! 1142: else ! 1143: { ! 1144: struct ospf_iface *ifa; ! 1145: WALK_LIST(ifa, p->iface_list) ! 1146: if (ifa->iface == a->iface) ! 1147: { ! 1148: /* RFC 5340 4.4.3 Event 5 - prefix added/deleted */ ! 1149: ospf_notify_link_lsa(ifa); ! 1150: ospf_notify_rt_lsa(ifa->oa); ! 1151: } ! 1152: } ! 1153: } ! 1154: ! 1155: ! 1156: static void ! 1157: ospf_reconfigure_ifaces2(struct ospf_proto *p) ! 1158: { ! 1159: struct iface *iface; ! 1160: struct ifa *a; ! 1161: ! 1162: WALK_LIST(iface, iface_list) ! 1163: { ! 1164: if (! (iface->flags & IF_UP)) ! 1165: continue; ! 1166: ! 1167: WALK_LIST(a, iface->addrs) ! 1168: { ! 1169: if (a->flags & IA_SECONDARY) ! 1170: continue; ! 1171: ! 1172: if (a->scope <= SCOPE_LINK) ! 1173: continue; ! 1174: ! 1175: struct ospf_mip_walk s = { .iface = iface, .a = a }; ! 1176: while (ospf_walk_matching_iface_patts(p, &s)) ! 1177: { ! 1178: /* Main inner loop */ ! 1179: struct ospf_iface *ifa = ospf_iface_find_by_key(p, a, s.ip->instance_id); ! 1180: if (ifa) ! 1181: { ! 1182: if ((ifa->oa == s.oa) && (ifa->marked < 2) && ! 1183: ospf_iface_reconfigure(ifa, s.ip)) ! 1184: continue; ! 1185: ! 1186: /* Hard restart */ ! 1187: log(L_INFO "%s: Restarting interface %s (%I/%d) in area %R", ! 1188: p->p.name, ifa->ifname, a->prefix, a->pxlen, s.oa->areaid); ! 1189: ospf_iface_shutdown(ifa); ! 1190: ospf_iface_remove(ifa); ! 1191: } ! 1192: ! 1193: ospf_iface_new(s.oa, a, s.ip); ! 1194: } ! 1195: } ! 1196: } ! 1197: } ! 1198: ! 1199: static void ! 1200: ospf_reconfigure_ifaces3(struct ospf_proto *p) ! 1201: { ! 1202: struct iface *iface; ! 1203: struct ifa *a; ! 1204: ! 1205: WALK_LIST(iface, iface_list) ! 1206: { ! 1207: if (! (iface->flags & IF_UP)) ! 1208: continue; ! 1209: ! 1210: WALK_LIST(a, iface->addrs) ! 1211: { ! 1212: if (a->flags & IA_SECONDARY) ! 1213: continue; ! 1214: ! 1215: if (a->scope != SCOPE_LINK) ! 1216: continue; ! 1217: ! 1218: struct ospf_mip_walk s = { .iface = iface }; ! 1219: while (ospf_walk_matching_iface_patts(p, &s)) ! 1220: { ! 1221: /* Main inner loop */ ! 1222: struct ospf_iface *ifa = ospf_iface_find_by_key(p, a, s.ip->instance_id); ! 1223: if (ifa) ! 1224: { ! 1225: if ((ifa->oa == s.oa) && (ifa->marked < 2) && ! 1226: ospf_iface_reconfigure(ifa, s.ip)) ! 1227: continue; ! 1228: ! 1229: /* Hard restart */ ! 1230: log(L_INFO "%s: Restarting interface %s (IID %d) in area %R", ! 1231: p->p.name, ifa->ifname, ifa->instance_id, s.oa->areaid); ! 1232: ospf_iface_shutdown(ifa); ! 1233: ospf_iface_remove(ifa); ! 1234: } ! 1235: ! 1236: ospf_iface_new(s.oa, a, s.ip); ! 1237: } ! 1238: } ! 1239: } ! 1240: } ! 1241: ! 1242: void ! 1243: ospf_reconfigure_ifaces(struct ospf_proto *p) ! 1244: { ! 1245: if (ospf_is_v2(p)) ! 1246: ospf_reconfigure_ifaces2(p); ! 1247: else ! 1248: ospf_reconfigure_ifaces3(p); ! 1249: } ! 1250: ! 1251: ! 1252: static void ! 1253: ospf_iface_change_mtu(struct ospf_proto *p, struct ospf_iface *ifa) ! 1254: { ! 1255: /* ifa is not vlink */ ! 1256: ! 1257: OSPF_TRACE(D_EVENTS, "Interface %s changed MTU to %d", ifa->iface->mtu); ! 1258: ! 1259: ifa->tx_length = ifa_tx_length(ifa); ! 1260: ! 1261: if (!ifa->sk) ! 1262: return; ! 1263: ! 1264: /* We do not shrink dynamic buffers */ ! 1265: uint bsize = ifa_bufsize(ifa); ! 1266: if (bsize > ifa->sk->rbsize) ! 1267: sk_set_rbsize(ifa->sk, bsize); ! 1268: if (bsize > ifa->sk->tbsize) ! 1269: sk_set_tbsize(ifa->sk, bsize); ! 1270: ! 1271: if (!ifa->stub) ! 1272: ospf_iface_update_flood_queue_size(ifa); ! 1273: } ! 1274: ! 1275: static void ! 1276: ospf_iface_notify(struct ospf_proto *p, uint flags, struct ospf_iface *ifa) ! 1277: { ! 1278: /* ifa is not vlink */ ! 1279: ! 1280: if (flags & IF_CHANGE_DOWN) ! 1281: { ! 1282: ospf_iface_remove(ifa); ! 1283: return; ! 1284: } ! 1285: ! 1286: if (flags & IF_CHANGE_LINK) ! 1287: ospf_iface_sm(ifa, (ifa->iface->flags & IF_LINK_UP) ? ISM_UNLOOP : ISM_LOOP); ! 1288: ! 1289: if (flags & IF_CHANGE_MTU) ! 1290: ospf_iface_change_mtu(p, ifa); ! 1291: } ! 1292: ! 1293: void ! 1294: ospf_if_notify(struct proto *P, uint flags, struct iface *iface) ! 1295: { ! 1296: struct ospf_proto *p = (struct ospf_proto *) P; ! 1297: ! 1298: /* ! 1299: if (iface->flags & IF_IGNORE) ! 1300: return; ! 1301: */ ! 1302: ! 1303: /* Going up means that there are no such ifaces yet */ ! 1304: if (flags & IF_CHANGE_UP) ! 1305: return; ! 1306: ! 1307: struct ospf_iface *ifa, *ifx; ! 1308: WALK_LIST_DELSAFE(ifa, ifx, p->iface_list) ! 1309: if (ifa->iface == iface) ! 1310: ospf_iface_notify(p, flags, ifa); ! 1311: ! 1312: /* We use here that even shutting down iface also shuts down ! 1313: the vlinks, but vlinks are not freed and stays in the ! 1314: iface_list even when down */ ! 1315: } ! 1316: ! 1317: void ! 1318: ospf_iface_info(struct ospf_iface *ifa) ! 1319: { ! 1320: char *more = ""; ! 1321: ! 1322: if (ifa->strictnbma && ! 1323: ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP))) ! 1324: more = " (strict)"; ! 1325: ! 1326: if (ifa->cf->real_bcast && ! 1327: ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_PTP))) ! 1328: more = " (real)"; ! 1329: ! 1330: if (ifa->type == OSPF_IT_VLINK) ! 1331: { ! 1332: cli_msg(-1015, "Virtual link %s to %R", ifa->ifname, ifa->vid); ! 1333: cli_msg(-1015, "\tPeer IP: %I", ifa->vip); ! 1334: cli_msg(-1015, "\tTransit area: %R (%u)", ifa->voa->areaid, ifa->voa->areaid); ! 1335: } ! 1336: else ! 1337: { ! 1338: if (ospf_is_v3(ifa->oa->po)) ! 1339: cli_msg(-1015, "Interface %s (IID %d)", ifa->ifname, ifa->instance_id); ! 1340: else if (ifa->addr->flags & IA_PEER) ! 1341: cli_msg(-1015, "Interface %s (peer %I)", ifa->ifname, ifa->addr->opposite); ! 1342: else ! 1343: cli_msg(-1015, "Interface %s (%I/%d)", ifa->ifname, ifa->addr->prefix, ifa->addr->pxlen); ! 1344: ! 1345: cli_msg(-1015, "\tType: %s%s", ospf_it[ifa->type], more); ! 1346: cli_msg(-1015, "\tArea: %R (%u)", ifa->oa->areaid, ifa->oa->areaid); ! 1347: } ! 1348: cli_msg(-1015, "\tState: %s%s", ospf_is_names[ifa->state], ifa->stub ? " (stub)" : ""); ! 1349: cli_msg(-1015, "\tPriority: %u", ifa->priority); ! 1350: cli_msg(-1015, "\tCost: %u", ifa->cost); ! 1351: if (ifa->oa->po->ecmp) ! 1352: cli_msg(-1015, "\tECMP weight: %d", ((int) ifa->ecmp_weight) + 1); ! 1353: cli_msg(-1015, "\tHello timer: %u", ifa->helloint); ! 1354: ! 1355: if (ifa->type == OSPF_IT_NBMA) ! 1356: { ! 1357: cli_msg(-1015, "\tPoll timer: %u", ifa->pollint); ! 1358: } ! 1359: cli_msg(-1015, "\tWait timer: %u", ifa->waitint); ! 1360: cli_msg(-1015, "\tDead timer: %u", ifa->deadint); ! 1361: cli_msg(-1015, "\tRetransmit timer: %u", ifa->rxmtint); ! 1362: if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA)) ! 1363: { ! 1364: cli_msg(-1015, "\tDesignated router (ID): %R", ifa->drid); ! 1365: cli_msg(-1015, "\tDesignated router (IP): %I", ifa->drip); ! 1366: cli_msg(-1015, "\tBackup designated router (ID): %R", ifa->bdrid); ! 1367: cli_msg(-1015, "\tBackup designated router (IP): %I", ifa->bdrip); ! 1368: } ! 1369: }