[ovs-dev] [PATCH 2/2] datapath-windows: Accept MPLS feature probe.

Sorin Vinturis svinturis at cloudbasesolutions.com
Mon Dec 21 19:12:11 UTC 2015


Currently all feature probe messages sent from userspace are
suppressed by the OVS extension.

This patch changes the current behaviour to allow feature probe
for MPLS.

Signed-off-by: Sorin Vinturis <svinturis at cloudbasesolutions.com>
---
 datapath-windows/ovsext/Flow.c                 | 136 ++++++++++++++++---------
 datapath-windows/ovsext/Mpls.h                 |  24 +++++
 datapath-windows/ovsext/Netlink/NetlinkError.h |   3 +
 3 files changed, 116 insertions(+), 47 deletions(-)

diff --git a/datapath-windows/ovsext/Flow.c b/datapath-windows/ovsext/Flow.c
index 99a89e6..a0f91c6 100644
--- a/datapath-windows/ovsext/Flow.c
+++ b/datapath-windows/ovsext/Flow.c
@@ -46,7 +46,9 @@ static VOID DeleteAllFlows(OVS_DATAPATH *datapath);
 static NTSTATUS AddFlow(OVS_DATAPATH *datapath, OvsFlow *flow);
 static VOID FreeFlow(OvsFlow *flow);
 static VOID __inline *GetStartAddrNBL(const NET_BUFFER_LIST *_pNB);
-static NTSTATUS _MapNlToFlowPut(POVS_MESSAGE msgIn, PNL_ATTR keyAttr,
+static NTSTATUS _MapNlToFlowPut(POVS_MESSAGE msgIn,
+                                PNL_ATTR* keyAttrs,
+                                PNL_ATTR* tunnelAttrs,
                                 PNL_ATTR actionAttr,
                                 PNL_ATTR flowAttrClear,
                                 OvsFlowPut *mappedFlow);
@@ -86,6 +88,7 @@ static NTSTATUS _MapFlowMplsKeyToNlKey(PNL_BUFFER nlBuf,
 static NTSTATUS OvsDoDumpFlows(OvsFlowDumpInput *dumpInput,
                                OvsFlowDumpOutput *dumpOutput,
                                UINT32 *replyLen);
+static NTSTATUS OvsProbeSupportedFeature(PNL_ATTR *keyAttr);
 
 
 #define OVS_FLOW_TABLE_SIZE 2048
@@ -256,8 +259,12 @@ OvsFlowNlCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
     PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
     PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
     POVS_HDR ovsHdr = &(msgIn->ovsHdr);
-    PNL_ATTR flowAttrs[__OVS_FLOW_ATTR_MAX];
+    PNL_ATTR flowAttrs[__OVS_FLOW_ATTR_MAX] = { NULL };
+    PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX] = { NULL };
+    PNL_ATTR tunnelAttrs[__OVS_TUNNEL_KEY_ATTR_MAX] = { NULL };
     UINT32 attrOffset = NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN;
+    UINT32 keyAttrOffset = 0;
+    UINT32 tunnelKeyAttrOffset = 0;
     OvsFlowPut mappedFlow;
     OvsFlowStats stats;
     struct ovs_flow_stats replyStats;
@@ -312,14 +319,52 @@ OvsFlowNlCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
        goto done;
     }
 
-    if (flowAttrs[OVS_FLOW_ATTR_PROBE]) {
-        OVS_LOG_ERROR("Attribute OVS_FLOW_ATTR_PROBE not supported");
+    keyAttrOffset = (UINT32)((PCHAR)flowAttrs[OVS_FLOW_ATTR_KEY] -
+                    (PCHAR)nlMsgHdr);
+
+    /* Get flow keys attributes */
+    if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset,
+        NlAttrLen(flowAttrs[OVS_FLOW_ATTR_KEY]),
+        nlFlowKeyPolicy, ARRAY_SIZE(nlFlowKeyPolicy),
+        keyAttrs, ARRAY_SIZE(keyAttrs)))
+        != TRUE) {
+        OVS_LOG_ERROR("Key Attr Parsing failed for msg: %p",
+                      nlMsgHdr);
+        rc = STATUS_INVALID_PARAMETER;
         goto done;
     }
 
