|
@@ -733,23 +733,6 @@ struct tcp_skb_cb {
|
|
|
|
|
|
#define TCP_SKB_CB(__skb) ((struct tcp_skb_cb *)&((__skb)->cb[0]))
|
|
|
|
|
|
-/* RFC3168 : 6.1.1 SYN packets must not have ECT/ECN bits set
|
|
|
- *
|
|
|
- * If we receive a SYN packet with these bits set, it means a network is
|
|
|
- * playing bad games with TOS bits. In order to avoid possible false congestion
|
|
|
- * notifications, we disable TCP ECN negociation.
|
|
|
- */
|
|
|
-static inline void
|
|
|
-TCP_ECN_create_request(struct request_sock *req, const struct sk_buff *skb,
|
|
|
- struct net *net)
|
|
|
-{
|
|
|
- const struct tcphdr *th = tcp_hdr(skb);
|
|
|
-
|
|
|
- if (net->ipv4.sysctl_tcp_ecn && th->ece && th->cwr &&
|
|
|
- INET_ECN_is_not_ect(TCP_SKB_CB(skb)->ip_dsfield))
|
|
|
- inet_rsk(req)->ecn_ok = 1;
|
|
|
-}
|
|
|
-
|
|
|
/* Due to TSO, an SKB can be composed of multiple actual
|
|
|
* packets. To keep these tracked properly, we use this.
|
|
|
*/
|
|
@@ -791,7 +774,10 @@ enum tcp_ca_event {
|
|
|
#define TCP_CA_MAX 128
|
|
|
#define TCP_CA_BUF_MAX (TCP_CA_NAME_MAX*TCP_CA_MAX)
|
|
|
|
|
|
+/* Algorithm can be set on socket without CAP_NET_ADMIN privileges */
|
|
|
#define TCP_CONG_NON_RESTRICTED 0x1
|
|
|
+/* Requires ECN/ECT set on all packets */
|
|
|
+#define TCP_CONG_NEEDS_ECN 0x2
|
|
|
|
|
|
struct tcp_congestion_ops {
|
|
|
struct list_head list;
|
|
@@ -840,6 +826,13 @@ u32 tcp_reno_ssthresh(struct sock *sk);
|
|
|
void tcp_reno_cong_avoid(struct sock *sk, u32 ack, u32 acked);
|
|
|
extern struct tcp_congestion_ops tcp_reno;
|
|
|
|
|
|
+static inline bool tcp_ca_needs_ecn(const struct sock *sk)
|
|
|
+{
|
|
|
+ const struct inet_connection_sock *icsk = inet_csk(sk);
|
|
|
+
|
|
|
+ return icsk->icsk_ca_ops->flags & TCP_CONG_NEEDS_ECN;
|
|
|
+}
|
|
|
+
|
|
|
static inline void tcp_set_ca_state(struct sock *sk, const u8 ca_state)
|
|
|
{
|
|
|
struct inet_connection_sock *icsk = inet_csk(sk);
|
|
@@ -857,6 +850,40 @@ static inline void tcp_ca_event(struct sock *sk, const enum tcp_ca_event event)
|
|
|
icsk->icsk_ca_ops->cwnd_event(sk, event);
|
|
|
}
|
|
|
|
|
|
+/* RFC3168 : 6.1.1 SYN packets must not have ECT/ECN bits set
|
|
|
+ *
|
|
|
+ * If we receive a SYN packet with these bits set, it means a
|
|
|
+ * network is playing bad games with TOS bits. In order to
|
|
|
+ * avoid possible false congestion notifications, we disable
|
|
|
+ * TCP ECN negociation.
|
|
|
+ *
|
|
|
+ * Exception: tcp_ca wants ECN. This is required for DCTCP
|
|
|
+ * congestion control; it requires setting ECT on all packets,
|
|
|
+ * including SYN. We inverse the test in this case: If our
|
|
|
+ * local socket wants ECN, but peer only set ece/cwr (but not
|
|
|
+ * ECT in IP header) its probably a non-DCTCP aware sender.
|
|
|
+ */
|
|
|
+static inline void
|
|
|
+TCP_ECN_create_request(struct request_sock *req, const struct sk_buff *skb,
|
|
|
+ const struct sock *listen_sk)
|
|
|
+{
|
|
|
+ const struct tcphdr *th = tcp_hdr(skb);
|
|
|
+ const struct net *net = sock_net(listen_sk);
|
|
|
+ bool th_ecn = th->ece && th->cwr;
|
|
|
+ bool ect, need_ecn;
|
|
|
+
|
|
|
+ if (!th_ecn)
|
|
|
+ return;
|
|
|
+
|
|
|
+ ect = !INET_ECN_is_not_ect(TCP_SKB_CB(skb)->ip_dsfield);
|
|
|
+ need_ecn = tcp_ca_needs_ecn(listen_sk);
|
|
|
+
|
|
|
+ if (!ect && !need_ecn && net->ipv4.sysctl_tcp_ecn)
|
|
|
+ inet_rsk(req)->ecn_ok = 1;
|
|
|
+ else if (ect && need_ecn)
|
|
|
+ inet_rsk(req)->ecn_ok = 1;
|
|
|
+}
|
|
|
+
|
|
|
/* These functions determine how the current flow behaves in respect of SACK
|
|
|
* handling. SACK is negotiated with the peer, and therefore it can vary
|
|
|
* between different flows.
|