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