tech-net archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

network synch bugs (was Re: ping: sendto: No buffer space available)



On Wed, Oct 05, 2011 at 10:27:03PM +0200, Thomas Klausner wrote:
> On Wed, Oct 05, 2011 at 09:44:30PM +0200, Thomas Klausner wrote:
> > When I start rtorrent with ~20 torrents and an effective traffic of a
> > few 100KB/s, after a short while the machine falls off the net. When I
> > do ping then, I see
> > ping: sendto: No buffer space available
> 
> It's even worse, ral0 falls off the net with normal web browsing
> (well, opening 10 tabs in firefox in parallel, but that's not much...)
> ral0 at pci2 dev 2 function 0: Ralink Technologies RT2561S 802.11b/g
> (rev. 0x00)
> ral0: interrupting at ioapic1 pin 17
> ral0: 802.11 address 00:1f:1f:59:57:52
> ral0: MAC/BBP RT2561C, RF RT2527
> ral0: 11b rates: 1Mbps 2Mbps 5.5Mbps 11Mbps
> ral0: 11g rates: 1Mbps 2Mbps 5.5Mbps 11Mbps 6Mbps 9Mbps 12Mbps 18Mbps
> 24Mbps 36Mbps 48Mbps 54Mbps

This may have something to do with the way that I have botched
synchronization in net80211, and the way that somebody else has botched
synchronization of ifnet ioctls.

The attached (untested) patches may help.

Dave

-- 
David Young             OJC Technologies is now Pixo
dyoung%pixotech.com@localhost     Urbana, IL   (217) 344-0444 x24
Index: if.c
===================================================================
RCS file: /cvsroot/src/sys/net/if.c,v
retrieving revision 1.251
diff -u -p -r1.251 if.c
--- if.c        12 Aug 2011 22:09:36 -0000      1.251
+++ if.c        5 Oct 2011 22:07:37 -0000
@@ -292,6 +293,9 @@ int
 if_nullioctl(struct ifnet *ifp, u_long cmd, void *data)
 {
 
+#ifdef straw_synch
+       cv_signal(&ifp->ifp_ioctl_emptied);
+#endif
        return ENXIO;
 }
 
@@ -497,8 +501,12 @@ if_attach(struct ifnet *ifp)
        }
        TAILQ_INIT(&ifp->if_addrlist);
        TAILQ_INSERT_TAIL(&ifnet, ifp, if_list);
+#ifdef straw_synch
+       ifioctl_attach(ifp);
+#else
        if (ifp->if_ioctl == NULL)
                ifp->if_ioctl = ifioctl_common;
+#endif
 
        mutex_enter(&index_gen_mtx);
        ifp->if_index_gen = index_gen++;
@@ -842,6 +850,10 @@ again:
 
        TAILQ_REMOVE(&ifnet, ifp, if_list);
 
+#ifdef straw_synch
+       ifioctl_detach(ifp);
+#endif
+
        /*
         * remove packets that came from ifp, from software interrupt queues.
         */
