2 * Copyright (c) 2014 VMware, Inc.
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:
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 #include "PacketParser.h"
28 #define OVS_DBG_MOD OVS_DBG_FLOW
31 #pragma warning( push )
32 #pragma warning( disable:4127 )
34 extern PNDIS_SPIN_LOCK gOvsCtrlLock;
35 extern POVS_SWITCH_CONTEXT gOvsSwitchContext;
36 extern UINT64 ovsTimeIncrementPerTick;
38 static NTSTATUS ReportFlowInfo(OvsFlow *flow, UINT32 getFlags,
40 static NTSTATUS HandleFlowPut(OvsFlowPut *put,
41 OVS_DATAPATH *datapath,
42 struct OvsFlowStats *stats);
43 static NTSTATUS OvsPrepareFlow(OvsFlow **flow, const OvsFlowPut *put,
45 static VOID RemoveFlow(OVS_DATAPATH *datapath, OvsFlow **flow);
46 static VOID DeleteAllFlows(OVS_DATAPATH *datapath);
47 static NTSTATUS AddFlow(OVS_DATAPATH *datapath, OvsFlow *flow);
48 static VOID FreeFlow(OvsFlow *flow);
49 static VOID __inline *GetStartAddrNBL(const NET_BUFFER_LIST *_pNB);
50 static NTSTATUS _MapNlToFlowPut(POVS_MESSAGE msgIn, PNL_ATTR keyAttr,
52 PNL_ATTR flowAttrClear,
53 OvsFlowPut *mappedFlow);
54 static VOID _MapKeyAttrToFlowPut(PNL_ATTR *keyAttrs,
55 PNL_ATTR *tunnelAttrs,
58 static VOID _MapTunAttrToFlowPut(PNL_ATTR *keyAttrs,
59 PNL_ATTR *tunnelAttrs,
61 static VOID _MapNlToFlowPutFlags(PGENL_MSG_HDR genlMsgHdr,
62 PNL_ATTR flowAttrClear,
63 OvsFlowPut *mappedFlow);
65 static NTSTATUS _FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
67 static NTSTATUS _FlowNlDumpCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
69 static NTSTATUS _MapFlowInfoToNl(PNL_BUFFER nlBuf,
70 OvsFlowInfo *flowInfo);
71 static NTSTATUS _MapFlowKeyToNlKey(PNL_BUFFER nlBuf,
73 static NTSTATUS _MapFlowTunKeyToNlKey(PNL_BUFFER nlBuf,
74 OvsIPv4TunnelKey *tunKey);
75 static NTSTATUS _MapFlowStatsToNlStats(PNL_BUFFER nlBuf,
76 OvsFlowStats *flowStats);
77 static NTSTATUS _MapFlowActionToNlAction(PNL_BUFFER nlBuf,
81 static NTSTATUS _MapFlowIpv4KeyToNlKey(PNL_BUFFER nlBuf,
82 IpKey *ipv4FlowPutKey);
83 static NTSTATUS _MapFlowIpv6KeyToNlKey(PNL_BUFFER nlBuf,
84 Ipv6Key *ipv6FlowPutKey,
85 Icmp6Key *ipv6FlowPutIcmpKey);
86 static NTSTATUS _MapFlowArpKeyToNlKey(PNL_BUFFER nlBuf,
87 ArpKey *arpFlowPutKey);
89 static NTSTATUS OvsDoDumpFlows(OvsFlowDumpInput *dumpInput,
90 OvsFlowDumpOutput *dumpOutput,
94 #define OVS_FLOW_TABLE_SIZE 2048
95 #define OVS_FLOW_TABLE_MASK (OVS_FLOW_TABLE_SIZE -1)
96 #define HASH_BUCKET(hash) ((hash) & OVS_FLOW_TABLE_MASK)
98 /* Flow family related netlink policies */
100 /* For Parsing attributes in FLOW_* commands */
101 static const NL_POLICY nlFlowPolicy[] = {
102 [OVS_FLOW_ATTR_KEY] = {.type = NL_A_NESTED, .optional = FALSE},
103 [OVS_FLOW_ATTR_MASK] = {.type = NL_A_NESTED, .optional = TRUE},
104 [OVS_FLOW_ATTR_ACTIONS] = {.type = NL_A_NESTED, .optional = TRUE},
105 [OVS_FLOW_ATTR_STATS] = {.type = NL_A_UNSPEC,
106 .minLen = sizeof(struct ovs_flow_stats),
107 .maxLen = sizeof(struct ovs_flow_stats),
109 [OVS_FLOW_ATTR_TCP_FLAGS] = {NL_A_U8, .optional = TRUE},
110 [OVS_FLOW_ATTR_USED] = {NL_A_U64, .optional = TRUE}
113 /* For Parsing nested OVS_FLOW_ATTR_KEY attributes.
114 * Some of the attributes like OVS_KEY_ATTR_RECIRC_ID
115 * & OVS_KEY_ATTR_MPLS are not supported yet. */
117 static 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),
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),
135 [OVS_KEY_ATTR_IPV6] = {.type = NL_A_UNSPEC,
136 .minLen = sizeof(struct ovs_key_ipv6),
137 .maxLen = sizeof(struct ovs_key_ipv6),
139 [OVS_KEY_ATTR_TCP] = {.type = NL_A_UNSPEC,
140 .minLen = sizeof(struct ovs_key_tcp),
141 .maxLen = sizeof(struct ovs_key_tcp),
143 [OVS_KEY_ATTR_UDP] = {.type = NL_A_UNSPEC,
144 .minLen = sizeof(struct ovs_key_udp),
145 .maxLen = sizeof(struct ovs_key_udp),
147 [OVS_KEY_ATTR_ICMP] = {.type = NL_A_UNSPEC,
148 .minLen = sizeof(struct ovs_key_icmp),
149 .maxLen = sizeof(struct ovs_key_icmp),
151 [OVS_KEY_ATTR_ICMPV6] = {.type = NL_A_UNSPEC,
152 .minLen = sizeof(struct ovs_key_icmpv6),
153 .maxLen = sizeof(struct ovs_key_icmpv6),
155 [OVS_KEY_ATTR_ARP] = {.type = NL_A_UNSPEC,
156 .minLen = sizeof(struct ovs_key_arp),
157 .maxLen = sizeof(struct ovs_key_arp),
159 [OVS_KEY_ATTR_ND] = {.type = NL_A_UNSPEC,
160 .minLen = sizeof(struct ovs_key_nd),
161 .maxLen = sizeof(struct ovs_key_nd),
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),
170 [OVS_KEY_ATTR_TCP_FLAGS] = {.type = NL_A_UNSPEC,
171 .minLen = 2, .maxLen = 2,
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}
180 /* For Parsing nested OVS_KEY_ATTR_TUNNEL attributes */
181 static const NL_POLICY nlFlowTunnelKeyPolicy[] = {
182 [OVS_TUNNEL_KEY_ATTR_ID] = {.type = NL_A_UNSPEC, .minLen = 8,
183 .maxLen = 8, .optional = TRUE},
184 [OVS_TUNNEL_KEY_ATTR_IPV4_SRC] = {.type = NL_A_UNSPEC, .minLen = 4,
185 .maxLen = 4, .optional = TRUE},
186 [OVS_TUNNEL_KEY_ATTR_IPV4_DST] = {.type = NL_A_UNSPEC, .minLen = 4 ,
187 .maxLen = 4, .optional = FALSE},
188 [OVS_TUNNEL_KEY_ATTR_TOS] = {.type = NL_A_UNSPEC, .minLen = 1,
189 .maxLen = 1, .optional = TRUE},
190 [OVS_TUNNEL_KEY_ATTR_TTL] = {.type = NL_A_UNSPEC, .minLen = 1,
191 .maxLen = 1, .optional = TRUE},
192 [OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT] = {.type = NL_A_UNSPEC, .minLen = 0,
193 .maxLen = 0, .optional = TRUE},
194 [OVS_TUNNEL_KEY_ATTR_CSUM] = {.type = NL_A_UNSPEC, .minLen = 0,
195 .maxLen = 0, .optional = TRUE},
196 [OVS_TUNNEL_KEY_ATTR_OAM] = {.type = NL_A_UNSPEC, .minLen = 0,
197 .maxLen = 0, .optional = TRUE},
198 [OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS] = {.type = NL_A_VAR_LEN,
202 /* For Parsing nested OVS_FLOW_ATTR_ACTIONS attributes */
203 static const NL_POLICY nlFlowActionPolicy[] = {
204 [OVS_ACTION_ATTR_OUTPUT] = {.type = NL_A_UNSPEC, .minLen = sizeof(UINT32),
205 .maxLen = sizeof(UINT32), .optional = TRUE},
206 [OVS_ACTION_ATTR_USERSPACE] = {.type = NL_A_VAR_LEN, .optional = TRUE},
207 [OVS_ACTION_ATTR_PUSH_VLAN] = {.type = NL_A_UNSPEC,
209 sizeof(struct ovs_action_push_vlan),
211 sizeof(struct ovs_action_push_vlan),
213 [OVS_ACTION_ATTR_POP_VLAN] = {.type = NL_A_UNSPEC, .optional = TRUE},
214 [OVS_ACTION_ATTR_PUSH_MPLS] = {.type = NL_A_UNSPEC,
216 sizeof(struct ovs_action_push_mpls),
218 sizeof(struct ovs_action_push_mpls),
220 [OVS_ACTION_ATTR_POP_MPLS] = {.type = NL_A_UNSPEC,
221 .minLen = sizeof(UINT16),
222 .maxLen = sizeof(UINT16),
224 [OVS_ACTION_ATTR_RECIRC] = {.type = NL_A_UNSPEC,
225 .minLen = sizeof(UINT32),
226 .maxLen = sizeof(UINT32),
228 [OVS_ACTION_ATTR_HASH] = {.type = NL_A_UNSPEC,
229 .minLen = sizeof(struct ovs_action_hash),
230 .maxLen = sizeof(struct ovs_action_hash),
232 [OVS_ACTION_ATTR_SET] = {.type = NL_A_VAR_LEN, .optional = TRUE},
233 [OVS_ACTION_ATTR_SAMPLE] = {.type = NL_A_VAR_LEN, .optional = TRUE}
237 *----------------------------------------------------------------------------
238 * Netlink interface for flow commands.
239 *----------------------------------------------------------------------------
243 *----------------------------------------------------------------------------
244 * OvsFlowNewCmdHandler --
245 * Handler for OVS_FLOW_CMD_NEW/SET/DEL command.
246 * It also handles FLUSH case (DEL w/o any key in input)
247 *----------------------------------------------------------------------------
250 OvsFlowNlCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
253 NTSTATUS rc = STATUS_SUCCESS;
254 POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;
255 POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer;
256 PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
257 PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
258 POVS_HDR ovsHdr = &(msgIn->ovsHdr);
259 PNL_ATTR nlAttrs[__OVS_FLOW_ATTR_MAX];
260 UINT32 attrOffset = NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN;
261 OvsFlowPut mappedFlow;
263 struct ovs_flow_stats replyStats;
264 NL_ERROR nlError = NL_ERROR_SUCCESS;
268 RtlZeroMemory(&mappedFlow, sizeof(OvsFlowPut));
269 RtlZeroMemory(&stats, sizeof(stats));
270 RtlZeroMemory(&replyStats, sizeof(replyStats));
274 if (!(usrParamsCtx->outputBuffer)) {
275 /* No output buffer */
276 rc = STATUS_INVALID_BUFFER_SIZE;
280 /* Get all the top level Flow attributes */
281 if ((NlAttrParse(nlMsgHdr, attrOffset, NlMsgAttrsLen(nlMsgHdr),
282 nlFlowPolicy, nlAttrs, ARRAY_SIZE(nlAttrs)))
284 OVS_LOG_ERROR("Attr Parsing failed for msg: %p",
286 rc = STATUS_INVALID_PARAMETER;
290 /* FLOW_DEL command w/o any key input is a flush case. */
291 if ((genlMsgHdr->cmd == OVS_FLOW_CMD_DEL) &&
292 (!(nlAttrs[OVS_FLOW_ATTR_KEY]))) {
293 rc = OvsFlushFlowIoctl(ovsHdr->dp_ifindex);
297 if ((rc = _MapNlToFlowPut(msgIn, nlAttrs[OVS_FLOW_ATTR_KEY],
298 nlAttrs[OVS_FLOW_ATTR_ACTIONS], nlAttrs[OVS_FLOW_ATTR_CLEAR],
301 OVS_LOG_ERROR("Conversion to OvsFlowPut failed");
305 rc = OvsPutFlowIoctl(&mappedFlow, sizeof (struct OvsFlowPut),
307 if (rc != STATUS_SUCCESS) {
308 OVS_LOG_ERROR("OvsFlowPut failed.");
312 replyStats.n_packets = stats.packetCount;
313 replyStats.n_bytes = stats.byteCount;
315 /* So far so good. Prepare the reply for userspace */
316 NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
317 usrParamsCtx->outputLength);
319 /* Prepare nl Msg headers */
320 rc = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,
321 nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
322 genlMsgHdr->cmd, OVS_FLOW_VERSION,
326 /* Append OVS_FLOW_ATTR_STATS attribute */
327 if (!NlMsgPutTailUnspec(&nlBuf, OVS_FLOW_ATTR_STATS,
328 (PCHAR)(&replyStats), sizeof(replyStats))) {
329 OVS_LOG_ERROR("Adding OVS_FLOW_ATTR_STATS attribute failed.");
330 rc = STATUS_INVALID_BUFFER_SIZE;
334 msgOut->nlMsg.nlmsgLen = NLMSG_ALIGN(NlBufSize(&nlBuf));
335 *replyLen = msgOut->nlMsg.nlmsgLen;
339 if ((nlError != NL_ERROR_SUCCESS) &&
340 (usrParamsCtx->outputBuffer)) {
341 POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
342 usrParamsCtx->outputBuffer;
343 BuildErrorMsg(msgIn, msgError, nlError);
344 *replyLen = msgError->nlMsg.nlmsgLen;
351 *----------------------------------------------------------------------------
352 * OvsFlowNlGetCmdHandler --
353 * Handler for OVS_FLOW_CMD_GET/DUMP commands.
354 *----------------------------------------------------------------------------
357 OvsFlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
360 NTSTATUS rc = STATUS_SUCCESS;
361 NL_ERROR nlError = NL_ERROR_SUCCESS;
362 POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;
366 if (!(usrParamsCtx->outputBuffer)) {
367 /* No output buffer */
368 rc = STATUS_INVALID_BUFFER_SIZE;
372 if (usrParamsCtx->devOp == OVS_TRANSACTION_DEV_OP) {
373 rc = _FlowNlGetCmdHandler(usrParamsCtx, replyLen);
375 rc = _FlowNlDumpCmdHandler(usrParamsCtx, replyLen);
378 if ((nlError != NL_ERROR_SUCCESS) &&
379 (usrParamsCtx->outputBuffer)) {
380 POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
381 usrParamsCtx->outputBuffer;
382 BuildErrorMsg(msgIn, msgError, nlError);
383 *replyLen = msgError->nlMsg.nlmsgLen;
391 *----------------------------------------------------------------------------
392 * _FlowNlGetCmdHandler --
393 * Handler for OVS_FLOW_CMD_GET command.
394 *----------------------------------------------------------------------------
397 _FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
400 NTSTATUS rc = STATUS_SUCCESS;
401 POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)
402 (usrParamsCtx->ovsInstance);
403 POVS_MESSAGE msgIn = instance->dumpState.ovsMsg;
404 PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
405 POVS_HDR ovsHdr = &(msgIn->ovsHdr);
406 PNL_MSG_HDR nlMsgOutHdr = NULL;
407 UINT32 attrOffset = NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN;
408 PNL_ATTR nlAttrs[__OVS_FLOW_ATTR_MAX];
410 OvsFlowGetInput getInput;
411 OvsFlowGetOutput getOutput;
413 PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX];
414 PNL_ATTR tunnelAttrs[__OVS_TUNNEL_KEY_ATTR_MAX];
416 NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
417 usrParamsCtx->outputLength);
418 RtlZeroMemory(&getInput, sizeof(OvsFlowGetInput));
419 RtlZeroMemory(&getOutput, sizeof(OvsFlowGetOutput));
420 UINT32 keyAttrOffset = 0;
421 UINT32 tunnelKeyAttrOffset = 0;
425 if (usrParamsCtx->inputLength > usrParamsCtx->outputLength) {
426 /* Should not be the case.
427 * We'll be copying the flow keys back from
428 * input buffer to output buffer. */
429 rc = STATUS_INVALID_PARAMETER;
430 OVS_LOG_ERROR("inputLength: %d GREATER THEN outputLength: %d",
431 usrParamsCtx->inputLength, usrParamsCtx->outputLength);
435 /* Get all the top level Flow attributes */
436 if ((NlAttrParse(nlMsgHdr, attrOffset, NlMsgAttrsLen(nlMsgHdr),
437 nlFlowPolicy, nlAttrs, ARRAY_SIZE(nlAttrs)))
439 OVS_LOG_ERROR("Attr Parsing failed for msg: %p",
441 rc = STATUS_INVALID_PARAMETER;
445 keyAttrOffset = (UINT32)((PCHAR) nlAttrs[OVS_FLOW_ATTR_KEY] -
448 /* Get flow keys attributes */
449 if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset,
450 NlAttrLen(nlAttrs[OVS_FLOW_ATTR_KEY]),
451 nlFlowKeyPolicy, keyAttrs, ARRAY_SIZE(keyAttrs)))
453 OVS_LOG_ERROR("Key Attr Parsing failed for msg: %p",
455 rc = STATUS_INVALID_PARAMETER;
459 if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
460 tunnelKeyAttrOffset = (UINT32)((PCHAR)
461 (keyAttrs[OVS_KEY_ATTR_TUNNEL])
464 /* Get tunnel keys attributes */
465 if ((NlAttrParseNested(nlMsgHdr, tunnelKeyAttrOffset,
466 NlAttrLen(keyAttrs[OVS_KEY_ATTR_TUNNEL]),
467 nlFlowTunnelKeyPolicy,
468 tunnelAttrs, ARRAY_SIZE(tunnelAttrs)))
470 OVS_LOG_ERROR("Tunnel key Attr Parsing failed for msg: %p",
472 rc = STATUS_INVALID_PARAMETER;
477 _MapKeyAttrToFlowPut(keyAttrs, tunnelAttrs,
480 getInput.dpNo = ovsHdr->dp_ifindex;
481 getInput.getFlags = FLOW_GET_STATS | FLOW_GET_ACTIONS;
483 /* 4th argument is a no op.
484 * We are keeping this argument to be compatible
485 * with our dpif-windows based interface. */
486 rc = OvsGetFlowIoctl(&getInput, &getOutput);
487 if (rc != STATUS_SUCCESS) {
488 OVS_LOG_ERROR("OvsGetFlowIoctl failed.");
492 /* Lets prepare the reply. */
493 nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, 0, 0));
495 /* Input already has all the attributes for the flow key.
496 * Lets copy the values back. */
497 RtlCopyMemory(usrParamsCtx->outputBuffer, usrParamsCtx->inputBuffer,
498 usrParamsCtx->inputLength);
500 rc = _MapFlowStatsToNlStats(&nlBuf, &((getOutput.info).stats));
501 if (rc != STATUS_SUCCESS) {
502 OVS_LOG_ERROR("_OvsFlowMapFlowKeyToNlStats failed.");
506 rc = _MapFlowActionToNlAction(&nlBuf, ((getOutput.info).actionsLen),
507 getOutput.info.actions);
508 if (rc != STATUS_SUCCESS) {
509 OVS_LOG_ERROR("_MapFlowActionToNlAction failed.");
513 NlMsgSetSize(nlMsgOutHdr, NlBufSize(&nlBuf));
514 NlMsgAlignSize(nlMsgOutHdr);
515 *replyLen += NlMsgSize(nlMsgOutHdr);
522 *----------------------------------------------------------------------------
523 * _FlowNlDumpCmdHandler --
524 * Handler for OVS_FLOW_CMD_GET command.
525 *----------------------------------------------------------------------------
528 _FlowNlDumpCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
531 NTSTATUS rc = STATUS_SUCCESS;
532 UINT32 temp = 0; /* To keep compiler happy for calling OvsDoDumpFlows */
534 POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)
535 (usrParamsCtx->ovsInstance);
537 if (usrParamsCtx->devOp == OVS_WRITE_DEV_OP) {
539 OvsSetupDumpStart(usrParamsCtx);
543 POVS_MESSAGE msgIn = instance->dumpState.ovsMsg;
544 PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
545 PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
546 POVS_HDR ovsHdr = &(msgIn->ovsHdr);
547 PNL_MSG_HDR nlMsgOutHdr = NULL;
548 UINT32 hdrOffset = 0;
551 OvsFlowDumpOutput dumpOutput;
552 OvsFlowDumpInput dumpInput;
555 NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
556 usrParamsCtx->outputLength);
558 ASSERT(usrParamsCtx->devOp == OVS_READ_DEV_OP);
559 ASSERT(usrParamsCtx->outputLength);
561 RtlZeroMemory(&dumpInput, sizeof(OvsFlowDumpInput));
562 RtlZeroMemory(&dumpOutput, sizeof(OvsFlowDumpOutput));
564 dumpInput.dpNo = ovsHdr->dp_ifindex;
565 dumpInput.getFlags = FLOW_GET_KEY | FLOW_GET_STATS | FLOW_GET_ACTIONS;
567 /* Lets provide as many flows to userspace as possible. */
569 dumpInput.position[0] = instance->dumpState.index[0];
570 dumpInput.position[1] = instance->dumpState.index[1];
572 rc = OvsDoDumpFlows(&dumpInput, &dumpOutput, &temp);
573 if (rc != STATUS_SUCCESS) {
574 OVS_LOG_ERROR("OvsDoDumpFlows failed with rc: %d", rc);
578 /* Done with Dump, send NLMSG_DONE */
579 if (!(dumpOutput.n)) {
580 OVS_LOG_INFO("Dump Done");
582 nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, NlBufSize(&nlBuf), 0));
583 rc = NlFillNlHdr(&nlBuf, NLMSG_DONE, NLM_F_MULTI,
584 nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid);
586 if (rc != STATUS_SUCCESS) {
587 OVS_LOG_ERROR("Unable to prepare DUMP_DONE reply.");
591 NlMsgAlignSize(nlMsgOutHdr);
592 *replyLen += NlMsgSize(nlMsgOutHdr);
594 FreeUserDumpState(instance);
598 hdrOffset = NlBufSize(&nlBuf);
599 nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, hdrOffset, 0));
602 rc = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, NLM_F_MULTI,
603 nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
604 genlMsgHdr->cmd, genlMsgHdr->version,
607 if (rc != STATUS_SUCCESS) {
608 /* Reset rc to success so that we can
609 * send already added messages to user space. */
614 /* Time to add attributes */
615 rc = _MapFlowInfoToNl(&nlBuf, &(dumpOutput.flow));
616 if (rc != STATUS_SUCCESS) {
617 /* Adding the attribute failed, we are out of
618 space in the buffer, remove the appended OVS header */
619 NlMsgSetSize(nlMsgOutHdr,
620 NlMsgSize(nlMsgOutHdr) -
621 sizeof(struct _OVS_MESSAGE));
623 /* Reset rc to success so that we can
624 * send already added messages to user space. */
629 NlMsgSetSize(nlMsgOutHdr, NlBufSize(&nlBuf) - hdrOffset);
630 NlMsgAlignSize(nlMsgOutHdr);
631 *replyLen += NlMsgSize(nlMsgOutHdr);
632 instance->dumpState.index[0] = dumpOutput.position[0];
633 instance->dumpState.index[1] = dumpOutput.position[1];
642 *----------------------------------------------------------------------------
643 * _MapFlowInfoToNl --
644 * Maps OvsFlowInfo to Netlink attributes.
645 *----------------------------------------------------------------------------
648 _MapFlowInfoToNl(PNL_BUFFER nlBuf, OvsFlowInfo *flowInfo)
650 NTSTATUS rc = STATUS_SUCCESS;
652 rc = _MapFlowKeyToNlKey(nlBuf, &(flowInfo->key));
653 if (rc != STATUS_SUCCESS) {
657 rc = _MapFlowStatsToNlStats(nlBuf, &(flowInfo->stats));
658 if (rc != STATUS_SUCCESS) {
662 rc = _MapFlowActionToNlAction(nlBuf, flowInfo->actionsLen,
664 if (rc != STATUS_SUCCESS) {
673 *----------------------------------------------------------------------------
674 * _MapFlowStatsToNlStats --
675 * Maps OvsFlowStats to OVS_FLOW_ATTR_STATS attribute.
676 *----------------------------------------------------------------------------
679 _MapFlowStatsToNlStats(PNL_BUFFER nlBuf, OvsFlowStats *flowStats)
681 NTSTATUS rc = STATUS_SUCCESS;
682 struct ovs_flow_stats replyStats;
684 replyStats.n_packets = flowStats->packetCount;
685 replyStats.n_bytes = flowStats->byteCount;
687 if (!NlMsgPutTailU64(nlBuf, OVS_FLOW_ATTR_USED, flowStats->used)) {
688 rc = STATUS_INVALID_BUFFER_SIZE;
692 if (!NlMsgPutTailUnspec(nlBuf, OVS_FLOW_ATTR_STATS,
693 (PCHAR)(&replyStats),
694 sizeof(struct ovs_flow_stats))) {
695 rc = STATUS_INVALID_BUFFER_SIZE;
699 if (!NlMsgPutTailU8(nlBuf, OVS_FLOW_ATTR_TCP_FLAGS, flowStats->tcpFlags)) {
700 rc = STATUS_INVALID_BUFFER_SIZE;
709 *----------------------------------------------------------------------------
710 * _MapFlowActionToNlAction --
711 * Maps flow actions to OVS_FLOW_ATTR_ACTION attribute.
712 *----------------------------------------------------------------------------
715 _MapFlowActionToNlAction(PNL_BUFFER nlBuf, uint32_t actionsLen,
718 NTSTATUS rc = STATUS_SUCCESS;
721 offset = NlMsgStartNested(nlBuf, OVS_FLOW_ATTR_ACTIONS);
723 /* Starting the nested attribute failed. */
724 rc = STATUS_INVALID_BUFFER_SIZE;
725 goto error_nested_start;
728 if (!NlBufCopyAtTail(nlBuf, (PCHAR)actions, actionsLen)) {
729 /* Adding a nested attribute failed. */
730 rc = STATUS_INVALID_BUFFER_SIZE;
735 NlMsgEndNested(nlBuf, offset);
742 *----------------------------------------------------------------------------
743 * _MapFlowKeyToNlKey --
744 * Maps OvsFlowKey to OVS_FLOW_ATTR_KEY attribute.
745 *----------------------------------------------------------------------------
748 _MapFlowKeyToNlKey(PNL_BUFFER nlBuf, OvsFlowKey *flowKey)
750 NTSTATUS rc = STATUS_SUCCESS;
751 struct ovs_key_ethernet ethKey;
754 offset = NlMsgStartNested(nlBuf, OVS_FLOW_ATTR_KEY);
756 /* Starting the nested attribute failed. */
757 rc = STATUS_UNSUCCESSFUL;
758 goto error_nested_start;
761 /* Ethernet header */
762 RtlCopyMemory(&(ethKey.eth_src), flowKey->l2.dlSrc, ETH_ADDR_LEN);
763 RtlCopyMemory(&(ethKey.eth_dst), flowKey->l2.dlDst, ETH_ADDR_LEN);
765 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ETHERNET,
767 sizeof(struct ovs_key_ethernet))) {
768 rc = STATUS_UNSUCCESSFUL;
772 if (!NlMsgPutTailU32(nlBuf, OVS_KEY_ATTR_IN_PORT,
773 flowKey->l2.inPort)) {
774 rc = STATUS_UNSUCCESSFUL;
778 if (!NlMsgPutTailU16(nlBuf, OVS_KEY_ATTR_ETHERTYPE,
779 htons(flowKey->l2.dlType))) {
780 rc = STATUS_UNSUCCESSFUL;
784 if (flowKey->l2.vlanTci) {
785 if (!NlMsgPutTailU16(nlBuf, OVS_KEY_ATTR_VLAN,
786 flowKey->l2.vlanTci)) {
787 rc = STATUS_UNSUCCESSFUL;
792 /* ==== L3 + L4 ==== */
793 switch (flowKey->l2.dlType) {
794 case ETH_TYPE_IPV4: {
795 IpKey *ipv4FlowPutKey = &(flowKey->ipKey);
796 rc = _MapFlowIpv4KeyToNlKey(nlBuf, ipv4FlowPutKey);
800 case ETH_TYPE_IPV6: {
801 Ipv6Key *ipv6FlowPutKey = &(flowKey->ipv6Key);
802 Icmp6Key *icmpv6FlowPutKey = &(flowKey->icmp6Key);
803 rc = _MapFlowIpv6KeyToNlKey(nlBuf, ipv6FlowPutKey,
809 case ETH_TYPE_RARP: {
810 ArpKey *arpFlowPutKey = &(flowKey->arpKey);
811 rc = _MapFlowArpKeyToNlKey(nlBuf, arpFlowPutKey);
819 if (rc != STATUS_SUCCESS) {
823 if (flowKey->tunKey.dst) {
824 rc = _MapFlowTunKeyToNlKey(nlBuf, &(flowKey->tunKey));
825 if (rc != STATUS_SUCCESS) {
831 NlMsgEndNested(nlBuf, offset);
837 *----------------------------------------------------------------------------
838 * _MapFlowTunKeyToNlKey --
839 * Maps OvsIPv4TunnelKey to OVS_TUNNEL_KEY_ATTR_ID attribute.
840 *----------------------------------------------------------------------------
843 _MapFlowTunKeyToNlKey(PNL_BUFFER nlBuf, OvsIPv4TunnelKey *tunKey)
845 NTSTATUS rc = STATUS_SUCCESS;
848 offset = NlMsgStartNested(nlBuf, OVS_KEY_ATTR_TUNNEL);
850 /* Starting the nested attribute failed. */
851 rc = STATUS_UNSUCCESSFUL;
852 goto error_nested_start;
855 if (!NlMsgPutTailU64(nlBuf, OVS_TUNNEL_KEY_ATTR_ID,
857 rc = STATUS_UNSUCCESSFUL;
861 if (!NlMsgPutTailU32(nlBuf, OVS_TUNNEL_KEY_ATTR_IPV4_DST,
863 rc = STATUS_UNSUCCESSFUL;
867 if (!NlMsgPutTailU32(nlBuf, OVS_TUNNEL_KEY_ATTR_IPV4_SRC,
869 rc = STATUS_UNSUCCESSFUL;
873 if (!NlMsgPutTailU8(nlBuf, OVS_TUNNEL_KEY_ATTR_TOS,
875 rc = STATUS_UNSUCCESSFUL;
879 if (!NlMsgPutTailU8(nlBuf, OVS_TUNNEL_KEY_ATTR_TTL,
881 rc = STATUS_UNSUCCESSFUL;
886 NlMsgEndNested(nlBuf, offset);
892 *----------------------------------------------------------------------------
893 * _MapFlowTunKeyToNlKey --
894 * Maps OvsIPv4FlowPutKey to OVS_KEY_ATTR_IPV4 attribute.
895 *----------------------------------------------------------------------------
898 _MapFlowIpv4KeyToNlKey(PNL_BUFFER nlBuf, IpKey *ipv4FlowPutKey)
900 NTSTATUS rc = STATUS_SUCCESS;
901 struct ovs_key_ipv4 ipv4Key;
903 ipv4Key.ipv4_src = ipv4FlowPutKey->nwSrc;
904 ipv4Key.ipv4_dst = ipv4FlowPutKey->nwDst;
905 ipv4Key.ipv4_proto = ipv4FlowPutKey->nwProto;
906 ipv4Key.ipv4_tos = ipv4FlowPutKey->nwTos;
907 ipv4Key.ipv4_ttl = ipv4FlowPutKey->nwTtl;
908 ipv4Key.ipv4_frag = ipv4FlowPutKey->nwFrag;
910 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_IPV4,
912 sizeof(struct ovs_key_ipv4))) {
913 rc = STATUS_UNSUCCESSFUL;
917 switch (ipv4Key.ipv4_proto) {
919 struct ovs_key_tcp tcpKey;
920 tcpKey.tcp_src = ipv4FlowPutKey->l4.tpSrc;
921 tcpKey.tcp_dst = ipv4FlowPutKey->l4.tpDst;
922 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_TCP,
925 rc = STATUS_UNSUCCESSFUL;
932 struct ovs_key_udp udpKey;
933 udpKey.udp_src = ipv4FlowPutKey->l4.tpSrc;
934 udpKey.udp_dst = ipv4FlowPutKey->l4.tpDst;
935 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_UDP,
938 rc = STATUS_UNSUCCESSFUL;
945 struct ovs_key_sctp sctpKey;
946 sctpKey.sctp_src = ipv4FlowPutKey->l4.tpSrc;
947 sctpKey.sctp_dst = ipv4FlowPutKey->l4.tpDst;
948 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_SCTP,
951 rc = STATUS_UNSUCCESSFUL;
958 struct ovs_key_icmp icmpKey;
959 /* XXX: revisit to see if htons is needed */
960 icmpKey.icmp_type = (__u8)(ipv4FlowPutKey->l4.tpSrc);
961 icmpKey.icmp_code = (__u8)(ipv4FlowPutKey->l4.tpDst);
963 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ICMP,
966 rc = STATUS_UNSUCCESSFUL;
981 *----------------------------------------------------------------------------
982 * _MapFlowIpv6KeyToNlKey --
983 * Maps _MapFlowIpv6KeyToNlKey to OVS_KEY_ATTR_IPV6 attribute.
984 *----------------------------------------------------------------------------
987 _MapFlowIpv6KeyToNlKey(PNL_BUFFER nlBuf, Ipv6Key *ipv6FlowPutKey,
988 Icmp6Key *icmpv6FlowPutKey)
990 NTSTATUS rc = STATUS_SUCCESS;
991 struct ovs_key_ipv6 ipv6Key;
993 RtlCopyMemory(&(ipv6Key.ipv6_src), &ipv6FlowPutKey->ipv6Src,
994 sizeof ipv6Key.ipv6_src);
995 RtlCopyMemory(&(ipv6Key.ipv6_dst), &ipv6FlowPutKey->ipv6Dst,
996 sizeof ipv6Key.ipv6_dst);
998 ipv6Key.ipv6_label = ipv6FlowPutKey->ipv6Label;
999 ipv6Key.ipv6_proto = ipv6FlowPutKey->nwProto;
1000 ipv6Key.ipv6_tclass = ipv6FlowPutKey->nwTos;
1001 ipv6Key.ipv6_hlimit = ipv6FlowPutKey->nwTtl;
1002 ipv6Key.ipv6_frag = ipv6FlowPutKey->nwFrag;
1004 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_IPV6,
1007 rc = STATUS_UNSUCCESSFUL;
1011 switch (ipv6Key.ipv6_proto) {
1013 struct ovs_key_tcp tcpKey;
1014 tcpKey.tcp_src = ipv6FlowPutKey->l4.tpSrc;
1015 tcpKey.tcp_dst = ipv6FlowPutKey->l4.tpDst;
1016 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_TCP,
1019 rc = STATUS_UNSUCCESSFUL;
1026 struct ovs_key_udp udpKey;
1027 udpKey.udp_src = ipv6FlowPutKey->l4.tpSrc;
1028 udpKey.udp_dst = ipv6FlowPutKey->l4.tpDst;
1029 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_UDP,
1032 rc = STATUS_UNSUCCESSFUL;
1038 case IPPROTO_SCTP: {
1039 struct ovs_key_sctp sctpKey;
1040 sctpKey.sctp_src = ipv6FlowPutKey->l4.tpSrc;
1041 sctpKey.sctp_dst = ipv6FlowPutKey->l4.tpDst;
1042 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_SCTP,
1045 rc = STATUS_UNSUCCESSFUL;
1051 case IPPROTO_ICMPV6: {
1052 struct ovs_key_icmpv6 icmpV6Key;
1053 struct ovs_key_nd ndKey;
1055 /* XXX: revisit to see if htons is needed */
1056 icmpV6Key.icmpv6_type = (__u8)(icmpv6FlowPutKey->l4.tpSrc);
1057 icmpV6Key.icmpv6_code = (__u8)(icmpv6FlowPutKey->l4.tpDst);
1059 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ICMPV6,
1060 (PCHAR)(&icmpV6Key),
1061 sizeof(icmpV6Key))) {
1062 rc = STATUS_UNSUCCESSFUL;
1066 RtlCopyMemory(&(ndKey.nd_target), &icmpv6FlowPutKey->ndTarget,
1067 sizeof(icmpv6FlowPutKey->ndTarget));
1068 RtlCopyMemory(&(ndKey.nd_sll), &icmpv6FlowPutKey->arpSha,
1070 RtlCopyMemory(&(ndKey.nd_tll), &icmpv6FlowPutKey->arpTha,
1072 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ND,
1075 rc = STATUS_UNSUCCESSFUL;
1091 *----------------------------------------------------------------------------
1092 * _MapFlowArpKeyToNlKey --
1093 * Maps _MapFlowArpKeyToNlKey to OVS_KEY_ATTR_ARP attribute.
1094 *----------------------------------------------------------------------------
1097 _MapFlowArpKeyToNlKey(PNL_BUFFER nlBuf, ArpKey *arpFlowPutKey)
1099 NTSTATUS rc = STATUS_SUCCESS;
1100 struct ovs_key_arp arpKey;
1102 arpKey.arp_sip = arpFlowPutKey->nwSrc;
1103 arpKey.arp_tip = arpFlowPutKey->nwDst;
1105 RtlCopyMemory(&(arpKey.arp_sha), arpFlowPutKey->arpSha, ETH_ADDR_LEN);
1106 RtlCopyMemory(&(arpKey.arp_tha), arpFlowPutKey->arpTha, ETH_ADDR_LEN);
1108 arpKey.arp_op = arpFlowPutKey->nwProto;
1110 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ARP,
1113 rc = STATUS_UNSUCCESSFUL;
1122 *----------------------------------------------------------------------------
1123 * _MapNlToFlowPut --
1124 * Maps input netlink message to OvsFlowPut.
1125 *----------------------------------------------------------------------------
1128 _MapNlToFlowPut(POVS_MESSAGE msgIn, PNL_ATTR keyAttr,
1129 PNL_ATTR actionAttr, PNL_ATTR flowAttrClear,
1130 OvsFlowPut *mappedFlow)
1132 NTSTATUS rc = STATUS_SUCCESS;
1133 PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
1134 PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
1135 POVS_HDR ovsHdr = &(msgIn->ovsHdr);
1137 UINT32 keyAttrOffset = (UINT32)((PCHAR)keyAttr - (PCHAR)nlMsgHdr);
1138 UINT32 tunnelKeyAttrOffset;
1140 PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX] = {NULL};
1141 PNL_ATTR tunnelAttrs[__OVS_TUNNEL_KEY_ATTR_MAX] = {NULL};
1143 /* Get flow keys attributes */
1144 if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset, NlAttrLen(keyAttr),
1145 nlFlowKeyPolicy, keyAttrs, ARRAY_SIZE(keyAttrs)))
1147 OVS_LOG_ERROR("Key Attr Parsing failed for msg: %p",
1149 rc = STATUS_INVALID_PARAMETER;
1153 if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
1154 tunnelKeyAttrOffset = (UINT32)((PCHAR)
1155 (keyAttrs[OVS_KEY_ATTR_TUNNEL])
1158 OVS_LOG_ERROR("Parse Flow Tunnel Key Policy");
1160 /* Get tunnel keys attributes */
1161 if ((NlAttrParseNested(nlMsgHdr, tunnelKeyAttrOffset,
1162 NlAttrLen(keyAttrs[OVS_KEY_ATTR_TUNNEL]),
1163 nlFlowTunnelKeyPolicy,
1164 tunnelAttrs, ARRAY_SIZE(tunnelAttrs)))
1166 OVS_LOG_ERROR("Tunnel key Attr Parsing failed for msg: %p",
1168 rc = STATUS_INVALID_PARAMETER;
1173 _MapKeyAttrToFlowPut(keyAttrs, tunnelAttrs,
1174 &(mappedFlow->key));
1176 /* Map the action */
1178 mappedFlow->actionsLen = NlAttrGetSize(actionAttr);
1179 mappedFlow->actions = NlAttrGet(actionAttr);
1182 mappedFlow->dpNo = ovsHdr->dp_ifindex;
1184 _MapNlToFlowPutFlags(genlMsgHdr, flowAttrClear,
1192 *----------------------------------------------------------------------------
1193 * _MapNlToFlowPutFlags --
1194 * Maps netlink message to OvsFlowPut->flags.
1195 *----------------------------------------------------------------------------
1198 _MapNlToFlowPutFlags(PGENL_MSG_HDR genlMsgHdr,
1199 PNL_ATTR flowAttrClear, OvsFlowPut *mappedFlow)
1203 switch (genlMsgHdr->cmd) {
1204 case OVS_FLOW_CMD_NEW:
1205 flags |= OVSWIN_FLOW_PUT_CREATE;
1207 case OVS_FLOW_CMD_DEL:
1208 flags |= OVSWIN_FLOW_PUT_DELETE;
1210 case OVS_FLOW_CMD_SET:
1211 flags |= OVSWIN_FLOW_PUT_MODIFY;
1217 if (flowAttrClear) {
1218 flags |= OVSWIN_FLOW_PUT_CLEAR;
1221 mappedFlow->flags = flags;
1225 *----------------------------------------------------------------------------
1226 * _MapKeyAttrToFlowPut --
1227 * Converts FLOW_KEY attribute to OvsFlowPut->key.
1228 *----------------------------------------------------------------------------
1231 _MapKeyAttrToFlowPut(PNL_ATTR *keyAttrs,
1232 PNL_ATTR *tunnelAttrs,
1233 OvsFlowKey *destKey)
1235 const struct ovs_key_ethernet *eth_key;
1237 _MapTunAttrToFlowPut(keyAttrs, tunnelAttrs, destKey);
1239 /* ===== L2 headers ===== */
1240 destKey->l2.inPort = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_IN_PORT]);
1241 eth_key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ETHERNET]);
1242 RtlCopyMemory(destKey->l2.dlSrc, eth_key->eth_src, ETH_ADDR_LEN);
1243 RtlCopyMemory(destKey->l2.dlDst, eth_key->eth_dst, ETH_ADDR_LEN);
1245 destKey->l2.dlType = ntohs((NlAttrGetU16(keyAttrs
1246 [OVS_KEY_ATTR_ETHERTYPE])));
1248 if (keyAttrs[OVS_KEY_ATTR_VLAN]) {
1249 destKey->l2.vlanTci = NlAttrGetU16(keyAttrs
1250 [OVS_KEY_ATTR_VLAN]);
1253 /* ==== L3 + L4. ==== */
1254 destKey->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + OVS_L2_KEY_SIZE
1255 - destKey->l2.offset;
1257 switch (destKey->l2.dlType) {
1258 case ETH_TYPE_IPV4: {
1260 if (keyAttrs[OVS_KEY_ATTR_IPV4]) {
1261 const struct ovs_key_ipv4 *ipv4Key;
1263 ipv4Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_IPV4]);
1264 IpKey *ipv4FlowPutKey = &(destKey->ipKey);
1265 ipv4FlowPutKey->nwSrc = ipv4Key->ipv4_src;
1266 ipv4FlowPutKey->nwDst = ipv4Key->ipv4_dst;
1267 ipv4FlowPutKey->nwProto = ipv4Key->ipv4_proto;
1268 ipv4FlowPutKey->nwTos = ipv4Key->ipv4_tos;
1269 ipv4FlowPutKey->nwTtl = ipv4Key->ipv4_ttl;
1270 ipv4FlowPutKey->nwFrag = ipv4Key->ipv4_frag;
1272 if (keyAttrs[OVS_KEY_ATTR_TCP]) {
1273 const struct ovs_key_tcp *tcpKey;
1274 tcpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_TCP]);
1275 ipv4FlowPutKey->l4.tpSrc = tcpKey->tcp_src;
1276 ipv4FlowPutKey->l4.tpDst = tcpKey->tcp_dst;
1279 if (keyAttrs[OVS_KEY_ATTR_UDP]) {
1280 const struct ovs_key_udp *udpKey;
1281 udpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_UDP]);
1282 ipv4FlowPutKey->l4.tpSrc = udpKey->udp_src;
1283 ipv4FlowPutKey->l4.tpDst = udpKey->udp_dst;
1286 if (keyAttrs[OVS_KEY_ATTR_SCTP]) {
1287 const struct ovs_key_sctp *sctpKey;
1288 sctpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_SCTP]);
1289 ipv4FlowPutKey->l4.tpSrc = sctpKey->sctp_src;
1290 ipv4FlowPutKey->l4.tpDst = sctpKey->sctp_dst;
1293 destKey->l2.keyLen += OVS_IP_KEY_SIZE;
1297 case ETH_TYPE_IPV6: {
1299 if (keyAttrs[OVS_KEY_ATTR_IPV6]) {
1300 const struct ovs_key_ipv6 *ipv6Key;
1302 ipv6Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_IPV6]);
1303 Ipv6Key *ipv6FlowPutKey = &(destKey->ipv6Key);
1305 RtlCopyMemory(&ipv6FlowPutKey->ipv6Src, ipv6Key->ipv6_src,
1306 sizeof ipv6Key->ipv6_src);
1307 RtlCopyMemory(&ipv6FlowPutKey->ipv6Dst, ipv6Key->ipv6_dst,
1308 sizeof ipv6Key->ipv6_dst);
1310 ipv6FlowPutKey->ipv6Label = ipv6Key->ipv6_label;
1311 ipv6FlowPutKey->nwProto = ipv6Key->ipv6_proto;
1312 ipv6FlowPutKey->nwTos = ipv6Key->ipv6_tclass;
1313 ipv6FlowPutKey->nwTtl = ipv6Key->ipv6_hlimit;
1314 ipv6FlowPutKey->nwFrag = ipv6Key->ipv6_frag;
1316 if (keyAttrs[OVS_KEY_ATTR_TCP]) {
1317 const struct ovs_key_tcp *tcpKey;
1318 tcpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_TCP]);
1319 ipv6FlowPutKey->l4.tpSrc = tcpKey->tcp_src;
1320 ipv6FlowPutKey->l4.tpDst = tcpKey->tcp_dst;
1323 if (keyAttrs[OVS_KEY_ATTR_UDP]) {
1324 const struct ovs_key_udp *udpKey;
1325 udpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_UDP]);
1326 ipv6FlowPutKey->l4.tpSrc = udpKey->udp_src;
1327 ipv6FlowPutKey->l4.tpDst = udpKey->udp_dst;
1330 if (keyAttrs[OVS_KEY_ATTR_SCTP]) {
1331 const struct ovs_key_sctp *sctpKey;
1332 sctpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_SCTP]);
1333 ipv6FlowPutKey->l4.tpSrc = sctpKey->sctp_src;
1334 ipv6FlowPutKey->l4.tpDst = sctpKey->sctp_dst;
1337 if (keyAttrs[OVS_KEY_ATTR_ICMPV6]) {
1338 const struct ovs_key_icmpv6 *icmpv6Key;
1340 Icmp6Key *icmp6FlowPutKey= &(destKey->icmp6Key);
1342 icmpv6Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ICMPV6]);
1344 icmp6FlowPutKey->l4.tpSrc = icmpv6Key->icmpv6_type;
1345 icmp6FlowPutKey->l4.tpDst = icmpv6Key->icmpv6_code;
1347 if (keyAttrs[OVS_KEY_ATTR_ND]) {
1348 const struct ovs_key_nd *ndKey;
1350 ndKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ND]);
1351 RtlCopyMemory(&icmp6FlowPutKey->ndTarget,
1352 ndKey->nd_target, sizeof (icmp6FlowPutKey->ndTarget));
1353 RtlCopyMemory(icmp6FlowPutKey->arpSha,
1354 ndKey->nd_sll, ETH_ADDR_LEN);
1355 RtlCopyMemory(icmp6FlowPutKey->arpTha,
1356 ndKey->nd_tll, ETH_ADDR_LEN);
1359 destKey->l2.keyLen += OVS_ICMPV6_KEY_SIZE;
1363 destKey->l2.keyLen += OVS_IPV6_KEY_SIZE;
1366 ipv6FlowPutKey->pad = 0;
1371 case ETH_TYPE_RARP: {
1372 ArpKey *arpFlowPutKey = &destKey->arpKey;
1373 const struct ovs_key_arp *arpKey;
1375 arpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ARP]);
1377 arpFlowPutKey->nwSrc = arpKey->arp_sip;
1378 arpFlowPutKey->nwDst = arpKey->arp_tip;
1380 RtlCopyMemory(arpFlowPutKey->arpSha, arpKey->arp_sha, ETH_ADDR_LEN);
1381 RtlCopyMemory(arpFlowPutKey->arpTha, arpKey->arp_tha, ETH_ADDR_LEN);
1382 arpFlowPutKey->nwProto = (UINT8)(arpKey->arp_op);
1383 arpFlowPutKey->pad[0] = 0;
1384 arpFlowPutKey->pad[1] = 0;
1385 arpFlowPutKey->pad[2] = 0;
1386 destKey->l2.keyLen += OVS_ARP_KEY_SIZE;
1393 *----------------------------------------------------------------------------
1394 * _MapTunAttrToFlowPut --
1395 * Converts FLOW_TUNNEL_KEY attribute to OvsFlowKey->tunKey.
1396 *----------------------------------------------------------------------------
1399 _MapTunAttrToFlowPut(PNL_ATTR *keyAttrs,
1401 OvsFlowKey *destKey)
1403 if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
1405 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_ID]) {
1406 destKey->tunKey.tunnelId = NlAttrGetU64
1407 (tunAttrs[OVS_TUNNEL_KEY_ATTR_ID]);
1408 destKey->tunKey.flags |= OVS_TNL_F_KEY;
1411 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_DST]) {
1412 destKey->tunKey.dst = NlAttrGetU32
1413 (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_DST]);
1416 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_SRC]) {
1417 destKey->tunKey.src = NlAttrGetU32
1418 (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_SRC]);
1421 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT]) {
1422 destKey->tunKey.flags |= OVS_TNL_F_DONT_FRAGMENT;
1425 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_CSUM]) {
1426 destKey->tunKey.flags |= OVS_TNL_F_CSUM;
1429 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_TOS]) {
1430 destKey->tunKey.tos = NlAttrGetU8
1431 (tunAttrs[OVS_TUNNEL_KEY_ATTR_TOS]);
1434 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_TTL]) {
1435 destKey->tunKey.ttl = NlAttrGetU8
1436 (tunAttrs[OVS_TUNNEL_KEY_ATTR_TTL]);
1439 destKey->tunKey.pad = 0;
1440 destKey->l2.offset = 0;
1442 destKey->tunKey.attr[0] = 0;
1443 destKey->tunKey.attr[1] = 0;
1444 destKey->tunKey.attr[2] = 0;
1445 destKey->l2.offset = sizeof destKey->tunKey;
1450 *----------------------------------------------------------------------------
1451 * OvsDeleteFlowTable --
1453 * NDIS_STATUS_SUCCESS always.
1454 *----------------------------------------------------------------------------
1457 OvsDeleteFlowTable(OVS_DATAPATH *datapath)
1459 if (datapath == NULL || datapath->flowTable == NULL) {
1460 return NDIS_STATUS_SUCCESS;
1463 DeleteAllFlows(datapath);
1464 OvsFreeMemory(datapath->flowTable);
1465 datapath->flowTable = NULL;
1466 NdisFreeRWLock(datapath->lock);
1468 return NDIS_STATUS_SUCCESS;
1472 *----------------------------------------------------------------------------
1473 * OvsAllocateFlowTable --
1475 * NDIS_STATUS_SUCCESS on success.
1476 * NDIS_STATUS_RESOURCES if memory couldn't be allocated
1477 *----------------------------------------------------------------------------
1480 OvsAllocateFlowTable(OVS_DATAPATH *datapath,
1481 POVS_SWITCH_CONTEXT switchContext)
1486 datapath->flowTable = OvsAllocateMemory(OVS_FLOW_TABLE_SIZE *
1487 sizeof (LIST_ENTRY));
1488 if (!datapath->flowTable) {
1489 return NDIS_STATUS_RESOURCES;
1491 for (i = 0; i < OVS_FLOW_TABLE_SIZE; i++) {
1492 bucket = &(datapath->flowTable[i]);
1493 InitializeListHead(bucket);
1495 datapath->lock = NdisAllocateRWLock(switchContext->NdisFilterHandle);
1497 return NDIS_STATUS_SUCCESS;
1502 *----------------------------------------------------------------------------
1503 * GetStartAddrNBL --
1504 * Get the virtual address of the frame.
1507 * Virtual address of the frame.
1508 *----------------------------------------------------------------------------
1510 static __inline VOID *
1511 GetStartAddrNBL(const NET_BUFFER_LIST *_pNB)
1519 // Ethernet Header is a guaranteed safe access.
1520 curMdl = (NET_BUFFER_LIST_FIRST_NB(_pNB))->CurrentMdl;
1521 curBuffer = MmGetSystemAddressForMdlSafe(curMdl, LowPagePriority);
1526 curHeader = (PEthHdr)
1527 (curBuffer + (NET_BUFFER_LIST_FIRST_NB(_pNB))->CurrentMdlOffset);
1529 return (VOID *) curHeader;
1533 OvsFlowUsed(OvsFlow *flow,
1534 const NET_BUFFER_LIST *packet,
1535 const POVS_PACKET_HDR_INFO layers)
1537 LARGE_INTEGER tickCount;
1539 KeQueryTickCount(&tickCount);
1540 flow->used = tickCount.QuadPart * ovsTimeIncrementPerTick;
1541 flow->packetCount++;
1542 flow->byteCount += OvsPacketLenNBL(packet);
1543 flow->tcpFlags |= OvsGetTcpFlags(packet, &flow->key, layers);
1548 DeleteAllFlows(OVS_DATAPATH *datapath)
1553 for (i = 0; i < OVS_FLOW_TABLE_SIZE; i++) {
1555 bucket = &(datapath->flowTable[i]);
1556 while (!IsListEmpty(bucket)) {
1558 next = bucket->Flink;
1559 flow = CONTAINING_RECORD(next, OvsFlow, ListEntry);
1560 RemoveFlow(datapath, &flow);
1566 *----------------------------------------------------------------------------
1567 * Initializes 'flow' members from 'packet', 'skb_priority', 'tun_id', and
1570 * Initializes 'packet' header pointers as follows:
1572 * - packet->l2 to the start of the Ethernet header.
1574 * - packet->l3 to just past the Ethernet header, or just past the
1575 * vlan_header if one is present, to the first byte of the payload of the
1578 * - packet->l4 to just past the IPv4 header, if one is present and has a
1579 * correct length, and otherwise NULL.
1581 * - packet->l7 to just past the TCP or UDP or ICMP header, if one is
1582 * present and has a correct length, and otherwise NULL.
1584 * Returns NDIS_STATUS_SUCCESS normally. Fails only if packet data cannot be accessed
1585 * (e.g. if Pkt_CopyBytesOut() returns an error).
1586 *----------------------------------------------------------------------------
1589 OvsExtractFlow(const NET_BUFFER_LIST *packet,
1592 POVS_PACKET_HDR_INFO layers,
1593 OvsIPv4TunnelKey *tunKey)
1595 struct Eth_Header *eth;
1602 ASSERT(tunKey->dst != 0);
1603 RtlMoveMemory(&flow->tunKey, tunKey, sizeof flow->tunKey);
1604 flow->l2.offset = 0;
1606 flow->tunKey.dst = 0;
1607 flow->l2.offset = OVS_WIN_TUNNEL_KEY_SIZE;
1610 flow->l2.inPort = inPort;
1612 if ( OvsPacketLenNBL(packet) < ETH_HEADER_LEN_DIX) {
1613 flow->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + 8 - flow->l2.offset;
1614 return NDIS_STATUS_SUCCESS;
1618 eth = (Eth_Header *)GetStartAddrNBL((NET_BUFFER_LIST *)packet);
1619 memcpy(flow->l2.dlSrc, eth->src, ETH_ADDR_LENGTH);
1620 memcpy(flow->l2.dlDst, eth->dst, ETH_ADDR_LENGTH);
1625 vlanTagValue = NET_BUFFER_LIST_INFO(packet, Ieee8021QNetBufferListInfo);
1627 PNDIS_NET_BUFFER_LIST_8021Q_INFO vlanTag =
1628 (PNDIS_NET_BUFFER_LIST_8021Q_INFO)(PVOID *)&vlanTagValue;
1629 flow->l2.vlanTci = htons(vlanTag->TagHeader.VlanId | OVSWIN_VLAN_CFI |
1630 (vlanTag->TagHeader.UserPriority << 13));
1632 if (eth->dix.typeNBO == ETH_TYPE_802_1PQ_NBO) {
1633 Eth_802_1pq_Tag *tag= (Eth_802_1pq_Tag *)ð->dix.typeNBO;
1634 flow->l2.vlanTci = ((UINT16)tag->priority << 13) |
1636 ((UINT16)tag->vidHi << 8) | tag->vidLo;
1637 offset = sizeof (Eth_802_1pq_Tag);
1639 flow->l2.vlanTci = 0;
1643 * Please note after this point, src mac and dst mac should
1644 * not be accessed through eth
1646 eth = (Eth_Header *)((UINT8 *)eth + offset);
1652 * XXX assume that at least the first
1653 * 12 bytes of received packets are mapped. This code has the stronger
1654 * assumption that at least the first 22 bytes of 'packet' is mapped (if my
1655 * arithmetic is right).
1657 if (ETH_TYPENOT8023(eth->dix.typeNBO)) {
1658 flow->l2.dlType = eth->dix.typeNBO;
1659 layers->l3Offset = ETH_HEADER_LEN_DIX + offset;
1660 } else if (OvsPacketLenNBL(packet) >= ETH_HEADER_LEN_802_3 &&
1661 eth->e802_3.llc.dsap == 0xaa &&
1662 eth->e802_3.llc.ssap == 0xaa &&
1663 eth->e802_3.llc.control == ETH_LLC_CONTROL_UFRAME &&
1664 eth->e802_3.snap.snapOrg[0] == 0x00 &&
1665 eth->e802_3.snap.snapOrg[1] == 0x00 &&
1666 eth->e802_3.snap.snapOrg[2] == 0x00) {
1667 flow->l2.dlType = eth->e802_3.snap.snapType.typeNBO;
1668 layers->l3Offset = ETH_HEADER_LEN_802_3 + offset;
1670 flow->l2.dlType = htons(OVSWIN_DL_TYPE_NONE);
1671 layers->l3Offset = ETH_HEADER_LEN_DIX + offset;
1674 flow->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + OVS_L2_KEY_SIZE - flow->l2.offset;
1675 /* Network layer. */
1676 if (flow->l2.dlType == htons(ETH_TYPE_IPV4)) {
1677 struct IPHdr ip_storage;
1678 const struct IPHdr *nh;
1679 IpKey *ipKey = &flow->ipKey;
1681 flow->l2.keyLen += OVS_IP_KEY_SIZE;
1683 nh = OvsGetIp(packet, layers->l3Offset, &ip_storage);
1685 layers->l4Offset = layers->l3Offset + nh->ihl * 4;
1687 ipKey->nwSrc = nh->saddr;
1688 ipKey->nwDst = nh->daddr;
1689 ipKey->nwProto = nh->protocol;
1691 ipKey->nwTos = nh->tos;
1692 if (nh->frag_off & htons(IP_MF | IP_OFFSET)) {
1693 ipKey->nwFrag = OVSWIN_NW_FRAG_ANY;
1694 if (nh->frag_off & htons(IP_OFFSET)) {
1695 ipKey->nwFrag |= OVSWIN_NW_FRAG_LATER;
1701 ipKey->nwTtl = nh->ttl;
1702 ipKey->l4.tpSrc = 0;
1703 ipKey->l4.tpDst = 0;
1705 if (!(nh->frag_off & htons(IP_OFFSET))) {
1706 if (ipKey->nwProto == SOCKET_IPPROTO_TCP) {
1707 OvsParseTcp(packet, &ipKey->l4, layers);
1708 } else if (ipKey->nwProto == SOCKET_IPPROTO_UDP) {
1709 OvsParseUdp(packet, &ipKey->l4, layers);
1710 } else if (ipKey->nwProto == SOCKET_IPPROTO_ICMP) {
1711 ICMPHdr icmpStorage;
1712 const ICMPHdr *icmp;
1714 icmp = OvsGetIcmp(packet, layers->l4Offset, &icmpStorage);
1716 ipKey->l4.tpSrc = htons(icmp->type);
1717 ipKey->l4.tpDst = htons(icmp->code);
1718 layers->l7Offset = layers->l4Offset + sizeof *icmp;
1723 ((UINT64 *)ipKey)[0] = 0;
1724 ((UINT64 *)ipKey)[1] = 0;
1726 } else if (flow->l2.dlType == htons(ETH_TYPE_IPV6)) {
1728 flow->l2.keyLen += OVS_IPV6_KEY_SIZE;
1729 status = OvsParseIPv6(packet, flow, layers);
1730 if (status != NDIS_STATUS_SUCCESS) {
1731 memset(&flow->ipv6Key, 0, sizeof (Ipv6Key));
1735 flow->ipv6Key.l4.tpSrc = 0;
1736 flow->ipv6Key.l4.tpDst = 0;
1737 flow->ipv6Key.pad = 0;
1739 if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_TCP) {
1740 OvsParseTcp(packet, &(flow->ipv6Key.l4), layers);
1741 } else if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_UDP) {
1742 OvsParseUdp(packet, &(flow->ipv6Key.l4), layers);
1743 } else if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_ICMPV6) {
1744 OvsParseIcmpV6(packet, flow, layers);
1745 flow->l2.keyLen += (OVS_ICMPV6_KEY_SIZE - OVS_IPV6_KEY_SIZE);
1747 } else if (flow->l2.dlType == htons(ETH_TYPE_ARP)) {
1748 EtherArp arpStorage;
1749 const EtherArp *arp;
1750 ArpKey *arpKey = &flow->arpKey;
1751 ((UINT64 *)arpKey)[0] = 0;
1752 ((UINT64 *)arpKey)[1] = 0;
1753 ((UINT64 *)arpKey)[2] = 0;
1754 flow->l2.keyLen += OVS_ARP_KEY_SIZE;
1755 arp = OvsGetArp(packet, layers->l3Offset, &arpStorage);
1756 if (arp && arp->ea_hdr.ar_hrd == htons(1) &&
1757 arp->ea_hdr.ar_pro == htons(ETH_TYPE_IPV4) &&
1758 arp->ea_hdr.ar_hln == ETH_ADDR_LENGTH &&
1759 arp->ea_hdr.ar_pln == 4) {
1760 /* We only match on the lower 8 bits of the opcode. */
1761 if (ntohs(arp->ea_hdr.ar_op) <= 0xff) {
1762 arpKey->nwProto = (UINT8)ntohs(arp->ea_hdr.ar_op);
1764 if (arpKey->nwProto == ARPOP_REQUEST
1765 || arpKey->nwProto == ARPOP_REPLY) {
1766 memcpy(&arpKey->nwSrc, arp->arp_spa, 4);
1767 memcpy(&arpKey->nwDst, arp->arp_tpa, 4);
1768 memcpy(arpKey->arpSha, arp->arp_sha, ETH_ADDR_LENGTH);
1769 memcpy(arpKey->arpTha, arp->arp_tha, ETH_ADDR_LENGTH);
1774 return NDIS_STATUS_SUCCESS;
1778 FlowEqual(UINT64 *src, UINT64 *dst, UINT32 size)
1781 ASSERT((size & 0x7) == 0);
1782 ASSERT(((UINT64)src & 0x7) == 0);
1783 ASSERT(((UINT64)dst & 0x7) == 0);
1784 for (i = 0; i < (size >> 3); i++) {
1785 if (src[i] != dst[i]) {
1794 * ----------------------------------------------------------------------------
1796 * Add a flow to flow table.
1799 * NDIS_STATUS_SUCCESS if no same flow in the flow table.
1800 * ----------------------------------------------------------------------------
1803 AddFlow(OVS_DATAPATH *datapath, OvsFlow *flow)
1807 if (OvsLookupFlow(datapath, &flow->key, &flow->hash, TRUE) != NULL) {
1808 return STATUS_INVALID_HANDLE;
1811 head = &(datapath->flowTable[HASH_BUCKET(flow->hash)]);
1813 * We need fence here to make sure flow's nextPtr is updated before
1814 * head->nextPtr is updated.
1818 //KeAcquireSpinLock(&FilterDeviceExtension->NblQueueLock, &oldIrql);
1819 InsertTailList(head, &flow->ListEntry);
1820 //KeReleaseSpinLock(&FilterDeviceExtension->NblQueueLock, oldIrql);
1824 return STATUS_SUCCESS;
1828 /* ----------------------------------------------------------------------------
1830 * Remove a flow from flow table, and added to wait list
1831 * ----------------------------------------------------------------------------
1834 RemoveFlow(OVS_DATAPATH *datapath,
1839 UNREFERENCED_PARAMETER(datapath);
1841 ASSERT(datapath->nFlows);
1843 // Remove the flow from queue
1844 RemoveEntryList(&f->ListEntry);
1850 * ----------------------------------------------------------------------------
1853 * Find flow from flow table based on flow key.
1854 * Caller should either hold portset handle or should
1855 * have a flowRef in datapath or Acquired datapath.
1858 * Flow pointer if lookup successful.
1859 * NULL if not exists.
1860 * ----------------------------------------------------------------------------
1863 OvsLookupFlow(OVS_DATAPATH *datapath,
1864 const OvsFlowKey *key,
1868 PLIST_ENTRY link, head;
1869 UINT16 offset = key->l2.offset;
1870 UINT16 size = key->l2.keyLen;
1873 ASSERT(key->tunKey.dst || offset == sizeof (OvsIPv4TunnelKey));
1874 ASSERT(!key->tunKey.dst || offset == 0);
1876 start = (UINT8 *)key + offset;
1879 *hash = OvsJhashBytes(start, size, 0);
1882 head = &datapath->flowTable[HASH_BUCKET(*hash)];
1884 while (link != head) {
1885 OvsFlow *flow = CONTAINING_RECORD(link, OvsFlow, ListEntry);
1887 if (flow->hash == *hash &&
1888 flow->key.l2.val == key->l2.val &&
1889 FlowEqual((UINT64 *)((uint8 *)&flow->key + offset),
1890 (UINT64 *)start, size)) {
1900 * ----------------------------------------------------------------------------
1902 * Calculate the hash for the given flow key.
1903 * ----------------------------------------------------------------------------
1906 OvsHashFlow(const OvsFlowKey *key)
1908 UINT16 offset = key->l2.offset;
1909 UINT16 size = key->l2.keyLen;
1912 ASSERT(key->tunKey.dst || offset == sizeof (OvsIPv4TunnelKey));
1913 ASSERT(!key->tunKey.dst || offset == 0);
1914 start = (UINT8 *)key + offset;
1915 return OvsJhashBytes(start, size, 0);
1920 * ----------------------------------------------------------------------------
1922 * Free a flow and its actions.
1923 * ----------------------------------------------------------------------------
1926 FreeFlow(OvsFlow *flow)
1929 OvsFreeMemory(flow);
1933 OvsDoDumpFlows(OvsFlowDumpInput *dumpInput,
1934 OvsFlowDumpOutput *dumpOutput,
1938 OVS_DATAPATH *datapath = NULL;
1940 PLIST_ENTRY node, head;
1942 UINT32 rowIndex, columnIndex;
1943 LOCK_STATE_EX dpLockState;
1944 NTSTATUS status = STATUS_SUCCESS;
1945 BOOLEAN findNextNonEmpty = FALSE;
1947 dpNo = dumpInput->dpNo;
1948 NdisAcquireSpinLock(gOvsCtrlLock);
1949 if (gOvsSwitchContext == NULL ||
1950 gOvsSwitchContext->dpNo != dpNo) {
1951 status = STATUS_INVALID_PARAMETER;
1955 rowIndex = dumpInput->position[0];
1956 if (rowIndex >= OVS_FLOW_TABLE_SIZE) {
1958 *replyLen = sizeof(*dumpOutput);
1962 columnIndex = dumpInput->position[1];
1964 datapath = &gOvsSwitchContext->datapath;
1966 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
1967 OvsAcquireDatapathRead(datapath, &dpLockState, TRUE);
1969 head = &datapath->flowTable[rowIndex];
1972 while (column < columnIndex) {
1981 findNextNonEmpty = TRUE;
1985 if (findNextNonEmpty) {
1986 while (head == node) {
1987 if (++rowIndex >= OVS_FLOW_TABLE_SIZE) {
1991 head = &datapath->flowTable[rowIndex];
1996 ASSERT(node != head);
1997 ASSERT(rowIndex < OVS_FLOW_TABLE_SIZE);
1999 flow = CONTAINING_RECORD(node, OvsFlow, ListEntry);
2000 status = ReportFlowInfo(flow, dumpInput->getFlags, &dumpOutput->flow);
2002 if (status == STATUS_BUFFER_TOO_SMALL) {
2003 dumpOutput->n = sizeof(OvsFlowDumpOutput) + flow->actionsLen;
2004 *replyLen = sizeof(*dumpOutput);
2006 dumpOutput->n = 1; //one flow reported.
2007 *replyLen = sizeof(*dumpOutput) + dumpOutput->flow.actionsLen;
2010 dumpOutput->position[0] = rowIndex;
2011 dumpOutput->position[1] = ++columnIndex;
2014 OvsReleaseDatapath(datapath, &dpLockState);
2017 NdisReleaseSpinLock(gOvsCtrlLock);
2022 OvsDumpFlowIoctl(PVOID inputBuffer,
2025 UINT32 outputLength,
2028 OvsFlowDumpOutput *dumpOutput = (OvsFlowDumpOutput *)outputBuffer;
2029 OvsFlowDumpInput *dumpInput = (OvsFlowDumpInput *)inputBuffer;
2031 if (inputBuffer == NULL || outputBuffer == NULL) {
2032 return STATUS_INVALID_PARAMETER;
2035 if ((inputLength != sizeof(OvsFlowDumpInput))
2036 || (outputLength != sizeof *dumpOutput + dumpInput->actionsLen)) {
2037 return STATUS_INFO_LENGTH_MISMATCH;
2040 return OvsDoDumpFlows(dumpInput, dumpOutput, replyLen);
2044 ReportFlowInfo(OvsFlow *flow,
2048 NTSTATUS status = STATUS_SUCCESS;
2050 if (getFlags & FLOW_GET_KEY) {
2051 // always copy the tunnel key part
2052 RtlCopyMemory(&info->key, &flow->key,
2053 flow->key.l2.keyLen + flow->key.l2.offset);
2056 if (getFlags & FLOW_GET_STATS) {
2057 OvsFlowStats *stats = &info->stats;
2058 stats->packetCount = flow->packetCount;
2059 stats->byteCount = flow->byteCount;
2060 stats->used = (UINT32)flow->used;
2061 stats->tcpFlags = flow->tcpFlags;
2064 if (getFlags & FLOW_GET_ACTIONS) {
2065 if (flow->actionsLen == 0) {
2066 info->actionsLen = 0;
2068 info->actions = flow->actions;
2069 info->actionsLen = flow->actionsLen;
2077 OvsPutFlowIoctl(PVOID inputBuffer,
2079 struct OvsFlowStats *stats)
2081 NTSTATUS status = STATUS_SUCCESS;
2082 OVS_DATAPATH *datapath = NULL;
2086 LOCK_STATE_EX dpLockState;
2088 if ((inputLength < sizeof(OvsFlowPut)) || (inputBuffer == NULL)) {
2089 return STATUS_INFO_LENGTH_MISMATCH;
2092 put = (OvsFlowPut *)inputBuffer;
2093 if (put->actionsLen > 0) {
2094 actionsLen = put->actionsLen;
2100 NdisAcquireSpinLock(gOvsCtrlLock);
2101 if (gOvsSwitchContext == NULL ||
2102 gOvsSwitchContext->dpNo != dpNo) {
2103 status = STATUS_INVALID_PARAMETER;
2107 datapath = &gOvsSwitchContext->datapath;
2109 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
2110 OvsAcquireDatapathWrite(datapath, &dpLockState, TRUE);
2111 status = HandleFlowPut(put, datapath, stats);
2112 OvsReleaseDatapath(datapath, &dpLockState);
2115 NdisReleaseSpinLock(gOvsCtrlLock);
2120 /* Handles flow add, modify as well as delete */
2122 HandleFlowPut(OvsFlowPut *put,
2123 OVS_DATAPATH *datapath,
2124 struct OvsFlowStats *stats)
2126 BOOLEAN mayCreate, mayModify, mayDelete;
2127 OvsFlow *KernelFlow;
2129 NTSTATUS status = STATUS_SUCCESS;
2131 mayCreate = (put->flags & OVSWIN_FLOW_PUT_CREATE) != 0;
2132 mayModify = (put->flags & OVSWIN_FLOW_PUT_MODIFY) != 0;
2133 mayDelete = (put->flags & OVSWIN_FLOW_PUT_DELETE) != 0;
2135 if ((mayCreate || mayModify) == mayDelete) {
2136 return STATUS_INVALID_PARAMETER;
2139 KernelFlow = OvsLookupFlow(datapath, &put->key, &hash, FALSE);
2142 return STATUS_INVALID_PARAMETER;
2145 status = OvsPrepareFlow(&KernelFlow, put, hash);
2146 if (status != STATUS_SUCCESS) {
2147 FreeFlow(KernelFlow);
2148 return STATUS_UNSUCCESSFUL;
2151 status = AddFlow(datapath, KernelFlow);
2152 if (status != STATUS_SUCCESS) {
2153 FreeFlow(KernelFlow);
2154 return STATUS_UNSUCCESSFUL;
2157 /* Validate the flow addition */
2160 OvsFlow *flow = OvsLookupFlow(datapath, &put->key, &newHash,
2163 ASSERT(newHash == hash);
2164 if (!flow || newHash != hash) {
2165 return STATUS_UNSUCCESSFUL;
2169 stats->packetCount = KernelFlow->packetCount;
2170 stats->byteCount = KernelFlow->byteCount;
2171 stats->tcpFlags = KernelFlow->tcpFlags;
2172 stats->used = (UINT32)KernelFlow->used;
2176 status = OvsPrepareFlow(&newFlow, put, hash);
2177 if (status != STATUS_SUCCESS) {
2178 return STATUS_UNSUCCESSFUL;
2181 KernelFlow = OvsLookupFlow(datapath, &put->key, &hash, TRUE);
2183 if ((put->flags & OVSWIN_FLOW_PUT_CLEAR) == 0) {
2184 newFlow->packetCount = KernelFlow->packetCount;
2185 newFlow->byteCount = KernelFlow->byteCount;
2186 newFlow->tcpFlags = KernelFlow->tcpFlags;
2188 RemoveFlow(datapath, &KernelFlow);
2190 if ((put->flags & OVSWIN_FLOW_PUT_CLEAR) == 0) {
2191 newFlow->packetCount = stats->packetCount;
2192 newFlow->byteCount = stats->byteCount;
2193 newFlow->tcpFlags = stats->tcpFlags;
2196 status = AddFlow(datapath, newFlow);
2197 ASSERT(status == STATUS_SUCCESS);
2199 /* Validate the flow addition */
2202 OvsFlow *testflow = OvsLookupFlow(datapath, &put->key,
2205 ASSERT(newHash == hash);
2206 if (!testflow || newHash != hash) {
2208 return STATUS_UNSUCCESSFUL;
2214 RemoveFlow(datapath, &KernelFlow);
2217 return STATUS_UNSUCCESSFUL;
2221 return STATUS_SUCCESS;
2225 OvsPrepareFlow(OvsFlow **flow,
2226 const OvsFlowPut *put,
2229 OvsFlow *localFlow = *flow;
2230 NTSTATUS status = STATUS_SUCCESS;
2234 OvsAllocateMemory(sizeof(OvsFlow) + put->actionsLen);
2235 if (localFlow == NULL) {
2236 status = STATUS_NO_MEMORY;
2240 localFlow->key = put->key;
2241 localFlow->actionsLen = put->actionsLen;
2242 if (put->actionsLen) {
2243 NdisMoveMemory((PUCHAR)localFlow->actions, put->actions,
2246 localFlow->userActionsLen = 0; // 0 indicate no conversion is made
2247 localFlow->used = 0;
2248 localFlow->packetCount = 0;
2249 localFlow->byteCount = 0;
2250 localFlow->tcpFlags = 0;
2251 localFlow->hash = hash;
2258 OvsGetFlowIoctl(PVOID inputBuffer,
2261 NTSTATUS status = STATUS_SUCCESS;
2262 OVS_DATAPATH *datapath = NULL;
2264 UINT32 getFlags, getActionsLen;
2265 OvsFlowGetInput *getInput;
2266 OvsFlowGetOutput *getOutput;
2269 LOCK_STATE_EX dpLockState;
2271 getInput = (OvsFlowGetInput *) inputBuffer;
2272 getFlags = getInput->getFlags;
2273 getActionsLen = getInput->actionsLen;
2275 if (outputBuffer == NULL) {
2276 return STATUS_INFO_LENGTH_MISMATCH;
2279 dpNo = getInput->dpNo;
2280 NdisAcquireSpinLock(gOvsCtrlLock);
2281 if (gOvsSwitchContext == NULL ||
2282 gOvsSwitchContext->dpNo != dpNo) {
2283 status = STATUS_INVALID_PARAMETER;
2287 datapath = &gOvsSwitchContext->datapath;
2289 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
2290 OvsAcquireDatapathRead(datapath, &dpLockState, TRUE);
2291 flow = OvsLookupFlow(datapath, &getInput->key, &hash, FALSE);
2293 status = STATUS_INVALID_PARAMETER;
2297 getOutput = (OvsFlowGetOutput *)outputBuffer;
2298 ReportFlowInfo(flow, getFlags, &getOutput->info);
2301 OvsReleaseDatapath(datapath, &dpLockState);
2303 NdisReleaseSpinLock(gOvsCtrlLock);
2308 OvsFlushFlowIoctl(UINT32 dpNo)
2310 NTSTATUS status = STATUS_SUCCESS;
2311 OVS_DATAPATH *datapath = NULL;
2312 LOCK_STATE_EX dpLockState;
2314 NdisAcquireSpinLock(gOvsCtrlLock);
2315 if (gOvsSwitchContext == NULL ||
2316 gOvsSwitchContext->dpNo != dpNo) {
2317 status = STATUS_INVALID_PARAMETER;
2321 datapath = &gOvsSwitchContext->datapath;
2323 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
2324 OvsAcquireDatapathWrite(datapath, &dpLockState, TRUE);
2325 DeleteAllFlows(datapath);
2326 OvsReleaseDatapath(datapath, &dpLockState);
2329 NdisReleaseSpinLock(gOvsCtrlLock);
2333 #pragma warning( pop )