summaryrefslogtreecommitdiffstats
path: root/common/VIL/conntrack/rte_ct_tcp.h
diff options
context:
space:
mode:
Diffstat (limited to 'common/VIL/conntrack/rte_ct_tcp.h')
-rw-r--r--common/VIL/conntrack/rte_ct_tcp.h484
1 files changed, 484 insertions, 0 deletions
diff --git a/common/VIL/conntrack/rte_ct_tcp.h b/common/VIL/conntrack/rte_ct_tcp.h
new file mode 100644
index 00000000..391200c6
--- /dev/null
+++ b/common/VIL/conntrack/rte_ct_tcp.h
@@ -0,0 +1,484 @@
+/*
+// Copyright (c) 2017 Intel Corporation
+//
+// 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 __INCLUDE_RTE_CT_TCP_H__
+#define __INCLUDE_RTE_CT_TCP_H__
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include <rte_tcp.h>
+#include <rte_port.h>
+#include <rte_timer.h>
+#include <rte_ip.h>
+#include <rte_tcp.h>
+#include <rte_udp.h>
+#include <rte_port.h>
+#include <rte_byteorder.h>
+#include "rte_cnxn_tracking.h"
+
+/* AN INNER, PRIVATE INTERFACE FOR RTE_CNXN_TRACKING */
+
+/* constants for TCP options */
+
+#define RTE_CT_TCPOPT_EOL 0 /* End of options */
+#define RTE_CT_TCPOPT_NOP 1 /* Padding */
+#define RTE_CT_TCPOPT_MSS 2 /* Segment size negotiating */
+#define RTE_CT_TCPOPT_WINDOW 3 /* Window scaling */
+#define RTE_CT_TCPOPT_SACK_PERM 4 /* SACK Permitted */
+#define RTE_CT_TCPOPT_SACK 5 /* SACK Block */
+#define RTE_CT_TCPOPT_TIMESTAMP 8 /* RTT estimations */
+
+#define RTE_CT_TCPOLEN_MSS 4
+#define RTE_CT_TCPOLEN_WINDOW 3
+#define RTE_CT_TCPOLEN_SACK_PERM 2
+#define RTE_CT_TCPOLEN_TIMESTAMP 10
+#define RTE_CT_TCPOLEN_PER_SACK_ENTRY 8
+
+#define RTE_CT_TCPOLEN_MSS_ALIGNED 4
+#define RTE_CT_TCPOLEN_WINDOW_ALIGNED 4
+#define RTE_CT_TCPOLEN_SACK_PERM_ALIGNED 4
+#define RTE_CT_TCPOLEN_TIMESTAMP_ALIGNED 12
+
+#define RTE_CT_MAX_TCP_WINDOW_SCALE 14
+
+#define RTE_SP_OPTIONS_MSS 1
+#define RTE_SP_OPTIONS_WINDOW_SCALE 2
+#define RTE_SP_OPTIONS_TIMESTAMP 4
+#define RTE_SP_OPTIONS_SACK_PERM 8
+
+
+enum rte_ct_packet_action {
+ RTE_CT_OPEN_CONNECTION,
+ RTE_CT_DROP_PACKET,
+ RTE_CT_FORWARD_PACKET,
+ RTE_CT_DESTROY_CNXN_AND_FORWARD_PACKET,
+ RTE_CT_REOPEN_CNXN_AND_FORWARD_PACKET,
+ RTE_CT_SEND_CLIENT_SYNACK,
+ RTE_CT_SEND_SERVER_SYN,
+ RTE_CT_SEND_SERVER_ACK,
+ RTE_CT_HIJACK
+};
+
+enum rte_ct_connstatus {
+ RTE_INIT_CONN,
+ RTE_SEEN_REPLY_CONN,
+ RTE_ASSURED_CONN
+};
+
+/* TCP tracking. */
+
+static const char *const rte_ct_tcp_names[] = {
+ "NONE",
+ "SYN_SENT",
+ "SYN_RECV",
+ "ESTABLISHED",
+ "FIN_WAIT",
+ "CLOSE_WAIT",
+ "LAST_ACK",
+ "TIME_WAIT",
+ "CLOSE",
+ "SYN_SENT2",
+ "RETRANS",
+ "UNACK",
+ "IGNORE"
+};
+
+static const char *const rte_ct_udp_names[] = {
+ "NONE_UDP",
+ "UNREPLIED",
+ "REPLIED"
+};
+
+/* Fixme: what about big packets? */
+#define RTE_MAX_ACKWIN_CONST 66000
+
+/* Window scaling is advertised by the sender */
+#define RTE_CT_TCP_FLAG_WINDOW_SCALE 0x01
+
+/* SACK is permitted by the sender */
+#define RTE_CT_TCP_FLAG_SACK_PERM 0x02
+
+/* This sender sent FIN first */
+#define RTE_CT_TCP_FLAG_CLOSE_INIT 0x04
+
+/* Be liberal in window checking */
+#define RTE_CT_TCP_FLAG_BE_LIBERAL 0x08
+
+/* Has unacknowledged data */
+#define RTE_CT_TCP_FLAG_DATA_UNACKNOWLEDGED 0x10
+
+/* The field td_maxack has been set */
+#define RTE_CT_TCP_FLAG_MAXACK_SET 0x20
+/* Marks possibility for expected RFC5961 challenge ACK */
+#define RTE_CT_EXP_CHALLENGE_ACK 0x40
+
+
+
+/* TCP header flags of interest */
+#define RTE_CT_TCPHDR_FIN 0x01
+#define RTE_CT_TCPHDR_SYN 0x02
+#define RTE_CT_TCPHDR_RST 0x04
+#define RTE_CT_TCPHDR_ACK 0x10
+
+#define RTE_CT_TCPHDR_RST_ACK (RTE_CT_TCPHDR_RST | RTE_CT_TCPHDR_ACK)
+
+
+
+/* state machine values. Note that order is important as relative checks made */
+enum rte_ct_tcp_states {
+ RTE_CT_TCP_NONE,
+ RTE_CT_TCP_SYN_SENT,
+ RTE_CT_TCP_SYN_RECV,
+ RTE_CT_TCP_ESTABLISHED,
+ RTE_CT_TCP_FIN_WAIT,
+ RTE_CT_TCP_CLOSE_WAIT,
+ RTE_CT_TCP_LAST_ACK,
+ RTE_CT_TCP_TIME_WAIT,
+ RTE_CT_TCP_CLOSE,
+ RTE_CT_TCP_SYN_SENT_2,
+ RTE_CT_TCP_RETRANS,
+ RTE_CT_TCP_UNACK,
+ RTE_CT_TCP_IGNORE
+};
+
+enum rte_ct_udp_states {
+ RTE_CT_UDP_NONE,
+ RTE_CT_UDP_UNREPLIED,
+ RTE_CT_UDP_REPLIED,
+ RTE_CT_UDP_MAX
+};
+
+
+
+#define RTE_CT_TCP_MAX RTE_CT_TCP_UNACK
+
+enum rte_ct_pkt_direction {
+ RTE_CT_DIR_ORIGINAL,
+ RTE_CT_DIR_REPLY
+};
+
+struct rte_ct_tcp_state {
+ uint32_t end; /* max of seq + len */
+ uint32_t maxend; /* max of ack + max(win, 1) */
+ uint32_t maxwin; /* max(win) */
+ uint32_t maxack; /* max of ack */
+ uint8_t scale; /* window scale factor */
+ uint8_t flags; /* per direction options */
+};
+
+struct rte_synproxy_options {
+ uint8_t options;
+ uint8_t window_scale;
+ uint16_t mss;
+ uint32_t ts_val;
+ uint32_t ts_echo_reply;
+ uint16_t initial_window;
+};
+
+struct ct_sp_cnxn_data {
+ /* buffer client pkt while waiting on server setup,
+ * store in reverse order
+ */
+ struct rte_mbuf *buffered_pkt_list;
+ uint32_t original_spoofed_seq;
+ /* difference between spoofed and real seq from server */
+ uint32_t seq_diff;
+ struct rte_synproxy_options cnxn_options;
+ /* non-zero if this connection created using synproxy */
+ uint8_t synproxied;
+ bool half_established;
+ /* non-zero after both half-connections established */
+ bool cnxn_established;
+};
+
+struct rte_ct_tcp {
+ struct rte_ct_tcp_state seen[2]; /* connection parms per direction */
+ uint8_t state;
+ uint8_t last_dir; /* Direction of the last packet
+ * (TODO: enum ip_conntrack_dir)
+ */
+ uint8_t retrans; /* Number of retransmitted packets */
+ uint8_t last_index; /* Index of the last packet */
+ uint32_t last_seq; /* Last seq number seen in dir */
+ uint32_t last_ack; /* Last seq number seen opposite dir */
+ uint32_t last_end; /* Last seq + len */
+ uint16_t last_win; /* Last window seen in dir */
+ /* For SYN packets while we may be out-of-sync */
+ uint8_t last_wscale; /* Last window scaling factor seen */
+ uint8_t last_flags; /* Last flags set */
+};
+
+/*
+ * rte_ct_cnxn_counters holds all the connection-specicif counters.
+ * TODO: Make available in public interface
+ */
+
+struct rte_ct_cnxn_counters {
+ uint64_t packets_received;//Added for CT-NAT
+ uint64_t packets_forwarded;
+ uint64_t packets_dropped;
+};
+
+struct rte_ct_proto {
+ struct rte_ct_tcp tcp_ct_data; /* TCP specific data fields*/
+ struct ct_sp_cnxn_data synproxy_data;
+};
+
+
+/*
+ * rte_ct_cnxn_data contains all the data for a TCP connection. This include
+ * state data as necessary for verifying the validity of TCP packets. In
+ * addition, it holds data necessary for implementing the TCP timers.
+ */
+
+struct rte_ct_cnxn_data {
+ /* The timer will be kept as part of the cnxn_data. When it fires, the
+ * pointer to the timer can be cast as the pointer to the cnxn_data
+ */
+ struct rte_timer timer; /* !!!!! IMPORTANT: Keep as first field !!!!! */
+
+ struct rte_ct_cnxn_counters counters;
+
+ /* full key stored here to allow the timer to remove the connection */
+ /* TODO: Consider storing key signature as well to speed up deletions.*/
+ uint32_t key[10];
+
+ struct rte_ct_proto ct_protocol;
+
+ /* the 100 ms timing step that a packet was seen for connection */
+ uint64_t expected_timeout;
+
+ /* Abstract states also used for timer values, e.g. RTE_CT_TCP_UNACK*/
+ uint8_t state_used_for_timer;
+
+ /* used to compute the "direction" of the packet */
+ uint8_t key_is_client_order;
+ uint8_t connstatus;
+ uint8_t protocol;
+ /* used to store the type of packet ipv4 or ipv6 */
+ uint8_t type;
+ //#ifdef FTP_ALG
+ // Bypass flag to indicate that ALG checking is no more needed;
+ uint8_t alg_bypass_flag;
+ // Can we use key_is_client_order for direction checking
+ uint8_t server_direction;
+ int16_t tcpSeqdiff;
+ // PORT = 0, PASV = 1
+ uint8_t ftp_session_type;
+ uint32_t tcp_payload_size;
+ int16_t seq_client;
+ int16_t ack_client;
+ int16_t seq_server;
+ int16_t ack_server;
+ //#endif
+} __rte_cache_aligned;
+
+
+#define RTE_CT_TCP_MAX_RETRANS 3
+
+struct rte_ct_tcptimeout {
+ /* a table of timeouts for each state of TCP */
+ uint64_t tcp_timeouts[RTE_CT_TCP_MAX + 1];
+};
+
+
+struct rte_ct_misc_options {
+ uint8_t synproxy_enabled;
+ uint32_t tcp_loose;
+ uint32_t tcp_be_liberal;
+ uint32_t tcp_max_retrans;
+};
+
+struct rte_ct_udptimeout {
+ uint64_t udp_timeouts[RTE_CT_UDP_MAX + 1];
+};
+
+struct rte_ct_timeout {
+ struct rte_ct_tcptimeout tcptimeout;
+ struct rte_ct_udptimeout udptimeout;
+};
+
+struct rte_ct_cnxn_tracker {
+ struct rte_hash *rhash;
+
+ /*
+ * Data for bulk hash lookup. Use this memory as temporary space.
+ * Too big for stack (64*16 bytes)
+ */
+ uint32_t hash_keys[RTE_HASH_LOOKUP_BULK_MAX][10];
+
+ /* table of pointers to above, for bulk hash lookup */
+ void *hash_key_ptrs[RTE_HASH_LOOKUP_BULK_MAX];
+ #ifdef CT_CGNAT
+ uint32_t positions[RTE_HASH_LOOKUP_BULK_MAX];/*added for ALG*/
+ #endif
+ /* hash table and timer storage */
+ uint32_t num_cnxn_entries;
+
+ /*
+ * pointer to data space used for hash table, "num_cnxn_entries" long.
+ * Memory allocated during initialization.
+ */
+ struct rte_ct_cnxn_data *hash_table_entries;
+ struct rte_CT_counter_block *counters;
+
+ uint64_t hertz;
+ uint64_t timing_cycles_per_timing_step;
+ uint64_t timing_100ms_steps;
+ uint64_t timing_100ms_steps_previous;
+ uint64_t timing_last_time;
+ struct rte_ct_timeout ct_timeout;
+ struct rte_ct_misc_options misc_options;
+
+ char name[16];
+ struct rte_ct_cnxn_data *new_connections[64];
+ struct rte_mbuf *buffered_pkt_list;
+ int latest_connection;
+ /* offset into mbuf where synnproxy can store a pointer */
+ uint16_t pointer_offset;
+} __rte_cache_aligned;
+
+/*
+ * Returns a value stating if this is a valid TCP open connection attempt.
+ * If valid, updates cnxn with any data fields it need to save.
+ */
+
+enum rte_ct_packet_action
+rte_ct_tcp_new_connection(
+ struct rte_ct_cnxn_tracker *inst,
+ struct rte_ct_cnxn_data *cnxn,
+ struct rte_mbuf *pkt,
+ int use_synproxy,
+ uint8_t ip_hdr_size);
+
+/*
+* Returns a value stating if this is a valid TCP packet for the give connection.
+* If valid, updates cnxn with any data fields it need to save.
+*/
+
+enum rte_ct_packet_action
+rte_ct_verify_tcp_packet(
+ struct rte_ct_cnxn_tracker *inst,
+ struct rte_ct_cnxn_data *cnxn,
+ struct rte_mbuf *pkt,
+ uint8_t key_was_flipped,
+ uint8_t ip_hdr_size);
+
+/*
+* Returns a value stating if this is a valid UDP open connection attempt.
+* If valid, updates cnxn with any data fields it need to save.
+*/
+
+uint8_t
+rte_ct_udp_new_connection(
+ struct rte_ct_cnxn_tracker *ct,
+ struct rte_ct_cnxn_data *cd,
+ struct rte_mbuf *pkt);
+
+/*
+* Returns a value stating if this is a valid UDP packet for the give connection.
+* If valid, updates cnxn with any data fields it need to save.
+*/
+
+enum rte_ct_packet_action
+rte_ct_udp_packet(
+ struct rte_ct_cnxn_tracker *ct,
+ struct rte_ct_cnxn_data *cd,
+ struct rte_mbuf *pkt,
+ uint8_t key_was_flipped);
+
+
+/*
+ * For the given connection, set a timeout based on the given state. If the
+ * timer is already set, this call will reset the timer with a new value.
+ */
+
+void
+rte_ct_set_cnxn_timer_for_tcp(
+ struct rte_ct_cnxn_tracker *ct,
+ struct rte_ct_cnxn_data *cd,
+ uint8_t tcp_state);
+
+void
+rte_ct_set_cnxn_timer_for_udp(
+ struct rte_ct_cnxn_tracker *ct,
+ struct rte_ct_cnxn_data *cd,
+ uint8_t tcp_state);
+
+/* Cancel timer associated with the connection. Safe to call if no timer set.*/
+void rte_ct_cancel_cnxn_timer(struct rte_ct_cnxn_data *cd);
+
+
+/*
+ * SYNPROXY related routines. Detailed comments are available in
+ * rte_ct_synproxy.c where they are implemented.
+ */
+
+
+/* these 3 routines convert a received packet to a different one */
+
+void
+rte_sp_cvt_to_spoofed_client_synack(struct rte_ct_cnxn_data *cd,
+ struct rte_mbuf *old_pkt);
+
+void
+rte_sp_cvt_to_spoofed_server_syn(struct rte_ct_cnxn_data *cd,
+ struct rte_mbuf *old_pkt);
+
+void
+rte_sp_cvt_to_spoofed_server_ack(struct rte_ct_cnxn_data *cd,
+ struct rte_mbuf *old_pkt);
+
+/* These two routines adjust seq or ack numbers,
+ * as part of the proxy mechanism
+ */
+
+void
+rte_sp_adjust_client_ack_before_window_check(
+ struct rte_ct_cnxn_data *cd,
+ void *i_hdr,
+ struct tcp_hdr *thdr,
+ enum rte_ct_pkt_direction dir);
+
+void
+rte_sp_adjust_server_seq_after_window_check(
+ struct rte_ct_cnxn_data *cd,
+ void *i_hdr,
+ struct tcp_hdr *thdr,
+ enum rte_ct_pkt_direction dir);
+
+
+
+/* parse tcp options and save in t_opts */
+void
+rte_sp_parse_options(struct rte_mbuf *pkt, struct rte_ct_cnxn_data *cd);
+
+
+/* these two routines deal with packet buffering */
+
+void
+rte_ct_buffer_packet(
+ struct rte_ct_cnxn_tracker *ct,
+ struct rte_ct_cnxn_data *cd,
+ struct rte_mbuf *pkt);
+
+void
+ rte_ct_release_buffered_packets(
+ struct rte_ct_cnxn_tracker *ct,
+ struct rte_ct_cnxn_data *cd);
+
+#endif /* TCPCONNTRACK_H */