@@ -1801,11 +1824,16 @@ ifioctl(struct socket *so, u_long cmd, v
 
        oif_flags = ifp->if_flags;
 
+#ifdef straw_synch
+       uint64_t nenter = percpu_getref(ifp->ifp_ioctl_nenter);
+       (*nenter)++;
+       mutex_enter(&ifp->ifp_ioctl_lock);
+#endif
        error = (*ifp->if_ioctl)(ifp, cmd, data);
        if (error != ENOTTY)
                ;
        else if (so->so_proto == NULL)
-               return EOPNOTSUPP;
+               error = EOPNOTSUPP;
        else {
 #ifdef COMPAT_OSOCK
                error = compat_ifioctl(so, ocmd, cmd, data, l);
@@ -1830,9 +1858,59 @@ ifioctl(struct socket *so, u_long cmd, v
                ifreqn2o(oifr, ifr);
 #endif
 
+#ifdef straw_synch
+       ifp->ifp_ioctl_nexit++;
+       mutex_exit(&ifp->ifp_ioctl_lock);
+#endif
        return error;
 }
 
+#ifdef straw_synch
+static void
+ifioctl_sum(void *p, void *arg, struct cpu_info *ci)
+{
+       uint64_t *sum = arg, *nenter = p;
+
+       *sum += *nenter;
+}
+
+static uint64_t
+ifioctl_entrances(struct ifnet *ifp)
+{
+       uint64_t sum = 0;
+
+       percpu_foreach(ifp->ifp_ioctl_nenter, ifioctl_sum, &sum);
+
+       return sum;
+}
+
+int
+ifioctl_attach(struct ifnet *ifp)
+{
+       if (ifp->if_ioctl == NULL)
+               ifp->if_ioctl = ifioctl_common;
+
+       ifp->ifp_ioctl_nenter = percpu_alloc(sizeof(uint64_t));
+       if (ifp->ifp_ioctl_nenter == NULL)
+               return ENOMEM;
+
+       mutex_init(&ifp->ifp_ioctl_lock, MUTEX_DEFAULT, IPL_NONE);
+       cv_init(&ifp->ifp_ioctl_emptied, ifp->ifp_xname);
+
+       return 0;
+}
+
+void
+ifioctl_detach(struct ifnet *ifp)
+{
+       mutex_enter(&ifp->ifp_ioctl_lock);
+       ifp->if_ioctl = if_nullioctl;
+       while (ifioctl_entrances(ifp) != ifp->if_ioctl_nexit)
+               cv_wait(&ifp->ifp_ioctl_emptied, &ifp->ifp_ioctl_lock);
+       mutex_exit(&ifp->ifp_ioctl_lock);
+}
+#endif
+
 /*
  * Return interface configuration
  * of system.  List may be used
Index: if.h
===================================================================
RCS file: /cvsroot/src/sys/net/if.h,v
retrieving revision 1.151
diff -u -p -r1.151 if.h
--- if.h        12 Aug 2011 22:09:17 -0000      1.151
+++ if.h        5 Oct 2011 22:07:37 -0000
@@ -296,6 +300,12 @@ typedef struct ifnet {
                                         * same, they are the same ifnet.
                                         */
        struct sysctllog        *if_sysctl_log;
+#ifdef straw_sched
+       kmutex_t if_ioctl_lock;
+       uint64_t if_ioctl_nexit;
+       percpu_t *if_ioctl_nenter;
+       kcondvar_t if_ioctl_emptied;
+#endif
 } ifnet_t;
 
 #define        if_mtu          if_data.ifi_mtu
? .ieee80211_netbsd.h.swp
Index: ieee80211_netbsd.c
===================================================================
RCS file: /cvsroot/src/sys/net80211/ieee80211_netbsd.c,v
retrieving revision 1.18
diff -u -p -r1.18 ieee80211_netbsd.c
--- ieee80211_netbsd.c  17 Jul 2011 20:54:52 -0000      1.18
+++ ieee80211_netbsd.c  5 Oct 2011 22:32:24 -0000
@@ -488,15 +488,11 @@ err:
 int
 ieee80211_node_dectestref(struct ieee80211_node *ni)
 {
-       int rc, s;
-       s = splnet();
-       if (--ni->ni_refcnt == 0) {
-               rc = 1;
-               ni->ni_refcnt = 1;
+       if (atomic_dec_uint_nv(&ni->ni_refcnt) == 0) {
+               atomic_inc_uint(&ni->ni_refcnt);
+               return 1;
        } else
-               rc = 0;
-       splx(s);
-       return rc;
+               return 0;
 }
 
 void
Index: ieee80211_netbsd.h
===================================================================
RCS file: /cvsroot/src/sys/net80211/ieee80211_netbsd.h,v
retrieving revision 1.15
diff -u -p -r1.15 ieee80211_netbsd.h
--- ieee80211_netbsd.h  15 Jun 2008 16:42:19 -0000      1.15
+++ ieee80211_netbsd.h  5 Oct 2011 22:32:24 -0000
@@ -30,6 +30,8 @@
 #ifndef _NET80211_IEEE80211_NETBSD_H_
 #define _NET80211_IEEE80211_NETBSD_H_
 
+#include <sys/atomic.h>
+
 #ifdef _KERNEL
 #define        IASSERT(__cond, __complaint)            \
        do {                                    \
@@ -167,9 +169,9 @@ typedef kmutex_t acl_lock_t;
 #define ieee80211_node_initref(_ni) \
        do { ((_ni)->ni_refcnt = 1); } while (0)
 #define ieee80211_node_incref(_ni) \
-       do { (_ni)->ni_refcnt++; } while (0)
+       atomic_inc_uint(&(_ni)->ni_refcnt)
 #define        ieee80211_node_decref(_ni) \
-       do { (_ni)->ni_refcnt--; } while (0)
+       atomic_dec_uint(&(_ni)->ni_refcnt)
 struct ieee80211_node;
 int ieee80211_node_dectestref(struct ieee80211_node *ni);
 #define        ieee80211_node_refcnt(_ni)      (_ni)->ni_refcnt


Home | Main Index | Thread Index | Old Index