X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fofp-parse.c;h=d563a4e440efc3d24f7611070c418d7ec0cd7e25;hb=b5d97350cdb4559fbce80057574e66daa1ac68df;hp=cc1419a0eb2ad9e34df0818d34e7f974151f759b;hpb=5682f723319241223baa7250ed215e1359dd6d8c;p=openvswitch diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c index cc1419a0..d563a4e4 100644 --- a/lib/ofp-parse.c +++ b/lib/ofp-parse.c @@ -21,6 +21,8 @@ #include #include +#include "byte-order.h" +#include "dynamic-string.h" #include "netdev.h" #include "ofp-util.h" #include "ofpbuf.h" @@ -30,10 +32,7 @@ #include "vconn.h" #include "vlog.h" - -VLOG_DEFINE_THIS_MODULE(ofp_parse) - -#define DEFAULT_IDLE_TIMEOUT 60 +VLOG_DEFINE_THIS_MODULE(ofp_parse); static uint32_t str_to_u32(const char *str) @@ -41,6 +40,10 @@ 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) { @@ -263,16 +266,32 @@ str_to_action(char *str, struct ofpbuf *b) nast->vendor = htonl(NX_VENDOR_ID); nast->subtype = htons(NXAST_SET_TUNNEL); nast->tun_id = htonl(str_to_u32(arg)); + } else if (!strcasecmp(act, "drop_spoofed_arp")) { + struct nx_action_header *nah; + 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")) { char *sp = NULL; - char *port = strtok_r(arg, ":q", &sp); + char *port_s = strtok_r(arg, ":q", &sp); char *queue = strtok_r(NULL, "", &sp); - if (port == NULL || queue == NULL) { + if (port_s == NULL || queue == NULL) { ovs_fatal(0, "\"enqueue\" syntax is \"enqueue:PORT:QUEUE\""); } - put_enqueue_action(b, str_to_u32(port), str_to_u32(queue)); + put_enqueue_action(b, str_to_u32(port_s), str_to_u32(queue)); } else if (!strcasecmp(act, "drop")) { /* A drop action in OpenFlow occurs by just not setting * an action. */ @@ -397,7 +416,7 @@ parse_ofp_str(char *string, struct ofp_match *match, struct ofpbuf *actions, *priority = OFP_DEFAULT_PRIORITY; } if (idle_timeout) { - *idle_timeout = DEFAULT_IDLE_TIMEOUT; + *idle_timeout = OFP_FLOW_PERMANENT; } if (hard_timeout) { *hard_timeout = OFP_FLOW_PERMANENT; @@ -462,10 +481,12 @@ parse_ofp_str(char *string, struct ofp_match *match, struct ofpbuf *actions, 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) { @@ -497,3 +518,65 @@ parse_ofp_str(char *string, struct ofp_match *match, struct ofpbuf *actions, 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; +}