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