netdev: handle netlink events on bridge ports

When a wifi interface is added/removed to/from a bridge, a
RTM_NEW/DELLINK event is issued. This is the same event used to signal
when an interface is created/deleted.

For this reason the event generated by the bridge code has to be
properly distinguished and handled accordingly. Failing to do so will
result in inconsistencies in iwd which will think an interface has been
deleted when it was actually not.

Detect incoming NEW/DELLINK bridge events and reacts accordingly. For
now, this simply means printing a simple message, as there is no
special logic in iwd for this yet.
This commit is contained in:
Antonio Quartulli 2018-06-12 12:20:18 +08:00 committed by Denis Kenzior
parent e2ac29b492
commit 896aa41082
1 changed files with 34 additions and 0 deletions

View File

@ -3472,6 +3472,30 @@ int netdev_set_iftype(struct netdev *netdev, enum netdev_iftype type)
return 0;
}
static void netdev_bridge_port_event(const struct ifinfomsg *ifi, int bytes,
bool added)
{
struct netdev *netdev;
struct rtattr *attr;
uint32_t master = 0;
netdev = netdev_find(ifi->ifi_index);
if (!netdev)
return;
for (attr = IFLA_RTA(ifi); RTA_OK(attr, bytes);
attr = RTA_NEXT(attr, bytes)) {
switch (attr->rta_type) {
case IFLA_MASTER:
memcpy(&master, RTA_DATA(attr), sizeof(master));
break;
}
}
l_debug("netdev: %d %s bridge: %d", ifi->ifi_index,
(added ? "added to" : "removed from"), master);
}
static void netdev_newlink_notify(const struct ifinfomsg *ifi, int bytes)
{
struct netdev *netdev;
@ -3480,6 +3504,11 @@ static void netdev_newlink_notify(const struct ifinfomsg *ifi, int bytes)
uint8_t old_addr[ETH_ALEN];
struct rtattr *attr;
if (ifi->ifi_family == AF_BRIDGE) {
netdev_bridge_port_event(ifi, bytes, true);
return;
}
netdev = netdev_find(ifi->ifi_index);
if (!netdev)
return;
@ -3525,6 +3554,11 @@ static void netdev_dellink_notify(const struct ifinfomsg *ifi, int bytes)
{
struct netdev *netdev;
if (ifi->ifi_family == AF_BRIDGE) {
netdev_bridge_port_event(ifi, bytes, false);
return;
}
netdev = l_queue_remove_if(netdev_list, netdev_match,
L_UINT_TO_PTR(ifi->ifi_index));
if (!netdev)