~ubuntu-branches/ubuntu/wily/openvswitch/wily

« back to all changes in this revision

Viewing changes to datapath-windows/ovsext/Flow.c

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2015-08-10 11:35:15 UTC
  • mfrom: (1.1.30)
  • Revision ID: package-import@ubuntu.com-20150810113515-575vj06oq29emxsn
Tags: 2.4.0~git20150810.97bab95-0ubuntu1
* New upstream snapshot from 2.4 branch:
  - d/*: Align any relevant packaging changes with upstream.
* d/*: wrap-and-sort.
* d/openvswitch-{common,vswitch}.install: Correct install location for
  bash completion files.
* d/tests/openflow.py: Explicitly use ovs-testcontroller as provided
  by 2.4.0 release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2014 VMware, Inc.
 
3
 *
 
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:
 
7
 *
 
8
 *     http://www.apache.org/licenses/LICENSE-2.0
 
9
 *
 
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.
 
15
 */
 
16
 
 
17
#include "precomp.h"
 
18
#include "NetProto.h"
 
19
#include "Util.h"
 
20
#include "Jhash.h"
 
21
#include "Flow.h"
 
22
#include "PacketParser.h"
 
23
#include "Datapath.h"
 
24
 
 
25
#ifdef OVS_DBG_MOD
 
26
#undef OVS_DBG_MOD
 
27
#endif
 
28
#define OVS_DBG_MOD OVS_DBG_FLOW
 
29
#include "Debug.h"
 
30
 
 
31
#pragma warning( push )
 
32
#pragma warning( disable:4127 )
 
33
 
 
34
extern POVS_SWITCH_CONTEXT gOvsSwitchContext;
 
35
extern UINT64 ovsTimeIncrementPerTick;
 
36
 
 
37
static NTSTATUS ReportFlowInfo(OvsFlow *flow, UINT32 getFlags,
 
38
                               OvsFlowInfo *info);
 
39
static NTSTATUS HandleFlowPut(OvsFlowPut *put,
 
40
                                  OVS_DATAPATH *datapath,
 
41
                                  struct OvsFlowStats *stats);
 
42
static NTSTATUS OvsPrepareFlow(OvsFlow **flow, const OvsFlowPut *put,
 
43
                               UINT64 hash);
 
44
static VOID RemoveFlow(OVS_DATAPATH *datapath, OvsFlow **flow);
 
45
static VOID DeleteAllFlows(OVS_DATAPATH *datapath);
 
46
static NTSTATUS AddFlow(OVS_DATAPATH *datapath, OvsFlow *flow);
 
47
static VOID FreeFlow(OvsFlow *flow);
 
48
static VOID __inline *GetStartAddrNBL(const NET_BUFFER_LIST *_pNB);
 
49
static NTSTATUS _MapNlToFlowPut(POVS_MESSAGE msgIn, PNL_ATTR keyAttr,
 
50
                                PNL_ATTR actionAttr,
 
51
                                PNL_ATTR flowAttrClear,
 
52
                                OvsFlowPut *mappedFlow);
 
53
static VOID _MapKeyAttrToFlowPut(PNL_ATTR *keyAttrs,
 
54
                                 PNL_ATTR *tunnelAttrs,
 
55
                                 OvsFlowKey *destKey);
 
56
 
 
57
static VOID _MapTunAttrToFlowPut(PNL_ATTR *keyAttrs,
 
58
                                 PNL_ATTR *tunnelAttrs,
 
59
                                 OvsFlowKey *destKey);
 
60
static VOID _MapNlToFlowPutFlags(PGENL_MSG_HDR genlMsgHdr,
 
61
                                 PNL_ATTR flowAttrClear,
 
62
                                 OvsFlowPut *mappedFlow);
 
63
 
 
64
static NTSTATUS _FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
 
65
                                     UINT32 *replyLen);
 
66
static NTSTATUS _FlowNlDumpCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
 
67
                                      UINT32 *replyLen);
 
68
static NTSTATUS _MapFlowInfoToNl(PNL_BUFFER nlBuf,
 
69
                                 OvsFlowInfo *flowInfo);
 
70
static NTSTATUS _MapFlowStatsToNlStats(PNL_BUFFER nlBuf,
 
71
                                       OvsFlowStats *flowStats);
 
72
static NTSTATUS _MapFlowActionToNlAction(PNL_BUFFER nlBuf,
 
73
                                         uint32_t actionsLen,
 
74
                                         PNL_ATTR actions);
 
75
 
 
76
static NTSTATUS _MapFlowIpv4KeyToNlKey(PNL_BUFFER nlBuf,
 
77
                                       IpKey *ipv4FlowPutKey);
 
78
static NTSTATUS _MapFlowIpv6KeyToNlKey(PNL_BUFFER nlBuf,
 
79
                                       Ipv6Key *ipv6FlowPutKey,
 
80
                                       Icmp6Key *ipv6FlowPutIcmpKey);
 
81
static NTSTATUS _MapFlowArpKeyToNlKey(PNL_BUFFER nlBuf,
 
82
                                      ArpKey *arpFlowPutKey);
 
83
 
 
84
static NTSTATUS OvsDoDumpFlows(OvsFlowDumpInput *dumpInput,
 
85
                               OvsFlowDumpOutput *dumpOutput,
 
86
                               UINT32 *replyLen);
 
87
 
 
88
 
 
89
#define OVS_FLOW_TABLE_SIZE 2048
 
90
#define OVS_FLOW_TABLE_MASK (OVS_FLOW_TABLE_SIZE -1)
 
91
#define HASH_BUCKET(hash) ((hash) & OVS_FLOW_TABLE_MASK)
 
92
 
 
93
/* Flow family related netlink policies */
 
94
 
 
95
/* For Parsing attributes in FLOW_* commands */
 
96
const NL_POLICY nlFlowPolicy[] = {
 
97
    [OVS_FLOW_ATTR_KEY] = {.type = NL_A_NESTED, .optional = FALSE},
 
98
    [OVS_FLOW_ATTR_MASK] = {.type = NL_A_NESTED, .optional = TRUE},
 
99
    [OVS_FLOW_ATTR_ACTIONS] = {.type = NL_A_NESTED, .optional = TRUE},
 
100
    [OVS_FLOW_ATTR_STATS] = {.type = NL_A_UNSPEC,
 
101
                             .minLen = sizeof(struct ovs_flow_stats),
 
102
                             .maxLen = sizeof(struct ovs_flow_stats),
 
103
                             .optional = TRUE},
 
104
    [OVS_FLOW_ATTR_TCP_FLAGS] = {NL_A_U8, .optional = TRUE},
 
105
    [OVS_FLOW_ATTR_USED] = {NL_A_U64, .optional = TRUE}
 
106
};
 
107
 
 
108
/* For Parsing nested OVS_FLOW_ATTR_KEY attributes.
 
109
 * Some of the attributes like OVS_KEY_ATTR_RECIRC_ID
 
110
 * & OVS_KEY_ATTR_MPLS are not supported yet. */
 
111
 
 
112
const NL_POLICY nlFlowKeyPolicy[] = {
 
113
    [OVS_KEY_ATTR_ENCAP] = {.type = NL_A_VAR_LEN, .optional = TRUE},
 
114
    [OVS_KEY_ATTR_PRIORITY] = {.type = NL_A_UNSPEC, .minLen = 4,
 
115
                               .maxLen = 4, .optional = TRUE},
 
116
    [OVS_KEY_ATTR_IN_PORT] = {.type = NL_A_UNSPEC, .minLen = 4,
 
117
                              .maxLen = 4, .optional = FALSE},
 
118
    [OVS_KEY_ATTR_ETHERNET] = {.type = NL_A_UNSPEC,
 
119
                               .minLen = sizeof(struct ovs_key_ethernet),
 
120
                               .maxLen = sizeof(struct ovs_key_ethernet),
 
121
                               .optional = TRUE},
 
122
    [OVS_KEY_ATTR_VLAN] = {.type = NL_A_UNSPEC, .minLen = 2,
 
123
                           .maxLen = 2, .optional = TRUE},
 
124
    [OVS_KEY_ATTR_ETHERTYPE] = {.type = NL_A_UNSPEC, .minLen = 2,
 
125
                                .maxLen = 2, .optional = TRUE},
 
126
    [OVS_KEY_ATTR_IPV4] = {.type = NL_A_UNSPEC,
 
127
                           .minLen = sizeof(struct ovs_key_ipv4),
 
128
                           .maxLen = sizeof(struct ovs_key_ipv4),
 
129
                           .optional = TRUE},
 
130
    [OVS_KEY_ATTR_IPV6] = {.type = NL_A_UNSPEC,
 
131
                           .minLen = sizeof(struct ovs_key_ipv6),
 
132
                           .maxLen = sizeof(struct ovs_key_ipv6),
 
133
                           .optional = TRUE},
 
134
    [OVS_KEY_ATTR_TCP] = {.type = NL_A_UNSPEC,
 
135
                          .minLen = sizeof(struct ovs_key_tcp),
 
136
                          .maxLen = sizeof(struct ovs_key_tcp),
 
137
                          .optional = TRUE},
 
138
    [OVS_KEY_ATTR_UDP] = {.type = NL_A_UNSPEC,
 
139
                          .minLen = sizeof(struct ovs_key_udp),
 
140
                          .maxLen = sizeof(struct ovs_key_udp),
 
141
                          .optional = TRUE},
 
142
    [OVS_KEY_ATTR_ICMP] = {.type = NL_A_UNSPEC,
 
143
                           .minLen = sizeof(struct ovs_key_icmp),
 
144
                           .maxLen = sizeof(struct ovs_key_icmp),
 
145
                           .optional = TRUE},
 
146
    [OVS_KEY_ATTR_ICMPV6] = {.type = NL_A_UNSPEC,
 
147
                             .minLen = sizeof(struct ovs_key_icmpv6),
 
148
                             .maxLen = sizeof(struct ovs_key_icmpv6),
 
149
                             .optional = TRUE},
 
150
    [OVS_KEY_ATTR_ARP] = {.type = NL_A_UNSPEC,
 
151
                          .minLen = sizeof(struct ovs_key_arp),
 
152
                          .maxLen = sizeof(struct ovs_key_arp),
 
153
                          .optional = TRUE},
 
154
    [OVS_KEY_ATTR_ND] = {.type = NL_A_UNSPEC,
 
155
                         .minLen = sizeof(struct ovs_key_nd),
 
156
                         .maxLen = sizeof(struct ovs_key_nd),
 
157
                         .optional = TRUE},
 
158
    [OVS_KEY_ATTR_SKB_MARK] = {.type = NL_A_UNSPEC, .minLen = 4,
 
159
                               .maxLen = 4, .optional = TRUE},
 
160
    [OVS_KEY_ATTR_TUNNEL] = {.type = NL_A_VAR_LEN, .optional = TRUE},
 
161
    [OVS_KEY_ATTR_SCTP] = {.type = NL_A_UNSPEC,
 
162
                           .minLen = sizeof(struct ovs_key_sctp),
 
163
                           .maxLen = sizeof(struct ovs_key_sctp),
 
164
                           .optional = TRUE},
 
165
    [OVS_KEY_ATTR_TCP_FLAGS] = {.type = NL_A_UNSPEC,
 
166
                                .minLen = 2, .maxLen = 2,
 
167
                                .optional = TRUE},
 
168
    [OVS_KEY_ATTR_DP_HASH] = {.type = NL_A_UNSPEC, .minLen = 4,
 
169
                              .maxLen = 4, .optional = TRUE},
 
170
    [OVS_KEY_ATTR_RECIRC_ID] = {.type = NL_A_UNSPEC, .minLen = 4,
 
171
                                .maxLen = 4, .optional = TRUE},
 
172
    [OVS_KEY_ATTR_MPLS] = {.type = NL_A_VAR_LEN, .optional = TRUE}
 
173
};
 
174
 
 
175
/* For Parsing nested OVS_KEY_ATTR_TUNNEL attributes */
 
176
const NL_POLICY nlFlowTunnelKeyPolicy[] = {
 
177
    [OVS_TUNNEL_KEY_ATTR_ID] = {.type = NL_A_UNSPEC, .minLen = 8,
 
178
                                .maxLen = 8, .optional = TRUE},
 
179
    [OVS_TUNNEL_KEY_ATTR_IPV4_SRC] = {.type = NL_A_UNSPEC, .minLen = 4,
 
180
                                      .maxLen = 4, .optional = TRUE},
 
181
    [OVS_TUNNEL_KEY_ATTR_IPV4_DST] = {.type = NL_A_UNSPEC, .minLen = 4 ,
 
182
                                      .maxLen = 4, .optional = FALSE},
 
183
    [OVS_TUNNEL_KEY_ATTR_TOS] = {.type = NL_A_UNSPEC, .minLen = 1,
 
184
                                 .maxLen = 1, .optional = TRUE},
 
185
    [OVS_TUNNEL_KEY_ATTR_TTL] = {.type = NL_A_UNSPEC, .minLen = 1,
 
186
                                 .maxLen = 1, .optional = TRUE},
 
187
    [OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT] = {.type = NL_A_UNSPEC, .minLen = 0,
 
188
                                           .maxLen = 0, .optional = TRUE},
 
189
    [OVS_TUNNEL_KEY_ATTR_CSUM] = {.type = NL_A_UNSPEC, .minLen = 0,
 
190
                                  .maxLen = 0, .optional = TRUE},
 
191
    [OVS_TUNNEL_KEY_ATTR_OAM] = {.type = NL_A_UNSPEC, .minLen = 0,
 
192
                                 .maxLen = 0, .optional = TRUE},
 
193
    [OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS] = {.type = NL_A_VAR_LEN,
 
194
                                         .optional = TRUE}
 
195
};
 
196
 
 
197
/* For Parsing nested OVS_FLOW_ATTR_ACTIONS attributes */
 
198
const NL_POLICY nlFlowActionPolicy[] = {
 
199
    [OVS_ACTION_ATTR_OUTPUT] = {.type = NL_A_UNSPEC, .minLen = sizeof(UINT32),
 
200
                                .maxLen = sizeof(UINT32), .optional = TRUE},
 
201
    [OVS_ACTION_ATTR_USERSPACE] = {.type = NL_A_VAR_LEN, .optional = TRUE},
 
202
    [OVS_ACTION_ATTR_PUSH_VLAN] = {.type = NL_A_UNSPEC,
 
203
                                   .minLen =
 
204
                                   sizeof(struct ovs_action_push_vlan),
 
205
                                   .maxLen =
 
206
                                   sizeof(struct ovs_action_push_vlan),
 
207
                                   .optional = TRUE},
 
208
    [OVS_ACTION_ATTR_POP_VLAN] = {.type = NL_A_UNSPEC, .optional = TRUE},
 
209
    [OVS_ACTION_ATTR_PUSH_MPLS] = {.type = NL_A_UNSPEC,
 
210
                                   .minLen =
 
211
                                   sizeof(struct ovs_action_push_mpls),
 
212
                                   .maxLen =
 
213
                                   sizeof(struct ovs_action_push_mpls),
 
214
                                   .optional = TRUE},
 
215
    [OVS_ACTION_ATTR_POP_MPLS] = {.type = NL_A_UNSPEC,
 
216
                                  .minLen = sizeof(UINT16),
 
217
                                  .maxLen = sizeof(UINT16),
 
218
                                  .optional = TRUE},
 
219
    [OVS_ACTION_ATTR_RECIRC] = {.type = NL_A_UNSPEC,
 
220
                                .minLen = sizeof(UINT32),
 
221
                                .maxLen = sizeof(UINT32),
 
222
                                .optional = TRUE},
 
223
    [OVS_ACTION_ATTR_HASH] = {.type = NL_A_UNSPEC,
 
224
                              .minLen = sizeof(struct ovs_action_hash),
 
225
                              .maxLen = sizeof(struct ovs_action_hash),
 
226
                              .optional = TRUE},
 
227
    [OVS_ACTION_ATTR_SET] = {.type = NL_A_VAR_LEN, .optional = TRUE},
 
228
    [OVS_ACTION_ATTR_SAMPLE] = {.type = NL_A_VAR_LEN, .optional = TRUE}
 
229
};
 
