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 : #include <vppinfra/bihash_16_8.h> 21 : 22 : /** 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. 28 : * 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. 35 : */ 36 : typedef struct cnat_client_t_ 37 : { 38 : CLIB_CACHE_LINE_ALIGN_MARK (cacheline0); 39 : 40 : /** 41 : * the client's IP address 42 : */ 43 : ip_address_t cc_ip; 44 : 45 : /** 46 : * How to send packets to this client post translation 47 : */ 48 : dpo_id_t cc_parent; 49 : 50 : /** 51 : * the FIB entry this client sources 52 : */ 53 : fib_node_index_t cc_fei; 54 : 55 : /** 56 : * number of DPO locks 57 : */ 58 : u32 cc_locks; 59 : 60 : /** 61 : * Translations refcount for cleanup 62 : */ 63 : u32 tr_refcnt; 64 : 65 : /** 66 : * Session refcount for cleanup 67 : */ 68 : u32 session_refcnt; 69 : 70 : /** 71 : * Parent cnat_client index if cloned via interpose 72 : * or own index if vanilla client. 73 : * Used to get translations & update session_refcnt 74 : */ 75 : index_t parent_cci; 76 : 77 : /** 78 : * Client flags 79 : */ 80 : u8 flags; 81 : } cnat_client_t; 82 : 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); 85 : 86 : extern cnat_client_t *cnat_client_pool; 87 : extern dpo_type_t cnat_client_dpo; 88 : 89 : static_always_inline cnat_client_t * 90 6297 : cnat_client_get (index_t i) 91 : { 92 6297 : return (pool_elt_at_index (cnat_client_pool, i)); 93 : } 94 : 95 : /** 96 : * A translation that references this VIP was deleted 97 : */ 98 : extern void cnat_client_translation_deleted (index_t cci); 99 : 100 : /** 101 : * A translation that references this VIP was added 102 : */ 103 : extern void cnat_client_translation_added (index_t cci); 104 : /** 105 : * Called in the main thread by RPC from the workers to learn a 106 : * new client 107 : */ 108 : extern void cnat_client_learn (const ip_address_t *addr); 109 : 110 : extern index_t cnat_client_add (const ip_address_t * ip, u8 flags); 111 : 112 : /** 113 : * Check all the clients were purged by translation & session purge 114 : */ 115 : extern int cnat_client_purge (void); 116 : 117 : /** 118 : * CNat Client (dpo) flags 119 : */ 120 : typedef enum 121 : { 122 : /* IP already present in the FIB, need to interpose dpo */ 123 : CNAT_FLAG_EXCLUSIVE = (1 << 1), 124 : } cnat_entry_flag_t; 125 : 126 : 127 : extern void cnat_client_throttle_pool_process (); 128 : 129 : /** 130 : * DB of clients 131 : */ 132 : typedef struct cnat_client_db_t_ 133 : { 134 : clib_bihash_16_8_t cc_ip_id_hash; 135 : /* Pool of addresses that have been throttled 136 : and need to be refcounted before calling 137 : cnat_client_free_by_ip */ 138 : clib_spinlock_t throttle_lock; 139 : uword *throttle_mem; 140 : } cnat_client_db_t; 141 : 142 : extern cnat_client_db_t cnat_client_db; 143 : 144 : /** 145 : * Find a client from an IP4 address 146 : */ 147 : static_always_inline cnat_client_t * 148 251 : cnat_client_ip4_find (const ip4_address_t * ip) 149 : { 150 : clib_bihash_kv_16_8_t bkey, bval; 151 : 152 251 : bkey.key[0] = ip->as_u32; 153 251 : bkey.key[1] = 0; 154 : 155 251 : if (clib_bihash_search_16_8 (&cnat_client_db.cc_ip_id_hash, &bkey, &bval)) 156 38 : return (NULL); 157 : 158 213 : return (pool_elt_at_index (cnat_client_pool, bval.value)); 159 : } 160 : 161 : /** 162 : * Find a client from an IP6 address 163 : */ 164 : static_always_inline cnat_client_t * 165 191 : cnat_client_ip6_find (const ip6_address_t * ip) 166 : { 167 : clib_bihash_kv_16_8_t bkey, bval; 168 : 169 191 : bkey.key[0] = ip->as_u64[0]; 170 191 : bkey.key[1] = ip->as_u64[1]; 171 : 172 191 : if (clib_bihash_search_16_8 (&cnat_client_db.cc_ip_id_hash, &bkey, &bval)) 173 30 : return (NULL); 174 : 175 161 : return (pool_elt_at_index (cnat_client_pool, bval.value)); 176 : } 177 : 178 : /** 179 : * Add a session refcnt to this client 180 : */ 181 : static_always_inline u32 182 242 : cnat_client_cnt_session (cnat_client_t * cc) 183 : { 184 242 : cnat_client_t *ccp = cnat_client_get (cc->parent_cci); 185 242 : return clib_atomic_add_fetch (&ccp->session_refcnt, 1); 186 : } 187 : 188 : /** 189 : * Del a session refcnt to this client 190 : */ 191 : static_always_inline u32 192 242 : cnat_client_uncnt_session (cnat_client_t * cc) 193 : { 194 242 : cnat_client_t *ccp = cnat_client_get (cc->parent_cci); 195 242 : return clib_atomic_sub_fetch (&ccp->session_refcnt, 1); 196 : } 197 : 198 : /* 199 : * fd.io coding-style-patch-verification: ON 200 : * 201 : * Local Variables: 202 : * eval: (c-set-style "gnu") 203 : * End: 204 : */ 205 : 206 : #endif