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 : 17 : #ifndef __CNAT_INLINE_H__ 18 : #define __CNAT_INLINE_H__ 19 : 20 : #include <cnat/cnat_types.h> 21 : 22 : always_inline int 23 4899 : cnat_ts_is_free_index (u32 index) 24 : { 25 4899 : u32 pidx = index >> (32 - CNAT_TS_MPOOL_BITS); 26 4899 : index = index & (0xffffffff >> CNAT_TS_MPOOL_BITS); 27 4899 : return pool_is_free_index (cnat_timestamps.ts_pools[pidx], index); 28 : } 29 : 30 : always_inline cnat_timestamp_t * 31 4730 : cnat_timestamp_get (u32 index) 32 : { 33 : /* 6 top bits for choosing pool */ 34 4730 : u32 pidx = index >> (32 - CNAT_TS_MPOOL_BITS); 35 4730 : index = index & (0xffffffff >> CNAT_TS_MPOOL_BITS); 36 4730 : return pool_elt_at_index (cnat_timestamps.ts_pools[pidx], index); 37 : } 38 : 39 : always_inline cnat_timestamp_t * 40 5434 : cnat_timestamp_get_if_valid (u32 index) 41 : { 42 : /* 6 top bits for choosing pool */ 43 5434 : u32 pidx = index >> (32 - CNAT_TS_MPOOL_BITS); 44 5434 : index = index & (0xffffffff >> CNAT_TS_MPOOL_BITS); 45 5434 : if (pidx >= cnat_timestamps.next_empty_pool_idx) 46 0 : return (NULL); 47 5434 : if (pool_is_free_index (cnat_timestamps.ts_pools[pidx], index)) 48 0 : return (NULL); 49 5434 : return pool_elt_at_index (cnat_timestamps.ts_pools[pidx], index); 50 : } 51 : 52 : always_inline index_t 53 140 : cnat_timestamp_alloc () 54 : { 55 : cnat_timestamp_t *ts; 56 : u32 index, pool_sz; 57 : uword pidx; 58 : 59 140 : clib_spinlock_lock (&cnat_timestamps.ts_lock); 60 140 : pidx = clib_bitmap_first_set (cnat_timestamps.ts_free); 61 140 : pool_sz = 1 << (CNAT_TS_BASE_SIZE + pidx); 62 140 : ASSERT (pidx <= cnat_timestamps.next_empty_pool_idx); 63 140 : if (pidx == cnat_timestamps.next_empty_pool_idx) 64 2 : pool_init_fixed ( 65 : cnat_timestamps.ts_pools[cnat_timestamps.next_empty_pool_idx++], 66 : pool_sz); 67 140 : pool_get (cnat_timestamps.ts_pools[pidx], ts); 68 140 : if (pool_elts (cnat_timestamps.ts_pools[pidx]) == pool_sz) 69 0 : clib_bitmap_set (cnat_timestamps.ts_free, pidx, 0); 70 140 : clib_spinlock_unlock (&cnat_timestamps.ts_lock); 71 : 72 140 : index = (u32) pidx << (32 - CNAT_TS_MPOOL_BITS); 73 140 : return index | (ts - cnat_timestamps.ts_pools[pidx]); 74 : } 75 : 76 : always_inline void 77 122 : cnat_timestamp_destroy (u32 index) 78 : { 79 122 : u32 pidx = index >> (32 - CNAT_TS_MPOOL_BITS); 80 122 : index = index & (0xffffffff >> CNAT_TS_MPOOL_BITS); 81 122 : clib_spinlock_lock (&cnat_timestamps.ts_lock); 82 122 : pool_put_index (cnat_timestamps.ts_pools[pidx], index); 83 122 : clib_bitmap_set (cnat_timestamps.ts_free, pidx, 1); 84 122 : clib_spinlock_unlock (&cnat_timestamps.ts_lock); 85 122 : } 86 : 87 : always_inline u32 88 140 : cnat_timestamp_new (f64 t) 89 : { 90 140 : index_t index = cnat_timestamp_alloc (); 91 140 : cnat_timestamp_t *ts = cnat_timestamp_get (index); 92 140 : ts->last_seen = t; 93 140 : ts->lifetime = cnat_main.session_max_age; 94 140 : ts->refcnt = CNAT_TIMESTAMP_INIT_REFCNT; 95 140 : return index; 96 : } 97 : 98 : always_inline void 99 140 : cnat_timestamp_inc_refcnt (u32 index) 100 : { 101 140 : cnat_timestamp_t *ts = cnat_timestamp_get (index); 102 140 : clib_atomic_add_fetch (&ts->refcnt, 1); 103 140 : } 104 : 105 : always_inline void 106 4450 : cnat_timestamp_update (u32 index, f64 t) 107 : { 108 4450 : cnat_timestamp_t *ts = cnat_timestamp_get (index); 109 4450 : ts->last_seen = t; 110 4450 : } 111 : 112 : always_inline void 113 0 : cnat_timestamp_set_lifetime (u32 index, u16 lifetime) 114 : { 115 0 : cnat_timestamp_t *ts = cnat_timestamp_get (index); 116 0 : ts->lifetime = lifetime; 117 0 : } 118 : 119 : always_inline f64 120 5172 : cnat_timestamp_exp (u32 index) 121 : { 122 : f64 t; 123 5172 : cnat_timestamp_t *ts = cnat_timestamp_get_if_valid (index); 124 5172 : if (NULL == ts) 125 0 : return -1; 126 5172 : t = ts->last_seen + (f64) ts->lifetime; 127 5172 : return t; 128 : } 129 : 130 : always_inline void 131 262 : cnat_timestamp_free (u32 index) 132 : { 133 262 : cnat_timestamp_t *ts = cnat_timestamp_get_if_valid (index); 134 262 : if (NULL == ts) 135 0 : return; 136 262 : if (0 == clib_atomic_sub_fetch (&ts->refcnt, 1)) 137 122 : cnat_timestamp_destroy (index); 138 : } 139 : 140 : /* 141 : * fd.io coding-style-patch-verification: ON 142 : * 143 : * Local Variables: 144 : * eval: (c-set-style "gnu") 145 : * End: 146 : */ 147 : 148 : #endif