Line data Source code
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/fib/fib_urpf_list.h>
17 : #include <vnet/adj/adj.h>
18 :
19 : /**
20 : * @brief pool of all fib_urpf_list
21 : */
22 : fib_urpf_list_t *fib_urpf_list_pool;
23 :
24 : u8 *
25 244 : format_fib_urpf_list (u8 *s, va_list *args)
26 : {
27 : fib_urpf_list_t *urpf;
28 : index_t ui;
29 : u32 *swi;
30 :
31 244 : ui = va_arg(*args, index_t);
32 :
33 244 : if (INDEX_INVALID != ui)
34 : {
35 232 : urpf = fib_urpf_list_get(ui);
36 :
37 232 : s = format(s, "uPRF-list:%d len:%d itfs:[",
38 232 : ui, vec_len(urpf->furpf_itfs));
39 :
40 378 : vec_foreach(swi, urpf->furpf_itfs)
41 : {
42 146 : s = format(s, "%d, ", *swi);
43 : }
44 232 : s = format(s, "]");
45 : }
46 : else
47 : {
48 12 : s = format(s, "uRPF-list: None");
49 : }
50 :
51 244 : return (s);
52 : }
53 :
54 : index_t
55 91473 : fib_urpf_list_alloc_and_lock (void)
56 : {
57 : fib_urpf_list_t *urpf;
58 91473 : u8 need_barrier_sync = pool_get_will_expand (fib_urpf_list_pool);
59 91473 : vlib_main_t *vm = vlib_get_main();
60 91473 : ASSERT (vm->thread_index == 0);
61 :
62 91473 : if (need_barrier_sync)
63 3932 : vlib_worker_thread_barrier_sync (vm);
64 :
65 91473 : pool_get(fib_urpf_list_pool, urpf);
66 :
67 91473 : if (need_barrier_sync)
68 3932 : vlib_worker_thread_barrier_release (vm);
69 :
70 91473 : clib_memset(urpf, 0, sizeof(*urpf));
71 :
72 91473 : urpf->furpf_locks++;
73 :
74 91473 : return (urpf - fib_urpf_list_pool);
75 : }
76 :
77 : void
78 262237 : fib_urpf_list_unlock (index_t ui)
79 : {
80 : fib_urpf_list_t *urpf;
81 :
82 262237 : if (INDEX_INVALID == ui)
83 112437 : return;
84 :
85 149800 : urpf = fib_urpf_list_get(ui);
86 :
87 149800 : urpf->furpf_locks--;
88 :
89 149800 : if (0 == urpf->furpf_locks)
90 : {
91 79447 : vec_free(urpf->furpf_itfs);
92 79447 : pool_put(fib_urpf_list_pool, urpf);
93 : }
94 : }
95 :
96 : void
97 79876 : fib_urpf_list_lock (index_t ui)
98 : {
99 : fib_urpf_list_t *urpf;
100 :
101 79876 : urpf = fib_urpf_list_get(ui);
102 :
103 79876 : urpf->furpf_locks++;
104 79876 : }
105 :
106 : /**
107 : * @brief Append another interface to the list.
108 : */
109 : void
110 89741 : fib_urpf_list_append (index_t ui,
111 : u32 sw_if_index)
112 : {
113 : fib_urpf_list_t *urpf;
114 :
115 89741 : urpf = fib_urpf_list_get(ui);
116 :
117 89741 : vec_add1(urpf->furpf_itfs, sw_if_index);
118 89741 : }
119 :
120 : /**
121 : * @brief Combine to interface lists
122 : */
123 : void
124 3306 : fib_urpf_list_combine (index_t ui1,
125 : index_t ui2)
126 : {
127 : fib_urpf_list_t *urpf1, *urpf2;
128 :
129 3306 : urpf1 = fib_urpf_list_get(ui1);
130 3306 : urpf2 = fib_urpf_list_get(ui2);
131 :
132 3306 : vec_append(urpf1->furpf_itfs, urpf2->furpf_itfs);
133 3306 : }
134 :
135 : /**
136 : * @brief Sort the interface indicies.
137 : * The sort is the first step in obtaining a unique list, so the order,
138 : * w.r.t. next-hop, interface,etc is not important. So a sort based on the
139 : * index is all we need.
140 : */
141 : static int
142 110941 : fib_urpf_itf_cmp_for_sort (void * v1,
143 : void * v2)
144 : {
145 110941 : const adj_index_t *i1 = v1, *i2 = v2;
146 110941 : return (*i2 < *i1);
147 : }
148 :
149 : /**
150 : * @brief Convert the uRPF list from the itf set obtained during the walk
151 : * to a unique list.
152 : */
153 : void
154 91473 : fib_urpf_list_bake (index_t ui)
155 : {
156 : fib_urpf_list_t *urpf;
157 :
158 91473 : urpf = fib_urpf_list_get(ui);
159 :
160 91473 : ASSERT(!(urpf->furpf_flags & FIB_URPF_LIST_BAKED));
161 :
162 91473 : if (vec_len(urpf->furpf_itfs) > 1)
163 : {
164 : u32 i, j;
165 : /*
166 : * cat list | sort | uniq > rpf_list
167 : */
168 : /* sort */
169 12056 : vec_sort_with_function(urpf->furpf_itfs, fib_urpf_itf_cmp_for_sort);
170 : /* remove duplicates */
171 12056 : i = 0;
172 49623 : for (j=1; j<vec_len(urpf->furpf_itfs); j++)
173 37567 : if (urpf->furpf_itfs[i] != urpf->furpf_itfs[j])
174 24367 : urpf->furpf_itfs[++i] = urpf->furpf_itfs[j];
175 : /* set the length of the vector to the number of unique itfs */
176 12056 : vec_set_len (urpf->furpf_itfs, i+1);
177 : }
178 :
179 91473 : urpf->furpf_flags |= FIB_URPF_LIST_BAKED;
180 91473 : }
181 :
182 : void
183 1 : fib_urpf_list_show_mem (void)
184 : {
185 1 : fib_show_memory_usage("uRPF-list",
186 1 : pool_elts(fib_urpf_list_pool),
187 1 : pool_len(fib_urpf_list_pool),
188 : sizeof(fib_urpf_list_t));
189 1 : }
190 :
191 : static clib_error_t *
192 1 : show_fib_urpf_list_command (vlib_main_t * vm,
193 : unformat_input_t * input,
194 : vlib_cli_command_t * cmd)
195 : {
196 : index_t ui;
197 :
198 1 : if (unformat (input, "%d", &ui))
199 : {
200 : /*
201 : * show one in detail
202 : */
203 0 : if (!pool_is_free_index(fib_urpf_list_pool, ui))
204 : {
205 0 : vlib_cli_output (vm, "%d@%U",
206 : ui,
207 : format_fib_urpf_list, ui);
208 : }
209 : else
210 : {
211 0 : vlib_cli_output (vm, "uRPF %d invalid", ui);
212 : }
213 : }
214 : else
215 : {
216 : /*
217 : * show all
218 : */
219 1 : vlib_cli_output (vm, "FIB uRPF Entries:");
220 8 : pool_foreach_index (ui, fib_urpf_list_pool)
221 : {
222 7 : vlib_cli_output (vm, "%d@%U",
223 : ui,
224 : format_fib_urpf_list, ui);
225 : }
226 : }
227 :
228 1 : return (NULL);
229 : }
230 :
231 : /* *INDENT-OFF* */
232 : /*?
233 : * The '<em>sh fib uRPF [index] </em>' command displays the uRPF lists
234 : *
235 : * @cliexpar
236 : * @cliexstart{show fib uRPF}
237 : * FIB uRPF Entries:
238 : * 0@uPRF-list:0 len:0 itfs:[]
239 : * 1@uPRF-list:1 len:2 itfs:[1, 2, ]
240 : * 2@uPRF-list:2 len:1 itfs:[3, ]
241 : * 3@uPRF-list:3 len:1 itfs:[9, ]
242 : * @cliexend
243 : ?*/
244 285289 : VLIB_CLI_COMMAND (show_fib_urpf_list, static) = {
245 : .path = "show fib uRPF",
246 : .function = show_fib_urpf_list_command,
247 : .short_help = "show fib uRPF",
248 : };
249 : /* *INDENT-OFF* */
|