summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAli Saidi <saidi@eecs.umich.edu>2004-09-22 18:39:37 -0400
committerAli Saidi <saidi@eecs.umich.edu>2004-09-22 18:39:37 -0400
commitac422ac949ac792da48bdd1417dc53d9850943ff (patch)
tree3125919709c79178d540a9223f1b12a522d6461d
parenteb7d32907679c2f19e3bc896a76484f537bc986d (diff)
parentfaece7a35a550d9e2875c1906f32e08456edb004 (diff)
downloadgem5-ac422ac949ac792da48bdd1417dc53d9850943ff.tar.xz
Merge zizzer:/bk/m5 into zeep.eecs.umich.edu:/z/saidi/work/m5-smp
--HG-- extra : convert_revision : 19dc01e1c0d2c0ba6b4d804b902429fb0a6a5552
-rw-r--r--SConscript1
-rw-r--r--arch/alpha/isa_desc4
-rw-r--r--base/crc.cc117
-rw-r--r--base/crc.hh37
-rw-r--r--base/inet.cc124
-rw-r--r--base/inet.hh130
-rw-r--r--base/refcnt.hh2
-rw-r--r--build/SConstruct1
-rw-r--r--cpu/simple_cpu/simple_cpu.cc41
-rw-r--r--dev/etherlink.cc7
-rw-r--r--dev/etherpkt.cc5
-rw-r--r--dev/etherpkt.hh64
-rw-r--r--dev/ethertap.cc2
-rw-r--r--dev/ethertap.hh2
-rw-r--r--dev/ns_gige.cc270
-rw-r--r--dev/ns_gige.hh19
16 files changed, 432 insertions, 394 deletions
diff --git a/SConscript b/SConscript
index 75cbc48ee..4ef66dec3 100644
--- a/SConscript
+++ b/SConscript
@@ -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/arch/alpha/isa_desc b/arch/alpha/isa_desc
index d6b99a8ae..9d65a02f0 100644
--- a/arch/alpha/isa_desc
+++ b/arch/alpha/isa_desc
@@ -1842,7 +1842,7 @@ decode OPCODE default Unknown::unknown() {
0x2a: ldl_l({{ EA = Rb + disp; }}, {{ Ra.sl = Mem.sl; }}, LOCKED);
0x2b: ldq_l({{ EA = Rb + disp; }}, {{ Ra.uq = Mem.uq; }}, LOCKED);
0x20: copy_load({{EA = Ra;}},
- {{ fault = xc->copySrcTranslate(EA);}},
+ {{fault = xc->copySrcTranslate(EA);}},
IsMemRef, IsLoad, IsCopy);
}
@@ -1864,7 +1864,7 @@ decode OPCODE default Unknown::unknown() {
0x26: sts({{ EA = Rb + disp; }}, {{ Mem.ul = t_to_s(Fa.uq); }});
0x27: stt({{ EA = Rb + disp; }}, {{ Mem.df = Fa; }});
0x24: copy_store({{EA = Rb;}},
- {{ fault = xc->copy(EA);}},
+ {{fault = xc->copy(EA);}},
IsMemRef, IsStore, IsCopy);
}
diff --git a/base/crc.cc b/base/crc.cc
new file mode 100644
index 000000000..8bff4b868
--- /dev/null
+++ b/base/crc.cc
@@ -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
index 000000000..bd6719b98
--- /dev/null
+++ b/base/crc.hh
@@ -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__
diff --git a/base/inet.cc b/base/inet.cc
index e2bdd19ff..ac0758c1f 100644
--- a/base/inet.cc
+++ b/base/inet.cc
@@ -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
-***********************************************************************/
diff --git a/base/inet.hh b/base/inet.hh
index 67ac5a504..b20c90beb 100644
--- a/base/inet.hh
+++ b/base/inet.hh
@@ -26,12 +26,132 @@
* 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;
+struct IpHdr;
+struct TcpHdr;
+struct UdpHdr;
+
+struct EthHdr : protected eth_hdr
+{
+ uint16_t type() const { return ntohs(eth_type); }
+
+ const IpHdr *ip() const
+ { return type() == ETH_TYPE_IP ? (const IpHdr *)payload() : 0; }
+
+ IpHdr *ip()
+ { return type() == ETH_TYPE_IP ? (IpHdr *)payload() : 0; }
+
+ bool unicast() { return eth_dst.data[0] == 0x00; }
+ bool multicast() { return eth_dst.data[0] == 0x01; }
+ bool broadcast() { return eth_dst.data[0] == 0xff; }
+
+ int size() const { return sizeof(EthHdr); }
+ const uint8_t *bytes() const { return (const uint8_t *)this; }
+ const uint8_t *payload() const { return bytes() + size(); }
+ uint8_t *bytes() { return (uint8_t *)this; }
+ uint8_t *payload() { return bytes() + size(); }
+};
+
+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 TcpHdr *tcp() const
+ { return proto() == IP_PROTO_TCP ? (const TcpHdr *)payload() : 0; }
+ const UdpHdr *udp() const
+ { return proto() == IP_PROTO_UDP ? (const UdpHdr *)payload() : 0; }
+
+ TcpHdr *tcp()
+ { return proto() == IP_PROTO_TCP ? (TcpHdr *)payload() : 0; }
+ UdpHdr *udp()
+ { return proto() == IP_PROTO_UDP ? (UdpHdr *)payload() : 0; }
+
+
+ int size() const { return hlen(); }
+ const uint8_t *bytes() const { return (const uint8_t *)this; }
+ const uint8_t *payload() const { return bytes() + size(); }
+ uint8_t *bytes() { return (uint8_t *)this; }
+ uint8_t *payload() { return bytes() + size(); }
+};
+
+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); }
+
+ int size() const { return off(); }
+ const uint8_t *bytes() const { return (const uint8_t *)this; }
+ const uint8_t *payload() const { return bytes() + size(); }
+ uint8_t *bytes() { return (uint8_t *)this; }
+ uint8_t *payload() { return bytes() + size(); }
+};
+
+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); }
+
+ int size() const { return sizeof(UdpHdr); }
+ const uint8_t *bytes() const { return (const uint8_t *)this; }
+ const uint8_t *payload() const { return bytes() + size(); }
+ uint8_t *bytes() { return (uint8_t *)this; }
+ uint8_t *payload() { return bytes() + size(); }
+};
+
+#endif // __BASE_INET_HH__
diff --git a/base/refcnt.hh b/base/refcnt.hh
index d308dd0cf..251dc905b 100644
--- a/base/refcnt.hh
+++ b/base/refcnt.hh
@@ -48,7 +48,7 @@ class RefCounted
template <class T>
class RefCountingPtr
{
- private:
+ protected:
T *data;
void copy(T *d) {
diff --git a/build/SConstruct b/build/SConstruct
index 41baa2d9c..6a629c064 100644
--- a/build/SConstruct
+++ b/build/SConstruct
@@ -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
diff --git a/cpu/simple_cpu/simple_cpu.cc b/cpu/simple_cpu/simple_cpu.cc
index 449b20fee..18e660483 100644
--- a/cpu/simple_cpu/simple_cpu.cc
+++ b/cpu/simple_cpu/simple_cpu.cc
@@ -338,16 +338,29 @@ change_thread_state(int thread_number, int activate, int priority)
Fault
SimpleCPU::copySrcTranslate(Addr src)
{
- memReq->reset(src, (dcacheInterface) ?
- dcacheInterface->getBlockSize()
- : 64);
+ static bool no_warn = true;
+ int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64;
+ // Only support block sizes of 64 atm.
+ assert(blk_size == 64);
+ int offset = src & (blk_size - 1);
+
+ // Make sure block doesn't span page
+ if (no_warn && (src & (~8191)) == ((src + blk_size) & (~8191))) {
+ warn("Copied block source spans pages.");
+ no_warn = false;
+ }
+
+
+ memReq->reset(src & ~(blk_size - 1), blk_size);
// translate to physical address
Fault fault = xc->translateDataReadReq(memReq);
+ assert(fault != Alignment_Fault);
+
if (fault == No_Fault) {
xc->copySrcAddr = src;
- xc->copySrcPhysAddr = memReq->paddr;
+ xc->copySrcPhysAddr = memReq->paddr + offset;
} else {
xc->copySrcAddr = 0;
xc->copySrcPhysAddr = 0;
@@ -358,14 +371,28 @@ SimpleCPU::copySrcTranslate(Addr src)
Fault
SimpleCPU::copy(Addr dest)
{
+ static bool no_warn = true;
int blk_size = (dcacheInterface) ? dcacheInterface->getBlockSize() : 64;
+ // Only support block sizes of 64 atm.
+ assert(blk_size == 64);
uint8_t data[blk_size];
- assert(xc->copySrcAddr);
- memReq->reset(dest, blk_size);
+ //assert(xc->copySrcAddr);
+ int offset = dest & (blk_size - 1);
+
+ // Make sure block doesn't span page
+ if (no_warn && (dest & (~8191)) == ((dest + blk_size) & (~8191))) {
+ no_warn = false;
+ warn("Copied block destination spans pages. ");
+ }
+
+ memReq->reset(dest & ~(blk_size -1), blk_size);
// translate to physical address
Fault fault = xc->translateDataWriteReq(memReq);
+
+ assert(fault != Alignment_Fault);
+
if (fault == No_Fault) {
- Addr dest_addr = memReq->paddr;
+ Addr dest_addr = memReq->paddr + offset;
// Need to read straight from memory since we have more than 8 bytes.
memReq->paddr = xc->copySrcPhysAddr;
xc->mem->read(memReq, data);
diff --git a/dev/etherlink.cc b/dev/etherlink.cc
index 3cc4f75ea..ccb18d363 100644
--- a/dev/etherlink.cc
+++ b/dev/etherlink.cc
@@ -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));
}
diff --git a/dev/etherpkt.cc b/dev/etherpkt.cc
index 9eda89e9d..273b8ee64 100644
--- a/dev/etherpkt.cc
+++ b/dev/etherpkt.cc
@@ -34,17 +34,16 @@
using namespace std;
void
-EtherPacket::serialize(ostream &os)
+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);
}
-
diff --git a/dev/etherpkt.hh b/dev/etherpkt.hh
index abdf30166..9c5f00491 100644
--- a/dev/etherpkt.hh
+++ b/dev/etherpkt.hh
@@ -37,70 +37,42 @@
#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; }
+ PacketData() : data(NULL), length(0) { }
+ PacketData(std::auto_ptr<uint8_t> d, int l)
+ : data(d.release()), length(l) { }
+ ~PacketData() { if (data) delete [] data; }
public:
- bool IsUnicast() { return data[0] == 0x00; }
- bool IsMulticast() { return data[0] == 0x01; }
- bool IsBroadcast() { return data[0] == 0xff; }
+ const EthHdr *eth() const { return (const EthHdr *)data; }
+ const IpHdr *ip() const {const EthHdr *h = eth(); return h ? h->ip() : 0;}
+ const TcpHdr *tcp() const {const IpHdr *h = ip(); return h ? h->tcp() : 0;}
+ const UdpHdr *udp() const {const IpHdr *h = ip(); return h ? h->udp() : 0;}
- 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);
- }
-
- ip_header *getIpHdr() {
- assert(isIpPkt());
- return (ip_header *) (data + sizeof(eth_header));
- }
-
- tcp_header *getTcpHdr(ip_header *ip) {
- assert(isTcpPkt(ip));
- return (tcp_header *) ((uint8_t *) ip + (ip->vers_len & 0xf)*4);
- }
-
- udp_header *getUdpHdr(ip_header *ip) {
- assert(isUdpPkt(ip));
- return (udp_header *) ((uint8_t *) ip + (ip->vers_len & 0xf)*4);
- }
- typedef RefCountingPtr<EtherPacket> PacketPtr;
+ EthHdr *eth() { return (EthHdr *)data; }
+ IpHdr *ip() { EthHdr *h = eth(); return h ? h->ip() : 0; }
+ TcpHdr *tcp() { IpHdr *h = ip(); return h ? h->tcp() : 0; }
+ UdpHdr *udp() { IpHdr *h = ip(); return h ? h->udp() : 0; }
+ 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__
diff --git a/dev/ethertap.cc b/dev/ethertap.cc
index edc400760..b40a93c1b 100644
--- a/dev/ethertap.cc
+++ b/dev/ethertap.cc
@@ -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);
diff --git a/dev/ethertap.hh b/dev/ethertap.hh
index 1fe368085..9c77a4a4f 100644
--- a/dev/ethertap.hh
+++ b/dev/ethertap.hh
@@ -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();
/*
diff --git a/dev/ns_gige.cc b/dev/ns_gige.cc
index 87ac5b593..9238a7c7e 100644
--- a/dev/ns_gige.cc
+++ b/dev/ns_gige.cc
@@ -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)
diff --git a/dev/ns_gige.hh b/dev/ns_gige.hh
index 82f640db1..b7838cf6f 100644
--- a/dev/ns_gige.hh
+++ b/dev/ns_gige.hh
@@ -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;