Line data Source code
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/fib/fib_source.h>
17 :
18 : static const char *fib_source_names[] = FIB_SOURCES;
19 : static const char *fib_source_behaviour_names[] = FIB_SOURCE_BEHAVIOURS;
20 :
21 : static fib_source_t fib_source_id = FIB_SOURCE_LAST+1;
22 :
23 : typedef 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 : */
34 : STATIC_ASSERT_SIZEOF(fib_source_priority_t, 1);
35 : static fib_source_priority_t fib_source_prio_by_class[0x100];
36 :
37 : typedef 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 :
45 : static fib_source_reg_t *fib_source_regs;
46 :
47 :
48 : u16
49 197606 : fib_source_get_prio (fib_source_t src)
50 : {
51 197606 : ASSERT(vec_len(fib_source_regs) > src);
52 :
53 395212 : return (((u16)fib_source_regs[src].fsr_prio.fsp_class << 8) |
54 197606 : fib_source_regs[src].fsr_prio.fsp_slot);
55 : }
56 :
57 : fib_source_behaviour_t
58 568212 : fib_source_get_behaviour (fib_source_t src)
59 : {
60 568212 : ASSERT(vec_len(fib_source_regs) > src);
61 :
62 568212 : return (fib_source_regs[src].fsr_behaviour);
63 : }
64 :
65 : u8 *
66 1451 : format_fib_source (u8 *s, va_list *a)
67 : {
68 1451 : fib_source_t src = va_arg(*a, int);
69 :
70 1451 : ASSERT(vec_len(fib_source_regs) > src);
71 :
72 1451 : return (format(s, "%s", fib_source_regs[src].fsr_name));
73 : }
74 :
75 : fib_source_priority_cmp_t
76 47231 : fib_source_cmp (fib_source_t s1,
77 : fib_source_t s2)
78 : {
79 94462 : if (fib_source_get_prio(s1) <
80 47231 : fib_source_get_prio(s2))
81 : {
82 308 : return (FIB_SOURCE_CMP_BETTER);
83 : }
84 93846 : else if (fib_source_get_prio(s1) >
85 46923 : fib_source_get_prio(s2))
86 : {
87 12040 : return (FIB_SOURCE_CMP_WORSE);
88 : }
89 34883 : return (FIB_SOURCE_CMP_EQUAL);
90 : }
91 :
92 : static void
93 21852 : fib_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 21852 : slot = fib_source_prio_by_class[prio]++;
106 :
107 21852 : vec_validate(fib_source_regs, src);
108 :
109 21852 : fsr = &fib_source_regs[src];
110 21852 : fsr->fsr_source = src;
111 21852 : fsr->fsr_name = strdup(name);
112 21852 : fsr->fsr_prio.fsp_class = prio;
113 21852 : fsr->fsr_prio.fsp_slot = slot;
114 21852 : fsr->fsr_behaviour = bh;
115 21852 : }
116 :
117 : fib_source_t
118 9202 : fib_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 9202 : ASSERT(fib_source_id < 255);
126 9202 : if (fib_source_id == 255)
127 0 : return (FIB_SOURCE_INVALID);
128 :
129 9202 : src = fib_source_id++;
130 :
131 9202 : fib_source_reg_init(src, name, prio, bh);
132 :
133 9202 : return (src);
134 : }
135 :
136 : void
137 12650 : fib_source_register (fib_source_t src,
138 : fib_source_priority_t prio,
139 : fib_source_behaviour_t bh)
140 : {
141 12650 : fib_source_reg_init(src, fib_source_names[src], prio, bh);
142 12650 : }
143 :
144 : static u8 *
145 78 : format_fib_source_reg (u8 *s, va_list *a)
146 : {
147 78 : fib_source_reg_t *fsr = va_arg(*a, fib_source_reg_t*);
148 :
149 78 : s = format(s, "[%d] %U prio:%d.%d behaviour:%s",
150 78 : fsr->fsr_source,
151 78 : format_fib_source, fsr->fsr_source,
152 78 : fsr->fsr_prio.fsp_class, fsr->fsr_prio.fsp_slot,
153 78 : fib_source_behaviour_names[fsr->fsr_behaviour]);
154 :
155 78 : return (s);
156 : }
157 :
158 : static int
159 150 : fib_source_reg_cmp_for_sort (void * v1,
160 : void * v2)
161 : {
162 150 : fib_source_reg_t *fsr1 = v1, *fsr2 = v2;
163 :
164 150 : return (fib_source_get_prio(fsr1->fsr_source) -
165 150 : fib_source_get_prio(fsr2->fsr_source));
166 : }
167 :
168 : void
169 2 : fib_source_walk (fib_source_walk_t fn,
170 : void *ctx)
171 : {
172 : fib_source_reg_t *fsr;
173 :
174 79 : vec_foreach(fsr, fib_source_regs)
175 : {
176 77 : if (WALK_STOP == fn(fsr->fsr_source,
177 : fsr->fsr_name,
178 77 : fsr->fsr_prio.fsp_class,
179 : fsr->fsr_behaviour,
180 : ctx))
181 0 : break;
182 : }
183 2 : }
184 :
185 : static clib_error_t *
186 2 : fib_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 2 : fsrs = vec_dup(fib_source_regs);
193 :
194 3 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
195 : {
196 1 : if (unformat (input, "prio") ||
197 0 : unformat (input, "priority"))
198 1 : vec_sort_with_function(fsrs, fib_source_reg_cmp_for_sort);
199 : }
200 80 : vec_foreach(fsr, fsrs)
201 : {
202 78 : vlib_cli_output(vm, "%U", format_fib_source_reg, fsr);
203 : }
204 2 : vec_free(fsrs);
205 :
206 2 : return (NULL);
207 : }
208 :
209 285289 : VLIB_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 :
216 : void
217 575 : fib_source_module_init (void)
218 : {
219 : #define _(s,p,b) fib_source_register(s,p,b);
220 575 : foreach_fib_source
221 : #undef _
222 575 : }
|