udp: fix csum computation when offload disabled
[vpp.git] / src / vnet / fib / fib_urpf_list.c
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 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     ui = va_arg(*args, index_t);
32
33     if (INDEX_INVALID != ui)
34     {
35         urpf = fib_urpf_list_get(ui);
36
37         s = format(s, "uPRF-list:%d len:%d itfs:[",
38                    ui, vec_len(urpf->furpf_itfs));
39
40         vec_foreach(swi, urpf->furpf_itfs)
41         {
42             s = format(s, "%d, ", *swi);
43         }
44         s = format(s, "]");
45     }
46     else
47     {
48         s = format(s, "uRPF-list: None");
49     }
50
51     return (s);
52 }
53
54 index_t
55 fib_urpf_list_alloc_and_lock (void)
56 {
57     fib_urpf_list_t *urpf;
58     u8 need_barrier_sync = pool_get_will_expand (fib_urpf_list_pool);
59     vlib_main_t *vm = vlib_get_main();
60     ASSERT (vm->thread_index == 0);
61
62     if (need_barrier_sync)
63         vlib_worker_thread_barrier_sync (vm);
64
65     pool_get(fib_urpf_list_pool, urpf);
66
67     if (need_barrier_sync)
68         vlib_worker_thread_barrier_release (vm);
69
70     clib_memset(urpf, 0, sizeof(*urpf));
71
72     urpf->furpf_locks++;
73
74     return (urpf - fib_urpf_list_pool);
75 }
76
77 void
78 fib_urpf_list_unlock (index_t ui)
79 {
80     fib_urpf_list_t *urpf;
81
82     if (INDEX_INVALID == ui)
83         return;
84
85     urpf = fib_urpf_list_get(ui);
86
87     urpf->furpf_locks--;
88
89     if (0 == urpf->furpf_locks)
90     {
91         vec_free(urpf->furpf_itfs);
92         pool_put(fib_urpf_list_pool, urpf);
93     }
94 }
95
96 void
97 fib_urpf_list_lock (index_t ui)
98 {
99     fib_urpf_list_t *urpf;
100
101     urpf = fib_urpf_list_get(ui);
102
103     urpf->furpf_locks++;
104 }
105
106 /**
107  * @brief Append another interface to the list.
108  */
109 void
110 fib_urpf_list_append (index_t ui,
111                       u32 sw_if_index)
112 {
113     fib_urpf_list_t *urpf;
114
115     urpf = fib_urpf_list_get(ui);
116
117     vec_add1(urpf->furpf_itfs, sw_if_index);
118 }
119
120 /**
121  * @brief Combine to interface lists
122  */
123 void
124 fib_urpf_list_combine (index_t ui1,
125                        index_t ui2)
126 {
127     fib_urpf_list_t *urpf1, *urpf2;
128
129     urpf1 = fib_urpf_list_get(ui1);
130     urpf2 = fib_urpf_list_get(ui2);
131
132     vec_append(urpf1->furpf_itfs, urpf2->furpf_itfs);
133 }
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 fib_urpf_itf_cmp_for_sort (void * v1,
143                            void * v2)
144 {
145     const adj_index_t *i1 = v1, *i2 = v2;
146     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 fib_urpf_list_bake (index_t ui)
155 {
156     fib_urpf_list_t *urpf;
157
158     urpf = fib_urpf_list_get(ui);
159
160     ASSERT(!(urpf->furpf_flags & FIB_URPF_LIST_BAKED));
161
162     if (vec_len(urpf->furpf_itfs) > 1)
163       {
164         u32 i, j;
165         /*
166          * cat list | sort | uniq > rpf_list
167          */
168         /* sort */
169         vec_sort_with_function(urpf->furpf_itfs, fib_urpf_itf_cmp_for_sort);
170         /* remove duplicates */
171         i = 0;
172         for (j=1; j<vec_len(urpf->furpf_itfs); j++)
173           if (urpf->furpf_itfs[i] != urpf->furpf_itfs[j])
174             urpf->furpf_itfs[++i] = urpf->furpf_itfs[j];
175         /* set the length of the vector to the number of unique itfs */
176         vec_set_len (urpf->furpf_itfs, i+1);
177       }
178
179     urpf->furpf_flags |= FIB_URPF_LIST_BAKED;
180 }
181
182 void
183 fib_urpf_list_show_mem (void)
184 {
185     fib_show_memory_usage("uRPF-list",
186                           pool_elts(fib_urpf_list_pool),
187                           pool_len(fib_urpf_list_pool),
188                           sizeof(fib_urpf_list_t));
189 }
190
191 static clib_error_t *
192 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     if (unformat (input, "%d", &ui))
199     {
200         /*
201          * show one in detail
202          */
203         if (!pool_is_free_index(fib_urpf_list_pool, ui))
204         {
205             vlib_cli_output (vm, "%d@%U",
206                              ui,
207                              format_fib_urpf_list, ui);
208         }
209         else
210         {
211             vlib_cli_output (vm, "uRPF %d invalid", ui);
212         }
213     }
214     else
215     {
216         /*
217          * show all
218          */
219         vlib_cli_output (vm, "FIB uRPF Entries:");
220         pool_foreach_index (ui, fib_urpf_list_pool)
221          {
222             vlib_cli_output (vm, "%d@%U",
223                              ui,
224                              format_fib_urpf_list, ui);
225         }
226     }
227
228     return (NULL);
229 }
230
231 /*?
232  * The '<em>sh fib uRPF [index] </em>' command displays the uRPF lists
233  *
234  * @cliexpar
235  * @cliexstart{show fib uRPF}
236  * FIB uRPF Entries:
237  *  0@uPRF-list:0 len:0 itfs:[]
238  *  1@uPRF-list:1 len:2 itfs:[1, 2, ]
239  *  2@uPRF-list:2 len:1 itfs:[3, ]
240  *  3@uPRF-list:3 len:1 itfs:[9, ]
241  * @cliexend
242 ?*/
243 VLIB_CLI_COMMAND (show_fib_urpf_list, static) = {
244   .path = "show fib uRPF",
245   .function = show_fib_urpf_list_command,
246   .short_help = "show fib uRPF",
247 };