net *net = net_get(p->p.main_channel->table, n);
- if (s->net && !nl_mergable_route(s, net, p, priority, i->rtm_type, i->rtm_family))
- nl_announce_route(s);
-
rta *ra = lp_allocz(s->pool, RTA_MAX_SIZE);
- ra->src = p->p.main_source;
ra->source = RTS_INHERIT;
ra->scope = SCOPE_UNIVERSE;
++ {
++ ea_list *ea = lp_alloc(s->pool, sizeof(ea_list) + 2 * sizeof(eattr));
++ *ea = (ea_list) { .flags = EALF_SORTED, .count = 2 };
++ ea->next = ra->eattrs;
++ ra->eattrs = ea;
++
++ ea->attrs[0] = (eattr) {
++ .id = EA_KRT_SOURCE,
++ .type = EAF_TYPE_INT,
++ .u.data = i->rtm_protocol
++ };
++
++ ea->attrs[1] = (eattr) {
++ .id = EA_KRT_METRIC,
++ .type = EAF_TYPE_INT,
++ .u.data = priority,
++ };
++ }
++
if (a[RTA_FLOW])
s->rta_flow = rta_get_u32(a[RTA_FLOW]);
else
}
}
- /*
- * Ideally, now we would send the received route to the rest of kernel code.
- * But IPv6 ECMP routes before 4.11 are sent as a sequence of routes, so we
- * postpone it and merge next hops until the end of the sequence. Note that
- * when doing merging of next hops, we expect the new route to be unipath.
- * Otherwise, we ignore additional next hops in nexthop_insert().
- */
- rte *e = rte_get_temp(ra);
++ rte *e = rte_get_temp(ra, p->p.main_source);
+ e->net = net;
- e->u.krt.src = krt_src;
- e->u.krt.proto = i->rtm_protocol;
- e->u.krt.seen = 0;
- e->u.krt.best = 0;
- e->u.krt.metric = priority;
- if (!s->net)
- {
- /* Store the new route */
- s->net = net;
- s->attrs = ra;
- s->proto = p;
- s->new = new;
- s->krt_src = krt_src;
- s->krt_type = i->rtm_type;
- s->krt_proto = i->rtm_protocol;
- s->krt_metric = priority;
- }
+ if (s->scan)
- krt_got_route(p, e);
++ krt_got_route(p, e, krt_src);
else
- {
- /* Merge next hops with the stored route */
- rta *oa = s->attrs;
- krt_got_route_async(p, e, new);
++ krt_got_route_async(p, e, new, krt_src);
- struct nexthop *nhs = &oa->nh;
- nexthop_insert(&nhs, &ra->nh);
-
- /* Perhaps new nexthop is inserted at the first position */
- if (nhs == &ra->nh)
- {
- /* Swap rtas */
- s->attrs = ra;
-
- /* Keep old eattrs */
- ra->eattrs = oa->eattrs;
- }
- }
+ lp_flush(s->pool);
}
void
struct proto_config * kif_init_config(int class);
void kif_request_scan(void);
-void krt_got_route(struct krt_proto *p, struct rte *e);
-void krt_got_route_async(struct krt_proto *p, struct rte *e, int new);
+ void krt_use_shared_scan(void);
+void krt_got_route(struct krt_proto *p, struct rte *e, s8 src);
+void krt_got_route_async(struct krt_proto *p, struct rte *e, int new, s8 src);
static inline int
krt_get_sync_error(struct krt_proto *p, struct rte *e)