tcp: move features to separate files

Type: refactor

Signed-off-by: Florin Coras <fcoras@cisco.com>
Change-Id: Ia477b8dba9266f47907967e363c11048e5cd95ab
This commit is contained in:
Florin Coras
2020-03-18 20:31:34 +00:00
committed by Dave Barach
parent a26f54421a
commit 999840cf80
18 changed files with 3128 additions and 2946 deletions
+1
View File
@@ -13,6 +13,7 @@
* limitations under the License.
*/
#include <vnet/tcp/tcp.h>
#include <vnet/tcp/tcp_inlines.h>
#define TCP_TEST_I(_cond, _comment, _args...) \
({ \
+8 -1
View File
@@ -659,9 +659,11 @@ list(APPEND VNET_SOURCES
tcp/tcp_output.c
tcp/tcp_input.c
tcp/tcp_newreno.c
tcp/tcp_cubic.c
tcp/tcp_bt.c
tcp/tcp_cli.c
tcp/tcp_cubic.c
tcp/tcp_debug.c
tcp/tcp_sack.c
tcp/tcp.c
)
@@ -674,7 +676,12 @@ list(APPEND VNET_MULTIARCH_SOURCES
list(APPEND VNET_HEADERS
tcp/tcp_packet.h
tcp/tcp_timer.h
tcp/tcp_bt.h
tcp/tcp_cc.h
tcp/tcp_debug.h
tcp/tcp_inlines.h
tcp/tcp_sack.h
tcp/tcp_types.h
tcp/tcp.h
tcp/tcp_error.def
)
+1 -1052
View File
File diff suppressed because it is too large Load Diff
+24 -939
View File
File diff suppressed because it is too large Load Diff
-5
View File
@@ -115,11 +115,6 @@ tcp_api_hookup (vlib_main_t * vm)
VLIB_API_INIT_FUNCTION (tcp_api_hookup);
void
tcp_api_reference (void)
{
}
/*
* fd.io coding-style-patch-verification: ON
*
+2
View File
@@ -16,7 +16,9 @@
* draft-cheng-iccrg-delivery-rate-estimation-00
*/
#include <vnet/tcp/tcp_bt.h>
#include <vnet/tcp/tcp.h>
#include <vnet/tcp/tcp_inlines.h>
static tcp_bt_sample_t *
bt_get_sample (tcp_byte_tracker_t * bt, u32 bts_index)
+91
View File
@@ -0,0 +1,91 @@
/*
* Copyright (c) 2020 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Rate estimation
*/
#ifndef SRC_VNET_TCP_TCP_BT_H_
#define SRC_VNET_TCP_TCP_BT_H_
#include <vnet/tcp/tcp_types.h>
/**
* Byte tracker initialize
*
* @param tc connection for which the byte tracker should be allocated and
* initialized
*/
void tcp_bt_init (tcp_connection_t * tc);
/**
* Byte tracker cleanup
*
* @param tc connection for which the byte tracker should be cleaned up
*/
void tcp_bt_cleanup (tcp_connection_t * tc);
/**
* Flush byte tracker samples
*
* @param tc tcp connection for which samples should be flushed
*/
void tcp_bt_flush_samples (tcp_connection_t * tc);
/**
* Track a tcp tx burst
*
* @param tc tcp connection
*/
void tcp_bt_track_tx (tcp_connection_t * tc, u32 len);
/**
* Track a tcp retransmission
*
* @param tc tcp connection
* @param start start sequence number
* @param end end sequence number
*/
void tcp_bt_track_rxt (tcp_connection_t * tc, u32 start, u32 end);
/**
* Generate a delivery rate sample from recently acked bytes
*
* @param tc tcp connection
* @param rs resulting rate sample
*/
void tcp_bt_sample_delivery_rate (tcp_connection_t * tc,
tcp_rate_sample_t * rs);
/**
* Check if sample to be generated is app limited
*
* @param tc tcp connection
*/
void tcp_bt_check_app_limited (tcp_connection_t * tc);
/**
* Check if the byte tracker is in sane state
*
* Should be used only for testing
*
* @param bt byte tracker
*/
int tcp_bt_is_sane (tcp_byte_tracker_t * bt);
format_function_t format_tcp_bt;
#endif /* SRC_VNET_TCP_TCP_BT_H_ */
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/
+111
View File
@@ -0,0 +1,111 @@
/*
* Copyright (c) 2020 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef SRC_VNET_TCP_TCP_CC_H_
#define SRC_VNET_TCP_TCP_CC_H_
#include <vnet/tcp/tcp_types.h>
always_inline void
tcp_cc_rcv_ack (tcp_connection_t * tc, tcp_rate_sample_t * rs)
{
tc->cc_algo->rcv_ack (tc, rs);
tc->tsecr_last_ack = tc->rcv_opts.tsecr;
}
static inline void
tcp_cc_rcv_cong_ack (tcp_connection_t * tc, tcp_cc_ack_t ack_type,
tcp_rate_sample_t * rs)
{
tc->cc_algo->rcv_cong_ack (tc, ack_type, rs);
}
static inline void
tcp_cc_congestion (tcp_connection_t * tc)
{
tc->cc_algo->congestion (tc);
}
static inline void
tcp_cc_loss (tcp_connection_t * tc)
{
tc->cc_algo->loss (tc);
}
static inline void
tcp_cc_recovered (tcp_connection_t * tc)
{
tc->cc_algo->recovered (tc);
}
static inline void
tcp_cc_undo_recovery (tcp_connection_t * tc)
{
if (tc->cc_algo->undo_recovery)
tc->cc_algo->undo_recovery (tc);
}
static inline void
tcp_cc_event (tcp_connection_t * tc, tcp_cc_event_t evt)
{
if (tc->cc_algo->event)
tc->cc_algo->event (tc, evt);
}
static inline u64
tcp_cc_get_pacing_rate (tcp_connection_t * tc)
{
if (tc->cc_algo->get_pacing_rate)
return tc->cc_algo->get_pacing_rate (tc);
f64 srtt = clib_min ((f64) tc->srtt * TCP_TICK, tc->mrtt_us);
/* TODO should constrain to interface's max throughput but
* we don't have link speeds for sw ifs ..*/
return ((f64) tc->cwnd / srtt);
}
static inline void *
tcp_cc_data (tcp_connection_t * tc)
{
return (void *) tc->cc_data;
}
/**
* Register exiting cc algo type
*/
void tcp_cc_algo_register (tcp_cc_algorithm_type_e type,
const tcp_cc_algorithm_t * vft);
/**
* Register new cc algo type
*/
tcp_cc_algorithm_type_e tcp_cc_algo_new_type (const tcp_cc_algorithm_t * vft);
tcp_cc_algorithm_t *tcp_cc_algo_get (tcp_cc_algorithm_type_e type);
void newreno_rcv_cong_ack (tcp_connection_t * tc, tcp_cc_ack_t ack_type,
tcp_rate_sample_t * rs);
#endif /* SRC_VNET_TCP_TCP_CC_H_ */
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/
File diff suppressed because it is too large Load Diff
+1
View File
@@ -14,6 +14,7 @@
*/
#include <vnet/tcp/tcp.h>
#include <vnet/tcp/tcp_inlines.h>
#include <math.h>
#define beta_cubic 0.7
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+1
View File
@@ -14,6 +14,7 @@
*/
#include <vnet/tcp/tcp.h>
#include <vnet/tcp/tcp_inlines.h>
typedef struct nwreno_cfg_
{
+3 -86
View File
@@ -14,6 +14,7 @@
*/
#include <vnet/tcp/tcp.h>
#include <vnet/tcp/tcp_inlines.h>
#include <math.h>
typedef enum _tcp_output_next
@@ -166,90 +167,6 @@ tcp_window_to_advertise (tcp_connection_t * tc, tcp_state_t state)
return tc->rcv_wnd >> tc->rcv_wscale;
}
/**
* Write TCP options to segment.
*/
static u32
tcp_options_write (u8 * data, tcp_options_t * opts)
{
u32 opts_len = 0;
u32 buf, seq_len = 4;
if (tcp_opts_mss (opts))
{
*data++ = TCP_OPTION_MSS;
*data++ = TCP_OPTION_LEN_MSS;
buf = clib_host_to_net_u16 (opts->mss);
clib_memcpy_fast (data, &buf, sizeof (opts->mss));
data += sizeof (opts->mss);
opts_len += TCP_OPTION_LEN_MSS;
}
if (tcp_opts_wscale (opts))
{
*data++ = TCP_OPTION_WINDOW_SCALE;
*data++ = TCP_OPTION_LEN_WINDOW_SCALE;
*data++ = opts->wscale;
opts_len += TCP_OPTION_LEN_WINDOW_SCALE;
}
if (tcp_opts_sack_permitted (opts))
{
*data++ = TCP_OPTION_SACK_PERMITTED;
*data++ = TCP_OPTION_LEN_SACK_PERMITTED;
opts_len += TCP_OPTION_LEN_SACK_PERMITTED;
}
if (tcp_opts_tstamp (opts))
{
*data++ = TCP_OPTION_TIMESTAMP;
*data++ = TCP_OPTION_LEN_TIMESTAMP;
buf = clib_host_to_net_u32 (opts->tsval);
clib_memcpy_fast (data, &buf, sizeof (opts->tsval));
data += sizeof (opts->tsval);
buf = clib_host_to_net_u32 (opts->tsecr);
clib_memcpy_fast (data, &buf, sizeof (opts->tsecr));
data += sizeof (opts->tsecr);
opts_len += TCP_OPTION_LEN_TIMESTAMP;
}
if (tcp_opts_sack (opts))
{
int i;
if (opts->n_sack_blocks != 0)
{
*data++ = TCP_OPTION_SACK_BLOCK;
*data++ = 2 + opts->n_sack_blocks * TCP_OPTION_LEN_SACK_BLOCK;
for (i = 0; i < opts->n_sack_blocks; i++)
{
buf = clib_host_to_net_u32 (opts->sacks[i].start);
clib_memcpy_fast (data, &buf, seq_len);
data += seq_len;
buf = clib_host_to_net_u32 (opts->sacks[i].end);
clib_memcpy_fast (data, &buf, seq_len);
data += seq_len;
}
opts_len += 2 + opts->n_sack_blocks * TCP_OPTION_LEN_SACK_BLOCK;
}
}
/* Terminate TCP options */
if (opts_len % 4)
{
*data++ = TCP_OPTION_EOL;
opts_len += TCP_OPTION_LEN_EOL;
}
/* Pad with zeroes to a u32 boundary */
while (opts_len % 4)
{
*data++ = TCP_OPTION_NOOP;
opts_len += TCP_OPTION_LEN_NOOP;
}
return opts_len;
}
static int
tcp_make_syn_options (tcp_connection_t * tc, tcp_options_t * opts)
{
@@ -563,7 +480,7 @@ tcp_make_ack (tcp_connection_t * tc, vlib_buffer_t * b)
/**
* Convert buffer to FIN-ACK
*/
void
static void
tcp_make_fin (tcp_connection_t * tc, vlib_buffer_t * b)
{
tcp_make_ack_i (tc, b, TCP_STATE_ESTABLISHED, TCP_FLAG_FIN | TCP_FLAG_ACK);
@@ -598,7 +515,7 @@ tcp_make_syn (tcp_connection_t * tc, vlib_buffer_t * b)
/**
* Convert buffer to SYN-ACK
*/
void
static void
tcp_make_synack (tcp_connection_t * tc, vlib_buffer_t * b)
{
tcp_options_t _snd_opts, *snd_opts = &_snd_opts;
+213
View File
@@ -172,6 +172,219 @@ typedef struct
#define TCP_MAX_WND_SCALE 14 /* See RFC 1323 */
#define TCP_OPTS_ALIGN 4
#define TCP_OPTS_MAX_SACK_BLOCKS 3
/* Modulo arithmetic for TCP sequence numbers */
#define seq_lt(_s1, _s2) ((i32)((_s1)-(_s2)) < 0)
#define seq_leq(_s1, _s2) ((i32)((_s1)-(_s2)) <= 0)
#define seq_gt(_s1, _s2) ((i32)((_s1)-(_s2)) > 0)
#define seq_geq(_s1, _s2) ((i32)((_s1)-(_s2)) >= 0)
#define seq_max(_s1, _s2) (seq_gt((_s1), (_s2)) ? (_s1) : (_s2))
/* Modulo arithmetic for timestamps */
#define timestamp_lt(_t1, _t2) ((i32)((_t1)-(_t2)) < 0)
#define timestamp_leq(_t1, _t2) ((i32)((_t1)-(_t2)) <= 0)
/**
* Parse TCP header options.
*
* @param th TCP header
* @param to TCP options data structure to be populated
* @param is_syn set if packet is syn
* @return -1 if parsing failed
*/
always_inline int
tcp_options_parse (tcp_header_t * th, tcp_options_t * to, u8 is_syn)
{
const u8 *data;
u8 opt_len, opts_len, kind;
int j;
sack_block_t b;
opts_len = (tcp_doff (th) << 2) - sizeof (tcp_header_t);
data = (const u8 *) (th + 1);
/* Zero out all flags but those set in SYN */
to->flags &= (TCP_OPTS_FLAG_SACK_PERMITTED | TCP_OPTS_FLAG_WSCALE
| TCP_OPTS_FLAG_TSTAMP | TCP_OPTS_FLAG_MSS);
for (; opts_len > 0; opts_len -= opt_len, data += opt_len)
{
kind = data[0];
/* Get options length */
if (kind == TCP_OPTION_EOL)
break;
else if (kind == TCP_OPTION_NOOP)
{
opt_len = 1;
continue;
}
else
{
/* broken options */
if (opts_len < 2)
return -1;
opt_len = data[1];
/* weird option length */
if (opt_len < 2 || opt_len > opts_len)
return -1;
}
/* Parse options */
switch (kind)
{
case TCP_OPTION_MSS:
if (!is_syn)
break;
if ((opt_len == TCP_OPTION_LEN_MSS) && tcp_syn (th))
{
to->flags |= TCP_OPTS_FLAG_MSS;
to->mss = clib_net_to_host_u16 (*(u16 *) (data + 2));
}
break;
case TCP_OPTION_WINDOW_SCALE:
if (!is_syn)
break;
if ((opt_len == TCP_OPTION_LEN_WINDOW_SCALE) && tcp_syn (th))
{
to->flags |= TCP_OPTS_FLAG_WSCALE;
to->wscale = data[2];
if (to->wscale > TCP_MAX_WND_SCALE)
to->wscale = TCP_MAX_WND_SCALE;
}
break;
case TCP_OPTION_TIMESTAMP:
if (is_syn)
to->flags |= TCP_OPTS_FLAG_TSTAMP;
if ((to->flags & TCP_OPTS_FLAG_TSTAMP)
&& opt_len == TCP_OPTION_LEN_TIMESTAMP)
{
to->tsval = clib_net_to_host_u32 (*(u32 *) (data + 2));
to->tsecr = clib_net_to_host_u32 (*(u32 *) (data + 6));
}
break;
case TCP_OPTION_SACK_PERMITTED:
if (!is_syn)
break;
if (opt_len == TCP_OPTION_LEN_SACK_PERMITTED && tcp_syn (th))
to->flags |= TCP_OPTS_FLAG_SACK_PERMITTED;
break;
case TCP_OPTION_SACK_BLOCK:
/* If SACK permitted was not advertised or a SYN, break */
if ((to->flags & TCP_OPTS_FLAG_SACK_PERMITTED) == 0 || tcp_syn (th))
break;
/* If too short or not correctly formatted, break */
if (opt_len < 10 || ((opt_len - 2) % TCP_OPTION_LEN_SACK_BLOCK))
break;
to->flags |= TCP_OPTS_FLAG_SACK;
to->n_sack_blocks = (opt_len - 2) / TCP_OPTION_LEN_SACK_BLOCK;
vec_reset_length (to->sacks);
for (j = 0; j < to->n_sack_blocks; j++)
{
b.start = clib_net_to_host_u32 (*(u32 *) (data + 2 + 8 * j));
b.end = clib_net_to_host_u32 (*(u32 *) (data + 6 + 8 * j));
vec_add1 (to->sacks, b);
}
break;
default:
/* Nothing to see here */
continue;
}
}
return 0;
}
/**
* Write TCP options to segment.
*
* @param data buffer where to write the options
* @param opts options to write
* @return length of options written
*/
always_inline u32
tcp_options_write (u8 * data, tcp_options_t * opts)
{
u32 opts_len = 0;
u32 buf, seq_len = 4;
if (tcp_opts_mss (opts))
{
*data++ = TCP_OPTION_MSS;
*data++ = TCP_OPTION_LEN_MSS;
buf = clib_host_to_net_u16 (opts->mss);
clib_memcpy_fast (data, &buf, sizeof (opts->mss));
data += sizeof (opts->mss);
opts_len += TCP_OPTION_LEN_MSS;
}
if (tcp_opts_wscale (opts))
{
*data++ = TCP_OPTION_WINDOW_SCALE;
*data++ = TCP_OPTION_LEN_WINDOW_SCALE;
*data++ = opts->wscale;
opts_len += TCP_OPTION_LEN_WINDOW_SCALE;
}
if (tcp_opts_sack_permitted (opts))
{
*data++ = TCP_OPTION_SACK_PERMITTED;
*data++ = TCP_OPTION_LEN_SACK_PERMITTED;
opts_len += TCP_OPTION_LEN_SACK_PERMITTED;
}
if (tcp_opts_tstamp (opts))
{
*data++ = TCP_OPTION_TIMESTAMP;
*data++ = TCP_OPTION_LEN_TIMESTAMP;
buf = clib_host_to_net_u32 (opts->tsval);
clib_memcpy_fast (data, &buf, sizeof (opts->tsval));
data += sizeof (opts->tsval);
buf = clib_host_to_net_u32 (opts->tsecr);
clib_memcpy_fast (data, &buf, sizeof (opts->tsecr));
data += sizeof (opts->tsecr);
opts_len += TCP_OPTION_LEN_TIMESTAMP;
}
if (tcp_opts_sack (opts))
{
int i;
if (opts->n_sack_blocks != 0)
{
*data++ = TCP_OPTION_SACK_BLOCK;
*data++ = 2 + opts->n_sack_blocks * TCP_OPTION_LEN_SACK_BLOCK;
for (i = 0; i < opts->n_sack_blocks; i++)
{
buf = clib_host_to_net_u32 (opts->sacks[i].start);
clib_memcpy_fast (data, &buf, seq_len);
data += seq_len;
buf = clib_host_to_net_u32 (opts->sacks[i].end);
clib_memcpy_fast (data, &buf, seq_len);
data += seq_len;
}
opts_len += 2 + opts->n_sack_blocks * TCP_OPTION_LEN_SACK_BLOCK;
}
}
/* Terminate TCP options */
if (opts_len % 4)
{
*data++ = TCP_OPTION_EOL;
opts_len += TCP_OPTION_LEN_EOL;
}
/* Pad with zeroes to a u32 boundary */
while (opts_len % 4)
{
*data++ = TCP_OPTION_NOOP;
opts_len += TCP_OPTION_LEN_NOOP;
}
return opts_len;
}
#endif /* included_tcp_packet_h */
/*
File diff suppressed because it is too large Load Diff
+126
View File
@@ -0,0 +1,126 @@
/*
* Copyright (c) 2020 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef SRC_VNET_TCP_TCP_SACK_H_
#define SRC_VNET_TCP_TCP_SACK_H_
#include <vnet/tcp/tcp_types.h>
always_inline u32
scoreboard_hole_index (sack_scoreboard_t * sb, sack_scoreboard_hole_t * hole)
{
ASSERT (!pool_is_free_index (sb->holes, hole - sb->holes));
return hole - sb->holes;
}
always_inline u32
scoreboard_hole_bytes (sack_scoreboard_hole_t * hole)
{
return hole->end - hole->start;
}
always_inline sack_scoreboard_hole_t *
scoreboard_get_hole (sack_scoreboard_t * sb, u32 index)
{
if (index != TCP_INVALID_SACK_HOLE_INDEX)
return pool_elt_at_index (sb->holes, index);
return 0;
}
always_inline sack_scoreboard_hole_t *
scoreboard_next_hole (sack_scoreboard_t * sb, sack_scoreboard_hole_t * hole)
{
if (hole->next != TCP_INVALID_SACK_HOLE_INDEX)
return pool_elt_at_index (sb->holes, hole->next);
return 0;
}
always_inline sack_scoreboard_hole_t *
scoreboard_prev_hole (sack_scoreboard_t * sb, sack_scoreboard_hole_t * hole)
{
if (hole->prev != TCP_INVALID_SACK_HOLE_INDEX)
return pool_elt_at_index (sb->holes, hole->prev);
return 0;
}
always_inline sack_scoreboard_hole_t *
scoreboard_first_hole (sack_scoreboard_t * sb)
{
if (sb->head != TCP_INVALID_SACK_HOLE_INDEX)
return pool_elt_at_index (sb->holes, sb->head);
return 0;
}
always_inline sack_scoreboard_hole_t *
scoreboard_last_hole (sack_scoreboard_t * sb)
{
if (sb->tail != TCP_INVALID_SACK_HOLE_INDEX)
return pool_elt_at_index (sb->holes, sb->tail);
return 0;
}
#if TCP_SCOREBOARD_TRACE
#define tcp_scoreboard_trace_add(_tc, _ack) \
{ \
static u64 _group = 0; \
sack_scoreboard_t *_sb = &_tc->sack_sb; \
sack_block_t *_sack, *_sacks; \
scoreboard_trace_elt_t *_elt; \
int i; \
_group++; \
_sacks = _tc->rcv_opts.sacks; \
for (i = 0; i < vec_len (_sacks); i++) \
{ \
_sack = &_sacks[i]; \
vec_add2 (_sb->trace, _elt, 1); \
_elt->start = _sack->start; \
_elt->end = _sack->end; \
_elt->ack = _elt->end == _ack ? _ack : 0; \
_elt->snd_una_max = _elt->end == _ack ? _tc->snd_una_max : 0; \
_elt->group = _group; \
} \
}
#else
#define tcp_scoreboard_trace_add(_tc, _ack)
#endif
sack_scoreboard_hole_t *scoreboard_next_rxt_hole (sack_scoreboard_t * sb,
sack_scoreboard_hole_t *
start, u8 have_sent_1_smss,
u8 * can_rescue,
u8 * snd_limited);
void scoreboard_clear (sack_scoreboard_t * sb);
void scoreboard_clear_reneging (sack_scoreboard_t * sb, u32 start, u32 end);
void scoreboard_init (sack_scoreboard_t * sb);
void scoreboard_init_rxt (sack_scoreboard_t * sb, u32 snd_una);
format_function_t format_tcp_scoreboard;
/* Made public for unit testing only */
void tcp_update_sack_list (tcp_connection_t * tc, u32 start, u32 end);
u32 tcp_sack_list_bytes (tcp_connection_t * tc);
void tcp_rcv_sacks (tcp_connection_t * tc, u32 ack);
u8 *tcp_scoreboard_replay (u8 * s, tcp_connection_t * tc, u8 verbose);
u8 tcp_scoreboard_is_sane_post_recovery (tcp_connection_t * tc);
#endif /* SRC_VNET_TCP_TCP_SACK_H_ */
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/
File diff suppressed because it is too large Load Diff