Line data Source code
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 5980 : cnat_client_get (index_t i) 92 : { 93 5980 : return (pool_elt_at_index (cnat_client_pool, i)); 94 : } 95 : 96 : /** 97 : * A translation that references this VIP was deleted 98 : */ 99 : extern void cnat_client_translation_deleted (index_t cci); 100 : 101 : /** 102 : * A translation that references this VIP was added 103 : */ 104 : extern void cnat_client_translation_added (index_t cci); 105 : /** 106 : * Called in the main thread by RPC from the workers to learn a 107 : * new client 108 : */ 109 : extern void cnat_client_learn (const ip_address_t *addr); 110 : 111 : extern index_t cnat_client_add (const ip_address_t * ip, u8 flags); 112 : 113 : /** 114 : * Check all the clients were purged by translation & session purge 115 : */ 116 : extern int cnat_client_purge (void); 117 : 118 : /** 119 : * CNat Client (dpo) flags 120 : */ 121 : typedef enum 122 : { 123 : /* IP already present in the FIB, need to interpose dpo */ 124 : CNAT_FLAG_EXCLUSIVE = (1 << 1), 125 : } cnat_entry_flag_t; 126 : 127 : 128 : extern void cnat_client_throttle_pool_process (); 129 : 130 : /** 131 : * DB of clients 132 : */ 133 : typedef struct cnat_client_db_t_ 134 : { 135 : uword *crd_cip4; 136 : uword *crd_cip6; 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; 141 : uword *throttle_mem; 142 : } cnat_client_db_t; 143 : 144 : extern cnat_client_db_t cnat_client_db; 145 : 146 : /** 147 : * Find a client from an IP4 address 148 : */ 149 : static_always_inline cnat_client_t * 150 162 : cnat_client_ip4_find (const ip4_address_t * ip) 151 : { 152 : uword *p; 153 : 154 162 : p = hash_get (cnat_client_db.crd_cip4, ip->as_u32); 155 : 156 162 : if (p) 157 133 : return (pool_elt_at_index (cnat_client_pool, p[0])); 158 : 159 29 : return (NULL); 160 : } 161 : 162 : static_always_inline u32 163 : cnat_client_ip4_find_index (const ip4_address_t * ip) 164 : { 165 : uword *p; 166 : 167 : p = hash_get (cnat_client_db.crd_cip4, ip->as_u32); 168 : 169 : if (p) 170 : return p[0]; 171 : 172 : return -1; 173 : } 174 : 175 : /** 176 : * Find a client from an IP6 address 177 : */ 178 : static_always_inline cnat_client_t * 179 182 : cnat_client_ip6_find (const ip6_address_t * ip) 180 : { 181 : uword *p; 182 : 183 182 : p = hash_get_mem (cnat_client_db.crd_cip6, ip); 184 : 185 182 : if (p) 186 153 : return (pool_elt_at_index (cnat_client_pool, p[0])); 187 : 188 29 : return (NULL); 189 : } 190 : 191 : /** 192 : * Add a session refcnt to this client 193 : */ 194 : static_always_inline u32 195 446 : cnat_client_cnt_session (cnat_client_t * cc) 196 : { 197 446 : cnat_client_t *ccp = cnat_client_get (cc->parent_cci); 198 446 : return clib_atomic_add_fetch (&ccp->session_refcnt, 1); 199 : } 200 : 201 : /** 202 : * Del a session refcnt to this client 203 : */ 204 : static_always_inline u32 205 176 : cnat_client_uncnt_session (cnat_client_t * cc) 206 : { 207 176 : cnat_client_t *ccp = cnat_client_get (cc->parent_cci); 208 176 : return clib_atomic_sub_fetch (&ccp->session_refcnt, 1); 209 : } 210 : 211 : /* 212 : * fd.io coding-style-patch-verification: ON 213 : * 214 : * Local Variables: 215 : * eval: (c-set-style "gnu") 216 : * End: 217 : */ 218 : 219 : #endif