Annotation of embedaddon/bird/proto/ospf/iface.c, revision 1.1
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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>