Clean up network header stuff and make it more generic. Use
authorNathan Binkert <binkertn@umich.edu>
Mon, 20 Sep 2004 14:43:53 +0000 (10:43 -0400)
committerNathan Binkert <binkertn@umich.edu>
Mon, 20 Sep 2004 14:43:53 +0000 (10:43 -0400)
libdnet when we can instead of our own home grown stuff.

SConscript:
    separate the crc code into its own file
base/inet.cc:
    move the crc stuff to crc.cc
    add generic code for calculating ip/tcp/udp checksums
base/inet.hh:
    -  move crc stuff to crc.hh
    -  #include all of the libdnet stuff.  (this makes base/inet.hh the
    only file you need to include if you want to use this kind of stuff.)
    -  Wrap some of the libdnet structs to get easier access to structure
    members.  These wrappers will automatically deal with masking/shifting/
    byte-swapping.
base/refcnt.hh:
    If one derives from RefCountingPtr, they should have access to
    the internal data pointer.
build/SConstruct:
    make #include of dnet stuff work
dev/etherlink.cc:
dev/ethertap.cc:
dev/ethertap.hh:
    EtherPacket -> PacketData
dev/etherpkt.cc:
    EtherPacket -> PacketData
    add a function for populating extra info about a packet.
    Basically just gives pointers to ethernet/ip/tcp/udp headers
    if they exist.
dev/etherpkt.hh:
    EtherPacket -> PacketData
    remove most of the packet header stuff from teh PacketData
    class and just add a few generic functions for grabbing various
    headers that may exist in the packet.  The old functionality is
    contained in the headers.
dev/ns_gige.cc:
    -  IP -> Ip, UDP -> Udp, TCP ->Tcp when used in variable names
    -  get rid of our own byte swapping functions.
    -  whack checksum code and use libdnet version.
    -  Get pointers to the various packet headers and grab info from
    those headers.  (The byte swapping in the headers now.)
    -  Add stats for Udp Checksums
dev/ns_gige.hh:
    use libdnet for checksum code.
    IP -> Ip, TCP -> Tcp in variable names
    add stats for UDP checksums

--HG--
extra : convert_revision : 96c4160e1967b7c0090acd456df4a76e1f3aab53

14 files changed:
SConscript
base/crc.cc [new file with mode: 0644]
base/crc.hh [new file with mode: 0644]
base/inet.cc
base/inet.hh
base/refcnt.hh
build/SConstruct
dev/etherlink.cc
dev/etherpkt.cc
dev/etherpkt.hh
dev/ethertap.cc
dev/ethertap.hh
dev/ns_gige.cc
dev/ns_gige.hh

