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

/*
 * XXX: OVS_USE_NL_INTERFACE is being used to keep the legacy DPIF interface
 * alive while we transition over to the netlink based interface.
 * OVS_USE_NL_INTERFACE = 0 => legacy inteface to use with dpif-windows.c
 * OVS_USE_NL_INTERFACE = 1 => netlink inteface to use with ported dpif-linux.c
 */

#ifndef __DATAPATH_H_
#define __DATAPATH_H_ 1

/*
 * Device operations to tag netlink commands with. This is a bitmask since it
 * is possible that a particular command can be invoked via different device
 * operations.
 */
#define OVS_READ_DEV_OP          (1 << 0)
#define OVS_WRITE_DEV_OP         (1 << 1)
#define OVS_TRANSACTION_DEV_OP   (1 << 2)
#define OVS_READ_EVENT_DEV_OP    (1 << 3)
#define OVS_READ_PACKET_DEV_OP   (1 << 4)

typedef struct _OVS_DEVICE_EXTENSION {
    INT numberOpenInstance;
    INT pidCount;
} OVS_DEVICE_EXTENSION, *POVS_DEVICE_EXTENSION;

// forward declaration
typedef struct _OVS_USER_PACKET_QUEUE OVS_USER_PACKET_QUEUE,
                                      *POVS_USER_PACKET_QUEUE;

/*
 * Private context for each handle on the device.
 */
typedef struct _OVS_OPEN_INSTANCE {
    UINT32 cookie;
    PFILE_OBJECT fileObject;
    PVOID eventQueue;
    POVS_USER_PACKET_QUEUE packetQueue;
    UINT32 pid;

    /*
     * On platforms that support netlink natively, there's generally some form of
     * serialization between concurrent calls to netlink sockets. However, OVS
     * userspace guarantees that a given netlink handle is not concurrently used.
     * Despite this, we do want to have some basic checks in the kernel to make
     * sure that things don't break if there are concurrent calls.
     *
     * This is generally not an issue since kernel data structure access should
     * be sychronized anyway. Only reason to have this safeguared is to protect
     * the state in "state-aware" read calls which rely on previous state. This
     * restriction might go away as the userspace code gets implemented.
     */
     INT inUse;

    struct {
        POVS_MESSAGE ovsMsg;    /* OVS message passed during dump start. */
        UINT32 index[2];        /* markers to continue dump from. One or more
                                 * of them may be used. Eg. in flow dump, the
                                 * markers can store the row and the column
                                 * indices. */
    } dumpState;                /* data to support dump commands. */
    LIST_ENTRY             pidLink; /* Links the instance to
                                     * pidHashArray */
} OVS_OPEN_INSTANCE, *POVS_OPEN_INSTANCE;

NDIS_STATUS OvsCreateDeviceObject(NDIS_HANDLE ovsExtDriverHandle);
VOID OvsDeleteDeviceObject();
VOID OvsInit();
VOID OvsCleanup();

POVS_OPEN_INSTANCE OvsGetOpenInstance(PFILE_OBJECT fileObject,
                                      UINT32 dpNo);

NTSTATUS OvsCompleteIrpRequest(PIRP irp, ULONG_PTR infoPtr, NTSTATUS status);

VOID OvsAcquireCtrlLock();
VOID OvsReleaseCtrlLock();

/*
 * Utility structure and functions to collect in one place all the parameters
 * passed during a call from userspace.
 */
typedef struct _OVS_USER_PARAMS_CONTEXT {
    PIRP irp;            /* The IRP used for the userspace call. */
    POVS_OPEN_INSTANCE ovsInstance; /* Private data of the device handle. */
    UINT32 devOp;        /* Device operation of the userspace call. */
    POVS_MESSAGE ovsMsg; /* OVS message that userspace passed down. */
    PVOID inputBuffer;   /* Input data specified by userspace. Maybe NULL. */
    UINT32 inputLength;  /* Length of input buffer. */
    PVOID outputBuffer;  /* Output buffer specified by userspace for reading
                          * data. Maybe NULL. */
    UINT32 outputLength; /* Length of output buffer. */
} OVS_USER_PARAMS_CONTEXT, *POVS_USER_PARAMS_CONTEXT;

static __inline VOID
InitUserParamsCtx(PIRP irp,
                  POVS_OPEN_INSTANCE ovsInstance,
                  UINT32 devOp,
                  POVS_MESSAGE ovsMsg,
                  PVOID inputBuffer,
                  UINT32 inputLength,
                  PVOID outputBuffer,
                  UINT32 outputLength,
                  POVS_USER_PARAMS_CONTEXT usrParamsCtx)
{
    usrParamsCtx->irp = irp;
    usrParamsCtx->ovsInstance = ovsInstance;
    usrParamsCtx->devOp = devOp;
    usrParamsCtx->ovsMsg = ovsMsg;
    usrParamsCtx->inputBuffer = inputBuffer;
    usrParamsCtx->inputLength = inputLength;
    usrParamsCtx->outputBuffer = outputBuffer;
    usrParamsCtx->outputLength = outputLength;
}

static __inline NTSTATUS
InitUserDumpState(POVS_OPEN_INSTANCE instance,
                  POVS_MESSAGE ovsMsg)
{
    /* Clear the dumpState from a previous dump sequence. */
    ASSERT(instance->dumpState.ovsMsg == NULL);
    ASSERT(ovsMsg);

    instance->dumpState.ovsMsg =
        (POVS_MESSAGE) OvsAllocateMemory(sizeof (OVS_MESSAGE));
    if (instance->dumpState.ovsMsg == NULL) {
        return STATUS_NO_MEMORY;
    }
    RtlCopyMemory(instance->dumpState.ovsMsg, ovsMsg,
                  sizeof *instance->dumpState.ovsMsg);
    RtlZeroMemory(instance->dumpState.index,
                  sizeof instance->dumpState.index);

    return STATUS_SUCCESS;
}

static __inline VOID
FreeUserDumpState(POVS_OPEN_INSTANCE instance)
{
    if (instance->dumpState.ovsMsg != NULL) {
        OvsFreeMemory(instance->dumpState.ovsMsg);
        RtlZeroMemory(&instance->dumpState, sizeof instance->dumpState);
    }
}

NTSTATUS OvsSetupDumpStart(POVS_USER_PARAMS_CONTEXT usrParamsCtx);

#endif /* __DATAPATH_H_ */