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