2 * Copyright (c) 2014 VMware, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
24 #define OVS_MAX_DPPORTS MAXUINT16
25 #define OVS_DPPORT_NUMBER_INVALID OVS_MAX_DPPORTS
27 * The local port (0) is a reserved port, that is not allowed to be be
28 * created by the netlink command vport add. On linux, this port is created
29 * at netlink command datapath new. However, on windows, we do not need to
30 * create it, and more, we shouldn't. The userspace attempts to create two
31 * internal vports, the LOCAL port (0) and the internal port (with any other
32 * port number). The non-LOCAL internal port is used in the userspace when it
33 * requests the internal port.
35 #define OVS_DPPORT_NUMBER_LOCAL 0
37 #define OVS_DPPORT_INTERNAL_NAME_A "internal"
38 #define OVS_DPPORT_INTERNAL_NAME_W L"internal"
39 #define OVS_DPPORT_EXTERNAL_NAME_A "external"
40 #define OVS_DPPORT_EXTERNAL_NAME_W L"external"
43 * A Vport, or Virtual Port, is a port on the OVS. It can be one of the
44 * following types. Some of the Vports are "real" ports on the hyper-v switch,
46 * - VIF port (VM's NIC)
47 * - External Adapters (physical NIC)
48 * - Internal Adapter (Virtual adapter exposed on the host).
49 * - Tunnel ports created by OVS userspace.
54 OVS_STATE_PORT_CREATED
,
55 OVS_STATE_NIC_CREATED
,
57 OVS_STATE_PORT_TEAR_DOWN
,
58 OVS_STATE_PORT_DELETED
,
61 typedef struct _OVS_VPORT_STATS
{
68 typedef struct _OVS_VPORT_ERR_STATS
{
73 } OVS_VPORT_ERR_STATS
;
75 /* used for vport netlink commands. */
76 typedef struct _OVS_VPORT_FULL_STATS
{
79 }OVS_VPORT_FULL_STATS
;
81 * Each internal, external adapter or vritual adapter has
82 * one vport entry. In addition, we have one vport for each
83 * tunnel type, such as vxlan, gre
85 typedef struct _OVS_VPORT_ENTRY
{
86 LIST_ENTRY ovsNameLink
;
87 LIST_ENTRY portIdLink
;
88 LIST_ENTRY portNoLink
;
89 LIST_ENTRY tunnelVportLink
;
91 OVS_VPORT_STATE ovsState
;
92 OVS_VPORT_TYPE ovsType
;
93 OVS_VPORT_STATS stats
;
94 OVS_VPORT_ERR_STATS errStats
;
97 /* ovsName is the ovs (datapath) port name - it is null terminated. */
98 CHAR ovsName
[OVS_MAX_PORT_NAME_LENGTH
];
101 NDIS_SWITCH_PORT_ID portId
;
102 NDIS_SWITCH_NIC_INDEX nicIndex
;
104 NDIS_SWITCH_PORT_STATE portState
;
105 NDIS_SWITCH_NIC_STATE nicState
;
106 NDIS_SWITCH_PORT_TYPE portType
;
108 UINT8 permMacAddress
[ETH_ADDR_LEN
];
109 UINT8 currMacAddress
[ETH_ADDR_LEN
];
110 UINT8 vmMacAddress
[ETH_ADDR_LEN
];
112 NDIS_SWITCH_PORT_NAME hvPortName
;
113 IF_COUNTED_STRING portFriendlyName
;
114 NDIS_SWITCH_NIC_NAME nicName
;
116 GUID netCfgInstanceId
;
118 * OVS userpace has a notion of bridges which basically defines an
119 * L2-domain. Each "bridge" has an "internal" port of type
120 * OVS_VPORT_TYPE_INTERNAL. Such a port is connected to the OVS datapath in
121 * one end, and the other end is a virtual adapter on the hypervisor host.
122 * This is akin to the Hyper-V "internal" NIC. It is intuitive to map the
123 * Hyper-V "internal" NIC to the OVS bridge's "internal" port, but there's
124 * only one Hyper-V NIC but multiple bridges. To support multiple OVS bridge
125 * "internal" ports, we use the flag 'isBridgeInternal' in each vport. We
126 * support addition of multiple bridge-internal ports. A vport with
127 * 'isBridgeInternal' == TRUE is a dummy port and has no backing currently.
128 * If a flow actions specifies the output port to be a bridge-internal port,
129 * the port is silently ignored.
131 BOOLEAN isBridgeInternal
;
133 UINT32 upcallPid
; /* netlink upcall port id */
134 PNL_ATTR portOptions
;
135 BOOLEAN isAbsentOnHv
; /* Is this port present on the
137 } OVS_VPORT_ENTRY
, *POVS_VPORT_ENTRY
;
139 struct _OVS_SWITCH_CONTEXT
;
141 POVS_VPORT_ENTRY
OvsFindVportByPortNo(POVS_SWITCH_CONTEXT switchContext
,
143 /* "name" is null-terminated */
144 POVS_VPORT_ENTRY
OvsFindVportByOvsName(POVS_SWITCH_CONTEXT switchContext
,
146 POVS_VPORT_ENTRY
OvsFindVportByHvNameA(POVS_SWITCH_CONTEXT switchContext
,
148 POVS_VPORT_ENTRY
OvsFindVportByPortIdAndNicIndex(POVS_SWITCH_CONTEXT switchContext
,
149 NDIS_SWITCH_PORT_ID portId
,
150 NDIS_SWITCH_NIC_INDEX index
);
151 POVS_VPORT_ENTRY
OvsFindTunnelVportByDstPort(POVS_SWITCH_CONTEXT switchContext
,
153 OVS_VPORT_TYPE ovsVportType
);
155 NDIS_STATUS
OvsAddConfiguredSwitchPorts(struct _OVS_SWITCH_CONTEXT
*switchContext
);
156 NDIS_STATUS
OvsInitConfiguredSwitchNics(struct _OVS_SWITCH_CONTEXT
*switchContext
);
158 VOID
OvsClearAllSwitchVports(struct _OVS_SWITCH_CONTEXT
*switchContext
);
160 NDIS_STATUS
HvCreateNic(POVS_SWITCH_CONTEXT switchContext
,
161 PNDIS_SWITCH_NIC_PARAMETERS nicParam
);
162 NDIS_STATUS
HvCreatePort(POVS_SWITCH_CONTEXT switchContext
,
163 PNDIS_SWITCH_PORT_PARAMETERS portParam
);
164 NDIS_STATUS
HvUpdatePort(POVS_SWITCH_CONTEXT switchContext
,
165 PNDIS_SWITCH_PORT_PARAMETERS portParam
);
166 VOID
HvTeardownPort(POVS_SWITCH_CONTEXT switchContext
,
167 PNDIS_SWITCH_PORT_PARAMETERS portParam
);
168 VOID
HvDeletePort(POVS_SWITCH_CONTEXT switchContext
,
169 PNDIS_SWITCH_PORT_PARAMETERS portParam
);
170 VOID
HvConnectNic(POVS_SWITCH_CONTEXT switchContext
,
171 PNDIS_SWITCH_NIC_PARAMETERS nicParam
);
172 VOID
HvUpdateNic(POVS_SWITCH_CONTEXT switchContext
,
173 PNDIS_SWITCH_NIC_PARAMETERS nicParam
);
174 VOID
HvDeleteNic(POVS_SWITCH_CONTEXT switchContext
,
175 PNDIS_SWITCH_NIC_PARAMETERS nicParam
);
176 VOID
HvDisconnectNic(POVS_SWITCH_CONTEXT switchContext
,
177 PNDIS_SWITCH_NIC_PARAMETERS nicParam
);
179 static __inline BOOLEAN
180 OvsIsTunnelVportType(OVS_VPORT_TYPE ovsType
)
182 return ovsType
== OVS_VPORT_TYPE_VXLAN
||
183 ovsType
== OVS_VPORT_TYPE_STT
||
184 ovsType
== OVS_VPORT_TYPE_GRE
;
188 static __inline PVOID
189 GetOvsVportPriv(POVS_VPORT_ENTRY ovsVport
)
191 return ovsVport
->priv
;
194 static __inline BOOLEAN
195 OvsIsInternalVportType(OVS_VPORT_TYPE ovsType
)
197 return ovsType
== OVS_VPORT_TYPE_INTERNAL
;
200 static __inline BOOLEAN
201 OvsIsBridgeInternalVport(POVS_VPORT_ENTRY vport
)
203 if (vport
->isBridgeInternal
) {
204 ASSERT(vport
->ovsType
== OVS_VPORT_TYPE_INTERNAL
);
206 return vport
->isBridgeInternal
== TRUE
;
209 NTSTATUS
OvsRemoveAndDeleteVport(PVOID usrParamsCtx
,
210 POVS_SWITCH_CONTEXT switchContext
,
211 POVS_VPORT_ENTRY vport
,
212 BOOLEAN hvDelete
, BOOLEAN ovsDelete
);
213 static __inline POVS_VPORT_ENTRY
214 OvsGetExternalVport(POVS_SWITCH_CONTEXT switchContext
)
216 return switchContext
->virtualExternalVport
;
219 static __inline UINT32
220 OvsGetExternalMtu(POVS_SWITCH_CONTEXT switchContext
)
222 ASSERT(OvsGetExternalVport(switchContext
));
223 return ((POVS_VPORT_ENTRY
) OvsGetExternalVport(switchContext
))->mtu
;
226 static __inline UINT16
227 GetPortFromPriv(POVS_VPORT_ENTRY vport
)
230 PVOID vportPriv
= GetOvsVportPriv(vport
);
232 /* XXX would better to have a commom tunnel "parent" structure */
234 switch(vport
->ovsType
) {
235 case OVS_VPORT_TYPE_VXLAN
:
236 dstPort
= ((POVS_VXLAN_VPORT
)vportPriv
)->dstPort
;
238 case OVS_VPORT_TYPE_STT
:
239 dstPort
= ((POVS_STT_VPORT
)vportPriv
)->dstPort
;
242 ASSERT(! "Port is not a tunnel port");
248 NDIS_STATUS
InitOvsVportCommon(POVS_SWITCH_CONTEXT switchContext
,
249 POVS_VPORT_ENTRY vport
);
250 NTSTATUS
OvsInitTunnelVport(PVOID usrParamsCtx
, POVS_VPORT_ENTRY vport
,
251 OVS_VPORT_TYPE ovsType
, UINT16 dstport
);
252 NTSTATUS
OvsInitBridgeInternalVport(POVS_VPORT_ENTRY vport
);
254 POVS_VPORT_ENTRY
OvsAllocateVport(VOID
);
256 #endif /* __VPORT_H_ */