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");
dbus_shutdown();
netdev_shutdown();
timeout = l_timeout_create(1, main_loop_quit, NULL, NULL);
break;

View File

@ -54,6 +54,7 @@ struct netdev {
uint32_t type;
uint8_t addr[ETH_ALEN];
struct device *device;
struct wiphy *wiphy;
unsigned int ifi_flags;
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_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);
if (netdev->sm) {
@ -288,9 +298,8 @@ static void netdev_free(void *data)
netdev_operstate_down_cb,
L_UINT_TO_PTR(netdev->index));
l_queue_destroy(netdev->watches, l_free);
l_free(netdev);
if (netdev_get_is_up(netdev))
netdev_set_powered(netdev, false, NULL, NULL, NULL);
}
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);
}
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,
uint32_t len, void *user_data)
{
const struct ifinfomsg *ifi = data;
unsigned int bytes;
struct netdev *netdev;
if (error != 0 || ifi->ifi_type != ARPHRD_ETHER ||
type != RTM_NEWLINK) {
@ -1211,9 +1255,23 @@ static void netdev_getlink_cb(int error, uint16_t type, const void *data,
return;
}
netdev = netdev_find(ifi->ifi_index);
if (!netdev)
return;
bytes = len - NLMSG_ALIGN(sizeof(struct ifinfomsg));
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)
@ -1342,16 +1400,11 @@ static void netdev_get_interface_callback(struct l_genl_msg *msg,
netdev->rekey_offload_support = true;
memcpy(netdev->addr, ifaddr, sizeof(netdev->addr));
memcpy(netdev->name, ifname, ifname_len);
netdev->wiphy = wiphy;
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);
netdev->device = device_create(wiphy, netdev);
/* Query interface flags */
bufsize = NLMSG_LENGTH(sizeof(struct ifinfomsg));
@ -1569,3 +1622,11 @@ bool netdev_exit(void)
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,
const char *whitelist, const char *blacklist);
bool netdev_exit(void);
void netdev_shutdown(void);