* [PATCH v2 0/5 RFC] TCPCT part 2: cleanup after part 1
@ 2009-12-31 19:33 William Allen Simpson
2009-12-31 19:38 ` [PATCH v2 RFC 1/5] TCPCT part 2a: TCP header pointer functions William Allen Simpson
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: William Allen Simpson @ 2009-12-31 19:33 UTC (permalink / raw)
To: Linux Kernel Network Developers
Some portions that were removed during the various part 1 patch splits,
but were cut off by the sudden unexpected end of that merge window.
[03 Dec 2009] I've restarted the subdivision numbering.
Therefore, this code has had some earlier review. No comments were
received in the past 4 weeks.
These patches are against the current linux-2.6 tree.
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 RFC 1/5] TCPCT part 2a: TCP header pointer functions
2009-12-31 19:33 [PATCH v2 0/5 RFC] TCPCT part 2: cleanup after part 1 William Allen Simpson
@ 2009-12-31 19:38 ` William Allen Simpson
2009-12-31 19:44 ` [PATCH v2 RFC 2/5] TCPCT part 2b: remove old tcp_optlen function William Allen Simpson
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: William Allen Simpson @ 2009-12-31 19:38 UTC (permalink / raw)
To: Linux Kernel Network Developers
[-- Attachment #1: Type: text/plain, Size: 359 bytes --]
Redefine two TCP header functions to accept TCP header pointer.
When subtracting, return signed int to allow error checking.
These functions will be used in subsequent patches that implement
additional features.
Signed-off-by: William.Allen.Simpson@gmail.com
---
include/linux/tcp.h | 12 ++++++++++++
1 files changed, 12 insertions(+), 0 deletions(-)
[-- Attachment #2: TCPCT+2a2.patch --]
[-- Type: text/plain, Size: 718 bytes --]
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index 7fee8a4..d0133cf 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -223,6 +223,18 @@ static inline unsigned int tcp_optlen(const struct sk_buff *skb)
return (tcp_hdr(skb)->doff - 5) * 4;
}
+/* Length of fixed header plus standard options. */
+static inline unsigned int tcp_header_len_th(const struct tcphdr *th)
+{
+ return th->doff * 4;
+}
+
+/* Length of standard options only. This could be negative. */
+static inline int tcp_option_len_th(const struct tcphdr *th)
+{
+ return (int)(th->doff * 4) - sizeof(*th);
+}
+
/* This defines a selective acknowledgement block. */
struct tcp_sack_block_wire {
__be32 start_seq;
--
1.6.3.3
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v2 RFC 2/5] TCPCT part 2b: remove old tcp_optlen function
2009-12-31 19:33 [PATCH v2 0/5 RFC] TCPCT part 2: cleanup after part 1 William Allen Simpson
2009-12-31 19:38 ` [PATCH v2 RFC 1/5] TCPCT part 2a: TCP header pointer functions William Allen Simpson
@ 2009-12-31 19:44 ` William Allen Simpson
2009-12-31 19:52 ` [PATCH v2 RFC 3/5] TCPCT part 2c: accept SYNACK data William Allen Simpson
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: William Allen Simpson @ 2009-12-31 19:44 UTC (permalink / raw)
To: Linux Kernel Network Developers; +Cc: Michael Chan
[-- Attachment #1: Type: text/plain, Size: 653 bytes --]
In the only two existing files using the old tcp_optlen() function,
clean up confusing and inconsistent mixing of both byte and word
offsets. Document assumptions.
No semantic changes. The drivers should function exactly as existing.
Untested. No response from testers in 9+ weeks.
Requires:
TCPCT part 2a: TCP header pointer functions
Signed-off-by: William.Allen.Simpson@gmail.com
CC: Michael Chan <mchan@broadcom.com>
---
drivers/net/bnx2.c | 26 +++++++++++++--------
drivers/net/tg3.c | 59 ++++++++++++++++++++++++++-------------------------
include/linux/tcp.h | 5 ----
3 files changed, 46 insertions(+), 44 deletions(-)
[-- Attachment #2: TCPCT+2b2.patch --]
[-- Type: text/plain, Size: 6942 bytes --]
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 65df1de..3fc4912 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -6352,6 +6352,11 @@ bnx2_vlan_rx_register(struct net_device *dev, struct vlan_group *vlgrp)
/* Called with netif_tx_lock.
* bnx2_tx_int() runs without netif_tx_lock unless it needs to call
* netif_wake_queue().
+ *
+ * Quoth David Miller:
+ * This is transmit, and the packets can only come from the Linux TCP stack,
+ * not some external entity. ... adding [length] checks to drivers would be
+ * just a lot of rediculious bloat. [sic]
*/
static netdev_tx_t
bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -6397,18 +6402,17 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
#endif
if ((mss = skb_shinfo(skb)->gso_size)) {
- u32 tcp_opt_len;
- struct iphdr *iph;
+ struct tcphdr *th = tcp_hdr(skb);
+ int tcp_opt_words = th->doff - (sizeof(*th) >> 2);
+ /* assumes positive tcp_opt_words without checking */
vlan_tag_flags |= TX_BD_FLAGS_SW_LSO;
- tcp_opt_len = tcp_optlen(skb);
-
if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) {
u32 tcp_off = skb_transport_offset(skb) -
sizeof(struct ipv6hdr) - ETH_HLEN;
- vlan_tag_flags |= ((tcp_opt_len >> 2) << 8) |
+ vlan_tag_flags |= (tcp_opt_words << 8) |
TX_BD_FLAGS_SW_FLAGS;
if (likely(tcp_off == 0))
vlan_tag_flags &= ~TX_BD_FLAGS_TCP6_OFF0_MSK;
@@ -6421,11 +6425,13 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
mss |= (tcp_off & 0xc) << TX_BD_TCP6_OFF2_SHL;
}
} else {
- iph = ip_hdr(skb);
- if (tcp_opt_len || (iph->ihl > 5)) {
- vlan_tag_flags |= ((iph->ihl - 5) +
- (tcp_opt_len >> 2)) << 8;
- }
+ struct iphdr *iph = ip_hdr(skb);
+ int ip_opt_words = iph->ihl - (sizeof(*iph) >> 2);
+ /* assumes positive ip_opt_words without checking */
+ int opt_words = ip_opt_words + tcp_opt_words;
+
+ if (opt_words > 0)
+ vlan_tag_flags |= opt_words << 8;
}
} else
mss = 0;
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 3a74d21..31179db 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -5421,6 +5421,11 @@ static void tg3_set_txd(struct tg3_napi *tnapi, int entry,
/* hard_start_xmit for devices that don't have any bugs and
* support TG3_FLG2_HW_TSO_2 and TG3_FLG2_HW_TSO_3 only.
+ *
+ * Quoth David Miller:
+ * This is transmit, and the packets can only come from the Linux TCP stack,
+ * not some external entity. ... adding [length] checks to drivers would be
+ * just a lot of rediculious bloat. [sic]
*/
static netdev_tx_t tg3_start_xmit(struct sk_buff *skb,
struct net_device *dev)
@@ -5458,7 +5463,7 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb,
base_flags = 0;
mss = 0;
if ((mss = skb_shinfo(skb)->gso_size) != 0) {
- int tcp_opt_len, ip_tcp_len;
+ struct tcphdr *th;
u32 hdrlen;
if (skb_header_cloned(skb) &&
@@ -5466,18 +5471,16 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb,
dev_kfree_skb(skb);
goto out_unlock;
}
+ th = tcp_hdr(skb);
if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
hdrlen = skb_headlen(skb) - ETH_HLEN;
else {
struct iphdr *iph = ip_hdr(skb);
- tcp_opt_len = tcp_optlen(skb);
- ip_tcp_len = ip_hdrlen(skb) + sizeof(struct tcphdr);
-
+ hdrlen = ip_hdrlen(skb) + tcp_header_len_th(th);
+ iph->tot_len = htons(mss + hdrlen);
iph->check = 0;
- iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len);
- hdrlen = ip_tcp_len + tcp_opt_len;
}
if (tp->tg3_flags2 & TG3_FLG2_HW_TSO_3) {
@@ -5491,7 +5494,7 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb,
base_flags |= (TXD_FLAG_CPU_PRE_DMA |
TXD_FLAG_CPU_POST_DMA);
- tcp_hdr(skb)->check = 0;
+ th->check = 0;
}
else if (skb->ip_summed == CHECKSUM_PARTIAL)
@@ -5624,6 +5627,11 @@ tg3_tso_bug_end:
/* hard_start_xmit for devices that have the 4G bug and/or 40-bit bug and
* support TG3_FLG2_HW_TSO_1 or firmware TSO only.
+ *
+ * Quoth David Miller:
+ * This is transmit, and the packets can only come from the Linux TCP stack,
+ * not some external entity. ... adding [length] checks to drivers would be
+ * just a lot of rediculious bloat. [sic]
*/
static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb,
struct net_device *dev)
@@ -5665,18 +5673,18 @@ static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb,
if ((mss = skb_shinfo(skb)->gso_size) != 0) {
struct iphdr *iph;
- u32 tcp_opt_len, ip_tcp_len, hdr_len;
+ struct tcphdr *th;
+ u32 hdr_len;
+ int opt_bytes;
if (skb_header_cloned(skb) &&
pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
dev_kfree_skb(skb);
goto out_unlock;
}
+ th = tcp_hdr(skb);
+ hdr_len = ip_hdrlen(skb) + tcp_header_len_th(th);
- tcp_opt_len = tcp_optlen(skb);
- ip_tcp_len = ip_hdrlen(skb) + sizeof(struct tcphdr);
-
- hdr_len = ip_tcp_len + tcp_opt_len;
if (unlikely((ETH_HLEN + hdr_len) > 80) &&
(tp->tg3_flags2 & TG3_FLG2_TSO_BUG))
return (tg3_tso_bug(tp, skb));
@@ -5688,13 +5696,14 @@ static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb,
iph->check = 0;
iph->tot_len = htons(mss + hdr_len);
if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) {
- tcp_hdr(skb)->check = 0;
+ th->check = 0;
base_flags &= ~TXD_FLAG_TCPUDP_CSUM;
} else
- tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr,
- iph->daddr, 0,
- IPPROTO_TCP,
- 0);
+ th->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
+ 0, IPPROTO_TCP, 0);
+
+ opt_bytes = hdr_len - sizeof(*iph) - sizeof(*th);
+ /* assumes positive opt_bytes without checking */
if (tp->tg3_flags2 & TG3_FLG2_HW_TSO_3) {
mss |= (hdr_len & 0xc) << 12;
@@ -5705,19 +5714,11 @@ static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb,
mss |= hdr_len << 9;
else if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_1) ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
- if (tcp_opt_len || iph->ihl > 5) {
- int tsflags;
-
- tsflags = (iph->ihl - 5) + (tcp_opt_len >> 2);
- mss |= (tsflags << 11);
- }
+ if (opt_bytes > 0)
+ mss |= opt_bytes << (11 - 2);
} else {
- if (tcp_opt_len || iph->ihl > 5) {
- int tsflags;
-
- tsflags = (iph->ihl - 5) + (tcp_opt_len >> 2);
- base_flags |= tsflags << 12;
- }
+ if (opt_bytes > 0)
+ base_flags |= opt_bytes << (12 - 2);
}
}
#if TG3_VLAN_TAG_USED
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index d0133cf..74728f7 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -218,11 +218,6 @@ static inline unsigned int tcp_hdrlen(const struct sk_buff *skb)
return tcp_hdr(skb)->doff * 4;
}
-static inline unsigned int tcp_optlen(const struct sk_buff *skb)
-{
- return (tcp_hdr(skb)->doff - 5) * 4;
-}
-
/* Length of fixed header plus standard options. */
static inline unsigned int tcp_header_len_th(const struct tcphdr *th)
{
--
1.6.3.3
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v2 RFC 3/5] TCPCT part 2c: accept SYNACK data
2009-12-31 19:33 [PATCH v2 0/5 RFC] TCPCT part 2: cleanup after part 1 William Allen Simpson
2009-12-31 19:38 ` [PATCH v2 RFC 1/5] TCPCT part 2a: TCP header pointer functions William Allen Simpson
2009-12-31 19:44 ` [PATCH v2 RFC 2/5] TCPCT part 2b: remove old tcp_optlen function William Allen Simpson
@ 2009-12-31 19:52 ` William Allen Simpson
2009-12-31 19:58 ` [PATCH v2 RFC 4/5] TCPCT part 2d: cleanup tcp_parse_options William Allen Simpson
2009-12-31 20:06 ` [PATCH v2 RFC 5/5] TCPCT part 2e: parse cookie pair and 64-bit timestamp William Allen Simpson
4 siblings, 0 replies; 6+ messages in thread
From: William Allen Simpson @ 2009-12-31 19:52 UTC (permalink / raw)
To: Linux Kernel Network Developers
[-- Attachment #1: Type: text/plain, Size: 707 bytes --]
When accompanied by cookie option, Initiator (client) queues incoming
SYNACK transaction data.
This is a straightforward re-implementation of an earlier (year-old)
patch that no longer applies cleanly, with permission of the original
author (Adam Langley). The patch was previously reviewed:
http://thread.gmane.org/gmane.linux.network/102586
This function will also be used in subsequent patches that implement
additional features.
Requires:
TCPCT part 1g: Responder Cookie => Initiator
TCPCT part 2a: TCP header pointer functions
Signed-off-by: William.Allen.Simpson@gmail.com
---
net/ipv4/tcp_input.c | 25 ++++++++++++++++++++++++-
1 files changed, 24 insertions(+), 1 deletions(-)
[-- Attachment #2: TCPCT+2c2.patch --]
[-- Type: text/plain, Size: 1724 bytes --]
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 28e0296..78604bd 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -5415,6 +5415,12 @@ discard:
return 0;
}
+/*
+ * Returns:
+ * +1 on reset,
+ * 0 success and/or SYNACK data,
+ * -1 on discard.
+ */
static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
struct tcphdr *th, unsigned len)
{
@@ -5423,6 +5429,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
struct tcp_sock *tp = tcp_sk(sk);
struct tcp_cookie_values *cvp = tp->cookie_values;
int saved_clamp = tp->rx_opt.mss_clamp;
+ int queued = 0;
tcp_parse_options(skb, &tp->rx_opt, &hash_location, 0);
@@ -5544,6 +5551,19 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
hash_location, cookie_size);
cvp->cookie_pair_size = cookie_pair_size;
}
+
+ queued = skb->len - tcp_header_len_th(th);
+ if (queued > 0) {
+ /* Queue incoming transaction data. */
+ __skb_pull(skb, tcp_header_len_th(th));
+ __skb_queue_tail(&sk->sk_receive_queue, skb);
+ skb_set_owner_r(skb, sk);
+ sk->sk_data_ready(sk, 0);
+ cvp->s_data_in = 1; /* true */
+ tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
+ tp->rcv_wup = TCP_SKB_CB(skb)->end_seq;
+ tp->copied_seq = TCP_SKB_CB(skb)->seq + 1;
+ }
}
smp_mb();
@@ -5597,11 +5617,14 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
TCP_DELACK_MAX, TCP_RTO_MAX);
discard:
- __kfree_skb(skb);
+ if (queued <= 0)
+ __kfree_skb(skb);
return 0;
} else {
tcp_send_ack(sk);
}
+ if (queued > 0)
+ return 0;
return -1;
}
--
1.6.3.3
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v2 RFC 4/5] TCPCT part 2d: cleanup tcp_parse_options
2009-12-31 19:33 [PATCH v2 0/5 RFC] TCPCT part 2: cleanup after part 1 William Allen Simpson
` (2 preceding siblings ...)
2009-12-31 19:52 ` [PATCH v2 RFC 3/5] TCPCT part 2c: accept SYNACK data William Allen Simpson
@ 2009-12-31 19:58 ` William Allen Simpson
2009-12-31 20:06 ` [PATCH v2 RFC 5/5] TCPCT part 2e: parse cookie pair and 64-bit timestamp William Allen Simpson
4 siblings, 0 replies; 6+ messages in thread
From: William Allen Simpson @ 2009-12-31 19:58 UTC (permalink / raw)
To: Linux Kernel Network Developers
[-- Attachment #1: Type: text/plain, Size: 364 bytes --]
Split switch, shift cases to the left, fix most lines beyond column 80.
Requires:
TCPCT part 1g: Responder Cookie => Initiator
TCPCT part 2a: TCP header pointer functions
Signed-off-by: William.Allen.Simpson@gmail.com
---
net/ipv4/tcp_input.c | 191 +++++++++++++++++++++++++++----------------------
1 files changed, 105 insertions(+), 86 deletions(-)
[-- Attachment #2: TCPCT+2d2.patch --]
[-- Type: text/plain, Size: 5898 bytes --]
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 78604bd..7f8c6ac 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -3729,12 +3729,12 @@ old_ack:
void tcp_parse_options(struct sk_buff *skb, struct tcp_options_received *opt_rx,
u8 **hvpp, int estab)
{
- unsigned char *ptr;
struct tcphdr *th = tcp_hdr(skb);
- int length = (th->doff * 4) - sizeof(struct tcphdr);
+ unsigned char *ptr = (unsigned char *)(th + 1);
+ int length = tcp_option_len_th(th);
- ptr = (unsigned char *)(th + 1);
- opt_rx->saw_tstamp = 0;
+ opt_rx->cookie_plus = 0;
+ opt_rx->saw_tstamp = 0; /* false */
while (length > 0) {
int opcode = *ptr++;
@@ -3747,98 +3747,117 @@ void tcp_parse_options(struct sk_buff *skb, struct tcp_options_received *opt_rx,
length--;
continue;
default:
- opsize = *ptr++;
- if (opsize < 2) /* "silly options" */
- return;
- if (opsize > length)
- return; /* don't parse partial options */
- switch (opcode) {
- case TCPOPT_MSS:
- if (opsize == TCPOLEN_MSS && th->syn && !estab) {
- u16 in_mss = get_unaligned_be16(ptr);
- if (in_mss) {
- if (opt_rx->user_mss &&
- opt_rx->user_mss < in_mss)
- in_mss = opt_rx->user_mss;
- opt_rx->mss_clamp = in_mss;
- }
- }
- break;
- case TCPOPT_WINDOW:
- if (opsize == TCPOLEN_WINDOW && th->syn &&
- !estab && sysctl_tcp_window_scaling) {
- __u8 snd_wscale = *(__u8 *)ptr;
- opt_rx->wscale_ok = 1;
- if (snd_wscale > 14) {
- if (net_ratelimit())
- printk(KERN_INFO "tcp_parse_options: Illegal window "
- "scaling value %d >14 received.\n",
- snd_wscale);
- snd_wscale = 14;
- }
- opt_rx->snd_wscale = snd_wscale;
- }
- break;
- case TCPOPT_TIMESTAMP:
- if ((opsize == TCPOLEN_TIMESTAMP) &&
- ((estab && opt_rx->tstamp_ok) ||
- (!estab && sysctl_tcp_timestamps))) {
- opt_rx->saw_tstamp = 1;
- opt_rx->rcv_tsval = get_unaligned_be32(ptr);
- opt_rx->rcv_tsecr = get_unaligned_be32(ptr + 4);
- }
- break;
- case TCPOPT_SACK_PERM:
- if (opsize == TCPOLEN_SACK_PERM && th->syn &&
- !estab && sysctl_tcp_sack) {
- opt_rx->sack_ok = 1;
- tcp_sack_reset(opt_rx);
+ /* fallthru */
+ break;
+ };
+
+ opsize = *ptr++;
+ if (opsize < 2) /* "silly options" */
+ return;
+ if (opsize > length)
+ return; /* don't parse partial options */
+
+ switch (opcode) {
+ case TCPOPT_MSS:
+ if (opsize == TCPOLEN_MSS && th->syn && !estab) {
+ u16 in_mss = get_unaligned_be16(ptr);
+ if (in_mss) {
+ if (opt_rx->user_mss &&
+ opt_rx->user_mss < in_mss)
+ in_mss = opt_rx->user_mss;
+ opt_rx->mss_clamp = in_mss;
}
- break;
+ }
+ break;
- case TCPOPT_SACK:
- if ((opsize >= (TCPOLEN_SACK_BASE + TCPOLEN_SACK_PERBLOCK)) &&
- !((opsize - TCPOLEN_SACK_BASE) % TCPOLEN_SACK_PERBLOCK) &&
- opt_rx->sack_ok) {
- TCP_SKB_CB(skb)->sacked = (ptr - 2) - (unsigned char *)th;
+ case TCPOPT_WINDOW:
+ if (opsize == TCPOLEN_WINDOW && th->syn &&
+ !estab && sysctl_tcp_window_scaling) {
+ __u8 snd_wscale = *(__u8 *)ptr;
+ opt_rx->wscale_ok = 1;
+ if (snd_wscale > 14) {
+ if (net_ratelimit())
+ printk(KERN_INFO
+ "tcp_parse_options: "
+ "window scaling value "
+ "%d > 14 received.\n",
+ snd_wscale);
+ snd_wscale = 14;
}
- break;
+ opt_rx->snd_wscale = snd_wscale;
+ }
+ break;
+
+ case TCPOPT_SACK_PERM:
+ if (opsize == TCPOLEN_SACK_PERM && th->syn &&
+ !estab && sysctl_tcp_sack) {
+ opt_rx->sack_ok = 1;
+ tcp_sack_reset(opt_rx);
+ }
+ break;
+
+ case TCPOPT_SACK:
+ if ((opsize >= (TCPOLEN_SACK_BASE + TCPOLEN_SACK_PERBLOCK)) &&
+ !((opsize - TCPOLEN_SACK_BASE) % TCPOLEN_SACK_PERBLOCK) &&
+ opt_rx->sack_ok) {
+ TCP_SKB_CB(skb)->sacked = (ptr - 2)
+ - (unsigned char *)th;
+ }
+ break;
+
+ case TCPOPT_TIMESTAMP:
+ if ((opsize == TCPOLEN_TIMESTAMP) &&
+ ((estab && opt_rx->tstamp_ok) ||
+ (!estab && sysctl_tcp_timestamps))) {
+ opt_rx->saw_tstamp = 1;
+ opt_rx->rcv_tsval = get_unaligned_be32(ptr);
+ opt_rx->rcv_tsecr = get_unaligned_be32(ptr + 4);
+ }
+ break;
#ifdef CONFIG_TCP_MD5SIG
- case TCPOPT_MD5SIG:
- /*
- * The MD5 Hash has already been
- * checked (see tcp_v{4,6}_do_rcv()).
- */
- break;
+ case TCPOPT_MD5SIG:
+ /*
+ * The MD5 Hash has already been
+ * checked (see tcp_v{4,6}_do_rcv()).
+ */
+ break;
#endif
- case TCPOPT_COOKIE:
- /* This option is variable length.
- */
- switch (opsize) {
- case TCPOLEN_COOKIE_BASE:
- /* not yet implemented */
- break;
- case TCPOLEN_COOKIE_PAIR:
- /* not yet implemented */
- break;
- case TCPOLEN_COOKIE_MIN+0:
- case TCPOLEN_COOKIE_MIN+2:
- case TCPOLEN_COOKIE_MIN+4:
- case TCPOLEN_COOKIE_MIN+6:
- case TCPOLEN_COOKIE_MAX:
- /* 16-bit multiple */
+ case TCPOPT_COOKIE:
+ /* This option is variable length.
+ */
+ switch (opsize) {
+ case TCPOLEN_COOKIE_BASE:
+ /* not yet implemented */
+ break;
+ case TCPOLEN_COOKIE_PAIR:
+ /* not yet implemented */
+ break;
+ case TCPOLEN_COOKIE_MIN+0:
+ case TCPOLEN_COOKIE_MIN+2:
+ case TCPOLEN_COOKIE_MIN+4:
+ case TCPOLEN_COOKIE_MIN+6:
+ case TCPOLEN_COOKIE_MAX:
+ /* 16-bit multiple */
+ if (opt_rx->cookie_plus == 0 &&
+ opt_rx->saw_tstamp &&
+ th->syn) {
opt_rx->cookie_plus = opsize;
*hvpp = ptr;
- default:
- /* ignore option */
- break;
- };
+ }
+ break;
+ default:
+ /* ignore option */
break;
};
+ break;
- ptr += opsize-2;
- length -= opsize;
- }
+ default:
+ /* skip unrecognized options */
+ break;
+ };
+
+ ptr += opsize - 2;
+ length -= opsize;
}
}
--
1.6.3.3
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v2 RFC 5/5] TCPCT part 2e: parse cookie pair and 64-bit timestamp
2009-12-31 19:33 [PATCH v2 0/5 RFC] TCPCT part 2: cleanup after part 1 William Allen Simpson
` (3 preceding siblings ...)
2009-12-31 19:58 ` [PATCH v2 RFC 4/5] TCPCT part 2d: cleanup tcp_parse_options William Allen Simpson
@ 2009-12-31 20:06 ` William Allen Simpson
4 siblings, 0 replies; 6+ messages in thread
From: William Allen Simpson @ 2009-12-31 20:06 UTC (permalink / raw)
To: Linux Kernel Network Developers
[-- Attachment #1: Type: text/plain, Size: 543 bytes --]
Parse cookie pair extended option (previously defined).
Define and parse 64-bit timestamp extended option (and minor cleanup).
However, only 32-bits are used at this time.
Requires:
TCPCT part 2a: TCP header pointer functions
TCPCT part 2d: cleanup tcp_parse_options
Signed-off-by: William.Allen.Simpson@gmail.com
---
include/linux/tcp.h | 10 +++++++++-
include/net/tcp.h | 15 ++++++++-------
net/ipv4/tcp_input.c | 45 +++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 60 insertions(+), 10 deletions(-)
[-- Attachment #2: TCPCT+2e2.patch --]
[-- Type: text/plain, Size: 4960 bytes --]
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index 74728f7..a14639a 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -260,13 +260,21 @@ struct tcp_options_received {
u8 num_sacks; /* Number of SACK blocks */
u16 user_mss; /* mss requested by user in ioctl */
u16 mss_clamp; /* Maximal mss, negotiated at connection setup */
+
+ /* When the options are extended beyond the maximum 40 bytes,
+ * then this holds the additional data offset (in bytes,
+ * the least significant 2 bits are always zero).
+ */
+ u16 extended:14, /* Up to 13 (40/3) by 255 by 4 bytes */
+ tstamp64:1, /* Seen on recent packet */
+ tstamp64_ok:1; /* Verified with cookie pair */
};
static inline void tcp_clear_options(struct tcp_options_received *rx_opt)
{
rx_opt->tstamp_ok = rx_opt->sack_ok = 0;
rx_opt->wscale_ok = rx_opt->snd_wscale = 0;
- rx_opt->cookie_plus = 0;
+ rx_opt->tstamp64_ok = 0;
}
/* This is the max number of SACKS that we'll generate and process. It's safe
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 34f5cc2..ed0ef2b 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -156,21 +156,20 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo);
/*
* TCP option
*/
-
-#define TCPOPT_NOP 1 /* Padding */
#define TCPOPT_EOL 0 /* End of options */
+#define TCPOPT_NOP 1 /* Padding */
#define TCPOPT_MSS 2 /* Segment size negotiating */
#define TCPOPT_WINDOW 3 /* Window scaling */
#define TCPOPT_SACK_PERM 4 /* SACK Permitted */
#define TCPOPT_SACK 5 /* SACK Block */
#define TCPOPT_TIMESTAMP 8 /* Better RTT estimations/PAWS */
#define TCPOPT_MD5SIG 19 /* MD5 Signature (RFC2385) */
-#define TCPOPT_COOKIE 253 /* Cookie extension (experimental) */
+#define TCPOPT_COOKIE 31 /* Cookie extension (experimental) */
+#define TCPOPT_TSTAMP64 32 /* 64-bit extension (experimental) */
/*
- * TCP option lengths
+ * TCP option lengths (same order as above)
*/
-
#define TCPOLEN_MSS 4
#define TCPOLEN_WINDOW 3
#define TCPOLEN_SACK_PERM 2
@@ -180,16 +179,18 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo);
#define TCPOLEN_COOKIE_PAIR 3 /* Cookie pair header extension */
#define TCPOLEN_COOKIE_MIN (TCPOLEN_COOKIE_BASE+TCP_COOKIE_MIN)
#define TCPOLEN_COOKIE_MAX (TCPOLEN_COOKIE_BASE+TCP_COOKIE_MAX)
+#define TCPOLEN_TSTAMP64 3
/* But this is what stacks really send out. */
-#define TCPOLEN_TSTAMP_ALIGNED 12
+#define TCPOLEN_MSS_ALIGNED 4
#define TCPOLEN_WSCALE_ALIGNED 4
#define TCPOLEN_SACKPERM_ALIGNED 4
#define TCPOLEN_SACK_BASE 2
#define TCPOLEN_SACK_BASE_ALIGNED 4
#define TCPOLEN_SACK_PERBLOCK 8
+#define TCPOLEN_TSTAMP_ALIGNED 12
#define TCPOLEN_MD5SIG_ALIGNED 20
-#define TCPOLEN_MSS_ALIGNED 4
+#define TCPOLEN_TSTAMP64_EXTEND 16
/* Flags in tp->nonagle */
#define TCP_NAGLE_OFF 1 /* Nagle's algo is disabled */
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 7f8c6ac..6b9eabe 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -3734,6 +3734,8 @@ void tcp_parse_options(struct sk_buff *skb, struct tcp_options_received *opt_rx,
int length = tcp_option_len_th(th);
opt_rx->cookie_plus = 0;
+ opt_rx->extended = 0;
+ opt_rx->tstamp64 = 0; /* false */
opt_rx->saw_tstamp = 0; /* false */
while (length > 0) {
@@ -3829,9 +3831,23 @@ void tcp_parse_options(struct sk_buff *skb, struct tcp_options_received *opt_rx,
case TCPOLEN_COOKIE_BASE:
/* not yet implemented */
break;
- case TCPOLEN_COOKIE_PAIR:
- /* not yet implemented */
+ case TCPOLEN_COOKIE_PAIR: {
+ int extend = *ptr * 4;
+
+ if (extend >= TCPOLEN_COOKIE_MIN &&
+ extend <= TCPOLEN_COOKIE_MAX &&
+ opt_rx->cookie_plus == 0 &&
+ opt_rx->saw_tstamp &&
+ !th->syn) {
+ opt_rx->cookie_plus =
+ TCPOLEN_COOKIE_BASE + extend;
+ *hvpp = (u8 *)th
+ + tcp_header_len_th(th)
+ + opt_rx->extended;
+ }
+ opt_rx->extended += extend;
break;
+ }
case TCPOLEN_COOKIE_MIN+0:
case TCPOLEN_COOKIE_MIN+2:
case TCPOLEN_COOKIE_MIN+4:
@@ -3851,6 +3867,31 @@ void tcp_parse_options(struct sk_buff *skb, struct tcp_options_received *opt_rx,
};
break;
+ case TCPOPT_TSTAMP64:
+ if (opsize == TCPOLEN_TSTAMP64) {
+ int extend = *ptr * 4;
+
+ if (extend == TCPOLEN_TSTAMP64_EXTEND &&
+ opt_rx->extended == 0 &&
+ !opt_rx->saw_tstamp &&
+ !th->syn) {
+ u8 *tsp = (u8 *)(th)
+ + tcp_header_len_th(th)
+ + 4; /* low 32-bits */
+
+ opt_rx->tstamp64 = 1; /* true */
+ opt_rx->saw_tstamp = 1; /* true */
+
+ /* 64-bits not yet implemented */
+ opt_rx->rcv_tsval =
+ get_unaligned_be32(tsp);
+ opt_rx->rcv_tsecr =
+ get_unaligned_be32(tsp + 8);
+ }
+ opt_rx->extended += extend;
+ }
+ break;
+
default:
/* skip unrecognized options */
break;
--
1.6.3.3
^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2009-12-31 20:06 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-12-31 19:33 [PATCH v2 0/5 RFC] TCPCT part 2: cleanup after part 1 William Allen Simpson
2009-12-31 19:38 ` [PATCH v2 RFC 1/5] TCPCT part 2a: TCP header pointer functions William Allen Simpson
2009-12-31 19:44 ` [PATCH v2 RFC 2/5] TCPCT part 2b: remove old tcp_optlen function William Allen Simpson
2009-12-31 19:52 ` [PATCH v2 RFC 3/5] TCPCT part 2c: accept SYNACK data William Allen Simpson
2009-12-31 19:58 ` [PATCH v2 RFC 4/5] TCPCT part 2d: cleanup tcp_parse_options William Allen Simpson
2009-12-31 20:06 ` [PATCH v2 RFC 5/5] TCPCT part 2e: parse cookie pair and 64-bit timestamp William Allen Simpson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).