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