2 * Copyright (c) 2014 VMware, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
22 #include "PacketParser.h"
28 #define OVS_DBG_MOD OVS_DBG_FLOW
31 #pragma warning( push )
32 #pragma warning( disable:4127 )
34 extern PNDIS_SPIN_LOCK gOvsCtrlLock;
35 extern POVS_SWITCH_CONTEXT gOvsSwitchContext;
36 extern UINT64 ovsTimeIncrementPerTick;
38 static NTSTATUS ReportFlowInfo(OvsFlow *flow, UINT32 getFlags,
40 static NTSTATUS HandleFlowPut(OvsFlowPut *put,
41 OVS_DATAPATH *datapath,
42 struct OvsFlowStats *stats);
43 static NTSTATUS OvsPrepareFlow(OvsFlow **flow, const OvsFlowPut *put,
45 static VOID RemoveFlow(OVS_DATAPATH *datapath, OvsFlow **flow);
46 static VOID DeleteAllFlows(OVS_DATAPATH *datapath);
47 static NTSTATUS AddFlow(OVS_DATAPATH *datapath, OvsFlow *flow);
48 static VOID FreeFlow(OvsFlow *flow);
49 static VOID __inline *GetStartAddrNBL(const NET_BUFFER_LIST *_pNB);
50 static NTSTATUS _MapNlToFlowPut(POVS_MESSAGE msgIn, PNL_ATTR keyAttr,
52 PNL_ATTR flowAttrClear,
53 OvsFlowPut *mappedFlow);
54 static VOID _MapKeyAttrToFlowPut(PNL_ATTR *keyAttrs,
55 PNL_ATTR *tunnelAttrs,
58 static VOID _MapTunAttrToFlowPut(PNL_ATTR *keyAttrs,
59 PNL_ATTR *tunnelAttrs,
61 static VOID _MapNlToFlowPutFlags(PGENL_MSG_HDR genlMsgHdr,
62 PNL_ATTR flowAttrClear,
63 OvsFlowPut *mappedFlow);
65 static NTSTATUS _FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
67 static NTSTATUS _FlowNlDumpCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
69 static NTSTATUS _MapFlowInfoToNl(PNL_BUFFER nlBuf,
70 OvsFlowInfo *flowInfo);
71 static NTSTATUS _MapFlowKeyToNlKey(PNL_BUFFER nlBuf,
73 static NTSTATUS _MapFlowTunKeyToNlKey(PNL_BUFFER nlBuf,
74 OvsIPv4TunnelKey *tunKey);
75 static NTSTATUS _MapFlowStatsToNlStats(PNL_BUFFER nlBuf,
76 OvsFlowStats *flowStats);
77 static NTSTATUS _MapFlowActionToNlAction(PNL_BUFFER nlBuf,
81 static NTSTATUS _MapFlowIpv4KeyToNlKey(PNL_BUFFER nlBuf,
82 IpKey *ipv4FlowPutKey);
83 static NTSTATUS _MapFlowIpv6KeyToNlKey(PNL_BUFFER nlBuf,
84 Ipv6Key *ipv6FlowPutKey,
85 Icmp6Key *ipv6FlowPutIcmpKey);
86 static NTSTATUS _MapFlowArpKeyToNlKey(PNL_BUFFER nlBuf,
87 ArpKey *arpFlowPutKey);
89 static NTSTATUS OvsDoDumpFlows(OvsFlowDumpInput *dumpInput,
90 OvsFlowDumpOutput *dumpOutput,
94 #define OVS_FLOW_TABLE_SIZE 2048
95 #define OVS_FLOW_TABLE_MASK (OVS_FLOW_TABLE_SIZE -1)
96 #define HASH_BUCKET(hash) ((hash) & OVS_FLOW_TABLE_MASK)
98 /* Flow family related netlink policies */
100 /* For Parsing attributes in FLOW_* commands */
101 static const NL_POLICY nlFlowPolicy[] = {
102 [OVS_FLOW_ATTR_KEY] = {.type = NL_A_NESTED, .optional = FALSE},
103 [OVS_FLOW_ATTR_MASK] = {.type = NL_A_NESTED, .optional = TRUE},
104 [OVS_FLOW_ATTR_ACTIONS] = {.type = NL_A_NESTED, .optional = TRUE},
105 [OVS_FLOW_ATTR_STATS] = {.type = NL_A_UNSPEC,
106 .minLen = sizeof(struct ovs_flow_stats),
107 .maxLen = sizeof(struct ovs_flow_stats),
109 [OVS_FLOW_ATTR_TCP_FLAGS] = {NL_A_U8, .optional = TRUE},
110 [OVS_FLOW_ATTR_USED] = {NL_A_U64, .optional = TRUE}
113 /* For Parsing nested OVS_FLOW_ATTR_KEY attributes.
114 * Some of the attributes like OVS_KEY_ATTR_RECIRC_ID
115 * & OVS_KEY_ATTR_MPLS are not supported yet. */
117 static const NL_POLICY nlFlowKeyPolicy[] = {
118 [OVS_KEY_ATTR_ENCAP] = {.type = NL_A_VAR_LEN, .optional = TRUE},
119 [OVS_KEY_ATTR_PRIORITY] = {.type = NL_A_UNSPEC, .minLen = 4,
120 .maxLen = 4, .optional = TRUE},
121 [OVS_KEY_ATTR_IN_PORT] = {.type = NL_A_UNSPEC, .minLen = 4,
122 .maxLen = 4, .optional = FALSE},
123 [OVS_KEY_ATTR_ETHERNET] = {.type = NL_A_UNSPEC,
124 .minLen = sizeof(struct ovs_key_ethernet),
125 .maxLen = sizeof(struct ovs_key_ethernet),
127 [OVS_KEY_ATTR_VLAN] = {.type = NL_A_UNSPEC, .minLen = 2,
128 .maxLen = 2, .optional = TRUE},
129 [OVS_KEY_ATTR_ETHERTYPE] = {.type = NL_A_UNSPEC, .minLen = 2,
130 .maxLen = 2, .optional = TRUE},
131 [OVS_KEY_ATTR_IPV4] = {.type = NL_A_UNSPEC,
132 .minLen = sizeof(struct ovs_key_ipv4),
133 .maxLen = sizeof(struct ovs_key_ipv4),
135 [OVS_KEY_ATTR_IPV6] = {.type = NL_A_UNSPEC,
136 .minLen = sizeof(struct ovs_key_ipv6),
137 .maxLen = sizeof(struct ovs_key_ipv6),
139 [OVS_KEY_ATTR_TCP] = {.type = NL_A_UNSPEC,
140 .minLen = sizeof(struct ovs_key_tcp),
141 .maxLen = sizeof(struct ovs_key_tcp),
143 [OVS_KEY_ATTR_UDP] = {.type = NL_A_UNSPEC,
144 .minLen = sizeof(struct ovs_key_udp),
145 .maxLen = sizeof(struct ovs_key_udp),
147 [OVS_KEY_ATTR_ICMP] = {.type = NL_A_UNSPEC,
148 .minLen = sizeof(struct ovs_key_icmp),
149 .maxLen = sizeof(struct ovs_key_icmp),
151 [OVS_KEY_ATTR_ICMPV6] = {.type = NL_A_UNSPEC,
152 .minLen = sizeof(struct ovs_key_icmpv6),
153 .maxLen = sizeof(struct ovs_key_icmpv6),
155 [OVS_KEY_ATTR_ARP] = {.type = NL_A_UNSPEC,
156 .minLen = sizeof(struct ovs_key_arp),
157 .maxLen = sizeof(struct ovs_key_arp),
159 [OVS_KEY_ATTR_ND] = {.type = NL_A_UNSPEC,
160 .minLen = sizeof(struct ovs_key_nd),
161 .maxLen = sizeof(struct ovs_key_nd),
163 [OVS_KEY_ATTR_SKB_MARK] = {.type = NL_A_UNSPEC, .minLen = 4,
164 .maxLen = 4, .optional = TRUE},
165 [OVS_KEY_ATTR_TUNNEL] = {.type = NL_A_VAR_LEN, .optional = TRUE},
166 [OVS_KEY_ATTR_SCTP] = {.type = NL_A_UNSPEC,
167 .minLen = sizeof(struct ovs_key_sctp),
168 .maxLen = sizeof(struct ovs_key_sctp),
170 [OVS_KEY_ATTR_TCP_FLAGS] = {.type = NL_A_UNSPEC,
171 .minLen = 2, .maxLen = 2,
173 [OVS_KEY_ATTR_DP_HASH] = {.type = NL_A_UNSPEC, .minLen = 4,
174 .maxLen = 4, .optional = TRUE},
175 [OVS_KEY_ATTR_RECIRC_ID] = {.type = NL_A_UNSPEC, .minLen = 4,
176 .maxLen = 4, .optional = TRUE},
177 [OVS_KEY_ATTR_MPLS] = {.type = NL_A_VAR_LEN, .optional = TRUE}
180 /* For Parsing nested OVS_KEY_ATTR_TUNNEL attributes */
181 static const NL_POLICY nlFlowTunnelKeyPolicy[] = {
182 [OVS_TUNNEL_KEY_ATTR_ID] = {.type = NL_A_UNSPEC, .minLen = 8,
183 .maxLen = 8, .optional = TRUE},
184 [OVS_TUNNEL_KEY_ATTR_IPV4_SRC] = {.type = NL_A_UNSPEC, .minLen = 4,
185 .maxLen = 4, .optional = TRUE},
186 [OVS_TUNNEL_KEY_ATTR_IPV4_DST] = {.type = NL_A_UNSPEC, .minLen = 4 ,
187 .maxLen = 4, .optional = FALSE},
188 [OVS_TUNNEL_KEY_ATTR_TOS] = {.type = NL_A_UNSPEC, .minLen = 1,
189 .maxLen = 1, .optional = TRUE},
190 [OVS_TUNNEL_KEY_ATTR_TTL] = {.type = NL_A_UNSPEC, .minLen = 1,
191 .maxLen = 1, .optional = TRUE},
192 [OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT] = {.type = NL_A_UNSPEC, .minLen = 0,
193 .maxLen = 0, .optional = TRUE},
194 [OVS_TUNNEL_KEY_ATTR_CSUM] = {.type = NL_A_UNSPEC, .minLen = 0,
195 .maxLen = 0, .optional = TRUE},
196 [OVS_TUNNEL_KEY_ATTR_OAM] = {.type = NL_A_UNSPEC, .minLen = 0,
197 .maxLen = 0, .optional = TRUE},
198 [OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS] = {.type = NL_A_VAR_LEN,
202 /* For Parsing nested OVS_FLOW_ATTR_ACTIONS attributes */
203 static const NL_POLICY nlFlowActionPolicy[] = {
204 [OVS_ACTION_ATTR_OUTPUT] = {.type = NL_A_UNSPEC, .minLen = sizeof(UINT32),
205 .maxLen = sizeof(UINT32), .optional = TRUE},
206 [OVS_ACTION_ATTR_USERSPACE] = {.type = NL_A_VAR_LEN, .optional = TRUE},
207 [OVS_ACTION_ATTR_PUSH_VLAN] = {.type = NL_A_UNSPEC,
209 sizeof(struct ovs_action_push_vlan),
211 sizeof(struct ovs_action_push_vlan),
213 [OVS_ACTION_ATTR_POP_VLAN] = {.type = NL_A_UNSPEC, .optional = TRUE},
214 [OVS_ACTION_ATTR_PUSH_MPLS] = {.type = NL_A_UNSPEC,
216 sizeof(struct ovs_action_push_mpls),
218 sizeof(struct ovs_action_push_mpls),
220 [OVS_ACTION_ATTR_POP_MPLS] = {.type = NL_A_UNSPEC,
221 .minLen = sizeof(UINT16),
222 .maxLen = sizeof(UINT16),
224 [OVS_ACTION_ATTR_RECIRC] = {.type = NL_A_UNSPEC,
225 .minLen = sizeof(UINT32),
226 .maxLen = sizeof(UINT32),
228 [OVS_ACTION_ATTR_HASH] = {.type = NL_A_UNSPEC,
229 .minLen = sizeof(struct ovs_action_hash),
230 .maxLen = sizeof(struct ovs_action_hash),
232 [OVS_ACTION_ATTR_SET] = {.type = NL_A_VAR_LEN, .optional = TRUE},
233 [OVS_ACTION_ATTR_SAMPLE] = {.type = NL_A_VAR_LEN, .optional = TRUE}
237 *----------------------------------------------------------------------------
238 * Netlink interface for flow commands.
239 *----------------------------------------------------------------------------
243 *----------------------------------------------------------------------------
244 * OvsFlowNewCmdHandler --
245 * Handler for OVS_FLOW_CMD_NEW/SET/DEL command.
246 * It also handles FLUSH case (DEL w/o any key in input)
247 *----------------------------------------------------------------------------
250 OvsFlowNlCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
253 NTSTATUS rc = STATUS_SUCCESS;
254 POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;
255 POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer;
256 PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
257 PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
258 POVS_HDR ovsHdr = &(msgIn->ovsHdr);
259 PNL_ATTR nlAttrs[__OVS_FLOW_ATTR_MAX];
260 UINT32 attrOffset = NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN;
261 OvsFlowPut mappedFlow;
263 struct ovs_flow_stats replyStats;
264 NL_ERROR nlError = NL_ERROR_SUCCESS;
268 RtlZeroMemory(&mappedFlow, sizeof(OvsFlowPut));
269 RtlZeroMemory(&stats, sizeof(stats));
270 RtlZeroMemory(&replyStats, sizeof(replyStats));
272 if (!(usrParamsCtx->outputBuffer)) {
273 /* No output buffer */
274 rc = STATUS_INVALID_BUFFER_SIZE;
278 /* Get all the top level Flow attributes */
279 if ((NlAttrParse(nlMsgHdr, attrOffset, NlMsgAttrsLen(nlMsgHdr),
280 nlFlowPolicy, nlAttrs, ARRAY_SIZE(nlAttrs)))
282 OVS_LOG_ERROR("Attr Parsing failed for msg: %p",
284 rc = STATUS_INVALID_PARAMETER;
288 /* FLOW_DEL command w/o any key input is a flush case. */
289 if ((genlMsgHdr->cmd == OVS_FLOW_CMD_DEL) &&
290 (!(nlAttrs[OVS_FLOW_ATTR_KEY]))) {
292 rc = OvsFlushFlowIoctl(ovsHdr->dp_ifindex);
294 if (rc == STATUS_SUCCESS) {
295 /* XXX: refactor this code. */
296 /* So far so good. Prepare the reply for userspace */
297 NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
298 usrParamsCtx->outputLength);
300 /* Prepare nl Msg headers */
301 rc = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,
302 nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
303 genlMsgHdr->cmd, OVS_FLOW_VERSION,
306 if (rc == STATUS_SUCCESS) {
307 *replyLen = msgOut->nlMsg.nlmsgLen;
314 if ((rc = _MapNlToFlowPut(msgIn, nlAttrs[OVS_FLOW_ATTR_KEY],
315 nlAttrs[OVS_FLOW_ATTR_ACTIONS], nlAttrs[OVS_FLOW_ATTR_CLEAR],
318 OVS_LOG_ERROR("Conversion to OvsFlowPut failed");
322 rc = OvsPutFlowIoctl(&mappedFlow, sizeof (struct OvsFlowPut),
324 if (rc != STATUS_SUCCESS) {
325 OVS_LOG_ERROR("OvsFlowPut failed.");
329 replyStats.n_packets = stats.packetCount;
330 replyStats.n_bytes = stats.byteCount;
332 /* So far so good. Prepare the reply for userspace */
333 NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
334 usrParamsCtx->outputLength);
336 /* Prepare nl Msg headers */
337 rc = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,
338 nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
339 genlMsgHdr->cmd, OVS_FLOW_VERSION,
343 /* Append OVS_FLOW_ATTR_STATS attribute */
344 if (!NlMsgPutTailUnspec(&nlBuf, OVS_FLOW_ATTR_STATS,
345 (PCHAR)(&replyStats), sizeof(replyStats))) {
346 OVS_LOG_ERROR("Adding OVS_FLOW_ATTR_STATS attribute failed.");
347 rc = STATUS_INVALID_BUFFER_SIZE;
351 msgOut->nlMsg.nlmsgLen = NLMSG_ALIGN(NlBufSize(&nlBuf));
352 *replyLen = msgOut->nlMsg.nlmsgLen;
356 if ((nlError != NL_ERROR_SUCCESS) &&
357 (usrParamsCtx->outputBuffer)) {
358 POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
359 usrParamsCtx->outputBuffer;
360 BuildErrorMsg(msgIn, msgError, nlError);
361 *replyLen = msgError->nlMsg.nlmsgLen;
369 *----------------------------------------------------------------------------
370 * OvsFlowNlGetCmdHandler --
371 * Handler for OVS_FLOW_CMD_GET/DUMP commands.
372 *----------------------------------------------------------------------------
375 OvsFlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
378 NTSTATUS rc = STATUS_SUCCESS;
379 NL_ERROR nlError = NL_ERROR_SUCCESS;
380 POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;
381 POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer;
382 PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
383 PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
384 POVS_HDR ovsHdr = &(msgIn->ovsHdr);
388 if (!(usrParamsCtx->outputBuffer)) {
389 /* No output buffer */
390 rc = STATUS_INVALID_BUFFER_SIZE;
394 if (usrParamsCtx->devOp == OVS_TRANSACTION_DEV_OP) {
395 rc = _FlowNlGetCmdHandler(usrParamsCtx, replyLen);
397 rc = _FlowNlDumpCmdHandler(usrParamsCtx, replyLen);
400 if ((nlError != NL_ERROR_SUCCESS) &&
401 (usrParamsCtx->outputBuffer)) {
402 POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
403 usrParamsCtx->outputBuffer;
404 BuildErrorMsg(msgIn, msgError, nlError);
405 *replyLen = msgError->nlMsg.nlmsgLen;
410 if (rc == STATUS_SUCCESS) {
411 NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
412 usrParamsCtx->outputLength);
414 /* Prepare nl Msg headers */
415 rc = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,
416 nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
417 genlMsgHdr->cmd, OVS_FLOW_VERSION,
420 if (rc == STATUS_SUCCESS) {
421 *replyLen = msgOut->nlMsg.nlmsgLen;
430 *----------------------------------------------------------------------------
431 * _FlowNlGetCmdHandler --
432 * Handler for OVS_FLOW_CMD_GET command.
433 *----------------------------------------------------------------------------
436 _FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
439 NTSTATUS rc = STATUS_SUCCESS;
440 POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)
441 (usrParamsCtx->ovsInstance);
442 POVS_MESSAGE msgIn = instance->dumpState.ovsMsg;
443 PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
444 POVS_HDR ovsHdr = &(msgIn->ovsHdr);
445 PNL_MSG_HDR nlMsgOutHdr = NULL;
446 UINT32 attrOffset = NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN;
447 PNL_ATTR nlAttrs[__OVS_FLOW_ATTR_MAX];
449 OvsFlowGetInput getInput;
450 OvsFlowGetOutput getOutput;
452 PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX];
453 PNL_ATTR tunnelAttrs[__OVS_TUNNEL_KEY_ATTR_MAX];
455 NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
456 usrParamsCtx->outputLength);
457 RtlZeroMemory(&getInput, sizeof(OvsFlowGetInput));
458 RtlZeroMemory(&getOutput, sizeof(OvsFlowGetOutput));
459 UINT32 keyAttrOffset = 0;
460 UINT32 tunnelKeyAttrOffset = 0;
462 if (usrParamsCtx->inputLength > usrParamsCtx->outputLength) {
463 /* Should not be the case.
464 * We'll be copying the flow keys back from
465 * input buffer to output buffer. */
466 rc = STATUS_INVALID_PARAMETER;
467 OVS_LOG_ERROR("inputLength: %d GREATER THEN outputLength: %d",
468 usrParamsCtx->inputLength, usrParamsCtx->outputLength);
472 /* Get all the top level Flow attributes */
473 if ((NlAttrParse(nlMsgHdr, attrOffset, NlMsgAttrsLen(nlMsgHdr),
474 nlFlowPolicy, nlAttrs, ARRAY_SIZE(nlAttrs)))
476 OVS_LOG_ERROR("Attr Parsing failed for msg: %p",
478 rc = STATUS_INVALID_PARAMETER;
482 keyAttrOffset = (UINT32)((PCHAR) nlAttrs[OVS_FLOW_ATTR_KEY] -
485 /* Get flow keys attributes */
486 if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset,
487 NlAttrLen(nlAttrs[OVS_FLOW_ATTR_KEY]),
488 nlFlowKeyPolicy, keyAttrs, ARRAY_SIZE(keyAttrs)))
490 OVS_LOG_ERROR("Key Attr Parsing failed for msg: %p",
492 rc = STATUS_INVALID_PARAMETER;
496 if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
497 tunnelKeyAttrOffset = (UINT32)((PCHAR)
498 (keyAttrs[OVS_KEY_ATTR_TUNNEL])
501 /* Get tunnel keys attributes */
502 if ((NlAttrParseNested(nlMsgHdr, tunnelKeyAttrOffset,
503 NlAttrLen(keyAttrs[OVS_KEY_ATTR_TUNNEL]),
504 nlFlowTunnelKeyPolicy,
505 tunnelAttrs, ARRAY_SIZE(tunnelAttrs)))
507 OVS_LOG_ERROR("Tunnel key Attr Parsing failed for msg: %p",
509 rc = STATUS_INVALID_PARAMETER;
514 _MapKeyAttrToFlowPut(keyAttrs, tunnelAttrs,
517 getInput.dpNo = ovsHdr->dp_ifindex;
518 getInput.getFlags = FLOW_GET_STATS | FLOW_GET_ACTIONS;
520 /* 4th argument is a no op.
521 * We are keeping this argument to be compatible
522 * with our dpif-windows based interface. */
523 rc = OvsGetFlowIoctl(&getInput, &getOutput);
524 if (rc != STATUS_SUCCESS) {
525 OVS_LOG_ERROR("OvsGetFlowIoctl failed.");
529 /* Lets prepare the reply. */
530 nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, 0, 0));
532 /* Input already has all the attributes for the flow key.
533 * Lets copy the values back. */
534 RtlCopyMemory(usrParamsCtx->outputBuffer, usrParamsCtx->inputBuffer,
535 usrParamsCtx->inputLength);
537 rc = _MapFlowStatsToNlStats(&nlBuf, &((getOutput.info).stats));
538 if (rc != STATUS_SUCCESS) {
539 OVS_LOG_ERROR("_OvsFlowMapFlowKeyToNlStats failed.");
543 rc = _MapFlowActionToNlAction(&nlBuf, ((getOutput.info).actionsLen),
544 getOutput.info.actions);
545 if (rc != STATUS_SUCCESS) {
546 OVS_LOG_ERROR("_MapFlowActionToNlAction failed.");
550 NlMsgSetSize(nlMsgOutHdr, NlBufSize(&nlBuf));
551 NlMsgAlignSize(nlMsgOutHdr);
552 *replyLen += NlMsgSize(nlMsgOutHdr);
559 *----------------------------------------------------------------------------
560 * _FlowNlDumpCmdHandler --
561 * Handler for OVS_FLOW_CMD_GET command.
562 *----------------------------------------------------------------------------
565 _FlowNlDumpCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
568 NTSTATUS rc = STATUS_SUCCESS;
569 UINT32 temp = 0; /* To keep compiler happy for calling OvsDoDumpFlows */
571 POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)
572 (usrParamsCtx->ovsInstance);
574 if (usrParamsCtx->devOp == OVS_WRITE_DEV_OP) {
576 OvsSetupDumpStart(usrParamsCtx);
580 POVS_MESSAGE msgIn = instance->dumpState.ovsMsg;
581 PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
582 PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
583 POVS_HDR ovsHdr = &(msgIn->ovsHdr);
584 PNL_MSG_HDR nlMsgOutHdr = NULL;
585 UINT32 hdrOffset = 0;
588 OvsFlowDumpOutput dumpOutput;
589 OvsFlowDumpInput dumpInput;
592 NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
593 usrParamsCtx->outputLength);
595 ASSERT(usrParamsCtx->devOp == OVS_READ_DEV_OP);
596 ASSERT(usrParamsCtx->outputLength);
598 RtlZeroMemory(&dumpInput, sizeof(OvsFlowDumpInput));
599 RtlZeroMemory(&dumpOutput, sizeof(OvsFlowDumpOutput));
601 dumpInput.dpNo = ovsHdr->dp_ifindex;
602 dumpInput.getFlags = FLOW_GET_KEY | FLOW_GET_STATS | FLOW_GET_ACTIONS;
604 /* Lets provide as many flows to userspace as possible. */
606 dumpInput.position[0] = instance->dumpState.index[0];
607 dumpInput.position[1] = instance->dumpState.index[1];
609 rc = OvsDoDumpFlows(&dumpInput, &dumpOutput, &temp);
610 if (rc != STATUS_SUCCESS) {
611 OVS_LOG_ERROR("OvsDoDumpFlows failed with rc: %d", rc);
615 /* Done with Dump, send NLMSG_DONE */
616 if (!(dumpOutput.n)) {
617 OVS_LOG_INFO("Dump Done");
619 nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, NlBufSize(&nlBuf), 0));
620 rc = NlFillNlHdr(&nlBuf, NLMSG_DONE, NLM_F_MULTI,
621 nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid);
623 if (rc != STATUS_SUCCESS) {
624 OVS_LOG_ERROR("Unable to prepare DUMP_DONE reply.");
628 NlMsgAlignSize(nlMsgOutHdr);
629 *replyLen += NlMsgSize(nlMsgOutHdr);
631 FreeUserDumpState(instance);
635 hdrOffset = NlBufSize(&nlBuf);
636 nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, hdrOffset, 0));
639 rc = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, NLM_F_MULTI,
640 nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
641 genlMsgHdr->cmd, genlMsgHdr->version,
644 if (rc != STATUS_SUCCESS) {
645 /* Reset rc to success so that we can
646 * send already added messages to user space. */
651 /* Time to add attributes */
652 rc = _MapFlowInfoToNl(&nlBuf, &(dumpOutput.flow));
653 if (rc != STATUS_SUCCESS) {
654 /* Adding the attribute failed, we are out of
655 space in the buffer, remove the appended OVS header */
656 NlMsgSetSize(nlMsgOutHdr,
657 NlMsgSize(nlMsgOutHdr) -
658 sizeof(struct _OVS_MESSAGE));
660 /* Reset rc to success so that we can
661 * send already added messages to user space. */
666 NlMsgSetSize(nlMsgOutHdr, NlBufSize(&nlBuf) - hdrOffset);
667 NlMsgAlignSize(nlMsgOutHdr);
668 *replyLen += NlMsgSize(nlMsgOutHdr);
669 instance->dumpState.index[0] = dumpOutput.position[0];
670 instance->dumpState.index[1] = dumpOutput.position[1];
679 *----------------------------------------------------------------------------
680 * _MapFlowInfoToNl --
681 * Maps OvsFlowInfo to Netlink attributes.
682 *----------------------------------------------------------------------------
685 _MapFlowInfoToNl(PNL_BUFFER nlBuf, OvsFlowInfo *flowInfo)
687 NTSTATUS rc = STATUS_SUCCESS;
689 rc = _MapFlowKeyToNlKey(nlBuf, &(flowInfo->key));
690 if (rc != STATUS_SUCCESS) {
694 rc = _MapFlowStatsToNlStats(nlBuf, &(flowInfo->stats));
695 if (rc != STATUS_SUCCESS) {
699 rc = _MapFlowActionToNlAction(nlBuf, flowInfo->actionsLen,
701 if (rc != STATUS_SUCCESS) {
710 *----------------------------------------------------------------------------
711 * _MapFlowStatsToNlStats --
712 * Maps OvsFlowStats to OVS_FLOW_ATTR_STATS attribute.
713 *----------------------------------------------------------------------------
716 _MapFlowStatsToNlStats(PNL_BUFFER nlBuf, OvsFlowStats *flowStats)
718 NTSTATUS rc = STATUS_SUCCESS;
719 struct ovs_flow_stats replyStats;
721 replyStats.n_packets = flowStats->packetCount;
722 replyStats.n_bytes = flowStats->byteCount;
724 if (!NlMsgPutTailU64(nlBuf, OVS_FLOW_ATTR_USED, flowStats->used)) {
725 rc = STATUS_INVALID_BUFFER_SIZE;
729 if (!NlMsgPutTailUnspec(nlBuf, OVS_FLOW_ATTR_STATS,
730 (PCHAR)(&replyStats),
731 sizeof(struct ovs_flow_stats))) {
732 rc = STATUS_INVALID_BUFFER_SIZE;
736 if (!NlMsgPutTailU8(nlBuf, OVS_FLOW_ATTR_TCP_FLAGS, flowStats->tcpFlags)) {
737 rc = STATUS_INVALID_BUFFER_SIZE;
746 *----------------------------------------------------------------------------
747 * _MapFlowActionToNlAction --
748 * Maps flow actions to OVS_FLOW_ATTR_ACTION attribute.
749 *----------------------------------------------------------------------------
752 _MapFlowActionToNlAction(PNL_BUFFER nlBuf, uint32_t actionsLen,
755 NTSTATUS rc = STATUS_SUCCESS;
758 offset = NlMsgStartNested(nlBuf, OVS_FLOW_ATTR_ACTIONS);
760 /* Starting the nested attribute failed. */
761 rc = STATUS_INVALID_BUFFER_SIZE;
762 goto error_nested_start;
765 if (!NlBufCopyAtTail(nlBuf, (PCHAR)actions, actionsLen)) {
766 /* Adding a nested attribute failed. */
767 rc = STATUS_INVALID_BUFFER_SIZE;
772 NlMsgEndNested(nlBuf, offset);
779 *----------------------------------------------------------------------------
780 * _MapFlowKeyToNlKey --
781 * Maps OvsFlowKey to OVS_FLOW_ATTR_KEY attribute.
782 *----------------------------------------------------------------------------
785 _MapFlowKeyToNlKey(PNL_BUFFER nlBuf, OvsFlowKey *flowKey)
787 NTSTATUS rc = STATUS_SUCCESS;
788 struct ovs_key_ethernet ethKey;
791 offset = NlMsgStartNested(nlBuf, OVS_FLOW_ATTR_KEY);
793 /* Starting the nested attribute failed. */
794 rc = STATUS_UNSUCCESSFUL;
795 goto error_nested_start;
798 /* Ethernet header */
799 RtlCopyMemory(&(ethKey.eth_src), flowKey->l2.dlSrc, ETH_ADDR_LEN);
800 RtlCopyMemory(&(ethKey.eth_dst), flowKey->l2.dlDst, ETH_ADDR_LEN);
802 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ETHERNET,
804 sizeof(struct ovs_key_ethernet))) {
805 rc = STATUS_UNSUCCESSFUL;
809 if (!NlMsgPutTailU32(nlBuf, OVS_KEY_ATTR_IN_PORT,
810 flowKey->l2.inPort)) {
811 rc = STATUS_UNSUCCESSFUL;
815 if (!NlMsgPutTailU16(nlBuf, OVS_KEY_ATTR_ETHERTYPE,
816 htons(flowKey->l2.dlType))) {
817 rc = STATUS_UNSUCCESSFUL;
821 if (flowKey->l2.vlanTci) {
822 if (!NlMsgPutTailU16(nlBuf, OVS_KEY_ATTR_VLAN,
823 flowKey->l2.vlanTci)) {
824 rc = STATUS_UNSUCCESSFUL;
829 /* ==== L3 + L4 ==== */
830 switch (flowKey->l2.dlType) {
831 case ETH_TYPE_IPV4: {
832 IpKey *ipv4FlowPutKey = &(flowKey->ipKey);
833 rc = _MapFlowIpv4KeyToNlKey(nlBuf, ipv4FlowPutKey);
837 case ETH_TYPE_IPV6: {
838 Ipv6Key *ipv6FlowPutKey = &(flowKey->ipv6Key);
839 Icmp6Key *icmpv6FlowPutKey = &(flowKey->icmp6Key);
840 rc = _MapFlowIpv6KeyToNlKey(nlBuf, ipv6FlowPutKey,
846 case ETH_TYPE_RARP: {
847 ArpKey *arpFlowPutKey = &(flowKey->arpKey);
848 rc = _MapFlowArpKeyToNlKey(nlBuf, arpFlowPutKey);
856 if (rc != STATUS_SUCCESS) {
860 if (flowKey->tunKey.dst) {
861 rc = _MapFlowTunKeyToNlKey(nlBuf, &(flowKey->tunKey));
862 if (rc != STATUS_SUCCESS) {
868 NlMsgEndNested(nlBuf, offset);
874 *----------------------------------------------------------------------------
875 * _MapFlowTunKeyToNlKey --
876 * Maps OvsIPv4TunnelKey to OVS_TUNNEL_KEY_ATTR_ID attribute.
877 *----------------------------------------------------------------------------
880 _MapFlowTunKeyToNlKey(PNL_BUFFER nlBuf, OvsIPv4TunnelKey *tunKey)
882 NTSTATUS rc = STATUS_SUCCESS;
885 offset = NlMsgStartNested(nlBuf, OVS_KEY_ATTR_TUNNEL);
887 /* Starting the nested attribute failed. */
888 rc = STATUS_UNSUCCESSFUL;
889 goto error_nested_start;
892 if (!NlMsgPutTailU64(nlBuf, OVS_TUNNEL_KEY_ATTR_ID,
894 rc = STATUS_UNSUCCESSFUL;
898 if (!NlMsgPutTailU32(nlBuf, OVS_TUNNEL_KEY_ATTR_IPV4_DST,
900 rc = STATUS_UNSUCCESSFUL;
904 if (!NlMsgPutTailU32(nlBuf, OVS_TUNNEL_KEY_ATTR_IPV4_SRC,
906 rc = STATUS_UNSUCCESSFUL;
910 if (!NlMsgPutTailU8(nlBuf, OVS_TUNNEL_KEY_ATTR_TOS,
912 rc = STATUS_UNSUCCESSFUL;
916 if (!NlMsgPutTailU8(nlBuf, OVS_TUNNEL_KEY_ATTR_TTL,
918 rc = STATUS_UNSUCCESSFUL;
923 NlMsgEndNested(nlBuf, offset);
929 *----------------------------------------------------------------------------
930 * _MapFlowTunKeyToNlKey --
931 * Maps OvsIPv4FlowPutKey to OVS_KEY_ATTR_IPV4 attribute.
932 *----------------------------------------------------------------------------
935 _MapFlowIpv4KeyToNlKey(PNL_BUFFER nlBuf, IpKey *ipv4FlowPutKey)
937 NTSTATUS rc = STATUS_SUCCESS;
938 struct ovs_key_ipv4 ipv4Key;
940 ipv4Key.ipv4_src = ipv4FlowPutKey->nwSrc;
941 ipv4Key.ipv4_dst = ipv4FlowPutKey->nwDst;
942 ipv4Key.ipv4_proto = ipv4FlowPutKey->nwProto;
943 ipv4Key.ipv4_tos = ipv4FlowPutKey->nwTos;
944 ipv4Key.ipv4_ttl = ipv4FlowPutKey->nwTtl;
945 ipv4Key.ipv4_frag = ipv4FlowPutKey->nwFrag;
947 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_IPV4,
949 sizeof(struct ovs_key_ipv4))) {
950 rc = STATUS_UNSUCCESSFUL;
954 switch (ipv4Key.ipv4_proto) {
956 struct ovs_key_tcp tcpKey;
957 tcpKey.tcp_src = ipv4FlowPutKey->l4.tpSrc;
958 tcpKey.tcp_dst = ipv4FlowPutKey->l4.tpDst;
959 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_TCP,
962 rc = STATUS_UNSUCCESSFUL;
969 struct ovs_key_udp udpKey;
970 udpKey.udp_src = ipv4FlowPutKey->l4.tpSrc;
971 udpKey.udp_dst = ipv4FlowPutKey->l4.tpDst;
972 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_UDP,
975 rc = STATUS_UNSUCCESSFUL;
982 struct ovs_key_sctp sctpKey;
983 sctpKey.sctp_src = ipv4FlowPutKey->l4.tpSrc;
984 sctpKey.sctp_dst = ipv4FlowPutKey->l4.tpDst;
985 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_SCTP,
988 rc = STATUS_UNSUCCESSFUL;
995 struct ovs_key_icmp icmpKey;
996 /* XXX: revisit to see if htons is needed */
997 icmpKey.icmp_type = (__u8)(ipv4FlowPutKey->l4.tpSrc);
998 icmpKey.icmp_code = (__u8)(ipv4FlowPutKey->l4.tpDst);
1000 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ICMP,
1003 rc = STATUS_UNSUCCESSFUL;
1018 *----------------------------------------------------------------------------
1019 * _MapFlowIpv6KeyToNlKey --
1020 * Maps _MapFlowIpv6KeyToNlKey to OVS_KEY_ATTR_IPV6 attribute.
1021 *----------------------------------------------------------------------------
1024 _MapFlowIpv6KeyToNlKey(PNL_BUFFER nlBuf, Ipv6Key *ipv6FlowPutKey,
1025 Icmp6Key *icmpv6FlowPutKey)
1027 NTSTATUS rc = STATUS_SUCCESS;
1028 struct ovs_key_ipv6 ipv6Key;
1030 RtlCopyMemory(&(ipv6Key.ipv6_src), &ipv6FlowPutKey->ipv6Src,
1031 sizeof ipv6Key.ipv6_src);
1032 RtlCopyMemory(&(ipv6Key.ipv6_dst), &ipv6FlowPutKey->ipv6Dst,
1033 sizeof ipv6Key.ipv6_dst);
1035 ipv6Key.ipv6_label = ipv6FlowPutKey->ipv6Label;
1036 ipv6Key.ipv6_proto = ipv6FlowPutKey->nwProto;
1037 ipv6Key.ipv6_tclass = ipv6FlowPutKey->nwTos;
1038 ipv6Key.ipv6_hlimit = ipv6FlowPutKey->nwTtl;
1039 ipv6Key.ipv6_frag = ipv6FlowPutKey->nwFrag;
1041 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_IPV6,
1044 rc = STATUS_UNSUCCESSFUL;
1048 switch (ipv6Key.ipv6_proto) {
1050 struct ovs_key_tcp tcpKey;
1051 tcpKey.tcp_src = ipv6FlowPutKey->l4.tpSrc;
1052 tcpKey.tcp_dst = ipv6FlowPutKey->l4.tpDst;
1053 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_TCP,
1056 rc = STATUS_UNSUCCESSFUL;
1063 struct ovs_key_udp udpKey;
1064 udpKey.udp_src = ipv6FlowPutKey->l4.tpSrc;
1065 udpKey.udp_dst = ipv6FlowPutKey->l4.tpDst;
1066 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_UDP,
1069 rc = STATUS_UNSUCCESSFUL;
1075 case IPPROTO_SCTP: {
1076 struct ovs_key_sctp sctpKey;
1077 sctpKey.sctp_src = ipv6FlowPutKey->l4.tpSrc;
1078 sctpKey.sctp_dst = ipv6FlowPutKey->l4.tpDst;
1079 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_SCTP,
1082 rc = STATUS_UNSUCCESSFUL;
1088 case IPPROTO_ICMPV6: {
1089 struct ovs_key_icmpv6 icmpV6Key;
1090 struct ovs_key_nd ndKey;
1092 /* XXX: revisit to see if htons is needed */
1093 icmpV6Key.icmpv6_type = (__u8)(icmpv6FlowPutKey->l4.tpSrc);
1094 icmpV6Key.icmpv6_code = (__u8)(icmpv6FlowPutKey->l4.tpDst);
1096 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ICMPV6,
1097 (PCHAR)(&icmpV6Key),
1098 sizeof(icmpV6Key))) {
1099 rc = STATUS_UNSUCCESSFUL;
1103 RtlCopyMemory(&(ndKey.nd_target), &icmpv6FlowPutKey->ndTarget,
1104 sizeof(icmpv6FlowPutKey->ndTarget));
1105 RtlCopyMemory(&(ndKey.nd_sll), &icmpv6FlowPutKey->arpSha,
1107 RtlCopyMemory(&(ndKey.nd_tll), &icmpv6FlowPutKey->arpTha,
1109 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ND,
1112 rc = STATUS_UNSUCCESSFUL;
1128 *----------------------------------------------------------------------------
1129 * _MapFlowArpKeyToNlKey --
1130 * Maps _MapFlowArpKeyToNlKey to OVS_KEY_ATTR_ARP attribute.
1131 *----------------------------------------------------------------------------
1134 _MapFlowArpKeyToNlKey(PNL_BUFFER nlBuf, ArpKey *arpFlowPutKey)
1136 NTSTATUS rc = STATUS_SUCCESS;
1137 struct ovs_key_arp arpKey;
1139 arpKey.arp_sip = arpFlowPutKey->nwSrc;
1140 arpKey.arp_tip = arpFlowPutKey->nwDst;
1142 RtlCopyMemory(&(arpKey.arp_sha), arpFlowPutKey->arpSha, ETH_ADDR_LEN);
1143 RtlCopyMemory(&(arpKey.arp_tha), arpFlowPutKey->arpTha, ETH_ADDR_LEN);
1145 arpKey.arp_op = arpFlowPutKey->nwProto;
1147 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ARP,
1150 rc = STATUS_UNSUCCESSFUL;
1159 *----------------------------------------------------------------------------
1160 * _MapNlToFlowPut --
1161 * Maps input netlink message to OvsFlowPut.
1162 *----------------------------------------------------------------------------
1165 _MapNlToFlowPut(POVS_MESSAGE msgIn, PNL_ATTR keyAttr,
1166 PNL_ATTR actionAttr, PNL_ATTR flowAttrClear,
1167 OvsFlowPut *mappedFlow)
1169 NTSTATUS rc = STATUS_SUCCESS;
1170 PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
1171 PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
1172 POVS_HDR ovsHdr = &(msgIn->ovsHdr);
1174 UINT32 keyAttrOffset = (UINT32)((PCHAR)keyAttr - (PCHAR)nlMsgHdr);
1175 UINT32 tunnelKeyAttrOffset;
1177 PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX] = {NULL};
1178 PNL_ATTR tunnelAttrs[__OVS_TUNNEL_KEY_ATTR_MAX] = {NULL};
1180 /* Get flow keys attributes */
1181 if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset, NlAttrLen(keyAttr),
1182 nlFlowKeyPolicy, keyAttrs, ARRAY_SIZE(keyAttrs)))
1184 OVS_LOG_ERROR("Key Attr Parsing failed for msg: %p",
1186 rc = STATUS_INVALID_PARAMETER;
1190 if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
1191 tunnelKeyAttrOffset = (UINT32)((PCHAR)
1192 (keyAttrs[OVS_KEY_ATTR_TUNNEL])
1195 OVS_LOG_ERROR("Parse Flow Tunnel Key Policy");
1197 /* Get tunnel keys attributes */
1198 if ((NlAttrParseNested(nlMsgHdr, tunnelKeyAttrOffset,
1199 NlAttrLen(keyAttrs[OVS_KEY_ATTR_TUNNEL]),
1200 nlFlowTunnelKeyPolicy,
1201 tunnelAttrs, ARRAY_SIZE(tunnelAttrs)))
1203 OVS_LOG_ERROR("Tunnel key Attr Parsing failed for msg: %p",
1205 rc = STATUS_INVALID_PARAMETER;
1210 _MapKeyAttrToFlowPut(keyAttrs, tunnelAttrs,
1211 &(mappedFlow->key));
1213 /* Map the action */
1215 mappedFlow->actionsLen = NlAttrGetSize(actionAttr);
1216 mappedFlow->actions = NlAttrGet(actionAttr);
1219 mappedFlow->dpNo = ovsHdr->dp_ifindex;
1221 _MapNlToFlowPutFlags(genlMsgHdr, flowAttrClear,
1229 *----------------------------------------------------------------------------
1230 * _MapNlToFlowPutFlags --
1231 * Maps netlink message to OvsFlowPut->flags.
1232 *----------------------------------------------------------------------------
1235 _MapNlToFlowPutFlags(PGENL_MSG_HDR genlMsgHdr,
1236 PNL_ATTR flowAttrClear, OvsFlowPut *mappedFlow)
1240 switch (genlMsgHdr->cmd) {
1241 case OVS_FLOW_CMD_NEW:
1242 flags |= OVSWIN_FLOW_PUT_CREATE;
1244 case OVS_FLOW_CMD_DEL:
1245 flags |= OVSWIN_FLOW_PUT_DELETE;
1247 case OVS_FLOW_CMD_SET:
1248 flags |= OVSWIN_FLOW_PUT_MODIFY;
1254 if (flowAttrClear) {
1255 flags |= OVSWIN_FLOW_PUT_CLEAR;
1258 mappedFlow->flags = flags;
1262 *----------------------------------------------------------------------------
1263 * _MapKeyAttrToFlowPut --
1264 * Converts FLOW_KEY attribute to OvsFlowPut->key.
1265 *----------------------------------------------------------------------------
1268 _MapKeyAttrToFlowPut(PNL_ATTR *keyAttrs,
1269 PNL_ATTR *tunnelAttrs,
1270 OvsFlowKey *destKey)
1272 _MapTunAttrToFlowPut(keyAttrs, tunnelAttrs, destKey);
1274 /* ===== L2 headers ===== */
1275 destKey->l2.inPort = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_IN_PORT]);
1277 if (keyAttrs[OVS_KEY_ATTR_ETHERNET]) {
1278 const struct ovs_key_ethernet *eth_key;
1279 eth_key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ETHERNET]);
1280 RtlCopyMemory(destKey->l2.dlSrc, eth_key->eth_src, ETH_ADDR_LEN);
1281 RtlCopyMemory(destKey->l2.dlDst, eth_key->eth_dst, ETH_ADDR_LEN);
1284 /* TODO: Ideally ETHERTYPE should not be optional.
1285 * But during vswitchd bootup we are seeing FLOW_ADD
1286 * requests with no ETHERTYPE attributes.
1287 * Need to verify this. */
1288 if (keyAttrs[OVS_KEY_ATTR_ETHERTYPE]) {
1289 destKey->l2.dlType = ntohs((NlAttrGetU16(keyAttrs
1290 [OVS_KEY_ATTR_ETHERTYPE])));
1293 if (keyAttrs[OVS_KEY_ATTR_VLAN]) {
1294 destKey->l2.vlanTci = NlAttrGetU16(keyAttrs
1295 [OVS_KEY_ATTR_VLAN]);
1298 /* ==== L3 + L4. ==== */
1299 destKey->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + OVS_L2_KEY_SIZE
1300 - destKey->l2.offset;
1302 switch (destKey->l2.dlType) {
1303 case ETH_TYPE_IPV4: {
1305 if (keyAttrs[OVS_KEY_ATTR_IPV4]) {
1306 const struct ovs_key_ipv4 *ipv4Key;
1308 ipv4Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_IPV4]);
1309 IpKey *ipv4FlowPutKey = &(destKey->ipKey);
1310 ipv4FlowPutKey->nwSrc = ipv4Key->ipv4_src;
1311 ipv4FlowPutKey->nwDst = ipv4Key->ipv4_dst;
1312 ipv4FlowPutKey->nwProto = ipv4Key->ipv4_proto;
1313 ipv4FlowPutKey->nwTos = ipv4Key->ipv4_tos;
1314 ipv4FlowPutKey->nwTtl = ipv4Key->ipv4_ttl;
1315 ipv4FlowPutKey->nwFrag = ipv4Key->ipv4_frag;
1317 if (keyAttrs[OVS_KEY_ATTR_TCP]) {
1318 const struct ovs_key_tcp *tcpKey;
1319 tcpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_TCP]);
1320 ipv4FlowPutKey->l4.tpSrc = tcpKey->tcp_src;
1321 ipv4FlowPutKey->l4.tpDst = tcpKey->tcp_dst;
1324 if (keyAttrs[OVS_KEY_ATTR_UDP]) {
1325 const struct ovs_key_udp *udpKey;
1326 udpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_UDP]);
1327 ipv4FlowPutKey->l4.tpSrc = udpKey->udp_src;
1328 ipv4FlowPutKey->l4.tpDst = udpKey->udp_dst;
1331 if (keyAttrs[OVS_KEY_ATTR_SCTP]) {
1332 const struct ovs_key_sctp *sctpKey;
1333 sctpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_SCTP]);
1334 ipv4FlowPutKey->l4.tpSrc = sctpKey->sctp_src;
1335 ipv4FlowPutKey->l4.tpDst = sctpKey->sctp_dst;
1338 destKey->l2.keyLen += OVS_IP_KEY_SIZE;
1342 case ETH_TYPE_IPV6: {
1344 if (keyAttrs[OVS_KEY_ATTR_IPV6]) {
1345 const struct ovs_key_ipv6 *ipv6Key;
1347 ipv6Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_IPV6]);
1348 Ipv6Key *ipv6FlowPutKey = &(destKey->ipv6Key);
1350 RtlCopyMemory(&ipv6FlowPutKey->ipv6Src, ipv6Key->ipv6_src,
1351 sizeof ipv6Key->ipv6_src);
1352 RtlCopyMemory(&ipv6FlowPutKey->ipv6Dst, ipv6Key->ipv6_dst,
1353 sizeof ipv6Key->ipv6_dst);
1355 ipv6FlowPutKey->ipv6Label = ipv6Key->ipv6_label;
1356 ipv6FlowPutKey->nwProto = ipv6Key->ipv6_proto;
1357 ipv6FlowPutKey->nwTos = ipv6Key->ipv6_tclass;
1358 ipv6FlowPutKey->nwTtl = ipv6Key->ipv6_hlimit;
1359 ipv6FlowPutKey->nwFrag = ipv6Key->ipv6_frag;
1361 if (keyAttrs[OVS_KEY_ATTR_TCP]) {
1362 const struct ovs_key_tcp *tcpKey;
1363 tcpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_TCP]);
1364 ipv6FlowPutKey->l4.tpSrc = tcpKey->tcp_src;
1365 ipv6FlowPutKey->l4.tpDst = tcpKey->tcp_dst;
1368 if (keyAttrs[OVS_KEY_ATTR_UDP]) {
1369 const struct ovs_key_udp *udpKey;
1370 udpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_UDP]);
1371 ipv6FlowPutKey->l4.tpSrc = udpKey->udp_src;
1372 ipv6FlowPutKey->l4.tpDst = udpKey->udp_dst;
1375 if (keyAttrs[OVS_KEY_ATTR_SCTP]) {
1376 const struct ovs_key_sctp *sctpKey;
1377 sctpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_SCTP]);
1378 ipv6FlowPutKey->l4.tpSrc = sctpKey->sctp_src;
1379 ipv6FlowPutKey->l4.tpDst = sctpKey->sctp_dst;
1382 if (keyAttrs[OVS_KEY_ATTR_ICMPV6]) {
1383 const struct ovs_key_icmpv6 *icmpv6Key;
1385 Icmp6Key *icmp6FlowPutKey= &(destKey->icmp6Key);
1387 icmpv6Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ICMPV6]);
1389 icmp6FlowPutKey->l4.tpSrc = icmpv6Key->icmpv6_type;
1390 icmp6FlowPutKey->l4.tpDst = icmpv6Key->icmpv6_code;
1392 if (keyAttrs[OVS_KEY_ATTR_ND]) {
1393 const struct ovs_key_nd *ndKey;
1395 ndKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ND]);
1396 RtlCopyMemory(&icmp6FlowPutKey->ndTarget,
1397 ndKey->nd_target, sizeof (icmp6FlowPutKey->ndTarget));
1398 RtlCopyMemory(icmp6FlowPutKey->arpSha,
1399 ndKey->nd_sll, ETH_ADDR_LEN);
1400 RtlCopyMemory(icmp6FlowPutKey->arpTha,
1401 ndKey->nd_tll, ETH_ADDR_LEN);
1404 destKey->l2.keyLen += OVS_ICMPV6_KEY_SIZE;
1408 destKey->l2.keyLen += OVS_IPV6_KEY_SIZE;
1411 ipv6FlowPutKey->pad = 0;
1416 case ETH_TYPE_RARP: {
1417 ArpKey *arpFlowPutKey = &destKey->arpKey;
1418 const struct ovs_key_arp *arpKey;
1420 arpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ARP]);
1422 arpFlowPutKey->nwSrc = arpKey->arp_sip;
1423 arpFlowPutKey->nwDst = arpKey->arp_tip;
1425 RtlCopyMemory(arpFlowPutKey->arpSha, arpKey->arp_sha, ETH_ADDR_LEN);
1426 RtlCopyMemory(arpFlowPutKey->arpTha, arpKey->arp_tha, ETH_ADDR_LEN);
1427 arpFlowPutKey->nwProto = (UINT8)(arpKey->arp_op);
1428 arpFlowPutKey->pad[0] = 0;
1429 arpFlowPutKey->pad[1] = 0;
1430 arpFlowPutKey->pad[2] = 0;
1431 destKey->l2.keyLen += OVS_ARP_KEY_SIZE;
1438 *----------------------------------------------------------------------------
1439 * _MapTunAttrToFlowPut --
1440 * Converts FLOW_TUNNEL_KEY attribute to OvsFlowKey->tunKey.
1441 *----------------------------------------------------------------------------
1444 _MapTunAttrToFlowPut(PNL_ATTR *keyAttrs,
1446 OvsFlowKey *destKey)
1448 if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
1450 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_ID]) {
1451 destKey->tunKey.tunnelId = NlAttrGetU64
1452 (tunAttrs[OVS_TUNNEL_KEY_ATTR_ID]);
1453 destKey->tunKey.flags |= OVS_TNL_F_KEY;
1456 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_DST]) {
1457 destKey->tunKey.dst = NlAttrGetU32
1458 (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_DST]);
1461 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_SRC]) {
1462 destKey->tunKey.src = NlAttrGetU32
1463 (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_SRC]);
1466 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT]) {
1467 destKey->tunKey.flags |= OVS_TNL_F_DONT_FRAGMENT;
1470 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_CSUM]) {
1471 destKey->tunKey.flags |= OVS_TNL_F_CSUM;
1474 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_TOS]) {
1475 destKey->tunKey.tos = NlAttrGetU8
1476 (tunAttrs[OVS_TUNNEL_KEY_ATTR_TOS]);
1479 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_TTL]) {
1480 destKey->tunKey.ttl = NlAttrGetU8
1481 (tunAttrs[OVS_TUNNEL_KEY_ATTR_TTL]);
1484 destKey->tunKey.pad = 0;
1485 destKey->l2.offset = 0;
1487 destKey->tunKey.attr[0] = 0;
1488 destKey->tunKey.attr[1] = 0;
1489 destKey->tunKey.attr[2] = 0;
1490 destKey->l2.offset = sizeof destKey->tunKey;
1495 *----------------------------------------------------------------------------
1496 * OvsDeleteFlowTable --
1498 * NDIS_STATUS_SUCCESS always.
1499 *----------------------------------------------------------------------------
1502 OvsDeleteFlowTable(OVS_DATAPATH *datapath)
1504 if (datapath == NULL || datapath->flowTable == NULL) {
1505 return NDIS_STATUS_SUCCESS;
1508 DeleteAllFlows(datapath);
1509 OvsFreeMemory(datapath->flowTable);
1510 datapath->flowTable = NULL;
1511 NdisFreeRWLock(datapath->lock);
1513 return NDIS_STATUS_SUCCESS;
1517 *----------------------------------------------------------------------------
1518 * OvsAllocateFlowTable --
1520 * NDIS_STATUS_SUCCESS on success.
1521 * NDIS_STATUS_RESOURCES if memory couldn't be allocated
1522 *----------------------------------------------------------------------------
1525 OvsAllocateFlowTable(OVS_DATAPATH *datapath,
1526 POVS_SWITCH_CONTEXT switchContext)
1531 datapath->flowTable = OvsAllocateMemory(OVS_FLOW_TABLE_SIZE *
1532 sizeof (LIST_ENTRY));
1533 if (!datapath->flowTable) {
1534 return NDIS_STATUS_RESOURCES;
1536 for (i = 0; i < OVS_FLOW_TABLE_SIZE; i++) {
1537 bucket = &(datapath->flowTable[i]);
1538 InitializeListHead(bucket);
1540 datapath->lock = NdisAllocateRWLock(switchContext->NdisFilterHandle);
1542 return NDIS_STATUS_SUCCESS;
1547 *----------------------------------------------------------------------------
1548 * GetStartAddrNBL --
1549 * Get the virtual address of the frame.
1552 * Virtual address of the frame.
1553 *----------------------------------------------------------------------------
1555 static __inline VOID *
1556 GetStartAddrNBL(const NET_BUFFER_LIST *_pNB)
1564 // Ethernet Header is a guaranteed safe access.
1565 curMdl = (NET_BUFFER_LIST_FIRST_NB(_pNB))->CurrentMdl;
1566 curBuffer = MmGetSystemAddressForMdlSafe(curMdl, LowPagePriority);
1571 curHeader = (PEthHdr)
1572 (curBuffer + (NET_BUFFER_LIST_FIRST_NB(_pNB))->CurrentMdlOffset);
1574 return (VOID *) curHeader;
1578 OvsFlowUsed(OvsFlow *flow,
1579 const NET_BUFFER_LIST *packet,
1580 const POVS_PACKET_HDR_INFO layers)
1582 LARGE_INTEGER tickCount;
1584 KeQueryTickCount(&tickCount);
1585 flow->used = tickCount.QuadPart * ovsTimeIncrementPerTick;
1586 flow->packetCount++;
1587 flow->byteCount += OvsPacketLenNBL(packet);
1588 flow->tcpFlags |= OvsGetTcpFlags(packet, &flow->key, layers);
1593 DeleteAllFlows(OVS_DATAPATH *datapath)
1598 for (i = 0; i < OVS_FLOW_TABLE_SIZE; i++) {
1600 bucket = &(datapath->flowTable[i]);
1601 while (!IsListEmpty(bucket)) {
1603 next = bucket->Flink;
1604 flow = CONTAINING_RECORD(next, OvsFlow, ListEntry);
1605 RemoveFlow(datapath, &flow);
1611 *----------------------------------------------------------------------------
1612 * Initializes 'flow' members from 'packet', 'skb_priority', 'tun_id', and
1615 * Initializes 'packet' header pointers as follows:
1617 * - packet->l2 to the start of the Ethernet header.
1619 * - packet->l3 to just past the Ethernet header, or just past the
1620 * vlan_header if one is present, to the first byte of the payload of the
1623 * - packet->l4 to just past the IPv4 header, if one is present and has a
1624 * correct length, and otherwise NULL.
1626 * - packet->l7 to just past the TCP or UDP or ICMP header, if one is
1627 * present and has a correct length, and otherwise NULL.
1629 * Returns NDIS_STATUS_SUCCESS normally. Fails only if packet data cannot be accessed
1630 * (e.g. if Pkt_CopyBytesOut() returns an error).
1631 *----------------------------------------------------------------------------
1634 OvsExtractFlow(const NET_BUFFER_LIST *packet,
1637 POVS_PACKET_HDR_INFO layers,
1638 OvsIPv4TunnelKey *tunKey)
1640 struct Eth_Header *eth;
1647 ASSERT(tunKey->dst != 0);
1648 RtlMoveMemory(&flow->tunKey, tunKey, sizeof flow->tunKey);
1649 flow->l2.offset = 0;
1651 flow->tunKey.dst = 0;
1652 flow->l2.offset = OVS_WIN_TUNNEL_KEY_SIZE;
1655 flow->l2.inPort = inPort;
1657 if ( OvsPacketLenNBL(packet) < ETH_HEADER_LEN_DIX) {
1658 flow->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + 8 - flow->l2.offset;
1659 return NDIS_STATUS_SUCCESS;
1663 eth = (Eth_Header *)GetStartAddrNBL((NET_BUFFER_LIST *)packet);
1664 memcpy(flow->l2.dlSrc, eth->src, ETH_ADDR_LENGTH);
1665 memcpy(flow->l2.dlDst, eth->dst, ETH_ADDR_LENGTH);
1670 vlanTagValue = NET_BUFFER_LIST_INFO(packet, Ieee8021QNetBufferListInfo);
1672 PNDIS_NET_BUFFER_LIST_8021Q_INFO vlanTag =
1673 (PNDIS_NET_BUFFER_LIST_8021Q_INFO)(PVOID *)&vlanTagValue;
1674 flow->l2.vlanTci = htons(vlanTag->TagHeader.VlanId | OVSWIN_VLAN_CFI |
1675 (vlanTag->TagHeader.UserPriority << 13));
1677 if (eth->dix.typeNBO == ETH_TYPE_802_1PQ_NBO) {
1678 Eth_802_1pq_Tag *tag= (Eth_802_1pq_Tag *)ð->dix.typeNBO;
1679 flow->l2.vlanTci = ((UINT16)tag->priority << 13) |
1681 ((UINT16)tag->vidHi << 8) | tag->vidLo;
1682 offset = sizeof (Eth_802_1pq_Tag);
1684 flow->l2.vlanTci = 0;
1688 * Please note after this point, src mac and dst mac should
1689 * not be accessed through eth
1691 eth = (Eth_Header *)((UINT8 *)eth + offset);
1697 * XXX assume that at least the first
1698 * 12 bytes of received packets are mapped. This code has the stronger
1699 * assumption that at least the first 22 bytes of 'packet' is mapped (if my
1700 * arithmetic is right).
1702 if (ETH_TYPENOT8023(eth->dix.typeNBO)) {
1703 flow->l2.dlType = eth->dix.typeNBO;
1704 layers->l3Offset = ETH_HEADER_LEN_DIX + offset;
1705 } else if (OvsPacketLenNBL(packet) >= ETH_HEADER_LEN_802_3 &&
1706 eth->e802_3.llc.dsap == 0xaa &&
1707 eth->e802_3.llc.ssap == 0xaa &&
1708 eth->e802_3.llc.control == ETH_LLC_CONTROL_UFRAME &&
1709 eth->e802_3.snap.snapOrg[0] == 0x00 &&
1710 eth->e802_3.snap.snapOrg[1] == 0x00 &&
1711 eth->e802_3.snap.snapOrg[2] == 0x00) {
1712 flow->l2.dlType = eth->e802_3.snap.snapType.typeNBO;
1713 layers->l3Offset = ETH_HEADER_LEN_802_3 + offset;
1715 flow->l2.dlType = htons(OVSWIN_DL_TYPE_NONE);
1716 layers->l3Offset = ETH_HEADER_LEN_DIX + offset;
1719 flow->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + OVS_L2_KEY_SIZE - flow->l2.offset;
1720 /* Network layer. */
1721 if (flow->l2.dlType == htons(ETH_TYPE_IPV4)) {
1722 struct IPHdr ip_storage;
1723 const struct IPHdr *nh;
1724 IpKey *ipKey = &flow->ipKey;
1726 flow->l2.keyLen += OVS_IP_KEY_SIZE;
1728 nh = OvsGetIp(packet, layers->l3Offset, &ip_storage);
1730 layers->l4Offset = layers->l3Offset + nh->ihl * 4;
1732 ipKey->nwSrc = nh->saddr;
1733 ipKey->nwDst = nh->daddr;
1734 ipKey->nwProto = nh->protocol;
1736 ipKey->nwTos = nh->tos;
1737 if (nh->frag_off & htons(IP_MF | IP_OFFSET)) {
1738 ipKey->nwFrag = OVSWIN_NW_FRAG_ANY;
1739 if (nh->frag_off & htons(IP_OFFSET)) {
1740 ipKey->nwFrag |= OVSWIN_NW_FRAG_LATER;
1746 ipKey->nwTtl = nh->ttl;
1747 ipKey->l4.tpSrc = 0;
1748 ipKey->l4.tpDst = 0;
1750 if (!(nh->frag_off & htons(IP_OFFSET))) {
1751 if (ipKey->nwProto == SOCKET_IPPROTO_TCP) {
1752 OvsParseTcp(packet, &ipKey->l4, layers);
1753 } else if (ipKey->nwProto == SOCKET_IPPROTO_UDP) {
1754 OvsParseUdp(packet, &ipKey->l4, layers);
1755 } else if (ipKey->nwProto == SOCKET_IPPROTO_ICMP) {
1756 ICMPHdr icmpStorage;
1757 const ICMPHdr *icmp;
1759 icmp = OvsGetIcmp(packet, layers->l4Offset, &icmpStorage);
1761 ipKey->l4.tpSrc = htons(icmp->type);
1762 ipKey->l4.tpDst = htons(icmp->code);
1763 layers->l7Offset = layers->l4Offset + sizeof *icmp;
1768 ((UINT64 *)ipKey)[0] = 0;
1769 ((UINT64 *)ipKey)[1] = 0;
1771 } else if (flow->l2.dlType == htons(ETH_TYPE_IPV6)) {
1773 flow->l2.keyLen += OVS_IPV6_KEY_SIZE;
1774 status = OvsParseIPv6(packet, flow, layers);
1775 if (status != NDIS_STATUS_SUCCESS) {
1776 memset(&flow->ipv6Key, 0, sizeof (Ipv6Key));
1780 flow->ipv6Key.l4.tpSrc = 0;
1781 flow->ipv6Key.l4.tpDst = 0;
1782 flow->ipv6Key.pad = 0;
1784 if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_TCP) {
1785 OvsParseTcp(packet, &(flow->ipv6Key.l4), layers);
1786 } else if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_UDP) {
1787 OvsParseUdp(packet, &(flow->ipv6Key.l4), layers);
1788 } else if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_ICMPV6) {
1789 OvsParseIcmpV6(packet, flow, layers);
1790 flow->l2.keyLen += (OVS_ICMPV6_KEY_SIZE - OVS_IPV6_KEY_SIZE);
1792 } else if (flow->l2.dlType == htons(ETH_TYPE_ARP)) {
1793 EtherArp arpStorage;
1794 const EtherArp *arp;
1795 ArpKey *arpKey = &flow->arpKey;
1796 ((UINT64 *)arpKey)[0] = 0;
1797 ((UINT64 *)arpKey)[1] = 0;
1798 ((UINT64 *)arpKey)[2] = 0;
1799 flow->l2.keyLen += OVS_ARP_KEY_SIZE;
1800 arp = OvsGetArp(packet, layers->l3Offset, &arpStorage);
1801 if (arp && arp->ea_hdr.ar_hrd == htons(1) &&
1802 arp->ea_hdr.ar_pro == htons(ETH_TYPE_IPV4) &&
1803 arp->ea_hdr.ar_hln == ETH_ADDR_LENGTH &&
1804 arp->ea_hdr.ar_pln == 4) {
1805 /* We only match on the lower 8 bits of the opcode. */
1806 if (ntohs(arp->ea_hdr.ar_op) <= 0xff) {
1807 arpKey->nwProto = (UINT8)ntohs(arp->ea_hdr.ar_op);
1809 if (arpKey->nwProto == ARPOP_REQUEST
1810 || arpKey->nwProto == ARPOP_REPLY) {
1811 memcpy(&arpKey->nwSrc, arp->arp_spa, 4);
1812 memcpy(&arpKey->nwDst, arp->arp_tpa, 4);
1813 memcpy(arpKey->arpSha, arp->arp_sha, ETH_ADDR_LENGTH);
1814 memcpy(arpKey->arpTha, arp->arp_tha, ETH_ADDR_LENGTH);
1819 return NDIS_STATUS_SUCCESS;
1823 FlowEqual(UINT64 *src, UINT64 *dst, UINT32 size)
1826 ASSERT((size & 0x7) == 0);
1827 ASSERT(((UINT64)src & 0x7) == 0);
1828 ASSERT(((UINT64)dst & 0x7) == 0);
1829 for (i = 0; i < (size >> 3); i++) {
1830 if (src[i] != dst[i]) {
1839 * ----------------------------------------------------------------------------
1841 * Add a flow to flow table.
1844 * NDIS_STATUS_SUCCESS if no same flow in the flow table.
1845 * ----------------------------------------------------------------------------
1848 AddFlow(OVS_DATAPATH *datapath, OvsFlow *flow)
1852 if (OvsLookupFlow(datapath, &flow->key, &flow->hash, TRUE) != NULL) {
1853 return STATUS_INVALID_HANDLE;
1856 head = &(datapath->flowTable[HASH_BUCKET(flow->hash)]);
1858 * We need fence here to make sure flow's nextPtr is updated before
1859 * head->nextPtr is updated.
1863 //KeAcquireSpinLock(&FilterDeviceExtension->NblQueueLock, &oldIrql);
1864 InsertTailList(head, &flow->ListEntry);
1865 //KeReleaseSpinLock(&FilterDeviceExtension->NblQueueLock, oldIrql);
1869 return STATUS_SUCCESS;
1873 /* ----------------------------------------------------------------------------
1875 * Remove a flow from flow table, and added to wait list
1876 * ----------------------------------------------------------------------------
1879 RemoveFlow(OVS_DATAPATH *datapath,
1884 UNREFERENCED_PARAMETER(datapath);
1886 ASSERT(datapath->nFlows);
1888 // Remove the flow from queue
1889 RemoveEntryList(&f->ListEntry);
1895 * ----------------------------------------------------------------------------
1898 * Find flow from flow table based on flow key.
1899 * Caller should either hold portset handle or should
1900 * have a flowRef in datapath or Acquired datapath.
1903 * Flow pointer if lookup successful.
1904 * NULL if not exists.
1905 * ----------------------------------------------------------------------------
1908 OvsLookupFlow(OVS_DATAPATH *datapath,
1909 const OvsFlowKey *key,
1913 PLIST_ENTRY link, head;
1914 UINT16 offset = key->l2.offset;
1915 UINT16 size = key->l2.keyLen;
1918 ASSERT(key->tunKey.dst || offset == sizeof (OvsIPv4TunnelKey));
1919 ASSERT(!key->tunKey.dst || offset == 0);
1921 start = (UINT8 *)key + offset;
1924 *hash = OvsJhashBytes(start, size, 0);
1927 head = &datapath->flowTable[HASH_BUCKET(*hash)];
1929 while (link != head) {
1930 OvsFlow *flow = CONTAINING_RECORD(link, OvsFlow, ListEntry);
1932 if (flow->hash == *hash &&
1933 flow->key.l2.val == key->l2.val &&
1934 FlowEqual((UINT64 *)((uint8 *)&flow->key + offset),
1935 (UINT64 *)start, size)) {
1945 * ----------------------------------------------------------------------------
1947 * Calculate the hash for the given flow key.
1948 * ----------------------------------------------------------------------------
1951 OvsHashFlow(const OvsFlowKey *key)
1953 UINT16 offset = key->l2.offset;
1954 UINT16 size = key->l2.keyLen;
1957 ASSERT(key->tunKey.dst || offset == sizeof (OvsIPv4TunnelKey));
1958 ASSERT(!key->tunKey.dst || offset == 0);
1959 start = (UINT8 *)key + offset;
1960 return OvsJhashBytes(start, size, 0);
1965 * ----------------------------------------------------------------------------
1967 * Free a flow and its actions.
1968 * ----------------------------------------------------------------------------
1971 FreeFlow(OvsFlow *flow)
1974 OvsFreeMemory(flow);
1978 OvsDoDumpFlows(OvsFlowDumpInput *dumpInput,
1979 OvsFlowDumpOutput *dumpOutput,
1983 OVS_DATAPATH *datapath = NULL;
1985 PLIST_ENTRY node, head;
1987 UINT32 rowIndex, columnIndex;
1988 LOCK_STATE_EX dpLockState;
1989 NTSTATUS status = STATUS_SUCCESS;
1990 BOOLEAN findNextNonEmpty = FALSE;
1992 dpNo = dumpInput->dpNo;
1993 NdisAcquireSpinLock(gOvsCtrlLock);
1994 if (gOvsSwitchContext == NULL ||
1995 gOvsSwitchContext->dpNo != dpNo) {
1996 status = STATUS_INVALID_PARAMETER;
2000 rowIndex = dumpInput->position[0];
2001 if (rowIndex >= OVS_FLOW_TABLE_SIZE) {
2003 *replyLen = sizeof(*dumpOutput);
2007 columnIndex = dumpInput->position[1];
2009 datapath = &gOvsSwitchContext->datapath;
2011 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
2012 OvsAcquireDatapathRead(datapath, &dpLockState, TRUE);
2014 head = &datapath->flowTable[rowIndex];
2017 while (column < columnIndex) {
2026 findNextNonEmpty = TRUE;
2030 if (findNextNonEmpty) {
2031 while (head == node) {
2032 if (++rowIndex >= OVS_FLOW_TABLE_SIZE) {
2036 head = &datapath->flowTable[rowIndex];
2041 ASSERT(node != head);
2042 ASSERT(rowIndex < OVS_FLOW_TABLE_SIZE);
2044 flow = CONTAINING_RECORD(node, OvsFlow, ListEntry);
2045 status = ReportFlowInfo(flow, dumpInput->getFlags, &dumpOutput->flow);
2047 if (status == STATUS_BUFFER_TOO_SMALL) {
2048 dumpOutput->n = sizeof(OvsFlowDumpOutput) + flow->actionsLen;
2049 *replyLen = sizeof(*dumpOutput);
2051 dumpOutput->n = 1; //one flow reported.
2052 *replyLen = sizeof(*dumpOutput) + dumpOutput->flow.actionsLen;
2055 dumpOutput->position[0] = rowIndex;
2056 dumpOutput->position[1] = ++columnIndex;
2059 OvsReleaseDatapath(datapath, &dpLockState);
2062 NdisReleaseSpinLock(gOvsCtrlLock);
2067 OvsDumpFlowIoctl(PVOID inputBuffer,
2070 UINT32 outputLength,
2073 OvsFlowDumpOutput *dumpOutput = (OvsFlowDumpOutput *)outputBuffer;
2074 OvsFlowDumpInput *dumpInput = (OvsFlowDumpInput *)inputBuffer;
2076 if (inputBuffer == NULL || outputBuffer == NULL) {
2077 return STATUS_INVALID_PARAMETER;
2080 if ((inputLength != sizeof(OvsFlowDumpInput))
2081 || (outputLength != sizeof *dumpOutput + dumpInput->actionsLen)) {
2082 return STATUS_INFO_LENGTH_MISMATCH;
2085 return OvsDoDumpFlows(dumpInput, dumpOutput, replyLen);
2089 ReportFlowInfo(OvsFlow *flow,
2093 NTSTATUS status = STATUS_SUCCESS;
2095 if (getFlags & FLOW_GET_KEY) {
2096 // always copy the tunnel key part
2097 RtlCopyMemory(&info->key, &flow->key,
2098 flow->key.l2.keyLen + flow->key.l2.offset);
2101 if (getFlags & FLOW_GET_STATS) {
2102 OvsFlowStats *stats = &info->stats;
2103 stats->packetCount = flow->packetCount;
2104 stats->byteCount = flow->byteCount;
2105 stats->used = (UINT32)flow->used;
2106 stats->tcpFlags = flow->tcpFlags;
2109 if (getFlags & FLOW_GET_ACTIONS) {
2110 if (flow->actionsLen == 0) {
2111 info->actionsLen = 0;
2113 info->actions = flow->actions;
2114 info->actionsLen = flow->actionsLen;
2122 OvsPutFlowIoctl(PVOID inputBuffer,
2124 struct OvsFlowStats *stats)
2126 NTSTATUS status = STATUS_SUCCESS;
2127 OVS_DATAPATH *datapath = NULL;
2131 LOCK_STATE_EX dpLockState;
2133 if ((inputLength < sizeof(OvsFlowPut)) || (inputBuffer == NULL)) {
2134 return STATUS_INFO_LENGTH_MISMATCH;
2137 put = (OvsFlowPut *)inputBuffer;
2138 if (put->actionsLen > 0) {
2139 actionsLen = put->actionsLen;
2145 NdisAcquireSpinLock(gOvsCtrlLock);
2146 if (gOvsSwitchContext == NULL ||
2147 gOvsSwitchContext->dpNo != dpNo) {
2148 status = STATUS_INVALID_PARAMETER;
2152 datapath = &gOvsSwitchContext->datapath;
2154 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
2155 OvsAcquireDatapathWrite(datapath, &dpLockState, TRUE);
2156 status = HandleFlowPut(put, datapath, stats);
2157 OvsReleaseDatapath(datapath, &dpLockState);
2160 NdisReleaseSpinLock(gOvsCtrlLock);
2165 /* Handles flow add, modify as well as delete */
2167 HandleFlowPut(OvsFlowPut *put,
2168 OVS_DATAPATH *datapath,
2169 struct OvsFlowStats *stats)
2171 BOOLEAN mayCreate, mayModify, mayDelete;
2172 OvsFlow *KernelFlow;
2174 NTSTATUS status = STATUS_SUCCESS;
2176 mayCreate = (put->flags & OVSWIN_FLOW_PUT_CREATE) != 0;
2177 mayModify = (put->flags & OVSWIN_FLOW_PUT_MODIFY) != 0;
2178 mayDelete = (put->flags & OVSWIN_FLOW_PUT_DELETE) != 0;
2180 if ((mayCreate || mayModify) == mayDelete) {
2181 return STATUS_INVALID_PARAMETER;
2184 KernelFlow = OvsLookupFlow(datapath, &put->key, &hash, FALSE);
2187 return STATUS_INVALID_PARAMETER;
2190 status = OvsPrepareFlow(&KernelFlow, put, hash);
2191 if (status != STATUS_SUCCESS) {
2192 FreeFlow(KernelFlow);
2193 return STATUS_UNSUCCESSFUL;
2196 status = AddFlow(datapath, KernelFlow);
2197 if (status != STATUS_SUCCESS) {
2198 FreeFlow(KernelFlow);
2199 return STATUS_UNSUCCESSFUL;
2202 /* Validate the flow addition */
2205 OvsFlow *flow = OvsLookupFlow(datapath, &put->key, &newHash,
2208 ASSERT(newHash == hash);
2209 if (!flow || newHash != hash) {
2210 return STATUS_UNSUCCESSFUL;
2214 stats->packetCount = KernelFlow->packetCount;
2215 stats->byteCount = KernelFlow->byteCount;
2216 stats->tcpFlags = KernelFlow->tcpFlags;
2217 stats->used = (UINT32)KernelFlow->used;
2221 status = OvsPrepareFlow(&newFlow, put, hash);
2222 if (status != STATUS_SUCCESS) {
2223 return STATUS_UNSUCCESSFUL;
2226 KernelFlow = OvsLookupFlow(datapath, &put->key, &hash, TRUE);
2228 if ((put->flags & OVSWIN_FLOW_PUT_CLEAR) == 0) {
2229 newFlow->packetCount = KernelFlow->packetCount;
2230 newFlow->byteCount = KernelFlow->byteCount;
2231 newFlow->tcpFlags = KernelFlow->tcpFlags;
2233 RemoveFlow(datapath, &KernelFlow);
2235 if ((put->flags & OVSWIN_FLOW_PUT_CLEAR) == 0) {
2236 newFlow->packetCount = stats->packetCount;
2237 newFlow->byteCount = stats->byteCount;
2238 newFlow->tcpFlags = stats->tcpFlags;
2241 status = AddFlow(datapath, newFlow);
2242 ASSERT(status == STATUS_SUCCESS);
2244 /* Validate the flow addition */
2247 OvsFlow *testflow = OvsLookupFlow(datapath, &put->key,
2250 ASSERT(newHash == hash);
2251 if (!testflow || newHash != hash) {
2253 return STATUS_UNSUCCESSFUL;
2259 RemoveFlow(datapath, &KernelFlow);
2262 return STATUS_UNSUCCESSFUL;
2266 return STATUS_SUCCESS;
2270 OvsPrepareFlow(OvsFlow **flow,
2271 const OvsFlowPut *put,
2274 OvsFlow *localFlow = *flow;
2275 NTSTATUS status = STATUS_SUCCESS;
2279 OvsAllocateMemory(sizeof(OvsFlow) + put->actionsLen);
2280 if (localFlow == NULL) {
2281 status = STATUS_NO_MEMORY;
2285 localFlow->key = put->key;
2286 localFlow->actionsLen = put->actionsLen;
2287 if (put->actionsLen) {
2288 NdisMoveMemory((PUCHAR)localFlow->actions, put->actions,
2291 localFlow->userActionsLen = 0; // 0 indicate no conversion is made
2292 localFlow->used = 0;
2293 localFlow->packetCount = 0;
2294 localFlow->byteCount = 0;
2295 localFlow->tcpFlags = 0;
2296 localFlow->hash = hash;
2303 OvsGetFlowIoctl(PVOID inputBuffer,
2306 NTSTATUS status = STATUS_SUCCESS;
2307 OVS_DATAPATH *datapath = NULL;
2309 UINT32 getFlags, getActionsLen;
2310 OvsFlowGetInput *getInput;
2311 OvsFlowGetOutput *getOutput;
2314 LOCK_STATE_EX dpLockState;
2316 getInput = (OvsFlowGetInput *) inputBuffer;
2317 getFlags = getInput->getFlags;
2318 getActionsLen = getInput->actionsLen;
2320 if (outputBuffer == NULL) {
2321 return STATUS_INFO_LENGTH_MISMATCH;
2324 dpNo = getInput->dpNo;
2325 NdisAcquireSpinLock(gOvsCtrlLock);
2326 if (gOvsSwitchContext == NULL ||
2327 gOvsSwitchContext->dpNo != dpNo) {
2328 status = STATUS_INVALID_PARAMETER;
2332 datapath = &gOvsSwitchContext->datapath;
2334 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
2335 OvsAcquireDatapathRead(datapath, &dpLockState, TRUE);
2336 flow = OvsLookupFlow(datapath, &getInput->key, &hash, FALSE);
2338 status = STATUS_INVALID_PARAMETER;
2342 getOutput = (OvsFlowGetOutput *)outputBuffer;
2343 ReportFlowInfo(flow, getFlags, &getOutput->info);
2346 OvsReleaseDatapath(datapath, &dpLockState);
2348 NdisReleaseSpinLock(gOvsCtrlLock);
2353 OvsFlushFlowIoctl(UINT32 dpNo)
2355 NTSTATUS status = STATUS_SUCCESS;
2356 OVS_DATAPATH *datapath = NULL;
2357 LOCK_STATE_EX dpLockState;
2359 NdisAcquireSpinLock(gOvsCtrlLock);
2360 if (gOvsSwitchContext == NULL ||
2361 gOvsSwitchContext->dpNo != dpNo) {
2362 status = STATUS_INVALID_PARAMETER;
2366 datapath = &gOvsSwitchContext->datapath;
2368 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
2369 OvsAcquireDatapathWrite(datapath, &dpLockState, TRUE);
2370 DeleteAllFlows(datapath);
2371 OvsReleaseDatapath(datapath, &dpLockState);
2374 NdisReleaseSpinLock(gOvsCtrlLock);
2378 #pragma warning( pop )