summaryrefslogtreecommitdiff
path: root/datapath-windows/ovsext
diff options
context:
space:
mode:
authorSairam Venugopal <vsairam@vmware.com>2016-11-09 16:34:22 -0800
committerGurucharan Shetty <guru@ovn.org>2016-11-11 13:53:07 -0800
commit6e83dfd9c77d83c873f9a51455a90d273e3ee157 (patch)
treeefb999fe360395e8164a1a9a4db6546c8f933d6f /datapath-windows/ovsext
parenta4dabb3df5d000e689915ff9f1df1d21ece0d496 (diff)
downloadopenvswitch-6e83dfd9c77d83c873f9a51455a90d273e3ee157.tar.gz
datapath-windows: Enable support for tracking ICMP code and type
Add support for tracking ICMP code and Type in the Hyper-V Conntrack module. This code is similar to the userspace connection tracker. Signed-off-by: Sairam Venugopal <vsairam@vmware.com> Acked-by: Anand Kumar <kumaranand@vmware.com> Signed-off-by: Gurucharan Shetty <guru@ovn.org>
Diffstat (limited to 'datapath-windows/ovsext')
-rw-r--r--datapath-windows/ovsext/Conntrack-icmp.c84
-rw-r--r--datapath-windows/ovsext/Conntrack-other.c15
-rw-r--r--datapath-windows/ovsext/Conntrack-tcp.c25
-rw-r--r--datapath-windows/ovsext/Conntrack.c73
-rw-r--r--datapath-windows/ovsext/Conntrack.h24
-rw-r--r--datapath-windows/ovsext/ovsext.vcxproj1
6 files changed, 190 insertions, 32 deletions
diff --git a/datapath-windows/ovsext/Conntrack-icmp.c b/datapath-windows/ovsext/Conntrack-icmp.c
new file mode 100644
index 000000000..7db8e7d0e
--- /dev/null
+++ b/datapath-windows/ovsext/Conntrack-icmp.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2016 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "NetProto.h"
+#include "Conntrack.h"
+#include <stddef.h>
+
+enum icmp_state {
+ ICMPS_FIRST,
+ ICMPS_REPLY,
+};
+
+struct conn_icmp {
+ struct OVS_CT_ENTRY up;
+ enum icmp_state state;
+};
+
+static const enum ct_timeout icmp_timeouts[] = {
+ [ICMPS_FIRST] = 60 * CT_INTERVAL_SEC,
+ [ICMPS_REPLY] = 30 * CT_INTERVAL_SEC,
+};
+
+static __inline struct conn_icmp *
+OvsCastConntrackEntryToIcmpEntry(OVS_CT_ENTRY* conn)
+{
+ return CONTAINER_OF(conn, struct conn_icmp, up);
+}
+
+enum CT_UPDATE_RES
+OvsConntrackUpdateIcmpEntry(OVS_CT_ENTRY* conn_,
+ BOOLEAN reply,
+ UINT64 now)
+{
+ struct conn_icmp *conn = OvsCastConntrackEntryToIcmpEntry(conn_);
+
+ if (reply && conn->state != ICMPS_REPLY) {
+ conn->state = ICMPS_REPLY;
+ }
+
+ OvsConntrackUpdateExpiration(&conn->up, now,
+ icmp_timeouts[conn->state]);
+
+ return CT_UPDATE_VALID;
+}
+
+BOOLEAN
+OvsConntrackValidateIcmpPacket(const ICMPHdr *icmp)
+{
+ return icmp->type == ICMP4_ECHO_REQUEST
+ || icmp->type == ICMP4_INFO_REQUEST
+ || icmp->type == ICMP4_TIMESTAMP_REQUEST;
+}
+
+OVS_CT_ENTRY *
+OvsConntrackCreateIcmpEntry(UINT64 now)
+{
+ struct conn_icmp *conn;
+
+ conn = OvsAllocateMemoryWithTag(sizeof(struct conn_icmp),
+ OVS_CT_POOL_TAG);
+ if (!conn) {
+ return NULL;
+ }
+
+ conn->state = ICMPS_FIRST;
+
+ OvsConntrackUpdateExpiration(&conn->up, now,
+ icmp_timeouts[conn->state]);
+
+ return &conn->up;
+}
diff --git a/datapath-windows/ovsext/Conntrack-other.c b/datapath-windows/ovsext/Conntrack-other.c
index b85302038..6c68ba8d0 100644
--- a/datapath-windows/ovsext/Conntrack-other.c
+++ b/datapath-windows/ovsext/Conntrack-other.c
@@ -41,14 +41,7 @@ OvsCastConntrackEntryToOtherEntry(OVS_CT_ENTRY *conn)
return CONTAINER_OF(conn, struct conn_other, up);
}
-static __inline VOID
-OvsConntrackUpdateExpiration(struct conn_other *conn, long long now)
-{
- ASSERT(conn);
- conn->up.expiration = now + other_timeouts[conn->state];
-}
-
-enum ct_update_res
+enum CT_UPDATE_RES
OvsConntrackUpdateOtherEntry(OVS_CT_ENTRY *conn_,
BOOLEAN reply,
UINT64 now)
@@ -62,7 +55,8 @@ OvsConntrackUpdateOtherEntry(OVS_CT_ENTRY *conn_,
conn->state = OTHERS_MULTIPLE;
}
- OvsConntrackUpdateExpiration(conn, now);
+ OvsConntrackUpdateExpiration(&conn->up, now,
+ other_timeouts[conn->state]);
return CT_UPDATE_VALID;
}
@@ -78,6 +72,7 @@ OvsConntrackCreateOtherEntry(UINT64 now)
}
conn->up = (OVS_CT_ENTRY) {0};
conn->state = OTHERS_FIRST;
- OvsConntrackUpdateExpiration(conn, now);
+ OvsConntrackUpdateExpiration(&conn->up, now,
+ other_timeouts[conn->state]);
return &conn->up;
}
diff --git a/datapath-windows/ovsext/Conntrack-tcp.c b/datapath-windows/ovsext/Conntrack-tcp.c
index 6adf490f7..c7fcfa8ff 100644
--- a/datapath-windows/ovsext/Conntrack-tcp.c
+++ b/datapath-windows/ovsext/Conntrack-tcp.c
@@ -199,14 +199,6 @@ OvsGetTcpPayloadLength(PNET_BUFFER_LIST nbl)
- (sizeof * tcp);
}
-static __inline void
-OvsConntrackUpdateExpiration(struct conn_tcp *conn,
- long long now,
- long long interval)
-{
- conn->up.expiration = now + interval;
-}
-
static __inline struct conn_tcp*
OvsCastConntrackEntryToTcpEntry(OVS_CT_ENTRY* conn)
{
@@ -383,18 +375,23 @@ OvsConntrackUpdateTcpEntry(OVS_CT_ENTRY* conn_,
if (src->state >= CT_DPIF_TCPS_FIN_WAIT_2
&& dst->state >= CT_DPIF_TCPS_FIN_WAIT_2) {
- OvsConntrackUpdateExpiration(conn, now, 30 * CT_INTERVAL_SEC);
+ OvsConntrackUpdateExpiration(&conn->up, now,
+ 30 * CT_INTERVAL_SEC);
} else if (src->state >= CT_DPIF_TCPS_CLOSING
&& dst->state >= CT_DPIF_TCPS_CLOSING) {
- OvsConntrackUpdateExpiration(conn, now, 45 * CT_INTERVAL_SEC);
+ OvsConntrackUpdateExpiration(&conn->up, now,
+ 45 * CT_INTERVAL_SEC);
} else if (src->state < CT_DPIF_TCPS_ESTABLISHED
|| dst->state < CT_DPIF_TCPS_ESTABLISHED) {
- OvsConntrackUpdateExpiration(conn, now, 30 * CT_INTERVAL_SEC);
+ OvsConntrackUpdateExpiration(&conn->up, now,
+ 30 * CT_INTERVAL_SEC);
} else if (src->state >= CT_DPIF_TCPS_CLOSING
|| dst->state >= CT_DPIF_TCPS_CLOSING) {
- OvsConntrackUpdateExpiration(conn, now, 15 * 60 * CT_INTERVAL_SEC);
+ OvsConntrackUpdateExpiration(&conn->up, now,
+ 15 * 60 * CT_INTERVAL_SEC);
} else {
- OvsConntrackUpdateExpiration(conn, now, 24 * 60 * 60 * CT_INTERVAL_SEC);
+ OvsConntrackUpdateExpiration(&conn->up, now,
+ 24 * 60 * 60 * CT_INTERVAL_SEC);
}
} else if ((dst->state < CT_DPIF_TCPS_SYN_SENT
|| dst->state >= CT_DPIF_TCPS_FIN_WAIT_2
@@ -518,7 +515,7 @@ OvsConntrackCreateTcpEntry(const TCPHdr *tcp,
src->state = CT_DPIF_TCPS_SYN_SENT;
dst->state = CT_DPIF_TCPS_CLOSED;
- OvsConntrackUpdateExpiration(newconn, now, CT_ENTRY_TIMEOUT);
+ OvsConntrackUpdateExpiration(&newconn->up, now, CT_ENTRY_TIMEOUT);
return &newconn->up;
}
diff --git a/datapath-windows/ovsext/Conntrack.c b/datapath-windows/ovsext/Conntrack.c
index 74fb38c40..b0846f6fc 100644
--- a/datapath-windows/ovsext/Conntrack.c
+++ b/datapath-windows/ovsext/Conntrack.c
@@ -211,7 +211,28 @@ OvsCtEntryCreate(PNET_BUFFER_LIST curNbl,
return entry;
}
case IPPROTO_ICMP:
+ {
+ ICMPHdr storage;
+ const ICMPHdr *icmp;
+ icmp = OvsGetIcmp(curNbl, l4Offset, &storage);
+ if (!OvsConntrackValidateIcmpPacket(icmp)) {
+ goto invalid;
+ }
+
+ state |= OVS_CS_F_NEW;
+ if (commit) {
+ entry = OvsConntrackCreateIcmpEntry(currentTime);
+ if (!entry) {
+ return NULL;
+ }
+ OvsCtAddEntry(entry, ctx, currentTime);
+ }
+
+ OvsCtUpdateFlowKey(key, state, ctx->key.zone, 0, NULL);
+ return entry;
+ }
case IPPROTO_UDP:
+ {
state |= OVS_CS_F_NEW;
if (commit) {
entry = OvsConntrackCreateOtherEntry(currentTime);
@@ -223,6 +244,7 @@ OvsCtEntryCreate(PNET_BUFFER_LIST curNbl,
OvsCtUpdateFlowKey(key, state, ctx->key.zone, 0, NULL);
return entry;
+ }
default:
goto invalid;
}
@@ -254,6 +276,7 @@ OvsCtUpdateEntry(OVS_CT_ENTRY* entry,
return OvsConntrackUpdateTcpEntry(entry, tcp, nbl, reply, now);
}
case IPPROTO_ICMP:
+ return OvsConntrackUpdateIcmpEntry(entry, reply, now);
case IPPROTO_UDP:
return OvsConntrackUpdateOtherEntry(entry, reply, now);
default:
@@ -338,8 +361,7 @@ OvsCtLookup(OvsConntrackKeyLookupCtx *ctx)
BOOLEAN reply = FALSE;
POVS_CT_ENTRY found = NULL;
- if (!ctTotalEntries)
- {
+ if (!ctTotalEntries) {
return found;
}
@@ -384,6 +406,27 @@ OvsExtractLookupCtxHash(OvsConntrackKeyLookupCtx *ctx)
hash);
}
+static UINT8
+OvsReverseIcmpType(UINT8 type)
+{
+ switch (type) {
+ case ICMP4_ECHO_REQUEST:
+ return ICMP4_ECHO_REPLY;
+ case ICMP4_ECHO_REPLY:
+ return ICMP4_ECHO_REQUEST;
+ case ICMP4_TIMESTAMP_REQUEST:
+ return ICMP4_TIMESTAMP_REPLY;
+ case ICMP4_TIMESTAMP_REPLY:
+ return ICMP4_TIMESTAMP_REQUEST;
+ case ICMP4_INFO_REQUEST:
+ return ICMP4_INFO_REPLY;
+ case ICMP4_INFO_REPLY:
+ return ICMP4_INFO_REQUEST;
+ default:
+ return 0;
+ }
+}
+
static __inline NDIS_STATUS
OvsCtSetupLookupCtx(OvsFlowKey *flowKey,
UINT16 zone,
@@ -408,16 +451,31 @@ OvsCtSetupLookupCtx(OvsFlowKey *flowKey,
const ICMPHdr *icmp;
icmp = OvsGetIcmp(curNbl, l4Offset, &icmpStorage);
ASSERT(icmp);
- ctx->key.src.port = ctx->key.dst.port = icmp->fields.echo.id;
/* Related bit is set when ICMP has an error */
/* XXX parse out the appropriate src and dst from inner pkt */
switch (icmp->type) {
+ case ICMP4_ECHO_REQUEST:
+ case ICMP4_ECHO_REPLY:
+ case ICMP4_TIMESTAMP_REQUEST:
+ case ICMP4_TIMESTAMP_REPLY:
+ case ICMP4_INFO_REQUEST:
+ case ICMP4_INFO_REPLY:
+ if (icmp->code != 0) {
+ return NDIS_STATUS_INVALID_PACKET;
+ }
+ /* Separate ICMP connection: identified using id */
+ ctx->key.dst.icmp_id = icmp->fields.echo.id;
+ ctx->key.src.icmp_id = icmp->fields.echo.id;
+ ctx->key.src.icmp_type = icmp->type;
+ ctx->key.dst.icmp_type = OvsReverseIcmpType(icmp->type);
+ break;
case ICMP4_DEST_UNREACH:
case ICMP4_TIME_EXCEEDED:
case ICMP4_PARAM_PROB:
case ICMP4_SOURCE_QUENCH:
case ICMP4_REDIRECT: {
+ /* XXX Handle inner packet */
ctx->related = TRUE;
break;
}
@@ -830,15 +888,18 @@ MapProtoTupleToNl(PNL_BUFFER nlBuf, OVS_CT_KEY *key)
|| key->dl_type == ntohs(ETH_TYPE_IPV6)) {
/* ICMP and ICMPv6 Type, Code and ID are currently not tracked */
if (key->nw_proto == IPPROTO_ICMP) {
- if (!NlMsgPutTailU16(nlBuf, CTA_PROTO_ICMP_ID, 0)) {
+ if (!NlMsgPutTailU16(nlBuf, CTA_PROTO_ICMP_ID,
+ htons(key->src.icmp_id))) {
status = NDIS_STATUS_FAILURE;
goto done;
}
- if (!NlMsgPutTailU8(nlBuf, CTA_PROTO_ICMP_TYPE, 0)) {
+ if (!NlMsgPutTailU8(nlBuf, CTA_PROTO_ICMP_TYPE,
+ key->src.icmp_type)) {
status = NDIS_STATUS_FAILURE;
goto done;
}
- if (!NlMsgPutTailU8(nlBuf, CTA_PROTO_ICMP_CODE, 0)) {
+ if (!NlMsgPutTailU8(nlBuf, CTA_PROTO_ICMP_CODE,
+ key->src.icmp_code)) {
status = NDIS_STATUS_FAILURE;
goto done;
}
diff --git a/datapath-windows/ovsext/Conntrack.h b/datapath-windows/ovsext/Conntrack.h
index 4995ff412..270e2dd15 100644
--- a/datapath-windows/ovsext/Conntrack.h
+++ b/datapath-windows/ovsext/Conntrack.h
@@ -31,7 +31,14 @@ struct ct_addr {
struct ct_endpoint {
struct ct_addr addr;
- ovs_be16 port;
+ union {
+ ovs_be16 port;
+ struct {
+ ovs_be16 icmp_id;
+ uint8_t icmp_type;
+ uint8_t icmp_code;
+ };
+ };
UINT16 pad;
};
@@ -94,6 +101,14 @@ typedef struct OvsConntrackKeyLookupCtx {
((STRUCT *) (void *) ((char *) (POINTER) - \
offsetof (STRUCT, MEMBER)))
+static __inline void
+OvsConntrackUpdateExpiration(OVS_CT_ENTRY *ctEntry,
+ long long now,
+ long long interval)
+{
+ ctEntry->expiration = now + interval;
+}
+
VOID OvsCleanupConntrack(VOID);
NTSTATUS OvsInitConntrack(POVS_SWITCH_CONTEXT context);
@@ -102,20 +117,25 @@ NDIS_STATUS OvsExecuteConntrackAction(PNET_BUFFER_LIST curNbl,
OvsFlowKey *key,
const PNL_ATTR a);
BOOLEAN OvsConntrackValidateTcpPacket(const TCPHdr *tcp);
+BOOLEAN OvsConntrackValidateIcmpPacket(const ICMPHdr *icmp);
OVS_CT_ENTRY * OvsConntrackCreateTcpEntry(const TCPHdr *tcp,
PNET_BUFFER_LIST nbl,
UINT64 now);
NDIS_STATUS OvsCtMapTcpProtoInfoToNl(PNL_BUFFER nlBuf,
OVS_CT_ENTRY *conn_);
OVS_CT_ENTRY * OvsConntrackCreateOtherEntry(UINT64 now);
+OVS_CT_ENTRY * OvsConntrackCreateIcmpEntry(UINT64 now);
enum CT_UPDATE_RES OvsConntrackUpdateTcpEntry(OVS_CT_ENTRY* conn_,
const TCPHdr *tcp,
PNET_BUFFER_LIST nbl,
BOOLEAN reply,
UINT64 now);
-enum ct_update_res OvsConntrackUpdateOtherEntry(OVS_CT_ENTRY *conn_,
+enum CT_UPDATE_RES OvsConntrackUpdateOtherEntry(OVS_CT_ENTRY *conn_,
BOOLEAN reply,
UINT64 now);
+enum CT_UPDATE_RES OvsConntrackUpdateIcmpEntry(OVS_CT_ENTRY* conn_,
+ BOOLEAN reply,
+ UINT64 now);
NTSTATUS
OvsCreateNlMsgFromCtEntry(POVS_CT_ENTRY entry,
PVOID outBuffer,
diff --git a/datapath-windows/ovsext/ovsext.vcxproj b/datapath-windows/ovsext/ovsext.vcxproj
index a00deb041..77530fdd3 100644
--- a/datapath-windows/ovsext/ovsext.vcxproj
+++ b/datapath-windows/ovsext/ovsext.vcxproj
@@ -178,6 +178,7 @@
<ItemGroup>
<ClCompile Include="Actions.c" />
<ClCompile Include="BufferMgmt.c" />
+ <ClCompile Include="Conntrack-icmp.c" />
<ClCompile Include="Conntrack-other.c" />
<ClCompile Include="Conntrack-tcp.c" />
<ClCompile Include="Conntrack.c" />