nat_check.h revision abc0cb87
1#ifndef  NAT_CHECK_H
2#define  NAT_CHECK_H
3/*
4 Hanoh Haim
5 Cisco Systems, Inc.
6*/
7
8/*
9Copyright (c) 2015-2015 Cisco Systems, Inc.
10
11Licensed under the Apache License, Version 2.0 (the "License");
12you may not use this file except in compliance with the License.
13You may obtain a copy of the License at
14
15    http://www.apache.org/licenses/LICENSE-2.0
16
17Unless required by applicable law or agreed to in writing, software
18distributed under the License is distributed on an "AS IS" BASIS,
19WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20See the License for the specific language governing permissions and
21limitations under the License.
22*/
23
24#include <map>
25#include "msg_manager.h"
26#include <common/Network/Packet/TcpHeader.h>
27#include <common/Network/Packet/UdpHeader.h>
28#include <common/Network/Packet/IPHeader.h>
29#include <common/Network/Packet/IPv6Header.h>
30#include <common/Network/Packet/EthernetHeader.h>
31#include "os_time.h"
32#include "nat_check_flow_table.h"
33
34// 2msec timeout
35#define MAX_TIME_MSG_IN_QUEUE_SEC  ( 0.002 )
36#define NAT_FLOW_ID_MASK 0x00ffffff
37
38class  CNatOption {
39public:
40    enum {
41        noIPV4_OPTION   = 0x10, /* dummy IPV4 option */
42        noOPTION_LEN    = 0x8,
43        noIPV4_MAGIC    = 0xEE,
44        noIPV4_MAGIC_RX    = 0xED,
45
46        noIPV6_OPTION_LEN    = (noOPTION_LEN/8)-1,
47        noIPV6_OPTION = 0x3C, /*IPv6-Opts	Destination Options for IPv6	RFC 2460*/
48    };
49
50    void set_option_type(uint8_t id) {
51        u.m_data[0 ] =id;
52    }
53
54    uint8_t get_option_type() {
55        return (u.m_data[0]);
56    }
57
58    void set_option_len(uint8_t len) {
59        u.m_data[1] = len;
60    }
61    uint8_t get_option_len(){
62        return ( u.m_data[1]);
63    }
64
65    void set_thread_id(uint8_t thread_id) {
66        u.m_data[3] = thread_id;
67    }
68
69    uint8_t get_thread_id() {
70        return (u.m_data[3]);
71    }
72
73    void set_magic(uint8_t magic){
74        u.m_data[2] = magic;
75    }
76
77    uint8_t get_magic(){
78        return (u.m_data[2]);
79    }
80
81    void set_fid(uint32_t fid) {
82        u.m_data_uint32[1] = fid & NAT_FLOW_ID_MASK;
83    }
84
85    uint32_t get_fid() {
86        return (u.m_data_uint32[1]);
87    }
88
89    bool is_valid_ipv4_magic_op0(void){
90        return ( ( PKT_NTOHL( u.m_data_uint32[0] )& 0xFFFFFF00 ) ==
91                 (CNatOption::noIPV4_OPTION <<24) +  (CNatOption::noOPTION_LEN<<16) + (CNatOption::noIPV4_MAGIC<<8) ?true:false);
92    }
93
94    bool is_valid_ipv4_magic(void) {
95        return (is_valid_ipv4_magic_op0());
96    }
97
98    bool is_valid_ipv6_magic(void) {
99        return ( ( PKT_NTOHL( u.m_data_uint32[0] )& 0x00FFFF00 ) ==
100                 (CNatOption::noIPV6_OPTION_LEN<<16) + (CNatOption::noIPV4_MAGIC<<8) ?true:false);
101
102    }
103
104    void set_init_ipv4_header() {
105        set_option_type(CNatOption::noIPV4_OPTION);
106        set_option_len(CNatOption::noOPTION_LEN);
107        set_magic(CNatOption::noIPV4_MAGIC);
108    }
109
110    void set_init_ipv6_header(void){
111        set_option_len(noIPV6_OPTION_LEN);
112        set_magic(CNatOption::noIPV4_MAGIC);
113    }
114
115    void dump(FILE *fd);
116
117private:
118    union u_ {
119        uint8_t  m_data[8];
120        uint32_t m_data_uint32[2];
121    } u;
122};
123
124struct CNatFlowInfo {
125    uint32_t m_external_ip;
126    uint32_t m_tcp_seq;
127    uint32_t m_fid;
128    uint16_t m_external_port;
129    uint16_t m_pad;
130};
131
132#if __x86_64__
133/* size of 64 bytes */
134    #define MAX_NAT_FLOW_INFO (7)
135    #define MAX_PKT_MSG_INFO  (26)
136#else
137    #define MAX_NAT_FLOW_INFO (8)
138    #define MAX_PKT_MSG_INFO  (30)
139#endif
140
141/*
142     !!!   WARNING  - CGenNodeNatInfo !!
143
144 this struct should be in the same size of CGenNode beacuse allocator is global .
145
146*/
147struct CGenNodeNatInfo : public CGenNodeMsgBase {
148    uint8_t       m_pad;
149    uint16_t      m_cnt;
150    //uint32_t      m_pad2;
151 #if __x86_64__
152    uint32_t      m_pad3;
153 #endif
154    CNatFlowInfo  m_data[MAX_NAT_FLOW_INFO];
155
156public:
157      CNatFlowInfo * get_next_msg() {
158          CNatFlowInfo * lp=&m_data[m_cnt];
159          m_cnt++;
160          return (lp);
161      }
162
163      void init();
164
165      bool is_full(){
166          return (m_cnt==MAX_NAT_FLOW_INFO?true:false);
167      }
168      void dump(FILE *fd);
169};
170
171struct CGenNodeLatencyPktInfo : public CGenNodeMsgBase {
172    uint8_t       m_dir;
173    uint16_t      m_latency_offset;
174
175    uint8_t       m_update_ts;
176    uint8_t       m_pad3[3];
177
178    struct rte_mbuf *m_pkt;
179
180    uint32_t      m_pad4[MAX_PKT_MSG_INFO];
181};
182
183
184/* per thread ring info for NAT messages
185   try to put as many messages  */
186class CNatPerThreadInfo {
187public:
188    CNatPerThreadInfo() {
189        m_last_time=0;
190        m_cur_nat_msg=0;
191        m_ring=0;
192    }
193public:
194    dsec_t            m_last_time;
195    CGenNodeNatInfo * m_cur_nat_msg;
196    CNodeRing       * m_ring;
197};
198
199
200class CNatStats {
201public:
202    uint64_t  m_total_rx;
203    uint64_t  m_total_msg;
204    /* errors */
205    uint64_t  m_err_no_valid_thread_id;
206    uint64_t  m_err_no_valid_proto;
207    uint64_t  m_err_queue_full;
208public:
209    void reset();
210    uint64_t get_errs(){
211        return  (m_err_no_valid_thread_id+m_err_no_valid_proto+m_err_queue_full);
212    }
213    void Dump(FILE *fd);
214};
215
216class CNatRxManager {
217
218public:
219    bool Create();
220    void Delete();
221    void handle_packet_ipv4(CNatOption * option, IPHeader * ipv4, bool is_first);
222    void handle_aging();
223    void Dump(FILE *fd);
224    void DumpShort(FILE *fd);
225    static inline uint32_t calc_tcp_ack_val(uint32_t fid, uint8_t thread_id) {
226	return ((fid &  NAT_FLOW_ID_MASK) << 8) | thread_id;
227    }
228    void get_info_from_tcp_ack(uint32_t tcp_ack, uint32_t &fid, uint8_t &thread_id);
229private:
230    CNatPerThreadInfo * get_thread_info(uint8_t thread_id);
231    void flush_node(CNatPerThreadInfo * thread_info);
232
233private:
234    uint8_t               m_max_threads;
235    CNatPerThreadInfo   * m_per_thread;
236    CNatStats             m_stats;
237    CNatCheckFlowTable    m_ft;
238};
239
240
241#endif
242