em device hangs on ifconfig alias ...
Pyun YongHyeon
pyunyh at gmail.com
Sat Jul 8 03:29:05 UTC 2006
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
-------------- next part --------------
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;
-------------- next part --------------
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;
More information about the freebsd-stable
mailing list