if_lagg: allow to invoke SIOCSLAGGPORT multiple times in a row

Currently, 'ifconfig laggX down' does not remove members from this
lagg(4) interface.  So, 'service netif stop laggX' followed by
'service netif start laggX' will choke, because "stop" will leave
interfaces attached to the laggX and ifconfig from the "start" will
refuse to add already-existing interfaces.

The real-world case is when I am bundling together my Ethernet and
WiFi interfaces and using multiple profiles for accessing network in
different places: system being booted up with one profile, but later
this profile being exchanged to another one, followed by 'service
netif restart' will not add WiFi interface back to the lagg: the
"stop" action from 'service netif restart' will shut down my main WiFi
interface, so wlan0 that exists in the lagg0 will be destroyed and
purged from lagg0; the "start" action will try to re-add both
interfaces, but since Ethernet one is already in lagg0, ifconfig will
refuse to add the wlan0 from WiFi interface.

Since adding the interface to the lagg(4) when it is already here
should be an idempotent action: we're really not changing anything,
so this fix doesn't change the semantics of interface addition.

Approved by: thompsa
Reviewed by: emaste
MFC after: 1 week
This commit is contained in:
Eygene Ryabinkin 2012-05-28 12:13:04 +00:00
parent 523f54dd4a
commit f74d5a7a20
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=236178
2 changed files with 8 additions and 2 deletions

View File

@ -40,7 +40,8 @@ setlaggport(const char *val, int d, int s, const struct afswtch *afp)
strlcpy(rp.rp_ifname, name, sizeof(rp.rp_ifname));
strlcpy(rp.rp_portname, val, sizeof(rp.rp_portname));
if (ioctl(s, SIOCSLAGGPORT, &rp))
/* Don't choke if the port is already in this lagg. */
if (ioctl(s, SIOCSLAGGPORT, &rp) && errno != EEXIST)
err(1, "SIOCSLAGGPORT");
}

View File

@ -516,8 +516,13 @@ lagg_port_create(struct lagg_softc *sc, struct ifnet *ifp)
return (ENOSPC);
/* Check if port has already been associated to a lagg */
if (ifp->if_lagg != NULL)
if (ifp->if_lagg != NULL) {
/* Port is already in the current lagg? */
lp = (struct lagg_port *)ifp->if_lagg;
if (lp->lp_softc == sc)
return (EEXIST);
return (EBUSY);
}
/* XXX Disallow non-ethernet interfaces (this should be any of 802) */
if (ifp->if_type != IFT_ETHER)