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
_MapNlToFlowPutFlags(PGENL_MSG_HDR genlMsgHdr
,
58 PNL_ATTR flowAttrClear
,
59 OvsFlowPut
*mappedFlow
);
61 static NTSTATUS
_FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx
,
63 static NTSTATUS
_FlowNlDumpCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx
,
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
,
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
);
83 static NTSTATUS
OvsDoDumpFlows(OvsFlowDumpInput
*dumpInput
,
84 OvsFlowDumpOutput
*dumpOutput
,
86 static NTSTATUS
OvsProbeSupportedFeature(POVS_MESSAGE msgIn
,
90 #define OVS_FLOW_TABLE_SIZE 2048
91 #define OVS_FLOW_TABLE_MASK (OVS_FLOW_TABLE_SIZE -1)
92 #define HASH_BUCKET(hash) ((hash) & OVS_FLOW_TABLE_MASK)
94 /* Flow family related netlink policies */
96 /* For Parsing attributes in FLOW_* commands */
97 const NL_POLICY nlFlowPolicy
[] = {
98 [OVS_FLOW_ATTR_KEY
] = {.type
= NL_A_NESTED
, .optional
= FALSE
},
99 [OVS_FLOW_ATTR_MASK
] = {.type
= NL_A_NESTED
, .optional
= TRUE
},
100 [OVS_FLOW_ATTR_ACTIONS
] = {.type
= NL_A_NESTED
, .optional
= TRUE
},
101 [OVS_FLOW_ATTR_STATS
] = {.type
= NL_A_UNSPEC
,
102 .minLen
= sizeof(struct ovs_flow_stats
),
103 .maxLen
= sizeof(struct ovs_flow_stats
),
105 [OVS_FLOW_ATTR_TCP_FLAGS
] = {NL_A_U8
, .optional
= TRUE
},
106 [OVS_FLOW_ATTR_USED
] = {NL_A_U64
, .optional
= TRUE
},
107 [OVS_FLOW_ATTR_PROBE
] = {.type
= NL_A_FLAG
, .optional
= TRUE
}
110 /* For Parsing nested OVS_FLOW_ATTR_KEY attributes. */
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
},
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
),
184 const UINT32 nlFlowKeyPolicyLen
= ARRAY_SIZE(nlFlowKeyPolicy
);
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
,
207 const UINT32 nlFlowTunnelKeyPolicyLen
= ARRAY_SIZE(nlFlowTunnelKeyPolicy
);
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
,
216 sizeof(struct ovs_action_push_vlan
),
218 sizeof(struct ovs_action_push_vlan
),
220 [OVS_ACTION_ATTR_POP_VLAN
] = {.type
= NL_A_UNSPEC
, .optional
= TRUE
},
221 [OVS_ACTION_ATTR_PUSH_MPLS
] = {.type
= NL_A_UNSPEC
,
223 sizeof(struct ovs_action_push_mpls
),
225 sizeof(struct ovs_action_push_mpls
),
227 [OVS_ACTION_ATTR_POP_MPLS
] = {.type
= NL_A_UNSPEC
,
228 .minLen
= sizeof(UINT16
),
229 .maxLen
= sizeof(UINT16
),
231 [OVS_ACTION_ATTR_RECIRC
] = {.type
= NL_A_UNSPEC
,
232 .minLen
= sizeof(UINT32
),
233 .maxLen
= sizeof(UINT32
),
235 [OVS_ACTION_ATTR_HASH
] = {.type
= NL_A_UNSPEC
,
236 .minLen
= sizeof(struct ovs_action_hash
),
237 .maxLen
= sizeof(struct ovs_action_hash
),
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
}
245 *----------------------------------------------------------------------------
246 * Netlink interface for flow commands.
247 *----------------------------------------------------------------------------
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 *----------------------------------------------------------------------------
258 OvsFlowNlCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx
,
261 NTSTATUS rc
= STATUS_SUCCESS
;
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
;
272 struct ovs_flow_stats replyStats
;
273 NL_ERROR nlError
= NL_ERROR_SUCCESS
;
276 RtlZeroMemory(&mappedFlow
, sizeof(OvsFlowPut
));
277 RtlZeroMemory(&stats
, sizeof(stats
));
278 RtlZeroMemory(&replyStats
, sizeof(replyStats
));
280 if (!(usrParamsCtx
->outputBuffer
)) {
281 /* No output buffer */
282 rc
= STATUS_INVALID_BUFFER_SIZE
;
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
))) {
291 rc
= OvsFlushFlowIoctl(ovsHdr
->dp_ifindex
);
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
);
299 /* Prepare nl Msg headers */
300 ok
= NlFillOvsMsg(&nlBuf
, nlMsgHdr
->nlmsgType
, 0,
301 nlMsgHdr
->nlmsgSeq
, nlMsgHdr
->nlmsgPid
,
302 genlMsgHdr
->cmd
, OVS_FLOW_VERSION
,
305 *replyLen
= msgOut
->nlMsg
.nlmsgLen
;
307 rc
= STATUS_INVALID_BUFFER_SIZE
;
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
)))
319 OVS_LOG_ERROR("Attr Parsing failed for msg: %p",
321 rc
= STATUS_INVALID_PARAMETER
;
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
);
333 if ((rc
= _MapNlToFlowPut(msgIn
, flowAttrs
[OVS_FLOW_ATTR_KEY
],
334 flowAttrs
[OVS_FLOW_ATTR_ACTIONS
],
335 flowAttrs
[OVS_FLOW_ATTR_CLEAR
],
338 OVS_LOG_ERROR("Conversion to OvsFlowPut failed");
342 rc
= OvsPutFlowIoctl(&mappedFlow
, sizeof (struct OvsFlowPut
),
344 if (rc
!= STATUS_SUCCESS
) {
345 OVS_LOG_ERROR("OvsPutFlowIoctl failed.");
347 * Report back to the userspace the flow could not be modified,
350 nlError
= NL_ERROR_NOENT
;
351 if (rc
== STATUS_DUPLICATE_NAME
) {
352 nlError
= NL_ERROR_EXIST
;
357 replyStats
.n_packets
= stats
.packetCount
;
358 replyStats
.n_bytes
= stats
.byteCount
;
360 /* So far so good. Prepare the reply for userspace */
361 NlBufInit(&nlBuf
, usrParamsCtx
->outputBuffer
,
362 usrParamsCtx
->outputLength
);
364 /* Prepare nl Msg headers */
365 ok
= NlFillOvsMsg(&nlBuf
, nlMsgHdr
->nlmsgType
, 0,
366 nlMsgHdr
->nlmsgSeq
, nlMsgHdr
->nlmsgPid
,
367 genlMsgHdr
->cmd
, OVS_FLOW_VERSION
,
370 rc
= STATUS_INVALID_BUFFER_SIZE
;
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
;
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
;
393 msgOut
->nlMsg
.nlmsgLen
= NLMSG_ALIGN(NlBufSize(&nlBuf
));
394 *replyLen
= msgOut
->nlMsg
.nlmsgLen
;
398 if (nlError
!= NL_ERROR_SUCCESS
) {
399 POVS_MESSAGE_ERROR msgError
= (POVS_MESSAGE_ERROR
)
400 usrParamsCtx
->outputBuffer
;
403 NlBuildErrorMsg(msgIn
, msgError
, nlError
, replyLen
);
404 ASSERT(*replyLen
!= 0);
412 *----------------------------------------------------------------------------
413 * OvsFlowNlGetCmdHandler --
414 * Handler for OVS_FLOW_CMD_GET/DUMP commands.
415 *----------------------------------------------------------------------------
418 OvsFlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx
,
421 NTSTATUS status
= STATUS_SUCCESS
;
423 if (usrParamsCtx
->devOp
== OVS_TRANSACTION_DEV_OP
) {
424 status
= _FlowNlGetCmdHandler(usrParamsCtx
, replyLen
);
426 status
= _FlowNlDumpCmdHandler(usrParamsCtx
, replyLen
);
433 *----------------------------------------------------------------------------
434 * _FlowNlGetCmdHandler --
435 * Handler for OVS_FLOW_CMD_GET command.
436 *----------------------------------------------------------------------------
439 _FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx
,
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
];
450 OvsFlowGetInput getInput
;
451 OvsFlowGetOutput getOutput
;
453 PNL_ATTR keyAttrs
[__OVS_KEY_ATTR_MAX
];
454 PNL_ATTR tunnelAttrs
[__OVS_TUNNEL_KEY_ATTR_MAX
];
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;
463 NL_ERROR nlError
= NL_ERROR_SUCCESS
;
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
);
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
)))
480 OVS_LOG_ERROR("Attr Parsing failed for msg: %p",
482 rc
= STATUS_INVALID_PARAMETER
;
486 keyAttrOffset
= (UINT32
)((PCHAR
) nlAttrs
[OVS_FLOW_ATTR_KEY
] -
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
)))
495 OVS_LOG_ERROR("Key Attr Parsing failed for msg: %p",
497 rc
= STATUS_INVALID_PARAMETER
;
501 if (keyAttrs
[OVS_KEY_ATTR_TUNNEL
]) {
502 tunnelKeyAttrOffset
= (UINT32
)((PCHAR
)
503 (keyAttrs
[OVS_KEY_ATTR_TUNNEL
])
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
)))
513 OVS_LOG_ERROR("Tunnel key Attr Parsing failed for msg: %p",
515 rc
= STATUS_INVALID_PARAMETER
;
520 _MapKeyAttrToFlowPut(keyAttrs
, tunnelAttrs
,
523 getInput
.dpNo
= ovsHdr
->dp_ifindex
;
524 getInput
.getFlags
= FLOW_GET_STATS
| FLOW_GET_ACTIONS
;
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.");
533 * Report back to the userspace the flow could not be found
535 nlError
= NL_ERROR_NOENT
;
539 /* Lets prepare the reply. */
540 nlMsgOutHdr
= (PNL_MSG_HDR
)(NlBufAt(&nlBuf
, 0, 0));
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
);
547 OVS_LOG_ERROR("Could not copy the data to the buffer tail");
551 rc
= _MapFlowStatsToNlStats(&nlBuf
, &((getOutput
.info
).stats
));
552 if (rc
!= STATUS_SUCCESS
) {
553 OVS_LOG_ERROR("_OvsFlowMapFlowKeyToNlStats failed.");
557 rc
= _MapFlowActionToNlAction(&nlBuf
, ((getOutput
.info
).actionsLen
),
558 getOutput
.info
.actions
);
559 if (rc
!= STATUS_SUCCESS
) {
560 OVS_LOG_ERROR("_MapFlowActionToNlAction failed.");
564 NlMsgSetSize(nlMsgOutHdr
, NlBufSize(&nlBuf
));
565 NlMsgAlignSize(nlMsgOutHdr
);
566 *replyLen
+= NlMsgSize(nlMsgOutHdr
);
569 if (nlError
!= NL_ERROR_SUCCESS
) {
570 POVS_MESSAGE_ERROR msgError
= (POVS_MESSAGE_ERROR
)
571 usrParamsCtx
->outputBuffer
;
574 NlBuildErrorMsg(msgIn
, msgError
, nlError
, replyLen
);
575 ASSERT(*replyLen
!= 0);
583 *----------------------------------------------------------------------------
584 * _FlowNlDumpCmdHandler --
585 * Handler for OVS_FLOW_CMD_DUMP command.
586 *----------------------------------------------------------------------------
589 _FlowNlDumpCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx
,
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
;
599 if (usrParamsCtx
->devOp
== OVS_WRITE_DEV_OP
) {
601 OvsSetupDumpStart(usrParamsCtx
);
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;
612 OvsFlowDumpOutput dumpOutput
;
613 OvsFlowDumpInput dumpInput
;
616 NlBufInit(&nlBuf
, usrParamsCtx
->outputBuffer
,
617 usrParamsCtx
->outputLength
);
619 ASSERT(usrParamsCtx
->devOp
== OVS_READ_DEV_OP
);
620 ASSERT(usrParamsCtx
->outputLength
);
622 RtlZeroMemory(&dumpInput
, sizeof(OvsFlowDumpInput
));
623 RtlZeroMemory(&dumpOutput
, sizeof(OvsFlowDumpOutput
));
625 dumpInput
.dpNo
= ovsHdr
->dp_ifindex
;
626 dumpInput
.getFlags
= FLOW_GET_KEY
| FLOW_GET_STATS
| FLOW_GET_ACTIONS
;
628 /* Lets provide as many flows to userspace as possible. */
630 dumpInput
.position
[0] = instance
->dumpState
.index
[0];
631 dumpInput
.position
[1] = instance
->dumpState
.index
[1];
633 rc
= OvsDoDumpFlows(&dumpInput
, &dumpOutput
, &temp
);
634 if (rc
!= STATUS_SUCCESS
) {
635 OVS_LOG_ERROR("OvsDoDumpFlows failed with rc: %d", rc
);
637 * Report back to the userspace the flows could not be found
639 nlError
= NL_ERROR_NOENT
;
643 /* Done with Dump, send NLMSG_DONE */
644 if (!(dumpOutput
.n
)) {
647 OVS_LOG_INFO("Dump Done");
649 nlMsgOutHdr
= (PNL_MSG_HDR
)(NlBufAt(&nlBuf
, NlBufSize(&nlBuf
), 0));
650 ok
= NlFillNlHdr(&nlBuf
, NLMSG_DONE
, NLM_F_MULTI
,
651 nlMsgHdr
->nlmsgSeq
, nlMsgHdr
->nlmsgPid
);
654 rc
= STATUS_INVALID_BUFFER_SIZE
;
655 OVS_LOG_ERROR("Unable to prepare DUMP_DONE reply.");
661 NlMsgAlignSize(nlMsgOutHdr
);
662 *replyLen
+= NlMsgSize(nlMsgOutHdr
);
664 FreeUserDumpState(instance
);
669 hdrOffset
= NlBufSize(&nlBuf
);
670 nlMsgOutHdr
= (PNL_MSG_HDR
)(NlBufAt(&nlBuf
, hdrOffset
, 0));
673 ok
= NlFillOvsMsg(&nlBuf
, nlMsgHdr
->nlmsgType
, NLM_F_MULTI
,
674 nlMsgHdr
->nlmsgSeq
, nlMsgHdr
->nlmsgPid
,
675 genlMsgHdr
->cmd
, genlMsgHdr
->version
,
679 /* Reset rc to success so that we can
680 * send already added messages to user space. */
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
));
694 /* Reset rc to success so that we can
695 * send already added messages to user space. */
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];
709 if (nlError
!= NL_ERROR_SUCCESS
) {
710 POVS_MESSAGE_ERROR msgError
= (POVS_MESSAGE_ERROR
)
711 usrParamsCtx
->outputBuffer
;
713 NlBuildErrorMsg(msgIn
, msgError
, nlError
, replyLen
);
714 ASSERT(*replyLen
!= 0);
722 *----------------------------------------------------------------------------
723 * _MapFlowInfoToNl --
724 * Maps OvsFlowInfo to Netlink attributes.
725 *----------------------------------------------------------------------------
728 _MapFlowInfoToNl(PNL_BUFFER nlBuf
, OvsFlowInfo
*flowInfo
)
732 rc
= MapFlowKeyToNlKey(nlBuf
, &(flowInfo
->key
), OVS_FLOW_ATTR_KEY
,
733 OVS_KEY_ATTR_TUNNEL
);
734 if (rc
!= STATUS_SUCCESS
) {
738 rc
= _MapFlowStatsToNlStats(nlBuf
, &(flowInfo
->stats
));
739 if (rc
!= STATUS_SUCCESS
) {
743 rc
= _MapFlowActionToNlAction(nlBuf
, flowInfo
->actionsLen
,
745 if (rc
!= STATUS_SUCCESS
) {
754 OvsFlowUsedTime(UINT64 flowUsed
)
756 UINT64 currentMs
, iddleMs
;
757 LARGE_INTEGER tickCount
;
759 KeQueryTickCount(&tickCount
);
760 iddleMs
= tickCount
.QuadPart
- flowUsed
;
761 iddleMs
*= ovsTimeIncrementPerTick
;
762 currentMs
= KeQueryPerformanceCounter(&tickCount
).QuadPart
* 1000 /
764 return currentMs
- iddleMs
;
768 *----------------------------------------------------------------------------
769 * _MapFlowStatsToNlStats --
770 * Maps OvsFlowStats to OVS_FLOW_ATTR_STATS attribute.
771 *----------------------------------------------------------------------------
774 _MapFlowStatsToNlStats(PNL_BUFFER nlBuf
, OvsFlowStats
*flowStats
)
776 NTSTATUS rc
= STATUS_SUCCESS
;
777 struct ovs_flow_stats replyStats
;
779 replyStats
.n_packets
= flowStats
->packetCount
;
780 replyStats
.n_bytes
= flowStats
->byteCount
;
782 if (flowStats
->used
&&
783 !NlMsgPutTailU64(nlBuf
, OVS_FLOW_ATTR_USED
,
784 OvsFlowUsedTime(flowStats
->used
))
786 rc
= STATUS_INVALID_BUFFER_SIZE
;
790 if (!NlMsgPutTailUnspec(nlBuf
, OVS_FLOW_ATTR_STATS
,
791 (PCHAR
)(&replyStats
),
792 sizeof(struct ovs_flow_stats
))) {
793 rc
= STATUS_INVALID_BUFFER_SIZE
;
797 if (!NlMsgPutTailU8(nlBuf
, OVS_FLOW_ATTR_TCP_FLAGS
, flowStats
->tcpFlags
)) {
798 rc
= STATUS_INVALID_BUFFER_SIZE
;
807 *----------------------------------------------------------------------------
808 * _MapFlowActionToNlAction --
809 * Maps flow actions to OVS_FLOW_ATTR_ACTION attribute.
810 *----------------------------------------------------------------------------
813 _MapFlowActionToNlAction(PNL_BUFFER nlBuf
, uint32_t actionsLen
,
816 NTSTATUS rc
= STATUS_SUCCESS
;
819 offset
= NlMsgStartNested(nlBuf
, OVS_FLOW_ATTR_ACTIONS
);
821 /* Starting the nested attribute failed. */
822 rc
= STATUS_INVALID_BUFFER_SIZE
;
823 goto error_nested_start
;
826 if (!NlBufCopyAtTail(nlBuf
, (PCHAR
)actions
, actionsLen
)) {
827 /* Adding a nested attribute failed. */
828 rc
= STATUS_INVALID_BUFFER_SIZE
;
833 NlMsgEndNested(nlBuf
, offset
);
840 *----------------------------------------------------------------------------
841 * MapFlowKeyToNlKey --
842 * Maps OvsFlowKey to OVS_FLOW_ATTR_KEY attribute.
843 *----------------------------------------------------------------------------
846 MapFlowKeyToNlKey(PNL_BUFFER nlBuf
,
851 NTSTATUS rc
= STATUS_SUCCESS
;
852 struct ovs_key_ethernet ethKey
;
855 offset
= NlMsgStartNested(nlBuf
, keyType
);
857 /* Starting the nested attribute failed. */
858 rc
= STATUS_UNSUCCESSFUL
;
859 goto error_nested_start
;
862 if (!NlMsgPutTailU32(nlBuf
, OVS_KEY_ATTR_RECIRC_ID
,
863 flowKey
->recircId
)) {
864 rc
= STATUS_UNSUCCESSFUL
;
868 if (!NlMsgPutTailU32(nlBuf
, OVS_KEY_ATTR_CT_STATE
,
869 flowKey
->ct
.state
)) {
870 rc
= STATUS_UNSUCCESSFUL
;
873 if (!NlMsgPutTailU16(nlBuf
, OVS_KEY_ATTR_CT_ZONE
,
875 rc
= STATUS_UNSUCCESSFUL
;
878 if (!NlMsgPutTailU32(nlBuf
, OVS_KEY_ATTR_CT_MARK
,
880 rc
= STATUS_UNSUCCESSFUL
;
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
;
890 if (flowKey
->dpHash
) {
891 if (!NlMsgPutTailU32(nlBuf
, OVS_KEY_ATTR_DP_HASH
,
893 rc
= STATUS_UNSUCCESSFUL
;
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
);
902 if (!NlMsgPutTailUnspec(nlBuf
, OVS_KEY_ATTR_ETHERNET
,
904 sizeof(struct ovs_key_ethernet
))) {
905 rc
= STATUS_UNSUCCESSFUL
;
909 if (!NlMsgPutTailU32(nlBuf
, OVS_KEY_ATTR_IN_PORT
,
910 flowKey
->l2
.inPort
)) {
911 rc
= STATUS_UNSUCCESSFUL
;
915 if (!NlMsgPutTailU16(nlBuf
, OVS_KEY_ATTR_ETHERTYPE
,
916 flowKey
->l2
.dlType
)) {
917 rc
= STATUS_UNSUCCESSFUL
;
921 if (flowKey
->l2
.vlanTci
) {
922 if (!NlMsgPutTailU16(nlBuf
, OVS_KEY_ATTR_VLAN
,
923 flowKey
->l2
.vlanTci
)) {
924 rc
= STATUS_UNSUCCESSFUL
;
929 /* ==== L3 + L4 ==== */
930 switch (ntohs(flowKey
->l2
.dlType
)) {
931 case ETH_TYPE_IPV4
: {
932 IpKey
*ipv4FlowPutKey
= &(flowKey
->ipKey
);
933 rc
= _MapFlowIpv4KeyToNlKey(nlBuf
, ipv4FlowPutKey
);
937 case ETH_TYPE_IPV6
: {
938 Ipv6Key
*ipv6FlowPutKey
= &(flowKey
->ipv6Key
);
939 Icmp6Key
*icmpv6FlowPutKey
= &(flowKey
->icmp6Key
);
940 rc
= _MapFlowIpv6KeyToNlKey(nlBuf
, ipv6FlowPutKey
,
946 case ETH_TYPE_RARP
: {
947 ArpKey
*arpFlowPutKey
= &(flowKey
->arpKey
);
948 rc
= _MapFlowArpKeyToNlKey(nlBuf
, arpFlowPutKey
);
953 case ETH_TYPE_MPLS_MCAST
: {
954 MplsKey
*mplsFlowPutKey
= &(flowKey
->mplsKey
);
955 rc
= _MapFlowMplsKeyToNlKey(nlBuf
, mplsFlowPutKey
);
963 if (rc
!= STATUS_SUCCESS
) {
967 if (flowKey
->tunKey
.dst
) {
968 rc
= MapFlowTunKeyToNlKey(nlBuf
, &(flowKey
->tunKey
),
970 if (rc
!= STATUS_SUCCESS
) {
976 NlMsgEndNested(nlBuf
, offset
);
982 *----------------------------------------------------------------------------
983 * MapFlowTunKeyToNlKey --
984 * Maps OvsIPv4TunnelKey to OVS_TUNNEL_KEY_ATTR_ID attribute.
985 *----------------------------------------------------------------------------
988 MapFlowTunKeyToNlKey(PNL_BUFFER nlBuf
,
989 OvsIPv4TunnelKey
*tunKey
,
992 NTSTATUS rc
= STATUS_SUCCESS
;
995 offset
= NlMsgStartNested(nlBuf
, tunKeyType
);
997 /* Starting the nested attribute failed. */
998 rc
= STATUS_UNSUCCESSFUL
;
999 goto error_nested_start
;
1002 if (!NlMsgPutTailU64(nlBuf
, OVS_TUNNEL_KEY_ATTR_ID
,
1003 tunKey
->tunnelId
)) {
1004 rc
= STATUS_UNSUCCESSFUL
;
1008 if (!NlMsgPutTailU32(nlBuf
, OVS_TUNNEL_KEY_ATTR_IPV4_DST
,
1010 rc
= STATUS_UNSUCCESSFUL
;
1014 if (!NlMsgPutTailU32(nlBuf
, OVS_TUNNEL_KEY_ATTR_IPV4_SRC
,
1016 rc
= STATUS_UNSUCCESSFUL
;
1020 if (!NlMsgPutTailU8(nlBuf
, OVS_TUNNEL_KEY_ATTR_TOS
,
1022 rc
= STATUS_UNSUCCESSFUL
;
1026 if (!NlMsgPutTailU8(nlBuf
, OVS_TUNNEL_KEY_ATTR_TTL
,
1028 rc
= STATUS_UNSUCCESSFUL
;
1033 NlMsgEndNested(nlBuf
, offset
);
1039 *----------------------------------------------------------------------------
1040 * _MapFlowTunKeyToNlKey --
1041 * Maps OvsIPv4FlowPutKey to OVS_KEY_ATTR_IPV4 attribute.
1042 *----------------------------------------------------------------------------
1045 _MapFlowIpv4KeyToNlKey(PNL_BUFFER nlBuf
, IpKey
*ipv4FlowPutKey
)
1047 NTSTATUS rc
= STATUS_SUCCESS
;
1048 struct ovs_key_ipv4 ipv4Key
;
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
;
1057 if (!NlMsgPutTailUnspec(nlBuf
, OVS_KEY_ATTR_IPV4
,
1059 sizeof(struct ovs_key_ipv4
))) {
1060 rc
= STATUS_UNSUCCESSFUL
;
1064 switch (ipv4Key
.ipv4_proto
) {
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
,
1072 rc
= STATUS_UNSUCCESSFUL
;
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
,
1085 rc
= STATUS_UNSUCCESSFUL
;
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
,
1098 rc
= STATUS_UNSUCCESSFUL
;
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
);
1109 if (!NlMsgPutTailUnspec(nlBuf
, OVS_KEY_ATTR_ICMP
,
1112 rc
= STATUS_UNSUCCESSFUL
;
1127 *----------------------------------------------------------------------------
1128 * _MapFlowIpv6KeyToNlKey --
1129 * Maps _MapFlowIpv6KeyToNlKey to OVS_KEY_ATTR_IPV6 attribute.
1130 *----------------------------------------------------------------------------
1133 _MapFlowIpv6KeyToNlKey(PNL_BUFFER nlBuf
, Ipv6Key
*ipv6FlowPutKey
,
1134 Icmp6Key
*icmpv6FlowPutKey
)
1136 NTSTATUS rc
= STATUS_SUCCESS
;
1137 struct ovs_key_ipv6 ipv6Key
;
1139 RtlCopyMemory(&(ipv6Key
.ipv6_src
), &ipv6FlowPutKey
->ipv6Src
,
1140 sizeof ipv6Key
.ipv6_src
);
1141 RtlCopyMemory(&(ipv6Key
.ipv6_dst
), &ipv6FlowPutKey
->ipv6Dst
,
1142 sizeof ipv6Key
.ipv6_dst
);
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
;
1150 if (!NlMsgPutTailUnspec(nlBuf
, OVS_KEY_ATTR_IPV6
,
1153 rc
= STATUS_UNSUCCESSFUL
;
1157 switch (ipv6Key
.ipv6_proto
) {
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
,
1165 rc
= STATUS_UNSUCCESSFUL
;
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
,
1178 rc
= STATUS_UNSUCCESSFUL
;
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
,
1191 rc
= STATUS_UNSUCCESSFUL
;
1197 case IPPROTO_ICMPV6
: {
1198 struct ovs_key_icmpv6 icmpV6Key
;
1199 struct ovs_key_nd ndKey
;
1201 icmpV6Key
.icmpv6_type
= (__u8
)ntohs(icmpv6FlowPutKey
->l4
.tpSrc
);
1202 icmpV6Key
.icmpv6_code
= (__u8
)ntohs(icmpv6FlowPutKey
->l4
.tpDst
);
1204 if (!NlMsgPutTailUnspec(nlBuf
, OVS_KEY_ATTR_ICMPV6
,
1205 (PCHAR
)(&icmpV6Key
),
1206 sizeof(icmpV6Key
))) {
1207 rc
= STATUS_UNSUCCESSFUL
;
1211 RtlCopyMemory(&(ndKey
.nd_target
), &icmpv6FlowPutKey
->ndTarget
,
1212 sizeof(icmpv6FlowPutKey
->ndTarget
));
1213 RtlCopyMemory(&(ndKey
.nd_sll
), &icmpv6FlowPutKey
->arpSha
,
1215 RtlCopyMemory(&(ndKey
.nd_tll
), &icmpv6FlowPutKey
->arpTha
,
1217 if (!NlMsgPutTailUnspec(nlBuf
, OVS_KEY_ATTR_ND
,
1220 rc
= STATUS_UNSUCCESSFUL
;
1236 *----------------------------------------------------------------------------
1237 * _MapFlowArpKeyToNlKey --
1238 * Maps _MapFlowArpKeyToNlKey to OVS_KEY_ATTR_ARP attribute.
1239 *----------------------------------------------------------------------------
1242 _MapFlowArpKeyToNlKey(PNL_BUFFER nlBuf
, ArpKey
*arpFlowPutKey
)
1244 NTSTATUS rc
= STATUS_SUCCESS
;
1245 struct ovs_key_arp arpKey
;
1247 arpKey
.arp_sip
= arpFlowPutKey
->nwSrc
;
1248 arpKey
.arp_tip
= arpFlowPutKey
->nwDst
;
1250 RtlCopyMemory(&(arpKey
.arp_sha
), arpFlowPutKey
->arpSha
, ETH_ADDR_LEN
);
1251 RtlCopyMemory(&(arpKey
.arp_tha
), arpFlowPutKey
->arpTha
, ETH_ADDR_LEN
);
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.
1261 * It is important to note that the flow table stores the ARP opcode field
1264 arpKey
.arp_op
= htons(arpFlowPutKey
->nwProto
);
1266 if (!NlMsgPutTailUnspec(nlBuf
, OVS_KEY_ATTR_ARP
,
1269 rc
= STATUS_UNSUCCESSFUL
;
1278 *----------------------------------------------------------------------------
1279 * _MapFlowMplsKeyToNlKey --
1280 * Maps _MapFlowMplsKeyToNlKey to OVS_KEY_ATTR_MPLS attribute.
1281 *----------------------------------------------------------------------------
1284 _MapFlowMplsKeyToNlKey(PNL_BUFFER nlBuf
, MplsKey
*mplsFlowPutKey
)
1286 NTSTATUS rc
= STATUS_SUCCESS
;
1287 struct ovs_key_mpls
*mplsKey
;
1289 mplsKey
= (struct ovs_key_mpls
*)
1290 NlMsgPutTailUnspecUninit(nlBuf
, OVS_KEY_ATTR_MPLS
, sizeof(*mplsKey
));
1292 rc
= STATUS_UNSUCCESSFUL
;
1296 mplsKey
->mpls_lse
= mplsFlowPutKey
->lse
;
1303 *----------------------------------------------------------------------------
1304 * _MapNlToFlowPut --
1305 * Maps input netlink message to OvsFlowPut.
1306 *----------------------------------------------------------------------------
1309 _MapNlToFlowPut(POVS_MESSAGE msgIn
, PNL_ATTR keyAttr
,
1310 PNL_ATTR actionAttr
, PNL_ATTR flowAttrClear
,
1311 OvsFlowPut
*mappedFlow
)
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
);
1318 UINT32 keyAttrOffset
= (UINT32
)((PCHAR
)keyAttr
- (PCHAR
)nlMsgHdr
);
1319 UINT32 tunnelKeyAttrOffset
;
1321 PNL_ATTR keyAttrs
[__OVS_KEY_ATTR_MAX
] = {NULL
};
1322 PNL_ATTR tunnelAttrs
[__OVS_TUNNEL_KEY_ATTR_MAX
] = {NULL
};
1324 /* Get flow keys attributes */
1325 if ((NlAttrParseNested(nlMsgHdr
, keyAttrOffset
, NlAttrLen(keyAttr
),
1326 nlFlowKeyPolicy
, ARRAY_SIZE(nlFlowKeyPolicy
),
1327 keyAttrs
, ARRAY_SIZE(keyAttrs
)))
1329 OVS_LOG_ERROR("Key Attr Parsing failed for msg: %p",
1331 rc
= STATUS_INVALID_PARAMETER
;
1335 if (keyAttrs
[OVS_KEY_ATTR_TUNNEL
]) {
1336 tunnelKeyAttrOffset
= (UINT32
)((PCHAR
)
1337 (keyAttrs
[OVS_KEY_ATTR_TUNNEL
])
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
)))
1347 OVS_LOG_ERROR("Tunnel key Attr Parsing failed for msg: %p",
1349 rc
= STATUS_INVALID_PARAMETER
;
1354 _MapKeyAttrToFlowPut(keyAttrs
, tunnelAttrs
,
1355 &(mappedFlow
->key
));
1357 /* Map the action */
1359 mappedFlow
->actionsLen
= NlAttrGetSize(actionAttr
);
1360 mappedFlow
->actions
= NlAttrGet(actionAttr
);
1363 mappedFlow
->dpNo
= ovsHdr
->dp_ifindex
;
1365 _MapNlToFlowPutFlags(genlMsgHdr
, flowAttrClear
,
1373 *----------------------------------------------------------------------------
1374 * _MapNlToFlowPutFlags --
1375 * Maps netlink message to OvsFlowPut->flags.
1376 *----------------------------------------------------------------------------
1379 _MapNlToFlowPutFlags(PGENL_MSG_HDR genlMsgHdr
,
1380 PNL_ATTR flowAttrClear
, OvsFlowPut
*mappedFlow
)
1384 switch (genlMsgHdr
->cmd
) {
1385 case OVS_FLOW_CMD_NEW
:
1386 flags
|= OVSWIN_FLOW_PUT_CREATE
;
1388 case OVS_FLOW_CMD_DEL
:
1389 flags
|= OVSWIN_FLOW_PUT_DELETE
;
1391 case OVS_FLOW_CMD_SET
:
1392 flags
|= OVSWIN_FLOW_PUT_MODIFY
;
1398 if (flowAttrClear
) {
1399 flags
|= OVSWIN_FLOW_PUT_CLEAR
;
1402 mappedFlow
->flags
= flags
;
1406 *----------------------------------------------------------------------------
1407 * _MapKeyAttrToFlowPut --
1408 * Converts FLOW_KEY attribute to OvsFlowPut->key.
1409 *----------------------------------------------------------------------------
1412 _MapKeyAttrToFlowPut(PNL_ATTR
*keyAttrs
,
1413 PNL_ATTR
*tunnelAttrs
,
1414 OvsFlowKey
*destKey
)
1416 MapTunAttrToFlowPut(keyAttrs
, tunnelAttrs
, destKey
);
1418 if (keyAttrs
[OVS_KEY_ATTR_RECIRC_ID
]) {
1419 destKey
->recircId
= NlAttrGetU32(keyAttrs
[OVS_KEY_ATTR_RECIRC_ID
]);
1422 if (keyAttrs
[OVS_KEY_ATTR_DP_HASH
]) {
1423 destKey
->dpHash
= NlAttrGetU32(keyAttrs
[OVS_KEY_ATTR_DP_HASH
]);
1426 if (keyAttrs
[OVS_KEY_ATTR_CT_STATE
]) {
1427 destKey
->ct
.state
= (NlAttrGetU32(keyAttrs
[OVS_KEY_ATTR_CT_STATE
]));
1430 if (keyAttrs
[OVS_KEY_ATTR_CT_ZONE
]) {
1431 destKey
->ct
.zone
= (NlAttrGetU16(keyAttrs
[OVS_KEY_ATTR_CT_ZONE
]));
1434 if (keyAttrs
[OVS_KEY_ATTR_CT_MARK
]) {
1435 destKey
->ct
.mark
= (NlAttrGetU32(keyAttrs
[OVS_KEY_ATTR_CT_MARK
]));
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
));
1444 /* ===== L2 headers ===== */
1445 destKey
->l2
.inPort
= NlAttrGetU32(keyAttrs
[OVS_KEY_ATTR_IN_PORT
]);
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
);
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
]));
1463 if (keyAttrs
[OVS_KEY_ATTR_VLAN
]) {
1464 destKey
->l2
.vlanTci
= NlAttrGetU16(keyAttrs
[OVS_KEY_ATTR_VLAN
]);
1467 /* ==== L3 + L4. ==== */
1468 destKey
->l2
.keyLen
= OVS_WIN_TUNNEL_KEY_SIZE
+ OVS_L2_KEY_SIZE
1469 - destKey
->l2
.offset
;
1471 switch (ntohs(destKey
->l2
.dlType
)) {
1472 case ETH_TYPE_IPV4
: {
1474 if (keyAttrs
[OVS_KEY_ATTR_IPV4
]) {
1475 const struct ovs_key_ipv4
*ipv4Key
;
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
;
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
;
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
;
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
;
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
);
1514 destKey
->l2
.keyLen
+= OVS_IP_KEY_SIZE
;
1518 case ETH_TYPE_IPV6
: {
1520 if (keyAttrs
[OVS_KEY_ATTR_IPV6
]) {
1521 const struct ovs_key_ipv6
*ipv6Key
;
1523 ipv6Key
= NlAttrGet(keyAttrs
[OVS_KEY_ATTR_IPV6
]);
1524 Ipv6Key
*ipv6FlowPutKey
= &(destKey
->ipv6Key
);
1526 RtlCopyMemory(&ipv6FlowPutKey
->ipv6Src
, ipv6Key
->ipv6_src
,
1527 sizeof ipv6Key
->ipv6_src
);
1528 RtlCopyMemory(&ipv6FlowPutKey
->ipv6Dst
, ipv6Key
->ipv6_dst
,
1529 sizeof ipv6Key
->ipv6_dst
);
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
;
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
;
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
;
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
;
1558 if (keyAttrs
[OVS_KEY_ATTR_ICMPV6
]) {
1559 const struct ovs_key_icmpv6
*icmpv6Key
;
1561 Icmp6Key
*icmp6FlowPutKey
= &(destKey
->icmp6Key
);
1563 icmpv6Key
= NlAttrGet(keyAttrs
[OVS_KEY_ATTR_ICMPV6
]);
1565 icmp6FlowPutKey
->l4
.tpSrc
= htons(icmpv6Key
->icmpv6_type
);
1566 icmp6FlowPutKey
->l4
.tpDst
= htons(icmpv6Key
->icmpv6_code
);
1568 if (keyAttrs
[OVS_KEY_ATTR_ND
]) {
1569 const struct ovs_key_nd
*ndKey
;
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
);
1580 destKey
->l2
.keyLen
+= OVS_ICMPV6_KEY_SIZE
;
1584 destKey
->l2
.keyLen
+= OVS_IPV6_KEY_SIZE
;
1587 ipv6FlowPutKey
->pad
= 0;
1592 case ETH_TYPE_RARP
: {
1594 if (keyAttrs
[OVS_KEY_ATTR_ARP
]) {
1595 ArpKey
*arpFlowPutKey
= &destKey
->arpKey
;
1596 const struct ovs_key_arp
*arpKey
;
1598 arpKey
= NlAttrGet(keyAttrs
[OVS_KEY_ATTR_ARP
]);
1600 arpFlowPutKey
->nwSrc
= arpKey
->arp_sip
;
1601 arpFlowPutKey
->nwDst
= arpKey
->arp_tip
;
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
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
;
1616 case ETH_TYPE_MPLS_MCAST
: {
1618 if (keyAttrs
[OVS_KEY_ATTR_MPLS
]) {
1619 MplsKey
*mplsFlowPutKey
= &destKey
->mplsKey
;
1620 const struct ovs_key_mpls
*mplsKey
;
1622 mplsKey
= NlAttrGet(keyAttrs
[OVS_KEY_ATTR_MPLS
]);
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
;
1637 *----------------------------------------------------------------------------
1638 * MapTunAttrToFlowPut --
1639 * Converts FLOW_TUNNEL_KEY attribute to OvsFlowKey->tunKey.
1640 *----------------------------------------------------------------------------
1643 MapTunAttrToFlowPut(PNL_ATTR
*keyAttrs
,
1645 OvsFlowKey
*destKey
)
1647 if (keyAttrs
[OVS_KEY_ATTR_TUNNEL
]) {
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
;
1655 if (tunAttrs
[OVS_TUNNEL_KEY_ATTR_IPV4_DST
]) {
1656 destKey
->tunKey
.dst
= NlAttrGetU32
1657 (tunAttrs
[OVS_TUNNEL_KEY_ATTR_IPV4_DST
]);
1660 if (tunAttrs
[OVS_TUNNEL_KEY_ATTR_IPV4_SRC
]) {
1661 destKey
->tunKey
.src
= NlAttrGetU32
1662 (tunAttrs
[OVS_TUNNEL_KEY_ATTR_IPV4_SRC
]);
1665 if (tunAttrs
[OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT
]) {
1666 destKey
->tunKey
.flags
|= OVS_TNL_F_DONT_FRAGMENT
;
1669 if (tunAttrs
[OVS_TUNNEL_KEY_ATTR_CSUM
]) {
1670 destKey
->tunKey
.flags
|= OVS_TNL_F_CSUM
;
1673 if (tunAttrs
[OVS_TUNNEL_KEY_ATTR_TOS
]) {
1674 destKey
->tunKey
.tos
= NlAttrGetU8
1675 (tunAttrs
[OVS_TUNNEL_KEY_ATTR_TOS
]);
1678 if (tunAttrs
[OVS_TUNNEL_KEY_ATTR_TTL
]) {
1679 destKey
->tunKey
.ttl
= NlAttrGetU8
1680 (tunAttrs
[OVS_TUNNEL_KEY_ATTR_TTL
]);
1683 destKey
->tunKey
.pad
= 0;
1684 destKey
->l2
.offset
= 0;
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
;
1694 *----------------------------------------------------------------------------
1695 * OvsDeleteFlowTable --
1697 * NDIS_STATUS_SUCCESS always.
1698 *----------------------------------------------------------------------------
1701 OvsDeleteFlowTable(OVS_DATAPATH
*datapath
)
1703 if (datapath
== NULL
|| datapath
->flowTable
== NULL
) {
1704 return NDIS_STATUS_SUCCESS
;
1707 DeleteAllFlows(datapath
);
1708 OvsFreeMemoryWithTag(datapath
->flowTable
, OVS_FLOW_POOL_TAG
);
1709 datapath
->flowTable
= NULL
;
1711 if (datapath
->lock
== NULL
) {
1712 return NDIS_STATUS_SUCCESS
;
1715 NdisFreeRWLock(datapath
->lock
);
1717 return NDIS_STATUS_SUCCESS
;
1721 *----------------------------------------------------------------------------
1722 * OvsAllocateFlowTable --
1724 * NDIS_STATUS_SUCCESS on success.
1725 * NDIS_STATUS_RESOURCES if memory couldn't be allocated
1726 *----------------------------------------------------------------------------
1729 OvsAllocateFlowTable(OVS_DATAPATH
*datapath
,
1730 POVS_SWITCH_CONTEXT switchContext
)
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
;
1740 for (i
= 0; i
< OVS_FLOW_TABLE_SIZE
; i
++) {
1741 bucket
= &(datapath
->flowTable
[i
]);
1742 InitializeListHead(bucket
);
1744 datapath
->lock
= NdisAllocateRWLock(switchContext
->NdisFilterHandle
);
1746 if (!datapath
->lock
) {
1747 return NDIS_STATUS_RESOURCES
;
1750 return NDIS_STATUS_SUCCESS
;
1755 *----------------------------------------------------------------------------
1756 * GetStartAddrNBL --
1757 * Get the virtual address of the frame.
1760 * Virtual address of the frame.
1761 *----------------------------------------------------------------------------
1763 static __inline VOID
*
1764 GetStartAddrNBL(const NET_BUFFER_LIST
*_pNB
)
1772 // Ethernet Header is a guaranteed safe access.
1773 curMdl
= (NET_BUFFER_LIST_FIRST_NB(_pNB
))->CurrentMdl
;
1774 curBuffer
= MmGetSystemAddressForMdlSafe(curMdl
, LowPagePriority
);
1779 curHeader
= (PEthHdr
)
1780 (curBuffer
+ (NET_BUFFER_LIST_FIRST_NB(_pNB
))->CurrentMdlOffset
);
1782 return (VOID
*) curHeader
;
1786 OvsFlowUsed(OvsFlow
*flow
,
1787 const NET_BUFFER_LIST
*packet
,
1788 const POVS_PACKET_HDR_INFO layers
)
1790 LARGE_INTEGER tickCount
;
1792 KeQueryTickCount(&tickCount
);
1793 flow
->used
= tickCount
.QuadPart
;
1794 flow
->packetCount
++;
1795 flow
->byteCount
+= OvsPacketLenNBL(packet
);
1796 flow
->tcpFlags
|= OvsGetTcpFlags(packet
, &flow
->key
, layers
);
1801 DeleteAllFlows(OVS_DATAPATH
*datapath
)
1806 for (i
= 0; i
< OVS_FLOW_TABLE_SIZE
; i
++) {
1808 bucket
= &(datapath
->flowTable
[i
]);
1809 while (!IsListEmpty(bucket
)) {
1811 next
= bucket
->Flink
;
1812 flow
= CONTAINING_RECORD(next
, OvsFlow
, ListEntry
);
1813 RemoveFlow(datapath
, &flow
);
1819 OvsGetFlowMetadata(OvsFlowKey
*key
,
1822 NDIS_STATUS status
= NDIS_STATUS_SUCCESS
;
1824 if (keyAttrs
[OVS_KEY_ATTR_RECIRC_ID
]) {
1825 key
->recircId
= NlAttrGetU32(keyAttrs
[OVS_KEY_ATTR_RECIRC_ID
]);
1828 if (keyAttrs
[OVS_KEY_ATTR_DP_HASH
]) {
1829 key
->dpHash
= NlAttrGetU32(keyAttrs
[OVS_KEY_ATTR_DP_HASH
]);
1832 if (keyAttrs
[OVS_KEY_ATTR_CT_STATE
]) {
1833 key
->ct
.state
= (NlAttrGetU32(keyAttrs
[OVS_KEY_ATTR_CT_STATE
]));
1836 if (keyAttrs
[OVS_KEY_ATTR_CT_ZONE
]) {
1837 key
->ct
.zone
= (NlAttrGetU16(keyAttrs
[OVS_KEY_ATTR_CT_ZONE
]));
1840 if (keyAttrs
[OVS_KEY_ATTR_CT_MARK
]) {
1841 key
->ct
.mark
= (NlAttrGetU32(keyAttrs
[OVS_KEY_ATTR_CT_MARK
]));
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
));
1854 *----------------------------------------------------------------------------
1855 * Initializes 'flow' members from 'packet', 'skb_priority', 'tun_id', and
1858 * Initializes 'packet' header pointers as follows:
1860 * - packet->l2 to the start of the Ethernet header.
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
1866 * - packet->l4 to just past the IPv4 header, if one is present and has a
1867 * correct length, and otherwise NULL.
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.
1872 * Returns NDIS_STATUS_SUCCESS normally. Fails only if packet data cannot be accessed
1873 * (e.g. if Pkt_CopyBytesOut() returns an error).
1874 *----------------------------------------------------------------------------
1877 OvsExtractFlow(const NET_BUFFER_LIST
*packet
,
1880 POVS_PACKET_HDR_INFO layers
,
1881 OvsIPv4TunnelKey
*tunKey
)
1883 struct Eth_Header
*eth
;
1890 ASSERT(tunKey
->dst
!= 0);
1891 RtlMoveMemory(&flow
->tunKey
, tunKey
, sizeof flow
->tunKey
);
1892 flow
->l2
.offset
= 0;
1894 flow
->tunKey
.dst
= 0;
1895 flow
->l2
.offset
= OVS_WIN_TUNNEL_KEY_SIZE
;
1898 flow
->l2
.inPort
= inPort
;
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
;
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
);
1913 vlanTagValue
= NET_BUFFER_LIST_INFO(packet
, Ieee8021QNetBufferListInfo
);
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));
1920 if (eth
->dix
.typeNBO
== ETH_TYPE_802_1PQ_NBO
) {
1921 Eth_802_1pq_Tag
*tag
= (Eth_802_1pq_Tag
*)ð
->dix
.typeNBO
;
1922 flow
->l2
.vlanTci
= ((UINT16
)tag
->priority
<< 13) |
1924 ((UINT16
)tag
->vidHi
<< 8) | tag
->vidLo
;
1925 offset
= sizeof (Eth_802_1pq_Tag
);
1927 flow
->l2
.vlanTci
= 0;
1931 * Please note after this point, src mac and dst mac should
1932 * not be accessed through eth
1934 eth
= (Eth_Header
*)((UINT8
*)eth
+ offset
);
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).
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
;
1958 flow
->l2
.dlType
= htons(OVSWIN_DL_TYPE_NONE
);
1959 layers
->l3Offset
= ETH_HEADER_LEN_DIX
+ offset
;
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
;
1969 flow
->l2
.keyLen
+= OVS_IP_KEY_SIZE
;
1971 nh
= OvsGetIp(packet
, layers
->l3Offset
, &ip_storage
);
1973 layers
->l4Offset
= layers
->l3Offset
+ nh
->ihl
* 4;
1975 ipKey
->nwSrc
= nh
->saddr
;
1976 ipKey
->nwDst
= nh
->daddr
;
1977 ipKey
->nwProto
= nh
->protocol
;
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
;
1986 ipKey
->nwFrag
= OVS_FRAG_TYPE_NONE
;
1989 ipKey
->nwTtl
= nh
->ttl
;
1990 ipKey
->l4
.tpSrc
= 0;
1991 ipKey
->l4
.tpDst
= 0;
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
;
2004 icmp
= OvsGetIcmp(packet
, layers
->l4Offset
, &icmpStorage
);
2006 ipKey
->l4
.tpSrc
= htons(icmp
->type
);
2007 ipKey
->l4
.tpDst
= htons(icmp
->code
);
2008 layers
->l7Offset
= layers
->l4Offset
+ sizeof *icmp
;
2013 ((UINT64
*)ipKey
)[0] = 0;
2014 ((UINT64
*)ipKey
)[1] = 0;
2016 } else if (flow
->l2
.dlType
== htons(ETH_TYPE_IPV6
)) {
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
));
2025 flow
->ipv6Key
.l4
.tpSrc
= 0;
2026 flow
->ipv6Key
.l4
.tpDst
= 0;
2027 flow
->ipv6Key
.pad
= 0;
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
);
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
);
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
);
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
;
2072 * In the presence of an MPLS label stack the end of the L2
2073 * header and the beginning of the L3 header differ.
2075 * A network packet may contain multiple MPLS labels, but we
2076 * are only interested in the topmost label stack entry.
2078 * Advance network header to the beginning of the L3 header.
2079 * layers->l3Offset corresponds to the end of the L2 header.
2081 for (UINT32 i
= 0; i
< FLOW_MAX_MPLS_LABELS
; i
++) {
2082 mpls
= OvsGetMpls(packet
, layers
->l3Offset
, &mplsStorage
);
2087 /* Keep only the topmost MPLS label stack entry. */
2089 mplsKey
->lse
= mpls
->lse
;
2092 layers
->l3Offset
+= MPLS_HLEN
;
2093 layers
->l4Offset
+= MPLS_HLEN
;
2095 if (mpls
->lse
& htonl(MPLS_BOS_MASK
)) {
2097 * Bottom of Stack bit is set, which means there are no
2098 * remaining MPLS labels in the packet.
2105 return NDIS_STATUS_SUCCESS
;
2109 FlowMemoryEqual(UINT64
*src
, UINT64
*dst
, UINT32 size
)
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
]) {
2124 FlowEqual(OvsFlow
*srcFlow
,
2125 const OvsFlowKey
*dstKey
,
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
,
2146 * ----------------------------------------------------------------------------
2148 * Add a flow to flow table.
2151 * NDIS_STATUS_SUCCESS if no same flow in the flow table.
2152 * ----------------------------------------------------------------------------
2155 AddFlow(OVS_DATAPATH
*datapath
, OvsFlow
*flow
)
2159 if (OvsLookupFlow(datapath
, &flow
->key
, &flow
->hash
, TRUE
) != NULL
) {
2160 return STATUS_INVALID_HANDLE
;
2163 head
= &(datapath
->flowTable
[HASH_BUCKET(flow
->hash
)]);
2165 * We need fence here to make sure flow's nextPtr is updated before
2166 * head->nextPtr is updated.
2170 //KeAcquireSpinLock(&FilterDeviceExtension->NblQueueLock, &oldIrql);
2171 InsertTailList(head
, &flow
->ListEntry
);
2172 //KeReleaseSpinLock(&FilterDeviceExtension->NblQueueLock, oldIrql);
2176 return STATUS_SUCCESS
;
2180 /* ----------------------------------------------------------------------------
2182 * Remove a flow from flow table, and added to wait list
2183 * ----------------------------------------------------------------------------
2186 RemoveFlow(OVS_DATAPATH
*datapath
,
2192 ASSERT(datapath
->nFlows
);
2194 // Remove the flow from queue
2195 RemoveEntryList(&f
->ListEntry
);
2201 * ----------------------------------------------------------------------------
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.
2209 * Flow pointer if lookup successful.
2210 * NULL if not exists.
2211 * ----------------------------------------------------------------------------
2214 OvsLookupFlow(OVS_DATAPATH
*datapath
,
2215 const OvsFlowKey
*key
,
2219 PLIST_ENTRY link
, head
;
2220 UINT16 offset
= key
->l2
.offset
;
2221 UINT16 size
= key
->l2
.keyLen
;
2224 ASSERT(key
->tunKey
.dst
|| offset
== sizeof (OvsIPv4TunnelKey
));
2225 ASSERT(!key
->tunKey
.dst
|| offset
== 0);
2227 start
= (UINT8
*)key
+ offset
;
2230 *hash
= OvsJhashBytes(start
, size
, 0);
2231 if (key
->recircId
) {
2232 *hash
= OvsJhashWords((UINT32
*)hash
, 1, key
->recircId
);
2235 *hash
= OvsJhashWords((UINT32
*)hash
, 1, key
->dpHash
);
2237 if (key
->ct
.state
) {
2238 *hash
= OvsJhashWords((UINT32
*)hash
, 1, key
->ct
.state
);
2241 *hash
= OvsJhashWords((UINT32
*)hash
, 1, key
->ct
.zone
);
2244 *hash
= OvsJhashWords((UINT32
*)hash
, 1, key
->ct
.zone
);
2246 if (key
->ct
.labels
.ct_labels
) {
2247 UINT32 lblHash
= OvsJhashBytes(&key
->ct
.labels
,
2248 sizeof(struct ovs_key_ct_labels
),
2250 *hash
= OvsJhashWords((UINT32
*)hash
, 1, lblHash
);
2254 head
= &datapath
->flowTable
[HASH_BUCKET(*hash
)];
2256 while (link
!= head
) {
2257 OvsFlow
*flow
= CONTAINING_RECORD(link
, OvsFlow
, ListEntry
);
2259 if (FlowEqual(flow
, key
, start
, *hash
, offset
, size
)) {
2269 * ----------------------------------------------------------------------------
2271 * Calculate the hash for the given flow key.
2272 * ----------------------------------------------------------------------------
2275 OvsHashFlow(const OvsFlowKey
*key
)
2277 UINT16 offset
= key
->l2
.offset
;
2278 UINT16 size
= key
->l2
.keyLen
;
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);
2289 * ----------------------------------------------------------------------------
2291 * Free a flow and its actions.
2292 * ----------------------------------------------------------------------------
2295 FreeFlow(OvsFlow
*flow
)
2298 OvsFreeMemoryWithTag(flow
, OVS_FLOW_POOL_TAG
);
2302 OvsDoDumpFlows(OvsFlowDumpInput
*dumpInput
,
2303 OvsFlowDumpOutput
*dumpOutput
,
2307 OVS_DATAPATH
*datapath
= NULL
;
2309 PLIST_ENTRY node
, head
;
2311 UINT32 rowIndex
, columnIndex
;
2312 LOCK_STATE_EX dpLockState
;
2313 NTSTATUS status
= STATUS_SUCCESS
;
2314 BOOLEAN findNextNonEmpty
= FALSE
;
2316 dpNo
= dumpInput
->dpNo
;
2317 if (gOvsSwitchContext
->dpNo
!= dpNo
) {
2318 status
= STATUS_INVALID_PARAMETER
;
2322 rowIndex
= dumpInput
->position
[0];
2323 if (rowIndex
>= OVS_FLOW_TABLE_SIZE
) {
2325 *replyLen
= sizeof(*dumpOutput
);
2329 columnIndex
= dumpInput
->position
[1];
2331 datapath
= &gOvsSwitchContext
->datapath
;
2333 OvsAcquireDatapathRead(datapath
, &dpLockState
, FALSE
);
2335 head
= &datapath
->flowTable
[rowIndex
];
2338 while (column
< columnIndex
) {
2347 findNextNonEmpty
= TRUE
;
2351 if (findNextNonEmpty
) {
2352 while (head
== node
) {
2353 if (++rowIndex
>= OVS_FLOW_TABLE_SIZE
) {
2357 head
= &datapath
->flowTable
[rowIndex
];
2362 ASSERT(node
!= head
);
2363 ASSERT(rowIndex
< OVS_FLOW_TABLE_SIZE
);
2365 flow
= CONTAINING_RECORD(node
, OvsFlow
, ListEntry
);
2366 status
= ReportFlowInfo(flow
, dumpInput
->getFlags
, &dumpOutput
->flow
);
2368 if (status
== STATUS_BUFFER_TOO_SMALL
) {
2369 dumpOutput
->n
= sizeof(OvsFlowDumpOutput
) + flow
->actionsLen
;
2370 *replyLen
= sizeof(*dumpOutput
);
2372 dumpOutput
->n
= 1; //one flow reported.
2373 *replyLen
= sizeof(*dumpOutput
) + dumpOutput
->flow
.actionsLen
;
2376 dumpOutput
->position
[0] = rowIndex
;
2377 dumpOutput
->position
[1] = ++columnIndex
;
2380 OvsReleaseDatapath(datapath
, &dpLockState
);
2387 ReportFlowInfo(OvsFlow
*flow
,
2391 NTSTATUS status
= STATUS_SUCCESS
;
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
);
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
;
2407 if (getFlags
& FLOW_GET_ACTIONS
) {
2408 if (flow
->actionsLen
== 0) {
2409 info
->actionsLen
= 0;
2411 info
->actions
= flow
->actions
;
2412 info
->actionsLen
= flow
->actionsLen
;
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
));
2429 OvsPutFlowIoctl(PVOID inputBuffer
,
2431 struct OvsFlowStats
*stats
)
2433 NTSTATUS status
= STATUS_SUCCESS
;
2434 OVS_DATAPATH
*datapath
= NULL
;
2438 LOCK_STATE_EX dpLockState
;
2440 if ((inputLength
< sizeof(OvsFlowPut
)) || (inputBuffer
== NULL
)) {
2441 return STATUS_INFO_LENGTH_MISMATCH
;
2444 put
= (OvsFlowPut
*)inputBuffer
;
2445 if (put
->actionsLen
> 0) {
2446 actionsLen
= put
->actionsLen
;
2452 if (gOvsSwitchContext
->dpNo
!= dpNo
) {
2453 status
= STATUS_INVALID_PARAMETER
;
2457 datapath
= &gOvsSwitchContext
->datapath
;
2459 OvsAcquireDatapathWrite(datapath
, &dpLockState
, FALSE
);
2460 status
= HandleFlowPut(put
, datapath
, stats
);
2461 OvsReleaseDatapath(datapath
, &dpLockState
);
2468 /* Handles flow add, modify as well as delete */
2470 HandleFlowPut(OvsFlowPut
*put
,
2471 OVS_DATAPATH
*datapath
,
2472 struct OvsFlowStats
*stats
)
2474 BOOLEAN mayCreate
, mayModify
, mayDelete
;
2475 OvsFlow
*KernelFlow
;
2477 NTSTATUS status
= STATUS_SUCCESS
;
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;
2483 if ((mayCreate
|| mayModify
) == mayDelete
) {
2484 return STATUS_INVALID_PARAMETER
;
2487 KernelFlow
= OvsLookupFlow(datapath
, &put
->key
, &hash
, FALSE
);
2490 return STATUS_INVALID_PARAMETER
;
2493 status
= OvsPrepareFlow(&KernelFlow
, put
, hash
);
2494 if (status
!= STATUS_SUCCESS
) {
2495 return STATUS_UNSUCCESSFUL
;
2498 status
= AddFlow(datapath
, KernelFlow
);
2499 if (status
!= STATUS_SUCCESS
) {
2500 FreeFlow(KernelFlow
);
2501 return STATUS_UNSUCCESSFUL
;
2505 /* Validate the flow addition */
2508 OvsFlow
*flow
= OvsLookupFlow(datapath
, &put
->key
, &newHash
,
2511 ASSERT(newHash
== hash
);
2512 if (!flow
|| newHash
!= hash
) {
2513 return STATUS_UNSUCCESSFUL
;
2518 stats
->packetCount
= KernelFlow
->packetCount
;
2519 stats
->byteCount
= KernelFlow
->byteCount
;
2520 stats
->tcpFlags
= KernelFlow
->tcpFlags
;
2521 stats
->used
= KernelFlow
->used
;
2525 status
= OvsPrepareFlow(&newFlow
, put
, hash
);
2526 if (status
!= STATUS_SUCCESS
) {
2527 return STATUS_UNSUCCESSFUL
;
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
;
2536 RemoveFlow(datapath
, &KernelFlow
);
2537 status
= AddFlow(datapath
, newFlow
);
2538 ASSERT(status
== STATUS_SUCCESS
);
2541 /* Validate the flow addition */
2544 OvsFlow
*testflow
= OvsLookupFlow(datapath
, &put
->key
,
2547 ASSERT(newHash
== hash
);
2548 if (!testflow
|| newHash
!= hash
) {
2550 return STATUS_UNSUCCESSFUL
;
2557 RemoveFlow(datapath
, &KernelFlow
);
2560 /* Return duplicate if an identical flow already exists. */
2561 return STATUS_DUPLICATE_NAME
;
2565 return STATUS_SUCCESS
;
2569 OvsPrepareFlow(OvsFlow
**flow
,
2570 const OvsFlowPut
*put
,
2573 OvsFlow
*localFlow
= *flow
;
2574 NTSTATUS status
= STATUS_SUCCESS
;
2578 OvsAllocateMemoryWithTag(sizeof(OvsFlow
) + put
->actionsLen
,
2580 if (localFlow
== NULL
) {
2581 status
= STATUS_NO_MEMORY
;
2585 localFlow
->key
= put
->key
;
2586 localFlow
->actionsLen
= put
->actionsLen
;
2587 if (put
->actionsLen
) {
2588 NdisMoveMemory((PUCHAR
)localFlow
->actions
, put
->actions
,
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
;
2603 OvsGetFlowIoctl(PVOID inputBuffer
,
2606 NTSTATUS status
= STATUS_SUCCESS
;
2607 OVS_DATAPATH
*datapath
= NULL
;
2609 UINT32 getFlags
, getActionsLen
;
2610 OvsFlowGetInput
*getInput
;
2611 OvsFlowGetOutput
*getOutput
;
2614 LOCK_STATE_EX dpLockState
;
2616 getInput
= (OvsFlowGetInput
*) inputBuffer
;
2617 getFlags
= getInput
->getFlags
;
2618 getActionsLen
= getInput
->actionsLen
;
2620 if (outputBuffer
== NULL
) {
2621 return STATUS_INFO_LENGTH_MISMATCH
;
2624 dpNo
= getInput
->dpNo
;
2625 if (gOvsSwitchContext
->dpNo
!= dpNo
) {
2626 status
= STATUS_INVALID_PARAMETER
;
2630 datapath
= &gOvsSwitchContext
->datapath
;
2632 OvsAcquireDatapathRead(datapath
, &dpLockState
, FALSE
);
2633 flow
= OvsLookupFlow(datapath
, &getInput
->key
, &hash
, FALSE
);
2635 status
= STATUS_INVALID_PARAMETER
;
2639 getOutput
= (OvsFlowGetOutput
*)outputBuffer
;
2640 ReportFlowInfo(flow
, getFlags
, &getOutput
->info
);
2643 OvsReleaseDatapath(datapath
, &dpLockState
);
2649 OvsFlushFlowIoctl(UINT32 dpNo
)
2651 NTSTATUS status
= STATUS_SUCCESS
;
2652 OVS_DATAPATH
*datapath
= NULL
;
2653 LOCK_STATE_EX dpLockState
;
2655 if (gOvsSwitchContext
->dpNo
!= dpNo
) {
2656 status
= STATUS_INVALID_PARAMETER
;
2660 datapath
= &gOvsSwitchContext
->datapath
;
2662 OvsAcquireDatapathWrite(datapath
, &dpLockState
, FALSE
);
2663 DeleteAllFlows(datapath
);
2664 OvsReleaseDatapath(datapath
, &dpLockState
);
2671 OvsFlowKeyAttrSize(void)
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 */
2695 OvsTunKeyAttrSize(void)
2697 /* Whenever adding new OVS_TUNNEL_KEY_ FIELDS, we should consider
2698 * updating this function.
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 */
2714 *----------------------------------------------------------------------------
2715 * OvsProbeSupportedFeature --
2716 * Verifies if the probed feature is supported.
2719 * STATUS_SUCCESS if the probed feature is supported.
2720 *----------------------------------------------------------------------------
2723 OvsProbeSupportedFeature(POVS_MESSAGE msgIn
,
2726 NTSTATUS status
= STATUS_SUCCESS
;
2727 PNL_MSG_HDR nlMsgHdr
= &(msgIn
->nlMsg
);
2729 UINT32 keyAttrOffset
= (UINT32
)((PCHAR
)keyAttr
- (PCHAR
)nlMsgHdr
);
2730 PNL_ATTR keyAttrs
[__OVS_KEY_ATTR_MAX
] = { NULL
};
2732 /* Get flow keys attributes */
2733 if ((NlAttrParseNested(nlMsgHdr
, keyAttrOffset
, NlAttrLen(keyAttr
),
2734 nlFlowKeyPolicy
, ARRAY_SIZE(nlFlowKeyPolicy
),
2735 keyAttrs
, ARRAY_SIZE(keyAttrs
)))
2737 OVS_LOG_ERROR("Key Attr Parsing failed for msg: %p",
2739 status
= STATUS_INVALID_PARAMETER
;
2743 if (keyAttrs
[OVS_KEY_ATTR_MPLS
] &&
2744 keyAttrs
[OVS_KEY_ATTR_ETHERTYPE
]) {
2745 ovs_be16 ethType
= NlAttrGetU16(keyAttrs
[OVS_KEY_ATTR_ETHERTYPE
]);
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
;
2753 OVS_LOG_ERROR("Wrong ethertype for MPLS attribute.");
2754 status
= STATUS_INVALID_PARAMETER
;
2756 } else if (keyAttrs
[OVS_KEY_ATTR_RECIRC_ID
]) {
2757 UINT32 recircId
= NlAttrGetU32(keyAttrs
[OVS_KEY_ATTR_RECIRC_ID
]);
2760 OVS_LOG_ERROR("Invalid recirculation ID.");
2761 status
= STATUS_INVALID_PARAMETER
;
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
);
2769 } else if (keyAttrs
[OVS_KEY_ATTR_CT_ZONE
]) {
2770 UINT16 zone
= (NlAttrGetU16(keyAttrs
[OVS_KEY_ATTR_CT_ZONE
]));
2772 OVS_LOG_ERROR("Invalid zone specified.");
2773 status
= STATUS_INVALID_PARAMETER
;
2775 } else if (keyAttrs
[OVS_KEY_ATTR_CT_MARK
]) {
2776 UINT32 mark
= (NlAttrGetU32(keyAttrs
[OVS_KEY_ATTR_CT_MARK
]));
2778 OVS_LOG_ERROR("Invalid ct mark specified.");
2779 status
= STATUS_INVALID_PARAMETER
;
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
;
2789 OVS_LOG_ERROR("Feature not supported.");
2790 status
= STATUS_INVALID_PARAMETER
;
2797 #pragma warning( pop )