mirror of
https://github.com/mfontanini/libtins
synced 2026-01-23 02:35:57 +01:00
Allow asking whether segment was acked
This commit is contained in:
@@ -129,6 +129,14 @@ public:
|
|||||||
* \brief Retrieves all acked intervals by Selective ACKs
|
* \brief Retrieves all acked intervals by Selective ACKs
|
||||||
*/
|
*/
|
||||||
const interval_set_type& acked_intervals() const;
|
const interval_set_type& acked_intervals() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Indicates whether the given segment has been already ACKed
|
||||||
|
*
|
||||||
|
* \param sequence_number The segment's sequence number
|
||||||
|
* \param length The segment's length
|
||||||
|
*/
|
||||||
|
bool is_segment_acked(uint32_t sequence_number, uint32_t length) const;
|
||||||
private:
|
private:
|
||||||
void process_sack(const std::vector<uint32_t>& sack);
|
void process_sack(const std::vector<uint32_t>& sack);
|
||||||
void cleanup_sacked_intervals(uint32_t old_ack, uint32_t new_ack);
|
void cleanup_sacked_intervals(uint32_t old_ack, uint32_t new_ack);
|
||||||
|
|||||||
@@ -282,6 +282,18 @@ public:
|
|||||||
* \brief Indicates whether ACK number tracking is enabled
|
* \brief Indicates whether ACK number tracking is enabled
|
||||||
*/
|
*/
|
||||||
bool ack_tracking_enabled() const;
|
bool ack_tracking_enabled() const;
|
||||||
|
|
||||||
|
#ifdef HAVE_ACK_TRACKER
|
||||||
|
/**
|
||||||
|
* Retrieves the ACK tracker for this Flow (const)
|
||||||
|
*/
|
||||||
|
const AckTracker& ack_tracker() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the ACK tracker for this Flow
|
||||||
|
*/
|
||||||
|
AckTracker& ack_tracker();
|
||||||
|
#endif // HAVE_ACK_TRACKER
|
||||||
private:
|
private:
|
||||||
// Compress all flags into just one struct using bitfields
|
// Compress all flags into just one struct using bitfields
|
||||||
struct flags {
|
struct flags {
|
||||||
|
|||||||
@@ -38,11 +38,23 @@
|
|||||||
using std::vector;
|
using std::vector;
|
||||||
using std::numeric_limits;
|
using std::numeric_limits;
|
||||||
|
|
||||||
|
using boost::icl::interval_bounds;
|
||||||
|
using boost::icl::contains;
|
||||||
|
|
||||||
using Tins::Internals::seq_compare;
|
using Tins::Internals::seq_compare;
|
||||||
|
|
||||||
namespace Tins {
|
namespace Tins {
|
||||||
namespace TCPIP {
|
namespace TCPIP {
|
||||||
|
|
||||||
|
uint32_t interval_end(const AckedRange::interval_type& interval) {
|
||||||
|
if (interval.bounds() == interval_bounds::right_open()) {
|
||||||
|
return interval.upper() - 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return interval.upper();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// AckedRange
|
// AckedRange
|
||||||
|
|
||||||
AckedRange::AckedRange(uint32_t first, uint32_t last)
|
AckedRange::AckedRange(uint32_t first, uint32_t last)
|
||||||
@@ -140,6 +152,22 @@ const AckTracker::interval_set_type& AckTracker::acked_intervals() const {
|
|||||||
return acked_intervals_;
|
return acked_intervals_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AckTracker::is_segment_acked(uint32_t sequence_number, uint32_t length) const {
|
||||||
|
if (length == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
AckedRange range(sequence_number, sequence_number + length - 1);
|
||||||
|
while (range.has_next()) {
|
||||||
|
AckedRange::interval_type interval = range.next();
|
||||||
|
const int comparison = seq_compare(interval_end(interval), ack_number_);
|
||||||
|
// Only check for SACKed intervals if the segment finishes after our ACK number
|
||||||
|
if (comparison >= 0 && !contains(acked_intervals_, interval)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // TCPIP
|
} // TCPIP
|
||||||
} // Tins
|
} // Tins
|
||||||
|
|
||||||
|
|||||||
@@ -319,6 +319,17 @@ bool Flow::ack_tracking_enabled() const {
|
|||||||
return flags_.ack_tracking;
|
return flags_.ack_tracking;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_ACK_TRACKER
|
||||||
|
const AckTracker& Flow::ack_tracker() const {
|
||||||
|
return ack_tracker_;
|
||||||
|
}
|
||||||
|
|
||||||
|
AckTracker& Flow::ack_tracker() {
|
||||||
|
return ack_tracker_;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // HAVE_ACK_TRACKER
|
||||||
|
|
||||||
} // TCPIP
|
} // TCPIP
|
||||||
} // Tins
|
} // Tins
|
||||||
|
|
||||||
|
|||||||
@@ -601,9 +601,14 @@ TEST_F(AckTrackerTest, AckedRange_WrapAround) {
|
|||||||
|
|
||||||
TEST_F(AckTrackerTest, AckingTcp1) {
|
TEST_F(AckTrackerTest, AckingTcp1) {
|
||||||
AckTracker tracker(0, false);
|
AckTracker tracker(0, false);
|
||||||
EXPECT_EQ(0, tracker.ack_number());
|
EXPECT_EQ(0, tracker.ack_number());
|
||||||
tracker.process_packet(make_tcp_ack(100));
|
tracker.process_packet(make_tcp_ack(100));
|
||||||
EXPECT_EQ(100, tracker.ack_number());
|
EXPECT_EQ(100, tracker.ack_number());
|
||||||
|
EXPECT_TRUE(tracker.is_segment_acked(0, 10));
|
||||||
|
EXPECT_TRUE(tracker.is_segment_acked(50, 10));
|
||||||
|
EXPECT_TRUE(tracker.is_segment_acked(99, 1));
|
||||||
|
EXPECT_FALSE(tracker.is_segment_acked(90, 20));
|
||||||
|
EXPECT_FALSE(tracker.is_segment_acked(99, 2));
|
||||||
tracker.process_packet(make_tcp_ack(50));
|
tracker.process_packet(make_tcp_ack(50));
|
||||||
EXPECT_EQ(100, tracker.ack_number());
|
EXPECT_EQ(100, tracker.ack_number());
|
||||||
tracker.process_packet(make_tcp_ack(150));
|
tracker.process_packet(make_tcp_ack(150));
|
||||||
@@ -635,6 +640,9 @@ TEST_F(AckTrackerTest, AckingTcp_Sack1) {
|
|||||||
AckTracker tracker(0, true);
|
AckTracker tracker(0, true);
|
||||||
tracker.process_packet(make_tcp_ack(0, make_pair(2, 5), make_pair(9, 11)));
|
tracker.process_packet(make_tcp_ack(0, make_pair(2, 5), make_pair(9, 11)));
|
||||||
EXPECT_EQ(3 + 2, tracker.acked_intervals().size());
|
EXPECT_EQ(3 + 2, tracker.acked_intervals().size());
|
||||||
|
EXPECT_TRUE(tracker.is_segment_acked(2, 3));
|
||||||
|
EXPECT_TRUE(tracker.is_segment_acked(9, 2));
|
||||||
|
EXPECT_FALSE(tracker.is_segment_acked(2, 9));
|
||||||
|
|
||||||
tracker.process_packet(make_tcp_ack(9));
|
tracker.process_packet(make_tcp_ack(9));
|
||||||
EXPECT_EQ(1, tracker.acked_intervals().size());
|
EXPECT_EQ(1, tracker.acked_intervals().size());
|
||||||
@@ -652,6 +660,10 @@ TEST_F(AckTrackerTest, AckingTcp_Sack2) {
|
|||||||
make_pair(0, 10)
|
make_pair(0, 10)
|
||||||
));
|
));
|
||||||
EXPECT_EQ(3 + 10, tracker.acked_intervals().size());
|
EXPECT_EQ(3 + 10, tracker.acked_intervals().size());
|
||||||
|
EXPECT_TRUE(tracker.is_segment_acked(maximum - 12, 2));
|
||||||
|
EXPECT_TRUE(tracker.is_segment_acked(maximum - 2, 1));
|
||||||
|
EXPECT_TRUE(tracker.is_segment_acked(2, 3));
|
||||||
|
EXPECT_FALSE(tracker.is_segment_acked(maximum - 10, 10));
|
||||||
|
|
||||||
tracker.process_packet(make_tcp_ack(maximum - 2));
|
tracker.process_packet(make_tcp_ack(maximum - 2));
|
||||||
EXPECT_EQ(1 + 10, tracker.acked_intervals().size());
|
EXPECT_EQ(1 + 10, tracker.acked_intervals().size());
|
||||||
|
|||||||
Reference in New Issue
Block a user