Rename KMALLOC_* -> MEM_* [2/2]
[akaros.git] / kern / src / net / ip.c
index eb06414..58f3c29 100644 (file)
@@ -1,17 +1,30 @@
-// 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>
+/* 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>
@@ -90,7 +103,7 @@ struct fragment4 {
        uint32_t src;
        uint32_t dst;
        uint16_t id;
-       uint32_t age;
+       uint64_t age;
 };
 
 struct fragment6 {
@@ -99,7 +112,7 @@ struct fragment6 {
        uint8_t src[IPaddrlen];
        uint8_t dst[IPaddrlen];
        unsigned int id;
-       uint32_t age;
+       uint64_t age;
 };
 
 struct Ipfrag {
@@ -310,7 +323,7 @@ ipoput4(struct Fs *f,
 
        /* If we dont need to fragment just send it */
        medialen = ifc->maxtu - ifc->m->hsize;
-       if (len <= medialen) {
+       if (bp->flag & Btso || len <= medialen) {
                if (!gating)
                        hnputs(eh->id, NEXT_ID(ip->id4));
                hnputs(eh->length, len);
@@ -346,6 +359,9 @@ ipoput4(struct Fs *f,
                goto raise;
        }
 
+       /* compute tcp/udp checksum in software before fragmenting */
+       ptclcsum_finalize(bp, 0);
+
        dlen = len - IP4HDR;
        xp = bp;
        if (gating)
@@ -353,6 +369,8 @@ ipoput4(struct Fs *f,
        else
                lid = NEXT_ID(ip->id4);
 
+       /* advance through the blist enough to drop IP4HDR size.  this should
+        * usually just be the first block. */
        offset = IP4HDR;
        while (xp != NULL && offset && offset >= BLEN(xp)) {
                offset -= BLEN(xp);
@@ -366,7 +384,7 @@ ipoput4(struct Fs *f,
                fragoff = 0;
        dlen += fragoff;
        for (; fragoff < dlen; fragoff += seglen) {
-               nb = allocb(IP4HDR + seglen);
+               nb = blist_clone(xp, IP4HDR, seglen, fragoff);
                feh = (struct Ip4hdr *)(nb->rp);
 
                memmove(nb->wp, eh, IP4HDR);
@@ -381,27 +399,6 @@ ipoput4(struct Fs *f,
                hnputs(feh->length, seglen + IP4HDR);
                hnputs(feh->id, lid);
 
-               /* Copy up the data area */
-               chunk = seglen;
-               while (chunk) {
-                       if (!xp) {
-                               ip->stats[OutDiscards]++;
-                               ip->stats[FragFails]++;
-                               freeblist(nb);
-                               netlog(f, Logip, "!xp: chunk %d\n", chunk);
-                               goto raise;
-                       }
-                       blklen = chunk;
-                       if (BLEN(xp) < chunk)
-                               blklen = BLEN(xp);
-                       memmove(nb->wp, xp->rp, blklen);
-                       nb->wp += blklen;
-                       xp->rp += blklen;
-                       chunk -= blklen;
-                       if (xp->rp == xp->wp)
-                               xp = xp->next;
-               }
-
                feh->cksum[0] = 0;
                feh->cksum[1] = 0;
                hnputs(feh->cksum, ipcsum(&feh->vihl));
@@ -537,7 +534,7 @@ void ipiput4(struct Fs *f, struct Ipifc *ifc, struct block *bp)
        }
 
        frag = nhgets(h->frag);
-       if (frag) {
+       if (frag && frag != IP_DF) {
                h->tos = 0;
                if (frag & IP_MF)
                        h->tos = 1;
@@ -575,7 +572,7 @@ int ipstats(struct Fs *f, char *buf, int len)
        p = buf;
        e = p + len;
        for (i = 0; i < Nstats; i++)
-               p = seprintf(p, e, "%s: %lu\n", statnames[i], ip->stats[i]);
+               p = seprintf(p, e, "%s: %u\n", statnames[i], ip->stats[i]);
        return p - buf;
 }