0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-21 09:11:54 +00:00

Netlink: Handle onlink flag on BSD-Netlink

On BSD, the onlink flag is not tracked or reported by kernel. We are
using an heuristic that assigns the onlink flag to routes scanned from
the kernel. We should use the same heuristic even in BSD-Netlink
case, as the onlink flag is not reported here too.

Thanks to Björn König for the original patch.
This commit is contained in:
Ondrej Zajicek 2024-12-12 04:04:07 +01:00
parent 38a422d489
commit e0ed978e75
7 changed files with 38 additions and 24 deletions

View File

@ -394,30 +394,6 @@ krt_replace_rte(struct krt_proto *p, net *n UNUSED, rte *new, rte *old)
}
}
/**
* krt_assume_onlink - check if routes on interface are considered onlink
* @iface: The interface of the next hop
* @ipv6: Switch to only consider IPv6 or IPv4 addresses.
*
* The BSD kernel does not support an onlink flag. If the interface has only
* host addresses configured, all routes should be considered as onlink and
* the function returns 1.
*/
static int
krt_assume_onlink(struct iface *iface, int ipv6)
{
const u8 type = ipv6 ? NET_IP6 : NET_IP4;
struct ifa *ifa;
WALK_LIST(ifa, iface->addrs)
{
if ((ifa->prefix.type == type) && !(ifa->flags & IA_HOST))
return 0;
}
return 1;
}
#define SKIP(ARG...) do { DBG("KRT: Ignoring route - " ARG); return; } while(0)
static void

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_SINGLE_ROUTE There is only one route per network
CONFIG_ASSUME_ONLINK Assume ONLINK flag on scanned routes based on a heuristic
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

@ -10,6 +10,7 @@
#define CONFIG_SELF_CONSCIOUS
#define CONFIG_MULTIPLE_TABLES
#define CONFIG_SINGLE_ROUTE
#define CONFIG_ASSUME_ONLINK
#define CONFIG_SKIP_MC_BIND
#define CONFIG_NO_IFACE_BIND

View File

@ -10,6 +10,7 @@
#define CONFIG_SELF_CONSCIOUS
#define CONFIG_MULTIPLE_TABLES
#define CONFIG_SINGLE_ROUTE
#define CONFIG_ASSUME_ONLINK
#define CONFIG_SKIP_MC_BIND
#define CONFIG_NO_IFACE_BIND

View File

@ -788,6 +788,11 @@ nl_parse_multipath(struct nl_parse_state *s, struct krt_proto *p, const net_addr
if (ipa_nonzero(rv->gw))
{
#ifdef CONFIG_ASSUME_ONLINK
if (krt_assume_onlink(rv->iface, ipa_is_ip6(rv->gw)))
rv->flags |= RNF_ONLINK;
#endif
neighbor *nbr;
nbr = neigh_find(&p->p, rv->gw, rv->iface,
(rv->flags & RNF_ONLINK) ? NEF_ONLINK : 0);
@ -1739,6 +1744,11 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
if ((i->rtm_family == AF_INET6) && ipa_in_netX(ra->nh.gw, (net_addr *) &sit))
return;
#ifdef CONFIG_ASSUME_ONLINK
if (krt_assume_onlink(ra->nh.iface, ipa_is_ip6(ra->nh.gw)))
ra->nh.flags |= RNF_ONLINK;
#endif
neighbor *nbr;
nbr = neigh_find(&p->p, ra->nh.gw, ra->nh.iface,
(ra->nh.flags & RNF_ONLINK) ? NEF_ONLINK : 0);

View File

@ -909,6 +909,30 @@ krt_scan_timer_kick(struct krt_proto *p)
tm_start(p->scan_timer, 0);
}
/**
* krt_assume_onlink - check if routes on interface are considered onlink
* @iface: The interface of the next hop
* @ipv6: Switch to only consider IPv6 or IPv4 addresses.
*
* The BSD kernel does not support an onlink flag. If the interface has only
* host addresses configured, all routes should be considered as onlink and
* the function returns 1. This is used when CONFIG_ASSUME_ONLINK is set.
*/
int
krt_assume_onlink(struct iface *iface, int ipv6)
{
const u8 type = ipv6 ? NET_IP6 : NET_IP4;
struct ifa *ifa;
WALK_LIST(ifa, iface->addrs)
{
if ((ifa->prefix.type == type) && !(ifa->flags & IA_HOST))
return 0;
}
return 1;
}
/*
* Updates

View File

@ -83,6 +83,7 @@ void kif_request_scan(void);
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);
int krt_assume_onlink(struct iface *iface, int ipv6);
static inline int
krt_get_sync_error(struct krt_proto *p, struct rte *e)