Recompute L4 checksum on-the-fly for TTag packets
This commit is contained in:
parent
896371b987
commit
b2ad3c5d08
@ -90,6 +90,8 @@ public:
|
|||||||
static bool packetGuid(const uchar *pkt, int pktLen, uint *guid);
|
static bool packetGuid(const uchar *pkt, int pktLen, uint *guid);
|
||||||
static bool packetTtagId(const uchar *pkt, int pktLen, uint *ttagId, uint *guid);
|
static bool packetTtagId(const uchar *pkt, int pktLen, uint *ttagId, uint *guid);
|
||||||
|
|
||||||
|
// XXX: Any change in kTypeLenXXX or magic value should also be done in
|
||||||
|
// TxThread/Ttag code as well where hardcoded values are used
|
||||||
static const quint32 kMaxGuid = 0x00ffffff;
|
static const quint32 kMaxGuid = 0x00ffffff;
|
||||||
static const quint32 kInvalidGuid = UINT_MAX;
|
static const quint32 kInvalidGuid = UINT_MAX;
|
||||||
static const quint8 kTypeLenTtagPlaceholder = 0x22;
|
static const quint8 kTypeLenTtagPlaceholder = 0x22;
|
||||||
|
@ -438,14 +438,35 @@ int PcapTxThread::sendQueueTransmit(pcap_t *p, PacketSequence *seq,
|
|||||||
if (seq->ttagPktInterval_
|
if (seq->ttagPktInterval_
|
||||||
&& ((stats_->pkts % seq->ttagPktInterval_) == 0)) {
|
&& ((stats_->pkts % seq->ttagPktInterval_) == 0)) {
|
||||||
ttagPkt = true;
|
ttagPkt = true;
|
||||||
|
// XXX: write 2xBytes instead of 1xHalf-word to avoid
|
||||||
|
// potential alignment problem
|
||||||
*(pkt+pktLen-5) = SignProtocol::kTypeLenTtag;
|
*(pkt+pktLen-5) = SignProtocol::kTypeLenTtag;
|
||||||
*(pkt+pktLen-6) = ttagId_++;
|
*(pkt+pktLen-6) = ttagId_;
|
||||||
|
|
||||||
|
// Recalc L4 checksum; use incremental checksum as per RFC 1624
|
||||||
|
// HC' = ~(~HC + ~m + m')
|
||||||
if (seq->ttagL4CksumOffset_) {
|
if (seq->ttagL4CksumOffset_) {
|
||||||
quint16 *cksum = reinterpret_cast<quint16*>(
|
quint16 *cksum = reinterpret_cast<quint16*>(
|
||||||
pkt + seq->ttagL4CksumOffset_);
|
pkt + seq->ttagL4CksumOffset_);
|
||||||
origCksum = *cksum;
|
origCksum = ntohs(*cksum);
|
||||||
*cksum = 0x0000; // FIXME: recalc cksum
|
// XXX: SignProtocol trailer
|
||||||
|
// ... | <guid> | 0x61 | 0x00 | 0x22 | 0x1d10c0da
|
||||||
|
// ... | <guid> | 0x61 | <TtagId> | 0x23 | 0x1d10c0da
|
||||||
|
// For odd pkt Length, Ttag spans across 2 half-words
|
||||||
|
// XXX: Hardcoded values instead of sign protocol constants
|
||||||
|
// used below for readability
|
||||||
|
quint32 newCksum = pktLen & 1 ?
|
||||||
|
quint16(~origCksum) + quint16(~0x221d) + 0x231d
|
||||||
|
+ quint16(~0x6100) + (0x6100 | ttagId_) :
|
||||||
|
quint16(~origCksum) + quint16(~0x0022) + (ttagId_ << 8 | 0x23);
|
||||||
|
while (newCksum > 0xffff)
|
||||||
|
newCksum = (newCksum & 0xffff) + (newCksum >> 16);
|
||||||
|
// XXX: For IPv4/UDP, if ~newcksum is 0x0000 we are supposed to
|
||||||
|
// set the checksum as 0xffff since 0x0000 indicates no cksum
|
||||||
|
// is present - we choose not to do this to avoid extra cost
|
||||||
|
*cksum = htons(~newCksum);
|
||||||
}
|
}
|
||||||
|
ttagId_++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sync) {
|
if (sync) {
|
||||||
@ -479,7 +500,7 @@ int PcapTxThread::sendQueueTransmit(pcap_t *p, PacketSequence *seq,
|
|||||||
if (seq->ttagL4CksumOffset_) {
|
if (seq->ttagL4CksumOffset_) {
|
||||||
quint16 *cksum = reinterpret_cast<quint16*>(
|
quint16 *cksum = reinterpret_cast<quint16*>(
|
||||||
pkt + seq->ttagL4CksumOffset_);
|
pkt + seq->ttagL4CksumOffset_);
|
||||||
*cksum = origCksum;
|
*cksum = htons(origCksum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user