diff --git a/SConscript b/SConscript index ddd16564b..6949d9548 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/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 +#include + +#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); -} -#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); + uint16_t sum = ip_cksum_add(this, hlen(), 0); + return ip_cksum_carry(sum); } -/*********************************************************************** - This is the end of the NetBSD code -***********************************************************************/ +uint16_t +IpHdr::tu_cksum() const +{ + 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); +} diff --git a/base/inet.hh b/base/inet.hh index 67ac5a504..86a04aae4 100644 --- a/base/inet.hh +++ b/base/inet.hh @@ -26,12 +26,96 @@ * 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 + +#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__ 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 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/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 §ion) 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 §ion) { 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..292fe7faf 100644 --- a/dev/etherpkt.cc +++ b/dev/etherpkt.cc @@ -34,17 +34,39 @@ 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 §ion) +PacketData::unserialize(Checkpoint *cp, const string §ion) { UNSERIALIZE_SCALAR(length); data = new uint8_t[length]; UNSERIALIZE_ARRAY(data, length); } - diff --git a/dev/etherpkt.hh b/dev/etherpkt.hh index abdf30166..53612b830 100644 --- a/dev/etherpkt.hh +++ b/dev/etherpkt.hh @@ -37,70 +37,50 @@ #include #include -#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 d, int l) - : data(d.release()), length(l) {} - ~EtherPacket() { if (data) delete [] data; } + protected: + uint8_t *_eth; + uint8_t *_ip; + uint8_t *_tcp; + uint8_t *_udp; + + void doext(); + void ext() + { + if (_eth != data) + doext(); + } public: - bool IsUnicast() { return data[0] == 0x00; } - bool IsMulticast() { return data[0] == 0x01; } - bool IsBroadcast() { return data[0] == 0xff; } + PacketData() : data(NULL), length(0) { doext(); } + PacketData(std::auto_ptr d, int l) + : data(d.release()), length(l) { doext(); } + ~PacketData() { if (data) delete [] data; } - 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 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 §ion); }; -typedef RefCountingPtr PacketPtr; +typedef RefCountingPtr 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 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 §ion) 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 §ion) 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 §ion) 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 §ion) 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 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;