net: tcp: Don't increment snd.nxt
[akaros.git] / kern / src / net / arp.c
index 6a244ba..1c240a0 100644 (file)
@@ -1,4 +1,31 @@
-// INFERNO
+/* Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+ * Portions Copyright © 1997-1999 Vita Nuova Limited
+ * Portions Copyright © 2000-2007 Vita Nuova Holdings Limited
+ *                                (www.vitanuova.com)
+ * Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+ *
+ * Modified for the Akaros operating system:
+ * Copyright (c) 2013-2014 The Regents of the University of California
+ * Copyright (c) 2013-2015 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE. */
+
 #include <vfs.h>
 #include <kfs.h>
 #include <slab.h>
@@ -45,8 +72,6 @@ struct arp {
        struct block *dropf, *dropl;
 };
 
-char *Ebadarp = "bad arp";
-
 #define haship(s) ((s)[IPaddrlen-1]%NHASH)
 
 int ReTransTimer = RETRANS_TIMER;
@@ -54,7 +79,7 @@ static void rxmitproc(void *v);
 
 void arpinit(struct Fs *f)
 {
-       f->arp = kzmalloc(sizeof(struct arp), KMALLOC_WAIT);
+       f->arp = kzmalloc(sizeof(struct arp), MEM_WAIT);
        qlock_init(&f->arp->qlock);
        rendez_init(&f->arp->rxmtq);
        f->arp->f = f;
@@ -66,8 +91,8 @@ void arpinit(struct Fs *f)
 /*
  *  create a new arp entry for an ip address.
  */
-static struct arpent *newarp6(struct arp *arp, uint8_t * ip, struct Ipifc *ifc,
-                                                         int addrxt)
+static struct arpent *newarp6(struct arp *arp, uint8_t *ip, struct Ipifc *ifc,
+                              int addrxt)
 {
        unsigned int t;
        struct block *next, *xp;
@@ -96,7 +121,8 @@ static struct arpent *newarp6(struct arp *arp, uint8_t * ip, struct Ipifc *ifc,
                        freeblist(xp);
                        xp = next;
                }
-       } else {        // queue icmp unreachable for rxmitproc later on, w/o arp lock
+       } else {
+               /* queue icmp unreachable for rxmitproc later, w/o arp lock */
                if (xp) {
                        if (arp->dropl == NULL)
                                arp->dropf = xp;
@@ -127,7 +153,7 @@ static struct arpent *newarp6(struct arp *arp, uint8_t * ip, struct Ipifc *ifc,
 
        memmove(a->ip, ip, sizeof(a->ip));
        a->utime = NOW;
-       a->ctime = 0;
+       a->ctime = 0;   /* somewhat of a "last sent time".  0, to trigger a send. */
        a->type = m;
 
        a->rtime = NOW + ReTransTimer;
@@ -204,12 +230,13 @@ void cleanarpent(struct arp *arp, struct arpent *a)
  *  waiting for ip->mac to be resolved.
  */
 struct arpent *arpget(struct arp *arp, struct block *bp, int version,
-                                         struct Ipifc *ifc, uint8_t * ip, uint8_t * mac)
+                      struct Ipifc *ifc, uint8_t *ip, uint8_t *mac)
 {
-       int hash;
+       int hash, len;
        struct arpent *a;
        struct medium *type = ifc->m;
        uint8_t v6ip[IPaddrlen];
+       uint16_t *s, *d;
 
        if (version == V4) {
                v4tov6(v6ip, ip);
@@ -219,7 +246,7 @@ struct arpent *arpget(struct arp *arp, struct block *bp, int version,
        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 (ipcmp(ip, a->ip) == 0)
                        if (type == a->type)
                                break;
        }
@@ -241,7 +268,13 @@ struct arpent *arpget(struct arp *arp, struct block *bp, int version,
                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)
@@ -266,7 +299,7 @@ void arprelease(struct arp *arp, struct arpent *a)
  * called with arp locked
  */
 struct block *arpresolve(struct arp *arp, struct arpent *a, struct medium *type,
-                                                uint8_t * mac)
+                         uint8_t *mac)
 {
        struct block *bp;
        struct arpent *f, **l;
@@ -288,14 +321,17 @@ struct block *arpresolve(struct arp *arp, struct arpent *a, struct medium *type,
        a->utime = NOW;
        bp = a->hold;
        a->hold = NULL;
+       /* brho: it looks like we return the entire hold list, though it might be
+        * purged by now via some other crazy arp list management.  our callers
+        * can't handle the arp's b->list stuff. */
+       assert(!bp->list);
        qunlock(&arp->qlock);
 
        return bp;
 }
 
-void
-arpenter(struct Fs *fs, int version, uint8_t * ip, uint8_t * mac, int n,
-                int refresh)
+void arpenter(struct Fs *fs, int version, uint8_t *ip, uint8_t *mac, int n,
+              int refresh)
 {
        ERRSTACK(1);
        struct arp *arp;
@@ -309,7 +345,6 @@ arpenter(struct Fs *fs, int version, uint8_t * ip, uint8_t * mac, int n,
        arp = fs->arp;
 
        if (n != 6) {
-//      print("arp: len = %d\n", n);
                return;
        }
 
@@ -328,7 +363,6 @@ arpenter(struct Fs *fs, int version, uint8_t * ip, uint8_t * mac, int n,
        }
 
        if (r == NULL) {
-//      print("arp: no route for entry\n");
                return;
        }
 
@@ -369,11 +403,11 @@ arpenter(struct Fs *fs, int version, uint8_t * ip, uint8_t * mac, int n,
                        while (bp) {
                                next = bp->list;
                                if (ifc != NULL) {
+                                       rlock(&ifc->rwlock);
                                        if (waserror()) {
                                                runlock(&ifc->rwlock);
                                                nexterror();
                                        }
-                                       rlock(&ifc->rwlock);
                                        if (ifc->m != NULL)
                                                ifc->m->bwrite(ifc, bp, version, ip);
                                        else
@@ -399,7 +433,7 @@ arpenter(struct Fs *fs, int version, uint8_t * ip, uint8_t * mac, int n,
        qunlock(&arp->qlock);
 }
 
-int arpwrite(struct Fs *fs, char *s, int len)
+int arpwrite(struct Fs *fs, char *s, long len)
 {
        int n;
        struct route *r;
@@ -412,14 +446,13 @@ int arpwrite(struct Fs *fs, char *s, int len)
 
        arp = fs->arp;
 
-       if (len == 0)
-               error(Ebadarp);
-       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)
+               error(EINVAL, ERROR_FIXME);
+       if (len > sizeof(buf))
+               len = sizeof(buf);
+       strlcpy(buf, s, sizeof(buf));
+       if (len > 0 && buf[len - 2] == '\n')
+               buf[len - 2] = 0;
 
        n = getfields(buf, f, 4, 1, " ");
        if (strcmp(f[0], "flush") == 0) {
@@ -437,7 +470,7 @@ int arpwrite(struct Fs *fs, char *s, int len)
                        }
                }
                memset(arp->hash, 0, sizeof(arp->hash));
-// clear all pkts on these lists (rxmt, dropf/l)
+               /* clear all pkts on these lists (rxmt, dropf/l) */
                arp->rxmt = NULL;
                arp->dropf = NULL;
                arp->dropl = NULL;
@@ -445,7 +478,7 @@ int arpwrite(struct Fs *fs, char *s, int len)
        } else if (strcmp(f[0], "add") == 0) {
                switch (n) {
                        default:
-                               error(Ebadarg);
+                               error(EINVAL, ERROR_FIXME);
                        case 3:
                                parseip(ip, f[1]);
                                if (isv4(ip))
@@ -453,26 +486,26 @@ int arpwrite(struct Fs *fs, char *s, int len)
                                else
                                        r = v6lookup(fs, ip, NULL);
                                if (r == NULL)
-                                       error("Destination unreachable");
+                                       error(EHOSTUNREACH, "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);
+                                       error(EINVAL, ERROR_FIXME);
                                parseip(ip, f[2]);
                                n = parsemac(mac, f[3], m->maclen);
                                break;
                }
 
                if (m->ares == NULL)
-                       error(Ebadarp);
+                       error(EINVAL, ERROR_FIXME);
 
                m->ares(fs, V6, ip, mac, n, 0);
        } else if (strcmp(f[0], "del") == 0) {
                if (n != 2)
-                       error(Ebadarg);
+                       error(EINVAL, ERROR_FIXME);
 
                parseip(ip, f[1]);
                qlock(&arp->qlock);
@@ -507,7 +540,7 @@ int arpwrite(struct Fs *fs, char *s, int len)
                }
                qunlock(&arp->qlock);
        } else
-               error(Ebadarp);
+               error(EINVAL, ERROR_FIXME);
 
        return len;
 }
@@ -516,22 +549,12 @@ enum {
        Alinelen = 90,
 };
 
-char *aformat = "%-6.6s %-8.8s %-40.40I %-32.32s\n";
-
-static void convmac(char *p, uint8_t * mac, int n)
-{
-       int left = n;
-       while (n-- > 0) {
-               p += snprintf(p, left, "0x%2.2x", *mac++);
-               left -= n;
-       }
-}
+static char *aformat = "%-6.6s %-8.8s %-40.40I %E\n";
 
 int arpread(struct arp *arp, char *p, uint32_t offset, int len)
 {
        struct arpent *a;
        int n;
-       char mac[2 * MAClen + 1];
        int left = len;
        int amt;
 
@@ -552,9 +575,8 @@ int arpread(struct arp *arp, char *p, uint32_t offset, int len)
                len--;
                left--;
                qlock(&arp->qlock);
-               convmac(mac, a->mac, a->type->maclen);
-               amt = snprintf(p + n, left,
-                                          aformat, a->type->name, arpstate[a->state], a->ip, mac);
+               amt = snprintf(p + n, left, aformat, a->type->name, arpstate[a->state],
+                              a->ip, a->mac);
                n += amt;
                left -= amt;
                qunlock(&arp->qlock);
@@ -563,7 +585,7 @@ int arpread(struct arp *arp, char *p, uint32_t offset, int len)
        return n;
 }
 
-extern int rxmitsols(struct arp *arp)
+static uint64_t rxmitsols(struct arp *arp)
 {
        unsigned int sflag;
        struct block *next, *xp;
@@ -571,7 +593,7 @@ extern int rxmitsols(struct arp *arp)
        struct Fs *f;
        uint8_t ipsrc[IPaddrlen];
        struct Ipifc *ifc = NULL;
-       long nrxt;
+       uint64_t nrxt;
 
        qlock(&arp->qlock);
        f = arp->f;
@@ -579,11 +601,11 @@ extern int rxmitsols(struct arp *arp)
        a = arp->rxmt;
        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;
+               goto dodrops;   /* return nrxt; */
 
        for (; a; a = a->nextrxt) {
                ifc = a->ifc;
@@ -666,10 +688,9 @@ static void rxmitproc(void *v)
 {
        ERRSTACK(2);
        struct arp *arp = v;
-       long wakeupat;
+       uint64_t wakeupat;
 
        arp->rxmitp = current;
-       //print("arp rxmitproc started\n");
        if (waserror()) {
                arp->rxmitp = 0;
                poperror();
@@ -681,7 +702,7 @@ static void rxmitproc(void *v)
                if (wakeupat == 0)
                        rendez_sleep(&arp->rxmtq, rxready, v);
                else if (wakeupat > ReTransTimer / 4)
-                       udelay_sched(wakeupat * 1000);
+                       kthread_usleep(wakeupat * 1000);
        }
        poperror();
 }