#ifndef __VPORT_H_
#define __VPORT_H_ 1
+#include "Gre.h"
+#include "Stt.h"
#include "Switch.h"
+#include "VxLan.h"
+
+#define OVS_MAX_DPPORTS MAXUINT16
+#define OVS_DPPORT_NUMBER_INVALID OVS_MAX_DPPORTS
+/*
+ * The local port (0) is a reserved port, that is not allowed to be be
+ * created by the netlink command vport add. On linux, this port is created
+ * at netlink command datapath new. However, on windows, we do not need to
+ * create it, and more, we shouldn't. The userspace attempts to create two
+ * internal vports, the LOCAL port (0) and the internal port (with any other
+ * port number). The non-LOCAL internal port is used in the userspace when it
+ * requests the internal port.
+ */
+#define OVS_DPPORT_NUMBER_LOCAL 0
/*
* A Vport, or Virtual Port, is a port on the OVS. It can be one of the
/*
* Each internal, external adapter or vritual adapter has
* one vport entry. In addition, we have one vport for each
- * tunnel type, such as vxlan, gre, gre64
+ * tunnel type, such as vxlan, gre
*/
typedef struct _OVS_VPORT_ENTRY {
- LIST_ENTRY nameLink;
- LIST_ENTRY portLink;
+ LIST_ENTRY ovsNameLink;
+ LIST_ENTRY portIdLink;
+ LIST_ENTRY portNoLink;
+ LIST_ENTRY tunnelVportLink;
OVS_VPORT_STATE ovsState;
OVS_VPORT_TYPE ovsType;
OVS_VPORT_ERR_STATS errStats;
UINT32 portNo;
UINT32 mtu;
+ /* ovsName is the ovs (datapath) port name - it is null terminated. */
CHAR ovsName[OVS_MAX_PORT_NAME_LENGTH];
- UINT32 ovsNameLen;
PVOID priv;
NDIS_SWITCH_PORT_ID portId;
NDIS_SWITCH_NIC_INDEX nicIndex;
+ NDIS_SWITCH_NIC_TYPE nicType;
UINT16 numaNodeId;
NDIS_SWITCH_PORT_STATE portState;
NDIS_SWITCH_NIC_STATE nicState;
NDIS_SWITCH_PORT_TYPE portType;
- BOOLEAN isValidationPort;
- UINT8 permMacAddress[MAC_ADDRESS_LEN];
- UINT8 currMacAddress[MAC_ADDRESS_LEN];
- UINT8 vmMacAddress[MAC_ADDRESS_LEN];
+ UINT8 permMacAddress[ETH_ADDR_LEN];
+ UINT8 currMacAddress[ETH_ADDR_LEN];
+ UINT8 vmMacAddress[ETH_ADDR_LEN];
- NDIS_SWITCH_PORT_NAME portName;
+ NDIS_SWITCH_PORT_NAME hvPortName;
+ IF_COUNTED_STRING portFriendlyName;
NDIS_SWITCH_NIC_NAME nicName;
NDIS_VM_NAME vmName;
GUID netCfgInstanceId;
+ /*
+ * OVS userpace has a notion of bridges which basically defines an
+ * L2-domain. Each "bridge" has an "internal" port of type
+ * OVS_VPORT_TYPE_INTERNAL. Such a port is connected to the OVS datapath in
+ * one end, and the other end is a virtual adapter on the hypervisor host.
+ * This is akin to the Hyper-V "internal" NIC. It is intuitive to map the
+ * Hyper-V "internal" NIC to the OVS bridge's "internal" port, but there's
+ * only one Hyper-V NIC but multiple bridges. To support multiple OVS bridge
+ * "internal" ports, we use the flag 'isBridgeInternal' in each vport. We
+ * support addition of multiple bridge-internal ports. A vport with
+ * 'isBridgeInternal' == TRUE is a dummy port and has no backing currently.
+ * If a flow actions specifies the output port to be a bridge-internal port,
+ * the port is silently ignored.
+ */
+ BOOLEAN isBridgeInternal;
BOOLEAN isExternal;
UINT32 upcallPid; /* netlink upcall port id */
+ PNL_ATTR portOptions;
+ BOOLEAN isAbsentOnHv; /* Is this port present on the
+ Hyper-V switch? */
} OVS_VPORT_ENTRY, *POVS_VPORT_ENTRY;
struct _OVS_SWITCH_CONTEXT;
-#define OVS_IS_VPORT_ENTRY_NULL(_SwitchContext, _i) \
- ((UINT64)(_SwitchContext)->vportArray[_i] <= 0xff)
-
-POVS_VPORT_ENTRY
-OvsFindVportByPortNo(struct _OVS_SWITCH_CONTEXT *switchContext,
- UINT32 portNo);
-POVS_VPORT_ENTRY
-OvsFindVportByOvsName(struct _OVS_SWITCH_CONTEXT *switchContext,
- CHAR *name, UINT32 length);
-POVS_VPORT_ENTRY
-OvsFindVportByPortIdAndNicIndex(struct _OVS_SWITCH_CONTEXT *switchContext,
- NDIS_SWITCH_PORT_ID portId,
- NDIS_SWITCH_NIC_INDEX index);
+POVS_VPORT_ENTRY OvsFindVportByPortNo(POVS_SWITCH_CONTEXT switchContext,
+ UINT32 portNo);
+/* "name" is null-terminated */
+POVS_VPORT_ENTRY OvsFindVportByOvsName(POVS_SWITCH_CONTEXT switchContext,
+ PSTR name);
+POVS_VPORT_ENTRY OvsFindVportByHvNameA(POVS_SWITCH_CONTEXT switchContext,
+ PSTR name);
+POVS_VPORT_ENTRY OvsFindVportByPortIdAndNicIndex(POVS_SWITCH_CONTEXT switchContext,
+ NDIS_SWITCH_PORT_ID portId,
+ NDIS_SWITCH_NIC_INDEX index);
+POVS_VPORT_ENTRY OvsFindTunnelVportByDstPort(POVS_SWITCH_CONTEXT switchContext,
+ UINT16 dstPort,
+ OVS_VPORT_TYPE ovsVportType);
+POVS_VPORT_ENTRY OvsFindTunnelVportByPortType(POVS_SWITCH_CONTEXT switchContext,
+ OVS_VPORT_TYPE ovsPortType);
NDIS_STATUS OvsAddConfiguredSwitchPorts(struct _OVS_SWITCH_CONTEXT *switchContext);
NDIS_STATUS OvsInitConfiguredSwitchNics(struct _OVS_SWITCH_CONTEXT *switchContext);
NDIS_STATUS HvCreateNic(POVS_SWITCH_CONTEXT switchContext,
PNDIS_SWITCH_NIC_PARAMETERS nicParam);
NDIS_STATUS HvCreatePort(POVS_SWITCH_CONTEXT switchContext,
+ PNDIS_SWITCH_PORT_PARAMETERS portParam,
+ NDIS_SWITCH_NIC_INDEX nicIndex);
+NDIS_STATUS HvUpdatePort(POVS_SWITCH_CONTEXT switchContext,
PNDIS_SWITCH_PORT_PARAMETERS portParam);
VOID HvTeardownPort(POVS_SWITCH_CONTEXT switchContext,
PNDIS_SWITCH_PORT_PARAMETERS portParam);
OvsIsTunnelVportType(OVS_VPORT_TYPE ovsType)
{
return ovsType == OVS_VPORT_TYPE_VXLAN ||
- ovsType == OVS_VPORT_TYPE_GRE ||
- ovsType == OVS_VPORT_TYPE_GRE64;
+ ovsType == OVS_VPORT_TYPE_STT ||
+ ovsType == OVS_VPORT_TYPE_GRE;
+}
+
+
+static __inline PVOID
+GetOvsVportPriv(POVS_VPORT_ENTRY ovsVport)
+{
+ return ovsVport->priv;
}
static __inline BOOLEAN
}
static __inline BOOLEAN
-OvsIsTunnelVportNo(UINT32 portNo)
+OvsIsVirtualExternalVport(POVS_VPORT_ENTRY vport)
{
- UINT32 idx = OVS_VPORT_INDEX(portNo);
- return (idx >= OVS_TUNNEL_INDEX_START && idx <= OVS_TUNNEL_INDEX_END);
+ return vport->nicType == NdisSwitchNicTypeExternal &&
+ vport->nicIndex == 0;
}
static __inline BOOLEAN
-OvsIsVifVportNo(UINT32 portNo)
+OvsIsRealExternalVport(POVS_VPORT_ENTRY vport)
{
- UINT32 idx = OVS_VPORT_INDEX(portNo);
- return (idx >= OVS_VM_VPORT_START && idx <= OVS_VM_VPORT_MAX);
+ return vport->nicType == NdisSwitchNicTypeExternal &&
+ vport->nicIndex != 0;
}
-static __inline POVS_VPORT_ENTRY
-OvsGetTunnelVport(OVS_VPORT_TYPE type)
+static __inline BOOLEAN
+OvsIsBridgeInternalVport(POVS_VPORT_ENTRY vport)
{
- ASSERT(OvsIsTunnelVportType(type));
- switch(type) {
- case OVS_VPORT_TYPE_VXLAN:
- return (POVS_VPORT_ENTRY) OvsGetVportFromIndex(OVS_VXLAN_VPORT_INDEX);
- default:
- ASSERT(! "OvsGetTunnelVport not implemented for this tunnel.");
- }
+ ASSERT(vport->isBridgeInternal != TRUE ||
+ vport->ovsType == OVS_VPORT_TYPE_INTERNAL);
+ return vport->isBridgeInternal == TRUE;
+}
+
+static __inline BOOLEAN
+OvsIsInternalNIC(NDIS_SWITCH_NIC_TYPE nicType)
+{
+ return nicType == NdisSwitchNicTypeInternal;
+}
- return NULL;
+static __inline BOOLEAN
+OvsIsRealExternalNIC(NDIS_SWITCH_NIC_TYPE nicType,
+ NDIS_SWITCH_NIC_INDEX nicIndex)
+{
+ return nicType == NdisSwitchNicTypeExternal &&
+ nicIndex != 0;
}
-static __inline PVOID
-OvsGetVportPriv(OVS_VPORT_TYPE type)
+NTSTATUS OvsRemoveAndDeleteVport(PVOID usrParamsCtx,
+ POVS_SWITCH_CONTEXT switchContext,
+ POVS_VPORT_ENTRY vport,
+ BOOLEAN hvDelete, BOOLEAN ovsDelete);
+static __inline POVS_VPORT_ENTRY
+OvsGetExternalVport(POVS_SWITCH_CONTEXT switchContext)
{
- return OvsGetTunnelVport(type)->priv;
+ return switchContext->virtualExternalVport;
}
static __inline UINT32
-OvsGetExternalMtu()
+OvsGetExternalMtu(POVS_SWITCH_CONTEXT switchContext)
+{
+ ASSERT(OvsGetExternalVport(switchContext));
+ return ((POVS_VPORT_ENTRY) OvsGetExternalVport(switchContext))->mtu;
+}
+
+static __inline UINT16
+GetPortFromPriv(POVS_VPORT_ENTRY vport)
{
- return ((POVS_VPORT_ENTRY) OvsGetExternalVport())->mtu;
+ UINT16 dstPort = 0;
+ PVOID vportPriv = GetOvsVportPriv(vport);
+
+ /* XXX would better to have a commom tunnel "parent" structure */
+ ASSERT(vportPriv);
+ switch(vport->ovsType) {
+ case OVS_VPORT_TYPE_GRE:
+ break;
+ case OVS_VPORT_TYPE_STT:
+ dstPort = ((POVS_STT_VPORT)vportPriv)->dstPort;
+ break;
+ case OVS_VPORT_TYPE_VXLAN:
+ dstPort = ((POVS_VXLAN_VPORT)vportPriv)->dstPort;
+ break;
+ default:
+ ASSERT(! "Port is not a tunnel port");
+ }
+ ASSERT(dstPort || vport->ovsType == OVS_VPORT_TYPE_GRE);
+ return dstPort;
}
+NDIS_STATUS InitOvsVportCommon(POVS_SWITCH_CONTEXT switchContext,
+ POVS_VPORT_ENTRY vport);
+NTSTATUS OvsInitTunnelVport(PVOID usrParamsCtx, POVS_VPORT_ENTRY vport,
+ OVS_VPORT_TYPE ovsType, UINT16 dstport);
+NTSTATUS OvsInitBridgeInternalVport(POVS_VPORT_ENTRY vport);
+
+POVS_VPORT_ENTRY OvsAllocateVport(VOID);
+
#endif /* __VPORT_H_ */