2 * Copyright (c) 2014 VMware, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
22 #include "PacketParser.h"
28 #define OVS_DBG_MOD OVS_DBG_FLOW
31 #pragma warning( push )
32 #pragma warning( disable:4127 )
34 extern PNDIS_SPIN_LOCK gOvsCtrlLock;
35 extern POVS_SWITCH_CONTEXT gOvsSwitchContext;
36 extern UINT64 ovsTimeIncrementPerTick;
38 static NTSTATUS ReportFlowInfo(OvsFlow *flow, UINT32 getFlags,
40 static NTSTATUS HandleFlowPut(OvsFlowPut *put,
41 OVS_DATAPATH *datapath,
42 struct OvsFlowStats *stats);
43 static NTSTATUS OvsPrepareFlow(OvsFlow **flow, const OvsFlowPut *put,
45 static VOID RemoveFlow(OVS_DATAPATH *datapath, OvsFlow **flow);
46 static VOID DeleteAllFlows(OVS_DATAPATH *datapath);
47 static NTSTATUS AddFlow(OVS_DATAPATH *datapath, OvsFlow *flow);
48 static VOID FreeFlow(OvsFlow *flow);
49 static VOID __inline *GetStartAddrNBL(const NET_BUFFER_LIST *_pNB);
50 static NTSTATUS _MapNlToFlowPut(POVS_MESSAGE msgIn, PNL_ATTR keyAttr,
52 PNL_ATTR flowAttrClear,
53 OvsFlowPut *mappedFlow);
54 static VOID _MapKeyAttrToFlowPut(PNL_ATTR *keyAttrs,
55 PNL_ATTR *tunnelAttrs,
58 static VOID _MapTunAttrToFlowPut(PNL_ATTR *keyAttrs,
59 PNL_ATTR *tunnelAttrs,
61 static VOID _MapNlToFlowPutFlags(PGENL_MSG_HDR genlMsgHdr,
62 PNL_ATTR flowAttrClear,
63 OvsFlowPut *mappedFlow);
65 static NTSTATUS _FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
67 static NTSTATUS _FlowNlDumpCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
69 static NTSTATUS _MapFlowInfoToNl(PNL_BUFFER nlBuf,
70 OvsFlowInfo *flowInfo);
71 static NTSTATUS _MapFlowStatsToNlStats(PNL_BUFFER nlBuf,
72 OvsFlowStats *flowStats);
73 static NTSTATUS _MapFlowActionToNlAction(PNL_BUFFER nlBuf,
77 static NTSTATUS _MapFlowIpv4KeyToNlKey(PNL_BUFFER nlBuf,
78 IpKey *ipv4FlowPutKey);
79 static NTSTATUS _MapFlowIpv6KeyToNlKey(PNL_BUFFER nlBuf,
80 Ipv6Key *ipv6FlowPutKey,
81 Icmp6Key *ipv6FlowPutIcmpKey);
82 static NTSTATUS _MapFlowArpKeyToNlKey(PNL_BUFFER nlBuf,
83 ArpKey *arpFlowPutKey);
85 static NTSTATUS OvsDoDumpFlows(OvsFlowDumpInput *dumpInput,
86 OvsFlowDumpOutput *dumpOutput,
90 #define OVS_FLOW_TABLE_SIZE 2048
91 #define OVS_FLOW_TABLE_MASK (OVS_FLOW_TABLE_SIZE -1)
92 #define HASH_BUCKET(hash) ((hash) & OVS_FLOW_TABLE_MASK)
94 /* Flow family related netlink policies */
96 /* For Parsing attributes in FLOW_* commands */
97 const NL_POLICY nlFlowPolicy[] = {
98 [OVS_FLOW_ATTR_KEY] = {.type = NL_A_NESTED, .optional = FALSE},
99 [OVS_FLOW_ATTR_MASK] = {.type = NL_A_NESTED, .optional = TRUE},
100 [OVS_FLOW_ATTR_ACTIONS] = {.type = NL_A_NESTED, .optional = TRUE},
101 [OVS_FLOW_ATTR_STATS] = {.type = NL_A_UNSPEC,
102 .minLen = sizeof(struct ovs_flow_stats),
103 .maxLen = sizeof(struct ovs_flow_stats),
105 [OVS_FLOW_ATTR_TCP_FLAGS] = {NL_A_U8, .optional = TRUE},
106 [OVS_FLOW_ATTR_USED] = {NL_A_U64, .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}
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;
250 POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;
251 POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer;
252 PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
253 PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
254 POVS_HDR ovsHdr = &(msgIn->ovsHdr);
255 PNL_ATTR nlAttrs[__OVS_FLOW_ATTR_MAX];
256 UINT32 attrOffset = NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN;
257 OvsFlowPut mappedFlow;
259 struct ovs_flow_stats replyStats;
260 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, nlAttrs, ARRAY_SIZE(nlAttrs)))
278 OVS_LOG_ERROR("Attr Parsing failed for msg: %p",
280 rc = STATUS_INVALID_PARAMETER;
284 /* FLOW_DEL command w/o any key input is a flush case. */
285 if ((genlMsgHdr->cmd == OVS_FLOW_CMD_DEL) &&
286 (!(nlAttrs[OVS_FLOW_ATTR_KEY]))) {
288 rc = OvsFlushFlowIoctl(ovsHdr->dp_ifindex);
290 if (rc == STATUS_SUCCESS) {
291 /* XXX: refactor this code. */
292 /* So far so good. Prepare the reply for userspace */
293 NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
294 usrParamsCtx->outputLength);
296 /* Prepare nl Msg headers */
297 rc = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,
298 nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
299 genlMsgHdr->cmd, OVS_FLOW_VERSION,
302 if (rc == STATUS_SUCCESS) {
303 *replyLen = msgOut->nlMsg.nlmsgLen;
310 if ((rc = _MapNlToFlowPut(msgIn, nlAttrs[OVS_FLOW_ATTR_KEY],
311 nlAttrs[OVS_FLOW_ATTR_ACTIONS], nlAttrs[OVS_FLOW_ATTR_CLEAR],
314 OVS_LOG_ERROR("Conversion to OvsFlowPut failed");
318 rc = OvsPutFlowIoctl(&mappedFlow, sizeof (struct OvsFlowPut),
320 if (rc != STATUS_SUCCESS) {
321 OVS_LOG_ERROR("OvsFlowPut failed.");
325 replyStats.n_packets = stats.packetCount;
326 replyStats.n_bytes = stats.byteCount;
328 /* So far so good. Prepare the reply for userspace */
329 NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
330 usrParamsCtx->outputLength);
332 /* Prepare nl Msg headers */
333 rc = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,
334 nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
335 genlMsgHdr->cmd, OVS_FLOW_VERSION,
338 if (rc != STATUS_SUCCESS) {
342 /* Append OVS_FLOW_ATTR_STATS attribute */
343 if (!NlMsgPutTailUnspec(&nlBuf, OVS_FLOW_ATTR_STATS,
344 (PCHAR)(&replyStats), sizeof(replyStats))) {
345 OVS_LOG_ERROR("Adding OVS_FLOW_ATTR_STATS attribute failed.");
346 rc = STATUS_INVALID_BUFFER_SIZE;
350 msgOut->nlMsg.nlmsgLen = NLMSG_ALIGN(NlBufSize(&nlBuf));
351 *replyLen = msgOut->nlMsg.nlmsgLen;
355 if (nlError != NL_ERROR_SUCCESS) {
356 POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
357 usrParamsCtx->outputBuffer;
358 BuildErrorMsg(msgIn, msgError, nlError);
359 *replyLen = msgError->nlMsg.nlmsgLen;
367 *----------------------------------------------------------------------------
368 * OvsFlowNlGetCmdHandler --
369 * Handler for OVS_FLOW_CMD_GET/DUMP commands.
370 *----------------------------------------------------------------------------
373 OvsFlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
376 NTSTATUS status = STATUS_SUCCESS;
377 NL_ERROR nlError = NL_ERROR_SUCCESS;
378 POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;
380 if (usrParamsCtx->devOp == OVS_TRANSACTION_DEV_OP) {
381 status = _FlowNlGetCmdHandler(usrParamsCtx, replyLen);
383 /* No trasanctional errors as of now.
384 * If we have something then we need to convert rc to
386 if ((nlError != NL_ERROR_SUCCESS) &&
387 (usrParamsCtx->outputBuffer)) {
388 POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
389 usrParamsCtx->outputBuffer;
390 BuildErrorMsg(msgIn, msgError, nlError);
391 *replyLen = msgError->nlMsg.nlmsgLen;
392 status = STATUS_SUCCESS;
396 status = _FlowNlDumpCmdHandler(usrParamsCtx, replyLen);
404 *----------------------------------------------------------------------------
405 * _FlowNlGetCmdHandler --
406 * Handler for OVS_FLOW_CMD_GET command.
407 *----------------------------------------------------------------------------
410 _FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
413 NTSTATUS rc = STATUS_SUCCESS;
414 POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)
415 (usrParamsCtx->ovsInstance);
416 POVS_MESSAGE msgIn = instance->dumpState.ovsMsg;
417 PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
418 POVS_HDR ovsHdr = &(msgIn->ovsHdr);
419 PNL_MSG_HDR nlMsgOutHdr = NULL;
420 UINT32 attrOffset = NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN;
421 PNL_ATTR nlAttrs[__OVS_FLOW_ATTR_MAX];
423 OvsFlowGetInput getInput;
424 OvsFlowGetOutput getOutput;
426 PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX];
427 PNL_ATTR tunnelAttrs[__OVS_TUNNEL_KEY_ATTR_MAX];
429 NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
430 usrParamsCtx->outputLength);
431 RtlZeroMemory(&getInput, sizeof(OvsFlowGetInput));
432 RtlZeroMemory(&getOutput, sizeof(OvsFlowGetOutput));
433 UINT32 keyAttrOffset = 0;
434 UINT32 tunnelKeyAttrOffset = 0;
436 if (usrParamsCtx->inputLength > usrParamsCtx->outputLength) {
437 /* Should not be the case.
438 * We'll be copying the flow keys back from
439 * input buffer to output buffer. */
440 rc = STATUS_INVALID_PARAMETER;
441 OVS_LOG_ERROR("inputLength: %d GREATER THEN outputLength: %d",
442 usrParamsCtx->inputLength, usrParamsCtx->outputLength);
446 /* Get all the top level Flow attributes */
447 if ((NlAttrParse(nlMsgHdr, attrOffset, NlMsgAttrsLen(nlMsgHdr),
448 nlFlowPolicy, nlAttrs, ARRAY_SIZE(nlAttrs)))
450 OVS_LOG_ERROR("Attr Parsing failed for msg: %p",
452 rc = STATUS_INVALID_PARAMETER;
456 keyAttrOffset = (UINT32)((PCHAR) nlAttrs[OVS_FLOW_ATTR_KEY] -
459 /* Get flow keys attributes */
460 if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset,
461 NlAttrLen(nlAttrs[OVS_FLOW_ATTR_KEY]),
462 nlFlowKeyPolicy, keyAttrs, ARRAY_SIZE(keyAttrs)))
464 OVS_LOG_ERROR("Key Attr Parsing failed for msg: %p",
466 rc = STATUS_INVALID_PARAMETER;
470 if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
471 tunnelKeyAttrOffset = (UINT32)((PCHAR)
472 (keyAttrs[OVS_KEY_ATTR_TUNNEL])
475 /* Get tunnel keys attributes */
476 if ((NlAttrParseNested(nlMsgHdr, tunnelKeyAttrOffset,
477 NlAttrLen(keyAttrs[OVS_KEY_ATTR_TUNNEL]),
478 nlFlowTunnelKeyPolicy,
479 tunnelAttrs, ARRAY_SIZE(tunnelAttrs)))
481 OVS_LOG_ERROR("Tunnel key Attr Parsing failed for msg: %p",
483 rc = STATUS_INVALID_PARAMETER;
488 _MapKeyAttrToFlowPut(keyAttrs, tunnelAttrs,
491 getInput.dpNo = ovsHdr->dp_ifindex;
492 getInput.getFlags = FLOW_GET_STATS | FLOW_GET_ACTIONS;
494 /* 4th argument is a no op.
495 * We are keeping this argument to be compatible
496 * with our dpif-windows based interface. */
497 rc = OvsGetFlowIoctl(&getInput, &getOutput);
498 if (rc != STATUS_SUCCESS) {
499 OVS_LOG_ERROR("OvsGetFlowIoctl failed.");
503 /* Lets prepare the reply. */
504 nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, 0, 0));
506 /* Input already has all the attributes for the flow key.
507 * Lets copy the values back. */
508 RtlCopyMemory(usrParamsCtx->outputBuffer, usrParamsCtx->inputBuffer,
509 usrParamsCtx->inputLength);
511 rc = _MapFlowStatsToNlStats(&nlBuf, &((getOutput.info).stats));
512 if (rc != STATUS_SUCCESS) {
513 OVS_LOG_ERROR("_OvsFlowMapFlowKeyToNlStats failed.");
517 rc = _MapFlowActionToNlAction(&nlBuf, ((getOutput.info).actionsLen),
518 getOutput.info.actions);
519 if (rc != STATUS_SUCCESS) {
520 OVS_LOG_ERROR("_MapFlowActionToNlAction failed.");
524 NlMsgSetSize(nlMsgOutHdr, NlBufSize(&nlBuf));
525 NlMsgAlignSize(nlMsgOutHdr);
526 *replyLen += NlMsgSize(nlMsgOutHdr);
533 *----------------------------------------------------------------------------
534 * _FlowNlDumpCmdHandler --
535 * Handler for OVS_FLOW_CMD_GET command.
536 *----------------------------------------------------------------------------
539 _FlowNlDumpCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
542 NTSTATUS rc = STATUS_SUCCESS;
543 UINT32 temp = 0; /* To keep compiler happy for calling OvsDoDumpFlows */
545 POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)
546 (usrParamsCtx->ovsInstance);
548 if (usrParamsCtx->devOp == OVS_WRITE_DEV_OP) {
550 OvsSetupDumpStart(usrParamsCtx);
554 POVS_MESSAGE msgIn = instance->dumpState.ovsMsg;
555 PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
556 PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
557 POVS_HDR ovsHdr = &(msgIn->ovsHdr);
558 PNL_MSG_HDR nlMsgOutHdr = NULL;
559 UINT32 hdrOffset = 0;
562 OvsFlowDumpOutput dumpOutput;
563 OvsFlowDumpInput dumpInput;
566 NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
567 usrParamsCtx->outputLength);
569 ASSERT(usrParamsCtx->devOp == OVS_READ_DEV_OP);
570 ASSERT(usrParamsCtx->outputLength);
572 RtlZeroMemory(&dumpInput, sizeof(OvsFlowDumpInput));
573 RtlZeroMemory(&dumpOutput, sizeof(OvsFlowDumpOutput));
575 dumpInput.dpNo = ovsHdr->dp_ifindex;
576 dumpInput.getFlags = FLOW_GET_KEY | FLOW_GET_STATS | FLOW_GET_ACTIONS;
578 /* Lets provide as many flows to userspace as possible. */
580 dumpInput.position[0] = instance->dumpState.index[0];
581 dumpInput.position[1] = instance->dumpState.index[1];
583 rc = OvsDoDumpFlows(&dumpInput, &dumpOutput, &temp);
584 if (rc != STATUS_SUCCESS) {
585 OVS_LOG_ERROR("OvsDoDumpFlows failed with rc: %d", rc);
589 /* Done with Dump, send NLMSG_DONE */
590 if (!(dumpOutput.n)) {
591 OVS_LOG_INFO("Dump Done");
593 nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, NlBufSize(&nlBuf), 0));
594 rc = NlFillNlHdr(&nlBuf, NLMSG_DONE, NLM_F_MULTI,
595 nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid);
597 if (rc != STATUS_SUCCESS) {
598 OVS_LOG_ERROR("Unable to prepare DUMP_DONE reply.");
602 NlMsgAlignSize(nlMsgOutHdr);
603 *replyLen += NlMsgSize(nlMsgOutHdr);
605 FreeUserDumpState(instance);
609 hdrOffset = NlBufSize(&nlBuf);
610 nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, hdrOffset, 0));
613 rc = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, NLM_F_MULTI,
614 nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
615 genlMsgHdr->cmd, genlMsgHdr->version,
618 if (rc != STATUS_SUCCESS) {
619 /* Reset rc to success so that we can
620 * send already added messages to user space. */
625 /* Time to add attributes */
626 rc = _MapFlowInfoToNl(&nlBuf, &(dumpOutput.flow));
627 if (rc != STATUS_SUCCESS) {
628 /* Adding the attribute failed, we are out of
629 space in the buffer, remove the appended OVS header */
630 NlMsgSetSize(nlMsgOutHdr,
631 NlMsgSize(nlMsgOutHdr) -
632 sizeof(struct _OVS_MESSAGE));
634 /* Reset rc to success so that we can
635 * send already added messages to user space. */
640 NlMsgSetSize(nlMsgOutHdr, NlBufSize(&nlBuf) - hdrOffset);
641 NlMsgAlignSize(nlMsgOutHdr);
642 *replyLen += NlMsgSize(nlMsgOutHdr);
643 instance->dumpState.index[0] = dumpOutput.position[0];
644 instance->dumpState.index[1] = dumpOutput.position[1];
653 *----------------------------------------------------------------------------
654 * _MapFlowInfoToNl --
655 * Maps OvsFlowInfo to Netlink attributes.
656 *----------------------------------------------------------------------------
659 _MapFlowInfoToNl(PNL_BUFFER nlBuf, OvsFlowInfo *flowInfo)
661 NTSTATUS rc = STATUS_SUCCESS;
663 rc = MapFlowKeyToNlKey(nlBuf, &(flowInfo->key), OVS_FLOW_ATTR_KEY,
664 OVS_KEY_ATTR_TUNNEL);
665 if (rc != STATUS_SUCCESS) {
669 rc = _MapFlowStatsToNlStats(nlBuf, &(flowInfo->stats));
670 if (rc != STATUS_SUCCESS) {
674 rc = _MapFlowActionToNlAction(nlBuf, flowInfo->actionsLen,
676 if (rc != STATUS_SUCCESS) {
685 *----------------------------------------------------------------------------
686 * _MapFlowStatsToNlStats --
687 * Maps OvsFlowStats to OVS_FLOW_ATTR_STATS attribute.
688 *----------------------------------------------------------------------------
691 _MapFlowStatsToNlStats(PNL_BUFFER nlBuf, OvsFlowStats *flowStats)
693 NTSTATUS rc = STATUS_SUCCESS;
694 struct ovs_flow_stats replyStats;
696 replyStats.n_packets = flowStats->packetCount;
697 replyStats.n_bytes = flowStats->byteCount;
699 if (!NlMsgPutTailU64(nlBuf, OVS_FLOW_ATTR_USED, flowStats->used)) {
700 rc = STATUS_INVALID_BUFFER_SIZE;
704 if (!NlMsgPutTailUnspec(nlBuf, OVS_FLOW_ATTR_STATS,
705 (PCHAR)(&replyStats),
706 sizeof(struct ovs_flow_stats))) {
707 rc = STATUS_INVALID_BUFFER_SIZE;
711 if (!NlMsgPutTailU8(nlBuf, OVS_FLOW_ATTR_TCP_FLAGS, flowStats->tcpFlags)) {
712 rc = STATUS_INVALID_BUFFER_SIZE;
721 *----------------------------------------------------------------------------
722 * _MapFlowActionToNlAction --
723 * Maps flow actions to OVS_FLOW_ATTR_ACTION attribute.
724 *----------------------------------------------------------------------------
727 _MapFlowActionToNlAction(PNL_BUFFER nlBuf, uint32_t actionsLen,
730 NTSTATUS rc = STATUS_SUCCESS;
733 offset = NlMsgStartNested(nlBuf, OVS_FLOW_ATTR_ACTIONS);
735 /* Starting the nested attribute failed. */
736 rc = STATUS_INVALID_BUFFER_SIZE;
737 goto error_nested_start;
740 if (!NlBufCopyAtTail(nlBuf, (PCHAR)actions, actionsLen)) {
741 /* Adding a nested attribute failed. */
742 rc = STATUS_INVALID_BUFFER_SIZE;
747 NlMsgEndNested(nlBuf, offset);
754 *----------------------------------------------------------------------------
755 * MapFlowKeyToNlKey --
756 * Maps OvsFlowKey to OVS_FLOW_ATTR_KEY attribute.
757 *----------------------------------------------------------------------------
760 MapFlowKeyToNlKey(PNL_BUFFER nlBuf,
765 NTSTATUS rc = STATUS_SUCCESS;
766 struct ovs_key_ethernet ethKey;
769 offset = NlMsgStartNested(nlBuf, keyType);
771 /* Starting the nested attribute failed. */
772 rc = STATUS_UNSUCCESSFUL;
773 goto error_nested_start;
776 /* Ethernet header */
777 RtlCopyMemory(&(ethKey.eth_src), flowKey->l2.dlSrc, ETH_ADDR_LEN);
778 RtlCopyMemory(&(ethKey.eth_dst), flowKey->l2.dlDst, ETH_ADDR_LEN);
780 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ETHERNET,
782 sizeof(struct ovs_key_ethernet))) {
783 rc = STATUS_UNSUCCESSFUL;
787 if (!NlMsgPutTailU32(nlBuf, OVS_KEY_ATTR_IN_PORT,
788 flowKey->l2.inPort)) {
789 rc = STATUS_UNSUCCESSFUL;
793 if (!NlMsgPutTailU16(nlBuf, OVS_KEY_ATTR_ETHERTYPE,
794 flowKey->l2.dlType)) {
795 rc = STATUS_UNSUCCESSFUL;
799 if (flowKey->l2.vlanTci) {
800 if (!NlMsgPutTailU16(nlBuf, OVS_KEY_ATTR_VLAN,
801 flowKey->l2.vlanTci)) {
802 rc = STATUS_UNSUCCESSFUL;
807 /* ==== L3 + L4 ==== */
808 switch (ntohs(flowKey->l2.dlType)) {
809 case ETH_TYPE_IPV4: {
810 IpKey *ipv4FlowPutKey = &(flowKey->ipKey);
811 rc = _MapFlowIpv4KeyToNlKey(nlBuf, ipv4FlowPutKey);
815 case ETH_TYPE_IPV6: {
816 Ipv6Key *ipv6FlowPutKey = &(flowKey->ipv6Key);
817 Icmp6Key *icmpv6FlowPutKey = &(flowKey->icmp6Key);
818 rc = _MapFlowIpv6KeyToNlKey(nlBuf, ipv6FlowPutKey,
824 case ETH_TYPE_RARP: {
825 ArpKey *arpFlowPutKey = &(flowKey->arpKey);
826 rc = _MapFlowArpKeyToNlKey(nlBuf, arpFlowPutKey);
834 if (rc != STATUS_SUCCESS) {
838 if (flowKey->tunKey.dst) {
839 rc = MapFlowTunKeyToNlKey(nlBuf, &(flowKey->tunKey),
841 if (rc != STATUS_SUCCESS) {
847 NlMsgEndNested(nlBuf, offset);
853 *----------------------------------------------------------------------------
854 * MapFlowTunKeyToNlKey --
855 * Maps OvsIPv4TunnelKey to OVS_TUNNEL_KEY_ATTR_ID attribute.
856 *----------------------------------------------------------------------------
859 MapFlowTunKeyToNlKey(PNL_BUFFER nlBuf,
860 OvsIPv4TunnelKey *tunKey,
863 NTSTATUS rc = STATUS_SUCCESS;
866 offset = NlMsgStartNested(nlBuf, tunKeyType);
868 /* Starting the nested attribute failed. */
869 rc = STATUS_UNSUCCESSFUL;
870 goto error_nested_start;
873 if (!NlMsgPutTailU64(nlBuf, OVS_TUNNEL_KEY_ATTR_ID,
875 rc = STATUS_UNSUCCESSFUL;
879 if (!NlMsgPutTailU32(nlBuf, OVS_TUNNEL_KEY_ATTR_IPV4_DST,
881 rc = STATUS_UNSUCCESSFUL;
885 if (!NlMsgPutTailU32(nlBuf, OVS_TUNNEL_KEY_ATTR_IPV4_SRC,
887 rc = STATUS_UNSUCCESSFUL;
891 if (!NlMsgPutTailU8(nlBuf, OVS_TUNNEL_KEY_ATTR_TOS,
893 rc = STATUS_UNSUCCESSFUL;
897 if (!NlMsgPutTailU8(nlBuf, OVS_TUNNEL_KEY_ATTR_TTL,
899 rc = STATUS_UNSUCCESSFUL;
904 NlMsgEndNested(nlBuf, offset);
910 *----------------------------------------------------------------------------
911 * _MapFlowTunKeyToNlKey --
912 * Maps OvsIPv4FlowPutKey to OVS_KEY_ATTR_IPV4 attribute.
913 *----------------------------------------------------------------------------
916 _MapFlowIpv4KeyToNlKey(PNL_BUFFER nlBuf, IpKey *ipv4FlowPutKey)
918 NTSTATUS rc = STATUS_SUCCESS;
919 struct ovs_key_ipv4 ipv4Key;
921 ipv4Key.ipv4_src = ipv4FlowPutKey->nwSrc;
922 ipv4Key.ipv4_dst = ipv4FlowPutKey->nwDst;
923 ipv4Key.ipv4_proto = ipv4FlowPutKey->nwProto;
924 ipv4Key.ipv4_tos = ipv4FlowPutKey->nwTos;
925 ipv4Key.ipv4_ttl = ipv4FlowPutKey->nwTtl;
926 ipv4Key.ipv4_frag = ipv4FlowPutKey->nwFrag;
928 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_IPV4,
930 sizeof(struct ovs_key_ipv4))) {
931 rc = STATUS_UNSUCCESSFUL;
935 switch (ipv4Key.ipv4_proto) {
937 struct ovs_key_tcp tcpKey;
938 tcpKey.tcp_src = ipv4FlowPutKey->l4.tpSrc;
939 tcpKey.tcp_dst = ipv4FlowPutKey->l4.tpDst;
940 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_TCP,
943 rc = STATUS_UNSUCCESSFUL;
950 struct ovs_key_udp udpKey;
951 udpKey.udp_src = ipv4FlowPutKey->l4.tpSrc;
952 udpKey.udp_dst = ipv4FlowPutKey->l4.tpDst;
953 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_UDP,
956 rc = STATUS_UNSUCCESSFUL;
963 struct ovs_key_sctp sctpKey;
964 sctpKey.sctp_src = ipv4FlowPutKey->l4.tpSrc;
965 sctpKey.sctp_dst = ipv4FlowPutKey->l4.tpDst;
966 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_SCTP,
969 rc = STATUS_UNSUCCESSFUL;
976 struct ovs_key_icmp icmpKey;
977 /* XXX: revisit to see if htons is needed */
978 icmpKey.icmp_type = (__u8)(ipv4FlowPutKey->l4.tpSrc);
979 icmpKey.icmp_code = (__u8)(ipv4FlowPutKey->l4.tpDst);
981 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ICMP,
984 rc = STATUS_UNSUCCESSFUL;
999 *----------------------------------------------------------------------------
1000 * _MapFlowIpv6KeyToNlKey --
1001 * Maps _MapFlowIpv6KeyToNlKey to OVS_KEY_ATTR_IPV6 attribute.
1002 *----------------------------------------------------------------------------
1005 _MapFlowIpv6KeyToNlKey(PNL_BUFFER nlBuf, Ipv6Key *ipv6FlowPutKey,
1006 Icmp6Key *icmpv6FlowPutKey)
1008 NTSTATUS rc = STATUS_SUCCESS;
1009 struct ovs_key_ipv6 ipv6Key;
1011 RtlCopyMemory(&(ipv6Key.ipv6_src), &ipv6FlowPutKey->ipv6Src,
1012 sizeof ipv6Key.ipv6_src);
1013 RtlCopyMemory(&(ipv6Key.ipv6_dst), &ipv6FlowPutKey->ipv6Dst,
1014 sizeof ipv6Key.ipv6_dst);
1016 ipv6Key.ipv6_label = ipv6FlowPutKey->ipv6Label;
1017 ipv6Key.ipv6_proto = ipv6FlowPutKey->nwProto;
1018 ipv6Key.ipv6_tclass = ipv6FlowPutKey->nwTos;
1019 ipv6Key.ipv6_hlimit = ipv6FlowPutKey->nwTtl;
1020 ipv6Key.ipv6_frag = ipv6FlowPutKey->nwFrag;
1022 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_IPV6,
1025 rc = STATUS_UNSUCCESSFUL;
1029 switch (ipv6Key.ipv6_proto) {
1031 struct ovs_key_tcp tcpKey;
1032 tcpKey.tcp_src = ipv6FlowPutKey->l4.tpSrc;
1033 tcpKey.tcp_dst = ipv6FlowPutKey->l4.tpDst;
1034 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_TCP,
1037 rc = STATUS_UNSUCCESSFUL;
1044 struct ovs_key_udp udpKey;
1045 udpKey.udp_src = ipv6FlowPutKey->l4.tpSrc;
1046 udpKey.udp_dst = ipv6FlowPutKey->l4.tpDst;
1047 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_UDP,
1050 rc = STATUS_UNSUCCESSFUL;
1056 case IPPROTO_SCTP: {
1057 struct ovs_key_sctp sctpKey;
1058 sctpKey.sctp_src = ipv6FlowPutKey->l4.tpSrc;
1059 sctpKey.sctp_dst = ipv6FlowPutKey->l4.tpDst;
1060 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_SCTP,
1063 rc = STATUS_UNSUCCESSFUL;
1069 case IPPROTO_ICMPV6: {
1070 struct ovs_key_icmpv6 icmpV6Key;
1071 struct ovs_key_nd ndKey;
1073 /* XXX: revisit to see if htons is needed */
1074 icmpV6Key.icmpv6_type = (__u8)(icmpv6FlowPutKey->l4.tpSrc);
1075 icmpV6Key.icmpv6_code = (__u8)(icmpv6FlowPutKey->l4.tpDst);
1077 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ICMPV6,
1078 (PCHAR)(&icmpV6Key),
1079 sizeof(icmpV6Key))) {
1080 rc = STATUS_UNSUCCESSFUL;
1084 RtlCopyMemory(&(ndKey.nd_target), &icmpv6FlowPutKey->ndTarget,
1085 sizeof(icmpv6FlowPutKey->ndTarget));
1086 RtlCopyMemory(&(ndKey.nd_sll), &icmpv6FlowPutKey->arpSha,
1088 RtlCopyMemory(&(ndKey.nd_tll), &icmpv6FlowPutKey->arpTha,
1090 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ND,
1093 rc = STATUS_UNSUCCESSFUL;
1109 *----------------------------------------------------------------------------
1110 * _MapFlowArpKeyToNlKey --
1111 * Maps _MapFlowArpKeyToNlKey to OVS_KEY_ATTR_ARP attribute.
1112 *----------------------------------------------------------------------------
1115 _MapFlowArpKeyToNlKey(PNL_BUFFER nlBuf, ArpKey *arpFlowPutKey)
1117 NTSTATUS rc = STATUS_SUCCESS;
1118 struct ovs_key_arp arpKey;
1120 arpKey.arp_sip = arpFlowPutKey->nwSrc;
1121 arpKey.arp_tip = arpFlowPutKey->nwDst;
1123 RtlCopyMemory(&(arpKey.arp_sha), arpFlowPutKey->arpSha, ETH_ADDR_LEN);
1124 RtlCopyMemory(&(arpKey.arp_tha), arpFlowPutKey->arpTha, ETH_ADDR_LEN);
1127 * Flow_Extract() stores 'nwProto' in host order for ARP since 'nwProto' is
1128 * 1 byte field and the ARP opcode is 2 bytes, and all of the kernel code
1129 * understand this while looking at an ARP key.
1130 * While we pass up the ARP key to userspace, convert from host order to
1131 * network order. Likewise, when processing an ARP key from userspace,
1132 * convert from network order to host order.
1134 * It is important to note that the flow table stores the ARP opcode field
1137 arpKey.arp_op = htons(arpFlowPutKey->nwProto);
1139 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ARP,
1142 rc = STATUS_UNSUCCESSFUL;
1151 *----------------------------------------------------------------------------
1152 * _MapNlToFlowPut --
1153 * Maps input netlink message to OvsFlowPut.
1154 *----------------------------------------------------------------------------
1157 _MapNlToFlowPut(POVS_MESSAGE msgIn, PNL_ATTR keyAttr,
1158 PNL_ATTR actionAttr, PNL_ATTR flowAttrClear,
1159 OvsFlowPut *mappedFlow)
1161 NTSTATUS rc = STATUS_SUCCESS;
1162 PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
1163 PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
1164 POVS_HDR ovsHdr = &(msgIn->ovsHdr);
1166 UINT32 keyAttrOffset = (UINT32)((PCHAR)keyAttr - (PCHAR)nlMsgHdr);
1167 UINT32 tunnelKeyAttrOffset;
1169 PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX] = {NULL};
1170 PNL_ATTR tunnelAttrs[__OVS_TUNNEL_KEY_ATTR_MAX] = {NULL};
1172 /* Get flow keys attributes */
1173 if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset, NlAttrLen(keyAttr),
1174 nlFlowKeyPolicy, keyAttrs, ARRAY_SIZE(keyAttrs)))
1176 OVS_LOG_ERROR("Key Attr Parsing failed for msg: %p",
1178 rc = STATUS_INVALID_PARAMETER;
1182 if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
1183 tunnelKeyAttrOffset = (UINT32)((PCHAR)
1184 (keyAttrs[OVS_KEY_ATTR_TUNNEL])
1187 OVS_LOG_ERROR("Parse Flow Tunnel Key Policy");
1189 /* Get tunnel keys attributes */
1190 if ((NlAttrParseNested(nlMsgHdr, tunnelKeyAttrOffset,
1191 NlAttrLen(keyAttrs[OVS_KEY_ATTR_TUNNEL]),
1192 nlFlowTunnelKeyPolicy,
1193 tunnelAttrs, ARRAY_SIZE(tunnelAttrs)))
1195 OVS_LOG_ERROR("Tunnel key Attr Parsing failed for msg: %p",
1197 rc = STATUS_INVALID_PARAMETER;
1202 _MapKeyAttrToFlowPut(keyAttrs, tunnelAttrs,
1203 &(mappedFlow->key));
1205 /* Map the action */
1207 mappedFlow->actionsLen = NlAttrGetSize(actionAttr);
1208 mappedFlow->actions = NlAttrGet(actionAttr);
1211 mappedFlow->dpNo = ovsHdr->dp_ifindex;
1213 _MapNlToFlowPutFlags(genlMsgHdr, flowAttrClear,
1221 *----------------------------------------------------------------------------
1222 * _MapNlToFlowPutFlags --
1223 * Maps netlink message to OvsFlowPut->flags.
1224 *----------------------------------------------------------------------------
1227 _MapNlToFlowPutFlags(PGENL_MSG_HDR genlMsgHdr,
1228 PNL_ATTR flowAttrClear, OvsFlowPut *mappedFlow)
1232 switch (genlMsgHdr->cmd) {
1233 case OVS_FLOW_CMD_NEW:
1234 flags |= OVSWIN_FLOW_PUT_CREATE;
1236 case OVS_FLOW_CMD_DEL:
1237 flags |= OVSWIN_FLOW_PUT_DELETE;
1239 case OVS_FLOW_CMD_SET:
1240 flags |= OVSWIN_FLOW_PUT_MODIFY;
1246 if (flowAttrClear) {
1247 flags |= OVSWIN_FLOW_PUT_CLEAR;
1250 mappedFlow->flags = flags;
1254 *----------------------------------------------------------------------------
1255 * _MapKeyAttrToFlowPut --
1256 * Converts FLOW_KEY attribute to OvsFlowPut->key.
1257 *----------------------------------------------------------------------------
1260 _MapKeyAttrToFlowPut(PNL_ATTR *keyAttrs,
1261 PNL_ATTR *tunnelAttrs,
1262 OvsFlowKey *destKey)
1264 _MapTunAttrToFlowPut(keyAttrs, tunnelAttrs, destKey);
1266 /* ===== L2 headers ===== */
1267 destKey->l2.inPort = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_IN_PORT]);
1269 if (keyAttrs[OVS_KEY_ATTR_ETHERNET]) {
1270 const struct ovs_key_ethernet *eth_key;
1271 eth_key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ETHERNET]);
1272 RtlCopyMemory(destKey->l2.dlSrc, eth_key->eth_src, ETH_ADDR_LEN);
1273 RtlCopyMemory(destKey->l2.dlDst, eth_key->eth_dst, ETH_ADDR_LEN);
1276 /* TODO: Ideally ETHERTYPE should not be optional.
1277 * But during vswitchd bootup we are seeing FLOW_ADD
1278 * requests with no ETHERTYPE attributes.
1279 * Need to verify this. */
1280 if (keyAttrs[OVS_KEY_ATTR_ETHERTYPE]) {
1281 destKey->l2.dlType = (NlAttrGetU16(keyAttrs
1282 [OVS_KEY_ATTR_ETHERTYPE]));
1285 if (keyAttrs[OVS_KEY_ATTR_VLAN]) {
1286 destKey->l2.vlanTci = NlAttrGetU16(keyAttrs[OVS_KEY_ATTR_VLAN]);
1289 /* ==== L3 + L4. ==== */
1290 destKey->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + OVS_L2_KEY_SIZE
1291 - destKey->l2.offset;
1293 switch (ntohs(destKey->l2.dlType)) {
1294 case ETH_TYPE_IPV4: {
1296 if (keyAttrs[OVS_KEY_ATTR_IPV4]) {
1297 const struct ovs_key_ipv4 *ipv4Key;
1299 ipv4Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_IPV4]);
1300 IpKey *ipv4FlowPutKey = &(destKey->ipKey);
1301 ipv4FlowPutKey->nwSrc = ipv4Key->ipv4_src;
1302 ipv4FlowPutKey->nwDst = ipv4Key->ipv4_dst;
1303 ipv4FlowPutKey->nwProto = ipv4Key->ipv4_proto;
1304 ipv4FlowPutKey->nwTos = ipv4Key->ipv4_tos;
1305 ipv4FlowPutKey->nwTtl = ipv4Key->ipv4_ttl;
1306 ipv4FlowPutKey->nwFrag = ipv4Key->ipv4_frag;
1308 if (keyAttrs[OVS_KEY_ATTR_TCP]) {
1309 const struct ovs_key_tcp *tcpKey;
1310 tcpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_TCP]);
1311 ipv4FlowPutKey->l4.tpSrc = tcpKey->tcp_src;
1312 ipv4FlowPutKey->l4.tpDst = tcpKey->tcp_dst;
1315 if (keyAttrs[OVS_KEY_ATTR_UDP]) {
1316 const struct ovs_key_udp *udpKey;
1317 udpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_UDP]);
1318 ipv4FlowPutKey->l4.tpSrc = udpKey->udp_src;
1319 ipv4FlowPutKey->l4.tpDst = udpKey->udp_dst;
1322 if (keyAttrs[OVS_KEY_ATTR_SCTP]) {
1323 const struct ovs_key_sctp *sctpKey;
1324 sctpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_SCTP]);
1325 ipv4FlowPutKey->l4.tpSrc = sctpKey->sctp_src;
1326 ipv4FlowPutKey->l4.tpDst = sctpKey->sctp_dst;
1329 destKey->l2.keyLen += OVS_IP_KEY_SIZE;
1333 case ETH_TYPE_IPV6: {
1335 if (keyAttrs[OVS_KEY_ATTR_IPV6]) {
1336 const struct ovs_key_ipv6 *ipv6Key;
1338 ipv6Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_IPV6]);
1339 Ipv6Key *ipv6FlowPutKey = &(destKey->ipv6Key);
1341 RtlCopyMemory(&ipv6FlowPutKey->ipv6Src, ipv6Key->ipv6_src,
1342 sizeof ipv6Key->ipv6_src);
1343 RtlCopyMemory(&ipv6FlowPutKey->ipv6Dst, ipv6Key->ipv6_dst,
1344 sizeof ipv6Key->ipv6_dst);
1346 ipv6FlowPutKey->ipv6Label = ipv6Key->ipv6_label;
1347 ipv6FlowPutKey->nwProto = ipv6Key->ipv6_proto;
1348 ipv6FlowPutKey->nwTos = ipv6Key->ipv6_tclass;
1349 ipv6FlowPutKey->nwTtl = ipv6Key->ipv6_hlimit;
1350 ipv6FlowPutKey->nwFrag = ipv6Key->ipv6_frag;
1352 if (keyAttrs[OVS_KEY_ATTR_TCP]) {
1353 const struct ovs_key_tcp *tcpKey;
1354 tcpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_TCP]);
1355 ipv6FlowPutKey->l4.tpSrc = tcpKey->tcp_src;
1356 ipv6FlowPutKey->l4.tpDst = tcpKey->tcp_dst;
1359 if (keyAttrs[OVS_KEY_ATTR_UDP]) {
1360 const struct ovs_key_udp *udpKey;
1361 udpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_UDP]);
1362 ipv6FlowPutKey->l4.tpSrc = udpKey->udp_src;
1363 ipv6FlowPutKey->l4.tpDst = udpKey->udp_dst;
1366 if (keyAttrs[OVS_KEY_ATTR_SCTP]) {
1367 const struct ovs_key_sctp *sctpKey;
1368 sctpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_SCTP]);
1369 ipv6FlowPutKey->l4.tpSrc = sctpKey->sctp_src;
1370 ipv6FlowPutKey->l4.tpDst = sctpKey->sctp_dst;
1373 if (keyAttrs[OVS_KEY_ATTR_ICMPV6]) {
1374 const struct ovs_key_icmpv6 *icmpv6Key;
1376 Icmp6Key *icmp6FlowPutKey= &(destKey->icmp6Key);
1378 icmpv6Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ICMPV6]);
1380 icmp6FlowPutKey->l4.tpSrc = icmpv6Key->icmpv6_type;
1381 icmp6FlowPutKey->l4.tpDst = icmpv6Key->icmpv6_code;
1383 if (keyAttrs[OVS_KEY_ATTR_ND]) {
1384 const struct ovs_key_nd *ndKey;
1386 ndKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ND]);
1387 RtlCopyMemory(&icmp6FlowPutKey->ndTarget,
1388 ndKey->nd_target, sizeof (icmp6FlowPutKey->ndTarget));
1389 RtlCopyMemory(icmp6FlowPutKey->arpSha,
1390 ndKey->nd_sll, ETH_ADDR_LEN);
1391 RtlCopyMemory(icmp6FlowPutKey->arpTha,
1392 ndKey->nd_tll, ETH_ADDR_LEN);
1395 destKey->l2.keyLen += OVS_ICMPV6_KEY_SIZE;
1399 destKey->l2.keyLen += OVS_IPV6_KEY_SIZE;
1402 ipv6FlowPutKey->pad = 0;
1407 case ETH_TYPE_RARP: {
1409 if (keyAttrs[OVS_KEY_ATTR_ARP]) {
1410 ArpKey *arpFlowPutKey = &destKey->arpKey;
1411 const struct ovs_key_arp *arpKey;
1413 arpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ARP]);
1415 arpFlowPutKey->nwSrc = arpKey->arp_sip;
1416 arpFlowPutKey->nwDst = arpKey->arp_tip;
1418 RtlCopyMemory(arpFlowPutKey->arpSha, arpKey->arp_sha, ETH_ADDR_LEN);
1419 RtlCopyMemory(arpFlowPutKey->arpTha, arpKey->arp_tha, ETH_ADDR_LEN);
1420 /* Kernel datapath assumes 'arpFlowPutKey->nwProto' to be in host
1422 arpFlowPutKey->nwProto = (UINT8)ntohs((arpKey->arp_op));
1423 arpFlowPutKey->pad[0] = 0;
1424 arpFlowPutKey->pad[1] = 0;
1425 arpFlowPutKey->pad[2] = 0;
1426 destKey->l2.keyLen += OVS_ARP_KEY_SIZE;
1434 *----------------------------------------------------------------------------
1435 * _MapTunAttrToFlowPut --
1436 * Converts FLOW_TUNNEL_KEY attribute to OvsFlowKey->tunKey.
1437 *----------------------------------------------------------------------------
1440 _MapTunAttrToFlowPut(PNL_ATTR *keyAttrs,
1442 OvsFlowKey *destKey)
1444 if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
1446 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_ID]) {
1447 destKey->tunKey.tunnelId = NlAttrGetU64
1448 (tunAttrs[OVS_TUNNEL_KEY_ATTR_ID]);
1449 destKey->tunKey.flags |= OVS_TNL_F_KEY;
1452 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_DST]) {
1453 destKey->tunKey.dst = NlAttrGetU32
1454 (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_DST]);
1457 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_SRC]) {
1458 destKey->tunKey.src = NlAttrGetU32
1459 (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_SRC]);
1462 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT]) {
1463 destKey->tunKey.flags |= OVS_TNL_F_DONT_FRAGMENT;
1466 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_CSUM]) {
1467 destKey->tunKey.flags |= OVS_TNL_F_CSUM;
1470 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_TOS]) {
1471 destKey->tunKey.tos = NlAttrGetU8
1472 (tunAttrs[OVS_TUNNEL_KEY_ATTR_TOS]);
1475 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_TTL]) {
1476 destKey->tunKey.ttl = NlAttrGetU8
1477 (tunAttrs[OVS_TUNNEL_KEY_ATTR_TTL]);
1480 destKey->tunKey.pad = 0;
1481 destKey->l2.offset = 0;
1483 destKey->tunKey.attr[0] = 0;
1484 destKey->tunKey.attr[1] = 0;
1485 destKey->tunKey.attr[2] = 0;
1486 destKey->l2.offset = sizeof destKey->tunKey;
1491 *----------------------------------------------------------------------------
1492 * OvsDeleteFlowTable --
1494 * NDIS_STATUS_SUCCESS always.
1495 *----------------------------------------------------------------------------
1498 OvsDeleteFlowTable(OVS_DATAPATH *datapath)
1500 if (datapath == NULL || datapath->flowTable == NULL) {
1501 return NDIS_STATUS_SUCCESS;
1504 DeleteAllFlows(datapath);
1505 OvsFreeMemory(datapath->flowTable);
1506 datapath->flowTable = NULL;
1507 NdisFreeRWLock(datapath->lock);
1509 return NDIS_STATUS_SUCCESS;
1513 *----------------------------------------------------------------------------
1514 * OvsAllocateFlowTable --
1516 * NDIS_STATUS_SUCCESS on success.
1517 * NDIS_STATUS_RESOURCES if memory couldn't be allocated
1518 *----------------------------------------------------------------------------
1521 OvsAllocateFlowTable(OVS_DATAPATH *datapath,
1522 POVS_SWITCH_CONTEXT switchContext)
1527 datapath->flowTable = OvsAllocateMemory(OVS_FLOW_TABLE_SIZE *
1528 sizeof (LIST_ENTRY));
1529 if (!datapath->flowTable) {
1530 return NDIS_STATUS_RESOURCES;
1532 for (i = 0; i < OVS_FLOW_TABLE_SIZE; i++) {
1533 bucket = &(datapath->flowTable[i]);
1534 InitializeListHead(bucket);
1536 datapath->lock = NdisAllocateRWLock(switchContext->NdisFilterHandle);
1538 return NDIS_STATUS_SUCCESS;
1543 *----------------------------------------------------------------------------
1544 * GetStartAddrNBL --
1545 * Get the virtual address of the frame.
1548 * Virtual address of the frame.
1549 *----------------------------------------------------------------------------
1551 static __inline VOID *
1552 GetStartAddrNBL(const NET_BUFFER_LIST *_pNB)
1560 // Ethernet Header is a guaranteed safe access.
1561 curMdl = (NET_BUFFER_LIST_FIRST_NB(_pNB))->CurrentMdl;
1562 curBuffer = MmGetSystemAddressForMdlSafe(curMdl, LowPagePriority);
1567 curHeader = (PEthHdr)
1568 (curBuffer + (NET_BUFFER_LIST_FIRST_NB(_pNB))->CurrentMdlOffset);
1570 return (VOID *) curHeader;
1574 OvsFlowUsed(OvsFlow *flow,
1575 const NET_BUFFER_LIST *packet,
1576 const POVS_PACKET_HDR_INFO layers)
1578 LARGE_INTEGER tickCount;
1580 KeQueryTickCount(&tickCount);
1581 flow->used = tickCount.QuadPart * ovsTimeIncrementPerTick;
1582 flow->packetCount++;
1583 flow->byteCount += OvsPacketLenNBL(packet);
1584 flow->tcpFlags |= OvsGetTcpFlags(packet, &flow->key, layers);
1589 DeleteAllFlows(OVS_DATAPATH *datapath)
1594 for (i = 0; i < OVS_FLOW_TABLE_SIZE; i++) {
1596 bucket = &(datapath->flowTable[i]);
1597 while (!IsListEmpty(bucket)) {
1599 next = bucket->Flink;
1600 flow = CONTAINING_RECORD(next, OvsFlow, ListEntry);
1601 RemoveFlow(datapath, &flow);
1607 *----------------------------------------------------------------------------
1608 * Initializes 'flow' members from 'packet', 'skb_priority', 'tun_id', and
1611 * Initializes 'packet' header pointers as follows:
1613 * - packet->l2 to the start of the Ethernet header.
1615 * - packet->l3 to just past the Ethernet header, or just past the
1616 * vlan_header if one is present, to the first byte of the payload of the
1619 * - packet->l4 to just past the IPv4 header, if one is present and has a
1620 * correct length, and otherwise NULL.
1622 * - packet->l7 to just past the TCP or UDP or ICMP header, if one is
1623 * present and has a correct length, and otherwise NULL.
1625 * Returns NDIS_STATUS_SUCCESS normally. Fails only if packet data cannot be accessed
1626 * (e.g. if Pkt_CopyBytesOut() returns an error).
1627 *----------------------------------------------------------------------------
1630 OvsExtractFlow(const NET_BUFFER_LIST *packet,
1633 POVS_PACKET_HDR_INFO layers,
1634 OvsIPv4TunnelKey *tunKey)
1636 struct Eth_Header *eth;
1643 ASSERT(tunKey->dst != 0);
1644 RtlMoveMemory(&flow->tunKey, tunKey, sizeof flow->tunKey);
1645 flow->l2.offset = 0;
1647 flow->tunKey.dst = 0;
1648 flow->l2.offset = OVS_WIN_TUNNEL_KEY_SIZE;
1651 flow->l2.inPort = inPort;
1653 if ( OvsPacketLenNBL(packet) < ETH_HEADER_LEN_DIX) {
1654 flow->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + 8 - flow->l2.offset;
1655 return NDIS_STATUS_SUCCESS;
1659 eth = (Eth_Header *)GetStartAddrNBL((NET_BUFFER_LIST *)packet);
1660 memcpy(flow->l2.dlSrc, eth->src, ETH_ADDR_LENGTH);
1661 memcpy(flow->l2.dlDst, eth->dst, ETH_ADDR_LENGTH);
1666 vlanTagValue = NET_BUFFER_LIST_INFO(packet, Ieee8021QNetBufferListInfo);
1668 PNDIS_NET_BUFFER_LIST_8021Q_INFO vlanTag =
1669 (PNDIS_NET_BUFFER_LIST_8021Q_INFO)(PVOID *)&vlanTagValue;
1670 flow->l2.vlanTci = htons(vlanTag->TagHeader.VlanId | OVSWIN_VLAN_CFI |
1671 (vlanTag->TagHeader.UserPriority << 13));
1673 if (eth->dix.typeNBO == ETH_TYPE_802_1PQ_NBO) {
1674 Eth_802_1pq_Tag *tag= (Eth_802_1pq_Tag *)ð->dix.typeNBO;
1675 flow->l2.vlanTci = ((UINT16)tag->priority << 13) |
1677 ((UINT16)tag->vidHi << 8) | tag->vidLo;
1678 offset = sizeof (Eth_802_1pq_Tag);
1680 flow->l2.vlanTci = 0;
1684 * Please note after this point, src mac and dst mac should
1685 * not be accessed through eth
1687 eth = (Eth_Header *)((UINT8 *)eth + offset);
1693 * XXX assume that at least the first
1694 * 12 bytes of received packets are mapped. This code has the stronger
1695 * assumption that at least the first 22 bytes of 'packet' is mapped (if my
1696 * arithmetic is right).
1698 if (ETH_TYPENOT8023(eth->dix.typeNBO)) {
1699 flow->l2.dlType = eth->dix.typeNBO;
1700 layers->l3Offset = ETH_HEADER_LEN_DIX + offset;
1701 } else if (OvsPacketLenNBL(packet) >= ETH_HEADER_LEN_802_3 &&
1702 eth->e802_3.llc.dsap == 0xaa &&
1703 eth->e802_3.llc.ssap == 0xaa &&
1704 eth->e802_3.llc.control == ETH_LLC_CONTROL_UFRAME &&
1705 eth->e802_3.snap.snapOrg[0] == 0x00 &&
1706 eth->e802_3.snap.snapOrg[1] == 0x00 &&
1707 eth->e802_3.snap.snapOrg[2] == 0x00) {
1708 flow->l2.dlType = eth->e802_3.snap.snapType.typeNBO;
1709 layers->l3Offset = ETH_HEADER_LEN_802_3 + offset;
1711 flow->l2.dlType = htons(OVSWIN_DL_TYPE_NONE);
1712 layers->l3Offset = ETH_HEADER_LEN_DIX + offset;
1715 flow->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + OVS_L2_KEY_SIZE - flow->l2.offset;
1716 /* Network layer. */
1717 if (flow->l2.dlType == htons(ETH_TYPE_IPV4)) {
1718 struct IPHdr ip_storage;
1719 const struct IPHdr *nh;
1720 IpKey *ipKey = &flow->ipKey;
1722 flow->l2.keyLen += OVS_IP_KEY_SIZE;
1724 nh = OvsGetIp(packet, layers->l3Offset, &ip_storage);
1726 layers->l4Offset = layers->l3Offset + nh->ihl * 4;
1728 ipKey->nwSrc = nh->saddr;
1729 ipKey->nwDst = nh->daddr;
1730 ipKey->nwProto = nh->protocol;
1732 ipKey->nwTos = nh->tos;
1733 if (nh->frag_off & htons(IP_MF | IP_OFFSET)) {
1734 ipKey->nwFrag = OVSWIN_NW_FRAG_ANY;
1735 if (nh->frag_off & htons(IP_OFFSET)) {
1736 ipKey->nwFrag |= OVSWIN_NW_FRAG_LATER;
1742 ipKey->nwTtl = nh->ttl;
1743 ipKey->l4.tpSrc = 0;
1744 ipKey->l4.tpDst = 0;
1746 if (!(nh->frag_off & htons(IP_OFFSET))) {
1747 if (ipKey->nwProto == SOCKET_IPPROTO_TCP) {
1748 OvsParseTcp(packet, &ipKey->l4, layers);
1749 } else if (ipKey->nwProto == SOCKET_IPPROTO_UDP) {
1750 OvsParseUdp(packet, &ipKey->l4, layers);
1751 } else if (ipKey->nwProto == SOCKET_IPPROTO_ICMP) {
1752 ICMPHdr icmpStorage;
1753 const ICMPHdr *icmp;
1755 icmp = OvsGetIcmp(packet, layers->l4Offset, &icmpStorage);
1757 ipKey->l4.tpSrc = htons(icmp->type);
1758 ipKey->l4.tpDst = htons(icmp->code);
1759 layers->l7Offset = layers->l4Offset + sizeof *icmp;
1764 ((UINT64 *)ipKey)[0] = 0;
1765 ((UINT64 *)ipKey)[1] = 0;
1767 } else if (flow->l2.dlType == htons(ETH_TYPE_IPV6)) {
1769 flow->l2.keyLen += OVS_IPV6_KEY_SIZE;
1770 status = OvsParseIPv6(packet, flow, layers);
1771 if (status != NDIS_STATUS_SUCCESS) {
1772 memset(&flow->ipv6Key, 0, sizeof (Ipv6Key));
1776 flow->ipv6Key.l4.tpSrc = 0;
1777 flow->ipv6Key.l4.tpDst = 0;
1778 flow->ipv6Key.pad = 0;
1780 if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_TCP) {
1781 OvsParseTcp(packet, &(flow->ipv6Key.l4), layers);
1782 } else if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_UDP) {
1783 OvsParseUdp(packet, &(flow->ipv6Key.l4), layers);
1784 } else if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_ICMPV6) {
1785 OvsParseIcmpV6(packet, flow, layers);
1786 flow->l2.keyLen += (OVS_ICMPV6_KEY_SIZE - OVS_IPV6_KEY_SIZE);
1788 } else if (flow->l2.dlType == htons(ETH_TYPE_ARP)) {
1789 EtherArp arpStorage;
1790 const EtherArp *arp;
1791 ArpKey *arpKey = &flow->arpKey;
1792 ((UINT64 *)arpKey)[0] = 0;
1793 ((UINT64 *)arpKey)[1] = 0;
1794 ((UINT64 *)arpKey)[2] = 0;
1795 flow->l2.keyLen += OVS_ARP_KEY_SIZE;
1796 arp = OvsGetArp(packet, layers->l3Offset, &arpStorage);
1797 if (arp && arp->ea_hdr.ar_hrd == htons(1) &&
1798 arp->ea_hdr.ar_pro == htons(ETH_TYPE_IPV4) &&
1799 arp->ea_hdr.ar_hln == ETH_ADDR_LENGTH &&
1800 arp->ea_hdr.ar_pln == 4) {
1801 /* We only match on the lower 8 bits of the opcode. */
1802 if (ntohs(arp->ea_hdr.ar_op) <= 0xff) {
1803 arpKey->nwProto = (UINT8)ntohs(arp->ea_hdr.ar_op);
1805 if (arpKey->nwProto == ARPOP_REQUEST
1806 || arpKey->nwProto == ARPOP_REPLY) {
1807 memcpy(&arpKey->nwSrc, arp->arp_spa, 4);
1808 memcpy(&arpKey->nwDst, arp->arp_tpa, 4);
1809 memcpy(arpKey->arpSha, arp->arp_sha, ETH_ADDR_LENGTH);
1810 memcpy(arpKey->arpTha, arp->arp_tha, ETH_ADDR_LENGTH);
1815 return NDIS_STATUS_SUCCESS;
1819 FlowEqual(UINT64 *src, UINT64 *dst, UINT32 size)
1822 ASSERT((size & 0x7) == 0);
1823 ASSERT(((UINT64)src & 0x7) == 0);
1824 ASSERT(((UINT64)dst & 0x7) == 0);
1825 for (i = 0; i < (size >> 3); i++) {
1826 if (src[i] != dst[i]) {
1835 * ----------------------------------------------------------------------------
1837 * Add a flow to flow table.
1840 * NDIS_STATUS_SUCCESS if no same flow in the flow table.
1841 * ----------------------------------------------------------------------------
1844 AddFlow(OVS_DATAPATH *datapath, OvsFlow *flow)
1848 if (OvsLookupFlow(datapath, &flow->key, &flow->hash, TRUE) != NULL) {
1849 return STATUS_INVALID_HANDLE;
1852 head = &(datapath->flowTable[HASH_BUCKET(flow->hash)]);
1854 * We need fence here to make sure flow's nextPtr is updated before
1855 * head->nextPtr is updated.
1859 //KeAcquireSpinLock(&FilterDeviceExtension->NblQueueLock, &oldIrql);
1860 InsertTailList(head, &flow->ListEntry);
1861 //KeReleaseSpinLock(&FilterDeviceExtension->NblQueueLock, oldIrql);
1865 return STATUS_SUCCESS;
1869 /* ----------------------------------------------------------------------------
1871 * Remove a flow from flow table, and added to wait list
1872 * ----------------------------------------------------------------------------
1875 RemoveFlow(OVS_DATAPATH *datapath,
1880 UNREFERENCED_PARAMETER(datapath);
1882 ASSERT(datapath->nFlows);
1884 // Remove the flow from queue
1885 RemoveEntryList(&f->ListEntry);
1891 * ----------------------------------------------------------------------------
1894 * Find flow from flow table based on flow key.
1895 * Caller should either hold portset handle or should
1896 * have a flowRef in datapath or Acquired datapath.
1899 * Flow pointer if lookup successful.
1900 * NULL if not exists.
1901 * ----------------------------------------------------------------------------
1904 OvsLookupFlow(OVS_DATAPATH *datapath,
1905 const OvsFlowKey *key,
1909 PLIST_ENTRY link, head;
1910 UINT16 offset = key->l2.offset;
1911 UINT16 size = key->l2.keyLen;
1914 ASSERT(key->tunKey.dst || offset == sizeof (OvsIPv4TunnelKey));
1915 ASSERT(!key->tunKey.dst || offset == 0);
1917 start = (UINT8 *)key + offset;
1920 *hash = OvsJhashBytes(start, size, 0);
1923 head = &datapath->flowTable[HASH_BUCKET(*hash)];
1925 while (link != head) {
1926 OvsFlow *flow = CONTAINING_RECORD(link, OvsFlow, ListEntry);
1928 if (flow->hash == *hash &&
1929 flow->key.l2.val == key->l2.val &&
1930 FlowEqual((UINT64 *)((uint8 *)&flow->key + offset),
1931 (UINT64 *)start, size)) {
1941 * ----------------------------------------------------------------------------
1943 * Calculate the hash for the given flow key.
1944 * ----------------------------------------------------------------------------
1947 OvsHashFlow(const OvsFlowKey *key)
1949 UINT16 offset = key->l2.offset;
1950 UINT16 size = key->l2.keyLen;
1953 ASSERT(key->tunKey.dst || offset == sizeof (OvsIPv4TunnelKey));
1954 ASSERT(!key->tunKey.dst || offset == 0);
1955 start = (UINT8 *)key + offset;
1956 return OvsJhashBytes(start, size, 0);
1961 * ----------------------------------------------------------------------------
1963 * Free a flow and its actions.
1964 * ----------------------------------------------------------------------------
1967 FreeFlow(OvsFlow *flow)
1970 OvsFreeMemory(flow);
1974 OvsDoDumpFlows(OvsFlowDumpInput *dumpInput,
1975 OvsFlowDumpOutput *dumpOutput,
1979 OVS_DATAPATH *datapath = NULL;
1981 PLIST_ENTRY node, head;
1983 UINT32 rowIndex, columnIndex;
1984 LOCK_STATE_EX dpLockState;
1985 NTSTATUS status = STATUS_SUCCESS;
1986 BOOLEAN findNextNonEmpty = FALSE;
1988 dpNo = dumpInput->dpNo;
1989 NdisAcquireSpinLock(gOvsCtrlLock);
1990 if (gOvsSwitchContext == NULL ||
1991 gOvsSwitchContext->dpNo != dpNo) {
1992 status = STATUS_INVALID_PARAMETER;
1996 rowIndex = dumpInput->position[0];
1997 if (rowIndex >= OVS_FLOW_TABLE_SIZE) {
1999 *replyLen = sizeof(*dumpOutput);
2003 columnIndex = dumpInput->position[1];
2005 datapath = &gOvsSwitchContext->datapath;
2007 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
2008 OvsAcquireDatapathRead(datapath, &dpLockState, TRUE);
2010 head = &datapath->flowTable[rowIndex];
2013 while (column < columnIndex) {
2022 findNextNonEmpty = TRUE;
2026 if (findNextNonEmpty) {
2027 while (head == node) {
2028 if (++rowIndex >= OVS_FLOW_TABLE_SIZE) {
2032 head = &datapath->flowTable[rowIndex];
2037 ASSERT(node != head);
2038 ASSERT(rowIndex < OVS_FLOW_TABLE_SIZE);
2040 flow = CONTAINING_RECORD(node, OvsFlow, ListEntry);
2041 status = ReportFlowInfo(flow, dumpInput->getFlags, &dumpOutput->flow);
2043 if (status == STATUS_BUFFER_TOO_SMALL) {
2044 dumpOutput->n = sizeof(OvsFlowDumpOutput) + flow->actionsLen;
2045 *replyLen = sizeof(*dumpOutput);
2047 dumpOutput->n = 1; //one flow reported.
2048 *replyLen = sizeof(*dumpOutput) + dumpOutput->flow.actionsLen;
2051 dumpOutput->position[0] = rowIndex;
2052 dumpOutput->position[1] = ++columnIndex;
2055 OvsReleaseDatapath(datapath, &dpLockState);
2058 NdisReleaseSpinLock(gOvsCtrlLock);
2063 OvsDumpFlowIoctl(PVOID inputBuffer,
2066 UINT32 outputLength,
2069 OvsFlowDumpOutput *dumpOutput = (OvsFlowDumpOutput *)outputBuffer;
2070 OvsFlowDumpInput *dumpInput = (OvsFlowDumpInput *)inputBuffer;
2072 if (inputBuffer == NULL || outputBuffer == NULL) {
2073 return STATUS_INVALID_PARAMETER;
2076 if ((inputLength != sizeof(OvsFlowDumpInput))
2077 || (outputLength != sizeof *dumpOutput + dumpInput->actionsLen)) {
2078 return STATUS_INFO_LENGTH_MISMATCH;
2081 return OvsDoDumpFlows(dumpInput, dumpOutput, replyLen);
2085 ReportFlowInfo(OvsFlow *flow,
2089 NTSTATUS status = STATUS_SUCCESS;
2091 if (getFlags & FLOW_GET_KEY) {
2092 // always copy the tunnel key part
2093 RtlCopyMemory(&info->key, &flow->key,
2094 flow->key.l2.keyLen + flow->key.l2.offset);
2097 if (getFlags & FLOW_GET_STATS) {
2098 OvsFlowStats *stats = &info->stats;
2099 stats->packetCount = flow->packetCount;
2100 stats->byteCount = flow->byteCount;
2101 stats->used = (UINT32)flow->used;
2102 stats->tcpFlags = flow->tcpFlags;
2105 if (getFlags & FLOW_GET_ACTIONS) {
2106 if (flow->actionsLen == 0) {
2107 info->actionsLen = 0;
2109 info->actions = flow->actions;
2110 info->actionsLen = flow->actionsLen;
2118 OvsPutFlowIoctl(PVOID inputBuffer,
2120 struct OvsFlowStats *stats)
2122 NTSTATUS status = STATUS_SUCCESS;
2123 OVS_DATAPATH *datapath = NULL;
2127 LOCK_STATE_EX dpLockState;
2129 if ((inputLength < sizeof(OvsFlowPut)) || (inputBuffer == NULL)) {
2130 return STATUS_INFO_LENGTH_MISMATCH;
2133 put = (OvsFlowPut *)inputBuffer;
2134 if (put->actionsLen > 0) {
2135 actionsLen = put->actionsLen;
2141 NdisAcquireSpinLock(gOvsCtrlLock);
2142 if (gOvsSwitchContext == NULL ||
2143 gOvsSwitchContext->dpNo != dpNo) {
2144 status = STATUS_INVALID_PARAMETER;
2148 datapath = &gOvsSwitchContext->datapath;
2150 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
2151 OvsAcquireDatapathWrite(datapath, &dpLockState, TRUE);
2152 status = HandleFlowPut(put, datapath, stats);
2153 OvsReleaseDatapath(datapath, &dpLockState);
2156 NdisReleaseSpinLock(gOvsCtrlLock);
2161 /* Handles flow add, modify as well as delete */
2163 HandleFlowPut(OvsFlowPut *put,
2164 OVS_DATAPATH *datapath,
2165 struct OvsFlowStats *stats)
2167 BOOLEAN mayCreate, mayModify, mayDelete;
2168 OvsFlow *KernelFlow;
2170 NTSTATUS status = STATUS_SUCCESS;
2172 mayCreate = (put->flags & OVSWIN_FLOW_PUT_CREATE) != 0;
2173 mayModify = (put->flags & OVSWIN_FLOW_PUT_MODIFY) != 0;
2174 mayDelete = (put->flags & OVSWIN_FLOW_PUT_DELETE) != 0;
2176 if ((mayCreate || mayModify) == mayDelete) {
2177 return STATUS_INVALID_PARAMETER;
2180 KernelFlow = OvsLookupFlow(datapath, &put->key, &hash, FALSE);
2183 return STATUS_INVALID_PARAMETER;
2186 status = OvsPrepareFlow(&KernelFlow, put, hash);
2187 if (status != STATUS_SUCCESS) {
2188 FreeFlow(KernelFlow);
2189 return STATUS_UNSUCCESSFUL;
2192 status = AddFlow(datapath, KernelFlow);
2193 if (status != STATUS_SUCCESS) {
2194 FreeFlow(KernelFlow);
2195 return STATUS_UNSUCCESSFUL;
2198 /* Validate the flow addition */
2201 OvsFlow *flow = OvsLookupFlow(datapath, &put->key, &newHash,
2204 ASSERT(newHash == hash);
2205 if (!flow || newHash != hash) {
2206 return STATUS_UNSUCCESSFUL;
2210 stats->packetCount = KernelFlow->packetCount;
2211 stats->byteCount = KernelFlow->byteCount;
2212 stats->tcpFlags = KernelFlow->tcpFlags;
2213 stats->used = (UINT32)KernelFlow->used;
2217 status = OvsPrepareFlow(&newFlow, put, hash);
2218 if (status != STATUS_SUCCESS) {
2219 return STATUS_UNSUCCESSFUL;
2222 KernelFlow = OvsLookupFlow(datapath, &put->key, &hash, TRUE);
2224 if ((put->flags & OVSWIN_FLOW_PUT_CLEAR) == 0) {
2225 newFlow->packetCount = KernelFlow->packetCount;
2226 newFlow->byteCount = KernelFlow->byteCount;
2227 newFlow->tcpFlags = KernelFlow->tcpFlags;
2229 RemoveFlow(datapath, &KernelFlow);
2231 if ((put->flags & OVSWIN_FLOW_PUT_CLEAR) == 0) {
2232 newFlow->packetCount = stats->packetCount;
2233 newFlow->byteCount = stats->byteCount;
2234 newFlow->tcpFlags = stats->tcpFlags;
2237 status = AddFlow(datapath, newFlow);
2238 ASSERT(status == STATUS_SUCCESS);
2240 /* Validate the flow addition */
2243 OvsFlow *testflow = OvsLookupFlow(datapath, &put->key,
2246 ASSERT(newHash == hash);
2247 if (!testflow || newHash != hash) {
2249 return STATUS_UNSUCCESSFUL;
2255 RemoveFlow(datapath, &KernelFlow);
2258 return STATUS_UNSUCCESSFUL;
2262 return STATUS_SUCCESS;
2266 OvsPrepareFlow(OvsFlow **flow,
2267 const OvsFlowPut *put,
2270 OvsFlow *localFlow = *flow;
2271 NTSTATUS status = STATUS_SUCCESS;
2275 OvsAllocateMemory(sizeof(OvsFlow) + put->actionsLen);
2276 if (localFlow == NULL) {
2277 status = STATUS_NO_MEMORY;
2281 localFlow->key = put->key;
2282 localFlow->actionsLen = put->actionsLen;
2283 if (put->actionsLen) {
2284 NdisMoveMemory((PUCHAR)localFlow->actions, put->actions,
2287 localFlow->userActionsLen = 0; // 0 indicate no conversion is made
2288 localFlow->used = 0;
2289 localFlow->packetCount = 0;
2290 localFlow->byteCount = 0;
2291 localFlow->tcpFlags = 0;
2292 localFlow->hash = hash;
2299 OvsGetFlowIoctl(PVOID inputBuffer,
2302 NTSTATUS status = STATUS_SUCCESS;
2303 OVS_DATAPATH *datapath = NULL;
2305 UINT32 getFlags, getActionsLen;
2306 OvsFlowGetInput *getInput;
2307 OvsFlowGetOutput *getOutput;
2310 LOCK_STATE_EX dpLockState;
2312 getInput = (OvsFlowGetInput *) inputBuffer;
2313 getFlags = getInput->getFlags;
2314 getActionsLen = getInput->actionsLen;
2316 if (outputBuffer == NULL) {
2317 return STATUS_INFO_LENGTH_MISMATCH;
2320 dpNo = getInput->dpNo;
2321 NdisAcquireSpinLock(gOvsCtrlLock);
2322 if (gOvsSwitchContext == NULL ||
2323 gOvsSwitchContext->dpNo != dpNo) {
2324 status = STATUS_INVALID_PARAMETER;
2328 datapath = &gOvsSwitchContext->datapath;
2330 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
2331 OvsAcquireDatapathRead(datapath, &dpLockState, TRUE);
2332 flow = OvsLookupFlow(datapath, &getInput->key, &hash, FALSE);
2334 status = STATUS_INVALID_PARAMETER;
2338 getOutput = (OvsFlowGetOutput *)outputBuffer;
2339 ReportFlowInfo(flow, getFlags, &getOutput->info);
2342 OvsReleaseDatapath(datapath, &dpLockState);
2344 NdisReleaseSpinLock(gOvsCtrlLock);
2349 OvsFlushFlowIoctl(UINT32 dpNo)
2351 NTSTATUS status = STATUS_SUCCESS;
2352 OVS_DATAPATH *datapath = NULL;
2353 LOCK_STATE_EX dpLockState;
2355 NdisAcquireSpinLock(gOvsCtrlLock);
2356 if (gOvsSwitchContext == NULL ||
2357 gOvsSwitchContext->dpNo != dpNo) {
2358 status = STATUS_INVALID_PARAMETER;
2362 datapath = &gOvsSwitchContext->datapath;
2364 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
2365 OvsAcquireDatapathWrite(datapath, &dpLockState, TRUE);
2366 DeleteAllFlows(datapath);
2367 OvsReleaseDatapath(datapath, &dpLockState);
2370 NdisReleaseSpinLock(gOvsCtrlLock);
2375 OvsFlowKeyAttrSize(void)
2377 return NlAttrTotalSize(4) /* OVS_KEY_ATTR_PRIORITY */
2378 + NlAttrTotalSize(0) /* OVS_KEY_ATTR_TUNNEL */
2379 + OvsTunKeyAttrSize()
2380 + NlAttrTotalSize(4) /* OVS_KEY_ATTR_IN_PORT */
2381 + NlAttrTotalSize(4) /* OVS_KEY_ATTR_SKB_MARK */
2382 + NlAttrTotalSize(4) /* OVS_KEY_ATTR_DP_HASH */
2383 + NlAttrTotalSize(4) /* OVS_KEY_ATTR_RECIRC_ID */
2384 + NlAttrTotalSize(12) /* OVS_KEY_ATTR_ETHERNET */
2385 + NlAttrTotalSize(2) /* OVS_KEY_ATTR_ETHERTYPE */
2386 + NlAttrTotalSize(4) /* OVS_KEY_ATTR_VLAN */
2387 + NlAttrTotalSize(0) /* OVS_KEY_ATTR_ENCAP */
2388 + NlAttrTotalSize(2) /* OVS_KEY_ATTR_ETHERTYPE */
2389 + NlAttrTotalSize(40) /* OVS_KEY_ATTR_IPV6 */
2390 + NlAttrTotalSize(2) /* OVS_KEY_ATTR_ICMPV6 */
2391 + NlAttrTotalSize(28); /* OVS_KEY_ATTR_ND */
2395 OvsTunKeyAttrSize(void)
2397 /* Whenever adding new OVS_TUNNEL_KEY_ FIELDS, we should consider
2398 * updating this function.
2400 return NlAttrTotalSize(8) /* OVS_TUNNEL_KEY_ATTR_ID */
2401 + NlAttrTotalSize(4) /* OVS_TUNNEL_KEY_ATTR_IPV4_SRC */
2402 + NlAttrTotalSize(4) /* OVS_TUNNEL_KEY_ATTR_IPV4_DST */
2403 + NlAttrTotalSize(1) /* OVS_TUNNEL_KEY_ATTR_TOS */
2404 + NlAttrTotalSize(1) /* OVS_TUNNEL_KEY_ATTR_TTL */
2405 + NlAttrTotalSize(0) /* OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT */
2406 + NlAttrTotalSize(0) /* OVS_TUNNEL_KEY_ATTR_CSUM */
2407 + NlAttrTotalSize(0) /* OVS_TUNNEL_KEY_ATTR_OAM */
2408 + NlAttrTotalSize(256) /* OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS */
2409 + NlAttrTotalSize(2) /* OVS_TUNNEL_KEY_ATTR_TP_SRC */
2410 + NlAttrTotalSize(2); /* OVS_TUNNEL_KEY_ATTR_TP_DST */
2413 #pragma warning( pop )