From patchwork Tue Sep 1 02:57:04 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jesse Gross X-Patchwork-Id: 512675 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from archives.nicira.com (unknown [IPv6:2600:3c00::f03c:91ff:fe6e:bdf7]) by ozlabs.org (Postfix) with ESMTP id F311E1401DA for ; Tue, 1 Sep 2015 12:57:20 +1000 (AEST) Received: from archives.nicira.com (localhost [127.0.0.1]) by archives.nicira.com (Postfix) with ESMTP id D6DDA1061B; Mon, 31 Aug 2015 19:57:18 -0700 (PDT) X-Original-To: dev@openvswitch.org Delivered-To: dev@openvswitch.org Received: from mx1e3.cudamail.com (mx1.cudamail.com [69.90.118.67]) by archives.nicira.com (Postfix) with ESMTPS id 6C46B10615 for ; Mon, 31 Aug 2015 19:57:16 -0700 (PDT) Received: from bar2.cudamail.com (localhost [127.0.0.1]) by mx1e3.cudamail.com (Postfix) with ESMTPS id B57CE42045E for ; Mon, 31 Aug 2015 20:57:14 -0600 (MDT) X-ASG-Debug-ID: 1441076233-03dc5333cc08040001-byXFYA Received: from mx1-pf1.cudamail.com ([192.168.24.1]) by bar2.cudamail.com with ESMTP id BlhcIYGGDqcRswdn (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Mon, 31 Aug 2015 20:57:14 -0600 (MDT) X-Barracuda-Envelope-From: jesse@nicira.com X-Barracuda-RBL-Trusted-Forwarder: 192.168.24.1 Received: from unknown (HELO mail-pa0-f46.google.com) (209.85.220.46) by mx1-pf1.cudamail.com with ESMTPS (RC4-SHA encrypted); 1 Sep 2015 02:57:13 -0000 Received-SPF: unknown (mx1-pf1.cudamail.com: Multiple SPF records returned) X-Barracuda-Apparent-Source-IP: 209.85.220.46 X-Barracuda-RBL-IP: 209.85.220.46 Received: by pabzx8 with SMTP id zx8so159681870pab.1 for ; Mon, 31 Aug 2015 19:57:12 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:subject:date:message-id; bh=1vUD6wI4BweQP5tD/rFvpIGR74hBeSO2eGtcOVsrKdc=; b=NXNdjVwGmc+r3i73ijtIratTV3oKwJ/bZ5IR+qW8iy/DguRhvGBg+Ji/tDexfgtWyd 32oOmmsa1Q/F9oYl8VePk/G5GM6sDKm2RatoOKOqTWi51i1361M/QkNQgwHTyjIzXEI+ /SCowhSq5bNe07OuIxWGYWTmKBb3iQ0Pzng268vOtdV8KMrvObIJNBZal/2dgsAss9x/ e14EXOKpxEps3s/UBR5MCHpEkmBqCvR/I7Y45QWYUnxs6Ch/Ugew3qLdFNwFtICK5bcJ dIm5ai2NlpLihkuS846Ivae/c6pfB8iMprSgF27fzvFVc82GPJstG3ymM42E3Id4XxPd 0y9w== X-Gm-Message-State: ALoCoQk0zRls2FTHhfg9x89XFyWGqG+7PYzUytVFgEZwpshhCy4QJfODhwHLr4SqMUQxCb9kA/p4 X-Received: by 10.68.234.167 with SMTP id uf7mr42378896pbc.51.1441076231961; Mon, 31 Aug 2015 19:57:11 -0700 (PDT) Received: from ubuntu.localdomain (c-71-202-123-143.hsd1.ca.comcast.net. [71.202.123.143]) by smtp.gmail.com with ESMTPSA id fu4sm16085715pbb.59.2015.08.31.19.57.10 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 31 Aug 2015 19:57:10 -0700 (PDT) X-CudaMail-Envelope-Sender: jesse@nicira.com From: Jesse Gross To: dev@openvswitch.org X-CudaMail-Whitelist-To: dev@openvswitch.org X-CudaMail-MID: CM-E1-830101063 X-CudaMail-DTE: 083115 X-CudaMail-Originating-IP: 209.85.220.46 Date: Mon, 31 Aug 2015 19:57:04 -0700 X-ASG-Orig-Subj: [##CM-E1-830101063##][PATCH 1/3] ofp-parse: Separate fields properly. Message-Id: <1441076226-60939-1-git-send-email-jesse@nicira.com> X-Mailer: git-send-email 2.1.4 X-Barracuda-Connect: UNKNOWN[192.168.24.1] X-Barracuda-Start-Time: 1441076234 X-Barracuda-Encrypted: DHE-RSA-AES256-SHA X-Barracuda-URL: https://web.cudamail.com:443/cgi-mod/mark.cgi X-ASG-Whitelist: Header =?UTF-8?B?eFwtY3VkYW1haWxcLXdoaXRlbGlzdFwtdG8=?= X-Virus-Scanned: by bsmtpd at cudamail.com X-Barracuda-BRTS-Status: 1 Subject: [ovs-dev] [PATCH 1/3] ofp-parse: Separate fields properly. X-BeenThere: dev@openvswitch.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dev-bounces@openvswitch.org Sender: "dev" Currently, each token in an OpenFlow match field is treated separately - whether this is a name, a value, or a single identifier. However, this means that attempting to get a value may result in grabbing the next token if no value exists. This avoids that problem by breaking the match string down into its components and then individually separating it into name/value pairs if appropriate. Signed-off-by: Jesse Gross Acked-by: Ben Pfaff --- lib/ofp-parse.c | 165 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 81 insertions(+), 84 deletions(-) diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c index eaaa8ba..a6190ed 100644 --- a/lib/ofp-parse.c +++ b/lib/ofp-parse.c @@ -256,7 +256,7 @@ parse_ofp_str__(struct ofputil_flow_mod *fm, int command, char *string, } fields; char *save_ptr = NULL; char *act_str = NULL; - char *name; + char *field; *usable_protocols = OFPUTIL_P_ANY; @@ -339,116 +339,113 @@ parse_ofp_str__(struct ofputil_flow_mod *fm, int command, char *string, return xstrdup("must specify an action"); } } - for (name = strtok_r(string, "=, \t\r\n", &save_ptr); name; - name = strtok_r(NULL, "=, \t\r\n", &save_ptr)) { + for (field = strtok_r(string, ", \t\r\n", &save_ptr); field; + field = strtok_r(NULL, ", \t\r\n", &save_ptr)) { const struct protocol *p; char *error = NULL; - if (parse_protocol(name, &p)) { + if (parse_protocol(field, &p)) { match_set_dl_type(&fm->match, htons(p->dl_type)); if (p->nw_proto) { match_set_nw_proto(&fm->match, p->nw_proto); } - } else if (fields & F_FLAGS && !strcmp(name, "send_flow_rem")) { + } else if (fields & F_FLAGS && !strcmp(field, "send_flow_rem")) { fm->flags |= OFPUTIL_FF_SEND_FLOW_REM; - } else if (fields & F_FLAGS && !strcmp(name, "check_overlap")) { + } else if (fields & F_FLAGS && !strcmp(field, "check_overlap")) { fm->flags |= OFPUTIL_FF_CHECK_OVERLAP; - } else if (fields & F_FLAGS && !strcmp(name, "reset_counts")) { + } else if (fields & F_FLAGS && !strcmp(field, "reset_counts")) { fm->flags |= OFPUTIL_FF_RESET_COUNTS; *usable_protocols &= OFPUTIL_P_OF12_UP; - } else if (fields & F_FLAGS && !strcmp(name, "no_packet_counts")) { + } else if (fields & F_FLAGS && !strcmp(field, "no_packet_counts")) { fm->flags |= OFPUTIL_FF_NO_PKT_COUNTS; *usable_protocols &= OFPUTIL_P_OF13_UP; - } else if (fields & F_FLAGS && !strcmp(name, "no_byte_counts")) { + } else if (fields & F_FLAGS && !strcmp(field, "no_byte_counts")) { fm->flags |= OFPUTIL_FF_NO_BYT_COUNTS; *usable_protocols &= OFPUTIL_P_OF13_UP; - } else if (!strcmp(name, "no_readonly_table") - || !strcmp(name, "allow_hidden_fields")) { + } else if (!strcmp(field, "no_readonly_table") + || !strcmp(field, "allow_hidden_fields")) { /* ignore these fields. */ - } else if (mf_from_name(name)) { - char *value; - - value = strtok_r(NULL, ", \t\r\n", &save_ptr); - if (!value) { - /* If there's no value, we're just trying to match on the - * existence of the field, so use a no-op value. */ - value = "0/0"; - } - - error = parse_field(mf_from_name(name), value, &fm->match, - usable_protocols); - if (error) { - return error; - } } else { - char *value; + char *name, *value; - value = strtok_r(NULL, ", \t\r\n", &save_ptr); - if (!value) { - return xasprintf("field %s missing value", name); - } + name = strsep(&field, "="); + value = field; - if (!strcmp(name, "table")) { - error = str_to_u8(value, "table", &fm->table_id); - if (fm->table_id != 0xff) { - *usable_protocols &= OFPUTIL_P_TID; + if (mf_from_name(name)) { + if (!value) { + /* If there's no value, we're just trying to match on the + * existence of the field, so use a no-op value. */ + value = "0/0"; } - } else if (fields & F_OUT_PORT && !strcmp(name, "out_port")) { - if (!ofputil_port_from_string(value, &fm->out_port)) { - error = xasprintf("%s is not a valid OpenFlow port", - value); + error = parse_field(mf_from_name(name), value, &fm->match, + usable_protocols); + } else { + if (!value) { + return xasprintf("field %s missing value", name); } - } else if (fields & F_PRIORITY && !strcmp(name, "priority")) { - uint16_t priority = 0; - - error = str_to_u16(value, name, &priority); - fm->priority = priority; - } else if (fields & F_TIMEOUT && !strcmp(name, "idle_timeout")) { - error = str_to_u16(value, name, &fm->idle_timeout); - } else if (fields & F_TIMEOUT && !strcmp(name, "hard_timeout")) { - error = str_to_u16(value, name, &fm->hard_timeout); - } else if (fields & F_IMPORTANCE && !strcmp(name, "importance")) { - error = str_to_u16(value, name, &fm->importance); - } else if (!strcmp(name, "cookie")) { - char *mask = strchr(value, '/'); - if (mask) { - /* A mask means we're searching for a cookie. */ - if (command == OFPFC_ADD) { - return xstrdup("flow additions cannot use " - "a cookie mask"); + if (!strcmp(name, "table")) { + error = str_to_u8(value, "table", &fm->table_id); + if (fm->table_id != 0xff) { + *usable_protocols &= OFPUTIL_P_TID; } - *mask = '\0'; - error = str_to_be64(value, &fm->cookie); - if (error) { - return error; + } else if (fields & F_OUT_PORT && !strcmp(name, "out_port")) { + if (!ofputil_port_from_string(value, &fm->out_port)) { + error = xasprintf("%s is not a valid OpenFlow port", + value); } - error = str_to_be64(mask + 1, &fm->cookie_mask); - - /* Matching of the cookie is only supported through NXM or - * OF1.1+. */ - if (fm->cookie_mask != htonll(0)) { - *usable_protocols &= OFPUTIL_P_NXM_OF11_UP; + } else if (fields & F_PRIORITY && !strcmp(name, "priority")) { + uint16_t priority = 0; + + error = str_to_u16(value, name, &priority); + fm->priority = priority; + } else if (fields & F_TIMEOUT && !strcmp(name, "idle_timeout")) { + error = str_to_u16(value, name, &fm->idle_timeout); + } else if (fields & F_TIMEOUT && !strcmp(name, "hard_timeout")) { + error = str_to_u16(value, name, &fm->hard_timeout); + } else if (fields & F_IMPORTANCE && !strcmp(name, "importance")) { + error = str_to_u16(value, name, &fm->importance); + } else if (!strcmp(name, "cookie")) { + char *mask = strchr(value, '/'); + + if (mask) { + /* A mask means we're searching for a cookie. */ + if (command == OFPFC_ADD) { + return xstrdup("flow additions cannot use " + "a cookie mask"); + } + *mask = '\0'; + error = str_to_be64(value, &fm->cookie); + if (error) { + return error; + } + error = str_to_be64(mask + 1, &fm->cookie_mask); + + /* Matching of the cookie is only supported through + * NXM or OF1.1+. */ + if (fm->cookie_mask != htonll(0)) { + *usable_protocols &= OFPUTIL_P_NXM_OF11_UP; + } + } else { + /* No mask means that the cookie is being set. */ + if (command != OFPFC_ADD && command != OFPFC_MODIFY + && command != OFPFC_MODIFY_STRICT) { + return xstrdup("cannot set cookie"); + } + error = str_to_be64(value, &fm->new_cookie); + fm->modify_cookie = true; } + } else if (!strcmp(name, "duration") + || !strcmp(name, "n_packets") + || !strcmp(name, "n_bytes") + || !strcmp(name, "idle_age") + || !strcmp(name, "hard_age")) { + /* Ignore these, so that users can feed the output of + * "ovs-ofctl dump-flows" back into commands that parse + * flows. */ } else { - /* No mask means that the cookie is being set. */ - if (command != OFPFC_ADD && command != OFPFC_MODIFY - && command != OFPFC_MODIFY_STRICT) { - return xstrdup("cannot set cookie"); - } - error = str_to_be64(value, &fm->new_cookie); - fm->modify_cookie = true; + error = xasprintf("unknown keyword %s", name); } - } else if (!strcmp(name, "duration") - || !strcmp(name, "n_packets") - || !strcmp(name, "n_bytes") - || !strcmp(name, "idle_age") - || !strcmp(name, "hard_age")) { - /* Ignore these, so that users can feed the output of - * "ovs-ofctl dump-flows" back into commands that parse - * flows. */ - } else { - error = xasprintf("unknown keyword %s", name); } if (error) {