IGbE: Add support for TCP segment offload
This commit is contained in:
parent
aab595a306
commit
400e516261
3 changed files with 243 additions and 37 deletions
|
@ -883,45 +883,128 @@ IGbE::RxDescCache::unserialize(Checkpoint *cp, const std::string §ion)
|
||||||
|
|
||||||
IGbE::TxDescCache::TxDescCache(IGbE *i, const std::string n, int s)
|
IGbE::TxDescCache::TxDescCache(IGbE *i, const std::string n, int s)
|
||||||
: DescCache<TxDesc>(i,n, s), pktDone(false), isTcp(false), pktWaiting(false),
|
: DescCache<TxDesc>(i,n, s), pktDone(false), isTcp(false), pktWaiting(false),
|
||||||
pktEvent(this)
|
useTso(false), pktEvent(this), headerEvent(this)
|
||||||
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
void
|
||||||
IGbE::TxDescCache::getPacketSize()
|
IGbE::TxDescCache::processContextDesc()
|
||||||
{
|
{
|
||||||
assert(unusedCache.size());
|
assert(unusedCache.size());
|
||||||
|
|
||||||
TxDesc *desc;
|
TxDesc *desc;
|
||||||
|
|
||||||
DPRINTF(EthernetDesc, "Starting processing of descriptor\n");
|
DPRINTF(EthernetDesc, "Checking and processing context descriptors\n");
|
||||||
|
|
||||||
while (unusedCache.size() && TxdOp::isContext(unusedCache.front())) {
|
while (!useTso && unusedCache.size() && TxdOp::isContext(unusedCache.front())) {
|
||||||
DPRINTF(EthernetDesc, "Got context descriptor type... skipping\n");
|
DPRINTF(EthernetDesc, "Got context descriptor type...\n");
|
||||||
|
|
||||||
// I think we can just ignore these for now?
|
|
||||||
desc = unusedCache.front();
|
desc = unusedCache.front();
|
||||||
DPRINTF(EthernetDesc, "Descriptor upper: %#x lower: %#X\n", desc->d1,
|
DPRINTF(EthernetDesc, "Descriptor upper: %#x lower: %#X\n",
|
||||||
desc->d2);
|
desc->d1, desc->d2);
|
||||||
|
|
||||||
|
|
||||||
// is this going to be a tcp or udp packet?
|
// is this going to be a tcp or udp packet?
|
||||||
isTcp = TxdOp::tcp(desc) ? true : false;
|
isTcp = TxdOp::tcp(desc) ? true : false;
|
||||||
|
|
||||||
// make sure it's ipv4
|
if (TxdOp::tse(desc)) {
|
||||||
//assert(TxdOp::ip(desc));
|
DPRINTF(EthernetDesc, "TCP offload enabled for packet hdrlen: %d mss: %d paylen %d\n",
|
||||||
|
TxdOp::hdrlen(desc), TxdOp::mss(desc), TxdOp::getLen(desc));
|
||||||
|
// setup all the TSO variables
|
||||||
|
useTso = true;
|
||||||
|
tsoHeaderLen = TxdOp::hdrlen(desc);
|
||||||
|
tsoMss = TxdOp::mss(desc);
|
||||||
|
tsoTotalLen = TxdOp::getLen(desc);
|
||||||
|
tsoLoadedHeader = false;
|
||||||
|
tsoDescBytesUsed = 0;
|
||||||
|
tsoUsedLen = 0;
|
||||||
|
tsoPrevSeq = 0;
|
||||||
|
tsoPktHasHeader = false;
|
||||||
|
tsoPkts = 0;
|
||||||
|
}
|
||||||
|
|
||||||
TxdOp::setDd(desc);
|
TxdOp::setDd(desc);
|
||||||
unusedCache.pop_front();
|
unusedCache.pop_front();
|
||||||
usedCache.push_back(desc);
|
usedCache.push_back(desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!unusedCache.size())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (useTso && !tsoLoadedHeader) {
|
||||||
|
// we need to fetch a header
|
||||||
|
DPRINTF(EthernetDesc, "Starting DMA of TSO header\n");
|
||||||
|
desc = unusedCache.front();
|
||||||
|
assert(TxdOp::isData(desc) && TxdOp::getLen(desc) >= tsoHeaderLen);
|
||||||
|
pktWaiting = true;
|
||||||
|
assert(tsoHeaderLen <= 256);
|
||||||
|
igbe->dmaRead(igbe->platform->pciToDma(TxdOp::getBuf(desc)),
|
||||||
|
tsoHeaderLen, &headerEvent, tsoHeader, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IGbE::TxDescCache::headerComplete()
|
||||||
|
{
|
||||||
|
DPRINTF(EthernetDesc, "TSO: Fetching TSO header complete\n");
|
||||||
|
pktWaiting = false;
|
||||||
|
|
||||||
|
assert(unusedCache.size());
|
||||||
|
TxDesc *desc = unusedCache.front();
|
||||||
|
DPRINTF(EthernetDesc, "TSO: len: %d tsoHeaderLen: %d\n",
|
||||||
|
TxdOp::getLen(desc), tsoHeaderLen);
|
||||||
|
|
||||||
|
if (TxdOp::getLen(desc) == tsoHeaderLen) {
|
||||||
|
tsoDescBytesUsed = 0;
|
||||||
|
tsoLoadedHeader = true;
|
||||||
|
unusedCache.pop_front();
|
||||||
|
usedCache.push_back(desc);
|
||||||
|
} else {
|
||||||
|
// I don't think this case happens, I think the headrer is always
|
||||||
|
// it's own packet, if it wasn't it might be as simple as just
|
||||||
|
// incrementing descBytesUsed by the header length, but I'm not
|
||||||
|
// completely sure
|
||||||
|
panic("TSO header part of bigger packet, not implemented\n");
|
||||||
|
}
|
||||||
|
enableSm();
|
||||||
|
igbe->checkDrain();
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
IGbE::TxDescCache::getPacketSize(EthPacketPtr p)
|
||||||
|
{
|
||||||
|
TxDesc *desc;
|
||||||
|
|
||||||
|
|
||||||
if (!unusedCache.size())
|
if (!unusedCache.size())
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
DPRINTF(EthernetDesc, "Starting processing of descriptor\n");
|
||||||
|
|
||||||
|
assert(!useTso || tsoLoadedHeader);
|
||||||
|
desc = unusedCache.front();
|
||||||
|
|
||||||
|
|
||||||
|
if (useTso) {
|
||||||
|
DPRINTF(EthernetDesc, "getPacket(): TxDescriptor data d1: %#llx d2: %#llx\n", desc->d1, desc->d2);
|
||||||
|
DPRINTF(EthernetDesc, "TSO: use: %d hdrlen: %d mss: %d total: %d used: %d loaded hdr: %d\n",
|
||||||
|
useTso, tsoHeaderLen, tsoMss, tsoTotalLen, tsoUsedLen, tsoLoadedHeader);
|
||||||
|
DPRINTF(EthernetDesc, "TSO: descBytesUsed: %d copyBytes: %d this descLen: %d\n",
|
||||||
|
tsoDescBytesUsed, tsoCopyBytes, TxdOp::getLen(desc));
|
||||||
|
DPRINTF(EthernetDesc, "TSO: pktHasHeader: %d\n", tsoPktHasHeader);
|
||||||
|
|
||||||
|
if (tsoPktHasHeader)
|
||||||
|
tsoCopyBytes = std::min((tsoMss + tsoHeaderLen) - p->length, TxdOp::getLen(desc) - tsoDescBytesUsed);
|
||||||
|
else
|
||||||
|
tsoCopyBytes = std::min(tsoMss, TxdOp::getLen(desc) - tsoDescBytesUsed);
|
||||||
|
Addr pkt_size = tsoCopyBytes + (tsoPktHasHeader ? 0 : tsoHeaderLen);
|
||||||
|
DPRINTF(EthernetDesc, "TSO: Next packet is %d bytes\n", pkt_size);
|
||||||
|
return pkt_size;
|
||||||
|
}
|
||||||
|
|
||||||
DPRINTF(EthernetDesc, "Next TX packet is %d bytes\n",
|
DPRINTF(EthernetDesc, "Next TX packet is %d bytes\n",
|
||||||
TxdOp::getLen(unusedCache.front()));
|
TxdOp::getLen(unusedCache.front()));
|
||||||
|
return TxdOp::getLen(desc);
|
||||||
return TxdOp::getLen(unusedCache.front());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -939,10 +1022,29 @@ IGbE::TxDescCache::getPacketData(EthPacketPtr p)
|
||||||
pktWaiting = true;
|
pktWaiting = true;
|
||||||
|
|
||||||
DPRINTF(EthernetDesc, "Starting DMA of packet at offset %d\n", p->length);
|
DPRINTF(EthernetDesc, "Starting DMA of packet at offset %d\n", p->length);
|
||||||
|
|
||||||
|
if (useTso) {
|
||||||
|
assert(tsoLoadedHeader);
|
||||||
|
if (!tsoPktHasHeader) {
|
||||||
|
DPRINTF(EthernetDesc, "Loading TSO header (%d bytes) into start of packet\n",
|
||||||
|
tsoHeaderLen);
|
||||||
|
memcpy(p->data, &tsoHeader,tsoHeaderLen);
|
||||||
|
p->length +=tsoHeaderLen;
|
||||||
|
tsoPktHasHeader = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (useTso) {
|
||||||
|
tsoDescBytesUsed += tsoCopyBytes;
|
||||||
|
assert(tsoDescBytesUsed <= TxdOp::getLen(desc));
|
||||||
|
DPRINTF(EthernetDesc, "Starting DMA of packet at offset %d length: %d\n",
|
||||||
|
p->length, tsoCopyBytes);
|
||||||
|
igbe->dmaRead(igbe->platform->pciToDma(TxdOp::getBuf(desc)) + tsoDescBytesUsed,
|
||||||
|
tsoCopyBytes, &pktEvent, p->data + p->length, igbe->txReadDelay);
|
||||||
|
} else {
|
||||||
igbe->dmaRead(igbe->platform->pciToDma(TxdOp::getBuf(desc)),
|
igbe->dmaRead(igbe->platform->pciToDma(TxdOp::getBuf(desc)),
|
||||||
TxdOp::getLen(desc), &pktEvent, p->data + p->length, igbe->txReadDelay);
|
TxdOp::getLen(desc), &pktEvent, p->data + p->length, igbe->txReadDelay);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -960,11 +1062,27 @@ IGbE::TxDescCache::pktComplete()
|
||||||
assert((TxdOp::isLegacy(desc) || TxdOp::isData(desc)) && TxdOp::getLen(desc));
|
assert((TxdOp::isLegacy(desc) || TxdOp::isData(desc)) && TxdOp::getLen(desc));
|
||||||
|
|
||||||
DPRINTF(EthernetDesc, "TxDescriptor data d1: %#llx d2: %#llx\n", desc->d1, desc->d2);
|
DPRINTF(EthernetDesc, "TxDescriptor data d1: %#llx d2: %#llx\n", desc->d1, desc->d2);
|
||||||
|
DPRINTF(EthernetDesc, "TSO: use: %d hdrlen: %d mss: %d total: %d used: %d loaded hdr: %d\n",
|
||||||
|
useTso, tsoHeaderLen, tsoMss, tsoTotalLen, tsoUsedLen, tsoLoadedHeader);
|
||||||
|
|
||||||
if (!TxdOp::eop(desc)) {
|
// Set the length of the data in the EtherPacket
|
||||||
|
if (useTso) {
|
||||||
|
pktPtr->length += tsoCopyBytes;
|
||||||
|
tsoUsedLen += tsoCopyBytes;
|
||||||
|
} else
|
||||||
pktPtr->length += TxdOp::getLen(desc);
|
pktPtr->length += TxdOp::getLen(desc);
|
||||||
|
|
||||||
|
DPRINTF(EthernetDesc, "TSO: descBytesUsed: %d copyBytes: %d\n",
|
||||||
|
tsoDescBytesUsed, tsoCopyBytes);
|
||||||
|
|
||||||
|
|
||||||
|
if ((!TxdOp::eop(desc) && !useTso) ||
|
||||||
|
(pktPtr->length < ( tsoMss + tsoHeaderLen) && tsoTotalLen != tsoUsedLen)) {
|
||||||
|
assert(!useTso || (tsoDescBytesUsed == TxdOp::getLen(desc)));
|
||||||
unusedCache.pop_front();
|
unusedCache.pop_front();
|
||||||
usedCache.push_back(desc);
|
usedCache.push_back(desc);
|
||||||
|
|
||||||
|
tsoDescBytesUsed = 0;
|
||||||
pktDone = true;
|
pktDone = true;
|
||||||
pktWaiting = false;
|
pktWaiting = false;
|
||||||
pktMultiDesc = true;
|
pktMultiDesc = true;
|
||||||
|
@ -977,25 +1095,47 @@ IGbE::TxDescCache::pktComplete()
|
||||||
igbe->checkDrain();
|
igbe->checkDrain();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pktMultiDesc = false;
|
pktMultiDesc = false;
|
||||||
|
|
||||||
// Set the length of the data in the EtherPacket
|
|
||||||
pktPtr->length += TxdOp::getLen(desc);
|
|
||||||
|
|
||||||
// no support for vlans
|
// no support for vlans
|
||||||
assert(!TxdOp::vle(desc));
|
assert(!TxdOp::vle(desc));
|
||||||
|
|
||||||
// we alway report status
|
|
||||||
assert(TxdOp::rs(desc));
|
|
||||||
|
|
||||||
// we only support single packet descriptors at this point
|
// we only support single packet descriptors at this point
|
||||||
|
if (!useTso)
|
||||||
assert(TxdOp::eop(desc));
|
assert(TxdOp::eop(desc));
|
||||||
|
|
||||||
// set that this packet is done
|
// set that this packet is done
|
||||||
|
if (TxdOp::rs(desc))
|
||||||
TxdOp::setDd(desc);
|
TxdOp::setDd(desc);
|
||||||
|
|
||||||
DPRINTF(EthernetDesc, "TxDescriptor data d1: %#llx d2: %#llx\n", desc->d1, desc->d2);
|
DPRINTF(EthernetDesc, "TxDescriptor data d1: %#llx d2: %#llx\n", desc->d1, desc->d2);
|
||||||
|
|
||||||
|
if (useTso) {
|
||||||
|
IpPtr ip(pktPtr);
|
||||||
|
if (ip) {
|
||||||
|
DPRINTF(EthernetDesc, "TSO: Modifying IP header. Id + %d\n",
|
||||||
|
tsoPkts);
|
||||||
|
ip->id(ip->id() + tsoPkts++);
|
||||||
|
ip->len(pktPtr->length - EthPtr(pktPtr)->size());
|
||||||
|
|
||||||
|
TcpPtr tcp(ip);
|
||||||
|
if (tcp) {
|
||||||
|
DPRINTF(EthernetDesc, "TSO: Modifying TCP header. old seq %d + %d\n",
|
||||||
|
tcp->seq(), tsoPrevSeq);
|
||||||
|
tcp->seq(tcp->seq() + tsoPrevSeq);
|
||||||
|
if (tsoUsedLen != tsoTotalLen)
|
||||||
|
tcp->flags(tcp->flags() & ~9); // clear fin & psh
|
||||||
|
}
|
||||||
|
UdpPtr udp(ip);
|
||||||
|
if (udp) {
|
||||||
|
DPRINTF(EthernetDesc, "TSO: Modifying UDP header.\n");
|
||||||
|
udp->len(pktPtr->length - EthPtr(pktPtr)->size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tsoPrevSeq = tsoUsedLen;
|
||||||
|
}
|
||||||
|
|
||||||
if (DTRACE(EthernetDesc)) {
|
if (DTRACE(EthernetDesc)) {
|
||||||
IpPtr ip(pktPtr);
|
IpPtr ip(pktPtr);
|
||||||
if (ip)
|
if (ip)
|
||||||
|
@ -1055,14 +1195,23 @@ IGbE::TxDescCache::pktComplete()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!useTso || TxdOp::getLen(desc) == tsoDescBytesUsed) {
|
||||||
|
DPRINTF(EthernetDesc, "Descriptor Done\n");
|
||||||
unusedCache.pop_front();
|
unusedCache.pop_front();
|
||||||
usedCache.push_back(desc);
|
usedCache.push_back(desc);
|
||||||
|
tsoDescBytesUsed = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (useTso && tsoUsedLen == tsoTotalLen)
|
||||||
|
useTso = false;
|
||||||
|
|
||||||
|
|
||||||
|
DPRINTF(EthernetDesc, "------Packet of %d bytes ready for transmission-------\n",
|
||||||
|
pktPtr->length);
|
||||||
pktDone = true;
|
pktDone = true;
|
||||||
pktWaiting = false;
|
pktWaiting = false;
|
||||||
pktPtr = NULL;
|
pktPtr = NULL;
|
||||||
|
tsoPktHasHeader = false;
|
||||||
DPRINTF(EthernetDesc, "Descriptor Done\n");
|
|
||||||
|
|
||||||
if (igbe->regs.txdctl.wthresh() == 0) {
|
if (igbe->regs.txdctl.wthresh() == 0) {
|
||||||
DPRINTF(EthernetDesc, "WTHRESH == 0, writing back descriptor\n");
|
DPRINTF(EthernetDesc, "WTHRESH == 0, writing back descriptor\n");
|
||||||
|
@ -1083,6 +1232,22 @@ IGbE::TxDescCache::serialize(std::ostream &os)
|
||||||
SERIALIZE_SCALAR(isTcp);
|
SERIALIZE_SCALAR(isTcp);
|
||||||
SERIALIZE_SCALAR(pktWaiting);
|
SERIALIZE_SCALAR(pktWaiting);
|
||||||
SERIALIZE_SCALAR(pktMultiDesc);
|
SERIALIZE_SCALAR(pktMultiDesc);
|
||||||
|
|
||||||
|
SERIALIZE_SCALAR(useTso);
|
||||||
|
SERIALIZE_SCALAR(tsoHeaderLen);
|
||||||
|
SERIALIZE_SCALAR(tsoMss);
|
||||||
|
SERIALIZE_SCALAR(tsoTotalLen);
|
||||||
|
SERIALIZE_SCALAR(tsoUsedLen);
|
||||||
|
SERIALIZE_SCALAR(tsoPrevSeq);;
|
||||||
|
SERIALIZE_SCALAR(tsoPktPayloadBytes);
|
||||||
|
SERIALIZE_SCALAR(tsoLoadedHeader);
|
||||||
|
SERIALIZE_SCALAR(tsoPktHasHeader);
|
||||||
|
SERIALIZE_ARRAY(tsoHeader, 256);
|
||||||
|
SERIALIZE_SCALAR(tsoDescBytesUsed);
|
||||||
|
SERIALIZE_SCALAR(tsoCopyBytes);
|
||||||
|
SERIALIZE_SCALAR(tsoPkts);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1093,6 +1258,20 @@ IGbE::TxDescCache::unserialize(Checkpoint *cp, const std::string §ion)
|
||||||
UNSERIALIZE_SCALAR(isTcp);
|
UNSERIALIZE_SCALAR(isTcp);
|
||||||
UNSERIALIZE_SCALAR(pktWaiting);
|
UNSERIALIZE_SCALAR(pktWaiting);
|
||||||
UNSERIALIZE_SCALAR(pktMultiDesc);
|
UNSERIALIZE_SCALAR(pktMultiDesc);
|
||||||
|
|
||||||
|
UNSERIALIZE_SCALAR(useTso);
|
||||||
|
UNSERIALIZE_SCALAR(tsoHeaderLen);
|
||||||
|
UNSERIALIZE_SCALAR(tsoMss);
|
||||||
|
UNSERIALIZE_SCALAR(tsoTotalLen);
|
||||||
|
UNSERIALIZE_SCALAR(tsoUsedLen);
|
||||||
|
UNSERIALIZE_SCALAR(tsoPrevSeq);;
|
||||||
|
UNSERIALIZE_SCALAR(tsoPktPayloadBytes);
|
||||||
|
UNSERIALIZE_SCALAR(tsoLoadedHeader);
|
||||||
|
UNSERIALIZE_SCALAR(tsoPktHasHeader);
|
||||||
|
UNSERIALIZE_ARRAY(tsoHeader, 256);
|
||||||
|
UNSERIALIZE_SCALAR(tsoDescBytesUsed);
|
||||||
|
UNSERIALIZE_SCALAR(tsoCopyBytes);
|
||||||
|
UNSERIALIZE_SCALAR(tsoPkts);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -1242,8 +1421,15 @@ IGbE::txStateMachine()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
txDescCache.processContextDesc();
|
||||||
|
if (txDescCache.packetWaiting()) {
|
||||||
|
DPRINTF(EthernetSM, "TXS: Fetching TSO header, stopping ticking\n");
|
||||||
|
txTick = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int size;
|
int size;
|
||||||
size = txDescCache.getPacketSize();
|
size = txDescCache.getPacketSize(txPacket);
|
||||||
if (size > 0 && txFifo.avail() > size) {
|
if (size > 0 && txFifo.avail() > size) {
|
||||||
DPRINTF(EthernetSM, "TXS: Reserving %d bytes in FIFO and begining "
|
DPRINTF(EthernetSM, "TXS: Reserving %d bytes in FIFO and begining "
|
||||||
"DMA of next packet\n", size);
|
"DMA of next packet\n", size);
|
||||||
|
|
|
@ -462,8 +462,8 @@ class IGbE : public EtherDevice
|
||||||
int descLeft() const
|
int descLeft() const
|
||||||
{
|
{
|
||||||
int left = unusedCache.size();
|
int left = unusedCache.size();
|
||||||
if (cachePnt - descTail() >= 0)
|
if (cachePnt >= descTail())
|
||||||
left += (cachePnt - descTail());
|
left += (descLen() - cachePnt + descTail());
|
||||||
else
|
else
|
||||||
left += (descTail() - cachePnt);
|
left += (descTail() - cachePnt);
|
||||||
|
|
||||||
|
@ -636,6 +636,21 @@ class IGbE : public EtherDevice
|
||||||
bool pktWaiting;
|
bool pktWaiting;
|
||||||
bool pktMultiDesc;
|
bool pktMultiDesc;
|
||||||
|
|
||||||
|
// tso variables
|
||||||
|
bool useTso;
|
||||||
|
Addr tsoHeaderLen;
|
||||||
|
Addr tsoMss;
|
||||||
|
Addr tsoTotalLen;
|
||||||
|
Addr tsoUsedLen;
|
||||||
|
Addr tsoPrevSeq;;
|
||||||
|
Addr tsoPktPayloadBytes;
|
||||||
|
bool tsoLoadedHeader;
|
||||||
|
bool tsoPktHasHeader;
|
||||||
|
uint8_t tsoHeader[256];
|
||||||
|
Addr tsoDescBytesUsed;
|
||||||
|
Addr tsoCopyBytes;
|
||||||
|
int tsoPkts;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TxDescCache(IGbE *i, std::string n, int s);
|
TxDescCache(IGbE *i, std::string n, int s);
|
||||||
|
|
||||||
|
@ -643,8 +658,9 @@ class IGbE : public EtherDevice
|
||||||
* return the size the of the packet to reserve space in tx fifo.
|
* return the size the of the packet to reserve space in tx fifo.
|
||||||
* @return size of the packet
|
* @return size of the packet
|
||||||
*/
|
*/
|
||||||
int getPacketSize();
|
int getPacketSize(EthPacketPtr p);
|
||||||
void getPacketData(EthPacketPtr p);
|
void getPacketData(EthPacketPtr p);
|
||||||
|
void processContextDesc();
|
||||||
|
|
||||||
/** Ask if the packet has been transfered so the state machine can give
|
/** Ask if the packet has been transfered so the state machine can give
|
||||||
* it to the fifo.
|
* it to the fifo.
|
||||||
|
@ -670,6 +686,9 @@ class IGbE : public EtherDevice
|
||||||
void pktComplete();
|
void pktComplete();
|
||||||
EventWrapper<TxDescCache, &TxDescCache::pktComplete> pktEvent;
|
EventWrapper<TxDescCache, &TxDescCache::pktComplete> pktEvent;
|
||||||
|
|
||||||
|
void headerComplete();
|
||||||
|
EventWrapper<TxDescCache, &TxDescCache::headerComplete> headerEvent;
|
||||||
|
|
||||||
virtual bool hasOutstandingEvents();
|
virtual bool hasOutstandingEvents();
|
||||||
|
|
||||||
virtual void serialize(std::ostream &os);
|
virtual void serialize(std::ostream &os);
|
||||||
|
|
|
@ -200,6 +200,7 @@ int ipcso(TxDesc *d) { assert(isContext(d)); return bits(d->d1,15,8); }
|
||||||
int ipcss(TxDesc *d) { assert(isContext(d)); return bits(d->d1,7,0); }
|
int ipcss(TxDesc *d) { assert(isContext(d)); return bits(d->d1,7,0); }
|
||||||
int mss(TxDesc *d) { assert(isContext(d)); return bits(d->d2,63,48); }
|
int mss(TxDesc *d) { assert(isContext(d)); return bits(d->d2,63,48); }
|
||||||
int hdrlen(TxDesc *d) { assert(isContext(d)); return bits(d->d2,47,40); }
|
int hdrlen(TxDesc *d) { assert(isContext(d)); return bits(d->d2,47,40); }
|
||||||
|
int utcmd(TxDesc *d) { assert(isContext(d)); return bits(d->d2,24,31); }
|
||||||
} // namespace TxdOp
|
} // namespace TxdOp
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue