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