BIER: fix support for longer bit-string lengths
[vpp.git] / src / vnet / bier / bier_types.h
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 #ifndef __BIER_TYPES_H__
17 #define __BIER_TYPES_H__
18
19 #include <vlib/vlib.h>
20 #include <vnet/dpo/dpo.h>
21
22 /**
23  * @brief Flags to control show output
24  */
25 typedef enum bier_show_flags_t_ {
26     BIER_SHOW_BRIEF,
27     BIER_SHOW_DETAIL = (1 << 0),
28 } bier_show_flags_t;
29
30 /**
31  * Types of BIER tables
32  */
33 typedef enum bier_table_type_t_ {
34     /**
35      * BIER over MPLS with SPF
36      */
37     BIER_TABLE_MPLS_SPF,
38
39     /**
40      * BIER over MPLS for TE
41      */
42     BIER_TABLE_MPLS_TE,
43 } __attribute__((packed)) bier_table_type_t;
44
45 #define BIER_TABLE_TYPES {              \
46     [BIER_TABLE_MPLS_SPF] = "mpls-spf", \
47     [BIER_TABLE_MPLS_TE]  = "mpls-te",  \
48 }
49
50 /**
51  * bier_hdr_len_id_t enumerator
52  **/
53 typedef enum bier_hdr_len_id_t_ {
54     BIER_HDR_LEN_64 = 0,
55     BIER_HDR_LEN_128,
56     BIER_HDR_LEN_256,
57     BIER_HDR_LEN_512,
58     BIER_HDR_LEN_1024,
59     /**
60      * Bit-string lengths greater than 1024 are not supported due to the
61      * limited about pf space available in a vlib_buffer_t to prepend a
62      * BIER header at imposition.
63      */
64     BIER_HDR_LEN_2048,
65     BIER_HDR_LEN_4096,
66     BIER_HDR_LEN_INVALID,
67 } __attribute__((packed)) bier_hdr_len_id_t;
68
69 #define BIER_HDR_LEN_IDS {             \
70     [BIER_HDR_LEN_INVALID] = "invalid",\
71     [BIER_HDR_LEN_64]      = "64",     \
72     [BIER_HDR_LEN_128]     = "128",    \
73     [BIER_HDR_LEN_256]     = "256",    \
74     [BIER_HDR_LEN_512]     = "512",    \
75     [BIER_HDR_LEN_1024]    = "1024",   \
76     [BIER_HDR_LEN_2048]    = "2048",   \
77     [BIER_HDR_LEN_4096]    = "4096",   \
78 }
79
80 #define FOR_EACH_BIER_HDR_LEN(_len)    \
81     for (_item = BIER_HDR_LEN_64;      \
82          _item <= BIER_HDR_LEN_4096;   \
83          _item++)
84
85 /**
86  * Format the header length field
87  */
88 extern u8 *format_bier_hdr_len_id(u8 *s, va_list *ap);
89
90 /*
91  * convert from prefix len to hdr ID
92  */
93 static inline bier_hdr_len_id_t
94 bier_prefix_len_to_hdr_id (u16 prfx_len) {
95
96     switch (prfx_len) {
97     case 7:
98         return (BIER_HDR_LEN_64);
99     case 8:
100         return (BIER_HDR_LEN_128);
101     case 9:
102         return (BIER_HDR_LEN_256);
103     case 10:
104         return (BIER_HDR_LEN_512);
105     case 11:
106         return (BIER_HDR_LEN_1024);
107     case 12:
108         return (BIER_HDR_LEN_2048);
109     case 13:
110         return (BIER_HDR_LEN_4096);
111     default:
112         break;
113     }
114
115     return (BIER_HDR_LEN_INVALID);
116 }
117
118 static inline bier_hdr_len_id_t
119 bier_hdr_byte_len_to_id (u32 bytes)
120 {
121     switch (bytes) {
122     case 8:
123         return (BIER_HDR_LEN_64);
124     case 16:
125         return (BIER_HDR_LEN_128);
126     case 32:
127         return (BIER_HDR_LEN_256);
128     case 64:
129         return (BIER_HDR_LEN_512);
130     case 128:
131         return (BIER_HDR_LEN_1024);
132     case 256:
133         return (BIER_HDR_LEN_2048);
134     case 512:
135         return (BIER_HDR_LEN_4096);
136     }
137
138     return (BIER_HDR_LEN_INVALID);
139 }
140
141 static inline bier_hdr_len_id_t
142 bier_hdr_bit_len_to_id (u32 bytes)
143 {
144     switch (bytes) {
145     case 64:
146         return (BIER_HDR_LEN_64);
147     case 128:
148         return (BIER_HDR_LEN_128);
149     case 256:
150         return (BIER_HDR_LEN_256);
151     case 512:
152         return (BIER_HDR_LEN_512);
153     case 1024:
154         return (BIER_HDR_LEN_1024);
155     case 2048:
156         return (BIER_HDR_LEN_2048);
157     case 4096:
158         return (BIER_HDR_LEN_4096);
159     }
160
161     return (BIER_HDR_LEN_INVALID);
162 }
163
164 /**
165  * bier_hdr_len_num_buckets_t enumerator
166  **/
167 typedef enum bier_hdr_len_num_buckets_t_ {
168     BIER_HDR_BUCKETS_64 = 8,
169     BIER_HDR_BUCKETS_128 = 16,
170     BIER_HDR_BUCKETS_256 = 32,
171     BIER_HDR_BUCKETS_512 = 64,
172     BIER_HDR_BUCKETS_1024 = 128,
173     BIER_HDR_BUCKETS_2048 = 256,
174     BIER_HDR_BUCKETS_4096 = 512,
175 } bier_hdr_len_num_buckets_t;
176
177 /**
178  * BIER header protocol payload types
179  **/
180 typedef enum bier_hdr_proto_id_t_ {
181     BIER_HDR_PROTO_INVALID = 0,
182     BIER_HDR_PROTO_MPLS_DOWN_STREAM,
183     BIER_HDR_PROTO_MPLS_UP_STREAM,
184     BIER_HDR_PROTO_ETHERNET,
185     BIER_HDR_PROTO_IPV4,
186     BIER_HDR_PROTO_IPV6,
187     BIER_HDR_PROTO_VXLAN,
188     BIER_HDR_PROTO_CTRL,
189     BIER_HDR_PROTO_OAM,
190 } __attribute__((packed)) bier_hdr_proto_id_t;
191
192 #define BIER_HDR_N_PROTO (BIER_HDR_PROTO_OAM + 1)
193
194 #define BIER_HDR_PROTO_ID_NAMES {                               \
195     [BIER_HDR_PROTO_INVALID] = "invalid",                       \
196     [BIER_HDR_PROTO_MPLS_DOWN_STREAM] = "mpls-down-stream",     \
197     [BIER_HDR_PROTO_MPLS_UP_STREAM] = "mpls-up-stream",         \
198     [BIER_HDR_PROTO_ETHERNET] = "ethernet",                     \
199     [BIER_HDR_PROTO_IPV4] = "ipv4",                             \
200     [BIER_HDR_PROTO_IPV6] = "ipv6",                             \
201     [BIER_HDR_PROTO_VXLAN] = "vxlan",                           \
202     [BIER_HDR_PROTO_CTRL] = "control-plane",                    \
203     [BIER_HDR_PROTO_OAM] = "oam",                               \
204 }
205
206 #define FOR_EACH_BIER_HDR_PROTO(_proto)                 \
207     for (_proto = BIER_HDR_PROTO_MPLS_DOWN_STREAM;      \
208          _proto <= BIER_HDR_PROTO_OAM;                  \
209          _proto++)
210
211 /**
212  * Format the header length field
213  */
214 extern u8 *format_bier_hdr_proto(u8 *s, va_list *ap);
215
216 /**
217  * Convert from BIER next-hop proto to DPO proto
218  */
219 extern dpo_proto_t bier_hdr_proto_to_dpo(bier_hdr_proto_id_t bproto);
220
221 /**
222  * BIER header versions
223  **/
224 typedef enum bier_hdr_version_t_ {
225     BIER_HDR_VERSION_1 = 0,
226 } __attribute__((packed)) bier_hdr_version_t;
227
228 /**
229  * bier_hdr_code_t enumerator
230  **/
231 typedef enum bier_hdr_code_t_ {
232     BIER_HDR_CODE_OAM_IPV4 = 0,
233     BIER_HDR_CODE_OAM_IPV6 = 1,
234     BIER_HDR_CODE_CTRL_IPV4 = 2,
235     BIER_HDR_CODE_CTRL_IPV6 = 3,
236 } __attribute__((packed)) bier_hdr_code_t;
237
238 /**
239  * bier_hdr_oam_sub_code_t enumerator
240  */
241 typedef enum bier_hdr_oam_sub_code_t_ {
242     BIER_HDR_SUB_CODE_OAM_PING_REQ = 0,
243     BIER_HDR_SUB_CODE_OAM_PING_RESP = 1,
244 } __attribute__((packed)) bier_hdr_oam_sub_code_t;
245
246 /**
247  * bier_hdr_ctrl_sub_code_t enumerator
248  */
249 typedef enum bier_hdr_ctrl_sub_code_t_ {
250     BIER_HDR_SUB_CODE_CTRL_MEMBER_REQ = 0,
251     BIER_HDR_SUB_CODE_CTRL_ATTACHED_NET = 1,
252 } __attribute__((packed)) bier_hdr_ctrl_sub_code_t;
253
254 /**
255  * A bucket is a byte. The byte string is thus always in network byte order.
256  */
257 typedef u8 bier_bit_mask_bucket_t;
258
259 /**
260  * 256 bits = 32 bytes
261  */
262 #define BIER_BIT_MASK_NUM_BUCKETS 32
263 #define BIER_BIT_MASK_MAX_BUCKET (BIER_BIT_MASK_NUM_BUCKETS - 1)
264
265 /**
266  * number of bits in a bucket
267  */
268 #define BIER_BIT_MASK_BITS_PER_BUCKET 8
269
270 /**
271  * Supported bit-posiotn range
272  */
273 #define BIER_BIT_MASK_MIN_POS (1)
274
275 /**
276  * A Variable length BitString
277  */
278 typedef struct bier_bit_string_t_ {
279     /**
280      * The length of the string in BYTES
281      */
282     u16 bbs_len;
283
284     /**
285      * The buckets in the string
286      */
287     bier_bit_mask_bucket_t *bbs_buckets;
288 } bier_bit_string_t;
289
290 /**
291  * A bit positon
292  *  as assigned to egress PEs
293  */
294 typedef u32 bier_bp_t;
295
296 #define BIER_BP_TO_INDEX(bp) (bp - 1)
297
298 /**
299  * The maximum BP that can be assigned
300  */
301 #define BIER_BP_MAX 0x10000
302
303 /**
304  * An identifier of the sender of BIER packets
305  * this is the source of the 'tree' - the BFIR
306  */
307 typedef u16 bier_hdr_src_id_t;
308
309 /**
310  * An entropy value in a BIER header
311  */
312 typedef u32 bier_hdr_entropy_t;
313
314 #define BIER_BP_INVALID 0
315
316 /**
317  * A BIER header of variable length
318  * The encoding follows:
319  *   https://tools.ietf.org/html/draft-ietf-bier-mpls-encapsulation-10
320  */
321 typedef struct bier_hdr_t_ {
322     /**
323      * The first nibble is always set to 0101
324      * to ensure that when carried over MPLS, the BIER packet
325      * is not mistaken for IPv[46]:
326      *   type: bier_hdr_version_t
327      *
328      * The second nibble is the version - this is 0:
329      *   type: bier_hdr_version_t
330      *
331      * The third nibble is header length ID
332      *   type: bier_hdr_len_id_t
333      *
334      * The next 20 bits are entropy
335      * An entropy value, calculated by the head end, used
336      * at the head and mid-points for load-balance hash
337      *   type: bier_hdr_entropy_t
338      */
339     u32 bh_first_word;
340
341     /**
342      * The second word comprises:
343      *  2 bits of OAM for passive perf measurement
344      *  2 reserved bits;
345      *  6 bits of DSCP
346      *  6 bits for the next-proto field of type;
347      *     bier_hdr_proto_id_t
348      */
349     u16 bh_oam_dscp_proto;
350
351     /**
352      * The BFR-ID of the sender
353      */
354     u16 bh_bfr_id;
355
356     /**
357      * The variable length bit-string
358      */
359     bier_bit_mask_bucket_t bh_bit_string[0];
360 } bier_hdr_t;
361
362 /**
363  * Format a BIER header
364  */
365 extern u8 *format_bier_hdr(u8 *s, va_list *ap);
366
367 /**
368  * The BIER Set ID assigned to a BIER table
369  */
370 typedef u32 bier_table_set_id_t;
371
372 #define BIER_TABLE_SET_INVALID_ID 0xffffffff
373
374 /**
375  * The BIER Sub-domain ID assigned to a BIER table
376  */
377 typedef u32 bier_table_sub_domain_id_t;
378
379 #define BIER_TABLE_SUB_DOMAIN_INVALID_ID 0xffffffff
380
381 /**
382  * An ID or instance number of a BIER sub-table
383  */
384 typedef u32 bier_table_ecmp_id_t;
385
386 /**
387  * Definition of the ID of the BIER main table
388  */
389 #define BIER_ECMP_TABLE_ID_MAIN 0xFFFF
390
391 /**
392  * The ID of a table
393  */
394 typedef struct bier_table_id_t_ {
395     /**
396      * The SET-ID
397      *  The control plane divdies the bit-position space
398      * into sets in the case the max bit-position is greater
399      * than the table's bit-string size
400      */
401     bier_table_set_id_t bti_set;
402
403     /**
404      * The Sub-Domain-ID
405      * The control plane has the configuration option to specify multiple
406      * domains or topologies.
407      */
408     bier_table_sub_domain_id_t bti_sub_domain;
409
410     /**
411      * The SUB/ECMP-ID
412      * Constructed by FIB to achieve ECMP between BFR-NBRs
413      */
414     bier_table_ecmp_id_t bti_ecmp;
415
416     /**
417      * The size of the bit string processed by this table.
418      */
419     bier_hdr_len_id_t bti_hdr_len;
420
421    /**
422      * The type of the table; SPF or TE, MPLS or IPv6
423      */
424     bier_table_type_t bti_type;
425 } bier_table_id_t;
426
427 /**
428  * Format a BIER table ID
429  */
430 extern u8 *format_bier_table_id(u8 *s, va_list *ap);
431
432 /**
433  * Compare to BIER table IDs for equality
434  */
435 extern int bier_table_id_cmp(const bier_table_id_t *btid1,
436                              const bier_table_id_t *btid2);
437
438 /**
439  * Conversion functions for the enumerated bit-string length
440  * values, to bit and bytes
441  */
442 extern u32 bier_hdr_len_id_to_num_buckets(bier_hdr_len_id_t id);
443 extern u32 bier_hdr_len_id_to_num_bytes(bier_hdr_len_id_t id);
444 extern u32 bier_hdr_len_id_to_max_bucket(bier_hdr_len_id_t id);
445 extern u32 bier_hdr_len_id_to_num_bits(bier_hdr_len_id_t id);
446 extern u32 bier_hdr_len_id_to_max_bit(bier_hdr_len_id_t id);
447 extern u32 bier_hdr_len_id_to_prefix_len(bier_hdr_len_id_t id);
448
449 #define BIER_OK 0
450 #define BIER_ERR_NO_TABLE 1
451 #define BIER_ERR_DUPLICATE_TABLE 2
452 #define BIER_ERR_PANIC 3
453 typedef int bier_rc;
454
455 /**
456  * The BIER universal 'label'
457  */
458 typedef u32 bier_bift_id_t;
459
460 /**
461  * An invalid value for the BIFT ID
462  * all ones implies a BSL that's invalid.
463  */
464 #define BIER_BIFT_ID_INVALID (~0)
465
466 extern u16 bier_bfit_id_get_sub_domain(bier_bift_id_t bift_id);
467 extern u16 bier_bfit_id_get_set(bier_bift_id_t bift_id);
468 extern bier_hdr_proto_id_t bier_bift_id_get_bit_string_length(bier_bift_id_t bift_id);
469
470 /**
471  * Encode a BIFT-ID as per draft-wijnandsxu-bier-non-mpls-bift-encoding-00.txt
472  */
473 extern bier_bift_id_t bier_bift_id_encode(bier_table_set_id_t set,
474                                           bier_table_sub_domain_id_t sd,
475                                           bier_hdr_len_id_t bsl);
476 extern void bier_bift_id_decode(bier_bift_id_t id,
477                                 bier_table_set_id_t *set,
478                                 bier_table_sub_domain_id_t *sd,
479                                 bier_hdr_len_id_t *bsl);
480
481 extern u8* format_bier_bift_id(u8 *s, va_list *ap);
482
483 #endif /* __BIER_TYPES_H__ */