]> git.proxmox.com Git - mirror_ovs.git/blob - lib/ofp-parse.c
openflow: Table maintenance commands for Geneve options.
[mirror_ovs.git] / lib / ofp-parse.c
1 /*
2 * Copyright (c) 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc.
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>
18
19 #include "ofp-parse.h"
20
21 #include <ctype.h>
22 #include <errno.h>
23 #include <stdlib.h>
24
25 #include "byte-order.h"
26 #include "dynamic-string.h"
27 #include "learn.h"
28 #include "meta-flow.h"
29 #include "multipath.h"
30 #include "netdev.h"
31 #include "nx-match.h"
32 #include "ofp-actions.h"
33 #include "ofp-util.h"
34 #include "ofpbuf.h"
35 #include "openflow/openflow.h"
36 #include "ovs-thread.h"
37 #include "packets.h"
38 #include "simap.h"
39 #include "socket-util.h"
40 #include "openvswitch/vconn.h"
41
42 /* Parses 'str' as an 8-bit unsigned integer into '*valuep'.
43 *
44 * 'name' describes the value parsed in an error message, if any.
45 *
46 * Returns NULL if successful, otherwise a malloc()'d string describing the
47 * error. The caller is responsible for freeing the returned string. */
48 char * OVS_WARN_UNUSED_RESULT
49 str_to_u8(const char *str, const char *name, uint8_t *valuep)
50 {
51 int value;
52
53 if (!str_to_int(str, 0, &value) || value < 0 || value > 255) {
54 return xasprintf("invalid %s \"%s\"", name, str);
55 }
56 *valuep = value;
57 return NULL;
58 }
59
60 /* Parses 'str' as a 16-bit unsigned integer into '*valuep'.
61 *
62 * 'name' describes the value parsed in an error message, if any.
63 *
64 * Returns NULL if successful, otherwise a malloc()'d string describing the
65 * error. The caller is responsible for freeing the returned string. */
66 char * OVS_WARN_UNUSED_RESULT
67 str_to_u16(const char *str, const char *name, uint16_t *valuep)
68 {
69 int value;
70
71 if (!str_to_int(str, 0, &value) || value < 0 || value > 65535) {
72 return xasprintf("invalid %s \"%s\"", name, str);
73 }
74 *valuep = value;
75 return NULL;
76 }
77
78 /* Parses 'str' as a 32-bit unsigned integer into '*valuep'.
79 *
80 * Returns NULL if successful, otherwise a malloc()'d string describing the
81 * error. The caller is responsible for freeing the returned string. */
82 char * OVS_WARN_UNUSED_RESULT
83 str_to_u32(const char *str, uint32_t *valuep)
84 {
85 char *tail;
86 uint32_t value;
87
88 if (!str[0]) {
89 return xstrdup("missing required numeric argument");
90 }
91
92 errno = 0;
93 value = strtoul(str, &tail, 0);
94 if (errno == EINVAL || errno == ERANGE || *tail) {
95 return xasprintf("invalid numeric format %s", str);
96 }
97 *valuep = value;
98 return NULL;
99 }
100
101 /* Parses 'str' as an 64-bit unsigned integer into '*valuep'.
102 *
103 * Returns NULL if successful, otherwise a malloc()'d string describing the
104 * error. The caller is responsible for freeing the returned string. */
105 char * OVS_WARN_UNUSED_RESULT
106 str_to_u64(const char *str, uint64_t *valuep)
107 {
108 char *tail;
109 uint64_t value;
110
111 if (!str[0]) {
112 return xstrdup("missing required numeric argument");
113 }
114
115 errno = 0;
116 value = strtoull(str, &tail, 0);
117 if (errno == EINVAL || errno == ERANGE || *tail) {
118 return xasprintf("invalid numeric format %s", str);
119 }
120 *valuep = value;
121 return NULL;
122 }
123
124 /* Parses 'str' as an 64-bit unsigned integer in network byte order into
125 * '*valuep'.
126 *
127 * Returns NULL if successful, otherwise a malloc()'d string describing the
128 * error. The caller is responsible for freeing the returned string. */
129 char * OVS_WARN_UNUSED_RESULT
130 str_to_be64(const char *str, ovs_be64 *valuep)
131 {
132 uint64_t value = 0;
133 char *error;
134
135 error = str_to_u64(str, &value);
136 if (!error) {
137 *valuep = htonll(value);
138 }
139 return error;
140 }
141
142 /* Parses 'str' as an Ethernet address into 'mac'.
143 *
144 * Returns NULL if successful, otherwise a malloc()'d string describing the
145 * error. The caller is responsible for freeing the returned string. */
146 char * OVS_WARN_UNUSED_RESULT
147 str_to_mac(const char *str, uint8_t mac[ETH_ADDR_LEN])
148 {
149 if (!ovs_scan(str, ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(mac))) {
150 return xasprintf("invalid mac address %s", str);
151 }
152 return NULL;
153 }
154
155 /* Parses 'str' as an IP address into '*ip'.
156 *
157 * Returns NULL if successful, otherwise a malloc()'d string describing the
158 * error. The caller is responsible for freeing the returned string. */
159 char * OVS_WARN_UNUSED_RESULT
160 str_to_ip(const char *str, ovs_be32 *ip)
161 {
162 struct in_addr in_addr;
163
164 if (lookup_ip(str, &in_addr)) {
165 return xasprintf("%s: could not convert to IP address", str);
166 }
167 *ip = in_addr.s_addr;
168 return NULL;
169 }
170
171 struct protocol {
172 const char *name;
173 uint16_t dl_type;
174 uint8_t nw_proto;
175 };
176
177 static bool
178 parse_protocol(const char *name, const struct protocol **p_out)
179 {
180 static const struct protocol protocols[] = {
181 { "ip", ETH_TYPE_IP, 0 },
182 { "arp", ETH_TYPE_ARP, 0 },
183 { "icmp", ETH_TYPE_IP, IPPROTO_ICMP },
184 { "tcp", ETH_TYPE_IP, IPPROTO_TCP },
185 { "udp", ETH_TYPE_IP, IPPROTO_UDP },
186 { "sctp", ETH_TYPE_IP, IPPROTO_SCTP },
187 { "ipv6", ETH_TYPE_IPV6, 0 },
188 { "ip6", ETH_TYPE_IPV6, 0 },
189 { "icmp6", ETH_TYPE_IPV6, IPPROTO_ICMPV6 },
190 { "tcp6", ETH_TYPE_IPV6, IPPROTO_TCP },
191 { "udp6", ETH_TYPE_IPV6, IPPROTO_UDP },
192 { "sctp6", ETH_TYPE_IPV6, IPPROTO_SCTP },
193 { "rarp", ETH_TYPE_RARP, 0},
194 { "mpls", ETH_TYPE_MPLS, 0 },
195 { "mplsm", ETH_TYPE_MPLS_MCAST, 0 },
196 };
197 const struct protocol *p;
198
199 for (p = protocols; p < &protocols[ARRAY_SIZE(protocols)]; p++) {
200 if (!strcmp(p->name, name)) {
201 *p_out = p;
202 return true;
203 }
204 }
205 *p_out = NULL;
206 return false;
207 }
208
209 /* Parses 's' as the (possibly masked) value of field 'mf', and updates
210 * 'match' appropriately. Restricts the set of usable protocols to ones
211 * supporting the parsed field.
212 *
213 * Returns NULL if successful, otherwise a malloc()'d string describing the
214 * error. The caller is responsible for freeing the returned string. */
215 static char * OVS_WARN_UNUSED_RESULT
216 parse_field(const struct mf_field *mf, const char *s, struct match *match,
217 enum ofputil_protocol *usable_protocols)
218 {
219 union mf_value value, mask;
220 char *error;
221
222 error = mf_parse(mf, s, &value, &mask);
223 if (!error) {
224 *usable_protocols &= mf_set(mf, &value, &mask, match);
225 }
226 return error;
227 }
228
229 static char *
230 extract_actions(char *s)
231 {
232 s = strstr(s, "action");
233 if (s) {
234 *s = '\0';
235 s = strchr(s + 1, '=');
236 return s ? s + 1 : NULL;
237 } else {
238 return NULL;
239 }
240 }
241
242
243 static char * OVS_WARN_UNUSED_RESULT
244 parse_ofp_str__(struct ofputil_flow_mod *fm, int command, char *string,
245 enum ofputil_protocol *usable_protocols)
246 {
247 enum {
248 F_OUT_PORT = 1 << 0,
249 F_ACTIONS = 1 << 1,
250 F_IMPORTANCE = 1 << 2,
251 F_TIMEOUT = 1 << 3,
252 F_PRIORITY = 1 << 4,
253 F_FLAGS = 1 << 5,
254 } fields;
255 char *save_ptr = NULL;
256 char *act_str = NULL;
257 char *name;
258
259 *usable_protocols = OFPUTIL_P_ANY;
260
261 if (command == -2) {
262 size_t len;
263
264 string += strspn(string, " \t\r\n"); /* Skip white space. */
265 len = strcspn(string, ", \t\r\n"); /* Get length of the first token. */
266
267 if (!strncmp(string, "add", len)) {
268 command = OFPFC_ADD;
269 } else if (!strncmp(string, "delete", len)) {
270 command = OFPFC_DELETE;
271 } else if (!strncmp(string, "delete_strict", len)) {
272 command = OFPFC_DELETE_STRICT;
273 } else if (!strncmp(string, "modify", len)) {
274 command = OFPFC_MODIFY;
275 } else if (!strncmp(string, "modify_strict", len)) {
276 command = OFPFC_MODIFY_STRICT;
277 } else {
278 len = 0;
279 command = OFPFC_ADD;
280 }
281 string += len;
282 }
283
284 switch (command) {
285 case -1:
286 fields = F_OUT_PORT;
287 break;
288
289 case OFPFC_ADD:
290 fields = F_ACTIONS | F_TIMEOUT | F_PRIORITY | F_FLAGS | F_IMPORTANCE;
291 break;
292
293 case OFPFC_DELETE:
294 fields = F_OUT_PORT;
295 break;
296
297 case OFPFC_DELETE_STRICT:
298 fields = F_OUT_PORT | F_PRIORITY;
299 break;
300
301 case OFPFC_MODIFY:
302 fields = F_ACTIONS | F_TIMEOUT | F_PRIORITY | F_FLAGS;
303 break;
304
305 case OFPFC_MODIFY_STRICT:
306 fields = F_ACTIONS | F_TIMEOUT | F_PRIORITY | F_FLAGS;
307 break;
308
309 default:
310 OVS_NOT_REACHED();
311 }
312
313 match_init_catchall(&fm->match);
314 fm->priority = OFP_DEFAULT_PRIORITY;
315 fm->cookie = htonll(0);
316 fm->cookie_mask = htonll(0);
317 if (command == OFPFC_MODIFY || command == OFPFC_MODIFY_STRICT) {
318 /* For modify, by default, don't update the cookie. */
319 fm->new_cookie = OVS_BE64_MAX;
320 } else{
321 fm->new_cookie = htonll(0);
322 }
323 fm->modify_cookie = false;
324 fm->table_id = 0xff;
325 fm->command = command;
326 fm->idle_timeout = OFP_FLOW_PERMANENT;
327 fm->hard_timeout = OFP_FLOW_PERMANENT;
328 fm->buffer_id = UINT32_MAX;
329 fm->out_port = OFPP_ANY;
330 fm->flags = 0;
331 fm->importance = 0;
332 fm->out_group = OFPG11_ANY;
333 fm->delete_reason = OFPRR_DELETE;
334 if (fields & F_ACTIONS) {
335 act_str = extract_actions(string);
336 if (!act_str) {
337 return xstrdup("must specify an action");
338 }
339 }
340 for (name = strtok_r(string, "=, \t\r\n", &save_ptr); name;
341 name = strtok_r(NULL, "=, \t\r\n", &save_ptr)) {
342 const struct protocol *p;
343 char *error = NULL;
344
345 if (parse_protocol(name, &p)) {
346 match_set_dl_type(&fm->match, htons(p->dl_type));
347 if (p->nw_proto) {
348 match_set_nw_proto(&fm->match, p->nw_proto);
349 }
350 } else if (fields & F_FLAGS && !strcmp(name, "send_flow_rem")) {
351 fm->flags |= OFPUTIL_FF_SEND_FLOW_REM;
352 } else if (fields & F_FLAGS && !strcmp(name, "check_overlap")) {
353 fm->flags |= OFPUTIL_FF_CHECK_OVERLAP;
354 } else if (fields & F_FLAGS && !strcmp(name, "reset_counts")) {
355 fm->flags |= OFPUTIL_FF_RESET_COUNTS;
356 *usable_protocols &= OFPUTIL_P_OF12_UP;
357 } else if (fields & F_FLAGS && !strcmp(name, "no_packet_counts")) {
358 fm->flags |= OFPUTIL_FF_NO_PKT_COUNTS;
359 *usable_protocols &= OFPUTIL_P_OF13_UP;
360 } else if (fields & F_FLAGS && !strcmp(name, "no_byte_counts")) {
361 fm->flags |= OFPUTIL_FF_NO_BYT_COUNTS;
362 *usable_protocols &= OFPUTIL_P_OF13_UP;
363 } else if (!strcmp(name, "no_readonly_table")
364 || !strcmp(name, "allow_hidden_fields")) {
365 /* ignore these fields. */
366 } else {
367 char *value;
368
369 value = strtok_r(NULL, ", \t\r\n", &save_ptr);
370 if (!value) {
371 return xasprintf("field %s missing value", name);
372 }
373
374 if (!strcmp(name, "table")) {
375 error = str_to_u8(value, "table", &fm->table_id);
376 if (fm->table_id != 0xff) {
377 *usable_protocols &= OFPUTIL_P_TID;
378 }
379 } else if (fields & F_OUT_PORT && !strcmp(name, "out_port")) {
380 if (!ofputil_port_from_string(value, &fm->out_port)) {
381 error = xasprintf("%s is not a valid OpenFlow port",
382 value);
383 }
384 } else if (fields & F_PRIORITY && !strcmp(name, "priority")) {
385 uint16_t priority = 0;
386
387 error = str_to_u16(value, name, &priority);
388 fm->priority = priority;
389 } else if (fields & F_TIMEOUT && !strcmp(name, "idle_timeout")) {
390 error = str_to_u16(value, name, &fm->idle_timeout);
391 } else if (fields & F_TIMEOUT && !strcmp(name, "hard_timeout")) {
392 error = str_to_u16(value, name, &fm->hard_timeout);
393 } else if (fields & F_IMPORTANCE && !strcmp(name, "importance")) {
394 error = str_to_u16(value, name, &fm->importance);
395 } else if (!strcmp(name, "cookie")) {
396 char *mask = strchr(value, '/');
397
398 if (mask) {
399 /* A mask means we're searching for a cookie. */
400 if (command == OFPFC_ADD) {
401 return xstrdup("flow additions cannot use "
402 "a cookie mask");
403 }
404 *mask = '\0';
405 error = str_to_be64(value, &fm->cookie);
406 if (error) {
407 return error;
408 }
409 error = str_to_be64(mask + 1, &fm->cookie_mask);
410
411 /* Matching of the cookie is only supported through NXM or
412 * OF1.1+. */
413 if (fm->cookie_mask != htonll(0)) {
414 *usable_protocols &= OFPUTIL_P_NXM_OF11_UP;
415 }
416 } else {
417 /* No mask means that the cookie is being set. */
418 if (command != OFPFC_ADD && command != OFPFC_MODIFY
419 && command != OFPFC_MODIFY_STRICT) {
420 return xstrdup("cannot set cookie");
421 }
422 error = str_to_be64(value, &fm->new_cookie);
423 fm->modify_cookie = true;
424 }
425 } else if (mf_from_name(name)) {
426 error = parse_field(mf_from_name(name), value, &fm->match,
427 usable_protocols);
428 } else if (!strcmp(name, "duration")
429 || !strcmp(name, "n_packets")
430 || !strcmp(name, "n_bytes")
431 || !strcmp(name, "idle_age")
432 || !strcmp(name, "hard_age")) {
433 /* Ignore these, so that users can feed the output of
434 * "ovs-ofctl dump-flows" back into commands that parse
435 * flows. */
436 } else {
437 error = xasprintf("unknown keyword %s", name);
438 }
439
440 if (error) {
441 return error;
442 }
443 }
444 }
445 /* Check for usable protocol interdependencies between match fields. */
446 if (fm->match.flow.dl_type == htons(ETH_TYPE_IPV6)) {
447 const struct flow_wildcards *wc = &fm->match.wc;
448 /* Only NXM and OXM support matching L3 and L4 fields within IPv6.
449 *
450 * (IPv6 specific fields as well as arp_sha, arp_tha, nw_frag, and
451 * nw_ttl are covered elsewhere so they don't need to be included in
452 * this test too.)
453 */
454 if (wc->masks.nw_proto || wc->masks.nw_tos
455 || wc->masks.tp_src || wc->masks.tp_dst) {
456 *usable_protocols &= OFPUTIL_P_NXM_OXM_ANY;
457 }
458 }
459 if (!fm->cookie_mask && fm->new_cookie == OVS_BE64_MAX
460 && (command == OFPFC_MODIFY || command == OFPFC_MODIFY_STRICT)) {
461 /* On modifies without a mask, we are supposed to add a flow if
462 * one does not exist. If a cookie wasn't been specified, use a
463 * default of zero. */
464 fm->new_cookie = htonll(0);
465 }
466 if (fields & F_ACTIONS) {
467 enum ofputil_protocol action_usable_protocols;
468 struct ofpbuf ofpacts;
469 char *error;
470
471 ofpbuf_init(&ofpacts, 32);
472 error = ofpacts_parse_instructions(act_str, &ofpacts,
473 &action_usable_protocols);
474 *usable_protocols &= action_usable_protocols;
475 if (!error) {
476 enum ofperr err;
477
478 err = ofpacts_check(ofpacts.data, ofpacts.size, &fm->match.flow,
479 OFPP_MAX, fm->table_id, 255, usable_protocols);
480 if (!err && !usable_protocols) {
481 err = OFPERR_OFPBAC_MATCH_INCONSISTENT;
482 }
483 if (err) {
484 error = xasprintf("actions are invalid with specified match "
485 "(%s)", ofperr_to_string(err));
486 }
487
488 }
489 if (error) {
490 ofpbuf_uninit(&ofpacts);
491 return error;
492 }
493
494 fm->ofpacts_len = ofpacts.size;
495 fm->ofpacts = ofpbuf_steal_data(&ofpacts);
496 } else {
497 fm->ofpacts_len = 0;
498 fm->ofpacts = NULL;
499 }
500
501 return NULL;
502 }
503
504 /* Convert 'str_' (as described in the Flow Syntax section of the ovs-ofctl man
505 * page) into 'fm' for sending the specified flow_mod 'command' to a switch.
506 * Returns the set of usable protocols in '*usable_protocols'.
507 *
508 * To parse syntax for an OFPT_FLOW_MOD (or NXT_FLOW_MOD), use an OFPFC_*
509 * constant for 'command'. To parse syntax for an OFPST_FLOW or
510 * OFPST_AGGREGATE (or NXST_FLOW or NXST_AGGREGATE), use -1 for 'command'.
511 *
512 * If 'command' is given as -2, 'str_' may begin with a command name ("add",
513 * "modify", "delete", "modify_strict", or "delete_strict"). A missing command
514 * name is treated as "add".
515 *
516 * Returns NULL if successful, otherwise a malloc()'d string describing the
517 * error. The caller is responsible for freeing the returned string. */
518 char * OVS_WARN_UNUSED_RESULT
519 parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_,
520 enum ofputil_protocol *usable_protocols)
521 {
522 char *string = xstrdup(str_);
523 char *error;
524
525 error = parse_ofp_str__(fm, command, string, usable_protocols);
526 if (error) {
527 fm->ofpacts = NULL;
528 fm->ofpacts_len = 0;
529 }
530
531 free(string);
532 return error;
533 }
534
535 static char * OVS_WARN_UNUSED_RESULT
536 parse_ofp_meter_mod_str__(struct ofputil_meter_mod *mm, char *string,
537 struct ofpbuf *bands, int command,
538 enum ofputil_protocol *usable_protocols)
539 {
540 enum {
541 F_METER = 1 << 0,
542 F_FLAGS = 1 << 1,
543 F_BANDS = 1 << 2,
544 } fields;
545 char *save_ptr = NULL;
546 char *band_str = NULL;
547 char *name;
548
549 /* Meters require at least OF 1.3. */
550 *usable_protocols = OFPUTIL_P_OF13_UP;
551
552 switch (command) {
553 case -1:
554 fields = F_METER;
555 break;
556
557 case OFPMC13_ADD:
558 fields = F_METER | F_FLAGS | F_BANDS;
559 break;
560
561 case OFPMC13_DELETE:
562 fields = F_METER;
563 break;
564
565 case OFPMC13_MODIFY:
566 fields = F_METER | F_FLAGS | F_BANDS;
567 break;
568
569 default:
570 OVS_NOT_REACHED();
571 }
572
573 mm->command = command;
574 mm->meter.meter_id = 0;
575 mm->meter.flags = 0;
576 if (fields & F_BANDS) {
577 band_str = strstr(string, "band");
578 if (!band_str) {
579 return xstrdup("must specify bands");
580 }
581 *band_str = '\0';
582
583 band_str = strchr(band_str + 1, '=');
584 if (!band_str) {
585 return xstrdup("must specify bands");
586 }
587
588 band_str++;
589 }
590 for (name = strtok_r(string, "=, \t\r\n", &save_ptr); name;
591 name = strtok_r(NULL, "=, \t\r\n", &save_ptr)) {
592
593 if (fields & F_FLAGS && !strcmp(name, "kbps")) {
594 mm->meter.flags |= OFPMF13_KBPS;
595 } else if (fields & F_FLAGS && !strcmp(name, "pktps")) {
596 mm->meter.flags |= OFPMF13_PKTPS;
597 } else if (fields & F_FLAGS && !strcmp(name, "burst")) {
598 mm->meter.flags |= OFPMF13_BURST;
599 } else if (fields & F_FLAGS && !strcmp(name, "stats")) {
600 mm->meter.flags |= OFPMF13_STATS;
601 } else {
602 char *value;
603
604 value = strtok_r(NULL, ", \t\r\n", &save_ptr);
605 if (!value) {
606 return xasprintf("field %s missing value", name);
607 }
608
609 if (!strcmp(name, "meter")) {
610 if (!strcmp(value, "all")) {
611 mm->meter.meter_id = OFPM13_ALL;
612 } else if (!strcmp(value, "controller")) {
613 mm->meter.meter_id = OFPM13_CONTROLLER;
614 } else if (!strcmp(value, "slowpath")) {
615 mm->meter.meter_id = OFPM13_SLOWPATH;
616 } else {
617 char *error = str_to_u32(value, &mm->meter.meter_id);
618 if (error) {
619 return error;
620 }
621 if (mm->meter.meter_id > OFPM13_MAX
622 || !mm->meter.meter_id) {
623 return xasprintf("invalid value for %s", name);
624 }
625 }
626 } else {
627 return xasprintf("unknown keyword %s", name);
628 }
629 }
630 }
631 if (fields & F_METER && !mm->meter.meter_id) {
632 return xstrdup("must specify 'meter'");
633 }
634 if (fields & F_FLAGS && !mm->meter.flags) {
635 return xstrdup("meter must specify either 'kbps' or 'pktps'");
636 }
637
638 if (fields & F_BANDS) {
639 uint16_t n_bands = 0;
640 struct ofputil_meter_band *band = NULL;
641 int i;
642
643 for (name = strtok_r(band_str, "=, \t\r\n", &save_ptr); name;
644 name = strtok_r(NULL, "=, \t\r\n", &save_ptr)) {
645
646 char *value;
647
648 value = strtok_r(NULL, ", \t\r\n", &save_ptr);
649 if (!value) {
650 return xasprintf("field %s missing value", name);
651 }
652
653 if (!strcmp(name, "type")) {
654 /* Start a new band */
655 band = ofpbuf_put_zeros(bands, sizeof *band);
656 n_bands++;
657
658 if (!strcmp(value, "drop")) {
659 band->type = OFPMBT13_DROP;
660 } else if (!strcmp(value, "dscp_remark")) {
661 band->type = OFPMBT13_DSCP_REMARK;
662 } else {
663 return xasprintf("field %s unknown value %s", name, value);
664 }
665 } else if (!band || !band->type) {
666 return xstrdup("band must start with the 'type' keyword");
667 } else if (!strcmp(name, "rate")) {
668 char *error = str_to_u32(value, &band->rate);
669 if (error) {
670 return error;
671 }
672 } else if (!strcmp(name, "burst_size")) {
673 char *error = str_to_u32(value, &band->burst_size);
674 if (error) {
675 return error;
676 }
677 } else if (!strcmp(name, "prec_level")) {
678 char *error = str_to_u8(value, name, &band->prec_level);
679 if (error) {
680 return error;
681 }
682 } else {
683 return xasprintf("unknown keyword %s", name);
684 }
685 }
686 /* validate bands */
687 if (!n_bands) {
688 return xstrdup("meter must have bands");
689 }
690
691 mm->meter.n_bands = n_bands;
692 mm->meter.bands = ofpbuf_steal_data(bands);
693
694 for (i = 0; i < n_bands; ++i) {
695 band = &mm->meter.bands[i];
696
697 if (!band->type) {
698 return xstrdup("band must have 'type'");
699 }
700 if (band->type == OFPMBT13_DSCP_REMARK) {
701 if (!band->prec_level) {
702 return xstrdup("'dscp_remark' band must have"
703 " 'prec_level'");
704 }
705 } else {
706 if (band->prec_level) {
707 return xstrdup("Only 'dscp_remark' band may have"
708 " 'prec_level'");
709 }
710 }
711 if (!band->rate) {
712 return xstrdup("band must have 'rate'");
713 }
714 if (mm->meter.flags & OFPMF13_BURST) {
715 if (!band->burst_size) {
716 return xstrdup("band must have 'burst_size' "
717 "when 'burst' flag is set");
718 }
719 } else {
720 if (band->burst_size) {
721 return xstrdup("band may have 'burst_size' only "
722 "when 'burst' flag is set");
723 }
724 }
725 }
726 } else {
727 mm->meter.n_bands = 0;
728 mm->meter.bands = NULL;
729 }
730
731 return NULL;
732 }
733
734 /* Convert 'str_' (as described in the Flow Syntax section of the ovs-ofctl man
735 * page) into 'mm' for sending the specified meter_mod 'command' to a switch.
736 *
737 * Returns NULL if successful, otherwise a malloc()'d string describing the
738 * error. The caller is responsible for freeing the returned string. */
739 char * OVS_WARN_UNUSED_RESULT
740 parse_ofp_meter_mod_str(struct ofputil_meter_mod *mm, const char *str_,
741 int command, enum ofputil_protocol *usable_protocols)
742 {
743 struct ofpbuf bands;
744 char *string;
745 char *error;
746
747 ofpbuf_init(&bands, 64);
748 string = xstrdup(str_);
749
750 error = parse_ofp_meter_mod_str__(mm, string, &bands, command,
751 usable_protocols);
752
753 free(string);
754 ofpbuf_uninit(&bands);
755
756 return error;
757 }
758
759 static char * OVS_WARN_UNUSED_RESULT
760 parse_flow_monitor_request__(struct ofputil_flow_monitor_request *fmr,
761 const char *str_, char *string,
762 enum ofputil_protocol *usable_protocols)
763 {
764 static atomic_count id = ATOMIC_COUNT_INIT(0);
765 char *save_ptr = NULL;
766 char *name;
767
768 fmr->id = atomic_count_inc(&id);
769
770 fmr->flags = (NXFMF_INITIAL | NXFMF_ADD | NXFMF_DELETE | NXFMF_MODIFY
771 | NXFMF_OWN | NXFMF_ACTIONS);
772 fmr->out_port = OFPP_NONE;
773 fmr->table_id = 0xff;
774 match_init_catchall(&fmr->match);
775
776 for (name = strtok_r(string, "=, \t\r\n", &save_ptr); name;
777 name = strtok_r(NULL, "=, \t\r\n", &save_ptr)) {
778 const struct protocol *p;
779
780 if (!strcmp(name, "!initial")) {
781 fmr->flags &= ~NXFMF_INITIAL;
782 } else if (!strcmp(name, "!add")) {
783 fmr->flags &= ~NXFMF_ADD;
784 } else if (!strcmp(name, "!delete")) {
785 fmr->flags &= ~NXFMF_DELETE;
786 } else if (!strcmp(name, "!modify")) {
787 fmr->flags &= ~NXFMF_MODIFY;
788 } else if (!strcmp(name, "!actions")) {
789 fmr->flags &= ~NXFMF_ACTIONS;
790 } else if (!strcmp(name, "!own")) {
791 fmr->flags &= ~NXFMF_OWN;
792 } else if (parse_protocol(name, &p)) {
793 match_set_dl_type(&fmr->match, htons(p->dl_type));
794 if (p->nw_proto) {
795 match_set_nw_proto(&fmr->match, p->nw_proto);
796 }
797 } else {
798 char *value;
799
800 value = strtok_r(NULL, ", \t\r\n", &save_ptr);
801 if (!value) {
802 return xasprintf("%s: field %s missing value", str_, name);
803 }
804
805 if (!strcmp(name, "table")) {
806 char *error = str_to_u8(value, "table", &fmr->table_id);
807 if (error) {
808 return error;
809 }
810 } else if (!strcmp(name, "out_port")) {
811 fmr->out_port = u16_to_ofp(atoi(value));
812 } else if (mf_from_name(name)) {
813 char *error;
814
815 error = parse_field(mf_from_name(name), value, &fmr->match,
816 usable_protocols);
817 if (error) {
818 return error;
819 }
820 } else {
821 return xasprintf("%s: unknown keyword %s", str_, name);
822 }
823 }
824 }
825 return NULL;
826 }
827
828 /* Convert 'str_' (as described in the documentation for the "monitor" command
829 * in the ovs-ofctl man page) into 'fmr'.
830 *
831 * Returns NULL if successful, otherwise a malloc()'d string describing the
832 * error. The caller is responsible for freeing the returned string. */
833 char * OVS_WARN_UNUSED_RESULT
834 parse_flow_monitor_request(struct ofputil_flow_monitor_request *fmr,
835 const char *str_,
836 enum ofputil_protocol *usable_protocols)
837 {
838 char *string = xstrdup(str_);
839 char *error = parse_flow_monitor_request__(fmr, str_, string,
840 usable_protocols);
841 free(string);
842 return error;
843 }
844
845 /* Parses 'string' as an OFPT_FLOW_MOD or NXT_FLOW_MOD with command 'command'
846 * (one of OFPFC_*) into 'fm'.
847 *
848 * If 'command' is given as -2, 'string' may begin with a command name ("add",
849 * "modify", "delete", "modify_strict", or "delete_strict"). A missing command
850 * name is treated as "add".
851 *
852 * Returns NULL if successful, otherwise a malloc()'d string describing the
853 * error. The caller is responsible for freeing the returned string. */
854 char * OVS_WARN_UNUSED_RESULT
855 parse_ofp_flow_mod_str(struct ofputil_flow_mod *fm, const char *string,
856 int command,
857 enum ofputil_protocol *usable_protocols)
858 {
859 char *error = parse_ofp_str(fm, command, string, usable_protocols);
860
861 if (!error) {
862 /* Normalize a copy of the match. This ensures that non-normalized
863 * flows get logged but doesn't affect what gets sent to the switch, so
864 * that the switch can do whatever it likes with the flow. */
865 struct match match_copy = fm->match;
866 ofputil_normalize_match(&match_copy);
867 }
868
869 return error;
870 }
871
872 /* Convert 'table_id' and 'flow_miss_handling' (as described for the
873 * "mod-table" command in the ovs-ofctl man page) into 'tm' for sending the
874 * specified table_mod 'command' to a switch.
875 *
876 * Returns NULL if successful, otherwise a malloc()'d string describing the
877 * error. The caller is responsible for freeing the returned string. */
878 char * OVS_WARN_UNUSED_RESULT
879 parse_ofp_table_mod(struct ofputil_table_mod *tm, const char *table_id,
880 const char *flow_miss_handling,
881 enum ofputil_protocol *usable_protocols)
882 {
883 /* Table mod requires at least OF 1.1. */
884 *usable_protocols = OFPUTIL_P_OF11_UP;
885
886 if (!strcasecmp(table_id, "all")) {
887 tm->table_id = OFPTT_ALL;
888 } else {
889 char *error = str_to_u8(table_id, "table_id", &tm->table_id);
890 if (error) {
891 return error;
892 }
893 }
894
895 if (strcmp(flow_miss_handling, "controller") == 0) {
896 tm->miss_config = OFPUTIL_TABLE_MISS_CONTROLLER;
897 } else if (strcmp(flow_miss_handling, "continue") == 0) {
898 tm->miss_config = OFPUTIL_TABLE_MISS_CONTINUE;
899 } else if (strcmp(flow_miss_handling, "drop") == 0) {
900 tm->miss_config = OFPUTIL_TABLE_MISS_DROP;
901 } else {
902 return xasprintf("invalid flow_miss_handling %s", flow_miss_handling);
903 }
904
905 if (tm->table_id == 0xfe
906 && tm->miss_config == OFPUTIL_TABLE_MISS_CONTINUE) {
907 return xstrdup("last table's flow miss handling can not be continue");
908 }
909
910 return NULL;
911 }
912
913
914 /* Opens file 'file_name' and reads each line as a flow_mod of the specified
915 * type (one of OFPFC_*). Stores each flow_mod in '*fm', an array allocated
916 * on the caller's behalf, and the number of flow_mods in '*n_fms'.
917 *
918 * If 'command' is given as -2, each line may start with a command name
919 * ("add", "modify", "delete", "modify_strict", or "delete_strict"). A missing
920 * command name is treated as "add".
921 *
922 * Returns NULL if successful, otherwise a malloc()'d string describing the
923 * error. The caller is responsible for freeing the returned string. */
924 char * OVS_WARN_UNUSED_RESULT
925 parse_ofp_flow_mod_file(const char *file_name, int command,
926 struct ofputil_flow_mod **fms, size_t *n_fms,
927 enum ofputil_protocol *usable_protocols)
928 {
929 size_t allocated_fms;
930 int line_number;
931 FILE *stream;
932 struct ds s;
933
934 *usable_protocols = OFPUTIL_P_ANY;
935
936 *fms = NULL;
937 *n_fms = 0;
938
939 stream = !strcmp(file_name, "-") ? stdin : fopen(file_name, "r");
940 if (stream == NULL) {
941 return xasprintf("%s: open failed (%s)",
942 file_name, ovs_strerror(errno));
943 }
944
945 allocated_fms = *n_fms;
946 ds_init(&s);
947 line_number = 0;
948 while (!ds_get_preprocessed_line(&s, stream, &line_number)) {
949 char *error;
950 enum ofputil_protocol usable;
951
952 if (*n_fms >= allocated_fms) {
953 *fms = x2nrealloc(*fms, &allocated_fms, sizeof **fms);
954 }
955 error = parse_ofp_flow_mod_str(&(*fms)[*n_fms], ds_cstr(&s), command,
956 &usable);
957 if (error) {
958 size_t i;
959
960 for (i = 0; i < *n_fms; i++) {
961 free(CONST_CAST(struct ofpact *, (*fms)[i].ofpacts));
962 }
963 free(*fms);
964 *fms = NULL;
965 *n_fms = 0;
966
967 ds_destroy(&s);
968 if (stream != stdin) {
969 fclose(stream);
970 }
971
972 return xasprintf("%s:%d: %s", file_name, line_number, error);
973 }
974 *usable_protocols &= usable; /* Each line can narrow the set. */
975 *n_fms += 1;
976 }
977
978 ds_destroy(&s);
979 if (stream != stdin) {
980 fclose(stream);
981 }
982 return NULL;
983 }
984
985 char * OVS_WARN_UNUSED_RESULT
986 parse_ofp_flow_stats_request_str(struct ofputil_flow_stats_request *fsr,
987 bool aggregate, const char *string,
988 enum ofputil_protocol *usable_protocols)
989 {
990 struct ofputil_flow_mod fm;
991 char *error;
992
993 error = parse_ofp_str(&fm, -1, string, usable_protocols);
994 if (error) {
995 return error;
996 }
997
998 /* Special table ID support not required for stats requests. */
999 if (*usable_protocols & OFPUTIL_P_OF10_STD_TID) {
1000 *usable_protocols |= OFPUTIL_P_OF10_STD;
1001 }
1002 if (*usable_protocols & OFPUTIL_P_OF10_NXM_TID) {
1003 *usable_protocols |= OFPUTIL_P_OF10_NXM;
1004 }
1005
1006 fsr->aggregate = aggregate;
1007 fsr->cookie = fm.cookie;
1008 fsr->cookie_mask = fm.cookie_mask;
1009 fsr->match = fm.match;
1010 fsr->out_port = fm.out_port;
1011 fsr->out_group = fm.out_group;
1012 fsr->table_id = fm.table_id;
1013 return NULL;
1014 }
1015
1016 /* Parses a specification of a flow from 's' into 'flow'. 's' must take the
1017 * form FIELD=VALUE[,FIELD=VALUE]... where each FIELD is the name of a
1018 * mf_field. Fields must be specified in a natural order for satisfying
1019 * prerequisites. If 'mask' is specified, fills the mask field for each of the
1020 * field specified in flow. If the map, 'names_portno' is specfied, converts
1021 * the in_port name into port no while setting the 'flow'.
1022 *
1023 * Returns NULL on success, otherwise a malloc()'d string that explains the
1024 * problem. */
1025 char *
1026 parse_ofp_exact_flow(struct flow *flow, struct flow *mask, const char *s,
1027 const struct simap *portno_names)
1028 {
1029 char *pos, *key, *value_s;
1030 char *error = NULL;
1031 char *copy;
1032
1033 memset(flow, 0, sizeof *flow);
1034 if (mask) {
1035 memset(mask, 0, sizeof *mask);
1036 }
1037
1038 pos = copy = xstrdup(s);
1039 while (ofputil_parse_key_value(&pos, &key, &value_s)) {
1040 const struct protocol *p;
1041 if (parse_protocol(key, &p)) {
1042 if (flow->dl_type) {
1043 error = xasprintf("%s: Ethernet type set multiple times", s);
1044 goto exit;
1045 }
1046 flow->dl_type = htons(p->dl_type);
1047 if (mask) {
1048 mask->dl_type = OVS_BE16_MAX;
1049 }
1050
1051 if (p->nw_proto) {
1052 if (flow->nw_proto) {
1053 error = xasprintf("%s: network protocol set "
1054 "multiple times", s);
1055 goto exit;
1056 }
1057 flow->nw_proto = p->nw_proto;
1058 if (mask) {
1059 mask->nw_proto = UINT8_MAX;
1060 }
1061 }
1062 } else {
1063 const struct mf_field *mf;
1064 union mf_value value;
1065 char *field_error;
1066
1067 mf = mf_from_name(key);
1068 if (!mf) {
1069 error = xasprintf("%s: unknown field %s", s, key);
1070 goto exit;
1071 }
1072
1073 if (!mf_are_prereqs_ok(mf, flow)) {
1074 error = xasprintf("%s: prerequisites not met for setting %s",
1075 s, key);
1076 goto exit;
1077 }
1078
1079 if (!mf_is_zero(mf, flow)) {
1080 error = xasprintf("%s: field %s set multiple times", s, key);
1081 goto exit;
1082 }
1083
1084 if (!strcmp(key, "in_port")
1085 && portno_names
1086 && simap_contains(portno_names, value_s)) {
1087 flow->in_port.ofp_port = u16_to_ofp(
1088 simap_get(portno_names, value_s));
1089 if (mask) {
1090 mask->in_port.ofp_port = u16_to_ofp(ntohs(OVS_BE16_MAX));
1091 }
1092 } else {
1093 field_error = mf_parse_value(mf, value_s, &value);
1094 if (field_error) {
1095 error = xasprintf("%s: bad value for %s (%s)",
1096 s, key, field_error);
1097 free(field_error);
1098 goto exit;
1099 }
1100
1101 mf_set_flow_value(mf, &value, flow);
1102 if (mask) {
1103 mf_mask_field(mf, mask);
1104 }
1105 }
1106 }
1107 }
1108
1109 if (!flow->in_port.ofp_port) {
1110 flow->in_port.ofp_port = OFPP_NONE;
1111 }
1112
1113 exit:
1114 free(copy);
1115
1116 if (error) {
1117 memset(flow, 0, sizeof *flow);
1118 if (mask) {
1119 memset(mask, 0, sizeof *mask);
1120 }
1121 }
1122 return error;
1123 }
1124
1125 static char * OVS_WARN_UNUSED_RESULT
1126 parse_bucket_str(struct ofputil_bucket *bucket, char *str_,
1127 enum ofputil_protocol *usable_protocols)
1128 {
1129 char *pos, *key, *value;
1130 struct ofpbuf ofpacts;
1131 struct ds actions;
1132 char *error;
1133
1134 bucket->weight = 1;
1135 bucket->bucket_id = OFPG15_BUCKET_ALL;
1136 bucket->watch_port = OFPP_ANY;
1137 bucket->watch_group = OFPG11_ANY;
1138
1139 ds_init(&actions);
1140
1141 pos = str_;
1142 error = NULL;
1143 while (ofputil_parse_key_value(&pos, &key, &value)) {
1144 if (!strcasecmp(key, "weight")) {
1145 error = str_to_u16(value, "weight", &bucket->weight);
1146 } else if (!strcasecmp(key, "watch_port")) {
1147 if (!ofputil_port_from_string(value, &bucket->watch_port)
1148 || (ofp_to_u16(bucket->watch_port) >= ofp_to_u16(OFPP_MAX)
1149 && bucket->watch_port != OFPP_ANY)) {
1150 error = xasprintf("%s: invalid watch_port", value);
1151 }
1152 } else if (!strcasecmp(key, "watch_group")) {
1153 error = str_to_u32(value, &bucket->watch_group);
1154 if (!error && bucket->watch_group > OFPG_MAX) {
1155 error = xasprintf("invalid watch_group id %"PRIu32,
1156 bucket->watch_group);
1157 }
1158 } else if (!strcasecmp(key, "bucket_id")) {
1159 error = str_to_u32(value, &bucket->bucket_id);
1160 if (!error && bucket->bucket_id > OFPG15_BUCKET_MAX) {
1161 error = xasprintf("invalid bucket_id id %"PRIu32,
1162 bucket->bucket_id);
1163 }
1164 *usable_protocols &= OFPUTIL_P_OF15_UP;
1165 } else if (!strcasecmp(key, "action") || !strcasecmp(key, "actions")) {
1166 ds_put_format(&actions, "%s,", value);
1167 } else {
1168 ds_put_format(&actions, "%s(%s),", key, value);
1169 }
1170
1171 if (error) {
1172 ds_destroy(&actions);
1173 return error;
1174 }
1175 }
1176
1177 if (!actions.length) {
1178 return xstrdup("bucket must specify actions");
1179 }
1180 ds_chomp(&actions, ',');
1181
1182 ofpbuf_init(&ofpacts, 0);
1183 error = ofpacts_parse_actions(ds_cstr(&actions), &ofpacts,
1184 usable_protocols);
1185 ds_destroy(&actions);
1186 if (error) {
1187 ofpbuf_uninit(&ofpacts);
1188 return error;
1189 }
1190 bucket->ofpacts = ofpacts.data;
1191 bucket->ofpacts_len = ofpacts.size;
1192
1193 return NULL;
1194 }
1195
1196 static char * OVS_WARN_UNUSED_RESULT
1197 parse_select_group_field(char *s, struct field_array *fa,
1198 enum ofputil_protocol *usable_protocols)
1199 {
1200 char *save_ptr = NULL;
1201 char *name;
1202
1203 for (name = strtok_r(s, "=, \t\r\n", &save_ptr); name;
1204 name = strtok_r(NULL, "=, \t\r\n", &save_ptr)) {
1205 const struct mf_field *mf = mf_from_name(name);
1206
1207 if (mf) {
1208 char *error;
1209 const char *value_str;
1210 union mf_value value;
1211
1212 if (bitmap_is_set(fa->used.bm, mf->id)) {
1213 return xasprintf("%s: duplicate field", name);
1214 }
1215
1216 value_str = strtok_r(NULL, ", \t\r\n", &save_ptr);
1217 if (value_str) {
1218 error = mf_parse_value(mf, value_str, &value);
1219 if (error) {
1220 return error;
1221 }
1222
1223 /* The mask cannot be all-zeros */
1224 if (is_all_zeros(&value, mf->n_bytes)) {
1225 return xasprintf("%s: values are wildcards here "
1226 "and must not be all-zeros", s);
1227 }
1228
1229 /* The values parsed are masks for fields used
1230 * by the selection method */
1231 if (!mf_is_mask_valid(mf, &value)) {
1232 return xasprintf("%s: invalid mask for field %s",
1233 value_str, mf->name);
1234 }
1235 } else {
1236 memset(&value, 0xff, mf->n_bytes);
1237 }
1238
1239 field_array_set(mf->id, &value, fa);
1240
1241 if (is_all_ones(&value, mf->n_bytes)) {
1242 *usable_protocols &= mf->usable_protocols_exact;
1243 } else if (mf->usable_protocols_bitwise == mf->usable_protocols_cidr
1244 || ip_is_cidr(value.be32)) {
1245 *usable_protocols &= mf->usable_protocols_cidr;
1246 } else {
1247 *usable_protocols &= mf->usable_protocols_bitwise;
1248 }
1249 } else {
1250 return xasprintf("%s: unknown field %s", s, name);
1251 }
1252 }
1253
1254 return NULL;
1255 }
1256
1257 static char * OVS_WARN_UNUSED_RESULT
1258 parse_ofp_group_mod_str__(struct ofputil_group_mod *gm, uint16_t command,
1259 char *string,
1260 enum ofputil_protocol *usable_protocols)
1261 {
1262 enum {
1263 F_GROUP_TYPE = 1 << 0,
1264 F_BUCKETS = 1 << 1,
1265 F_COMMAND_BUCKET_ID = 1 << 2,
1266 F_COMMAND_BUCKET_ID_ALL = 1 << 3,
1267 } fields;
1268 char *save_ptr = NULL;
1269 bool had_type = false;
1270 bool had_command_bucket_id = false;
1271 char *name;
1272 struct ofputil_bucket *bucket;
1273 char *error = NULL;
1274
1275 *usable_protocols = OFPUTIL_P_OF11_UP;
1276
1277 switch (command) {
1278 case OFPGC11_ADD:
1279 fields = F_GROUP_TYPE | F_BUCKETS;
1280 break;
1281
1282 case OFPGC11_DELETE:
1283 fields = 0;
1284 break;
1285
1286 case OFPGC11_MODIFY:
1287 fields = F_GROUP_TYPE | F_BUCKETS;
1288 break;
1289
1290 case OFPGC15_INSERT_BUCKET:
1291 fields = F_BUCKETS | F_COMMAND_BUCKET_ID;
1292 *usable_protocols &= OFPUTIL_P_OF15_UP;
1293 break;
1294
1295 case OFPGC15_REMOVE_BUCKET:
1296 fields = F_COMMAND_BUCKET_ID | F_COMMAND_BUCKET_ID_ALL;
1297 *usable_protocols &= OFPUTIL_P_OF15_UP;
1298 break;
1299
1300 default:
1301 OVS_NOT_REACHED();
1302 }
1303
1304 memset(gm, 0, sizeof *gm);
1305 gm->command = command;
1306 gm->group_id = OFPG_ANY;
1307 gm->command_bucket_id = OFPG15_BUCKET_ALL;
1308 list_init(&gm->buckets);
1309 if (command == OFPGC11_DELETE && string[0] == '\0') {
1310 gm->group_id = OFPG_ALL;
1311 return NULL;
1312 }
1313
1314 *usable_protocols = OFPUTIL_P_OF11_UP;
1315
1316 if (fields & F_BUCKETS) {
1317 char *bkt_str = strstr(string, "bucket=");
1318
1319 if (bkt_str) {
1320 *bkt_str = '\0';
1321 }
1322
1323 while (bkt_str) {
1324 char *next_bkt_str;
1325
1326 bkt_str = strchr(bkt_str + 1, '=');
1327 if (!bkt_str) {
1328 error = xstrdup("must specify bucket content");
1329 goto out;
1330 }
1331 bkt_str++;
1332
1333 next_bkt_str = strstr(bkt_str, "bucket=");
1334 if (next_bkt_str) {
1335 *next_bkt_str = '\0';
1336 }
1337
1338 bucket = xzalloc(sizeof(struct ofputil_bucket));
1339 error = parse_bucket_str(bucket, bkt_str, usable_protocols);
1340 if (error) {
1341 free(bucket);
1342 goto out;
1343 }
1344 list_push_back(&gm->buckets, &bucket->list_node);
1345
1346 bkt_str = next_bkt_str;
1347 }
1348 }
1349
1350 for (name = strtok_r(string, "=, \t\r\n", &save_ptr); name;
1351 name = strtok_r(NULL, "=, \t\r\n", &save_ptr)) {
1352 char *value;
1353
1354 value = strtok_r(NULL, ", \t\r\n", &save_ptr);
1355 if (!value) {
1356 error = xasprintf("field %s missing value", name);
1357 goto out;
1358 }
1359
1360 if (!strcmp(name, "command_bucket_id")) {
1361 if (!(fields & F_COMMAND_BUCKET_ID)) {
1362 error = xstrdup("command bucket id is not needed");
1363 goto out;
1364 }
1365 if (!strcmp(value, "all")) {
1366 gm->command_bucket_id = OFPG15_BUCKET_ALL;
1367 } else if (!strcmp(value, "first")) {
1368 gm->command_bucket_id = OFPG15_BUCKET_FIRST;
1369 } else if (!strcmp(value, "last")) {
1370 gm->command_bucket_id = OFPG15_BUCKET_LAST;
1371 } else {
1372 error = str_to_u32(value, &gm->command_bucket_id);
1373 if (error) {
1374 goto out;
1375 }
1376 if (gm->command_bucket_id > OFPG15_BUCKET_MAX
1377 && (gm->command_bucket_id != OFPG15_BUCKET_FIRST
1378 && gm->command_bucket_id != OFPG15_BUCKET_LAST
1379 && gm->command_bucket_id != OFPG15_BUCKET_ALL)) {
1380 error = xasprintf("invalid command bucket id %"PRIu32,
1381 gm->command_bucket_id);
1382 goto out;
1383 }
1384 }
1385 if (gm->command_bucket_id == OFPG15_BUCKET_ALL
1386 && !(fields & F_COMMAND_BUCKET_ID_ALL)) {
1387 error = xstrdup("command_bucket_id=all is not permitted");
1388 goto out;
1389 }
1390 had_command_bucket_id = true;
1391 } else if (!strcmp(name, "group_id")) {
1392 if(!strcmp(value, "all")) {
1393 gm->group_id = OFPG_ALL;
1394 } else {
1395 error = str_to_u32(value, &gm->group_id);
1396 if (error) {
1397 goto out;
1398 }
1399 if (gm->group_id != OFPG_ALL && gm->group_id > OFPG_MAX) {
1400 error = xasprintf("invalid group id %"PRIu32,
1401 gm->group_id);
1402 goto out;
1403 }
1404 }
1405 } else if (!strcmp(name, "type")){
1406 if (!(fields & F_GROUP_TYPE)) {
1407 error = xstrdup("type is not needed");
1408 goto out;
1409 }
1410 if (!strcmp(value, "all")) {
1411 gm->type = OFPGT11_ALL;
1412 } else if (!strcmp(value, "select")) {
1413 gm->type = OFPGT11_SELECT;
1414 } else if (!strcmp(value, "indirect")) {
1415 gm->type = OFPGT11_INDIRECT;
1416 } else if (!strcmp(value, "ff") ||
1417 !strcmp(value, "fast_failover")) {
1418 gm->type = OFPGT11_FF;
1419 } else {
1420 error = xasprintf("invalid group type %s", value);
1421 goto out;
1422 }
1423 had_type = true;
1424 } else if (!strcmp(name, "bucket")) {
1425 error = xstrdup("bucket is not needed");
1426 goto out;
1427 } else if (!strcmp(name, "selection_method")) {
1428 if (!(fields & F_GROUP_TYPE)) {
1429 error = xstrdup("selection method is not needed");
1430 goto out;
1431 }
1432 if (strlen(value) >= NTR_MAX_SELECTION_METHOD_LEN) {
1433 error = xasprintf("selection method is longer than %u"
1434 " bytes long",
1435 NTR_MAX_SELECTION_METHOD_LEN - 1);
1436 goto out;
1437 }
1438 memset(gm->props.selection_method, '\0',
1439 NTR_MAX_SELECTION_METHOD_LEN);
1440 strcpy(gm->props.selection_method, value);
1441 *usable_protocols &= OFPUTIL_P_OF15_UP;
1442 } else if (!strcmp(name, "selection_method_param")) {
1443 if (!(fields & F_GROUP_TYPE)) {
1444 error = xstrdup("selection method param is not needed");
1445 goto out;
1446 }
1447 error = str_to_u64(value, &gm->props.selection_method_param);
1448 if (error) {
1449 goto out;
1450 }
1451 *usable_protocols &= OFPUTIL_P_OF15_UP;
1452 } else if (!strcmp(name, "fields")) {
1453 if (!(fields & F_GROUP_TYPE)) {
1454 error = xstrdup("fields are not needed");
1455 goto out;
1456 }
1457 error = parse_select_group_field(value, &gm->props.fields,
1458 usable_protocols);
1459 if (error) {
1460 goto out;
1461 }
1462 *usable_protocols &= OFPUTIL_P_OF15_UP;
1463 } else {
1464 error = xasprintf("unknown keyword %s", name);
1465 goto out;
1466 }
1467 }
1468 if (gm->group_id == OFPG_ANY) {
1469 error = xstrdup("must specify a group_id");
1470 goto out;
1471 }
1472 if (fields & F_GROUP_TYPE && !had_type) {
1473 error = xstrdup("must specify a type");
1474 goto out;
1475 }
1476
1477 if (fields & F_COMMAND_BUCKET_ID) {
1478 if (!(fields & F_COMMAND_BUCKET_ID_ALL || had_command_bucket_id)) {
1479 error = xstrdup("must specify a command bucket id");
1480 goto out;
1481 }
1482 } else if (had_command_bucket_id) {
1483 error = xstrdup("command bucket id is not needed");
1484 goto out;
1485 }
1486
1487 /* Validate buckets. */
1488 LIST_FOR_EACH (bucket, list_node, &gm->buckets) {
1489 if (bucket->weight != 1 && gm->type != OFPGT11_SELECT) {
1490 error = xstrdup("Only select groups can have bucket weights.");
1491 goto out;
1492 }
1493 }
1494 if (gm->type == OFPGT11_INDIRECT && !list_is_short(&gm->buckets)) {
1495 error = xstrdup("Indirect groups can have at most one bucket.");
1496 goto out;
1497 }
1498
1499 return NULL;
1500 out:
1501 ofputil_bucket_list_destroy(&gm->buckets);
1502 return error;
1503 }
1504
1505 char * OVS_WARN_UNUSED_RESULT
1506 parse_ofp_group_mod_str(struct ofputil_group_mod *gm, uint16_t command,
1507 const char *str_,
1508 enum ofputil_protocol *usable_protocols)
1509 {
1510 char *string = xstrdup(str_);
1511 char *error = parse_ofp_group_mod_str__(gm, command, string,
1512 usable_protocols);
1513 free(string);
1514
1515 if (error) {
1516 ofputil_bucket_list_destroy(&gm->buckets);
1517 }
1518 return error;
1519 }
1520
1521 char * OVS_WARN_UNUSED_RESULT
1522 parse_ofp_group_mod_file(const char *file_name, uint16_t command,
1523 struct ofputil_group_mod **gms, size_t *n_gms,
1524 enum ofputil_protocol *usable_protocols)
1525 {
1526 size_t allocated_gms;
1527 int line_number;
1528 FILE *stream;
1529 struct ds s;
1530
1531 *gms = NULL;
1532 *n_gms = 0;
1533
1534 stream = !strcmp(file_name, "-") ? stdin : fopen(file_name, "r");
1535 if (stream == NULL) {
1536 return xasprintf("%s: open failed (%s)",
1537 file_name, ovs_strerror(errno));
1538 }
1539
1540 allocated_gms = *n_gms;
1541 ds_init(&s);
1542 line_number = 0;
1543 *usable_protocols = OFPUTIL_P_OF11_UP;
1544 while (!ds_get_preprocessed_line(&s, stream, &line_number)) {
1545 enum ofputil_protocol usable;
1546 char *error;
1547
1548 if (*n_gms >= allocated_gms) {
1549 struct ofputil_group_mod *new_gms;
1550 size_t i;
1551
1552 new_gms = x2nrealloc(*gms, &allocated_gms, sizeof **gms);
1553 for (i = 0; i < *n_gms; i++) {
1554 list_moved(&new_gms[i].buckets, &(*gms)[i].buckets);
1555 }
1556 *gms = new_gms;
1557 }
1558 error = parse_ofp_group_mod_str(&(*gms)[*n_gms], command, ds_cstr(&s),
1559 &usable);
1560 if (error) {
1561 size_t i;
1562
1563 for (i = 0; i < *n_gms; i++) {
1564 ofputil_bucket_list_destroy(&(*gms)[i].buckets);
1565 }
1566 free(*gms);
1567 *gms = NULL;
1568 *n_gms = 0;
1569
1570 ds_destroy(&s);
1571 if (stream != stdin) {
1572 fclose(stream);
1573 }
1574
1575 return xasprintf("%s:%d: %s", file_name, line_number, error);
1576 }
1577 *usable_protocols &= usable;
1578 *n_gms += 1;
1579 }
1580
1581 ds_destroy(&s);
1582 if (stream != stdin) {
1583 fclose(stream);
1584 }
1585 return NULL;
1586 }
1587
1588 char * OVS_WARN_UNUSED_RESULT
1589 parse_ofp_geneve_table_mod_str(struct ofputil_geneve_table_mod *gtm,
1590 uint16_t command, const char *s,
1591 enum ofputil_protocol *usable_protocols)
1592 {
1593 *usable_protocols = OFPUTIL_P_NXM_OXM_ANY;
1594
1595 gtm->command = command;
1596 list_init(&gtm->mappings);
1597
1598 while (*s) {
1599 struct ofputil_geneve_map *map = xmalloc(sizeof *map);
1600 int n;
1601
1602 if (*s == ',') {
1603 s++;
1604 }
1605
1606 list_push_back(&gtm->mappings, &map->list_node);
1607
1608 if (!ovs_scan(s, "{class=%"SCNi16",type=%"SCNi8",len=%"SCNi8"}->tun_metadata%"SCNi16"%n",
1609 &map->option_class, &map->option_type, &map->option_len,
1610 &map->index, &n)) {
1611 ofputil_uninit_geneve_table(&gtm->mappings);
1612 return xstrdup("invalid geneve mapping");
1613 }
1614
1615 s += n;
1616 }
1617
1618 return NULL;
1619 }