qio: Track the amount of bytes read
[akaros.git] / kern / src / net / ipaux.c
index 5ac4872..c466a84 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>
 /*
  *  well known IP addresses
  */
+uint8_t IPv4_loopback[IPaddrlen] = {
+       0, 0, 0, 0,
+       0, 0, 0, 0,
+       0, 0, 0xff, 0xff,
+       0x7f, 0x00, 0x00, 0x01
+};
+
+uint8_t IPv4_zeroes[IPaddrlen] = {
+       0, 0, 0, 0,
+       0, 0, 0, 0,
+       0, 0, 0xff, 0xff,
+       0x00, 0x00, 0x00, 0x00
+};
+
 uint8_t IPv4bcast[IPaddrlen] = {
        0, 0, 0, 0,
        0, 0, 0, 0,
@@ -216,6 +257,53 @@ uint8_t v6solicitednodemask[IPaddrlen] = {
 
 int v6snpreflen = 13;
 
+uint16_t ptclcsum_one(struct block *bp, int offset, int len)
+{
+       uint8_t *addr;
+       uint32_t losum, hisum;
+       uint16_t csum;
+       int odd, blocklen, x, i, boff;
+       struct extra_bdata *ebd;
+
+       hisum = 0;
+       losum = 0;
+       odd = 0;
+
+       if (offset < BHLEN(bp)) {
+               x = MIN(len, BHLEN(bp) - offset);
+               odd = (odd + x) & 1;
+               addr = bp->rp + offset;
+               losum = ptclbsum(addr, x);
+               len -= x;
+               offset = 0;
+       } else {
+               offset -= BHLEN(bp);
+       }
+       for (int i = 0; (i < bp->nr_extra_bufs) && len; i++) {
+               ebd = &bp->extra_data[i];
+               boff = MIN(offset, ebd->len);
+               if (offset) {
+                       offset -= boff;
+                       if (offset)
+                               continue;
+               }
+               x = MIN(len, ebd->len - boff);
+               addr = (void *)(ebd->base + ebd->off);
+               if (odd)
+                       hisum += ptclbsum(addr, x);
+               else
+                       losum += ptclbsum(addr, x);
+               odd = (odd + x) & 1;
+               len -= x;
+       }
+       losum += hisum >> 8;
+       losum += (hisum & 0xff) << 8;
+       while ((csum = losum >> 16) != 0)
+               losum = csum + (losum & 0xffff);
+
+       return losum & 0xffff;
+}
+
 uint16_t ptclcsum(struct block *bp, int offset, int len)
 {
        uint8_t *addr;
@@ -234,7 +322,7 @@ uint16_t ptclcsum(struct block *bp, int offset, int len)
        addr = bp->rp + offset;
        blocklen = BLEN(bp) - offset;
 
-       if (bp->next == NULL) {
+       if (bp->next == NULL && bp->extra_len == 0) {
                if (blocklen < len)
                        len = blocklen;
                return ~ptclbsum(addr, len) & 0xffff;
@@ -245,11 +333,8 @@ uint16_t ptclcsum(struct block *bp, int offset, int len)
 
        odd = 0;
        while (len) {
-               x = blocklen;
-               if (len < x)
-                       x = len;
-
-               csum = ptclbsum(addr, x);
+               x = MIN(blocklen, len);
+               csum = ptclcsum_one(bp, offset, x);
                if (odd)
                        hisum += csum;
                else
@@ -261,7 +346,7 @@ uint16_t ptclcsum(struct block *bp, int offset, int len)
                if (bp == NULL)
                        break;
                blocklen = BLEN(bp);
-               addr = bp->rp;
+               offset = 0;
        }
 
        losum += hisum >> 8;