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