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/bier/bier_bift_table.h>
17 : #include <vnet/dpo/drop_dpo.h>
18 : #include <vnet/udp/udp_local.h>
19 :
20 : typedef enum {
21 : #define bier_error(n,s) BIER_INPUT_ERROR_##n,
22 : #include <vnet/bier/bier_input_error.def>
23 : #undef bier_error
24 : BIER_INPUT_N_ERROR,
25 : } bier_input_error_t;
26 :
27 : static char * bier_error_strings[] = {
28 : #define bier_error(n,s) s,
29 : #include <vnet/bier/bier_input_error.def>
30 : #undef bier_error
31 : };
32 :
33 : /**
34 : * Global BIFT table
35 : */
36 : bier_bfit_table_t *bier_bift_table;
37 :
38 : /**
39 : * Forward declare the node
40 : */
41 : vlib_node_registration_t bier_bift_input_node;
42 :
43 : void
44 1 : bier_bift_table_entry_add (bier_bift_id_t id,
45 : const dpo_id_t *dpo)
46 : {
47 1 : if (NULL == bier_bift_table)
48 : {
49 : u32 ii;
50 :
51 : /*
52 : * allocate the table and
53 : * set each of the entries therein to a BIER drop
54 : */
55 1 : bier_bift_table = clib_mem_alloc_aligned(sizeof(*bier_bift_table),
56 : CLIB_CACHE_LINE_BYTES);
57 1 : clib_memset(bier_bift_table, 0, sizeof(*bier_bift_table));
58 :
59 1048580 : for (ii = 0; ii < BIER_BIFT_N_ENTRIES; ii++)
60 : {
61 1048580 : dpo_stack_from_node(bier_bift_input_node.index,
62 1048580 : &bier_bift_table->bblt_dpos[ii],
63 : drop_dpo_get(DPO_PROTO_BIER));
64 : }
65 :
66 : /*
67 : * register to handle packets that arrive on the assigned
68 : * UDP port
69 : */
70 1 : udp_register_dst_port(vlib_get_main(),
71 : UDP_DST_PORT_BIER,
72 : bier_bift_input_node.index,
73 : 0);
74 1 : udp_register_dst_port(vlib_get_main(),
75 : UDP_DST_PORT_BIER,
76 : bier_bift_input_node.index,
77 : 1);
78 : }
79 :
80 1 : dpo_stack_from_node(bier_bift_input_node.index,
81 1 : &bier_bift_table->bblt_dpos[id],
82 : dpo);
83 :
84 1 : bier_bift_table->bblt_n_entries++;
85 1 : }
86 :
87 : void
88 1 : bier_bift_table_entry_remove (bier_bift_id_t id)
89 : {
90 1 : ASSERT(NULL != bier_bift_table);
91 :
92 1 : dpo_reset(&bier_bift_table->bblt_dpos[id]);
93 :
94 1 : bier_bift_table->bblt_n_entries--;
95 :
96 1 : if (0 == bier_bift_table->bblt_n_entries)
97 : {
98 1 : udp_unregister_dst_port(vlib_get_main(),
99 : UDP_DST_PORT_BIER,
100 : 0);
101 1 : udp_unregister_dst_port(vlib_get_main(),
102 : UDP_DST_PORT_BIER,
103 : 1);
104 :
105 1 : clib_mem_free(bier_bift_table);
106 1 : bier_bift_table = NULL;
107 : }
108 1 : }
109 :
110 : /**
111 : * @brief Packet trace record for BIER input
112 : */
113 : typedef struct bier_bift_input_trace_t_
114 : {
115 : u32 bift_id;
116 : } bier_bift_input_trace_t;
117 :
118 : static uword
119 1 : bier_bift_input (vlib_main_t * vm,
120 : vlib_node_runtime_t * node,
121 : vlib_frame_t * from_frame)
122 : {
123 : u32 n_left_from, next_index, * from, * to_next;
124 :
125 1 : from = vlib_frame_vector_args (from_frame);
126 1 : n_left_from = from_frame->n_vectors;
127 1 : next_index = node->cached_next_index;
128 :
129 2 : while (n_left_from > 0)
130 : {
131 : u32 n_left_to_next;
132 :
133 1 : vlib_get_next_frame (vm, node, next_index,
134 : to_next, n_left_to_next);
135 :
136 2 : while (n_left_from > 0 && n_left_to_next > 0)
137 : {
138 : bier_bift_id_t *biftp0, bift0;
139 : const dpo_id_t *dpo0;
140 : vlib_buffer_t * b0;
141 : u32 bi0, next0;
142 :
143 1 : bi0 = from[0];
144 1 : to_next[0] = bi0;
145 1 : from += 1;
146 1 : to_next += 1;
147 1 : n_left_from -= 1;
148 1 : n_left_to_next -= 1;
149 :
150 1 : b0 = vlib_get_buffer (vm, bi0);
151 1 : biftp0 = vlib_buffer_get_current (b0);
152 1 : vlib_buffer_advance(b0, sizeof(bift0));
153 1 : bift0 = clib_net_to_host_u32(*biftp0);
154 :
155 : /*
156 : * Do the lookup based on the first 20 bits, i.e. the
157 : * encoding of the set, sub-domain and BSL
158 : */
159 1 : dpo0 = bier_bift_dp_lookup(bift0);
160 :
161 : /*
162 : * save the TTL for later during egress
163 : */
164 1 : vnet_buffer(b0)->mpls.ttl = vnet_mpls_uc_get_ttl(bift0);
165 :
166 1 : next0 = dpo0->dpoi_next_node;
167 1 : vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
168 :
169 1 : if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
170 : {
171 : bier_bift_input_trace_t *tr;
172 :
173 1 : tr = vlib_add_trace(vm, node, b0, sizeof (*tr));
174 1 : tr->bift_id = bift0;
175 : }
176 :
177 1 : vlib_validate_buffer_enqueue_x1(vm, node, next_index,
178 : to_next, n_left_to_next,
179 : bi0, next0);
180 : }
181 :
182 1 : vlib_put_next_frame(vm, node, next_index, n_left_to_next);
183 : }
184 :
185 1 : vlib_node_increment_counter(vm, bier_bift_input_node.index,
186 : BIER_INPUT_ERROR_PKTS_VALID,
187 1 : from_frame->n_vectors);
188 1 : return (from_frame->n_vectors);
189 : }
190 :
191 : static u8 *
192 2 : format_bier_bift_input_trace (u8 * s, va_list * args)
193 : {
194 2 : CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
195 2 : CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
196 2 : bier_bift_input_trace_t * t = va_arg (*args, bier_bift_input_trace_t *);
197 :
198 2 : s = format (s, "BIFT-ID:[%U]", format_bier_bift_id,
199 : vnet_mpls_uc_get_label(t->bift_id));
200 2 : return s;
201 : }
202 :
203 178120 : VLIB_REGISTER_NODE (bier_bift_input_node) = {
204 : .function = bier_bift_input,
205 : .name = "bier-bift-input",
206 : /* Takes a vector of packets. */
207 : .vector_size = sizeof (u32),
208 : .n_errors = BIER_INPUT_N_ERROR,
209 : .error_strings = bier_error_strings,
210 : .n_next_nodes = 0,
211 : .format_trace = format_bier_bift_input_trace,
212 : };
213 :
214 : clib_error_t *
215 0 : show_bier_bift_cmd (vlib_main_t * vm,
216 : unformat_input_t * input,
217 : vlib_cli_command_t * cmd)
218 : {
219 0 : clib_error_t * error = NULL;
220 : u32 hdr_len, set, sub_domain;
221 :
222 0 : set = hdr_len = sub_domain = ~0;
223 :
224 0 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
225 0 : if (unformat (input, "sd %d", &sub_domain)) {
226 : ;
227 0 : } else if (unformat (input, "set %d", &set)) {
228 : ;
229 0 : } else if (unformat (input, "bsl %d", &hdr_len)) {
230 : ;
231 : }
232 : else
233 : {
234 0 : error = unformat_parse_error (input);
235 0 : goto done;
236 : }
237 : }
238 :
239 0 : if (NULL == bier_bift_table)
240 : {
241 0 : vlib_cli_output(vm, "no BIFT entries");
242 0 : goto done;
243 : }
244 :
245 0 : if (~0 == set)
246 : {
247 : u32 ii;
248 :
249 0 : for (ii = 0; ii < BIER_BIFT_N_ENTRIES; ii++)
250 : {
251 0 : if (!dpo_is_drop(&bier_bift_table->bblt_dpos[ii]))
252 : {
253 : bier_hdr_len_id_t bsl;
254 :
255 0 : bier_bift_id_decode(ii, &set, &sub_domain, &bsl);
256 :
257 0 : vlib_cli_output(vm, "set: %d, sub-domain:%d, BSL:%U",
258 : set, sub_domain,
259 : format_bier_hdr_len_id, bsl);
260 0 : vlib_cli_output(vm, " %U",
261 : format_dpo_id,
262 0 : &bier_bift_table->bblt_dpos[ii], 0);
263 : }
264 : }
265 : }
266 : else
267 : {
268 : bier_bift_id_t id;
269 :
270 0 : id = bier_bift_id_encode(set, sub_domain,
271 0 : bier_hdr_bit_len_to_id(hdr_len));
272 :
273 0 : if (!dpo_is_drop(&bier_bift_table->bblt_dpos[id]))
274 : {
275 0 : vlib_cli_output(vm, "set: %d, sub-domain:%d, BSL:%U",
276 : set, sub_domain,
277 : format_bier_hdr_len_id, hdr_len);
278 0 : vlib_cli_output(vm, " %U",
279 : format_dpo_id,
280 0 : &bier_bift_table->bblt_dpos[id], 0);
281 : }
282 : }
283 0 : done:
284 0 : return (error);
285 : }
286 :
287 272887 : VLIB_CLI_COMMAND (show_bier_bift_command, static) = {
288 : .path = "show bier bift",
289 : .short_help = "show bier bift [set <value>] [sd <value>] [bsl <value>]",
290 : .function = show_bier_bift_cmd,
291 : };
|