diff --git a/src/link_prober/IcmpPayload.h b/src/link_prober/IcmpPayload.h index 7a269897..738e65b4 100644 --- a/src/link_prober/IcmpPayload.h +++ b/src/link_prober/IcmpPayload.h @@ -48,9 +48,8 @@ namespace link_prober *@brief Supported TLV types */ enum TlvType: uint8_t { - TLV_COMMAND = 1, - TLV_SENTINEL = 0x0f, - TLV_COUNT + TLV_COMMAND = 0x5, + TLV_SENTINEL = 0xff, }; #define TlvHead \ diff --git a/src/link_prober/LinkProber.cpp b/src/link_prober/LinkProber.cpp index c44e6d3a..7e265087 100644 --- a/src/link_prober/LinkProber.cpp +++ b/src/link_prober/LinkProber.cpp @@ -232,18 +232,23 @@ void LinkProber::handleUpdateEthernetFrame() // void LinkProber::handleSendSwitchCommand() { - new (mTxBuffer.data() + sizeof(ether_header) + sizeof(iphdr) + sizeof(icmphdr) + sizeof(IcmpPayload)) TlvCommand(); - new (mTxBuffer.data() + sizeof(ether_header) + sizeof(iphdr) + sizeof(icmphdr) + sizeof(IcmpPayload) + sizeof(TlvCommand)) TlvSentinel(); + new (mTxBuffer.data() + mPacketHeaderSize + sizeof(IcmpPayload)) TlvCommand(); + new (mTxBuffer.data() + mPacketHeaderSize + sizeof(IcmpPayload) + sizeof(TlvCommand)) TlvSentinel(); + size_t totalPayloadSize = sizeof(IcmpPayload) + sizeof(TlvCommand) + sizeof(TlvSentinel); + iphdr *ipHeader = reinterpret_cast (mTxBuffer.data() + sizeof(ether_header)); icmphdr *icmpHeader = reinterpret_cast (mTxBuffer.data() + sizeof(ether_header) + sizeof(iphdr)); - computeChecksum(icmpHeader, sizeof(icmphdr) + sizeof(IcmpPayload) + sizeof(TlvCommand) + sizeof(TlvSentinel)); - mTxPacketSize = sizeof(ether_header) + sizeof(iphdr) + sizeof(icmphdr) + sizeof(IcmpPayload) + sizeof(TlvCommand) + sizeof(TlvSentinel); + computeChecksum(icmpHeader, sizeof(icmphdr) + totalPayloadSize); + mTxPacketSize = mPacketHeaderSize + totalPayloadSize; + ipHeader->tot_len = htons(sizeof(iphdr) + sizeof(icmphdr) + totalPayloadSize); sendHeartbeat(); - new (mTxBuffer.data() + sizeof(ether_header) + sizeof(iphdr) + sizeof(icmphdr) + sizeof(IcmpPayload)) TlvSentinel(); - computeChecksum(icmpHeader, sizeof(icmphdr) + sizeof(IcmpPayload) + sizeof(TlvSentinel)); - mTxPacketSize = sizeof(ether_header) + sizeof(iphdr) + sizeof(icmphdr) + sizeof(IcmpPayload) + sizeof(TlvSentinel); + new (mTxBuffer.data() + mPacketHeaderSize + sizeof(IcmpPayload)) TlvSentinel(); + totalPayloadSize = sizeof(IcmpPayload) + sizeof(TlvSentinel); + computeChecksum(icmpHeader, sizeof(icmphdr) + totalPayloadSize); + mTxPacketSize = mPacketHeaderSize + totalPayloadSize; + ipHeader->tot_len = htons(sizeof(iphdr) + sizeof(icmphdr) + totalPayloadSize); // inform the composite state machine about commend send completion boost::asio::io_service::strand &strand = mLinkProberStateMachine.getStrand(); @@ -279,6 +284,31 @@ void LinkProber::sendHeartbeat() } } +// +// ---> handleTlvCommandRecv(size_t offset, bool isPeer); +// +// handle packet reception +// +void LinkProber::handleTlvCommandRecv( + size_t offset, + bool isPeer +) +{ + TlvCommand *tlvCommand = reinterpret_cast (mTxBuffer.data() + offset); + if (isPeer) { + if (tlvCommand->command == static_cast (Command::COMMAND_SWITCH_ACTIVE)) { + boost::asio::io_service::strand &strand = mLinkProberStateMachine.getStrand(); + boost::asio::io_service &ioService = strand.context(); + ioService.post(strand.wrap(boost::bind( + static_cast + (&LinkProberStateMachine::processEvent), + &mLinkProberStateMachine, + LinkProberStateMachine::getSwitchActiveRequestEvent() + ))); + } + } +} + // // ---> handleRecv(const boost::system::error_code& errorCode, size_t bytesTransferred); // @@ -298,7 +328,7 @@ void LinkProber::handleRecv( ); IcmpPayload *icmpPayload = reinterpret_cast ( - mRxBuffer.data() + sizeof(ether_header) + sizeof(iphdr) + sizeof(icmphdr) + mRxBuffer.data() + mPacketHeaderSize ); if (ntohl(icmpPayload->cookie) == IcmpPayload::getCookie() && @@ -308,7 +338,7 @@ void LinkProber::handleRecv( mMuxPortConfig.getPortName() % mMuxPortConfig.getBladeIpv4Address().to_string() ); - bool isMatch = memcmp(icmpPayload->uuid, IcmpPayload::getGuidData(), sizeof(icmpPayload->uuid)); + bool isMatch = memcmp(icmpPayload->uuid, IcmpPayload::getGuidData(), sizeof(icmpPayload->uuid)) == 0; if (isMatch) { MUXLOGTRACE(boost::format("%s: Matching Guid") % mMuxPortConfig.getPortName()); @@ -317,33 +347,23 @@ void LinkProber::handleRecv( mLinkProberStateMachine.postLinkProberStateEvent(LinkProberStateMachine::getIcmpSelfEvent()); } - uint8_t tlvStartOffset = sizeof(ether_header) + sizeof(iphdr) + sizeof(icmphdr) + sizeof(IcmpPayload); - while (tlvStartOffset + sizeof(Tlv) < MUX_MAX_ICMP_BUFFER_SIZE) - { + uint8_t tlvStartOffset = mPacketHeaderSize + sizeof(IcmpPayload); + while (tlvStartOffset + sizeof(Tlv) < bytesTransferred) { Tlv *currentTlv = reinterpret_cast (mTxBuffer.data() + tlvStartOffset); - if (currentTlv->type == TlvType::TLV_COMMAND) { - TlvCommand *tlvCommand = reinterpret_cast (mTxBuffer.data() + tlvStartOffset); - if (!isMatch) { - if (tlvCommand->command == static_cast (Command::COMMAND_SWITCH_ACTIVE)) { - boost::asio::io_service::strand &strand = mLinkProberStateMachine.getStrand(); - boost::asio::io_service &ioService = strand.context(); - ioService.post(strand.wrap(boost::bind( - static_cast - (&LinkProberStateMachine::processEvent), - &mLinkProberStateMachine, - LinkProberStateMachine::getSwitchActiveRequestEvent() - ))); - } - } - tlvStartOffset += sizeof(TlvCommand); - } else if (currentTlv->type == TlvType::TLV_SENTINEL) { - // sentinel TLV, stop processing - break; - } else { - // unknown TLV type, ignore - break; + size_t currentTlvLength = ntohs(currentTlv->length); + switch (currentTlv->type) { + case TlvType::TLV_COMMAND: + handleTlvCommandRecv(tlvStartOffset, !isMatch); + break; + case TlvType::TLV_SENTINEL: + // sentinel TLV, stop processing + break; + default: + // unknonw TLV, try to skip + if (currentTlvLength == 0) + break; + tlvStartOffset += sizeof(Tlv) + currentTlvLength; } - } } else { // Unknown ICMP packet, ignore. @@ -563,9 +583,9 @@ void LinkProber::initializeSendBuffer() iphdr *ipHeader = reinterpret_cast (mTxBuffer.data() + sizeof(ether_header)); icmphdr *icmpHeader = reinterpret_cast (mTxBuffer.data() + sizeof(ether_header) + sizeof(iphdr)); - IcmpPayload *icmpPayload = new (mTxBuffer.data() + sizeof(ether_header) + sizeof(iphdr) + sizeof(icmphdr)) IcmpPayload(); - TlvSentinel *tlvSentinel = new (mTxBuffer.data() + sizeof(ether_header) + sizeof(iphdr) + sizeof(icmphdr) + sizeof(IcmpPayload)) TlvSentinel(); - mTxPacketSize = sizeof(ether_header) + sizeof(iphdr) + sizeof(icmphdr) + sizeof(IcmpPayload) + sizeof(TlvSentinel); + IcmpPayload *icmpPayload = new (mTxBuffer.data() + mPacketHeaderSize) IcmpPayload(); + TlvSentinel *tlvSentinel = new (mTxBuffer.data() + mPacketHeaderSize + sizeof(IcmpPayload)) TlvSentinel(); + mTxPacketSize = mPacketHeaderSize + sizeof(IcmpPayload) + sizeof(TlvSentinel); ipHeader->ihl = sizeof(iphdr) >> 2; ipHeader->version = IPVERSION; diff --git a/src/link_prober/LinkProber.h b/src/link_prober/LinkProber.h index a4a30e3f..d372749d 100644 --- a/src/link_prober/LinkProber.h +++ b/src/link_prober/LinkProber.h @@ -188,6 +188,21 @@ class LinkProber */ void sendHeartbeat(); + /** + *@method handleTlvCommandRecv + * + *@brief handle TLV command + * + *@param offset (in) start offset for TlvCommand struct in mRxBuffer + *@param isPeer (in) True if the reply received is from the peer ToR + * + *@return none + */ + void handleTlvCommandRecv( + size_t offset, + bool isPeer + ); + /** *@method handleRecv * @@ -359,6 +374,8 @@ class LinkProber uint32_t mIcmpChecksum = 0; uint32_t mIpChecksum = 0; + static const size_t mPacketHeaderSize = sizeof(ether_header) + sizeof(iphdr) + sizeof(icmphdr); + boost::asio::io_service::strand mStrand; boost::asio::deadline_timer mDeadlineTimer; boost::asio::deadline_timer mSuspendTimer; diff --git a/test/LinkProberTest.cpp b/test/LinkProberTest.cpp index 778475e9..a3d666ed 100644 --- a/test/LinkProberTest.cpp +++ b/test/LinkProberTest.cpp @@ -105,7 +105,7 @@ TEST_F(LinkProberTest, CalculateChecksum) initializeSendBuffer(); icmphdr *icmpHeader = reinterpret_cast (getTxBuffer().data() + sizeof(ether_header) + sizeof(iphdr)); - EXPECT_TRUE(icmpHeader->checksum == 12339); + EXPECT_TRUE(icmpHeader->checksum == 12099); } TEST_F(LinkProberTest, UpdateEthernetFrame) @@ -118,7 +118,7 @@ TEST_F(LinkProberTest, UpdateEthernetFrame) handleUpdateEthernetFrame(); icmphdr *icmpHeader = reinterpret_cast (getTxBuffer().data() + sizeof(ether_header) + sizeof(iphdr)); - EXPECT_TRUE(icmpHeader->checksum == 12339); + EXPECT_TRUE(icmpHeader->checksum == 12099); } TEST_F(LinkProberTest, UpdateSequenceNo) @@ -136,7 +136,7 @@ TEST_F(LinkProberTest, UpdateSequenceNo) handleUpdateSequenceNumber(); icmphdr *icmpHeader = reinterpret_cast (getTxBuffer().data() + sizeof(ether_header) + sizeof(iphdr)); - EXPECT_TRUE(icmpHeader->checksum == 12083); + EXPECT_TRUE(icmpHeader->checksum == 11843); EXPECT_TRUE(getRxSelfSeqNo() + 1 == ntohs(icmpHeader->un.echo.sequence)); EXPECT_TRUE(getRxPeerSeqNo() + 1 == ntohs(icmpHeader->un.echo.sequence));