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 <vsai...@vmware.com>
---
 datapath-windows/ovsext/Conntrack.c | 62 +++++++++++++++++++++++++++++++++++--
 datapath-windows/ovsext/Conntrack.h |  8 +++++
 datapath-windows/ovsext/Switch.c    |  8 +++++
 3 files changed, 76 insertions(+), 2 deletions(-)

diff --git a/datapath-windows/ovsext/Conntrack.c 
b/datapath-windows/ovsext/Conntrack.c
index d240c29..114c7b7 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,
+              char *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;
+    char *helper = NULL;
+
     NDIS_STATUS status;
 
     status = OvsDetectCtPacket(key);
@@ -674,9 +720,21 @@ OvsExecuteConntrackAction(PNET_BUFFER_LIST curNbl,
     if (ctAttr) {
         labels = NlAttrGet(ctAttr);
     }
+    ctAttr = NlAttrFindNested(a, OVS_CT_ATTR_HELPER);
+    if (ctAttr) {
+        helper = NlAttrGet(ctAttr);
+        if (!memchr(helper, '\0', 16)) {
+            OVS_LOG_ERROR("Invalid CT_ATTR_HELPER:%s", helper);
+            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 44fdfa0..d22b0c4 100644
--- a/datapath-windows/ovsext/Conntrack.h
+++ b/datapath-windows/ovsext/Conntrack.h
@@ -86,6 +86,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 {
@@ -204,4 +205,11 @@ OvsCtRelatedEntryCreate(UINT8 ipProto,
 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/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

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to