Hi Sai! One small nit inline.
Thanks, Paul Acked-by: Paul-Daniel Boca <pb...@cloudbasesolutions.com> > -----Original Message----- > From: dev [mailto:dev-boun...@openvswitch.org] On Behalf Of Sairam > Venugopal > Sent: Tuesday, June 21, 2016 4:23 AM > To: dev@openvswitch.org > Subject: [ovs-dev] [PATCH 7/9] datapath-windows: Add support for dump- > conntrack in datapath > > Create the methods used for dumping conntrack entries from the hyper-v > datapath to userspace by means of netfilter netlink messages. Some of the > attributes are not supported by the datapath and have been defaulted to 0. > > Signed-off-by: Sairam Venugopal <vsai...@vmware.com> > --- > datapath-windows/ovsext/Conntrack-tcp.c | 59 +++++ > datapath-windows/ovsext/Conntrack.c | 447 > +++++++++++++++++++++++++++++++- > datapath-windows/ovsext/Conntrack.h | 5 + > datapath-windows/ovsext/Util.h | 4 + > 4 files changed, 512 insertions(+), 3 deletions(-) > > diff --git a/datapath-windows/ovsext/Conntrack-tcp.c b/datapath- > windows/ovsext/Conntrack-tcp.c > index 19925c3..1d60323 100644 > --- a/datapath-windows/ovsext/Conntrack-tcp.c > +++ b/datapath-windows/ovsext/Conntrack-tcp.c > @@ -523,3 +523,62 @@ OvsConntrackCreateTcpEntry(const TCPHdr *tcp, > > return &newconn->up; > } > + > +static __inline uint8_t > +OvsCtTcpPeerToProtoInfoFlags(const struct tcp_peer *peer) > +{ > + uint8_t res = 0; > + > + if (peer->wscale & CT_WSCALE_FLAG) { > + res |= CT_DPIF_TCPF_WINDOW_SCALE; > + } > + > + if (peer->wscale & CT_WSCALE_UNKNOWN) { > + res |= CT_DPIF_TCPF_BE_LIBERAL; > + } > + > + return res; > +} > + > +NDIS_STATUS > +OvsCtMapTcpProtoInfoToNl(PNL_BUFFER nlBuf, OVS_CT_ENTRY *conn_) > +{ > + struct conn_tcp *conn = OvsCastConntrackEntryToTcpEntry(conn_); > + NDIS_STATUS status = NDIS_STATUS_SUCCESS; > + UINT32 offset = 0; > + > + offset = NlMsgStartNested(nlBuf, CTA_PROTOINFO_TCP); > + if (!offset) { > + return NDIS_STATUS_FAILURE; > + } > + > + if (!NlMsgPutTailU8(nlBuf, CTA_PROTOINFO_TCP_STATE, > + conn->peer[0].state)) { > + status = NDIS_STATUS_FAILURE; > + goto done; > + } > + if (!NlMsgPutTailU8(nlBuf, CTA_PROTOINFO_TCP_WSCALE_ORIGINAL, > + (conn->peer[0].wscale & CT_WSCALE_MASK))) { > + status = NDIS_STATUS_FAILURE; > + goto done; > + } > + if (!NlMsgPutTailU8(nlBuf, CTA_PROTOINFO_TCP_WSCALE_REPLY, > + (conn->peer[1].wscale & CT_WSCALE_MASK))) { > + status = NDIS_STATUS_FAILURE; > + goto done; > + } > + if (!NlMsgPutTailU16(nlBuf, CTA_PROTOINFO_TCP_FLAGS_ORIGINAL, > + OvsCtTcpPeerToProtoInfoFlags(&conn->peer[0]))) { > + status = NDIS_STATUS_FAILURE; > + goto done; > + } > + if (!NlMsgPutTailU16(nlBuf, CTA_PROTOINFO_TCP_FLAGS_REPLY, > + OvsCtTcpPeerToProtoInfoFlags(&conn->peer[1]))) { > + status = NDIS_STATUS_FAILURE; > + goto done; > + } > + > +done: > + NlMsgEndNested(nlBuf, offset); > + return status; > +} > diff --git a/datapath-windows/ovsext/Conntrack.c b/datapath- > windows/ovsext/Conntrack.c > index 15c495d..2e628e5 100644 > --- a/datapath-windows/ovsext/Conntrack.c > +++ b/datapath-windows/ovsext/Conntrack.c > @@ -24,6 +24,10 @@ > #include "PacketParser.h" > #include "Debug.h" > > +#define WINDOWS_TICK 10000000 > +#define SEC_TO_UNIX_EPOCH 11644473600LL > +#define SEC_TO_NANOSEC 1000000000LL > + > typedef struct _OVS_CT_THREAD_CTX { > KEVENT event; > PVOID threadObject; > @@ -34,6 +38,7 @@ KSTART_ROUTINE ovsConntrackEntryCleaner; > static PLIST_ENTRY ovsConntrackTable; > static OVS_CT_THREAD_CTX ctThreadCtx; > static PNDIS_RW_LOCK_EX ovsConntrackLockObj; > +extern POVS_SWITCH_CONTEXT gOvsSwitchContext; > > /* > > *---------------------------------------------------------------------------- > @@ -147,11 +152,12 @@ OvsCtUpdateFlowKey(struct OvsFlowKey *key, > } > > static __inline VOID > -OvsCtAddEntry(POVS_CT_ENTRY entry, OvsConntrackKeyLookupCtx *ctx) > +OvsCtAddEntry(POVS_CT_ENTRY entry, OvsConntrackKeyLookupCtx *ctx, > UINT64 now) > { > NdisMoveMemory(&entry->key, &ctx->key, sizeof (OVS_CT_KEY)); > NdisMoveMemory(&entry->rev_key, &ctx->key, sizeof (OVS_CT_KEY)); > OvsCtKeyReverse(&entry->rev_key); > + entry->timestampStart = now; > InsertHeadList(&ovsConntrackTable[ctx->hash & CT_HASH_TABLE_MASK], > &entry->link); > } > @@ -181,7 +187,10 @@ OvsCtEntryCreate(PNET_BUFFER_LIST curNbl, > state |= OVS_CS_F_NEW; > if (commit) { > entry = OvsConntrackCreateTcpEntry(tcp, curNbl, currentTime); > - OvsCtAddEntry(entry, ctx); > + if (!entry) { > + return NULL; > + } > + OvsCtAddEntry(entry, ctx, currentTime); > } > > OvsCtUpdateFlowKey(key, state, ctx->key.zone, 0, NULL); > @@ -192,7 +201,10 @@ OvsCtEntryCreate(PNET_BUFFER_LIST curNbl, > state |= OVS_CS_F_NEW; > if (commit) { > entry = OvsConntrackCreateOtherEntry(currentTime); > - OvsCtAddEntry(entry, ctx); > + if (!entry) { > + return NULL; > + } > + OvsCtAddEntry(entry, ctx, currentTime); > } > > OvsCtUpdateFlowKey(key, state, ctx->key.zone, 0, NULL); > @@ -290,6 +302,18 @@ OvsCtKeyAreSame(OVS_CT_KEY ctxKey, > OVS_CT_KEY entryKey) > (ctxKey.zone == entryKey.zone)); > } > > +static __inline VOID > +OvsCtIncrementCounters(POVS_CT_ENTRY entry, BOOLEAN reply, > PNET_BUFFER_LIST nbl) > +{ > + if (reply) { > + entry->rev_key.byteCount+= OvsPacketLenNBL(nbl); > + entry->rev_key.packetCount++; > + } else { > + entry->key.byteCount += OvsPacketLenNBL(nbl);; [Paul Boca] Double ';' at the end of line > + entry->key.packetCount++; > + } > +} > + > static __inline POVS_CT_ENTRY > OvsCtLookup(OvsConntrackKeyLookupCtx *ctx) > { > @@ -440,6 +464,9 @@ OvsProcessConntrackEntry(PNET_BUFFER_LIST > curNbl, > ctx->entry = NULL; > entry = OvsCtEntryCreate(curNbl, key->ipKey.nwProto, l4Offset, > ctx, key, commit, currentTime); > + if (!entry) { > + return NULL; > + } > break; > } > } > @@ -517,6 +544,7 @@ OvsCtExecute_(PNET_BUFFER_LIST curNbl, > key, commit, currentTime); > } else { > /* Process the entry and update CT flags */ > + OvsCtIncrementCounters(entry, ctx.reply, curNbl); > entry = OvsProcessConntrackEntry(curNbl, layers->l4Offset, &ctx, key, > zone, commit, currentTime); > } > @@ -699,3 +727,416 @@ done: > > return status; > } > + > +static __inline NDIS_STATUS > +MapIpTupleToNl(PNL_BUFFER nlBuf, OVS_CT_KEY *key) > +{ > + NDIS_STATUS status = NDIS_STATUS_SUCCESS; > + UINT32 offset = 0; > + > + offset = NlMsgStartNested(nlBuf, CTA_TUPLE_IP); > + if (!offset) { > + return NDIS_STATUS_FAILURE; > + } > + > + if (key->dl_type == ntohs(ETH_TYPE_IPV4)) { > + if (!NlMsgPutTailU32(nlBuf, CTA_IP_V4_SRC, key->src.addr.ipv4)) { > + status = NDIS_STATUS_FAILURE; > + goto done; > + } > + if (!NlMsgPutTailU32(nlBuf, CTA_IP_V4_DST, key->dst.addr.ipv4)) { > + status = NDIS_STATUS_FAILURE; > + goto done; > + } > + } else if (key->dl_type == ntohs(ETH_TYPE_IPV6)) { > + if (!NlMsgPutTailUnspec(nlBuf, CTA_IP_V6_SRC, > + (PCHAR)(&key->src.addr.ipv6), > + sizeof(key->src.addr.ipv6))) { > + status = NDIS_STATUS_FAILURE; > + goto done; > + } > + if (!NlMsgPutTailUnspec(nlBuf, CTA_IP_V6_DST, > + (PCHAR)(&key->dst.addr.ipv6), > + sizeof(key->dst.addr.ipv6))) { > + status = NDIS_STATUS_FAILURE; > + goto done; > + } > + } > + > +done: > + NlMsgEndNested(nlBuf, offset); > + return status; > +} > + > +static __inline NDIS_STATUS > +MapProtoTupleToNl(PNL_BUFFER nlBuf, OVS_CT_KEY *key) > +{ > + NDIS_STATUS status = NDIS_STATUS_SUCCESS; > + UINT32 offset = 0; > + > + offset = NlMsgStartNested(nlBuf, CTA_TUPLE_PROTO); > + if (!offset) { > + return NDIS_STATUS_FAILURE; > + } > + > + if (!NlMsgPutTailU8(nlBuf, CTA_PROTO_NUM, key->nw_proto)) { > + status = NDIS_STATUS_FAILURE; > + goto done; > + } > + > + if (key->dl_type == ntohs(ETH_TYPE_IPV4) > + || 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)) { > + status = NDIS_STATUS_FAILURE; > + goto done; > + } > + if (!NlMsgPutTailU8(nlBuf, CTA_PROTO_ICMP_TYPE, 0)) { > + status = NDIS_STATUS_FAILURE; > + goto done; > + } > + if (!NlMsgPutTailU8(nlBuf, CTA_PROTO_ICMP_CODE, 0)) { > + status = NDIS_STATUS_FAILURE; > + goto done; > + } > + } else if (key->nw_proto == IPPROTO_ICMP) { > + if (!NlMsgPutTailU16(nlBuf, CTA_PROTO_ICMPV6_ID, 0)) { > + status = NDIS_STATUS_FAILURE; > + goto done; > + } > + if (!NlMsgPutTailU8(nlBuf, CTA_PROTO_ICMPV6_TYPE, 0)) { > + status = NDIS_STATUS_FAILURE; > + goto done; > + } > + if (!NlMsgPutTailU8(nlBuf, CTA_PROTO_ICMPV6_CODE, 0)) { > + status = NDIS_STATUS_FAILURE; > + goto done; > + } > + } else { > + if (!NlMsgPutTailU16(nlBuf, CTA_PROTO_SRC_PORT, > + key->src.port)) { > + status = NDIS_STATUS_FAILURE; > + goto done; > + } > + if (!NlMsgPutTailU16(nlBuf, CTA_PROTO_DST_PORT, > + key->dst.port)) { > + status = NDIS_STATUS_FAILURE; > + goto done; > + } > + } > + } > + > +done: > + NlMsgEndNested(nlBuf, offset); > + return status; > +} > + > +static __inline NDIS_STATUS > +MapCtKeyTupleToNl(PNL_BUFFER nlBuf, > + UINT16 tupleType, > + OVS_CT_KEY *key) > +{ > + NDIS_STATUS status = NDIS_STATUS_SUCCESS; > + UINT32 offset = 0; > + > + offset = NlMsgStartNested(nlBuf, tupleType); > + if (!offset) { > + return NDIS_STATUS_FAILURE; > + } > + > + status = MapIpTupleToNl(nlBuf, key); > + if (status != NDIS_STATUS_SUCCESS) { > + goto done; > + } > + > + status = MapProtoTupleToNl(nlBuf, key); > + if (status != NDIS_STATUS_SUCCESS) { > + goto done; > + } > + > +done: > + NlMsgEndNested(nlBuf, offset); > + return status; > +} > + > +static __inline NDIS_STATUS > +MapCtCounterToNl(PNL_BUFFER nlBuf, > + UINT16 counterType, > + OVS_CT_KEY *key) > +{ > + NDIS_STATUS status = NDIS_STATUS_SUCCESS; > + UINT32 offset = 0; > + > + offset = NlMsgStartNested(nlBuf, counterType); > + if (!offset) { > + return NDIS_STATUS_FAILURE; > + } > + > + if (!NlMsgPutTailU64(nlBuf, CTA_COUNTERS_PACKETS, > + htonll(key->packetCount))) { > + status = NDIS_STATUS_FAILURE; > + goto done; > + } > + > + if (!NlMsgPutTailU64(nlBuf, CTA_COUNTERS_BYTES, > + htonll(key->byteCount))) { > + status = NDIS_STATUS_FAILURE; > + goto done; > + } > + > +done: > + NlMsgEndNested(nlBuf, offset); > + return status; > +} > + > +/* Userspace expects system time to be Unix timestamp in Nano Seconds */ > +static __inline unsigned > +WindowsTickToUnixSeconds(long long windowsTicks) > +{ > + /* > + Windows epoch starts 1601-01-01T00:00:00Z. It's 11644473600 seconds > + before the UNIX/Linux epoch (1970-01-01T00:00:00Z). Windows ticks > are > + in 100 nanoseconds > + */ > + return (unsigned)((windowsTicks / WINDOWS_TICK > + - SEC_TO_UNIX_EPOCH)); > +} > + > +static NTSTATUS > +OvsCreateNlMsgFromCtEntry(POVS_CT_ENTRY entry, > + POVS_MESSAGE msgIn, > + PVOID outBuffer, > + UINT32 outBufLen, > + int dpIfIndex) > +{ > + NL_BUFFER nlBuf; > + BOOLEAN ok; > + PNL_MSG_HDR nlMsg; > + UINT32 timeout; > + NDIS_STATUS status; > + UINT64 currentTime, expiration; > + NdisGetCurrentSystemTime((LARGE_INTEGER *)¤tTime); > + UINT8 nfgenFamily = 0; > + if (entry->key.dl_type == htons(ETH_TYPE_IPV4)) { > + nfgenFamily = AF_INET; > + } else if (entry->key.dl_type == htons(ETH_TYPE_IPV6)) { > + nfgenFamily = AF_INET6; > + } > + > + NlBufInit(&nlBuf, outBuffer, outBufLen); > + /* Mimic netfilter */ > + UINT16 nlmsgType = (NFNL_SUBSYS_CTNETLINK << 8 | > IPCTNL_MSG_CT_NEW); > + ok = NlFillOvsMsgForNfGenMsg(&nlBuf, nlmsgType, NLM_F_CREATE, > + msgIn->nlMsg.nlmsgSeq, > + msgIn->nlMsg.nlmsgPid, > + nfgenFamily, > + msgIn->nfGenMsg.version, > + dpIfIndex); > + if (!ok) { > + return STATUS_INVALID_BUFFER_SIZE; > + } > + > + status = MapCtKeyTupleToNl(&nlBuf, CTA_TUPLE_ORIG, &entry->key); > + if (status != NDIS_STATUS_SUCCESS) { > + return STATUS_UNSUCCESSFUL; > + } > + > + status = MapCtKeyTupleToNl(&nlBuf, CTA_TUPLE_REPLY, &entry- > >rev_key); > + if (status != NDIS_STATUS_SUCCESS) { > + return STATUS_UNSUCCESSFUL; > + } > + > + status = MapCtCounterToNl(&nlBuf, CTA_COUNTERS_ORIG, &entry->key); > + if (status != NDIS_STATUS_SUCCESS) { > + return STATUS_UNSUCCESSFUL; > + } > + > + status = MapCtCounterToNl(&nlBuf, CTA_COUNTERS_REPLY, &entry- > >rev_key); > + if (status != NDIS_STATUS_SUCCESS) { > + return STATUS_UNSUCCESSFUL; > + } > + > + if (entry->key.zone) { > + if (!NlMsgPutTailU16(&nlBuf, CTA_ZONE, htons(entry->key.zone))) { > + return STATUS_INVALID_BUFFER_SIZE; > + } > + } > + > + if (entry->mark) { > + if (!NlMsgPutTailU32(&nlBuf, CTA_MARK, htonl(entry->mark))) { > + return STATUS_INVALID_BUFFER_SIZE; > + } > + } > + > + if (entry->labels.ct_labels) { > + ok = NlMsgPutTailUnspec(&nlBuf, CTA_LABELS, > + (PCHAR)(&entry->labels), > + sizeof(entry->labels)); > + if (!ok) { > + return STATUS_INVALID_BUFFER_SIZE; > + } > + } > + > + expiration = entry->expiration - currentTime; > + timeout = (UINT32) ((expiration > 0) ? expiration / CT_INTERVAL_SEC: 0); > + if (timeout > 0) { > + if (!NlMsgPutTailU32(&nlBuf, CTA_TIMEOUT, htonl(timeout))) { > + return STATUS_INVALID_BUFFER_SIZE; > + } > + } > + > + if (entry->key.nw_proto == IPPROTO_TCP) { > + /* Add ProtoInfo for TCP */ > + UINT32 offset; > + offset = NlMsgStartNested(&nlBuf, CTA_PROTOINFO); > + if (!offset) { > + return NDIS_STATUS_FAILURE; > + } > + > + status = OvsCtMapTcpProtoInfoToNl(&nlBuf, entry); > + if (status != NDIS_STATUS_SUCCESS) { > + return STATUS_UNSUCCESSFUL; > + } > + > + NlMsgEndNested(&nlBuf, offset); > + } > + > + /* CTA_STATUS is required but not implemented. Default to 0 */ > + if (!NlMsgPutTailU32(&nlBuf, CTA_STATUS, 0)) { > + return STATUS_INVALID_BUFFER_SIZE; > + } > + > + /* Mimic netfilter - nf_conntrack_netlink.c: > + static inline int ctnetlink_dump_id(struct sk_buff *skb, const struct > nf_conn *ct) { > + NLA_PUT_BE32(skb, CTA_ID, htonl((unsigned long)ct)); > + return 0; > + } > + */ > + if(!NlMsgPutTailU32(&nlBuf, CTA_ID, htonl((UINT32) entry))) { > + return STATUS_INVALID_BUFFER_SIZE; > + } > + > + if (entry->timestampStart) { > + UINT32 offset; > + offset = NlMsgStartNested(&nlBuf, CTA_TIMESTAMP); > + if (!offset) { > + return NDIS_STATUS_FAILURE; > + } > + UINT64 start; > + start = WindowsTickToUnixSeconds(entry->timestampStart); > + start = start * SEC_TO_NANOSEC; > + if (!NlMsgPutTailU64(&nlBuf, CTA_TIMESTAMP_START, htonll(start))) { > + return STATUS_INVALID_BUFFER_SIZE; > + } > + > + NlMsgEndNested(&nlBuf, offset); > + } > + > + nlMsg = (PNL_MSG_HDR)NlBufAt(&nlBuf, 0, 0); > + nlMsg->nlmsgLen = NlBufSize(&nlBuf); > + > + return STATUS_SUCCESS; > +} > + > +/* > + > *---------------------------------------------------------------------------- > + * OvsCtDumpCmdHandler -- > + * Handler for IPCTNL_MSG_CT_GET command. > + * > + * XXX - Try to consolidate dump handler patterns around dumpState usage > + * The following dumpHandler is similar to one vport.c uses > + > *---------------------------------------------------------------------------- > +*/ > +NTSTATUS > +OvsCtDumpCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, > + UINT32 *replyLen) > +{ > + NTSTATUS rc; > + /* Setup Dump Start if it's OVS_WRITE_DEV_OP and return */ > + if (usrParamsCtx->devOp == OVS_WRITE_DEV_OP) { > + *replyLen = 0; > + OvsSetupDumpStart(usrParamsCtx); > + return STATUS_SUCCESS; > + } > + > + POVS_OPEN_INSTANCE instance = > + (POVS_OPEN_INSTANCE)usrParamsCtx->ovsInstance; > + POVS_MESSAGE msgIn; > + UINT32 i; > + > + ASSERT(usrParamsCtx->devOp == OVS_READ_DEV_OP); > + if (instance->dumpState.ovsMsg == NULL) { > + ASSERT(FALSE); > + return STATUS_INVALID_DEVICE_STATE; > + } > + > + /* Output buffer has been validated while validating read dev op. */ > + ASSERT(usrParamsCtx->outputBuffer != NULL); > + msgIn = instance->dumpState.ovsMsg; > + UINT32 inBucket = instance->dumpState.index[0]; > + UINT32 inIndex = instance->dumpState.index[1]; > + UINT32 outIndex = 0; > + > + LOCK_STATE_EX lockState; > + NdisAcquireRWLockRead(ovsConntrackLockObj, &lockState, 0); > + > + for (i = inBucket; i < CT_HASH_TABLE_SIZE; i++) { > + PLIST_ENTRY head, link; > + head = &ovsConntrackTable[i]; > + POVS_CT_ENTRY entry = NULL; > + > + outIndex = 0; > + LIST_FORALL(head, link) { > + /* > + * if one or more dumps were previously done on this same > bucket, > + * inIndex will be > 0, so we'll need to reply with the > + * inIndex + 1 ct-entry from the bucket. > + */ > + if (outIndex >= inIndex) { > + entry = CONTAINING_RECORD(link, OVS_CT_ENTRY, link); > + > + rc = OvsCreateNlMsgFromCtEntry(entry, msgIn, > + usrParamsCtx->outputBuffer, > + usrParamsCtx->outputLength, > + gOvsSwitchContext->dpNo); > + > + if (rc != NDIS_STATUS_SUCCESS) { > + NdisReleaseRWLock(ovsConntrackLockObj, &lockState); > + return STATUS_UNSUCCESSFUL; > + } > + > + ++outIndex; > + break; > + } > + > + ++outIndex; > + } > + > + if (entry) { > + break; > + } > + > + /* > + * if no ct-entry was found above, check the next bucket, > beginning > + * with the first (i.e. index 0) elem from within that bucket > + */ > + inIndex = 0; > + } > + > + instance->dumpState.index[0] = i; > + instance->dumpState.index[1] = outIndex; > + NdisReleaseRWLock(ovsConntrackLockObj, &lockState); > + > + /* if i < CT_HASH_TABLE_SIZE => entry was found */ > + if (i < CT_HASH_TABLE_SIZE) { > + POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx- > >outputBuffer; > + *replyLen = msgOut->nlMsg.nlmsgLen; > + } else { > + /* if i >= CT_HASH_TABLE_SIZE => entry was not found => dump done > */ > + *replyLen = 0; > + FreeUserDumpState(instance); > + } > + > + return STATUS_SUCCESS; > +} > diff --git a/datapath-windows/ovsext/Conntrack.h b/datapath- > windows/ovsext/Conntrack.h > index 883ac57..6d573c8 100644 > --- a/datapath-windows/ovsext/Conntrack.h > +++ b/datapath-windows/ovsext/Conntrack.h > @@ -59,6 +59,8 @@ typedef struct _OVS_CT_KEY { > UINT16 dl_type; > UINT8 nw_proto; > UINT16 zone; > + UINT64 packetCount; > + UINT64 byteCount; > } OVS_CT_KEY, *POVS_CT_KEY; > > typedef struct OVS_CT_ENTRY { > @@ -67,6 +69,7 @@ typedef struct OVS_CT_ENTRY { > UINT64 expiration; > LIST_ENTRY link; > UINT32 mark; > + UINT64 timestampStart; > struct ovs_key_ct_labels labels; > } OVS_CT_ENTRY, *POVS_CT_ENTRY; > > @@ -102,6 +105,8 @@ BOOLEAN OvsConntrackValidateTcpPacket(const > TCPHdr *tcp); > 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); > enum CT_UPDATE_RES OvsConntrackUpdateTcpEntry(OVS_CT_ENTRY* > conn_, > const TCPHdr *tcp, > diff --git a/datapath-windows/ovsext/Util.h b/datapath- > windows/ovsext/Util.h > index 4bcde3b..aa54322 100644 > --- a/datapath-windows/ovsext/Util.h > +++ b/datapath-windows/ovsext/Util.h > @@ -79,6 +79,10 @@ VOID OvsAppendList(PLIST_ENTRY dst, PLIST_ENTRY > src); > #define ntohs(_x) _byteswap_ushort((USHORT)(_x)) > #define htonl(_x) _byteswap_ulong((ULONG)(_x)) > #define ntohl(_x) _byteswap_ulong((ULONG)(_x)) > +#define htonll(_x) ((1==htonl(1)) ? (_x) : \ > + ((uint64_t) htonl(_x) << 32) | htonl(_x >> 32)) > +#define ntohll(_x) ((1==ntohl(1)) ? (_x) : \ > + ((uint64_t) ntohl(_x) << 32) | ntohl(_x >> 32)) > #endif > > #define OVS_INIT_OBJECT_HEADER(_obj, _type, _revision, _size) \ > -- > 2.5.0.windows.1 > > _______________________________________________ > dev mailing list > dev@openvswitch.org > http://openvswitch.org/mailman/listinfo/dev _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev