#include <errno.h>
#include <stdlib.h>
+#include "byte-order.h"
+#include "dynamic-string.h"
#include "netdev.h"
#include "ofp-util.h"
#include "ofpbuf.h"
#include "vconn.h"
#include "vlog.h"
-
-VLOG_DEFINE_THIS_MODULE(ofp_parse)
+VLOG_DEFINE_THIS_MODULE(ofp_parse);
static uint32_t
str_to_u32(const char *str)
char *tail;
uint32_t value;
+ if (!str) {
+ ovs_fatal(0, "missing required numeric argument");
+ }
+
errno = 0;
value = strtoul(str, &tail, 0);
if (errno == EINVAL || errno == ERANGE || *tail) {
nah = put_action(b, sizeof *nah, OFPAT_VENDOR);
nah->vendor = htonl(NX_VENDOR_ID);
nah->subtype = htons(NXAST_DROP_SPOOFED_ARP);
+ } else if (!strcasecmp(act, "set_queue")) {
+ struct nx_action_set_queue *nasq;
+ nasq = put_action(b, sizeof *nasq, OFPAT_VENDOR);
+ nasq->vendor = htonl(NX_VENDOR_ID);
+ nasq->subtype = htons(NXAST_SET_QUEUE);
+ nasq->queue_id = htonl(str_to_u32(arg));
+ } else if (!strcasecmp(act, "pop_queue")) {
+ struct nx_action_header *nah;
+ nah = put_action(b, sizeof *nah, OFPAT_VENDOR);
+ nah->vendor = htonl(NX_VENDOR_ID);
+ nah->subtype = htons(NXAST_POP_QUEUE);
} else if (!strcasecmp(act, "output")) {
put_output_action(b, str_to_u32(arg));
} else if (!strcasecmp(act, "enqueue")) {
if (!strcmp(value, "*") || !strcmp(value, "ANY")) {
wildcards |= f->wildcard;
} else {
+ uint16_t port_no;
+
wildcards &= ~f->wildcard;
if (f->wildcard == OFPFW_IN_PORT
- && parse_port_name(value, (uint16_t *) data)) {
- /* Nothing to do. */
+ && parse_port_name(value, &port_no)) {
+ match->in_port = htons(port_no);
} else if (f->type == F_U8) {
*(uint8_t *) data = str_to_u32(value);
} else if (f->type == F_U16) {
free(new);
}
}
+
+/* Parses 'string' as a OFPT_FLOW_MOD with subtype OFPFC_ADD and returns an
+ * ofpbuf that contains it. */
+struct ofpbuf *
+parse_ofp_add_flow_str(char *string)
+{
+ struct ofpbuf *buffer;
+ struct ofp_flow_mod *ofm;
+ uint16_t priority, idle_timeout, hard_timeout;
+ uint64_t cookie;
+ struct ofp_match match;
+
+ /* parse_ofp_str() will expand and reallocate the data in 'buffer', so we
+ * can't keep pointers to across the parse_ofp_str() call. */
+ make_openflow(sizeof *ofm, OFPT_FLOW_MOD, &buffer);
+ parse_ofp_str(string, &match, buffer,
+ NULL, NULL, &priority, &idle_timeout, &hard_timeout,
+ &cookie);
+ ofm = buffer->data;
+ ofm->match = match;
+ ofm->command = htons(OFPFC_ADD);
+ ofm->cookie = htonll(cookie);
+ ofm->idle_timeout = htons(idle_timeout);
+ ofm->hard_timeout = htons(hard_timeout);
+ ofm->buffer_id = htonl(UINT32_MAX);
+ ofm->priority = htons(priority);
+ update_openflow_length(buffer);
+
+ return buffer;
+}
+
+/* Parses an OFPT_FLOW_MOD with subtype OFPFC_ADD from 'stream' and returns an
+ * ofpbuf that contains it. Returns a null pointer if end-of-file is reached
+ * before reading a flow. */
+struct ofpbuf *
+parse_ofp_add_flow_file(FILE *stream)
+{
+ struct ofpbuf *b = NULL;
+ struct ds s = DS_EMPTY_INITIALIZER;
+
+ while (!ds_get_line(&s, stream)) {
+ char *line = ds_cstr(&s);
+ char *comment;
+
+ /* Delete comments. */
+ comment = strchr(line, '#');
+ if (comment) {
+ *comment = '\0';
+ }
+
+ /* Drop empty lines. */
+ if (line[strspn(line, " \t\n")] == '\0') {
+ continue;
+ }
+
+ b = parse_ofp_add_flow_str(line);
+ break;
+ }
+ ds_destroy(&s);
+
+ return b;
+}