[ovs-dev,02/10] userspace: Add bridge property 'packet-type-aware'

Submitted by Zoltán Balogh on April 18, 2017, 11:19 a.m.

Details

Message ID AM2PR07MB10422070F2542AA041A921C38A190@AM2PR07MB1042.eurprd07.prod.outlook.com
State Deferred
Headers show

Commit Message

Zoltán Balogh April 18, 2017, 11:19 a.m.
From: Jan Scheurich <jan.scheurich@ericsson.com>

New boolean parmeter "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.

Signed-off-by: Jan Scheurich <jan.scheurich@ericsson.com>
---
 ofproto/ofproto-dpif-xlate.c | 33 +++++++++++++++++++++------------
 ofproto/ofproto-dpif-xlate.h |  1 +
 ofproto/ofproto-dpif.c       |  1 +
 ofproto/ofproto-provider.h   |  1 +
 ofproto/ofproto.c            |  6 ++++++
 ofproto/ofproto.h            |  1 +
 vswitchd/bridge.c            |  9 +++++++++
 vswitchd/vswitch.xml         |  8 ++++++++
 8 files changed, 48 insertions(+), 12 deletions(-)

Patch hide | download patch | download mbox

diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
index 9a5a878..6dd8a07 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;
@@ -553,6 +554,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,
@@ -813,6 +815,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) {
@@ -858,6 +861,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;
 }
 
@@ -948,7 +952,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);
     }
@@ -1100,6 +1104,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;
@@ -1118,7 +1123,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
@@ -3504,16 +3509,20 @@  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;
 
-    if (flow->packet_type == htonl(PT_ETH) && xport->is_layer3 ) {
-        /* Ethernet packet to L3 outport -> pop ethernet header. */
-        flow->packet_type = htonl(PACKET_TYPE(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;
+    /* 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)) {
diff --git a/ofproto/ofproto-dpif-xlate.h b/ofproto/ofproto-dpif-xlate.h
index 12abfa3..78fa108 100644
--- a/ofproto/ofproto-dpif-xlate.h
+++ b/ofproto/ofproto-dpif-xlate.h
@@ -163,6 +163,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 8a059b2..66cb180 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 b7b12cd..2286814 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 7440d5b..81fe02a 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -782,6 +782,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)
 {
diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h
index 1e48e19..02f81cc 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/vswitchd/bridge.c b/vswitchd/bridge.c
index 867a26d..dcdac35 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);
 
@@ -3799,6 +3801,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 3233126..24807e3 100644
--- a/vswitchd/vswitch.xml
+++ b/vswitchd/vswitch.xml
@@ -854,6 +854,14 @@ 
         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.
+      </column>
+
       <column name="protocols">
         <p>
           List of OpenFlow protocols that may be used when negotiating