2 * Copyright (c) 2014 VMware, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
22 #include "PacketParser.h"
28 #define OVS_DBG_MOD OVS_DBG_FLOW
31 #pragma warning( push )
32 #pragma warning( disable:4127 )
34 extern POVS_SWITCH_CONTEXT gOvsSwitchContext;
35 extern UINT64 ovsTimeIncrementPerTick;
37 static NTSTATUS ReportFlowInfo(OvsFlow *flow, UINT32 getFlags,
39 static NTSTATUS HandleFlowPut(OvsFlowPut *put,
40 OVS_DATAPATH *datapath,
41 struct OvsFlowStats *stats);
42 static NTSTATUS OvsPrepareFlow(OvsFlow **flow, const OvsFlowPut *put,
44 static VOID RemoveFlow(OVS_DATAPATH *datapath, OvsFlow **flow);
45 static VOID DeleteAllFlows(OVS_DATAPATH *datapath);
46 static NTSTATUS AddFlow(OVS_DATAPATH *datapath, OvsFlow *flow);
47 static VOID FreeFlow(OvsFlow *flow);
48 static VOID __inline *GetStartAddrNBL(const NET_BUFFER_LIST *_pNB);
49 static NTSTATUS _MapNlToFlowPut(POVS_MESSAGE msgIn, PNL_ATTR keyAttr,
51 PNL_ATTR flowAttrClear,
52 OvsFlowPut *mappedFlow);
53 static VOID _MapKeyAttrToFlowPut(PNL_ATTR *keyAttrs,
54 PNL_ATTR *tunnelAttrs,
57 static VOID _MapTunAttrToFlowPut(PNL_ATTR *keyAttrs,
58 PNL_ATTR *tunnelAttrs,
60 static VOID _MapNlToFlowPutFlags(PGENL_MSG_HDR genlMsgHdr,
61 PNL_ATTR flowAttrClear,
62 OvsFlowPut *mappedFlow);
64 static NTSTATUS _FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
66 static NTSTATUS _FlowNlDumpCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
68 static NTSTATUS _MapFlowInfoToNl(PNL_BUFFER nlBuf,
69 OvsFlowInfo *flowInfo);
70 static NTSTATUS _MapFlowStatsToNlStats(PNL_BUFFER nlBuf,
71 OvsFlowStats *flowStats);
72 static NTSTATUS _MapFlowActionToNlAction(PNL_BUFFER nlBuf,
76 static NTSTATUS _MapFlowIpv4KeyToNlKey(PNL_BUFFER nlBuf,
77 IpKey *ipv4FlowPutKey);
78 static NTSTATUS _MapFlowIpv6KeyToNlKey(PNL_BUFFER nlBuf,
79 Ipv6Key *ipv6FlowPutKey,
80 Icmp6Key *ipv6FlowPutIcmpKey);
81 static NTSTATUS _MapFlowArpKeyToNlKey(PNL_BUFFER nlBuf,
82 ArpKey *arpFlowPutKey);
83 static NTSTATUS _MapFlowMplsKeyToNlKey(PNL_BUFFER nlBuf,
84 MplsKey *mplsFlowPutKey);
86 static NTSTATUS OvsDoDumpFlows(OvsFlowDumpInput *dumpInput,
87 OvsFlowDumpOutput *dumpOutput,
89 static NTSTATUS OvsProbeSupportedFeature(POVS_MESSAGE msgIn,
93 #define OVS_FLOW_TABLE_SIZE 2048
94 #define OVS_FLOW_TABLE_MASK (OVS_FLOW_TABLE_SIZE -1)
95 #define HASH_BUCKET(hash) ((hash) & OVS_FLOW_TABLE_MASK)
97 /* Flow family related netlink policies */
99 /* For Parsing attributes in FLOW_* commands */
100 const NL_POLICY nlFlowPolicy[] = {
101 [OVS_FLOW_ATTR_KEY] = {.type = NL_A_NESTED, .optional = FALSE},
102 [OVS_FLOW_ATTR_MASK] = {.type = NL_A_NESTED, .optional = TRUE},
103 [OVS_FLOW_ATTR_ACTIONS] = {.type = NL_A_NESTED, .optional = TRUE},
104 [OVS_FLOW_ATTR_STATS] = {.type = NL_A_UNSPEC,
105 .minLen = sizeof(struct ovs_flow_stats),
106 .maxLen = sizeof(struct ovs_flow_stats),
108 [OVS_FLOW_ATTR_TCP_FLAGS] = {NL_A_U8, .optional = TRUE},
109 [OVS_FLOW_ATTR_USED] = {NL_A_U64, .optional = TRUE},
110 [OVS_FLOW_ATTR_PROBE] = {.type = NL_A_FLAG, .optional = TRUE}
113 /* For Parsing nested OVS_FLOW_ATTR_KEY attributes.
114 * Some of the attributes like OVS_KEY_ATTR_RECIRC_ID
115 * are not supported yet. */
117 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}
179 const UINT32 nlFlowKeyPolicyLen = ARRAY_SIZE(nlFlowKeyPolicy);
181 /* For Parsing nested OVS_KEY_ATTR_TUNNEL attributes */
182 const NL_POLICY nlFlowTunnelKeyPolicy[] = {
183 [OVS_TUNNEL_KEY_ATTR_ID] = {.type = NL_A_UNSPEC, .minLen = 8,
184 .maxLen = 8, .optional = TRUE},
185 [OVS_TUNNEL_KEY_ATTR_IPV4_SRC] = {.type = NL_A_UNSPEC, .minLen = 4,
186 .maxLen = 4, .optional = TRUE},
187 [OVS_TUNNEL_KEY_ATTR_IPV4_DST] = {.type = NL_A_UNSPEC, .minLen = 4 ,
188 .maxLen = 4, .optional = FALSE},
189 [OVS_TUNNEL_KEY_ATTR_TOS] = {.type = NL_A_UNSPEC, .minLen = 1,
190 .maxLen = 1, .optional = TRUE},
191 [OVS_TUNNEL_KEY_ATTR_TTL] = {.type = NL_A_UNSPEC, .minLen = 1,
192 .maxLen = 1, .optional = TRUE},
193 [OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT] = {.type = NL_A_UNSPEC, .minLen = 0,
194 .maxLen = 0, .optional = TRUE},
195 [OVS_TUNNEL_KEY_ATTR_CSUM] = {.type = NL_A_UNSPEC, .minLen = 0,
196 .maxLen = 0, .optional = TRUE},
197 [OVS_TUNNEL_KEY_ATTR_OAM] = {.type = NL_A_UNSPEC, .minLen = 0,
198 .maxLen = 0, .optional = TRUE},
199 [OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS] = {.type = NL_A_VAR_LEN,
203 /* For Parsing nested OVS_FLOW_ATTR_ACTIONS attributes */
204 const NL_POLICY nlFlowActionPolicy[] = {
205 [OVS_ACTION_ATTR_OUTPUT] = {.type = NL_A_UNSPEC, .minLen = sizeof(UINT32),
206 .maxLen = sizeof(UINT32), .optional = TRUE},
207 [OVS_ACTION_ATTR_USERSPACE] = {.type = NL_A_VAR_LEN, .optional = TRUE},
208 [OVS_ACTION_ATTR_PUSH_VLAN] = {.type = NL_A_UNSPEC,
210 sizeof(struct ovs_action_push_vlan),
212 sizeof(struct ovs_action_push_vlan),
214 [OVS_ACTION_ATTR_POP_VLAN] = {.type = NL_A_UNSPEC, .optional = TRUE},
215 [OVS_ACTION_ATTR_PUSH_MPLS] = {.type = NL_A_UNSPEC,
217 sizeof(struct ovs_action_push_mpls),
219 sizeof(struct ovs_action_push_mpls),
221 [OVS_ACTION_ATTR_POP_MPLS] = {.type = NL_A_UNSPEC,
222 .minLen = sizeof(UINT16),
223 .maxLen = sizeof(UINT16),
225 [OVS_ACTION_ATTR_RECIRC] = {.type = NL_A_UNSPEC,
226 .minLen = sizeof(UINT32),
227 .maxLen = sizeof(UINT32),
229 [OVS_ACTION_ATTR_HASH] = {.type = NL_A_UNSPEC,
230 .minLen = sizeof(struct ovs_action_hash),
231 .maxLen = sizeof(struct ovs_action_hash),
233 [OVS_ACTION_ATTR_SET] = {.type = NL_A_VAR_LEN, .optional = TRUE},
234 [OVS_ACTION_ATTR_SAMPLE] = {.type = NL_A_VAR_LEN, .optional = TRUE}
238 *----------------------------------------------------------------------------
239 * Netlink interface for flow commands.
240 *----------------------------------------------------------------------------
244 *----------------------------------------------------------------------------
245 * OvsFlowNewCmdHandler --
246 * Handler for OVS_FLOW_CMD_NEW/SET/DEL command.
247 * It also handles FLUSH case (DEL w/o any key in input)
248 *----------------------------------------------------------------------------
251 OvsFlowNlCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
254 NTSTATUS rc = STATUS_SUCCESS;
256 POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;
257 POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer;
258 PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
259 PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
260 POVS_HDR ovsHdr = &(msgIn->ovsHdr);
261 PNL_ATTR flowAttrs[__OVS_FLOW_ATTR_MAX];
262 UINT32 attrOffset = NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN;
263 OvsFlowPut mappedFlow;
265 struct ovs_flow_stats replyStats;
266 NL_ERROR nlError = NL_ERROR_SUCCESS;
269 RtlZeroMemory(&mappedFlow, sizeof(OvsFlowPut));
270 RtlZeroMemory(&stats, sizeof(stats));
271 RtlZeroMemory(&replyStats, sizeof(replyStats));
273 if (!(usrParamsCtx->outputBuffer)) {
274 /* No output buffer */
275 rc = STATUS_INVALID_BUFFER_SIZE;
279 /* Get all the top level Flow attributes */
280 if ((NlAttrParse(nlMsgHdr, attrOffset, NlMsgAttrsLen(nlMsgHdr),
281 nlFlowPolicy, ARRAY_SIZE(nlFlowPolicy),
282 flowAttrs, ARRAY_SIZE(flowAttrs)))
284 OVS_LOG_ERROR("Attr Parsing failed for msg: %p",
286 rc = STATUS_INVALID_PARAMETER;
290 /* FLOW_DEL command w/o any key input is a flush case. */
291 if ((genlMsgHdr->cmd == OVS_FLOW_CMD_DEL) &&
292 (!(flowAttrs[OVS_FLOW_ATTR_KEY]))) {
294 rc = OvsFlushFlowIoctl(ovsHdr->dp_ifindex);
296 if (rc == STATUS_SUCCESS) {
297 /* XXX: refactor this code. */
298 /* So far so good. Prepare the reply for userspace */
299 NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
300 usrParamsCtx->outputLength);
302 /* Prepare nl Msg headers */
303 ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,
304 nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
305 genlMsgHdr->cmd, OVS_FLOW_VERSION,
308 *replyLen = msgOut->nlMsg.nlmsgLen;
310 rc = STATUS_INVALID_BUFFER_SIZE;
317 if (flowAttrs[OVS_FLOW_ATTR_PROBE]) {
318 rc = OvsProbeSupportedFeature(msgIn, flowAttrs[OVS_FLOW_ATTR_KEY]);
319 if (rc != STATUS_SUCCESS) {
320 nlError = NlMapStatusToNlErr(rc);
325 if ((rc = _MapNlToFlowPut(msgIn, flowAttrs[OVS_FLOW_ATTR_KEY],
326 flowAttrs[OVS_FLOW_ATTR_ACTIONS],
327 flowAttrs[OVS_FLOW_ATTR_CLEAR],
330 OVS_LOG_ERROR("Conversion to OvsFlowPut failed");
334 rc = OvsPutFlowIoctl(&mappedFlow, sizeof (struct OvsFlowPut),
336 if (rc != STATUS_SUCCESS) {
337 OVS_LOG_ERROR("OvsPutFlowIoctl failed.");
339 * Report back to the userspace the flow could not be modified,
342 nlError = NL_ERROR_NOENT;
346 replyStats.n_packets = stats.packetCount;
347 replyStats.n_bytes = stats.byteCount;
349 /* So far so good. Prepare the reply for userspace */
350 NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
351 usrParamsCtx->outputLength);
353 /* Prepare nl Msg headers */
354 ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,
355 nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
356 genlMsgHdr->cmd, OVS_FLOW_VERSION,
359 rc = STATUS_INVALID_BUFFER_SIZE;
365 /* Append OVS_FLOW_ATTR_KEY attribute. This is need i.e. for flow delete*/
366 if (!NlMsgPutNested(&nlBuf, OVS_FLOW_ATTR_KEY,
367 NlAttrData(flowAttrs[OVS_FLOW_ATTR_KEY]),
368 NlAttrGetSize(flowAttrs[OVS_FLOW_ATTR_KEY]))) {
369 OVS_LOG_ERROR("Adding OVS_FLOW_ATTR_KEY attribute failed.");
370 rc = STATUS_INVALID_BUFFER_SIZE;
374 /* Append OVS_FLOW_ATTR_STATS attribute */
375 if (!NlMsgPutTailUnspec(&nlBuf, OVS_FLOW_ATTR_STATS,
376 (PCHAR)(&replyStats), sizeof(replyStats))) {
377 OVS_LOG_ERROR("Adding OVS_FLOW_ATTR_STATS attribute failed.");
378 rc = STATUS_INVALID_BUFFER_SIZE;
382 msgOut->nlMsg.nlmsgLen = NLMSG_ALIGN(NlBufSize(&nlBuf));
383 *replyLen = msgOut->nlMsg.nlmsgLen;
387 if (nlError != NL_ERROR_SUCCESS) {
388 POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
389 usrParamsCtx->outputBuffer;
390 NlBuildErrorMsg(msgIn, msgError, nlError);
391 *replyLen = msgError->nlMsg.nlmsgLen;
399 *----------------------------------------------------------------------------
400 * OvsFlowNlGetCmdHandler --
401 * Handler for OVS_FLOW_CMD_GET/DUMP commands.
402 *----------------------------------------------------------------------------
405 OvsFlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
408 NTSTATUS status = STATUS_SUCCESS;
410 if (usrParamsCtx->devOp == OVS_TRANSACTION_DEV_OP) {
411 status = _FlowNlGetCmdHandler(usrParamsCtx, replyLen);
413 status = _FlowNlDumpCmdHandler(usrParamsCtx, replyLen);
420 *----------------------------------------------------------------------------
421 * _FlowNlGetCmdHandler --
422 * Handler for OVS_FLOW_CMD_GET command.
423 *----------------------------------------------------------------------------
426 _FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
429 NTSTATUS rc = STATUS_SUCCESS;
430 POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;
431 PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
432 POVS_HDR ovsHdr = &(msgIn->ovsHdr);
433 PNL_MSG_HDR nlMsgOutHdr = NULL;
434 UINT32 attrOffset = NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN;
435 PNL_ATTR nlAttrs[__OVS_FLOW_ATTR_MAX];
437 OvsFlowGetInput getInput;
438 OvsFlowGetOutput getOutput;
440 PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX];
441 PNL_ATTR tunnelAttrs[__OVS_TUNNEL_KEY_ATTR_MAX];
443 NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
444 usrParamsCtx->outputLength);
445 RtlZeroMemory(&getInput, sizeof(OvsFlowGetInput));
446 RtlZeroMemory(&getOutput, sizeof(OvsFlowGetOutput));
447 UINT32 keyAttrOffset = 0;
448 UINT32 tunnelKeyAttrOffset = 0;
450 NL_ERROR nlError = NL_ERROR_SUCCESS;
452 if (usrParamsCtx->inputLength > usrParamsCtx->outputLength) {
453 /* Should not be the case.
454 * We'll be copying the flow keys back from
455 * input buffer to output buffer. */
456 rc = STATUS_INVALID_PARAMETER;
457 OVS_LOG_ERROR("inputLength: %d GREATER THEN outputLength: %d",
458 usrParamsCtx->inputLength, usrParamsCtx->outputLength);
462 /* Get all the top level Flow attributes */
463 if ((NlAttrParse(nlMsgHdr, attrOffset, NlMsgAttrsLen(nlMsgHdr),
464 nlFlowPolicy, ARRAY_SIZE(nlFlowPolicy),
465 nlAttrs, ARRAY_SIZE(nlAttrs)))
467 OVS_LOG_ERROR("Attr Parsing failed for msg: %p",
469 rc = STATUS_INVALID_PARAMETER;
473 keyAttrOffset = (UINT32)((PCHAR) nlAttrs[OVS_FLOW_ATTR_KEY] -
476 /* Get flow keys attributes */
477 if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset,
478 NlAttrLen(nlAttrs[OVS_FLOW_ATTR_KEY]),
479 nlFlowKeyPolicy, ARRAY_SIZE(nlFlowKeyPolicy),
480 keyAttrs, ARRAY_SIZE(keyAttrs)))
482 OVS_LOG_ERROR("Key Attr Parsing failed for msg: %p",
484 rc = STATUS_INVALID_PARAMETER;
488 if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
489 tunnelKeyAttrOffset = (UINT32)((PCHAR)
490 (keyAttrs[OVS_KEY_ATTR_TUNNEL])
493 /* Get tunnel keys attributes */
494 if ((NlAttrParseNested(nlMsgHdr, tunnelKeyAttrOffset,
495 NlAttrLen(keyAttrs[OVS_KEY_ATTR_TUNNEL]),
496 nlFlowTunnelKeyPolicy,
497 ARRAY_SIZE(nlFlowTunnelKeyPolicy),
498 tunnelAttrs, ARRAY_SIZE(tunnelAttrs)))
500 OVS_LOG_ERROR("Tunnel key Attr Parsing failed for msg: %p",
502 rc = STATUS_INVALID_PARAMETER;
507 _MapKeyAttrToFlowPut(keyAttrs, tunnelAttrs,
510 getInput.dpNo = ovsHdr->dp_ifindex;
511 getInput.getFlags = FLOW_GET_STATS | FLOW_GET_ACTIONS;
513 /* 4th argument is a no op.
514 * We are keeping this argument to be compatible
515 * with our dpif-windows based interface. */
516 rc = OvsGetFlowIoctl(&getInput, &getOutput);
517 if (rc != STATUS_SUCCESS) {
518 OVS_LOG_ERROR("OvsGetFlowIoctl failed.");
520 * Report back to the userspace the flow could not be found
522 nlError = NL_ERROR_NOENT;
526 /* Lets prepare the reply. */
527 nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, 0, 0));
529 /* Input already has all the attributes for the flow key.
530 * Lets copy the values back. */
531 ok = NlMsgPutTail(&nlBuf, (PCHAR)(usrParamsCtx->inputBuffer),
532 usrParamsCtx->inputLength);
534 OVS_LOG_ERROR("Could not copy the data to the buffer tail");
538 rc = _MapFlowStatsToNlStats(&nlBuf, &((getOutput.info).stats));
539 if (rc != STATUS_SUCCESS) {
540 OVS_LOG_ERROR("_OvsFlowMapFlowKeyToNlStats failed.");
544 rc = _MapFlowActionToNlAction(&nlBuf, ((getOutput.info).actionsLen),
545 getOutput.info.actions);
546 if (rc != STATUS_SUCCESS) {
547 OVS_LOG_ERROR("_MapFlowActionToNlAction failed.");
551 NlMsgSetSize(nlMsgOutHdr, NlBufSize(&nlBuf));
552 NlMsgAlignSize(nlMsgOutHdr);
553 *replyLen += NlMsgSize(nlMsgOutHdr);
556 if (nlError != NL_ERROR_SUCCESS) {
557 POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
558 usrParamsCtx->outputBuffer;
559 NlBuildErrorMsg(msgIn, msgError, nlError);
560 *replyLen = msgError->nlMsg.nlmsgLen;
568 *----------------------------------------------------------------------------
569 * _FlowNlDumpCmdHandler --
570 * Handler for OVS_FLOW_CMD_DUMP command.
571 *----------------------------------------------------------------------------
574 _FlowNlDumpCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
577 NTSTATUS rc = STATUS_SUCCESS;
578 UINT32 temp = 0; /* To keep compiler happy for calling OvsDoDumpFlows */
579 NL_ERROR nlError = NL_ERROR_SUCCESS;
580 POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)
581 (usrParamsCtx->ovsInstance);
582 POVS_MESSAGE msgIn = instance->dumpState.ovsMsg;
584 if (usrParamsCtx->devOp == OVS_WRITE_DEV_OP) {
586 OvsSetupDumpStart(usrParamsCtx);
590 PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
591 PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
592 POVS_HDR ovsHdr = &(msgIn->ovsHdr);
593 PNL_MSG_HDR nlMsgOutHdr = NULL;
594 UINT32 hdrOffset = 0;
597 OvsFlowDumpOutput dumpOutput;
598 OvsFlowDumpInput dumpInput;
601 NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
602 usrParamsCtx->outputLength);
604 ASSERT(usrParamsCtx->devOp == OVS_READ_DEV_OP);
605 ASSERT(usrParamsCtx->outputLength);
607 RtlZeroMemory(&dumpInput, sizeof(OvsFlowDumpInput));
608 RtlZeroMemory(&dumpOutput, sizeof(OvsFlowDumpOutput));
610 dumpInput.dpNo = ovsHdr->dp_ifindex;
611 dumpInput.getFlags = FLOW_GET_KEY | FLOW_GET_STATS | FLOW_GET_ACTIONS;
613 /* Lets provide as many flows to userspace as possible. */
615 dumpInput.position[0] = instance->dumpState.index[0];
616 dumpInput.position[1] = instance->dumpState.index[1];
618 rc = OvsDoDumpFlows(&dumpInput, &dumpOutput, &temp);
619 if (rc != STATUS_SUCCESS) {
620 OVS_LOG_ERROR("OvsDoDumpFlows failed with rc: %d", rc);
622 * Report back to the userspace the flows could not be found
624 nlError = NL_ERROR_NOENT;
628 /* Done with Dump, send NLMSG_DONE */
629 if (!(dumpOutput.n)) {
632 OVS_LOG_INFO("Dump Done");
634 nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, NlBufSize(&nlBuf), 0));
635 ok = NlFillNlHdr(&nlBuf, NLMSG_DONE, NLM_F_MULTI,
636 nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid);
639 rc = STATUS_INVALID_BUFFER_SIZE;
640 OVS_LOG_ERROR("Unable to prepare DUMP_DONE reply.");
646 NlMsgAlignSize(nlMsgOutHdr);
647 *replyLen += NlMsgSize(nlMsgOutHdr);
649 FreeUserDumpState(instance);
654 hdrOffset = NlBufSize(&nlBuf);
655 nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, hdrOffset, 0));
658 ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, NLM_F_MULTI,
659 nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
660 genlMsgHdr->cmd, genlMsgHdr->version,
664 /* Reset rc to success so that we can
665 * send already added messages to user space. */
670 /* Time to add attributes */
671 rc = _MapFlowInfoToNl(&nlBuf, &(dumpOutput.flow));
672 if (rc != STATUS_SUCCESS) {
673 /* Adding the attribute failed, we are out of
674 space in the buffer, remove the appended OVS header */
675 NlMsgSetSize(nlMsgOutHdr,
676 NlMsgSize(nlMsgOutHdr) -
677 sizeof(struct _OVS_MESSAGE));
679 /* Reset rc to success so that we can
680 * send already added messages to user space. */
685 NlMsgSetSize(nlMsgOutHdr, NlBufSize(&nlBuf) - hdrOffset);
686 NlMsgAlignSize(nlMsgOutHdr);
687 *replyLen += NlMsgSize(nlMsgOutHdr);
688 instance->dumpState.index[0] = dumpOutput.position[0];
689 instance->dumpState.index[1] = dumpOutput.position[1];
694 if (nlError != NL_ERROR_SUCCESS) {
695 POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
696 usrParamsCtx->outputBuffer;
697 NlBuildErrorMsg(msgIn, msgError, nlError);
698 *replyLen = msgError->nlMsg.nlmsgLen;
706 *----------------------------------------------------------------------------
707 * _MapFlowInfoToNl --
708 * Maps OvsFlowInfo to Netlink attributes.
709 *----------------------------------------------------------------------------
712 _MapFlowInfoToNl(PNL_BUFFER nlBuf, OvsFlowInfo *flowInfo)
714 NTSTATUS rc = STATUS_SUCCESS;
716 rc = MapFlowKeyToNlKey(nlBuf, &(flowInfo->key), OVS_FLOW_ATTR_KEY,
717 OVS_KEY_ATTR_TUNNEL);
718 if (rc != STATUS_SUCCESS) {
722 rc = _MapFlowStatsToNlStats(nlBuf, &(flowInfo->stats));
723 if (rc != STATUS_SUCCESS) {
727 rc = _MapFlowActionToNlAction(nlBuf, flowInfo->actionsLen,
729 if (rc != STATUS_SUCCESS) {
738 *----------------------------------------------------------------------------
739 * _MapFlowStatsToNlStats --
740 * Maps OvsFlowStats to OVS_FLOW_ATTR_STATS attribute.
741 *----------------------------------------------------------------------------
744 _MapFlowStatsToNlStats(PNL_BUFFER nlBuf, OvsFlowStats *flowStats)
746 NTSTATUS rc = STATUS_SUCCESS;
747 struct ovs_flow_stats replyStats;
749 replyStats.n_packets = flowStats->packetCount;
750 replyStats.n_bytes = flowStats->byteCount;
752 if (!NlMsgPutTailU64(nlBuf, OVS_FLOW_ATTR_USED, flowStats->used)) {
753 rc = STATUS_INVALID_BUFFER_SIZE;
757 if (!NlMsgPutTailUnspec(nlBuf, OVS_FLOW_ATTR_STATS,
758 (PCHAR)(&replyStats),
759 sizeof(struct ovs_flow_stats))) {
760 rc = STATUS_INVALID_BUFFER_SIZE;
764 if (!NlMsgPutTailU8(nlBuf, OVS_FLOW_ATTR_TCP_FLAGS, flowStats->tcpFlags)) {
765 rc = STATUS_INVALID_BUFFER_SIZE;
774 *----------------------------------------------------------------------------
775 * _MapFlowActionToNlAction --
776 * Maps flow actions to OVS_FLOW_ATTR_ACTION attribute.
777 *----------------------------------------------------------------------------
780 _MapFlowActionToNlAction(PNL_BUFFER nlBuf, uint32_t actionsLen,
783 NTSTATUS rc = STATUS_SUCCESS;
786 offset = NlMsgStartNested(nlBuf, OVS_FLOW_ATTR_ACTIONS);
788 /* Starting the nested attribute failed. */
789 rc = STATUS_INVALID_BUFFER_SIZE;
790 goto error_nested_start;
793 if (!NlBufCopyAtTail(nlBuf, (PCHAR)actions, actionsLen)) {
794 /* Adding a nested attribute failed. */
795 rc = STATUS_INVALID_BUFFER_SIZE;
800 NlMsgEndNested(nlBuf, offset);
807 *----------------------------------------------------------------------------
808 * MapFlowKeyToNlKey --
809 * Maps OvsFlowKey to OVS_FLOW_ATTR_KEY attribute.
810 *----------------------------------------------------------------------------
813 MapFlowKeyToNlKey(PNL_BUFFER nlBuf,
818 NTSTATUS rc = STATUS_SUCCESS;
819 struct ovs_key_ethernet ethKey;
822 offset = NlMsgStartNested(nlBuf, keyType);
824 /* Starting the nested attribute failed. */
825 rc = STATUS_UNSUCCESSFUL;
826 goto error_nested_start;
829 /* Ethernet header */
830 RtlCopyMemory(&(ethKey.eth_src), flowKey->l2.dlSrc, ETH_ADDR_LEN);
831 RtlCopyMemory(&(ethKey.eth_dst), flowKey->l2.dlDst, ETH_ADDR_LEN);
833 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ETHERNET,
835 sizeof(struct ovs_key_ethernet))) {
836 rc = STATUS_UNSUCCESSFUL;
840 if (!NlMsgPutTailU32(nlBuf, OVS_KEY_ATTR_IN_PORT,
841 flowKey->l2.inPort)) {
842 rc = STATUS_UNSUCCESSFUL;
846 if (!NlMsgPutTailU16(nlBuf, OVS_KEY_ATTR_ETHERTYPE,
847 flowKey->l2.dlType)) {
848 rc = STATUS_UNSUCCESSFUL;
852 if (flowKey->l2.vlanTci) {
853 if (!NlMsgPutTailU16(nlBuf, OVS_KEY_ATTR_VLAN,
854 flowKey->l2.vlanTci)) {
855 rc = STATUS_UNSUCCESSFUL;
860 /* ==== L3 + L4 ==== */
861 switch (ntohs(flowKey->l2.dlType)) {
862 case ETH_TYPE_IPV4: {
863 IpKey *ipv4FlowPutKey = &(flowKey->ipKey);
864 rc = _MapFlowIpv4KeyToNlKey(nlBuf, ipv4FlowPutKey);
868 case ETH_TYPE_IPV6: {
869 Ipv6Key *ipv6FlowPutKey = &(flowKey->ipv6Key);
870 Icmp6Key *icmpv6FlowPutKey = &(flowKey->icmp6Key);
871 rc = _MapFlowIpv6KeyToNlKey(nlBuf, ipv6FlowPutKey,
877 case ETH_TYPE_RARP: {
878 ArpKey *arpFlowPutKey = &(flowKey->arpKey);
879 rc = _MapFlowArpKeyToNlKey(nlBuf, arpFlowPutKey);
884 case ETH_TYPE_MPLS_MCAST: {
885 MplsKey *mplsFlowPutKey = &(flowKey->mplsKey);
886 rc = _MapFlowMplsKeyToNlKey(nlBuf, mplsFlowPutKey);
894 if (rc != STATUS_SUCCESS) {
898 if (flowKey->tunKey.dst) {
899 rc = MapFlowTunKeyToNlKey(nlBuf, &(flowKey->tunKey),
901 if (rc != STATUS_SUCCESS) {
907 NlMsgEndNested(nlBuf, offset);
913 *----------------------------------------------------------------------------
914 * MapFlowTunKeyToNlKey --
915 * Maps OvsIPv4TunnelKey to OVS_TUNNEL_KEY_ATTR_ID attribute.
916 *----------------------------------------------------------------------------
919 MapFlowTunKeyToNlKey(PNL_BUFFER nlBuf,
920 OvsIPv4TunnelKey *tunKey,
923 NTSTATUS rc = STATUS_SUCCESS;
926 offset = NlMsgStartNested(nlBuf, tunKeyType);
928 /* Starting the nested attribute failed. */
929 rc = STATUS_UNSUCCESSFUL;
930 goto error_nested_start;
933 if (!NlMsgPutTailU64(nlBuf, OVS_TUNNEL_KEY_ATTR_ID,
935 rc = STATUS_UNSUCCESSFUL;
939 if (!NlMsgPutTailU32(nlBuf, OVS_TUNNEL_KEY_ATTR_IPV4_DST,
941 rc = STATUS_UNSUCCESSFUL;
945 if (!NlMsgPutTailU32(nlBuf, OVS_TUNNEL_KEY_ATTR_IPV4_SRC,
947 rc = STATUS_UNSUCCESSFUL;
951 if (!NlMsgPutTailU8(nlBuf, OVS_TUNNEL_KEY_ATTR_TOS,
953 rc = STATUS_UNSUCCESSFUL;
957 if (!NlMsgPutTailU8(nlBuf, OVS_TUNNEL_KEY_ATTR_TTL,
959 rc = STATUS_UNSUCCESSFUL;
964 NlMsgEndNested(nlBuf, offset);
970 *----------------------------------------------------------------------------
971 * _MapFlowTunKeyToNlKey --
972 * Maps OvsIPv4FlowPutKey to OVS_KEY_ATTR_IPV4 attribute.
973 *----------------------------------------------------------------------------
976 _MapFlowIpv4KeyToNlKey(PNL_BUFFER nlBuf, IpKey *ipv4FlowPutKey)
978 NTSTATUS rc = STATUS_SUCCESS;
979 struct ovs_key_ipv4 ipv4Key;
981 ipv4Key.ipv4_src = ipv4FlowPutKey->nwSrc;
982 ipv4Key.ipv4_dst = ipv4FlowPutKey->nwDst;
983 ipv4Key.ipv4_proto = ipv4FlowPutKey->nwProto;
984 ipv4Key.ipv4_tos = ipv4FlowPutKey->nwTos;
985 ipv4Key.ipv4_ttl = ipv4FlowPutKey->nwTtl;
986 ipv4Key.ipv4_frag = ipv4FlowPutKey->nwFrag;
988 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_IPV4,
990 sizeof(struct ovs_key_ipv4))) {
991 rc = STATUS_UNSUCCESSFUL;
995 switch (ipv4Key.ipv4_proto) {
997 struct ovs_key_tcp tcpKey;
998 tcpKey.tcp_src = ipv4FlowPutKey->l4.tpSrc;
999 tcpKey.tcp_dst = ipv4FlowPutKey->l4.tpDst;
1000 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_TCP,
1003 rc = STATUS_UNSUCCESSFUL;
1010 struct ovs_key_udp udpKey;
1011 udpKey.udp_src = ipv4FlowPutKey->l4.tpSrc;
1012 udpKey.udp_dst = ipv4FlowPutKey->l4.tpDst;
1013 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_UDP,
1016 rc = STATUS_UNSUCCESSFUL;
1022 case IPPROTO_SCTP: {
1023 struct ovs_key_sctp sctpKey;
1024 sctpKey.sctp_src = ipv4FlowPutKey->l4.tpSrc;
1025 sctpKey.sctp_dst = ipv4FlowPutKey->l4.tpDst;
1026 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_SCTP,
1029 rc = STATUS_UNSUCCESSFUL;
1035 case IPPROTO_ICMP: {
1036 struct ovs_key_icmp icmpKey;
1037 /* XXX: revisit to see if htons is needed */
1038 icmpKey.icmp_type = (__u8)(ipv4FlowPutKey->l4.tpSrc);
1039 icmpKey.icmp_code = (__u8)(ipv4FlowPutKey->l4.tpDst);
1041 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ICMP,
1044 rc = STATUS_UNSUCCESSFUL;
1059 *----------------------------------------------------------------------------
1060 * _MapFlowIpv6KeyToNlKey --
1061 * Maps _MapFlowIpv6KeyToNlKey to OVS_KEY_ATTR_IPV6 attribute.
1062 *----------------------------------------------------------------------------
1065 _MapFlowIpv6KeyToNlKey(PNL_BUFFER nlBuf, Ipv6Key *ipv6FlowPutKey,
1066 Icmp6Key *icmpv6FlowPutKey)
1068 NTSTATUS rc = STATUS_SUCCESS;
1069 struct ovs_key_ipv6 ipv6Key;
1071 RtlCopyMemory(&(ipv6Key.ipv6_src), &ipv6FlowPutKey->ipv6Src,
1072 sizeof ipv6Key.ipv6_src);
1073 RtlCopyMemory(&(ipv6Key.ipv6_dst), &ipv6FlowPutKey->ipv6Dst,
1074 sizeof ipv6Key.ipv6_dst);
1076 ipv6Key.ipv6_label = ipv6FlowPutKey->ipv6Label;
1077 ipv6Key.ipv6_proto = ipv6FlowPutKey->nwProto;
1078 ipv6Key.ipv6_tclass = ipv6FlowPutKey->nwTos;
1079 ipv6Key.ipv6_hlimit = ipv6FlowPutKey->nwTtl;
1080 ipv6Key.ipv6_frag = ipv6FlowPutKey->nwFrag;
1082 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_IPV6,
1085 rc = STATUS_UNSUCCESSFUL;
1089 switch (ipv6Key.ipv6_proto) {
1091 struct ovs_key_tcp tcpKey;
1092 tcpKey.tcp_src = ipv6FlowPutKey->l4.tpSrc;
1093 tcpKey.tcp_dst = ipv6FlowPutKey->l4.tpDst;
1094 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_TCP,
1097 rc = STATUS_UNSUCCESSFUL;
1104 struct ovs_key_udp udpKey;
1105 udpKey.udp_src = ipv6FlowPutKey->l4.tpSrc;
1106 udpKey.udp_dst = ipv6FlowPutKey->l4.tpDst;
1107 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_UDP,
1110 rc = STATUS_UNSUCCESSFUL;
1116 case IPPROTO_SCTP: {
1117 struct ovs_key_sctp sctpKey;
1118 sctpKey.sctp_src = ipv6FlowPutKey->l4.tpSrc;
1119 sctpKey.sctp_dst = ipv6FlowPutKey->l4.tpDst;
1120 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_SCTP,
1123 rc = STATUS_UNSUCCESSFUL;
1129 case IPPROTO_ICMPV6: {
1130 struct ovs_key_icmpv6 icmpV6Key;
1131 struct ovs_key_nd ndKey;
1133 /* XXX: revisit to see if htons is needed */
1134 icmpV6Key.icmpv6_type = (__u8)(icmpv6FlowPutKey->l4.tpSrc);
1135 icmpV6Key.icmpv6_code = (__u8)(icmpv6FlowPutKey->l4.tpDst);
1137 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ICMPV6,
1138 (PCHAR)(&icmpV6Key),
1139 sizeof(icmpV6Key))) {
1140 rc = STATUS_UNSUCCESSFUL;
1144 RtlCopyMemory(&(ndKey.nd_target), &icmpv6FlowPutKey->ndTarget,
1145 sizeof(icmpv6FlowPutKey->ndTarget));
1146 RtlCopyMemory(&(ndKey.nd_sll), &icmpv6FlowPutKey->arpSha,
1148 RtlCopyMemory(&(ndKey.nd_tll), &icmpv6FlowPutKey->arpTha,
1150 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ND,
1153 rc = STATUS_UNSUCCESSFUL;
1169 *----------------------------------------------------------------------------
1170 * _MapFlowArpKeyToNlKey --
1171 * Maps _MapFlowArpKeyToNlKey to OVS_KEY_ATTR_ARP attribute.
1172 *----------------------------------------------------------------------------
1175 _MapFlowArpKeyToNlKey(PNL_BUFFER nlBuf, ArpKey *arpFlowPutKey)
1177 NTSTATUS rc = STATUS_SUCCESS;
1178 struct ovs_key_arp arpKey;
1180 arpKey.arp_sip = arpFlowPutKey->nwSrc;
1181 arpKey.arp_tip = arpFlowPutKey->nwDst;
1183 RtlCopyMemory(&(arpKey.arp_sha), arpFlowPutKey->arpSha, ETH_ADDR_LEN);
1184 RtlCopyMemory(&(arpKey.arp_tha), arpFlowPutKey->arpTha, ETH_ADDR_LEN);
1187 * Flow_Extract() stores 'nwProto' in host order for ARP since 'nwProto' is
1188 * 1 byte field and the ARP opcode is 2 bytes, and all of the kernel code
1189 * understand this while looking at an ARP key.
1190 * While we pass up the ARP key to userspace, convert from host order to
1191 * network order. Likewise, when processing an ARP key from userspace,
1192 * convert from network order to host order.
1194 * It is important to note that the flow table stores the ARP opcode field
1197 arpKey.arp_op = htons(arpFlowPutKey->nwProto);
1199 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ARP,
1202 rc = STATUS_UNSUCCESSFUL;
1211 *----------------------------------------------------------------------------
1212 * _MapFlowMplsKeyToNlKey --
1213 * Maps _MapFlowMplsKeyToNlKey to OVS_KEY_ATTR_MPLS attribute.
1214 *----------------------------------------------------------------------------
1217 _MapFlowMplsKeyToNlKey(PNL_BUFFER nlBuf, MplsKey *mplsFlowPutKey)
1219 NTSTATUS rc = STATUS_SUCCESS;
1220 struct ovs_key_mpls *mplsKey;
1222 mplsKey = (struct ovs_key_mpls *)
1223 NlMsgPutTailUnspecUninit(nlBuf, OVS_KEY_ATTR_MPLS, sizeof(*mplsKey));
1225 rc = STATUS_UNSUCCESSFUL;
1229 mplsKey->mpls_lse = mplsFlowPutKey->lse;
1236 *----------------------------------------------------------------------------
1237 * _MapNlToFlowPut --
1238 * Maps input netlink message to OvsFlowPut.
1239 *----------------------------------------------------------------------------
1242 _MapNlToFlowPut(POVS_MESSAGE msgIn, PNL_ATTR keyAttr,
1243 PNL_ATTR actionAttr, PNL_ATTR flowAttrClear,
1244 OvsFlowPut *mappedFlow)
1246 NTSTATUS rc = STATUS_SUCCESS;
1247 PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
1248 PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
1249 POVS_HDR ovsHdr = &(msgIn->ovsHdr);
1251 UINT32 keyAttrOffset = (UINT32)((PCHAR)keyAttr - (PCHAR)nlMsgHdr);
1252 UINT32 tunnelKeyAttrOffset;
1254 PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX] = {NULL};
1255 PNL_ATTR tunnelAttrs[__OVS_TUNNEL_KEY_ATTR_MAX] = {NULL};
1257 /* Get flow keys attributes */
1258 if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset, NlAttrLen(keyAttr),
1259 nlFlowKeyPolicy, ARRAY_SIZE(nlFlowKeyPolicy),
1260 keyAttrs, ARRAY_SIZE(keyAttrs)))
1262 OVS_LOG_ERROR("Key Attr Parsing failed for msg: %p",
1264 rc = STATUS_INVALID_PARAMETER;
1268 if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
1269 tunnelKeyAttrOffset = (UINT32)((PCHAR)
1270 (keyAttrs[OVS_KEY_ATTR_TUNNEL])
1273 /* Get tunnel keys attributes */
1274 if ((NlAttrParseNested(nlMsgHdr, tunnelKeyAttrOffset,
1275 NlAttrLen(keyAttrs[OVS_KEY_ATTR_TUNNEL]),
1276 nlFlowTunnelKeyPolicy,
1277 ARRAY_SIZE(nlFlowTunnelKeyPolicy),
1278 tunnelAttrs, ARRAY_SIZE(tunnelAttrs)))
1280 OVS_LOG_ERROR("Tunnel key Attr Parsing failed for msg: %p",
1282 rc = STATUS_INVALID_PARAMETER;
1287 _MapKeyAttrToFlowPut(keyAttrs, tunnelAttrs,
1288 &(mappedFlow->key));
1290 /* Map the action */
1292 mappedFlow->actionsLen = NlAttrGetSize(actionAttr);
1293 mappedFlow->actions = NlAttrGet(actionAttr);
1296 mappedFlow->dpNo = ovsHdr->dp_ifindex;
1298 _MapNlToFlowPutFlags(genlMsgHdr, flowAttrClear,
1306 *----------------------------------------------------------------------------
1307 * _MapNlToFlowPutFlags --
1308 * Maps netlink message to OvsFlowPut->flags.
1309 *----------------------------------------------------------------------------
1312 _MapNlToFlowPutFlags(PGENL_MSG_HDR genlMsgHdr,
1313 PNL_ATTR flowAttrClear, OvsFlowPut *mappedFlow)
1317 switch (genlMsgHdr->cmd) {
1318 case OVS_FLOW_CMD_NEW:
1319 flags |= OVSWIN_FLOW_PUT_CREATE;
1321 case OVS_FLOW_CMD_DEL:
1322 flags |= OVSWIN_FLOW_PUT_DELETE;
1324 case OVS_FLOW_CMD_SET:
1325 flags |= OVSWIN_FLOW_PUT_MODIFY;
1331 if (flowAttrClear) {
1332 flags |= OVSWIN_FLOW_PUT_CLEAR;
1335 mappedFlow->flags = flags;
1339 *----------------------------------------------------------------------------
1340 * _MapKeyAttrToFlowPut --
1341 * Converts FLOW_KEY attribute to OvsFlowPut->key.
1342 *----------------------------------------------------------------------------
1345 _MapKeyAttrToFlowPut(PNL_ATTR *keyAttrs,
1346 PNL_ATTR *tunnelAttrs,
1347 OvsFlowKey *destKey)
1349 _MapTunAttrToFlowPut(keyAttrs, tunnelAttrs, destKey);
1351 /* ===== L2 headers ===== */
1352 destKey->l2.inPort = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_IN_PORT]);
1354 if (keyAttrs[OVS_KEY_ATTR_ETHERNET]) {
1355 const struct ovs_key_ethernet *eth_key;
1356 eth_key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ETHERNET]);
1357 RtlCopyMemory(destKey->l2.dlSrc, eth_key->eth_src, ETH_ADDR_LEN);
1358 RtlCopyMemory(destKey->l2.dlDst, eth_key->eth_dst, ETH_ADDR_LEN);
1361 /* TODO: Ideally ETHERTYPE should not be optional.
1362 * But during vswitchd bootup we are seeing FLOW_ADD
1363 * requests with no ETHERTYPE attributes.
1364 * Need to verify this. */
1365 if (keyAttrs[OVS_KEY_ATTR_ETHERTYPE]) {
1366 destKey->l2.dlType = (NlAttrGetU16(keyAttrs
1367 [OVS_KEY_ATTR_ETHERTYPE]));
1370 if (keyAttrs[OVS_KEY_ATTR_VLAN]) {
1371 destKey->l2.vlanTci = NlAttrGetU16(keyAttrs[OVS_KEY_ATTR_VLAN]);
1374 /* ==== L3 + L4. ==== */
1375 destKey->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + OVS_L2_KEY_SIZE
1376 - destKey->l2.offset;
1378 switch (ntohs(destKey->l2.dlType)) {
1379 case ETH_TYPE_IPV4: {
1381 if (keyAttrs[OVS_KEY_ATTR_IPV4]) {
1382 const struct ovs_key_ipv4 *ipv4Key;
1384 ipv4Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_IPV4]);
1385 IpKey *ipv4FlowPutKey = &(destKey->ipKey);
1386 ipv4FlowPutKey->nwSrc = ipv4Key->ipv4_src;
1387 ipv4FlowPutKey->nwDst = ipv4Key->ipv4_dst;
1388 ipv4FlowPutKey->nwProto = ipv4Key->ipv4_proto;
1389 ipv4FlowPutKey->nwTos = ipv4Key->ipv4_tos;
1390 ipv4FlowPutKey->nwTtl = ipv4Key->ipv4_ttl;
1391 ipv4FlowPutKey->nwFrag = ipv4Key->ipv4_frag;
1393 if (keyAttrs[OVS_KEY_ATTR_TCP]) {
1394 const struct ovs_key_tcp *tcpKey;
1395 tcpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_TCP]);
1396 ipv4FlowPutKey->l4.tpSrc = tcpKey->tcp_src;
1397 ipv4FlowPutKey->l4.tpDst = tcpKey->tcp_dst;
1400 if (keyAttrs[OVS_KEY_ATTR_UDP]) {
1401 const struct ovs_key_udp *udpKey;
1402 udpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_UDP]);
1403 ipv4FlowPutKey->l4.tpSrc = udpKey->udp_src;
1404 ipv4FlowPutKey->l4.tpDst = udpKey->udp_dst;
1407 if (keyAttrs[OVS_KEY_ATTR_SCTP]) {
1408 const struct ovs_key_sctp *sctpKey;
1409 sctpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_SCTP]);
1410 ipv4FlowPutKey->l4.tpSrc = sctpKey->sctp_src;
1411 ipv4FlowPutKey->l4.tpDst = sctpKey->sctp_dst;
1414 destKey->l2.keyLen += OVS_IP_KEY_SIZE;
1418 case ETH_TYPE_IPV6: {
1420 if (keyAttrs[OVS_KEY_ATTR_IPV6]) {
1421 const struct ovs_key_ipv6 *ipv6Key;
1423 ipv6Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_IPV6]);
1424 Ipv6Key *ipv6FlowPutKey = &(destKey->ipv6Key);
1426 RtlCopyMemory(&ipv6FlowPutKey->ipv6Src, ipv6Key->ipv6_src,
1427 sizeof ipv6Key->ipv6_src);
1428 RtlCopyMemory(&ipv6FlowPutKey->ipv6Dst, ipv6Key->ipv6_dst,
1429 sizeof ipv6Key->ipv6_dst);
1431 ipv6FlowPutKey->ipv6Label = ipv6Key->ipv6_label;
1432 ipv6FlowPutKey->nwProto = ipv6Key->ipv6_proto;
1433 ipv6FlowPutKey->nwTos = ipv6Key->ipv6_tclass;
1434 ipv6FlowPutKey->nwTtl = ipv6Key->ipv6_hlimit;
1435 ipv6FlowPutKey->nwFrag = ipv6Key->ipv6_frag;
1437 if (keyAttrs[OVS_KEY_ATTR_TCP]) {
1438 const struct ovs_key_tcp *tcpKey;
1439 tcpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_TCP]);
1440 ipv6FlowPutKey->l4.tpSrc = tcpKey->tcp_src;
1441 ipv6FlowPutKey->l4.tpDst = tcpKey->tcp_dst;
1444 if (keyAttrs[OVS_KEY_ATTR_UDP]) {
1445 const struct ovs_key_udp *udpKey;
1446 udpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_UDP]);
1447 ipv6FlowPutKey->l4.tpSrc = udpKey->udp_src;
1448 ipv6FlowPutKey->l4.tpDst = udpKey->udp_dst;
1451 if (keyAttrs[OVS_KEY_ATTR_SCTP]) {
1452 const struct ovs_key_sctp *sctpKey;
1453 sctpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_SCTP]);
1454 ipv6FlowPutKey->l4.tpSrc = sctpKey->sctp_src;
1455 ipv6FlowPutKey->l4.tpDst = sctpKey->sctp_dst;
1458 if (keyAttrs[OVS_KEY_ATTR_ICMPV6]) {
1459 const struct ovs_key_icmpv6 *icmpv6Key;
1461 Icmp6Key *icmp6FlowPutKey= &(destKey->icmp6Key);
1463 icmpv6Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ICMPV6]);
1465 icmp6FlowPutKey->l4.tpSrc = icmpv6Key->icmpv6_type;
1466 icmp6FlowPutKey->l4.tpDst = icmpv6Key->icmpv6_code;
1468 if (keyAttrs[OVS_KEY_ATTR_ND]) {
1469 const struct ovs_key_nd *ndKey;
1471 ndKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ND]);
1472 RtlCopyMemory(&icmp6FlowPutKey->ndTarget,
1473 ndKey->nd_target, sizeof (icmp6FlowPutKey->ndTarget));
1474 RtlCopyMemory(icmp6FlowPutKey->arpSha,
1475 ndKey->nd_sll, ETH_ADDR_LEN);
1476 RtlCopyMemory(icmp6FlowPutKey->arpTha,
1477 ndKey->nd_tll, ETH_ADDR_LEN);
1480 destKey->l2.keyLen += OVS_ICMPV6_KEY_SIZE;
1484 destKey->l2.keyLen += OVS_IPV6_KEY_SIZE;
1487 ipv6FlowPutKey->pad = 0;
1492 case ETH_TYPE_RARP: {
1494 if (keyAttrs[OVS_KEY_ATTR_ARP]) {
1495 ArpKey *arpFlowPutKey = &destKey->arpKey;
1496 const struct ovs_key_arp *arpKey;
1498 arpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ARP]);
1500 arpFlowPutKey->nwSrc = arpKey->arp_sip;
1501 arpFlowPutKey->nwDst = arpKey->arp_tip;
1503 RtlCopyMemory(arpFlowPutKey->arpSha, arpKey->arp_sha, ETH_ADDR_LEN);
1504 RtlCopyMemory(arpFlowPutKey->arpTha, arpKey->arp_tha, ETH_ADDR_LEN);
1505 /* Kernel datapath assumes 'arpFlowPutKey->nwProto' to be in host
1507 arpFlowPutKey->nwProto = (UINT8)ntohs((arpKey->arp_op));
1508 arpFlowPutKey->pad[0] = 0;
1509 arpFlowPutKey->pad[1] = 0;
1510 arpFlowPutKey->pad[2] = 0;
1511 destKey->l2.keyLen += OVS_ARP_KEY_SIZE;
1516 case ETH_TYPE_MPLS_MCAST: {
1518 if (keyAttrs[OVS_KEY_ATTR_MPLS]) {
1519 MplsKey *mplsFlowPutKey = &destKey->mplsKey;
1520 const struct ovs_key_mpls *mplsKey;
1522 mplsKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_MPLS]);
1524 mplsFlowPutKey->lse = mplsKey->mpls_lse;
1525 mplsFlowPutKey->pad[0] = 0;
1526 mplsFlowPutKey->pad[1] = 0;
1527 mplsFlowPutKey->pad[2] = 0;
1528 mplsFlowPutKey->pad[3] = 0;
1529 destKey->l2.keyLen += sizeof(MplsKey);
1537 *----------------------------------------------------------------------------
1538 * _MapTunAttrToFlowPut --
1539 * Converts FLOW_TUNNEL_KEY attribute to OvsFlowKey->tunKey.
1540 *----------------------------------------------------------------------------
1543 _MapTunAttrToFlowPut(PNL_ATTR *keyAttrs,
1545 OvsFlowKey *destKey)
1547 if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
1549 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_ID]) {
1550 destKey->tunKey.tunnelId = NlAttrGetU64
1551 (tunAttrs[OVS_TUNNEL_KEY_ATTR_ID]);
1552 destKey->tunKey.flags |= OVS_TNL_F_KEY;
1555 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_DST]) {
1556 destKey->tunKey.dst = NlAttrGetU32
1557 (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_DST]);
1560 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_SRC]) {
1561 destKey->tunKey.src = NlAttrGetU32
1562 (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_SRC]);
1565 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT]) {
1566 destKey->tunKey.flags |= OVS_TNL_F_DONT_FRAGMENT;
1569 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_CSUM]) {
1570 destKey->tunKey.flags |= OVS_TNL_F_CSUM;
1573 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_TOS]) {
1574 destKey->tunKey.tos = NlAttrGetU8
1575 (tunAttrs[OVS_TUNNEL_KEY_ATTR_TOS]);
1578 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_TTL]) {
1579 destKey->tunKey.ttl = NlAttrGetU8
1580 (tunAttrs[OVS_TUNNEL_KEY_ATTR_TTL]);
1583 destKey->tunKey.pad = 0;
1584 destKey->l2.offset = 0;
1586 destKey->tunKey.attr[0] = 0;
1587 destKey->tunKey.attr[1] = 0;
1588 destKey->tunKey.attr[2] = 0;
1589 destKey->l2.offset = sizeof destKey->tunKey;
1594 *----------------------------------------------------------------------------
1595 * OvsDeleteFlowTable --
1597 * NDIS_STATUS_SUCCESS always.
1598 *----------------------------------------------------------------------------
1601 OvsDeleteFlowTable(OVS_DATAPATH *datapath)
1603 if (datapath == NULL || datapath->flowTable == NULL) {
1604 return NDIS_STATUS_SUCCESS;
1607 DeleteAllFlows(datapath);
1608 OvsFreeMemoryWithTag(datapath->flowTable, OVS_FLOW_POOL_TAG);
1609 datapath->flowTable = NULL;
1611 if (datapath->lock == NULL) {
1612 return NDIS_STATUS_SUCCESS;
1615 NdisFreeRWLock(datapath->lock);
1617 return NDIS_STATUS_SUCCESS;
1621 *----------------------------------------------------------------------------
1622 * OvsAllocateFlowTable --
1624 * NDIS_STATUS_SUCCESS on success.
1625 * NDIS_STATUS_RESOURCES if memory couldn't be allocated
1626 *----------------------------------------------------------------------------
1629 OvsAllocateFlowTable(OVS_DATAPATH *datapath,
1630 POVS_SWITCH_CONTEXT switchContext)
1635 datapath->flowTable = OvsAllocateMemoryWithTag(
1636 OVS_FLOW_TABLE_SIZE * sizeof(LIST_ENTRY), OVS_FLOW_POOL_TAG);
1637 if (!datapath->flowTable) {
1638 return NDIS_STATUS_RESOURCES;
1640 for (i = 0; i < OVS_FLOW_TABLE_SIZE; i++) {
1641 bucket = &(datapath->flowTable[i]);
1642 InitializeListHead(bucket);
1644 datapath->lock = NdisAllocateRWLock(switchContext->NdisFilterHandle);
1646 if (!datapath->lock) {
1647 return NDIS_STATUS_RESOURCES;
1650 return NDIS_STATUS_SUCCESS;
1655 *----------------------------------------------------------------------------
1656 * GetStartAddrNBL --
1657 * Get the virtual address of the frame.
1660 * Virtual address of the frame.
1661 *----------------------------------------------------------------------------
1663 static __inline VOID *
1664 GetStartAddrNBL(const NET_BUFFER_LIST *_pNB)
1672 // Ethernet Header is a guaranteed safe access.
1673 curMdl = (NET_BUFFER_LIST_FIRST_NB(_pNB))->CurrentMdl;
1674 curBuffer = MmGetSystemAddressForMdlSafe(curMdl, LowPagePriority);
1679 curHeader = (PEthHdr)
1680 (curBuffer + (NET_BUFFER_LIST_FIRST_NB(_pNB))->CurrentMdlOffset);
1682 return (VOID *) curHeader;
1686 OvsFlowUsed(OvsFlow *flow,
1687 const NET_BUFFER_LIST *packet,
1688 const POVS_PACKET_HDR_INFO layers)
1690 LARGE_INTEGER tickCount;
1692 KeQueryTickCount(&tickCount);
1693 flow->used = tickCount.QuadPart * ovsTimeIncrementPerTick;
1694 flow->packetCount++;
1695 flow->byteCount += OvsPacketLenNBL(packet);
1696 flow->tcpFlags |= OvsGetTcpFlags(packet, &flow->key, layers);
1701 DeleteAllFlows(OVS_DATAPATH *datapath)
1706 for (i = 0; i < OVS_FLOW_TABLE_SIZE; i++) {
1708 bucket = &(datapath->flowTable[i]);
1709 while (!IsListEmpty(bucket)) {
1711 next = bucket->Flink;
1712 flow = CONTAINING_RECORD(next, OvsFlow, ListEntry);
1713 RemoveFlow(datapath, &flow);
1719 *----------------------------------------------------------------------------
1720 * Initializes 'flow' members from 'packet', 'skb_priority', 'tun_id', and
1723 * Initializes 'packet' header pointers as follows:
1725 * - packet->l2 to the start of the Ethernet header.
1727 * - packet->l3 to just past the Ethernet header, or just past the
1728 * vlan_header if one is present, to the first byte of the payload of the
1731 * - packet->l4 to just past the IPv4 header, if one is present and has a
1732 * correct length, and otherwise NULL.
1734 * - packet->l7 to just past the TCP, UDP, SCTP or ICMP header, if one is
1735 * present and has a correct length, and otherwise NULL.
1737 * Returns NDIS_STATUS_SUCCESS normally. Fails only if packet data cannot be accessed
1738 * (e.g. if Pkt_CopyBytesOut() returns an error).
1739 *----------------------------------------------------------------------------
1742 OvsExtractFlow(const NET_BUFFER_LIST *packet,
1745 POVS_PACKET_HDR_INFO layers,
1746 OvsIPv4TunnelKey *tunKey)
1748 struct Eth_Header *eth;
1755 ASSERT(tunKey->dst != 0);
1756 RtlMoveMemory(&flow->tunKey, tunKey, sizeof flow->tunKey);
1757 flow->l2.offset = 0;
1759 flow->tunKey.dst = 0;
1760 flow->l2.offset = OVS_WIN_TUNNEL_KEY_SIZE;
1763 flow->l2.inPort = inPort;
1765 if ( OvsPacketLenNBL(packet) < ETH_HEADER_LEN_DIX) {
1766 flow->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + 8 - flow->l2.offset;
1767 return NDIS_STATUS_SUCCESS;
1771 eth = (Eth_Header *)GetStartAddrNBL((NET_BUFFER_LIST *)packet);
1772 memcpy(flow->l2.dlSrc, eth->src, ETH_ADDR_LENGTH);
1773 memcpy(flow->l2.dlDst, eth->dst, ETH_ADDR_LENGTH);
1778 vlanTagValue = NET_BUFFER_LIST_INFO(packet, Ieee8021QNetBufferListInfo);
1780 PNDIS_NET_BUFFER_LIST_8021Q_INFO vlanTag =
1781 (PNDIS_NET_BUFFER_LIST_8021Q_INFO)(PVOID *)&vlanTagValue;
1782 flow->l2.vlanTci = htons(vlanTag->TagHeader.VlanId | OVSWIN_VLAN_CFI |
1783 (vlanTag->TagHeader.UserPriority << 13));
1785 if (eth->dix.typeNBO == ETH_TYPE_802_1PQ_NBO) {
1786 Eth_802_1pq_Tag *tag= (Eth_802_1pq_Tag *)ð->dix.typeNBO;
1787 flow->l2.vlanTci = ((UINT16)tag->priority << 13) |
1789 ((UINT16)tag->vidHi << 8) | tag->vidLo;
1790 offset = sizeof (Eth_802_1pq_Tag);
1792 flow->l2.vlanTci = 0;
1796 * Please note after this point, src mac and dst mac should
1797 * not be accessed through eth
1799 eth = (Eth_Header *)((UINT8 *)eth + offset);
1805 * XXX assume that at least the first
1806 * 12 bytes of received packets are mapped. This code has the stronger
1807 * assumption that at least the first 22 bytes of 'packet' is mapped (if my
1808 * arithmetic is right).
1810 if (ETH_TYPENOT8023(eth->dix.typeNBO)) {
1811 flow->l2.dlType = eth->dix.typeNBO;
1812 layers->l3Offset = ETH_HEADER_LEN_DIX + offset;
1813 } else if (OvsPacketLenNBL(packet) >= ETH_HEADER_LEN_802_3 &&
1814 eth->e802_3.llc.dsap == 0xaa &&
1815 eth->e802_3.llc.ssap == 0xaa &&
1816 eth->e802_3.llc.control == ETH_LLC_CONTROL_UFRAME &&
1817 eth->e802_3.snap.snapOrg[0] == 0x00 &&
1818 eth->e802_3.snap.snapOrg[1] == 0x00 &&
1819 eth->e802_3.snap.snapOrg[2] == 0x00) {
1820 flow->l2.dlType = eth->e802_3.snap.snapType.typeNBO;
1821 layers->l3Offset = ETH_HEADER_LEN_802_3 + offset;
1823 flow->l2.dlType = htons(OVSWIN_DL_TYPE_NONE);
1824 layers->l3Offset = ETH_HEADER_LEN_DIX + offset;
1827 flow->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + OVS_L2_KEY_SIZE - flow->l2.offset;
1828 /* Network layer. */
1829 if (flow->l2.dlType == htons(ETH_TYPE_IPV4)) {
1830 struct IPHdr ip_storage;
1831 const struct IPHdr *nh;
1832 IpKey *ipKey = &flow->ipKey;
1834 flow->l2.keyLen += OVS_IP_KEY_SIZE;
1836 nh = OvsGetIp(packet, layers->l3Offset, &ip_storage);
1838 layers->l4Offset = layers->l3Offset + nh->ihl * 4;
1840 ipKey->nwSrc = nh->saddr;
1841 ipKey->nwDst = nh->daddr;
1842 ipKey->nwProto = nh->protocol;
1844 ipKey->nwTos = nh->tos;
1845 if (nh->frag_off & htons(IP_MF | IP_OFFSET)) {
1846 ipKey->nwFrag = OVS_FRAG_TYPE_FIRST;
1847 if (nh->frag_off & htons(IP_OFFSET)) {
1848 ipKey->nwFrag = OVS_FRAG_TYPE_LATER;
1851 ipKey->nwFrag = OVS_FRAG_TYPE_NONE;
1854 ipKey->nwTtl = nh->ttl;
1855 ipKey->l4.tpSrc = 0;
1856 ipKey->l4.tpDst = 0;
1858 if (!(nh->frag_off & htons(IP_OFFSET))) {
1859 if (ipKey->nwProto == SOCKET_IPPROTO_TCP) {
1860 OvsParseTcp(packet, &ipKey->l4, layers);
1861 } else if (ipKey->nwProto == SOCKET_IPPROTO_UDP) {
1862 OvsParseUdp(packet, &ipKey->l4, layers);
1863 } else if (ipKey->nwProto == SOCKET_IPPROTO_SCTP) {
1864 OvsParseSctp(packet, &ipKey->l4, layers);
1865 } else if (ipKey->nwProto == SOCKET_IPPROTO_ICMP) {
1866 ICMPHdr icmpStorage;
1867 const ICMPHdr *icmp;
1869 icmp = OvsGetIcmp(packet, layers->l4Offset, &icmpStorage);
1871 ipKey->l4.tpSrc = htons(icmp->type);
1872 ipKey->l4.tpDst = htons(icmp->code);
1873 layers->l7Offset = layers->l4Offset + sizeof *icmp;
1878 ((UINT64 *)ipKey)[0] = 0;
1879 ((UINT64 *)ipKey)[1] = 0;
1881 } else if (flow->l2.dlType == htons(ETH_TYPE_IPV6)) {
1883 flow->l2.keyLen += OVS_IPV6_KEY_SIZE;
1884 status = OvsParseIPv6(packet, flow, layers);
1885 if (status != NDIS_STATUS_SUCCESS) {
1886 memset(&flow->ipv6Key, 0, sizeof (Ipv6Key));
1890 flow->ipv6Key.l4.tpSrc = 0;
1891 flow->ipv6Key.l4.tpDst = 0;
1892 flow->ipv6Key.pad = 0;
1894 if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_TCP) {
1895 OvsParseTcp(packet, &(flow->ipv6Key.l4), layers);
1896 } else if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_UDP) {
1897 OvsParseUdp(packet, &(flow->ipv6Key.l4), layers);
1898 } else if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_SCTP) {
1899 OvsParseSctp(packet, &flow->ipv6Key.l4, layers);
1900 } else if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_ICMPV6) {
1901 OvsParseIcmpV6(packet, flow, layers);
1902 flow->l2.keyLen += (OVS_ICMPV6_KEY_SIZE - OVS_IPV6_KEY_SIZE);
1904 } else if (flow->l2.dlType == htons(ETH_TYPE_ARP)) {
1905 EtherArp arpStorage;
1906 const EtherArp *arp;
1907 ArpKey *arpKey = &flow->arpKey;
1908 ((UINT64 *)arpKey)[0] = 0;
1909 ((UINT64 *)arpKey)[1] = 0;
1910 ((UINT64 *)arpKey)[2] = 0;
1911 flow->l2.keyLen += OVS_ARP_KEY_SIZE;
1912 arp = OvsGetArp(packet, layers->l3Offset, &arpStorage);
1913 if (arp && arp->ea_hdr.ar_hrd == htons(1) &&
1914 arp->ea_hdr.ar_pro == htons(ETH_TYPE_IPV4) &&
1915 arp->ea_hdr.ar_hln == ETH_ADDR_LENGTH &&
1916 arp->ea_hdr.ar_pln == 4) {
1917 /* We only match on the lower 8 bits of the opcode. */
1918 if (ntohs(arp->ea_hdr.ar_op) <= 0xff) {
1919 arpKey->nwProto = (UINT8)ntohs(arp->ea_hdr.ar_op);
1921 if (arpKey->nwProto == ARPOP_REQUEST
1922 || arpKey->nwProto == ARPOP_REPLY) {
1923 memcpy(&arpKey->nwSrc, arp->arp_spa, 4);
1924 memcpy(&arpKey->nwDst, arp->arp_tpa, 4);
1925 memcpy(arpKey->arpSha, arp->arp_sha, ETH_ADDR_LENGTH);
1926 memcpy(arpKey->arpTha, arp->arp_tha, ETH_ADDR_LENGTH);
1929 } else if (OvsEthertypeIsMpls(flow->l2.dlType)) {
1930 MPLSHdr mplsStorage;
1931 const MPLSHdr *mpls;
1932 MplsKey *mplsKey = &flow->mplsKey;
1933 ((UINT64 *)mplsKey)[0] = 0;
1934 flow->l2.keyLen += OVS_MPLS_KEY_SIZE;
1937 * In the presence of an MPLS label stack the end of the L2
1938 * header and the beginning of the L3 header differ.
1940 * A network packet may contain multiple MPLS labels, but we
1941 * are only interested in the topmost label stack entry.
1943 * Advance network header to the beginning of the L3 header.
1944 * layers->l3Offset corresponds to the end of the L2 header.
1946 for (UINT32 i = 0; i < FLOW_MAX_MPLS_LABELS; i++) {
1947 mpls = OvsGetMpls(packet, layers->l3Offset, &mplsStorage);
1952 /* Keep only the topmost MPLS label stack entry. */
1954 mplsKey->lse = mpls->lse;
1957 layers->l3Offset += MPLS_HLEN;
1958 layers->l4Offset += MPLS_HLEN;
1960 if (mpls->lse & htonl(MPLS_BOS_MASK)) {
1962 * Bottom of Stack bit is set, which means there are no
1963 * remaining MPLS labels in the packet.
1970 return NDIS_STATUS_SUCCESS;
1974 FlowEqual(UINT64 *src, UINT64 *dst, UINT32 size)
1977 ASSERT((size & 0x7) == 0);
1978 ASSERT(((UINT64)src & 0x7) == 0);
1979 ASSERT(((UINT64)dst & 0x7) == 0);
1980 for (i = 0; i < (size >> 3); i++) {
1981 if (src[i] != dst[i]) {
1990 * ----------------------------------------------------------------------------
1992 * Add a flow to flow table.
1995 * NDIS_STATUS_SUCCESS if no same flow in the flow table.
1996 * ----------------------------------------------------------------------------
1999 AddFlow(OVS_DATAPATH *datapath, OvsFlow *flow)
2003 if (OvsLookupFlow(datapath, &flow->key, &flow->hash, TRUE) != NULL) {
2004 return STATUS_INVALID_HANDLE;
2007 head = &(datapath->flowTable[HASH_BUCKET(flow->hash)]);
2009 * We need fence here to make sure flow's nextPtr is updated before
2010 * head->nextPtr is updated.
2014 //KeAcquireSpinLock(&FilterDeviceExtension->NblQueueLock, &oldIrql);
2015 InsertTailList(head, &flow->ListEntry);
2016 //KeReleaseSpinLock(&FilterDeviceExtension->NblQueueLock, oldIrql);
2020 return STATUS_SUCCESS;
2024 /* ----------------------------------------------------------------------------
2026 * Remove a flow from flow table, and added to wait list
2027 * ----------------------------------------------------------------------------
2030 RemoveFlow(OVS_DATAPATH *datapath,
2036 ASSERT(datapath->nFlows);
2038 // Remove the flow from queue
2039 RemoveEntryList(&f->ListEntry);
2045 * ----------------------------------------------------------------------------
2048 * Find flow from flow table based on flow key.
2049 * Caller should either hold portset handle or should
2050 * have a flowRef in datapath or Acquired datapath.
2053 * Flow pointer if lookup successful.
2054 * NULL if not exists.
2055 * ----------------------------------------------------------------------------
2058 OvsLookupFlow(OVS_DATAPATH *datapath,
2059 const OvsFlowKey *key,
2063 PLIST_ENTRY link, head;
2064 UINT16 offset = key->l2.offset;
2065 UINT16 size = key->l2.keyLen;
2068 ASSERT(key->tunKey.dst || offset == sizeof (OvsIPv4TunnelKey));
2069 ASSERT(!key->tunKey.dst || offset == 0);
2071 start = (UINT8 *)key + offset;
2074 *hash = OvsJhashBytes(start, size, 0);
2077 head = &datapath->flowTable[HASH_BUCKET(*hash)];
2079 while (link != head) {
2080 OvsFlow *flow = CONTAINING_RECORD(link, OvsFlow, ListEntry);
2082 if (flow->hash == *hash &&
2083 flow->key.l2.val == key->l2.val &&
2084 FlowEqual((UINT64 *)((uint8 *)&flow->key + offset),
2085 (UINT64 *)start, size)) {
2095 * ----------------------------------------------------------------------------
2097 * Calculate the hash for the given flow key.
2098 * ----------------------------------------------------------------------------
2101 OvsHashFlow(const OvsFlowKey *key)
2103 UINT16 offset = key->l2.offset;
2104 UINT16 size = key->l2.keyLen;
2107 ASSERT(key->tunKey.dst || offset == sizeof (OvsIPv4TunnelKey));
2108 ASSERT(!key->tunKey.dst || offset == 0);
2109 start = (UINT8 *)key + offset;
2110 return OvsJhashBytes(start, size, 0);
2115 * ----------------------------------------------------------------------------
2117 * Free a flow and its actions.
2118 * ----------------------------------------------------------------------------
2121 FreeFlow(OvsFlow *flow)
2124 OvsFreeMemoryWithTag(flow, OVS_FLOW_POOL_TAG);
2128 OvsDoDumpFlows(OvsFlowDumpInput *dumpInput,
2129 OvsFlowDumpOutput *dumpOutput,
2133 OVS_DATAPATH *datapath = NULL;
2135 PLIST_ENTRY node, head;
2137 UINT32 rowIndex, columnIndex;
2138 LOCK_STATE_EX dpLockState;
2139 NTSTATUS status = STATUS_SUCCESS;
2140 BOOLEAN findNextNonEmpty = FALSE;
2142 dpNo = dumpInput->dpNo;
2143 if (gOvsSwitchContext->dpNo != dpNo) {
2144 status = STATUS_INVALID_PARAMETER;
2148 rowIndex = dumpInput->position[0];
2149 if (rowIndex >= OVS_FLOW_TABLE_SIZE) {
2151 *replyLen = sizeof(*dumpOutput);
2155 columnIndex = dumpInput->position[1];
2157 datapath = &gOvsSwitchContext->datapath;
2159 OvsAcquireDatapathRead(datapath, &dpLockState, FALSE);
2161 head = &datapath->flowTable[rowIndex];
2164 while (column < columnIndex) {
2173 findNextNonEmpty = TRUE;
2177 if (findNextNonEmpty) {
2178 while (head == node) {
2179 if (++rowIndex >= OVS_FLOW_TABLE_SIZE) {
2183 head = &datapath->flowTable[rowIndex];
2188 ASSERT(node != head);
2189 ASSERT(rowIndex < OVS_FLOW_TABLE_SIZE);
2191 flow = CONTAINING_RECORD(node, OvsFlow, ListEntry);
2192 status = ReportFlowInfo(flow, dumpInput->getFlags, &dumpOutput->flow);
2194 if (status == STATUS_BUFFER_TOO_SMALL) {
2195 dumpOutput->n = sizeof(OvsFlowDumpOutput) + flow->actionsLen;
2196 *replyLen = sizeof(*dumpOutput);
2198 dumpOutput->n = 1; //one flow reported.
2199 *replyLen = sizeof(*dumpOutput) + dumpOutput->flow.actionsLen;
2202 dumpOutput->position[0] = rowIndex;
2203 dumpOutput->position[1] = ++columnIndex;
2206 OvsReleaseDatapath(datapath, &dpLockState);
2213 ReportFlowInfo(OvsFlow *flow,
2217 NTSTATUS status = STATUS_SUCCESS;
2219 if (getFlags & FLOW_GET_KEY) {
2220 // always copy the tunnel key part
2221 RtlCopyMemory(&info->key, &flow->key,
2222 flow->key.l2.keyLen + flow->key.l2.offset);
2225 if (getFlags & FLOW_GET_STATS) {
2226 OvsFlowStats *stats = &info->stats;
2227 stats->packetCount = flow->packetCount;
2228 stats->byteCount = flow->byteCount;
2229 stats->used = (UINT32)flow->used;
2230 stats->tcpFlags = flow->tcpFlags;
2233 if (getFlags & FLOW_GET_ACTIONS) {
2234 if (flow->actionsLen == 0) {
2235 info->actionsLen = 0;
2237 info->actions = flow->actions;
2238 info->actionsLen = flow->actionsLen;
2246 OvsPutFlowIoctl(PVOID inputBuffer,
2248 struct OvsFlowStats *stats)
2250 NTSTATUS status = STATUS_SUCCESS;
2251 OVS_DATAPATH *datapath = NULL;
2255 LOCK_STATE_EX dpLockState;
2257 if ((inputLength < sizeof(OvsFlowPut)) || (inputBuffer == NULL)) {
2258 return STATUS_INFO_LENGTH_MISMATCH;
2261 put = (OvsFlowPut *)inputBuffer;
2262 if (put->actionsLen > 0) {
2263 actionsLen = put->actionsLen;
2269 if (gOvsSwitchContext->dpNo != dpNo) {
2270 status = STATUS_INVALID_PARAMETER;
2274 datapath = &gOvsSwitchContext->datapath;
2276 OvsAcquireDatapathWrite(datapath, &dpLockState, FALSE);
2277 status = HandleFlowPut(put, datapath, stats);
2278 OvsReleaseDatapath(datapath, &dpLockState);
2285 /* Handles flow add, modify as well as delete */
2287 HandleFlowPut(OvsFlowPut *put,
2288 OVS_DATAPATH *datapath,
2289 struct OvsFlowStats *stats)
2291 BOOLEAN mayCreate, mayModify, mayDelete;
2292 OvsFlow *KernelFlow;
2294 NTSTATUS status = STATUS_SUCCESS;
2296 mayCreate = (put->flags & OVSWIN_FLOW_PUT_CREATE) != 0;
2297 mayModify = (put->flags & OVSWIN_FLOW_PUT_MODIFY) != 0;
2298 mayDelete = (put->flags & OVSWIN_FLOW_PUT_DELETE) != 0;
2300 if ((mayCreate || mayModify) == mayDelete) {
2301 return STATUS_INVALID_PARAMETER;
2304 KernelFlow = OvsLookupFlow(datapath, &put->key, &hash, FALSE);
2307 return STATUS_INVALID_PARAMETER;
2310 status = OvsPrepareFlow(&KernelFlow, put, hash);
2311 if (status != STATUS_SUCCESS) {
2312 return STATUS_UNSUCCESSFUL;
2315 status = AddFlow(datapath, KernelFlow);
2316 if (status != STATUS_SUCCESS) {
2317 FreeFlow(KernelFlow);
2318 return STATUS_UNSUCCESSFUL;
2321 /* Validate the flow addition */
2324 OvsFlow *flow = OvsLookupFlow(datapath, &put->key, &newHash,
2327 ASSERT(newHash == hash);
2328 if (!flow || newHash != hash) {
2329 return STATUS_UNSUCCESSFUL;
2333 stats->packetCount = KernelFlow->packetCount;
2334 stats->byteCount = KernelFlow->byteCount;
2335 stats->tcpFlags = KernelFlow->tcpFlags;
2336 stats->used = (UINT32)KernelFlow->used;
2340 status = OvsPrepareFlow(&newFlow, put, hash);
2341 if (status != STATUS_SUCCESS) {
2342 return STATUS_UNSUCCESSFUL;
2345 KernelFlow = OvsLookupFlow(datapath, &put->key, &hash, TRUE);
2347 if ((put->flags & OVSWIN_FLOW_PUT_CLEAR) == 0) {
2348 newFlow->packetCount = KernelFlow->packetCount;
2349 newFlow->byteCount = KernelFlow->byteCount;
2350 newFlow->tcpFlags = KernelFlow->tcpFlags;
2352 RemoveFlow(datapath, &KernelFlow);
2354 if ((put->flags & OVSWIN_FLOW_PUT_CLEAR) == 0) {
2355 newFlow->packetCount = stats->packetCount;
2356 newFlow->byteCount = stats->byteCount;
2357 newFlow->tcpFlags = stats->tcpFlags;
2360 status = AddFlow(datapath, newFlow);
2361 ASSERT(status == STATUS_SUCCESS);
2363 /* Validate the flow addition */
2366 OvsFlow *testflow = OvsLookupFlow(datapath, &put->key,
2369 ASSERT(newHash == hash);
2370 if (!testflow || newHash != hash) {
2372 return STATUS_UNSUCCESSFUL;
2378 RemoveFlow(datapath, &KernelFlow);
2381 /* Return success if an identical flow already exists. */
2382 /* XXX: should we return EEXIST in a netlink error? */
2383 return STATUS_SUCCESS;
2387 return STATUS_SUCCESS;
2391 OvsPrepareFlow(OvsFlow **flow,
2392 const OvsFlowPut *put,
2395 OvsFlow *localFlow = *flow;
2396 NTSTATUS status = STATUS_SUCCESS;
2400 OvsAllocateMemoryWithTag(sizeof(OvsFlow) + put->actionsLen,
2402 if (localFlow == NULL) {
2403 status = STATUS_NO_MEMORY;
2407 localFlow->key = put->key;
2408 localFlow->actionsLen = put->actionsLen;
2409 if (put->actionsLen) {
2410 NdisMoveMemory((PUCHAR)localFlow->actions, put->actions,
2413 localFlow->userActionsLen = 0; // 0 indicate no conversion is made
2414 localFlow->used = 0;
2415 localFlow->packetCount = 0;
2416 localFlow->byteCount = 0;
2417 localFlow->tcpFlags = 0;
2418 localFlow->hash = hash;
2425 OvsGetFlowIoctl(PVOID inputBuffer,
2428 NTSTATUS status = STATUS_SUCCESS;
2429 OVS_DATAPATH *datapath = NULL;
2431 UINT32 getFlags, getActionsLen;
2432 OvsFlowGetInput *getInput;
2433 OvsFlowGetOutput *getOutput;
2436 LOCK_STATE_EX dpLockState;
2438 getInput = (OvsFlowGetInput *) inputBuffer;
2439 getFlags = getInput->getFlags;
2440 getActionsLen = getInput->actionsLen;
2442 if (outputBuffer == NULL) {
2443 return STATUS_INFO_LENGTH_MISMATCH;
2446 dpNo = getInput->dpNo;
2447 if (gOvsSwitchContext->dpNo != dpNo) {
2448 status = STATUS_INVALID_PARAMETER;
2452 datapath = &gOvsSwitchContext->datapath;
2454 OvsAcquireDatapathRead(datapath, &dpLockState, FALSE);
2455 flow = OvsLookupFlow(datapath, &getInput->key, &hash, FALSE);
2457 status = STATUS_INVALID_PARAMETER;
2461 getOutput = (OvsFlowGetOutput *)outputBuffer;
2462 ReportFlowInfo(flow, getFlags, &getOutput->info);
2465 OvsReleaseDatapath(datapath, &dpLockState);
2471 OvsFlushFlowIoctl(UINT32 dpNo)
2473 NTSTATUS status = STATUS_SUCCESS;
2474 OVS_DATAPATH *datapath = NULL;
2475 LOCK_STATE_EX dpLockState;
2477 if (gOvsSwitchContext->dpNo != dpNo) {
2478 status = STATUS_INVALID_PARAMETER;
2482 datapath = &gOvsSwitchContext->datapath;
2484 OvsAcquireDatapathWrite(datapath, &dpLockState, FALSE);
2485 DeleteAllFlows(datapath);
2486 OvsReleaseDatapath(datapath, &dpLockState);
2493 OvsFlowKeyAttrSize(void)
2495 return NlAttrTotalSize(4) /* OVS_KEY_ATTR_PRIORITY */
2496 + NlAttrTotalSize(0) /* OVS_KEY_ATTR_TUNNEL */
2497 + OvsTunKeyAttrSize()
2498 + NlAttrTotalSize(4) /* OVS_KEY_ATTR_IN_PORT */
2499 + NlAttrTotalSize(4) /* OVS_KEY_ATTR_SKB_MARK */
2500 + NlAttrTotalSize(4) /* OVS_KEY_ATTR_DP_HASH */
2501 + NlAttrTotalSize(4) /* OVS_KEY_ATTR_RECIRC_ID */
2502 + NlAttrTotalSize(12) /* OVS_KEY_ATTR_ETHERNET */
2503 + NlAttrTotalSize(2) /* OVS_KEY_ATTR_ETHERTYPE */
2504 + NlAttrTotalSize(4) /* OVS_KEY_ATTR_VLAN */
2505 + NlAttrTotalSize(0) /* OVS_KEY_ATTR_ENCAP */
2506 + NlAttrTotalSize(2) /* OVS_KEY_ATTR_ETHERTYPE */
2507 + NlAttrTotalSize(40) /* OVS_KEY_ATTR_IPV6 */
2508 + NlAttrTotalSize(2) /* OVS_KEY_ATTR_ICMPV6 */
2509 + NlAttrTotalSize(28); /* OVS_KEY_ATTR_ND */
2513 OvsTunKeyAttrSize(void)
2515 /* Whenever adding new OVS_TUNNEL_KEY_ FIELDS, we should consider
2516 * updating this function.
2518 return NlAttrTotalSize(8) /* OVS_TUNNEL_KEY_ATTR_ID */
2519 + NlAttrTotalSize(4) /* OVS_TUNNEL_KEY_ATTR_IPV4_SRC */
2520 + NlAttrTotalSize(4) /* OVS_TUNNEL_KEY_ATTR_IPV4_DST */
2521 + NlAttrTotalSize(1) /* OVS_TUNNEL_KEY_ATTR_TOS */
2522 + NlAttrTotalSize(1) /* OVS_TUNNEL_KEY_ATTR_TTL */
2523 + NlAttrTotalSize(0) /* OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT */
2524 + NlAttrTotalSize(0) /* OVS_TUNNEL_KEY_ATTR_CSUM */
2525 + NlAttrTotalSize(0) /* OVS_TUNNEL_KEY_ATTR_OAM */
2526 + NlAttrTotalSize(256) /* OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS */
2527 + NlAttrTotalSize(2) /* OVS_TUNNEL_KEY_ATTR_TP_SRC */
2528 + NlAttrTotalSize(2); /* OVS_TUNNEL_KEY_ATTR_TP_DST */
2532 *----------------------------------------------------------------------------
2533 * OvsProbeSupportedFeature --
2534 * Verifies if the probed feature is supported.
2537 * STATUS_SUCCESS if the probed feature is supported.
2538 *----------------------------------------------------------------------------
2541 OvsProbeSupportedFeature(POVS_MESSAGE msgIn,
2544 NTSTATUS status = STATUS_SUCCESS;
2545 PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
2547 UINT32 keyAttrOffset = (UINT32)((PCHAR)keyAttr - (PCHAR)nlMsgHdr);
2548 PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX] = { NULL };
2550 /* Get flow keys attributes */
2551 if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset, NlAttrLen(keyAttr),
2552 nlFlowKeyPolicy, ARRAY_SIZE(nlFlowKeyPolicy),
2553 keyAttrs, ARRAY_SIZE(keyAttrs)))
2555 OVS_LOG_ERROR("Key Attr Parsing failed for msg: %p",
2557 status = STATUS_INVALID_PARAMETER;
2561 if (keyAttrs[OVS_KEY_ATTR_MPLS] &&
2562 keyAttrs[OVS_KEY_ATTR_ETHERTYPE]) {
2563 ovs_be16 ethType = NlAttrGetU16(keyAttrs[OVS_KEY_ATTR_ETHERTYPE]);
2565 if (OvsEthertypeIsMpls(ethType)) {
2566 if (!OvsCountMplsLabels(keyAttrs[OVS_KEY_ATTR_MPLS])) {
2567 OVS_LOG_ERROR("Maximum supported MPLS labels exceeded.");
2568 status = STATUS_INVALID_MESSAGE;
2571 OVS_LOG_ERROR("Wrong ethertype for MPLS attribute.");
2572 status = STATUS_INVALID_PARAMETER;
2575 OVS_LOG_ERROR("Probed feature not supported.");
2576 status = STATUS_INVALID_PARAMETER;
2583 #pragma warning( pop )