Annotation of embedaddon/quagga/ospfd/ospf_interface.c, revision 1.1.1.3
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:
1.1.1.3 ! misho 52:
1.1 misho 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: ospf_opaque_type9_lsa_init (oi);
245:
246: oi->ospf = ospf;
247:
248: return oi;
249: }
250:
251: /* Restore an interface to its pre UP state
252: Used from ism_interface_down only */
253: void
254: ospf_if_cleanup (struct ospf_interface *oi)
255: {
256: struct route_node *rn;
257: struct listnode *node, *nnode;
258: struct ospf_neighbor *nbr;
259: struct ospf_nbr_nbma *nbr_nbma;
260: struct ospf_lsa *lsa;
261:
262: /* oi->nbrs and oi->nbr_nbma should be deleted on InterfaceDown event */
263: /* delete all static neighbors attached to this interface */
264: for (ALL_LIST_ELEMENTS (oi->nbr_nbma, node, nnode, nbr_nbma))
265: {
266: OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll);
267:
268: if (nbr_nbma->nbr)
269: {
270: nbr_nbma->nbr->nbr_nbma = NULL;
271: nbr_nbma->nbr = NULL;
272: }
273:
274: nbr_nbma->oi = NULL;
275:
276: listnode_delete (oi->nbr_nbma, nbr_nbma);
277: }
278:
279: /* send Neighbor event KillNbr to all associated neighbors. */
280: for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
281: if ((nbr = rn->info) != NULL)
282: if (nbr != oi->nbr_self)
283: OSPF_NSM_EVENT_EXECUTE (nbr, NSM_KillNbr);
284:
285: /* Cleanup Link State Acknowlegdment list. */
286: for (ALL_LIST_ELEMENTS (oi->ls_ack, node, nnode, lsa))
287: ospf_lsa_unlock (&lsa); /* oi->ls_ack */
288: list_delete_all_node (oi->ls_ack);
289:
290: oi->crypt_seqnum = 0;
291:
292: /* Empty link state update queue */
293: ospf_ls_upd_queue_empty (oi);
294:
295: /* Reset pseudo neighbor. */
1.1.1.3 ! misho 296: ospf_nbr_self_reset (oi);
1.1 misho 297: }
298:
299: void
300: ospf_if_free (struct ospf_interface *oi)
301: {
302: ospf_if_down (oi);
303:
304: assert (oi->state == ISM_Down);
305:
306: ospf_opaque_type9_lsa_term (oi);
307:
308: /* Free Pseudo Neighbour */
309: ospf_nbr_delete (oi->nbr_self);
310:
311: route_table_finish (oi->nbrs);
312: route_table_finish (oi->ls_upd_queue);
313:
314: /* Free any lists that should be freed */
315: list_free (oi->nbr_nbma);
316:
317: list_free (oi->ls_ack);
318: list_free (oi->ls_ack_direct.ls_ack);
319:
320: ospf_delete_from_if (oi->ifp, oi);
321:
322: listnode_delete (oi->ospf->oiflist, oi);
323: listnode_delete (oi->area->oiflist, oi);
324:
325: thread_cancel_event (master, oi);
326:
327: memset (oi, 0, sizeof (*oi));
328: XFREE (MTYPE_OSPF_IF, oi);
329: }
330:
1.1.1.3 ! misho 331:
1.1 misho 332: /*
333: * check if interface with given address is configured and
334: * return it if yes. special treatment for PtP networks.
335: */
336: struct ospf_interface *
337: ospf_if_is_configured (struct ospf *ospf, struct in_addr *address)
338: {
339: struct listnode *node, *nnode;
340: struct ospf_interface *oi;
341: struct prefix_ipv4 addr;
342:
343: addr.family = AF_INET;
344: addr.prefix = *address;
345: addr.prefixlen = IPV4_MAX_PREFIXLEN;
346:
347: for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
348: if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
349: {
350: if (oi->type == OSPF_IFTYPE_POINTOPOINT)
351: {
352: /* special leniency: match if addr is anywhere on peer subnet */
353: if (prefix_match(CONNECTED_PREFIX(oi->connected),
354: (struct prefix *)&addr))
355: return oi;
356: }
357: else
358: {
359: if (IPV4_ADDR_SAME (address, &oi->address->u.prefix4))
360: return oi;
361: }
362: }
363: return NULL;
364: }
365:
366: int
367: ospf_if_is_up (struct ospf_interface *oi)
368: {
369: return if_is_up (oi->ifp);
370: }
371:
372: struct ospf_interface *
373: ospf_if_exists (struct ospf_interface *oic)
374: {
375: struct listnode *node;
376: struct ospf *ospf;
377: struct ospf_interface *oi;
378:
379: if ((ospf = ospf_lookup ()) == NULL)
380: return NULL;
381:
382: for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
383: if (oi == oic)
384: return oi;
385:
386: return NULL;
387: }
388:
1.1.1.2 misho 389: /* Lookup OSPF interface by router LSA posistion */
390: struct ospf_interface *
391: ospf_if_lookup_by_lsa_pos (struct ospf_area *area, int lsa_pos)
392: {
393: struct listnode *node;
394: struct ospf_interface *oi;
395:
396: for (ALL_LIST_ELEMENTS_RO (area->oiflist, node, oi))
397: {
398: if (lsa_pos >= oi->lsa_pos_beg && lsa_pos < oi->lsa_pos_end)
399: return oi;
400: }
401: return NULL;
402: }
403:
1.1 misho 404: struct ospf_interface *
405: ospf_if_lookup_by_local_addr (struct ospf *ospf,
406: struct interface *ifp, struct in_addr address)
407: {
408: struct listnode *node;
409: struct ospf_interface *oi;
410:
411: for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
412: if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
413: {
414: if (ifp && oi->ifp != ifp)
415: continue;
416:
417: if (IPV4_ADDR_SAME (&address, &oi->address->u.prefix4))
418: return oi;
419: }
420:
421: return NULL;
422: }
423:
424: struct ospf_interface *
425: ospf_if_lookup_by_prefix (struct ospf *ospf, struct prefix_ipv4 *p)
426: {
427: struct listnode *node;
428: struct ospf_interface *oi;
429:
430: /* Check each Interface. */
431: for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
432: {
433: if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
434: {
435: struct prefix ptmp;
436:
437: prefix_copy (&ptmp, CONNECTED_PREFIX(oi->connected));
438: apply_mask (&ptmp);
439: if (prefix_same (&ptmp, (struct prefix *) p))
440: return oi;
441: }
442: }
443: return NULL;
444: }
445:
446: /* determine receiving interface by ifp and source address */
447: struct ospf_interface *
448: ospf_if_lookup_recv_if (struct ospf *ospf, struct in_addr src,
449: struct interface *ifp)
450: {
451: struct route_node *rn;
452: struct prefix_ipv4 addr;
453: struct ospf_interface *oi, *match;
454:
455: addr.family = AF_INET;
456: addr.prefix = src;
457: addr.prefixlen = IPV4_MAX_BITLEN;
458:
459: match = NULL;
460:
461: for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
462: {
463: oi = rn->info;
464:
465: if (!oi) /* oi can be NULL for PtP aliases */
466: continue;
467:
468: if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
469: continue;
470:
471: if (if_is_loopback (oi->ifp))
472: continue;
473:
474: if (prefix_match (CONNECTED_PREFIX(oi->connected),
475: (struct prefix *) &addr))
476: {
477: if ( (match == NULL) ||
478: (match->address->prefixlen < oi->address->prefixlen)
479: )
480: match = oi;
481: }
482: }
483:
484: return match;
485: }
1.1.1.3 ! misho 486:
1.1 misho 487: void
488: ospf_if_stream_set (struct ospf_interface *oi)
489: {
490: /* set output fifo queue. */
491: if (oi->obuf == NULL)
492: oi->obuf = ospf_fifo_new ();
493: }
494:
495: void
496: ospf_if_stream_unset (struct ospf_interface *oi)
497: {
498: struct ospf *ospf = oi->ospf;
499:
500: if (oi->obuf)
501: {
502: ospf_fifo_free (oi->obuf);
503: oi->obuf = NULL;
504:
505: if (oi->on_write_q)
506: {
507: listnode_delete (ospf->oi_write_q, oi);
508: if (list_isempty(ospf->oi_write_q))
509: OSPF_TIMER_OFF (ospf->t_write);
510: oi->on_write_q = 0;
511: }
512: }
513: }
514:
1.1.1.3 ! misho 515:
1.1 misho 516: static struct ospf_if_params *
517: ospf_new_if_params (void)
518: {
519: struct ospf_if_params *oip;
520:
521: oip = XCALLOC (MTYPE_OSPF_IF_PARAMS, sizeof (struct ospf_if_params));
522:
523: if (!oip)
524: return NULL;
525:
526: UNSET_IF_PARAM (oip, output_cost_cmd);
527: UNSET_IF_PARAM (oip, transmit_delay);
528: UNSET_IF_PARAM (oip, retransmit_interval);
529: UNSET_IF_PARAM (oip, passive_interface);
530: UNSET_IF_PARAM (oip, v_hello);
531: UNSET_IF_PARAM (oip, fast_hello);
532: UNSET_IF_PARAM (oip, v_wait);
533: UNSET_IF_PARAM (oip, priority);
534: UNSET_IF_PARAM (oip, type);
535: UNSET_IF_PARAM (oip, auth_simple);
536: UNSET_IF_PARAM (oip, auth_crypt);
537: UNSET_IF_PARAM (oip, auth_type);
538:
539: oip->auth_crypt = list_new ();
540:
541: oip->network_lsa_seqnum = htonl(OSPF_INITIAL_SEQUENCE_NUMBER);
542:
543: return oip;
544: }
545:
546: void
547: ospf_del_if_params (struct ospf_if_params *oip)
548: {
549: list_delete (oip->auth_crypt);
550: XFREE (MTYPE_OSPF_IF_PARAMS, oip);
551: }
552:
553: void
554: ospf_free_if_params (struct interface *ifp, struct in_addr addr)
555: {
556: struct ospf_if_params *oip;
557: struct prefix_ipv4 p;
558: struct route_node *rn;
559:
560: p.family = AF_INET;
561: p.prefixlen = IPV4_MAX_PREFIXLEN;
562: p.prefix = addr;
563: rn = route_node_lookup (IF_OIFS_PARAMS (ifp), (struct prefix*)&p);
564: if (!rn || !rn->info)
565: return;
566:
567: oip = rn->info;
568: route_unlock_node (rn);
569:
570: if (!OSPF_IF_PARAM_CONFIGURED (oip, output_cost_cmd) &&
571: !OSPF_IF_PARAM_CONFIGURED (oip, transmit_delay) &&
572: !OSPF_IF_PARAM_CONFIGURED (oip, retransmit_interval) &&
573: !OSPF_IF_PARAM_CONFIGURED (oip, passive_interface) &&
574: !OSPF_IF_PARAM_CONFIGURED (oip, v_hello) &&
575: !OSPF_IF_PARAM_CONFIGURED (oip, fast_hello) &&
576: !OSPF_IF_PARAM_CONFIGURED (oip, v_wait) &&
577: !OSPF_IF_PARAM_CONFIGURED (oip, priority) &&
578: !OSPF_IF_PARAM_CONFIGURED (oip, type) &&
579: !OSPF_IF_PARAM_CONFIGURED (oip, auth_simple) &&
580: !OSPF_IF_PARAM_CONFIGURED (oip, auth_type) &&
581: listcount (oip->auth_crypt) == 0 &&
582: ntohl (oip->network_lsa_seqnum) != OSPF_INITIAL_SEQUENCE_NUMBER)
583: {
584: ospf_del_if_params (oip);
585: rn->info = NULL;
586: route_unlock_node (rn);
587: }
588: }
589:
590: struct ospf_if_params *
591: ospf_lookup_if_params (struct interface *ifp, struct in_addr addr)
592: {
593: struct prefix_ipv4 p;
594: struct route_node *rn;
595:
596: p.family = AF_INET;
597: p.prefixlen = IPV4_MAX_PREFIXLEN;
598: p.prefix = addr;
599:
600: rn = route_node_lookup (IF_OIFS_PARAMS (ifp), (struct prefix*)&p);
601:
602: if (rn)
603: {
604: route_unlock_node (rn);
605: return rn->info;
606: }
607:
608: return NULL;
609: }
610:
611: struct ospf_if_params *
612: ospf_get_if_params (struct interface *ifp, struct in_addr addr)
613: {
614: struct prefix_ipv4 p;
615: struct route_node *rn;
616:
617: p.family = AF_INET;
618: p.prefixlen = IPV4_MAX_PREFIXLEN;
619: p.prefix = addr;
620:
621: rn = route_node_get (IF_OIFS_PARAMS (ifp), (struct prefix*)&p);
622:
623: if (rn->info == NULL)
624: rn->info = ospf_new_if_params ();
625: else
626: route_unlock_node (rn);
627:
628: return rn->info;
629: }
630:
631: void
632: ospf_if_update_params (struct interface *ifp, struct in_addr addr)
633: {
634: struct route_node *rn;
635: struct ospf_interface *oi;
636:
637: for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
638: {
639: if ((oi = rn->info) == NULL)
640: continue;
641:
642: if (IPV4_ADDR_SAME (&oi->address->u.prefix4, &addr))
643: oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4);
644: }
645: }
646:
647: int
648: ospf_if_new_hook (struct interface *ifp)
649: {
650: int rc = 0;
651:
652: ifp->info = XCALLOC (MTYPE_OSPF_IF_INFO, sizeof (struct ospf_if_info));
653:
654: IF_OIFS (ifp) = route_table_init ();
655: IF_OIFS_PARAMS (ifp) = route_table_init ();
656:
657: IF_DEF_PARAMS (ifp) = ospf_new_if_params ();
658:
659: SET_IF_PARAM (IF_DEF_PARAMS (ifp), transmit_delay);
660: IF_DEF_PARAMS (ifp)->transmit_delay = OSPF_TRANSMIT_DELAY_DEFAULT;
661:
662: SET_IF_PARAM (IF_DEF_PARAMS (ifp), retransmit_interval);
663: IF_DEF_PARAMS (ifp)->retransmit_interval = OSPF_RETRANSMIT_INTERVAL_DEFAULT;
664:
665: SET_IF_PARAM (IF_DEF_PARAMS (ifp), priority);
666: IF_DEF_PARAMS (ifp)->priority = OSPF_ROUTER_PRIORITY_DEFAULT;
667:
668: IF_DEF_PARAMS (ifp)->mtu_ignore = OSPF_MTU_IGNORE_DEFAULT;
669:
670: SET_IF_PARAM (IF_DEF_PARAMS (ifp), v_hello);
671: IF_DEF_PARAMS (ifp)->v_hello = OSPF_HELLO_INTERVAL_DEFAULT;
672:
673: SET_IF_PARAM (IF_DEF_PARAMS (ifp), fast_hello);
674: IF_DEF_PARAMS (ifp)->fast_hello = OSPF_FAST_HELLO_DEFAULT;
675:
676: SET_IF_PARAM (IF_DEF_PARAMS (ifp), v_wait);
677: IF_DEF_PARAMS (ifp)->v_wait = OSPF_ROUTER_DEAD_INTERVAL_DEFAULT;
678:
679: SET_IF_PARAM (IF_DEF_PARAMS (ifp), auth_simple);
680: memset (IF_DEF_PARAMS (ifp)->auth_simple, 0, OSPF_AUTH_SIMPLE_SIZE);
681:
682: SET_IF_PARAM (IF_DEF_PARAMS (ifp), auth_type);
683: IF_DEF_PARAMS (ifp)->auth_type = OSPF_AUTH_NOTSET;
684:
685: rc = ospf_opaque_new_if (ifp);
686: return rc;
687: }
688:
689: static int
690: ospf_if_delete_hook (struct interface *ifp)
691: {
692: int rc = 0;
693: struct route_node *rn;
694: rc = ospf_opaque_del_if (ifp);
695:
696: route_table_finish (IF_OIFS (ifp));
697:
698: for (rn = route_top (IF_OIFS_PARAMS (ifp)); rn; rn = route_next (rn))
699: if (rn->info)
700: ospf_del_if_params (rn->info);
701: route_table_finish (IF_OIFS_PARAMS (ifp));
702:
703: ospf_del_if_params ((struct ospf_if_params *) IF_DEF_PARAMS (ifp));
704: XFREE (MTYPE_OSPF_IF_INFO, ifp->info);
705: ifp->info = NULL;
706:
707: return rc;
708: }
709:
710: int
711: ospf_if_is_enable (struct ospf_interface *oi)
712: {
713: if (!if_is_loopback (oi->ifp))
714: if (if_is_up (oi->ifp))
715: return 1;
716:
717: return 0;
718: }
719:
720: void
721: ospf_if_set_multicast(struct ospf_interface *oi)
722: {
723: if ((oi->state > ISM_Loopback) &&
724: (oi->type != OSPF_IFTYPE_LOOPBACK) &&
725: (oi->type != OSPF_IFTYPE_VIRTUALLINK) &&
726: (OSPF_IF_PASSIVE_STATUS(oi) == OSPF_IF_ACTIVE))
727: {
728: /* The interface should belong to the OSPF-all-routers group. */
729: if (!OI_MEMBER_CHECK(oi, MEMBER_ALLROUTERS) &&
730: (ospf_if_add_allspfrouters(oi->ospf, oi->address,
731: oi->ifp->ifindex) >= 0))
732: /* Set the flag only if the system call to join succeeded. */
733: OI_MEMBER_JOINED(oi, MEMBER_ALLROUTERS);
734: }
735: else
736: {
737: /* The interface should NOT belong to the OSPF-all-routers group. */
738: if (OI_MEMBER_CHECK(oi, MEMBER_ALLROUTERS))
739: {
740: /* Only actually drop if this is the last reference */
741: if (OI_MEMBER_COUNT(oi, MEMBER_ALLROUTERS) == 1)
742: ospf_if_drop_allspfrouters (oi->ospf, oi->address,
743: oi->ifp->ifindex);
744: /* Unset the flag regardless of whether the system call to leave
745: the group succeeded, since it's much safer to assume that
746: we are not a member. */
747: OI_MEMBER_LEFT(oi,MEMBER_ALLROUTERS);
748: }
749: }
750:
751: if (((oi->type == OSPF_IFTYPE_BROADCAST) ||
752: (oi->type == OSPF_IFTYPE_POINTOPOINT)) &&
753: ((oi->state == ISM_DR) || (oi->state == ISM_Backup)) &&
754: (OSPF_IF_PASSIVE_STATUS(oi) == OSPF_IF_ACTIVE))
755: {
756: /* The interface should belong to the OSPF-designated-routers group. */
757: if (!OI_MEMBER_CHECK(oi, MEMBER_DROUTERS) &&
758: (ospf_if_add_alldrouters(oi->ospf, oi->address,
759: oi->ifp->ifindex) >= 0))
760: /* Set the flag only if the system call to join succeeded. */
761: OI_MEMBER_JOINED(oi, MEMBER_DROUTERS);
762: }
763: else
764: {
765: /* The interface should NOT belong to the OSPF-designated-routers group */
766: if (OI_MEMBER_CHECK(oi, MEMBER_DROUTERS))
767: {
768: /* drop only if last reference */
769: if (OI_MEMBER_COUNT(oi, MEMBER_DROUTERS) == 1)
770: ospf_if_drop_alldrouters(oi->ospf, oi->address, oi->ifp->ifindex);
771:
772: /* Unset the flag regardless of whether the system call to leave
773: the group succeeded, since it's much safer to assume that
774: we are not a member. */
775: OI_MEMBER_LEFT(oi, MEMBER_DROUTERS);
776: }
777: }
778: }
779:
780: int
781: ospf_if_up (struct ospf_interface *oi)
782: {
783: if (oi == NULL)
784: return 0;
785:
786: if (oi->type == OSPF_IFTYPE_LOOPBACK)
787: OSPF_ISM_EVENT_SCHEDULE (oi, ISM_LoopInd);
788: else
789: {
790: struct ospf *ospf = ospf_lookup ();
791: if (ospf != NULL)
792: ospf_adjust_sndbuflen (ospf, oi->ifp->mtu);
793: else
794: zlog_warn ("%s: ospf_lookup() returned NULL", __func__);
795: ospf_if_stream_set (oi);
796: OSPF_ISM_EVENT_SCHEDULE (oi, ISM_InterfaceUp);
797: }
798:
799: return 1;
800: }
801:
802: int
803: ospf_if_down (struct ospf_interface *oi)
804: {
805: if (oi == NULL)
806: return 0;
807:
808: OSPF_ISM_EVENT_EXECUTE (oi, ISM_InterfaceDown);
1.1.1.2 misho 809: /* delete position in router LSA */
810: oi->lsa_pos_beg = 0;
811: oi->lsa_pos_end = 0;
1.1 misho 812: /* Shutdown packet reception and sending */
813: ospf_if_stream_unset (oi);
814:
815: return 1;
816: }
817:
1.1.1.3 ! misho 818:
1.1 misho 819: /* Virtual Link related functions. */
820:
821: struct ospf_vl_data *
822: ospf_vl_data_new (struct ospf_area *area, struct in_addr vl_peer)
823: {
824: struct ospf_vl_data *vl_data;
825:
826: vl_data = XCALLOC (MTYPE_OSPF_VL_DATA, sizeof (struct ospf_vl_data));
827:
828: vl_data->vl_peer.s_addr = vl_peer.s_addr;
829: vl_data->vl_area_id = area->area_id;
830: vl_data->format = area->format;
831:
832: return vl_data;
833: }
834:
835: void
836: ospf_vl_data_free (struct ospf_vl_data *vl_data)
837: {
838: XFREE (MTYPE_OSPF_VL_DATA, vl_data);
839: }
840:
841: u_int vlink_count = 0;
842:
843: struct ospf_interface *
844: ospf_vl_new (struct ospf *ospf, struct ospf_vl_data *vl_data)
845: {
846: struct ospf_interface * voi;
847: struct interface * vi;
848: char ifname[INTERFACE_NAMSIZ + 1];
849: struct ospf_area *area;
850: struct in_addr area_id;
851: struct connected *co;
852: struct prefix_ipv4 *p;
853:
854: if (IS_DEBUG_OSPF_EVENT)
855: zlog_debug ("ospf_vl_new(): Start");
856: if (vlink_count == OSPF_VL_MAX_COUNT)
857: {
858: if (IS_DEBUG_OSPF_EVENT)
859: zlog_debug ("ospf_vl_new(): Alarm: "
860: "cannot create more than OSPF_MAX_VL_COUNT virtual links");
861: return NULL;
862: }
863:
864: if (IS_DEBUG_OSPF_EVENT)
865: zlog_debug ("ospf_vl_new(): creating pseudo zebra interface");
866:
867: snprintf (ifname, sizeof(ifname), "VLINK%d", vlink_count);
868: vi = if_create (ifname, strnlen(ifname, sizeof(ifname)));
869: co = connected_new ();
870: co->ifp = vi;
871: listnode_add (vi->connected, co);
872:
873: p = prefix_ipv4_new ();
874: p->family = AF_INET;
875: p->prefix.s_addr = 0;
876: p->prefixlen = 0;
877:
878: co->address = (struct prefix *)p;
879:
880: voi = ospf_if_new (ospf, vi, co->address);
881: if (voi == NULL)
882: {
883: if (IS_DEBUG_OSPF_EVENT)
884: zlog_debug ("ospf_vl_new(): Alarm: OSPF int structure is not created");
885: return NULL;
886: }
887: voi->connected = co;
888: voi->vl_data = vl_data;
889: voi->ifp->mtu = OSPF_VL_MTU;
890: voi->type = OSPF_IFTYPE_VIRTUALLINK;
891:
892: vlink_count++;
893: if (IS_DEBUG_OSPF_EVENT)
894: zlog_debug ("ospf_vl_new(): Created name: %s", ifname);
895: if (IS_DEBUG_OSPF_EVENT)
896: zlog_debug ("ospf_vl_new(): set if->name to %s", vi->name);
897:
898: area_id.s_addr = 0;
899: area = ospf_area_get (ospf, area_id, OSPF_AREA_ID_FORMAT_ADDRESS);
900: voi->area = area;
901:
902: if (IS_DEBUG_OSPF_EVENT)
903: zlog_debug ("ospf_vl_new(): set associated area to the backbone");
904:
905: ospf_nbr_add_self (voi);
906: ospf_area_add_if (voi->area, voi);
907:
908: ospf_if_stream_set (voi);
909:
910: if (IS_DEBUG_OSPF_EVENT)
911: zlog_debug ("ospf_vl_new(): Stop");
912: return voi;
913: }
914:
915: static void
916: ospf_vl_if_delete (struct ospf_vl_data *vl_data)
917: {
918: struct interface *ifp = vl_data->vl_oi->ifp;
919: vl_data->vl_oi->address->u.prefix4.s_addr = 0;
920: vl_data->vl_oi->address->prefixlen = 0;
921: ospf_if_free (vl_data->vl_oi);
922: if_delete (ifp);
923: vlink_count--;
924: }
925:
926: /* Look up vl_data for given peer, optionally qualified to be in the
927: * specified area. NULL area returns first found..
928: */
929: struct ospf_vl_data *
930: ospf_vl_lookup (struct ospf *ospf, struct ospf_area *area,
931: struct in_addr vl_peer)
932: {
933: struct ospf_vl_data *vl_data;
934: struct listnode *node;
935:
936: if (IS_DEBUG_OSPF_EVENT)
937: {
938: zlog_debug ("%s: Looking for %s", __func__, inet_ntoa (vl_peer));
939: if (area)
940: zlog_debug ("%s: in area %s", __func__, inet_ntoa (area->area_id));
941: }
942:
943: for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl_data))
944: {
945: if (IS_DEBUG_OSPF_EVENT)
946: zlog_debug ("%s: VL %s, peer %s", __func__,
947: vl_data->vl_oi->ifp->name,
948: inet_ntoa (vl_data->vl_peer));
949:
950: if (area && !IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
951: continue;
952:
953: if (IPV4_ADDR_SAME (&vl_data->vl_peer, &vl_peer))
954: return vl_data;
955: }
956:
957: return NULL;
958: }
959:
960: static void
961: ospf_vl_shutdown (struct ospf_vl_data *vl_data)
962: {
963: struct ospf_interface *oi;
964:
965: if ((oi = vl_data->vl_oi) == NULL)
966: return;
967:
968: oi->address->u.prefix4.s_addr = 0;
969: oi->address->prefixlen = 0;
970:
971: UNSET_FLAG (oi->ifp->flags, IFF_UP);
972: /* OSPF_ISM_EVENT_SCHEDULE (oi, ISM_InterfaceDown); */
973: OSPF_ISM_EVENT_EXECUTE (oi, ISM_InterfaceDown);
974: }
975:
976: void
977: ospf_vl_add (struct ospf *ospf, struct ospf_vl_data *vl_data)
978: {
979: listnode_add (ospf->vlinks, vl_data);
980: #ifdef HAVE_SNMP
981: ospf_snmp_vl_add (vl_data);
982: #endif /* HAVE_SNMP */
983: }
984:
985: void
986: ospf_vl_delete (struct ospf *ospf, struct ospf_vl_data *vl_data)
987: {
988: ospf_vl_shutdown (vl_data);
989: ospf_vl_if_delete (vl_data);
990:
991: #ifdef HAVE_SNMP
992: ospf_snmp_vl_delete (vl_data);
993: #endif /* HAVE_SNMP */
994: listnode_delete (ospf->vlinks, vl_data);
995:
996: ospf_vl_data_free (vl_data);
997: }
998:
999: static int
1000: ospf_vl_set_params (struct ospf_vl_data *vl_data, struct vertex *v)
1001: {
1002: int changed = 0;
1003: struct ospf_interface *voi;
1004: struct listnode *node;
1005: struct vertex_parent *vp = NULL;
1.1.1.3 ! misho 1006: unsigned int i;
1.1 misho 1007: struct router_lsa *rl;
1008:
1009: voi = vl_data->vl_oi;
1010:
1011: if (voi->output_cost != v->distance)
1012: {
1013:
1014: voi->output_cost = v->distance;
1015: changed = 1;
1016: }
1017:
1018: for (ALL_LIST_ELEMENTS_RO (v->parents, node, vp))
1019: {
1020: vl_data->nexthop.oi = vp->nexthop->oi;
1021: vl_data->nexthop.router = vp->nexthop->router;
1022:
1023: if (!IPV4_ADDR_SAME(&voi->address->u.prefix4,
1024: &vl_data->nexthop.oi->address->u.prefix4))
1025: changed = 1;
1026:
1027: voi->address->u.prefix4 = vl_data->nexthop.oi->address->u.prefix4;
1028: voi->address->prefixlen = vl_data->nexthop.oi->address->prefixlen;
1029:
1030: break; /* We take the first interface. */
1031: }
1032:
1033: rl = (struct router_lsa *)v->lsa;
1034:
1035: /* use SPF determined backlink index in struct vertex
1036: * for virtual link destination address
1037: */
1038: if (vp && vp->backlink >= 0)
1039: {
1040: if (!IPV4_ADDR_SAME (&vl_data->peer_addr,
1041: &rl->link[vp->backlink].link_data))
1042: changed = 1;
1043: vl_data->peer_addr = rl->link[vp->backlink].link_data;
1044: }
1045: else
1046: {
1047: /* This is highly odd, there is no backlink index
1048: * there should be due to the ospf_spf_has_link() check
1049: * in SPF. Lets warn and try pick a link anyway.
1050: */
1051: zlog_warn ("ospf_vl_set_params: No backlink for %s!",
1052: vl_data->vl_oi->ifp->name);
1053: for (i = 0; i < ntohs (rl->links); i++)
1054: {
1055: switch (rl->link[i].type)
1056: {
1057: case LSA_LINK_TYPE_VIRTUALLINK:
1058: if (IS_DEBUG_OSPF_EVENT)
1059: zlog_debug ("found back link through VL");
1060: case LSA_LINK_TYPE_TRANSIT:
1061: case LSA_LINK_TYPE_POINTOPOINT:
1062: if (!IPV4_ADDR_SAME (&vl_data->peer_addr,
1063: &rl->link[i].link_data))
1064: changed = 1;
1065: vl_data->peer_addr = rl->link[i].link_data;
1066: }
1067: }
1068: }
1069:
1070: if (IS_DEBUG_OSPF_EVENT)
1071: zlog_debug ("%s: %s peer address: %s, cost: %d,%schanged", __func__,
1072: vl_data->vl_oi->ifp->name,
1073: inet_ntoa(vl_data->peer_addr),
1074: voi->output_cost,
1075: (changed ? " " : " un"));
1076:
1077: return changed;
1078: }
1079:
1080:
1081: void
1082: ospf_vl_up_check (struct ospf_area *area, struct in_addr rid,
1083: struct vertex *v)
1084: {
1085: struct ospf *ospf = area->ospf;
1086: struct listnode *node;
1087: struct ospf_vl_data *vl_data;
1088: struct ospf_interface *oi;
1089:
1090: if (IS_DEBUG_OSPF_EVENT)
1091: {
1092: zlog_debug ("ospf_vl_up_check(): Start");
1093: zlog_debug ("ospf_vl_up_check(): Router ID is %s", inet_ntoa (rid));
1094: zlog_debug ("ospf_vl_up_check(): Area is %s", inet_ntoa (area->area_id));
1095: }
1096:
1097: for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl_data))
1098: {
1099: if (IS_DEBUG_OSPF_EVENT)
1100: {
1101: zlog_debug ("%s: considering VL, %s in area %s", __func__,
1102: vl_data->vl_oi->ifp->name,
1103: inet_ntoa (vl_data->vl_area_id));
1104: zlog_debug ("%s: peer ID: %s", __func__,
1105: inet_ntoa (vl_data->vl_peer));
1106: }
1107:
1108: if (IPV4_ADDR_SAME (&vl_data->vl_peer, &rid) &&
1109: IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
1110: {
1111: oi = vl_data->vl_oi;
1112: SET_FLAG (vl_data->flags, OSPF_VL_FLAG_APPROVED);
1113:
1114: if (IS_DEBUG_OSPF_EVENT)
1115: zlog_debug ("ospf_vl_up_check(): this VL matched");
1116:
1117: if (oi->state == ISM_Down)
1118: {
1119: if (IS_DEBUG_OSPF_EVENT)
1120: zlog_debug ("ospf_vl_up_check(): VL is down, waking it up");
1121: SET_FLAG (oi->ifp->flags, IFF_UP);
1122: OSPF_ISM_EVENT_EXECUTE(oi,ISM_InterfaceUp);
1123: }
1124:
1125: if (ospf_vl_set_params (vl_data, v))
1126: {
1127: if (IS_DEBUG_OSPF (ism, ISM_EVENTS))
1128: zlog_debug ("ospf_vl_up_check: VL cost change,"
1129: " scheduling router lsa refresh");
1130: if (ospf->backbone)
1131: ospf_router_lsa_update_area (ospf->backbone);
1132: else if (IS_DEBUG_OSPF (ism, ISM_EVENTS))
1133: zlog_debug ("ospf_vl_up_check: VL cost change, no backbone!");
1134: }
1135: }
1136: }
1137: }
1138:
1139: void
1140: ospf_vl_unapprove (struct ospf *ospf)
1141: {
1142: struct listnode *node;
1143: struct ospf_vl_data *vl_data;
1144:
1145: for (ALL_LIST_ELEMENTS_RO (ospf->vlinks, node, vl_data))
1146: UNSET_FLAG (vl_data->flags, OSPF_VL_FLAG_APPROVED);
1147: }
1148:
1149: void
1150: ospf_vl_shut_unapproved (struct ospf *ospf)
1151: {
1152: struct listnode *node, *nnode;
1153: struct ospf_vl_data *vl_data;
1154:
1155: for (ALL_LIST_ELEMENTS (ospf->vlinks, node, nnode, vl_data))
1156: if (!CHECK_FLAG (vl_data->flags, OSPF_VL_FLAG_APPROVED))
1157: ospf_vl_shutdown (vl_data);
1158: }
1159:
1160: int
1161: ospf_full_virtual_nbrs (struct ospf_area *area)
1162: {
1163: if (IS_DEBUG_OSPF_EVENT)
1164: {
1165: zlog_debug ("counting fully adjacent virtual neighbors in area %s",
1166: inet_ntoa (area->area_id));
1167: zlog_debug ("there are %d of them", area->full_vls);
1168: }
1169:
1170: return area->full_vls;
1171: }
1172:
1173: int
1174: ospf_vls_in_area (struct ospf_area *area)
1175: {
1176: struct listnode *node;
1177: struct ospf_vl_data *vl_data;
1178: int c = 0;
1179:
1180: for (ALL_LIST_ELEMENTS_RO (area->ospf->vlinks, node, vl_data))
1181: if (IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
1182: c++;
1183:
1184: return c;
1185: }
1186:
1.1.1.3 ! misho 1187:
1.1 misho 1188: struct crypt_key *
1189: ospf_crypt_key_new ()
1190: {
1191: return XCALLOC (MTYPE_OSPF_CRYPT_KEY, sizeof (struct crypt_key));
1192: }
1193:
1194: void
1195: ospf_crypt_key_add (struct list *crypt, struct crypt_key *ck)
1196: {
1197: listnode_add (crypt, ck);
1198: }
1199:
1200: struct crypt_key *
1201: ospf_crypt_key_lookup (struct list *auth_crypt, u_char key_id)
1202: {
1203: struct listnode *node;
1204: struct crypt_key *ck;
1205:
1206: for (ALL_LIST_ELEMENTS_RO (auth_crypt, node, ck))
1207: if (ck->key_id == key_id)
1208: return ck;
1209:
1210: return NULL;
1211: }
1212:
1213: int
1214: ospf_crypt_key_delete (struct list *auth_crypt, u_char key_id)
1215: {
1216: struct listnode *node, *nnode;
1217: struct crypt_key *ck;
1218:
1219: for (ALL_LIST_ELEMENTS (auth_crypt, node, nnode, ck))
1220: {
1221: if (ck->key_id == key_id)
1222: {
1223: listnode_delete (auth_crypt, ck);
1224: XFREE (MTYPE_OSPF_CRYPT_KEY, ck);
1225: return 1;
1226: }
1227: }
1228:
1229: return 0;
1230: }
1231:
1232: u_char
1233: ospf_default_iftype(struct interface *ifp)
1234: {
1235: if (if_is_pointopoint (ifp))
1236: return OSPF_IFTYPE_POINTOPOINT;
1237: else if (if_is_loopback (ifp))
1238: return OSPF_IFTYPE_LOOPBACK;
1239: else
1240: return OSPF_IFTYPE_BROADCAST;
1241: }
1242:
1243: void
1244: ospf_if_init ()
1245: {
1246: /* Initialize Zebra interface data structure. */
1247: om->iflist = iflist;
1248: if_add_hook (IF_NEW_HOOK, ospf_if_new_hook);
1249: if_add_hook (IF_DELETE_HOOK, ospf_if_delete_hook);
1250: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>