2
* Copyright (c) 2014 VMware, Inc.
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
* you may not use this file except in compliance with the License.
6
* You may obtain a copy of the License at:
8
* http://www.apache.org/licenses/LICENSE-2.0
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
22
#include "PacketParser.h"
28
#define OVS_DBG_MOD OVS_DBG_FLOW
31
#pragma warning( push )
32
#pragma warning( disable:4127 )
34
extern POVS_SWITCH_CONTEXT gOvsSwitchContext;
35
extern UINT64 ovsTimeIncrementPerTick;
37
static NTSTATUS ReportFlowInfo(OvsFlow *flow, UINT32 getFlags,
39
static NTSTATUS HandleFlowPut(OvsFlowPut *put,
40
OVS_DATAPATH *datapath,
41
struct OvsFlowStats *stats);
42
static NTSTATUS OvsPrepareFlow(OvsFlow **flow, const OvsFlowPut *put,
44
static VOID RemoveFlow(OVS_DATAPATH *datapath, OvsFlow **flow);
45
static VOID DeleteAllFlows(OVS_DATAPATH *datapath);
46
static NTSTATUS AddFlow(OVS_DATAPATH *datapath, OvsFlow *flow);
47
static VOID FreeFlow(OvsFlow *flow);
48
static VOID __inline *GetStartAddrNBL(const NET_BUFFER_LIST *_pNB);
49
static NTSTATUS _MapNlToFlowPut(POVS_MESSAGE msgIn, PNL_ATTR keyAttr,
51
PNL_ATTR flowAttrClear,
52
OvsFlowPut *mappedFlow);
53
static VOID _MapKeyAttrToFlowPut(PNL_ATTR *keyAttrs,
54
PNL_ATTR *tunnelAttrs,
57
static VOID _MapTunAttrToFlowPut(PNL_ATTR *keyAttrs,
58
PNL_ATTR *tunnelAttrs,
60
static VOID _MapNlToFlowPutFlags(PGENL_MSG_HDR genlMsgHdr,
61
PNL_ATTR flowAttrClear,
62
OvsFlowPut *mappedFlow);
64
static NTSTATUS _FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
66
static NTSTATUS _FlowNlDumpCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
68
static NTSTATUS _MapFlowInfoToNl(PNL_BUFFER nlBuf,
69
OvsFlowInfo *flowInfo);
70
static NTSTATUS _MapFlowStatsToNlStats(PNL_BUFFER nlBuf,
71
OvsFlowStats *flowStats);
72
static NTSTATUS _MapFlowActionToNlAction(PNL_BUFFER nlBuf,
76
static NTSTATUS _MapFlowIpv4KeyToNlKey(PNL_BUFFER nlBuf,
77
IpKey *ipv4FlowPutKey);
78
static NTSTATUS _MapFlowIpv6KeyToNlKey(PNL_BUFFER nlBuf,
79
Ipv6Key *ipv6FlowPutKey,
80
Icmp6Key *ipv6FlowPutIcmpKey);
81
static NTSTATUS _MapFlowArpKeyToNlKey(PNL_BUFFER nlBuf,
82
ArpKey *arpFlowPutKey);
84
static NTSTATUS OvsDoDumpFlows(OvsFlowDumpInput *dumpInput,
85
OvsFlowDumpOutput *dumpOutput,
89
#define OVS_FLOW_TABLE_SIZE 2048
90
#define OVS_FLOW_TABLE_MASK (OVS_FLOW_TABLE_SIZE -1)
91
#define HASH_BUCKET(hash) ((hash) & OVS_FLOW_TABLE_MASK)
93
/* Flow family related netlink policies */
95
/* For Parsing attributes in FLOW_* commands */
96
const NL_POLICY nlFlowPolicy[] = {
97
[OVS_FLOW_ATTR_KEY] = {.type = NL_A_NESTED, .optional = FALSE},
98
[OVS_FLOW_ATTR_MASK] = {.type = NL_A_NESTED, .optional = TRUE},
99
[OVS_FLOW_ATTR_ACTIONS] = {.type = NL_A_NESTED, .optional = TRUE},
100
[OVS_FLOW_ATTR_STATS] = {.type = NL_A_UNSPEC,
101
.minLen = sizeof(struct ovs_flow_stats),
102
.maxLen = sizeof(struct ovs_flow_stats),
104
[OVS_FLOW_ATTR_TCP_FLAGS] = {NL_A_U8, .optional = TRUE},
105
[OVS_FLOW_ATTR_USED] = {NL_A_U64, .optional = TRUE}
108
/* For Parsing nested OVS_FLOW_ATTR_KEY attributes.
109
* Some of the attributes like OVS_KEY_ATTR_RECIRC_ID
110
* & OVS_KEY_ATTR_MPLS are not supported yet. */
112
const NL_POLICY nlFlowKeyPolicy[] = {
113
[OVS_KEY_ATTR_ENCAP] = {.type = NL_A_VAR_LEN, .optional = TRUE},
114
[OVS_KEY_ATTR_PRIORITY] = {.type = NL_A_UNSPEC, .minLen = 4,
115
.maxLen = 4, .optional = TRUE},
116
[OVS_KEY_ATTR_IN_PORT] = {.type = NL_A_UNSPEC, .minLen = 4,
117
.maxLen = 4, .optional = FALSE},
118
[OVS_KEY_ATTR_ETHERNET] = {.type = NL_A_UNSPEC,
119
.minLen = sizeof(struct ovs_key_ethernet),
120
.maxLen = sizeof(struct ovs_key_ethernet),
122
[OVS_KEY_ATTR_VLAN] = {.type = NL_A_UNSPEC, .minLen = 2,
123
.maxLen = 2, .optional = TRUE},
124
[OVS_KEY_ATTR_ETHERTYPE] = {.type = NL_A_UNSPEC, .minLen = 2,
125
.maxLen = 2, .optional = TRUE},
126
[OVS_KEY_ATTR_IPV4] = {.type = NL_A_UNSPEC,
127
.minLen = sizeof(struct ovs_key_ipv4),
128
.maxLen = sizeof(struct ovs_key_ipv4),
130
[OVS_KEY_ATTR_IPV6] = {.type = NL_A_UNSPEC,
131
.minLen = sizeof(struct ovs_key_ipv6),
132
.maxLen = sizeof(struct ovs_key_ipv6),
134
[OVS_KEY_ATTR_TCP] = {.type = NL_A_UNSPEC,
135
.minLen = sizeof(struct ovs_key_tcp),
136
.maxLen = sizeof(struct ovs_key_tcp),
138
[OVS_KEY_ATTR_UDP] = {.type = NL_A_UNSPEC,
139
.minLen = sizeof(struct ovs_key_udp),
140
.maxLen = sizeof(struct ovs_key_udp),
142
[OVS_KEY_ATTR_ICMP] = {.type = NL_A_UNSPEC,
143
.minLen = sizeof(struct ovs_key_icmp),
144
.maxLen = sizeof(struct ovs_key_icmp),
146
[OVS_KEY_ATTR_ICMPV6] = {.type = NL_A_UNSPEC,
147
.minLen = sizeof(struct ovs_key_icmpv6),
148
.maxLen = sizeof(struct ovs_key_icmpv6),
150
[OVS_KEY_ATTR_ARP] = {.type = NL_A_UNSPEC,
151
.minLen = sizeof(struct ovs_key_arp),
152
.maxLen = sizeof(struct ovs_key_arp),
154
[OVS_KEY_ATTR_ND] = {.type = NL_A_UNSPEC,
155
.minLen = sizeof(struct ovs_key_nd),
156
.maxLen = sizeof(struct ovs_key_nd),
158
[OVS_KEY_ATTR_SKB_MARK] = {.type = NL_A_UNSPEC, .minLen = 4,
159
.maxLen = 4, .optional = TRUE},
160
[OVS_KEY_ATTR_TUNNEL] = {.type = NL_A_VAR_LEN, .optional = TRUE},
161
[OVS_KEY_ATTR_SCTP] = {.type = NL_A_UNSPEC,
162
.minLen = sizeof(struct ovs_key_sctp),
163
.maxLen = sizeof(struct ovs_key_sctp),
165
[OVS_KEY_ATTR_TCP_FLAGS] = {.type = NL_A_UNSPEC,
166
.minLen = 2, .maxLen = 2,
168
[OVS_KEY_ATTR_DP_HASH] = {.type = NL_A_UNSPEC, .minLen = 4,
169
.maxLen = 4, .optional = TRUE},
170
[OVS_KEY_ATTR_RECIRC_ID] = {.type = NL_A_UNSPEC, .minLen = 4,
171
.maxLen = 4, .optional = TRUE},
172
[OVS_KEY_ATTR_MPLS] = {.type = NL_A_VAR_LEN, .optional = TRUE}
175
/* For Parsing nested OVS_KEY_ATTR_TUNNEL attributes */
176
const NL_POLICY nlFlowTunnelKeyPolicy[] = {
177
[OVS_TUNNEL_KEY_ATTR_ID] = {.type = NL_A_UNSPEC, .minLen = 8,
178
.maxLen = 8, .optional = TRUE},
179
[OVS_TUNNEL_KEY_ATTR_IPV4_SRC] = {.type = NL_A_UNSPEC, .minLen = 4,
180
.maxLen = 4, .optional = TRUE},
181
[OVS_TUNNEL_KEY_ATTR_IPV4_DST] = {.type = NL_A_UNSPEC, .minLen = 4 ,
182
.maxLen = 4, .optional = FALSE},
183
[OVS_TUNNEL_KEY_ATTR_TOS] = {.type = NL_A_UNSPEC, .minLen = 1,
184
.maxLen = 1, .optional = TRUE},
185
[OVS_TUNNEL_KEY_ATTR_TTL] = {.type = NL_A_UNSPEC, .minLen = 1,
186
.maxLen = 1, .optional = TRUE},
187
[OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT] = {.type = NL_A_UNSPEC, .minLen = 0,
188
.maxLen = 0, .optional = TRUE},
189
[OVS_TUNNEL_KEY_ATTR_CSUM] = {.type = NL_A_UNSPEC, .minLen = 0,
190
.maxLen = 0, .optional = TRUE},
191
[OVS_TUNNEL_KEY_ATTR_OAM] = {.type = NL_A_UNSPEC, .minLen = 0,
192
.maxLen = 0, .optional = TRUE},
193
[OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS] = {.type = NL_A_VAR_LEN,
197
/* For Parsing nested OVS_FLOW_ATTR_ACTIONS attributes */
198
const NL_POLICY nlFlowActionPolicy[] = {
199
[OVS_ACTION_ATTR_OUTPUT] = {.type = NL_A_UNSPEC, .minLen = sizeof(UINT32),
200
.maxLen = sizeof(UINT32), .optional = TRUE},
201
[OVS_ACTION_ATTR_USERSPACE] = {.type = NL_A_VAR_LEN, .optional = TRUE},
202
[OVS_ACTION_ATTR_PUSH_VLAN] = {.type = NL_A_UNSPEC,
204
sizeof(struct ovs_action_push_vlan),
206
sizeof(struct ovs_action_push_vlan),
208
[OVS_ACTION_ATTR_POP_VLAN] = {.type = NL_A_UNSPEC, .optional = TRUE},
209
[OVS_ACTION_ATTR_PUSH_MPLS] = {.type = NL_A_UNSPEC,
211
sizeof(struct ovs_action_push_mpls),
213
sizeof(struct ovs_action_push_mpls),
215
[OVS_ACTION_ATTR_POP_MPLS] = {.type = NL_A_UNSPEC,
216
.minLen = sizeof(UINT16),
217
.maxLen = sizeof(UINT16),
219
[OVS_ACTION_ATTR_RECIRC] = {.type = NL_A_UNSPEC,
220
.minLen = sizeof(UINT32),
221
.maxLen = sizeof(UINT32),
223
[OVS_ACTION_ATTR_HASH] = {.type = NL_A_UNSPEC,
224
.minLen = sizeof(struct ovs_action_hash),
225
.maxLen = sizeof(struct ovs_action_hash),
227
[OVS_ACTION_ATTR_SET] = {.type = NL_A_VAR_LEN, .optional = TRUE},
228
[OVS_ACTION_ATTR_SAMPLE] = {.type = NL_A_VAR_LEN, .optional = TRUE}
232
*----------------------------------------------------------------------------
233
* Netlink interface for flow commands.
234
*----------------------------------------------------------------------------
238
*----------------------------------------------------------------------------
239
* OvsFlowNewCmdHandler --
240
* Handler for OVS_FLOW_CMD_NEW/SET/DEL command.
241
* It also handles FLUSH case (DEL w/o any key in input)
242
*----------------------------------------------------------------------------
245
OvsFlowNlCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
248
NTSTATUS rc = STATUS_SUCCESS;
250
POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;
251
POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer;
252
PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
253
PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
254
POVS_HDR ovsHdr = &(msgIn->ovsHdr);
255
PNL_ATTR nlAttrs[__OVS_FLOW_ATTR_MAX];
256
UINT32 attrOffset = NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN;
257
OvsFlowPut mappedFlow;
259
struct ovs_flow_stats replyStats;
260
NL_ERROR nlError = NL_ERROR_SUCCESS;
263
RtlZeroMemory(&mappedFlow, sizeof(OvsFlowPut));
264
RtlZeroMemory(&stats, sizeof(stats));
265
RtlZeroMemory(&replyStats, sizeof(replyStats));
267
if (!(usrParamsCtx->outputBuffer)) {
268
/* No output buffer */
269
rc = STATUS_INVALID_BUFFER_SIZE;
273
/* Get all the top level Flow attributes */
274
if ((NlAttrParse(nlMsgHdr, attrOffset, NlMsgAttrsLen(nlMsgHdr),
275
nlFlowPolicy, nlAttrs, ARRAY_SIZE(nlAttrs)))
277
OVS_LOG_ERROR("Attr Parsing failed for msg: %p",
279
rc = STATUS_INVALID_PARAMETER;
283
/* FLOW_DEL command w/o any key input is a flush case. */
284
if ((genlMsgHdr->cmd == OVS_FLOW_CMD_DEL) &&
285
(!(nlAttrs[OVS_FLOW_ATTR_KEY]))) {
287
rc = OvsFlushFlowIoctl(ovsHdr->dp_ifindex);
289
if (rc == STATUS_SUCCESS) {
290
/* XXX: refactor this code. */
291
/* So far so good. Prepare the reply for userspace */
292
NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
293
usrParamsCtx->outputLength);
295
/* Prepare nl Msg headers */
296
ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,
297
nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
298
genlMsgHdr->cmd, OVS_FLOW_VERSION,
301
*replyLen = msgOut->nlMsg.nlmsgLen;
303
rc = STATUS_INVALID_BUFFER_SIZE;
310
if ((rc = _MapNlToFlowPut(msgIn, nlAttrs[OVS_FLOW_ATTR_KEY],
311
nlAttrs[OVS_FLOW_ATTR_ACTIONS], nlAttrs[OVS_FLOW_ATTR_CLEAR],
314
OVS_LOG_ERROR("Conversion to OvsFlowPut failed");
318
rc = OvsPutFlowIoctl(&mappedFlow, sizeof (struct OvsFlowPut),
320
if (rc != STATUS_SUCCESS) {
321
OVS_LOG_ERROR("OvsPutFlowIoctl failed.");
325
replyStats.n_packets = stats.packetCount;
326
replyStats.n_bytes = stats.byteCount;
328
/* So far so good. Prepare the reply for userspace */
329
NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
330
usrParamsCtx->outputLength);
332
/* Prepare nl Msg headers */
333
ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,
334
nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
335
genlMsgHdr->cmd, OVS_FLOW_VERSION,
338
rc = STATUS_INVALID_BUFFER_SIZE;
344
/* Append OVS_FLOW_ATTR_STATS attribute */
345
if (!NlMsgPutTailUnspec(&nlBuf, OVS_FLOW_ATTR_STATS,
346
(PCHAR)(&replyStats), sizeof(replyStats))) {
347
OVS_LOG_ERROR("Adding OVS_FLOW_ATTR_STATS attribute failed.");
348
rc = STATUS_INVALID_BUFFER_SIZE;
352
msgOut->nlMsg.nlmsgLen = NLMSG_ALIGN(NlBufSize(&nlBuf));
353
*replyLen = msgOut->nlMsg.nlmsgLen;
357
if (nlError != NL_ERROR_SUCCESS) {
358
POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
359
usrParamsCtx->outputBuffer;
360
NlBuildErrorMsg(msgIn, msgError, nlError);
361
*replyLen = msgError->nlMsg.nlmsgLen;
369
*----------------------------------------------------------------------------
370
* OvsFlowNlGetCmdHandler --
371
* Handler for OVS_FLOW_CMD_GET/DUMP commands.
372
*----------------------------------------------------------------------------
375
OvsFlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
378
NTSTATUS status = STATUS_SUCCESS;
379
NL_ERROR nlError = NL_ERROR_SUCCESS;
380
POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;
382
if (usrParamsCtx->devOp == OVS_TRANSACTION_DEV_OP) {
383
status = _FlowNlGetCmdHandler(usrParamsCtx, replyLen);
385
/* No trasanctional errors as of now.
386
* If we have something then we need to convert rc to
388
if ((nlError != NL_ERROR_SUCCESS) &&
389
(usrParamsCtx->outputBuffer)) {
390
POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
391
usrParamsCtx->outputBuffer;
392
NlBuildErrorMsg(msgIn, msgError, nlError);
393
*replyLen = msgError->nlMsg.nlmsgLen;
394
status = STATUS_SUCCESS;
398
status = _FlowNlDumpCmdHandler(usrParamsCtx, replyLen);
406
*----------------------------------------------------------------------------
407
* _FlowNlGetCmdHandler --
408
* Handler for OVS_FLOW_CMD_GET command.
409
*----------------------------------------------------------------------------
412
_FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
415
NTSTATUS rc = STATUS_SUCCESS;
416
POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;
417
PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
418
POVS_HDR ovsHdr = &(msgIn->ovsHdr);
419
PNL_MSG_HDR nlMsgOutHdr = NULL;
420
UINT32 attrOffset = NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN;
421
PNL_ATTR nlAttrs[__OVS_FLOW_ATTR_MAX];
423
OvsFlowGetInput getInput;
424
OvsFlowGetOutput getOutput;
426
PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX];
427
PNL_ATTR tunnelAttrs[__OVS_TUNNEL_KEY_ATTR_MAX];
429
NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
430
usrParamsCtx->outputLength);
431
RtlZeroMemory(&getInput, sizeof(OvsFlowGetInput));
432
RtlZeroMemory(&getOutput, sizeof(OvsFlowGetOutput));
433
UINT32 keyAttrOffset = 0;
434
UINT32 tunnelKeyAttrOffset = 0;
437
if (usrParamsCtx->inputLength > usrParamsCtx->outputLength) {
438
/* Should not be the case.
439
* We'll be copying the flow keys back from
440
* input buffer to output buffer. */
441
rc = STATUS_INVALID_PARAMETER;
442
OVS_LOG_ERROR("inputLength: %d GREATER THEN outputLength: %d",
443
usrParamsCtx->inputLength, usrParamsCtx->outputLength);
447
/* Get all the top level Flow attributes */
448
if ((NlAttrParse(nlMsgHdr, attrOffset, NlMsgAttrsLen(nlMsgHdr),
449
nlFlowPolicy, nlAttrs, ARRAY_SIZE(nlAttrs)))
451
OVS_LOG_ERROR("Attr Parsing failed for msg: %p",
453
rc = STATUS_INVALID_PARAMETER;
457
keyAttrOffset = (UINT32)((PCHAR) nlAttrs[OVS_FLOW_ATTR_KEY] -
460
/* Get flow keys attributes */
461
if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset,
462
NlAttrLen(nlAttrs[OVS_FLOW_ATTR_KEY]),
463
nlFlowKeyPolicy, keyAttrs, ARRAY_SIZE(keyAttrs)))
465
OVS_LOG_ERROR("Key Attr Parsing failed for msg: %p",
467
rc = STATUS_INVALID_PARAMETER;
471
if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
472
tunnelKeyAttrOffset = (UINT32)((PCHAR)
473
(keyAttrs[OVS_KEY_ATTR_TUNNEL])
476
/* Get tunnel keys attributes */
477
if ((NlAttrParseNested(nlMsgHdr, tunnelKeyAttrOffset,
478
NlAttrLen(keyAttrs[OVS_KEY_ATTR_TUNNEL]),
479
nlFlowTunnelKeyPolicy,
480
tunnelAttrs, ARRAY_SIZE(tunnelAttrs)))
482
OVS_LOG_ERROR("Tunnel key Attr Parsing failed for msg: %p",
484
rc = STATUS_INVALID_PARAMETER;
489
_MapKeyAttrToFlowPut(keyAttrs, tunnelAttrs,
492
getInput.dpNo = ovsHdr->dp_ifindex;
493
getInput.getFlags = FLOW_GET_STATS | FLOW_GET_ACTIONS;
495
/* 4th argument is a no op.
496
* We are keeping this argument to be compatible
497
* with our dpif-windows based interface. */
498
rc = OvsGetFlowIoctl(&getInput, &getOutput);
499
if (rc != STATUS_SUCCESS) {
500
OVS_LOG_ERROR("OvsGetFlowIoctl failed.");
504
/* Lets prepare the reply. */
505
nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, 0, 0));
507
/* Input already has all the attributes for the flow key.
508
* Lets copy the values back. */
509
ok = NlMsgPutTail(&nlBuf, (PCHAR)(usrParamsCtx->inputBuffer),
510
usrParamsCtx->inputLength);
512
OVS_LOG_ERROR("Could not copy the data to the buffer tail");
516
rc = _MapFlowStatsToNlStats(&nlBuf, &((getOutput.info).stats));
517
if (rc != STATUS_SUCCESS) {
518
OVS_LOG_ERROR("_OvsFlowMapFlowKeyToNlStats failed.");
522
rc = _MapFlowActionToNlAction(&nlBuf, ((getOutput.info).actionsLen),
523
getOutput.info.actions);
524
if (rc != STATUS_SUCCESS) {
525
OVS_LOG_ERROR("_MapFlowActionToNlAction failed.");
529
NlMsgSetSize(nlMsgOutHdr, NlBufSize(&nlBuf));
530
NlMsgAlignSize(nlMsgOutHdr);
531
*replyLen += NlMsgSize(nlMsgOutHdr);
538
*----------------------------------------------------------------------------
539
* _FlowNlDumpCmdHandler --
540
* Handler for OVS_FLOW_CMD_DUMP command.
541
*----------------------------------------------------------------------------
544
_FlowNlDumpCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
547
NTSTATUS rc = STATUS_SUCCESS;
548
UINT32 temp = 0; /* To keep compiler happy for calling OvsDoDumpFlows */
550
POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)
551
(usrParamsCtx->ovsInstance);
553
if (usrParamsCtx->devOp == OVS_WRITE_DEV_OP) {
555
OvsSetupDumpStart(usrParamsCtx);
559
POVS_MESSAGE msgIn = instance->dumpState.ovsMsg;
560
PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
561
PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
562
POVS_HDR ovsHdr = &(msgIn->ovsHdr);
563
PNL_MSG_HDR nlMsgOutHdr = NULL;
564
UINT32 hdrOffset = 0;
567
OvsFlowDumpOutput dumpOutput;
568
OvsFlowDumpInput dumpInput;
571
NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
572
usrParamsCtx->outputLength);
574
ASSERT(usrParamsCtx->devOp == OVS_READ_DEV_OP);
575
ASSERT(usrParamsCtx->outputLength);
577
RtlZeroMemory(&dumpInput, sizeof(OvsFlowDumpInput));
578
RtlZeroMemory(&dumpOutput, sizeof(OvsFlowDumpOutput));
580
dumpInput.dpNo = ovsHdr->dp_ifindex;
581
dumpInput.getFlags = FLOW_GET_KEY | FLOW_GET_STATS | FLOW_GET_ACTIONS;
583
/* Lets provide as many flows to userspace as possible. */
585
dumpInput.position[0] = instance->dumpState.index[0];
586
dumpInput.position[1] = instance->dumpState.index[1];
588
rc = OvsDoDumpFlows(&dumpInput, &dumpOutput, &temp);
589
if (rc != STATUS_SUCCESS) {
590
OVS_LOG_ERROR("OvsDoDumpFlows failed with rc: %d", rc);
594
/* Done with Dump, send NLMSG_DONE */
595
if (!(dumpOutput.n)) {
598
OVS_LOG_INFO("Dump Done");
600
nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, NlBufSize(&nlBuf), 0));
601
ok = NlFillNlHdr(&nlBuf, NLMSG_DONE, NLM_F_MULTI,
602
nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid);
605
rc = STATUS_INVALID_BUFFER_SIZE;
606
OVS_LOG_ERROR("Unable to prepare DUMP_DONE reply.");
612
NlMsgAlignSize(nlMsgOutHdr);
613
*replyLen += NlMsgSize(nlMsgOutHdr);
615
FreeUserDumpState(instance);
620
hdrOffset = NlBufSize(&nlBuf);
621
nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, hdrOffset, 0));
624
ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, NLM_F_MULTI,
625
nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
626
genlMsgHdr->cmd, genlMsgHdr->version,
630
/* Reset rc to success so that we can
631
* send already added messages to user space. */
636
/* Time to add attributes */
637
rc = _MapFlowInfoToNl(&nlBuf, &(dumpOutput.flow));
638
if (rc != STATUS_SUCCESS) {
639
/* Adding the attribute failed, we are out of
640
space in the buffer, remove the appended OVS header */
641
NlMsgSetSize(nlMsgOutHdr,
642
NlMsgSize(nlMsgOutHdr) -
643
sizeof(struct _OVS_MESSAGE));
645
/* Reset rc to success so that we can
646
* send already added messages to user space. */
651
NlMsgSetSize(nlMsgOutHdr, NlBufSize(&nlBuf) - hdrOffset);
652
NlMsgAlignSize(nlMsgOutHdr);
653
*replyLen += NlMsgSize(nlMsgOutHdr);
654
instance->dumpState.index[0] = dumpOutput.position[0];
655
instance->dumpState.index[1] = dumpOutput.position[1];
664
*----------------------------------------------------------------------------
665
* _MapFlowInfoToNl --
666
* Maps OvsFlowInfo to Netlink attributes.
667
*----------------------------------------------------------------------------
670
_MapFlowInfoToNl(PNL_BUFFER nlBuf, OvsFlowInfo *flowInfo)
672
NTSTATUS rc = STATUS_SUCCESS;
674
rc = MapFlowKeyToNlKey(nlBuf, &(flowInfo->key), OVS_FLOW_ATTR_KEY,
675
OVS_KEY_ATTR_TUNNEL);
676
if (rc != STATUS_SUCCESS) {
680
rc = _MapFlowStatsToNlStats(nlBuf, &(flowInfo->stats));
681
if (rc != STATUS_SUCCESS) {
685
rc = _MapFlowActionToNlAction(nlBuf, flowInfo->actionsLen,
687
if (rc != STATUS_SUCCESS) {
696
*----------------------------------------------------------------------------
697
* _MapFlowStatsToNlStats --
698
* Maps OvsFlowStats to OVS_FLOW_ATTR_STATS attribute.
699
*----------------------------------------------------------------------------
702
_MapFlowStatsToNlStats(PNL_BUFFER nlBuf, OvsFlowStats *flowStats)
704
NTSTATUS rc = STATUS_SUCCESS;
705
struct ovs_flow_stats replyStats;
707
replyStats.n_packets = flowStats->packetCount;
708
replyStats.n_bytes = flowStats->byteCount;
710
if (!NlMsgPutTailU64(nlBuf, OVS_FLOW_ATTR_USED, flowStats->used)) {
711
rc = STATUS_INVALID_BUFFER_SIZE;
715
if (!NlMsgPutTailUnspec(nlBuf, OVS_FLOW_ATTR_STATS,
716
(PCHAR)(&replyStats),
717
sizeof(struct ovs_flow_stats))) {
718
rc = STATUS_INVALID_BUFFER_SIZE;
722
if (!NlMsgPutTailU8(nlBuf, OVS_FLOW_ATTR_TCP_FLAGS, flowStats->tcpFlags)) {
723
rc = STATUS_INVALID_BUFFER_SIZE;
732
*----------------------------------------------------------------------------
733
* _MapFlowActionToNlAction --
734
* Maps flow actions to OVS_FLOW_ATTR_ACTION attribute.
735
*----------------------------------------------------------------------------
738
_MapFlowActionToNlAction(PNL_BUFFER nlBuf, uint32_t actionsLen,
741
NTSTATUS rc = STATUS_SUCCESS;
744
offset = NlMsgStartNested(nlBuf, OVS_FLOW_ATTR_ACTIONS);
746
/* Starting the nested attribute failed. */
747
rc = STATUS_INVALID_BUFFER_SIZE;
748
goto error_nested_start;
751
if (!NlBufCopyAtTail(nlBuf, (PCHAR)actions, actionsLen)) {
752
/* Adding a nested attribute failed. */
753
rc = STATUS_INVALID_BUFFER_SIZE;
758
NlMsgEndNested(nlBuf, offset);
765
*----------------------------------------------------------------------------
766
* MapFlowKeyToNlKey --
767
* Maps OvsFlowKey to OVS_FLOW_ATTR_KEY attribute.
768
*----------------------------------------------------------------------------
771
MapFlowKeyToNlKey(PNL_BUFFER nlBuf,
776
NTSTATUS rc = STATUS_SUCCESS;
777
struct ovs_key_ethernet ethKey;
780
offset = NlMsgStartNested(nlBuf, keyType);
782
/* Starting the nested attribute failed. */
783
rc = STATUS_UNSUCCESSFUL;
784
goto error_nested_start;
787
/* Ethernet header */
788
RtlCopyMemory(&(ethKey.eth_src), flowKey->l2.dlSrc, ETH_ADDR_LEN);
789
RtlCopyMemory(&(ethKey.eth_dst), flowKey->l2.dlDst, ETH_ADDR_LEN);
791
if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ETHERNET,
793
sizeof(struct ovs_key_ethernet))) {
794
rc = STATUS_UNSUCCESSFUL;
798
if (!NlMsgPutTailU32(nlBuf, OVS_KEY_ATTR_IN_PORT,
799
flowKey->l2.inPort)) {
800
rc = STATUS_UNSUCCESSFUL;
804
if (!NlMsgPutTailU16(nlBuf, OVS_KEY_ATTR_ETHERTYPE,
805
flowKey->l2.dlType)) {
806
rc = STATUS_UNSUCCESSFUL;
810
if (flowKey->l2.vlanTci) {
811
if (!NlMsgPutTailU16(nlBuf, OVS_KEY_ATTR_VLAN,
812
flowKey->l2.vlanTci)) {
813
rc = STATUS_UNSUCCESSFUL;
818
/* ==== L3 + L4 ==== */
819
switch (ntohs(flowKey->l2.dlType)) {
820
case ETH_TYPE_IPV4: {
821
IpKey *ipv4FlowPutKey = &(flowKey->ipKey);
822
rc = _MapFlowIpv4KeyToNlKey(nlBuf, ipv4FlowPutKey);
826
case ETH_TYPE_IPV6: {
827
Ipv6Key *ipv6FlowPutKey = &(flowKey->ipv6Key);
828
Icmp6Key *icmpv6FlowPutKey = &(flowKey->icmp6Key);
829
rc = _MapFlowIpv6KeyToNlKey(nlBuf, ipv6FlowPutKey,
835
case ETH_TYPE_RARP: {
836
ArpKey *arpFlowPutKey = &(flowKey->arpKey);
837
rc = _MapFlowArpKeyToNlKey(nlBuf, arpFlowPutKey);
845
if (rc != STATUS_SUCCESS) {
849
if (flowKey->tunKey.dst) {
850
rc = MapFlowTunKeyToNlKey(nlBuf, &(flowKey->tunKey),
852
if (rc != STATUS_SUCCESS) {
858
NlMsgEndNested(nlBuf, offset);
864
*----------------------------------------------------------------------------
865
* MapFlowTunKeyToNlKey --
866
* Maps OvsIPv4TunnelKey to OVS_TUNNEL_KEY_ATTR_ID attribute.
867
*----------------------------------------------------------------------------
870
MapFlowTunKeyToNlKey(PNL_BUFFER nlBuf,
871
OvsIPv4TunnelKey *tunKey,
874
NTSTATUS rc = STATUS_SUCCESS;
877
offset = NlMsgStartNested(nlBuf, tunKeyType);
879
/* Starting the nested attribute failed. */
880
rc = STATUS_UNSUCCESSFUL;
881
goto error_nested_start;
884
if (!NlMsgPutTailU64(nlBuf, OVS_TUNNEL_KEY_ATTR_ID,
886
rc = STATUS_UNSUCCESSFUL;
890
if (!NlMsgPutTailU32(nlBuf, OVS_TUNNEL_KEY_ATTR_IPV4_DST,
892
rc = STATUS_UNSUCCESSFUL;
896
if (!NlMsgPutTailU32(nlBuf, OVS_TUNNEL_KEY_ATTR_IPV4_SRC,
898
rc = STATUS_UNSUCCESSFUL;
902
if (!NlMsgPutTailU8(nlBuf, OVS_TUNNEL_KEY_ATTR_TOS,
904
rc = STATUS_UNSUCCESSFUL;
908
if (!NlMsgPutTailU8(nlBuf, OVS_TUNNEL_KEY_ATTR_TTL,
910
rc = STATUS_UNSUCCESSFUL;
915
NlMsgEndNested(nlBuf, offset);
921
*----------------------------------------------------------------------------
922
* _MapFlowTunKeyToNlKey --
923
* Maps OvsIPv4FlowPutKey to OVS_KEY_ATTR_IPV4 attribute.
924
*----------------------------------------------------------------------------
927
_MapFlowIpv4KeyToNlKey(PNL_BUFFER nlBuf, IpKey *ipv4FlowPutKey)
929
NTSTATUS rc = STATUS_SUCCESS;
930
struct ovs_key_ipv4 ipv4Key;
932
ipv4Key.ipv4_src = ipv4FlowPutKey->nwSrc;
933
ipv4Key.ipv4_dst = ipv4FlowPutKey->nwDst;
934
ipv4Key.ipv4_proto = ipv4FlowPutKey->nwProto;
935
ipv4Key.ipv4_tos = ipv4FlowPutKey->nwTos;
936
ipv4Key.ipv4_ttl = ipv4FlowPutKey->nwTtl;
937
ipv4Key.ipv4_frag = ipv4FlowPutKey->nwFrag;
939
if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_IPV4,
941
sizeof(struct ovs_key_ipv4))) {
942
rc = STATUS_UNSUCCESSFUL;
946
switch (ipv4Key.ipv4_proto) {
948
struct ovs_key_tcp tcpKey;
949
tcpKey.tcp_src = ipv4FlowPutKey->l4.tpSrc;
950
tcpKey.tcp_dst = ipv4FlowPutKey->l4.tpDst;
951
if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_TCP,
954
rc = STATUS_UNSUCCESSFUL;
961
struct ovs_key_udp udpKey;
962
udpKey.udp_src = ipv4FlowPutKey->l4.tpSrc;
963
udpKey.udp_dst = ipv4FlowPutKey->l4.tpDst;
964
if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_UDP,
967
rc = STATUS_UNSUCCESSFUL;
974
struct ovs_key_sctp sctpKey;
975
sctpKey.sctp_src = ipv4FlowPutKey->l4.tpSrc;
976
sctpKey.sctp_dst = ipv4FlowPutKey->l4.tpDst;
977
if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_SCTP,
980
rc = STATUS_UNSUCCESSFUL;
987
struct ovs_key_icmp icmpKey;
988
/* XXX: revisit to see if htons is needed */
989
icmpKey.icmp_type = (__u8)(ipv4FlowPutKey->l4.tpSrc);
990
icmpKey.icmp_code = (__u8)(ipv4FlowPutKey->l4.tpDst);
992
if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ICMP,
995
rc = STATUS_UNSUCCESSFUL;
1010
*----------------------------------------------------------------------------
1011
* _MapFlowIpv6KeyToNlKey --
1012
* Maps _MapFlowIpv6KeyToNlKey to OVS_KEY_ATTR_IPV6 attribute.
1013
*----------------------------------------------------------------------------
1016
_MapFlowIpv6KeyToNlKey(PNL_BUFFER nlBuf, Ipv6Key *ipv6FlowPutKey,
1017
Icmp6Key *icmpv6FlowPutKey)
1019
NTSTATUS rc = STATUS_SUCCESS;
1020
struct ovs_key_ipv6 ipv6Key;
1022
RtlCopyMemory(&(ipv6Key.ipv6_src), &ipv6FlowPutKey->ipv6Src,
1023
sizeof ipv6Key.ipv6_src);
1024
RtlCopyMemory(&(ipv6Key.ipv6_dst), &ipv6FlowPutKey->ipv6Dst,
1025
sizeof ipv6Key.ipv6_dst);
1027
ipv6Key.ipv6_label = ipv6FlowPutKey->ipv6Label;
1028
ipv6Key.ipv6_proto = ipv6FlowPutKey->nwProto;
1029
ipv6Key.ipv6_tclass = ipv6FlowPutKey->nwTos;
1030
ipv6Key.ipv6_hlimit = ipv6FlowPutKey->nwTtl;
1031
ipv6Key.ipv6_frag = ipv6FlowPutKey->nwFrag;
1033
if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_IPV6,
1036
rc = STATUS_UNSUCCESSFUL;
1040
switch (ipv6Key.ipv6_proto) {
1042
struct ovs_key_tcp tcpKey;
1043
tcpKey.tcp_src = ipv6FlowPutKey->l4.tpSrc;
1044
tcpKey.tcp_dst = ipv6FlowPutKey->l4.tpDst;
1045
if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_TCP,
1048
rc = STATUS_UNSUCCESSFUL;
1055
struct ovs_key_udp udpKey;
1056
udpKey.udp_src = ipv6FlowPutKey->l4.tpSrc;
1057
udpKey.udp_dst = ipv6FlowPutKey->l4.tpDst;
1058
if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_UDP,
1061
rc = STATUS_UNSUCCESSFUL;
1067
case IPPROTO_SCTP: {
1068
struct ovs_key_sctp sctpKey;
1069
sctpKey.sctp_src = ipv6FlowPutKey->l4.tpSrc;
1070
sctpKey.sctp_dst = ipv6FlowPutKey->l4.tpDst;
1071
if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_SCTP,
1074
rc = STATUS_UNSUCCESSFUL;
1080
case IPPROTO_ICMPV6: {
1081
struct ovs_key_icmpv6 icmpV6Key;
1082
struct ovs_key_nd ndKey;
1084
/* XXX: revisit to see if htons is needed */
1085
icmpV6Key.icmpv6_type = (__u8)(icmpv6FlowPutKey->l4.tpSrc);
1086
icmpV6Key.icmpv6_code = (__u8)(icmpv6FlowPutKey->l4.tpDst);
1088
if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ICMPV6,
1089
(PCHAR)(&icmpV6Key),
1090
sizeof(icmpV6Key))) {
1091
rc = STATUS_UNSUCCESSFUL;
1095
RtlCopyMemory(&(ndKey.nd_target), &icmpv6FlowPutKey->ndTarget,
1096
sizeof(icmpv6FlowPutKey->ndTarget));
1097
RtlCopyMemory(&(ndKey.nd_sll), &icmpv6FlowPutKey->arpSha,
1099
RtlCopyMemory(&(ndKey.nd_tll), &icmpv6FlowPutKey->arpTha,
1101
if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ND,
1104
rc = STATUS_UNSUCCESSFUL;
1120
*----------------------------------------------------------------------------
1121
* _MapFlowArpKeyToNlKey --
1122
* Maps _MapFlowArpKeyToNlKey to OVS_KEY_ATTR_ARP attribute.
1123
*----------------------------------------------------------------------------
1126
_MapFlowArpKeyToNlKey(PNL_BUFFER nlBuf, ArpKey *arpFlowPutKey)
1128
NTSTATUS rc = STATUS_SUCCESS;
1129
struct ovs_key_arp arpKey;
1131
arpKey.arp_sip = arpFlowPutKey->nwSrc;
1132
arpKey.arp_tip = arpFlowPutKey->nwDst;
1134
RtlCopyMemory(&(arpKey.arp_sha), arpFlowPutKey->arpSha, ETH_ADDR_LEN);
1135
RtlCopyMemory(&(arpKey.arp_tha), arpFlowPutKey->arpTha, ETH_ADDR_LEN);
1138
* Flow_Extract() stores 'nwProto' in host order for ARP since 'nwProto' is
1139
* 1 byte field and the ARP opcode is 2 bytes, and all of the kernel code
1140
* understand this while looking at an ARP key.
1141
* While we pass up the ARP key to userspace, convert from host order to
1142
* network order. Likewise, when processing an ARP key from userspace,
1143
* convert from network order to host order.
1145
* It is important to note that the flow table stores the ARP opcode field
1148
arpKey.arp_op = htons(arpFlowPutKey->nwProto);
1150
if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ARP,
1153
rc = STATUS_UNSUCCESSFUL;
1162
*----------------------------------------------------------------------------
1163
* _MapNlToFlowPut --
1164
* Maps input netlink message to OvsFlowPut.
1165
*----------------------------------------------------------------------------
1168
_MapNlToFlowPut(POVS_MESSAGE msgIn, PNL_ATTR keyAttr,
1169
PNL_ATTR actionAttr, PNL_ATTR flowAttrClear,
1170
OvsFlowPut *mappedFlow)
1172
NTSTATUS rc = STATUS_SUCCESS;
1173
PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
1174
PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
1175
POVS_HDR ovsHdr = &(msgIn->ovsHdr);
1177
UINT32 keyAttrOffset = (UINT32)((PCHAR)keyAttr - (PCHAR)nlMsgHdr);
1178
UINT32 tunnelKeyAttrOffset;
1180
PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX] = {NULL};
1181
PNL_ATTR tunnelAttrs[__OVS_TUNNEL_KEY_ATTR_MAX] = {NULL};
1183
/* Get flow keys attributes */
1184
if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset, NlAttrLen(keyAttr),
1185
nlFlowKeyPolicy, keyAttrs, ARRAY_SIZE(keyAttrs)))
1187
OVS_LOG_ERROR("Key Attr Parsing failed for msg: %p",
1189
rc = STATUS_INVALID_PARAMETER;
1193
if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
1194
tunnelKeyAttrOffset = (UINT32)((PCHAR)
1195
(keyAttrs[OVS_KEY_ATTR_TUNNEL])
1198
/* Get tunnel keys attributes */
1199
if ((NlAttrParseNested(nlMsgHdr, tunnelKeyAttrOffset,
1200
NlAttrLen(keyAttrs[OVS_KEY_ATTR_TUNNEL]),
1201
nlFlowTunnelKeyPolicy,
1202
tunnelAttrs, ARRAY_SIZE(tunnelAttrs)))
1204
OVS_LOG_ERROR("Tunnel key Attr Parsing failed for msg: %p",
1206
rc = STATUS_INVALID_PARAMETER;
1211
_MapKeyAttrToFlowPut(keyAttrs, tunnelAttrs,
1212
&(mappedFlow->key));
1214
/* Map the action */
1216
mappedFlow->actionsLen = NlAttrGetSize(actionAttr);
1217
mappedFlow->actions = NlAttrGet(actionAttr);
1220
mappedFlow->dpNo = ovsHdr->dp_ifindex;
1222
_MapNlToFlowPutFlags(genlMsgHdr, flowAttrClear,
1230
*----------------------------------------------------------------------------
1231
* _MapNlToFlowPutFlags --
1232
* Maps netlink message to OvsFlowPut->flags.
1233
*----------------------------------------------------------------------------
1236
_MapNlToFlowPutFlags(PGENL_MSG_HDR genlMsgHdr,
1237
PNL_ATTR flowAttrClear, OvsFlowPut *mappedFlow)
1241
switch (genlMsgHdr->cmd) {
1242
case OVS_FLOW_CMD_NEW:
1243
flags |= OVSWIN_FLOW_PUT_CREATE;
1245
case OVS_FLOW_CMD_DEL:
1246
flags |= OVSWIN_FLOW_PUT_DELETE;
1248
case OVS_FLOW_CMD_SET:
1249
flags |= OVSWIN_FLOW_PUT_MODIFY;
1255
if (flowAttrClear) {
1256
flags |= OVSWIN_FLOW_PUT_CLEAR;
1259
mappedFlow->flags = flags;
1263
*----------------------------------------------------------------------------
1264
* _MapKeyAttrToFlowPut --
1265
* Converts FLOW_KEY attribute to OvsFlowPut->key.
1266
*----------------------------------------------------------------------------
1269
_MapKeyAttrToFlowPut(PNL_ATTR *keyAttrs,
1270
PNL_ATTR *tunnelAttrs,
1271
OvsFlowKey *destKey)
1273
_MapTunAttrToFlowPut(keyAttrs, tunnelAttrs, destKey);
1275
/* ===== L2 headers ===== */
1276
destKey->l2.inPort = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_IN_PORT]);
1278
if (keyAttrs[OVS_KEY_ATTR_ETHERNET]) {
1279
const struct ovs_key_ethernet *eth_key;
1280
eth_key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ETHERNET]);
1281
RtlCopyMemory(destKey->l2.dlSrc, eth_key->eth_src, ETH_ADDR_LEN);
1282
RtlCopyMemory(destKey->l2.dlDst, eth_key->eth_dst, ETH_ADDR_LEN);
1285
/* TODO: Ideally ETHERTYPE should not be optional.
1286
* But during vswitchd bootup we are seeing FLOW_ADD
1287
* requests with no ETHERTYPE attributes.
1288
* Need to verify this. */
1289
if (keyAttrs[OVS_KEY_ATTR_ETHERTYPE]) {
1290
destKey->l2.dlType = (NlAttrGetU16(keyAttrs
1291
[OVS_KEY_ATTR_ETHERTYPE]));
1294
if (keyAttrs[OVS_KEY_ATTR_VLAN]) {
1295
destKey->l2.vlanTci = NlAttrGetU16(keyAttrs[OVS_KEY_ATTR_VLAN]);
1298
/* ==== L3 + L4. ==== */
1299
destKey->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + OVS_L2_KEY_SIZE
1300
- destKey->l2.offset;
1302
switch (ntohs(destKey->l2.dlType)) {
1303
case ETH_TYPE_IPV4: {
1305
if (keyAttrs[OVS_KEY_ATTR_IPV4]) {
1306
const struct ovs_key_ipv4 *ipv4Key;
1308
ipv4Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_IPV4]);
1309
IpKey *ipv4FlowPutKey = &(destKey->ipKey);
1310
ipv4FlowPutKey->nwSrc = ipv4Key->ipv4_src;
1311
ipv4FlowPutKey->nwDst = ipv4Key->ipv4_dst;
1312
ipv4FlowPutKey->nwProto = ipv4Key->ipv4_proto;
1313
ipv4FlowPutKey->nwTos = ipv4Key->ipv4_tos;
1314
ipv4FlowPutKey->nwTtl = ipv4Key->ipv4_ttl;
1315
ipv4FlowPutKey->nwFrag = ipv4Key->ipv4_frag;
1317
if (keyAttrs[OVS_KEY_ATTR_TCP]) {
1318
const struct ovs_key_tcp *tcpKey;
1319
tcpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_TCP]);
1320
ipv4FlowPutKey->l4.tpSrc = tcpKey->tcp_src;
1321
ipv4FlowPutKey->l4.tpDst = tcpKey->tcp_dst;
1324
if (keyAttrs[OVS_KEY_ATTR_UDP]) {
1325
const struct ovs_key_udp *udpKey;
1326
udpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_UDP]);
1327
ipv4FlowPutKey->l4.tpSrc = udpKey->udp_src;
1328
ipv4FlowPutKey->l4.tpDst = udpKey->udp_dst;
1331
if (keyAttrs[OVS_KEY_ATTR_SCTP]) {
1332
const struct ovs_key_sctp *sctpKey;
1333
sctpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_SCTP]);
1334
ipv4FlowPutKey->l4.tpSrc = sctpKey->sctp_src;
1335
ipv4FlowPutKey->l4.tpDst = sctpKey->sctp_dst;
1338
destKey->l2.keyLen += OVS_IP_KEY_SIZE;
1342
case ETH_TYPE_IPV6: {
1344
if (keyAttrs[OVS_KEY_ATTR_IPV6]) {
1345
const struct ovs_key_ipv6 *ipv6Key;
1347
ipv6Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_IPV6]);
1348
Ipv6Key *ipv6FlowPutKey = &(destKey->ipv6Key);
1350
RtlCopyMemory(&ipv6FlowPutKey->ipv6Src, ipv6Key->ipv6_src,
1351
sizeof ipv6Key->ipv6_src);
1352
RtlCopyMemory(&ipv6FlowPutKey->ipv6Dst, ipv6Key->ipv6_dst,
1353
sizeof ipv6Key->ipv6_dst);
1355
ipv6FlowPutKey->ipv6Label = ipv6Key->ipv6_label;
1356
ipv6FlowPutKey->nwProto = ipv6Key->ipv6_proto;
1357
ipv6FlowPutKey->nwTos = ipv6Key->ipv6_tclass;
1358
ipv6FlowPutKey->nwTtl = ipv6Key->ipv6_hlimit;
1359
ipv6FlowPutKey->nwFrag = ipv6Key->ipv6_frag;
1361
if (keyAttrs[OVS_KEY_ATTR_TCP]) {
1362
const struct ovs_key_tcp *tcpKey;
1363
tcpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_TCP]);
1364
ipv6FlowPutKey->l4.tpSrc = tcpKey->tcp_src;
1365
ipv6FlowPutKey->l4.tpDst = tcpKey->tcp_dst;
1368
if (keyAttrs[OVS_KEY_ATTR_UDP]) {
1369
const struct ovs_key_udp *udpKey;
1370
udpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_UDP]);
1371
ipv6FlowPutKey->l4.tpSrc = udpKey->udp_src;
1372
ipv6FlowPutKey->l4.tpDst = udpKey->udp_dst;
1375
if (keyAttrs[OVS_KEY_ATTR_SCTP]) {
1376
const struct ovs_key_sctp *sctpKey;
1377
sctpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_SCTP]);
1378
ipv6FlowPutKey->l4.tpSrc = sctpKey->sctp_src;
1379
ipv6FlowPutKey->l4.tpDst = sctpKey->sctp_dst;
1382
if (keyAttrs[OVS_KEY_ATTR_ICMPV6]) {
1383
const struct ovs_key_icmpv6 *icmpv6Key;
1385
Icmp6Key *icmp6FlowPutKey= &(destKey->icmp6Key);
1387
icmpv6Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ICMPV6]);
1389
icmp6FlowPutKey->l4.tpSrc = icmpv6Key->icmpv6_type;
1390
icmp6FlowPutKey->l4.tpDst = icmpv6Key->icmpv6_code;
1392
if (keyAttrs[OVS_KEY_ATTR_ND]) {
1393
const struct ovs_key_nd *ndKey;
1395
ndKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ND]);
1396
RtlCopyMemory(&icmp6FlowPutKey->ndTarget,
1397
ndKey->nd_target, sizeof (icmp6FlowPutKey->ndTarget));
1398
RtlCopyMemory(icmp6FlowPutKey->arpSha,
1399
ndKey->nd_sll, ETH_ADDR_LEN);
1400
RtlCopyMemory(icmp6FlowPutKey->arpTha,
1401
ndKey->nd_tll, ETH_ADDR_LEN);
1404
destKey->l2.keyLen += OVS_ICMPV6_KEY_SIZE;
1408
destKey->l2.keyLen += OVS_IPV6_KEY_SIZE;
1411
ipv6FlowPutKey->pad = 0;
1416
case ETH_TYPE_RARP: {
1418
if (keyAttrs[OVS_KEY_ATTR_ARP]) {
1419
ArpKey *arpFlowPutKey = &destKey->arpKey;
1420
const struct ovs_key_arp *arpKey;
1422
arpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ARP]);
1424
arpFlowPutKey->nwSrc = arpKey->arp_sip;
1425
arpFlowPutKey->nwDst = arpKey->arp_tip;
1427
RtlCopyMemory(arpFlowPutKey->arpSha, arpKey->arp_sha, ETH_ADDR_LEN);
1428
RtlCopyMemory(arpFlowPutKey->arpTha, arpKey->arp_tha, ETH_ADDR_LEN);
1429
/* Kernel datapath assumes 'arpFlowPutKey->nwProto' to be in host
1431
arpFlowPutKey->nwProto = (UINT8)ntohs((arpKey->arp_op));
1432
arpFlowPutKey->pad[0] = 0;
1433
arpFlowPutKey->pad[1] = 0;
1434
arpFlowPutKey->pad[2] = 0;
1435
destKey->l2.keyLen += OVS_ARP_KEY_SIZE;
1443
*----------------------------------------------------------------------------
1444
* _MapTunAttrToFlowPut --
1445
* Converts FLOW_TUNNEL_KEY attribute to OvsFlowKey->tunKey.
1446
*----------------------------------------------------------------------------
1449
_MapTunAttrToFlowPut(PNL_ATTR *keyAttrs,
1451
OvsFlowKey *destKey)
1453
if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
1455
if (tunAttrs[OVS_TUNNEL_KEY_ATTR_ID]) {
1456
destKey->tunKey.tunnelId = NlAttrGetU64
1457
(tunAttrs[OVS_TUNNEL_KEY_ATTR_ID]);
1458
destKey->tunKey.flags |= OVS_TNL_F_KEY;
1461
if (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_DST]) {
1462
destKey->tunKey.dst = NlAttrGetU32
1463
(tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_DST]);
1466
if (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_SRC]) {
1467
destKey->tunKey.src = NlAttrGetU32
1468
(tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_SRC]);
1471
if (tunAttrs[OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT]) {
1472
destKey->tunKey.flags |= OVS_TNL_F_DONT_FRAGMENT;
1475
if (tunAttrs[OVS_TUNNEL_KEY_ATTR_CSUM]) {
1476
destKey->tunKey.flags |= OVS_TNL_F_CSUM;
1479
if (tunAttrs[OVS_TUNNEL_KEY_ATTR_TOS]) {
1480
destKey->tunKey.tos = NlAttrGetU8
1481
(tunAttrs[OVS_TUNNEL_KEY_ATTR_TOS]);
1484
if (tunAttrs[OVS_TUNNEL_KEY_ATTR_TTL]) {
1485
destKey->tunKey.ttl = NlAttrGetU8
1486
(tunAttrs[OVS_TUNNEL_KEY_ATTR_TTL]);
1489
destKey->tunKey.pad = 0;
1490
destKey->l2.offset = 0;
1492
destKey->tunKey.attr[0] = 0;
1493
destKey->tunKey.attr[1] = 0;
1494
destKey->tunKey.attr[2] = 0;
1495
destKey->l2.offset = sizeof destKey->tunKey;
1500
*----------------------------------------------------------------------------
1501
* OvsDeleteFlowTable --
1503
* NDIS_STATUS_SUCCESS always.
1504
*----------------------------------------------------------------------------
1507
OvsDeleteFlowTable(OVS_DATAPATH *datapath)
1509
if (datapath == NULL || datapath->flowTable == NULL) {
1510
return NDIS_STATUS_SUCCESS;
1513
DeleteAllFlows(datapath);
1514
OvsFreeMemoryWithTag(datapath->flowTable, OVS_FLOW_POOL_TAG);
1515
datapath->flowTable = NULL;
1517
if (datapath->lock == NULL) {
1518
return NDIS_STATUS_SUCCESS;
1521
NdisFreeRWLock(datapath->lock);
1523
return NDIS_STATUS_SUCCESS;
1527
*----------------------------------------------------------------------------
1528
* OvsAllocateFlowTable --
1530
* NDIS_STATUS_SUCCESS on success.
1531
* NDIS_STATUS_RESOURCES if memory couldn't be allocated
1532
*----------------------------------------------------------------------------
1535
OvsAllocateFlowTable(OVS_DATAPATH *datapath,
1536
POVS_SWITCH_CONTEXT switchContext)
1541
datapath->flowTable = OvsAllocateMemoryWithTag(
1542
OVS_FLOW_TABLE_SIZE * sizeof(LIST_ENTRY), OVS_FLOW_POOL_TAG);
1543
if (!datapath->flowTable) {
1544
return NDIS_STATUS_RESOURCES;
1546
for (i = 0; i < OVS_FLOW_TABLE_SIZE; i++) {
1547
bucket = &(datapath->flowTable[i]);
1548
InitializeListHead(bucket);
1550
datapath->lock = NdisAllocateRWLock(switchContext->NdisFilterHandle);
1552
if (!datapath->lock) {
1553
return NDIS_STATUS_RESOURCES;
1556
return NDIS_STATUS_SUCCESS;
1561
*----------------------------------------------------------------------------
1562
* GetStartAddrNBL --
1563
* Get the virtual address of the frame.
1566
* Virtual address of the frame.
1567
*----------------------------------------------------------------------------
1569
static __inline VOID *
1570
GetStartAddrNBL(const NET_BUFFER_LIST *_pNB)
1578
// Ethernet Header is a guaranteed safe access.
1579
curMdl = (NET_BUFFER_LIST_FIRST_NB(_pNB))->CurrentMdl;
1580
curBuffer = MmGetSystemAddressForMdlSafe(curMdl, LowPagePriority);
1585
curHeader = (PEthHdr)
1586
(curBuffer + (NET_BUFFER_LIST_FIRST_NB(_pNB))->CurrentMdlOffset);
1588
return (VOID *) curHeader;
1592
OvsFlowUsed(OvsFlow *flow,
1593
const NET_BUFFER_LIST *packet,
1594
const POVS_PACKET_HDR_INFO layers)
1596
LARGE_INTEGER tickCount;
1598
KeQueryTickCount(&tickCount);
1599
flow->used = tickCount.QuadPart * ovsTimeIncrementPerTick;
1600
flow->packetCount++;
1601
flow->byteCount += OvsPacketLenNBL(packet);
1602
flow->tcpFlags |= OvsGetTcpFlags(packet, &flow->key, layers);
1607
DeleteAllFlows(OVS_DATAPATH *datapath)
1612
for (i = 0; i < OVS_FLOW_TABLE_SIZE; i++) {
1614
bucket = &(datapath->flowTable[i]);
1615
while (!IsListEmpty(bucket)) {
1617
next = bucket->Flink;
1618
flow = CONTAINING_RECORD(next, OvsFlow, ListEntry);
1619
RemoveFlow(datapath, &flow);
1625
*----------------------------------------------------------------------------
1626
* Initializes 'flow' members from 'packet', 'skb_priority', 'tun_id', and
1629
* Initializes 'packet' header pointers as follows:
1631
* - packet->l2 to the start of the Ethernet header.
1633
* - packet->l3 to just past the Ethernet header, or just past the
1634
* vlan_header if one is present, to the first byte of the payload of the
1637
* - packet->l4 to just past the IPv4 header, if one is present and has a
1638
* correct length, and otherwise NULL.
1640
* - packet->l7 to just past the TCP or UDP or ICMP header, if one is
1641
* present and has a correct length, and otherwise NULL.
1643
* Returns NDIS_STATUS_SUCCESS normally. Fails only if packet data cannot be accessed
1644
* (e.g. if Pkt_CopyBytesOut() returns an error).
1645
*----------------------------------------------------------------------------
1648
OvsExtractFlow(const NET_BUFFER_LIST *packet,
1651
POVS_PACKET_HDR_INFO layers,
1652
OvsIPv4TunnelKey *tunKey)
1654
struct Eth_Header *eth;
1661
ASSERT(tunKey->dst != 0);
1662
RtlMoveMemory(&flow->tunKey, tunKey, sizeof flow->tunKey);
1663
flow->l2.offset = 0;
1665
flow->tunKey.dst = 0;
1666
flow->l2.offset = OVS_WIN_TUNNEL_KEY_SIZE;
1669
flow->l2.inPort = inPort;
1671
if ( OvsPacketLenNBL(packet) < ETH_HEADER_LEN_DIX) {
1672
flow->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + 8 - flow->l2.offset;
1673
return NDIS_STATUS_SUCCESS;
1677
eth = (Eth_Header *)GetStartAddrNBL((NET_BUFFER_LIST *)packet);
1678
memcpy(flow->l2.dlSrc, eth->src, ETH_ADDR_LENGTH);
1679
memcpy(flow->l2.dlDst, eth->dst, ETH_ADDR_LENGTH);
1684
vlanTagValue = NET_BUFFER_LIST_INFO(packet, Ieee8021QNetBufferListInfo);
1686
PNDIS_NET_BUFFER_LIST_8021Q_INFO vlanTag =
1687
(PNDIS_NET_BUFFER_LIST_8021Q_INFO)(PVOID *)&vlanTagValue;
1688
flow->l2.vlanTci = htons(vlanTag->TagHeader.VlanId | OVSWIN_VLAN_CFI |
1689
(vlanTag->TagHeader.UserPriority << 13));
1691
if (eth->dix.typeNBO == ETH_TYPE_802_1PQ_NBO) {
1692
Eth_802_1pq_Tag *tag= (Eth_802_1pq_Tag *)ð->dix.typeNBO;
1693
flow->l2.vlanTci = ((UINT16)tag->priority << 13) |
1695
((UINT16)tag->vidHi << 8) | tag->vidLo;
1696
offset = sizeof (Eth_802_1pq_Tag);
1698
flow->l2.vlanTci = 0;
1702
* Please note after this point, src mac and dst mac should
1703
* not be accessed through eth
1705
eth = (Eth_Header *)((UINT8 *)eth + offset);
1711
* XXX assume that at least the first
1712
* 12 bytes of received packets are mapped. This code has the stronger
1713
* assumption that at least the first 22 bytes of 'packet' is mapped (if my
1714
* arithmetic is right).
1716
if (ETH_TYPENOT8023(eth->dix.typeNBO)) {
1717
flow->l2.dlType = eth->dix.typeNBO;
1718
layers->l3Offset = ETH_HEADER_LEN_DIX + offset;
1719
} else if (OvsPacketLenNBL(packet) >= ETH_HEADER_LEN_802_3 &&
1720
eth->e802_3.llc.dsap == 0xaa &&
1721
eth->e802_3.llc.ssap == 0xaa &&
1722
eth->e802_3.llc.control == ETH_LLC_CONTROL_UFRAME &&
1723
eth->e802_3.snap.snapOrg[0] == 0x00 &&
1724
eth->e802_3.snap.snapOrg[1] == 0x00 &&
1725
eth->e802_3.snap.snapOrg[2] == 0x00) {
1726
flow->l2.dlType = eth->e802_3.snap.snapType.typeNBO;
1727
layers->l3Offset = ETH_HEADER_LEN_802_3 + offset;
1729
flow->l2.dlType = htons(OVSWIN_DL_TYPE_NONE);
1730
layers->l3Offset = ETH_HEADER_LEN_DIX + offset;
1733
flow->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + OVS_L2_KEY_SIZE - flow->l2.offset;
1734
/* Network layer. */
1735
if (flow->l2.dlType == htons(ETH_TYPE_IPV4)) {
1736
struct IPHdr ip_storage;
1737
const struct IPHdr *nh;
1738
IpKey *ipKey = &flow->ipKey;
1740
flow->l2.keyLen += OVS_IP_KEY_SIZE;
1742
nh = OvsGetIp(packet, layers->l3Offset, &ip_storage);
1744
layers->l4Offset = layers->l3Offset + nh->ihl * 4;
1746
ipKey->nwSrc = nh->saddr;
1747
ipKey->nwDst = nh->daddr;
1748
ipKey->nwProto = nh->protocol;
1750
ipKey->nwTos = nh->tos;
1751
if (nh->frag_off & htons(IP_MF | IP_OFFSET)) {
1752
ipKey->nwFrag = OVSWIN_NW_FRAG_ANY;
1753
if (nh->frag_off & htons(IP_OFFSET)) {
1754
ipKey->nwFrag |= OVSWIN_NW_FRAG_LATER;
1760
ipKey->nwTtl = nh->ttl;
1761
ipKey->l4.tpSrc = 0;
1762
ipKey->l4.tpDst = 0;
1764
if (!(nh->frag_off & htons(IP_OFFSET))) {
1765
if (ipKey->nwProto == SOCKET_IPPROTO_TCP) {
1766
OvsParseTcp(packet, &ipKey->l4, layers);
1767
} else if (ipKey->nwProto == SOCKET_IPPROTO_UDP) {
1768
OvsParseUdp(packet, &ipKey->l4, layers);
1769
} else if (ipKey->nwProto == SOCKET_IPPROTO_ICMP) {
1770
ICMPHdr icmpStorage;
1771
const ICMPHdr *icmp;
1773
icmp = OvsGetIcmp(packet, layers->l4Offset, &icmpStorage);
1775
ipKey->l4.tpSrc = htons(icmp->type);
1776
ipKey->l4.tpDst = htons(icmp->code);
1777
layers->l7Offset = layers->l4Offset + sizeof *icmp;
1782
((UINT64 *)ipKey)[0] = 0;
1783
((UINT64 *)ipKey)[1] = 0;
1785
} else if (flow->l2.dlType == htons(ETH_TYPE_IPV6)) {
1787
flow->l2.keyLen += OVS_IPV6_KEY_SIZE;
1788
status = OvsParseIPv6(packet, flow, layers);
1789
if (status != NDIS_STATUS_SUCCESS) {
1790
memset(&flow->ipv6Key, 0, sizeof (Ipv6Key));
1794
flow->ipv6Key.l4.tpSrc = 0;
1795
flow->ipv6Key.l4.tpDst = 0;
1796
flow->ipv6Key.pad = 0;
1798
if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_TCP) {
1799
OvsParseTcp(packet, &(flow->ipv6Key.l4), layers);
1800
} else if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_UDP) {
1801
OvsParseUdp(packet, &(flow->ipv6Key.l4), layers);
1802
} else if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_ICMPV6) {
1803
OvsParseIcmpV6(packet, flow, layers);
1804
flow->l2.keyLen += (OVS_ICMPV6_KEY_SIZE - OVS_IPV6_KEY_SIZE);
1806
} else if (flow->l2.dlType == htons(ETH_TYPE_ARP)) {
1807
EtherArp arpStorage;
1808
const EtherArp *arp;
1809
ArpKey *arpKey = &flow->arpKey;
1810
((UINT64 *)arpKey)[0] = 0;
1811
((UINT64 *)arpKey)[1] = 0;
1812
((UINT64 *)arpKey)[2] = 0;
1813
flow->l2.keyLen += OVS_ARP_KEY_SIZE;
1814
arp = OvsGetArp(packet, layers->l3Offset, &arpStorage);
1815
if (arp && arp->ea_hdr.ar_hrd == htons(1) &&
1816
arp->ea_hdr.ar_pro == htons(ETH_TYPE_IPV4) &&
1817
arp->ea_hdr.ar_hln == ETH_ADDR_LENGTH &&
1818
arp->ea_hdr.ar_pln == 4) {
1819
/* We only match on the lower 8 bits of the opcode. */
1820
if (ntohs(arp->ea_hdr.ar_op) <= 0xff) {
1821
arpKey->nwProto = (UINT8)ntohs(arp->ea_hdr.ar_op);
1823
if (arpKey->nwProto == ARPOP_REQUEST
1824
|| arpKey->nwProto == ARPOP_REPLY) {
1825
memcpy(&arpKey->nwSrc, arp->arp_spa, 4);
1826
memcpy(&arpKey->nwDst, arp->arp_tpa, 4);
1827
memcpy(arpKey->arpSha, arp->arp_sha, ETH_ADDR_LENGTH);
1828
memcpy(arpKey->arpTha, arp->arp_tha, ETH_ADDR_LENGTH);
1833
return NDIS_STATUS_SUCCESS;
1837
FlowEqual(UINT64 *src, UINT64 *dst, UINT32 size)
1840
ASSERT((size & 0x7) == 0);
1841
ASSERT(((UINT64)src & 0x7) == 0);
1842
ASSERT(((UINT64)dst & 0x7) == 0);
1843
for (i = 0; i < (size >> 3); i++) {
1844
if (src[i] != dst[i]) {
1853
* ----------------------------------------------------------------------------
1855
* Add a flow to flow table.
1858
* NDIS_STATUS_SUCCESS if no same flow in the flow table.
1859
* ----------------------------------------------------------------------------
1862
AddFlow(OVS_DATAPATH *datapath, OvsFlow *flow)
1866
if (OvsLookupFlow(datapath, &flow->key, &flow->hash, TRUE) != NULL) {
1867
return STATUS_INVALID_HANDLE;
1870
head = &(datapath->flowTable[HASH_BUCKET(flow->hash)]);
1872
* We need fence here to make sure flow's nextPtr is updated before
1873
* head->nextPtr is updated.
1877
//KeAcquireSpinLock(&FilterDeviceExtension->NblQueueLock, &oldIrql);
1878
InsertTailList(head, &flow->ListEntry);
1879
//KeReleaseSpinLock(&FilterDeviceExtension->NblQueueLock, oldIrql);
1883
return STATUS_SUCCESS;
1887
/* ----------------------------------------------------------------------------
1889
* Remove a flow from flow table, and added to wait list
1890
* ----------------------------------------------------------------------------
1893
RemoveFlow(OVS_DATAPATH *datapath,
1899
ASSERT(datapath->nFlows);
1901
// Remove the flow from queue
1902
RemoveEntryList(&f->ListEntry);
1908
* ----------------------------------------------------------------------------
1911
* Find flow from flow table based on flow key.
1912
* Caller should either hold portset handle or should
1913
* have a flowRef in datapath or Acquired datapath.
1916
* Flow pointer if lookup successful.
1917
* NULL if not exists.
1918
* ----------------------------------------------------------------------------
1921
OvsLookupFlow(OVS_DATAPATH *datapath,
1922
const OvsFlowKey *key,
1926
PLIST_ENTRY link, head;
1927
UINT16 offset = key->l2.offset;
1928
UINT16 size = key->l2.keyLen;
1931
ASSERT(key->tunKey.dst || offset == sizeof (OvsIPv4TunnelKey));
1932
ASSERT(!key->tunKey.dst || offset == 0);
1934
start = (UINT8 *)key + offset;
1937
*hash = OvsJhashBytes(start, size, 0);
1940
head = &datapath->flowTable[HASH_BUCKET(*hash)];
1942
while (link != head) {
1943
OvsFlow *flow = CONTAINING_RECORD(link, OvsFlow, ListEntry);
1945
if (flow->hash == *hash &&
1946
flow->key.l2.val == key->l2.val &&
1947
FlowEqual((UINT64 *)((uint8 *)&flow->key + offset),
1948
(UINT64 *)start, size)) {
1958
* ----------------------------------------------------------------------------
1960
* Calculate the hash for the given flow key.
1961
* ----------------------------------------------------------------------------
1964
OvsHashFlow(const OvsFlowKey *key)
1966
UINT16 offset = key->l2.offset;
1967
UINT16 size = key->l2.keyLen;
1970
ASSERT(key->tunKey.dst || offset == sizeof (OvsIPv4TunnelKey));
1971
ASSERT(!key->tunKey.dst || offset == 0);
1972
start = (UINT8 *)key + offset;
1973
return OvsJhashBytes(start, size, 0);
1978
* ----------------------------------------------------------------------------
1980
* Free a flow and its actions.
1981
* ----------------------------------------------------------------------------
1984
FreeFlow(OvsFlow *flow)
1987
OvsFreeMemoryWithTag(flow, OVS_FLOW_POOL_TAG);
1991
OvsDoDumpFlows(OvsFlowDumpInput *dumpInput,
1992
OvsFlowDumpOutput *dumpOutput,
1996
OVS_DATAPATH *datapath = NULL;
1998
PLIST_ENTRY node, head;
2000
UINT32 rowIndex, columnIndex;
2001
LOCK_STATE_EX dpLockState;
2002
NTSTATUS status = STATUS_SUCCESS;
2003
BOOLEAN findNextNonEmpty = FALSE;
2005
dpNo = dumpInput->dpNo;
2006
if (gOvsSwitchContext->dpNo != dpNo) {
2007
status = STATUS_INVALID_PARAMETER;
2011
rowIndex = dumpInput->position[0];
2012
if (rowIndex >= OVS_FLOW_TABLE_SIZE) {
2014
*replyLen = sizeof(*dumpOutput);
2018
columnIndex = dumpInput->position[1];
2020
datapath = &gOvsSwitchContext->datapath;
2022
OvsAcquireDatapathRead(datapath, &dpLockState, FALSE);
2024
head = &datapath->flowTable[rowIndex];
2027
while (column < columnIndex) {
2036
findNextNonEmpty = TRUE;
2040
if (findNextNonEmpty) {
2041
while (head == node) {
2042
if (++rowIndex >= OVS_FLOW_TABLE_SIZE) {
2046
head = &datapath->flowTable[rowIndex];
2051
ASSERT(node != head);
2052
ASSERT(rowIndex < OVS_FLOW_TABLE_SIZE);
2054
flow = CONTAINING_RECORD(node, OvsFlow, ListEntry);
2055
status = ReportFlowInfo(flow, dumpInput->getFlags, &dumpOutput->flow);
2057
if (status == STATUS_BUFFER_TOO_SMALL) {
2058
dumpOutput->n = sizeof(OvsFlowDumpOutput) + flow->actionsLen;
2059
*replyLen = sizeof(*dumpOutput);
2061
dumpOutput->n = 1; //one flow reported.
2062
*replyLen = sizeof(*dumpOutput) + dumpOutput->flow.actionsLen;
2065
dumpOutput->position[0] = rowIndex;
2066
dumpOutput->position[1] = ++columnIndex;
2069
OvsReleaseDatapath(datapath, &dpLockState);
2076
ReportFlowInfo(OvsFlow *flow,
2080
NTSTATUS status = STATUS_SUCCESS;
2082
if (getFlags & FLOW_GET_KEY) {
2083
// always copy the tunnel key part
2084
RtlCopyMemory(&info->key, &flow->key,
2085
flow->key.l2.keyLen + flow->key.l2.offset);
2088
if (getFlags & FLOW_GET_STATS) {
2089
OvsFlowStats *stats = &info->stats;
2090
stats->packetCount = flow->packetCount;
2091
stats->byteCount = flow->byteCount;
2092
stats->used = (UINT32)flow->used;
2093
stats->tcpFlags = flow->tcpFlags;
2096
if (getFlags & FLOW_GET_ACTIONS) {
2097
if (flow->actionsLen == 0) {
2098
info->actionsLen = 0;
2100
info->actions = flow->actions;
2101
info->actionsLen = flow->actionsLen;
2109
OvsPutFlowIoctl(PVOID inputBuffer,
2111
struct OvsFlowStats *stats)
2113
NTSTATUS status = STATUS_SUCCESS;
2114
OVS_DATAPATH *datapath = NULL;
2118
LOCK_STATE_EX dpLockState;
2120
if ((inputLength < sizeof(OvsFlowPut)) || (inputBuffer == NULL)) {
2121
return STATUS_INFO_LENGTH_MISMATCH;
2124
put = (OvsFlowPut *)inputBuffer;
2125
if (put->actionsLen > 0) {
2126
actionsLen = put->actionsLen;
2132
if (gOvsSwitchContext->dpNo != dpNo) {
2133
status = STATUS_INVALID_PARAMETER;
2137
datapath = &gOvsSwitchContext->datapath;
2139
OvsAcquireDatapathWrite(datapath, &dpLockState, FALSE);
2140
status = HandleFlowPut(put, datapath, stats);
2141
OvsReleaseDatapath(datapath, &dpLockState);
2148
/* Handles flow add, modify as well as delete */
2150
HandleFlowPut(OvsFlowPut *put,
2151
OVS_DATAPATH *datapath,
2152
struct OvsFlowStats *stats)
2154
BOOLEAN mayCreate, mayModify, mayDelete;
2155
OvsFlow *KernelFlow;
2157
NTSTATUS status = STATUS_SUCCESS;
2159
mayCreate = (put->flags & OVSWIN_FLOW_PUT_CREATE) != 0;
2160
mayModify = (put->flags & OVSWIN_FLOW_PUT_MODIFY) != 0;
2161
mayDelete = (put->flags & OVSWIN_FLOW_PUT_DELETE) != 0;
2163
if ((mayCreate || mayModify) == mayDelete) {
2164
return STATUS_INVALID_PARAMETER;
2167
KernelFlow = OvsLookupFlow(datapath, &put->key, &hash, FALSE);
2170
return STATUS_INVALID_PARAMETER;
2173
status = OvsPrepareFlow(&KernelFlow, put, hash);
2174
if (status != STATUS_SUCCESS) {
2175
return STATUS_UNSUCCESSFUL;
2178
status = AddFlow(datapath, KernelFlow);
2179
if (status != STATUS_SUCCESS) {
2180
FreeFlow(KernelFlow);
2181
return STATUS_UNSUCCESSFUL;
2184
/* Validate the flow addition */
2187
OvsFlow *flow = OvsLookupFlow(datapath, &put->key, &newHash,
2190
ASSERT(newHash == hash);
2191
if (!flow || newHash != hash) {
2192
return STATUS_UNSUCCESSFUL;
2196
stats->packetCount = KernelFlow->packetCount;
2197
stats->byteCount = KernelFlow->byteCount;
2198
stats->tcpFlags = KernelFlow->tcpFlags;
2199
stats->used = (UINT32)KernelFlow->used;
2203
status = OvsPrepareFlow(&newFlow, put, hash);
2204
if (status != STATUS_SUCCESS) {
2205
return STATUS_UNSUCCESSFUL;
2208
KernelFlow = OvsLookupFlow(datapath, &put->key, &hash, TRUE);
2210
if ((put->flags & OVSWIN_FLOW_PUT_CLEAR) == 0) {
2211
newFlow->packetCount = KernelFlow->packetCount;
2212
newFlow->byteCount = KernelFlow->byteCount;
2213
newFlow->tcpFlags = KernelFlow->tcpFlags;
2215
RemoveFlow(datapath, &KernelFlow);
2217
if ((put->flags & OVSWIN_FLOW_PUT_CLEAR) == 0) {
2218
newFlow->packetCount = stats->packetCount;
2219
newFlow->byteCount = stats->byteCount;
2220
newFlow->tcpFlags = stats->tcpFlags;
2223
status = AddFlow(datapath, newFlow);
2224
ASSERT(status == STATUS_SUCCESS);
2226
/* Validate the flow addition */
2229
OvsFlow *testflow = OvsLookupFlow(datapath, &put->key,
2232
ASSERT(newHash == hash);
2233
if (!testflow || newHash != hash) {
2235
return STATUS_UNSUCCESSFUL;
2241
RemoveFlow(datapath, &KernelFlow);
2244
/* Return success if an identical flow already exists. */
2245
/* XXX: should we return EEXIST in a netlink error? */
2246
return STATUS_SUCCESS;
2250
return STATUS_SUCCESS;
2254
OvsPrepareFlow(OvsFlow **flow,
2255
const OvsFlowPut *put,
2258
OvsFlow *localFlow = *flow;
2259
NTSTATUS status = STATUS_SUCCESS;
2263
OvsAllocateMemoryWithTag(sizeof(OvsFlow) + put->actionsLen,
2265
if (localFlow == NULL) {
2266
status = STATUS_NO_MEMORY;
2270
localFlow->key = put->key;
2271
localFlow->actionsLen = put->actionsLen;
2272
if (put->actionsLen) {
2273
NdisMoveMemory((PUCHAR)localFlow->actions, put->actions,
2276
localFlow->userActionsLen = 0; // 0 indicate no conversion is made
2277
localFlow->used = 0;
2278
localFlow->packetCount = 0;
2279
localFlow->byteCount = 0;
2280
localFlow->tcpFlags = 0;
2281
localFlow->hash = hash;
2288
OvsGetFlowIoctl(PVOID inputBuffer,
2291
NTSTATUS status = STATUS_SUCCESS;
2292
OVS_DATAPATH *datapath = NULL;
2294
UINT32 getFlags, getActionsLen;
2295
OvsFlowGetInput *getInput;
2296
OvsFlowGetOutput *getOutput;
2299
LOCK_STATE_EX dpLockState;
2301
getInput = (OvsFlowGetInput *) inputBuffer;
2302
getFlags = getInput->getFlags;
2303
getActionsLen = getInput->actionsLen;
2305
if (outputBuffer == NULL) {
2306
return STATUS_INFO_LENGTH_MISMATCH;
2309
dpNo = getInput->dpNo;
2310
if (gOvsSwitchContext->dpNo != dpNo) {
2311
status = STATUS_INVALID_PARAMETER;
2315
datapath = &gOvsSwitchContext->datapath;
2317
OvsAcquireDatapathRead(datapath, &dpLockState, FALSE);
2318
flow = OvsLookupFlow(datapath, &getInput->key, &hash, FALSE);
2320
status = STATUS_INVALID_PARAMETER;
2324
getOutput = (OvsFlowGetOutput *)outputBuffer;
2325
ReportFlowInfo(flow, getFlags, &getOutput->info);
2328
OvsReleaseDatapath(datapath, &dpLockState);
2334
OvsFlushFlowIoctl(UINT32 dpNo)
2336
NTSTATUS status = STATUS_SUCCESS;
2337
OVS_DATAPATH *datapath = NULL;
2338
LOCK_STATE_EX dpLockState;
2340
if (gOvsSwitchContext->dpNo != dpNo) {
2341
status = STATUS_INVALID_PARAMETER;
2345
datapath = &gOvsSwitchContext->datapath;
2347
OvsAcquireDatapathWrite(datapath, &dpLockState, FALSE);
2348
DeleteAllFlows(datapath);
2349
OvsReleaseDatapath(datapath, &dpLockState);
2356
OvsFlowKeyAttrSize(void)
2358
return NlAttrTotalSize(4) /* OVS_KEY_ATTR_PRIORITY */
2359
+ NlAttrTotalSize(0) /* OVS_KEY_ATTR_TUNNEL */
2360
+ OvsTunKeyAttrSize()
2361
+ NlAttrTotalSize(4) /* OVS_KEY_ATTR_IN_PORT */
2362
+ NlAttrTotalSize(4) /* OVS_KEY_ATTR_SKB_MARK */
2363
+ NlAttrTotalSize(4) /* OVS_KEY_ATTR_DP_HASH */
2364
+ NlAttrTotalSize(4) /* OVS_KEY_ATTR_RECIRC_ID */
2365
+ NlAttrTotalSize(12) /* OVS_KEY_ATTR_ETHERNET */
2366
+ NlAttrTotalSize(2) /* OVS_KEY_ATTR_ETHERTYPE */
2367
+ NlAttrTotalSize(4) /* OVS_KEY_ATTR_VLAN */
2368
+ NlAttrTotalSize(0) /* OVS_KEY_ATTR_ENCAP */
2369
+ NlAttrTotalSize(2) /* OVS_KEY_ATTR_ETHERTYPE */
2370
+ NlAttrTotalSize(40) /* OVS_KEY_ATTR_IPV6 */
2371
+ NlAttrTotalSize(2) /* OVS_KEY_ATTR_ICMPV6 */
2372
+ NlAttrTotalSize(28); /* OVS_KEY_ATTR_ND */
2376
OvsTunKeyAttrSize(void)
2378
/* Whenever adding new OVS_TUNNEL_KEY_ FIELDS, we should consider
2379
* updating this function.
2381
return NlAttrTotalSize(8) /* OVS_TUNNEL_KEY_ATTR_ID */
2382
+ NlAttrTotalSize(4) /* OVS_TUNNEL_KEY_ATTR_IPV4_SRC */
2383
+ NlAttrTotalSize(4) /* OVS_TUNNEL_KEY_ATTR_IPV4_DST */
2384
+ NlAttrTotalSize(1) /* OVS_TUNNEL_KEY_ATTR_TOS */
2385
+ NlAttrTotalSize(1) /* OVS_TUNNEL_KEY_ATTR_TTL */
2386
+ NlAttrTotalSize(0) /* OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT */
2387
+ NlAttrTotalSize(0) /* OVS_TUNNEL_KEY_ATTR_CSUM */
2388
+ NlAttrTotalSize(0) /* OVS_TUNNEL_KEY_ATTR_OAM */
2389
+ NlAttrTotalSize(256) /* OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS */
2390
+ NlAttrTotalSize(2) /* OVS_TUNNEL_KEY_ATTR_TP_SRC */
2391
+ NlAttrTotalSize(2); /* OVS_TUNNEL_KEY_ATTR_TP_DST */
2394
#pragma warning( pop )