FD.io VPP  v16.09
Vector Packet Processing
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/ip/adj_alloc.h>
17 #include <vnet/ip/ip.h>
18 
19 /*
20  * any operation which could cause the adj vector to be reallocated
21  * must have a worker thread barrier
22  */
23 
24 static inline int will_reallocate (ip_adjacency_t * adjs, u32 n)
25 {
26  uword aligned_header_bytes, new_data_bytes;
27  uword data_bytes;
28  aa_header_t * ah = aa_header (adjs);
29 
30  if (adjs == 0)
31  return 1;
32 
33  data_bytes = (vec_len (adjs) + n) * sizeof (*adjs);
34 
35  aligned_header_bytes = vec_header_bytes (aa_aligned_header_bytes);
36 
37  new_data_bytes = data_bytes + aligned_header_bytes;
38 
39  ASSERT (clib_mem_is_heap_object (_vec_find(ah)));
40 
41  if (PREDICT_TRUE(new_data_bytes <= clib_mem_size (_vec_find(ah))))
42  return 0;
43 
44  return 1;
45 }
46 
49 {
51  aa_header_t * ah = aa_header (adjs);
52  ip_adjacency_t * adj_block;
53  u32 freelist_length;
54  int need_barrier_sync = 0;
55 
56  ASSERT(os_get_cpu_number() == 0);
57  ASSERT (clib_mem_is_heap_object (_vec_find(ah)));
58 
59  /* If we don't have a freelist of size N, fresh allocation is required */
60  if (vec_len (ah->free_indices_by_size) <= n)
61  {
62  if (will_reallocate (adjs, n))
63  {
64  need_barrier_sync = 1;
66  }
67  /* Workers wont look at the freelists... */
69  vec_add2_ha (adjs, adj_block, n, aa_aligned_header_bytes,
71  if (need_barrier_sync)
73  goto out;
74  }
75  /* See if we have a free adj block to dole out */
76  if ((freelist_length = vec_len(ah->free_indices_by_size[n])))
77  {
78  u32 index = ah->free_indices_by_size[n][freelist_length-1];
79 
80  adj_block = &adjs[index];
81  _vec_len(ah->free_indices_by_size[n]) -= 1;
82  goto out;
83  }
84  /* Allocate a new block of size N */
85  if (will_reallocate (adjs, n))
86  {
87  need_barrier_sync = 1;
89  }
90  vec_add2_ha (adjs, adj_block, n, aa_aligned_header_bytes,
92 
93  if (need_barrier_sync)
95 
96  out:
97  memset (adj_block, 0, n * (sizeof(*adj_block)));
98  adj_block->heap_handle = adj_block - adjs;
99  adj_block->n_adj = n;
100  *blockp = adj_block;
101  return adjs;
102 }
103 
105 {
106  aa_header_t * ah = aa_header (adjs);
107 
108  ASSERT (adjs && adj && (adj->heap_handle < vec_len (adjs)));
109  ASSERT (adj->n_adj < vec_len (ah->free_indices_by_size));
110  ASSERT (adj->heap_handle != 0);
111 
113  adj->heap_handle = 0;
114 }
115 
117 {
118  ip_adjacency_t * adj_block;
119  aa_header_t * ah;
120  int i;
121 
122  vec_add2_ha (adjs, adj_block, n, aa_aligned_header_bytes,
124 
125  memset (adj_block, 0, n * sizeof(*adj_block));
126  ah = aa_header (adjs);
127  memset (ah, 0, sizeof (*ah));
128 
130 
131  for (i = 0 ; i < vec_len (adjs); i++)
132  {
133  adj_block->n_adj = 1;
134  adj_block->heap_handle = ~0;
135  /* Euchre the allocator into returning 0, 1, 2, etc. */
136  vec_add1 (ah->free_indices_by_size[1], n - (i+1));
137  }
138 
139  return adjs;
140 }
141 
142 u8 * format_adjacency_alloc (u8 * s, va_list * args)
143 {
144  vnet_main_t * vnm = va_arg (*args, vnet_main_t *);
145  ip_lookup_main_t * lm = va_arg (*args, ip_lookup_main_t *);
146  ip_adjacency_t * adjs = va_arg (*args, ip_adjacency_t *);
147  int verbose = va_arg (*args, int);
148  ip_adjacency_t * adj;
149  u32 inuse = 0, freed = 0;
150  u32 on_freelist = 0;
151  int i, j;
152  aa_header_t * ah = aa_header (adjs);
153 
154  for (i = 0; i < vec_len (adjs); i += adj->n_adj)
155  {
156  adj = adjs + i;
157  if ((i == 0) || adj->heap_handle)
158  inuse += adj->n_adj;
159  else
160  freed += adj->n_adj;
161  }
162 
163  for (i = 1; i < vec_len(ah->free_indices_by_size); i++)
164  {
165  for (j = 0; j < vec_len(ah->free_indices_by_size[i]); j++)
166  {
167  adj = adjs + ah->free_indices_by_size[i][j];
168  ASSERT(adj->heap_handle == 0);
169  on_freelist += adj->n_adj;
170  }
171  }
172 
173  s = format (s, "adjs: %d total, %d in use, %d free, %d on freelists\n",
174  vec_len(adjs), inuse, freed, on_freelist);
175  if (verbose)
176  {
177  for (i = 0; i < vec_len (adjs); i += adj->n_adj)
178  {
179  adj = adjs + i;
180  if ((i == 0) || adj->heap_handle)
181  {
182  if (adj->n_adj > 1)
183  s = format (s, "[%d-%d] ", i, i+adj->n_adj-1);
184  else
185  s = format (s, "[%d] ", i);
186 
187  for (j = 0; j < adj->n_adj; j++)
188  {
189  if (j > 0)
190  s = format (s, " ");
191 
192  s = format(s, "%U\n", format_ip_adjacency,
193  vnm, lm, i+j);
194  }
195  }
196  }
197  }
198  return s;
199 }
200 
201 static clib_error_t *
203  unformat_input_t * input,
204  vlib_cli_command_t * cmd)
205 {
206  int verbose = 0;
207  vnet_main_t *vnm = vnet_get_main();
208  ip_lookup_main_t *lm = 0;
209  ip_adjacency_t * adjs = 0;
210  int is_ip4 = 1;
211 
212  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
213  {
214  if (unformat (input, "verbose"))
215  verbose = 1;
216  else if (unformat (input, "ip4"))
217  ;
218  else if (unformat (input, "ip6"))
219  is_ip4 = 0;
220  else
221  return clib_error_return (0, "unknown input `%U'",
222  format_unformat_error, input);
223  }
224 
225  if (is_ip4)
226  lm = &ip4_main.lookup_main;
227  else
228  lm = &ip6_main.lookup_main;
229 
230  adjs = lm->adjacency_heap;
231 
232  vlib_cli_output (vm, "%U", format_adjacency_alloc, vnm, lm, adjs, verbose);
233 
234  return 0;
235 }
236 
237 VLIB_CLI_COMMAND (show_adjacency_alloc_command, static) = {
238  .path = "show adjacency alloc",
239  .short_help = "show adjacency alloc",
241 };
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:396
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:966
ip_adjacency_t * adjacency_heap
Adjacency heap.
Definition: lookup.h:401
u16 n_adj
Number of adjecencies in block.
Definition: lookup.h:176
#define PREDICT_TRUE(x)
Definition: clib.h:98
IP unicast adjacency.
Definition: lookup.h:164
ip_adjacency_t * aa_bootstrap(ip_adjacency_t *adjs, u32 n)
Definition: adj_alloc.c:116
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
ip_adjacency_t * aa_alloc(ip_adjacency_t *adjs, ip_adjacency_t **blockp, u32 n)
Definition: adj_alloc.c:48
void aa_free(ip_adjacency_t *adjs, ip_adjacency_t *adj)
Definition: adj_alloc.c:104
#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:115
vnet_main_t * vnet_get_main(void)
Definition: misc.c:45
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:24
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:202
#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 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:1144
#define aa_aligned_header_bytes
Definition: adj_alloc.h:37
#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:2955
ip_lookup_main_t lookup_main
Definition: ip6.h:110
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:418
static uword clib_mem_is_heap_object(void *p)
Definition: mem.h:137
u32 ** free_indices_by_size
Definition: adj_alloc.h:34
u64 uword
Definition: types.h:112
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
u32 heap_handle
Handle for this adjacency in adjacency heap.
Definition: lookup.h:167
u8 * format_adjacency_alloc(u8 *s, va_list *args)
Definition: adj_alloc.c:142
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:1176
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1578
#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:41
format_function_t format_ip_adjacency
Definition: format.h:51