[ovs-dev] [PATCH 15/15] datapath-windows: Add files that map userspace attr types to unique arg types

Samuel Ghinet sghinet at cloudbasesolutions.com
Wed Aug 6 17:12:50 UTC 2014


Add files for mapping arg types: from userspace to  kernel and vice versa.

The approach of mapping attribute types from userspace to kernel has the following advantages:
* each arg type can uniquely identify the windows netlink attribute data. Its value does not depend on
parent attribute types, or the command type, or the target (datapath or flow, etc.) which also makes it
easier to debug in case a wrong value happens somewhere.
* having unique arg types in kernel allows the separation of code: parsing, verification, processing.
Having one place in code where we do all checks may be easier to manage. Also, this improves clarity,
because checks do not need to be done everywhere / anywhere a data is used.

Signed-off-by: Samuel Ghinet <sghinet at cloudbasesolutions.com>
---
 datapath-windows/ovsext/Winetlink/ArgToAttribute.c | 200 +++++++++
 datapath-windows/ovsext/Winetlink/ArgToAttribute.h |  21 +
 datapath-windows/ovsext/Winetlink/ArgumentType.h   | 490 +++++++++++++++++++++
 datapath-windows/ovsext/Winetlink/AttrToArgument.c | 197 +++++++++
 datapath-windows/ovsext/Winetlink/AttrToArgument.h |  22 +
 datapath-windows/ovsext/ovsext.vcxproj             |   5 +
 datapath-windows/ovsext/ovsext.vcxproj.filters     |  15 +
 7 files changed, 950 insertions(+)
 create mode 100644 datapath-windows/ovsext/Winetlink/ArgToAttribute.c
 create mode 100644 datapath-windows/ovsext/Winetlink/ArgToAttribute.h
 create mode 100644 datapath-windows/ovsext/Winetlink/ArgumentType.h
 create mode 100644 datapath-windows/ovsext/Winetlink/AttrToArgument.c
 create mode 100644 datapath-windows/ovsext/Winetlink/AttrToArgument.h

