]>
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
))
147 .src
= p
->p
.main_source
,
149 .scope
= SCOPE_UNIVERSE
,
153 u8 rt_metric
= rt
->metric
;
154 u16 rt_tag
= rt
->tag
;
155 struct rip_rte
*rt2
= rt
->next
;
157 /* Find second valid rte */
158 while (rt2
&& !rip_valid_rte(rt2
))
164 struct mpnh
*nhs
= NULL
;
165 struct mpnh
**nhp
= &nhs
;
168 for (rt
= en
->routes
; rt
&& (num
< p
->ecmp
); rt
= rt
->next
)
170 if (!rip_valid_rte(rt
))
173 struct mpnh
*nh
= alloca(sizeof(struct mpnh
));
174 nh
->gw
= rt
->next_hop
;
175 nh
->iface
= rt
->from
->nbr
->iface
;
176 nh
->weight
= rt
->from
->ifa
->cf
->ecmp_weight
;
182 if (rt
->tag
!= rt_tag
)
186 a0
.dest
= RTD_MULTIPATH
;
192 a0
.dest
= RTD_ROUTER
;
193 a0
.gw
= rt
->next_hop
;
194 a0
.iface
= rt
->from
->nbr
->iface
;
195 a0
.from
= rt
->from
->nbr
->addr
;
198 rta
*a
= rta_lookup(&a0
);
199 rte
*e
= rte_get_temp(a
);
201 e
->u
.rip
.from
= a0
.iface
;
202 e
->u
.rip
.metric
= rt_metric
;
203 e
->u
.rip
.tag
= rt_tag
;
207 rte_update(&p
->p
, en
->n
.addr
, e
);
212 rte_update(&p
->p
, en
->n
.addr
, NULL
);
217 * rip_update_rte - enter a route update to RIP routing table
219 * @addr: network address
220 * @new: a &rip_rte representing the new route
222 * The function is called by the RIP packet processing code whenever it receives
223 * a reachable route. The appropriate routing table entry is found and the list
224 * of incoming routes is updated. Eventually, the change is also propagated to
225 * the core by rip_announce_rte(). Note that for unreachable routes,
226 * rip_withdraw_rte() should be called instead of rip_update_rte().
229 rip_update_rte(struct rip_proto
*p
, net_addr
*n
, struct rip_rte
*new)
231 struct rip_entry
*en
= fib_get(&p
->rtable
, n
);
232 struct rip_rte
*rt
, **rp
;
235 /* If the new route is better, remove all current routes */
236 if (en
->routes
&& new->metric
< en
->routes
->metric
)
238 rip_remove_rte(p
, &en
->routes
);
240 /* Find the old route (also set rp for later) */
241 for (rp
= &en
->routes
; rt
= *rp
; rp
= &rt
->next
)
242 if (rt
->from
== new->from
)
244 if (rip_same_rte(rt
, new))
246 rt
->expires
= new->expires
;
250 /* Remove the old route */
251 rip_remove_rte(p
, rp
);
256 /* If the new route is optimal, add it to the list */
257 if (!en
->routes
|| new->metric
== en
->routes
->metric
)
259 rt
= rip_add_rte(p
, rp
, new);
263 /* Announce change if on relevant position (the first or any for ECMP) */
264 if (changed
&& (rp
== &en
->routes
|| p
->ecmp
))
265 rip_announce_rte(p
, en
);
269 * rip_withdraw_rte - enter a route withdraw to RIP routing table
271 * @addr: network address
272 * @from: a &rip_neighbor propagating the withdraw
274 * The function is called by the RIP packet processing code whenever it receives
275 * an unreachable route. The incoming route for given network from nbr @from is
276 * removed. Eventually, the change is also propagated by rip_announce_rte().
279 rip_withdraw_rte(struct rip_proto
*p
, net_addr
*n
, struct rip_neighbor
*from
)
281 struct rip_entry
*en
= fib_find(&p
->rtable
, n
);
282 struct rip_rte
*rt
, **rp
;
287 /* Find the old route */
288 for (rp
= &en
->routes
; rt
= *rp
; rp
= &rt
->next
)
289 if (rt
->from
== from
)
295 /* Remove the old route */
296 rip_remove_rte(p
, rp
);
298 /* Announce change if on relevant position */
299 if (rp
== &en
->routes
|| p
->ecmp
)
300 rip_announce_rte(p
, en
);
304 * rip_rt_notify - core tells us about new route, so store
305 * it into our data structures.
308 rip_rt_notify(struct proto
*P
, struct channel
*ch UNUSED
, struct network
*net
, struct rte
*new,
309 struct rte
*old UNUSED
, struct ea_list
*attrs
)
311 struct rip_proto
*p
= (struct rip_proto
*) P
;
312 struct rip_entry
*en
;
318 u32 rt_metric
= ea_get_int(attrs
, EA_RIP_METRIC
, 1);
319 u32 rt_tag
= ea_get_int(attrs
, EA_RIP_TAG
, 0);
321 if (rt_metric
> p
->infinity
)
323 log(L_WARN
"%s: Invalid rip_metric value %u for route %N",
324 p
->p
.name
, rt_metric
, net
->n
.addr
);
325 rt_metric
= p
->infinity
;
330 log(L_WARN
"%s: Invalid rip_tag value %u for route %N",
331 p
->p
.name
, rt_tag
, net
->n
.addr
);
332 rt_metric
= p
->infinity
;
337 * Note that we accept exported routes with infinity metric (this could
338 * happen if rip_metric is modified in filters). Such entry has infinity
339 * metric but is RIP_ENTRY_VALID and therefore is not subject to garbage
343 en
= fib_get(&p
->rtable
, net
->n
.addr
);
345 old_metric
= en
->valid
? en
->metric
: -1;
347 en
->valid
= RIP_ENTRY_VALID
;
348 en
->metric
= rt_metric
;
350 en
->from
= (new->attrs
->src
->proto
== P
) ? new->u
.rip
.from
: NULL
;
351 en
->iface
= new->attrs
->iface
;
352 en
->next_hop
= new->attrs
->gw
;
357 en
= fib_find(&p
->rtable
, net
->n
.addr
);
359 if (!en
|| en
->valid
!= RIP_ENTRY_VALID
)
362 old_metric
= en
->metric
;
364 en
->valid
= RIP_ENTRY_STALE
;
365 en
->metric
= p
->infinity
;
369 en
->next_hop
= IPA_NONE
;
372 /* Activate triggered updates */
373 if (en
->metric
!= old_metric
)
376 rip_trigger_update(p
);
385 struct rip_neighbor
*
386 rip_get_neighbor(struct rip_proto
*p
, ip_addr
*a
, struct rip_iface
*ifa
)
388 neighbor
*nbr
= neigh_find2(&p
->p
, a
, ifa
->iface
, 0);
390 if (!nbr
|| (nbr
->scope
== SCOPE_HOST
) || !rip_iface_link_up(ifa
))
396 TRACE(D_EVENTS
, "New neighbor %I on %s", *a
, ifa
->iface
->name
);
398 struct rip_neighbor
*n
= mb_allocz(p
->p
.pool
, sizeof(struct rip_neighbor
));
404 add_tail(&ifa
->neigh_list
, NODE n
);
410 rip_remove_neighbor(struct rip_proto
*p
, struct rip_neighbor
*n
)
412 neighbor
*nbr
= n
->nbr
;
414 TRACE(D_EVENTS
, "Removing neighbor %I on %s", nbr
->addr
, nbr
->iface
->name
);
429 /* Related routes are removed in rip_timer() */
434 rip_lock_neighbor(struct rip_neighbor
*n
)
440 rip_unlock_neighbor(struct rip_neighbor
*n
)
444 if (!n
->nbr
&& !n
->uc
)
449 rip_neigh_notify(struct neighbor
*nbr
)
451 struct rip_proto
*p
= (struct rip_proto
*) nbr
->proto
;
452 struct rip_neighbor
*n
= nbr
->data
;
458 * We assume that rip_neigh_notify() is called before rip_if_notify() for
459 * IF_CHANGE_DOWN and therefore n->ifa is still valid. We have no such
460 * ordering assumption for IF_CHANGE_LINK, so we test link state of the
461 * underlying iface instead of just rip_iface state.
463 if ((nbr
->scope
<= 0) || !rip_iface_link_up(n
->ifa
))
464 rip_remove_neighbor(p
, n
);
468 rip_bfd_notify(struct bfd_request
*req
)
470 struct rip_neighbor
*n
= req
->data
;
471 struct rip_proto
*p
= n
->ifa
->rip
;
475 TRACE(D_EVENTS
, "BFD session down for nbr %I on %s",
476 n
->nbr
->addr
, n
->ifa
->iface
->name
);
477 rip_remove_neighbor(p
, n
);
482 rip_update_bfd(struct rip_proto
*p
, struct rip_neighbor
*n
)
484 int use_bfd
= n
->ifa
->cf
->bfd
&& n
->last_seen
;
486 if (use_bfd
&& !n
->bfd_req
)
489 * For RIPv2, use the same address as rip_open_socket(). For RIPng, neighbor
490 * should contain an address from the same prefix, thus also link-local. It
491 * may cause problems if two link-local addresses are assigned to one iface.
493 ip_addr saddr
= rip_is_v2(p
) ? n
->ifa
->sk
->saddr
: n
->nbr
->ifa
->ip
;
494 n
->bfd_req
= bfd_request_session(p
->p
.pool
, n
->nbr
->addr
, saddr
,
495 n
->nbr
->iface
, rip_bfd_notify
, n
);
498 if (!use_bfd
&& n
->bfd_req
)
511 rip_iface_start(struct rip_iface
*ifa
)
513 struct rip_proto
*p
= ifa
->rip
;
515 TRACE(D_EVENTS
, "Starting interface %s", ifa
->iface
->name
);
517 ifa
->next_regular
= now
+ (random() % ifa
->cf
->update_time
) + 1;
518 ifa
->next_triggered
= now
; /* Available immediately */
519 ifa
->want_triggered
= 1; /* All routes in triggered update */
520 tm_start(ifa
->timer
, 1); /* Or 100 ms */
523 if (!ifa
->cf
->passive
)
524 rip_send_request(ifa
->rip
, ifa
);
528 rip_iface_stop(struct rip_iface
*ifa
)
530 struct rip_proto
*p
= ifa
->rip
;
531 struct rip_neighbor
*n
;
533 TRACE(D_EVENTS
, "Stopping interface %s", ifa
->iface
->name
);
535 rip_reset_tx_session(p
, ifa
);
537 WALK_LIST_FIRST(n
, ifa
->neigh_list
)
538 rip_remove_neighbor(p
, n
);
545 rip_iface_link_up(struct rip_iface
*ifa
)
547 return !ifa
->cf
->check_link
|| (ifa
->iface
->flags
& IF_LINK_UP
);
551 rip_iface_update_state(struct rip_iface
*ifa
)
553 int up
= ifa
->sk
&& rip_iface_link_up(ifa
);
559 rip_iface_start(ifa
);
565 rip_iface_update_buffers(struct rip_iface
*ifa
)
570 uint rbsize
= ifa
->cf
->rx_buffer
?: ifa
->iface
->mtu
;
571 uint tbsize
= ifa
->cf
->tx_length
?: ifa
->iface
->mtu
;
572 rbsize
= MAX(rbsize
, tbsize
);
574 sk_set_rbsize(ifa
->sk
, rbsize
);
575 sk_set_tbsize(ifa
->sk
, tbsize
);
577 uint headers
= (rip_is_v2(ifa
->rip
) ? IP4_HEADER_LENGTH
: IP6_HEADER_LENGTH
) + UDP_HEADER_LENGTH
;
578 ifa
->tx_plen
= tbsize
- headers
;
580 if (ifa
->cf
->auth_type
== RIP_AUTH_CRYPTO
)
581 ifa
->tx_plen
-= RIP_AUTH_TAIL_LENGTH
;
585 rip_iface_update_bfd(struct rip_iface
*ifa
)
587 struct rip_proto
*p
= ifa
->rip
;
588 struct rip_neighbor
*n
;
590 WALK_LIST(n
, ifa
->neigh_list
)
591 rip_update_bfd(p
, n
);
596 rip_iface_locked(struct object_lock
*lock
)
598 struct rip_iface
*ifa
= lock
->data
;
599 struct rip_proto
*p
= ifa
->rip
;
601 if (!rip_open_socket(ifa
))
603 log(L_ERR
"%s: Cannot open socket for %s", p
->p
.name
, ifa
->iface
->name
);
607 rip_iface_update_buffers(ifa
);
608 rip_iface_update_state(ifa
);
612 static struct rip_iface
*
613 rip_find_iface(struct rip_proto
*p
, struct iface
*what
)
615 struct rip_iface
*ifa
;
617 WALK_LIST(ifa
, p
->iface_list
)
618 if (ifa
->iface
== what
)
625 rip_add_iface(struct rip_proto
*p
, struct iface
*iface
, struct rip_iface_config
*ic
)
627 struct rip_iface
*ifa
;
629 TRACE(D_EVENTS
, "Adding interface %s", iface
->name
);
631 ifa
= mb_allocz(p
->p
.pool
, sizeof(struct rip_iface
));
636 if (ipa_nonzero(ic
->address
))
637 ifa
->addr
= ic
->address
;
638 else if (ic
->mode
== RIP_IM_MULTICAST
)
639 ifa
->addr
= rip_is_v2(p
) ? IP4_RIP_ROUTERS
: IP6_RIP_ROUTERS
;
641 ifa
->addr
= iface
->addr
->brd
;
643 init_list(&ifa
->neigh_list
);
645 add_tail(&p
->iface_list
, NODE ifa
);
647 ifa
->timer
= tm_new_set(p
->p
.pool
, rip_iface_timer
, ifa
, 0, 0);
649 struct object_lock
*lock
= olock_new(p
->p
.pool
);
650 lock
->type
= OBJLOCK_UDP
;
651 lock
->port
= ic
->port
;
654 lock
->hook
= rip_iface_locked
;
661 rip_remove_iface(struct rip_proto
*p
, struct rip_iface
*ifa
)
665 TRACE(D_EVENTS
, "Removing interface %s", ifa
->iface
->name
);
677 rip_reconfigure_iface(struct rip_proto
*p
, struct rip_iface
*ifa
, struct rip_iface_config
*new)
679 struct rip_iface_config
*old
= ifa
->cf
;
681 /* Change of these options would require to reset the iface socket */
682 if ((new->mode
!= old
->mode
) ||
683 (new->port
!= old
->port
) ||
684 (new->tx_tos
!= old
->tx_tos
) ||
685 (new->tx_priority
!= old
->tx_priority
) ||
686 (new->ttl_security
!= old
->ttl_security
))
689 TRACE(D_EVENTS
, "Reconfiguring interface %s", ifa
->iface
->name
);
693 if (ifa
->next_regular
> (now
+ new->update_time
))
694 ifa
->next_regular
= now
+ (random() % new->update_time
) + 1;
696 if ((new->tx_length
!= old
->tx_length
) || (new->rx_buffer
!= old
->rx_buffer
))
697 rip_iface_update_buffers(ifa
);
699 if (new->check_link
!= old
->check_link
)
700 rip_iface_update_state(ifa
);
702 if (new->bfd
!= old
->bfd
)
703 rip_iface_update_bfd(ifa
);
706 rip_iface_kick_timer(ifa
);
712 rip_reconfigure_ifaces(struct rip_proto
*p
, struct rip_config
*cf
)
716 WALK_LIST(iface
, iface_list
)
718 if (! (iface
->flags
& IF_UP
))
721 struct rip_iface
*ifa
= rip_find_iface(p
, iface
);
722 struct rip_iface_config
*ic
= (void *) iface_patt_find(&cf
->patt_list
, iface
, NULL
);
726 if (rip_reconfigure_iface(p
, ifa
, ic
))
730 log(L_INFO
"%s: Restarting interface %s", p
->p
.name
, ifa
->iface
->name
);
731 rip_remove_iface(p
, ifa
);
732 rip_add_iface(p
, iface
, ic
);
736 rip_remove_iface(p
, ifa
);
739 rip_add_iface(p
, iface
, ic
);
744 rip_if_notify(struct proto
*P
, unsigned flags
, struct iface
*iface
)
746 struct rip_proto
*p
= (void *) P
;
747 struct rip_config
*cf
= (void *) P
->cf
;
749 if (iface
->flags
& IF_IGNORE
)
752 if (flags
& IF_CHANGE_UP
)
754 struct rip_iface_config
*ic
= (void *) iface_patt_find(&cf
->patt_list
, iface
, NULL
);
757 rip_add_iface(p
, iface
, ic
);
762 struct rip_iface
*ifa
= rip_find_iface(p
, iface
);
767 if (flags
& IF_CHANGE_DOWN
)
769 rip_remove_iface(p
, ifa
);
773 if (flags
& IF_CHANGE_MTU
)
774 rip_iface_update_buffers(ifa
);
776 if (flags
& IF_CHANGE_LINK
)
777 rip_iface_update_state(ifa
);
786 * rip_timer - RIP main timer hook
789 * The RIP main timer is responsible for routing table maintenance. Invalid or
790 * expired routes (&rip_rte) are removed and garbage collection of stale routing
791 * table entries (&rip_entry) is done. Changes are propagated to core tables,
792 * route reload is also done here. Note that garbage collection uses a maximal
793 * GC time, while interfaces maintain an illusion of per-interface GC times in
794 * rip_send_response().
796 * Keeping incoming routes and the selected outgoing route are two independent
797 * functions, therefore after garbage collection some entries now considered
798 * invalid (RIP_ENTRY_DUMMY) still may have non-empty list of incoming routes,
799 * while some valid entries (representing an outgoing route) may have that list
802 * The main timer is not scheduled periodically but it uses the time of the
803 * current next event and the minimal interval of any possible event to compute
804 * the time of the next run.
809 struct rip_proto
*p
= t
->data
;
810 struct rip_config
*cf
= (void *) (p
->p
.cf
);
811 struct rip_iface
*ifa
;
812 struct rip_neighbor
*n
, *nn
;
813 struct fib_iterator fit
;
814 bird_clock_t next
= now
+ MIN(cf
->min_timeout_time
, cf
->max_garbage_time
);
815 bird_clock_t expires
= 0;
817 TRACE(D_EVENTS
, "Main timer fired");
819 FIB_ITERATE_INIT(&fit
, &p
->rtable
);
822 FIB_ITERATE_START(&p
->rtable
, &fit
, struct rip_entry
, en
)
824 struct rip_rte
*rt
, **rp
;
827 /* Checking received routes for timeout and for dead neighbors */
828 for (rp
= &en
->routes
; rt
= *rp
; /* rp = &rt->next */)
830 if (!rip_valid_rte(rt
) || (rt
->expires
<= now
))
832 rip_remove_rte(p
, rp
);
837 next
= MIN(next
, rt
->expires
);
841 /* Propagating eventual change */
842 if (changed
|| p
->rt_reload
)
845 * We have to restart the iteration because there may be a cascade of
846 * synchronous events rip_announce_rte() -> nest table change ->
847 * rip_rt_notify() -> p->rtable change, invalidating hidden variables.
850 FIB_ITERATE_PUT_NEXT(&fit
, &p
->rtable
);
851 rip_announce_rte(p
, en
);
855 /* Checking stale entries for garbage collection timeout */
856 if (en
->valid
== RIP_ENTRY_STALE
)
858 expires
= en
->changed
+ cf
->max_garbage_time
;
862 // TRACE(D_EVENTS, "entry is too old: %N", en->n.addr);
866 next
= MIN(next
, expires
);
869 /* Remove empty nodes */
870 if (!en
->valid
&& !en
->routes
)
872 FIB_ITERATE_PUT(&fit
);
873 fib_delete(&p
->rtable
, en
);
881 /* Handling neighbor expiration */
882 WALK_LIST(ifa
, p
->iface_list
)
883 WALK_LIST_DELSAFE(n
, nn
, ifa
->neigh_list
)
886 expires
= n
->last_seen
+ n
->ifa
->cf
->timeout_time
;
889 rip_remove_neighbor(p
, n
);
891 next
= MIN(next
, expires
);
894 tm_start(p
->timer
, MAX(next
- now
, 1));
898 rip_kick_timer(struct rip_proto
*p
)
900 if (p
->timer
->expires
> (now
+ 1))
901 tm_start(p
->timer
, 1); /* Or 100 ms */
905 * rip_iface_timer - RIP interface timer hook
908 * RIP interface timers are responsible for scheduling both regular and
909 * triggered updates. Fixed, delay-independent period is used for regular
910 * updates, while minimal separating interval is enforced for triggered updates.
911 * The function also ensures that a new update is not started when the old one
915 rip_iface_timer(timer
*t
)
917 struct rip_iface
*ifa
= t
->data
;
918 struct rip_proto
*p
= ifa
->rip
;
919 bird_clock_t period
= ifa
->cf
->update_time
;
921 if (ifa
->cf
->passive
)
924 TRACE(D_EVENTS
, "Interface timer fired for %s", ifa
->iface
->name
);
928 if (now
< (ifa
->next_regular
+ period
))
929 { tm_start(ifa
->timer
, 1); return; }
931 /* We are too late, reset is done by rip_send_table() */
932 log(L_WARN
"%s: Too slow update on %s, resetting", p
->p
.name
, ifa
->iface
->name
);
935 if (now
>= ifa
->next_regular
)
937 /* Send regular update, set timer for next period (or following one if necessay) */
938 TRACE(D_EVENTS
, "Sending regular updates for %s", ifa
->iface
->name
);
939 rip_send_table(p
, ifa
, ifa
->addr
, 0);
940 ifa
->next_regular
+= period
* (1 + ((now
- ifa
->next_regular
) / period
));
941 ifa
->want_triggered
= 0;
944 else if (ifa
->want_triggered
&& (now
>= ifa
->next_triggered
))
946 /* Send triggered update, enforce interval between triggered updates */
947 TRACE(D_EVENTS
, "Sending triggered updates for %s", ifa
->iface
->name
);
948 rip_send_table(p
, ifa
, ifa
->addr
, ifa
->want_triggered
);
949 ifa
->next_triggered
= now
+ MIN(5, period
/ 2 + 1);
950 ifa
->want_triggered
= 0;
954 tm_start(ifa
->timer
, ifa
->want_triggered
? 1 : (ifa
->next_regular
- now
));
958 rip_iface_kick_timer(struct rip_iface
*ifa
)
960 if (ifa
->timer
->expires
> (now
+ 1))
961 tm_start(ifa
->timer
, 1); /* Or 100 ms */
965 rip_trigger_update(struct rip_proto
*p
)
970 struct rip_iface
*ifa
;
971 WALK_LIST(ifa
, p
->iface_list
)
973 /* Interface not active */
977 /* Already scheduled */
978 if (ifa
->want_triggered
)
981 TRACE(D_EVENTS
, "Scheduling triggered updates for %s", ifa
->iface
->name
);
982 ifa
->want_triggered
= now
;
983 rip_iface_kick_timer(ifa
);
994 static struct ea_list
*
995 rip_prepare_attrs(struct linpool
*pool
, ea_list
*next
, u8 metric
, u16 tag
)
997 struct ea_list
*l
= lp_alloc(pool
, sizeof(struct ea_list
) + 2 * sizeof(eattr
));
1000 l
->flags
= EALF_SORTED
;
1003 l
->attrs
[0].id
= EA_RIP_METRIC
;
1004 l
->attrs
[0].flags
= 0;
1005 l
->attrs
[0].type
= EAF_TYPE_INT
| EAF_TEMP
;
1006 l
->attrs
[0].u
.data
= metric
;
1008 l
->attrs
[1].id
= EA_RIP_TAG
;
1009 l
->attrs
[1].flags
= 0;
1010 l
->attrs
[1].type
= EAF_TYPE_INT
| EAF_TEMP
;
1011 l
->attrs
[1].u
.data
= tag
;
1017 rip_import_control(struct proto
*P
, struct rte
**rt
, struct ea_list
**attrs
, struct linpool
*pool
)
1019 /* Prepare attributes with initial values */
1020 if ((*rt
)->attrs
->source
!= RTS_RIP
)
1021 *attrs
= rip_prepare_attrs(pool
, *attrs
, 1, 0);
1027 rip_reload_routes(struct channel
*C
)
1029 struct rip_proto
*p
= (struct rip_proto
*) C
->proto
;
1034 TRACE(D_EVENTS
, "Scheduling route reload");
1039 static struct ea_list
*
1040 rip_make_tmp_attrs(struct rte
*rt
, struct linpool
*pool
)
1042 return rip_prepare_attrs(pool
, NULL
, rt
->u
.rip
.metric
, rt
->u
.rip
.tag
);
1046 rip_store_tmp_attrs(struct rte
*rt
, struct ea_list
*attrs
)
1048 rt
->u
.rip
.metric
= ea_get_int(attrs
, EA_RIP_METRIC
, 1);
1049 rt
->u
.rip
.tag
= ea_get_int(attrs
, EA_RIP_TAG
, 0);
1053 rip_rte_better(struct rte
*new, struct rte
*old
)
1055 return new->u
.rip
.metric
< old
->u
.rip
.metric
;
1059 rip_rte_same(struct rte
*new, struct rte
*old
)
1061 return ((new->u
.rip
.metric
== old
->u
.rip
.metric
) &&
1062 (new->u
.rip
.tag
== old
->u
.rip
.tag
) &&
1063 (new->u
.rip
.from
== old
->u
.rip
.from
));
1068 rip_postconfig(struct proto_config
*CF
)
1070 // struct rip_config *cf = (void *) CF;
1072 /* Define default channel */
1073 if (EMPTY_LIST(CF
->channels
))
1074 channel_config_new(NULL
, CF
->net_type
, CF
);
1077 static struct proto
*
1078 rip_init(struct proto_config
*CF
)
1080 struct proto
*P
= proto_new(CF
);
1082 P
->main_channel
= proto_add_channel(P
, proto_cf_main_channel(CF
));
1084 P
->if_notify
= rip_if_notify
;
1085 P
->rt_notify
= rip_rt_notify
;
1086 P
->neigh_notify
= rip_neigh_notify
;
1087 P
->import_control
= rip_import_control
;
1088 P
->reload_routes
= rip_reload_routes
;
1089 P
->make_tmp_attrs
= rip_make_tmp_attrs
;
1090 P
->store_tmp_attrs
= rip_store_tmp_attrs
;
1091 P
->rte_better
= rip_rte_better
;
1092 P
->rte_same
= rip_rte_same
;
1098 rip_start(struct proto
*P
)
1100 struct rip_proto
*p
= (void *) P
;
1101 struct rip_config
*cf
= (void *) (P
->cf
);
1103 init_list(&p
->iface_list
);
1104 fib_init(&p
->rtable
, P
->pool
, cf
->rip2
? NET_IP4
: NET_IP6
,
1105 sizeof(struct rip_entry
), OFFSETOF(struct rip_entry
, n
), 0, NULL
);
1106 p
->rte_slab
= sl_new(P
->pool
, sizeof(struct rip_rte
));
1107 p
->timer
= tm_new_set(P
->pool
, rip_timer
, p
, 0, 0);
1111 p
->infinity
= cf
->infinity
;
1114 p
->log_pkt_tbf
= (struct tbf
){ .rate
= 1, .burst
= 5 };
1115 p
->log_rte_tbf
= (struct tbf
){ .rate
= 4, .burst
= 20 };
1117 tm_start(p
->timer
, MIN(cf
->min_timeout_time
, cf
->max_garbage_time
));
1123 rip_reconfigure(struct proto
*P
, struct proto_config
*CF
)
1125 struct rip_proto
*p
= (void *) P
;
1126 struct rip_config
*new = (void *) CF
;
1127 // struct rip_config *old = (void *) (P->cf);
1129 if (new->rip2
!= p
->rip2
)
1132 if (new->infinity
!= p
->infinity
)
1135 if (!proto_configure_channel(P
, &P
->main_channel
, proto_cf_main_channel(CF
)))
1138 TRACE(D_EVENTS
, "Reconfiguring");
1141 p
->ecmp
= new->ecmp
;
1142 rip_reconfigure_ifaces(p
, new);
1151 rip_get_route_info(rte
*rte
, byte
*buf
, ea_list
*attrs
)
1153 buf
+= bsprintf(buf
, " (%d/%d)", rte
->pref
, rte
->u
.rip
.metric
);
1156 bsprintf(buf
, " [%04x]", rte
->u
.rip
.tag
);
1160 rip_get_attr(eattr
*a
, byte
*buf
, int buflen UNUSED
)
1165 bsprintf(buf
, "metric: %d", a
->u
.data
);
1169 bsprintf(buf
, "tag: %04x", a
->u
.data
);
1178 rip_show_interfaces(struct proto
*P
, char *iff
)
1180 struct rip_proto
*p
= (void *) P
;
1181 struct rip_iface
*ifa
= NULL
;
1182 struct rip_neighbor
*n
= NULL
;
1184 if (p
->p
.proto_state
!= PS_UP
)
1186 cli_msg(-1021, "%s: is not up", p
->p
.name
);
1191 cli_msg(-1021, "%s:", p
->p
.name
);
1192 cli_msg(-1021, "%-10s %-6s %6s %6s %6s",
1193 "Interface", "State", "Metric", "Nbrs", "Timer");
1195 WALK_LIST(ifa
, p
->iface_list
)
1197 if (iff
&& !patmatch(iff
, ifa
->iface
->name
))
1201 WALK_LIST(n
, ifa
->neigh_list
)
1205 int timer
= MAX(ifa
->next_regular
- now
, 0);
1206 cli_msg(-1021, "%-10s %-6s %6u %6u %6u",
1207 ifa
->iface
->name
, (ifa
->up
? "Up" : "Down"), ifa
->cf
->metric
, nbrs
, timer
);
1214 rip_show_neighbors(struct proto
*P
, char *iff
)
1216 struct rip_proto
*p
= (void *) P
;
1217 struct rip_iface
*ifa
= NULL
;
1218 struct rip_neighbor
*n
= NULL
;
1220 if (p
->p
.proto_state
!= PS_UP
)
1222 cli_msg(-1022, "%s: is not up", p
->p
.name
);
1227 cli_msg(-1022, "%s:", p
->p
.name
);
1228 cli_msg(-1022, "%-25s %-10s %6s %6s %6s",
1229 "IP address", "Interface", "Metric", "Routes", "Seen");
1231 WALK_LIST(ifa
, p
->iface_list
)
1233 if (iff
&& !patmatch(iff
, ifa
->iface
->name
))
1236 WALK_LIST(n
, ifa
->neigh_list
)
1241 int timer
= now
- n
->last_seen
;
1242 cli_msg(-1022, "%-25I %-10s %6u %6u %6u",
1243 n
->nbr
->addr
, ifa
->iface
->name
, ifa
->cf
->metric
, n
->uc
, timer
);
1251 rip_dump(struct proto
*P
)
1253 struct rip_proto
*p
= (struct rip_proto
*) P
;
1254 struct rip_iface
*ifa
;
1258 FIB_WALK(&p
->rtable
, struct rip_entry
, en
)
1260 debug("RIP: entry #%d: %N via %I dev %s valid %d metric %d age %d s\n",
1261 i
++, en
->n
.addr
, en
->next_hop
, en
->iface
->name
,
1262 en
->valid
, en
->metric
, now
- en
->changed
);
1267 WALK_LIST(ifa
, p
->iface_list
)
1269 debug("RIP: interface #%d: %s, %I, up = %d, busy = %d\n",
1270 i
++, ifa
->iface
->name
, ifa
->sk
? ifa
->sk
->daddr
: IPA_NONE
,
1271 ifa
->up
, ifa
->tx_active
);
1276 struct protocol proto_rip
= {
1278 .template = "rip%d",
1279 .attr_class
= EAP_RIP
,
1280 .preference
= DEF_PREF_RIP
,
1281 .channel_mask
= NB_IP
,
1282 .proto_size
= sizeof(struct rip_proto
),
1283 .config_size
= sizeof(struct rip_config
),
1284 .postconfig
= rip_postconfig
,
1288 .reconfigure
= rip_reconfigure
,
1289 .get_route_info
= rip_get_route_info
,
1290 .get_attr
= rip_get_attr