From patchwork Mon Jun 12 22:28:33 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 774859 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org 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 3wmnjF32vfz9s06 for ; Tue, 13 Jun 2017 08:33:05 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id B2DC9C3C; Mon, 12 Jun 2017 22:29:23 +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 3B9A9BA2 for ; Mon, 12 Jun 2017 22:29:22 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 140191A4 for ; Mon, 12 Jun 2017 22:29:20 +0000 (UTC) Received: from mfilter18-d.gandi.net (mfilter18-d.gandi.net [217.70.178.146]) by relay6-d.mail.gandi.net (Postfix) with ESMTP id F3D94FB8AC; Tue, 13 Jun 2017 00:29:18 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at mfilter18-d.gandi.net Received: from relay6-d.mail.gandi.net ([IPv6:::ffff:217.70.183.198]) by mfilter18-d.gandi.net (mfilter18-d.gandi.net [::ffff:10.0.15.180]) (amavisd-new, port 10024) with ESMTP id MJtjFvvJjyq9; Tue, 13 Jun 2017 00:29:17 +0200 (CEST) X-Originating-IP: 208.91.2.3 Received: from sigabrt.benpfaff.org (unknown [208.91.2.3]) (Authenticated sender: blp@ovn.org) by relay6-d.mail.gandi.net (Postfix) with ESMTPSA id C364AFB87D; Tue, 13 Jun 2017 00:29:15 +0200 (CEST) From: Ben Pfaff To: dev@openvswitch.org Date: Mon, 12 Jun 2017 15:28:33 -0700 Message-Id: <20170612222856.14108-9-blp@ovn.org> X-Mailer: git-send-email 2.10.2 In-Reply-To: <20170612222856.14108-1-blp@ovn.org> References: <20170612222856.14108-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 08/31] userspace: Add bridge property 'packet-type-aware' 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 From: Jan Scheurich New boolean parameter "other-config:packet-type-aware' in bridge table. Pass non-Ethernet packets unchanged into packet-type-aware bridges. Do not convert packet type when sending packet from packet-type-aware bridge to a port. Only include field MFF_PACKET_TYPE in matchabale and maskable fields if the ofproto bridge is packet-type-aware. Add default match on packet_type Ethernet in case of packet-type-aware bridge. Reject packet_type match in case of non-ptap bridge. Removed packet_type from list of matching properties in tests/ofproto.at. Signed-off-by: Jan Scheurich Signed-off-by: Ben Pfaff --- lib/nx-match.c | 10 ++++++++-- lib/nx-match.h | 4 ++-- ofproto/ofproto-dpif-xlate.c | 36 +++++++++++++++++++++++------------- ofproto/ofproto-dpif-xlate.h | 1 + ofproto/ofproto-dpif.c | 1 + ofproto/ofproto-provider.h | 1 + ofproto/ofproto.c | 26 +++++++++++++++++++++++--- ofproto/ofproto.h | 1 + tests/ofproto.at | 1 - vswitchd/bridge.c | 9 +++++++++ vswitchd/vswitch.xml | 9 +++++++++ 11 files changed, 78 insertions(+), 21 deletions(-) diff --git a/lib/nx-match.c b/lib/nx-match.c index 7284f2213817..47552bfb0125 100644 --- a/lib/nx-match.c +++ b/lib/nx-match.c @@ -2083,12 +2083,15 @@ oxm_writable_fields(void) /* Returns a bitmap of fields that can be encoded in OXM and that can be * matched in a flow table. */ struct mf_bitmap -oxm_matchable_fields(void) +oxm_matchable_fields(bool packet_type_aware) { struct mf_bitmap b = MF_BITMAP_INITIALIZER; int i; for (i = 0; i < MFF_N_IDS; i++) { + if (i == MFF_PACKET_TYPE && !packet_type_aware) { + continue; + } if (mf_oxm_header(i, 0)) { bitmap_set1(b.bm, i); } @@ -2099,12 +2102,15 @@ oxm_matchable_fields(void) /* Returns a bitmap of fields that can be encoded in OXM and that can be * matched in a flow table with an arbitrary bitmask. */ struct mf_bitmap -oxm_maskable_fields(void) +oxm_maskable_fields(bool packet_type_aware) { struct mf_bitmap b = MF_BITMAP_INITIALIZER; int i; for (i = 0; i < MFF_N_IDS; i++) { + if (i == MFF_PACKET_TYPE && !packet_type_aware) { + continue; + } if (mf_oxm_header(i, 0) && mf_from_id(i)->maskable == MFM_FULLY) { bitmap_set1(b.bm, i); } diff --git a/lib/nx-match.h b/lib/nx-match.h index 90cb6f8fd329..fa995a16729b 100644 --- a/lib/nx-match.h +++ b/lib/nx-match.h @@ -149,8 +149,8 @@ ovs_be64 oxm_bitmap_from_mf_bitmap(const struct mf_bitmap *, enum ofp_version); struct mf_bitmap oxm_bitmap_to_mf_bitmap(ovs_be64 oxm_bitmap, enum ofp_version); struct mf_bitmap oxm_writable_fields(void); -struct mf_bitmap oxm_matchable_fields(void); -struct mf_bitmap oxm_maskable_fields(void); +struct mf_bitmap oxm_matchable_fields(bool packet_type_aware); +struct mf_bitmap oxm_maskable_fields(bool packet_type_aware); /* Dealing with the 'ofs_nbits' members in several Nicira extensions. */ diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index a94e9f689c1b..6f70f85947e2 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -108,6 +108,7 @@ struct xbridge { bool has_in_band; /* Bridge has in band control? */ bool forward_bpdu; /* Bridge forwards STP BPDUs? */ + bool packet_type_aware; /* Bridge is packet-type-aware? */ /* Datapath feature support. */ struct dpif_backer_support support; @@ -555,6 +556,7 @@ static void xlate_xbridge_set(struct xbridge *, struct dpif *, const struct dpif_ipfix *, const struct netflow *, bool forward_bpdu, bool has_in_band, + bool packet_type_aware, const struct dpif_backer_support *); static void xlate_xbundle_set(struct xbundle *xbundle, enum port_vlan_mode vlan_mode, @@ -815,6 +817,7 @@ xlate_xbridge_set(struct xbridge *xbridge, const struct dpif_ipfix *ipfix, const struct netflow *netflow, bool forward_bpdu, bool has_in_band, + bool packet_type_aware, const struct dpif_backer_support *support) { if (xbridge->ml != ml) { @@ -860,6 +863,7 @@ xlate_xbridge_set(struct xbridge *xbridge, xbridge->dpif = dpif; xbridge->forward_bpdu = forward_bpdu; xbridge->has_in_band = has_in_band; + xbridge->packet_type_aware = packet_type_aware; xbridge->support = *support; } @@ -950,7 +954,7 @@ xlate_xbridge_copy(struct xbridge *xbridge) xbridge->rstp, xbridge->ms, xbridge->mbridge, xbridge->sflow, xbridge->ipfix, xbridge->netflow, xbridge->forward_bpdu, xbridge->has_in_band, - &xbridge->support); + xbridge->packet_type_aware, &xbridge->support); LIST_FOR_EACH (xbundle, list_node, &xbridge->xbundles) { xlate_xbundle_copy(new_xbridge, xbundle); } @@ -1102,6 +1106,7 @@ xlate_ofproto_set(struct ofproto_dpif *ofproto, const char *name, const struct dpif_ipfix *ipfix, const struct netflow *netflow, bool forward_bpdu, bool has_in_band, + bool packet_type_aware, const struct dpif_backer_support *support) { struct xbridge *xbridge; @@ -1120,7 +1125,7 @@ xlate_ofproto_set(struct ofproto_dpif *ofproto, const char *name, xbridge->name = xstrdup(name); xlate_xbridge_set(xbridge, dpif, ml, stp, rstp, ms, mbridge, sflow, ipfix, - netflow, forward_bpdu, has_in_band, support); + netflow, forward_bpdu, has_in_band, packet_type_aware, support); } static void @@ -3351,17 +3356,6 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port, return; } - if (flow->packet_type == htonl(PT_ETH) && xport->is_layer3) { - /* Ethernet packet to L3 outport -> pop ethernet header. */ - flow->packet_type = PACKET_TYPE_BE(OFPHTN_ETHERTYPE, - ntohs(flow->dl_type)); - } else if (flow->packet_type != htonl(PT_ETH) && !xport->is_layer3) { - /* L2 outport and non-ethernet packet_type -> add dummy eth header. */ - flow->packet_type = htonl(PT_ETH); - flow->dl_dst = eth_addr_zero; - flow->dl_src = eth_addr_zero; - } - if (xport->peer) { const struct xport *peer = xport->peer; struct flow old_flow = ctx->xin->flow; @@ -3502,6 +3496,22 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port, memcpy(flow_vlans, flow->vlans, sizeof flow_vlans); flow_nw_tos = flow->nw_tos; + /* In a bridge that is not packet type-aware convert the packet to what + * the output port expects. */ + if (!ctx->xbridge->packet_type_aware) { + if (flow->packet_type == htonl(PT_ETH) && xport->is_layer3 ) { + /* Ethernet packet to L3 outport -> pop ethernet header. */ + flow->packet_type = PACKET_TYPE_BE(OFPHTN_ETHERTYPE, + ntohs(flow->dl_type)); + } + else if (flow->packet_type != htonl(PT_ETH) && !xport->is_layer3) { + /* L2 outport and non-ethernet packet_type -> add dummy eth header. */ + flow->packet_type = htonl(PT_ETH); + flow->dl_dst = eth_addr_zero; + flow->dl_src = eth_addr_zero; + } + } + if (count_skb_priorities(xport)) { memset(&wc->masks.skb_priority, 0xff, sizeof wc->masks.skb_priority); if (dscp_from_skb_priority(xport, flow->skb_priority, &dscp)) { diff --git a/ofproto/ofproto-dpif-xlate.h b/ofproto/ofproto-dpif-xlate.h index 68e114afb9ae..69eda23c5a37 100644 --- a/ofproto/ofproto-dpif-xlate.h +++ b/ofproto/ofproto-dpif-xlate.h @@ -166,6 +166,7 @@ void xlate_ofproto_set(struct ofproto_dpif *, const char *name, struct dpif *, const struct mbridge *, const struct dpif_sflow *, const struct dpif_ipfix *, const struct netflow *, bool forward_bpdu, bool has_in_band, + bool packet_type_aware, const struct dpif_backer_support *support); void xlate_remove_ofproto(struct ofproto_dpif *); diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index cca6c52b2de0..752d2304a163 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -446,6 +446,7 @@ type_run(const char *type) ofproto->netflow, ofproto->up.forward_bpdu, connmgr_has_in_band(ofproto->up.connmgr), + ofproto->up.packet_type_aware, &ofproto->backer->support); HMAP_FOR_EACH (bundle, hmap_node, &ofproto->bundles) { diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h index 9dc73c482119..fbf3bdaeac8d 100644 --- a/ofproto/ofproto-provider.h +++ b/ofproto/ofproto-provider.h @@ -85,6 +85,7 @@ struct ofproto { char *serial_desc; /* Serial number (NULL for default). */ char *dp_desc; /* Datapath description (NULL for default). */ enum ofputil_frag_handling frag_handling; + bool packet_type_aware; /* Supports packet-type aware pipeline */ /* Datapath. */ struct hmap ports; /* Contains "struct ofport"s. */ diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index ad94db514c47..67aaa755f10e 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -784,6 +784,12 @@ ofproto_set_dp_desc(struct ofproto *p, const char *dp_desc) p->dp_desc = nullable_xstrdup(dp_desc); } +void +ofproto_set_packet_type_aware(struct ofproto *p, bool pta) +{ + p->packet_type_aware = pta; +} + int ofproto_set_snoops(struct ofproto *ofproto, const struct sset *snoops) { @@ -3208,8 +3214,8 @@ query_tables(struct ofproto *ofproto, struct ofputil_table_stats **statsp) { struct mf_bitmap rw_fields = oxm_writable_fields(); - struct mf_bitmap match = oxm_matchable_fields(); - struct mf_bitmap mask = oxm_maskable_fields(); + struct mf_bitmap match = oxm_matchable_fields(ofproto->packet_type_aware); + struct mf_bitmap mask = oxm_maskable_fields(ofproto->packet_type_aware); struct ofputil_table_features *features; struct ofputil_table_stats *stats; @@ -4710,6 +4716,7 @@ add_flow_init(struct ofproto *ofproto, struct ofproto_flow_mod *ofm, OVS_EXCLUDED(ofproto_mutex) { struct oftable *table; + struct match match = fm->match; struct cls_rule cr; uint8_t table_id; enum ofperr error; @@ -4750,8 +4757,21 @@ add_flow_init(struct ofproto *ofproto, struct ofproto_flow_mod *ofm, return OFPERR_OFPBRC_EPERM; } + if (ofproto->packet_type_aware) { + if (!match.wc.masks.packet_type) { + /* Add default match on packet_type Ethernet.*/ + match.flow.packet_type = htonl(PT_ETH); + match.wc.masks.packet_type = OVS_BE32_MAX; + } + } else { + if (match.wc.masks.packet_type) { + /* Match on packet_type not allowed. */ + return OFPERR_OFPBMC_BAD_TYPE; + } + } + if (!ofm->temp_rule) { - cls_rule_init(&cr, &fm->match, fm->priority); + cls_rule_init(&cr, &match, fm->priority); /* Allocate new rule. Destroys 'cr'. */ error = ofproto_rule_create(ofproto, &cr, table - ofproto->tables, diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h index 1e48e1952aa2..02f81ccf06c6 100644 --- a/ofproto/ofproto.h +++ b/ofproto/ofproto.h @@ -325,6 +325,7 @@ void ofproto_set_threads(int n_handlers, int n_revalidators); void ofproto_type_set_config(const char *type, const struct smap *other_config); void ofproto_set_dp_desc(struct ofproto *, const char *dp_desc); +void ofproto_set_packet_type_aware(struct ofproto *p, bool pta); int ofproto_set_snoops(struct ofproto *, const struct sset *snoops); int ofproto_set_netflow(struct ofproto *, const struct netflow_options *nf_options); diff --git a/tests/ofproto.at b/tests/ofproto.at index 25aa00aff4a2..76a33b6902aa 100644 --- a/tests/ofproto.at +++ b/tests/ofproto.at @@ -2390,7 +2390,6 @@ metadata in_port in_port_oxm pkt_mark ct_mark ct_label reg0 reg1 reg2 reg3 reg4 matching: dp_hash: arbitrary mask recirc_id: exact match or wildcard - packet_type: exact match or wildcard conj_id: exact match or wildcard tun_id: arbitrary mask tun_src: arbitrary mask diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index cc7a43b65112..ac9550f37fc7 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -254,6 +254,7 @@ static void bridge_configure_ipfix(struct bridge *); static void bridge_configure_spanning_tree(struct bridge *); static void bridge_configure_tables(struct bridge *); static void bridge_configure_dp_desc(struct bridge *); +static void bridge_configure_packet_type_aware(struct bridge *); static void bridge_configure_aa(struct bridge *); static void bridge_aa_refresh_queued(struct bridge *); static bool bridge_aa_need_refresh(struct bridge *); @@ -708,6 +709,7 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg) bridge_configure_tables(br); bridge_configure_dp_desc(br); bridge_configure_aa(br); + bridge_configure_packet_type_aware(br); } free(managers); @@ -3801,6 +3803,13 @@ bridge_configure_dp_desc(struct bridge *br) smap_get(&br->cfg->other_config, "dp-desc")); } +static void +bridge_configure_packet_type_aware(struct bridge *br) +{ + ofproto_set_packet_type_aware(br->ofproto, + smap_get_bool(&br->cfg->other_config, "packet-type-aware", false)); +} + static struct aa_mapping * bridge_aa_mapping_find(struct bridge *br, const int64_t isid) { diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml index d219bfd68204..829c13688f31 100644 --- a/vswitchd/vswitch.xml +++ b/vswitchd/vswitch.xml @@ -855,6 +855,15 @@ ID, the default queue is used instead. + + If set to true, the bridge supports the packet type awareness + feature introduced in OpenFlow version 1.5. The bridge can switch Ethernet + and non-Ethernet packets and a controller must consider the type and match + on the packet_type match field as appropriate. OVS does support the packet- + type-aware property from OpenFlow version 1.3. + +

List of OpenFlow protocols that may be used when negotiating