FD.io VPP  v16.06
Vector Packet Processing
cnat_v4_functions.c
Go to the documentation of this file.
1 /*
2  *---------------------------------------------------------------------------
3  * cnat_v4_funtions.c
4  *
5  * Copyright (c) 2008-2013 Cisco and/or its affiliates.
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at:
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *---------------------------------------------------------------------------
18  */
19 #include <vlib/vlib.h>
20 #include <vnet/vnet.h>
21 #include <vnet/pg/pg.h>
22 #include <vppinfra/error.h>
23 
24 
25 #include "tcp_header_definitions.h"
26 #include "cnat_db.h"
27 #include "cnat_config.h"
28 #include "cnat_v4_functions.h"
29 #include "dslite_defs.h"
30 #include "dslite_db.h"
31 
34 
35 static tcp_logging_struct_t tcp_logging_array[MAX_TCP_LOGGING_COUNT];
36 
37 /*
38  * Function to log TCP pkts checksum changes..
39  */
40 void
42  u32 seq_num,
43  u32 ack_num,
44  u32 old_ip,
45  u32 new_ip,
46  u16 old_port,
47  u16 new_port,
48  u16 old_ip_crc,
49  u16 new_ip_crc,
50  u16 old_tcp_crc,
51  u16 new_tcp_crc)
52 {
53  tcp_logging_array[tcp_logging_count].seq_num = seq_num;
54  tcp_logging_array[tcp_logging_count].ack_num = ack_num;
55  tcp_logging_array[tcp_logging_count].old_ip = old_ip;
56  tcp_logging_array[tcp_logging_count].new_ip = new_ip;
57  tcp_logging_array[tcp_logging_count].old_port = old_port;
58  tcp_logging_array[tcp_logging_count].new_port = new_port;
59  tcp_logging_array[tcp_logging_count].old_ip_crc = old_ip_crc;
60  tcp_logging_array[tcp_logging_count].new_ip_crc = new_ip_crc;
61  tcp_logging_array[tcp_logging_count].old_tcp_crc = old_tcp_crc;
62  tcp_logging_array[tcp_logging_count].new_tcp_crc = new_tcp_crc;
63 
65 
69  }
70 }
71 
72 /*
73  * Function to dmp TCP pkts logged..
74  */
75 void
77 {
78  u32 i, total_count, start_entry;
79 
81  total_count = MAX_TCP_LOGGING_COUNT;
82  start_entry = tcp_logging_count;
83  printf("Logging Entries Wrapped Around, displaying %d entries\n",
84  total_count);
85  } else {
86  total_count = tcp_logging_count;
87  start_entry = 0;
88  printf("Displaying %d entries\n", total_count);
89  }
90 
91  printf("SEQ ACK IP_O IP_N PORT_O PORT_N L3_CRC_O L3_CRC_N L4_CRC_O L4_CRC_N\n");
92 
93  for (i = 0; i < total_count; i++) {
94  u32 entry = (i + start_entry) % MAX_TCP_LOGGING_COUNT;
95 
96  printf("%04d: 0x%08x 0x%08x 0x%08x 0x%08x 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x\n",
97  entry,
98  tcp_logging_array[entry].seq_num,
99  tcp_logging_array[entry].ack_num,
100  tcp_logging_array[entry].old_ip,
101  tcp_logging_array[entry].new_ip,
102  tcp_logging_array[entry].old_port,
103  tcp_logging_array[entry].new_port,
104  tcp_logging_array[entry].old_ip_crc,
105  tcp_logging_array[entry].new_ip_crc,
106  tcp_logging_array[entry].old_tcp_crc,
107  tcp_logging_array[entry].new_tcp_crc);
108  }
109 }
110 
111 /*
112  * Function to enable TCP logging
113  */
114 void
116 {
117  switch (enable_flag) {
118 
119  case TCP_LOGGING_DISABLE:
121  printf("\nTCP Logging ALREADY DISABLED\n");
122  } else {
123  printf("\nTCP Logging DISABLED\n");
124  }
126  break;
127 
128  case TCP_LOGGING_ENABLE:
130  printf("\nTCP Logging ALREADY ENABLED\n");
131  } else {
133  tcp_logging_count = 0;
135 
136  printf("\nTCP Logging ENABLED\n");
137  }
138  break;
139 
142  break;
143 
145  default:
146  printf("\ntcp_logging_enable_flag %d, tcp_log_count %d\n",
148  printf("To Enable TCP LOGGING provide a flag value of %d\n",
150  break;
151  }
152 }
153 
154 void hex_dump (u8 * p, int len) {
155  int i;
156  for (i=0;i<len;i++) {
157  if(i && (i & 0x3 ) == 0) printf(" ");
158  if(i && (i & 0xf ) == 0) printf("\n");
159  PLATFORM_DEBUG_PRINT("%02X ", p[i]);
160  }
161  PLATFORM_DEBUG_PRINT("\n");
162 }
163 
164 void
166 {
167  u32 i, total_len;
168 
169  u8 *pkt = (u8 *) ip;
170 
171  total_len = clib_net_to_host_u16(ip->total_len_bytes);
172 
173  printf("\n======== PRINTING PKT START======\n");
174  printf("======== IP PACKET LEN %d ===========\n", total_len);
175  for (i=0; i < 20; i++) {
176  printf(" %02X ", *(pkt + i));
177  }
178 
179  printf("\n======== ICMP HEADER =================\n");
180  for (i=20; i < 28; i++) {
181  printf(" %02X ", *(pkt + i));
182  }
183 
184  printf("\n======== ICMP BODY ===================\n");
185  for (i=28; i < total_len; i++) {
186  printf(" %02X ", *(pkt + i));
187  }
188 
189  printf("\n======== PRINTING PKT END =======\n");
190 }
191 
192 void
194 {
195  u32 i, total_len, udp_len;
196 
197  u8 *pkt = (u8 *) ip;
198 
199  total_len = clib_net_to_host_u16(ip->total_len_bytes);
200  udp_len = total_len - 20;
201 
202  printf("\n======== PRINTING PKT START======\n");
203  printf("======== IP PACKET LEN %d ===========\n", total_len);
204  for (i=0; i < 20; i++) {
205  printf(" %02X ", *(pkt + i));
206  }
207  printf("\n======== UDP PSEUDO HEADER ==========\n");
208  for (i=12; i < 20; i++) {
209  printf(" %02X ", *(pkt + i));
210  }
211  printf(" 00 11 %02X %02X ", udp_len >> 8, udp_len & 0xff);
212 
213  printf("\n======== UDP HEADER =================\n");
214  for (i=20; i < 28; i++) {
215  printf(" %02X ", *(pkt + i));
216  }
217  printf("\n======== UDP BODY ===================\n");
218  for (i=28; i < total_len; i++) {
219  printf(" %02X ", *(pkt + i));
220  }
221 
222  printf("\n======== PRINTING PKT END =======\n");
223 }
224 
225 void
227 {
228  u32 i, total_len, tcp_len;
229 
230  u8 *pkt = (u8 *) ip;
231 
232  total_len = clib_net_to_host_u16(ip->total_len_bytes);
233  tcp_len = total_len - 20;
234 
235  printf("\n======== PRINTING PKT START======\n");
236  printf("======== IP PACKET LEN %d ===========\n", total_len);
237  for (i=0; i < 20; i++) {
238  printf(" %02X ", *(pkt + i));
239  }
240  printf("\n======== TCP PSEUDO HEADER ==========\n");
241  for (i=12; i < 20; i++) {
242  printf(" %02X ", *(pkt + i));
243  }
244  printf(" 00 06 %02X %02X ", tcp_len >> 8, tcp_len & 0xff);
245 
246  printf("\n======== TCP HEADER =================\n");
247  for (i=20; i < 40; i++) {
248  printf(" %02X ", *(pkt + i));
249  }
250  printf("\n======== TCP BODY ===================\n");
251  for (i=40; i < total_len; i++) {
252  printf(" %02X ", *(pkt + i));
253  }
254 
255  printf("\n======== PRINTING PKT END =======\n");
256 }
257 
258 /* IN: ipv4 and tcp header pointer,
259  * new ipv4 addr and port value
260  * main db index for accessing per vrf mss value
261  * DO:
262  * NAT
263  * mss adjust if needed
264  * ip & tcp checksum update (incremental)
265  */
266 
268  tcp_hdr_type * tcp,
269  u32 ipv4_addr,
270  u16 port,
272 {
273  u8 *mss_ptr;
274  u8 check_mss = 0;
275  u16 mss_old, mss_new;
276  cnat_vrfmap_t * vrf_map_p;
277 
279  tcp,
280  &(ip->src_addr),
281  &(tcp->src_port),
282  ipv4_addr,
283  port);
284  u16 frag_offset =
285  clib_net_to_host_u16(ip->frag_flags_offset);
286 
287  if(PREDICT_FALSE(frag_offset & IP_FRAG_OFFSET_MASK)) {
288  return; /* No TCP Header at all */
289  }
290 
291  /*
292  * check SYN bit and if options field is present
293  * If yes, proceed to extract the options and get TCP MSS value
294  */
295  check_mss = ((tcp->flags & TCP_FLAG_SYN) &&
296  (((tcp->hdr_len>>4) << 2) > sizeof(tcp_hdr_type)));
297 
298  if (PREDICT_FALSE(check_mss)) {
299 
300  /* get per VRF mss config */
303  } else {
304  vrf_map_p = cnat_map_by_vrf + db->vrfmap_index;
305  mss_new = vrf_map_p->tcp_mss;
306  }
307  DSLITE_PRINTF(1, "Check MSS true..%u\n", mss_new);
308  /*
309  * If TCP MSS is not configured, skip the MSS checks
310  */
312 
313  /* if mss_ptr != NULL, then it points to MSS option */
314  mss_ptr = tcp_findoption(tcp, TCP_OPTION_MSS);
315 
316  /*
317  * TCP option field: | kind 1B | len 1B | value 2B|
318  * where kind != [0,1]
319  */
320  if (PREDICT_TRUE(mss_ptr && (mss_ptr[1] == 4))) {
321 
322  u16 *ptr = (u16*)(mss_ptr + 2);
323 
324  mss_old = clib_net_to_host_u16(*ptr);
325 
326  if (PREDICT_FALSE(mss_old > mss_new)) {
327  u32 sum32;
328  u16 mss_old_r, old_tcp_checksum_r;
329 
330  *ptr = clib_host_to_net_u16(mss_new);
331 
332  mss_old_r = ~mss_old;
333 
334  old_tcp_checksum_r =
335  ~clib_net_to_host_u16(tcp->tcp_checksum);
336 
337  /*
338  * Revise the TCP checksum
339  */
340  sum32 = old_tcp_checksum_r + mss_old_r + mss_new;
341  FILL_CHECKSUM(tcp->tcp_checksum, sum32)
342 
345  clib_net_to_host_u32(tcp->seq_num),
346  clib_net_to_host_u32(tcp->ack_num),
347  0,
348  0,
349  mss_old,
350  mss_new,
351  0,
352  0,
353  ~old_tcp_checksum_r,
354  clib_net_to_host_u16(tcp->tcp_checksum));
355  }
356  }
357  }
358  }
359  }
360 }
361 
363  return 0x01010101;
364 }
#define TCP_LOGGING_DISABLE
static u8 * tcp_findoption(tcp_hdr_type *tcp, u8 option)
u16 flags
Definition: cnat_db.h:159
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:267
#define DSLITE_PRINTF(level,...)
Definition: dslite_db.h:28
#define MAX_TCP_LOGGING_COUNT
#define PREDICT_TRUE(x)
Definition: clib.h:98
void tcp_in2out_nat_mss_n_checksum(ipv4_header *ip, tcp_hdr_type *tcp, u32 ipv4_addr, u16 port, cnat_main_db_entry_t *db)
Definition: cnat_db.h:153
void print_tcp_pkt(ipv4_header *ip)
#define TCP_LOGGING_PACKET_DUMP
u16 tcp_mss
Definition: dslite_defs.h:115
#define PLATFORM_DEBUG_PRINT(...)
u32 tcp_logging_enable_flag
void hex_dump(u8 *p, int len)
#define TCP_LOGGING_ENABLE
static void cnat_v4_recalculate_tcp_checksum(ipv4_header *ip, tcp_hdr_type *tcp, u32 *ip_addr_ptr, u16 *tcp_port_addr_ptr, u32 new_ip, u16 new_port)
void tcp_debug_logging(u32 seq_num, u32 ack_num, u32 old_ip, u32 new_ip, u16 old_port, u16 new_port, u16 old_ip_crc, u16 new_ip_crc, u16 old_tcp_crc, u16 new_tcp_crc)
static u32 tcp_logging_overflow
dslite_table_entry_t * dslite_table_db_ptr
Definition: cnat_global.c:52
#define TCP_FLAG_SYN
#define PREDICT_FALSE(x)
Definition: clib.h:97
void tcp_debug_logging_enable_disable(u32 enable_flag)
void print_udp_pkt(ipv4_header *ip)
struct tcp_hdr_type tcp_hdr_type
#define V4_TCP_MSS_NOT_CONFIGURED_VALUE
Definition: cnat_config.h:53
#define CNAT_DB_DSLITE_FLAG
Definition: cnat_db.h:188
void tcp_debug_logging_dump(void)
unsigned int u32
Definition: types.h:88
static u32 tcp_logging_count
#define TCP_LOGGING_SUMMARY_DUMP
unsigned short u16
Definition: types.h:57
cnat_vrfmap_t * cnat_map_by_vrf
Definition: cnat_db_v2.c:212
#define IP_FRAG_OFFSET_MASK
u16 dslite_nat44_inst_id
Definition: cnat_db.h:260
unsigned char u8
Definition: types.h:56
u16 vrfmap_index
Definition: cnat_db.h:192
#define FILL_CHECKSUM(checksum_field, sum32)
void print_icmp_pkt(ipv4_header *ip)
u32 get_my_svi_intf_ip_addr()