1
0
mirror of https://github.com/systemd/systemd.git synced 2024-12-22 17:35:35 +03:00

network: manage WLAN phy

This commit is contained in:
Yu Watanabe 2022-02-15 02:06:29 +09:00
parent 1d4312d5f9
commit edb69db2b0
6 changed files with 289 additions and 0 deletions

View File

@ -143,6 +143,8 @@ sources = files('''
networkd-util.h
networkd-wifi.c
networkd-wifi.h
networkd-wiphy.c
networkd-wiphy.h
tc/cake.c
tc/cake.h
tc/codel.c

View File

@ -42,6 +42,7 @@
#include "networkd-speed-meter.h"
#include "networkd-state-file.h"
#include "networkd-wifi.h"
#include "networkd-wiphy.h"
#include "ordered-set.h"
#include "path-lookup.h"
#include "path-util.h"
@ -554,6 +555,9 @@ Manager* manager_free(Manager *m) {
m->netdevs = hashmap_free_with_destructor(m->netdevs, netdev_unref);
m->wiphy_by_name = hashmap_free(m->wiphy_by_name);
m->wiphy_by_index = hashmap_free_with_destructor(m->wiphy_by_index, wiphy_free);
ordered_set_free_free(m->address_pools);
hashmap_free(m->route_table_names_by_number);
@ -793,6 +797,20 @@ static int manager_enumerate_nexthop(Manager *m) {
return manager_enumerate_internal(m, m->rtnl, req, manager_rtnl_process_nexthop);
}
static int manager_enumerate_nl80211_wiphy(Manager *m) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
assert(m);
assert(m->genl);
r = sd_genl_message_new(m->genl, NL80211_GENL_NAME, NL80211_CMD_GET_WIPHY, &req);
if (r < 0)
return r;
return manager_enumerate_internal(m, m->genl, req, manager_genl_process_nl80211_wiphy);
}
static int manager_enumerate_nl80211_config(Manager *m) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
@ -878,6 +896,12 @@ int manager_enumerate(Manager *m) {
else if (r < 0)
return log_error_errno(r, "Could not enumerate routing policy rules: %m");
r = manager_enumerate_nl80211_wiphy(m);
if (r == -EOPNOTSUPP)
log_debug_errno(r, "Could not enumerate wireless LAN phy, ignoring: %m");
else if (r < 0)
return log_error_errno(r, "Could not enumerate wireless LAN phy: %m");
r = manager_enumerate_nl80211_config(m);
if (r == -EOPNOTSUPP)
log_debug_errno(r, "Could not enumerate wireless LAN interfaces, ignoring: %m");

View File

@ -84,6 +84,10 @@ struct Manager {
Hashmap *route_table_numbers_by_name;
Hashmap *route_table_names_by_number;
/* Wiphy */
Hashmap *wiphy_by_index;
Hashmap *wiphy_by_name;
/* For link speed meter */
bool use_speed_meter;
sd_event_source *speed_meter_event_source;

View File

@ -8,6 +8,7 @@
#include "networkd-link.h"
#include "networkd-manager.h"
#include "networkd-wifi.h"
#include "networkd-wiphy.h"
#include "string-util.h"
#include "wifi-util.h"
@ -72,6 +73,8 @@ int manager_genl_process_nl80211_config(sd_netlink *genl, sd_netlink_message *me
log_debug_errno(r, "nl80211: failed to determine genl message command, ignoring: %m");
return 0;
}
if (IN_SET(cmd, NL80211_CMD_NEW_WIPHY, NL80211_CMD_DEL_WIPHY))
return manager_genl_process_nl80211_wiphy(genl, message, manager);
if (!IN_SET(cmd, NL80211_CMD_SET_INTERFACE, NL80211_CMD_NEW_INTERFACE, NL80211_CMD_DEL_INTERFACE)) {
log_debug("nl80211: ignoring nl80211 %s(%u) message.",
strna(nl80211_cmd_to_string(cmd)), cmd);

View File

@ -0,0 +1,205 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <linux/nl80211.h>
#include "device-util.h"
#include "networkd-manager.h"
#include "networkd-wiphy.h"
#include "parse-util.h"
#include "wifi-util.h"
Wiphy *wiphy_free(Wiphy *w) {
if (!w)
return NULL;
if (w->manager) {
hashmap_remove_value(w->manager->wiphy_by_index, UINT32_TO_PTR(w->index), w);
if (w->name)
hashmap_remove_value(w->manager->wiphy_by_name, w->name, w);
}
free(w->name);
return mfree(w);
}
static int wiphy_new(Manager *manager, uint32_t index, Wiphy **ret) {
_cleanup_(wiphy_freep) Wiphy *w = NULL;
int r;
assert(manager);
w = new(Wiphy, 1);
if (!w)
return -ENOMEM;
*w = (Wiphy) {
.index = index,
};
r = hashmap_ensure_put(&manager->wiphy_by_index, NULL, UINT32_TO_PTR(w->index), w);
if (r < 0)
return r;
w->manager = manager;
if (ret)
*ret = w;
TAKE_PTR(w);
return 0;
}
int wiphy_get_by_index(Manager *manager, uint32_t index, Wiphy **ret) {
Wiphy *w;
assert(manager);
w = hashmap_get(manager->wiphy_by_index, UINT32_TO_PTR(index));
if (!w)
return -ENODEV;
if (ret)
*ret = w;
return 0;
}
int wiphy_get_by_name(Manager *manager, const char *name, Wiphy **ret) {
Wiphy *w;
assert(manager);
assert(name);
w = hashmap_get(manager->wiphy_by_name, name);
if (!w)
return -ENODEV;
if (ret)
*ret = w;
return 0;
}
static int wiphy_update_name(Wiphy *w, sd_netlink_message *message) {
const char *name;
int r;
assert(w);
assert(w->manager);
assert(message);
r = sd_netlink_message_read_string(message, NL80211_ATTR_WIPHY_NAME, &name);
if (r == -ENODATA)
return 0;
if (r < 0)
return r;
if (streq_ptr(w->name, name))
return 0;
if (w->name)
hashmap_remove_value(w->manager->wiphy_by_name, w->name, w);
r = free_and_strdup(&w->name, name);
if (r < 0)
return r;
return hashmap_ensure_put(&w->manager->wiphy_by_name, &string_hash_ops, w->name, w);
}
static int wiphy_update(Wiphy *w, sd_netlink_message *message) {
int r;
assert(w);
assert(message);
r = wiphy_update_name(w, message);
if (r < 0)
return log_wiphy_debug_errno(w, r, "Failed to update wiphy name: %m");
return 0;
}
int manager_genl_process_nl80211_wiphy(sd_netlink *genl, sd_netlink_message *message, Manager *manager) {
const char *family;
uint32_t index;
uint8_t cmd;
Wiphy *w = NULL;
int r;
assert(genl);
assert(message);
assert(manager);
if (sd_netlink_message_is_error(message)) {
r = sd_netlink_message_get_errno(message);
if (r < 0)
log_message_warning_errno(message, r, "nl80211: received error message, ignoring");
return 0;
}
r = sd_genl_message_get_family_name(genl, message, &family);
if (r < 0) {
log_debug_errno(r, "nl80211: failed to determine genl family, ignoring: %m");
return 0;
}
if (!streq(family, NL80211_GENL_NAME)) {
log_debug("nl80211: Received message of unexpected genl family '%s', ignoring.", family);
return 0;
}
r = sd_genl_message_get_command(genl, message, &cmd);
if (r < 0) {
log_debug_errno(r, "nl80211: failed to determine genl message command, ignoring: %m");
return 0;
}
r = sd_netlink_message_read_u32(message, NL80211_ATTR_WIPHY, &index);
if (r < 0) {
log_debug_errno(r, "nl80211: received %s(%u) message without valid index, ignoring: %m",
strna(nl80211_cmd_to_string(cmd)), cmd);
return 0;
}
(void) wiphy_get_by_index(manager, index, &w);
switch (cmd) {
case NL80211_CMD_NEW_WIPHY: {
bool is_new = !w;
if (!w) {
r = wiphy_new(manager, index, &w);
if (r < 0) {
log_warning_errno(r, "Failed to allocate wiphy, ignoring: %m");
return 0;
}
}
r = wiphy_update(w, message);
if (r < 0) {
log_wiphy_warning_errno(w, r, "Failed to update wiphy, ignoring: %m");
return 0;
}
log_wiphy_debug(w, "Received %s phy.", is_new ? "new" : "updated");
break;
}
case NL80211_CMD_DEL_WIPHY:
if (!w) {
log_debug("The kernel removes wiphy we do not know, ignoring: %m");
return 0;
}
log_wiphy_debug(w, "Removed.");
wiphy_free(w);
break;
default:
log_wiphy_debug(w, "nl80211: received %s(%u) message.",
strna(nl80211_cmd_to_string(cmd)), cmd);
}
return 0;
}

View File

@ -0,0 +1,51 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <inttypes.h>
#include "sd-device.h"
#include "macro.h"
typedef struct Manager Manager;
typedef struct Wiphy {
Manager *manager;
uint32_t index;
char *name;
} Wiphy;
Wiphy *wiphy_free(Wiphy *w);
DEFINE_TRIVIAL_CLEANUP_FUNC(Wiphy*, wiphy_free);
int wiphy_get_by_index(Manager *manager, uint32_t index, Wiphy **ret);
int wiphy_get_by_name(Manager *manager, const char *name, Wiphy **ret);
int manager_genl_process_nl80211_wiphy(sd_netlink *genl, sd_netlink_message *message, Manager *manager);
#define log_wiphy_full_errno_zerook(w, level, error, ...) \
({ \
const Wiphy *_w = (w); \
log_interface_full_errno_zerook(_w ? _w->name : NULL, level, error, __VA_ARGS__); \
})
#define log_wiphy_full_errno(w, level, error, ...) \
({ \
int _error = (error); \
ASSERT_NON_ZERO(_error); \
log_wiphy_full_errno_zerook(w, level, _error, __VA_ARGS__); \
})
#define log_wiphy_full(w, level, ...) (void) log_wiphy_full_errno_zerook(w, level, 0, __VA_ARGS__)
#define log_wiphy_debug(w, ...) log_wiphy_full(w, LOG_DEBUG, __VA_ARGS__)
#define log_wiphy_info(w, ...) log_wiphy_full(w, LOG_INFO, __VA_ARGS__)
#define log_wiphy_notice(w, ...) log_wiphy_full(w, LOG_NOTICE, __VA_ARGS__)
#define log_wiphy_warning(w, ...) log_wiphy_full(w, LOG_WARNING, __VA_ARGS__)
#define log_wiphy_error(w, ...) log_wiphy_full(w, LOG_ERR, __VA_ARGS__)
#define log_wiphy_debug_errno(w, error, ...) log_wiphy_full_errno(w, LOG_DEBUG, error, __VA_ARGS__)
#define log_wiphy_info_errno(w, error, ...) log_wiphy_full_errno(w, LOG_INFO, error, __VA_ARGS__)
#define log_wiphy_notice_errno(w, error, ...) log_wiphy_full_errno(w, LOG_NOTICE, error, __VA_ARGS__)
#define log_wiphy_warning_errno(w, error, ...) log_wiphy_full_errno(w, LOG_WARNING, error, __VA_ARGS__)
#define log_wiphy_error_errno(w, error, ...) log_wiphy_full_errno(w, LOG_ERR, error, __VA_ARGS__)