This is an proposed enhancement to
"Implement OpenFlow support for MPLS, for up to 3 labels."

It is in preparation for not adding flows to the datapath
which have more MPLS LSEs than the datapath supports.

Signed-off-by: Simon Horman <ho...@verge.net.au>
---
 ofproto/ofproto-dpif.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 59 insertions(+)

diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index 62c1e4c..6da8e5c 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -256,6 +256,10 @@ struct dpif_backer {
      * OVS_USERSPACE_ATTR_USERDATA in OVS_ACTION_ATTR_USERSPACE actions.
      * False if the datapath supports only 8-byte (or shorter) userdata. */
     bool variable_length_userdata;
+
+    /* Maximum number of MPLS label stack entries that the datapath supports
+     * in a match */
+    size_t max_mpls_depth;
 };
 
 /* All existing ofproto_backer instances, indexed by ofproto->up.type. */
@@ -781,6 +785,7 @@ struct odp_garbage {
 };
 
 static bool check_variable_length_userdata(struct dpif_backer *backer);
+static size_t check_max_mpls_depth(struct dpif_backer *backer);
 
 static int
 open_dpif_backer(const char *type, struct dpif_backer **backerp)
@@ -881,6 +886,7 @@ open_dpif_backer(const char *type, struct dpif_backer 
**backerp)
         return error;
     }
     backer->variable_length_userdata = check_variable_length_userdata(backer);
+    backer->max_mpls_depth = check_max_mpls_depth(backer);
 
     if (backer->recv_set_enable) {
         udpif_set_threads(backer->udpif, n_handlers, n_revalidators);
@@ -965,6 +971,59 @@ check_variable_length_userdata(struct dpif_backer *backer)
     }
 }
 
+/* Tests the MPLS label stack depth supported by 'backer''s datapath.
+ *
+ * Returns the number of elements in a struct flow's mpls_lse field
+ * if the datapath supports at least that many entries in an
+ * MPLS label stack.
+ * Otherwise returns the number of MPLS push actions supported by
+ * the datapath. */
+static size_t
+check_max_mpls_depth(struct dpif_backer *backer)
+{
+    size_t i;
+    struct flow flow;
+    int error;
+
+    /* If ARRAY_SIZE(flow.mpls_lse) becomes large then it might
+     * make more sense to do a binary search here. */
+    for (i = ARRAY_SIZE(flow.mpls_lse) - 1; i > 0; i--) {
+        struct odputil_keybuf keybuf;
+        struct ofpbuf key;
+
+        memset(&flow, 0, sizeof flow);
+        flow.dl_type = htons(ETH_TYPE_MPLS);
+        flow_set_mpls_bos(&flow, ARRAY_SIZE(flow.mpls_lse) - 1, 1);
+
+        ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
+        odp_flow_key_from_flow(&key, &flow, 0);
+
+        error = dpif_flow_put(backer->dpif, DPIF_FP_CREATE, key.data, key.size,
+                              NULL, 0, NULL, 0, NULL);
+        if (!error) {
+            error = dpif_flow_del(backer->dpif, key.data, key.size, NULL);
+            if (error) {
+                goto err;
+            }
+            i++;
+            break;
+        } else if (error != EINVAL) {
+            goto err;
+        }
+    }
+
+    VLOG_INFO("%s: MPLS label stack length probed as %"PRIuSIZE,
+              dpif_name(backer->dpif), i);
+    return i;
+
+err:
+    /* Something odd happened.  We're not sure how large an
+     * MPLS label stack the datapath supports. Default to 0. */
+    VLOG_WARN("%s: mpls stack length feature probe failed (%s)",
+              dpif_name(backer->dpif), ovs_strerror(error));
+    return 0;
+}
+
 static int
 construct(struct ofproto *ofproto_)
 {
-- 
1.8.4

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to