]> git.proxmox.com Git - mirror_frr.git/blame - ospfd/ospf_interface.c
Initial revision
[mirror_frr.git] / ospfd / ospf_interface.c
CommitLineData
718e3744 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/ospf_spf.h"
36#include "ospfd/ospf_interface.h"
37#include "ospfd/ospf_ism.h"
38#include "ospfd/ospf_asbr.h"
39#include "ospfd/ospf_lsa.h"
40#include "ospfd/ospf_lsdb.h"
41#include "ospfd/ospf_neighbor.h"
42#include "ospfd/ospf_nsm.h"
43#include "ospfd/ospf_packet.h"
44#include "ospfd/ospf_abr.h"
45#include "ospfd/ospfd.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\f
53int
54ospf_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 = ospf_top ? ospf_top->ref_bandwidth : OSPF_DEFAULT_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
81void
82ospf_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_timer_add (oi->area);
101 }
102 }
103}
104
105void
106ospf_if_reset_variables (struct ospf_interface *oi)
107{
108 /* Set default values. */
109 /* don't clear this flag. oi->flag = OSPF_IF_DISABLE; */
110
111 if (oi->vl_data)
112 oi->type = OSPF_IFTYPE_VIRTUALLINK;
113 else
114 /* preserve network-type */
115 if (oi->type != OSPF_IFTYPE_NBMA)
116 oi->type = OSPF_IFTYPE_BROADCAST;
117
118 oi->state = ISM_Down;
119
120 oi->crypt_seqnum = 0;
121
122 /* This must be short, (less than RxmtInterval)
123 - RFC 2328 Section 13.5 para 3. Set to 1 second to avoid Acks being
124 held back for too long - MAG */
125 oi->v_ls_ack = 1;
126}
127
128void
129ospf_add_to_if (struct interface *ifp, struct ospf_interface *oi)
130{
131 struct route_node *rn;
132 struct prefix p;
133
134 p = *oi->address;
135 p.prefixlen = IPV4_MAX_PREFIXLEN;
136
137 rn = route_node_get (IF_OIFS (ifp), &p);
138 assert (! rn->info);
139 rn->info = oi;
140}
141
142void
143ospf_delete_from_if (struct interface *ifp, struct ospf_interface *oi)
144{
145 struct route_node *rn;
146 struct prefix p;
147
148 p = *oi->address;
149 p.prefixlen = IPV4_MAX_PREFIXLEN;
150
151 rn = route_node_lookup (IF_OIFS (oi->ifp), &p);
152 assert (rn);
153 assert (rn->info);
154 rn->info = NULL;
155 route_unlock_node (rn);
156 route_unlock_node (rn);
157}
158
159struct ospf_interface *
160ospf_if_new (struct interface *ifp, struct prefix *p)
161{
162 struct ospf_interface *oi;
163
164 oi = XCALLOC (MTYPE_OSPF_IF, sizeof (struct ospf_interface));
165 memset (oi, 0, sizeof (struct ospf_interface));
166
167 /* Set zebra interface pointer. */
168 oi->ifp = ifp;
169 oi->address = p;
170
171 ospf_add_to_if (ifp, oi);
172 listnode_add (ospf_top->oiflist, oi);
173
174 /* Clear self-originated network-LSA. */
175 oi->network_lsa_self = NULL;
176
177 /* Initialize neighbor list. */
178 oi->nbrs = route_table_init ();
179
180 /* Initialize static neighbor list. */
181 oi->nbr_nbma = list_new ();
182
183 /* Initialize Link State Acknowledgment list. */
184 oi->ls_ack = list_new ();
185 oi->ls_ack_direct.ls_ack = list_new ();
186
187 /* Set default values. */
188 ospf_if_reset_variables (oi);
189
190 /* Add pseudo neighbor. */
191 oi->nbr_self = ospf_nbr_new (oi);
192 oi->nbr_self->state = NSM_TwoWay;
193 /* oi->nbr_self->router_id = ospf_top->router_id; */
194 oi->nbr_self->priority = OSPF_IF_PARAM (oi, priority);
195 oi->nbr_self->options = OSPF_OPTION_E;
196
197 oi->ls_upd_queue = route_table_init ();
198 oi->t_ls_upd_event = NULL;
199 oi->t_ls_ack_direct = NULL;
200
201#ifdef HAVE_OPAQUE_LSA
202 ospf_opaque_type9_lsa_init (oi);
203#endif /* HAVE_OPAQUE_LSA */
204
205 oi->ospf = ospf_top;
206
207 return oi;
208}
209
210/* Restore an interface to its pre UP state
211 Used from ism_interface_down only */
212void
213ospf_if_cleanup (struct ospf_interface *oi)
214{
215 struct route_node *rn;
216 listnode node;
217 struct ospf_neighbor *nbr;
218
219 /* oi->nbrs and oi->nbr_nbma should be deletete on InterafceDown event */
220 /* delete all static neighbors attached to this interface */
221 for (node = listhead (oi->nbr_nbma); node; )
222 {
223 struct ospf_nbr_nbma *nbr_nbma = getdata (node);
224 nextnode (node);
225
226 OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll);
227
228 if (nbr_nbma->nbr)
229 {
230 nbr_nbma->nbr->nbr_nbma = NULL;
231 nbr_nbma->nbr = NULL;
232 }
233
234 nbr_nbma->oi = NULL;
235
236 listnode_delete (oi->nbr_nbma, nbr_nbma);
237 }
238
239 /* send Neighbor event KillNbr to all associated neighbors. */
240 for (rn = route_top (oi->nbrs); rn; rn = route_next (rn))
241 if ((nbr = rn->info) != NULL)
242 if (nbr != oi->nbr_self)
243 OSPF_NSM_EVENT_EXECUTE (nbr, NSM_KillNbr);
244
245 /* Cleanup Link State Acknowlegdment list. */
246 for (node = listhead (oi->ls_ack); node; nextnode (node))
247 ospf_lsa_unlock (node->data);
248 list_delete_all_node (oi->ls_ack);
249
250 oi->crypt_seqnum = 0;
251
252 /* Empty link state update queue */
253 ospf_ls_upd_queue_empty (oi);
254
255 /* Handle pseudo neighbor. */
256 ospf_nbr_delete (oi->nbr_self);
257 oi->nbr_self = ospf_nbr_new (oi);
258 oi->nbr_self->state = NSM_TwoWay;
259 oi->nbr_self->priority = OSPF_IF_PARAM (oi, priority);
260 oi->nbr_self->options = OSPF_OPTION_E;
261
262 ospf_lsa_unlock (oi->network_lsa_self);
263 oi->network_lsa_self = NULL;
264 OSPF_TIMER_OFF (oi->t_network_lsa_self);
265}
266
267void
268ospf_if_free (struct ospf_interface *oi)
269{
270 ospf_if_down (oi);
271
272 assert (oi->state == ISM_Down);
273
274#ifdef HAVE_OPAQUE_LSA
275 ospf_opaque_type9_lsa_term (oi);
276#endif /* HAVE_OPAQUE_LSA */
277
278 /* Free Pseudo Neighbour */
279 ospf_nbr_delete (oi->nbr_self);
280
281 route_table_finish (oi->nbrs);
282 route_table_finish (oi->ls_upd_queue);
283
284 /* Free any lists that should be freed */
285 list_free (oi->nbr_nbma);
286
287 list_free (oi->ls_ack);
288 list_free (oi->ls_ack_direct.ls_ack);
289
290 ospf_delete_from_if (oi->ifp, oi);
291
292 listnode_delete (ospf_top->oiflist, oi);
293 listnode_delete (oi->area->oiflist, oi);
294
295 memset (oi, 0, sizeof (*oi));
296 XFREE (MTYPE_OSPF_IF, oi);
297}
298
299\f
300/*
301* check if interface with given address is configured and
302* return it if yes.
303*/
304struct ospf_interface *
305ospf_if_is_configured (struct in_addr *address)
306{
307 listnode node;
308 struct ospf_interface *oi;
309 struct prefix *addr;
310
311 for (node = listhead (ospf_top->oiflist); node; nextnode (node))
312 if ((oi = getdata (node)) != NULL && oi->type != OSPF_IFTYPE_VIRTUALLINK)
313 {
314 if (oi->type == OSPF_IFTYPE_POINTOPOINT)
315 addr = oi->connected->destination;
316 else
317 addr = oi->address;
318
319 if (IPV4_ADDR_SAME (address, &addr->u.prefix4))
320 return oi;
321 }
322
323 return NULL;
324}
325
326int
327ospf_if_is_up (struct ospf_interface *oi)
328{
329 return if_is_up (oi->ifp);
330}
331
332struct ospf_interface *
333ospf_if_lookup_by_local_addr (struct interface *ifp, struct in_addr address)
334{
335 listnode node;
336 struct ospf_interface *oi;
337
338 for (node = listhead (ospf_top->oiflist); node; nextnode (node))
339 if ((oi = getdata (node)) != NULL && oi->type != OSPF_IFTYPE_VIRTUALLINK)
340 {
341 if (ifp && oi->ifp != ifp)
342 continue;
343
344 if (IPV4_ADDR_SAME (&address, &oi->address->u.prefix4))
345 return oi;
346 }
347
348 return NULL;
349}
350
351struct ospf_interface *
352ospf_if_lookup_by_prefix (struct prefix_ipv4 *p)
353{
354 listnode node;
355 struct ospf_interface *oi;
356 struct prefix ptmp;
357
358 /* Check each Interface. */
359 for (node = listhead (ospf_top->oiflist); node; nextnode (node)) {
360 if ((oi = getdata (node)) != NULL && oi->type != OSPF_IFTYPE_VIRTUALLINK)
361 {
362 if (oi->type == OSPF_IFTYPE_POINTOPOINT) {
363 prefix_copy (&ptmp, oi->connected->destination);
364 ptmp.prefixlen = IPV4_MAX_BITLEN;
365 }
366 else
367 prefix_copy (&ptmp, oi->address);
368
369 apply_mask (&ptmp);
370 if (prefix_same (&ptmp, (struct prefix *) p))
371 return oi;
372 }
373 }
374 return NULL;
375}
376
377/* determine receiving interface by source of packet */
378struct ospf_interface *
379ospf_if_lookup_recv_interface (struct in_addr src)
380{
381 listnode node;
382 struct prefix_ipv4 addr;
383 struct ospf_interface *oi, *match;
384
385 addr.family = AF_INET;
386 addr.prefix = src;
387 addr.prefixlen = IPV4_MAX_BITLEN;
388
389 match = NULL;
390
391 for (node = listhead (ospf_top->oiflist); node; nextnode (node))
392 {
393 oi = getdata (node);
394
395 if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
396 continue;
397
398 if (oi->type == OSPF_IFTYPE_POINTOPOINT)
399 {
400 if (IPV4_ADDR_SAME (&oi->connected->destination->u.prefix4, &src))
401 return oi;
402 }
403 else
404 {
405 if (prefix_match (oi->address, (struct prefix *) &addr))
406 match = oi;
407 }
408 }
409
410 return match;
411}
412\f
413void
414ospf_if_stream_set (struct ospf_interface *oi)
415{
416 /* set output fifo queue. */
417 if (oi->obuf == NULL)
418 oi->obuf = ospf_fifo_new ();
419}
420
421void
422ospf_if_stream_unset (struct ospf_interface *oi)
423{
424 if (oi->obuf)
425 {
426 ospf_fifo_free (oi->obuf);
427 oi->obuf = NULL;
428
429 if (oi->on_write_q)
430 {
431 listnode_delete (ospf_top->oi_write_q, oi);
432 if (list_isempty(ospf_top->oi_write_q))
433 OSPF_TIMER_OFF (ospf_top->t_write);
434 oi->on_write_q = 0;
435 }
436 }
437}
438\f
439struct ospf_if_params *
440ospf_new_if_params ()
441{
442 struct ospf_if_params *oip;
443
444 oip = XMALLOC (MTYPE_OSPF_IF_PARAMS, sizeof (struct ospf_if_params));
445 memset (oip, 0, sizeof (struct ospf_if_params));
446
447 if (!oip)
448 return NULL;
449
450 memset (oip, 0, sizeof (struct ospf_if_params));
451
452 UNSET_IF_PARAM (oip, output_cost_cmd);
453 UNSET_IF_PARAM (oip, transmit_delay);
454 UNSET_IF_PARAM (oip, retransmit_interval);
455 UNSET_IF_PARAM (oip, passive_interface);
456 UNSET_IF_PARAM (oip, v_hello);
457 UNSET_IF_PARAM (oip, v_wait);
458 UNSET_IF_PARAM (oip, priority);
459 UNSET_IF_PARAM (oip, type);
460 UNSET_IF_PARAM (oip, auth_simple);
461 UNSET_IF_PARAM (oip, auth_crypt);
462 UNSET_IF_PARAM (oip, auth_type);
463
464 oip->auth_crypt = list_new ();
465
466 return oip;
467}
468
469void
470ospf_del_if_params (struct ospf_if_params *oip)
471{
472 list_delete (oip->auth_crypt);
473 XFREE (MTYPE_OSPF_IF_PARAMS, oip);
474}
475
476void
477ospf_free_if_params (struct interface *ifp, struct in_addr addr)
478{
479 struct ospf_if_params *oip;
480 struct prefix_ipv4 p;
481 struct route_node *rn;
482 p.prefixlen = IPV4_MAX_PREFIXLEN;
483 p.prefix = addr;
484 rn = route_node_lookup (IF_OIFS_PARAMS (ifp), (struct prefix*)&p);
485 if (!rn || !rn->info)
486 return;
487
488 oip = rn->info;
489 route_unlock_node (rn);
490
491 if (!OSPF_IF_PARAM_CONFIGURED (oip, output_cost_cmd) &&
492 !OSPF_IF_PARAM_CONFIGURED (oip, transmit_delay) &&
493 !OSPF_IF_PARAM_CONFIGURED (oip, retransmit_interval) &&
494 !OSPF_IF_PARAM_CONFIGURED (oip, passive_interface) &&
495 !OSPF_IF_PARAM_CONFIGURED (oip, v_hello) &&
496 !OSPF_IF_PARAM_CONFIGURED (oip, v_wait) &&
497 !OSPF_IF_PARAM_CONFIGURED (oip, priority) &&
498 !OSPF_IF_PARAM_CONFIGURED (oip, type) &&
499 !OSPF_IF_PARAM_CONFIGURED (oip, auth_simple) &&
500 !OSPF_IF_PARAM_CONFIGURED (oip, auth_type) &&
501 listcount (oip->auth_crypt) == 0)
502 {
503 ospf_del_if_params (oip);
504 rn->info = NULL;
505 route_unlock_node (rn);
506 }
507}
508
509struct ospf_if_params *
510ospf_lookup_if_params (struct interface *ifp, struct in_addr addr)
511{
512 struct prefix_ipv4 p;
513 struct route_node *rn;
514
515 p.prefixlen = IPV4_MAX_PREFIXLEN;
516 p.prefix = addr;
517
518 rn = route_node_lookup (IF_OIFS_PARAMS (ifp), (struct prefix*)&p);
519
520 if (rn)
521 {
522 route_unlock_node (rn);
523 return rn->info;
524 }
525
526 return NULL;
527}
528
529struct ospf_if_params *
530ospf_get_if_params (struct interface *ifp, struct in_addr addr)
531{
532 struct prefix_ipv4 p;
533 struct route_node *rn;
534
535 p.family = AF_INET;
536 p.prefixlen = IPV4_MAX_PREFIXLEN;
537 p.prefix = addr;
538
539 rn = route_node_get (IF_OIFS_PARAMS (ifp), (struct prefix*)&p);
540
541 if (rn->info == NULL)
542 rn->info = ospf_new_if_params ();
543 else
544 route_unlock_node (rn);
545
546 return rn->info;
547}
548
549void
550ospf_if_update_params (struct interface *ifp, struct in_addr addr)
551{
552 struct route_node *rn;
553 struct ospf_interface *oi;
554
555 for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
556 {
557 if ((oi = rn->info) == NULL)
558 continue;
559
560 if (IPV4_ADDR_SAME (&oi->address->u.prefix4, &addr))
561 oi->params = ospf_lookup_if_params (ifp, oi->address->u.prefix4);
562 }
563}
564
565int
566ospf_if_new_hook (struct interface *ifp)
567{
568 int rc = 0;
569
570 ifp->info = XMALLOC (MTYPE_OSPF_IF_INFO, sizeof (struct ospf_if_info));
571 memset (ifp->info, 0, sizeof (struct ospf_if_info));
572
573 IF_OIFS (ifp) = route_table_init ();
574 IF_OIFS_PARAMS (ifp) = route_table_init ();
575
576 IF_DEF_PARAMS (ifp) = ospf_new_if_params ();
577
578 SET_IF_PARAM (IF_DEF_PARAMS (ifp), transmit_delay);
579 IF_DEF_PARAMS (ifp)->transmit_delay = OSPF_TRANSMIT_DELAY_DEFAULT;
580
581 SET_IF_PARAM (IF_DEF_PARAMS (ifp), retransmit_interval);
582 IF_DEF_PARAMS (ifp)->retransmit_interval = OSPF_RETRANSMIT_INTERVAL_DEFAULT;
583
584 SET_IF_PARAM (IF_DEF_PARAMS (ifp), priority);
585 IF_DEF_PARAMS (ifp)->priority = OSPF_ROUTER_PRIORITY_DEFAULT;
586
587 SET_IF_PARAM (IF_DEF_PARAMS (ifp), passive_interface);
588 IF_DEF_PARAMS (ifp)->passive_interface = OSPF_IF_ACTIVE;
589
590 SET_IF_PARAM (IF_DEF_PARAMS (ifp), v_hello);
591 IF_DEF_PARAMS (ifp)->v_hello = OSPF_HELLO_INTERVAL_DEFAULT;
592
593 SET_IF_PARAM (IF_DEF_PARAMS (ifp), v_wait);
594 IF_DEF_PARAMS (ifp)->v_wait = OSPF_ROUTER_DEAD_INTERVAL_DEFAULT;
595
596 SET_IF_PARAM (IF_DEF_PARAMS (ifp), auth_simple);
597 memset (IF_DEF_PARAMS (ifp)->auth_simple, 0, OSPF_AUTH_SIMPLE_SIZE);
598
599 SET_IF_PARAM (IF_DEF_PARAMS (ifp), auth_crypt);
600 IF_DEF_PARAMS (ifp)->auth_crypt = list_new ();
601
602 SET_IF_PARAM (IF_DEF_PARAMS (ifp), auth_type);
603 IF_DEF_PARAMS (ifp)->auth_type = OSPF_AUTH_NOTSET;
604
605#ifdef HAVE_OPAQUE_LSA
606 rc = ospf_opaque_new_if (ifp);
607#endif /* HAVE_OPAQUE_LSA */
608 return rc;
609}
610
611int
612ospf_if_delete_hook (struct interface *ifp)
613{
614 int rc = 0;
615#ifdef HAVE_OPAQUE_LSA
616 rc = ospf_opaque_del_if (ifp);
617#endif /* HAVE_OPAQUE_LSA */
618 route_table_finish (IF_OIFS (ifp));
619 route_table_finish (IF_OIFS_PARAMS (ifp));
620 XFREE (MTYPE_OSPF_IF_INFO, ifp->info);
621 ifp->info = NULL;
622
623 return rc;
624}
625
626int
627ospf_if_is_enable (struct ospf_interface *oi)
628{
629 if (!if_is_loopback (oi->ifp))
630 if (if_is_up (oi->ifp))
631 return 1;
632
633 return 0;
634}
635
636int
637ospf_if_up (struct ospf_interface *oi)
638{
639 if (oi == NULL)
640 return 0;
641
642 if (oi->type == OSPF_IFTYPE_LOOPBACK)
643 OSPF_ISM_EVENT_SCHEDULE (oi, ISM_LoopInd);
644 else
645 {
646 if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
647 ospf_if_add_allspfrouters (ospf_top, oi->address, oi->ifp->ifindex);
648 ospf_if_stream_set (oi);
649 OSPF_ISM_EVENT_SCHEDULE (oi, ISM_InterfaceUp);
650 }
651
652 return 1;
653}
654
655int
656ospf_if_down (struct ospf_interface *oi)
657{
658 if (oi == NULL)
659 return 0;
660
661 OSPF_ISM_EVENT_EXECUTE (oi, ISM_InterfaceDown);
662 /* Shutdown packet reception and sending */
663 ospf_if_stream_unset (oi);
664 if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
665 ospf_if_drop_allspfrouters (ospf_top, oi->address, oi->ifp->ifindex);
666
667
668 return 1;
669}
670
671\f
672/* Virtual Link related functions. */
673
674struct ospf_vl_data *
675ospf_vl_data_new (struct ospf_area *area, struct in_addr vl_peer)
676{
677 struct ospf_vl_data *vl_data;
678
679 vl_data = XMALLOC (MTYPE_OSPF_VL_DATA, sizeof (struct ospf_vl_data));
680 memset (vl_data, 0, sizeof (struct ospf_vl_data));
681
682 vl_data->vl_peer.s_addr = vl_peer.s_addr;
683 vl_data->vl_area_id = area->area_id;
684 vl_data->format = area->format;
685
686 return vl_data;
687}
688
689void
690ospf_vl_data_free (struct ospf_vl_data *vl_data)
691{
692 XFREE (MTYPE_OSPF_VL_DATA, vl_data);
693}
694
695u_int vlink_count = 0;
696
697struct ospf_interface *
698ospf_vl_new (struct ospf_vl_data *vl_data)
699{
700 struct ospf_interface * voi;
701 struct interface * vi;
702 char ifname[INTERFACE_NAMSIZ + 1];
703 struct ospf_area *area;
704 struct in_addr area_id;
705 struct connected *co;
706 struct prefix_ipv4 *p;
707
708 if (IS_DEBUG_OSPF_EVENT)
709 zlog_info ("ospf_vl_new(): Start");
710 if (vlink_count == OSPF_VL_MAX_COUNT)
711 {
712 if (IS_DEBUG_OSPF_EVENT)
713 zlog_info ("ospf_vl_new(): Alarm: "
714 "cannot create more than OSPF_MAX_VL_COUNT virtual links");
715 return NULL;
716 }
717
718 if (IS_DEBUG_OSPF_EVENT)
719 zlog_info ("ospf_vl_new(): creating pseudo zebra interface");
720
721 vi = if_create ();
722 co = connected_new ();
723 co->ifp = vi;
724 listnode_add (vi->connected, co);
725
726 p = prefix_ipv4_new ();
727 p->family = AF_INET;
728 p->prefix.s_addr = 0;
729 p->prefixlen = 0;
730
731 co->address = (struct prefix *)p;
732
733 voi = ospf_if_new (vi, co->address);
734 if (voi == NULL)
735 {
736 if (IS_DEBUG_OSPF_EVENT)
737 zlog_info ("ospf_vl_new(): Alarm: OSPF int structure is not created");
738 return NULL;
739 }
740 voi->connected = co;
741 voi->vl_data = vl_data;
742 voi->ifp->mtu = OSPF_VL_MTU;
743 voi->type = OSPF_IFTYPE_VIRTUALLINK;
744
745 sprintf (ifname, "VLINK%d", vlink_count++);
746 if (IS_DEBUG_OSPF_EVENT)
747 zlog_info ("ospf_vl_new(): Created name: %s", ifname);
748 strncpy (vi->name, ifname, IFNAMSIZ);
749 if (IS_DEBUG_OSPF_EVENT)
750 zlog_info ("ospf_vl_new(): set if->name to %s", vi->name);
751
752 area_id.s_addr = 0;
753 area = ospf_area_get (area_id, OSPF_AREA_ID_FORMAT_ADDRESS);
754 voi->area = area;
755
756 if (IS_DEBUG_OSPF_EVENT)
757 zlog_info ("ospf_vl_new(): set associated area to the backbone");
758
759 ospf_area_add_if (voi->area, voi);
760
761 ospf_if_stream_set (voi);
762
763 if (IS_DEBUG_OSPF_EVENT)
764 zlog_info ("ospf_vl_new(): Stop");
765 return voi;
766}
767
768void
769ospf_vl_if_delete (struct ospf_vl_data *vl_data)
770{
771 struct interface *ifp = vl_data->vl_oi->ifp;
772 vl_data->vl_oi->address->u.prefix4.s_addr = 0;
773 vl_data->vl_oi->address->prefixlen = 0;
774 ospf_if_free (vl_data->vl_oi);
775 if_delete (ifp);
776 vlink_count--;
777}
778
779struct ospf_vl_data *
780ospf_vl_lookup (struct ospf_area *area, struct in_addr vl_peer)
781{
782 struct ospf_vl_data *vl_data;
783 listnode node;
784
785 for (node = listhead (ospf_top->vlinks); node; nextnode (node))
786 if ((vl_data = getdata (node)) != NULL)
787 if (vl_data->vl_peer.s_addr == vl_peer.s_addr &&
788 IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
789 return vl_data;
790
791 return NULL;
792}
793
794void
795ospf_vl_shutdown (struct ospf_vl_data *vl_data)
796{
797 struct ospf_interface *oi;
798
799 if ((oi = vl_data->vl_oi) == NULL)
800 return;
801
802 oi->address->u.prefix4.s_addr = 0;
803 oi->address->prefixlen = 0;
804
805 UNSET_FLAG (oi->ifp->flags, IFF_UP);
806 /* OSPF_ISM_EVENT_SCHEDULE (oi, ISM_InterfaceDown); */
807 OSPF_ISM_EVENT_EXECUTE (oi, ISM_InterfaceDown);
808}
809
810void
811ospf_vl_add (struct ospf_vl_data *vl_data)
812{
813 listnode_add (ospf_top->vlinks, vl_data);
814#ifdef HAVE_SNMP
815 ospf_snmp_vl_add (vl_data);
816#endif /* HAVE_SNMP */
817}
818
819void
820ospf_vl_delete (struct ospf_vl_data *vl_data)
821{
822 ospf_vl_shutdown (vl_data);
823 ospf_vl_if_delete (vl_data);
824
825#ifdef HAVE_SNMP
826 ospf_snmp_vl_delete (vl_data);
827#endif /* HAVE_SNMP */
828 listnode_delete (ospf_top->vlinks, vl_data);
829
830 ospf_vl_data_free (vl_data);
831}
832
833void
834ospf_vl_set_params (struct ospf_vl_data *vl_data, struct vertex *v)
835{
836 int changed = 0;
837 struct ospf_interface *voi;
838 listnode node;
839 struct vertex_nexthop *nh;
840 int i;
841 struct router_lsa *rl;
842
843 voi = vl_data->vl_oi;
844
845 if (voi->output_cost != v->distance)
846 {
847 voi->output_cost = v->distance;
848 changed = 1;
849 }
850
851 for (node = listhead (v->nexthop); node; nextnode (node))
852 if ((nh = getdata (node)) != NULL)
853 {
854 vl_data->out_oi = (struct ospf_interface *) nh->oi;
855
856 voi->address->u.prefix4 = vl_data->out_oi->address->u.prefix4;
857 voi->address->prefixlen = vl_data->out_oi->address->prefixlen;
858
859 break; /* We take the first interface. */
860 }
861
862 rl = (struct router_lsa *)v->lsa;
863
864 for (i = 0; i < ntohs (rl->links); i++)
865 {
866 switch (rl->link[i].type)
867 {
868 case LSA_LINK_TYPE_VIRTUALLINK:
869 if (IS_DEBUG_OSPF_EVENT)
870 zlog_info ("found back link through VL");
871 case LSA_LINK_TYPE_TRANSIT:
872 case LSA_LINK_TYPE_POINTOPOINT:
873 vl_data->peer_addr = rl->link[i].link_data;
874 if (IS_DEBUG_OSPF_EVENT)
875 zlog_info ("%s peer address is %s\n",
876 vl_data->vl_oi->ifp->name, inet_ntoa(vl_data->peer_addr));
877 return;
878 }
879 }
880}
881
882
883void
884ospf_vl_up_check (struct ospf_area * area, struct in_addr rid,
885 struct vertex *v)
886{
887 listnode node;
888 struct ospf_vl_data *vl_data;
889 struct ospf_interface *oi;
890
891 if (IS_DEBUG_OSPF_EVENT)
892 {
893 zlog_info ("ospf_vl_up_check(): Start");
894 zlog_info ("ospf_vl_up_check(): Router ID is %s", inet_ntoa (rid));
895 zlog_info ("ospf_vl_up_check(): Area is %s", inet_ntoa (area->area_id));
896 }
897
898 for (node = listhead (ospf_top->vlinks); node; nextnode (node))
899 {
900 if ((vl_data = getdata (node)) == NULL)
901 continue;
902
903 if (IS_DEBUG_OSPF_EVENT)
904 {
905 zlog_info ("ospf_vl_up_check(): considering VL, name: %s",
906 vl_data->vl_oi->ifp->name);
907 zlog_info ("ospf_vl_up_check(): VL area: %s, peer ID: %s",
908 inet_ntoa (vl_data->vl_area_id),
909 inet_ntoa (vl_data->vl_peer));
910 }
911
912 if (IPV4_ADDR_SAME (&vl_data->vl_peer, &rid) &&
913 IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
914 {
915 oi = vl_data->vl_oi;
916 SET_FLAG (vl_data->flags, OSPF_VL_FLAG_APPROVED);
917
918 if (IS_DEBUG_OSPF_EVENT)
919 zlog_info ("ospf_vl_up_check(): this VL matched");
920
921 if (oi->state == ISM_Down)
922 {
923 if (IS_DEBUG_OSPF_EVENT)
924 zlog_info ("ospf_vl_up_check(): VL is down, waking it up");
925 SET_FLAG (oi->ifp->flags, IFF_UP);
926 OSPF_ISM_EVENT_SCHEDULE (oi, ISM_InterfaceUp);
927 }
928
929 ospf_vl_set_params (vl_data, v);
930 }
931 }
932}
933
934void
935ospf_vl_unapprove ()
936{
937 listnode node;
938 struct ospf_vl_data *vl_data;
939
940 for (node = listhead (ospf_top->vlinks); node; nextnode (node))
941 if ((vl_data = getdata (node)) != NULL)
942 UNSET_FLAG (vl_data->flags, OSPF_VL_FLAG_APPROVED);
943}
944
945void
946ospf_vl_shut_unapproved ()
947{
948 listnode node;
949 struct ospf_vl_data *vl_data;
950
951 for (node = listhead (ospf_top->vlinks); node; nextnode (node))
952 if ((vl_data = getdata (node)) != NULL)
953 if (!CHECK_FLAG (vl_data->flags, OSPF_VL_FLAG_APPROVED))
954 ospf_vl_shutdown (vl_data);
955}
956
957int
958ospf_full_virtual_nbrs (struct ospf_area *area)
959{
960 if (IS_DEBUG_OSPF_EVENT)
961 {
962 zlog_info ("counting fully adjacent virtual neighbors in area %s",
963 inet_ntoa (area->area_id));
964 zlog_info ("there are %d of them", area->full_vls);
965 }
966
967 return area->full_vls;
968}
969
970int
971ospf_vls_in_area (struct ospf_area *area)
972{
973 listnode node;
974 struct ospf_vl_data *vl_data;
975 int c = 0;
976
977 for (node = listhead (ospf_top->vlinks); node; nextnode (node))
978 if ((vl_data = getdata (node)) != NULL)
979 if (IPV4_ADDR_SAME (&vl_data->vl_area_id, &area->area_id))
980 c++;
981
982 return c;
983}
984
985\f
986struct crypt_key *
987ospf_crypt_key_new ()
988{
989 struct crypt_key *ck;
990
991 ck = XMALLOC (MTYPE_OSPF_CRYPT_KEY, sizeof (struct crypt_key));
992 memset (ck, 0, sizeof (struct crypt_key));
993
994 return ck;
995}
996
997void
998ospf_crypt_key_add (list crypt, struct crypt_key *ck)
999{
1000 listnode_add (crypt, ck);
1001}
1002
1003struct crypt_key *
1004ospf_crypt_key_lookup (list auth_crypt, u_char key_id)
1005{
1006 listnode node;
1007 struct crypt_key *ck;
1008
1009 for (node = listhead (auth_crypt); node; nextnode (node))
1010 {
1011 ck = getdata (node);
1012 if (ck->key_id == key_id)
1013 return ck;
1014 }
1015
1016 return NULL;
1017}
1018
1019int
1020ospf_crypt_key_delete (list auth_crypt, u_char key_id)
1021{
1022 listnode node;
1023 struct crypt_key *ck;
1024
1025 for (node = listhead (auth_crypt); node; nextnode (node))
1026 {
1027 ck = getdata (node);
1028 if (ck->key_id == key_id)
1029 {
1030 listnode_delete (auth_crypt, ck);
1031 return 1;
1032 }
1033 }
1034
1035 return 0;
1036}
1037
1038void
1039ospf_if_init ()
1040{
1041 /* Initialize Zebra interface data structure. */
1042 if_init ();
1043 if_add_hook (IF_NEW_HOOK, ospf_if_new_hook);
1044 if_add_hook (IF_DELETE_HOOK, ospf_if_delete_hook);
1045}