]> git.proxmox.com Git - mirror_ovs.git/blob - datapath-windows/ovsext/Flow.c
c2e02277a38fd8b8125102ff7bd79b6b1c2943b5
[mirror_ovs.git] / datapath-windows / ovsext / Flow.c
1 /*
2 * Copyright (c) 2014 VMware, Inc.
3 *
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:
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
17 #include "precomp.h"
18 #include "NetProto.h"
19 #include "Util.h"
20 #include "Jhash.h"
21 #include "Flow.h"
22 #include "PacketParser.h"
23 #include "Datapath.h"
24
25 #ifdef OVS_DBG_MOD
26 #undef OVS_DBG_MOD
27 #endif
28 #define OVS_DBG_MOD OVS_DBG_FLOW
29 #include "Debug.h"
30
31 #pragma warning( push )
32 #pragma warning( disable:4127 )
33
34 extern POVS_SWITCH_CONTEXT gOvsSwitchContext;
35 extern UINT64 ovsTimeIncrementPerTick;
36
37 static NTSTATUS ReportFlowInfo(OvsFlow *flow, UINT32 getFlags,
38 OvsFlowInfo *info);
39 static NTSTATUS HandleFlowPut(OvsFlowPut *put,
40 OVS_DATAPATH *datapath,
41 struct OvsFlowStats *stats);
42 static NTSTATUS OvsPrepareFlow(OvsFlow **flow, const OvsFlowPut *put,
43 UINT64 hash);
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,
50 PNL_ATTR actionAttr,
51 PNL_ATTR flowAttrClear,
52 OvsFlowPut *mappedFlow);
53 static VOID _MapKeyAttrToFlowPut(PNL_ATTR *keyAttrs,
54 PNL_ATTR *tunnelAttrs,
55 OvsFlowKey *destKey);
56
57 static VOID _MapNlToFlowPutFlags(PGENL_MSG_HDR genlMsgHdr,
58 PNL_ATTR flowAttrClear,
59 OvsFlowPut *mappedFlow);
60
61 static NTSTATUS _FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
62 UINT32 *replyLen);
63 static NTSTATUS _FlowNlDumpCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
64 UINT32 *replyLen);
65 static NTSTATUS _MapFlowInfoToNl(PNL_BUFFER nlBuf,
66 OvsFlowInfo *flowInfo);
67 static NTSTATUS _MapFlowStatsToNlStats(PNL_BUFFER nlBuf,
68 OvsFlowStats *flowStats);
69 static NTSTATUS _MapFlowActionToNlAction(PNL_BUFFER nlBuf,
70 uint32_t actionsLen,
71 PNL_ATTR actions);
72
73 static NTSTATUS _MapFlowIpv4KeyToNlKey(PNL_BUFFER nlBuf,
74 IpKey *ipv4FlowPutKey);
75 static NTSTATUS _MapFlowIpv6KeyToNlKey(PNL_BUFFER nlBuf,
76 Ipv6Key *ipv6FlowPutKey,
77 Icmp6Key *ipv6FlowPutIcmpKey);
78 static NTSTATUS _MapFlowArpKeyToNlKey(PNL_BUFFER nlBuf,
79 ArpKey *arpFlowPutKey);
80 static NTSTATUS _MapFlowMplsKeyToNlKey(PNL_BUFFER nlBuf,
81 MplsKey *mplsFlowPutKey);
82
83 static NTSTATUS OvsDoDumpFlows(OvsFlowDumpInput *dumpInput,
84 OvsFlowDumpOutput *dumpOutput,
85 UINT32 *replyLen);
86 static NTSTATUS OvsProbeSupportedFeature(POVS_MESSAGE msgIn,
87 PNL_ATTR keyAttr);
88
89
90 #define OVS_FLOW_TABLE_SIZE 2048
91 #define OVS_FLOW_TABLE_MASK (OVS_FLOW_TABLE_SIZE -1)
92 #define HASH_BUCKET(hash) ((hash) & OVS_FLOW_TABLE_MASK)
93
94 /* Flow family related netlink policies */
95
96 /* For Parsing attributes in FLOW_* commands */
97 const NL_POLICY nlFlowPolicy[] = {
98 [OVS_FLOW_ATTR_KEY] = {.type = NL_A_NESTED, .optional = FALSE},
99 [OVS_FLOW_ATTR_MASK] = {.type = NL_A_NESTED, .optional = TRUE},
100 [OVS_FLOW_ATTR_ACTIONS] = {.type = NL_A_NESTED, .optional = TRUE},
101 [OVS_FLOW_ATTR_STATS] = {.type = NL_A_UNSPEC,
102 .minLen = sizeof(struct ovs_flow_stats),
103 .maxLen = sizeof(struct ovs_flow_stats),
104 .optional = TRUE},
105 [OVS_FLOW_ATTR_TCP_FLAGS] = {NL_A_U8, .optional = TRUE},
106 [OVS_FLOW_ATTR_USED] = {NL_A_U64, .optional = TRUE},
107 [OVS_FLOW_ATTR_PROBE] = {.type = NL_A_FLAG, .optional = TRUE}
108 };
109
110 /* For Parsing nested OVS_FLOW_ATTR_KEY attributes. */
111
112 const NL_POLICY nlFlowKeyPolicy[] = {
113 [OVS_KEY_ATTR_ENCAP] = {.type = NL_A_VAR_LEN, .optional = TRUE},
114 [OVS_KEY_ATTR_PRIORITY] = {.type = NL_A_UNSPEC, .minLen = 4,
115 .maxLen = 4, .optional = TRUE},
116 [OVS_KEY_ATTR_IN_PORT] = {.type = NL_A_UNSPEC, .minLen = 4,
117 .maxLen = 4, .optional = FALSE},
118 [OVS_KEY_ATTR_ETHERNET] = {.type = NL_A_UNSPEC,
119 .minLen = sizeof(struct ovs_key_ethernet),
120 .maxLen = sizeof(struct ovs_key_ethernet),
121 .optional = TRUE},
122 [OVS_KEY_ATTR_VLAN] = {.type = NL_A_UNSPEC, .minLen = 2,
123 .maxLen = 2, .optional = TRUE},
124 [OVS_KEY_ATTR_ETHERTYPE] = {.type = NL_A_UNSPEC, .minLen = 2,
125 .maxLen = 2, .optional = TRUE},
126 [OVS_KEY_ATTR_IPV4] = {.type = NL_A_UNSPEC,
127 .minLen = sizeof(struct ovs_key_ipv4),
128 .maxLen = sizeof(struct ovs_key_ipv4),
129 .optional = TRUE},
130 [OVS_KEY_ATTR_IPV6] = {.type = NL_A_UNSPEC,
131 .minLen = sizeof(struct ovs_key_ipv6),
132 .maxLen = sizeof(struct ovs_key_ipv6),
133 .optional = TRUE},
134 [OVS_KEY_ATTR_TCP] = {.type = NL_A_UNSPEC,
135 .minLen = sizeof(struct ovs_key_tcp),
136 .maxLen = sizeof(struct ovs_key_tcp),
137 .optional = TRUE},
138 [OVS_KEY_ATTR_UDP] = {.type = NL_A_UNSPEC,
139 .minLen = sizeof(struct ovs_key_udp),
140 .maxLen = sizeof(struct ovs_key_udp),
141 .optional = TRUE},
142 [OVS_KEY_ATTR_ICMP] = {.type = NL_A_UNSPEC,
143 .minLen = sizeof(struct ovs_key_icmp),
144 .maxLen = sizeof(struct ovs_key_icmp),
145 .optional = TRUE},
146 [OVS_KEY_ATTR_ICMPV6] = {.type = NL_A_UNSPEC,
147 .minLen = sizeof(struct ovs_key_icmpv6),
148 .maxLen = sizeof(struct ovs_key_icmpv6),
149 .optional = TRUE},
150 [OVS_KEY_ATTR_ARP] = {.type = NL_A_UNSPEC,
151 .minLen = sizeof(struct ovs_key_arp),
152 .maxLen = sizeof(struct ovs_key_arp),
153 .optional = TRUE},
154 [OVS_KEY_ATTR_ND] = {.type = NL_A_UNSPEC,
155 .minLen = sizeof(struct ovs_key_nd),
156 .maxLen = sizeof(struct ovs_key_nd),
157 .optional = TRUE},
158 [OVS_KEY_ATTR_SKB_MARK] = {.type = NL_A_UNSPEC, .minLen = 4,
159 .maxLen = 4, .optional = TRUE},
160 [OVS_KEY_ATTR_TUNNEL] = {.type = NL_A_VAR_LEN, .optional = TRUE},
161 [OVS_KEY_ATTR_SCTP] = {.type = NL_A_UNSPEC,
162 .minLen = sizeof(struct ovs_key_sctp),
163 .maxLen = sizeof(struct ovs_key_sctp),
164 .optional = TRUE},
165 [OVS_KEY_ATTR_TCP_FLAGS] = {.type = NL_A_UNSPEC,
166 .minLen = 2, .maxLen = 2,
167 .optional = TRUE},
168 [OVS_KEY_ATTR_DP_HASH] = {.type = NL_A_UNSPEC, .minLen = 4,
169 .maxLen = 4, .optional = TRUE},
170 [OVS_KEY_ATTR_RECIRC_ID] = {.type = NL_A_UNSPEC, .minLen = 4,
171 .maxLen = 4, .optional = TRUE},
172 [OVS_KEY_ATTR_MPLS] = {.type = NL_A_VAR_LEN, .optional = TRUE},
173 [OVS_KEY_ATTR_CT_STATE] = {.type = NL_A_UNSPEC, .minLen = 4,
174 .maxLen = 4, .optional = TRUE},
175 [OVS_KEY_ATTR_CT_ZONE] = {.type = NL_A_UNSPEC, .minLen = 2,
176 .maxLen = 2, .optional = TRUE},
177 [OVS_KEY_ATTR_CT_MARK] = {.type = NL_A_UNSPEC, .minLen = 4,
178 .maxLen = 4, .optional = TRUE},
179 [OVS_KEY_ATTR_CT_LABELS] = {.type = NL_A_UNSPEC,
180 .minLen = sizeof(struct ovs_key_ct_labels),
181 .maxLen = sizeof(struct ovs_key_ct_labels),
182 .optional = TRUE}
183 };
184 const UINT32 nlFlowKeyPolicyLen = ARRAY_SIZE(nlFlowKeyPolicy);
185
186 /* For Parsing nested OVS_KEY_ATTR_TUNNEL attributes */
187 const NL_POLICY nlFlowTunnelKeyPolicy[] = {
188 [OVS_TUNNEL_KEY_ATTR_ID] = {.type = NL_A_UNSPEC, .minLen = 8,
189 .maxLen = 8, .optional = TRUE},
190 [OVS_TUNNEL_KEY_ATTR_IPV4_SRC] = {.type = NL_A_UNSPEC, .minLen = 4,
191 .maxLen = 4, .optional = TRUE},
192 [OVS_TUNNEL_KEY_ATTR_IPV4_DST] = {.type = NL_A_UNSPEC, .minLen = 4 ,
193 .maxLen = 4, .optional = FALSE},
194 [OVS_TUNNEL_KEY_ATTR_TOS] = {.type = NL_A_UNSPEC, .minLen = 1,
195 .maxLen = 1, .optional = TRUE},
196 [OVS_TUNNEL_KEY_ATTR_TTL] = {.type = NL_A_UNSPEC, .minLen = 1,
197 .maxLen = 1, .optional = TRUE},
198 [OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT] = {.type = NL_A_UNSPEC, .minLen = 0,
199 .maxLen = 0, .optional = TRUE},
200 [OVS_TUNNEL_KEY_ATTR_CSUM] = {.type = NL_A_UNSPEC, .minLen = 0,
201 .maxLen = 0, .optional = TRUE},
202 [OVS_TUNNEL_KEY_ATTR_OAM] = {.type = NL_A_UNSPEC, .minLen = 0,
203 .maxLen = 0, .optional = TRUE},
204 [OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS] = {.type = NL_A_VAR_LEN,
205 .optional = TRUE}
206 };
207 const UINT32 nlFlowTunnelKeyPolicyLen = ARRAY_SIZE(nlFlowTunnelKeyPolicy);
208
209 /* For Parsing nested OVS_FLOW_ATTR_ACTIONS attributes */
210 const NL_POLICY nlFlowActionPolicy[] = {
211 [OVS_ACTION_ATTR_OUTPUT] = {.type = NL_A_UNSPEC, .minLen = sizeof(UINT32),
212 .maxLen = sizeof(UINT32), .optional = TRUE},
213 [OVS_ACTION_ATTR_USERSPACE] = {.type = NL_A_VAR_LEN, .optional = TRUE},
214 [OVS_ACTION_ATTR_PUSH_VLAN] = {.type = NL_A_UNSPEC,
215 .minLen =
216 sizeof(struct ovs_action_push_vlan),
217 .maxLen =
218 sizeof(struct ovs_action_push_vlan),
219 .optional = TRUE},
220 [OVS_ACTION_ATTR_POP_VLAN] = {.type = NL_A_UNSPEC, .optional = TRUE},
221 [OVS_ACTION_ATTR_PUSH_MPLS] = {.type = NL_A_UNSPEC,
222 .minLen =
223 sizeof(struct ovs_action_push_mpls),
224 .maxLen =
225 sizeof(struct ovs_action_push_mpls),
226 .optional = TRUE},
227 [OVS_ACTION_ATTR_POP_MPLS] = {.type = NL_A_UNSPEC,
228 .minLen = sizeof(UINT16),
229 .maxLen = sizeof(UINT16),
230 .optional = TRUE},
231 [OVS_ACTION_ATTR_RECIRC] = {.type = NL_A_UNSPEC,
232 .minLen = sizeof(UINT32),
233 .maxLen = sizeof(UINT32),
234 .optional = TRUE},
235 [OVS_ACTION_ATTR_HASH] = {.type = NL_A_UNSPEC,
236 .minLen = sizeof(struct ovs_action_hash),
237 .maxLen = sizeof(struct ovs_action_hash),
238 .optional = TRUE},
239 [OVS_ACTION_ATTR_SET] = {.type = NL_A_VAR_LEN, .optional = TRUE},
240 [OVS_ACTION_ATTR_SAMPLE] = {.type = NL_A_VAR_LEN, .optional = TRUE},
241 [OVS_ACTION_ATTR_CT] = {.type = NL_A_VAR_LEN, .optional = TRUE}
242 };
243
244 /*
245 *----------------------------------------------------------------------------
246 * Netlink interface for flow commands.
247 *----------------------------------------------------------------------------
248 */
249
250 /*
251 *----------------------------------------------------------------------------
252 * OvsFlowNewCmdHandler --
253 * Handler for OVS_FLOW_CMD_NEW/SET/DEL command.
254 * It also handles FLUSH case (DEL w/o any key in input)
255 *----------------------------------------------------------------------------
256 */
257 NTSTATUS
258 OvsFlowNlCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
259 UINT32 *replyLen)
260 {
261 NTSTATUS rc = STATUS_SUCCESS;
262 BOOLEAN ok = FALSE;
263 POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;
264 POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer;
265 PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
266 PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
267 POVS_HDR ovsHdr = &(msgIn->ovsHdr);
268 PNL_ATTR flowAttrs[__OVS_FLOW_ATTR_MAX];
269 UINT32 attrOffset = NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN;
270 OvsFlowPut mappedFlow;
271 OvsFlowStats stats;
272 struct ovs_flow_stats replyStats;
273 NL_ERROR nlError = NL_ERROR_SUCCESS;
274 NL_BUFFER nlBuf;
275
276 RtlZeroMemory(&mappedFlow, sizeof(OvsFlowPut));
277 RtlZeroMemory(&stats, sizeof(stats));
278 RtlZeroMemory(&replyStats, sizeof(replyStats));
279
280 if (!(usrParamsCtx->outputBuffer)) {
281 /* No output buffer */
282 rc = STATUS_INVALID_BUFFER_SIZE;
283 goto done;
284 }
285
286 /* FLOW_DEL command w/o any key input is a flush case.
287 If we don't have any attr, we treat this as a flush command*/
288 if ((genlMsgHdr->cmd == OVS_FLOW_CMD_DEL) &&
289 (!NlMsgAttrsLen(nlMsgHdr))) {
290
291 rc = OvsFlushFlowIoctl(ovsHdr->dp_ifindex);
292
293 if (rc == STATUS_SUCCESS) {
294 /* XXX: refactor this code. */
295 /* So far so good. Prepare the reply for userspace */
296 NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
297 usrParamsCtx->outputLength);
298
299 /* Prepare nl Msg headers */
300 ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,
301 nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
302 genlMsgHdr->cmd, OVS_FLOW_VERSION,
303 ovsHdr->dp_ifindex);
304 if (ok) {
305 *replyLen = msgOut->nlMsg.nlmsgLen;
306 } else {
307 rc = STATUS_INVALID_BUFFER_SIZE;
308 }
309 }
310
311 goto done;
312 }
313
314 /* Get all the top level Flow attributes */
315 if ((NlAttrParse(nlMsgHdr, attrOffset, NlMsgAttrsLen(nlMsgHdr),
316 nlFlowPolicy, ARRAY_SIZE(nlFlowPolicy),
317 flowAttrs, ARRAY_SIZE(flowAttrs)))
318 != TRUE) {
319 OVS_LOG_ERROR("Attr Parsing failed for msg: %p",
320 nlMsgHdr);
321 rc = STATUS_INVALID_PARAMETER;
322 goto done;
323 }
324
325 if (flowAttrs[OVS_FLOW_ATTR_PROBE]) {
326 rc = OvsProbeSupportedFeature(msgIn, flowAttrs[OVS_FLOW_ATTR_KEY]);
327 if (rc != STATUS_SUCCESS) {
328 nlError = NlMapStatusToNlErr(rc);
329 goto done;
330 }
331 }
332
333 if ((rc = _MapNlToFlowPut(msgIn, flowAttrs[OVS_FLOW_ATTR_KEY],
334 flowAttrs[OVS_FLOW_ATTR_ACTIONS],
335 flowAttrs[OVS_FLOW_ATTR_CLEAR],
336 &mappedFlow))
337 != STATUS_SUCCESS) {
338 OVS_LOG_ERROR("Conversion to OvsFlowPut failed");
339 goto done;
340 }
341
342 rc = OvsPutFlowIoctl(&mappedFlow, sizeof (struct OvsFlowPut),
343 &stats);
344 if (rc != STATUS_SUCCESS) {
345 OVS_LOG_ERROR("OvsPutFlowIoctl failed.");
346 /*
347 * Report back to the userspace the flow could not be modified,
348 * created or deleted
349 */
350 nlError = NL_ERROR_NOENT;
351 if (rc == STATUS_DUPLICATE_NAME) {
352 nlError = NL_ERROR_EXIST;
353 }
354 goto done;
355 }
356
357 replyStats.n_packets = stats.packetCount;
358 replyStats.n_bytes = stats.byteCount;
359
360 /* So far so good. Prepare the reply for userspace */
361 NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
362 usrParamsCtx->outputLength);
363
364 /* Prepare nl Msg headers */
365 ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,
366 nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
367 genlMsgHdr->cmd, OVS_FLOW_VERSION,
368 ovsHdr->dp_ifindex);
369 if (!ok) {
370 rc = STATUS_INVALID_BUFFER_SIZE;
371 goto done;
372 } else {
373 rc = STATUS_SUCCESS;
374 }
375
376 /* Append OVS_FLOW_ATTR_KEY attribute. This is need i.e. for flow delete*/
377 if (!NlMsgPutNested(&nlBuf, OVS_FLOW_ATTR_KEY,
378 NlAttrData(flowAttrs[OVS_FLOW_ATTR_KEY]),
379 NlAttrGetSize(flowAttrs[OVS_FLOW_ATTR_KEY]))) {
380 OVS_LOG_ERROR("Adding OVS_FLOW_ATTR_KEY attribute failed.");
381 rc = STATUS_INVALID_BUFFER_SIZE;
382 goto done;
383 }
384
385 /* Append OVS_FLOW_ATTR_STATS attribute */
386 if (!NlMsgPutTailUnspec(&nlBuf, OVS_FLOW_ATTR_STATS,
387 (PCHAR)(&replyStats), sizeof(replyStats))) {
388 OVS_LOG_ERROR("Adding OVS_FLOW_ATTR_STATS attribute failed.");
389 rc = STATUS_INVALID_BUFFER_SIZE;
390 goto done;
391 }
392
393 msgOut->nlMsg.nlmsgLen = NLMSG_ALIGN(NlBufSize(&nlBuf));
394 *replyLen = msgOut->nlMsg.nlmsgLen;
395
396 done:
397
398 if (nlError != NL_ERROR_SUCCESS) {
399 POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
400 usrParamsCtx->outputBuffer;
401
402 ASSERT(msgError);
403 NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);
404 ASSERT(*replyLen != 0);
405 rc = STATUS_SUCCESS;
406 }
407
408 return rc;
409 }
410
411 /*
412 *----------------------------------------------------------------------------
413 * OvsFlowNlGetCmdHandler --
414 * Handler for OVS_FLOW_CMD_GET/DUMP commands.
415 *----------------------------------------------------------------------------
416 */
417 NTSTATUS
418 OvsFlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
419 UINT32 *replyLen)
420 {
421 NTSTATUS status = STATUS_SUCCESS;
422
423 if (usrParamsCtx->devOp == OVS_TRANSACTION_DEV_OP) {
424 status = _FlowNlGetCmdHandler(usrParamsCtx, replyLen);
425 } else {
426 status = _FlowNlDumpCmdHandler(usrParamsCtx, replyLen);
427 }
428
429 return status;
430 }
431
432 /*
433 *----------------------------------------------------------------------------
434 * _FlowNlGetCmdHandler --
435 * Handler for OVS_FLOW_CMD_GET command.
436 *----------------------------------------------------------------------------
437 */
438 NTSTATUS
439 _FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
440 UINT32 *replyLen)
441 {
442 NTSTATUS rc = STATUS_SUCCESS;
443 POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;
444 PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
445 POVS_HDR ovsHdr = &(msgIn->ovsHdr);
446 PNL_MSG_HDR nlMsgOutHdr = NULL;
447 UINT32 attrOffset = NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN;
448 PNL_ATTR nlAttrs[__OVS_FLOW_ATTR_MAX];
449
450 OvsFlowGetInput getInput;
451 OvsFlowGetOutput getOutput;
452 NL_BUFFER nlBuf;
453 PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX];
454 PNL_ATTR tunnelAttrs[__OVS_TUNNEL_KEY_ATTR_MAX];
455
456 NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
457 usrParamsCtx->outputLength);
458 RtlZeroMemory(&getInput, sizeof(OvsFlowGetInput));
459 RtlZeroMemory(&getOutput, sizeof(OvsFlowGetOutput));
460 UINT32 keyAttrOffset = 0;
461 UINT32 tunnelKeyAttrOffset = 0;
462 BOOLEAN ok;
463 NL_ERROR nlError = NL_ERROR_SUCCESS;
464
465 if (usrParamsCtx->inputLength > usrParamsCtx->outputLength) {
466 /* Should not be the case.
467 * We'll be copying the flow keys back from
468 * input buffer to output buffer. */
469 rc = STATUS_INVALID_PARAMETER;
470 OVS_LOG_ERROR("inputLength: %d GREATER THEN outputLength: %d",
471 usrParamsCtx->inputLength, usrParamsCtx->outputLength);
472 goto done;
473 }
474
475 /* Get all the top level Flow attributes */
476 if ((NlAttrParse(nlMsgHdr, attrOffset, NlMsgAttrsLen(nlMsgHdr),
477 nlFlowPolicy, ARRAY_SIZE(nlFlowPolicy),
478 nlAttrs, ARRAY_SIZE(nlAttrs)))
479 != TRUE) {
480 OVS_LOG_ERROR("Attr Parsing failed for msg: %p",
481 nlMsgHdr);
482 rc = STATUS_INVALID_PARAMETER;
483 goto done;
484 }
485
486 keyAttrOffset = (UINT32)((PCHAR) nlAttrs[OVS_FLOW_ATTR_KEY] -
487 (PCHAR)nlMsgHdr);
488
489 /* Get flow keys attributes */
490 if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset,
491 NlAttrLen(nlAttrs[OVS_FLOW_ATTR_KEY]),
492 nlFlowKeyPolicy, ARRAY_SIZE(nlFlowKeyPolicy),
493 keyAttrs, ARRAY_SIZE(keyAttrs)))
494 != TRUE) {
495 OVS_LOG_ERROR("Key Attr Parsing failed for msg: %p",
496 nlMsgHdr);
497 rc = STATUS_INVALID_PARAMETER;
498 goto done;
499 }
500
501 if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
502 tunnelKeyAttrOffset = (UINT32)((PCHAR)
503 (keyAttrs[OVS_KEY_ATTR_TUNNEL])
504 - (PCHAR)nlMsgHdr);
505
506 /* Get tunnel keys attributes */
507 if ((NlAttrParseNested(nlMsgHdr, tunnelKeyAttrOffset,
508 NlAttrLen(keyAttrs[OVS_KEY_ATTR_TUNNEL]),
509 nlFlowTunnelKeyPolicy,
510 ARRAY_SIZE(nlFlowTunnelKeyPolicy),
511 tunnelAttrs, ARRAY_SIZE(tunnelAttrs)))
512 != TRUE) {
513 OVS_LOG_ERROR("Tunnel key Attr Parsing failed for msg: %p",
514 nlMsgHdr);
515 rc = STATUS_INVALID_PARAMETER;
516 goto done;
517 }
518 }
519
520 _MapKeyAttrToFlowPut(keyAttrs, tunnelAttrs,
521 &(getInput.key));
522
523 getInput.dpNo = ovsHdr->dp_ifindex;
524 getInput.getFlags = FLOW_GET_STATS | FLOW_GET_ACTIONS;
525
526 /* 4th argument is a no op.
527 * We are keeping this argument to be compatible
528 * with our dpif-windows based interface. */
529 rc = OvsGetFlowIoctl(&getInput, &getOutput);
530 if (rc != STATUS_SUCCESS) {
531 OVS_LOG_ERROR("OvsGetFlowIoctl failed.");
532 /*
533 * Report back to the userspace the flow could not be found
534 */
535 nlError = NL_ERROR_NOENT;
536 goto done;
537 }
538
539 /* Lets prepare the reply. */
540 nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, 0, 0));
541
542 /* Input already has all the attributes for the flow key.
543 * Lets copy the values back. */
544 ok = NlMsgPutTail(&nlBuf, (PCHAR)(usrParamsCtx->inputBuffer),
545 usrParamsCtx->inputLength);
546 if (!ok) {
547 OVS_LOG_ERROR("Could not copy the data to the buffer tail");
548 goto done;
549 }
550
551 rc = _MapFlowStatsToNlStats(&nlBuf, &((getOutput.info).stats));
552 if (rc != STATUS_SUCCESS) {
553 OVS_LOG_ERROR("_OvsFlowMapFlowKeyToNlStats failed.");
554 goto done;
555 }
556
557 rc = _MapFlowActionToNlAction(&nlBuf, ((getOutput.info).actionsLen),
558 getOutput.info.actions);
559 if (rc != STATUS_SUCCESS) {
560 OVS_LOG_ERROR("_MapFlowActionToNlAction failed.");
561 goto done;
562 }
563
564 NlMsgSetSize(nlMsgOutHdr, NlBufSize(&nlBuf));
565 NlMsgAlignSize(nlMsgOutHdr);
566 *replyLen += NlMsgSize(nlMsgOutHdr);
567
568 done:
569 if (nlError != NL_ERROR_SUCCESS) {
570 POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
571 usrParamsCtx->outputBuffer;
572
573 ASSERT(msgError);
574 NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);
575 ASSERT(*replyLen != 0);
576 rc = STATUS_SUCCESS;
577 }
578
579 return rc;
580 }
581
582 /*
583 *----------------------------------------------------------------------------
584 * _FlowNlDumpCmdHandler --
585 * Handler for OVS_FLOW_CMD_DUMP command.
586 *----------------------------------------------------------------------------
587 */
588 NTSTATUS
589 _FlowNlDumpCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
590 UINT32 *replyLen)
591 {
592 NTSTATUS rc = STATUS_SUCCESS;
593 UINT32 temp = 0; /* To keep compiler happy for calling OvsDoDumpFlows */
594 NL_ERROR nlError = NL_ERROR_SUCCESS;
595 POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)
596 (usrParamsCtx->ovsInstance);
597 POVS_MESSAGE msgIn = instance->dumpState.ovsMsg;
598
599 if (usrParamsCtx->devOp == OVS_WRITE_DEV_OP) {
600 /* Dump Start */
601 OvsSetupDumpStart(usrParamsCtx);
602 goto done;
603 }
604
605 PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
606 PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
607 POVS_HDR ovsHdr = &(msgIn->ovsHdr);
608 PNL_MSG_HDR nlMsgOutHdr = NULL;
609 UINT32 hdrOffset = 0;
610
611 /* Get Next */
612 OvsFlowDumpOutput dumpOutput;
613 OvsFlowDumpInput dumpInput;
614 NL_BUFFER nlBuf;
615
616 NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
617 usrParamsCtx->outputLength);
618
619 ASSERT(usrParamsCtx->devOp == OVS_READ_DEV_OP);
620 ASSERT(usrParamsCtx->outputLength);
621
622 RtlZeroMemory(&dumpInput, sizeof(OvsFlowDumpInput));
623 RtlZeroMemory(&dumpOutput, sizeof(OvsFlowDumpOutput));
624
625 dumpInput.dpNo = ovsHdr->dp_ifindex;
626 dumpInput.getFlags = FLOW_GET_KEY | FLOW_GET_STATS | FLOW_GET_ACTIONS;
627
628 /* Lets provide as many flows to userspace as possible. */
629 do {
630 dumpInput.position[0] = instance->dumpState.index[0];
631 dumpInput.position[1] = instance->dumpState.index[1];
632
633 rc = OvsDoDumpFlows(&dumpInput, &dumpOutput, &temp);
634 if (rc != STATUS_SUCCESS) {
635 OVS_LOG_ERROR("OvsDoDumpFlows failed with rc: %d", rc);
636 /*
637 * Report back to the userspace the flows could not be found
638 */
639 nlError = NL_ERROR_NOENT;
640 break;
641 }
642
643 /* Done with Dump, send NLMSG_DONE */
644 if (!(dumpOutput.n)) {
645 BOOLEAN ok;
646
647 OVS_LOG_INFO("Dump Done");
648
649 nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, NlBufSize(&nlBuf), 0));
650 ok = NlFillNlHdr(&nlBuf, NLMSG_DONE, NLM_F_MULTI,
651 nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid);
652
653 if (!ok) {
654 rc = STATUS_INVALID_BUFFER_SIZE;
655 OVS_LOG_ERROR("Unable to prepare DUMP_DONE reply.");
656 break;
657 } else {
658 rc = STATUS_SUCCESS;
659 }
660
661 NlMsgAlignSize(nlMsgOutHdr);
662 *replyLen += NlMsgSize(nlMsgOutHdr);
663
664 FreeUserDumpState(instance);
665 break;
666 } else {
667 BOOLEAN ok;
668
669 hdrOffset = NlBufSize(&nlBuf);
670 nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, hdrOffset, 0));
671
672 /* Netlink header */
673 ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, NLM_F_MULTI,
674 nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
675 genlMsgHdr->cmd, genlMsgHdr->version,
676 ovsHdr->dp_ifindex);
677
678 if (!ok) {
679 /* Reset rc to success so that we can
680 * send already added messages to user space. */
681 rc = STATUS_SUCCESS;
682 break;
683 }
684
685 /* Time to add attributes */
686 rc = _MapFlowInfoToNl(&nlBuf, &(dumpOutput.flow));
687 if (rc != STATUS_SUCCESS) {
688 /* Adding the attribute failed, we are out of
689 space in the buffer, remove the appended OVS header */
690 NlMsgSetSize(nlMsgOutHdr,
691 NlMsgSize(nlMsgOutHdr) -
692 sizeof(struct _OVS_MESSAGE));
693
694 /* Reset rc to success so that we can
695 * send already added messages to user space. */
696 rc = STATUS_SUCCESS;
697 break;
698 }
699
700 NlMsgSetSize(nlMsgOutHdr, NlBufSize(&nlBuf) - hdrOffset);
701 NlMsgAlignSize(nlMsgOutHdr);
702 *replyLen += NlMsgSize(nlMsgOutHdr);
703 instance->dumpState.index[0] = dumpOutput.position[0];
704 instance->dumpState.index[1] = dumpOutput.position[1];
705 }
706 } while(TRUE);
707
708 done:
709 if (nlError != NL_ERROR_SUCCESS) {
710 POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
711 usrParamsCtx->outputBuffer;
712 ASSERT(msgError);
713 NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);
714 ASSERT(*replyLen != 0);
715 rc = STATUS_SUCCESS;
716 }
717
718 return rc;
719 }
720
721 /*
722 *----------------------------------------------------------------------------
723 * _MapFlowInfoToNl --
724 * Maps OvsFlowInfo to Netlink attributes.
725 *----------------------------------------------------------------------------
726 */
727 static NTSTATUS
728 _MapFlowInfoToNl(PNL_BUFFER nlBuf, OvsFlowInfo *flowInfo)
729 {
730 NTSTATUS rc;
731
732 rc = MapFlowKeyToNlKey(nlBuf, &(flowInfo->key), OVS_FLOW_ATTR_KEY,
733 OVS_KEY_ATTR_TUNNEL);
734 if (rc != STATUS_SUCCESS) {
735 goto done;
736 }
737
738 rc = _MapFlowStatsToNlStats(nlBuf, &(flowInfo->stats));
739 if (rc != STATUS_SUCCESS) {
740 goto done;
741 }
742
743 rc = _MapFlowActionToNlAction(nlBuf, flowInfo->actionsLen,
744 flowInfo->actions);
745 if (rc != STATUS_SUCCESS) {
746 goto done;
747 }
748
749 done:
750 return rc;
751 }
752
753 UINT64
754 OvsFlowUsedTime(UINT64 flowUsed)
755 {
756 UINT64 currentMs, iddleMs;
757 LARGE_INTEGER tickCount;
758
759 KeQueryTickCount(&tickCount);
760 iddleMs = tickCount.QuadPart - flowUsed;
761 iddleMs *= ovsTimeIncrementPerTick;
762 currentMs = KeQueryPerformanceCounter(&tickCount).QuadPart * 1000 /
763 tickCount.QuadPart;
764 return currentMs - iddleMs;
765 }
766
767 /*
768 *----------------------------------------------------------------------------
769 * _MapFlowStatsToNlStats --
770 * Maps OvsFlowStats to OVS_FLOW_ATTR_STATS attribute.
771 *----------------------------------------------------------------------------
772 */
773 static NTSTATUS
774 _MapFlowStatsToNlStats(PNL_BUFFER nlBuf, OvsFlowStats *flowStats)
775 {
776 NTSTATUS rc = STATUS_SUCCESS;
777 struct ovs_flow_stats replyStats;
778
779 replyStats.n_packets = flowStats->packetCount;
780 replyStats.n_bytes = flowStats->byteCount;
781
782 if (flowStats->used &&
783 !NlMsgPutTailU64(nlBuf, OVS_FLOW_ATTR_USED,
784 OvsFlowUsedTime(flowStats->used))
785 ) {
786 rc = STATUS_INVALID_BUFFER_SIZE;
787 goto done;
788 }
789
790 if (!NlMsgPutTailUnspec(nlBuf, OVS_FLOW_ATTR_STATS,
791 (PCHAR)(&replyStats),
792 sizeof(struct ovs_flow_stats))) {
793 rc = STATUS_INVALID_BUFFER_SIZE;
794 goto done;
795 }
796
797 if (!NlMsgPutTailU8(nlBuf, OVS_FLOW_ATTR_TCP_FLAGS, flowStats->tcpFlags)) {
798 rc = STATUS_INVALID_BUFFER_SIZE;
799 goto done;
800 }
801
802 done:
803 return rc;
804 }
805
806 /*
807 *----------------------------------------------------------------------------
808 * _MapFlowActionToNlAction --
809 * Maps flow actions to OVS_FLOW_ATTR_ACTION attribute.
810 *----------------------------------------------------------------------------
811 */
812 static NTSTATUS
813 _MapFlowActionToNlAction(PNL_BUFFER nlBuf, uint32_t actionsLen,
814 PNL_ATTR actions)
815 {
816 NTSTATUS rc = STATUS_SUCCESS;
817 UINT32 offset = 0;
818
819 offset = NlMsgStartNested(nlBuf, OVS_FLOW_ATTR_ACTIONS);
820 if (!offset) {
821 /* Starting the nested attribute failed. */
822 rc = STATUS_INVALID_BUFFER_SIZE;
823 goto error_nested_start;
824 }
825
826 if (!NlBufCopyAtTail(nlBuf, (PCHAR)actions, actionsLen)) {
827 /* Adding a nested attribute failed. */
828 rc = STATUS_INVALID_BUFFER_SIZE;
829 goto done;
830 }
831
832 done:
833 NlMsgEndNested(nlBuf, offset);
834 error_nested_start:
835 return rc;
836
837 }
838
839 /*
840 *----------------------------------------------------------------------------
841 * MapFlowKeyToNlKey --
842 * Maps OvsFlowKey to OVS_FLOW_ATTR_KEY attribute.
843 *----------------------------------------------------------------------------
844 */
845 NTSTATUS
846 MapFlowKeyToNlKey(PNL_BUFFER nlBuf,
847 OvsFlowKey *flowKey,
848 UINT16 keyType,
849 UINT16 tunKeyType)
850 {
851 NTSTATUS rc = STATUS_SUCCESS;
852 struct ovs_key_ethernet ethKey;
853 UINT32 offset = 0;
854
855 offset = NlMsgStartNested(nlBuf, keyType);
856 if (!offset) {
857 /* Starting the nested attribute failed. */
858 rc = STATUS_UNSUCCESSFUL;
859 goto error_nested_start;
860 }
861
862 if (!NlMsgPutTailU32(nlBuf, OVS_KEY_ATTR_RECIRC_ID,
863 flowKey->recircId)) {
864 rc = STATUS_UNSUCCESSFUL;
865 goto done;
866 }
867
868 if (!NlMsgPutTailU32(nlBuf, OVS_KEY_ATTR_CT_STATE,
869 flowKey->ct.state)) {
870 rc = STATUS_UNSUCCESSFUL;
871 goto done;
872 }
873 if (!NlMsgPutTailU16(nlBuf, OVS_KEY_ATTR_CT_ZONE,
874 flowKey->ct.zone)) {
875 rc = STATUS_UNSUCCESSFUL;
876 goto done;
877 }
878 if (!NlMsgPutTailU32(nlBuf, OVS_KEY_ATTR_CT_MARK,
879 flowKey->ct.mark)) {
880 rc = STATUS_UNSUCCESSFUL;
881 goto done;
882 }
883 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_CT_LABELS,
884 (PCHAR)(&flowKey->ct.labels),
885 sizeof(struct ovs_key_ct_labels))) {
886 rc = STATUS_UNSUCCESSFUL;
887 goto done;
888 }
889
890 if (flowKey->dpHash) {
891 if (!NlMsgPutTailU32(nlBuf, OVS_KEY_ATTR_DP_HASH,
892 flowKey->dpHash)) {
893 rc = STATUS_UNSUCCESSFUL;
894 goto done;
895 }
896 }
897
898 /* Ethernet header */
899 RtlCopyMemory(&(ethKey.eth_src), flowKey->l2.dlSrc, ETH_ADDR_LEN);
900 RtlCopyMemory(&(ethKey.eth_dst), flowKey->l2.dlDst, ETH_ADDR_LEN);
901
902 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ETHERNET,
903 (PCHAR)(&ethKey),
904 sizeof(struct ovs_key_ethernet))) {
905 rc = STATUS_UNSUCCESSFUL;
906 goto done;
907 }
908
909 if (!NlMsgPutTailU32(nlBuf, OVS_KEY_ATTR_IN_PORT,
910 flowKey->l2.inPort)) {
911 rc = STATUS_UNSUCCESSFUL;
912 goto done;
913 }
914
915 if (!NlMsgPutTailU16(nlBuf, OVS_KEY_ATTR_ETHERTYPE,
916 flowKey->l2.dlType)) {
917 rc = STATUS_UNSUCCESSFUL;
918 goto done;
919 }
920
921 if (flowKey->l2.vlanTci) {
922 if (!NlMsgPutTailU16(nlBuf, OVS_KEY_ATTR_VLAN,
923 flowKey->l2.vlanTci)) {
924 rc = STATUS_UNSUCCESSFUL;
925 goto done;
926 }
927 }
928
929 /* ==== L3 + L4 ==== */
930 switch (ntohs(flowKey->l2.dlType)) {
931 case ETH_TYPE_IPV4: {
932 IpKey *ipv4FlowPutKey = &(flowKey->ipKey);
933 rc = _MapFlowIpv4KeyToNlKey(nlBuf, ipv4FlowPutKey);
934 break;
935 }
936
937 case ETH_TYPE_IPV6: {
938 Ipv6Key *ipv6FlowPutKey = &(flowKey->ipv6Key);
939 Icmp6Key *icmpv6FlowPutKey = &(flowKey->icmp6Key);
940 rc = _MapFlowIpv6KeyToNlKey(nlBuf, ipv6FlowPutKey,
941 icmpv6FlowPutKey);
942 break;
943 }
944
945 case ETH_TYPE_ARP:
946 case ETH_TYPE_RARP: {
947 ArpKey *arpFlowPutKey = &(flowKey->arpKey);
948 rc = _MapFlowArpKeyToNlKey(nlBuf, arpFlowPutKey);
949 break;
950 }
951
952 case ETH_TYPE_MPLS:
953 case ETH_TYPE_MPLS_MCAST: {
954 MplsKey *mplsFlowPutKey = &(flowKey->mplsKey);
955 rc = _MapFlowMplsKeyToNlKey(nlBuf, mplsFlowPutKey);
956 break;
957 }
958
959 default:
960 break;
961 }
962
963 if (rc != STATUS_SUCCESS) {
964 goto done;
965 }
966
967 if (flowKey->tunKey.dst) {
968 rc = MapFlowTunKeyToNlKey(nlBuf, &(flowKey->tunKey),
969 tunKeyType);
970 if (rc != STATUS_SUCCESS) {
971 goto done;
972 }
973 }
974
975 done:
976 NlMsgEndNested(nlBuf, offset);
977 error_nested_start:
978 return rc;
979 }
980
981 /*
982 *----------------------------------------------------------------------------
983 * MapFlowTunKeyToNlKey --
984 * Maps OvsIPv4TunnelKey to OVS_TUNNEL_KEY_ATTR_ID attribute.
985 *----------------------------------------------------------------------------
986 */
987 NTSTATUS
988 MapFlowTunKeyToNlKey(PNL_BUFFER nlBuf,
989 OvsIPv4TunnelKey *tunKey,
990 UINT16 tunKeyType)
991 {
992 NTSTATUS rc = STATUS_SUCCESS;
993 UINT32 offset = 0;
994
995 offset = NlMsgStartNested(nlBuf, tunKeyType);
996 if (!offset) {
997 /* Starting the nested attribute failed. */
998 rc = STATUS_UNSUCCESSFUL;
999 goto error_nested_start;
1000 }
1001
1002 if (!NlMsgPutTailU64(nlBuf, OVS_TUNNEL_KEY_ATTR_ID,
1003 tunKey->tunnelId)) {
1004 rc = STATUS_UNSUCCESSFUL;
1005 goto done;
1006 }
1007
1008 if (!NlMsgPutTailU32(nlBuf, OVS_TUNNEL_KEY_ATTR_IPV4_DST,
1009 tunKey->dst)) {
1010 rc = STATUS_UNSUCCESSFUL;
1011 goto done;
1012 }
1013
1014 if (!NlMsgPutTailU32(nlBuf, OVS_TUNNEL_KEY_ATTR_IPV4_SRC,
1015 tunKey->src)) {
1016 rc = STATUS_UNSUCCESSFUL;
1017 goto done;
1018 }
1019
1020 if (!NlMsgPutTailU8(nlBuf, OVS_TUNNEL_KEY_ATTR_TOS,
1021 tunKey->tos)) {
1022 rc = STATUS_UNSUCCESSFUL;
1023 goto done;
1024 }
1025
1026 if (!NlMsgPutTailU8(nlBuf, OVS_TUNNEL_KEY_ATTR_TTL,
1027 tunKey->ttl)) {
1028 rc = STATUS_UNSUCCESSFUL;
1029 goto done;
1030 }
1031
1032 done:
1033 NlMsgEndNested(nlBuf, offset);
1034 error_nested_start:
1035 return rc;
1036 }
1037
1038 /*
1039 *----------------------------------------------------------------------------
1040 * _MapFlowTunKeyToNlKey --
1041 * Maps OvsIPv4FlowPutKey to OVS_KEY_ATTR_IPV4 attribute.
1042 *----------------------------------------------------------------------------
1043 */
1044 static NTSTATUS
1045 _MapFlowIpv4KeyToNlKey(PNL_BUFFER nlBuf, IpKey *ipv4FlowPutKey)
1046 {
1047 NTSTATUS rc = STATUS_SUCCESS;
1048 struct ovs_key_ipv4 ipv4Key;
1049
1050 ipv4Key.ipv4_src = ipv4FlowPutKey->nwSrc;
1051 ipv4Key.ipv4_dst = ipv4FlowPutKey->nwDst;
1052 ipv4Key.ipv4_proto = ipv4FlowPutKey->nwProto;
1053 ipv4Key.ipv4_tos = ipv4FlowPutKey->nwTos;
1054 ipv4Key.ipv4_ttl = ipv4FlowPutKey->nwTtl;
1055 ipv4Key.ipv4_frag = ipv4FlowPutKey->nwFrag;
1056
1057 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_IPV4,
1058 (PCHAR)(&ipv4Key),
1059 sizeof(struct ovs_key_ipv4))) {
1060 rc = STATUS_UNSUCCESSFUL;
1061 goto done;
1062 }
1063
1064 switch (ipv4Key.ipv4_proto) {
1065 case IPPROTO_TCP: {
1066 struct ovs_key_tcp tcpKey;
1067 tcpKey.tcp_src = ipv4FlowPutKey->l4.tpSrc;
1068 tcpKey.tcp_dst = ipv4FlowPutKey->l4.tpDst;
1069 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_TCP,
1070 (PCHAR)(&tcpKey),
1071 sizeof(tcpKey))) {
1072 rc = STATUS_UNSUCCESSFUL;
1073 goto done;
1074 }
1075 break;
1076 }
1077
1078 case IPPROTO_UDP: {
1079 struct ovs_key_udp udpKey;
1080 udpKey.udp_src = ipv4FlowPutKey->l4.tpSrc;
1081 udpKey.udp_dst = ipv4FlowPutKey->l4.tpDst;
1082 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_UDP,
1083 (PCHAR)(&udpKey),
1084 sizeof(udpKey))) {
1085 rc = STATUS_UNSUCCESSFUL;
1086 goto done;
1087 }
1088 break;
1089 }
1090
1091 case IPPROTO_SCTP: {
1092 struct ovs_key_sctp sctpKey;
1093 sctpKey.sctp_src = ipv4FlowPutKey->l4.tpSrc;
1094 sctpKey.sctp_dst = ipv4FlowPutKey->l4.tpDst;
1095 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_SCTP,
1096 (PCHAR)(&sctpKey),
1097 sizeof(sctpKey))) {
1098 rc = STATUS_UNSUCCESSFUL;
1099 goto done;
1100 }
1101 break;
1102 }
1103
1104 case IPPROTO_ICMP: {
1105 struct ovs_key_icmp icmpKey;
1106 icmpKey.icmp_type = (__u8)ntohs(ipv4FlowPutKey->l4.tpSrc);
1107 icmpKey.icmp_code = (__u8)ntohs(ipv4FlowPutKey->l4.tpDst);
1108
1109 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ICMP,
1110 (PCHAR)(&icmpKey),
1111 sizeof(icmpKey))) {
1112 rc = STATUS_UNSUCCESSFUL;
1113 goto done;
1114 }
1115 break;
1116 }
1117
1118 default:
1119 break;
1120 }
1121
1122 done:
1123 return rc;
1124 }
1125
1126 /*
1127 *----------------------------------------------------------------------------
1128 * _MapFlowIpv6KeyToNlKey --
1129 * Maps _MapFlowIpv6KeyToNlKey to OVS_KEY_ATTR_IPV6 attribute.
1130 *----------------------------------------------------------------------------
1131 */
1132 static NTSTATUS
1133 _MapFlowIpv6KeyToNlKey(PNL_BUFFER nlBuf, Ipv6Key *ipv6FlowPutKey,
1134 Icmp6Key *icmpv6FlowPutKey)
1135 {
1136 NTSTATUS rc = STATUS_SUCCESS;
1137 struct ovs_key_ipv6 ipv6Key;
1138
1139 RtlCopyMemory(&(ipv6Key.ipv6_src), &ipv6FlowPutKey->ipv6Src,
1140 sizeof ipv6Key.ipv6_src);
1141 RtlCopyMemory(&(ipv6Key.ipv6_dst), &ipv6FlowPutKey->ipv6Dst,
1142 sizeof ipv6Key.ipv6_dst);
1143
1144 ipv6Key.ipv6_label = ipv6FlowPutKey->ipv6Label;
1145 ipv6Key.ipv6_proto = ipv6FlowPutKey->nwProto;
1146 ipv6Key.ipv6_tclass = ipv6FlowPutKey->nwTos;
1147 ipv6Key.ipv6_hlimit = ipv6FlowPutKey->nwTtl;
1148 ipv6Key.ipv6_frag = ipv6FlowPutKey->nwFrag;
1149
1150 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_IPV6,
1151 (PCHAR)(&ipv6Key),
1152 sizeof(ipv6Key))) {
1153 rc = STATUS_UNSUCCESSFUL;
1154 goto done;
1155 }
1156
1157 switch (ipv6Key.ipv6_proto) {
1158 case IPPROTO_TCP: {
1159 struct ovs_key_tcp tcpKey;
1160 tcpKey.tcp_src = ipv6FlowPutKey->l4.tpSrc;
1161 tcpKey.tcp_dst = ipv6FlowPutKey->l4.tpDst;
1162 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_TCP,
1163 (PCHAR)(&tcpKey),
1164 sizeof(tcpKey))) {
1165 rc = STATUS_UNSUCCESSFUL;
1166 goto done;
1167 }
1168 break;
1169 }
1170
1171 case IPPROTO_UDP: {
1172 struct ovs_key_udp udpKey;
1173 udpKey.udp_src = ipv6FlowPutKey->l4.tpSrc;
1174 udpKey.udp_dst = ipv6FlowPutKey->l4.tpDst;
1175 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_UDP,
1176 (PCHAR)(&udpKey),
1177 sizeof(udpKey))) {
1178 rc = STATUS_UNSUCCESSFUL;
1179 goto done;
1180 }
1181 break;
1182 }
1183
1184 case IPPROTO_SCTP: {
1185 struct ovs_key_sctp sctpKey;
1186 sctpKey.sctp_src = ipv6FlowPutKey->l4.tpSrc;
1187 sctpKey.sctp_dst = ipv6FlowPutKey->l4.tpDst;
1188 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_SCTP,
1189 (PCHAR)(&sctpKey),
1190 sizeof(sctpKey))) {
1191 rc = STATUS_UNSUCCESSFUL;
1192 goto done;
1193 }
1194 break;
1195 }
1196
1197 case IPPROTO_ICMPV6: {
1198 struct ovs_key_icmpv6 icmpV6Key;
1199 struct ovs_key_nd ndKey;
1200
1201 icmpV6Key.icmpv6_type = (__u8)ntohs(icmpv6FlowPutKey->l4.tpSrc);
1202 icmpV6Key.icmpv6_code = (__u8)ntohs(icmpv6FlowPutKey->l4.tpDst);
1203
1204 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ICMPV6,
1205 (PCHAR)(&icmpV6Key),
1206 sizeof(icmpV6Key))) {
1207 rc = STATUS_UNSUCCESSFUL;
1208 goto done;
1209 }
1210
1211 RtlCopyMemory(&(ndKey.nd_target), &icmpv6FlowPutKey->ndTarget,
1212 sizeof(icmpv6FlowPutKey->ndTarget));
1213 RtlCopyMemory(&(ndKey.nd_sll), &icmpv6FlowPutKey->arpSha,
1214 ETH_ADDR_LEN);
1215 RtlCopyMemory(&(ndKey.nd_tll), &icmpv6FlowPutKey->arpTha,
1216 ETH_ADDR_LEN);
1217 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ND,
1218 (PCHAR)(&ndKey),
1219 sizeof(ndKey))) {
1220 rc = STATUS_UNSUCCESSFUL;
1221 goto done;
1222 }
1223
1224 break;
1225 }
1226
1227 default:
1228 break;
1229 }
1230
1231 done:
1232 return rc;
1233 }
1234
1235 /*
1236 *----------------------------------------------------------------------------
1237 * _MapFlowArpKeyToNlKey --
1238 * Maps _MapFlowArpKeyToNlKey to OVS_KEY_ATTR_ARP attribute.
1239 *----------------------------------------------------------------------------
1240 */
1241 static NTSTATUS
1242 _MapFlowArpKeyToNlKey(PNL_BUFFER nlBuf, ArpKey *arpFlowPutKey)
1243 {
1244 NTSTATUS rc = STATUS_SUCCESS;
1245 struct ovs_key_arp arpKey;
1246
1247 arpKey.arp_sip = arpFlowPutKey->nwSrc;
1248 arpKey.arp_tip = arpFlowPutKey->nwDst;
1249
1250 RtlCopyMemory(&(arpKey.arp_sha), arpFlowPutKey->arpSha, ETH_ADDR_LEN);
1251 RtlCopyMemory(&(arpKey.arp_tha), arpFlowPutKey->arpTha, ETH_ADDR_LEN);
1252
1253 /*
1254 * Flow_Extract() stores 'nwProto' in host order for ARP since 'nwProto' is
1255 * 1 byte field and the ARP opcode is 2 bytes, and all of the kernel code
1256 * understand this while looking at an ARP key.
1257 * While we pass up the ARP key to userspace, convert from host order to
1258 * network order. Likewise, when processing an ARP key from userspace,
1259 * convert from network order to host order.
1260 *
1261 * It is important to note that the flow table stores the ARP opcode field
1262 * in host order.
1263 */
1264 arpKey.arp_op = htons(arpFlowPutKey->nwProto);
1265
1266 if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ARP,
1267 (PCHAR)(&arpKey),
1268 sizeof(arpKey))) {
1269 rc = STATUS_UNSUCCESSFUL;
1270 goto done;
1271 }
1272
1273 done:
1274 return rc;
1275 }
1276
1277 /*
1278 *----------------------------------------------------------------------------
1279 * _MapFlowMplsKeyToNlKey --
1280 * Maps _MapFlowMplsKeyToNlKey to OVS_KEY_ATTR_MPLS attribute.
1281 *----------------------------------------------------------------------------
1282 */
1283 static NTSTATUS
1284 _MapFlowMplsKeyToNlKey(PNL_BUFFER nlBuf, MplsKey *mplsFlowPutKey)
1285 {
1286 NTSTATUS rc = STATUS_SUCCESS;
1287 struct ovs_key_mpls *mplsKey;
1288
1289 mplsKey = (struct ovs_key_mpls *)
1290 NlMsgPutTailUnspecUninit(nlBuf, OVS_KEY_ATTR_MPLS, sizeof(*mplsKey));
1291 if (!mplsKey) {
1292 rc = STATUS_UNSUCCESSFUL;
1293 goto done;
1294 }
1295
1296 mplsKey->mpls_lse = mplsFlowPutKey->lse;
1297
1298 done:
1299 return rc;
1300 }
1301
1302 /*
1303 *----------------------------------------------------------------------------
1304 * _MapNlToFlowPut --
1305 * Maps input netlink message to OvsFlowPut.
1306 *----------------------------------------------------------------------------
1307 */
1308 static NTSTATUS
1309 _MapNlToFlowPut(POVS_MESSAGE msgIn, PNL_ATTR keyAttr,
1310 PNL_ATTR actionAttr, PNL_ATTR flowAttrClear,
1311 OvsFlowPut *mappedFlow)
1312 {
1313 NTSTATUS rc = STATUS_SUCCESS;
1314 PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
1315 PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
1316 POVS_HDR ovsHdr = &(msgIn->ovsHdr);
1317
1318 UINT32 keyAttrOffset = (UINT32)((PCHAR)keyAttr - (PCHAR)nlMsgHdr);
1319 UINT32 tunnelKeyAttrOffset;
1320
1321 PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX] = {NULL};
1322 PNL_ATTR tunnelAttrs[__OVS_TUNNEL_KEY_ATTR_MAX] = {NULL};
1323
1324 /* Get flow keys attributes */
1325 if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset, NlAttrLen(keyAttr),
1326 nlFlowKeyPolicy, ARRAY_SIZE(nlFlowKeyPolicy),
1327 keyAttrs, ARRAY_SIZE(keyAttrs)))
1328 != TRUE) {
1329 OVS_LOG_ERROR("Key Attr Parsing failed for msg: %p",
1330 nlMsgHdr);
1331 rc = STATUS_INVALID_PARAMETER;
1332 goto done;
1333 }
1334
1335 if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
1336 tunnelKeyAttrOffset = (UINT32)((PCHAR)
1337 (keyAttrs[OVS_KEY_ATTR_TUNNEL])
1338 - (PCHAR)nlMsgHdr);
1339
1340 /* Get tunnel keys attributes */
1341 if ((NlAttrParseNested(nlMsgHdr, tunnelKeyAttrOffset,
1342 NlAttrLen(keyAttrs[OVS_KEY_ATTR_TUNNEL]),
1343 nlFlowTunnelKeyPolicy,
1344 ARRAY_SIZE(nlFlowTunnelKeyPolicy),
1345 tunnelAttrs, ARRAY_SIZE(tunnelAttrs)))
1346 != TRUE) {
1347 OVS_LOG_ERROR("Tunnel key Attr Parsing failed for msg: %p",
1348 nlMsgHdr);
1349 rc = STATUS_INVALID_PARAMETER;
1350 goto done;
1351 }
1352 }
1353
1354 _MapKeyAttrToFlowPut(keyAttrs, tunnelAttrs,
1355 &(mappedFlow->key));
1356
1357 /* Map the action */
1358 if (actionAttr) {
1359 mappedFlow->actionsLen = NlAttrGetSize(actionAttr);
1360 mappedFlow->actions = NlAttrGet(actionAttr);
1361 }
1362
1363 mappedFlow->dpNo = ovsHdr->dp_ifindex;
1364
1365 _MapNlToFlowPutFlags(genlMsgHdr, flowAttrClear,
1366 mappedFlow);
1367
1368 done:
1369 return rc;
1370 }
1371
1372 /*
1373 *----------------------------------------------------------------------------
1374 * _MapNlToFlowPutFlags --
1375 * Maps netlink message to OvsFlowPut->flags.
1376 *----------------------------------------------------------------------------
1377 */
1378 static VOID
1379 _MapNlToFlowPutFlags(PGENL_MSG_HDR genlMsgHdr,
1380 PNL_ATTR flowAttrClear, OvsFlowPut *mappedFlow)
1381 {
1382 uint32_t flags = 0;
1383
1384 switch (genlMsgHdr->cmd) {
1385 case OVS_FLOW_CMD_NEW:
1386 flags |= OVSWIN_FLOW_PUT_CREATE;
1387 break;
1388 case OVS_FLOW_CMD_DEL:
1389 flags |= OVSWIN_FLOW_PUT_DELETE;
1390 break;
1391 case OVS_FLOW_CMD_SET:
1392 flags |= OVSWIN_FLOW_PUT_MODIFY;
1393 break;
1394 default:
1395 ASSERT(0);
1396 }
1397
1398 if (flowAttrClear) {
1399 flags |= OVSWIN_FLOW_PUT_CLEAR;
1400 }
1401
1402 mappedFlow->flags = flags;
1403 }
1404
1405 /*
1406 *----------------------------------------------------------------------------
1407 * _MapKeyAttrToFlowPut --
1408 * Converts FLOW_KEY attribute to OvsFlowPut->key.
1409 *----------------------------------------------------------------------------
1410 */
1411 static VOID
1412 _MapKeyAttrToFlowPut(PNL_ATTR *keyAttrs,
1413 PNL_ATTR *tunnelAttrs,
1414 OvsFlowKey *destKey)
1415 {
1416 MapTunAttrToFlowPut(keyAttrs, tunnelAttrs, destKey);
1417
1418 if (keyAttrs[OVS_KEY_ATTR_RECIRC_ID]) {
1419 destKey->recircId = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_RECIRC_ID]);
1420 }
1421
1422 if (keyAttrs[OVS_KEY_ATTR_DP_HASH]) {
1423 destKey->dpHash = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_DP_HASH]);
1424 }
1425
1426 if (keyAttrs[OVS_KEY_ATTR_CT_STATE]) {
1427 destKey->ct.state = (NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_CT_STATE]));
1428 }
1429
1430 if (keyAttrs[OVS_KEY_ATTR_CT_ZONE]) {
1431 destKey->ct.zone = (NlAttrGetU16(keyAttrs[OVS_KEY_ATTR_CT_ZONE]));
1432 }
1433
1434 if (keyAttrs[OVS_KEY_ATTR_CT_MARK]) {
1435 destKey->ct.mark = (NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_CT_MARK]));
1436 }
1437
1438 if (keyAttrs[OVS_KEY_ATTR_CT_LABELS]) {
1439 const struct ovs_key_ct_labels *ct_labels;
1440 ct_labels = NlAttrGet(keyAttrs[OVS_KEY_ATTR_CT_LABELS]);
1441 RtlCopyMemory(&destKey->ct.labels, ct_labels, sizeof(struct ovs_key_ct_labels));
1442 }
1443
1444 /* ===== L2 headers ===== */
1445 destKey->l2.inPort = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_IN_PORT]);
1446
1447 if (keyAttrs[OVS_KEY_ATTR_ETHERNET]) {
1448 const struct ovs_key_ethernet *eth_key;
1449 eth_key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ETHERNET]);
1450 RtlCopyMemory(destKey->l2.dlSrc, eth_key->eth_src, ETH_ADDR_LEN);
1451 RtlCopyMemory(destKey->l2.dlDst, eth_key->eth_dst, ETH_ADDR_LEN);
1452 }
1453
1454 /* TODO: Ideally ETHERTYPE should not be optional.
1455 * But during vswitchd bootup we are seeing FLOW_ADD
1456 * requests with no ETHERTYPE attributes.
1457 * Need to verify this. */
1458 if (keyAttrs[OVS_KEY_ATTR_ETHERTYPE]) {
1459 destKey->l2.dlType = (NlAttrGetU16(keyAttrs
1460 [OVS_KEY_ATTR_ETHERTYPE]));
1461 }
1462
1463 if (keyAttrs[OVS_KEY_ATTR_VLAN]) {
1464 destKey->l2.vlanTci = NlAttrGetU16(keyAttrs[OVS_KEY_ATTR_VLAN]);
1465 }
1466
1467 /* ==== L3 + L4. ==== */
1468 destKey->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + OVS_L2_KEY_SIZE
1469 - destKey->l2.offset;
1470
1471 switch (ntohs(destKey->l2.dlType)) {
1472 case ETH_TYPE_IPV4: {
1473
1474 if (keyAttrs[OVS_KEY_ATTR_IPV4]) {
1475 const struct ovs_key_ipv4 *ipv4Key;
1476
1477 ipv4Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_IPV4]);
1478 IpKey *ipv4FlowPutKey = &(destKey->ipKey);
1479 ipv4FlowPutKey->nwSrc = ipv4Key->ipv4_src;
1480 ipv4FlowPutKey->nwDst = ipv4Key->ipv4_dst;
1481 ipv4FlowPutKey->nwProto = ipv4Key->ipv4_proto;
1482 ipv4FlowPutKey->nwTos = ipv4Key->ipv4_tos;
1483 ipv4FlowPutKey->nwTtl = ipv4Key->ipv4_ttl;
1484 ipv4FlowPutKey->nwFrag = ipv4Key->ipv4_frag;
1485
1486 if (keyAttrs[OVS_KEY_ATTR_TCP]) {
1487 const struct ovs_key_tcp *tcpKey;
1488 tcpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_TCP]);
1489 ipv4FlowPutKey->l4.tpSrc = tcpKey->tcp_src;
1490 ipv4FlowPutKey->l4.tpDst = tcpKey->tcp_dst;
1491 }
1492
1493 if (keyAttrs[OVS_KEY_ATTR_UDP]) {
1494 const struct ovs_key_udp *udpKey;
1495 udpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_UDP]);
1496 ipv4FlowPutKey->l4.tpSrc = udpKey->udp_src;
1497 ipv4FlowPutKey->l4.tpDst = udpKey->udp_dst;
1498 }
1499
1500 if (keyAttrs[OVS_KEY_ATTR_SCTP]) {
1501 const struct ovs_key_sctp *sctpKey;
1502 sctpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_SCTP]);
1503 ipv4FlowPutKey->l4.tpSrc = sctpKey->sctp_src;
1504 ipv4FlowPutKey->l4.tpDst = sctpKey->sctp_dst;
1505 }
1506
1507 if (keyAttrs[OVS_KEY_ATTR_ICMP]) {
1508 const struct ovs_key_icmp *icmpKey;
1509 icmpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ICMP]);
1510 ipv4FlowPutKey->l4.tpSrc = htons(icmpKey->icmp_type);
1511 ipv4FlowPutKey->l4.tpDst = htons(icmpKey->icmp_code);
1512 }
1513
1514 destKey->l2.keyLen += OVS_IP_KEY_SIZE;
1515 }
1516 break;
1517 }
1518 case ETH_TYPE_IPV6: {
1519
1520 if (keyAttrs[OVS_KEY_ATTR_IPV6]) {
1521 const struct ovs_key_ipv6 *ipv6Key;
1522
1523 ipv6Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_IPV6]);
1524 Ipv6Key *ipv6FlowPutKey = &(destKey->ipv6Key);
1525
1526 RtlCopyMemory(&ipv6FlowPutKey->ipv6Src, ipv6Key->ipv6_src,
1527 sizeof ipv6Key->ipv6_src);
1528 RtlCopyMemory(&ipv6FlowPutKey->ipv6Dst, ipv6Key->ipv6_dst,
1529 sizeof ipv6Key->ipv6_dst);
1530
1531 ipv6FlowPutKey->ipv6Label = ipv6Key->ipv6_label;
1532 ipv6FlowPutKey->nwProto = ipv6Key->ipv6_proto;
1533 ipv6FlowPutKey->nwTos = ipv6Key->ipv6_tclass;
1534 ipv6FlowPutKey->nwTtl = ipv6Key->ipv6_hlimit;
1535 ipv6FlowPutKey->nwFrag = ipv6Key->ipv6_frag;
1536
1537 if (keyAttrs[OVS_KEY_ATTR_TCP]) {
1538 const struct ovs_key_tcp *tcpKey;
1539 tcpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_TCP]);
1540 ipv6FlowPutKey->l4.tpSrc = tcpKey->tcp_src;
1541 ipv6FlowPutKey->l4.tpDst = tcpKey->tcp_dst;
1542 }
1543
1544 if (keyAttrs[OVS_KEY_ATTR_UDP]) {
1545 const struct ovs_key_udp *udpKey;
1546 udpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_UDP]);
1547 ipv6FlowPutKey->l4.tpSrc = udpKey->udp_src;
1548 ipv6FlowPutKey->l4.tpDst = udpKey->udp_dst;
1549 }
1550
1551 if (keyAttrs[OVS_KEY_ATTR_SCTP]) {
1552 const struct ovs_key_sctp *sctpKey;
1553 sctpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_SCTP]);
1554 ipv6FlowPutKey->l4.tpSrc = sctpKey->sctp_src;
1555 ipv6FlowPutKey->l4.tpDst = sctpKey->sctp_dst;
1556 }
1557
1558 if (keyAttrs[OVS_KEY_ATTR_ICMPV6]) {
1559 const struct ovs_key_icmpv6 *icmpv6Key;
1560
1561 Icmp6Key *icmp6FlowPutKey= &(destKey->icmp6Key);
1562
1563 icmpv6Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ICMPV6]);
1564
1565 icmp6FlowPutKey->l4.tpSrc = htons(icmpv6Key->icmpv6_type);
1566 icmp6FlowPutKey->l4.tpDst = htons(icmpv6Key->icmpv6_code);
1567
1568 if (keyAttrs[OVS_KEY_ATTR_ND]) {
1569 const struct ovs_key_nd *ndKey;
1570
1571 ndKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ND]);
1572 RtlCopyMemory(&icmp6FlowPutKey->ndTarget,
1573 ndKey->nd_target, sizeof (icmp6FlowPutKey->ndTarget));
1574 RtlCopyMemory(icmp6FlowPutKey->arpSha,
1575 ndKey->nd_sll, ETH_ADDR_LEN);
1576 RtlCopyMemory(icmp6FlowPutKey->arpTha,
1577 ndKey->nd_tll, ETH_ADDR_LEN);
1578 }
1579
1580 destKey->l2.keyLen += OVS_ICMPV6_KEY_SIZE;
1581
1582 } else {
1583
1584 destKey->l2.keyLen += OVS_IPV6_KEY_SIZE;
1585 }
1586
1587 ipv6FlowPutKey->pad = 0;
1588 }
1589 break;
1590 }
1591 case ETH_TYPE_ARP:
1592 case ETH_TYPE_RARP: {
1593
1594 if (keyAttrs[OVS_KEY_ATTR_ARP]) {
1595 ArpKey *arpFlowPutKey = &destKey->arpKey;
1596 const struct ovs_key_arp *arpKey;
1597
1598 arpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ARP]);
1599
1600 arpFlowPutKey->nwSrc = arpKey->arp_sip;
1601 arpFlowPutKey->nwDst = arpKey->arp_tip;
1602
1603 RtlCopyMemory(arpFlowPutKey->arpSha, arpKey->arp_sha, ETH_ADDR_LEN);
1604 RtlCopyMemory(arpFlowPutKey->arpTha, arpKey->arp_tha, ETH_ADDR_LEN);
1605 /* Kernel datapath assumes 'arpFlowPutKey->nwProto' to be in host
1606 * order. */
1607 arpFlowPutKey->nwProto = (UINT8)ntohs((arpKey->arp_op));
1608 arpFlowPutKey->pad[0] = 0;
1609 arpFlowPutKey->pad[1] = 0;
1610 arpFlowPutKey->pad[2] = 0;
1611 destKey->l2.keyLen += OVS_ARP_KEY_SIZE;
1612 }
1613 break;
1614 }
1615 case ETH_TYPE_MPLS:
1616 case ETH_TYPE_MPLS_MCAST: {
1617
1618 if (keyAttrs[OVS_KEY_ATTR_MPLS]) {
1619 MplsKey *mplsFlowPutKey = &destKey->mplsKey;
1620 const struct ovs_key_mpls *mplsKey;
1621
1622 mplsKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_MPLS]);
1623
1624 mplsFlowPutKey->lse = mplsKey->mpls_lse;
1625 mplsFlowPutKey->pad[0] = 0;
1626 mplsFlowPutKey->pad[1] = 0;
1627 mplsFlowPutKey->pad[2] = 0;
1628 mplsFlowPutKey->pad[3] = 0;
1629 destKey->l2.keyLen += OVS_MPLS_KEY_SIZE;
1630 }
1631 break;
1632 }
1633 }
1634 }
1635
1636 /*
1637 *----------------------------------------------------------------------------
1638 * MapTunAttrToFlowPut --
1639 * Converts FLOW_TUNNEL_KEY attribute to OvsFlowKey->tunKey.
1640 *----------------------------------------------------------------------------
1641 */
1642 VOID
1643 MapTunAttrToFlowPut(PNL_ATTR *keyAttrs,
1644 PNL_ATTR *tunAttrs,
1645 OvsFlowKey *destKey)
1646 {
1647 if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
1648
1649 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_ID]) {
1650 destKey->tunKey.tunnelId = NlAttrGetU64
1651 (tunAttrs[OVS_TUNNEL_KEY_ATTR_ID]);
1652 destKey->tunKey.flags |= OVS_TNL_F_KEY;
1653 }
1654
1655 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_DST]) {
1656 destKey->tunKey.dst = NlAttrGetU32
1657 (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_DST]);
1658 }
1659
1660 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_SRC]) {
1661 destKey->tunKey.src = NlAttrGetU32
1662 (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_SRC]);
1663 }
1664
1665 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT]) {
1666 destKey->tunKey.flags |= OVS_TNL_F_DONT_FRAGMENT;
1667 }
1668
1669 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_CSUM]) {
1670 destKey->tunKey.flags |= OVS_TNL_F_CSUM;
1671 }
1672
1673 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_TOS]) {
1674 destKey->tunKey.tos = NlAttrGetU8
1675 (tunAttrs[OVS_TUNNEL_KEY_ATTR_TOS]);
1676 }
1677
1678 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_TTL]) {
1679 destKey->tunKey.ttl = NlAttrGetU8
1680 (tunAttrs[OVS_TUNNEL_KEY_ATTR_TTL]);
1681 }
1682
1683 destKey->tunKey.pad = 0;
1684 destKey->l2.offset = 0;
1685 } else {
1686 destKey->tunKey.attr[0] = 0;
1687 destKey->tunKey.attr[1] = 0;
1688 destKey->tunKey.attr[2] = 0;
1689 destKey->l2.offset = sizeof destKey->tunKey;
1690 }
1691 }
1692
1693 /*
1694 *----------------------------------------------------------------------------
1695 * OvsDeleteFlowTable --
1696 * Results:
1697 * NDIS_STATUS_SUCCESS always.
1698 *----------------------------------------------------------------------------
1699 */
1700 NDIS_STATUS
1701 OvsDeleteFlowTable(OVS_DATAPATH *datapath)
1702 {
1703 if (datapath == NULL || datapath->flowTable == NULL) {
1704 return NDIS_STATUS_SUCCESS;
1705 }
1706
1707 DeleteAllFlows(datapath);
1708 OvsFreeMemoryWithTag(datapath->flowTable, OVS_FLOW_POOL_TAG);
1709 datapath->flowTable = NULL;
1710
1711 if (datapath->lock == NULL) {
1712 return NDIS_STATUS_SUCCESS;
1713 }
1714
1715 NdisFreeRWLock(datapath->lock);
1716
1717 return NDIS_STATUS_SUCCESS;
1718 }
1719
1720 /*
1721 *----------------------------------------------------------------------------
1722 * OvsAllocateFlowTable --
1723 * Results:
1724 * NDIS_STATUS_SUCCESS on success.
1725 * NDIS_STATUS_RESOURCES if memory couldn't be allocated
1726 *----------------------------------------------------------------------------
1727 */
1728 NDIS_STATUS
1729 OvsAllocateFlowTable(OVS_DATAPATH *datapath,
1730 POVS_SWITCH_CONTEXT switchContext)
1731 {
1732 PLIST_ENTRY bucket;
1733 int i;
1734
1735 datapath->flowTable = OvsAllocateMemoryWithTag(
1736 OVS_FLOW_TABLE_SIZE * sizeof(LIST_ENTRY), OVS_FLOW_POOL_TAG);
1737 if (!datapath->flowTable) {
1738 return NDIS_STATUS_RESOURCES;
1739 }
1740 for (i = 0; i < OVS_FLOW_TABLE_SIZE; i++) {
1741 bucket = &(datapath->flowTable[i]);
1742 InitializeListHead(bucket);
1743 }
1744 datapath->lock = NdisAllocateRWLock(switchContext->NdisFilterHandle);
1745
1746 if (!datapath->lock) {
1747 return NDIS_STATUS_RESOURCES;
1748 }
1749
1750 return NDIS_STATUS_SUCCESS;
1751 }
1752
1753
1754 /*
1755 *----------------------------------------------------------------------------
1756 * GetStartAddrNBL --
1757 * Get the virtual address of the frame.
1758 *
1759 * Results:
1760 * Virtual address of the frame.
1761 *----------------------------------------------------------------------------
1762 */
1763 static __inline VOID *
1764 GetStartAddrNBL(const NET_BUFFER_LIST *_pNB)
1765 {
1766 PMDL curMdl;
1767 PUINT8 curBuffer;
1768 PEthHdr curHeader;
1769
1770 ASSERT(_pNB);
1771
1772 // Ethernet Header is a guaranteed safe access.
1773 curMdl = (NET_BUFFER_LIST_FIRST_NB(_pNB))->CurrentMdl;
1774 curBuffer = MmGetSystemAddressForMdlSafe(curMdl, LowPagePriority);
1775 if (!curBuffer) {
1776 return NULL;
1777 }
1778
1779 curHeader = (PEthHdr)
1780 (curBuffer + (NET_BUFFER_LIST_FIRST_NB(_pNB))->CurrentMdlOffset);
1781
1782 return (VOID *) curHeader;
1783 }
1784
1785 VOID
1786 OvsFlowUsed(OvsFlow *flow,
1787 const NET_BUFFER_LIST *packet,
1788 const POVS_PACKET_HDR_INFO layers)
1789 {
1790 LARGE_INTEGER tickCount;
1791
1792 KeQueryTickCount(&tickCount);
1793 flow->used = tickCount.QuadPart;
1794 flow->packetCount++;
1795 flow->byteCount += OvsPacketLenNBL(packet);
1796 flow->tcpFlags |= OvsGetTcpFlags(packet, &flow->key, layers);
1797 }
1798
1799
1800 VOID
1801 DeleteAllFlows(OVS_DATAPATH *datapath)
1802 {
1803 INT i;
1804 PLIST_ENTRY bucket;
1805
1806 for (i = 0; i < OVS_FLOW_TABLE_SIZE; i++) {
1807 PLIST_ENTRY next;
1808 bucket = &(datapath->flowTable[i]);
1809 while (!IsListEmpty(bucket)) {
1810 OvsFlow *flow;
1811 next = bucket->Flink;
1812 flow = CONTAINING_RECORD(next, OvsFlow, ListEntry);
1813 RemoveFlow(datapath, &flow);
1814 }
1815 }
1816 }
1817
1818 NDIS_STATUS
1819 OvsGetFlowMetadata(OvsFlowKey *key,
1820 PNL_ATTR *keyAttrs)
1821 {
1822 NDIS_STATUS status = NDIS_STATUS_SUCCESS;
1823
1824 if (keyAttrs[OVS_KEY_ATTR_RECIRC_ID]) {
1825 key->recircId = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_RECIRC_ID]);
1826 }
1827
1828 if (keyAttrs[OVS_KEY_ATTR_DP_HASH]) {
1829 key->dpHash = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_DP_HASH]);
1830 }
1831
1832 if (keyAttrs[OVS_KEY_ATTR_CT_STATE]) {
1833 key->ct.state = (NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_CT_STATE]));
1834 }
1835
1836 if (keyAttrs[OVS_KEY_ATTR_CT_ZONE]) {
1837 key->ct.zone = (NlAttrGetU16(keyAttrs[OVS_KEY_ATTR_CT_ZONE]));
1838 }
1839
1840 if (keyAttrs[OVS_KEY_ATTR_CT_MARK]) {
1841 key->ct.mark = (NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_CT_MARK]));
1842 }
1843
1844 if (keyAttrs[OVS_KEY_ATTR_CT_LABELS]) {
1845 const struct ovs_key_ct_labels *ct_labels;
1846 ct_labels = NlAttrGet(keyAttrs[OVS_KEY_ATTR_CT_LABELS]);
1847 RtlCopyMemory(&key->ct.labels, ct_labels, sizeof(struct ovs_key_ct_labels));
1848 }
1849
1850 return status;
1851 }
1852
1853 /*
1854 *----------------------------------------------------------------------------
1855 * Initializes 'flow' members from 'packet', 'skb_priority', 'tun_id', and
1856 * 'ofp_in_port'.
1857 *
1858 * Initializes 'packet' header pointers as follows:
1859 *
1860 * - packet->l2 to the start of the Ethernet header.
1861 *
1862 * - packet->l3 to just past the Ethernet header, or just past the
1863 * vlan_header if one is present, to the first byte of the payload of the
1864 * Ethernet frame.
1865 *
1866 * - packet->l4 to just past the IPv4 header, if one is present and has a
1867 * correct length, and otherwise NULL.
1868 *
1869 * - packet->l7 to just past the TCP, UDP, SCTP or ICMP header, if one is
1870 * present and has a correct length, and otherwise NULL.
1871 *
1872 * Returns NDIS_STATUS_SUCCESS normally. Fails only if packet data cannot be accessed
1873 * (e.g. if Pkt_CopyBytesOut() returns an error).
1874 *----------------------------------------------------------------------------
1875 */
1876 NDIS_STATUS
1877 OvsExtractFlow(const NET_BUFFER_LIST *packet,
1878 UINT32 inPort,
1879 OvsFlowKey *flow,
1880 POVS_PACKET_HDR_INFO layers,
1881 OvsIPv4TunnelKey *tunKey)
1882 {
1883 struct Eth_Header *eth;
1884 UINT8 offset = 0;
1885 PVOID vlanTagValue;
1886
1887 layers->value = 0;
1888
1889 if (tunKey) {
1890 ASSERT(tunKey->dst != 0);
1891 RtlMoveMemory(&flow->tunKey, tunKey, sizeof flow->tunKey);
1892 flow->l2.offset = 0;
1893 } else {
1894 flow->tunKey.dst = 0;
1895 flow->l2.offset = OVS_WIN_TUNNEL_KEY_SIZE;
1896 }
1897
1898 flow->l2.inPort = inPort;
1899
1900 if ( OvsPacketLenNBL(packet) < ETH_HEADER_LEN_DIX) {
1901 flow->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + 8 - flow->l2.offset;
1902 return NDIS_STATUS_SUCCESS;
1903 }
1904
1905 /* Link layer. */
1906 eth = (Eth_Header *)GetStartAddrNBL((NET_BUFFER_LIST *)packet);
1907 memcpy(flow->l2.dlSrc, eth->src, ETH_ADDR_LENGTH);
1908 memcpy(flow->l2.dlDst, eth->dst, ETH_ADDR_LENGTH);
1909
1910 /*
1911 * vlan_tci.
1912 */
1913 vlanTagValue = NET_BUFFER_LIST_INFO(packet, Ieee8021QNetBufferListInfo);
1914 if (vlanTagValue) {
1915 PNDIS_NET_BUFFER_LIST_8021Q_INFO vlanTag =
1916 (PNDIS_NET_BUFFER_LIST_8021Q_INFO)(PVOID *)&vlanTagValue;
1917 flow->l2.vlanTci = htons(vlanTag->TagHeader.VlanId | OVSWIN_VLAN_CFI |
1918 (vlanTag->TagHeader.UserPriority << 13));
1919 } else {
1920 if (eth->dix.typeNBO == ETH_TYPE_802_1PQ_NBO) {
1921 Eth_802_1pq_Tag *tag= (Eth_802_1pq_Tag *)&eth->dix.typeNBO;
1922 flow->l2.vlanTci = ((UINT16)tag->priority << 13) |
1923 OVSWIN_VLAN_CFI |
1924 ((UINT16)tag->vidHi << 8) | tag->vidLo;
1925 offset = sizeof (Eth_802_1pq_Tag);
1926 } else {
1927 flow->l2.vlanTci = 0;
1928 }
1929 /*
1930 * XXX
1931 * Please note after this point, src mac and dst mac should
1932 * not be accessed through eth
1933 */
1934 eth = (Eth_Header *)((UINT8 *)eth + offset);
1935 }
1936
1937 /*
1938 * dl_type.
1939 *
1940 * XXX assume that at least the first
1941 * 12 bytes of received packets are mapped. This code has the stronger
1942 * assumption that at least the first 22 bytes of 'packet' is mapped (if my
1943 * arithmetic is right).
1944 */
1945 if (ETH_TYPENOT8023(eth->dix.typeNBO)) {
1946 flow->l2.dlType = eth->dix.typeNBO;
1947 layers->l3Offset = ETH_HEADER_LEN_DIX + offset;
1948 } else if (OvsPacketLenNBL(packet) >= ETH_HEADER_LEN_802_3 &&
1949 eth->e802_3.llc.dsap == 0xaa &&
1950 eth->e802_3.llc.ssap == 0xaa &&
1951 eth->e802_3.llc.control == ETH_LLC_CONTROL_UFRAME &&
1952 eth->e802_3.snap.snapOrg[0] == 0x00 &&
1953 eth->e802_3.snap.snapOrg[1] == 0x00 &&
1954 eth->e802_3.snap.snapOrg[2] == 0x00) {
1955 flow->l2.dlType = eth->e802_3.snap.snapType.typeNBO;
1956 layers->l3Offset = ETH_HEADER_LEN_802_3 + offset;
1957 } else {
1958 flow->l2.dlType = htons(OVSWIN_DL_TYPE_NONE);
1959 layers->l3Offset = ETH_HEADER_LEN_DIX + offset;
1960 }
1961
1962 flow->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + OVS_L2_KEY_SIZE - flow->l2.offset;
1963 /* Network layer. */
1964 if (flow->l2.dlType == htons(ETH_TYPE_IPV4)) {
1965 struct IPHdr ip_storage;
1966 const struct IPHdr *nh;
1967 IpKey *ipKey = &flow->ipKey;
1968
1969 flow->l2.keyLen += OVS_IP_KEY_SIZE;
1970 layers->isIPv4 = 1;
1971 nh = OvsGetIp(packet, layers->l3Offset, &ip_storage);
1972 if (nh) {
1973 layers->l4Offset = layers->l3Offset + nh->ihl * 4;
1974
1975 ipKey->nwSrc = nh->saddr;
1976 ipKey->nwDst = nh->daddr;
1977 ipKey->nwProto = nh->protocol;
1978
1979 ipKey->nwTos = nh->tos;
1980 if (nh->frag_off & htons(IP_MF | IP_OFFSET)) {
1981 ipKey->nwFrag = OVS_FRAG_TYPE_FIRST;
1982 if (nh->frag_off & htons(IP_OFFSET)) {
1983 ipKey->nwFrag = OVS_FRAG_TYPE_LATER;
1984 }
1985 } else {
1986 ipKey->nwFrag = OVS_FRAG_TYPE_NONE;
1987 }
1988
1989 ipKey->nwTtl = nh->ttl;
1990 ipKey->l4.tpSrc = 0;
1991 ipKey->l4.tpDst = 0;
1992
1993 if (!(nh->frag_off & htons(IP_OFFSET))) {
1994 if (ipKey->nwProto == SOCKET_IPPROTO_TCP) {
1995 OvsParseTcp(packet, &ipKey->l4, layers);
1996 } else if (ipKey->nwProto == SOCKET_IPPROTO_UDP) {
1997 OvsParseUdp(packet, &ipKey->l4, layers);
1998 } else if (ipKey->nwProto == SOCKET_IPPROTO_SCTP) {
1999 OvsParseSctp(packet, &ipKey->l4, layers);
2000 } else if (ipKey->nwProto == SOCKET_IPPROTO_ICMP) {
2001 ICMPHdr icmpStorage;
2002 const ICMPHdr *icmp;
2003
2004 icmp = OvsGetIcmp(packet, layers->l4Offset, &icmpStorage);
2005 if (icmp) {
2006 ipKey->l4.tpSrc = htons(icmp->type);
2007 ipKey->l4.tpDst = htons(icmp->code);
2008 layers->l7Offset = layers->l4Offset + sizeof *icmp;
2009 }
2010 }
2011 }
2012 } else {
2013 ((UINT64 *)ipKey)[0] = 0;
2014 ((UINT64 *)ipKey)[1] = 0;
2015 }
2016 } else if (flow->l2.dlType == htons(ETH_TYPE_IPV6)) {
2017 NDIS_STATUS status;
2018 flow->l2.keyLen += OVS_IPV6_KEY_SIZE;
2019 status = OvsParseIPv6(packet, flow, layers);
2020 if (status != NDIS_STATUS_SUCCESS) {
2021 memset(&flow->ipv6Key, 0, sizeof (Ipv6Key));
2022 return status;
2023 }
2024 layers->isIPv6 = 1;
2025 flow->ipv6Key.l4.tpSrc = 0;
2026 flow->ipv6Key.l4.tpDst = 0;
2027 flow->ipv6Key.pad = 0;
2028
2029 if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_TCP) {
2030 OvsParseTcp(packet, &(flow->ipv6Key.l4), layers);
2031 } else if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_UDP) {
2032 OvsParseUdp(packet, &(flow->ipv6Key.l4), layers);
2033 } else if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_SCTP) {
2034 OvsParseSctp(packet, &flow->ipv6Key.l4, layers);
2035 } else if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_ICMPV6) {
2036 OvsParseIcmpV6(packet, flow, layers);
2037 flow->l2.keyLen += (OVS_ICMPV6_KEY_SIZE - OVS_IPV6_KEY_SIZE);
2038 }
2039 } else if (flow->l2.dlType == htons(ETH_TYPE_ARP)) {
2040 EtherArp arpStorage;
2041 const EtherArp *arp;
2042 ArpKey *arpKey = &flow->arpKey;
2043 ((UINT64 *)arpKey)[0] = 0;
2044 ((UINT64 *)arpKey)[1] = 0;
2045 ((UINT64 *)arpKey)[2] = 0;
2046 flow->l2.keyLen += OVS_ARP_KEY_SIZE;
2047 arp = OvsGetArp(packet, layers->l3Offset, &arpStorage);
2048 if (arp && arp->ea_hdr.ar_hrd == htons(1) &&
2049 arp->ea_hdr.ar_pro == htons(ETH_TYPE_IPV4) &&
2050 arp->ea_hdr.ar_hln == ETH_ADDR_LENGTH &&
2051 arp->ea_hdr.ar_pln == 4) {
2052 /* We only match on the lower 8 bits of the opcode. */
2053 if (ntohs(arp->ea_hdr.ar_op) <= 0xff) {
2054 arpKey->nwProto = (UINT8)ntohs(arp->ea_hdr.ar_op);
2055 }
2056 if (arpKey->nwProto == ARPOP_REQUEST
2057 || arpKey->nwProto == ARPOP_REPLY) {
2058 memcpy(&arpKey->nwSrc, arp->arp_spa, 4);
2059 memcpy(&arpKey->nwDst, arp->arp_tpa, 4);
2060 memcpy(arpKey->arpSha, arp->arp_sha, ETH_ADDR_LENGTH);
2061 memcpy(arpKey->arpTha, arp->arp_tha, ETH_ADDR_LENGTH);
2062 }
2063 }
2064 } else if (OvsEthertypeIsMpls(flow->l2.dlType)) {
2065 MPLSHdr mplsStorage;
2066 const MPLSHdr *mpls;
2067 MplsKey *mplsKey = &flow->mplsKey;
2068 ((UINT64 *)mplsKey)[0] = 0;
2069 flow->l2.keyLen += OVS_MPLS_KEY_SIZE;
2070
2071 /*
2072 * In the presence of an MPLS label stack the end of the L2
2073 * header and the beginning of the L3 header differ.
2074 *
2075 * A network packet may contain multiple MPLS labels, but we
2076 * are only interested in the topmost label stack entry.
2077 *
2078 * Advance network header to the beginning of the L3 header.
2079 * layers->l3Offset corresponds to the end of the L2 header.
2080 */
2081 for (UINT32 i = 0; i < FLOW_MAX_MPLS_LABELS; i++) {
2082 mpls = OvsGetMpls(packet, layers->l3Offset, &mplsStorage);
2083 if (!mpls) {
2084 break;
2085 }
2086
2087 /* Keep only the topmost MPLS label stack entry. */
2088 if (i == 0) {
2089 mplsKey->lse = mpls->lse;
2090 }
2091
2092 layers->l3Offset += MPLS_HLEN;
2093 layers->l4Offset += MPLS_HLEN;
2094
2095 if (mpls->lse & htonl(MPLS_BOS_MASK)) {
2096 /*
2097 * Bottom of Stack bit is set, which means there are no
2098 * remaining MPLS labels in the packet.
2099 */
2100 break;
2101 }
2102 }
2103 }
2104
2105 return NDIS_STATUS_SUCCESS;
2106 }
2107
2108 __inline BOOLEAN
2109 FlowMemoryEqual(UINT64 *src, UINT64 *dst, UINT32 size)
2110 {
2111 UINT32 i;
2112 ASSERT((size & 0x7) == 0);
2113 ASSERT(((UINT64)src & 0x7) == 0);
2114 ASSERT(((UINT64)dst & 0x7) == 0);
2115 for (i = 0; i < (size >> 3); i++) {
2116 if (src[i] != dst[i]) {
2117 return FALSE;
2118 }
2119 }
2120 return TRUE;
2121 }
2122
2123 __inline BOOLEAN
2124 FlowEqual(OvsFlow *srcFlow,
2125 const OvsFlowKey *dstKey,
2126 UINT8 *dstStart,
2127 UINT64 hash,
2128 UINT32 offset,
2129 UINT16 size)
2130 {
2131 return (srcFlow->hash == hash &&
2132 srcFlow->key.l2.val == dstKey->l2.val &&
2133 srcFlow->key.recircId == dstKey->recircId &&
2134 srcFlow->key.dpHash == dstKey->dpHash &&
2135 srcFlow->key.ct.state == dstKey->ct.state &&
2136 srcFlow->key.ct.zone == dstKey->ct.zone &&
2137 srcFlow->key.ct.mark == dstKey->ct.mark &&
2138 !memcmp(&srcFlow->key.ct.labels, &dstKey->ct.labels,
2139 sizeof(struct ovs_key_ct_labels)) &&
2140 FlowMemoryEqual((UINT64 *)((UINT8 *)&srcFlow->key + offset),
2141 (UINT64 *) dstStart,
2142 size));
2143 }
2144
2145 /*
2146 * ----------------------------------------------------------------------------
2147 * AddFlow --
2148 * Add a flow to flow table.
2149 *
2150 * Results:
2151 * NDIS_STATUS_SUCCESS if no same flow in the flow table.
2152 * ----------------------------------------------------------------------------
2153 */
2154 NTSTATUS
2155 AddFlow(OVS_DATAPATH *datapath, OvsFlow *flow)
2156 {
2157 PLIST_ENTRY head;
2158
2159 if (OvsLookupFlow(datapath, &flow->key, &flow->hash, TRUE) != NULL) {
2160 return STATUS_INVALID_HANDLE;
2161 }
2162
2163 head = &(datapath->flowTable[HASH_BUCKET(flow->hash)]);
2164 /*
2165 * We need fence here to make sure flow's nextPtr is updated before
2166 * head->nextPtr is updated.
2167 */
2168 KeMemoryBarrier();
2169
2170 //KeAcquireSpinLock(&FilterDeviceExtension->NblQueueLock, &oldIrql);
2171 InsertTailList(head, &flow->ListEntry);
2172 //KeReleaseSpinLock(&FilterDeviceExtension->NblQueueLock, oldIrql);
2173
2174 datapath->nFlows++;
2175
2176 return STATUS_SUCCESS;
2177 }
2178
2179
2180 /* ----------------------------------------------------------------------------
2181 * RemoveFlow --
2182 * Remove a flow from flow table, and added to wait list
2183 * ----------------------------------------------------------------------------
2184 */
2185 VOID
2186 RemoveFlow(OVS_DATAPATH *datapath,
2187 OvsFlow **flow)
2188 {
2189 OvsFlow *f = *flow;
2190 *flow = NULL;
2191
2192 ASSERT(datapath->nFlows);
2193 datapath->nFlows--;
2194 // Remove the flow from queue
2195 RemoveEntryList(&f->ListEntry);
2196 FreeFlow(f);
2197 }
2198
2199
2200 /*
2201 * ----------------------------------------------------------------------------
2202 * OvsLookupFlow --
2203 *
2204 * Find flow from flow table based on flow key.
2205 * Caller should either hold portset handle or should
2206 * have a flowRef in datapath or Acquired datapath.
2207 *
2208 * Results:
2209 * Flow pointer if lookup successful.
2210 * NULL if not exists.
2211 * ----------------------------------------------------------------------------
2212 */
2213 OvsFlow *
2214 OvsLookupFlow(OVS_DATAPATH *datapath,
2215 const OvsFlowKey *key,
2216 UINT64 *hash,
2217 BOOLEAN hashValid)
2218 {
2219 PLIST_ENTRY link, head;
2220 UINT16 offset = key->l2.offset;
2221 UINT16 size = key->l2.keyLen;
2222 UINT8 *start;
2223
2224 ASSERT(key->tunKey.dst || offset == sizeof (OvsIPv4TunnelKey));
2225 ASSERT(!key->tunKey.dst || offset == 0);
2226
2227 start = (UINT8 *)key + offset;
2228
2229 if (!hashValid) {
2230 *hash = OvsJhashBytes(start, size, 0);
2231 if (key->recircId) {
2232 *hash = OvsJhashWords((UINT32*)hash, 1, key->recircId);
2233 }
2234 if (key->dpHash) {
2235 *hash = OvsJhashWords((UINT32*)hash, 1, key->dpHash);
2236 }
2237 if (key->ct.state) {
2238 *hash = OvsJhashWords((UINT32*)hash, 1, key->ct.state);
2239 }
2240 if (key->ct.zone) {
2241 *hash = OvsJhashWords((UINT32*)hash, 1, key->ct.zone);
2242 }
2243 if (key->ct.mark) {
2244 *hash = OvsJhashWords((UINT32*)hash, 1, key->ct.zone);
2245 }
2246 if (key->ct.labels.ct_labels) {
2247 UINT32 lblHash = OvsJhashBytes(&key->ct.labels,
2248 sizeof(struct ovs_key_ct_labels),
2249 0);
2250 *hash = OvsJhashWords((UINT32*)hash, 1, lblHash);
2251 }
2252 }
2253
2254 head = &datapath->flowTable[HASH_BUCKET(*hash)];
2255 link = head->Flink;
2256 while (link != head) {
2257 OvsFlow *flow = CONTAINING_RECORD(link, OvsFlow, ListEntry);
2258
2259 if (FlowEqual(flow, key, start, *hash, offset, size)) {
2260 return flow;
2261 }
2262 link = link->Flink;
2263 }
2264 return NULL;
2265 }
2266
2267
2268 /*
2269 * ----------------------------------------------------------------------------
2270 * OvsHashFlow --
2271 * Calculate the hash for the given flow key.
2272 * ----------------------------------------------------------------------------
2273 */
2274 UINT64
2275 OvsHashFlow(const OvsFlowKey *key)
2276 {
2277 UINT16 offset = key->l2.offset;
2278 UINT16 size = key->l2.keyLen;
2279 UINT8 *start;
2280
2281 ASSERT(key->tunKey.dst || offset == sizeof (OvsIPv4TunnelKey));
2282 ASSERT(!key->tunKey.dst || offset == 0);
2283 start = (UINT8 *)key + offset;
2284 return OvsJhashBytes(start, size, 0);
2285 }
2286
2287
2288 /*
2289 * ----------------------------------------------------------------------------
2290 * FreeFlow --
2291 * Free a flow and its actions.
2292 * ----------------------------------------------------------------------------
2293 */
2294 VOID
2295 FreeFlow(OvsFlow *flow)
2296 {
2297 ASSERT(flow);
2298 OvsFreeMemoryWithTag(flow, OVS_FLOW_POOL_TAG);
2299 }
2300
2301 NTSTATUS
2302 OvsDoDumpFlows(OvsFlowDumpInput *dumpInput,
2303 OvsFlowDumpOutput *dumpOutput,
2304 UINT32 *replyLen)
2305 {
2306 UINT32 dpNo;
2307 OVS_DATAPATH *datapath = NULL;
2308 OvsFlow *flow;
2309 PLIST_ENTRY node, head;
2310 UINT32 column = 0;
2311 UINT32 rowIndex, columnIndex;
2312 LOCK_STATE_EX dpLockState;
2313 NTSTATUS status = STATUS_SUCCESS;
2314 BOOLEAN findNextNonEmpty = FALSE;
2315
2316 dpNo = dumpInput->dpNo;
2317 if (gOvsSwitchContext->dpNo != dpNo) {
2318 status = STATUS_INVALID_PARAMETER;
2319 goto exit;
2320 }
2321
2322 rowIndex = dumpInput->position[0];
2323 if (rowIndex >= OVS_FLOW_TABLE_SIZE) {
2324 dumpOutput->n = 0;
2325 *replyLen = sizeof(*dumpOutput);
2326 goto exit;
2327 }
2328
2329 columnIndex = dumpInput->position[1];
2330
2331 datapath = &gOvsSwitchContext->datapath;
2332 ASSERT(datapath);
2333 OvsAcquireDatapathRead(datapath, &dpLockState, FALSE);
2334
2335 head = &datapath->flowTable[rowIndex];
2336 node = head->Flink;
2337
2338 while (column < columnIndex) {
2339 if (node == head) {
2340 break;
2341 }
2342 node = node->Flink;
2343 column++;
2344 }
2345
2346 if (node == head) {
2347 findNextNonEmpty = TRUE;
2348 columnIndex = 0;
2349 }
2350
2351 if (findNextNonEmpty) {
2352 while (head == node) {
2353 if (++rowIndex >= OVS_FLOW_TABLE_SIZE) {
2354 dumpOutput->n = 0;
2355 goto dp_unlock;
2356 }
2357 head = &datapath->flowTable[rowIndex];
2358 node = head->Flink;
2359 }
2360 }
2361
2362 ASSERT(node != head);
2363 ASSERT(rowIndex < OVS_FLOW_TABLE_SIZE);
2364
2365 flow = CONTAINING_RECORD(node, OvsFlow, ListEntry);
2366 status = ReportFlowInfo(flow, dumpInput->getFlags, &dumpOutput->flow);
2367
2368 if (status == STATUS_BUFFER_TOO_SMALL) {
2369 dumpOutput->n = sizeof(OvsFlowDumpOutput) + flow->actionsLen;
2370 *replyLen = sizeof(*dumpOutput);
2371 } else {
2372 dumpOutput->n = 1; //one flow reported.
2373 *replyLen = sizeof(*dumpOutput) + dumpOutput->flow.actionsLen;
2374 }
2375
2376 dumpOutput->position[0] = rowIndex;
2377 dumpOutput->position[1] = ++columnIndex;
2378
2379 dp_unlock:
2380 OvsReleaseDatapath(datapath, &dpLockState);
2381
2382 exit:
2383 return status;
2384 }
2385
2386 static NTSTATUS
2387 ReportFlowInfo(OvsFlow *flow,
2388 UINT32 getFlags,
2389 OvsFlowInfo *info)
2390 {
2391 NTSTATUS status = STATUS_SUCCESS;
2392
2393 if (getFlags & FLOW_GET_KEY) {
2394 // always copy the tunnel key part
2395 RtlCopyMemory(&info->key, &flow->key,
2396 flow->key.l2.keyLen + flow->key.l2.offset);
2397 }
2398
2399 if (getFlags & FLOW_GET_STATS) {
2400 OvsFlowStats *stats = &info->stats;
2401 stats->packetCount = flow->packetCount;
2402 stats->byteCount = flow->byteCount;
2403 stats->used = flow->used;
2404 stats->tcpFlags = flow->tcpFlags;
2405 }
2406
2407 if (getFlags & FLOW_GET_ACTIONS) {
2408 if (flow->actionsLen == 0) {
2409 info->actionsLen = 0;
2410 } else {
2411 info->actions = flow->actions;
2412 info->actionsLen = flow->actionsLen;
2413 }
2414 }
2415
2416 info->key.recircId = flow->key.recircId;
2417 info->key.dpHash = flow->key.dpHash;
2418 info->key.ct.state = flow->key.ct.state;
2419 info->key.ct.zone = flow->key.ct.zone;
2420 info->key.ct.mark = flow->key.ct.mark;
2421 NdisMoveMemory(&info->key.ct.labels,
2422 &flow->key.ct.labels,
2423 sizeof(struct ovs_key_ct_labels));
2424
2425 return status;
2426 }
2427
2428 NTSTATUS
2429 OvsPutFlowIoctl(PVOID inputBuffer,
2430 UINT32 inputLength,
2431 struct OvsFlowStats *stats)
2432 {
2433 NTSTATUS status = STATUS_SUCCESS;
2434 OVS_DATAPATH *datapath = NULL;
2435 ULONG actionsLen;
2436 OvsFlowPut *put;
2437 UINT32 dpNo;
2438 LOCK_STATE_EX dpLockState;
2439
2440 if ((inputLength < sizeof(OvsFlowPut)) || (inputBuffer == NULL)) {
2441 return STATUS_INFO_LENGTH_MISMATCH;
2442 }
2443
2444 put = (OvsFlowPut *)inputBuffer;
2445 if (put->actionsLen > 0) {
2446 actionsLen = put->actionsLen;
2447 } else {
2448 actionsLen = 0;
2449 }
2450
2451 dpNo = put->dpNo;
2452 if (gOvsSwitchContext->dpNo != dpNo) {
2453 status = STATUS_INVALID_PARAMETER;
2454 goto exit;
2455 }
2456
2457 datapath = &gOvsSwitchContext->datapath;
2458 ASSERT(datapath);
2459 OvsAcquireDatapathWrite(datapath, &dpLockState, FALSE);
2460 status = HandleFlowPut(put, datapath, stats);
2461 OvsReleaseDatapath(datapath, &dpLockState);
2462
2463 exit:
2464 return status;
2465 }
2466
2467
2468 /* Handles flow add, modify as well as delete */
2469 static NTSTATUS
2470 HandleFlowPut(OvsFlowPut *put,
2471 OVS_DATAPATH *datapath,
2472 struct OvsFlowStats *stats)
2473 {
2474 BOOLEAN mayCreate, mayModify, mayDelete;
2475 OvsFlow *KernelFlow;
2476 UINT64 hash;
2477 NTSTATUS status = STATUS_SUCCESS;
2478
2479 mayCreate = (put->flags & OVSWIN_FLOW_PUT_CREATE) != 0;
2480 mayModify = (put->flags & OVSWIN_FLOW_PUT_MODIFY) != 0;
2481 mayDelete = (put->flags & OVSWIN_FLOW_PUT_DELETE) != 0;
2482
2483 if ((mayCreate || mayModify) == mayDelete) {
2484 return STATUS_INVALID_PARAMETER;
2485 }
2486
2487 KernelFlow = OvsLookupFlow(datapath, &put->key, &hash, FALSE);
2488 if (!KernelFlow) {
2489 if (!mayCreate) {
2490 return STATUS_INVALID_PARAMETER;
2491 }
2492
2493 status = OvsPrepareFlow(&KernelFlow, put, hash);
2494 if (status != STATUS_SUCCESS) {
2495 return STATUS_UNSUCCESSFUL;
2496 }
2497
2498 status = AddFlow(datapath, KernelFlow);
2499 if (status != STATUS_SUCCESS) {
2500 FreeFlow(KernelFlow);
2501 return STATUS_UNSUCCESSFUL;
2502 }
2503
2504 #if DBG
2505 /* Validate the flow addition */
2506 {
2507 UINT64 newHash;
2508 OvsFlow *flow = OvsLookupFlow(datapath, &put->key, &newHash,
2509 FALSE);
2510 ASSERT(flow);
2511 ASSERT(newHash == hash);
2512 if (!flow || newHash != hash) {
2513 return STATUS_UNSUCCESSFUL;
2514 }
2515 }
2516 #endif
2517 } else {
2518 stats->packetCount = KernelFlow->packetCount;
2519 stats->byteCount = KernelFlow->byteCount;
2520 stats->tcpFlags = KernelFlow->tcpFlags;
2521 stats->used = KernelFlow->used;
2522
2523 if (mayModify) {
2524 OvsFlow *newFlow;
2525 status = OvsPrepareFlow(&newFlow, put, hash);
2526 if (status != STATUS_SUCCESS) {
2527 return STATUS_UNSUCCESSFUL;
2528 }
2529
2530 if ((put->flags & OVSWIN_FLOW_PUT_CLEAR) == 0) {
2531 newFlow->packetCount = KernelFlow->packetCount;
2532 newFlow->byteCount = KernelFlow->byteCount;
2533 newFlow->tcpFlags = KernelFlow->tcpFlags;
2534 newFlow->used = KernelFlow->used;
2535 }
2536 RemoveFlow(datapath, &KernelFlow);
2537 status = AddFlow(datapath, newFlow);
2538 ASSERT(status == STATUS_SUCCESS);
2539
2540 #if DBG
2541 /* Validate the flow addition */
2542 {
2543 UINT64 newHash;
2544 OvsFlow *testflow = OvsLookupFlow(datapath, &put->key,
2545 &newHash, FALSE);
2546 ASSERT(testflow);
2547 ASSERT(newHash == hash);
2548 if (!testflow || newHash != hash) {
2549 FreeFlow(newFlow);
2550 return STATUS_UNSUCCESSFUL;
2551 }
2552 }
2553 #endif
2554 } else {
2555 if (mayDelete) {
2556 if (KernelFlow) {
2557 RemoveFlow(datapath, &KernelFlow);
2558 }
2559 } else {
2560 /* Return duplicate if an identical flow already exists. */
2561 return STATUS_DUPLICATE_NAME;
2562 }
2563 }
2564 }
2565 return STATUS_SUCCESS;
2566 }
2567
2568 static NTSTATUS
2569 OvsPrepareFlow(OvsFlow **flow,
2570 const OvsFlowPut *put,
2571 UINT64 hash)
2572 {
2573 OvsFlow *localFlow = *flow;
2574 NTSTATUS status = STATUS_SUCCESS;
2575
2576 do {
2577 *flow = localFlow =
2578 OvsAllocateMemoryWithTag(sizeof(OvsFlow) + put->actionsLen,
2579 OVS_FLOW_POOL_TAG);
2580 if (localFlow == NULL) {
2581 status = STATUS_NO_MEMORY;
2582 break;
2583 }
2584
2585 localFlow->key = put->key;
2586 localFlow->actionsLen = put->actionsLen;
2587 if (put->actionsLen) {
2588 NdisMoveMemory((PUCHAR)localFlow->actions, put->actions,
2589 put->actionsLen);
2590 }
2591 localFlow->userActionsLen = 0; // 0 indicate no conversion is made
2592 localFlow->used = 0;
2593 localFlow->packetCount = 0;
2594 localFlow->byteCount = 0;
2595 localFlow->tcpFlags = 0;
2596 localFlow->hash = hash;
2597 } while(FALSE);
2598
2599 return status;
2600 }
2601
2602 NTSTATUS
2603 OvsGetFlowIoctl(PVOID inputBuffer,
2604 PVOID outputBuffer)
2605 {
2606 NTSTATUS status = STATUS_SUCCESS;
2607 OVS_DATAPATH *datapath = NULL;
2608 OvsFlow *flow;
2609 UINT32 getFlags, getActionsLen;
2610 OvsFlowGetInput *getInput;
2611 OvsFlowGetOutput *getOutput;
2612 UINT64 hash;
2613 UINT32 dpNo;
2614 LOCK_STATE_EX dpLockState;
2615
2616 getInput = (OvsFlowGetInput *) inputBuffer;
2617 getFlags = getInput->getFlags;
2618 getActionsLen = getInput->actionsLen;
2619
2620 if (outputBuffer == NULL) {
2621 return STATUS_INFO_LENGTH_MISMATCH;
2622 }
2623
2624 dpNo = getInput->dpNo;
2625 if (gOvsSwitchContext->dpNo != dpNo) {
2626 status = STATUS_INVALID_PARAMETER;
2627 goto exit;
2628 }
2629
2630 datapath = &gOvsSwitchContext->datapath;
2631 ASSERT(datapath);
2632 OvsAcquireDatapathRead(datapath, &dpLockState, FALSE);
2633 flow = OvsLookupFlow(datapath, &getInput->key, &hash, FALSE);
2634 if (!flow) {
2635 status = STATUS_INVALID_PARAMETER;
2636 goto dp_unlock;
2637 }
2638
2639 getOutput = (OvsFlowGetOutput *)outputBuffer;
2640 ReportFlowInfo(flow, getFlags, &getOutput->info);
2641
2642 dp_unlock:
2643 OvsReleaseDatapath(datapath, &dpLockState);
2644 exit:
2645 return status;
2646 }
2647
2648 NTSTATUS
2649 OvsFlushFlowIoctl(UINT32 dpNo)
2650 {
2651 NTSTATUS status = STATUS_SUCCESS;
2652 OVS_DATAPATH *datapath = NULL;
2653 LOCK_STATE_EX dpLockState;
2654
2655 if (gOvsSwitchContext->dpNo != dpNo) {
2656 status = STATUS_INVALID_PARAMETER;
2657 goto exit;
2658 }
2659
2660 datapath = &gOvsSwitchContext->datapath;
2661 ASSERT(datapath);
2662 OvsAcquireDatapathWrite(datapath, &dpLockState, FALSE);
2663 DeleteAllFlows(datapath);
2664 OvsReleaseDatapath(datapath, &dpLockState);
2665
2666 exit:
2667 return status;
2668 }
2669
2670 UINT32
2671 OvsFlowKeyAttrSize(void)
2672 {
2673 return NlAttrTotalSize(4) /* OVS_KEY_ATTR_PRIORITY */
2674 + NlAttrTotalSize(0) /* OVS_KEY_ATTR_TUNNEL */
2675 + OvsTunKeyAttrSize()
2676 + NlAttrTotalSize(4) /* OVS_KEY_ATTR_IN_PORT */
2677 + NlAttrTotalSize(4) /* OVS_KEY_ATTR_SKB_MARK */
2678 + NlAttrTotalSize(4) /* OVS_KEY_ATTR_DP_HASH */
2679 + NlAttrTotalSize(4) /* OVS_KEY_ATTR_RECIRC_ID */
2680 + NlAttrTotalSize(4) /* OVS_KEY_ATTR_CT_STATE */
2681 + NlAttrTotalSize(2) /* OVS_KEY_ATTR_CT_ZONE */
2682 + NlAttrTotalSize(4) /* OVS_KEY_ATTR_CT_MARK */
2683 + NlAttrTotalSize(16) /* OVS_KEY_ATTR_CT_LABELS */
2684 + NlAttrTotalSize(12) /* OVS_KEY_ATTR_ETHERNET */
2685 + NlAttrTotalSize(2) /* OVS_KEY_ATTR_ETHERTYPE */
2686 + NlAttrTotalSize(4) /* OVS_KEY_ATTR_VLAN */
2687 + NlAttrTotalSize(0) /* OVS_KEY_ATTR_ENCAP */
2688 + NlAttrTotalSize(2) /* OVS_KEY_ATTR_ETHERTYPE */
2689 + NlAttrTotalSize(40) /* OVS_KEY_ATTR_IPV6 */
2690 + NlAttrTotalSize(2) /* OVS_KEY_ATTR_ICMPV6 */
2691 + NlAttrTotalSize(28); /* OVS_KEY_ATTR_ND */
2692 }
2693
2694 UINT32
2695 OvsTunKeyAttrSize(void)
2696 {
2697 /* Whenever adding new OVS_TUNNEL_KEY_ FIELDS, we should consider
2698 * updating this function.
2699 */
2700 return NlAttrTotalSize(8) /* OVS_TUNNEL_KEY_ATTR_ID */
2701 + NlAttrTotalSize(4) /* OVS_TUNNEL_KEY_ATTR_IPV4_SRC */
2702 + NlAttrTotalSize(4) /* OVS_TUNNEL_KEY_ATTR_IPV4_DST */
2703 + NlAttrTotalSize(1) /* OVS_TUNNEL_KEY_ATTR_TOS */
2704 + NlAttrTotalSize(1) /* OVS_TUNNEL_KEY_ATTR_TTL */
2705 + NlAttrTotalSize(0) /* OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT */
2706 + NlAttrTotalSize(0) /* OVS_TUNNEL_KEY_ATTR_CSUM */
2707 + NlAttrTotalSize(0) /* OVS_TUNNEL_KEY_ATTR_OAM */
2708 + NlAttrTotalSize(256) /* OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS */
2709 + NlAttrTotalSize(2) /* OVS_TUNNEL_KEY_ATTR_TP_SRC */
2710 + NlAttrTotalSize(2); /* OVS_TUNNEL_KEY_ATTR_TP_DST */
2711 }
2712
2713 /*
2714 *----------------------------------------------------------------------------
2715 * OvsProbeSupportedFeature --
2716 * Verifies if the probed feature is supported.
2717 *
2718 * Results:
2719 * STATUS_SUCCESS if the probed feature is supported.
2720 *----------------------------------------------------------------------------
2721 */
2722 static NTSTATUS
2723 OvsProbeSupportedFeature(POVS_MESSAGE msgIn,
2724 PNL_ATTR keyAttr)
2725 {
2726 NTSTATUS status = STATUS_SUCCESS;
2727 PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
2728
2729 UINT32 keyAttrOffset = (UINT32)((PCHAR)keyAttr - (PCHAR)nlMsgHdr);
2730 PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX] = { NULL };
2731
2732 /* Get flow keys attributes */
2733 if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset, NlAttrLen(keyAttr),
2734 nlFlowKeyPolicy, ARRAY_SIZE(nlFlowKeyPolicy),
2735 keyAttrs, ARRAY_SIZE(keyAttrs)))
2736 != TRUE) {
2737 OVS_LOG_ERROR("Key Attr Parsing failed for msg: %p",
2738 nlMsgHdr);
2739 status = STATUS_INVALID_PARAMETER;
2740 goto done;
2741 }
2742
2743 if (keyAttrs[OVS_KEY_ATTR_MPLS] &&
2744 keyAttrs[OVS_KEY_ATTR_ETHERTYPE]) {
2745 ovs_be16 ethType = NlAttrGetU16(keyAttrs[OVS_KEY_ATTR_ETHERTYPE]);
2746
2747 if (OvsEthertypeIsMpls(ethType)) {
2748 if (!OvsCountMplsLabels(keyAttrs[OVS_KEY_ATTR_MPLS])) {
2749 OVS_LOG_ERROR("Maximum supported MPLS labels exceeded.");
2750 status = STATUS_INVALID_MESSAGE;
2751 }
2752 } else {
2753 OVS_LOG_ERROR("Wrong ethertype for MPLS attribute.");
2754 status = STATUS_INVALID_PARAMETER;
2755 }
2756 } else if (keyAttrs[OVS_KEY_ATTR_RECIRC_ID]) {
2757 UINT32 recircId = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_RECIRC_ID]);
2758
2759 if (!recircId) {
2760 OVS_LOG_ERROR("Invalid recirculation ID.");
2761 status = STATUS_INVALID_PARAMETER;
2762 }
2763 } else if (keyAttrs[OVS_KEY_ATTR_CT_STATE]) {
2764 UINT32 state = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_CT_STATE]);
2765 if (state & OVS_CS_F_DST_NAT || state & OVS_CS_F_SRC_NAT) {
2766 status = STATUS_INVALID_PARAMETER;
2767 OVS_LOG_ERROR("Contrack NAT is not supported:%d", state);
2768 }
2769 } else if (keyAttrs[OVS_KEY_ATTR_CT_ZONE]) {
2770 UINT16 zone = (NlAttrGetU16(keyAttrs[OVS_KEY_ATTR_CT_ZONE]));
2771 if (!zone) {
2772 OVS_LOG_ERROR("Invalid zone specified.");
2773 status = STATUS_INVALID_PARAMETER;
2774 }
2775 } else if (keyAttrs[OVS_KEY_ATTR_CT_MARK]) {
2776 UINT32 mark = (NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_CT_MARK]));
2777 if (!mark) {
2778 OVS_LOG_ERROR("Invalid ct mark specified.");
2779 status = STATUS_INVALID_PARAMETER;
2780 }
2781 } else if (keyAttrs[OVS_KEY_ATTR_CT_LABELS]) {
2782 const struct ovs_key_ct_labels *ct_labels;
2783 ct_labels = NlAttrGet(keyAttrs[OVS_KEY_ATTR_CT_LABELS]);
2784 if (!ct_labels->ct_labels) {
2785 OVS_LOG_ERROR("Invalid ct label specified.");
2786 status = STATUS_INVALID_PARAMETER;
2787 }
2788 } else {
2789 OVS_LOG_ERROR("Feature not supported.");
2790 status = STATUS_INVALID_PARAMETER;
2791 }
2792
2793 done:
2794 return status;
2795 }
2796
2797 #pragma warning( pop )