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