-- cgit v1.2.3 From a58b834c8e333385f9be37eb4d343d70f8177613 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 20 Sep 2004 10:43:53 -0400 Subject: Clean up network header stuff and make it more generic. Use 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 --- SConscript | 1 + base/crc.cc | 117 ++++++++++++++++++++++++ base/crc.hh | 37 ++++++++ base/inet.cc | 124 +++---------------------- base/inet.hh | 94 +++++++++++++++++-- base/refcnt.hh | 2 +- build/SConstruct | 1 + dev/etherlink.cc | 7 +- dev/etherpkt.cc | 28 +++++- dev/etherpkt.hh | 72 ++++++--------- dev/ethertap.cc | 2 +- dev/ethertap.hh | 2 +- dev/ns_gige.cc | 270 +++++++++++++++---------------------------------------- dev/ns_gige.hh | 19 ++-- 14 files changed, 391 insertions(+), 385 deletions(-) create mode 100644 base/crc.cc create mode 100644 base/crc.hh 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); + 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..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; } - - 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 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 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; -- cgit v1.2.3 From 15d08a3422d5038b7fe8aa1e3206e27e889d69e3 Mon Sep 17 00:00:00 2001 From: Erik Hallnor Date: Mon, 20 Sep 2004 22:00:35 -0400 Subject: Update copies to work around alignment faults. arch/alpha/isa_desc: whitespace fix. cpu/simple_cpu/simple_cpu.cc: Add support to make sure we don't get alignment faults in copies. Warn if we go over an 8k page boundary. --HG-- extra : convert_revision : 98b38da86a66215d80ea9eb6e6f1f68ee573cb57 --- arch/alpha/isa_desc | 4 ++-- cpu/simple_cpu/simple_cpu.cc | 41 ++++++++++++++++++++++++++++++++++------- 2 files changed, 36 insertions(+), 9 deletions(-) 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/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); -- cgit v1.2.3 From 1d02345a24f6e439545c0752e4dfcb54b8a23537 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Tue, 21 Sep 2004 01:41:55 -0400 Subject: a bit more cleaning of the network header wrappers. base/inet.hh: add functions to the various headers to grab the most common encapsulated protocols. This could easily get out of hand, but we're just worrying about tcp, udp, and ip for now. add common functions size(), bytes(), and payload() to all wrappers. size() gets the header size bytes() returns a uint8_t * to the beginning of the header payload() returns a uint8_t * to the beginning of the payload. dev/etherpkt.cc: dev/etherpkt.hh: don't cache pointers to headers. It's probably not worth the hassle. --HG-- extra : convert_revision : ba9df85ac019b8a48233042dde79fb9da9546410 --- base/inet.hh | 52 ++++++++++++++++++++++++++++++++++++++++++++-------- dev/etherpkt.cc | 23 ----------------------- dev/etherpkt.hh | 30 +++++++++++------------------- 3 files changed, 55 insertions(+), 50 deletions(-) diff --git a/base/inet.hh b/base/inet.hh index 86a04aae4..b20c90beb 100644 --- a/base/inet.hh +++ b/base/inet.hh @@ -53,15 +53,30 @@ std::string eaddr_string(const uint8_t a[6]); +struct EthHdr; +struct IpHdr; +struct TcpHdr; +struct UdpHdr; + 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); } + + 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 @@ -83,8 +98,23 @@ struct IpHdr : protected ip_hdr 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(); } + + 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 @@ -101,8 +131,11 @@ struct TcpHdr : protected tcp_hdr 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(); } + 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 @@ -114,8 +147,11 @@ struct UdpHdr : protected udp_hdr 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); } + 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/dev/etherpkt.cc b/dev/etherpkt.cc index 292fe7faf..273b8ee64 100644 --- a/dev/etherpkt.cc +++ b/dev/etherpkt.cc @@ -33,29 +33,6 @@ using namespace std; -void -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) { diff --git a/dev/etherpkt.hh b/dev/etherpkt.hh index 53612b830..9c5f00491 100644 --- a/dev/etherpkt.hh +++ b/dev/etherpkt.hh @@ -51,30 +51,22 @@ class PacketData : public RefCounted uint8_t *data; int length; - protected: - uint8_t *_eth; - uint8_t *_ip; - uint8_t *_tcp; - uint8_t *_udp; - - void doext(); - void ext() - { - if (_eth != data) - doext(); - } - public: - PacketData() : data(NULL), length(0) { doext(); } + PacketData() : data(NULL), length(0) { } PacketData(std::auto_ptr d, int l) - : data(d.release()), length(l) { doext(); } + : data(d.release()), length(l) { } ~PacketData() { if (data) delete [] data; } 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; } + 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;} + + 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); -- cgit v1.2.3