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
This commit is contained in:
Nathan Binkert 2004-09-20 10:43:53 -04:00
parent bb59e2e7a3
commit a58b834c8e
14 changed files with 394 additions and 388 deletions

View file

@ -244,6 +244,7 @@ full_system_sources = Split('''
arch/alpha/pseudo_inst.cc arch/alpha/pseudo_inst.cc
arch/alpha/vtophys.cc arch/alpha/vtophys.cc
base/crc.cc
base/inet.cc base/inet.cc
base/remote_gdb.cc base/remote_gdb.cc

117
base/crc.cc Normal file
View file

@ -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);
}

37
base/crc.hh Normal file
View file

@ -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__

View file

@ -33,7 +33,7 @@
#include "sim/host.hh" #include "sim/host.hh"
#include "base/inet.hh" #include "base/inet.hh"
using namespace::std; using namespace std;
string string
eaddr_string(const uint8_t a[6]) eaddr_string(const uint8_t a[6])
{ {
@ -43,119 +43,19 @@ eaddr_string(const uint8_t a[6])
return stream.str(); return stream.str();
} }
/* uint16_t
* Copyright (c) 1988, 1992, 1993 IpHdr::ip_cksum() const
* 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)
{ {
uint32_t c, crc, carry; uint16_t sum = ip_cksum_add(this, hlen(), 0);
size_t i, j; return ip_cksum_carry(sum);
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
This is the end of the NetBSD code 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);
}

View file

@ -26,12 +26,96 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef __INET_HH__ #ifndef __BASE_INET_HH__
#define __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" #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]); 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__

View file

@ -48,7 +48,7 @@ class RefCounted
template <class T> template <class T>
class RefCountingPtr class RefCountingPtr
{ {
private: protected:
T *data; T *data;
void copy(T *d) { void copy(T *d) {

View file

@ -254,6 +254,7 @@ default_env.Append(ENV = { 'M5_EXT' : EXT_SRCDIR })
default_env.Append(CCFLAGS='-pipe') default_env.Append(CCFLAGS='-pipe')
default_env.Append(CCFLAGS='-fno-strict-aliasing') default_env.Append(CCFLAGS='-fno-strict-aliasing')
default_env.Append(CCFLAGS=Split('-Wall -Wno-sign-compare -Werror -Wundef')) 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 # libelf build is described in its own SConscript file. Using a
# dictionary for exports lets us export "default_env" so the # dictionary for exports lets us export "default_env" so the

View file

@ -41,8 +41,9 @@
#include "dev/etherlink.hh" #include "dev/etherlink.hh"
#include "dev/etherpkt.hh" #include "dev/etherpkt.hh"
#include "sim/builder.hh" #include "sim/builder.hh"
#include "sim/universe.hh" #include "sim/serialize.hh"
#include "sim/system.hh" #include "sim/system.hh"
#include "sim/universe.hh"
using namespace std; using namespace std;
@ -196,7 +197,7 @@ EtherLink::Link::unserialize(Checkpoint *cp, const string &section)
bool packet_exists; bool packet_exists;
UNSERIALIZE_SCALAR(packet_exists); UNSERIALIZE_SCALAR(packet_exists);
if (packet_exists) { if (packet_exists) {
packet = new EtherPacket; packet = new PacketData;
packet->unserialize(cp, csprintf("%s.packet", section)); packet->unserialize(cp, csprintf("%s.packet", section));
} }
@ -246,7 +247,7 @@ void
LinkDelayEvent::unserialize(Checkpoint *cp, const string &section) LinkDelayEvent::unserialize(Checkpoint *cp, const string &section)
{ {
Event::unserialize(cp, section); Event::unserialize(cp, section);
packet = new EtherPacket; packet = new PacketData;
packet->unserialize(cp, csprintf("%s.packet", section)); packet->unserialize(cp, csprintf("%s.packet", section));
} }

View file

@ -34,17 +34,39 @@
using namespace std; using namespace std;
void 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_SCALAR(length);
SERIALIZE_ARRAY(data, length); SERIALIZE_ARRAY(data, length);
} }
void void
EtherPacket::unserialize(Checkpoint *cp, const string &section) PacketData::unserialize(Checkpoint *cp, const string &section)
{ {
UNSERIALIZE_SCALAR(length); UNSERIALIZE_SCALAR(length);
data = new uint8_t[length]; data = new uint8_t[length];
UNSERIALIZE_ARRAY(data, length); UNSERIALIZE_ARRAY(data, length);
} }

View file

@ -37,70 +37,50 @@
#include <memory> #include <memory>
#include <assert.h> #include <assert.h>
#include "sim/host.hh"
#include "base/refcnt.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 * Reference counted class containing ethernet packet data
*/ */
class EtherPacket : public RefCounted class Checkpoint;
class PacketData : public RefCounted
{ {
public: public:
uint8_t *data; uint8_t *data;
int length; int length;
public: protected:
EtherPacket() : data(NULL), length(0) {} uint8_t *_eth;
EtherPacket(std::auto_ptr<uint8_t> d, int l) uint8_t *_ip;
: data(d.release()), length(l) {} uint8_t *_tcp;
~EtherPacket() { if (data) delete [] data; } uint8_t *_udp;
void doext();
void ext()
{
if (_eth != data)
doext();
}
public: public:
bool IsUnicast() { return data[0] == 0x00; } PacketData() : data(NULL), length(0) { doext(); }
bool IsMulticast() { return data[0] == 0x01; } PacketData(std::auto_ptr<uint8_t> d, int l)
bool IsBroadcast() { return data[0] == 0xff; } : data(d.release()), length(l) { doext(); }
~PacketData() { if (data) delete [] data; }
bool isIpPkt() { public:
eth_header *eth = (eth_header *) data; EthHdr *eth() { ext(); return (EthHdr *)_eth; }
return (eth->type == 0x8); IpHdr *ip() { ext(); return (IpHdr *)_ip; }
} TcpHdr *tcp() { ext(); return (TcpHdr *)_tcp; }
bool isTcpPkt(ip_header *ip) { UdpHdr *udp() { ext(); return (UdpHdr *)_udp; }
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;
public:
void serialize(std::ostream &os); void serialize(std::ostream &os);
void unserialize(Checkpoint *cp, const std::string &section); void unserialize(Checkpoint *cp, const std::string &section);
}; };
typedef RefCountingPtr<EtherPacket> PacketPtr; typedef RefCountingPtr<PacketData> PacketPtr;
#endif // __ETHERPKT_HH__ #endif // __ETHERPKT_HH__

View file

@ -219,7 +219,7 @@ EtherTap::process(int revent)
while (data_len != 0 && buffer_offset >= data_len + sizeof(u_int32_t)) { while (data_len != 0 && buffer_offset >= data_len + sizeof(u_int32_t)) {
PacketPtr packet; PacketPtr packet;
packet = new EtherPacket; packet = new PacketData;
packet->data = new uint8_t[data_len]; packet->data = new uint8_t[data_len];
packet->length = data_len; packet->length = data_len;
memcpy(packet->data, data, data_len); memcpy(packet->data, data, data_len);

View file

@ -70,7 +70,7 @@ class EtherTap : public EtherInt
std::queue<PacketPtr> packetBuffer; std::queue<PacketPtr> packetBuffer;
void process(int revent); void process(int revent);
void enqueue(EtherPacket *packet); void enqueue(PacketData *packet);
void retransmit(); void retransmit();
/* /*

View file

@ -87,11 +87,6 @@ const char *NsDmaState[] =
using namespace std; 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) .prereq(rxBytes)
; ;
txIPChecksums txIpChecksums
.name(name() + ".txIPChecksums") .name(name() + ".txIpChecksums")
.desc("Number of tx IP Checksums done by device") .desc("Number of tx IP Checksums done by device")
.precision(0) .precision(0)
.prereq(txBytes) .prereq(txBytes)
; ;
rxIPChecksums rxIpChecksums
.name(name() + ".rxIPChecksums") .name(name() + ".rxIpChecksums")
.desc("Number of rx IP Checksums done by device") .desc("Number of rx IP Checksums done by device")
.precision(0) .precision(0)
.prereq(rxBytes) .prereq(rxBytes)
; ;
txTCPChecksums txTcpChecksums
.name(name() + ".txTCPChecksums") .name(name() + ".txTcpChecksums")
.desc("Number of tx TCP Checksums done by device") .desc("Number of tx TCP Checksums done by device")
.precision(0) .precision(0)
.prereq(txBytes) .prereq(txBytes)
; ;
rxTCPChecksums rxTcpChecksums
.name(name() + ".rxTCPChecksums") .name(name() + ".rxTcpChecksums")
.desc("Number of rx TCP Checksums done by device") .desc("Number of rx TCP Checksums done by device")
.precision(0) .precision(0)
.prereq(rxBytes) .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 descDmaReads
.name(name() + ".descDMAReads") .name(name() + ".descDMAReads")
.desc("Number of descriptors the device read w/ DMA") .desc("Number of descriptors the device read w/ DMA")
@ -1332,14 +1341,13 @@ NSGigE::rxKick()
#if TRACING_ON #if TRACING_ON
if (DTRACE(Ethernet)) { if (DTRACE(Ethernet)) {
if (rxPacket->isIpPkt()) { const IpHdr *ip = rxPacket->ip();
ip_header *ip = rxPacket->getIpHdr(); if (ip) {
DPRINTF(Ethernet, "ID is %d\n", reverseEnd16(ip->ID)); DPRINTF(Ethernet, "ID is %d\n", ip->id());
if (rxPacket->isTcpPkt()) { const TcpHdr *tcp = rxPacket->tcp();
tcp_header *tcp = rxPacket->getTcpHdr(ip); if (tcp) {
DPRINTF(Ethernet, "Src Port=%d, Dest Port=%d\n", DPRINTF(Ethernet, "Src Port=%d, Dest Port=%d\n",
reverseEnd16(tcp->src_port_num), tcp->sport(), tcp->dport());
reverseEnd16(tcp->dest_port_num));
} }
} }
} }
@ -1395,33 +1403,36 @@ NSGigE::rxKick()
*/ */
if (rxFilterEnable) { if (rxFilterEnable) {
rxDescCache.cmdsts &= ~CMDSTS_DEST_MASK; rxDescCache.cmdsts &= ~CMDSTS_DEST_MASK;
if (rxFifo.front()->IsUnicast()) EthHdr *eth = rxFifoFront()->eth();
if (eth->unicast())
rxDescCache.cmdsts |= CMDSTS_DEST_SELF; rxDescCache.cmdsts |= CMDSTS_DEST_SELF;
if (rxFifo.front()->IsMulticast()) if (eth->multicast())
rxDescCache.cmdsts |= CMDSTS_DEST_MULTI; rxDescCache.cmdsts |= CMDSTS_DEST_MULTI;
if (rxFifo.front()->IsBroadcast()) if (eth->broadcast())
rxDescCache.cmdsts |= CMDSTS_DEST_MASK; rxDescCache.cmdsts |= CMDSTS_DEST_MASK;
} }
#endif #endif
if (rxPacket->isIpPkt() && extstsEnable) { if (extstsEnable && rxPacket->ip()) {
rxDescCache.extsts |= EXTSTS_IPPKT; rxDescCache.extsts |= EXTSTS_IPPKT;
rxIPChecksums++; rxIpChecksums++;
if (!ipChecksum(rxPacket, false)) { IpHdr *ip = rxPacket->ip();
if (ip->ip_cksum() != 0) {
DPRINTF(EthernetCksum, "Rx IP Checksum Error\n"); DPRINTF(EthernetCksum, "Rx IP Checksum Error\n");
rxDescCache.extsts |= EXTSTS_IPERR; rxDescCache.extsts |= EXTSTS_IPERR;
} }
if (rxPacket->isTcpPkt()) { if (rxPacket->tcp()) {
rxDescCache.extsts |= EXTSTS_TCPPKT; rxDescCache.extsts |= EXTSTS_TCPPKT;
rxTCPChecksums++; rxTcpChecksums++;
if (!tcpChecksum(rxPacket, false)) { if (ip->tu_cksum() != 0) {
DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n"); DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n");
rxDescCache.extsts |= EXTSTS_TCPERR; rxDescCache.extsts |= EXTSTS_TCPERR;
} }
} else if (rxPacket->isUdpPkt()) { } else if (rxPacket->udp()) {
rxDescCache.extsts |= EXTSTS_UDPPKT; rxDescCache.extsts |= EXTSTS_UDPPKT;
if (!udpChecksum(rxPacket, false)) { rxUdpChecksums++;
if (ip->tu_cksum() != 0) {
DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n"); DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n");
rxDescCache.extsts |= EXTSTS_UDPERR; rxDescCache.extsts |= EXTSTS_UDPERR;
} }
@ -1539,14 +1550,13 @@ NSGigE::transmit()
if (interface->sendPacket(txFifo.front())) { if (interface->sendPacket(txFifo.front())) {
#if TRACING_ON #if TRACING_ON
if (DTRACE(Ethernet)) { if (DTRACE(Ethernet)) {
if (txFifo.front()->isIpPkt()) { const IpHdr *ip = txFifo.front()->ip();
ip_header *ip = txFifo.front()->getIpHdr(); if (ip) {
DPRINTF(Ethernet, "ID is %d\n", reverseEnd16(ip->ID)); DPRINTF(Ethernet, "ID is %d\n", ip->id());
if (txFifo.front()->isTcpPkt()) { const TcpHdr *tcp = txFifo.front()->tcp();
tcp_header *tcp = txFifo.front()->getTcpHdr(ip); if (tcp) {
DPRINTF(Ethernet, "Src Port=%d, Dest Port=%d\n", DPRINTF(Ethernet, "Src Port=%d, Dest Port=%d\n",
reverseEnd16(tcp->src_port_num), tcp->sport(), tcp->dport());
reverseEnd16(tcp->dest_port_num));
} }
} }
} }
@ -1780,7 +1790,7 @@ NSGigE::txKick()
case txFifoBlock: case txFifoBlock:
if (!txPacket) { if (!txPacket) {
DPRINTF(EthernetSM, "****starting the tx of a new packet****\n"); DPRINTF(EthernetSM, "****starting the tx of a new packet****\n");
txPacket = new EtherPacket; txPacket = new PacketData;
txPacket->data = new uint8_t[16384]; txPacket->data = new uint8_t[16384];
txPacketBufPtr = txPacket->data; txPacketBufPtr = txPacket->data;
} }
@ -1806,15 +1816,22 @@ NSGigE::txKick()
DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n"); DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n");
/* deal with the the packet that just finished */ /* deal with the the packet that just finished */
if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) { if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) {
IpHdr *ip = txPacket->ip();
if (txDescCache.extsts & EXTSTS_UDPPKT) { 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) { } else if (txDescCache.extsts & EXTSTS_TCPPKT) {
tcpChecksum(txPacket, true); TcpHdr *tcp = txPacket->tcp();
txTCPChecksums++; tcp->sum(0);
tcp->sum(ip->tu_cksum());
txTcpChecksums++;
} }
if (txDescCache.extsts & EXTSTS_IPPKT) { if (txDescCache.extsts & EXTSTS_IPPKT) {
ipChecksum(txPacket, true); ip->sum(0);
txIPChecksums++; ip->sum(ip->ip_cksum());
txIpChecksums++;
} }
} }
@ -1977,9 +1994,8 @@ NSGigE::rxFilter(PacketPtr packet)
bool drop = true; bool drop = true;
string type; string type;
if (packet->IsUnicast()) { EthHdr *eth = packet->eth();
type = "unicast"; if (eth->unicast()) {
// If we're accepting all unicast addresses // If we're accepting all unicast addresses
if (acceptUnicast) if (acceptUnicast)
drop = false; drop = false;
@ -1989,28 +2005,19 @@ NSGigE::rxFilter(PacketPtr packet)
memcmp(rom.perfectMatch, packet->data, EADDR_LEN) == 0) memcmp(rom.perfectMatch, packet->data, EADDR_LEN) == 0)
drop = false; drop = false;
eth_header *eth = (eth_header *) packet->data; if (acceptArp && eth->type() == ETH_TYPE_ARP)
if ((acceptArp) && (eth->type == 0x608))
drop = false; drop = false;
} else if (packet->IsBroadcast()) { } else if (eth->broadcast()) {
type = "broadcast";
// if we're accepting broadcasts // if we're accepting broadcasts
if (acceptBroadcast) if (acceptBroadcast)
drop = false; drop = false;
} else if (packet->IsMulticast()) { } else if (eth->multicast()) {
type = "multicast";
// if we're accepting all multicasts // if we're accepting all multicasts
if (acceptMulticast) if (acceptMulticast)
drop = false; drop = false;
} else {
type = "unknown";
// oh well, punt on this one
} }
if (drop) { if (drop) {
@ -2058,121 +2065,6 @@ NSGigE::recvPacket(PacketPtr packet)
return true; 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); UNSERIALIZE_SCALAR(txNumPkts);
int i; int i;
for (i = 0; i < txNumPkts; ++i) { for (i = 0; i < txNumPkts; ++i) {
PacketPtr p = new EtherPacket; PacketPtr p = new PacketData;
p->unserialize(cp, csprintf("%s.rxFifo%d", section, i)); p->unserialize(cp, csprintf("%s.rxFifo%d", section, i));
txFifo.push_back(p); txFifo.push_back(p);
} }
@ -2406,7 +2298,7 @@ NSGigE::unserialize(Checkpoint *cp, const std::string &section)
int rxNumPkts; int rxNumPkts;
UNSERIALIZE_SCALAR(rxNumPkts); UNSERIALIZE_SCALAR(rxNumPkts);
for (i = 0; i < rxNumPkts; ++i) { for (i = 0; i < rxNumPkts; ++i) {
PacketPtr p = new EtherPacket; PacketPtr p = new PacketData;
p->unserialize(cp, csprintf("%s.rxFifo%d", section, i)); p->unserialize(cp, csprintf("%s.rxFifo%d", section, i));
rxFifo.push_back(p); rxFifo.push_back(p);
} }
@ -2417,7 +2309,7 @@ NSGigE::unserialize(Checkpoint *cp, const std::string &section)
bool txPacketExists; bool txPacketExists;
UNSERIALIZE_SCALAR(txPacketExists); UNSERIALIZE_SCALAR(txPacketExists);
if (txPacketExists) { if (txPacketExists) {
txPacket = new EtherPacket; txPacket = new PacketData;
txPacket->unserialize(cp, csprintf("%s.txPacket", section)); txPacket->unserialize(cp, csprintf("%s.txPacket", section));
uint32_t txPktBufPtr; uint32_t txPktBufPtr;
UNSERIALIZE_SCALAR(txPktBufPtr); UNSERIALIZE_SCALAR(txPktBufPtr);
@ -2429,7 +2321,7 @@ NSGigE::unserialize(Checkpoint *cp, const std::string &section)
UNSERIALIZE_SCALAR(rxPacketExists); UNSERIALIZE_SCALAR(rxPacketExists);
rxPacket = 0; rxPacket = 0;
if (rxPacketExists) { if (rxPacketExists) {
rxPacket = new EtherPacket; rxPacket = new PacketData;
rxPacket->unserialize(cp, csprintf("%s.rxPacket", section)); rxPacket->unserialize(cp, csprintf("%s.rxPacket", section));
uint32_t rxPktBufPtr; uint32_t rxPktBufPtr;
UNSERIALIZE_SCALAR(rxPktBufPtr); UNSERIALIZE_SCALAR(rxPktBufPtr);
@ -2530,28 +2422,6 @@ NSGigE::cacheAccess(MemReqPtr &req)
req->paddr, req->paddr - addr); req->paddr, req->paddr - addr);
return curTick + pioLatency; 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) BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt)

View file

@ -329,15 +329,6 @@ class NSGigE : public PciDev
typedef EventWrapper<NSGigE, &NSGigE::cpuInterrupt> IntrEvent; typedef EventWrapper<NSGigE, &NSGigE::cpuInterrupt> IntrEvent;
friend class IntrEvent; friend class IntrEvent;
IntrEvent *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; NSGigEInt *interface;
public: public:
@ -377,10 +368,12 @@ class NSGigE : public PciDev
Stats::Scalar<> rxBytes; Stats::Scalar<> rxBytes;
Stats::Scalar<> txPackets; Stats::Scalar<> txPackets;
Stats::Scalar<> rxPackets; Stats::Scalar<> rxPackets;
Stats::Scalar<> txIPChecksums; Stats::Scalar<> txIpChecksums;
Stats::Scalar<> rxIPChecksums; Stats::Scalar<> rxIpChecksums;
Stats::Scalar<> txTCPChecksums; Stats::Scalar<> txTcpChecksums;
Stats::Scalar<> rxTCPChecksums; Stats::Scalar<> rxTcpChecksums;
Stats::Scalar<> txUdpChecksums;
Stats::Scalar<> rxUdpChecksums;
Stats::Scalar<> descDmaReads; Stats::Scalar<> descDmaReads;
Stats::Scalar<> descDmaWrites; Stats::Scalar<> descDmaWrites;
Stats::Scalar<> descDmaRdBytes; Stats::Scalar<> descDmaRdBytes;