230
 
 
231
/*
 
232
 *----------------------------------------------------------------------------
 
233
 * Netlink interface for flow commands.
 
234
 *----------------------------------------------------------------------------
 
235
 */
 
236
 
 
237
/*
 
238
 *----------------------------------------------------------------------------
 
239
 *  OvsFlowNewCmdHandler --
 
240
 *    Handler for OVS_FLOW_CMD_NEW/SET/DEL command.
 
241
 *    It also handles FLUSH case (DEL w/o any key in input)
 
242
 *----------------------------------------------------------------------------
 
243
 */
 
244
NTSTATUS
 
245
OvsFlowNlCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
 
246
                    UINT32 *replyLen)
 
247
{
 
248
    NTSTATUS rc = STATUS_SUCCESS;
 
249
    BOOLEAN ok;
 
250
    POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;
 
251
    POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer;
 
252
    PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
 
253
    PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
 
254
    POVS_HDR ovsHdr = &(msgIn->ovsHdr);
 
255
    PNL_ATTR nlAttrs[__OVS_FLOW_ATTR_MAX];
 
256
    UINT32 attrOffset = NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN;
 
257
    OvsFlowPut mappedFlow;
 
258
    OvsFlowStats stats;
 
259
    struct ovs_flow_stats replyStats;
 
260
    NL_ERROR nlError = NL_ERROR_SUCCESS;
 
261
    NL_BUFFER nlBuf;
 
262
 
 
263
    RtlZeroMemory(&mappedFlow, sizeof(OvsFlowPut));
 
264
    RtlZeroMemory(&stats, sizeof(stats));
 
265
    RtlZeroMemory(&replyStats, sizeof(replyStats));
 
266
 
 
267
    if (!(usrParamsCtx->outputBuffer)) {
 
268
        /* No output buffer */
 
269
        rc = STATUS_INVALID_BUFFER_SIZE;
 
270
        goto done;
 
271
    }
 
272
 
 
273
    /* Get all the top level Flow attributes */
 
274
    if ((NlAttrParse(nlMsgHdr, attrOffset, NlMsgAttrsLen(nlMsgHdr),
 
275
                     nlFlowPolicy, nlAttrs, ARRAY_SIZE(nlAttrs)))
 
276
                     != TRUE) {
 
277
        OVS_LOG_ERROR("Attr Parsing failed for msg: %p",
 
278
                       nlMsgHdr);
 
279
        rc = STATUS_INVALID_PARAMETER;
 
280
        goto done;
 
281
    }
 
282
 
 
283
    /* FLOW_DEL command w/o any key input is a flush case. */
 
284
    if ((genlMsgHdr->cmd == OVS_FLOW_CMD_DEL) &&
 
285
        (!(nlAttrs[OVS_FLOW_ATTR_KEY]))) {
 
286
 
 
287
        rc = OvsFlushFlowIoctl(ovsHdr->dp_ifindex);
 
288
 
 
289
       if (rc == STATUS_SUCCESS) {
 
290
            /* XXX: refactor this code. */
 
291
            /* So far so good. Prepare the reply for userspace */
 
292
            NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
 
293
                      usrParamsCtx->outputLength);
 
294
 
 
295
            /* Prepare nl Msg headers */
 
296
            ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,
 
297
                              nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
 
298
                              genlMsgHdr->cmd, OVS_FLOW_VERSION,
 
299
                              ovsHdr->dp_ifindex);
 
300
            if (ok) {
 
301
                *replyLen = msgOut->nlMsg.nlmsgLen;
 
302
            } else {
 
303
                rc = STATUS_INVALID_BUFFER_SIZE;
 
304
            }
 
305
       }
 
306
 
 
307
       goto done;
 
308
    }
 
309
 
 
310
    if ((rc = _MapNlToFlowPut(msgIn, nlAttrs[OVS_FLOW_ATTR_KEY],
 
311
         nlAttrs[OVS_FLOW_ATTR_ACTIONS], nlAttrs[OVS_FLOW_ATTR_CLEAR],
 
312
         &mappedFlow))
 
313
        != STATUS_SUCCESS) {
 
314
        OVS_LOG_ERROR("Conversion to OvsFlowPut failed");
 
315
        goto done;
 
316
    }
 
317
 
 
318
    rc = OvsPutFlowIoctl(&mappedFlow, sizeof (struct OvsFlowPut),
 
319
                         &stats);
 
320
    if (rc != STATUS_SUCCESS) {
 
321
        OVS_LOG_ERROR("OvsPutFlowIoctl failed.");
 
322
        goto done;
 
323
    }
 
324
 
 
325
    replyStats.n_packets = stats.packetCount;
 
326
    replyStats.n_bytes = stats.byteCount;
 
327
 
 
328
    /* So far so good. Prepare the reply for userspace */
 
329
    NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
 
330
              usrParamsCtx->outputLength);
 
331
 
 
332
    /* Prepare nl Msg headers */
 
333
    ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,
 
334
                      nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
 
335
                      genlMsgHdr->cmd, OVS_FLOW_VERSION,
 
336
                      ovsHdr->dp_ifindex);
 
337
    if (!ok) {
 
338
        rc = STATUS_INVALID_BUFFER_SIZE;
 
339
        goto done;
 
340
    } else {
 
341
        rc = STATUS_SUCCESS;
 
342
    }
 
343
 
 
344
    /* Append OVS_FLOW_ATTR_STATS attribute */
 
345
    if (!NlMsgPutTailUnspec(&nlBuf, OVS_FLOW_ATTR_STATS,
 
346
        (PCHAR)(&replyStats), sizeof(replyStats))) {
 
347
        OVS_LOG_ERROR("Adding OVS_FLOW_ATTR_STATS attribute failed.");
 
348
        rc = STATUS_INVALID_BUFFER_SIZE;
 
349
        goto done;
 
350
    }
 
351
 
 
352
    msgOut->nlMsg.nlmsgLen = NLMSG_ALIGN(NlBufSize(&nlBuf));
 
353
    *replyLen = msgOut->nlMsg.nlmsgLen;
 
354
 
 
355
done:
 
356
 
 
357
    if (nlError != NL_ERROR_SUCCESS) {
 
358
        POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
 
359
                                       usrParamsCtx->outputBuffer;
 
360
        NlBuildErrorMsg(msgIn, msgError, nlError);
 
361
        *replyLen = msgError->nlMsg.nlmsgLen;
 
362
        rc = STATUS_SUCCESS;
 
363
    }
 
364
 
 
365
    return rc;
 
366
}
 
367
 
 
368
/*
 
369
 *----------------------------------------------------------------------------
 
370
 *  OvsFlowNlGetCmdHandler --
 
371
 *    Handler for OVS_FLOW_CMD_GET/DUMP commands.
 
372
 *----------------------------------------------------------------------------
 
373
 */
 
374
NTSTATUS
 
375
OvsFlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
 
376
                       UINT32 *replyLen)
 
377
{
 
378
    NTSTATUS status = STATUS_SUCCESS;
 
379
    NL_ERROR nlError = NL_ERROR_SUCCESS;
 
380
    POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;
 
381
 
 
382
    if (usrParamsCtx->devOp == OVS_TRANSACTION_DEV_OP) {
 
383
        status = _FlowNlGetCmdHandler(usrParamsCtx, replyLen);
 
384
 
 
385
        /* No trasanctional errors as of now.
 
386
         * If we have something then we need to convert rc to
 
387
         * nlError. */
 
388
        if ((nlError != NL_ERROR_SUCCESS) &&
 
389
            (usrParamsCtx->outputBuffer)) {
 
390
            POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
 
391
                                           usrParamsCtx->outputBuffer;
 
392
            NlBuildErrorMsg(msgIn, msgError, nlError);
 
393
            *replyLen = msgError->nlMsg.nlmsgLen;
 
394
            status = STATUS_SUCCESS;
 
395
            goto done;
 
396
        }
 
397
    } else {
 
398
        status = _FlowNlDumpCmdHandler(usrParamsCtx, replyLen);
 
399
    }
 
400
 
 
401
done:
 
402
    return status;
 
403
}
 
404
 
 
405
/*
 
406
 *----------------------------------------------------------------------------
 
407
 *  _FlowNlGetCmdHandler --
 
408
 *    Handler for OVS_FLOW_CMD_GET command.
 
409
 *----------------------------------------------------------------------------
 
410
 */
 
411
NTSTATUS
 
412
_FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
 
413
                     UINT32 *replyLen)
 
414
{
 
415
    NTSTATUS rc = STATUS_SUCCESS;
 
416
    POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;
 
417
    PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
 
418
    POVS_HDR ovsHdr = &(msgIn->ovsHdr);
 
419
    PNL_MSG_HDR nlMsgOutHdr = NULL;
 
420
    UINT32 attrOffset = NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN;
 
421
    PNL_ATTR nlAttrs[__OVS_FLOW_ATTR_MAX];
 
422
 
 
423
    OvsFlowGetInput getInput;
 
424
    OvsFlowGetOutput getOutput;
 
425
    NL_BUFFER nlBuf;
 
426
    PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX];
 
427
    PNL_ATTR tunnelAttrs[__OVS_TUNNEL_KEY_ATTR_MAX];
 
428
 
 
429
    NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
 
430
              usrParamsCtx->outputLength);
 
431
    RtlZeroMemory(&getInput, sizeof(OvsFlowGetInput));
 
432
    RtlZeroMemory(&getOutput, sizeof(OvsFlowGetOutput));
 
433
    UINT32 keyAttrOffset = 0;
 
434
    UINT32 tunnelKeyAttrOffset = 0;
 
435
    BOOLEAN ok;
 
436
 
 
437
    if (usrParamsCtx->inputLength > usrParamsCtx->outputLength) {
 
438
        /* Should not be the case.
 
439
         * We'll be copying the flow keys back from
 
440
         * input buffer to output buffer. */
 
441
        rc = STATUS_INVALID_PARAMETER;
 
442
        OVS_LOG_ERROR("inputLength: %d GREATER THEN outputLength: %d",
 
443
                      usrParamsCtx->inputLength, usrParamsCtx->outputLength);
 
444
        goto done;
 
445
    }
 
446
 
 
447
    /* Get all the top level Flow attributes */
 
448
    if ((NlAttrParse(nlMsgHdr, attrOffset, NlMsgAttrsLen(nlMsgHdr),
 
449
                     nlFlowPolicy, nlAttrs, ARRAY_SIZE(nlAttrs)))
 
450
                     != TRUE) {
 
451
        OVS_LOG_ERROR("Attr Parsing failed for msg: %p",
 
452
                       nlMsgHdr);
 
453
        rc = STATUS_INVALID_PARAMETER;
 
454
        goto done;
 
455
    }
 
456
 
 
457
    keyAttrOffset = (UINT32)((PCHAR) nlAttrs[OVS_FLOW_ATTR_KEY] -
 
458
                    (PCHAR)nlMsgHdr);
 
459
 
 
460
    /* Get flow keys attributes */
 
461
    if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset,
 
462
                           NlAttrLen(nlAttrs[OVS_FLOW_ATTR_KEY]),
 
463
                           nlFlowKeyPolicy, keyAttrs, ARRAY_SIZE(keyAttrs)))
 
464
                           != TRUE) {
 
465
        OVS_LOG_ERROR("Key Attr Parsing failed for msg: %p",
 
466
                       nlMsgHdr);
 
467
        rc = STATUS_INVALID_PARAMETER;
 
468
        goto done;
 
469
    }
 
470
 
 
471
    if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
 
472
        tunnelKeyAttrOffset = (UINT32)((PCHAR)
 
473
                              (keyAttrs[OVS_KEY_ATTR_TUNNEL])
 
474
                              - (PCHAR)nlMsgHdr);
 
475
 
 
476
        /* Get tunnel keys attributes */
 
477
        if ((NlAttrParseNested(nlMsgHdr, tunnelKeyAttrOffset,
 
478
                               NlAttrLen(keyAttrs[OVS_KEY_ATTR_TUNNEL]),
 
479
                               nlFlowTunnelKeyPolicy,
 
480
                               tunnelAttrs, ARRAY_SIZE(tunnelAttrs)))
 
481
                               != TRUE) {
 
482
            OVS_LOG_ERROR("Tunnel key Attr Parsing failed for msg: %p",
 
483
                           nlMsgHdr);
 
484
            rc = STATUS_INVALID_PARAMETER;
 
485
            goto done;
 
486
        }
 
487
    }
 
488
 
 
489
    _MapKeyAttrToFlowPut(keyAttrs, tunnelAttrs,
 
490
                         &(getInput.key));
 
491
 
 
492
    getInput.dpNo = ovsHdr->dp_ifindex;
 
493
    getInput.getFlags = FLOW_GET_STATS | FLOW_GET_ACTIONS;
 
494
 
 
495
    /* 4th argument is a no op.
 
496
     * We are keeping this argument to be compatible
 
497
     * with our dpif-windows based interface. */
 
498
    rc = OvsGetFlowIoctl(&getInput, &getOutput);
 
499
    if (rc != STATUS_SUCCESS) {
 
500
        OVS_LOG_ERROR("OvsGetFlowIoctl failed.");
 
501
        goto done;
 
502
    }
 
503
 
 
504
    /* Lets prepare the reply. */
 
505
    nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, 0, 0));
 
506
 
 
507
    /* Input already has all the attributes for the flow key.
 
508
     * Lets copy the values back. */
 
509
    ok = NlMsgPutTail(&nlBuf, (PCHAR)(usrParamsCtx->inputBuffer),
 
510
                      usrParamsCtx->inputLength);
 
511
    if (!ok) {
 
512
        OVS_LOG_ERROR("Could not copy the data to the buffer tail");
 
513
        goto done;
 
514
    }
 
515
 
 
516
    rc = _MapFlowStatsToNlStats(&nlBuf, &((getOutput.info).stats));
 
517
    if (rc != STATUS_SUCCESS) {
 
518
        OVS_LOG_ERROR("_OvsFlowMapFlowKeyToNlStats failed.");
 
519
        goto done;
 
520
    }
 
521
 
 
522
    rc = _MapFlowActionToNlAction(&nlBuf, ((getOutput.info).actionsLen),
 
523
                                  getOutput.info.actions);
 
524
    if (rc != STATUS_SUCCESS) {
 
525
        OVS_LOG_ERROR("_MapFlowActionToNlAction failed.");
 
526
        goto done;
 
527
    }
 
528
 
 
529
    NlMsgSetSize(nlMsgOutHdr, NlBufSize(&nlBuf));
 
530
    NlMsgAlignSize(nlMsgOutHdr);
 
531
    *replyLen += NlMsgSize(nlMsgOutHdr);
 
