]> git.proxmox.com Git - mirror_ovs.git/blame - lib/ofp-parse.c
ovs-dpctl: Describe -s option in usage message.
[mirror_ovs.git] / lib / ofp-parse.c
CommitLineData
f22716dc 1/*
e0edde6f 2 * Copyright (c) 2010, 2011, 2012 Nicira, Inc.
f22716dc
JP
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
00b1c62f 21#include <ctype.h>
f22716dc
JP
22#include <errno.h>
23#include <stdlib.h>
24
3b6a2571 25#include "autopath.h"
daff3353 26#include "bundle.h"
10a24935 27#include "byte-order.h"
15f1f1b6 28#include "dynamic-string.h"
75a75043 29#include "learn.h"
6a885fd0 30#include "meta-flow.h"
53ddd40a 31#include "multipath.h"
f25d0cf3 32#include "netdev.h"
f393f81e 33#include "nx-match.h"
f25d0cf3 34#include "ofp-actions.h"
f22716dc
JP
35#include "ofp-util.h"
36#include "ofpbuf.h"
37#include "openflow/openflow.h"
38#include "packets.h"
39#include "socket-util.h"
40#include "vconn.h"
41#include "vlog.h"
f22716dc 42
d98e6007 43VLOG_DEFINE_THIS_MODULE(ofp_parse);
f22716dc 44
99b67183
BP
45static void ofp_fatal(const char *flow, bool verbose, const char *format, ...)
46 NO_RETURN;
47
c3636ffc
BP
48static uint8_t
49str_to_table_id(const char *str)
50{
51 int table_id;
52
53 if (!str_to_int(str, 10, &table_id) || table_id < 0 || table_id > 255) {
54 ovs_fatal(0, "invalid table \"%s\"", str);
55 }
56 return table_id;
57}
58
59static uint16_t
60str_to_u16(const char *str, const char *name)
61{
62 int value;
63
64 if (!str_to_int(str, 0, &value) || value < 0 || value > 65535) {
65 ovs_fatal(0, "invalid %s \"%s\"", name, str);
66 }
67 return value;
68}
69
f22716dc
JP
70static uint32_t
71str_to_u32(const char *str)
72{
73 char *tail;
74 uint32_t value;
75
c4894ed4 76 if (!str[0]) {
ce5452cf
EJ
77 ovs_fatal(0, "missing required numeric argument");
78 }
79
f22716dc
JP
80 errno = 0;
81 value = strtoul(str, &tail, 0);
82 if (errno == EINVAL || errno == ERANGE || *tail) {
83 ovs_fatal(0, "invalid numeric format %s", str);
84 }
85 return value;
86}
87
88static uint64_t
89str_to_u64(const char *str)
90{
91 char *tail;
92 uint64_t value;
93
c4894ed4
BP
94 if (!str[0]) {
95 ovs_fatal(0, "missing required numeric argument");
96 }
97
f22716dc
JP
98 errno = 0;
99 value = strtoull(str, &tail, 0);
100 if (errno == EINVAL || errno == ERANGE || *tail) {
101 ovs_fatal(0, "invalid numeric format %s", str);
102 }
103 return value;
104}
105
106static void
107str_to_mac(const char *str, uint8_t mac[6])
108{
109 if (sscanf(str, ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(mac))
110 != ETH_ADDR_SCAN_COUNT) {
111 ovs_fatal(0, "invalid mac address %s", str);
112 }
113}
114
cb8ca532 115static void
6a885fd0 116str_to_ip(const char *str, ovs_be32 *ip)
cb8ca532 117{
f22716dc 118 struct in_addr in_addr;
f22716dc 119
6a885fd0 120 if (lookup_ip(str, &in_addr)) {
f22716dc
JP
121 ovs_fatal(0, "%s: could not convert to IP address", str);
122 }
123 *ip = in_addr.s_addr;
d31f1109
JP
124}
125
5682f723 126static void
f25d0cf3 127parse_enqueue(char *arg, struct ofpbuf *ofpacts)
5682f723 128{
333eba21
BP
129 char *sp = NULL;
130 char *port = strtok_r(arg, ":q", &sp);
131 char *queue = strtok_r(NULL, "", &sp);
f25d0cf3 132 struct ofpact_enqueue *enqueue;
333eba21
BP
133
134 if (port == NULL || queue == NULL) {
135 ovs_fatal(0, "\"enqueue\" syntax is \"enqueue:PORT:QUEUE\"");
136 }
137
f25d0cf3
BP
138 enqueue = ofpact_put_ENQUEUE(ofpacts);
139 enqueue->port = str_to_u32(port);
140 enqueue->queue = str_to_u32(queue);
5682f723
BP
141}
142
f694937d 143static void
f25d0cf3 144parse_output(char *arg, struct ofpbuf *ofpacts)
f694937d
EJ
145{
146 if (strchr(arg, '[')) {
f25d0cf3 147 struct ofpact_output_reg *output_reg;
f694937d 148
f25d0cf3
BP
149 output_reg = ofpact_put_OUTPUT_REG(ofpacts);
150 mf_parse_subfield(&output_reg->src, arg);
151 output_reg->max_len = UINT16_MAX;
f694937d 152 } else {
f25d0cf3
BP
153 struct ofpact_output *output;
154
155 output = ofpact_put_OUTPUT(ofpacts);
156 output->port = str_to_u32(arg);
157 output->max_len = output->port == OFPP_CONTROLLER ? UINT16_MAX : 0;
f694937d
EJ
158 }
159}
160
29901626 161static void
f25d0cf3 162parse_resubmit(char *arg, struct ofpbuf *ofpacts)
29901626 163{
f25d0cf3 164 struct ofpact_resubmit *resubmit;
29901626 165 char *in_port_s, *table_s;
f25d0cf3
BP
166
167 resubmit = ofpact_put_RESUBMIT(ofpacts);
29901626
BP
168
169 in_port_s = strsep(&arg, ",");
170 if (in_port_s && in_port_s[0]) {
8010100b 171 if (!ofputil_port_from_string(in_port_s, &resubmit->in_port)) {
c6100d92 172 ovs_fatal(0, "%s: resubmit to unknown port", in_port_s);
29901626
BP
173 }
174 } else {
f25d0cf3 175 resubmit->in_port = OFPP_IN_PORT;
29901626
BP
176 }
177
178 table_s = strsep(&arg, ",");
f25d0cf3 179 resubmit->table_id = table_s && table_s[0] ? str_to_u32(table_s) : 255;
29901626 180
f25d0cf3 181 if (resubmit->in_port == OFPP_IN_PORT && resubmit->table_id == 255) {
29901626
BP
182 ovs_fatal(0, "at least one \"in_port\" or \"table\" must be specified "
183 " on resubmit");
184 }
333eba21
BP
185}
186
187static void
f25d0cf3 188parse_note(const char *arg, struct ofpbuf *ofpacts)
333eba21 189{
f25d0cf3 190 struct ofpact_note *note;
333eba21 191
f25d0cf3 192 note = ofpact_put_NOTE(ofpacts);
333eba21
BP
193 while (*arg != '\0') {
194 uint8_t byte;
195 bool ok;
196
197 if (*arg == '.') {
198 arg++;
199 }
200 if (*arg == '\0') {
201 break;
202 }
203
204 byte = hexits_value(arg, 2, &ok);
205 if (!ok) {
206 ovs_fatal(0, "bad hex digit in `note' argument");
207 }
f25d0cf3 208 ofpbuf_put(ofpacts, &byte, 1);
333eba21 209
f25d0cf3
BP
210 note = ofpacts->l2;
211 note->length++;
333eba21 212
f25d0cf3 213 arg += 2;
333eba21 214 }
f25d0cf3 215 ofpact_update_len(ofpacts, &note->ofpact);
333eba21
BP
216}
217
0e553d9c
BP
218static void
219parse_fin_timeout(struct ofpbuf *b, char *arg)
220{
f25d0cf3 221 struct ofpact_fin_timeout *oft = ofpact_put_FIN_TIMEOUT(b);
0e553d9c
BP
222 char *key, *value;
223
0e553d9c
BP
224 while (ofputil_parse_key_value(&arg, &key, &value)) {
225 if (!strcmp(key, "idle_timeout")) {
f25d0cf3 226 oft->fin_idle_timeout = str_to_u16(value, key);
0e553d9c 227 } else if (!strcmp(key, "hard_timeout")) {
f25d0cf3 228 oft->fin_hard_timeout = str_to_u16(value, key);
0e553d9c
BP
229 } else {
230 ovs_fatal(0, "invalid key '%s' in 'fin_timeout' argument", key);
231 }
232 }
233}
234
a7349929
BP
235static void
236parse_controller(struct ofpbuf *b, char *arg)
237{
238 enum ofp_packet_in_reason reason = OFPR_ACTION;
239 uint16_t controller_id = 0;
240 uint16_t max_len = UINT16_MAX;
241
242 if (!arg[0]) {
243 /* Use defaults. */
244 } else if (strspn(arg, "0123456789") == strlen(arg)) {
245 max_len = str_to_u16(arg, "max_len");
246 } else {
247 char *name, *value;
248
249 while (ofputil_parse_key_value(&arg, &name, &value)) {
250 if (!strcmp(name, "reason")) {
251 if (!ofputil_packet_in_reason_from_string(value, &reason)) {
252 ovs_fatal(0, "unknown reason \"%s\"", value);
253 }
254 } else if (!strcmp(name, "max_len")) {
255 max_len = str_to_u16(value, "max_len");
256 } else if (!strcmp(name, "id")) {
257 controller_id = str_to_u16(value, "id");
258 } else {
259 ovs_fatal(0, "unknown key \"%s\" parsing controller action",
260 name);
261 }
262 }
263 }
264
265 if (reason == OFPR_ACTION && controller_id == 0) {
f25d0cf3
BP
266 struct ofpact_output *output;
267
268 output = ofpact_put_OUTPUT(b);
269 output->port = OFPP_CONTROLLER;
270 output->max_len = max_len;
a7349929 271 } else {
f25d0cf3 272 struct ofpact_controller *controller;
a7349929 273
f25d0cf3
BP
274 controller = ofpact_put_CONTROLLER(b);
275 controller->max_len = max_len;
276 controller->reason = reason;
277 controller->controller_id = controller_id;
a7349929
BP
278 }
279}
280
c2d967a5 281static void
99086062 282parse_noargs_dec_ttl(struct ofpbuf *b)
c2d967a5
MM
283{
284 struct ofpact_cnt_ids *ids;
7bcb1506 285 uint16_t id = 0;
c2d967a5
MM
286
287 ids = ofpact_put_DEC_TTL(b);
7bcb1506
IY
288 ofpbuf_put(b, &id, sizeof id);
289 ids = b->l2;
290 ids->n_controllers++;
291 ofpact_update_len(b, &ids->ofpact);
292}
c2d967a5 293
7bcb1506 294static void
99086062 295parse_dec_ttl(struct ofpbuf *b, char *arg)
7bcb1506 296{
c2d967a5 297 if (*arg == '\0') {
99086062 298 parse_noargs_dec_ttl(b);
c2d967a5 299 } else {
7bcb1506 300 struct ofpact_cnt_ids *ids;
c2d967a5
MM
301 char *cntr;
302
7bcb1506 303 ids = ofpact_put_DEC_TTL(b);
c2d967a5
MM
304 ids->ofpact.compat = OFPUTIL_NXAST_DEC_TTL_CNT_IDS;
305 for (cntr = strtok_r(arg, ", ", &arg); cntr != NULL;
306 cntr = strtok_r(NULL, ", ", &arg)) {
307 uint16_t id = atoi(cntr);
308
309 ofpbuf_put(b, &id, sizeof id);
310 ids = b->l2;
311 ids->n_controllers++;
312 }
313 if (!ids->n_controllers) {
314 ovs_fatal(0, "dec_ttl_cnt_ids: expected at least one controller "
315 "id.");
316 }
7bcb1506 317 ofpact_update_len(b, &ids->ofpact);
c2d967a5 318 }
c2d967a5
MM
319}
320
f5c45121
SH
321static void
322set_field_parse(const char *arg, struct ofpbuf *ofpacts)
323{
324 char *orig = xstrdup(arg);
325 struct ofpact_reg_load *load = ofpact_put_REG_LOAD(ofpacts);
326 char *value;
327 char *delim;
328 char *key;
329 const struct mf_field *mf;
330 const char *error;
331 union mf_value mf_value;
332
333 value = orig;
334 delim = strstr(orig, "->");
335 if (!delim) {
336 ovs_fatal(0, "%s: missing `->'", orig);
337 }
338 if (strlen(delim) <= strlen("->")) {
339 ovs_fatal(0, "%s: missing field name following `->'", orig);
340 }
341
342 key = delim + strlen("->");
343 mf = mf_from_name(key);
344 if (!mf) {
345 ovs_fatal(0, "%s is not valid oxm field name", key);
346 }
347 if (!mf->writable) {
348 ovs_fatal(0, "%s is not allowed to set", key);
349 }
350
351 delim[0] = '\0';
352 error = mf_parse_value(mf, value, &mf_value);
353 if (error) {
354 ovs_fatal(0, "%s", error);
355 }
356 if (!mf_is_value_valid(mf, &mf_value)) {
357 ovs_fatal(0, "%s is not valid valid for field %s", value, key);
358 }
359 ofpact_set_field_init(load, mf, &mf_value);
360 free(orig);
361}
362
4cceacb9
JS
363static void
364parse_metadata(struct ofpbuf *b, char *arg)
365{
366 struct ofpact_metadata *om;
367 char *mask = strchr(arg, '/');
368
369 om = ofpact_put_WRITE_METADATA(b);
370
371 if (mask) {
372 *mask = '\0';
373 om->mask = htonll(str_to_u64(mask + 1));
374 } else {
375 om->mask = htonll(UINT64_MAX);
376 }
377
378 om->metadata = htonll(str_to_u64(arg));
379}
380
333eba21 381static void
75a75043 382parse_named_action(enum ofputil_action_code code, const struct flow *flow,
f25d0cf3 383 char *arg, struct ofpbuf *ofpacts)
333eba21 384{
f25d0cf3
BP
385 struct ofpact_tunnel *tunnel;
386 uint16_t vid;
3e34fbdd 387 uint16_t ethertype;
f25d0cf3
BP
388 ovs_be32 ip;
389 uint8_t pcp;
390 uint8_t tos;
333eba21
BP
391
392 switch (code) {
690a61c5
BP
393 case OFPUTIL_ACTION_INVALID:
394 NOT_REACHED();
395
08f94c0e 396 case OFPUTIL_OFPAT10_OUTPUT:
d01c980f 397 case OFPUTIL_OFPAT11_OUTPUT:
f25d0cf3 398 parse_output(arg, ofpacts);
333eba21
BP
399 break;
400
08f94c0e 401 case OFPUTIL_OFPAT10_SET_VLAN_VID:
d01c980f 402 case OFPUTIL_OFPAT11_SET_VLAN_VID:
f25d0cf3
BP
403 vid = str_to_u32(arg);
404 if (vid & ~VLAN_VID_MASK) {
405 ovs_fatal(0, "%s: not a valid VLAN VID", arg);
406 }
407 ofpact_put_SET_VLAN_VID(ofpacts)->vlan_vid = vid;
333eba21
BP
408 break;
409
08f94c0e 410 case OFPUTIL_OFPAT10_SET_VLAN_PCP:
d01c980f 411 case OFPUTIL_OFPAT11_SET_VLAN_PCP:
f25d0cf3
BP
412 pcp = str_to_u32(arg);
413 if (pcp & ~7) {
414 ovs_fatal(0, "%s: not a valid VLAN PCP", arg);
415 }
416 ofpact_put_SET_VLAN_PCP(ofpacts)->vlan_pcp = pcp;
333eba21
BP
417 break;
418
78a3fff6 419 case OFPUTIL_OFPAT12_SET_FIELD:
f5c45121 420 set_field_parse(arg, ofpacts);
78a3fff6
SH
421 break;
422
08f94c0e 423 case OFPUTIL_OFPAT10_STRIP_VLAN:
8e61c110 424 case OFPUTIL_OFPAT11_POP_VLAN:
f25d0cf3 425 ofpact_put_STRIP_VLAN(ofpacts);
333eba21
BP
426 break;
427
3e34fbdd
IY
428 case OFPUTIL_OFPAT11_PUSH_VLAN:
429 ethertype = str_to_u16(arg, "ethertype");
430 if (ethertype != ETH_TYPE_VLAN_8021Q) {
431 /* TODO:XXXX ETH_TYPE_VLAN_8021AD case isn't supported */
432 ovs_fatal(0, "%s: not a valid VLAN ethertype", arg);
433 }
434 ofpact_put_PUSH_VLAN(ofpacts);
435 break;
436
08f94c0e 437 case OFPUTIL_OFPAT10_SET_DL_SRC:
d01c980f 438 case OFPUTIL_OFPAT11_SET_DL_SRC:
f25d0cf3
BP
439 str_to_mac(arg, ofpact_put_SET_ETH_SRC(ofpacts)->mac);
440 break;
441
08f94c0e 442 case OFPUTIL_OFPAT10_SET_DL_DST:
d01c980f 443 case OFPUTIL_OFPAT11_SET_DL_DST:
f25d0cf3 444 str_to_mac(arg, ofpact_put_SET_ETH_DST(ofpacts)->mac);
333eba21
BP
445 break;
446
08f94c0e 447 case OFPUTIL_OFPAT10_SET_NW_SRC:
d01c980f 448 case OFPUTIL_OFPAT11_SET_NW_SRC:
f25d0cf3
BP
449 str_to_ip(arg, &ip);
450 ofpact_put_SET_IPV4_SRC(ofpacts)->ipv4 = ip;
451 break;
452
08f94c0e 453 case OFPUTIL_OFPAT10_SET_NW_DST:
d01c980f 454 case OFPUTIL_OFPAT11_SET_NW_DST:
f25d0cf3
BP
455 str_to_ip(arg, &ip);
456 ofpact_put_SET_IPV4_DST(ofpacts)->ipv4 = ip;
333eba21
BP
457 break;
458
08f94c0e 459 case OFPUTIL_OFPAT10_SET_NW_TOS:
d01c980f 460 case OFPUTIL_OFPAT11_SET_NW_TOS:
f25d0cf3
BP
461 tos = str_to_u32(arg);
462 if (tos & ~IP_DSCP_MASK) {
463 ovs_fatal(0, "%s: not a valid TOS", arg);
464 }
465 ofpact_put_SET_IPV4_DSCP(ofpacts)->dscp = tos;
333eba21
BP
466 break;
467
7bcb1506 468 case OFPUTIL_OFPAT11_DEC_NW_TTL:
68194f84 469 NOT_REACHED();
7bcb1506 470
08f94c0e 471 case OFPUTIL_OFPAT10_SET_TP_SRC:
d01c980f 472 case OFPUTIL_OFPAT11_SET_TP_SRC:
f25d0cf3
BP
473 ofpact_put_SET_L4_SRC_PORT(ofpacts)->port = str_to_u32(arg);
474 break;
475
08f94c0e 476 case OFPUTIL_OFPAT10_SET_TP_DST:
d01c980f 477 case OFPUTIL_OFPAT11_SET_TP_DST:
f25d0cf3 478 ofpact_put_SET_L4_DST_PORT(ofpacts)->port = str_to_u32(arg);
333eba21
BP
479 break;
480
08f94c0e 481 case OFPUTIL_OFPAT10_ENQUEUE:
f25d0cf3 482 parse_enqueue(arg, ofpacts);
333eba21
BP
483 break;
484
485 case OFPUTIL_NXAST_RESUBMIT:
f25d0cf3 486 parse_resubmit(arg, ofpacts);
333eba21
BP
487 break;
488
489 case OFPUTIL_NXAST_SET_TUNNEL:
f25d0cf3
BP
490 case OFPUTIL_NXAST_SET_TUNNEL64:
491 tunnel = ofpact_put_SET_TUNNEL(ofpacts);
492 tunnel->ofpact.compat = code;
493 tunnel->tun_id = str_to_u64(arg);
333eba21
BP
494 break;
495
4cceacb9
JS
496 case OFPUTIL_NXAST_WRITE_METADATA:
497 parse_metadata(ofpacts, arg);
498 break;
499
333eba21 500 case OFPUTIL_NXAST_SET_QUEUE:
f25d0cf3 501 ofpact_put_SET_QUEUE(ofpacts)->queue_id = str_to_u32(arg);
333eba21
BP
502 break;
503
504 case OFPUTIL_NXAST_POP_QUEUE:
f25d0cf3 505 ofpact_put_POP_QUEUE(ofpacts);
333eba21
BP
506 break;
507
508 case OFPUTIL_NXAST_REG_MOVE:
f25d0cf3 509 nxm_parse_reg_move(ofpact_put_REG_MOVE(ofpacts), arg);
333eba21
BP
510 break;
511
512 case OFPUTIL_NXAST_REG_LOAD:
f25d0cf3 513 nxm_parse_reg_load(ofpact_put_REG_LOAD(ofpacts), arg);
333eba21
BP
514 break;
515
516 case OFPUTIL_NXAST_NOTE:
f25d0cf3 517 parse_note(arg, ofpacts);
93996add
BP
518 break;
519
333eba21 520 case OFPUTIL_NXAST_MULTIPATH:
f25d0cf3 521 multipath_parse(ofpact_put_MULTIPATH(ofpacts), arg);
333eba21
BP
522 break;
523
c51c638a 524 case OFPUTIL_NXAST_AUTOPATH__DEPRECATED:
f25d0cf3 525 autopath_parse(ofpact_put_AUTOPATH(ofpacts), arg);
333eba21
BP
526 break;
527
528 case OFPUTIL_NXAST_BUNDLE:
f25d0cf3 529 bundle_parse(arg, ofpacts);
333eba21
BP
530 break;
531
532 case OFPUTIL_NXAST_BUNDLE_LOAD:
f25d0cf3 533 bundle_parse_load(arg, ofpacts);
333eba21
BP
534 break;
535
536 case OFPUTIL_NXAST_RESUBMIT_TABLE:
537 case OFPUTIL_NXAST_OUTPUT_REG:
c2d967a5 538 case OFPUTIL_NXAST_DEC_TTL_CNT_IDS:
333eba21 539 NOT_REACHED();
75a75043
BP
540
541 case OFPUTIL_NXAST_LEARN:
f25d0cf3 542 learn_parse(arg, flow, ofpacts);
75a75043 543 break;
a61680c6 544
848e8809 545 case OFPUTIL_NXAST_EXIT:
f25d0cf3 546 ofpact_put_EXIT(ofpacts);
848e8809 547 break;
f0fd1a17
PS
548
549 case OFPUTIL_NXAST_DEC_TTL:
99086062 550 parse_dec_ttl(ofpacts, arg);
f0fd1a17 551 break;
0e553d9c
BP
552
553 case OFPUTIL_NXAST_FIN_TIMEOUT:
f25d0cf3 554 parse_fin_timeout(ofpacts, arg);
0e553d9c 555 break;
a7349929
BP
556
557 case OFPUTIL_NXAST_CONTROLLER:
f25d0cf3 558 parse_controller(ofpacts, arg);
a7349929 559 break;
333eba21
BP
560 }
561}
562
8dd54666
IY
563static bool
564str_to_ofpact__(const struct flow *flow, char *pos, char *act, char *arg,
565 struct ofpbuf *ofpacts, int n_actions)
566{
567 int code = ofputil_action_code_from_name(act);
568 if (code >= 0) {
569 parse_named_action(code, flow, arg, ofpacts);
570 } else if (!strcasecmp(act, "drop")) {
571 if (n_actions) {
572 ovs_fatal(0, "Drop actions must not be preceded by other "
573 "actions");
574 } else if (ofputil_parse_key_value(&pos, &act, &arg)) {
575 ovs_fatal(0, "Drop actions must not be followed by other "
576 "actions");
577 }
578 return false;
579 } else {
8010100b
BP
580 uint16_t port;
581 if (ofputil_port_from_string(act, &port)) {
8dd54666
IY
582 ofpact_put_OUTPUT(ofpacts)->port = port;
583 } else {
584 ovs_fatal(0, "Unknown action: %s", act);
585 }
586 }
587
588 return true;
589}
590
f22716dc 591static void
f25d0cf3 592str_to_ofpacts(const struct flow *flow, char *str, struct ofpbuf *ofpacts)
f22716dc 593{
0ff22822 594 char *pos, *act, *arg;
4cceacb9 595 enum ofperr error;
f22716dc
JP
596 int n_actions;
597
53ddd40a 598 pos = str;
d13803eb 599 n_actions = 0;
0ff22822 600 while (ofputil_parse_key_value(&pos, &act, &arg)) {
8dd54666 601 if (!str_to_ofpact__(flow, pos, act, arg, ofpacts, n_actions)) {
0ff22822 602 break;
8dd54666
IY
603 }
604 n_actions++;
605 }
4cceacb9
JS
606
607 error = ofpacts_verify(ofpacts->data, ofpacts->size);
608 if (error) {
609 ovs_fatal(0, "Incorrect action ordering");
610 }
611
8dd54666
IY
612 ofpact_pad(ofpacts);
613}
614
615static void
616parse_named_instruction(enum ovs_instruction_type type,
617 char *arg, struct ofpbuf *ofpacts)
618{
4cceacb9
JS
619 enum ofperr error;
620
8dd54666
IY
621 switch (type) {
622 case OVSINST_OFPIT11_APPLY_ACTIONS:
623 NOT_REACHED(); /* This case is handled by str_to_inst_ofpacts() */
624 break;
625
626 case OVSINST_OFPIT11_WRITE_ACTIONS:
627 /* TODO:XXX */
628 ovs_fatal(0, "instruction write-actions is not supported yet");
629 break;
630
631 case OVSINST_OFPIT11_CLEAR_ACTIONS:
b19e8793 632 ofpact_put_CLEAR_ACTIONS(ofpacts);
8dd54666
IY
633 break;
634
635 case OVSINST_OFPIT11_WRITE_METADATA:
4cceacb9 636 parse_metadata(ofpacts, arg);
8dd54666
IY
637 break;
638
639 case OVSINST_OFPIT11_GOTO_TABLE: {
640 struct ofpact_goto_table *ogt = ofpact_put_GOTO_TABLE(ofpacts);
641 char *table_s = strsep(&arg, ",");
642 if (!table_s || !table_s[0]) {
643 ovs_fatal(0, "instruction goto-table needs table id");
644 }
645 ogt->table_id = str_to_table_id(table_s);
646 break;
647 }
648 }
4cceacb9
JS
649
650 /* If write_metadata is specified as an action AND an instruction, ofpacts
651 could be invalid. */
652 error = ofpacts_verify(ofpacts->data, ofpacts->size);
653 if (error) {
654 ovs_fatal(0, "Incorrect instruction ordering");
655 }
8dd54666
IY
656}
657
658static void
659str_to_inst_ofpacts(const struct flow *flow, char *str, struct ofpbuf *ofpacts)
660{
661 char *pos, *inst, *arg;
662 int type;
663 const char *prev_inst = NULL;
664 int prev_type = -1;
665 int n_actions = 0;
666
667 pos = str;
668 while (ofputil_parse_key_value(&pos, &inst, &arg)) {
669 type = ofpact_instruction_type_from_name(inst);
670 if (type < 0) {
671 if (!str_to_ofpact__(flow, pos, inst, arg, ofpacts, n_actions)) {
672 break;
673 }
674
675 type = OVSINST_OFPIT11_APPLY_ACTIONS;
676 if (prev_type == type) {
677 n_actions++;
678 continue;
c6100d92 679 }
8dd54666
IY
680 } else if (type == OVSINST_OFPIT11_APPLY_ACTIONS) {
681 ovs_fatal(0, "%s isn't supported. Just write actions then "
682 "it is interpreted as apply_actions", inst);
683 } else {
684 parse_named_instruction(type, arg, ofpacts);
685 }
686
687 if (type == prev_type) {
688 ovs_fatal(0, "instruction can be specified at most once: %s",
689 inst);
f22716dc 690 }
8dd54666
IY
691 if (type <= prev_type) {
692 ovs_fatal(0, "Instruction %s must be specified before %s",
693 inst, prev_inst);
694 }
695
696 prev_inst = inst;
697 prev_type = type;
d13803eb 698 n_actions++;
f22716dc 699 }
f25d0cf3 700 ofpact_pad(ofpacts);
f22716dc
JP
701}
702
703struct protocol {
704 const char *name;
705 uint16_t dl_type;
706 uint8_t nw_proto;
707};
708
709static bool
710parse_protocol(const char *name, const struct protocol **p_out)
711{
712 static const struct protocol protocols[] = {
713 { "ip", ETH_TYPE_IP, 0 },
714 { "arp", ETH_TYPE_ARP, 0 },
6767a2cc
JP
715 { "icmp", ETH_TYPE_IP, IPPROTO_ICMP },
716 { "tcp", ETH_TYPE_IP, IPPROTO_TCP },
717 { "udp", ETH_TYPE_IP, IPPROTO_UDP },
d31f1109
JP
718 { "ipv6", ETH_TYPE_IPV6, 0 },
719 { "ip6", ETH_TYPE_IPV6, 0 },
720 { "icmp6", ETH_TYPE_IPV6, IPPROTO_ICMPV6 },
721 { "tcp6", ETH_TYPE_IPV6, IPPROTO_TCP },
722 { "udp6", ETH_TYPE_IPV6, IPPROTO_UDP },
8087f5ff
MM
723 { "rarp", ETH_TYPE_RARP, 0},
724};
f22716dc
JP
725 const struct protocol *p;
726
727 for (p = protocols; p < &protocols[ARRAY_SIZE(protocols)]; p++) {
728 if (!strcmp(p->name, name)) {
729 *p_out = p;
730 return true;
731 }
732 }
733 *p_out = NULL;
734 return false;
735}
736
ec610b7b
AE
737static void
738ofp_fatal(const char *flow, bool verbose, const char *format, ...)
739{
740 va_list args;
741
742 if (verbose) {
743 fprintf(stderr, "%s:\n", flow);
744 }
745
746 va_start(args, format);
747 ovs_fatal_valist(0, format, args);
748}
749
8050b31d 750static void
81a76618 751parse_field(const struct mf_field *mf, const char *s, struct match *match)
8050b31d 752{
6a885fd0
BP
753 union mf_value value, mask;
754 char *error;
bad68a99 755
6a885fd0
BP
756 error = mf_parse(mf, s, &value, &mask);
757 if (error) {
758 ovs_fatal(0, "%s", error);
8050b31d 759 }
8050b31d 760
81a76618 761 mf_set(mf, &value, &mask, match);
00b1c62f
BP
762}
763
c821124b
BP
764/* Convert 'str_' (as described in the Flow Syntax section of the ovs-ofctl man
765 * page) into 'fm' for sending the specified flow_mod 'command' to a switch.
766 * If 'actions' is specified, an action must be in 'string' and may be expanded
767 * or reallocated.
768 *
769 * To parse syntax for an OFPT_FLOW_MOD (or NXT_FLOW_MOD), use an OFPFC_*
770 * constant for 'command'. To parse syntax for an OFPST_FLOW or
771 * OFPST_AGGREGATE (or NXST_FLOW or NXST_AGGREGATE), use -1 for 'command'. */
0199c526 772void
a9a2da38
BP
773parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_,
774 bool verbose)
f22716dc 775{
c821124b
BP
776 enum {
777 F_OUT_PORT = 1 << 0,
778 F_ACTIONS = 1 << 1,
c821124b 779 F_TIMEOUT = 1 << 3,
a993007b
BP
780 F_PRIORITY = 1 << 4,
781 F_FLAGS = 1 << 5,
c821124b 782 } fields;
ec610b7b 783 char *string = xstrdup(str_);
f22716dc 784 char *save_ptr = NULL;
75a75043 785 char *act_str = NULL;
f22716dc 786 char *name;
f22716dc 787
c821124b
BP
788 switch (command) {
789 case -1:
790 fields = F_OUT_PORT;
791 break;
792
793 case OFPFC_ADD:
a993007b 794 fields = F_ACTIONS | F_TIMEOUT | F_PRIORITY | F_FLAGS;
c821124b
BP
795 break;
796
797 case OFPFC_DELETE:
798 fields = F_OUT_PORT;
799 break;
800
801 case OFPFC_DELETE_STRICT:
802 fields = F_OUT_PORT | F_PRIORITY;
803 break;
804
805 case OFPFC_MODIFY:
a993007b 806 fields = F_ACTIONS | F_TIMEOUT | F_PRIORITY | F_FLAGS;
c821124b
BP
807 break;
808
809 case OFPFC_MODIFY_STRICT:
a993007b 810 fields = F_ACTIONS | F_TIMEOUT | F_PRIORITY | F_FLAGS;
c821124b
BP
811 break;
812
813 default:
814 NOT_REACHED();
815 }
816
81a76618
BP
817 match_init_catchall(&fm->match);
818 fm->priority = OFP_DEFAULT_PRIORITY;
88ca35ee 819 fm->cookie = htonll(0);
e729e793 820 fm->cookie_mask = htonll(0);
623e1caf
JP
821 if (command == OFPFC_MODIFY || command == OFPFC_MODIFY_STRICT) {
822 /* For modify, by default, don't update the cookie. */
823 fm->new_cookie = htonll(UINT64_MAX);
824 } else{
825 fm->new_cookie = htonll(0);
826 }
6c1491fb 827 fm->table_id = 0xff;
c821124b 828 fm->command = command;
88ca35ee
BP
829 fm->idle_timeout = OFP_FLOW_PERMANENT;
830 fm->hard_timeout = OFP_FLOW_PERMANENT;
831 fm->buffer_id = UINT32_MAX;
7f05e7ab 832 fm->out_port = OFPP_ANY;
88ca35ee 833 fm->flags = 0;
c821124b 834 if (fields & F_ACTIONS) {
c821124b 835 act_str = strstr(string, "action");
f22716dc 836 if (!act_str) {
ec610b7b 837 ofp_fatal(str_, verbose, "must specify an action");
f22716dc
JP
838 }
839 *act_str = '\0';
840
841 act_str = strchr(act_str + 1, '=');
842 if (!act_str) {
ec610b7b 843 ofp_fatal(str_, verbose, "must specify an action");
f22716dc
JP
844 }
845
846 act_str++;
f22716dc 847 }
f22716dc
JP
848 for (name = strtok_r(string, "=, \t\r\n", &save_ptr); name;
849 name = strtok_r(NULL, "=, \t\r\n", &save_ptr)) {
850 const struct protocol *p;
851
852 if (parse_protocol(name, &p)) {
81a76618 853 match_set_dl_type(&fm->match, htons(p->dl_type));
f22716dc 854 if (p->nw_proto) {
81a76618 855 match_set_nw_proto(&fm->match, p->nw_proto);
f22716dc 856 }
a993007b
BP
857 } else if (fields & F_FLAGS && !strcmp(name, "send_flow_rem")) {
858 fm->flags |= OFPFF_SEND_FLOW_REM;
859 } else if (fields & F_FLAGS && !strcmp(name, "check_overlap")) {
860 fm->flags |= OFPFF_CHECK_OVERLAP;
2e1ae200
JR
861 } else if (fields & F_FLAGS && !strcmp(name, "reset_counts")) {
862 fm->flags |= OFPFF12_RESET_COUNTS;
863 } else if (fields & F_FLAGS && !strcmp(name, "no_packet_counts")) {
864 fm->flags |= OFPFF13_NO_PKT_COUNTS;
865 } else if (fields & F_FLAGS && !strcmp(name, "no_byte_counts")) {
866 fm->flags |= OFPFF13_NO_BYT_COUNTS;
f22716dc 867 } else {
f22716dc
JP
868 char *value;
869
870 value = strtok_r(NULL, ", \t\r\n", &save_ptr);
871 if (!value) {
ec610b7b 872 ofp_fatal(str_, verbose, "field %s missing value", name);
f22716dc
JP
873 }
874
6c1491fb 875 if (!strcmp(name, "table")) {
c3636ffc 876 fm->table_id = str_to_table_id(value);
8050b31d 877 } else if (!strcmp(name, "out_port")) {
8010100b 878 if (!ofputil_port_from_string(name, &fm->out_port)) {
c6100d92
BP
879 ofp_fatal(str_, verbose, "%s is not a valid OpenFlow port",
880 name);
881 }
c821124b 882 } else if (fields & F_PRIORITY && !strcmp(name, "priority")) {
81a76618 883 fm->priority = str_to_u16(value, name);
c821124b 884 } else if (fields & F_TIMEOUT && !strcmp(name, "idle_timeout")) {
c3636ffc 885 fm->idle_timeout = str_to_u16(value, name);
c821124b 886 } else if (fields & F_TIMEOUT && !strcmp(name, "hard_timeout")) {
c3636ffc 887 fm->hard_timeout = str_to_u16(value, name);
e729e793
JP
888 } else if (!strcmp(name, "cookie")) {
889 char *mask = strchr(value, '/');
623e1caf 890
e729e793 891 if (mask) {
623e1caf 892 /* A mask means we're searching for a cookie. */
e729e793
JP
893 if (command == OFPFC_ADD) {
894 ofp_fatal(str_, verbose, "flow additions cannot use "
895 "a cookie mask");
896 }
897 *mask = '\0';
623e1caf 898 fm->cookie = htonll(str_to_u64(value));
e729e793
JP
899 fm->cookie_mask = htonll(str_to_u64(mask+1));
900 } else {
623e1caf
JP
901 /* No mask means that the cookie is being set. */
902 if (command != OFPFC_ADD && command != OFPFC_MODIFY
903 && command != OFPFC_MODIFY_STRICT) {
904 ofp_fatal(str_, verbose, "cannot set cookie");
905 }
906 fm->new_cookie = htonll(str_to_u64(value));
e729e793 907 }
6a885fd0 908 } else if (mf_from_name(name)) {
81a76618 909 parse_field(mf_from_name(name), value, &fm->match);
2c6d8411
BP
910 } else if (!strcmp(name, "duration")
911 || !strcmp(name, "n_packets")
912 || !strcmp(name, "n_bytes")) {
913 /* Ignore these, so that users can feed the output of
914 * "ovs-ofctl dump-flows" back into commands that parse
915 * flows. */
f22716dc 916 } else {
ec610b7b 917 ofp_fatal(str_, verbose, "unknown keyword %s", name);
f22716dc
JP
918 }
919 }
920 }
623e1caf
JP
921 if (!fm->cookie_mask && fm->new_cookie == htonll(UINT64_MAX)
922 && (command == OFPFC_MODIFY || command == OFPFC_MODIFY_STRICT)) {
923 /* On modifies without a mask, we are supposed to add a flow if
924 * one does not exist. If a cookie wasn't been specified, use a
925 * default of zero. */
926 fm->new_cookie = htonll(0);
927 }
75a75043 928 if (fields & F_ACTIONS) {
f25d0cf3 929 struct ofpbuf ofpacts;
75a75043 930
f25d0cf3 931 ofpbuf_init(&ofpacts, 32);
8dd54666 932 str_to_inst_ofpacts(&fm->match.flow, act_str, &ofpacts);
f25d0cf3
BP
933 fm->ofpacts_len = ofpacts.size;
934 fm->ofpacts = ofpbuf_steal_data(&ofpacts);
75a75043 935 } else {
f25d0cf3
BP
936 fm->ofpacts_len = 0;
937 fm->ofpacts = NULL;
75a75043 938 }
ec610b7b
AE
939
940 free(string);
f22716dc 941}
15f1f1b6 942
2b07c8b1
BP
943/* Convert 'str_' (as described in the documentation for the "monitor" command
944 * in the ovs-ofctl man page) into 'fmr'. */
945void
946parse_flow_monitor_request(struct ofputil_flow_monitor_request *fmr,
947 const char *str_)
948{
949 static uint32_t id;
950
951 char *string = xstrdup(str_);
952 char *save_ptr = NULL;
953 char *name;
954
955 fmr->id = id++;
956 fmr->flags = (NXFMF_INITIAL | NXFMF_ADD | NXFMF_DELETE | NXFMF_MODIFY
957 | NXFMF_OWN | NXFMF_ACTIONS);
958 fmr->out_port = OFPP_NONE;
959 fmr->table_id = 0xff;
81a76618 960 match_init_catchall(&fmr->match);
2b07c8b1
BP
961
962 for (name = strtok_r(string, "=, \t\r\n", &save_ptr); name;
963 name = strtok_r(NULL, "=, \t\r\n", &save_ptr)) {
964 const struct protocol *p;
965
966 if (!strcmp(name, "!initial")) {
967 fmr->flags &= ~NXFMF_INITIAL;
968 } else if (!strcmp(name, "!add")) {
969 fmr->flags &= ~NXFMF_ADD;
970 } else if (!strcmp(name, "!delete")) {
971 fmr->flags &= ~NXFMF_DELETE;
972 } else if (!strcmp(name, "!modify")) {
973 fmr->flags &= ~NXFMF_MODIFY;
974 } else if (!strcmp(name, "!actions")) {
975 fmr->flags &= ~NXFMF_ACTIONS;
976 } else if (!strcmp(name, "!own")) {
977 fmr->flags &= ~NXFMF_OWN;
978 } else if (parse_protocol(name, &p)) {
81a76618 979 match_set_dl_type(&fmr->match, htons(p->dl_type));
2b07c8b1 980 if (p->nw_proto) {
81a76618 981 match_set_nw_proto(&fmr->match, p->nw_proto);
2b07c8b1
BP
982 }
983 } else {
984 char *value;
985
986 value = strtok_r(NULL, ", \t\r\n", &save_ptr);
987 if (!value) {
988 ovs_fatal(0, "%s: field %s missing value", str_, name);
989 }
990
991 if (!strcmp(name, "table")) {
992 fmr->table_id = str_to_table_id(value);
993 } else if (!strcmp(name, "out_port")) {
994 fmr->out_port = atoi(value);
995 } else if (mf_from_name(name)) {
996 parse_field(mf_from_name(name), value, &fmr->match);
997 } else {
998 ovs_fatal(0, "%s: unknown keyword %s", str_, name);
999 }
1000 }
1001 }
1002 free(string);
1003}
1004
0c3d5fc8
BP
1005/* Parses 's' as a set of OpenFlow actions and appends the actions to
1006 * 'actions'.
1007 *
1008 * Prints an error on stderr and aborts the program if 's' syntax is
1009 * invalid. */
1010void
f25d0cf3 1011parse_ofpacts(const char *s_, struct ofpbuf *ofpacts)
0c3d5fc8
BP
1012{
1013 char *s = xstrdup(s_);
f25d0cf3 1014 str_to_ofpacts(NULL, s, ofpacts);
0c3d5fc8
BP
1015 free(s);
1016}
1017
88ca35ee 1018/* Parses 'string' as an OFPT_FLOW_MOD or NXT_FLOW_MOD with command 'command'
27527aa0 1019 * (one of OFPFC_*) into 'fm'. */
88ca35ee 1020void
27527aa0 1021parse_ofp_flow_mod_str(struct ofputil_flow_mod *fm, const char *string,
a7fc1744 1022 uint16_t command, bool verbose)
15f1f1b6 1023{
81a76618 1024 struct match match_copy;
88ca35ee 1025
27527aa0 1026 parse_ofp_str(fm, command, string, verbose);
88ca35ee 1027
81a76618 1028 /* Normalize a copy of the match. This ensures that non-normalized flows
01b389b1
BP
1029 * get logged but doesn't affect what gets sent to the switch, so that the
1030 * switch can do whatever it likes with the flow. */
81a76618
BP
1031 match_copy = fm->match;
1032 ofputil_normalize_match(&match_copy);
15f1f1b6
BP
1033}
1034
27527aa0
BP
1035void
1036parse_ofp_flow_mod_file(const char *file_name, uint16_t command,
1037 struct ofputil_flow_mod **fms, size_t *n_fms)
15f1f1b6 1038{
27527aa0
BP
1039 size_t allocated_fms;
1040 FILE *stream;
dd8101bc 1041 struct ds s;
15f1f1b6 1042
27527aa0
BP
1043 stream = !strcmp(file_name, "-") ? stdin : fopen(file_name, "r");
1044 if (stream == NULL) {
1045 ovs_fatal(errno, "%s: open", file_name);
1046 }
1047
1048 allocated_fms = *n_fms;
dd8101bc 1049 ds_init(&s);
27527aa0
BP
1050 while (!ds_get_preprocessed_line(&s, stream)) {
1051 if (*n_fms >= allocated_fms) {
1052 *fms = x2nrealloc(*fms, &allocated_fms, sizeof **fms);
1053 }
1054 parse_ofp_flow_mod_str(&(*fms)[*n_fms], ds_cstr(&s), command, false);
1055 *n_fms += 1;
15f1f1b6
BP
1056 }
1057 ds_destroy(&s);
1058
27527aa0
BP
1059 if (stream != stdin) {
1060 fclose(stream);
1061 }
88ca35ee
BP
1062}
1063
1064void
81d1ea94 1065parse_ofp_flow_stats_request_str(struct ofputil_flow_stats_request *fsr,
a7fc1744 1066 bool aggregate, const char *string)
88ca35ee 1067{
a9a2da38 1068 struct ofputil_flow_mod fm;
88ca35ee 1069
c821124b 1070 parse_ofp_str(&fm, -1, string, false);
88ca35ee 1071 fsr->aggregate = aggregate;
e729e793
JP
1072 fsr->cookie = fm.cookie;
1073 fsr->cookie_mask = fm.cookie_mask;
81a76618 1074 fsr->match = fm.match;
88ca35ee 1075 fsr->out_port = fm.out_port;
6c1491fb 1076 fsr->table_id = fm.table_id;
15f1f1b6 1077}
ccbe50f8
BP
1078
1079/* Parses a specification of a flow from 's' into 'flow'. 's' must take the
1080 * form FIELD=VALUE[,FIELD=VALUE]... where each FIELD is the name of a
1081 * mf_field. Fields must be specified in a natural order for satisfying
1082 * prerequisites.
1083 *
1084 * Returns NULL on success, otherwise a malloc()'d string that explains the
1085 * problem. */
1086char *
1087parse_ofp_exact_flow(struct flow *flow, const char *s)
1088{
1089 char *pos, *key, *value_s;
1090 char *error = NULL;
1091 char *copy;
1092
1093 memset(flow, 0, sizeof *flow);
1094
1095 pos = copy = xstrdup(s);
1096 while (ofputil_parse_key_value(&pos, &key, &value_s)) {
1097 const struct protocol *p;
1098 if (parse_protocol(key, &p)) {
1099 if (flow->dl_type) {
1100 error = xasprintf("%s: Ethernet type set multiple times", s);
1101 goto exit;
1102 }
1103 flow->dl_type = htons(p->dl_type);
1104
1105 if (p->nw_proto) {
1106 if (flow->nw_proto) {
1107 error = xasprintf("%s: network protocol set "
1108 "multiple times", s);
1109 goto exit;
1110 }
1111 flow->nw_proto = p->nw_proto;
1112 }
1113 } else {
1114 const struct mf_field *mf;
1115 union mf_value value;
1116 char *field_error;
1117
1118 mf = mf_from_name(key);
1119 if (!mf) {
1120 error = xasprintf("%s: unknown field %s", s, key);
1121 goto exit;
1122 }
1123
1124 if (!mf_are_prereqs_ok(mf, flow)) {
1125 error = xasprintf("%s: prerequisites not met for setting %s",
1126 s, key);
1127 goto exit;
1128 }
1129
1130 if (!mf_is_zero(mf, flow)) {
1131 error = xasprintf("%s: field %s set multiple times", s, key);
1132 goto exit;
1133 }
1134
1135 field_error = mf_parse_value(mf, value_s, &value);
1136 if (field_error) {
1137 error = xasprintf("%s: bad value for %s (%s)",
1138 s, key, field_error);
1139 free(field_error);
1140 goto exit;
1141 }
1142
1143 mf_set_flow_value(mf, &value, flow);
1144 }
1145 }
1146
1147exit:
1148 free(copy);
1149
1150 if (error) {
1151 memset(flow, 0, sizeof *flow);
1152 }
1153 return error;
1154}