When dNAT-ing to a VIP, it can happen that the return session conflicts with another forward session than the one we own. This patchs adds a rsession_flags CNAT_SESSION_RETRY_SNAT that makes cnat_session_create search for a free src port to use for the resulting return session. It also makes forward & return session share their fate in the session scanner. Type: fix Change-Id: Id0edf59abf8e5bc0c0d8941ba289c4563c77dee0 Signed-off-by: Nathan Skrzypczak <nathan.skrzypczak@gmail.com>
205 lines
4.8 KiB
C
205 lines
4.8 KiB
C
/*
|
|
* Copyright (c) 2020 Cisco and/or its affiliates.
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at:
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#ifndef __CNAT_SESSION_H__
|
|
#define __CNAT_SESSION_H__
|
|
|
|
#include <vnet/udp/udp_packet.h>
|
|
|
|
#include <cnat/cnat_types.h>
|
|
#include <cnat/cnat_client.h>
|
|
#include <cnat/cnat_bihash.h>
|
|
|
|
/**
|
|
* A session represents the memory of a translation.
|
|
* In the tx direction (from behind to in front of the NAT), the
|
|
* session is preserved so subsequent packets follow the same path
|
|
* even if the translation has been updated. In the tx direction
|
|
* the session represents the swap from the VIP to the server address
|
|
* In the RX direction the swap is from the server address/port to VIP.
|
|
*
|
|
* A session exists only as key and value in the bihash, there is no
|
|
* pool for this object. If there were a pool, one would need to be
|
|
* concerned about what worker is using it.
|
|
*/
|
|
typedef struct cnat_session_t_
|
|
{
|
|
/**
|
|
* this key sits in the same memory location a 'key' in the bihash kvp
|
|
*/
|
|
struct
|
|
{
|
|
/**
|
|
* IP 4/6 address in the rx/tx direction
|
|
*/
|
|
ip46_address_t cs_ip[VLIB_N_DIR];
|
|
|
|
/**
|
|
* ports in rx/tx
|
|
*/
|
|
u16 cs_port[VLIB_N_DIR];
|
|
|
|
/**
|
|
* The IP protocol TCP or UDP only supported
|
|
*/
|
|
ip_protocol_t cs_proto;
|
|
|
|
/**
|
|
* The address family describing the IP addresses
|
|
*/
|
|
u8 cs_af;
|
|
|
|
/**
|
|
* input / output / fib session
|
|
*/
|
|
u8 cs_loc;
|
|
|
|
u8 __cs_pad;
|
|
} key;
|
|
/**
|
|
* this value sits in the same memory location a 'value' in the bihash kvp
|
|
*/
|
|
struct
|
|
{
|
|
/**
|
|
* The IP address to translate to.
|
|
*/
|
|
ip46_address_t cs_ip[VLIB_N_DIR];
|
|
|
|
/**
|
|
* the port to translate to.
|
|
*/
|
|
u16 cs_port[VLIB_N_DIR];
|
|
|
|
/**
|
|
* The load balance object to use to forward
|
|
*/
|
|
index_t cs_lbi;
|
|
|
|
/**
|
|
* Persist translation->ct_lb.dpoi_next_node
|
|
*/
|
|
u32 dpoi_next_node;
|
|
|
|
/**
|
|
* Timestamp index this session was last used
|
|
*/
|
|
u32 cs_ts_index;
|
|
|
|
/**
|
|
* session flags
|
|
*/
|
|
u32 flags;
|
|
|
|
u32 __pad;
|
|
} value;
|
|
} cnat_session_t;
|
|
|
|
typedef enum cnat_session_flag_t_
|
|
{
|
|
/**
|
|
* Indicates a return path session that was source NATed
|
|
* on the way in.
|
|
*/
|
|
CNAT_SESSION_FLAG_HAS_SNAT = (1 << 0),
|
|
/**
|
|
* This session source port was allocated, free it on cleanup
|
|
*/
|
|
CNAT_SESSION_FLAG_ALLOC_PORT = (1 << 1),
|
|
/**
|
|
* This session doesn't have a client, do not attempt to free it
|
|
*/
|
|
CNAT_SESSION_FLAG_NO_CLIENT = (1 << 2),
|
|
|
|
/* Do not actually translate the packet but still forward it
|
|
* Used for Maglev, with an encap */
|
|
CNAT_SESSION_FLAG_NO_NAT = (1 << 3),
|
|
|
|
/* Debug flag marking return sessions */
|
|
CNAT_SESSION_IS_RETURN = (1 << 4),
|
|
|
|
/** On conflicts when adding the return session, try to sNAT the
|
|
* forward session, and dNAT the return session with a random port */
|
|
CNAT_SESSION_RETRY_SNAT = (1 << 5),
|
|
|
|
} cnat_session_flag_t;
|
|
|
|
typedef enum cnat_session_location_t_
|
|
{
|
|
CNAT_LOCATION_INPUT = 0,
|
|
CNAT_LOCATION_OUTPUT = 1,
|
|
CNAT_LOCATION_FIB = 0xff,
|
|
} cnat_session_location_t;
|
|
|
|
extern u8 *format_cnat_session (u8 * s, va_list * args);
|
|
|
|
/**
|
|
* Ensure the session object correctly overlays the bihash key/value pair
|
|
*/
|
|
STATIC_ASSERT (STRUCT_OFFSET_OF (cnat_session_t, key) ==
|
|
STRUCT_OFFSET_OF (cnat_bihash_kv_t, key),
|
|
"key overlaps");
|
|
STATIC_ASSERT (STRUCT_OFFSET_OF (cnat_session_t, value) ==
|
|
STRUCT_OFFSET_OF (cnat_bihash_kv_t, value),
|
|
"value overlaps");
|
|
STATIC_ASSERT (sizeof (cnat_session_t) == sizeof (cnat_bihash_kv_t),
|
|
"session kvp");
|
|
|
|
/**
|
|
* The DB of sessions
|
|
*/
|
|
extern cnat_bihash_t cnat_session_db;
|
|
|
|
/**
|
|
* Callback function invoked during a walk of all translations
|
|
*/
|
|
typedef walk_rc_t (*cnat_session_walk_cb_t) (const cnat_session_t *
|
|
session, void *ctx);
|
|
|
|
/**
|
|
* Walk/visit each of the cnat session
|
|
*/
|
|
extern void cnat_session_walk (cnat_session_walk_cb_t cb, void *ctx);
|
|
|
|
/**
|
|
* Scan the session DB for expired sessions
|
|
*/
|
|
extern u64 cnat_session_scan (vlib_main_t * vm, f64 start_time, int i);
|
|
|
|
/**
|
|
* Purge all the sessions
|
|
*/
|
|
extern int cnat_session_purge (void);
|
|
|
|
/**
|
|
* Free a session & update refcounts
|
|
*/
|
|
extern void cnat_session_free (cnat_session_t * session);
|
|
|
|
/**
|
|
* Port cleanup callback
|
|
*/
|
|
extern void (*cnat_free_port_cb) (u16 port, ip_protocol_t iproto);
|
|
|
|
/*
|
|
* fd.io coding-style-patch-verification: ON
|
|
*
|
|
* Local Variables:
|
|
* eval: (c-set-style "gnu")
|
|
* End:
|
|
*/
|
|
|
|
#endif
|