KRT: Fixes some minor bugs in kernel protocol
This commit is contained in:
parent
d217ba5111
commit
78a2cc289f
2 changed files with 71 additions and 41 deletions
|
@ -703,6 +703,11 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int new)
|
||||||
r.r.rtm_scope = RT_SCOPE_UNIVERSE;
|
r.r.rtm_scope = RT_SCOPE_UNIVERSE;
|
||||||
nl_add_attr_ipa(&r.h, sizeof(r), RTA_DST, net->n.prefix);
|
nl_add_attr_ipa(&r.h, sizeof(r), RTA_DST, net->n.prefix);
|
||||||
|
|
||||||
|
/* For route delete, we do not specify route attributes */
|
||||||
|
if (!new)
|
||||||
|
return nl_exchange(&r.h);
|
||||||
|
|
||||||
|
|
||||||
if (ea = ea_find(eattrs, EA_KRT_METRIC))
|
if (ea = ea_find(eattrs, EA_KRT_METRIC))
|
||||||
nl_add_attr_u32(&r.h, sizeof(r), RTA_PRIORITY, ea->u.data);
|
nl_add_attr_u32(&r.h, sizeof(r), RTA_PRIORITY, ea->u.data);
|
||||||
|
|
||||||
|
|
|
@ -592,6 +592,44 @@ krt_flush_routes(struct krt_proto *p)
|
||||||
FIB_WALK_END;
|
FIB_WALK_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct rte *
|
||||||
|
krt_export_net(struct krt_proto *p, net *net, rte **rt_free, ea_list **tmpa)
|
||||||
|
{
|
||||||
|
struct filter *filter = p->p.main_ahook->out_filter;
|
||||||
|
rte *rt;
|
||||||
|
|
||||||
|
rt = net->routes;
|
||||||
|
*rt_free = NULL;
|
||||||
|
|
||||||
|
if (!rte_is_valid(rt))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (filter == FILTER_REJECT)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
struct proto *src = rt->attrs->src->proto;
|
||||||
|
*tmpa = src->make_tmp_attrs ? src->make_tmp_attrs(rt, krt_filter_lp) : NULL;
|
||||||
|
|
||||||
|
/* We could run krt_import_control() here, but it is already handled by KRF_INSTALLED */
|
||||||
|
|
||||||
|
if (filter == FILTER_ACCEPT)
|
||||||
|
goto accept;
|
||||||
|
|
||||||
|
if (f_run(filter, &rt, tmpa, krt_filter_lp, FF_FORCE_TMPATTR) > F_ACCEPT)
|
||||||
|
goto reject;
|
||||||
|
|
||||||
|
|
||||||
|
accept:
|
||||||
|
if (rt != net->routes)
|
||||||
|
*rt_free = rt;
|
||||||
|
return rt;
|
||||||
|
|
||||||
|
reject:
|
||||||
|
if (rt != net->routes)
|
||||||
|
rte_free(rt);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
krt_same_dest(rte *k, rte *e)
|
krt_same_dest(rte *k, rte *e)
|
||||||
{
|
{
|
||||||
|
@ -620,7 +658,6 @@ krt_same_dest(rte *k, rte *e)
|
||||||
void
|
void
|
||||||
krt_got_route(struct krt_proto *p, rte *e)
|
krt_got_route(struct krt_proto *p, rte *e)
|
||||||
{
|
{
|
||||||
rte *old;
|
|
||||||
net *net = e->net;
|
net *net = e->net;
|
||||||
int verdict;
|
int verdict;
|
||||||
|
|
||||||
|
@ -663,15 +700,26 @@ krt_got_route(struct krt_proto *p, rte *e)
|
||||||
goto sentenced;
|
goto sentenced;
|
||||||
}
|
}
|
||||||
|
|
||||||
old = net->routes;
|
if (net->n.flags & KRF_INSTALLED)
|
||||||
if ((net->n.flags & KRF_INSTALLED) && rte_is_valid(old))
|
|
||||||
{
|
{
|
||||||
/* There may be changes in route attributes, we ignore that.
|
rte *new, *rt_free;
|
||||||
Also, this does not work well if gw is changed in export filter */
|
ea_list *tmpa;
|
||||||
if ((net->n.flags & KRF_SYNC_ERROR) || ! krt_same_dest(e, old))
|
|
||||||
|
new = krt_export_net(p, net, &rt_free, &tmpa);
|
||||||
|
|
||||||
|
/* TODO: There also may be changes in route eattrs, we ignore that for now. */
|
||||||
|
|
||||||
|
if (!new)
|
||||||
|
verdict = KRF_DELETE;
|
||||||
|
else if ((net->n.flags & KRF_SYNC_ERROR) || !krt_same_dest(e, new))
|
||||||
verdict = KRF_UPDATE;
|
verdict = KRF_UPDATE;
|
||||||
else
|
else
|
||||||
verdict = KRF_SEEN;
|
verdict = KRF_SEEN;
|
||||||
|
|
||||||
|
if (rt_free)
|
||||||
|
rte_free(rt_free);
|
||||||
|
|
||||||
|
lp_flush(krt_filter_lp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
verdict = KRF_DELETE;
|
verdict = KRF_DELETE;
|
||||||
|
@ -692,25 +740,6 @@ krt_got_route(struct krt_proto *p, rte *e)
|
||||||
rte_free(e);
|
rte_free(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
|
||||||
krt_export_rte(struct krt_proto *p, rte **new, ea_list **tmpa)
|
|
||||||
{
|
|
||||||
struct filter *filter = p->p.main_ahook->out_filter;
|
|
||||||
|
|
||||||
if (! *new)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (filter == FILTER_REJECT)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (filter == FILTER_ACCEPT)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
struct proto *src = (*new)->attrs->src->proto;
|
|
||||||
*tmpa = src->make_tmp_attrs ? src->make_tmp_attrs(*new, krt_filter_lp) : NULL;
|
|
||||||
return f_run(filter, new, tmpa, krt_filter_lp, FF_FORCE_TMPATTR) <= F_ACCEPT;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
krt_prune(struct krt_proto *p)
|
krt_prune(struct krt_proto *p)
|
||||||
{
|
{
|
||||||
|
@ -721,7 +750,7 @@ krt_prune(struct krt_proto *p)
|
||||||
{
|
{
|
||||||
net *n = (net *) f;
|
net *n = (net *) f;
|
||||||
int verdict = f->flags & KRF_VERDICT_MASK;
|
int verdict = f->flags & KRF_VERDICT_MASK;
|
||||||
rte *new, *new0, *old;
|
rte *new, *old, *rt_free = NULL;
|
||||||
ea_list *tmpa = NULL;
|
ea_list *tmpa = NULL;
|
||||||
|
|
||||||
if (verdict == KRF_UPDATE || verdict == KRF_DELETE)
|
if (verdict == KRF_UPDATE || verdict == KRF_DELETE)
|
||||||
|
@ -733,23 +762,18 @@ krt_prune(struct krt_proto *p)
|
||||||
else
|
else
|
||||||
old = NULL;
|
old = NULL;
|
||||||
|
|
||||||
new = new0 = n->routes;
|
|
||||||
if (verdict == KRF_CREATE || verdict == KRF_UPDATE)
|
if (verdict == KRF_CREATE || verdict == KRF_UPDATE)
|
||||||
{
|
{
|
||||||
/* We have to run export filter to get proper 'new' route */
|
/* We have to run export filter to get proper 'new' route */
|
||||||
if (! krt_export_rte(p, &new, &tmpa))
|
new = krt_export_net(p, n, &rt_free, &tmpa);
|
||||||
{
|
|
||||||
/* Route rejected, should not happen (KRF_INSTALLED) but to be sure .. */
|
if (!new)
|
||||||
verdict = (verdict == KRF_CREATE) ? KRF_IGNORE : KRF_DELETE;
|
verdict = (verdict == KRF_CREATE) ? KRF_IGNORE : KRF_DELETE;
|
||||||
|
else
|
||||||
|
tmpa = ea_append(tmpa, new->attrs->eattrs);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
new = NULL;
|
||||||
ea_list **x = &tmpa;
|
|
||||||
while (*x)
|
|
||||||
x = &((*x)->next);
|
|
||||||
*x = new ? new->attrs->eattrs : NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (verdict)
|
switch (verdict)
|
||||||
{
|
{
|
||||||
|
@ -778,8 +802,8 @@ krt_prune(struct krt_proto *p)
|
||||||
|
|
||||||
if (old)
|
if (old)
|
||||||
rte_free(old);
|
rte_free(old);
|
||||||
if (new != new0)
|
if (rt_free)
|
||||||
rte_free(new);
|
rte_free(rt_free);
|
||||||
lp_flush(krt_filter_lp);
|
lp_flush(krt_filter_lp);
|
||||||
f->flags &= ~KRF_VERDICT_MASK;
|
f->flags &= ~KRF_VERDICT_MASK;
|
||||||
}
|
}
|
||||||
|
@ -974,6 +998,7 @@ krt_import_control(struct proto *P, rte **new, ea_list **attrs, struct linpool *
|
||||||
* We will remove KRT_INSTALLED flag, which stops such withdraw to be
|
* We will remove KRT_INSTALLED flag, which stops such withdraw to be
|
||||||
* processed in krt_rt_notify() and krt_replace_rte().
|
* processed in krt_rt_notify() and krt_replace_rte().
|
||||||
*/
|
*/
|
||||||
|
if (e == e->net->routes)
|
||||||
e->net->n.flags &= ~KRF_INSTALLED;
|
e->net->n.flags &= ~KRF_INSTALLED;
|
||||||
#endif
|
#endif
|
||||||
return -1;
|
return -1;
|
||||||
|
|
Loading…
Reference in a new issue