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:
parent
bb59e2e7a3
commit
a58b834c8e
14 changed files with 394 additions and 388 deletions
|
@ -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
117
base/crc.cc
Normal 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
37
base/crc.hh
Normal 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__
|
128
base/inet.cc
128
base/inet.cc
|
@ -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);
|
||||||
|
}
|
||||||
|
|
94
base/inet.hh
94
base/inet.hh
|
@ -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__
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 §ion)
|
||||||
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 §ion)
|
LinkDelayEvent::unserialize(Checkpoint *cp, const string §ion)
|
||||||
{
|
{
|
||||||
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 §ion)
|
PacketData::unserialize(Checkpoint *cp, const string §ion)
|
||||||
{
|
{
|
||||||
UNSERIALIZE_SCALAR(length);
|
UNSERIALIZE_SCALAR(length);
|
||||||
data = new uint8_t[length];
|
data = new uint8_t[length];
|
||||||
UNSERIALIZE_ARRAY(data, length);
|
UNSERIALIZE_ARRAY(data, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 §ion);
|
void unserialize(Checkpoint *cp, const std::string §ion);
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef RefCountingPtr<EtherPacket> PacketPtr;
|
typedef RefCountingPtr<PacketData> PacketPtr;
|
||||||
|
|
||||||
#endif // __ETHERPKT_HH__
|
#endif // __ETHERPKT_HH__
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
270
dev/ns_gige.cc
270
dev/ns_gige.cc
|
@ -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 §ion)
|
||||||
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 §ion)
|
||||||
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 §ion)
|
||||||
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 §ion)
|
||||||
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)
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue