if (rt)
{
/* Update */
- net *n = net_get(p->p.table, en->n.addr);
-
rta a0 = {
.src = p->p.main_source,
.source = RTS_RIP,
.scope = SCOPE_UNIVERSE,
- .cast = RTC_UNICAST
+ .dest = RTD_UNICAST,
};
u8 rt_metric = rt->metric;
u16 rt_tag = rt->tag;
- struct rip_rte *rt2 = rt->next;
-
- /* Find second valid rte */
- while (rt2 && !rip_valid_rte(rt2))
- rt2 = rt2->next;
- if (p->ecmp && rt2)
+ if (p->ecmp)
{
/* ECMP route */
- struct mpnh *nhs = NULL;
- struct mpnh **nhp = &nhs;
+ struct nexthop *nhs = NULL;
int num = 0;
for (rt = en->routes; rt && (num < p->ecmp); rt = rt->next)
if (!rip_valid_rte(rt))
continue;
- struct mpnh *nh = alloca(sizeof(struct mpnh));
+ struct nexthop *nh = allocz(sizeof(struct nexthop));
+
nh->gw = rt->next_hop;
nh->iface = rt->from->nbr->iface;
nh->weight = rt->from->ifa->cf->ecmp_weight;
- nh->next = NULL;
- *nhp = nh;
- nhp = &(nh->next);
+
+ nexthop_insert(&nhs, nh);
num++;
if (rt->tag != rt_tag)
rt_tag = 0;
}
- a0.dest = RTD_MULTIPATH;
- a0.nexthops = nhs;
+ a0.nh = *nhs;
}
else
{
/* Unipath route */
- a0.dest = RTD_ROUTER;
- a0.gw = rt->next_hop;
- a0.iface = rt->from->nbr->iface;
a0.from = rt->from->nbr->addr;
+ a0.nh.gw = rt->next_hop;
+ a0.nh.iface = rt->from->nbr->iface;
}
rta *a = rta_lookup(&a0);
rte *e = rte_get_temp(a);
- e->u.rip.from = a0.iface;
+ e->u.rip.from = a0.nh.iface;
e->u.rip.metric = rt_metric;
e->u.rip.tag = rt_tag;
- e->net = n;
e->pflags = 0;
- rte_update(&p->p, n, e);
+ rte_update(&p->p, en->n.addr, e);
}
else
{
/* Withdraw */
- net *n = net_find(p->p.table, en->n.addr);
- rte_update(&p->p, n, NULL);
+ rte_update(&p->p, en->n.addr, NULL);
}
}
* it into our data structures.
*/
static void
-rip_rt_notify(struct proto *P, struct rtable *table UNUSED, struct network *net, struct rte *new,
+rip_rt_notify(struct proto *P, struct channel *ch UNUSED, struct network *net, struct rte *new,
struct rte *old UNUSED, struct ea_list *attrs)
{
struct rip_proto *p = (struct rip_proto *) P;
en->metric = rt_metric;
en->tag = rt_tag;
en->from = (new->attrs->src->proto == P) ? new->u.rip.from : NULL;
- en->iface = new->attrs->iface;
- en->next_hop = new->attrs->gw;
+ en->iface = new->attrs->nh.iface;
+ en->next_hop = new->attrs->nh.gw;
}
else
{
ifa->tx_plen = tbsize - headers;
if (ifa->cf->auth_type == RIP_AUTH_CRYPTO)
- ifa->tx_plen -= RIP_AUTH_TAIL_LENGTH;
+ ifa->tx_plen -= RIP_AUTH_TAIL_LENGTH + max_mac_length(ifa->cf->passwords);
}
static inline void
ifa->cf = new;
- if (ifa->next_regular > (now + new->update_time))
- ifa->next_regular = now + (random() % new->update_time) + 1;
+ rip_iface_update_buffers(ifa);
- if ((new->tx_length != old->tx_length) || (new->rx_buffer != old->rx_buffer))
- rip_iface_update_buffers(ifa);
+ if (ifa->next_regular > (now + (bird_clock_t) new->update_time))
+ ifa->next_regular = now + (random() % new->update_time) + 1;
if (new->check_link != old->check_link)
rip_iface_update_state(ifa);
FIB_ITERATE_INIT(&fit, &p->rtable);
loop:
- FIB_ITERATE_START(&p->rtable, &fit, node)
+ FIB_ITERATE_START(&p->rtable, &fit, struct rip_entry, en)
{
- struct rip_entry *en = (struct rip_entry *) node;
struct rip_rte *rt, **rp;
int changed = 0;
* rip_rt_notify() -> p->rtable change, invalidating hidden variables.
*/
- FIB_ITERATE_PUT_NEXT(&fit, &p->rtable, node);
+ FIB_ITERATE_PUT_NEXT(&fit, &p->rtable);
rip_announce_rte(p, en);
goto loop;
}
/* Remove empty nodes */
if (!en->valid && !en->routes)
{
- FIB_ITERATE_PUT(&fit, node);
- fib_delete(&p->rtable, node);
+ FIB_ITERATE_PUT(&fit);
+ fib_delete(&p->rtable, en);
goto loop;
}
}
- FIB_ITERATE_END(node);
+ FIB_ITERATE_END;
p->rt_reload = 0;
}
static int
-rip_import_control(struct proto *P, struct rte **rt, struct ea_list **attrs, struct linpool *pool)
+rip_import_control(struct proto *P UNUSED, struct rte **rt, struct ea_list **attrs, struct linpool *pool)
{
/* Prepare attributes with initial values */
if ((*rt)->attrs->source != RTS_RIP)
return 0;
}
-static int
-rip_reload_routes(struct proto *P)
+static void
+rip_reload_routes(struct channel *C)
{
- struct rip_proto *p = (struct rip_proto *) P;
+ struct rip_proto *p = (struct rip_proto *) C->proto;
if (p->rt_reload)
- return 1;
+ return;
TRACE(D_EVENTS, "Scheduling route reload");
p->rt_reload = 1;
rip_kick_timer(p);
-
- return 1;
}
static struct ea_list *
}
+static void
+rip_postconfig(struct proto_config *CF)
+{
+ // struct rip_config *cf = (void *) CF;
+
+ /* Define default channel */
+ if (EMPTY_LIST(CF->channels))
+ channel_config_new(NULL, CF->net_type, CF);
+}
+
static struct proto *
-rip_init(struct proto_config *cfg)
+rip_init(struct proto_config *CF)
{
- struct proto *P = proto_new(cfg, sizeof(struct rip_proto));
+ struct proto *P = proto_new(CF);
+
+ P->main_channel = proto_add_channel(P, proto_cf_main_channel(CF));
- P->accept_ra_types = RA_OPTIMAL;
P->if_notify = rip_if_notify;
P->rt_notify = rip_rt_notify;
P->neigh_notify = rip_neigh_notify;
}
static int
-rip_reconfigure(struct proto *P, struct proto_config *c)
+rip_reconfigure(struct proto *P, struct proto_config *CF)
{
struct rip_proto *p = (void *) P;
- struct rip_config *new = (void *) c;
+ struct rip_config *new = (void *) CF;
// struct rip_config *old = (void *) (P->cf);
if (new->rip2 != p->rip2)
if (new->infinity != p->infinity)
return 0;
+ if (!proto_configure_channel(P, &P->main_channel, proto_cf_main_channel(CF)))
+ return 0;
+
TRACE(D_EVENTS, "Reconfiguring");
- p->p.cf = c;
+ p->p.cf = CF;
p->ecmp = new->ecmp;
rip_reconfigure_ifaces(p, new);
}
static void
-rip_get_route_info(rte *rte, byte *buf, ea_list *attrs)
+rip_get_route_info(rte *rte, byte *buf, ea_list *attrs UNUSED)
{
buf += bsprintf(buf, " (%d/%d)", rte->pref, rte->u.rip.metric);
int i;
i = 0;
- FIB_WALK(&p->rtable, e)
+ FIB_WALK(&p->rtable, struct rip_entry, en)
{
- struct rip_entry *en = (struct rip_entry *) e;
debug("RIP: entry #%d: %N via %I dev %s valid %d metric %d age %d s\n",
i++, en->n.addr, en->next_hop, en->iface->name,
en->valid, en->metric, now - en->changed);
.template = "rip%d",
.attr_class = EAP_RIP,
.preference = DEF_PREF_RIP,
+ .channel_mask = NB_IP,
+ .proto_size = sizeof(struct rip_proto),
.config_size = sizeof(struct rip_config),
+ .postconfig = rip_postconfig,
.init = rip_init,
.dump = rip_dump,
.start = rip_start,