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