Line data Source code
1 : /*
2 : * Copyright (c) 2017 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 : * bier_imposition : The BIER imposition object
17 : *
18 : * A BIER imposition object is present in the IP mcast output list
19 : * and represents the imposition of a BIER bitmask. After BIER header
20 : * imposition the packet is forward within the appropriate/specified
21 : * BIER table
22 : */
23 :
24 : #include <vnet/bier/bier_imp.h>
25 : #include <vnet/bier/bier_table.h>
26 : #include <vnet/bier/bier_hdr_inlines.h>
27 : #include <vnet/fib/fib_node.h>
28 : #include <vnet/mpls/mpls_types.h>
29 :
30 : /**
31 : * The memory pool of all imp objects
32 : */
33 : bier_imp_t *bier_imp_pool;
34 :
35 : /**
36 : * When constructing the BIER imp ID from an index and BSL, shift
37 : * the BSL this far
38 : */
39 : #define BIER_IMP_ID_HLEN_SHIFT 24
40 :
41 : static void
42 85 : bier_imp_lock_i (bier_imp_t *bi)
43 : {
44 85 : bi->bi_locks++;
45 85 : }
46 :
47 : void
48 78 : bier_imp_lock (index_t bii)
49 : {
50 78 : bier_imp_lock_i(bier_imp_get(bii));
51 78 : }
52 :
53 : static index_t
54 349 : bier_imp_get_index(bier_imp_t *bi)
55 : {
56 349 : return (bi - bier_imp_pool);
57 : }
58 :
59 : index_t
60 7 : bier_imp_add_or_lock (const bier_table_id_t *bti,
61 : bier_bp_t sender,
62 : const bier_bit_string_t *bs)
63 : {
64 7 : bier_imp_t *bi = NULL;
65 : fib_protocol_t fproto;
66 : index_t btii;
67 :
68 7 : pool_get_aligned(bier_imp_pool, bi, CLIB_CACHE_LINE_BYTES);
69 :
70 7 : bi->bi_tbl = *bti;
71 7 : btii = bier_table_lock(bti);
72 :
73 : /*
74 : * init the BIER header we will paint on in the data plane
75 : */
76 7 : bier_hdr_init(&bi->bi_hdr,
77 : BIER_HDR_VERSION_1,
78 : BIER_HDR_PROTO_INVALID, // filled in later
79 7 : bti->bti_hdr_len,
80 : 0, // entropy
81 : sender);
82 7 : bier_hdr_hton(&bi->bi_hdr);
83 7 : clib_memcpy_fast(&bi->bi_bits, bs->bbs_buckets, bs->bbs_len);
84 :
85 7 : bier_imp_lock_i(bi);
86 :
87 : /*
88 : * get and stack on the forwarding info from the table
89 : */
90 21 : FOR_EACH_FIB_IP_PROTOCOL(fproto)
91 : {
92 : /*
93 : * initialise to invalid first, lest we pick up garbage
94 : * from the pool alloc
95 : */
96 14 : dpo_id_t dpo = DPO_INVALID;
97 14 : bi->bi_dpo[fproto] = dpo;
98 :
99 14 : bier_table_contribute_forwarding(btii, &dpo);
100 14 : dpo_stack(DPO_BIER_IMP, fib_proto_to_dpo(fproto),
101 14 : &bi->bi_dpo[fproto],
102 : &dpo);
103 14 : dpo_reset(&dpo);
104 : }
105 :
106 7 : return (bier_imp_get_index(bi));
107 : }
108 :
109 : void
110 85 : bier_imp_unlock (index_t bii)
111 : {
112 : fib_protocol_t fproto;
113 : bier_imp_t *bi;
114 :
115 85 : if (INDEX_INVALID == bii)
116 : {
117 0 : return;
118 : }
119 :
120 85 : bi = bier_imp_get(bii);
121 :
122 85 : bi->bi_locks--;
123 :
124 85 : if (0 == bi->bi_locks)
125 : {
126 7 : bier_table_unlock(&bi->bi_tbl);
127 :
128 21 : FOR_EACH_FIB_IP_PROTOCOL(fproto)
129 : {
130 14 : dpo_reset(&bi->bi_dpo[fproto]);
131 : }
132 7 : pool_put(bier_imp_pool, bi);
133 : }
134 : }
135 :
136 : u8*
137 342 : format_bier_imp (u8* s, va_list *args)
138 : {
139 342 : index_t bii = va_arg (*args, index_t);
140 342 : u32 indent = va_arg(*args, u32);
141 342 : bier_show_flags_t flags = va_arg(*args, bier_show_flags_t);
142 : bier_imp_t *bi;
143 :
144 342 : bi = bier_imp_get(bii);
145 :
146 342 : s = format(s, "bier-imp:[%d]: tbl:[%U] hdr:[%U]",
147 : bier_imp_get_index(bi),
148 : format_bier_table_id, &bi->bi_tbl,
149 : format_bier_hdr, &bi->bi_hdr);
150 :
151 342 : if (BIER_SHOW_DETAIL & flags)
152 : {
153 : bier_bit_string_t bbs;
154 : bier_hdr_t copy;
155 :
156 171 : copy = bi->bi_hdr;
157 171 : bier_hdr_ntoh(©);
158 171 : bier_bit_string_init(&bbs,
159 171 : bier_hdr_get_len_id(©),
160 171 : bi->bi_bits);
161 :
162 171 : s = format(s, "\n%U%U",
163 : format_white_space, indent,
164 : format_bier_bit_string, &bbs);
165 171 : s = format(s, "\n%U%U",
166 : format_white_space, indent,
167 : format_dpo_id, &bi->bi_dpo, indent+2);
168 : }
169 :
170 342 : return (s);
171 : }
172 :
173 : void
174 28 : bier_imp_contribute_forwarding (index_t bii,
175 : dpo_proto_t proto,
176 : dpo_id_t *dpo)
177 : {
178 28 : dpo_set(dpo, DPO_BIER_IMP, proto, bii);
179 28 : }
180 :
181 : const static char* const bier_imp_ip4_nodes[] =
182 : {
183 : "bier-imp-ip4",
184 : NULL,
185 : };
186 : const static char* const bier_imp_ip6_nodes[] =
187 : {
188 : "bier-imp-ip6",
189 : NULL,
190 : };
191 :
192 : const static char* const * const bier_imp_nodes[DPO_PROTO_NUM] =
193 : {
194 : [DPO_PROTO_IP4] = bier_imp_ip4_nodes,
195 : [DPO_PROTO_IP6] = bier_imp_ip6_nodes,
196 : };
197 :
198 : static void
199 72 : bier_imp_dpo_lock (dpo_id_t *dpo)
200 : {
201 72 : bier_imp_lock(dpo->dpoi_index);
202 72 : }
203 :
204 : static void
205 72 : bier_imp_dpo_unlock (dpo_id_t *dpo)
206 : {
207 72 : bier_imp_unlock(dpo->dpoi_index);
208 72 : }
209 :
210 : static void
211 0 : bier_imp_dpo_mem_show (void)
212 : {
213 0 : fib_show_memory_usage("BIER imposition",
214 0 : pool_elts(bier_imp_pool),
215 0 : pool_len(bier_imp_pool),
216 : sizeof(bier_imp_t));
217 0 : }
218 :
219 : static u8*
220 171 : format_bier_imp_dpo (u8* s, va_list *ap)
221 : {
222 171 : index_t index = va_arg(*ap, index_t);
223 171 : u32 indent = va_arg(*ap, u32);
224 :
225 171 : s = format(s, "%U", format_bier_imp, index, indent, BIER_SHOW_DETAIL);
226 :
227 171 : return (s);
228 : }
229 :
230 : const static dpo_vft_t bier_imp_vft = {
231 : .dv_lock = bier_imp_dpo_lock,
232 : .dv_unlock = bier_imp_dpo_unlock,
233 : .dv_format = format_bier_imp_dpo,
234 : .dv_mem_show = bier_imp_dpo_mem_show,
235 : };
236 :
237 : clib_error_t *
238 559 : bier_imp_db_module_init (vlib_main_t *vm)
239 : {
240 559 : dpo_register(DPO_BIER_IMP, &bier_imp_vft, bier_imp_nodes);
241 :
242 559 : return (NULL);
243 : }
244 :
245 90719 : VLIB_INIT_FUNCTION (bier_imp_db_module_init);
246 :
247 : static clib_error_t *
248 0 : show_bier_imp (vlib_main_t * vm,
249 : unformat_input_t * input,
250 : vlib_cli_command_t * cmd)
251 : {
252 : bier_imp_t *bi;
253 : index_t bii;
254 :
255 0 : bii = INDEX_INVALID;
256 :
257 0 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
258 0 : if (unformat (input, "%d", &bii))
259 : ;
260 : else
261 : {
262 0 : break;
263 : }
264 : }
265 :
266 0 : if (INDEX_INVALID == bii)
267 : {
268 0 : pool_foreach (bi, bier_imp_pool)
269 : {
270 0 : vlib_cli_output(vm, "%U", format_bier_imp,
271 : bier_imp_get_index(bi),
272 : 1,
273 : BIER_SHOW_BRIEF);
274 : }
275 : }
276 : else
277 : {
278 0 : if (pool_is_free_index(bier_imp_pool, bii))
279 : {
280 0 : vlib_cli_output(vm, "No such BIER imposition: %d", bii);
281 : }
282 : else
283 : {
284 0 : vlib_cli_output(vm, "%U", format_bier_imp, bii, 1,
285 : BIER_SHOW_DETAIL);
286 : }
287 : }
288 0 : return (NULL);
289 : }
290 :
291 272887 : VLIB_CLI_COMMAND (show_bier_imp_node, static) = {
292 : .path = "show bier imp",
293 : .short_help = "show bier imp [index]",
294 : .function = show_bier_imp,
295 : };
|