summaryrefslogtreecommitdiffstats
path: root/src/vnet/tcp/tcp_output.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet/tcp/tcp_output.c')
-rw-r--r--src/vnet/tcp/tcp_output.c92
1 files changed, 40 insertions, 52 deletions
diff --git a/src/vnet/tcp/tcp_output.c b/src/vnet/tcp/tcp_output.c
index 1b9530b4e1a..69b34cc595f 100644
--- a/src/vnet/tcp/tcp_output.c
+++ b/src/vnet/tcp/tcp_output.c
@@ -690,78 +690,76 @@ tcp_enqueue_to_output (tcp_worker_ctx_t * wrk, vlib_buffer_t * b, u32 bi,
#endif /* CLIB_MARCH_VARIANT */
static int
-tcp_make_reset_in_place (vlib_main_t * vm, vlib_buffer_t * b0,
- tcp_state_t state, u8 thread_index, u8 is_ip4)
+tcp_make_reset_in_place (vlib_main_t * vm, vlib_buffer_t * b, u8 is_ip4)
{
ip4_header_t *ih4;
ip6_header_t *ih6;
- tcp_header_t *th0;
- ip4_address_t src_ip40, dst_ip40;
- ip6_address_t src_ip60, dst_ip60;
+ tcp_header_t *th;
+ ip4_address_t src_ip4, dst_ip4;
+ ip6_address_t src_ip6, dst_ip6;
u16 src_port, dst_port;
- u32 tmp;
- u32 seq, ack;
+ u32 tmp, len, seq, ack;
u8 flags;
/* Find IP and TCP headers */
- th0 = tcp_buffer_hdr (b0);
+ th = tcp_buffer_hdr (b);
/* Save src and dst ip */
if (is_ip4)
{
- ih4 = vlib_buffer_get_current (b0);
+ ih4 = vlib_buffer_get_current (b);
ASSERT ((ih4->ip_version_and_header_length & 0xF0) == 0x40);
- src_ip40.as_u32 = ih4->src_address.as_u32;
- dst_ip40.as_u32 = ih4->dst_address.as_u32;
+ src_ip4.as_u32 = ih4->src_address.as_u32;
+ dst_ip4.as_u32 = ih4->dst_address.as_u32;
}
else
{
- ih6 = vlib_buffer_get_current (b0);
+ ih6 = vlib_buffer_get_current (b);
ASSERT ((ih6->ip_version_traffic_class_and_flow_label & 0xF0) == 0x60);
- clib_memcpy_fast (&src_ip60, &ih6->src_address, sizeof (ip6_address_t));
- clib_memcpy_fast (&dst_ip60, &ih6->dst_address, sizeof (ip6_address_t));
+ clib_memcpy_fast (&src_ip6, &ih6->src_address, sizeof (ip6_address_t));
+ clib_memcpy_fast (&dst_ip6, &ih6->dst_address, sizeof (ip6_address_t));
}
- src_port = th0->src_port;
- dst_port = th0->dst_port;
+ src_port = th->src_port;
+ dst_port = th->dst_port;
+ flags = TCP_FLAG_RST;
- /* Try to determine what/why we're actually resetting */
- if (state == TCP_STATE_CLOSED)
+ /*
+ * RFC 793. If the ACK bit is off, sequence number zero is used,
+ * <SEQ=0><ACK=SEG.SEQ+SEG.LEN><CTL=RST,ACK>
+ * If the ACK bit is on,
+ * <SEQ=SEG.ACK><CTL=RST>
+ */
+ if (tcp_ack (th))
{
- if (!tcp_syn (th0))
- return -1;
-
- tmp = clib_net_to_host_u32 (th0->seq_number);
-
- /* Got a SYN for no listener. */
- flags = TCP_FLAG_RST | TCP_FLAG_ACK;
- ack = clib_host_to_net_u32 (tmp + 1);
- seq = 0;
+ seq = th->ack_number;
+ ack = 0;
}
else
{
- flags = TCP_FLAG_RST;
- seq = th0->ack_number;
- ack = 0;
+ flags |= TCP_FLAG_ACK;
+ tmp = clib_net_to_host_u32 (th->seq_number);
+ len = vnet_buffer (b)->tcp.data_len + tcp_is_syn (th) + tcp_is_fin (th);
+ ack = clib_host_to_net_u32 (tmp + len);
+ seq = 0;
}
- tcp_reuse_buffer (vm, b0);
- tcp_trajectory_add_start (b0, 4);
- th0 = vlib_buffer_push_tcp_net_order (b0, dst_port, src_port, seq, ack,
- sizeof (tcp_header_t), flags, 0);
+ tcp_reuse_buffer (vm, b);
+ tcp_trajectory_add_start (b, 4);
+ th = vlib_buffer_push_tcp_net_order (b, dst_port, src_port, seq, ack,
+ sizeof (tcp_header_t), flags, 0);
if (is_ip4)
{
- ih4 = vlib_buffer_push_ip4 (vm, b0, &dst_ip40, &src_ip40,
+ ih4 = vlib_buffer_push_ip4 (vm, b, &dst_ip4, &src_ip4,
IP_PROTOCOL_TCP, 1);
- th0->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ih4);
+ th->checksum = ip4_tcp_udp_compute_checksum (vm, b, ih4);
}
else
{
int bogus = ~0;
- ih6 = vlib_buffer_push_ip6 (vm, b0, &dst_ip60, &src_ip60,
- IP_PROTOCOL_TCP);
- th0->checksum = ip6_tcp_udp_icmp_compute_checksum (vm, b0, ih6, &bogus);
+ ih6 = vlib_buffer_push_ip6 (vm, b, &dst_ip6, &src_ip6, IP_PROTOCOL_TCP);
+ th->checksum = ip6_tcp_udp_icmp_compute_checksum (vm, b, ih6, &bogus);
ASSERT (!bogus);
}
@@ -2515,8 +2513,8 @@ static uword
tcp46_send_reset_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
vlib_frame_t * from_frame, u8 is_ip4)
{
+ u32 error0 = TCP_ERROR_RST_SENT, next0 = TCP_RESET_NEXT_IP_LOOKUP;
u32 n_left_from, next_index, *from, *to_next;
- u32 my_thread_index = vm->thread_index;
from = vlib_frame_vector_args (from_frame);
n_left_from = from_frame->n_vectors;
@@ -2531,11 +2529,10 @@ tcp46_send_reset_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
while (n_left_from > 0 && n_left_to_next > 0)
{
- u32 bi0;
vlib_buffer_t *b0;
tcp_tx_trace_t *t0;
tcp_header_t *th0;
- u32 error0 = TCP_ERROR_RST_SENT, next0 = TCP_RESET_NEXT_IP_LOOKUP;
+ u32 bi0;
bi0 = from[0];
to_next[0] = bi0;
@@ -2545,20 +2542,11 @@ tcp46_send_reset_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
n_left_to_next -= 1;
b0 = vlib_get_buffer (vm, bi0);
-
- if (tcp_make_reset_in_place (vm, b0, vnet_buffer (b0)->tcp.flags,
- my_thread_index, is_ip4))
- {
- error0 = TCP_ERROR_LOOKUP_DROPS;
- next0 = TCP_RESET_NEXT_DROP;
- goto done;
- }
+ tcp_make_reset_in_place (vm, b0, is_ip4);
/* Prepare to send to IP lookup */
vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0;
- next0 = TCP_RESET_NEXT_IP_LOOKUP;
- done:
b0->error = node->errors[error0];
b0->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))