|
@@ -153,18 +153,27 @@ static inline u64 max48(const u64 seq1, const u64 seq2)
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * dccp_loss_free - Evaluates condition for data loss from RFC 4340, 7.7.1
|
|
|
- * @s1: start sequence number
|
|
|
- * @s2: end sequence number
|
|
|
+ * dccp_loss_count - Approximate the number of lost data packets in a burst loss
|
|
|
+ * @s1: last known sequence number before the loss ('hole')
|
|
|
+ * @s2: first sequence number seen after the 'hole'
|
|
|
* @ndp: NDP count on packet with sequence number @s2
|
|
|
- * Returns true if the sequence range s1...s2 has no data loss.
|
|
|
*/
|
|
|
-static inline bool dccp_loss_free(const u64 s1, const u64 s2, const u64 ndp)
|
|
|
+static inline u64 dccp_loss_count(const u64 s1, const u64 s2, const u64 ndp)
|
|
|
{
|
|
|
s64 delta = dccp_delta_seqno(s1, s2);
|
|
|
|
|
|
WARN_ON(delta < 0);
|
|
|
- return (u64)delta <= ndp + 1;
|
|
|
+ delta -= ndp + 1;
|
|
|
+
|
|
|
+ return delta > 0 ? delta : 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * dccp_loss_free - Evaluate condition for data loss from RFC 4340, 7.7.1
|
|
|
+ */
|
|
|
+static inline bool dccp_loss_free(const u64 s1, const u64 s2, const u64 ndp)
|
|
|
+{
|
|
|
+ return dccp_loss_count(s1, s2, ndp) == 0;
|
|
|
}
|
|
|
|
|
|
enum {
|
|
@@ -414,6 +423,23 @@ static inline void dccp_update_gsr(struct sock *sk, u64 seq)
|
|
|
dp->dccps_gsr = seq;
|
|
|
/* Sequence validity window depends on remote Sequence Window (7.5.1) */
|
|
|
dp->dccps_swl = SUB48(ADD48(dp->dccps_gsr, 1), dp->dccps_r_seq_win / 4);
|
|
|
+ /*
|
|
|
+ * Adjust SWL so that it is not below ISR. In contrast to RFC 4340,
|
|
|
+ * 7.5.1 we perform this check beyond the initial handshake: W/W' are
|
|
|
+ * always > 32, so for the first W/W' packets in the lifetime of a
|
|
|
+ * connection we always have to adjust SWL.
|
|
|
+ * A second reason why we are doing this is that the window depends on
|
|
|
+ * the feature-remote value of Sequence Window: nothing stops the peer
|
|
|
+ * from updating this value while we are busy adjusting SWL for the
|
|
|
+ * first W packets (we would have to count from scratch again then).
|
|
|
+ * Therefore it is safer to always make sure that the Sequence Window
|
|
|
+ * is not artificially extended by a peer who grows SWL downwards by
|
|
|
+ * continually updating the feature-remote Sequence-Window.
|
|
|
+ * If sequence numbers wrap it is bad luck. But that will take a while
|
|
|
+ * (48 bit), and this measure prevents Sequence-number attacks.
|
|
|
+ */
|
|
|
+ if (before48(dp->dccps_swl, dp->dccps_isr))
|
|
|
+ dp->dccps_swl = dp->dccps_isr;
|
|
|
dp->dccps_swh = ADD48(dp->dccps_gsr, (3 * dp->dccps_r_seq_win) / 4);
|
|
|
}
|
|
|
|
|
@@ -424,14 +450,16 @@ static inline void dccp_update_gss(struct sock *sk, u64 seq)
|
|
|
dp->dccps_gss = seq;
|
|
|
/* Ack validity window depends on local Sequence Window value (7.5.1) */
|
|
|
dp->dccps_awl = SUB48(ADD48(dp->dccps_gss, 1), dp->dccps_l_seq_win);
|
|
|
+ /* Adjust AWL so that it is not below ISS - see comment above for SWL */
|
|
|
+ if (before48(dp->dccps_awl, dp->dccps_iss))
|
|
|
+ dp->dccps_awl = dp->dccps_iss;
|
|
|
dp->dccps_awh = dp->dccps_gss;
|
|
|
}
|
|
|
|
|
|
static inline int dccp_ack_pending(const struct sock *sk)
|
|
|
{
|
|
|
const struct dccp_sock *dp = dccp_sk(sk);
|
|
|
- return dp->dccps_timestamp_echo != 0 ||
|
|
|
- (dp->dccps_hc_rx_ackvec != NULL &&
|
|
|
+ return (dp->dccps_hc_rx_ackvec != NULL &&
|
|
|
dccp_ackvec_pending(dp->dccps_hc_rx_ackvec)) ||
|
|
|
inet_csk_ack_scheduled(sk);
|
|
|
}
|