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