netdev: Reset interface state on init and exit

Take any managed interface down when iwd detects it and bring it back
up to start with a clean state.  On exit take interfaces down.
This commit is contained in:
Andrew Zaborowski 2016-07-13 04:29:52 +02:00 committed by Denis Kenzior
parent 2e845b5ee2
commit 19fa024bd8
3 changed files with 72 additions and 9 deletions

View File

@ -63,6 +63,7 @@ static void signal_handler(struct l_signal *signal, uint32_t signo,
l_info("Terminate"); l_info("Terminate");
dbus_shutdown(); dbus_shutdown();
netdev_shutdown();
timeout = l_timeout_create(1, main_loop_quit, NULL, NULL); timeout = l_timeout_create(1, main_loop_quit, NULL, NULL);
break; break;

View File

@ -54,6 +54,7 @@ struct netdev {
uint32_t type; uint32_t type;
uint8_t addr[ETH_ALEN]; uint8_t addr[ETH_ALEN];
struct device *device; struct device *device;
struct wiphy *wiphy;
unsigned int ifi_flags; unsigned int ifi_flags;
netdev_event_func_t event_filter; netdev_event_func_t event_filter;
@ -269,6 +270,15 @@ static void netdev_free(void *data)
l_debug("Freeing netdev %s[%d]", netdev->name, netdev->index); l_debug("Freeing netdev %s[%d]", netdev->name, netdev->index);
l_queue_destroy(netdev->watches, l_free);
l_free(netdev);
}
static void netdev_shutdown_one(void *data, void *user_data)
{
struct netdev *netdev = data;
device_remove(netdev->device); device_remove(netdev->device);
if (netdev->sm) { if (netdev->sm) {
@ -288,9 +298,8 @@ static void netdev_free(void *data)
netdev_operstate_down_cb, netdev_operstate_down_cb,
L_UINT_TO_PTR(netdev->index)); L_UINT_TO_PTR(netdev->index));
l_queue_destroy(netdev->watches, l_free); if (netdev_get_is_up(netdev))
netdev_set_powered(netdev, false, NULL, NULL, NULL);
l_free(netdev);
} }
static bool netdev_match(const void *a, const void *b) static bool netdev_match(const void *a, const void *b)
@ -1198,11 +1207,46 @@ static void netdev_dellink_notify(const struct ifinfomsg *ifi, int bytes)
netdev_free(netdev); netdev_free(netdev);
} }
static void netdev_initial_up_cb(struct netdev *netdev, int result,
void *user_data)
{
if (result != 0) {
l_error("Error bringing interface %i up: %s", netdev->index,
strerror(-result));
return;
}
netdev_set_linkmode_and_operstate(netdev->index, 1,
IF_OPER_DORMANT,
netdev_operstate_dormant_cb,
netdev);
l_debug("Interface %i initialized", netdev->index);
netdev->device = device_create(netdev->wiphy, netdev);
}
static void netdev_initial_down_cb(struct netdev *netdev, int result,
void *user_data)
{
if (result != 0) {
l_error("Error taking interface %i down: %s", netdev->index,
strerror(-result));
return;
}
netdev_set_powered(netdev, true, netdev_initial_up_cb,
NULL, NULL);
}
static void netdev_getlink_cb(int error, uint16_t type, const void *data, static void netdev_getlink_cb(int error, uint16_t type, const void *data,
uint32_t len, void *user_data) uint32_t len, void *user_data)
{ {
const struct ifinfomsg *ifi = data; const struct ifinfomsg *ifi = data;
unsigned int bytes; unsigned int bytes;
struct netdev *netdev;
if (error != 0 || ifi->ifi_type != ARPHRD_ETHER || if (error != 0 || ifi->ifi_type != ARPHRD_ETHER ||
type != RTM_NEWLINK) { type != RTM_NEWLINK) {
@ -1211,9 +1255,23 @@ static void netdev_getlink_cb(int error, uint16_t type, const void *data,
return; return;
} }
netdev = netdev_find(ifi->ifi_index);
if (!netdev)
return;
bytes = len - NLMSG_ALIGN(sizeof(struct ifinfomsg)); bytes = len - NLMSG_ALIGN(sizeof(struct ifinfomsg));
netdev_newlink_notify(ifi, bytes); netdev_newlink_notify(ifi, bytes);
/*
* If the interface is UP, reset it to ensure a clean state,
* otherwise just bring it UP.
*/
if (netdev_get_is_up(netdev)) {
netdev_set_powered(netdev, false, netdev_initial_down_cb,
NULL, NULL);
} else
netdev_initial_down_cb(netdev, 0, NULL);
} }
static bool netdev_is_managed(const char *ifname) static bool netdev_is_managed(const char *ifname)
@ -1342,16 +1400,11 @@ static void netdev_get_interface_callback(struct l_genl_msg *msg,
netdev->rekey_offload_support = true; netdev->rekey_offload_support = true;
memcpy(netdev->addr, ifaddr, sizeof(netdev->addr)); memcpy(netdev->addr, ifaddr, sizeof(netdev->addr));
memcpy(netdev->name, ifname, ifname_len); memcpy(netdev->name, ifname, ifname_len);
netdev->wiphy = wiphy;
l_queue_push_tail(netdev_list, netdev); l_queue_push_tail(netdev_list, netdev);
netdev_set_linkmode_and_operstate(netdev->index, 1,
IF_OPER_DORMANT,
netdev_operstate_dormant_cb,
netdev);
l_debug("Found interface %s[%d]", netdev->name, netdev->index); l_debug("Found interface %s[%d]", netdev->name, netdev->index);
netdev->device = device_create(wiphy, netdev);
/* Query interface flags */ /* Query interface flags */
bufsize = NLMSG_LENGTH(sizeof(struct ifinfomsg)); bufsize = NLMSG_LENGTH(sizeof(struct ifinfomsg));
@ -1569,3 +1622,11 @@ bool netdev_exit(void)
return true; return true;
} }
void netdev_shutdown(void)
{
if (!rtnl)
return;
l_queue_foreach(netdev_list, netdev_shutdown_one, NULL);
}

View File

@ -85,3 +85,4 @@ bool netdev_watch_remove(struct netdev *netdev, uint32_t id);
bool netdev_init(struct l_genl_family *in, bool netdev_init(struct l_genl_family *in,
const char *whitelist, const char *blacklist); const char *whitelist, const char *blacklist);
bool netdev_exit(void); bool netdev_exit(void);
void netdev_shutdown(void);