On Fri, Jul 07, 2006 at 10:38:01PM +0100, Robert Watson wrote:
 > 
 > On Fri, 7 Jul 2006, User Freebsd wrote:
 > 
 > >>I think that I have patched, built and loaded the em(4) kernel module 
 > >>correctly. After applying the patch there were no rejects, before 
 > >>building the module I intentionally appended " (patched)" to its version 
 > >>string in if_em.c, and could see that in dmesg every time I loaded the 
 > >>module: em1: <Intel(R) PRO/1000 Network Connection Version - 3.2.18 
 > >>(patched)>
 > >
 > >Is it possible that we're going at this issue backwards?  It isn't the 
 > >lack of ARP packet going out that is causing the problems with moving IPs, 
 > >but that delay that we're seeing when aliasing a new IP on the stack?  The 
 > >ARP packet *is* being attempted, but is timing out before the re-init is 
 > >completing?
 > 
 > Yes -- basically, there are two problems:
 > 
 > (1) A little problem, in which an arp announcement is sent before the link 
 > has
 >     settled after reset.
 > 
 > (2) A big problem, in which the interface is gratuitously recent requiring
 >     long settling times.
 > 
 > I'd really like to see a fix to the second of these problems (not resetting 
 > when an IP is added or removed, resulting in link renegotiation); the first 
 > one I'm less concerned about, although it would make some amount of sense 
 > to do an arp announcement when the link goes up.
 > 

Ah, I see. Thanks for the insight.
How about the attached patch?

-- 
Regards,
Pyun YongHyeon
Index: if_em.c
===================================================================
RCS file: /pool/ncvs/src/sys/dev/em/if_em.c,v
retrieving revision 1.116
diff -u -r1.116 if_em.c
--- if_em.c     6 Jun 2006 08:03:49 -0000       1.116
+++ if_em.c     8 Jul 2006 03:30:36 -0000
@@ -67,6 +67,7 @@
 
 #include <netinet/in_systm.h>
 #include <netinet/in.h>
+#include <netinet/if_ether.h>
 #include <netinet/ip.h>
 #include <netinet/tcp.h>
 #include <netinet/udp.h>
@@ -692,6 +693,9 @@
 
        EM_LOCK_ASSERT(sc);
 
+       if ((ifp->if_drv_flags & (IFF_DRV_RUNNING|IFF_DRV_OACTIVE)) !=
+           IFF_DRV_RUNNING)
+               return;
        if (!sc->link_active)
                return;
 
@@ -745,6 +749,7 @@
 {
        struct em_softc *sc = ifp->if_softc;
        struct ifreq *ifr = (struct ifreq *)data;
+       struct ifaddr *ifa = (struct ifaddr *)data;
        int error = 0;
 
        if (sc->in_detach)
@@ -752,9 +757,22 @@
 
        switch (command) {
        case SIOCSIFADDR:
-       case SIOCGIFADDR:
-               IOCTL_DEBUGOUT("ioctl rcv'd: SIOCxIFADDR (Get/Set Interface 
Addr)");
-               ether_ioctl(ifp, command, data);
+               if (ifa->ifa_addr->sa_family == AF_INET) {
+                       /*
+                        * XXX
+                        * Since resetting hardware takes a very long time
+                        * we only initialize the hardware only when it is
+                        * absolutely required.
+                        */
+                       ifp->if_flags |= IFF_UP;
+                       if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+                               EM_LOCK(sc);
+                               em_init_locked(sc);
+                               EM_UNLOCK(sc);
+                       }
+                       arp_ifinit(ifp, ifa);
+               } else
+                       error = ether_ioctl(ifp, command, data);
                break;
        case SIOCSIFMTU:
            {
@@ -802,17 +820,19 @@
                IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFFLAGS (Set Interface 
Flags)");
                EM_LOCK(sc);
                if (ifp->if_flags & IFF_UP) {
-                       if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+                       if ((ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+                               if ((ifp->if_flags ^ sc->if_flags) &
+                                   IFF_PROMISC) {
+                                       em_disable_promisc(sc);
+                                       em_set_promisc(sc);
+                               }
+                       } else
                                em_init_locked(sc);
-                       }
-
-                       em_disable_promisc(sc);
-                       em_set_promisc(sc);
                } else {
-                       if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+                       if (ifp->if_drv_flags & IFF_DRV_RUNNING)
                                em_stop(sc);
-                       }
                }
+               sc->if_flags = ifp->if_flags;
                EM_UNLOCK(sc);
                break;
        case SIOCADDMULTI:
@@ -878,8 +898,8 @@
                break;
            }
        default:
