cnat: Destination based NAT
[vpp.git] / src / plugins / cnat / cnat_client.h
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 #ifndef __CNAT_CLIENT_H__
17 #define __CNAT_CLIENT_H__
18
19 #include <cnat/cnat_types.h>
20
21 /**
22  * A client is a representation of an IP address behind the NAT.
23  * A client thus sends packet to a VIP.
24  * Clients are learned in the Data-plane when they send packets,
25  * but, since they make additions to the FIB they must be programmed
26  * in the main thread. They are aged out when they become idle.
27  *
28  * A client interposes in the FIB graph for the prefix corresponding
29  * to the client (e.g. client's-IP/32). As a result this client object
30  * is cloned as the interpose DPO. The clones are removed when the lock
31  * count drops to zero. The originals are removed when the client ages.
32  * At forwarding time the client preforms the reverse translation and
33  * then ships the packet to where the FIB would send it.
34  */
35 typedef struct cnat_client_t_
36 {
37   CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
38
39   /**
40    * the client's IP address
41    */
42   ip_address_t cc_ip;
43
44   /**
45    * How to send packets to this client post translation
46    */
47   dpo_id_t cc_parent;
48
49   /**
50    * the FIB entry this client sources
51    */
52   fib_node_index_t cc_fei;
53
54   /**
55    * number of DPO locks
56    */
57   u32 cc_locks;
58
59   /**
60    * Translations refcount for cleanup
61    */
62   u32 tr_refcnt;
63
64   /**
65    * Session refcount for cleanup
66    */
67   u32 session_refcnt;
68
69   /**
70    * Parent cnat_client index if cloned via interpose
71    * or own index if vanilla client.
72    * Used to get translations & update session_refcnt
73    */
74   index_t parent_cci;
75
76   /**
77    * Client flags
78    */
79   u8 flags;
80 } cnat_client_t;
81
82 extern u8 *format_cnat_client (u8 * s, va_list * args);
83 extern void cnat_client_free_by_ip (ip46_address_t * addr, u8 af);
84
85 extern cnat_client_t *cnat_client_pool;
86 extern dpo_type_t cnat_client_dpo;
87
88 #define CC_INDEX_INVALID ((u32)(~0))
89
90 static_always_inline cnat_client_t *
91 cnat_client_get (index_t i)
92 {
93   return (pool_elt_at_index (cnat_client_pool, i));
94 }
95
96 typedef struct cnat_learn_arg_t_
97 {
98   ip_address_t addr;
99 } cnat_learn_arg_t;
100
101 /**
102  * A translation that references this VIP was deleted
103  */
104 extern void cnat_client_translation_deleted (index_t cci);
105
106 /**
107  * A translation that references this VIP was added
108  */
109 extern void cnat_client_translation_added (index_t cci);
110 /**
111  * Called in the main thread by RPC from the workers to learn a
112  * new client
113  */
114 extern void cnat_client_learn (const cnat_learn_arg_t * l);
115
116 extern index_t cnat_client_add (const ip_address_t * ip, u8 flags);
117
118 /**
119  * Check all the clients were purged by translation & session purge
120  */
121 extern int cnat_client_purge (void);
122
123 /**
124  * CNat Client (dpo) flags
125  */
126 typedef enum
127 {
128   /* IP already present in the FIB, need to interpose dpo */
129   CNAT_FLAG_EXCLUSIVE = (1 << 1),
130   /* Prune this entry */
131   CNAT_FLAG_EXPIRES = (1 << 2),
132 } cnat_entry_flag_t;
133
134
135 extern void cnat_client_throttle_pool_process ();
136
137 /**
138  * DB of clients
139  */
140 typedef struct cnat_client_db_t_
141 {
142   uword *crd_cip4;
143   uword *crd_cip6;
144   /* Pool of addresses that have been throttled
145      and need to be refcounted before calling
146      cnat_client_free_by_ip */
147   ip_address_t **throttle_pool;
148   clib_spinlock_t *throttle_pool_lock;
149 } cnat_client_db_t;
150
151 extern cnat_client_db_t cnat_client_db;
152
153 /**
154  * Find a client from an IP4 address
155  */
156 static_always_inline cnat_client_t *
157 cnat_client_ip4_find (const ip4_address_t * ip)
158 {
159   uword *p;
160
161   p = hash_get (cnat_client_db.crd_cip4, ip->as_u32);
162
163   if (p)
164     return (pool_elt_at_index (cnat_client_pool, p[0]));
165
166   return (NULL);
167 }
168
169 static_always_inline u32
170 cnat_client_ip4_find_index (const ip4_address_t * ip)
171 {
172   uword *p;
173
174   p = hash_get (cnat_client_db.crd_cip4, ip->as_u32);
175
176   if (p)
177     return p[0];
178
179   return -1;
180 }
181
182 /**
183  * Find a client from an IP6 address
184  */
185 static_always_inline cnat_client_t *
186 cnat_client_ip6_find (const ip6_address_t * ip)
187 {
188   uword *p;
189
190   p = hash_get_mem (cnat_client_db.crd_cip6, ip);
191
192   if (p)
193     return (pool_elt_at_index (cnat_client_pool, p[0]));
194
195   return (NULL);
196 }
197
198 /**
199  * Add a session refcnt to this client
200  */
201 static_always_inline u32
202 cnat_client_cnt_session (cnat_client_t * cc)
203 {
204   cnat_client_t *ccp = cnat_client_get (cc->parent_cci);
205   return clib_atomic_add_fetch (&ccp->session_refcnt, 1);
206 }
207
208 /**
209  * Del a session refcnt to this client
210  */
211 static_always_inline u32
212 cnat_client_uncnt_session (cnat_client_t * cc)
213 {
214   cnat_client_t *ccp = cnat_client_get (cc->parent_cci);
215   return clib_atomic_sub_fetch (&ccp->session_refcnt, 1);
216 }
217
218 /*
219  * fd.io coding-style-patch-verification: ON
220  *
221  * Local Variables:
222  * eval: (c-set-style "gnu")
223  * End:
224  */
225
226 #endif