]>
Commit | Line | Data |
---|---|---|
3bffc610 | 1 | /* |
eadd1644 | 2 | * Copyright (c) 2011, 2012, 2013, 2014 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" |
7888d2a6 | 27 | #include "openvswitch/ofp-parse.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 AZ |
48 | ofpbuf_init(&odp_mask, 0); |
49 | error = odp_flow_from_string(ds_cstr(&in), NULL, | |
50 | &odp_key, &odp_mask); | |
3bffc610 | 51 | if (error) { |
e6cc0bab | 52 | printf("odp_flow_from_string: error\n"); |
3bffc610 BP |
53 | goto next; |
54 | } | |
55 | ||
e6cc0bab | 56 | if (!wc_keys) { |
5262eea1 JG |
57 | struct odp_flow_key_parms odp_parms = { |
58 | .flow = &flow, | |
2494ccd7 JS |
59 | .support = { |
60 | .recirc = true, | |
07659514 JS |
61 | .ct_state = true, |
62 | .ct_zone = true, | |
8e53fe8c | 63 | .ct_mark = true, |
9daf2348 | 64 | .ct_label = true, |
f0fb825a | 65 | .max_vlan_headers = SIZE_MAX, |
2494ccd7 | 66 | }, |
5262eea1 JG |
67 | }; |
68 | ||
e6cc0bab | 69 | /* Convert odp_key to flow. */ |
6fd6ed71 | 70 | fitness = odp_flow_key_to_flow(odp_key.data, odp_key.size, &flow); |
e6cc0bab AZ |
71 | switch (fitness) { |
72 | case ODP_FIT_PERFECT: | |
73 | break; | |
74 | ||
75 | case ODP_FIT_TOO_LITTLE: | |
76 | printf("ODP_FIT_TOO_LITTLE: "); | |
77 | break; | |
78 | ||
79 | case ODP_FIT_TOO_MUCH: | |
80 | printf("ODP_FIT_TOO_MUCH: "); | |
81 | break; | |
82 | ||
83 | case ODP_FIT_ERROR: | |
84 | printf("odp_flow_key_to_flow: error\n"); | |
85 | goto next; | |
86 | } | |
87 | /* Convert cls_rule back to odp_key. */ | |
88 | ofpbuf_uninit(&odp_key); | |
89 | ofpbuf_init(&odp_key, 0); | |
5262eea1 | 90 | odp_flow_key_from_flow(&odp_parms, &odp_key); |
e6cc0bab | 91 | |
6fd6ed71 | 92 | if (odp_key.size > ODPUTIL_FLOW_KEY_BYTES) { |
437d0d22 | 93 | printf ("too long: %"PRIu32" > %d\n", |
6fd6ed71 | 94 | odp_key.size, ODPUTIL_FLOW_KEY_BYTES); |
e6cc0bab AZ |
95 | exit_code = 1; |
96 | } | |
2508ac16 BP |
97 | } |
98 | ||
3bffc610 BP |
99 | /* Convert odp_key to string. */ |
100 | ds_init(&out); | |
e6cc0bab | 101 | if (wc_keys) { |
6fd6ed71 PS |
102 | odp_flow_format(odp_key.data, odp_key.size, |
103 | odp_mask.data, odp_mask.size, NULL, &out, false); | |
e6cc0bab | 104 | } else { |
6fd6ed71 | 105 | odp_flow_key_format(odp_key.data, odp_key.size, &out); |
e6cc0bab | 106 | } |
3bffc610 BP |
107 | puts(ds_cstr(&out)); |
108 | ds_destroy(&out); | |
109 | ||
110 | next: | |
111 | ofpbuf_uninit(&odp_key); | |
9d4e54c6 | 112 | ofpbuf_uninit(&odp_mask); |
3bffc610 BP |
113 | } |
114 | ds_destroy(&in); | |
115 | ||
2508ac16 | 116 | return exit_code; |
3bffc610 | 117 | } |
eb1b39b3 BP |
118 | |
119 | static int | |
120 | parse_actions(void) | |
121 | { | |
122 | struct ds in; | |
123 | ||
124 | ds_init(&in); | |
316bd0f8 | 125 | vlog_set_levels_from_string_assert("odp_util:console:dbg"); |
eb1b39b3 BP |
126 | while (!ds_get_test_line(&in, stdin)) { |
127 | struct ofpbuf odp_actions; | |
128 | struct ds out; | |
129 | int error; | |
130 | ||
131 | /* Convert string to OVS DP actions. */ | |
132 | ofpbuf_init(&odp_actions, 0); | |
133 | error = odp_actions_from_string(ds_cstr(&in), NULL, &odp_actions); | |
134 | if (error) { | |
135 | printf("odp_actions_from_string: error\n"); | |
136 | goto next; | |
137 | } | |
138 | ||
139 | /* Convert odp_actions back to string. */ | |
140 | ds_init(&out); | |
0722f341 | 141 | format_odp_actions(&out, odp_actions.data, odp_actions.size, NULL); |
eb1b39b3 BP |
142 | puts(ds_cstr(&out)); |
143 | ds_destroy(&out); | |
144 | ||
145 | next: | |
146 | ofpbuf_uninit(&odp_actions); | |
147 | } | |
148 | ds_destroy(&in); | |
149 | ||
150 | return 0; | |
151 | } | |
152 | ||
5a0a5702 GS |
153 | static int |
154 | parse_filter(char *filter_parse) | |
155 | { | |
156 | struct ds in; | |
157 | struct flow flow_filter; | |
158 | struct flow_wildcards wc_filter; | |
159 | char *error, *filter = NULL; | |
160 | ||
161 | vlog_set_levels_from_string_assert("odp_util:console:dbg"); | |
162 | if (filter_parse && !strncmp(filter_parse, "filter=", 7)) { | |
13a233f7 | 163 | filter = xstrdup(filter_parse + 7); |
5a0a5702 GS |
164 | memset(&flow_filter, 0, sizeof(flow_filter)); |
165 | memset(&wc_filter, 0, sizeof(wc_filter)); | |
166 | ||
8d8ab6c2 | 167 | error = parse_ofp_exact_flow(&flow_filter, &wc_filter, NULL, filter, |
5a0a5702 GS |
168 | NULL); |
169 | if (error) { | |
170 | ovs_fatal(0, "Failed to parse filter (%s)", error); | |
171 | } | |
172 | } else { | |
173 | ovs_fatal(0, "No filter to parse."); | |
174 | } | |
175 | ||
176 | ds_init(&in); | |
177 | while (!ds_get_test_line(&in, stdin)) { | |
178 | struct ofpbuf odp_key; | |
179 | struct ofpbuf odp_mask; | |
180 | struct ds out; | |
181 | int error; | |
182 | ||
183 | /* Convert string to OVS DP key. */ | |
184 | ofpbuf_init(&odp_key, 0); | |
185 | ofpbuf_init(&odp_mask, 0); | |
186 | error = odp_flow_from_string(ds_cstr(&in), NULL, | |
187 | &odp_key, &odp_mask); | |
188 | if (error) { | |
189 | printf("odp_flow_from_string: error\n"); | |
190 | goto next; | |
191 | } | |
192 | ||
193 | if (filter) { | |
194 | struct flow flow; | |
195 | struct flow_wildcards wc; | |
196 | struct match match, match_filter; | |
197 | struct minimatch minimatch; | |
198 | ||
6fd6ed71 | 199 | odp_flow_key_to_flow(odp_key.data, odp_key.size, &flow); |
8d8ab6c2 | 200 | odp_flow_key_to_mask(odp_mask.data, odp_mask.size, &wc, &flow); |
5a0a5702 GS |
201 | match_init(&match, &flow, &wc); |
202 | ||
203 | match_init(&match_filter, &flow_filter, &wc); | |
204 | match_init(&match_filter, &match_filter.flow, &wc_filter); | |
205 | minimatch_init(&minimatch, &match_filter); | |
206 | ||
207 | if (!minimatch_matches_flow(&minimatch, &match.flow)) { | |
208 | minimatch_destroy(&minimatch); | |
209 | goto next; | |
210 | } | |
211 | minimatch_destroy(&minimatch); | |
212 | } | |
213 | /* Convert odp_key to string. */ | |
214 | ds_init(&out); | |
6fd6ed71 PS |
215 | odp_flow_format(odp_key.data, odp_key.size, |
216 | odp_mask.data, odp_mask.size, NULL, &out, false); | |
5a0a5702 GS |
217 | puts(ds_cstr(&out)); |
218 | ds_destroy(&out); | |
219 | ||
220 | next: | |
221 | ofpbuf_uninit(&odp_key); | |
222 | ofpbuf_uninit(&odp_mask); | |
223 | } | |
224 | ds_destroy(&in); | |
225 | ||
226 | free(filter); | |
227 | return 0; | |
228 | } | |
229 | ||
eadd1644 AZ |
230 | static void |
231 | test_odp_main(int argc, char *argv[]) | |
eb1b39b3 | 232 | { |
eadd1644 AZ |
233 | int exit_code = 0; |
234 | ||
5a0a5702 | 235 | set_program_name(argv[0]); |
eb1b39b3 | 236 | if (argc == 2 &&!strcmp(argv[1], "parse-keys")) { |
eadd1644 | 237 | exit_code =parse_keys(false); |
e6cc0bab | 238 | } else if (argc == 2 &&!strcmp(argv[1], "parse-wc-keys")) { |
eadd1644 | 239 | exit_code =parse_keys(true); |
eb1b39b3 | 240 | } else if (argc == 2 && !strcmp(argv[1], "parse-actions")) { |
eadd1644 | 241 | exit_code = parse_actions(); |
5a0a5702 | 242 | } else if (argc == 3 && !strcmp(argv[1], "parse-filter")) { |
eadd1644 | 243 | exit_code =parse_filter(argv[2]); |
eb1b39b3 | 244 | } else { |
e6cc0bab | 245 | ovs_fatal(0, "usage: %s parse-keys | parse-wc-keys | parse-actions", argv[0]); |
eb1b39b3 | 246 | } |
eadd1644 AZ |
247 | |
248 | exit(exit_code); | |
eb1b39b3 | 249 | } |
eadd1644 AZ |
250 | |
251 | OVSTEST_REGISTER("test-odp", test_odp_main); |