Implement TSO
[akaros.git] / kern / src / net / arp.c
index 11f4fb1..00e07b0 100644 (file)
@@ -1,28 +1,31 @@
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "../port/error.h"
-
-#include "ip.h"
-#include "ipv6.h"
+// INFERNO
+#include <vfs.h>
+#include <kfs.h>
+#include <slab.h>
+#include <kmalloc.h>
+#include <kref.h>
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+#include <error.h>
+#include <cpio.h>
+#include <pmap.h>
+#include <smp.h>
+#include <ip.h>
 
 /*
  *  address resolution tables
  */
 
-enum
-{
-       NHASH           = (1<<6),
-       NCACHE          = 256,
+enum {
+       NHASH = (1 << 6),
+       NCACHE = 256,
 
-       AOK             = 1,
-       AWAIT           = 2,
+       AOK = 1,
+       AWAIT = 2,
 };
 
-char *arpstate[] =
-{
+char *arpstate[] = {
        "UNUSED",
        "OK",
        "WAIT",
@@ -31,53 +34,53 @@ char *arpstate[] =
 /*
  *  one per Fs
  */
-struct Arp
-{
-       QLock;
-       Fs      *f;
-       Arpent  *hash[NHASH];
-       Arpent  cache[NCACHE];
-       Arpent  *rxmt;
-       Proc    *rxmitp;        /* neib sol re-transmit proc */
-       Rendez  rxmtq;
-       Block   *dropf, *dropl;
+struct arp {
+       qlock_t qlock;
+       struct Fs *f;
+       struct arpent *hash[NHASH];
+       struct arpent cache[NCACHE];
+       struct arpent *rxmt;
+       struct proc *rxmitp;            /* neib sol re-transmit proc */
+       struct rendez rxmtq;
+       struct block *dropf, *dropl;
 };
 
 char *Ebadarp = "bad arp";
 
 #define haship(s) ((s)[IPaddrlen-1]%NHASH)
 
-extern int     ReTransTimer = RETRANS_TIMER;
-static void    rxmitproc(void *v);
+int ReTransTimer = RETRANS_TIMER;
+static void rxmitproc(void *v);
 
-void
-arpinit(Fs *f)
+void arpinit(struct Fs *f)
 {
-       f->arp = smalloc(sizeof(Arp));
+       f->arp = kzmalloc(sizeof(struct arp), KMALLOC_WAIT);
+       qlock_init(&f->arp->qlock);
+       rendez_init(&f->arp->rxmtq);
        f->arp->f = f;
-       f->arp->rxmt = nil;
-       f->arp->dropf = f->arp->dropl = nil;
-       kproc("rxmitproc", rxmitproc, f->arp, 0);
+       f->arp->rxmt = NULL;
+       f->arp->dropf = f->arp->dropl = NULL;
+       ktask("rxmitproc", rxmitproc, f->arp);
 }
 
 /*
  *  create a new arp entry for an ip address.
  */
-static Arpent*
-newarp6(Arp *arp, uchar *ip, Ipifc *ifc, int addrxt)
+static struct arpent *newarp6(struct arp *arp, uint8_t * ip, struct Ipifc *ifc,
+                                                         int addrxt)
 {
-       uint t;
-       Block *next, *xp;
-       Arpent *a, *e, *f, **l;
-       Medium *m = ifc->m;
+       unsigned int t;
+       struct block *next, *xp;
+       struct arpent *a, *e, *f, **l;
+       struct medium *m = ifc->m;
        int empty;
 
        /* find oldest entry */
        e = &arp->cache[NCACHE];
        a = arp->cache;
        t = a->utime;
-       for(f = a; f < e; f++){
-               if(f->utime < t){
+       for (f = a; f < e; f++) {
+               if (f->utime < t) {
                        t = f->utime;
                        a = f;
                }
@@ -85,33 +88,32 @@ newarp6(Arp *arp, uchar *ip, Ipifc *ifc, int addrxt)
 
        /* dump waiting packets */
        xp = a->hold;
-       a->hold = nil;
+       a->hold = NULL;
 
-       if(isv4(a->ip)){
-               while(xp){
+       if (isv4(a->ip)) {
+               while (xp) {
                        next = xp->list;
                        freeblist(xp);
                        xp = next;
                }
-       }
-       else {  // queue icmp unreachable for rxmitproc later on, w/o arp lock
-               if(xp){
-                       if(arp->dropl == nil) 
+       } else {        // queue icmp unreachable for rxmitproc later on, w/o arp lock
+               if (xp) {
+                       if (arp->dropl == NULL)
                                arp->dropf = xp;
                        else
                                arp->dropl->list = xp;
 
-                       for(next = xp->list; next; next = next->list)
+                       for (next = xp->list; next; next = next->list)
                                xp = next;
                        arp->dropl = xp;
-                       wakeup(&arp->rxmtq);
+                       rendez_wakeup(&arp->rxmtq);
                }
        }
 
        /* take out of current chain */
        l = &arp->hash[haship(a->ip)];
-       for(f = *l; f; f = f->hash){
-               if(f == a){
+       for (f = *l; f; f = f->hash) {
+               if (f == a) {
                        *l = a->hash;
                        break;
                }
@@ -134,46 +136,45 @@ newarp6(Arp *arp, uchar *ip, Ipifc *ifc, int addrxt)
        a->ifcid = ifc->ifcid;
 
        /* put to the end of re-transmit chain; addrxt is 0 when isv4(a->ip) */
-       if(!ipismulticast(a->ip) && addrxt){
+       if (!ipismulticast(a->ip) && addrxt) {
                l = &arp->rxmt;
-               empty = (*l==nil);
+               empty = (*l == NULL);
 
-               for(f = *l; f; f = f->nextrxt){
-                       if(f == a){
+               for (f = *l; f; f = f->nextrxt) {
+                       if (f == a) {
                                *l = a->nextrxt;
                                break;
                        }
                        l = &f->nextrxt;
                }
-               for(f = *l; f; f = f->nextrxt){
+               for (f = *l; f; f = f->nextrxt) {
                        l = &f->nextrxt;
                }
                *l = a;
-               if(empty) 
-                       wakeup(&arp->rxmtq);
+               if (empty)
+                       rendez_wakeup(&arp->rxmtq);
        }
 
-       a->nextrxt = nil;
+       a->nextrxt = NULL;
 
        return a;
 }
 
 /* called with arp qlocked */
 
-void
-cleanarpent(Arp *arp, Arpent *a)
+void cleanarpent(struct arp *arp, struct arpent *a)
 {
-       Arpent *f, **l;
+       struct arpent *f, **l;
 
        a->utime = 0;
        a->ctime = 0;
        a->type = 0;
        a->state = 0;
-       
+
        /* take out of current chain */
        l = &arp->hash[haship(a->ip)];
-       for(f = *l; f; f = f->hash){
-               if(f == a){
+       for (f = *l; f; f = f->hash) {
+               if (f == a) {
                        *l = a->hash;
                        break;
                }
@@ -182,99 +183,105 @@ cleanarpent(Arp *arp, Arpent *a)
 
        /* take out of re-transmit chain */
        l = &arp->rxmt;
-       for(f = *l; f; f = f->nextrxt){
-               if(f == a){
+       for (f = *l; f; f = f->nextrxt) {
+               if (f == a) {
                        *l = a->nextrxt;
                        break;
                }
                l = &f->nextrxt;
        }
-       a->nextrxt = nil;
-       a->hash = nil;
-       a->hold = nil;
-       a->last = nil;
-       a->ifc = nil;
+       a->nextrxt = NULL;
+       a->hash = NULL;
+       a->hold = NULL;
+       a->last = NULL;
+       a->ifc = NULL;
 }
 
 /*
  *  fill in the media address if we have it.  Otherwise return an
- *  Arpent that represents the state of the address resolution FSM
+ *  arpent that represents the state of the address resolution FSM
  *  for ip.  Add the packet to be sent onto the list of packets
  *  waiting for ip->mac to be resolved.
  */
-Arpent*
-arpget(Arp *arp, Block *bp, int version, Ipifc *ifc, uchar *ip, uchar *mac)
+struct arpent *arpget(struct arp *arp, struct block *bp, int version,
+                                         struct Ipifc *ifc, uint8_t * ip, uint8_t * mac)
 {
-       int hash;
-       Arpent *a;
-       Medium *type = ifc->m;
-       uchar v6ip[IPaddrlen];
+       int hash, len;
+       struct arpent *a;
+       struct medium *type = ifc->m;
+       uint8_t v6ip[IPaddrlen];
+       uint16_t *s, *d;
 
-       if(version == V4){
+       if (version == V4) {
                v4tov6(v6ip, ip);
                ip = v6ip;
        }
 
-       qlock(arp);
+       qlock(&arp->qlock);
        hash = haship(ip);
-       for(a = arp->hash[hash]; a; a = a->hash){
-               if(memcmp(ip, a->ip, sizeof(a->ip)) == 0)
-               if(type == a->type)
-                       break;
+       for (a = arp->hash[hash]; a; a = a->hash) {
+               if (ipcmp(ip, a->ip) == 0)
+                       if (type == a->type)
+                               break;
        }
 
-       if(a == nil){
+       if (a == NULL) {
                a = newarp6(arp, ip, ifc, (version != V4));
                a->state = AWAIT;
        }
        a->utime = NOW;
-       if(a->state == AWAIT){
-               if(bp != nil){
-                       if(a->hold)
+       if (a->state == AWAIT) {
+               if (bp != NULL) {
+                       if (a->hold)
                                a->last->list = bp;
                        else
                                a->hold = bp;
                        a->last = bp;
-                       bp->list = nil; 
+                       bp->list = NULL;
                }
-               return a;               /* return with arp qlocked */
+               return a;       /* return with arp qlocked */
        }
 
-       memmove(mac, a->mac, a->type->maclen);
+       s = (uint16_t *)a->mac;
+       d = (uint16_t *)mac;
+       len = a->type->maclen / 2;
+       while (len) {
+               *d++ = *s++;
+               len--;
+       }
 
        /* remove old entries */
-       if(NOW - a->ctime > 15*60*1000)
+       if (NOW - a->ctime > 15 * 60 * 1000)
                cleanarpent(arp, a);
 
-       qunlock(arp);
-       return nil;
+       qunlock(&arp->qlock);
+       return NULL;
 }
 
 /*
  * called with arp locked
  */
-void
-arprelease(Arp *arp, Arpent*)
+void arprelease(struct arp *arp, struct arpent *a)
 {
-       qunlock(arp);
+       qunlock(&arp->qlock);
 }
 
 /*
- * Copy out the mac address from the Arpent.  Return the
+ * Copy out the mac address from the arpent.  Return the
  * block waiting to get sent to this mac address.
  *
  * called with arp locked
  */
-Block*
-arpresolve(Arp *arp, Arpent *a, Medium *type, uchar *mac)
+struct block *arpresolve(struct arp *arp, struct arpent *a, struct medium *type,
+                                                uint8_t * mac)
 {
-       Block *bp;
-       Arpent *f, **l;
+       struct block *bp;
+       struct arpent *f, **l;
 
-       if(!isv4(a->ip)){
+       if (!isv4(a->ip)) {
                l = &arp->rxmt;
-               for(f = *l; f; f = f->nextrxt){
-                       if(f == a){
+               for (f = *l; f; f = f->nextrxt) {
+                       if (f == a) {
                                *l = a->nextrxt;
                                break;
                        }
@@ -287,66 +294,68 @@ arpresolve(Arp *arp, Arpent *a, Medium *type, uchar *mac)
        a->state = AOK;
        a->utime = NOW;
        bp = a->hold;
-       a->hold = nil;
-       qunlock(arp);
+       a->hold = NULL;
+       qunlock(&arp->qlock);
 
        return bp;
 }
 
 void
-arpenter(Fs *fs, int version, uchar *ip, uchar *mac, int n, int refresh)
+arpenter(struct Fs *fs, int version, uint8_t * ip, uint8_t * mac, int n,
+                int refresh)
 {
-       Arp *arp;
-       Route *r;
-       Arpent *a, *f, **l;
-       Ipifc *ifc;
-       Medium *type;
-       Block *bp, *next;
-       uchar v6ip[IPaddrlen];
+       ERRSTACK(1);
+       struct arp *arp;
+       struct route *r;
+       struct arpent *a, *f, **l;
+       struct Ipifc *ifc;
+       struct medium *type;
+       struct block *bp, *next;
+       uint8_t v6ip[IPaddrlen];
 
        arp = fs->arp;
 
-       if(n != 6){
-//             print("arp: len = %d\n", n);
+       if (n != 6) {
+//      print("arp: len = %d\n", n);
                return;
        }
 
-       switch(version){
-       case V4:
-               r = v4lookup(fs, ip, nil);
-               v4tov6(v6ip, ip);
-               ip = v6ip;
-               break;
-       case V6:
-               r = v6lookup(fs, ip, nil);
-               break;
-       default:
-               panic("arpenter: version %d", version);
-               return; /* to supress warnings */
+       switch (version) {
+               case V4:
+                       r = v4lookup(fs, ip, NULL);
+                       v4tov6(v6ip, ip);
+                       ip = v6ip;
+                       break;
+               case V6:
+                       r = v6lookup(fs, ip, NULL);
+                       break;
+               default:
+                       panic("arpenter: version %d", version);
+                       return; /* to supress warnings */
        }
 
-       if(r == nil){
-//             print("arp: no route for entry\n");
+       if (r == NULL) {
+//      print("arp: no route for entry\n");
                return;
        }
 
-       ifc = r->ifc;
+       ifc = r->rt.ifc;
        type = ifc->m;
 
-       qlock(arp);
-       for(a = arp->hash[haship(ip)]; a; a = a->hash){
-               if(a->type != type || (a->state != AWAIT && a->state != AOK))
+       qlock(&arp->qlock);
+       for (a = arp->hash[haship(ip)]; a; a = a->hash) {
+               if (a->type != type || (a->state != AWAIT && a->state != AOK))
                        continue;
 
-               if(ipcmp(a->ip, ip) == 0){
+               if (ipcmp(a->ip, ip) == 0) {
                        a->state = AOK;
                        memmove(a->mac, mac, type->maclen);
 
-                       if(version == V6){
+                       if (version == V6) {
                                /* take out of re-transmit chain */
                                l = &arp->rxmt;
-                               for(f = *l; f; f = f->nextrxt){
-                                       if(f == a){
+                               for (f = *l; f; f = f->nextrxt) {
+                                       if (f == a) {
                                                *l = a->nextrxt;
                                                break;
                                        }
@@ -357,26 +366,26 @@ arpenter(Fs *fs, int version, uchar *ip, uchar *mac, int n, int refresh)
                        a->ifc = ifc;
                        a->ifcid = ifc->ifcid;
                        bp = a->hold;
-                       a->hold = nil;
-                       if(version == V4)
+                       a->hold = NULL;
+                       if (version == V4)
                                ip += IPv4off;
                        a->utime = NOW;
                        a->ctime = a->utime;
-                       qunlock(arp);
+                       qunlock(&arp->qlock);
 
-                       while(bp){
+                       while (bp) {
                                next = bp->list;
-                               if(ifc != nil){
-                                       if(waserror()){
-                                               runlock(ifc);
+                               if (ifc != NULL) {
+                                       if (waserror()) {
+                                               runlock(&ifc->rwlock);
                                                nexterror();
                                        }
-                                       rlock(ifc);
-                                       if(ifc->m != nil)
+                                       rlock(&ifc->rwlock);
+                                       if (ifc->m != NULL)
                                                ifc->m->bwrite(ifc, bp, version, ip);
                                        else
                                                freeb(bp);
-                                       runlock(ifc);
+                                       runlock(&ifc->rwlock);
                                        poperror();
                                } else
                                        freeb(bp);
@@ -386,7 +395,7 @@ arpenter(Fs *fs, int version, uchar *ip, uchar *mac, int n, int refresh)
                }
        }
 
-       if(refresh == 0){
+       if (refresh == 0) {
                a = newarp6(arp, ip, ifc, 0);
                a->state = AOK;
                a->type = type;
@@ -394,42 +403,41 @@ arpenter(Fs *fs, int version, uchar *ip, uchar *mac, int n, int refresh)
                memmove(a->mac, mac, type->maclen);
        }
 
-       qunlock(arp);
+       qunlock(&arp->qlock);
 }
 
-int
-arpwrite(Fs *fs, char *s, int len)
+int arpwrite(struct Fs *fs, char *s, int len)
 {
        int n;
-       Route *r;
-       Arp *arp;
-       Block *bp;
-       Arpent *a, *fl, **l;
-       Medium *m;
+       struct route *r;
+       struct arp *arp;
+       struct block *bp;
+       struct arpent *a, *fl, **l;
+       struct medium *m;
        char *f[4], buf[256];
-       uchar ip[IPaddrlen], mac[MAClen];
+       uint8_t ip[IPaddrlen], mac[MAClen];
 
        arp = fs->arp;
 
-       if(len == 0)
+       if (len == 0)
                error(Ebadarp);
-       if(len >= sizeof(buf))
-               len = sizeof(buf)-1;
+       if (len >= sizeof(buf))
+               len = sizeof(buf) - 1;
        strncpy(buf, s, len);
        buf[len] = 0;
-       if(len > 0 && buf[len-1] == '\n')
-               buf[len-1] = 0;
+       if (len > 0 && buf[len - 1] == '\n')
+               buf[len - 1] = 0;
 
        n = getfields(buf, f, 4, 1, " ");
-       if(strcmp(f[0], "flush") == 0){
-               qlock(arp);
-               for(a = arp->cache; a < &arp->cache[NCACHE]; a++){
+       if (strcmp(f[0], "flush") == 0) {
+               qlock(&arp->qlock);
+               for (a = arp->cache; a < &arp->cache[NCACHE]; a++) {
                        memset(a->ip, 0, sizeof(a->ip));
                        memset(a->mac, 0, sizeof(a->mac));
-                       a->hash = nil;
+                       a->hash = NULL;
                        a->state = 0;
                        a->utime = 0;
-                       while(a->hold != nil){
+                       while (a->hold != NULL) {
                                bp = a->hold->list;
                                freeblist(a->hold);
                                a->hold = bp;
@@ -437,208 +445,214 @@ arpwrite(Fs *fs, char *s, int len)
                }
                memset(arp->hash, 0, sizeof(arp->hash));
 // clear all pkts on these lists (rxmt, dropf/l)
-               arp->rxmt = nil;
-               arp->dropf = nil;
-               arp->dropl = nil;
-               qunlock(arp);
-       } else if(strcmp(f[0], "add") == 0){
-               switch(n){
-               default:
-                       error(Ebadarg);
-               case 3:
-                       parseip(ip, f[1]);
-                       if(isv4(ip))
-                               r = v4lookup(fs, ip+IPv4off, nil);
-                       else
-                               r = v6lookup(fs, ip, nil);
-                       if(r == nil)
-                               error("Destination unreachable");
-                       m = r->ifc->m;
-                       n = parsemac(mac, f[2], m->maclen);
-                       break;
-               case 4:
-                       m = ipfindmedium(f[1]);
-                       if(m == nil)
-                               error(Ebadarp);
-                       parseip(ip, f[2]);
-                       n = parsemac(mac, f[3], m->maclen);
-                       break;
+               arp->rxmt = NULL;
+               arp->dropf = NULL;
+               arp->dropl = NULL;
+               qunlock(&arp->qlock);
+       } else if (strcmp(f[0], "add") == 0) {
+               switch (n) {
+                       default:
+                               error(Ebadarg);
+                       case 3:
+                               parseip(ip, f[1]);
+                               if (isv4(ip))
+                                       r = v4lookup(fs, ip + IPv4off, NULL);
+                               else
+                                       r = v6lookup(fs, ip, NULL);
+                               if (r == NULL)
+                                       error("Destination unreachable");
+                               m = r->rt.ifc->m;
+                               n = parsemac(mac, f[2], m->maclen);
+                               break;
+                       case 4:
+                               m = ipfindmedium(f[1]);
+                               if (m == NULL)
+                                       error(Ebadarp);
+                               parseip(ip, f[2]);
+                               n = parsemac(mac, f[3], m->maclen);
+                               break;
                }
 
-               if(m->ares == nil)
+               if (m->ares == NULL)
                        error(Ebadarp);
 
                m->ares(fs, V6, ip, mac, n, 0);
-       } else if(strcmp(f[0], "del") == 0){
-               if(n != 2)
+       } else if (strcmp(f[0], "del") == 0) {
+               if (n != 2)
                        error(Ebadarg);
 
                parseip(ip, f[1]);
-               qlock(arp);
+               qlock(&arp->qlock);
 
                l = &arp->hash[haship(ip)];
-               for(a = *l; a; a = a->hash){
-                       if(memcmp(ip, a->ip, sizeof(a->ip)) == 0){
+               for (a = *l; a; a = a->hash) {
+                       if (memcmp(ip, a->ip, sizeof(a->ip)) == 0) {
                                *l = a->hash;
                                break;
                        }
                        l = &a->hash;
                }
-       
-               if(a){
+
+               if (a) {
                        /* take out of re-transmit chain */
                        l = &arp->rxmt;
-                       for(fl = *l; fl; fl = fl->nextrxt){
-                               if(fl == a){
+                       for (fl = *l; fl; fl = fl->nextrxt) {
+                               if (fl == a) {
                                        *l = a->nextrxt;
                                        break;
                                }
                                l = &fl->nextrxt;
                        }
 
-                       a->nextrxt = nil;
-                       a->hash = nil;
-                       a->hold = nil;
-                       a->last = nil;
-                       a->ifc = nil;
+                       a->nextrxt = NULL;
+                       a->hash = NULL;
+                       a->hold = NULL;
+                       a->last = NULL;
+                       a->ifc = NULL;
                        memset(a->ip, 0, sizeof(a->ip));
                        memset(a->mac, 0, sizeof(a->mac));
                }
-               qunlock(arp);
+               qunlock(&arp->qlock);
        } else
                error(Ebadarp);
 
        return len;
 }
 
-enum
-{
-       Alinelen=       90,
+enum {
+       Alinelen = 90,
 };
 
-char *aformat = "%-6.6s %-8.8s %-40.40I %-32.32s\n";
+char *aformat = "%-6.6s %-8.8s %-40.40I %E\n";
 
-static void
-convmac(char *p, uchar *mac, int n)
+static void convmac(char *p, uint8_t * mac, int n)
 {
-       while(n-- > 0)
-               p += sprint(p, "%2.2ux", *mac++);
+       int left = n;
+       while (n-- > 0) {
+               p += snprintf(p, left, "%02x", *mac++);
+               if (n > 1)
+                       p += snprintf(p, left, ":");
+               left -= n;
+       }
 }
 
-int
-arpread(Arp *arp, char *p, ulong offset, int len)
+int arpread(struct arp *arp, char *p, uint32_t offset, int len)
 {
-       Arpent *a;
+       struct arpent *a;
        int n;
-       char mac[2*MAClen+1];
+       char mac[2 * MAClen + 1];
+       int left = len;
+       int amt;
 
-       if(offset % Alinelen)
+       if (offset % Alinelen)
                return 0;
 
-       offset = offset/Alinelen;
-       len = len/Alinelen;
+       offset = offset / Alinelen;
+       len = len / Alinelen;
 
        n = 0;
-       for(a = arp->cache; len > 0 && a < &arp->cache[NCACHE]; a++){
-               if(a->state == 0)
+       for (a = arp->cache; len > 0 && a < &arp->cache[NCACHE]; a++) {
+               if (a->state == 0)
                        continue;
-               if(offset > 0){
+               if (offset > 0) {
                        offset--;
                        continue;
                }
                len--;
-               qlock(arp);
+               left--;
+               qlock(&arp->qlock);
                convmac(mac, a->mac, a->type->maclen);
-               n += sprint(p+n, aformat, a->type->name, arpstate[a->state], a->ip, mac);
-               qunlock(arp);
+               amt = snprintf(p + n, left,
+                                          aformat, a->type->name, arpstate[a->state], a->ip, mac);
+               n += amt;
+               left -= amt;
+               qunlock(&arp->qlock);
        }
 
        return n;
 }
 
-extern int
-rxmitsols(Arp *arp)
+extern int rxmitsols(struct arp *arp)
 {
-       uint sflag;
-       Block *next, *xp;
-       Arpent *a, *b, **l;
-       Fs *f;
-       uchar ipsrc[IPaddrlen];
-       Ipifc *ifc = nil;
+       unsigned int sflag;
+       struct block *next, *xp;
+       struct arpent *a, *b, **l;
+       struct Fs *f;
+       uint8_t ipsrc[IPaddrlen];
+       struct Ipifc *ifc = NULL;
        long nrxt;
 
-       qlock(arp);
+       qlock(&arp->qlock);
        f = arp->f;
 
        a = arp->rxmt;
-       if(a==nil){
+       if (a == NULL) {
                nrxt = 0;
-               goto dodrops;           //return nrxt;
+               goto dodrops;   //return nrxt;
        }
        nrxt = a->rtime - NOW;
-       if(nrxt > 3*ReTransTimer/4) 
-               goto dodrops;           //return nrxt;
+       if (nrxt > 3 * ReTransTimer / 4)
+               goto dodrops;   //return nrxt;
 
-       for(; a; a = a->nextrxt){
+       for (; a; a = a->nextrxt) {
                ifc = a->ifc;
-               assert(ifc != nil);
-               if((a->rxtsrem <= 0) || !(canrlock(ifc)) || (a->ifcid != ifc->ifcid)){
+               assert(ifc != NULL);
+               if ((a->rxtsrem <= 0) || !(canrlock(&ifc->rwlock))
+                       || (a->ifcid != ifc->ifcid)) {
                        xp = a->hold;
-                       a->hold = nil;
+                       a->hold = NULL;
 
-                       if(xp){
-                               if(arp->dropl == nil) 
+                       if (xp) {
+                               if (arp->dropl == NULL)
                                        arp->dropf = xp;
                                else
                                        arp->dropl->list = xp;
                        }
 
                        cleanarpent(arp, a);
-               }
-               else
+               } else
                        break;
        }
-       if(a == nil)
+       if (a == NULL)
                goto dodrops;
 
+       qunlock(&arp->qlock);   /* for icmpns */
+       if ((sflag = ipv6anylocal(ifc, ipsrc)) != SRC_UNSPEC)
+               icmpns(f, ipsrc, sflag, a->ip, TARG_MULTI, ifc->mac);
 
-       qunlock(arp);   /* for icmpns */
-       if((sflag = ipv6anylocal(ifc, ipsrc)) != SRC_UNSPEC) 
-               icmpns(f, ipsrc, sflag, a->ip, TARG_MULTI, ifc->mac); 
-
-       runlock(ifc);
-       qlock(arp);     
+       runlock(&ifc->rwlock);
+       qlock(&arp->qlock);
 
        /* put to the end of re-transmit chain */
        l = &arp->rxmt;
-       for(b = *l; b; b = b->nextrxt){
-               if(b == a){
+       for (b = *l; b; b = b->nextrxt) {
+               if (b == a) {
                        *l = a->nextrxt;
                        break;
                }
                l = &b->nextrxt;
        }
-       for(b = *l; b; b = b->nextrxt){
+       for (b = *l; b; b = b->nextrxt) {
                l = &b->nextrxt;
        }
        *l = a;
        a->rxtsrem--;
-       a->nextrxt = nil;
+       a->nextrxt = NULL;
        a->rtime = NOW + ReTransTimer;
 
        a = arp->rxmt;
-       if(a==nil)
+       if (a == NULL)
                nrxt = 0;
-       else 
+       else
                nrxt = a->rtime - NOW;
 
 dodrops:
        xp = arp->dropf;
-       arp->dropf = nil;
-       arp->dropl = nil;
-       qunlock(arp);
+       arp->dropf = NULL;
+       arp->dropl = NULL;
+       qunlock(&arp->qlock);
 
-       for(; xp; xp = next){
+       for (; xp; xp = next) {
                next = xp->list;
                icmphostunr(f, ifc, xp, icmp6_adr_unreach, 1);
        }
@@ -647,35 +661,36 @@ dodrops:
 
 }
 
-static int
-rxready(void *v)
+static int rxready(void *v)
 {
-       Arp *arp = (Arp *) v;
+       struct arp *arp = (struct arp *)v;
        int x;
 
-       x = ((arp->rxmt != nil) || (arp->dropf != nil));
+       x = ((arp->rxmt != NULL) || (arp->dropf != NULL));
 
        return x;
 }
 
-static void
-rxmitproc(void *v)
+static void rxmitproc(void *v)
 {
-       Arp *arp = v;
+       ERRSTACK(2);
+       struct arp *arp = v;
        long wakeupat;
 
-       arp->rxmitp = up;
+       arp->rxmitp = current;
        //print("arp rxmitproc started\n");
-       if(waserror()){
+       if (waserror()) {
                arp->rxmitp = 0;
-               pexit("hangup", 1);
+               poperror();
+               warn("arp rxmit ktask exited");
+               return;
        }
-       for(;;){
+       for (;;) {
                wakeupat = rxmitsols(arp);
-               if(wakeupat == 0) 
-                       sleep(&arp->rxmtq, rxready, v); 
-               else if(wakeupat > ReTransTimer/4) 
-                       tsleep(&arp->rxmtq, return0, 0, wakeupat); 
+               if (wakeupat == 0)
+                       rendez_sleep(&arp->rxmtq, rxready, v);
+               else if (wakeupat > ReTransTimer / 4)
+                       udelay_sched(wakeupat * 1000);
        }
+       poperror();
 }
-