- Check if_type of "addm <interface>" before setting the

interface's MTU to the if_bridge(4) interface.  This fixes a
  bug that MTU value of "addm <interface>" is used even when it
  is invalid for the if_bridge(4) member:

  # ifconfig bridge0 create
  # ifconfig bridge0
  bridge0: flags=8802<BROADCAST,SIMPLEX,MULTICAST> metric 0 mtu 1500
  ...
  # ifconfig bridge0 addm lo0
  ifconfig: BRDGADD lo0: Invalid argument
  # ifconfig bridge0
  bridge0: flags=8802<BROADCAST,SIMPLEX,MULTICAST> metric 0 mtu 16384
  ...

- Do not ignore MTU value of an interface even when if_type == IFT_GIF.
  This fixes MTU mismatch when an if_bridge(4) interface has a
  gif(4) interface and no other interface as the member, and it
  is directly used for L2 communication with EtherIP tunneling
  enabled.

- Implement SIOCSIFMTU ioctl.  Changing the MTU is allowed only
  when all members have the same MTU value.
This commit is contained in:
Hiroki Sato 2010-01-31 08:16:37 +00:00
parent cd18ad8347
commit c2a5f1a57a

View File

@ -683,6 +683,8 @@ static int
bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
struct bridge_softc *sc = ifp->if_softc;
struct ifreq *ifr = (struct ifreq *)data;
struct bridge_iflist *bif;
struct thread *td = curthread;
union {
struct ifbreq ifbreq;
@ -772,10 +774,29 @@ bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
break;
case SIOCSIFMTU:
/* Do not allow the MTU to be changed on the bridge */
error = EINVAL;
if (ifr->ifr_mtu < 576) {
error = EINVAL;
break;
}
if (LIST_EMPTY(&sc->sc_iflist)) {
sc->sc_ifp->if_mtu = ifr->ifr_mtu;
break;
}
BRIDGE_LOCK(sc);
LIST_FOREACH(bif, &sc->sc_iflist, bif_next) {
if (bif->bif_ifp->if_mtu != ifr->ifr_mtu) {
log(LOG_NOTICE, "%s: invalid MTU: %lu(%s)"
" != %d\n", sc->sc_ifp->if_xname,
bif->bif_ifp->if_mtu,
bif->bif_ifp->if_xname, ifr->ifr_mtu);
error = EINVAL;
break;
}
}
if (!error)
sc->sc_ifp->if_mtu = ifr->ifr_mtu;
BRIDGE_UNLOCK(sc);
break;
default:
/*
* drop the lock as ether_ioctl() will call bridge_start() and
@ -989,17 +1010,6 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg)
if (ifs == bif->bif_ifp)
return (EBUSY);
/* Allow the first Ethernet member to define the MTU */
if (ifs->if_type != IFT_GIF) {
if (LIST_EMPTY(&sc->sc_iflist))
sc->sc_ifp->if_mtu = ifs->if_mtu;
else if (sc->sc_ifp->if_mtu != ifs->if_mtu) {
if_printf(sc->sc_ifp, "invalid MTU for %s\n",
ifs->if_xname);
return (EINVAL);
}
}
if (ifs->if_bridge == sc)
return (EEXIST);
@ -1025,6 +1035,16 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg)
goto out;
}
/* Allow the first Ethernet member to define the MTU */
if (LIST_EMPTY(&sc->sc_iflist))
sc->sc_ifp->if_mtu = ifs->if_mtu;
else if (sc->sc_ifp->if_mtu != ifs->if_mtu) {
if_printf(sc->sc_ifp, "invalid MTU: %lu(%s) != %lu\n",
ifs->if_mtu, ifs->if_xname, sc->sc_ifp->if_mtu);
error = EINVAL;
goto out;
}
/*
* Assign the interface's MAC address to the bridge if it's the first
* member and the MAC address of the bridge has not been changed from