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");
318 if ((rc = _MapNlToFlowPut(msgIn, flowAttrs[OVS_FLOW_ATTR_KEY],
319 flowAttrs[OVS_FLOW_ATTR_ACTIONS], flowAttrs[OVS_FLOW_ATTR_CLEAR],
322 OVS_LOG_ERROR("Conversion to OvsFlowPut failed");
326 rc = OvsPutFlowIoctl(&mappedFlow, sizeof (struct OvsFlowPut),
328 if (rc != STATUS_SUCCESS) {
329 OVS_LOG_ERROR("OvsPutFlowIoctl failed.");
331 * Report back to the userspace the flow could not be modified,
334 nlError = NL_ERROR_NOENT;
338 replyStats.n_packets = stats.packetCount;
339 replyStats.n_bytes = stats.byteCount;
341 /* So far so good. Prepare the reply for userspace */
342 NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
343 usrParamsCtx->outputLength);
345 /* Prepare nl Msg headers */
346 ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,
347 nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
348 genlMsgHdr->cmd, OVS_FLOW_VERSION,
351 rc = STATUS_INVALID_BUFFER_SIZE;
357 /* Append OVS_FLOW_ATTR_KEY attribute. This is need i.e. for flow delete*/
358 if (!NlMsgPutNested(&nlBuf, OVS_FLOW_ATTR_KEY,
359 NlAttrData(flowAttrs[OVS_FLOW_ATTR_KEY]),
360 NlAttrGetSize(flowAttrs[OVS_FLOW_ATTR_KEY]))) {
361 OVS_LOG_ERROR("Adding OVS_FLOW_ATTR_KEY attribute failed.");
362 rc = STATUS_INVALID_BUFFER_SIZE;
366 /* Append OVS_FLOW_ATTR_STATS attribute */
367 if (!NlMsgPutTailUnspec(&nlBuf, OVS_FLOW_ATTR_STATS,
368 (PCHAR)(&replyStats), sizeof(replyStats))) {
369 OVS_LOG_ERROR("Adding OVS_FLOW_ATTR_STATS attribute failed.");
370 rc = STATUS_INVALID_BUFFER_SIZE;
374 msgOut->nlMsg.nlmsgLen = NLMSG_ALIGN(NlBufSize(&nlBuf));
375 *replyLen = msgOut->nlMsg.nlmsgLen;
379 if (nlError != NL_ERROR_SUCCESS) {
380 POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
381 usrParamsCtx->outputBuffer;
382 NlBuildErrorMsg(msgIn, msgError, nlError);
383 *replyLen = msgError->nlMsg.nlmsgLen;
391 *----------------------------------------------------------------------------
392 * OvsFlowNlGetCmdHandler --
393 * Handler for OVS_FLOW_CMD_GET/DUMP commands.
394 *----------------------------------------------------------------------------
397 OvsFlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
400 NTSTATUS status = STATUS_SUCCESS;
402 if (usrParamsCtx->devOp == OVS_TRANSACTION_DEV_OP) {
403 status = _FlowNlGetCmdHandler(usrParamsCtx, replyLen);
405 status = _FlowNlDumpCmdHandler(usrParamsCtx, replyLen);
412 *----------------------------------------------------------------------------
413 * _FlowNlGetCmdHandler --
414 * Handler for OVS_FLOW_CMD_GET command.
415 *----------------------------------------------------------------------------
418 _FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
421 NTSTATUS rc = STATUS_SUCCESS;
422 POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;
423 PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
424 POVS_HDR ovsHdr = &(msgIn->ovsHdr);
425 PNL_MSG_HDR nlMsgOutHdr = NULL;
426 UINT32 attrOffset = NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN;
427 PNL_ATTR nlAttrs[__OVS_FLOW_ATTR_MAX];
429 OvsFlowGetInput getInput;
430 OvsFlowGetOutput getOutput;
432 PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX];
433 PNL_ATTR tunnelAttrs[__OVS_TUNNEL_KEY_ATTR_MAX];
435 NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
436 usrParamsCtx->outputLength);
437 RtlZeroMemory(&getInput, sizeof(OvsFlowGetInput));
438 RtlZeroMemory(&getOutput, sizeof(OvsFlowGetOutput));
439 UINT32 keyAttrOffset = 0;
440 UINT32 tunnelKeyAttrOffset = 0;
442 NL_ERROR nlError = NL_ERROR_SUCCESS;
444 if (usrParamsCtx->inputLength > usrParamsCtx->outputLength) {
445 /* Should not be the case.
446 * We'll be copying the flow keys back from
447 * input buffer to output buffer. */
448 rc = STATUS_INVALID_PARAMETER;
449 OVS_LOG_ERROR("inputLength: %d GREATER THEN outputLength: %d",
450 usrParamsCtx->inputLength, usrParamsCtx->outputLength);
454 /* Get all the top level Flow attributes */
455 if ((NlAttrParse(nlMsgHdr, attrOffset, NlMsgAttrsLen(nlMsgHdr),
456 nlFlowPolicy, ARRAY_SIZE(nlFlowPolicy),
457 nlAttrs, ARRAY_SIZE(nlAttrs)))
459 OVS_LOG_ERROR("Attr Parsing failed for msg: %p",
461 rc = STATUS_INVALID_PARAMETER;
465 keyAttrOffset = (UINT32)((PCHAR) nlAttrs[OVS_FLOW_ATTR_KEY] -
468 /* Get flow keys attributes */
469 if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset,
470 NlAttrLen(nlAttrs[OVS_FLOW_ATTR_KEY]),
471 nlFlowKeyPolicy, ARRAY_SIZE(nlFlowKeyPolicy),
472 keyAttrs, ARRAY_SIZE(keyAttrs)))
474 OVS_LOG_ERROR("Key Attr Parsing failed for msg: %p",
476 rc = STATUS_INVALID_PARAMETER;
480 if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
481 tunnelKeyAttrOffset = (UINT32)((PCHAR)
482 (keyAttrs[OVS_KEY_ATTR_TUNNEL])
485 /* Get tunnel keys attributes */
486 if ((NlAttrParseNested(nlMsgHdr, tunnelKeyAttrOffset,
487 NlAttrLen(keyAttrs[OVS_KEY_ATTR_TUNNEL]),
488 nlFlowTunnelKeyPolicy,
489 ARRAY_SIZE(nlFlowTunnelKeyPolicy),
490 tunnelAttrs, ARRAY_SIZE(tunnelAttrs)))
492 OVS_LOG_ERROR("Tunnel key Attr Parsing failed for msg: %p",
494 rc = STATUS_INVALID_PARAMETER;
499 _MapKeyAttrToFlowPut(keyAttrs, tunnelAttrs,
502 getInput.dpNo = ovsHdr->dp_ifindex;
503 getInput.getFlags = FLOW_GET_STATS | FLOW_GET_ACTIONS;
505 /* 4th argument is a no op.
506 * We are keeping this argument to be compatible
507 * with our dpif-windows based interface. */
508 rc = OvsGetFlowIoctl(&getInput, &getOutput);
509 if (rc != STATUS_SUCCESS) {
510 OVS_LOG_ERROR("OvsGetFlowIoctl failed.");
512 * Report back to the userspace the flow could not be found
514 nlError = NL_ERROR_NOENT;
518 /* Lets prepare the reply. */
519 nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, 0, 0));
521 /* Input already has all the attributes for the flow key.
522 * Lets copy the values back. */
523 ok = NlMsgPutTail(&nlBuf, (PCHAR)(usrParamsCtx->inputBuffer),
524 usrParamsCtx->inputLength);
526 OVS_LOG_ERROR("Could not copy the data to the buffer tail");
530 rc = _MapFlowStatsToNlStats(&nlBuf, &((getOutput.info).stats));
531 if (rc != STATUS_SUCCESS) {
532 OVS_LOG_ERROR("_OvsFlowMapFlowKeyToNlStats failed.");
536 rc = _MapFlowActionToNlAction(&nlBuf, ((getOutput.info).actionsLen),
537 getOutput.info.actions);
538 if (rc != STATUS_SUCCESS) {
539 OVS_LOG_ERROR("_MapFlowActionToNlAction failed.");
543 NlMsgSetSize(nlMsgOutHdr, NlBufSize(&nlBuf));
544 NlMsgAlignSize(nlMsgOutHdr);
545 *replyLen += NlMsgSize(nlMsgOutHdr);
548 if (nlError != NL_ERROR_SUCCESS) {
549 POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
550 usrParamsCtx->outputBuffer;
551 NlBuildErrorMsg(msgIn, msgError, nlError);
552 *replyLen = msgError->nlMsg.nlmsgLen;
560 *----------------------------------------------------------------------------
561 * _FlowNlDumpCmdHandler --
562 * Handler for OVS_FLOW_CMD_DUMP command.
563 *----------------------------------------------------------------------------
566 _FlowNlDumpCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
569 NTSTATUS rc = STATUS_SUCCESS;
570 UINT32 temp = 0; /* To keep compiler happy for calling OvsDoDumpFlows */
571 NL_ERROR nlError = NL_ERROR_SUCCESS;
572 POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)
573 (usrParamsCtx->ovsInstance);
574 POVS_MESSAGE msgIn = instance->dumpState.ovsMsg;
576 if (usrParamsCtx->devOp == OVS_WRITE_DEV_OP) {
578 OvsSetupDumpStart(usrParamsCtx);
582 PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
583 PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
584 POVS_HDR ovsHdr = &(msgIn->ovsHdr);
585 PNL_MSG_HDR nlMsgOutHdr = NULL;
586 UINT32 hdrOffset = 0;
589 OvsFlowDumpOutput dumpOutput;
590 OvsFlowDumpInput dumpInput;
593 NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
594 usrParamsCtx->outputLength);
596 ASSERT(usrParamsCtx->devOp == OVS_READ_DEV_OP);
597 ASSERT(usrParamsCtx->outputLength);
599 RtlZeroMemory(&dumpInput, sizeof(OvsFlowDumpInput));
600 RtlZeroMemory(&dumpOutput, sizeof(OvsFlowDumpOutput));
602 dumpInput.dpNo = ovsHdr->dp_ifindex;
603 dumpInput.getFlags = FLOW_GET_KEY | FLOW_GET_STATS | FLOW_GET_ACTIONS;
605 /* Lets provide as many flows to userspace as possible. */
607 dumpInput.position[0] = instance->dumpState.index[0];
608 dumpInput.position[1] = instance->dumpState.index[1];
610 rc = OvsDoDumpFlows(&dumpInput, &dumpOutput, &temp);
611 if (rc != STATUS_SUCCESS) {
612 OVS_LOG_ERROR("OvsDoDumpFlows failed with rc: %d", rc);
614 * Report back to the userspace the flows could not be found
616 nlError = NL_ERROR_NOENT;
620 /* Done with Dump, send NLMSG_DONE */
621 if (!(dumpOutput.n)) {
624 OVS_LOG_INFO("Dump Done");
626 nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, NlBufSize(&nlBuf), 0));
627 ok = NlFillNlHdr(&nlBuf, NLMSG_DONE, NLM_F_MULTI,
628 nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid);
631 rc = STATUS_INVALID_BUFFER_SIZE;
632 OVS_LOG_ERROR("Unable to prepare DUMP_DONE reply.");
638 NlMsgAlignSize(nlMsgOutHdr);
639 *replyLen += NlMsgSize(nlMsgOutHdr);
641 FreeUserDumpState(instance);
646 hdrOffset = NlBufSize(&nlBuf);
647 nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, hdrOffset, 0));
650 ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, NLM_F_MULTI,
651 nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
652 genlMsgHdr->cmd, genlMsgHdr->version,
656 /* Reset rc to success so that we can
657 * send already added messages to user space. */
662 /* Time to add attributes */
663 rc = _MapFlowInfoToNl(&nlBuf, &(dumpOutput.flow));
664 if (rc != STATUS_SUCCESS) {
665 /* Adding the attribute failed, we are out of
666 space in the buffer, remove the appended OVS header */
667 NlMsgSetSize(nlMsgOutHdr,
668 NlMsgSize(nlMsgOutHdr) -
669 sizeof(struct _OVS_MESSAGE));
671 /* Reset rc to success so that we can
672 * send already added messages to user space. */
677 NlMsgSetSize(nlMsgOutHdr, NlBufSize(&nlBuf) - hdrOffset);
678 NlMsgAlignSize(nlMsgOutHdr);
679 *replyLen += NlMsgSize(nlMsgOutHdr);
680 instance->dumpState.index[0] = dumpOutput.position[0];
681 instance->dumpState.index[1] = dumpOutput.position[1];
686 if (nlError != NL_ERROR_SUCCESS) {
687 POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
688 usrParamsCtx->outputBuffer;
689 NlBuildErrorMsg(msgIn, msgError, nlError);
690 *replyLen = msgError->nlMsg.nlmsgLen;
698 *----------------------------------------------------------------------------
699 * _MapFlowInfoToNl --
700 * Maps OvsFlowInfo to Netlink attributes.
701 *----------------------------------------------------------------------------
704 _MapFlowInfoToNl(PNL_BUFFER nlBuf, OvsFlowInfo *flowInfo)
706 NTSTATUS rc = STATUS_SUCCESS;
708 rc = MapFlowKeyToNlKey(nlBuf, &(flowInfo->key), OVS_FLOW_ATTR_KEY,
709 OVS_KEY_ATTR_TUNNEL);
710 if (rc != STATUS_SUCCESS) {
714 rc = _MapFlowStatsToNlStats(nlBuf, &(flowInfo->stats));
715 if (rc != STATUS_SUCCESS) {
719 rc = _MapFlowActionToNlAction(nlBuf, flowInfo->actionsLen,
721 if (rc != STATUS_SUCCESS) {
730 *----------------------------------------------------------------------------
731 * _MapFlowStatsToNlStats --
732 * Maps OvsFlowStats to OVS_FLOW_ATTR_STATS attribute.
733 *----------------------------------------------------------------------------
736 _MapFlowStatsToNlStats(PNL_BUFFER nlBuf, OvsFlowStats *flowStats)
738 NTSTATUS rc = STATUS_SUCCESS;
739 struct ovs_flow_stats replyStats;
741 replyStats.n_packets = flowStats->packetCount;
742 replyStats.n_bytes = flowStats->byteCount;
744 if (!NlMsgPutTailU64(nlBuf, OVS_FLOW_ATTR_USED, flowStats->used)) {
745 rc = STATUS_INVALID_BUFFER_SIZE;
749 if (!NlMsgPutTailUnspec(nlBuf, OVS_FLOW_ATTR_STATS,
750 (PCHAR)(&replyStats),
751 sizeof(struct ovs_flow_stats))) {
752 rc = STATUS_INVALID_BUFFER_SIZE;
756 if (!NlMsgPutTailU8(nlBuf, OVS_FLOW_ATTR_TCP_FLAGS, flowStats->tcpFlags)) {
757 rc = STATUS_INVALID_BUFFER_SIZE;
766 *----------------------------------------------------------------------------
767 * _MapFlowActionToNlAction --
768 * Maps flow actions to OVS_FLOW_ATTR_ACTION attribute.
769 *----------------------------------------------------------------------------
772 _MapFlowActionToNlAction(PNL_BUFFER nlBuf, uint32_t actionsLen,
775 NTSTATUS rc = STATUS_SUCCESS;
778 offset = NlMsgStartNested(nlBuf, OVS_FLOW_ATTR_ACTIONS);
780 /* Starting the nested attribute failed. */
781 rc = STATUS_INVALID_BUFFER_SIZE;
782 goto error_nested_start;
785 if (!NlBufCopyAtTail(nlBuf, (PCHAR)actions, actionsLen)) {
786 /* Adding a nested attribute failed. */
787 rc = STATUS_INVALID_BUFFER_SIZE;
792 NlMsgEndNested(nlBuf, offset);
799 *----------------------------------------------------------------------------
800 * MapFlowKeyToNlKey --
801 * Maps OvsFlowKey to OVS_FLOW_ATTR_KEY attribute.
802 *----------------------------------------------------------------------------
805 MapFlowKeyToNlKey(PNL_BUFFER nlBuf,
810 NTSTATUS rc = STATUS_SUCCESS;
811 struct ovs_key_ethernet ethKey;
814 offset = NlMsgStartNested(nlBuf, keyType);
816 /* Starting the nested attribute failed. */
817 rc = STATUS_UNSUCCESSFUL;
818 goto error_nested_start;
821 /* Ethernet header */
822 RtlCopyMemory(&(ethKey.eth_src), flowKey->l2.dlSrc, ETH_ADDR_LEN);
823 RtlCopyMemory(&(ethKey.eth_dst), flowKey->l2.dlDst, ETH_ADDR_LEN);
825 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ETHERNET,
827 sizeof(struct ovs_key_ethernet))) {
828 rc = STATUS_UNSUCCESSFUL;
832 if (!NlMsgPutTailU32(nlBuf, OVS_KEY_ATTR_IN_PORT,
833 flowKey->l2.inPort)) {
834 rc = STATUS_UNSUCCESSFUL;
838 if (!NlMsgPutTailU16(nlBuf, OVS_KEY_ATTR_ETHERTYPE,
839 flowKey->l2.dlType)) {
840 rc = STATUS_UNSUCCESSFUL;
844 if (flowKey->l2.vlanTci) {
845 if (!NlMsgPutTailU16(nlBuf, OVS_KEY_ATTR_VLAN,
846 flowKey->l2.vlanTci)) {
847 rc = STATUS_UNSUCCESSFUL;
852 /* ==== L3 + L4 ==== */
853 switch (ntohs(flowKey->l2.dlType)) {
854 case ETH_TYPE_IPV4: {
855 IpKey *ipv4FlowPutKey = &(flowKey->ipKey);
856 rc = _MapFlowIpv4KeyToNlKey(nlBuf, ipv4FlowPutKey);
860 case ETH_TYPE_IPV6: {
861 Ipv6Key *ipv6FlowPutKey = &(flowKey->ipv6Key);
862 Icmp6Key *icmpv6FlowPutKey = &(flowKey->icmp6Key);
863 rc = _MapFlowIpv6KeyToNlKey(nlBuf, ipv6FlowPutKey,
869 case ETH_TYPE_RARP: {
870 ArpKey *arpFlowPutKey = &(flowKey->arpKey);
871 rc = _MapFlowArpKeyToNlKey(nlBuf, arpFlowPutKey);
879 if (rc != STATUS_SUCCESS) {
883 if (flowKey->tunKey.dst) {
884 rc = MapFlowTunKeyToNlKey(nlBuf, &(flowKey->tunKey),
886 if (rc != STATUS_SUCCESS) {
892 NlMsgEndNested(nlBuf, offset);
898 *----------------------------------------------------------------------------
899 * MapFlowTunKeyToNlKey --
900 * Maps OvsIPv4TunnelKey to OVS_TUNNEL_KEY_ATTR_ID attribute.
901 *----------------------------------------------------------------------------
904 MapFlowTunKeyToNlKey(PNL_BUFFER nlBuf,
905 OvsIPv4TunnelKey *tunKey,
908 NTSTATUS rc = STATUS_SUCCESS;
911 offset = NlMsgStartNested(nlBuf, tunKeyType);
913 /* Starting the nested attribute failed. */
914 rc = STATUS_UNSUCCESSFUL;
915 goto error_nested_start;
918 if (!NlMsgPutTailU64(nlBuf, OVS_TUNNEL_KEY_ATTR_ID,
920 rc = STATUS_UNSUCCESSFUL;
924 if (!NlMsgPutTailU32(nlBuf, OVS_TUNNEL_KEY_ATTR_IPV4_DST,
926 rc = STATUS_UNSUCCESSFUL;
930 if (!NlMsgPutTailU32(nlBuf, OVS_TUNNEL_KEY_ATTR_IPV4_SRC,
932 rc = STATUS_UNSUCCESSFUL;
936 if (!NlMsgPutTailU8(nlBuf, OVS_TUNNEL_KEY_ATTR_TOS,
938 rc = STATUS_UNSUCCESSFUL;
942 if (!NlMsgPutTailU8(nlBuf, OVS_TUNNEL_KEY_ATTR_TTL,
944 rc = STATUS_UNSUCCESSFUL;
949 NlMsgEndNested(nlBuf, offset);
955 *----------------------------------------------------------------------------
956 * _MapFlowTunKeyToNlKey --
957 * Maps OvsIPv4FlowPutKey to OVS_KEY_ATTR_IPV4 attribute.
958 *----------------------------------------------------------------------------
961 _MapFlowIpv4KeyToNlKey(PNL_BUFFER nlBuf, IpKey *ipv4FlowPutKey)
963 NTSTATUS rc = STATUS_SUCCESS;
964 struct ovs_key_ipv4 ipv4Key;
966 ipv4Key.ipv4_src = ipv4FlowPutKey->nwSrc;
967 ipv4Key.ipv4_dst = ipv4FlowPutKey->nwDst;
968 ipv4Key.ipv4_proto = ipv4FlowPutKey->nwProto;
969 ipv4Key.ipv4_tos = ipv4FlowPutKey->nwTos;
970 ipv4Key.ipv4_ttl = ipv4FlowPutKey->nwTtl;
971 ipv4Key.ipv4_frag = ipv4FlowPutKey->nwFrag;
973 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_IPV4,
975 sizeof(struct ovs_key_ipv4))) {
976 rc = STATUS_UNSUCCESSFUL;
980 switch (ipv4Key.ipv4_proto) {
982 struct ovs_key_tcp tcpKey;
983 tcpKey.tcp_src = ipv4FlowPutKey->l4.tpSrc;
984 tcpKey.tcp_dst = ipv4FlowPutKey->l4.tpDst;
985 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_TCP,
988 rc = STATUS_UNSUCCESSFUL;
995 struct ovs_key_udp udpKey;
996 udpKey.udp_src = ipv4FlowPutKey->l4.tpSrc;
997 udpKey.udp_dst = ipv4FlowPutKey->l4.tpDst;
998 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_UDP,
1001 rc = STATUS_UNSUCCESSFUL;
1007 case IPPROTO_SCTP: {
1008 struct ovs_key_sctp sctpKey;
1009 sctpKey.sctp_src = ipv4FlowPutKey->l4.tpSrc;
1010 sctpKey.sctp_dst = ipv4FlowPutKey->l4.tpDst;
1011 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_SCTP,
1014 rc = STATUS_UNSUCCESSFUL;
1020 case IPPROTO_ICMP: {
1021 struct ovs_key_icmp icmpKey;
1022 /* XXX: revisit to see if htons is needed */
1023 icmpKey.icmp_type = (__u8)(ipv4FlowPutKey->l4.tpSrc);
1024 icmpKey.icmp_code = (__u8)(ipv4FlowPutKey->l4.tpDst);
1026 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ICMP,
1029 rc = STATUS_UNSUCCESSFUL;
1044 *----------------------------------------------------------------------------
1045 * _MapFlowIpv6KeyToNlKey --
1046 * Maps _MapFlowIpv6KeyToNlKey to OVS_KEY_ATTR_IPV6 attribute.
1047 *----------------------------------------------------------------------------
1050 _MapFlowIpv6KeyToNlKey(PNL_BUFFER nlBuf, Ipv6Key *ipv6FlowPutKey,
1051 Icmp6Key *icmpv6FlowPutKey)
1053 NTSTATUS rc = STATUS_SUCCESS;
1054 struct ovs_key_ipv6 ipv6Key;
1056 RtlCopyMemory(&(ipv6Key.ipv6_src), &ipv6FlowPutKey->ipv6Src,
1057 sizeof ipv6Key.ipv6_src);
1058 RtlCopyMemory(&(ipv6Key.ipv6_dst), &ipv6FlowPutKey->ipv6Dst,
1059 sizeof ipv6Key.ipv6_dst);
1061 ipv6Key.ipv6_label = ipv6FlowPutKey->ipv6Label;
1062 ipv6Key.ipv6_proto = ipv6FlowPutKey->nwProto;
1063 ipv6Key.ipv6_tclass = ipv6FlowPutKey->nwTos;
1064 ipv6Key.ipv6_hlimit = ipv6FlowPutKey->nwTtl;
1065 ipv6Key.ipv6_frag = ipv6FlowPutKey->nwFrag;
1067 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_IPV6,
1070 rc = STATUS_UNSUCCESSFUL;
1074 switch (ipv6Key.ipv6_proto) {
1076 struct ovs_key_tcp tcpKey;
1077 tcpKey.tcp_src = ipv6FlowPutKey->l4.tpSrc;
1078 tcpKey.tcp_dst = ipv6FlowPutKey->l4.tpDst;
1079 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_TCP,
1082 rc = STATUS_UNSUCCESSFUL;
1089 struct ovs_key_udp udpKey;
1090 udpKey.udp_src = ipv6FlowPutKey->l4.tpSrc;
1091 udpKey.udp_dst = ipv6FlowPutKey->l4.tpDst;
1092 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_UDP,
1095 rc = STATUS_UNSUCCESSFUL;
1101 case IPPROTO_SCTP: {
1102 struct ovs_key_sctp sctpKey;
1103 sctpKey.sctp_src = ipv6FlowPutKey->l4.tpSrc;
1104 sctpKey.sctp_dst = ipv6FlowPutKey->l4.tpDst;
1105 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_SCTP,
1108 rc = STATUS_UNSUCCESSFUL;
1114 case IPPROTO_ICMPV6: {
1115 struct ovs_key_icmpv6 icmpV6Key;
1116 struct ovs_key_nd ndKey;
1118 /* XXX: revisit to see if htons is needed */
1119 icmpV6Key.icmpv6_type = (__u8)(icmpv6FlowPutKey->l4.tpSrc);
1120 icmpV6Key.icmpv6_code = (__u8)(icmpv6FlowPutKey->l4.tpDst);
1122 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ICMPV6,
1123 (PCHAR)(&icmpV6Key),
1124 sizeof(icmpV6Key))) {
1125 rc = STATUS_UNSUCCESSFUL;
1129 RtlCopyMemory(&(ndKey.nd_target), &icmpv6FlowPutKey->ndTarget,
1130 sizeof(icmpv6FlowPutKey->ndTarget));
1131 RtlCopyMemory(&(ndKey.nd_sll), &icmpv6FlowPutKey->arpSha,
1133 RtlCopyMemory(&(ndKey.nd_tll), &icmpv6FlowPutKey->arpTha,
1135 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ND,
1138 rc = STATUS_UNSUCCESSFUL;
1154 *----------------------------------------------------------------------------
1155 * _MapFlowArpKeyToNlKey --
1156 * Maps _MapFlowArpKeyToNlKey to OVS_KEY_ATTR_ARP attribute.
1157 *----------------------------------------------------------------------------
1160 _MapFlowArpKeyToNlKey(PNL_BUFFER nlBuf, ArpKey *arpFlowPutKey)
1162 NTSTATUS rc = STATUS_SUCCESS;
1163 struct ovs_key_arp arpKey;
1165 arpKey.arp_sip = arpFlowPutKey->nwSrc;
1166 arpKey.arp_tip = arpFlowPutKey->nwDst;
1168 RtlCopyMemory(&(arpKey.arp_sha), arpFlowPutKey->arpSha, ETH_ADDR_LEN);
1169 RtlCopyMemory(&(arpKey.arp_tha), arpFlowPutKey->arpTha, ETH_ADDR_LEN);
1172 * Flow_Extract() stores 'nwProto' in host order for ARP since 'nwProto' is
1173 * 1 byte field and the ARP opcode is 2 bytes, and all of the kernel code
1174 * understand this while looking at an ARP key.
1175 * While we pass up the ARP key to userspace, convert from host order to
1176 * network order. Likewise, when processing an ARP key from userspace,
1177 * convert from network order to host order.
1179 * It is important to note that the flow table stores the ARP opcode field
1182 arpKey.arp_op = htons(arpFlowPutKey->nwProto);
1184 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ARP,
1187 rc = STATUS_UNSUCCESSFUL;
1196 *----------------------------------------------------------------------------
1197 * _MapNlToFlowPut --
1198 * Maps input netlink message to OvsFlowPut.
1199 *----------------------------------------------------------------------------
1202 _MapNlToFlowPut(POVS_MESSAGE msgIn, PNL_ATTR keyAttr,
1203 PNL_ATTR actionAttr, PNL_ATTR flowAttrClear,
1204 OvsFlowPut *mappedFlow)
1206 NTSTATUS rc = STATUS_SUCCESS;
1207 PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
1208 PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
1209 POVS_HDR ovsHdr = &(msgIn->ovsHdr);
1211 UINT32 keyAttrOffset = (UINT32)((PCHAR)keyAttr - (PCHAR)nlMsgHdr);
1212 UINT32 tunnelKeyAttrOffset;
1214 PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX] = {NULL};
1215 PNL_ATTR tunnelAttrs[__OVS_TUNNEL_KEY_ATTR_MAX] = {NULL};
1217 /* Get flow keys attributes */
1218 if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset, NlAttrLen(keyAttr),
1219 nlFlowKeyPolicy, ARRAY_SIZE(nlFlowKeyPolicy),
1220 keyAttrs, ARRAY_SIZE(keyAttrs)))
1222 OVS_LOG_ERROR("Key Attr Parsing failed for msg: %p",
1224 rc = STATUS_INVALID_PARAMETER;
1228 if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
1229 tunnelKeyAttrOffset = (UINT32)((PCHAR)
1230 (keyAttrs[OVS_KEY_ATTR_TUNNEL])
1233 /* Get tunnel keys attributes */
1234 if ((NlAttrParseNested(nlMsgHdr, tunnelKeyAttrOffset,
1235 NlAttrLen(keyAttrs[OVS_KEY_ATTR_TUNNEL]),
1236 nlFlowTunnelKeyPolicy,
1237 ARRAY_SIZE(nlFlowTunnelKeyPolicy),
1238 tunnelAttrs, ARRAY_SIZE(tunnelAttrs)))
1240 OVS_LOG_ERROR("Tunnel key Attr Parsing failed for msg: %p",
1242 rc = STATUS_INVALID_PARAMETER;
1247 _MapKeyAttrToFlowPut(keyAttrs, tunnelAttrs,
1248 &(mappedFlow->key));
1250 /* Map the action */
1252 mappedFlow->actionsLen = NlAttrGetSize(actionAttr);
1253 mappedFlow->actions = NlAttrGet(actionAttr);
1256 mappedFlow->dpNo = ovsHdr->dp_ifindex;
1258 _MapNlToFlowPutFlags(genlMsgHdr, flowAttrClear,
1266 *----------------------------------------------------------------------------
1267 * _MapNlToFlowPutFlags --
1268 * Maps netlink message to OvsFlowPut->flags.
1269 *----------------------------------------------------------------------------
1272 _MapNlToFlowPutFlags(PGENL_MSG_HDR genlMsgHdr,
1273 PNL_ATTR flowAttrClear, OvsFlowPut *mappedFlow)
1277 switch (genlMsgHdr->cmd) {
1278 case OVS_FLOW_CMD_NEW:
1279 flags |= OVSWIN_FLOW_PUT_CREATE;
1281 case OVS_FLOW_CMD_DEL:
1282 flags |= OVSWIN_FLOW_PUT_DELETE;
1284 case OVS_FLOW_CMD_SET:
1285 flags |= OVSWIN_FLOW_PUT_MODIFY;
1291 if (flowAttrClear) {
1292 flags |= OVSWIN_FLOW_PUT_CLEAR;
1295 mappedFlow->flags = flags;
1299 *----------------------------------------------------------------------------
1300 * _MapKeyAttrToFlowPut --
1301 * Converts FLOW_KEY attribute to OvsFlowPut->key.
1302 *----------------------------------------------------------------------------
1305 _MapKeyAttrToFlowPut(PNL_ATTR *keyAttrs,
1306 PNL_ATTR *tunnelAttrs,
1307 OvsFlowKey *destKey)
1309 _MapTunAttrToFlowPut(keyAttrs, tunnelAttrs, destKey);
1311 /* ===== L2 headers ===== */
1312 destKey->l2.inPort = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_IN_PORT]);
1314 if (keyAttrs[OVS_KEY_ATTR_ETHERNET]) {
1315 const struct ovs_key_ethernet *eth_key;
1316 eth_key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ETHERNET]);
1317 RtlCopyMemory(destKey->l2.dlSrc, eth_key->eth_src, ETH_ADDR_LEN);
1318 RtlCopyMemory(destKey->l2.dlDst, eth_key->eth_dst, ETH_ADDR_LEN);
1321 /* TODO: Ideally ETHERTYPE should not be optional.
1322 * But during vswitchd bootup we are seeing FLOW_ADD
1323 * requests with no ETHERTYPE attributes.
1324 * Need to verify this. */
1325 if (keyAttrs[OVS_KEY_ATTR_ETHERTYPE]) {
1326 destKey->l2.dlType = (NlAttrGetU16(keyAttrs
1327 [OVS_KEY_ATTR_ETHERTYPE]));
1330 if (keyAttrs[OVS_KEY_ATTR_VLAN]) {
1331 destKey->l2.vlanTci = NlAttrGetU16(keyAttrs[OVS_KEY_ATTR_VLAN]);
1334 /* ==== L3 + L4. ==== */
1335 destKey->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + OVS_L2_KEY_SIZE
1336 - destKey->l2.offset;
1338 switch (ntohs(destKey->l2.dlType)) {
1339 case ETH_TYPE_IPV4: {
1341 if (keyAttrs[OVS_KEY_ATTR_IPV4]) {
1342 const struct ovs_key_ipv4 *ipv4Key;
1344 ipv4Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_IPV4]);
1345 IpKey *ipv4FlowPutKey = &(destKey->ipKey);
1346 ipv4FlowPutKey->nwSrc = ipv4Key->ipv4_src;
1347 ipv4FlowPutKey->nwDst = ipv4Key->ipv4_dst;
1348 ipv4FlowPutKey->nwProto = ipv4Key->ipv4_proto;
1349 ipv4FlowPutKey->nwTos = ipv4Key->ipv4_tos;
1350 ipv4FlowPutKey->nwTtl = ipv4Key->ipv4_ttl;
1351 ipv4FlowPutKey->nwFrag = ipv4Key->ipv4_frag;
1353 if (keyAttrs[OVS_KEY_ATTR_TCP]) {
1354 const struct ovs_key_tcp *tcpKey;
1355 tcpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_TCP]);
1356 ipv4FlowPutKey->l4.tpSrc = tcpKey->tcp_src;
1357 ipv4FlowPutKey->l4.tpDst = tcpKey->tcp_dst;
1360 if (keyAttrs[OVS_KEY_ATTR_UDP]) {
1361 const struct ovs_key_udp *udpKey;
1362 udpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_UDP]);
1363 ipv4FlowPutKey->l4.tpSrc = udpKey->udp_src;
1364 ipv4FlowPutKey->l4.tpDst = udpKey->udp_dst;
1367 if (keyAttrs[OVS_KEY_ATTR_SCTP]) {
1368 const struct ovs_key_sctp *sctpKey;
1369 sctpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_SCTP]);
1370 ipv4FlowPutKey->l4.tpSrc = sctpKey->sctp_src;
1371 ipv4FlowPutKey->l4.tpDst = sctpKey->sctp_dst;
1374 destKey->l2.keyLen += OVS_IP_KEY_SIZE;
1378 case ETH_TYPE_IPV6: {
1380 if (keyAttrs[OVS_KEY_ATTR_IPV6]) {
1381 const struct ovs_key_ipv6 *ipv6Key;
1383 ipv6Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_IPV6]);
1384 Ipv6Key *ipv6FlowPutKey = &(destKey->ipv6Key);
1386 RtlCopyMemory(&ipv6FlowPutKey->ipv6Src, ipv6Key->ipv6_src,
1387 sizeof ipv6Key->ipv6_src);
1388 RtlCopyMemory(&ipv6FlowPutKey->ipv6Dst, ipv6Key->ipv6_dst,
1389 sizeof ipv6Key->ipv6_dst);
1391 ipv6FlowPutKey->ipv6Label = ipv6Key->ipv6_label;
1392 ipv6FlowPutKey->nwProto = ipv6Key->ipv6_proto;
1393 ipv6FlowPutKey->nwTos = ipv6Key->ipv6_tclass;
1394 ipv6FlowPutKey->nwTtl = ipv6Key->ipv6_hlimit;
1395 ipv6FlowPutKey->nwFrag = ipv6Key->ipv6_frag;
1397 if (keyAttrs[OVS_KEY_ATTR_TCP]) {
1398 const struct ovs_key_tcp *tcpKey;
1399 tcpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_TCP]);
1400 ipv6FlowPutKey->l4.tpSrc = tcpKey->tcp_src;
1401 ipv6FlowPutKey->l4.tpDst = tcpKey->tcp_dst;
1404 if (keyAttrs[OVS_KEY_ATTR_UDP]) {
1405 const struct ovs_key_udp *udpKey;
1406 udpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_UDP]);
1407 ipv6FlowPutKey->l4.tpSrc = udpKey->udp_src;
1408 ipv6FlowPutKey->l4.tpDst = udpKey->udp_dst;
1411 if (keyAttrs[OVS_KEY_ATTR_SCTP]) {
1412 const struct ovs_key_sctp *sctpKey;
1413 sctpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_SCTP]);
1414 ipv6FlowPutKey->l4.tpSrc = sctpKey->sctp_src;
1415 ipv6FlowPutKey->l4.tpDst = sctpKey->sctp_dst;
1418 if (keyAttrs[OVS_KEY_ATTR_ICMPV6]) {
1419 const struct ovs_key_icmpv6 *icmpv6Key;
1421 Icmp6Key *icmp6FlowPutKey= &(destKey->icmp6Key);
1423 icmpv6Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ICMPV6]);
1425 icmp6FlowPutKey->l4.tpSrc = icmpv6Key->icmpv6_type;
1426 icmp6FlowPutKey->l4.tpDst = icmpv6Key->icmpv6_code;
1428 if (keyAttrs[OVS_KEY_ATTR_ND]) {
1429 const struct ovs_key_nd *ndKey;
1431 ndKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ND]);
1432 RtlCopyMemory(&icmp6FlowPutKey->ndTarget,
1433 ndKey->nd_target, sizeof (icmp6FlowPutKey->ndTarget));
1434 RtlCopyMemory(icmp6FlowPutKey->arpSha,
1435 ndKey->nd_sll, ETH_ADDR_LEN);
1436 RtlCopyMemory(icmp6FlowPutKey->arpTha,
1437 ndKey->nd_tll, ETH_ADDR_LEN);
1440 destKey->l2.keyLen += OVS_ICMPV6_KEY_SIZE;
1444 destKey->l2.keyLen += OVS_IPV6_KEY_SIZE;
1447 ipv6FlowPutKey->pad = 0;
1452 case ETH_TYPE_RARP: {
1454 if (keyAttrs[OVS_KEY_ATTR_ARP]) {
1455 ArpKey *arpFlowPutKey = &destKey->arpKey;
1456 const struct ovs_key_arp *arpKey;
1458 arpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ARP]);
1460 arpFlowPutKey->nwSrc = arpKey->arp_sip;
1461 arpFlowPutKey->nwDst = arpKey->arp_tip;
1463 RtlCopyMemory(arpFlowPutKey->arpSha, arpKey->arp_sha, ETH_ADDR_LEN);
1464 RtlCopyMemory(arpFlowPutKey->arpTha, arpKey->arp_tha, ETH_ADDR_LEN);
1465 /* Kernel datapath assumes 'arpFlowPutKey->nwProto' to be in host
1467 arpFlowPutKey->nwProto = (UINT8)ntohs((arpKey->arp_op));
1468 arpFlowPutKey->pad[0] = 0;
1469 arpFlowPutKey->pad[1] = 0;
1470 arpFlowPutKey->pad[2] = 0;
1471 destKey->l2.keyLen += OVS_ARP_KEY_SIZE;
1479 *----------------------------------------------------------------------------
1480 * _MapTunAttrToFlowPut --
1481 * Converts FLOW_TUNNEL_KEY attribute to OvsFlowKey->tunKey.
1482 *----------------------------------------------------------------------------
1485 _MapTunAttrToFlowPut(PNL_ATTR *keyAttrs,
1487 OvsFlowKey *destKey)
1489 if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
1491 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_ID]) {
1492 destKey->tunKey.tunnelId = NlAttrGetU64
1493 (tunAttrs[OVS_TUNNEL_KEY_ATTR_ID]);
1494 destKey->tunKey.flags |= OVS_TNL_F_KEY;
1497 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_DST]) {
1498 destKey->tunKey.dst = NlAttrGetU32
1499 (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_DST]);
1502 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_SRC]) {
1503 destKey->tunKey.src = NlAttrGetU32
1504 (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_SRC]);
1507 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT]) {
1508 destKey->tunKey.flags |= OVS_TNL_F_DONT_FRAGMENT;
1511 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_CSUM]) {
1512 destKey->tunKey.flags |= OVS_TNL_F_CSUM;
1515 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_TOS]) {
1516 destKey->tunKey.tos = NlAttrGetU8
1517 (tunAttrs[OVS_TUNNEL_KEY_ATTR_TOS]);
1520 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_TTL]) {
1521 destKey->tunKey.ttl = NlAttrGetU8
1522 (tunAttrs[OVS_TUNNEL_KEY_ATTR_TTL]);
1525 destKey->tunKey.pad = 0;
1526 destKey->l2.offset = 0;
1528 destKey->tunKey.attr[0] = 0;
1529 destKey->tunKey.attr[1] = 0;
1530 destKey->tunKey.attr[2] = 0;
1531 destKey->l2.offset = sizeof destKey->tunKey;
1536 *----------------------------------------------------------------------------
1537 * OvsDeleteFlowTable --
1539 * NDIS_STATUS_SUCCESS always.
1540 *----------------------------------------------------------------------------
1543 OvsDeleteFlowTable(OVS_DATAPATH *datapath)
1545 if (datapath == NULL || datapath->flowTable == NULL) {
1546 return NDIS_STATUS_SUCCESS;
1549 DeleteAllFlows(datapath);
1550 OvsFreeMemoryWithTag(datapath->flowTable, OVS_FLOW_POOL_TAG);
1551 datapath->flowTable = NULL;
1553 if (datapath->lock == NULL) {
1554 return NDIS_STATUS_SUCCESS;
1557 NdisFreeRWLock(datapath->lock);
1559 return NDIS_STATUS_SUCCESS;
1563 *----------------------------------------------------------------------------
1564 * OvsAllocateFlowTable --
1566 * NDIS_STATUS_SUCCESS on success.
1567 * NDIS_STATUS_RESOURCES if memory couldn't be allocated
1568 *----------------------------------------------------------------------------
1571 OvsAllocateFlowTable(OVS_DATAPATH *datapath,
1572 POVS_SWITCH_CONTEXT switchContext)
1577 datapath->flowTable = OvsAllocateMemoryWithTag(
1578 OVS_FLOW_TABLE_SIZE * sizeof(LIST_ENTRY), OVS_FLOW_POOL_TAG);
1579 if (!datapath->flowTable) {
1580 return NDIS_STATUS_RESOURCES;
1582 for (i = 0; i < OVS_FLOW_TABLE_SIZE; i++) {
1583 bucket = &(datapath->flowTable[i]);
1584 InitializeListHead(bucket);
1586 datapath->lock = NdisAllocateRWLock(switchContext->NdisFilterHandle);
1588 if (!datapath->lock) {
1589 return NDIS_STATUS_RESOURCES;
1592 return NDIS_STATUS_SUCCESS;
1597 *----------------------------------------------------------------------------
1598 * GetStartAddrNBL --
1599 * Get the virtual address of the frame.
1602 * Virtual address of the frame.
1603 *----------------------------------------------------------------------------
1605 static __inline VOID *
1606 GetStartAddrNBL(const NET_BUFFER_LIST *_pNB)
1614 // Ethernet Header is a guaranteed safe access.
1615 curMdl = (NET_BUFFER_LIST_FIRST_NB(_pNB))->CurrentMdl;
1616 curBuffer = MmGetSystemAddressForMdlSafe(curMdl, LowPagePriority);
1621 curHeader = (PEthHdr)
1622 (curBuffer + (NET_BUFFER_LIST_FIRST_NB(_pNB))->CurrentMdlOffset);
1624 return (VOID *) curHeader;
1628 OvsFlowUsed(OvsFlow *flow,
1629 const NET_BUFFER_LIST *packet,
1630 const POVS_PACKET_HDR_INFO layers)
1632 LARGE_INTEGER tickCount;
1634 KeQueryTickCount(&tickCount);
1635 flow->used = tickCount.QuadPart * ovsTimeIncrementPerTick;
1636 flow->packetCount++;
1637 flow->byteCount += OvsPacketLenNBL(packet);
1638 flow->tcpFlags |= OvsGetTcpFlags(packet, &flow->key, layers);
1643 DeleteAllFlows(OVS_DATAPATH *datapath)
1648 for (i = 0; i < OVS_FLOW_TABLE_SIZE; i++) {
1650 bucket = &(datapath->flowTable[i]);
1651 while (!IsListEmpty(bucket)) {
1653 next = bucket->Flink;
1654 flow = CONTAINING_RECORD(next, OvsFlow, ListEntry);
1655 RemoveFlow(datapath, &flow);
1661 *----------------------------------------------------------------------------
1662 * Initializes 'flow' members from 'packet', 'skb_priority', 'tun_id', and
1665 * Initializes 'packet' header pointers as follows:
1667 * - packet->l2 to the start of the Ethernet header.
1669 * - packet->l3 to just past the Ethernet header, or just past the
1670 * vlan_header if one is present, to the first byte of the payload of the
1673 * - packet->l4 to just past the IPv4 header, if one is present and has a
1674 * correct length, and otherwise NULL.
1676 * - packet->l7 to just past the TCP or UDP or ICMP header, if one is
1677 * present and has a correct length, and otherwise NULL.
1679 * Returns NDIS_STATUS_SUCCESS normally. Fails only if packet data cannot be accessed
1680 * (e.g. if Pkt_CopyBytesOut() returns an error).
1681 *----------------------------------------------------------------------------
1684 OvsExtractFlow(const NET_BUFFER_LIST *packet,
1687 POVS_PACKET_HDR_INFO layers,
1688 OvsIPv4TunnelKey *tunKey)
1690 struct Eth_Header *eth;
1697 ASSERT(tunKey->dst != 0);
1698 RtlMoveMemory(&flow->tunKey, tunKey, sizeof flow->tunKey);
1699 flow->l2.offset = 0;
1701 flow->tunKey.dst = 0;
1702 flow->l2.offset = OVS_WIN_TUNNEL_KEY_SIZE;
1705 flow->l2.inPort = inPort;
1707 if ( OvsPacketLenNBL(packet) < ETH_HEADER_LEN_DIX) {
1708 flow->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + 8 - flow->l2.offset;
1709 return NDIS_STATUS_SUCCESS;
1713 eth = (Eth_Header *)GetStartAddrNBL((NET_BUFFER_LIST *)packet);
1714 memcpy(flow->l2.dlSrc, eth->src, ETH_ADDR_LENGTH);
1715 memcpy(flow->l2.dlDst, eth->dst, ETH_ADDR_LENGTH);
1720 vlanTagValue = NET_BUFFER_LIST_INFO(packet, Ieee8021QNetBufferListInfo);
1722 PNDIS_NET_BUFFER_LIST_8021Q_INFO vlanTag =
1723 (PNDIS_NET_BUFFER_LIST_8021Q_INFO)(PVOID *)&vlanTagValue;
1724 flow->l2.vlanTci = htons(vlanTag->TagHeader.VlanId | OVSWIN_VLAN_CFI |
1725 (vlanTag->TagHeader.UserPriority << 13));
1727 if (eth->dix.typeNBO == ETH_TYPE_802_1PQ_NBO) {
1728 Eth_802_1pq_Tag *tag= (Eth_802_1pq_Tag *)ð->dix.typeNBO;
1729 flow->l2.vlanTci = ((UINT16)tag->priority << 13) |
1731 ((UINT16)tag->vidHi << 8) | tag->vidLo;
1732 offset = sizeof (Eth_802_1pq_Tag);
1734 flow->l2.vlanTci = 0;
1738 * Please note after this point, src mac and dst mac should
1739 * not be accessed through eth
1741 eth = (Eth_Header *)((UINT8 *)eth + offset);
1747 * XXX assume that at least the first
1748 * 12 bytes of received packets are mapped. This code has the stronger
1749 * assumption that at least the first 22 bytes of 'packet' is mapped (if my
1750 * arithmetic is right).
1752 if (ETH_TYPENOT8023(eth->dix.typeNBO)) {
1753 flow->l2.dlType = eth->dix.typeNBO;
1754 layers->l3Offset = ETH_HEADER_LEN_DIX + offset;
1755 } else if (OvsPacketLenNBL(packet) >= ETH_HEADER_LEN_802_3 &&
1756 eth->e802_3.llc.dsap == 0xaa &&
1757 eth->e802_3.llc.ssap == 0xaa &&
1758 eth->e802_3.llc.control == ETH_LLC_CONTROL_UFRAME &&
1759 eth->e802_3.snap.snapOrg[0] == 0x00 &&
1760 eth->e802_3.snap.snapOrg[1] == 0x00 &&
1761 eth->e802_3.snap.snapOrg[2] == 0x00) {
1762 flow->l2.dlType = eth->e802_3.snap.snapType.typeNBO;
1763 layers->l3Offset = ETH_HEADER_LEN_802_3 + offset;
1765 flow->l2.dlType = htons(OVSWIN_DL_TYPE_NONE);
1766 layers->l3Offset = ETH_HEADER_LEN_DIX + offset;
1769 flow->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + OVS_L2_KEY_SIZE - flow->l2.offset;
1770 /* Network layer. */
1771 if (flow->l2.dlType == htons(ETH_TYPE_IPV4)) {
1772 struct IPHdr ip_storage;
1773 const struct IPHdr *nh;
1774 IpKey *ipKey = &flow->ipKey;
1776 flow->l2.keyLen += OVS_IP_KEY_SIZE;
1778 nh = OvsGetIp(packet, layers->l3Offset, &ip_storage);
1780 layers->l4Offset = layers->l3Offset + nh->ihl * 4;
1782 ipKey->nwSrc = nh->saddr;
1783 ipKey->nwDst = nh->daddr;
1784 ipKey->nwProto = nh->protocol;
1786 ipKey->nwTos = nh->tos;
1787 if (nh->frag_off & htons(IP_MF | IP_OFFSET)) {
1788 ipKey->nwFrag = OVS_FRAG_TYPE_FIRST;
1789 if (nh->frag_off & htons(IP_OFFSET)) {
1790 ipKey->nwFrag = OVS_FRAG_TYPE_LATER;
1793 ipKey->nwFrag = OVS_FRAG_TYPE_NONE;
1796 ipKey->nwTtl = nh->ttl;
1797 ipKey->l4.tpSrc = 0;
1798 ipKey->l4.tpDst = 0;
1800 if (!(nh->frag_off & htons(IP_OFFSET))) {
1801 if (ipKey->nwProto == SOCKET_IPPROTO_TCP) {
1802 OvsParseTcp(packet, &ipKey->l4, layers);
1803 } else if (ipKey->nwProto == SOCKET_IPPROTO_UDP) {
1804 OvsParseUdp(packet, &ipKey->l4, layers);
1805 } else if (ipKey->nwProto == SOCKET_IPPROTO_ICMP) {
1806 ICMPHdr icmpStorage;
1807 const ICMPHdr *icmp;
1809 icmp = OvsGetIcmp(packet, layers->l4Offset, &icmpStorage);
1811 ipKey->l4.tpSrc = htons(icmp->type);
1812 ipKey->l4.tpDst = htons(icmp->code);
1813 layers->l7Offset = layers->l4Offset + sizeof *icmp;
1818 ((UINT64 *)ipKey)[0] = 0;
1819 ((UINT64 *)ipKey)[1] = 0;
1821 } else if (flow->l2.dlType == htons(ETH_TYPE_IPV6)) {
1823 flow->l2.keyLen += OVS_IPV6_KEY_SIZE;
1824 status = OvsParseIPv6(packet, flow, layers);
1825 if (status != NDIS_STATUS_SUCCESS) {
1826 memset(&flow->ipv6Key, 0, sizeof (Ipv6Key));
1830 flow->ipv6Key.l4.tpSrc = 0;
1831 flow->ipv6Key.l4.tpDst = 0;
1832 flow->ipv6Key.pad = 0;
1834 if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_TCP) {
1835 OvsParseTcp(packet, &(flow->ipv6Key.l4), layers);
1836 } else if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_UDP) {
1837 OvsParseUdp(packet, &(flow->ipv6Key.l4), layers);
1838 } else if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_ICMPV6) {
1839 OvsParseIcmpV6(packet, flow, layers);
1840 flow->l2.keyLen += (OVS_ICMPV6_KEY_SIZE - OVS_IPV6_KEY_SIZE);
1842 } else if (flow->l2.dlType == htons(ETH_TYPE_ARP)) {
1843 EtherArp arpStorage;
1844 const EtherArp *arp;
1845 ArpKey *arpKey = &flow->arpKey;
1846 ((UINT64 *)arpKey)[0] = 0;
1847 ((UINT64 *)arpKey)[1] = 0;
1848 ((UINT64 *)arpKey)[2] = 0;
1849 flow->l2.keyLen += OVS_ARP_KEY_SIZE;
1850 arp = OvsGetArp(packet, layers->l3Offset, &arpStorage);
1851 if (arp && arp->ea_hdr.ar_hrd == htons(1) &&
1852 arp->ea_hdr.ar_pro == htons(ETH_TYPE_IPV4) &&
1853 arp->ea_hdr.ar_hln == ETH_ADDR_LENGTH &&
1854 arp->ea_hdr.ar_pln == 4) {
1855 /* We only match on the lower 8 bits of the opcode. */
1856 if (ntohs(arp->ea_hdr.ar_op) <= 0xff) {
1857 arpKey->nwProto = (UINT8)ntohs(arp->ea_hdr.ar_op);
1859 if (arpKey->nwProto == ARPOP_REQUEST
1860 || arpKey->nwProto == ARPOP_REPLY) {
1861 memcpy(&arpKey->nwSrc, arp->arp_spa, 4);
1862 memcpy(&arpKey->nwDst, arp->arp_tpa, 4);
1863 memcpy(arpKey->arpSha, arp->arp_sha, ETH_ADDR_LENGTH);
1864 memcpy(arpKey->arpTha, arp->arp_tha, ETH_ADDR_LENGTH);
1869 return NDIS_STATUS_SUCCESS;
1873 FlowEqual(UINT64 *src, UINT64 *dst, UINT32 size)
1876 ASSERT((size & 0x7) == 0);
1877 ASSERT(((UINT64)src & 0x7) == 0);
1878 ASSERT(((UINT64)dst & 0x7) == 0);
1879 for (i = 0; i < (size >> 3); i++) {
1880 if (src[i] != dst[i]) {
1889 * ----------------------------------------------------------------------------
1891 * Add a flow to flow table.
1894 * NDIS_STATUS_SUCCESS if no same flow in the flow table.
1895 * ----------------------------------------------------------------------------
1898 AddFlow(OVS_DATAPATH *datapath, OvsFlow *flow)
1902 if (OvsLookupFlow(datapath, &flow->key, &flow->hash, TRUE) != NULL) {
1903 return STATUS_INVALID_HANDLE;
1906 head = &(datapath->flowTable[HASH_BUCKET(flow->hash)]);
1908 * We need fence here to make sure flow's nextPtr is updated before
1909 * head->nextPtr is updated.
1913 //KeAcquireSpinLock(&FilterDeviceExtension->NblQueueLock, &oldIrql);
1914 InsertTailList(head, &flow->ListEntry);
1915 //KeReleaseSpinLock(&FilterDeviceExtension->NblQueueLock, oldIrql);
1919 return STATUS_SUCCESS;
1923 /* ----------------------------------------------------------------------------
1925 * Remove a flow from flow table, and added to wait list
1926 * ----------------------------------------------------------------------------
1929 RemoveFlow(OVS_DATAPATH *datapath,
1935 ASSERT(datapath->nFlows);
1937 // Remove the flow from queue
1938 RemoveEntryList(&f->ListEntry);
1944 * ----------------------------------------------------------------------------
1947 * Find flow from flow table based on flow key.
1948 * Caller should either hold portset handle or should
1949 * have a flowRef in datapath or Acquired datapath.
1952 * Flow pointer if lookup successful.
1953 * NULL if not exists.
1954 * ----------------------------------------------------------------------------
1957 OvsLookupFlow(OVS_DATAPATH *datapath,
1958 const OvsFlowKey *key,
1962 PLIST_ENTRY link, head;
1963 UINT16 offset = key->l2.offset;
1964 UINT16 size = key->l2.keyLen;
1967 ASSERT(key->tunKey.dst || offset == sizeof (OvsIPv4TunnelKey));
1968 ASSERT(!key->tunKey.dst || offset == 0);
1970 start = (UINT8 *)key + offset;
1973 *hash = OvsJhashBytes(start, size, 0);
1976 head = &datapath->flowTable[HASH_BUCKET(*hash)];
1978 while (link != head) {
1979 OvsFlow *flow = CONTAINING_RECORD(link, OvsFlow, ListEntry);
1981 if (flow->hash == *hash &&
1982 flow->key.l2.val == key->l2.val &&
1983 FlowEqual((UINT64 *)((uint8 *)&flow->key + offset),
1984 (UINT64 *)start, size)) {
1994 * ----------------------------------------------------------------------------
1996 * Calculate the hash for the given flow key.
1997 * ----------------------------------------------------------------------------
2000 OvsHashFlow(const OvsFlowKey *key)
2002 UINT16 offset = key->l2.offset;
2003 UINT16 size = key->l2.keyLen;
2006 ASSERT(key->tunKey.dst || offset == sizeof (OvsIPv4TunnelKey));
2007 ASSERT(!key->tunKey.dst || offset == 0);
2008 start = (UINT8 *)key + offset;
2009 return OvsJhashBytes(start, size, 0);
2014 * ----------------------------------------------------------------------------
2016 * Free a flow and its actions.
2017 * ----------------------------------------------------------------------------
2020 FreeFlow(OvsFlow *flow)
2023 OvsFreeMemoryWithTag(flow, OVS_FLOW_POOL_TAG);
2027 OvsDoDumpFlows(OvsFlowDumpInput *dumpInput,
2028 OvsFlowDumpOutput *dumpOutput,
2032 OVS_DATAPATH *datapath = NULL;
2034 PLIST_ENTRY node, head;
2036 UINT32 rowIndex, columnIndex;
2037 LOCK_STATE_EX dpLockState;
2038 NTSTATUS status = STATUS_SUCCESS;
2039 BOOLEAN findNextNonEmpty = FALSE;
2041 dpNo = dumpInput->dpNo;
2042 if (gOvsSwitchContext->dpNo != dpNo) {
2043 status = STATUS_INVALID_PARAMETER;
2047 rowIndex = dumpInput->position[0];
2048 if (rowIndex >= OVS_FLOW_TABLE_SIZE) {
2050 *replyLen = sizeof(*dumpOutput);
2054 columnIndex = dumpInput->position[1];
2056 datapath = &gOvsSwitchContext->datapath;
2058 OvsAcquireDatapathRead(datapath, &dpLockState, FALSE);
2060 head = &datapath->flowTable[rowIndex];
2063 while (column < columnIndex) {
2072 findNextNonEmpty = TRUE;
2076 if (findNextNonEmpty) {
2077 while (head == node) {
2078 if (++rowIndex >= OVS_FLOW_TABLE_SIZE) {
2082 head = &datapath->flowTable[rowIndex];
2087 ASSERT(node != head);
2088 ASSERT(rowIndex < OVS_FLOW_TABLE_SIZE);
2090 flow = CONTAINING_RECORD(node, OvsFlow, ListEntry);
2091 status = ReportFlowInfo(flow, dumpInput->getFlags, &dumpOutput->flow);
2093 if (status == STATUS_BUFFER_TOO_SMALL) {
2094 dumpOutput->n = sizeof(OvsFlowDumpOutput) + flow->actionsLen;
2095 *replyLen = sizeof(*dumpOutput);
2097 dumpOutput->n = 1; //one flow reported.
2098 *replyLen = sizeof(*dumpOutput) + dumpOutput->flow.actionsLen;
2101 dumpOutput->position[0] = rowIndex;
2102 dumpOutput->position[1] = ++columnIndex;
2105 OvsReleaseDatapath(datapath, &dpLockState);
2112 ReportFlowInfo(OvsFlow *flow,
2116 NTSTATUS status = STATUS_SUCCESS;
2118 if (getFlags & FLOW_GET_KEY) {
2119 // always copy the tunnel key part
2120 RtlCopyMemory(&info->key, &flow->key,
2121 flow->key.l2.keyLen + flow->key.l2.offset);
2124 if (getFlags & FLOW_GET_STATS) {
2125 OvsFlowStats *stats = &info->stats;
2126 stats->packetCount = flow->packetCount;
2127 stats->byteCount = flow->byteCount;
2128 stats->used = (UINT32)flow->used;
2129 stats->tcpFlags = flow->tcpFlags;
2132 if (getFlags & FLOW_GET_ACTIONS) {
2133 if (flow->actionsLen == 0) {
2134 info->actionsLen = 0;
2136 info->actions = flow->actions;
2137 info->actionsLen = flow->actionsLen;
2145 OvsPutFlowIoctl(PVOID inputBuffer,
2147 struct OvsFlowStats *stats)
2149 NTSTATUS status = STATUS_SUCCESS;
2150 OVS_DATAPATH *datapath = NULL;
2154 LOCK_STATE_EX dpLockState;
2156 if ((inputLength < sizeof(OvsFlowPut)) || (inputBuffer == NULL)) {
2157 return STATUS_INFO_LENGTH_MISMATCH;
2160 put = (OvsFlowPut *)inputBuffer;
2161 if (put->actionsLen > 0) {
2162 actionsLen = put->actionsLen;
2168 if (gOvsSwitchContext->dpNo != dpNo) {
2169 status = STATUS_INVALID_PARAMETER;
2173 datapath = &gOvsSwitchContext->datapath;
2175 OvsAcquireDatapathWrite(datapath, &dpLockState, FALSE);
2176 status = HandleFlowPut(put, datapath, stats);
2177 OvsReleaseDatapath(datapath, &dpLockState);
2184 /* Handles flow add, modify as well as delete */
2186 HandleFlowPut(OvsFlowPut *put,
2187 OVS_DATAPATH *datapath,
2188 struct OvsFlowStats *stats)
2190 BOOLEAN mayCreate, mayModify, mayDelete;
2191 OvsFlow *KernelFlow;
2193 NTSTATUS status = STATUS_SUCCESS;
2195 mayCreate = (put->flags & OVSWIN_FLOW_PUT_CREATE) != 0;
2196 mayModify = (put->flags & OVSWIN_FLOW_PUT_MODIFY) != 0;
2197 mayDelete = (put->flags & OVSWIN_FLOW_PUT_DELETE) != 0;
2199 if ((mayCreate || mayModify) == mayDelete) {
2200 return STATUS_INVALID_PARAMETER;
2203 KernelFlow = OvsLookupFlow(datapath, &put->key, &hash, FALSE);
2206 return STATUS_INVALID_PARAMETER;
2209 status = OvsPrepareFlow(&KernelFlow, put, hash);
2210 if (status != STATUS_SUCCESS) {
2211 return STATUS_UNSUCCESSFUL;
2214 status = AddFlow(datapath, KernelFlow);
2215 if (status != STATUS_SUCCESS) {
2216 FreeFlow(KernelFlow);
2217 return STATUS_UNSUCCESSFUL;
2220 /* Validate the flow addition */
2223 OvsFlow *flow = OvsLookupFlow(datapath, &put->key, &newHash,
2226 ASSERT(newHash == hash);
2227 if (!flow || newHash != hash) {
2228 return STATUS_UNSUCCESSFUL;
2232 stats->packetCount = KernelFlow->packetCount;
2233 stats->byteCount = KernelFlow->byteCount;
2234 stats->tcpFlags = KernelFlow->tcpFlags;
2235 stats->used = (UINT32)KernelFlow->used;
2239 status = OvsPrepareFlow(&newFlow, put, hash);
2240 if (status != STATUS_SUCCESS) {
2241 return STATUS_UNSUCCESSFUL;
2244 KernelFlow = OvsLookupFlow(datapath, &put->key, &hash, TRUE);
2246 if ((put->flags & OVSWIN_FLOW_PUT_CLEAR) == 0) {
2247 newFlow->packetCount = KernelFlow->packetCount;
2248 newFlow->byteCount = KernelFlow->byteCount;
2249 newFlow->tcpFlags = KernelFlow->tcpFlags;
2251 RemoveFlow(datapath, &KernelFlow);
2253 if ((put->flags & OVSWIN_FLOW_PUT_CLEAR) == 0) {
2254 newFlow->packetCount = stats->packetCount;
2255 newFlow->byteCount = stats->byteCount;
2256 newFlow->tcpFlags = stats->tcpFlags;
2259 status = AddFlow(datapath, newFlow);
2260 ASSERT(status == STATUS_SUCCESS);
2262 /* Validate the flow addition */
2265 OvsFlow *testflow = OvsLookupFlow(datapath, &put->key,
2268 ASSERT(newHash == hash);
2269 if (!testflow || newHash != hash) {
2271 return STATUS_UNSUCCESSFUL;
2277 RemoveFlow(datapath, &KernelFlow);
2280 /* Return success if an identical flow already exists. */
2281 /* XXX: should we return EEXIST in a netlink error? */
2282 return STATUS_SUCCESS;
2286 return STATUS_SUCCESS;
2290 OvsPrepareFlow(OvsFlow **flow,
2291 const OvsFlowPut *put,
2294 OvsFlow *localFlow = *flow;
2295 NTSTATUS status = STATUS_SUCCESS;
2299 OvsAllocateMemoryWithTag(sizeof(OvsFlow) + put->actionsLen,
2301 if (localFlow == NULL) {
2302 status = STATUS_NO_MEMORY;
2306 localFlow->key = put->key;
2307 localFlow->actionsLen = put->actionsLen;
2308 if (put->actionsLen) {
2309 NdisMoveMemory((PUCHAR)localFlow->actions, put->actions,
2312 localFlow->userActionsLen = 0; // 0 indicate no conversion is made
2313 localFlow->used = 0;
2314 localFlow->packetCount = 0;
2315 localFlow->byteCount = 0;
2316 localFlow->tcpFlags = 0;
2317 localFlow->hash = hash;
2324 OvsGetFlowIoctl(PVOID inputBuffer,
2327 NTSTATUS status = STATUS_SUCCESS;
2328 OVS_DATAPATH *datapath = NULL;
2330 UINT32 getFlags, getActionsLen;
2331 OvsFlowGetInput *getInput;
2332 OvsFlowGetOutput *getOutput;
2335 LOCK_STATE_EX dpLockState;
2337 getInput = (OvsFlowGetInput *) inputBuffer;
2338 getFlags = getInput->getFlags;
2339 getActionsLen = getInput->actionsLen;
2341 if (outputBuffer == NULL) {
2342 return STATUS_INFO_LENGTH_MISMATCH;
2345 dpNo = getInput->dpNo;
2346 if (gOvsSwitchContext->dpNo != dpNo) {
2347 status = STATUS_INVALID_PARAMETER;
2351 datapath = &gOvsSwitchContext->datapath;
2353 OvsAcquireDatapathRead(datapath, &dpLockState, FALSE);
2354 flow = OvsLookupFlow(datapath, &getInput->key, &hash, FALSE);
2356 status = STATUS_INVALID_PARAMETER;
2360 getOutput = (OvsFlowGetOutput *)outputBuffer;
2361 ReportFlowInfo(flow, getFlags, &getOutput->info);
2364 OvsReleaseDatapath(datapath, &dpLockState);
2370 OvsFlushFlowIoctl(UINT32 dpNo)
2372 NTSTATUS status = STATUS_SUCCESS;
2373 OVS_DATAPATH *datapath = NULL;
2374 LOCK_STATE_EX dpLockState;
2376 if (gOvsSwitchContext->dpNo != dpNo) {
2377 status = STATUS_INVALID_PARAMETER;
2381 datapath = &gOvsSwitchContext->datapath;
2383 OvsAcquireDatapathWrite(datapath, &dpLockState, FALSE);
2384 DeleteAllFlows(datapath);
2385 OvsReleaseDatapath(datapath, &dpLockState);
2392 OvsFlowKeyAttrSize(void)
2394 return NlAttrTotalSize(4) /* OVS_KEY_ATTR_PRIORITY */
2395 + NlAttrTotalSize(0) /* OVS_KEY_ATTR_TUNNEL */
2396 + OvsTunKeyAttrSize()
2397 + NlAttrTotalSize(4) /* OVS_KEY_ATTR_IN_PORT */
2398 + NlAttrTotalSize(4) /* OVS_KEY_ATTR_SKB_MARK */
2399 + NlAttrTotalSize(4) /* OVS_KEY_ATTR_DP_HASH */
2400 + NlAttrTotalSize(4) /* OVS_KEY_ATTR_RECIRC_ID */
2401 + NlAttrTotalSize(12) /* OVS_KEY_ATTR_ETHERNET */
2402 + NlAttrTotalSize(2) /* OVS_KEY_ATTR_ETHERTYPE */
2403 + NlAttrTotalSize(4) /* OVS_KEY_ATTR_VLAN */
2404 + NlAttrTotalSize(0) /* OVS_KEY_ATTR_ENCAP */
2405 + NlAttrTotalSize(2) /* OVS_KEY_ATTR_ETHERTYPE */
2406 + NlAttrTotalSize(40) /* OVS_KEY_ATTR_IPV6 */
2407 + NlAttrTotalSize(2) /* OVS_KEY_ATTR_ICMPV6 */
2408 + NlAttrTotalSize(28); /* OVS_KEY_ATTR_ND */
2412 OvsTunKeyAttrSize(void)
2414 /* Whenever adding new OVS_TUNNEL_KEY_ FIELDS, we should consider
2415 * updating this function.
2417 return NlAttrTotalSize(8) /* OVS_TUNNEL_KEY_ATTR_ID */
2418 + NlAttrTotalSize(4) /* OVS_TUNNEL_KEY_ATTR_IPV4_SRC */
2419 + NlAttrTotalSize(4) /* OVS_TUNNEL_KEY_ATTR_IPV4_DST */
2420 + NlAttrTotalSize(1) /* OVS_TUNNEL_KEY_ATTR_TOS */
2421 + NlAttrTotalSize(1) /* OVS_TUNNEL_KEY_ATTR_TTL */
2422 + NlAttrTotalSize(0) /* OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT */
2423 + NlAttrTotalSize(0) /* OVS_TUNNEL_KEY_ATTR_CSUM */
2424 + NlAttrTotalSize(0) /* OVS_TUNNEL_KEY_ATTR_OAM */
2425 + NlAttrTotalSize(256) /* OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS */
2426 + NlAttrTotalSize(2) /* OVS_TUNNEL_KEY_ATTR_TP_SRC */
2427 + NlAttrTotalSize(2); /* OVS_TUNNEL_KEY_ATTR_TP_DST */
2430 #pragma warning( pop )