]>
Commit | Line | Data |
---|---|---|
3bffc610 | 1 | /* |
d40533fc | 2 | * Copyright (c) 2011, 2012, 2013, 2014, 2019 Nicira, Inc. |
3bffc610 BP |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | * you may not use this file except in compliance with the License. | |
6 | * You may obtain a copy of the License at: | |
7 | * | |
8 | * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | * | |
10 | * Unless required by applicable law or agreed to in writing, software | |
11 | * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | * See the License for the specific language governing permissions and | |
14 | * limitations under the License. | |
15 | */ | |
16 | ||
17 | #include <config.h> | |
3f636c7e JR |
18 | #undef NDEBUG |
19 | #include "odp-util.h" | |
3bffc610 | 20 | #include <stdio.h> |
3e8a2ad1 | 21 | #include "openvswitch/dynamic-string.h" |
3bffc610 | 22 | #include "flow.h" |
e29747e4 | 23 | #include "openvswitch/match.h" |
64c96779 | 24 | #include "openvswitch/ofpbuf.h" |
3f636c7e | 25 | #include "ovstest.h" |
eb1b39b3 | 26 | #include "util.h" |
0d71302e | 27 | #include "openvswitch/ofp-flow.h" |
e6211adc | 28 | #include "openvswitch/vlog.h" |
3bffc610 | 29 | |
eb1b39b3 | 30 | static int |
e6cc0bab | 31 | parse_keys(bool wc_keys) |
3bffc610 | 32 | { |
2508ac16 | 33 | int exit_code = 0; |
3bffc610 BP |
34 | struct ds in; |
35 | ||
36 | ds_init(&in); | |
316bd0f8 | 37 | vlog_set_levels_from_string_assert("odp_util:console:dbg"); |
06d7ae7d | 38 | while (!ds_get_test_line(&in, stdin)) { |
b0f7b9b5 | 39 | enum odp_key_fitness fitness; |
3bffc610 | 40 | struct ofpbuf odp_key; |
e6cc0bab | 41 | struct ofpbuf odp_mask; |
3bffc610 BP |
42 | struct flow flow; |
43 | struct ds out; | |
44 | int error; | |
3bffc610 | 45 | |
df2c07f4 | 46 | /* Convert string to OVS DP key. */ |
3bffc610 | 47 | ofpbuf_init(&odp_key, 0); |
e6cc0bab | 48 | ofpbuf_init(&odp_mask, 0); |
d40533fc | 49 | char *error_s; |
e6cc0bab | 50 | error = odp_flow_from_string(ds_cstr(&in), NULL, |
d40533fc | 51 | &odp_key, &odp_mask, &error_s); |
3bffc610 | 52 | if (error) { |
d40533fc BP |
53 | printf("odp_flow_from_string: error (%s)\n", error_s); |
54 | free(error_s); | |
3bffc610 BP |
55 | goto next; |
56 | } | |
57 | ||
e6cc0bab | 58 | if (!wc_keys) { |
5262eea1 JG |
59 | struct odp_flow_key_parms odp_parms = { |
60 | .flow = &flow, | |
2494ccd7 JS |
61 | .support = { |
62 | .recirc = true, | |
07659514 JS |
63 | .ct_state = true, |
64 | .ct_zone = true, | |
8e53fe8c | 65 | .ct_mark = true, |
9daf2348 | 66 | .ct_label = true, |
f0fb825a | 67 | .max_vlan_headers = SIZE_MAX, |
d0d57149 | 68 | .nd_ext = true, |
2494ccd7 | 69 | }, |
5262eea1 JG |
70 | }; |
71 | ||
e6cc0bab | 72 | /* Convert odp_key to flow. */ |
d40533fc BP |
73 | fitness = odp_flow_key_to_flow(odp_key.data, odp_key.size, &flow, |
74 | &error_s); | |
e6cc0bab AZ |
75 | switch (fitness) { |
76 | case ODP_FIT_PERFECT: | |
77 | break; | |
78 | ||
79 | case ODP_FIT_TOO_LITTLE: | |
80 | printf("ODP_FIT_TOO_LITTLE: "); | |
81 | break; | |
82 | ||
83 | case ODP_FIT_TOO_MUCH: | |
84 | printf("ODP_FIT_TOO_MUCH: "); | |
85 | break; | |
86 | ||
87 | case ODP_FIT_ERROR: | |
d40533fc BP |
88 | printf("odp_flow_key_to_flow: error (%s)\n", error_s); |
89 | free(error_s); | |
e6cc0bab AZ |
90 | goto next; |
91 | } | |
92 | /* Convert cls_rule back to odp_key. */ | |
93 | ofpbuf_uninit(&odp_key); | |
94 | ofpbuf_init(&odp_key, 0); | |
5262eea1 | 95 | odp_flow_key_from_flow(&odp_parms, &odp_key); |
e6cc0bab | 96 | |
6fd6ed71 | 97 | if (odp_key.size > ODPUTIL_FLOW_KEY_BYTES) { |
437d0d22 | 98 | printf ("too long: %"PRIu32" > %d\n", |
6fd6ed71 | 99 | odp_key.size, ODPUTIL_FLOW_KEY_BYTES); |
e6cc0bab AZ |
100 | exit_code = 1; |
101 | } | |
2508ac16 BP |
102 | } |
103 | ||
3bffc610 BP |
104 | /* Convert odp_key to string. */ |
105 | ds_init(&out); | |
e6cc0bab | 106 | if (wc_keys) { |
6fd6ed71 PS |
107 | odp_flow_format(odp_key.data, odp_key.size, |
108 | odp_mask.data, odp_mask.size, NULL, &out, false); | |
e6cc0bab | 109 | } else { |
6fd6ed71 | 110 | odp_flow_key_format(odp_key.data, odp_key.size, &out); |
e6cc0bab | 111 | } |
3bffc610 BP |
112 | puts(ds_cstr(&out)); |
113 | ds_destroy(&out); | |
114 | ||
115 | next: | |
116 | ofpbuf_uninit(&odp_key); | |
9d4e54c6 | 117 | ofpbuf_uninit(&odp_mask); |
3bffc610 BP |
118 | } |
119 | ds_destroy(&in); | |
120 | ||
2508ac16 | 121 | return exit_code; |
3bffc610 | 122 | } |
eb1b39b3 BP |
123 | |
124 | static int | |
125 | parse_actions(void) | |
126 | { | |
127 | struct ds in; | |
128 | ||
129 | ds_init(&in); | |
316bd0f8 | 130 | vlog_set_levels_from_string_assert("odp_util:console:dbg"); |
eb1b39b3 BP |
131 | while (!ds_get_test_line(&in, stdin)) { |
132 | struct ofpbuf odp_actions; | |
133 | struct ds out; | |
134 | int error; | |
135 | ||
136 | /* Convert string to OVS DP actions. */ | |
137 | ofpbuf_init(&odp_actions, 0); | |
138 | error = odp_actions_from_string(ds_cstr(&in), NULL, &odp_actions); | |
139 | if (error) { | |
140 | printf("odp_actions_from_string: error\n"); | |
141 | goto next; | |
142 | } | |
143 | ||
144 | /* Convert odp_actions back to string. */ | |
145 | ds_init(&out); | |
0722f341 | 146 | format_odp_actions(&out, odp_actions.data, odp_actions.size, NULL); |
eb1b39b3 BP |
147 | puts(ds_cstr(&out)); |
148 | ds_destroy(&out); | |
149 | ||
150 | next: | |
151 | ofpbuf_uninit(&odp_actions); | |
152 | } | |
153 | ds_destroy(&in); | |
154 | ||
155 | return 0; | |
156 | } | |
157 | ||
5a0a5702 GS |
158 | static int |
159 | parse_filter(char *filter_parse) | |
160 | { | |
161 | struct ds in; | |
162 | struct flow flow_filter; | |
163 | struct flow_wildcards wc_filter; | |
164 | char *error, *filter = NULL; | |
165 | ||
166 | vlog_set_levels_from_string_assert("odp_util:console:dbg"); | |
167 | if (filter_parse && !strncmp(filter_parse, "filter=", 7)) { | |
13a233f7 | 168 | filter = xstrdup(filter_parse + 7); |
5a0a5702 GS |
169 | memset(&flow_filter, 0, sizeof(flow_filter)); |
170 | memset(&wc_filter, 0, sizeof(wc_filter)); | |
171 | ||
8d8ab6c2 | 172 | error = parse_ofp_exact_flow(&flow_filter, &wc_filter, NULL, filter, |
5a0a5702 GS |
173 | NULL); |
174 | if (error) { | |
175 | ovs_fatal(0, "Failed to parse filter (%s)", error); | |
176 | } | |
177 | } else { | |
178 | ovs_fatal(0, "No filter to parse."); | |
179 | } | |
180 | ||
181 | ds_init(&in); | |
182 | while (!ds_get_test_line(&in, stdin)) { | |
183 | struct ofpbuf odp_key; | |
184 | struct ofpbuf odp_mask; | |
185 | struct ds out; | |
5a0a5702 GS |
186 | |
187 | /* Convert string to OVS DP key. */ | |
188 | ofpbuf_init(&odp_key, 0); | |
189 | ofpbuf_init(&odp_mask, 0); | |
d40533fc BP |
190 | char *error_s; |
191 | if (odp_flow_from_string(ds_cstr(&in), NULL, &odp_key, &odp_mask, | |
192 | &error_s)) { | |
193 | printf("odp_flow_from_string: error (%s)\n", error_s); | |
194 | free(error_s); | |
5a0a5702 GS |
195 | goto next; |
196 | } | |
197 | ||
198 | if (filter) { | |
199 | struct flow flow; | |
200 | struct flow_wildcards wc; | |
201 | struct match match, match_filter; | |
202 | struct minimatch minimatch; | |
203 | ||
d40533fc BP |
204 | odp_flow_key_to_flow(odp_key.data, odp_key.size, &flow, NULL); |
205 | odp_flow_key_to_mask(odp_mask.data, odp_mask.size, &wc, &flow, | |
206 | NULL); | |
5a0a5702 GS |
207 | match_init(&match, &flow, &wc); |
208 | ||
209 | match_init(&match_filter, &flow_filter, &wc); | |
210 | match_init(&match_filter, &match_filter.flow, &wc_filter); | |
211 | minimatch_init(&minimatch, &match_filter); | |
212 | ||
213 | if (!minimatch_matches_flow(&minimatch, &match.flow)) { | |
214 | minimatch_destroy(&minimatch); | |
215 | goto next; | |
216 | } | |
217 | minimatch_destroy(&minimatch); | |
218 | } | |
219 | /* Convert odp_key to string. */ | |
220 | ds_init(&out); | |
6fd6ed71 PS |
221 | odp_flow_format(odp_key.data, odp_key.size, |
222 | odp_mask.data, odp_mask.size, NULL, &out, false); | |
5a0a5702 GS |
223 | puts(ds_cstr(&out)); |
224 | ds_destroy(&out); | |
225 | ||
226 | next: | |
227 | ofpbuf_uninit(&odp_key); | |
228 | ofpbuf_uninit(&odp_mask); | |
229 | } | |
230 | ds_destroy(&in); | |
231 | ||
232 | free(filter); | |
233 | return 0; | |
234 | } | |
235 | ||
eadd1644 AZ |
236 | static void |
237 | test_odp_main(int argc, char *argv[]) | |
eb1b39b3 | 238 | { |
eadd1644 AZ |
239 | int exit_code = 0; |
240 | ||
5a0a5702 | 241 | set_program_name(argv[0]); |
eb1b39b3 | 242 | if (argc == 2 &&!strcmp(argv[1], "parse-keys")) { |
eadd1644 | 243 | exit_code =parse_keys(false); |
e6cc0bab | 244 | } else if (argc == 2 &&!strcmp(argv[1], "parse-wc-keys")) { |
eadd1644 | 245 | exit_code =parse_keys(true); |
eb1b39b3 | 246 | } else if (argc == 2 && !strcmp(argv[1], "parse-actions")) { |
eadd1644 | 247 | exit_code = parse_actions(); |
5a0a5702 | 248 | } else if (argc == 3 && !strcmp(argv[1], "parse-filter")) { |
eadd1644 | 249 | exit_code =parse_filter(argv[2]); |
eb1b39b3 | 250 | } else { |
e6cc0bab | 251 | ovs_fatal(0, "usage: %s parse-keys | parse-wc-keys | parse-actions", argv[0]); |
eb1b39b3 | 252 | } |
eadd1644 AZ |
253 | |
254 | exit(exit_code); | |
eb1b39b3 | 255 | } |
eadd1644 AZ |
256 | |
257 | OVSTEST_REGISTER("test-odp", test_odp_main); |