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/feature/feature.h>
17 : #include <vnet/classify/flow_classify.h>
18 :
19 : flow_classify_main_t flow_classify_main;
20 :
21 : static void
22 0 : vnet_flow_classify_feature_enable (vlib_main_t * vnm,
23 : flow_classify_main_t * fcm,
24 : u32 sw_if_index,
25 : flow_classify_table_id_t tid,
26 : int feature_enable)
27 : {
28 : vnet_feature_config_main_t *vfcm;
29 : u8 arc;
30 :
31 0 : if (tid == FLOW_CLASSIFY_TABLE_IP4)
32 : {
33 0 : vnet_feature_enable_disable ("ip4-unicast", "ip4-flow-classify",
34 : sw_if_index, feature_enable, 0, 0);
35 0 : arc = vnet_get_feature_arc_index ("ip4-unicast");
36 : }
37 : else
38 : {
39 0 : vnet_feature_enable_disable ("ip6-unicast", "ip6-flow-classify",
40 : sw_if_index, feature_enable, 0, 0);
41 0 : arc = vnet_get_feature_arc_index ("ip6-unicast");
42 : }
43 :
44 0 : vfcm = vnet_get_feature_arc_config_main (arc);
45 0 : fcm->vnet_config_main[tid] = &vfcm->config_main;
46 0 : }
47 :
48 : int
49 0 : vnet_set_flow_classify_intfc (vlib_main_t * vm, u32 sw_if_index,
50 : u32 ip4_table_index, u32 ip6_table_index,
51 : u32 is_add)
52 : {
53 0 : flow_classify_main_t *fcm = &flow_classify_main;
54 0 : vnet_classify_main_t *vcm = fcm->vnet_classify_main;
55 0 : u32 pct[FLOW_CLASSIFY_N_TABLES] = { ip4_table_index, ip6_table_index };
56 : u32 ti;
57 :
58 : /* Assume that we've validated sw_if_index in the API layer */
59 :
60 0 : for (ti = 0; ti < FLOW_CLASSIFY_N_TABLES; ti++)
61 : {
62 0 : if (pct[ti] == ~0)
63 0 : continue;
64 :
65 0 : if (pool_is_free_index (vcm->tables, pct[ti]))
66 0 : return VNET_API_ERROR_NO_SUCH_TABLE;
67 :
68 0 : vec_validate_init_empty
69 : (fcm->classify_table_index_by_sw_if_index[ti], sw_if_index, ~0);
70 :
71 : /* Reject any DEL operation with wrong sw_if_index */
72 0 : if (!is_add &&
73 0 : (pct[ti] !=
74 0 : fcm->classify_table_index_by_sw_if_index[ti][sw_if_index]))
75 : {
76 0 : clib_warning
77 : ("Non-existent intf_idx=%d with table_index=%d for delete",
78 : sw_if_index, pct[ti]);
79 0 : return VNET_API_ERROR_NO_SUCH_TABLE;
80 : }
81 :
82 : /* Return ok on ADD operaton if feature is already enabled */
83 0 : if (is_add &&
84 0 : fcm->classify_table_index_by_sw_if_index[ti][sw_if_index] != ~0)
85 0 : return 0;
86 :
87 0 : vnet_flow_classify_feature_enable (vm, fcm, sw_if_index, ti, is_add);
88 :
89 0 : if (is_add)
90 0 : fcm->classify_table_index_by_sw_if_index[ti][sw_if_index] = pct[ti];
91 : else
92 0 : fcm->classify_table_index_by_sw_if_index[ti][sw_if_index] = ~0;
93 : }
94 :
95 :
96 0 : return 0;
97 : }
98 :
99 : static clib_error_t *
100 0 : set_flow_classify_command_fn (vlib_main_t * vm,
101 : unformat_input_t * input,
102 : vlib_cli_command_t * cmd)
103 : {
104 0 : vnet_main_t *vnm = vnet_get_main ();
105 0 : u32 sw_if_index = ~0;
106 0 : u32 ip4_table_index = ~0;
107 0 : u32 ip6_table_index = ~0;
108 0 : u32 is_add = 1;
109 0 : u32 idx_cnt = 0;
110 : int rv;
111 :
112 0 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
113 : {
114 0 : if (unformat (input, "interface %U", unformat_vnet_sw_interface,
115 : vnm, &sw_if_index))
116 : ;
117 0 : else if (unformat (input, "ip4-table %d", &ip4_table_index))
118 0 : idx_cnt++;
119 0 : else if (unformat (input, "ip6-table %d", &ip6_table_index))
120 0 : idx_cnt++;
121 0 : else if (unformat (input, "del"))
122 0 : is_add = 0;
123 : else
124 0 : break;
125 : }
126 :
127 0 : if (sw_if_index == ~0)
128 0 : return clib_error_return (0, "Interface must be specified.");
129 :
130 0 : if (!idx_cnt)
131 0 : return clib_error_return (0, "Table index should be specified.");
132 :
133 0 : if (idx_cnt > 1)
134 0 : return clib_error_return (0, "Only one table index per API is allowed.");
135 :
136 0 : rv = vnet_set_flow_classify_intfc (vm, sw_if_index, ip4_table_index,
137 : ip6_table_index, is_add);
138 :
139 0 : switch (rv)
140 : {
141 0 : case 0:
142 0 : break;
143 :
144 0 : case VNET_API_ERROR_NO_MATCHING_INTERFACE:
145 0 : return clib_error_return (0, "No such interface");
146 :
147 0 : case VNET_API_ERROR_NO_SUCH_ENTRY:
148 0 : return clib_error_return (0, "No such classifier table");
149 : }
150 0 : return 0;
151 : }
152 :
153 : /* *INDENT-OFF* */
154 272887 : VLIB_CLI_COMMAND (set_input_acl_command, static) = {
155 : .path = "set flow classify",
156 : .short_help =
157 : "set flow classify interface <int> [ip4-table <index>]\n"
158 : " [ip6-table <index>] [del]",
159 : .function = set_flow_classify_command_fn,
160 : };
161 : /* *INDENT-ON* */
162 :
163 : static uword
164 0 : unformat_table_type (unformat_input_t * input, va_list * va)
165 : {
166 0 : u32 *r = va_arg (*va, u32 *);
167 : u32 tid;
168 :
169 0 : if (unformat (input, "ip4"))
170 0 : tid = FLOW_CLASSIFY_TABLE_IP4;
171 0 : else if (unformat (input, "ip6"))
172 0 : tid = FLOW_CLASSIFY_TABLE_IP6;
173 : else
174 0 : return 0;
175 :
176 0 : *r = tid;
177 0 : return 1;
178 : }
179 :
180 : static clib_error_t *
181 0 : show_flow_classify_command_fn (vlib_main_t * vm,
182 : unformat_input_t * input,
183 : vlib_cli_command_t * cmd)
184 : {
185 0 : flow_classify_main_t *fcm = &flow_classify_main;
186 0 : u32 type = FLOW_CLASSIFY_N_TABLES;
187 : u32 *vec_tbl;
188 : int i;
189 :
190 0 : if (unformat (input, "type %U", unformat_table_type, &type))
191 : ;
192 : else
193 0 : return clib_error_return (0, "Type must be specified.");;
194 :
195 0 : if (type == FLOW_CLASSIFY_N_TABLES)
196 0 : return clib_error_return (0, "Invalid table type.");
197 :
198 0 : vec_tbl = fcm->classify_table_index_by_sw_if_index[type];
199 :
200 0 : if (vec_len (vec_tbl))
201 0 : vlib_cli_output (vm, "%10s%20s\t\t%s", "Intfc idx", "Classify table",
202 : "Interface name");
203 : else
204 0 : vlib_cli_output (vm, "No tables configured.");
205 :
206 0 : for (i = 0; i < vec_len (vec_tbl); i++)
207 : {
208 0 : if (vec_elt (vec_tbl, i) == ~0)
209 0 : continue;
210 :
211 0 : vlib_cli_output (vm, "%10d%20d\t\t%U", i, vec_elt (vec_tbl, i),
212 : format_vnet_sw_if_index_name, fcm->vnet_main, i);
213 : }
214 :
215 0 : return 0;
216 : }
217 :
218 : /* *INDENT-OFF* */
219 272887 : VLIB_CLI_COMMAND (show_flow_classify_command, static) = {
220 : .path = "show classify flow",
221 : .short_help = "show classify flow type [ip4|ip6]",
222 : .function = show_flow_classify_command_fn,
223 : };
224 : /* *INDENT-ON* */
225 :
226 : /*
227 : * fd.io coding-style-patch-verification: ON
228 : *
229 : * Local Variables:
230 : * eval: (c-set-style "gnu")
231 : * End:
232 : */
|