FD.io VPP  v21.06-3-gbb25fbf28
Vector Packet Processing
cnat_node_vip.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_inline.h>
19 #include <cnat/cnat_src_policy.h>
20 
22 {
27 
30 
31 /* CNat sub for NAT behind a fib entry (VIP or interposed real IP) */
32 static uword
34  cnat_node_ctx_t *ctx, int session_not_found,
35  cnat_session_t *session)
36 {
39  const cnat_translation_t *ct = NULL;
40  ip4_header_t *ip4 = NULL;
41  ip_protocol_t iproto;
42  ip6_header_t *ip6 = NULL;
43  udp_header_t *udp0;
44  cnat_client_t *cc;
45  u16 next0;
46  index_t cti;
47  u8 trace_flags = 0;
48  int rv;
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  cc = cnat_client_get (vnet_buffer (b)->ip.adj_index[VLIB_TX]);
64 
65  /* Wrong session key */
66  if (session->key.cs_proto == 0)
67  {
68  /* Dont translate & follow the fib programming */
69  next0 = cc->cc_parent.dpoi_next_node;
70  vnet_buffer (b)->ip.adj_index[VLIB_TX] = cc->cc_parent.dpoi_index;
71  goto trace;
72  }
73 
74  if (!session_not_found)
75  {
76  /* session table hit */
77  cnat_timestamp_update (session->value.cs_ts_index, ctx->now);
78 
79  if (INDEX_INVALID != session->value.cs_lbi)
80  {
81  /* Translate & follow the translation given LB */
82  next0 = session->value.dpoi_next_node;
83  vnet_buffer (b)->ip.adj_index[VLIB_TX] = session->value.cs_lbi;
84  }
85  else if (session->value.flags & CNAT_SESSION_FLAG_HAS_SNAT)
86  {
87  /* The return needs DNAT, so we need an additionnal
88  * lookup after translation */
90  }
91  else
92  {
93  /* Translate & follow the fib programming */
94  next0 = cc->cc_parent.dpoi_next_node;
95  vnet_buffer (b)->ip.adj_index[VLIB_TX] = cc->cc_parent.dpoi_index;
96  }
97  }
98  else
99  {
100  ct =
102  clib_host_to_net_u16 (udp0->dst_port), iproto);
103  if (NULL == ct)
104  {
105  /* Dont translate & Follow the fib programming */
106  vnet_buffer (b)->ip.adj_index[VLIB_TX] = cc->cc_parent.dpoi_index;
107  next0 = cc->cc_parent.dpoi_next_node;
108  goto trace;
109  }
110 
111  /* New flow, create the sessions */
112  cnat_ep_trk_t *trk0;
113  u32 rsession_flags = 0;
114  u32 dpoi_index = -1;
115 
116  trk0 = cnat_load_balance (ct, ctx->af, ip4, ip6, &dpoi_index);
117  if (PREDICT_FALSE (NULL == trk0))
118  {
119  /* Dont translate & Follow the fib programming */
120  vnet_buffer (b)->ip.adj_index[VLIB_TX] = cc->cc_parent.dpoi_index;
121  next0 = cc->cc_parent.dpoi_next_node;
122  goto trace;
123  }
124 
125  /* add the session */
126  ip46_address_copy (&session->value.cs_ip[VLIB_TX],
127  &trk0->ct_ep[VLIB_TX].ce_ip.ip);
128  if (ip_address_is_zero (&trk0->ct_ep[VLIB_RX].ce_ip))
129  {
130  if (AF_IP4 == ctx->af)
132  &ip4->src_address);
133  else
135  &ip6->src_address);
136  }
137  else
138  {
139  /* We source NAT with the translation */
140  rsession_flags |= CNAT_SESSION_FLAG_HAS_SNAT;
141  ip46_address_copy (&session->value.cs_ip[VLIB_RX],
142  &trk0->ct_ep[VLIB_RX].ce_ip.ip);
143  }
144  session->value.cs_port[VLIB_TX] =
145  clib_host_to_net_u16 (trk0->ct_ep[VLIB_TX].ce_port);
146  session->value.cs_port[VLIB_RX] =
147  clib_host_to_net_u16 (trk0->ct_ep[VLIB_RX].ce_port);
148 
149  session->value.dpoi_next_node = ct->ct_lb.dpoi_next_node;
150  session->value.cs_lbi = dpoi_index;
151  session->value.flags = 0;
152 
153  rv = cspm->vip_policy (vm, b, session, &rsession_flags, ct, ctx);
155  rv = cspm->default_policy (vm, b, session, &rsession_flags, ct, ctx);
156  if (rv)
157  {
159  {
163  CNAT_ERROR_EXHAUSTED_PORTS, 1);
164  }
166  goto trace;
167  }
168 
169  /* refcnt session in current client */
171  cnat_session_create (session, ctx, CNAT_LOCATION_FIB, rsession_flags);
172  trace_flags |= CNAT_TRACE_SESSION_CREATED;
173 
174  next0 = ct->ct_lb.dpoi_next_node;
175  vnet_buffer (b)->ip.adj_index[VLIB_TX] = session->value.cs_lbi;
176  }
177 
178  if (AF_IP4 == ctx->af)
179  cnat_translation_ip4 (session, ip4, udp0);
180  else
181  cnat_translation_ip6 (session, ip6, udp0);
182 
183  if (NULL != ct)
184  {
185  cti = ct - cnat_translation_pool;
186  vlib_increment_combined_counter (cntm, ctx->thread_index, cti, 1,
188  }
189 
190 trace:
191  if (PREDICT_FALSE (ctx->do_trace))
192  {
193  trace_flags |= session_not_found ? 0 : CNAT_TRACE_SESSION_FOUND;
194  cnat_add_trace (vm, node, b, session, ct, trace_flags);
195  }
196  return next0;
197 }
198 
202 {
203  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
205  CNAT_LOCATION_FIB, 1 /* do_trace */);
207  CNAT_LOCATION_FIB, 0 /* do_trace */);
208 }
209 
213 {
214  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
216  CNAT_LOCATION_FIB, 1 /* do_trace */);
218  CNAT_LOCATION_FIB, 0 /* do_trace */);
219 }
220 
222 {
223  .name = "ip4-cnat-tx",
224  .vector_size = sizeof (u32),
225  .format_trace = format_cnat_trace,
227  .n_errors = 0,
228  .n_next_nodes = CNAT_TRANSLATION_N_NEXT,
229  .next_nodes =
230  {
231  [CNAT_TRANSLATION_NEXT_DROP] = "ip4-drop",
232  [CNAT_TRANSLATION_NEXT_LOOKUP] = "ip4-lookup",
233  },
234 };
236 {
237  .name = "ip6-cnat-tx",
238  .vector_size = sizeof (u32),
239  .format_trace = format_cnat_trace,
241  .n_errors = 0,
242  .n_next_nodes = CNAT_TRANSLATION_N_NEXT,
243  .next_nodes =
244  {
245  [CNAT_TRANSLATION_NEXT_DROP] = "ip6-drop",
246  [CNAT_TRANSLATION_NEXT_LOOKUP] = "ip6-lookup",
247  },
248 };
249 
250 /*
251  * fd.io coding-style-patch-verification: ON
252  *
253  * Local Variables:
254  * eval: (c-set-style "gnu")
255  * End:
256  */
dpo_id_t_::dpoi_next_node
u16 dpoi_next_node
The next VLIB node to follow.
Definition: dpo.h:186
cnat_src_policy_main
cnat_src_policy_main_t cnat_src_policy_main
Definition: cnat_src_policy.c:22
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
dpo_id_t_::dpoi_index
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:190
cnat_load_balance
static_always_inline cnat_ep_trk_t * cnat_load_balance(const cnat_translation_t *ct, ip_address_family_t af, ip4_header_t *ip4, ip6_header_t *ip6, u32 *dpoi_index)
Definition: cnat_node.h:807
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
cnat_ep_trk_t_::ct_ep
cnat_endpoint_t ct_ep[VLIB_N_DIR]
The EP being tracked.
Definition: cnat_translation.h:37
ip4
vl_api_ip4_address_t ip4
Definition: one.api:376
cnat_translation_next_t_
cnat_translation_next_t_
Definition: cnat_node_vip.c:21
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_client_cnt_session
static_always_inline u32 cnat_client_cnt_session(cnat_client_t *cc)
Add a session refcnt to this client.
Definition: cnat_client.h:195
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_node_ctx_
Definition: cnat_types.h:155
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_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_::dpoi_next_node
u32 dpoi_next_node
Persist translation->ct_lb.dpoi_next_node.
Definition: cnat_session.h:94
cnat_session_t_
A session represents the memory of a translation.
Definition: cnat_session.h:37
CNAT_SOURCE_ERROR_USE_DEFAULT
@ CNAT_SOURCE_ERROR_USE_DEFAULT
Definition: cnat_src_policy.h:36
vlib_frame_t
Definition: node.h:372
CNAT_SOURCE_ERROR_EXHAUSTED_PORTS
@ CNAT_SOURCE_ERROR_EXHAUSTED_PORTS
Definition: cnat_src_policy.h:35
vlib_buffer_length_in_chain
static uword vlib_buffer_length_in_chain(vlib_main_t *vm, vlib_buffer_t *b)
Get length in bytes of the buffer chain.
Definition: buffer_funcs.h:433
udp_header_t
Definition: udp_packet.h:45
ip4_header_t
Definition: ip4_packet.h:87
cnat_node.h
CNAT_TRANSLATION_N_NEXT
@ CNAT_TRANSLATION_N_NEXT
Definition: cnat_node_vip.c:25
cnat_client_t_::cc_parent
dpo_id_t cc_parent
How to send packets to this client post translation.
Definition: cnat_client.h:47
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
vnet_buffer
#define vnet_buffer(b)
Definition: buffer.h:437
cnat_client_t_::parent_cci
index_t parent_cci
Parent cnat_client index if cloned via interpose or own index if vanilla client.
Definition: cnat_client.h:74
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
index_t
u32 index_t
A Data-Path Object is an object that represents actions that are applied to packets are they are swit...
Definition: dpo.h:43
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
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_vip_ip4_node
vlib_node_registration_t cnat_vip_ip4_node
(constructor) VLIB_REGISTER_NODE (cnat_vip_ip4_node)
Definition: cnat_node_vip.c:28
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_src_policy_main_::vip_policy
cnat_vip_source_policy_t vip_policy
Definition: cnat_src_policy.h:56
vlib_node_registration_t
struct _vlib_node_registration vlib_node_registration_t
ip46_address_copy
static_always_inline void ip46_address_copy(ip46_address_t *dst, const ip46_address_t *src)
Definition: ip46_address.h:123
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
ip_address_is_zero
bool ip_address_is_zero(const ip_address_t *ip)
Definition: ip_types.c:102
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
vlib_combined_counter_main_t
A collection of combined counters.
Definition: counter.h:203
u32
unsigned int u32
Definition: types.h:88
udp_header_t::dst_port
u16 dst_port
Definition: udp_packet.h:48
ip6
vl_api_ip6_address_t ip6
Definition: one.api:424
cnat_vip_ip6_node
vlib_node_registration_t cnat_vip_ip6_node
(constructor) VLIB_REGISTER_NODE (cnat_vip_ip6_node)
Definition: cnat_node_vip.c:29
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_src_policy_main_::default_policy
cnat_vip_source_policy_t default_policy
Definition: cnat_src_policy.h:57
AF_IP6
@ AF_IP6
Definition: ip_types.h:24
ip6_header_t
Definition: ip6_packet.h:294
cnat_client_get
static_always_inline cnat_client_t * cnat_client_get(index_t i)
Definition: cnat_client.h:91
ip_protocol_t
enum ip_protocol ip_protocol_t
cnat_endpoint_t_::ce_port
u16 ce_port
Definition: cnat_types.h:77
vlib_main_t
Definition: main.h:102
cnat_translation_counters
vlib_combined_counter_main_t cnat_translation_counters
Counters for each translation.
Definition: cnat_translation.c:33
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
ip
vl_api_address_t ip
Definition: l2.api:558
cnat_translation_t_::ct_lb
dpo_id_t ct_lb
The LB used to forward to the backends.
Definition: cnat_translation.h:127
cnat_src_policy.h
cnat_translation_pool
cnat_translation_t * cnat_translation_pool
Definition: cnat_translation.c:26
ip_address::ip
ip46_address_t ip
Definition: ip_types.h:81
rv
int __clib_unused rv
Definition: application.c:491
CNAT_LOCATION_FIB
@ CNAT_LOCATION_FIB
Definition: cnat_session.h:138
cnat_vip_node_fn
static uword cnat_vip_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_vip.c:33
vlib_node_runtime_t
Definition: node.h:454
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
cnat_client_t_
A client is a representation of an IP address behind the NAT.
Definition: cnat_client.h:35
VLIB_TX
@ VLIB_TX
Definition: defs.h:47
CNAT_TRANSLATION_NEXT_DROP
@ CNAT_TRANSLATION_NEXT_DROP
Definition: cnat_node_vip.c:23
CNAT_TRANSLATION_NEXT_LOOKUP
@ CNAT_TRANSLATION_NEXT_LOOKUP
Definition: cnat_node_vip.c:24
cnat_translation_next_t
enum cnat_translation_next_t_ cnat_translation_next_t
type
vl_api_fib_path_type_t type
Definition: fib_types.api:123
vlib_increment_combined_counter
vlib_increment_combined_counter(ccm, ti, sw_if_index, n_buffers, n_bytes)
CNAT_TRACE_SESSION_CREATED
@ CNAT_TRACE_SESSION_CREATED
Definition: cnat_node.h:49
cnat_translation_t_
A Translation represents the translation of a VEP to one of a set of real server addresses.
Definition: cnat_translation.h:117
cnat_ep_trk_t_
Data used to track an EP in the FIB.
Definition: cnat_translation.h:32
cnat_src_policy_main_
Definition: cnat_src_policy.h:54
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
cnat_find_translation
static_always_inline cnat_translation_t * cnat_find_translation(index_t cti, u16 port, ip_protocol_t proto)
Definition: cnat_translation.h:250
VLIB_REGISTER_NODE
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169