-    if ((rc = _MapNlToFlowPut(msgIn, flowAttrs[OVS_FLOW_ATTR_KEY],
-        flowAttrs[OVS_FLOW_ATTR_ACTIONS], flowAttrs[OVS_FLOW_ATTR_CLEAR],
-         &mappedFlow))
+    if (flowAttrs[OVS_FLOW_ATTR_PROBE]) {
+        rc = OvsProbeSupportedFeature(keyAttrs);
+        if (rc != STATUS_SUCCESS) {
+            nlError = NlMapStatusToNlErr(rc);
+            goto done;
+        }
+    }
+
+    if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
+        tunnelKeyAttrOffset = (UINT32)((PCHAR)
+            (keyAttrs[OVS_KEY_ATTR_TUNNEL])
+            - (PCHAR)nlMsgHdr);
+
+        /* Get tunnel keys attributes */
+        if ((NlAttrParseNested(nlMsgHdr, tunnelKeyAttrOffset,
+            NlAttrLen(keyAttrs[OVS_KEY_ATTR_TUNNEL]),
+            nlFlowTunnelKeyPolicy,
+            ARRAY_SIZE(nlFlowTunnelKeyPolicy),
+            tunnelAttrs, ARRAY_SIZE(tunnelAttrs)))
+            != TRUE) {
+            OVS_LOG_ERROR("Tunnel key Attr Parsing failed for msg: %p",
+                          nlMsgHdr);
+            rc = STATUS_INVALID_PARAMETER;
+            goto done;
+        }
+    }
+
+    if ((rc = _MapNlToFlowPut(msgIn, keyAttrs, tunnelAttrs,
+                              flowAttrs[OVS_FLOW_ATTR_ACTIONS],
+                              flowAttrs[OVS_FLOW_ATTR_CLEAR],
+                              &mappedFlow))
         != STATUS_SUCCESS) {
         OVS_LOG_ERROR("Conversion to OvsFlowPut failed");
         goto done;
@@ -1233,51 +1278,14 @@ done:
  *----------------------------------------------------------------------------
  */
 static NTSTATUS
-_MapNlToFlowPut(POVS_MESSAGE msgIn, PNL_ATTR keyAttr,
+_MapNlToFlowPut(POVS_MESSAGE msgIn, PNL_ATTR* keyAttrs, PNL_ATTR* tunnelAttrs,
                 PNL_ATTR actionAttr, PNL_ATTR flowAttrClear,
                 OvsFlowPut *mappedFlow)
 {
     NTSTATUS rc = STATUS_SUCCESS;
-    PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
     PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
     POVS_HDR ovsHdr = &(msgIn->ovsHdr);
 
-    UINT32 keyAttrOffset = (UINT32)((PCHAR)keyAttr - (PCHAR)nlMsgHdr);
-    UINT32 tunnelKeyAttrOffset;
-
-    PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX] = {NULL};
-    PNL_ATTR tunnelAttrs[__OVS_TUNNEL_KEY_ATTR_MAX] = {NULL};
-
-    /* Get flow keys attributes */
-    if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset, NlAttrLen(keyAttr),
-                           nlFlowKeyPolicy, ARRAY_SIZE(nlFlowKeyPolicy),
-                           keyAttrs, ARRAY_SIZE(keyAttrs)))
-                           != TRUE) {
-        OVS_LOG_ERROR("Key Attr Parsing failed for msg: %p",
-                       nlMsgHdr);
-        rc = STATUS_INVALID_PARAMETER;
-        goto done;
-    }
-
-    if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
-        tunnelKeyAttrOffset = (UINT32)((PCHAR)
-                              (keyAttrs[OVS_KEY_ATTR_TUNNEL])
-                              - (PCHAR)nlMsgHdr);
-
-        /* Get tunnel keys attributes */
-        if ((NlAttrParseNested(nlMsgHdr, tunnelKeyAttrOffset,
-                               NlAttrLen(keyAttrs[OVS_KEY_ATTR_TUNNEL]),
-                               nlFlowTunnelKeyPolicy,
-                               ARRAY_SIZE(nlFlowTunnelKeyPolicy),
-                               tunnelAttrs, ARRAY_SIZE(tunnelAttrs)))
-                               != TRUE) {
-            OVS_LOG_ERROR("Tunnel key Attr Parsing failed for msg: %p",
-                           nlMsgHdr);
-            rc = STATUS_INVALID_PARAMETER;
-            goto done;
-        }
-    }
-
     _MapKeyAttrToFlowPut(keyAttrs, tunnelAttrs,
                          &(mappedFlow->key));
 
