@@ -1058,6 +1058,14 @@ static inline int tcp_skb_mss(const struct sk_buff *skb)
return TCP_SKB_CB(skb)->tcp_gso_size;
}
+/* I wish gso_size would have a bit more sane initialization than
+ * something-or-zero which complicates things
+ */
+static inline int tcp_skb_seglen(const struct sk_buff *skb)
+{
+ return tcp_skb_pcount(skb) == 1 ? skb->len : tcp_skb_mss(skb);
+}
+
static inline bool tcp_skb_can_collapse_to(const struct sk_buff *skb)
{
return likely(!TCP_SKB_CB(skb)->eor);
@@ -1550,14 +1550,6 @@ static bool tcp_shifted_skb(struct sock *sk, struct sk_buff *prev,
return true;
}
-/* I wish gso_size would have a bit more sane initialization than
- * something-or-zero which complicates things
- */
-static int tcp_skb_seglen(const struct sk_buff *skb)
-{
- return tcp_skb_pcount(skb) == 1 ? skb->len : tcp_skb_mss(skb);
-}
-
/* Shifting pages past head area doesn't work */
static int skb_can_shift(const struct sk_buff *skb)
{
@@ -1033,10 +1033,19 @@ static unsigned int tcp_established_options(struct sock *sk, struct sk_buff *skb
if (unlikely(BPF_SOCK_OPS_TEST_FLAG(tp,
BPF_SOCK_OPS_WRITE_HDR_OPT_CB_FLAG))) {
unsigned int remaining = MAX_TCP_OPTION_SPACE - size;
+ unsigned int old_remaining;
- bpf_skops_hdr_opt_len(sk, skb, NULL, NULL, 0, opts, &remaining);
+ if (skb) {
+ unsigned int reserved_opt_spc;
+
+ reserved_opt_spc = tp->mss_cache - tcp_skb_seglen(skb);
+ if (reserved_opt_spc < remaining)
+ remaining = reserved_opt_spc;
+ }
- size = MAX_TCP_OPTION_SPACE - remaining;
+ old_remaining = remaining;
+ bpf_skops_hdr_opt_len(sk, skb, NULL, NULL, 0, opts, &remaining);
+ size += old_remaining - remaining;
}
return size;