em device hangs on ifconfig alias ...
Atanas
atanas at asd.aplus.net
Mon Jul 10 20:40:53 UTC 2006
Pyun YongHyeon said the following on 7/7/06 8:32 PM:
> On Fri, Jul 07, 2006 at 10:38:01PM +0100, Robert Watson wrote:
> >
> > 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?
>
This patch seems to fix both of the issues, or at least this is what I
see now:
- the card no longer gets reset when adding an alias;
- the arp packet gets delivered;
- adding 250 aliases takes less than a second;
I haven't fully tested whether all 250 IP aliases were accessible (I
used non-routable IP addresses), but I suppose so. Also I couldn't
stress the patched driver enough to see whether it performs as expected.
But in overall it looks good. I guess some more testing might be needed
in order to merge the patch into the source tree.
Regards,
Atanas
>
>
> ------------------------------------------------------------------------
>
> 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 at freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-stable
> To unsubscribe, send any mail to "freebsd-stable-unsubscribe at freebsd.org"
More information about the freebsd-stable
mailing list