18b52a31eSHanoh Haim#ifndef  NAT_CHECK_H
28b52a31eSHanoh Haim#define  NAT_CHECK_H
38b52a31eSHanoh Haim/*
48b52a31eSHanoh Haim Hanoh Haim
58b52a31eSHanoh Haim Cisco Systems, Inc.
68b52a31eSHanoh Haim*/
78b52a31eSHanoh Haim
88b52a31eSHanoh Haim/*
98b52a31eSHanoh HaimCopyright (c) 2015-2015 Cisco Systems, Inc.
108b52a31eSHanoh Haim
118b52a31eSHanoh HaimLicensed under the Apache License, Version 2.0 (the "License");
128b52a31eSHanoh Haimyou may not use this file except in compliance with the License.
138b52a31eSHanoh HaimYou may obtain a copy of the License at
148b52a31eSHanoh Haim
158b52a31eSHanoh Haim    http://www.apache.org/licenses/LICENSE-2.0
168b52a31eSHanoh Haim
178b52a31eSHanoh HaimUnless required by applicable law or agreed to in writing, software
188b52a31eSHanoh Haimdistributed under the License is distributed on an "AS IS" BASIS,
198b52a31eSHanoh HaimWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
208b52a31eSHanoh HaimSee the License for the specific language governing permissions and
218b52a31eSHanoh Haimlimitations under the License.
228b52a31eSHanoh Haim*/
238b52a31eSHanoh Haim
24cc5cc563SIdo Barnea#include <map>
258b52a31eSHanoh Haim#include "msg_manager.h"
268b52a31eSHanoh Haim#include <common/Network/Packet/TcpHeader.h>
278b52a31eSHanoh Haim#include <common/Network/Packet/UdpHeader.h>
288b52a31eSHanoh Haim#include <common/Network/Packet/IPHeader.h>
298b52a31eSHanoh Haim#include <common/Network/Packet/IPv6Header.h>
308b52a31eSHanoh Haim#include <common/Network/Packet/EthernetHeader.h>
3162623efcSIdo Barnea#include "os_time.h"
327b9d1088SIdo Barnea#include "nat_check_flow_table.h"
338b52a31eSHanoh Haim
348b52a31eSHanoh Haim// 2msec timeout
358b52a31eSHanoh Haim#define MAX_TIME_MSG_IN_QUEUE_SEC  ( 0.002 )
36e528048bSIdo Barnea#define NAT_FLOW_ID_MASK_TCP_ACK 0x00ffffff
37e528048bSIdo Barnea#define NAT_FLOW_ID_MASK_IP_ID   0x000001ff
3862623efcSIdo Barnea
3962623efcSIdo Barneaclass  CNatOption {
4062623efcSIdo Barneapublic:
4162623efcSIdo Barnea    enum {
4262623efcSIdo Barnea        noIPV4_OPTION   = 0x10, /* dummy IPV4 option */
4362623efcSIdo Barnea        noOPTION_LEN    = 0x8,
4462623efcSIdo Barnea        noIPV4_MAGIC    = 0xEE,
4562623efcSIdo Barnea        noIPV4_MAGIC_RX    = 0xED,
4662623efcSIdo Barnea
4762623efcSIdo Barnea        noIPV6_OPTION_LEN    = (noOPTION_LEN/8)-1,
4862623efcSIdo Barnea        noIPV6_OPTION = 0x3C, /*IPv6-Opts	Destination Options for IPv6	RFC 2460*/
4962623efcSIdo Barnea    };
5062623efcSIdo Barnea
5162623efcSIdo Barnea    void set_option_type(uint8_t id) {
5262623efcSIdo Barnea        u.m_data[0 ] =id;
5362623efcSIdo Barnea    }
5462623efcSIdo Barnea
5562623efcSIdo Barnea    uint8_t get_option_type() {
5662623efcSIdo Barnea        return (u.m_data[0]);
5762623efcSIdo Barnea    }
5862623efcSIdo Barnea
5962623efcSIdo Barnea    void set_option_len(uint8_t len) {
6062623efcSIdo Barnea        u.m_data[1] = len;
6162623efcSIdo Barnea    }
6262623efcSIdo Barnea    uint8_t get_option_len(){
6362623efcSIdo Barnea        return ( u.m_data[1]);
6462623efcSIdo Barnea    }
6562623efcSIdo Barnea
6662623efcSIdo Barnea    void set_thread_id(uint8_t thread_id) {
6762623efcSIdo Barnea        u.m_data[3] = thread_id;
6862623efcSIdo Barnea    }
6962623efcSIdo Barnea
7062623efcSIdo Barnea    uint8_t get_thread_id() {
7162623efcSIdo Barnea        return (u.m_data[3]);
7262623efcSIdo Barnea    }
7362623efcSIdo Barnea
7462623efcSIdo Barnea    void set_magic(uint8_t magic){
7562623efcSIdo Barnea        u.m_data[2] = magic;
7662623efcSIdo Barnea    }
7762623efcSIdo Barnea
7862623efcSIdo Barnea    uint8_t get_magic(){
7962623efcSIdo Barnea        return (u.m_data[2]);
8062623efcSIdo Barnea    }
8162623efcSIdo Barnea
82e528048bSIdo Barnea    // Used when doing NAT using IP option
8362623efcSIdo Barnea    void set_fid(uint32_t fid) {
84e528048bSIdo Barnea        u.m_data_uint32[1] = fid & NAT_FLOW_ID_MASK_TCP_ACK;
8562623efcSIdo Barnea    }
8662623efcSIdo Barnea
8762623efcSIdo Barnea    uint32_t get_fid() {
8862623efcSIdo Barnea        return (u.m_data_uint32[1]);
8962623efcSIdo Barnea    }
9062623efcSIdo Barnea
9162623efcSIdo Barnea    bool is_valid_ipv4_magic_op0(void){
9262623efcSIdo Barnea        return ( ( PKT_NTOHL( u.m_data_uint32[0] )& 0xFFFFFF00 ) ==
9362623efcSIdo Barnea                 (CNatOption::noIPV4_OPTION <<24) +  (CNatOption::noOPTION_LEN<<16) + (CNatOption::noIPV4_MAGIC<<8) ?true:false);
9462623efcSIdo Barnea    }
9562623efcSIdo Barnea
9662623efcSIdo Barnea    bool is_valid_ipv4_magic(void) {
9762623efcSIdo Barnea        return (is_valid_ipv4_magic_op0());
9862623efcSIdo Barnea    }
9962623efcSIdo Barnea
10062623efcSIdo Barnea    bool is_valid_ipv6_magic(void) {
10162623efcSIdo Barnea        return ( ( PKT_NTOHL( u.m_data_uint32[0] )& 0x00FFFF00 ) ==
10262623efcSIdo Barnea                 (CNatOption::noIPV6_OPTION_LEN<<16) + (CNatOption::noIPV4_MAGIC<<8) ?true:false);
10362623efcSIdo Barnea
10462623efcSIdo Barnea    }
10562623efcSIdo Barnea
10662623efcSIdo Barnea    void set_init_ipv4_header() {
10762623efcSIdo Barnea        set_option_type(CNatOption::noIPV4_OPTION);
10862623efcSIdo Barnea        set_option_len(CNatOption::noOPTION_LEN);
10962623efcSIdo Barnea        set_magic(CNatOption::noIPV4_MAGIC);
11062623efcSIdo Barnea    }
11162623efcSIdo Barnea
11262623efcSIdo Barnea    void set_init_ipv6_header(void){
11362623efcSIdo Barnea        set_option_len(noIPV6_OPTION_LEN);
11462623efcSIdo Barnea        set_magic(CNatOption::noIPV4_MAGIC);
11562623efcSIdo Barnea    }
11662623efcSIdo Barnea
11762623efcSIdo Barnea    void dump(FILE *fd);
11862623efcSIdo Barnea
11962623efcSIdo Barneaprivate:
12062623efcSIdo Barnea    union u_ {
12162623efcSIdo Barnea        uint8_t  m_data[8];
12262623efcSIdo Barnea        uint32_t m_data_uint32[2];
12362623efcSIdo Barnea    } u;
12462623efcSIdo Barnea};
1258b52a31eSHanoh Haim
1268b52a31eSHanoh Haimstruct CNatFlowInfo {
1278b52a31eSHanoh Haim    uint32_t m_external_ip;
128cc5cc563SIdo Barnea    uint32_t m_tcp_seq;
1298b52a31eSHanoh Haim    uint32_t m_fid;
1308b52a31eSHanoh Haim    uint16_t m_external_port;
1318b52a31eSHanoh Haim    uint16_t m_pad;
1328b52a31eSHanoh Haim};
1338b52a31eSHanoh Haim
1348b52a31eSHanoh Haim#if __x86_64__
1358b52a31eSHanoh Haim/* size of 64 bytes */
1368b52a31eSHanoh Haim    #define MAX_NAT_FLOW_INFO (7)
1378b52a31eSHanoh Haim    #define MAX_PKT_MSG_INFO  (26)
1388b52a31eSHanoh Haim#else
1398b52a31eSHanoh Haim    #define MAX_NAT_FLOW_INFO (8)
1408b52a31eSHanoh Haim    #define MAX_PKT_MSG_INFO  (30)
1418b52a31eSHanoh Haim#endif
1428b52a31eSHanoh Haim
1438b52a31eSHanoh Haim/*
1448b52a31eSHanoh Haim     !!!   WARNING  - CGenNodeNatInfo !!
1458b52a31eSHanoh Haim
1468b52a31eSHanoh Haim this struct should be in the same size of CGenNode beacuse allocator is global .
1478b52a31eSHanoh Haim
1488b52a31eSHanoh Haim*/
14962623efcSIdo Barneastruct CGenNodeNatInfo : public CGenNodeMsgBase {
1508b52a31eSHanoh Haim    uint8_t       m_pad;
1518b52a31eSHanoh Haim    uint16_t      m_cnt;
1528b52a31eSHanoh Haim    //uint32_t      m_pad2;
15362623efcSIdo Barnea #if __x86_64__
1548b52a31eSHanoh Haim    uint32_t      m_pad3;
15562623efcSIdo Barnea #endif
1568b52a31eSHanoh Haim    CNatFlowInfo  m_data[MAX_NAT_FLOW_INFO];
157eae78d43SHanoh Haim    uint64_t      m_pad4[8];
1588b52a31eSHanoh Haim
1598b52a31eSHanoh Haimpublic:
16062623efcSIdo Barnea      CNatFlowInfo * get_next_msg() {
1618b52a31eSHanoh Haim          CNatFlowInfo * lp=&m_data[m_cnt];
1628b52a31eSHanoh Haim          m_cnt++;
1638b52a31eSHanoh Haim          return (lp);
1648b52a31eSHanoh Haim      }
1658b52a31eSHanoh Haim
1668b52a31eSHanoh Haim      void init();
1678b52a31eSHanoh Haim
1688b52a31eSHanoh Haim      bool is_full(){
1698b52a31eSHanoh Haim          return (m_cnt==MAX_NAT_FLOW_INFO?true:false);
1708b52a31eSHanoh Haim      }
1718b52a31eSHanoh Haim      void dump(FILE *fd);
1728b52a31eSHanoh Haim};
1738b52a31eSHanoh Haim
17462623efcSIdo Barneastruct CGenNodeLatencyPktInfo : public CGenNodeMsgBase {
1758b52a31eSHanoh Haim    uint8_t       m_dir;
1768b52a31eSHanoh Haim    uint16_t      m_latency_offset;
178abc0cb87Simarom    uint8_t       m_update_ts;
179abc0cb87Simarom    uint8_t       m_pad3[3];
181abc0cb87Simarom    struct rte_mbuf *m_pkt;
1828b52a31eSHanoh Haim
1838b52a31eSHanoh Haim    uint32_t      m_pad4[MAX_PKT_MSG_INFO];
184eae78d43SHanoh Haim    uint64_t      m_pad5[8];
1858b52a31eSHanoh Haim};
1868b52a31eSHanoh Haim
1878b52a31eSHanoh Haim
1888b52a31eSHanoh Haim/* per thread ring info for NAT messages
1898b52a31eSHanoh Haim   try to put as many messages  */
1908b52a31eSHanoh Haimclass CNatPerThreadInfo {
1918b52a31eSHanoh Haimpublic:
19262623efcSIdo Barnea    CNatPerThreadInfo() {
1938b52a31eSHanoh Haim        m_last_time=0;
1948b52a31eSHanoh Haim        m_cur_nat_msg=0;
1958b52a31eSHanoh Haim        m_ring=0;
1968b52a31eSHanoh Haim    }
1978b52a31eSHanoh Haimpublic:
1988b52a31eSHanoh Haim    dsec_t            m_last_time;
1998b52a31eSHanoh Haim    CGenNodeNatInfo * m_cur_nat_msg;
2008b52a31eSHanoh Haim    CNodeRing       * m_ring;
2018b52a31eSHanoh Haim};
2028b52a31eSHanoh Haim
2038b52a31eSHanoh Haim
2048b52a31eSHanoh Haimclass CNatStats {
2058b52a31eSHanoh Haimpublic:
2068b52a31eSHanoh Haim    uint64_t  m_total_rx;
2078b52a31eSHanoh Haim    uint64_t  m_total_msg;
2088b52a31eSHanoh Haim    /* errors */
2098b52a31eSHanoh Haim    uint64_t  m_err_no_valid_thread_id;
2108b52a31eSHanoh Haim    uint64_t  m_err_no_valid_proto;
2118b52a31eSHanoh Haim    uint64_t  m_err_queue_full;
2128b52a31eSHanoh Haimpublic:
21362623efcSIdo Barnea    void reset();
2148b52a31eSHanoh Haim    uint64_t get_errs(){
2158b52a31eSHanoh Haim        return  (m_err_no_valid_thread_id+m_err_no_valid_proto+m_err_queue_full);
2168b52a31eSHanoh Haim    }
2178b52a31eSHanoh Haim    void Dump(FILE *fd);
2188b52a31eSHanoh Haim};
2198b52a31eSHanoh Haim
2208b52a31eSHanoh Haimclass CNatRxManager {
2218b52a31eSHanoh Haim
2228b52a31eSHanoh Haimpublic:
2238b52a31eSHanoh Haim    bool Create();
2248b52a31eSHanoh Haim    void Delete();
225cc5cc563SIdo Barnea    void handle_packet_ipv4(CNatOption * option, IPHeader * ipv4, bool is_first);
2268b52a31eSHanoh Haim    void handle_aging();
22762623efcSIdo Barnea    void Dump(FILE *fd);
2288b52a31eSHanoh Haim    void DumpShort(FILE *fd);
22962623efcSIdo Barnea    static inline uint32_t calc_tcp_ack_val(uint32_t fid, uint8_t thread_id) {
230e528048bSIdo Barnea        return ((fid &  NAT_FLOW_ID_MASK_TCP_ACK) << 8) | thread_id;
231e528048bSIdo Barnea    }
232e528048bSIdo Barnea    static inline uint16_t calc_ip_id_val(uint32_t fid, uint8_t thread_id) {
233e528048bSIdo Barnea        // MSB bit == 1 signals this is latency packet
234e528048bSIdo Barnea        return ((fid &  NAT_FLOW_ID_MASK_IP_ID) << 6) | (thread_id & 0x3f) | 0x8000;
23562623efcSIdo Barnea    }
23662623efcSIdo Barnea    void get_info_from_tcp_ack(uint32_t tcp_ack, uint32_t &fid, uint8_t &thread_id);
237e528048bSIdo Barnea    void get_info_from_ip_id(uint16_t ip_id, uint32_t &fid, uint8_t &thread_id);
2388b52a31eSHanoh Haimprivate:
2398b52a31eSHanoh Haim    CNatPerThreadInfo * get_thread_info(uint8_t thread_id);
2408b52a31eSHanoh Haim    void flush_node(CNatPerThreadInfo * thread_info);
2418b52a31eSHanoh Haim
2428b52a31eSHanoh Haimprivate:
2438b52a31eSHanoh Haim    uint8_t               m_max_threads;
2448b52a31eSHanoh Haim    CNatPerThreadInfo   * m_per_thread;
2458b52a31eSHanoh Haim    CNatStats             m_stats;
2467b9d1088SIdo Barnea    CNatCheckFlowTable    m_ft;
2478b52a31eSHanoh Haim};
2488b52a31eSHanoh Haim
2498b52a31eSHanoh Haim
2508b52a31eSHanoh Haim#endif