532
 
 
533
done:
 
534
    return rc;
 
535
}
 
536
 
 
537
/*
 
538
 *----------------------------------------------------------------------------
 
539
 *  _FlowNlDumpCmdHandler --
 
540
 *    Handler for OVS_FLOW_CMD_DUMP command.
 
541
 *----------------------------------------------------------------------------
 
542
 */
 
543
NTSTATUS
 
544
_FlowNlDumpCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
 
545
                      UINT32 *replyLen)
 
546
{
 
547
    NTSTATUS rc = STATUS_SUCCESS;
 
548
    UINT32  temp = 0;   /* To keep compiler happy for calling OvsDoDumpFlows */
 
549
 
 
550
    POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)
 
551
                                  (usrParamsCtx->ovsInstance);
 
552
 
 
553
    if (usrParamsCtx->devOp == OVS_WRITE_DEV_OP) {
 
554
        /* Dump Start */
 
555
        OvsSetupDumpStart(usrParamsCtx);
 
556
        goto done;
 
557
    }
 
558
 
 
559
    POVS_MESSAGE msgIn = instance->dumpState.ovsMsg;
 
560
    PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
 
561
    PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
 
562
    POVS_HDR ovsHdr = &(msgIn->ovsHdr);
 
563
    PNL_MSG_HDR nlMsgOutHdr = NULL;
 
564
    UINT32 hdrOffset = 0;
 
565
 
 
566
    /* Get Next */
 
567
    OvsFlowDumpOutput dumpOutput;
 
568
    OvsFlowDumpInput dumpInput;
 
569
    NL_BUFFER nlBuf;
 
570
 
 
571
    NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
 
572
              usrParamsCtx->outputLength);
 
573
 
 
574
    ASSERT(usrParamsCtx->devOp == OVS_READ_DEV_OP);
 
575
    ASSERT(usrParamsCtx->outputLength);
 
576
 
 
577
    RtlZeroMemory(&dumpInput, sizeof(OvsFlowDumpInput));
 
578
    RtlZeroMemory(&dumpOutput, sizeof(OvsFlowDumpOutput));
 
579
 
 
580
    dumpInput.dpNo = ovsHdr->dp_ifindex;
 
581
    dumpInput.getFlags = FLOW_GET_KEY | FLOW_GET_STATS | FLOW_GET_ACTIONS;
 
582
 
 
583
    /* Lets provide as many flows to userspace as possible. */
 
584
    do {
 
585
        dumpInput.position[0] = instance->dumpState.index[0];
 
586
        dumpInput.position[1] = instance->dumpState.index[1];
 
587
 
 
588
        rc = OvsDoDumpFlows(&dumpInput, &dumpOutput, &temp);
 
589
        if (rc != STATUS_SUCCESS) {
 
590
            OVS_LOG_ERROR("OvsDoDumpFlows failed with rc: %d", rc);
 
591
            break;
 
592
        }
 
593
 
 
594
        /* Done with Dump, send NLMSG_DONE */
 
595
        if (!(dumpOutput.n)) {
 
596
            BOOLEAN ok;
 
597
 
 
598
            OVS_LOG_INFO("Dump Done");
 
599
 
 
600
            nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, NlBufSize(&nlBuf), 0));
 
601
            ok = NlFillNlHdr(&nlBuf, NLMSG_DONE, NLM_F_MULTI,
 
602
                             nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid);
 
603
 
 
604
            if (!ok) {
 
605
                rc = STATUS_INVALID_BUFFER_SIZE;
 
606
                OVS_LOG_ERROR("Unable to prepare DUMP_DONE reply.");
 
607
                break;
 
608
            } else {
 
609
                rc = STATUS_SUCCESS;
 
610
            }
 
611
 
 
612
            NlMsgAlignSize(nlMsgOutHdr);
 
613
            *replyLen += NlMsgSize(nlMsgOutHdr);
 
614
 
 
615
            FreeUserDumpState(instance);
 
616
            break;
 
617
        } else {
 
618
            BOOLEAN ok;
 
619
 
 
620
            hdrOffset = NlBufSize(&nlBuf);
 
621
            nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, hdrOffset, 0));
 
622
 
 
623
            /* Netlink header */
 
624
            ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, NLM_F_MULTI,
 
625
                              nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
 
626
                              genlMsgHdr->cmd, genlMsgHdr->version,
 
627
                              ovsHdr->dp_ifindex);
 
628
 
 
629
            if (!ok) {
 
630
                /* Reset rc to success so that we can
 
631
                 * send already added messages to user space. */
 
632
                rc = STATUS_SUCCESS;
 
633
                break;
 
634
            }
 
635
 
 
636
            /* Time to add attributes */
 
637
            rc = _MapFlowInfoToNl(&nlBuf, &(dumpOutput.flow));
 
638
            if (rc != STATUS_SUCCESS) {
 
639
                /* Adding the attribute failed, we are out of
 
640
                   space in the buffer, remove the appended OVS header */
 
641
                NlMsgSetSize(nlMsgOutHdr,
 
642
                             NlMsgSize(nlMsgOutHdr) -
 
643
                             sizeof(struct _OVS_MESSAGE));
 
644
 
 
645
                /* Reset rc to success so that we can
 
646
                 * send already added messages to user space. */
 
647
                rc = STATUS_SUCCESS;
 
648
                break;
 
649
            }
 
650
 
 
651
            NlMsgSetSize(nlMsgOutHdr, NlBufSize(&nlBuf) - hdrOffset);
 
652
            NlMsgAlignSize(nlMsgOutHdr);
 
653
            *replyLen += NlMsgSize(nlMsgOutHdr);
 
654
            instance->dumpState.index[0] = dumpOutput.position[0];
 
655
            instance->dumpState.index[1] = dumpOutput.position[1];
 
656
        }
 
657
    } while(TRUE);
 
658
 
 
659
done:
 
660
    return rc;
 
661
}
 
662
 
 
663
/*
 
664
 *----------------------------------------------------------------------------
 
665
 *  _MapFlowInfoToNl --
 
666
 *    Maps OvsFlowInfo to Netlink attributes.
 
667
 *----------------------------------------------------------------------------
 
668
 */
 
669
static NTSTATUS
 
670
_MapFlowInfoToNl(PNL_BUFFER nlBuf, OvsFlowInfo *flowInfo)
 
671
{
 
672
    NTSTATUS rc = STATUS_SUCCESS;
 
673
 
 
674
    rc = MapFlowKeyToNlKey(nlBuf, &(flowInfo->key), OVS_FLOW_ATTR_KEY,
 
675
                           OVS_KEY_ATTR_TUNNEL);
 
676
    if (rc != STATUS_SUCCESS) {
 
677
        goto done;
 
678
    }
 
679
 
 
680
    rc = _MapFlowStatsToNlStats(nlBuf, &(flowInfo->stats));
 
681
    if (rc != STATUS_SUCCESS) {
 
682
        goto done;
 
683
    }
 
684
 
 
685
    rc = _MapFlowActionToNlAction(nlBuf, flowInfo->actionsLen,
 
686
                                  flowInfo->actions);
 
687
    if (rc != STATUS_SUCCESS) {
 
688
        goto done;
 
689
    }
 
690
 
 
691
done:
 
692
    return rc;
 
693
}
 
694
 
 
695
/*
 
696
 *----------------------------------------------------------------------------
 
697
 *  _MapFlowStatsToNlStats --
 
698
 *    Maps OvsFlowStats to OVS_FLOW_ATTR_STATS attribute.
 
699
 *----------------------------------------------------------------------------
 
700
 */
 
701
static NTSTATUS
 
702
_MapFlowStatsToNlStats(PNL_BUFFER nlBuf, OvsFlowStats *flowStats)
 
703
{
 
704
    NTSTATUS rc = STATUS_SUCCESS;
 
705
    struct ovs_flow_stats replyStats;
 
706
 
 
707
    replyStats.n_packets = flowStats->packetCount;
 
708
    replyStats.n_bytes = flowStats->byteCount;
 
709
 
 
710
    if (!NlMsgPutTailU64(nlBuf, OVS_FLOW_ATTR_USED, flowStats->used)) {
 
711
        rc = STATUS_INVALID_BUFFER_SIZE;
 
712
        goto done;
 
713
    }
 
714
 
 
715
    if (!NlMsgPutTailUnspec(nlBuf, OVS_FLOW_ATTR_STATS,
 
716
                           (PCHAR)(&replyStats),
 
717
                           sizeof(struct ovs_flow_stats))) {
 
718
        rc = STATUS_INVALID_BUFFER_SIZE;
 
719
        goto done;
 
720
    }
 
721
 
 
722
    if (!NlMsgPutTailU8(nlBuf, OVS_FLOW_ATTR_TCP_FLAGS, flowStats->tcpFlags)) {
 
723
        rc = STATUS_INVALID_BUFFER_SIZE;
 
724
        goto done;
 
725
    }
 
726
 
 
727
done:
 
728
    return rc;
 
729
}
 
730
 
 
731
/*
 
732
 *----------------------------------------------------------------------------
 
733
 *  _MapFlowActionToNlAction --
 
734
 *    Maps flow actions to OVS_FLOW_ATTR_ACTION attribute.
 
735
 *----------------------------------------------------------------------------
 
736
 */
 
737
static NTSTATUS
 
738
_MapFlowActionToNlAction(PNL_BUFFER nlBuf, uint32_t actionsLen,
 
739
                         PNL_ATTR actions)
 
740
{
 
741
    NTSTATUS rc = STATUS_SUCCESS;
 
742
    UINT32 offset = 0;
 
743
 
 
744
    offset = NlMsgStartNested(nlBuf, OVS_FLOW_ATTR_ACTIONS);
 
745
    if (!offset) {
 
746
        /* Starting the nested attribute failed. */
 
747
        rc = STATUS_INVALID_BUFFER_SIZE;
 
748
        goto error_nested_start;
 
749
    }
 
750
 
 
751
    if (!NlBufCopyAtTail(nlBuf, (PCHAR)actions, actionsLen)) {
 
752
        /* Adding a nested attribute failed. */
 
753
        rc = STATUS_INVALID_BUFFER_SIZE;
 
754
        goto done;
 
755
    }
 
756
 
 
757
done:
 
758
    NlMsgEndNested(nlBuf, offset);
 
759
error_nested_start:
 
760
    return rc;
 
761
 
 
762
}
 
763
 
 
764
/*
 
765
 *----------------------------------------------------------------------------
 
766
 *  MapFlowKeyToNlKey --
 
767
 *   Maps OvsFlowKey to OVS_FLOW_ATTR_KEY attribute.
 
768
 *----------------------------------------------------------------------------
 
769
 */
 
770
NTSTATUS
 
771
MapFlowKeyToNlKey(PNL_BUFFER nlBuf,
 
772
                  OvsFlowKey *flowKey,
 
773
                  UINT16 keyType,
 
774
                  UINT16 tunKeyType)
 
775
{
 
776
    NTSTATUS rc = STATUS_SUCCESS;
 
777
    struct ovs_key_ethernet ethKey;
 
778
    UINT32 offset = 0;
 
779
 
 
780
    offset = NlMsgStartNested(nlBuf, keyType);
 
781
    if (!offset) {
 
782
        /* Starting the nested attribute failed. */
 
783
        rc = STATUS_UNSUCCESSFUL;
 
784
        goto error_nested_start;
 
785
    }
 
786
 
 
787
    /* Ethernet header */
 
788
    RtlCopyMemory(&(ethKey.eth_src), flowKey->l2.dlSrc, ETH_ADDR_LEN);
 
789
    RtlCopyMemory(&(ethKey.eth_dst), flowKey->l2.dlDst, ETH_ADDR_LEN);
 
790
 
 
791
    if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ETHERNET,
 
792
                           (PCHAR)(&ethKey),
 
793
                           sizeof(struct ovs_key_ethernet))) {
 
794
        rc = STATUS_UNSUCCESSFUL;
 
795
        goto done;
 
796
    }
 
797
 
 
798
    if (!NlMsgPutTailU32(nlBuf, OVS_KEY_ATTR_IN_PORT,
 
799
                         flowKey->l2.inPort)) {
 
800
        rc = STATUS_UNSUCCESSFUL;
 
801
        goto done;
 
802
    }
 
803
 
 
804
    if (!NlMsgPutTailU16(nlBuf, OVS_KEY_ATTR_ETHERTYPE,
 
805
                         flowKey->l2.dlType)) {
 
806
        rc = STATUS_UNSUCCESSFUL;
 
807
        goto done;
 
808
    }
 
809
 
 
810
    if (flowKey->l2.vlanTci) {
 
811
        if (!NlMsgPutTailU16(nlBuf, OVS_KEY_ATTR_VLAN,
 
812
                             flowKey->l2.vlanTci)) {
 
813
            rc = STATUS_UNSUCCESSFUL;
 
814
            goto done;
 
815
        }
 
816
    }
 
817
 
 
818
    /* ==== L3 + L4 ==== */
 
819
    switch (ntohs(flowKey->l2.dlType)) {
 
820
        case ETH_TYPE_IPV4: {
 
821
        IpKey *ipv4FlowPutKey = &(flowKey->ipKey);
 
822
        rc = _MapFlowIpv4KeyToNlKey(nlBuf, ipv4FlowPutKey);
 
823
        break;
 
824
        }
 
825
 
 
826
        case ETH_TYPE_IPV6: {
 
827
        Ipv6Key *ipv6FlowPutKey = &(flowKey->ipv6Key);
 
828
        Icmp6Key *icmpv6FlowPutKey = &(flowKey->icmp6Key);
 
829
        rc = _MapFlowIpv6KeyToNlKey(nlBuf, ipv6FlowPutKey,
 
830
                                    icmpv6FlowPutKey);
 
831
        break;
 
832
        }
 
833
 
 
834
        case ETH_TYPE_ARP:
 
835
        case ETH_TYPE_RARP: {
 
836
        ArpKey *arpFlowPutKey = &(flowKey->arpKey);
 
837
        rc = _MapFlowArpKeyToNlKey(nlBuf, arpFlowPutKey);
 
838
        break;
 
839
        }
 
840
 
 
841
        default:
 
842
        break;
 
843
    }
 
844
 
 
845
    if (rc != STATUS_SUCCESS) {
 
846
        goto done;
 
847
    }
 
848
 
 
849
    if (flowKey->tunKey.dst) {
 
850
        rc = MapFlowTunKeyToNlKey(nlBuf, &(flowKey->tunKey),
 
851
                                  tunKeyType);
 
852
        if (rc != STATUS_SUCCESS) {
 
853
            goto done;
 
854
        }
 
855
    }
 
856
 
 
857
done:
 
858
    NlMsgEndNested(nlBuf, offset);
 
859
error_nested_start:
 
860
    return rc;
 
861
}
 
862
 
 
863
/*
 
864
 *----------------------------------------------------------------------------
 
865
 *  MapFlowTunKeyToNlKey --
 
866
 *   Maps OvsIPv4TunnelKey to OVS_TUNNEL_KEY_ATTR_ID attribute.
 
867
 *----------------------------------------------------------------------------
 
868
 */
 
869
NTSTATUS
 
870
MapFlowTunKeyToNlKey(PNL_BUFFER nlBuf,
 
871
                     OvsIPv4TunnelKey *tunKey,
 
872
                     UINT16 tunKeyType)
 
