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