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:
committed by
Ilya Maximets
parent
f9d3039039
commit
d90b4f2928
@@ -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);
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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]);
|
||||
|
@@ -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. */
|
||||
|
Reference in New Issue
Block a user