X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fofp-parse.c;h=034a6de6948fb5ed2ce3c7c62cd6f041c85211c0;hb=d58c5bc2d854ce601338d0785c8086d619a16135;hp=c630ccd1a08ca63ed78f0d4795bbf3302ac94400;hpb=27527aa09ce456796eeea728cef9528aa5612b70;p=openvswitch diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c index c630ccd1..034a6de6 100644 --- a/lib/ofp-parse.c +++ b/lib/ofp-parse.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011, 2012 Nicira Networks. + * Copyright (c) 2010, 2011, 2012 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -124,7 +124,7 @@ put_output_action(struct ofpbuf *b, uint16_t port) { struct ofp_action_output *oao; - oao = ofputil_put_OFPAT_OUTPUT(b); + oao = ofputil_put_OFPAT10_OUTPUT(b); oao->port = htons(port); return oao; } @@ -141,7 +141,7 @@ parse_enqueue(struct ofpbuf *b, char *arg) ovs_fatal(0, "\"enqueue\" syntax is \"enqueue:PORT:QUEUE\""); } - oae = ofputil_put_OFPAT_ENQUEUE(b); + oae = ofputil_put_OFPAT10_ENQUEUE(b); oae->port = htons(str_to_u32(port)); oae->queue_id = htonl(str_to_u32(queue)); } @@ -320,47 +320,47 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow, struct ofp_action_tp_port *oata; switch (code) { - case OFPUTIL_OFPAT_OUTPUT: + case OFPUTIL_OFPAT10_OUTPUT: parse_output(b, arg); break; - case OFPUTIL_OFPAT_SET_VLAN_VID: - oavv = ofputil_put_OFPAT_SET_VLAN_VID(b); + case OFPUTIL_OFPAT10_SET_VLAN_VID: + oavv = ofputil_put_OFPAT10_SET_VLAN_VID(b); oavv->vlan_vid = htons(str_to_u32(arg)); break; - case OFPUTIL_OFPAT_SET_VLAN_PCP: - oavp = ofputil_put_OFPAT_SET_VLAN_PCP(b); + case OFPUTIL_OFPAT10_SET_VLAN_PCP: + oavp = ofputil_put_OFPAT10_SET_VLAN_PCP(b); oavp->vlan_pcp = str_to_u32(arg); break; - case OFPUTIL_OFPAT_STRIP_VLAN: - ofputil_put_OFPAT_STRIP_VLAN(b); + case OFPUTIL_OFPAT10_STRIP_VLAN: + ofputil_put_OFPAT10_STRIP_VLAN(b); break; - case OFPUTIL_OFPAT_SET_DL_SRC: - case OFPUTIL_OFPAT_SET_DL_DST: + case OFPUTIL_OFPAT10_SET_DL_SRC: + case OFPUTIL_OFPAT10_SET_DL_DST: oada = ofputil_put_action(code, b); str_to_mac(arg, oada->dl_addr); break; - case OFPUTIL_OFPAT_SET_NW_SRC: - case OFPUTIL_OFPAT_SET_NW_DST: + case OFPUTIL_OFPAT10_SET_NW_SRC: + case OFPUTIL_OFPAT10_SET_NW_DST: oana = ofputil_put_action(code, b); str_to_ip(arg, &oana->nw_addr); break; - case OFPUTIL_OFPAT_SET_NW_TOS: - ofputil_put_OFPAT_SET_NW_TOS(b)->nw_tos = str_to_u32(arg); + case OFPUTIL_OFPAT10_SET_NW_TOS: + ofputil_put_OFPAT10_SET_NW_TOS(b)->nw_tos = str_to_u32(arg); break; - case OFPUTIL_OFPAT_SET_TP_SRC: - case OFPUTIL_OFPAT_SET_TP_DST: + case OFPUTIL_OFPAT10_SET_TP_SRC: + case OFPUTIL_OFPAT10_SET_TP_DST: oata = ofputil_put_action(code, b); oata->tp_port = htons(str_to_u32(arg)); break; - case OFPUTIL_OFPAT_ENQUEUE: + case OFPUTIL_OFPAT10_ENQUEUE: parse_enqueue(b, arg); break; @@ -755,3 +755,80 @@ parse_ofp_flow_stats_request_str(struct ofputil_flow_stats_request *fsr, fsr->out_port = fm.out_port; fsr->table_id = fm.table_id; } + +/* Parses a specification of a flow from 's' into 'flow'. 's' must take the + * form FIELD=VALUE[,FIELD=VALUE]... where each FIELD is the name of a + * mf_field. Fields must be specified in a natural order for satisfying + * prerequisites. + * + * Returns NULL on success, otherwise a malloc()'d string that explains the + * problem. */ +char * +parse_ofp_exact_flow(struct flow *flow, const char *s) +{ + char *pos, *key, *value_s; + char *error = NULL; + char *copy; + + memset(flow, 0, sizeof *flow); + + pos = copy = xstrdup(s); + while (ofputil_parse_key_value(&pos, &key, &value_s)) { + const struct protocol *p; + if (parse_protocol(key, &p)) { + if (flow->dl_type) { + error = xasprintf("%s: Ethernet type set multiple times", s); + goto exit; + } + flow->dl_type = htons(p->dl_type); + + if (p->nw_proto) { + if (flow->nw_proto) { + error = xasprintf("%s: network protocol set " + "multiple times", s); + goto exit; + } + flow->nw_proto = p->nw_proto; + } + } else { + const struct mf_field *mf; + union mf_value value; + char *field_error; + + mf = mf_from_name(key); + if (!mf) { + error = xasprintf("%s: unknown field %s", s, key); + goto exit; + } + + if (!mf_are_prereqs_ok(mf, flow)) { + error = xasprintf("%s: prerequisites not met for setting %s", + s, key); + goto exit; + } + + if (!mf_is_zero(mf, flow)) { + error = xasprintf("%s: field %s set multiple times", s, key); + goto exit; + } + + field_error = mf_parse_value(mf, value_s, &value); + if (field_error) { + error = xasprintf("%s: bad value for %s (%s)", + s, key, field_error); + free(field_error); + goto exit; + } + + mf_set_flow_value(mf, &value, flow); + } + } + +exit: + free(copy); + + if (error) { + memset(flow, 0, sizeof *flow); + } + return error; +}