diff options
author | Sairam Venugopal <vsairam@vmware.com> | 2016-04-13 11:54:03 -0700 |
---|---|---|
committer | Ben Pfaff <blp@ovn.org> | 2016-04-14 10:11:46 -0700 |
commit | 792d377d8330606ad122dae5f941e5088c10cf14 (patch) | |
tree | 233132b3b7fc3b4fb7f0c35a71d51b53d4a364b5 /datapath-windows/ovsext/Flow.c | |
parent | ce05810425872709ddda9d7755b3348f584849ff (diff) | |
download | openvswitch-792d377d8330606ad122dae5f941e5088c10cf14.tar.gz |
datapath-windows: Add Connection Tracking Support
Enable support for Stateful Firewall in Hyper-V by adding a Connection
Tracking module. The module has been ported over from the userspace
implementation patch of a similar name.
The current version of the module supports ct - zone, mark and label for
TCP packets. Support for other packet formats will be added in subsequent
patches.
The conntrack-tcp module is adapted from FreeBSD's pf subsystem and hence
the BSD license. It has been ported over to match OVS Hyper-V coding
style.
Signed-off-by: Sairam Venugopal <vsairam@vmware.com>
Signed-off-by: Daniele Di Proietto <diproiettod@vmware.com>
Co-Authored-by: Daniele Di Proietto <diproiettod@vmware.com>
Acked-by: Nithin Raju <nithin@vmware.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Diffstat (limited to 'datapath-windows/ovsext/Flow.c')
-rw-r--r-- | datapath-windows/ovsext/Flow.c | 128 |
1 files changed, 126 insertions, 2 deletions
diff --git a/datapath-windows/ovsext/Flow.c b/datapath-windows/ovsext/Flow.c index f74ce12e8..a7e9bd2ea 100644 --- a/datapath-windows/ovsext/Flow.c +++ b/datapath-windows/ovsext/Flow.c @@ -172,7 +172,17 @@ const NL_POLICY nlFlowKeyPolicy[] = { .maxLen = 4, .optional = TRUE}, [OVS_KEY_ATTR_RECIRC_ID] = {.type = NL_A_UNSPEC, .minLen = 4, .maxLen = 4, .optional = TRUE}, - [OVS_KEY_ATTR_MPLS] = {.type = NL_A_VAR_LEN, .optional = TRUE} + [OVS_KEY_ATTR_MPLS] = {.type = NL_A_VAR_LEN, .optional = TRUE}, + [OVS_KEY_ATTR_CT_STATE] = {.type = NL_A_UNSPEC, .minLen = 4, + .maxLen = 4, .optional = TRUE}, + [OVS_KEY_ATTR_CT_ZONE] = {.type = NL_A_UNSPEC, .minLen = 2, + .maxLen = 2, .optional = TRUE}, + [OVS_KEY_ATTR_CT_MARK] = {.type = NL_A_UNSPEC, .minLen = 4, + .maxLen = 4, .optional = TRUE}, + [OVS_KEY_ATTR_CT_LABELS] = {.type = NL_A_UNSPEC, + .minLen = sizeof(struct ovs_key_ct_labels), + .maxLen = sizeof(struct ovs_key_ct_labels), + .optional = TRUE} }; const UINT32 nlFlowKeyPolicyLen = ARRAY_SIZE(nlFlowKeyPolicy); @@ -229,7 +239,8 @@ const NL_POLICY nlFlowActionPolicy[] = { .maxLen = sizeof(struct ovs_action_hash), .optional = TRUE}, [OVS_ACTION_ATTR_SET] = {.type = NL_A_VAR_LEN, .optional = TRUE}, - [OVS_ACTION_ATTR_SAMPLE] = {.type = NL_A_VAR_LEN, .optional = TRUE} + [OVS_ACTION_ATTR_SAMPLE] = {.type = NL_A_VAR_LEN, .optional = TRUE}, + [OVS_ACTION_ATTR_CT] = {.type = NL_A_VAR_LEN, .optional = TRUE} }; /* @@ -850,6 +861,28 @@ MapFlowKeyToNlKey(PNL_BUFFER nlBuf, goto done; } + if (!NlMsgPutTailU32(nlBuf, OVS_KEY_ATTR_CT_STATE, + flowKey->ct.state)) { + rc = STATUS_UNSUCCESSFUL; + goto done; + } + if (!NlMsgPutTailU16(nlBuf, OVS_KEY_ATTR_CT_ZONE, + flowKey->ct.zone)) { + rc = STATUS_UNSUCCESSFUL; + goto done; + } + if (!NlMsgPutTailU32(nlBuf, OVS_KEY_ATTR_CT_MARK, + flowKey->ct.mark)) { + rc = STATUS_UNSUCCESSFUL; + goto done; + } + if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_CT_LABELS, + (PCHAR)(&flowKey->ct.labels), + sizeof(struct ovs_key_ct_labels))) { + rc = STATUS_UNSUCCESSFUL; + goto done; + } + if (flowKey->dpHash) { if (!NlMsgPutTailU32(nlBuf, OVS_KEY_ATTR_DP_HASH, flowKey->dpHash)) { @@ -1386,6 +1419,24 @@ _MapKeyAttrToFlowPut(PNL_ATTR *keyAttrs, destKey->dpHash = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_DP_HASH]); } + if (keyAttrs[OVS_KEY_ATTR_CT_STATE]) { + destKey->ct.state = (NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_CT_STATE])); + } + + if (keyAttrs[OVS_KEY_ATTR_CT_ZONE]) { + destKey->ct.zone = (NlAttrGetU16(keyAttrs[OVS_KEY_ATTR_CT_ZONE])); + } + + if (keyAttrs[OVS_KEY_ATTR_CT_MARK]) { + destKey->ct.mark = (NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_CT_MARK])); + } + + if (keyAttrs[OVS_KEY_ATTR_CT_LABELS]) { + const struct ovs_key_ct_labels *ct_labels; + ct_labels = NlAttrGet(keyAttrs[OVS_KEY_ATTR_CT_LABELS]); + RtlCopyMemory(&destKey->ct.labels, ct_labels, sizeof(struct ovs_key_ct_labels)); + } + /* ===== L2 headers ===== */ destKey->l2.inPort = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_IN_PORT]); @@ -1774,6 +1825,24 @@ OvsGetFlowMetadata(OvsFlowKey *key, key->dpHash = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_DP_HASH]); } + if (keyAttrs[OVS_KEY_ATTR_CT_STATE]) { + key->ct.state = (NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_CT_STATE])); + } + + if (keyAttrs[OVS_KEY_ATTR_CT_ZONE]) { + key->ct.zone = (NlAttrGetU16(keyAttrs[OVS_KEY_ATTR_CT_ZONE])); + } + + if (keyAttrs[OVS_KEY_ATTR_CT_MARK]) { + key->ct.mark = (NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_CT_MARK])); + } + + if (keyAttrs[OVS_KEY_ATTR_CT_LABELS]) { + const struct ovs_key_ct_labels *ct_labels; + ct_labels = NlAttrGet(keyAttrs[OVS_KEY_ATTR_CT_LABELS]); + RtlCopyMemory(&key->ct.labels, ct_labels, sizeof(struct ovs_key_ct_labels)); + } + return status; } @@ -2059,6 +2128,11 @@ FlowEqual(OvsFlow *srcFlow, srcFlow->key.l2.val == dstKey->l2.val && srcFlow->key.recircId == dstKey->recircId && srcFlow->key.dpHash == dstKey->dpHash && + srcFlow->key.ct.state == dstKey->ct.state && + srcFlow->key.ct.zone == dstKey->ct.zone && + srcFlow->key.ct.mark == dstKey->ct.mark && + !memcmp(&srcFlow->key.ct.labels, &dstKey->ct.labels, + sizeof(struct ovs_key_ct_labels)) && FlowMemoryEqual((UINT64 *)((UINT8 *)&srcFlow->key + offset), (UINT64 *) dstStart, size)); @@ -2156,6 +2230,21 @@ OvsLookupFlow(OVS_DATAPATH *datapath, if (key->dpHash) { *hash = OvsJhashWords((UINT32*)hash, 1, key->dpHash); } + if (key->ct.state) { + *hash = OvsJhashWords((UINT32*)hash, 1, key->ct.state); + } + if (key->ct.zone) { + *hash = OvsJhashWords((UINT32*)hash, 1, key->ct.zone); + } + if (key->ct.mark) { + *hash = OvsJhashWords((UINT32*)hash, 1, key->ct.zone); + } + if (key->ct.labels.ct_labels) { + UINT32 lblHash = OvsJhashBytes(&key->ct.labels, + sizeof(struct ovs_key_ct_labels), + 0); + *hash = OvsJhashWords((UINT32*)hash, 1, lblHash); + } } head = &datapath->flowTable[HASH_BUCKET(*hash)]; @@ -2322,6 +2411,12 @@ ReportFlowInfo(OvsFlow *flow, info->key.recircId = flow->key.recircId; info->key.dpHash = flow->key.dpHash; + info->key.ct.state = flow->key.ct.state; + info->key.ct.zone = flow->key.ct.zone; + info->key.ct.mark = flow->key.ct.mark; + NdisMoveMemory(&info->key.ct.labels, + &flow->key.ct.labels, + sizeof(struct ovs_key_ct_labels)); return status; } @@ -2578,6 +2673,10 @@ OvsFlowKeyAttrSize(void) + NlAttrTotalSize(4) /* OVS_KEY_ATTR_SKB_MARK */ + NlAttrTotalSize(4) /* OVS_KEY_ATTR_DP_HASH */ + NlAttrTotalSize(4) /* OVS_KEY_ATTR_RECIRC_ID */ + + NlAttrTotalSize(4) /* OVS_KEY_ATTR_CT_STATE */ + + NlAttrTotalSize(2) /* OVS_KEY_ATTR_CT_ZONE */ + + NlAttrTotalSize(4) /* OVS_KEY_ATTR_CT_MARK */ + + NlAttrTotalSize(16) /* OVS_KEY_ATTR_CT_LABELS */ + NlAttrTotalSize(12) /* OVS_KEY_ATTR_ETHERNET */ + NlAttrTotalSize(2) /* OVS_KEY_ATTR_ETHERTYPE */ + NlAttrTotalSize(4) /* OVS_KEY_ATTR_VLAN */ @@ -2657,6 +2756,31 @@ OvsProbeSupportedFeature(POVS_MESSAGE msgIn, OVS_LOG_ERROR("Invalid recirculation ID."); status = STATUS_INVALID_PARAMETER; } + } else if (keyAttrs[OVS_KEY_ATTR_CT_STATE]) { + UINT32 state = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_CT_STATE]); + if (state & OVS_CS_F_DST_NAT || state & OVS_CS_F_SRC_NAT) { + status = STATUS_INVALID_PARAMETER; + OVS_LOG_ERROR("Contrack NAT is not supported:%d", state); + } + } else if (keyAttrs[OVS_KEY_ATTR_CT_ZONE]) { + UINT16 zone = (NlAttrGetU16(keyAttrs[OVS_KEY_ATTR_CT_ZONE])); + if (!zone) { + OVS_LOG_ERROR("Invalid zone specified."); + status = STATUS_INVALID_PARAMETER; + } + } else if (keyAttrs[OVS_KEY_ATTR_CT_MARK]) { + UINT32 mark = (NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_CT_MARK])); + if (!mark) { + OVS_LOG_ERROR("Invalid ct mark specified."); + status = STATUS_INVALID_PARAMETER; + } + } else if (keyAttrs[OVS_KEY_ATTR_CT_LABELS]) { + const struct ovs_key_ct_labels *ct_labels; + ct_labels = NlAttrGet(keyAttrs[OVS_KEY_ATTR_CT_LABELS]); + if (!ct_labels->ct_labels) { + OVS_LOG_ERROR("Invalid ct label specified."); + status = STATUS_INVALID_PARAMETER; + } } else { OVS_LOG_ERROR("Feature not supported."); status = STATUS_INVALID_PARAMETER; |