mirror of
https://github.com/openvswitch/ovs
synced 2025-08-30 22:05:19 +00:00
ofp-parse: Do not exit() upon a parse error.
Until now, failure to parse a flow in the ofp-parse module has caused the program to abort immediately with a fatal error. This makes it hard to use these functions from any long-lived program. This commit fixes the problem. Signed-off-by: Ben Pfaff <blp@nicira.com>
This commit is contained in:
58
lib/bundle.c
58
lib/bundle.c
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2011, 2012 Nicira, Inc.
|
||||
/* Copyright (c) 2011, 2012, 2013 Nicira, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -251,8 +251,11 @@ bundle_to_nxast(const struct ofpact_bundle *bundle, struct ofpbuf *openflow)
|
||||
}
|
||||
}
|
||||
|
||||
/* Helper for bundle_parse and bundle_parse_load. */
|
||||
static void
|
||||
/* Helper for bundle_parse and bundle_parse_load.
|
||||
*
|
||||
* Returns NULL if successful, otherwise a malloc()'d string describing the
|
||||
* error. The caller is responsible for freeing the returned string.*/
|
||||
static char * WARN_UNUSED_RESULT
|
||||
bundle_parse__(const char *s, char **save_ptr,
|
||||
const char *fields, const char *basis, const char *algorithm,
|
||||
const char *slave_type, const char *dst,
|
||||
@@ -261,12 +264,12 @@ bundle_parse__(const char *s, char **save_ptr,
|
||||
struct ofpact_bundle *bundle;
|
||||
|
||||
if (!slave_delim) {
|
||||
ovs_fatal(0, "%s: not enough arguments to bundle action", s);
|
||||
return xasprintf("%s: not enough arguments to bundle action", s);
|
||||
}
|
||||
|
||||
if (strcasecmp(slave_delim, "slaves")) {
|
||||
ovs_fatal(0, "%s: missing slave delimiter, expected `slaves' got `%s'",
|
||||
s, slave_delim);
|
||||
return xasprintf("%s: missing slave delimiter, expected `slaves' "
|
||||
"got `%s'", s, slave_delim);
|
||||
}
|
||||
|
||||
bundle = ofpact_put_BUNDLE(ofpacts);
|
||||
@@ -281,7 +284,7 @@ bundle_parse__(const char *s, char **save_ptr,
|
||||
}
|
||||
|
||||
if (!ofputil_port_from_string(slave, &slave_port)) {
|
||||
ovs_fatal(0, "%s: bad port number", slave);
|
||||
return xasprintf("%s: bad port number", slave);
|
||||
}
|
||||
ofpbuf_put(ofpacts, &slave_port, sizeof slave_port);
|
||||
|
||||
@@ -297,7 +300,7 @@ bundle_parse__(const char *s, char **save_ptr,
|
||||
} else if (!strcasecmp(fields, "symmetric_l4")) {
|
||||
bundle->fields = NX_HASH_FIELDS_SYMMETRIC_L4;
|
||||
} else {
|
||||
ovs_fatal(0, "%s: unknown fields `%s'", s, fields);
|
||||
return xasprintf("%s: unknown fields `%s'", s, fields);
|
||||
}
|
||||
|
||||
if (!strcasecmp(algorithm, "active_backup")) {
|
||||
@@ -305,25 +308,34 @@ bundle_parse__(const char *s, char **save_ptr,
|
||||
} else if (!strcasecmp(algorithm, "hrw")) {
|
||||
bundle->algorithm = NX_BD_ALG_HRW;
|
||||
} else {
|
||||
ovs_fatal(0, "%s: unknown algorithm `%s'", s, algorithm);
|
||||
return xasprintf("%s: unknown algorithm `%s'", s, algorithm);
|
||||
}
|
||||
|
||||
if (strcasecmp(slave_type, "ofport")) {
|
||||
ovs_fatal(0, "%s: unknown slave_type `%s'", s, slave_type);
|
||||
return xasprintf("%s: unknown slave_type `%s'", s, slave_type);
|
||||
}
|
||||
|
||||
if (dst) {
|
||||
mf_parse_subfield(&bundle->dst, dst);
|
||||
char *error = mf_parse_subfield(&bundle->dst, dst);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Converts a bundle action string contained in 's' to an nx_action_bundle and
|
||||
* stores it in 'b'. Sets 'b''s l2 pointer to NULL. */
|
||||
void
|
||||
* stores it in 'b'. Sets 'b''s l2 pointer to NULL.
|
||||
*
|
||||
* Returns NULL if successful, otherwise a malloc()'d string describing the
|
||||
* error. The caller is responsible for freeing the returned string. */
|
||||
char * WARN_UNUSED_RESULT
|
||||
bundle_parse(const char *s, struct ofpbuf *ofpacts)
|
||||
{
|
||||
char *fields, *basis, *algorithm, *slave_type, *slave_delim;
|
||||
char *tokstr, *save_ptr;
|
||||
char *error;
|
||||
|
||||
save_ptr = NULL;
|
||||
tokstr = xstrdup(s);
|
||||
@@ -333,18 +345,24 @@ bundle_parse(const char *s, struct ofpbuf *ofpacts)
|
||||
slave_type = strtok_r(NULL, ", ", &save_ptr);
|
||||
slave_delim = strtok_r(NULL, ": ", &save_ptr);
|
||||
|
||||
bundle_parse__(s, &save_ptr, fields, basis, algorithm, slave_type, NULL,
|
||||
slave_delim, ofpacts);
|
||||
error = bundle_parse__(s, &save_ptr, fields, basis, algorithm, slave_type,
|
||||
NULL, slave_delim, ofpacts);
|
||||
free(tokstr);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Converts a bundle_load action string contained in 's' to an nx_action_bundle
|
||||
* and stores it in 'b'. Sets 'b''s l2 pointer to NULL. */
|
||||
void
|
||||
* and stores it in 'b'. Sets 'b''s l2 pointer to NULL.
|
||||
*
|
||||
* Returns NULL if successful, otherwise a malloc()'d string describing the
|
||||
* error. The caller is responsible for freeing the returned string.*/
|
||||
char * WARN_UNUSED_RESULT
|
||||
bundle_parse_load(const char *s, struct ofpbuf *ofpacts)
|
||||
{
|
||||
char *fields, *basis, *algorithm, *slave_type, *dst, *slave_delim;
|
||||
char *tokstr, *save_ptr;
|
||||
char *error;
|
||||
|
||||
save_ptr = NULL;
|
||||
tokstr = xstrdup(s);
|
||||
@@ -355,10 +373,12 @@ bundle_parse_load(const char *s, struct ofpbuf *ofpacts)
|
||||
dst = strtok_r(NULL, ", ", &save_ptr);
|
||||
slave_delim = strtok_r(NULL, ": ", &save_ptr);
|
||||
|
||||
bundle_parse__(s, &save_ptr, fields, basis, algorithm, slave_type, dst,
|
||||
slave_delim, ofpacts);
|
||||
error = bundle_parse__(s, &save_ptr, fields, basis, algorithm, slave_type,
|
||||
dst, slave_delim, ofpacts);
|
||||
|
||||
free(tokstr);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Appends a human-readable representation of 'nab' to 's'. */
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2011, 2012 Nicira, Inc.
|
||||
/* Copyright (c) 2011, 2012, 2013 Nicira, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "compiler.h"
|
||||
#include "ofp-errors.h"
|
||||
#include "openflow/nicira-ext.h"
|
||||
#include "openvswitch/types.h"
|
||||
@@ -44,8 +45,9 @@ enum ofperr bundle_from_openflow(const struct nx_action_bundle *,
|
||||
enum ofperr bundle_check(const struct ofpact_bundle *, ofp_port_t max_ports,
|
||||
const struct flow *);
|
||||
void bundle_to_nxast(const struct ofpact_bundle *, struct ofpbuf *of10);
|
||||
void bundle_parse(const char *, struct ofpbuf *ofpacts);
|
||||
void bundle_parse_load(const char *, struct ofpbuf *ofpacts);
|
||||
char *bundle_parse(const char *, struct ofpbuf *ofpacts) WARN_UNUSED_RESULT;
|
||||
char *bundle_parse_load(const char *, struct ofpbuf *ofpacts)
|
||||
WARN_UNUSED_RESULT;
|
||||
void bundle_format(const struct ofpact_bundle *, struct ds *);
|
||||
|
||||
#endif /* bundle.h */
|
||||
|
@@ -238,14 +238,21 @@ ds_get_line(struct ds *ds, FILE *file)
|
||||
* Deletes comments introduced by "#" and skips lines that contains only white
|
||||
* space (after deleting comments).
|
||||
*
|
||||
* If 'line_numberp' is nonnull, increments '*line_numberp' by the number of
|
||||
* lines read from 'file'.
|
||||
*
|
||||
* Returns 0 if successful, EOF if no non-blank line was found. */
|
||||
int
|
||||
ds_get_preprocessed_line(struct ds *ds, FILE *file)
|
||||
ds_get_preprocessed_line(struct ds *ds, FILE *file, int *line_numberp)
|
||||
{
|
||||
while (!ds_get_line(ds, file)) {
|
||||
char *line = ds_cstr(ds);
|
||||
char *comment;
|
||||
|
||||
if (line_numberp) {
|
||||
++*line_numberp;
|
||||
}
|
||||
|
||||
/* Delete comments. */
|
||||
comment = strchr(line, '#');
|
||||
if (comment) {
|
||||
|
@@ -58,7 +58,7 @@ void ds_put_printable(struct ds *, const char *, size_t);
|
||||
void ds_put_hex_dump(struct ds *ds, const void *buf_, size_t size,
|
||||
uintptr_t ofs, bool ascii);
|
||||
int ds_get_line(struct ds *, FILE *);
|
||||
int ds_get_preprocessed_line(struct ds *, FILE *);
|
||||
int ds_get_preprocessed_line(struct ds *, FILE *, int *line_number);
|
||||
int ds_get_test_line(struct ds *, FILE *);
|
||||
|
||||
void ds_put_strftime(struct ds *, const char *template, time_t when, bool utc)
|
||||
|
121
lib/learn.c
121
lib/learn.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012 Nicira, Inc.
|
||||
* Copyright (c) 2011, 2012, 2013 Nicira, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -390,13 +390,16 @@ learn_mask(const struct ofpact_learn *learn, struct flow_wildcards *wc)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
/* Returns NULL if successful, otherwise a malloc()'d string describing the
|
||||
* error. The caller is responsible for freeing the returned string. */
|
||||
static char * WARN_UNUSED_RESULT
|
||||
learn_parse_load_immediate(const char *s, struct ofpact_learn_spec *spec)
|
||||
{
|
||||
const char *full_s = s;
|
||||
const char *arrow = strstr(s, "->");
|
||||
struct mf_subfield dst;
|
||||
union mf_subvalue imm;
|
||||
char *error;
|
||||
|
||||
memset(&imm, 0, sizeof imm);
|
||||
if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X') && arrow) {
|
||||
@@ -408,7 +411,7 @@ learn_parse_load_immediate(const char *s, struct ofpact_learn_spec *spec)
|
||||
for (i = 0; i < n; i++) {
|
||||
int hexit = hexit_value(in[-i]);
|
||||
if (hexit < 0) {
|
||||
ovs_fatal(0, "%s: bad hex digit in value", full_s);
|
||||
return xasprintf("%s: bad hex digit in value", full_s);
|
||||
}
|
||||
out[-(i / 2)] |= i % 2 ? hexit << 4 : hexit;
|
||||
}
|
||||
@@ -418,19 +421,19 @@ learn_parse_load_immediate(const char *s, struct ofpact_learn_spec *spec)
|
||||
}
|
||||
|
||||
if (strncmp(s, "->", 2)) {
|
||||
ovs_fatal(0, "%s: missing `->' following value", full_s);
|
||||
return xasprintf("%s: missing `->' following value", full_s);
|
||||
}
|
||||
s += 2;
|
||||
|
||||
s = mf_parse_subfield(&dst, s);
|
||||
if (*s != '\0') {
|
||||
ovs_fatal(0, "%s: trailing garbage following destination", full_s);
|
||||
error = mf_parse_subfield(&dst, s);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
if (!bitwise_is_all_zeros(&imm, sizeof imm, dst.n_bits,
|
||||
(8 * sizeof imm) - dst.n_bits)) {
|
||||
ovs_fatal(0, "%s: value does not fit into %u bits",
|
||||
full_s, dst.n_bits);
|
||||
return xasprintf("%s: value does not fit into %u bits",
|
||||
full_s, dst.n_bits);
|
||||
}
|
||||
|
||||
spec->n_bits = dst.n_bits;
|
||||
@@ -438,9 +441,12 @@ learn_parse_load_immediate(const char *s, struct ofpact_learn_spec *spec)
|
||||
spec->src_imm = imm;
|
||||
spec->dst_type = NX_LEARN_DST_LOAD;
|
||||
spec->dst = dst;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
/* Returns NULL if successful, otherwise a malloc()'d string describing the
|
||||
* error. The caller is responsible for freeing the returned string. */
|
||||
static char * WARN_UNUSED_RESULT
|
||||
learn_parse_spec(const char *orig, char *name, char *value,
|
||||
struct ofpact_learn_spec *spec)
|
||||
{
|
||||
@@ -451,7 +457,7 @@ learn_parse_spec(const char *orig, char *name, char *value,
|
||||
|
||||
error = mf_parse_value(dst, value, &imm);
|
||||
if (error) {
|
||||
ovs_fatal(0, "%s", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
spec->n_bits = dst->n_bits;
|
||||
@@ -465,21 +471,23 @@ learn_parse_spec(const char *orig, char *name, char *value,
|
||||
spec->dst.n_bits = dst->n_bits;
|
||||
} else if (strchr(name, '[')) {
|
||||
/* Parse destination and check prerequisites. */
|
||||
if (mf_parse_subfield(&spec->dst, name)[0] != '\0') {
|
||||
ovs_fatal(0, "%s: syntax error after NXM field name `%s'",
|
||||
orig, name);
|
||||
char *error;
|
||||
|
||||
error = mf_parse_subfield(&spec->dst, name);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Parse source and check prerequisites. */
|
||||
if (value[0] != '\0') {
|
||||
if (mf_parse_subfield(&spec->src, value)[0] != '\0') {
|
||||
ovs_fatal(0, "%s: syntax error after NXM field name `%s'",
|
||||
orig, value);
|
||||
error = mf_parse_subfield(&spec->src, value);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
if (spec->src.n_bits != spec->dst.n_bits) {
|
||||
ovs_fatal(0, "%s: bit widths of %s (%u) and %s (%u) differ",
|
||||
orig, name, spec->src.n_bits, value,
|
||||
spec->dst.n_bits);
|
||||
return xasprintf("%s: bit widths of %s (%u) and %s (%u) "
|
||||
"differ", orig, name, spec->src.n_bits, value,
|
||||
spec->dst.n_bits);
|
||||
}
|
||||
} else {
|
||||
spec->src = spec->dst;
|
||||
@@ -490,11 +498,18 @@ learn_parse_spec(const char *orig, char *name, char *value,
|
||||
spec->dst_type = NX_LEARN_DST_MATCH;
|
||||
} else if (!strcmp(name, "load")) {
|
||||
if (value[strcspn(value, "[-")] == '-') {
|
||||
learn_parse_load_immediate(value, spec);
|
||||
char *error = learn_parse_load_immediate(value, spec);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
} else {
|
||||
struct ofpact_reg_move move;
|
||||
char *error;
|
||||
|
||||
nxm_parse_reg_move(&move, value);
|
||||
error = nxm_parse_reg_move(&move, value);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
spec->n_bits = move.src.n_bits;
|
||||
spec->src_type = NX_LEARN_SRC_FIELD;
|
||||
@@ -503,38 +518,29 @@ learn_parse_spec(const char *orig, char *name, char *value,
|
||||
spec->dst = move.dst;
|
||||
}
|
||||
} else if (!strcmp(name, "output")) {
|
||||
if (mf_parse_subfield(&spec->src, value)[0] != '\0') {
|
||||
ovs_fatal(0, "%s: syntax error after NXM field name `%s'",
|
||||
orig, name);
|
||||
char *error = mf_parse_subfield(&spec->src, value);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
spec->n_bits = spec->src.n_bits;
|
||||
spec->src_type = NX_LEARN_SRC_FIELD;
|
||||
spec->dst_type = NX_LEARN_DST_OUTPUT;
|
||||
} else {
|
||||
ovs_fatal(0, "%s: unknown keyword %s", orig, name);
|
||||
return xasprintf("%s: unknown keyword %s", orig, name);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Parses 'arg' as a set of arguments to the "learn" action and appends a
|
||||
* matching OFPACT_LEARN action to 'ofpacts'. ovs-ofctl(8) describes the
|
||||
* format parsed.
|
||||
*
|
||||
* Prints an error on stderr and aborts the program if 'arg' syntax is invalid.
|
||||
*
|
||||
* If 'flow' is nonnull, then it should be the flow from a struct match that is
|
||||
* the matching rule for the learning action. This helps to better validate
|
||||
* the action's arguments.
|
||||
*
|
||||
* Modifies 'arg'. */
|
||||
void
|
||||
learn_parse(char *arg, struct ofpbuf *ofpacts)
|
||||
/* Returns NULL if successful, otherwise a malloc()'d string describing the
|
||||
* error. The caller is responsible for freeing the returned string. */
|
||||
static char * WARN_UNUSED_RESULT
|
||||
learn_parse__(char *orig, char *arg, struct ofpbuf *ofpacts)
|
||||
{
|
||||
char *orig = xstrdup(arg);
|
||||
char *name, *value;
|
||||
|
||||
struct ofpact_learn *learn;
|
||||
struct match match;
|
||||
char *name, *value;
|
||||
|
||||
learn = ofpact_put_LEARN(ofpacts);
|
||||
learn->idle_timeout = OFP_FLOW_PERMANENT;
|
||||
@@ -547,8 +553,8 @@ learn_parse(char *arg, struct ofpbuf *ofpacts)
|
||||
if (!strcmp(name, "table")) {
|
||||
learn->table_id = atoi(value);
|
||||
if (learn->table_id == 255) {
|
||||
ovs_fatal(0, "%s: table id 255 not valid for `learn' action",
|
||||
orig);
|
||||
return xasprintf("%s: table id 255 not valid for `learn' "
|
||||
"action", orig);
|
||||
}
|
||||
} else if (!strcmp(name, "priority")) {
|
||||
learn->priority = atoi(value);
|
||||
@@ -564,12 +570,16 @@ learn_parse(char *arg, struct ofpbuf *ofpacts)
|
||||
learn->cookie = strtoull(value, NULL, 0);
|
||||
} else {
|
||||
struct ofpact_learn_spec *spec;
|
||||
char *error;
|
||||
|
||||
spec = ofpbuf_put_zeros(ofpacts, sizeof *spec);
|
||||
learn = ofpacts->l2;
|
||||
learn->n_specs++;
|
||||
|
||||
learn_parse_spec(orig, name, value, spec);
|
||||
error = learn_parse_spec(orig, name, value, spec);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Update 'match' to allow for satisfying destination
|
||||
* prerequisites. */
|
||||
@@ -581,7 +591,28 @@ learn_parse(char *arg, struct ofpbuf *ofpacts)
|
||||
}
|
||||
ofpact_update_len(ofpacts, &learn->ofpact);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Parses 'arg' as a set of arguments to the "learn" action and appends a
|
||||
* matching OFPACT_LEARN action to 'ofpacts'. ovs-ofctl(8) describes the
|
||||
* format parsed.
|
||||
*
|
||||
* Returns NULL if successful, otherwise a malloc()'d string describing the
|
||||
* error. The caller is responsible for freeing the returned string.
|
||||
*
|
||||
* If 'flow' is nonnull, then it should be the flow from a struct match that is
|
||||
* the matching rule for the learning action. This helps to better validate
|
||||
* the action's arguments.
|
||||
*
|
||||
* Modifies 'arg'. */
|
||||
char * WARN_UNUSED_RESULT
|
||||
learn_parse(char *arg, struct ofpbuf *ofpacts)
|
||||
{
|
||||
char *orig = xstrdup(arg);
|
||||
char *error = learn_parse__(orig, arg, ofpacts);
|
||||
free(orig);
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Appends a description of 'learn' to 's', in the format that ovs-ofctl(8)
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012 Nicira, Inc.
|
||||
* Copyright (c) 2011, 2012, 2013 Nicira, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,6 +17,7 @@
|
||||
#ifndef LEARN_H
|
||||
#define LEARN_H 1
|
||||
|
||||
#include "compiler.h"
|
||||
#include "ofp-errors.h"
|
||||
|
||||
struct ds;
|
||||
@@ -41,7 +42,7 @@ void learn_execute(const struct ofpact_learn *, const struct flow *,
|
||||
struct ofputil_flow_mod *, struct ofpbuf *ofpacts);
|
||||
void learn_mask(const struct ofpact_learn *, struct flow_wildcards *);
|
||||
|
||||
void learn_parse(char *, struct ofpbuf *ofpacts);
|
||||
char *learn_parse(char *, struct ofpbuf *ofpacts) WARN_UNUSED_RESULT;
|
||||
void learn_format(const struct ofpact_learn *, struct ds *);
|
||||
|
||||
#endif /* learn.h */
|
||||
|
@@ -2641,7 +2641,7 @@ mf_parse_subfield_name(const char *name, int name_len, bool *wild)
|
||||
* bit indexes. "..end" may be omitted to indicate a single bit. "start..end"
|
||||
* may both be omitted (the [] are still required) to indicate an entire
|
||||
* field. */
|
||||
char *
|
||||
char * WARN_UNUSED_RESULT
|
||||
mf_parse_subfield__(struct mf_subfield *sf, const char **sp)
|
||||
{
|
||||
const struct mf_field *field;
|
||||
@@ -2696,24 +2696,23 @@ mf_parse_subfield__(struct mf_subfield *sf, const char **sp)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Parses a subfield from the beginning of 's' into 'sf'. Returns the first
|
||||
* byte in 's' following the parsed string.
|
||||
*
|
||||
* Exits with an error message if 's' has incorrect syntax.
|
||||
/* Parses a subfield from the entirety of 's' into 'sf'. Returns NULL if
|
||||
* successful, otherwise a malloc()'d string describing the error. The caller
|
||||
* is responsible for freeing the returned string.
|
||||
*
|
||||
* The syntax parsed from 's' takes the form "header[start..end]" where
|
||||
* 'header' is the name of an NXM field and 'start' and 'end' are (inclusive)
|
||||
* bit indexes. "..end" may be omitted to indicate a single bit. "start..end"
|
||||
* may both be omitted (the [] are still required) to indicate an entire
|
||||
* field. */
|
||||
const char *
|
||||
char * WARN_UNUSED_RESULT
|
||||
mf_parse_subfield(struct mf_subfield *sf, const char *s)
|
||||
{
|
||||
char *msg = mf_parse_subfield__(sf, &s);
|
||||
if (msg) {
|
||||
ovs_fatal(0, "%s", msg);
|
||||
char *error = mf_parse_subfield__(sf, &s);
|
||||
if (!error && s[0]) {
|
||||
error = xstrdup("unexpected input following field syntax");
|
||||
}
|
||||
return s;
|
||||
return error;
|
||||
}
|
||||
|
||||
void
|
||||
|
@@ -360,8 +360,10 @@ uint64_t mf_get_subfield(const struct mf_subfield *, const struct flow *);
|
||||
|
||||
|
||||
void mf_format_subfield(const struct mf_subfield *, struct ds *);
|
||||
char *mf_parse_subfield__(struct mf_subfield *sf, const char **s);
|
||||
const char *mf_parse_subfield(struct mf_subfield *, const char *);
|
||||
char *mf_parse_subfield__(struct mf_subfield *sf, const char **s)
|
||||
WARN_UNUSED_RESULT;
|
||||
char *mf_parse_subfield(struct mf_subfield *, const char *s)
|
||||
WARN_UNUSED_RESULT;
|
||||
|
||||
enum ofperr mf_check_src(const struct mf_subfield *, const struct flow *);
|
||||
enum ofperr mf_check_dst(const struct mf_subfield *, const struct flow *);
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2011, 2012 Nicira, Inc.
|
||||
* Copyright (c) 2010, 2011, 2012, 2013 Nicira, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -195,14 +195,14 @@ multipath_algorithm(uint32_t hash, enum nx_mp_algorithm algorithm,
|
||||
/* Parses 's_' as a set of arguments to the "multipath" action and initializes
|
||||
* 'mp' accordingly. ovs-ofctl(8) describes the format parsed.
|
||||
*
|
||||
* Prints an error on stderr and aborts the program if 's_' syntax is
|
||||
* invalid. */
|
||||
void
|
||||
multipath_parse(struct ofpact_multipath *mp, const char *s_)
|
||||
* Returns NULL if successful, otherwise a malloc()'d string describing the
|
||||
* error. The caller is responsible for freeing the returned string.*/
|
||||
static char * WARN_UNUSED_RESULT
|
||||
multipath_parse__(struct ofpact_multipath *mp, const char *s_, char *s)
|
||||
{
|
||||
char *s = xstrdup(s_);
|
||||
char *save_ptr = NULL;
|
||||
char *fields, *basis, *algorithm, *n_links_str, *arg, *dst;
|
||||
char *error;
|
||||
int n_links;
|
||||
|
||||
fields = strtok_r(s, ", ", &save_ptr);
|
||||
@@ -212,7 +212,7 @@ multipath_parse(struct ofpact_multipath *mp, const char *s_)
|
||||
arg = strtok_r(NULL, ", ", &save_ptr);
|
||||
dst = strtok_r(NULL, ", ", &save_ptr);
|
||||
if (!dst) {
|
||||
ovs_fatal(0, "%s: not enough arguments to multipath action", s_);
|
||||
return xasprintf("%s: not enough arguments to multipath action", s_);
|
||||
}
|
||||
|
||||
ofpact_init_MULTIPATH(mp);
|
||||
@@ -221,7 +221,7 @@ multipath_parse(struct ofpact_multipath *mp, const char *s_)
|
||||
} else if (!strcasecmp(fields, "symmetric_l4")) {
|
||||
mp->fields = NX_HASH_FIELDS_SYMMETRIC_L4;
|
||||
} else {
|
||||
ovs_fatal(0, "%s: unknown fields `%s'", s_, fields);
|
||||
return xasprintf("%s: unknown fields `%s'", s_, fields);
|
||||
}
|
||||
mp->basis = atoi(basis);
|
||||
if (!strcasecmp(algorithm, "modulo_n")) {
|
||||
@@ -233,24 +233,41 @@ multipath_parse(struct ofpact_multipath *mp, const char *s_)
|
||||
} else if (!strcasecmp(algorithm, "iter_hash")) {
|
||||
mp->algorithm = NX_MP_ALG_ITER_HASH;
|
||||
} else {
|
||||
ovs_fatal(0, "%s: unknown algorithm `%s'", s_, algorithm);
|
||||
return xasprintf("%s: unknown algorithm `%s'", s_, algorithm);
|
||||
}
|
||||
n_links = atoi(n_links_str);
|
||||
if (n_links < 1 || n_links > 65536) {
|
||||
ovs_fatal(0, "%s: n_links %d is not in valid range 1 to 65536",
|
||||
s_, n_links);
|
||||
return xasprintf("%s: n_links %d is not in valid range 1 to 65536",
|
||||
s_, n_links);
|
||||
}
|
||||
mp->max_link = n_links - 1;
|
||||
mp->arg = atoi(arg);
|
||||
|
||||
mf_parse_subfield(&mp->dst, dst);
|
||||
error = mf_parse_subfield(&mp->dst, dst);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
if (mp->dst.n_bits < 16 && n_links > (1u << mp->dst.n_bits)) {
|
||||
ovs_fatal(0, "%s: %d-bit destination field has %u possible values, "
|
||||
"less than specified n_links %d",
|
||||
s_, mp->dst.n_bits, 1u << mp->dst.n_bits, n_links);
|
||||
return xasprintf("%s: %d-bit destination field has %u possible "
|
||||
"values, less than specified n_links %d",
|
||||
s_, mp->dst.n_bits, 1u << mp->dst.n_bits, n_links);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Parses 's_' as a set of arguments to the "multipath" action and initializes
|
||||
* 'mp' accordingly. ovs-ofctl(8) describes the format parsed.
|
||||
*
|
||||
* Returns NULL if successful, otherwise a malloc()'d string describing the
|
||||
* error. The caller is responsible for freeing the returned string. */
|
||||
char * WARN_UNUSED_RESULT
|
||||
multipath_parse(struct ofpact_multipath *mp, const char *s_)
|
||||
{
|
||||
char *s = xstrdup(s_);
|
||||
char *error = multipath_parse__(mp, s_, s);
|
||||
free(s);
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Appends a description of 'mp' to 's', in the format that ovs-ofctl(8)
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2011, 2012 Nicira, Inc.
|
||||
* Copyright (c) 2010, 2011, 2012, 2013 Nicira, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,6 +18,7 @@
|
||||
#define MULTIPATH_H 1
|
||||
|
||||
#include <stdint.h>
|
||||
#include "compiler.h"
|
||||
#include "ofp-errors.h"
|
||||
|
||||
struct ds;
|
||||
@@ -42,7 +43,8 @@ void multipath_to_nxast(const struct ofpact_multipath *,
|
||||
void multipath_execute(const struct ofpact_multipath *, struct flow *,
|
||||
struct flow_wildcards *);
|
||||
|
||||
void multipath_parse(struct ofpact_multipath *, const char *);
|
||||
char *multipath_parse(struct ofpact_multipath *, const char *)
|
||||
WARN_UNUSED_RESULT;
|
||||
void multipath_format(const struct ofpact_multipath *, struct ds *);
|
||||
|
||||
#endif /* multipath.h */
|
||||
|
@@ -1004,50 +1004,67 @@ oxm_match_from_string(const char *s, struct ofpbuf *b)
|
||||
return match_len;
|
||||
}
|
||||
|
||||
void
|
||||
/* Parses 's' as a "move" action, in the form described in ovs-ofctl(8), into
|
||||
* '*move'.
|
||||
*
|
||||
* Returns NULL if successful, otherwise a malloc()'d string describing the
|
||||
* error. The caller is responsible for freeing the returned string. */
|
||||
char * WARN_UNUSED_RESULT
|
||||
nxm_parse_reg_move(struct ofpact_reg_move *move, const char *s)
|
||||
{
|
||||
const char *full_s = s;
|
||||
char *error;
|
||||
|
||||
s = mf_parse_subfield(&move->src, s);
|
||||
error = mf_parse_subfield__(&move->src, &s);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
if (strncmp(s, "->", 2)) {
|
||||
ovs_fatal(0, "%s: missing `->' following source", full_s);
|
||||
return xasprintf("%s: missing `->' following source", full_s);
|
||||
}
|
||||
s += 2;
|
||||
s = mf_parse_subfield(&move->dst, s);
|
||||
if (*s != '\0') {
|
||||
ovs_fatal(0, "%s: trailing garbage following destination", full_s);
|
||||
error = mf_parse_subfield(&move->dst, s);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
if (move->src.n_bits != move->dst.n_bits) {
|
||||
ovs_fatal(0, "%s: source field is %d bits wide but destination is "
|
||||
"%d bits wide", full_s,
|
||||
move->src.n_bits, move->dst.n_bits);
|
||||
return xasprintf("%s: source field is %d bits wide but destination is "
|
||||
"%d bits wide", full_s,
|
||||
move->src.n_bits, move->dst.n_bits);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
/* Parses 's' as a "load" action, in the form described in ovs-ofctl(8), into
|
||||
* '*load'.
|
||||
*
|
||||
* Returns NULL if successful, otherwise a malloc()'d string describing the
|
||||
* error. The caller is responsible for freeing the returned string. */
|
||||
char * WARN_UNUSED_RESULT
|
||||
nxm_parse_reg_load(struct ofpact_reg_load *load, const char *s)
|
||||
{
|
||||
const char *full_s = s;
|
||||
uint64_t value = strtoull(s, (char **) &s, 0);
|
||||
char *error;
|
||||
|
||||
if (strncmp(s, "->", 2)) {
|
||||
ovs_fatal(0, "%s: missing `->' following value", full_s);
|
||||
return xasprintf("%s: missing `->' following value", full_s);
|
||||
}
|
||||
s += 2;
|
||||
s = mf_parse_subfield(&load->dst, s);
|
||||
if (*s != '\0') {
|
||||
ovs_fatal(0, "%s: trailing garbage following destination", full_s);
|
||||
error = mf_parse_subfield(&load->dst, s);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
if (load->dst.n_bits < 64 && (value >> load->dst.n_bits) != 0) {
|
||||
ovs_fatal(0, "%s: value %"PRIu64" does not fit into %d bits",
|
||||
full_s, value, load->dst.n_bits);
|
||||
return xasprintf("%s: value %"PRIu64" does not fit into %d bits",
|
||||
full_s, value, load->dst.n_bits);
|
||||
}
|
||||
|
||||
load->subvalue.be64[0] = htonll(0);
|
||||
load->subvalue.be64[1] = htonll(value);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* nxm_format_reg_move(), nxm_format_reg_load(). */
|
||||
@@ -1316,13 +1333,27 @@ nxm_reg_load(const struct mf_subfield *dst, uint64_t src_data,
|
||||
}
|
||||
|
||||
/* nxm_parse_stack_action, works for both push() and pop(). */
|
||||
void
|
||||
|
||||
/* Parses 's' as a "push" or "pop" action, in the form described in
|
||||
* ovs-ofctl(8), into '*stack_action'.
|
||||
*
|
||||
* Returns NULL if successful, otherwise a malloc()'d string describing the
|
||||
* error. The caller is responsible for freeing the returned string. */
|
||||
char * WARN_UNUSED_RESULT
|
||||
nxm_parse_stack_action(struct ofpact_stack *stack_action, const char *s)
|
||||
{
|
||||
s = mf_parse_subfield(&stack_action->subfield, s);
|
||||
if (*s != '\0') {
|
||||
ovs_fatal(0, "%s: trailing garbage following push or pop", s);
|
||||
char *error;
|
||||
|
||||
error = mf_parse_subfield__(&stack_action->subfield, &s);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
if (*s != '\0') {
|
||||
return xasprintf("%s: trailing garbage following push or pop", s);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2011, 2012 Nicira, Inc.
|
||||
* Copyright (c) 2010, 2011, 2012, 2013 Nicira, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include "compiler.h"
|
||||
#include "flow.h"
|
||||
#include "ofp-errors.h"
|
||||
#include "openvswitch/types.h"
|
||||
@@ -57,8 +58,10 @@ char *oxm_match_to_string(const uint8_t *, unsigned int match_len);
|
||||
int nx_match_from_string(const char *, struct ofpbuf *);
|
||||
int oxm_match_from_string(const char *, struct ofpbuf *);
|
||||
|
||||
void nxm_parse_reg_move(struct ofpact_reg_move *, const char *);
|
||||
void nxm_parse_reg_load(struct ofpact_reg_load *, const char *);
|
||||
char *nxm_parse_reg_move(struct ofpact_reg_move *, const char *)
|
||||
WARN_UNUSED_RESULT;
|
||||
char *nxm_parse_reg_load(struct ofpact_reg_load *, const char *)
|
||||
WARN_UNUSED_RESULT;
|
||||
|
||||
void nxm_format_reg_move(const struct ofpact_reg_move *, struct ds *);
|
||||
void nxm_format_reg_load(const struct ofpact_reg_load *, struct ds *);
|
||||
@@ -86,7 +89,8 @@ void nxm_execute_reg_load(const struct ofpact_reg_load *, struct flow *);
|
||||
void nxm_reg_load(const struct mf_subfield *, uint64_t src_data,
|
||||
struct flow *);
|
||||
|
||||
void nxm_parse_stack_action(struct ofpact_stack *, const char *);
|
||||
char *nxm_parse_stack_action(struct ofpact_stack *, const char *)
|
||||
WARN_UNUSED_RESULT;
|
||||
|
||||
void nxm_format_stack_push(const struct ofpact_stack *, struct ds *);
|
||||
void nxm_format_stack_pop(const struct ofpact_stack *, struct ds *);
|
||||
|
942
lib/ofp-parse.c
942
lib/ofp-parse.c
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2011, 2012 Nicira, Inc.
|
||||
* Copyright (c) 2010, 2011, 2012, 2013 Nicira, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "compiler.h"
|
||||
|
||||
struct flow;
|
||||
struct ofpbuf;
|
||||
@@ -30,26 +31,31 @@ struct ofputil_flow_monitor_request;
|
||||
struct ofputil_flow_stats_request;
|
||||
struct ofputil_meter_mod;
|
||||
|
||||
void parse_ofp_str(struct ofputil_flow_mod *, int command, const char *str_,
|
||||
bool verbose);
|
||||
char *parse_ofp_str(struct ofputil_flow_mod *, int command, const char *str_)
|
||||
WARN_UNUSED_RESULT;
|
||||
|
||||
void parse_ofp_flow_mod_str(struct ofputil_flow_mod *, const char *string,
|
||||
uint16_t command, bool verbose);
|
||||
void parse_ofp_flow_mod_file(const char *file_name, uint16_t command,
|
||||
struct ofputil_flow_mod **fms, size_t *n_fms);
|
||||
char *parse_ofp_flow_mod_str(struct ofputil_flow_mod *, const char *string,
|
||||
uint16_t command)
|
||||
WARN_UNUSED_RESULT;
|
||||
char *parse_ofp_flow_mod_file(const char *file_name, uint16_t command,
|
||||
struct ofputil_flow_mod **fms, size_t *n_fms)
|
||||
WARN_UNUSED_RESULT;
|
||||
|
||||
void parse_ofp_flow_stats_request_str(struct ofputil_flow_stats_request *,
|
||||
bool aggregate, const char *string);
|
||||
char *parse_ofp_flow_stats_request_str(struct ofputil_flow_stats_request *,
|
||||
bool aggregate, const char *string)
|
||||
WARN_UNUSED_RESULT;
|
||||
|
||||
|
||||
void parse_ofpacts(const char *, struct ofpbuf *ofpacts);
|
||||
char *parse_ofpacts(const char *, struct ofpbuf *ofpacts)
|
||||
WARN_UNUSED_RESULT;
|
||||
|
||||
char *parse_ofp_exact_flow(struct flow *, const char *);
|
||||
|
||||
void parse_ofp_meter_mod_str(struct ofputil_meter_mod *, const char *string,
|
||||
int command, bool verbose);
|
||||
char *parse_ofp_meter_mod_str(struct ofputil_meter_mod *, const char *string,
|
||||
int command)
|
||||
WARN_UNUSED_RESULT;
|
||||
|
||||
void parse_flow_monitor_request(struct ofputil_flow_monitor_request *,
|
||||
const char *);
|
||||
char *parse_flow_monitor_request(struct ofputil_flow_monitor_request *,
|
||||
const char *)
|
||||
WARN_UNUSED_RESULT;
|
||||
|
||||
#endif /* ofp-parse.h */
|
||||
|
@@ -75,11 +75,13 @@ AT_CHECK([[ovs-ofctl parse-flow 'actions=learn(load:5->NXM_OF_IP_DST[])']],
|
||||
[1], [], [stderr])
|
||||
AT_CHECK([sed -e 's/.*|meta_flow|WARN|//' < stderr], [0],
|
||||
[[destination field ip_dst lacks correct prerequisites
|
||||
ovs-ofctl: actions are invalid with specified match (OFPBAC_BAD_ARGUMENT)
|
||||
]], [[]])
|
||||
AT_CHECK([[ovs-ofctl parse-flow 'actions=learn(load:NXM_OF_IP_DST[]->NXM_NX_REG1[])']],
|
||||
[1], [], [stderr])
|
||||
AT_CHECK([sed -e 's/.*|meta_flow|WARN|//' < stderr], [0],
|
||||
[[source field ip_dst lacks correct prerequisites
|
||||
ovs-ofctl: actions are invalid with specified match (OFPBAC_BAD_ARGUMENT)
|
||||
]])
|
||||
AT_CLEANUP
|
||||
|
||||
|
@@ -166,7 +166,7 @@ AT_SETUP([ofproto-dpif - DSCP])
|
||||
OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=dummy])
|
||||
ADD_OF_PORTS([br0], [9])
|
||||
AT_DATA([flows.txt], [dnl
|
||||
actions=output:65534,enqueue:1:1,enqueue:1:2,enqueue:1:2,enqueue:1:1,output:1,mod_nw_tos:0,output:1,output:65534
|
||||
actions=output:LOCAL,enqueue:1:1,enqueue:1:2,enqueue:1:2,enqueue:1:1,output:1,mod_nw_tos:0,output:1,output:LOCAL
|
||||
])
|
||||
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
|
||||
AT_CHECK([ovs-vsctl -- \
|
||||
@@ -197,8 +197,8 @@ AT_DATA([flows.txt], [dnl
|
||||
in_port=local actions=local,flood
|
||||
in_port=1 actions=flood
|
||||
in_port=2 actions=all
|
||||
in_port=3 actions=output:65534,output:1,output:2,output:3,output:4,output:5,output:6,output:7
|
||||
in_port=4 actions=enqueue:65534:1,enqueue:1:1,enqueue:2:1,enqueue:3:2,enqueue:4:1,enqueue:5:1,enqueue:6:1,enqueue:7:1
|
||||
in_port=3 actions=output:LOCAL,output:1,output:2,output:3,output:4,output:5,output:6,output:7
|
||||
in_port=4 actions=enqueue:LOCAL:1,enqueue:1:1,enqueue:2:1,enqueue:3:2,enqueue:4:1,enqueue:5:1,enqueue:6:1,enqueue:7:1
|
||||
])
|
||||
AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
|
||||
AT_CHECK([ovs-ofctl mod-port br0 5 noforward])
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2011, 2012 Nicira, Inc.
|
||||
/* Copyright (c) 2011, 2012, 2013 Nicira, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -71,9 +71,14 @@ parse_bundle_actions(char *actions)
|
||||
struct ofpact_bundle *bundle;
|
||||
struct ofpbuf ofpacts;
|
||||
struct ofpact *action;
|
||||
char *error;
|
||||
|
||||
ofpbuf_init(&ofpacts, 0);
|
||||
bundle_parse_load(actions, &ofpacts);
|
||||
error = bundle_parse_load(actions, &ofpacts);
|
||||
if (error) {
|
||||
ovs_fatal(0, "%s", error);
|
||||
}
|
||||
|
||||
action = ofpacts.data;
|
||||
bundle = ofpact_get_BUNDLE(xmemdup(action, action->len));
|
||||
ofpbuf_uninit(&ofpacts);
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2012 Nicira, Inc.
|
||||
* Copyright (c) 2010, 2012, 2013 Nicira, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -35,6 +35,7 @@ main(int argc, char *argv[])
|
||||
enum { MP_MAX_LINKS = 63 };
|
||||
struct ofpact_multipath mp;
|
||||
bool ok = true;
|
||||
char *error;
|
||||
int n;
|
||||
|
||||
set_program_name(argv[0]);
|
||||
@@ -44,7 +45,11 @@ main(int argc, char *argv[])
|
||||
ovs_fatal(0, "usage: %s multipath_action", program_name);
|
||||
}
|
||||
|
||||
multipath_parse(&mp, argv[1]);
|
||||
error = multipath_parse(&mp, argv[1]);
|
||||
if (error) {
|
||||
ovs_fatal(0, "%s", error);
|
||||
}
|
||||
|
||||
for (n = 1; n <= MP_MAX_LINKS; n++) {
|
||||
enum { N_FLOWS = 65536 };
|
||||
double disruption, perfect, distribution;
|
||||
|
@@ -278,6 +278,7 @@ parse_options(int argc, char *argv[])
|
||||
|
||||
for (;;) {
|
||||
int indexptr;
|
||||
char *error;
|
||||
int c;
|
||||
|
||||
c = getopt_long(argc, argv, short_options, long_options, &indexptr);
|
||||
@@ -327,8 +328,11 @@ parse_options(int argc, char *argv[])
|
||||
break;
|
||||
|
||||
case OPT_WITH_FLOWS:
|
||||
parse_ofp_flow_mod_file(optarg, OFPFC_ADD, &default_flows,
|
||||
&n_default_flows);
|
||||
error = parse_ofp_flow_mod_file(optarg, OFPFC_ADD, &default_flows,
|
||||
&n_default_flows);
|
||||
if (error) {
|
||||
ovs_fatal(0, "%s", error);
|
||||
}
|
||||
break;
|
||||
|
||||
case OPT_UNIXCTL:
|
||||
|
@@ -866,8 +866,14 @@ prepare_dump_flows(int argc, char *argv[], bool aggregate,
|
||||
enum ofputil_protocol usable_protocols, protocol;
|
||||
struct ofputil_flow_stats_request fsr;
|
||||
struct vconn *vconn;
|
||||
char *error;
|
||||
|
||||
error = parse_ofp_flow_stats_request_str(&fsr, aggregate,
|
||||
argc > 2 ? argv[2] : "");
|
||||
if (error) {
|
||||
ovs_fatal(0, "%s", error);
|
||||
}
|
||||
|
||||
parse_ofp_flow_stats_request_str(&fsr, aggregate, argc > 2 ? argv[2] : "");
|
||||
usable_protocols = ofputil_flow_stats_request_usable_protocols(&fsr);
|
||||
|
||||
protocol = open_vconn(argv[1], &vconn);
|
||||
@@ -1087,8 +1093,12 @@ ofctl_flow_mod_file(int argc OVS_UNUSED, char *argv[], uint16_t command)
|
||||
{
|
||||
struct ofputil_flow_mod *fms = NULL;
|
||||
size_t n_fms = 0;
|
||||
char *error;
|
||||
|
||||
parse_ofp_flow_mod_file(argv[2], command, &fms, &n_fms);
|
||||
error = parse_ofp_flow_mod_file(argv[2], command, &fms, &n_fms);
|
||||
if (error) {
|
||||
ovs_fatal(0, "%s", error);
|
||||
}
|
||||
ofctl_flow_mod__(argv[1], fms, n_fms);
|
||||
free(fms);
|
||||
}
|
||||
@@ -1100,7 +1110,12 @@ ofctl_flow_mod(int argc, char *argv[], uint16_t command)
|
||||
ofctl_flow_mod_file(argc, argv, command);
|
||||
} else {
|
||||
struct ofputil_flow_mod fm;
|
||||
parse_ofp_flow_mod_str(&fm, argc > 2 ? argv[2] : "", command, false);
|
||||
char *error;
|
||||
|
||||
error = parse_ofp_flow_mod_str(&fm, argc > 2 ? argv[2] : "", command);
|
||||
if (error) {
|
||||
ovs_fatal(0, "%s", error);
|
||||
}
|
||||
ofctl_flow_mod__(argv[1], &fm, 1);
|
||||
}
|
||||
}
|
||||
@@ -1439,8 +1454,12 @@ ofctl_monitor(int argc, char *argv[])
|
||||
} else if (!strncmp(arg, "watch:", 6)) {
|
||||
struct ofputil_flow_monitor_request fmr;
|
||||
struct ofpbuf *msg;
|
||||
char *error;
|
||||
|
||||
parse_flow_monitor_request(&fmr, arg + 6);
|
||||
error = parse_flow_monitor_request(&fmr, arg + 6);
|
||||
if (error) {
|
||||
ovs_fatal(0, "%s", error);
|
||||
}
|
||||
|
||||
msg = ofpbuf_new(0);
|
||||
ofputil_append_flow_monitor_request(&fmr, msg);
|
||||
@@ -1538,10 +1557,14 @@ ofctl_packet_out(int argc, char *argv[])
|
||||
struct ofputil_packet_out po;
|
||||
struct ofpbuf ofpacts;
|
||||
struct vconn *vconn;
|
||||
char *error;
|
||||
int i;
|
||||
|
||||
ofpbuf_init(&ofpacts, 64);
|
||||
parse_ofpacts(argv[3], &ofpacts);
|
||||
error = parse_ofpacts(argv[3], &ofpacts);
|
||||
if (error) {
|
||||
ovs_fatal(0, "%s", error);
|
||||
}
|
||||
|
||||
po.buffer_id = UINT32_MAX;
|
||||
po.in_port = str_to_port_no(argv[1], argv[2]);
|
||||
@@ -1905,6 +1928,7 @@ static enum ofputil_protocol
|
||||
read_flows_from_file(const char *filename, struct classifier *cls, int index)
|
||||
{
|
||||
enum ofputil_protocol usable_protocols;
|
||||
int line_number;
|
||||
struct ds s;
|
||||
FILE *file;
|
||||
|
||||
@@ -1915,11 +1939,16 @@ read_flows_from_file(const char *filename, struct classifier *cls, int index)
|
||||
|
||||
ds_init(&s);
|
||||
usable_protocols = OFPUTIL_P_ANY;
|
||||
while (!ds_get_preprocessed_line(&s, file)) {
|
||||
line_number = 0;
|
||||
while (!ds_get_preprocessed_line(&s, file, &line_number)) {
|
||||
struct fte_version *version;
|
||||
struct ofputil_flow_mod fm;
|
||||
char *error;
|
||||
|
||||
parse_ofp_str(&fm, OFPFC_ADD, ds_cstr(&s), true);
|
||||
error = parse_ofp_str(&fm, OFPFC_ADD, ds_cstr(&s));
|
||||
if (error) {
|
||||
ovs_fatal(0, "%s:%d: %s", filename, line_number, error);
|
||||
}
|
||||
|
||||
version = xmalloc(sizeof *version);
|
||||
version->cookie = fm.new_cookie;
|
||||
@@ -2232,8 +2261,12 @@ static void
|
||||
ofctl_parse_flow(int argc OVS_UNUSED, char *argv[])
|
||||
{
|
||||
struct ofputil_flow_mod fm;
|
||||
char *error;
|
||||
|
||||
parse_ofp_flow_mod_str(&fm, argv[1], OFPFC_ADD, false);
|
||||
error = parse_ofp_flow_mod_str(&fm, argv[1], OFPFC_ADD);
|
||||
if (error) {
|
||||
ovs_fatal(0, "%s", error);
|
||||
}
|
||||
ofctl_parse_flows__(&fm, 1);
|
||||
}
|
||||
|
||||
@@ -2244,8 +2277,12 @@ ofctl_parse_flows(int argc OVS_UNUSED, char *argv[])
|
||||
{
|
||||
struct ofputil_flow_mod *fms = NULL;
|
||||
size_t n_fms = 0;
|
||||
char *error;
|
||||
|
||||
parse_ofp_flow_mod_file(argv[1], OFPFC_ADD, &fms, &n_fms);
|
||||
error = parse_ofp_flow_mod_file(argv[1], OFPFC_ADD, &fms, &n_fms);
|
||||
if (error) {
|
||||
ovs_fatal(0, "%s", error);
|
||||
}
|
||||
ofctl_parse_flows__(fms, n_fms);
|
||||
free(fms);
|
||||
}
|
||||
@@ -2367,7 +2404,7 @@ ofctl_parse_ofp10_actions(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
|
||||
struct ds in;
|
||||
|
||||
ds_init(&in);
|
||||
while (!ds_get_preprocessed_line(&in, stdin)) {
|
||||
while (!ds_get_preprocessed_line(&in, stdin, NULL)) {
|
||||
struct ofpbuf of10_out;
|
||||
struct ofpbuf of10_in;
|
||||
struct ofpbuf ofpacts;
|
||||
@@ -2431,7 +2468,7 @@ ofctl_parse_ofp10_match(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
|
||||
|
||||
ds_init(&in);
|
||||
ds_init(&expout);
|
||||
while (!ds_get_preprocessed_line(&in, stdin)) {
|
||||
while (!ds_get_preprocessed_line(&in, stdin, NULL)) {
|
||||
struct ofpbuf match_in, match_expout;
|
||||
struct ofp10_match match_out;
|
||||
struct ofp10_match match_normal;
|
||||
@@ -2503,7 +2540,7 @@ ofctl_parse_ofp11_match(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
|
||||
struct ds in;
|
||||
|
||||
ds_init(&in);
|
||||
while (!ds_get_preprocessed_line(&in, stdin)) {
|
||||
while (!ds_get_preprocessed_line(&in, stdin, NULL)) {
|
||||
struct ofpbuf match_in;
|
||||
struct ofp11_match match_out;
|
||||
struct match match;
|
||||
@@ -2552,7 +2589,7 @@ ofctl_parse_ofp11_actions(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
|
||||
struct ds in;
|
||||
|
||||
ds_init(&in);
|
||||
while (!ds_get_preprocessed_line(&in, stdin)) {
|
||||
while (!ds_get_preprocessed_line(&in, stdin, NULL)) {
|
||||
struct ofpbuf of11_out;
|
||||
struct ofpbuf of11_in;
|
||||
struct ofpbuf ofpacts;
|
||||
@@ -2610,7 +2647,7 @@ ofctl_parse_ofp11_instructions(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
|
||||
struct ds in;
|
||||
|
||||
ds_init(&in);
|
||||
while (!ds_get_preprocessed_line(&in, stdin)) {
|
||||
while (!ds_get_preprocessed_line(&in, stdin, NULL)) {
|
||||
struct ofpbuf of11_out;
|
||||
struct ofpbuf of11_in;
|
||||
struct ofpbuf ofpacts;
|
||||
@@ -2699,6 +2736,7 @@ ofctl_check_vlan(int argc OVS_UNUSED, char *argv[])
|
||||
struct match of11_match;
|
||||
|
||||
enum ofperr error;
|
||||
char *error_s;
|
||||
|
||||
match_init_catchall(&match);
|
||||
match.flow.vlan_tci = htons(strtoul(argv[1], NULL, 16));
|
||||
@@ -2708,7 +2746,10 @@ ofctl_check_vlan(int argc OVS_UNUSED, char *argv[])
|
||||
string_s = match_to_string(&match, OFP_DEFAULT_PRIORITY);
|
||||
printf("%s -> ", string_s);
|
||||
fflush(stdout);
|
||||
parse_ofp_str(&fm, -1, string_s, false);
|
||||
error_s = parse_ofp_str(&fm, -1, string_s);
|
||||
if (error_s) {
|
||||
ovs_fatal(0, "%s", error_s);
|
||||
}
|
||||
printf("%04"PRIx16"/%04"PRIx16"\n",
|
||||
ntohs(fm.match.flow.vlan_tci),
|
||||
ntohs(fm.match.wc.masks.vlan_tci));
|
||||
|
Reference in New Issue
Block a user