summaryrefslogtreecommitdiff
path: root/datapath-windows/ovsext/Flow.c
diff options
context:
space:
mode:
authorSorin Vinturis <svinturis@cloudbasesolutions.com>2016-02-02 10:41:27 +0000
committerGurucharan Shetty <guru@ovn.org>2016-02-02 08:23:47 -0800
commit5874d571188500ec7aa6d98c778347c6774c3a24 (patch)
tree11e86cc1ee6e6c36bfcce1e1f2e541d659f8a605 /datapath-windows/ovsext/Flow.c
parentfa47c1145c5c69933466539f63efa91900b8c5b2 (diff)
downloadopenvswitch-5874d571188500ec7aa6d98c778347c6774c3a24.tar.gz
datapath-windows: Support for OVS_KEY_ATTR_MPLS attribute
This patch adds OVS_KEY_ATTR_MPLS to the OVS flow mechanism. Tested using ping. Tested using iperf (TCP and UDP). Tested using DriverVerifier. Signed-off-by: Sorin Vinturis <svinturis@cloudbasesolutions.com> Acked-by: Nithin Raju <nithin@vmware.com> Signed-off-by: Gurucharan Shetty <guru@ovn.org>
Diffstat (limited to 'datapath-windows/ovsext/Flow.c')
-rw-r--r--datapath-windows/ovsext/Flow.c102
1 files changed, 96 insertions, 6 deletions
diff --git a/datapath-windows/ovsext/Flow.c b/datapath-windows/ovsext/Flow.c
index 31ddc6681..a2f053542 100644
--- a/datapath-windows/ovsext/Flow.c
+++ b/datapath-windows/ovsext/Flow.c
@@ -80,6 +80,8 @@ static NTSTATUS _MapFlowIpv6KeyToNlKey(PNL_BUFFER nlBuf,
Icmp6Key *ipv6FlowPutIcmpKey);
static NTSTATUS _MapFlowArpKeyToNlKey(PNL_BUFFER nlBuf,
ArpKey *arpFlowPutKey);
+static NTSTATUS _MapFlowMplsKeyToNlKey(PNL_BUFFER nlBuf,
+ MplsKey *mplsFlowPutKey);
static NTSTATUS OvsDoDumpFlows(OvsFlowDumpInput *dumpInput,
OvsFlowDumpOutput *dumpOutput,
@@ -108,7 +110,7 @@ const NL_POLICY nlFlowPolicy[] = {
/* For Parsing nested OVS_FLOW_ATTR_KEY attributes.
* Some of the attributes like OVS_KEY_ATTR_RECIRC_ID
- * & OVS_KEY_ATTR_MPLS are not supported yet. */
+ * are not supported yet. */
const NL_POLICY nlFlowKeyPolicy[] = {
[OVS_KEY_ATTR_ENCAP] = {.type = NL_A_VAR_LEN, .optional = TRUE},
@@ -872,6 +874,13 @@ MapFlowKeyToNlKey(PNL_BUFFER nlBuf,
break;
}
+ case ETH_TYPE_MPLS:
+ case ETH_TYPE_MPLS_MCAST: {
+ MplsKey *mplsFlowPutKey = &(flowKey->mplsKey);
+ rc = _MapFlowMplsKeyToNlKey(nlBuf, mplsFlowPutKey);
+ break;
+ }
+
default:
break;
}
@@ -1194,6 +1203,31 @@ done:
/*
*----------------------------------------------------------------------------
+ * _MapFlowMplsKeyToNlKey --
+ * Maps _MapFlowMplsKeyToNlKey to OVS_KEY_ATTR_MPLS attribute.
+ *----------------------------------------------------------------------------
+ */
+static NTSTATUS
+_MapFlowMplsKeyToNlKey(PNL_BUFFER nlBuf, MplsKey *mplsFlowPutKey)
+{
+ NTSTATUS rc = STATUS_SUCCESS;
+ struct ovs_key_mpls *mplsKey;
+
+ mplsKey = (struct ovs_key_mpls *)
+ NlMsgPutTailUnspecUninit(nlBuf, OVS_KEY_ATTR_MPLS, sizeof(*mplsKey));
+ if (!mplsKey) {
+ rc = STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ mplsKey->mpls_lse = mplsFlowPutKey->lse;
+
+done:
+ return rc;
+}
+
+/*
+ *----------------------------------------------------------------------------
* _MapNlToFlowPut --
* Maps input netlink message to OvsFlowPut.
*----------------------------------------------------------------------------
@@ -1469,8 +1503,26 @@ _MapKeyAttrToFlowPut(PNL_ATTR *keyAttrs,
arpFlowPutKey->pad[1] = 0;
arpFlowPutKey->pad[2] = 0;
destKey->l2.keyLen += OVS_ARP_KEY_SIZE;
- break;
}
+ break;
+ }
+ case ETH_TYPE_MPLS:
+ case ETH_TYPE_MPLS_MCAST: {
+
+ if (keyAttrs[OVS_KEY_ATTR_MPLS]) {
+ MplsKey *mplsFlowPutKey = &destKey->mplsKey;
+ const struct ovs_key_mpls *mplsKey;
+
+ mplsKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_MPLS]);
+
+ mplsFlowPutKey->lse = mplsKey->mpls_lse;
+ mplsFlowPutKey->pad[0] = 0;
+ mplsFlowPutKey->pad[1] = 0;
+ mplsFlowPutKey->pad[2] = 0;
+ mplsFlowPutKey->pad[3] = 0;
+ destKey->l2.keyLen += sizeof(MplsKey);
+ }
+ break;
}
}
}
@@ -1734,10 +1786,10 @@ OvsExtractFlow(const NET_BUFFER_LIST *packet,
flow->l2.vlanTci = 0;
}
/*
- * XXX
- * Please note after this point, src mac and dst mac should
- * not be accessed through eth
- */
+ * XXX
+ * Please note after this point, src mac and dst mac should
+ * not be accessed through eth
+ */
eth = (Eth_Header *)((UINT8 *)eth + offset);
}
@@ -1868,6 +1920,44 @@ OvsExtractFlow(const NET_BUFFER_LIST *packet,
memcpy(arpKey->arpTha, arp->arp_tha, ETH_ADDR_LENGTH);
}
}
+ } else if (OvsEthertypeIsMpls(flow->l2.dlType)) {
+ MPLSHdr mplsStorage;
+ const MPLSHdr *mpls;
+ MplsKey *mplsKey = &flow->mplsKey;
+ ((UINT64 *)mplsKey)[0] = 0;
+
+ /*
+ * In the presence of an MPLS label stack the end of the L2
+ * header and the beginning of the L3 header differ.
+ *
+ * A network packet may contain multiple MPLS labels, but we
+ * are only interested in the topmost label stack entry.
+ *
+ * Advance network header to the beginning of the L3 header.
+ * layers->l3Offset corresponds to the end of the L2 header.
+ */
+ for (UINT32 i = 0; i < FLOW_MAX_MPLS_LABELS; i++) {
+ mpls = OvsGetMpls(packet, layers->l3Offset, &mplsStorage);
+ if (!mpls) {
+ break;
+ }
+
+ /* Keep only the topmost MPLS label stack entry. */
+ if (i == 0) {
+ mplsKey->lse = mpls->lse;
+ }
+
+ layers->l3Offset += MPLS_HLEN;
+ layers->l4Offset += MPLS_HLEN;
+
+ if (mpls->lse & htonl(MPLS_BOS_MASK)) {
+ /*
+ * Bottom of Stack bit is set, which means there are no
+ * remaining MPLS labels in the packet.
+ */
+ break;
+ }
+ }
}
return NDIS_STATUS_SUCCESS;