ipsec: IPSec protection for multi-point tunnel interfaces
[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
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 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   if (tid == FLOW_CLASSIFY_TABLE_IP4)
32     {
33       vnet_feature_enable_disable ("ip4-unicast", "ip4-flow-classify",
34                                    sw_if_index, feature_enable, 0, 0);
35       arc = vnet_get_feature_arc_index ("ip4-unicast");
36     }
37   else
38     {
39       vnet_feature_enable_disable ("ip6-unicast", "ip6-flow-classify",
40                                    sw_if_index, feature_enable, 0, 0);
41       arc = vnet_get_feature_arc_index ("ip6-unicast");
42     }
43
44   vfcm = vnet_get_feature_arc_config_main (arc);
45   fcm->vnet_config_main[tid] = &vfcm->config_main;
46 }
47
48 int
49 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   flow_classify_main_t *fcm = &flow_classify_main;
54   vnet_classify_main_t *vcm = fcm->vnet_classify_main;
55   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   for (ti = 0; ti < FLOW_CLASSIFY_N_TABLES; ti++)
61     {
62       if (pct[ti] == ~0)
63         continue;
64
65       if (pool_is_free_index (vcm->tables, pct[ti]))
66         return VNET_API_ERROR_NO_SUCH_TABLE;
67
68       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       if (!is_add &&
73           (pct[ti] !=
74            fcm->classify_table_index_by_sw_if_index[ti][sw_if_index]))
75         {
76           clib_warning
77             ("Non-existent intf_idx=%d with table_index=%d for delete",
78              sw_if_index, pct[ti]);
79           return VNET_API_ERROR_NO_SUCH_TABLE;
80         }
81
82       /* Return ok on ADD operaton if feature is already enabled */
83       if (is_add &&
84           fcm->classify_table_index_by_sw_if_index[ti][sw_if_index] != ~0)
85         return 0;
86
87       vnet_flow_classify_feature_enable (vm, fcm, sw_if_index, ti, is_add);
88
89       if (is_add)
90         fcm->classify_table_index_by_sw_if_index[ti][sw_if_index] = pct[ti];
91       else
92         fcm->classify_table_index_by_sw_if_index[ti][sw_if_index] = ~0;
93     }
94
95
96   return 0;
97 }
98
99 static clib_error_t *
100 set_flow_classify_command_fn (vlib_main_t * vm,
101                               unformat_input_t * input,
102                               vlib_cli_command_t * cmd)
103 {
104   vnet_main_t *vnm = vnet_get_main ();
105   u32 sw_if_index = ~0;
106   u32 ip4_table_index = ~0;
107   u32 ip6_table_index = ~0;
108   u32 is_add = 1;
109   u32 idx_cnt = 0;
110   int rv;
111
112   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
113     {
114       if (unformat (input, "interface %U", unformat_vnet_sw_interface,
115                     vnm, &sw_if_index))
116         ;
117       else if (unformat (input, "ip4-table %d", &ip4_table_index))
118         idx_cnt++;
119       else if (unformat (input, "ip6-table %d", &ip6_table_index))
120         idx_cnt++;
121       else if (unformat (input, "del"))
122         is_add = 0;
123       else
124         break;
125     }
126
127   if (sw_if_index == ~0)
128     return clib_error_return (0, "Interface must be specified.");
129
130   if (!idx_cnt)
131     return clib_error_return (0, "Table index should be specified.");
132
133   if (idx_cnt > 1)
134     return clib_error_return (0, "Only one table index per API is allowed.");
135
136   rv = vnet_set_flow_classify_intfc (vm, sw_if_index, ip4_table_index,
137                                      ip6_table_index, is_add);
138
139   switch (rv)
140     {
141     case 0:
142       break;
143
144     case VNET_API_ERROR_NO_MATCHING_INTERFACE:
145       return clib_error_return (0, "No such interface");
146
147     case VNET_API_ERROR_NO_SUCH_ENTRY:
148       return clib_error_return (0, "No such classifier table");
149     }
150   return 0;
151 }
152
153 /* *INDENT-OFF* */
154 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 unformat_table_type (unformat_input_t * input, va_list * va)
165 {
166   u32 *r = va_arg (*va, u32 *);
167   u32 tid;
168
169   if (unformat (input, "ip4"))
170     tid = FLOW_CLASSIFY_TABLE_IP4;
171   else if (unformat (input, "ip6"))
172     tid = FLOW_CLASSIFY_TABLE_IP6;
173   else
174     return 0;
175
176   *r = tid;
177   return 1;
178 }
179
180 static clib_error_t *
181 show_flow_classify_command_fn (vlib_main_t * vm,
182                                unformat_input_t * input,
183                                vlib_cli_command_t * cmd)
184 {
185   flow_classify_main_t *fcm = &flow_classify_main;
186   u32 type = FLOW_CLASSIFY_N_TABLES;
187   u32 *vec_tbl;
188   int i;
189
190   if (unformat (input, "type %U", unformat_table_type, &type))
191     ;
192   else
193     return clib_error_return (0, "Type must be specified.");;
194
195   if (type == FLOW_CLASSIFY_N_TABLES)
196     return clib_error_return (0, "Invalid table type.");
197
198   vec_tbl = fcm->classify_table_index_by_sw_if_index[type];
199
200   if (vec_len (vec_tbl))
201     vlib_cli_output (vm, "%10s%20s\t\t%s", "Intfc idx", "Classify table",
202                      "Interface name");
203   else
204     vlib_cli_output (vm, "No tables configured.");
205
206   for (i = 0; i < vec_len (vec_tbl); i++)
207     {
208       if (vec_elt (vec_tbl, i) == ~0)
209         continue;
210
211       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   return 0;
216 }
217
218 /* *INDENT-OFF* */
219 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  */