@@ -1290,9 +1298,8 @@ _MapNlToFlowPut(POVS_MESSAGE msgIn, PNL_ATTR keyAttr,
     mappedFlow->dpNo = ovsHdr->dp_ifindex;
 
     _MapNlToFlowPutFlags(genlMsgHdr, flowAttrClear,
-                                mappedFlow);
+                         mappedFlow);
 
-done:
     return rc;
 }
 
@@ -2520,4 +2527,39 @@ OvsTunKeyAttrSize(void)
          + NlAttrTotalSize(2);   /* OVS_TUNNEL_KEY_ATTR_TP_DST */
 }
 
+/*
+ *----------------------------------------------------------------------------
+ *  OvsProbeSupportedFeature --
+ *    Verifies if the probed feature is supported.
+ * 
+ * Results:
+ *   STATUS_SUCCESS if the probed feature is supported.
+ *----------------------------------------------------------------------------
+ */
+static NTSTATUS
+OvsProbeSupportedFeature(PNL_ATTR *keyAttrs)
+{
+    NTSTATUS status = STATUS_SUCCESS;
+    
+    if (keyAttrs[OVS_KEY_ATTR_MPLS] &&
+        keyAttrs[OVS_KEY_ATTR_ETHERTYPE]) {
+        ovs_be16 ethType = NlAttrGetU16(keyAttrs[OVS_KEY_ATTR_ETHERTYPE]);
+
+        if (OvsEthertypeIsMpls(ethType)) {
+            if (!OvsCountMplsLabels(keyAttrs[OVS_KEY_ATTR_MPLS])) {
+                OVS_LOG_ERROR("Maximum supported MPLS labels exceeded.");
+                status = STATUS_INVALID_MESSAGE;
+            }
+        } else {
+            OVS_LOG_ERROR("Wrong ethertype for MPLS attribute.");
+            status = STATUS_INVALID_PARAMETER;
+        }
+    } else {
+        OVS_LOG_ERROR("Probed feature not supported.");
+        status = STATUS_NOT_SUPPORTED;
+    }
+
+    return status;
+}
+
 #pragma warning( pop )
diff --git a/datapath-windows/ovsext/Mpls.h b/datapath-windows/ovsext/Mpls.h
index 3508233..4b5c30c 100644
--- a/datapath-windows/ovsext/Mpls.h
+++ b/datapath-windows/ovsext/Mpls.h
@@ -60,4 +60,28 @@ OvsEthertypeIsMpls(ovs_be16 ethertype)
            ethertype == htons(ETH_TYPE_MPLS_MCAST);
 }
 
+/* Returns the number of MPLS LSEs present in 'a'
+ *
+ * Counts 'flow''s MPLS label stack entries (LESs) stopping at the first
+ * entry that has the bottom of stack (BOS) bit set. If no such entry exists,
+ * then zero is returned, meaning that the maximum number of supported
+ * MPLS LSEs exceeded.
+ */
+__inline UINT32
+OvsCountMplsLabels(PNL_ATTR a)
+{
+    const MPLSHdr *mpls = NlAttrGet(a);
+    UINT32 count = 0;
+    BOOLEAN bos = FALSE;
+
+    for (count = 0; count < FLOW_MAX_MPLS_LABELS; count++) {
+        if ((mpls + count)->lse & htonl(MPLS_BOS_MASK)) {
+            bos = TRUE;
+            break;
+        }
+    }
+
+    return bos ? ++count : 0;
+}
+
 #endif /* __MPLS_H_ */
diff --git a/datapath-windows/ovsext/Netlink/NetlinkError.h b/datapath-windows/ovsext/Netlink/NetlinkError.h
index eefa89e..36115c8 100644
--- a/datapath-windows/ovsext/Netlink/NetlinkError.h
+++ b/datapath-windows/ovsext/Netlink/NetlinkError.h
@@ -229,6 +229,9 @@ NlMapStatusToNlErr(NTSTATUS status)
     case STATUS_OBJECT_NAME_EXISTS:
       ret = NL_ERROR_EXIST;
       break;
+    case STATUS_INVALID_MESSAGE:
+      ret = NL_ERROR_BADMSG;
+      break;
     default:
       ret = NL_ERROR_OTHER;
       break;
-- 
1.9.0.msysgit.0



More information about the dev mailing list