blob: 0aeecae545fe95a20abc005465982bd8292fb3f1 [file] [log] [blame]
Neale Ranns3bab8f92019-12-04 06:11:00 +00001/*
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/fib/fib_source.h>
17
18static const char *fib_source_names[] = FIB_SOURCES;
19static const char *fib_source_behaviour_names[] = FIB_SOURCE_BEHAVIOURS;
20
21static fib_source_t fib_source_id = FIB_SOURCE_LAST+1;
22
23typedef struct fib_source_prio_t_
24{
25 fib_source_priority_t fsp_class;
26 fib_source_priority_t fsp_slot;
27} fib_source_prio_t;
28
29/**
30 * for each client requested priority count the number pf uses of
31 * that prio so we can asign is usage a slot number, and therefore
32 * each request will have a unique value.
33 */
34STATIC_ASSERT_SIZEOF(fib_source_priority_t, 1);
35static fib_source_priority_t fib_source_prio_by_class[0x100];
36
37typedef struct fib_source_reg_t_
38{
39 fib_source_t fsr_source;
40 const char *fsr_name;
41 fib_source_behaviour_t fsr_behaviour;
42 fib_source_prio_t fsr_prio;
43} fib_source_reg_t;
44
45static fib_source_reg_t *fib_source_regs;
46
47
48u16
49fib_source_get_prio (fib_source_t src)
50{
51 ASSERT(vec_len(fib_source_regs) > src);
52
53 return (((u16)fib_source_regs[src].fsr_prio.fsp_class << 8) |
54 fib_source_regs[src].fsr_prio.fsp_slot);
55}
56
57fib_source_behaviour_t
58fib_source_get_behaviour (fib_source_t src)
59{
60 ASSERT(vec_len(fib_source_regs) > src);
61
62 return (fib_source_regs[src].fsr_behaviour);
63}
64
65u8 *
66format_fib_source (u8 *s, va_list *a)
67{
68 fib_source_t src = va_arg(*a, int);
69
70 ASSERT(vec_len(fib_source_regs) > src);
71
72 return (format(s, "%s", fib_source_regs[src].fsr_name));
73}
74
75fib_source_priority_cmp_t
76fib_source_cmp (fib_source_t s1,
77 fib_source_t s2)
78{
79 if (fib_source_get_prio(s1) <
80 fib_source_get_prio(s2))
81 {
82 return (FIB_SOURCE_CMP_BETTER);
83 }
84 else if (fib_source_get_prio(s1) >
85 fib_source_get_prio(s2))
86 {
87 return (FIB_SOURCE_CMP_WORSE);
88 }
89 return (FIB_SOURCE_CMP_EQUAL);
90}
91
92static void
93fib_source_reg_init (fib_source_t src,
94 const char *name,
95 fib_source_priority_t prio,
96 fib_source_behaviour_t bh)
97{
98 fib_source_priority_t slot;
99 fib_source_reg_t *fsr;
100
101 /*
102 * ensure we assign a unique priority to each request
103 * otherwise different source will be treated like ECMP
104 */
105 slot = fib_source_prio_by_class[prio]++;
106
107 vec_validate(fib_source_regs, src);
108
109 fsr = &fib_source_regs[src];
110 fsr->fsr_source = src;
111 fsr->fsr_name = strdup(name);
112 fsr->fsr_prio.fsp_class = prio;
113 fsr->fsr_prio.fsp_slot = slot;
114 fsr->fsr_behaviour = bh;
115}
116
117fib_source_t
118fib_source_allocate (const char *name,
119 fib_source_priority_t prio,
120 fib_source_behaviour_t bh)
121{
122 fib_source_t src;
123
124 // max value range
125 ASSERT(fib_source_id < 255);
126 if (fib_source_id == 255)
127 return (FIB_SOURCE_INVALID);
128
129 src = fib_source_id++;
130
131 fib_source_reg_init(src, name, prio, bh);
132
133 return (src);
134}
135
136void
137fib_source_register (fib_source_t src,
138 fib_source_priority_t prio,
139 fib_source_behaviour_t bh)
140{
141 fib_source_reg_init(src, fib_source_names[src], prio, bh);
142}
143
144static u8 *
145format_fib_source_reg (u8 *s, va_list *a)
146{
147 fib_source_reg_t *fsr = va_arg(*a, fib_source_reg_t*);
148
149 s = format(s, "[%d] %U prio:%d.%d behaviour:%s",
150 fsr->fsr_source,
151 format_fib_source, fsr->fsr_source,
152 fsr->fsr_prio.fsp_class, fsr->fsr_prio.fsp_slot,
153 fib_source_behaviour_names[fsr->fsr_behaviour]);
154
155 return (s);
156}
157
158static int
159fib_source_reg_cmp_for_sort (void * v1,
160 void * v2)
161{
162 fib_source_reg_t *fsr1 = v1, *fsr2 = v2;
163
164 return (fib_source_get_prio(fsr1->fsr_source) -
165 fib_source_get_prio(fsr2->fsr_source));
166}
167
168void
169fib_source_walk (fib_source_walk_t fn,
170 void *ctx)
171{
172 fib_source_reg_t *fsr;
173
174 vec_foreach(fsr, fib_source_regs)
175 {
176 if (WALK_STOP == fn(fsr->fsr_source,
177 fsr->fsr_name,
178 fsr->fsr_prio.fsp_class,
179 fsr->fsr_behaviour,
180 ctx))
181 break;
182 }
183}
184
185static clib_error_t *
186fib_source_show (vlib_main_t * vm,
187 unformat_input_t * input,
188 vlib_cli_command_t * cmd)
189{
190 fib_source_reg_t *fsr, *fsrs;
191
192 fsrs = vec_dup(fib_source_regs);
193
194 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
195 {
196 if (unformat (input, "prio") ||
197 unformat (input, "priority"))
198 vec_sort_with_function(fsrs, fib_source_reg_cmp_for_sort);
199 }
200 vec_foreach(fsr, fsrs)
201 {
202 vlib_cli_output(vm, "%U", format_fib_source_reg, fsr);
203 }
204 vec_free(fsrs);
205
206 return (NULL);
207}
208
209VLIB_CLI_COMMAND (show_fib_sources, static) = {
210 .path = "show fib source",
211 .function = fib_source_show,
212 .short_help = "show fib source [prio]",
213};
214
215
216void
217fib_source_module_init (void)
218{
219#define _(s,p,b) fib_source_register(s,p,b);
220 foreach_fib_source
221#undef _
222}