[ovs-dev] [PATCH v2 4/4] datapath-windows: Conntrack - Enable FTP support

Sairam Venugopal vsairam at vmware.com
Fri Dec 9 20:04:46 UTC 2016


Enable the support for tracking FTP connections in the Connection tracker.
This checks an incoming ftp control connection to extract the related data
connection. When a matching data connection arrives, it would then update
the connection entry to point to the original control connection.

Signed-off-by: Sairam Venugopal <vsairam at vmware.com>
---
 datapath-windows/ovsext/Conntrack.c       | 61 ++++++++++++++++++++++++++++++-
 datapath-windows/ovsext/Conntrack.h       |  8 ++++
 datapath-windows/ovsext/Netlink/Netlink.c | 16 ++++++++
 datapath-windows/ovsext/Netlink/Netlink.h |  1 +
 datapath-windows/ovsext/Switch.c          |  8 ++++
 5 files changed, 92 insertions(+), 2 deletions(-)

diff --git a/datapath-windows/ovsext/Conntrack.c b/datapath-windows/ovsext/Conntrack.c
index 1436431..1554916 100644
--- a/datapath-windows/ovsext/Conntrack.c
+++ b/datapath-windows/ovsext/Conntrack.c
@@ -192,11 +192,21 @@ OvsCtEntryCreate(PNET_BUFFER_LIST curNbl,
             }
 
             state |= OVS_CS_F_NEW;
+            POVS_CT_ENTRY parentEntry = NULL;
+            parentEntry = OvsCtRelatedLookup(ctx->key, currentTime);
+            if (parentEntry != NULL) {
+                state |= OVS_CS_F_RELATED;
+            }
+
             if (commit) {
                 entry = OvsConntrackCreateTcpEntry(tcp, curNbl, currentTime);
                 if (!entry) {
                     return NULL;
                 }
+                /* If this is related entry, then update parent */
+                if (parentEntry != NULL) {
+                    entry->parent = parentEntry;
+                }
                 OvsCtAddEntry(entry, ctx, currentTime);
             }
 
@@ -492,6 +502,13 @@ OvsCtSetupLookupCtx(OvsFlowKey *flowKey,
     return NDIS_STATUS_SUCCESS;
 }
 
