summaryrefslogtreecommitdiff
path: root/datapath-windows/ovsext/Vport.h
blob: 32cbf8bcc0cf1c777e0985a2ecc18d61dfecdc2c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
/*
 * Copyright (c) 2014 VMware, Inc.
 *
 * 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.
 */

#ifndef __VPORT_H_
#define __VPORT_H_ 1

#include "Gre.h"
#include "Stt.h"
#include "Switch.h"
#include "VxLan.h"
#include "Geneve.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
 * 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
 * following types. Some of the Vports are "real" ports on the hyper-v switch,
 * and some are not:
 * - VIF port (VM's NIC)
 * - External Adapters (physical NIC)
 * - Internal Adapter (Virtual adapter exposed on the host).
 * - Tunnel ports created by OVS userspace.
 */

typedef enum {
    OVS_STATE_UNKNOWN,
    OVS_STATE_PORT_CREATED,
    OVS_STATE_NIC_CREATED,
    OVS_STATE_CONNECTED,
    OVS_STATE_PORT_TEAR_DOWN,
    OVS_STATE_PORT_DELETED,
} OVS_VPORT_STATE;

typedef struct _OVS_VPORT_STATS {
    UINT64 rxPackets;
    UINT64 txPackets;
    UINT64 rxBytes;
    UINT64 txBytes;
} OVS_VPORT_STATS;

typedef struct _OVS_VPORT_ERR_STATS {
    UINT64  rxErrors;
    UINT64  txErrors;
    UINT64  rxDropped;
    UINT64  txDropped;
} OVS_VPORT_ERR_STATS;

/* used for vport netlink commands. */
typedef struct _OVS_VPORT_FULL_STATS {
    OVS_VPORT_STATS;
    OVS_VPORT_ERR_STATS;
}OVS_VPORT_FULL_STATS;
/*
 * 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
 */
typedef struct _OVS_VPORT_ENTRY {
    LIST_ENTRY                   ovsNameLink;
    LIST_ENTRY                   portIdLink;
    LIST_ENTRY                   portNoLink;
    LIST_ENTRY                   tunnelVportLink;

    OVS_VPORT_STATE              ovsState;
    OVS_VPORT_TYPE               ovsType;
    OVS_VPORT_STATS              stats;
    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];

    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;

    UINT8                        permMacAddress[ETH_ADDR_LEN];
    UINT8                        currMacAddress[ETH_ADDR_LEN];
    UINT8                        vmMacAddress[ETH_ADDR_LEN];

    NDIS_SWITCH_PORT_NAME        hvPortName;
    IF_COUNTED_STRING            portFriendlyName;
    NDIS_SWITCH_NIC_NAME         nicName;
    NDIS_SWITCH_NIC_FRIENDLYNAME nicFriendlyName;
    NDIS_VM_NAME                 vmName;
    GUID                         netCfgInstanceId;
    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;

_Requires_lock_held_(switchContext->dispatchLock)
POVS_VPORT_ENTRY OvsFindVportByPortNo(POVS_SWITCH_CONTEXT switchContext,
                                      UINT32 portNo);
/* "name" is null-terminated */
_Requires_lock_held_(switchContext->dispatchLock)
POVS_VPORT_ENTRY OvsFindVportByOvsName(POVS_SWITCH_CONTEXT switchContext,
                                       PSTR name);
_Requires_lock_held_(switchContext->dispatchLock)
POVS_VPORT_ENTRY OvsFindVportByHvNameA(POVS_SWITCH_CONTEXT switchContext,
                                       PSTR name);
_Requires_lock_held_(switchContext->dispatchLock)
POVS_VPORT_ENTRY OvsFindVportByHvNameW(POVS_SWITCH_CONTEXT switchContext,
                                       PWSTR wsName, SIZE_T wstrSize);
_Requires_lock_held_(switchContext->dispatchLock)
POVS_VPORT_ENTRY OvsFindVportByPortIdAndNicIndex(POVS_SWITCH_CONTEXT switchContext,
                                                 NDIS_SWITCH_PORT_ID portId,
                                                 NDIS_SWITCH_NIC_INDEX index);
BOOLEAN OvsIsExternalVportByPortId(POVS_SWITCH_CONTEXT switchContext,
                                   NDIS_SWITCH_PORT_ID portId);
POVS_VPORT_ENTRY OvsFindTunnelVportByDstPortAndType(POVS_SWITCH_CONTEXT switchContext,
                                                    UINT16 dstPort,
                                                    OVS_VPORT_TYPE ovsPortType);
POVS_VPORT_ENTRY OvsFindTunnelVportByDstPortAndNWProto(POVS_SWITCH_CONTEXT switchContext,
                                                       UINT16 dstPort,
                                                       UINT8 nwProto);
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);

VOID OvsClearAllSwitchVports(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);
VOID HvDeletePort(POVS_SWITCH_CONTEXT switchContext,
                  PNDIS_SWITCH_PORT_PARAMETERS portParam);
VOID HvConnectNic(POVS_SWITCH_CONTEXT switchContext,
                  PNDIS_SWITCH_NIC_PARAMETERS nicParam);
VOID HvUpdateNic(POVS_SWITCH_CONTEXT switchContext,
                 PNDIS_SWITCH_NIC_PARAMETERS nicParam);
VOID HvDeleteNic(POVS_SWITCH_CONTEXT switchContext,
                 PNDIS_SWITCH_NIC_PARAMETERS nicParam);
VOID HvDisconnectNic(POVS_SWITCH_CONTEXT switchContext,
                     PNDIS_SWITCH_NIC_PARAMETERS nicParam);

static __inline BOOLEAN
OvsIsTunnelVportType(OVS_VPORT_TYPE ovsType)
{
    return ovsType == OVS_VPORT_TYPE_VXLAN ||
           ovsType == OVS_VPORT_TYPE_GENEVE ||
           ovsType == OVS_VPORT_TYPE_STT ||
           ovsType == OVS_VPORT_TYPE_GRE;
}


static __inline PVOID
GetOvsVportPriv(POVS_VPORT_ENTRY ovsVport)
{
    return ovsVport->priv;
}

static __inline BOOLEAN
OvsIsInternalVportType(OVS_VPORT_TYPE ovsType)
{
    return ovsType == OVS_VPORT_TYPE_INTERNAL;
}

static __inline BOOLEAN
OvsIsVirtualExternalVport(POVS_VPORT_ENTRY vport)
{
    return vport->nicType == NdisSwitchNicTypeExternal &&
           vport->nicIndex == 0;
}

static __inline BOOLEAN
OvsIsRealExternalVport(POVS_VPORT_ENTRY vport)
{
    return vport->nicType == NdisSwitchNicTypeExternal &&
           vport->nicIndex != 0;
}

static __inline BOOLEAN
OvsIsInternalNIC(NDIS_SWITCH_NIC_TYPE   nicType)
{
    return nicType == NdisSwitchNicTypeInternal;
}

static __inline BOOLEAN
OvsIsRealExternalNIC(NDIS_SWITCH_NIC_TYPE   nicType,
                     NDIS_SWITCH_NIC_INDEX  nicIndex)
{
    return nicType == NdisSwitchNicTypeExternal &&
           nicIndex != 0;
}

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 switchContext->virtualExternalVport;
}

static __inline UINT32
OvsGetExternalMtu(POVS_SWITCH_CONTEXT switchContext)
{
    ASSERT(OvsGetExternalVport(switchContext));
    return ((POVS_VPORT_ENTRY) OvsGetExternalVport(switchContext))->mtu;
}

static __inline UINT16
GetPortFromPriv(POVS_VPORT_ENTRY vport)
{
    UINT16 dstPort = 0;
    PVOID vportPriv = GetOvsVportPriv(vport);

    /* XXX would better to have a common 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;
    case OVS_VPORT_TYPE_GENEVE:
        dstPort = ((POVS_GENEVE_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_ */