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