+/* 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)
+{
+ struct flow flow;
+ int n;
+
+ for (n = 0; n < FLOW_MAX_MPLS_LABELS; n++) {
+ struct odputil_keybuf keybuf;
+ struct ofpbuf key;
+ int error;
+
+ memset(&flow, 0, sizeof flow);
+ flow.dl_type = htons(ETH_TYPE_MPLS);
+ flow_set_mpls_bos(&flow, n, 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 | DPIF_FP_MODIFY,
+ key.data, key.size, NULL, 0, NULL, 0, NULL);
+ if (error && error != EEXIST) {
+ if (error != EINVAL) {
+ VLOG_WARN("%s: MPLS stack length feature probe failed (%s)",
+ dpif_name(backer->dpif), ovs_strerror(error));
+ }
+ break;
+ }
+
+ error = dpif_flow_del(backer->dpif, key.data, key.size, NULL);
+ if (error) {
+ VLOG_WARN("%s: failed to delete MPLS feature probe flow",
+ dpif_name(backer->dpif));
+ }
+ }
+
+ VLOG_INFO("%s: MPLS label stack length probed as %d",
+ dpif_name(backer->dpif), n);
+ return n;
+}
+