FIB: encode the label stack in the FIB path during table dump
[vpp.git] / src / vnet / mfib / mfib_types.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/mfib/mfib_types.h>
17
18 #include <vnet/ip/ip.h>
19
20 /**
21  * String names for each flag
22  */
23 static const char *mfib_flag_names[] = MFIB_ENTRY_NAMES_SHORT;
24 static const char *mfib_flag_names_long[] = MFIB_ENTRY_NAMES_LONG;
25
26 static const char *mfib_itf_flag_long_names[] = MFIB_ITF_NAMES_LONG;
27 static const char *mfib_itf_flag_names[] = MFIB_ITF_NAMES_SHORT;
28
29 int
30 mfib_prefix_is_cover (const mfib_prefix_t *p1,
31                       const mfib_prefix_t *p2)
32 {
33     if (!ip46_address_is_equal(&p1->fp_src_addr, &p2->fp_src_addr))
34         return (0);
35
36     switch (p1->fp_proto)
37     {
38     case FIB_PROTOCOL_IP4:
39         return (ip4_destination_matches_route(&ip4_main,
40                                               &p1->fp_grp_addr.ip4,
41                                               &p2->fp_grp_addr.ip4,
42                                               p1->fp_len));
43     case FIB_PROTOCOL_IP6:
44         return (ip6_destination_matches_route(&ip6_main,
45                                               &p1->fp_grp_addr.ip6,
46                                               &p2->fp_grp_addr.ip6,
47                                               p1->fp_len));
48     case FIB_PROTOCOL_MPLS:
49         break;
50     }
51     return (0);
52 }
53
54 int
55 mfib_prefix_is_host (const mfib_prefix_t *pfx)
56 {
57     switch (pfx->fp_proto)
58     {
59     case FIB_PROTOCOL_IP4:
60         return (64 == pfx->fp_len);
61     case FIB_PROTOCOL_IP6:
62         return (256 == pfx->fp_len);
63     case FIB_PROTOCOL_MPLS:
64         ASSERT(0);
65         break;
66     }
67     return (0);
68 }
69
70 fib_forward_chain_type_t
71 mfib_forw_chain_type_from_dpo_proto (dpo_proto_t proto)
72 {
73     switch (proto)
74     {
75     case DPO_PROTO_IP4:
76         return (FIB_FORW_CHAIN_TYPE_MCAST_IP4);
77     case DPO_PROTO_IP6:
78         return (FIB_FORW_CHAIN_TYPE_MCAST_IP6);
79     case DPO_PROTO_MPLS:
80     case DPO_PROTO_ETHERNET:
81     case DPO_PROTO_NSH:
82     case DPO_PROTO_BIER:
83         break;
84     }
85     ASSERT(0);
86     return (FIB_FORW_CHAIN_TYPE_MCAST_IP4);
87 }
88
89 fib_forward_chain_type_t
90 mfib_forw_chain_type_from_fib_proto (fib_protocol_t proto)
91 {
92     switch (proto)
93     {
94     case FIB_PROTOCOL_IP4:
95         return (FIB_FORW_CHAIN_TYPE_MCAST_IP4);
96     case FIB_PROTOCOL_IP6:
97         return (FIB_FORW_CHAIN_TYPE_MCAST_IP6);
98     case FIB_PROTOCOL_MPLS:
99         break;
100     }
101     ASSERT(0);
102     return (FIB_FORW_CHAIN_TYPE_MCAST_IP4);
103 }
104
105 u8 *
106 format_mfib_prefix (u8 * s, va_list * args)
107 {
108     mfib_prefix_t *fp = va_arg (*args, mfib_prefix_t *);
109
110     /*
111      * protocol specific so it prints ::/0 correctly.
112      */
113     switch (fp->fp_proto)
114     {
115     case FIB_PROTOCOL_IP6:
116     {
117         ip6_address_t p6 = fp->fp_grp_addr.ip6;
118         u32 len = (fp->fp_len > 128 ? 128 : fp->fp_len);
119
120         ip6_address_mask(&p6, &(ip6_main.fib_masks[len]));
121
122         if (ip6_address_is_zero(&fp->fp_src_addr.ip6))
123         {
124             s = format(s, "(*, ");
125         }
126         else
127         {
128             s = format (s, "(%U, ", format_ip6_address, &fp->fp_src_addr.ip6);
129         }
130         s = format (s, "%U", format_ip6_address, &p6);
131         s = format (s, "/%d)", len);
132         break;
133     }
134     case FIB_PROTOCOL_IP4:
135     {
136         ip4_address_t p4 = fp->fp_grp_addr.ip4;
137         u32 len = (fp->fp_len > 32 ? 32 : fp->fp_len);
138
139         p4.as_u32 &= ip4_main.fib_masks[len];
140
141         if (0 == fp->fp_src_addr.ip4.as_u32)
142         {
143             s = format(s, "(*, ");
144         }
145         else
146         {
147             s = format (s, "(%U, ", format_ip4_address, &fp->fp_src_addr.ip4);
148         }
149         s = format (s, "%U", format_ip4_address, &p4);
150         s = format (s, "/%d)", len);
151         break;
152     }
153     case FIB_PROTOCOL_MPLS:
154         break;
155     }
156
157     return (s);
158 }
159
160 u8 *
161 format_mfib_entry_flags (u8 * s, va_list * args)
162 {
163     mfib_entry_attribute_t attr;
164     mfib_entry_flags_t flags;
165
166     flags = va_arg (*args, mfib_entry_flags_t);
167
168     if (MFIB_ENTRY_FLAG_NONE != flags) {
169         s = format(s, " flags:");
170         FOR_EACH_MFIB_ATTRIBUTE(attr) {
171             if ((1<<attr) & flags) {
172                 s = format (s, "%s,", mfib_flag_names_long[attr]);
173             }
174         }
175     }
176
177     return (s);
178 }
179
180 u8 *
181 format_mfib_itf_flags (u8 * s, va_list * args)
182 {
183     mfib_itf_attribute_t attr;
184     mfib_itf_flags_t flags;
185
186     flags = va_arg (*args, mfib_itf_flags_t);
187
188     FOR_EACH_MFIB_ITF_ATTRIBUTE(attr) {
189         if ((1<<attr) & flags) {
190             s = format (s, "%s,", mfib_itf_flag_long_names[attr]);
191         }
192     }
193
194     return (s);
195 }
196
197 uword
198 unformat_mfib_itf_flags (unformat_input_t * input,
199                          va_list * args)
200 {
201     mfib_itf_flags_t old, *iflags = va_arg (*args, mfib_itf_flags_t*);
202     mfib_itf_attribute_t attr;
203
204     old = *iflags;
205     FOR_EACH_MFIB_ITF_ATTRIBUTE(attr) {
206         if (unformat (input, mfib_itf_flag_long_names[attr]))
207             *iflags |= (1 << attr);
208     }
209     FOR_EACH_MFIB_ITF_ATTRIBUTE(attr) {
210         if (unformat (input, mfib_itf_flag_names[attr]))
211             *iflags |= (1 << attr);
212     }
213
214     return (old == *iflags ? 0 : 1);
215 }
216
217 uword
218 unformat_mfib_entry_flags (unformat_input_t * input,
219                            va_list * args)
220 {
221     mfib_entry_flags_t old, *eflags = va_arg (*args, mfib_entry_flags_t*);
222     mfib_entry_attribute_t attr;
223
224     old = *eflags;
225     FOR_EACH_MFIB_ATTRIBUTE(attr) {
226         if (unformat (input, mfib_flag_names_long[attr]))
227             *eflags |= (1 << attr);
228     }
229     FOR_EACH_MFIB_ATTRIBUTE(attr) {
230         if (unformat (input, mfib_flag_names[attr]))
231             *eflags |= (1 << attr);
232     }
233
234     return (old == *eflags ? 0 : 1);
235 }
236
237 clib_error_t *
238 mfib_show_route_flags (vlib_main_t * vm,
239                        unformat_input_t * main_input,
240                        vlib_cli_command_t * cmd)
241 {
242     mfib_entry_attribute_t attr;
243
244     FOR_EACH_MFIB_ATTRIBUTE(attr) {
245         vlib_cli_output(vm, "%s = %s",
246                         mfib_flag_names[attr],
247                         mfib_flag_names_long[attr]);
248     }
249
250     return (NULL);
251 }
252
253 /*?
254  * This command displays the set of supported flags applicable to an MFIB route
255  */
256 /* *INDENT-OFF* */
257 VLIB_CLI_COMMAND (mfib_route_flags_command, static) =
258 {
259   .path = "show mfib route flags",
260   .short_help = "Flags applicable to an MFIB route",
261   .function = mfib_show_route_flags,
262   .is_mp_safe = 1,
263 };
264 /* *INDENT-ON* */
265
266 clib_error_t *
267 mfib_show_itf_flags (vlib_main_t * vm,
268                      unformat_input_t * main_input,
269                      vlib_cli_command_t * cmd)
270 {
271     mfib_itf_attribute_t attr;
272
273     FOR_EACH_MFIB_ITF_ATTRIBUTE(attr) {
274         vlib_cli_output(vm, "%s = %s",
275                         mfib_itf_flag_names[attr],
276                         mfib_itf_flag_long_names[attr]);
277     }
278
279     return (NULL);
280 }
281
282 /*?
283  * This command displays the set of supported flags applicable to an MFIB interface
284  */
285 /* *INDENT-OFF* */
286 VLIB_CLI_COMMAND (mfib_itf_flags_command, static) =
287 {
288   .path = "show mfib itf flags",
289   .short_help = "Flags applicable to an MFIB interfaces",
290   .function = mfib_show_itf_flags,
291   .is_mp_safe = 1,
292 };
293 /* *INDENT-ON* */