-               IOCTL_DEBUGOUT1("ioctl received: UNKNOWN (0x%x)", (int)command);
-               error = EINVAL;
+               error = ether_ioctl(ifp, command, data);
+               break;
        }
 
        return (error);
Index: if_em.h
===================================================================
RCS file: /pool/ncvs/src/sys/dev/em/if_em.h,v
retrieving revision 1.44
diff -u -r1.44 if_em.h
--- if_em.h     15 Feb 2006 08:39:50 -0000      1.44
+++ if_em.h     8 Jul 2006 03:30:43 -0000
@@ -259,6 +259,7 @@
        struct callout  timer;
        struct callout  tx_fifo_timer;
        int             io_rid;
+       int             if_flags;
        struct mtx      mtx;
        int             em_insert_vlan_header;
        struct task     link_task;
Index: if_em.c
===================================================================
RCS file: /pool/ncvs/src/sys/dev/em/if_em.c,v
retrieving revision 1.65.2.16
diff -u -r1.65.2.16 if_em.c
--- if_em.c     19 May 2006 00:19:57 -0000      1.65.2.16
+++ if_em.c     8 Jul 2006 03:29:16 -0000
@@ -657,8 +657,9 @@
 
        mtx_assert(&adapter->mtx, MA_OWNED);
 
-        if (!adapter->link_active)
-                return;
+       if ((ifp->if_drv_flags & (IFF_DRV_RUNNING|IFF_DRV_OACTIVE)) !=
+           IFF_DRV_RUNNING)
+               return;
 
         while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) {
 
@@ -714,15 +715,29 @@
 {
        struct ifreq   *ifr = (struct ifreq *) data;
        struct adapter * adapter = ifp->if_softc;
+       struct ifaddr *ifa = (struct ifaddr *)data;
        int error = 0;
 
        if (adapter->in_detach) return(error);
 
        switch (command) {
        case SIOCSIFADDR:
-       case SIOCGIFADDR:
-               IOCTL_DEBUGOUT("ioctl rcv'd: SIOCxIFADDR (Get/Set Interface 
Addr)");
-               ether_ioctl(ifp, command, data);
+               if (ifa->ifa_addr->sa_family == AF_INET) {
+                       /*
+                        * XXX
+                        * Since resetting hardware takes a very long time
+                        * we only initialize the hardware only when it is
+                        * absolutely required.
+                        */
+                       ifp->if_flags |= IFF_UP;
+                       if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+                               EM_LOCK(adapter);
+                               em_init_locked(adapter);
+                               EM_UNLOCK(adapter);
+                       }
+                       arp_ifinit(ifp, ifa);
+               } else
+                       error = ether_ioctl(ifp, command, data);
                break;
        case SIOCSIFMTU:
            {
@@ -760,12 +775,14 @@
                IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFFLAGS (Set Interface 
Flags)");
                EM_LOCK(adapter);
                if (ifp->if_flags & IFF_UP) {
-                       if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+                       if ((ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+                               if ((ifp->if_flags ^ adapter->if_flags) &
+                                   IFF_PROMISC) {
+                                       em_disable_promisc(adapter);
+                                       em_set_promisc(adapter);
+                               }
+                       } else
                                em_init_locked(adapter);
-                       }
-
-                       em_disable_promisc(adapter);
-                       em_set_promisc(adapter);
                } else {
                        if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
                                em_stop(adapter);
@@ -835,8 +852,8 @@
                break;
            }
        default:
-               IOCTL_DEBUGOUT1("ioctl received: UNKNOWN (0x%x)", (int)command);
-               error = EINVAL;
+               error = ether_ioctl(ifp, command, data);
+               break;
        }
 
        return(error);
Index: if_em.h
===================================================================
RCS file: /pool/ncvs/src/sys/dev/em/if_em.h,v
retrieving revision 1.32.2.2
diff -u -r1.32.2.2 if_em.h
--- if_em.h     25 Nov 2005 14:11:59 -0000      1.32.2.2
+++ if_em.h     8 Jul 2006 03:29:25 -0000
@@ -65,6 +65,7 @@
 
 #include <netinet/in_systm.h>
 #include <netinet/in.h>
+#include <netinet/if_ether.h>
 #include <netinet/ip.h>
 #include <netinet/tcp.h>
 #include <netinet/udp.h>
@@ -331,6 +332,7 @@
        struct callout  timer;
        struct callout  tx_fifo_timer;
        int             io_rid;
+       int             if_flags;
        u_int8_t        unit;
        struct mtx      mtx;
        int             em_insert_vlan_header;
_______________________________________________
freebsd-stable@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-stable
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to