]>
git.ipfire.org Git - thirdparty/bird.git/blob - proto/rip/rip.c
eb2323160fbbf009b070662982661d5854534fd1
2 * BIRD -- Routing Information Protocol (RIP)
4 * (c) 1998--1999 Pavel Machek <pavel@ucw.cz>
5 * (c) 2004--2013 Ondrej Filip <feela@network.cz>
6 * (c) 2009--2015 Ondrej Zajicek <santiago@crfreenet.org>
7 * (c) 2009--2015 CZ.NIC z.s.p.o.
9 * Can be freely distributed and used under the terms of the GNU GPL.
13 * DOC: Routing Information Protocol (RIP)
15 * The RIP protocol is implemented in two files: |rip.c| containing the protocol
16 * logic, route management and the protocol glue with BIRD core, and |packets.c|
17 * handling RIP packet processing, RX, TX and protocol sockets.
19 * Each instance of RIP is described by a structure &rip_proto, which contains
20 * an internal RIP routing table, a list of protocol interfaces and the main
21 * timer responsible for RIP routing table cleanup.
23 * RIP internal routing table contains incoming and outgoing routes. For each
24 * network (represented by structure &rip_entry) there is one outgoing route
25 * stored directly in &rip_entry and an one-way linked list of incoming routes
26 * (structures &rip_rte). The list contains incoming routes from different RIP
27 * neighbors, but only routes with the lowest metric are stored (i.e., all
28 * stored incoming routes have the same metric).
30 * Note that RIP itself does not select outgoing route, that is done by the core
31 * routing table. When a new incoming route is received, it is propagated to the
32 * RIP table by rip_update_rte() and possibly stored in the list of incoming
33 * routes. Then the change may be propagated to the core by rip_announce_rte().
34 * The core selects the best route and propagate it to RIP by rip_rt_notify(),
35 * which updates outgoing route part of &rip_entry and possibly triggers route
36 * propagation by rip_trigger_update().
38 * RIP interfaces are represented by structures &rip_iface. A RIP interface
39 * contains a per-interface socket, a list of associated neighbors, interface
40 * configuration, and state information related to scheduled interface events
41 * and running update sessions. RIP interfaces are added and removed based on
42 * core interface notifications.
44 * There are two RIP interface events - regular updates and triggered updates.
45 * Both are managed from the RIP interface timer (rip_iface_timer()). Regular
46 * updates are called at fixed interval and propagate the whole routing table,
47 * while triggered updates are scheduled by rip_trigger_update() due to some
48 * routing table change and propagate only the routes modified since the time
49 * they were scheduled. There are also unicast-destined requested updates, but
50 * these are sent directly as a reaction to received RIP request message. The
51 * update session is started by rip_send_table(). There may be at most one
52 * active update session per interface, as the associated state (including the
53 * fib iterator) is stored directly in &rip_iface structure.
55 * RIP neighbors are represented by structures &rip_neighbor. Compared to
56 * neighbor handling in other routing protocols, RIP does not have explicit
57 * neighbor discovery and adjacency maintenance, which makes the &rip_neighbor
58 * related code a bit peculiar. RIP neighbors are interlinked with core neighbor
59 * structures (&neighbor) and use core neighbor notifications to ensure that RIP
60 * neighbors are timely removed. RIP neighbors are added based on received route
61 * notifications and removed based on core neighbor and RIP interface events.
63 * RIP neighbors are linked by RIP routes and use counter to track the number of
64 * associated routes, but when these RIP routes timeout, associated RIP neighbor
65 * is still alive (with zero counter). When RIP neighbor is removed but still
66 * has some associated routes, it is not freed, just changed to detached state
67 * (core neighbors and RIP ifaces are unlinked), then during the main timer
68 * cleanup phase the associated routes are removed and the &rip_neighbor
69 * structure is finally freed.
71 * Supported standards:
75 * RFC 2091 - Triggered RIP for demand circuits
76 * RFC 4822 - RIP cryptographic authentication
83 static inline void rip_lock_neighbor(struct rip_neighbor
*n
);
84 static inline void rip_unlock_neighbor(struct rip_neighbor
*n
);
85 static inline int rip_iface_link_up(struct rip_iface
*ifa
);
86 static inline void rip_kick_timer(struct rip_proto
*p
);
87 static inline void rip_iface_kick_timer(struct rip_iface
*ifa
);
88 static void rip_iface_timer(timer
*timer
);
89 static void rip_trigger_update(struct rip_proto
*p
);
96 static struct rip_rte
*
97 rip_add_rte(struct rip_proto
*p
, struct rip_rte
**rp
, struct rip_rte
*src
)
99 struct rip_rte
*rt
= sl_alloc(p
->rte_slab
);
101 memcpy(rt
, src
, sizeof(struct rip_rte
));
105 rip_lock_neighbor(rt
->from
);
111 rip_remove_rte(struct rip_proto
*p UNUSED
, struct rip_rte
**rp
)
113 struct rip_rte
*rt
= *rp
;
115 rip_unlock_neighbor(rt
->from
);
121 static inline int rip_same_rte(struct rip_rte
*a
, struct rip_rte
*b
)
122 { return a
->metric
== b
->metric
&& a
->tag
== b
->tag
&& ipa_equal(a
->next_hop
, b
->next_hop
); }
124 static inline int rip_valid_rte(struct rip_rte
*rt
)
125 { return rt
->from
->ifa
!= NULL
; }
128 * rip_announce_rte - announce route from RIP routing table to the core
130 * @en: related network
132 * The function takes a list of incoming routes from @en, prepare appropriate
133 * &rte for the core and propagate it by rte_update().
136 rip_announce_rte(struct rip_proto
*p
, struct rip_entry
*en
)
138 struct rip_rte
*rt
= en
->routes
;
140 /* Find first valid rte */
141 while (rt
&& !rip_valid_rte(rt
))
148 .pref
= p
->p
.main_channel
->preference
,
150 .scope
= SCOPE_UNIVERSE
,
154 u8 rt_metric
= rt
->metric
;
155 u16 rt_tag
= rt
->tag
;
160 struct nexthop
*nhs
= NULL
;
163 for (rt
= en
->routes
; rt
&& (num
< p
->ecmp
); rt
= rt
->next
)
165 if (!rip_valid_rte(rt
))
168 struct nexthop
*nh
= allocz(sizeof(struct nexthop
));
170 nh
->gw
= rt
->next_hop
;
171 nh
->iface
= rt
->from
->ifa
->iface
;
172 nh
->weight
= rt
->from
->ifa
->cf
->ecmp_weight
;
174 nexthop_insert(&nhs
, nh
);
177 if (rt
->tag
!= rt_tag
)
186 a0
.from
= rt
->from
->nbr
->addr
;
187 a0
.nh
.gw
= rt
->next_hop
;
188 a0
.nh
.iface
= rt
->from
->ifa
->iface
;
191 a0
.eattrs
= alloca(sizeof(ea_list
) + 3*sizeof(eattr
));
192 memset(a0
.eattrs
, 0, sizeof(ea_list
)); /* Zero-ing only the ea_list header */
193 a0
.eattrs
->count
= 3;
194 a0
.eattrs
->attrs
[0] = (eattr
) {
196 .type
= EAF_TYPE_INT
,
199 a0
.eattrs
->attrs
[1] = (eattr
) {
201 .type
= EAF_TYPE_INT
,
204 a0
.eattrs
->attrs
[2] = (eattr
) {
206 .type
= EAF_TYPE_PTR
,
207 .u
.data
= (uintptr_t) a0
.nh
.iface
,
210 rta
*a
= rta_lookup(&a0
);
211 rte
*e
= rte_get_temp(a
, p
->p
.main_source
);
213 rte_update(&p
->p
, en
->n
.addr
, e
);
218 rte_update(&p
->p
, en
->n
.addr
, NULL
);
223 * rip_update_rte - enter a route update to RIP routing table
225 * @addr: network address
226 * @new: a &rip_rte representing the new route
228 * The function is called by the RIP packet processing code whenever it receives
229 * a reachable route. The appropriate routing table entry is found and the list
230 * of incoming routes is updated. Eventually, the change is also propagated to
231 * the core by rip_announce_rte(). Note that for unreachable routes,
232 * rip_withdraw_rte() should be called instead of rip_update_rte().
235 rip_update_rte(struct rip_proto
*p
, net_addr
*n
, struct rip_rte
*new)
237 struct rip_entry
*en
= fib_get(&p
->rtable
, n
);
238 struct rip_rte
*rt
, **rp
;
241 /* If the new route is better, remove all current routes */
242 if (en
->routes
&& new->metric
< en
->routes
->metric
)
244 rip_remove_rte(p
, &en
->routes
);
246 /* Find the old route (also set rp for later) */
247 for (rp
= &en
->routes
; rt
= *rp
; rp
= &rt
->next
)
248 if (rt
->from
== new->from
)
250 if (rip_same_rte(rt
, new))
252 rt
->expires
= new->expires
;
256 /* Remove the old route */
257 rip_remove_rte(p
, rp
);
262 /* If the new route is optimal, add it to the list */
263 if (!en
->routes
|| new->metric
== en
->routes
->metric
)
265 rt
= rip_add_rte(p
, rp
, new);
269 /* Announce change if on relevant position (the first or any for ECMP) */
270 if (changed
&& (rp
== &en
->routes
|| p
->ecmp
))
271 rip_announce_rte(p
, en
);
275 * rip_withdraw_rte - enter a route withdraw to RIP routing table
277 * @addr: network address
278 * @from: a &rip_neighbor propagating the withdraw
280 * The function is called by the RIP packet processing code whenever it receives
281 * an unreachable route. The incoming route for given network from nbr @from is
282 * removed. Eventually, the change is also propagated by rip_announce_rte().
285 rip_withdraw_rte(struct rip_proto
*p
, net_addr
*n
, struct rip_neighbor
*from
)
287 struct rip_entry
*en
= fib_find(&p
->rtable
, n
);
288 struct rip_rte
*rt
, **rp
;
293 /* Find the old route */
294 for (rp
= &en
->routes
; rt
= *rp
; rp
= &rt
->next
)
295 if (rt
->from
== from
)
301 /* Remove the old route */
302 rip_remove_rte(p
, rp
);
304 /* Announce change if on relevant position */
305 if (rp
== &en
->routes
|| p
->ecmp
)
306 rip_announce_rte(p
, en
);
310 * rip_rt_notify - core tells us about new route, so store
311 * it into our data structures.
314 rip_rt_notify(struct proto
*P
, struct channel
*ch UNUSED
, struct network
*net
, struct rte
*new,
315 struct rte
*old UNUSED
)
317 struct rip_proto
*p
= (struct rip_proto
*) P
;
318 struct rip_entry
*en
;
324 u32 rt_tag
= ea_get_int(new->attrs
->eattrs
, EA_RIP_TAG
, 0);
325 u32 rt_metric
= ea_get_int(new->attrs
->eattrs
, EA_RIP_METRIC
, 1);
326 struct iface
*rt_from
= (struct iface
*) ea_get_int(new->attrs
->eattrs
, EA_RIP_FROM
, 0);
328 if (rt_metric
> p
->infinity
)
330 log(L_WARN
"%s: Invalid rip_metric value %u for route %N",
331 p
->p
.name
, rt_metric
, net
->n
.addr
);
332 rt_metric
= p
->infinity
;
337 log(L_WARN
"%s: Invalid rip_tag value %u for route %N",
338 p
->p
.name
, rt_tag
, net
->n
.addr
);
339 rt_metric
= p
->infinity
;
344 * Note that we accept exported routes with infinity metric (this could
345 * happen if rip_metric is modified in filters). Such entry has infinity
346 * metric but is RIP_ENTRY_VALID and therefore is not subject to garbage
350 en
= fib_get(&p
->rtable
, net
->n
.addr
);
352 old_metric
= en
->valid
? en
->metric
: -1;
354 en
->valid
= RIP_ENTRY_VALID
;
355 en
->metric
= rt_metric
;
357 en
->from
= (new->src
->proto
== P
) ? rt_from
: NULL
;
358 en
->iface
= new->attrs
->nh
.iface
;
359 en
->next_hop
= new->attrs
->nh
.gw
;
364 en
= fib_find(&p
->rtable
, net
->n
.addr
);
366 if (!en
|| en
->valid
!= RIP_ENTRY_VALID
)
369 old_metric
= en
->metric
;
371 en
->valid
= RIP_ENTRY_STALE
;
372 en
->metric
= p
->infinity
;
376 en
->next_hop
= IPA_NONE
;
379 /* Activate triggered updates */
380 if (en
->metric
!= old_metric
)
382 en
->changed
= current_time();
383 rip_trigger_update(p
);
388 rip_flush_table(struct rip_proto
*p
, struct rip_neighbor
*n
)
390 btime expires
= current_time() + n
->ifa
->cf
->timeout_time
;
392 FIB_WALK(&p
->rtable
, struct rip_entry
, en
)
394 for (struct rip_rte
*e
= en
->routes
; e
; e
= e
->next
)
395 if ((e
->from
== n
) && (e
->expires
== TIME_INFINITY
))
396 e
->expires
= expires
;
406 struct rip_neighbor
*
407 rip_get_neighbor(struct rip_proto
*p
, ip_addr
*a
, struct rip_iface
*ifa
)
409 neighbor
*nbr
= neigh_find(&p
->p
, *a
, ifa
->iface
, 0);
411 if (!nbr
|| (nbr
->scope
== SCOPE_HOST
) || !rip_iface_link_up(ifa
))
417 TRACE(D_EVENTS
, "New neighbor %I on %s", *a
, ifa
->iface
->name
);
419 struct rip_neighbor
*n
= mb_allocz(p
->p
.pool
, sizeof(struct rip_neighbor
));
425 add_tail(&ifa
->neigh_list
, NODE n
);
431 rip_remove_neighbor(struct rip_proto
*p
, struct rip_neighbor
*n
)
433 neighbor
*nbr
= n
->nbr
;
435 TRACE(D_EVENTS
, "Removing neighbor %I on %s", nbr
->addr
, nbr
->ifreq
->name
);
450 /* Related routes are removed in rip_timer() */
455 rip_lock_neighbor(struct rip_neighbor
*n
)
461 rip_unlock_neighbor(struct rip_neighbor
*n
)
465 if (!n
->nbr
&& !n
->uc
)
470 rip_neigh_notify(struct neighbor
*nbr
)
472 struct rip_proto
*p
= (struct rip_proto
*) nbr
->proto
;
473 struct rip_neighbor
*n
= nbr
->data
;
479 * We assume that rip_neigh_notify() is called before rip_if_notify() for
480 * IF_CHANGE_DOWN and therefore n->ifa is still valid. We have no such
481 * ordering assumption for IF_CHANGE_LINK, so we test link state of the
482 * underlying iface instead of just rip_iface state.
484 if ((nbr
->scope
<= 0) || !rip_iface_link_up(n
->ifa
))
485 rip_remove_neighbor(p
, n
);
489 rip_bfd_notify(struct bfd_request
*req
)
491 struct rip_neighbor
*n
= req
->data
;
492 struct rip_proto
*p
= n
->ifa
->rip
;
496 TRACE(D_EVENTS
, "BFD session down for nbr %I on %s",
497 n
->nbr
->addr
, n
->ifa
->iface
->name
);
498 rip_remove_neighbor(p
, n
);
503 rip_update_bfd(struct rip_proto
*p
, struct rip_neighbor
*n
)
505 int use_bfd
= n
->ifa
->cf
->bfd
&& n
->last_seen
;
507 if (use_bfd
&& !n
->bfd_req
)
510 * For RIPv2, use the same address as rip_open_socket(). For RIPng, neighbor
511 * should contain an address from the same prefix, thus also link-local. It
512 * may cause problems if two link-local addresses are assigned to one iface.
514 ip_addr saddr
= rip_is_v2(p
) ? n
->ifa
->sk
->saddr
: n
->nbr
->ifa
->ip
;
515 n
->bfd_req
= bfd_request_session(p
->p
.pool
, n
->nbr
->addr
, saddr
,
516 n
->nbr
->iface
, p
->p
.vrf
,
517 rip_bfd_notify
, n
, NULL
);
520 if (!use_bfd
&& n
->bfd_req
)
533 rip_iface_start(struct rip_iface
*ifa
)
535 struct rip_proto
*p
= ifa
->rip
;
537 TRACE(D_EVENTS
, "Starting interface %s", ifa
->iface
->name
);
539 if (! ifa
->cf
->demand_circuit
)
541 ifa
->next_regular
= current_time() + (random() % ifa
->cf
->update_time
) + 100 MS
;
542 tm_set(ifa
->timer
, ifa
->next_regular
);
546 ifa
->next_regular
= TIME_INFINITY
;
551 if (ifa
->cf
->passive
)
554 rip_send_request(p
, ifa
);
555 rip_send_table(p
, ifa
, ifa
->addr
, 0);
559 rip_iface_stop(struct rip_iface
*ifa
)
561 struct rip_proto
*p
= ifa
->rip
;
562 struct rip_neighbor
*n
;
564 TRACE(D_EVENTS
, "Stopping interface %s", ifa
->iface
->name
);
566 rip_reset_tx_session(p
, ifa
);
568 ifa
->next_regular
= 0;
569 ifa
->next_triggered
= 0;
570 ifa
->want_triggered
= 0;
576 ifa
->req_pending
= 0;
578 if (ifa
->cf
->demand_circuit
&& !ifa
->cf
->passive
)
579 rip_send_flush(p
, ifa
);
581 WALK_LIST_FIRST(n
, ifa
->neigh_list
)
582 rip_remove_neighbor(p
, n
);
585 tm_stop(ifa
->rxmt_timer
);
590 rip_iface_link_up(struct rip_iface
*ifa
)
592 return !ifa
->cf
->check_link
|| (ifa
->iface
->flags
& IF_LINK_UP
);
596 rip_iface_update_state(struct rip_iface
*ifa
)
598 int up
= ifa
->sk
&& rip_iface_link_up(ifa
);
604 rip_iface_start(ifa
);
610 rip_iface_update_buffers(struct rip_iface
*ifa
)
615 uint rbsize
= ifa
->cf
->rx_buffer
?: ifa
->iface
->mtu
;
616 uint tbsize
= ifa
->cf
->tx_length
?: ifa
->iface
->mtu
;
617 rbsize
= MAX(rbsize
, tbsize
);
619 sk_set_rbsize(ifa
->sk
, rbsize
);
620 sk_set_tbsize(ifa
->sk
, tbsize
);
622 uint headers
= (rip_is_v2(ifa
->rip
) ? IP4_HEADER_LENGTH
: IP6_HEADER_LENGTH
) + UDP_HEADER_LENGTH
;
623 ifa
->tx_plen
= tbsize
- headers
;
625 if (ifa
->cf
->auth_type
== RIP_AUTH_CRYPTO
)
626 ifa
->tx_plen
-= RIP_AUTH_TAIL_LENGTH
+ max_mac_length(ifa
->cf
->passwords
);
630 rip_iface_update_bfd(struct rip_iface
*ifa
)
632 struct rip_proto
*p
= ifa
->rip
;
633 struct rip_neighbor
*n
;
635 WALK_LIST(n
, ifa
->neigh_list
)
636 rip_update_bfd(p
, n
);
641 rip_iface_locked(struct object_lock
*lock
)
643 struct rip_iface
*ifa
= lock
->data
;
644 struct rip_proto
*p
= ifa
->rip
;
646 if (!rip_open_socket(ifa
))
648 log(L_ERR
"%s: Cannot open socket for %s", p
->p
.name
, ifa
->iface
->name
);
652 rip_iface_update_buffers(ifa
);
653 rip_iface_update_state(ifa
);
657 static struct rip_iface
*
658 rip_find_iface(struct rip_proto
*p
, struct iface
*what
)
660 struct rip_iface
*ifa
;
662 WALK_LIST(ifa
, p
->iface_list
)
663 if (ifa
->iface
== what
)
670 rip_add_iface(struct rip_proto
*p
, struct iface
*iface
, struct rip_iface_config
*ic
)
672 struct rip_iface
*ifa
;
674 TRACE(D_EVENTS
, "Adding interface %s", iface
->name
);
676 ifa
= mb_allocz(p
->p
.pool
, sizeof(struct rip_iface
));
681 if (ipa_nonzero(ic
->address
))
682 ifa
->addr
= ic
->address
;
683 else if (ic
->mode
== RIP_IM_MULTICAST
)
684 ifa
->addr
= rip_is_v2(p
) ? IP4_RIP_ROUTERS
: IP6_RIP_ROUTERS
;
686 ifa
->addr
= iface
->addr4
->brd
;
688 * The above is just a workaround for BSD as it can't send broadcasts
689 * to 255.255.255.255. BSD systems need the network broadcast address instead.
691 * TODO: move this to sysdep code
694 init_list(&ifa
->neigh_list
);
696 add_tail(&p
->iface_list
, NODE ifa
);
698 ifa
->timer
= tm_new_init(p
->p
.pool
, rip_iface_timer
, ifa
, 0, 0);
699 ifa
->rxmt_timer
= tm_new_init(p
->p
.pool
, rip_rxmt_timeout
, ifa
, 0, 0);
701 struct object_lock
*lock
= olock_new(p
->p
.pool
);
702 lock
->type
= OBJLOCK_UDP
;
703 lock
->port
= ic
->port
;
706 lock
->hook
= rip_iface_locked
;
713 rip_remove_iface(struct rip_proto
*p
, struct rip_iface
*ifa
)
717 TRACE(D_EVENTS
, "Removing interface %s", ifa
->iface
->name
);
729 rip_reconfigure_iface(struct rip_proto
*p
, struct rip_iface
*ifa
, struct rip_iface_config
*new)
731 struct rip_iface_config
*old
= ifa
->cf
;
733 /* Change of these options would require to reset the iface socket */
734 if ((new->mode
!= old
->mode
) ||
735 (new->port
!= old
->port
) ||
736 (new->tx_tos
!= old
->tx_tos
) ||
737 (new->tx_priority
!= old
->tx_priority
) ||
738 (new->ttl_security
!= old
->ttl_security
) ||
739 (new->demand_circuit
!= old
->demand_circuit
))
742 TRACE(D_EVENTS
, "Reconfiguring interface %s", ifa
->iface
->name
);
746 rip_iface_update_buffers(ifa
);
748 if ((! ifa
->cf
->demand_circuit
) &&
749 (ifa
->next_regular
> (current_time() + new->update_time
)))
750 ifa
->next_regular
= current_time() + (random() % new->update_time
) + 100 MS
;
752 if (ifa
->up
&& new->demand_circuit
&& (new->passive
!= old
->passive
))
755 rip_send_flush(p
, ifa
);
758 rip_send_request(p
, ifa
);
759 rip_send_table(p
, ifa
, ifa
->addr
, 0);
763 if (new->check_link
!= old
->check_link
)
764 rip_iface_update_state(ifa
);
766 if (new->bfd
!= old
->bfd
)
767 rip_iface_update_bfd(ifa
);
770 rip_iface_kick_timer(ifa
);
776 rip_reconfigure_ifaces(struct rip_proto
*p
, struct rip_config
*cf
)
780 WALK_LIST(iface
, iface_list
)
782 if (!(iface
->flags
& IF_UP
))
785 /* Ignore ifaces without appropriate address */
786 if (rip_is_v2(p
) ? !iface
->addr4
: !iface
->llv6
)
789 struct rip_iface
*ifa
= rip_find_iface(p
, iface
);
790 struct rip_iface_config
*ic
= (void *) iface_patt_find(&cf
->patt_list
, iface
, NULL
);
794 if (rip_reconfigure_iface(p
, ifa
, ic
))
798 log(L_INFO
"%s: Restarting interface %s", p
->p
.name
, ifa
->iface
->name
);
799 rip_remove_iface(p
, ifa
);
800 rip_add_iface(p
, iface
, ic
);
804 rip_remove_iface(p
, ifa
);
807 rip_add_iface(p
, iface
, ic
);
812 rip_if_notify(struct proto
*P
, unsigned flags
, struct iface
*iface
)
814 struct rip_proto
*p
= (void *) P
;
815 struct rip_config
*cf
= (void *) P
->cf
;
816 struct rip_iface
*ifa
= rip_find_iface(p
, iface
);
818 if (iface
->flags
& IF_IGNORE
)
821 /* Add, remove or restart interface */
822 if (flags
& (IF_CHANGE_UPDOWN
| (rip_is_v2(p
) ? IF_CHANGE_ADDR4
: IF_CHANGE_LLV6
)))
825 rip_remove_iface(p
, ifa
);
827 if (!(iface
->flags
& IF_UP
))
830 /* Ignore ifaces without appropriate address */
831 if (rip_is_v2(p
) ? !iface
->addr4
: !iface
->llv6
)
834 struct rip_iface_config
*ic
= (void *) iface_patt_find(&cf
->patt_list
, iface
, NULL
);
836 rip_add_iface(p
, iface
, ic
);
844 if (flags
& IF_CHANGE_MTU
)
845 rip_iface_update_buffers(ifa
);
847 if (flags
& IF_CHANGE_LINK
)
848 rip_iface_update_state(ifa
);
857 * rip_timer - RIP main timer hook
860 * The RIP main timer is responsible for routing table maintenance. Invalid or
861 * expired routes (&rip_rte) are removed and garbage collection of stale routing
862 * table entries (&rip_entry) is done. Changes are propagated to core tables,
863 * route reload is also done here. Note that garbage collection uses a maximal
864 * GC time, while interfaces maintain an illusion of per-interface GC times in
865 * rip_send_response().
867 * Keeping incoming routes and the selected outgoing route are two independent
868 * functions, therefore after garbage collection some entries now considered
869 * invalid (RIP_ENTRY_DUMMY) still may have non-empty list of incoming routes,
870 * while some valid entries (representing an outgoing route) may have that list
873 * The main timer is not scheduled periodically but it uses the time of the
874 * current next event and the minimal interval of any possible event to compute
875 * the time of the next run.
880 struct rip_proto
*p
= t
->data
;
881 struct rip_config
*cf
= (void *) (p
->p
.cf
);
882 struct rip_iface
*ifa
;
883 struct rip_neighbor
*n
, *nn
;
884 struct fib_iterator fit
;
885 btime now_
= current_time();
886 btime next
= now_
+ MIN(cf
->min_timeout_time
, cf
->max_garbage_time
);
889 TRACE(D_EVENTS
, "Main timer fired");
891 FIB_ITERATE_INIT(&fit
, &p
->rtable
);
894 FIB_ITERATE_START(&p
->rtable
, &fit
, struct rip_entry
, en
)
896 struct rip_rte
*rt
, **rp
;
899 /* Checking received routes for timeout and for dead neighbors */
900 for (rp
= &en
->routes
; rt
= *rp
; /* rp = &rt->next */)
902 if (!rip_valid_rte(rt
) || (rt
->expires
<= now_
))
904 rip_remove_rte(p
, rp
);
909 next
= MIN(next
, rt
->expires
);
913 /* Propagating eventual change */
914 if (changed
|| p
->rt_reload
)
917 * We have to restart the iteration because there may be a cascade of
918 * synchronous events rip_announce_rte() -> nest table change ->
919 * rip_rt_notify() -> p->rtable change, invalidating hidden variables.
922 FIB_ITERATE_PUT_NEXT(&fit
, &p
->rtable
);
923 rip_announce_rte(p
, en
);
927 /* Checking stale entries for garbage collection timeout */
928 if (en
->valid
== RIP_ENTRY_STALE
)
930 expires
= en
->changed
+ cf
->max_garbage_time
;
934 // TRACE(D_EVENTS, "entry is too old: %N", en->n.addr);
938 next
= MIN(next
, expires
);
941 /* Remove empty nodes */
942 if (!en
->valid
&& !en
->routes
)
944 FIB_ITERATE_PUT(&fit
);
945 fib_delete(&p
->rtable
, en
);
953 /* Handling neighbor expiration */
954 WALK_LIST(ifa
, p
->iface_list
)
956 /* No expiration for demand circuit ifaces */
957 if (ifa
->cf
->demand_circuit
)
960 WALK_LIST_DELSAFE(n
, nn
, ifa
->neigh_list
)
963 expires
= n
->last_seen
+ n
->ifa
->cf
->timeout_time
;
966 rip_remove_neighbor(p
, n
);
968 next
= MIN(next
, expires
);
972 tm_start(p
->timer
, MAX(next
- now_
, 100 MS
));
976 rip_kick_timer(struct rip_proto
*p
)
978 if ((p
->timer
->expires
> (current_time() + 100 MS
)))
979 tm_start(p
->timer
, 100 MS
);
983 * rip_iface_timer - RIP interface timer hook
986 * RIP interface timers are responsible for scheduling both regular and
987 * triggered updates. Fixed, delay-independent period is used for regular
988 * updates, while minimal separating interval is enforced for triggered updates.
989 * The function also ensures that a new update is not started when the old one
993 rip_iface_timer(timer
*t
)
995 struct rip_iface
*ifa
= t
->data
;
996 struct rip_proto
*p
= ifa
->rip
;
997 btime now_
= current_time();
998 btime period
= ifa
->cf
->update_time
;
1000 if (ifa
->cf
->passive
)
1003 TRACE(D_EVENTS
, "Interface timer fired for %s", ifa
->iface
->name
);
1007 tm_start(ifa
->timer
, 100 MS
);
1011 if (now_
>= ifa
->next_regular
)
1013 /* Send regular update, set timer for next period (or following one if necessay) */
1014 TRACE(D_EVENTS
, "Sending regular updates for %s", ifa
->iface
->name
);
1015 rip_send_table(p
, ifa
, ifa
->addr
, 0);
1016 ifa
->next_regular
+= period
* (1 + ((now_
- ifa
->next_regular
) / period
));
1017 ifa
->want_triggered
= 0;
1020 else if (ifa
->want_triggered
&& (now_
>= ifa
->next_triggered
))
1022 /* Send triggered update, enforce interval between triggered updates */
1023 TRACE(D_EVENTS
, "Sending triggered updates for %s", ifa
->iface
->name
);
1024 rip_send_table(p
, ifa
, ifa
->addr
, ifa
->want_triggered
);
1025 ifa
->next_triggered
= now_
+ MIN(5 S
, period
/ 2);
1026 ifa
->want_triggered
= 0;
1030 if (ifa
->want_triggered
&& (ifa
->next_triggered
< ifa
->next_regular
))
1031 tm_set(ifa
->timer
, ifa
->next_triggered
);
1032 else if (ifa
->next_regular
!= TIME_INFINITY
)
1033 tm_set(ifa
->timer
, ifa
->next_regular
);
1038 rip_iface_kick_timer(struct rip_iface
*ifa
)
1040 if ((! tm_active(ifa
->timer
)) || (ifa
->timer
->expires
> (current_time() + 100 MS
)))
1041 tm_start(ifa
->timer
, 100 MS
);
1045 rip_trigger_update(struct rip_proto
*p
)
1050 struct rip_iface
*ifa
;
1051 WALK_LIST(ifa
, p
->iface_list
)
1053 /* Interface not active */
1057 /* Already scheduled */
1058 if (ifa
->want_triggered
)
1061 TRACE(D_EVENTS
, "Scheduling triggered updates for %s", ifa
->iface
->name
);
1062 ifa
->want_triggered
= current_time();
1063 rip_iface_kick_timer(ifa
);
1074 rip_reload_routes(struct channel
*C
)
1076 struct rip_proto
*p
= (struct rip_proto
*) C
->proto
;
1081 TRACE(D_EVENTS
, "Scheduling route reload");
1087 rip_rte_better(struct rte
*new, struct rte
*old
)
1089 ASSERT_DIE(new->src
== old
->src
);
1090 struct rip_proto
*p
= (struct rip_proto
*) new->src
->proto
;
1092 u32 new_metric
= ea_get_int(new->attrs
->eattrs
, EA_RIP_METRIC
, p
->infinity
);
1093 u32 old_metric
= ea_get_int(old
->attrs
->eattrs
, EA_RIP_METRIC
, p
->infinity
);
1095 return new_metric
< old_metric
;
1099 rip_rte_igp_metric(struct rte
*rt
)
1101 return ea_get_int(rt
->attrs
->eattrs
, EA_RIP_METRIC
, IGP_METRIC_UNKNOWN
);
1105 rip_postconfig(struct proto_config
*CF
)
1107 // struct rip_config *cf = (void *) CF;
1109 /* Define default channel */
1110 if (! proto_cf_main_channel(CF
))
1111 channel_config_new(NULL
, net_label
[CF
->net_type
], CF
->net_type
, CF
);
1114 static struct proto
*
1115 rip_init(struct proto_config
*CF
)
1117 struct proto
*P
= proto_new(CF
);
1119 P
->main_channel
= proto_add_channel(P
, proto_cf_main_channel(CF
));
1121 P
->if_notify
= rip_if_notify
;
1122 P
->rt_notify
= rip_rt_notify
;
1123 P
->neigh_notify
= rip_neigh_notify
;
1124 P
->reload_routes
= rip_reload_routes
;
1125 P
->rte_better
= rip_rte_better
;
1126 P
->rte_igp_metric
= rip_rte_igp_metric
;
1132 rip_start(struct proto
*P
)
1134 struct rip_proto
*p
= (void *) P
;
1135 struct rip_config
*cf
= (void *) (P
->cf
);
1137 init_list(&p
->iface_list
);
1138 fib_init(&p
->rtable
, P
->pool
, cf
->rip2
? NET_IP4
: NET_IP6
,
1139 sizeof(struct rip_entry
), OFFSETOF(struct rip_entry
, n
), 0, NULL
);
1140 p
->rte_slab
= sl_new(P
->pool
, sizeof(struct rip_rte
));
1141 p
->timer
= tm_new_init(P
->pool
, rip_timer
, p
, 0, 0);
1145 p
->infinity
= cf
->infinity
;
1148 p
->log_pkt_tbf
= (struct tbf
){ .rate
= 1, .burst
= 5 };
1149 p
->log_rte_tbf
= (struct tbf
){ .rate
= 4, .burst
= 20 };
1151 tm_start(p
->timer
, MIN(cf
->min_timeout_time
, cf
->max_garbage_time
));
1157 rip_shutdown(struct proto
*P
)
1159 struct rip_proto
*p
= (void *) P
;
1161 TRACE(D_EVENTS
, "Shutdown requested");
1163 struct rip_iface
*ifa
;
1164 WALK_LIST(ifa
, p
->iface_list
)
1165 rip_iface_stop(ifa
);
1171 rip_reconfigure(struct proto
*P
, struct proto_config
*CF
)
1173 struct rip_proto
*p
= (void *) P
;
1174 struct rip_config
*new = (void *) CF
;
1175 // struct rip_config *old = (void *) (P->cf);
1177 if (new->rip2
!= p
->rip2
)
1180 if (new->infinity
!= p
->infinity
)
1183 if (!proto_configure_channel(P
, &P
->main_channel
, proto_cf_main_channel(CF
)))
1186 TRACE(D_EVENTS
, "Reconfiguring");
1189 p
->ecmp
= new->ecmp
;
1190 rip_reconfigure_ifaces(p
, new);
1199 rip_get_route_info(rte
*rte
, byte
*buf
)
1201 struct rip_proto
*p
= (struct rip_proto
*) rte
->src
->proto
;
1202 u32 rt_metric
= ea_get_int(rte
->attrs
->eattrs
, EA_RIP_METRIC
, p
->infinity
);
1203 u32 rt_tag
= ea_get_int(rte
->attrs
->eattrs
, EA_RIP_TAG
, 0);
1205 buf
+= bsprintf(buf
, " (%d/%d)", rte
->attrs
->pref
, rt_metric
);
1208 bsprintf(buf
, " [%04x]", rt_tag
);
1212 rip_get_attr(const eattr
*a
, byte
*buf
, int buflen UNUSED
)
1217 bsprintf(buf
, "metric: %d", a
->u
.data
);
1221 bsprintf(buf
, "tag: %04x", a
->u
.data
);
1230 rip_show_interfaces(struct proto
*P
, const char *iff
)
1232 struct rip_proto
*p
= (void *) P
;
1233 struct rip_iface
*ifa
= NULL
;
1234 struct rip_neighbor
*n
= NULL
;
1236 if (p
->p
.proto_state
!= PS_UP
)
1238 cli_msg(-1021, "%s: is not up", p
->p
.name
);
1242 cli_msg(-1021, "%s:", p
->p
.name
);
1243 cli_msg(-1021, "%-10s %-6s %6s %6s %7s",
1244 "Interface", "State", "Metric", "Nbrs", "Timer");
1246 WALK_LIST(ifa
, p
->iface_list
)
1248 if (iff
&& !patmatch(iff
, ifa
->iface
->name
))
1252 WALK_LIST(n
, ifa
->neigh_list
)
1256 btime now_
= current_time();
1257 btime timer
= ((ifa
->next_regular
< TIME_INFINITY
) && (ifa
->next_regular
> now_
)) ?
1258 (ifa
->next_regular
- now_
) : 0;
1259 cli_msg(-1021, "%-10s %-6s %6u %6u %7t",
1260 ifa
->iface
->name
, (ifa
->up
? "Up" : "Down"), ifa
->cf
->metric
, nbrs
, timer
);
1265 rip_show_neighbors(struct proto
*P
, const char *iff
)
1267 struct rip_proto
*p
= (void *) P
;
1268 struct rip_iface
*ifa
= NULL
;
1269 struct rip_neighbor
*n
= NULL
;
1271 if (p
->p
.proto_state
!= PS_UP
)
1273 cli_msg(-1022, "%s: is not up", p
->p
.name
);
1277 cli_msg(-1022, "%s:", p
->p
.name
);
1278 cli_msg(-1022, "%-25s %-10s %6s %6s %7s",
1279 "IP address", "Interface", "Metric", "Routes", "Seen");
1281 WALK_LIST(ifa
, p
->iface_list
)
1283 if (iff
&& !patmatch(iff
, ifa
->iface
->name
))
1286 WALK_LIST(n
, ifa
->neigh_list
)
1291 btime timer
= current_time() - n
->last_seen
;
1292 cli_msg(-1022, "%-25I %-10s %6u %6u %7t",
1293 n
->nbr
->addr
, ifa
->iface
->name
, ifa
->cf
->metric
, n
->uc
, timer
);
1299 rip_dump(struct proto
*P
)
1301 struct rip_proto
*p
= (struct rip_proto
*) P
;
1302 struct rip_iface
*ifa
;
1306 FIB_WALK(&p
->rtable
, struct rip_entry
, en
)
1308 debug("RIP: entry #%d: %N via %I dev %s valid %d metric %d age %t\n",
1309 i
++, en
->n
.addr
, en
->next_hop
, en
->iface
? en
->iface
->name
: "(null)",
1310 en
->valid
, en
->metric
, current_time() - en
->changed
);
1312 for (struct rip_rte
*e
= en
->routes
; e
; e
= e
->next
)
1313 debug("RIP: via %I metric %d expires %t\n",
1314 e
->next_hop
, e
->metric
, e
->expires
- current_time());
1319 WALK_LIST(ifa
, p
->iface_list
)
1321 debug("RIP: interface #%d: %s, %I, up = %d, busy = %d\n",
1322 i
++, ifa
->iface
->name
, ifa
->sk
? ifa
->sk
->daddr
: IPA_NONE
,
1323 ifa
->up
, ifa
->tx_active
);
1328 struct protocol proto_rip
= {
1330 .template = "rip%d",
1331 .class = PROTOCOL_RIP
,
1332 .preference
= DEF_PREF_RIP
,
1333 .channel_mask
= NB_IP
,
1334 .proto_size
= sizeof(struct rip_proto
),
1335 .config_size
= sizeof(struct rip_config
),
1336 .postconfig
= rip_postconfig
,
1340 .shutdown
= rip_shutdown
,
1341 .reconfigure
= rip_reconfigure
,
1342 .get_route_info
= rip_get_route_info
,
1343 .get_attr
= rip_get_attr