summaryrefslogtreecommitdiff
path: root/datapath-windows/ovsext/Vport.h
blob: ba21c62430079ddaa2ccb89566fe470004afeb2d (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
/*
 * 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 "Switch.h"
#include "VxLan.h"
#include "Stt.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

#define OVS_DPPORT_INTERNAL_NAME_A  "internal"
#define OVS_DPPORT_INTERNAL_NAME_W  L"internal"
#define OVS_DPPORT_EXTERNAL_NAME_A   "external"
#define OVS_DPPORT_EXTERNAL_NAME_W  L"external"

/*
 * 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;
    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_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;

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);

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_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_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
OvsIsBridgeInternalVport(POVS_VPORT_ENTRY vport)
{
    if (vport->isBridgeInternal) {
       ASSERT(vport->ovsType == OVS_VPORT_TYPE_INTERNAL);
    }
    return vport->isBridgeInternal == TRUE;
}

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 commom tunnel "parent" structure */
    ASSERT(vportPriv);
    switch(vport->ovsType) {
    case OVS_VPORT_TYPE_VXLAN:
        dstPort = ((POVS_VXLAN_VPORT)vportPriv)->dstPort;
        break;
    case OVS_VPORT_TYPE_STT:
        dstPort = ((POVS_STT_VPORT)vportPriv)->dstPort;
        break;
    default:
        ASSERT(! "Port is not a tunnel port");
    }
    ASSERT(dstPort);
    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_ */