]>
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> |
3bffc610 BP |
21 | #include "dynamic-string.h" |
22 | #include "flow.h" | |
5a0a5702 | 23 | #include "match.h" |
5a0a5702 | 24 | #include "ofp-parse.h" |
3bffc610 | 25 | #include "ofpbuf.h" |
3f636c7e | 26 | #include "ovstest.h" |
eb1b39b3 | 27 | #include "util.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, |
2494ccd7 | 65 | }, |
5262eea1 JG |
66 | }; |
67 | ||
e6cc0bab | 68 | /* Convert odp_key to flow. */ |
6fd6ed71 | 69 | fitness = odp_flow_key_to_flow(odp_key.data, odp_key.size, &flow); |
e6cc0bab AZ |
70 | switch (fitness) { |
71 | case ODP_FIT_PERFECT: | |
72 | break; | |
73 | ||
74 | case ODP_FIT_TOO_LITTLE: | |
75 | printf("ODP_FIT_TOO_LITTLE: "); | |
76 | break; | |
77 | ||
78 | case ODP_FIT_TOO_MUCH: | |
79 | printf("ODP_FIT_TOO_MUCH: "); | |
80 | break; | |
81 | ||
82 | case ODP_FIT_ERROR: | |
83 | printf("odp_flow_key_to_flow: error\n"); | |
84 | goto next; | |
85 | } | |
86 | /* Convert cls_rule back to odp_key. */ | |
87 | ofpbuf_uninit(&odp_key); | |
88 | ofpbuf_init(&odp_key, 0); | |
5262eea1 JG |
89 | odp_parms.odp_in_port = flow.in_port.odp_port; |
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); | |
112 | } | |
113 | ds_destroy(&in); | |
114 | ||
2508ac16 | 115 | return exit_code; |
3bffc610 | 116 | } |
eb1b39b3 BP |
117 | |
118 | static int | |
119 | parse_actions(void) | |
120 | { | |
121 | struct ds in; | |
122 | ||
123 | ds_init(&in); | |
316bd0f8 | 124 | vlog_set_levels_from_string_assert("odp_util:console:dbg"); |
eb1b39b3 BP |
125 | while (!ds_get_test_line(&in, stdin)) { |
126 | struct ofpbuf odp_actions; | |
127 | struct ds out; | |
128 | int error; | |
129 | ||
130 | /* Convert string to OVS DP actions. */ | |
131 | ofpbuf_init(&odp_actions, 0); | |
132 | error = odp_actions_from_string(ds_cstr(&in), NULL, &odp_actions); | |
133 | if (error) { | |
134 | printf("odp_actions_from_string: error\n"); | |
135 | goto next; | |
136 | } | |
137 | ||
138 | /* Convert odp_actions back to string. */ | |
139 | ds_init(&out); | |
6fd6ed71 | 140 | format_odp_actions(&out, odp_actions.data, odp_actions.size); |
eb1b39b3 BP |
141 | puts(ds_cstr(&out)); |
142 | ds_destroy(&out); | |
143 | ||
144 | next: | |
145 | ofpbuf_uninit(&odp_actions); | |
146 | } | |
147 | ds_destroy(&in); | |
148 | ||
149 | return 0; | |
150 | } | |
151 | ||
5a0a5702 GS |
152 | static int |
153 | parse_filter(char *filter_parse) | |
154 | { | |
155 | struct ds in; | |
156 | struct flow flow_filter; | |
157 | struct flow_wildcards wc_filter; | |
158 | char *error, *filter = NULL; | |
159 | ||
160 | vlog_set_levels_from_string_assert("odp_util:console:dbg"); | |
161 | if (filter_parse && !strncmp(filter_parse, "filter=", 7)) { | |
13a233f7 | 162 | filter = xstrdup(filter_parse + 7); |
5a0a5702 GS |
163 | memset(&flow_filter, 0, sizeof(flow_filter)); |
164 | memset(&wc_filter, 0, sizeof(wc_filter)); | |
165 | ||
166 | error = parse_ofp_exact_flow(&flow_filter, &wc_filter.masks, filter, | |
167 | NULL); | |
168 | if (error) { | |
169 | ovs_fatal(0, "Failed to parse filter (%s)", error); | |
170 | } | |
171 | } else { | |
172 | ovs_fatal(0, "No filter to parse."); | |
173 | } | |
174 | ||
175 | ds_init(&in); | |
176 | while (!ds_get_test_line(&in, stdin)) { | |
177 | struct ofpbuf odp_key; | |
178 | struct ofpbuf odp_mask; | |
179 | struct ds out; | |
180 | int error; | |
181 | ||
182 | /* Convert string to OVS DP key. */ | |
183 | ofpbuf_init(&odp_key, 0); | |
184 | ofpbuf_init(&odp_mask, 0); | |
185 | error = odp_flow_from_string(ds_cstr(&in), NULL, | |
186 | &odp_key, &odp_mask); | |
187 | if (error) { | |
188 | printf("odp_flow_from_string: error\n"); | |
189 | goto next; | |
190 | } | |
191 | ||
192 | if (filter) { | |
193 | struct flow flow; | |
194 | struct flow_wildcards wc; | |
195 | struct match match, match_filter; | |
196 | struct minimatch minimatch; | |
197 | ||
6fd6ed71 | 198 | odp_flow_key_to_flow(odp_key.data, odp_key.size, &flow); |
ec1f6f32 JG |
199 | odp_flow_key_to_mask(odp_mask.data, odp_mask.size, odp_key.data, |
200 | odp_key.size, &wc.masks, &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); |