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 POVS_SWITCH_CONTEXT gOvsSwitchContext;
35 extern UINT64 ovsTimeIncrementPerTick;
37 static NTSTATUS ReportFlowInfo(OvsFlow *flow, UINT32 getFlags,
39 static NTSTATUS HandleFlowPut(OvsFlowPut *put,
40 OVS_DATAPATH *datapath,
41 struct OvsFlowStats *stats);
42 static NTSTATUS OvsPrepareFlow(OvsFlow **flow, const OvsFlowPut *put,
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,
51 PNL_ATTR flowAttrClear,
52 OvsFlowPut *mappedFlow);
53 static VOID _MapKeyAttrToFlowPut(PNL_ATTR *keyAttrs,
54 PNL_ATTR *tunnelAttrs,
57 static VOID _MapTunAttrToFlowPut(PNL_ATTR *keyAttrs,
58 PNL_ATTR *tunnelAttrs,
60 static VOID _MapNlToFlowPutFlags(PGENL_MSG_HDR genlMsgHdr,
61 PNL_ATTR flowAttrClear,
62 OvsFlowPut *mappedFlow);
64 static NTSTATUS _FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
66 static NTSTATUS _FlowNlDumpCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
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,
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);
84 static NTSTATUS OvsDoDumpFlows(OvsFlowDumpInput *dumpInput,
85 OvsFlowDumpOutput *dumpOutput,
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)
93 /* Flow family related netlink policies */
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),
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}
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. */
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),
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),
131 [OVS_KEY_ATTR_IPV6] = {.type = NL_A_UNSPEC,
132 .minLen = sizeof(struct ovs_key_ipv6),
133 .maxLen = sizeof(struct ovs_key_ipv6),
135 [OVS_KEY_ATTR_TCP] = {.type = NL_A_UNSPEC,
136 .minLen = sizeof(struct ovs_key_tcp),
137 .maxLen = sizeof(struct ovs_key_tcp),
139 [OVS_KEY_ATTR_UDP] = {.type = NL_A_UNSPEC,
140 .minLen = sizeof(struct ovs_key_udp),
141 .maxLen = sizeof(struct ovs_key_udp),
143 [OVS_KEY_ATTR_ICMP] = {.type = NL_A_UNSPEC,
144 .minLen = sizeof(struct ovs_key_icmp),
145 .maxLen = sizeof(struct ovs_key_icmp),
147 [OVS_KEY_ATTR_ICMPV6] = {.type = NL_A_UNSPEC,
148 .minLen = sizeof(struct ovs_key_icmpv6),
149 .maxLen = sizeof(struct ovs_key_icmpv6),
151 [OVS_KEY_ATTR_ARP] = {.type = NL_A_UNSPEC,
152 .minLen = sizeof(struct ovs_key_arp),
153 .maxLen = sizeof(struct ovs_key_arp),
155 [OVS_KEY_ATTR_ND] = {.type = NL_A_UNSPEC,
156 .minLen = sizeof(struct ovs_key_nd),
157 .maxLen = sizeof(struct ovs_key_nd),
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),
166 [OVS_KEY_ATTR_TCP_FLAGS] = {.type = NL_A_UNSPEC,
167 .minLen = 2, .maxLen = 2,
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}
175 const UINT32 nlFlowKeyPolicyLen = ARRAY_SIZE(nlFlowKeyPolicy);
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,
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,
206 sizeof(struct ovs_action_push_vlan),
208 sizeof(struct ovs_action_push_vlan),
210 [OVS_ACTION_ATTR_POP_VLAN] = {.type = NL_A_UNSPEC, .optional = TRUE},
211 [OVS_ACTION_ATTR_PUSH_MPLS] = {.type = NL_A_UNSPEC,
213 sizeof(struct ovs_action_push_mpls),
215 sizeof(struct ovs_action_push_mpls),
217 [OVS_ACTION_ATTR_POP_MPLS] = {.type = NL_A_UNSPEC,
218 .minLen = sizeof(UINT16),
219 .maxLen = sizeof(UINT16),
221 [OVS_ACTION_ATTR_RECIRC] = {.type = NL_A_UNSPEC,
222 .minLen = sizeof(UINT32),
223 .maxLen = sizeof(UINT32),
225 [OVS_ACTION_ATTR_HASH] = {.type = NL_A_UNSPEC,
226 .minLen = sizeof(struct ovs_action_hash),
227 .maxLen = sizeof(struct ovs_action_hash),
229 [OVS_ACTION_ATTR_SET] = {.type = NL_A_VAR_LEN, .optional = TRUE},
230 [OVS_ACTION_ATTR_SAMPLE] = {.type = NL_A_VAR_LEN, .optional = TRUE}
234 *----------------------------------------------------------------------------
235 * Netlink interface for flow commands.
236 *----------------------------------------------------------------------------
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 *----------------------------------------------------------------------------
247 OvsFlowNlCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
250 NTSTATUS rc = STATUS_SUCCESS;
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;
261 struct ovs_flow_stats replyStats;
262 NL_ERROR nlError = NL_ERROR_SUCCESS;
265 RtlZeroMemory(&mappedFlow, sizeof(OvsFlowPut));
266 RtlZeroMemory(&stats, sizeof(stats));
267 RtlZeroMemory(&replyStats, sizeof(replyStats));
269 if (!(usrParamsCtx->outputBuffer)) {
270 /* No output buffer */
271 rc = STATUS_INVALID_BUFFER_SIZE;
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)))
280 OVS_LOG_ERROR("Attr Parsing failed for msg: %p",
282 rc = STATUS_INVALID_PARAMETER;
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]))) {
290 rc = OvsFlushFlowIoctl(ovsHdr->dp_ifindex);
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);
298 /* Prepare nl Msg headers */
299 ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,
300 nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
301 genlMsgHdr->cmd, OVS_FLOW_VERSION,
304 *replyLen = msgOut->nlMsg.nlmsgLen;
306 rc = STATUS_INVALID_BUFFER_SIZE;
313 if (flowAttrs[OVS_FLOW_ATTR_PROBE]) {
314 OVS_LOG_ERROR("Attribute OVS_FLOW_ATTR_PROBE not supported");
315 nlError = NL_ERROR_NOENT;
319 if ((rc = _MapNlToFlowPut(msgIn, flowAttrs[OVS_FLOW_ATTR_KEY],
320 flowAttrs[OVS_FLOW_ATTR_ACTIONS], flowAttrs[OVS_FLOW_ATTR_CLEAR],
323 OVS_LOG_ERROR("Conversion to OvsFlowPut failed");
327 rc = OvsPutFlowIoctl(&mappedFlow, sizeof (struct OvsFlowPut),
329 if (rc != STATUS_SUCCESS) {
330 OVS_LOG_ERROR("OvsPutFlowIoctl failed.");
334 replyStats.n_packets = stats.packetCount;
335 replyStats.n_bytes = stats.byteCount;
337 /* So far so good. Prepare the reply for userspace */
338 NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
339 usrParamsCtx->outputLength);
341 /* Prepare nl Msg headers */
342 ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,
343 nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
344 genlMsgHdr->cmd, OVS_FLOW_VERSION,
347 rc = STATUS_INVALID_BUFFER_SIZE;
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;
361 msgOut->nlMsg.nlmsgLen = NLMSG_ALIGN(NlBufSize(&nlBuf));
362 *replyLen = msgOut->nlMsg.nlmsgLen;
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;
378 *----------------------------------------------------------------------------
379 * OvsFlowNlGetCmdHandler --
380 * Handler for OVS_FLOW_CMD_GET/DUMP commands.
381 *----------------------------------------------------------------------------
384 OvsFlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
387 NTSTATUS status = STATUS_SUCCESS;
388 NL_ERROR nlError = NL_ERROR_SUCCESS;
389 POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;
391 if (usrParamsCtx->devOp == OVS_TRANSACTION_DEV_OP) {
392 status = _FlowNlGetCmdHandler(usrParamsCtx, replyLen);
394 /* No trasanctional errors as of now.
395 * If we have something then we need to convert rc to
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;
407 status = _FlowNlDumpCmdHandler(usrParamsCtx, replyLen);
415 *----------------------------------------------------------------------------
416 * _FlowNlGetCmdHandler --
417 * Handler for OVS_FLOW_CMD_GET command.
418 *----------------------------------------------------------------------------
421 _FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
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];
432 OvsFlowGetInput getInput;
433 OvsFlowGetOutput getOutput;
435 PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX];
436 PNL_ATTR tunnelAttrs[__OVS_TUNNEL_KEY_ATTR_MAX];
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;
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);
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)))
461 OVS_LOG_ERROR("Attr Parsing failed for msg: %p",
463 rc = STATUS_INVALID_PARAMETER;
467 keyAttrOffset = (UINT32)((PCHAR) nlAttrs[OVS_FLOW_ATTR_KEY] -
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)))
476 OVS_LOG_ERROR("Key Attr Parsing failed for msg: %p",
478 rc = STATUS_INVALID_PARAMETER;
482 if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
483 tunnelKeyAttrOffset = (UINT32)((PCHAR)
484 (keyAttrs[OVS_KEY_ATTR_TUNNEL])
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)))
494 OVS_LOG_ERROR("Tunnel key Attr Parsing failed for msg: %p",
496 rc = STATUS_INVALID_PARAMETER;
501 _MapKeyAttrToFlowPut(keyAttrs, tunnelAttrs,
504 getInput.dpNo = ovsHdr->dp_ifindex;
505 getInput.getFlags = FLOW_GET_STATS | FLOW_GET_ACTIONS;
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.");
516 /* Lets prepare the reply. */
517 nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, 0, 0));
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);
524 OVS_LOG_ERROR("Could not copy the data to the buffer tail");
528 rc = _MapFlowStatsToNlStats(&nlBuf, &((getOutput.info).stats));
529 if (rc != STATUS_SUCCESS) {
530 OVS_LOG_ERROR("_OvsFlowMapFlowKeyToNlStats failed.");
534 rc = _MapFlowActionToNlAction(&nlBuf, ((getOutput.info).actionsLen),
535 getOutput.info.actions);
536 if (rc != STATUS_SUCCESS) {
537 OVS_LOG_ERROR("_MapFlowActionToNlAction failed.");
541 NlMsgSetSize(nlMsgOutHdr, NlBufSize(&nlBuf));
542 NlMsgAlignSize(nlMsgOutHdr);
543 *replyLen += NlMsgSize(nlMsgOutHdr);
550 *----------------------------------------------------------------------------
551 * _FlowNlDumpCmdHandler --
552 * Handler for OVS_FLOW_CMD_DUMP command.
553 *----------------------------------------------------------------------------
556 _FlowNlDumpCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
559 NTSTATUS rc = STATUS_SUCCESS;
560 UINT32 temp = 0; /* To keep compiler happy for calling OvsDoDumpFlows */
562 POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)
563 (usrParamsCtx->ovsInstance);
565 if (usrParamsCtx->devOp == OVS_WRITE_DEV_OP) {
567 OvsSetupDumpStart(usrParamsCtx);
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;
579 OvsFlowDumpOutput dumpOutput;
580 OvsFlowDumpInput dumpInput;
583 NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
584 usrParamsCtx->outputLength);
586 ASSERT(usrParamsCtx->devOp == OVS_READ_DEV_OP);
587 ASSERT(usrParamsCtx->outputLength);
589 RtlZeroMemory(&dumpInput, sizeof(OvsFlowDumpInput));
590 RtlZeroMemory(&dumpOutput, sizeof(OvsFlowDumpOutput));
592 dumpInput.dpNo = ovsHdr->dp_ifindex;
593 dumpInput.getFlags = FLOW_GET_KEY | FLOW_GET_STATS | FLOW_GET_ACTIONS;
595 /* Lets provide as many flows to userspace as possible. */
597 dumpInput.position[0] = instance->dumpState.index[0];
598 dumpInput.position[1] = instance->dumpState.index[1];
600 rc = OvsDoDumpFlows(&dumpInput, &dumpOutput, &temp);
601 if (rc != STATUS_SUCCESS) {
602 OVS_LOG_ERROR("OvsDoDumpFlows failed with rc: %d", rc);
606 /* Done with Dump, send NLMSG_DONE */
607 if (!(dumpOutput.n)) {
610 OVS_LOG_INFO("Dump Done");
612 nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, NlBufSize(&nlBuf), 0));
613 ok = NlFillNlHdr(&nlBuf, NLMSG_DONE, NLM_F_MULTI,
614 nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid);
617 rc = STATUS_INVALID_BUFFER_SIZE;
618 OVS_LOG_ERROR("Unable to prepare DUMP_DONE reply.");
624 NlMsgAlignSize(nlMsgOutHdr);
625 *replyLen += NlMsgSize(nlMsgOutHdr);
627 FreeUserDumpState(instance);
632 hdrOffset = NlBufSize(&nlBuf);
633 nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, hdrOffset, 0));
636 ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, NLM_F_MULTI,
637 nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
638 genlMsgHdr->cmd, genlMsgHdr->version,
642 /* Reset rc to success so that we can
643 * send already added messages to user space. */
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));
657 /* Reset rc to success so that we can
658 * send already added messages to user space. */
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];
676 *----------------------------------------------------------------------------
677 * _MapFlowInfoToNl --
678 * Maps OvsFlowInfo to Netlink attributes.
679 *----------------------------------------------------------------------------
682 _MapFlowInfoToNl(PNL_BUFFER nlBuf, OvsFlowInfo *flowInfo)
684 NTSTATUS rc = STATUS_SUCCESS;
686 rc = MapFlowKeyToNlKey(nlBuf, &(flowInfo->key), OVS_FLOW_ATTR_KEY,
687 OVS_KEY_ATTR_TUNNEL);
688 if (rc != STATUS_SUCCESS) {
692 rc = _MapFlowStatsToNlStats(nlBuf, &(flowInfo->stats));
693 if (rc != STATUS_SUCCESS) {
697 rc = _MapFlowActionToNlAction(nlBuf, flowInfo->actionsLen,
699 if (rc != STATUS_SUCCESS) {
708 *----------------------------------------------------------------------------
709 * _MapFlowStatsToNlStats --
710 * Maps OvsFlowStats to OVS_FLOW_ATTR_STATS attribute.
711 *----------------------------------------------------------------------------
714 _MapFlowStatsToNlStats(PNL_BUFFER nlBuf, OvsFlowStats *flowStats)
716 NTSTATUS rc = STATUS_SUCCESS;
717 struct ovs_flow_stats replyStats;
719 replyStats.n_packets = flowStats->packetCount;
720 replyStats.n_bytes = flowStats->byteCount;
722 if (!NlMsgPutTailU64(nlBuf, OVS_FLOW_ATTR_USED, flowStats->used)) {
723 rc = STATUS_INVALID_BUFFER_SIZE;
727 if (!NlMsgPutTailUnspec(nlBuf, OVS_FLOW_ATTR_STATS,
728 (PCHAR)(&replyStats),
729 sizeof(struct ovs_flow_stats))) {
730 rc = STATUS_INVALID_BUFFER_SIZE;
734 if (!NlMsgPutTailU8(nlBuf, OVS_FLOW_ATTR_TCP_FLAGS, flowStats->tcpFlags)) {
735 rc = STATUS_INVALID_BUFFER_SIZE;
744 *----------------------------------------------------------------------------
745 * _MapFlowActionToNlAction --
746 * Maps flow actions to OVS_FLOW_ATTR_ACTION attribute.
747 *----------------------------------------------------------------------------
750 _MapFlowActionToNlAction(PNL_BUFFER nlBuf, uint32_t actionsLen,
753 NTSTATUS rc = STATUS_SUCCESS;
756 offset = NlMsgStartNested(nlBuf, OVS_FLOW_ATTR_ACTIONS);
758 /* Starting the nested attribute failed. */
759 rc = STATUS_INVALID_BUFFER_SIZE;
760 goto error_nested_start;
763 if (!NlBufCopyAtTail(nlBuf, (PCHAR)actions, actionsLen)) {
764 /* Adding a nested attribute failed. */
765 rc = STATUS_INVALID_BUFFER_SIZE;
770 NlMsgEndNested(nlBuf, offset);
777 *----------------------------------------------------------------------------
778 * MapFlowKeyToNlKey --
779 * Maps OvsFlowKey to OVS_FLOW_ATTR_KEY attribute.
780 *----------------------------------------------------------------------------
783 MapFlowKeyToNlKey(PNL_BUFFER nlBuf,
788 NTSTATUS rc = STATUS_SUCCESS;
789 struct ovs_key_ethernet ethKey;
792 offset = NlMsgStartNested(nlBuf, keyType);
794 /* Starting the nested attribute failed. */
795 rc = STATUS_UNSUCCESSFUL;
796 goto error_nested_start;
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);
803 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ETHERNET,
805 sizeof(struct ovs_key_ethernet))) {
806 rc = STATUS_UNSUCCESSFUL;
810 if (!NlMsgPutTailU32(nlBuf, OVS_KEY_ATTR_IN_PORT,
811 flowKey->l2.inPort)) {
812 rc = STATUS_UNSUCCESSFUL;
816 if (!NlMsgPutTailU16(nlBuf, OVS_KEY_ATTR_ETHERTYPE,
817 flowKey->l2.dlType)) {
818 rc = STATUS_UNSUCCESSFUL;
822 if (flowKey->l2.vlanTci) {
823 if (!NlMsgPutTailU16(nlBuf, OVS_KEY_ATTR_VLAN,
824 flowKey->l2.vlanTci)) {
825 rc = STATUS_UNSUCCESSFUL;
830 /* ==== L3 + L4 ==== */
831 switch (ntohs(flowKey->l2.dlType)) {
832 case ETH_TYPE_IPV4: {
833 IpKey *ipv4FlowPutKey = &(flowKey->ipKey);
834 rc = _MapFlowIpv4KeyToNlKey(nlBuf, ipv4FlowPutKey);
838 case ETH_TYPE_IPV6: {
839 Ipv6Key *ipv6FlowPutKey = &(flowKey->ipv6Key);
840 Icmp6Key *icmpv6FlowPutKey = &(flowKey->icmp6Key);
841 rc = _MapFlowIpv6KeyToNlKey(nlBuf, ipv6FlowPutKey,
847 case ETH_TYPE_RARP: {
848 ArpKey *arpFlowPutKey = &(flowKey->arpKey);
849 rc = _MapFlowArpKeyToNlKey(nlBuf, arpFlowPutKey);
857 if (rc != STATUS_SUCCESS) {
861 if (flowKey->tunKey.dst) {
862 rc = MapFlowTunKeyToNlKey(nlBuf, &(flowKey->tunKey),
864 if (rc != STATUS_SUCCESS) {
870 NlMsgEndNested(nlBuf, offset);
876 *----------------------------------------------------------------------------
877 * MapFlowTunKeyToNlKey --
878 * Maps OvsIPv4TunnelKey to OVS_TUNNEL_KEY_ATTR_ID attribute.
879 *----------------------------------------------------------------------------
882 MapFlowTunKeyToNlKey(PNL_BUFFER nlBuf,
883 OvsIPv4TunnelKey *tunKey,
886 NTSTATUS rc = STATUS_SUCCESS;
889 offset = NlMsgStartNested(nlBuf, tunKeyType);
891 /* Starting the nested attribute failed. */
892 rc = STATUS_UNSUCCESSFUL;
893 goto error_nested_start;
896 if (!NlMsgPutTailU64(nlBuf, OVS_TUNNEL_KEY_ATTR_ID,
898 rc = STATUS_UNSUCCESSFUL;
902 if (!NlMsgPutTailU32(nlBuf, OVS_TUNNEL_KEY_ATTR_IPV4_DST,
904 rc = STATUS_UNSUCCESSFUL;
908 if (!NlMsgPutTailU32(nlBuf, OVS_TUNNEL_KEY_ATTR_IPV4_SRC,
910 rc = STATUS_UNSUCCESSFUL;
914 if (!NlMsgPutTailU8(nlBuf, OVS_TUNNEL_KEY_ATTR_TOS,
916 rc = STATUS_UNSUCCESSFUL;
920 if (!NlMsgPutTailU8(nlBuf, OVS_TUNNEL_KEY_ATTR_TTL,
922 rc = STATUS_UNSUCCESSFUL;
927 NlMsgEndNested(nlBuf, offset);
933 *----------------------------------------------------------------------------
934 * _MapFlowTunKeyToNlKey --
935 * Maps OvsIPv4FlowPutKey to OVS_KEY_ATTR_IPV4 attribute.
936 *----------------------------------------------------------------------------
939 _MapFlowIpv4KeyToNlKey(PNL_BUFFER nlBuf, IpKey *ipv4FlowPutKey)
941 NTSTATUS rc = STATUS_SUCCESS;
942 struct ovs_key_ipv4 ipv4Key;
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;
951 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_IPV4,
953 sizeof(struct ovs_key_ipv4))) {
954 rc = STATUS_UNSUCCESSFUL;
958 switch (ipv4Key.ipv4_proto) {
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,
966 rc = STATUS_UNSUCCESSFUL;
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,
979 rc = STATUS_UNSUCCESSFUL;
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,
992 rc = STATUS_UNSUCCESSFUL;
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);
1004 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ICMP,
1007 rc = STATUS_UNSUCCESSFUL;
1022 *----------------------------------------------------------------------------
1023 * _MapFlowIpv6KeyToNlKey --
1024 * Maps _MapFlowIpv6KeyToNlKey to OVS_KEY_ATTR_IPV6 attribute.
1025 *----------------------------------------------------------------------------
1028 _MapFlowIpv6KeyToNlKey(PNL_BUFFER nlBuf, Ipv6Key *ipv6FlowPutKey,
1029 Icmp6Key *icmpv6FlowPutKey)
1031 NTSTATUS rc = STATUS_SUCCESS;
1032 struct ovs_key_ipv6 ipv6Key;
1034 RtlCopyMemory(&(ipv6Key.ipv6_src), &ipv6FlowPutKey->ipv6Src,
1035 sizeof ipv6Key.ipv6_src);
1036 RtlCopyMemory(&(ipv6Key.ipv6_dst), &ipv6FlowPutKey->ipv6Dst,
1037 sizeof ipv6Key.ipv6_dst);
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;
1045 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_IPV6,
1048 rc = STATUS_UNSUCCESSFUL;
1052 switch (ipv6Key.ipv6_proto) {
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,
1060 rc = STATUS_UNSUCCESSFUL;
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,
1073 rc = STATUS_UNSUCCESSFUL;
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,
1086 rc = STATUS_UNSUCCESSFUL;
1092 case IPPROTO_ICMPV6: {
1093 struct ovs_key_icmpv6 icmpV6Key;
1094 struct ovs_key_nd ndKey;
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);
1100 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ICMPV6,
1101 (PCHAR)(&icmpV6Key),
1102 sizeof(icmpV6Key))) {
1103 rc = STATUS_UNSUCCESSFUL;
1107 RtlCopyMemory(&(ndKey.nd_target), &icmpv6FlowPutKey->ndTarget,
1108 sizeof(icmpv6FlowPutKey->ndTarget));
1109 RtlCopyMemory(&(ndKey.nd_sll), &icmpv6FlowPutKey->arpSha,
1111 RtlCopyMemory(&(ndKey.nd_tll), &icmpv6FlowPutKey->arpTha,
1113 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ND,
1116 rc = STATUS_UNSUCCESSFUL;
1132 *----------------------------------------------------------------------------
1133 * _MapFlowArpKeyToNlKey --
1134 * Maps _MapFlowArpKeyToNlKey to OVS_KEY_ATTR_ARP attribute.
1135 *----------------------------------------------------------------------------
1138 _MapFlowArpKeyToNlKey(PNL_BUFFER nlBuf, ArpKey *arpFlowPutKey)
1140 NTSTATUS rc = STATUS_SUCCESS;
1141 struct ovs_key_arp arpKey;
1143 arpKey.arp_sip = arpFlowPutKey->nwSrc;
1144 arpKey.arp_tip = arpFlowPutKey->nwDst;
1146 RtlCopyMemory(&(arpKey.arp_sha), arpFlowPutKey->arpSha, ETH_ADDR_LEN);
1147 RtlCopyMemory(&(arpKey.arp_tha), arpFlowPutKey->arpTha, ETH_ADDR_LEN);
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.
1157 * It is important to note that the flow table stores the ARP opcode field
1160 arpKey.arp_op = htons(arpFlowPutKey->nwProto);
1162 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ARP,
1165 rc = STATUS_UNSUCCESSFUL;
1174 *----------------------------------------------------------------------------
1175 * _MapNlToFlowPut --
1176 * Maps input netlink message to OvsFlowPut.
1177 *----------------------------------------------------------------------------
1180 _MapNlToFlowPut(POVS_MESSAGE msgIn, PNL_ATTR keyAttr,
1181 PNL_ATTR actionAttr, PNL_ATTR flowAttrClear,
1182 OvsFlowPut *mappedFlow)
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);
1189 UINT32 keyAttrOffset = (UINT32)((PCHAR)keyAttr - (PCHAR)nlMsgHdr);
1190 UINT32 tunnelKeyAttrOffset;
1192 PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX] = {NULL};
1193 PNL_ATTR tunnelAttrs[__OVS_TUNNEL_KEY_ATTR_MAX] = {NULL};
1195 /* Get flow keys attributes */
1196 if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset, NlAttrLen(keyAttr),
1197 nlFlowKeyPolicy, ARRAY_SIZE(nlFlowKeyPolicy),
1198 keyAttrs, ARRAY_SIZE(keyAttrs)))
1200 OVS_LOG_ERROR("Key Attr Parsing failed for msg: %p",
1202 rc = STATUS_INVALID_PARAMETER;
1206 if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
1207 tunnelKeyAttrOffset = (UINT32)((PCHAR)
1208 (keyAttrs[OVS_KEY_ATTR_TUNNEL])
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)))
1218 OVS_LOG_ERROR("Tunnel key Attr Parsing failed for msg: %p",
1220 rc = STATUS_INVALID_PARAMETER;
1225 _MapKeyAttrToFlowPut(keyAttrs, tunnelAttrs,
1226 &(mappedFlow->key));
1228 /* Map the action */
1230 mappedFlow->actionsLen = NlAttrGetSize(actionAttr);
1231 mappedFlow->actions = NlAttrGet(actionAttr);
1234 mappedFlow->dpNo = ovsHdr->dp_ifindex;
1236 _MapNlToFlowPutFlags(genlMsgHdr, flowAttrClear,
1244 *----------------------------------------------------------------------------
1245 * _MapNlToFlowPutFlags --
1246 * Maps netlink message to OvsFlowPut->flags.
1247 *----------------------------------------------------------------------------
1250 _MapNlToFlowPutFlags(PGENL_MSG_HDR genlMsgHdr,
1251 PNL_ATTR flowAttrClear, OvsFlowPut *mappedFlow)
1255 switch (genlMsgHdr->cmd) {
1256 case OVS_FLOW_CMD_NEW:
1257 flags |= OVSWIN_FLOW_PUT_CREATE;
1259 case OVS_FLOW_CMD_DEL:
1260 flags |= OVSWIN_FLOW_PUT_DELETE;
1262 case OVS_FLOW_CMD_SET:
1263 flags |= OVSWIN_FLOW_PUT_MODIFY;
1269 if (flowAttrClear) {
1270 flags |= OVSWIN_FLOW_PUT_CLEAR;
1273 mappedFlow->flags = flags;
1277 *----------------------------------------------------------------------------
1278 * _MapKeyAttrToFlowPut --
1279 * Converts FLOW_KEY attribute to OvsFlowPut->key.
1280 *----------------------------------------------------------------------------
1283 _MapKeyAttrToFlowPut(PNL_ATTR *keyAttrs,
1284 PNL_ATTR *tunnelAttrs,
1285 OvsFlowKey *destKey)
1287 _MapTunAttrToFlowPut(keyAttrs, tunnelAttrs, destKey);
1289 /* ===== L2 headers ===== */
1290 destKey->l2.inPort = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_IN_PORT]);
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);
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]));
1308 if (keyAttrs[OVS_KEY_ATTR_VLAN]) {
1309 destKey->l2.vlanTci = NlAttrGetU16(keyAttrs[OVS_KEY_ATTR_VLAN]);
1312 /* ==== L3 + L4. ==== */
1313 destKey->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + OVS_L2_KEY_SIZE
1314 - destKey->l2.offset;
1316 switch (ntohs(destKey->l2.dlType)) {
1317 case ETH_TYPE_IPV4: {
1319 if (keyAttrs[OVS_KEY_ATTR_IPV4]) {
1320 const struct ovs_key_ipv4 *ipv4Key;
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;
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;
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;
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;
1352 destKey->l2.keyLen += OVS_IP_KEY_SIZE;
1356 case ETH_TYPE_IPV6: {
1358 if (keyAttrs[OVS_KEY_ATTR_IPV6]) {
1359 const struct ovs_key_ipv6 *ipv6Key;
1361 ipv6Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_IPV6]);
1362 Ipv6Key *ipv6FlowPutKey = &(destKey->ipv6Key);
1364 RtlCopyMemory(&ipv6FlowPutKey->ipv6Src, ipv6Key->ipv6_src,
1365 sizeof ipv6Key->ipv6_src);
1366 RtlCopyMemory(&ipv6FlowPutKey->ipv6Dst, ipv6Key->ipv6_dst,
1367 sizeof ipv6Key->ipv6_dst);
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;
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;
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;
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;
1396 if (keyAttrs[OVS_KEY_ATTR_ICMPV6]) {
1397 const struct ovs_key_icmpv6 *icmpv6Key;
1399 Icmp6Key *icmp6FlowPutKey= &(destKey->icmp6Key);
1401 icmpv6Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ICMPV6]);
1403 icmp6FlowPutKey->l4.tpSrc = icmpv6Key->icmpv6_type;
1404 icmp6FlowPutKey->l4.tpDst = icmpv6Key->icmpv6_code;
1406 if (keyAttrs[OVS_KEY_ATTR_ND]) {
1407 const struct ovs_key_nd *ndKey;
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);
1418 destKey->l2.keyLen += OVS_ICMPV6_KEY_SIZE;
1422 destKey->l2.keyLen += OVS_IPV6_KEY_SIZE;
1425 ipv6FlowPutKey->pad = 0;
1430 case ETH_TYPE_RARP: {
1432 if (keyAttrs[OVS_KEY_ATTR_ARP]) {
1433 ArpKey *arpFlowPutKey = &destKey->arpKey;
1434 const struct ovs_key_arp *arpKey;
1436 arpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ARP]);
1438 arpFlowPutKey->nwSrc = arpKey->arp_sip;
1439 arpFlowPutKey->nwDst = arpKey->arp_tip;
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
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;
1457 *----------------------------------------------------------------------------
1458 * _MapTunAttrToFlowPut --
1459 * Converts FLOW_TUNNEL_KEY attribute to OvsFlowKey->tunKey.
1460 *----------------------------------------------------------------------------
1463 _MapTunAttrToFlowPut(PNL_ATTR *keyAttrs,
1465 OvsFlowKey *destKey)
1467 if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
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;
1475 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_DST]) {
1476 destKey->tunKey.dst = NlAttrGetU32
1477 (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_DST]);
1480 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_SRC]) {
1481 destKey->tunKey.src = NlAttrGetU32
1482 (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_SRC]);
1485 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT]) {
1486 destKey->tunKey.flags |= OVS_TNL_F_DONT_FRAGMENT;
1489 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_CSUM]) {
1490 destKey->tunKey.flags |= OVS_TNL_F_CSUM;
1493 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_TOS]) {
1494 destKey->tunKey.tos = NlAttrGetU8
1495 (tunAttrs[OVS_TUNNEL_KEY_ATTR_TOS]);
1498 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_TTL]) {
1499 destKey->tunKey.ttl = NlAttrGetU8
1500 (tunAttrs[OVS_TUNNEL_KEY_ATTR_TTL]);
1503 destKey->tunKey.pad = 0;
1504 destKey->l2.offset = 0;
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;
1514 *----------------------------------------------------------------------------
1515 * OvsDeleteFlowTable --
1517 * NDIS_STATUS_SUCCESS always.
1518 *----------------------------------------------------------------------------
1521 OvsDeleteFlowTable(OVS_DATAPATH *datapath)
1523 if (datapath == NULL || datapath->flowTable == NULL) {
1524 return NDIS_STATUS_SUCCESS;
1527 DeleteAllFlows(datapath);
1528 OvsFreeMemoryWithTag(datapath->flowTable, OVS_FLOW_POOL_TAG);
1529 datapath->flowTable = NULL;
1531 if (datapath->lock == NULL) {
1532 return NDIS_STATUS_SUCCESS;
1535 NdisFreeRWLock(datapath->lock);
1537 return NDIS_STATUS_SUCCESS;
1541 *----------------------------------------------------------------------------
1542 * OvsAllocateFlowTable --
1544 * NDIS_STATUS_SUCCESS on success.
1545 * NDIS_STATUS_RESOURCES if memory couldn't be allocated
1546 *----------------------------------------------------------------------------
1549 OvsAllocateFlowTable(OVS_DATAPATH *datapath,
1550 POVS_SWITCH_CONTEXT switchContext)
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;
1560 for (i = 0; i < OVS_FLOW_TABLE_SIZE; i++) {
1561 bucket = &(datapath->flowTable[i]);
1562 InitializeListHead(bucket);
1564 datapath->lock = NdisAllocateRWLock(switchContext->NdisFilterHandle);
1566 if (!datapath->lock) {
1567 return NDIS_STATUS_RESOURCES;
1570 return NDIS_STATUS_SUCCESS;
1575 *----------------------------------------------------------------------------
1576 * GetStartAddrNBL --
1577 * Get the virtual address of the frame.
1580 * Virtual address of the frame.
1581 *----------------------------------------------------------------------------
1583 static __inline VOID *
1584 GetStartAddrNBL(const NET_BUFFER_LIST *_pNB)
1592 // Ethernet Header is a guaranteed safe access.
1593 curMdl = (NET_BUFFER_LIST_FIRST_NB(_pNB))->CurrentMdl;
1594 curBuffer = MmGetSystemAddressForMdlSafe(curMdl, LowPagePriority);
1599 curHeader = (PEthHdr)
1600 (curBuffer + (NET_BUFFER_LIST_FIRST_NB(_pNB))->CurrentMdlOffset);
1602 return (VOID *) curHeader;
1606 OvsFlowUsed(OvsFlow *flow,
1607 const NET_BUFFER_LIST *packet,
1608 const POVS_PACKET_HDR_INFO layers)
1610 LARGE_INTEGER tickCount;
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);
1621 DeleteAllFlows(OVS_DATAPATH *datapath)
1626 for (i = 0; i < OVS_FLOW_TABLE_SIZE; i++) {
1628 bucket = &(datapath->flowTable[i]);
1629 while (!IsListEmpty(bucket)) {
1631 next = bucket->Flink;
1632 flow = CONTAINING_RECORD(next, OvsFlow, ListEntry);
1633 RemoveFlow(datapath, &flow);
1639 *----------------------------------------------------------------------------
1640 * Initializes 'flow' members from 'packet', 'skb_priority', 'tun_id', and
1643 * Initializes 'packet' header pointers as follows:
1645 * - packet->l2 to the start of the Ethernet header.
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
1651 * - packet->l4 to just past the IPv4 header, if one is present and has a
1652 * correct length, and otherwise NULL.
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.
1657 * Returns NDIS_STATUS_SUCCESS normally. Fails only if packet data cannot be accessed
1658 * (e.g. if Pkt_CopyBytesOut() returns an error).
1659 *----------------------------------------------------------------------------
1662 OvsExtractFlow(const NET_BUFFER_LIST *packet,
1665 POVS_PACKET_HDR_INFO layers,
1666 OvsIPv4TunnelKey *tunKey)
1668 struct Eth_Header *eth;
1675 ASSERT(tunKey->dst != 0);
1676 RtlMoveMemory(&flow->tunKey, tunKey, sizeof flow->tunKey);
1677 flow->l2.offset = 0;
1679 flow->tunKey.dst = 0;
1680 flow->l2.offset = OVS_WIN_TUNNEL_KEY_SIZE;
1683 flow->l2.inPort = inPort;
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;
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);
1698 vlanTagValue = NET_BUFFER_LIST_INFO(packet, Ieee8021QNetBufferListInfo);
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));
1705 if (eth->dix.typeNBO == ETH_TYPE_802_1PQ_NBO) {
1706 Eth_802_1pq_Tag *tag= (Eth_802_1pq_Tag *)ð->dix.typeNBO;
1707 flow->l2.vlanTci = ((UINT16)tag->priority << 13) |
1709 ((UINT16)tag->vidHi << 8) | tag->vidLo;
1710 offset = sizeof (Eth_802_1pq_Tag);
1712 flow->l2.vlanTci = 0;
1716 * Please note after this point, src mac and dst mac should
1717 * not be accessed through eth
1719 eth = (Eth_Header *)((UINT8 *)eth + offset);
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).
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;
1743 flow->l2.dlType = htons(OVSWIN_DL_TYPE_NONE);
1744 layers->l3Offset = ETH_HEADER_LEN_DIX + offset;
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;
1754 flow->l2.keyLen += OVS_IP_KEY_SIZE;
1756 nh = OvsGetIp(packet, layers->l3Offset, &ip_storage);
1758 layers->l4Offset = layers->l3Offset + nh->ihl * 4;
1760 ipKey->nwSrc = nh->saddr;
1761 ipKey->nwDst = nh->daddr;
1762 ipKey->nwProto = nh->protocol;
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;
1774 ipKey->nwTtl = nh->ttl;
1775 ipKey->l4.tpSrc = 0;
1776 ipKey->l4.tpDst = 0;
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;
1787 icmp = OvsGetIcmp(packet, layers->l4Offset, &icmpStorage);
1789 ipKey->l4.tpSrc = htons(icmp->type);
1790 ipKey->l4.tpDst = htons(icmp->code);
1791 layers->l7Offset = layers->l4Offset + sizeof *icmp;
1796 ((UINT64 *)ipKey)[0] = 0;
1797 ((UINT64 *)ipKey)[1] = 0;
1799 } else if (flow->l2.dlType == htons(ETH_TYPE_IPV6)) {
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));
1808 flow->ipv6Key.l4.tpSrc = 0;
1809 flow->ipv6Key.l4.tpDst = 0;
1810 flow->ipv6Key.pad = 0;
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);
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);
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);
1847 return NDIS_STATUS_SUCCESS;
1851 FlowEqual(UINT64 *src, UINT64 *dst, UINT32 size)
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]) {
1867 * ----------------------------------------------------------------------------
1869 * Add a flow to flow table.
1872 * NDIS_STATUS_SUCCESS if no same flow in the flow table.
1873 * ----------------------------------------------------------------------------
1876 AddFlow(OVS_DATAPATH *datapath, OvsFlow *flow)
1880 if (OvsLookupFlow(datapath, &flow->key, &flow->hash, TRUE) != NULL) {
1881 return STATUS_INVALID_HANDLE;
1884 head = &(datapath->flowTable[HASH_BUCKET(flow->hash)]);
1886 * We need fence here to make sure flow's nextPtr is updated before
1887 * head->nextPtr is updated.
1891 //KeAcquireSpinLock(&FilterDeviceExtension->NblQueueLock, &oldIrql);
1892 InsertTailList(head, &flow->ListEntry);
1893 //KeReleaseSpinLock(&FilterDeviceExtension->NblQueueLock, oldIrql);
1897 return STATUS_SUCCESS;
1901 /* ----------------------------------------------------------------------------
1903 * Remove a flow from flow table, and added to wait list
1904 * ----------------------------------------------------------------------------
1907 RemoveFlow(OVS_DATAPATH *datapath,
1913 ASSERT(datapath->nFlows);
1915 // Remove the flow from queue
1916 RemoveEntryList(&f->ListEntry);
1922 * ----------------------------------------------------------------------------
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.
1930 * Flow pointer if lookup successful.
1931 * NULL if not exists.
1932 * ----------------------------------------------------------------------------
1935 OvsLookupFlow(OVS_DATAPATH *datapath,
1936 const OvsFlowKey *key,
1940 PLIST_ENTRY link, head;
1941 UINT16 offset = key->l2.offset;
1942 UINT16 size = key->l2.keyLen;
1945 ASSERT(key->tunKey.dst || offset == sizeof (OvsIPv4TunnelKey));
1946 ASSERT(!key->tunKey.dst || offset == 0);
1948 start = (UINT8 *)key + offset;
1951 *hash = OvsJhashBytes(start, size, 0);
1954 head = &datapath->flowTable[HASH_BUCKET(*hash)];
1956 while (link != head) {
1957 OvsFlow *flow = CONTAINING_RECORD(link, OvsFlow, ListEntry);
1959 if (flow->hash == *hash &&
1960 flow->key.l2.val == key->l2.val &&
1961 FlowEqual((UINT64 *)((uint8 *)&flow->key + offset),
1962 (UINT64 *)start, size)) {
1972 * ----------------------------------------------------------------------------
1974 * Calculate the hash for the given flow key.
1975 * ----------------------------------------------------------------------------
1978 OvsHashFlow(const OvsFlowKey *key)
1980 UINT16 offset = key->l2.offset;
1981 UINT16 size = key->l2.keyLen;
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);
1992 * ----------------------------------------------------------------------------
1994 * Free a flow and its actions.
1995 * ----------------------------------------------------------------------------
1998 FreeFlow(OvsFlow *flow)
2001 OvsFreeMemoryWithTag(flow, OVS_FLOW_POOL_TAG);
2005 OvsDoDumpFlows(OvsFlowDumpInput *dumpInput,
2006 OvsFlowDumpOutput *dumpOutput,
2010 OVS_DATAPATH *datapath = NULL;
2012 PLIST_ENTRY node, head;
2014 UINT32 rowIndex, columnIndex;
2015 LOCK_STATE_EX dpLockState;
2016 NTSTATUS status = STATUS_SUCCESS;
2017 BOOLEAN findNextNonEmpty = FALSE;
2019 dpNo = dumpInput->dpNo;
2020 if (gOvsSwitchContext->dpNo != dpNo) {
2021 status = STATUS_INVALID_PARAMETER;
2025 rowIndex = dumpInput->position[0];
2026 if (rowIndex >= OVS_FLOW_TABLE_SIZE) {
2028 *replyLen = sizeof(*dumpOutput);
2032 columnIndex = dumpInput->position[1];
2034 datapath = &gOvsSwitchContext->datapath;
2036 OvsAcquireDatapathRead(datapath, &dpLockState, FALSE);
2038 head = &datapath->flowTable[rowIndex];
2041 while (column < columnIndex) {
2050 findNextNonEmpty = TRUE;
2054 if (findNextNonEmpty) {
2055 while (head == node) {
2056 if (++rowIndex >= OVS_FLOW_TABLE_SIZE) {
2060 head = &datapath->flowTable[rowIndex];
2065 ASSERT(node != head);
2066 ASSERT(rowIndex < OVS_FLOW_TABLE_SIZE);
2068 flow = CONTAINING_RECORD(node, OvsFlow, ListEntry);
2069 status = ReportFlowInfo(flow, dumpInput->getFlags, &dumpOutput->flow);
2071 if (status == STATUS_BUFFER_TOO_SMALL) {
2072 dumpOutput->n = sizeof(OvsFlowDumpOutput) + flow->actionsLen;
2073 *replyLen = sizeof(*dumpOutput);
2075 dumpOutput->n = 1; //one flow reported.
2076 *replyLen = sizeof(*dumpOutput) + dumpOutput->flow.actionsLen;
2079 dumpOutput->position[0] = rowIndex;
2080 dumpOutput->position[1] = ++columnIndex;
2083 OvsReleaseDatapath(datapath, &dpLockState);
2090 ReportFlowInfo(OvsFlow *flow,
2094 NTSTATUS status = STATUS_SUCCESS;
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);
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;
2110 if (getFlags & FLOW_GET_ACTIONS) {
2111 if (flow->actionsLen == 0) {
2112 info->actionsLen = 0;
2114 info->actions = flow->actions;
2115 info->actionsLen = flow->actionsLen;
2123 OvsPutFlowIoctl(PVOID inputBuffer,
2125 struct OvsFlowStats *stats)
2127 NTSTATUS status = STATUS_SUCCESS;
2128 OVS_DATAPATH *datapath = NULL;
2132 LOCK_STATE_EX dpLockState;
2134 if ((inputLength < sizeof(OvsFlowPut)) || (inputBuffer == NULL)) {
2135 return STATUS_INFO_LENGTH_MISMATCH;
2138 put = (OvsFlowPut *)inputBuffer;
2139 if (put->actionsLen > 0) {
2140 actionsLen = put->actionsLen;
2146 if (gOvsSwitchContext->dpNo != dpNo) {
2147 status = STATUS_INVALID_PARAMETER;
2151 datapath = &gOvsSwitchContext->datapath;
2153 OvsAcquireDatapathWrite(datapath, &dpLockState, FALSE);
2154 status = HandleFlowPut(put, datapath, stats);
2155 OvsReleaseDatapath(datapath, &dpLockState);
2162 /* Handles flow add, modify as well as delete */
2164 HandleFlowPut(OvsFlowPut *put,
2165 OVS_DATAPATH *datapath,
2166 struct OvsFlowStats *stats)
2168 BOOLEAN mayCreate, mayModify, mayDelete;
2169 OvsFlow *KernelFlow;
2171 NTSTATUS status = STATUS_SUCCESS;
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;
2177 if ((mayCreate || mayModify) == mayDelete) {
2178 return STATUS_INVALID_PARAMETER;
2181 KernelFlow = OvsLookupFlow(datapath, &put->key, &hash, FALSE);
2184 return STATUS_INVALID_PARAMETER;
2187 status = OvsPrepareFlow(&KernelFlow, put, hash);
2188 if (status != STATUS_SUCCESS) {
2189 return STATUS_UNSUCCESSFUL;
2192 status = AddFlow(datapath, KernelFlow);
2193 if (status != STATUS_SUCCESS) {
2194 FreeFlow(KernelFlow);
2195 return STATUS_UNSUCCESSFUL;
2198 /* Validate the flow addition */
2201 OvsFlow *flow = OvsLookupFlow(datapath, &put->key, &newHash,
2204 ASSERT(newHash == hash);
2205 if (!flow || newHash != hash) {
2206 return STATUS_UNSUCCESSFUL;
2210 stats->packetCount = KernelFlow->packetCount;
2211 stats->byteCount = KernelFlow->byteCount;
2212 stats->tcpFlags = KernelFlow->tcpFlags;
2213 stats->used = (UINT32)KernelFlow->used;
2217 status = OvsPrepareFlow(&newFlow, put, hash);
2218 if (status != STATUS_SUCCESS) {
2219 return STATUS_UNSUCCESSFUL;
2222 KernelFlow = OvsLookupFlow(datapath, &put->key, &hash, TRUE);
2224 if ((put->flags & OVSWIN_FLOW_PUT_CLEAR) == 0) {
2225 newFlow->packetCount = KernelFlow->packetCount;
2226 newFlow->byteCount = KernelFlow->byteCount;
2227 newFlow->tcpFlags = KernelFlow->tcpFlags;
2229 RemoveFlow(datapath, &KernelFlow);
2231 if ((put->flags & OVSWIN_FLOW_PUT_CLEAR) == 0) {
2232 newFlow->packetCount = stats->packetCount;
2233 newFlow->byteCount = stats->byteCount;
2234 newFlow->tcpFlags = stats->tcpFlags;
2237 status = AddFlow(datapath, newFlow);
2238 ASSERT(status == STATUS_SUCCESS);
2240 /* Validate the flow addition */
2243 OvsFlow *testflow = OvsLookupFlow(datapath, &put->key,
2246 ASSERT(newHash == hash);
2247 if (!testflow || newHash != hash) {
2249 return STATUS_UNSUCCESSFUL;
2255 RemoveFlow(datapath, &KernelFlow);
2258 /* Return success if an identical flow already exists. */
2259 /* XXX: should we return EEXIST in a netlink error? */
2260 return STATUS_SUCCESS;
2264 return STATUS_SUCCESS;
2268 OvsPrepareFlow(OvsFlow **flow,
2269 const OvsFlowPut *put,
2272 OvsFlow *localFlow = *flow;
2273 NTSTATUS status = STATUS_SUCCESS;
2277 OvsAllocateMemoryWithTag(sizeof(OvsFlow) + put->actionsLen,
2279 if (localFlow == NULL) {
2280 status = STATUS_NO_MEMORY;
2284 localFlow->key = put->key;
2285 localFlow->actionsLen = put->actionsLen;
2286 if (put->actionsLen) {
2287 NdisMoveMemory((PUCHAR)localFlow->actions, put->actions,
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;
2302 OvsGetFlowIoctl(PVOID inputBuffer,
2305 NTSTATUS status = STATUS_SUCCESS;
2306 OVS_DATAPATH *datapath = NULL;
2308 UINT32 getFlags, getActionsLen;
2309 OvsFlowGetInput *getInput;
2310 OvsFlowGetOutput *getOutput;
2313 LOCK_STATE_EX dpLockState;
2315 getInput = (OvsFlowGetInput *) inputBuffer;
2316 getFlags = getInput->getFlags;
2317 getActionsLen = getInput->actionsLen;
2319 if (outputBuffer == NULL) {
2320 return STATUS_INFO_LENGTH_MISMATCH;
2323 dpNo = getInput->dpNo;
2324 if (gOvsSwitchContext->dpNo != dpNo) {
2325 status = STATUS_INVALID_PARAMETER;
2329 datapath = &gOvsSwitchContext->datapath;
2331 OvsAcquireDatapathRead(datapath, &dpLockState, FALSE);
2332 flow = OvsLookupFlow(datapath, &getInput->key, &hash, FALSE);
2334 status = STATUS_INVALID_PARAMETER;
2338 getOutput = (OvsFlowGetOutput *)outputBuffer;
2339 ReportFlowInfo(flow, getFlags, &getOutput->info);
2342 OvsReleaseDatapath(datapath, &dpLockState);
2348 OvsFlushFlowIoctl(UINT32 dpNo)
2350 NTSTATUS status = STATUS_SUCCESS;
2351 OVS_DATAPATH *datapath = NULL;
2352 LOCK_STATE_EX dpLockState;
2354 if (gOvsSwitchContext->dpNo != dpNo) {
2355 status = STATUS_INVALID_PARAMETER;
2359 datapath = &gOvsSwitchContext->datapath;
2361 OvsAcquireDatapathWrite(datapath, &dpLockState, FALSE);
2362 DeleteAllFlows(datapath);
2363 OvsReleaseDatapath(datapath, &dpLockState);
2370 OvsFlowKeyAttrSize(void)
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 */
2390 OvsTunKeyAttrSize(void)
2392 /* Whenever adding new OVS_TUNNEL_KEY_ FIELDS, we should consider
2393 * updating this function.
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 */
2408 #pragma warning( pop )