From bfdcee2baae88dff5ffebbfca7096bdc62596763 Mon Sep 17 00:00:00 2001 From: Srivats P Date: Wed, 12 Apr 2023 15:47:55 +0530 Subject: [PATCH] Recompute L4 checksum on-the-fly for TTag packets --- common/sign.h | 2 ++ server/pcaptxthread.cpp | 29 +++++++++++++++++++++++++---- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/common/sign.h b/common/sign.h index b3fe00e..cdfdbd8 100644 --- a/common/sign.h +++ b/common/sign.h @@ -90,6 +90,8 @@ public: static bool packetGuid(const uchar *pkt, int pktLen, 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 kInvalidGuid = UINT_MAX; static const quint8 kTypeLenTtagPlaceholder = 0x22; diff --git a/server/pcaptxthread.cpp b/server/pcaptxthread.cpp index 0dd8719..340fda5 100644 --- a/server/pcaptxthread.cpp +++ b/server/pcaptxthread.cpp @@ -438,14 +438,35 @@ int PcapTxThread::sendQueueTransmit(pcap_t *p, PacketSequence *seq, if (seq->ttagPktInterval_ && ((stats_->pkts % seq->ttagPktInterval_) == 0)) { ttagPkt = true; + // XXX: write 2xBytes instead of 1xHalf-word to avoid + // potential alignment problem *(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_) { quint16 *cksum = reinterpret_cast( pkt + seq->ttagL4CksumOffset_); - origCksum = *cksum; - *cksum = 0x0000; // FIXME: recalc cksum + origCksum = ntohs(*cksum); + // XXX: SignProtocol trailer + // ... | | 0x61 | 0x00 | 0x22 | 0x1d10c0da + // ... | | 0x61 | | 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) { @@ -479,7 +500,7 @@ int PcapTxThread::sendQueueTransmit(pcap_t *p, PacketSequence *seq, if (seq->ttagL4CksumOffset_) { quint16 *cksum = reinterpret_cast( pkt + seq->ttagL4CksumOffset_); - *cksum = origCksum; + *cksum = htons(origCksum); } }