2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-31 22:35:15 +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:
Ben Pfaff
2013-07-08 10:15:00 -07:00
parent 5ed2d819bb
commit bdda5aca7b
20 changed files with 991 additions and 456 deletions

View File

@@ -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'. */