]>
git.ipfire.org Git - thirdparty/bird.git/blob - proto/ospf/iface.c
4 * (c) 1999--2005 Ondrej Filip <feela@network.cz>
6 * Can be freely distributed and used under the terms of the GNU GPL.
11 char *ospf_is
[] = { "down", "loop", "waiting", "ptp", "drother",
15 char *ospf_ism
[] = { "interface up", "wait timer fired", "backup seen",
16 "neighbor change", "loop indicated", "unloop indicated", "interface down"
19 char *ospf_it
[] = { "broadcast", "nbma", "ptp", "ptmp", "virtual link" };
22 poll_timer_hook(timer
* timer
)
24 ospf_hello_send(timer
->data
, OHS_POLL
, NULL
);
28 hello_timer_hook(timer
* timer
)
30 ospf_hello_send(timer
->data
, OHS_HELLO
, NULL
);
34 wait_timer_hook(timer
* timer
)
36 struct ospf_iface
*ifa
= (struct ospf_iface
*) timer
->data
;
37 struct proto
*p
= &ifa
->oa
->po
->proto
;
39 OSPF_TRACE(D_EVENTS
, "Wait timer fired on interface %s.", ifa
->iface
->name
);
40 ospf_iface_sm(ifa
, ISM_WAITF
);
43 static void ospf_iface_change_mtu(struct proto_ospf
*po
, struct ospf_iface
*ifa
);
46 rxbufsize(struct ospf_iface
*ifa
)
50 case OSPF_RXBUF_NORMAL
:
51 return (ifa
->iface
->mtu
* 2);
53 case OSPF_RXBUF_LARGE
:
54 return OSPF_MAX_PKT_SIZE
;
63 find_nbma_node_in(list
*nnl
, ip_addr ip
)
67 if (ipa_equal(nn
->ip
, ip
))
73 ospf_sk_open(struct ospf_iface
*ifa
)
75 sock
*sk
= sk_new(ifa
->pool
);
77 sk
->dport
= OSPF_PROTO
;
80 sk
->tos
= ifa
->cf
->tx_tos
;
81 sk
->priority
= ifa
->cf
->tx_priority
;
82 sk
->rx_hook
= ospf_rx_hook
;
83 sk
->tx_hook
= ospf_tx_hook
;
84 sk
->err_hook
= ospf_err_hook
;
85 sk
->iface
= ifa
->iface
;
86 sk
->rbsize
= rxbufsize(ifa
);
87 sk
->tbsize
= rxbufsize(ifa
);
88 sk
->data
= (void *) ifa
;
89 sk
->flags
= SKF_LADDR_RX
;
95 /* 12 is an offset of the checksum in an OSPF packet */
96 if (sk_set_ipv6_checksum(sk
, 12) < 0)
101 * For OSPFv2: When sending a packet, it is important to have a
102 * proper source address. We expect that when we send one-hop
103 * unicast packets, OS chooses a source address according to the
104 * destination address (to be in the same prefix). We also expect
105 * that when we send multicast packets, OS uses the source address
106 * from sk->saddr registered to OS by sk_setup_multicast(). This
107 * behavior is needed to implement multiple virtual ifaces (struct
108 * ospf_iface) on one physical iface and is signalized by
109 * CONFIG_MC_PROPER_SRC.
111 * If this behavior is not available (for example on BSD), we create
112 * non-stub iface just for the primary IP address (see
113 * ospf_iface_stubby()) and we expect OS to use primary IP address
114 * as a source address for both unicast and multicast packets.
116 * FIXME: the primary IP address is currently just the
117 * lexicographically smallest address on an interface, it should be
118 * signalized by sysdep code which one is really the primary.
121 sk
->saddr
= ifa
->addr
->ip
;
122 if ((ifa
->type
== OSPF_IT_BCAST
) || (ifa
->type
== OSPF_IT_PTP
))
124 if (ifa
->cf
->real_bcast
)
126 ifa
->all_routers
= ifa
->addr
->brd
;
128 if (sk_set_broadcast(sk
, 1) < 0)
133 ifa
->all_routers
= AllSPFRouters
;
134 sk
->ttl
= 1; /* Hack, this will affect just multicast packets */
136 if (sk_setup_multicast(sk
) < 0)
139 if (sk_join_group(sk
, ifa
->all_routers
) < 0)
154 ospf_sk_join_dr(struct ospf_iface
*ifa
)
159 sk_join_group(ifa
->sk
, AllDRouters
);
164 ospf_sk_leave_dr(struct ospf_iface
*ifa
)
169 sk_leave_group(ifa
->sk
, AllDRouters
);
174 ospf_iface_down(struct ospf_iface
*ifa
)
176 struct ospf_neighbor
*n
, *nx
;
177 struct proto_ospf
*po
= ifa
->oa
->po
;
178 struct proto
*p
= &po
->proto
;
179 struct ospf_iface
*iff
;
181 if (ifa
->type
!= OSPF_IT_VLINK
)
184 OSPF_TRACE(D_EVENTS
, "Removing interface %s (%I/%d) from area %R",
185 ifa
->iface
->name
, ifa
->addr
->prefix
, ifa
->addr
->pxlen
, ifa
->oa
->areaid
);
187 OSPF_TRACE(D_EVENTS
, "Removing interface %s (IID %d) from area %R",
188 ifa
->iface
->name
, ifa
->instance_id
, ifa
->oa
->areaid
);
191 /* First of all kill all the related vlinks */
192 WALK_LIST(iff
, po
->iface_list
)
194 if ((iff
->type
== OSPF_IT_VLINK
) && (iff
->vifa
== ifa
))
195 ospf_iface_sm(iff
, ISM_DOWN
);
199 WALK_LIST_DELSAFE(n
, nx
, ifa
->neigh_list
)
201 OSPF_TRACE(D_EVENTS
, "Removing neighbor %I", n
->ip
);
202 ospf_neigh_remove(n
);
205 if (ifa
->hello_timer
)
206 tm_stop(ifa
->hello_timer
);
209 tm_stop(ifa
->poll_timer
);
212 tm_stop(ifa
->wait_timer
);
214 if (ifa
->type
== OSPF_IT_VLINK
)
234 ospf_iface_remove(struct ospf_iface
*ifa
)
236 struct proto
*p
= &ifa
->oa
->po
->proto
;
237 if (ifa
->type
== OSPF_IT_VLINK
)
238 OSPF_TRACE(D_EVENTS
, "Removing vlink to %R via area %R", ifa
->vid
, ifa
->voa
->areaid
);
240 ospf_iface_sm(ifa
, ISM_DOWN
);
246 ospf_iface_shutdown(struct ospf_iface
*ifa
)
248 if (ifa
->state
> OSPF_IS_DOWN
)
249 ospf_hello_send(ifa
, OHS_SHUTDOWN
, NULL
);
253 * ospf_iface_chstate - handle changes of interface state
254 * @ifa: OSPF interface
257 * Many actions must be taken according to interface state changes. New network
258 * LSAs must be originated, flushed, new multicast sockets to listen for messages for
259 * %ALLDROUTERS have to be opened, etc.
262 ospf_iface_chstate(struct ospf_iface
*ifa
, u8 state
)
264 struct proto_ospf
*po
= ifa
->oa
->po
;
265 struct proto
*p
= &po
->proto
;
266 u8 oldstate
= ifa
->state
;
268 if (oldstate
== state
)
273 if (ifa
->type
== OSPF_IT_VLINK
)
274 OSPF_TRACE(D_EVENTS
, "Changing state of virtual link %R from %s to %s",
275 ifa
->vid
, ospf_is
[oldstate
], ospf_is
[state
]);
277 OSPF_TRACE(D_EVENTS
, "Changing state of iface %s from %s to %s",
278 ifa
->iface
->name
, ospf_is
[oldstate
], ospf_is
[state
]);
280 if ((ifa
->type
== OSPF_IT_BCAST
) && !ifa
->cf
->real_bcast
&& ifa
->sk
)
282 if ((state
== OSPF_IS_BACKUP
) || (state
== OSPF_IS_DR
))
283 ospf_sk_join_dr(ifa
);
285 ospf_sk_leave_dr(ifa
);
288 if ((oldstate
== OSPF_IS_DR
) && (ifa
->net_lsa
!= NULL
))
290 ifa
->net_lsa
->lsa
.age
= LSA_MAXAGE
;
291 if (state
>= OSPF_IS_WAITING
)
292 ospf_lsupd_flush_nlsa(po
, ifa
->net_lsa
);
294 if (can_flush_lsa(po
))
295 flush_lsa(ifa
->net_lsa
, po
);
299 if ((oldstate
> OSPF_IS_LOOP
) && (state
<= OSPF_IS_LOOP
))
300 ospf_iface_down(ifa
);
302 schedule_rt_lsa(ifa
->oa
);
303 // FIXME flushling of link LSA
307 * ospf_iface_sm - OSPF interface state machine
308 * @ifa: OSPF interface
309 * @event: event comming to state machine
311 * This fully respects 9.3 of RFC 2328 except we have slightly
312 * different handling of %DOWN and %LOOP state. We remove intefaces
313 * that are %DOWN. %DOWN state is used when an interface is waiting
314 * for a lock. %LOOP state is used when an interface does not have a
318 ospf_iface_sm(struct ospf_iface
*ifa
, int event
)
320 DBG("SM on %s %s. Event is '%s'\n", (ifa
->type
== OSPF_IT_VLINK
) ? "vlink" : "iface",
321 ifa
->iface
? ifa
->iface
->name
: "(none)" , ospf_ism
[event
]);
326 if (ifa
->state
<= OSPF_IS_LOOP
)
328 /* Now, nothing should be adjacent */
329 if ((ifa
->type
== OSPF_IT_PTP
) || (ifa
->type
== OSPF_IT_PTMP
) || (ifa
->type
== OSPF_IT_VLINK
))
331 ospf_iface_chstate(ifa
, OSPF_IS_PTP
);
335 if (ifa
->priority
== 0)
336 ospf_iface_chstate(ifa
, OSPF_IS_DROTHER
);
339 ospf_iface_chstate(ifa
, OSPF_IS_WAITING
);
341 tm_start(ifa
->wait_timer
, ifa
->waitint
);
345 if (ifa
->hello_timer
)
346 tm_start(ifa
->hello_timer
, ifa
->helloint
);
349 tm_start(ifa
->poll_timer
, ifa
->pollint
);
351 ospf_hello_send(ifa
, OHS_HELLO
, NULL
);
352 schedule_link_lsa(ifa
);
358 if (ifa
->state
== OSPF_IS_WAITING
)
365 if ((ifa
->state
== OSPF_IS_DROTHER
) || (ifa
->state
== OSPF_IS_DR
) ||
366 (ifa
->state
== OSPF_IS_BACKUP
))
369 schedule_rt_lsa(ifa
->oa
);
374 if ((ifa
->state
> OSPF_IS_LOOP
) && ifa
->check_link
)
375 ospf_iface_chstate(ifa
, OSPF_IS_LOOP
);
379 /* Immediate go UP */
380 if (ifa
->state
== OSPF_IS_LOOP
)
381 ospf_iface_sm(ifa
, ISM_UP
);
385 ospf_iface_chstate(ifa
, OSPF_IS_DOWN
);
389 bug("OSPF_I_SM - Unknown event?");
396 ospf_iface_classify_int(struct iface
*ifa
, struct ifa
*addr
)
398 if (ipa_nonzero(addr
->opposite
))
399 return (ifa
->flags
& IF_MULTICAST
) ? OSPF_IT_PTP
: OSPF_IT_PTMP
;
401 if ((ifa
->flags
& (IF_MULTIACCESS
| IF_MULTICAST
)) ==
402 (IF_MULTIACCESS
| IF_MULTICAST
))
403 return OSPF_IT_BCAST
;
405 if ((ifa
->flags
& (IF_MULTIACCESS
| IF_MULTICAST
)) == IF_MULTIACCESS
)
412 ospf_iface_classify(u8 type
, struct ifa
*addr
)
414 return (type
!= OSPF_IT_UNDEF
) ? type
: ospf_iface_classify_int(addr
->iface
, addr
);
419 ospf_iface_find(struct proto_ospf
*p
, struct iface
*what
)
421 struct ospf_iface
*i
;
423 WALK_LIST(i
, p
->iface_list
) if ((i
->iface
== what
) && (i
->type
!= OSPF_IT_VLINK
))
429 ospf_iface_add(struct object_lock
*lock
)
431 struct ospf_iface
*ifa
= lock
->data
;
432 struct proto_ospf
*po
= ifa
->oa
->po
;
433 struct proto
*p
= &po
->proto
;
435 /* Open socket if interface is not stub */
436 if (! ifa
->stub
&& ! ospf_sk_open(ifa
))
438 log(L_ERR
"%s: Socket open failed on interface %s, declaring as stub", p
->name
, ifa
->iface
->name
);
439 ifa
->ioprob
= OSPF_I_SK
;
445 ifa
->hello_timer
= tm_new_set(ifa
->pool
, hello_timer_hook
, ifa
, 0, ifa
->helloint
);
447 if (ifa
->type
== OSPF_IT_NBMA
)
448 ifa
->poll_timer
= tm_new_set(ifa
->pool
, poll_timer_hook
, ifa
, 0, ifa
->pollint
);
450 if ((ifa
->type
== OSPF_IT_BCAST
) || (ifa
->type
== OSPF_IT_NBMA
))
451 ifa
->wait_timer
= tm_new_set(ifa
->pool
, wait_timer_hook
, ifa
, 0, 0);
454 /* Do iface UP, unless there is no link and we use link detection */
455 ospf_iface_sm(ifa
, (ifa
->check_link
&& !(ifa
->iface
->flags
& IF_LINK_UP
)) ? ISM_LOOP
: ISM_UP
);
459 add_nbma_node(struct ospf_iface
*ifa
, struct nbma_node
*src
, int found
)
461 struct nbma_node
*n
= mb_alloc(ifa
->pool
, sizeof(struct nbma_node
));
462 add_tail(&ifa
->nbma_list
, NODE n
);
464 n
->eligible
= src
->eligible
;
469 ospf_iface_stubby(struct ospf_iface_patt
*ip
, struct ifa
*addr
)
474 /* a host/loopback address */
475 if (addr
->flags
& IA_HOST
)
479 * We cannot properly support multiple OSPF ifaces on real iface
480 * with multiple prefixes, therefore we force OSPF ifaces with
481 * non-primary IP prefixes to be stub.
483 #if defined(OSPFv2) && !defined(CONFIG_MC_PROPER_SRC)
484 if (! (addr
->flags
& IA_PRIMARY
))
492 ospf_iface_new(struct ospf_area
*oa
, struct ifa
*addr
, struct ospf_iface_patt
*ip
)
494 struct proto
*p
= &oa
->po
->proto
;
495 struct iface
*iface
= addr
? addr
->iface
: NULL
;
498 struct ospf_iface
*ifa
;
499 struct nbma_node
*nb
;
500 struct object_lock
*lock
;
502 if (ip
->type
== OSPF_IT_VLINK
)
503 OSPF_TRACE(D_EVENTS
, "Adding vlink to %R via area %R", ip
->vid
, ip
->voa
);
507 OSPF_TRACE(D_EVENTS
, "Adding interface %s (%I/%d) to area %R",
508 iface
->name
, addr
->prefix
, addr
->pxlen
, oa
->areaid
);
510 OSPF_TRACE(D_EVENTS
, "Adding interface %s (IID %d) to area %R",
511 iface
->name
, ip
->instance_id
, oa
->areaid
);
515 pool
= rp_new(p
->pool
, "OSPF Interface");
516 ifa
= mb_allocz(pool
, sizeof(struct ospf_iface
));
523 ifa
->cost
= ip
->cost
;
524 ifa
->rxmtint
= ip
->rxmtint
;
525 ifa
->inftransdelay
= ip
->inftransdelay
;
526 ifa
->priority
= ip
->priority
;
527 ifa
->helloint
= ip
->helloint
;
528 ifa
->pollint
= ip
->pollint
;
529 ifa
->strictnbma
= ip
->strictnbma
;
530 ifa
->waitint
= ip
->waitint
;
531 ifa
->deadint
= ip
->deadint
;
532 ifa
->stub
= ospf_iface_stubby(ip
, addr
);
533 ifa
->ioprob
= OSPF_I_OK
;
534 ifa
->rxbuf
= ip
->rxbuf
;
535 ifa
->check_link
= ip
->check_link
;
536 ifa
->ecmp_weight
= ip
->ecmp_weight
;
539 ifa
->autype
= ip
->autype
;
540 ifa
->passwords
= ip
->passwords
;
541 ifa
->ptp_netmask
= addr
? !(addr
->flags
& IA_PEER
) : 0;
542 if (ip
->ptp_netmask
< 2)
543 ifa
->ptp_netmask
= ip
->ptp_netmask
;
547 ifa
->instance_id
= ip
->instance_id
;
550 ifa
->type
= ospf_iface_classify(ip
->type
, addr
);
552 /* Check validity of interface type */
553 int old_type
= ifa
->type
;
554 u32 if_multi_flag
= ip
->real_bcast
? IF_BROADCAST
: IF_MULTICAST
;
557 if ((ifa
->type
== OSPF_IT_BCAST
) && (addr
->flags
& IA_PEER
))
558 ifa
->type
= OSPF_IT_PTP
;
560 if ((ifa
->type
== OSPF_IT_NBMA
) && (addr
->flags
& IA_PEER
))
561 ifa
->type
= OSPF_IT_PTMP
;
564 if ((ifa
->type
== OSPF_IT_BCAST
) && !(iface
->flags
& if_multi_flag
))
565 ifa
->type
= OSPF_IT_NBMA
;
567 if ((ifa
->type
== OSPF_IT_PTP
) && !(iface
->flags
& if_multi_flag
))
568 ifa
->type
= OSPF_IT_PTMP
;
570 if (ifa
->type
!= old_type
)
571 log(L_WARN
"%s: Cannot use interface %s as %s, forcing %s",
572 p
->name
, iface
->name
, ospf_it
[old_type
], ospf_it
[ifa
->type
]);
574 /* Assign iface ID, for vlinks, this is ugly hack */
575 ifa
->iface_id
= (ifa
->type
!= OSPF_IT_VLINK
) ? iface
->index
: oa
->po
->last_vlink_id
++;
577 init_list(&ifa
->neigh_list
);
578 init_list(&ifa
->nbma_list
);
580 WALK_LIST(nb
, ip
->nbma_list
)
582 /* In OSPFv3, addr is link-local while configured neighbors could
583 have global IP (although RFC 5340 C.5 says link-local addresses
584 should be used). Because OSPFv3 iface is not subnet-specific,
585 there is no need for ipa_in_net() check */
588 if (!ipa_in_net(nb
->ip
, addr
->prefix
, addr
->pxlen
))
591 if (!ipa_has_link_scope(nb
->ip
))
592 log(L_WARN
"In OSPFv3, configured neighbor address (%I) should be link-local", nb
->ip
);
595 add_nbma_node(ifa
, nb
, 0);
598 ifa
->state
= OSPF_IS_DOWN
;
599 add_tail(&oa
->po
->iface_list
, NODE ifa
);
601 if (ifa
->type
== OSPF_IT_VLINK
)
603 ifa
->voa
= ospf_find_area(oa
->po
, ip
->voa
);
606 ifa
->hello_timer
= tm_new_set(ifa
->pool
, hello_timer_hook
, ifa
, 0, ifa
->helloint
);
608 return; /* Don't lock, don't add sockets */
612 * In some cases we allow more ospf_ifaces on one physical iface.
613 * In OSPFv2, if they use different IP address prefix.
614 * In OSPFv3, if they use different instance_id.
615 * Therefore, we store such info to lock->addr field.
618 lock
= olock_new(pool
);
620 lock
->addr
= ifa
->addr
->prefix
;
622 lock
->addr
= _MI(0,0,0,ifa
->instance_id
);
624 lock
->type
= OBJLOCK_IP
;
625 lock
->port
= OSPF_PROTO
;
628 lock
->hook
= ospf_iface_add
;
634 ospf_iface_change_timer(timer
*tm
, unsigned val
)
646 ospf_iface_reconfigure(struct ospf_iface
*ifa
, struct ospf_iface_patt
*new)
648 struct proto
*p
= &ifa
->oa
->po
->proto
;
649 struct nbma_node
*nb
, *nbx
;
650 char *ifname
= (ifa
->type
!= OSPF_IT_VLINK
) ? ifa
->iface
->name
: "vlink";
652 /* Type could be changed in ospf_iface_new(),
653 but if config values are same then also results are same */
654 int old_type
= ospf_iface_classify(ifa
->cf
->type
, ifa
->addr
);
655 int new_type
= ospf_iface_classify(new->type
, ifa
->addr
);
656 if (old_type
!= new_type
)
659 int new_stub
= ospf_iface_stubby(new, ifa
->addr
);
660 if (ifa
->stub
!= new_stub
)
663 /* Change of these options would require to reset the iface socket */
664 if ((new->real_bcast
!= ifa
->cf
->real_bcast
) ||
665 (new->tx_tos
!= ifa
->cf
->tx_tos
) ||
666 (new->tx_priority
!= ifa
->cf
->tx_priority
))
674 if (ifa
->helloint
!= new->helloint
)
676 OSPF_TRACE(D_EVENTS
, "Changing hello interval on interface %s from %d to %d",
677 ifname
, ifa
->helloint
, new->helloint
);
679 ifa
->helloint
= new->helloint
;
680 ospf_iface_change_timer(ifa
->hello_timer
, ifa
->helloint
);
684 if (ifa
->rxmtint
!= new->rxmtint
)
686 OSPF_TRACE(D_EVENTS
, "Changing retransmit interval on interface %s from %d to %d",
687 ifname
, ifa
->rxmtint
, new->rxmtint
);
689 ifa
->rxmtint
= new->rxmtint
;
693 if (ifa
->pollint
!= new->pollint
)
695 OSPF_TRACE(D_EVENTS
, "Changing poll interval on interface %s from %d to %d",
696 ifname
, ifa
->pollint
, new->pollint
);
698 ifa
->pollint
= new->pollint
;
699 ospf_iface_change_timer(ifa
->poll_timer
, ifa
->pollint
);
703 if (ifa
->waitint
!= new->waitint
)
705 OSPF_TRACE(D_EVENTS
, "Changing wait interval on interface %s from %d to %d",
706 ifname
, ifa
->waitint
, new->waitint
);
708 ifa
->waitint
= new->waitint
;
709 if (ifa
->wait_timer
&& ifa
->wait_timer
->expires
)
710 tm_start(ifa
->wait_timer
, ifa
->waitint
);
714 if (ifa
->deadint
!= new->deadint
)
716 OSPF_TRACE(D_EVENTS
, "Changing dead interval on interface %s from %d to %d",
717 ifname
, ifa
->deadint
, new->deadint
);
718 ifa
->deadint
= new->deadint
;
722 if (ifa
->inftransdelay
!= new->inftransdelay
)
724 OSPF_TRACE(D_EVENTS
, "Changing transmit delay on interface %s from %d to %d",
725 ifname
, ifa
->inftransdelay
, new->inftransdelay
);
726 ifa
->inftransdelay
= new->inftransdelay
;
731 if (ifa
->autype
!= new->autype
)
733 OSPF_TRACE(D_EVENTS
, "Changing authentication type on interface %s", ifname
);
734 ifa
->autype
= new->autype
;
737 /* Update passwords */
738 ifa
->passwords
= new->passwords
;
741 /* Remaining options are just for proper interfaces */
742 if (ifa
->type
== OSPF_IT_VLINK
)
747 if (ifa
->cost
!= new->cost
)
749 OSPF_TRACE(D_EVENTS
, "Changing cost on interface %s from %d to %d",
750 ifname
, ifa
->cost
, new->cost
);
752 ifa
->cost
= new->cost
;
756 if (ifa
->priority
!= new->priority
)
758 OSPF_TRACE(D_EVENTS
, "Changing priority on interface %s from %d to %d",
759 ifname
, ifa
->priority
, new->priority
);
760 ifa
->priority
= new->priority
;
764 if (ifa
->strictnbma
!= new->strictnbma
)
766 OSPF_TRACE(D_EVENTS
, "Changing NBMA strictness on interface %s", ifname
);
767 ifa
->strictnbma
= new->strictnbma
;
770 /* NBMA LIST - remove or update old */
771 WALK_LIST_DELSAFE(nb
, nbx
, ifa
->nbma_list
)
773 struct nbma_node
*nb2
= find_nbma_node_in(&new->nbma_list
, nb
->ip
);
776 if (nb
->eligible
!= nb2
->eligible
)
778 OSPF_TRACE(D_EVENTS
, "Changing eligibility of neighbor %I on interface %s",
780 nb
->eligible
= nb2
->eligible
;
785 OSPF_TRACE(D_EVENTS
, "Removing NBMA neighbor %I on interface %s",
792 /* NBMA LIST - add new */
793 WALK_LIST(nb
, new->nbma_list
)
795 /* See related note in ospf_iface_new() */
797 if (!ipa_in_net(nb
->ip
, ifa
->addr
->prefix
, ifa
->addr
->pxlen
))
800 if (!ipa_has_link_scope(nb
->ip
))
801 log(L_WARN
"In OSPFv3, configured neighbor address (%I) should be link-local", nb
->ip
);
804 if (! find_nbma_node(ifa
, nb
->ip
))
806 OSPF_TRACE(D_EVENTS
, "Adding NBMA neighbor %I on interface %s",
808 add_nbma_node(ifa
, nb
, !!find_neigh_by_ip(ifa
, nb
->ip
));
813 if (ifa
->rxbuf
!= new->rxbuf
)
815 OSPF_TRACE(D_EVENTS
, "Changing rxbuf interface %s from %d to %d",
816 ifname
, ifa
->rxbuf
, new->rxbuf
);
817 ifa
->rxbuf
= new->rxbuf
;
818 ospf_iface_change_mtu(ifa
->oa
->po
, ifa
);
822 if (ifa
->check_link
!= new->check_link
)
824 OSPF_TRACE(D_EVENTS
, "%s link check on interface %s",
825 new->check_link
? "Enabling" : "Disabling", ifname
);
826 ifa
->check_link
= new->check_link
;
828 if (!(ifa
->iface
->flags
& IF_LINK_UP
))
829 ospf_iface_sm(ifa
, ifa
->check_link
? ISM_LOOP
: ISM_UNLOOP
);
833 if (ifa
->ecmp_weight
!= new->ecmp_weight
)
835 OSPF_TRACE(D_EVENTS
, "Changing ECMP weight of interface %s from %d to %d",
836 ifname
, (int)ifa
->ecmp_weight
+ 1, (int)new->ecmp_weight
+ 1);
837 ifa
->ecmp_weight
= new->ecmp_weight
;
840 /* instance_id is not updated - it is part of key */
848 static inline struct ospf_iface_patt
*
849 ospf_iface_patt_find(struct ospf_area_config
*ac
, struct ifa
*a
)
851 return (struct ospf_iface_patt
*) iface_patt_find(&ac
->patt_list
, a
->iface
, a
);
855 ospf_ifa_notify(struct proto
*p
, unsigned flags
, struct ifa
*a
)
857 struct proto_ospf
*po
= (struct proto_ospf
*) p
;
859 if (a
->flags
& IA_SECONDARY
)
862 if (a
->scope
<= SCOPE_LINK
)
865 /* In OSPFv2, we create OSPF iface for each address. */
866 if (flags
& IF_CHANGE_UP
)
869 struct ospf_area
*oa
;
870 WALK_LIST(oa
, po
->area_list
)
872 struct ospf_iface_patt
*ip
;
873 if (ip
= ospf_iface_patt_find(oa
->ac
, a
))
876 ospf_iface_new(oa
, a
, ip
);
882 log(L_WARN
"%s: Interface %s (IP %I) matches for multiple areas", p
->name
, a
->iface
->name
, a
->ip
);
885 if (flags
& IF_CHANGE_DOWN
)
887 struct ospf_iface
*ifa
, *ifx
;
888 WALK_LIST_DELSAFE(ifa
, ifx
, po
->iface_list
)
890 if ((ifa
->type
!= OSPF_IT_VLINK
) && (ifa
->addr
== a
))
891 ospf_iface_remove(ifa
);
892 /* See a note in ospf_iface_notify() */
897 static struct ospf_iface
*
898 ospf_iface_find_by_key(struct ospf_area
*oa
, struct ifa
*a
)
900 struct ospf_iface
*ifa
;
901 WALK_LIST(ifa
, oa
->po
->iface_list
)
902 if ((ifa
->addr
== a
) && (ifa
->oa
== oa
) && (ifa
->type
!= OSPF_IT_VLINK
))
909 ospf_ifaces_reconfigure(struct ospf_area
*oa
, struct ospf_area_config
*nac
)
911 struct ospf_iface_patt
*ip
;
915 WALK_LIST(iface
, iface_list
)
917 if (! (iface
->flags
& IF_UP
))
920 WALK_LIST(a
, iface
->addrs
)
922 if (a
->flags
& IA_SECONDARY
)
925 if (a
->scope
<= SCOPE_LINK
)
928 if (ip
= ospf_iface_patt_find(oa
->ac
, a
))
930 /* Main inner loop */
931 struct ospf_iface
*ifa
= ospf_iface_find_by_key(oa
, a
);
934 if (ospf_iface_reconfigure(ifa
, ip
))
938 ospf_iface_shutdown(ifa
);
939 ospf_iface_remove(ifa
);
942 ospf_iface_new(oa
, a
, ip
);
951 struct ospf_iface_patt
*
952 ospf_iface_patt_find(struct ospf_area_config
*ac
, struct iface
*iface
, int iid
)
954 struct ospf_iface_patt
*pt
, *res
= NULL
;
956 WALK_LIST(pt
, ac
->patt_list
)
957 if ((pt
->instance_id
>= iid
) && (iface_patt_match(&pt
->i
, iface
, NULL
)) &&
958 (!res
|| (pt
->instance_id
< res
->instance_id
)))
965 ospf_ifa_notify(struct proto
*p
, unsigned flags
, struct ifa
*a
)
967 struct proto_ospf
*po
= (struct proto_ospf
*) p
;
969 if (a
->flags
& IA_SECONDARY
)
972 if (a
->scope
< SCOPE_LINK
)
975 /* In OSPFv3, we create OSPF iface for link-local address,
976 other addresses are used for link-LSA. */
977 if (a
->scope
== SCOPE_LINK
)
979 if (flags
& IF_CHANGE_UP
)
982 struct ospf_area
*oa
;
984 WALK_LIST(oa
, po
->area_list
)
988 struct ospf_iface_patt
*ip
;
989 while (ip
= ospf_iface_patt_find(oa
->ac
, a
->iface
, iid
))
991 ospf_iface_new(oa
, a
, ip
);
992 if (ip
->instance_id
== 0)
994 iid
= ip
->instance_id
+ 1;
999 log(L_WARN
"%s: Interface %s matches for multiple areas",
1000 p
->name
, a
->iface
->name
);
1003 if (flags
& IF_CHANGE_DOWN
)
1005 struct ospf_iface
*ifa
, *ifx
;
1006 WALK_LIST_DELSAFE(ifa
, ifx
, po
->iface_list
)
1008 if ((ifa
->type
!= OSPF_IT_VLINK
) && (ifa
->addr
== a
))
1009 ospf_iface_remove(ifa
);
1010 /* See a note in ospf_iface_notify() */
1016 struct ospf_iface
*ifa
;
1017 WALK_LIST(ifa
, po
->iface_list
)
1019 if (ifa
->iface
== a
->iface
)
1021 schedule_rt_lsa(ifa
->oa
);
1022 /* Event 5 from RFC5340 4.4.3. */
1023 schedule_link_lsa(ifa
);
1030 static struct ospf_iface
*
1031 ospf_iface_find_by_key(struct ospf_area
*oa
, struct ifa
*a
, int iid
)
1033 struct ospf_iface
*ifa
;
1034 WALK_LIST(ifa
, oa
->po
->iface_list
)
1035 if ((ifa
->addr
== a
) && (ifa
->oa
== oa
) && (ifa
->instance_id
== iid
) && (ifa
->type
!= OSPF_IT_VLINK
))
1042 ospf_ifaces_reconfigure(struct ospf_area
*oa
, struct ospf_area_config
*nac
)
1044 struct ospf_iface_patt
*ip
;
1045 struct iface
*iface
;
1048 WALK_LIST(iface
, iface_list
)
1050 if (! (iface
->flags
& IF_UP
))
1053 WALK_LIST(a
, iface
->addrs
)
1055 if (a
->flags
& IA_SECONDARY
)
1058 if (a
->scope
!= SCOPE_LINK
)
1062 while (ip
= ospf_iface_patt_find(nac
, iface
, iid
))
1064 iid
= ip
->instance_id
+ 1;
1066 /* Main inner loop */
1067 struct ospf_iface
*ifa
= ospf_iface_find_by_key(oa
, a
, ip
->instance_id
);
1070 if (ospf_iface_reconfigure(ifa
, ip
))
1074 ospf_iface_shutdown(ifa
);
1075 ospf_iface_remove(ifa
);
1078 ospf_iface_new(oa
, a
, ip
);
1087 ospf_iface_change_mtu(struct proto_ospf
*po
, struct ospf_iface
*ifa
)
1089 struct proto
*p
= &po
->proto
;
1090 struct ospf_packet
*op
;
1091 struct ospf_neighbor
*n
;
1092 OSPF_TRACE(D_EVENTS
, "Changing MTU on interface %s", ifa
->iface
->name
);
1096 ifa
->sk
->rbsize
= rxbufsize(ifa
);
1097 ifa
->sk
->tbsize
= rxbufsize(ifa
);
1098 sk_reallocate(ifa
->sk
);
1101 WALK_LIST(n
, ifa
->neigh_list
)
1103 op
= (struct ospf_packet
*) n
->ldbdes
;
1104 n
->ldbdes
= mb_allocz(n
->pool
, ifa
->iface
->mtu
);
1106 if (ntohs(op
->length
) <= ifa
->iface
->mtu
) /* If the packet in old buffer is bigger, let it filled by zeros */
1107 memcpy(n
->ldbdes
, op
, ifa
->iface
->mtu
); /* If the packet is old is same or smaller, copy it */
1114 ospf_iface_notify(struct proto_ospf
*po
, unsigned flags
, struct ospf_iface
*ifa
)
1116 if (flags
& IF_CHANGE_DOWN
)
1118 ospf_iface_remove(ifa
);
1122 if (flags
& IF_CHANGE_LINK
)
1123 ospf_iface_sm(ifa
, (ifa
->iface
->flags
& IF_LINK_UP
) ? ISM_UNLOOP
: ISM_LOOP
);
1125 if (flags
& IF_CHANGE_MTU
)
1126 ospf_iface_change_mtu(po
, ifa
);
1130 ospf_if_notify(struct proto
*p
, unsigned flags
, struct iface
*iface
)
1132 struct proto_ospf
*po
= (struct proto_ospf
*) p
;
1135 if (iface->flags & IF_IGNORE)
1139 /* Going up means that there are no such ifaces yet */
1140 if (flags
& IF_CHANGE_UP
)
1143 struct ospf_iface
*ifa
, *ifx
;
1144 WALK_LIST_DELSAFE(ifa
, ifx
, po
->iface_list
)
1145 if ((ifa
->type
!= OSPF_IT_VLINK
) && (ifa
->iface
== iface
))
1146 ospf_iface_notify(po
, flags
, ifa
);
1148 /* We use here that even shutting down iface also shuts down
1149 the vlinks, but vlinks are not freed and stays in the
1150 iface_list even when down */
1154 ospf_iface_info(struct ospf_iface
*ifa
)
1158 if (ifa
->strictnbma
&&
1159 ((ifa
->type
== OSPF_IT_NBMA
) || (ifa
->type
== OSPF_IT_PTMP
)))
1162 if (ifa
->cf
->real_bcast
&&
1163 ((ifa
->type
== OSPF_IT_BCAST
) || (ifa
->type
== OSPF_IT_PTP
)))
1166 if (ifa
->type
== OSPF_IT_VLINK
)
1168 cli_msg(-1015, "Virtual link to %R:", ifa
->vid
);
1169 cli_msg(-1015, "\tPeer IP: %I", ifa
->vip
);
1170 cli_msg(-1015, "\tTransit area: %R (%u)", ifa
->voa
->areaid
,
1172 cli_msg(-1015, "\tInterface: \"%s\"",
1173 (ifa
->iface
? ifa
->iface
->name
: "(none)"));
1178 if (ifa
->addr
->flags
& IA_PEER
)
1179 cli_msg(-1015, "Interface %s (peer %I)", ifa
->iface
->name
, ifa
->addr
->opposite
);
1181 cli_msg(-1015, "Interface %s (%I/%d)", ifa
->iface
->name
, ifa
->addr
->prefix
, ifa
->addr
->pxlen
);
1183 cli_msg(-1015, "Interface %s (IID %d)", ifa
->iface
->name
, ifa
->instance_id
);
1185 cli_msg(-1015, "\tType: %s%s", ospf_it
[ifa
->type
], more
);
1186 cli_msg(-1015, "\tArea: %R (%u)", ifa
->oa
->areaid
, ifa
->oa
->areaid
);
1188 cli_msg(-1015, "\tState: %s%s", ospf_is
[ifa
->state
], ifa
->stub
? " (stub)" : "");
1189 cli_msg(-1015, "\tPriority: %u", ifa
->priority
);
1190 cli_msg(-1015, "\tCost: %u", ifa
->cost
);
1191 if (ifa
->oa
->po
->ecmp
)
1192 cli_msg(-1015, "\tECMP weight: %d", ((int) ifa
->ecmp_weight
) + 1);
1193 cli_msg(-1015, "\tHello timer: %u", ifa
->helloint
);
1195 if (ifa
->type
== OSPF_IT_NBMA
)
1197 cli_msg(-1015, "\tPoll timer: %u", ifa
->pollint
);
1199 cli_msg(-1015, "\tWait timer: %u", ifa
->waitint
);
1200 cli_msg(-1015, "\tDead timer: %u", ifa
->deadint
);
1201 cli_msg(-1015, "\tRetransmit timer: %u", ifa
->rxmtint
);
1202 if ((ifa
->type
== OSPF_IT_BCAST
) || (ifa
->type
== OSPF_IT_NBMA
))
1204 cli_msg(-1015, "\tDesigned router (ID): %R", ifa
->drid
);
1205 cli_msg(-1015, "\tDesigned router (IP): %I", ifa
->drip
);
1206 cli_msg(-1015, "\tBackup designed router (ID): %R", ifa
->bdrid
);
1207 cli_msg(-1015, "\tBackup designed router (IP): %I", ifa
->bdrip
);