summaryrefslogtreecommitdiff
path: root/datapath-windows/ovsext/Conntrack.c
diff options
context:
space:
mode:
authorldejing <ldejing@vmware.com>2022-04-11 18:07:11 +0800
committerAlin-Gabriel Serdean <aserdean@ovn.org>2022-04-22 12:08:38 +0300
commit53b75e91ded95d25c6cae5698ad242ad775ebb40 (patch)
tree913638673d2db7d164b1a07b989167d490efb670 /datapath-windows/ovsext/Conntrack.c
parent96dc66ddadc35475ed93b25a84874c926f4d9dd3 (diff)
downloadopenvswitch-53b75e91ded95d25c6cae5698ad242ad775ebb40.tar.gz
datapath-windows: Add IPv6 conntrack support on Windows.
Implementation on Windows: Currently, IPv4 conntrack was supported on the windows platform. In this patch we have implemented ipv6 conntrack functions according to the current logic of the IPv4 conntrack. This implementation has included TcpV6(nat and normal scenario), UdpV6(nat and normal scenario), IcmpV6 conntrack of echo request/reply packet and FtpV6(nat and normal scenario). Testing Topology: On the Windows VM runs on the ESXi host, two hyper-v ports attached to the ovs bridge; one hyper-v port worked as client and the other port worked as server. Testing Case: 1. TcpV6 a) Tcp request/reply conntrack for normal scenario. In this scenario, 20::1 as client, 20::2 as server, it will generate following conntrack entry: (Origin(src=20::1, src_port=1555, dst=20::2, dst_port=1556), reply(src=20::2,src_port=1556,dst=20::1,dst_port=1555),protocol=tcp) b) Tcp request/reply conntrack for nat scenario. In this scenario, 20::1 as client, 20::10 as floating ip, 21::3 as server, it will generate following conntrack entry: (Origin(src=20::1, src_port=1555, dst=20::10, dst_port=1556), reply(src=21::3, src_port=1556, dst=20::1, dst_port= 1555),protocol=tcp) 2. UdpV6 a) Udp request/reply conntrack for normal scenario. (Origin(src=20::1, src_port=1555, dst=20::2, dst_port=1556), reply(src=20::2,src_port=1556,dst=20::1,dst_port=1555),protocol=udp) b) Udp request/reply conntrack for nat scenario. (Origin(src=20::1, src_port=1555, dst=20::10, dst_port=1556), reply(src=21::3, src_port=1556, dst=20::1, dst_port= 1555),protocol=udp) 3. IcmpV6: a) Icmpv6 request/reply conntrack for normal scenario. Currently Icmpv6 only support to construct conntrack for echo request/reply packet, take (20::1 -> 20::2) for example, it will generate following conntrack entry: (origin(src = 20::1, dst=20::2), reply(src=20::2, dst=20::1), protocol=icmp) b) Icmp request/reply conntrack for dnat scenario, for example (20::1->20::10->21::3), 20::1 is client, 20::10 is floating ip, 21::3 is server ip. It will generate flow like below: (origin(src=20::1, dst=20::10), reply(src=21::3, dst=20::1), protocol=icmp) 4. FtpV6 a) Ftp request/reply conntrack for normal scenario. In this scenario, take 20::1 as client, 20::2 as server, it will generate two conntrack entries: Ftp active mode (Origin(src=20::1, src_port=1555, dst=20::2, dst_port=21), reply(src=20::2, src_port=21, dst=20::1, dst_port=1555), protocol=tcp) (Origin(src=20::2, src_port=20, dst=20::1, dst_port=1556), reply(src=20::1, src_port=1556, dst=20::2, dst_port=20), protocol=tcp) Ftp passive mode (Origin(src=20::1, src_port=1555, dst=20::2, dst_port=21), reply(src=20::2,src_port=21,dst=20::1,dst_port=1555),protocol=tcp) (Origin(src=20::1, src_port=1556, dst=20::2, dst_port=1557), reply(src=20::2,src_port=1557, dst=20::1, dst_port=1556) protocol=tcp) b) Ftp request/reply conntrack for nat scenario. Ftp passive mode, In this secnario, 20::1 as client, 20::10 as floating ip, 21::3 as server ip. It will generate following flow: (Origin(src=20::1, src_port=1555, dst=20::10, dst_port=21), reply(src=21::3, src_port=21, dst=20::1, dst_port= 1555),protocol=tcp) (Origin(src=20::1, src_port=1556, dst=20::10, dst_port=1557), reply(src=21::3, src_port=1557, dst=20::1, dst_port= 1556),protocol=tcp) 5. Regression test for IpV4 in Antrea project (about 60 test case) Future work: 1) IcmpV6 redirect packet conntrack. 2) IpV6 fragment support on Udp. 3) Support napt for IPv6. 4) FtpV6 active mode for nat. Signed-off-by: ldejing <ldejing@vmware.com> Signed-off-by: Alin-Gabriel Serdean <aserdean@ovn.org>
Diffstat (limited to 'datapath-windows/ovsext/Conntrack.c')
-rw-r--r--datapath-windows/ovsext/Conntrack.c287
1 files changed, 263 insertions, 24 deletions
diff --git a/datapath-windows/ovsext/Conntrack.c b/datapath-windows/ovsext/Conntrack.c
index 237efa9e9..471bf961b 100644
--- a/datapath-windows/ovsext/Conntrack.c
+++ b/datapath-windows/ovsext/Conntrack.c
@@ -189,6 +189,13 @@ OvsCtSetZoneLimit(int zone, ULONG value) {
NdisReleaseSpinLock(&ovsCtZoneLock);
}
+static uint32_t
+OvsCtEndpointHashAdd(uint32_t hash, const struct ct_endpoint *ep)
+{
+ BUILD_ASSERT_DECL(sizeof *ep % 4 == 0);
+ return OvsJhashBytes((UINT32 *)ep, sizeof *ep, hash);
+}
+
/*
*----------------------------------------------------------------------------
* OvsCtHashKey
@@ -199,8 +206,10 @@ UINT32
OvsCtHashKey(const OVS_CT_KEY *key)
{
UINT32 hsrc, hdst, hash;
- hsrc = key->src.addr.ipv4 | ntohl(key->src.port);
- hdst = key->dst.addr.ipv4 | ntohl(key->dst.port);
+ hsrc = ntohl(key->src.port);
+ hdst = ntohl(key->dst.port);
+ hsrc = OvsCtEndpointHashAdd(hsrc, &key->src);
+ hdst = OvsCtEndpointHashAdd(hdst, &key->dst);
hash = hsrc ^ hdst; /* TO identify reverse traffic */
hash = hash | (key->zone + key->nw_proto);
hash = OvsJhashWords((uint32_t*) &hash, 1, hash);
@@ -341,6 +350,26 @@ OvsCtEntryCreate(OvsForwardingContext *fwdCtx,
}
break;
}
+ case IPPROTO_ICMPV6:
+ {
+ ICMPHdr storage;
+ const ICMPHdr *icmp;
+ icmp = OvsGetIcmp(curNbl, layers->l4Offset, &storage);
+ if (!OvsConntrackValidateIcmp6Packet(icmp)) {
+ if(icmp) {
+ OVS_LOG_TRACE("Invalid ICMP packet detected, icmp->type %u",
+ icmp->type);
+ }
+ state = OVS_CS_F_INVALID;
+ break;
+ }
+
+ if (commit) {
+ entry = OvsConntrackCreateIcmpEntry(currentTime);
+ }
+ break;
+ }
+
case IPPROTO_ICMP:
{
ICMPHdr storage;
@@ -435,6 +464,15 @@ OvsCtUpdateEntry(OVS_CT_ENTRY* entry,
NdisReleaseSpinLock(&(entry->lock));
break;
}
+
+ case IPPROTO_ICMPV6:
+ {
+ NdisAcquireSpinLock(&(entry->lock));
+ status = OvsConntrackUpdateIcmpEntry(entry, reply, now);
+ NdisReleaseSpinLock(&(entry->lock));
+ break;
+ }
+
case IPPROTO_UDP:
{
NdisAcquireSpinLock(&(entry->lock));
@@ -528,6 +566,23 @@ OvsDetectCtPacket(OvsForwardingContext *fwdCtx,
}
return NDIS_STATUS_NOT_SUPPORTED;
case ETH_TYPE_IPV6:
+ if (key->ipv6Key.nwProto == IPPROTO_ICMPV6
+ || key->ipv6Key.nwProto == IPPROTO_TCP
+ || key->ipv6Key.nwProto == IPPROTO_UDP) {
+ /** TODO fragment **/
+
+ /** Extract flow key from packet and assign it to
+ * returned parameter. **/
+ status = OvsExtractFlow(fwdCtx->curNbl, fwdCtx->srcVportNo,
+ &newFlowKey, &fwdCtx->layers,
+ !OvsIphIsZero(&(fwdCtx->tunKey.dst)) ? &(fwdCtx->tunKey) : NULL);
+ if (status != NDIS_STATUS_SUCCESS) {
+ OVS_LOG_ERROR("Extract flow for ipv6 failed Nbl %p", fwdCtx->curNbl);
+ return status;
+ }
+ *key = newFlowKey;
+ return NDIS_STATUS_SUCCESS;
+ }
return NDIS_STATUS_NOT_SUPPORTED;
}
@@ -606,6 +661,54 @@ OvsCtLookup(OvsConntrackKeyLookupCtx *ctx)
return found;
}
+const TCPHdr*
+OvsGetTcpHeader(PNET_BUFFER_LIST nbl,
+ OVS_PACKET_HDR_INFO *layers,
+ VOID *storage,
+ UINT32 *tcpPayloadLen)
+{
+ IPHdr *ipHdr;
+ IPv6Hdr *ipv6Hdr;
+ TCPHdr *tcp;
+ VOID *dest = storage;
+ uint16_t ipv6ExtLength = 0;
+
+ if (layers->isIPv6) {
+ ipv6Hdr = NdisGetDataBuffer(NET_BUFFER_LIST_FIRST_NB(nbl),
+ layers->l4Offset + sizeof(TCPHdr),
+ NULL, 1, 0);
+ if (ipv6Hdr == NULL) {
+ return NULL;
+ }
+
+ tcp = (TCPHdr *)((PCHAR)ipv6Hdr + layers->l4Offset);
+ ipv6Hdr = (IPv6Hdr *)((PCHAR)ipv6Hdr + layers->l3Offset);
+ if (tcp->doff * 4 >= sizeof *tcp) {
+ NdisMoveMemory(dest, tcp, sizeof(TCPHdr));
+ ipv6ExtLength = layers->l4Offset - layers->l3Offset - sizeof(IPv6Hdr);
+ *tcpPayloadLen = (ntohs(ipv6Hdr->payload_len) - ipv6ExtLength - TCP_HDR_LEN(tcp));
+ return storage;
+ }
+ } else {
+ ipHdr = NdisGetDataBuffer(NET_BUFFER_LIST_FIRST_NB(nbl),
+ layers->l4Offset + sizeof(TCPHdr),
+ NULL, 1 /*no align*/, 0);
+ if (ipHdr == NULL) {
+ return NULL;
+ }
+
+ ipHdr = (IPHdr *)((PCHAR)ipHdr + layers->l3Offset);
+ tcp = (TCPHdr *)((PCHAR)ipHdr + ipHdr->ihl * 4);
+
+ if (tcp->doff * 4 >= sizeof *tcp) {
+ NdisMoveMemory(dest, tcp, sizeof(TCPHdr));
+ *tcpPayloadLen = TCP_DATA_LENGTH(ipHdr, tcp);
+ return storage;
+ }
+ }
+ return NULL;
+}
+
static UINT8
OvsReverseIcmpType(UINT8 type)
{
@@ -622,6 +725,10 @@ OvsReverseIcmpType(UINT8 type)
return ICMP4_INFO_REPLY;
case ICMP4_INFO_REPLY:
return ICMP4_INFO_REQUEST;
+ case ICMP6_ECHO_REQUEST:
+ return ICMP6_ECHO_REPLY;
+ case ICMP6_ECHO_REPLY:
+ return ICMP6_ECHO_REQUEST;
default:
return 0;
}
@@ -692,8 +799,8 @@ OvsCtSetupLookupCtx(OvsFlowKey *flowKey,
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.dst.icmp_id = ntohs(icmp->fields.echo.id);
+ ctx->key.src.icmp_id = ntohs(icmp->fields.echo.id);
ctx->key.src.icmp_type = icmp->type;
ctx->key.dst.icmp_type = OvsReverseIcmpType(icmp->type);
break;
@@ -702,7 +809,6 @@ OvsCtSetupLookupCtx(OvsFlowKey *flowKey,
case ICMP4_PARAM_PROB:
case ICMP4_SOURCE_QUENCH:
case ICMP4_REDIRECT: {
- /* XXX Handle inner packet */
ctx->related = TRUE;
break;
}
@@ -717,7 +823,53 @@ OvsCtSetupLookupCtx(OvsFlowKey *flowKey,
ctx->key.src.port = flowKey->ipv6Key.l4.tpSrc;
ctx->key.dst.port = flowKey->ipv6Key.l4.tpDst;
- /* XXX Handle ICMPv6 errors*/
+ if (flowKey->ipv6Key.nwProto == IPPROTO_ICMPV6) {
+ ICMPHdr icmpStorage;
+ const ICMPHdr *icmp;
+ icmp = OvsGetIcmp(curNbl, l4Offset, &icmpStorage);
+ ASSERT(icmp);
+
+ switch (icmp->type) {
+ case ICMP6_ECHO_REQUEST:
+ case ICMP6_ECHO_REPLY: {
+ ctx->key.dst.icmp_id = ntohs(icmp->fields.echo.id);
+ ctx->key.src.icmp_id = ntohs(icmp->fields.echo.id);
+ ctx->key.src.icmp_type = icmp->type;
+ ctx->key.dst.icmp_type = OvsReverseIcmpType(icmp->type);
+ break;
+ }
+ case ICMP6_DST_UNREACH:
+ case ICMP6_TIME_EXCEEDED:
+ case ICMP6_PARAM_PROB:
+ case ICMP6_PACKET_TOO_BIG: {
+ Ipv6Key ipv6Key;
+ OVS_PACKET_HDR_INFO layers;
+ OvsExtractLayers(curNbl, &layers);
+ layers.l3Offset = layers.l7Offset;
+ NDIS_STATUS status = OvsParseIPv6(curNbl, &ipv6Key, &layers);
+ if (status != NDIS_STATUS_SUCCESS) {
+ return NDIS_STATUS_INVALID_PACKET;
+ }
+ ctx->key.src.addr.ipv6 = ipv6Key.ipv6Src;
+ ctx->key.dst.addr.ipv6 = ipv6Key.ipv6Dst;
+ ctx->key.nw_proto = ipv6Key.nwProto;
+ if (ipv6Key.nwProto == SOCKET_IPPROTO_TCP) {
+ OvsParseTcp(curNbl, &(ipv6Key.l4), &layers);
+ } else if (ipv6Key.nwProto == SOCKET_IPPROTO_UDP) {
+ OvsParseUdp(curNbl, &(ipv6Key.l4), &layers);
+ } else if (ipv6Key.nwProto == SOCKET_IPPROTO_SCTP) {
+ OvsParseSctp(curNbl, &ipv6Key.l4, &layers);
+ }
+ ctx->key.src.port = ipv6Key.l4.tpSrc;
+ ctx->key.dst.port = ipv6Key.l4.tpDst;
+ OvsCtKeyReverse(&ctx->key);
+ ctx->related = TRUE;
+ break;
+ }
+ default:
+ ctx->related = FALSE;
+ }
+ }
} else {
return NDIS_STATUS_INVALID_PACKET;
}
@@ -744,6 +896,13 @@ OvsDetectFtpPacket(OvsFlowKey *key) {
ntohs(key->ipKey.l4.tpSrc) == IPPORT_FTP));
}
+static __inline BOOLEAN
+OvsDetectFtp6Packet(OvsFlowKey *key) {
+ return (key->ipv6Key.nwProto == IPPROTO_TCP &&
+ (ntohs(key->ipv6Key.l4.tpDst) == IPPORT_FTP ||
+ ntohs(key->ipv6Key.l4.tpSrc) == IPPORT_FTP));
+}
+
/*
*----------------------------------------------------------------------------
* OvsProcessConntrackEntry
@@ -777,11 +936,22 @@ OvsProcessConntrackEntry(OvsForwardingContext *fwdCtx,
} else {
CT_UPDATE_RES result;
UINT32 bucketIdx;
- result = OvsCtUpdateEntry(entry, curNbl, key->ipKey.nwProto, layers,
- ctx->reply, currentTime);
+
+ if (layers->isIPv6) {
+ result = OvsCtUpdateEntry(entry, curNbl, key->ipv6Key.nwProto, layers,
+ ctx->reply, currentTime);
+ } else {
+ result = OvsCtUpdateEntry(entry, curNbl, key->ipKey.nwProto, layers,
+ ctx->reply, currentTime);
+ }
+
switch (result) {
case CT_UPDATE_VALID:
state |= OVS_CS_F_ESTABLISHED;
+ /** when the ct state is established, at least
+ * request/reply two packets go through,
+ * so the ct_state shouldn't contain new.**/
+ state &= ~OVS_CS_F_NEW;
if (ctx->reply) {
state |= OVS_CS_F_REPLY_DIR;
}
@@ -796,9 +966,17 @@ OvsProcessConntrackEntry(OvsForwardingContext *fwdCtx,
OvsCtEntryDelete(ctx->entry, TRUE);
NdisReleaseRWLock(ovsCtBucketLock[bucketIdx], &lockStateTable);
ctx->entry = NULL;
- entry = OvsCtEntryCreate(fwdCtx, key->ipKey.nwProto, layers,
- ctx, key, natInfo, commit, currentTime,
- entryCreated);
+
+ if (layers->isIPv6) {
+ entry = OvsCtEntryCreate(fwdCtx, key->ipv6Key.nwProto, layers,
+ ctx, key, natInfo, commit, currentTime,
+ entryCreated);
+ } else {
+ entry = OvsCtEntryCreate(fwdCtx, key->ipKey.nwProto, layers,
+ ctx, key, natInfo, commit, currentTime,
+ entryCreated);
+ }
+
if (!entry) {
return NULL;
}
@@ -810,7 +988,8 @@ OvsProcessConntrackEntry(OvsForwardingContext *fwdCtx,
}
if (entry) {
NdisAcquireSpinLock(&(entry->lock));
- if (key->ipKey.nwProto == IPPROTO_TCP) {
+ if ((layers->isIPv6 && key->ipv6Key.nwProto == IPPROTO_TCP) ||
+ (!(layers->isIPv6) && key->ipKey.nwProto == IPPROTO_TCP)) {
/* Update the related bit if there is a parent */
if (entry->parent) {
state |= OVS_CS_F_RELATED;
@@ -938,6 +1117,29 @@ OvsCtUpdateTuple(OvsFlowKey *key, OVS_CT_KEY *ctKey)
htons(ctKey->src.icmp_code);
}
+/*
+ * --------------------------------------------------------------------------
+ * OvsCtUpdateTupleV6 name --
+ * Update origin tuple for ipv6 packet.
+ * --------------------------------------------------------------------------
+ */
+static __inline void
+OvsCtUpdateTupleV6(OvsFlowKey *key, OVS_CT_KEY *ctKey)
+{
+ RtlCopyMemory(&key->ct.tuple_ipv6.ipv6_src, &ctKey->src.addr.ipv6_aligned, sizeof(key->ct.tuple_ipv6.ipv6_src));
+ RtlCopyMemory(&key->ct.tuple_ipv6.ipv6_dst, &ctKey->dst.addr.ipv6_aligned, sizeof(key->ct.tuple_ipv6.ipv6_dst));
+ key->ct.tuple_ipv6.ipv6_proto = ctKey->nw_proto;
+
+ /* Orig tuple Port is overloaded to take in ICMP-Type & Code */
+ /* This mimics the behavior in lib/conntrack.c*/
+ key->ct.tuple_ipv6.src_port = ctKey->nw_proto != IPPROTO_ICMPV6 ?
+ ctKey->src.port :
+ htons(ctKey->src.icmp_type);
+ key->ct.tuple_ipv6.dst_port = ctKey->nw_proto != IPPROTO_ICMPV6 ?
+ ctKey->dst.port :
+ htons(ctKey->src.icmp_code);
+}
+
static __inline NDIS_STATUS
OvsCtExecute_(OvsForwardingContext *fwdCtx,
OvsFlowKey *key,
@@ -954,6 +1156,8 @@ OvsCtExecute_(OvsForwardingContext *fwdCtx,
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
BOOLEAN triggerUpdateEvent = FALSE;
BOOLEAN entryCreated = FALSE;
+ BOOLEAN isFtpPacket = FALSE;
+ BOOLEAN isFtpRequestDirection = FALSE;
POVS_CT_ENTRY entry = NULL;
POVS_CT_ENTRY parent = NULL;
PNET_BUFFER_LIST curNbl = fwdCtx->curNbl;
@@ -1004,10 +1208,17 @@ OvsCtExecute_(OvsForwardingContext *fwdCtx,
return NDIS_STATUS_RESOURCES;
}
/* If no matching entry was found, create one and add New state */
- entry = OvsCtEntryCreate(fwdCtx, key->ipKey.nwProto,
- layers, &ctx,
- key, natInfo, commit, currentTime,
- &entryCreated);
+ if (key->l2.dlType == htons(ETH_TYPE_IPV6)) {
+ entry = OvsCtEntryCreate(fwdCtx, key->ipv6Key.nwProto,
+ layers, &ctx,
+ key, natInfo, commit, currentTime,
+ &entryCreated);
+ } else {
+ entry = OvsCtEntryCreate(fwdCtx, key->ipKey.nwProto,
+ layers, &ctx,
+ key, natInfo, commit, currentTime,
+ &entryCreated);
+ }
}
if (entry == NULL) {
@@ -1030,10 +1241,22 @@ OvsCtExecute_(OvsForwardingContext *fwdCtx,
OvsCtSetMarkLabel(key, entry, mark, labels, &triggerUpdateEvent);
- if (OvsDetectFtpPacket(key)) {
+ if (layers->isIPv6) {
+ isFtpPacket = OvsDetectFtp6Packet(key);
+ if (ntohs(key->ipv6Key.l4.tpDst) == IPPORT_FTP) {
+ isFtpRequestDirection = TRUE;
+ }
+ } else {
+ isFtpPacket = OvsDetectFtpPacket(key);
+ if (ntohs(key->ipKey.l4.tpDst) == IPPORT_FTP) {
+ isFtpRequestDirection = TRUE;
+ }
+ }
+
+ if (isFtpPacket) {
/* FTP parser will always be loaded */
status = OvsCtHandleFtp(curNbl, key, layers, currentTime, entry,
- (ntohs(key->ipKey.l4.tpDst) == IPPORT_FTP));
+ isFtpRequestDirection);
if (status != NDIS_STATUS_SUCCESS) {
OVS_LOG_ERROR("Error while parsing the FTP packet");
}
@@ -1064,6 +1287,14 @@ OvsCtExecute_(OvsForwardingContext *fwdCtx,
} else {
OvsCtUpdateTuple(key, &entry->key);
}
+ } else if (entry->key.dl_type == ntohs(ETH_TYPE_IPV6)) {
+ if (parent != NULL) {
+ OVS_ACQUIRE_SPIN_LOCK(&(parent->lock), irql);
+ OvsCtUpdateTupleV6(key, &parent->key);
+ OVS_RELEASE_SPIN_LOCK(&(parent->lock), irql);
+ } else {
+ OvsCtUpdateTupleV6(key, &entry->key);
+ }
}
if (entryCreated) {
@@ -1400,13 +1631,15 @@ MapNlToCtTuple(POVS_MESSAGE msgIn, PNL_ATTR ctAttr,
PNL_ATTR ctTupleAttrs[__CTA_MAX];
UINT32 attrOffset;
static const NL_POLICY ctTuplePolicy[] = {
- [CTA_TUPLE_IP] = {.type = NL_A_NESTED, .optional = FALSE },
- [CTA_TUPLE_PROTO] = {.type = NL_A_NESTED, .optional = FALSE},
+ [CTA_TUPLE_IP] = { .type = NL_A_NESTED, .optional = FALSE },
+ [CTA_TUPLE_PROTO] = { .type = NL_A_NESTED, .optional = FALSE},
};
static const NL_POLICY ctTupleIpPolicy[] = {
[CTA_IP_V4_SRC] = { .type = NL_A_BE32, .optional = TRUE },
[CTA_IP_V4_DST] = { .type = NL_A_BE32, .optional = TRUE },
+ [CTA_IP_V6_SRC] = { .type = NL_A_BE32,.optional = TRUE },
+ [CTA_IP_V6_DST] = { .type = NL_A_BE32,.optional = TRUE },
};
static const NL_POLICY ctTupleProtoPolicy[] = {
@@ -1415,6 +1648,9 @@ MapNlToCtTuple(POVS_MESSAGE msgIn, PNL_ATTR ctAttr,
[CTA_PROTO_DST_PORT] = { .type = NL_A_BE16, .optional = TRUE },
[CTA_PROTO_ICMP_TYPE] = { .type = NL_A_U8, .optional = TRUE },
[CTA_PROTO_ICMP_CODE] = { .type = NL_A_U8, .optional = TRUE },
+ [CTA_PROTO_ICMPV6_ID] = { .type = NL_A_BE16,.optional = TRUE },
+ [CTA_PROTO_ICMPV6_TYPE] = { .type = NL_A_U8,.optional = TRUE },
+ [CTA_PROTO_ICMPV6_CODE] = { .type = NL_A_U8,.optional = TRUE },
};
if (!ctAttr) {
@@ -1467,8 +1703,11 @@ MapNlToCtTuple(POVS_MESSAGE msgIn, PNL_ATTR ctAttr,
ctTupleProtoAttrs[CTA_PROTO_ICMP_CODE] ) {
ct_tuple->src_port = NlAttrGetU8(ctTupleProtoAttrs[CTA_PROTO_ICMP_TYPE]);
ct_tuple->dst_port = NlAttrGetU8(ctTupleProtoAttrs[CTA_PROTO_ICMP_CODE]);
+ } else if (ctTupleProtoAttrs[CTA_PROTO_ICMPV6_TYPE] &&
+ ctTupleProtoAttrs[CTA_PROTO_ICMPV6_CODE] ) {
+ ct_tuple->src_port = NlAttrGetU8(ctTupleProtoAttrs[CTA_PROTO_ICMPV6_TYPE]);
+ ct_tuple->dst_port = NlAttrGetU8(ctTupleProtoAttrs[CTA_PROTO_ICMPV6_CODE]);
}
-
}
}
@@ -1551,15 +1790,15 @@ MapProtoTupleToNl(PNL_BUFFER nlBuf, OVS_CT_KEY *key)
goto done;
}
} else if (key->nw_proto == IPPROTO_ICMPV6) {
- if (!NlMsgPutTailU16(nlBuf, CTA_PROTO_ICMPV6_ID, 0)) {
+ if (!NlMsgPutTailU16(nlBuf, CTA_PROTO_ICMPV6_ID, htons(key->src.icmp_id))) {
status = NDIS_STATUS_FAILURE;
goto done;
}
- if (!NlMsgPutTailU8(nlBuf, CTA_PROTO_ICMPV6_TYPE, 0)) {
+ if (!NlMsgPutTailU8(nlBuf, CTA_PROTO_ICMPV6_TYPE, key->src.icmp_type)) {
status = NDIS_STATUS_FAILURE;
goto done;
}
- if (!NlMsgPutTailU8(nlBuf, CTA_PROTO_ICMPV6_CODE, 0)) {
+ if (!NlMsgPutTailU8(nlBuf, CTA_PROTO_ICMPV6_CODE, key->src.icmp_code)) {
status = NDIS_STATUS_FAILURE;
goto done;
}