873
{
 
874
    NTSTATUS rc = STATUS_SUCCESS;
 
875
    UINT32 offset = 0;
 
876
 
 
877
    offset = NlMsgStartNested(nlBuf, tunKeyType);
 
878
    if (!offset) {
 
879
        /* Starting the nested attribute failed. */
 
880
        rc = STATUS_UNSUCCESSFUL;
 
881
        goto error_nested_start;
 
882
    }
 
883
 
 
884
    if (!NlMsgPutTailU64(nlBuf, OVS_TUNNEL_KEY_ATTR_ID,
 
885
                         tunKey->tunnelId)) {
 
886
        rc = STATUS_UNSUCCESSFUL;
 
887
        goto done;
 
888
    }
 
889
 
 
890
    if (!NlMsgPutTailU32(nlBuf, OVS_TUNNEL_KEY_ATTR_IPV4_DST,
 
891
                         tunKey->dst)) {
 
892
        rc = STATUS_UNSUCCESSFUL;
 
893
        goto done;
 
894
    }
 
895
 
 
896
    if (!NlMsgPutTailU32(nlBuf, OVS_TUNNEL_KEY_ATTR_IPV4_SRC,
 
897
                         tunKey->src)) {
 
898
        rc = STATUS_UNSUCCESSFUL;
 
899
        goto done;
 
900
    }
 
901
 
 
902
    if (!NlMsgPutTailU8(nlBuf, OVS_TUNNEL_KEY_ATTR_TOS,
 
903
                        tunKey->tos)) {
 
904
        rc = STATUS_UNSUCCESSFUL;
 
905
        goto done;
 
906
    }
 
907
 
 
908
    if (!NlMsgPutTailU8(nlBuf, OVS_TUNNEL_KEY_ATTR_TTL,
 
909
                         tunKey->ttl)) {
 
910
        rc = STATUS_UNSUCCESSFUL;
 
911
        goto done;
 
912
    }
 
913
 
 
914
done:
 
915
    NlMsgEndNested(nlBuf, offset);
 
916
error_nested_start:
 
917
    return rc;
 
918
}
 
919
 
 
920
/*
 
921
 *----------------------------------------------------------------------------
 
922
 *  _MapFlowTunKeyToNlKey --
 
923
 *    Maps OvsIPv4FlowPutKey to OVS_KEY_ATTR_IPV4 attribute.
 
924
 *----------------------------------------------------------------------------
 
925
 */
 
926
static NTSTATUS
 
927
_MapFlowIpv4KeyToNlKey(PNL_BUFFER nlBuf, IpKey *ipv4FlowPutKey)
 
928
{
 
929
    NTSTATUS rc = STATUS_SUCCESS;
 
930
    struct ovs_key_ipv4 ipv4Key;
 
931
 
 
932
    ipv4Key.ipv4_src = ipv4FlowPutKey->nwSrc;
 
933
    ipv4Key.ipv4_dst = ipv4FlowPutKey->nwDst;
 
934
    ipv4Key.ipv4_proto = ipv4FlowPutKey->nwProto;
 
935
    ipv4Key.ipv4_tos = ipv4FlowPutKey->nwTos;
 
936
    ipv4Key.ipv4_ttl = ipv4FlowPutKey->nwTtl;
 
937
    ipv4Key.ipv4_frag = ipv4FlowPutKey->nwFrag;
 
938
 
 
939
    if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_IPV4,
 
940
                           (PCHAR)(&ipv4Key),
 
941
                           sizeof(struct ovs_key_ipv4))) {
 
942
        rc = STATUS_UNSUCCESSFUL;
 
943
        goto done;
 
944
    }
 
945
 
 
946
    switch (ipv4Key.ipv4_proto) {
 
947
        case IPPROTO_TCP: {
 
948
            struct ovs_key_tcp tcpKey;
 
949
            tcpKey.tcp_src = ipv4FlowPutKey->l4.tpSrc;
 
950
            tcpKey.tcp_dst = ipv4FlowPutKey->l4.tpDst;
 
951
            if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_TCP,
 
952
                                   (PCHAR)(&tcpKey),
 
953
                                   sizeof(tcpKey))) {
 
954
                rc = STATUS_UNSUCCESSFUL;
 
955
                goto done;
 
956
            }
 
957
            break;
 
958
        }
 
959
 
 
960
        case IPPROTO_UDP: {
 
961
            struct ovs_key_udp udpKey;
 
962
            udpKey.udp_src = ipv4FlowPutKey->l4.tpSrc;
 
963
            udpKey.udp_dst = ipv4FlowPutKey->l4.tpDst;
 
964
            if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_UDP,
 
965
                                   (PCHAR)(&udpKey),
 
966
                                   sizeof(udpKey))) {
 
967
                rc = STATUS_UNSUCCESSFUL;
 
968
                goto done;
 
969
            }
 
970
            break;
 
971
        }
 
972
 
 
973
        case IPPROTO_SCTP: {
 
974
            struct ovs_key_sctp sctpKey;
 
975
            sctpKey.sctp_src = ipv4FlowPutKey->l4.tpSrc;
 
976
            sctpKey.sctp_dst = ipv4FlowPutKey->l4.tpDst;
 
977
            if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_SCTP,
 
978
                                   (PCHAR)(&sctpKey),
 
979
                                   sizeof(sctpKey))) {
 
980
                rc = STATUS_UNSUCCESSFUL;
 
981
                goto done;
 
982
            }
 
983
            break;
 
984
        }
 
985
 
 
986
        case IPPROTO_ICMP: {
 
987
            struct ovs_key_icmp icmpKey;
 
988
            /* XXX: revisit to see if htons is needed */
 
989
            icmpKey.icmp_type = (__u8)(ipv4FlowPutKey->l4.tpSrc);
 
990
            icmpKey.icmp_code = (__u8)(ipv4FlowPutKey->l4.tpDst);
 
991
 
 
992
            if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ICMP,
 
993
                                   (PCHAR)(&icmpKey),
 
994
                                   sizeof(icmpKey))) {
 
995
                rc = STATUS_UNSUCCESSFUL;
 
996
                goto done;
 
997
            }
 
998
            break;
 
999
        }
 
1000
 
 
1001
        default:
 
1002
            break;
 
1003
    }
 
1004
 
 
1005
done:
 
1006
    return rc;
 
1007
}
 
1008
 
 
1009
/*
 
1010
 *----------------------------------------------------------------------------
 
1011
 *  _MapFlowIpv6KeyToNlKey --
 
1012
 *    Maps _MapFlowIpv6KeyToNlKey to OVS_KEY_ATTR_IPV6 attribute.
 
1013
 *----------------------------------------------------------------------------
 
1014
 */
 
1015
static NTSTATUS
 
1016
_MapFlowIpv6KeyToNlKey(PNL_BUFFER nlBuf, Ipv6Key *ipv6FlowPutKey,
 
1017
                       Icmp6Key *icmpv6FlowPutKey)
 
1018
{
 
1019
    NTSTATUS rc = STATUS_SUCCESS;
 
1020
    struct ovs_key_ipv6 ipv6Key;
 
1021
 
 
1022
    RtlCopyMemory(&(ipv6Key.ipv6_src), &ipv6FlowPutKey->ipv6Src,
 
1023
                  sizeof ipv6Key.ipv6_src);
 
1024
    RtlCopyMemory(&(ipv6Key.ipv6_dst), &ipv6FlowPutKey->ipv6Dst,
 
1025
                  sizeof ipv6Key.ipv6_dst);
 
1026
 
 
1027
    ipv6Key.ipv6_label = ipv6FlowPutKey->ipv6Label;
 
1028
    ipv6Key.ipv6_proto = ipv6FlowPutKey->nwProto;
 
1029
    ipv6Key.ipv6_tclass = ipv6FlowPutKey->nwTos;
 
1030
    ipv6Key.ipv6_hlimit = ipv6FlowPutKey->nwTtl;
 
1031
    ipv6Key.ipv6_frag = ipv6FlowPutKey->nwFrag;
 
1032
 
 
1033
    if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_IPV6,
 
1034
                           (PCHAR)(&ipv6Key),
 
1035
                           sizeof(ipv6Key))) {
 
1036
        rc = STATUS_UNSUCCESSFUL;
 
1037
        goto done;
 
1038
    }
 
1039
 
 
1040
    switch (ipv6Key.ipv6_proto) {
 
1041
        case IPPROTO_TCP: {
 
1042
            struct ovs_key_tcp tcpKey;
 
1043
            tcpKey.tcp_src = ipv6FlowPutKey->l4.tpSrc;
 
1044
            tcpKey.tcp_dst = ipv6FlowPutKey->l4.tpDst;
 
1045
            if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_TCP,
 
1046
                                   (PCHAR)(&tcpKey),
 
1047
                                   sizeof(tcpKey))) {
 
1048
                rc = STATUS_UNSUCCESSFUL;
 
1049
                goto done;
 
1050
            }
 
1051
            break;
 
1052
        }
 
1053
 
 
1054
        case IPPROTO_UDP: {
 
1055
            struct ovs_key_udp udpKey;
 
1056
            udpKey.udp_src = ipv6FlowPutKey->l4.tpSrc;
 
1057
            udpKey.udp_dst = ipv6FlowPutKey->l4.tpDst;
 
1058
            if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_UDP,
 
1059
                                   (PCHAR)(&udpKey),
 
1060
                                   sizeof(udpKey))) {
 
1061
                rc = STATUS_UNSUCCESSFUL;
 
1062
                goto done;
 
1063
            }
 
1064
            break;
 
1065
        }
 
1066
 
 
1067
        case IPPROTO_SCTP: {
 
1068
            struct ovs_key_sctp sctpKey;
 
1069
            sctpKey.sctp_src = ipv6FlowPutKey->l4.tpSrc;
 
1070
            sctpKey.sctp_dst = ipv6FlowPutKey->l4.tpDst;
 
1071
            if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_SCTP,
 
1072
                                   (PCHAR)(&sctpKey),
 
1073
                                   sizeof(sctpKey))) {
 
1074
                rc = STATUS_UNSUCCESSFUL;
 
1075
                goto done;
 
1076
            }
 
1077
            break;
 
1078
        }
 
1079
 
 
1080
        case IPPROTO_ICMPV6: {
 
1081
            struct ovs_key_icmpv6 icmpV6Key;
 
1082
            struct ovs_key_nd ndKey;
 
1083
 
 
1084
            /* XXX: revisit to see if htons is needed */
 
1085
            icmpV6Key.icmpv6_type = (__u8)(icmpv6FlowPutKey->l4.tpSrc);
 
1086
            icmpV6Key.icmpv6_code = (__u8)(icmpv6FlowPutKey->l4.tpDst);
 
1087
 
 
1088
            if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ICMPV6,
 
1089
                                   (PCHAR)(&icmpV6Key),
 
1090
                                   sizeof(icmpV6Key))) {
 
1091
                rc = STATUS_UNSUCCESSFUL;
 
1092
                goto done;
 
1093
            }
 
1094
 
 
1095
            RtlCopyMemory(&(ndKey.nd_target), &icmpv6FlowPutKey->ndTarget,
 
1096
                          sizeof(icmpv6FlowPutKey->ndTarget));
 
1097
            RtlCopyMemory(&(ndKey.nd_sll), &icmpv6FlowPutKey->arpSha,
 
1098
                          ETH_ADDR_LEN);
 
1099
            RtlCopyMemory(&(ndKey.nd_tll), &icmpv6FlowPutKey->arpTha,
 
1100
                          ETH_ADDR_LEN);
 
1101
            if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ND,
 
1102
                                   (PCHAR)(&ndKey),
 
1103
                                   sizeof(ndKey))) {
 
1104
                rc = STATUS_UNSUCCESSFUL;
 
1105
                goto done;
 
1106
            }
 
1107
 
 
1108
            break;
 
1109
        }
 
1110
 
 
1111
        default:
 
1112
            break;
 
1113
    }
 
1114
 
 
1115
done:
 
1116
    return rc;
 
1117
}
 
1118
 
 
1119
/*
 
1120
 *----------------------------------------------------------------------------
 
1121
 *  _MapFlowArpKeyToNlKey --
 
1122
 *    Maps _MapFlowArpKeyToNlKey to OVS_KEY_ATTR_ARP attribute.
 
1123
 *----------------------------------------------------------------------------
 
1124
 */
 
1125
static NTSTATUS
 
1126
_MapFlowArpKeyToNlKey(PNL_BUFFER nlBuf, ArpKey *arpFlowPutKey)
 
1127
{
 
1128
    NTSTATUS rc = STATUS_SUCCESS;
 
1129
    struct ovs_key_arp arpKey;
 
1130
 
 
1131
    arpKey.arp_sip = arpFlowPutKey->nwSrc;
 
1132
    arpKey.arp_tip = arpFlowPutKey->nwDst;
 
1133
 
 
1134
    RtlCopyMemory(&(arpKey.arp_sha), arpFlowPutKey->arpSha, ETH_ADDR_LEN);
 
1135
    RtlCopyMemory(&(arpKey.arp_tha), arpFlowPutKey->arpTha, ETH_ADDR_LEN);
 
1136
 
 
1137
    /*
 
1138
     * Flow_Extract() stores 'nwProto' in host order for ARP since 'nwProto' is
 
1139
     * 1 byte field and the ARP opcode is 2 bytes, and all of the kernel code
 
1140
     * understand this while looking at an ARP key.
 
1141
     * While we pass up the ARP key to userspace, convert from host order to
 
1142
     * network order. Likewise, when processing an ARP key from userspace,
 
1143
     * convert from network order to host order.
 
1144
     *
 
1145
     * It is important to note that the flow table stores the ARP opcode field
 
1146
     * in host order.
 
1147
     */
 
1148
    arpKey.arp_op = htons(arpFlowPutKey->nwProto);
 
1149
 
 
1150
    if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ARP,
 
1151
                           (PCHAR)(&arpKey),
 
1152
                           sizeof(arpKey))) {
 
1153
        rc = STATUS_UNSUCCESSFUL;
 
1154
        goto done;
 
1155
    }
 
1156
 
 
1157
done:
 
1158
    return rc;
 
1159
}
 
1160
 
 
1161
/*
 
1162
 *----------------------------------------------------------------------------
 
1163
 *  _MapNlToFlowPut --
 
1164
 *    Maps input netlink message to OvsFlowPut.
 
1165
 *----------------------------------------------------------------------------
 
1166
 */
 
1167
static NTSTATUS
 
1168
_MapNlToFlowPut(POVS_MESSAGE msgIn, PNL_ATTR keyAttr,
 
1169
                PNL_ATTR actionAttr, PNL_ATTR flowAttrClear,
 
1170
                OvsFlowPut *mappedFlow)
 
1171
{
 
1172
    NTSTATUS rc = STATUS_SUCCESS;
 
1173
    PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
 
1174
    PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
 
1175
    POVS_HDR ovsHdr = &(msgIn->ovsHdr);
 
1176
 
 
1177
    UINT32 keyAttrOffset = (UINT32)((PCHAR)keyAttr - (PCHAR)nlMsgHdr);
 
1178
    UINT32 tunnelKeyAttrOffset;
 
1179
 
 
1180
    PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX] = {NULL};
 
1181
    PNL_ATTR tunnelAttrs[__OVS_TUNNEL_KEY_ATTR_MAX] = {NULL};
 
1182
 
 
1183
    /* Get flow keys attributes */
 
1184
    if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset, NlAttrLen(keyAttr),
 
