2
0
mirror of https://github.com/openvswitch/ovs synced 2025-09-01 06:45:17 +00:00

rtnetlink: ignore IFLA_WIRELESS events.

Some older wireless drivers - ones relying on the
old and long deprecated wireless extension ioctl
system - can generate quite a bit of IFLA_WIRELESS
events depending on their configuration and
runtime conditions. These are delivered as
RTNLGRP_LINK via RTM_NEWLINK messages.

These tend to be relatively easily identifiable
because they report the change mask being 0. This
isn't guaranteed but in practice it shouldn't be a
problem. None of the wireless events that I ever
observed actually carry any unique information
about netdev states that ovs-vswitchd is
interested in. Hence ignoring these shouldn't
cause any problems.

These events can be responsible for a significant
CPU churn as ovs-vswitchd attempts to do plenty of
work for each and every netlink message regardless
of what that message carries. On low-end devices
such as consumer-grade routers these can lead to a
lot of CPU cycles being wasted, adding up to heat
output and reducing performance.

It could be argued that wireless drivers in
question should be fixed, but that isn't exactly a
trivial thing to do. Patching ovs seems far more
viable while still making sense.

Signed-off-by: Michal Kazior <michal@plume.com>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
This commit is contained in:
Michal Kazior
2021-03-04 15:32:54 +00:00
committed by Ilya Maximets
parent f9d3039039
commit d90b4f2928
5 changed files with 35 additions and 2 deletions

View File

@@ -26,9 +26,14 @@ struct if_notifier {
};
static void
if_notifier_cb(const struct rtnetlink_change *change OVS_UNUSED, void *aux)
if_notifier_cb(const struct rtnetlink_change *change, void *aux)
{
struct if_notifier *notifier;
if (change && change->irrelevant) {
return;
}
notifier = aux;
notifier->cb(notifier->aux);
}

View File

@@ -742,7 +742,7 @@ netdev_linux_run(const struct netdev_class *netdev_class OVS_UNUSED)
if (!error) {
struct rtnetlink_change change;
if (rtnetlink_parse(&buf, &change)) {
if (rtnetlink_parse(&buf, &change) && !change.irrelevant) {
struct netdev *netdev_ = NULL;
char dev_name[IFNAMSIZ];
@@ -6344,6 +6344,7 @@ netdev_linux_update_via_netlink(struct netdev_linux *netdev)
}
if (rtnetlink_parse(reply, change)
&& !change->irrelevant
&& change->nlmsg_type == RTM_NEWLINK) {
bool changed = false;
error = 0;

View File

@@ -342,6 +342,10 @@ static void
name_table_change(const struct rtnetlink_change *change,
void *aux OVS_UNUSED)
{
if (change && change->irrelevant) {
return;
}
/* Changes to interface status can cause routing table changes that some
* versions of the linux kernel do not advertise for some reason. */
route_table_valid = false;

View File

@@ -88,6 +88,8 @@ rtnetlink_parse(struct ofpbuf *buf, struct rtnetlink_change *change)
const struct nlmsghdr *nlmsg = buf->data;
bool parsed = false;
change->irrelevant = false;
if (rtnetlink_type_is_rtnlgrp_link(nlmsg->nlmsg_type)) {
/* Policy for RTNLGRP_LINK messages.
*
@@ -99,6 +101,7 @@ rtnetlink_parse(struct ofpbuf *buf, struct rtnetlink_change *change)
[IFLA_MTU] = { .type = NL_A_U32, .optional = true },
[IFLA_ADDRESS] = { .type = NL_A_UNSPEC, .optional = true },
[IFLA_LINKINFO] = { .type = NL_A_NESTED, .optional = true },
[IFLA_WIRELESS] = { .type = NL_A_UNSPEC, .optional = true },
};
struct nlattr *attrs[ARRAY_SIZE(policy)];
@@ -111,6 +114,23 @@ rtnetlink_parse(struct ofpbuf *buf, struct rtnetlink_change *change)
ifinfo = ofpbuf_at(buf, NLMSG_HDRLEN, sizeof *ifinfo);
/* Wireless events can be spammy and cause a
* lot of unnecessary churn and CPU load in
* ovs-vswitchd. The best way to filter them out
* is to rely on the IFLA_WIRELESS and
* ifi_change. As per rtnetlink_ifinfo_prep() in
* the kernel, the ifi_change = 0. That combined
* with the fact wireless events never really
* change interface state (as far as core
* networking is concerned) they can be ignored
* by ovs-vswitchd. It doesn't understand
* wireless extensions anyway and has no way of
* presenting these bits into ovsdb.
*/
if (attrs[IFLA_WIRELESS] && ifinfo->ifi_change == 0) {
change->irrelevant = true;
}
change->nlmsg_type = nlmsg->nlmsg_type;
change->if_index = ifinfo->ifi_index;
change->ifname = nl_attr_get_string(attrs[IFLA_IFNAME]);

View File

@@ -45,6 +45,9 @@ struct rtnetlink_change {
int mtu; /* Current MTU. */
struct eth_addr mac;
unsigned int ifi_flags; /* Flags of network device. */
bool irrelevant; /* Some events, notably wireless extensions,
don't really indicate real netdev change
that OVS should care about. */
/* Network device address status. */
/* xxx To be added when needed. */