From patchwork Wed Jan 27 11:44:33 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: niti1489@gmail.com X-Patchwork-Id: 573939 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from archives.nicira.com (li376-54.members.linode.com [96.126.127.54]) by ozlabs.org (Postfix) with ESMTP id 3DD471400A0 for ; Wed, 27 Jan 2016 22:45:04 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b=P59H+Y5M; dkim-atps=neutral Received: from archives.nicira.com (localhost [127.0.0.1]) by archives.nicira.com (Postfix) with ESMTP id DF6131061F; Wed, 27 Jan 2016 03:45:03 -0800 (PST) X-Original-To: dev@openvswitch.org Delivered-To: dev@openvswitch.org Received: from mx3v3.cudamail.com (mx3.cudamail.com [64.34.241.5]) by archives.nicira.com (Postfix) with ESMTPS id 770121061D for ; Wed, 27 Jan 2016 03:45:02 -0800 (PST) Received: from bar3.cudamail.com (localhost [127.0.0.1]) by mx3v3.cudamail.com (Postfix) with ESMTPS id 81715162391 for ; Wed, 27 Jan 2016 04:45:01 -0700 (MST) X-ASG-Debug-ID: 1453895098-03dd7b0cbf93eb50001-byXFYA Received: from mx3-pf3.cudamail.com ([192.168.14.3]) by bar3.cudamail.com with ESMTP id K3E7P6UgnlFWwR6H (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Wed, 27 Jan 2016 04:44:58 -0700 (MST) X-Barracuda-Envelope-From: niti1489@gmail.com X-Barracuda-RBL-Trusted-Forwarder: 192.168.14.3 Received: from unknown (HELO mail-pf0-f195.google.com) (209.85.192.195) by mx3-pf3.cudamail.com with ESMTPS (RC4-SHA encrypted); 27 Jan 2016 12:17:37 -0000 Received-SPF: pass (mx3-pf3.cudamail.com: SPF record at _netblocks.google.com designates 209.85.192.195 as permitted sender) X-Barracuda-Apparent-Source-IP: 209.85.192.195 X-Barracuda-RBL-IP: 209.85.192.195 Received: by mail-pf0-f195.google.com with SMTP id 65so331151pfd.1 for ; Wed, 27 Jan 2016 03:44:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=jeIirez3JqwAeVo2rNNnHwGCIJK0O20bCosU6NTdraA=; b=P59H+Y5M0U401M1e1K/gOeWspmiVD+dau9370sxjzfWCT6jNI4lhbyLVn6OQf79IG4 iBv4rvyh15UGzeYdCSuwsJMItg2unfhj1DoHEWwlTRDLfAKp6JaWPIWejnx8YKkNAFas Cspkzg7/bX1CCAsQGsF9dS9jQr12F4izq10AoOvUN/1rXC7W/8VPk+Nv5JF9jd43rxoA 1oDcgUhHxZIgbQSBIwzVzCavBlt5PzQ7CxCHgcGlO2EiCRvCXvKEjMocnSMdGxq/cO8N Oau+6P6u3yR9DlXKxp3OyAr1lz+ujsPpAtJDJsvC/Hlfu9dIN3g5NZzK3D5nra6nqlHw hfAw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=jeIirez3JqwAeVo2rNNnHwGCIJK0O20bCosU6NTdraA=; b=aO5kxe9cM/Y50DxDW7DvgRegXr9spgzhZtXtRFeCLuliR60yoVly6DsDAAQval9KBo y7eaVQqqzYfxE8IhZqPGvpMMmOPPCc+dXL5OYbcG7QQJaPpZDetzEeuUrmMM8rqeRaBl Z9K6Ky1FqC2O7sWLwd4YRGoLgCBJ1f3IpYAMP8KJ6XxENocNzUjGdgOHXQshdLWyxKeA in2BFh9ixdq67ITZbRuc+a7winKmmB3xK6BQEHXKChqYshSSHNpkFn5qPd2TC3AoAzGa cOBlhG2AHk1uGdcYInL04t3z9NLpNMX+68QPB8Etg82k5CsYLQzyC6Bp5F+WPiiL3Um6 kIWg== X-Gm-Message-State: AG10YOQsID+sy1f2cH00T0tbFLq7ek4jvpSJ5KobsUV04JgYkHMI2am1qhN5sQChUtvYFg== X-Received: by 10.98.64.195 with SMTP id f64mr13550248pfd.103.1453895091016; Wed, 27 Jan 2016 03:44:51 -0800 (PST) Received: from localhost.localdomain ([14.98.63.219]) by smtp.gmail.com with ESMTPSA id lq10sm8517982pab.36.2016.01.27.03.44.44 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 27 Jan 2016 03:44:49 -0800 (PST) X-CudaMail-Envelope-Sender: niti1489@gmail.com From: niti1489@gmail.com X-Google-Original-From: niti.rohilla@tcs.com To: dev@openvswitch.org X-CudaMail-MID: CM-V3-126004949 X-CudaMail-DTE: 012716 X-CudaMail-Originating-IP: 209.85.192.195 Date: Wed, 27 Jan 2016 17:14:33 +0530 X-ASG-Orig-Subj: [##CM-V3-126004949##][PATCH 1/2 v2] ofctl: This patch add support for setting the first egress table for egress processing. Message-Id: <1453895073-29161-1-git-send-email-niti.rohilla@tcs.com> X-Mailer: git-send-email 2.5.0 X-GBUdb-Analysis: 0, 209.85.192.195, Ugly c=0.291963 p=-0.176471 Source Normal X-MessageSniffer-Rules: 0-0-0-32767-c X-Barracuda-Connect: UNKNOWN[192.168.14.3] X-Barracuda-Start-Time: 1453895098 X-Barracuda-Encrypted: DHE-RSA-AES256-SHA X-Barracuda-URL: https://web.cudamail.com:443/cgi-mod/mark.cgi X-Barracuda-BRTS-Status: 1 X-Virus-Scanned: by bsmtpd at cudamail.com X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=3.5 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=4.0 tests=BSF_SC5_MJ1963, DKIM_SIGNED, NO_REAL_NAME, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.26496 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 NO_REAL_NAME From: does not include a real name 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Cc: deepankar.gupta@tcs.com, partha.datta@tcs.com Subject: [ovs-dev] [PATCH 1/2 v2] ofctl: This patch add support for setting the first egress table for egress processing. 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" From: Niti Rohilla "ovs-ofctl set-first-egress-table " can be used to set first egress table. This patch enhances TABLE_FEATURES_REQUEST message to set the first egress table and TABLE_FEATURES_REPLY to identify the table which is configured as first egress table. Signed-off-by: Niti Rohilla --- Difference between v1->v2 - Removed the implementation added for OF1.5 and incorporated the egress table code in OF1.3 implementation. - Replaced the hard coded values for OFPAT_ with OFPACT_OUTPUT and OFPACT_GROUP. - Removed the global variable in utility library and added a function to set/get the egress table id. - Rebased with latest master include/openflow/openflow-1.3.h | 3 +- include/openflow/openflow-1.5.h | 7 ++ lib/ofp-actions.c | 23 ++++ lib/ofp-actions.h | 4 +- lib/ofp-msgs.h | 2 +- lib/ofp-parse.c | 25 +++++ lib/ofp-parse.h | 6 ++ lib/ofp-print.c | 6 ++ lib/ofp-util.c | 74 +++++++++++-- lib/ofp-util.h | 15 ++- ofproto/ofproto-provider.h | 5 + ofproto/ofproto.c | 55 ++++++++-- tests/ofp-print.at | 222 ++++++++++++++++++++++++++++++++++++++ tests/ofproto.at | 230 ++++++++++++++++++++++++++++++++++++++++ utilities/ovs-ofctl.c | 36 ++++++- 15 files changed, 690 insertions(+), 23 deletions(-) diff --git a/include/openflow/openflow-1.3.h b/include/openflow/openflow-1.3.h index a521995..aa15d56 100644 --- a/include/openflow/openflow-1.3.h +++ b/include/openflow/openflow-1.3.h @@ -221,7 +221,8 @@ struct ofp13_table_features { ovs_be16 length; /* Length is padded to 64 bits. */ uint8_t table_id; /* Identifier of table. Lower numbered tables are consulted first. */ - uint8_t pad[5]; /* Align to 64-bits. */ + uint8_t command; /* One of OFPTFC_* (OF1.5+). */ + ovs_be32 features; /* Bitmap of OFPTFF_* values (OF1.5+). */ char name[OFP_MAX_TABLE_NAME_LEN]; ovs_be64 metadata_match; /* Bits of metadata table can match. */ ovs_be64 metadata_write; /* Bits of metadata table can write. */ diff --git a/include/openflow/openflow-1.5.h b/include/openflow/openflow-1.5.h index 0c478d1..3c51361 100644 --- a/include/openflow/openflow-1.5.h +++ b/include/openflow/openflow-1.5.h @@ -149,4 +149,11 @@ struct ofp15_group_desc_stats { }; OFP_ASSERT(sizeof(struct ofp15_group_desc_stats) == 16); +/* Flags of features supported by the table. */ +enum ofp15_table_feature_flag { + OFPTFF_INGRESS_TABLE = 1 << 0, /* Can be configured as ingress table. */ + OFPTFF_EGRESS_TABLE = 1 << 1, /* Can be configured as egress table. */ + OFPTFF_FIRST_EGRESS = 1 << 4, /* Is the first egress table. */ +}; + #endif /* openflow/openflow-1.5.h */ diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c index ff3bc12..651c91e 100644 --- a/lib/ofp-actions.c +++ b/lib/ofp-actions.c @@ -7789,3 +7789,26 @@ pad_ofpat(struct ofpbuf *openflow, size_t start_ofs) oah->len = htons(openflow->size - start_ofs); } +/* If first egress table is set then flow tables used for egress + * processing must forbid the use of output action or group action in + * write-action instruction and must advertise the same in flow table + * features as mentioned in the specification. + * + * OFPAT_* values, i.e. 0 for OFPACT_OUTPUT and 22 for OFPACT_GROUP is + * used for comparison. + */ + +void +ofpact_put_ofp15_write_actions(uint64_t *ofpacts_bitmap, + enum ofp_version version) +{ + const struct ofpact_map *x; + + for (x = get_ofpact_map(version); x->ofpat >= 0; x++) { + if (x->ofpact == OFPACT_OUTPUT || x->ofpact == OFPACT_GROUP) { + continue; + } else { + *ofpacts_bitmap |= (UINT64_C(1) << x->ofpact); + } + } +} diff --git a/lib/ofp-actions.h b/lib/ofp-actions.h index 5dec177..9276daf 100644 --- a/lib/ofp-actions.h +++ b/lib/ofp-actions.h @@ -1013,5 +1013,7 @@ enum ofperr ovs_instruction_type_from_inst_type( ovs_be32 ovsinst_bitmap_to_openflow(uint32_t ovsinst_bitmap, enum ofp_version); uint32_t ovsinst_bitmap_from_openflow(ovs_be32 ofpit_bitmap, enum ofp_version); - +void +ofpact_put_ofp15_write_actions(uint64_t *ofpacts_bitmap, + enum ofp_version version); #endif /* ofp-actions.h */ diff --git a/lib/ofp-msgs.h b/lib/ofp-msgs.h index a15efb6..6e84798 100644 --- a/lib/ofp-msgs.h +++ b/lib/ofp-msgs.h @@ -374,7 +374,7 @@ enum ofpraw { /* OFPST 1.3+ (11): struct ofp13_meter_features. */ OFPRAW_OFPST13_METER_FEATURES_REPLY, - /* OFPST 1.3+ (12): void. */ + /* OFPST 1.3+ (12): struct ofp13_table_features[]. */ OFPRAW_OFPST13_TABLE_FEATURES_REQUEST, /* OFPST 1.3+ (12): struct ofp13_table_features, uint8_t[8][]. */ diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c index 5ef3892..f131adb 100644 --- a/lib/ofp-parse.c +++ b/lib/ofp-parse.c @@ -1704,3 +1704,28 @@ parse_ofp_tlv_table_mod_str(struct ofputil_tlv_table_mod *ttm, return NULL; } + +/* Convert 'table_id' and table feature flag 'OFPTFF_FIRST_EGRESS' into 'tf' + * for sending a set_table_features command to a switch. + * + * Stores a bitmap of the OpenFlow versions that are usable for 'tf' into + * '*usable_versions'. + * + * 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 +parse_ofp_table_features(struct ofputil_table_features *tf, + const char *table_id, + uint32_t *usable_versions) +{ + char *error = str_to_u8(table_id, "table_id", &tf->table_id); + if (error) { + return error; + } + + *usable_versions = (1u << OFP15_VERSION); + + tf->features |= OFPTFF_FIRST_EGRESS; + + return NULL; +} diff --git a/lib/ofp-parse.h b/lib/ofp-parse.h index a1c147b..fba2efd 100644 --- a/lib/ofp-parse.h +++ b/lib/ofp-parse.h @@ -36,6 +36,7 @@ struct ofputil_meter_mod; struct ofputil_table_mod; struct ofputil_tlv_table_mod; struct simap; +struct ofputil_table_features; enum ofputil_protocol; char *parse_ofp_str(struct ofputil_flow_mod *, int command, const char *str_, @@ -52,6 +53,11 @@ char *parse_ofp_table_mod(struct ofputil_table_mod *, uint32_t *usable_versions) OVS_WARN_UNUSED_RESULT; +char *parse_ofp_table_features(struct ofputil_table_features *tf, + const char *table_id, + uint32_t *usable_versions) + OVS_WARN_UNUSED_RESULT; + char *parse_ofp_flow_mod_file(const char *file_name, int command, struct ofputil_flow_mod **fms, size_t *n_fms, enum ofputil_protocol *usable_protocols) diff --git a/lib/ofp-print.c b/lib/ofp-print.c index 5af4bf0..ab79065 100644 --- a/lib/ofp-print.c +++ b/lib/ofp-print.c @@ -2782,6 +2782,12 @@ ofp_print_table_features(struct ds *s, } + if (features->features >= 0) { + ds_put_format(s, " features: %s\n", + (features->features & OFPTFF_FIRST_EGRESS) ? + "first egress table" : "none"); + } + if (features->max_entries) { ds_put_format(s, " max_entries=%"PRIu32"\n", features->max_entries); } diff --git a/lib/ofp-util.c b/lib/ofp-util.c index aa4d2f3..bf1a28f 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -4725,12 +4725,16 @@ ofputil_decode_table_features(struct ofpbuf *msg, struct ofp13_table_features *otf; struct ofpbuf properties; unsigned int len; + enum ofpraw raw; + enum ofperr error; - memset(tf, 0, sizeof *tf); - - if (!msg->header) { - ofpraw_pull_assert(msg); + error = (msg->header ? ofpraw_decode(&raw, msg->header) + : ofpraw_pull(&raw, msg)); + if (error) { + return error; } + + memset(tf, 0, sizeof *tf); oh = msg->header; if (!msg->size) { @@ -4754,6 +4758,20 @@ ofputil_decode_table_features(struct ofpbuf *msg, return OFPERR_OFPTFFC_BAD_TABLE; } + if (oh->version >= OFP15_VERSION && + raw == OFPRAW_OFPST13_TABLE_FEATURES_REQUEST) { + + /* Return an error if TABLE_FEATURES_REQUEST attempts to set table 0 + * as first egress table. */ + if (tf->table_id == 0) { + return OFPERR_OFPTFFC_BAD_TABLE; + } + + /* Return an error if TABLE_FEATURES_REQUEST contain properties. */ + if (properties.size > 0) { + return OFPERR_OFPBPC_BAD_LEN; + } + } ovs_strlcpy(tf->name, otf->name, OFP_MAX_TABLE_NAME_LEN); tf->metadata_match = otf->metadata_match; tf->metadata_write = otf->metadata_write; @@ -4767,7 +4785,19 @@ ofputil_decode_table_features(struct ofpbuf *msg, tf->supports_vacancy_events = -1; } tf->max_entries = ntohl(otf->max_entries); - + if (oh->version >= OFP15_VERSION) { + /* Return an error if any flag other than OFPTFF_FIRST_EGRESS is set. + */ + uint32_t features = ntohl(otf->features); + if ((features & OFPTFF_FIRST_EGRESS) != 0) { + tf->features |= OFPTFF_FIRST_EGRESS; + } else if ((features & OFPTFF_INGRESS_TABLE) != 0 || + (features & OFPTFF_EGRESS_TABLE) != 0 ) { + return OFPERR_OFPBFC_BAD_FLAGS; + } + } else { + tf->features = -1; + } while (properties.size > 0) { struct ofpbuf payload; enum ofperr error; @@ -4869,7 +4899,8 @@ ofputil_decode_table_features(struct ofpbuf *msg, /* Encodes and returns a request to obtain the table features of a switch. * The message is encoded for OpenFlow version 'ofp_version'. */ struct ofpbuf * -ofputil_encode_table_features_request(enum ofp_version ofp_version) +ofputil_encode_table_features_request(const struct ofputil_table_features *tf, + enum ofp_version ofp_version) { struct ofpbuf *request = NULL; @@ -4881,10 +4912,22 @@ ofputil_encode_table_features_request(enum ofp_version ofp_version) "(\'-O OpenFlow13\')"); case OFP13_VERSION: case OFP14_VERSION: - case OFP15_VERSION: request = ofpraw_alloc(OFPRAW_OFPST13_TABLE_FEATURES_REQUEST, ofp_version, 0); break; + case OFP15_VERSION: { + struct ofp13_table_features *otf; + + request = ofpraw_alloc(OFPRAW_OFPST13_TABLE_FEATURES_REQUEST, + ofp_version, 0); + if (tf != NULL && (tf->features & OFPTFF_FIRST_EGRESS)) { + otf = ofpbuf_put_zeros(request, sizeof *otf); + otf->table_id = tf->table_id; + otf->features = htonl(tf->features); + otf->length = htons(sizeof *otf); + } + } + break; default: OVS_NOT_REACHED(); } @@ -4973,7 +5016,11 @@ ofputil_append_table_features_reply(const struct ofputil_table_features *tf, } } otf->max_entries = htonl(tf->max_entries); - + if (version >= OFP15_VERSION) { + if ((tf->features & OFPTFF_FIRST_EGRESS) != 0) { + otf->features |= htonl(OFPTFF_FIRST_EGRESS); + } + } put_table_instruction_features(reply, &tf->nonmiss, 0, version); put_table_instruction_features(reply, &tf->miss, 1, version); @@ -6075,6 +6122,7 @@ ofputil_decode_table_stats_reply(struct ofpbuf *msg, memset(features, 0, sizeof *features); features->supports_eviction = -1; features->supports_vacancy_events = -1; + features->features = -1; switch ((enum ofp_version) oh->version) { case OFP10_VERSION: @@ -9812,3 +9860,13 @@ ofputil_async_cfg_default(enum ofp_version version) .slave[OAM_PORT_STATUS] = OFPPR_BITS, }; } + +uint8_t ofputil_egress_table_id(uint8_t table_id) +{ + static uint8_t egress_table_id = 0; + + if (table_id > 0) { + egress_table_id = table_id; + } + return egress_table_id; +} diff --git a/lib/ofp-util.h b/lib/ofp-util.h index 866e1bc..6e5e117 100644 --- a/lib/ofp-util.h +++ b/lib/ofp-util.h @@ -767,6 +767,15 @@ struct ofputil_table_features { int supports_eviction; /* OF1.4+ only. */ int supports_vacancy_events; /* OF1.4+ only. */ + /* The features field is a bitmap of OFPTFF_* values that defines how the + * flow table can be used and what are its basic features. + * + * 'features' is relevant only for Openflow 1.5 and later only. For 1.5, + * it will be OFPTFF_FIRST_EGRESS if first egress table is set, otherwise + * 0. For other versions, they are decoded as -1 and ignored for encoding. + */ + int features; /* OF1.5+ only. */ + /* Table features related to instructions. There are two instances: * * - 'miss' reports features available in the table miss flow. @@ -823,7 +832,9 @@ int ofputil_decode_table_desc(struct ofpbuf *, struct ofputil_table_desc *, enum ofp_version); -struct ofpbuf *ofputil_encode_table_features_request(enum ofp_version); +struct ofpbuf * +ofputil_encode_table_features_request(const struct ofputil_table_features *, + enum ofp_version); struct ofpbuf *ofputil_encode_table_desc_request(enum ofp_version); @@ -1356,4 +1367,6 @@ enum ofperr ofputil_decode_requestforward(const struct ofp_header *, struct ofputil_requestforward *); void ofputil_destroy_requestforward(struct ofputil_requestforward *); +uint8_t ofputil_egress_table_id(uint8_t table_id); + #endif /* ofp-util.h */ diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h index b6aac0a..3a84c5d 100644 --- a/ofproto/ofproto-provider.h +++ b/ofproto/ofproto-provider.h @@ -95,6 +95,7 @@ struct ofproto { int n_tables; cls_version_t tables_version; /* Controls which rules are visible to * table lookups. */ + uint8_t first_egress_table_id; /* Contains first egress table id. */ /* Rules indexed on their cookie values, in all flow tables. */ struct hindex cookies OVS_GUARDED_BY(ofproto_mutex); @@ -267,6 +268,10 @@ struct oftable { atomic_ulong n_matched; atomic_ulong n_missed; + + /* The features field is a bitmap that defines how the flow table can be + * used and what are its basic features. */ + enum ofp15_table_feature_flag features; }; /* Assigns TABLE to each oftable, in turn, in OFPROTO. diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index 3faf42a..fdcbb80 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -3118,7 +3118,8 @@ handle_echo_request(struct ofconn *ofconn, const struct ofp_header *oh) static void query_tables(struct ofproto *ofproto, struct ofputil_table_features **featuresp, - struct ofputil_table_stats **statsp) + struct ofputil_table_stats **statsp, + enum ofp_version version) { struct mf_bitmap rw_fields = oxm_writable_fields(); struct mf_bitmap match = oxm_matchable_fields(); @@ -3150,7 +3151,12 @@ query_tables(struct ofproto *ofproto, if (!more_tables) { f->nonmiss.instructions &= ~(1u << OVSINST_OFPIT11_GOTO_TABLE); } - f->nonmiss.write.ofpacts = (UINT64_C(1) << N_OFPACTS) - 1; + if (version >= OFP15_VERSION && ofputil_egress_table_id(0) && + f->table_id >= ofputil_egress_table_id(0)) { + ofpact_put_ofp15_write_actions(&f->nonmiss.write.ofpacts, version); + } else { + f->nonmiss.write.ofpacts = (UINT64_C(1) << N_OFPACTS) - 1; + } f->nonmiss.write.set_fields = rw_fields; f->nonmiss.apply = f->nonmiss.write; f->miss = f->nonmiss; @@ -3158,6 +3164,9 @@ query_tables(struct ofproto *ofproto, f->match = match; f->mask = mask; f->wildcard = match; + if (ofproto->tables[i].features & OFPTFF_FIRST_EGRESS) { + f->features |= OFPTFF_FIRST_EGRESS; + } } if (statsp) { @@ -3194,14 +3203,15 @@ query_tables(struct ofproto *ofproto, static void query_switch_features(struct ofproto *ofproto, - bool *arp_match_ip, uint64_t *ofpacts) + bool *arp_match_ip, uint64_t *ofpacts, + enum ofp_version version) { struct ofputil_table_features *features, *f; *arp_match_ip = false; *ofpacts = 0; - query_tables(ofproto, &features, NULL); + query_tables(ofproto, &features, NULL, version); for (f = features; f < &features[ofproto->n_tables]; f++) { *ofpacts |= f->nonmiss.apply.ofpacts | f->miss.apply.ofpacts; if (bitmap_is_set(f->match.bm, MFF_ARP_SPA) || @@ -3224,7 +3234,8 @@ handle_features_request(struct ofconn *ofconn, const struct ofp_header *oh) bool arp_match_ip; struct ofpbuf *b; - query_switch_features(ofproto, &arp_match_ip, &features.ofpacts); + query_switch_features(ofproto, &arp_match_ip, &features.ofpacts, + oh->version); features.datapath_id = ofproto->datapath_id; features.n_buffers = pktbuf_capacity(); @@ -3531,7 +3542,7 @@ handle_table_stats_request(struct ofconn *ofconn, struct ofpbuf *reply; size_t i; - query_tables(ofproto, &features, &stats); + query_tables(ofproto, &features, &stats, request->version); reply = ofputil_encode_table_stats_reply(request); for (i = 0; i < ofproto->n_tables; i++) { @@ -3555,15 +3566,41 @@ handle_table_features_request(struct ofconn *ofconn, struct ofputil_table_features *features; struct ovs_list replies; struct ofpbuf msg; + enum ofperr error = 0; size_t i; ofpbuf_use_const(&msg, request, ntohs(request->length)); ofpraw_pull_assert(&msg); - if (msg.size || ofpmp_more(request)) { - return OFPERR_OFPTFFC_EPERM; + + if (request->version < OFP15_VERSION) { + if (msg.size || ofpmp_more(request)) { + return OFPERR_OFPTFFC_EPERM; + } + } else { + if (msg.size) { + struct ofputil_table_features tf; + error = ofputil_decode_table_features(&msg, &tf, false); + if (error) { + return error; + } + if ((tf.features & OFPTFF_FIRST_EGRESS) != 0) { + for (i = 0; i < ofproto->n_tables; i++) { + if (ofproto->tables[i].features & OFPTFF_FIRST_EGRESS) { + ofproto->tables[i].features &= ~OFPTFF_FIRST_EGRESS; + break; + } + } + ovs_mutex_lock(&ofproto_mutex); + ofproto->tables[tf.table_id].features |= OFPTFF_FIRST_EGRESS; + ofproto->first_egress_table_id = tf.table_id; + ofputil_egress_table_id(tf.table_id); + ovs_mutex_unlock(&ofproto_mutex); + } + return 0; + } } - query_tables(ofproto, &features, NULL); + query_tables(ofproto, &features, NULL, request->version); ofpmp_init(&replies, request); for (i = 0; i < ofproto->n_tables; i++) { diff --git a/tests/ofp-print.at b/tests/ofp-print.at index c791cb2..3b33ed7 100644 --- a/tests/ofp-print.at +++ b/tests/ofp-print.at @@ -2475,6 +2475,228 @@ f5 f6 f7 f8 f9 fa fb fc fd 00 00 00 00 00 00 00 \ ]) AT_CLEANUP +AT_SETUP([OFPST_TABLE_FEATURES request - OF1.5]) +AT_KEYWORDS([ofp-print OFPT_STATS_REQUEST]) +AT_CHECK([ovs-ofctl ofp-print "\ +06 13 09 40 00 00 00 d5 00 0c 00 01 00 00 00 00 \ +09 30 00 00 00 00 00 00 74 61 62 6c 65 30 00 00 \ +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \ +00 00 00 00 00 00 00 00 ff ff ff ff ff ff ff ff \ +ff ff ff ff ff ff ff ff 00 00 00 03 00 0f 42 40 \ +00 00 00 2c 00 01 00 08 00 00 00 00 00 02 00 08 \ +00 00 00 00 00 03 00 08 00 00 00 00 00 04 00 08 \ +00 00 00 00 00 05 00 08 00 00 00 00 00 00 00 00 \ +00 01 00 2c 00 01 00 08 00 00 00 00 00 02 00 08 \ +00 00 00 00 00 03 00 08 00 00 00 00 00 04 00 08 \ +00 00 00 00 00 05 00 08 00 00 00 00 00 00 00 00 \ +00 02 01 01 01 02 03 04 05 06 07 08 09 0a 0b 0c \ +0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c \ +1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c \ +2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c \ +3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c \ +4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c \ +5d 5e 5f 60 61 62 63 64 65 66 67 68 69 6a 6b 6c \ +6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 7b 7c \ +7d 7e 7f 80 81 82 83 84 85 86 87 88 89 8a 8b 8c \ +8d 8e 8f 90 91 92 93 94 95 96 97 98 99 9a 9b 9c \ +9d 9e 9f a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac \ +ad ae af b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc \ +bd be bf c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc \ +cd ce cf d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc \ +dd de df e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec \ +ed ee ef f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc \ +fd 00 00 00 00 00 00 00 00 03 01 01 01 02 03 04 \ +05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 \ +15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 \ +25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 \ +35 36 37 38 39 3a 3b 3c 3d 3e 3f 40 41 42 43 44 \ +45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 \ +55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 64 \ +65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 \ +75 76 77 78 79 7a 7b 7c 7d 7e 7f 80 81 82 83 84 \ +85 86 87 88 89 8a 8b 8c 8d 8e 8f 90 91 92 93 94 \ +95 96 97 98 99 9a 9b 9c 9d 9e 9f a0 a1 a2 a3 a4 \ +a5 a6 a7 a8 a9 aa ab ac ad ae af b0 b1 b2 b3 b4 \ +b5 b6 b7 b8 b9 ba bb bc bd be bf c0 c1 c2 c3 c4 \ +c5 c6 c7 c8 c9 ca cb cc cd ce cf d0 d1 d2 d3 d4 \ +d5 d6 d7 d8 d9 da db dc dd de df e0 e1 e2 e3 e4 \ +e5 e6 e7 e8 e9 ea eb ec ed ee ef f0 f1 f2 f3 f4 \ +f5 f6 f7 f8 f9 fa fb fc fd 00 00 00 00 00 00 00 \ +00 04 00 84 00 00 00 08 00 00 00 00 00 0b 00 08 \ +00 00 00 00 00 0c 00 08 00 00 00 00 00 0f 00 08 \ +00 00 00 00 00 10 00 08 00 00 00 00 00 11 00 08 \ +00 00 00 00 00 12 00 08 00 00 00 00 00 13 00 08 \ +00 00 00 00 00 14 00 08 00 00 00 00 00 15 00 08 \ +00 00 00 00 00 16 00 08 00 00 00 00 00 17 00 08 \ +00 00 00 00 00 18 00 08 00 00 00 00 00 19 00 08 \ +00 00 00 00 00 1a 00 08 00 00 00 00 00 1b 00 08 \ +00 00 00 00 00 00 00 00 00 05 00 84 00 00 00 08 \ +00 00 00 00 00 0b 00 08 00 00 00 00 00 0c 00 08 \ +00 00 00 00 00 0f 00 08 00 00 00 00 00 10 00 08 \ +00 00 00 00 00 11 00 08 00 00 00 00 00 12 00 08 \ +00 00 00 00 00 13 00 08 00 00 00 00 00 14 00 08 \ +00 00 00 00 00 15 00 08 00 00 00 00 00 16 00 08 \ +00 00 00 00 00 17 00 08 00 00 00 00 00 18 00 08 \ +00 00 00 00 00 19 00 08 00 00 00 00 00 1a 00 08 \ +00 00 00 00 00 1b 00 08 00 00 00 00 00 00 00 00 \ +00 06 00 84 00 00 00 08 00 00 00 00 00 0b 00 08 \ +00 00 00 00 00 0c 00 08 00 00 00 00 00 0f 00 08 \ +00 00 00 00 00 10 00 08 00 00 00 00 00 11 00 08 \ +00 00 00 00 00 12 00 08 00 00 00 00 00 13 00 08 \ +00 00 00 00 00 14 00 08 00 00 00 00 00 15 00 08 \ +00 00 00 00 00 16 00 08 00 00 00 00 00 17 00 08 \ +00 00 00 00 00 18 00 08 00 00 00 00 00 19 00 08 \ +00 00 00 00 00 1a 00 08 00 00 00 00 00 1b 00 08 \ +00 00 00 00 00 00 00 00 00 07 00 84 00 00 00 08 \ +00 00 00 00 00 0b 00 08 00 00 00 00 00 0c 00 08 \ +00 00 00 00 00 0f 00 08 00 00 00 00 00 10 00 08 \ +00 00 00 00 00 11 00 08 00 00 00 00 00 12 00 08 \ +00 00 00 00 00 13 00 08 00 00 00 00 00 14 00 08 \ +00 00 00 00 00 15 00 08 00 00 00 00 00 16 00 08 \ +00 00 00 00 00 17 00 08 00 00 00 00 00 18 00 08 \ +00 00 00 00 00 19 00 08 00 00 00 00 00 1a 00 08 \ +00 00 00 00 00 1b 00 08 00 00 00 00 00 00 00 00 \ +00 08 00 dc 80 00 4c 08 00 01 3e 04 00 01 40 04 \ +80 00 04 08 00 00 00 02 80 00 00 04 00 01 42 04 \ +00 01 00 04 00 01 02 04 00 01 04 04 00 01 06 04 \ +00 01 08 04 00 01 0a 04 00 01 0c 04 00 01 0e 04 \ +80 00 08 06 80 00 06 06 80 00 0a 02 00 00 08 02 \ +80 00 0c 02 80 00 0e 01 80 00 44 04 80 00 46 01 \ +80 00 48 01 80 00 16 04 80 00 18 04 80 00 34 10 \ +80 00 36 10 80 00 38 04 80 00 14 01 00 00 0a 01 \ +80 00 10 01 80 00 12 01 00 01 3a 01 00 01 34 01 \ +80 00 2a 02 80 00 2c 04 80 00 2e 04 80 00 30 06 \ +80 00 32 06 80 00 1a 02 80 00 1c 02 00 01 44 02 \ +80 00 1e 02 80 00 20 02 80 00 22 02 80 00 24 02 \ +80 00 26 01 80 00 28 01 80 00 3a 01 80 00 3c 01 \ +80 00 3e 10 80 00 40 06 80 00 42 06 00 00 00 00 \ +00 0a 00 dc 80 00 4c 08 00 01 3e 04 00 01 40 04 \ +80 00 04 08 00 00 00 02 80 00 00 04 00 01 42 04 \ +00 01 00 04 00 01 02 04 00 01 04 04 00 01 06 04 \ +00 01 08 04 00 01 0a 04 00 01 0c 04 00 01 0e 04 \ +80 00 08 06 80 00 06 06 80 00 0a 02 00 00 08 02 \ +80 00 0c 02 80 00 0e 01 80 00 44 04 80 00 46 01 \ +80 00 48 01 80 00 16 04 80 00 18 04 80 00 34 10 \ +80 00 36 10 80 00 38 04 80 00 14 01 00 00 0a 01 \ +80 00 10 01 80 00 12 01 00 01 3a 01 00 01 34 01 \ +80 00 2a 02 80 00 2c 04 80 00 2e 04 80 00 30 06 \ +80 00 32 06 80 00 1a 02 80 00 1c 02 00 01 44 02 \ +80 00 1e 02 80 00 20 02 80 00 22 02 80 00 24 02 \ +80 00 26 01 80 00 28 01 80 00 3a 01 80 00 3c 01 \ +80 00 3e 10 80 00 40 06 80 00 42 06 00 00 00 00 \ +00 0c 00 a8 80 00 4c 08 00 01 3e 04 00 01 40 04 \ +80 00 04 08 00 00 00 02 80 00 00 04 00 01 42 04 \ +00 01 00 04 00 01 02 04 00 01 04 04 00 01 06 04 \ +00 01 08 04 00 01 0a 04 00 01 0c 04 00 01 0e 04 \ +80 00 08 06 80 00 06 06 00 00 08 02 80 00 0c 02 \ +80 00 0e 01 80 00 44 04 80 00 46 01 80 00 16 04 \ +80 00 18 04 80 00 34 10 80 00 36 10 00 00 0a 01 \ +80 00 10 01 80 00 12 01 00 01 3a 01 80 00 2a 02 \ +80 00 2c 04 80 00 2e 04 80 00 30 06 80 00 32 06 \ +80 00 1a 02 80 00 1c 02 80 00 1e 02 80 00 20 02 \ +80 00 22 02 80 00 24 02 00 0d 00 a8 80 00 4c 08 \ +00 01 3e 04 00 01 40 04 80 00 04 08 00 00 00 02 \ +80 00 00 04 00 01 42 04 00 01 00 04 00 01 02 04 \ +00 01 04 04 00 01 06 04 00 01 08 04 00 01 0a 04 \ +00 01 0c 04 00 01 0e 04 80 00 08 06 80 00 06 06 \ +00 00 08 02 80 00 0c 02 80 00 0e 01 80 00 44 04 \ +80 00 46 01 80 00 16 04 80 00 18 04 80 00 34 10 \ +80 00 36 10 00 00 0a 01 80 00 10 01 80 00 12 01 \ +00 01 3a 01 80 00 2a 02 80 00 2c 04 80 00 2e 04 \ +80 00 30 06 80 00 32 06 80 00 1a 02 80 00 1c 02 \ +80 00 1e 02 80 00 20 02 80 00 22 02 80 00 24 02 \ +00 0e 00 a8 80 00 4c 08 00 01 3e 04 00 01 40 04 \ +80 00 04 08 00 00 00 02 80 00 00 04 00 01 42 04 \ +00 01 00 04 00 01 02 04 00 01 04 04 00 01 06 04 \ +00 01 08 04 00 01 0a 04 00 01 0c 04 00 01 0e 04 \ +80 00 08 06 80 00 06 06 00 00 08 02 80 00 0c 02 \ +80 00 0e 01 80 00 44 04 80 00 46 01 80 00 16 04 \ +80 00 18 04 80 00 34 10 80 00 36 10 00 00 0a 01 \ +80 00 10 01 80 00 12 01 00 01 3a 01 80 00 2a 02 \ +80 00 2c 04 80 00 2e 04 80 00 30 06 80 00 32 06 \ +80 00 1a 02 80 00 1c 02 80 00 1e 02 80 00 20 02 \ +80 00 22 02 80 00 24 02 00 0f 00 a8 80 00 4c 08 \ +00 01 3e 04 00 01 40 04 80 00 04 08 00 00 00 02 \ +80 00 00 04 00 01 42 04 00 01 00 04 00 01 02 04 \ +00 01 04 04 00 01 06 04 00 01 08 04 00 01 0a 04 \ +00 01 0c 04 00 01 0e 04 80 00 08 06 80 00 06 06 \ +00 00 08 02 80 00 0c 02 80 00 0e 01 80 00 44 04 \ +80 00 46 01 80 00 16 04 80 00 18 04 80 00 34 10 \ +80 00 36 10 00 00 0a 01 80 00 10 01 80 00 12 01 \ +00 01 3a 01 80 00 2a 02 80 00 2c 04 80 00 2e 04 \ +80 00 30 06 80 00 32 06 80 00 1a 02 80 00 1c 02 \ +80 00 1e 02 80 00 20 02 80 00 22 02 80 00 24 02 \ +"], [0], [OFPST_TABLE_FEATURES reply (OF1.5) (xid=0xd5): + table 0 ("table0"): + metadata: match=0xffffffffffffffff write=0xffffffffffffffff + eviction: not supported + vacancy events: not supported + features: none + max_entries=1000000 + instructions (table miss and others): + next tables: 1-253 + instructions: apply_actions,clear_actions,write_actions,write_metadata,goto_table + Write-Actions and Apply-Actions features: + actions: output group set_field strip_vlan push_vlan mod_nw_ttl dec_ttl set_mpls_ttl dec_mpls_ttl push_mpls pop_mpls set_queue + supported on Set-Field: tun_id tun_src tun_dst metadata in_port in_port_oxm pkt_mark reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 eth_src eth_dst vlan_tci vlan_vid vlan_pcp mpls_label mpls_tc ip_src ip_dst ipv6_src ipv6_dst nw_tos ip_dscp nw_ecn nw_ttl arp_op arp_spa arp_tpa arp_sha arp_tha tcp_src tcp_dst udp_src udp_dst sctp_src sctp_dst + matching: + tun_id: exact match or wildcard + tun_src: exact match or wildcard + tun_dst: exact match or wildcard + metadata: exact match or wildcard + in_port: exact match or wildcard + in_port_oxm: exact match or wildcard + pkt_mark: exact match or wildcard + reg0: exact match or wildcard + reg1: exact match or wildcard + reg2: exact match or wildcard + reg3: exact match or wildcard + reg4: exact match or wildcard + reg5: exact match or wildcard + reg6: exact match or wildcard + reg7: exact match or wildcard + eth_src: exact match or wildcard + eth_dst: exact match or wildcard + eth_type: exact match or wildcard + vlan_tci: exact match or wildcard + vlan_vid: exact match or wildcard + vlan_pcp: exact match or wildcard + mpls_label: exact match or wildcard + mpls_tc: exact match or wildcard + mpls_bos: exact match or wildcard + ip_src: exact match or wildcard + ip_dst: exact match or wildcard + ipv6_src: exact match or wildcard + ipv6_dst: exact match or wildcard + ipv6_label: exact match or wildcard + nw_proto: exact match or wildcard + nw_tos: exact match or wildcard + ip_dscp: exact match or wildcard + nw_ecn: exact match or wildcard + nw_ttl: exact match or wildcard + ip_frag: exact match or wildcard + arp_op: exact match or wildcard + arp_spa: exact match or wildcard + arp_tpa: exact match or wildcard + arp_sha: exact match or wildcard + arp_tha: exact match or wildcard + tcp_src: exact match or wildcard + tcp_dst: exact match or wildcard + tcp_flags: exact match or wildcard + udp_src: exact match or wildcard + udp_dst: exact match or wildcard + sctp_src: exact match or wildcard + sctp_dst: exact match or wildcard + icmp_type: exact match or wildcard + icmp_code: exact match or wildcard + icmpv6_type: exact match or wildcard + icmpv6_code: exact match or wildcard + nd_target: exact match or wildcard + nd_sll: exact match or wildcard + nd_tll: exact match or wildcard +]) +AT_CLEANUP + AT_SETUP([OFPT_BARRIER_REQUEST - OF1.0]) AT_KEYWORDS([ofp-print]) AT_CHECK([ovs-ofctl ofp-print '01 12 00 08 00 00 00 01'], [0], [dnl diff --git a/tests/ofproto.at b/tests/ofproto.at index 61a6be5..e1a63e4 100644 --- a/tests/ofproto.at +++ b/tests/ofproto.at @@ -1975,6 +1975,236 @@ AT_CHECK([ovs-ofctl -O OpenFlow13 dump-table-features br0], [0], [expout]) OVS_VSWITCHD_STOP AT_CLEANUP +AT_SETUP([ofproto - table features (OpenFlow 1.5)]) +OVS_VSWITCHD_START +head_table () { + printf ' table 0 ("%s"): + metadata: match=0xffffffffffffffff write=0xffffffffffffffff + eviction: not supported + vacancy events: not supported + features: none + max_entries=1000000 + instructions (table miss and others): + next tables: 1-253 + instructions: meter,apply_actions,clear_actions,write_actions,write_metadata,goto_table + Write-Actions and Apply-Actions features: + actions: output group set_field strip_vlan push_vlan mod_nw_ttl dec_ttl set_mpls_ttl dec_mpls_ttl push_mpls pop_mpls set_queue + supported on Set-Field: tun_id tun_src tun_dst tun_ipv6_src tun_ipv6_dst tun_flags tun_gbp_id tun_gbp_flags tun_metadata0 tun_metadata1 tun_metadata2 tun_metadata3 tun_metadata4 tun_metadata5 tun_metadata6 tun_metadata7 tun_metadata8 tun_metadata9 tun_metadata10 tun_metadata11 tun_metadata12 tun_metadata13 tun_metadata14 tun_metadata15 tun_metadata16 tun_metadata17 tun_metadata18 tun_metadata19 tun_metadata20 tun_metadata21 tun_metadata22 tun_metadata23 tun_metadata24 tun_metadata25 tun_metadata26 tun_metadata27 tun_metadata28 tun_metadata29 tun_metadata30 tun_metadata31 tun_metadata32 tun_metadata33 tun_metadata34 tun_metadata35 tun_metadata36 tun_metadata37 tun_metadata38 tun_metadata39 tun_metadata40 tun_metadata41 tun_metadata42 tun_metadata43 tun_metadata44 tun_metadata45 tun_metadata46 tun_metadata47 tun_metadata48 tun_metadata49 tun_metadata50 tun_metadata51 tun_metadata52 tun_metadata53 tun_metadata54 tun_metadata55 tun_metadata56 tun_metadata57 tun_metadata5 8 tun_metadata59 tun_metadata60 tun_metadata61 tun_metadata62 tun_metadata63 metadata in_port in_port_oxm pkt_mark ct_mark ct_label reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 xreg0 xreg1 xreg2 xreg3 eth_src eth_dst vlan_tci vlan_vid vlan_pcp mpls_label mpls_tc ip_src ip_dst ipv6_src ipv6_dst ipv6_label nw_tos ip_dscp nw_ecn nw_ttl arp_op arp_spa arp_tpa arp_sha arp_tha tcp_src tcp_dst udp_src udp_dst sctp_src sctp_dst icmp_type icmp_code icmpv6_type icmpv6_code nd_target nd_sll nd_tll + matching: + dp_hash: arbitrary mask + recirc_id: exact match or wildcard + conj_id: exact match or wildcard + tun_id: arbitrary mask + tun_src: arbitrary mask + tun_dst: arbitrary mask + tun_ipv6_src: arbitrary mask + tun_ipv6_dst: arbitrary mask + tun_flags: arbitrary mask + tun_gbp_id: arbitrary mask + tun_gbp_flags: arbitrary mask + tun_metadata0: arbitrary mask + tun_metadata1: arbitrary mask + tun_metadata2: arbitrary mask + tun_metadata3: arbitrary mask + tun_metadata4: arbitrary mask + tun_metadata5: arbitrary mask + tun_metadata6: arbitrary mask + tun_metadata7: arbitrary mask + tun_metadata8: arbitrary mask + tun_metadata9: arbitrary mask + tun_metadata10: arbitrary mask + tun_metadata11: arbitrary mask + tun_metadata12: arbitrary mask + tun_metadata13: arbitrary mask + tun_metadata14: arbitrary mask + tun_metadata15: arbitrary mask + tun_metadata16: arbitrary mask + tun_metadata17: arbitrary mask + tun_metadata18: arbitrary mask + tun_metadata19: arbitrary mask + tun_metadata20: arbitrary mask + tun_metadata21: arbitrary mask + tun_metadata22: arbitrary mask + tun_metadata23: arbitrary mask + tun_metadata24: arbitrary mask + tun_metadata25: arbitrary mask + tun_metadata26: arbitrary mask + tun_metadata27: arbitrary mask + tun_metadata28: arbitrary mask + tun_metadata29: arbitrary mask + tun_metadata30: arbitrary mask + tun_metadata31: arbitrary mask + tun_metadata32: arbitrary mask + tun_metadata33: arbitrary mask + tun_metadata34: arbitrary mask + tun_metadata35: arbitrary mask + tun_metadata36: arbitrary mask + tun_metadata37: arbitrary mask + tun_metadata38: arbitrary mask + tun_metadata39: arbitrary mask + tun_metadata40: arbitrary mask + tun_metadata41: arbitrary mask + tun_metadata42: arbitrary mask + tun_metadata43: arbitrary mask + tun_metadata44: arbitrary mask + tun_metadata45: arbitrary mask + tun_metadata46: arbitrary mask + tun_metadata47: arbitrary mask + tun_metadata48: arbitrary mask + tun_metadata49: arbitrary mask + tun_metadata50: arbitrary mask + tun_metadata51: arbitrary mask + tun_metadata52: arbitrary mask + tun_metadata53: arbitrary mask + tun_metadata54: arbitrary mask + tun_metadata55: arbitrary mask + tun_metadata56: arbitrary mask + tun_metadata57: arbitrary mask + tun_metadata58: arbitrary mask + tun_metadata59: arbitrary mask + tun_metadata60: arbitrary mask + tun_metadata61: arbitrary mask + tun_metadata62: arbitrary mask + tun_metadata63: arbitrary mask + metadata: arbitrary mask + in_port: exact match or wildcard + in_port_oxm: exact match or wildcard + actset_output: exact match or wildcard + pkt_mark: arbitrary mask + ct_state: arbitrary mask + ct_zone: exact match or wildcard + ct_mark: arbitrary mask + ct_label: arbitrary mask + reg0: arbitrary mask + reg1: arbitrary mask + reg2: arbitrary mask + reg3: arbitrary mask + reg4: arbitrary mask + reg5: arbitrary mask + reg6: arbitrary mask + reg7: arbitrary mask + xreg0: arbitrary mask + xreg1: arbitrary mask + xreg2: arbitrary mask + xreg3: arbitrary mask + eth_src: arbitrary mask + eth_dst: arbitrary mask + eth_type: exact match or wildcard + vlan_tci: arbitrary mask + vlan_vid: arbitrary mask + vlan_pcp: exact match or wildcard + mpls_label: exact match or wildcard + mpls_tc: exact match or wildcard + mpls_bos: exact match or wildcard + ip_src: arbitrary mask + ip_dst: arbitrary mask + ipv6_src: arbitrary mask + ipv6_dst: arbitrary mask + ipv6_label: arbitrary mask + nw_proto: exact match or wildcard + nw_tos: exact match or wildcard + ip_dscp: exact match or wildcard + nw_ecn: exact match or wildcard + nw_ttl: exact match or wildcard + ip_frag: arbitrary mask + arp_op: exact match or wildcard + arp_spa: arbitrary mask + arp_tpa: arbitrary mask + arp_sha: arbitrary mask + arp_tha: arbitrary mask + tcp_src: arbitrary mask + tcp_dst: arbitrary mask + tcp_flags: arbitrary mask + udp_src: arbitrary mask + udp_dst: arbitrary mask + sctp_src: arbitrary mask + sctp_dst: arbitrary mask + icmp_type: exact match or wildcard + icmp_code: exact match or wildcard + icmpv6_type: exact match or wildcard + icmpv6_code: exact match or wildcard + nd_target: arbitrary mask + nd_sll: arbitrary mask + nd_tll: arbitrary mask + +' $1 +} +ditto() { + printf ' table %d ("%s"): + metadata: match=0xffffffffffffffff write=0xffffffffffffffff + eviction: not supported + vacancy events: not supported + features: none + max_entries=%d + instructions (table miss and others): + next tables: %d-253 + (same instructions) + (same actions) + (same matching) + +' $1 $2 $3 `expr $1 + 1` +} +tail_tables() { +echo ' table 252 ("table252"): + metadata: match=0xffffffffffffffff write=0xffffffffffffffff + eviction: not supported + vacancy events: not supported + features: none + max_entries=1000000 + instructions (table miss and others): + next tables: 253 + (same instructions) + (same actions) + (same matching) + + table 253 ("table253"): + metadata: match=0xffffffffffffffff write=0xffffffffffffffff + eviction: not supported + vacancy events: not supported + features: none + max_entries=1000000 + instructions (table miss and others): + instructions: meter,apply_actions,clear_actions,write_actions,write_metadata + (same actions) + (same matching) +' +} +first_egress_table() { +echo ' table 251 ("table251"): + metadata: match=0xffffffffffffffff write=0xffffffffffffffff + eviction: not supported + vacancy events: not supported + features: first egress table + max_entries=1000000 + instructions (table miss and others): + next tables: 252-253 + (same instructions) + Write-Actions and Apply-Actions features: + actions: set_field strip_vlan push_vlan mod_nw_ttl dec_ttl set_mpls_ttl dec_mpls_ttl push_mpls pop_mpls set_queue + supported on Set-Field: tun_id tun_src tun_dst tun_ipv6_src tun_ipv6_dst tun_flags tun_gbp_id tun_gbp_flags tun_metadata0 tun_metadata1 tun_metadata2 tun_metadata3 tun_metadata4 tun_metadata5 tun_metadata6 tun_metadata7 tun_metadata8 tun_metadata9 tun_metadata10 tun_metadata11 tun_metadata12 tun_metadata13 tun_metadata14 tun_metadata15 tun_metadata16 tun_metadata17 tun_metadata18 tun_metadata19 tun_metadata20 tun_metadata21 tun_metadata22 tun_metadata23 tun_metadata24 tun_metadata25 tun_metadata26 tun_metadata27 tun_metadata28 tun_metadata29 tun_metadata30 tun_metadata31 tun_metadata32 tun_metadata33 tun_metadata34 tun_metadata35 tun_metadata36 tun_metadata37 tun_metadata38 tun_metadata39 tun_metadata40 tun_metadata41 tun_metadata42 tun_metadata43 tun_metadata44 tun_metadata45 tun_metadata46 tun_metadata47 tun_metadata48 tun_metadata49 tun_metadata50 tun_metadata51 tun_metadata52 tun_metadata53 tun_metadata54 tun_metadata55 tun_metadata56 tun_metadata57 tun_metadata5 8 tun_metadata59 tun_metadata60 tun_metadata61 tun_metadata62 tun_metadata63 metadata in_port in_port_oxm pkt_mark ct_mark ct_label reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 xreg0 xreg1 xreg2 xreg3 eth_src eth_dst vlan_tci vlan_vid vlan_pcp mpls_label mpls_tc ip_src ip_dst ipv6_src ipv6_dst ipv6_label nw_tos ip_dscp nw_ecn nw_ttl arp_op arp_spa arp_tpa arp_sha arp_tha tcp_src tcp_dst udp_src udp_dst sctp_src sctp_dst icmp_type icmp_code icmpv6_type icmpv6_code nd_target nd_sll nd_tll + (same matching) +' +} +(head_table classifier + for i in `seq 1 251`; do + ditto $i table$i 1000000 + done + tail_tables) > expout +AT_CHECK([ovs-ofctl -O OpenFlow15 dump-table-features br0], [0], [expout]) +# Set first egress table. +ovs-ofctl -O Openflow15 set-first-egress-table br0 251 + +# Check that the configuration was updated. +(head_table classifier + for i in `seq 1 250`; do + ditto $i table$i 1000000 + done + first_egress_table + tail_tables) > expout +AT_CHECK([ovs-ofctl -O OpenFlow15 dump-table-features br0], [0], [expout]) +OVS_VSWITCHD_STOP +AT_CLEANUP + AT_SETUP([ofproto - table description (OpenFlow 1.4)]) OVS_VSWITCHD_START (x=0 diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c index 96d6c89..106fdde 100644 --- a/utilities/ovs-ofctl.c +++ b/utilities/ovs-ofctl.c @@ -343,6 +343,7 @@ usage(void) " dump-desc SWITCH print switch description\n" " dump-tables SWITCH print table stats\n" " dump-table-features SWITCH print table features\n" + " set-first-egress-table SWITCH TABLE set first egress table\n" " dump-table-desc SWITCH print table description (OF1.4+)\n" " mod-port SWITCH IFACE ACT modify port behavior\n" " mod-table SWITCH MOD modify flow table behavior\n" @@ -713,9 +714,9 @@ ofctl_dump_table_features(struct ovs_cmdl_context *ctx) { struct ofpbuf *request; struct vconn *vconn; - + struct ofputil_table_features *tf = NULL; open_vconn(ctx->argv[1], &vconn); - request = ofputil_encode_table_features_request(vconn_get_version(vconn)); + request = ofputil_encode_table_features_request(tf, vconn_get_version(vconn)); /* The following is similar to dump_trivial_transaction(), but it * maintains the previous 'ofputil_table_features' from one stats reply @@ -788,6 +789,35 @@ ofctl_dump_table_features(struct ovs_cmdl_context *ctx) } static void +ofctl_set_first_egress_table(struct ovs_cmdl_context *ctx) +{ + uint32_t usable_versions; + struct ofputil_table_features tf; + struct vconn *vconn; + char *error; + + error = parse_ofp_table_features(&tf, ctx->argv[2], &usable_versions); + if (error) { + ovs_fatal(0, "%s", error); + } + + uint32_t allowed_versions = get_allowed_ofp_versions(); + if (!(allowed_versions & usable_versions)) { + struct ds versions = DS_EMPTY_INITIALIZER; + ofputil_format_version_bitmap_names(&versions, usable_versions); + ovs_fatal(0, "set_first_egress_table '%s' requires one of the OpenFlow " + "versions %s (use -O)", + ctx->argv[2], ds_cstr(&versions)); + } + mask_allowed_ofp_versions(usable_versions); + + open_vconn(ctx->argv[1], &vconn); + transact_noreply(vconn, ofputil_encode_table_features_request(&tf, + vconn_get_version(vconn))); + vconn_close(vconn); +} + +static void ofctl_dump_table_desc(struct ovs_cmdl_context *ctx) { struct ofpbuf *request; @@ -3875,6 +3905,8 @@ static const struct ovs_cmdl_command all_commands[] = { 1, 1, ofctl_dump_tables }, { "dump-table-features", "switch", 1, 1, ofctl_dump_table_features }, + { "set-first-egress-table", "switch table", + 2, 2, ofctl_set_first_egress_table }, { "dump-table-desc", "switch", 1, 1, ofctl_dump_table_desc }, { "dump-flows", "switch",