1185
                           nlFlowKeyPolicy, keyAttrs, ARRAY_SIZE(keyAttrs)))
 
1186
                           != TRUE) {
 
1187
        OVS_LOG_ERROR("Key Attr Parsing failed for msg: %p",
 
1188
                       nlMsgHdr);
 
1189
        rc = STATUS_INVALID_PARAMETER;
 
1190
        goto done;
 
1191
    }
 
1192
 
 
1193
    if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
 
1194
        tunnelKeyAttrOffset = (UINT32)((PCHAR)
 
1195
                              (keyAttrs[OVS_KEY_ATTR_TUNNEL])
 
1196
                              - (PCHAR)nlMsgHdr);
 
1197
 
 
1198
        /* Get tunnel keys attributes */
 
1199
        if ((NlAttrParseNested(nlMsgHdr, tunnelKeyAttrOffset,
 
1200
                               NlAttrLen(keyAttrs[OVS_KEY_ATTR_TUNNEL]),
 
1201
                               nlFlowTunnelKeyPolicy,
 
1202
                               tunnelAttrs, ARRAY_SIZE(tunnelAttrs)))
 
1203
                               != TRUE) {
 
1204
            OVS_LOG_ERROR("Tunnel key Attr Parsing failed for msg: %p",
 
1205
                           nlMsgHdr);
 
1206
            rc = STATUS_INVALID_PARAMETER;
 
1207
            goto done;
 
1208
        }
 
1209
    }
 
1210
 
 
1211
    _MapKeyAttrToFlowPut(keyAttrs, tunnelAttrs,
 
1212
                         &(mappedFlow->key));
 
1213
 
 
1214
    /* Map the action */
 
1215
    if (actionAttr) {
 
1216
        mappedFlow->actionsLen = NlAttrGetSize(actionAttr);
 
1217
        mappedFlow->actions = NlAttrGet(actionAttr);
 
1218
    }
 
1219
 
 
1220
    mappedFlow->dpNo = ovsHdr->dp_ifindex;
 
1221
 
 
1222
    _MapNlToFlowPutFlags(genlMsgHdr, flowAttrClear,
 
1223
                                mappedFlow);
 
1224
 
 
1225
done:
 
1226
    return rc;
 
1227
}
 
1228
 
 
1229
/*
 
1230
 *----------------------------------------------------------------------------
 
1231
 *  _MapNlToFlowPutFlags --
 
1232
 *    Maps netlink message to OvsFlowPut->flags.
 
1233
 *----------------------------------------------------------------------------
 
1234
 */
 
1235
static VOID
 
1236
_MapNlToFlowPutFlags(PGENL_MSG_HDR genlMsgHdr,
 
1237
                     PNL_ATTR flowAttrClear, OvsFlowPut *mappedFlow)
 
1238
{
 
1239
    uint32_t flags = 0;
 
1240
 
 
1241
    switch (genlMsgHdr->cmd) {
 
1242
    case OVS_FLOW_CMD_NEW:
 
1243
         flags |= OVSWIN_FLOW_PUT_CREATE;
 
1244
         break;
 
1245
    case OVS_FLOW_CMD_DEL:
 
1246
         flags |= OVSWIN_FLOW_PUT_DELETE;
 
1247
         break;
 
1248
    case OVS_FLOW_CMD_SET:
 
1249
         flags |= OVSWIN_FLOW_PUT_MODIFY;
 
1250
         break;
 
1251
    default:
 
1252
         ASSERT(0);
 
1253
    }
 
1254
 
 
1255
    if (flowAttrClear) {
 
1256
        flags |= OVSWIN_FLOW_PUT_CLEAR;
 
1257
    }
 
1258
 
 
1259
    mappedFlow->flags = flags;
 
1260
}
 
1261
 
 
1262
/*
 
1263
 *----------------------------------------------------------------------------
 
1264
 *  _MapKeyAttrToFlowPut --
 
1265
 *    Converts FLOW_KEY attribute to OvsFlowPut->key.
 
1266
 *----------------------------------------------------------------------------
 
1267
 */
 
1268
static VOID
 
1269
_MapKeyAttrToFlowPut(PNL_ATTR *keyAttrs,
 
1270
                     PNL_ATTR *tunnelAttrs,
 
1271
                     OvsFlowKey *destKey)
 
1272
{
 
1273
    _MapTunAttrToFlowPut(keyAttrs, tunnelAttrs, destKey);
 
1274
 
 
1275
    /* ===== L2 headers ===== */
 
1276
    destKey->l2.inPort = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_IN_PORT]);
 
1277
 
 
1278
    if (keyAttrs[OVS_KEY_ATTR_ETHERNET]) {
 
1279
        const struct ovs_key_ethernet *eth_key;
 
1280
        eth_key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ETHERNET]);
 
1281
        RtlCopyMemory(destKey->l2.dlSrc, eth_key->eth_src, ETH_ADDR_LEN);
 
1282
        RtlCopyMemory(destKey->l2.dlDst, eth_key->eth_dst, ETH_ADDR_LEN);
 
1283
    }
 
1284
 
 
1285
    /* TODO: Ideally ETHERTYPE should not be optional.
 
1286
     * But during vswitchd bootup we are seeing FLOW_ADD
 
1287
     * requests with no ETHERTYPE attributes.
 
1288
     * Need to verify this. */
 
1289
    if (keyAttrs[OVS_KEY_ATTR_ETHERTYPE]) {
 
1290
        destKey->l2.dlType = (NlAttrGetU16(keyAttrs
 
1291
                                        [OVS_KEY_ATTR_ETHERTYPE]));
 
1292
    }
 
1293
 
 
1294
    if (keyAttrs[OVS_KEY_ATTR_VLAN]) {
 
1295
        destKey->l2.vlanTci = NlAttrGetU16(keyAttrs[OVS_KEY_ATTR_VLAN]);
 
1296
    }
 
1297
 
 
1298
    /* ==== L3 + L4. ==== */
 
1299
    destKey->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + OVS_L2_KEY_SIZE
 
1300
                         - destKey->l2.offset;
 
1301
 
 
1302
    switch (ntohs(destKey->l2.dlType)) {
 
1303
    case ETH_TYPE_IPV4: {
 
1304
 
 
1305
        if (keyAttrs[OVS_KEY_ATTR_IPV4]) {
 
1306
            const struct ovs_key_ipv4 *ipv4Key;
 
1307
 
 
1308
            ipv4Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_IPV4]);
 
1309
            IpKey *ipv4FlowPutKey = &(destKey->ipKey);
 
1310
            ipv4FlowPutKey->nwSrc = ipv4Key->ipv4_src;
 
1311
            ipv4FlowPutKey->nwDst = ipv4Key->ipv4_dst;
 
1312
            ipv4FlowPutKey->nwProto = ipv4Key->ipv4_proto;
 
1313
            ipv4FlowPutKey->nwTos = ipv4Key->ipv4_tos;
 
1314
            ipv4FlowPutKey->nwTtl = ipv4Key->ipv4_ttl;
 
1315
            ipv4FlowPutKey->nwFrag = ipv4Key->ipv4_frag;
 
1316
 
 
1317
            if (keyAttrs[OVS_KEY_ATTR_TCP]) {
 
1318
                const struct ovs_key_tcp *tcpKey;
 
1319
                tcpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_TCP]);
 
1320
                ipv4FlowPutKey->l4.tpSrc = tcpKey->tcp_src;
 
1321
                ipv4FlowPutKey->l4.tpDst = tcpKey->tcp_dst;
 
1322
            }
 
1323
 
 
1324
            if (keyAttrs[OVS_KEY_ATTR_UDP]) {
 
1325
                const struct ovs_key_udp *udpKey;
 
1326
                udpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_UDP]);
 
1327
                ipv4FlowPutKey->l4.tpSrc = udpKey->udp_src;
 
1328
                ipv4FlowPutKey->l4.tpDst = udpKey->udp_dst;
 
1329
            }
 
1330
 
 
1331
            if (keyAttrs[OVS_KEY_ATTR_SCTP]) {
 
1332
                const struct ovs_key_sctp *sctpKey;
 
1333
                sctpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_SCTP]);
 
1334
                ipv4FlowPutKey->l4.tpSrc = sctpKey->sctp_src;
 
1335
                ipv4FlowPutKey->l4.tpDst = sctpKey->sctp_dst;
 
1336
            }
 
1337
 
 
1338
            destKey->l2.keyLen += OVS_IP_KEY_SIZE;
 
1339
        }
 
1340
        break;
 
1341
    }
 
1342
    case ETH_TYPE_IPV6: {
 
1343
 
 
1344
        if (keyAttrs[OVS_KEY_ATTR_IPV6]) {
 
1345
            const struct ovs_key_ipv6 *ipv6Key;
 
1346
 
 
1347
            ipv6Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_IPV6]);
 
1348
            Ipv6Key *ipv6FlowPutKey = &(destKey->ipv6Key);
 
1349
 
 
1350
            RtlCopyMemory(&ipv6FlowPutKey->ipv6Src, ipv6Key->ipv6_src,
 
1351
                          sizeof ipv6Key->ipv6_src);
 
1352
            RtlCopyMemory(&ipv6FlowPutKey->ipv6Dst, ipv6Key->ipv6_dst,
 
1353
                          sizeof ipv6Key->ipv6_dst);
 
1354
 
 
1355
            ipv6FlowPutKey->ipv6Label = ipv6Key->ipv6_label;
 
1356
            ipv6FlowPutKey->nwProto  = ipv6Key->ipv6_proto;
 
1357
            ipv6FlowPutKey->nwTos = ipv6Key->ipv6_tclass;
 
1358
            ipv6FlowPutKey->nwTtl = ipv6Key->ipv6_hlimit;
 
1359
            ipv6FlowPutKey->nwFrag = ipv6Key->ipv6_frag;
 
1360
 
 
1361
            if (keyAttrs[OVS_KEY_ATTR_TCP]) {
 
1362
                const struct ovs_key_tcp *tcpKey;
 
1363
                tcpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_TCP]);
 
1364
                ipv6FlowPutKey->l4.tpSrc = tcpKey->tcp_src;
 
1365
                ipv6FlowPutKey->l4.tpDst = tcpKey->tcp_dst;
 
1366
            }
 
1367
 
 
1368
            if (keyAttrs[OVS_KEY_ATTR_UDP]) {
 
1369
                const struct ovs_key_udp *udpKey;
 
1370
                udpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_UDP]);
 
1371
                ipv6FlowPutKey->l4.tpSrc = udpKey->udp_src;
 
1372
                ipv6FlowPutKey->l4.tpDst = udpKey->udp_dst;
 
1373
            }
 
1374
 
 
1375
            if (keyAttrs[OVS_KEY_ATTR_SCTP]) {
 
1376
                const struct ovs_key_sctp *sctpKey;
 
1377
                sctpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_SCTP]);
 
1378
                ipv6FlowPutKey->l4.tpSrc = sctpKey->sctp_src;
 
1379
                ipv6FlowPutKey->l4.tpDst = sctpKey->sctp_dst;
 
1380
            }
 
1381
 
 
1382
            if (keyAttrs[OVS_KEY_ATTR_ICMPV6]) {
 
1383
                const struct ovs_key_icmpv6 *icmpv6Key;
 
1384
 
 
1385
                Icmp6Key *icmp6FlowPutKey= &(destKey->icmp6Key);
 
1386
 
 
1387
                icmpv6Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ICMPV6]);
 
1388
 
 
1389
                icmp6FlowPutKey->l4.tpSrc = icmpv6Key->icmpv6_type;
 
1390
                icmp6FlowPutKey->l4.tpDst = icmpv6Key->icmpv6_code;
 
1391
 
 
1392
                if (keyAttrs[OVS_KEY_ATTR_ND]) {
 
1393
                    const struct ovs_key_nd *ndKey;
 
1394
 
 
1395
                    ndKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ND]);
 
1396
                    RtlCopyMemory(&icmp6FlowPutKey->ndTarget,
 
1397
                                  ndKey->nd_target, sizeof (icmp6FlowPutKey->ndTarget));
 
1398
                    RtlCopyMemory(icmp6FlowPutKey->arpSha,
 
1399
                                  ndKey->nd_sll, ETH_ADDR_LEN);
 
1400
                    RtlCopyMemory(icmp6FlowPutKey->arpTha,
 
1401
                                  ndKey->nd_tll, ETH_ADDR_LEN);
 
1402
                }
 
1403
 
 
1404
                destKey->l2.keyLen += OVS_ICMPV6_KEY_SIZE;
 
1405
 
 
1406
            } else {
 
1407
 
 
1408
                destKey->l2.keyLen += OVS_IPV6_KEY_SIZE;
 
1409
            }
 
1410
 
 
1411
            ipv6FlowPutKey->pad = 0;
 
1412
        }
 
1413
        break;
 
1414
    }
 
1415
    case ETH_TYPE_ARP:
 
1416
    case ETH_TYPE_RARP: {
 
1417
 
 
1418
        if (keyAttrs[OVS_KEY_ATTR_ARP]) {
 
1419
            ArpKey *arpFlowPutKey = &destKey->arpKey;
 
1420
            const struct ovs_key_arp *arpKey;
 
1421
 
 
1422
            arpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ARP]);
 
1423
 
 
1424
            arpFlowPutKey->nwSrc = arpKey->arp_sip;
 
1425
            arpFlowPutKey->nwDst = arpKey->arp_tip;
 
1426
 
 
1427
            RtlCopyMemory(arpFlowPutKey->arpSha, arpKey->arp_sha, ETH_ADDR_LEN);
 
1428
            RtlCopyMemory(arpFlowPutKey->arpTha, arpKey->arp_tha, ETH_ADDR_LEN);
 
1429
            /* Kernel datapath assumes 'arpFlowPutKey->nwProto' to be in host
 
1430
             * order. */
 
1431
            arpFlowPutKey->nwProto = (UINT8)ntohs((arpKey->arp_op));
 
1432
            arpFlowPutKey->pad[0] = 0;
 
1433
            arpFlowPutKey->pad[1] = 0;
 
1434
            arpFlowPutKey->pad[2] = 0;
 
1435
            destKey->l2.keyLen += OVS_ARP_KEY_SIZE;
 
1436
            break;
 
1437
        }
 
1438
    }
 
1439
    }
 
1440
}
 
1441
 
 
1442
/*
 
1443
 *----------------------------------------------------------------------------
 
1444
 *  _MapTunAttrToFlowPut --
 
1445
 *    Converts FLOW_TUNNEL_KEY attribute to OvsFlowKey->tunKey.
 
1446
 *----------------------------------------------------------------------------
 
1447
 */
 
1448
static VOID
 
1449
_MapTunAttrToFlowPut(PNL_ATTR *keyAttrs,
 
1450
                     PNL_ATTR *tunAttrs,
 
1451
                     OvsFlowKey *destKey)
 
1452
{
 
1453
    if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
 
1454
 
 
1455
        if (tunAttrs[OVS_TUNNEL_KEY_ATTR_ID]) {
 
1456
            destKey->tunKey.tunnelId = NlAttrGetU64
 
1457
                                       (tunAttrs[OVS_TUNNEL_KEY_ATTR_ID]);
 
1458
            destKey->tunKey.flags |= OVS_TNL_F_KEY;
 
1459
        }
 
1460
 
 
1461
        if (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_DST]) {
 
1462
        destKey->tunKey.dst = NlAttrGetU32
 
1463
                              (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_DST]);
 
