Author: hrs
Date: Sun Jan 31 08:16:37 2010
New Revision: 203272
URL: http://svn.freebsd.org/changeset/base/203272

Log:
  - 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.

Modified:
  head/sys/net/if_bridge.c

Modified: head/sys/net/if_bridge.c
==============================================================================
--- head/sys/net/if_bridge.c    Sun Jan 31 03:06:12 2010        (r203271)
+++ head/sys/net/if_bridge.c    Sun Jan 31 08:16:37 2010        (r203272)
@@ -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 c
                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
                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
                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
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to