KRT: Fixes learning of preferred kernel routes.

When a new route was imported from kernel and chosen as preferred, then
the old best route was propagated as a withdraw to the kernel protocol.
Under some circumstances such withdraw propagated to the BSD kernel could
remove the new alien route and thus reverting the import.
This commit is contained in:
Ondrej Zajicek 2015-04-25 20:43:43 +02:00
parent 90097f4fb9
commit c5ff44a703
4 changed files with 17 additions and 0 deletions

View file

@ -5,6 +5,7 @@ CONFIG_AUTO_ROUTES Device routes are added automagically by the kernel
CONFIG_SELF_CONSCIOUS We're able to recognize whether route was installed by us
CONFIG_MULTIPLE_TABLES The kernel supports multiple routing tables
CONFIG_ALL_TABLES_AT_ONCE Kernel scanner wants to process all tables at once
CONFIG_SINGLE_ROUTE There is only one route per network
CONFIG_MC_PROPER_SRC Multicast packets have source address according to socket saddr field
CONFIG_SKIP_MC_BIND Don't call bind on multicast socket (def for *BSD)

View file

@ -11,6 +11,7 @@
#define CONFIG_AUTO_ROUTES
#define CONFIG_SELF_CONSCIOUS
#define CONFIG_MULTIPLE_TABLES
#define CONFIG_SINGLE_ROUTE
#define CONFIG_SKIP_MC_BIND
#define CONFIG_NO_IFACE_BIND

View file

@ -9,6 +9,7 @@
#define CONFIG_AUTO_ROUTES
#define CONFIG_SELF_CONSCIOUS
#define CONFIG_MULTIPLE_TABLES
#define CONFIG_SINGLE_ROUTE
#define CONFIG_SKIP_MC_BIND
#define CONFIG_NO_IFACE_BIND

View file

@ -961,7 +961,21 @@ krt_import_control(struct proto *P, rte **new, ea_list **attrs, struct linpool *
rte *e = *new;
if (e->attrs->src->proto == P)
{
#ifdef CONFIG_SINGLE_ROUTE
/*
* Implicit withdraw - when the imported kernel route becomes the best one,
* we know that the previous one exported to the kernel was already removed,
* but if we processed the update as usual, we would send withdraw to the
* kernel, which would remove the new imported route instead.
*
* We will remove KRT_INSTALLED flag, which stops such withdraw to be
* processed in krt_rt_notify() and krt_replace_rte().
*/
e->net->n.flags &= ~KRF_INSTALLED;
#endif
return -1;
}
if (!KRT_CF->devroutes &&
(e->attrs->dest == RTD_DEVICE) &&