1464
        }
 
1465
 
 
1466
        if (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_SRC]) {
 
1467
        destKey->tunKey.src = NlAttrGetU32
 
1468
                              (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_SRC]);
 
1469
        }
 
1470
 
 
1471
        if (tunAttrs[OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT]) {
 
1472
            destKey->tunKey.flags |= OVS_TNL_F_DONT_FRAGMENT;
 
1473
        }
 
1474
 
 
1475
        if (tunAttrs[OVS_TUNNEL_KEY_ATTR_CSUM]) {
 
1476
            destKey->tunKey.flags |= OVS_TNL_F_CSUM;
 
1477
        }
 
1478
 
 
1479
        if (tunAttrs[OVS_TUNNEL_KEY_ATTR_TOS]) {
 
1480
        destKey->tunKey.tos = NlAttrGetU8
 
1481
                              (tunAttrs[OVS_TUNNEL_KEY_ATTR_TOS]);
 
1482
        }
 
1483
 
 
1484
        if (tunAttrs[OVS_TUNNEL_KEY_ATTR_TTL]) {
 
1485
        destKey->tunKey.ttl = NlAttrGetU8
 
1486
                              (tunAttrs[OVS_TUNNEL_KEY_ATTR_TTL]);
 
1487
        }
 
1488
 
 
1489
        destKey->tunKey.pad = 0;
 
1490
        destKey->l2.offset = 0;
 
1491
    } else {
 
1492
        destKey->tunKey.attr[0] = 0;
 
1493
        destKey->tunKey.attr[1] = 0;
 
1494
        destKey->tunKey.attr[2] = 0;
 
1495
        destKey->l2.offset = sizeof destKey->tunKey;
 
1496
    }
 
1497
}
 
1498
 
 
1499
/*
 
1500
 *----------------------------------------------------------------------------
 
1501
 * OvsDeleteFlowTable --
 
1502
 * Results:
 
1503
 *    NDIS_STATUS_SUCCESS always.
 
1504
 *----------------------------------------------------------------------------
 
1505
 */
 
1506
NDIS_STATUS
 
1507
OvsDeleteFlowTable(OVS_DATAPATH *datapath)
 
1508
{
 
1509
    if (datapath == NULL || datapath->flowTable == NULL) {
 
1510
        return NDIS_STATUS_SUCCESS;
 
1511
    }
 
1512
 
 
1513
    DeleteAllFlows(datapath);
 
1514
    OvsFreeMemoryWithTag(datapath->flowTable, OVS_FLOW_POOL_TAG);
 
1515
    datapath->flowTable = NULL;
 
1516
 
 
1517
    if (datapath->lock == NULL) {
 
1518
        return NDIS_STATUS_SUCCESS;
 
1519
    }
 
1520
 
 
1521
    NdisFreeRWLock(datapath->lock);
 
1522
 
 
1523
    return NDIS_STATUS_SUCCESS;
 
1524
}
 
1525
 
 
1526
/*
 
1527
 *----------------------------------------------------------------------------
 
1528
 * OvsAllocateFlowTable --
 
1529
 * Results:
 
1530
 *    NDIS_STATUS_SUCCESS on success.
 
1531
 *    NDIS_STATUS_RESOURCES if memory couldn't be allocated
 
1532
 *----------------------------------------------------------------------------
 
1533
 */
 
1534
NDIS_STATUS
 
1535
OvsAllocateFlowTable(OVS_DATAPATH *datapath,
 
1536
                     POVS_SWITCH_CONTEXT switchContext)
 
1537
{
 
1538
    PLIST_ENTRY bucket;
 
1539
    int i;
 
1540
 
 
1541
    datapath->flowTable = OvsAllocateMemoryWithTag(
 
1542
        OVS_FLOW_TABLE_SIZE * sizeof(LIST_ENTRY), OVS_FLOW_POOL_TAG);
 
1543
    if (!datapath->flowTable) {
 
1544
        return NDIS_STATUS_RESOURCES;
 
1545
    }
 
1546
    for (i = 0; i < OVS_FLOW_TABLE_SIZE; i++) {
 
1547
        bucket = &(datapath->flowTable[i]);
 
1548
        InitializeListHead(bucket);
 
1549
    }
 
1550
    datapath->lock = NdisAllocateRWLock(switchContext->NdisFilterHandle);
 
1551
 
 
1552
    if (!datapath->lock) {
 
1553
        return NDIS_STATUS_RESOURCES;
 
1554
    }
 
1555
 
 
1556
    return NDIS_STATUS_SUCCESS;
 
1557
}
 
1558
 
 
1559
 
 
1560
/*
 
1561
 *----------------------------------------------------------------------------
 
1562
 *  GetStartAddrNBL --
 
1563
 *    Get the virtual address of the frame.
 
1564
 *
 
1565
 *  Results:
 
1566
 *    Virtual address of the frame.
 
1567
 *----------------------------------------------------------------------------
 
1568
 */
 
1569
static __inline VOID *
 
1570
GetStartAddrNBL(const NET_BUFFER_LIST *_pNB)
 
1571
{
 
1572
    PMDL curMdl;
 
1573
    PUINT8 curBuffer;
 
1574
    PEthHdr curHeader;
 
1575
 
 
1576
    ASSERT(_pNB);
 
1577
 
 
1578
    // Ethernet Header is a guaranteed safe access.
 
1579
    curMdl = (NET_BUFFER_LIST_FIRST_NB(_pNB))->CurrentMdl;
 
1580
    curBuffer =  MmGetSystemAddressForMdlSafe(curMdl, LowPagePriority);
 
1581
    if (!curBuffer) {
 
1582
        return NULL;
 
1583
    }
 
1584
 
 
1585
    curHeader = (PEthHdr)
 
1586
    (curBuffer + (NET_BUFFER_LIST_FIRST_NB(_pNB))->CurrentMdlOffset);
 
1587
 
 
1588
    return (VOID *) curHeader;
 
1589
}
 
1590
 
 
1591
VOID
 
1592
OvsFlowUsed(OvsFlow *flow,
 
1593
            const NET_BUFFER_LIST *packet,
 
1594
            const POVS_PACKET_HDR_INFO layers)
 
1595
{
 
1596
    LARGE_INTEGER tickCount;
 
1597
 
 
1598
    KeQueryTickCount(&tickCount);
 
1599
    flow->used = tickCount.QuadPart * ovsTimeIncrementPerTick;
 
1600
    flow->packetCount++;
 
1601
    flow->byteCount += OvsPacketLenNBL(packet);
 
1602
    flow->tcpFlags |= OvsGetTcpFlags(packet, &flow->key, layers);
 
1603
}
 
1604
 
 
1605
 
 
1606
VOID
 
1607
DeleteAllFlows(OVS_DATAPATH *datapath)
 
1608
{
 
1609
    INT i;
 
1610
    PLIST_ENTRY bucket;
 
1611
 
 
1612
    for (i = 0; i < OVS_FLOW_TABLE_SIZE; i++) {
 
1613
        PLIST_ENTRY next;
 
1614
        bucket = &(datapath->flowTable[i]);
 
1615
        while (!IsListEmpty(bucket)) {
 
1616
            OvsFlow *flow;
 
1617
            next = bucket->Flink;
 
1618
            flow = CONTAINING_RECORD(next, OvsFlow, ListEntry);
 
1619
            RemoveFlow(datapath, &flow);
 
1620
        }
 
1621
    }
 
1622
}
 
1623
 
 
1624
/*
 
1625
 *----------------------------------------------------------------------------
 
1626
 * Initializes 'flow' members from 'packet', 'skb_priority', 'tun_id', and
 
1627
 * 'ofp_in_port'.
 
1628
 *
 
1629
 * Initializes 'packet' header pointers as follows:
 
1630
 *
 
1631
 *    - packet->l2 to the start of the Ethernet header.
 
1632
 *
 
1633
 *    - packet->l3 to just past the Ethernet header, or just past the
 
1634
 *      vlan_header if one is present, to the first byte of the payload of the
 
1635
 *      Ethernet frame.
 
1636
 *
 
1637
 *    - packet->l4 to just past the IPv4 header, if one is present and has a
 
1638
 *      correct length, and otherwise NULL.
 
1639
 *
 
1640
 *    - packet->l7 to just past the TCP or UDP or ICMP header, if one is
 
1641
 *      present and has a correct length, and otherwise NULL.
 
1642
 *
 
1643
 * Returns NDIS_STATUS_SUCCESS normally.  Fails only if packet data cannot be accessed
 
1644
 * (e.g. if Pkt_CopyBytesOut() returns an error).
 
1645
 *----------------------------------------------------------------------------
 
1646
 */
 
1647
NDIS_STATUS
 
1648
OvsExtractFlow(const NET_BUFFER_LIST *packet,
 
1649
               UINT32 inPort,
 
1650
               OvsFlowKey *flow,
 
1651
               POVS_PACKET_HDR_INFO layers,
 
1652
               OvsIPv4TunnelKey *tunKey)
 
1653
{
 
1654
    struct Eth_Header *eth;
 
1655
    UINT8 offset = 0;
 
1656
    PVOID vlanTagValue;
 
1657
 
 
1658
    layers->value = 0;
 
1659
 
 
1660
    if (tunKey) {
 
1661
        ASSERT(tunKey->dst != 0);
 
1662
        RtlMoveMemory(&flow->tunKey, tunKey, sizeof flow->tunKey);
 
1663
        flow->l2.offset = 0;
 
1664
    } else {
 
1665
        flow->tunKey.dst = 0;
 
1666
        flow->l2.offset = OVS_WIN_TUNNEL_KEY_SIZE;
 
1667
    }
 
1668
 
 
1669
    flow->l2.inPort = inPort;
 
1670
 
 
1671
    if ( OvsPacketLenNBL(packet) < ETH_HEADER_LEN_DIX) {
 
1672
        flow->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + 8 - flow->l2.offset;
 
1673
        return NDIS_STATUS_SUCCESS;
 
1674
    }
 
1675
 
 
1676
    /* Link layer. */
 
1677
    eth = (Eth_Header *)GetStartAddrNBL((NET_BUFFER_LIST *)packet);
 
1678
    memcpy(flow->l2.dlSrc, eth->src, ETH_ADDR_LENGTH);
 
1679
    memcpy(flow->l2.dlDst, eth->dst, ETH_ADDR_LENGTH);
 
1680
 
 
1681
    /*
 
1682
     * vlan_tci.
 
1683
     */
 
1684
    vlanTagValue = NET_BUFFER_LIST_INFO(packet, Ieee8021QNetBufferListInfo);
 
1685
    if (vlanTagValue) {
 
1686
        PNDIS_NET_BUFFER_LIST_8021Q_INFO vlanTag =
 
1687
            (PNDIS_NET_BUFFER_LIST_8021Q_INFO)(PVOID *)&vlanTagValue;
 
1688
        flow->l2.vlanTci = htons(vlanTag->TagHeader.VlanId | OVSWIN_VLAN_CFI |
 
1689
                                 (vlanTag->TagHeader.UserPriority << 13));
 
1690
    } else {
 
1691
        if (eth->dix.typeNBO == ETH_TYPE_802_1PQ_NBO) {
 
1692
            Eth_802_1pq_Tag *tag= (Eth_802_1pq_Tag *)&eth->dix.typeNBO;
 
1693
            flow->l2.vlanTci = ((UINT16)tag->priority << 13) |
 
1694
                               OVSWIN_VLAN_CFI |
 
1695
                               ((UINT16)tag->vidHi << 8)  | tag->vidLo;
 
1696
            offset = sizeof (Eth_802_1pq_Tag);
 
1697
        } else {
 
1698
            flow->l2.vlanTci = 0;
 
1699
        }
 
1700
        /*
 
1701
        * XXX
 
1702
        * Please note after this point, src mac and dst mac should
 
1703
        * not be accessed through eth
 
1704
        */
 
1705
        eth = (Eth_Header *)((UINT8 *)eth + offset);
 
1706
    }
 
1707
 
 
1708
    /*
 
1709
     * dl_type.
 
1710
     *
 
1711
     * XXX assume that at least the first
 
1712
     * 12 bytes of received packets are mapped.  This code has the stronger
 
1713
     * assumption that at least the first 22 bytes of 'packet' is mapped (if my
 
1714
     * arithmetic is right).
 
1715
     */
 
1716
    if (ETH_TYPENOT8023(eth->dix.typeNBO)) {
 
1717
        flow->l2.dlType = eth->dix.typeNBO;
 
1718
        layers->l3Offset = ETH_HEADER_LEN_DIX + offset;
 
1719
    } else if (OvsPacketLenNBL(packet)  >= ETH_HEADER_LEN_802_3 &&
 
1720
              eth->e802_3.llc.dsap == 0xaa &&
 
1721
              eth->e802_3.llc.ssap == 0xaa &&
 
1722
              eth->e802_3.llc.control == ETH_LLC_CONTROL_UFRAME &&
 
1723
              eth->e802_3.snap.snapOrg[0] == 0x00 &&
 
1724
              eth->e802_3.snap.snapOrg[1] == 0x00 &&
 
1725
              eth->e802_3.snap.snapOrg[2] == 0x00) {
 
1726
        flow->l2.dlType = eth->e802_3.snap.snapType.typeNBO;
 
1727
        layers->l3Offset = ETH_HEADER_LEN_802_3 + offset;
 
1728
    } else {
 
1729
        flow->l2.dlType = htons(OVSWIN_DL_TYPE_NONE);
 
1730
        layers->l3Offset = ETH_HEADER_LEN_DIX + offset;
 
1731
    }
 
1732
 
 
1733
    flow->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + OVS_L2_KEY_SIZE - flow->l2.offset;
 
1734
    /* Network layer. */
 
1735
    if (flow->l2.dlType == htons(ETH_TYPE_IPV4)) {
 
1736
        struct IPHdr ip_storage;
 
1737
        const struct IPHdr *nh;
 
1738
        IpKey *ipKey = &flow->ipKey;
 
1739
 
 
1740
        flow->l2.keyLen += OVS_IP_KEY_SIZE;
 
1741
        layers->isIPv4 = 1;
 
1742
        nh = OvsGetIp(packet, layers->l3Offset, &ip_storage);
 
1743
        if (nh) {
 
1744
            layers->l4Offset = layers->l3Offset + nh->ihl * 4;
 
1745
 
 
1746
            ipKey->nwSrc = nh->saddr;
 
1747
            ipKey->nwDst = nh->daddr;
 
1748
            ipKey->nwProto = nh->protocol;
 
1749
 
 
1750
            ipKey->nwTos = nh->tos;
 
1751
            if (nh->frag_off & htons(IP_MF | IP_OFFSET)) {
 
1752
                ipKey->nwFrag = OVSWIN_NW_FRAG_ANY;
 
1753
                if (nh->frag_off & htons(IP_OFFSET)) {
 
1754
                    ipKey->nwFrag |= OVSWIN_NW_FRAG_LATER;
 
1755
                }
 
1756
            } else {
 
1757
                ipKey->nwFrag = 0;
 
1758
            }
 
1759
 
 
1760
            ipKey->nwTtl = nh->ttl;
 
1761
            ipKey->l4.tpSrc = 0;
 
1762
            ipKey->l4.tpDst = 0;
 
1763
 
 
1764
            if (!(nh->frag_off & htons(IP_OFFSET))) {
 
1765
                if (ipKey->nwProto == SOCKET_IPPROTO_TCP) {
 
1766
                    OvsParseTcp(packet, &ipKey->l4, layers);
 
1767
                } else if (ipKey->nwProto == SOCKET_IPPROTO_UDP) {
 
1768
                    OvsParseUdp(packet, &ipKey->l4, layers);
 
1769
                } else if (ipKey->nwProto == SOCKET_IPPROTO_ICMP) {
 
1770
                    ICMPHdr icmpStorage;
 
1771
                    const ICMPHdr *icmp;
 
1772
 
 
1773
                    icmp = OvsGetIcmp(packet, layers->l4Offset, &icmpStorage);
 
1774
                    if (icmp) {
 
1775
                        ipKey->l4.tpSrc = htons(icmp->type);
 
1776
                        ipKey->l4.tpDst = htons(icmp->code);
 
1777
                        layers->l7Offset = layers->l4Offset + sizeof *icmp;
 
1778
                    }
 
1779
                }
 
1780
            }
 
1781
        } else {
 
1782
            ((UINT64 *)ipKey)[0] = 0;
 
1783
            ((UINT64 *)ipKey)[1] = 0;
 
1784
        }
 
1785
    } else if (flow->l2.dlType == htons(ETH_TYPE_IPV6)) {
 
1786
        NDIS_STATUS status;
 
1787
        flow->l2.keyLen += OVS_IPV6_KEY_SIZE;
 
1788
        status = OvsParseIPv6(packet, flow, layers);
 
1789
        if (status != NDIS_STATUS_SUCCESS) {
 
1790
            memset(&flow->ipv6Key, 0, sizeof (Ipv6Key));
 
1791
            return status;
 
1792
        }
 
1793
        layers->isIPv6 = 1;
 
1794
        flow->ipv6Key.l4.tpSrc = 0;
 
1795
        flow->ipv6Key.l4.tpDst = 0;
 
1796
        flow->ipv6Key.pad = 0;
 
1797
 
 
1798
        if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_TCP) {
 
1799
            OvsParseTcp(packet, &(flow->ipv6Key.l4), layers);
 
1800
        } else if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_UDP) {
 
1801
            OvsParseUdp(packet, &(flow->ipv6Key.l4), layers);
 
1802
        } else if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_ICMPV6) {
 
1803
            OvsParseIcmpV6(packet, flow, layers);
 
1804
            flow->l2.keyLen += (OVS_ICMPV6_KEY_SIZE - OVS_IPV6_KEY_SIZE);
 
1805
        }
 
