Annotation of embedaddon/quagga/ospfd/ospf_interface.c, revision 1.1.1.1
1.1 misho 1: /*
2: * OSPF Interface functions.
3: * Copyright (C) 1999, 2000 Toshiaki Takada
4: *
5: * This file is part of GNU Zebra.
6: *
7: * GNU Zebra is free software; you can redistribute it and/or modify
8: * it under the terms of the GNU General Public License as published
9: * by the Free Software Foundation; either version 2, or (at your
10: * option) any later version.
11: *
12: * GNU Zebra is distributed in the hope that it will be useful, but
13: * WITHOUT ANY WARRANTY; without even the implied warranty of
14: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15: * General Public License for more details.
16: *
17: * You should have received a copy of the GNU General Public License
18: * along with GNU Zebra; see the file COPYING. If not, write to the
19: * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20: * Boston, MA 02111-1307, USA.
21: */
22:
23: #include <zebra.h>
24:
25: #include "thread.h"
26: #include "linklist.h"
27: #include "prefix.h"
28: #include "if.h"
29: #include "table.h"
30: #include "memory.h"
31: #include "command.h"
32: #include "stream.h"
33: #include "log.h"
34:
35: #include "ospfd/ospfd.h"
36: #include "ospfd/ospf_spf.h"
37: #include "ospfd/ospf_interface.h"
38: #include "ospfd/ospf_ism.h"
39: #include "ospfd/ospf_asbr.h"
40: #include "ospfd/ospf_lsa.h"
41: #include "ospfd/ospf_lsdb.h"
42: #include "ospfd/ospf_neighbor.h"
43: #include "ospfd/ospf_nsm.h"
44: #include "ospfd/ospf_packet.h"
45: #include "ospfd/ospf_abr.h"
46: #include "ospfd/ospf_network.h"
47: #include "ospfd/ospf_dump.h"
48: #ifdef HAVE_SNMP
49: #include "ospfd/ospf_snmp.h"
50: #endif /* HAVE_SNMP */
51:
52:
53: int
54: ospf_if_get_output_cost (struct ospf_interface *oi)
55: {
56: /* If all else fails, use default OSPF cost */
57: u_int32_t cost;
58: u_int32_t bw, refbw;
59:
60: bw = oi->ifp->bandwidth ? oi->ifp->bandwidth : OSPF_DEFAULT_BANDWIDTH;
61: refbw = oi->ospf->ref_bandwidth;
62:
63: /* A specifed ip ospf cost overrides a calculated one. */
64: if (OSPF_IF_PARAM_CONFIGURED (IF_DEF_PARAMS (oi->ifp), output_cost_cmd) ||
65: OSPF_IF_PARAM_CONFIGURED (oi->params, output_cost_cmd))
66: cost = OSPF_IF_PARAM (oi, output_cost_cmd);
67: /* See if a cost can be calculated from the zebra processes
68: interface bandwidth field. */
69: else
70: {
71: cost = (u_int32_t) ((double)refbw / (double)bw + (double)0.5);
72: if (cost < 1)
73: cost = 1;
74: else if (cost > 65535)
75: cost = 65535;
76: }
77:
78: return cost;
79: }
80:
81: void
82: ospf_if_recalculate_output_cost (struct interface *ifp)
83: {
84: u_int32_t newcost;
85: struct route_node *rn;
86:
87: for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
88: {
89: struct ospf_interface *oi;
90:
91: if ( (oi = rn->info) == NULL)
92: continue;
93:
94: newcost = ospf_if_get_output_cost (oi);
95:
96: /* Is actual output cost changed? */
97: if (oi->output_cost != newcost)
98: {
99: oi->output_cost = newcost;
100: ospf_router_lsa_update_area (oi->area);
101: }
102: }
103: }
104:
105: /* Simulate down/up on the interface. This is needed, for example, when
106: the MTU changes. */
107: void
108: ospf_if_reset(struct interface *ifp)
109: {
110: struct route_node *rn;
111:
112: for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
113: {
114: struct ospf_interface *oi;
115:
116: if ( (oi = rn->info) == NULL)
117: continue;
118:
119: ospf_if_down(oi);
120: ospf_if_up(oi);
121: }
122: }
123:
124: void
125: ospf_if_reset_variables (struct ospf_interface *oi)
126: {
127: /* Set default values. */
128: /* don't clear this flag. oi->flag = OSPF_IF_DISABLE; */
129:
130: if (oi->vl_data)
131: oi->type = OSPF_IFTYPE_VIRTUALLINK;
132: else
133: /* preserve network-type */
134: if (oi->type != OSPF_IFTYPE_NBMA)
135: oi->type = OSPF_IFTYPE_BROADCAST;
136:
137: oi->state = ISM_Down;
138:
139: oi->crypt_seqnum = 0;
140:
141: /* This must be short, (less than RxmtInterval)
142: - RFC 2328 Section 13.5 para 3. Set to 1 second to avoid Acks being
143: held back for too long - MAG */
144: oi->v_ls_ack = 1;
145: }
146:
147: /* lookup oi for specified prefix/ifp */
148: struct ospf_interface *
149: ospf_if_table_lookup (struct interface *ifp, struct prefix *prefix)
150: {
151: struct prefix p;
152: struct route_node *rn;
153: struct ospf_interface *rninfo = NULL;
154:
155: p = *prefix;
156: p.prefixlen = IPV4_MAX_PREFIXLEN;
157:
158: /* route_node_get implicitely locks */
159: if ((rn = route_node_lookup (IF_OIFS (ifp), &p)))
160: {
161: rninfo = (struct ospf_interface *) rn->info;
162: route_unlock_node (rn);
163: }
164:
165: return rninfo;
166: }
167:
168: static void
169: ospf_add_to_if (struct interface *ifp, struct ospf_interface *oi)
170: {
171: struct route_node *rn;
172: struct prefix p;
173:
174: p = *oi->address;
175: p.prefixlen = IPV4_MAX_PREFIXLEN;
176:
177: rn = route_node_get (IF_OIFS (ifp), &p);
178: /* rn->info should either be NULL or equal to this oi
179: * as route_node_get may return an existing node
180: */
181: assert (!rn->info || rn->info == oi);
182: rn->info = oi;
183: }
184:
185: static void
186: ospf_delete_from_if (struct interface *ifp, struct ospf_interface *oi)
187: {
188: struct route_node *rn;
189: struct prefix p;
190:
191: p = *oi->address;
192: p.prefixlen = IPV4_MAX_PREFIXLEN;
193:
194: rn = route_node_lookup (IF_OIFS (oi->ifp), &p);
195: assert (rn);
196: assert (rn->info);
197: rn->info = NULL;
198: route_unlock_node (rn);
199: route_unlock_node (rn);
200: }
201:
202: struct ospf_interface *
203: ospf_if_new (struct ospf *ospf, struct interface *ifp, struct prefix *p)
204: {
205: struct ospf_interface *oi;
206:
207: if ((oi = ospf_if_table_lookup (ifp, p)) == NULL)
208: {
209: oi = XCALLOC (MTYPE_OSPF_IF, sizeof (struct ospf_interface));
210: memset (oi, 0, sizeof (struct ospf_interface));
211: }
212: else
213: return oi;
214:
215: /* Set zebra interface pointer. */
216: oi->ifp = ifp;
217: oi->address = p;
218:
219: ospf_add_to_if (ifp, oi);
220: listnode_add (ospf->oiflist, oi);
221:
222: /* Initialize neighbor list. */
223: oi->nbrs = route_table_init ();
224:
225: /* Initialize static neighbor list. */
226: oi->nbr_nbma = list_new ();
227:
228: /* Initialize Link State Acknowledgment list. */
229: oi->ls_ack = list_new ();
230: oi->ls_ack_direct.ls_ack = list_new ();
231:
232: /* Set default values. */
233: ospf_if_reset_variables (oi);
234:
235: /* Add pseudo neighbor. */
236: oi->nbr_self = ospf_nbr_new (oi);
237:
238: oi->ls_upd_queue = route_table_init ();
239: oi->t_ls_upd_event = NULL;
240: oi->t_ls_ack_direct = NULL;
241:
242: oi->crypt_seqnum = time (NULL);
243:
244: #ifdef HAVE_OPAQUE_LSA
245: ospf_opaque_type9_lsa_init (oi);
246: #endif /* HAVE_OPAQUE_LSA */
247:
248: oi->ospf = ospf;
249:
250: return oi;
251: }
252:
253: /* Restore an interface to its pre UP state
254: Used from ism_interface_down only */
255: void
256: ospf_if_cleanup (struct ospf_interface *oi)
257: {
258: struct route_node *rn;
259: struct listnode *node, *nnode;
260: struct ospf_neighbor *nbr;
261: struct ospf_nbr_nbma *nbr_nbma;
262: struct ospf_lsa *lsa;
263:
264: /* oi->nbrs and oi->nbr_nbma should be deleted on InterfaceDown event */
265: /* delete all static neighbors attached to this interface */
266: for (ALL_LIST_ELEMENTS (oi->nbr_nbma, node, nnode, nbr_nbma))
267: {
268: OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll);
269:
270: if (nbr_nbma->nbr)
271: {
272: nbr_nbma->nbr->nbr_nbma = NULL;
273: nbr_nbma->nbr = NULL;
274: }
275:
276: nbr_nbma->oi = NULL;
277:
278: listnode_delete (oi->nbr_nbma, nbr_nbma);
279: }
280:
281: /* send Neighbor event KillNbr to all associated neighbors. */
282: for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
283: if ((nbr = rn->info) != NULL)
284: if (nbr != oi->nbr_self)
285: OSPF_NSM_EVENT_EXECUTE (nbr, NSM_KillNbr);
286:
287: /* Cleanup Link State Acknowlegdment list. */
288: for (ALL_LIST_ELEMENTS (oi->ls_ack, node, nnode, lsa))
289: ospf_lsa_unlock (&lsa); /* oi->ls_ack */
290: list_delete_all_node (oi->ls_ack);
291:
292: oi->crypt_seqnum = 0;
293:
294: /* Empty link state update queue */
295: ospf_ls_upd_queue_empty (oi);
296:
297: /* Reset pseudo neighbor. */
298: ospf_nbr_delete (oi->nbr_self);
299: oi->nbr_self = ospf_nbr_new (oi);
300: ospf_nbr_add_self (oi);
301: }
302:
303: void
304: ospf_if_free (struct ospf_interface *oi)
305: {
306: ospf_if_down (oi);
307:
308: assert (oi->state == ISM_Down);
309:
310: #ifdef HAVE_OPAQUE_LSA
311: ospf_opaque_type9_lsa_term (oi);
312: #endif /* HAVE_OPAQUE_LSA */
313:
314: /* Free Pseudo Neighbour */
315: ospf_nbr_delete (oi->nbr_self);
316:
317: route_table_finish (oi->nbrs);
318: route_table_finish (oi->ls_upd_queue);
319:
320: /* Free any lists that should be freed */
321: list_free (oi->nbr_nbma);
322:
323: list_free (oi->ls_ack);
324: list_free (oi->ls_ack_direct.ls_ack);
325:
326: ospf_delete_from_if (oi->ifp, oi);
327:
328: listnode_delete (oi->ospf->oiflist, oi);
329: listnode_delete (oi->area->oiflist, oi);
330:
331: thread_cancel_event (master, oi);
332:
333: memset (oi, 0, sizeof (*oi));
334: XFREE (MTYPE_OSPF_IF, oi);
335: }
336:
337:
338: /*
339: * check if interface with given address is configured and
340: * return it if yes. special treatment for PtP networks.
341: */
342: struct ospf_interface *
343: ospf_if_is_configured (struct ospf *ospf, struct in_addr *address)
344: {
345: struct listnode *node, *nnode;
346: struct ospf_interface *oi;
347: struct prefix_ipv4 addr;
348:
349: addr.family = AF_INET;
350: addr.prefix = *address;
351: addr.prefixlen = IPV4_MAX_PREFIXLEN;
352:
353: for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
354: if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
355: {
356: if (oi->type == OSPF_IFTYPE_POINTOPOINT)
357: {
358: /* special leniency: match if addr is anywhere on peer subnet */
359: if (prefix_match(CONNECTED_PREFIX(oi->connected),
360: (struct prefix *)&addr))
361: return oi;
362: }
363: else
364: {
365: if (IPV4_ADDR_SAME (address, &oi->address->u.prefix4))
366: return oi;
367: }
368: }
369: return NULL;
370: }
371:
372: int
373: ospf_if_is_up (struct ospf_interface *oi)
374: {
375: return if_is_up (oi->ifp);
376: }
377:
378: struct ospf_interface *
379: ospf_if_exists (struct ospf_interface *oic)
380: {
381: struct listnode *node;
382: struct ospf *ospf;
383: struct ospf_interface *oi;
384:
385: if ((ospf = ospf_lookup ()) == NULL)
386: return NULL;
387:
388: for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
389: if (oi == oic)
390: return oi;
391:
392: return NULL;
393: }
394:
395: struct ospf_interface *
396: ospf_if_lookup_by_local_addr (struct ospf *ospf,
397: struct interface *ifp, struct in_addr address)
398: {
399: struct listnode *node;
400: struct ospf_interface *oi;
401:
402: for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
403: if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
404: {
405: if (ifp && oi->ifp != ifp)
406: continue;
407:
408: if (IPV4_ADDR_SAME (&address, &oi->address->u.prefix4))
409: return oi;
410: }
411:
412: return NULL;
413: }
414:
415: struct ospf_interface *
416: ospf_if_lookup_by_prefix (struct ospf *ospf, struct prefix_ipv4 *p)
417: {
418: struct listnode *node;
419: struct ospf_interface *oi;
420:
421: /* Check each Interface. */
422: for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
423: {
424: if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
425: {
426: struct prefix ptmp;
427:
428: prefix_copy (&ptmp, CONNECTED_PREFIX(oi->connected));
429: apply_mask (&ptmp);
430: if (prefix_same (&ptmp, (struct prefix *) p))
431: return oi;
432: }
433: }
434: return NULL;
435: }
436:
437: /* determine receiving interface by ifp and source address */
438: struct ospf_interface *
439: ospf_if_lookup_recv_if (struct ospf *ospf, struct in_addr src,
440: struct interface *ifp)
441: {
442: struct route_node *rn;
443: struct prefix_ipv4 addr;
444: struct ospf_interface *oi, *match;
445:
446: addr.family = AF_INET;
447: addr.prefix = src;
448: addr.prefixlen = IPV4_MAX_BITLEN;
449:
450: match = NULL;
451:
452: for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
453: {
454: oi = rn->info;
455:
456: if (!oi) /* oi can be NULL for PtP aliases */
457: continue;
458:
459: if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
460: continue;
461:
462: if (if_is_loopback (oi->ifp))
463: continue;
464:
465: if (prefix_match (CONNECTED_PREFIX(oi->connected),
466: (struct prefix *) &addr))
467: {
468: if ( (match == NULL) ||
469: (match->address->prefixlen < oi->address->prefixlen)
470: )
471: match = oi;
472: }
473: }
474:
475: return match;
476: }
477:
478: void
479: ospf_if_stream_set (struct ospf_interface *oi)
480: {
481: /* set output fifo queue. */
482: if (oi->obuf == NULL)
483: oi->obuf = ospf_fifo_new ();
484: }
485:
486: void
487: ospf_if_stream_unset (struct ospf_interface *oi)
488: {
489: struct ospf *ospf = oi->ospf;
490:
491: if (oi->obuf)
492: {
493: ospf_fifo_free (oi->obuf);
494: oi->obuf = NULL;
495:
496: if (oi->on_write_q)
497: {
498: listnode_delete (ospf->oi_write_q, oi);
499: if (list_isempty(ospf->oi_write_q))
500: OSPF_TIMER_OFF (ospf->t_write);
501: oi->on_write_q = 0;
502: }
503: }
504: }
505:
506:
507: static struct ospf_if_params *
508: ospf_new_if_params (void)
509: {
510: struct ospf_if_params *oip;
511:
512: oip = XCALLOC (MTYPE_OSPF_IF_PARAMS, sizeof (struct ospf_if_params));
513:
514: if (!oip)
515: return NULL;
516:
517: UNSET_IF_PARAM (oip, output_cost_cmd);
518: UNSET_IF_PARAM (oip, transmit_delay);
519: UNSET_IF_PARAM (oip, retransmit_interval);
520: UNSET_IF_PARAM (oip, passive_interface);
521: UNSET_IF_PARAM (oip, v_hello);
522: UNSET_IF_PARAM (oip, fast_hello);
523: UNSET_IF_PARAM (oip, v_wait);
524: UNSET_IF_PARAM (oip, priority);
525: UNSET_IF_PARAM (oip, type);
526: UNSET_IF_PARAM (oip, auth_simple);
527: UNSET_IF_PARAM (oip, auth_crypt);
528: UNSET_IF_PARAM (oip, auth_type);
529:
530: oip->auth_crypt = list_new ();
531:
532: oip->network_lsa_seqnum = htonl(OSPF_INITIAL_SEQUENCE_NUMBER);
533:
534: return oip;
535: }
536:
537: void
538: ospf_del_if_params (struct ospf_if_params *oip)
539: {
540: list_delete (oip->auth_crypt);
541: XFREE (MTYPE_OSPF_IF_PARAMS, oip);
542: }
543:
544: void
545: ospf_free_if_params (struct interface *ifp, struct in_addr addr)
546: {
547: struct ospf_if_params *oip;
548: struct prefix_ipv4 p;
549: struct route_node *rn;
550:
551: p.family = AF_INET;
552: p.prefixlen = IPV4_MAX_PREFIXLEN;
553: p.prefix = addr;
554: rn = route_node_lookup (IF_OIFS_PARAMS (ifp), (struct prefix*)&p);
555: if (!rn || !rn->info)
556: return;
557:
558: oip = rn->info;
559: route_unlock_node (rn);
560:
561: if (!OSPF_IF_PARAM_CONFIGURED (oip, output_cost_cmd) &&
562: !OSPF_IF_PARAM_CONFIGURED (oip, transmit_delay) &&
563: !OSPF_IF_PARAM_CONFIGURED (oip, retransmit_interval) &&
564: !OSPF_IF_PARAM_CONFIGURED (oip, passive_interface) &&
565: !OSPF_IF_PARAM_CONFIGURED (oip, v_hello) &&
566: !OSPF_IF_PARAM_CONFIGURED (oip, fast_hello) &&
567: !OSPF_IF_PARAM_CONFIGURED (oip, v_wait) &&
568: !OSPF_IF_PARAM_CONFIGURED (oip, priority) &&
569: !OSPF_IF_PARAM_CONFIGURED (oip, type) &&
570: !OSPF_IF_PARAM_CONFIGURED (oip, auth_simple) &&
571: !OSPF_IF_PARAM_CONFIGURED (oip, auth_type) &&
572: listcount (oip->auth_crypt) == 0 &&
573: ntohl (oip->network_lsa_seqnum) != OSPF_INITIAL_SEQUENCE_NUMBER)
574: {
575: ospf_del_if_params (oip);
576: rn->info = NULL;
577: route_unlock_node (rn);
578: }
579: }
580:
581: struct ospf_if_params *
582: ospf_lookup_if_params (struct interface *ifp, struct in_addr addr)
583: {
584: struct prefix_ipv4 p;
585: struct route_node *rn;
586:
587: p.family = AF_INET;
588: p.prefixlen = IPV4_MAX_PREFIXLEN;
589: p.prefix = addr;
590:
591: rn = route_node_lookup (IF_OIFS_PARAMS (ifp), (struct prefix*)&p);
592:
593: if (rn)
594: {
595: route_unlock_node (rn);
596: return rn->info;
597: }
598:
599: return NULL;
600: }
601:
602: struct ospf_if_params *
603: ospf_get_if_params (struct interface *ifp, struct in_addr addr)
604: {
605: struct prefix_ipv4 p;
606: struct route_node *rn;
607:
608: p.family = AF_INET;
609: p.prefixlen = IPV4_MAX_PREFIXLEN;
610: p.prefix = addr;
611:
612: rn = route_node_get (IF_OIFS_PARAMS (ifp), (struct prefix*)&p);
613:
614: if (rn->info == NULL)
615: rn->info = ospf_new_if_params ();
616: else
617: route_unlock_node (rn);
618:
619: return rn->info;
620: }
621:
622: void
623: ospf_if_update_params (struct interface *ifp, struct in_addr addr)
624: {
625: struct route_node *rn;
626: struct ospf_interface *oi;
627:
628: for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
629: {
630: if ((oi = rn->info) == NULL)
631: continue;
632:
633: if (IPV4_ADDR_SAME (&oi->address->u.prefix4, &addr))
634: oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4);
635: }
636: }
637:
638: int
639: ospf_if_new_hook (struct interface *ifp)
640: {
641: int rc = 0;
642:
643: ifp->info = XCALLOC (MTYPE_OSPF_IF_INFO, sizeof (struct ospf_if_info));
644:
645: IF_OIFS (ifp) = route_table_init ();
646: IF_OIFS_PARAMS (ifp) = route_table_init ();
647:
648: IF_DEF_PARAMS (ifp) = ospf_new_if_params ();
649:
650: SET_IF_PARAM (IF_DEF_PARAMS (ifp), transmit_delay);
651: IF_DEF_PARAMS (ifp)->transmit_delay = OSPF_TRANSMIT_DELAY_DEFAULT;
652:
653: SET_IF_PARAM (IF_DEF_PARAMS (ifp), retransmit_interval);
654: IF_DEF_PARAMS (ifp)->retransmit_interval = OSPF_RETRANSMIT_INTERVAL_DEFAULT;
655:
656: SET_IF_PARAM (IF_DEF_PARAMS (ifp), priority);
657: IF_DEF_PARAMS (ifp)->priority = OSPF_ROUTER_PRIORITY_DEFAULT;
658:
659: IF_DEF_PARAMS (ifp)->mtu_ignore = OSPF_MTU_IGNORE_DEFAULT;
660:
661: SET_IF_PARAM (IF_DEF_PARAMS (ifp), v_hello);
662: IF_DEF_PARAMS (ifp)->v_hello = OSPF_HELLO_INTERVAL_DEFAULT;
663:
664: SET_IF_PARAM (IF_DEF_PARAMS (ifp), fast_hello);
665: IF_DEF_PARAMS (ifp)->fast_hello = OSPF_FAST_HELLO_DEFAULT;
666:
667: SET_IF_PARAM (IF_DEF_PARAMS (ifp), v_wait);
668: IF_DEF_PARAMS (ifp)->v_wait = OSPF_ROUTER_DEAD_INTERVAL_DEFAULT;
669:
670: SET_IF_PARAM (IF_DEF_PARAMS (ifp), auth_simple);
671: memset (IF_DEF_PARAMS (ifp)->auth_simple, 0, OSPF_AUTH_SIMPLE_SIZE);
672:
673: SET_IF_PARAM (IF_DEF_PARAMS (ifp), auth_type);
674: IF_DEF_PARAMS (ifp)->auth_type = OSPF_AUTH_NOTSET;
675:
676: #ifdef HAVE_OPAQUE_LSA
677: rc = ospf_opaque_new_if (ifp);
678: #endif /* HAVE_OPAQUE_LSA */
679: return rc;
680: }
681:
682: static int
683: ospf_if_delete_hook (struct interface *ifp)
684: {
685: int rc = 0;
686: struct route_node *rn;
687: #ifdef HAVE_OPAQUE_LSA
688: rc = ospf_opaque_del_if (ifp);
689: #endif /* HAVE_OPAQUE_LSA */
690:
691: route_table_finish (IF_OIFS (ifp));
692:
693: for (rn = route_top (IF_OIFS_PARAMS (ifp)); rn; rn = route_next (rn))
694: if (rn->info)
695: ospf_del_if_params (rn->info);
696: route_table_finish (IF_OIFS_PARAMS (ifp));
697:
698: ospf_del_if_params ((struct ospf_if_params *) IF_DEF_PARAMS (ifp));
699: XFREE (MTYPE_OSPF_IF_INFO, ifp->info);
700: ifp->info = NULL;
701:
702: return rc;
703: }
704:
705: int
706: ospf_if_is_enable (struct ospf_interface *oi)
707: {
708: if (!if_is_loopback (oi->ifp))
709: if (if_is_up (oi->ifp))
710: return 1;
711:
712: return 0;
713: }
714:
715: void
716: ospf_if_set_multicast(struct ospf_interface *oi)
717: {
718: if ((oi->state > ISM_Loopback) &&
719: (oi->type != OSPF_IFTYPE_LOOPBACK) &&
720: (oi->type != OSPF_IFTYPE_VIRTUALLINK) &&
721: (OSPF_IF_PASSIVE_STATUS(oi) == OSPF_IF_ACTIVE))
722: {
723: /* The interface should belong to the OSPF-all-routers group. */
724: if (!OI_MEMBER_CHECK(oi, MEMBER_ALLROUTERS) &&
725: (ospf_if_add_allspfrouters(oi->ospf, oi->address,
726: oi->ifp->ifindex) >= 0))
727: /* Set the flag only if the system call to join succeeded. */
728: OI_MEMBER_JOINED(oi, MEMBER_ALLROUTERS);
729: }
730: else
731: {
732: /* The interface should NOT belong to the OSPF-all-routers group. */
733: if (OI_MEMBER_CHECK(oi, MEMBER_ALLROUTERS))
734: {
735: /* Only actually drop if this is the last reference */
736: if (OI_MEMBER_COUNT(oi, MEMBER_ALLROUTERS) == 1)
737: ospf_if_drop_allspfrouters (oi->ospf, oi->address,
738: oi->ifp->ifindex);
739: /* Unset the flag regardless of whether the system call to leave
740: the group succeeded, since it's much safer to assume that
741: we are not a member. */
742: OI_MEMBER_LEFT(oi,MEMBER_ALLROUTERS);
743: }
744: }
745:
746: if (((oi->type == OSPF_IFTYPE_BROADCAST) ||
747: (oi->type == OSPF_IFTYPE_POINTOPOINT)) &&
748: ((oi->state == ISM_DR) || (oi->state == ISM_Backup)) &&
749: (OSPF_IF_PASSIVE_STATUS(oi) == OSPF_IF_ACTIVE))
750: {
751: /* The interface should belong to the OSPF-designated-routers group. */
752: if (!OI_MEMBER_CHECK(oi, MEMBER_DROUTERS) &&
753: (ospf_if_add_alldrouters(oi->ospf, oi->address,
754: oi->ifp->ifindex) >= 0))
755: /* Set the flag only if the system call to join succeeded. */
756: OI_MEMBER_JOINED(oi, MEMBER_DROUTERS);
757: }
758: else
759: {
760: /* The interface should NOT belong to the OSPF-designated-routers group */
761: if (OI_MEMBER_CHECK(oi, MEMBER_DROUTERS))
762: {
763: /* drop only if last reference */
764: if (OI_MEMBER_COUNT(oi, MEMBER_DROUTERS) == 1)
765: ospf_if_drop_alldrouters(oi->ospf, oi->address, oi->ifp->ifindex);
766:
767: /* Unset the flag regardless of whether the system call to leave
768: the group succeeded, since it's much safer to assume that
769: we are not a member. */
770: OI_MEMBER_LEFT(oi, MEMBER_DROUTERS);
771: }
772: }
773: }
774:
775: int
776: ospf_if_up (struct ospf_interface *oi)
777: {
778: if (oi == NULL)
779: return 0;
780:
781: if (oi->type == OSPF_IFTYPE_LOOPBACK)
782: OSPF_ISM_EVENT_SCHEDULE (oi, ISM_LoopInd);
783: else
784: {
785: struct ospf *ospf = ospf_lookup ();
786: if (ospf != NULL)
787: ospf_adjust_sndbuflen (ospf, oi->ifp->mtu);
788: else
789: zlog_warn ("%s: ospf_lookup() returned NULL", __func__);
790: ospf_if_stream_set (oi);
791: OSPF_ISM_EVENT_SCHEDULE (oi, ISM_InterfaceUp);
792: }
793:
794: return 1;
795: }
796:
797: int
798: ospf_if_down (struct ospf_interface *oi)
799: {
800: if (oi == NULL)
801: return 0;
802:
803: OSPF_ISM_EVENT_EXECUTE (oi, ISM_InterfaceDown);
804: /* Shutdown packet reception and sending */
805: ospf_if_stream_unset (oi);
806:
807: return 1;
808: }
809:
810:
811: /* Virtual Link related functions. */
812:
813: struct ospf_vl_data *
814: ospf_vl_data_new (struct ospf_area *area, struct in_addr vl_peer)
815: {
816: struct ospf_vl_data *vl_data;
817:
818: vl_data = XCALLOC (MTYPE_OSPF_VL_DATA, sizeof (struct ospf_vl_data));
819:
820: vl_data->vl_peer.s_addr = vl_peer.s_addr;
821: vl_data->vl_area_id = area->area_id;
822: vl_data->format = area->format;
823:
824: return vl_data;
825: }
826:
827: void
828: ospf_vl_data_free (struct ospf_vl_data *vl_data)
829: {
830: XFREE (MTYPE_OSPF_VL_DATA, vl_data);
831: }
832:
833: u_int vlink_count = 0;
834:
835: struct ospf_interface *
836: ospf_vl_new (struct ospf *ospf, struct ospf_vl_data *vl_data)
837: {
838: struct ospf_interface * voi;
839: struct interface * vi;
840: char ifname[INTERFACE_NAMSIZ + 1];
841: struct ospf_area *area;
842: struct in_addr area_id;
843: struct connected *co;
844: struct prefix_ipv4 *p;
845:
846: if (IS_DEBUG_OSPF_EVENT)
847: zlog_debug ("ospf_vl_new(): Start");
848: if (vlink_count == OSPF_VL_MAX_COUNT)
849: {
850: if (IS_DEBUG_OSPF_EVENT)
851: zlog_debug ("ospf_vl_new(): Alarm: "
852: "cannot create more than OSPF_MAX_VL_COUNT virtual links");
853: return NULL;
854: }
855:
856: if (IS_DEBUG_OSPF_EVENT)
857: zlog_debug ("ospf_vl_new(): creating pseudo zebra interface");
858:
859: snprintf (ifname, sizeof(ifname), "VLINK%d", vlink_count);
860: vi = if_create (ifname, strnlen(ifname, sizeof(ifname)));
861: co = connected_new ();
862: co->ifp = vi;
863: listnode_add (vi->connected, co);
864:
865: p = prefix_ipv4_new ();
866: p->family = AF_INET;
867: p->prefix.s_addr = 0;
868: p->prefixlen = 0;
869:
870: co->address = (struct prefix *)p;
871:
872: voi = ospf_if_new (ospf, vi, co->address);
873: if (voi == NULL)
874: {
875: if (IS_DEBUG_OSPF_EVENT)
876: zlog_debug ("ospf_vl_new(): Alarm: OSPF int structure is not created");
877: return NULL;
878: }
879: voi->connected = co;
880: voi->vl_data = vl_data;
881: voi->ifp->mtu = OSPF_VL_MTU;
882: voi->type = OSPF_IFTYPE_VIRTUALLINK;
883:
884: vlink_count++;
885: if (IS_DEBUG_OSPF_EVENT)
886: zlog_debug ("ospf_vl_new(): Created name: %s", ifname);
887: if (IS_DEBUG_OSPF_EVENT)
888: zlog_debug ("ospf_vl_new(): set if->name to %s", vi->name);
889:
890: area_id.s_addr = 0;
891: area = ospf_area_get (ospf, area_id, OSPF_AREA_ID_FORMAT_ADDRESS);
892: voi->area = area;
893:
894: if (IS_DEBUG_OSPF_EVENT)
895: zlog_debug ("ospf_vl_new(): set associated area to the backbone");
896:
897: ospf_nbr_add_self (voi);
898: ospf_area_add_if (voi->area, voi);
899:
900: ospf_if_stream_set (voi);
901:
902: if (IS_DEBUG_OSPF_EVENT)
903: zlog_debug ("ospf_vl_new(): Stop");
904: return voi;
905: }
906:
907: static void
908: ospf_vl_if_delete (struct ospf_vl_data *vl_data)
909: {
910: struct interface *ifp = vl_data->vl_oi->ifp;
911: vl_data->vl_oi->address->u.prefix4.s_addr = 0;
912: vl_data->vl_oi->address->prefixlen = 0;
913: ospf_if_free (vl_data->vl_oi);
914: if_delete (ifp);
915: vlink_count--;
916: }
917:
918: /* Look up vl_data for given peer, optionally qualified to be in the
919: * specified area. NULL area returns first found..
920: */
921: struct ospf_vl_data *
922: ospf_vl_lookup (struct ospf *ospf, struct ospf_area *area,
923: struct in_addr vl_peer)
924: {
925: struct ospf_vl_data *vl_data;
926: struct listnode *node;
927:
928: if (IS_DEBUG_OSPF_EVENT)
929: {
930: zlog_debug ("%s: Looking for %s", __func__, inet_ntoa (vl_peer));
931: if (area)
932: zlog_debug ("%s: in area %s", __func__, inet_ntoa (area->area_id));
933: }
934:
935: for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl_data))
936: {
937: if (IS_DEBUG_OSPF_EVENT)
938: zlog_debug ("%s: VL %s, peer %s", __func__,
939: vl_data->vl_oi->ifp->name,
940: inet_ntoa (vl_data->vl_peer));
941:
942: if (area && !IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
943: continue;
944:
945: if (IPV4_ADDR_SAME (&vl_data->vl_peer, &vl_peer))
946: return vl_data;
947: }
948:
949: return NULL;
950: }
951:
952: static void
953: ospf_vl_shutdown (struct ospf_vl_data *vl_data)
954: {
955: struct ospf_interface *oi;
956:
957: if ((oi = vl_data->vl_oi) == NULL)
958: return;
959:
960: oi->address->u.prefix4.s_addr = 0;
961: oi->address->prefixlen = 0;
962:
963: UNSET_FLAG (oi->ifp->flags, IFF_UP);
964: /* OSPF_ISM_EVENT_SCHEDULE (oi, ISM_InterfaceDown); */
965: OSPF_ISM_EVENT_EXECUTE (oi, ISM_InterfaceDown);
966: }
967:
968: void
969: ospf_vl_add (struct ospf *ospf, struct ospf_vl_data *vl_data)
970: {
971: listnode_add (ospf->vlinks, vl_data);
972: #ifdef HAVE_SNMP
973: ospf_snmp_vl_add (vl_data);
974: #endif /* HAVE_SNMP */
975: }
976:
977: void
978: ospf_vl_delete (struct ospf *ospf, struct ospf_vl_data *vl_data)
979: {
980: ospf_vl_shutdown (vl_data);
981: ospf_vl_if_delete (vl_data);
982:
983: #ifdef HAVE_SNMP
984: ospf_snmp_vl_delete (vl_data);
985: #endif /* HAVE_SNMP */
986: listnode_delete (ospf->vlinks, vl_data);
987:
988: ospf_vl_data_free (vl_data);
989: }
990:
991: static int
992: ospf_vl_set_params (struct ospf_vl_data *vl_data, struct vertex *v)
993: {
994: int changed = 0;
995: struct ospf_interface *voi;
996: struct listnode *node;
997: struct vertex_parent *vp = NULL;
998: int i;
999: struct router_lsa *rl;
1000:
1001: voi = vl_data->vl_oi;
1002:
1003: if (voi->output_cost != v->distance)
1004: {
1005:
1006: voi->output_cost = v->distance;
1007: changed = 1;
1008: }
1009:
1010: for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
1011: {
1012: vl_data->nexthop.oi = vp->nexthop->oi;
1013: vl_data->nexthop.router = vp->nexthop->router;
1014:
1015: if (!IPV4_ADDR_SAME(&voi->address->u.prefix4,
1016: &vl_data->nexthop.oi->address->u.prefix4))
1017: changed = 1;
1018:
1019: voi->address->u.prefix4 = vl_data->nexthop.oi->address->u.prefix4;
1020: voi->address->prefixlen = vl_data->nexthop.oi->address->prefixlen;
1021:
1022: break; /* We take the first interface. */
1023: }
1024:
1025: rl = (struct router_lsa *)v->lsa;
1026:
1027: /* use SPF determined backlink index in struct vertex
1028: * for virtual link destination address
1029: */
1030: if (vp && vp->backlink >= 0)
1031: {
1032: if (!IPV4_ADDR_SAME (&vl_data->peer_addr,
1033: &rl->link[vp->backlink].link_data))
1034: changed = 1;
1035: vl_data->peer_addr = rl->link[vp->backlink].link_data;
1036: }
1037: else
1038: {
1039: /* This is highly odd, there is no backlink index
1040: * there should be due to the ospf_spf_has_link() check
1041: * in SPF. Lets warn and try pick a link anyway.
1042: */
1043: zlog_warn ("ospf_vl_set_params: No backlink for %s!",
1044: vl_data->vl_oi->ifp->name);
1045: for (i = 0; i < ntohs (rl->links); i++)
1046: {
1047: switch (rl->link[i].type)
1048: {
1049: case LSA_LINK_TYPE_VIRTUALLINK:
1050: if (IS_DEBUG_OSPF_EVENT)
1051: zlog_debug ("found back link through VL");
1052: case LSA_LINK_TYPE_TRANSIT:
1053: case LSA_LINK_TYPE_POINTOPOINT:
1054: if (!IPV4_ADDR_SAME (&vl_data->peer_addr,
1055: &rl->link[i].link_data))
1056: changed = 1;
1057: vl_data->peer_addr = rl->link[i].link_data;
1058: }
1059: }
1060: }
1061:
1062: if (IS_DEBUG_OSPF_EVENT)
1063: zlog_debug ("%s: %s peer address: %s, cost: %d,%schanged", __func__,
1064: vl_data->vl_oi->ifp->name,
1065: inet_ntoa(vl_data->peer_addr),
1066: voi->output_cost,
1067: (changed ? " " : " un"));
1068:
1069: return changed;
1070: }
1071:
1072:
1073: void
1074: ospf_vl_up_check (struct ospf_area *area, struct in_addr rid,
1075: struct vertex *v)
1076: {
1077: struct ospf *ospf = area->ospf;
1078: struct listnode *node;
1079: struct ospf_vl_data *vl_data;
1080: struct ospf_interface *oi;
1081:
1082: if (IS_DEBUG_OSPF_EVENT)
1083: {
1084: zlog_debug ("ospf_vl_up_check(): Start");
1085: zlog_debug ("ospf_vl_up_check(): Router ID is %s", inet_ntoa (rid));
1086: zlog_debug ("ospf_vl_up_check(): Area is %s", inet_ntoa (area->area_id));
1087: }
1088:
1089: for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl_data))
1090: {
1091: if (IS_DEBUG_OSPF_EVENT)
1092: {
1093: zlog_debug ("%s: considering VL, %s in area %s", __func__,
1094: vl_data->vl_oi->ifp->name,
1095: inet_ntoa (vl_data->vl_area_id));
1096: zlog_debug ("%s: peer ID: %s", __func__,
1097: inet_ntoa (vl_data->vl_peer));
1098: }
1099:
1100: if (IPV4_ADDR_SAME (&vl_data->vl_peer, &rid) &&
1101: IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
1102: {
1103: oi = vl_data->vl_oi;
1104: SET_FLAG (vl_data->flags, OSPF_VL_FLAG_APPROVED);
1105:
1106: if (IS_DEBUG_OSPF_EVENT)
1107: zlog_debug ("ospf_vl_up_check(): this VL matched");
1108:
1109: if (oi->state == ISM_Down)
1110: {
1111: if (IS_DEBUG_OSPF_EVENT)
1112: zlog_debug ("ospf_vl_up_check(): VL is down, waking it up");
1113: SET_FLAG (oi->ifp->flags, IFF_UP);
1114: OSPF_ISM_EVENT_EXECUTE(oi,ISM_InterfaceUp);
1115: }
1116:
1117: if (ospf_vl_set_params (vl_data, v))
1118: {
1119: if (IS_DEBUG_OSPF (ism, ISM_EVENTS))
1120: zlog_debug ("ospf_vl_up_check: VL cost change,"
1121: " scheduling router lsa refresh");
1122: if (ospf->backbone)
1123: ospf_router_lsa_update_area (ospf->backbone);
1124: else if (IS_DEBUG_OSPF (ism, ISM_EVENTS))
1125: zlog_debug ("ospf_vl_up_check: VL cost change, no backbone!");
1126: }
1127: }
1128: }
1129: }
1130:
1131: void
1132: ospf_vl_unapprove (struct ospf *ospf)
1133: {
1134: struct listnode *node;
1135: struct ospf_vl_data *vl_data;
1136:
1137: for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl_data))
1138: UNSET_FLAG (vl_data->flags, OSPF_VL_FLAG_APPROVED);
1139: }
1140:
1141: void
1142: ospf_vl_shut_unapproved (struct ospf *ospf)
1143: {
1144: struct listnode *node, *nnode;
1145: struct ospf_vl_data *vl_data;
1146:
1147: for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
1148: if (!CHECK_FLAG (vl_data->flags, OSPF_VL_FLAG_APPROVED))
1149: ospf_vl_shutdown (vl_data);
1150: }
1151:
1152: int
1153: ospf_full_virtual_nbrs (struct ospf_area *area)
1154: {
1155: if (IS_DEBUG_OSPF_EVENT)
1156: {
1157: zlog_debug ("counting fully adjacent virtual neighbors in area %s",
1158: inet_ntoa (area->area_id));
1159: zlog_debug ("there are %d of them", area->full_vls);
1160: }
1161:
1162: return area->full_vls;
1163: }
1164:
1165: int
1166: ospf_vls_in_area (struct ospf_area *area)
1167: {
1168: struct listnode *node;
1169: struct ospf_vl_data *vl_data;
1170: int c = 0;
1171:
1172: for (ALL_LIST_ELEMENTS_RO (area->ospf->vlinks, node, vl_data))
1173: if (IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
1174: c++;
1175:
1176: return c;
1177: }
1178:
1179:
1180: struct crypt_key *
1181: ospf_crypt_key_new ()
1182: {
1183: return XCALLOC (MTYPE_OSPF_CRYPT_KEY, sizeof (struct crypt_key));
1184: }
1185:
1186: void
1187: ospf_crypt_key_add (struct list *crypt, struct crypt_key *ck)
1188: {
1189: listnode_add (crypt, ck);
1190: }
1191:
1192: struct crypt_key *
1193: ospf_crypt_key_lookup (struct list *auth_crypt, u_char key_id)
1194: {
1195: struct listnode *node;
1196: struct crypt_key *ck;
1197:
1198: for (ALL_LIST_ELEMENTS_RO (auth_crypt, node, ck))
1199: if (ck->key_id == key_id)
1200: return ck;
1201:
1202: return NULL;
1203: }
1204:
1205: int
1206: ospf_crypt_key_delete (struct list *auth_crypt, u_char key_id)
1207: {
1208: struct listnode *node, *nnode;
1209: struct crypt_key *ck;
1210:
1211: for (ALL_LIST_ELEMENTS (auth_crypt, node, nnode, ck))
1212: {
1213: if (ck->key_id == key_id)
1214: {
1215: listnode_delete (auth_crypt, ck);
1216: XFREE (MTYPE_OSPF_CRYPT_KEY, ck);
1217: return 1;
1218: }
1219: }
1220:
1221: return 0;
1222: }
1223:
1224: u_char
1225: ospf_default_iftype(struct interface *ifp)
1226: {
1227: if (if_is_pointopoint (ifp))
1228: return OSPF_IFTYPE_POINTOPOINT;
1229: else if (if_is_loopback (ifp))
1230: return OSPF_IFTYPE_LOOPBACK;
1231: else
1232: return OSPF_IFTYPE_BROADCAST;
1233: }
1234:
1235: void
1236: ospf_if_init ()
1237: {
1238: /* Initialize Zebra interface data structure. */
1239: if_init ();
1240: om->iflist = iflist;
1241: if_add_hook (IF_NEW_HOOK, ospf_if_new_hook);
1242: if_add_hook (IF_DELETE_HOOK, ospf_if_delete_hook);
1243: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>