[ovs-dev] [PATCH v3 2/6] userspace: Add bridge property 'packet-type-aware'
Zoltán Balogh
zoltan.balogh at ericsson.com
Fri Jun 2 16:28:58 UTC 2017
From: Jan Scheurich <jan.scheurich at ericsson.com>
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 <jan.scheurich at ericsson.com>
---
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 9657dc01f..0cde69981 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 90cb6f8fd..fa995a167 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 e682e2f6f..63b9d5c1c 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 68e114afb..69eda23c5 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 8d90446ed..309b59ccf 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 9dc73c482..fbf3bdaea 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 a75d41411..de30d3b7b 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)
{
@@ -3209,8 +3215,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;
@@ -4711,6 +4717,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;
@@ -4751,8 +4758,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 1e48e1952..02f81ccf0 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 25aa00aff..76a33b690 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 cc7a43b65..ac9550f37 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 bf0211909..19c12739c 100644
--- a/vswitchd/vswitch.xml
+++ b/vswitchd/vswitch.xml
@@ -855,6 +855,15 @@
ID, the default queue is used instead.
</column>
+ <column name="other_config" key="packet-type-aware"
+ type='{"type": "boolean"}'>
+ If set to <code>true</code>, 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.
+ </column>
+
<column name="protocols">
<p>
List of OpenFlow protocols that may be used when negotiating
--
2.11.0
More information about the dev
mailing list