From patchwork Fri Jan 12 20:57:20 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 860198 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3zJFTT1H8Yz9sQm for ; Sat, 13 Jan 2018 07:58:37 +1100 (AEDT) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 782C11039; Fri, 12 Jan 2018 20:57:37 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id B9DB3FF9 for ; Fri, 12 Jan 2018 20:57:36 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from relay4-d.mail.gandi.net (relay4-d.mail.gandi.net [217.70.183.196]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id CA84118A for ; Fri, 12 Jan 2018 20:57:30 +0000 (UTC) X-Originating-IP: 208.91.3.26 Received: from sigabrt.benpfaff.org (unknown [208.91.3.26]) (Authenticated sender: blp@ovn.org) by relay4-d.mail.gandi.net (Postfix) with ESMTPSA id 35A921720A5; Fri, 12 Jan 2018 21:57:27 +0100 (CET) From: Ben Pfaff To: dev@openvswitch.org Date: Fri, 12 Jan 2018 12:57:20 -0800 Message-Id: <20180112205722.25360-2-blp@ovn.org> X-Mailer: git-send-email 2.10.2 In-Reply-To: <20180112205722.25360-1-blp@ovn.org> References: <20180112205722.25360-1-blp@ovn.org> X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Cc: Ben Pfaff Subject: [ovs-dev] [PATCH v2 1/3] ofp-actions: Make formatting and parsing functions take a struct argument. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org An upcoming commit will add another parameter for parsing and formatting actions. It is much easier to add these parameters if they are encapsulated in a struct, so this commit first makes that change. Signed-off-by: Ben Pfaff Reviewed-by: Yifeng Sun --- include/openvswitch/ofp-actions.h | 32 +- lib/ofp-actions.c | 1137 +++++++++++++++---------------------- lib/ofp-parse.c | 24 +- lib/ofp-print.c | 40 +- ofproto/ofproto-dpif-trace.c | 8 +- ofproto/ofproto-dpif-xlate.c | 12 +- ofproto/ofproto.c | 3 +- ovn/controller/ofctrl.c | 3 +- ovn/utilities/ovn-sbctl.c | 3 +- tests/test-ovn.c | 3 +- utilities/ovs-ofctl.c | 19 +- 11 files changed, 565 insertions(+), 719 deletions(-) diff --git a/include/openvswitch/ofp-actions.h b/include/openvswitch/ofp-actions.h index 4e957358f90a..454c705ccf73 100644 --- a/include/openvswitch/ofp-actions.h +++ b/include/openvswitch/ofp-actions.h @@ -1064,18 +1064,32 @@ bool ofpacts_equal_stringwise(const struct ofpact a[], size_t a_len, const struct mf_field *ofpact_get_mf_dst(const struct ofpact *ofpact); uint32_t ofpacts_get_meter(const struct ofpact[], size_t ofpacts_len); -/* Formatting and parsing ofpacts. */ +/* Formatting ofpacts. */ +struct ofpact_format_params { + /* Input. */ + const struct ofputil_port_map *port_map; + + /* Output. */ + struct ds *s; +}; void ofpacts_format(const struct ofpact[], size_t ofpacts_len, - const struct ofputil_port_map *, struct ds *); -char *ofpacts_parse_actions(const char *, const struct ofputil_port_map *, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols) + const struct ofpact_format_params *); +const char *ofpact_name(enum ofpact_type); + +/* Parsing ofpacts. */ +struct ofpact_parse_params { + /* Input. */ + const struct ofputil_port_map *port_map; + + /* Output. */ + struct ofpbuf *ofpacts; + enum ofputil_protocol *usable_protocols; +}; +char *ofpacts_parse_actions(const char *, const struct ofpact_parse_params *) OVS_WARN_UNUSED_RESULT; -char *ofpacts_parse_instructions(const char *, const struct ofputil_port_map *, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols) +char *ofpacts_parse_instructions(const char *, + const struct ofpact_parse_params *) OVS_WARN_UNUSED_RESULT; -const char *ofpact_name(enum ofpact_type); /* Internal use by the helpers below. */ void ofpact_init(struct ofpact *, enum ofpact_type, size_t len); diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c index db933634bf8b..93792ddfca4b 100644 --- a/lib/ofp-actions.c +++ b/lib/ofp-actions.c @@ -417,8 +417,7 @@ static void *ofpact_put_raw(struct ofpbuf *, enum ofp_version, enum ofp_raw_action_type, uint64_t arg); static char *OVS_WARN_UNUSED_RESULT ofpacts_parse( - char *str, const struct ofputil_port_map *, - struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols, + char *str, const struct ofpact_parse_params *pp, bool allow_instructions, enum ofpact_type outer_action); static enum ofperr ofpacts_pull_openflow_actions__( struct ofpbuf *openflow, unsigned int actions_len, @@ -426,8 +425,7 @@ static enum ofperr ofpacts_pull_openflow_actions__( struct ofpbuf *ofpacts, enum ofpact_type outer_action, const struct vl_mff_map *vl_mff_map, uint64_t *ofpacts_tlv_bitmap); static char * OVS_WARN_UNUSED_RESULT ofpacts_parse_copy( - const char *s_, const struct ofputil_port_map *, struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols, + const char *s_, const struct ofpact_parse_params *pp, bool allow_instructions, enum ofpact_type outer_action); /* Returns the ofpact following 'ofpact', except that if 'ofpact' contains @@ -607,16 +605,16 @@ encode_OUTPUT(const struct ofpact_output *output, } static char * OVS_WARN_UNUSED_RESULT -parse_truncate_subfield(struct ofpact_output_trunc *output_trunc, - const char *arg_, - const struct ofputil_port_map *port_map) +parse_truncate_subfield(const char *arg_, + const struct ofpact_parse_params *pp, + struct ofpact_output_trunc *output_trunc) { char *key, *value; char *arg = CONST_CAST(char *, arg_); while (ofputil_parse_key_value(&arg, &key, &value)) { if (!strcmp(key, "port")) { - if (!ofputil_port_from_string(value, port_map, + if (!ofputil_port_from_string(value, pp->port_map, &output_trunc->port)) { return xasprintf("output to unknown truncate port: %s", value); @@ -643,21 +641,18 @@ parse_truncate_subfield(struct ofpact_output_trunc *output_trunc, } static char * OVS_WARN_UNUSED_RESULT -parse_OUTPUT(const char *arg, - const struct ofputil_port_map *port_map, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_OUTPUT(const char *arg, const struct ofpact_parse_params *pp) { if (strstr(arg, "port") && strstr(arg, "max_len")) { struct ofpact_output_trunc *output_trunc; - output_trunc = ofpact_put_OUTPUT_TRUNC(ofpacts); - return parse_truncate_subfield(output_trunc, arg, port_map); + output_trunc = ofpact_put_OUTPUT_TRUNC(pp->ofpacts); + return parse_truncate_subfield(arg, pp, output_trunc); } ofp_port_t port; - if (ofputil_port_from_string(arg, port_map, &port)) { - struct ofpact_output *output = ofpact_put_OUTPUT(ofpacts); + if (ofputil_port_from_string(arg, pp->port_map, &port)) { + struct ofpact_output *output = ofpact_put_OUTPUT(pp->ofpacts); output->port = port; output->max_len = output->port == OFPP_CONTROLLER ? UINT16_MAX : 0; return NULL; @@ -668,7 +663,7 @@ parse_OUTPUT(const char *arg, if (!error) { struct ofpact_output_reg *output_reg; - output_reg = ofpact_put_OUTPUT_REG(ofpacts); + output_reg = ofpact_put_OUTPUT_REG(pp->ofpacts); output_reg->max_len = UINT16_MAX; output_reg->src = src; return NULL; @@ -680,14 +675,14 @@ parse_OUTPUT(const char *arg, static void format_OUTPUT(const struct ofpact_output *a, - const struct ofputil_port_map *port_map, struct ds *s) + const struct ofpact_format_params *fp) { if (ofp_to_u16(a->port) < ofp_to_u16(OFPP_MAX)) { - ds_put_format(s, "%soutput:%s", colors.special, colors.end); + ds_put_format(fp->s, "%soutput:%s", colors.special, colors.end); } - ofputil_format_port(a->port, port_map, s); + ofputil_format_port(a->port, fp->port_map, fp->s); if (a->port == OFPP_CONTROLLER) { - ds_put_format(s, ":%"PRIu16, a->max_len); + ds_put_format(fp->s, ":%"PRIu16, a->max_len); } } @@ -710,20 +705,16 @@ encode_GROUP(const struct ofpact_group *group, } static char * OVS_WARN_UNUSED_RESULT -parse_GROUP(char *arg, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_GROUP(char *arg, const struct ofpact_parse_params *pp) { - return str_to_u32(arg, &ofpact_put_GROUP(ofpacts)->group_id); + return str_to_u32(arg, &ofpact_put_GROUP(pp->ofpacts)->group_id); } static void format_GROUP(const struct ofpact_group *a, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%sgroup:%s%"PRIu32, + ds_put_format(fp->s, "%sgroup:%s%"PRIu32, colors.special, colors.end, a->group_id); } @@ -891,10 +882,7 @@ encode_CONTROLLER(const struct ofpact_controller *controller, } static char * OVS_WARN_UNUSED_RESULT -parse_CONTROLLER(char *arg, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_CONTROLLER(char *arg, const struct ofpact_parse_params *pp) { enum ofp_packet_in_reason reason = OFPR_ACTION; uint16_t controller_id = 0; @@ -941,30 +929,30 @@ parse_CONTROLLER(char *arg, if (reason == OFPR_ACTION && controller_id == 0 && !userdata && !pause) { struct ofpact_output *output; - output = ofpact_put_OUTPUT(ofpacts); + output = ofpact_put_OUTPUT(pp->ofpacts); output->port = OFPP_CONTROLLER; output->max_len = max_len; } else { struct ofpact_controller *controller; - controller = ofpact_put_CONTROLLER(ofpacts); + controller = ofpact_put_CONTROLLER(pp->ofpacts); controller->max_len = max_len; controller->reason = reason; controller->controller_id = controller_id; controller->pause = pause; if (userdata) { - size_t start_ofs = ofpacts->size; - const char *end = ofpbuf_put_hex(ofpacts, userdata, NULL); + size_t start_ofs = pp->ofpacts->size; + const char *end = ofpbuf_put_hex(pp->ofpacts, userdata, NULL); if (*end) { return xstrdup("bad hex digit in `controller' " "action `userdata'"); } - size_t userdata_len = ofpacts->size - start_ofs; - controller = ofpacts->header; + size_t userdata_len = pp->ofpacts->size - start_ofs; + controller = pp->ofpacts->header; controller->userdata_len = userdata_len; } - ofpact_finish_CONTROLLER(ofpacts, &controller); + ofpact_finish_CONTROLLER(pp->ofpacts, &controller); } return NULL; @@ -983,42 +971,41 @@ format_hex_arg(struct ds *s, const uint8_t *data, size_t len) static void format_CONTROLLER(const struct ofpact_controller *a, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { if (a->reason == OFPR_ACTION && !a->controller_id && !a->userdata_len && !a->pause) { - ds_put_format(s, "%sCONTROLLER:%s%"PRIu16, + ds_put_format(fp->s, "%sCONTROLLER:%s%"PRIu16, colors.special, colors.end, a->max_len); } else { enum ofp_packet_in_reason reason = a->reason; - ds_put_format(s, "%scontroller(%s", colors.paren, colors.end); + ds_put_format(fp->s, "%scontroller(%s", colors.paren, colors.end); if (reason != OFPR_ACTION) { char reasonbuf[OFPUTIL_PACKET_IN_REASON_BUFSIZE]; - ds_put_format(s, "%sreason=%s%s,", colors.param, colors.end, + ds_put_format(fp->s, "%sreason=%s%s,", colors.param, colors.end, ofputil_packet_in_reason_to_string( reason, reasonbuf, sizeof reasonbuf)); } if (a->max_len != UINT16_MAX) { - ds_put_format(s, "%smax_len=%s%"PRIu16",", + ds_put_format(fp->s, "%smax_len=%s%"PRIu16",", colors.param, colors.end, a->max_len); } if (a->controller_id != 0) { - ds_put_format(s, "%sid=%s%"PRIu16",", + ds_put_format(fp->s, "%sid=%s%"PRIu16",", colors.param, colors.end, a->controller_id); } if (a->userdata_len) { - ds_put_format(s, "%suserdata=%s", colors.param, colors.end); - format_hex_arg(s, a->userdata, a->userdata_len); - ds_put_char(s, ','); + ds_put_format(fp->s, "%suserdata=%s", colors.param, colors.end); + format_hex_arg(fp->s, a->userdata, a->userdata_len); + ds_put_char(fp->s, ','); } if (a->pause) { - ds_put_format(s, "%spause%s,", colors.value, colors.end); + ds_put_format(fp->s, "%spause%s,", colors.value, colors.end); } - ds_chomp(s, ','); - ds_put_format(s, "%s)%s", colors.paren, colors.end); + ds_chomp(fp->s, ','); + ds_put_format(fp->s, "%s)%s", colors.paren, colors.end); } } @@ -1074,10 +1061,7 @@ encode_ENQUEUE(const struct ofpact_enqueue *enqueue, } static char * OVS_WARN_UNUSED_RESULT -parse_ENQUEUE(char *arg, - const struct ofputil_port_map *port_map, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_ENQUEUE(char *arg, const struct ofpact_parse_params *pp) { char *sp = NULL; char *port = strtok_r(arg, ":q,", &sp); @@ -1089,8 +1073,8 @@ parse_ENQUEUE(char *arg, "\"enqueue(PORT,QUEUE)\""); } - enqueue = ofpact_put_ENQUEUE(ofpacts); - if (!ofputil_port_from_string(port, port_map, &enqueue->port)) { + enqueue = ofpact_put_ENQUEUE(pp->ofpacts); + if (!ofputil_port_from_string(port, pp->port_map, &enqueue->port)) { return xasprintf("%s: enqueue to unknown port", port); } return str_to_u32(queue, &enqueue->queue); @@ -1098,11 +1082,11 @@ parse_ENQUEUE(char *arg, static void format_ENQUEUE(const struct ofpact_enqueue *a, - const struct ofputil_port_map *port_map, struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%senqueue:%s", colors.param, colors.end); - ofputil_format_port(a->port, port_map, s); - ds_put_format(s, ":%"PRIu32, a->queue); + ds_put_format(fp->s, "%senqueue:%s", colors.param, colors.end); + ofputil_format_port(a->port, fp->port_map, fp->s); + ds_put_format(fp->s, ":%"PRIu32, a->queue); } /* Action structure for NXAST_OUTPUT_REG. @@ -1245,21 +1229,17 @@ encode_OUTPUT_REG(const struct ofpact_output_reg *output_reg, } static char * OVS_WARN_UNUSED_RESULT -parse_OUTPUT_REG(const char *arg, - const struct ofputil_port_map *port_map, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_OUTPUT_REG(const char *arg, const struct ofpact_parse_params *pp) { - return parse_OUTPUT(arg, port_map, ofpacts, usable_protocols); + return parse_OUTPUT(arg, pp); } static void format_OUTPUT_REG(const struct ofpact_output_reg *a, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%soutput:%s", colors.special, colors.end); - mf_format_subfield(&a->src, s); + ds_put_format(fp->s, "%soutput:%s", colors.special, colors.end); + mf_format_subfield(&a->src, fp->s); } /* Action structure for NXAST_BUNDLE and NXAST_BUNDLE_LOAD. @@ -1462,25 +1442,22 @@ encode_BUNDLE(const struct ofpact_bundle *bundle, } static char * OVS_WARN_UNUSED_RESULT -parse_BUNDLE(const char *arg, const struct ofputil_port_map *port_map, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_BUNDLE(const char *arg, const struct ofpact_parse_params *pp) { - return bundle_parse(arg, port_map, ofpacts); + return bundle_parse(arg, pp->port_map, pp->ofpacts); } static char * OVS_WARN_UNUSED_RESULT -parse_bundle_load(const char *arg, const struct ofputil_port_map *port_map, - struct ofpbuf *ofpacts) +parse_bundle_load(const char *arg, const struct ofpact_parse_params *pp) { - return bundle_parse_load(arg, port_map, ofpacts); + return bundle_parse_load(arg, pp->port_map, pp->ofpacts); } static void format_BUNDLE(const struct ofpact_bundle *a, - const struct ofputil_port_map *port_map, struct ds *s) + const struct ofpact_format_params *fp) { - bundle_format(a, port_map, s); + bundle_format(a, fp->port_map, fp->s); } /* Set VLAN actions. */ @@ -1538,8 +1515,8 @@ encode_SET_VLAN_VID(const struct ofpact_vlan_vid *vlan_vid, } static char * OVS_WARN_UNUSED_RESULT -parse_set_vlan_vid(char *arg, - struct ofpbuf *ofpacts, bool push_vlan_if_needed) +parse_set_vlan_vid(char *arg, bool push_vlan_if_needed, + const struct ofpact_parse_params *pp) { struct ofpact_vlan_vid *vlan_vid; uint16_t vid; @@ -1553,27 +1530,23 @@ parse_set_vlan_vid(char *arg, if (vid & ~VLAN_VID_MASK) { return xasprintf("%s: not a valid VLAN VID", arg); } - vlan_vid = ofpact_put_SET_VLAN_VID(ofpacts); + vlan_vid = ofpact_put_SET_VLAN_VID(pp->ofpacts); vlan_vid->vlan_vid = vid; vlan_vid->push_vlan_if_needed = push_vlan_if_needed; return NULL; } static char * OVS_WARN_UNUSED_RESULT -parse_SET_VLAN_VID(char *arg, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_SET_VLAN_VID(char *arg, const struct ofpact_parse_params *pp) { - return parse_set_vlan_vid(arg, ofpacts, false); + return parse_set_vlan_vid(arg, false, pp); } static void format_SET_VLAN_VID(const struct ofpact_vlan_vid *a, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%s%s:%s%"PRIu16, colors.param, + ds_put_format(fp->s, "%s%s:%s%"PRIu16, colors.param, a->push_vlan_if_needed ? "mod_vlan_vid" : "set_vlan_vid", colors.end, a->vlan_vid); } @@ -1633,8 +1606,8 @@ encode_SET_VLAN_PCP(const struct ofpact_vlan_pcp *vlan_pcp, } static char * OVS_WARN_UNUSED_RESULT -parse_set_vlan_pcp(char *arg, - struct ofpbuf *ofpacts, bool push_vlan_if_needed) +parse_set_vlan_pcp(char *arg, bool push_vlan_if_needed, + const struct ofpact_parse_params *pp) { struct ofpact_vlan_pcp *vlan_pcp; uint8_t pcp; @@ -1648,27 +1621,23 @@ parse_set_vlan_pcp(char *arg, if (pcp & ~7) { return xasprintf("%s: not a valid VLAN PCP", arg); } - vlan_pcp = ofpact_put_SET_VLAN_PCP(ofpacts); + vlan_pcp = ofpact_put_SET_VLAN_PCP(pp->ofpacts); vlan_pcp->vlan_pcp = pcp; vlan_pcp->push_vlan_if_needed = push_vlan_if_needed; return NULL; } static char * OVS_WARN_UNUSED_RESULT -parse_SET_VLAN_PCP(char *arg, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_SET_VLAN_PCP(char *arg, const struct ofpact_parse_params *pp) { - return parse_set_vlan_pcp(arg, ofpacts, false); + return parse_set_vlan_pcp(arg, false, pp); } static void format_SET_VLAN_PCP(const struct ofpact_vlan_pcp *a, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%s%s:%s%"PRIu8, colors.param, + ds_put_format(fp->s, "%s%s:%s%"PRIu8, colors.param, a->push_vlan_if_needed ? "mod_vlan_pcp" : "set_vlan_pcp", colors.end, a->vlan_pcp); } @@ -1701,28 +1670,24 @@ encode_STRIP_VLAN(const struct ofpact_null *null OVS_UNUSED, } static char * OVS_WARN_UNUSED_RESULT -parse_STRIP_VLAN(char *arg OVS_UNUSED, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_STRIP_VLAN(char *arg OVS_UNUSED, const struct ofpact_parse_params *pp) { - ofpact_put_STRIP_VLAN(ofpacts)->ofpact.raw = OFPAT_RAW10_STRIP_VLAN; + ofpact_put_STRIP_VLAN(pp->ofpacts)->ofpact.raw = OFPAT_RAW10_STRIP_VLAN; return NULL; } static char * OVS_WARN_UNUSED_RESULT -parse_pop_vlan(struct ofpbuf *ofpacts) +parse_pop_vlan(const struct ofpact_parse_params *pp) { - ofpact_put_STRIP_VLAN(ofpacts)->ofpact.raw = OFPAT_RAW11_POP_VLAN; + ofpact_put_STRIP_VLAN(pp->ofpacts)->ofpact.raw = OFPAT_RAW11_POP_VLAN; return NULL; } static void format_STRIP_VLAN(const struct ofpact_null *a, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, (a->ofpact.raw == OFPAT_RAW11_POP_VLAN + ds_put_format(fp->s, (a->ofpact.raw == OFPAT_RAW11_POP_VLAN ? "%spop_vlan%s" : "%sstrip_vlan%s"), colors.value, colors.end); @@ -1757,16 +1722,13 @@ encode_PUSH_VLAN(const struct ofpact_push_vlan *push_vlan, } static char * OVS_WARN_UNUSED_RESULT -parse_PUSH_VLAN(char *arg, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_PUSH_VLAN(char *arg, const struct ofpact_parse_params *pp) { struct ofpact_push_vlan *push_vlan; uint16_t ethertype; char *error; - *usable_protocols &= OFPUTIL_P_OF11_UP; + *pp->usable_protocols &= OFPUTIL_P_OF11_UP; error = str_to_u16(arg, "ethertype", ðertype); if (error) { return error; @@ -1775,17 +1737,16 @@ parse_PUSH_VLAN(char *arg, if (!eth_type_vlan(htons(ethertype))) { return xasprintf("%s: not a valid VLAN ethertype", arg); } - push_vlan = ofpact_put_PUSH_VLAN(ofpacts); + push_vlan = ofpact_put_PUSH_VLAN(pp->ofpacts); push_vlan->ethertype = htons(ethertype); return NULL; } static void format_PUSH_VLAN(const struct ofpact_push_vlan *push_vlan, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%spush_vlan:%s%#"PRIx16, + ds_put_format(fp->s, "%spush_vlan:%s%#"PRIx16, colors.param, colors.end, ntohs(push_vlan->ethertype)); } @@ -1851,38 +1812,30 @@ encode_SET_ETH_DST(const struct ofpact_mac *mac, } static char * OVS_WARN_UNUSED_RESULT -parse_SET_ETH_SRC(char *arg, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_SET_ETH_SRC(char *arg, const struct ofpact_parse_params *pp) { - return str_to_mac(arg, &ofpact_put_SET_ETH_SRC(ofpacts)->mac); + return str_to_mac(arg, &ofpact_put_SET_ETH_SRC(pp->ofpacts)->mac); } static char * OVS_WARN_UNUSED_RESULT -parse_SET_ETH_DST(char *arg, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_SET_ETH_DST(char *arg, const struct ofpact_parse_params *pp) { - return str_to_mac(arg, &ofpact_put_SET_ETH_DST(ofpacts)->mac); + return str_to_mac(arg, &ofpact_put_SET_ETH_DST(pp->ofpacts)->mac); } static void format_SET_ETH_SRC(const struct ofpact_mac *a, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%smod_dl_src:%s"ETH_ADDR_FMT, + ds_put_format(fp->s, "%smod_dl_src:%s"ETH_ADDR_FMT, colors.param, colors.end, ETH_ADDR_ARGS(a->mac)); } static void format_SET_ETH_DST(const struct ofpact_mac *a, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%smod_dl_dst:%s"ETH_ADDR_FMT, + ds_put_format(fp->s, "%smod_dl_dst:%s"ETH_ADDR_FMT, colors.param, colors.end, ETH_ADDR_ARGS(a->mac)); } @@ -1937,38 +1890,30 @@ encode_SET_IPV4_DST(const struct ofpact_ipv4 *ipv4, } static char * OVS_WARN_UNUSED_RESULT -parse_SET_IPV4_SRC(char *arg, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_SET_IPV4_SRC(char *arg, const struct ofpact_parse_params *pp) { - return str_to_ip(arg, &ofpact_put_SET_IPV4_SRC(ofpacts)->ipv4); + return str_to_ip(arg, &ofpact_put_SET_IPV4_SRC(pp->ofpacts)->ipv4); } static char * OVS_WARN_UNUSED_RESULT -parse_SET_IPV4_DST(char *arg, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_SET_IPV4_DST(char *arg, const struct ofpact_parse_params *pp) { - return str_to_ip(arg, &ofpact_put_SET_IPV4_DST(ofpacts)->ipv4); + return str_to_ip(arg, &ofpact_put_SET_IPV4_DST(pp->ofpacts)->ipv4); } static void format_SET_IPV4_SRC(const struct ofpact_ipv4 *a, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%smod_nw_src:%s"IP_FMT, + ds_put_format(fp->s, "%smod_nw_src:%s"IP_FMT, colors.param, colors.end, IP_ARGS(a->ipv4)); } static void format_SET_IPV4_DST(const struct ofpact_ipv4 *a, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%smod_nw_dst:%s"IP_FMT, + ds_put_format(fp->s, "%smod_nw_dst:%s"IP_FMT, colors.param, colors.end, IP_ARGS(a->ipv4)); } @@ -1999,10 +1944,8 @@ encode_SET_IP_DSCP(const struct ofpact_dscp *dscp, } static char * OVS_WARN_UNUSED_RESULT -parse_SET_IP_DSCP(char *arg, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_SET_IP_DSCP(char *arg, const struct ofpact_parse_params *pp) + { uint8_t tos; char *error; @@ -2015,16 +1958,16 @@ parse_SET_IP_DSCP(char *arg, if (tos & ~IP_DSCP_MASK) { return xasprintf("%s: not a valid TOS", arg); } - ofpact_put_SET_IP_DSCP(ofpacts)->dscp = tos; + ofpact_put_SET_IP_DSCP(pp->ofpacts)->dscp = tos; return NULL; } static void format_SET_IP_DSCP(const struct ofpact_dscp *a, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%smod_nw_tos:%s%d", colors.param, colors.end, a->dscp); + ds_put_format(fp->s, "%smod_nw_tos:%s%d", + colors.param, colors.end, a->dscp); } /* Set IPv4/v6 ECN actions. */ @@ -2059,10 +2002,7 @@ encode_SET_IP_ECN(const struct ofpact_ecn *ip_ecn, } static char * OVS_WARN_UNUSED_RESULT -parse_SET_IP_ECN(char *arg, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_SET_IP_ECN(char *arg, const struct ofpact_parse_params *pp) { uint8_t ecn; char *error; @@ -2075,16 +2015,15 @@ parse_SET_IP_ECN(char *arg, if (ecn & ~IP_ECN_MASK) { return xasprintf("%s: not a valid ECN", arg); } - ofpact_put_SET_IP_ECN(ofpacts)->ecn = ecn; + ofpact_put_SET_IP_ECN(pp->ofpacts)->ecn = ecn; return NULL; } static void format_SET_IP_ECN(const struct ofpact_ecn *a, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%smod_nw_ecn:%s%d", + ds_put_format(fp->s, "%smod_nw_ecn:%s%d", colors.param, colors.end, a->ecn); } @@ -2113,10 +2052,8 @@ encode_SET_IP_TTL(const struct ofpact_ip_ttl *ttl, } static char * OVS_WARN_UNUSED_RESULT -parse_SET_IP_TTL(char *arg, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_SET_IP_TTL(char *arg, const struct ofpact_parse_params *pp) + { uint8_t ttl; char *error; @@ -2126,16 +2063,16 @@ parse_SET_IP_TTL(char *arg, return error; } - ofpact_put_SET_IP_TTL(ofpacts)->ttl = ttl; + ofpact_put_SET_IP_TTL(pp->ofpacts)->ttl = ttl; return NULL; } static void format_SET_IP_TTL(const struct ofpact_ip_ttl *a, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%smod_nw_ttl:%s%d", colors.param, colors.end, a->ttl); + ds_put_format(fp->s, "%smod_nw_ttl:%s%d", + colors.param, colors.end, a->ttl); } /* Set TCP/UDP/SCTP port actions. */ @@ -2200,39 +2137,33 @@ encode_SET_L4_DST_PORT(const struct ofpact_l4_port *l4_port, } static char * OVS_WARN_UNUSED_RESULT -parse_SET_L4_SRC_PORT(char *arg, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_SET_L4_SRC_PORT(char *arg, const struct ofpact_parse_params *pp) { return str_to_u16(arg, "source port", - &ofpact_put_SET_L4_SRC_PORT(ofpacts)->port); + &ofpact_put_SET_L4_SRC_PORT(pp->ofpacts)->port); } static char * OVS_WARN_UNUSED_RESULT -parse_SET_L4_DST_PORT(char *arg, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_SET_L4_DST_PORT(char *arg, const struct ofpact_parse_params *pp) { return str_to_u16(arg, "destination port", - &ofpact_put_SET_L4_DST_PORT(ofpacts)->port); + &ofpact_put_SET_L4_DST_PORT(pp->ofpacts)->port); } static void format_SET_L4_SRC_PORT(const struct ofpact_l4_port *a, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%smod_tp_src:%s%d", colors.param, colors.end, a->port); + ds_put_format(fp->s, "%smod_tp_src:%s%d", + colors.param, colors.end, a->port); } static void format_SET_L4_DST_PORT(const struct ofpact_l4_port *a, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%smod_tp_dst:%s%d", colors.param, colors.end, a->port); + ds_put_format(fp->s, "%smod_tp_dst:%s%d", + colors.param, colors.end, a->port); } /* Action structure for OFPAT_COPY_FIELD. */ @@ -2520,21 +2451,17 @@ encode_REG_MOVE(const struct ofpact_reg_move *move, } static char * OVS_WARN_UNUSED_RESULT -parse_REG_MOVE(const char *arg, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_REG_MOVE(const char *arg, const struct ofpact_parse_params *pp) { - struct ofpact_reg_move *move = ofpact_put_REG_MOVE(ofpacts); + struct ofpact_reg_move *move = ofpact_put_REG_MOVE(pp->ofpacts); return nxm_parse_reg_move(move, arg); } static void format_REG_MOVE(const struct ofpact_reg_move *a, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - nxm_format_reg_move(a, s); + nxm_format_reg_move(a, fp->s); } /* Action structure for OFPAT12_SET_FIELD. */ @@ -3027,14 +2954,12 @@ set_field_split_str(char *arg, char **key, char **value, char **delim) } /* Parses a "set_field" action with argument 'arg', appending the parsed - * action to 'ofpacts'. + * action to 'pp->ofpacts'. * * Returns NULL if successful, otherwise a malloc()'d string describing the * error. The caller is responsible for freeing the returned string. */ static char * OVS_WARN_UNUSED_RESULT -set_field_parse__(char *arg, const struct ofputil_port_map *port_map, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols) +set_field_parse__(char *arg, const struct ofpact_parse_params *pp) { char *value; char *delim; @@ -3057,7 +2982,7 @@ set_field_parse__(char *arg, const struct ofputil_port_map *port_map, } delim[0] = '\0'; - error = mf_parse(mf, value, port_map, &sf_value, &sf_mask); + error = mf_parse(mf, value, pp->port_map, &sf_value, &sf_mask); if (error) { return error; } @@ -3066,30 +2991,28 @@ set_field_parse__(char *arg, const struct ofputil_port_map *port_map, return xasprintf("%s is not a valid value for field %s", value, key); } - *usable_protocols &= mf->usable_protocols_exact; + *pp->usable_protocols &= mf->usable_protocols_exact; - ofpact_put_set_field(ofpacts, mf, &sf_value, &sf_mask); + ofpact_put_set_field(pp->ofpacts, mf, &sf_value, &sf_mask); return NULL; } /* Parses 'arg' as the argument to a "set_field" action, and appends such an - * action to 'ofpacts'. + * action to 'pp->ofpacts'. * * Returns NULL if successful, otherwise a malloc()'d string describing the * error. The caller is responsible for freeing the returned string. */ static char * OVS_WARN_UNUSED_RESULT -parse_SET_FIELD(const char *arg, const struct ofputil_port_map *port_map, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols) +parse_SET_FIELD(const char *arg, const struct ofpact_parse_params *pp) { char *copy = xstrdup(arg); - char *error = set_field_parse__(copy, port_map, ofpacts, usable_protocols); + char *error = set_field_parse__(copy, pp); free(copy); return error; } static char * OVS_WARN_UNUSED_RESULT -parse_reg_load(char *arg, struct ofpbuf *ofpacts) +parse_reg_load(char *arg, const struct ofpact_parse_params *pp) { struct mf_subfield dst; char *key, *value_str; @@ -3123,8 +3046,8 @@ parse_reg_load(char *arg, struct ofpbuf *ofpacts) return error; } - struct ofpact_set_field *sf = ofpact_put_reg_load(ofpacts, dst.field, NULL, - NULL); + struct ofpact_set_field *sf = ofpact_put_reg_load(pp->ofpacts, dst.field, + NULL, NULL); bitwise_copy(&value, dst.field->n_bytes, 0, sf->value, dst.field->n_bytes, dst.ofs, dst.n_bits); @@ -3135,8 +3058,7 @@ parse_reg_load(char *arg, struct ofpbuf *ofpacts) static void format_SET_FIELD(const struct ofpact_set_field *a, - const struct ofputil_port_map *port_map, - struct ds *s) + const struct ofpact_format_params *fp) { if (a->ofpact.raw == NXAST_RAW_REG_LOAD) { struct mf_subfield dst; @@ -3144,17 +3066,18 @@ format_SET_FIELD(const struct ofpact_set_field *a, dst.ofs = dst.n_bits = 0; while (next_load_segment(a, &dst, &value)) { - ds_put_format(s, "%sload:%s%#"PRIx64"%s->%s", + ds_put_format(fp->s, "%sload:%s%#"PRIx64"%s->%s", colors.special, colors.end, value, colors.special, colors.end); - mf_format_subfield(&dst, s); - ds_put_char(s, ','); + mf_format_subfield(&dst, fp->s); + ds_put_char(fp->s, ','); } - ds_chomp(s, ','); + ds_chomp(fp->s, ','); } else { - ds_put_format(s, "%sset_field:%s", colors.special, colors.end); - mf_format(a->field, a->value, ofpact_set_field_mask(a), port_map, s); - ds_put_format(s, "%s->%s%s", + ds_put_format(fp->s, "%sset_field:%s", colors.special, colors.end); + mf_format(a->field, a->value, ofpact_set_field_mask(a), + fp->port_map, fp->s); + ds_put_format(fp->s, "%s->%s%s", colors.special, colors.end, a->field->name); } } @@ -3319,37 +3242,29 @@ encode_STACK_POP(const struct ofpact_stack *stack, } static char * OVS_WARN_UNUSED_RESULT -parse_STACK_PUSH(char *arg, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_STACK_PUSH(char *arg, const struct ofpact_parse_params *pp) { - return nxm_parse_stack_action(ofpact_put_STACK_PUSH(ofpacts), arg); + return nxm_parse_stack_action(ofpact_put_STACK_PUSH(pp->ofpacts), arg); } static char * OVS_WARN_UNUSED_RESULT -parse_STACK_POP(char *arg, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_STACK_POP(char *arg, const struct ofpact_parse_params *pp) { - return nxm_parse_stack_action(ofpact_put_STACK_POP(ofpacts), arg); + return nxm_parse_stack_action(ofpact_put_STACK_POP(pp->ofpacts), arg); } static void format_STACK_PUSH(const struct ofpact_stack *a, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - nxm_format_stack_push(a, s); + nxm_format_stack_push(a, fp->s); } static void format_STACK_POP(const struct ofpact_stack *a, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - nxm_format_stack_pop(a, s); + nxm_format_stack_pop(a, fp->s); } /* Action structure for NXAST_DEC_TTL_CNT_IDS. @@ -3457,66 +3372,62 @@ encode_DEC_TTL(const struct ofpact_cnt_ids *dec_ttl, } static void -parse_noargs_dec_ttl(struct ofpbuf *ofpacts) +parse_noargs_dec_ttl(const struct ofpact_parse_params *pp) { struct ofpact_cnt_ids *ids; uint16_t id = 0; - ofpact_put_DEC_TTL(ofpacts); - ofpbuf_put(ofpacts, &id, sizeof id); - ids = ofpacts->header; + ofpact_put_DEC_TTL(pp->ofpacts); + ofpbuf_put(pp->ofpacts, &id, sizeof id); + ids = pp->ofpacts->header; ids->n_controllers++; - ofpact_finish_DEC_TTL(ofpacts, &ids); + ofpact_finish_DEC_TTL(pp->ofpacts, &ids); } static char * OVS_WARN_UNUSED_RESULT -parse_DEC_TTL(char *arg, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_DEC_TTL(char *arg, const struct ofpact_parse_params *pp) { if (*arg == '\0') { - parse_noargs_dec_ttl(ofpacts); + parse_noargs_dec_ttl(pp); } else { struct ofpact_cnt_ids *ids; char *cntr; - ids = ofpact_put_DEC_TTL(ofpacts); + ids = ofpact_put_DEC_TTL(pp->ofpacts); ids->ofpact.raw = NXAST_RAW_DEC_TTL_CNT_IDS; for (cntr = strtok_r(arg, ", ", &arg); cntr != NULL; cntr = strtok_r(NULL, ", ", &arg)) { uint16_t id = atoi(cntr); - ofpbuf_put(ofpacts, &id, sizeof id); - ids = ofpacts->header; + ofpbuf_put(pp->ofpacts, &id, sizeof id); + ids = pp->ofpacts->header; ids->n_controllers++; } if (!ids->n_controllers) { return xstrdup("dec_ttl_cnt_ids: expected at least one controller " "id."); } - ofpact_finish_DEC_TTL(ofpacts, &ids); + ofpact_finish_DEC_TTL(pp->ofpacts, &ids); } return NULL; } static void format_DEC_TTL(const struct ofpact_cnt_ids *a, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { size_t i; - ds_put_format(s, "%sdec_ttl%s", colors.paren, colors.end); + ds_put_format(fp->s, "%sdec_ttl%s", colors.paren, colors.end); if (a->ofpact.raw == NXAST_RAW_DEC_TTL_CNT_IDS) { - ds_put_format(s, "%s(%s", colors.paren, colors.end); + ds_put_format(fp->s, "%s(%s", colors.paren, colors.end); for (i = 0; i < a->n_controllers; i++) { if (i) { - ds_put_cstr(s, ","); + ds_put_cstr(fp->s, ","); } - ds_put_format(s, "%"PRIu16, a->cnt_ids[i]); + ds_put_format(fp->s, "%"PRIu16, a->cnt_ids[i]); } - ds_put_format(s, "%s)%s", colors.paren, colors.end); + ds_put_format(fp->s, "%s)%s", colors.paren, colors.end); } } @@ -3544,12 +3455,10 @@ encode_SET_MPLS_LABEL(const struct ofpact_mpls_label *label, } static char * OVS_WARN_UNUSED_RESULT -parse_SET_MPLS_LABEL(char *arg, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_SET_MPLS_LABEL(char *arg, const struct ofpact_parse_params *pp) { - struct ofpact_mpls_label *mpls_label = ofpact_put_SET_MPLS_LABEL(ofpacts); + struct ofpact_mpls_label *mpls_label + = ofpact_put_SET_MPLS_LABEL(pp->ofpacts); if (*arg == '\0') { return xstrdup("set_mpls_label: expected label."); } @@ -3560,10 +3469,9 @@ parse_SET_MPLS_LABEL(char *arg, static void format_SET_MPLS_LABEL(const struct ofpact_mpls_label *a, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%sset_mpls_label(%s%"PRIu32"%s)%s", + ds_put_format(fp->s, "%sset_mpls_label(%s%"PRIu32"%s)%s", colors.paren, colors.end, ntohl(a->label), colors.paren, colors.end); } @@ -3591,12 +3499,9 @@ encode_SET_MPLS_TC(const struct ofpact_mpls_tc *tc, } static char * OVS_WARN_UNUSED_RESULT -parse_SET_MPLS_TC(char *arg, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_SET_MPLS_TC(char *arg, const struct ofpact_parse_params *pp) { - struct ofpact_mpls_tc *mpls_tc = ofpact_put_SET_MPLS_TC(ofpacts); + struct ofpact_mpls_tc *mpls_tc = ofpact_put_SET_MPLS_TC(pp->ofpacts); if (*arg == '\0') { return xstrdup("set_mpls_tc: expected tc."); @@ -3608,10 +3513,9 @@ parse_SET_MPLS_TC(char *arg, static void format_SET_MPLS_TC(const struct ofpact_mpls_tc *a, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%sset_mpls_ttl(%s%"PRIu8"%s)%s", + ds_put_format(fp->s, "%sset_mpls_ttl(%s%"PRIu8"%s)%s", colors.paren, colors.end, a->tc, colors.paren, colors.end); } @@ -3635,17 +3539,14 @@ encode_SET_MPLS_TTL(const struct ofpact_mpls_ttl *ttl, } /* Parses 'arg' as the argument to a "set_mpls_ttl" action, and appends such an - * action to 'ofpacts'. + * action to 'pp->ofpacts'. * * Returns NULL if successful, otherwise a malloc()'d string describing the * error. The caller is responsible for freeing the returned string. */ static char * OVS_WARN_UNUSED_RESULT -parse_SET_MPLS_TTL(char *arg, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_SET_MPLS_TTL(char *arg, const struct ofpact_parse_params *pp) { - struct ofpact_mpls_ttl *mpls_ttl = ofpact_put_SET_MPLS_TTL(ofpacts); + struct ofpact_mpls_ttl *mpls_ttl = ofpact_put_SET_MPLS_TTL(pp->ofpacts); if (*arg == '\0') { return xstrdup("set_mpls_ttl: expected ttl."); @@ -3657,10 +3558,9 @@ parse_SET_MPLS_TTL(char *arg, static void format_SET_MPLS_TTL(const struct ofpact_mpls_ttl *a, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%sset_mpls_ttl(%s%"PRIu8"%s)%s", + ds_put_format(fp->s, "%sset_mpls_ttl(%s%"PRIu8"%s)%s", colors.paren, colors.end, a->ttl, colors.paren, colors.end); } @@ -3682,21 +3582,17 @@ encode_DEC_MPLS_TTL(const struct ofpact_null *null OVS_UNUSED, } static char * OVS_WARN_UNUSED_RESULT -parse_DEC_MPLS_TTL(char *arg OVS_UNUSED, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_DEC_MPLS_TTL(char *arg OVS_UNUSED, const struct ofpact_parse_params *pp) { - ofpact_put_DEC_MPLS_TTL(ofpacts); + ofpact_put_DEC_MPLS_TTL(pp->ofpacts); return NULL; } static void format_DEC_MPLS_TTL(const struct ofpact_null *a OVS_UNUSED, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%sdec_mpls_ttl%s", colors.value, colors.end); + ds_put_format(fp->s, "%sdec_mpls_ttl%s", colors.value, colors.end); } /* Push MPLS label action. */ @@ -3725,27 +3621,23 @@ encode_PUSH_MPLS(const struct ofpact_push_mpls *push_mpls, } static char * OVS_WARN_UNUSED_RESULT -parse_PUSH_MPLS(char *arg, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_PUSH_MPLS(char *arg, const struct ofpact_parse_params *pp) { uint16_t ethertype; char *error; error = str_to_u16(arg, "push_mpls", ðertype); if (!error) { - ofpact_put_PUSH_MPLS(ofpacts)->ethertype = htons(ethertype); + ofpact_put_PUSH_MPLS(pp->ofpacts)->ethertype = htons(ethertype); } return error; } static void format_PUSH_MPLS(const struct ofpact_push_mpls *a, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%spush_mpls:%s0x%04"PRIx16, + ds_put_format(fp->s, "%spush_mpls:%s0x%04"PRIx16, colors.param, colors.end, ntohs(a->ethertype)); } @@ -3768,27 +3660,23 @@ encode_POP_MPLS(const struct ofpact_pop_mpls *pop_mpls, } static char * OVS_WARN_UNUSED_RESULT -parse_POP_MPLS(char *arg, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_POP_MPLS(char *arg, const struct ofpact_parse_params *pp) { uint16_t ethertype; char *error; error = str_to_u16(arg, "pop_mpls", ðertype); if (!error) { - ofpact_put_POP_MPLS(ofpacts)->ethertype = htons(ethertype); + ofpact_put_POP_MPLS(pp->ofpacts)->ethertype = htons(ethertype); } return error; } static void format_POP_MPLS(const struct ofpact_pop_mpls *a, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%spop_mpls:%s0x%04"PRIx16, + ds_put_format(fp->s, "%spop_mpls:%s0x%04"PRIx16, colors.param, colors.end, ntohs(a->ethertype)); } @@ -3835,31 +3723,27 @@ encode_SET_TUNNEL(const struct ofpact_tunnel *tunnel, } static char * OVS_WARN_UNUSED_RESULT -parse_set_tunnel(char *arg, struct ofpbuf *ofpacts, - enum ofp_raw_action_type raw) +parse_set_tunnel(char *arg, enum ofp_raw_action_type raw, + const struct ofpact_parse_params *pp) { struct ofpact_tunnel *tunnel; - tunnel = ofpact_put_SET_TUNNEL(ofpacts); + tunnel = ofpact_put_SET_TUNNEL(pp->ofpacts); tunnel->ofpact.raw = raw; return str_to_u64(arg, &tunnel->tun_id); } static char * OVS_WARN_UNUSED_RESULT -parse_SET_TUNNEL(char *arg, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_SET_TUNNEL(char *arg, const struct ofpact_parse_params *pp) { - return parse_set_tunnel(arg, ofpacts, NXAST_RAW_SET_TUNNEL); + return parse_set_tunnel(arg, NXAST_RAW_SET_TUNNEL, pp); } static void format_SET_TUNNEL(const struct ofpact_tunnel *a, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%sset_tunnel%s:%s%#"PRIx64, colors.param, + ds_put_format(fp->s, "%sset_tunnel%s:%s%#"PRIx64, colors.param, (a->tun_id > UINT32_MAX || a->ofpact.raw == NXAST_RAW_SET_TUNNEL64 ? "64" : ""), colors.end, a->tun_id); @@ -3884,20 +3768,16 @@ encode_SET_QUEUE(const struct ofpact_queue *queue, } static char * OVS_WARN_UNUSED_RESULT -parse_SET_QUEUE(char *arg, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_SET_QUEUE(char *arg, const struct ofpact_parse_params *pp) { - return str_to_u32(arg, &ofpact_put_SET_QUEUE(ofpacts)->queue_id); + return str_to_u32(arg, &ofpact_put_SET_QUEUE(pp->ofpacts)->queue_id); } static void format_SET_QUEUE(const struct ofpact_queue *a, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%sset_queue:%s%"PRIu32, + ds_put_format(fp->s, "%sset_queue:%s%"PRIu32, colors.param, colors.end, a->queue_id); } @@ -3919,20 +3799,17 @@ encode_POP_QUEUE(const struct ofpact_null *null OVS_UNUSED, static char * OVS_WARN_UNUSED_RESULT parse_POP_QUEUE(const char *arg OVS_UNUSED, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) + const struct ofpact_parse_params *pp) { - ofpact_put_POP_QUEUE(ofpacts); + ofpact_put_POP_QUEUE(pp->ofpacts); return NULL; } static void format_POP_QUEUE(const struct ofpact_null *a OVS_UNUSED, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%spop_queue%s", colors.value, colors.end); + ds_put_format(fp->s, "%spop_queue%s", colors.value, colors.end); } /* Action structure for NXAST_FIN_TIMEOUT. @@ -3993,12 +3870,9 @@ encode_FIN_TIMEOUT(const struct ofpact_fin_timeout *fin_timeout, } static char * OVS_WARN_UNUSED_RESULT -parse_FIN_TIMEOUT(char *arg, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_FIN_TIMEOUT(char *arg, const struct ofpact_parse_params *pp) { - struct ofpact_fin_timeout *oft = ofpact_put_FIN_TIMEOUT(ofpacts); + struct ofpact_fin_timeout *oft = ofpact_put_FIN_TIMEOUT(pp->ofpacts); char *key, *value; while (ofputil_parse_key_value(&arg, &key, &value)) { @@ -4022,20 +3896,19 @@ parse_FIN_TIMEOUT(char *arg, static void format_FIN_TIMEOUT(const struct ofpact_fin_timeout *a, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%sfin_timeout(%s", colors.paren, colors.end); + ds_put_format(fp->s, "%sfin_timeout(%s", colors.paren, colors.end); if (a->fin_idle_timeout) { - ds_put_format(s, "%sidle_timeout=%s%"PRIu16",", + ds_put_format(fp->s, "%sidle_timeout=%s%"PRIu16",", colors.param, colors.end, a->fin_idle_timeout); } if (a->fin_hard_timeout) { - ds_put_format(s, "%shard_timeout=%s%"PRIu16",", + ds_put_format(fp->s, "%shard_timeout=%s%"PRIu16",", colors.param, colors.end, a->fin_hard_timeout); } - ds_chomp(s, ','); - ds_put_format(s, "%s)%s", colors.paren, colors.end); + ds_chomp(fp->s, ','); + ds_put_format(fp->s, "%s)%s", colors.paren, colors.end); } /* Action structure for NXAST_ENCAP */ @@ -4149,10 +4022,7 @@ parse_ed_props(const uint16_t prop_class, char **arg, int *n_props, struct ofpbu */ static char * OVS_WARN_UNUSED_RESULT -parse_ENCAP(char *arg, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *out, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_ENCAP(char *arg, const struct ofpact_parse_params *pp) { struct ofpact_encap *encap; char *key, *value, *str; @@ -4160,7 +4030,7 @@ parse_ENCAP(char *arg, uint16_t prop_class; int n_props = 0; - encap = ofpact_put_ENCAP(out); + encap = ofpact_put_ENCAP(pp->ofpacts); encap->hdr_size = 0; /* Parse encap header type. */ str = arg; @@ -4174,14 +4044,14 @@ parse_ENCAP(char *arg, return xasprintf("Invalid encap prop class: %s", key); } /* Parse encap properties. */ - error = parse_ed_props(prop_class, &value, &n_props, out); + error = parse_ed_props(prop_class, &value, &n_props, pp->ofpacts); if (error != NULL) { return error; } - /* ofbuf out may have been re-allocated. */ - encap = out->header; + /* ofpbuf may have been re-allocated. */ + encap = pp->ofpacts->header; encap->n_props = n_props; - ofpact_finish_ENCAP(out, &encap); + ofpact_finish_ENCAP(pp->ofpacts, &encap); return NULL; } @@ -4221,17 +4091,16 @@ format_ed_props(struct ds *s, uint16_t n_props, static void format_ENCAP(const struct ofpact_encap *a, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%sencap(%s", colors.paren, colors.end); - ds_put_format(s, "%s", format_encap_pkt_type(a->new_pkt_type)); + ds_put_format(fp->s, "%sencap(%s", colors.paren, colors.end); + ds_put_format(fp->s, "%s", format_encap_pkt_type(a->new_pkt_type)); if (a->n_props > 0) { - ds_put_format(s, "%s(%s", colors.paren, colors.end); - format_ed_props(s, a->n_props, a->props); - ds_put_format(s, "%s)%s", colors.paren, colors.end); + ds_put_format(fp->s, "%s(%s", colors.paren, colors.end); + format_ed_props(fp->s, a->n_props, a->props); + ds_put_format(fp->s, "%s)%s", colors.paren, colors.end); } - ds_put_format(s, "%s)%s", colors.paren, colors.end); + ds_put_format(fp->s, "%s)%s", colors.paren, colors.end); } /* Action structure for NXAST_DECAP */ @@ -4281,17 +4150,14 @@ encode_DECAP(const struct ofpact_decap *decap, } static char * OVS_WARN_UNUSED_RESULT -parse_DECAP(char *arg, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_DECAP(char *arg, const struct ofpact_parse_params *pp) { struct ofpact_decap *decap; char *key, *value, *pos; char *error = NULL; uint16_t ns, type; - decap = ofpact_put_DECAP(ofpacts); + decap = ofpact_put_DECAP(pp->ofpacts); /* Default next packet_type is PT_USE_NEXT_PROTO. */ decap->new_pkt_type = htonl(PT_USE_NEXT_PROTO); @@ -4328,16 +4194,15 @@ parse_DECAP(char *arg, static void format_DECAP(const struct ofpact_decap *a, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%sdecap(%s", colors.paren, colors.end); + ds_put_format(fp->s, "%sdecap(%s", colors.paren, colors.end); if (a->new_pkt_type != htonl(PT_USE_NEXT_PROTO)) { - ds_put_format(s, "packet_type(ns=%"PRIu16",id=%#"PRIx16")", + ds_put_format(fp->s, "packet_type(ns=%"PRIu16",id=%#"PRIx16")", pt_ns(a->new_pkt_type), pt_ns_type(a->new_pkt_type)); } - ds_put_format(s, "%s)%s", colors.paren, colors.end); + ds_put_format(fp->s, "%s)%s", colors.paren, colors.end); } /* Action dec_nsh_ttl */ @@ -4357,20 +4222,17 @@ encode_DEC_NSH_TTL(const struct ofpact_null *null OVS_UNUSED, } static char * OVS_WARN_UNUSED_RESULT -parse_DEC_NSH_TTL(char *arg OVS_UNUSED, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_DEC_NSH_TTL(char *arg OVS_UNUSED, const struct ofpact_parse_params *pp) { - ofpact_put_DEC_NSH_TTL(ofpacts); + ofpact_put_DEC_NSH_TTL(pp->ofpacts); return NULL; } static void format_DEC_NSH_TTL(const struct ofpact_null *a OVS_UNUSED, - const struct ofputil_port_map *port_map OVS_UNUSED, struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%sdec_nsh_ttl%s", colors.special, colors.end); + ds_put_format(fp->s, "%sdec_nsh_ttl%s", colors.special, colors.end); } @@ -4517,19 +4379,16 @@ encode_RESUBMIT(const struct ofpact_resubmit *resubmit, } static char * OVS_WARN_UNUSED_RESULT -parse_RESUBMIT(char *arg, - const struct ofputil_port_map *port_map, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_RESUBMIT(char *arg, const struct ofpact_parse_params *pp) { struct ofpact_resubmit *resubmit; char *in_port_s, *table_s, *ct_s; - resubmit = ofpact_put_RESUBMIT(ofpacts); + resubmit = ofpact_put_RESUBMIT(pp->ofpacts); in_port_s = strsep(&arg, ","); if (in_port_s && in_port_s[0]) { - if (!ofputil_port_from_string(in_port_s, port_map, + if (!ofputil_port_from_string(in_port_s, pp->port_map, &resubmit->in_port)) { return xasprintf("%s: resubmit to unknown port", in_port_s); } @@ -4570,24 +4429,24 @@ parse_RESUBMIT(char *arg, static void format_RESUBMIT(const struct ofpact_resubmit *a, - const struct ofputil_port_map *port_map, struct ds *s) + const struct ofpact_format_params *fp) { if (a->in_port != OFPP_IN_PORT && a->table_id == 255) { - ds_put_format(s, "%sresubmit:%s", colors.special, colors.end); - ofputil_format_port(a->in_port, port_map, s); + ds_put_format(fp->s, "%sresubmit:%s", colors.special, colors.end); + ofputil_format_port(a->in_port, fp->port_map, fp->s); } else { - ds_put_format(s, "%sresubmit(%s", colors.paren, colors.end); + ds_put_format(fp->s, "%sresubmit(%s", colors.paren, colors.end); if (a->in_port != OFPP_IN_PORT) { - ofputil_format_port(a->in_port, port_map, s); + ofputil_format_port(a->in_port, fp->port_map, fp->s); } - ds_put_char(s, ','); + ds_put_char(fp->s, ','); if (a->table_id != 255) { - ds_put_format(s, "%"PRIu8, a->table_id); + ds_put_format(fp->s, "%"PRIu8, a->table_id); } if (a->with_ct_orig) { - ds_put_cstr(s, ",ct"); + ds_put_cstr(fp->s, ",ct"); } - ds_put_format(s, "%s)%s", colors.paren, colors.end); + ds_put_format(fp->s, "%s)%s", colors.paren, colors.end); } } @@ -5163,18 +5022,16 @@ encode_LEARN(const struct ofpact_learn *learn, } static char * OVS_WARN_UNUSED_RESULT -parse_LEARN(char *arg, const struct ofputil_port_map *port_map, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_LEARN(char *arg, const struct ofpact_parse_params *pp) { - return learn_parse(arg, port_map, ofpacts); + return learn_parse(arg, pp->port_map, pp->ofpacts); } static void format_LEARN(const struct ofpact_learn *a, - const struct ofputil_port_map *port_map, struct ds *s) + const struct ofpact_format_params *fp) { - learn_format(a, port_map, s); + learn_format(a, fp->port_map, fp->s); } /* Action structure for NXAST_CONJUNCTION. */ @@ -5227,20 +5084,16 @@ encode_CONJUNCTION(const struct ofpact_conjunction *oc, static void format_CONJUNCTION(const struct ofpact_conjunction *oc, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%sconjunction(%s%"PRIu32",%d/%"PRIu8"%s)%s", + ds_put_format(fp->s, "%sconjunction(%s%"PRIu32",%d/%"PRIu8"%s)%s", colors.paren, colors.end, oc->id, oc->clause + 1, oc->n_clauses, colors.paren, colors.end); } static char * OVS_WARN_UNUSED_RESULT -parse_CONJUNCTION(const char *arg, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_CONJUNCTION(const char *arg, const struct ofpact_parse_params *pp) { uint8_t n_clauses; uint8_t clause; @@ -5263,7 +5116,7 @@ parse_CONJUNCTION(const char *arg, "number of clauses"); } - add_conjunction(ofpacts, id, clause - 1, n_clauses); + add_conjunction(pp->ofpacts, id, clause - 1, n_clauses); return NULL; } @@ -5382,20 +5235,16 @@ encode_MULTIPATH(const struct ofpact_multipath *mp, } static char * OVS_WARN_UNUSED_RESULT -parse_MULTIPATH(const char *arg, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_MULTIPATH(const char *arg, const struct ofpact_parse_params *pp) { - return multipath_parse(ofpact_put_MULTIPATH(ofpacts), arg); + return multipath_parse(ofpact_put_MULTIPATH(pp->ofpacts), arg); } static void format_MULTIPATH(const struct ofpact_multipath *a, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - multipath_format(a, s); + multipath_format(a, fp->s); } /* Action structure for NXAST_NOTE. @@ -5449,30 +5298,27 @@ encode_NOTE(const struct ofpact_note *note, } static char * OVS_WARN_UNUSED_RESULT -parse_NOTE(const char *arg, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) -{ - size_t start_ofs = ofpacts->size; - ofpact_put_NOTE(ofpacts); - arg = ofpbuf_put_hex(ofpacts, arg, NULL); +parse_NOTE(const char *arg, const struct ofpact_parse_params *pp) +{ + size_t start_ofs = pp->ofpacts->size; + ofpact_put_NOTE(pp->ofpacts); + arg = ofpbuf_put_hex(pp->ofpacts, arg, NULL); if (arg[0]) { return xstrdup("bad hex digit in `note' argument"); } - struct ofpact_note *note = ofpbuf_at_assert(ofpacts, start_ofs, + struct ofpact_note *note = ofpbuf_at_assert(pp->ofpacts, start_ofs, sizeof *note); - note->length = ofpacts->size - (start_ofs + sizeof *note); - ofpact_finish_NOTE(ofpacts, ¬e); + note->length = pp->ofpacts->size - (start_ofs + sizeof *note); + ofpact_finish_NOTE(pp->ofpacts, ¬e); return NULL; } static void format_NOTE(const struct ofpact_note *a, - const struct ofputil_port_map *port_map OVS_UNUSED, struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%snote:%s", colors.param, colors.end); - format_hex_arg(s, a->data, a->length); + ds_put_format(fp->s, "%snote:%s", colors.param, colors.end); + format_hex_arg(fp->s, a->data, a->length); } /* Exit action. */ @@ -5492,20 +5338,17 @@ encode_EXIT(const struct ofpact_null *null OVS_UNUSED, } static char * OVS_WARN_UNUSED_RESULT -parse_EXIT(char *arg OVS_UNUSED, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_EXIT(char *arg OVS_UNUSED, const struct ofpact_parse_params *pp) { - ofpact_put_EXIT(ofpacts); + ofpact_put_EXIT(pp->ofpacts); return NULL; } static void format_EXIT(const struct ofpact_null *a OVS_UNUSED, - const struct ofputil_port_map *port_map OVS_UNUSED, struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%sexit%s", colors.special, colors.end); + ds_put_format(fp->s, "%sexit%s", colors.special, colors.end); } /* Unroll xlate action. */ @@ -5520,19 +5363,16 @@ encode_UNROLL_XLATE(const struct ofpact_unroll_xlate *unroll OVS_UNUSED, static char * OVS_WARN_UNUSED_RESULT parse_UNROLL_XLATE(char *arg OVS_UNUSED, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts OVS_UNUSED, - enum ofputil_protocol *usable_protocols OVS_UNUSED) + const struct ofpact_parse_params *pp OVS_UNUSED) { OVS_NOT_REACHED(); } static void format_UNROLL_XLATE(const struct ofpact_unroll_xlate *a, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%sunroll_xlate(%s%stable=%s%"PRIu8 + ds_put_format(fp->s, "%sunroll_xlate(%s%stable=%s%"PRIu8 ", %scookie=%s%"PRIu64"%s)%s", colors.paren, colors.end, colors.special, colors.end, a->rule_table_id, @@ -5587,33 +5427,30 @@ encode_CLONE(const struct ofpact_nest *clone, } static char * OVS_WARN_UNUSED_RESULT -parse_CLONE(char *arg, const struct ofputil_port_map *port_map, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols) +parse_CLONE(char *arg, const struct ofpact_parse_params *pp) { - const size_t clone_offset = ofpacts_pull(ofpacts); - struct ofpact_nest *clone = ofpact_put_CLONE(ofpacts); + const size_t clone_offset = ofpacts_pull(pp->ofpacts); + struct ofpact_nest *clone = ofpact_put_CLONE(pp->ofpacts); char *error; - ofpbuf_pull(ofpacts, sizeof *clone); - error = ofpacts_parse_copy(arg, port_map, ofpacts, - usable_protocols, false, 0); + ofpbuf_pull(pp->ofpacts, sizeof *clone); + error = ofpacts_parse_copy(arg, pp, false, 0); /* header points to the action list */ - ofpacts->header = ofpbuf_push_uninit(ofpacts, sizeof *clone); - clone = ofpacts->header; + pp->ofpacts->header = ofpbuf_push_uninit(pp->ofpacts, sizeof *clone); + clone = pp->ofpacts->header; - ofpact_finish_CLONE(ofpacts, &clone); - ofpbuf_push_uninit(ofpacts, clone_offset); + ofpact_finish_CLONE(pp->ofpacts, &clone); + ofpbuf_push_uninit(pp->ofpacts, clone_offset); return error; } static void format_CLONE(const struct ofpact_nest *a, - const struct ofputil_port_map *port_map, struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%sclone(%s", colors.paren, colors.end); - ofpacts_format(a->actions, ofpact_nest_get_action_len(a), port_map, s); - ds_put_format(s, "%s)%s", colors.paren, colors.end); + ds_put_format(fp->s, "%sclone(%s", colors.paren, colors.end); + ofpacts_format(a->actions, ofpact_nest_get_action_len(a), fp); + ds_put_format(fp->s, "%s)%s", colors.paren, colors.end); } /* Action structure for NXAST_SAMPLE. @@ -5766,16 +5603,14 @@ encode_SAMPLE(const struct ofpact_sample *sample, } /* Parses 'arg' as the argument to a "sample" action, and appends such an - * action to 'ofpacts'. + * action to 'pp->ofpacts'. * * Returns NULL if successful, otherwise a malloc()'d string describing the * error. The caller is responsible for freeing the returned string. */ static char * OVS_WARN_UNUSED_RESULT -parse_SAMPLE(char *arg, const struct ofputil_port_map *port_map, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_SAMPLE(char *arg, const struct ofpact_parse_params *pp) { - struct ofpact_sample *os = ofpact_put_SAMPLE(ofpacts); + struct ofpact_sample *os = ofpact_put_SAMPLE(pp->ofpacts); os->sampling_port = OFPP_NONE; os->direction = NX_ACTION_SAMPLE_DEFAULT; @@ -5795,7 +5630,7 @@ parse_SAMPLE(char *arg, const struct ofputil_port_map *port_map, } else if (!strcmp(key, "obs_point_id")) { error = str_to_u32(value, &os->obs_point_id); } else if (!strcmp(key, "sampling_port")) { - if (!ofputil_port_from_string(value, port_map, + if (!ofputil_port_from_string(value, pp->port_map, &os->sampling_port)) { error = xasprintf("%s: unknown port", value); } @@ -5820,9 +5655,9 @@ parse_SAMPLE(char *arg, const struct ofputil_port_map *port_map, static void format_SAMPLE(const struct ofpact_sample *a, - const struct ofputil_port_map *port_map, struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%ssample(%s%sprobability=%s%"PRIu16 + ds_put_format(fp->s, "%ssample(%s%sprobability=%s%"PRIu16 ",%scollector_set_id=%s%"PRIu32 ",%sobs_domain_id=%s%"PRIu32 ",%sobs_point_id=%s%"PRIu32, @@ -5832,15 +5667,15 @@ format_SAMPLE(const struct ofpact_sample *a, colors.param, colors.end, a->obs_domain_id, colors.param, colors.end, a->obs_point_id); if (a->sampling_port != OFPP_NONE) { - ds_put_format(s, ",%ssampling_port=%s", colors.param, colors.end); - ofputil_format_port(a->sampling_port, port_map, s); + ds_put_format(fp->s, ",%ssampling_port=%s", colors.param, colors.end); + ofputil_format_port(a->sampling_port, fp->port_map, fp->s); } if (a->direction == NX_ACTION_SAMPLE_INGRESS) { - ds_put_format(s, ",%singress%s", colors.param, colors.end); + ds_put_format(fp->s, ",%singress%s", colors.param, colors.end); } else if (a->direction == NX_ACTION_SAMPLE_EGRESS) { - ds_put_format(s, ",%segress%s", colors.param, colors.end); + ds_put_format(fp->s, ",%segress%s", colors.param, colors.end); } - ds_put_format(s, "%s)%s", colors.paren, colors.end); + ds_put_format(fp->s, "%s)%s", colors.paren, colors.end); } /* debug instructions. */ @@ -5873,21 +5708,17 @@ encode_DEBUG_RECIRC(const struct ofpact_null *n OVS_UNUSED, } static char * OVS_WARN_UNUSED_RESULT -parse_DEBUG_RECIRC(char *arg OVS_UNUSED, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_DEBUG_RECIRC(char *arg OVS_UNUSED, const struct ofpact_parse_params *pp) { - ofpact_put_DEBUG_RECIRC(ofpacts); + ofpact_put_DEBUG_RECIRC(pp->ofpacts); return NULL; } static void format_DEBUG_RECIRC(const struct ofpact_null *a OVS_UNUSED, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%sdebug_recirc%s", colors.value, colors.end); + ds_put_format(fp->s, "%sdebug_recirc%s", colors.value, colors.end); } static enum ofperr @@ -5910,21 +5741,17 @@ encode_DEBUG_SLOW(const struct ofpact_null *n OVS_UNUSED, } static char * OVS_WARN_UNUSED_RESULT -parse_DEBUG_SLOW(char *arg OVS_UNUSED, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_DEBUG_SLOW(char *arg OVS_UNUSED, const struct ofpact_parse_params *pp) { - ofpact_put_DEBUG_SLOW(ofpacts); + ofpact_put_DEBUG_SLOW(pp->ofpacts); return NULL; } static void format_DEBUG_SLOW(const struct ofpact_null *a OVS_UNUSED, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%sdebug_slow%s", colors.value, colors.end); + ds_put_format(fp->s, "%sdebug_slow%s", colors.value, colors.end); } /* Action structure for NXAST_CT. @@ -6187,25 +6014,22 @@ encode_CT(const struct ofpact_conntrack *conntrack, } static char *OVS_WARN_UNUSED_RESULT -parse_NAT(char *arg, const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *, enum ofputil_protocol * OVS_UNUSED); +parse_NAT(char *arg, const struct ofpact_parse_params *pp); /* Parses 'arg' as the argument to a "ct" action, and appends such an - * action to 'ofpacts'. + * action to 'pp->ofpacts'. * * Returns NULL if successful, otherwise a malloc()'d string describing the * error. The caller is responsible for freeing the returned string. */ static char * OVS_WARN_UNUSED_RESULT -parse_CT(char *arg, const struct ofputil_port_map *port_map, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols) +parse_CT(char *arg, const struct ofpact_parse_params *pp) { - const size_t ct_offset = ofpacts_pull(ofpacts); + const size_t ct_offset = ofpacts_pull(pp->ofpacts); struct ofpact_conntrack *oc; char *error = NULL; char *key, *value; - oc = ofpact_put_CT(ofpacts); + oc = ofpact_put_CT(pp->ofpacts); oc->flags = 0; oc->recirc_table = NX_CT_RECIRC_NONE; while (ofputil_parse_key_value(&arg, &key, &value)) { @@ -6231,26 +6055,27 @@ parse_CT(char *arg, const struct ofputil_port_map *port_map, } else if (!strcmp(key, "alg")) { error = str_to_connhelper(value, &oc->alg); } else if (!strcmp(key, "nat")) { - const size_t nat_offset = ofpacts_pull(ofpacts); + const size_t nat_offset = ofpacts_pull(pp->ofpacts); - error = parse_NAT(value, port_map, ofpacts, usable_protocols); + error = parse_NAT(value, pp); /* Update CT action pointer and length. */ - ofpacts->header = ofpbuf_push_uninit(ofpacts, nat_offset); - oc = ofpacts->header; + pp->ofpacts->header = ofpbuf_push_uninit(pp->ofpacts, nat_offset); + oc = pp->ofpacts->header; } else if (!strcmp(key, "exec")) { /* Hide existing actions from ofpacts_parse_copy(), so the * nesting can be handled transparently. */ enum ofputil_protocol usable_protocols2; - const size_t exec_offset = ofpacts_pull(ofpacts); + const size_t exec_offset = ofpacts_pull(pp->ofpacts); /* Initializes 'usable_protocol2', fold it back to * '*usable_protocols' afterwards, so that we do not lose * restrictions already in there. */ - error = ofpacts_parse_copy(value, port_map, ofpacts, - &usable_protocols2, false, OFPACT_CT); - *usable_protocols &= usable_protocols2; - ofpacts->header = ofpbuf_push_uninit(ofpacts, exec_offset); - oc = ofpacts->header; + struct ofpact_parse_params pp2 = *pp; + pp2.usable_protocols = &usable_protocols2; + error = ofpacts_parse_copy(value, &pp2, false, OFPACT_CT); + *pp->usable_protocols &= usable_protocols2; + pp->ofpacts->header = ofpbuf_push_uninit(pp->ofpacts, exec_offset); + oc = pp->ofpacts->header; } else { error = xasprintf("invalid argument to \"ct\" action: `%s'", key); } @@ -6261,8 +6086,8 @@ parse_CT(char *arg, const struct ofputil_port_map *port_map, if (!error && oc->flags & NX_CT_F_FORCE && !(oc->flags & NX_CT_F_COMMIT)) { error = xasprintf("\"force\" flag requires \"commit\" flag."); } - ofpact_finish_CT(ofpacts, &oc); - ofpbuf_push_uninit(ofpacts, ct_offset); + ofpact_finish_CT(pp->ofpacts, &oc); + ofpbuf_push_uninit(pp->ofpacts, ct_offset); return error; } @@ -6286,31 +6111,29 @@ format_alg(int port, struct ds *s) } static void format_NAT(const struct ofpact_nat *, - const struct ofputil_port_map *port_map, - struct ds *ds); + const struct ofpact_format_params *fp); static void format_CT(const struct ofpact_conntrack *a, - const struct ofputil_port_map *port_map, - struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%sct(%s", colors.paren, colors.end); + ds_put_format(fp->s, "%sct(%s", colors.paren, colors.end); if (a->flags & NX_CT_F_COMMIT) { - ds_put_format(s, "%scommit%s,", colors.value, colors.end); + ds_put_format(fp->s, "%scommit%s,", colors.value, colors.end); } if (a->flags & NX_CT_F_FORCE) { - ds_put_format(s, "%sforce%s,", colors.value, colors.end); + ds_put_format(fp->s, "%sforce%s,", colors.value, colors.end); } if (a->recirc_table != NX_CT_RECIRC_NONE) { - ds_put_format(s, "%stable=%s%"PRIu8",", + ds_put_format(fp->s, "%stable=%s%"PRIu8",", colors.special, colors.end, a->recirc_table); } if (a->zone_src.field) { - ds_put_format(s, "%szone=%s", colors.param, colors.end); - mf_format_subfield(&a->zone_src, s); - ds_put_char(s, ','); + ds_put_format(fp->s, "%szone=%s", colors.param, colors.end); + mf_format_subfield(&a->zone_src, fp->s); + ds_put_char(fp->s, ','); } else if (a->zone_imm) { - ds_put_format(s, "%szone=%s%"PRIu16",", + ds_put_format(fp->s, "%szone=%s%"PRIu16",", colors.param, colors.end, a->zone_imm); } /* If the first action is a NAT action, format it outside of the 'exec' @@ -6318,19 +6141,19 @@ format_CT(const struct ofpact_conntrack *a, const struct ofpact *action = a->actions; size_t actions_len = ofpact_ct_get_action_len(a); if (actions_len && action->type == OFPACT_NAT) { - format_NAT(ofpact_get_NAT(action), port_map, s); - ds_put_char(s, ','); + format_NAT(ofpact_get_NAT(action), fp); + ds_put_char(fp->s, ','); actions_len -= OFPACT_ALIGN(action->len); action = ofpact_next(action); } if (actions_len) { - ds_put_format(s, "%sexec(%s", colors.paren, colors.end); - ofpacts_format(action, actions_len, port_map, s); - ds_put_format(s, "%s),%s", colors.paren, colors.end); + ds_put_format(fp->s, "%sexec(%s", colors.paren, colors.end); + ofpacts_format(action, actions_len, fp); + ds_put_format(fp->s, "%s),%s", colors.paren, colors.end); } - format_alg(a->alg, s); - ds_chomp(s, ','); - ds_put_format(s, "%s)%s", colors.paren, colors.end); + format_alg(a->alg, fp->s); + ds_chomp(fp->s, ','); + ds_put_format(fp->s, "%s)%s", colors.paren, colors.end); } /* ct_clear action. */ @@ -6351,21 +6174,17 @@ encode_CT_CLEAR(const struct ofpact_null *null OVS_UNUSED, } static char * OVS_WARN_UNUSED_RESULT -parse_CT_CLEAR(char *arg OVS_UNUSED, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_CT_CLEAR(char *arg OVS_UNUSED, const struct ofpact_parse_params *pp) { - ofpact_put_CT_CLEAR(ofpacts); + ofpact_put_CT_CLEAR(pp->ofpacts); return NULL; } static void format_CT_CLEAR(const struct ofpact_null *a OVS_UNUSED, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%sct_clear%s", colors.value, colors.end); + ds_put_format(fp->s, "%sct_clear%s", colors.value, colors.end); } /* NAT action. */ @@ -6547,64 +6366,62 @@ decode_NXAST_RAW_NAT(const struct nx_action_nat *nan, } static void -format_NAT(const struct ofpact_nat *a, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *ds) +format_NAT(const struct ofpact_nat *a, const struct ofpact_format_params *fp) { - ds_put_format(ds, "%snat%s", colors.paren, colors.end); + ds_put_format(fp->s, "%snat%s", colors.paren, colors.end); if (a->flags & (NX_NAT_F_SRC | NX_NAT_F_DST)) { - ds_put_format(ds, "%s(%s", colors.paren, colors.end); - ds_put_format(ds, a->flags & NX_NAT_F_SRC ? "%ssrc%s" : "%sdst%s", + ds_put_format(fp->s, "%s(%s", colors.paren, colors.end); + ds_put_format(fp->s, a->flags & NX_NAT_F_SRC ? "%ssrc%s" : "%sdst%s", colors.param, colors.end); if (a->range_af != AF_UNSPEC) { - ds_put_format(ds, "%s=%s", colors.param, colors.end); + ds_put_format(fp->s, "%s=%s", colors.param, colors.end); if (a->range_af == AF_INET) { - ds_put_format(ds, IP_FMT, IP_ARGS(a->range.addr.ipv4.min)); + ds_put_format(fp->s, IP_FMT, IP_ARGS(a->range.addr.ipv4.min)); if (a->range.addr.ipv4.max && a->range.addr.ipv4.max != a->range.addr.ipv4.min) { - ds_put_format(ds, "-"IP_FMT, + ds_put_format(fp->s, "-"IP_FMT, IP_ARGS(a->range.addr.ipv4.max)); } } else if (a->range_af == AF_INET6) { - ipv6_format_addr_bracket(&a->range.addr.ipv6.min, ds, + ipv6_format_addr_bracket(&a->range.addr.ipv6.min, fp->s, a->range.proto.min); if (!ipv6_mask_is_any(&a->range.addr.ipv6.max) && memcmp(&a->range.addr.ipv6.max, &a->range.addr.ipv6.min, sizeof(struct in6_addr)) != 0) { - ds_put_char(ds, '-'); - ipv6_format_addr_bracket(&a->range.addr.ipv6.max, ds, + ds_put_char(fp->s, '-'); + ipv6_format_addr_bracket(&a->range.addr.ipv6.max, fp->s, a->range.proto.min); } } if (a->range.proto.min) { - ds_put_char(ds, ':'); - ds_put_format(ds, "%"PRIu16, a->range.proto.min); + ds_put_char(fp->s, ':'); + ds_put_format(fp->s, "%"PRIu16, a->range.proto.min); if (a->range.proto.max && a->range.proto.max != a->range.proto.min) { - ds_put_format(ds, "-%"PRIu16, a->range.proto.max); + ds_put_format(fp->s, "-%"PRIu16, a->range.proto.max); } } - ds_put_char(ds, ','); + ds_put_char(fp->s, ','); if (a->flags & NX_NAT_F_PERSISTENT) { - ds_put_format(ds, "%spersistent%s,", + ds_put_format(fp->s, "%spersistent%s,", colors.value, colors.end); } if (a->flags & NX_NAT_F_PROTO_HASH) { - ds_put_format(ds, "%shash%s,", colors.value, colors.end); + ds_put_format(fp->s, "%shash%s,", colors.value, colors.end); } if (a->flags & NX_NAT_F_PROTO_RANDOM) { - ds_put_format(ds, "%srandom%s,", colors.value, colors.end); + ds_put_format(fp->s, "%srandom%s,", colors.value, colors.end); } } - ds_chomp(ds, ','); - ds_put_format(ds, "%s)%s", colors.paren, colors.end); + ds_chomp(fp->s, ','); + ds_put_format(fp->s, "%s)%s", colors.paren, colors.end); } } @@ -6668,17 +6485,14 @@ error: /* Parses 'arg' as the argument to a "nat" action, and appends such an - * action to 'ofpacts'. + * action to 'pp->ofpacts'. * * Returns NULL if successful, otherwise a malloc()'d string describing the * error. The caller is responsible for freeing the returned string. */ static char * OVS_WARN_UNUSED_RESULT -parse_NAT(char *arg, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_NAT(char *arg, const struct ofpact_parse_params *pp) { - struct ofpact_nat *on = ofpact_put_NAT(ofpacts); + struct ofpact_nat *on = ofpact_put_NAT(pp->ofpacts); char *key, *value; on->flags = 0; @@ -6766,9 +6580,7 @@ encode_OUTPUT_TRUNC(const struct ofpact_output_trunc *output_trunc, static char * OVS_WARN_UNUSED_RESULT parse_OUTPUT_TRUNC(const char *arg, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts OVS_UNUSED, - enum ofputil_protocol *usable_protocols OVS_UNUSED) + const struct ofpact_parse_params *pp OVS_UNUSED) { /* Disable output_trunc parsing. Expose as output(port=N,max_len=M) and * reuse parse_OUTPUT to parse output_trunc action. */ @@ -6777,11 +6589,11 @@ parse_OUTPUT_TRUNC(const char *arg, static void format_OUTPUT_TRUNC(const struct ofpact_output_trunc *a, - const struct ofputil_port_map *port_map, struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%soutput%s(port=", colors.special, colors.end); - ofputil_format_port(a->port, port_map, s); - ds_put_format(s, ",max_len=%"PRIu32")", a->max_len); + ds_put_format(fp->s, "%soutput%s(port=", colors.special, colors.end); + ofputil_format_port(a->port, fp->port_map, fp->s); + ds_put_format(fp->s, ",max_len=%"PRIu32")", a->max_len); } @@ -6797,21 +6609,17 @@ encode_METER(const struct ofpact_meter *meter, } static char * OVS_WARN_UNUSED_RESULT -parse_METER(char *arg, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols) +parse_METER(char *arg, const struct ofpact_parse_params *pp) { - *usable_protocols &= OFPUTIL_P_OF13_UP; - return str_to_u32(arg, &ofpact_put_METER(ofpacts)->meter_id); + *pp->usable_protocols &= OFPUTIL_P_OF13_UP; + return str_to_u32(arg, &ofpact_put_METER(pp->ofpacts)->meter_id); } static void format_METER(const struct ofpact_meter *a, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%smeter:%s%"PRIu32, + ds_put_format(fp->s, "%smeter:%s%"PRIu32, colors.param, colors.end, a->meter_id); } @@ -6828,21 +6636,17 @@ encode_CLEAR_ACTIONS(const struct ofpact_null *null OVS_UNUSED, } static char * OVS_WARN_UNUSED_RESULT -parse_CLEAR_ACTIONS(char *arg OVS_UNUSED, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_CLEAR_ACTIONS(char *arg OVS_UNUSED, const struct ofpact_parse_params *pp) { - ofpact_put_CLEAR_ACTIONS(ofpacts); + ofpact_put_CLEAR_ACTIONS(pp->ofpacts); return NULL; } static void format_CLEAR_ACTIONS(const struct ofpact_null *a OVS_UNUSED, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%sclear_actions%s", colors.value, colors.end); + ds_put_format(fp->s, "%sclear_actions%s", colors.value, colors.end); } /* Write-Actions instruction. */ @@ -6863,17 +6667,15 @@ encode_WRITE_ACTIONS(const struct ofpact_nest *actions, } static char * OVS_WARN_UNUSED_RESULT -parse_WRITE_ACTIONS(char *arg, const struct ofputil_port_map *port_map, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols) +parse_WRITE_ACTIONS(char *arg, const struct ofpact_parse_params *pp) { - size_t ofs = ofpacts_pull(ofpacts); + size_t ofs = ofpacts_pull(pp->ofpacts); struct ofpact_nest *on; char *error; /* Add a Write-Actions instruction and then pull it off. */ - ofpact_put(ofpacts, OFPACT_WRITE_ACTIONS, sizeof *on); - ofpbuf_pull(ofpacts, sizeof *on); + ofpact_put(pp->ofpacts, OFPACT_WRITE_ACTIONS, sizeof *on); + ofpbuf_pull(pp->ofpacts, sizeof *on); /* Parse nested actions. * @@ -6882,26 +6684,25 @@ parse_WRITE_ACTIONS(char *arg, const struct ofputil_port_map *port_map, * that it doesn't actually include the nested actions. That means that * ofpacts_parse() would reject them as being part of an Apply-Actions that * follows a Write-Actions, which is an invalid order. */ - error = ofpacts_parse(arg, port_map, ofpacts, usable_protocols, false, - OFPACT_WRITE_ACTIONS); + error = ofpacts_parse(arg, pp, false, OFPACT_WRITE_ACTIONS); /* Put the Write-Actions back on and update its length. */ - on = ofpbuf_push_uninit(ofpacts, sizeof *on); - on->ofpact.len = ofpacts->size; + on = ofpbuf_push_uninit(pp->ofpacts, sizeof *on); + on->ofpact.len = pp->ofpacts->size; /* Put any previous actions or instructions back on. */ - ofpbuf_push_uninit(ofpacts, ofs); + ofpbuf_push_uninit(pp->ofpacts, ofs); return error; } static void format_WRITE_ACTIONS(const struct ofpact_nest *a, - const struct ofputil_port_map *port_map, struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%swrite_actions(%s", colors.paren, colors.end); - ofpacts_format(a->actions, ofpact_nest_get_action_len(a), port_map, s); - ds_put_format(s, "%s)%s", colors.paren, colors.end); + ds_put_format(fp->s, "%swrite_actions(%s", colors.paren, colors.end); + ofpacts_format(a->actions, ofpact_nest_get_action_len(a), fp); + ds_put_format(fp->s, "%s)%s", colors.paren, colors.end); } /* Action structure for NXAST_WRITE_METADATA. @@ -6956,17 +6757,14 @@ encode_WRITE_METADATA(const struct ofpact_metadata *metadata, } static char * OVS_WARN_UNUSED_RESULT -parse_WRITE_METADATA(char *arg, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols) +parse_WRITE_METADATA(char *arg, const struct ofpact_parse_params *pp) { struct ofpact_metadata *om; char *mask = strchr(arg, '/'); - *usable_protocols &= OFPUTIL_P_NXM_OF11_UP; + *pp->usable_protocols &= OFPUTIL_P_NXM_OF11_UP; - om = ofpact_put_WRITE_METADATA(ofpacts); + om = ofpact_put_WRITE_METADATA(pp->ofpacts); if (mask) { char *error; @@ -6984,13 +6782,12 @@ parse_WRITE_METADATA(char *arg, static void format_WRITE_METADATA(const struct ofpact_metadata *a, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%swrite_metadata:%s%#"PRIx64, + ds_put_format(fp->s, "%swrite_metadata:%s%#"PRIx64, colors.param, colors.end, ntohll(a->metadata)); if (a->mask != OVS_BE64_MAX) { - ds_put_format(s, "/%#"PRIx64, ntohll(a->mask)); + ds_put_format(fp->s, "/%#"PRIx64, ntohll(a->mask)); } } @@ -7016,12 +6813,9 @@ encode_GOTO_TABLE(const struct ofpact_goto_table *goto_table, } static char * OVS_WARN_UNUSED_RESULT -parse_GOTO_TABLE(char *arg, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols OVS_UNUSED) +parse_GOTO_TABLE(char *arg, const struct ofpact_parse_params *pp) { - struct ofpact_goto_table *ogt = ofpact_put_GOTO_TABLE(ofpacts); + struct ofpact_goto_table *ogt = ofpact_put_GOTO_TABLE(pp->ofpacts); char *table_s = strsep(&arg, ","); if (!table_s || !table_s[0]) { return xstrdup("instruction goto-table needs table id"); @@ -7031,10 +6825,9 @@ parse_GOTO_TABLE(char *arg, static void format_GOTO_TABLE(const struct ofpact_goto_table *a, - const struct ofputil_port_map *port_map OVS_UNUSED, - struct ds *s) + const struct ofpact_format_params *fp) { - ds_put_format(s, "%sgoto_table:%s%"PRIu8, + ds_put_format(fp->s, "%sgoto_table:%s%"PRIu8, colors.param, colors.end, a->table_id); } @@ -8780,10 +8573,12 @@ ofpacts_equal_stringwise(const struct ofpact *a, size_t a_len, const struct ofpact *b, size_t b_len) { struct ds a_s = DS_EMPTY_INITIALIZER; - struct ds b_s = DS_EMPTY_INITIALIZER; + struct ofpact_format_params a_fp = { .s = &a_s }; + ofpacts_format(a, a_len, &a_fp); - ofpacts_format(a, a_len, NULL, &a_s); - ofpacts_format(b, b_len, NULL, &b_s); + struct ds b_s = DS_EMPTY_INITIALIZER; + struct ofpact_format_params b_fp = { .s = &b_s }; + ofpacts_format(b, b_len, &b_fp); bool equal = !strcmp(ds_cstr(&a_s), ds_cstr(&b_s)); @@ -8821,13 +8616,12 @@ ofpacts_get_meter(const struct ofpact ofpacts[], size_t ofpacts_len) static void ofpact_format(const struct ofpact *a, - const struct ofputil_port_map *port_map, struct ds *s) + const struct ofpact_format_params *fp) { switch (a->type) { #define OFPACT(ENUM, STRUCT, MEMBER, NAME) \ case OFPACT_##ENUM: \ - format_##ENUM(ALIGNED_CAST(const struct STRUCT *, a), \ - port_map, s); \ + format_##ENUM(ALIGNED_CAST(const struct STRUCT *, a), fp); \ break; OFPACTS #undef OFPACT @@ -8837,23 +8631,23 @@ ofpact_format(const struct ofpact *a, } /* Appends a string representing the 'ofpacts_len' bytes of ofpacts in - * 'ofpacts' to 'string'. If 'port_map' is nonnull, uses it to translate - * port numbers to names in output. */ + * 'ofpacts' to 'fp->s'. If 'port_map' is nonnull, uses it to translate port + * numbers to names in output. */ void ofpacts_format(const struct ofpact *ofpacts, size_t ofpacts_len, - const struct ofputil_port_map *port_map, struct ds *string) + const struct ofpact_format_params *fp) { if (!ofpacts_len) { - ds_put_format(string, "%sdrop%s", colors.drop, colors.end); + ds_put_format(fp->s, "%sdrop%s", colors.drop, colors.end); } else { const struct ofpact *a; OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) { if (a != ofpacts) { - ds_put_char(string, ','); + ds_put_char(fp->s, ','); } - ofpact_format(a, port_map, string); + ofpact_format(a, fp); } } } @@ -8907,13 +8701,12 @@ ofpact_finish(struct ofpbuf *ofpacts, struct ofpact *ofpact) static char * OVS_WARN_UNUSED_RESULT ofpact_parse(enum ofpact_type type, char *value, - const struct ofputil_port_map *port_map, struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols) + const struct ofpact_parse_params *pp) { switch (type) { #define OFPACT(ENUM, STRUCT, MEMBER, NAME) \ case OFPACT_##ENUM: \ - return parse_##ENUM(value, port_map, ofpacts, usable_protocols); + return parse_##ENUM(value, pp); OFPACTS #undef OFPACT default: @@ -8943,9 +8736,7 @@ ofpact_type_from_name(const char *name, enum ofpact_type *type) * If 'outer_action' is specified, indicates that the actions being parsed * are nested within another action of the type specified in 'outer_action'. */ static char * OVS_WARN_UNUSED_RESULT -ofpacts_parse__(char *str, const struct ofputil_port_map *port_map, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols, +ofpacts_parse__(char *str, const struct ofpact_parse_params *pp, bool allow_instructions, enum ofpact_type outer_action) { int prev_inst = -1; @@ -8962,31 +8753,28 @@ ofpacts_parse__(char *str, const struct ofputil_port_map *port_map, ofp_port_t port; if (ofpact_type_from_name(key, &type)) { - error = ofpact_parse(type, value, port_map, - ofpacts, usable_protocols); + error = ofpact_parse(type, value, pp); inst = ovs_instruction_type_from_ofpact_type(type); } else if (!strcasecmp(key, "mod_vlan_vid")) { - error = parse_set_vlan_vid(value, ofpacts, true); + error = parse_set_vlan_vid(value, true, pp); } else if (!strcasecmp(key, "mod_vlan_pcp")) { - error = parse_set_vlan_pcp(value, ofpacts, true); + error = parse_set_vlan_pcp(value, true, pp); } else if (!strcasecmp(key, "set_nw_ttl")) { - error = parse_SET_IP_TTL(value, port_map, - ofpacts, usable_protocols); + error = parse_SET_IP_TTL(value, pp); } else if (!strcasecmp(key, "pop_vlan")) { - error = parse_pop_vlan(ofpacts); + error = parse_pop_vlan(pp); } else if (!strcasecmp(key, "set_tunnel64")) { - error = parse_set_tunnel(value, ofpacts, - NXAST_RAW_SET_TUNNEL64); + error = parse_set_tunnel(value, NXAST_RAW_SET_TUNNEL64, pp); } else if (!strcasecmp(key, "load")) { - error = parse_reg_load(value, ofpacts); + error = parse_reg_load(value, pp); } else if (!strcasecmp(key, "bundle_load")) { - error = parse_bundle_load(value, port_map, ofpacts); + error = parse_bundle_load(value, pp); } else if (!strcasecmp(key, "drop")) { drop = true; } else if (!strcasecmp(key, "apply_actions")) { return xstrdup("apply_actions is the default instruction"); - } else if (ofputil_port_from_string(key, port_map, &port)) { - ofpact_put_OUTPUT(ofpacts)->port = port; + } else if (ofputil_port_from_string(key, pp->port_map, &port)) { + ofpact_put_OUTPUT(pp->ofpacts)->port = port; } else { return xasprintf("unknown action %s", key); } @@ -9013,12 +8801,12 @@ ofpacts_parse__(char *str, const struct ofputil_port_map *port_map, prev_inst = inst; } - if (drop && ofpacts->size) { + if (drop && pp->ofpacts->size) { return xstrdup("\"drop\" must not be accompanied by any other action " "or instruction"); } - retval = ofpacts_verify(ofpacts->data, ofpacts->size, + retval = ofpacts_verify(pp->ofpacts->data, pp->ofpacts->size, (allow_instructions ? (1u << N_OVS_INSTRUCTIONS) - 1 : 1u << OVSINST_OFPIT11_APPLY_ACTIONS), @@ -9031,32 +8819,27 @@ ofpacts_parse__(char *str, const struct ofputil_port_map *port_map, } static char * OVS_WARN_UNUSED_RESULT -ofpacts_parse(char *str, const struct ofputil_port_map *port_map, - struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols, +ofpacts_parse(char *str, const struct ofpact_parse_params *pp, bool allow_instructions, enum ofpact_type outer_action) { - uint32_t orig_size = ofpacts->size; - char *error = ofpacts_parse__(str, port_map, ofpacts, usable_protocols, - allow_instructions, outer_action); + uint32_t orig_size = pp->ofpacts->size; + char *error = ofpacts_parse__(str, pp, allow_instructions, outer_action); if (error) { - ofpacts->size = orig_size; + pp->ofpacts->size = orig_size; } return error; } static char * OVS_WARN_UNUSED_RESULT -ofpacts_parse_copy(const char *s_, const struct ofputil_port_map *port_map, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols, +ofpacts_parse_copy(const char *s_, const struct ofpact_parse_params *pp, bool allow_instructions, enum ofpact_type outer_action) { char *error, *s; - *usable_protocols = OFPUTIL_P_ANY; + *pp->usable_protocols = OFPUTIL_P_ANY; s = xstrdup(s_); - error = ofpacts_parse(s, port_map, ofpacts, usable_protocols, - allow_instructions, outer_action); + error = ofpacts_parse(s, pp, allow_instructions, outer_action); free(s); return error; @@ -9069,12 +8852,9 @@ ofpacts_parse_copy(const char *s_, const struct ofputil_port_map *port_map, * Returns NULL if successful, otherwise a malloc()'d string describing the * error. The caller is responsible for freeing the returned string. */ char * OVS_WARN_UNUSED_RESULT -ofpacts_parse_actions(const char *s, const struct ofputil_port_map *port_map, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols) +ofpacts_parse_actions(const char *s, const struct ofpact_parse_params *pp) { - return ofpacts_parse_copy(s, port_map, ofpacts, usable_protocols, - false, 0); + return ofpacts_parse_copy(s, pp, false, 0); } /* Parses 's' as a set of OpenFlow instructions and appends the instructions to @@ -9083,12 +8863,9 @@ ofpacts_parse_actions(const char *s, const struct ofputil_port_map *port_map, * Returns NULL if successful, otherwise a malloc()'d string describing the * error. The caller is responsible for freeing the returned string. */ char * OVS_WARN_UNUSED_RESULT -ofpacts_parse_instructions(const char *s, - const struct ofputil_port_map *port_map, - struct ofpbuf *ofpacts, - enum ofputil_protocol *usable_protocols) +ofpacts_parse_instructions(const char *s, const struct ofpact_parse_params *pp) { - return ofpacts_parse_copy(s, port_map, ofpacts, usable_protocols, true, 0); + return ofpacts_parse_copy(s, pp, true, 0); } const char * diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c index bacbaa63886e..b68081740f09 100644 --- a/lib/ofp-parse.c +++ b/lib/ofp-parse.c @@ -557,8 +557,12 @@ parse_ofp_str__(struct ofputil_flow_mod *fm, int command, char *string, char *error; ofpbuf_init(&ofpacts, 32); - error = ofpacts_parse_instructions(act_str, port_map, &ofpacts, - &action_usable_protocols); + struct ofpact_parse_params pp = { + .port_map = port_map, + .ofpacts = &ofpacts, + .usable_protocols = &action_usable_protocols + }; + error = ofpacts_parse_instructions(act_str, &pp); *usable_protocols &= action_usable_protocols; if (!error) { enum ofperr err; @@ -713,8 +717,12 @@ parse_ofp_packet_out_str__(struct ofputil_packet_out *po, char *string, } if (act_str) { - error = ofpacts_parse_actions(act_str, port_map, &ofpacts, - &action_usable_protocols); + struct ofpact_parse_params pp = { + .port_map = port_map, + .ofpacts = &ofpacts, + .usable_protocols = &action_usable_protocols, + }; + error = ofpacts_parse_actions(act_str, &pp); *usable_protocols &= action_usable_protocols; if (error) { goto out; @@ -1487,8 +1495,12 @@ parse_bucket_str(struct ofputil_bucket *bucket, char *str_, ds_chomp(&actions, ','); ofpbuf_init(&ofpacts, 0); - error = ofpacts_parse_actions(ds_cstr(&actions), port_map, &ofpacts, - usable_protocols); + struct ofpact_parse_params pp = { + .port_map = port_map, + .ofpacts = &ofpacts, + .usable_protocols = usable_protocols, + }; + error = ofpacts_parse_actions(ds_cstr(&actions), &pp); ds_destroy(&actions); if (error) { ofpbuf_uninit(&ofpacts); diff --git a/lib/ofp-print.c b/lib/ofp-print.c index 8a1f426ade36..639d3bddf36d 100644 --- a/lib/ofp-print.c +++ b/lib/ofp-print.c @@ -205,15 +205,20 @@ ofp_print_packet_in(struct ds *string, const struct ofp_header *oh, ds_put_cstr(string, " continuation.conntracked=true\n"); } + struct ofpact_format_params fp = { + .port_map = port_map, + .s = string, + }; + if (pin.actions_len) { ds_put_cstr(string, " continuation.actions="); - ofpacts_format(pin.actions, pin.actions_len, port_map, string); + ofpacts_format(pin.actions, pin.actions_len, &fp); ds_put_char(string, '\n'); } if (pin.action_set_len) { ds_put_cstr(string, " continuation.action_set="); - ofpacts_format(pin.action_set, pin.action_set_len, port_map, string); + ofpacts_format(pin.action_set, pin.action_set_len, &fp); ds_put_char(string, '\n'); } @@ -252,7 +257,11 @@ ofp_print_packet_out(struct ds *string, const struct ofp_header *oh, match_format(&po.flow_metadata, port_map, string, OFP_DEFAULT_PRIORITY); ds_put_cstr(string, " actions="); - ofpacts_format(po.ofpacts, po.ofpacts_len, port_map, string); + struct ofpact_format_params fp = { + .port_map = port_map, + .s = string, + }; + ofpacts_format(po.ofpacts, po.ofpacts_len, &fp); if (po.buffer_id == UINT32_MAX) { ds_put_format(string, " data_len=%"PRIuSIZE, po.packet_len); @@ -916,7 +925,11 @@ ofp_print_flow_mod(struct ds *s, const struct ofp_header *oh, ofp_print_flow_flags(s, fm.flags); ds_put_cstr(s, "actions="); - ofpacts_format(fm.ofpacts, fm.ofpacts_len, port_map, s); + struct ofpact_format_params fp = { + .port_map = port_map, + .s = s, + }; + ofpacts_format(fm.ofpacts, fm.ofpacts_len, &fp); ofpbuf_uninit(&ofpacts); return 0; @@ -1749,7 +1762,11 @@ ofp_print_flow_stats(struct ds *string, const struct ofputil_flow_stats *fs, } ds_put_format(string, "%sactions=%s", colors.actions, colors.end); - ofpacts_format(fs->ofpacts, fs->ofpacts_len, port_map, string); + struct ofpact_format_params fp = { + .port_map = port_map, + .s = string, + }; + ofpacts_format(fs->ofpacts, fs->ofpacts_len, &fp); } static enum ofperr @@ -2544,8 +2561,11 @@ ofp_print_nxst_flow_monitor_reply(struct ds *string, ds_put_char(string, ' '); } ds_put_cstr(string, "actions="); - ofpacts_format(update.ofpacts, update.ofpacts_len, port_map, - string); + struct ofpact_format_params fp = { + .port_map = port_map, + .s = string, + }; + ofpacts_format(update.ofpacts, update.ofpacts_len, &fp); } } } @@ -2676,7 +2696,11 @@ ofp_print_group(struct ds *s, uint32_t group_id, uint8_t type, } ds_put_cstr(s, "actions="); - ofpacts_format(bucket->ofpacts, bucket->ofpacts_len, port_map, s); + struct ofpact_format_params fp = { + .port_map = port_map, + .s = s, + }; + ofpacts_format(bucket->ofpacts, bucket->ofpacts_len, &fp); ds_put_char(s, ','); } diff --git a/ofproto/ofproto-dpif-trace.c b/ofproto/ofproto-dpif-trace.c index 4999d1d6f326..7b29013db99a 100644 --- a/ofproto/ofproto-dpif-trace.c +++ b/ofproto/ofproto-dpif-trace.c @@ -463,8 +463,12 @@ ofproto_unixctl_trace_actions(struct unixctl_conn *conn, int argc, ofpbuf_init(&ofpacts, 0); /* Parse actions. */ - error = ofpacts_parse_actions(argv[--argc], NULL, - &ofpacts, &usable_protocols); + struct ofpact_parse_params pp = { + .port_map = NULL, + .ofpacts = &ofpacts, + .usable_protocols = &usable_protocols, + }; + error = ofpacts_parse_actions(argv[--argc], &pp); if (error) { unixctl_command_reply_error(conn, error); free(error); diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index 896d5e290a46..fa9a89334163 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -693,7 +693,8 @@ xlate_report_actions(const struct xlate_ctx *ctx, enum oftrace_node_type type, if (OVS_UNLIKELY(ctx->xin->trace)) { struct ds s = DS_EMPTY_INITIALIZER; ds_put_format(&s, "%s: ", title); - ofpacts_format(ofpacts, ofpacts_len, NULL, &s); + struct ofpact_format_params fp = { .s = &s }; + ofpacts_format(ofpacts, ofpacts_len, &fp); oftrace_report(ctx->xin->trace, type, ds_cstr(&s)); ds_destroy(&s); } @@ -714,7 +715,8 @@ xlate_report_action_set(const struct xlate_ctx *ctx, const char *verb) ofpacts_execute_action_set(&action_list, &ctx->action_set); if (action_list.size) { struct ds s = DS_EMPTY_INITIALIZER; - ofpacts_format(action_list.data, action_list.size, NULL, &s); + struct ofpact_format_params fp = { .s = &s }; + ofpacts_format(action_list.data, action_list.size, &fp); xlate_report(ctx, OFT_DETAIL, "action set %s: %s", verb, ds_cstr(&s)); ds_destroy(&s); @@ -4978,7 +4980,8 @@ xlate_learn_action(struct xlate_ctx *ctx, const struct ofpact_learn *learn) ds_put_cstr(&s, " send_flow_rem"); } ds_put_cstr(&s, " actions="); - ofpacts_format(fm.ofpacts, fm.ofpacts_len, NULL, &s); + struct ofpact_format_params fp = { .s = &s }; + ofpacts_format(fm.ofpacts, fm.ofpacts_len, &fp); xlate_report(ctx, OFT_DETAIL, "%s", ds_cstr(&s)); ds_destroy(&s); } @@ -6087,7 +6090,8 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, if (OVS_UNLIKELY(ctx->xin->trace)) { struct ds s = DS_EMPTY_INITIALIZER; - ofpacts_format(a, OFPACT_ALIGN(a->len), NULL, &s); + struct ofpact_format_params fp = { .s = &s }; + ofpacts_format(a, OFPACT_ALIGN(a->len), &fp); xlate_report(ctx, OFT_ACTION, "%s", ds_cstr(&s)); ds_destroy(&s); } diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index d42acd747acc..71f449f7ddda 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -4399,7 +4399,8 @@ flow_stats_ds(struct ofproto *ofproto, struct rule *rule, struct ds *results) ds_put_char(results, ','); ds_put_cstr(results, "actions="); - ofpacts_format(actions->ofpacts, actions->ofpacts_len, NULL, results); + struct ofpact_format_params fp = { .s = results }; + ofpacts_format(actions->ofpacts, actions->ofpacts_len, &fp); ds_put_cstr(results, "\n"); } diff --git a/ovn/controller/ofctrl.c b/ovn/controller/ofctrl.c index 2fa980ebdae1..264667769296 100644 --- a/ovn/controller/ofctrl.c +++ b/ovn/controller/ofctrl.c @@ -685,7 +685,8 @@ ovn_flow_to_string(const struct ovn_flow *f) ds_put_format(&s, "priority=%"PRIu16", ", f->priority); match_format(&f->match, NULL, &s, OFP_DEFAULT_PRIORITY); ds_put_cstr(&s, ", actions="); - ofpacts_format(f->ofpacts, f->ofpacts_len, NULL, &s); + struct ofpact_format_params fp = { .s = &s }; + ofpacts_format(f->ofpacts, f->ofpacts_len, &fp); return ds_steal_cstr(&s); } diff --git a/ovn/utilities/ovn-sbctl.c b/ovn/utilities/ovn-sbctl.c index 1c2e6843f23c..0cb8ea480438 100644 --- a/ovn/utilities/ovn-sbctl.c +++ b/ovn/utilities/ovn-sbctl.c @@ -806,7 +806,8 @@ sbctl_dump_openflow(struct vconn *vconn, const struct uuid *uuid, bool stats) } ds_put_format(&s, "%sactions=%s", colors.actions, colors.end); - ofpacts_format(fs->ofpacts, fs->ofpacts_len, NULL, &s); + struct ofpact_format_params fp = { .s = &s }; + ofpacts_format(fs->ofpacts, fs->ofpacts_len, &fp); } printf(" %s\n", ds_cstr(&s)); } diff --git a/tests/test-ovn.c b/tests/test-ovn.c index f9a5085f7185..89b46dbff6fc 100644 --- a/tests/test-ovn.c +++ b/tests/test-ovn.c @@ -1263,7 +1263,8 @@ test_parse_actions(struct ovs_cmdl_context *ctx OVS_UNUSED) ofpbuf_init(&ofpacts, 0); ovnacts_encode(ovnacts.data, ovnacts.size, &ep, &ofpacts); struct ds ofpacts_s = DS_EMPTY_INITIALIZER; - ofpacts_format(ofpacts.data, ofpacts.size, NULL, &ofpacts_s); + struct ofpact_format_params fp = { .s = &ofpacts_s }; + ofpacts_format(ofpacts.data, ofpacts.size, &fp); printf(" encodes as %s\n", ds_cstr(&ofpacts_s)); ds_destroy(&ofpacts_s); ofpbuf_uninit(&ofpacts); diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c index 953184da4d19..56af5a444d95 100644 --- a/utilities/ovs-ofctl.c +++ b/utilities/ovs-ofctl.c @@ -2194,9 +2194,12 @@ ofctl_packet_out(struct ovs_cmdl_context *ctx) int i; ofpbuf_init(&ofpacts, 64); - error = ofpacts_parse_actions(ctx->argv[3], - ports_to_accept(ctx->argv[1]), &ofpacts, - &usable_protocols); + struct ofpact_parse_params pp = { + .port_map = ports_to_accept(ctx->argv[1]), + .ofpacts = &ofpacts, + .usable_protocols = &usable_protocols + }; + error = ofpacts_parse_actions(ctx->argv[3], &pp); if (error) { ovs_fatal(0, "%s", error); } @@ -3181,8 +3184,11 @@ fte_version_format(const struct fte_state *fte_state, const struct fte *fte, } ds_put_cstr(s, " actions="); - ofpacts_format(version->ofpacts, version->ofpacts_len, - fte_state->port_map, s); + struct ofpact_format_params fp = { + .port_map = fte_state->port_map, + .s = s, + }; + ofpacts_format(version->ofpacts, version->ofpacts_len, &fp); ds_put_char(s, '\n'); } @@ -4038,7 +4044,8 @@ ofctl_parse_actions__(const char *version_s, bool instructions) /* Print cls_rule. */ ds_init(&s); ds_put_cstr(&s, "actions="); - ofpacts_format(ofpacts.data, ofpacts.size, NULL, &s); + struct ofpact_format_params fp = { .s = &s }; + ofpacts_format(ofpacts.data, ofpacts.size, &fp); puts(ds_cstr(&s)); ds_destroy(&s); From patchwork Fri Jan 12 20:57:21 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 860196 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3zJFSp6SClz9s7c for ; Sat, 13 Jan 2018 07:58:02 +1100 (AEDT) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 84276FED; Fri, 12 Jan 2018 20:57:33 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 13292FD2 for ; Fri, 12 Jan 2018 20:57:33 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from relay4-d.mail.gandi.net (relay4-d.mail.gandi.net [217.70.183.196]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 531D2473 for ; Fri, 12 Jan 2018 20:57:32 +0000 (UTC) X-Originating-IP: 208.91.3.26 Received: from sigabrt.benpfaff.org (unknown [208.91.3.26]) (Authenticated sender: blp@ovn.org) by relay4-d.mail.gandi.net (Postfix) with ESMTPSA id 30CCB172094; Fri, 12 Jan 2018 21:57:29 +0100 (CET) From: Ben Pfaff To: dev@openvswitch.org Date: Fri, 12 Jan 2018 12:57:21 -0800 Message-Id: <20180112205722.25360-3-blp@ovn.org> X-Mailer: git-send-email 2.10.2 In-Reply-To: <20180112205722.25360-1-blp@ovn.org> References: <20180112205722.25360-1-blp@ovn.org> X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Cc: Ben Pfaff Subject: [ovs-dev] [PATCH v2 2/3] ofp-util: New data structure for mapping between table names and numbers. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org This shares the infrastructure for mapping port names and numbers. It will be used in an upcoming commit. Signed-off-by: Ben Pfaff Reviewed-by: Yifeng Sun --- include/openvswitch/ofp-util.h | 33 +++++++-- lib/ofp-util.c | 150 ++++++++++++++++++++++++++++++----------- 2 files changed, 138 insertions(+), 45 deletions(-) diff --git a/include/openvswitch/ofp-util.h b/include/openvswitch/ofp-util.h index 296078a2fe8b..d9780dd44582 100644 --- a/include/openvswitch/ofp-util.h +++ b/include/openvswitch/ofp-util.h @@ -43,15 +43,24 @@ union ofp_action; struct ofpact_set_field; struct vl_mff_map; -/* Mapping between port numbers and names. */ -struct ofputil_port_map { +/* Name-number mapping. + * + * This is not exported directly but only through specializations for port + * name-number and table name-number mappings. */ +struct ofputil_name_map { struct hmap by_name; struct hmap by_number; }; - -#define OFPUTIL_PORT_MAP_INITIALIZER(MAP) \ +#define OFPUTIL_NAME_MAP_INITIALIZER(MAP) \ { HMAP_INITIALIZER(&(MAP)->by_name), HMAP_INITIALIZER(&(MAP)->by_number) } +/* Mapping between port numbers and names. */ +struct ofputil_port_map { + struct ofputil_name_map map; +}; +#define OFPUTIL_PORT_MAP_INITIALIZER(MAP) \ + { OFPUTIL_NAME_MAP_INITIALIZER(&(MAP)->map) } + void ofputil_port_map_init(struct ofputil_port_map *); const char *ofputil_port_map_get_name(const struct ofputil_port_map *, ofp_port_t); @@ -791,6 +800,22 @@ struct ofputil_table_mod_prop_vacancy { uint8_t vacancy; /* Current vacancy (%). */ }; +/* Mapping between table numbers and names. */ +struct ofputil_table_map { + struct ofputil_name_map map; +}; +#define OFPUTIL_TABLE_MAP_INITIALIZER(MAP) \ + { OFPUTIL_NAME_MAP_INITIALIZER((MAP).map) } + +void ofputil_table_map_init(struct ofputil_table_map *); +const char *ofputil_table_map_get_name(const struct ofputil_table_map *, + uint8_t); +uint8_t ofputil_table_map_get_number(const struct ofputil_table_map *, + const char *name); +void ofputil_table_map_put(struct ofputil_table_map *, + uint8_t, const char *name); +void ofputil_table_map_destroy(struct ofputil_table_map *); + /* Abstract ofp_table_mod. */ struct ofputil_table_mod { uint8_t table_id; /* ID of the table, 0xff indicates all tables. */ diff --git a/lib/ofp-util.c b/lib/ofp-util.c index 597112e4f84e..f3b2e3f6108c 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -7454,12 +7454,14 @@ ofputil_port_to_string(ofp_port_t port, snprintf(namebuf, bufsize, "%"PRIu32, port); } -/* ofputil_port_map. */ -struct ofputil_port_map_node { +/* ofputil_name_map. */ + +struct ofputil_name_map_node { struct hmap_node name_node; struct hmap_node number_node; - ofp_port_t ofp_port; /* Port number. */ - char *name; /* Port name. */ + + uint32_t number; + char *name; /* OpenFlow doesn't require port names to be unique, although that's the * only sensible way. However, even in Open vSwitch it's possible for two @@ -7469,22 +7471,25 @@ struct ofputil_port_map_node { * corner case. * * OpenFlow does require port numbers to be unique. We check for duplicate - * ports numbers just in case a switch has a bug. */ + * ports numbers just in case a switch has a bug. + * + * OpenFlow doesn't require table names to be unique and Open vSwitch + * doesn't try to make them unique. */ bool duplicate; }; -void -ofputil_port_map_init(struct ofputil_port_map *map) +static void +ofputil_name_map_init(struct ofputil_name_map *map) { hmap_init(&map->by_name); hmap_init(&map->by_number); } -static struct ofputil_port_map_node * -ofputil_port_map_find_by_name(const struct ofputil_port_map *map, +static struct ofputil_name_map_node * +ofputil_name_map_find_by_name(const struct ofputil_name_map *map, const char *name) { - struct ofputil_port_map_node *node; + struct ofputil_name_map_node *node; HMAP_FOR_EACH_WITH_HASH (node, name_node, hash_string(name, 0), &map->by_name) { @@ -7495,38 +7500,38 @@ ofputil_port_map_find_by_name(const struct ofputil_port_map *map, return NULL; } -static struct ofputil_port_map_node * -ofputil_port_map_find_by_number(const struct ofputil_port_map *map, - ofp_port_t ofp_port) +static struct ofputil_name_map_node * +ofputil_name_map_find_by_number(const struct ofputil_name_map *map, + uint32_t number) { - struct ofputil_port_map_node *node; + struct ofputil_name_map_node *node; - HMAP_FOR_EACH_IN_BUCKET (node, number_node, hash_ofp_port(ofp_port), + HMAP_FOR_EACH_IN_BUCKET (node, number_node, hash_int(number, 0), &map->by_number) { - if (node->ofp_port == ofp_port) { + if (node->number == number) { return node; } } return NULL; } -void -ofputil_port_map_put(struct ofputil_port_map *map, - ofp_port_t ofp_port, const char *name) +static void +ofputil_name_map_put(struct ofputil_name_map *map, + uint32_t number, const char *name) { - struct ofputil_port_map_node *node; + struct ofputil_name_map_node *node; /* Look for duplicate name. */ - node = ofputil_port_map_find_by_name(map, name); + node = ofputil_name_map_find_by_name(map, name); if (node) { - if (node->ofp_port != ofp_port) { + if (node->number != number) { node->duplicate = true; } return; } /* Look for duplicate number. */ - node = ofputil_port_map_find_by_number(map, ofp_port); + node = ofputil_name_map_find_by_number(map, number); if (node) { node->duplicate = true; return; @@ -7534,19 +7539,53 @@ ofputil_port_map_put(struct ofputil_port_map *map, /* Add new node. */ node = xmalloc(sizeof *node); - hmap_insert(&map->by_number, &node->number_node, hash_ofp_port(ofp_port)); + hmap_insert(&map->by_number, &node->number_node, hash_int(number, 0)); hmap_insert(&map->by_name, &node->name_node, hash_string(name, 0)); - node->ofp_port = ofp_port; + node->number = number; node->name = xstrdup(name); node->duplicate = false; } +static void +ofputil_name_map_destroy(struct ofputil_name_map *map) +{ + if (map) { + struct ofputil_name_map_node *node, *next; + + HMAP_FOR_EACH_SAFE (node, next, name_node, &map->by_name) { + hmap_remove(&map->by_name, &node->name_node); + hmap_remove(&map->by_number, &node->number_node); + free(node->name); + free(node); + } + hmap_destroy(&map->by_name); + hmap_destroy(&map->by_number); + } +} + +/* ofputil_port_map. */ + +void +ofputil_port_map_init(struct ofputil_port_map *map) +{ + ofputil_name_map_init(&map->map); +} + +void +ofputil_port_map_put(struct ofputil_port_map *map, + ofp_port_t ofp_port, const char *name) +{ + ofputil_name_map_put(&map->map, ofp_to_u16(ofp_port), name); +} + const char * ofputil_port_map_get_name(const struct ofputil_port_map *map, ofp_port_t ofp_port) { - struct ofputil_port_map_node *node - = map ? ofputil_port_map_find_by_number(map, ofp_port) : NULL; + struct ofputil_name_map_node *node + = (map + ? ofputil_name_map_find_by_number(&map->map, ofp_to_u16(ofp_port)) + : NULL); return node && !node->duplicate ? node->name : NULL; } @@ -7554,26 +7593,55 @@ ofp_port_t ofputil_port_map_get_number(const struct ofputil_port_map *map, const char *name) { - struct ofputil_port_map_node *node - = map ? ofputil_port_map_find_by_name(map, name) : NULL; - return node && !node->duplicate ? node->ofp_port : OFPP_NONE; + struct ofputil_name_map_node *node + = map ? ofputil_name_map_find_by_name(&map->map, name) : NULL; + return node && !node->duplicate ? u16_to_ofp(node->number) : OFPP_NONE; } void ofputil_port_map_destroy(struct ofputil_port_map *map) { - if (map) { - struct ofputil_port_map_node *node, *next; + ofputil_name_map_destroy(&map->map); +} + + +/* ofputil_table_map. */ - HMAP_FOR_EACH_SAFE (node, next, name_node, &map->by_name) { - hmap_remove(&map->by_name, &node->name_node); - hmap_remove(&map->by_number, &node->number_node); - free(node->name); - free(node); - } - hmap_destroy(&map->by_name); - hmap_destroy(&map->by_number); - } +void +ofputil_table_map_init(struct ofputil_table_map *map) +{ + ofputil_name_map_init(&map->map); +} + +void +ofputil_table_map_put(struct ofputil_table_map *map, + uint8_t table_id, const char *name) +{ + ofputil_name_map_put(&map->map, table_id, name); +} + +const char * +ofputil_table_map_get_name(const struct ofputil_table_map *map, + uint8_t table_id) +{ + struct ofputil_name_map_node *node + = map ? ofputil_name_map_find_by_number(&map->map, table_id) : NULL; + return node && !node->duplicate ? node->name : NULL; +} + +uint8_t +ofputil_table_map_get_number(const struct ofputil_table_map *map, + const char *name) +{ + struct ofputil_name_map_node *node + = map ? ofputil_name_map_find_by_name(&map->map, name) : NULL; + return node && !node->duplicate ? node->number : UINT8_MAX; +} + +void +ofputil_table_map_destroy(struct ofputil_table_map *map) +{ + ofputil_name_map_destroy(&map->map); } /* Stores the group id represented by 's' into '*group_idp'. 's' may be an From patchwork Fri Jan 12 20:57:22 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 860201 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3zJFVM6rNDz9s7c for ; Sat, 13 Jan 2018 07:59:23 +1100 (AEDT) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id C8632104D; Fri, 12 Jan 2018 20:57:43 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id DA74D102A for ; Fri, 12 Jan 2018 20:57:42 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from relay4-d.mail.gandi.net (relay4-d.mail.gandi.net [217.70.183.196]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 7516912E for ; Fri, 12 Jan 2018 20:57:35 +0000 (UTC) X-Originating-IP: 208.91.3.26 Received: from sigabrt.benpfaff.org (unknown [208.91.3.26]) (Authenticated sender: blp@ovn.org) by relay4-d.mail.gandi.net (Postfix) with ESMTPSA id B8A2417209C; Fri, 12 Jan 2018 21:57:31 +0100 (CET) From: Ben Pfaff To: dev@openvswitch.org Date: Fri, 12 Jan 2018 12:57:22 -0800 Message-Id: <20180112205722.25360-4-blp@ovn.org> X-Mailer: git-send-email 2.10.2 In-Reply-To: <20180112205722.25360-1-blp@ovn.org> References: <20180112205722.25360-1-blp@ovn.org> X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Cc: Ben Pfaff Subject: [ovs-dev] [PATCH v2 3/3] Support accepting and displaying table names in OVS tools. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org OpenFlow has little-known support for naming tables. Open vSwitch has supported table names for ages, but it has never used or displayed them outside of commands dedicated to table manipulation. This commit adds support for table names in ovs-ofctl. When a table has a name, it displays that name in flows and actions, so that, for example, the following: table=1, arp, actions=resubmit(,2) might become: table=ingress_acl, arp, actions=resubmit(,mac_learning) given appropriately named tables. For backward compatibility, only interactive ovs-ofctl commands by default display table names; to display them in scripts, use the new --names option. This feature was inspired by a talk that Kei Nohguchi presented at Open vSwitch 2017 Fall Conference. CC: Kei Nohguchi Signed-off-by: Ben Pfaff --- NEWS | 11 ++ include/openvswitch/ofp-actions.h | 2 + include/openvswitch/ofp-parse.h | 20 ++- include/openvswitch/ofp-print.h | 12 +- include/openvswitch/ofp-util.h | 8 ++ lib/learn.c | 20 ++- lib/learn.h | 6 +- lib/learning-switch.c | 2 +- lib/ofp-actions.c | 45 +++--- lib/ofp-parse.c | 80 +++++++---- lib/ofp-print.c | 202 ++++++++++++++++---------- lib/ofp-util.c | 109 ++++++++++++-- lib/vconn.c | 10 +- ofproto/ofproto-dpif.c | 4 +- ofproto/ofproto.c | 2 +- ovn/controller/ofctrl.c | 12 +- ovn/controller/pinctrl.c | 2 +- ovn/utilities/ovn-sbctl.c | 2 +- ovn/utilities/ovn-trace.c | 2 +- tests/ofproto.at | 89 ++++++++---- utilities/ovs-ofctl.8.in | 90 +++++++----- utilities/ovs-ofctl.c | 294 +++++++++++++++++++++++++++++++------- utilities/ovs-testcontroller.c | 2 +- 23 files changed, 739 insertions(+), 287 deletions(-) diff --git a/NEWS b/NEWS index cb020d00d00c..edc2cff7cbd5 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,14 @@ +Post-v2.9.0 +-------------------- + - ovs-ofctl: + * ovs-ofctl now accepts and display table names in place of numbers. By + default it always accepts names and in interactive use it displays them; + use --names or --no-names to override. See ovs-ofctl(8) for details. + - ovs-vswitchd: + * Previous versions gave OpenFlow tables default names of the form + "table#". These are not helpful names for the purpose of accepting + and displaying table names, so now tables by default have no names. + Post-v2.8.0 -------------------- - NSH implementation now conforms to latest draft (draft-ietf-sfc-nsh-28). diff --git a/include/openvswitch/ofp-actions.h b/include/openvswitch/ofp-actions.h index 454c705ccf73..cba027b1d945 100644 --- a/include/openvswitch/ofp-actions.h +++ b/include/openvswitch/ofp-actions.h @@ -1068,6 +1068,7 @@ uint32_t ofpacts_get_meter(const struct ofpact[], size_t ofpacts_len); struct ofpact_format_params { /* Input. */ const struct ofputil_port_map *port_map; + const struct ofputil_table_map *table_map; /* Output. */ struct ds *s; @@ -1080,6 +1081,7 @@ const char *ofpact_name(enum ofpact_type); struct ofpact_parse_params { /* Input. */ const struct ofputil_port_map *port_map; + const struct ofputil_table_map *table_map; /* Output. */ struct ofpbuf *ofpacts; diff --git a/include/openvswitch/ofp-parse.h b/include/openvswitch/ofp-parse.h index 013a8f3edf70..c4228a50358f 100644 --- a/include/openvswitch/ofp-parse.h +++ b/include/openvswitch/ofp-parse.h @@ -45,26 +45,33 @@ enum ofputil_protocol; char *parse_ofp_str(struct ofputil_flow_mod *, int command, const char *str_, const struct ofputil_port_map *, + const struct ofputil_table_map *, enum ofputil_protocol *usable_protocols) OVS_WARN_UNUSED_RESULT; char *parse_ofp_flow_mod_str(struct ofputil_flow_mod *, const char *string, - const struct ofputil_port_map *, int command, + const struct ofputil_port_map *, + const struct ofputil_table_map *, + int command, enum ofputil_protocol *usable_protocols) OVS_WARN_UNUSED_RESULT; char *parse_ofp_packet_out_str(struct ofputil_packet_out *po, const char *str_, const struct ofputil_port_map *, + const struct ofputil_table_map *, enum ofputil_protocol *usable_protocols) OVS_WARN_UNUSED_RESULT; char *parse_ofp_table_mod(struct ofputil_table_mod *, const char *table_id, const char *flow_miss_handling, + const struct ofputil_table_map *, uint32_t *usable_versions) OVS_WARN_UNUSED_RESULT; char *parse_ofp_flow_mod_file(const char *file_name, - const struct ofputil_port_map *, int command, + const struct ofputil_port_map *, + const struct ofputil_table_map *, + int command, struct ofputil_flow_mod **fms, size_t *n_fms, enum ofputil_protocol *usable_protocols) OVS_WARN_UNUSED_RESULT; @@ -72,6 +79,7 @@ char *parse_ofp_flow_mod_file(const char *file_name, char *parse_ofp_flow_stats_request_str(struct ofputil_flow_stats_request *, bool aggregate, const char *string, const struct ofputil_port_map *, + const struct ofputil_table_map *, enum ofputil_protocol *usable_protocols) OVS_WARN_UNUSED_RESULT; @@ -86,12 +94,14 @@ char *parse_ofp_meter_mod_str(struct ofputil_meter_mod *, const char *string, char *parse_flow_monitor_request(struct ofputil_flow_monitor_request *, const char *, - const struct ofputil_port_map *port_map, + const struct ofputil_port_map *, + const struct ofputil_table_map *, enum ofputil_protocol *usable_protocols) OVS_WARN_UNUSED_RESULT; char *parse_ofp_group_mod_file(const char *file_name, - const struct ofputil_port_map *, int command, + const struct ofputil_port_map *, + const struct ofputil_table_map *, int command, struct ofputil_group_mod **gms, size_t *n_gms, enum ofputil_protocol *usable_protocols) OVS_WARN_UNUSED_RESULT; @@ -99,11 +109,13 @@ char *parse_ofp_group_mod_file(const char *file_name, char *parse_ofp_group_mod_str(struct ofputil_group_mod *, int command, const char *string, const struct ofputil_port_map *, + const struct ofputil_table_map *, enum ofputil_protocol *usable_protocols) OVS_WARN_UNUSED_RESULT; char *parse_ofp_bundle_file(const char *file_name, const struct ofputil_port_map *, + const struct ofputil_table_map *, struct ofputil_bundle_msg **, size_t *n_bms, enum ofputil_protocol *) OVS_WARN_UNUSED_RESULT; diff --git a/include/openvswitch/ofp-print.h b/include/openvswitch/ofp-print.h index d02634e3e91c..ed113786a28c 100644 --- a/include/openvswitch/ofp-print.h +++ b/include/openvswitch/ofp-print.h @@ -31,6 +31,7 @@ struct ofp_header; struct ofputil_flow_stats; struct ofputil_port_map; struct ofputil_table_features; +struct ofputil_table_map; struct ofputil_table_stats; struct dp_packet; @@ -39,7 +40,7 @@ extern "C" { #endif void ofp_print(FILE *, const void *, size_t, const struct ofputil_port_map *, - int verbosity); + const struct ofputil_table_map *, int verbosity); void ofp_print_packet(FILE *stream, const void *data, size_t len, ovs_be32 packet_type); void ofp_print_dp_packet(FILE *stream, const struct dp_packet *packet); @@ -48,7 +49,7 @@ void ofp10_match_print(struct ds *, const struct ofp10_match *, const struct ofputil_port_map *, int verbosity); char *ofp_to_string(const void *, size_t, const struct ofputil_port_map *, - int verbosity); + const struct ofputil_table_map *, int verbosity); char *ofp10_match_to_string(const struct ofp10_match *, const struct ofputil_port_map *, int verbosity); char *ofp_packet_to_string(const void *data, size_t len, ovs_be32 packet_type); @@ -59,10 +60,13 @@ void ofp_print_table_features( struct ds *, const struct ofputil_table_features *features, const struct ofputil_table_features *prev_features, const struct ofputil_table_stats *stats, - const struct ofputil_table_stats *prev_stats); + const struct ofputil_table_stats *prev_stats, + const struct ofputil_table_map *table_map); void ofp_print_flow_stats(struct ds *, const struct ofputil_flow_stats *, - const struct ofputil_port_map *, bool show_stats); + const struct ofputil_port_map *, + const struct ofputil_table_map *, + bool show_stats); #ifdef __cplusplus } diff --git a/include/openvswitch/ofp-util.h b/include/openvswitch/ofp-util.h index d9780dd44582..5dd1b34c216b 100644 --- a/include/openvswitch/ofp-util.h +++ b/include/openvswitch/ofp-util.h @@ -816,6 +816,14 @@ void ofputil_table_map_put(struct ofputil_table_map *, uint8_t, const char *name); void ofputil_table_map_destroy(struct ofputil_table_map *); +/* Table numbers. */ +bool ofputil_table_from_string(const char *, const struct ofputil_table_map *, + uint8_t *tablep); +void ofputil_format_table(uint8_t table, const struct ofputil_table_map *, + struct ds *); +void ofputil_table_to_string(uint8_t, const struct ofputil_table_map *, + char *namebuf, size_t bufsize); + /* Abstract ofp_table_mod. */ struct ofputil_table_mod { uint8_t table_id; /* ID of the table, 0xff indicates all tables. */ diff --git a/lib/learn.c b/lib/learn.c index 9e321371c0a5..5164082f8e52 100644 --- a/lib/learn.c +++ b/lib/learn.c @@ -381,6 +381,7 @@ learn_parse_spec(const char *orig, char *name, char *value, * error. The caller is responsible for freeing the returned string. */ static char * OVS_WARN_UNUSED_RESULT learn_parse__(char *orig, char *arg, const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map, struct ofpbuf *ofpacts) { struct ofpact_learn *learn; @@ -396,8 +397,10 @@ learn_parse__(char *orig, char *arg, const struct ofputil_port_map *port_map, match_init_catchall(&match); while (ofputil_parse_key_value(&arg, &name, &value)) { if (!strcmp(name, "table")) { - learn->table_id = atoi(value); - if (learn->table_id == 255) { + if (!ofputil_table_from_string(value, table_map, + &learn->table_id)) { + return xasprintf("unknown table \"%s\"", value); + } else if (learn->table_id == 255) { return xasprintf("%s: table id 255 not valid for `learn' " "action", orig); } @@ -465,10 +468,11 @@ learn_parse__(char *orig, char *arg, const struct ofputil_port_map *port_map, * Modifies 'arg'. */ char * OVS_WARN_UNUSED_RESULT learn_parse(char *arg, const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map, struct ofpbuf *ofpacts) { char *orig = xstrdup(arg); - char *error = learn_parse__(orig, arg, port_map, ofpacts); + char *error = learn_parse__(orig, arg, port_map, table_map, ofpacts); free(orig); return error; } @@ -477,16 +481,18 @@ learn_parse(char *arg, const struct ofputil_port_map *port_map, * describes. */ void learn_format(const struct ofpact_learn *learn, - const struct ofputil_port_map *port_map, struct ds *s) + const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map, + struct ds *s) { const struct ofpact_learn_spec *spec; struct match match; match_init_catchall(&match); - ds_put_format(s, "%slearn(%s%stable=%s%"PRIu8, - colors.learn, colors.end, colors.special, colors.end, - learn->table_id); + ds_put_format(s, "%slearn(%s%stable=%s", + colors.learn, colors.end, colors.special, colors.end); + ofputil_format_table(learn->table_id, table_map, s); if (learn->idle_timeout != OFP_FLOW_PERMANENT) { ds_put_format(s, ",%sidle_timeout=%s%"PRIu16, colors.param, colors.end, learn->idle_timeout); diff --git a/lib/learn.h b/lib/learn.h index 31d3a14e827a..2bdfee702dac 100644 --- a/lib/learn.h +++ b/lib/learn.h @@ -28,6 +28,7 @@ struct ofpbuf; struct ofpact_learn; struct ofputil_flow_mod; struct ofputil_port_map; +struct ofputil_table_map; struct nx_action_learn; /* NXAST_LEARN helper functions. @@ -41,9 +42,10 @@ void learn_execute(const struct ofpact_learn *, const struct flow *, void learn_mask(const struct ofpact_learn *, struct flow_wildcards *); char *learn_parse(char *, const struct ofputil_port_map *, - struct ofpbuf *ofpacts) + const struct ofputil_table_map *, struct ofpbuf *ofpacts) OVS_WARN_UNUSED_RESULT; void learn_format(const struct ofpact_learn *, - const struct ofputil_port_map *, struct ds *); + const struct ofputil_port_map *, + const struct ofputil_table_map *, struct ds *); #endif /* learn.h */ diff --git a/lib/learning-switch.c b/lib/learning-switch.c index 5b014e5f3757..f840f034875f 100644 --- a/lib/learning-switch.c +++ b/lib/learning-switch.c @@ -369,7 +369,7 @@ lswitch_process_packet(struct lswitch *sw, const struct ofpbuf *msg) } else if (type == OFPTYPE_FLOW_REMOVED) { /* Nothing to do. */ } else if (VLOG_IS_DBG_ENABLED()) { - char *s = ofp_to_string(msg->data, msg->size, NULL, 2); + char *s = ofp_to_string(msg->data, msg->size, NULL, NULL, 2); VLOG_DBG_RL(&rl, "%016llx: OpenFlow packet ignored: %s", sw->datapath_id, s); free(s); diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c index 93792ddfca4b..47b6fcd6c691 100644 --- a/lib/ofp-actions.c +++ b/lib/ofp-actions.c @@ -4398,14 +4398,10 @@ parse_RESUBMIT(char *arg, const struct ofpact_parse_params *pp) table_s = strsep(&arg, ","); if (table_s && table_s[0]) { - uint32_t table_id = 0; - char *error; - - error = str_to_u32(table_s, &table_id); - if (error) { - return error; + if (!ofputil_table_from_string(table_s, pp->table_map, + &resubmit->table_id)) { + return xasprintf("%s: resubmit to unknown table", table_s); } - resubmit->table_id = table_id; } else { resubmit->table_id = 255; } @@ -4441,7 +4437,7 @@ format_RESUBMIT(const struct ofpact_resubmit *a, } ds_put_char(fp->s, ','); if (a->table_id != 255) { - ds_put_format(fp->s, "%"PRIu8, a->table_id); + ofputil_format_table(a->table_id, fp->table_map, fp->s); } if (a->with_ct_orig) { ds_put_cstr(fp->s, ",ct"); @@ -5024,14 +5020,14 @@ encode_LEARN(const struct ofpact_learn *learn, static char * OVS_WARN_UNUSED_RESULT parse_LEARN(char *arg, const struct ofpact_parse_params *pp) { - return learn_parse(arg, pp->port_map, pp->ofpacts); + return learn_parse(arg, pp->port_map, pp->table_map, pp->ofpacts); } static void format_LEARN(const struct ofpact_learn *a, const struct ofpact_format_params *fp) { - learn_format(a, fp->port_map, fp->s); + learn_format(a, fp->port_map, fp->table_map, fp->s); } /* Action structure for NXAST_CONJUNCTION. */ @@ -5372,10 +5368,11 @@ static void format_UNROLL_XLATE(const struct ofpact_unroll_xlate *a, const struct ofpact_format_params *fp) { - ds_put_format(fp->s, "%sunroll_xlate(%s%stable=%s%"PRIu8 - ", %scookie=%s%"PRIu64"%s)%s", + ds_put_format(fp->s, "%sunroll_xlate(%s%stable=%s", colors.paren, colors.end, - colors.special, colors.end, a->rule_table_id, + colors.special, colors.end); + ofputil_format_table(a->rule_table_id, fp->table_map, fp->s); + ds_put_format(fp->s, ", %scookie=%s%"PRIu64"%s)%s", colors.param, colors.end, ntohll(a->rule_cookie), colors.paren, colors.end); } @@ -6038,8 +6035,10 @@ parse_CT(char *arg, const struct ofpact_parse_params *pp) } else if (!strcmp(key, "force")) { oc->flags |= NX_CT_F_FORCE; } else if (!strcmp(key, "table")) { - error = str_to_u8(value, "recirc_table", &oc->recirc_table); - if (!error && oc->recirc_table == NX_CT_RECIRC_NONE) { + if (!ofputil_table_from_string(value, pp->table_map, + &oc->recirc_table)) { + error = xasprintf("unknown table %s", value); + } else if (oc->recirc_table == NX_CT_RECIRC_NONE) { error = xasprintf("invalid table %#"PRIx8, oc->recirc_table); } } else if (!strcmp(key, "zone")) { @@ -6125,8 +6124,9 @@ format_CT(const struct ofpact_conntrack *a, ds_put_format(fp->s, "%sforce%s,", colors.value, colors.end); } if (a->recirc_table != NX_CT_RECIRC_NONE) { - ds_put_format(fp->s, "%stable=%s%"PRIu8",", - colors.special, colors.end, a->recirc_table); + ds_put_format(fp->s, "%stable=%s", colors.special, colors.end); + ofputil_format_table(a->recirc_table, fp->table_map, fp->s); + ds_put_char(fp->s, ','); } if (a->zone_src.field) { ds_put_format(fp->s, "%szone=%s", colors.param, colors.end); @@ -6816,19 +6816,18 @@ static char * OVS_WARN_UNUSED_RESULT parse_GOTO_TABLE(char *arg, const struct ofpact_parse_params *pp) { struct ofpact_goto_table *ogt = ofpact_put_GOTO_TABLE(pp->ofpacts); - char *table_s = strsep(&arg, ","); - if (!table_s || !table_s[0]) { - return xstrdup("instruction goto-table needs table id"); + if (!ofputil_table_from_string(arg, pp->table_map, &ogt->table_id)) { + return xasprintf("unknown table \"%s\"", arg); } - return str_to_u8(table_s, "table", &ogt->table_id); + return NULL; } static void format_GOTO_TABLE(const struct ofpact_goto_table *a, const struct ofpact_format_params *fp) { - ds_put_format(fp->s, "%sgoto_table:%s%"PRIu8, - colors.param, colors.end, a->table_id); + ds_put_format(fp->s, "%sgoto_table:%s", colors.param, colors.end); + ofputil_format_table(a->table_id, fp->table_map, fp->s); } static void diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c index b68081740f09..1e30c20f4966 100644 --- a/lib/ofp-parse.c +++ b/lib/ofp-parse.c @@ -322,6 +322,7 @@ extract_actions(char *s) static char * OVS_WARN_UNUSED_RESULT parse_ofp_str__(struct ofputil_flow_mod *fm, int command, char *string, const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map, enum ofputil_protocol *usable_protocols) { enum { @@ -450,7 +451,10 @@ parse_ofp_str__(struct ofputil_flow_mod *fm, int command, char *string, } if (!strcmp(name, "table")) { - error = str_to_u8(value, "table", &fm->table_id); + if (!ofputil_table_from_string(value, table_map, + &fm->table_id)) { + return xasprintf("unknown table \"%s\"", value); + } if (fm->table_id != 0xff) { *usable_protocols &= OFPUTIL_P_TID; } @@ -559,6 +563,7 @@ parse_ofp_str__(struct ofputil_flow_mod *fm, int command, char *string, ofpbuf_init(&ofpacts, 32); struct ofpact_parse_params pp = { .port_map = port_map, + .table_map = table_map, .ofpacts = &ofpacts, .usable_protocols = &action_usable_protocols }; @@ -610,12 +615,14 @@ parse_ofp_str__(struct ofputil_flow_mod *fm, int command, char *string, char * OVS_WARN_UNUSED_RESULT parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_, const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map, enum ofputil_protocol *usable_protocols) { char *string = xstrdup(str_); char *error; - error = parse_ofp_str__(fm, command, string, port_map, usable_protocols); + error = parse_ofp_str__(fm, command, string, port_map, table_map, + usable_protocols); if (error) { fm->ofpacts = NULL; fm->ofpacts_len = 0; @@ -630,6 +637,7 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_, static char * OVS_WARN_UNUSED_RESULT parse_ofp_packet_out_str__(struct ofputil_packet_out *po, char *string, const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map, enum ofputil_protocol *usable_protocols) { enum ofputil_protocol action_usable_protocols; @@ -719,6 +727,7 @@ parse_ofp_packet_out_str__(struct ofputil_packet_out *po, char *string, if (act_str) { struct ofpact_parse_params pp = { .port_map = port_map, + .table_map = table_map, .ofpacts = &ofpacts, .usable_protocols = &action_usable_protocols, }; @@ -750,12 +759,14 @@ out: char * OVS_WARN_UNUSED_RESULT parse_ofp_packet_out_str(struct ofputil_packet_out *po, const char *str_, const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map, enum ofputil_protocol *usable_protocols) { char *string = xstrdup(str_); char *error; - error = parse_ofp_packet_out_str__(po, string, port_map, usable_protocols); + error = parse_ofp_packet_out_str__(po, string, port_map, table_map, + usable_protocols); if (error) { po->ofpacts = NULL; po->ofpacts_len = 0; @@ -996,6 +1007,7 @@ static char * OVS_WARN_UNUSED_RESULT parse_flow_monitor_request__(struct ofputil_flow_monitor_request *fmr, const char *str_, const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map, char *string, enum ofputil_protocol *usable_protocols) { @@ -1040,7 +1052,10 @@ parse_flow_monitor_request__(struct ofputil_flow_monitor_request *fmr, } if (!strcmp(name, "table")) { - error = str_to_u8(value, "table", &fmr->table_id); + if (!ofputil_table_from_string(value, table_map, + &fmr->table_id)) { + error = xasprintf("unknown table \"%s\"", value); + } } else if (!strcmp(name, "out_port")) { fmr->out_port = u16_to_ofp(atoi(value)); } else { @@ -1064,11 +1079,12 @@ char * OVS_WARN_UNUSED_RESULT parse_flow_monitor_request(struct ofputil_flow_monitor_request *fmr, const char *str_, const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map, enum ofputil_protocol *usable_protocols) { char *string = xstrdup(str_); - char *error = parse_flow_monitor_request__(fmr, str_, port_map, string, - usable_protocols); + char *error = parse_flow_monitor_request__(fmr, str_, port_map, table_map, + string, usable_protocols); free(string); return error; } @@ -1084,10 +1100,12 @@ parse_flow_monitor_request(struct ofputil_flow_monitor_request *fmr, * error. The caller is responsible for freeing the returned string. */ char * OVS_WARN_UNUSED_RESULT parse_ofp_flow_mod_str(struct ofputil_flow_mod *fm, const char *string, - const struct ofputil_port_map *port_map, int command, + const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map, + int command, enum ofputil_protocol *usable_protocols) { - char *error = parse_ofp_str(fm, command, string, port_map, + char *error = parse_ofp_str(fm, command, string, port_map, table_map, usable_protocols); if (!error) { @@ -1167,16 +1185,16 @@ exit: * error. The caller is responsible for freeing the returned string. */ char * OVS_WARN_UNUSED_RESULT parse_ofp_table_mod(struct ofputil_table_mod *tm, const char *table_id, - const char *setting, uint32_t *usable_versions) + const char *setting, + const struct ofputil_table_map *table_map, + uint32_t *usable_versions) { *usable_versions = 0; if (!strcasecmp(table_id, "all")) { tm->table_id = OFPTT_ALL; - } else { - char *error = str_to_u8(table_id, "table_id", &tm->table_id); - if (error) { - return error; - } + } else if (!ofputil_table_from_string(table_id, table_map, + &tm->table_id)) { + return xasprintf("unknown table \"%s\"", table_id); } tm->miss = OFPUTIL_TABLE_MISS_DEFAULT; @@ -1240,7 +1258,9 @@ parse_ofp_table_mod(struct ofputil_table_mod *tm, const char *table_id, * error. The caller is responsible for freeing the returned string. */ char * OVS_WARN_UNUSED_RESULT parse_ofp_flow_mod_file(const char *file_name, - const struct ofputil_port_map *port_map, int command, + const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map, + int command, struct ofputil_flow_mod **fms, size_t *n_fms, enum ofputil_protocol *usable_protocols) { @@ -1271,7 +1291,7 @@ parse_ofp_flow_mod_file(const char *file_name, *fms = x2nrealloc(*fms, &allocated_fms, sizeof **fms); } error = parse_ofp_flow_mod_str(&(*fms)[*n_fms], ds_cstr(&s), port_map, - command, &usable); + table_map, command, &usable); if (error) { char *err_msg; size_t i; @@ -1307,12 +1327,14 @@ char * OVS_WARN_UNUSED_RESULT parse_ofp_flow_stats_request_str(struct ofputil_flow_stats_request *fsr, bool aggregate, const char *string, const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map, enum ofputil_protocol *usable_protocols) { struct ofputil_flow_mod fm; char *error; - error = parse_ofp_str(&fm, -1, string, port_map, usable_protocols); + error = parse_ofp_str(&fm, -1, string, port_map, table_map, + usable_protocols); if (error) { return error; } @@ -1438,8 +1460,9 @@ exit: static char * OVS_WARN_UNUSED_RESULT parse_bucket_str(struct ofputil_bucket *bucket, char *str_, - const struct ofputil_port_map *port_map, uint8_t group_type, - enum ofputil_protocol *usable_protocols) + const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map, + uint8_t group_type, enum ofputil_protocol *usable_protocols) { char *pos, *key, *value; struct ofpbuf ofpacts; @@ -1497,6 +1520,7 @@ parse_bucket_str(struct ofputil_bucket *bucket, char *str_, ofpbuf_init(&ofpacts, 0); struct ofpact_parse_params pp = { .port_map = port_map, + .table_map = table_map, .ofpacts = &ofpacts, .usable_protocols = usable_protocols, }; @@ -1575,6 +1599,7 @@ static char * OVS_WARN_UNUSED_RESULT parse_ofp_group_mod_str__(struct ofputil_group_mod *gm, int command, char *string, const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map, enum ofputil_protocol *usable_protocols) { enum { @@ -1828,7 +1853,7 @@ parse_ofp_group_mod_str__(struct ofputil_group_mod *gm, int command, } bucket = xzalloc(sizeof(struct ofputil_bucket)); - error = parse_bucket_str(bucket, bkt_str, port_map, + error = parse_bucket_str(bucket, bkt_str, port_map, table_map, gm->type, usable_protocols); if (error) { free(bucket); @@ -1862,11 +1887,12 @@ char * OVS_WARN_UNUSED_RESULT parse_ofp_group_mod_str(struct ofputil_group_mod *gm, int command, const char *str_, const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map, enum ofputil_protocol *usable_protocols) { char *string = xstrdup(str_); - char *error = parse_ofp_group_mod_str__(gm, command, string, - port_map, usable_protocols); + char *error = parse_ofp_group_mod_str__(gm, command, string, port_map, + table_map, usable_protocols); free(string); return error; } @@ -1878,6 +1904,7 @@ parse_ofp_group_mod_str(struct ofputil_group_mod *gm, int command, char * OVS_WARN_UNUSED_RESULT parse_ofp_group_mod_file(const char *file_name, const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map, int command, struct ofputil_group_mod **gms, size_t *n_gms, enum ofputil_protocol *usable_protocols) @@ -1915,7 +1942,7 @@ parse_ofp_group_mod_file(const char *file_name, *gms = new_gms; } error = parse_ofp_group_mod_str(&(*gms)[*n_gms], command, ds_cstr(&s), - port_map, &usable); + port_map, table_map, &usable); if (error) { size_t i; @@ -1956,6 +1983,7 @@ parse_ofp_group_mod_file(const char *file_name, char * OVS_WARN_UNUSED_RESULT parse_ofp_bundle_file(const char *file_name, const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map, struct ofputil_bundle_msg **bms, size_t *n_bms, enum ofputil_protocol *usable_protocols) { @@ -2003,7 +2031,7 @@ parse_ofp_bundle_file(const char *file_name, if (!strncmp(s, "flow", len)) { s += len; error = parse_ofp_flow_mod_str(&(*bms)[*n_bms].fm, s, port_map, - -2, &usable); + table_map, -2, &usable); if (error) { break; } @@ -2011,7 +2039,7 @@ parse_ofp_bundle_file(const char *file_name, } else if (!strncmp(s, "group", len)) { s += len; error = parse_ofp_group_mod_str(&(*bms)[*n_bms].gm, -2, s, - port_map, &usable); + port_map, table_map, &usable); if (error) { break; } @@ -2019,7 +2047,7 @@ parse_ofp_bundle_file(const char *file_name, } else if (!strncmp(s, "packet-out", len)) { s += len; error = parse_ofp_packet_out_str(&(*bms)[*n_bms].po, s, port_map, - &usable); + table_map, &usable); if (error) { break; } diff --git a/lib/ofp-print.c b/lib/ofp-print.c index 639d3bddf36d..dede3197cb98 100644 --- a/lib/ofp-print.c +++ b/lib/ofp-print.c @@ -119,7 +119,8 @@ format_hex_arg(struct ds *s, const uint8_t *data, size_t len) static enum ofperr ofp_print_packet_in(struct ds *string, const struct ofp_header *oh, - const struct ofputil_port_map *port_map, int verbosity) + const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map, int verbosity) { char reasonbuf[OFPUTIL_PACKET_IN_REASON_BUFSIZE]; struct ofputil_packet_in_private pin; @@ -134,8 +135,10 @@ ofp_print_packet_in(struct ds *string, const struct ofp_header *oh, return error; } - if (public->table_id) { - ds_put_format(string, " table_id=%"PRIu8, public->table_id); + if (public->table_id + || ofputil_table_map_get_name(table_map, public->table_id)) { + ds_put_format(string, " table_id="); + ofputil_format_table(public->table_id, table_map, string); } if (public->cookie != OVS_BE64_MAX) { @@ -207,6 +210,7 @@ ofp_print_packet_in(struct ds *string, const struct ofp_header *oh, struct ofpact_format_params fp = { .port_map = port_map, + .table_map = table_map, .s = string, }; @@ -240,7 +244,8 @@ ofp_print_packet_in(struct ds *string, const struct ofp_header *oh, static enum ofperr ofp_print_packet_out(struct ds *string, const struct ofp_header *oh, - const struct ofputil_port_map *port_map, int verbosity) + const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map, int verbosity) { struct ofputil_packet_out po; struct ofpbuf ofpacts; @@ -259,6 +264,7 @@ ofp_print_packet_out(struct ds *string, const struct ofp_header *oh, ds_put_cstr(string, " actions="); struct ofpact_format_params fp = { .port_map = port_map, + .table_map = table_map, .s = string, }; ofpacts_format(po.ofpacts, po.ofpacts_len, &fp); @@ -815,7 +821,8 @@ ofp_print_flow_flags(struct ds *s, enum ofputil_flow_mod_flags flags) static enum ofperr ofp_print_flow_mod(struct ds *s, const struct ofp_header *oh, - const struct ofputil_port_map *port_map, int verbosity) + const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map, int verbosity) { struct ofputil_flow_mod fm; struct ofpbuf ofpacts; @@ -855,8 +862,10 @@ ofp_print_flow_mod(struct ds *s, const struct ofp_header *oh, default: ds_put_format(s, "cmd:%d", fm.command); } - if (fm.table_id != 0) { - ds_put_format(s, " table:%d", fm.table_id); + if (fm.table_id != 0 + || ofputil_table_map_get_name(table_map, fm.table_id)) { + ds_put_format(s, " table:"); + ofputil_format_table(fm.table_id, table_map, s); } ds_put_char(s, ' '); @@ -927,6 +936,7 @@ ofp_print_flow_mod(struct ds *s, const struct ofp_header *oh, ds_put_cstr(s, "actions="); struct ofpact_format_params fp = { .port_map = port_map, + .table_map = table_map, .s = s, }; ofpacts_format(fm.ofpacts, fm.ofpacts_len, &fp); @@ -994,7 +1004,8 @@ ofp_flow_removed_reason_to_string(enum ofp_flow_removed_reason reason, static enum ofperr ofp_print_flow_removed(struct ds *string, const struct ofp_header *oh, - const struct ofputil_port_map *port_map) + const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map) { char reasonbuf[OFP_FLOW_REMOVED_REASON_BUFSIZE]; struct ofputil_flow_removed fr; @@ -1013,7 +1024,8 @@ ofp_print_flow_removed(struct ds *string, const struct ofp_header *oh, sizeof reasonbuf)); if (fr.table_id != 255) { - ds_put_format(string, " table_id=%"PRIu8, fr.table_id); + ds_put_format(string, " table_id="); + ofputil_format_table(fr.table_id, table_map, string); } if (fr.cookie != htonll(0)) { @@ -1133,7 +1145,8 @@ ofputil_table_vacancy_to_string(enum ofputil_table_vacancy vacancy) } static enum ofperr -ofp_print_table_mod(struct ds *string, const struct ofp_header *oh) +ofp_print_table_mod(struct ds *string, const struct ofp_header *oh, + const struct ofputil_table_map *table_map) { struct ofputil_table_mod pm; enum ofperr error; @@ -1146,7 +1159,8 @@ ofp_print_table_mod(struct ds *string, const struct ofp_header *oh) if (pm.table_id == 0xff) { ds_put_cstr(string, " table_id: ALL_TABLES"); } else { - ds_put_format(string, " table_id=%"PRIu8, pm.table_id); + ds_put_format(string, " table_id="); + ofputil_format_table(pm.table_id, table_map, string); } if (pm.miss != OFPUTIL_TABLE_MISS_DEFAULT) { @@ -1176,9 +1190,11 @@ ofp_print_table_mod(struct ds *string, const struct ofp_header *oh) /* This function will print the Table description properties. */ static void -ofp_print_table_desc(struct ds *string, const struct ofputil_table_desc *td) +ofp_print_table_desc(struct ds *string, const struct ofputil_table_desc *td, + const struct ofputil_table_map *table_map) { - ds_put_format(string, "\n table %"PRIu8, td->table_id); + ds_put_format(string, "\n table "); + ofputil_format_table(td->table_id, table_map, string); ds_put_cstr(string, ":\n"); ds_put_format(string, " eviction=%s eviction_flags=", ofputil_table_eviction_to_string(td->eviction)); @@ -1198,7 +1214,8 @@ ofp_print_table_desc(struct ds *string, const struct ofputil_table_desc *td) } static enum ofperr -ofp_print_table_status_message(struct ds *string, const struct ofp_header *oh) +ofp_print_table_status_message(struct ds *string, const struct ofp_header *oh, + const struct ofputil_table_map *table_map) { struct ofputil_table_status ts; enum ofperr error; @@ -1215,7 +1232,7 @@ ofp_print_table_status_message(struct ds *string, const struct ofp_header *oh) } ds_put_format(string, "\ntable_desc:-"); - ofp_print_table_desc(string, &ts.desc); + ofp_print_table_desc(string, &ts.desc, table_map); return 0; } @@ -1606,7 +1623,8 @@ ofp_print_hello(struct ds *string, const struct ofp_header *oh) static enum ofperr ofp_print_error_msg(struct ds *string, const struct ofp_header *oh, - const struct ofputil_port_map *port_map) + const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map) { struct ofpbuf payload; enum ofperr error; @@ -1622,7 +1640,7 @@ ofp_print_error_msg(struct ds *string, const struct ofp_header *oh, if (error == OFPERR_OFPHFC_INCOMPATIBLE || error == OFPERR_OFPHFC_EPERM) { ds_put_printable(string, payload.data, payload.size); } else { - s = ofp_to_string(payload.data, payload.size, port_map, 1); + s = ofp_to_string(payload.data, payload.size, port_map, table_map, 1); ds_put_cstr(string, s); free(s); } @@ -1676,7 +1694,8 @@ ofp_print_ofpst_desc_reply(struct ds *string, const struct ofp_header *oh) static enum ofperr ofp_print_flow_stats_request(struct ds *string, const struct ofp_header *oh, - const struct ofputil_port_map *port_map) + const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map) { struct ofputil_flow_stats_request fsr; enum ofperr error; @@ -1687,7 +1706,8 @@ ofp_print_flow_stats_request(struct ds *string, const struct ofp_header *oh, } if (fsr.table_id != 0xff) { - ds_put_format(string, " table=%"PRIu8, fsr.table_id); + ds_put_format(string, " table="); + ofputil_format_table(fsr.table_id, table_map, string); } if (fsr.out_port != OFPP_ANY) { @@ -1707,7 +1727,9 @@ ofp_print_flow_stats_request(struct ds *string, const struct ofp_header *oh, * ages, otherwise they are omitted. */ void ofp_print_flow_stats(struct ds *string, const struct ofputil_flow_stats *fs, - const struct ofputil_port_map *port_map, bool show_stats) + const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map, + bool show_stats) { if (show_stats || fs->cookie) { ds_put_format(string, "%scookie=%s0x%"PRIx64", ", @@ -1719,9 +1741,11 @@ ofp_print_flow_stats(struct ds *string, const struct ofputil_flow_stats *fs, ds_put_cstr(string, ", "); } - if (show_stats || fs->table_id) { - ds_put_format(string, "%stable=%s%"PRIu8", ", - colors.special, colors.end, fs->table_id); + if (show_stats || fs->table_id + || ofputil_table_map_get_name(table_map, fs->table_id) != NULL) { + ds_put_format(string, "%stable=%s", colors.special, colors.end); + ofputil_format_table(fs->table_id, table_map, string); + ds_put_cstr(string, ", "); } if (show_stats) { ds_put_format(string, "%sn_packets=%s%"PRIu64", ", @@ -1764,6 +1788,7 @@ ofp_print_flow_stats(struct ds *string, const struct ofputil_flow_stats *fs, ds_put_format(string, "%sactions=%s", colors.actions, colors.end); struct ofpact_format_params fp = { .port_map = port_map, + .table_map = table_map, .s = string, }; ofpacts_format(fs->ofpacts, fs->ofpacts_len, &fp); @@ -1771,7 +1796,8 @@ ofp_print_flow_stats(struct ds *string, const struct ofputil_flow_stats *fs, static enum ofperr ofp_print_flow_stats_reply(struct ds *string, const struct ofp_header *oh, - const struct ofputil_port_map *port_map) + const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map) { struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length)); struct ofpbuf ofpacts; @@ -1786,7 +1812,7 @@ ofp_print_flow_stats_reply(struct ds *string, const struct ofp_header *oh, break; } ds_put_cstr(string, "\n "); - ofp_print_flow_stats(string, &fs, port_map, true); + ofp_print_flow_stats(string, &fs, port_map, table_map, true); } ofpbuf_uninit(&ofpacts); @@ -1991,7 +2017,8 @@ ofp_print_ofpst_port_reply(struct ds *string, const struct ofp_header *oh, } static enum ofperr -ofp_print_table_stats_reply(struct ds *string, const struct ofp_header *oh) +ofp_print_table_stats_reply(struct ds *string, const struct ofp_header *oh, + const struct ofputil_table_map *table_map) { struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length)); ofpraw_pull_assert(&b); @@ -2011,7 +2038,8 @@ ofp_print_table_stats_reply(struct ds *string, const struct ofp_header *oh) ds_put_char(string, '\n'); ofp_print_table_features(string, &features, i ? &prev_features : NULL, - &stats, i ? &prev_stats : NULL); + &stats, i ? &prev_stats : NULL, + table_map); prev_features = features; prev_stats = stats; } @@ -2469,7 +2497,8 @@ nx_flow_monitor_flags_to_name(uint32_t bit) static enum ofperr ofp_print_nxst_flow_monitor_request(struct ds *string, const struct ofp_header *oh, - const struct ofputil_port_map *port_map) + const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map) { struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length)); for (;;) { @@ -2491,7 +2520,8 @@ ofp_print_nxst_flow_monitor_request(struct ds *string, } if (request.table_id != 0xff) { - ds_put_format(string, " table=%"PRIu8, request.table_id); + ds_put_format(string, " table="); + ofputil_format_table(request.table_id, table_map, string); } ds_put_char(string, ' '); @@ -2503,7 +2533,8 @@ ofp_print_nxst_flow_monitor_request(struct ds *string, static enum ofperr ofp_print_nxst_flow_monitor_reply(struct ds *string, const struct ofp_header *oh, - const struct ofputil_port_map *port_map) + const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map) { uint64_t ofpacts_stub[1024 / 8]; struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(ofpacts_stub); @@ -2542,7 +2573,8 @@ ofp_print_nxst_flow_monitor_reply(struct ds *string, continue; } - ds_put_format(string, " table=%"PRIu8, update.table_id); + ds_put_format(string, " table="); + ofputil_format_table(update.table_id, table_map, string); if (update.idle_timeout != OFP_FLOW_PERMANENT) { ds_put_format(string, " idle_timeout=%"PRIu16, update.idle_timeout); @@ -2563,6 +2595,7 @@ ofp_print_nxst_flow_monitor_reply(struct ds *string, ds_put_cstr(string, "actions="); struct ofpact_format_params fp = { .port_map = port_map, + .table_map = table_map, .s = string, }; ofpacts_format(update.ofpacts, update.ofpacts_len, &fp); @@ -2643,7 +2676,8 @@ ofp_print_group(struct ds *s, uint32_t group_id, uint8_t type, const struct ovs_list *p_buckets, const struct ofputil_group_props *props, enum ofp_version ofp_version, bool suppress_type, - const struct ofputil_port_map *port_map) + const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map) { struct ofputil_bucket *bucket; @@ -2698,6 +2732,7 @@ ofp_print_group(struct ds *s, uint32_t group_id, uint8_t type, ds_put_cstr(s, "actions="); struct ofpact_format_params fp = { .port_map = port_map, + .table_map = table_map, .s = s, }; ofpacts_format(bucket->ofpacts, bucket->ofpacts_len, &fp); @@ -2720,7 +2755,8 @@ ofp_print_ofpst_group_desc_request(struct ds *string, static enum ofperr ofp_print_group_desc(struct ds *s, const struct ofp_header *oh, - const struct ofputil_port_map *port_map) + const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map) { struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length)); for (;;) { @@ -2735,7 +2771,7 @@ ofp_print_group_desc(struct ds *s, const struct ofp_header *oh, ds_put_char(s, '\n'); ds_put_char(s, ' '); ofp_print_group(s, gd.group_id, gd.type, &gd.buckets, &gd.props, - oh->version, false, port_map); + oh->version, false, port_map, table_map); ofputil_uninit_group_desc(&gd); } } @@ -2842,7 +2878,8 @@ ofp_print_group_features(struct ds *string, const struct ofp_header *oh) static void ofp_print_group_mod__(struct ds *s, enum ofp_version ofp_version, const struct ofputil_group_mod *gm, - const struct ofputil_port_map *port_map) + const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map) { bool bucket_command = false; @@ -2887,12 +2924,13 @@ ofp_print_group_mod__(struct ds *s, enum ofp_version ofp_version, } ofp_print_group(s, gm->group_id, gm->type, &gm->buckets, &gm->props, - ofp_version, bucket_command, port_map); + ofp_version, bucket_command, port_map, table_map); } static enum ofperr ofp_print_group_mod(struct ds *s, const struct ofp_header *oh, - const struct ofputil_port_map *port_map) + const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map) { struct ofputil_group_mod gm; int error; @@ -2901,7 +2939,7 @@ ofp_print_group_mod(struct ds *s, const struct ofp_header *oh, if (error) { return error; } - ofp_print_group_mod__(s, oh->version, &gm, port_map); + ofp_print_group_mod__(s, oh->version, &gm, port_map, table_map); ofputil_uninit_group_mod(&gm); return 0; } @@ -3071,11 +3109,13 @@ ofp_print_table_features(struct ds *s, const struct ofputil_table_features *features, const struct ofputil_table_features *prev_features, const struct ofputil_table_stats *stats, - const struct ofputil_table_stats *prev_stats) + const struct ofputil_table_stats *prev_stats, + const struct ofputil_table_map *table_map) { int i; - ds_put_format(s, " table %"PRIu8, features->table_id); + ds_put_format(s, " table "); + ofputil_format_table(features->table_id, table_map, s); if (features->name[0]) { ds_put_format(s, " (\"%s\")", features->name); } @@ -3170,7 +3210,8 @@ ofp_print_table_features(struct ds *s, } static enum ofperr -ofp_print_table_features_reply(struct ds *s, const struct ofp_header *oh) +ofp_print_table_features_reply(struct ds *s, const struct ofp_header *oh, + const struct ofputil_table_map *table_map) { struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length)); @@ -3185,13 +3226,15 @@ ofp_print_table_features_reply(struct ds *s, const struct ofp_header *oh) } ds_put_char(s, '\n'); - ofp_print_table_features(s, &tf, i ? &prev : NULL, NULL, NULL); + ofp_print_table_features(s, &tf, i ? &prev : NULL, NULL, NULL, + table_map); prev = tf; } } static enum ofperr -ofp_print_table_desc_reply(struct ds *s, const struct ofp_header *oh) +ofp_print_table_desc_reply(struct ds *s, const struct ofp_header *oh, + const struct ofputil_table_map *table_map) { struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length)); for (;;) { @@ -3202,7 +3245,7 @@ ofp_print_table_desc_reply(struct ds *s, const struct ofp_header *oh) if (retval) { return retval != EOF ? retval : 0; } - ofp_print_table_desc(s, &td); + ofp_print_table_desc(s, &td, table_map); } } @@ -3268,7 +3311,9 @@ ofp_print_bundle_ctrl(struct ds *s, const struct ofp_header *oh) static enum ofperr ofp_print_bundle_add(struct ds *s, const struct ofp_header *oh, - const struct ofputil_port_map *port_map, int verbosity) + const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map, + int verbosity) { int error; struct ofputil_bundle_add_msg badd; @@ -3285,7 +3330,7 @@ ofp_print_bundle_add(struct ds *s, const struct ofp_header *oh, ds_put_char(s, '\n'); char *msg = ofp_to_string(badd.msg, ntohs(badd.msg->length), port_map, - verbosity); + table_map, verbosity); ds_put_and_free_cstr(s, msg); return 0; @@ -3376,7 +3421,8 @@ ofp_print_tlv_table_reply(struct ds *s, const struct ofp_header *oh) * request forward is taken from rf.request.type */ static enum ofperr ofp_print_requestforward(struct ds *string, const struct ofp_header *oh, - const struct ofputil_port_map *port_map) + const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map) { struct ofputil_requestforward rf; enum ofperr error; @@ -3391,7 +3437,8 @@ ofp_print_requestforward(struct ds *string, const struct ofp_header *oh, switch (rf.reason) { case OFPRFR_GROUP_MOD: ds_put_cstr(string, "group_mod"); - ofp_print_group_mod__(string, oh->version, rf.group_mod, port_map); + ofp_print_group_mod__(string, oh->version, rf.group_mod, port_map, + table_map); break; case OFPRFR_METER_MOD: @@ -3491,7 +3538,8 @@ ofp_print_nxt_ct_flush_zone(struct ds *string, const struct nx_zone_id *nzi) static enum ofperr ofp_to_string__(const struct ofp_header *oh, - const struct ofputil_port_map *port_map, enum ofpraw raw, + const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map, enum ofpraw raw, struct ds *string, int verbosity) { const void *msg = oh; @@ -3509,7 +3557,7 @@ ofp_to_string__(const struct ofp_header *oh, return ofp_print_ofpst_group_desc_request(string, oh); case OFPTYPE_GROUP_DESC_STATS_REPLY: - return ofp_print_group_desc(string, oh, port_map); + return ofp_print_group_desc(string, oh, port_map, table_map); case OFPTYPE_GROUP_FEATURES_STATS_REQUEST: ofp_print_stats(string, oh); @@ -3519,21 +3567,21 @@ ofp_to_string__(const struct ofp_header *oh, return ofp_print_group_features(string, oh); case OFPTYPE_GROUP_MOD: - return ofp_print_group_mod(string, oh, port_map); + return ofp_print_group_mod(string, oh, port_map, table_map); case OFPTYPE_TABLE_FEATURES_STATS_REQUEST: case OFPTYPE_TABLE_FEATURES_STATS_REPLY: - return ofp_print_table_features_reply(string, oh); + return ofp_print_table_features_reply(string, oh, table_map); case OFPTYPE_TABLE_DESC_REQUEST: case OFPTYPE_TABLE_DESC_REPLY: - return ofp_print_table_desc_reply(string, oh); + return ofp_print_table_desc_reply(string, oh, table_map); case OFPTYPE_HELLO: return ofp_print_hello(string, oh); case OFPTYPE_ERROR: - return ofp_print_error_msg(string, oh, port_map); + return ofp_print_error_msg(string, oh, port_map, table_map); case OFPTYPE_ECHO_REQUEST: case OFPTYPE_ECHO_REPLY: @@ -3555,25 +3603,26 @@ ofp_to_string__(const struct ofp_header *oh, return ofp_print_set_config(string, oh); case OFPTYPE_PACKET_IN: - return ofp_print_packet_in(string, oh, port_map, verbosity); + return ofp_print_packet_in(string, oh, port_map, table_map, verbosity); case OFPTYPE_FLOW_REMOVED: - return ofp_print_flow_removed(string, oh, port_map); + return ofp_print_flow_removed(string, oh, port_map, table_map); case OFPTYPE_PORT_STATUS: return ofp_print_port_status(string, oh); case OFPTYPE_PACKET_OUT: - return ofp_print_packet_out(string, oh, port_map, verbosity); + return ofp_print_packet_out(string, oh, port_map, table_map, + verbosity); case OFPTYPE_FLOW_MOD: - return ofp_print_flow_mod(string, oh, port_map, verbosity); + return ofp_print_flow_mod(string, oh, port_map, table_map, verbosity); case OFPTYPE_PORT_MOD: return ofp_print_port_mod(string, oh, port_map); case OFPTYPE_TABLE_MOD: - return ofp_print_table_mod(string, oh); + return ofp_print_table_mod(string, oh, table_map); case OFPTYPE_METER_MOD: return ofp_print_meter_mod(string, oh); @@ -3595,10 +3644,10 @@ ofp_to_string__(const struct ofp_header *oh, return ofp_print_role_status_message(string, oh); case OFPTYPE_REQUESTFORWARD: - return ofp_print_requestforward(string, oh, port_map); + return ofp_print_requestforward(string, oh, port_map, table_map); case OFPTYPE_TABLE_STATUS: - return ofp_print_table_status_message(string, oh); + return ofp_print_table_status_message(string, oh, table_map); case OFPTYPE_METER_STATS_REQUEST: case OFPTYPE_METER_CONFIG_STATS_REQUEST: @@ -3625,7 +3674,7 @@ ofp_to_string__(const struct ofp_header *oh, case OFPTYPE_FLOW_STATS_REQUEST: case OFPTYPE_AGGREGATE_STATS_REQUEST: ofp_print_stats(string, oh); - return ofp_print_flow_stats_request(string, oh, port_map); + return ofp_print_flow_stats_request(string, oh, port_map, table_map); case OFPTYPE_TABLE_STATS_REQUEST: ofp_print_stats(string, oh); @@ -3645,7 +3694,7 @@ ofp_to_string__(const struct ofp_header *oh, case OFPTYPE_FLOW_STATS_REPLY: ofp_print_stats(string, oh); - return ofp_print_flow_stats_reply(string, oh, port_map); + return ofp_print_flow_stats_reply(string, oh, port_map, table_map); case OFPTYPE_QUEUE_STATS_REPLY: ofp_print_stats(string, oh); @@ -3657,7 +3706,7 @@ ofp_to_string__(const struct ofp_header *oh, case OFPTYPE_TABLE_STATS_REPLY: ofp_print_stats(string, oh); - return ofp_print_table_stats_reply(string, oh); + return ofp_print_table_stats_reply(string, oh, table_map); case OFPTYPE_AGGREGATE_STATS_REPLY: ofp_print_stats(string, oh); @@ -3699,16 +3748,19 @@ ofp_to_string__(const struct ofp_header *oh, break; case OFPTYPE_FLOW_MONITOR_STATS_REQUEST: - return ofp_print_nxst_flow_monitor_request(string, msg, port_map); + return ofp_print_nxst_flow_monitor_request(string, msg, port_map, + table_map); case OFPTYPE_FLOW_MONITOR_STATS_REPLY: - return ofp_print_nxst_flow_monitor_reply(string, msg, port_map); + return ofp_print_nxst_flow_monitor_reply(string, msg, port_map, + table_map); case OFPTYPE_BUNDLE_CONTROL: return ofp_print_bundle_ctrl(string, msg); case OFPTYPE_BUNDLE_ADD_MESSAGE: - return ofp_print_bundle_add(string, msg, port_map, verbosity); + return ofp_print_bundle_add(string, msg, port_map, table_map, + verbosity); case OFPTYPE_NXT_TLV_TABLE_MOD: return ofp_print_tlv_table_mod(string, msg); @@ -3720,7 +3772,8 @@ ofp_to_string__(const struct ofp_header *oh, return ofp_print_tlv_table_reply(string, msg); case OFPTYPE_NXT_RESUME: - return ofp_print_packet_in(string, msg, port_map, verbosity); + return ofp_print_packet_in(string, msg, port_map, table_map, + verbosity); case OFPTYPE_IPFIX_BRIDGE_STATS_REQUEST: break; case OFPTYPE_IPFIX_BRIDGE_STATS_REPLY: @@ -3751,7 +3804,9 @@ add_newline(struct ds *s) * for freeing the string. */ char * ofp_to_string(const void *oh_, size_t len, - const struct ofputil_port_map *port_map, int verbosity) + const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map, + int verbosity) { struct ds string = DS_EMPTY_INITIALIZER; const struct ofp_header *oh = oh_; @@ -3787,7 +3842,8 @@ ofp_to_string(const void *oh_, size_t len, ofp_header_to_string__(oh, raw, &string); size_t header_len = string.length; - error = ofp_to_string__(oh, port_map, raw, &string, verbosity); + error = ofp_to_string__(oh, port_map, table_map, + raw, &string, verbosity); if (error) { if (string.length > header_len) { ds_chomp(&string, ' '); @@ -3827,9 +3883,11 @@ print_and_free(FILE *stream, char *string) * numbers increase verbosity. */ void ofp_print(FILE *stream, const void *oh, size_t len, - const struct ofputil_port_map *port_map, int verbosity) + const struct ofputil_port_map *port_map, + const struct ofputil_table_map *table_map, int verbosity) { - print_and_free(stream, ofp_to_string(oh, len, port_map, verbosity)); + print_and_free(stream, ofp_to_string(oh, len, port_map, table_map, + verbosity)); } /* Dumps the contents of the Ethernet frame in the 'len' bytes starting at diff --git a/lib/ofp-util.c b/lib/ofp-util.c index f3b2e3f6108c..09ad93132918 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -7378,16 +7378,16 @@ ofputil_port_get_reserved_name(ofp_port_t port) } } -/* A port name doesn't need to be quoted if it is alphanumeric and starts with - * a letter. */ +/* A table or port name doesn't need to be quoted if it is alphanumeric and + * starts with a letter. */ static bool -port_name_needs_quotes(const char *port_name) +name_needs_quotes(const char *name) { - if (!isalpha((unsigned char) port_name[0])) { + if (!isalpha((unsigned char) name[0])) { return true; } - for (const char *p = port_name + 1; *p; p++) { + for (const char *p = name + 1; *p; p++) { if (!isalnum((unsigned char) *p)) { return true; } @@ -7395,13 +7395,14 @@ port_name_needs_quotes(const char *port_name) return false; } +/* Appends port or table 'name' to 's', quoting it if necessary. */ static void -put_port_name(const char *port_name, struct ds *s) +put_name(const char *name, struct ds *s) { - if (port_name_needs_quotes(port_name)) { - json_string_escape(port_name, s); + if (name_needs_quotes(name)) { + json_string_escape(name, s); } else { - ds_put_cstr(s, port_name); + ds_put_cstr(s, name); } } @@ -7420,7 +7421,7 @@ ofputil_format_port(ofp_port_t port, const struct ofputil_port_map *port_map, const char *port_name = ofputil_port_map_get_name(port_map, port); if (port_name) { - put_port_name(port_name, s); + put_name(port_name, s); return; } @@ -7445,7 +7446,7 @@ ofputil_port_to_string(ofp_port_t port, const char *port_name = ofputil_port_map_get_name(port_map, port); if (port_name) { struct ds s = DS_EMPTY_INITIALIZER; - put_port_name(port_name, &s); + put_name(port_name, &s); ovs_strlcpy(namebuf, ds_cstr(&s), bufsize); ds_destroy(&s); return; @@ -7644,6 +7645,92 @@ ofputil_table_map_destroy(struct ofputil_table_map *map) ofputil_name_map_destroy(&map->map); } +/* Table numbers. */ + +/* Stores the table number represented by 's' into '*tablep'. 's' may be an + * integer or, if 'table_map' is nonnull, a name (quoted or unquoted). + * + * Returns true if successful, false if 's' is not a valid OpenFlow table + * number or name. The caller should issue an error message in this case, + * because this function usually does not. (This gives the caller an + * opportunity to look up the table name another way, e.g. by contacting the + * switch and listing the names of all its tables). */ +bool +ofputil_table_from_string(const char *s, + const struct ofputil_table_map *table_map, + uint8_t *tablep) +{ + *tablep = 0; + if (*s == '-') { + VLOG_WARN("Negative value %s is not a valid table number.", s); + return false; + } + + unsigned int table; + if (str_to_uint(s, 10, &table)) { + if (table > 255) { + VLOG_WARN("table %u is outside the supported range 0 through 255", + table); + return false; + } + *tablep = table; + return true; + } else { + if (s[0] != '"') { + table = ofputil_table_map_get_number(table_map, s); + } else { + size_t length = strlen(s); + char *name = NULL; + if (length > 1 + && s[length - 1] == '"' + && json_string_unescape(s + 1, length - 2, &name)) { + table = ofputil_table_map_get_number(table_map, name); + } + free(name); + } + if (table != UINT8_MAX) { + *tablep = table; + return true; + } + + return false; + } +} + +/* Appends to 's' a string representation of the OpenFlow table number 'table', + * either the table number or a name drawn from 'table_map'. */ +void +ofputil_format_table(uint8_t table, const struct ofputil_table_map *table_map, + struct ds *s) +{ + const char *table_name = ofputil_table_map_get_name(table_map, table); + if (table_name) { + put_name(table_name, s); + } else { + ds_put_format(s, "%"PRIu8, table); + } +} + +/* Puts in the 'bufsize' byte in 'namebuf' a null-terminated string + * representation of OpenFlow table number 'table', either the table's number + * or a name drawn from 'table_map'. */ +void +ofputil_table_to_string(uint8_t table, + const struct ofputil_table_map *table_map, + char *namebuf, size_t bufsize) +{ + const char *table_name = ofputil_table_map_get_name(table_map, table); + if (table_name) { + struct ds s = DS_EMPTY_INITIALIZER; + put_name(table_name, &s); + ovs_strlcpy(namebuf, ds_cstr(&s), bufsize); + ds_destroy(&s); + return; + } + + snprintf(namebuf, bufsize, "%"PRIu8, table); +} + /* Stores the group id represented by 's' into '*group_idp'. 's' may be an * integer or, for reserved group IDs, the standard OpenFlow name for the group * (either "ANY" or "ALL"). diff --git a/lib/vconn.c b/lib/vconn.c index bb56be2d2901..f0d00eec104f 100644 --- a/lib/vconn.c +++ b/lib/vconn.c @@ -496,7 +496,7 @@ vcs_recv_hello(struct vconn *vconn) ofpbuf_delete(b); return; } else { - char *s = ofp_to_string(b->data, b->size, NULL, 1); + char *s = ofp_to_string(b->data, b->size, NULL, NULL, 1); VLOG_WARN_RL(&bad_ofmsg_rl, "%s: received message while expecting hello: %s", vconn->name, s); @@ -642,7 +642,8 @@ do_recv(struct vconn *vconn, struct ofpbuf **msgp) if (!retval) { COVERAGE_INC(vconn_received); if (VLOG_IS_DBG_ENABLED()) { - char *s = ofp_to_string((*msgp)->data, (*msgp)->size, NULL, 1); + char *s = ofp_to_string((*msgp)->data, (*msgp)->size, + NULL, NULL, 1); VLOG_DBG_RL(&ofmsg_rl, "%s: received: %s", vconn->name, s); free(s); } @@ -682,7 +683,7 @@ do_send(struct vconn *vconn, struct ofpbuf *msg) COVERAGE_INC(vconn_sent); retval = (vconn->vclass->send)(vconn, msg); } else { - char *s = ofp_to_string(msg->data, msg->size, NULL, 1); + char *s = ofp_to_string(msg->data, msg->size, NULL, NULL, 1); retval = (vconn->vclass->send)(vconn, msg); if (retval != EAGAIN) { VLOG_DBG_RL(&ofmsg_rl, "%s: sent (%s): %s", @@ -958,7 +959,8 @@ recv_flow_stats_reply(struct vconn *vconn, ovs_be32 send_xid, error = ofptype_decode(&type, reply->data); if (error || type != OFPTYPE_FLOW_STATS_REPLY) { VLOG_WARN_RL(&rl, "received bad reply: %s", - ofp_to_string(reply->data, reply->size, NULL, 1)); + ofp_to_string(reply->data, reply->size, + NULL, NULL, 1)); return EPROTO; } } diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 6157b70aee60..c7427846c047 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -1700,11 +1700,9 @@ flush(struct ofproto *ofproto_) static void query_tables(struct ofproto *ofproto, - struct ofputil_table_features *features, + struct ofputil_table_features *features OVS_UNUSED, struct ofputil_table_stats *stats) { - strcpy(features->name, "classifier"); - if (stats) { int i; diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index 71f449f7ddda..6d3e12976408 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -3225,7 +3225,7 @@ query_tables(struct ofproto *ofproto, struct ofputil_table_features *f = &features[i]; f->table_id = i; - sprintf(f->name, "table%d", i); + f->name[0] = '\0'; f->metadata_match = OVS_BE64_MAX; f->metadata_write = OVS_BE64_MAX; atomic_read_relaxed(&ofproto->tables[i].miss_config, &f->miss_config); diff --git a/ovn/controller/ofctrl.c b/ovn/controller/ofctrl.c index 264667769296..26cf186dcae8 100644 --- a/ovn/controller/ofctrl.c +++ b/ovn/controller/ofctrl.c @@ -286,7 +286,7 @@ recv_S_TLV_TABLE_REQUESTED(const struct ofp_header *oh, enum ofptype type, VLOG_ERR("switch refused to allocate Geneve option (%s)", ofperr_to_string(ofperr_decode_msg(oh, NULL))); } else { - char *s = ofp_to_string(oh, ntohs(oh->length), NULL, 1); + char *s = ofp_to_string(oh, ntohs(oh->length), NULL, NULL, 1); VLOG_ERR("unexpected reply to TLV table request (%s)", s); free(s); } @@ -340,7 +340,7 @@ recv_S_TLV_TABLE_MOD_SENT(const struct ofp_header *oh, enum ofptype type, goto error; } } else { - char *s = ofp_to_string(oh, ntohs(oh->length), NULL, 1); + char *s = ofp_to_string(oh, ntohs(oh->length), NULL, NULL, 1); VLOG_ERR("unexpected reply to Geneve option allocation request (%s)", s); free(s); @@ -513,7 +513,7 @@ ofctrl_run(const struct ovsrec_bridge *br_int, struct shash *pending_ct_zones) OVS_NOT_REACHED(); } } else { - char *s = ofp_to_string(oh, ntohs(oh->length), NULL, 1); + char *s = ofp_to_string(oh, ntohs(oh->length), NULL, NULL, 1); VLOG_WARN("could not decode OpenFlow message (%s): %s", ofperr_to_string(error), s); free(s); @@ -573,7 +573,7 @@ log_openflow_rl(struct vlog_rate_limit *rl, enum vlog_level level, const struct ofp_header *oh, const char *title) { if (!vlog_should_drop(&this_module, level, rl)) { - char *s = ofp_to_string(oh, ntohs(oh->length), NULL, 2); + char *s = ofp_to_string(oh, ntohs(oh->length), NULL, NULL, 2); vlog(&this_module, level, "%s: %s", title, s); free(s); } @@ -878,7 +878,7 @@ ofctrl_put(struct hmap *flow_table, struct shash *pending_ct_zones, error = parse_ofp_group_mod_str(&gm, OFPGC11_ADD, ds_cstr(&group_string), NULL, - &usable_protocols); + NULL, &usable_protocols); if (!error) { add_group_mod(&gm, &msgs); } else { @@ -978,7 +978,7 @@ ofctrl_put(struct hmap *flow_table, struct shash *pending_ct_zones, error = parse_ofp_group_mod_str(&gm, OFPGC11_DELETE, ds_cstr(&group_string), NULL, - &usable_protocols); + NULL, &usable_protocols); if (!error) { add_group_mod(&gm, &msgs); } else { diff --git a/ovn/controller/pinctrl.c b/ovn/controller/pinctrl.c index 7542db3f4854..27bcf3317f99 100644 --- a/ovn/controller/pinctrl.c +++ b/ovn/controller/pinctrl.c @@ -1039,7 +1039,7 @@ pinctrl_recv(const struct ofp_header *oh, enum ofptype type, if (VLOG_IS_DBG_ENABLED()) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(30, 300); - char *s = ofp_to_string(oh, ntohs(oh->length), NULL, 2); + char *s = ofp_to_string(oh, ntohs(oh->length), NULL, NULL, 2); VLOG_DBG_RL(&rl, "OpenFlow packet ignored: %s", s); free(s); diff --git a/ovn/utilities/ovn-sbctl.c b/ovn/utilities/ovn-sbctl.c index 0cb8ea480438..dc56d864c986 100644 --- a/ovn/utilities/ovn-sbctl.c +++ b/ovn/utilities/ovn-sbctl.c @@ -796,7 +796,7 @@ sbctl_dump_openflow(struct vconn *vconn, const struct uuid *uuid, bool stats) ds_clear(&s); if (stats) { - ofp_print_flow_stats(&s, fs, NULL, true); + ofp_print_flow_stats(&s, fs, NULL, NULL, true); } else { ds_put_format(&s, "%stable=%s%"PRIu8" ", colors.special, colors.end, fs->table_id); diff --git a/ovn/utilities/ovn-trace.c b/ovn/utilities/ovn-trace.c index 7ff4a2682557..279303be0c6a 100644 --- a/ovn/utilities/ovn-trace.c +++ b/ovn/utilities/ovn-trace.c @@ -1932,7 +1932,7 @@ trace_openflow(const struct ovntrace_flow *f, struct ovs_list *super) struct ds s = DS_EMPTY_INITIALIZER; for (size_t i = 0; i < n_fses; i++) { ds_clear(&s); - ofp_print_flow_stats(&s, &fses[i], NULL, true); + ofp_print_flow_stats(&s, &fses[i], NULL, NULL, true); ovntrace_node_append(super, OVNTRACE_NODE_ACTION, "%s", ds_cstr(&s)); } diff --git a/tests/ofproto.at b/tests/ofproto.at index b49f546afa67..1b0ba94fd837 100644 --- a/tests/ofproto.at +++ b/tests/ofproto.at @@ -2174,7 +2174,7 @@ OVS_VSWITCHD_START # Check the default configuration. head_table() { printf 'OFPST_TABLE reply (xid=0x2): - table 0 ("%s"): + table 0%s: active=0, lookup=0, matched=0 max_entries=1000000 matching: @@ -2191,14 +2191,14 @@ head_table() { tcp_src: exact match or wildcard tcp_dst: exact match or wildcard -' $1 +' "$1" } ditto() { for i in `seq $1 $2`; do - printf ' table %d ("table%d"): ditto\n' $i $i + printf ' table %d: ditto\n' $i done } -(head_table classifier; ditto 1 253) > expout +(head_table; ditto 1 253) > expout AT_CHECK([ovs-ofctl dump-tables br0], [0], [expout]) # Change the configuration. AT_CHECK( @@ -2211,12 +2211,12 @@ AT_CHECK( <1> ]) # Check that the configuration was updated. -(head_table main; echo ' table 1 ("table1"): +(head_table ' ("main")'; echo ' table 1: active=0, lookup=0, matched=0 max_entries=1024 (same matching) - table 2 ("table2"): + table 2: active=0, lookup=0, matched=0 max_entries=1000000 (same matching) @@ -2250,7 +2250,7 @@ AT_CHECK([test `grep '240\.0\.0\.1' stdout | grep -v table_id= | wc -l` -gt 0]) # Check that dump-tables doesn't count the hidden flows. head_table() { printf 'OFPST_TABLE reply: - table 0 ("%s"): + table 0: active=0, lookup=0, matched=0 max_entries=1000000 matching: @@ -2267,14 +2267,14 @@ head_table() { tcp_src: exact match or wildcard tcp_dst: exact match or wildcard -' $1 +' } ditto() { for i in `seq $1 $2`; do - printf ' table %d ("table%d"): ditto\n' $i $i + printf ' table %d: ditto\n' $i done } -(head_table classifier; ditto 1 253) > expout +(head_table; ditto 1 253) > expout AT_CHECK([ovs-ofctl dump-tables br0 | strip_xids], [0], [expout]) OVS_VSWITCHD_STOP(["/240\.0\.0\.1/d"]) AT_CLEANUP @@ -2284,7 +2284,7 @@ OVS_VSWITCHD_START # Check the default configuration. head_table() { printf 'OFPST_TABLE reply (OF1.2) (xid=0x2): - table 0 ("%s"): + table 0%s: active=0, lookup=0, matched=0 metadata: match=0xffffffffffffffff write=0xffffffffffffffff config=controller @@ -2331,15 +2331,15 @@ head_table() { nd_sll: exact match or wildcard nd_tll: exact match or wildcard -' $1 +' "$1" } ditto() { for i in `seq $1 $2`; do - printf ' table %d ("table%d"): ditto\n' $i $i + printf ' table %d: ditto\n' $i done } tail_table() { - printf ' table 253 ("table253"): + printf ' table 253: active=0, lookup=0, matched=0 metadata: match=0xffffffffffffffff write=0xffffffffffffffff config=controller @@ -2350,7 +2350,7 @@ tail_table() { (same matching) ' } -(head_table classifier; ditto 1 252; tail_table) > expout +(head_table; ditto 1 252; tail_table) > expout AT_CHECK([ovs-ofctl -O OpenFlow12 dump-tables br0], [0], [expout]) # Change the configuration. AT_CHECK( @@ -2363,7 +2363,7 @@ AT_CHECK( <1> ]) # Check that the configuration was updated. -(head_table main; echo ' table 1 ("table1"): +(head_table ' ("main")'; echo ' table 1: active=0, lookup=0, matched=0 metadata: match=0xffffffffffffffff write=0xffffffffffffffff config=controller @@ -2371,7 +2371,7 @@ AT_CHECK( (same instructions) (same matching) - table 2 ("table2"): + table 2: active=0, lookup=0, matched=0 metadata: match=0xffffffffffffffff write=0xffffffffffffffff config=controller @@ -2386,7 +2386,7 @@ AT_CLEANUP AT_SETUP([ofproto - table features (OpenFlow 1.3)]) OVS_VSWITCHD_START head_table () { - printf ' table 0 ("%s"): + printf ' table 0%s: metadata: match=0xffffffffffffffff write=0xffffffffffffffff max_entries=1000000 instructions (table miss and others): @@ -2569,10 +2569,10 @@ metadata in_port in_port_oxm pkt_mark ct_mark ct_label reg0 reg1 reg2 reg3 reg4 nsh_c4: arbitrary mask nsh_ttl: exact match or wildcard -' $1 +' "$1" } ditto() { - printf ' table %d ("%s"): + printf ' table %d: metadata: match=0xffffffffffffffff write=0xffffffffffffffff max_entries=%d instructions (table miss and others): @@ -2581,10 +2581,10 @@ ditto() { (same actions) (same matching) -' $1 $2 $3 `expr $1 + 1` +' $1 $2 `expr $1 + 1` } tail_tables() { -echo ' table 252 ("table252"): +echo ' table 252: metadata: match=0xffffffffffffffff write=0xffffffffffffffff max_entries=1000000 instructions (table miss and others): @@ -2593,7 +2593,7 @@ echo ' table 252 ("table252"): (same actions) (same matching) - table 253 ("table253"): + table 253: metadata: match=0xffffffffffffffff write=0xffffffffffffffff max_entries=1000000 instructions (table miss and others): @@ -2602,9 +2602,9 @@ echo ' table 252 ("table252"): (same matching) ' } -(head_table classifier +(head_table for i in `seq 1 251`; do - ditto $i table$i 1000000 + ditto $i 1000000 done tail_tables) > expout AT_CHECK([ovs-ofctl -O OpenFlow13 dump-table-features br0], [0], [expout]) @@ -2619,16 +2619,49 @@ AT_CHECK( <1> ]) # Check that the configuration was updated. -(head_table main - ditto 1 table1 1024 +(head_table ' ("main")' + ditto 1 1024 for i in `seq 2 251`; do - ditto $i table$i 1000000 + ditto $i 1000000 done tail_tables) > expout AT_CHECK([ovs-ofctl -O OpenFlow13 dump-table-features br0], [0], [expout]) OVS_VSWITCHD_STOP AT_CLEANUP +AT_SETUP([ofproto - flow table names]) +OVS_VSWITCHD_START +add_of_ports br0 1 2 +AT_CHECK( + [ovs-vsctl \ + -- --id=@t0 create Flow_Table name=zero \ + -- --id=@t1 create Flow_Table name=one \ + -- --id=@t2 create Flow_Table name=two \ + -- set bridge br0 'flow_tables={0=@t0,1=@t1,2=@t2}' \ + | uuidfilt], + [0], [<0> +<1> +<2> +]) +AT_DATA([flows.txt], [dnl +table=zero in_port=p2 actions=p1,resubmit(,one) +table=one,in_port=p1,ip,actions=ct(table=two) +table=one,in_port=p1,arp,actions=goto_table(two) +]) +AT_CHECK([ovs-ofctl add-flows br0 flows.txt]) +AT_CHECK([ovs-ofctl --names --no-stats dump-flows br0], [0], [dnl + table=zero, in_port=p2 actions=output:p1,resubmit(,one) + table=one, ip,in_port=p1 actions=ct(table=two) + table=one, arp,in_port=p1 actions=resubmit(,two) +]) +AT_CHECK([ovs-ofctl --no-names --no-stats dump-flows br0], [0], [dnl + in_port=2 actions=output:1,resubmit(,1) + table=1, ip,in_port=1 actions=ct(table=2) + table=1, arp,in_port=1 actions=resubmit(,2) +]) +OVS_VSWITCHD_STOP +AT_CLEANUP + AT_SETUP([ofproto - table description (OpenFlow 1.4)]) OVS_VSWITCHD_START (x=0 diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in index 95344c7e3872..7649bc5c4c50 100644 --- a/utilities/ovs-ofctl.8.in +++ b/utilities/ovs-ofctl.8.in @@ -66,9 +66,12 @@ Prints to the console features for each of the flow tables used by \fBdump\-table\-desc \fIswitch\fR Prints to the console configuration for each of the flow tables used by \fIswitch\fR for OpenFlow 1.4+. -.IP "\fBmod\-table \fIswitch\fR \fItable_id\fR \fIsetting\fR" -This command configures flow table settings for OpenFlow table -\fItable_id\fR within \fIswitch\fR. The available settings depend on +.IP "\fBmod\-table \fIswitch\fR \fItable\fR \fIsetting\fR" +This command configures flow table settings in \fIswitch\fR for +OpenFlow table \fItable\fR, which may be expressed as a number or +(unless \fB\-\-no\-names\fR is specified) a name. +.IP +The available settings depend on the OpenFlow version in use. In OpenFlow 1.1 and 1.2 (which must be enabled with the \fB\-O\fR option) only, \fBmod\-table\fR configures behavior when no flow is found when a packet is looked up in a flow @@ -606,9 +609,11 @@ connection to the switch. (These could only occur using the COMMANDS\fR.) .IP "\fB!actions\fR" Do not report actions as part of flow updates. -.IP "\fBtable=\fInumber\fR" -Limits the monitoring to the table with the given \fInumber\fR between -0 and 254. By default, all tables are monitored. +.IP "\fBtable=\fItable\fR" +Limits the monitoring to the table with the given \fItable\fR, which +may be expressed as a number between 0 and 254 or (unless +\fB\-\-no\-names\fR is specified) a name. By default, all tables are +monitored. .IP "\fBout_port=\fIport\fR" If set, only flows that output to \fIport\fR are monitored. The \fIport\fR may be an OpenFlow port number or keyword @@ -699,10 +704,11 @@ flows not in normal form. them. In addition to match fields, commands that operate on flows accept a few additional key-value pairs: . -.IP \fBtable=\fInumber\fR -For flow dump commands, limits the flows dumped to those in the table -with the given \fInumber\fR between 0 and 254. If not specified (or if -255 is specified as \fInumber\fR), then flows in all tables are +.IP \fBtable=\fItable\fR +For flow dump commands, limits the flows dumped to those in +\fItable\fR, which may be expressed as a number between 0 and 255 or +(unless \fB\-\-no\-names\fR is specified) a name. If not specified +(or if 255 is specified as \fItable\fR), then flows in all tables are dumped. . .IP @@ -970,8 +976,8 @@ only known to be implemented by Open vSwitch: .IP \fBresubmit\fB:\fIport\fR .IQ \fBresubmit\fB(\fR[\fIport\fR]\fB,\fR[\fItable\fR]\fB) .IQ \fBresubmit\fB(\fR[\fIport\fR]\fB,\fR[\fItable\fR]\fB,ct) -Re-searches this OpenFlow flow table (or the table whose number is -specified by \fItable\fR) with the \fBin_port\fR field replaced by +Re-searches this OpenFlow flow table (or table \fItable\fR, if +specified) with the \fBin_port\fR field replaced by \fIport\fR (if \fIport\fR is specified) and the packet 5-tuple fields swapped with the corresponding conntrack original direction tuple fields (if \fBct\fR is specified, see \fBct_nw_src\fR above), and @@ -980,6 +986,9 @@ in this flow entry. The \fBin_port\fR and swapped 5-tuple fields are restored immediately after the search, before any actions are executed. .IP +The \fItable\fR may be expressed as a number between 0 and 254 or +(unless \fB\-\-no\-names\fR is specified) a name. +.IP The \fBct\fR option requires a valid connection tracking state as a match prerequisite in the flow where this action is placed. Examples of valid connection tracking state matches include @@ -1057,12 +1066,14 @@ existing connection and start a new one in the current direction. This flag has no effect if the original direction of the connection is already the same as that of the current packet. .RE -.IP \fBtable=\fInumber\fR +.IP \fBtable=\fItable\fR Fork pipeline processing in two. The original instance of the packet will continue processing the current actions list as an untracked packet. An additional instance of the packet will be sent to the connection tracker, which will be re-injected into the OpenFlow pipeline to resume processing in table -\fInumber\fR, with the \fBct_state\fR and other ct match fields set. If the +\fInumber\fR (which may be specified as a number between 0 and 254 or, +unless \fB\-\-no\-names\fR is specified, a name), with the +\fBct_state\fR and other ct match fields set. If \fBtable\fR is not specified, then the packet which is submitted to the connection tracker is not re-injected into the OpenFlow pipeline. It is strongly recommended to specify a table later than the current table to prevent @@ -1472,10 +1483,10 @@ flow syntax. Adds a \fBfin_timeout\fR action with the specified arguments to the new flow. This feature was added in Open vSwitch 1.5.90. . -.IP \fBtable=\fInumber\fR +.IP \fBtable=\fItable\fR The table in which the new flow should be inserted. Specify a decimal -number between 0 and 254. The default, if \fBtable\fR is unspecified, -is table 1. +number between 0 and 254 or (unless \fB\-\-no\-names\fR is specified) +a name. The default, if \fBtable\fR is unspecified, is table 1. . .IP \fBdelete_learned\fR This flag enables deletion of the learned flows when the flow with the @@ -1547,12 +1558,6 @@ Add an \fBoutput\fR action to the new flow's actions, that outputs to the OpenFlow port taken from \fIfield\fB[\fIstart\fB..\fIend\fB]\fR, which must be an NXM field as described above. .RE -.IP -For best performance, segregate learned flows into a table (using -\fBtable=\fInumber\fR) that is not used for any other flows except -possibly for a lowest-priority ``catch-all'' flow, that is, a flow -with no match criteria. (This is why the default \fBtable\fR is 1, to -keep the learned flows separate from the primary flow table 0.) .RE . .RS @@ -1675,7 +1680,9 @@ band type. See the description of the \fBMeter Table Commands\fR, above, for more details. . .IP \fBgoto_table\fR:\fItable\fR -Indicates the next table in the process pipeline. +Jumps to \fItable\Fr as the next table in the process pipeline. The +\fItable\fR may be a number between 0 and 254 or (unless +\fB\-\-no\-names\fR is specified) a name. . .IP "\fBfin_timeout(\fIargument\fR[\fB,\fIargument\fR]\fB)" This action changes the idle timeout or hard timeout, or both, of this @@ -2286,21 +2293,24 @@ Uses strict matching when running flow modification commands. . .IP "\fB\-\-names\fR" .IQ "\fB\-\-no\-names\fR" -Every OpenFlow port has a name and a number. By default, -\fBovs\-ofctl\fR commands accept both port names and numbers, and they -display port names if \fBovs\-ofctl\fR is running on an interactive -console, port numbers otherwise. With \fB\-\-names\fR, -\fBovs\-ofctl\fR commands both accept and display port names; with -\fB\-\-no\-names\fR, commands neither accept nor display port names. -.IP -If a port name contains special characters or might be confused with a -keyword within a flow, it may be enclosed in double quotes (escaped -from the shell). If necessary, JSON-style escape sequences may be -used inside quotes, as specified in RFC 7159. When it displays port -names, \fBovs\-ofctl\fR quotes any name that does not start with a -letter followed by letters or digits. -.IP -These options are new in Open vSwitch 2.8. Earlier versions always +Every OpenFlow port has a name and a number, and every OpenFlow flow +table has a number and sometimes a name. By default, \fBovs\-ofctl\fR +commands accept both port and table names and numbers, and they +display port and table names if \fBovs\-ofctl\fR is running on an +interactive console, numbers otherwise. With \fB\-\-names\fR, +\fBovs\-ofctl\fR commands both accept and display port and table +names; with \fB\-\-no\-names\fR, commands neither accept nor display +port and table names. +.IP +If a port or table name contains special characters or might be +confused with a keyword within a flow, it may be enclosed in double +quotes (escaped from the shell). If necessary, JSON-style escape +sequences may be used inside quotes, as specified in RFC 7159. When +it displays port and table names, \fBovs\-ofctl\fR quotes any name +that does not start with a letter followed by letters or digits. +.IP +Open vSwitch added support for port names and these options. Open +vSwitch 2.10 added support for table names. Earlier versions always behaved as if \fB\-\-no\-names\fR were specified. .IP Open vSwitch does not place its own limit on the length of port names, @@ -2312,6 +2322,8 @@ Truncation can also cause long names that are different to appear to be the same; when a switch has two ports with the same (truncated) name, \fBovs\-ofctl\fR refuses to display or accept the name, using the number instead. +.IP +OpenFlow and Open vSwitch limit table names to 32 bytes. . .IP "\fB\-\-stats\fR" .IQ "\fB\-\-no\-stats\fR" diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c index 56af5a444d95..4f7cdf6d5eee 100644 --- a/utilities/ovs-ofctl.c +++ b/utilities/ovs-ofctl.c @@ -125,15 +125,18 @@ struct sort_criterion { static struct sort_criterion *criteria; static size_t n_criteria, allocated_criteria; -/* --names, --no-names: Show port names in output and accept port numbers in - * input. (When neither is specified, the default is to accept port numbers - * but, for backward compatibility, not to show them unless this is an - * interactive console session.) */ -static int use_port_names = -1; +/* --names, --no-names: Show port and table names in output and accept them in + * input. (When neither is specified, the default is to accept port names but, + * for backward compatibility, not to show them unless this is an interactive + * console session.) */ +static int use_names = -1; static const struct ofputil_port_map *ports_to_accept(const char *vconn_name); static const struct ofputil_port_map *ports_to_show(const char *vconn_name); -static bool should_accept_ports(void); -static bool should_show_ports(void); +static const struct ofputil_table_map *tables_to_accept( + const char *vconn_name); +static const struct ofputil_table_map *tables_to_show(const char *vconn_name); +static bool should_accept_names(void); +static bool should_show_names(void); /* --stats, --no-stats: Show statistics in flow dumps? */ static int show_stats = 1; @@ -213,8 +216,8 @@ parse_options(int argc, char *argv[]) {"timestamp", no_argument, NULL, OPT_TIMESTAMP}, {"sort", optional_argument, NULL, OPT_SORT}, {"rsort", optional_argument, NULL, OPT_RSORT}, - {"names", no_argument, &use_port_names, 1}, - {"no-names", no_argument, &use_port_names, 0}, + {"names", no_argument, &use_names, 1}, + {"no-names", no_argument, &use_names, 0}, {"stats", no_argument, &show_stats, 1}, {"no-stats", no_argument, &show_stats, 0}, {"unixctl", required_argument, NULL, OPT_UNIXCTL}, @@ -636,7 +639,9 @@ dump_transaction(struct vconn *vconn, struct ofpbuf *request) enum ofpraw raw; ofp_print(stdout, reply->data, reply->size, - ports_to_show(vconn_get_name(vconn)), verbosity + 1); + ports_to_show(vconn_get_name(vconn)), + tables_to_show(vconn_get_name(vconn)), + verbosity + 1); ofpraw_decode(&raw, reply->data); if (ofptype_from_ofpraw(raw) == OFPTYPE_ERROR) { @@ -648,6 +653,7 @@ dump_transaction(struct vconn *vconn, struct ofpbuf *request) ofp_to_string( reply->data, reply->size, ports_to_show(vconn_get_name(vconn)), + tables_to_show(vconn_get_name(vconn)), verbosity + 1)); } } else { @@ -662,7 +668,9 @@ dump_transaction(struct vconn *vconn, struct ofpbuf *request) run(vconn_transact(vconn, request, &reply), "talking to %s", vconn_get_name(vconn)); ofp_print(stdout, reply->data, reply->size, - ports_to_show(vconn_get_name(vconn)), verbosity + 1); + ports_to_show(vconn_get_name(vconn)), + tables_to_show(vconn_get_name(vconn)), + verbosity + 1); ofpbuf_delete(reply); } } @@ -693,7 +701,9 @@ transact_multiple_noreply(struct vconn *vconn, struct ovs_list *requests) "talking to %s", vconn_get_name(vconn)); if (reply) { ofp_print(stderr, reply->data, reply->size, - ports_to_show(vconn_get_name(vconn)), verbosity + 2); + ports_to_show(vconn_get_name(vconn)), + tables_to_show(vconn_get_name(vconn)), + verbosity + 2); exit(1); } ofpbuf_delete(reply); @@ -739,7 +749,7 @@ bundle_print_errors(struct ovs_list *errors, struct ovs_list *requests, } fprintf(stderr, "Error %s for: ", ofperr_get_name(ofperr)); ofp_print(stderr, ofp_msg, msg_len, ports_to_show(vconn_name), - verbosity + 1); + tables_to_show(vconn_name), verbosity + 1); } ofpbuf_uninit(&payload); ofpbuf_delete(error); @@ -819,7 +829,7 @@ ofctl_show(struct ovs_cmdl_context *ctx) run(vconn_transact(vconn, request, &reply), "talking to %s", vconn_name); has_ports = ofputil_switch_features_has_ports(reply); - ofp_print(stdout, reply->data, reply->size, NULL, verbosity + 1); + ofp_print(stdout, reply->data, reply->size, NULL, NULL, verbosity + 1); ofpbuf_delete(reply); if (!has_ports) { @@ -880,7 +890,7 @@ ofctl_dump_table_features(struct ovs_cmdl_context *ctx) if (error) { ovs_fatal(0, "decode error: %s", ofperr_get_name(error)); } else if (type == OFPTYPE_ERROR) { - ofp_print(stdout, reply->data, reply->size, NULL, + ofp_print(stdout, reply->data, reply->size, NULL, NULL, verbosity + 1); done = true; } else if (type == OFPTYPE_TABLE_FEATURES_STATS_REPLY) { @@ -900,7 +910,8 @@ ofctl_dump_table_features(struct ovs_cmdl_context *ctx) struct ds s = DS_EMPTY_INITIALIZER; ofp_print_table_features(&s, &tf, n ? &prev : NULL, - NULL, NULL); + NULL, NULL, + tables_to_show(ctx->argv[1])); puts(ds_cstr(&s)); ds_destroy(&s); @@ -911,6 +922,7 @@ ofctl_dump_table_features(struct ovs_cmdl_context *ctx) ovs_fatal(0, "received bad reply: %s", ofp_to_string(reply->data, reply->size, ports_to_show(ctx->argv[1]), + tables_to_show(ctx->argv[1]), verbosity + 1)); } } else { @@ -1040,7 +1052,7 @@ port_iterator_next(struct port_iterator *pi, struct ofputil_phy_port *pp) } else if (retval != EOF) { ovs_fatal(0, "received bad reply: %s", ofp_to_string(pi->reply->data, pi->reply->size, - NULL, verbosity + 1)); + NULL, NULL, verbosity + 1)); } } @@ -1062,7 +1074,7 @@ port_iterator_next(struct port_iterator *pi, struct ofputil_phy_port *pp) || type != OFPTYPE_PORT_DESC_STATS_REPLY) { ovs_fatal(0, "received bad reply: %s", ofp_to_string(pi->reply->data, pi->reply->size, NULL, - verbosity + 1)); + NULL, verbosity + 1)); } pi->more = (ofpmp_flags(oh) & OFPSF_REPLY_MORE) != 0; @@ -1159,33 +1171,189 @@ get_port_map(const char *vconn_name) static const struct ofputil_port_map * ports_to_accept(const char *vconn_name) { - return should_accept_ports() ? get_port_map(vconn_name) : NULL; + return should_accept_names() ? get_port_map(vconn_name) : NULL; } static const struct ofputil_port_map * ports_to_show(const char *vconn_name) { - return should_show_ports() ? get_port_map(vconn_name) : NULL; + return should_show_names() ? get_port_map(vconn_name) : NULL; +} + +struct table_iterator { + struct vconn *vconn; + + enum { TI_STATS, TI_FEATURES } variant; + struct ofpbuf *reply; + ovs_be32 send_xid; + bool more; + + struct ofputil_table_features features; +}; + +/* Initializes 'ti' to prepare for iterating through all of the tables on the + * OpenFlow switch to which 'vconn' is connected. + * + * During iteration, the client should not make other use of 'vconn', because + * that can cause other messages to be interleaved with the replies used by the + * iterator and thus some tables may be missed or a hang can occur. */ +static void +table_iterator_init(struct table_iterator *ti, struct vconn *vconn) +{ + memset(ti, 0, sizeof *ti); + ti->vconn = vconn; + ti->variant = (vconn_get_version(vconn) < OFP13_VERSION + ? TI_STATS : TI_FEATURES); + ti->more = true; + + enum ofpraw raw = (ti->variant == TI_STATS + ? OFPRAW_OFPST_TABLE_REQUEST + : OFPRAW_OFPST13_TABLE_FEATURES_REQUEST); + struct ofpbuf *rq = ofpraw_alloc(raw, vconn_get_version(vconn), 0); + ti->send_xid = ((struct ofp_header *) rq->data)->xid; + send_openflow_buffer(ti->vconn, rq); +} + +/* Obtains the next table from 'ti'. On success, returns the next table's + * features; on failure, returns NULL. */ +static const struct ofputil_table_features * +table_iterator_next(struct table_iterator *ti) +{ + for (;;) { + if (ti->reply) { + int retval; + if (ti->variant == TI_STATS) { + struct ofputil_table_stats ts; + retval = ofputil_decode_table_stats_reply(ti->reply, + &ts, &ti->features); + } else { + ovs_assert(ti->variant == TI_FEATURES); + retval = ofputil_decode_table_features(ti->reply, + &ti->features, + true); + } + if (!retval) { + return &ti->features; + } else if (retval != EOF) { + ovs_fatal(0, "received bad reply: %s", + ofp_to_string(ti->reply->data, ti->reply->size, + NULL, NULL, verbosity + 1)); + } + } + + if (!ti->more) { + return NULL; + } + + ovs_be32 recv_xid; + do { + ofpbuf_delete(ti->reply); + run(vconn_recv_block(ti->vconn, &ti->reply), + "OpenFlow receive failed"); + recv_xid = ((struct ofp_header *) ti->reply->data)->xid; + } while (ti->send_xid != recv_xid); + + struct ofp_header *oh = ti->reply->data; + enum ofptype type; + if (ofptype_pull(&type, ti->reply) + || type != (ti->variant == TI_STATS + ? OFPTYPE_TABLE_STATS_REPLY + : OFPTYPE_TABLE_FEATURES_STATS_REPLY)) { + ovs_fatal(0, "received bad reply: %s", + ofp_to_string(ti->reply->data, ti->reply->size, NULL, + NULL, verbosity + 1)); + } + + ti->more = (ofpmp_flags(oh) & OFPSF_REPLY_MORE) != 0; + } +} + +/* Destroys iterator 'ti'. */ +static void +table_iterator_destroy(struct table_iterator *ti) +{ + if (ti) { + while (ti->more) { + /* Drain vconn's queue of any other replies for this request. */ + table_iterator_next(ti); + } + + ofpbuf_delete(ti->reply); + } +} + +static const struct ofputil_table_map * +get_table_map(const char *vconn_name) +{ + static struct shash table_maps = SHASH_INITIALIZER(&table_maps); + struct ofputil_table_map *map = shash_find_data(&table_maps, vconn_name); + if (!map) { + map = xmalloc(sizeof *map); + ofputil_table_map_init(map); + shash_add(&table_maps, vconn_name, map); + + if (!strchr(vconn_name, ':') || !vconn_verify_name(vconn_name)) { + /* For an active vconn (which includes a vconn constructed from a + * bridge name), connect to it and pull down the port name-number + * mapping. */ + struct vconn *vconn; + open_vconn(vconn_name, &vconn); + + struct table_iterator ti; + table_iterator_init(&ti, vconn); + for (;;) { + const struct ofputil_table_features *tf + = table_iterator_next(&ti); + if (!tf) { + break; + } + if (tf->name[0]) { + ofputil_table_map_put(map, tf->table_id, tf->name); + } + } + table_iterator_destroy(&ti); + + vconn_close(vconn); + } else { + /* Don't bother with passive vconns, since it could take a long + * time for the remote to try to connect to us. Don't bother with + * invalid vconn names either. */ + } + } + return map; +} + +static const struct ofputil_table_map * +tables_to_accept(const char *vconn_name) +{ + return should_accept_names() ? get_table_map(vconn_name) : NULL; +} + +static const struct ofputil_table_map * +tables_to_show(const char *vconn_name) +{ + return should_show_names() ? get_table_map(vconn_name) : NULL; } -/* We accept port names unless the feature is turned off explicitly. */ +/* We accept port and table names unless the feature is turned off + * explicitly. */ static bool -should_accept_ports(void) +should_accept_names(void) { - return use_port_names != 0; + return use_names != 0; } -/* We show port names only if the feature is turned on explicitly, or if we're - * interacting with a user on the console. */ +/* We show port and table names only if the feature is turned on explicitly, or + * if we're interacting with a user on the console. */ static bool -should_show_ports(void) +should_show_names(void) { static int interactive = -1; if (interactive == -1) { interactive = isatty(STDOUT_FILENO); } - return use_port_names > 0 || (use_port_names == -1 && interactive); + return use_names > 0 || (use_names == -1 && interactive); } /* Returns the port number corresponding to 'port_name' (which may be a port @@ -1218,7 +1386,7 @@ try_set_protocol(struct vconn *vconn, enum ofputil_protocol want, run(vconn_transact_noreply(vconn, request, &reply), "talking to %s", vconn_get_name(vconn)); if (reply) { - char *s = ofp_to_string(reply->data, reply->size, NULL, 2); + char *s = ofp_to_string(reply->data, reply->size, NULL, NULL, 2); VLOG_DBG("%s: failed to set protocol, switch replied: %s", vconn_get_name(vconn), s); free(s); @@ -1270,8 +1438,11 @@ prepare_dump_flows(int argc, char *argv[], bool aggregate, const char *match = argc > 2 ? argv[2] : ""; const struct ofputil_port_map *port_map = *match ? ports_to_accept(vconn_name) : NULL; + const struct ofputil_table_map *table_map + = *match ? tables_to_accept(vconn_name) : NULL; error = parse_ofp_flow_stats_request_str(fsr, aggregate, match, - port_map, &usable_protocols); + port_map, table_map, + &usable_protocols); if (error) { ovs_fatal(0, "%s", error); } @@ -1362,7 +1533,7 @@ compare_flows(const void *afs_, const void *bfs_) static void ofctl_dump_flows(struct ovs_cmdl_context *ctx) { - if (!n_criteria && !should_show_ports() && show_stats) { + if (!n_criteria && !should_show_names() && show_stats) { ofctl_dump_flows__(ctx->argc, ctx->argv, false); return; } else { @@ -1384,7 +1555,7 @@ ofctl_dump_flows(struct ovs_cmdl_context *ctx) for (size_t i = 0; i < n_fses; i++) { ds_clear(&s); ofp_print_flow_stats(&s, &fses[i], ports_to_show(ctx->argv[1]), - show_stats); + tables_to_show(ctx->argv[1]), show_stats); printf(" %s\n", ds_cstr(&s)); } ds_destroy(&s); @@ -1575,7 +1746,8 @@ ofctl_flow_mod_file(int argc OVS_UNUSED, char *argv[], int command) * this is backwards compatible. */ command = -2; } - error = parse_ofp_flow_mod_file(argv[2], ports_to_accept(argv[1]), command, + error = parse_ofp_flow_mod_file(argv[2], ports_to_accept(argv[1]), + tables_to_accept(argv[1]), command, &fms, &n_fms, &usable_protocols); if (error) { ovs_fatal(0, "%s", error); @@ -1595,7 +1767,8 @@ ofctl_flow_mod(int argc, char *argv[], uint16_t command) enum ofputil_protocol usable_protocols; error = parse_ofp_flow_mod_str(&fm, argc > 2 ? argv[2] : "", - ports_to_accept(argv[1]), command, + ports_to_accept(argv[1]), + tables_to_accept(argv[1]), command, &usable_protocols); if (error) { ovs_fatal(0, "%s", error); @@ -1645,7 +1818,7 @@ set_packet_in_format(struct vconn *vconn, run(vconn_transact_noreply(vconn, spif, &reply), "talking to %s", vconn_get_name(vconn)); if (reply) { - char *s = ofp_to_string(reply->data, reply->size, NULL, 2); + char *s = ofp_to_string(reply->data, reply->size, NULL, NULL, 2); VLOG_DBG("%s: failed to set packet in format to nx_packet_in, " "controller replied: %s.", vconn_get_name(vconn), s); @@ -1741,7 +1914,8 @@ ofctl_send(struct unixctl_conn *conn, int argc, fprintf(stderr, "send: "); ofp_print(stderr, msg->data, msg->size, - ports_to_show(vconn_get_name(vconn)), verbosity); + ports_to_show(vconn_get_name(vconn)), + tables_to_show(vconn_get_name(vconn)), verbosity); error = vconn_send_block(vconn, msg); if (error) { @@ -1777,7 +1951,7 @@ unixctl_packet_out(struct unixctl_conn *conn, int OVS_UNUSED argc, error_msg = parse_ofp_packet_out_str( &po, argv[1], ports_to_accept(vconn_get_name(vconn)), - &usable_protocols); + tables_to_accept(vconn_get_name(vconn)), &usable_protocols); if (error_msg) { ds_put_format(&reply, "%s\n", error_msg); free(error_msg); @@ -1793,7 +1967,8 @@ unixctl_packet_out(struct unixctl_conn *conn, int OVS_UNUSED argc, struct ofpbuf *msg = ofputil_encode_packet_out(&po, protocol); ofp_print(stderr, msg->data, msg->size, - ports_to_show(vconn_get_name(vconn)), verbosity); + ports_to_show(vconn_get_name(vconn)), + tables_to_show(vconn_get_name(vconn)), verbosity); int error = vconn_send_block(vconn, msg); if (error) { @@ -1957,7 +2132,8 @@ monitor_vconn(struct vconn *vconn, bool reply_to_echo_requests, ofptype_decode(&type, b->data); ofp_print(stderr, b->data, b->size, - ports_to_show(vconn_get_name(vconn)), verbosity + 2); + ports_to_show(vconn_get_name(vconn)), + tables_to_show(vconn_get_name(vconn)), verbosity + 2); fflush(stderr); switch ((int) type) { @@ -2000,6 +2176,7 @@ monitor_vconn(struct vconn *vconn, bool reply_to_echo_requests, fprintf(stderr, "send: "); ofp_print(stderr, reply->data, reply->size, ports_to_show(vconn_get_name(vconn)), + tables_to_show(vconn_get_name(vconn)), verbosity + 2); fflush(stderr); @@ -2079,6 +2256,7 @@ ofctl_monitor(struct ovs_cmdl_context *ctx) error = parse_flow_monitor_request(&fmr, arg + 6, ports_to_accept(ctx->argv[1]), + tables_to_accept(ctx->argv[1]), &usable_protocols); if (error) { ovs_fatal(0, "%s", error); @@ -2196,6 +2374,7 @@ ofctl_packet_out(struct ovs_cmdl_context *ctx) ofpbuf_init(&ofpacts, 64); struct ofpact_parse_params pp = { .port_map = ports_to_accept(ctx->argv[1]), + .table_map = tables_to_accept(ctx->argv[1]), .ofpacts = &ofpacts, .usable_protocols = &usable_protocols }; @@ -2233,6 +2412,7 @@ ofctl_packet_out(struct ovs_cmdl_context *ctx) } else if (ctx->argc == 3) { error = parse_ofp_packet_out_str(&po, ctx->argv[2], ports_to_accept(ctx->argv[1]), + tables_to_accept(ctx->argv[1]), &usable_protocols); if (error) { ovs_fatal(0, "%s", error); @@ -2339,7 +2519,7 @@ fetch_table_desc(struct vconn *vconn, struct ofputil_table_mod *tm, if (ofptype_pull(&type, &b) || type != OFPTYPE_TABLE_DESC_REPLY) { ovs_fatal(0, "received bad reply: %s", - ofp_to_string(reply->data, reply->size, NULL, + ofp_to_string(reply->data, reply->size, NULL, NULL, verbosity + 1)); } uint16_t flags = ofpmp_flags(oh); @@ -2382,6 +2562,7 @@ ofctl_mod_table(struct ovs_cmdl_context *ctx) int i; error = parse_ofp_table_mod(&tm, ctx->argv[2], ctx->argv[3], + tables_to_accept(ctx->argv[1]), &usable_versions); if (error) { ovs_fatal(0, "%s", error); @@ -2507,7 +2688,7 @@ ofctl_ofp_parse(struct ovs_cmdl_context *ctx) ovs_fatal(0, "%s: unexpected end of file mid-message", filename); } - ofp_print(stdout, b.data, b.size, NULL, verbosity + 2); + ofp_print(stdout, b.data, b.size, NULL, NULL, verbosity + 2); } ofpbuf_uninit(&b); @@ -2595,7 +2776,7 @@ ofctl_ofp_parse_pcap(struct ovs_cmdl_context *ctx) IP_ARGS(flow.nw_src), ntohs(flow.tp_src), IP_ARGS(flow.nw_dst), ntohs(flow.tp_dst)); ofp_print(stdout, dp_packet_data(payload), length, - NULL, verbosity + 1); + NULL, NULL, verbosity + 1); dp_packet_pull(payload, length); } } @@ -2640,9 +2821,10 @@ ofctl_ping(struct ovs_cmdl_context *ctx) || reply->size != payload || memcmp(request->msg, reply->msg, payload)) { printf("Reply does not match request. Request:\n"); - ofp_print(stdout, request, request->size, NULL, verbosity + 2); + ofp_print(stdout, request, request->size, NULL, NULL, + verbosity + 2); printf("Reply:\n"); - ofp_print(stdout, reply, reply->size, NULL, verbosity + 2); + ofp_print(stdout, reply, reply->size, NULL, NULL, verbosity + 2); } printf("%"PRIu32" bytes from %s: xid=%08"PRIx32" time=%.1f ms\n", reply->size, ctx->argv[1], ntohl(rpy_hdr->xid), @@ -2805,6 +2987,7 @@ ofctl_group_mod_file(int argc OVS_UNUSED, char *argv[], int command) command = -2; } error = parse_ofp_group_mod_file(argv[2], ports_to_accept(argv[1]), + tables_to_accept(argv[1]), command, &gms, &n_gms, &usable_protocols); if (error) { ovs_fatal(0, "%s", error); @@ -2825,6 +3008,7 @@ ofctl_group_mod(int argc, char *argv[], uint16_t command) error = parse_ofp_group_mod_str(&gm, command, argc > 2 ? argv[2] : "", ports_to_accept(argv[1]), + tables_to_accept(argv[1]), &usable_protocols); if (error) { ovs_fatal(0, "%s", error); @@ -2885,6 +3069,7 @@ ofctl_dump_group_stats(struct ovs_cmdl_context *ctx) error = parse_ofp_group_mod_str(&gm, OFPGC11_DELETE, ctx->argc > 2 ? ctx->argv[2] : "", ports_to_accept(ctx->argv[1]), + tables_to_accept(ctx->argv[1]), &usable_protocols); if (error) { ovs_fatal(0, "%s", error); @@ -2950,6 +3135,7 @@ ofctl_bundle(struct ovs_cmdl_context *ctx) char *error; error = parse_ofp_bundle_file(ctx->argv[2], ports_to_accept(ctx->argv[1]), + tables_to_accept(ctx->argv[1]), &bms, &n_bms, &usable_protocols); if (error) { ovs_fatal(0, "%s", error); @@ -3122,9 +3308,11 @@ struct fte_state { /* The final metadata table that we have constructed. */ struct tun_table *tun_tab; - /* Port map. There is only one port map, not one per source, because it - * only makes sense to display a single name for a given port number. */ + /* Port and table map. There is only one of each, not one per source, + * because it only makes sense to display a single name for a given port + * or table number. */ const struct ofputil_port_map *port_map; + const struct ofputil_table_map *table_map; }; /* Frees 'version' and the data that it owns. */ @@ -3358,6 +3546,7 @@ fte_state_init(struct fte_state *state) ovs_list_init(&state->fte_pending_list); state->tun_tab = NULL; state->port_map = NULL; + state->table_map = NULL; } static void @@ -3443,7 +3632,7 @@ read_flows_from_file(const char *filename, struct fte_state *state, int index) enum ofputil_protocol usable; error = parse_ofp_str(&fm, OFPFC_ADD, ds_cstr(&s), state->port_map, - &usable); + state->table_map, &usable); if (error) { ovs_fatal(0, "%s:%d: %s", filename, line_number, error); } @@ -3564,6 +3753,7 @@ ofctl_replace_flows(struct ovs_cmdl_context *ctx) fte_state_init(&fte_state); fte_state.port_map = ports_to_accept(ctx->argv[1]); + fte_state.table_map = tables_to_accept(ctx->argv[1]); usable_protocols = read_flows_from_file(ctx->argv[2], &fte_state, FILE_IDX); protocol = open_vconn(ctx->argv[1], &vconn); @@ -3815,7 +4005,7 @@ ofctl_parse_flows__(struct ofputil_flow_mod *fms, size_t n_fms, struct ofpbuf *msg; msg = ofputil_encode_flow_mod(fm, protocol); - ofp_print(stdout, msg->data, msg->size, NULL, verbosity); + ofp_print(stdout, msg->data, msg->size, NULL, NULL, verbosity); ofpbuf_delete(msg); free(CONST_CAST(struct ofpact *, fm->ofpacts)); @@ -3831,7 +4021,7 @@ ofctl_parse_flow(struct ovs_cmdl_context *ctx) struct ofputil_flow_mod fm; char *error; - error = parse_ofp_flow_mod_str(&fm, ctx->argv[1], NULL, + error = parse_ofp_flow_mod_str(&fm, ctx->argv[1], NULL, NULL, OFPFC_ADD, &usable_protocols); if (error) { ovs_fatal(0, "%s", error); @@ -3849,7 +4039,7 @@ ofctl_parse_flows(struct ovs_cmdl_context *ctx) size_t n_fms = 0; char *error; - error = parse_ofp_flow_mod_file(ctx->argv[1], NULL, OFPFC_ADD, + error = parse_ofp_flow_mod_file(ctx->argv[1], NULL, NULL, OFPFC_ADD, &fms, &n_fms, &usable_protocols); if (error) { ovs_fatal(0, "%s", error); @@ -4291,7 +4481,7 @@ ofctl_check_vlan(struct ovs_cmdl_context *ctx) string_s = match_to_string(&match, NULL, OFP_DEFAULT_PRIORITY); printf("%s -> ", string_s); fflush(stdout); - error_s = parse_ofp_str(&fm, -1, string_s, NULL, &usable_protocols); + error_s = parse_ofp_str(&fm, -1, string_s, NULL, NULL, &usable_protocols); if (error_s) { ovs_fatal(0, "%s", error_s); } @@ -4460,7 +4650,7 @@ ofctl_ofp_print(struct ovs_cmdl_context *ctx) if (ofpbuf_put_hex(&packet, buffer, NULL)[0] != '\0') { ovs_fatal(0, "trailing garbage following hex bytes"); } - ofp_print(stdout, packet.data, packet.size, NULL, verbosity); + ofp_print(stdout, packet.data, packet.size, NULL, NULL, verbosity); ofpbuf_uninit(&packet); ds_destroy(&line); } @@ -4475,7 +4665,7 @@ ofctl_encode_hello(struct ovs_cmdl_context *ctx) hello = ofputil_encode_hello(bitmap); ovs_hex_dump(stdout, hello->data, hello->size, 0, false); - ofp_print(stdout, hello->data, hello->size, NULL, verbosity); + ofp_print(stdout, hello->data, hello->size, NULL, NULL, verbosity); ofpbuf_delete(hello); } diff --git a/utilities/ovs-testcontroller.c b/utilities/ovs-testcontroller.c index 8f8fc2bb13a1..571af0c7f971 100644 --- a/utilities/ovs-testcontroller.c +++ b/utilities/ovs-testcontroller.c @@ -335,7 +335,7 @@ parse_options(int argc, char *argv[]) break; case OPT_WITH_FLOWS: - error = parse_ofp_flow_mod_file(optarg, NULL, OFPFC_ADD, + error = parse_ofp_flow_mod_file(optarg, NULL, NULL, OFPFC_ADD, &default_flows, &n_default_flows, &usable_protocols); if (error) {