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}
108 /* For Parsing nested OVS_FLOW_ATTR_KEY attributes.
109 * Some of the attributes like OVS_KEY_ATTR_RECIRC_ID
110 * & OVS_KEY_ATTR_MPLS are not supported yet. */
112 const NL_POLICY nlFlowKeyPolicy[] = {
113 [OVS_KEY_ATTR_ENCAP] = {.type = NL_A_VAR_LEN, .optional = TRUE},
114 [OVS_KEY_ATTR_PRIORITY] = {.type = NL_A_UNSPEC, .minLen = 4,
115 .maxLen = 4, .optional = TRUE},
116 [OVS_KEY_ATTR_IN_PORT] = {.type = NL_A_UNSPEC, .minLen = 4,
117 .maxLen = 4, .optional = FALSE},
118 [OVS_KEY_ATTR_ETHERNET] = {.type = NL_A_UNSPEC,
119 .minLen = sizeof(struct ovs_key_ethernet),
120 .maxLen = sizeof(struct ovs_key_ethernet),
122 [OVS_KEY_ATTR_VLAN] = {.type = NL_A_UNSPEC, .minLen = 2,
123 .maxLen = 2, .optional = TRUE},
124 [OVS_KEY_ATTR_ETHERTYPE] = {.type = NL_A_UNSPEC, .minLen = 2,
125 .maxLen = 2, .optional = TRUE},
126 [OVS_KEY_ATTR_IPV4] = {.type = NL_A_UNSPEC,
127 .minLen = sizeof(struct ovs_key_ipv4),
128 .maxLen = sizeof(struct ovs_key_ipv4),
130 [OVS_KEY_ATTR_IPV6] = {.type = NL_A_UNSPEC,
131 .minLen = sizeof(struct ovs_key_ipv6),
132 .maxLen = sizeof(struct ovs_key_ipv6),
134 [OVS_KEY_ATTR_TCP] = {.type = NL_A_UNSPEC,
135 .minLen = sizeof(struct ovs_key_tcp),
136 .maxLen = sizeof(struct ovs_key_tcp),
138 [OVS_KEY_ATTR_UDP] = {.type = NL_A_UNSPEC,
139 .minLen = sizeof(struct ovs_key_udp),
140 .maxLen = sizeof(struct ovs_key_udp),
142 [OVS_KEY_ATTR_ICMP] = {.type = NL_A_UNSPEC,
143 .minLen = sizeof(struct ovs_key_icmp),
144 .maxLen = sizeof(struct ovs_key_icmp),
146 [OVS_KEY_ATTR_ICMPV6] = {.type = NL_A_UNSPEC,
147 .minLen = sizeof(struct ovs_key_icmpv6),
148 .maxLen = sizeof(struct ovs_key_icmpv6),
150 [OVS_KEY_ATTR_ARP] = {.type = NL_A_UNSPEC,
151 .minLen = sizeof(struct ovs_key_arp),
152 .maxLen = sizeof(struct ovs_key_arp),
154 [OVS_KEY_ATTR_ND] = {.type = NL_A_UNSPEC,
155 .minLen = sizeof(struct ovs_key_nd),
156 .maxLen = sizeof(struct ovs_key_nd),
158 [OVS_KEY_ATTR_SKB_MARK] = {.type = NL_A_UNSPEC, .minLen = 4,
159 .maxLen = 4, .optional = TRUE},
160 [OVS_KEY_ATTR_TUNNEL] = {.type = NL_A_VAR_LEN, .optional = TRUE},
161 [OVS_KEY_ATTR_SCTP] = {.type = NL_A_UNSPEC,
162 .minLen = sizeof(struct ovs_key_sctp),
163 .maxLen = sizeof(struct ovs_key_sctp),
165 [OVS_KEY_ATTR_TCP_FLAGS] = {.type = NL_A_UNSPEC,
166 .minLen = 2, .maxLen = 2,
168 [OVS_KEY_ATTR_DP_HASH] = {.type = NL_A_UNSPEC, .minLen = 4,
169 .maxLen = 4, .optional = TRUE},
170 [OVS_KEY_ATTR_RECIRC_ID] = {.type = NL_A_UNSPEC, .minLen = 4,
171 .maxLen = 4, .optional = TRUE},
172 [OVS_KEY_ATTR_MPLS] = {.type = NL_A_VAR_LEN, .optional = TRUE}
174 const UINT32 nlFlowKeyPolicyLen = ARRAY_SIZE(nlFlowKeyPolicy);
176 /* For Parsing nested OVS_KEY_ATTR_TUNNEL attributes */
177 const NL_POLICY nlFlowTunnelKeyPolicy[] = {
178 [OVS_TUNNEL_KEY_ATTR_ID] = {.type = NL_A_UNSPEC, .minLen = 8,
179 .maxLen = 8, .optional = TRUE},
180 [OVS_TUNNEL_KEY_ATTR_IPV4_SRC] = {.type = NL_A_UNSPEC, .minLen = 4,
181 .maxLen = 4, .optional = TRUE},
182 [OVS_TUNNEL_KEY_ATTR_IPV4_DST] = {.type = NL_A_UNSPEC, .minLen = 4 ,
183 .maxLen = 4, .optional = FALSE},
184 [OVS_TUNNEL_KEY_ATTR_TOS] = {.type = NL_A_UNSPEC, .minLen = 1,
185 .maxLen = 1, .optional = TRUE},
186 [OVS_TUNNEL_KEY_ATTR_TTL] = {.type = NL_A_UNSPEC, .minLen = 1,
187 .maxLen = 1, .optional = TRUE},
188 [OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT] = {.type = NL_A_UNSPEC, .minLen = 0,
189 .maxLen = 0, .optional = TRUE},
190 [OVS_TUNNEL_KEY_ATTR_CSUM] = {.type = NL_A_UNSPEC, .minLen = 0,
191 .maxLen = 0, .optional = TRUE},
192 [OVS_TUNNEL_KEY_ATTR_OAM] = {.type = NL_A_UNSPEC, .minLen = 0,
193 .maxLen = 0, .optional = TRUE},
194 [OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS] = {.type = NL_A_VAR_LEN,
198 /* For Parsing nested OVS_FLOW_ATTR_ACTIONS attributes */
199 const NL_POLICY nlFlowActionPolicy[] = {
200 [OVS_ACTION_ATTR_OUTPUT] = {.type = NL_A_UNSPEC, .minLen = sizeof(UINT32),
201 .maxLen = sizeof(UINT32), .optional = TRUE},
202 [OVS_ACTION_ATTR_USERSPACE] = {.type = NL_A_VAR_LEN, .optional = TRUE},
203 [OVS_ACTION_ATTR_PUSH_VLAN] = {.type = NL_A_UNSPEC,
205 sizeof(struct ovs_action_push_vlan),
207 sizeof(struct ovs_action_push_vlan),
209 [OVS_ACTION_ATTR_POP_VLAN] = {.type = NL_A_UNSPEC, .optional = TRUE},
210 [OVS_ACTION_ATTR_PUSH_MPLS] = {.type = NL_A_UNSPEC,
212 sizeof(struct ovs_action_push_mpls),
214 sizeof(struct ovs_action_push_mpls),
216 [OVS_ACTION_ATTR_POP_MPLS] = {.type = NL_A_UNSPEC,
217 .minLen = sizeof(UINT16),
218 .maxLen = sizeof(UINT16),
220 [OVS_ACTION_ATTR_RECIRC] = {.type = NL_A_UNSPEC,
221 .minLen = sizeof(UINT32),
222 .maxLen = sizeof(UINT32),
224 [OVS_ACTION_ATTR_HASH] = {.type = NL_A_UNSPEC,
225 .minLen = sizeof(struct ovs_action_hash),
226 .maxLen = sizeof(struct ovs_action_hash),
228 [OVS_ACTION_ATTR_SET] = {.type = NL_A_VAR_LEN, .optional = TRUE},
229 [OVS_ACTION_ATTR_SAMPLE] = {.type = NL_A_VAR_LEN, .optional = TRUE}
233 *----------------------------------------------------------------------------
234 * Netlink interface for flow commands.
235 *----------------------------------------------------------------------------
239 *----------------------------------------------------------------------------
240 * OvsFlowNewCmdHandler --
241 * Handler for OVS_FLOW_CMD_NEW/SET/DEL command.
242 * It also handles FLUSH case (DEL w/o any key in input)
243 *----------------------------------------------------------------------------
246 OvsFlowNlCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
249 NTSTATUS rc = STATUS_SUCCESS;
251 POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;
252 POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer;
253 PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
254 PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
255 POVS_HDR ovsHdr = &(msgIn->ovsHdr);
256 PNL_ATTR nlAttrs[__OVS_FLOW_ATTR_MAX];
257 UINT32 attrOffset = NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN;
258 OvsFlowPut mappedFlow;
260 struct ovs_flow_stats replyStats;
261 NL_ERROR nlError = NL_ERROR_SUCCESS;
264 RtlZeroMemory(&mappedFlow, sizeof(OvsFlowPut));
265 RtlZeroMemory(&stats, sizeof(stats));
266 RtlZeroMemory(&replyStats, sizeof(replyStats));
268 if (!(usrParamsCtx->outputBuffer)) {
269 /* No output buffer */
270 rc = STATUS_INVALID_BUFFER_SIZE;
274 /* Get all the top level Flow attributes */
275 if ((NlAttrParse(nlMsgHdr, attrOffset, NlMsgAttrsLen(nlMsgHdr),
276 nlFlowPolicy, ARRAY_SIZE(nlFlowPolicy),
277 nlAttrs, ARRAY_SIZE(nlAttrs)))
279 OVS_LOG_ERROR("Attr Parsing failed for msg: %p",
281 rc = STATUS_INVALID_PARAMETER;
285 /* FLOW_DEL command w/o any key input is a flush case. */
286 if ((genlMsgHdr->cmd == OVS_FLOW_CMD_DEL) &&
287 (!(nlAttrs[OVS_FLOW_ATTR_KEY]))) {
289 rc = OvsFlushFlowIoctl(ovsHdr->dp_ifindex);
291 if (rc == STATUS_SUCCESS) {
292 /* XXX: refactor this code. */
293 /* So far so good. Prepare the reply for userspace */
294 NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
295 usrParamsCtx->outputLength);
297 /* Prepare nl Msg headers */
298 ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,
299 nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
300 genlMsgHdr->cmd, OVS_FLOW_VERSION,
303 *replyLen = msgOut->nlMsg.nlmsgLen;
305 rc = STATUS_INVALID_BUFFER_SIZE;
312 if ((rc = _MapNlToFlowPut(msgIn, nlAttrs[OVS_FLOW_ATTR_KEY],
313 nlAttrs[OVS_FLOW_ATTR_ACTIONS], nlAttrs[OVS_FLOW_ATTR_CLEAR],
316 OVS_LOG_ERROR("Conversion to OvsFlowPut failed");
320 rc = OvsPutFlowIoctl(&mappedFlow, sizeof (struct OvsFlowPut),
322 if (rc != STATUS_SUCCESS) {
323 OVS_LOG_ERROR("OvsPutFlowIoctl failed.");
327 replyStats.n_packets = stats.packetCount;
328 replyStats.n_bytes = stats.byteCount;
330 /* So far so good. Prepare the reply for userspace */
331 NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
332 usrParamsCtx->outputLength);
334 /* Prepare nl Msg headers */
335 ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,
336 nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
337 genlMsgHdr->cmd, OVS_FLOW_VERSION,
340 rc = STATUS_INVALID_BUFFER_SIZE;
346 /* Append OVS_FLOW_ATTR_STATS attribute */
347 if (!NlMsgPutTailUnspec(&nlBuf, OVS_FLOW_ATTR_STATS,
348 (PCHAR)(&replyStats), sizeof(replyStats))) {
349 OVS_LOG_ERROR("Adding OVS_FLOW_ATTR_STATS attribute failed.");
350 rc = STATUS_INVALID_BUFFER_SIZE;
354 msgOut->nlMsg.nlmsgLen = NLMSG_ALIGN(NlBufSize(&nlBuf));
355 *replyLen = msgOut->nlMsg.nlmsgLen;
359 if (nlError != NL_ERROR_SUCCESS) {
360 POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
361 usrParamsCtx->outputBuffer;
362 NlBuildErrorMsg(msgIn, msgError, nlError);
363 *replyLen = msgError->nlMsg.nlmsgLen;
371 *----------------------------------------------------------------------------
372 * OvsFlowNlGetCmdHandler --
373 * Handler for OVS_FLOW_CMD_GET/DUMP commands.
374 *----------------------------------------------------------------------------
377 OvsFlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
380 NTSTATUS status = STATUS_SUCCESS;
381 NL_ERROR nlError = NL_ERROR_SUCCESS;
382 POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;
384 if (usrParamsCtx->devOp == OVS_TRANSACTION_DEV_OP) {
385 status = _FlowNlGetCmdHandler(usrParamsCtx, replyLen);
387 /* No trasanctional errors as of now.
388 * If we have something then we need to convert rc to
390 if ((nlError != NL_ERROR_SUCCESS) &&
391 (usrParamsCtx->outputBuffer)) {
392 POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
393 usrParamsCtx->outputBuffer;
394 NlBuildErrorMsg(msgIn, msgError, nlError);
395 *replyLen = msgError->nlMsg.nlmsgLen;
396 status = STATUS_SUCCESS;
400 status = _FlowNlDumpCmdHandler(usrParamsCtx, replyLen);
408 *----------------------------------------------------------------------------
409 * _FlowNlGetCmdHandler --
410 * Handler for OVS_FLOW_CMD_GET command.
411 *----------------------------------------------------------------------------
414 _FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
417 NTSTATUS rc = STATUS_SUCCESS;
418 POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;
419 PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
420 POVS_HDR ovsHdr = &(msgIn->ovsHdr);
421 PNL_MSG_HDR nlMsgOutHdr = NULL;
422 UINT32 attrOffset = NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN;
423 PNL_ATTR nlAttrs[__OVS_FLOW_ATTR_MAX];
425 OvsFlowGetInput getInput;
426 OvsFlowGetOutput getOutput;
428 PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX];
429 PNL_ATTR tunnelAttrs[__OVS_TUNNEL_KEY_ATTR_MAX];
431 NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
432 usrParamsCtx->outputLength);
433 RtlZeroMemory(&getInput, sizeof(OvsFlowGetInput));
434 RtlZeroMemory(&getOutput, sizeof(OvsFlowGetOutput));
435 UINT32 keyAttrOffset = 0;
436 UINT32 tunnelKeyAttrOffset = 0;
439 if (usrParamsCtx->inputLength > usrParamsCtx->outputLength) {
440 /* Should not be the case.
441 * We'll be copying the flow keys back from
442 * input buffer to output buffer. */
443 rc = STATUS_INVALID_PARAMETER;
444 OVS_LOG_ERROR("inputLength: %d GREATER THEN outputLength: %d",
445 usrParamsCtx->inputLength, usrParamsCtx->outputLength);
449 /* Get all the top level Flow attributes */
450 if ((NlAttrParse(nlMsgHdr, attrOffset, NlMsgAttrsLen(nlMsgHdr),
451 nlFlowPolicy, ARRAY_SIZE(nlFlowPolicy),
452 nlAttrs, ARRAY_SIZE(nlAttrs)))
454 OVS_LOG_ERROR("Attr Parsing failed for msg: %p",
456 rc = STATUS_INVALID_PARAMETER;
460 keyAttrOffset = (UINT32)((PCHAR) nlAttrs[OVS_FLOW_ATTR_KEY] -
463 /* Get flow keys attributes */
464 if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset,
465 NlAttrLen(nlAttrs[OVS_FLOW_ATTR_KEY]),
466 nlFlowKeyPolicy, ARRAY_SIZE(nlFlowKeyPolicy),
467 keyAttrs, ARRAY_SIZE(keyAttrs)))
469 OVS_LOG_ERROR("Key Attr Parsing failed for msg: %p",
471 rc = STATUS_INVALID_PARAMETER;
475 if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
476 tunnelKeyAttrOffset = (UINT32)((PCHAR)
477 (keyAttrs[OVS_KEY_ATTR_TUNNEL])
480 /* Get tunnel keys attributes */
481 if ((NlAttrParseNested(nlMsgHdr, tunnelKeyAttrOffset,
482 NlAttrLen(keyAttrs[OVS_KEY_ATTR_TUNNEL]),
483 nlFlowTunnelKeyPolicy,
484 ARRAY_SIZE(nlFlowTunnelKeyPolicy),
485 tunnelAttrs, ARRAY_SIZE(tunnelAttrs)))
487 OVS_LOG_ERROR("Tunnel key Attr Parsing failed for msg: %p",
489 rc = STATUS_INVALID_PARAMETER;
494 _MapKeyAttrToFlowPut(keyAttrs, tunnelAttrs,
497 getInput.dpNo = ovsHdr->dp_ifindex;
498 getInput.getFlags = FLOW_GET_STATS | FLOW_GET_ACTIONS;
500 /* 4th argument is a no op.
501 * We are keeping this argument to be compatible
502 * with our dpif-windows based interface. */
503 rc = OvsGetFlowIoctl(&getInput, &getOutput);
504 if (rc != STATUS_SUCCESS) {
505 OVS_LOG_ERROR("OvsGetFlowIoctl failed.");
509 /* Lets prepare the reply. */
510 nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, 0, 0));
512 /* Input already has all the attributes for the flow key.
513 * Lets copy the values back. */
514 ok = NlMsgPutTail(&nlBuf, (PCHAR)(usrParamsCtx->inputBuffer),
515 usrParamsCtx->inputLength);
517 OVS_LOG_ERROR("Could not copy the data to the buffer tail");
521 rc = _MapFlowStatsToNlStats(&nlBuf, &((getOutput.info).stats));
522 if (rc != STATUS_SUCCESS) {
523 OVS_LOG_ERROR("_OvsFlowMapFlowKeyToNlStats failed.");
527 rc = _MapFlowActionToNlAction(&nlBuf, ((getOutput.info).actionsLen),
528 getOutput.info.actions);
529 if (rc != STATUS_SUCCESS) {
530 OVS_LOG_ERROR("_MapFlowActionToNlAction failed.");
534 NlMsgSetSize(nlMsgOutHdr, NlBufSize(&nlBuf));
535 NlMsgAlignSize(nlMsgOutHdr);
536 *replyLen += NlMsgSize(nlMsgOutHdr);
543 *----------------------------------------------------------------------------
544 * _FlowNlDumpCmdHandler --
545 * Handler for OVS_FLOW_CMD_DUMP command.
546 *----------------------------------------------------------------------------
549 _FlowNlDumpCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
552 NTSTATUS rc = STATUS_SUCCESS;
553 UINT32 temp = 0; /* To keep compiler happy for calling OvsDoDumpFlows */
555 POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)
556 (usrParamsCtx->ovsInstance);
558 if (usrParamsCtx->devOp == OVS_WRITE_DEV_OP) {
560 OvsSetupDumpStart(usrParamsCtx);
564 POVS_MESSAGE msgIn = instance->dumpState.ovsMsg;
565 PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
566 PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
567 POVS_HDR ovsHdr = &(msgIn->ovsHdr);
568 PNL_MSG_HDR nlMsgOutHdr = NULL;
569 UINT32 hdrOffset = 0;
572 OvsFlowDumpOutput dumpOutput;
573 OvsFlowDumpInput dumpInput;
576 NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
577 usrParamsCtx->outputLength);
579 ASSERT(usrParamsCtx->devOp == OVS_READ_DEV_OP);
580 ASSERT(usrParamsCtx->outputLength);
582 RtlZeroMemory(&dumpInput, sizeof(OvsFlowDumpInput));
583 RtlZeroMemory(&dumpOutput, sizeof(OvsFlowDumpOutput));
585 dumpInput.dpNo = ovsHdr->dp_ifindex;
586 dumpInput.getFlags = FLOW_GET_KEY | FLOW_GET_STATS | FLOW_GET_ACTIONS;
588 /* Lets provide as many flows to userspace as possible. */
590 dumpInput.position[0] = instance->dumpState.index[0];
591 dumpInput.position[1] = instance->dumpState.index[1];
593 rc = OvsDoDumpFlows(&dumpInput, &dumpOutput, &temp);
594 if (rc != STATUS_SUCCESS) {
595 OVS_LOG_ERROR("OvsDoDumpFlows failed with rc: %d", rc);
599 /* Done with Dump, send NLMSG_DONE */
600 if (!(dumpOutput.n)) {
603 OVS_LOG_INFO("Dump Done");
605 nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, NlBufSize(&nlBuf), 0));
606 ok = NlFillNlHdr(&nlBuf, NLMSG_DONE, NLM_F_MULTI,
607 nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid);
610 rc = STATUS_INVALID_BUFFER_SIZE;
611 OVS_LOG_ERROR("Unable to prepare DUMP_DONE reply.");
617 NlMsgAlignSize(nlMsgOutHdr);
618 *replyLen += NlMsgSize(nlMsgOutHdr);
620 FreeUserDumpState(instance);
625 hdrOffset = NlBufSize(&nlBuf);
626 nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, hdrOffset, 0));
629 ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, NLM_F_MULTI,
630 nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
631 genlMsgHdr->cmd, genlMsgHdr->version,
635 /* Reset rc to success so that we can
636 * send already added messages to user space. */
641 /* Time to add attributes */
642 rc = _MapFlowInfoToNl(&nlBuf, &(dumpOutput.flow));
643 if (rc != STATUS_SUCCESS) {
644 /* Adding the attribute failed, we are out of
645 space in the buffer, remove the appended OVS header */
646 NlMsgSetSize(nlMsgOutHdr,
647 NlMsgSize(nlMsgOutHdr) -
648 sizeof(struct _OVS_MESSAGE));
650 /* Reset rc to success so that we can
651 * send already added messages to user space. */
656 NlMsgSetSize(nlMsgOutHdr, NlBufSize(&nlBuf) - hdrOffset);
657 NlMsgAlignSize(nlMsgOutHdr);
658 *replyLen += NlMsgSize(nlMsgOutHdr);
659 instance->dumpState.index[0] = dumpOutput.position[0];
660 instance->dumpState.index[1] = dumpOutput.position[1];
669 *----------------------------------------------------------------------------
670 * _MapFlowInfoToNl --
671 * Maps OvsFlowInfo to Netlink attributes.
672 *----------------------------------------------------------------------------
675 _MapFlowInfoToNl(PNL_BUFFER nlBuf, OvsFlowInfo *flowInfo)
677 NTSTATUS rc = STATUS_SUCCESS;
679 rc = MapFlowKeyToNlKey(nlBuf, &(flowInfo->key), OVS_FLOW_ATTR_KEY,
680 OVS_KEY_ATTR_TUNNEL);
681 if (rc != STATUS_SUCCESS) {
685 rc = _MapFlowStatsToNlStats(nlBuf, &(flowInfo->stats));
686 if (rc != STATUS_SUCCESS) {
690 rc = _MapFlowActionToNlAction(nlBuf, flowInfo->actionsLen,
692 if (rc != STATUS_SUCCESS) {
701 *----------------------------------------------------------------------------
702 * _MapFlowStatsToNlStats --
703 * Maps OvsFlowStats to OVS_FLOW_ATTR_STATS attribute.
704 *----------------------------------------------------------------------------
707 _MapFlowStatsToNlStats(PNL_BUFFER nlBuf, OvsFlowStats *flowStats)
709 NTSTATUS rc = STATUS_SUCCESS;
710 struct ovs_flow_stats replyStats;
712 replyStats.n_packets = flowStats->packetCount;
713 replyStats.n_bytes = flowStats->byteCount;
715 if (!NlMsgPutTailU64(nlBuf, OVS_FLOW_ATTR_USED, flowStats->used)) {
716 rc = STATUS_INVALID_BUFFER_SIZE;
720 if (!NlMsgPutTailUnspec(nlBuf, OVS_FLOW_ATTR_STATS,
721 (PCHAR)(&replyStats),
722 sizeof(struct ovs_flow_stats))) {
723 rc = STATUS_INVALID_BUFFER_SIZE;
727 if (!NlMsgPutTailU8(nlBuf, OVS_FLOW_ATTR_TCP_FLAGS, flowStats->tcpFlags)) {
728 rc = STATUS_INVALID_BUFFER_SIZE;
737 *----------------------------------------------------------------------------
738 * _MapFlowActionToNlAction --
739 * Maps flow actions to OVS_FLOW_ATTR_ACTION attribute.
740 *----------------------------------------------------------------------------
743 _MapFlowActionToNlAction(PNL_BUFFER nlBuf, uint32_t actionsLen,
746 NTSTATUS rc = STATUS_SUCCESS;
749 offset = NlMsgStartNested(nlBuf, OVS_FLOW_ATTR_ACTIONS);
751 /* Starting the nested attribute failed. */
752 rc = STATUS_INVALID_BUFFER_SIZE;
753 goto error_nested_start;
756 if (!NlBufCopyAtTail(nlBuf, (PCHAR)actions, actionsLen)) {
757 /* Adding a nested attribute failed. */
758 rc = STATUS_INVALID_BUFFER_SIZE;
763 NlMsgEndNested(nlBuf, offset);
770 *----------------------------------------------------------------------------
771 * MapFlowKeyToNlKey --
772 * Maps OvsFlowKey to OVS_FLOW_ATTR_KEY attribute.
773 *----------------------------------------------------------------------------
776 MapFlowKeyToNlKey(PNL_BUFFER nlBuf,
781 NTSTATUS rc = STATUS_SUCCESS;
782 struct ovs_key_ethernet ethKey;
785 offset = NlMsgStartNested(nlBuf, keyType);
787 /* Starting the nested attribute failed. */
788 rc = STATUS_UNSUCCESSFUL;
789 goto error_nested_start;
792 /* Ethernet header */
793 RtlCopyMemory(&(ethKey.eth_src), flowKey->l2.dlSrc, ETH_ADDR_LEN);
794 RtlCopyMemory(&(ethKey.eth_dst), flowKey->l2.dlDst, ETH_ADDR_LEN);
796 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ETHERNET,
798 sizeof(struct ovs_key_ethernet))) {
799 rc = STATUS_UNSUCCESSFUL;
803 if (!NlMsgPutTailU32(nlBuf, OVS_KEY_ATTR_IN_PORT,
804 flowKey->l2.inPort)) {
805 rc = STATUS_UNSUCCESSFUL;
809 if (!NlMsgPutTailU16(nlBuf, OVS_KEY_ATTR_ETHERTYPE,
810 flowKey->l2.dlType)) {
811 rc = STATUS_UNSUCCESSFUL;
815 if (flowKey->l2.vlanTci) {
816 if (!NlMsgPutTailU16(nlBuf, OVS_KEY_ATTR_VLAN,
817 flowKey->l2.vlanTci)) {
818 rc = STATUS_UNSUCCESSFUL;
823 /* ==== L3 + L4 ==== */
824 switch (ntohs(flowKey->l2.dlType)) {
825 case ETH_TYPE_IPV4: {
826 IpKey *ipv4FlowPutKey = &(flowKey->ipKey);
827 rc = _MapFlowIpv4KeyToNlKey(nlBuf, ipv4FlowPutKey);
831 case ETH_TYPE_IPV6: {
832 Ipv6Key *ipv6FlowPutKey = &(flowKey->ipv6Key);
833 Icmp6Key *icmpv6FlowPutKey = &(flowKey->icmp6Key);
834 rc = _MapFlowIpv6KeyToNlKey(nlBuf, ipv6FlowPutKey,
840 case ETH_TYPE_RARP: {
841 ArpKey *arpFlowPutKey = &(flowKey->arpKey);
842 rc = _MapFlowArpKeyToNlKey(nlBuf, arpFlowPutKey);
850 if (rc != STATUS_SUCCESS) {
854 if (flowKey->tunKey.dst) {
855 rc = MapFlowTunKeyToNlKey(nlBuf, &(flowKey->tunKey),
857 if (rc != STATUS_SUCCESS) {
863 NlMsgEndNested(nlBuf, offset);
869 *----------------------------------------------------------------------------
870 * MapFlowTunKeyToNlKey --
871 * Maps OvsIPv4TunnelKey to OVS_TUNNEL_KEY_ATTR_ID attribute.
872 *----------------------------------------------------------------------------
875 MapFlowTunKeyToNlKey(PNL_BUFFER nlBuf,
876 OvsIPv4TunnelKey *tunKey,
879 NTSTATUS rc = STATUS_SUCCESS;
882 offset = NlMsgStartNested(nlBuf, tunKeyType);
884 /* Starting the nested attribute failed. */
885 rc = STATUS_UNSUCCESSFUL;
886 goto error_nested_start;
889 if (!NlMsgPutTailU64(nlBuf, OVS_TUNNEL_KEY_ATTR_ID,
891 rc = STATUS_UNSUCCESSFUL;
895 if (!NlMsgPutTailU32(nlBuf, OVS_TUNNEL_KEY_ATTR_IPV4_DST,
897 rc = STATUS_UNSUCCESSFUL;
901 if (!NlMsgPutTailU32(nlBuf, OVS_TUNNEL_KEY_ATTR_IPV4_SRC,
903 rc = STATUS_UNSUCCESSFUL;
907 if (!NlMsgPutTailU8(nlBuf, OVS_TUNNEL_KEY_ATTR_TOS,
909 rc = STATUS_UNSUCCESSFUL;
913 if (!NlMsgPutTailU8(nlBuf, OVS_TUNNEL_KEY_ATTR_TTL,
915 rc = STATUS_UNSUCCESSFUL;
920 NlMsgEndNested(nlBuf, offset);
926 *----------------------------------------------------------------------------
927 * _MapFlowTunKeyToNlKey --
928 * Maps OvsIPv4FlowPutKey to OVS_KEY_ATTR_IPV4 attribute.
929 *----------------------------------------------------------------------------
932 _MapFlowIpv4KeyToNlKey(PNL_BUFFER nlBuf, IpKey *ipv4FlowPutKey)
934 NTSTATUS rc = STATUS_SUCCESS;
935 struct ovs_key_ipv4 ipv4Key;
937 ipv4Key.ipv4_src = ipv4FlowPutKey->nwSrc;
938 ipv4Key.ipv4_dst = ipv4FlowPutKey->nwDst;
939 ipv4Key.ipv4_proto = ipv4FlowPutKey->nwProto;
940 ipv4Key.ipv4_tos = ipv4FlowPutKey->nwTos;
941 ipv4Key.ipv4_ttl = ipv4FlowPutKey->nwTtl;
942 ipv4Key.ipv4_frag = ipv4FlowPutKey->nwFrag;
944 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_IPV4,
946 sizeof(struct ovs_key_ipv4))) {
947 rc = STATUS_UNSUCCESSFUL;
951 switch (ipv4Key.ipv4_proto) {
953 struct ovs_key_tcp tcpKey;
954 tcpKey.tcp_src = ipv4FlowPutKey->l4.tpSrc;
955 tcpKey.tcp_dst = ipv4FlowPutKey->l4.tpDst;
956 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_TCP,
959 rc = STATUS_UNSUCCESSFUL;
966 struct ovs_key_udp udpKey;
967 udpKey.udp_src = ipv4FlowPutKey->l4.tpSrc;
968 udpKey.udp_dst = ipv4FlowPutKey->l4.tpDst;
969 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_UDP,
972 rc = STATUS_UNSUCCESSFUL;
979 struct ovs_key_sctp sctpKey;
980 sctpKey.sctp_src = ipv4FlowPutKey->l4.tpSrc;
981 sctpKey.sctp_dst = ipv4FlowPutKey->l4.tpDst;
982 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_SCTP,
985 rc = STATUS_UNSUCCESSFUL;
992 struct ovs_key_icmp icmpKey;
993 /* XXX: revisit to see if htons is needed */
994 icmpKey.icmp_type = (__u8)(ipv4FlowPutKey->l4.tpSrc);
995 icmpKey.icmp_code = (__u8)(ipv4FlowPutKey->l4.tpDst);
997 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ICMP,
1000 rc = STATUS_UNSUCCESSFUL;
1015 *----------------------------------------------------------------------------
1016 * _MapFlowIpv6KeyToNlKey --
1017 * Maps _MapFlowIpv6KeyToNlKey to OVS_KEY_ATTR_IPV6 attribute.
1018 *----------------------------------------------------------------------------
1021 _MapFlowIpv6KeyToNlKey(PNL_BUFFER nlBuf, Ipv6Key *ipv6FlowPutKey,
1022 Icmp6Key *icmpv6FlowPutKey)
1024 NTSTATUS rc = STATUS_SUCCESS;
1025 struct ovs_key_ipv6 ipv6Key;
1027 RtlCopyMemory(&(ipv6Key.ipv6_src), &ipv6FlowPutKey->ipv6Src,
1028 sizeof ipv6Key.ipv6_src);
1029 RtlCopyMemory(&(ipv6Key.ipv6_dst), &ipv6FlowPutKey->ipv6Dst,
1030 sizeof ipv6Key.ipv6_dst);
1032 ipv6Key.ipv6_label = ipv6FlowPutKey->ipv6Label;
1033 ipv6Key.ipv6_proto = ipv6FlowPutKey->nwProto;
1034 ipv6Key.ipv6_tclass = ipv6FlowPutKey->nwTos;
1035 ipv6Key.ipv6_hlimit = ipv6FlowPutKey->nwTtl;
1036 ipv6Key.ipv6_frag = ipv6FlowPutKey->nwFrag;
1038 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_IPV6,
1041 rc = STATUS_UNSUCCESSFUL;
1045 switch (ipv6Key.ipv6_proto) {
1047 struct ovs_key_tcp tcpKey;
1048 tcpKey.tcp_src = ipv6FlowPutKey->l4.tpSrc;
1049 tcpKey.tcp_dst = ipv6FlowPutKey->l4.tpDst;
1050 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_TCP,
1053 rc = STATUS_UNSUCCESSFUL;
1060 struct ovs_key_udp udpKey;
1061 udpKey.udp_src = ipv6FlowPutKey->l4.tpSrc;
1062 udpKey.udp_dst = ipv6FlowPutKey->l4.tpDst;
1063 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_UDP,
1066 rc = STATUS_UNSUCCESSFUL;
1072 case IPPROTO_SCTP: {
1073 struct ovs_key_sctp sctpKey;
1074 sctpKey.sctp_src = ipv6FlowPutKey->l4.tpSrc;
1075 sctpKey.sctp_dst = ipv6FlowPutKey->l4.tpDst;
1076 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_SCTP,
1079 rc = STATUS_UNSUCCESSFUL;
1085 case IPPROTO_ICMPV6: {
1086 struct ovs_key_icmpv6 icmpV6Key;
1087 struct ovs_key_nd ndKey;
1089 /* XXX: revisit to see if htons is needed */
1090 icmpV6Key.icmpv6_type = (__u8)(icmpv6FlowPutKey->l4.tpSrc);
1091 icmpV6Key.icmpv6_code = (__u8)(icmpv6FlowPutKey->l4.tpDst);
1093 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ICMPV6,
1094 (PCHAR)(&icmpV6Key),
1095 sizeof(icmpV6Key))) {
1096 rc = STATUS_UNSUCCESSFUL;
1100 RtlCopyMemory(&(ndKey.nd_target), &icmpv6FlowPutKey->ndTarget,
1101 sizeof(icmpv6FlowPutKey->ndTarget));
1102 RtlCopyMemory(&(ndKey.nd_sll), &icmpv6FlowPutKey->arpSha,
1104 RtlCopyMemory(&(ndKey.nd_tll), &icmpv6FlowPutKey->arpTha,
1106 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ND,
1109 rc = STATUS_UNSUCCESSFUL;
1125 *----------------------------------------------------------------------------
1126 * _MapFlowArpKeyToNlKey --
1127 * Maps _MapFlowArpKeyToNlKey to OVS_KEY_ATTR_ARP attribute.
1128 *----------------------------------------------------------------------------
1131 _MapFlowArpKeyToNlKey(PNL_BUFFER nlBuf, ArpKey *arpFlowPutKey)
1133 NTSTATUS rc = STATUS_SUCCESS;
1134 struct ovs_key_arp arpKey;
1136 arpKey.arp_sip = arpFlowPutKey->nwSrc;
1137 arpKey.arp_tip = arpFlowPutKey->nwDst;
1139 RtlCopyMemory(&(arpKey.arp_sha), arpFlowPutKey->arpSha, ETH_ADDR_LEN);
1140 RtlCopyMemory(&(arpKey.arp_tha), arpFlowPutKey->arpTha, ETH_ADDR_LEN);
1143 * Flow_Extract() stores 'nwProto' in host order for ARP since 'nwProto' is
1144 * 1 byte field and the ARP opcode is 2 bytes, and all of the kernel code
1145 * understand this while looking at an ARP key.
1146 * While we pass up the ARP key to userspace, convert from host order to
1147 * network order. Likewise, when processing an ARP key from userspace,
1148 * convert from network order to host order.
1150 * It is important to note that the flow table stores the ARP opcode field
1153 arpKey.arp_op = htons(arpFlowPutKey->nwProto);
1155 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ARP,
1158 rc = STATUS_UNSUCCESSFUL;
1167 *----------------------------------------------------------------------------
1168 * _MapNlToFlowPut --
1169 * Maps input netlink message to OvsFlowPut.
1170 *----------------------------------------------------------------------------
1173 _MapNlToFlowPut(POVS_MESSAGE msgIn, PNL_ATTR keyAttr,
1174 PNL_ATTR actionAttr, PNL_ATTR flowAttrClear,
1175 OvsFlowPut *mappedFlow)
1177 NTSTATUS rc = STATUS_SUCCESS;
1178 PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
1179 PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
1180 POVS_HDR ovsHdr = &(msgIn->ovsHdr);
1182 UINT32 keyAttrOffset = (UINT32)((PCHAR)keyAttr - (PCHAR)nlMsgHdr);
1183 UINT32 tunnelKeyAttrOffset;
1185 PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX] = {NULL};
1186 PNL_ATTR tunnelAttrs[__OVS_TUNNEL_KEY_ATTR_MAX] = {NULL};
1188 /* Get flow keys attributes */
1189 if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset, NlAttrLen(keyAttr),
1190 nlFlowKeyPolicy, ARRAY_SIZE(nlFlowKeyPolicy),
1191 keyAttrs, ARRAY_SIZE(keyAttrs)))
1193 OVS_LOG_ERROR("Key Attr Parsing failed for msg: %p",
1195 rc = STATUS_INVALID_PARAMETER;
1199 if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
1200 tunnelKeyAttrOffset = (UINT32)((PCHAR)
1201 (keyAttrs[OVS_KEY_ATTR_TUNNEL])
1204 /* Get tunnel keys attributes */
1205 if ((NlAttrParseNested(nlMsgHdr, tunnelKeyAttrOffset,
1206 NlAttrLen(keyAttrs[OVS_KEY_ATTR_TUNNEL]),
1207 nlFlowTunnelKeyPolicy,
1208 ARRAY_SIZE(nlFlowTunnelKeyPolicy),
1209 tunnelAttrs, ARRAY_SIZE(tunnelAttrs)))
1211 OVS_LOG_ERROR("Tunnel key Attr Parsing failed for msg: %p",
1213 rc = STATUS_INVALID_PARAMETER;
1218 _MapKeyAttrToFlowPut(keyAttrs, tunnelAttrs,
1219 &(mappedFlow->key));
1221 /* Map the action */
1223 mappedFlow->actionsLen = NlAttrGetSize(actionAttr);
1224 mappedFlow->actions = NlAttrGet(actionAttr);
1227 mappedFlow->dpNo = ovsHdr->dp_ifindex;
1229 _MapNlToFlowPutFlags(genlMsgHdr, flowAttrClear,
1237 *----------------------------------------------------------------------------
1238 * _MapNlToFlowPutFlags --
1239 * Maps netlink message to OvsFlowPut->flags.
1240 *----------------------------------------------------------------------------
1243 _MapNlToFlowPutFlags(PGENL_MSG_HDR genlMsgHdr,
1244 PNL_ATTR flowAttrClear, OvsFlowPut *mappedFlow)
1248 switch (genlMsgHdr->cmd) {
1249 case OVS_FLOW_CMD_NEW:
1250 flags |= OVSWIN_FLOW_PUT_CREATE;
1252 case OVS_FLOW_CMD_DEL:
1253 flags |= OVSWIN_FLOW_PUT_DELETE;
1255 case OVS_FLOW_CMD_SET:
1256 flags |= OVSWIN_FLOW_PUT_MODIFY;
1262 if (flowAttrClear) {
1263 flags |= OVSWIN_FLOW_PUT_CLEAR;
1266 mappedFlow->flags = flags;
1270 *----------------------------------------------------------------------------
1271 * _MapKeyAttrToFlowPut --
1272 * Converts FLOW_KEY attribute to OvsFlowPut->key.
1273 *----------------------------------------------------------------------------
1276 _MapKeyAttrToFlowPut(PNL_ATTR *keyAttrs,
1277 PNL_ATTR *tunnelAttrs,
1278 OvsFlowKey *destKey)
1280 _MapTunAttrToFlowPut(keyAttrs, tunnelAttrs, destKey);
1282 /* ===== L2 headers ===== */
1283 destKey->l2.inPort = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_IN_PORT]);
1285 if (keyAttrs[OVS_KEY_ATTR_ETHERNET]) {
1286 const struct ovs_key_ethernet *eth_key;
1287 eth_key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ETHERNET]);
1288 RtlCopyMemory(destKey->l2.dlSrc, eth_key->eth_src, ETH_ADDR_LEN);
1289 RtlCopyMemory(destKey->l2.dlDst, eth_key->eth_dst, ETH_ADDR_LEN);
1292 /* TODO: Ideally ETHERTYPE should not be optional.
1293 * But during vswitchd bootup we are seeing FLOW_ADD
1294 * requests with no ETHERTYPE attributes.
1295 * Need to verify this. */
1296 if (keyAttrs[OVS_KEY_ATTR_ETHERTYPE]) {
1297 destKey->l2.dlType = (NlAttrGetU16(keyAttrs
1298 [OVS_KEY_ATTR_ETHERTYPE]));
1301 if (keyAttrs[OVS_KEY_ATTR_VLAN]) {
1302 destKey->l2.vlanTci = NlAttrGetU16(keyAttrs[OVS_KEY_ATTR_VLAN]);
1305 /* ==== L3 + L4. ==== */
1306 destKey->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + OVS_L2_KEY_SIZE
1307 - destKey->l2.offset;
1309 switch (ntohs(destKey->l2.dlType)) {
1310 case ETH_TYPE_IPV4: {
1312 if (keyAttrs[OVS_KEY_ATTR_IPV4]) {
1313 const struct ovs_key_ipv4 *ipv4Key;
1315 ipv4Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_IPV4]);
1316 IpKey *ipv4FlowPutKey = &(destKey->ipKey);
1317 ipv4FlowPutKey->nwSrc = ipv4Key->ipv4_src;
1318 ipv4FlowPutKey->nwDst = ipv4Key->ipv4_dst;
1319 ipv4FlowPutKey->nwProto = ipv4Key->ipv4_proto;
1320 ipv4FlowPutKey->nwTos = ipv4Key->ipv4_tos;
1321 ipv4FlowPutKey->nwTtl = ipv4Key->ipv4_ttl;
1322 ipv4FlowPutKey->nwFrag = ipv4Key->ipv4_frag;
1324 if (keyAttrs[OVS_KEY_ATTR_TCP]) {
1325 const struct ovs_key_tcp *tcpKey;
1326 tcpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_TCP]);
1327 ipv4FlowPutKey->l4.tpSrc = tcpKey->tcp_src;
1328 ipv4FlowPutKey->l4.tpDst = tcpKey->tcp_dst;
1331 if (keyAttrs[OVS_KEY_ATTR_UDP]) {
1332 const struct ovs_key_udp *udpKey;
1333 udpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_UDP]);
1334 ipv4FlowPutKey->l4.tpSrc = udpKey->udp_src;
1335 ipv4FlowPutKey->l4.tpDst = udpKey->udp_dst;
1338 if (keyAttrs[OVS_KEY_ATTR_SCTP]) {
1339 const struct ovs_key_sctp *sctpKey;
1340 sctpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_SCTP]);
1341 ipv4FlowPutKey->l4.tpSrc = sctpKey->sctp_src;
1342 ipv4FlowPutKey->l4.tpDst = sctpKey->sctp_dst;
1345 destKey->l2.keyLen += OVS_IP_KEY_SIZE;
1349 case ETH_TYPE_IPV6: {
1351 if (keyAttrs[OVS_KEY_ATTR_IPV6]) {
1352 const struct ovs_key_ipv6 *ipv6Key;
1354 ipv6Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_IPV6]);
1355 Ipv6Key *ipv6FlowPutKey = &(destKey->ipv6Key);
1357 RtlCopyMemory(&ipv6FlowPutKey->ipv6Src, ipv6Key->ipv6_src,
1358 sizeof ipv6Key->ipv6_src);
1359 RtlCopyMemory(&ipv6FlowPutKey->ipv6Dst, ipv6Key->ipv6_dst,
1360 sizeof ipv6Key->ipv6_dst);
1362 ipv6FlowPutKey->ipv6Label = ipv6Key->ipv6_label;
1363 ipv6FlowPutKey->nwProto = ipv6Key->ipv6_proto;
1364 ipv6FlowPutKey->nwTos = ipv6Key->ipv6_tclass;
1365 ipv6FlowPutKey->nwTtl = ipv6Key->ipv6_hlimit;
1366 ipv6FlowPutKey->nwFrag = ipv6Key->ipv6_frag;
1368 if (keyAttrs[OVS_KEY_ATTR_TCP]) {
1369 const struct ovs_key_tcp *tcpKey;
1370 tcpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_TCP]);
1371 ipv6FlowPutKey->l4.tpSrc = tcpKey->tcp_src;
1372 ipv6FlowPutKey->l4.tpDst = tcpKey->tcp_dst;
1375 if (keyAttrs[OVS_KEY_ATTR_UDP]) {
1376 const struct ovs_key_udp *udpKey;
1377 udpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_UDP]);
1378 ipv6FlowPutKey->l4.tpSrc = udpKey->udp_src;
1379 ipv6FlowPutKey->l4.tpDst = udpKey->udp_dst;
1382 if (keyAttrs[OVS_KEY_ATTR_SCTP]) {
1383 const struct ovs_key_sctp *sctpKey;
1384 sctpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_SCTP]);
1385 ipv6FlowPutKey->l4.tpSrc = sctpKey->sctp_src;
1386 ipv6FlowPutKey->l4.tpDst = sctpKey->sctp_dst;
1389 if (keyAttrs[OVS_KEY_ATTR_ICMPV6]) {
1390 const struct ovs_key_icmpv6 *icmpv6Key;
1392 Icmp6Key *icmp6FlowPutKey= &(destKey->icmp6Key);
1394 icmpv6Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ICMPV6]);
1396 icmp6FlowPutKey->l4.tpSrc = icmpv6Key->icmpv6_type;
1397 icmp6FlowPutKey->l4.tpDst = icmpv6Key->icmpv6_code;
1399 if (keyAttrs[OVS_KEY_ATTR_ND]) {
1400 const struct ovs_key_nd *ndKey;
1402 ndKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ND]);
1403 RtlCopyMemory(&icmp6FlowPutKey->ndTarget,
1404 ndKey->nd_target, sizeof (icmp6FlowPutKey->ndTarget));
1405 RtlCopyMemory(icmp6FlowPutKey->arpSha,
1406 ndKey->nd_sll, ETH_ADDR_LEN);
1407 RtlCopyMemory(icmp6FlowPutKey->arpTha,
1408 ndKey->nd_tll, ETH_ADDR_LEN);
1411 destKey->l2.keyLen += OVS_ICMPV6_KEY_SIZE;
1415 destKey->l2.keyLen += OVS_IPV6_KEY_SIZE;
1418 ipv6FlowPutKey->pad = 0;
1423 case ETH_TYPE_RARP: {
1425 if (keyAttrs[OVS_KEY_ATTR_ARP]) {
1426 ArpKey *arpFlowPutKey = &destKey->arpKey;
1427 const struct ovs_key_arp *arpKey;
1429 arpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ARP]);
1431 arpFlowPutKey->nwSrc = arpKey->arp_sip;
1432 arpFlowPutKey->nwDst = arpKey->arp_tip;
1434 RtlCopyMemory(arpFlowPutKey->arpSha, arpKey->arp_sha, ETH_ADDR_LEN);
1435 RtlCopyMemory(arpFlowPutKey->arpTha, arpKey->arp_tha, ETH_ADDR_LEN);
1436 /* Kernel datapath assumes 'arpFlowPutKey->nwProto' to be in host
1438 arpFlowPutKey->nwProto = (UINT8)ntohs((arpKey->arp_op));
1439 arpFlowPutKey->pad[0] = 0;
1440 arpFlowPutKey->pad[1] = 0;
1441 arpFlowPutKey->pad[2] = 0;
1442 destKey->l2.keyLen += OVS_ARP_KEY_SIZE;
1450 *----------------------------------------------------------------------------
1451 * _MapTunAttrToFlowPut --
1452 * Converts FLOW_TUNNEL_KEY attribute to OvsFlowKey->tunKey.
1453 *----------------------------------------------------------------------------
1456 _MapTunAttrToFlowPut(PNL_ATTR *keyAttrs,
1458 OvsFlowKey *destKey)
1460 if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
1462 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_ID]) {
1463 destKey->tunKey.tunnelId = NlAttrGetU64
1464 (tunAttrs[OVS_TUNNEL_KEY_ATTR_ID]);
1465 destKey->tunKey.flags |= OVS_TNL_F_KEY;
1468 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_DST]) {
1469 destKey->tunKey.dst = NlAttrGetU32
1470 (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_DST]);
1473 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_SRC]) {
1474 destKey->tunKey.src = NlAttrGetU32
1475 (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_SRC]);
1478 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT]) {
1479 destKey->tunKey.flags |= OVS_TNL_F_DONT_FRAGMENT;
1482 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_CSUM]) {
1483 destKey->tunKey.flags |= OVS_TNL_F_CSUM;
1486 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_TOS]) {
1487 destKey->tunKey.tos = NlAttrGetU8
1488 (tunAttrs[OVS_TUNNEL_KEY_ATTR_TOS]);
1491 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_TTL]) {
1492 destKey->tunKey.ttl = NlAttrGetU8
1493 (tunAttrs[OVS_TUNNEL_KEY_ATTR_TTL]);
1496 destKey->tunKey.pad = 0;
1497 destKey->l2.offset = 0;
1499 destKey->tunKey.attr[0] = 0;
1500 destKey->tunKey.attr[1] = 0;
1501 destKey->tunKey.attr[2] = 0;
1502 destKey->l2.offset = sizeof destKey->tunKey;
1507 *----------------------------------------------------------------------------
1508 * OvsDeleteFlowTable --
1510 * NDIS_STATUS_SUCCESS always.
1511 *----------------------------------------------------------------------------
1514 OvsDeleteFlowTable(OVS_DATAPATH *datapath)
1516 if (datapath == NULL || datapath->flowTable == NULL) {
1517 return NDIS_STATUS_SUCCESS;
1520 DeleteAllFlows(datapath);
1521 OvsFreeMemoryWithTag(datapath->flowTable, OVS_FLOW_POOL_TAG);
1522 datapath->flowTable = NULL;
1524 if (datapath->lock == NULL) {
1525 return NDIS_STATUS_SUCCESS;
1528 NdisFreeRWLock(datapath->lock);
1530 return NDIS_STATUS_SUCCESS;
1534 *----------------------------------------------------------------------------
1535 * OvsAllocateFlowTable --
1537 * NDIS_STATUS_SUCCESS on success.
1538 * NDIS_STATUS_RESOURCES if memory couldn't be allocated
1539 *----------------------------------------------------------------------------
1542 OvsAllocateFlowTable(OVS_DATAPATH *datapath,
1543 POVS_SWITCH_CONTEXT switchContext)
1548 datapath->flowTable = OvsAllocateMemoryWithTag(
1549 OVS_FLOW_TABLE_SIZE * sizeof(LIST_ENTRY), OVS_FLOW_POOL_TAG);
1550 if (!datapath->flowTable) {
1551 return NDIS_STATUS_RESOURCES;
1553 for (i = 0; i < OVS_FLOW_TABLE_SIZE; i++) {
1554 bucket = &(datapath->flowTable[i]);
1555 InitializeListHead(bucket);
1557 datapath->lock = NdisAllocateRWLock(switchContext->NdisFilterHandle);
1559 if (!datapath->lock) {
1560 return NDIS_STATUS_RESOURCES;
1563 return NDIS_STATUS_SUCCESS;
1568 *----------------------------------------------------------------------------
1569 * GetStartAddrNBL --
1570 * Get the virtual address of the frame.
1573 * Virtual address of the frame.
1574 *----------------------------------------------------------------------------
1576 static __inline VOID *
1577 GetStartAddrNBL(const NET_BUFFER_LIST *_pNB)
1585 // Ethernet Header is a guaranteed safe access.
1586 curMdl = (NET_BUFFER_LIST_FIRST_NB(_pNB))->CurrentMdl;
1587 curBuffer = MmGetSystemAddressForMdlSafe(curMdl, LowPagePriority);
1592 curHeader = (PEthHdr)
1593 (curBuffer + (NET_BUFFER_LIST_FIRST_NB(_pNB))->CurrentMdlOffset);
1595 return (VOID *) curHeader;
1599 OvsFlowUsed(OvsFlow *flow,
1600 const NET_BUFFER_LIST *packet,
1601 const POVS_PACKET_HDR_INFO layers)
1603 LARGE_INTEGER tickCount;
1605 KeQueryTickCount(&tickCount);
1606 flow->used = tickCount.QuadPart * ovsTimeIncrementPerTick;
1607 flow->packetCount++;
1608 flow->byteCount += OvsPacketLenNBL(packet);
1609 flow->tcpFlags |= OvsGetTcpFlags(packet, &flow->key, layers);
1614 DeleteAllFlows(OVS_DATAPATH *datapath)
1619 for (i = 0; i < OVS_FLOW_TABLE_SIZE; i++) {
1621 bucket = &(datapath->flowTable[i]);
1622 while (!IsListEmpty(bucket)) {
1624 next = bucket->Flink;
1625 flow = CONTAINING_RECORD(next, OvsFlow, ListEntry);
1626 RemoveFlow(datapath, &flow);
1632 *----------------------------------------------------------------------------
1633 * Initializes 'flow' members from 'packet', 'skb_priority', 'tun_id', and
1636 * Initializes 'packet' header pointers as follows:
1638 * - packet->l2 to the start of the Ethernet header.
1640 * - packet->l3 to just past the Ethernet header, or just past the
1641 * vlan_header if one is present, to the first byte of the payload of the
1644 * - packet->l4 to just past the IPv4 header, if one is present and has a
1645 * correct length, and otherwise NULL.
1647 * - packet->l7 to just past the TCP or UDP or ICMP header, if one is
1648 * present and has a correct length, and otherwise NULL.
1650 * Returns NDIS_STATUS_SUCCESS normally. Fails only if packet data cannot be accessed
1651 * (e.g. if Pkt_CopyBytesOut() returns an error).
1652 *----------------------------------------------------------------------------
1655 OvsExtractFlow(const NET_BUFFER_LIST *packet,
1658 POVS_PACKET_HDR_INFO layers,
1659 OvsIPv4TunnelKey *tunKey)
1661 struct Eth_Header *eth;
1668 ASSERT(tunKey->dst != 0);
1669 RtlMoveMemory(&flow->tunKey, tunKey, sizeof flow->tunKey);
1670 flow->l2.offset = 0;
1672 flow->tunKey.dst = 0;
1673 flow->l2.offset = OVS_WIN_TUNNEL_KEY_SIZE;
1676 flow->l2.inPort = inPort;
1678 if ( OvsPacketLenNBL(packet) < ETH_HEADER_LEN_DIX) {
1679 flow->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + 8 - flow->l2.offset;
1680 return NDIS_STATUS_SUCCESS;
1684 eth = (Eth_Header *)GetStartAddrNBL((NET_BUFFER_LIST *)packet);
1685 memcpy(flow->l2.dlSrc, eth->src, ETH_ADDR_LENGTH);
1686 memcpy(flow->l2.dlDst, eth->dst, ETH_ADDR_LENGTH);
1691 vlanTagValue = NET_BUFFER_LIST_INFO(packet, Ieee8021QNetBufferListInfo);
1693 PNDIS_NET_BUFFER_LIST_8021Q_INFO vlanTag =
1694 (PNDIS_NET_BUFFER_LIST_8021Q_INFO)(PVOID *)&vlanTagValue;
1695 flow->l2.vlanTci = htons(vlanTag->TagHeader.VlanId | OVSWIN_VLAN_CFI |
1696 (vlanTag->TagHeader.UserPriority << 13));
1698 if (eth->dix.typeNBO == ETH_TYPE_802_1PQ_NBO) {
1699 Eth_802_1pq_Tag *tag= (Eth_802_1pq_Tag *)ð->dix.typeNBO;
1700 flow->l2.vlanTci = ((UINT16)tag->priority << 13) |
1702 ((UINT16)tag->vidHi << 8) | tag->vidLo;
1703 offset = sizeof (Eth_802_1pq_Tag);
1705 flow->l2.vlanTci = 0;
1709 * Please note after this point, src mac and dst mac should
1710 * not be accessed through eth
1712 eth = (Eth_Header *)((UINT8 *)eth + offset);
1718 * XXX assume that at least the first
1719 * 12 bytes of received packets are mapped. This code has the stronger
1720 * assumption that at least the first 22 bytes of 'packet' is mapped (if my
1721 * arithmetic is right).
1723 if (ETH_TYPENOT8023(eth->dix.typeNBO)) {
1724 flow->l2.dlType = eth->dix.typeNBO;
1725 layers->l3Offset = ETH_HEADER_LEN_DIX + offset;
1726 } else if (OvsPacketLenNBL(packet) >= ETH_HEADER_LEN_802_3 &&
1727 eth->e802_3.llc.dsap == 0xaa &&
1728 eth->e802_3.llc.ssap == 0xaa &&
1729 eth->e802_3.llc.control == ETH_LLC_CONTROL_UFRAME &&
1730 eth->e802_3.snap.snapOrg[0] == 0x00 &&
1731 eth->e802_3.snap.snapOrg[1] == 0x00 &&
1732 eth->e802_3.snap.snapOrg[2] == 0x00) {
1733 flow->l2.dlType = eth->e802_3.snap.snapType.typeNBO;
1734 layers->l3Offset = ETH_HEADER_LEN_802_3 + offset;
1736 flow->l2.dlType = htons(OVSWIN_DL_TYPE_NONE);
1737 layers->l3Offset = ETH_HEADER_LEN_DIX + offset;
1740 flow->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + OVS_L2_KEY_SIZE - flow->l2.offset;
1741 /* Network layer. */
1742 if (flow->l2.dlType == htons(ETH_TYPE_IPV4)) {
1743 struct IPHdr ip_storage;
1744 const struct IPHdr *nh;
1745 IpKey *ipKey = &flow->ipKey;
1747 flow->l2.keyLen += OVS_IP_KEY_SIZE;
1749 nh = OvsGetIp(packet, layers->l3Offset, &ip_storage);
1751 layers->l4Offset = layers->l3Offset + nh->ihl * 4;
1753 ipKey->nwSrc = nh->saddr;
1754 ipKey->nwDst = nh->daddr;
1755 ipKey->nwProto = nh->protocol;
1757 ipKey->nwTos = nh->tos;
1758 if (nh->frag_off & htons(IP_MF | IP_OFFSET)) {
1759 ipKey->nwFrag = OVSWIN_NW_FRAG_ANY;
1760 if (nh->frag_off & htons(IP_OFFSET)) {
1761 ipKey->nwFrag |= OVSWIN_NW_FRAG_LATER;
1767 ipKey->nwTtl = nh->ttl;
1768 ipKey->l4.tpSrc = 0;
1769 ipKey->l4.tpDst = 0;
1771 if (!(nh->frag_off & htons(IP_OFFSET))) {
1772 if (ipKey->nwProto == SOCKET_IPPROTO_TCP) {
1773 OvsParseTcp(packet, &ipKey->l4, layers);
1774 } else if (ipKey->nwProto == SOCKET_IPPROTO_UDP) {
1775 OvsParseUdp(packet, &ipKey->l4, layers);
1776 } else if (ipKey->nwProto == SOCKET_IPPROTO_ICMP) {
1777 ICMPHdr icmpStorage;
1778 const ICMPHdr *icmp;
1780 icmp = OvsGetIcmp(packet, layers->l4Offset, &icmpStorage);
1782 ipKey->l4.tpSrc = htons(icmp->type);
1783 ipKey->l4.tpDst = htons(icmp->code);
1784 layers->l7Offset = layers->l4Offset + sizeof *icmp;
1789 ((UINT64 *)ipKey)[0] = 0;
1790 ((UINT64 *)ipKey)[1] = 0;
1792 } else if (flow->l2.dlType == htons(ETH_TYPE_IPV6)) {
1794 flow->l2.keyLen += OVS_IPV6_KEY_SIZE;
1795 status = OvsParseIPv6(packet, flow, layers);
1796 if (status != NDIS_STATUS_SUCCESS) {
1797 memset(&flow->ipv6Key, 0, sizeof (Ipv6Key));
1801 flow->ipv6Key.l4.tpSrc = 0;
1802 flow->ipv6Key.l4.tpDst = 0;
1803 flow->ipv6Key.pad = 0;
1805 if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_TCP) {
1806 OvsParseTcp(packet, &(flow->ipv6Key.l4), layers);
1807 } else if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_UDP) {
1808 OvsParseUdp(packet, &(flow->ipv6Key.l4), layers);
1809 } else if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_ICMPV6) {
1810 OvsParseIcmpV6(packet, flow, layers);
1811 flow->l2.keyLen += (OVS_ICMPV6_KEY_SIZE - OVS_IPV6_KEY_SIZE);
1813 } else if (flow->l2.dlType == htons(ETH_TYPE_ARP)) {
1814 EtherArp arpStorage;
1815 const EtherArp *arp;
1816 ArpKey *arpKey = &flow->arpKey;
1817 ((UINT64 *)arpKey)[0] = 0;
1818 ((UINT64 *)arpKey)[1] = 0;
1819 ((UINT64 *)arpKey)[2] = 0;
1820 flow->l2.keyLen += OVS_ARP_KEY_SIZE;
1821 arp = OvsGetArp(packet, layers->l3Offset, &arpStorage);
1822 if (arp && arp->ea_hdr.ar_hrd == htons(1) &&
1823 arp->ea_hdr.ar_pro == htons(ETH_TYPE_IPV4) &&
1824 arp->ea_hdr.ar_hln == ETH_ADDR_LENGTH &&
1825 arp->ea_hdr.ar_pln == 4) {
1826 /* We only match on the lower 8 bits of the opcode. */
1827 if (ntohs(arp->ea_hdr.ar_op) <= 0xff) {
1828 arpKey->nwProto = (UINT8)ntohs(arp->ea_hdr.ar_op);
1830 if (arpKey->nwProto == ARPOP_REQUEST
1831 || arpKey->nwProto == ARPOP_REPLY) {
1832 memcpy(&arpKey->nwSrc, arp->arp_spa, 4);
1833 memcpy(&arpKey->nwDst, arp->arp_tpa, 4);
1834 memcpy(arpKey->arpSha, arp->arp_sha, ETH_ADDR_LENGTH);
1835 memcpy(arpKey->arpTha, arp->arp_tha, ETH_ADDR_LENGTH);
1840 return NDIS_STATUS_SUCCESS;
1844 FlowEqual(UINT64 *src, UINT64 *dst, UINT32 size)
1847 ASSERT((size & 0x7) == 0);
1848 ASSERT(((UINT64)src & 0x7) == 0);
1849 ASSERT(((UINT64)dst & 0x7) == 0);
1850 for (i = 0; i < (size >> 3); i++) {
1851 if (src[i] != dst[i]) {
1860 * ----------------------------------------------------------------------------
1862 * Add a flow to flow table.
1865 * NDIS_STATUS_SUCCESS if no same flow in the flow table.
1866 * ----------------------------------------------------------------------------
1869 AddFlow(OVS_DATAPATH *datapath, OvsFlow *flow)
1873 if (OvsLookupFlow(datapath, &flow->key, &flow->hash, TRUE) != NULL) {
1874 return STATUS_INVALID_HANDLE;
1877 head = &(datapath->flowTable[HASH_BUCKET(flow->hash)]);
1879 * We need fence here to make sure flow's nextPtr is updated before
1880 * head->nextPtr is updated.
1884 //KeAcquireSpinLock(&FilterDeviceExtension->NblQueueLock, &oldIrql);
1885 InsertTailList(head, &flow->ListEntry);
1886 //KeReleaseSpinLock(&FilterDeviceExtension->NblQueueLock, oldIrql);
1890 return STATUS_SUCCESS;
1894 /* ----------------------------------------------------------------------------
1896 * Remove a flow from flow table, and added to wait list
1897 * ----------------------------------------------------------------------------
1900 RemoveFlow(OVS_DATAPATH *datapath,
1906 ASSERT(datapath->nFlows);
1908 // Remove the flow from queue
1909 RemoveEntryList(&f->ListEntry);
1915 * ----------------------------------------------------------------------------
1918 * Find flow from flow table based on flow key.
1919 * Caller should either hold portset handle or should
1920 * have a flowRef in datapath or Acquired datapath.
1923 * Flow pointer if lookup successful.
1924 * NULL if not exists.
1925 * ----------------------------------------------------------------------------
1928 OvsLookupFlow(OVS_DATAPATH *datapath,
1929 const OvsFlowKey *key,
1933 PLIST_ENTRY link, head;
1934 UINT16 offset = key->l2.offset;
1935 UINT16 size = key->l2.keyLen;
1938 ASSERT(key->tunKey.dst || offset == sizeof (OvsIPv4TunnelKey));
1939 ASSERT(!key->tunKey.dst || offset == 0);
1941 start = (UINT8 *)key + offset;
1944 *hash = OvsJhashBytes(start, size, 0);
1947 head = &datapath->flowTable[HASH_BUCKET(*hash)];
1949 while (link != head) {
1950 OvsFlow *flow = CONTAINING_RECORD(link, OvsFlow, ListEntry);
1952 if (flow->hash == *hash &&
1953 flow->key.l2.val == key->l2.val &&
1954 FlowEqual((UINT64 *)((uint8 *)&flow->key + offset),
1955 (UINT64 *)start, size)) {
1965 * ----------------------------------------------------------------------------
1967 * Calculate the hash for the given flow key.
1968 * ----------------------------------------------------------------------------
1971 OvsHashFlow(const OvsFlowKey *key)
1973 UINT16 offset = key->l2.offset;
1974 UINT16 size = key->l2.keyLen;
1977 ASSERT(key->tunKey.dst || offset == sizeof (OvsIPv4TunnelKey));
1978 ASSERT(!key->tunKey.dst || offset == 0);
1979 start = (UINT8 *)key + offset;
1980 return OvsJhashBytes(start, size, 0);
1985 * ----------------------------------------------------------------------------
1987 * Free a flow and its actions.
1988 * ----------------------------------------------------------------------------
1991 FreeFlow(OvsFlow *flow)
1994 OvsFreeMemoryWithTag(flow, OVS_FLOW_POOL_TAG);
1998 OvsDoDumpFlows(OvsFlowDumpInput *dumpInput,
1999 OvsFlowDumpOutput *dumpOutput,
2003 OVS_DATAPATH *datapath = NULL;
2005 PLIST_ENTRY node, head;
2007 UINT32 rowIndex, columnIndex;
2008 LOCK_STATE_EX dpLockState;
2009 NTSTATUS status = STATUS_SUCCESS;
2010 BOOLEAN findNextNonEmpty = FALSE;
2012 dpNo = dumpInput->dpNo;
2013 if (gOvsSwitchContext->dpNo != dpNo) {
2014 status = STATUS_INVALID_PARAMETER;
2018 rowIndex = dumpInput->position[0];
2019 if (rowIndex >= OVS_FLOW_TABLE_SIZE) {
2021 *replyLen = sizeof(*dumpOutput);
2025 columnIndex = dumpInput->position[1];
2027 datapath = &gOvsSwitchContext->datapath;
2029 OvsAcquireDatapathRead(datapath, &dpLockState, FALSE);
2031 head = &datapath->flowTable[rowIndex];
2034 while (column < columnIndex) {
2043 findNextNonEmpty = TRUE;
2047 if (findNextNonEmpty) {
2048 while (head == node) {
2049 if (++rowIndex >= OVS_FLOW_TABLE_SIZE) {
2053 head = &datapath->flowTable[rowIndex];
2058 ASSERT(node != head);
2059 ASSERT(rowIndex < OVS_FLOW_TABLE_SIZE);
2061 flow = CONTAINING_RECORD(node, OvsFlow, ListEntry);
2062 status = ReportFlowInfo(flow, dumpInput->getFlags, &dumpOutput->flow);
2064 if (status == STATUS_BUFFER_TOO_SMALL) {
2065 dumpOutput->n = sizeof(OvsFlowDumpOutput) + flow->actionsLen;
2066 *replyLen = sizeof(*dumpOutput);
2068 dumpOutput->n = 1; //one flow reported.
2069 *replyLen = sizeof(*dumpOutput) + dumpOutput->flow.actionsLen;
2072 dumpOutput->position[0] = rowIndex;
2073 dumpOutput->position[1] = ++columnIndex;
2076 OvsReleaseDatapath(datapath, &dpLockState);
2083 ReportFlowInfo(OvsFlow *flow,
2087 NTSTATUS status = STATUS_SUCCESS;
2089 if (getFlags & FLOW_GET_KEY) {
2090 // always copy the tunnel key part
2091 RtlCopyMemory(&info->key, &flow->key,
2092 flow->key.l2.keyLen + flow->key.l2.offset);
2095 if (getFlags & FLOW_GET_STATS) {
2096 OvsFlowStats *stats = &info->stats;
2097 stats->packetCount = flow->packetCount;
2098 stats->byteCount = flow->byteCount;
2099 stats->used = (UINT32)flow->used;
2100 stats->tcpFlags = flow->tcpFlags;
2103 if (getFlags & FLOW_GET_ACTIONS) {
2104 if (flow->actionsLen == 0) {
2105 info->actionsLen = 0;
2107 info->actions = flow->actions;
2108 info->actionsLen = flow->actionsLen;
2116 OvsPutFlowIoctl(PVOID inputBuffer,
2118 struct OvsFlowStats *stats)
2120 NTSTATUS status = STATUS_SUCCESS;
2121 OVS_DATAPATH *datapath = NULL;
2125 LOCK_STATE_EX dpLockState;
2127 if ((inputLength < sizeof(OvsFlowPut)) || (inputBuffer == NULL)) {
2128 return STATUS_INFO_LENGTH_MISMATCH;
2131 put = (OvsFlowPut *)inputBuffer;
2132 if (put->actionsLen > 0) {
2133 actionsLen = put->actionsLen;
2139 if (gOvsSwitchContext->dpNo != dpNo) {
2140 status = STATUS_INVALID_PARAMETER;
2144 datapath = &gOvsSwitchContext->datapath;
2146 OvsAcquireDatapathWrite(datapath, &dpLockState, FALSE);
2147 status = HandleFlowPut(put, datapath, stats);
2148 OvsReleaseDatapath(datapath, &dpLockState);
2155 /* Handles flow add, modify as well as delete */
2157 HandleFlowPut(OvsFlowPut *put,
2158 OVS_DATAPATH *datapath,
2159 struct OvsFlowStats *stats)
2161 BOOLEAN mayCreate, mayModify, mayDelete;
2162 OvsFlow *KernelFlow;
2164 NTSTATUS status = STATUS_SUCCESS;
2166 mayCreate = (put->flags & OVSWIN_FLOW_PUT_CREATE) != 0;
2167 mayModify = (put->flags & OVSWIN_FLOW_PUT_MODIFY) != 0;
2168 mayDelete = (put->flags & OVSWIN_FLOW_PUT_DELETE) != 0;
2170 if ((mayCreate || mayModify) == mayDelete) {
2171 return STATUS_INVALID_PARAMETER;
2174 KernelFlow = OvsLookupFlow(datapath, &put->key, &hash, FALSE);
2177 return STATUS_INVALID_PARAMETER;
2180 status = OvsPrepareFlow(&KernelFlow, put, hash);
2181 if (status != STATUS_SUCCESS) {
2182 return STATUS_UNSUCCESSFUL;
2185 status = AddFlow(datapath, KernelFlow);
2186 if (status != STATUS_SUCCESS) {
2187 FreeFlow(KernelFlow);
2188 return STATUS_UNSUCCESSFUL;
2191 /* Validate the flow addition */
2194 OvsFlow *flow = OvsLookupFlow(datapath, &put->key, &newHash,
2197 ASSERT(newHash == hash);
2198 if (!flow || newHash != hash) {
2199 return STATUS_UNSUCCESSFUL;
2203 stats->packetCount = KernelFlow->packetCount;
2204 stats->byteCount = KernelFlow->byteCount;
2205 stats->tcpFlags = KernelFlow->tcpFlags;
2206 stats->used = (UINT32)KernelFlow->used;
2210 status = OvsPrepareFlow(&newFlow, put, hash);
2211 if (status != STATUS_SUCCESS) {
2212 return STATUS_UNSUCCESSFUL;
2215 KernelFlow = OvsLookupFlow(datapath, &put->key, &hash, TRUE);
2217 if ((put->flags & OVSWIN_FLOW_PUT_CLEAR) == 0) {
2218 newFlow->packetCount = KernelFlow->packetCount;
2219 newFlow->byteCount = KernelFlow->byteCount;
2220 newFlow->tcpFlags = KernelFlow->tcpFlags;
2222 RemoveFlow(datapath, &KernelFlow);
2224 if ((put->flags & OVSWIN_FLOW_PUT_CLEAR) == 0) {
2225 newFlow->packetCount = stats->packetCount;
2226 newFlow->byteCount = stats->byteCount;
2227 newFlow->tcpFlags = stats->tcpFlags;
2230 status = AddFlow(datapath, newFlow);
2231 ASSERT(status == STATUS_SUCCESS);
2233 /* Validate the flow addition */
2236 OvsFlow *testflow = OvsLookupFlow(datapath, &put->key,
2239 ASSERT(newHash == hash);
2240 if (!testflow || newHash != hash) {
2242 return STATUS_UNSUCCESSFUL;
2248 RemoveFlow(datapath, &KernelFlow);
2251 /* Return success if an identical flow already exists. */
2252 /* XXX: should we return EEXIST in a netlink error? */
2253 return STATUS_SUCCESS;
2257 return STATUS_SUCCESS;
2261 OvsPrepareFlow(OvsFlow **flow,
2262 const OvsFlowPut *put,
2265 OvsFlow *localFlow = *flow;
2266 NTSTATUS status = STATUS_SUCCESS;
2270 OvsAllocateMemoryWithTag(sizeof(OvsFlow) + put->actionsLen,
2272 if (localFlow == NULL) {
2273 status = STATUS_NO_MEMORY;
2277 localFlow->key = put->key;
2278 localFlow->actionsLen = put->actionsLen;
2279 if (put->actionsLen) {
2280 NdisMoveMemory((PUCHAR)localFlow->actions, put->actions,
2283 localFlow->userActionsLen = 0; // 0 indicate no conversion is made
2284 localFlow->used = 0;
2285 localFlow->packetCount = 0;
2286 localFlow->byteCount = 0;
2287 localFlow->tcpFlags = 0;
2288 localFlow->hash = hash;
2295 OvsGetFlowIoctl(PVOID inputBuffer,
2298 NTSTATUS status = STATUS_SUCCESS;
2299 OVS_DATAPATH *datapath = NULL;
2301 UINT32 getFlags, getActionsLen;
2302 OvsFlowGetInput *getInput;
2303 OvsFlowGetOutput *getOutput;
2306 LOCK_STATE_EX dpLockState;
2308 getInput = (OvsFlowGetInput *) inputBuffer;
2309 getFlags = getInput->getFlags;
2310 getActionsLen = getInput->actionsLen;
2312 if (outputBuffer == NULL) {
2313 return STATUS_INFO_LENGTH_MISMATCH;
2316 dpNo = getInput->dpNo;
2317 if (gOvsSwitchContext->dpNo != dpNo) {
2318 status = STATUS_INVALID_PARAMETER;
2322 datapath = &gOvsSwitchContext->datapath;
2324 OvsAcquireDatapathRead(datapath, &dpLockState, FALSE);
2325 flow = OvsLookupFlow(datapath, &getInput->key, &hash, FALSE);
2327 status = STATUS_INVALID_PARAMETER;
2331 getOutput = (OvsFlowGetOutput *)outputBuffer;
2332 ReportFlowInfo(flow, getFlags, &getOutput->info);
2335 OvsReleaseDatapath(datapath, &dpLockState);
2341 OvsFlushFlowIoctl(UINT32 dpNo)
2343 NTSTATUS status = STATUS_SUCCESS;
2344 OVS_DATAPATH *datapath = NULL;
2345 LOCK_STATE_EX dpLockState;
2347 if (gOvsSwitchContext->dpNo != dpNo) {
2348 status = STATUS_INVALID_PARAMETER;
2352 datapath = &gOvsSwitchContext->datapath;
2354 OvsAcquireDatapathWrite(datapath, &dpLockState, FALSE);
2355 DeleteAllFlows(datapath);
2356 OvsReleaseDatapath(datapath, &dpLockState);
2363 OvsFlowKeyAttrSize(void)
2365 return NlAttrTotalSize(4) /* OVS_KEY_ATTR_PRIORITY */
2366 + NlAttrTotalSize(0) /* OVS_KEY_ATTR_TUNNEL */
2367 + OvsTunKeyAttrSize()
2368 + NlAttrTotalSize(4) /* OVS_KEY_ATTR_IN_PORT */
2369 + NlAttrTotalSize(4) /* OVS_KEY_ATTR_SKB_MARK */
2370 + NlAttrTotalSize(4) /* OVS_KEY_ATTR_DP_HASH */
2371 + NlAttrTotalSize(4) /* OVS_KEY_ATTR_RECIRC_ID */
2372 + NlAttrTotalSize(12) /* OVS_KEY_ATTR_ETHERNET */
2373 + NlAttrTotalSize(2) /* OVS_KEY_ATTR_ETHERTYPE */
2374 + NlAttrTotalSize(4) /* OVS_KEY_ATTR_VLAN */
2375 + NlAttrTotalSize(0) /* OVS_KEY_ATTR_ENCAP */
2376 + NlAttrTotalSize(2) /* OVS_KEY_ATTR_ETHERTYPE */
2377 + NlAttrTotalSize(40) /* OVS_KEY_ATTR_IPV6 */
2378 + NlAttrTotalSize(2) /* OVS_KEY_ATTR_ICMPV6 */
2379 + NlAttrTotalSize(28); /* OVS_KEY_ATTR_ND */
2383 OvsTunKeyAttrSize(void)
2385 /* Whenever adding new OVS_TUNNEL_KEY_ FIELDS, we should consider
2386 * updating this function.
2388 return NlAttrTotalSize(8) /* OVS_TUNNEL_KEY_ATTR_ID */
2389 + NlAttrTotalSize(4) /* OVS_TUNNEL_KEY_ATTR_IPV4_SRC */
2390 + NlAttrTotalSize(4) /* OVS_TUNNEL_KEY_ATTR_IPV4_DST */
2391 + NlAttrTotalSize(1) /* OVS_TUNNEL_KEY_ATTR_TOS */
2392 + NlAttrTotalSize(1) /* OVS_TUNNEL_KEY_ATTR_TTL */
2393 + NlAttrTotalSize(0) /* OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT */
2394 + NlAttrTotalSize(0) /* OVS_TUNNEL_KEY_ATTR_CSUM */
2395 + NlAttrTotalSize(0) /* OVS_TUNNEL_KEY_ATTR_OAM */
2396 + NlAttrTotalSize(256) /* OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS */
2397 + NlAttrTotalSize(2) /* OVS_TUNNEL_KEY_ATTR_TP_SRC */
2398 + NlAttrTotalSize(2); /* OVS_TUNNEL_KEY_ATTR_TP_DST */
2401 #pragma warning( pop )