diff --git a/datapath-windows/ovsext/Winetlink/ArgToAttribute.c b/datapath-windows/ovsext/Winetlink/ArgToAttribute.c
new file mode 100644
index 0000000..ef1efc8
--- /dev/null
+++ b/datapath-windows/ovsext/Winetlink/ArgToAttribute.c
@@ -0,0 +1,200 @@
+/*
+Copyright 2014 Cloudbase Solutions Srl
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http ://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include "ArgToAttribute.h"
+#include "ArgumentType.h"
+#include "WinlProtocol.h"
+
+static const int s_argsToAttribsDatapath[] =
+{
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_DATAPATH_NAME, DATAPATH)] = OVS_DP_ATTR_NAME,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_DATAPATH_STATS, DATAPATH)] = OVS_DP_ATTR_STATS,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_DATAPATH_UPCALL_PORT_ID, DATAPATH)] = OVS_DP_ATTR_UPCALL_PID,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_DATAPATH_MEGAFLOW_STATS, DATAPATH)] = OVS_DP_ATTR_MEGAFLOW_STATS,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_DATAPATH_USER_FEATURES, DATAPATH)] = OVS_DP_ATTR_USER_FEATURES,
+};
+
+static const int s_argsToAttribsTunnel[] =
+{
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_PI_TUNNEL_ID, PI_TUNNEL)] = OVS_TUNNEL_KEY_ATTR_ID,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_PI_TUNNEL_IPV4_SRC, PI_TUNNEL)] = OVS_TUNNEL_KEY_ATTR_IPV4_SRC,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_PI_TUNNEL_IPV4_DST, PI_TUNNEL)] = OVS_TUNNEL_KEY_ATTR_IPV4_DST,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_PI_TUNNEL_TOS, PI_TUNNEL)] = OVS_TUNNEL_KEY_ATTR_TOS,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_PI_TUNNEL_TTL, PI_TUNNEL)] = OVS_TUNNEL_KEY_ATTR_TTL,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_PI_TUNNEL_DONT_FRAGMENT, PI_TUNNEL)] = OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_PI_TUNNEL_CHECKSUM, PI_TUNNEL)] = OVS_TUNNEL_KEY_ATTR_CSUM,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_PI_TUNNEL_OAM, PI_TUNNEL)] = OVS_TUNNEL_KEY_ATTR_OAM,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_PI_TUNNEL_GENEVE_OPTIONS, PI_TUNNEL)] = OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS,
+};
+
+static const int s_argsToAttribsPI[] =
+{
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_PI_PACKET_PRIORITY, PI)] = OVS_KEY_ATTR_PRIORITY,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_PI_DP_INPUT_PORT, PI)] = OVS_KEY_ATTR_IN_PORT,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_PI_ETH_ADDRESS, PI)] = OVS_KEY_ATTR_ETHERNET,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_PI_ETH_TYPE, PI)] = OVS_KEY_ATTR_ETHERTYPE,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_PI_VLAN_TCI, PI)] = OVS_KEY_ATTR_VLAN,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_PI_IPV4, PI)] = OVS_KEY_ATTR_IPV4,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_PI_IPV6, PI)] = OVS_KEY_ATTR_IPV6,
+
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_PI_TCP, PI)] = OVS_KEY_ATTR_TCP,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_PI_TCP_FLAGS, PI)] = OVS_KEY_ATTR_TCP_FLAGS,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_PI_UDP, PI)] = OVS_KEY_ATTR_UDP,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_PI_SCTP, PI)] = OVS_KEY_ATTR_SCTP,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_PI_ICMP, PI)] = OVS_KEY_ATTR_ICMP,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_PI_ICMP6, PI)] = OVS_KEY_ATTR_ICMPV6,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_PI_ARP, PI)] = OVS_KEY_ATTR_ARP,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_PI_NEIGHBOR_DISCOVERY, PI)] = OVS_KEY_ATTR_ND,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_PI_MPLS, PI)] = OVS_KEY_ATTR_MPLS,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_PI_DATAPATH_HASH, PI)] = OVS_KEY_ATTR_DP_HASH,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_PI_DATAPATH_RECIRCULATION_ID, PI)] = OVS_KEY_ATTR_RECIRC_ID,
+
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_PI_PACKET_MARK, PI)] = OVS_KEY_ATTR_SKB_MARK,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_PI_TUNNEL_GROUP, PI)] = OVS_KEY_ATTR_TUNNEL,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_PI_ENCAP_GROUP, PI)] = OVS_KEY_ATTR_ENCAP,
+};
+
+static const int s_argsToAttribsFlow[] =
+{
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_FLOW_STATS, FLOW)] = OVS_FLOW_ATTR_STATS,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_FLOW_TCP_FLAGS, FLOW)] = OVS_FLOW_ATTR_TCP_FLAGS,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_FLOW_TIME_USED, FLOW)] = OVS_FLOW_ATTR_USED,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_FLOW_CLEAR, FLOW)] = OVS_FLOW_ATTR_CLEAR,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_FLOW_PI_GROUP, FLOW)] = OVS_FLOW_ATTR_KEY,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_FLOW_ACTIONS_GROUP, FLOW)] = OVS_FLOW_ATTR_ACTIONS,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_FLOW_MASK_GROUP, FLOW)] = OVS_FLOW_ATTR_MASK
+};
+
+static const int s_argsToAttribsUpcall[] =
+{
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_ACTION_UPCALL_PORT_ID, ACTION_UPCALL)] = OVS_USERSPACE_ATTR_PID,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_ACTION_UPCALL_DATA, ACTION_UPCALL)] = OVS_USERSPACE_ATTR_USERDATA,
+};
+
+static const int s_argsToAttribsSample[] =
+{
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_ACTION_SAMPLE_PROBABILITY, ACTION_SAMPLE)] = OVS_SAMPLE_ATTR_PROBABILITY,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_ACTION_SAMPLE_ACTIONS_GROUP, ACTION_SAMPLE)] = OVS_SAMPLE_ATTR_ACTIONS,
+};
+
+static const int s_argsToAttribsActions[] =
+{
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_ACTION_OUTPUT_TO_PORT, ACTION)] = OVS_ACTION_ATTR_OUTPUT,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_ACTION_UPCALL_GROUP, ACTION)] = OVS_ACTION_ATTR_USERSPACE,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_ACTION_SETINFO_GROUP, ACTION)] = OVS_ACTION_ATTR_SET,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_ACTION_PUSH_VLAN, ACTION)] = OVS_ACTION_ATTR_PUSH_VLAN,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_ACTION_POP_VLAN, ACTION)] = OVS_ACTION_ATTR_POP_VLAN,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_ACTION_SAMPLE_GROUP, ACTION)] = OVS_ACTION_ATTR_SAMPLE,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_ACTION_PUSH_MPLS, ACTION)] = OVS_ACTION_ATTR_PUSH_MPLS,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_ACTION_POP_MPLS, ACTION)] = OVS_ACTION_ATTR_POP_MPLS,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_ACTION_RECIRCULATION, ACTION)] = OVS_ACTION_ATTR_RECIRC,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_ACTION_HASH, ACTION)] = OVS_ACTION_ATTR_HASH
+};
+
+static const int s_argsToAttribsPacket[] =
+{
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_PACKET_BUFFER, PACKET)] = OVS_PACKET_ATTR_PACKET,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_PACKET_PI_GROUP, PACKET)] = OVS_PACKET_ATTR_KEY,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_PACKET_ACTIONS_GROUP, PACKET)] = OVS_PACKET_ATTR_ACTIONS,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_PACKET_USERDATA, PACKET)] = OVS_PACKET_ATTR_USERDATA
+};
+
+static const int s_argsToAttribsPortOptions[] =
+{
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_DPPORT_OPTION_DESTINATION_PORT, DPPORT_OPTION)] = OVS_TUNNEL_ATTR_DST_PORT,
+};
+
+static const int s_argsToAttribsPort[] =
+{
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_DPPORT_NUMBER, DPPORT)] = OVS_VPORT_ATTR_PORT_NO,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_DPPORT_NAME, DPPORT)] = OVS_VPORT_ATTR_NAME,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_DPPORT_STATS, DPPORT)] = OVS_VPORT_ATTR_STATS,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_DPPORT_TYPE, DPPORT)] = OVS_VPORT_ATTR_TYPE,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_DPPORT_UPCALL_PORT_ID, DPPORT)] = OVS_VPORT_ATTR_UPCALL_PID,
+    [OVS_ARG_TOINDEX(OVS_ARGTYPE_DPPORT_OPTIONS_GROUP, DPPORT)] = OVS_VPORT_ATTR_OPTIONS,
+};
+
+typedef struct _OVS_ARG_GROUP_INFO
+{
+    OVS_ARGTYPE parent;
+    const int* group;
+    OVS_ARGTYPE min;
+    OVS_ARGTYPE max;
+}OVS_ARG_GROUP_INFO, *POVS_ARG_GROUP_INFO;
+
+static const OVS_ARG_GROUP_INFO s_argsToAttribs[OVS_ARG_GROUP_COUNT] =
+{
+    { OVS_ARGTYPE_PSEUDOGROUP_DATAPATH, s_argsToAttribsDatapath, OVS_ARGTYPE_FIRST_DATAPATH, OVS_ARGTYPE_LAST_DATAPATH },
+    { OVS_ARGTYPE_PSEUDOGROUP_FLOW, s_argsToAttribsFlow, OVS_ARGTYPE_FIRST_FLOW, OVS_ARGTYPE_LAST_FLOW },
+    { OVS_ARGTYPE_PSEUDOGROUP_DPPORT, s_argsToAttribsPort, OVS_ARGTYPE_FIRST_DPPORT, OVS_ARGTYPE_LAST_DPPORT },
+    { OVS_ARGTYPE_PSEUDOGROUP_PACKET, s_argsToAttribsPacket, OVS_ARGTYPE_FIRST_PACKET, OVS_ARGTYPE_LAST_PACKET },
+
+    { OVS_ARGTYPE_FLOW_PI_GROUP, s_argsToAttribsPI, OVS_ARGTYPE_FIRST_PI, OVS_ARGTYPE_LAST_PI },
+    { OVS_ARGTYPE_FLOW_MASK_GROUP, s_argsToAttribsPI, OVS_ARGTYPE_FIRST_PI, OVS_ARGTYPE_LAST_PI },
+    { OVS_ARGTYPE_FLOW_ACTIONS_GROUP, s_argsToAttribsActions, OVS_ARGTYPE_FIRST_ACTION, OVS_ARGTYPE_LAST_ACTION },
+
+    { OVS_ARGTYPE_PI_ENCAP_GROUP, s_argsToAttribsPI, OVS_ARGTYPE_FIRST_PI, OVS_ARGTYPE_LAST_PI },
+    { OVS_ARGTYPE_PI_TUNNEL_GROUP, s_argsToAttribsTunnel, OVS_ARGTYPE_FIRST_PI_TUNNEL, OVS_ARGTYPE_LAST_PI_TUNNEL },
+
+    { OVS_ARGTYPE_PACKET_PI_GROUP, s_argsToAttribsPI, OVS_ARGTYPE_FIRST_PI, OVS_ARGTYPE_LAST_PI },
+    { OVS_ARGTYPE_PACKET_ACTIONS_GROUP, s_argsToAttribsActions, OVS_ARGTYPE_FIRST_ACTION, OVS_ARGTYPE_LAST_ACTION },
+
+    { OVS_ARGTYPE_ACTION_UPCALL_GROUP, s_argsToAttribsUpcall, OVS_ARGTYPE_FIRST_ACTION_UPCALL, OVS_ARGTYPE_LAST_ACTION_UPCALL },
+    { OVS_ARGTYPE_ACTION_SETINFO_GROUP, s_argsToAttribsPI, OVS_ARGTYPE_FIRST_PI, OVS_ARGTYPE_LAST_PI },
+    { OVS_ARGTYPE_ACTION_SAMPLE_GROUP, s_argsToAttribsSample, OVS_ARGTYPE_FIRST_ACTION_SAMPLE, OVS_ARGTYPE_LAST_ACTION_SAMPLE },
+
+    { OVS_ARGTYPE_ACTION_SAMPLE_ACTIONS_GROUP, s_argsToAttribsActions, OVS_ARGTYPE_FIRST_ACTION, OVS_ARGTYPE_LAST_ACTION },
+    { OVS_ARGTYPE_DPPORT_OPTIONS_GROUP, s_argsToAttribsPortOptions, OVS_ARGTYPE_FIRST_DPPORT_OPTION, OVS_ARGTYPE_LAST_DPPORT_OPTION },
+};
+
+static const OVS_ARG_GROUP_INFO* _FindGroup(OVS_ARGTYPE parentArgType, _Out_ OVS_ARGTYPE* pMin, _Out_ OVS_ARGTYPE* pMax)
+{
+    for (int i = 0; i < OVS_ARG_GROUP_COUNT; ++i)
+    {
+        const OVS_ARG_GROUP_INFO* pGroup = s_argsToAttribs + i;
+
+        if (parentArgType == pGroup->parent)
+        {
+            *pMin = pGroup->min;
+            *pMax = pGroup->max;
+
+            return pGroup;
+        }
+    }
+
+    OVS_CHECK(__UNEXPECTED__);
+    return NULL;
+}
+
+BOOLEAN ArgType_To_AttrType(UINT16 parentArgType, _Inout_ UINT16* pTypeAsAttr)
+{
+    const OVS_ARG_GROUP_INFO* pGroup = NULL;
+    OVS_ARGTYPE minArg = OVS_ARGTYPE_INVALID, maxArg = OVS_ARGTYPE_INVALID;
+    ULONG attrType = 0;
+    UINT16 typeAsAttr = *pTypeAsAttr;
+
+    pGroup = _FindGroup(parentArgType, &minArg, &maxArg);
+
+    OVS_CHECK_RET(pGroup, FALSE);
+    OVS_CHECK_RET(typeAsAttr >= minArg && typeAsAttr <= maxArg, FALSE);
+
+    attrType = pGroup->group[ArgTypeToIndex(typeAsAttr)];
+    OVS_CHECK_RET(attrType > 0 && attrType <= MAXUINT16, FALSE);
+
+    *pTypeAsAttr = (UINT16)attrType;
+
+    return TRUE;
+}
diff --git a/datapath-windows/ovsext/Winetlink/ArgToAttribute.h b/datapath-windows/ovsext/Winetlink/ArgToAttribute.h
new file mode 100644
index 0000000..1e6935f
--- /dev/null
+++ b/datapath-windows/ovsext/Winetlink/ArgToAttribute.h
@@ -0,0 +1,21 @@
+/*
+Copyright 2014 Cloudbase Solutions Srl
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http ://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#pragma once
+
+#include "precomp.h"
+
+BOOLEAN ArgType_To_AttrType(UINT16 parentArgType, _Inout_ UINT16* pTypeAsAttr);
diff --git a/datapath-windows/ovsext/Winetlink/ArgumentType.h b/datapath-windows/ovsext/Winetlink/ArgumentType.h
new file mode 100644
index 0000000..55bfa85
--- /dev/null
+++ b/datapath-windows/ovsext/Winetlink/ArgumentType.h
@@ -0,0 +1,490 @@
+/*
+Copyright 2014 Cloudbase Solutions Srl
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http ://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#pragma once
+
+#define OVS_DRIVER_FLOW_VERSION                1
+#define OVS_DRIVER_DATAPATH_VERSION            1
+#define OVS_DRIVER_VPORT_VERSION               1
+#define OVS_DRIVER_PACKET_VERSION              1
+
+/******************************************/
+
+typedef enum _OVS_ARGTYPE
+{
+    OVS_ARGTYPE_PSEUDOGROUP_INVALID = 0x00D,
+    OVS_ARGTYPE_FIRST_PSEUDOGROUP = OVS_ARGTYPE_PSEUDOGROUP_INVALID,
+
+    OVS_ARGTYPE_PSEUDOGROUP_FLOW = 0x00E,
+    OVS_ARGTYPE_PSEUDOGROUP_DATAPATH = 0x00F,
+    OVS_ARGTYPE_PSEUDOGROUP_DPPORT = 0x010,
+    OVS_ARGTYPE_PSEUDOGROUP_PACKET = 0x011,
+    OVS_ARGTYPE_LAST_PSEUDOGROUP = OVS_ARGTYPE_PSEUDOGROUP_PACKET,
+
+    OVS_ARGTYPE_LAST_GROUP = OVS_ARGTYPE_PSEUDOGROUP_PACKET,
+
+    OVS_ARGTYPE_INVALID = 0x000,
+
+    /********************************************** TARGET: FLOW; GROUP: MAIN *******************************************/
+
+    OVS_ARGTYPE_FLOW_INVALID = 0x20,
+    OVS_ARGTYPE_FIRST_FLOW = OVS_ARGTYPE_FLOW_INVALID,
+
+    OVS_ARGTYPE_FLOW_PI_GROUP,                  //0x021
+
+    //actions to apply to packets matching the flow
+    OVS_ARGTYPE_FLOW_ACTIONS_GROUP,             //0x022
+
+    //Flow request: ignored
+    //Flow reply: only if there have been packets matched by the flow
+    //Data Type: OVS_WINL_FLOW_STATS
+    OVS_ARGTYPE_FLOW_STATS,                     //0x23
+
+    //All tcp control bits / flags that were on packets matched by this flow
+    //Flow request: ignored
+    //Flow reply: only if tcpFlags != 0
+    //data type: UINT8
+    OVS_ARGTYPE_FLOW_TCP_FLAGS,                //0x024
+
+    //The time at which the last packet was matched by this flow. The time is given by performance counter
+    //(i.e. by windows' system monotonic clock), in miliseconds
+    //Flow request: ignored
+    //Flow reply: only if there have been packets matched by the flow
+    //data type: UINT64
+    OVS_ARGTYPE_FLOW_TIME_USED,                //0x025
+
+    //Used to clear from the flow: last used time, tcpFlags, and statistics.
+    //Flow request: for Flow_Set or Flow_New with override (i.e. when flow already exists)
+    //Flow reply: not used
+    //data type: no data
+    OVS_ARGTYPE_FLOW_CLEAR,                    //0x026
+
+    OVS_ARGTYPE_FLOW_MASK_GROUP,               //0x027
+
+    OVS_ARGTYPE_LAST_FLOW = OVS_ARGTYPE_FLOW_MASK_GROUP,
+
+    /************************************ TARGET: FLOW / PACKET; group: KEY **********************************************/
+    //GROUP NOTE: This group represents attributes: OVS_PACKET_ATTR_KEY and OVS_FLOW_ATTR_KEY and
+    //                                                OVS_FLOW_ATTR_MASK
+    //NOTE: The PI Masks belongs here as well
+
+    OVS_ARGTYPE_PI_INVALID = 0x040,
+    OVS_ARGTYPE_FIRST_PI = OVS_ARGTYPE_PI_INVALID,
+
+    //-- Packet priority.
+    //NOTE: might be QoS priority; might have no meaning for windows.
+    //data type: UINT32
+    OVS_ARGTYPE_PI_PACKET_PRIORITY,         //0x041
+
+    //source port / input port, given as the dp port number (not hyper-v switch port id)
+    //data type: UINT32
+    OVS_ARGTYPE_PI_DP_INPUT_PORT,            //0x042
+
+    //data type: OVS_PI_ETH_ADDRESS
+    OVS_ARGTYPE_PI_ETH_ADDRESS,            //0x043
+
+    //data type: BE16; values: enum constants of: OVS_ETHERNET_TYPE
+    OVS_ARGTYPE_PI_ETH_TYPE,                //0x044
+
+    //VLAN tag control information (Q-Tagged frames). Includes: User Priority, CFI, Vlan Identifier
+    //data type: BE16.
+    OVS_ARGTYPE_PI_VLAN_TCI,                //0x045
+
+    //data type: OVS_PI_IPV4
+    OVS_ARGTYPE_PI_IPV4,                    //0x046
+
+    //data type: OVS_PI_IPV6
+    OVS_ARGTYPE_PI_IPV6,                    //0x047
+
+    //data type: OVS_PI_TCP
+    OVS_ARGTYPE_PI_TCP,                    //0x048
+
+    //data type: OVS_PI_UDP
+    OVS_ARGTYPE_PI_UDP,                    //0x049
+
+    //data type: OVS_PI_SCTP
+    OVS_ARGTYPE_PI_SCTP,                    //0x04A
+
+    //data type: OVS_PI_ICMP
+    OVS_ARGTYPE_PI_ICMP,                    //0x04B
+
+    //data type: OVS_PI_ICMP6
+    OVS_ARGTYPE_PI_ICMP6,                    //0x04C
+
+    //data type: OVS_PI_ARP
+    OVS_ARGTYPE_PI_ARP,                    //0x04D
+
+    //data type: OVS_PI_NEIGHBOR_DISCOVERY
+    OVS_ARGTYPE_PI_NEIGHBOR_DISCOVERY,        //0x04E
+
+    //data type: UINT32;
+    OVS_ARGTYPE_PI_PACKET_MARK,            //0x04F,
+
+    //data type: OVS_PI_IPV4_TUNNEL
+    //NOTE: OVS_ARGTYPE_FLOW_KEY_IPV4_TUNNEL is used only in kernel. IT IS NOT USED in userspace!
+    OVS_ARGTYPE_PI_IPV4_TUNNEL,            //0x050
+
+    //-- Multi Protocol Label Switching
+    //http://www.networkworld.com/community/node/18007
+    //data type: OVS_PI_MPLS, see FlowKey.h
+    OVS_ARGTYPE_PI_MPLS,                    //0x051
+
+    //Encapsulation Group = another set of packet info-s, for the encapsulation. contains: eth type, ip layer PI, transport layer PI
+    //might have been an older version of "tunnel info". The encapsulation group does not appear to be used in latest versions of ovs
+    OVS_ARGTYPE_PI_ENCAP_GROUP,             //0x052
+
+    //received from userspace
+    OVS_ARGTYPE_PI_TUNNEL_GROUP,            //0x053
+
+    //type: BE16
+    OVS_ARGTYPE_PI_TCP_FLAGS,                //0x054
+
+    //hash value: 0 = not computed
+    //type: UINT32
+    OVS_ARGTYPE_PI_DATAPATH_HASH,            //0x055
+
+    //type: UINT32
+    OVS_ARGTYPE_PI_DATAPATH_RECIRCULATION_ID,        //0x056
+
+    OVS_ARGTYPE_LAST_PI = OVS_ARGTYPE_PI_DATAPATH_RECIRCULATION_ID,
+
+    /******************************************* TARGET: FLOW: group = KEY / TUNNEL (FROM USERSPACE ONLY!) **********************************************/
+
+    //GROUP NOTE: this group represents the OVS_USPACE_TUNNEL_KEY_ATTRIBUTE
+
+    OVS_ARGTYPE_PI_TUNNEL_INVALID = 0x060,
+    OVS_ARGTYPE_FIRST_PI_TUNNEL = OVS_ARGTYPE_PI_TUNNEL_INVALID,
+
+    //data type: BE64
+    OVS_ARGTYPE_PI_TUNNEL_ID,               //0x061
+
+    //data type: BE32
+    OVS_ARGTYPE_PI_TUNNEL_IPV4_SRC,        //0x062
+
+    //data type: BE32
+    OVS_ARGTYPE_PI_TUNNEL_IPV4_DST,        //0x063
+
+    //data type: UINT8
+    OVS_ARGTYPE_PI_TUNNEL_TOS,                //0x064
+
+    //data type: UINT8
+    OVS_ARGTYPE_PI_TUNNEL_TTL,                //0x065
+
+    //data type: no data (it's a flag)
+    OVS_ARGTYPE_PI_TUNNEL_DONT_FRAGMENT,    //0x066
+
+    //data type: no data (it's a flag)
+    OVS_ARGTYPE_PI_TUNNEL_CHECKSUM,        //0x067
+
+    //data type: no data (it's a flag)
+    OVS_ARGTYPE_PI_TUNNEL_OAM,                //0x068
+
+    //data: an array of "geneve options" structs (not yet defined!)
+    OVS_ARGTYPE_PI_TUNNEL_GENEVE_OPTIONS,    //0x069
+
+    OVS_ARGTYPE_LAST_PI_TUNNEL = OVS_ARGTYPE_PI_TUNNEL_GENEVE_OPTIONS,
+
+    /************************************* TARGET: PACKET; GROUP: MAIN *****************************************************/
+
+    OVS_ARGTYPE_PACKET_INVALID = 0x80,
+    OVS_ARGTYPE_FIRST_PACKET = OVS_ARGTYPE_PACKET_INVALID,
+
+    //GROUP NOTE: This group represents OVS_USPACE_PACKET_ATTRIBUTE
+    OVS_ARGTYPE_PACKET_PI_GROUP,                    //0x81
+
+    //Packet notifications (queue to userspace). It is the NET_BUFFER data.
+    //data type: "void*", i.e. data opaque to the user
+    OVS_ARGTYPE_PACKET_BUFFER,                      //0x82
+
+    //actions to apply to packets being executed
+    OVS_ARGTYPE_PACKET_ACTIONS_GROUP,        //0x83
+
+    //data type: OVS_ARGUMENT; it is set from userspace only.
+    OVS_ARGTYPE_PACKET_USERDATA,            //0x084
+
+    OVS_ARGTYPE_LAST_PACKET = OVS_ARGTYPE_PACKET_USERDATA,
+
+    /************************************ TARGET: FLOW / PACKET; group = ACTIONS **********************************************/
+
+    //GROUP NOTE: this group represents OVS_PACKET_ATTR_ACTIONS and OVS_FLOW_ATTR_ACTIONS
+    OVS_ARGTYPE_ACTION_INVALID = 0x0A0,
+    OVS_ARGTYPE_FIRST_ACTION = OVS_ARGTYPE_ACTION_INVALID,
+
+    //dp port number to which to send the packet to (no hyper-v switch port id)
+    //data type: UINT32 (however, it is used as UINT16)
+    OVS_ARGTYPE_ACTION_OUTPUT_TO_PORT,      //0x0A1
+
+    OVS_ARGTYPE_ACTION_UPCALL_GROUP,         //0x0A2
+
+    //contains packet info args to set
+    OVS_ARGTYPE_ACTION_SETINFO_GROUP,        //0x0A3
+
+    //Insert Vlan header into the packet
+    //data type: OVS_ACTION_PUSH_VLAN
+    OVS_ARGTYPE_ACTION_PUSH_VLAN,            //0x0A4
+
+    //Remove the Vlan header from the packet.
+    //TODO: it might be possible for a packet to be wrapped into multiple Vlan headers
+    //data type: no data
+    OVS_ARGTYPE_ACTION_POP_VLAN,            //0x0A5
+
+    OVS_ARGTYPE_ACTION_SAMPLE_GROUP,        //0x0A6
+
+    OVS_ARGTYPE_ACTION_PUSH_MPLS,            //0x0A7
+
+    //value: eth type
+    OVS_ARGTYPE_ACTION_POP_MPLS,            //0x0A8
+
+    //data type: OVS_ACTION_FLOW_HASH
+    OVS_ARGTYPE_ACTION_HASH,                //0x0A9
+
+    //data type: UINT32
+    OVS_ARGTYPE_ACTION_RECIRCULATION,        //0x0AA
+
+    OVS_ARGTYPE_LAST_ACTION = OVS_ARGTYPE_ACTION_RECIRCULATION,
+
+    /************************************ TARGET: FLOW / PACKET; group = ACTIONS / UPCALL **********************************************/
+
+    //GROUP NOTE: this group represents OVS_USPACE_UPCALL_ATTRIBUTE
+    OVS_ARGTYPE_ACTION_UPCALL_INVALID = 0x0C0,
+    OVS_ARGTYPE_FIRST_ACTION_UPCALL = OVS_ARGTYPE_ACTION_UPCALL_INVALID,
+
+    //Port Id associated with the file HANDLE
+    //data type: UINT32
+    OVS_ARGTYPE_ACTION_UPCALL_PORT_ID,          //0x0C1
+
+    //Sent from userspace (optionally). It comes as Action / Output to Userspace
+    //data type: OVS_ARGUMENT
+    OVS_ARGTYPE_ACTION_UPCALL_DATA,            //0x0C2
+
+    OVS_ARGTYPE_LAST_ACTION_UPCALL = OVS_ARGTYPE_ACTION_UPCALL_DATA,
+
+    /************************************ TARGET: FLOW / PACKET; group: ACTIONS / SAMPLE **********************************************/
+
+    //GROUP NOTE: this group represents OVS_USPACE_SAMPLE_ATTRIBUTE
+    OVS_ARGTYPE_ACTION_SAMPLE_INVALID = 0x0E0,
+    OVS_ARGTYPE_FIRST_ACTION_SAMPLE = OVS_ARGTYPE_ACTION_SAMPLE_INVALID,
+
+    //The fraction of packets to sample (i.e. execute actions upon). Values:
+    //    a) 0            = do not sample
+    //    b) MAXUINT32    = sample all packets
+    //    c) other value
+
+    //data type: UINT32
+    OVS_ARGTYPE_ACTION_SAMPLE_PROBABILITY,          //0x0E1
+
+    //actions to apply to packets (being executed / matched by flow) in a sample action
+    OVS_ARGTYPE_ACTION_SAMPLE_ACTIONS_GROUP,        //0x0E2
+
+    OVS_ARGTYPE_LAST_ACTION_SAMPLE = OVS_ARGTYPE_ACTION_SAMPLE_ACTIONS_GROUP,
+
+    /******************************************** TARGET: DATAPATH; group: MAIN *********************************************/
+
+    OVS_ARGTYPE_DATAPATH_INVALID = 0x100,
+    OVS_ARGTYPE_FIRST_DATAPATH = OVS_ARGTYPE_DATAPATH_INVALID,
+
+    //Datapath request: required in Datapath_New
+    //Datapath reply: always present
+    //data type: null-terminated ASCII string
+    OVS_ARGTYPE_DATAPATH_NAME,              //0x101
+
+    //The userspace port id associated with the file HANDLE, by which upcalls should be read from userspace
+    //Datapath request: required in Datapath_New
+    //if (Datapath port Id == 0) => do not queue upcall message.
+    //data type: UINT32
+    OVS_ARGTYPE_DATAPATH_UPCALL_PORT_ID,    //0x102
+
+    //Datapath request: never
+    //Datapath reply: always
+    //data type: OVS_DATAPATH_STATS
+    OVS_ARGTYPE_DATAPATH_STATS,                //0x103
+
+    //Datapath request: never
+    //Datapath reply: always
+    //data type: OVS_DATAPATH_MEGAFLOW_STATS
+    OVS_ARGTYPE_DATAPATH_MEGAFLOW_STATS,    //0x104
+
+    //Datapath request: new or set
+    //Datapath reply: always
+    //data type: UINT32. values: constants of enum OVS_DATAPATH_FEATURE
+    OVS_ARGTYPE_DATAPATH_USER_FEATURES,        //0x105
+
+    OVS_ARGTYPE_LAST_DATAPATH = OVS_ARGTYPE_DATAPATH_USER_FEATURES,
+
+    /****************************************** TARGET: DPPORT; group: MAIN ************************************************/
+
+    OVS_ARGTYPE_DPPORT_INVALID = 0x120,
+    OVS_ARGTYPE_FIRST_DPPORT = OVS_ARGTYPE_DPPORT_INVALID,
+
+    //dp port number (not hyper-v switch port id)
+    //data type: UINT32. It is used in code as UINT16
+    OVS_ARGTYPE_DPPORT_NUMBER,              //0x121
+
+    //data type: UINT32; values: constants of enum OVS_DPPORT_TYPE
+    OVS_ARGTYPE_DPPORT_TYPE,                //0x122
+
+    //data type: null-terminated ASCII string. max size should be 17.
+    OVS_ARGTYPE_DPPORT_NAME,                //0x123
+
+    OVS_ARGTYPE_DPPORT_OPTIONS_GROUP,       //0x124
+
+    //OVS 1.11:
+    //The Port Id associated with the file HANDLE that handles the upcalls coming from this dp port.
+    //if (portId == 0) => do not queue upcall
+    //data type: UINT32
+    //OVS 2.3:
+    //array of Port Ids associated with the file HANDLE that handles the upcalls coming from this odp port.
+    //if we have only one port id, and its value is 0 => don't queue upcall
+    OVS_ARGTYPE_DPPORT_UPCALL_PORT_ID,        //0x125
+
+    //data type: OVS_DPPORT_STATS
+    OVS_ARGTYPE_DPPORT_STATS,                //0x126
+
+    OVS_ARGTYPE_LAST_DPPORT = OVS_ARGTYPE_DPPORT_STATS,
+
+    /************************************ TARGET: FLOW / PACKET; GROUP: PORT / OPTIONS **********************************************/
+
+    OVS_ARGTYPE_DPPORT_OPTION_INVALID = 0x140,
+    OVS_ARGTYPE_FIRST_DPPORT_OPTION = OVS_ARGTYPE_DPPORT_OPTION_INVALID,
+
+    //UINT16
+    OVS_ARGTYPE_DPPORT_OPTION_DESTINATION_PORT,     //0x141
+
+    OVS_ARGTYPE_LAST_DPPORT_OPTION = OVS_ARGTYPE_DPPORT_OPTION_DESTINATION_PORT,
+} OVS_ARGTYPE;
+
+#define OVS_ARG_GROUP_COUNT 16
+
+#define OVS_ARGTYPE_COUNT(group) (OVS_ARGTYPE_LAST_##group - OVS_ARGTYPE_FIRST_##group + 1)
+
+static __inline BOOLEAN IsArgTypeGroup(OVS_ARGTYPE argType)
+{
+    switch (argType)
+    {
+    case OVS_ARGTYPE_PSEUDOGROUP_DATAPATH:
+    case OVS_ARGTYPE_PSEUDOGROUP_FLOW:
+    case OVS_ARGTYPE_PSEUDOGROUP_PACKET:
+    case OVS_ARGTYPE_PSEUDOGROUP_DPPORT:
+    case OVS_ARGTYPE_FLOW_PI_GROUP:
+    case OVS_ARGTYPE_FLOW_ACTIONS_GROUP:
+    case OVS_ARGTYPE_FLOW_MASK_GROUP:
+    case OVS_ARGTYPE_PI_ENCAP_GROUP:
+    case OVS_ARGTYPE_PI_TUNNEL_GROUP:
+    case OVS_ARGTYPE_PACKET_PI_GROUP:
+    case OVS_ARGTYPE_PACKET_ACTIONS_GROUP:
+    case OVS_ARGTYPE_ACTION_UPCALL_GROUP:
+    case OVS_ARGTYPE_ACTION_SETINFO_GROUP:
+    case OVS_ARGTYPE_ACTION_SAMPLE_GROUP:
+    case OVS_ARGTYPE_ACTION_SAMPLE_ACTIONS_GROUP:
+    case OVS_ARGTYPE_DPPORT_OPTIONS_GROUP:
+        return TRUE;
+    default:
+        return FALSE;
+    }
+}
+
+//given an arg type, returns the index of the arg within its group, starting from 1
+#define OVS_ARG_TOINDEX(argType, group) (argType - OVS_ARGTYPE_FIRST_##group)
+#define OVS_ARG_TOINDEX_FIRST(argType, firstArgType) (argType - firstArgType)
+
+#define _OVS_ARGTYPE_FIRST(argType, first, last)            \
+    if (argType >= first && argType <= last)    \
+    return first;           \
+
+#define _OVS_ARGTYPE_LAST(argType, first, last)            \
+    if (argType >= first && argType <= last)    \
+    return last;           \
+
+static __inline OVS_ARGTYPE GetFirstArgTypeInGroup(OVS_ARGTYPE argType)
+{
+    _OVS_ARGTYPE_FIRST(argType, OVS_ARGTYPE_FIRST_PSEUDOGROUP, OVS_ARGTYPE_LAST_PSEUDOGROUP);
+    _OVS_ARGTYPE_FIRST(argType, OVS_ARGTYPE_FIRST_ACTION, OVS_ARGTYPE_LAST_ACTION);
+    _OVS_ARGTYPE_FIRST(argType, OVS_ARGTYPE_FIRST_ACTION_SAMPLE, OVS_ARGTYPE_LAST_ACTION_SAMPLE);
+    _OVS_ARGTYPE_FIRST(argType, OVS_ARGTYPE_FIRST_ACTION_UPCALL, OVS_ARGTYPE_LAST_ACTION_UPCALL);
+    _OVS_ARGTYPE_FIRST(argType, OVS_ARGTYPE_FIRST_DATAPATH, OVS_ARGTYPE_LAST_DATAPATH);
+    _OVS_ARGTYPE_FIRST(argType, OVS_ARGTYPE_FIRST_FLOW, OVS_ARGTYPE_LAST_FLOW);
+    _OVS_ARGTYPE_FIRST(argType, OVS_ARGTYPE_FIRST_DPPORT, OVS_ARGTYPE_LAST_DPPORT);
+    _OVS_ARGTYPE_FIRST(argType, OVS_ARGTYPE_FIRST_DPPORT_OPTION, OVS_ARGTYPE_LAST_DPPORT_OPTION);
+    _OVS_ARGTYPE_FIRST(argType, OVS_ARGTYPE_FIRST_PACKET, OVS_ARGTYPE_LAST_PACKET);
+    _OVS_ARGTYPE_FIRST(argType, OVS_ARGTYPE_FIRST_PI, OVS_ARGTYPE_LAST_PI);
+    _OVS_ARGTYPE_FIRST(argType, OVS_ARGTYPE_FIRST_PI_TUNNEL, OVS_ARGTYPE_LAST_PI_TUNNEL);
+
+    return OVS_ARGTYPE_INVALID;
+}
+
+static __inline OVS_ARGTYPE GetLastArgTypeInGroup(OVS_ARGTYPE argType)
+{
+    _OVS_ARGTYPE_LAST(argType, OVS_ARGTYPE_FIRST_PSEUDOGROUP, OVS_ARGTYPE_LAST_PSEUDOGROUP);
+    _OVS_ARGTYPE_LAST(argType, OVS_ARGTYPE_FIRST_ACTION, OVS_ARGTYPE_LAST_ACTION);
+    _OVS_ARGTYPE_LAST(argType, OVS_ARGTYPE_FIRST_ACTION_SAMPLE, OVS_ARGTYPE_LAST_ACTION_SAMPLE);
+    _OVS_ARGTYPE_LAST(argType, OVS_ARGTYPE_FIRST_ACTION_UPCALL, OVS_ARGTYPE_LAST_ACTION_UPCALL);
+    _OVS_ARGTYPE_LAST(argType, OVS_ARGTYPE_FIRST_DATAPATH, OVS_ARGTYPE_LAST_DATAPATH);
+    _OVS_ARGTYPE_LAST(argType, OVS_ARGTYPE_FIRST_FLOW, OVS_ARGTYPE_LAST_FLOW);
+    _OVS_ARGTYPE_LAST(argType, OVS_ARGTYPE_FIRST_DPPORT, OVS_ARGTYPE_LAST_DPPORT);
+    _OVS_ARGTYPE_LAST(argType, OVS_ARGTYPE_FIRST_DPPORT_OPTION, OVS_ARGTYPE_LAST_DPPORT_OPTION);
+    _OVS_ARGTYPE_LAST(argType, OVS_ARGTYPE_FIRST_PACKET, OVS_ARGTYPE_LAST_PACKET);
+    _OVS_ARGTYPE_LAST(argType, OVS_ARGTYPE_FIRST_PI, OVS_ARGTYPE_LAST_PI);
+    _OVS_ARGTYPE_LAST(argType, OVS_ARGTYPE_FIRST_PI_TUNNEL, OVS_ARGTYPE_LAST_PI_TUNNEL);
+
+    return OVS_ARGTYPE_INVALID;
+}
+
+#define OVS_MAX_2(x1, x2) max(x1, x2)
+#define OVS_MAX_3(x1, ...) max(x1, OVS_MAX_2(__VA_ARGS__))
+#define OVS_MAX_4(x1, ...) max(x1, OVS_MAX_3(__VA_ARGS__))
+#define OVS_MAX_5(x1, ...) max(x1, OVS_MAX_4(__VA_ARGS__))
+#define OVS_MAX_6(x1, ...) max(x1, OVS_MAX_5(__VA_ARGS__))
+#define OVS_MAX_7(x1, ...) max(x1, OVS_MAX_6(__VA_ARGS__))
+#define OVS_MAX_8(x1, ...) max(x1, OVS_MAX_7(__VA_ARGS__))
+#define OVS_MAX_9(x1, ...) max(x1, OVS_MAX_8(__VA_ARGS__))
+#define OVS_MAX_10(x1, ...) max(x1, OVS_MAX_9(__VA_ARGS__))
+#define OVS_MAX_11(x1, ...) max(x1, OVS_MAX_10(__VA_ARGS__))
+
+#define OVS_ARGTYPE_MAX_COUNT OVS_MAX_11                        \
+(                                                               \
+    OVS_ARGTYPE_COUNT(PSEUDOGROUP),                             \
+    OVS_ARGTYPE_COUNT(ACTION),                                  \
+    OVS_ARGTYPE_COUNT(ACTION_SAMPLE),                           \
+    OVS_ARGTYPE_COUNT(ACTION_UPCALL),                           \
+    OVS_ARGTYPE_COUNT(DATAPATH),                                \
+    OVS_ARGTYPE_COUNT(FLOW),                                    \
+    OVS_ARGTYPE_COUNT(DPPORT),                                  \
+    OVS_ARGTYPE_COUNT(DPPORT_OPTION),                           \
+    OVS_ARGTYPE_COUNT(PACKET),                                  \
+    OVS_ARGTYPE_COUNT(PI),                                      \
+    OVS_ARGTYPE_COUNT(PI_TUNNEL)                               \
+)
+
+static __inline int CountArgTypesInGroup(OVS_ARGTYPE argType)
+{
+    OVS_ARGTYPE first = GetFirstArgTypeInGroup(argType);
+    OVS_ARGTYPE last = GetLastArgTypeInGroup(argType);
+
+    OVS_CHECK(first != OVS_ARGTYPE_INVALID);
+    OVS_CHECK(last != OVS_ARGTYPE_INVALID);
+
+    //the 'invalid' arg excluded
+    return last - first;
+}
+
+//somewhat equivalent to OVS_ARG_TOINDEX
+static __inline int ArgTypeToIndex(OVS_ARGTYPE argType)
+{
+    OVS_ARGTYPE first = GetFirstArgTypeInGroup(argType);
+    OVS_CHECK(first != OVS_ARGTYPE_INVALID);
+
+    return argType - first;
+}
diff --git a/datapath-windows/ovsext/Winetlink/AttrToArgument.c b/datapath-windows/ovsext/Winetlink/AttrToArgument.c
new file mode 100644
index 0000000..ccd28f2
--- /dev/null
+++ b/datapath-windows/ovsext/Winetlink/AttrToArgument.c
@@ -0,0 +1,197 @@
+/*
+Copyright 2014 Cloudbase Solutions Srl
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http ://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#include "AttrToArgument.h"
+#include "WinlProtocol.h"
+
+static const int s_attrsToArgsDatapath[] =
+{
+    [OVS_DP_ATTR_NAME] = OVS_ARGTYPE_DATAPATH_NAME,
+    [OVS_DP_ATTR_STATS] = OVS_ARGTYPE_DATAPATH_STATS,
+    [OVS_DP_ATTR_UPCALL_PID] = OVS_ARGTYPE_DATAPATH_UPCALL_PORT_ID,
+    [OVS_DP_ATTR_MEGAFLOW_STATS] = OVS_ARGTYPE_DATAPATH_MEGAFLOW_STATS,
+    [OVS_DP_ATTR_USER_FEATURES] = OVS_ARGTYPE_DATAPATH_USER_FEATURES,
+};
+
+static const int s_attrsToArgsTunnel[] =
+{
+    [OVS_TUNNEL_KEY_ATTR_ID] = OVS_ARGTYPE_PI_TUNNEL_ID,
+    [OVS_TUNNEL_KEY_ATTR_IPV4_SRC] = OVS_ARGTYPE_PI_TUNNEL_IPV4_SRC,
+    [OVS_TUNNEL_KEY_ATTR_IPV4_DST] = OVS_ARGTYPE_PI_TUNNEL_IPV4_DST,
+    [OVS_TUNNEL_KEY_ATTR_TOS] = OVS_ARGTYPE_PI_TUNNEL_TOS,
+    [OVS_TUNNEL_KEY_ATTR_TTL] = OVS_ARGTYPE_PI_TUNNEL_TTL,
+    [OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT] = OVS_ARGTYPE_PI_TUNNEL_DONT_FRAGMENT,
+    [OVS_TUNNEL_KEY_ATTR_CSUM] = OVS_ARGTYPE_PI_TUNNEL_CHECKSUM,
+    [OVS_TUNNEL_KEY_ATTR_OAM] = OVS_ARGTYPE_PI_TUNNEL_OAM,
+    [OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS] = OVS_ARGTYPE_PI_TUNNEL_GENEVE_OPTIONS,
+};
+
+static const int s_attrsToArgsPI[] =
+{
+    [OVS_KEY_ATTR_PRIORITY] = OVS_ARGTYPE_PI_PACKET_PRIORITY,
+    [OVS_KEY_ATTR_IN_PORT] = OVS_ARGTYPE_PI_DP_INPUT_PORT,
+    [OVS_KEY_ATTR_ETHERNET] = OVS_ARGTYPE_PI_ETH_ADDRESS,
+    [OVS_KEY_ATTR_ETHERTYPE] = OVS_ARGTYPE_PI_ETH_TYPE,
+    [OVS_KEY_ATTR_VLAN] = OVS_ARGTYPE_PI_VLAN_TCI,
+    [OVS_KEY_ATTR_IPV4] = OVS_ARGTYPE_PI_IPV4,
+    [OVS_KEY_ATTR_IPV6] = OVS_ARGTYPE_PI_IPV6,
+
+    [OVS_KEY_ATTR_TCP] = OVS_ARGTYPE_PI_TCP,
+    [OVS_KEY_ATTR_TCP_FLAGS] = OVS_ARGTYPE_PI_TCP_FLAGS,
+    [OVS_KEY_ATTR_UDP] = OVS_ARGTYPE_PI_UDP,
+    [OVS_KEY_ATTR_SCTP] = OVS_ARGTYPE_PI_SCTP,
+    [OVS_KEY_ATTR_ICMP] = OVS_ARGTYPE_PI_ICMP,
+    [OVS_KEY_ATTR_ICMPV6] = OVS_ARGTYPE_PI_ICMP6,
+    [OVS_KEY_ATTR_ARP] = OVS_ARGTYPE_PI_ARP,
+    [OVS_KEY_ATTR_ND] = OVS_ARGTYPE_PI_NEIGHBOR_DISCOVERY,
+    [OVS_KEY_ATTR_MPLS] = OVS_ARGTYPE_PI_MPLS,
+    [OVS_KEY_ATTR_DP_HASH] = OVS_ARGTYPE_PI_DATAPATH_HASH,
+    [OVS_KEY_ATTR_RECIRC_ID] = OVS_ARGTYPE_PI_DATAPATH_RECIRCULATION_ID,
+
+    [OVS_KEY_ATTR_SKB_MARK] = OVS_ARGTYPE_PI_PACKET_MARK,
+    [OVS_KEY_ATTR_TUNNEL] = OVS_ARGTYPE_PI_TUNNEL_GROUP,
+    [OVS_KEY_ATTR_ENCAP] = OVS_ARGTYPE_PI_ENCAP_GROUP,
+};
+
+static const int s_attrsToArgsFlow[] =
+{
+    [OVS_FLOW_ATTR_STATS] = OVS_ARGTYPE_FLOW_STATS,
+    [OVS_FLOW_ATTR_TCP_FLAGS] = OVS_ARGTYPE_FLOW_TCP_FLAGS,
+    [OVS_FLOW_ATTR_USED] = OVS_ARGTYPE_FLOW_TIME_USED,
+    [OVS_FLOW_ATTR_CLEAR] = OVS_ARGTYPE_FLOW_CLEAR,
+    [OVS_FLOW_ATTR_KEY] = OVS_ARGTYPE_FLOW_PI_GROUP,
+    [OVS_FLOW_ATTR_ACTIONS] = OVS_ARGTYPE_FLOW_ACTIONS_GROUP,
+    [OVS_FLOW_ATTR_MASK] = OVS_ARGTYPE_FLOW_MASK_GROUP
+};
+
+static const int s_attrsToArgsUpcall[] =
+{
+    [OVS_USERSPACE_ATTR_PID] = OVS_ARGTYPE_ACTION_UPCALL_PORT_ID,
+    [OVS_USERSPACE_ATTR_USERDATA] = OVS_ARGTYPE_ACTION_UPCALL_DATA,
+};
+
+static const int s_attrsToArgsSample[] =
+{
+    [OVS_SAMPLE_ATTR_PROBABILITY] = OVS_ARGTYPE_ACTION_SAMPLE_PROBABILITY,
+    [OVS_SAMPLE_ATTR_ACTIONS] = OVS_ARGTYPE_ACTION_SAMPLE_ACTIONS_GROUP,
+};
+
+static const int s_attrsToArgsActions[] =
+{
+    [OVS_ACTION_ATTR_OUTPUT] = OVS_ARGTYPE_ACTION_OUTPUT_TO_PORT,
+    [OVS_ACTION_ATTR_USERSPACE] = OVS_ARGTYPE_ACTION_UPCALL_GROUP,
+    [OVS_ACTION_ATTR_SET] = OVS_ARGTYPE_ACTION_SETINFO_GROUP,
+    [OVS_ACTION_ATTR_PUSH_VLAN] = OVS_ARGTYPE_ACTION_PUSH_VLAN,
+    [OVS_ACTION_ATTR_POP_VLAN] = OVS_ARGTYPE_ACTION_POP_VLAN,
+    [OVS_ACTION_ATTR_SAMPLE] = OVS_ARGTYPE_ACTION_SAMPLE_GROUP,
+    [OVS_ACTION_ATTR_PUSH_MPLS] = OVS_ARGTYPE_ACTION_PUSH_MPLS,
+    [OVS_ACTION_ATTR_POP_MPLS] = OVS_ARGTYPE_ACTION_POP_MPLS,
+    [OVS_ACTION_ATTR_RECIRC] = OVS_ARGTYPE_ACTION_RECIRCULATION,
+    [OVS_ACTION_ATTR_HASH] = OVS_ARGTYPE_ACTION_HASH
+};
+
+static const int s_attrsToArgsPacket[] =
+{
+    [OVS_PACKET_ATTR_PACKET] = OVS_ARGTYPE_PACKET_BUFFER,
+    [OVS_PACKET_ATTR_KEY] = OVS_ARGTYPE_PACKET_PI_GROUP,
+    [OVS_PACKET_ATTR_ACTIONS] = OVS_ARGTYPE_PACKET_ACTIONS_GROUP,
+    [OVS_PACKET_ATTR_USERDATA] = OVS_ARGTYPE_PACKET_USERDATA
+};
+
+static const int s_attrsToArgsPortOptions[] =
+{
+    [OVS_TUNNEL_ATTR_DST_PORT] = OVS_ARGTYPE_DPPORT_OPTION_DESTINATION_PORT,
+};
+
+static const int s_attrsToArgsPort[] =
+{
+    [OVS_VPORT_ATTR_PORT_NO] = OVS_ARGTYPE_DPPORT_NUMBER,
+    [OVS_VPORT_ATTR_NAME] = OVS_ARGTYPE_DPPORT_NAME,
+    [OVS_VPORT_ATTR_STATS] = OVS_ARGTYPE_DPPORT_STATS,
+    [OVS_VPORT_ATTR_TYPE] = OVS_ARGTYPE_DPPORT_TYPE,
+    [OVS_VPORT_ATTR_UPCALL_PID] = OVS_ARGTYPE_DPPORT_UPCALL_PORT_ID,
+    [OVS_VPORT_ATTR_OPTIONS] = OVS_ARGTYPE_DPPORT_OPTIONS_GROUP,
+};
+
+typedef struct _OVS_ATTR_GROUP_INFO
+{
+    OVS_ARGTYPE parent;
+    const int* group;
+    int max;
+}OVS_ATTR_GROUP_INFO, *POVS_ATTR_GROUP_INFO;
+
+static const OVS_ATTR_GROUP_INFO s_argsToAttribs[OVS_ARG_GROUP_COUNT] =
+{
+    { OVS_ARGTYPE_PSEUDOGROUP_DATAPATH, s_attrsToArgsDatapath, OVS_DP_ATTR_MAX},
+    { OVS_ARGTYPE_PSEUDOGROUP_FLOW, s_attrsToArgsFlow, OVS_FLOW_ATTR_MAX },
+    { OVS_ARGTYPE_PSEUDOGROUP_DPPORT, s_attrsToArgsPort, OVS_VPORT_ATTR_MAX },
+    { OVS_ARGTYPE_PSEUDOGROUP_PACKET, s_attrsToArgsPacket, OVS_PACKET_ATTR_MAX },
+
+    { OVS_ARGTYPE_FLOW_PI_GROUP, s_attrsToArgsPI, OVS_KEY_ATTR_MAX },
+    { OVS_ARGTYPE_FLOW_MASK_GROUP, s_attrsToArgsPI, OVS_KEY_ATTR_MAX },
+    { OVS_ARGTYPE_FLOW_ACTIONS_GROUP, s_attrsToArgsActions, OVS_ACTION_ATTR_MAX },
+
+    { OVS_ARGTYPE_PI_ENCAP_GROUP, s_attrsToArgsPI, OVS_KEY_ATTR_MAX },
+    { OVS_ARGTYPE_PI_TUNNEL_GROUP, s_attrsToArgsTunnel, OVS_TUNNEL_KEY_ATTR_MAX },
+
+    { OVS_ARGTYPE_PACKET_PI_GROUP, s_attrsToArgsPI, OVS_KEY_ATTR_MAX },
+    { OVS_ARGTYPE_PACKET_ACTIONS_GROUP, s_attrsToArgsActions, OVS_ACTION_ATTR_MAX },
+
+    { OVS_ARGTYPE_ACTION_UPCALL_GROUP, s_attrsToArgsUpcall, OVS_USERSPACE_ATTR_MAX },
+    { OVS_ARGTYPE_ACTION_SETINFO_GROUP, s_attrsToArgsPI, OVS_KEY_ATTR_MAX },
+    { OVS_ARGTYPE_ACTION_SAMPLE_GROUP, s_attrsToArgsSample, OVS_SAMPLE_ATTR_MAX },
+
+    { OVS_ARGTYPE_ACTION_SAMPLE_ACTIONS_GROUP, s_attrsToArgsActions, OVS_ACTION_ATTR_MAX },
+    { OVS_ARGTYPE_DPPORT_OPTIONS_GROUP, s_attrsToArgsPortOptions, OVS_TUNNEL_ATTR_MAX },
+};
+
+static const OVS_ATTR_GROUP_INFO* _FindGroup(OVS_ARGTYPE parentArgType, _Out_ int* pMax)
+{
+    for (int i = 0; i < OVS_ARG_GROUP_COUNT; ++i)
+    {
+        const OVS_ATTR_GROUP_INFO* pGroup = s_argsToAttribs + i;
+
+        if (parentArgType == pGroup->parent)
+        {
+            *pMax = pGroup->max;
+
+            return pGroup;
+        }
+    }
+
+    OVS_CHECK(__UNEXPECTED__);
+    return NULL;
+}
+
+BOOLEAN AttrType_To_ArgType(UINT16 attrType, OVS_ARGTYPE parentArgType, OVS_ARGTYPE* pTypeAsArg)
+{
+    const OVS_ATTR_GROUP_INFO* pGroup = NULL;
+    int maxAttr = 0;
+    ULONG argType = 0;
+
+    pGroup = _FindGroup(parentArgType, &maxAttr);
+
+    //TODO: the func should still return BOOLEAN
+    OVS_CHECK_RET(pGroup, FALSE);
+    OVS_CHECK_RET(attrType <= maxAttr, FALSE);
+
+    argType = pGroup->group[attrType];
+    OVS_CHECK_RET(argType != OVS_ARGTYPE_INVALID, FALSE);
+
+    *pTypeAsArg = argType;
+
+    return TRUE;
+}
diff --git a/datapath-windows/ovsext/Winetlink/AttrToArgument.h b/datapath-windows/ovsext/Winetlink/AttrToArgument.h
new file mode 100644
index 0000000..3bb7156
--- /dev/null
+++ b/datapath-windows/ovsext/Winetlink/AttrToArgument.h
@@ -0,0 +1,22 @@
+/*
+Copyright 2014 Cloudbase Solutions Srl
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http ://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+#pragma once
+
+#include "precomp.h"
+#include "ArgumentType.h"
+
+BOOLEAN AttrType_To_ArgType(UINT16 attrType, OVS_ARGTYPE parentType, OVS_ARGTYPE* pTypeAsArg);
diff --git a/datapath-windows/ovsext/ovsext.vcxproj b/datapath-windows/ovsext/ovsext.vcxproj
index a42bdc9..ba31b23 100644
--- a/datapath-windows/ovsext/ovsext.vcxproj
+++ b/datapath-windows/ovsext/ovsext.vcxproj
@@ -99,6 +99,9 @@
     <ClInclude Include="Transfer\Tunnel.h" />
     <ClInclude Include="Transfer\TunnelIntf.h" />
     <ClInclude Include="Transfer\Vxlan.h" />
+    <ClInclude Include="Winetlink\ArgToAttribute.h" />
+    <ClInclude Include="Winetlink\ArgumentType.h" />
+    <ClInclude Include="Winetlink\AttrToArgument.h" />
     <ClInclude Include="Winetlink\Event.h" />
     <ClInclude Include="Winetlink\Ioctl.h" />
     <ClInclude Include="Winetlink\Netlink.h" />
@@ -167,6 +170,8 @@
     <ClCompile Include="Transfer\Tunnel.c" />
     <ClCompile Include="Transfer\TunnelFilter.c" />
     <ClCompile Include="Transfer\Vxlan.c" />
+    <ClCompile Include="Winetlink\ArgToAttribute.c" />
+    <ClCompile Include="Winetlink\AttrToArgument.c" />
     <ClCompile Include="Winetlink\Event.c" />
     <ClCompile Include="Winetlink\Ioctl.c" />
     <ClCompile Include="Winetlink\User.c" />
diff --git a/datapath-windows/ovsext/ovsext.vcxproj.filters b/datapath-windows/ovsext/ovsext.vcxproj.filters
index 3beed7f..3006cfd 100644
--- a/datapath-windows/ovsext/ovsext.vcxproj.filters
+++ b/datapath-windows/ovsext/ovsext.vcxproj.filters
@@ -101,6 +101,15 @@
     <ClInclude Include="OpenFlow\DpPort.h">
       <Filter>OpenFlow</Filter>
     </ClInclude>
+    <ClInclude Include="Winetlink\ArgToAttribute.h">
+      <Filter>Winetlink</Filter>
+    </ClInclude>
+    <ClInclude Include="Winetlink\ArgumentType.h">
+      <Filter>Winetlink</Filter>
+    </ClInclude>
+    <ClInclude Include="Winetlink\AttrToArgument.h">
+      <Filter>Winetlink</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="ovsext.rc" />
@@ -205,5 +214,11 @@
     <ClCompile Include="OpenFlow\DpPort.c">
       <Filter>OpenFlow</Filter>
     </ClCompile>
+    <ClCompile Include="Winetlink\ArgToAttribute.c">
+      <Filter>Winetlink</Filter>
+    </ClCompile>
+    <ClCompile Include="Winetlink\AttrToArgument.c">
+      <Filter>Winetlink</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>
\ No newline at end of file
--
1.8.3.msysgit.0





More information about the dev mailing list