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