diff options
author | Nathan Binkert <binkertn@umich.edu> | 2004-09-20 10:43:53 -0400 |
---|---|---|
committer | Nathan Binkert <binkertn@umich.edu> | 2004-09-20 10:43:53 -0400 |
commit | a58b834c8e333385f9be37eb4d343d70f8177613 (patch) | |
tree | 8f9d8224a37617ae697e3c3620f7dbfad11c34dd /dev | |
parent | bb59e2e7a3ec7e599dac92cfc780c7fdde2ad286 (diff) | |
download | gem5-a58b834c8e333385f9be37eb4d343d70f8177613.tar.xz |
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
Diffstat (limited to 'dev')
-rw-r--r-- | dev/etherlink.cc | 7 | ||||
-rw-r--r-- | dev/etherpkt.cc | 28 | ||||
-rw-r--r-- | dev/etherpkt.hh | 72 | ||||
-rw-r--r-- | dev/ethertap.cc | 2 | ||||
-rw-r--r-- | dev/ethertap.hh | 2 | ||||
-rw-r--r-- | dev/ns_gige.cc | 270 | ||||
-rw-r--r-- | dev/ns_gige.hh | 19 |
7 files changed, 133 insertions, 267 deletions
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 <memory> #include <assert.h> -#include "sim/host.hh" #include "base/refcnt.hh" -#include "base/inet_hdrs.hh" +#include "base/inet.hh" +#include "sim/host.hh" -class Checkpoint; /* * Reference counted class containing ethernet packet data */ -class EtherPacket : public RefCounted +class Checkpoint; +class PacketData : public RefCounted { public: uint8_t *data; int length; - public: - EtherPacket() : data(NULL), length(0) {} - EtherPacket(std::auto_ptr<uint8_t> d, int l) - : data(d.release()), length(l) {} - ~EtherPacket() { if (data) delete [] data; } - - 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<uint8_t> 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<EtherPacket> 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<EtherPacket> PacketPtr; +typedef RefCountingPtr<PacketData> PacketPtr; #endif // __ETHERPKT_HH__ diff --git a/dev/ethertap.cc b/dev/ethertap.cc index edc400760..b40a93c1b 100644 --- a/dev/ethertap.cc +++ b/dev/ethertap.cc @@ -219,7 +219,7 @@ EtherTap::process(int revent) while (data_len != 0 && buffer_offset >= data_len + sizeof(u_int32_t)) { PacketPtr packet; - packet = new EtherPacket; + packet = new PacketData; packet->data = new uint8_t[data_len]; packet->length = data_len; memcpy(packet->data, data, data_len); diff --git a/dev/ethertap.hh b/dev/ethertap.hh index 1fe368085..9c77a4a4f 100644 --- a/dev/ethertap.hh +++ b/dev/ethertap.hh @@ -70,7 +70,7 @@ class EtherTap : public EtherInt std::queue<PacketPtr> packetBuffer; void process(int revent); - void enqueue(EtherPacket *packet); + void enqueue(PacketData *packet); void retransmit(); /* diff --git a/dev/ns_gige.cc b/dev/ns_gige.cc index 87ac5b593..9238a7c7e 100644 --- a/dev/ns_gige.cc +++ b/dev/ns_gige.cc @@ -87,11 +87,6 @@ const char *NsDmaState[] = using namespace std; -// helper function declarations -// These functions reverse Endianness so we can evaluate network data -// correctly -uint16_t reverseEnd16(uint16_t); -uint32_t reverseEnd32(uint32_t); /////////////////////////////////////////////////////////////////////// // @@ -194,34 +189,48 @@ NSGigE::regStats() .prereq(rxBytes) ; - txIPChecksums - .name(name() + ".txIPChecksums") + txIpChecksums + .name(name() + ".txIpChecksums") .desc("Number of tx IP Checksums done by device") .precision(0) .prereq(txBytes) ; - rxIPChecksums - .name(name() + ".rxIPChecksums") + rxIpChecksums + .name(name() + ".rxIpChecksums") .desc("Number of rx IP Checksums done by device") .precision(0) .prereq(rxBytes) ; - txTCPChecksums - .name(name() + ".txTCPChecksums") + txTcpChecksums + .name(name() + ".txTcpChecksums") .desc("Number of tx TCP Checksums done by device") .precision(0) .prereq(txBytes) ; - rxTCPChecksums - .name(name() + ".rxTCPChecksums") + rxTcpChecksums + .name(name() + ".rxTcpChecksums") .desc("Number of rx TCP Checksums done by device") .precision(0) .prereq(rxBytes) ; + txUdpChecksums + .name(name() + ".txUdpChecksums") + .desc("Number of tx UDP Checksums done by device") + .precision(0) + .prereq(txBytes) + ; + + rxUdpChecksums + .name(name() + ".rxUdpChecksums") + .desc("Number of rx UDP Checksums done by device") + .precision(0) + .prereq(rxBytes) + ; + descDmaReads .name(name() + ".descDMAReads") .desc("Number of descriptors the device read w/ DMA") @@ -1332,14 +1341,13 @@ NSGigE::rxKick() #if TRACING_ON if (DTRACE(Ethernet)) { - if (rxPacket->isIpPkt()) { - ip_header *ip = rxPacket->getIpHdr(); - DPRINTF(Ethernet, "ID is %d\n", reverseEnd16(ip->ID)); - if (rxPacket->isTcpPkt()) { - tcp_header *tcp = rxPacket->getTcpHdr(ip); + const IpHdr *ip = rxPacket->ip(); + if (ip) { + DPRINTF(Ethernet, "ID is %d\n", ip->id()); + const TcpHdr *tcp = rxPacket->tcp(); + if (tcp) { DPRINTF(Ethernet, "Src Port=%d, Dest Port=%d\n", - reverseEnd16(tcp->src_port_num), - reverseEnd16(tcp->dest_port_num)); + tcp->sport(), tcp->dport()); } } } @@ -1395,33 +1403,36 @@ NSGigE::rxKick() */ if (rxFilterEnable) { rxDescCache.cmdsts &= ~CMDSTS_DEST_MASK; - if (rxFifo.front()->IsUnicast()) + EthHdr *eth = rxFifoFront()->eth(); + if (eth->unicast()) rxDescCache.cmdsts |= CMDSTS_DEST_SELF; - if (rxFifo.front()->IsMulticast()) + if (eth->multicast()) rxDescCache.cmdsts |= CMDSTS_DEST_MULTI; - if (rxFifo.front()->IsBroadcast()) + if (eth->broadcast()) rxDescCache.cmdsts |= CMDSTS_DEST_MASK; } #endif - if (rxPacket->isIpPkt() && extstsEnable) { + if (extstsEnable && rxPacket->ip()) { rxDescCache.extsts |= EXTSTS_IPPKT; - rxIPChecksums++; - if (!ipChecksum(rxPacket, false)) { + rxIpChecksums++; + IpHdr *ip = rxPacket->ip(); + if (ip->ip_cksum() != 0) { DPRINTF(EthernetCksum, "Rx IP Checksum Error\n"); rxDescCache.extsts |= EXTSTS_IPERR; } - if (rxPacket->isTcpPkt()) { + if (rxPacket->tcp()) { rxDescCache.extsts |= EXTSTS_TCPPKT; - rxTCPChecksums++; - if (!tcpChecksum(rxPacket, false)) { + rxTcpChecksums++; + if (ip->tu_cksum() != 0) { DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n"); rxDescCache.extsts |= EXTSTS_TCPERR; } - } else if (rxPacket->isUdpPkt()) { + } else if (rxPacket->udp()) { rxDescCache.extsts |= EXTSTS_UDPPKT; - if (!udpChecksum(rxPacket, false)) { + rxUdpChecksums++; + if (ip->tu_cksum() != 0) { DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n"); rxDescCache.extsts |= EXTSTS_UDPERR; } @@ -1539,14 +1550,13 @@ NSGigE::transmit() if (interface->sendPacket(txFifo.front())) { #if TRACING_ON if (DTRACE(Ethernet)) { - if (txFifo.front()->isIpPkt()) { - ip_header *ip = txFifo.front()->getIpHdr(); - DPRINTF(Ethernet, "ID is %d\n", reverseEnd16(ip->ID)); - if (txFifo.front()->isTcpPkt()) { - tcp_header *tcp = txFifo.front()->getTcpHdr(ip); + const IpHdr *ip = txFifo.front()->ip(); + if (ip) { + DPRINTF(Ethernet, "ID is %d\n", ip->id()); + const TcpHdr *tcp = txFifo.front()->tcp(); + if (tcp) { DPRINTF(Ethernet, "Src Port=%d, Dest Port=%d\n", - reverseEnd16(tcp->src_port_num), - reverseEnd16(tcp->dest_port_num)); + tcp->sport(), tcp->dport()); } } } @@ -1780,7 +1790,7 @@ NSGigE::txKick() case txFifoBlock: if (!txPacket) { DPRINTF(EthernetSM, "****starting the tx of a new packet****\n"); - txPacket = new EtherPacket; + txPacket = new PacketData; txPacket->data = new uint8_t[16384]; txPacketBufPtr = txPacket->data; } @@ -1806,15 +1816,22 @@ NSGigE::txKick() DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n"); /* deal with the the packet that just finished */ if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) { + IpHdr *ip = txPacket->ip(); if (txDescCache.extsts & EXTSTS_UDPPKT) { - udpChecksum(txPacket, true); + UdpHdr *udp = txPacket->udp(); + udp->sum(0); + udp->sum(ip->tu_cksum()); + txUdpChecksums++; } else if (txDescCache.extsts & EXTSTS_TCPPKT) { - tcpChecksum(txPacket, true); - txTCPChecksums++; + TcpHdr *tcp = txPacket->tcp(); + tcp->sum(0); + tcp->sum(ip->tu_cksum()); + txTcpChecksums++; } if (txDescCache.extsts & EXTSTS_IPPKT) { - ipChecksum(txPacket, true); - txIPChecksums++; + ip->sum(0); + ip->sum(ip->ip_cksum()); + txIpChecksums++; } } @@ -1977,9 +1994,8 @@ NSGigE::rxFilter(PacketPtr packet) bool drop = true; string type; - if (packet->IsUnicast()) { - type = "unicast"; - + EthHdr *eth = packet->eth(); + if (eth->unicast()) { // If we're accepting all unicast addresses if (acceptUnicast) drop = false; @@ -1989,28 +2005,19 @@ NSGigE::rxFilter(PacketPtr packet) memcmp(rom.perfectMatch, packet->data, EADDR_LEN) == 0) drop = false; - eth_header *eth = (eth_header *) packet->data; - if ((acceptArp) && (eth->type == 0x608)) + if (acceptArp && eth->type() == ETH_TYPE_ARP) drop = false; - } else if (packet->IsBroadcast()) { - type = "broadcast"; - + } else if (eth->broadcast()) { // if we're accepting broadcasts if (acceptBroadcast) drop = false; - } else if (packet->IsMulticast()) { - type = "multicast"; - + } else if (eth->multicast()) { // if we're accepting all multicasts if (acceptMulticast) drop = false; - } else { - type = "unknown"; - - // oh well, punt on this one } if (drop) { @@ -2058,121 +2065,6 @@ NSGigE::recvPacket(PacketPtr packet) return true; } -/** - * does a udp checksum. if gen is true, then it generates it and puts - * it in the right place else, it just checks what it calculates - * against the value in the header in packet - */ -bool -NSGigE::udpChecksum(PacketPtr packet, bool gen) -{ - ip_header *ip = packet->getIpHdr(); - udp_header *hdr = packet->getUdpHdr(ip); - - pseudo_header *pseudo = new pseudo_header; - - pseudo->src_ip_addr = ip->src_ip_addr; - pseudo->dest_ip_addr = ip->dest_ip_addr; - pseudo->protocol = ip->protocol; - pseudo->len = hdr->len; - - uint16_t cksum = checksumCalc((uint16_t *) pseudo, (uint16_t *) hdr, - (uint32_t) hdr->len); - - delete pseudo; - if (gen) - hdr->chksum = cksum; - else - if (cksum != 0) - return false; - - return true; -} - -bool -NSGigE::tcpChecksum(PacketPtr packet, bool gen) -{ - ip_header *ip = packet->getIpHdr(); - tcp_header *hdr = packet->getTcpHdr(ip); - - uint16_t cksum; - pseudo_header *pseudo = new pseudo_header; - if (!gen) { - pseudo->src_ip_addr = ip->src_ip_addr; - pseudo->dest_ip_addr = ip->dest_ip_addr; - pseudo->protocol = reverseEnd16(ip->protocol); - pseudo->len = reverseEnd16(reverseEnd16(ip->dgram_len) - - (ip->vers_len & 0xf)*4); - - cksum = checksumCalc((uint16_t *) pseudo, (uint16_t *) hdr, - (uint32_t) reverseEnd16(pseudo->len)); - } else { - pseudo->src_ip_addr = 0; - pseudo->dest_ip_addr = 0; - pseudo->protocol = hdr->chksum; - pseudo->len = 0; - hdr->chksum = 0; - cksum = checksumCalc((uint16_t *) pseudo, (uint16_t *) hdr, - (uint32_t) (reverseEnd16(ip->dgram_len) - - (ip->vers_len & 0xf)*4)); - } - - delete pseudo; - if (gen) - hdr->chksum = cksum; - else - if (cksum != 0) - return false; - - return true; -} - -bool -NSGigE::ipChecksum(PacketPtr packet, bool gen) -{ - ip_header *hdr = packet->getIpHdr(); - - uint16_t cksum = checksumCalc(NULL, (uint16_t *) hdr, - (hdr->vers_len & 0xf)*4); - - if (gen) { - DPRINTF(EthernetCksum, "generated checksum: %#x\n", cksum); - hdr->hdr_chksum = cksum; - } - else - if (cksum != 0) - return false; - - return true; -} - -uint16_t -NSGigE::checksumCalc(uint16_t *pseudo, uint16_t *buf, uint32_t len) -{ - uint32_t sum = 0; - - uint16_t last_pad = 0; - if (len & 1) { - last_pad = buf[len/2] & 0xff; - len--; - sum += last_pad; - } - - if (pseudo) { - sum = pseudo[0] + pseudo[1] + pseudo[2] + - pseudo[3] + pseudo[4] + pseudo[5]; - } - - for (int i=0; i < (len/2); ++i) { - sum += buf[i]; - } - - while (sum >> 16) - sum = (sum >> 16) + (sum & 0xffff); - - return ~sum; -} - //===================================================================== // // @@ -2398,7 +2290,7 @@ NSGigE::unserialize(Checkpoint *cp, const std::string §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<NSGigE, &NSGigE::cpuInterrupt> IntrEvent; friend class IntrEvent; IntrEvent *intrEvent; - - /** - * Hardware checksum support - */ - bool udpChecksum(PacketPtr packet, bool gen); - bool tcpChecksum(PacketPtr packet, bool gen); - bool ipChecksum(PacketPtr packet, bool gen); - uint16_t checksumCalc(uint16_t *pseudo, uint16_t *buf, uint32_t len); - NSGigEInt *interface; public: @@ -377,10 +368,12 @@ class NSGigE : public PciDev Stats::Scalar<> rxBytes; Stats::Scalar<> txPackets; Stats::Scalar<> rxPackets; - Stats::Scalar<> txIPChecksums; - Stats::Scalar<> rxIPChecksums; - Stats::Scalar<> txTCPChecksums; - Stats::Scalar<> rxTCPChecksums; + Stats::Scalar<> txIpChecksums; + Stats::Scalar<> rxIpChecksums; + Stats::Scalar<> txTcpChecksums; + Stats::Scalar<> rxTcpChecksums; + Stats::Scalar<> txUdpChecksums; + Stats::Scalar<> rxUdpChecksums; Stats::Scalar<> descDmaReads; Stats::Scalar<> descDmaWrites; Stats::Scalar<> descDmaRdBytes; |