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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 #ifndef __CNAT_CLIENT_H__
17 #define __CNAT_CLIENT_H__
19 #include <cnat/cnat_types.h>
20 #include <vppinfra/bihash_16_8.h>
23 * A client is a representation of an IP address behind the NAT.
24 * A client thus sends packet to a VIP.
25 * Clients are learned in the Data-plane when they send packets,
26 * but, since they make additions to the FIB they must be programmed
27 * in the main thread. They are aged out when they become idle.
29 * A client interposes in the FIB graph for the prefix corresponding
30 * to the client (e.g. client's-IP/32). As a result this client object
31 * is cloned as the interpose DPO. The clones are removed when the lock
32 * count drops to zero. The originals are removed when the client ages.
33 * At forwarding time the client preforms the reverse translation and
34 * then ships the packet to where the FIB would send it.
36 typedef struct cnat_client_t_
38 CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
41 * the client's IP address
46 * How to send packets to this client post translation
51 * the FIB entry this client sources
53 fib_node_index_t cc_fei;
61 * Translations refcount for cleanup
66 * Session refcount for cleanup
71 * Parent cnat_client index if cloned via interpose
72 * or own index if vanilla client.
73 * Used to get translations & update session_refcnt
83 extern u8 *format_cnat_client (u8 * s, va_list * args);
84 extern void cnat_client_free_by_ip (ip46_address_t * addr, u8 af);
86 extern cnat_client_t *cnat_client_pool;
87 extern dpo_type_t cnat_client_dpo;
89 #define CC_INDEX_INVALID ((u32)(~0))
91 static_always_inline cnat_client_t *
92 cnat_client_get (index_t i)
94 return (pool_elt_at_index (cnat_client_pool, i));
98 * A translation that references this VIP was deleted
100 extern void cnat_client_translation_deleted (index_t cci);
103 * A translation that references this VIP was added
105 extern void cnat_client_translation_added (index_t cci);
107 * Called in the main thread by RPC from the workers to learn a
110 extern void cnat_client_learn (const ip_address_t *addr);
112 extern index_t cnat_client_add (const ip_address_t * ip, u8 flags);
115 * Check all the clients were purged by translation & session purge
117 extern int cnat_client_purge (void);
120 * CNat Client (dpo) flags
124 /* IP already present in the FIB, need to interpose dpo */
125 CNAT_FLAG_EXCLUSIVE = (1 << 1),
129 extern void cnat_client_throttle_pool_process ();
134 typedef struct cnat_client_db_t_
136 clib_bihash_16_8_t cc_ip_id_hash;
137 /* Pool of addresses that have been throttled
138 and need to be refcounted before calling
139 cnat_client_free_by_ip */
140 clib_spinlock_t throttle_lock;
144 extern cnat_client_db_t cnat_client_db;
147 * Find a client from an IP4 address
149 static_always_inline cnat_client_t *
150 cnat_client_ip4_find (const ip4_address_t * ip)
152 clib_bihash_kv_16_8_t bkey, bval;
154 bkey.key[0] = ip->as_u32;
157 if (clib_bihash_search_16_8 (&cnat_client_db.cc_ip_id_hash, &bkey, &bval))
160 return (pool_elt_at_index (cnat_client_pool, bval.value));
164 * Find a client from an IP6 address
166 static_always_inline cnat_client_t *
167 cnat_client_ip6_find (const ip6_address_t * ip)
169 clib_bihash_kv_16_8_t bkey, bval;
171 bkey.key[0] = ip->as_u64[0];
172 bkey.key[1] = ip->as_u64[1];
174 if (clib_bihash_search_16_8 (&cnat_client_db.cc_ip_id_hash, &bkey, &bval))
177 return (pool_elt_at_index (cnat_client_pool, bval.value));
181 * Add a session refcnt to this client
183 static_always_inline u32
184 cnat_client_cnt_session (cnat_client_t * cc)
186 cnat_client_t *ccp = cnat_client_get (cc->parent_cci);
187 return clib_atomic_add_fetch (&ccp->session_refcnt, 1);
191 * Del a session refcnt to this client
193 static_always_inline u32
194 cnat_client_uncnt_session (cnat_client_t * cc)
196 cnat_client_t *ccp = cnat_client_get (cc->parent_cci);
197 return clib_atomic_sub_fetch (&ccp->session_refcnt, 1);
201 * fd.io coding-style-patch-verification: ON
204 * eval: (c-set-style "gnu")