summaryrefslogtreecommitdiff
path: root/datapath-windows/ovsext/Flow.c
diff options
context:
space:
mode:
authorSairam Venugopal <vsairam@vmware.com>2016-04-13 11:54:03 -0700
committerBen Pfaff <blp@ovn.org>2016-04-14 10:11:46 -0700
commit792d377d8330606ad122dae5f941e5088c10cf14 (patch)
tree233132b3b7fc3b4fb7f0c35a71d51b53d4a364b5 /datapath-windows/ovsext/Flow.c
parentce05810425872709ddda9d7755b3348f584849ff (diff)
downloadopenvswitch-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.c128
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;