1806
    } else if (flow->l2.dlType == htons(ETH_TYPE_ARP)) {
 
1807
        EtherArp arpStorage;
 
1808
        const EtherArp *arp;
 
1809
        ArpKey *arpKey = &flow->arpKey;
 
1810
        ((UINT64 *)arpKey)[0] = 0;
 
1811
        ((UINT64 *)arpKey)[1] = 0;
 
1812
        ((UINT64 *)arpKey)[2] = 0;
 
1813
        flow->l2.keyLen += OVS_ARP_KEY_SIZE;
 
1814
        arp = OvsGetArp(packet, layers->l3Offset, &arpStorage);
 
1815
        if (arp && arp->ea_hdr.ar_hrd == htons(1) &&
 
1816
            arp->ea_hdr.ar_pro == htons(ETH_TYPE_IPV4) &&
 
1817
            arp->ea_hdr.ar_hln == ETH_ADDR_LENGTH &&
 
1818
            arp->ea_hdr.ar_pln == 4) {
 
1819
            /* We only match on the lower 8 bits of the opcode. */
 
1820
            if (ntohs(arp->ea_hdr.ar_op) <= 0xff) {
 
1821
                arpKey->nwProto = (UINT8)ntohs(arp->ea_hdr.ar_op);
 
1822
            }
 
1823
            if (arpKey->nwProto == ARPOP_REQUEST
 
1824
                || arpKey->nwProto == ARPOP_REPLY) {
 
1825
                memcpy(&arpKey->nwSrc, arp->arp_spa, 4);
 
1826
                memcpy(&arpKey->nwDst, arp->arp_tpa, 4);
 
1827
                memcpy(arpKey->arpSha, arp->arp_sha, ETH_ADDR_LENGTH);
 
1828
                memcpy(arpKey->arpTha, arp->arp_tha, ETH_ADDR_LENGTH);
 
1829
            }
 
1830
        }
 
1831
    }
 
1832
 
 
1833
    return NDIS_STATUS_SUCCESS;
 
1834
}
 
1835
 
 
1836
__inline BOOLEAN
 
1837
FlowEqual(UINT64 *src, UINT64 *dst, UINT32 size)
 
1838
{
 
1839
    UINT32 i;
 
1840
    ASSERT((size & 0x7) == 0);
 
1841
    ASSERT(((UINT64)src & 0x7) == 0);
 
1842
    ASSERT(((UINT64)dst & 0x7) == 0);
 
1843
    for (i = 0; i < (size >> 3); i++) {
 
1844
        if (src[i] != dst[i]) {
 
1845
            return FALSE;
 
1846
        }
 
1847
    }
 
1848
    return TRUE;
 
1849
}
 
1850
 
 
1851
 
 
1852
/*
 
1853
 * ----------------------------------------------------------------------------
 
1854
 * AddFlow --
 
1855
 *    Add a flow to flow table.
 
1856
 *
 
1857
 * Results:
 
1858
 *   NDIS_STATUS_SUCCESS if no same flow in the flow table.
 
1859
 * ----------------------------------------------------------------------------
 
1860
 */
 
1861
NTSTATUS
 
1862
AddFlow(OVS_DATAPATH *datapath, OvsFlow *flow)
 
1863
{
 
1864
    PLIST_ENTRY head;
 
1865
 
 
1866
    if (OvsLookupFlow(datapath, &flow->key, &flow->hash, TRUE) != NULL) {
 
1867
        return STATUS_INVALID_HANDLE;
 
1868
    }
 
1869
 
 
1870
    head = &(datapath->flowTable[HASH_BUCKET(flow->hash)]);
 
1871
    /*
 
1872
     * We need fence here to make sure flow's nextPtr is updated before
 
1873
     * head->nextPtr is updated.
 
1874
     */
 
1875
    KeMemoryBarrier();
 
1876
 
 
1877
    //KeAcquireSpinLock(&FilterDeviceExtension->NblQueueLock, &oldIrql);
 
1878
    InsertTailList(head, &flow->ListEntry);
 
1879
    //KeReleaseSpinLock(&FilterDeviceExtension->NblQueueLock, oldIrql);
 
1880
 
 
1881
    datapath->nFlows++;
 
1882
 
 
1883
    return STATUS_SUCCESS;
 
1884
}
 
1885
 
 
1886
 
 
1887
/* ----------------------------------------------------------------------------
 
1888
 * RemoveFlow --
 
1889
 *   Remove a flow from flow table, and added to wait list
 
1890
 * ----------------------------------------------------------------------------
 
1891
 */
 
1892
VOID
 
1893
RemoveFlow(OVS_DATAPATH *datapath,
 
1894
           OvsFlow **flow)
 
1895
{
 
1896
    OvsFlow *f = *flow;
 
1897
    *flow = NULL;
 
1898
 
 
1899
    ASSERT(datapath->nFlows);
 
1900
    datapath->nFlows--;
 
1901
    // Remove the flow  from queue
 
1902
    RemoveEntryList(&f->ListEntry);
 
1903
    FreeFlow(f);
 
1904
}
 
1905
 
 
1906
 
 
1907
/*
 
1908
 * ----------------------------------------------------------------------------
 
1909
 * OvsLookupFlow --
 
1910
 *
 
1911
 *    Find flow from flow table based on flow key.
 
1912
 *    Caller should either hold portset handle or should
 
1913
 *    have a flowRef in datapath or Acquired datapath.
 
1914
 *
 
1915
 * Results:
 
1916
 *    Flow pointer if lookup successful.
 
1917
 *    NULL if not exists.
 
1918
 * ----------------------------------------------------------------------------
 
1919
 */
 
1920
OvsFlow *
 
1921
OvsLookupFlow(OVS_DATAPATH *datapath,
 
1922
              const OvsFlowKey *key,
 
1923
              UINT64 *hash,
 
1924
              BOOLEAN hashValid)
 
1925
{
 
1926
    PLIST_ENTRY link, head;
 
1927
    UINT16 offset = key->l2.offset;
 
1928
    UINT16 size = key->l2.keyLen;
 
1929
    UINT8 *start;
 
1930
 
 
1931
    ASSERT(key->tunKey.dst || offset == sizeof (OvsIPv4TunnelKey));
 
1932
    ASSERT(!key->tunKey.dst || offset == 0);
 
1933
 
 
1934
    start = (UINT8 *)key + offset;
 
1935
 
 
1936
    if (!hashValid) {
 
1937
        *hash = OvsJhashBytes(start, size, 0);
 
1938
    }
 
1939
 
 
1940
    head = &datapath->flowTable[HASH_BUCKET(*hash)];
 
1941
    link  = head->Flink;
 
1942
    while (link != head) {
 
1943
        OvsFlow *flow = CONTAINING_RECORD(link, OvsFlow, ListEntry);
 
1944
 
 
1945
        if (flow->hash == *hash &&
 
1946
            flow->key.l2.val == key->l2.val &&
 
1947
            FlowEqual((UINT64 *)((uint8 *)&flow->key + offset),
 
1948
                         (UINT64 *)start, size)) {
 
1949
            return flow;
 
1950
        }
 
1951
        link = link->Flink;
 
1952
    }
 
1953
    return NULL;
 
1954
}
 
1955
 
 
1956
 
 
1957
/*
 
1958
 * ----------------------------------------------------------------------------
 
1959
 * OvsHashFlow --
 
1960
 *    Calculate the hash for the given flow key.
 
1961
 * ----------------------------------------------------------------------------
 
1962
 */
 
1963
UINT64
 
1964
OvsHashFlow(const OvsFlowKey *key)
 
1965
{
 
1966
    UINT16 offset = key->l2.offset;
 
1967
    UINT16 size = key->l2.keyLen;
 
1968
    UINT8 *start;
 
1969
 
 
1970
    ASSERT(key->tunKey.dst || offset == sizeof (OvsIPv4TunnelKey));
 
1971
    ASSERT(!key->tunKey.dst || offset == 0);
 
1972
    start = (UINT8 *)key + offset;
 
1973
    return OvsJhashBytes(start, size, 0);
 
1974
}
 
1975
 
 
1976
 
 
1977
/*
 
1978
 * ----------------------------------------------------------------------------
 
1979
 * FreeFlow --
 
1980
 *    Free a flow and its actions.
 
1981
 * ----------------------------------------------------------------------------
 
1982
 */
 
1983
VOID
 
1984
FreeFlow(OvsFlow *flow)
 
1985
{
 
1986
    ASSERT(flow);
 
1987
    OvsFreeMemoryWithTag(flow, OVS_FLOW_POOL_TAG);
 
1988
}
 
1989
 
 
1990
NTSTATUS
 
1991
OvsDoDumpFlows(OvsFlowDumpInput *dumpInput,
 
1992
               OvsFlowDumpOutput *dumpOutput,
 
1993
               UINT32 *replyLen)
 
1994
{
 
1995
    UINT32 dpNo;
 
1996
    OVS_DATAPATH *datapath = NULL;
 
1997
    OvsFlow *flow;
 
1998
    PLIST_ENTRY node, head;
 
1999
    UINT32 column = 0;
 
2000
    UINT32 rowIndex, columnIndex;
 
2001
    LOCK_STATE_EX dpLockState;
 
2002
    NTSTATUS status = STATUS_SUCCESS;
 
2003
    BOOLEAN findNextNonEmpty = FALSE;
 
2004
 
 
2005
    dpNo = dumpInput->dpNo;
 
2006
    if (gOvsSwitchContext->dpNo != dpNo) {
 
2007
        status = STATUS_INVALID_PARAMETER;
 
2008
        goto exit;
 
2009
    }
 
2010
 
 
2011
    rowIndex = dumpInput->position[0];
 
2012
    if (rowIndex >= OVS_FLOW_TABLE_SIZE) {
 
2013
        dumpOutput->n = 0;
 
2014
        *replyLen = sizeof(*dumpOutput);
 
2015
        goto exit;
 
2016
    }
 
2017
 
 
2018
    columnIndex = dumpInput->position[1];
 
2019
 
 
2020
    datapath = &gOvsSwitchContext->datapath;
 
2021
    ASSERT(datapath);
 
2022
    OvsAcquireDatapathRead(datapath, &dpLockState, FALSE);
 
2023
 
 
2024
    head = &datapath->flowTable[rowIndex];
 
2025
    node = head->Flink;
 
2026
 
 
2027
    while (column < columnIndex) {
 
2028
        if (node == head) {
 
2029
            break;
 
2030
        }
 
2031
        node = node->Flink;
 
2032
        column++;
 
2033
    }
 
2034
 
 
2035
    if (node == head) {
 
2036
        findNextNonEmpty = TRUE;
 
2037
        columnIndex = 0;
 
2038
    }
 
2039
 
 
2040
    if (findNextNonEmpty) {
 
2041
        while (head == node) {
 
2042
            if (++rowIndex >= OVS_FLOW_TABLE_SIZE) {
 
2043
                dumpOutput->n = 0;
 
2044
                goto dp_unlock;
 
2045
            }
 
2046
            head = &datapath->flowTable[rowIndex];
 
2047
            node = head->Flink;
 
2048
        }
 
2049
    }
 
2050
 
 
2051
    ASSERT(node != head);
 
2052
    ASSERT(rowIndex < OVS_FLOW_TABLE_SIZE);
 
2053
 
 
2054
    flow = CONTAINING_RECORD(node, OvsFlow, ListEntry);
 
2055
    status = ReportFlowInfo(flow, dumpInput->getFlags, &dumpOutput->flow);
 
2056
 
 
2057
    if (status == STATUS_BUFFER_TOO_SMALL) {
 
2058
        dumpOutput->n = sizeof(OvsFlowDumpOutput) + flow->actionsLen;
 
2059
        *replyLen = sizeof(*dumpOutput);
 
2060
    } else {
 
2061
        dumpOutput->n = 1; //one flow reported.
 
2062
        *replyLen = sizeof(*dumpOutput) + dumpOutput->flow.actionsLen;
 
2063
    }
 
2064
 
 
2065
    dumpOutput->position[0] = rowIndex;
 
2066
    dumpOutput->position[1] = ++columnIndex;
 
2067
 
 
2068
dp_unlock:
 
2069
    OvsReleaseDatapath(datapath, &dpLockState);
 
2070
 
 
2071
exit:
 
2072
    return status;
 
2073
}
 
2074
 
 
2075
static NTSTATUS
 
2076
ReportFlowInfo(OvsFlow *flow,
 
2077
               UINT32 getFlags,
 
2078
               OvsFlowInfo *info)
 
