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