summaryrefslogtreecommitdiff
path: root/datapath-windows/ovsext/Switch.h
blob: 806ee782053116fc64084c00b199cec179f75f63 (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
/*
 * 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.
 */

/*
 * This file contains the definition of the switch object for the OVS.
 */

#ifndef __SWITCH_H_
#define __SWITCH_H_ 1

#include "NetProto.h"
#include "BufferMgmt.h"
#include "TunnelIntf.h"
#define OVS_MAX_VPORT_ARRAY_SIZE 1024
#define OVS_MAX_PID_ARRAY_SIZE   1024

#define OVS_VPORT_MASK (OVS_MAX_VPORT_ARRAY_SIZE - 1)
#define OVS_PID_MASK (OVS_MAX_PID_ARRAY_SIZE - 1)

#define OVS_INTERNAL_VPORT_DEFAULT_INDEX 0

//Tunnel port indicies
#define RESERVED_START_INDEX1    1
#define OVS_TUNNEL_INDEX_START RESERVED_START_INDEX1
#define OVS_VXLAN_VPORT_INDEX    2
#define OVS_GRE_VPORT_INDEX      3
#define OVS_TUNNEL_INDEX_END OVS_GRE_VPORT_INDEX

#define OVS_MAX_PHYS_ADAPTERS    32
#define OVS_MAX_IP_VPOR          32

#define OVS_HASH_BASIS   0x13578642

typedef struct _OVS_VPORT_ENTRY *POVS_VPORT_ENTRY;

typedef struct _OVS_DATAPATH
{
   PLIST_ENTRY             flowTable;       // Contains OvsFlows.
   UINT32                  nFlows;          // Number of entries in flowTable.

   // List_Links              queues[64];      // Hash table of queue IDs.

   /* Statistics. */
   UINT64                  hits;            // Number of flow table hits.
   UINT64                  misses;          // Number of flow table misses.
   UINT64                  lost;            // Number of dropped misses.

   /* Used to protect the flows in the flowtable. */
   PNDIS_RW_LOCK_EX        lock;
} OVS_DATAPATH, *POVS_DATAPATH;

/*
 * OVS_SWITCH_CONTEXT
 *
 * The context allocated per switch., For OVS, we only
 * support one switch which corresponding to one datapath.
 * Each datapath can have multiple logical bridges configured
 * which is maintained by vswitchd.
 */

typedef enum OVS_SWITCH_DATAFLOW_STATE
{
    OvsSwitchPaused,
    OvsSwitchRunning
} OVS_SWITCH_DATAFLOW_STATE, *POVS_SWITCH_DATAFLOW_STATE;

typedef enum OVS_SWITCH_CONTROFLOW_STATE
{
    OvsSwitchUnknown,
    OvsSwitchAttached,
    OvsSwitchDetached
} OVS_SWITCH_CONTROLFLOW_STATE, *POVS_SWITCH_CONTROLFLOW_STATE;

// XXX: Take care of alignment and grouping members by cacheline
typedef struct _OVS_SWITCH_CONTEXT
{
    /* Coarse and fine-grained switch states. */
    OVS_SWITCH_DATAFLOW_STATE dataFlowState;
    OVS_SWITCH_CONTROLFLOW_STATE controlFlowState;
    BOOLEAN                 isActivated;
    BOOLEAN                 isActivateFailed;

    UINT32                  dpNo;

    /*
     * 'virtualExternalVport' represents default external interface. This is
     * a virtual interface. The friendly name of such an interface has
     * been observed to be: "Microsoft Default External Interface". This NIC
     * has 'NicIndex' == 0.
     *
     * The "real" physical external NIC has 'NicIndex' > 0. For each
     * external interface, virtual or physical, NDIS gives an NIC level
     * OID callback. Note that, even though there are multiple "NICs",
     * there's only one underlying Hyper-V port. Thus, we get a single
     * NDIS port-level callback, but multiple NDIS NIC-level callbacks.
     *
     * The virtual external NIC can be accessed at 'virtualExternalVport', and
     * is assigned the name "external.defaultAdapter". The virtual external
     * NIC is not inserted into the 'portIdHashArray' since the port must not
     * be exposed to OVS userspace.
     *
     * The physical external NICs are assigned names "external.%INDEX%",
     * where '%INDEX%' represents the 'NicIndex' of the NIC.
     *
     * While adding a physical external NIC in OvsInitConfiguredSwitchNics(),
     * some required properties of the vport are available only at the
     * NDIS port-level. So, these are copied from 'virtualExternalVport'.
     * The vport created for the physical external NIC is inserted into the
     * 'portIdHashArray'.
     *
     * When the virtual external NIC is torn down or deleted, the
     * corresponding physical external ports are also torn down or
     * deleted. The number of physical external NICs is tracked by
     * 'numPhysicalNics'.
     */
    NDIS_SWITCH_PORT_ID     virtualExternalPortId;
    POVS_VPORT_ENTRY        virtualExternalVport;   /* the virtual adapter
                                                     * vport */
    INT32                   countInternalVports;    /* the number of internal
                                                     * vports */
    UINT32                  ipHelperBoundVportNo;   /* vportNo bound to
                                                     * IpHelper */

    /*
     * 'portIdHashArray' ONLY contains ports that exist on the Hyper-V switch,
     * namely: VIF (vNIC) ports, external port and Hyper-V internal port.
     * 'numHvVports' counts the ports in 'portIdHashArray'. If a port got
     * deleted on the Hyper-V switch, it gets deleted from 'portIdHashArray'.
     * The port itself will not get deallocated if it has been added from OVS
     * userspace. 'numHvVports' is decremented when the port is deallocated.
     *
     * 'portNoHashArray' ONLY contains ports that are added from OVS userspace,
     * regardless of whether that port exists on the Hyper-V switch or not.
     * Tunnel ports and bridge-internal ports are examples of ports that do not
     * exist on the Hyper-V switch, and 'numNonHvVports' counts such ports in
     * 'portNoHashArray'.
     *
     * 'tunnelVportsArray' contains tunnel ports that are added from OVS
     * userspace. Currently only VXLAN tunnels are added in this list.
     *
     * 'ovsPortNameHashArray' contains the same entries as 'portNoHashArray' but
     * hashed on a different key.
     */
    PLIST_ENTRY             portIdHashArray;        // based on Hyper-V portId
    PLIST_ENTRY             portNoHashArray;        // based on ovs port number
    PLIST_ENTRY             tunnelVportsArray;      // based on ovs dst port number
    PLIST_ENTRY             ovsPortNameHashArray;   // based on ovsName
    PLIST_ENTRY             pidHashArray;           // based on packet pids
    NDIS_SPIN_LOCK          pidHashLock;            // Lock for pidHash table

    UINT32                  numPhysicalNics;        // the number of physical
                                                    // external NICs.
    UINT32                  numHvVports;
    UINT32                  numNonHvVports;

    /* Lock taken over the switch. This protects the ports on the switch. */
    PNDIS_RW_LOCK_EX        dispatchLock;

    /* The flowtable. */
    OVS_DATAPATH            datapath;

    /* Handle to the OVSExt filter driver. Same as 'gOvsExtDriverHandle'. */
    NDIS_HANDLE NdisFilterHandle;

    /* Handle and callbacks exposed by the underlying hyper-v switch. */
    NDIS_SWITCH_CONTEXT NdisSwitchContext;
    NDIS_SWITCH_OPTIONAL_HANDLERS NdisSwitchHandlers;

    volatile LONG pendingInjectedNblCount;
    volatile LONG pendingOidCount;

    OVS_NBL_POOL            ovsPool;
} OVS_SWITCH_CONTEXT, *POVS_SWITCH_CONTEXT;


_IRQL_raises_(DISPATCH_LEVEL)
_IRQL_saves_global_(OldIrql, lockState)
_Acquires_lock_(datapath->lock)
static __inline VOID
OvsAcquireDatapathRead(OVS_DATAPATH *datapath,
                       LOCK_STATE_EX *lockState,
                       BOOLEAN dispatch)
{
    ASSERT(datapath);
    NdisAcquireRWLockRead(datapath->lock, lockState,
                          dispatch ? NDIS_RWL_AT_DISPATCH_LEVEL : 0);
}

_IRQL_raises_(DISPATCH_LEVEL)
_IRQL_saves_global_(OldIrql, lockState)
_Acquires_lock_(datapath->lock)
static __inline VOID
OvsAcquireDatapathWrite(OVS_DATAPATH *datapath,
                        LOCK_STATE_EX *lockState,
                        BOOLEAN dispatch)
{
    ASSERT(datapath);
    NdisAcquireRWLockWrite(datapath->lock, lockState,
                           dispatch ? NDIS_RWL_AT_DISPATCH_LEVEL : 0);
}

_IRQL_requires_(DISPATCH_LEVEL)
_IRQL_restores_global_(OldIrql, lockState)
_Requires_lock_held_(datapath->lock)
_Releases_lock_(datapath->lock)
static __inline VOID
OvsReleaseDatapath(OVS_DATAPATH *datapath,
                   LOCK_STATE_EX *lockState)
{
    ASSERT(datapath);
    NdisReleaseRWLock(datapath->lock, lockState);
}

BOOLEAN
OvsAcquireSwitchContext(VOID);

VOID
OvsReleaseSwitchContext(POVS_SWITCH_CONTEXT switchContext);

#endif /* __SWITCH_H_ */