diff options
Diffstat (limited to 'src/plugins/cnat/cnat_client.h')
-rw-r--r-- | src/plugins/cnat/cnat_client.h | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/src/plugins/cnat/cnat_client.h b/src/plugins/cnat/cnat_client.h new file mode 100644 index 00000000000..9bc622dcc2c --- /dev/null +++ b/src/plugins/cnat/cnat_client.h @@ -0,0 +1,226 @@ +/* + * 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_CLIENT_H__ +#define __CNAT_CLIENT_H__ + +#include <cnat/cnat_types.h> + +/** + * A client is a representation of an IP address behind the NAT. + * A client thus sends packet to a VIP. + * Clients are learned in the Data-plane when they send packets, + * but, since they make additions to the FIB they must be programmed + * in the main thread. They are aged out when they become idle. + * + * A client interposes in the FIB graph for the prefix corresponding + * to the client (e.g. client's-IP/32). As a result this client object + * is cloned as the interpose DPO. The clones are removed when the lock + * count drops to zero. The originals are removed when the client ages. + * At forwarding time the client preforms the reverse translation and + * then ships the packet to where the FIB would send it. + */ +typedef struct cnat_client_t_ +{ + CLIB_CACHE_LINE_ALIGN_MARK (cacheline0); + + /** + * the client's IP address + */ + ip_address_t cc_ip; + + /** + * How to send packets to this client post translation + */ + dpo_id_t cc_parent; + + /** + * the FIB entry this client sources + */ + fib_node_index_t cc_fei; + + /** + * number of DPO locks + */ + u32 cc_locks; + + /** + * Translations refcount for cleanup + */ + u32 tr_refcnt; + + /** + * Session refcount for cleanup + */ + u32 session_refcnt; + + /** + * Parent cnat_client index if cloned via interpose + * or own index if vanilla client. + * Used to get translations & update session_refcnt + */ + index_t parent_cci; + + /** + * Client flags + */ + u8 flags; +} cnat_client_t; + +extern u8 *format_cnat_client (u8 * s, va_list * args); +extern void cnat_client_free_by_ip (ip46_address_t * addr, u8 af); + +extern cnat_client_t *cnat_client_pool; +extern dpo_type_t cnat_client_dpo; + +#define CC_INDEX_INVALID ((u32)(~0)) + +static_always_inline cnat_client_t * +cnat_client_get (index_t i) +{ + return (pool_elt_at_index (cnat_client_pool, i)); +} + +typedef struct cnat_learn_arg_t_ +{ + ip_address_t addr; +} cnat_learn_arg_t; + +/** + * A translation that references this VIP was deleted + */ +extern void cnat_client_translation_deleted (index_t cci); + +/** + * A translation that references this VIP was added + */ +extern void cnat_client_translation_added (index_t cci); +/** + * Called in the main thread by RPC from the workers to learn a + * new client + */ +extern void cnat_client_learn (const cnat_learn_arg_t * l); + +extern index_t cnat_client_add (const ip_address_t * ip, u8 flags); + +/** + * Check all the clients were purged by translation & session purge + */ +extern int cnat_client_purge (void); + +/** + * CNat Client (dpo) flags + */ +typedef enum +{ + /* IP already present in the FIB, need to interpose dpo */ + CNAT_FLAG_EXCLUSIVE = (1 << 1), + /* Prune this entry */ + CNAT_FLAG_EXPIRES = (1 << 2), +} cnat_entry_flag_t; + + +extern void cnat_client_throttle_pool_process (); + +/** + * DB of clients + */ +typedef struct cnat_client_db_t_ +{ + uword *crd_cip4; + uword *crd_cip6; + /* Pool of addresses that have been throttled + and need to be refcounted before calling + cnat_client_free_by_ip */ + ip_address_t **throttle_pool; + clib_spinlock_t *throttle_pool_lock; +} cnat_client_db_t; + +extern cnat_client_db_t cnat_client_db; + +/** + * Find a client from an IP4 address + */ +static_always_inline cnat_client_t * +cnat_client_ip4_find (const ip4_address_t * ip) +{ + uword *p; + + p = hash_get (cnat_client_db.crd_cip4, ip->as_u32); + + if (p) + return (pool_elt_at_index (cnat_client_pool, p[0])); + + return (NULL); +} + +static_always_inline u32 +cnat_client_ip4_find_index (const ip4_address_t * ip) +{ + uword *p; + + p = hash_get (cnat_client_db.crd_cip4, ip->as_u32); + + if (p) + return p[0]; + + return -1; +} + +/** + * Find a client from an IP6 address + */ +static_always_inline cnat_client_t * +cnat_client_ip6_find (const ip6_address_t * ip) +{ + uword *p; + + p = hash_get_mem (cnat_client_db.crd_cip6, ip); + + if (p) + return (pool_elt_at_index (cnat_client_pool, p[0])); + + return (NULL); +} + +/** + * Add a session refcnt to this client + */ +static_always_inline u32 +cnat_client_cnt_session (cnat_client_t * cc) +{ + cnat_client_t *ccp = cnat_client_get (cc->parent_cci); + return clib_atomic_add_fetch (&ccp->session_refcnt, 1); +} + +/** + * Del a session refcnt to this client + */ +static_always_inline u32 +cnat_client_uncnt_session (cnat_client_t * cc) +{ + cnat_client_t *ccp = cnat_client_get (cc->parent_cci); + return clib_atomic_sub_fetch (&ccp->session_refcnt, 1); +} + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ + +#endif |