FD.io VPP  v16.12-rc0-171-g5499b19
Vector Packet Processing
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
adj_alloc.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 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 #include <vnet/adj/adj_alloc.h>
17 #include <vnet/ip/ip.h>
18 
19 /*
20  * the single adj heap
21  */
23 
24 /*
25  * any operation which could cause the adj vector to be reallocated
26  * must have a worker thread barrier
27  */
28 static inline int will_reallocate (ip_adjacency_t * adjs, u32 n)
29 {
30  uword aligned_header_bytes, new_data_bytes;
31  uword data_bytes;
32  aa_header_t * ah = aa_header (adjs);
33 
34  if (adjs == 0)
35  return 1;
36 
37  data_bytes = (vec_len (adjs) + n) * sizeof (*adjs);
38 
39  aligned_header_bytes = vec_header_bytes (aa_aligned_header_bytes);
40 
41  new_data_bytes = data_bytes + aligned_header_bytes;
42 
43  ASSERT (clib_mem_is_heap_object (_vec_find(ah)));
44 
45  if (PREDICT_TRUE(new_data_bytes <= clib_mem_size (_vec_find(ah))))
46  return 0;
47 
48  return 1;
49 }
50 
52 aa_alloc (void)
53 {
55  aa_header_t * ah = aa_header (adj_heap);
56  ip_adjacency_t * adj_block;
57  u32 freelist_length;
58  int need_barrier_sync = 0;
59  u32 n = 1;
60 
61  ASSERT(os_get_cpu_number() == 0);
62  ASSERT (clib_mem_is_heap_object (_vec_find(ah)));
63 
64  /* If we don't have a freelist of size N, fresh allocation is required */
65  if (vec_len (ah->free_indices_by_size) <= n)
66  {
67  if (will_reallocate (adj_heap, n))
68  {
69  need_barrier_sync = 1;
71  }
72  /* Workers wont look at the freelists... */
74  vec_add2_ha (adj_heap, adj_block, n, aa_aligned_header_bytes,
76  if (need_barrier_sync)
78  goto out;
79  }
80  /* See if we have a free adj block to dole out */
81  if ((freelist_length = vec_len(ah->free_indices_by_size[n])))
82  {
83  u32 index = ah->free_indices_by_size[n][freelist_length-1];
84 
85  adj_block = &adj_heap[index];
86  _vec_len(ah->free_indices_by_size[n]) -= 1;
87  goto out;
88  }
89  /* Allocate a new block of size N */
90  if (will_reallocate (adj_heap, n))
91  {
92  need_barrier_sync = 1;
94  }
95  vec_add2_ha (adj_heap, adj_block, n, aa_aligned_header_bytes,
97 
98  if (need_barrier_sync)
100 
101  out:
102  memset (adj_block, 0, n * (sizeof(*adj_block)));
103  adj_block->heap_handle = adj_block - adj_heap;
104  adj_block->n_adj = n;
105 
106  /*
107  * the adj heap may have realloc'd. recache.
108  */
111 
112  return (adj_block);
113 }
114 
116 {
117  aa_header_t * ah = aa_header (adj_heap);
118 
119  ASSERT (adj_heap && adj && (adj->heap_handle < vec_len (adj_heap)));
120  ASSERT (adj->heap_handle != 0);
121 
123  adj->heap_handle = 0;
124 }
125 
127 {
128  ip_adjacency_t * adj_block;
129  aa_header_t * ah;
130  int i;
131 
132  vec_add2_ha (adj_heap, adj_block, n, aa_aligned_header_bytes,
134 
135  memset (adj_block, 0, n * sizeof(*adj_block));
136  ah = aa_header (adj_heap);
137  memset (ah, 0, sizeof (*ah));
138 
140 
141  for (i = 0 ; i < vec_len (adj_heap); i++)
142  {
143  adj_block->n_adj = 1;
144  adj_block->heap_handle = ~0;
145  /* Euchre the allocator into returning 0, 1, 2, etc. */
146  vec_add1 (ah->free_indices_by_size[1], n - (i+1));
147  }
148 
151 }
152 
153 u8 * format_adjacency_alloc (u8 * s, va_list * args)
154 {
155  vnet_main_t * vnm = va_arg (*args, vnet_main_t *);
156  int verbose = va_arg (*args, int);
157  ip_adjacency_t * adj;
158  u32 inuse = 0, freed = 0;
159  u32 on_freelist = 0;
160  int i, j;
161  aa_header_t * ah = aa_header (adj_heap);
162 
163  for (i = 0; i < vec_len (adj_heap); i += adj->n_adj)
164  {
165  adj = adj_heap + i;
166  if ((i == 0) || adj->heap_handle)
167  inuse += adj->n_adj;
168  else
169  freed += adj->n_adj;
170  }
171 
172  for (i = 1; i < vec_len(ah->free_indices_by_size); i++)
173  {
174  for (j = 0; j < vec_len(ah->free_indices_by_size[i]); j++)
175  {
176  adj = adj_heap + ah->free_indices_by_size[i][j];
177  ASSERT(adj->heap_handle == 0);
178  on_freelist += adj->n_adj;
179  }
180  }
181 
182  s = format (s, "adj_heap: %d total, %d in use, %d free, %d on freelists\n",
183  vec_len(adj_heap), inuse, freed, on_freelist);
184  if (verbose)
185  {
186  for (i = 0; i < vec_len (adj_heap); i += adj->n_adj)
187  {
188  adj = adj_heap + i;
189  if ((i == 0) || adj->heap_handle)
190  {
191  if (adj->n_adj > 1)
192  s = format (s, "[%d-%d] ", i, i+adj->n_adj-1);
193  else
194  s = format (s, "[%d] ", i);
195 
196  for (j = 0; j < adj->n_adj; j++)
197  {
198  if (j > 0)
199  s = format (s, " ");
200 
201  s = format(s, "%U\n", format_ip_adjacency,
202  vnm, i+j, FORMAT_IP_ADJACENCY_NONE);
203  }
204  }
205  }
206  }
207  return s;
208 }
209 
210 static clib_error_t *
212  unformat_input_t * input,
213  vlib_cli_command_t * cmd)
214 {
215  int verbose = 0;
216  vnet_main_t *vnm = vnet_get_main();
217 
218  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
219  {
220  if (unformat (input, "verbose"))
221  verbose = 1;
222  else
223  return clib_error_return (0, "unknown input `%U'",
224  format_unformat_error, input);
225  }
226 
227  vlib_cli_output (vm, "%U", format_adjacency_alloc, vnm, verbose);
228 
229  return 0;
230 }
231 
232 VLIB_CLI_COMMAND (show_adjacency_alloc_command, static) = {
233  .path = "show adjacency alloc",
234  .short_help = "show adjacency alloc",
236 };
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:396
Adjacency allocator: heap-like in that the code will dole out contiguous chunks of n items...
Definition: adj_alloc.h:34
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
u32 heap_handle
Definition: lookup.h:177
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:966
ip_adjacency_t * aa_alloc(void)
Definition: adj_alloc.c:52
ip_adjacency_t * adjacency_heap
Definition: lookup.h:345
#define PREDICT_TRUE(x)
Definition: clib.h:98
ip_adjacency_t * adj_heap
The global adjacnecy heap.
Definition: adj_alloc.c:22
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
IP unicast adjacency.
Definition: lookup.h:174
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:482
ip_lookup_main_t lookup_main
Definition: ip4.h:96
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
static uword vec_header_bytes(uword header_bytes)
Definition: vec_bootstrap.h:79
static int will_reallocate(ip_adjacency_t *adjs, u32 n)
Definition: adj_alloc.c:28
static clib_error_t * show_adjacency_alloc_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: adj_alloc.c:211
void aa_bootstrap(u32 n)
Definition: adj_alloc.c:126
#define vec_add2_ha(V, P, N, H, A)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:504
uword os_get_cpu_number(void)
Definition: unix-misc.c:224
void aa_free(ip_adjacency_t *adj)
Definition: adj_alloc.c:115
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:575
static uword clib_mem_size(void *p)
Definition: mem.h:187
vlib_main_t vlib_global_main
Definition: main.c:1535
void vlib_worker_thread_barrier_sync(vlib_main_t *vm)
Definition: threads.c:1197
#define aa_aligned_header_bytes
Definition: adj_alloc.h:38
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
ip6_main_t ip6_main
Definition: ip6_forward.c:2627
ip_lookup_main_t lookup_main
Definition: ip6.h:132
static uword clib_mem_is_heap_object(void *p)
Definition: mem.h:137
u32 ** free_indices_by_size
Definition: adj_alloc.h:35
u64 uword
Definition: types.h:112
u16 n_adj
Number of adjecencies in block.
Definition: lookup.h:181
VLIB_CLI_COMMAND(set_interface_ip_source_and_port_range_check_command, static)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
u8 * format_adjacency_alloc(u8 *s, va_list *args)
Definition: adj_alloc.c:153
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
void vlib_worker_thread_barrier_release(vlib_main_t *vm)
Definition: threads.c:1229
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:418
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:996
#define clib_error_return(e, args...)
Definition: error.h:111
struct _unformat_input_t unformat_input_t
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
static aa_header_t * aa_header(void *v)
Definition: adj_alloc.h:42
format_function_t format_ip_adjacency
Definition: format.h:57