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 <vppinfra/types.h>
17#include <vnet/bier/bier_types.h>
18#include <vnet/bier/bier_hdr_inlines.h>
19
20/*
21 * enum to string conversions
22 */
23const static char* const bier_hdr_len_id_names[] = BIER_HDR_LEN_IDS;
24const static char* const bier_hdr_proto_names[] = BIER_HDR_PROTO_ID_NAMES;
25
26const static u16 bier_hdr_len_num_buckets[] = {
27    [BIER_HDR_LEN_INVALID] = 0,
28    [BIER_HDR_LEN_64] = 8,
29    [BIER_HDR_LEN_128] = 16,
30    [BIER_HDR_LEN_256] = 32,
31    [BIER_HDR_LEN_512] = 64,
32    [BIER_HDR_LEN_1024] = 128,
33    [BIER_HDR_LEN_2048] = 256,
34    [BIER_HDR_LEN_4096] = 512,
35};
36
37const static u16 bier_hdr_len_num_bits[] = {
38    [BIER_HDR_LEN_INVALID] = 0,
39    [BIER_HDR_LEN_64] = 64,
40    [BIER_HDR_LEN_128] = 128,
41    [BIER_HDR_LEN_256] = 256,
42    [BIER_HDR_LEN_512] = 512,
43    [BIER_HDR_LEN_1024] = 1024,
44    [BIER_HDR_LEN_2048] = 2048,
45    [BIER_HDR_LEN_4096] = 4096,
46};
47
48const static u16 bier_hdr_len_prefix_len[] = {
49    [BIER_HDR_LEN_INVALID] = 0,
50    [BIER_HDR_LEN_64] = 7,
51    [BIER_HDR_LEN_128] = 8,
52    [BIER_HDR_LEN_256] = 9,
53    [BIER_HDR_LEN_512] = 10,
54    [BIER_HDR_LEN_1024] = 11,
55    [BIER_HDR_LEN_2048] = 12,
56    [BIER_HDR_LEN_4096] = 13,
57};
58
59u32
60bier_hdr_len_id_to_num_buckets (bier_hdr_len_id_t id)
61{
62    return (bier_hdr_len_num_buckets[id]);
63}
64
65u32
66bier_hdr_len_id_to_num_bytes (bier_hdr_len_id_t id)
67{
68    return (bier_hdr_len_id_to_num_buckets(id));
69}
70
71u32
72bier_hdr_len_id_to_max_bucket (bier_hdr_len_id_t id)
73{
74    return (bier_hdr_len_id_to_num_buckets(id) - 1);
75}
76
77u32
78bier_hdr_len_id_to_num_bits (bier_hdr_len_id_t id)
79{
80    return (bier_hdr_len_num_bits[id]);
81}
82
83u32
84bier_hdr_len_id_to_max_bit (bier_hdr_len_id_t id)
85{
86    return (bier_hdr_len_id_to_num_bits(id));
87}
88
89u32
90bier_hdr_len_id_to_prefix_len (bier_hdr_len_id_t id)
91{
92    return (bier_hdr_len_prefix_len[id]);
93}
94
95u8 *
96format_bier_hdr_len_id (u8 *s, va_list *ap)
97{
98    bier_hdr_len_id_t hli = va_arg(*ap, int); // int promotion of bier_hdr_len_id_t
99
100    return (format(s, "%s", bier_hdr_len_id_names[hli]));
101}
102
103u8 *
104format_bier_hdr_proto (u8 *s, va_list *ap)
105{
106    bier_hdr_proto_id_t pi = va_arg(*ap, int);
107
108    return (format(s, "%s", bier_hdr_proto_names[pi]));
109}
110
111int
112bier_table_id_cmp (const bier_table_id_t *btid1,
113                   const bier_table_id_t *btid2)
114{
115    int res;
116
117    res = (btid1->bti_set - btid2->bti_set);
118
119    if (0 == res)
120    {
121        res  = (btid1->bti_sub_domain - btid2->bti_sub_domain);
122    }
123    if (0 == res)
124    {
125        res = (btid1->bti_ecmp - btid2->bti_ecmp);
126    }
127    if (0 == res)
128    {
129        res = (btid1->bti_hdr_len - btid2->bti_hdr_len);
130    }
131    if (0 == res)
132    {
133        res = (btid1->bti_type - btid2->bti_type);
134    }
135    return (res);
136}
137
138dpo_proto_t
139bier_hdr_proto_to_dpo (bier_hdr_proto_id_t bproto)
140{
141    switch (bproto)
142    {
143    case BIER_HDR_PROTO_INVALID:
144    case BIER_HDR_PROTO_CTRL:
145    case BIER_HDR_PROTO_OAM:
146        ASSERT(0);
147        break;
148    case BIER_HDR_PROTO_MPLS_DOWN_STREAM:
149    case BIER_HDR_PROTO_MPLS_UP_STREAM:
150        return (DPO_PROTO_MPLS);
151    case BIER_HDR_PROTO_ETHERNET:
152    case BIER_HDR_PROTO_VXLAN:
153        return (DPO_PROTO_ETHERNET);
154    case BIER_HDR_PROTO_IPV4:
155        return (DPO_PROTO_IP4);
156    case BIER_HDR_PROTO_IPV6:
157        return (DPO_PROTO_IP4);
158    }
159
160    return (DPO_PROTO_NUM);
161}
162
163bier_bift_id_t
164bier_bift_id_encode (bier_table_set_id_t set,
165                     bier_table_sub_domain_id_t sd,
166                     bier_hdr_len_id_t bsl)
167{
168    bier_bift_id_t id;
169
170    id = bsl;
171    id = id << 8;
172    id |= sd;
173    id = id << 8;
174    id |= set;
175
176    return (id);
177}
178
179void
180bier_bift_id_decode (bier_bift_id_t id,
181                     bier_table_set_id_t *set,
182                     bier_table_sub_domain_id_t *sd,
183                     bier_hdr_len_id_t *bsl)
184{
185    *set = id & 0xff;
186    id = id >> 8;
187    *sd = id & 0xff;
188    id = id >> 8;
189    *bsl = id;
190}
191
192u8 *
193format_bier_table_id (u8 *s, va_list *ap)
194{
195    bier_table_id_t *btid = va_arg(*ap, bier_table_id_t *);
196
197    return (format(s, "sub-domain:%d set:%d ecmp:%d bsl:%U",
198                   btid->bti_sub_domain,
199                   btid->bti_set,
200                   btid->bti_ecmp,
201                   format_bier_hdr_len_id, btid->bti_hdr_len));
202}
203
204u8 *
205format_bier_hdr (u8 *s, va_list *ap)
206{
207    bier_hdr_t *bh = va_arg(*ap, bier_hdr_t *);
208    bier_hdr_t copy = *bh;
209
210    bier_hdr_ntoh(&copy);
211
212    return (format(s, "nibble:%d version:%d hdr-len:%U entropy:%d proto:%U src:%d",
213                   bier_hdr_get_1st_nibble(&copy),
214                   bier_hdr_get_version(&copy),
215                   format_bier_hdr_len_id, bier_hdr_get_len_id(&copy),
216                   bier_hdr_get_entropy(&copy),
217                   format_bier_hdr_proto, bier_hdr_get_proto_id(&copy),
218                   bier_hdr_get_src_id(&copy)));
219}
220
221 u8*
222 format_bier_bift_id(u8 *s, va_list *ap)
223 {
224     bier_bift_id_t id = va_arg(*ap, bier_bift_id_t);
225     bier_table_sub_domain_id_t sd;
226     bier_table_set_id_t set;
227     bier_hdr_len_id_t bsl;
228
229     bier_bift_id_decode(id, &set, &sd, &bsl);
230
231     return (format(s, "0x%x -> set:%d sd:%d hdr-len:%U",
232                    id, set, sd, format_bier_hdr_len_id, bsl));
233 }
234