diff options
Diffstat (limited to 'common/VIL/conntrack/rte_ct_tcp.h')
-rw-r--r-- | common/VIL/conntrack/rte_ct_tcp.h | 484 |
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 */ |