]>
git.ipfire.org Git - thirdparty/bird.git/blob - proto/rip/rip.c
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 4822 - RIP cryptographic authentication
82 static inline void rip_lock_neighbor(struct rip_neighbor
*n
);
83 static inline void rip_unlock_neighbor(struct rip_neighbor
*n
);
84 static inline int rip_iface_link_up(struct rip_iface
*ifa
);
85 static inline void rip_kick_timer(struct rip_proto
*p
);
86 static inline void rip_iface_kick_timer(struct rip_iface
*ifa
);
87 static void rip_iface_timer(timer
*timer
);
88 static void rip_trigger_update(struct rip_proto
*p
);
95 static struct rip_rte
*
96 rip_add_rte(struct rip_proto
*p
, struct rip_rte
**rp
, struct rip_rte
*src
)
98 struct rip_rte
*rt
= sl_alloc(p
->rte_slab
);
100 memcpy(rt
, src
, sizeof(struct rip_rte
));
104 rip_lock_neighbor(rt
->from
);
110 rip_remove_rte(struct rip_proto
*p
, struct rip_rte
**rp
)
112 struct rip_rte
*rt
= *rp
;
114 rip_unlock_neighbor(rt
->from
);
117 sl_free(p
->rte_slab
, rt
);
120 static inline int rip_same_rte(struct rip_rte
*a
, struct rip_rte
*b
)
121 { return a
->metric
== b
->metric
&& a
->tag
== b
->tag
&& ipa_equal(a
->next_hop
, b
->next_hop
); }
123 static inline int rip_valid_rte(struct rip_rte
*rt
)
124 { return rt
->from
->ifa
!= NULL
; }
127 * rip_announce_rte - announce route from RIP routing table to the core
129 * @en: related network
131 * The function takes a list of incoming routes from @en, prepare appropriate
132 * &rte for the core and propagate it by rte_update().
135 rip_announce_rte(struct rip_proto
*p
, struct rip_entry
*en
)
137 struct rip_rte
*rt
= en
->routes
;
139 /* Find first valid rte */
140 while (rt
&& !rip_valid_rte(rt
))
146 net
*n
= net_get(p
->p
.main_channel
->table
, en
->n
.addr
);
149 .src
= p
->p
.main_source
,
151 .scope
= SCOPE_UNIVERSE
,
155 u8 rt_metric
= rt
->metric
;
156 u16 rt_tag
= rt
->tag
;
157 struct rip_rte
*rt2
= rt
->next
;
159 /* Find second valid rte */
160 while (rt2
&& !rip_valid_rte(rt2
))
166 struct mpnh
*nhs
= NULL
;
167 struct mpnh
**nhp
= &nhs
;
170 for (rt
= en
->routes
; rt
&& (num
< p
->ecmp
); rt
= rt
->next
)
172 if (!rip_valid_rte(rt
))
175 struct mpnh
*nh
= alloca(sizeof(struct mpnh
));
176 nh
->gw
= rt
->next_hop
;
177 nh
->iface
= rt
->from
->nbr
->iface
;
178 nh
->weight
= rt
->from
->ifa
->cf
->ecmp_weight
;
184 if (rt
->tag
!= rt_tag
)
188 a0
.dest
= RTD_MULTIPATH
;
194 a0
.dest
= RTD_ROUTER
;
195 a0
.gw
= rt
->next_hop
;
196 a0
.iface
= rt
->from
->nbr
->iface
;
197 a0
.from
= rt
->from
->nbr
->addr
;
200 rta
*a
= rta_lookup(&a0
);
201 rte
*e
= rte_get_temp(a
);
203 e
->u
.rip
.from
= a0
.iface
;
204 e
->u
.rip
.metric
= rt_metric
;
205 e
->u
.rip
.tag
= rt_tag
;
210 rte_update(&p
->p
, n
, e
);
215 net
*n
= net_find(p
->p
.main_channel
->table
, en
->n
.addr
);
216 rte_update(&p
->p
, n
, NULL
);
221 * rip_update_rte - enter a route update to RIP routing table
223 * @addr: network address
224 * @new: a &rip_rte representing the new route
226 * The function is called by the RIP packet processing code whenever it receives
227 * a reachable route. The appropriate routing table entry is found and the list
228 * of incoming routes is updated. Eventually, the change is also propagated to
229 * the core by rip_announce_rte(). Note that for unreachable routes,
230 * rip_withdraw_rte() should be called instead of rip_update_rte().
233 rip_update_rte(struct rip_proto
*p
, net_addr
*n
, struct rip_rte
*new)
235 struct rip_entry
*en
= fib_get(&p
->rtable
, n
);
236 struct rip_rte
*rt
, **rp
;
239 /* If the new route is better, remove all current routes */
240 if (en
->routes
&& new->metric
< en
->routes
->metric
)
242 rip_remove_rte(p
, &en
->routes
);
244 /* Find the old route (also set rp for later) */
245 for (rp
= &en
->routes
; rt
= *rp
; rp
= &rt
->next
)
246 if (rt
->from
== new->from
)
248 if (rip_same_rte(rt
, new))
250 rt
->expires
= new->expires
;
254 /* Remove the old route */
255 rip_remove_rte(p
, rp
);
260 /* If the new route is optimal, add it to the list */
261 if (!en
->routes
|| new->metric
== en
->routes
->metric
)
263 rt
= rip_add_rte(p
, rp
, new);
267 /* Announce change if on relevant position (the first or any for ECMP) */
268 if (changed
&& (rp
== &en
->routes
|| p
->ecmp
))
269 rip_announce_rte(p
, en
);
273 * rip_withdraw_rte - enter a route withdraw to RIP routing table
275 * @addr: network address
276 * @from: a &rip_neighbor propagating the withdraw
278 * The function is called by the RIP packet processing code whenever it receives
279 * an unreachable route. The incoming route for given network from nbr @from is
280 * removed. Eventually, the change is also propagated by rip_announce_rte().
283 rip_withdraw_rte(struct rip_proto
*p
, net_addr
*n
, struct rip_neighbor
*from
)
285 struct rip_entry
*en
= fib_find(&p
->rtable
, n
);
286 struct rip_rte
*rt
, **rp
;
291 /* Find the old route */
292 for (rp
= &en
->routes
; rt
= *rp
; rp
= &rt
->next
)
293 if (rt
->from
== from
)
299 /* Remove the old route */
300 rip_remove_rte(p
, rp
);
302 /* Announce change if on relevant position */
303 if (rp
== &en
->routes
|| p
->ecmp
)
304 rip_announce_rte(p
, en
);
308 * rip_rt_notify - core tells us about new route, so store
309 * it into our data structures.
312 rip_rt_notify(struct proto
*P
, struct rtable
*table UNUSED
, struct network
*net
, struct rte
*new,
313 struct rte
*old UNUSED
, struct ea_list
*attrs
)
315 struct rip_proto
*p
= (struct rip_proto
*) P
;
316 struct rip_entry
*en
;
322 u32 rt_metric
= ea_get_int(attrs
, EA_RIP_METRIC
, 1);
323 u32 rt_tag
= ea_get_int(attrs
, EA_RIP_TAG
, 0);
325 if (rt_metric
> p
->infinity
)
327 log(L_WARN
"%s: Invalid rip_metric value %u for route %N",
328 p
->p
.name
, rt_metric
, net
->n
.addr
);
329 rt_metric
= p
->infinity
;
334 log(L_WARN
"%s: Invalid rip_tag value %u for route %N",
335 p
->p
.name
, rt_tag
, net
->n
.addr
);
336 rt_metric
= p
->infinity
;
341 * Note that we accept exported routes with infinity metric (this could
342 * happen if rip_metric is modified in filters). Such entry has infinity
343 * metric but is RIP_ENTRY_VALID and therefore is not subject to garbage
347 en
= fib_get(&p
->rtable
, net
->n
.addr
);
349 old_metric
= en
->valid
? en
->metric
: -1;
351 en
->valid
= RIP_ENTRY_VALID
;
352 en
->metric
= rt_metric
;
354 en
->from
= (new->attrs
->src
->proto
== P
) ? new->u
.rip
.from
: NULL
;
355 en
->iface
= new->attrs
->iface
;
356 en
->next_hop
= new->attrs
->gw
;
361 en
= fib_find(&p
->rtable
, net
->n
.addr
);
363 if (!en
|| en
->valid
!= RIP_ENTRY_VALID
)
366 old_metric
= en
->metric
;
368 en
->valid
= RIP_ENTRY_STALE
;
369 en
->metric
= p
->infinity
;
373 en
->next_hop
= IPA_NONE
;
376 /* Activate triggered updates */
377 if (en
->metric
!= old_metric
)
380 rip_trigger_update(p
);
389 struct rip_neighbor
*
390 rip_get_neighbor(struct rip_proto
*p
, ip_addr
*a
, struct rip_iface
*ifa
)
392 neighbor
*nbr
= neigh_find2(&p
->p
, a
, ifa
->iface
, 0);
394 if (!nbr
|| (nbr
->scope
== SCOPE_HOST
) || !rip_iface_link_up(ifa
))
400 TRACE(D_EVENTS
, "New neighbor %I on %s", *a
, ifa
->iface
->name
);
402 struct rip_neighbor
*n
= mb_allocz(p
->p
.pool
, sizeof(struct rip_neighbor
));
408 add_tail(&ifa
->neigh_list
, NODE n
);
414 rip_remove_neighbor(struct rip_proto
*p
, struct rip_neighbor
*n
)
416 neighbor
*nbr
= n
->nbr
;
418 TRACE(D_EVENTS
, "Removing neighbor %I on %s", nbr
->addr
, nbr
->iface
->name
);
433 /* Related routes are removed in rip_timer() */
438 rip_lock_neighbor(struct rip_neighbor
*n
)
444 rip_unlock_neighbor(struct rip_neighbor
*n
)
448 if (!n
->nbr
&& !n
->uc
)
453 rip_neigh_notify(struct neighbor
*nbr
)
455 struct rip_proto
*p
= (struct rip_proto
*) nbr
->proto
;
456 struct rip_neighbor
*n
= nbr
->data
;
462 * We assume that rip_neigh_notify() is called before rip_if_notify() for
463 * IF_CHANGE_DOWN and therefore n->ifa is still valid. We have no such
464 * ordering assumption for IF_CHANGE_LINK, so we test link state of the
465 * underlying iface instead of just rip_iface state.
467 if ((nbr
->scope
<= 0) || !rip_iface_link_up(n
->ifa
))
468 rip_remove_neighbor(p
, n
);
472 rip_bfd_notify(struct bfd_request
*req
)
474 struct rip_neighbor
*n
= req
->data
;
475 struct rip_proto
*p
= n
->ifa
->rip
;
479 TRACE(D_EVENTS
, "BFD session down for nbr %I on %s",
480 n
->nbr
->addr
, n
->ifa
->iface
->name
);
481 rip_remove_neighbor(p
, n
);
486 rip_update_bfd(struct rip_proto
*p
, struct rip_neighbor
*n
)
488 int use_bfd
= n
->ifa
->cf
->bfd
&& n
->last_seen
;
490 if (use_bfd
&& !n
->bfd_req
)
493 * For RIPv2, use the same address as rip_open_socket(). For RIPng, neighbor
494 * should contain an address from the same prefix, thus also link-local. It
495 * may cause problems if two link-local addresses are assigned to one iface.
497 ip_addr saddr
= rip_is_v2(p
) ? n
->ifa
->sk
->saddr
: n
->nbr
->ifa
->ip
;
498 n
->bfd_req
= bfd_request_session(p
->p
.pool
, n
->nbr
->addr
, saddr
,
499 n
->nbr
->iface
, rip_bfd_notify
, n
);
502 if (!use_bfd
&& n
->bfd_req
)
515 rip_iface_start(struct rip_iface
*ifa
)
517 struct rip_proto
*p
= ifa
->rip
;
519 TRACE(D_EVENTS
, "Starting interface %s", ifa
->iface
->name
);
521 ifa
->next_regular
= now
+ (random() % ifa
->cf
->update_time
) + 1;
522 ifa
->next_triggered
= now
; /* Available immediately */
523 ifa
->want_triggered
= 1; /* All routes in triggered update */
524 tm_start(ifa
->timer
, 1); /* Or 100 ms */
527 if (!ifa
->cf
->passive
)
528 rip_send_request(ifa
->rip
, ifa
);
532 rip_iface_stop(struct rip_iface
*ifa
)
534 struct rip_proto
*p
= ifa
->rip
;
535 struct rip_neighbor
*n
;
537 TRACE(D_EVENTS
, "Stopping interface %s", ifa
->iface
->name
);
539 rip_reset_tx_session(p
, ifa
);
541 WALK_LIST_FIRST(n
, ifa
->neigh_list
)
542 rip_remove_neighbor(p
, n
);
549 rip_iface_link_up(struct rip_iface
*ifa
)
551 return !ifa
->cf
->check_link
|| (ifa
->iface
->flags
& IF_LINK_UP
);
555 rip_iface_update_state(struct rip_iface
*ifa
)
557 int up
= ifa
->sk
&& rip_iface_link_up(ifa
);
563 rip_iface_start(ifa
);
569 rip_iface_update_buffers(struct rip_iface
*ifa
)
574 uint rbsize
= ifa
->cf
->rx_buffer
?: ifa
->iface
->mtu
;
575 uint tbsize
= ifa
->cf
->tx_length
?: ifa
->iface
->mtu
;
576 rbsize
= MAX(rbsize
, tbsize
);
578 sk_set_rbsize(ifa
->sk
, rbsize
);
579 sk_set_tbsize(ifa
->sk
, tbsize
);
581 uint headers
= (rip_is_v2(ifa
->rip
) ? IP4_HEADER_LENGTH
: IP6_HEADER_LENGTH
) + UDP_HEADER_LENGTH
;
582 ifa
->tx_plen
= tbsize
- headers
;
584 if (ifa
->cf
->auth_type
== RIP_AUTH_CRYPTO
)
585 ifa
->tx_plen
-= RIP_AUTH_TAIL_LENGTH
;
589 rip_iface_update_bfd(struct rip_iface
*ifa
)
591 struct rip_proto
*p
= ifa
->rip
;
592 struct rip_neighbor
*n
;
594 WALK_LIST(n
, ifa
->neigh_list
)
595 rip_update_bfd(p
, n
);
600 rip_iface_locked(struct object_lock
*lock
)
602 struct rip_iface
*ifa
= lock
->data
;
603 struct rip_proto
*p
= ifa
->rip
;
605 if (!rip_open_socket(ifa
))
607 log(L_ERR
"%s: Cannot open socket for %s", p
->p
.name
, ifa
->iface
->name
);
611 rip_iface_update_buffers(ifa
);
612 rip_iface_update_state(ifa
);
616 static struct rip_iface
*
617 rip_find_iface(struct rip_proto
*p
, struct iface
*what
)
619 struct rip_iface
*ifa
;
621 WALK_LIST(ifa
, p
->iface_list
)
622 if (ifa
->iface
== what
)
629 rip_add_iface(struct rip_proto
*p
, struct iface
*iface
, struct rip_iface_config
*ic
)
631 struct rip_iface
*ifa
;
633 TRACE(D_EVENTS
, "Adding interface %s", iface
->name
);
635 ifa
= mb_allocz(p
->p
.pool
, sizeof(struct rip_iface
));
640 if (ipa_nonzero(ic
->address
))
641 ifa
->addr
= ic
->address
;
642 else if (ic
->mode
== RIP_IM_MULTICAST
)
643 ifa
->addr
= rip_is_v2(p
) ? IP4_RIP_ROUTERS
: IP6_RIP_ROUTERS
;
645 ifa
->addr
= iface
->addr
->brd
;
647 init_list(&ifa
->neigh_list
);
649 add_tail(&p
->iface_list
, NODE ifa
);
651 ifa
->timer
= tm_new_set(p
->p
.pool
, rip_iface_timer
, ifa
, 0, 0);
653 struct object_lock
*lock
= olock_new(p
->p
.pool
);
654 lock
->type
= OBJLOCK_UDP
;
655 lock
->port
= ic
->port
;
658 lock
->hook
= rip_iface_locked
;
665 rip_remove_iface(struct rip_proto
*p
, struct rip_iface
*ifa
)
669 TRACE(D_EVENTS
, "Removing interface %s", ifa
->iface
->name
);
681 rip_reconfigure_iface(struct rip_proto
*p
, struct rip_iface
*ifa
, struct rip_iface_config
*new)
683 struct rip_iface_config
*old
= ifa
->cf
;
685 /* Change of these options would require to reset the iface socket */
686 if ((new->mode
!= old
->mode
) ||
687 (new->port
!= old
->port
) ||
688 (new->tx_tos
!= old
->tx_tos
) ||
689 (new->tx_priority
!= old
->tx_priority
) ||
690 (new->ttl_security
!= old
->ttl_security
))
693 TRACE(D_EVENTS
, "Reconfiguring interface %s", ifa
->iface
->name
);
697 if (ifa
->next_regular
> (now
+ new->update_time
))
698 ifa
->next_regular
= now
+ (random() % new->update_time
) + 1;
700 if ((new->tx_length
!= old
->tx_length
) || (new->rx_buffer
!= old
->rx_buffer
))
701 rip_iface_update_buffers(ifa
);
703 if (new->check_link
!= old
->check_link
)
704 rip_iface_update_state(ifa
);
706 if (new->bfd
!= old
->bfd
)
707 rip_iface_update_bfd(ifa
);
710 rip_iface_kick_timer(ifa
);
716 rip_reconfigure_ifaces(struct rip_proto
*p
, struct rip_config
*cf
)
720 WALK_LIST(iface
, iface_list
)
722 if (! (iface
->flags
& IF_UP
))
725 struct rip_iface
*ifa
= rip_find_iface(p
, iface
);
726 struct rip_iface_config
*ic
= (void *) iface_patt_find(&cf
->patt_list
, iface
, NULL
);
730 if (rip_reconfigure_iface(p
, ifa
, ic
))
734 log(L_INFO
"%s: Restarting interface %s", p
->p
.name
, ifa
->iface
->name
);
735 rip_remove_iface(p
, ifa
);
736 rip_add_iface(p
, iface
, ic
);
740 rip_remove_iface(p
, ifa
);
743 rip_add_iface(p
, iface
, ic
);
748 rip_if_notify(struct proto
*P
, unsigned flags
, struct iface
*iface
)
750 struct rip_proto
*p
= (void *) P
;
751 struct rip_config
*cf
= (void *) P
->cf
;
753 if (iface
->flags
& IF_IGNORE
)
756 if (flags
& IF_CHANGE_UP
)
758 struct rip_iface_config
*ic
= (void *) iface_patt_find(&cf
->patt_list
, iface
, NULL
);
761 rip_add_iface(p
, iface
, ic
);
766 struct rip_iface
*ifa
= rip_find_iface(p
, iface
);
771 if (flags
& IF_CHANGE_DOWN
)
773 rip_remove_iface(p
, ifa
);
777 if (flags
& IF_CHANGE_MTU
)
778 rip_iface_update_buffers(ifa
);
780 if (flags
& IF_CHANGE_LINK
)
781 rip_iface_update_state(ifa
);
790 * rip_timer - RIP main timer hook
793 * The RIP main timer is responsible for routing table maintenance. Invalid or
794 * expired routes (&rip_rte) are removed and garbage collection of stale routing
795 * table entries (&rip_entry) is done. Changes are propagated to core tables,
796 * route reload is also done here. Note that garbage collection uses a maximal
797 * GC time, while interfaces maintain an illusion of per-interface GC times in
798 * rip_send_response().
800 * Keeping incoming routes and the selected outgoing route are two independent
801 * functions, therefore after garbage collection some entries now considered
802 * invalid (RIP_ENTRY_DUMMY) still may have non-empty list of incoming routes,
803 * while some valid entries (representing an outgoing route) may have that list
806 * The main timer is not scheduled periodically but it uses the time of the
807 * current next event and the minimal interval of any possible event to compute
808 * the time of the next run.
813 struct rip_proto
*p
= t
->data
;
814 struct rip_config
*cf
= (void *) (p
->p
.cf
);
815 struct rip_iface
*ifa
;
816 struct rip_neighbor
*n
, *nn
;
817 struct fib_iterator fit
;
818 bird_clock_t next
= now
+ MIN(cf
->min_timeout_time
, cf
->max_garbage_time
);
819 bird_clock_t expires
= 0;
821 TRACE(D_EVENTS
, "Main timer fired");
823 FIB_ITERATE_INIT(&fit
, &p
->rtable
);
826 FIB_ITERATE_START(&p
->rtable
, &fit
, struct rip_entry
, en
)
828 struct rip_rte
*rt
, **rp
;
831 /* Checking received routes for timeout and for dead neighbors */
832 for (rp
= &en
->routes
; rt
= *rp
; /* rp = &rt->next */)
834 if (!rip_valid_rte(rt
) || (rt
->expires
<= now
))
836 rip_remove_rte(p
, rp
);
841 next
= MIN(next
, rt
->expires
);
845 /* Propagating eventual change */
846 if (changed
|| p
->rt_reload
)
849 * We have to restart the iteration because there may be a cascade of
850 * synchronous events rip_announce_rte() -> nest table change ->
851 * rip_rt_notify() -> p->rtable change, invalidating hidden variables.
854 FIB_ITERATE_PUT_NEXT(&fit
, &p
->rtable
);
855 rip_announce_rte(p
, en
);
859 /* Checking stale entries for garbage collection timeout */
860 if (en
->valid
== RIP_ENTRY_STALE
)
862 expires
= en
->changed
+ cf
->max_garbage_time
;
866 // TRACE(D_EVENTS, "entry is too old: %N", en->n.addr);
870 next
= MIN(next
, expires
);
873 /* Remove empty nodes */
874 if (!en
->valid
&& !en
->routes
)
876 FIB_ITERATE_PUT(&fit
);
877 fib_delete(&p
->rtable
, en
);
885 /* Handling neighbor expiration */
886 WALK_LIST(ifa
, p
->iface_list
)
887 WALK_LIST_DELSAFE(n
, nn
, ifa
->neigh_list
)
890 expires
= n
->last_seen
+ n
->ifa
->cf
->timeout_time
;
893 rip_remove_neighbor(p
, n
);
895 next
= MIN(next
, expires
);
898 tm_start(p
->timer
, MAX(next
- now
, 1));
902 rip_kick_timer(struct rip_proto
*p
)
904 if (p
->timer
->expires
> (now
+ 1))
905 tm_start(p
->timer
, 1); /* Or 100 ms */
909 * rip_iface_timer - RIP interface timer hook
912 * RIP interface timers are responsible for scheduling both regular and
913 * triggered updates. Fixed, delay-independent period is used for regular
914 * updates, while minimal separating interval is enforced for triggered updates.
915 * The function also ensures that a new update is not started when the old one
919 rip_iface_timer(timer
*t
)
921 struct rip_iface
*ifa
= t
->data
;
922 struct rip_proto
*p
= ifa
->rip
;
923 bird_clock_t period
= ifa
->cf
->update_time
;
925 if (ifa
->cf
->passive
)
928 TRACE(D_EVENTS
, "Interface timer fired for %s", ifa
->iface
->name
);
932 if (now
< (ifa
->next_regular
+ period
))
933 { tm_start(ifa
->timer
, 1); return; }
935 /* We are too late, reset is done by rip_send_table() */
936 log(L_WARN
"%s: Too slow update on %s, resetting", p
->p
.name
, ifa
->iface
->name
);
939 if (now
>= ifa
->next_regular
)
941 /* Send regular update, set timer for next period (or following one if necessay) */
942 TRACE(D_EVENTS
, "Sending regular updates for %s", ifa
->iface
->name
);
943 rip_send_table(p
, ifa
, ifa
->addr
, 0);
944 ifa
->next_regular
+= period
* (1 + ((now
- ifa
->next_regular
) / period
));
945 ifa
->want_triggered
= 0;
948 else if (ifa
->want_triggered
&& (now
>= ifa
->next_triggered
))
950 /* Send triggered update, enforce interval between triggered updates */
951 TRACE(D_EVENTS
, "Sending triggered updates for %s", ifa
->iface
->name
);
952 rip_send_table(p
, ifa
, ifa
->addr
, ifa
->want_triggered
);
953 ifa
->next_triggered
= now
+ MIN(5, period
/ 2 + 1);
954 ifa
->want_triggered
= 0;
958 tm_start(ifa
->timer
, ifa
->want_triggered
? 1 : (ifa
->next_regular
- now
));
962 rip_iface_kick_timer(struct rip_iface
*ifa
)
964 if (ifa
->timer
->expires
> (now
+ 1))
965 tm_start(ifa
->timer
, 1); /* Or 100 ms */
969 rip_trigger_update(struct rip_proto
*p
)
974 struct rip_iface
*ifa
;
975 WALK_LIST(ifa
, p
->iface_list
)
977 /* Interface not active */
981 /* Already scheduled */
982 if (ifa
->want_triggered
)
985 TRACE(D_EVENTS
, "Scheduling triggered updates for %s", ifa
->iface
->name
);
986 ifa
->want_triggered
= now
;
987 rip_iface_kick_timer(ifa
);
998 static struct ea_list
*
999 rip_prepare_attrs(struct linpool
*pool
, ea_list
*next
, u8 metric
, u16 tag
)
1001 struct ea_list
*l
= lp_alloc(pool
, sizeof(struct ea_list
) + 2 * sizeof(eattr
));
1004 l
->flags
= EALF_SORTED
;
1007 l
->attrs
[0].id
= EA_RIP_METRIC
;
1008 l
->attrs
[0].flags
= 0;
1009 l
->attrs
[0].type
= EAF_TYPE_INT
| EAF_TEMP
;
1010 l
->attrs
[0].u
.data
= metric
;
1012 l
->attrs
[1].id
= EA_RIP_TAG
;
1013 l
->attrs
[1].flags
= 0;
1014 l
->attrs
[1].type
= EAF_TYPE_INT
| EAF_TEMP
;
1015 l
->attrs
[1].u
.data
= tag
;
1021 rip_import_control(struct proto
*P
, struct rte
**rt
, struct ea_list
**attrs
, struct linpool
*pool
)
1023 /* Prepare attributes with initial values */
1024 if ((*rt
)->attrs
->source
!= RTS_RIP
)
1025 *attrs
= rip_prepare_attrs(pool
, *attrs
, 1, 0);
1031 rip_reload_routes(struct channel
*C
)
1033 struct rip_proto
*p
= (struct rip_proto
*) C
->proto
;
1038 TRACE(D_EVENTS
, "Scheduling route reload");
1043 static struct ea_list
*
1044 rip_make_tmp_attrs(struct rte
*rt
, struct linpool
*pool
)
1046 return rip_prepare_attrs(pool
, NULL
, rt
->u
.rip
.metric
, rt
->u
.rip
.tag
);
1050 rip_store_tmp_attrs(struct rte
*rt
, struct ea_list
*attrs
)
1052 rt
->u
.rip
.metric
= ea_get_int(attrs
, EA_RIP_METRIC
, 1);
1053 rt
->u
.rip
.tag
= ea_get_int(attrs
, EA_RIP_TAG
, 0);
1057 rip_rte_better(struct rte
*new, struct rte
*old
)
1059 return new->u
.rip
.metric
< old
->u
.rip
.metric
;
1063 rip_rte_same(struct rte
*new, struct rte
*old
)
1065 return ((new->u
.rip
.metric
== old
->u
.rip
.metric
) &&
1066 (new->u
.rip
.tag
== old
->u
.rip
.tag
) &&
1067 (new->u
.rip
.from
== old
->u
.rip
.from
));
1072 rip_postconfig(struct proto_config
*CF
)
1074 // struct rip_config *cf = (void *) CF;
1076 /* Define default channel */
1077 if (EMPTY_LIST(CF
->channels
))
1078 channel_config_new(NULL
, CF
->net_type
, CF
);
1081 static struct proto
*
1082 rip_init(struct proto_config
*CF
)
1084 struct proto
*P
= proto_new(CF
);
1086 P
->main_channel
= proto_add_channel(P
, proto_cf_main_channel(CF
));
1088 P
->if_notify
= rip_if_notify
;
1089 P
->rt_notify
= rip_rt_notify
;
1090 P
->neigh_notify
= rip_neigh_notify
;
1091 P
->import_control
= rip_import_control
;
1092 P
->reload_routes
= rip_reload_routes
;
1093 P
->make_tmp_attrs
= rip_make_tmp_attrs
;
1094 P
->store_tmp_attrs
= rip_store_tmp_attrs
;
1095 P
->rte_better
= rip_rte_better
;
1096 P
->rte_same
= rip_rte_same
;
1102 rip_start(struct proto
*P
)
1104 struct rip_proto
*p
= (void *) P
;
1105 struct rip_config
*cf
= (void *) (P
->cf
);
1107 init_list(&p
->iface_list
);
1108 fib_init(&p
->rtable
, P
->pool
, cf
->rip2
? NET_IP4
: NET_IP6
,
1109 sizeof(struct rip_entry
), OFFSETOF(struct rip_entry
, n
), 0, NULL
);
1110 p
->rte_slab
= sl_new(P
->pool
, sizeof(struct rip_rte
));
1111 p
->timer
= tm_new_set(P
->pool
, rip_timer
, p
, 0, 0);
1115 p
->infinity
= cf
->infinity
;
1118 p
->log_pkt_tbf
= (struct tbf
){ .rate
= 1, .burst
= 5 };
1119 p
->log_rte_tbf
= (struct tbf
){ .rate
= 4, .burst
= 20 };
1121 tm_start(p
->timer
, MIN(cf
->min_timeout_time
, cf
->max_garbage_time
));
1127 rip_reconfigure(struct proto
*P
, struct proto_config
*CF
)
1129 struct rip_proto
*p
= (void *) P
;
1130 struct rip_config
*new = (void *) CF
;
1131 // struct rip_config *old = (void *) (P->cf);
1133 if (new->rip2
!= p
->rip2
)
1136 if (new->infinity
!= p
->infinity
)
1139 if (!proto_configure_channel(P
, &P
->main_channel
, proto_cf_main_channel(CF
)))
1142 TRACE(D_EVENTS
, "Reconfiguring");
1145 p
->ecmp
= new->ecmp
;
1146 rip_reconfigure_ifaces(p
, new);
1155 rip_get_route_info(rte
*rte
, byte
*buf
, ea_list
*attrs
)
1157 buf
+= bsprintf(buf
, " (%d/%d)", rte
->pref
, rte
->u
.rip
.metric
);
1160 bsprintf(buf
, " [%04x]", rte
->u
.rip
.tag
);
1164 rip_get_attr(eattr
*a
, byte
*buf
, int buflen UNUSED
)
1169 bsprintf(buf
, "metric: %d", a
->u
.data
);
1173 bsprintf(buf
, "tag: %04x", a
->u
.data
);
1182 rip_show_interfaces(struct proto
*P
, char *iff
)
1184 struct rip_proto
*p
= (void *) P
;
1185 struct rip_iface
*ifa
= NULL
;
1186 struct rip_neighbor
*n
= NULL
;
1188 if (p
->p
.proto_state
!= PS_UP
)
1190 cli_msg(-1021, "%s: is not up", p
->p
.name
);
1195 cli_msg(-1021, "%s:", p
->p
.name
);
1196 cli_msg(-1021, "%-10s %-6s %6s %6s %6s",
1197 "Interface", "State", "Metric", "Nbrs", "Timer");
1199 WALK_LIST(ifa
, p
->iface_list
)
1201 if (iff
&& !patmatch(iff
, ifa
->iface
->name
))
1205 WALK_LIST(n
, ifa
->neigh_list
)
1209 int timer
= MAX(ifa
->next_regular
- now
, 0);
1210 cli_msg(-1021, "%-10s %-6s %6u %6u %6u",
1211 ifa
->iface
->name
, (ifa
->up
? "Up" : "Down"), ifa
->cf
->metric
, nbrs
, timer
);
1218 rip_show_neighbors(struct proto
*P
, char *iff
)
1220 struct rip_proto
*p
= (void *) P
;
1221 struct rip_iface
*ifa
= NULL
;
1222 struct rip_neighbor
*n
= NULL
;
1224 if (p
->p
.proto_state
!= PS_UP
)
1226 cli_msg(-1022, "%s: is not up", p
->p
.name
);
1231 cli_msg(-1022, "%s:", p
->p
.name
);
1232 cli_msg(-1022, "%-25s %-10s %6s %6s %6s",
1233 "IP address", "Interface", "Metric", "Routes", "Seen");
1235 WALK_LIST(ifa
, p
->iface_list
)
1237 if (iff
&& !patmatch(iff
, ifa
->iface
->name
))
1240 WALK_LIST(n
, ifa
->neigh_list
)
1245 int timer
= now
- n
->last_seen
;
1246 cli_msg(-1022, "%-25I %-10s %6u %6u %6u",
1247 n
->nbr
->addr
, ifa
->iface
->name
, ifa
->cf
->metric
, n
->uc
, timer
);
1255 rip_dump(struct proto
*P
)
1257 struct rip_proto
*p
= (struct rip_proto
*) P
;
1258 struct rip_iface
*ifa
;
1262 FIB_WALK(&p
->rtable
, struct rip_entry
, en
)
1264 debug("RIP: entry #%d: %N via %I dev %s valid %d metric %d age %d s\n",
1265 i
++, en
->n
.addr
, en
->next_hop
, en
->iface
->name
,
1266 en
->valid
, en
->metric
, now
- en
->changed
);
1271 WALK_LIST(ifa
, p
->iface_list
)
1273 debug("RIP: interface #%d: %s, %I, up = %d, busy = %d\n",
1274 i
++, ifa
->iface
->name
, ifa
->sk
? ifa
->sk
->daddr
: IPA_NONE
,
1275 ifa
->up
, ifa
->tx_active
);
1280 struct protocol proto_rip
= {
1282 .template = "rip%d",
1283 .attr_class
= EAP_RIP
,
1284 .preference
= DEF_PREF_RIP
,
1285 .channel_mask
= NB_IP
,
1286 .proto_size
= sizeof(struct rip_proto
),
1287 .config_size
= sizeof(struct rip_config
),
1288 .postconfig
= rip_postconfig
,
1292 .reconfigure
= rip_reconfigure
,
1293 .get_route_info
= rip_get_route_info
,
1294 .get_attr
= rip_get_attr