FD.io VPP  v21.06-3-gbb25fbf28
Vector Packet Processing
cnat_node_snat.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <vlibmemory/api.h>
17 #include <cnat/cnat_node.h>
18 #include <cnat/cnat_snat_policy.h>
19 #include <cnat/cnat_inline.h>
20 #include <cnat/cnat_src_policy.h>
21 
22 typedef enum cnat_snat_next_
23 {
27 
30 
31 /* CNat sub for source NAT as a feature arc on ip[46]-unicast
32  This node's sub shouldn't apply to the same flows as
33  cnat_vip_inline */
34 static uword
37  int session_not_found, cnat_session_t *session)
38 {
40  ip4_header_t *ip4 = NULL;
41  ip_protocol_t iproto;
42  ip6_header_t *ip6 = NULL;
43  udp_header_t *udp0;
44  u32 arc_next0;
45  u16 next0;
46  u16 sport;
47  u8 trace_flags = 0;
48  int rv, do_snat;
49 
50  if (AF_IP4 == ctx->af)
51  {
53  iproto = ip4->protocol;
54  udp0 = (udp_header_t *) (ip4 + 1);
55  }
56  else
57  {
59  iproto = ip6->protocol;
60  udp0 = (udp_header_t *) (ip6 + 1);
61  }
62 
63  /* By default don't follow previous next0 */
64  vnet_feature_next (&arc_next0, b);
65  next0 = arc_next0;
66 
67  /* Wrong session key */
68  if (session->key.cs_proto == 0)
69  goto trace;
70 
71  if (!session_not_found)
72  {
73  /* session table hit */
74  cnat_timestamp_update (session->value.cs_ts_index, ctx->now);
75  }
76  else
77  {
78  ip46_address_t ip46_dst_address;
79  if (AF_IP4 == ctx->af)
80  ip46_address_set_ip4 (&ip46_dst_address, &ip4->dst_address);
81  else
82  ip46_address_set_ip6 (&ip46_dst_address, &ip6->dst_address);
83 
84  do_snat = cpm->snat_policy (b, session);
85  if (!do_snat)
86  goto trace;
87 
88  /* New flow, create the sessions if necessary. session will be a snat
89  session, and rsession will be a dnat session
90  Note: packet going through this path are going to the outside,
91  so they will never hit the NAT again (they are not going towards
92  a VIP) */
93  if (AF_IP4 == ctx->af)
94  {
96  goto trace;
98  &ip_addr_v4 (&cpm->snat_ip4.ce_ip));
100  &ip4->dst_address);
101  }
102  else
103  {
105  goto trace;
107  &ip_addr_v6 (&cpm->snat_ip6.ce_ip));
109  &ip6->dst_address);
110  }
111 
112 
113  sport = 0;
114  rv = cnat_allocate_port (&sport, iproto);
115  if (rv)
116  {
118  CNAT_ERROR_EXHAUSTED_PORTS, 1);
119  next0 = CNAT_SNAT_NEXT_DROP;
120  goto trace;
121  }
122  session->value.cs_port[VLIB_RX] = sport;
123  session->value.cs_port[VLIB_TX] = sport;
124  if (iproto == IP_PROTOCOL_TCP || iproto == IP_PROTOCOL_UDP)
125  session->value.cs_port[VLIB_TX] = udp0->dst_port;
126 
127  session->value.cs_lbi = INDEX_INVALID;
128  session->value.flags =
130  trace_flags |= CNAT_TRACE_SESSION_CREATED;
131 
134  }
135 
136 
137  if (AF_IP4 == ctx->af)
138  cnat_translation_ip4 (session, ip4, udp0);
139  else
140  cnat_translation_ip6 (session, ip6, udp0);
141 
142 trace:
143  if (PREDICT_FALSE (b->flags & VLIB_BUFFER_IS_TRACED))
144  {
145  trace_flags |= session_not_found ? 0 : CNAT_TRACE_SESSION_FOUND;
146  cnat_add_trace (vm, node, b, session, NULL, trace_flags);
147  }
148  return next0;
149 }
150 
154 {
155  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
157  CNAT_LOCATION_FIB, 1 /* do_trace */);
159  CNAT_LOCATION_FIB, 0 /* do_trace */);
160 }
161 
165 {
166  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
168  CNAT_LOCATION_FIB, 1 /* do_trace */);
170  CNAT_LOCATION_FIB, 0 /* do_trace */);
171 }
172 
174  .name = "cnat-snat-ip4",
175  .vector_size = sizeof (u32),
176  .format_trace = format_cnat_trace,
178  .n_errors = CNAT_N_ERROR,
179  .error_strings = cnat_error_strings,
180  .n_next_nodes = CNAT_SNAT_N_NEXT,
181  .next_nodes = {
182  [CNAT_SNAT_NEXT_DROP] = "ip4-drop",
183  },
184 };
185 
187  .name = "cnat-snat-ip6",
188  .vector_size = sizeof (u32),
189  .format_trace = format_cnat_trace,
191  .n_errors = CNAT_N_ERROR,
192  .error_strings = cnat_error_strings,
193  .n_next_nodes = CNAT_SNAT_N_NEXT,
194  .next_nodes = {
195  [CNAT_SNAT_NEXT_DROP] = "ip6-drop",
196  },
197 };
198 
200  .arc_name = "ip4-unicast",
201  .node_name = "cnat-snat-ip4",
202 };
203 
205  .arc_name = "ip6-unicast",
206  .node_name = "cnat-snat-ip6",
207 };
208 
209 /*
210  * fd.io coding-style-patch-verification: ON
211  *
212  * Local Variables:
213  * eval: (c-set-style "gnu")
214  * End:
215  */
cnat_snat_node_fn
static uword cnat_snat_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_buffer_t *b, cnat_node_ctx_t *ctx, int session_not_found, cnat_session_t *session)
Definition: cnat_node_snat.c:35
CNAT_EP_FLAG_RESOLVED
@ CNAT_EP_FLAG_RESOLVED
Definition: cnat_types.h:70
trace
static vlib_cli_command_t trace
(constructor) VLIB_CLI_COMMAND (trace)
Definition: vlib_api_cli.c:899
api.h
cnat_add_trace
static_always_inline void cnat_add_trace(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_buffer_t *b, cnat_session_t *session, const cnat_translation_t *ct, u8 flags)
Definition: cnat_node.h:55
cnat_session_t_::cs_ip
ip46_address_t cs_ip[VLIB_N_DIR]
IP 4/6 address in the rx/tx direction.
Definition: cnat_session.h:47
frame
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: nat44_ei.c:3048
ip4
vl_api_ip4_address_t ip4
Definition: one.api:376
ip46_address_set_ip4
static void ip46_address_set_ip4(ip46_address_t *ip46, const ip4_address_t *ip)
Definition: ip46_address.h:67
cnat_session_t_::cs_lbi
index_t cs_lbi
The load balance object to use to forward.
Definition: cnat_session.h:89
CNAT_SESSION_FLAG_NO_CLIENT
@ CNAT_SESSION_FLAG_NO_CLIENT
This session doesn't have a client, do not attempt to free it.
Definition: cnat_session.h:124
VLIB_NODE_TYPE_INTERNAL
@ VLIB_NODE_TYPE_INTERNAL
Definition: node.h:72
ip46_address_set_ip6
static_always_inline void ip46_address_set_ip6(ip46_address_t *dst, const ip6_address_t *src)
Definition: ip46_address.h:130
node
vlib_main_t vlib_node_runtime_t * node
Definition: nat44_ei.c:3047
CNAT_N_ERROR
@ CNAT_N_ERROR
Definition: cnat_types.h:179
cnat_node_ctx_
Definition: cnat_types.h:155
cnat_error_strings
char * cnat_error_strings[]
Definition: cnat_types.c:22
u16
unsigned short u16
Definition: types.h:57
vm
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
AF_IP4
@ AF_IP4
Definition: ip_types.h:23
CNAT_SNAT_NEXT_DROP
@ CNAT_SNAT_NEXT_DROP
Definition: cnat_node_snat.c:24
cnat_session_create
static_always_inline void cnat_session_create(cnat_session_t *session, cnat_node_ctx_t *ctx, cnat_session_location_t rsession_location, u8 rsession_flags)
Create NAT sessions rsession_location is the location the (return) session will be matched at.
Definition: cnat_node.h:841
VLIB_RX
@ VLIB_RX
Definition: defs.h:46
cnat_session_t_
A session represents the memory of a translation.
Definition: cnat_session.h:37
vlib_frame_t
Definition: node.h:372
udp_header_t
Definition: udp_packet.h:45
ip4_header_t
Definition: ip4_packet.h:87
cnat_snat_policy_main_t_::snat_ip4
cnat_endpoint_t snat_ip4
Definition: cnat_snat_policy.h:70
cnat_node.h
sport
u16 sport
Definition: pnat.api:43
CNAT_TRACE_SESSION_FOUND
@ CNAT_TRACE_SESSION_FOUND
Definition: cnat_node.h:48
VLIB_NODE_FN
#define VLIB_NODE_FN(node)
Definition: node.h:202
ip_addr_v6
#define ip_addr_v6(_a)
Definition: ip_types.h:92
VLIB_NODE_FLAG_TRACE
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:291
format_cnat_trace
static u8 * format_cnat_trace(u8 *s, va_list *args)
Definition: cnat_node.h:75
PREDICT_FALSE
#define PREDICT_FALSE(x)
Definition: clib.h:124
vnet_feature_next
static_always_inline void vnet_feature_next(u32 *next0, vlib_buffer_t *b0)
Definition: feature.h:322
CNAT_SESSION_FLAG_HAS_SNAT
@ CNAT_SESSION_FLAG_HAS_SNAT
Indicates a return path session that was source NATed on the way in.
Definition: cnat_session.h:116
uword
u64 uword
Definition: types.h:112
cnat_translation_ip6
static_always_inline void cnat_translation_ip6(const cnat_session_t *session, ip6_header_t *ip6, udp_header_t *udp)
Definition: cnat_node.h:640
cnat_timestamp_update
static void cnat_timestamp_update(u32 index, f64 t)
Definition: cnat_inline.h:47
ip_addr_v4
#define ip_addr_v4(_a)
Definition: ip_types.h:91
vlib_node_increment_counter
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
Definition: node_funcs.h:1244
cnat_inline.h
cnat_translation_ip4
static_always_inline void cnat_translation_ip4(const cnat_session_t *session, ip4_header_t *ip4, udp_header_t *udp)
Definition: cnat_node.h:383
cnat_allocate_port
int cnat_allocate_port(u16 *port, ip_protocol_t iproto)
Definition: cnat_src_policy.c:109
vlib_node_registration_t
struct _vlib_node_registration vlib_node_registration_t
cnat_session_t_::cs_ts_index
u32 cs_ts_index
Timestamp index this session was last used.
Definition: cnat_session.h:99
cnat_session_t_::cs_proto
ip_protocol_t cs_proto
The IP protocol TCP or UDP only supported.
Definition: cnat_session.h:57
cnat_session_t_::key
struct cnat_session_t_::@635 key
this key sits in the same memory location a 'key' in the bihash kvp
cnat_session_t_::value
struct cnat_session_t_::@636 value
this value sits in the same memory location a 'value' in the bihash kvp
cnat_session_t_::flags
u32 flags
session flags
Definition: cnat_session.h:104
cnat_snat_next_
cnat_snat_next_
Definition: cnat_node_snat.c:22
u32
unsigned int u32
Definition: types.h:88
udp_header_t::dst_port
u16 dst_port
Definition: udp_packet.h:48
CNAT_SESSION_FLAG_ALLOC_PORT
@ CNAT_SESSION_FLAG_ALLOC_PORT
This session source port was allocated, free it on cleanup.
Definition: cnat_session.h:120
ip6
vl_api_ip6_address_t ip6
Definition: one.api:424
cnat_node_inline
static uword cnat_node_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, cnat_node_sub_t cnat_sub, ip_address_family_t af, cnat_session_location_t cs_loc, u8 do_trace)
Definition: cnat_node.h:933
ctx
long ctx[MAX_CONNS]
Definition: main.c:144
cnat_snat_policy_main_t_::snat_policy
cnat_snat_policy_t snat_policy
Definition: cnat_snat_policy.h:67
AF_IP6
@ AF_IP6
Definition: ip_types.h:24
cnat_snat_ip4_node
vlib_node_registration_t cnat_snat_ip4_node
(constructor) VLIB_REGISTER_NODE (cnat_snat_ip4_node)
Definition: cnat_node_snat.c:28
ip6_header_t
Definition: ip6_packet.h:294
cnat_snat_policy_main_t_
Definition: cnat_snat_policy.h:58
ip_protocol_t
enum ip_protocol ip_protocol_t
vlib_main_t
Definition: main.h:102
cnat_snat_policy_main_t_::snat_ip6
cnat_endpoint_t snat_ip6
Definition: cnat_snat_policy.h:73
cnat_endpoint_t_::ce_ip
ip_address_t ce_ip
Definition: cnat_types.h:75
b
vlib_buffer_t ** b
Definition: nat44_ei_out2in.c:717
u8
unsigned char u8
Definition: types.h:56
vlib_buffer_get_current
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:257
cnat_src_policy.h
rv
int __clib_unused rv
Definition: application.c:491
CNAT_LOCATION_FIB
@ CNAT_LOCATION_FIB
Definition: cnat_session.h:138
cnat_endpoint_t_::ce_flags
u8 ce_flags
Definition: cnat_types.h:78
vlib_node_runtime_t
Definition: node.h:454
cnat_snat_policy_main
cnat_snat_policy_main_t cnat_snat_policy_main
Definition: cnat_snat_policy.c:20
INDEX_INVALID
#define INDEX_INVALID
Invalid index - used when no index is known blazoned capitals INVALID speak volumes where ~0 does not...
Definition: dpo.h:49
VNET_FEATURE_INIT
VNET_FEATURE_INIT(cnat_snat_ip4_node, static)
VLIB_TX
@ VLIB_TX
Definition: defs.h:47
CNAT_SNAT_N_NEXT
@ CNAT_SNAT_N_NEXT
Definition: cnat_node_snat.c:25
cnat_snat_next_t
enum cnat_snat_next_ cnat_snat_next_t
type
vl_api_fib_path_type_t type
Definition: fib_types.api:123
cnat_snat_policy.h
CNAT_TRACE_SESSION_CREATED
@ CNAT_TRACE_SESSION_CREATED
Definition: cnat_node.h:49
cnat_snat_ip6_node
vlib_node_registration_t cnat_snat_ip6_node
(constructor) VLIB_REGISTER_NODE (cnat_snat_ip6_node)
Definition: cnat_node_snat.c:29
vlib_buffer_t::flags
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index,...
Definition: buffer.h:133
vlib_buffer_t
VLIB buffer representation.
Definition: buffer.h:111
cnat_session_t_::cs_port
u16 cs_port[VLIB_N_DIR]
ports in rx/tx
Definition: cnat_session.h:52
VLIB_REGISTER_NODE
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169