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