index ddd16564bd7579cc7378e82bf55498469aea4ef2..6949d9548c060c9dbb59d711548bff973a7d5e39 100644 (file)
@@ -244,6 +244,7 @@ full_system_sources = Split('''
        arch/alpha/pseudo_inst.cc
        arch/alpha/vtophys.cc
 
+       base/crc.cc
        base/inet.cc
        base/remote_gdb.cc
 
diff --git a/base/crc.cc b/base/crc.cc
new file mode 100644 (file)
index 0000000..8bff4b8
--- /dev/null
@@ -0,0 +1,117 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1988, 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sstream>
+#include <string>
+
+#include "sim/host.hh"
+#include "base/crc.hh"
+
+#define ETHER_CRC_POLY_LE 0xedb88320
+#define ETHER_CRC_POLY_BE 0x04c11db6
+
+#if 0
+/*
+ * This is for reference.  We have a table-driven version
+ * of the little-endian crc32 generator, which is faster
+ * than the double-loop.
+ */
+uint32_t
+crc32le(const uint8_t *buf, size_t len)
+{
+    uint32_t c, crc, carry;
+    size_t i, j;
+
+    crc = 0xffffffffU;      /* initial value */
+
+    for (i = 0; i < len; i++) {
+        c = buf[i];
+        for (j = 0; j < 8; j++) {
+            carry = ((crc & 0x01) ? 1 : 0) ^ (c & 0x01);
+            crc >>= 1;
+            c >>= 1;
+            if (carry)
+                crc = (crc ^ ETHER_CRC_POLY_LE);
+        }
+    }
+
+    return (crc);
+}
+#else
+uint32_t
+crc32le(const uint8_t *buf, size_t len)
+{
+    static const uint32_t crctab[] = {
+        0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
+        0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
+        0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
+        0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
+    };
+    uint32_t crc;
+    int i;
+
+    crc = 0xffffffffU;      /* initial value */
+
+    for (i = 0; i < len; i++) {
+        crc ^= buf[i];
+        crc = (crc >> 4) ^ crctab[crc & 0xf];
+        crc = (crc >> 4) ^ crctab[crc & 0xf];
+    }
+
+    return (crc);
+}
+#endif
+
+uint32_t
+crc32be(const uint8_t *buf, size_t len)
+{
+    uint32_t c, crc, carry;
+    size_t i, j;
+
+    crc = 0xffffffffU;      /* initial value */
+
+    for (i = 0; i < len; i++) {
+        c = buf[i];
+        for (j = 0; j < 8; j++) {
+            carry = ((crc & 0x80000000U) ? 1 : 0) ^ (c & 0x01);
+            crc <<= 1;
+            c >>= 1;
+            if (carry)
+                crc = (crc ^ ETHER_CRC_POLY_BE) | carry;
+        }
+    }
+
+    return (crc);
+}
diff --git a/base/crc.hh b/base/crc.hh
new file mode 100644 (file)
index 0000000..bd6719b
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2002-2003 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BASE_CRC_HH__
+#define __BASE_CRC_HH__
+
+#include "sim/host.hh"
+
+uint32_t crc32be(const uint8_t *buf, size_t len);
+uint32_t crc32le(const uint8_t *buf, size_t len);
+
+#endif // __BASE_CRC_HH__
index e2bdd19ffd1162384f97b0f06a76795c8c6db1e2..ac0758c1f009c9fac0f614c06e566bfea7592e78 100644 (file)
@@ -33,7 +33,7 @@
 #include "sim/host.hh"
 #include "base/inet.hh"
 
-using namespace::std;
+using namespace std;
 string
 eaddr_string(const uint8_t a[6])
 {
@@ -43,119 +43,19 @@ eaddr_string(const uint8_t a[6])
     return stream.str();
 }
 
-/*
- * Copyright (c) 1988, 1992, 1993
- *     The Regents of the University of California.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-/***********************************************************************
-                 This section of code taken from NetBSD
-***********************************************************************/
-
-#define ETHER_CRC_POLY_LE 0xedb88320
-#define ETHER_CRC_POLY_BE 0x04c11db6
-
-#if 0
-/*
- * This is for reference.  We have a table-driven version
- * of the little-endian crc32 generator, which is faster
- * than the double-loop.
- */
-uint32_t
-crc32le(const uint8_t *buf, size_t len)
+uint16_t
+IpHdr::ip_cksum() const
 {
-    uint32_t c, crc, carry;
-    size_t i, j;
-
-    crc = 0xffffffffU;      /* initial value */
-
-    for (i = 0; i < len; i++) {
-        c = buf[i];
-        for (j = 0; j < 8; j++) {
-            carry = ((crc & 0x01) ? 1 : 0) ^ (c & 0x01);
-            crc >>= 1;
-            c >>= 1;
-            if (carry)
-                crc = (crc ^ ETHER_CRC_POLY_LE);
-        }
-    }
-
-    return (crc);
-}
-#else
-uint32_t
-crc32le(const uint8_t *buf, size_t len)
-{
-    static const uint32_t crctab[] = {
-        0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
-        0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
-        0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
-        0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
-    };
-    uint32_t crc;
-    int i;
-
-    crc = 0xffffffffU;      /* initial value */
-
-    for (i = 0; i < len; i++) {
-        crc ^= buf[i];
-        crc = (crc >> 4) ^ crctab[crc & 0xf];
-        crc = (crc >> 4) ^ crctab[crc & 0xf];
-    }
-
-    return (crc);
+    uint16_t sum = ip_cksum_add(this, hlen(), 0);
+    return ip_cksum_carry(sum);
 }
-#endif
 
-uint32_t
-crc32be(const uint8_t *buf, size_t len)
+uint16_t
+IpHdr::tu_cksum() const
 {
-    uint32_t c, crc, carry;
-    size_t i, j;
-
-    crc = 0xffffffffU;      /* initial value */
-
-    for (i = 0; i < len; i++) {
-        c = buf[i];
-        for (j = 0; j < 8; j++) {
-            carry = ((crc & 0x80000000U) ? 1 : 0) ^ (c & 0x01);
-            crc <<= 1;
-            c >>= 1;
-            if (carry)
-                crc = (crc ^ ETHER_CRC_POLY_BE) | carry;
-        }
-    }
-
-    return (crc);
+    uint16_t sum = ip_cksum_add(payload(), len() - hlen(), 0);
+    sum = ip_cksum_add(&ip_src, 4, sum);
+    sum = ip_cksum_add(&ip_dst, 4, sum);
+    sum += htons(ip_p + ip_len);
+    return ip_cksum_carry(sum);
 }
-
-/***********************************************************************
-                 This is the end of the NetBSD code
-***********************************************************************/
index 67ac5a5043f348ed84c74b2bcaf42d27c4a90cab..86a04aae47d5d9eff9876ae3a04fd3eb05ef9785 100644 (file)
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef __INET_HH__
-#define __INET_HH__
+#ifndef __BASE_INET_HH__
+#define __BASE_INET_HH__
+
+#include <string>
+
+#include "dnet/os.h"
+
+#include "dnet/eth.h"
+#include "dnet/ip.h"
+#include "dnet/ip6.h"
+#include "dnet/addr.h"
+#include "dnet/arp.h"
+#include "dnet/icmp.h"
+#include "dnet/tcp.h"
+#include "dnet/udp.h"
+
+#include "dnet/intf.h"
+#include "dnet/route.h"
+#include "dnet/fw.h"
+
+#include "dnet/blob.h"
+#include "dnet/rand.h"
 
 #include "sim/host.hh"
 
-uint32_t crc32be(const uint8_t *buf, size_t len);
-uint32_t crc32le(const uint8_t *buf, size_t len);
 std::string eaddr_string(const uint8_t a[6]);
-#endif // __INET_HH__
+
+struct EthHdr : protected eth_hdr
+{
+    uint16_t type() const { return ntohs(eth_type); }
+    const uint8_t *payload() const { return (const uint8_t *)this + sizeof(*this); }
+    uint8_t *payload() { return (uint8_t *)this + sizeof(*this); }
+
+    bool unicast() { return eth_dst.data[0] == 0x00; }
+    bool multicast() { return eth_dst.data[0] == 0x01; }
+    bool broadcast() { return eth_dst.data[0] == 0xff; }
+};
+
+struct IpHdr : protected ip_hdr
+{
+    uint8_t  version() const { return ip_v; }
+    uint8_t  hlen() const { return ip_hl; }
+    uint8_t  tos() const { return ip_tos; }
+    uint16_t len() const { return ntohs(ip_len); }
+    uint16_t id() const { return ntohs(ip_id); }
+    uint16_t frag_flags() const { return ntohs(ip_off) >> 13; }
+    uint16_t frag_off() const { return ntohs(ip_off) & 0x1fff; }
+    uint8_t  ttl() const { return ip_ttl; }
+    uint8_t  proto() const { return ip_p; }
+    uint16_t sum() const { return ntohs(ip_sum); }
+    uint32_t src() const { return ntohl(ip_src); }
+    uint32_t dst() const { return ntohl(ip_dst); }
+
+    void sum(uint16_t sum) { ip_sum = htons(sum); }
+
+    uint16_t ip_cksum() const;
+    uint16_t tu_cksum() const;
+    const uint8_t  *payload() const { return (const uint8_t *)this + hlen(); }
+    uint8_t  *payload() { return (uint8_t *)this + hlen(); }
+};
+
+struct TcpHdr : protected tcp_hdr
+{
+    uint16_t sport() const { return ntohs(th_sport); }
+    uint16_t dport() const { return ntohs(th_dport); }
+    uint32_t seq() const { return ntohl(th_seq); }
+    uint32_t ack() const { return ntohl(th_ack); }
+    uint8_t  off() const { return th_off; }
+    uint8_t  flags() const { return th_flags & 0x3f; }
+    uint16_t win() const { return ntohs(th_win); }
+    uint16_t sum() const { return ntohs(th_sum); }
+    uint16_t urp() const { return ntohs(th_urp); }
+
+    void sum(uint16_t sum) { th_sum = htons(sum); }
+
+    const uint8_t *payload() const { return (const uint8_t *)this + off(); }
+    uint8_t *payload() { return (uint8_t *)this + off(); }
+};
+
+struct UdpHdr : protected udp_hdr
+{
+    uint16_t sport() const { return ntohs(uh_sport); }
+    uint16_t dport() const { return ntohs(uh_dport); }
+    uint16_t len() const { return ntohs(uh_ulen); }
+    uint16_t sum() const { return ntohs(uh_sum); }
+
+    void sum(uint16_t sum) { uh_sum = htons(sum); }
+
+    const uint8_t *payload() const { return (const uint8_t *)this + sizeof(*this); }
+    uint8_t *payload() { return (uint8_t *)this + sizeof(*this); }
+};
+
+#endif // __BASE_INET_HH__
index d308dd0cfeff61d2e3ae38613be5b94795a029a2..251dc905bad2345adf13219a7fb9a86bf6230568 100644 (file)
@@ -48,7 +48,7 @@ class RefCounted
 template <class T>
 class RefCountingPtr
 {
-  private:
+  protected:
     T *data;
 
     void copy(T *d) {
index 41baa2d9c2a9a1dafc0e48ee555bc276dbea904e..6a629c06486114d8f43be402f852c390cd0b2e7f 100644 (file)
@@ -254,6 +254,7 @@ default_env.Append(ENV = { 'M5_EXT' : EXT_SRCDIR })
 default_env.Append(CCFLAGS='-pipe')
 default_env.Append(CCFLAGS='-fno-strict-aliasing')
 default_env.Append(CCFLAGS=Split('-Wall -Wno-sign-compare -Werror -Wundef'))
+default_env.Append(CPPPATH=[os.path.join(EXT_SRCDIR + '/dnet')])
 
 # libelf build is described in its own SConscript file.  Using a
 # dictionary for exports lets us export "default_env" so the
index 3cc4f75ead359fbec476e1caff6269303dc664b0..ccb18d3632d7eada8c0dffcb9c4294c6f4837ab2 100644 (file)
@@ -41,8 +41,9 @@
 #include "dev/etherlink.hh"
 #include "dev/etherpkt.hh"
 #include "sim/builder.hh"
-#include "sim/universe.hh"
+#include "sim/serialize.hh"
 #include "sim/system.hh"
+#include "sim/universe.hh"
 
 using namespace std;
 
@@ -196,7 +197,7 @@ EtherLink::Link::unserialize(Checkpoint *cp, const string &section)
     bool packet_exists;
     UNSERIALIZE_SCALAR(packet_exists);
     if (packet_exists) {
-        packet = new EtherPacket;
+        packet = new PacketData;
         packet->unserialize(cp, csprintf("%s.packet", section));
     }
 
@@ -246,7 +247,7 @@ void
 LinkDelayEvent::unserialize(Checkpoint *cp, const string &section)
 {
     Event::unserialize(cp, section);
-    packet = new EtherPacket;
+    packet = new PacketData;
     packet->unserialize(cp, csprintf("%s.packet", section));
 }
 
index 9eda89e9d3972d3d0ef0058c722189f6df58761a..292fe7faf26eb2d59a4449903594baeb446e631d 100644 (file)
 using namespace std;
 
 void
-EtherPacket::serialize(ostream &os)
+PacketData::doext()
+{
+    _eth = 0;
+    _ip = 0;
+    _tcp = 0;
+    _udp = 0;
+
+    if (!data)
+        return;
+
+    _eth = data;
+    if (eth()->type() == ETH_TYPE_IP) {
+        _ip = eth()->payload();
+
+        if (ip()->proto() == IP_PROTO_TCP)
+            _tcp = ip()->payload();
+
+        if (ip()->proto() == IP_PROTO_UDP)
+            _udp = ip()->payload();
+    }
+}
+
+void
+PacketData::serialize(ostream &os)
 {
     SERIALIZE_SCALAR(length);
     SERIALIZE_ARRAY(data, length);
 }
 
 void
-EtherPacket::unserialize(Checkpoint *cp, const string &section)
+PacketData::unserialize(Checkpoint *cp, const string &section)
 {
     UNSERIALIZE_SCALAR(length);
     data = new uint8_t[length];
     UNSERIALIZE_ARRAY(data, length);
 }
-
index abdf301663216d69de3be99865e7df2aa4a713f8..53612b830e745c811bf7e5ff63cdfd6c3f0f3b09 100644 (file)
 #include <memory>
 #include <assert.h>
 
-#include "sim/host.hh"
 #include "base/refcnt.hh"
-#include "base/inet_hdrs.hh"
+#include "base/inet.hh"
+#include "sim/host.hh"
 
-class Checkpoint;
 /*
  * Reference counted class containing ethernet packet data
  */
-class EtherPacket : public RefCounted
+class Checkpoint;
+class PacketData : public RefCounted
 {
   public:
     uint8_t *data;
     int length;
 
-  public:
-    EtherPacket() : data(NULL), length(0) {}
-    EtherPacket(std::auto_ptr<uint8_t> d, int l)
-        : data(d.release()), length(l) {}
-    ~EtherPacket() { if (data) delete [] data; }
-
-  public:
-    bool IsUnicast() { return data[0] == 0x00; }
-    bool IsMulticast() { return data[0] == 0x01; }
-    bool IsBroadcast() { return data[0] == 0xff; }
-
-    bool isIpPkt() {
-        eth_header *eth = (eth_header *) data;
-        return (eth->type == 0x8);
-    }
-    bool isTcpPkt(ip_header *ip) {
-        return (ip->protocol == 0x6);
-    }
-    bool isTcpPkt() {
-        ip_header *ip = getIpHdr();
-        return (ip->protocol == 0x6);
-    }
-    bool isUdpPkt(ip_header *ip) {
-        return (ip->protocol == 17);
-    }
-    bool isUdpPkt() {
-        ip_header *ip = getIpHdr();
-        return (ip->protocol == 17);
-    }
+  protected:
+    uint8_t *_eth;
+    uint8_t *_ip;
+    uint8_t *_tcp;
+    uint8_t *_udp;
 
-    ip_header *getIpHdr() {
-        assert(isIpPkt());
-        return (ip_header *) (data + sizeof(eth_header));
+    void doext();
+    void ext()
+    {
+        if (_eth != data)
+            doext();
     }
 
-    tcp_header *getTcpHdr(ip_header *ip) {
-        assert(isTcpPkt(ip));
-        return (tcp_header *) ((uint8_t *) ip + (ip->vers_len & 0xf)*4);
-    }
+  public:
+    PacketData() : data(NULL), length(0) { doext(); }
+    PacketData(std::auto_ptr<uint8_t> d, int l)
+        : data(d.release()), length(l) { doext(); }
+    ~PacketData() { if (data) delete [] data; }
 
-    udp_header *getUdpHdr(ip_header *ip) {
-        assert(isUdpPkt(ip));
-        return (udp_header *) ((uint8_t *) ip + (ip->vers_len & 0xf)*4);
-    }
-    typedef RefCountingPtr<EtherPacket> PacketPtr;
+  public:
+    EthHdr *eth() { ext(); return (EthHdr *)_eth; }
+    IpHdr *ip() { ext(); return (IpHdr *)_ip; }
+    TcpHdr *tcp() { ext(); return (TcpHdr *)_tcp; }
+    UdpHdr *udp() { ext(); return (UdpHdr *)_udp; }
 
+  public:
     void serialize(std::ostream &os);
     void unserialize(Checkpoint *cp, const std::string &section);
 };
 
-typedef RefCountingPtr<EtherPacket> PacketPtr;
+typedef RefCountingPtr<PacketData> PacketPtr;
 
 #endif // __ETHERPKT_HH__
index edc400760c6a023a2c104e907151bb56694a104a..b40a93c1b446a05a55fab01397b9ed766064cdc6 100644 (file)
@@ -219,7 +219,7 @@ EtherTap::process(int revent)
 
     while (data_len != 0 && buffer_offset >= data_len + sizeof(u_int32_t)) {
         PacketPtr packet;
-        packet = new EtherPacket;
+        packet = new PacketData;
         packet->data = new uint8_t[data_len];
         packet->length = data_len;
         memcpy(packet->data, data, data_len);
index 1fe368085715475d8bde9f38d2436a73c290b15a..9c77a4a4faad7b3942d95776e230d0eec9abac22 100644 (file)
@@ -70,7 +70,7 @@ class EtherTap : public EtherInt
     std::queue<PacketPtr> packetBuffer;
 
     void process(int revent);
-    void enqueue(EtherPacket *packet);
+    void enqueue(PacketData *packet);
     void retransmit();
 
     /*
index 87ac5b5932758249925b4db9259528eec54327da..9238a7c7eb9443a8599cb15c368d45dabaca0a83 100644 (file)
@@ -87,11 +87,6 @@ const char *NsDmaState[] =
 
 using namespace std;
 
-// helper function declarations
-// These functions reverse Endianness so we can evaluate network data
-// correctly
-uint16_t reverseEnd16(uint16_t);
-uint32_t reverseEnd32(uint32_t);
 
 ///////////////////////////////////////////////////////////////////////
 //
@@ -194,34 +189,48 @@ NSGigE::regStats()
         .prereq(rxBytes)
         ;
 
-    txIPChecksums
-        .name(name() + ".txIPChecksums")
+    txIpChecksums
+        .name(name() + ".txIpChecksums")
         .desc("Number of tx IP Checksums done by device")
         .precision(0)
         .prereq(txBytes)
         ;
 
-    rxIPChecksums
-        .name(name() + ".rxIPChecksums")
+    rxIpChecksums
+        .name(name() + ".rxIpChecksums")
         .desc("Number of rx IP Checksums done by device")
         .precision(0)
         .prereq(rxBytes)
         ;
 
-    txTCPChecksums
-        .name(name() + ".txTCPChecksums")
+    txTcpChecksums
+        .name(name() + ".txTcpChecksums")
         .desc("Number of tx TCP Checksums done by device")
         .precision(0)
         .prereq(txBytes)
         ;
 
-    rxTCPChecksums
-        .name(name() + ".rxTCPChecksums")
+    rxTcpChecksums
+        .name(name() + ".rxTcpChecksums")
         .desc("Number of rx TCP Checksums done by device")
         .precision(0)
         .prereq(rxBytes)
         ;
 
+    txUdpChecksums
+        .name(name() + ".txUdpChecksums")
+        .desc("Number of tx UDP Checksums done by device")
+        .precision(0)
+        .prereq(txBytes)
+        ;
+
+    rxUdpChecksums
+        .name(name() + ".rxUdpChecksums")
+        .desc("Number of rx UDP Checksums done by device")
+        .precision(0)
+        .prereq(rxBytes)
+        ;
+
     descDmaReads
         .name(name() + ".descDMAReads")
         .desc("Number of descriptors the device read w/ DMA")
@@ -1332,14 +1341,13 @@ NSGigE::rxKick()
 
 #if TRACING_ON
             if (DTRACE(Ethernet)) {
-                if (rxPacket->isIpPkt()) {
-                    ip_header *ip = rxPacket->getIpHdr();
-                    DPRINTF(Ethernet, "ID is %d\n", reverseEnd16(ip->ID));
-                    if (rxPacket->isTcpPkt()) {
-                        tcp_header *tcp = rxPacket->getTcpHdr(ip);
+                const IpHdr *ip = rxPacket->ip();
+                if (ip) {
+                    DPRINTF(Ethernet, "ID is %d\n", ip->id());
+                    const TcpHdr *tcp = rxPacket->tcp();
+                    if (tcp) {
                         DPRINTF(Ethernet, "Src Port=%d, Dest Port=%d\n",
-                                reverseEnd16(tcp->src_port_num),
-                                reverseEnd16(tcp->dest_port_num));
+                                tcp->sport(), tcp->dport());
                     }
                 }
             }
@@ -1395,33 +1403,36 @@ NSGigE::rxKick()
              */
             if (rxFilterEnable) {
                 rxDescCache.cmdsts &= ~CMDSTS_DEST_MASK;
-                if (rxFifo.front()->IsUnicast())
+                EthHdr *eth = rxFifoFront()->eth();
+                if (eth->unicast())
                     rxDescCache.cmdsts |= CMDSTS_DEST_SELF;
-                if (rxFifo.front()->IsMulticast())
+                if (eth->multicast())
                     rxDescCache.cmdsts |= CMDSTS_DEST_MULTI;
-                if (rxFifo.front()->IsBroadcast())
+                if (eth->broadcast())
                     rxDescCache.cmdsts |= CMDSTS_DEST_MASK;
             }
 #endif
 
-            if (rxPacket->isIpPkt() && extstsEnable) {
+            if (extstsEnable && rxPacket->ip()) {
                 rxDescCache.extsts |= EXTSTS_IPPKT;
-                rxIPChecksums++;
-                if (!ipChecksum(rxPacket, false)) {
+                rxIpChecksums++;
+                IpHdr *ip = rxPacket->ip();
+                if (ip->ip_cksum() != 0) {
                     DPRINTF(EthernetCksum, "Rx IP Checksum Error\n");
                     rxDescCache.extsts |= EXTSTS_IPERR;
                 }
-                if (rxPacket->isTcpPkt()) {
+                if (rxPacket->tcp()) {
                     rxDescCache.extsts |= EXTSTS_TCPPKT;
-                    rxTCPChecksums++;
-                    if (!tcpChecksum(rxPacket, false)) {
+                    rxTcpChecksums++;
+                    if (ip->tu_cksum() != 0) {
                         DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n");
                         rxDescCache.extsts |= EXTSTS_TCPERR;
 
                     }
-                } else if (rxPacket->isUdpPkt()) {
+                } else if (rxPacket->udp()) {
                     rxDescCache.extsts |= EXTSTS_UDPPKT;
-                    if (!udpChecksum(rxPacket, false)) {
+                    rxUdpChecksums++;
+                    if (ip->tu_cksum() != 0) {
                         DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n");
                         rxDescCache.extsts |= EXTSTS_UDPERR;
                     }
@@ -1539,14 +1550,13 @@ NSGigE::transmit()
     if (interface->sendPacket(txFifo.front())) {
 #if TRACING_ON
         if (DTRACE(Ethernet)) {
-            if (txFifo.front()->isIpPkt()) {
-                ip_header *ip = txFifo.front()->getIpHdr();
-                DPRINTF(Ethernet, "ID is %d\n", reverseEnd16(ip->ID));
-                if (txFifo.front()->isTcpPkt()) {
-                    tcp_header *tcp = txFifo.front()->getTcpHdr(ip);
+            const IpHdr *ip = txFifo.front()->ip();
+            if (ip) {
+                DPRINTF(Ethernet, "ID is %d\n", ip->id());
+                const TcpHdr *tcp = txFifo.front()->tcp();
+                if (tcp) {
                     DPRINTF(Ethernet, "Src Port=%d, Dest Port=%d\n",
-                            reverseEnd16(tcp->src_port_num),
-                            reverseEnd16(tcp->dest_port_num));
+                            tcp->sport(), tcp->dport());
                 }
             }
         }
@@ -1780,7 +1790,7 @@ NSGigE::txKick()
       case txFifoBlock:
         if (!txPacket) {
             DPRINTF(EthernetSM, "****starting the tx of a new packet****\n");
-            txPacket = new EtherPacket;
+            txPacket = new PacketData;
             txPacket->data = new uint8_t[16384];
             txPacketBufPtr = txPacket->data;
         }
@@ -1806,15 +1816,22 @@ NSGigE::txKick()
                 DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n");
                 /* deal with the the packet that just finished */
                 if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) {
+                    IpHdr *ip = txPacket->ip();
                     if (txDescCache.extsts & EXTSTS_UDPPKT) {
-                        udpChecksum(txPacket, true);
+                        UdpHdr *udp = txPacket->udp();
+                        udp->sum(0);
+                        udp->sum(ip->tu_cksum());
+                        txUdpChecksums++;
                     } else if (txDescCache.extsts & EXTSTS_TCPPKT) {
-                        tcpChecksum(txPacket, true);
-                        txTCPChecksums++;
+                        TcpHdr *tcp = txPacket->tcp();
+                        tcp->sum(0);
+                        tcp->sum(ip->tu_cksum());
+                        txTcpChecksums++;
                     }
                     if (txDescCache.extsts & EXTSTS_IPPKT) {
-                        ipChecksum(txPacket, true);
-                        txIPChecksums++;
+                        ip->sum(0);
+                        ip->sum(ip->ip_cksum());
+                        txIpChecksums++;
                     }
                 }
 
@@ -1977,9 +1994,8 @@ NSGigE::rxFilter(PacketPtr packet)
     bool drop = true;
     string type;
 
-    if (packet->IsUnicast()) {
-        type = "unicast";
-
+    EthHdr *eth = packet->eth();
+    if (eth->unicast()) {
         // If we're accepting all unicast addresses
         if (acceptUnicast)
             drop = false;
@@ -1989,28 +2005,19 @@ NSGigE::rxFilter(PacketPtr packet)
             memcmp(rom.perfectMatch, packet->data, EADDR_LEN) == 0)
             drop = false;
 
-        eth_header *eth = (eth_header *) packet->data;
-        if ((acceptArp) && (eth->type == 0x608))
+        if (acceptArp && eth->type() == ETH_TYPE_ARP)
             drop = false;
 
-    } else if (packet->IsBroadcast()) {
-        type = "broadcast";
-
+    } else if (eth->broadcast()) {
         // if we're accepting broadcasts
         if (acceptBroadcast)
             drop = false;
 
-    } else if (packet->IsMulticast()) {
-        type = "multicast";
-
+    } else if (eth->multicast()) {
         // if we're accepting all multicasts
         if (acceptMulticast)
             drop = false;
 
-    } else {
-        type = "unknown";
-
-        // oh well, punt on this one
     }
 
     if (drop) {
@@ -2058,121 +2065,6 @@ NSGigE::recvPacket(PacketPtr packet)
     return true;
 }
 
-/**
- * does a udp checksum.  if gen is true, then it generates it and puts
- * it in the right place else, it just checks what it calculates
- * against the value in the header in packet
- */
-bool
-NSGigE::udpChecksum(PacketPtr packet, bool gen)
-{
-    ip_header *ip = packet->getIpHdr();
-    udp_header *hdr = packet->getUdpHdr(ip);
-
-    pseudo_header *pseudo = new pseudo_header;
-
-    pseudo->src_ip_addr = ip->src_ip_addr;
-    pseudo->dest_ip_addr = ip->dest_ip_addr;
-    pseudo->protocol = ip->protocol;
-    pseudo->len = hdr->len;
-
-    uint16_t cksum = checksumCalc((uint16_t *) pseudo, (uint16_t *) hdr,
-                                  (uint32_t) hdr->len);
-
-    delete pseudo;
-    if (gen)
-        hdr->chksum = cksum;
-    else
-        if (cksum != 0)
-            return false;
-
-    return true;
-}
-
-bool
-NSGigE::tcpChecksum(PacketPtr packet, bool gen)
-{
-    ip_header *ip = packet->getIpHdr();
-    tcp_header *hdr = packet->getTcpHdr(ip);
-
-    uint16_t cksum;
-    pseudo_header *pseudo = new pseudo_header;
-    if (!gen) {
-        pseudo->src_ip_addr = ip->src_ip_addr;
-        pseudo->dest_ip_addr = ip->dest_ip_addr;
-        pseudo->protocol = reverseEnd16(ip->protocol);
-        pseudo->len = reverseEnd16(reverseEnd16(ip->dgram_len) -
-                                   (ip->vers_len & 0xf)*4);
-
-        cksum = checksumCalc((uint16_t *) pseudo, (uint16_t *) hdr,
-                             (uint32_t) reverseEnd16(pseudo->len));
-    } else {
-        pseudo->src_ip_addr = 0;
-        pseudo->dest_ip_addr = 0;
-        pseudo->protocol = hdr->chksum;
-        pseudo->len = 0;
-        hdr->chksum = 0;
-        cksum = checksumCalc((uint16_t *) pseudo, (uint16_t *) hdr,
-                             (uint32_t) (reverseEnd16(ip->dgram_len) -
-                                         (ip->vers_len & 0xf)*4));
-    }
-
-    delete pseudo;
-    if (gen)
-        hdr->chksum = cksum;
-    else
-        if (cksum != 0)
-            return false;
-
-    return true;
-}
-
-bool
-NSGigE::ipChecksum(PacketPtr packet, bool gen)
-{
-    ip_header *hdr = packet->getIpHdr();
-
-    uint16_t cksum = checksumCalc(NULL, (uint16_t *) hdr,
-                                  (hdr->vers_len & 0xf)*4);
-
-    if (gen) {
-        DPRINTF(EthernetCksum, "generated checksum: %#x\n", cksum);
-        hdr->hdr_chksum = cksum;
-    }
-    else
-        if (cksum != 0)
-            return false;
-
-    return true;
-}
-
-uint16_t
-NSGigE::checksumCalc(uint16_t *pseudo, uint16_t *buf, uint32_t len)
-{
-    uint32_t sum = 0;
-
-    uint16_t last_pad = 0;
-    if (len & 1) {
-        last_pad = buf[len/2] & 0xff;
-        len--;
-        sum += last_pad;
-    }
-
-    if (pseudo) {
-        sum = pseudo[0] + pseudo[1] + pseudo[2] +
-            pseudo[3] + pseudo[4] + pseudo[5];
-    }
-
-    for (int i=0; i < (len/2); ++i) {
-        sum += buf[i];
-    }
-
-    while (sum >> 16)
-        sum = (sum >> 16) + (sum & 0xffff);
-
-    return ~sum;
-}
-
 //=====================================================================
 //
 //
@@ -2398,7 +2290,7 @@ NSGigE::unserialize(Checkpoint *cp, const std::string &section)
     UNSERIALIZE_SCALAR(txNumPkts);
     int i;
     for (i = 0; i < txNumPkts; ++i) {
-        PacketPtr p = new EtherPacket;
+        PacketPtr p = new PacketData;
         p->unserialize(cp, csprintf("%s.rxFifo%d", section, i));
         txFifo.push_back(p);
     }
@@ -2406,7 +2298,7 @@ NSGigE::unserialize(Checkpoint *cp, const std::string &section)
     int rxNumPkts;
     UNSERIALIZE_SCALAR(rxNumPkts);
     for (i = 0; i < rxNumPkts; ++i) {
-        PacketPtr p = new EtherPacket;
+        PacketPtr p = new PacketData;
         p->unserialize(cp, csprintf("%s.rxFifo%d", section, i));
         rxFifo.push_back(p);
     }
@@ -2417,7 +2309,7 @@ NSGigE::unserialize(Checkpoint *cp, const std::string &section)
     bool txPacketExists;
     UNSERIALIZE_SCALAR(txPacketExists);
     if (txPacketExists) {
-        txPacket = new EtherPacket;
+        txPacket = new PacketData;
         txPacket->unserialize(cp, csprintf("%s.txPacket", section));
         uint32_t txPktBufPtr;
         UNSERIALIZE_SCALAR(txPktBufPtr);
@@ -2429,7 +2321,7 @@ NSGigE::unserialize(Checkpoint *cp, const std::string &section)
     UNSERIALIZE_SCALAR(rxPacketExists);
     rxPacket = 0;
     if (rxPacketExists) {
-        rxPacket = new EtherPacket;
+        rxPacket = new PacketData;
         rxPacket->unserialize(cp, csprintf("%s.rxPacket", section));
         uint32_t rxPktBufPtr;
         UNSERIALIZE_SCALAR(rxPktBufPtr);
@@ -2530,28 +2422,6 @@ NSGigE::cacheAccess(MemReqPtr &req)
             req->paddr, req->paddr - addr);
     return curTick + pioLatency;
 }
-//=====================================================================
-
-
-//********** helper functions******************************************
-
-uint16_t reverseEnd16(uint16_t num)
-{
-    uint16_t reverse = (num & 0xff)<<8;
-    reverse += ((num & 0xff00) >> 8);
-    return reverse;
-}
-
-uint32_t reverseEnd32(uint32_t num)
-{
-    uint32_t reverse = (reverseEnd16(num & 0xffff)) << 16;
-    reverse += reverseEnd16((uint16_t) ((num & 0xffff0000) >> 8));
-    return reverse;
-}
-
-
-
-//=====================================================================
 
 BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt)
 
index 82f640db176b61dfd4f186c13443ee9d7ec01d2d..b7838cf6f8874c98bbeade4cc09847ec1f746739 100644 (file)
@@ -329,15 +329,6 @@ class NSGigE : public PciDev
     typedef EventWrapper<NSGigE, &NSGigE::cpuInterrupt> IntrEvent;
     friend class IntrEvent;
     IntrEvent *intrEvent;
-
-    /**
-     * Hardware checksum support
-     */
-    bool udpChecksum(PacketPtr packet, bool gen);
-    bool tcpChecksum(PacketPtr packet, bool gen);
-    bool ipChecksum(PacketPtr packet, bool gen);
-    uint16_t checksumCalc(uint16_t *pseudo, uint16_t *buf, uint32_t len);
-
     NSGigEInt *interface;
 
   public:
@@ -377,10 +368,12 @@ class NSGigE : public PciDev
     Stats::Scalar<> rxBytes;
     Stats::Scalar<> txPackets;
     Stats::Scalar<> rxPackets;
-    Stats::Scalar<> txIPChecksums;
-    Stats::Scalar<> rxIPChecksums;
-    Stats::Scalar<> txTCPChecksums;
-    Stats::Scalar<> rxTCPChecksums;
+    Stats::Scalar<> txIpChecksums;
+    Stats::Scalar<> rxIpChecksums;
+    Stats::Scalar<> txTcpChecksums;
+    Stats::Scalar<> rxTcpChecksums;
+    Stats::Scalar<> txUdpChecksums;
+    Stats::Scalar<> rxUdpChecksums;
     Stats::Scalar<> descDmaReads;
     Stats::Scalar<> descDmaWrites;
     Stats::Scalar<> descDmaRdBytes;