2079
{
 
2080
    NTSTATUS status = STATUS_SUCCESS;
 
2081
 
 
2082
    if (getFlags & FLOW_GET_KEY) {
 
2083
        // always copy the tunnel key part
 
2084
        RtlCopyMemory(&info->key, &flow->key,
 
2085
                            flow->key.l2.keyLen + flow->key.l2.offset);
 
2086
    }
 
2087
 
 
2088
    if (getFlags & FLOW_GET_STATS) {
 
2089
        OvsFlowStats *stats = &info->stats;
 
2090
        stats->packetCount = flow->packetCount;
 
2091
        stats->byteCount = flow->byteCount;
 
2092
        stats->used = (UINT32)flow->used;
 
2093
        stats->tcpFlags = flow->tcpFlags;
 
2094
    }
 
2095
 
 
2096
    if (getFlags & FLOW_GET_ACTIONS) {
 
2097
        if (flow->actionsLen == 0) {
 
2098
            info->actionsLen = 0;
 
2099
        } else {
 
2100
            info->actions = flow->actions;
 
2101
            info->actionsLen = flow->actionsLen;
 
2102
        }
 
2103
    }
 
2104
 
 
2105
    return status;
 
2106
}
 
2107
 
 
2108
NTSTATUS
 
2109
OvsPutFlowIoctl(PVOID inputBuffer,
 
2110
                UINT32 inputLength,
 
2111
                struct OvsFlowStats *stats)
 
2112
{
 
2113
    NTSTATUS status = STATUS_SUCCESS;
 
2114
    OVS_DATAPATH *datapath = NULL;
 
2115
    ULONG actionsLen;
 
2116
    OvsFlowPut *put;
 
2117
    UINT32 dpNo;
 
2118
    LOCK_STATE_EX dpLockState;
 
2119
 
 
2120
    if ((inputLength < sizeof(OvsFlowPut)) || (inputBuffer == NULL)) {
 
2121
        return STATUS_INFO_LENGTH_MISMATCH;
 
2122
    }
 
2123
 
 
2124
    put = (OvsFlowPut *)inputBuffer;
 
2125
    if (put->actionsLen > 0) {
 
2126
        actionsLen = put->actionsLen;
 
2127
    } else {
 
2128
        actionsLen = 0;
 
2129
    }
 
2130
 
 
2131
    dpNo = put->dpNo;
 
2132
    if (gOvsSwitchContext->dpNo != dpNo) {
 
2133
        status = STATUS_INVALID_PARAMETER;
 
2134
        goto exit;
 
2135
    }
 
2136
 
 
2137
    datapath = &gOvsSwitchContext->datapath;
 
2138
    ASSERT(datapath);
 
2139
    OvsAcquireDatapathWrite(datapath, &dpLockState, FALSE);
 
2140
    status = HandleFlowPut(put, datapath, stats);
 
2141
    OvsReleaseDatapath(datapath, &dpLockState);
 
2142
 
 
2143
exit:
 
2144
    return status;
 
2145
}
 
2146
 
 
2147
 
 
2148
/* Handles flow add, modify as well as delete */
 
2149
static NTSTATUS
 
2150
HandleFlowPut(OvsFlowPut *put,
 
2151
              OVS_DATAPATH *datapath,
 
2152
              struct OvsFlowStats *stats)
 
2153
{
 
2154
    BOOLEAN   mayCreate, mayModify, mayDelete;
 
2155
    OvsFlow   *KernelFlow;
 
2156
    UINT64    hash;
 
2157
    NTSTATUS  status = STATUS_SUCCESS;
 
2158
 
 
2159
    mayCreate = (put->flags & OVSWIN_FLOW_PUT_CREATE) != 0;
 
2160
    mayModify = (put->flags & OVSWIN_FLOW_PUT_MODIFY) != 0;
 
2161
    mayDelete = (put->flags & OVSWIN_FLOW_PUT_DELETE) != 0;
 
2162
 
 
2163
    if ((mayCreate || mayModify) == mayDelete) {
 
2164
        return STATUS_INVALID_PARAMETER;
 
2165
    }
 
2166
 
 
2167
    KernelFlow = OvsLookupFlow(datapath, &put->key, &hash, FALSE);
 
2168
    if (!KernelFlow) {
 
2169
        if (!mayCreate) {
 
2170
            return STATUS_INVALID_PARAMETER;
 
2171
        }
 
2172
 
 
2173
        status = OvsPrepareFlow(&KernelFlow, put, hash);
 
2174
        if (status != STATUS_SUCCESS) {
 
2175
            return STATUS_UNSUCCESSFUL;
 
2176
        }
 
2177
 
 
2178
        status = AddFlow(datapath, KernelFlow);
 
2179
        if (status != STATUS_SUCCESS) {
 
2180
            FreeFlow(KernelFlow);
 
2181
            return STATUS_UNSUCCESSFUL;
 
2182
        }
 
2183
 
 
2184
        /* Validate the flow addition */
 
2185
        {
 
2186
            UINT64 newHash;
 
2187
            OvsFlow *flow = OvsLookupFlow(datapath, &put->key, &newHash,
 
2188
                                                                    FALSE);
 
2189
            ASSERT(flow);
 
2190
            ASSERT(newHash == hash);
 
2191
            if (!flow || newHash != hash) {
 
2192
                return STATUS_UNSUCCESSFUL;
 
2193
            }
 
2194
        }
 
2195
    } else {
 
2196
        stats->packetCount = KernelFlow->packetCount;
 
2197
        stats->byteCount = KernelFlow->byteCount;
 
2198
        stats->tcpFlags = KernelFlow->tcpFlags;
 
2199
        stats->used = (UINT32)KernelFlow->used;
 
2200
 
 
2201
        if (mayModify) {
 
2202
            OvsFlow *newFlow;
 
2203
            status = OvsPrepareFlow(&newFlow, put, hash);
 
2204
            if (status != STATUS_SUCCESS) {
 
2205
                return STATUS_UNSUCCESSFUL;
 
2206
            }
 
2207
 
 
2208
            KernelFlow = OvsLookupFlow(datapath, &put->key, &hash, TRUE);
 
2209
            if (KernelFlow)  {
 
2210
                if ((put->flags & OVSWIN_FLOW_PUT_CLEAR) == 0) {
 
2211
                    newFlow->packetCount = KernelFlow->packetCount;
 
2212
                    newFlow->byteCount = KernelFlow->byteCount;
 
2213
                    newFlow->tcpFlags = KernelFlow->tcpFlags;
 
2214
                }
 
2215
                RemoveFlow(datapath, &KernelFlow);
 
2216
            }  else  {
 
2217
                if ((put->flags & OVSWIN_FLOW_PUT_CLEAR) == 0)  {
 
2218
                    newFlow->packetCount = stats->packetCount;
 
2219
                    newFlow->byteCount = stats->byteCount;
 
2220
                    newFlow->tcpFlags = stats->tcpFlags;
 
2221
                }
 
2222
            }
 
2223
            status = AddFlow(datapath, newFlow);
 
2224
            ASSERT(status == STATUS_SUCCESS);
 
2225
 
 
2226
            /* Validate the flow addition */
 
2227
            {
 
2228
                UINT64 newHash;
 
2229
                OvsFlow *testflow = OvsLookupFlow(datapath, &put->key,
 
2230
                                                            &newHash, FALSE);
 
2231
                ASSERT(testflow);
 
2232
                ASSERT(newHash == hash);
 
2233
                if (!testflow || newHash != hash) {
 
2234
                    FreeFlow(newFlow);
 
2235
                    return STATUS_UNSUCCESSFUL;
 
2236
                }
 
2237
            }
 
2238
        } else {
 
2239
            if (mayDelete) {
 
2240
                if (KernelFlow) {
 
2241
                    RemoveFlow(datapath, &KernelFlow);
 
2242
                }
 
2243
            } else {
 
2244
                /* Return success if an identical flow already exists. */
 
2245
                /* XXX: should we return EEXIST in a netlink error? */
 
2246
                return STATUS_SUCCESS;
 
2247
            }
 
2248
        }
 
2249
    }
 
2250
    return STATUS_SUCCESS;
 
2251
}
 
2252
 
 
2253
static NTSTATUS
 
2254
OvsPrepareFlow(OvsFlow **flow,
 
2255
               const OvsFlowPut *put,
 
2256
               UINT64 hash)
 
2257
{
 
2258
    OvsFlow     *localFlow = *flow;
 
2259
    NTSTATUS status = STATUS_SUCCESS;
 
2260
 
 
2261
    do {
 
2262
        *flow = localFlow =
 
2263
            OvsAllocateMemoryWithTag(sizeof(OvsFlow) + put->actionsLen,
 
2264
                                     OVS_FLOW_POOL_TAG);
 
2265
        if (localFlow == NULL) {
 
2266
            status = STATUS_NO_MEMORY;
 
2267
            break;
 
2268
        }
 
2269
 
 
2270
        localFlow->key = put->key;
 
2271
        localFlow->actionsLen = put->actionsLen;
 
2272
        if (put->actionsLen) {
 
2273
            NdisMoveMemory((PUCHAR)localFlow->actions, put->actions,
 
2274
                                       put->actionsLen);
 
2275
        }
 
2276
        localFlow->userActionsLen = 0;  // 0 indicate no conversion is made
 
2277
        localFlow->used = 0;
 
2278
        localFlow->packetCount = 0;
 
2279
        localFlow->byteCount = 0;
 
2280
        localFlow->tcpFlags = 0;
 
2281
        localFlow->hash = hash;
 
2282
    } while(FALSE);
 
2283
 
 
2284
    return status;
 
2285
}
 
2286
 
 
2287
NTSTATUS
 
2288
OvsGetFlowIoctl(PVOID inputBuffer,
 
2289
                PVOID outputBuffer)
 
2290
{
 
2291
    NTSTATUS status = STATUS_SUCCESS;
 
2292
    OVS_DATAPATH *datapath = NULL;
 
2293
    OvsFlow *flow;
 
2294
    UINT32 getFlags, getActionsLen;
 
2295
    OvsFlowGetInput *getInput;
 
2296
    OvsFlowGetOutput *getOutput;
 
2297
    UINT64 hash;
 
2298
    UINT32 dpNo;
 
2299
    LOCK_STATE_EX dpLockState;
 
2300
 
 
2301
    getInput = (OvsFlowGetInput *) inputBuffer;
 
2302
    getFlags = getInput->getFlags;
 
2303
    getActionsLen = getInput->actionsLen;
 
2304
 
 
2305
    if (outputBuffer == NULL) {
 
2306
        return STATUS_INFO_LENGTH_MISMATCH;
 
2307
    }
 
2308
 
 
2309
    dpNo = getInput->dpNo;
 
2310
    if (gOvsSwitchContext->dpNo != dpNo) {
 
2311
        status = STATUS_INVALID_PARAMETER;
 
2312
        goto exit;
 
2313
    }
 
2314
 
 
2315
    datapath = &gOvsSwitchContext->datapath;
 
2316
    ASSERT(datapath);
 
2317
    OvsAcquireDatapathRead(datapath, &dpLockState, FALSE);
 
2318
    flow = OvsLookupFlow(datapath, &getInput->key, &hash, FALSE);
 
2319
    if (!flow) {
 
2320
        status = STATUS_INVALID_PARAMETER;
 
2321
        goto dp_unlock;
 
2322
    }
 
2323
 
 
2324
    getOutput = (OvsFlowGetOutput *)outputBuffer;
 
2325
    ReportFlowInfo(flow, getFlags, &getOutput->info);
 
2326
 
 
2327
dp_unlock:
 
2328
    OvsReleaseDatapath(datapath, &dpLockState);
 
2329
exit:
 
2330
    return status;
 
2331
}
 
2332
 
 
2333
NTSTATUS
 
2334
OvsFlushFlowIoctl(UINT32 dpNo)
 
2335
{
 
2336
    NTSTATUS status = STATUS_SUCCESS;
 
2337
    OVS_DATAPATH *datapath = NULL;
 
2338
    LOCK_STATE_EX dpLockState;
 
2339
 
 
2340
    if (gOvsSwitchContext->dpNo != dpNo) {
 
2341
        status = STATUS_INVALID_PARAMETER;
 
2342
        goto exit;
 
2343
    }
 
2344
 
 
2345
    datapath = &gOvsSwitchContext->datapath;
 
2346
    ASSERT(datapath);
 
2347
    OvsAcquireDatapathWrite(datapath, &dpLockState, FALSE);
 
2348
    DeleteAllFlows(datapath);
 
2349
    OvsReleaseDatapath(datapath, &dpLockState);
 
2350
 
 
2351
exit:
 
2352
    return status;
 
2353
}
 
2354
 
 
2355
UINT32
 
2356
OvsFlowKeyAttrSize(void)
 
2357
{
 
2358
    return NlAttrTotalSize(4)   /* OVS_KEY_ATTR_PRIORITY */
 
2359
         + NlAttrTotalSize(0)   /* OVS_KEY_ATTR_TUNNEL */
 
2360
         + OvsTunKeyAttrSize()
 
2361
         + NlAttrTotalSize(4)   /* OVS_KEY_ATTR_IN_PORT */
 
2362
         + NlAttrTotalSize(4)   /* OVS_KEY_ATTR_SKB_MARK */
 
2363
         + NlAttrTotalSize(4)   /* OVS_KEY_ATTR_DP_HASH */
 
2364
         + NlAttrTotalSize(4)   /* OVS_KEY_ATTR_RECIRC_ID */
 
2365
         + NlAttrTotalSize(12)  /* OVS_KEY_ATTR_ETHERNET */
 
2366
         + NlAttrTotalSize(2)   /* OVS_KEY_ATTR_ETHERTYPE */
 
2367
         + NlAttrTotalSize(4)   /* OVS_KEY_ATTR_VLAN */
 
2368
         + NlAttrTotalSize(0)   /* OVS_KEY_ATTR_ENCAP */
 
2369
         + NlAttrTotalSize(2)   /* OVS_KEY_ATTR_ETHERTYPE */
 
2370
         + NlAttrTotalSize(40)  /* OVS_KEY_ATTR_IPV6 */
 
2371
         + NlAttrTotalSize(2)   /* OVS_KEY_ATTR_ICMPV6 */
 
2372
         + NlAttrTotalSize(28); /* OVS_KEY_ATTR_ND */
 
2373
}
 
2374
 
 
2375
UINT32
 
2376
OvsTunKeyAttrSize(void)
 
2377
{
 
2378
    /* Whenever adding new OVS_TUNNEL_KEY_ FIELDS, we should consider
 
2379
     * updating this function.
 
2380
     */
 
2381
    return NlAttrTotalSize(8)    /* OVS_TUNNEL_KEY_ATTR_ID */
 
2382
         + NlAttrTotalSize(4)    /* OVS_TUNNEL_KEY_ATTR_IPV4_SRC */
 
2383
         + NlAttrTotalSize(4)    /* OVS_TUNNEL_KEY_ATTR_IPV4_DST */
 
2384
         + NlAttrTotalSize(1)    /* OVS_TUNNEL_KEY_ATTR_TOS */
 
2385
         + NlAttrTotalSize(1)    /* OVS_TUNNEL_KEY_ATTR_TTL */
 
2386
         + NlAttrTotalSize(0)    /* OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT */
 
2387
         + NlAttrTotalSize(0)    /* OVS_TUNNEL_KEY_ATTR_CSUM */
 
2388
         + NlAttrTotalSize(0)    /* OVS_TUNNEL_KEY_ATTR_OAM */
 
2389
         + NlAttrTotalSize(256)  /* OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS */
 
2390
         + NlAttrTotalSize(2)    /* OVS_TUNNEL_KEY_ATTR_TP_SRC */
 
2391
         + NlAttrTotalSize(2);   /* OVS_TUNNEL_KEY_ATTR_TP_DST */
 
2392
}
 
2393
 
 
2394
#pragma warning( pop )