+static __inline BOOLEAN
+OvsDetectFtpPacket(OvsFlowKey *key) {
+    return (key->ipKey.nwProto == IPPROTO_TCP &&
+            (ntohs(key->ipKey.l4.tpDst) == IPPORT_FTP ||
+            ntohs(key->ipKey.l4.tpSrc) == IPPORT_FTP));
+}
+
 /*
  *----------------------------------------------------------------------------
  * OvsProcessConntrackEntry
@@ -542,6 +559,21 @@ OvsProcessConntrackEntry(PNET_BUFFER_LIST curNbl,
             break;
         }
     }
+
+    if (key->ipKey.nwProto == IPPROTO_TCP && entry) {
+        /* Update the related bit if there is a parent */
+        if (entry->parent) {
+            state |= OVS_CS_F_RELATED;
+        } else {
+            POVS_CT_ENTRY parentEntry;
+            parentEntry = OvsCtRelatedLookup(ctx->key, currentTime);
+            if (parentEntry != NULL) {
+                entry->parent = parentEntry;
+                state |= OVS_CS_F_RELATED;
+            }
+        }
+    }
+
     /* Copy mark and label from entry into flowKey. If actions specify
        different mark and label, update the flowKey. */
     if (entry != NULL) {
@@ -592,7 +624,8 @@ OvsCtExecute_(PNET_BUFFER_LIST curNbl,
               BOOLEAN commit,
               UINT16 zone,
               MD_MARK *mark,
-              MD_LABELS *labels)
+              MD_LABELS *labels,
+              PCHAR helper)
 {
     NDIS_STATUS status = NDIS_STATUS_SUCCESS;
     POVS_CT_ENTRY entry = NULL;
@@ -629,6 +662,17 @@ OvsCtExecute_(PNET_BUFFER_LIST curNbl,
         OvsConntrackSetLabels(key, entry, &labels->value, &labels->mask);
     }
 
+    if (entry && OvsDetectFtpPacket(key)) {
+        /* FTP parser will always be loaded */
+        UNREFERENCED_PARAMETER(helper);
+
+        status = OvsCtHandleFtp(curNbl, key, layers, currentTime, entry,
+                                (ntohs(key->ipKey.l4.tpDst) == IPPORT_FTP));
+        if (status != NDIS_STATUS_SUCCESS) {
+            OVS_LOG_ERROR("Error while parsing the FTP packet");
+        }
+    }
+
     NdisReleaseRWLock(ovsConntrackLockObj, &lockState);
 
     return status;
@@ -651,6 +695,8 @@ OvsExecuteConntrackAction(PNET_BUFFER_LIST curNbl,
     UINT16 zone = 0;
     MD_MARK *mark = NULL;
     MD_LABELS *labels = NULL;
+    PCHAR helper = NULL;
+
     NDIS_STATUS status;
 
     status = OvsDetectCtPacket(key);
@@ -674,9 +720,20 @@ OvsExecuteConntrackAction(PNET_BUFFER_LIST curNbl,
     if (ctAttr) {
         labels = NlAttrGet(ctAttr);
     }
+    ctAttr = NlAttrFindNested(a, OVS_CT_ATTR_HELPER);
+    if (ctAttr) {
+        helper = NlAttrGetString(ctAttr);
+        if (helper == NULL) {
+            return NDIS_STATUS_INVALID_PARAMETER;
+        }
+        if (strcmp("ftp", helper) != 0) {
+            /* Only support FTP */
+            return NDIS_STATUS_NOT_SUPPORTED;
+        }
+    }
 
     status = OvsCtExecute_(curNbl, key, layers,
-                           commit, zone, mark, labels);
+                           commit, zone, mark, labels, helper);
     return status;
 }
 
diff --git a/datapath-windows/ovsext/Conntrack.h b/datapath-windows/ovsext/Conntrack.h
index e93842d..124d2af 100644
--- a/datapath-windows/ovsext/Conntrack.h
+++ b/datapath-windows/ovsext/Conntrack.h
@@ -85,6 +85,7 @@ typedef struct OVS_CT_ENTRY {
     UINT32      mark;
     UINT64      timestampStart;
     struct ovs_key_ct_labels labels;
+    PVOID       parent; /* Points to main connection */
 } OVS_CT_ENTRY, *POVS_CT_ENTRY;
 
 typedef struct OVS_CT_REL_ENTRY {
@@ -200,4 +201,11 @@ NDIS_STATUS OvsCtRelatedEntryCreate(UINT8 ipProto,
                                     POVS_CT_ENTRY parent);
 POVS_CT_ENTRY OvsCtRelatedLookup(OVS_CT_KEY key, UINT64 currentTime);
 
+NDIS_STATUS OvsCtHandleFtp(PNET_BUFFER_LIST curNbl,
+                           OvsFlowKey *key,
+                           OVS_PACKET_HDR_INFO *layers,
+                           UINT64 currentTime,
+                           POVS_CT_ENTRY entry,
+                           BOOLEAN request);
+
 #endif /* __OVS_CONNTRACK_H_ */
diff --git a/datapath-windows/ovsext/Netlink/Netlink.c b/datapath-windows/ovsext/Netlink/Netlink.c
index 2432205..a63f066 100644
--- a/datapath-windows/ovsext/Netlink/Netlink.c
+++ b/datapath-windows/ovsext/Netlink/Netlink.c
@@ -992,6 +992,22 @@ NlAttrGetU64(const PNL_ATTR nla)
 
 /*
  * ---------------------------------------------------------------------------
+ * Returns the string value in 'nla''s payload.
+ * Returns NULL if it is not a proper '\0' terminated string.
+ * ---------------------------------------------------------------------------
+ */
+PCHAR
+NlAttrGetString(const PNL_ATTR nla)
+{
+    ASSERT(nla->nlaLen >= NLA_HDRLEN);
+    if (!memchr(NlAttrGet(nla), '\0', nla->nlaLen - NLA_HDRLEN)) {
+        return NULL;
+    }
+    return NlAttrGet(nla);
+}
+
+/*
+ * ---------------------------------------------------------------------------
  * Validate the netlink attribute against the policy
  * ---------------------------------------------------------------------------
  */
diff --git a/datapath-windows/ovsext/Netlink/Netlink.h b/datapath-windows/ovsext/Netlink/Netlink.h
index 363f575..964c0e5 100644
--- a/datapath-windows/ovsext/Netlink/Netlink.h
+++ b/datapath-windows/ovsext/Netlink/Netlink.h
@@ -138,6 +138,7 @@ UINT8 NlAttrGetU8(const PNL_ATTR nla);
 UINT16 NlAttrGetU16(const PNL_ATTR nla);
 UINT32 NlAttrGetU32(const PNL_ATTR nla);
 UINT64 NlAttrGetU64(const PNL_ATTR nla);
+PCHAR NlAttrGetString(const PNL_ATTR nla);
 const PNL_ATTR NlAttrFind__(const PNL_ATTR attrs,
                             UINT32 size, UINT16 type);
 const PNL_ATTR NlAttrFindNested(const PNL_ATTR nla,
diff --git a/datapath-windows/ovsext/Switch.c b/datapath-windows/ovsext/Switch.c
index db023e9..138a656 100644
--- a/datapath-windows/ovsext/Switch.c
+++ b/datapath-windows/ovsext/Switch.c
@@ -225,6 +225,13 @@ OvsCreateSwitch(NDIS_HANDLE ndisFilterHandle,
         goto create_switch_done;
     }
 
+    status = OvsInitCtRelated(switchContext);
+    if (status != STATUS_SUCCESS) {
+        OvsUninitSwitchContext(switchContext);
+        OVS_LOG_ERROR("Exit: Failed to initialize Connection tracking");
+        goto create_switch_done;
+    }
+
     *switchContextOut = switchContext;
 
 create_switch_done:
@@ -257,6 +264,7 @@ OvsExtDetach(NDIS_HANDLE filterModuleContext)
     OvsCleanupIpHelper();
     OvsCleanupSttDefragmentation();
     OvsCleanupConntrack();
+    OvsCleanupCtRelated();
     /* This completes the cleanup, and a new attach can be handled now. */
 
     OVS_LOG_TRACE("Exit: OvsDetach Successfully");
-- 
2.9.0.windows.1



More information about the dev mailing list