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"
27 #define OVS_DBG_MOD OVS_DBG_FLOW
30 #pragma warning( push )
31 #pragma warning( disable:4127 )
33 extern PNDIS_SPIN_LOCK gOvsCtrlLock;
34 extern POVS_SWITCH_CONTEXT gOvsSwitchContext;
35 extern UINT64 ovsTimeIncrementPerTick;
37 static NTSTATUS ReportFlowInfo(OvsFlow *flow, UINT32 getFlags,
38 UINT32 getActionsLen, OvsFlowInfo *info);
39 static NTSTATUS HandleFlowPut(OvsFlowPut *put,
40 OVS_DATAPATH *datapath,
41 struct OvsFlowStats *stats);
42 static NTSTATUS OvsPrepareFlow(OvsFlow **flow, const OvsFlowPut *put,
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,
55 OvsFlowPut *mappedFlow);
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 #define OVS_FLOW_TABLE_SIZE 2048
65 #define OVS_FLOW_TABLE_MASK (OVS_FLOW_TABLE_SIZE -1)
66 #define HASH_BUCKET(hash) ((hash) & OVS_FLOW_TABLE_MASK)
68 /* Flow family related netlink policies */
70 /* For Parsing attributes in FLOW_* commands */
71 static const NL_POLICY nlFlowPolicy[] = {
72 [OVS_FLOW_ATTR_KEY] = {.type = NL_A_NESTED, .optional = FALSE},
73 [OVS_FLOW_ATTR_MASK] = {.type = NL_A_NESTED, .optional = TRUE},
74 [OVS_FLOW_ATTR_ACTIONS] = {.type = NL_A_NESTED, .optional = TRUE},
75 [OVS_FLOW_ATTR_STATS] = {.type = NL_A_UNSPEC,
76 .minLen = sizeof(struct ovs_flow_stats),
77 .maxLen = sizeof(struct ovs_flow_stats),
79 [OVS_FLOW_ATTR_TCP_FLAGS] = {NL_A_U8, .optional = TRUE},
80 [OVS_FLOW_ATTR_USED] = {NL_A_U64, .optional = TRUE}
83 /* For Parsing nested OVS_FLOW_ATTR_KEY attributes.
84 * Some of the attributes like OVS_KEY_ATTR_RECIRC_ID
85 * & OVS_KEY_ATTR_MPLS are not supported yet. */
87 static const NL_POLICY nlFlowKeyPolicy[] = {
88 [OVS_KEY_ATTR_ENCAP] = {.type = NL_A_VAR_LEN, .optional = TRUE},
89 [OVS_KEY_ATTR_PRIORITY] = {.type = NL_A_UNSPEC, .minLen = 4,
90 .maxLen = 4, .optional = TRUE},
91 [OVS_KEY_ATTR_IN_PORT] = {.type = NL_A_UNSPEC, .minLen = 4,
92 .maxLen = 4, .optional = FALSE},
93 [OVS_KEY_ATTR_ETHERNET] = {.type = NL_A_UNSPEC,
94 .minLen = sizeof(struct ovs_key_ethernet),
95 .maxLen = sizeof(struct ovs_key_ethernet),
97 [OVS_KEY_ATTR_VLAN] = {.type = NL_A_UNSPEC, .minLen = 2,
98 .maxLen = 2, .optional = TRUE},
99 [OVS_KEY_ATTR_ETHERTYPE] = {.type = NL_A_UNSPEC, .minLen = 2,
100 .maxLen = 2, .optional = TRUE},
101 [OVS_KEY_ATTR_IPV4] = {.type = NL_A_UNSPEC,
102 .minLen = sizeof(struct ovs_key_ipv4),
103 .maxLen = sizeof(struct ovs_key_ipv4),
105 [OVS_KEY_ATTR_IPV6] = {.type = NL_A_UNSPEC,
106 .minLen = sizeof(struct ovs_key_ipv6),
107 .maxLen = sizeof(struct ovs_key_ipv6),
109 [OVS_KEY_ATTR_TCP] = {.type = NL_A_UNSPEC,
110 .minLen = sizeof(struct ovs_key_tcp),
111 .maxLen = sizeof(struct ovs_key_tcp),
113 [OVS_KEY_ATTR_UDP] = {.type = NL_A_UNSPEC,
114 .minLen = sizeof(struct ovs_key_udp),
115 .maxLen = sizeof(struct ovs_key_udp),
117 [OVS_KEY_ATTR_ICMP] = {.type = NL_A_UNSPEC,
118 .minLen = sizeof(struct ovs_key_icmp),
119 .maxLen = sizeof(struct ovs_key_icmp),
121 [OVS_KEY_ATTR_ICMPV6] = {.type = NL_A_UNSPEC,
122 .minLen = sizeof(struct ovs_key_icmpv6),
123 .maxLen = sizeof(struct ovs_key_icmpv6),
125 [OVS_KEY_ATTR_ARP] = {.type = NL_A_UNSPEC,
126 .minLen = sizeof(struct ovs_key_arp),
127 .maxLen = sizeof(struct ovs_key_arp),
129 [OVS_KEY_ATTR_ND] = {.type = NL_A_UNSPEC,
130 .minLen = sizeof(struct ovs_key_nd),
131 .maxLen = sizeof(struct ovs_key_nd),
133 [OVS_KEY_ATTR_SKB_MARK] = {.type = NL_A_UNSPEC, .minLen = 4,
134 .maxLen = 4, .optional = TRUE},
135 [OVS_KEY_ATTR_TUNNEL] = {.type = NL_A_VAR_LEN, .optional = TRUE},
136 [OVS_KEY_ATTR_SCTP] = {.type = NL_A_UNSPEC,
137 .minLen = sizeof(struct ovs_key_sctp),
138 .maxLen = sizeof(struct ovs_key_sctp),
140 [OVS_KEY_ATTR_TCP_FLAGS] = {.type = NL_A_UNSPEC,
141 .minLen = 2, .maxLen = 2,
143 [OVS_KEY_ATTR_DP_HASH] = {.type = NL_A_UNSPEC, .minLen = 4,
144 .maxLen = 4, .optional = TRUE},
145 [OVS_KEY_ATTR_RECIRC_ID] = {.type = NL_A_UNSPEC, .minLen = 4,
146 .maxLen = 4, .optional = TRUE},
147 [OVS_KEY_ATTR_MPLS] = {.type = NL_A_VAR_LEN, .optional = TRUE}
150 /* For Parsing nested OVS_KEY_ATTR_TUNNEL attributes */
151 static const NL_POLICY nlFlowTunnelKeyPolicy[] = {
152 [OVS_TUNNEL_KEY_ATTR_ID] = {.type = NL_A_UNSPEC, .minLen = 8,
153 .maxLen = 8, .optional = TRUE},
154 [OVS_TUNNEL_KEY_ATTR_IPV4_SRC] = {.type = NL_A_UNSPEC, .minLen = 4,
155 .maxLen = 4, .optional = TRUE},
156 [OVS_TUNNEL_KEY_ATTR_IPV4_DST] = {.type = NL_A_UNSPEC, .minLen = 4 ,
157 .maxLen = 4, .optional = FALSE},
158 [OVS_TUNNEL_KEY_ATTR_TOS] = {.type = NL_A_UNSPEC, .minLen = 1,
159 .maxLen = 1, .optional = TRUE},
160 [OVS_TUNNEL_KEY_ATTR_TTL] = {.type = NL_A_UNSPEC, .minLen = 1,
161 .maxLen = 1, .optional = TRUE},
162 [OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT] = {.type = NL_A_UNSPEC, .minLen = 0,
163 .maxLen = 0, .optional = TRUE},
164 [OVS_TUNNEL_KEY_ATTR_CSUM] = {.type = NL_A_UNSPEC, .minLen = 0,
165 .maxLen = 0, .optional = TRUE},
166 [OVS_TUNNEL_KEY_ATTR_OAM] = {.type = NL_A_UNSPEC, .minLen = 0,
167 .maxLen = 0, .optional = TRUE},
168 [OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS] = {.type = NL_A_VAR_LEN,
172 /* For Parsing nested OVS_FLOW_ATTR_ACTIONS attributes */
173 static const NL_POLICY nlFlowActionPolicy[] = {
174 [OVS_ACTION_ATTR_OUTPUT] = {.type = NL_A_UNSPEC, .minLen = sizeof(UINT32),
175 .maxLen = sizeof(UINT32), .optional = TRUE},
176 [OVS_ACTION_ATTR_USERSPACE] = {.type = NL_A_VAR_LEN, .optional = TRUE},
177 [OVS_ACTION_ATTR_PUSH_VLAN] = {.type = NL_A_UNSPEC,
179 sizeof(struct ovs_action_push_vlan),
181 sizeof(struct ovs_action_push_vlan),
183 [OVS_ACTION_ATTR_POP_VLAN] = {.type = NL_A_UNSPEC, .optional = TRUE},
184 [OVS_ACTION_ATTR_PUSH_MPLS] = {.type = NL_A_UNSPEC,
186 sizeof(struct ovs_action_push_mpls),
188 sizeof(struct ovs_action_push_mpls),
190 [OVS_ACTION_ATTR_POP_MPLS] = {.type = NL_A_UNSPEC,
191 .minLen = sizeof(UINT16),
192 .maxLen = sizeof(UINT16),
194 [OVS_ACTION_ATTR_RECIRC] = {.type = NL_A_UNSPEC,
195 .minLen = sizeof(UINT32),
196 .maxLen = sizeof(UINT32),
198 [OVS_ACTION_ATTR_HASH] = {.type = NL_A_UNSPEC,
199 .minLen = sizeof(struct ovs_action_hash),
200 .maxLen = sizeof(struct ovs_action_hash),
202 [OVS_ACTION_ATTR_SET] = {.type = NL_A_VAR_LEN, .optional = TRUE},
203 [OVS_ACTION_ATTR_SAMPLE] = {.type = NL_A_VAR_LEN, .optional = TRUE}
207 *----------------------------------------------------------------------------
208 * Netlink interface for flow commands.
209 *----------------------------------------------------------------------------
213 *----------------------------------------------------------------------------
214 * OvsFlowNlNewCmdHandler --
215 * Handler for OVS_FLOW_CMD_NEW/SET/DEL command.
216 * It also handles FLUSH case (DEL w/o any key in input)
217 *----------------------------------------------------------------------------
220 OvsFlowNlNewCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
223 NTSTATUS rc = STATUS_SUCCESS;
224 POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;
225 POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer;
226 PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
227 PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
228 POVS_HDR ovsHdr = &(msgIn->ovsHdr);
229 PNL_ATTR nlAttrs[__OVS_FLOW_ATTR_MAX];
230 UINT32 attrOffset = NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN;
231 OvsFlowPut mappedFlow;
233 struct ovs_flow_stats replyStats;
237 RtlZeroMemory(&mappedFlow, sizeof(OvsFlowPut));
238 RtlZeroMemory(&stats, sizeof(stats));
239 RtlZeroMemory(&replyStats, sizeof(replyStats));
243 /* Get all the top level Flow attributes */
244 if ((NlAttrParse(nlMsgHdr, attrOffset, NlMsgAttrsLen(nlMsgHdr),
245 nlFlowPolicy, nlAttrs, ARRAY_SIZE(nlAttrs)))
247 OVS_LOG_ERROR("Attr Parsing failed for msg: %p",
249 rc = STATUS_UNSUCCESSFUL;
253 /* FLOW_DEL command w/o any key input is a flush case. */
254 if ((genlMsgHdr->cmd == OVS_FLOW_CMD_DEL) &&
255 (!(nlAttrs[OVS_FLOW_ATTR_KEY]))) {
256 rc = OvsFlushFlowIoctl(ovsHdr->dp_ifindex);
260 if ((_MapNlToFlowPut(msgIn, nlAttrs[OVS_FLOW_ATTR_KEY],
261 nlAttrs[OVS_FLOW_ATTR_ACTIONS], nlAttrs[OVS_FLOW_ATTR_CLEAR],
264 OVS_LOG_ERROR("Conversion to OvsFlowPut failed");
268 rc = OvsPutFlowIoctl(&mappedFlow, sizeof (struct OvsFlowPut),
270 if (rc != STATUS_SUCCESS) {
271 OVS_LOG_ERROR("OvsFlowPut failed.");
275 if (!(usrParamsCtx->outputBuffer)) {
276 /* No output buffer */
277 OVS_LOG_ERROR("outputBuffer NULL.");
281 replyStats.n_packets = stats.packetCount;
282 replyStats.n_bytes = stats.byteCount;
284 /* So far so good. Prepare the reply for userspace */
285 NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
286 usrParamsCtx->outputLength);
288 /* Prepare nl Msg headers */
289 rc = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,
290 nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
291 genlMsgHdr->cmd, OVS_FLOW_VERSION,
295 /* Append OVS_FLOW_ATTR_STATS attribute */
296 if (!NlMsgPutTailUnspec(&nlBuf, OVS_FLOW_ATTR_STATS,
297 (PCHAR)(&replyStats), sizeof(replyStats))) {
298 OVS_LOG_ERROR("Adding OVS_FLOW_ATTR_STATS attribute failed.");
299 rc = STATUS_UNSUCCESSFUL;
302 *replyLen = msgOut->nlMsg.nlmsgLen;
309 *----------------------------------------------------------------------------
311 * Maps input netlink message to OvsFlowPut.
312 *----------------------------------------------------------------------------
315 _MapNlToFlowPut(POVS_MESSAGE msgIn, PNL_ATTR keyAttr,
316 PNL_ATTR actionAttr, PNL_ATTR flowAttrClear,
317 OvsFlowPut *mappedFlow)
319 NTSTATUS rc = STATUS_SUCCESS;
320 PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
321 PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
322 POVS_HDR ovsHdr = &(msgIn->ovsHdr);
324 UINT32 keyAttrOffset = (UINT32)((PCHAR)keyAttr - (PCHAR)nlMsgHdr);
325 UINT32 tunnelKeyAttrOffset;
327 PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX] = {NULL};
328 PNL_ATTR tunnelAttrs[__OVS_TUNNEL_KEY_ATTR_MAX] = {NULL};
330 /* Get flow keys attributes */
331 if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset, NlAttrLen(keyAttr),
332 nlFlowKeyPolicy, keyAttrs, ARRAY_SIZE(keyAttrs)))
334 OVS_LOG_ERROR("Key Attr Parsing failed for msg: %p",
336 rc = STATUS_UNSUCCESSFUL;
340 if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
341 tunnelKeyAttrOffset = (UINT32)((PCHAR)
342 (keyAttrs[OVS_KEY_ATTR_TUNNEL])
345 OVS_LOG_ERROR("Parse Flow Tunnel Key Policy");
347 /* Get tunnel keys attributes */
348 if ((NlAttrParseNested(nlMsgHdr, tunnelKeyAttrOffset,
349 NlAttrLen(keyAttr), nlFlowTunnelKeyPolicy,
350 tunnelAttrs, ARRAY_SIZE(tunnelAttrs)))
352 OVS_LOG_ERROR("Tunnel key Attr Parsing failed for msg: %p",
354 rc = STATUS_UNSUCCESSFUL;
359 _MapKeyAttrToFlowPut(keyAttrs, tunnelAttrs,
364 mappedFlow->actionsLen = NlAttrGetSize(actionAttr);
365 mappedFlow->actions = NlAttrGet(actionAttr);
368 mappedFlow->dpNo = ovsHdr->dp_ifindex;
370 _MapNlToFlowPutFlags(genlMsgHdr, flowAttrClear,
378 *----------------------------------------------------------------------------
379 * _MapNlToFlowPutFlags --
380 * Maps netlink message to OvsFlowPut->flags.
381 *----------------------------------------------------------------------------
384 _MapNlToFlowPutFlags(PGENL_MSG_HDR genlMsgHdr,
385 PNL_ATTR flowAttrClear, OvsFlowPut *mappedFlow)
389 switch (genlMsgHdr->cmd) {
390 case OVS_FLOW_CMD_NEW:
391 flags |= OVSWIN_FLOW_PUT_CREATE;
393 case OVS_FLOW_CMD_DEL:
394 flags |= OVSWIN_FLOW_PUT_DELETE;
396 case OVS_FLOW_CMD_SET:
397 flags |= OVSWIN_FLOW_PUT_MODIFY;
404 flags |= OVSWIN_FLOW_PUT_CLEAR;
407 mappedFlow->flags = flags;
411 *----------------------------------------------------------------------------
412 * _MapKeyAttrToFlowPut --
413 * Converts FLOW_KEY attribute to OvsFlowPut->key.
414 *----------------------------------------------------------------------------
417 _MapKeyAttrToFlowPut(PNL_ATTR *keyAttrs,
418 PNL_ATTR *tunnelAttrs,
419 OvsFlowPut *mappedFlow)
421 const struct ovs_key_ethernet *eth_key;
422 OvsFlowKey *destKey = &(mappedFlow->key);
424 _MapTunAttrToFlowPut(keyAttrs, tunnelAttrs, destKey);
426 /* ===== L2 headers ===== */
427 destKey->l2.inPort = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_IN_PORT]);
428 eth_key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ETHERNET]);
429 RtlCopyMemory(destKey->l2.dlSrc, eth_key->eth_src, ETH_ADDR_LEN);
430 RtlCopyMemory(destKey->l2.dlDst, eth_key->eth_dst, ETH_ADDR_LEN);
432 destKey->l2.dlType = ntohs((NlAttrGetU16(keyAttrs
433 [OVS_KEY_ATTR_ETHERTYPE])));
435 if (keyAttrs[OVS_KEY_ATTR_VLAN]) {
436 destKey->l2.vlanTci = NlAttrGetU16(keyAttrs
437 [OVS_KEY_ATTR_VLAN]);
440 /* ==== L3 + L4. ==== */
441 destKey->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + OVS_L2_KEY_SIZE
442 - destKey->l2.offset;
444 switch (destKey->l2.dlType) {
445 case ETH_TYPE_IPV4: {
447 if (keyAttrs[OVS_KEY_ATTR_IPV4]) {
448 const struct ovs_key_ipv4 *ipv4Key;
450 ipv4Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_IPV4]);
451 IpKey *ipv4FlowPutKey = &(destKey->ipKey);
452 ipv4FlowPutKey->nwSrc = ipv4Key->ipv4_src;
453 ipv4FlowPutKey->nwDst = ipv4Key->ipv4_dst;
454 ipv4FlowPutKey->nwProto = ipv4Key->ipv4_proto;
455 ipv4FlowPutKey->nwTos = ipv4Key->ipv4_tos;
456 ipv4FlowPutKey->nwTtl = ipv4Key->ipv4_ttl;
457 ipv4FlowPutKey->nwFrag = ipv4Key->ipv4_frag;
459 if (keyAttrs[OVS_KEY_ATTR_TCP]) {
460 const struct ovs_key_tcp *tcpKey;
461 tcpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_TCP]);
462 ipv4FlowPutKey->l4.tpSrc = tcpKey->tcp_src;
463 ipv4FlowPutKey->l4.tpDst = tcpKey->tcp_dst;
466 if (keyAttrs[OVS_KEY_ATTR_UDP]) {
467 const struct ovs_key_udp *udpKey;
468 udpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_UDP]);
469 ipv4FlowPutKey->l4.tpSrc = udpKey->udp_src;
470 ipv4FlowPutKey->l4.tpDst = udpKey->udp_dst;
473 if (keyAttrs[OVS_KEY_ATTR_SCTP]) {
474 const struct ovs_key_sctp *sctpKey;
475 sctpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_SCTP]);
476 ipv4FlowPutKey->l4.tpSrc = sctpKey->sctp_src;
477 ipv4FlowPutKey->l4.tpDst = sctpKey->sctp_dst;
480 destKey->l2.keyLen += OVS_IP_KEY_SIZE;
484 case ETH_TYPE_IPV6: {
486 if (keyAttrs[OVS_KEY_ATTR_IPV6]) {
487 const struct ovs_key_ipv6 *ipv6Key;
489 ipv6Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_IPV6]);
490 Ipv6Key *ipv6FlowPutKey = &(destKey->ipv6Key);
492 RtlCopyMemory(&ipv6FlowPutKey->ipv6Src, ipv6Key->ipv6_src,
493 sizeof ipv6Key->ipv6_src);
494 RtlCopyMemory(&ipv6FlowPutKey->ipv6Dst, ipv6Key->ipv6_dst,
495 sizeof ipv6Key->ipv6_dst);
497 ipv6FlowPutKey->ipv6Label = ipv6Key->ipv6_label;
498 ipv6FlowPutKey->nwProto = ipv6Key->ipv6_proto;
499 ipv6FlowPutKey->nwTos = ipv6Key->ipv6_tclass;
500 ipv6FlowPutKey->nwTtl = ipv6Key->ipv6_hlimit;
501 ipv6FlowPutKey->nwFrag = ipv6Key->ipv6_frag;
503 if (keyAttrs[OVS_KEY_ATTR_TCP]) {
504 const struct ovs_key_tcp *tcpKey;
505 tcpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_TCP]);
506 ipv6FlowPutKey->l4.tpSrc = tcpKey->tcp_src;
507 ipv6FlowPutKey->l4.tpDst = tcpKey->tcp_dst;
510 if (keyAttrs[OVS_KEY_ATTR_UDP]) {
511 const struct ovs_key_udp *udpKey;
512 udpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_UDP]);
513 ipv6FlowPutKey->l4.tpSrc = udpKey->udp_src;
514 ipv6FlowPutKey->l4.tpDst = udpKey->udp_dst;
517 if (keyAttrs[OVS_KEY_ATTR_SCTP]) {
518 const struct ovs_key_sctp *sctpKey;
519 sctpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_SCTP]);
520 ipv6FlowPutKey->l4.tpSrc = sctpKey->sctp_src;
521 ipv6FlowPutKey->l4.tpDst = sctpKey->sctp_dst;
524 if (keyAttrs[OVS_KEY_ATTR_ICMPV6]) {
525 const struct ovs_key_icmpv6 *icmpv6Key;
527 Icmp6Key *icmp6FlowPutKey= &(destKey->icmp6Key);
529 icmpv6Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ICMPV6]);
531 icmp6FlowPutKey->l4.tpSrc = icmpv6Key->icmpv6_type;
532 icmp6FlowPutKey->l4.tpDst = icmpv6Key->icmpv6_code;
534 if (keyAttrs[OVS_KEY_ATTR_ND]) {
535 const struct ovs_key_nd *ndKey;
537 ndKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ND]);
538 RtlCopyMemory(&icmp6FlowPutKey->ndTarget,
539 ndKey->nd_target, sizeof (icmp6FlowPutKey->ndTarget));
540 RtlCopyMemory(icmp6FlowPutKey->arpSha,
541 ndKey->nd_sll, ETH_ADDR_LEN);
542 RtlCopyMemory(icmp6FlowPutKey->arpTha,
543 ndKey->nd_tll, ETH_ADDR_LEN);
546 destKey->l2.keyLen += OVS_ICMPV6_KEY_SIZE;
550 destKey->l2.keyLen += OVS_IPV6_KEY_SIZE;
553 ipv6FlowPutKey->pad = 0;
558 case ETH_TYPE_RARP: {
559 ArpKey *arpFlowPutKey = &destKey->arpKey;
560 const struct ovs_key_arp *arpKey;
562 arpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ARP]);
564 arpFlowPutKey->nwSrc = arpKey->arp_sip;
565 arpFlowPutKey->nwDst = arpKey->arp_tip;
567 RtlCopyMemory(arpFlowPutKey->arpSha, arpKey->arp_sha, ETH_ADDR_LEN);
568 RtlCopyMemory(arpFlowPutKey->arpTha, arpKey->arp_tha, ETH_ADDR_LEN);
569 arpFlowPutKey->nwProto = (UINT8)(arpKey->arp_op);
570 arpFlowPutKey->pad[0] = 0;
571 arpFlowPutKey->pad[1] = 0;
572 arpFlowPutKey->pad[2] = 0;
573 destKey->l2.keyLen += OVS_ARP_KEY_SIZE;
580 *----------------------------------------------------------------------------
581 * _MapTunAttrToFlowPut --
582 * Converts FLOW_TUNNEL_KEY attribute to OvsFlowKey->tunKey.
583 *----------------------------------------------------------------------------
586 _MapTunAttrToFlowPut(PNL_ATTR *keyAttrs,
590 if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
592 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_ID]) {
593 destKey->tunKey.tunnelId = NlAttrGetU64
594 (tunAttrs[OVS_TUNNEL_KEY_ATTR_ID]);
595 destKey->tunKey.flags |= OVS_TNL_F_KEY;
598 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_DST]) {
599 destKey->tunKey.dst = NlAttrGetU32
600 (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_DST]);
603 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_SRC]) {
604 destKey->tunKey.src = NlAttrGetU32
605 (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_SRC]);
608 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT]) {
609 destKey->tunKey.flags |= OVS_TNL_F_DONT_FRAGMENT;
612 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_CSUM]) {
613 destKey->tunKey.flags |= OVS_TNL_F_CSUM;
616 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_TOS]) {
617 destKey->tunKey.tos = NlAttrGetU8
618 (tunAttrs[OVS_TUNNEL_KEY_ATTR_TOS]);
621 if (tunAttrs[OVS_TUNNEL_KEY_ATTR_TTL]) {
622 destKey->tunKey.ttl = NlAttrGetU8
623 (tunAttrs[OVS_TUNNEL_KEY_ATTR_TTL]);
626 destKey->tunKey.pad = 0;
627 destKey->l2.offset = 0;
629 destKey->tunKey.attr[0] = 0;
630 destKey->tunKey.attr[1] = 0;
631 destKey->tunKey.attr[2] = 0;
632 destKey->l2.offset = sizeof destKey->tunKey;
637 *----------------------------------------------------------------------------
638 * OvsDeleteFlowTable --
640 * NDIS_STATUS_SUCCESS always.
641 *----------------------------------------------------------------------------
644 OvsDeleteFlowTable(OVS_DATAPATH *datapath)
646 if (datapath == NULL || datapath->flowTable == NULL) {
647 return NDIS_STATUS_SUCCESS;
650 DeleteAllFlows(datapath);
651 OvsFreeMemory(datapath->flowTable);
652 datapath->flowTable = NULL;
653 NdisFreeRWLock(datapath->lock);
655 return NDIS_STATUS_SUCCESS;
659 *----------------------------------------------------------------------------
660 * OvsAllocateFlowTable --
662 * NDIS_STATUS_SUCCESS on success.
663 * NDIS_STATUS_RESOURCES if memory couldn't be allocated
664 *----------------------------------------------------------------------------
667 OvsAllocateFlowTable(OVS_DATAPATH *datapath,
668 POVS_SWITCH_CONTEXT switchContext)
673 datapath->flowTable = OvsAllocateMemory(OVS_FLOW_TABLE_SIZE *
674 sizeof (LIST_ENTRY));
675 if (!datapath->flowTable) {
676 return NDIS_STATUS_RESOURCES;
678 for (i = 0; i < OVS_FLOW_TABLE_SIZE; i++) {
679 bucket = &(datapath->flowTable[i]);
680 InitializeListHead(bucket);
682 datapath->lock = NdisAllocateRWLock(switchContext->NdisFilterHandle);
684 return NDIS_STATUS_SUCCESS;
689 *----------------------------------------------------------------------------
691 * Get the virtual address of the frame.
694 * Virtual address of the frame.
695 *----------------------------------------------------------------------------
697 static __inline VOID *
698 GetStartAddrNBL(const NET_BUFFER_LIST *_pNB)
706 // Ethernet Header is a guaranteed safe access.
707 curMdl = (NET_BUFFER_LIST_FIRST_NB(_pNB))->CurrentMdl;
708 curBuffer = MmGetSystemAddressForMdlSafe(curMdl, LowPagePriority);
713 curHeader = (PEthHdr)
714 (curBuffer + (NET_BUFFER_LIST_FIRST_NB(_pNB))->CurrentMdlOffset);
716 return (VOID *) curHeader;
720 OvsFlowUsed(OvsFlow *flow,
721 const NET_BUFFER_LIST *packet,
722 const POVS_PACKET_HDR_INFO layers)
724 LARGE_INTEGER tickCount;
726 KeQueryTickCount(&tickCount);
727 flow->used = tickCount.QuadPart * ovsTimeIncrementPerTick;
729 flow->byteCount += OvsPacketLenNBL(packet);
730 flow->tcpFlags |= OvsGetTcpFlags(packet, &flow->key, layers);
735 DeleteAllFlows(OVS_DATAPATH *datapath)
740 for (i = 0; i < OVS_FLOW_TABLE_SIZE; i++) {
742 bucket = &(datapath->flowTable[i]);
743 while (!IsListEmpty(bucket)) {
745 next = bucket->Flink;
746 flow = CONTAINING_RECORD(next, OvsFlow, ListEntry);
747 RemoveFlow(datapath, &flow);
753 *----------------------------------------------------------------------------
754 * Initializes 'flow' members from 'packet', 'skb_priority', 'tun_id', and
757 * Initializes 'packet' header pointers as follows:
759 * - packet->l2 to the start of the Ethernet header.
761 * - packet->l3 to just past the Ethernet header, or just past the
762 * vlan_header if one is present, to the first byte of the payload of the
765 * - packet->l4 to just past the IPv4 header, if one is present and has a
766 * correct length, and otherwise NULL.
768 * - packet->l7 to just past the TCP or UDP or ICMP header, if one is
769 * present and has a correct length, and otherwise NULL.
771 * Returns NDIS_STATUS_SUCCESS normally. Fails only if packet data cannot be accessed
772 * (e.g. if Pkt_CopyBytesOut() returns an error).
773 *----------------------------------------------------------------------------
776 OvsExtractFlow(const NET_BUFFER_LIST *packet,
779 POVS_PACKET_HDR_INFO layers,
780 OvsIPv4TunnelKey *tunKey)
782 struct Eth_Header *eth;
789 ASSERT(tunKey->dst != 0);
790 RtlMoveMemory(&flow->tunKey, tunKey, sizeof flow->tunKey);
793 flow->tunKey.dst = 0;
794 flow->l2.offset = OVS_WIN_TUNNEL_KEY_SIZE;
797 flow->l2.inPort = inPort;
799 if ( OvsPacketLenNBL(packet) < ETH_HEADER_LEN_DIX) {
800 flow->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + 8 - flow->l2.offset;
801 return NDIS_STATUS_SUCCESS;
805 eth = (Eth_Header *)GetStartAddrNBL((NET_BUFFER_LIST *)packet);
806 memcpy(flow->l2.dlSrc, eth->src, ETH_ADDR_LENGTH);
807 memcpy(flow->l2.dlDst, eth->dst, ETH_ADDR_LENGTH);
812 vlanTagValue = NET_BUFFER_LIST_INFO(packet, Ieee8021QNetBufferListInfo);
814 PNDIS_NET_BUFFER_LIST_8021Q_INFO vlanTag =
815 (PNDIS_NET_BUFFER_LIST_8021Q_INFO)(PVOID *)&vlanTagValue;
816 flow->l2.vlanTci = htons(vlanTag->TagHeader.VlanId | OVSWIN_VLAN_CFI |
817 (vlanTag->TagHeader.UserPriority << 13));
819 if (eth->dix.typeNBO == ETH_TYPE_802_1PQ_NBO) {
820 Eth_802_1pq_Tag *tag= (Eth_802_1pq_Tag *)ð->dix.typeNBO;
821 flow->l2.vlanTci = ((UINT16)tag->priority << 13) |
823 ((UINT16)tag->vidHi << 8) | tag->vidLo;
824 offset = sizeof (Eth_802_1pq_Tag);
826 flow->l2.vlanTci = 0;
830 * Please note after this point, src mac and dst mac should
831 * not be accessed through eth
833 eth = (Eth_Header *)((UINT8 *)eth + offset);
839 * XXX assume that at least the first
840 * 12 bytes of received packets are mapped. This code has the stronger
841 * assumption that at least the first 22 bytes of 'packet' is mapped (if my
842 * arithmetic is right).
844 if (ETH_TYPENOT8023(eth->dix.typeNBO)) {
845 flow->l2.dlType = eth->dix.typeNBO;
846 layers->l3Offset = ETH_HEADER_LEN_DIX + offset;
847 } else if (OvsPacketLenNBL(packet) >= ETH_HEADER_LEN_802_3 &&
848 eth->e802_3.llc.dsap == 0xaa &&
849 eth->e802_3.llc.ssap == 0xaa &&
850 eth->e802_3.llc.control == ETH_LLC_CONTROL_UFRAME &&
851 eth->e802_3.snap.snapOrg[0] == 0x00 &&
852 eth->e802_3.snap.snapOrg[1] == 0x00 &&
853 eth->e802_3.snap.snapOrg[2] == 0x00) {
854 flow->l2.dlType = eth->e802_3.snap.snapType.typeNBO;
855 layers->l3Offset = ETH_HEADER_LEN_802_3 + offset;
857 flow->l2.dlType = htons(OVSWIN_DL_TYPE_NONE);
858 layers->l3Offset = ETH_HEADER_LEN_DIX + offset;
861 flow->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + OVS_L2_KEY_SIZE - flow->l2.offset;
863 if (flow->l2.dlType == htons(ETH_TYPE_IPV4)) {
864 struct IPHdr ip_storage;
865 const struct IPHdr *nh;
866 IpKey *ipKey = &flow->ipKey;
868 flow->l2.keyLen += OVS_IP_KEY_SIZE;
870 nh = OvsGetIp(packet, layers->l3Offset, &ip_storage);
872 layers->l4Offset = layers->l3Offset + nh->ihl * 4;
874 ipKey->nwSrc = nh->saddr;
875 ipKey->nwDst = nh->daddr;
876 ipKey->nwProto = nh->protocol;
878 ipKey->nwTos = nh->tos;
879 if (nh->frag_off & htons(IP_MF | IP_OFFSET)) {
880 ipKey->nwFrag = OVSWIN_NW_FRAG_ANY;
881 if (nh->frag_off & htons(IP_OFFSET)) {
882 ipKey->nwFrag |= OVSWIN_NW_FRAG_LATER;
888 ipKey->nwTtl = nh->ttl;
892 if (!(nh->frag_off & htons(IP_OFFSET))) {
893 if (ipKey->nwProto == SOCKET_IPPROTO_TCP) {
894 OvsParseTcp(packet, &ipKey->l4, layers);
895 } else if (ipKey->nwProto == SOCKET_IPPROTO_UDP) {
896 OvsParseUdp(packet, &ipKey->l4, layers);
897 } else if (ipKey->nwProto == SOCKET_IPPROTO_ICMP) {
901 icmp = OvsGetIcmp(packet, layers->l4Offset, &icmpStorage);
903 ipKey->l4.tpSrc = htons(icmp->type);
904 ipKey->l4.tpDst = htons(icmp->code);
905 layers->l7Offset = layers->l4Offset + sizeof *icmp;
910 ((UINT64 *)ipKey)[0] = 0;
911 ((UINT64 *)ipKey)[1] = 0;
913 } else if (flow->l2.dlType == htons(ETH_TYPE_IPV6)) {
915 flow->l2.keyLen += OVS_IPV6_KEY_SIZE;
916 status = OvsParseIPv6(packet, flow, layers);
917 if (status != NDIS_STATUS_SUCCESS) {
918 memset(&flow->ipv6Key, 0, sizeof (Ipv6Key));
922 flow->ipv6Key.l4.tpSrc = 0;
923 flow->ipv6Key.l4.tpDst = 0;
924 flow->ipv6Key.pad = 0;
926 if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_TCP) {
927 OvsParseTcp(packet, &(flow->ipv6Key.l4), layers);
928 } else if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_UDP) {
929 OvsParseUdp(packet, &(flow->ipv6Key.l4), layers);
930 } else if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_ICMPV6) {
931 OvsParseIcmpV6(packet, flow, layers);
932 flow->l2.keyLen += (OVS_ICMPV6_KEY_SIZE - OVS_IPV6_KEY_SIZE);
934 } else if (flow->l2.dlType == htons(ETH_TYPE_ARP)) {
937 ArpKey *arpKey = &flow->arpKey;
938 ((UINT64 *)arpKey)[0] = 0;
939 ((UINT64 *)arpKey)[1] = 0;
940 ((UINT64 *)arpKey)[2] = 0;
941 flow->l2.keyLen += OVS_ARP_KEY_SIZE;
942 arp = OvsGetArp(packet, layers->l3Offset, &arpStorage);
943 if (arp && arp->ea_hdr.ar_hrd == htons(1) &&
944 arp->ea_hdr.ar_pro == htons(ETH_TYPE_IPV4) &&
945 arp->ea_hdr.ar_hln == ETH_ADDR_LENGTH &&
946 arp->ea_hdr.ar_pln == 4) {
947 /* We only match on the lower 8 bits of the opcode. */
948 if (ntohs(arp->ea_hdr.ar_op) <= 0xff) {
949 arpKey->nwProto = (UINT8)ntohs(arp->ea_hdr.ar_op);
951 if (arpKey->nwProto == ARPOP_REQUEST
952 || arpKey->nwProto == ARPOP_REPLY) {
953 memcpy(&arpKey->nwSrc, arp->arp_spa, 4);
954 memcpy(&arpKey->nwDst, arp->arp_tpa, 4);
955 memcpy(arpKey->arpSha, arp->arp_sha, ETH_ADDR_LENGTH);
956 memcpy(arpKey->arpTha, arp->arp_tha, ETH_ADDR_LENGTH);
961 return NDIS_STATUS_SUCCESS;
965 FlowEqual(UINT64 *src, UINT64 *dst, UINT32 size)
968 ASSERT((size & 0x7) == 0);
969 ASSERT(((UINT64)src & 0x7) == 0);
970 ASSERT(((UINT64)dst & 0x7) == 0);
971 for (i = 0; i < (size >> 3); i++) {
972 if (src[i] != dst[i]) {
981 * ----------------------------------------------------------------------------
983 * Add a flow to flow table.
986 * NDIS_STATUS_SUCCESS if no same flow in the flow table.
987 * ----------------------------------------------------------------------------
990 AddFlow(OVS_DATAPATH *datapath, OvsFlow *flow)
994 if (OvsLookupFlow(datapath, &flow->key, &flow->hash, TRUE) != NULL) {
995 return STATUS_INVALID_HANDLE;
998 head = &(datapath->flowTable[HASH_BUCKET(flow->hash)]);
1000 * We need fence here to make sure flow's nextPtr is updated before
1001 * head->nextPtr is updated.
1005 //KeAcquireSpinLock(&FilterDeviceExtension->NblQueueLock, &oldIrql);
1006 InsertTailList(head, &flow->ListEntry);
1007 //KeReleaseSpinLock(&FilterDeviceExtension->NblQueueLock, oldIrql);
1011 return STATUS_SUCCESS;
1015 /* ----------------------------------------------------------------------------
1017 * Remove a flow from flow table, and added to wait list
1018 * ----------------------------------------------------------------------------
1021 RemoveFlow(OVS_DATAPATH *datapath,
1026 UNREFERENCED_PARAMETER(datapath);
1028 ASSERT(datapath->nFlows);
1030 // Remove the flow from queue
1031 RemoveEntryList(&f->ListEntry);
1037 * ----------------------------------------------------------------------------
1040 * Find flow from flow table based on flow key.
1041 * Caller should either hold portset handle or should
1042 * have a flowRef in datapath or Acquired datapath.
1045 * Flow pointer if lookup successful.
1046 * NULL if not exists.
1047 * ----------------------------------------------------------------------------
1050 OvsLookupFlow(OVS_DATAPATH *datapath,
1051 const OvsFlowKey *key,
1055 PLIST_ENTRY link, head;
1056 UINT16 offset = key->l2.offset;
1057 UINT16 size = key->l2.keyLen;
1060 ASSERT(key->tunKey.dst || offset == sizeof (OvsIPv4TunnelKey));
1061 ASSERT(!key->tunKey.dst || offset == 0);
1063 start = (UINT8 *)key + offset;
1066 *hash = OvsJhashBytes(start, size, 0);
1069 head = &datapath->flowTable[HASH_BUCKET(*hash)];
1071 while (link != head) {
1072 OvsFlow *flow = CONTAINING_RECORD(link, OvsFlow, ListEntry);
1074 if (flow->hash == *hash &&
1075 flow->key.l2.val == key->l2.val &&
1076 FlowEqual((UINT64 *)((uint8 *)&flow->key + offset),
1077 (UINT64 *)start, size)) {
1087 * ----------------------------------------------------------------------------
1089 * Calculate the hash for the given flow key.
1090 * ----------------------------------------------------------------------------
1093 OvsHashFlow(const OvsFlowKey *key)
1095 UINT16 offset = key->l2.offset;
1096 UINT16 size = key->l2.keyLen;
1099 ASSERT(key->tunKey.dst || offset == sizeof (OvsIPv4TunnelKey));
1100 ASSERT(!key->tunKey.dst || offset == 0);
1101 start = (UINT8 *)key + offset;
1102 return OvsJhashBytes(start, size, 0);
1107 * ----------------------------------------------------------------------------
1109 * Free a flow and its actions.
1110 * ----------------------------------------------------------------------------
1113 FreeFlow(OvsFlow *flow)
1116 OvsFreeMemory(flow);
1120 OvsDoDumpFlows(OvsFlowDumpInput *dumpInput,
1121 OvsFlowDumpOutput *dumpOutput,
1125 OVS_DATAPATH *datapath = NULL;
1127 PLIST_ENTRY node, head;
1129 UINT32 rowIndex, columnIndex;
1130 LOCK_STATE_EX dpLockState;
1131 NTSTATUS status = STATUS_SUCCESS;
1132 BOOLEAN findNextNonEmpty = FALSE;
1134 dpNo = dumpInput->dpNo;
1135 NdisAcquireSpinLock(gOvsCtrlLock);
1136 if (gOvsSwitchContext == NULL ||
1137 gOvsSwitchContext->dpNo != dpNo) {
1138 status = STATUS_INVALID_PARAMETER;
1142 rowIndex = dumpInput->position[0];
1143 if (rowIndex >= OVS_FLOW_TABLE_SIZE) {
1145 *replyLen = sizeof(*dumpOutput);
1149 columnIndex = dumpInput->position[1];
1151 datapath = &gOvsSwitchContext->datapath;
1153 OvsAcquireDatapathRead(datapath, &dpLockState, FALSE);
1155 head = &datapath->flowTable[rowIndex];
1158 while (column < columnIndex) {
1167 findNextNonEmpty = TRUE;
1171 if (findNextNonEmpty) {
1172 while (head == node) {
1173 if (++rowIndex >= OVS_FLOW_TABLE_SIZE) {
1177 head = &datapath->flowTable[rowIndex];
1182 ASSERT(node != head);
1183 ASSERT(rowIndex < OVS_FLOW_TABLE_SIZE);
1185 flow = CONTAINING_RECORD(node, OvsFlow, ListEntry);
1186 status = ReportFlowInfo(flow, dumpInput->getFlags, dumpInput->actionsLen,
1189 if (status == STATUS_BUFFER_TOO_SMALL) {
1190 dumpOutput->n = sizeof(OvsFlowDumpOutput) + flow->actionsLen;
1191 *replyLen = sizeof(*dumpOutput);
1193 dumpOutput->n = 1; //one flow reported.
1194 *replyLen = sizeof(*dumpOutput) + dumpOutput->flow.actionsLen;
1197 dumpOutput->position[0] = rowIndex;
1198 dumpOutput->position[1] = ++columnIndex;
1201 OvsReleaseDatapath(datapath, &dpLockState);
1204 NdisReleaseSpinLock(gOvsCtrlLock);
1209 OvsDumpFlowIoctl(PVOID inputBuffer,
1212 UINT32 outputLength,
1215 OvsFlowDumpOutput *dumpOutput = (OvsFlowDumpOutput *)outputBuffer;
1216 OvsFlowDumpInput *dumpInput = (OvsFlowDumpInput *)inputBuffer;
1218 if (inputBuffer == NULL || outputBuffer == NULL) {
1219 return STATUS_INVALID_PARAMETER;
1222 if ((inputLength != sizeof(OvsFlowDumpInput))
1223 || (outputLength != sizeof *dumpOutput + dumpInput->actionsLen)) {
1224 return STATUS_INFO_LENGTH_MISMATCH;
1227 return OvsDoDumpFlows(dumpInput, dumpOutput, replyLen);
1231 ReportFlowInfo(OvsFlow *flow,
1233 UINT32 getActionsLen,
1236 NTSTATUS status = STATUS_SUCCESS;
1238 if (getFlags & FLOW_GET_KEY) {
1239 // always copy the tunnel key part
1240 RtlCopyMemory(&info->key, &flow->key,
1241 flow->key.l2.keyLen + flow->key.l2.offset);
1244 if (getFlags & FLOW_GET_STATS) {
1245 OvsFlowStats *stats = &info->stats;
1246 stats->packetCount = flow->packetCount;
1247 stats->byteCount = flow->byteCount;
1248 stats->used = (UINT32)flow->used;
1249 stats->tcpFlags = flow->tcpFlags;
1252 if (getFlags & FLOW_GET_ACTIONS) {
1253 if (flow->actionsLen == 0) {
1254 info->actionsLen = 0;
1255 } else if (flow->actionsLen > getActionsLen) {
1256 info->actionsLen = 0;
1257 status = STATUS_BUFFER_TOO_SMALL;
1259 RtlCopyMemory(info->actions, flow->actions, flow->actionsLen);
1260 info->actionsLen = flow->actionsLen;
1268 OvsPutFlowIoctl(PVOID inputBuffer,
1270 struct OvsFlowStats *stats)
1272 NTSTATUS status = STATUS_SUCCESS;
1273 OVS_DATAPATH *datapath = NULL;
1277 LOCK_STATE_EX dpLockState;
1279 if ((inputLength < sizeof(OvsFlowPut)) || (inputBuffer == NULL)) {
1280 return STATUS_INFO_LENGTH_MISMATCH;
1283 put = (OvsFlowPut *)inputBuffer;
1284 if (put->actionsLen > 0) {
1285 actionsLen = put->actionsLen;
1291 NdisAcquireSpinLock(gOvsCtrlLock);
1292 if (gOvsSwitchContext == NULL ||
1293 gOvsSwitchContext->dpNo != dpNo) {
1294 status = STATUS_INVALID_PARAMETER;
1298 datapath = &gOvsSwitchContext->datapath;
1300 OvsAcquireDatapathWrite(datapath, &dpLockState, FALSE);
1301 status = HandleFlowPut(put, datapath, stats);
1302 OvsReleaseDatapath(datapath, &dpLockState);
1305 NdisReleaseSpinLock(gOvsCtrlLock);
1310 /* Handles flow add, modify as well as delete */
1312 HandleFlowPut(OvsFlowPut *put,
1313 OVS_DATAPATH *datapath,
1314 struct OvsFlowStats *stats)
1316 BOOLEAN mayCreate, mayModify, mayDelete;
1317 OvsFlow *KernelFlow;
1319 NTSTATUS status = STATUS_SUCCESS;
1321 mayCreate = (put->flags & OVSWIN_FLOW_PUT_CREATE) != 0;
1322 mayModify = (put->flags & OVSWIN_FLOW_PUT_MODIFY) != 0;
1323 mayDelete = (put->flags & OVSWIN_FLOW_PUT_DELETE) != 0;
1325 if ((mayCreate || mayModify) == mayDelete) {
1326 return STATUS_INVALID_PARAMETER;
1329 KernelFlow = OvsLookupFlow(datapath, &put->key, &hash, FALSE);
1332 return STATUS_INVALID_PARAMETER;
1335 status = OvsPrepareFlow(&KernelFlow, put, hash);
1336 if (status != STATUS_SUCCESS) {
1337 FreeFlow(KernelFlow);
1338 return STATUS_UNSUCCESSFUL;
1341 status = AddFlow(datapath, KernelFlow);
1342 if (status != STATUS_SUCCESS) {
1343 FreeFlow(KernelFlow);
1344 return STATUS_UNSUCCESSFUL;
1347 /* Validate the flow addition */
1350 OvsFlow *flow = OvsLookupFlow(datapath, &put->key, &newHash,
1353 ASSERT(newHash == hash);
1354 if (!flow || newHash != hash) {
1355 return STATUS_UNSUCCESSFUL;
1359 stats->packetCount = KernelFlow->packetCount;
1360 stats->byteCount = KernelFlow->byteCount;
1361 stats->tcpFlags = KernelFlow->tcpFlags;
1362 stats->used = (UINT32)KernelFlow->used;
1366 status = OvsPrepareFlow(&newFlow, put, hash);
1367 if (status != STATUS_SUCCESS) {
1368 return STATUS_UNSUCCESSFUL;
1371 KernelFlow = OvsLookupFlow(datapath, &put->key, &hash, TRUE);
1373 if ((put->flags & OVSWIN_FLOW_PUT_CLEAR) == 0) {
1374 newFlow->packetCount = KernelFlow->packetCount;
1375 newFlow->byteCount = KernelFlow->byteCount;
1376 newFlow->tcpFlags = KernelFlow->tcpFlags;
1378 RemoveFlow(datapath, &KernelFlow);
1380 if ((put->flags & OVSWIN_FLOW_PUT_CLEAR) == 0) {
1381 newFlow->packetCount = stats->packetCount;
1382 newFlow->byteCount = stats->byteCount;
1383 newFlow->tcpFlags = stats->tcpFlags;
1386 status = AddFlow(datapath, newFlow);
1387 ASSERT(status == STATUS_SUCCESS);
1389 /* Validate the flow addition */
1392 OvsFlow *testflow = OvsLookupFlow(datapath, &put->key,
1395 ASSERT(newHash == hash);
1396 if (!testflow || newHash != hash) {
1398 return STATUS_UNSUCCESSFUL;
1404 RemoveFlow(datapath, &KernelFlow);
1407 return STATUS_UNSUCCESSFUL;
1411 return STATUS_SUCCESS;
1415 OvsPrepareFlow(OvsFlow **flow,
1416 const OvsFlowPut *put,
1419 OvsFlow *localFlow = *flow;
1420 NTSTATUS status = STATUS_SUCCESS;
1424 OvsAllocateMemory(sizeof(OvsFlow) + put->actionsLen);
1425 if (localFlow == NULL) {
1426 status = STATUS_NO_MEMORY;
1430 localFlow->key = put->key;
1431 localFlow->actionsLen = put->actionsLen;
1432 if (put->actionsLen) {
1433 NdisMoveMemory((PUCHAR)localFlow->actions, put->actions,
1436 localFlow->userActionsLen = 0; // 0 indicate no conversion is made
1437 localFlow->used = 0;
1438 localFlow->packetCount = 0;
1439 localFlow->byteCount = 0;
1440 localFlow->tcpFlags = 0;
1441 localFlow->hash = hash;
1448 OvsGetFlowIoctl(PVOID inputBuffer,
1451 UINT32 outputLength,
1454 NTSTATUS status = STATUS_SUCCESS;
1455 OVS_DATAPATH *datapath = NULL;
1457 UINT32 getFlags, getActionsLen;
1458 OvsFlowGetInput *getInput;
1459 OvsFlowGetOutput *getOutput;
1462 LOCK_STATE_EX dpLockState;
1464 if (inputLength != sizeof(OvsFlowGetInput)
1465 || inputBuffer == NULL) {
1466 return STATUS_INFO_LENGTH_MISMATCH;
1469 getInput = (OvsFlowGetInput *) inputBuffer;
1470 getFlags = getInput->getFlags;
1471 getActionsLen = getInput->actionsLen;
1472 if (getInput->getFlags & FLOW_GET_KEY) {
1473 return STATUS_INVALID_PARAMETER;
1476 if (outputBuffer == NULL
1477 || outputLength != (sizeof *getOutput +
1478 getInput->actionsLen)) {
1479 return STATUS_INFO_LENGTH_MISMATCH;
1482 dpNo = getInput->dpNo;
1483 NdisAcquireSpinLock(gOvsCtrlLock);
1484 if (gOvsSwitchContext == NULL ||
1485 gOvsSwitchContext->dpNo != dpNo) {
1486 status = STATUS_INVALID_PARAMETER;
1490 datapath = &gOvsSwitchContext->datapath;
1492 OvsAcquireDatapathRead(datapath, &dpLockState, FALSE);
1493 flow = OvsLookupFlow(datapath, &getInput->key, &hash, FALSE);
1495 status = STATUS_INVALID_PARAMETER;
1499 // XXX: can be optimized to return only how much is written out
1500 *replyLen = outputLength;
1501 getOutput = (OvsFlowGetOutput *)outputBuffer;
1502 ReportFlowInfo(flow, getFlags, getActionsLen, &getOutput->info);
1505 OvsReleaseDatapath(datapath, &dpLockState);
1507 NdisReleaseSpinLock(gOvsCtrlLock);
1512 OvsFlushFlowIoctl(UINT32 dpNo)
1514 NTSTATUS status = STATUS_SUCCESS;
1515 OVS_DATAPATH *datapath = NULL;
1516 LOCK_STATE_EX dpLockState;
1518 NdisAcquireSpinLock(gOvsCtrlLock);
1519 if (gOvsSwitchContext == NULL ||
1520 gOvsSwitchContext->dpNo != dpNo) {
1521 status = STATUS_INVALID_PARAMETER;
1525 datapath = &gOvsSwitchContext->datapath;
1527 OvsAcquireDatapathWrite(datapath, &dpLockState, FALSE);
1528 DeleteAllFlows(datapath);
1529 OvsReleaseDatapath(datapath, &dpLockState);
1532 NdisReleaseSpinLock(gOvsCtrlLock);
1536 #pragma warning( pop )