I wasn't sure how to interpret this. Does this mean that you will review this patch later, or does it mean something else?
Thanks, Ben. On Wed, Jun 01, 2016 at 04:48:58AM +0000, Nithin Raju wrote: > Yin, > I went ahead and sent out a patch for the updates w.r.t > OvsFindTunnelVportByDstPort(). Pls have a look: > https://patchwork.ozlabs.org/patch/628483/ > > I¹ll send out the comments for the remainder of the patch. > > Thanks, > -- Nithin > > > -----Original Message----- > From: dev <dev-boun...@openvswitch.org> on behalf of Yin Lin > <li...@vmware.com> > Date: Tuesday, May 24, 2016 at 4:28 PM > To: "dev@openvswitch.org" <dev@openvswitch.org> > Subject: [ovs-dev] [PATCH 2/2] [PATCH v5] datapath-windows: Add > Geneve support > > >Signed-off-by: Yin Lin <li...@vmware.com> > >--- > >Fixed checksum flag issue brought up by Jesse and automake.mk issue by > >Nithin. > >--- > > datapath-windows/automake.mk | 2 + > > datapath-windows/ovsext/Actions.c | 82 +++----- > > datapath-windows/ovsext/Debug.h | 1 + > > datapath-windows/ovsext/DpInternal.h | 29 ++- > > datapath-windows/ovsext/Flow.c | 172 ++++++++++++++-- > > datapath-windows/ovsext/Flow.h | 7 + > > datapath-windows/ovsext/Geneve.c | 356 > >+++++++++++++++++++++++++++++++++ > > datapath-windows/ovsext/Geneve.h | 122 +++++++++++ > > datapath-windows/ovsext/Gre.c | 7 +- > > datapath-windows/ovsext/Stt.c | 2 +- > > datapath-windows/ovsext/Tunnel.c | 3 +- > > datapath-windows/ovsext/Util.h | 1 + > > datapath-windows/ovsext/Vport.c | 23 ++- > > datapath-windows/ovsext/Vport.h | 10 +- > > datapath-windows/ovsext/ovsext.vcxproj | 2 + > > 15 files changed, 727 insertions(+), 92 deletions(-) > > create mode 100644 datapath-windows/ovsext/Geneve.c > > create mode 100644 datapath-windows/ovsext/Geneve.h > > > >diff --git a/datapath-windows/automake.mk b/datapath-windows/automake.mk > >index c9af806..53fb5c5 100644 > >--- a/datapath-windows/automake.mk > >+++ b/datapath-windows/automake.mk > >@@ -68,6 +68,8 @@ EXTRA_DIST += \ > > datapath-windows/ovsext/Vport.h \ > > datapath-windows/ovsext/Vxlan.c \ > > datapath-windows/ovsext/Vxlan.h \ > >+ datapath-windows/ovsext/Geneve.c \ > >+ datapath-windows/ovsext/Geneve.h \ > > datapath-windows/ovsext/ovsext.inf \ > > datapath-windows/ovsext/ovsext.rc \ > > datapath-windows/ovsext/ovsext.vcxproj \ > >diff --git a/datapath-windows/ovsext/Actions.c > >b/datapath-windows/ovsext/Actions.c > >index 5ad29ee..560f7a1 100644 > >--- a/datapath-windows/ovsext/Actions.c > >+++ b/datapath-windows/ovsext/Actions.c > >@@ -48,6 +48,8 @@ typedef struct _OVS_ACTION_STATS { > > UINT64 txVxlan; > > UINT64 rxStt; > > UINT64 txStt; > >+ UINT64 rxGeneve; > >+ UINT64 txGeneve; > > UINT64 flowMiss; > > UINT64 flowUserspace; > > UINT64 txTcp; > >@@ -227,18 +229,22 @@ OvsDetectTunnelRxPkt(OvsForwardingContext > >*ovsFwdCtx, > > break; > > case IPPROTO_TCP: > > tunnelVport = > >OvsFindTunnelVportByDstPort(ovsFwdCtx->switchContext, > >- dstPort, > >- > >OVS_VPORT_TYPE_STT); > >+ dstPort); > > if (tunnelVport) { > >+ ASSERT(tunnelVport->ovsType == OVS_VPORT_TYPE_STT); > > ovsActionStats.rxStt++; > > } > > break; > > case IPPROTO_UDP: > > tunnelVport = > >OvsFindTunnelVportByDstPort(ovsFwdCtx->switchContext, > >- dstPort, > >- > >OVS_VPORT_TYPE_VXLAN); > >+ dstPort); > > if (tunnelVport) { > >- ovsActionStats.rxVxlan++; > >+ if (tunnelVport->ovsType == OVS_VPORT_TYPE_VXLAN) { > >+ ovsActionStats.rxVxlan++; > >+ } else { > >+ ASSERT(tunnelVport->ovsType == > >OVS_VPORT_TYPE_GENEVE); > >+ ovsActionStats.rxGeneve++; > >+ } > > } > > break; > > } > >@@ -333,6 +339,9 @@ OvsDetectTunnelPkt(OvsForwardingContext *ovsFwdCtx, > > case OVS_VPORT_TYPE_STT: > > ovsActionStats.txStt++; > > break; > >+ case OVS_VPORT_TYPE_GENEVE: > >+ ovsActionStats.txGeneve++; > >+ break; > > } > > ovsFwdCtx->tunnelTxNic = dstVport; > > } > >@@ -689,6 +698,11 @@ OvsTunnelPortTx(OvsForwardingContext *ovsFwdCtx) > > &ovsFwdCtx->tunKey, > >ovsFwdCtx->switchContext, > > &ovsFwdCtx->layers, &newNbl); > > break; > >+ case OVS_VPORT_TYPE_GENEVE: > >+ status = OvsEncapGeneve(ovsFwdCtx->tunnelTxNic, > >ovsFwdCtx->curNbl, > >+ &ovsFwdCtx->tunKey, > >ovsFwdCtx->switchContext, > >+ &ovsFwdCtx->layers, &newNbl); > >+ break; > > default: > > ASSERT(! "Tx: Unhandled tunnel type"); > > } > >@@ -767,6 +781,10 @@ OvsTunnelPortRx(OvsForwardingContext *ovsFwdCtx) > > dropReason = L"OVS-STT segment is cached"; > > } > > break; > >+ case OVS_VPORT_TYPE_GENEVE: > >+ status = OvsDecapGeneve(ovsFwdCtx->switchContext, > >ovsFwdCtx->curNbl, > >+ &ovsFwdCtx->tunKey, &newNbl); > >+ break; > > default: > > OVS_LOG_ERROR("Rx: Unhandled tunnel type: %d\n", > > tunnelRxVport->ovsType); > >@@ -1233,57 +1251,6 @@ OvsActionMplsPush(OvsForwardingContext *ovsFwdCtx, > > } > > > > /* > >- * > >-------------------------------------------------------------------------- > >- * OvsTunnelAttrToIPv4TunnelKey -- > >- * Convert tunnel attribute to OvsIPv4TunnelKey. > >- * > >-------------------------------------------------------------------------- > >- */ > >-static __inline NDIS_STATUS > >-OvsTunnelAttrToIPv4TunnelKey(PNL_ATTR attr, > >- OvsIPv4TunnelKey *tunKey) > >-{ > >- PNL_ATTR a; > >- INT rem; > >- > >- tunKey->attr[0] = 0; > >- tunKey->attr[1] = 0; > >- tunKey->attr[2] = 0; > >- ASSERT(NlAttrType(attr) == OVS_KEY_ATTR_TUNNEL); > >- > >- NL_ATTR_FOR_EACH_UNSAFE (a, rem, NlAttrData(attr), > >- NlAttrGetSize(attr)) { > >- switch (NlAttrType(a)) { > >- case OVS_TUNNEL_KEY_ATTR_ID: > >- tunKey->tunnelId = NlAttrGetBe64(a); > >- tunKey->flags |= OVS_TNL_F_KEY; > >- break; > >- case OVS_TUNNEL_KEY_ATTR_IPV4_SRC: > >- tunKey->src = NlAttrGetBe32(a); > >- break; > >- case OVS_TUNNEL_KEY_ATTR_IPV4_DST: > >- tunKey->dst = NlAttrGetBe32(a); > >- break; > >- case OVS_TUNNEL_KEY_ATTR_TOS: > >- tunKey->tos = NlAttrGetU8(a); > >- break; > >- case OVS_TUNNEL_KEY_ATTR_TTL: > >- tunKey->ttl = NlAttrGetU8(a); > >- break; > >- case OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT: > >- tunKey->flags |= OVS_TNL_F_DONT_FRAGMENT; > >- break; > >- case OVS_TUNNEL_KEY_ATTR_CSUM: > >- tunKey->flags |= OVS_TNL_F_CSUM; > >- break; > >- default: > >- ASSERT(0); > >- } > >- } > >- > >- return NDIS_STATUS_SUCCESS; > >-} > >- > >-/* > > > >*------------------------------------------------------------------------- > >--- > > * OvsUpdateEthHeader -- > > * Updates the ethernet header in ovsFwdCtx.curNbl inline based on > >the > >@@ -1511,7 +1478,8 @@ OvsExecuteSetAction(OvsForwardingContext *ovsFwdCtx, > > case OVS_KEY_ATTR_TUNNEL: > > { > > OvsIPv4TunnelKey tunKey; > >- status = OvsTunnelAttrToIPv4TunnelKey((PNL_ATTR)a, &tunKey); > >+ NTSTATUS convertStatus = > >OvsTunnelAttrToIPv4TunnelKey((PNL_ATTR)a, &tunKey); > >+ status = SUCCEEDED(convertStatus) ? NDIS_STATUS_SUCCESS : > >NDIS_STATUS_FAILURE; > > ASSERT(status == NDIS_STATUS_SUCCESS); > > tunKey.flow_hash = (uint16)(hash ? *hash : OvsHashFlow(key)); > > tunKey.dst_port = key->ipKey.l4.tpDst; > >diff --git a/datapath-windows/ovsext/Debug.h > >b/datapath-windows/ovsext/Debug.h > >index e5ed963..935f858 100644 > >--- a/datapath-windows/ovsext/Debug.h > >+++ b/datapath-windows/ovsext/Debug.h > >@@ -41,6 +41,7 @@ > > #define OVS_DBG_TUNFLT BIT32(21) > > #define OVS_DBG_STT BIT32(22) > > #define OVS_DBG_CONTRK BIT32(23) > >+#define OVS_DBG_GENEVE BIT32(24) > > > > #define OVS_DBG_RESERVED BIT32(31) > > //Please add above OVS_DBG_RESERVED. > >diff --git a/datapath-windows/ovsext/DpInternal.h > >b/datapath-windows/ovsext/DpInternal.h > >index a3ce311..a95467b 100644 > >--- a/datapath-windows/ovsext/DpInternal.h > >+++ b/datapath-windows/ovsext/DpInternal.h > >@@ -128,10 +128,18 @@ typedef struct L2Key { > > } L2Key; /* Size of 24 byte. */ > > > > /* Number of packet attributes required to store OVS tunnel key. */ > >-#define NUM_PKT_ATTR_REQUIRED 3 > >+#define NUM_PKT_ATTR_REQUIRED 35 > >+#define TUN_OPT_MAX_LEN 255 > > > > typedef union OvsIPv4TunnelKey { > >+ /* Options should always be the first member of tunnel key. > >+ * They are stored at the end of the array if they are less than the > >+ * maximum size. This allows us to get the benefits of variable > >length > >+ * matching for small options. > >+ */ > > struct { > >+ UINT8 tunOpts[TUN_OPT_MAX_LEN]; /* Tunnel options. */ > >+ UINT8 tunOptLen; /* Tunnel option length in byte. */ > > ovs_be32 dst; > > ovs_be32 src; > > ovs_be64 tunnelId; > >@@ -147,7 +155,22 @@ typedef union OvsIPv4TunnelKey { > > }; > > }; > > uint64_t attr[NUM_PKT_ATTR_REQUIRED]; > >-} OvsIPv4TunnelKey; /* Size of 24 byte. */ > >+} OvsIPv4TunnelKey; /* Size of 280 byte. */ > >+ > >+__inline uint8_t TunnelKeyGetOptionsOffset(OvsIPv4TunnelKey *key) > >+{ > >+ return TUN_OPT_MAX_LEN - key->tunOptLen; > >+} > >+ > >+__inline uint8_t* TunnelKeyGetOptions(OvsIPv4TunnelKey *key) > >+{ > >+ return key->tunOpts + TunnelKeyGetOptionsOffset(key); > >+} > >+ > >+__inline uint16_t TunnelKeyGetRealSize(OvsIPv4TunnelKey *key) > >+{ > >+ return sizeof(OvsIPv4TunnelKey) - TunnelKeyGetOptionsOffset(key); > >+} > > > > typedef struct MplsKey { > > ovs_be32 lse; /* MPLS topmost label stack entry. */ > >@@ -155,7 +178,7 @@ typedef struct MplsKey { > > } MplsKey; /* Size of 8 bytes. */ > > > > typedef __declspec(align(8)) struct OvsFlowKey { > >- OvsIPv4TunnelKey tunKey; /* 24 bytes */ > >+ OvsIPv4TunnelKey tunKey; /* 280 bytes */ > > L2Key l2; /* 24 bytes */ > > union { > > /* These headers are mutually exclusive. */ > >diff --git a/datapath-windows/ovsext/Flow.c > >b/datapath-windows/ovsext/Flow.c > >index d957d39..b0a8f44 100644 > >--- a/datapath-windows/ovsext/Flow.c > >+++ b/datapath-windows/ovsext/Flow.c > >@@ -21,6 +21,7 @@ > > #include "Flow.h" > > #include "PacketParser.h" > > #include "Datapath.h" > >+#include "Geneve.h" > > > > #ifdef OVS_DBG_MOD > > #undef OVS_DBG_MOD > >@@ -88,7 +89,7 @@ static NTSTATUS OvsDoDumpFlows(OvsFlowDumpInput > >*dumpInput, > > UINT32 *replyLen); > > static NTSTATUS OvsProbeSupportedFeature(POVS_MESSAGE msgIn, > > PNL_ATTR keyAttr); > >- > >+static UINT16 OvsGetFlowL2Offset(OvsIPv4TunnelKey *tunKey); > > > > #define OVS_FLOW_TABLE_SIZE 2048 > > #define OVS_FLOW_TABLE_MASK (OVS_FLOW_TABLE_SIZE -1) > >@@ -1029,6 +1030,13 @@ MapFlowTunKeyToNlKey(PNL_BUFFER nlBuf, > > goto done; > > } > > > >+ if (tunKey->tunOptLen > 0 && > >+ !NlMsgPutTailUnspec(nlBuf, OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS, > >+ (PCHAR)TunnelKeyGetOptions(tunKey), > >tunKey->tunOptLen)) { > >+ rc = STATUS_UNSUCCESSFUL; > >+ goto done; > >+ } > >+ > > done: > > NlMsgEndNested(nlBuf, offset); > > error_nested_start: > >@@ -1635,6 +1643,116 @@ _MapKeyAttrToFlowPut(PNL_ATTR *keyAttrs, > > > > /* > > > >*------------------------------------------------------------------------- > >--- > >+ * OvsTunnelAttrToGeneveOptions -- > >+ * Converts OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS attribute to > >tunKey->tunOpts. > >+ > >*------------------------------------------------------------------------- > >--- > >+ */ > >+static __inline NTSTATUS > >+OvsTunnelAttrToGeneveOptions(PNL_ATTR attr, > >+ OvsIPv4TunnelKey *tunKey) > >+{ > >+ UINT32 optLen = NlAttrGetSize(attr); > >+ GeneveOptionHdr *option; > >+ if (optLen > TUN_OPT_MAX_LEN) { > >+ OVS_LOG_ERROR("Geneve option length err (len %d, max %Iu).", > >+ optLen, TUN_OPT_MAX_LEN); > >+ return STATUS_INFO_LENGTH_MISMATCH; > >+ } else if (optLen % 4 != 0) { > >+ OVS_LOG_ERROR("Geneve opt len %d is not a multiple of 4.", > >optLen); > >+ return STATUS_INFO_LENGTH_MISMATCH; > >+ } > >+ tunKey->tunOptLen = (UINT8)optLen; > >+ option = (GeneveOptionHdr *)TunnelKeyGetOptions(tunKey); > >+ memcpy(option, NlAttrData(attr), optLen); > >+ while (optLen > 0) { > >+ UINT32 len; > >+ if (optLen < sizeof(*option)) { > >+ return STATUS_INFO_LENGTH_MISMATCH; > >+ } > >+ len = sizeof(*option) + option->length * 4; > >+ if (len > optLen) { > >+ return STATUS_INFO_LENGTH_MISMATCH; > >+ } > >+ if (option->type & GENEVE_CRIT_OPT_TYPE) { > >+ tunKey->flags |= OVS_TNL_F_CRT_OPT; > >+ } > >+ option = (GeneveOptionHdr *)((UINT8 *)option + len); > >+ optLen -= len; > >+ } > >+ return STATUS_SUCCESS; > >+} > >+ > >+ > >+/* > >+ > >*------------------------------------------------------------------------- > >--- > >+ * OvsTunnelAttrToIPv4TunnelKey -- > >+ * Converts OVS_KEY_ATTR_TUNNEL attribute to tunKey. > >+ > >*------------------------------------------------------------------------- > >--- > >+ */ > >+NTSTATUS > >+OvsTunnelAttrToIPv4TunnelKey(PNL_ATTR attr, > >+ OvsIPv4TunnelKey *tunKey) > >+{ > >+ PNL_ATTR a; > >+ INT rem; > >+ INT hasOpt = 0; > >+ NTSTATUS status; > >+ > >+ memset(tunKey, 0, OVS_WIN_TUNNEL_KEY_SIZE); > >+ ASSERT(NlAttrType(attr) == OVS_KEY_ATTR_TUNNEL); > >+ > >+ NL_ATTR_FOR_EACH_UNSAFE(a, rem, NlAttrData(attr), > >+ NlAttrGetSize(attr)) { > >+ switch (NlAttrType(a)) { > >+ case OVS_TUNNEL_KEY_ATTR_ID: > >+ tunKey->tunnelId = NlAttrGetBe64(a); > >+ tunKey->flags |= OVS_TNL_F_KEY; > >+ break; > >+ case OVS_TUNNEL_KEY_ATTR_IPV4_SRC: > >+ tunKey->src = NlAttrGetBe32(a); > >+ break; > >+ case OVS_TUNNEL_KEY_ATTR_IPV4_DST: > >+ tunKey->dst = NlAttrGetBe32(a); > >+ break; > >+ case OVS_TUNNEL_KEY_ATTR_TOS: > >+ tunKey->tos = NlAttrGetU8(a); > >+ break; > >+ case OVS_TUNNEL_KEY_ATTR_TTL: > >+ tunKey->ttl = NlAttrGetU8(a); > >+ break; > >+ case OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT: > >+ tunKey->flags |= OVS_TNL_F_DONT_FRAGMENT; > >+ break; > >+ case OVS_TUNNEL_KEY_ATTR_CSUM: > >+ tunKey->flags |= OVS_TNL_F_CSUM; > >+ break; > >+ case OVS_TUNNEL_KEY_ATTR_OAM: > >+ tunKey->flags |= OVS_TNL_F_OAM; > >+ break; > >+ case OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS: > >+ if (hasOpt) { > >+ /* Duplicate options attribute is not allowed. */ > >+ return NDIS_STATUS_FAILURE; > >+ } > >+ status = OvsTunnelAttrToGeneveOptions(a, tunKey); > >+ if (!SUCCEEDED(status)) { > >+ return status; > >+ } > >+ tunKey->flags |= OVS_TNL_F_GENEVE_OPT; > >+ hasOpt = 1; > >+ break; > >+ default: > >+ // XXX: Support OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS > >+ return STATUS_INVALID_PARAMETER; > >+ } > >+ } > >+ > >+ return STATUS_SUCCESS; > >+} > >+ > >+ > >+/* > >+ > >*------------------------------------------------------------------------- > >--- > > * _MapTunAttrToFlowPut -- > > * Converts FLOW_TUNNEL_KEY attribute to OvsFlowKey->tunKey. > > > >*------------------------------------------------------------------------- > >--- > >@@ -1644,8 +1762,10 @@ _MapTunAttrToFlowPut(PNL_ATTR *keyAttrs, > > PNL_ATTR *tunAttrs, > > OvsFlowKey *destKey) > > { > >+ memset(&destKey->tunKey, 0, OVS_WIN_TUNNEL_KEY_SIZE); > > if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) { > >- > >+ /* XXX: This blocks performs same functionality as > >OvsTunnelAttrToIPv4TunnelKey. > >+ Consider refactoring the code.*/ > > if (tunAttrs[OVS_TUNNEL_KEY_ATTR_ID]) { > > destKey->tunKey.tunnelId = NlAttrGetU64 > > > >(tunAttrs[OVS_TUNNEL_KEY_ATTR_ID]); > >@@ -1680,13 +1800,18 @@ _MapTunAttrToFlowPut(PNL_ATTR *keyAttrs, > > (tunAttrs[OVS_TUNNEL_KEY_ATTR_TTL]); > > } > > > >- destKey->tunKey.pad = 0; > >- destKey->l2.offset = 0; > >+ if (tunAttrs[OVS_TUNNEL_KEY_ATTR_OAM]) { > >+ destKey->tunKey.flags |= OVS_TNL_F_OAM; > >+ } > >+ > >+ if (tunAttrs[OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS]) { > >+ > >OvsTunnelAttrToGeneveOptions(tunAttrs[OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS], > >+ &destKey->tunKey); > >+ destKey->tunKey.flags |= OVS_TNL_F_GENEVE_OPT; > >+ } > >+ destKey->l2.offset = OvsGetFlowL2Offset(&destKey->tunKey); > > } else { > >- destKey->tunKey.attr[0] = 0; > >- destKey->tunKey.attr[1] = 0; > >- destKey->tunKey.attr[2] = 0; > >- destKey->l2.offset = sizeof destKey->tunKey; > >+ destKey->l2.offset = OvsGetFlowL2Offset(NULL); > > } > > } > > > >@@ -1850,6 +1975,20 @@ OvsGetFlowMetadata(OvsFlowKey *key, > > return status; > > } > > > >+UINT16 > >+OvsGetFlowL2Offset(OvsIPv4TunnelKey *tunKey) > >+{ > >+ if (tunKey != NULL) { > >+ // Align with int64 boundary > >+ if (tunKey->tunOptLen == 0) { > >+ return (TUN_OPT_MAX_LEN + 1) / 8 * 8; > >+ } > >+ return TunnelKeyGetOptionsOffset(tunKey) / 8 * 8; > >+ } else { > >+ return OVS_WIN_TUNNEL_KEY_SIZE; > >+ } > >+} > >+ > > /* > > > >*------------------------------------------------------------------------- > >--- > > * Initializes 'flow' members from 'packet', 'skb_priority', 'tun_id', > >and > >@@ -1881,23 +2020,25 @@ OvsExtractFlow(const NET_BUFFER_LIST *packet, > > OvsIPv4TunnelKey *tunKey) > > { > > struct Eth_Header *eth; > >- UINT8 offset = 0; > >+ UINT8 offset; > > PVOID vlanTagValue; > > > > layers->value = 0; > > > > if (tunKey) { > > ASSERT(tunKey->dst != 0); > >- RtlMoveMemory(&flow->tunKey, tunKey, sizeof flow->tunKey); > >- flow->l2.offset = 0; > >+ offset = TunnelKeyGetOptionsOffset(tunKey); > >+ RtlMoveMemory(((UINT8 *)&flow->tunKey) + offset, > >+ ((UINT8 *)tunKey) + offset, > >+ TunnelKeyGetRealSize(tunKey)); > > } else { > > flow->tunKey.dst = 0; > >- flow->l2.offset = OVS_WIN_TUNNEL_KEY_SIZE; > > } > >- > >+ flow->l2.offset = OvsGetFlowL2Offset(tunKey); > > flow->l2.inPort = inPort; > >+ offset = 0; > > > >- if ( OvsPacketLenNBL(packet) < ETH_HEADER_LEN_DIX) { > >+ if (OvsPacketLenNBL(packet) < ETH_HEADER_LEN_DIX) { > > flow->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + 8 - flow->l2.offset; > > return NDIS_STATUS_SUCCESS; > > } > >@@ -2222,7 +2363,6 @@ OvsLookupFlow(OVS_DATAPATH *datapath, > > UINT8 *start; > > > > ASSERT(key->tunKey.dst || offset == sizeof (OvsIPv4TunnelKey)); > >- ASSERT(!key->tunKey.dst || offset == 0); > > > > start = (UINT8 *)key + offset; > > > >@@ -2278,7 +2418,7 @@ OvsHashFlow(const OvsFlowKey *key) > > UINT16 size = key->l2.keyLen; > > UINT8 *start; > > > >- ASSERT(key->tunKey.dst || offset == sizeof (OvsIPv4TunnelKey)); > >+ ASSERT(key->tunKey.dst || offset == sizeof(OvsIPv4TunnelKey)); > > ASSERT(!key->tunKey.dst || offset == 0); > > start = (UINT8 *)key + offset; > > return OvsJhashBytes(start, size, 0); > >diff --git a/datapath-windows/ovsext/Flow.h > >b/datapath-windows/ovsext/Flow.h > >index 310c472..3722b5d 100644 > >--- a/datapath-windows/ovsext/Flow.h > >+++ b/datapath-windows/ovsext/Flow.h > >@@ -83,10 +83,17 @@ NTSTATUS MapFlowTunKeyToNlKey(PNL_BUFFER nlBuf, > >OvsIPv4TunnelKey *tunKey, > > UINT16 tunKeyType); > > UINT32 OvsFlowKeyAttrSize(void); > > UINT32 OvsTunKeyAttrSize(void); > >+NTSTATUS OvsTunnelAttrToIPv4TunnelKey(PNL_ATTR attr, OvsIPv4TunnelKey > >*tunKey); > > > > /* Flags for tunneling */ > > #define OVS_TNL_F_DONT_FRAGMENT (1 << 0) > > #define OVS_TNL_F_CSUM (1 << 1) > > #define OVS_TNL_F_KEY (1 << 2) > >+#define OVS_TNL_F_OAM (1 << 3) > >+#define OVS_TNL_F_CRT_OPT (1 << 4) > >+#define OVS_TNL_F_GENEVE_OPT (1 << 5) > >+#define OVS_TNL_F_VXLAN_OPT (1 << 6) > >+ > >+#define OVS_TNL_HAS_OPTIONS (OVS_TNL_F_GENEVE_OPT | > >OVS_TNL_F_VXLAN_OPT) > > > > #endif /* __FLOW_H_ */ > >diff --git a/datapath-windows/ovsext/Geneve.c > >b/datapath-windows/ovsext/Geneve.c > >new file mode 100644 > >index 0000000..d59945d > >--- /dev/null > >+++ b/datapath-windows/ovsext/Geneve.c > >@@ -0,0 +1,356 @@ > >+/* > >+ * 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: > >+ * > >+ * > >https://urldefense.proofpoint.com/v2/url?u=http-3A__www.apache.org_license > >s_LICENSE-2D2.0&d=CwIGaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=p > >NHQcdr7B40b4h6Yb7FIedI1dnBsxdDuTLBYD3JqV80&m=62Xt8BBpUG4AqJ0X8YjOtMfZRYm0C > >1SOzdOxdvcn9ok&s=pd1fscKFk3BO3GSaqAVHqwpPhjWfuk9h4zFaTwkcPso&e= > >+ * > >+ * 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 "precomp.h" > >+ > >+#include "Atomic.h" > >+#include "Debug.h" > >+#include "Flow.h" > >+#include "IpHelper.h" > >+#include "Jhash.h" > >+#include "NetProto.h" > >+#include "Offload.h" > >+#include "PacketIO.h" > >+#include "PacketParser.h" > >+#include "Geneve.h" > >+#include "Switch.h" > >+#include "User.h" > >+#include "Util.h" > >+#include "Vport.h" > >+ > >+#ifdef OVS_DBG_MOD > >+#undef OVS_DBG_MOD > >+#endif > >+#define OVS_DBG_MOD OVS_DBG_GENEVE > >+ > >+ > >+NTSTATUS OvsInitGeneveTunnel(POVS_VPORT_ENTRY vport, > >+ UINT16 udpDestPort) > >+{ > >+ POVS_GENEVE_VPORT genevePort; > >+ > >+ genevePort = (POVS_GENEVE_VPORT) > >OvsAllocateMemoryWithTag(sizeof(*genevePort), > >+ > >OVS_GENEVE_POOL_TAG); > >+ if (!genevePort) { > >+ OVS_LOG_ERROR("Insufficient memory, can't allocate > >GENEVE_VPORT"); > >+ return STATUS_INSUFFICIENT_RESOURCES; > >+ } > >+ > >+ RtlZeroMemory(genevePort, sizeof(*genevePort)); > >+ genevePort->dstPort = udpDestPort; > >+ vport->priv = (PVOID) genevePort; > >+ return STATUS_SUCCESS; > >+} > >+ > >+VOID > >+OvsCleanupGeneveTunnel(POVS_VPORT_ENTRY vport) > >+{ > >+ if (vport->ovsType != OVS_VPORT_TYPE_GENEVE || > >+ vport->priv == NULL) { > >+ return; > >+ } > >+ > >+ OvsFreeMemoryWithTag(vport->priv, OVS_GENEVE_POOL_TAG); > >+ vport->priv = NULL; > >+} > >+ > >+NDIS_STATUS OvsEncapGeneve(POVS_VPORT_ENTRY vport, > >+ PNET_BUFFER_LIST curNbl, > >+ OvsIPv4TunnelKey *tunKey, > >+ POVS_SWITCH_CONTEXT switchContext, > >+ POVS_PACKET_HDR_INFO layers, > >+ PNET_BUFFER_LIST *newNbl) > >+{ > >+ NTSTATUS status; > >+ OVS_FWD_INFO fwdInfo; > >+ PNET_BUFFER curNb; > >+ PMDL curMdl; > >+ PUINT8 bufferStart; > >+ EthHdr *ethHdr; > >+ IPHdr *ipHdr; > >+ UDPHdr *udpHdr; > >+ GeneveHdr *geneveHdr; > >+ GeneveOptionHdr *optHdr; > >+ POVS_GENEVE_VPORT vportGeneve; > >+ UINT32 headRoom = OvsGetGeneveTunHdrMinSize() + tunKey->tunOptLen; > >+ UINT32 packetLength; > >+ ULONG mss = 0; > >+ NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo; > >+ > >+ status = OvsLookupIPFwdInfo(tunKey->dst, &fwdInfo); > >+ if (status != STATUS_SUCCESS) { > >+ OvsFwdIPHelperRequest(NULL, 0, tunKey, NULL, NULL, NULL); > >+ // return NDIS_STATUS_PENDING; > >+ /* > >+ * XXX: Don't know if the completionList will make any sense when > >+ * accessed in the callback. Make sure the caveats are known. > >+ * > >+ * XXX: This code will work once we are able to grab locks in the > >+ * callback. > >+ */ > >+ return NDIS_STATUS_FAILURE; > >+ } > >+ > >+ /* > >+ * XXX: the assumption currently is that the NBL is owned by OVS, and > >+ * headroom has already been allocated as part of allocating the NBL > >and > >+ * MDL. > >+ */ > >+ curNb = NET_BUFFER_LIST_FIRST_NB(curNbl); > >+ packetLength = NET_BUFFER_DATA_LENGTH(curNb); > >+ > >+ if (layers->isTcp) { > >+ mss = OVSGetTcpMSS(curNbl); > >+ > >+ OVS_LOG_TRACE("MSS %u packet len %u", mss, > >+ packetLength); > >+ if (mss) { > >+ OVS_LOG_TRACE("l4Offset %d", layers->l4Offset); > >+ *newNbl = OvsTcpSegmentNBL(switchContext, curNbl, layers, > >+ mss, headRoom); > >+ if (*newNbl == NULL) { > >+ OVS_LOG_ERROR("Unable to segment NBL"); > >+ return NDIS_STATUS_FAILURE; > >+ } > >+ /* Clear out LSO flags after this point */ > >+ NET_BUFFER_LIST_INFO(*newNbl, TcpLargeSendNetBufferListInfo) > >= 0; > >+ } > >+ } > >+ > >+ vportGeneve = (POVS_GENEVE_VPORT) GetOvsVportPriv(vport); > >+ ASSERT(vportGeneve != NULL); > >+ > >+ /* If we didn't split the packet above, make a copy now */ > >+ if (*newNbl == NULL) { > >+ *newNbl = OvsPartialCopyNBL(switchContext, curNbl, 0, headRoom, > >+ FALSE /*NBL info*/); > >+ if (*newNbl == NULL) { > >+ OVS_LOG_ERROR("Unable to copy NBL"); > >+ return NDIS_STATUS_FAILURE; > >+ } > >+ NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo; > >+ csumInfo.Value = NET_BUFFER_LIST_INFO(curNbl, > >+ > >TcpIpChecksumNetBufferListInfo); > >+ status = OvsApplySWChecksumOnNB(layers, *newNbl, &csumInfo); > >+ > >+ if (status != NDIS_STATUS_SUCCESS) { > >+ goto ret_error; > >+ } > >+ } > >+ > >+ curNbl = *newNbl; > >+ for (curNb = NET_BUFFER_LIST_FIRST_NB(curNbl); curNb != NULL; > >+ curNb = curNb->Next) { > >+ status = NdisRetreatNetBufferDataStart(curNb, headRoom, 0, NULL); > >+ if (status != NDIS_STATUS_SUCCESS) { > >+ goto ret_error; > >+ } > >+ > >+ curMdl = NET_BUFFER_CURRENT_MDL(curNb); > >+ bufferStart = (PUINT8)MmGetSystemAddressForMdlSafe(curMdl, > >LowPagePriority); > >+ if (!bufferStart) { > >+ status = NDIS_STATUS_RESOURCES; > >+ goto ret_error; > >+ } > >+ > >+ bufferStart += NET_BUFFER_CURRENT_MDL_OFFSET(curNb); > >+ if (NET_BUFFER_NEXT_NB(curNb)) { > >+ OVS_LOG_TRACE("nb length %u next %u", > >NET_BUFFER_DATA_LENGTH(curNb), > >+ NET_BUFFER_DATA_LENGTH(curNb->Next)); > >+ } > >+ > >+ /* L2 header */ > >+ ethHdr = (EthHdr *)bufferStart; > >+ ASSERT(((PCHAR)&fwdInfo.dstMacAddr + sizeof fwdInfo.dstMacAddr) > >== > >+ (PCHAR)&fwdInfo.srcMacAddr); > >+ NdisMoveMemory(ethHdr->Destination, fwdInfo.dstMacAddr, > >+ sizeof ethHdr->Destination + sizeof > >ethHdr->Source); > >+ ethHdr->Type = htons(ETH_TYPE_IPV4); > >+ > >+ /* IP header */ > >+ ipHdr = (IPHdr *)((PCHAR)ethHdr + sizeof *ethHdr); > >+ > >+ ipHdr->ihl = sizeof *ipHdr / 4; > >+ ipHdr->version = IPPROTO_IPV4; > >+ ipHdr->tos = tunKey->tos; > >+ ipHdr->tot_len = htons(NET_BUFFER_DATA_LENGTH(curNb) - sizeof > >*ethHdr); > >+ ipHdr->id = (uint16)atomic_add64(&vportGeneve->ipId, > >+ NET_BUFFER_DATA_LENGTH(curNb)); > >+ ipHdr->frag_off = (tunKey->flags & OVS_TNL_F_DONT_FRAGMENT) ? > >+ IP_DF_NBO : 0; > >+ ipHdr->ttl = tunKey->ttl ? tunKey->ttl : GENEVE_DEFAULT_TTL; > >+ ipHdr->protocol = IPPROTO_UDP; > >+ ASSERT(tunKey->dst == fwdInfo.dstIpAddr); > >+ ASSERT(tunKey->src == fwdInfo.srcIpAddr || tunKey->src == 0); > >+ ipHdr->saddr = fwdInfo.srcIpAddr; > >+ ipHdr->daddr = fwdInfo.dstIpAddr; > >+ > >+ /* UDP header */ > >+ udpHdr = (UDPHdr *)((PCHAR)ipHdr + sizeof *ipHdr); > >+ udpHdr->source = htons(tunKey->flow_hash | MAXINT16); > >+ udpHdr->dest = htons(vportGeneve->dstPort); > >+ udpHdr->len = htons(NET_BUFFER_DATA_LENGTH(curNb) - headRoom + > >+ sizeof *udpHdr + sizeof *geneveHdr + > >tunKey->tunOptLen); > >+ if (tunKey->flags & OVS_TNL_F_CSUM) { > >+ UINT16 udpChksumLen = (UINT16) NET_BUFFER_DATA_LENGTH(curNb) > >- > >+ sizeof *ipHdr - sizeof *ethHdr; > >+ udpHdr->check = IPPseudoChecksum(&ipHdr->saddr, > >&ipHdr->daddr, > >+ IPPROTO_UDP, udpChksumLen); > >+ } else { > >+ udpHdr->check = 0; > >+ } > >+ /* Geneve header */ > >+ geneveHdr = (GeneveHdr *)((PCHAR)udpHdr + sizeof *udpHdr); > >+ geneveHdr->version = GENEVE_VER; > >+ geneveHdr->optLen = tunKey->tunOptLen / 4; > >+ geneveHdr->oam = !!(tunKey->flags & OVS_TNL_F_OAM); > >+ geneveHdr->critical = !!(tunKey->flags & OVS_TNL_F_CRT_OPT); > >+ geneveHdr->reserved1 = 0; > >+ geneveHdr->protocol = htons(ETH_P_TEB); > >+ geneveHdr->vni = GENEVE_TUNNELID_TO_VNI(tunKey->tunnelId); > >+ geneveHdr->reserved2 = 0; > >+ > >+ /* Geneve header options */ > >+ optHdr = (GeneveOptionHdr *)(geneveHdr + 1); > >+ memcpy(optHdr, TunnelKeyGetOptions(tunKey), tunKey->tunOptLen); > >+ > >+ csumInfo.Value = 0; > >+ csumInfo.Transmit.IpHeaderChecksum = 1; > >+ csumInfo.Transmit.IsIPv4 = 1; > >+ if (tunKey->flags & OVS_TNL_F_CSUM) { > >+ csumInfo.Transmit.UdpChecksum = 1; > >+ } > >+ NET_BUFFER_LIST_INFO(curNbl, > >+ TcpIpChecksumNetBufferListInfo) = > >csumInfo.Value; > >+ } > >+ return STATUS_SUCCESS; > >+ > >+ret_error: > >+ OvsCompleteNBL(switchContext, *newNbl, TRUE); > >+ *newNbl = NULL; > >+ return status; > >+} > >+ > >+NDIS_STATUS OvsDecapGeneve(POVS_SWITCH_CONTEXT switchContext, > >+ PNET_BUFFER_LIST curNbl, > >+ OvsIPv4TunnelKey *tunKey, > >+ PNET_BUFFER_LIST *newNbl) > >+{ > >+ PNET_BUFFER curNb; > >+ PMDL curMdl; > >+ EthHdr *ethHdr; > >+ IPHdr *ipHdr; > >+ UDPHdr *udpHdr; > >+ GeneveHdr *geneveHdr; > >+ UINT32 tunnelSize; > >+ UINT32 packetLength; > >+ PUINT8 bufferStart; > >+ PVOID optStart; > >+ NDIS_STATUS status; > >+ > >+ /* Check the length of the UDP payload */ > >+ curNb = NET_BUFFER_LIST_FIRST_NB(curNbl); > >+ tunnelSize = OvsGetGeneveTunHdrMinSize(); > >+ packetLength = NET_BUFFER_DATA_LENGTH(curNb); > >+ if (packetLength <= tunnelSize) { > >+ return NDIS_STATUS_INVALID_LENGTH; > >+ } > >+ > >+ /* > >+ * Create a copy of the NBL so that we have all the headers in one > >MDL. > >+ */ > >+ *newNbl = OvsPartialCopyNBL(switchContext, curNbl, > >+ tunnelSize, 0, > >+ TRUE /*copy NBL info */); > >+ > >+ if (*newNbl == NULL) { > >+ return NDIS_STATUS_RESOURCES; > >+ } > >+ > >+ /* XXX: Handle VLAN header. */ > >+ curNbl = *newNbl; > >+ curNb = NET_BUFFER_LIST_FIRST_NB(curNbl); > >+ curMdl = NET_BUFFER_CURRENT_MDL(curNb); > >+ bufferStart = (PUINT8)MmGetSystemAddressForMdlSafe(curMdl, > >LowPagePriority) + > >+ NET_BUFFER_CURRENT_MDL_OFFSET(curNb); > >+ if (!bufferStart) { > >+ status = NDIS_STATUS_RESOURCES; > >+ goto dropNbl; > >+ } > >+ > >+ ethHdr = (EthHdr *)bufferStart; > >+ /* XXX: Handle IP options. */ > >+ ipHdr = (IPHdr *)((PCHAR)ethHdr + sizeof *ethHdr); > >+ tunKey->src = ipHdr->saddr; > >+ tunKey->dst = ipHdr->daddr; > >+ tunKey->tos = ipHdr->tos; > >+ tunKey->ttl = ipHdr->ttl; > >+ tunKey->pad = 0; > >+ udpHdr = (UDPHdr *)((PCHAR)ipHdr + sizeof *ipHdr); > >+ > >+ /* Validate if NIC has indicated checksum failure. */ > >+ status = OvsValidateUDPChecksum(curNbl, udpHdr->check == 0); > >+ if (status != NDIS_STATUS_SUCCESS) { > >+ goto dropNbl; > >+ } > >+ > >+ /* Calculate and verify UDP checksum if NIC didn't do it. */ > >+ if (udpHdr->check != 0) { > >+ status = OvsCalculateUDPChecksum(curNbl, curNb, ipHdr, udpHdr, > >packetLength); > >+ tunKey->flags |= OVS_TNL_F_CSUM; > >+ if (status != NDIS_STATUS_SUCCESS) { > >+ goto dropNbl; > >+ } > >+ } > >+ > >+ geneveHdr = (GeneveHdr *)((PCHAR)udpHdr + sizeof *udpHdr); > >+ if (geneveHdr->protocol != htons(ETH_P_TEB)) { > >+ status = STATUS_NDIS_INVALID_PACKET; > >+ goto dropNbl; > >+ } > >+ tunKey->flags = OVS_TNL_F_KEY; > >+ if (geneveHdr->oam) { > >+ tunKey->flags |= OVS_TNL_F_OAM; > >+ } > >+ tunKey->tunnelId = GENEVE_VNI_TO_TUNNELID(geneveHdr->vni); > >+ tunKey->tunOptLen = (uint8)geneveHdr->optLen * 4; > >+ if (tunKey->tunOptLen > TUN_OPT_MAX_LEN || > >+ packetLength < tunnelSize + tunKey->tunOptLen) { > >+ status = NDIS_STATUS_INVALID_LENGTH; > >+ goto dropNbl; > >+ } > >+ /* Clear out the receive flag for the inner packet. */ > >+ NET_BUFFER_LIST_INFO(curNbl, TcpIpChecksumNetBufferListInfo) = 0; > >+ > >+ NdisAdvanceNetBufferDataStart(curNb, tunnelSize, FALSE, NULL); > >+ if (tunKey->tunOptLen > 0) { > >+ optStart = NdisGetDataBuffer(curNb, tunKey->tunOptLen, > >+ TunnelKeyGetOptions(tunKey), 1 /*no > >align*/, 0); > >+ > >+ /* If data is contiguous in the buffer, NdisGetDataBuffer will > >not copy > >+ data to the storage. Manual copy is needed. */ > >+ if (optStart != TunnelKeyGetOptions(tunKey)) { > >+ memcpy(TunnelKeyGetOptions(tunKey), optStart, > >tunKey->tunOptLen); > >+ } > >+ NdisAdvanceNetBufferDataStart(curNb, tunKey->tunOptLen, FALSE, > >NULL); > >+ } > >+ return NDIS_STATUS_SUCCESS; > >+ > >+dropNbl: > >+ OvsCompleteNBL(switchContext, *newNbl, TRUE); > >+ *newNbl = NULL; > >+ return status; > >+} > >diff --git a/datapath-windows/ovsext/Geneve.h > >b/datapath-windows/ovsext/Geneve.h > >new file mode 100644 > >index 0000000..74325a5 > >--- /dev/null > >+++ b/datapath-windows/ovsext/Geneve.h > >@@ -0,0 +1,122 @@ > >+/* > >+ * 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: > >+ * > >+ * > >https://urldefense.proofpoint.com/v2/url?u=http-3A__www.apache.org_license > >s_LICENSE-2D2.0&d=CwIGaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=p > >NHQcdr7B40b4h6Yb7FIedI1dnBsxdDuTLBYD3JqV80&m=62Xt8BBpUG4AqJ0X8YjOtMfZRYm0C > >1SOzdOxdvcn9ok&s=pd1fscKFk3BO3GSaqAVHqwpPhjWfuk9h4zFaTwkcPso&e= > >+ * > >+ * 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. > >+ */ > >+ > >+ > >+#ifndef __GENEVE_H_ > >+#define __GENEVE_H_ 1 > >+ > >+#include "NetProto.h" > >+typedef struct _OVS_GENEVE_VPORT { > >+ UINT16 dstPort; > >+ UINT64 filterID; > >+ UINT64 ipId; > >+ /* > >+ * To be filled > >+ */ > >+} OVS_GENEVE_VPORT, *POVS_GENEVE_VPORT; > >+ > >+/* Geneve Header: > >+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ > >+ * |Ver| Opt Len |O|C| Rsvd. | Protocol Type | > >+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ > >+ * | Virtual Network Identifier (VNI) | Reserved | > >+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ > >+ * | Variable Length Options | > >+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ > >+ * > >+ * Option Header: > >+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ > >+ * | Option Class | Type |R|R|R| Length | > >+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ > >+ * | Variable Option Data | > >+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ > >+ */ > >+typedef struct GeneveHdr { > >+ /* Length of options fields in int32 excluding the common header */ > >+ UINT32 optLen : 6; > >+ /* Version. */ > >+ UINT32 version:2; > >+ /* Reserved. */ > >+ UINT32 reserved1 : 6; > >+ /* Critical options present */ > >+ UINT32 critical : 1; > >+ /* This packet contains a control message instead of a data payload > >*/ > >+ UINT32 oam:1; > >+ /* Protocol Type. */ > >+ UINT32 protocol:16; > >+ /* VNI */ > >+ UINT32 vni:24; > >+ /* Reserved. */ > >+ UINT32 reserved2:8; > >+} GeneveHdr; > >+ > >+typedef struct GeneveOptionHdr { > >+ /* Namespace for the 'type' field. */ > >+ UINT32 optionClass:16; > >+ /* Format of data contained in the option. */ > >+ UINT32 type:8; > >+ /* Reserved. */ > >+ UINT32 reserved:3; > >+ /* Length of option in int32 excluding the option header. */ > >+ UINT32 length:5; > >+} GeneveOptionHdr; > >+ > >+#define GENEVE_CRIT_OPT_TYPE (1 << 7) > >+ > >+NTSTATUS OvsInitGeneveTunnel(POVS_VPORT_ENTRY vport, > >+ UINT16 udpDestPort); > >+ > >+VOID OvsCleanupGeneveTunnel(POVS_VPORT_ENTRY vport); > >+ > >+ > >+NDIS_STATUS OvsEncapGeneve(POVS_VPORT_ENTRY vport, > >+ PNET_BUFFER_LIST curNbl, > >+ OvsIPv4TunnelKey *tunKey, > >+ POVS_SWITCH_CONTEXT switchContext, > >+ POVS_PACKET_HDR_INFO layers, > >+ PNET_BUFFER_LIST *newNbl); > >+ > >+NDIS_STATUS OvsDecapGeneve(POVS_SWITCH_CONTEXT switchContext, > >+ PNET_BUFFER_LIST curNbl, > >+ OvsIPv4TunnelKey *tunKey, > >+ PNET_BUFFER_LIST *newNbl); > >+ > >+static __inline UINT32 > >+OvsGetGeneveTunHdrMinSize(VOID) > >+{ > >+ /* XXX: Can L2 include VLAN at all? */ > >+ return sizeof (EthHdr) + sizeof (IPHdr) + sizeof (UDPHdr) + > >+ sizeof (GeneveHdr); > >+} > >+ > >+static __inline UINT32 > >+OvsGetGeneveTunHdrMaxSize(VOID) > >+{ > >+ /* XXX: Can L2 include VLAN at all? */ > >+ return OvsGetGeneveTunHdrMinSize() + TUN_OPT_MAX_LEN; > >+} > >+ > >+#define GENEVE_UDP_PORT 6081 > >+#define GENEVE_UDP_PORT_NBO 0xC117 > >+#define GENEVE_VER 0 > >+#define GENEVE_DEFAULT_TTL 64 > >+#define GENEVE_ID_IS_VALID(geneveID) (0 < (geneveID) && (vxlanID) <= > >0xffffff) > >+#define GENEVE_TUNNELID_TO_VNI(_tID) (UINT32)(((UINT64)(_tID)) >> 40) > >+#define GENEVE_VNI_TO_TUNNELID(_vni) (((UINT64)(_vni)) << 40) > >+#define ETH_P_TEB 0x6558 /* Trans Ether Bridging */ > >+ > >+#endif /* __GENEVE_H_ */ > >+ > >diff --git a/datapath-windows/ovsext/Gre.c b/datapath-windows/ovsext/Gre.c > >index cb41593..fbcbdb4 100644 > >--- a/datapath-windows/ovsext/Gre.c > >+++ b/datapath-windows/ovsext/Gre.c > >@@ -299,7 +299,7 @@ OvsDecapGre(POVS_SWITCH_CONTEXT switchContext, > > EthHdr *ethHdr; > > IPHdr *ipHdr; > > GREHdr *greHdr; > >- UINT32 tunnelSize = 0, packetLength = 0; > >+ UINT32 tunnelSize, packetLength; > > UINT32 headRoom = 0; > > PUINT8 bufferStart; > > NDIS_STATUS status; > >@@ -307,7 +307,8 @@ OvsDecapGre(POVS_SWITCH_CONTEXT switchContext, > > curNb = NET_BUFFER_LIST_FIRST_NB(curNbl); > > packetLength = NET_BUFFER_DATA_LENGTH(curNb); > > tunnelSize = GreTunHdrSize(tunKey->flags); > >- if (packetLength <= tunnelSize) { > >+ > >+ if (packetLength < tunnelSize) { > > return NDIS_STATUS_INVALID_LENGTH; > > } > > > >@@ -315,7 +316,7 @@ OvsDecapGre(POVS_SWITCH_CONTEXT switchContext, > > * Create a copy of the NBL so that we have all the headers in one > >MDL. > > */ > > *newNbl = OvsPartialCopyNBL(switchContext, curNbl, > >- tunnelSize + OVS_DEFAULT_COPY_SIZE, 0, > >+ tunnelSize, 0, > > TRUE /*copy NBL info */); > > > > if (*newNbl == NULL) { > >diff --git a/datapath-windows/ovsext/Stt.c b/datapath-windows/ovsext/Stt.c > >index dd7bf92..f08ca27 100644 > >--- a/datapath-windows/ovsext/Stt.c > >+++ b/datapath-windows/ovsext/Stt.c > >@@ -761,7 +761,7 @@ OvsDecapStt(POVS_SWITCH_CONTEXT switchContext, > > advanceCnt = hdrLen; > > > > ipHdr = NdisGetDataBuffer(curNb, sizeof *ipHdr, (PVOID) &ipBuf, > >- 1 /*no align*/, 0); > >+ 1 /*no align*/, 0); > > ASSERT(ipHdr); > > > > TCPHdr *tcp = (TCPHdr *)((PCHAR)ipHdr + ipHdr->ihl * 4); > >diff --git a/datapath-windows/ovsext/Tunnel.c > >b/datapath-windows/ovsext/Tunnel.c > >index 97d2020..4f3ae3e 100644 > >--- a/datapath-windows/ovsext/Tunnel.c > >+++ b/datapath-windows/ovsext/Tunnel.c > >@@ -286,8 +286,7 @@ OvsInjectPacketThroughActions(PNET_BUFFER_LIST pNbl, > > SendFlags |= NDIS_SEND_FLAGS_DISPATCH_LEVEL; > > > > vport = OvsFindTunnelVportByDstPort(gOvsSwitchContext, > >- htons(tunnelKey.dst_port), > >- OVS_VPORT_TYPE_VXLAN); > >+ htons(tunnelKey.dst_port)); > > > > if (vport == NULL){ > > status = STATUS_UNSUCCESSFUL; > >diff --git a/datapath-windows/ovsext/Util.h > >b/datapath-windows/ovsext/Util.h > >index 4bcde3b..15793c0 100644 > >--- a/datapath-windows/ovsext/Util.h > >+++ b/datapath-windows/ovsext/Util.h > >@@ -38,6 +38,7 @@ > > #define OVS_TUNFLT_POOL_TAG 'WSVO' > > #define OVS_RECIRC_POOL_TAG 'CSVO' > > #define OVS_CT_POOL_TAG 'CTVO' > >+#define OVS_GENEVE_POOL_TAG 'GNVO' > > > > VOID *OvsAllocateMemory(size_t size); > > VOID *OvsAllocateMemoryWithTag(size_t size, ULONG tag); > >diff --git a/datapath-windows/ovsext/Vport.c > >b/datapath-windows/ovsext/Vport.c > >index 4299169..7e5cfc1 100644 > >--- a/datapath-windows/ovsext/Vport.c > >+++ b/datapath-windows/ovsext/Vport.c > >@@ -692,8 +692,7 @@ OvsFindVportByPortNo(POVS_SWITCH_CONTEXT > >switchContext, > > > > POVS_VPORT_ENTRY > > OvsFindTunnelVportByDstPort(POVS_SWITCH_CONTEXT switchContext, > >- UINT16 dstPort, > >- OVS_VPORT_TYPE ovsPortType) > >+ UINT16 dstPort) > > { > > POVS_VPORT_ENTRY vport; > > PLIST_ENTRY head, link; > >@@ -702,8 +701,7 @@ OvsFindTunnelVportByDstPort(POVS_SWITCH_CONTEXT > >switchContext, > > head = &(switchContext->tunnelVportsArray[hash & OVS_VPORT_MASK]); > > LIST_FORALL(head, link) { > > vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, > >tunnelVportLink); > >- if (GetPortFromPriv(vport) == dstPort && > >- vport->ovsType == ovsPortType) { > >+ if (GetPortFromPriv(vport) == dstPort) { > > return vport; > > } > > } > >@@ -1042,6 +1040,9 @@ OvsInitTunnelVport(PVOID userContext, > > case OVS_VPORT_TYPE_STT: > > status = OvsInitSttTunnel(vport, dstPort); > > break; > >+ case OVS_VPORT_TYPE_GENEVE: > >+ status = OvsInitGeneveTunnel(vport, dstPort); > >+ break; > > default: > > ASSERT(0); > > } > >@@ -1185,6 +1186,7 @@ InitOvsVportCommon(POVS_SWITCH_CONTEXT > >switchContext, > > case OVS_VPORT_TYPE_GRE: > > case OVS_VPORT_TYPE_VXLAN: > > case OVS_VPORT_TYPE_STT: > >+ case OVS_VPORT_TYPE_GENEVE: > > { > > UINT16 dstPort = GetPortFromPriv(vport); > > hash = OvsJhashBytes(&dstPort, > >@@ -1268,6 +1270,9 @@ OvsRemoveAndDeleteVport(PVOID usrParamsContext, > > return status; > > } > > } > >+ case OVS_VPORT_TYPE_GENEVE: > >+ OvsCleanupGeneveTunnel(vport); > >+ break; > > case OVS_VPORT_TYPE_STT: > > OvsCleanupSttTunnel(vport); > > break; > >@@ -1329,9 +1334,7 @@ OvsRemoveAndDeleteVport(PVOID usrParamsContext, > > InitializeListHead(&vport->ovsNameLink); > > RemoveEntryList(&vport->portNoLink); > > InitializeListHead(&vport->portNoLink); > >- if (OVS_VPORT_TYPE_VXLAN == vport->ovsType || > >- OVS_VPORT_TYPE_STT == vport->ovsType || > >- OVS_VPORT_TYPE_GRE == vport->ovsType) { > >+ if (OvsIsTunnelVportType(vport->ovsType)) { > > RemoveEntryList(&vport->tunnelVportLink); > > InitializeListHead(&vport->tunnelVportLink); > > } > >@@ -2227,6 +2230,9 @@ OvsNewVportCmdHandler(POVS_USER_PARAMS_CONTEXT > >usrParamsCtx, > > case OVS_VPORT_TYPE_VXLAN: > > transportPortDest = VXLAN_UDP_PORT; > > break; > >+ case OVS_VPORT_TYPE_GENEVE: > >+ transportPortDest = GENEVE_UDP_PORT; > >+ break; > > case OVS_VPORT_TYPE_STT: > > transportPortDest = STT_TCP_PORT; > > break; > >@@ -2336,6 +2342,9 @@ Cleanup: > > case OVS_VPORT_TYPE_STT: > > OvsCleanupSttTunnel(vport); > > break; > >+ case OVS_VPORT_TYPE_GENEVE: > >+ OvsCleanupGeneveTunnel(vport); > >+ break; > > default: > > ASSERT(!"Invalid tunnel port type"); > > } > >diff --git a/datapath-windows/ovsext/Vport.h > >b/datapath-windows/ovsext/Vport.h > >index 373896d..8f0b8a8 100644 > >--- a/datapath-windows/ovsext/Vport.h > >+++ b/datapath-windows/ovsext/Vport.h > >@@ -21,6 +21,7 @@ > > #include "Stt.h" > > #include "Switch.h" > > #include "VxLan.h" > >+#include "Geneve.h" > > > > #define OVS_MAX_DPPORTS MAXUINT16 > > #define OVS_DPPORT_NUMBER_INVALID OVS_MAX_DPPORTS > >@@ -146,8 +147,7 @@ POVS_VPORT_ENTRY > >OvsFindVportByPortIdAndNicIndex(POVS_SWITCH_CONTEXT switchConte > > NDIS_SWITCH_PORT_ID > >portId, > > NDIS_SWITCH_NIC_INDEX > >index); > > POVS_VPORT_ENTRY OvsFindTunnelVportByDstPort(POVS_SWITCH_CONTEXT > >switchContext, > >- UINT16 dstPort, > >- OVS_VPORT_TYPE > >ovsVportType); > >+ UINT16 dstPort); > > POVS_VPORT_ENTRY OvsFindTunnelVportByPortType(POVS_SWITCH_CONTEXT > >switchContext, > > OVS_VPORT_TYPE > >ovsPortType); > > > >@@ -181,7 +181,8 @@ OvsIsTunnelVportType(OVS_VPORT_TYPE ovsType) > > { > > return ovsType == OVS_VPORT_TYPE_VXLAN || > > ovsType == OVS_VPORT_TYPE_STT || > >- ovsType == OVS_VPORT_TYPE_GRE; > >+ ovsType == OVS_VPORT_TYPE_GRE || > >+ ovsType == OVS_VPORT_TYPE_GENEVE; > > } > > > > > >@@ -267,6 +268,9 @@ GetPortFromPriv(POVS_VPORT_ENTRY vport) > > case OVS_VPORT_TYPE_VXLAN: > > dstPort = ((POVS_VXLAN_VPORT)vportPriv)->dstPort; > > break; > >+ case OVS_VPORT_TYPE_GENEVE: > >+ dstPort = ((POVS_GENEVE_VPORT)vportPriv)->dstPort; > >+ break; > > default: > > ASSERT(! "Port is not a tunnel port"); > > } > >diff --git a/datapath-windows/ovsext/ovsext.vcxproj > >b/datapath-windows/ovsext/ovsext.vcxproj > >index 0356ddf..02fa60c 100644 > >--- a/datapath-windows/ovsext/ovsext.vcxproj > >+++ b/datapath-windows/ovsext/ovsext.vcxproj > >@@ -81,6 +81,7 @@ > > <ClInclude Include="Ethernet.h" /> > > <ClInclude Include="Event.h" /> > > <ClInclude Include="Flow.h" /> > >+ <ClInclude Include="Geneve.h" /> > > <ClInclude Include="Gre.h" /> > > <ClInclude Include="IpHelper.h" /> > > <ClInclude Include="Jhash.h" /> > >@@ -182,6 +183,7 @@ > > <ClCompile Include="Driver.c" /> > > <ClCompile Include="Event.c" /> > > <ClCompile Include="Flow.c" /> > >+ <ClCompile Include="Geneve.c" /> > > <ClCompile Include="Gre.c" /> > > <ClCompile Include="IpHelper.c" /> > > <ClCompile Include="Jhash.c" /> > >-- > >2.8.0.windows.1 > > > >_______________________________________________ > >dev mailing list > >dev@openvswitch.org > >https://urldefense.proofpoint.com/v2/url?u=http-3A__openvswitch.org_mailma > >n_listinfo_dev&d=CwIGaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=pN > >HQcdr7B40b4h6Yb7FIedI1dnBsxdDuTLBYD3JqV80&m=62Xt8BBpUG4AqJ0X8YjOtMfZRYm0C1 > >SOzdOxdvcn9ok&s=tl9Z_geYFFKX3JcT35a7Aj5CdmcG9m0Xjcovds_NlNE&e= > > _______________________________________________ > dev mailing list > dev@openvswitch.org > http://openvswitch.org/mailman/listinfo/dev _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev