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