Add extern to *_main global variable declarations in header files.
[vpp.git] / src / vnet / classify / flow_classify.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 #include <vnet/classify/flow_classify.h>
16
17 flow_classify_main_t flow_classify_main;
18
19 static void
20 vnet_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 {
26   vnet_feature_config_main_t *vfcm;
27   u8 arc;
28
29   if (tid == FLOW_CLASSIFY_TABLE_IP4)
30     {
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     }
35   else
36     {
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     }
41
42   vfcm = vnet_get_feature_arc_config_main (arc);
43   fcm->vnet_config_main[tid] = &vfcm->config_main;
44 }
45
46 int 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
94 static clib_error_t *
95 set_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
148 VLIB_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
156 static uword
157 unformat_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 }
172 static clib_error_t *
173 show_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
210 VLIB_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 };