Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/1.2/patches/2233255/?format=api
{ "id": 2233255, "url": "http://patchwork.ozlabs.org/api/1.2/patches/2233255/?format=api", "web_url": "http://patchwork.ozlabs.org/project/openvswitch/patch/20260505225239.2401918-5-i.maximets@ovn.org/", "project": { "id": 47, "url": "http://patchwork.ozlabs.org/api/1.2/projects/47/?format=api", "name": "Open vSwitch", "link_name": "openvswitch", "list_id": "ovs-dev.openvswitch.org", "list_email": "ovs-dev@openvswitch.org", "web_url": "http://openvswitch.org/", "scm_url": "git@github.com:openvswitch/ovs.git", "webscm_url": "https://github.com/openvswitch/ovs", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20260505225239.2401918-5-i.maximets@ovn.org>", "list_archive_url": null, "date": "2026-05-05T22:52:13", "name": "[ovs-dev,4/5] datapath-windows: Remove.", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "2e2ef6c62f585be7bdd40b0c0f0ed83b74d989cf", "submitter": { "id": 76798, "url": "http://patchwork.ozlabs.org/api/1.2/people/76798/?format=api", "name": "Ilya Maximets", "email": "i.maximets@ovn.org" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/openvswitch/patch/20260505225239.2401918-5-i.maximets@ovn.org/mbox/", "series": [ { "id": 502908, "url": "http://patchwork.ozlabs.org/api/1.2/series/502908/?format=api", "web_url": "http://patchwork.ozlabs.org/project/openvswitch/list/?series=502908", "date": "2026-05-05T22:52:10", "name": "Remove Windows support.", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/502908/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2233255/comments/", "check": "success", "checks": "http://patchwork.ozlabs.org/api/patches/2233255/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<ovs-dev-bounces@openvswitch.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "ovs-dev@openvswitch.org" ], "Delivered-To": [ "patchwork-incoming@legolas.ozlabs.org", "ovs-dev@lists.linuxfoundation.org" ], "Authentication-Results": [ "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org\n (client-ip=2605:bc80:3010::136; helo=smtp3.osuosl.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org)", "smtp2.osuosl.org;\n dmarc=none (p=none dis=none) header.from=ovn.org" ], "Received": [ "from smtp3.osuosl.org (smtp3.osuosl.org [IPv6:2605:bc80:3010::136])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g9DMn0gHnz1yJV\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 06 May 2026 08:53:57 +1000 (AEST)", "from localhost (localhost [127.0.0.1])\n\tby smtp3.osuosl.org (Postfix) with ESMTP id 9F87060C0D;\n\tTue, 5 May 2026 22:53:55 +0000 (UTC)", "from smtp3.osuosl.org ([127.0.0.1])\n by localhost (smtp3.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id THf0JkMjBtWB; Tue, 5 May 2026 22:53:45 +0000 (UTC)", "from lists.linuxfoundation.org (lf-lists.osuosl.org\n [IPv6:2605:bc80:3010:104::8cd3:938])\n\tby smtp3.osuosl.org (Postfix) with ESMTPS id 1560460BF0;\n\tTue, 5 May 2026 22:53:45 +0000 (UTC)", "from lf-lists.osuosl.org (localhost [127.0.0.1])\n\tby lists.linuxfoundation.org (Postfix) with ESMTP id D5B41C04EB;\n\tTue, 5 May 2026 22:53:44 +0000 (UTC)", "from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133])\n by lists.linuxfoundation.org (Postfix) with ESMTP id 1975CC04E7\n for <ovs-dev@openvswitch.org>; Tue, 5 May 2026 22:53:43 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n by smtp2.osuosl.org (Postfix) with ESMTP id BD5E4404A7\n for <ovs-dev@openvswitch.org>; Tue, 5 May 2026 22:53:20 +0000 (UTC)", "from smtp2.osuosl.org ([127.0.0.1])\n by localhost (smtp2.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id LOQdJxTxwfGP for <ovs-dev@openvswitch.org>;\n Tue, 5 May 2026 22:53:15 +0000 (UTC)", "from mail-wr1-f67.google.com (mail-wr1-f67.google.com\n [209.85.221.67])\n by smtp2.osuosl.org (Postfix) with ESMTPS id BAC21404D6\n for <ovs-dev@openvswitch.org>; Tue, 5 May 2026 22:53:13 +0000 (UTC)", "by mail-wr1-f67.google.com with SMTP id\n ffacd0b85a97d-44c350a5b87so1846944f8f.3\n for <ovs-dev@openvswitch.org>; Tue, 05 May 2026 15:53:13 -0700 (PDT)", "from im-t490s (37-48-40-237.nat.epc.tmcz.cz. [37.48.40.237])\n by smtp.gmail.com with ESMTPSA id\n ffacd0b85a97d-45055960811sm8060136f8f.27.2026.05.05.15.53.08\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Tue, 05 May 2026 15:53:09 -0700 (PDT)" ], "X-Virus-Scanned": [ "amavis at osuosl.org", "amavis at osuosl.org" ], "X-Comment": "SPF check N/A for local connections -\n client-ip=2605:bc80:3010:104::8cd3:938; helo=lists.linuxfoundation.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=<UNKNOWN> ", "DKIM-Filter": [ "OpenDKIM Filter v2.11.0 smtp3.osuosl.org 1560460BF0", "OpenDKIM Filter v2.11.0 smtp2.osuosl.org BAC21404D6" ], "Received-SPF": "Pass (mailfrom) identity=mailfrom; client-ip=209.85.221.67;\n helo=mail-wr1-f67.google.com; envelope-from=i.maximets.ovn@gmail.com;\n receiver=<UNKNOWN>", "DMARC-Filter": "OpenDMARC Filter v1.4.2 smtp2.osuosl.org BAC21404D6", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1778021592; x=1778626392;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from\n :to:cc:subject:date:message-id:reply-to;\n bh=pQRLNntI7SLWECv3Cd/fABliYzyFXEgboiv7kSemanw=;\n b=hc/W18M3rCj5Xy5tQ6gxvOJwVEwzTUOn/MBqMbpAYltl9LKH/zbBfeXVQQzqeJtuaH\n c5IGMoGIKz89vUeUuzg8a/m/zppqtpYzdGp+eutXtXX/HT3TUemdMTMErJZ3RbOFHDch\n uXSr9IFQNKQynAmxd65umn6VoQj3SlUCN1rZ24TAeFxqdWle0FZ1r2Tf+TV55cbb69ZZ\n r/m54p/TJFwpFSWkWwaoI50wJ2Y5sD3rf7jD9RvhEngYGO7h5T8l4DfCBf5Ze91CxLFt\n xeQmzzTq/MPsjPHwejKuNW6mgfsJwuQbTSEdIV0AmX7l/5BCqxPYtFuNYftkvfrAAw0f\n 7KEg==", "X-Gm-Message-State": "AOJu0YzdRG3jPw1LkWqhegOeSF0z2sr2jSyjCPgHvwXlBQZPROsB3oUw\n XgGUNv6qJoW/iP9zE+uuXw2XAw1n01VRMGR5TdUN8rS7kSi1oQnY0N3DaZe+pH+v", "X-Gm-Gg": "AeBDietMkkjquzxah6+ahDJhFf3IghjvZkq7rdo8ICgKllzllsjgXAKX/W7ozdqbsLb\n fiDoMvKt4cY7DLealzuayJ5/BxhwGBLa1ze1iUjKE5qz2Bogl+6s2UESNx6nkYEkpeKsePZpPNB\n 1a7SxFvV7YNtizb24+cWULfoohoD4QnCRFJYnbMDEZJPK7zHnIIjQ5T0gc9ppfsYd+56M/a5qti\n pyg3l5lWnxWcHO2iV2z+kDlqNln5pjN1UZiDr7+riuxpz0ZDUGSNkj7oUUwI57crRFoJaLukGQK\n 9718yzP04K2iQeq9JR69Nj0o2dy+NjYoUxdk5khzN3spowVmXB3oVpRaP+zAjDyBsIzWSbOsM6o\n gDZa3qB3HpLLqbLPrh6PxjFB7TpLaeLOwm2qrAh6tQ5aXCtsASGB3DKZpXavUuJlENRdwiAa5aa\n i5eAhPrXTpvjBEfUPX4uosK2nsnBEZN0pPUvIGUhROqV1T33qhxUyjgYI=", "X-Received": "by 2002:a05:6000:26c9:b0:44b:cb31:b767 with SMTP id\n ffacd0b85a97d-4515d2e6d77mr1563466f8f.36.1778021590622;\n Tue, 05 May 2026 15:53:10 -0700 (PDT)", "From": "Ilya Maximets <i.maximets@ovn.org>", "To": "ovs-dev@openvswitch.org", "Cc": "Ilya Maximets <i.maximets@ovn.org>", "Date": "Wed, 6 May 2026 00:52:13 +0200", "Message-ID": "<20260505225239.2401918-5-i.maximets@ovn.org>", "X-Mailer": "git-send-email 2.53.0", "In-Reply-To": "<20260505225239.2401918-1-i.maximets@ovn.org>", "References": "<20260505225239.2401918-1-i.maximets@ovn.org>", "MIME-Version": "1.0", "Subject": "[ovs-dev] [PATCH 4/5] datapath-windows: Remove.", "X-BeenThere": "ovs-dev@openvswitch.org", "X-Mailman-Version": "2.1.30", "Precedence": "list", "List-Id": "<ovs-dev.openvswitch.org>", "List-Unsubscribe": "<https://mail.openvswitch.org/mailman/options/ovs-dev>,\n <mailto:ovs-dev-request@openvswitch.org?subject=unsubscribe>", "List-Archive": "<http://mail.openvswitch.org/pipermail/ovs-dev/>", "List-Post": "<mailto:ovs-dev@openvswitch.org>", "List-Help": "<mailto:ovs-dev-request@openvswitch.org?subject=help>", "List-Subscribe": "<https://mail.openvswitch.org/mailman/listinfo/ovs-dev>,\n <mailto:ovs-dev-request@openvswitch.org?subject=subscribe>", "Content-Type": "text/plain; charset=\"utf-8\"", "Content-Transfer-Encoding": "base64", "Errors-To": "ovs-dev-bounces@openvswitch.org", "Sender": "\"dev\" <ovs-dev-bounces@openvswitch.org>" }, "content": "Windows support was deprecated in 3.7, it's time to remove it.\nThe next bit is the actual datapath implementation.\n\nAlso removing mentions of the Windows kernel support from the\nreleases documentation and vswitch man pages.\n\nSigned-off-by: Ilya Maximets <i.maximets@ovn.org>\n---\n Documentation/faq/releases.rst | 104 +-\n Makefile.am | 38 +-\n NEWS | 3 +\n configure.ac | 1 -\n datapath-windows/.gitignore | 9 -\n datapath-windows/Package/package.VcxProj | 234 --\n datapath-windows/Package/package.VcxProj.user | 30 -\n datapath-windows/automake.mk | 98 -\n .../include/OvsDpInterfaceCtExt.h | 538 ---\n datapath-windows/include/OvsDpInterfaceExt.h | 183 -\n datapath-windows/include/automake.mk | 10 -\n .../misc/DriverRecommendedRules.ruleset | 86 -\n datapath-windows/misc/OVS.psm1 | 210 -\n datapath-windows/misc/install.cmd | 4 -\n datapath-windows/misc/uninstall.cmd | 1 -\n datapath-windows/ovsext.sln | 82 -\n datapath-windows/ovsext/Actions.c | 2690 -------------\n datapath-windows/ovsext/Actions.h | 141 -\n datapath-windows/ovsext/Atomic.h | 32 -\n datapath-windows/ovsext/BufferMgmt.c | 2244 -----------\n datapath-windows/ovsext/BufferMgmt.h | 151 -\n datapath-windows/ovsext/Conntrack-ftp.c | 365 --\n datapath-windows/ovsext/Conntrack-icmp.c | 105 -\n datapath-windows/ovsext/Conntrack-nat.c | 523 ---\n datapath-windows/ovsext/Conntrack-nat.h | 39 -\n datapath-windows/ovsext/Conntrack-other.c | 81 -\n datapath-windows/ovsext/Conntrack-related.c | 361 --\n datapath-windows/ovsext/Conntrack-tcp.c | 632 ---\n datapath-windows/ovsext/Conntrack.c | 2351 ------------\n datapath-windows/ovsext/Conntrack.h | 233 --\n datapath-windows/ovsext/Datapath.c | 1927 ----------\n datapath-windows/ovsext/Datapath.h | 133 -\n datapath-windows/ovsext/Debug.c | 59 -\n datapath-windows/ovsext/Debug.h | 76 -\n datapath-windows/ovsext/DpInternal.h | 371 --\n datapath-windows/ovsext/Driver.c | 204 -\n datapath-windows/ovsext/Ethernet.h | 452 ---\n datapath-windows/ovsext/Event.c | 626 ---\n datapath-windows/ovsext/Event.h | 67 -\n datapath-windows/ovsext/Flow.c | 3388 -----------------\n datapath-windows/ovsext/Flow.h | 105 -\n datapath-windows/ovsext/Geneve.c | 440 ---\n datapath-windows/ovsext/Geneve.h | 146 -\n datapath-windows/ovsext/Gre.c | 456 ---\n datapath-windows/ovsext/Gre.h | 122 -\n datapath-windows/ovsext/Ip6Fragment.c | 808 ----\n datapath-windows/ovsext/Ip6Fragment.h | 111 -\n datapath-windows/ovsext/IpFragment.c | 526 ---\n datapath-windows/ovsext/IpFragment.h | 75 -\n datapath-windows/ovsext/IpHelper.c | 2257 -----------\n datapath-windows/ovsext/IpHelper.h | 234 --\n datapath-windows/ovsext/Jhash.c | 131 -\n datapath-windows/ovsext/Jhash.h | 30 -\n datapath-windows/ovsext/Meter.c | 540 ---\n datapath-windows/ovsext/Meter.h | 68 -\n datapath-windows/ovsext/Mpls.h | 80 -\n datapath-windows/ovsext/NetProto.h | 439 ---\n datapath-windows/ovsext/Netlink/Netlink.c | 1236 ------\n datapath-windows/ovsext/Netlink/Netlink.h | 243 --\n datapath-windows/ovsext/Netlink/NetlinkBuf.c | 351 --\n datapath-windows/ovsext/Netlink/NetlinkBuf.h | 69 -\n .../ovsext/Netlink/NetlinkError.h | 241 --\n .../ovsext/Netlink/NetlinkProto.h | 135 -\n datapath-windows/ovsext/Offload.c | 780 ----\n datapath-windows/ovsext/Offload.h | 53 -\n datapath-windows/ovsext/Oid.c | 882 -----\n datapath-windows/ovsext/Oid.h | 29 -\n datapath-windows/ovsext/PacketIO.c | 586 ---\n datapath-windows/ovsext/PacketIO.h | 51 -\n datapath-windows/ovsext/PacketParser.c | 332 --\n datapath-windows/ovsext/PacketParser.h | 170 -\n datapath-windows/ovsext/Recirc.c | 344 --\n datapath-windows/ovsext/Recirc.h | 107 -\n datapath-windows/ovsext/Switch.c | 649 ----\n datapath-windows/ovsext/Switch.h | 233 --\n datapath-windows/ovsext/Tunnel.c | 338 --\n datapath-windows/ovsext/Tunnel.h | 51 -\n datapath-windows/ovsext/TunnelFilter.c | 1656 --------\n datapath-windows/ovsext/TunnelIntf.h | 44 -\n datapath-windows/ovsext/Types.h | 53 -\n datapath-windows/ovsext/User.c | 1310 -------\n datapath-windows/ovsext/User.h | 130 -\n datapath-windows/ovsext/Util.c | 182 -\n datapath-windows/ovsext/Util.h | 210 -\n datapath-windows/ovsext/Vport.c | 2830 --------------\n datapath-windows/ovsext/Vport.h | 275 --\n datapath-windows/ovsext/Vxlan.c | 577 ---\n datapath-windows/ovsext/Vxlan.h | 97 -\n datapath-windows/ovsext/ovsext.inf | 84 -\n datapath-windows/ovsext/ovsext.rc | 89 -\n datapath-windows/ovsext/ovsext.vcxproj | 457 ---\n datapath-windows/ovsext/ovsext.vcxproj.user | 30 -\n datapath-windows/ovsext/precomp.h | 34 -\n datapath-windows/ovsext/precompsrc.c | 17 -\n datapath-windows/ovsext/resource.h | 1576 --------\n debian/copyright.in | 1 -\n m4/openvswitch.m4 | 51 -\n vswitchd/vswitch.xml | 45 +-\n 98 files changed, 79 insertions(+), 41999 deletions(-)\n delete mode 100644 datapath-windows/.gitignore\n delete mode 100644 datapath-windows/Package/package.VcxProj\n delete mode 100644 datapath-windows/Package/package.VcxProj.user\n delete mode 100644 datapath-windows/automake.mk\n delete mode 100644 datapath-windows/include/OvsDpInterfaceCtExt.h\n delete mode 100644 datapath-windows/include/OvsDpInterfaceExt.h\n delete mode 100644 datapath-windows/include/automake.mk\n delete mode 100644 datapath-windows/misc/DriverRecommendedRules.ruleset\n delete mode 100644 datapath-windows/misc/OVS.psm1\n delete mode 100644 datapath-windows/misc/install.cmd\n delete mode 100644 datapath-windows/misc/uninstall.cmd\n delete mode 100644 datapath-windows/ovsext.sln\n delete mode 100644 datapath-windows/ovsext/Actions.c\n delete mode 100644 datapath-windows/ovsext/Actions.h\n delete mode 100644 datapath-windows/ovsext/Atomic.h\n delete mode 100644 datapath-windows/ovsext/BufferMgmt.c\n delete mode 100644 datapath-windows/ovsext/BufferMgmt.h\n delete mode 100644 datapath-windows/ovsext/Conntrack-ftp.c\n delete mode 100644 datapath-windows/ovsext/Conntrack-icmp.c\n delete mode 100644 datapath-windows/ovsext/Conntrack-nat.c\n delete mode 100644 datapath-windows/ovsext/Conntrack-nat.h\n delete mode 100644 datapath-windows/ovsext/Conntrack-other.c\n delete mode 100644 datapath-windows/ovsext/Conntrack-related.c\n delete mode 100644 datapath-windows/ovsext/Conntrack-tcp.c\n delete mode 100644 datapath-windows/ovsext/Conntrack.c\n delete mode 100644 datapath-windows/ovsext/Conntrack.h\n delete mode 100644 datapath-windows/ovsext/Datapath.c\n delete mode 100644 datapath-windows/ovsext/Datapath.h\n delete mode 100644 datapath-windows/ovsext/Debug.c\n delete mode 100644 datapath-windows/ovsext/Debug.h\n delete mode 100644 datapath-windows/ovsext/DpInternal.h\n delete mode 100644 datapath-windows/ovsext/Driver.c\n delete mode 100644 datapath-windows/ovsext/Ethernet.h\n delete mode 100644 datapath-windows/ovsext/Event.c\n delete mode 100644 datapath-windows/ovsext/Event.h\n delete mode 100644 datapath-windows/ovsext/Flow.c\n delete mode 100644 datapath-windows/ovsext/Flow.h\n delete mode 100644 datapath-windows/ovsext/Geneve.c\n delete mode 100644 datapath-windows/ovsext/Geneve.h\n delete mode 100644 datapath-windows/ovsext/Gre.c\n delete mode 100644 datapath-windows/ovsext/Gre.h\n delete mode 100644 datapath-windows/ovsext/Ip6Fragment.c\n delete mode 100644 datapath-windows/ovsext/Ip6Fragment.h\n delete mode 100644 datapath-windows/ovsext/IpFragment.c\n delete mode 100644 datapath-windows/ovsext/IpFragment.h\n delete mode 100644 datapath-windows/ovsext/IpHelper.c\n delete mode 100644 datapath-windows/ovsext/IpHelper.h\n delete mode 100644 datapath-windows/ovsext/Jhash.c\n delete mode 100644 datapath-windows/ovsext/Jhash.h\n delete mode 100644 datapath-windows/ovsext/Meter.c\n delete mode 100644 datapath-windows/ovsext/Meter.h\n delete mode 100644 datapath-windows/ovsext/Mpls.h\n delete mode 100644 datapath-windows/ovsext/NetProto.h\n delete mode 100644 datapath-windows/ovsext/Netlink/Netlink.c\n delete mode 100644 datapath-windows/ovsext/Netlink/Netlink.h\n delete mode 100644 datapath-windows/ovsext/Netlink/NetlinkBuf.c\n delete mode 100644 datapath-windows/ovsext/Netlink/NetlinkBuf.h\n delete mode 100644 datapath-windows/ovsext/Netlink/NetlinkError.h\n delete mode 100644 datapath-windows/ovsext/Netlink/NetlinkProto.h\n delete mode 100644 datapath-windows/ovsext/Offload.c\n delete mode 100644 datapath-windows/ovsext/Offload.h\n delete mode 100644 datapath-windows/ovsext/Oid.c\n delete mode 100644 datapath-windows/ovsext/Oid.h\n delete mode 100644 datapath-windows/ovsext/PacketIO.c\n delete mode 100644 datapath-windows/ovsext/PacketIO.h\n delete mode 100644 datapath-windows/ovsext/PacketParser.c\n delete mode 100644 datapath-windows/ovsext/PacketParser.h\n delete mode 100644 datapath-windows/ovsext/Recirc.c\n delete mode 100644 datapath-windows/ovsext/Recirc.h\n delete mode 100644 datapath-windows/ovsext/Switch.c\n delete mode 100644 datapath-windows/ovsext/Switch.h\n delete mode 100644 datapath-windows/ovsext/Tunnel.c\n delete mode 100644 datapath-windows/ovsext/Tunnel.h\n delete mode 100644 datapath-windows/ovsext/TunnelFilter.c\n delete mode 100644 datapath-windows/ovsext/TunnelIntf.h\n delete mode 100644 datapath-windows/ovsext/Types.h\n delete mode 100644 datapath-windows/ovsext/User.c\n delete mode 100644 datapath-windows/ovsext/User.h\n delete mode 100644 datapath-windows/ovsext/Util.c\n delete mode 100644 datapath-windows/ovsext/Util.h\n delete mode 100644 datapath-windows/ovsext/Vport.c\n delete mode 100644 datapath-windows/ovsext/Vport.h\n delete mode 100644 datapath-windows/ovsext/Vxlan.c\n delete mode 100644 datapath-windows/ovsext/Vxlan.h\n delete mode 100644 datapath-windows/ovsext/ovsext.inf\n delete mode 100644 datapath-windows/ovsext/ovsext.rc\n delete mode 100644 datapath-windows/ovsext/ovsext.vcxproj\n delete mode 100644 datapath-windows/ovsext/ovsext.vcxproj.user\n delete mode 100644 datapath-windows/ovsext/precomp.h\n delete mode 100644 datapath-windows/ovsext/precompsrc.c\n delete mode 100644 datapath-windows/ovsext/resource.h", "diff": "diff --git a/Documentation/faq/releases.rst b/Documentation/faq/releases.rst\nindex 1db42ad5c..e7227820f 100644\n--- a/Documentation/faq/releases.rst\n+++ b/Documentation/faq/releases.rst\n@@ -47,6 +47,12 @@ Q: What Linux kernel versions does each Open vSwitch release work with?\n source code was completely removed from the Open vSwitch source tree in\n 3.0 release.\n \n+Q: Does Open vSwitch support running on Windows (Hyper-V)?\n+\n+ A: Support for the Windows datapath, a.k.a. Hyper-V, was deprecated starting\n+ with Open vSwitch 3.7 and the source code was completely removed from the\n+ Open vSwitch source tree in the next release.\n+\n Q: Are all features available with all datapaths?\n \n A: Open vSwitch supports different datapaths on different platforms. Each\n@@ -66,9 +72,6 @@ Q: Are all features available with all datapaths?\n DPDK and AF_XDP devices when support for those is built. This\n is the only datapath that works on NetBSD, FreeBSD and Mac OSX.\n \n- Hyper-V\n- Also known as the Windows datapath.\n-\n The following table lists the datapath supported features from an\n Open vSwitch user's perspective. The \"Linux upstream\" column\n lists the Linux kernel version that introduced a given feature\n@@ -77,45 +80,42 @@ Q: Are all features available with all datapaths?\n given feature into the included kernel module or the userspace\n datapath, respectively.\n \n- ========================== ============== ========= =======\n- Feature Linux upstream Userspace Hyper-V\n- ========================== ============== ========= =======\n- Connection tracking 4.3 2.6 YES\n- Connection tracking-IPv6 YES YES 3.0\n- Conntrack Fragment Reass. 4.3 2.12 YES\n- Conntrack IPv6 Fragment 4.3 2.12 3.1\n- Conntrack Timeout Policies 5.2 2.14 NO\n- Conntrack Zone Limit 4.18 2.13 YES\n- Conntrack NAT 4.6 2.8 YES\n- Conntrack NAT6 4.6 2.8 3.0\n- Conntrack Helper Persist. YES 3.3 NO\n- Tunnel - GRE 3.11 2.4 YES\n- Tunnel - VXLAN 3.12 2.4 YES\n- Tunnel - Geneve 3.18 2.4 YES\n- Tunnel - GRE-IPv6 4.18 2.6 NO\n- Tunnel - VXLAN-IPv6 4.3 2.6 NO\n- Tunnel - Geneve-IPv6 4.4 2.6 3.0\n- Tunnel - ERSPAN 4.18 2.10 NO\n- Tunnel - ERSPAN-IPv6 4.18 2.10 NO\n- Tunnel - GTP-U NO 2.14 NO\n- Tunnel - SRv6 NO 3.2 NO\n- Tunnel - Bareudp 5.7 NO NO\n- QoS - Policing YES 2.6 NO\n- QoS - Shaping YES NO NO\n- sFlow YES 1.0 NO\n- IPFIX 3.10 1.11 YES\n- Set action YES 1.0 PARTIAL\n- NIC Bonding YES 1.0 YES\n- Multiple VTEPs YES 1.10 YES\n- Meter action 4.15 2.7 NO\n- check_pkt_len action 5.2 2.12 NO\n- ========================== ============== ========= =======\n+ ========================== ============== =========\n+ Feature Linux upstream Userspace\n+ ========================== ============== =========\n+ Connection tracking 4.3 2.6\n+ Connection tracking-IPv6 YES YES\n+ Conntrack Fragment Reass. 4.3 2.12\n+ Conntrack IPv6 Fragment 4.3 2.12\n+ Conntrack Timeout Policies 5.2 2.14\n+ Conntrack Zone Limit 4.18 2.13\n+ Conntrack NAT 4.6 2.8\n+ Conntrack NAT6 4.6 2.8\n+ Conntrack Helper Persist. YES 3.3\n+ Tunnel - GRE 3.11 2.4\n+ Tunnel - VXLAN 3.12 2.4\n+ Tunnel - Geneve 3.18 2.4\n+ Tunnel - GRE-IPv6 4.18 2.6\n+ Tunnel - VXLAN-IPv6 4.3 2.6\n+ Tunnel - Geneve-IPv6 4.4 2.6\n+ Tunnel - ERSPAN 4.18 2.10\n+ Tunnel - ERSPAN-IPv6 4.18 2.10\n+ Tunnel - GTP-U NO 2.14\n+ Tunnel - SRv6 NO 3.2\n+ Tunnel - Bareudp 5.7 NO\n+ QoS - Policing YES 2.6\n+ QoS - Shaping YES NO\n+ sFlow YES 1.0\n+ IPFIX 3.10 1.11\n+ Set action YES 1.0\n+ NIC Bonding YES 1.0\n+ Multiple VTEPs YES 1.10\n+ Meter action 4.15 2.7\n+ check_pkt_len action 5.2 2.12\n+ ========================== ============== =========\n \n Do note, however:\n \n- * Only a limited set of flow fields is modifiable via the set action by the\n- Hyper-V datapath.\n-\n * Userspace datapath support, in some cases, is dependent on the associated\n interface types. For example, DPDK interfaces support ingress and egress\n policing, but not shaping.\n@@ -124,19 +124,19 @@ Q: Are all features available with all datapaths?\n vSwitch user, e.g. because their absence can be hidden by the ofproto layer\n (usually this comes with a performance penalty).\n \n- ===================== ============== ============== ========= =======\n- Feature Linux upstream Linux OVS tree Userspace Hyper-V\n- ===================== ============== ============== ========= =======\n- SCTP flows 3.12 YES YES YES\n- MPLS 3.19 YES YES YES\n- UFID 4.0 YES YES NO\n- Megaflows 3.12 YES YES NO\n- Masked set action 4.0 YES YES NO\n- Recirculation 3.19 YES YES YES\n- TCP flags matching 3.13 YES YES NO\n- Validate flow actions YES YES N/A NO\n- Multiple datapaths YES YES YES NO\n- ===================== ============== ============== ========= =======\n+ ===================== ============== ============== =========\n+ Feature Linux upstream Linux OVS tree Userspace\n+ ===================== ============== ============== =========\n+ SCTP flows 3.12 YES YES\n+ MPLS 3.19 YES YES\n+ UFID 4.0 YES YES\n+ Megaflows 3.12 YES YES\n+ Masked set action 4.0 YES YES\n+ Recirculation 3.19 YES YES\n+ TCP flags matching 3.13 YES YES\n+ Validate flow actions YES YES N/A\n+ Multiple datapaths YES YES YES\n+ ===================== ============== ============== =========\n \n Q: What DPDK version does each Open vSwitch release work with?\n \ndiff --git a/Makefile.am b/Makefile.am\nindex 13ffc9e28..43cffbd72 100644\n--- a/Makefile.am\n+++ b/Makefile.am\n@@ -16,7 +16,6 @@ AM_LDFLAGS += $(OVS_LDFLAGS)\n \n if WIN32\n AM_CPPFLAGS += -I $(top_srcdir)/include/windows\n-AM_CPPFLAGS += -I $(top_srcdir)/datapath-windows/include\n AM_CPPFLAGS += $(PTHREAD_INCLUDES)\n AM_CPPFLAGS += $(MSVC_CFLAGS)\n AM_LDFLAGS += $(PTHREAD_LDFLAGS)\n@@ -232,7 +231,7 @@ config-h-check:\n \t@cd $(srcdir); \\\n \tif test -e .git && (git --version) >/dev/null 2>&1 && \\\n \t git --no-pager grep -L '#include <config\\.h>' `git ls-files | grep '\\.c$$' | \\\n-\t grep -vE '^datapath-windows|^lib/sflow|^python|^third-party'`; \\\n+\t grep -vE '^lib/sflow|^python|^third-party'`; \\\n \tthen \\\n \t echo \"See above for list of violations of the rule that\"; \\\n \t echo \"every C source file must #include <config.h>.\"; \\\n@@ -253,7 +252,7 @@ printf-check:\n \t@cd $(srcdir); \\\n \tif test -e .git && (git --version) >/dev/null 2>&1 && \\\n \t git --no-pager grep -n -E -e '%[-+ #0-9.*]*([ztj]|hh)' --and --not -e 'ovs_scan' `git ls-files | grep '\\.[ch]$$' | \\\n-\t grep -vE '^datapath-windows|^lib/sflow|^third-party'`; \\\n+\t grep -vE '^lib/sflow|^third-party'`; \\\n \tthen \\\n \t echo \"See above for list of violations of the rule that\"; \\\n \t echo \"'z', 't', 'j', 'hh' printf() type modifiers are\"; \\\n@@ -338,7 +337,7 @@ thread-safety-check:\n \tif test -e .git && (git --version) >/dev/null 2>&1 && \\\n \t grep -n -f build-aux/thread-safety-forbidden \\\n \t `git ls-files | grep '\\.[ch]$$' \\\n-\t | $(EGREP) -v '^datapath-windows|^lib/sflow|^third-party'` /dev/null \\\n+\t | $(EGREP) -v '^lib/sflow|^third-party'` /dev/null \\\n \t | $(EGREP) -v ':[ \t]*/?\\*' \\\n \t | $(EGREP) -v '^tests/test-lib-route-table.c'; \\\n \tthen \\\n@@ -421,35 +420,6 @@ manpages.mk: $(MAN_ROOTS) build-aux/sodepends.py python/ovs_build_helpers/soutil\n CLEANFILES += manpages.mk\n CLEANFILES += manpage-dep-check\n \n-if VSTUDIO_DDK\n-ALL_LOCAL += ovsext\n-ARCH = x64\n-ovsext: datapath-windows/ovsext.sln $(srcdir)/datapath-windows/include/OvsDpInterface.h\n-if VSTUDIO_WIN8\n-\tMSBuild.exe //nologo //maxcpucount datapath-windows/ovsext.sln /target:Build /property:Configuration=\"Win8$(VSTUDIO_CONFIG)\" /property:Version=\"$(PACKAGE_VERSION)\" //p:Platform=$(ARCH)\n-endif\n-if VSTUDIO_WIN8_1\n-\tMSBuild.exe //nologo //maxcpucount datapath-windows/ovsext.sln /target:Build /property:Configuration=\"Win8.1$(VSTUDIO_CONFIG)\" /property:Version=\"$(PACKAGE_VERSION)\" //p:Platform=$(ARCH)\n-endif\n-if VSTUDIO_WIN10\n-\tMSBuild.exe //nologo //maxcpucount datapath-windows/ovsext.sln /target:Build /property:Configuration=\"Win10$(VSTUDIO_CONFIG)\" /property:Version=\"$(PACKAGE_VERSION)\" //p:Platform=$(ARCH)\n-endif\n-\n-\n-CLEAN_LOCAL += ovsext_clean\n-ovsext_clean: datapath-windows/ovsext.sln\n-if VSTUDIO_WIN8\n-\tMSBuild.exe //nologo //maxcpucount datapath-windows/ovsext.sln /target:Clean /property:Configuration=\"Win8$(VSTUDIO_CONFIG)\" /property:Version=\"$(PACKAGE_VERSION)\" //p:Platform=$(ARCH)\n-endif\n-if VSTUDIO_WIN8_1\n-\tMSBuild.exe //nologo //maxcpucount datapath-windows/ovsext.sln /target:Clean /property:Configuration=\"Win8.1$(VSTUDIO_CONFIG)\" /property:Version=\"$(PACKAGE_VERSION)\" //p:Platform=$(ARCH)\n-endif\n-if VSTUDIO_WIN10\n-\tMSBuild.exe //nologo //maxcpucount datapath-windows/ovsext.sln /target:Clean /property:Configuration=\"Win10$(VSTUDIO_CONFIG)\" /property:Version=\"$(PACKAGE_VERSION)\" //p:Platform=$(ARCH)\n-endif\n-endif\n-.PHONY: ovsext\n-\n clang-analyze: clean\n \t@which clang scan-build >/dev/null 2>&1 || \\\n \t (echo \"Unable to find clang/scan-build, Install clang,clang-analyzer packages\"; exit 1)\n@@ -484,7 +454,5 @@ include rhel/automake.mk\n include python/automake.mk\n include tutorial/automake.mk\n include vtep/automake.mk\n-include datapath-windows/automake.mk\n-include datapath-windows/include/automake.mk\n include selinux/automake.mk\n include build-aux/automake.mk\ndiff --git a/NEWS b/NEWS\nindex 1a3044cbf..260f0a561 100644\n--- a/NEWS\n+++ b/NEWS\n@@ -3,6 +3,9 @@ Post-v3.7.0\n - Userspace datapath:\n * ARP/ND lookups for native tunnel are now rate limited. The holdout\n timer can be configured with 'tnl/neigh/retrans_time'.\n+ - Windows:\n+ * The previously deprecated Windows kernel datapath implementation is\n+ now fully removed.\n \n \n v3.7.0 - 16 Feb 2026\ndiff --git a/configure.ac b/configure.ac\nindex 56eacbbc7..1da99d8d5 100644\n--- a/configure.ac\n+++ b/configure.ac\n@@ -89,7 +89,6 @@ AC_FUNC_STRERROR_R\n \n OVS_CHECK_WIN64\n OVS_CHECK_WIN32\n-OVS_CHECK_VISUAL_STUDIO_DDK\n OVS_CHECK_COVERAGE\n OVS_CHECK_NDEBUG\n OVS_CHECK_USDT\ndiff --git a/datapath-windows/.gitignore b/datapath-windows/.gitignore\ndeleted file mode 100644\nindex 8e8f0c7e9..000000000\n--- a/datapath-windows/.gitignore\n+++ /dev/null\n@@ -1,9 +0,0 @@\n-/.vs\n-/Package/x64/\n-*.db\n-*.opendb\n-*.opensdf\n-*.sdf\n-/ovsext/x64/\n-/x64\n-/ovsext/ovsext.aps\ndiff --git a/datapath-windows/Package/package.VcxProj b/datapath-windows/Package/package.VcxProj\ndeleted file mode 100644\nindex 994c34dc2..000000000\n--- a/datapath-windows/Package/package.VcxProj\n+++ /dev/null\n@@ -1,234 +0,0 @@\n-<?xml version=\"1.0\" encoding=\"utf-8\"?>\n-<Project DefaultTargets=\"Build\" ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n- <ItemGroup Label=\"ProjectConfigurations\">\n- <ProjectConfiguration Include=\"Win10 Debug|x64\">\n- <Configuration>Win10 Debug</Configuration>\n- <Platform>x64</Platform>\n- </ProjectConfiguration>\n- <ProjectConfiguration Include=\"Win10 Release|x64\">\n- <Configuration>Win10 Release</Configuration>\n- <Platform>x64</Platform>\n- </ProjectConfiguration>\n- <ProjectConfiguration Include=\"Win10Analyze|x64\">\n- <Configuration>Win10Analyze</Configuration>\n- <Platform>x64</Platform>\n- </ProjectConfiguration>\n- <ProjectConfiguration Include=\"Win8.1 Debug|x64\">\n- <Configuration>Win8.1 Debug</Configuration>\n- <Platform>x64</Platform>\n- </ProjectConfiguration>\n- <ProjectConfiguration Include=\"Win8 Debug|x64\">\n- <Configuration>Win8 Debug</Configuration>\n- <Platform>x64</Platform>\n- </ProjectConfiguration>\n- <ProjectConfiguration Include=\"Win8.1 Release|x64\">\n- <Configuration>Win8.1 Release</Configuration>\n- <Platform>x64</Platform>\n- </ProjectConfiguration>\n- <ProjectConfiguration Include=\"Win8 Release|x64\">\n- <Configuration>Win8 Release</Configuration>\n- <Platform>x64</Platform>\n- </ProjectConfiguration>\n- <ProjectConfiguration Include=\"Win8.1Analyze|x64\">\n- <Configuration>Win8.1Analyze</Configuration>\n- <Platform>x64</Platform>\n- </ProjectConfiguration>\n- <ProjectConfiguration Include=\"Win8Analyze|x64\">\n- <Configuration>Win8Analyze</Configuration>\n- <Platform>x64</Platform>\n- </ProjectConfiguration>\n- </ItemGroup>\n- <PropertyGroup Label=\"PropertySheets\">\n- <ConfigurationType>Utility</ConfigurationType>\n- <DriverType>Package</DriverType>\n- <DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>\n- <Configuration>Win8 Debug</Configuration>\n- </PropertyGroup>\n- <PropertyGroup Label=\"Globals\">\n- <VCTargetsPath Condition=\"'$(VCTargetsPath11)' != '' and '$(VisualStudioVersion)' == '11.0'\">$(VCTargetsPath11)</VCTargetsPath>\n- <PlatformToolsetVer Condition=\"$(WindowsSdkDir.EndsWith('\\Windows Kits\\10\\'))\">10.0</PlatformToolsetVer>\n- <PlatformToolsetVer Condition=\"$(WindowsSdkDir.EndsWith('\\Windows Kits\\8.1\\'))\">8.1</PlatformToolsetVer>\n- </PropertyGroup>\n- <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n- <PropertyGroup Label=\"Globals\">\n- <ProjectGuid>{911D7389-3E61-449F-B8F3-14AD7EE9A0F2}</ProjectGuid>\n- <SampleGuid>{E753AF15-94DC-4773-AED9-06A6636E6E67}</SampleGuid>\n- <RootNamespace>$(MSBuildProjectName)</RootNamespace>\n- </PropertyGroup>\n- <PropertyGroup Label=\"Configuration\" Condition=\"'$(Configuration)|$(Platform)'=='Win8.1 Debug|x64'\">\n- <TargetVersion>WindowsV6.3</TargetVersion>\n- <UseDebugLibraries>true</UseDebugLibraries>\n- <PlatformToolsetVer Condition=\"'$(PlatformToolsetVer)' == ''\">8.1</PlatformToolsetVer>\n- <PlatformToolset>WindowsKernelModeDriver$(PlatformToolsetVer)</PlatformToolset>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8.1Analyze|x64'\" Label=\"Configuration\">\n- <TargetVersion>WindowsV6.3</TargetVersion>\n- <UseDebugLibraries>true</UseDebugLibraries>\n- <PlatformToolsetVer Condition=\"'$(PlatformToolsetVer)' == ''\">8.1</PlatformToolsetVer>\n- <PlatformToolset>WindowsKernelModeDriver$(PlatformToolsetVer)</PlatformToolset>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win10 Debug|x64'\" Label=\"Configuration\">\n- <TargetVersion>\n- </TargetVersion>\n- <UseDebugLibraries>true</UseDebugLibraries>\n- <PlatformToolsetVer Condition=\"'$(PlatformToolsetVer)' == ''\">10.0</PlatformToolsetVer>\n- <PlatformToolset>WindowsKernelModeDriver$(PlatformToolsetVer)</PlatformToolset>\n- <DriverTargetPlatform>Desktop</DriverTargetPlatform>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win10Analyze|x64'\" Label=\"Configuration\">\n- <TargetVersion />\n- <UseDebugLibraries>true</UseDebugLibraries>\n- <PlatformToolsetVer Condition=\"'$(PlatformToolsetVer)' == ''\">10.0</PlatformToolsetVer>\n- <PlatformToolset>WindowsKernelModeDriver$(PlatformToolsetVer)</PlatformToolset>\n- <DriverTargetPlatform>Desktop</DriverTargetPlatform>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8 Debug|x64'\" Label=\"Configuration\">\n- <TargetVersion>Windows8</TargetVersion>\n- <UseDebugLibraries>true</UseDebugLibraries>\n- <PlatformToolsetVer Condition=\"'$(PlatformToolsetVer)' == ''\">8.1</PlatformToolsetVer>\n- <PlatformToolset>WindowsKernelModeDriver$(PlatformToolsetVer)</PlatformToolset>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8Analyze|x64'\" Label=\"Configuration\">\n- <TargetVersion>Windows8</TargetVersion>\n- <UseDebugLibraries>true</UseDebugLibraries>\n- <PlatformToolsetVer Condition=\"'$(PlatformToolsetVer)' == ''\">8.1</PlatformToolsetVer>\n- <PlatformToolset>WindowsKernelModeDriver$(PlatformToolsetVer)</PlatformToolset>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win10 Release|x64'\" Label=\"Configuration\">\n- <TargetVersion>\n- </TargetVersion>\n- <UseDebugLibraries>false</UseDebugLibraries>\n- <PlatformToolsetVer Condition=\"'$(PlatformToolsetVer)' == ''\">10.0</PlatformToolsetVer>\n- <PlatformToolset>WindowsKernelModeDriver$(PlatformToolsetVer)</PlatformToolset>\n- <DriverTargetPlatform>Universal</DriverTargetPlatform>\n- </PropertyGroup>\n- <PropertyGroup Label=\"Configuration\" Condition=\"'$(Configuration)|$(Platform)'=='Win8.1 Release|x64'\">\n- <TargetVersion>WindowsV6.3</TargetVersion>\n- <UseDebugLibraries>false</UseDebugLibraries>\n- <PlatformToolsetVer Condition=\"'$(PlatformToolsetVer)' == ''\">8.1</PlatformToolsetVer>\n- <PlatformToolset>WindowsKernelModeDriver$(PlatformToolsetVer)</PlatformToolset>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8 Release|x64'\" Label=\"Configuration\">\n- <TargetVersion>Windows8</TargetVersion>\n- <UseDebugLibraries>false</UseDebugLibraries>\n- <PlatformToolsetVer Condition=\"'$(PlatformToolsetVer)' == ''\">8.1</PlatformToolsetVer>\n- <PlatformToolset>WindowsKernelModeDriver$(PlatformToolsetVer)</PlatformToolset>\n- </PropertyGroup>\n- <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n- <ImportGroup Label=\"ExtensionSettings\">\n- </ImportGroup>\n- <ImportGroup Label=\"PropertySheets\">\n- <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n- </ImportGroup>\n- <PropertyGroup Label=\"UserMacros\" />\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win10 Debug|x64'\">\n- <Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win10Analyze|x64'\">\n- <Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>\n- </PropertyGroup>\n- <PropertyGroup>\n- <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>\n- <EnableDeployment>False</EnableDeployment>\n- <ImportToStore>False</ImportToStore>\n- <InstallMode>None</InstallMode>\n- <HardwareIdString />\n- <CommandLine />\n- <ScriptPath />\n- <DeployFiles />\n- <ScriptName />\n- <ScriptDeviceQuery>%PathToInf%</ScriptDeviceQuery>\n- <EnableVerifier>False</EnableVerifier>\n- <AllDrivers>False</AllDrivers>\n- <VerifyProjectOutput>True</VerifyProjectOutput>\n- <VerifyDrivers />\n- <VerifyFlags>133563</VerifyFlags>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win10 Release|x64'\">\n- <Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>\n- </PropertyGroup>\n- <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8 Debug|x64'\">\n- <Inf2Cat>\n- <UseLocalTime>true</UseLocalTime>\n- </Inf2Cat>\n- <DriverSign>\n- <FileDigestAlgorithm>SHA256</FileDigestAlgorithm>\n- </DriverSign>\n- </ItemDefinitionGroup>\n- <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8Analyze|x64'\">\n- <Inf2Cat>\n- <UseLocalTime>true</UseLocalTime>\n- </Inf2Cat>\n- <DriverSign>\n- <FileDigestAlgorithm>SHA256</FileDigestAlgorithm>\n- </DriverSign>\n- </ItemDefinitionGroup>\n- <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Win10 Debug|x64'\">\n- <Inf2Cat>\n- <UseLocalTime>true</UseLocalTime>\n- </Inf2Cat>\n- <DriverSign>\n- <FileDigestAlgorithm>SHA256</FileDigestAlgorithm>\n- </DriverSign>\n- </ItemDefinitionGroup>\n- <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Win10Analyze|x64'\">\n- <Inf2Cat>\n- <UseLocalTime>true</UseLocalTime>\n- </Inf2Cat>\n- <DriverSign>\n- <FileDigestAlgorithm>SHA256</FileDigestAlgorithm>\n- </DriverSign>\n- </ItemDefinitionGroup>\n- <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8.1 Debug|x64'\">\n- <Inf2Cat>\n- <UseLocalTime>true</UseLocalTime>\n- </Inf2Cat>\n- <DriverSign>\n- <FileDigestAlgorithm>SHA256</FileDigestAlgorithm>\n- </DriverSign>\n- </ItemDefinitionGroup>\n- <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8.1Analyze|x64'\">\n- <Inf2Cat>\n- <UseLocalTime>true</UseLocalTime>\n- </Inf2Cat>\n- <DriverSign>\n- <FileDigestAlgorithm>SHA256</FileDigestAlgorithm>\n- </DriverSign>\n- </ItemDefinitionGroup>\n- <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8 Release|x64'\">\n- <Inf2Cat>\n- <UseLocalTime>true</UseLocalTime>\n- </Inf2Cat>\n- <DriverSign>\n- <FileDigestAlgorithm>SHA256</FileDigestAlgorithm>\n- </DriverSign>\n- </ItemDefinitionGroup>\n- <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8.1 Release|x64'\">\n- <Inf2Cat>\n- <UseLocalTime>true</UseLocalTime>\n- </Inf2Cat>\n- <DriverSign>\n- <FileDigestAlgorithm>SHA256</FileDigestAlgorithm>\n- </DriverSign>\n- </ItemDefinitionGroup>\n- <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Win10 Release|x64'\">\n- <Inf2Cat>\n- <UseLocalTime>true</UseLocalTime>\n- </Inf2Cat>\n- <DriverSign>\n- <FileDigestAlgorithm>SHA256</FileDigestAlgorithm>\n- </DriverSign>\n- </ItemDefinitionGroup>\n- <ItemGroup>\n- <!--Inf Include=\"DriverInf.inv\" /-->\n- <FilesToPackage Include=\"@(Inf->'%(CopyOutput)')\" Condition=\"'@(Inf)'!=''\" />\n- </ItemGroup>\n- <ItemGroup>\n- <ProjectReference Include=\"..\\ovsext\\ovsext.vcxproj\">\n- <Project>{63FE215D-98BE-4440-8081-C6160EFB80FA}</Project>\n- </ProjectReference>\n- </ItemGroup>\n- <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n- <ImportGroup Label=\"ExtensionTargets\">\n- </ImportGroup>\n-</Project>\n\\ No newline at end of file\ndiff --git a/datapath-windows/Package/package.VcxProj.user b/datapath-windows/Package/package.VcxProj.user\ndeleted file mode 100644\nindex 5b0c53539..000000000\n--- a/datapath-windows/Package/package.VcxProj.user\n+++ /dev/null\n@@ -1,30 +0,0 @@\n-<?xml version=\"1.0\" encoding=\"utf-8\"?>\n-<Project ToolsVersion=\"12.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8 Debug|x64'\">\n- <SignMode>TestSign</SignMode>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8Analyze|x64'\">\n- <SignMode>TestSign</SignMode>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8.1 Debug|x64'\">\n- <SignMode>TestSign</SignMode>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8.1Analyze|x64'\">\n- <SignMode>TestSign</SignMode>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win10 Debug|x64'\">\n- <SignMode>TestSign</SignMode>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win10Analyze|x64'\">\n- <SignMode>TestSign</SignMode>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8 Release|x64'\">\n- <SignMode>TestSign</SignMode>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8.1 Release|x64'\">\n- <SignMode>TestSign</SignMode>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win10 Release|x64'\">\n- <SignMode>TestSign</SignMode>\n- </PropertyGroup>\n-</Project>\n\\ No newline at end of file\ndiff --git a/datapath-windows/automake.mk b/datapath-windows/automake.mk\ndeleted file mode 100644\nindex 7d0d82d41..000000000\n--- a/datapath-windows/automake.mk\n+++ /dev/null\n@@ -1,98 +0,0 @@\n-EXTRA_DIST += \\\n-\tdatapath-windows/Package/package.VcxProj \\\n-\tdatapath-windows/Package/package.VcxProj.user \\\n-\tdatapath-windows/include/OvsDpInterfaceExt.h \\\n-\tdatapath-windows/include/OvsDpInterfaceCtExt.h \\\n-\tdatapath-windows/misc/DriverRecommendedRules.ruleset \\\n-\tdatapath-windows/misc/OVS.psm1 \\\n-\tdatapath-windows/misc/install.cmd \\\n-\tdatapath-windows/misc/uninstall.cmd \\\n-\tdatapath-windows/ovsext.sln \\\n-\tdatapath-windows/ovsext/Actions.c \\\n-\tdatapath-windows/ovsext/Actions.h \\\n-\tdatapath-windows/ovsext/Atomic.h \\\n-\tdatapath-windows/ovsext/BufferMgmt.c \\\n-\tdatapath-windows/ovsext/BufferMgmt.h \\\n-\tdatapath-windows/ovsext/Conntrack-ftp.c \\\n-\tdatapath-windows/ovsext/Conntrack-icmp.c \\\n-\tdatapath-windows/ovsext/Conntrack-other.c \\\n-\tdatapath-windows/ovsext/Conntrack-related.c \\\n-\tdatapath-windows/ovsext/Conntrack-nat.c \\\n-\tdatapath-windows/ovsext/Conntrack-tcp.c \\\n-\tdatapath-windows/ovsext/Conntrack-nat.h \\\n-\tdatapath-windows/ovsext/Conntrack.c \\\n-\tdatapath-windows/ovsext/Conntrack.h \\\n-\tdatapath-windows/ovsext/Datapath.c \\\n-\tdatapath-windows/ovsext/Datapath.h \\\n-\tdatapath-windows/ovsext/Debug.c \\\n-\tdatapath-windows/ovsext/Debug.h \\\n-\tdatapath-windows/ovsext/DpInternal.h\\\n-\tdatapath-windows/ovsext/Driver.c \\\n-\tdatapath-windows/ovsext/Ethernet.h \\\n-\tdatapath-windows/ovsext/Event.c \\\n-\tdatapath-windows/ovsext/Event.h \\\n-\tdatapath-windows/ovsext/Flow.c \\\n-\tdatapath-windows/ovsext/Flow.h \\\n-\tdatapath-windows/ovsext/Gre.h \\\n-\tdatapath-windows/ovsext/Gre.c \\\n-\tdatapath-windows/ovsext/IpFragment.c \\\n-\tdatapath-windows/ovsext/IpFragment.h \\\n-\tdatapath-windows/ovsext/Ip6Fragment.c \\\n-\tdatapath-windows/ovsext/Ip6Fragment.h \\\n-\tdatapath-windows/ovsext/IpHelper.c \\\n-\tdatapath-windows/ovsext/IpHelper.h \\\n-\tdatapath-windows/ovsext/Jhash.c \\\n-\tdatapath-windows/ovsext/Jhash.h \\\n-\tdatapath-windows/ovsext/Mpls.h \\\n-\tdatapath-windows/ovsext/Meter.c \\\n-\tdatapath-windows/ovsext/Meter.h \\\n-\tdatapath-windows/ovsext/NetProto.h \\\n-\tdatapath-windows/ovsext/Netlink/Netlink.c \\\n-\tdatapath-windows/ovsext/Netlink/Netlink.h \\\n-\tdatapath-windows/ovsext/Netlink/NetlinkBuf.c \\\n-\tdatapath-windows/ovsext/Netlink/NetlinkBuf.h \\\n-\tdatapath-windows/ovsext/Netlink/NetlinkError.h \\\n-\tdatapath-windows/ovsext/Netlink/NetlinkProto.h \\\n-\tdatapath-windows/ovsext/Offload.c \\\n-\tdatapath-windows/ovsext/Offload.h \\\n-\tdatapath-windows/ovsext/Oid.c \\\n-\tdatapath-windows/ovsext/Oid.h \\\n-\tdatapath-windows/ovsext/PacketIO.c \\\n-\tdatapath-windows/ovsext/PacketIO.h \\\n-\tdatapath-windows/ovsext/PacketParser.c \\\n-\tdatapath-windows/ovsext/PacketParser.h \\\n-\tdatapath-windows/ovsext/Recirc.c \\\n-\tdatapath-windows/ovsext/Recirc.h \\\n-\tdatapath-windows/ovsext/Switch.c \\\n-\tdatapath-windows/ovsext/Switch.h \\\n-\tdatapath-windows/ovsext/Tunnel.c \\\n-\tdatapath-windows/ovsext/Tunnel.h \\\n-\tdatapath-windows/ovsext/TunnelFilter.c \\\n-\tdatapath-windows/ovsext/TunnelIntf.h \\\n-\tdatapath-windows/ovsext/Types.h \\\n-\tdatapath-windows/ovsext/User.c \\\n-\tdatapath-windows/ovsext/User.h \\\n-\tdatapath-windows/ovsext/Util.c \\\n-\tdatapath-windows/ovsext/Util.h \\\n-\tdatapath-windows/ovsext/Vport.c \\\n-\tdatapath-windows/ovsext/Vport.h \\\n-\tdatapath-windows/ovsext/Vxlan.c \\\n-\tdatapath-windows/ovsext/Vxlan.h \\\n-\tdatapath-windows/ovsext/Geneve.c \\\n-\tdatapath-windows/ovsext/Geneve.h \\\n-\tdatapath-windows/ovsext/ovsext.inf \\\n-\tdatapath-windows/ovsext/ovsext.rc \\\n-\tdatapath-windows/ovsext/ovsext.vcxproj \\\n-\tdatapath-windows/ovsext/ovsext.vcxproj.user \\\n-\tdatapath-windows/ovsext/precomp.h \\\n-\tdatapath-windows/ovsext/precompsrc.c \\\n-\tdatapath-windows/ovsext/resource.h\n-\n-datapath_windows_analyze: all\n-\tMSBuild.exe //nologo //maxcpucount datapath-windows/ovsext.sln /target:Build /property:Configuration=\"Win10Analyze\"\n-\tMSBuild.exe //nologo //maxcpucount datapath-windows/ovsext.sln /target:Build /property:Configuration=\"Win8.1Analyze\"\n-\tMSBuild.exe //nologo //maxcpucount datapath-windows/ovsext.sln /target:Build /property:Configuration=\"Win8Analyze\"\n-\n-datapath_windows: all\n-\tMSBuild.exe //nologo //maxcpucount datapath-windows/ovsext.sln /target:Build /property:Configuration=\"Win10Debug\"\n-\tMSBuild.exe //nologo //maxcpucount datapath-windows/ovsext.sln /target:Build /property:Configuration=\"Win10Release\"\ndiff --git a/datapath-windows/include/OvsDpInterfaceCtExt.h b/datapath-windows/include/OvsDpInterfaceCtExt.h\ndeleted file mode 100644\nindex 3379f0a25..000000000\n--- a/datapath-windows/include/OvsDpInterfaceCtExt.h\n+++ /dev/null\n@@ -1,538 +0,0 @@\n-/*\n- * Copyright (c) 2016 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#ifndef __OVS_DP_INTERFACE_CT_EXT_H_\n-#define __OVS_DP_INTERFACE_CT_EXT_H_ 1\n-\n-/* Conntrack Netlink headers */\n-#define NFNL_TYPE_CT_GET (NFNL_SUBSYS_CTNETLINK << 8 | IPCTNL_MSG_CT_GET)\n-#define NFNL_TYPE_CT_DEL (NFNL_SUBSYS_CTNETLINK << 8 | IPCTNL_MSG_CT_DELETE)\n-#define IS_NFNL_CMD(nlmsgType) ((nlmsgType == NFNL_TYPE_CT_GET) \\\n- || (nlmsgType == NFNL_TYPE_CT_DEL))\n-#define OVS_NL_CT_ATTR_MAX (IPCTNL_MSG_MAX - 1)\n-\n-#define OVS_CT_FAMILY \"ovs_ct\"\n-#define OVS_CT_MCGROUP \"ovs_ct\"\n-#define OVS_CT_VERSION 1\n-\n-/* File: nfnetlink.h */\n-enum nfnetlink_groups {\n- NFNLGRP_NONE,\n-#define NFNLGRP_NONE NFNLGRP_NONE\n- NFNLGRP_CONNTRACK_NEW,\n-#define NFNLGRP_CONNTRACK_NEW NFNLGRP_CONNTRACK_NEW\n- NFNLGRP_CONNTRACK_UPDATE,\n-#define NFNLGRP_CONNTRACK_UPDATE NFNLGRP_CONNTRACK_UPDATE\n- NFNLGRP_CONNTRACK_DESTROY,\n-#define NFNLGRP_CONNTRACK_DESTROY NFNLGRP_CONNTRACK_DESTROY\n- NFNLGRP_CONNTRACK_EXP_NEW,\n-#define NFNLGRP_CONNTRACK_EXP_NEW NFNLGRP_CONNTRACK_EXP_NEW\n- NFNLGRP_CONNTRACK_EXP_UPDATE,\n-#define NFNLGRP_CONNTRACK_EXP_UPDATE NFNLGRP_CONNTRACK_EXP_UPDATE\n- NFNLGRP_CONNTRACK_EXP_DESTROY,\n-#define NFNLGRP_CONNTRACK_EXP_DESTROY NFNLGRP_CONNTRACK_EXP_DESTROY\n- NFNLGRP_NFTABLES,\n-#define NFNLGRP_NFTABLES NFNLGRP_NFTABLES\n- __NFNLGRP_MAX,\n-};\n-#define NFNLGRP_MAX (__NFNLGRP_MAX - 1)\n-\n-struct nfgenmsg {\n- UINT8 nfgen_family; /* AF_xxx (AF_UNSPEC/AF_INET/AF_INET6) */\n- UINT8 version; /* nfnetlink version (currently set to v0) */\n- UINT16 res_id; /* resource id (unused in Windows) */\n- struct ovs_header ovsHdr; /* Pad this for Windows */\n-};\n-\n-#define NFNETLINK_V0 0\n-#define NFNL_SUBSYS_ID(x) ((x & 0xff00) >> 8)\n-#define NFNL_MSG_TYPE(x) (x & 0x00ff)\n-\n-#define NFNL_SUBSYS_NONE 0\n-#define NFNL_SUBSYS_CTNETLINK 1\n-#define NFNL_SUBSYS_CTNETLINK_EXP 2\n-#define NFNL_SUBSYS_QUEUE 3\n-#define NFNL_SUBSYS_ULOG 4\n-#define NFNL_SUBSYS_OSF 5\n-#define NFNL_SUBSYS_IPSET 6\n-#define NFNL_SUBSYS_ACCT 7\n-#define NFNL_SUBSYS_CTNETLINK_TIMEOUT 8\n-#define NFNL_SUBSYS_CTHELPER 9\n-#define NFNL_SUBSYS_NFTABLES 10\n-#define NFNL_SUBSYS_NFT_COMPAT 11\n-#define NFNL_SUBSYS_COUNT 12\n-\n-#define NFNL_MSG_BATCH_BEGIN NLMSG_MIN_TYPE\n-#define NFNL_MSG_BATCH_END NLMSG_MIN_TYPE+1\n-\n-/* File: nf_conntrack_common.h */\n-enum ip_conntrack_info {\n- IP_CT_ESTABLISHED,\n- IP_CT_RELATED,\n- IP_CT_NEW,\n- IP_CT_IS_REPLY,\n- IP_CT_ESTABLISHED_REPLY = IP_CT_ESTABLISHED + IP_CT_IS_REPLY,\n- IP_CT_RELATED_REPLY = IP_CT_RELATED + IP_CT_IS_REPLY,\n- IP_CT_NEW_REPLY = IP_CT_NEW + IP_CT_IS_REPLY,\n- IP_CT_NUMBER = IP_CT_IS_REPLY * 2 - 1\n-};\n-\n-enum ip_conntrack_status {\n- IPS_EXPECTED_BIT = 0,\n- IPS_EXPECTED = (1 << IPS_EXPECTED_BIT),\n- IPS_SEEN_REPLY_BIT = 1,\n- IPS_SEEN_REPLY = (1 << IPS_SEEN_REPLY_BIT),\n- IPS_ASSURED_BIT = 2,\n- IPS_ASSURED = (1 << IPS_ASSURED_BIT),\n- IPS_CONFIRMED_BIT = 3,\n- IPS_CONFIRMED = (1 << IPS_CONFIRMED_BIT),\n- IPS_SRC_NAT_BIT = 4,\n- IPS_SRC_NAT = (1 << IPS_SRC_NAT_BIT),\n- IPS_DST_NAT_BIT = 5,\n- IPS_DST_NAT = (1 << IPS_DST_NAT_BIT),\n- IPS_NAT_MASK = (IPS_DST_NAT | IPS_SRC_NAT),\n- IPS_SEQ_ADJUST_BIT = 6,\n- IPS_SEQ_ADJUST = (1 << IPS_SEQ_ADJUST_BIT),\n- IPS_SRC_NAT_DONE_BIT = 7,\n- IPS_SRC_NAT_DONE = (1 << IPS_SRC_NAT_DONE_BIT),\n- IPS_DST_NAT_DONE_BIT = 8,\n- IPS_DST_NAT_DONE = (1 << IPS_DST_NAT_DONE_BIT),\n- IPS_NAT_DONE_MASK = (IPS_DST_NAT_DONE | IPS_SRC_NAT_DONE),\n- IPS_DYING_BIT = 9,\n- IPS_DYING = (1 << IPS_DYING_BIT),\n- IPS_FIXED_TIMEOUT_BIT = 10,\n- IPS_FIXED_TIMEOUT = (1 << IPS_FIXED_TIMEOUT_BIT),\n- IPS_TEMPLATE_BIT = 11,\n- IPS_TEMPLATE = (1 << IPS_TEMPLATE_BIT),\n- IPS_UNTRACKED_BIT = 12,\n- IPS_UNTRACKED = (1 << IPS_UNTRACKED_BIT),\n-};\n-\n-enum ip_conntrack_events {\n- IPCT_NEW,\n- IPCT_RELATED,\n- IPCT_DESTROY,\n- IPCT_REPLY,\n- IPCT_ASSURED,\n- IPCT_PROTOINFO,\n- IPCT_HELPER,\n- IPCT_MARK,\n- IPCT_NATSEQADJ,\n- IPCT_SECMARK,\n- IPCT_LABEL,\n-};\n-\n-enum ip_conntrack_expect_events {\n- IPEXP_NEW,\n- IPEXP_DESTROY,\n-};\n-\n-#define NF_CT_EXPECT_PERMANENT 0x1\n-#define NF_CT_EXPECT_INACTIVE 0x2\n-#define NF_CT_EXPECT_USERSPACE 0x4\n-\n-/* File: nfnetlink_conntrack.h */\n-enum cntl_msg_types {\n- IPCTNL_MSG_CT_NEW,\n- IPCTNL_MSG_CT_GET,\n- IPCTNL_MSG_CT_DELETE,\n- IPCTNL_MSG_CT_GET_CTRZERO,\n- IPCTNL_MSG_CT_GET_STATS_CPU,\n- IPCTNL_MSG_CT_GET_STATS,\n- IPCTNL_MSG_CT_GET_DYING,\n- IPCTNL_MSG_CT_GET_UNCONFIRMED,\n- IPCTNL_MSG_MAX\n-};\n-\n-enum ctnl_exp_msg_types {\n- IPCTNL_MSG_EXP_NEW,\n- IPCTNL_MSG_EXP_GET,\n- IPCTNL_MSG_EXP_DELETE,\n- IPCTNL_MSG_EXP_GET_STATS_CPU,\n- IPCTNL_MSG_EXP_MAX\n-};\n-\n-enum ctattr_type {\n- CTA_UNSPEC,\n- CTA_TUPLE_ORIG,\n- CTA_TUPLE_REPLY,\n- CTA_STATUS,\n- CTA_PROTOINFO,\n- CTA_HELP,\n- CTA_NAT_SRC,\n-#define CTA_NAT CTA_NAT_SRC\n- CTA_TIMEOUT,\n- CTA_MARK,\n- CTA_COUNTERS_ORIG,\n- CTA_COUNTERS_REPLY,\n- CTA_USE,\n- CTA_ID,\n- CTA_NAT_DST,\n- CTA_TUPLE_MASTER,\n- CTA_NAT_SEQ_ADJ_ORIG,\n- CTA_NAT_SEQ_ADJ_REPLY,\n- CTA_SECMARK,\n- CTA_ZONE,\n- CTA_SECCTX,\n- CTA_TIMESTAMP,\n- CTA_MARK_MASK,\n- CTA_LABELS,\n- CTA_LABELS_MASK,\n- __CTA_MAX\n-};\n-#define CTA_MAX (__CTA_MAX - 1)\n-\n-enum ctattr_tuple {\n- CTA_TUPLE_UNSPEC,\n- CTA_TUPLE_IP,\n- CTA_TUPLE_PROTO,\n- __CTA_TUPLE_MAX\n-};\n-#define CTA_TUPLE_MAX (__CTA_TUPLE_MAX - 1)\n-\n-enum ctattr_ip {\n- CTA_IP_UNSPEC,\n- CTA_IP_V4_SRC,\n- CTA_IP_V4_DST,\n- CTA_IP_V6_SRC,\n- CTA_IP_V6_DST,\n- __CTA_IP_MAX\n-};\n-#define CTA_IP_MAX (__CTA_IP_MAX - 1)\n-\n-enum ctattr_l4proto {\n- CTA_PROTO_UNSPEC,\n- CTA_PROTO_NUM,\n- CTA_PROTO_SRC_PORT,\n- CTA_PROTO_DST_PORT,\n- CTA_PROTO_ICMP_ID,\n- CTA_PROTO_ICMP_TYPE,\n- CTA_PROTO_ICMP_CODE,\n- CTA_PROTO_ICMPV6_ID,\n- CTA_PROTO_ICMPV6_TYPE,\n- CTA_PROTO_ICMPV6_CODE,\n- __CTA_PROTO_MAX\n-};\n-#define CTA_PROTO_MAX (__CTA_PROTO_MAX - 1)\n-\n-enum ctattr_protoinfo {\n- CTA_PROTOINFO_UNSPEC,\n- CTA_PROTOINFO_TCP,\n- CTA_PROTOINFO_DCCP,\n- CTA_PROTOINFO_SCTP,\n- __CTA_PROTOINFO_MAX\n-};\n-#define CTA_PROTOINFO_MAX (__CTA_PROTOINFO_MAX - 1)\n-\n-enum ctattr_protoinfo_tcp {\n- CTA_PROTOINFO_TCP_UNSPEC,\n- CTA_PROTOINFO_TCP_STATE,\n- CTA_PROTOINFO_TCP_WSCALE_ORIGINAL,\n- CTA_PROTOINFO_TCP_WSCALE_REPLY,\n- CTA_PROTOINFO_TCP_FLAGS_ORIGINAL,\n- CTA_PROTOINFO_TCP_FLAGS_REPLY,\n- __CTA_PROTOINFO_TCP_MAX\n-};\n-#define CTA_PROTOINFO_TCP_MAX (__CTA_PROTOINFO_TCP_MAX - 1)\n-\n-enum ctattr_protoinfo_dccp {\n- CTA_PROTOINFO_DCCP_UNSPEC,\n- CTA_PROTOINFO_DCCP_STATE,\n- CTA_PROTOINFO_DCCP_ROLE,\n- CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ,\n- __CTA_PROTOINFO_DCCP_MAX,\n-};\n-#define CTA_PROTOINFO_DCCP_MAX (__CTA_PROTOINFO_DCCP_MAX - 1)\n-\n-enum ctattr_protoinfo_sctp {\n- CTA_PROTOINFO_SCTP_UNSPEC,\n- CTA_PROTOINFO_SCTP_STATE,\n- CTA_PROTOINFO_SCTP_VTAG_ORIGINAL,\n- CTA_PROTOINFO_SCTP_VTAG_REPLY,\n- __CTA_PROTOINFO_SCTP_MAX\n-};\n-#define CTA_PROTOINFO_SCTP_MAX (__CTA_PROTOINFO_SCTP_MAX - 1)\n-\n-enum ctattr_counters {\n- CTA_COUNTERS_UNSPEC,\n- CTA_COUNTERS_PACKETS,\n- CTA_COUNTERS_BYTES,\n- CTA_COUNTERS32_PACKETS,\n- CTA_COUNTERS32_BYTES,\n- __CTA_COUNTERS_MAX\n-};\n-#define CTA_COUNTERS_MAX (__CTA_COUNTERS_MAX - 1)\n-\n-enum ctattr_tstamp {\n- CTA_TIMESTAMP_UNSPEC,\n- CTA_TIMESTAMP_START,\n- CTA_TIMESTAMP_STOP,\n- __CTA_TIMESTAMP_MAX\n-};\n-#define CTA_TIMESTAMP_MAX (__CTA_TIMESTAMP_MAX - 1)\n-\n-enum ctattr_nat {\n- CTA_NAT_UNSPEC,\n- CTA_NAT_V4_MINIP,\n-#define CTA_NAT_MINIP CTA_NAT_V4_MINIP\n- CTA_NAT_V4_MAXIP,\n-#define CTA_NAT_MAXIP CTA_NAT_V4_MAXIP\n- CTA_NAT_PROTO,\n- CTA_NAT_V6_MINIP,\n- CTA_NAT_V6_MAXIP,\n- __CTA_NAT_MAX\n-};\n-#define CTA_NAT_MAX (__CTA_NAT_MAX - 1)\n-\n-enum ctattr_protonat {\n- CTA_PROTONAT_UNSPEC,\n- CTA_PROTONAT_PORT_MIN,\n- CTA_PROTONAT_PORT_MAX,\n- __CTA_PROTONAT_MAX\n-};\n-#define CTA_PROTONAT_MAX (__CTA_PROTONAT_MAX - 1)\n-\n-enum ctattr_natseq {\n- CTA_NAT_SEQ_UNSPEC,\n- CTA_NAT_SEQ_CORRECTION_POS,\n- CTA_NAT_SEQ_OFFSET_BEFORE,\n- CTA_NAT_SEQ_OFFSET_AFTER,\n- __CTA_NAT_SEQ_MAX\n-};\n-#define CTA_NAT_SEQ_MAX (__CTA_NAT_SEQ_MAX - 1)\n-\n-enum ctattr_expect {\n- CTA_EXPECT_UNSPEC,\n- CTA_EXPECT_MASTER,\n- CTA_EXPECT_TUPLE,\n- CTA_EXPECT_MASK,\n- CTA_EXPECT_TIMEOUT,\n- CTA_EXPECT_ID,\n- CTA_EXPECT_HELP_NAME,\n- CTA_EXPECT_ZONE,\n- CTA_EXPECT_FLAGS,\n- CTA_EXPECT_CLASS,\n- CTA_EXPECT_NAT,\n- CTA_EXPECT_FN,\n- __CTA_EXPECT_MAX\n-};\n-#define CTA_EXPECT_MAX (__CTA_EXPECT_MAX - 1)\n-\n-enum ctattr_expect_nat {\n- CTA_EXPECT_NAT_UNSPEC,\n- CTA_EXPECT_NAT_DIR,\n- CTA_EXPECT_NAT_TUPLE,\n- __CTA_EXPECT_NAT_MAX\n-};\n-#define CTA_EXPECT_NAT_MAX (__CTA_EXPECT_NAT_MAX - 1)\n-\n-enum ctattr_help {\n- CTA_HELP_UNSPEC,\n- CTA_HELP_NAME,\n- CTA_HELP_INFO,\n- __CTA_HELP_MAX\n-};\n-#define CTA_HELP_MAX (__CTA_HELP_MAX - 1)\n-\n-enum ctattr_secctx {\n- CTA_SECCTX_UNSPEC,\n- CTA_SECCTX_NAME,\n- __CTA_SECCTX_MAX\n-};\n-#define CTA_SECCTX_MAX (__CTA_SECCTX_MAX - 1)\n-\n-enum ctattr_stats_cpu {\n- CTA_STATS_UNSPEC,\n- CTA_STATS_SEARCHED,\n- CTA_STATS_FOUND,\n- CTA_STATS_NEW,\n- CTA_STATS_INVALID,\n- CTA_STATS_IGNORE,\n- CTA_STATS_DELETE,\n- CTA_STATS_DELETE_LIST,\n- CTA_STATS_INSERT,\n- CTA_STATS_INSERT_FAILED,\n- CTA_STATS_DROP,\n- CTA_STATS_EARLY_DROP,\n- CTA_STATS_ERROR,\n- CTA_STATS_SEARCH_RESTART,\n- __CTA_STATS_MAX,\n-};\n-#define CTA_STATS_MAX (__CTA_STATS_MAX - 1)\n-\n-enum ctattr_stats_global {\n- CTA_STATS_GLOBAL_UNSPEC,\n- CTA_STATS_GLOBAL_ENTRIES,\n- __CTA_STATS_GLOBAL_MAX,\n-};\n-#define CTA_STATS_GLOBAL_MAX (__CTA_STATS_GLOBAL_MAX - 1)\n-\n-enum ctattr_expect_stats {\n- CTA_STATS_EXP_UNSPEC,\n- CTA_STATS_EXP_NEW,\n- CTA_STATS_EXP_CREATE,\n- CTA_STATS_EXP_DELETE,\n- __CTA_STATS_EXP_MAX,\n-};\n-#define CTA_STATS_EXP_MAX (__CTA_STATS_EXP_MAX - 1)\n-\n-/* File: nf_conntrack_tcp.h */\n-enum tcp_conntrack {\n- TCP_CONNTRACK_NONE,\n- TCP_CONNTRACK_SYN_SENT,\n- TCP_CONNTRACK_SYN_RECV,\n- TCP_CONNTRACK_ESTABLISHED,\n- TCP_CONNTRACK_FIN_WAIT,\n- TCP_CONNTRACK_CLOSE_WAIT,\n- TCP_CONNTRACK_LAST_ACK,\n- TCP_CONNTRACK_TIME_WAIT,\n- TCP_CONNTRACK_CLOSE,\n- TCP_CONNTRACK_LISTEN,\n-#define TCP_CONNTRACK_SYN_SENT2 TCP_CONNTRACK_LISTEN\n- TCP_CONNTRACK_MAX,\n- TCP_CONNTRACK_IGNORE,\n- TCP_CONNTRACK_RETRANS,\n- TCP_CONNTRACK_UNACK,\n- TCP_CONNTRACK_TIMEOUT_MAX\n-};\n-\n-#define IP_CT_TCP_FLAG_WINDOW_SCALE 0x01\n-#define IP_CT_TCP_FLAG_SACK_PERM 0x02\n-#define IP_CT_TCP_FLAG_CLOSE_INIT 0x04\n-#define IP_CT_TCP_FLAG_BE_LIBERAL 0x08\n-#define IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED 0x10\n-#define IP_CT_TCP_FLAG_MAXACK_SET 0x20\n-\n-struct nf_ct_tcp_flags {\n- UINT8 flags;\n- UINT8 mask;\n-};\n-\n-/* File: nfnetlink_cttimeout.h. XXX: the following are not implemented */\n-enum ctnl_timeout_msg_types {\n- IPCTNL_MSG_TIMEOUT_NEW,\n- IPCTNL_MSG_TIMEOUT_GET,\n- IPCTNL_MSG_TIMEOUT_DELETE,\n- IPCTNL_MSG_TIMEOUT_DEFAULT_SET,\n- IPCTNL_MSG_TIMEOUT_DEFAULT_GET,\n-\n- IPCTNL_MSG_TIMEOUT_MAX\n-};\n-\n-enum ctattr_timeout {\n- CTA_TIMEOUT_UNSPEC,\n- CTA_TIMEOUT_NAME,\n- CTA_TIMEOUT_L3PROTO,\n- CTA_TIMEOUT_L4PROTO,\n- CTA_TIMEOUT_DATA,\n- CTA_TIMEOUT_USE,\n- __CTA_TIMEOUT_MAX\n-};\n-#define CTA_TIMEOUT_MAX (__CTA_TIMEOUT_MAX - 1)\n-\n-enum ctattr_timeout_generic {\n- CTA_TIMEOUT_GENERIC_UNSPEC,\n- CTA_TIMEOUT_GENERIC_TIMEOUT,\n- __CTA_TIMEOUT_GENERIC_MAX\n-};\n-#define CTA_TIMEOUT_GENERIC_MAX (__CTA_TIMEOUT_GENERIC_MAX - 1)\n-\n-enum ctattr_timeout_tcp {\n- CTA_TIMEOUT_TCP_UNSPEC,\n- CTA_TIMEOUT_TCP_SYN_SENT,\n- CTA_TIMEOUT_TCP_SYN_RECV,\n- CTA_TIMEOUT_TCP_ESTABLISHED,\n- CTA_TIMEOUT_TCP_FIN_WAIT,\n- CTA_TIMEOUT_TCP_CLOSE_WAIT,\n- CTA_TIMEOUT_TCP_LAST_ACK,\n- CTA_TIMEOUT_TCP_TIME_WAIT,\n- CTA_TIMEOUT_TCP_CLOSE,\n- CTA_TIMEOUT_TCP_SYN_SENT2,\n- CTA_TIMEOUT_TCP_RETRANS,\n- CTA_TIMEOUT_TCP_UNACK,\n- __CTA_TIMEOUT_TCP_MAX\n-};\n-#define CTA_TIMEOUT_TCP_MAX (__CTA_TIMEOUT_TCP_MAX - 1)\n-\n-enum ctattr_timeout_udp {\n- CTA_TIMEOUT_UDP_UNSPEC,\n- CTA_TIMEOUT_UDP_UNREPLIED,\n- CTA_TIMEOUT_UDP_REPLIED,\n- __CTA_TIMEOUT_UDP_MAX\n-};\n-#define CTA_TIMEOUT_UDP_MAX (__CTA_TIMEOUT_UDP_MAX - 1)\n-\n-enum ctattr_timeout_udplite {\n- CTA_TIMEOUT_UDPLITE_UNSPEC,\n- CTA_TIMEOUT_UDPLITE_UNREPLIED,\n- CTA_TIMEOUT_UDPLITE_REPLIED,\n- __CTA_TIMEOUT_UDPLITE_MAX\n-};\n-#define CTA_TIMEOUT_UDPLITE_MAX (__CTA_TIMEOUT_UDPLITE_MAX - 1)\n-\n-enum ctattr_timeout_icmp {\n- CTA_TIMEOUT_ICMP_UNSPEC,\n- CTA_TIMEOUT_ICMP_TIMEOUT,\n- __CTA_TIMEOUT_ICMP_MAX\n-};\n-#define CTA_TIMEOUT_ICMP_MAX (__CTA_TIMEOUT_ICMP_MAX - 1)\n-\n-enum ctattr_timeout_dccp {\n- CTA_TIMEOUT_DCCP_UNSPEC,\n- CTA_TIMEOUT_DCCP_REQUEST,\n- CTA_TIMEOUT_DCCP_RESPOND,\n- CTA_TIMEOUT_DCCP_PARTOPEN,\n- CTA_TIMEOUT_DCCP_OPEN,\n- CTA_TIMEOUT_DCCP_CLOSEREQ,\n- CTA_TIMEOUT_DCCP_CLOSING,\n- CTA_TIMEOUT_DCCP_TIMEWAIT,\n- __CTA_TIMEOUT_DCCP_MAX\n-};\n-#define CTA_TIMEOUT_DCCP_MAX (__CTA_TIMEOUT_DCCP_MAX - 1)\n-\n-enum ctattr_timeout_sctp {\n- CTA_TIMEOUT_SCTP_UNSPEC,\n- CTA_TIMEOUT_SCTP_CLOSED,\n- CTA_TIMEOUT_SCTP_COOKIE_WAIT,\n- CTA_TIMEOUT_SCTP_COOKIE_ECHOED,\n- CTA_TIMEOUT_SCTP_ESTABLISHED,\n- CTA_TIMEOUT_SCTP_SHUTDOWN_SENT,\n- CTA_TIMEOUT_SCTP_SHUTDOWN_RECD,\n- CTA_TIMEOUT_SCTP_SHUTDOWN_ACK_SENT,\n- CTA_TIMEOUT_SCTP_HEARTBEAT_SENT,\n- CTA_TIMEOUT_SCTP_HEARTBEAT_ACKED,\n- __CTA_TIMEOUT_SCTP_MAX\n-};\n-#define CTA_TIMEOUT_SCTP_MAX (__CTA_TIMEOUT_SCTP_MAX - 1)\n-\n-enum ctattr_timeout_icmpv6 {\n- CTA_TIMEOUT_ICMPV6_UNSPEC,\n- CTA_TIMEOUT_ICMPV6_TIMEOUT,\n- __CTA_TIMEOUT_ICMPV6_MAX\n-};\n-#define CTA_TIMEOUT_ICMPV6_MAX (__CTA_TIMEOUT_ICMPV6_MAX - 1)\n-\n-enum ctattr_timeout_gre {\n- CTA_TIMEOUT_GRE_UNSPEC,\n- CTA_TIMEOUT_GRE_UNREPLIED,\n- CTA_TIMEOUT_GRE_REPLIED,\n- __CTA_TIMEOUT_GRE_MAX\n-};\n-#define CTA_TIMEOUT_GRE_MAX (__CTA_TIMEOUT_GRE_MAX - 1)\n-\n-#define CTNL_TIMEOUT_NAME_MAX\t32\n-\n-#endif /* __OVS_DP_INTERFACE_CT_EXT_H_ */\ndiff --git a/datapath-windows/include/OvsDpInterfaceExt.h b/datapath-windows/include/OvsDpInterfaceExt.h\ndeleted file mode 100644\nindex 045e4cbd6..000000000\n--- a/datapath-windows/include/OvsDpInterfaceExt.h\n+++ /dev/null\n@@ -1,183 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#ifndef __OVS_DP_INTERFACE_EXT_H_\n-#define __OVS_DP_INTERFACE_EXT_H_ 1\n-\n-/* Windows kernel datapath extensions to the standard datapath interface. */\n-\n-/* Version number of the datapath interface extensions. */\n-#define OVS_DATAPATH_EXT_VERSION 1\n-\n-/* Name of the device. */\n-#define OVS_DEVICE_NAME_NT L\"\\\\Device\\\\OpenvSwitchDevice\"\n-#define OVS_DEVICE_NAME_DOS L\"\\\\DosDevices\\\\OpenvSwitchDevice\"\n-#define OVS_DEVICE_NAME_USER TEXT(\"\\\\\\\\.\\\\OpenvSwitchDevice\")\n-\n-#define OVS_IOCTL_DEVICE_TYPE 45000\n-\n-#define OVS_IOCTL_START 0x100\n-/* We used Direct I/O (zero copy) for the buffers. */\n-/* Non-Netlink-based IOCTLs. */\n-#define OVS_IOCTL_GET_PID \\\n- CTL_CODE (OVS_IOCTL_DEVICE_TYPE, OVS_IOCTL_START + 0x0, METHOD_BUFFERED,\\\n- FILE_WRITE_ACCESS)\n-/* Netlink-based IOCTLs. */\n-#define OVS_IOCTL_READ \\\n- CTL_CODE (OVS_IOCTL_DEVICE_TYPE, OVS_IOCTL_START + 0x1, METHOD_OUT_DIRECT,\\\n- FILE_READ_ACCESS)\n-#define OVS_IOCTL_READ_EVENT \\\n- CTL_CODE (OVS_IOCTL_DEVICE_TYPE, OVS_IOCTL_START + 0x2, METHOD_OUT_DIRECT, \\\n- FILE_READ_ACCESS)\n-#define OVS_IOCTL_READ_PACKET \\\n- CTL_CODE (OVS_IOCTL_DEVICE_TYPE, OVS_IOCTL_START + 0x3, METHOD_OUT_DIRECT, \\\n- FILE_READ_ACCESS)\n-#define OVS_IOCTL_WRITE \\\n- CTL_CODE (OVS_IOCTL_DEVICE_TYPE, OVS_IOCTL_START + 0x4, METHOD_IN_DIRECT,\\\n- FILE_READ_ACCESS)\n-#define OVS_IOCTL_TRANSACT \\\n- CTL_CODE (OVS_IOCTL_DEVICE_TYPE, OVS_IOCTL_START + 0x5, METHOD_OUT_DIRECT,\\\n- FILE_WRITE_ACCESS)\n-\n-/*\n- * On platforms that support netlink natively, the operating system assigns a\n- * dynamic value to a netlink family when it is registered. In the absense of\n- * such mechanism, defined hard-coded values that are known both to userspace\n- * and kernel.\n- */\n-#define OVS_WIN_NL_INVALID_FAMILY_ID 0\n-#define OVS_WIN_NL_CTRL_FAMILY_ID (NLMSG_MIN_TYPE + 1)\n-#define OVS_WIN_NL_DATAPATH_FAMILY_ID (NLMSG_MIN_TYPE + 2)\n-#define OVS_WIN_NL_PACKET_FAMILY_ID (NLMSG_MIN_TYPE + 3)\n-#define OVS_WIN_NL_VPORT_FAMILY_ID (NLMSG_MIN_TYPE + 4)\n-#define OVS_WIN_NL_FLOW_FAMILY_ID (NLMSG_MIN_TYPE + 5)\n-#define OVS_WIN_NL_NETDEV_FAMILY_ID (NLMSG_MIN_TYPE + 6)\n-/*\n- * Conntrack Family is defined in OvsDpInterfaceCtExt.h\n- * OVS_WIN_NL_CT_FAMILY_ID is not used in the messages, but used internally\n- * in the kernel as a placeholder to enable parsing out the ct family cmds.\n- */\n-\n-#define OVS_WIN_NL_CT_FAMILY_ID (NLMSG_MIN_TYPE + 7)\n-#define OVS_WIN_NL_CTLIMIT_FAMILY_ID (NLMSG_MIN_TYPE + 8)\n-\n-/* Meter Family */\n-#define OVS_WIN_NL_METER_FAMILY_ID (NLMSG_MIN_TYPE + 9)\n-\n-#define OVS_WIN_NL_INVALID_MCGRP_ID 0\n-#define OVS_WIN_NL_MCGRP_START_ID 100\n-#define OVS_WIN_NL_VPORT_MCGRP_ID (OVS_WIN_NL_MCGRP_START_ID + 1)\n-\n-/*\n- * Define a family of netlink command specific to Windows. This is part of the\n- * extensions.\n- */\n-#define OVS_WIN_CONTROL_FAMILY \"ovs_win_control\"\n-#define OVS_WIN_CONTROL_MCGROUP \"ovs_win_control\"\n-#define OVS_WIN_CONTROL_VERSION 1\n-\n-/* Commands available under the OVS_WIN_CONTROL_FAMILY. */\n-enum ovs_win_control_cmd {\n- OVS_CTRL_CMD_WIN_PEND_REQ,\n- OVS_CTRL_CMD_WIN_PEND_PACKET_REQ,\n- OVS_CTRL_CMD_MC_SUBSCRIBE_REQ,\n- OVS_CTRL_CMD_PACKET_SUBSCRIBE_REQ,\n-\n- /* This command logically belongs to the Vport family */\n- OVS_CTRL_CMD_EVENT_NOTIFY,\n- OVS_CTRL_CMD_READ_NOTIFY,\n-\n- /* Used for Socket property */\n- OVS_CTRL_CMD_SOCK_PROP\n-};\n-\n-/* NL Attributes for joining/unjoining an MC group */\n-enum ovs_nl_mcast_attr {\n- OVS_NL_ATTR_MCAST_GRP, /* (UINT32) Join an MC group */\n- OVS_NL_ATTR_MCAST_JOIN, /* (UINT8) 1/0 - Join/Unjoin */\n- OVS_NL_ATTR_PACKET_SUBSCRIBE, /* (UNINT8): 1/0 - subscribe/unsubscribe */\n- OVS_NL_ATTR_PACKET_PID, /* (UNINT32) netlink PID to receive upcalls */\n- __OVS_NL_ATTR_CTRL_MAX\n-};\n-#define OVS_WIN_CONTROL_ATTR_MAX (__OVS_NL_ATTR_CTRL_MAX - 1)\n-\n-/*\n- * Netdev family of commands specific to Windows.\n- */\n-#define OVS_WIN_NETDEV_FAMILY \"ovs_win_netdev\"\n-#define OVS_WIN_NETDEV_MCGROUP \"ovs_win_netdev\"\n-#define OVS_WIN_NETDEV_VERSION 1\n-\n-enum ovs_win_netdev_cmd {\n- OVS_WIN_NETDEV_CMD_UNSPEC,\n- OVS_WIN_NETDEV_CMD_GET, /* information about the netdev. */\n-};\n-\n-/**\n- * For every vport on the datapath, there is a corresponding netdev. General\n- * network device attributes of a vport that are not specific to OVS, such as\n- * MTU are represented using a netdev. For convenience, some of the vport\n- * attributes are also included as netdev attributes.\n- *\n- * enum ovs_win_netdev_attr - attributes for %OVS_WIN_NETDEV_* commands.\n- * @OVS_WIN_NETDEV_ATTR_PORT_NO: 32-bit port number of the vport within the\n- * datapath.\n- * @OVS_WIN_NETDEV_ATTR_TYPE: 32-bit %OVS_VPORT_TYPE_* constant describing\n- * the type of vport.\n- * @OVS_WIN_NETDEV_ATTR_NAME: Name of vport. Maximum length %IFNAMSIZ-1 bytes\n- * plus a null terminator.\n- * @OVS_WIN_NETDEV_ATTR_MAC_ADDR: MAC address of the vport. %ETH_ADDR_LEN bytes\n- * long.\n- * @OVS_WIN_NETDEV_ATTR_MTU : 32-bit MTU of the vport.\n- * @OVS_WIN_NETDEV_ATTR_IF_FLAGS: 32-bit %OVS_WIN_NETDEV_IFF_* interface flags\n- * of the vport.\n- *\n- * These attributes follow the &struct ovs_header within the Generic Netlink\n- * payload for %OVS_WIN_NETDEV_* commands.\n- *\n- * For all requests, if %OVS_WIN_NETDEV_ATTR_NAME is specified then it is used\n- * to look up the netdev to operate on; dp_idx from the &struct\n- * ovs_header is not relevant for the look up.\n- */\n-enum ovs_win_netdev_attr {\n- OVS_WIN_NETDEV_ATTR_UNSPEC,\n- OVS_WIN_NETDEV_ATTR_PORT_NO, /* u32 port number within datapath. */\n- OVS_WIN_NETDEV_ATTR_TYPE, /* u32 OVS_NETDEV_TYPE_* constant. */\n- OVS_WIN_NETDEV_ATTR_NAME, /* string name, up to IFNAMSIZ bytes long. */\n- OVS_WIN_NETDEV_ATTR_MAC_ADDR, /* MAC address of the vport. */\n- OVS_WIN_NETDEV_ATTR_MTU, /* MTU of the vport. */\n- OVS_WIN_NETDEV_ATTR_IF_FLAGS, /* Interface flags o the vport. */\n- __OVS_WIN_NETDEV_ATTR_MAX\n-};\n-#define OVS_WIN_NETDEV_ATTR_MAX (__OVS_WIN_NETDEV_ATTR_MAX - 1)\n-\n-#define OVS_WIN_NETDEV_IFF_UP (1 << 0)\n-#define OVS_WIN_NETDEV_IFF_PROMISC (1 << 1)\n-\n-typedef struct ovs_dp_stats OVS_DP_STATS;\n-typedef enum ovs_vport_type OVS_VPORT_TYPE;\n-\n-/* NL Attributes for setting socket attributes */\n-enum ovs_nl_sock_attr {\n- /* (UINT32) Netlink Protocol set in Userspace and read in Kernel */\n- OVS_NL_ATTR_SOCK_PROTO,\n- /* (UINT32) Instance PID set in Kernel and read in Userspace */\n- OVS_NL_ATTR_SOCK_PID,\n- __OVS_NL_ATTR_SOCK_MAX\n-};\n-#define OVS_WIN_SOCK_ATTR_MAX (__OVS_NL_ATTR_SOCK_MAX - 1)\n-\n-#endif /* __OVS_DP_INTERFACE_EXT_H_ */\ndiff --git a/datapath-windows/include/automake.mk b/datapath-windows/include/automake.mk\ndeleted file mode 100644\nindex 185a06b03..000000000\n--- a/datapath-windows/include/automake.mk\n+++ /dev/null\n@@ -1,10 +0,0 @@\n-if WIN32\n-BUILT_SOURCES += $(srcdir)/datapath-windows/include/OvsDpInterface.h\n-endif\n-\n-$(srcdir)/datapath-windows/include/OvsDpInterface.h: \\\n- include/linux/openvswitch.h \\\n- build-aux/extract-odp-netlink-windows-dp-h\n-\t$(AM_V_GEN)sed -f $(srcdir)/build-aux/extract-odp-netlink-windows-dp-h < $< > $@\n-\n-CLEANFILES += $(srcdir)/datapath-windows/include/OvsDpInterface.h\ndiff --git a/datapath-windows/misc/DriverRecommendedRules.ruleset b/datapath-windows/misc/DriverRecommendedRules.ruleset\ndeleted file mode 100644\nindex 0faae599c..000000000\n--- a/datapath-windows/misc/DriverRecommendedRules.ruleset\n+++ /dev/null\n@@ -1,86 +0,0 @@\n-<?xml version=\"1.0\" encoding=\"utf-8\"?>\n-<RuleSet Name=\"Microsoft Driver Recommended Rules\" Description=\"This rule set contains rules recommended for drivers.\" ToolsVersion=\"10.0\">\n- <Include Path=\"NativeRecommendedRules.ruleset\" Action=\"Default\" />\n- <Rules AnalyzerId=\"Microsoft.Analyzers.NativeCodeAnalysis\" RuleNamespace=\"Microsoft.Rules.Native\">\n- <Rule Id=\"C28101\" Action=\"Warning\" />\n- <Rule Id=\"C28110\" Action=\"Warning\" />\n- <Rule Id=\"C28111\" Action=\"Warning\" />\n- <Rule Id=\"C28114\" Action=\"Warning\" />\n- <Rule Id=\"C28120\" Action=\"Warning\" />\n- <Rule Id=\"C28121\" Action=\"Warning\" />\n- <Rule Id=\"C28122\" Action=\"Warning\" />\n- <Rule Id=\"C28123\" Action=\"Warning\" />\n- <Rule Id=\"C28124\" Action=\"Warning\" />\n- <Rule Id=\"C28126\" Action=\"Warning\" />\n- <Rule Id=\"C28127\" Action=\"Warning\" />\n- <Rule Id=\"C28128\" Action=\"Warning\" />\n- <Rule Id=\"C28129\" Action=\"Warning\" />\n- <Rule Id=\"C28131\" Action=\"Warning\" />\n- <Rule Id=\"C28132\" Action=\"Warning\" />\n- <Rule Id=\"C28133\" Action=\"Warning\" />\n- <Rule Id=\"C28134\" Action=\"Warning\" />\n- <Rule Id=\"C28135\" Action=\"Warning\" />\n- <Rule Id=\"C28139\" Action=\"Warning\" />\n- <Rule Id=\"C28141\" Action=\"Warning\" />\n- <Rule Id=\"C28143\" Action=\"Warning\" />\n- <Rule Id=\"C28144\" Action=\"Warning\" />\n- <Rule Id=\"C28145\" Action=\"Warning\" />\n- <Rule Id=\"C28146\" Action=\"Warning\" />\n- <Rule Id=\"C28147\" Action=\"Warning\" />\n- <Rule Id=\"C28150\" Action=\"Warning\" />\n- <Rule Id=\"C28151\" Action=\"Warning\" />\n- <Rule Id=\"C28152\" Action=\"Warning\" />\n- <Rule Id=\"C28153\" Action=\"Warning\" />\n- <Rule Id=\"C28156\" Action=\"Warning\" />\n- <Rule Id=\"C28157\" Action=\"Warning\" />\n- <Rule Id=\"C28158\" Action=\"Warning\" />\n- <Rule Id=\"C28161\" Action=\"Warning\" />\n- <Rule Id=\"C28162\" Action=\"Warning\" />\n- <Rule Id=\"C28165\" Action=\"Warning\" />\n- <Rule Id=\"C28166\" Action=\"Warning\" />\n- <Rule Id=\"C28167\" Action=\"Warning\" />\n- <Rule Id=\"C28168\" Action=\"Warning\" />\n- <Rule Id=\"C28169\" Action=\"Warning\" />\n- <Rule Id=\"C28170\" Action=\"Warning\" />\n- <Rule Id=\"C28171\" Action=\"Warning\" />\n- <Rule Id=\"C28172\" Action=\"Warning\" />\n- <Rule Id=\"C28175\" Action=\"Warning\" />\n- <Rule Id=\"C28176\" Action=\"Warning\" />\n- <Rule Id=\"C28177\" Action=\"Warning\" />\n- <Rule Id=\"C28208\" Action=\"Warning\" />\n- <Rule Id=\"C28260\" Action=\"Warning\" />\n- <Rule Id=\"C28266\" Action=\"Warning\" />\n- <Rule Id=\"C28268\" Action=\"Warning\" />\n- <Rule Id=\"C28601\" Action=\"Warning\" />\n- <Rule Id=\"C28602\" Action=\"Warning\" />\n- <Rule Id=\"C28604\" Action=\"Warning\" />\n- <Rule Id=\"C28615\" Action=\"Warning\" />\n- <Rule Id=\"C28616\" Action=\"Warning\" />\n- <Rule Id=\"C28617\" Action=\"Warning\" />\n- <Rule Id=\"C28623\" Action=\"Warning\" />\n- <Rule Id=\"C28624\" Action=\"Warning\" />\n- <Rule Id=\"C28625\" Action=\"Warning\" />\n- <Rule Id=\"C28636\" Action=\"Warning\" />\n- <Rule Id=\"C28637\" Action=\"Warning\" />\n- <Rule Id=\"C28638\" Action=\"Warning\" />\n- <Rule Id=\"C28639\" Action=\"Warning\" />\n- <Rule Id=\"C28640\" Action=\"Warning\" />\n- <Rule Id=\"C28645\" Action=\"Warning\" />\n- <Rule Id=\"C28648\" Action=\"Warning\" />\n- <Rule Id=\"C28650\" Action=\"Warning\" />\n- <Rule Id=\"C28714\" Action=\"Warning\" />\n- <Rule Id=\"C28715\" Action=\"Warning\" />\n- <Rule Id=\"C28716\" Action=\"Warning\" />\n- <Rule Id=\"C28717\" Action=\"Warning\" />\n- <Rule Id=\"C28719\" Action=\"Warning\" />\n- <Rule Id=\"C28720\" Action=\"Warning\" />\n- <Rule Id=\"C28721\" Action=\"Warning\" />\n- <Rule Id=\"C28726\" Action=\"Warning\" />\n- <Rule Id=\"C28727\" Action=\"Warning\" />\n- <Rule Id=\"C28730\" Action=\"Warning\" />\n- <Rule Id=\"C28735\" Action=\"Warning\" />\n- <Rule Id=\"C28736\" Action=\"Warning\" />\n- <Rule Id=\"C28750\" Action=\"Warning\" />\n- <Rule Id=\"C28751\" Action=\"Warning\" />\n- </Rules>\n-</RuleSet>\ndiff --git a/datapath-windows/misc/OVS.psm1 b/datapath-windows/misc/OVS.psm1\ndeleted file mode 100644\nindex a8ffcaefd..000000000\n--- a/datapath-windows/misc/OVS.psm1\n+++ /dev/null\n@@ -1,210 +0,0 @@\n-<#\n-Copyright 2014, 2015 Cloudbase Solutions Srl\n-\n-Licensed under the Apache License, Version 2.0 (the \"License\");\n-you may not use this file except in compliance with the License.\n-You may obtain a copy of the License at\n-\n- http://www.apache.org/licenses/LICENSE-2.0\n-\n-Unless required by applicable law or agreed to in writing, software\n-distributed under the License is distributed on an \"AS IS\" BASIS,\n-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n-See the License for the specific language governing permissions and\n-limitations under the License.\n-#>\n-\n-$WMI_JOB_STATUS_STARTED = 4096\n-$WMI_JOB_STATE_RUNNING = 4\n-$WMI_JOB_STATE_COMPLETED = 7\n-\n-$hvassembly = [System.Reflection.Assembly]::LoadWithPartialName(\"Microsoft.HyperV.PowerShell\")\n-\n-function Set-VMNetworkAdapterOVSPort\n-{\n- [CmdletBinding()]\n- param\n- (\n- [parameter(Mandatory=$true, ValueFromPipeline=$true)]\n- [Microsoft.HyperV.PowerShell.VMNetworkAdapter]$VMNetworkAdapter,\n-\n- [parameter(Mandatory=$true)]\n- [ValidateLength(1, 48)]\n- [string]$OVSPortName\n- )\n- process\n- {\n- $ns = \"root\\virtualization\\v2\"\n- $EscapedId = $VMNetworkAdapter.Id.Replace('\\', '\\\\')\n-\n- $sd = gwmi -namespace $ns -class Msvm_EthernetPortAllocationSettingData -Filter \"ElementName = '$OVSPortName'\"\n- if($sd)\n- {\n- if($sd.InstanceId.Contains($VMNetworkAdapter.Id))\n- {\n- throw \"The OVS port name '$OVSPortName' is already assigned to this port.\"\n- }\n- throw \"Cannot assign the OVS port name '$OVSPortName' as it is already assigned to an other port.\"\n- }\n-\n- $sd = gwmi -namespace $ns -class Msvm_EthernetPortAllocationSettingData -Filter \"InstanceId like '$EscapedId%'\"\n-\n- if($sd)\n- {\n- $sd.ElementName = $OVSPortName\n-\n- $vsms = gwmi -namespace $ns -class Msvm_VirtualSystemManagementService\n- $retVal = $vsms.ModifyResourceSettings(@($sd.GetText(1)))\n- try\n- {\n- CheckWMIReturnValue $retVal\n- }\n- catch\n- {\n- throw \"Assigning OVS port '$OVSPortName' failed\"\n- }\n- }\n- }\n-}\n-\n-function Get-VMNetworkAdapterByOVSPort\n-{\n- [CmdletBinding()]\n- param\n- (\n-\n- [parameter(Mandatory=$true)]\n- [ValidateLength(1, 48)]\n- [string]$OVSPortName\n- )\n- process\n- {\n- $ns = \"root\\virtualization\\v2\"\n-\n- $sd = gwmi -namespace $ns -class Msvm_EthernetPortAllocationSettingData -Filter \"ElementName = '$OVSPortName'\"\n- if($sd)\n- {\n- return $sd\n- }\n- }\n-}\n-\n-function Get-VMByOVSPort\n-{\n- [CmdletBinding()]\n- param\n- (\n- [parameter(Mandatory=$true)]\n- [ValidateLength(1, 48)]\n- [string]$OVSPortName\n- )\n- process\n- {\n- $ns = \"root\\virtualization\\v2\"\n-\n- $vms = gwmi -namespace $ns -class Msvm_VirtualSystemSettingData\n- ForEach($vm in $vms)\n- {\n- $ports = gwmi -Namespace $ns -Query \"\n- Associators of {$vm} Where\n- ResultClass = Msvm_EthernetPortAllocationSettingData\"\n- if ($ports.ElementName -eq $OVSPortName)\n- {\n- return $vm\n- }\n- }\n- }\n-}\n-\n-#This function returns the Msvm_VirtualSystemSettingData given a VMName\n-function Get-VMNetworkAdapterWithOVSPort\n-{\n- [CmdletBinding()]\n- param\n- (\n- [parameter(Mandatory=$true)]\n- [ValidateLength(1, 1024)]\n- [string]$vmName\n- )\n- process\n- {\n- $ns = \"root\\virtualization\\v2\"\n- $vm = {}\n- $ports = {}\n-\n- $vm = gwmi -namespace $ns -class Msvm_VirtualSystemSettingData -Filter \"ElementName = '$VMName'\"\n-\n- $ports = gwmi -Namespace $ns -Query \"\n- Associators of {$vm} Where\n- ResultClass = Msvm_EthernetPortAllocationSettingData\"\n-\n- return $ports\n- }\n-}\n-\n-function CheckWMIReturnValue($retVal)\n-{\n- if ($retVal.ReturnValue -ne 0)\n- {\n- if ($retVal.ReturnValue -eq $WMI_JOB_STATUS_STARTED)\n- {\n- do\n- {\n- $job = [wmi]$retVal.Job\n- }\n- while ($job.JobState -eq $WMI_JOB_STATE_RUNNING)\n-\n- if ($job.JobState -ne $WMI_JOB_STATE_COMPLETED)\n- {\n- echo $job.ReturnValue\n- $errorString = \"Job Failed. Job State: \" + $job.JobState.ToString()\n- if ($job.__CLASS -eq \"Msvm_ConcreteJob\")\n- {\n- $errorString += \" Error Code: \" + $job.ErrorCode.ToString()\n- $errorString += \" Error Details: \" + $job.ErrorDescription\n- }\n- else\n- {\n- $error = $job.GetError()\n- if ($error.Error)\n- {\n- $errorString += \" Error:\" + $error.Error\n- }\n- }\n- throw $errorString\n- }\n- }\n- else\n- {\n- throw \"Job Failed. Return Value: {0}\" -f $job.ReturnValue\n- }\n- }\n-}\n-\n-function Set-VMNetworkAdapterOVSPortDirect\n-{\n- [CmdletBinding()]\n- param\n- (\n- [parameter(Mandatory=$true)]\n- [ValidateLength(1, 1024)]\n- [string]$vmName,\n-\n- [parameter(Mandatory=$true)]\n- [ValidateLength(1, 48)]\n- [string]$OVSPortName\n- )\n- process\n- {\n- $vnic = 0\n-\n- if ($vmName)\n- {\n- $vnic = Get-VMNetworkAdapter -VMName $vmName\n- }\n- # XXX the vnic index should be provided by the caller\n- $vnic[0] | Set-VMNetworkAdapterOVSPort -OVSPortName $OVSPortName\n- }\n-}\n-\n-Export-ModuleMember -function Set-*, Get-*\ndiff --git a/datapath-windows/misc/install.cmd b/datapath-windows/misc/install.cmd\ndeleted file mode 100644\nindex 797d1ef1f..000000000\n--- a/datapath-windows/misc/install.cmd\n+++ /dev/null\n@@ -1,4 +0,0 @@\n-netcfg -l .\\ovsext.inf -c s -i OVSExt\n-\n-net stop vmms\n-net start vmms\ndiff --git a/datapath-windows/misc/uninstall.cmd b/datapath-windows/misc/uninstall.cmd\ndeleted file mode 100644\nindex 68a04be61..000000000\n--- a/datapath-windows/misc/uninstall.cmd\n+++ /dev/null\n@@ -1 +0,0 @@\n-netcfg -u OVSExt\ndiff --git a/datapath-windows/ovsext.sln b/datapath-windows/ovsext.sln\ndeleted file mode 100644\nindex ab006e84f..000000000\n--- a/datapath-windows/ovsext.sln\n+++ /dev/null\n@@ -1,82 +0,0 @@\n-Microsoft Visual Studio Solution File, Format Version 12.00\n-# Visual Studio 2013\n-VisualStudioVersion = 12.0.31101.0\n-MinimumVisualStudioVersion = 10.0.40219.1\n-Project(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"Package\", \"Package\", \"{6BA8554E-AE50-49B0-9C98-4592447FEF8D}\"\n-EndProject\n-Project(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"OVSExt\", \"OVSExt\", \"{4A841675-477D-40A2-9CC6-128C3B8714F8}\"\n-EndProject\n-Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"package\", \"Package\\package.VcxProj\", \"{911D7389-3E61-449F-B8F3-14AD7EE9A0F2}\"\n-EndProject\n-Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"ovsext\", \"ovsext\\ovsext.vcxproj\", \"{63FE215D-98BE-4440-8081-C6160EFB80FA}\"\n-EndProject\n-Global\n-\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n-\t\tWin10Analyze|x64 = Win10Analyze|x64\n-\t\tWin10Debug|x64 = Win10Debug|x64\n-\t\tWin10Release|x64 = Win10Release|x64\n-\t\tWin8.1Analyze|x64 = Win8.1Analyze|x64\n-\t\tWin8.1Debug|x64 = Win8.1Debug|x64\n-\t\tWin8.1Release|x64 = Win8.1Release|x64\n-\t\tWin8Analyze|x64 = Win8Analyze|x64\n-\t\tWin8Debug|x64 = Win8Debug|x64\n-\t\tWin8Release|x64 = Win8Release|x64\n-\tEndGlobalSection\n-\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n-\t\t{911D7389-3E61-449F-B8F3-14AD7EE9A0F2}.Win10Analyze|x64.ActiveCfg = Win10Analyze|x64\n-\t\t{911D7389-3E61-449F-B8F3-14AD7EE9A0F2}.Win10Analyze|x64.Build.0 = Win10Analyze|x64\n-\t\t{911D7389-3E61-449F-B8F3-14AD7EE9A0F2}.Win10Debug|x64.ActiveCfg = Win10 Debug|x64\n-\t\t{911D7389-3E61-449F-B8F3-14AD7EE9A0F2}.Win10Debug|x64.Build.0 = Win10 Debug|x64\n-\t\t{911D7389-3E61-449F-B8F3-14AD7EE9A0F2}.Win10Debug|x64.Deploy.0 = Win10 Debug|x64\n-\t\t{911D7389-3E61-449F-B8F3-14AD7EE9A0F2}.Win10Release|x64.ActiveCfg = Win10 Release|x64\n-\t\t{911D7389-3E61-449F-B8F3-14AD7EE9A0F2}.Win10Release|x64.Build.0 = Win10 Release|x64\n-\t\t{911D7389-3E61-449F-B8F3-14AD7EE9A0F2}.Win10Release|x64.Deploy.0 = Win10 Release|x64\n-\t\t{911D7389-3E61-449F-B8F3-14AD7EE9A0F2}.Win8.1Analyze|x64.ActiveCfg = Win8.1Analyze|x64\n-\t\t{911D7389-3E61-449F-B8F3-14AD7EE9A0F2}.Win8.1Analyze|x64.Build.0 = Win8.1Analyze|x64\n-\t\t{911D7389-3E61-449F-B8F3-14AD7EE9A0F2}.Win8.1Analyze|x64.Deploy.0 = Win8.1Analyze|x64\n-\t\t{911D7389-3E61-449F-B8F3-14AD7EE9A0F2}.Win8.1Debug|x64.ActiveCfg = Win8.1 Debug|x64\n-\t\t{911D7389-3E61-449F-B8F3-14AD7EE9A0F2}.Win8.1Debug|x64.Build.0 = Win8.1 Debug|x64\n-\t\t{911D7389-3E61-449F-B8F3-14AD7EE9A0F2}.Win8.1Release|x64.ActiveCfg = Win8.1 Release|x64\n-\t\t{911D7389-3E61-449F-B8F3-14AD7EE9A0F2}.Win8.1Release|x64.Build.0 = Win8.1 Release|x64\n-\t\t{911D7389-3E61-449F-B8F3-14AD7EE9A0F2}.Win8Analyze|x64.ActiveCfg = Win8Analyze|x64\n-\t\t{911D7389-3E61-449F-B8F3-14AD7EE9A0F2}.Win8Analyze|x64.Build.0 = Win8Analyze|x64\n-\t\t{911D7389-3E61-449F-B8F3-14AD7EE9A0F2}.Win8Analyze|x64.Deploy.0 = Win8Analyze|x64\n-\t\t{911D7389-3E61-449F-B8F3-14AD7EE9A0F2}.Win8Debug|x64.ActiveCfg = Win8 Debug|x64\n-\t\t{911D7389-3E61-449F-B8F3-14AD7EE9A0F2}.Win8Debug|x64.Build.0 = Win8 Debug|x64\n-\t\t{911D7389-3E61-449F-B8F3-14AD7EE9A0F2}.Win8Release|x64.ActiveCfg = Win8 Release|x64\n-\t\t{911D7389-3E61-449F-B8F3-14AD7EE9A0F2}.Win8Release|x64.Build.0 = Win8 Release|x64\n-\t\t{63FE215D-98BE-4440-8081-C6160EFB80FA}.Win10Analyze|x64.ActiveCfg = Win10Analyze|x64\n-\t\t{63FE215D-98BE-4440-8081-C6160EFB80FA}.Win10Analyze|x64.Build.0 = Win10Analyze|x64\n-\t\t{63FE215D-98BE-4440-8081-C6160EFB80FA}.Win10Debug|x64.ActiveCfg = Win10 Debug|x64\n-\t\t{63FE215D-98BE-4440-8081-C6160EFB80FA}.Win10Debug|x64.Build.0 = Win10 Debug|x64\n-\t\t{63FE215D-98BE-4440-8081-C6160EFB80FA}.Win10Debug|x64.Deploy.0 = Win10 Debug|x64\n-\t\t{63FE215D-98BE-4440-8081-C6160EFB80FA}.Win10Release|x64.ActiveCfg = Win10 Release|x64\n-\t\t{63FE215D-98BE-4440-8081-C6160EFB80FA}.Win10Release|x64.Build.0 = Win10 Release|x64\n-\t\t{63FE215D-98BE-4440-8081-C6160EFB80FA}.Win10Release|x64.Deploy.0 = Win10 Release|x64\n-\t\t{63FE215D-98BE-4440-8081-C6160EFB80FA}.Win8.1Analyze|x64.ActiveCfg = Win8.1Analyze|x64\n-\t\t{63FE215D-98BE-4440-8081-C6160EFB80FA}.Win8.1Analyze|x64.Build.0 = Win8.1Analyze|x64\n-\t\t{63FE215D-98BE-4440-8081-C6160EFB80FA}.Win8.1Analyze|x64.Deploy.0 = Win8.1Analyze|x64\n-\t\t{63FE215D-98BE-4440-8081-C6160EFB80FA}.Win8.1Debug|x64.ActiveCfg = Win8.1 Debug|x64\n-\t\t{63FE215D-98BE-4440-8081-C6160EFB80FA}.Win8.1Debug|x64.Build.0 = Win8.1 Debug|x64\n-\t\t{63FE215D-98BE-4440-8081-C6160EFB80FA}.Win8.1Debug|x64.Deploy.0 = Win8.1 Debug|x64\n-\t\t{63FE215D-98BE-4440-8081-C6160EFB80FA}.Win8.1Release|x64.ActiveCfg = Win8.1 Release|x64\n-\t\t{63FE215D-98BE-4440-8081-C6160EFB80FA}.Win8.1Release|x64.Build.0 = Win8.1 Release|x64\n-\t\t{63FE215D-98BE-4440-8081-C6160EFB80FA}.Win8.1Release|x64.Deploy.0 = Win8.1 Release|x64\n-\t\t{63FE215D-98BE-4440-8081-C6160EFB80FA}.Win8Analyze|x64.ActiveCfg = Win8Analyze|x64\n-\t\t{63FE215D-98BE-4440-8081-C6160EFB80FA}.Win8Analyze|x64.Build.0 = Win8Analyze|x64\n-\t\t{63FE215D-98BE-4440-8081-C6160EFB80FA}.Win8Analyze|x64.Deploy.0 = Win8Analyze|x64\n-\t\t{63FE215D-98BE-4440-8081-C6160EFB80FA}.Win8Debug|x64.ActiveCfg = Win8 Debug|x64\n-\t\t{63FE215D-98BE-4440-8081-C6160EFB80FA}.Win8Debug|x64.Build.0 = Win8 Debug|x64\n-\t\t{63FE215D-98BE-4440-8081-C6160EFB80FA}.Win8Debug|x64.Deploy.0 = Win8 Debug|x64\n-\t\t{63FE215D-98BE-4440-8081-C6160EFB80FA}.Win8Release|x64.ActiveCfg = Win8 Release|x64\n-\t\t{63FE215D-98BE-4440-8081-C6160EFB80FA}.Win8Release|x64.Build.0 = Win8 Release|x64\n-\t\t{63FE215D-98BE-4440-8081-C6160EFB80FA}.Win8Release|x64.Deploy.0 = Win8 Release|x64\n-\tEndGlobalSection\n-\tGlobalSection(SolutionProperties) = preSolution\n-\t\tHideSolutionNode = FALSE\n-\tEndGlobalSection\n-\tGlobalSection(NestedProjects) = preSolution\n-\t\t{911D7389-3E61-449F-B8F3-14AD7EE9A0F2} = {6BA8554E-AE50-49B0-9C98-4592447FEF8D}\n-\t\t{63FE215D-98BE-4440-8081-C6160EFB80FA} = {4A841675-477D-40A2-9CC6-128C3B8714F8}\n-\tEndGlobalSection\n-EndGlobal\ndiff --git a/datapath-windows/ovsext/Actions.c b/datapath-windows/ovsext/Actions.c\ndeleted file mode 100644\nindex 36b74df73..000000000\n--- a/datapath-windows/ovsext/Actions.c\n+++ /dev/null\n@@ -1,2690 +0,0 @@\n-/*\n- * Copyright (c) 2014, 2016 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#include \"precomp.h\"\n-\n-#include \"Actions.h\"\n-#include \"Conntrack.h\"\n-#include \"Debug.h\"\n-#include \"Event.h\"\n-#include \"Flow.h\"\n-#include \"Gre.h\"\n-#include \"Jhash.h\"\n-#include \"Meter.h\"\n-#include \"Mpls.h\"\n-#include \"NetProto.h\"\n-#include \"Offload.h\"\n-#include \"PacketIO.h\"\n-#include \"Recirc.h\"\n-#include \"Switch.h\"\n-#include \"User.h\"\n-#include \"Vport.h\"\n-#include \"Vxlan.h\"\n-#include \"Geneve.h\"\n-#include \"IpFragment.h\"\n-\n-#ifdef OVS_DBG_MOD\n-#undef OVS_DBG_MOD\n-#endif\n-#define OVS_DBG_MOD OVS_DBG_ACTION\n-\n-#define OVS_DEST_PORTS_ARRAY_MIN_SIZE 2\n-\n-typedef struct _OVS_ACTION_STATS {\n- UINT64 rxGre;\n- UINT64 txGre;\n- UINT64 rxVxlan;\n- UINT64 txVxlan;\n- UINT64 rxGeneve;\n- UINT64 txGeneve;\n- UINT64 flowMiss;\n- UINT64 flowUserspace;\n- UINT64 txTcp;\n- UINT32 failedFlowMiss;\n- UINT32 noVport;\n- UINT32 failedFlowExtract;\n- UINT32 noResource;\n- UINT32 noCopiedNbl;\n- UINT32 failedEncap;\n- UINT32 failedDecap;\n- UINT32 cannotGrowDest;\n- UINT32 zeroActionLen;\n- UINT32 failedChecksum;\n- UINT32 deferredActionsQueueFull;\n- UINT32 deferredActionsExecLimit;\n-} OVS_ACTION_STATS, *POVS_ACTION_STATS;\n-\n-OVS_ACTION_STATS ovsActionStats;\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsInitForwardingCtx --\n- * Function to init/re-init the 'ovsFwdCtx' context as the actions pipeline\n- * is being executed.\n- *\n- * Result:\n- * NDIS_STATUS_SUCCESS on success\n- * Other NDIS_STATUS upon failure. Upon failure, it is safe to call\n- * OvsCompleteNBLForwardingCtx(), since 'ovsFwdCtx' has been initialized\n- * enough for OvsCompleteNBLForwardingCtx() to do its work.\n- * --------------------------------------------------------------------------\n- */\n-static __inline NDIS_STATUS\n-OvsInitForwardingCtx(OvsForwardingContext *ovsFwdCtx,\n- POVS_SWITCH_CONTEXT switchContext,\n- PNET_BUFFER_LIST curNbl,\n- UINT32 srcVportNo,\n- ULONG sendFlags,\n- PNDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO fwdDetail,\n- OvsCompletionList *completionList,\n- OVS_PACKET_HDR_INFO *layers,\n- BOOLEAN resetTunnelInfo)\n-{\n- ASSERT(ovsFwdCtx);\n- ASSERT(switchContext);\n- ASSERT(curNbl);\n- ASSERT(fwdDetail);\n-\n- /*\n- * Set values for curNbl and switchContext so upon failures, we have enough\n- * information to do cleanup.\n- */\n- ovsFwdCtx->curNbl = curNbl;\n- ovsFwdCtx->switchContext = switchContext;\n- ovsFwdCtx->completionList = completionList;\n- ovsFwdCtx->fwdDetail = fwdDetail;\n-\n- if (fwdDetail->NumAvailableDestinations > 0) {\n- /*\n- * XXX: even though MSDN says GetNetBufferListDestinations() returns\n- * NDIS_STATUS, the header files say otherwise.\n- */\n- switchContext->NdisSwitchHandlers.GetNetBufferListDestinations(\n- switchContext->NdisSwitchContext, curNbl,\n- &ovsFwdCtx->destinationPorts);\n-\n- ASSERT(ovsFwdCtx->destinationPorts);\n- /* Ensure that none of the elements are consumed yet. */\n- ASSERT(ovsFwdCtx->destinationPorts->NumElements ==\n- fwdDetail->NumAvailableDestinations);\n- } else {\n- ovsFwdCtx->destinationPorts = NULL;\n- }\n- ovsFwdCtx->destPortsSizeIn = fwdDetail->NumAvailableDestinations;\n- ovsFwdCtx->destPortsSizeOut = 0;\n- ovsFwdCtx->srcVportNo = srcVportNo;\n- ovsFwdCtx->sendFlags = sendFlags;\n- if (layers) {\n- ovsFwdCtx->layers = *layers;\n- } else {\n- RtlZeroMemory(&ovsFwdCtx->layers, sizeof ovsFwdCtx->layers);\n- }\n- if (resetTunnelInfo) {\n- ovsFwdCtx->tunnelTxNic = NULL;\n- ovsFwdCtx->tunnelRxNic = NULL;\n- RtlZeroMemory(&ovsFwdCtx->tunKey, sizeof ovsFwdCtx->tunKey);\n- }\n-\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsDoFragmentNbl --\n- * Utility function to Fragment nbl based on mru.\n- * --------------------------------------------------------------------------\n- */\n-static __inline VOID\n-OvsDoFragmentNbl(OvsForwardingContext *ovsFwdCtx, UINT16 mru)\n-{\n- PNET_BUFFER_LIST fragNbl = NULL;\n- fragNbl = OvsFragmentNBL(ovsFwdCtx->switchContext,\n- ovsFwdCtx->curNbl,\n- &(ovsFwdCtx->layers),\n- mru, 0, TRUE);\n-\n- if (fragNbl != NULL) {\n- OvsCompleteNBL(ovsFwdCtx->switchContext, ovsFwdCtx->curNbl, TRUE);\n- ovsFwdCtx->curNbl = fragNbl;\n- } else {\n- OVS_LOG_INFO(\"Fragment NBL failed for MRU = %u\", mru);\n- }\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsDetectTunnelRxPkt --\n- * Utility function for an RX packet to detect its tunnel type.\n- *\n- * Result:\n- * True - if the tunnel type was detected.\n- * False - if not a tunnel packet or tunnel type not supported.\n- * --------------------------------------------------------------------------\n- */\n-static __inline BOOLEAN\n-OvsDetectTunnelRxPkt(OvsForwardingContext *ovsFwdCtx,\n- const OvsFlowKey *flowKey)\n-{\n- POVS_VPORT_ENTRY tunnelVport = NULL;\n-\n- /* XXX: we should also check for the length of the UDP payload to pick\n- * packets only if they are at least VXLAN header size.\n- */\n-\n- /*\n- * For some of the tunnel types such as GRE, the dstPort is not applicable\n- * since GRE does not have a L4 port. We use '0' for convenience.\n- */\n-\n- if ((flowKey->l2.dlType == htons(ETH_TYPE_IPV4) &&\n- !flowKey->ipKey.nwFrag) ||\n- (flowKey->l2.dlType == htons(ETH_TYPE_IPV6) &&\n- !flowKey->ipv6Key.nwFrag)) {\n- UINT16 dstPort = 0;\n- uint8_t nwProto = 0;\n- if (flowKey->l2.dlType == htons(ETH_TYPE_IPV6)) {\n- dstPort = htons(flowKey->ipv6Key.l4.tpDst);\n- nwProto = flowKey->ipv6Key.nwProto;\n- } else if (flowKey->l2.dlType == htons(ETH_TYPE_IPV4)) {\n- dstPort = htons(flowKey->ipKey.l4.tpDst);\n- nwProto = flowKey->ipKey.nwProto;\n- }\n- ASSERT(nwProto != IPPROTO_GRE || dstPort == 0);\n-\n- tunnelVport =\n- OvsFindTunnelVportByDstPortAndNWProto(ovsFwdCtx->switchContext,\n- dstPort, nwProto);\n- if (tunnelVport) {\n- switch(tunnelVport->ovsType) {\n- case OVS_VPORT_TYPE_VXLAN:\n- ovsActionStats.rxVxlan++;\n- break;\n- case OVS_VPORT_TYPE_GENEVE:\n- ovsActionStats.rxGeneve++;\n- break;\n- case OVS_VPORT_TYPE_GRE:\n- ovsActionStats.rxGre++;\n- break;\n- }\n- }\n- }\n-\n- // We might get tunnel packets even before the tunnel gets initialized.\n- if (tunnelVport) {\n- ASSERT(ovsFwdCtx->tunnelRxNic == NULL);\n- ovsFwdCtx->tunnelRxNic = tunnelVport;\n- return TRUE;\n- }\n-\n- return FALSE;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsDetectTunnelPkt --\n- * Utility function to detect if a packet is to be subjected to\n- * tunneling (Tx) or de-tunneling (Rx). Various factors such as source\n- * port, destination port, packet contents, and previously setup tunnel\n- * context are used.\n- *\n- * Result:\n- * True - If the packet is to be subjected to tunneling.\n- * In case of invalid tunnel context, the tunneling functionality is\n- * a no-op and is completed within this function itself by consuming\n- * all of the tunneling context.\n- * False - If not a tunnel packet or tunnel type not supported. Caller should\n- * process the packet as a non-tunnel packet.\n- * --------------------------------------------------------------------------\n- */\n-static __inline BOOLEAN\n-OvsDetectTunnelPkt(OvsForwardingContext *ovsFwdCtx,\n- const POVS_VPORT_ENTRY dstVport,\n- const OvsFlowKey *flowKey)\n-{\n- if (OvsIsInternalVportType(dstVport->ovsType)) {\n- /*\n- * Rx:\n- * The source of NBL during tunneling Rx could be the external\n- * port or if it is being executed from userspace, the source port is\n- * default port.\n- */\n- BOOLEAN validSrcPort =\n- (OvsIsExternalVportByPortId(ovsFwdCtx->switchContext,\n- ovsFwdCtx->fwdDetail->SourcePortId)) ||\n- (ovsFwdCtx->fwdDetail->SourcePortId ==\n- NDIS_SWITCH_DEFAULT_PORT_ID);\n-\n- if (validSrcPort && OvsDetectTunnelRxPkt(ovsFwdCtx, flowKey)) {\n- ASSERT(ovsFwdCtx->tunnelTxNic == NULL);\n- ASSERT(ovsFwdCtx->tunnelRxNic != NULL);\n- return TRUE;\n- }\n- } else if (OvsIsTunnelVportType(dstVport->ovsType)) {\n- ASSERT(ovsFwdCtx->tunnelRxNic == NULL);\n-\n- /*\n- * Tx:\n- * The destination port is a tunnel port. Encapsulation must be\n- * performed only on packets that originate from:\n- * - a VIF port\n- * - a bridge-internal port (packets generated from userspace)\n- * - no port.\n- * - tunnel port\n- * If the packet will not be encapsulated, consume the tunnel context\n- * by clearing it.\n- */\n- if (ovsFwdCtx->srcVportNo != OVS_DPPORT_NUMBER_INVALID) {\n-\n- POVS_VPORT_ENTRY vport = OvsFindVportByPortNo(\n- ovsFwdCtx->switchContext, ovsFwdCtx->srcVportNo);\n-\n- if (!vport ||\n- (vport->ovsType != OVS_VPORT_TYPE_NETDEV &&\n- vport->ovsType != OVS_VPORT_TYPE_INTERNAL &&\n- !OvsIsTunnelVportType(vport->ovsType))) {\n- RtlZeroMemory(&ovsFwdCtx->tunKey.dst, sizeof(ovsFwdCtx->tunKey.dst));\n- }\n- }\n-\n- /* Tunnel the packet only if tunnel context is set. */\n- if (!OvsIphIsZero(&(ovsFwdCtx->tunKey.dst))) {\n- switch(dstVport->ovsType) {\n- case OVS_VPORT_TYPE_GRE:\n- ovsActionStats.txGre++;\n- break;\n- case OVS_VPORT_TYPE_VXLAN:\n- ovsActionStats.txVxlan++;\n- break;\n- case OVS_VPORT_TYPE_GENEVE:\n- ovsActionStats.txGeneve++;\n- break;\n- }\n- ovsFwdCtx->tunnelTxNic = dstVport;\n- }\n-\n- return TRUE;\n- }\n-\n- return FALSE;\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsAddPorts --\n- * Add the specified destination vport into the forwarding context. If the\n- * vport is a VIF/external port, it is added directly to the NBL. If it is\n- * a tunneling port, it is NOT added to the NBL.\n- *\n- * Result:\n- * NDIS_STATUS_SUCCESS on success\n- * Other NDIS_STATUS upon failure.\n- * --------------------------------------------------------------------------\n- */\n-static __inline NDIS_STATUS\n-OvsAddPorts(OvsForwardingContext *ovsFwdCtx,\n- OvsFlowKey *flowKey,\n- NDIS_SWITCH_PORT_ID dstPortId,\n- BOOLEAN preserveVLAN,\n- BOOLEAN preservePriority)\n-{\n- POVS_VPORT_ENTRY vport;\n- PNDIS_SWITCH_PORT_DESTINATION fwdPort;\n- NDIS_STATUS status;\n- POVS_SWITCH_CONTEXT switchContext = ovsFwdCtx->switchContext;\n-\n- /*\n- * We hold the dispatch lock that protects the list of vports, so vports\n- * validated here can be added as destinations safely before we call into\n- * NDIS.\n- *\n- * Some of the vports can be tunnelled ports as well in which case\n- * they should be added to a separate list of tunnelled destination ports\n- * instead of the VIF ports. The context for the tunnel is settable\n- * in OvsForwardingContext.\n- */\n- vport = OvsFindVportByPortNo(ovsFwdCtx->switchContext, dstPortId);\n- if (vport == NULL || vport->ovsState != OVS_STATE_CONNECTED) {\n- /*\n- * There may be some latency between a port disappearing, and userspace\n- * updating the recalculated flows. In the meantime, handle invalid\n- * ports gracefully.\n- */\n- ovsActionStats.noVport++;\n- return NDIS_STATUS_SUCCESS;\n- }\n- ASSERT(vport->nicState == NdisSwitchNicStateConnected);\n- vport->stats.txPackets++;\n- vport->stats.txBytes +=\n- NET_BUFFER_DATA_LENGTH(NET_BUFFER_LIST_FIRST_NB(ovsFwdCtx->curNbl));\n-\n- if (OvsDetectTunnelPkt(ovsFwdCtx, vport, flowKey)) {\n- return NDIS_STATUS_SUCCESS;\n- }\n-\n- if (ovsFwdCtx->destPortsSizeOut == ovsFwdCtx->destPortsSizeIn) {\n- if (ovsFwdCtx->destPortsSizeIn == 0) {\n- ASSERT(ovsFwdCtx->destinationPorts == NULL);\n- ASSERT(ovsFwdCtx->fwdDetail->NumAvailableDestinations == 0);\n- status =\n- switchContext->NdisSwitchHandlers.GrowNetBufferListDestinations(\n- switchContext->NdisSwitchContext, ovsFwdCtx->curNbl,\n- OVS_DEST_PORTS_ARRAY_MIN_SIZE,\n- &ovsFwdCtx->destinationPorts);\n- if (status != NDIS_STATUS_SUCCESS) {\n- ovsActionStats.cannotGrowDest++;\n- return status;\n- }\n- ovsFwdCtx->destPortsSizeIn =\n- ovsFwdCtx->fwdDetail->NumAvailableDestinations;\n- ASSERT(ovsFwdCtx->destinationPorts);\n- } else {\n- ASSERT(ovsFwdCtx->destinationPorts != NULL);\n- /*\n- * NumElements:\n- * A ULONG value that specifies the total number of\n- * NDIS_SWITCH_PORT_DESTINATION elements in the\n- * NDIS_SWITCH_FORWARDING_DESTINATION_ARRAY structure.\n- *\n- * NumDestinations:\n- * A ULONG value that specifies the number of\n- * NDIS_SWITCH_PORT_DESTINATION elements in the\n- * NDIS_SWITCH_FORWARDING_DESTINATION_ARRAY structure that\n- * specify port destinations.\n- *\n- * NumAvailableDestinations:\n- * A value that specifies the number of unused extensible switch\n- * destination ports elements within an NET_BUFFER_LIST structure.\n- */\n- ASSERT(ovsFwdCtx->destinationPorts->NumElements ==\n- ovsFwdCtx->destPortsSizeIn);\n- ASSERT(ovsFwdCtx->destinationPorts->NumDestinations ==\n- ovsFwdCtx->destPortsSizeOut -\n- ovsFwdCtx->fwdDetail->NumAvailableDestinations);\n- ASSERT(ovsFwdCtx->fwdDetail->NumAvailableDestinations > 0);\n- /*\n- * Before we grow the array of destination ports, the current set\n- * of ports needs to be committed. Only the ports added since the\n- * last commit need to be part of the new update.\n- */\n- status = switchContext->NdisSwitchHandlers.UpdateNetBufferListDestinations(\n- switchContext->NdisSwitchContext, ovsFwdCtx->curNbl,\n- ovsFwdCtx->fwdDetail->NumAvailableDestinations,\n- ovsFwdCtx->destinationPorts);\n- if (status != NDIS_STATUS_SUCCESS) {\n- ovsActionStats.cannotGrowDest++;\n- return status;\n- }\n- ASSERT(ovsFwdCtx->destinationPorts->NumElements ==\n- ovsFwdCtx->destPortsSizeIn);\n- ASSERT(ovsFwdCtx->destinationPorts->NumDestinations ==\n- ovsFwdCtx->destPortsSizeOut);\n- ASSERT(ovsFwdCtx->fwdDetail->NumAvailableDestinations == 0);\n-\n- status = switchContext->NdisSwitchHandlers.GrowNetBufferListDestinations(\n- switchContext->NdisSwitchContext, ovsFwdCtx->curNbl,\n- ovsFwdCtx->destPortsSizeIn, &ovsFwdCtx->destinationPorts);\n- if (status != NDIS_STATUS_SUCCESS) {\n- ovsActionStats.cannotGrowDest++;\n- return status;\n- }\n- ASSERT(ovsFwdCtx->destinationPorts != NULL);\n- ovsFwdCtx->destPortsSizeIn <<= 1;\n- }\n- }\n-\n- ASSERT(ovsFwdCtx->destPortsSizeOut < ovsFwdCtx->destPortsSizeIn);\n- fwdPort =\n- NDIS_SWITCH_PORT_DESTINATION_AT_ARRAY_INDEX(ovsFwdCtx->destinationPorts,\n- ovsFwdCtx->destPortsSizeOut);\n-\n- fwdPort->PortId = vport->portId;\n- fwdPort->NicIndex = vport->nicIndex;\n- fwdPort->IsExcluded = 0;\n- fwdPort->PreserveVLAN = preserveVLAN;\n- fwdPort->PreservePriority = preservePriority;\n- ovsFwdCtx->destPortsSizeOut += 1;\n-\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsClearTunTxCtx --\n- * Utility function to clear tx tunneling context.\n- * --------------------------------------------------------------------------\n- */\n-static __inline VOID\n-OvsClearTunTxCtx(OvsForwardingContext *ovsFwdCtx)\n-{\n- ovsFwdCtx->tunnelTxNic = NULL;\n- RtlZeroMemory(&ovsFwdCtx->tunKey.dst, sizeof(ovsFwdCtx->tunKey.dst));\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsClearTunRxCtx --\n- * Utility function to clear rx tunneling context.\n- * --------------------------------------------------------------------------\n- */\n-static __inline VOID\n-OvsClearTunRxCtx(OvsForwardingContext *ovsFwdCtx)\n-{\n- ovsFwdCtx->tunnelRxNic = NULL;\n- RtlZeroMemory(&ovsFwdCtx->tunKey.dst, sizeof(ovsFwdCtx->tunKey.dst));\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsCompleteNBLForwardingCtx --\n- * This utility function is responsible for freeing/completing an NBL - either\n- * by adding it to a completion list or by freeing it.\n- *\n- * Side effects:\n- * It also resets the necessary fields in 'ovsFwdCtx'.\n- * --------------------------------------------------------------------------\n- */\n-static __inline VOID\n-OvsCompleteNBLForwardingCtx(OvsForwardingContext *ovsFwdCtx,\n- PCWSTR dropReason)\n-{\n- NDIS_STRING filterReason;\n-\n- RtlInitUnicodeString(&filterReason, dropReason);\n- if (ovsFwdCtx->completionList) {\n- OvsAddPktCompletionList(ovsFwdCtx->completionList, TRUE,\n- ovsFwdCtx->fwdDetail->SourcePortId, ovsFwdCtx->curNbl, 1,\n- &filterReason);\n- ovsFwdCtx->curNbl = NULL;\n- } else {\n- /* If there is no completionList, we assume this is ovs created NBL */\n- ovsFwdCtx->curNbl = OvsCompleteNBL(ovsFwdCtx->switchContext,\n- ovsFwdCtx->curNbl, TRUE);\n- ASSERT(ovsFwdCtx->curNbl == NULL);\n- }\n- /* XXX: these can be made debug only to save cycles. Ideally the pipeline\n- * using these fields should reset the values at the end of the pipeline. */\n- ovsFwdCtx->destPortsSizeOut = 0;\n- ovsFwdCtx->tunnelTxNic = NULL;\n- ovsFwdCtx->tunnelRxNic = NULL;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsDoFlowLookupOutput --\n- * Function to be used for the second stage of a tunneling workflow, ie.:\n- * - On the encapsulated packet on Tx path, to do a flow extract, flow\n- * lookup and excuting the actions.\n- * - On the decapsulated packet on Rx path, to do a flow extract, flow\n- * lookup and excuting the actions.\n- *\n- * XXX: It is assumed that the NBL in 'ovsFwdCtx' is owned by OVS. This is\n- * until the new buffer management framework is adopted.\n- *\n- * Side effects:\n- * The NBL in 'ovsFwdCtx' is consumed.\n- * --------------------------------------------------------------------------\n- */\n-static __inline NDIS_STATUS\n-OvsDoFlowLookupOutput(OvsForwardingContext* ovsFwdCtx)\n-{\n- OvsFlowKey key = { 0 };\n- OvsFlow *flow = NULL;\n- UINT64 hash = 0;\n- NDIS_STATUS status = NDIS_STATUS_SUCCESS;\n- POVS_VPORT_ENTRY vport =\n- OvsFindVportByPortNo(ovsFwdCtx->switchContext, ovsFwdCtx->srcVportNo);\n- if (vport == NULL || vport->ovsState != OVS_STATE_CONNECTED) {\n- OvsCompleteNBLForwardingCtx(ovsFwdCtx,\n- L\"OVS-Dropped due to internal/tunnel port removal\");\n- ovsActionStats.noVport++;\n- return NDIS_STATUS_SUCCESS;\n- }\n- ASSERT(vport->nicState == NdisSwitchNicStateConnected);\n-\n- /* Assert that in the Rx direction, key is always setup. */\n- ASSERT(ovsFwdCtx->tunnelRxNic == NULL || !OvsIphIsZero(&(ovsFwdCtx->tunKey.dst)));\n- status =\n- OvsExtractFlow(ovsFwdCtx->curNbl, ovsFwdCtx->srcVportNo,\n- &key, &ovsFwdCtx->layers,\n- !OvsIphIsZero(&(ovsFwdCtx->tunKey.dst))? &(ovsFwdCtx->tunKey):NULL);\n- if (status != NDIS_STATUS_SUCCESS) {\n- OvsCompleteNBLForwardingCtx(ovsFwdCtx,\n- L\"OVS-Flow extract failed\");\n- ovsActionStats.failedFlowExtract++;\n- return status;\n- }\n-\n- flow = OvsLookupFlow(&ovsFwdCtx->switchContext->datapath, &key, &hash, FALSE);\n- if (flow) {\n- OvsFlowUsed(flow, ovsFwdCtx->curNbl, &ovsFwdCtx->layers);\n- ovsFwdCtx->switchContext->datapath.hits++;\n- status = OvsDoExecuteActions(ovsFwdCtx->switchContext,\n- ovsFwdCtx->completionList,\n- ovsFwdCtx->curNbl,\n- ovsFwdCtx->srcVportNo,\n- ovsFwdCtx->sendFlags,\n- &key, &hash, &ovsFwdCtx->layers,\n- flow->actions, flow->actionsLen);\n- ovsFwdCtx->curNbl = NULL;\n- } else {\n- LIST_ENTRY missedPackets;\n- UINT32 num = 0;\n- ovsFwdCtx->switchContext->datapath.misses++;\n- InitializeListHead(&missedPackets);\n- status = OvsCreateAndAddPackets(NULL, 0, OVS_PACKET_CMD_MISS, vport,\n- &key,ovsFwdCtx->curNbl,\n- FALSE, &ovsFwdCtx->layers,\n- ovsFwdCtx->switchContext, &missedPackets, &num);\n- if (num) {\n- OvsQueuePackets(&missedPackets, num);\n- }\n- if (status == NDIS_STATUS_SUCCESS) {\n- /* Complete the packet since it was copied to user buffer. */\n- OvsCompleteNBLForwardingCtx(ovsFwdCtx,\n- L\"OVS-Dropped since packet was copied to userspace\");\n- ovsActionStats.flowMiss++;\n- status = NDIS_STATUS_SUCCESS;\n- } else {\n- OvsCompleteNBLForwardingCtx(ovsFwdCtx,\n- L\"OVS-Dropped due to failure to queue to userspace\");\n- status = NDIS_STATUS_FAILURE;\n- ovsActionStats.failedFlowMiss++;\n- }\n- }\n-\n- return status;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsTunnelPortTx --\n- * The start function for Tx tunneling - encapsulates the packet, and\n- * outputs the packet on the PIF bridge.\n- *\n- * Side effects:\n- * The NBL in 'ovsFwdCtx' is consumed.\n- * --------------------------------------------------------------------------\n- */\n-static __inline NDIS_STATUS\n-OvsTunnelPortTx(OvsForwardingContext *ovsFwdCtx)\n-{\n- NDIS_STATUS status = NDIS_STATUS_FAILURE;\n- PNET_BUFFER_LIST newNbl = NULL;\n- UINT32 srcVportNo;\n- NDIS_SWITCH_NIC_INDEX srcNicIndex;\n- NDIS_SWITCH_PORT_ID srcPortId;\n- POVS_BUFFER_CONTEXT ctx;\n-\n- /*\n- * Setup the source port to be the internal port to as to facilitate the\n- * second OvsLookupFlow.\n- */\n- if (ovsFwdCtx->switchContext->countInternalVports <= 0 ||\n- ovsFwdCtx->switchContext->virtualExternalVport == NULL) {\n- OvsClearTunTxCtx(ovsFwdCtx);\n- OvsCompleteNBLForwardingCtx(ovsFwdCtx,\n- L\"OVS-Dropped since either internal or external port is absent\");\n- return NDIS_STATUS_FAILURE;\n- }\n-\n- ctx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(ovsFwdCtx->curNbl);\n- if (ctx->mru != 0) {\n- OvsDoFragmentNbl(ovsFwdCtx, ctx->mru);\n- }\n- OVS_FWD_INFO switchFwdInfo = { 0 };\n-\n- /* Apply the encapsulation. The encapsulation will not consume the NBL. */\n- switch(ovsFwdCtx->tunnelTxNic->ovsType) {\n- case OVS_VPORT_TYPE_GRE:\n- status = OvsEncapGre(ovsFwdCtx->tunnelTxNic, ovsFwdCtx->curNbl,\n- &ovsFwdCtx->tunKey, ovsFwdCtx->switchContext,\n- &ovsFwdCtx->layers, &newNbl, &switchFwdInfo);\n- break;\n- case OVS_VPORT_TYPE_VXLAN:\n- status = OvsEncapVxlan(ovsFwdCtx->tunnelTxNic, ovsFwdCtx->curNbl,\n- &ovsFwdCtx->tunKey, ovsFwdCtx->switchContext,\n- &ovsFwdCtx->layers, &newNbl, &switchFwdInfo);\n- break;\n- case OVS_VPORT_TYPE_GENEVE:\n- status = OvsEncapGeneve(ovsFwdCtx->tunnelTxNic, ovsFwdCtx->curNbl,\n- &ovsFwdCtx->tunKey, ovsFwdCtx->switchContext,\n- &ovsFwdCtx->layers, &newNbl, &switchFwdInfo);\n- break;\n- default:\n- ASSERT(! \"Tx: Unhandled tunnel type\");\n- }\n-\n- /* Reset the tunnel context so that it doesn't get used after this point. */\n- OvsClearTunTxCtx(ovsFwdCtx);\n-\n- if (status == NDIS_STATUS_SUCCESS && switchFwdInfo.vport != NULL) {\n- ASSERT(newNbl);\n- /*\n- * Save the 'srcVportNo', 'srcPortId', 'srcNicIndex' so that\n- * this can be applied to the new NBL later on.\n- */\n- srcVportNo = switchFwdInfo.vport->portNo;\n- srcPortId = switchFwdInfo.vport->portId;\n- srcNicIndex = switchFwdInfo.vport->nicIndex;\n-\n- OvsCompleteNBLForwardingCtx(ovsFwdCtx,\n- L\"Complete after cloning NBL for encapsulation\");\n- status = OvsInitForwardingCtx(ovsFwdCtx, ovsFwdCtx->switchContext,\n- newNbl, srcVportNo, 0,\n- NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(newNbl),\n- ovsFwdCtx->completionList,\n- &ovsFwdCtx->layers, FALSE);\n- ovsFwdCtx->curNbl = newNbl;\n- /* Update the forwarding detail for the new NBL */\n- ovsFwdCtx->fwdDetail->SourcePortId = srcPortId;\n- ovsFwdCtx->fwdDetail->SourceNicIndex = srcNicIndex;\n- status = OvsDoFlowLookupOutput(ovsFwdCtx);\n- ASSERT(ovsFwdCtx->curNbl == NULL);\n- } else {\n- /*\n- * XXX: Temporary freeing of the packet until we register a\n- * callback to IP helper.\n- */\n- OvsCompleteNBLForwardingCtx(ovsFwdCtx,\n- L\"OVS-Dropped due to encap failure\");\n- ovsActionStats.failedEncap++;\n- status = NDIS_STATUS_SUCCESS;\n- }\n-\n- return status;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsTunnelPortRx --\n- * Decapsulate the incoming NBL based on the tunnel type and goes through\n- * the flow lookup for the inner packet.\n- *\n- * Note: IP checksum is validate here, but L4 checksum validation needs\n- * to be done by the corresponding tunnel types.\n- *\n- * Side effects:\n- * The NBL in 'ovsFwdCtx' is consumed.\n- * --------------------------------------------------------------------------\n- */\n-static __inline NDIS_STATUS\n-OvsTunnelPortRx(OvsForwardingContext *ovsFwdCtx)\n-{\n- NDIS_STATUS status = NDIS_STATUS_SUCCESS;\n- PNET_BUFFER_LIST newNbl = NULL;\n- POVS_VPORT_ENTRY tunnelRxVport = ovsFwdCtx->tunnelRxNic;\n- PCWSTR dropReason = L\"OVS-dropped due to new decap packet\";\n-\n- if (OvsValidateIPChecksum(ovsFwdCtx->curNbl, &ovsFwdCtx->layers)\n- != NDIS_STATUS_SUCCESS) {\n- ovsActionStats.failedChecksum++;\n- OVS_LOG_INFO(\"Packet dropped due to IP checksum failure.\");\n- goto dropNbl;\n- }\n-\n- /*\n- * Decap port functions should return a new NBL if it was copied, and\n- * this new NBL should be setup as the ovsFwdCtx->curNbl.\n- */\n-\n- switch(tunnelRxVport->ovsType) {\n- case OVS_VPORT_TYPE_GRE:\n- status = OvsDecapGre(ovsFwdCtx->switchContext, ovsFwdCtx->curNbl,\n- &ovsFwdCtx->tunKey, &newNbl);\n- break;\n- case OVS_VPORT_TYPE_VXLAN:\n- status = OvsDecapVxlan(ovsFwdCtx->switchContext, ovsFwdCtx->curNbl,\n- &ovsFwdCtx->tunKey, &newNbl);\n- break;\n- case OVS_VPORT_TYPE_GENEVE:\n- status = OvsDecapGeneve(ovsFwdCtx->switchContext, ovsFwdCtx->curNbl,\n- &ovsFwdCtx->tunKey, &newNbl);\n- break;\n- default:\n- OVS_LOG_ERROR(\"Rx: Unhandled tunnel type: %d\\n\",\n- tunnelRxVport->ovsType);\n- ASSERT(! \"Rx: Unhandled tunnel type\");\n- status = NDIS_STATUS_NOT_SUPPORTED;\n- }\n-\n- if (status != NDIS_STATUS_SUCCESS) {\n- ovsActionStats.failedDecap++;\n- goto dropNbl;\n- }\n-\n- /*\n- * tunnelRxNic and other fields will be cleared, re-init the context\n- * before usage.\n- */\n- OvsCompleteNBLForwardingCtx(ovsFwdCtx, dropReason);\n-\n- if (newNbl) {\n- /* Decapsulated packet is in a new NBL */\n- ovsFwdCtx->tunnelRxNic = tunnelRxVport;\n- OvsInitForwardingCtx(ovsFwdCtx, ovsFwdCtx->switchContext,\n- newNbl, tunnelRxVport->portNo, 0,\n- NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(newNbl),\n- ovsFwdCtx->completionList,\n- &ovsFwdCtx->layers, FALSE);\n-\n- /*\n- * Set the NBL's SourcePortId and SourceNicIndex to default values to\n- * keep NDIS happy when we forward the packet.\n- */\n- ovsFwdCtx->fwdDetail->SourcePortId = NDIS_SWITCH_DEFAULT_PORT_ID;\n- ovsFwdCtx->fwdDetail->SourceNicIndex = 0;\n-\n- status = OvsDoFlowLookupOutput(ovsFwdCtx);\n- }\n- ASSERT(ovsFwdCtx->curNbl == NULL);\n- OvsClearTunRxCtx(ovsFwdCtx);\n-\n- return status;\n-\n-dropNbl:\n- OvsCompleteNBLForwardingCtx(ovsFwdCtx,\n- L\"OVS-dropped due to decap failure\");\n- OvsClearTunRxCtx(ovsFwdCtx);\n- return status;\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsOutputForwardingCtx --\n- * This function outputs an NBL to NDIS or to a tunneling pipeline based on\n- * the ports added so far into 'ovsFwdCtx'.\n- *\n- * Side effects:\n- * This function consumes the NBL - either by forwarding it successfully to\n- * NDIS, or adding it to the completion list in 'ovsFwdCtx', or freeing it.\n- *\n- * Also makes sure that the list of destination ports - tunnel or otherwise is\n- * drained.\n- * --------------------------------------------------------------------------\n- */\n-static __inline NDIS_STATUS\n-OvsOutputForwardingCtx(OvsForwardingContext *ovsFwdCtx)\n-{\n- NDIS_STATUS status = STATUS_SUCCESS;\n- POVS_SWITCH_CONTEXT switchContext = ovsFwdCtx->switchContext;\n- PCWSTR dropReason;\n- POVS_BUFFER_CONTEXT ctx;\n-\n- /*\n- * Handle the case where the some of the destination ports are tunneled\n- * ports - the non-tunneled ports get a unmodified copy of the NBL, and the\n- * tunneling pipeline starts when we output the packet to tunneled port.\n- */\n- if (ovsFwdCtx->destPortsSizeOut > 0) {\n- PNET_BUFFER_LIST newNbl = NULL;\n- PNET_BUFFER nb;\n- UINT32 portsToUpdate =\n- ovsFwdCtx->fwdDetail->NumAvailableDestinations -\n- (ovsFwdCtx->destPortsSizeIn - ovsFwdCtx->destPortsSizeOut);\n-\n- ASSERT(ovsFwdCtx->destinationPorts != NULL);\n-\n- /*\n- * Create a copy of the packet in order to do encap on it later. Also,\n- * don't copy the offload context since the encap'd packet has a\n- * different set of headers. This will change when we implement offloads\n- * before doing encapsulation.\n- */\n- if (ovsFwdCtx->tunnelTxNic != NULL || ovsFwdCtx->tunnelRxNic != NULL) {\n- POVS_BUFFER_CONTEXT oldCtx, newCtx;\n- nb = NET_BUFFER_LIST_FIRST_NB(ovsFwdCtx->curNbl);\n- oldCtx = (POVS_BUFFER_CONTEXT)\n- NET_BUFFER_LIST_CONTEXT_DATA_START(ovsFwdCtx->curNbl);\n- newNbl = OvsPartialCopyNBL(ovsFwdCtx->switchContext,\n- ovsFwdCtx->curNbl,\n- 0, 0, TRUE /*copy NBL info*/);\n- if (newNbl == NULL) {\n- status = NDIS_STATUS_RESOURCES;\n- ovsActionStats.noCopiedNbl++;\n- dropReason = L\"Dropped due to failure to create NBL copy.\";\n- goto dropit;\n- }\n- newCtx = (POVS_BUFFER_CONTEXT)\n- NET_BUFFER_LIST_CONTEXT_DATA_START(newNbl);\n- newCtx->mru = oldCtx->mru;\n- }\n-\n- /* It does not seem like we'll get here unless 'portsToUpdate' > 0. */\n- ASSERT(portsToUpdate > 0);\n- status = switchContext->NdisSwitchHandlers.UpdateNetBufferListDestinations(\n- switchContext->NdisSwitchContext, ovsFwdCtx->curNbl,\n- portsToUpdate, ovsFwdCtx->destinationPorts);\n- if (status != NDIS_STATUS_SUCCESS) {\n- OvsCompleteNBL(ovsFwdCtx->switchContext, newNbl, TRUE);\n- ovsActionStats.cannotGrowDest++;\n- dropReason = L\"Dropped due to failure to update destinations.\";\n- goto dropit;\n- }\n-\n- ctx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(ovsFwdCtx->curNbl);\n- if (ctx->mru != 0) {\n- OvsDoFragmentNbl(ovsFwdCtx, ctx->mru);\n- }\n-\n- OvsSendNBLIngress(ovsFwdCtx->switchContext, ovsFwdCtx->curNbl,\n- ovsFwdCtx->sendFlags);\n- /* End this pipeline by resetting the corresponding context. */\n- ovsFwdCtx->destPortsSizeOut = 0;\n- ovsFwdCtx->curNbl = NULL;\n- if (newNbl) {\n- status = OvsInitForwardingCtx(ovsFwdCtx, ovsFwdCtx->switchContext,\n- newNbl, ovsFwdCtx->srcVportNo, 0,\n- NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(newNbl),\n- ovsFwdCtx->completionList,\n- &ovsFwdCtx->layers, FALSE);\n- if (status != NDIS_STATUS_SUCCESS) {\n- dropReason = L\"Dropped due to resources.\";\n- goto dropit;\n- }\n- }\n- }\n-\n- if (ovsFwdCtx->tunnelTxNic != NULL) {\n- status = OvsTunnelPortTx(ovsFwdCtx);\n- ASSERT(ovsFwdCtx->tunnelTxNic == NULL);\n- ASSERT(OvsIphIsZero(&(ovsFwdCtx->tunKey.dst)));\n- } else if (ovsFwdCtx->tunnelRxNic != NULL) {\n- status = OvsTunnelPortRx(ovsFwdCtx);\n- ASSERT(ovsFwdCtx->tunnelRxNic == NULL);\n- ASSERT(OvsIphIsZero(&(ovsFwdCtx->tunKey.dst)));\n- }\n- ASSERT(ovsFwdCtx->curNbl == NULL);\n-\n- return status;\n-\n-dropit:\n- if (status != NDIS_STATUS_SUCCESS) {\n- OvsCompleteNBLForwardingCtx(ovsFwdCtx, dropReason);\n- }\n-\n- return status;\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsLookupFlowOutput --\n- * Utility function for external callers to do flow extract, lookup,\n- * actions execute on a given NBL.\n- *\n- * Note: If this is being used from a callback function, make sure that the\n- * arguments specified are still valid in the asynchronous context.\n- *\n- * Side effects:\n- * This function consumes the NBL.\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-OvsLookupFlowOutput(POVS_SWITCH_CONTEXT switchContext,\n- VOID *compList,\n- PNET_BUFFER_LIST curNbl,\n- POVS_VPORT_ENTRY internalVport)\n-{\n- NDIS_STATUS status;\n- OvsForwardingContext ovsFwdCtx;\n-\n- /* XXX: make sure comp list was not a stack variable previously. */\n- OvsCompletionList *completionList = (OvsCompletionList *)compList;\n-\n- /*\n- * XXX: can internal port disappear while we are busy doing ARP resolution?\n- * It could, but will we get this callback from IP helper in that case. Need\n- * to check.\n- */\n- ASSERT(switchContext->countInternalVports > 0);\n- status = OvsInitForwardingCtx(&ovsFwdCtx, switchContext, curNbl,\n- internalVport->portNo, 0,\n- NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(curNbl),\n- completionList, NULL, TRUE);\n- if (status != NDIS_STATUS_SUCCESS) {\n- OvsCompleteNBLForwardingCtx(&ovsFwdCtx,\n- L\"OVS-Dropped due to resources\");\n- return;\n- }\n-\n- ASSERT(FALSE);\n- /*\n- * XXX: We need to acquire the dispatch lock and the datapath lock.\n- */\n-\n- OvsDoFlowLookupOutput(&ovsFwdCtx);\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsOutputBeforeSetAction --\n- * Function to be called to complete one set of actions on an NBL, before\n- * we start the next one.\n- * --------------------------------------------------------------------------\n- */\n-static __inline NDIS_STATUS\n-OvsOutputBeforeSetAction(OvsForwardingContext *ovsFwdCtx)\n-{\n- PNET_BUFFER_LIST newNbl;\n- NDIS_STATUS status;\n-\n- /*\n- * Create a copy and work on the copy after this point. The original NBL is\n- * forwarded. One reason to not use the copy for forwarding is that\n- * ports have already been added to the original NBL, and it might be\n- * inefficient/impossible to remove/re-add them to the copy. There's no\n- * notion of removing the ports, the ports need to be marked as\n- * \"isExcluded\". There's seems no real advantage to retaining the original\n- * and sending out the copy instead.\n- *\n- * XXX: We are copying the offload context here. This is to handle actions\n- * such as:\n- * outport, pop_vlan(), outport, push_vlan(), outport\n- *\n- * copy size needs to include inner ether + IP + TCP, need to revisit\n- * if we support IP options.\n- * XXX Head room needs to include the additional encap.\n- * XXX copySize check is not considering multiple NBs.\n- */\n- newNbl = OvsPartialCopyNBL(ovsFwdCtx->switchContext, ovsFwdCtx->curNbl,\n- 0, 0, TRUE /*copy NBL info*/);\n-\n- ASSERT(ovsFwdCtx->destPortsSizeOut > 0 ||\n- ovsFwdCtx->tunnelTxNic != NULL || ovsFwdCtx->tunnelRxNic != NULL);\n-\n- /* Send the original packet out and save the original source port number */\n- UINT32 tempVportNo = ovsFwdCtx->srcVportNo;\n- status = OvsOutputForwardingCtx(ovsFwdCtx);\n- ASSERT(ovsFwdCtx->curNbl == NULL);\n- ASSERT(ovsFwdCtx->destPortsSizeOut == 0);\n- ASSERT(ovsFwdCtx->tunnelRxNic == NULL);\n- ASSERT(ovsFwdCtx->tunnelTxNic == NULL);\n-\n- /* If we didn't make a copy, can't continue. */\n- if (newNbl == NULL) {\n- ovsActionStats.noCopiedNbl++;\n- return NDIS_STATUS_RESOURCES;\n- }\n-\n- /* Finish the remaining actions with the new NBL */\n- if (status != NDIS_STATUS_SUCCESS) {\n- OvsCompleteNBL(ovsFwdCtx->switchContext, newNbl, TRUE);\n- } else {\n- status = OvsInitForwardingCtx(ovsFwdCtx, ovsFwdCtx->switchContext,\n- newNbl, tempVportNo, 0,\n- NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(newNbl),\n- ovsFwdCtx->completionList,\n- &ovsFwdCtx->layers, FALSE);\n- }\n-\n- return status;\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsPopFieldInPacketBuf --\n- * Function to pop a specified field of length 'shiftLength' located at\n- * 'shiftOffset' from the Ethernet header. The data on the left of the\n- * 'shiftOffset' is right shifted.\n- *\n- * Returns a pointer to the new start in 'bufferData'.\n- * --------------------------------------------------------------------------\n- */\n-static __inline NDIS_STATUS\n-OvsPopFieldInPacketBuf(OvsForwardingContext *ovsFwdCtx,\n- UINT32 shiftOffset,\n- UINT32 shiftLength,\n- PUINT8 *bufferData)\n-{\n- PNET_BUFFER curNb;\n- PMDL curMdl;\n- PUINT8 bufferStart;\n- UINT32 packetLen, mdlLen;\n- PNET_BUFFER_LIST newNbl;\n- NDIS_STATUS status;\n-\n- newNbl = OvsPartialCopyNBL(ovsFwdCtx->switchContext, ovsFwdCtx->curNbl,\n- 0, 0, TRUE /* copy NBL info */);\n- if (!newNbl) {\n- ovsActionStats.noCopiedNbl++;\n- return NDIS_STATUS_RESOURCES;\n- }\n-\n- /* Complete the original NBL and create a copy to modify. */\n- OvsCompleteNBLForwardingCtx(ovsFwdCtx, L\"OVS-Dropped due to copy\");\n-\n- status = OvsInitForwardingCtx(ovsFwdCtx, ovsFwdCtx->switchContext, newNbl,\n- ovsFwdCtx->srcVportNo, 0,\n- NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(newNbl),\n- NULL, &ovsFwdCtx->layers, FALSE);\n- if (status != NDIS_STATUS_SUCCESS) {\n- OvsCompleteNBLForwardingCtx(ovsFwdCtx,\n- L\"Dropped due to resouces\");\n- return NDIS_STATUS_RESOURCES;\n- }\n-\n- curNb = NET_BUFFER_LIST_FIRST_NB(ovsFwdCtx->curNbl);\n- packetLen = NET_BUFFER_DATA_LENGTH(curNb);\n- ASSERT(curNb->Next == NULL);\n- curMdl = NET_BUFFER_CURRENT_MDL(curNb);\n- NdisQueryMdl(curMdl, &bufferStart, &mdlLen, LowPagePriority);\n- if (!bufferStart) {\n- return NDIS_STATUS_RESOURCES;\n- }\n- mdlLen -= NET_BUFFER_CURRENT_MDL_OFFSET(curNb);\n- /* Bail out if L2 + shiftLength is not contiguous in the first buffer. */\n- if (MIN(packetLen, mdlLen) < sizeof(EthHdr) + shiftLength) {\n- ASSERT(FALSE);\n- return NDIS_STATUS_FAILURE;\n- }\n- bufferStart += NET_BUFFER_CURRENT_MDL_OFFSET(curNb);\n- /* XXX At the momemnt !bufferData means it should be treated as VLAN. We\n- * should split the function and refactor. */\n- if (!bufferData) {\n- EthHdr *ethHdr = (EthHdr *)bufferStart;\n- if (ethHdr->Type != ETH_TYPE_802_1PQ_NBO) {\n- OVS_LOG_ERROR(\"Invalid ethHdr type %u, nbl %p\", ethHdr->Type, ovsFwdCtx->curNbl);\n- return NDIS_STATUS_INVALID_PACKET;\n- }\n- }\n- RtlMoveMemory(bufferStart + shiftLength, bufferStart, shiftOffset);\n- NdisAdvanceNetBufferDataStart(curNb, shiftLength, FALSE, NULL);\n-\n- if (bufferData) {\n- *bufferData = bufferStart + shiftLength;\n- }\n-\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsPopVlanInPktBuf --\n- * Function to pop a VLAN tag when the tag is in the packet buffer.\n- * --------------------------------------------------------------------------\n- */\n-static __inline NDIS_STATUS\n-OvsPopVlanInPktBuf(OvsForwardingContext *ovsFwdCtx)\n-{\n- NDIS_STATUS status;\n- OVS_PACKET_HDR_INFO* layers = &ovsFwdCtx->layers;\n-\n- /*\n- * Declare a dummy vlanTag structure since we need to compute the size\n- * of shiftLength. The NDIS one is a unionized structure.\n- */\n- NDIS_PACKET_8021Q_INFO vlanTag = {0};\n- UINT32 shiftLength = sizeof(vlanTag.TagHeader);\n- UINT32 shiftOffset = sizeof(DL_EUI48) + sizeof(DL_EUI48);\n-\n- status = OvsPopFieldInPacketBuf(ovsFwdCtx, shiftOffset, shiftLength,\n- NULL);\n-\n- if (status == NDIS_STATUS_SUCCESS) {\n- layers->l3Offset -= (UINT16) shiftLength;\n- layers->l4Offset -= (UINT16) shiftLength;\n- }\n-\n- return status;\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsActionMplsPop --\n- * Function to pop the first MPLS label from the current packet.\n- * --------------------------------------------------------------------------\n- */\n-static __inline NDIS_STATUS\n-OvsActionMplsPop(OvsForwardingContext *ovsFwdCtx,\n- ovs_be16 ethertype)\n-{\n- NDIS_STATUS status;\n- OVS_PACKET_HDR_INFO *layers = &ovsFwdCtx->layers;\n- EthHdr *ethHdr = NULL;\n-\n- status = OvsPopFieldInPacketBuf(ovsFwdCtx, sizeof(*ethHdr),\n- MPLS_HLEN, (PUINT8*)ðHdr);\n- if (status == NDIS_STATUS_SUCCESS) {\n- if (ethHdr && OvsEthertypeIsMpls(ethHdr->Type)) {\n- ethHdr->Type = ethertype;\n- }\n-\n- layers->l3Offset -= MPLS_HLEN;\n- layers->l4Offset -= MPLS_HLEN;\n- }\n-\n- return status;\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsActionMplsPush --\n- * Function to push the MPLS label into the current packet.\n- * --------------------------------------------------------------------------\n- */\n-static __inline NDIS_STATUS\n-OvsActionMplsPush(OvsForwardingContext *ovsFwdCtx,\n- const struct ovs_action_push_mpls *mpls)\n-{\n- NDIS_STATUS status;\n- PNET_BUFFER curNb = NULL;\n- PMDL curMdl = NULL;\n- PUINT8 bufferStart = NULL;\n- OVS_PACKET_HDR_INFO *layers = &ovsFwdCtx->layers;\n- EthHdr *ethHdr = NULL;\n- MPLSHdr *mplsHdr = NULL;\n- UINT32 mdlLen = 0, curMdlOffset = 0;\n- PNET_BUFFER_LIST newNbl;\n-\n- newNbl = OvsPartialCopyNBL(ovsFwdCtx->switchContext, ovsFwdCtx->curNbl,\n- layers->l3Offset, MPLS_HLEN, TRUE);\n- if (!newNbl) {\n- ovsActionStats.noCopiedNbl++;\n- return NDIS_STATUS_RESOURCES;\n- }\n- OvsCompleteNBLForwardingCtx(ovsFwdCtx,\n- L\"Complete after partial copy.\");\n-\n- status = OvsInitForwardingCtx(ovsFwdCtx, ovsFwdCtx->switchContext,\n- newNbl, ovsFwdCtx->srcVportNo, 0,\n- NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(newNbl),\n- NULL, &ovsFwdCtx->layers, FALSE);\n- if (status != NDIS_STATUS_SUCCESS) {\n- OvsCompleteNBLForwardingCtx(ovsFwdCtx,\n- L\"OVS-Dropped due to resources\");\n- return NDIS_STATUS_RESOURCES;\n- }\n-\n- curNb = NET_BUFFER_LIST_FIRST_NB(ovsFwdCtx->curNbl);\n- ASSERT(curNb->Next == NULL);\n-\n- status = NdisRetreatNetBufferDataStart(curNb, MPLS_HLEN, 0, NULL);\n- if (status != NDIS_STATUS_SUCCESS) {\n- return status;\n- }\n-\n- curMdl = NET_BUFFER_CURRENT_MDL(curNb);\n- NdisQueryMdl(curMdl, &bufferStart, &mdlLen, LowPagePriority);\n- if (!curMdl) {\n- ovsActionStats.noResource++;\n- return NDIS_STATUS_RESOURCES;\n- }\n-\n- curMdlOffset = NET_BUFFER_CURRENT_MDL_OFFSET(curNb);\n- mdlLen -= curMdlOffset;\n- ASSERT(mdlLen >= MPLS_HLEN);\n-\n- ethHdr = (EthHdr *)(bufferStart + curMdlOffset);\n- ASSERT(ethHdr);\n- RtlMoveMemory(ethHdr, (UINT8*)ethHdr + MPLS_HLEN, sizeof(*ethHdr));\n- ethHdr->Type = mpls->mpls_ethertype;\n-\n- mplsHdr = (MPLSHdr *)(ethHdr + 1);\n- mplsHdr->lse = mpls->mpls_lse;\n-\n- layers->l3Offset += MPLS_HLEN;\n- layers->l4Offset += MPLS_HLEN;\n-\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsUpdateEthHeader --\n- * Updates the ethernet header in ovsFwdCtx.curNbl inline based on the\n- * specified key.\n- *----------------------------------------------------------------------------\n- */\n-static __inline NDIS_STATUS\n-OvsUpdateEthHeader(OvsForwardingContext *ovsFwdCtx,\n- OvsFlowKey *key,\n- const struct ovs_key_ethernet *ethAttr)\n-{\n- PNET_BUFFER curNb;\n- PMDL curMdl;\n- PUINT8 bufferStart;\n- EthHdr *ethHdr;\n- UINT32 packetLen, mdlLen;\n-\n- curNb = NET_BUFFER_LIST_FIRST_NB(ovsFwdCtx->curNbl);\n- ASSERT(curNb->Next == NULL);\n- packetLen = NET_BUFFER_DATA_LENGTH(curNb);\n- curMdl = NET_BUFFER_CURRENT_MDL(curNb);\n- NdisQueryMdl(curMdl, &bufferStart, &mdlLen, LowPagePriority);\n- if (!bufferStart) {\n- ovsActionStats.noResource++;\n- return NDIS_STATUS_RESOURCES;\n- }\n- mdlLen -= NET_BUFFER_CURRENT_MDL_OFFSET(curNb);\n- ASSERT(mdlLen > 0);\n- /* Bail out if the L2 header is not in a contiguous buffer. */\n- if (MIN(packetLen, mdlLen) < sizeof *ethHdr) {\n- ASSERT(FALSE);\n- return NDIS_STATUS_FAILURE;\n- }\n- ethHdr = (EthHdr *)(bufferStart + NET_BUFFER_CURRENT_MDL_OFFSET(curNb));\n-\n- RtlCopyMemory(ethHdr->Destination, ethAttr->eth_dst, ETH_ADDR_LENGTH);\n- RtlCopyMemory(ethHdr->Source, ethAttr->eth_src, ETH_ADDR_LENGTH);\n- /* Update l2 flow key */\n- RtlCopyMemory(key->l2.dlDst, ethAttr->eth_dst, ETH_ADDR_LENGTH);\n- RtlCopyMemory(key->l2.dlSrc, ethAttr->eth_src, ETH_ADDR_LENGTH);\n-\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsGetHeaderBySize --\n- * Tries to retrieve a continuous buffer from 'ovsFwdCtx->curnbl' of size\n- * 'size'.\n- * If the original buffer is insufficient it will, try to clone the net\n- * buffer list and force the size.\n- * Returns 'NULL' on failure or a pointer to the first byte of the data\n- * in the first net buffer of the net buffer list 'nbl'.\n- *----------------------------------------------------------------------------\n- */\n-PUINT8 OvsGetHeaderBySize(OvsForwardingContext *ovsFwdCtx,\n- UINT32 size)\n-{\n- PNET_BUFFER curNb;\n- UINT32 mdlLen, packetLen;\n- PMDL curMdl;\n- ULONG curMdlOffset;\n- PUINT8 start;\n-\n- curNb = NET_BUFFER_LIST_FIRST_NB(ovsFwdCtx->curNbl);\n- ASSERT(curNb->Next == NULL);\n- packetLen = NET_BUFFER_DATA_LENGTH(curNb);\n- curMdl = NET_BUFFER_CURRENT_MDL(curNb);\n- NdisQueryMdl(curMdl, &start, &mdlLen, LowPagePriority);\n- if (!start) {\n- ovsActionStats.noResource++;\n- return NULL;\n- }\n-\n- curMdlOffset = NET_BUFFER_CURRENT_MDL_OFFSET(curNb);\n- mdlLen -= curMdlOffset;\n- ASSERT((INT)mdlLen >= 0);\n-\n- /* Count of number of bytes of valid data there are in the first MDL. */\n- mdlLen = MIN(packetLen, mdlLen);\n- if (mdlLen < size) {\n- PNET_BUFFER_LIST newNbl;\n- NDIS_STATUS status;\n- newNbl = OvsPartialCopyNBL(ovsFwdCtx->switchContext, ovsFwdCtx->curNbl,\n- size, 0, TRUE /*copy NBL info*/);\n- if (!newNbl) {\n- ovsActionStats.noCopiedNbl++;\n- return NULL;\n- }\n- OvsCompleteNBLForwardingCtx(ovsFwdCtx,\n- L\"Complete after partial copy.\");\n-\n- status = OvsInitForwardingCtx(ovsFwdCtx, ovsFwdCtx->switchContext,\n- newNbl, ovsFwdCtx->srcVportNo, 0,\n- NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(newNbl),\n- NULL, &ovsFwdCtx->layers, FALSE);\n-\n- if (status != NDIS_STATUS_SUCCESS) {\n- OvsCompleteNBLForwardingCtx(ovsFwdCtx,\n- L\"OVS-Dropped due to resources\");\n- return NULL;\n- }\n-\n- curNb = NET_BUFFER_LIST_FIRST_NB(ovsFwdCtx->curNbl);\n- ASSERT(curNb->Next == NULL);\n- curMdl = NET_BUFFER_CURRENT_MDL(curNb);\n- NdisQueryMdl(curMdl, &start, &mdlLen, LowPagePriority);\n- if (!curMdl) {\n- ovsActionStats.noResource++;\n- return NULL;\n- }\n- curMdlOffset = NET_BUFFER_CURRENT_MDL_OFFSET(curNb);\n- mdlLen -= curMdlOffset;\n- ASSERT(mdlLen >= size);\n- }\n-\n- return start + curMdlOffset;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsUpdateUdpPorts --\n- * Updates the UDP source or destination port in ovsFwdCtx.curNbl inline\n- * based on the specified key.\n- *----------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsUpdateUdpPorts(OvsForwardingContext *ovsFwdCtx,\n- OvsFlowKey *key,\n- const struct ovs_key_udp *udpAttr)\n-{\n- PUINT8 bufferStart;\n- OVS_PACKET_HDR_INFO *layers = &ovsFwdCtx->layers;\n- UDPHdr *udpHdr = NULL;\n-\n- ASSERT(layers->value != 0);\n-\n- if (!layers->isUdp) {\n- ovsActionStats.noCopiedNbl++;\n- return NDIS_STATUS_FAILURE;\n- }\n-\n- bufferStart = OvsGetHeaderBySize(ovsFwdCtx, layers->l7Offset);\n- if (!bufferStart) {\n- return NDIS_STATUS_RESOURCES;\n- }\n-\n- udpHdr = (UDPHdr *)(bufferStart + layers->l4Offset);\n- if (udpHdr->check) {\n- if (udpHdr->source != udpAttr->udp_src) {\n- udpHdr->check = ChecksumUpdate16(udpHdr->check, udpHdr->source,\n- udpAttr->udp_src);\n- udpHdr->source = udpAttr->udp_src;\n- key->ipKey.l4.tpSrc = udpAttr->udp_src;\n- }\n- if (udpHdr->dest != udpAttr->udp_dst) {\n- udpHdr->check = ChecksumUpdate16(udpHdr->check, udpHdr->dest,\n- udpAttr->udp_dst);\n- udpHdr->dest = udpAttr->udp_dst;\n- key->ipKey.l4.tpDst = udpAttr->udp_dst;\n- }\n- } else {\n- udpHdr->source = udpAttr->udp_src;\n- key->ipKey.l4.tpSrc = udpAttr->udp_src;\n- udpHdr->dest = udpAttr->udp_dst;\n- key->ipKey.l4.tpDst = udpAttr->udp_dst;\n- }\n-\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsUpdateTcpPorts --\n- * Updates the TCP source or destination port in ovsFwdCtx.curNbl inline\n- * based on the specified key.\n- *----------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsUpdateTcpPorts(OvsForwardingContext *ovsFwdCtx,\n- OvsFlowKey *key,\n- const struct ovs_key_tcp *tcpAttr)\n-{\n- PUINT8 bufferStart;\n- OVS_PACKET_HDR_INFO *layers = &ovsFwdCtx->layers;\n- TCPHdr *tcpHdr = NULL;\n-\n- ASSERT(layers->value != 0);\n-\n- if (!layers->isTcp) {\n- ovsActionStats.noCopiedNbl++;\n- return NDIS_STATUS_FAILURE;\n- }\n-\n- bufferStart = OvsGetHeaderBySize(ovsFwdCtx, layers->l7Offset);\n- if (!bufferStart) {\n- return NDIS_STATUS_RESOURCES;\n- }\n-\n- tcpHdr = (TCPHdr *)(bufferStart + layers->l4Offset);\n-\n- if (tcpHdr->source != tcpAttr->tcp_src) {\n- tcpHdr->check = ChecksumUpdate16(tcpHdr->check, tcpHdr->source,\n- tcpAttr->tcp_src);\n- tcpHdr->source = tcpAttr->tcp_src;\n- key->ipKey.l4.tpSrc = tcpAttr->tcp_src;\n- }\n- if (tcpHdr->dest != tcpAttr->tcp_dst) {\n- tcpHdr->check = ChecksumUpdate16(tcpHdr->check, tcpHdr->dest,\n- tcpAttr->tcp_dst);\n- tcpHdr->dest = tcpAttr->tcp_dst;\n- key->ipKey.l4.tpDst = tcpAttr->tcp_dst;\n- }\n-\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsUpdateAddressAndPort --\n- * Updates the source/destination IP and port fields in\n- * ovsFwdCtx.curNbl inline based on the specified key.\n- *----------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsUpdateAddressAndPort(OvsForwardingContext *ovsFwdCtx,\n- UINT32 newAddr, UINT16 newPort,\n- BOOLEAN isSource, BOOLEAN isTx)\n-{\n- PUINT8 bufferStart;\n- UINT32 hdrSize;\n- OVS_PACKET_HDR_INFO *layers = &ovsFwdCtx->layers;\n- IPHdr *ipHdr;\n- TCPHdr *tcpHdr = NULL;\n- UDPHdr *udpHdr = NULL;\n- UINT32 *addrField = NULL;\n- UINT16 *portField = NULL;\n- UINT16 *checkField = NULL;\n- BOOLEAN l4Offload = FALSE;\n- NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo;\n- UINT16 preNatPseudoChecksum = 0;\n- BOOLEAN preservePseudoChecksum = FALSE;\n-\n- ASSERT(layers->value != 0);\n-\n- if (layers->isTcp || layers->isUdp) {\n- hdrSize = layers->l4Offset +\n- layers->isTcp ? sizeof (*tcpHdr) : sizeof (*udpHdr);\n- } else {\n- hdrSize = layers->l3Offset + sizeof (*ipHdr);\n- }\n-\n- bufferStart = OvsGetHeaderBySize(ovsFwdCtx, hdrSize);\n- if (!bufferStart) {\n- return NDIS_STATUS_RESOURCES;\n- }\n-\n- ipHdr = (IPHdr *)(bufferStart + layers->l3Offset);\n-\n- if (layers->isTcp) {\n- tcpHdr = (TCPHdr *)(bufferStart + layers->l4Offset);\n- } else if (layers->isUdp) {\n- udpHdr = (UDPHdr *)(bufferStart + layers->l4Offset);\n- }\n-\n- csumInfo.Value = NET_BUFFER_LIST_INFO(ovsFwdCtx->curNbl,\n- TcpIpChecksumNetBufferListInfo);\n-\n- /*\n- * Adjust the IP header inline as dictated by the action, and also update\n- * the IP and the TCP checksum for the data modified.\n- *\n- * In the future, this could be optimized to make one call to\n- * ChecksumUpdate32(). Ignoring this for now, since for the most common\n- * case, we only update the TTL.\n- */\n- /*Only tx direction the checksum value will be reset to be PseudoChecksum*/\n- if (!isTx) {\n- preNatPseudoChecksum = IPPseudoChecksum(&ipHdr->saddr, &ipHdr->daddr,\n- tcpHdr ? IPPROTO_TCP : IPPROTO_UDP,\n- ntohs(ipHdr->tot_len) - ipHdr->ihl * 4);\n- }\n-\n- if (isSource) {\n- addrField = &ipHdr->saddr;\n- if (tcpHdr) {\n- portField = &tcpHdr->source;\n- checkField = &tcpHdr->check;\n- l4Offload = isTx ? (BOOLEAN)csumInfo.Transmit.TcpChecksum :\n- ((BOOLEAN)csumInfo.Receive.TcpChecksumSucceeded ||\n- (BOOLEAN)csumInfo.Receive.TcpChecksumFailed);\n- } else if (udpHdr) {\n- portField = &udpHdr->source;\n- checkField = &udpHdr->check;\n- l4Offload = isTx ? (BOOLEAN)csumInfo.Transmit.UdpChecksum :\n- ((BOOLEAN)csumInfo.Receive.UdpChecksumSucceeded ||\n- (BOOLEAN)csumInfo.Receive.UdpChecksumFailed);\n- }\n- if (!isTx && l4Offload) {\n- if (*checkField == preNatPseudoChecksum) {\n- preservePseudoChecksum = TRUE;\n- }\n- }\n- if (isTx && l4Offload || preservePseudoChecksum) {\n- *checkField = IPPseudoChecksum(&newAddr, &ipHdr->daddr,\n- tcpHdr ? IPPROTO_TCP : IPPROTO_UDP,\n- ntohs(ipHdr->tot_len) - ipHdr->ihl * 4);\n- }\n- } else {\n- addrField = &ipHdr->daddr;\n- if (tcpHdr) {\n- portField = &tcpHdr->dest;\n- checkField = &tcpHdr->check;\n- l4Offload = isTx ? (BOOLEAN)csumInfo.Transmit.TcpChecksum :\n- ((BOOLEAN)csumInfo.Receive.TcpChecksumSucceeded ||\n- (BOOLEAN)csumInfo.Receive.TcpChecksumFailed);\n- } else if (udpHdr) {\n- portField = &udpHdr->dest;\n- checkField = &udpHdr->check;\n- l4Offload = isTx ? (BOOLEAN)csumInfo.Transmit.UdpChecksum :\n- ((BOOLEAN)csumInfo.Receive.UdpChecksumSucceeded ||\n- (BOOLEAN)csumInfo.Receive.UdpChecksumFailed);\n- }\n- if (!isTx && l4Offload) {\n- if (*checkField == preNatPseudoChecksum) {\n- preservePseudoChecksum = TRUE;\n- }\n- }\n-\n- if (isTx && l4Offload || preservePseudoChecksum) {\n- *checkField = IPPseudoChecksum(&ipHdr->saddr, &newAddr,\n- tcpHdr ? IPPROTO_TCP : IPPROTO_UDP,\n- ntohs(ipHdr->tot_len) - ipHdr->ihl * 4);\n- }\n- }\n-\n- if (*addrField != newAddr) {\n- UINT32 oldAddr = *addrField;\n- if ((checkField && *checkField != 0) &&\n- (!l4Offload || (!isTx && !preservePseudoChecksum))) {\n- /* Recompute total checksum. */\n- *checkField = ChecksumUpdate32(*checkField, oldAddr,\n- newAddr);\n- }\n- if (ipHdr->check != 0) {\n- ipHdr->check = ChecksumUpdate32(ipHdr->check, oldAddr,\n- newAddr);\n- }\n-\n- *addrField = newAddr;\n- }\n-\n- if (portField && *portField != newPort) {\n- if ((checkField) &&\n- (!l4Offload || (!isTx && !preservePseudoChecksum))) {\n- /* Recompute total checksum. */\n- *checkField = ChecksumUpdate16(*checkField, *portField,\n- newPort);\n- }\n- *portField = newPort;\n- }\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-UINT16\n-OvsCalculateICMPv6Checksum(struct in6_addr srcAddr,\n- struct in6_addr dstAddr,\n- uint16_t totalLength,\n- uint16_t protocol,\n- uint16_t *icmpStart,\n- uint16_t length)\n-{\n- uint32_t checkSum = 0;\n- uint16_t *srcAddressPtr = (uint16_t *)&srcAddr;\n- uint16_t *dstAddressPtr = (uint16_t *)&dstAddr;\n- uint16_t *value = (uint16_t *)icmpStart;\n- int index = 0;\n-\n- checkSum = totalLength + protocol;\n-\n- for (int i = 0; i < 8; i++) {\n- checkSum += ntohs(srcAddressPtr[i]);\n- checkSum += ntohs(dstAddressPtr[i]);\n- }\n-\n- for (index = length; index > 1; index -= 2) {\n- checkSum += ntohs(*value);\n- value++;\n- }\n-\n- if (index > 0) {\n- checkSum += (uint16_t)(*((uint8_t *)value));\n- }\n-\n- while ((checkSum >> 16) & 0xffff) {\n- checkSum = (checkSum & 0xffff) + ((checkSum >> 16) & 0xffff);\n- }\n-\n- return htons(~((uint16_t)checkSum));\n-}\n-\n-/*\n- *-----------------------------------------------------------------------------\n- *\n- * OvsUpdateAddressAndPortForIpv6--\n- *\n- * Update ipv6 address in ovsFwdCtx.curNbl.\n- *\n- * Results:\n- * None\n- *\n- * Side effects:\n- * None\n- *\n- *-----------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsUpdateAddressAndPortForIpv6(OvsForwardingContext *ovsFwdCtx,\n- struct in6_addr newAddr, UINT16 newPort,\n- BOOLEAN isSource, BOOLEAN isTx)\n-{\n- PUINT8 bufferStart;\n- UINT32 hdrSize;\n- OVS_PACKET_HDR_INFO *layers = &ovsFwdCtx->layers;\n- IPv6Hdr *ipHdr;\n- TCPHdr *tcpHdr = NULL;\n- UDPHdr *udpHdr = NULL;\n- struct in6_addr *addrField = NULL;\n- UINT16 *portField = NULL;\n- UINT16 *checkField = NULL;\n- BOOLEAN l4Offload = FALSE;\n- NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo;\n-\n- ASSERT(layers->value != 0);\n-\n- if (layers->isTcp || layers->isUdp) {\n- hdrSize = layers->l4Offset +\n- layers->isTcp ? sizeof (*tcpHdr) : sizeof (*udpHdr);\n- } else {\n- hdrSize = layers->l3Offset + sizeof (*ipHdr);\n- }\n-\n- csumInfo.Value = NET_BUFFER_LIST_INFO(ovsFwdCtx->curNbl,\n- TcpIpChecksumNetBufferListInfo);\n-\n- bufferStart = OvsGetHeaderBySize(ovsFwdCtx, hdrSize);\n- if (!bufferStart) {\n- return NDIS_STATUS_RESOURCES;\n- }\n-\n- ipHdr = (IPv6Hdr *)(bufferStart + layers->l3Offset);\n-\n- if (layers->isTcp) {\n- tcpHdr = (TCPHdr *)(bufferStart + layers->l4Offset);\n- } else if (layers->isUdp) {\n- udpHdr = (UDPHdr *)(bufferStart + layers->l4Offset);\n- }\n-\n- if (isSource) {\n- addrField = &ipHdr->saddr;\n- if (tcpHdr) {\n- portField = &tcpHdr->source;\n- checkField = &tcpHdr->check;\n- l4Offload = isTx ? (BOOLEAN)csumInfo.Transmit.TcpChecksum :\n- ((BOOLEAN)csumInfo.Receive.TcpChecksumSucceeded ||\n- (BOOLEAN)csumInfo.Receive.TcpChecksumFailed);\n- } else if (udpHdr) {\n- portField = &udpHdr->source;\n- checkField = &udpHdr->check;\n- l4Offload = isTx ? (BOOLEAN)csumInfo.Transmit.UdpChecksum :\n- ((BOOLEAN)csumInfo.Receive.UdpChecksumSucceeded ||\n- (BOOLEAN)csumInfo.Receive.UdpChecksumFailed);\n- }\n- if (isTx && l4Offload) {\n- *checkField = IPv6PseudoChecksum((UINT32 *)&newAddr, (UINT32 *)&ipHdr->daddr,\n- tcpHdr ? IPPROTO_TCP : IPPROTO_UDP,\n- ntohs(ipHdr->payload_len) -\n- (ovsFwdCtx->layers.l4Offset - ovsFwdCtx->layers.l3Offset));\n- }\n- } else {\n- addrField = &ipHdr->daddr;\n- if (tcpHdr) {\n- portField = &tcpHdr->dest;\n- checkField = &tcpHdr->check;\n- l4Offload = isTx ? (BOOLEAN)csumInfo.Transmit.TcpChecksum :\n- ((BOOLEAN)csumInfo.Receive.TcpChecksumSucceeded ||\n- (BOOLEAN)csumInfo.Receive.TcpChecksumFailed);\n- } else if (udpHdr) {\n- portField = &udpHdr->dest;\n- checkField = &udpHdr->check;\n- l4Offload = isTx ? (BOOLEAN)csumInfo.Transmit.UdpChecksum :\n- ((BOOLEAN)csumInfo.Receive.UdpChecksumSucceeded ||\n- (BOOLEAN)csumInfo.Receive.UdpChecksumFailed);\n- }\n-\n- if (isTx && l4Offload) {\n- *checkField = IPv6PseudoChecksum((UINT32 *)&ipHdr->saddr, (UINT32 *)&newAddr,\n- tcpHdr ? IPPROTO_TCP : IPPROTO_UDP,\n- ntohs(ipHdr->payload_len) -\n- (ovsFwdCtx->layers.l4Offset - ovsFwdCtx->layers.l3Offset));\n- }\n- }\n-\n- if (memcmp(addrField, &newAddr, sizeof(struct in6_addr))) {\n- if ((checkField && *checkField != 0) && (!l4Offload || !isTx)) {\n- uint32_t *oldField = (uint32_t *)addrField;\n- uint32_t *newField = (uint32_t *)&newAddr;\n- *checkField = ChecksumUpdate32(*checkField, oldField[0], newField[0]);\n- *checkField = ChecksumUpdate32(*checkField, oldField[1], newField[1]);\n- *checkField = ChecksumUpdate32(*checkField, oldField[2], newField[2]);\n- *checkField = ChecksumUpdate32(*checkField, oldField[3], newField[3]);\n- }\n-\n- *addrField = newAddr;\n-\n- if (layers->isIcmp) {\n- ICMPHdr *icmp =(ICMPHdr *)(bufferStart + layers->l4Offset);\n- icmp->checksum = 0x00;\n- icmp->checksum = OvsCalculateICMPv6Checksum(ipHdr->saddr, ipHdr->daddr,\n- ntohs(ipHdr->payload_len),\n- IPPROTO_ICMPV6,\n- (uint16_t *)icmp,\n- ntohs(ipHdr->payload_len));\n- }\n- }\n-\n- if (portField && *portField != newPort) {\n- if ((checkField) && (!l4Offload || !isTx)) {\n- /* Recompute total checksum. */\n- *checkField = ChecksumUpdate16(*checkField, *portField,\n- newPort);\n- }\n- *portField = newPort;\n- }\n-\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsUpdateIPv4Header --\n- * Updates the IPv4 header in ovsFwdCtx.curNbl inline based on the\n- * specified key.\n- *----------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsUpdateIPv4Header(OvsForwardingContext *ovsFwdCtx,\n- OvsFlowKey *key,\n- const struct ovs_key_ipv4 *ipAttr)\n-{\n- PUINT8 bufferStart;\n- UINT32 hdrSize;\n- OVS_PACKET_HDR_INFO *layers = &ovsFwdCtx->layers;\n- IPHdr *ipHdr;\n- TCPHdr *tcpHdr = NULL;\n- UDPHdr *udpHdr = NULL;\n-\n- ASSERT(layers->value != 0);\n-\n- if (layers->isTcp || layers->isUdp) {\n- hdrSize = layers->l4Offset +\n- layers->isTcp ? sizeof (*tcpHdr) : sizeof (*udpHdr);\n- } else {\n- hdrSize = layers->l3Offset + sizeof (*ipHdr);\n- }\n-\n- bufferStart = OvsGetHeaderBySize(ovsFwdCtx, hdrSize);\n- if (!bufferStart) {\n- return NDIS_STATUS_RESOURCES;\n- }\n-\n- ipHdr = (IPHdr *)(bufferStart + layers->l3Offset);\n-\n- if (layers->isTcp) {\n- tcpHdr = (TCPHdr *)(bufferStart + layers->l4Offset);\n- } else if (layers->isUdp) {\n- udpHdr = (UDPHdr *)(bufferStart + layers->l4Offset);\n- }\n-\n- /*\n- * Adjust the IP header inline as dictated by the action, and also update\n- * the IP and the TCP checksum for the data modified.\n- *\n- * In the future, this could be optimized to make one call to\n- * ChecksumUpdate32(). Ignoring this for now, since for the most common\n- * case, we only update the TTL.\n- */\n- if (ipHdr->saddr != ipAttr->ipv4_src) {\n- if (tcpHdr) {\n- tcpHdr->check = ChecksumUpdate32(tcpHdr->check, ipHdr->saddr,\n- ipAttr->ipv4_src);\n- } else if (udpHdr && udpHdr->check) {\n- udpHdr->check = ChecksumUpdate32(udpHdr->check, ipHdr->saddr,\n- ipAttr->ipv4_src);\n- }\n-\n- if (ipHdr->check != 0) {\n- ipHdr->check = ChecksumUpdate32(ipHdr->check, ipHdr->saddr,\n- ipAttr->ipv4_src);\n- }\n- ipHdr->saddr = ipAttr->ipv4_src;\n- key->ipKey.nwSrc = ipAttr->ipv4_src;\n- }\n- if (ipHdr->daddr != ipAttr->ipv4_dst) {\n- if (tcpHdr) {\n- tcpHdr->check = ChecksumUpdate32(tcpHdr->check, ipHdr->daddr,\n- ipAttr->ipv4_dst);\n- } else if (udpHdr && udpHdr->check) {\n- udpHdr->check = ChecksumUpdate32(udpHdr->check, ipHdr->daddr,\n- ipAttr->ipv4_dst);\n- }\n-\n- if (ipHdr->check != 0) {\n- ipHdr->check = ChecksumUpdate32(ipHdr->check, ipHdr->daddr,\n- ipAttr->ipv4_dst);\n- }\n- ipHdr->daddr = ipAttr->ipv4_dst;\n- key->ipKey.nwDst = ipAttr->ipv4_dst;\n- }\n- if (ipHdr->protocol != ipAttr->ipv4_proto) {\n- UINT16 oldProto = (ipHdr->protocol << 16) & 0xff00;\n- UINT16 newProto = (ipAttr->ipv4_proto << 16) & 0xff00;\n- if (tcpHdr) {\n- tcpHdr->check = ChecksumUpdate16(tcpHdr->check, oldProto, newProto);\n- } else if (udpHdr && udpHdr->check) {\n- udpHdr->check = ChecksumUpdate16(udpHdr->check, oldProto, newProto);\n- }\n-\n- if (ipHdr->check != 0) {\n- ipHdr->check = ChecksumUpdate16(ipHdr->check, oldProto, newProto);\n- }\n- ipHdr->protocol = ipAttr->ipv4_proto;\n- key->ipKey.nwProto = ipAttr->ipv4_proto;\n- }\n- if (ipHdr->ttl != ipAttr->ipv4_ttl) {\n- UINT16 oldTtl = (ipHdr->ttl) & 0xff;\n- UINT16 newTtl = (ipAttr->ipv4_ttl) & 0xff;\n- if (ipHdr->check != 0) {\n- ipHdr->check = ChecksumUpdate16(ipHdr->check, oldTtl, newTtl);\n- }\n- ipHdr->ttl = ipAttr->ipv4_ttl;\n- key->ipKey.nwTtl = ipAttr->ipv4_ttl;\n- }\n- if (ipHdr->dscp != (ipAttr->ipv4_tos & 0xfc)) {\n- /* ECN + DSCP */\n- UINT8 newTos = (ipHdr->tos & 0x3) | (ipAttr->ipv4_tos & 0xfc);\n- if (ipHdr->check != 0) {\n- ipHdr->check = ChecksumUpdate16(ipHdr->check, ipHdr->tos, newTos);\n- }\n- ipHdr->tos = newTos;\n- key->ipKey.nwTos = newTos;\n- }\n-\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsExecuteSetAction --\n- * Executes a set() action, but storing the actions into 'ovsFwdCtx'\n- * --------------------------------------------------------------------------\n- */\n-static __inline NDIS_STATUS\n-OvsExecuteSetAction(OvsForwardingContext *ovsFwdCtx,\n- OvsFlowKey *key,\n- UINT64 *hash,\n- const PNL_ATTR a)\n-{\n- enum ovs_key_attr type = NlAttrType(a);\n- NDIS_STATUS status = NDIS_STATUS_SUCCESS;\n-\n- switch (type) {\n- case OVS_KEY_ATTR_ETHERNET:\n- status = OvsUpdateEthHeader(ovsFwdCtx, key,\n- NlAttrGetUnspec(a, sizeof(struct ovs_key_ethernet)));\n- break;\n-\n- case OVS_KEY_ATTR_IPV4:\n- status = OvsUpdateIPv4Header(ovsFwdCtx, key,\n- NlAttrGetUnspec(a, sizeof(struct ovs_key_ipv4)));\n- break;\n-\n- case OVS_KEY_ATTR_TUNNEL:\n- {\n- OvsIPTunnelKey tunKey = { 0 };\n- tunKey.flow_hash = (uint16)(hash ? *hash : OvsHashFlow(key));\n- tunKey.dst_port = key->ipKey.l4.tpDst;\n- NTSTATUS convertStatus = OvsTunnelAttrToIPTunnelKey((PNL_ATTR)a, &tunKey);\n- status = SUCCEEDED(convertStatus) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE;\n- ASSERT(status == NDIS_STATUS_SUCCESS);\n- RtlCopyMemory(&ovsFwdCtx->tunKey, &tunKey, sizeof ovsFwdCtx->tunKey);\n- RtlCopyMemory(&key->tunKey, &tunKey, sizeof key->tunKey);\n- break;\n- }\n-\n- case OVS_KEY_ATTR_UDP:\n- status = OvsUpdateUdpPorts(ovsFwdCtx, key,\n- NlAttrGetUnspec(a, sizeof(struct ovs_key_udp)));\n- break;\n-\n- case OVS_KEY_ATTR_TCP:\n- status = OvsUpdateTcpPorts(ovsFwdCtx, key,\n- NlAttrGetUnspec(a, sizeof(struct ovs_key_tcp)));\n- break;\n-\n- default:\n- OVS_LOG_INFO(\"Unhandled attribute %#x\", type);\n- break;\n- }\n- return status;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsExecuteRecirc --\n- * The function adds a deferred action to allow the current packet, nbl,\n- * to re-enter datapath packet processing.\n- * --------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsExecuteRecirc(OvsForwardingContext *ovsFwdCtx,\n- OvsFlowKey *key,\n- const PNL_ATTR actions,\n- int rem)\n-{\n- POVS_DEFERRED_ACTION deferredAction = NULL;\n- PNET_BUFFER_LIST newNbl = NULL;\n-\n- if (!NlAttrIsLast(actions, rem)) {\n- /*\n- * Recirc action is the not the last action of the action list, so we\n- * need to clone the packet.\n- */\n- newNbl = OvsPartialCopyNBL(ovsFwdCtx->switchContext, ovsFwdCtx->curNbl,\n- 0, 0, TRUE /*copy NBL info*/);\n- /*\n- * Skip the recirc action when out of memory, but continue on with the\n- * rest of the action list.\n- */\n- if (newNbl == NULL) {\n- ovsActionStats.noCopiedNbl++;\n- return NDIS_STATUS_SUCCESS;\n- }\n- }\n-\n- if (newNbl) {\n- deferredAction = OvsAddDeferredActions(newNbl, key, &(ovsFwdCtx->layers),\n- NULL);\n- } else {\n- deferredAction = OvsAddDeferredActions(ovsFwdCtx->curNbl, key,\n- &(ovsFwdCtx->layers), NULL);\n- }\n-\n- if (deferredAction) {\n- deferredAction->key.recircId = NlAttrGetU32(actions);\n- } else {\n- if (newNbl) {\n- ovsActionStats.deferredActionsQueueFull++;\n- OvsCompleteNBL(ovsFwdCtx->switchContext, newNbl, TRUE);\n- }\n- }\n-\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsExecuteHash --\n- * The function updates datapath hash read from userspace.\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-OvsExecuteHash(OvsFlowKey *key,\n- const PNL_ATTR attr)\n-{\n- struct ovs_action_hash *hash_act = NlAttrData(attr);\n- UINT32 hash = 0;\n-\n- hash = (UINT32)OvsHashFlow(key);\n- hash = OvsJhashWords(&hash, 1, hash_act->hash_basis);\n- if (!hash)\n- hash = 1;\n-\n- key->dpHash = hash;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsOutputUserspaceAction --\n- * This function sends the packet to userspace according to nested\n- * %OVS_USERSPACE_ATTR_* attributes.\n- * --------------------------------------------------------------------------\n- */\n-static __inline NDIS_STATUS\n-OvsOutputUserspaceAction(OvsForwardingContext *ovsFwdCtx,\n- OvsFlowKey *key,\n- const PNL_ATTR attr)\n-{\n- NTSTATUS status = NDIS_STATUS_SUCCESS;\n- PNL_ATTR userdataAttr;\n- PNL_ATTR egrTunAttr = NULL;\n- POVS_PACKET_QUEUE_ELEM elem;\n- POVS_PACKET_HDR_INFO layers = &ovsFwdCtx->layers;\n- BOOLEAN isRecv = FALSE;\n- OVS_FWD_INFO fwdInfo;\n- OvsIPTunnelKey tunKey;\n-\n- POVS_VPORT_ENTRY vport = OvsFindVportByPortNo(ovsFwdCtx->switchContext,\n- ovsFwdCtx->srcVportNo);\n-\n- if (vport) {\n- if (vport->isExternal ||\n- OvsIsTunnelVportType(vport->ovsType)) {\n- isRecv = TRUE;\n- }\n- }\n-\n- userdataAttr = NlAttrFindNested(attr, OVS_USERSPACE_ATTR_USERDATA);\n- /* Indicate the packet is from egress-tunnel direction */\n- egrTunAttr = NlAttrFindNested(attr, OVS_USERSPACE_ATTR_EGRESS_TUN_PORT);\n-\n- /* Fill tunnel key to export to usersspace to calculate the template id */\n- if (egrTunAttr) {\n- RtlZeroMemory(&tunKey, sizeof tunKey);\n- RtlCopyMemory(&tunKey, &ovsFwdCtx->tunKey, sizeof tunKey);\n- if (!OvsIphIsZero(&(tunKey.src))) {\n- status = OvsLookupIPhFwdInfo(tunKey.src, tunKey.dst, &fwdInfo);\n- if (status == NDIS_STATUS_SUCCESS &&\n- OvsIphAddrEquals(&(tunKey.dst), &(fwdInfo.dstIphAddr))) {\n- OvsCopyIphAddress(&(tunKey.src), &fwdInfo.srcIphAddr);\n- }\n- }\n- tunKey.flow_hash = tunKey.flow_hash ? tunKey.flow_hash : MAXINT16;\n- }\n-\n- elem = OvsCreateQueueNlPacket(NlAttrData(userdataAttr),\n- NlAttrGetSize(userdataAttr),\n- OVS_PACKET_CMD_ACTION,\n- vport, key,\n- egrTunAttr ? &(tunKey) : NULL,\n- ovsFwdCtx->curNbl,\n- NET_BUFFER_LIST_FIRST_NB(ovsFwdCtx->curNbl),\n- isRecv,\n- layers);\n- if (elem) {\n- LIST_ENTRY missedPackets;\n- InitializeListHead(&missedPackets);\n- InsertTailList(&missedPackets, &elem->link);\n- OvsQueuePackets(&missedPackets, 1);\n- } else {\n- status = NDIS_STATUS_FAILURE;\n- }\n-\n- return status;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsExecuteSampleAction --\n- * Executes actions based on probability, as specified in the nested\n- * %OVS_SAMPLE_ATTR_* attributes.\n- * --------------------------------------------------------------------------\n- */\n-static __inline NDIS_STATUS\n-OvsExecuteSampleAction(OvsForwardingContext *ovsFwdCtx,\n- OvsFlowKey *key,\n- const PNL_ATTR attr)\n-{\n- PNET_BUFFER_LIST newNbl = NULL;\n- PNL_ATTR actionsList = NULL;\n- PNL_ATTR a = NULL;\n- INT rem = 0;\n-\n- SRand();\n- NL_ATTR_FOR_EACH_UNSAFE(a, rem, NlAttrData(attr), NlAttrGetSize(attr)) {\n- switch (NlAttrType(a)) {\n- case OVS_SAMPLE_ATTR_PROBABILITY:\n- {\n- UINT32 probability = NlAttrGetU32(a);\n-\n- if (!probability || Rand() > probability) {\n- return 0;\n- }\n- break;\n- }\n- case OVS_SAMPLE_ATTR_ACTIONS:\n- actionsList = a;\n- break;\n- }\n- }\n-\n- if (actionsList) {\n- rem = NlAttrGetSize(actionsList);\n- a = (PNL_ATTR)NlAttrData(actionsList);\n- }\n-\n- if (!rem) {\n- /* Actions list is empty, do nothing */\n- return STATUS_SUCCESS;\n- }\n-\n- /*\n- * The only known usage of sample action is having a single user-space\n- * action. Treat this usage as a special case.\n- */\n- if (NlAttrType(a) == OVS_ACTION_ATTR_USERSPACE &&\n- NlAttrIsLast(a, rem)) {\n- return OvsOutputUserspaceAction(ovsFwdCtx, key, a);\n- }\n-\n- newNbl = OvsPartialCopyNBL(ovsFwdCtx->switchContext, ovsFwdCtx->curNbl,\n- 0, 0, TRUE /*copy NBL info*/);\n- if (newNbl == NULL) {\n- /*\n- * Skip the sample action when out of memory, but continue on with the\n- * rest of the action list.\n- */\n- ovsActionStats.noCopiedNbl++;\n- return STATUS_SUCCESS;\n- }\n-\n- if (!OvsAddDeferredActions(newNbl, key, &(ovsFwdCtx->layers), a)) {\n- OVS_LOG_INFO(\n- \"Deferred actions limit reached, dropping sample action.\");\n- OvsCompleteNBL(ovsFwdCtx->switchContext, newNbl, TRUE);\n- }\n-\n- return STATUS_SUCCESS;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsDoExecuteActions --\n- * Interpret and execute the specified 'actions' on the specified packet\n- * 'curNbl'. The expectation is that if the packet needs to be dropped\n- * (completed) for some reason, it is added to 'completionList' so that the\n- * caller can complete the packet. If 'completionList' is NULL, the NBL is\n- * assumed to be generated by OVS and freed up. Otherwise, the function\n- * consumes the NBL by generating a NDIS send indication for the packet.\n- *\n- * There are one or more of \"clone\" NBLs that may get generated while\n- * executing the actions. Upon any failures, the \"cloned\" NBLs are freed up,\n- * and the caller does not have to worry about them.\n- *\n- * Success or failure is returned based on whether the specified actions\n- * were executed successfully on the packet or not.\n- * --------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsDoExecuteActions(POVS_SWITCH_CONTEXT switchContext,\n- OvsCompletionList *completionList,\n- PNET_BUFFER_LIST curNbl,\n- UINT32 portNo,\n- ULONG sendFlags,\n- OvsFlowKey *key,\n- UINT64 *hash,\n- OVS_PACKET_HDR_INFO *layers,\n- const PNL_ATTR actions,\n- INT actionsLen)\n-{\n- PNL_ATTR a;\n- INT rem;\n- UINT32 dstPortID;\n- OvsForwardingContext ovsFwdCtx;\n- PCWSTR dropReason = L\"\";\n- NDIS_STATUS status;\n- PNDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO fwdDetail =\n- NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(curNbl);\n-\n- /* XXX: ASSERT that the flow table lock is held. */\n- status = OvsInitForwardingCtx(&ovsFwdCtx, switchContext, curNbl, portNo,\n- sendFlags, fwdDetail, completionList,\n- layers, TRUE);\n- if (status != NDIS_STATUS_SUCCESS) {\n- dropReason = L\"OVS-initing destination port list failed\";\n- goto dropit;\n- }\n-\n- if (actionsLen == 0) {\n- dropReason = L\"OVS-Dropped due to Flow action\";\n- ovsActionStats.zeroActionLen++;\n- goto dropit;\n- }\n-\n- NL_ATTR_FOR_EACH_UNSAFE (a, rem, actions, actionsLen) {\n- switch(NlAttrType(a)) {\n- case OVS_ACTION_ATTR_OUTPUT:\n- dstPortID = NlAttrGetU32(a);\n- status = OvsAddPorts(&ovsFwdCtx, key, dstPortID,\n- TRUE, TRUE);\n- if (status != NDIS_STATUS_SUCCESS) {\n- dropReason = L\"OVS-adding destination port failed\";\n- goto dropit;\n- }\n- break;\n-\n- case OVS_ACTION_ATTR_PUSH_VLAN:\n- {\n- struct ovs_action_push_vlan *vlan;\n- PVOID vlanTagValue;\n- PNDIS_NET_BUFFER_LIST_8021Q_INFO vlanTag;\n-\n- if (ovsFwdCtx.destPortsSizeOut > 0 || ovsFwdCtx.tunnelTxNic != NULL\n- || ovsFwdCtx.tunnelRxNic != NULL) {\n- status = OvsOutputBeforeSetAction(&ovsFwdCtx);\n- if (status != NDIS_STATUS_SUCCESS) {\n- dropReason = L\"OVS-adding destination failed\";\n- goto dropit;\n- }\n- }\n-\n- vlanTagValue = NET_BUFFER_LIST_INFO(ovsFwdCtx.curNbl,\n- Ieee8021QNetBufferListInfo);\n- if (vlanTagValue != NULL) {\n- /*\n- * XXX: We don't support double VLAN tag offload. In such cases,\n- * we need to insert the existing one into the packet buffer,\n- * and add the new one as offload. This will take care of\n- * guest tag-in-tag case as well as OVS rules that specify\n- * tag-in-tag.\n- */\n- } else {\n- vlanTagValue = 0;\n- vlanTag = (PNDIS_NET_BUFFER_LIST_8021Q_INFO)(PVOID *)&vlanTagValue;\n- vlan = (struct ovs_action_push_vlan *)NlAttrGet((const PNL_ATTR)a);\n- vlanTag->TagHeader.VlanId = ntohs(vlan->vlan_tci) & 0xfff;\n- vlanTag->TagHeader.UserPriority = ntohs(vlan->vlan_tci) >> 13;\n- vlanTag->TagHeader.CanonicalFormatId = (ntohs(vlan->vlan_tci) >> 12) & 0x1;\n-\n- NET_BUFFER_LIST_INFO(ovsFwdCtx.curNbl,\n- Ieee8021QNetBufferListInfo) = vlanTagValue;\n- }\n- break;\n- }\n-\n- case OVS_ACTION_ATTR_POP_VLAN:\n- {\n- if (ovsFwdCtx.destPortsSizeOut > 0 || ovsFwdCtx.tunnelTxNic != NULL\n- || ovsFwdCtx.tunnelRxNic != NULL) {\n- status = OvsOutputBeforeSetAction(&ovsFwdCtx);\n- if (status != NDIS_STATUS_SUCCESS) {\n- dropReason = L\"OVS-adding destination failed\";\n- goto dropit;\n- }\n- }\n-\n- if (NET_BUFFER_LIST_INFO(ovsFwdCtx.curNbl,\n- Ieee8021QNetBufferListInfo) != 0) {\n- NET_BUFFER_LIST_INFO(ovsFwdCtx.curNbl,\n- Ieee8021QNetBufferListInfo) = 0;\n- } else {\n- /*\n- * The VLAN tag is inserted into the packet buffer. Pop the tag\n- * by packet buffer modification.\n- */\n- status = OvsPopVlanInPktBuf(&ovsFwdCtx);\n- if (status != NDIS_STATUS_SUCCESS) {\n- OVS_LOG_ERROR(\"OVS-pop vlan action failed status = %lu\", status);\n- dropReason = L\"OVS-pop vlan action failed\";\n- goto dropit;\n- }\n- }\n- /* Reset vlan header info in flowkey. */\n- key->l2.vlanKey.vlanTci = 0;\n- key->l2.vlanKey.vlanTpid = 0;\n- break;\n- }\n-\n- case OVS_ACTION_ATTR_PUSH_MPLS:\n- {\n- if (ovsFwdCtx.destPortsSizeOut > 0 || ovsFwdCtx.tunnelTxNic != NULL\n- || ovsFwdCtx.tunnelRxNic != NULL) {\n- status = OvsOutputBeforeSetAction(&ovsFwdCtx);\n- if (status != NDIS_STATUS_SUCCESS) {\n- dropReason = L\"OVS-adding destination failed\";\n- goto dropit;\n- }\n- }\n-\n- status = OvsActionMplsPush(&ovsFwdCtx,\n- (struct ovs_action_push_mpls *)NlAttrGet\n- ((const PNL_ATTR)a));\n- if (status != NDIS_STATUS_SUCCESS) {\n- dropReason = L\"OVS-push MPLS action failed\";\n- goto dropit;\n- }\n- layers->l3Offset += MPLS_HLEN;\n- layers->l4Offset += MPLS_HLEN;\n- break;\n- }\n-\n- case OVS_ACTION_ATTR_POP_MPLS:\n- {\n- if (ovsFwdCtx.destPortsSizeOut > 0 || ovsFwdCtx.tunnelTxNic != NULL\n- || ovsFwdCtx.tunnelRxNic != NULL) {\n- status = OvsOutputBeforeSetAction(&ovsFwdCtx);\n- if (status != NDIS_STATUS_SUCCESS) {\n- dropReason = L\"OVS-adding destination failed\";\n- goto dropit;\n- }\n- }\n-\n- status = OvsActionMplsPop(&ovsFwdCtx, NlAttrGetBe16(a));\n- if (status != NDIS_STATUS_SUCCESS) {\n- dropReason = L\"OVS-pop MPLS action failed\";\n- goto dropit;\n- }\n- layers->l3Offset -= MPLS_HLEN;\n- layers->l4Offset -= MPLS_HLEN;\n- break;\n- }\n-\n- case OVS_ACTION_ATTR_HASH:\n- {\n- if (ovsFwdCtx.destPortsSizeOut > 0 || ovsFwdCtx.tunnelTxNic != NULL\n- || ovsFwdCtx.tunnelRxNic != NULL) {\n- status = OvsOutputBeforeSetAction(&ovsFwdCtx);\n- if (status != NDIS_STATUS_SUCCESS) {\n- dropReason = L\"OVS-adding destination failed\";\n- goto dropit;\n- }\n- }\n-\n- OvsExecuteHash(key, (const PNL_ATTR)a);\n- break;\n- }\n-\n- case OVS_ACTION_ATTR_CT:\n- {\n- if (ovsFwdCtx.destPortsSizeOut > 0\n- || ovsFwdCtx.tunnelTxNic != NULL\n- || ovsFwdCtx.tunnelRxNic != NULL) {\n- status = OvsOutputBeforeSetAction(&ovsFwdCtx);\n- if (status != NDIS_STATUS_SUCCESS) {\n- dropReason = L\"OVS-adding destination failed\";\n- goto dropit;\n- }\n- }\n-\n- PNET_BUFFER_LIST oldNbl = ovsFwdCtx.curNbl;\n- status = OvsExecuteConntrackAction(&ovsFwdCtx, key,\n- (const PNL_ATTR)a);\n- if (status != NDIS_STATUS_SUCCESS) {\n- /* Pending NBLs are consumed by Defragmentation. */\n- if (status != NDIS_STATUS_PENDING) {\n- OVS_LOG_ERROR(\"CT Action failed status = %lu\", status);\n- dropReason = L\"OVS-conntrack action failed\";\n- } else {\n- /* We added a new pending NBL to be consumed later.\n- * Report to the userspace that the action applied\n- * successfully */\n- status = NDIS_STATUS_SUCCESS;\n- }\n- goto dropit;\n- } else if (oldNbl != ovsFwdCtx.curNbl) {\n- /*\n- * OvsIpv4Reassemble/OvsIpv6Reassemble consumes the\n- * original NBL and creates a new one and assigns\n- * it to the curNbl of ovsFwdCtx.\n- */\n- OvsInitForwardingCtx(&ovsFwdCtx,\n- ovsFwdCtx.switchContext,\n- ovsFwdCtx.curNbl,\n- ovsFwdCtx.srcVportNo,\n- ovsFwdCtx.sendFlags,\n- NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(ovsFwdCtx.curNbl),\n- ovsFwdCtx.completionList,\n- &ovsFwdCtx.layers, FALSE);\n- key->ipKey.nwFrag = OVS_FRAG_TYPE_NONE;\n- key->ipv6Key.nwFrag = OVS_FRAG_TYPE_NONE;\n- }\n- break;\n- }\n-\n- case OVS_ACTION_ATTR_RECIRC:\n- {\n- if (ovsFwdCtx.destPortsSizeOut > 0 || ovsFwdCtx.tunnelTxNic != NULL\n- || ovsFwdCtx.tunnelRxNic != NULL) {\n- status = OvsOutputBeforeSetAction(&ovsFwdCtx);\n- if (status != NDIS_STATUS_SUCCESS) {\n- dropReason = L\"OVS-adding destination failed\";\n- goto dropit;\n- }\n- }\n-\n- status = OvsExecuteRecirc(&ovsFwdCtx, key, (const PNL_ATTR)a, rem);\n- if (status != NDIS_STATUS_SUCCESS) {\n- dropReason = L\"OVS-recirculation action failed\";\n- goto dropit;\n- }\n-\n- if (NlAttrIsLast(a, rem)) {\n- goto exit;\n- }\n- break;\n- }\n-\n- case OVS_ACTION_ATTR_USERSPACE:\n- {\n- status = OvsOutputUserspaceAction(&ovsFwdCtx, key,\n- (const PNL_ATTR)a);\n- if (status != NDIS_STATUS_SUCCESS) {\n- dropReason = L\"OVS-Dropped due to failure to queue to \"\n- L\"userspace\";\n- goto dropit;\n- }\n- dropReason = L\"OVS-Completed since packet was copied to \"\n- L\"userspace\";\n- break;\n- }\n- case OVS_ACTION_ATTR_SET:\n- {\n- OvsIPTunnelKey pre_tunKey = { 0 };\n- if (ovsFwdCtx.destPortsSizeOut > 0 || ovsFwdCtx.tunnelTxNic != NULL\n- || ovsFwdCtx.tunnelRxNic != NULL) {\n- status = OvsOutputBeforeSetAction(&ovsFwdCtx);\n- if (status != NDIS_STATUS_SUCCESS) {\n- dropReason = L\"OVS-adding destination failed\";\n- goto dropit;\n- }\n- }\n- RtlCopyMemory(&pre_tunKey, &key->tunKey, sizeof key->tunKey);\n- status = OvsExecuteSetAction(&ovsFwdCtx, key, hash,\n- (const PNL_ATTR)NlAttrGet\n- ((const PNL_ATTR)a));\n- if (status != NDIS_STATUS_SUCCESS) {\n- dropReason = L\"OVS-set action failed\";\n- goto dropit;\n- }\n-\n- if (!OvsIphIsZero(&(key->tunKey.dst)) &&\n- key->l2.offset != OvsGetFlowIPL2Offset(&key->tunKey)) {\n- key->l2.offset = OvsGetFlowIPL2Offset(&ovsFwdCtx.tunKey);\n- }\n- if (!OvsIphIsZero(&(pre_tunKey.dst))) {\n- /*if pre_tunkey dst is not null in multiple IPV6 Geneve tunnels case,\n- * for broadcast and multicast packet the flow pipeline will set different\n- * tunnel setting on one flow. In such case, it needs to do layers update.\n- * Elsewise it will meet BSOD issue but in IPV4 tunnel the BSOD will not\n- * have construct case to make it happen.\n- */\n- status = OvsExtractLayers(ovsFwdCtx.curNbl, &ovsFwdCtx.layers);\n- if (status != NDIS_STATUS_SUCCESS) {\n- dropReason = L\"OVS-set action ExtractLayers failed\";\n- goto dropit;\n- }\n- }\n- break;\n- }\n- case OVS_ACTION_ATTR_METER: {\n- if (OvsMeterExecute(&ovsFwdCtx, NlAttrGetU32(a))) {\n- OVS_LOG_INFO(\"Drop packet\");\n- dropReason = L\"Ovs-meter exceed max rate\";\n- goto dropit;\n- }\n-\n- break;\n- }\n- case OVS_ACTION_ATTR_SAMPLE:\n- {\n- if (ovsFwdCtx.destPortsSizeOut > 0 || ovsFwdCtx.tunnelTxNic != NULL\n- || ovsFwdCtx.tunnelRxNic != NULL) {\n- status = OvsOutputBeforeSetAction(&ovsFwdCtx);\n- if (status != NDIS_STATUS_SUCCESS) {\n- dropReason = L\"OVS-adding destination failed\";\n- goto dropit;\n- }\n- }\n-\n- status = OvsExecuteSampleAction(&ovsFwdCtx, key,\n- (const PNL_ATTR)a);\n- if (status != NDIS_STATUS_SUCCESS) {\n- dropReason = L\"OVS-sample action failed\";\n- goto dropit;\n- }\n- break;\n- }\n- default:\n- status = NDIS_STATUS_NOT_SUPPORTED;\n- break;\n- }\n- }\n-\n- if (ovsFwdCtx.destPortsSizeOut > 0 || ovsFwdCtx.tunnelTxNic != NULL\n- || ovsFwdCtx.tunnelRxNic != NULL) {\n- status = OvsOutputForwardingCtx(&ovsFwdCtx);\n- ASSERT(ovsFwdCtx.curNbl == NULL);\n- }\n-\n- ASSERT(ovsFwdCtx.destPortsSizeOut == 0);\n- ASSERT(ovsFwdCtx.tunnelRxNic == NULL);\n- ASSERT(ovsFwdCtx.tunnelTxNic == NULL);\n-\n-dropit:\n- /*\n- * If curNbl != NULL, it implies the NBL has not been not freed up so far.\n- */\n- if (ovsFwdCtx.curNbl) {\n- OvsCompleteNBLForwardingCtx(&ovsFwdCtx, dropReason);\n- }\n-\n-exit:\n- return status;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsActionsExecute --\n- * The function interprets and executes the specified 'actions' on the\n- * specified packet 'curNbl'. See 'OvsDoExecuteActions' description for\n- * more details.\n- *\n- * Also executes deferred actions added by recirculation or sample\n- * actions.\n- * --------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsActionsExecute(POVS_SWITCH_CONTEXT switchContext,\n- OvsCompletionList *completionList,\n- PNET_BUFFER_LIST curNbl,\n- UINT32 portNo,\n- ULONG sendFlags,\n- OvsFlowKey *key,\n- UINT64 *hash,\n- OVS_PACKET_HDR_INFO *layers,\n- const PNL_ATTR actions,\n- INT actionsLen)\n-{\n- NDIS_STATUS status;\n-\n- status = OvsDoExecuteActions(switchContext, completionList, curNbl,\n- portNo, sendFlags, key, hash, layers,\n- actions, actionsLen);\n-\n- if (status == STATUS_SUCCESS) {\n- status = OvsProcessDeferredActions(switchContext, completionList,\n- portNo, sendFlags);\n- }\n-\n- return status;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsDoRecirc --\n- * The function processes the packet 'curNbl' that re-entered datapath\n- * packet processing after a recirculation action.\n- * --------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsDoRecirc(POVS_SWITCH_CONTEXT switchContext,\n- OvsCompletionList *completionList,\n- PNET_BUFFER_LIST curNbl,\n- OvsFlowKey *key,\n- UINT32 srcPortNo,\n- OVS_PACKET_HDR_INFO *layers)\n-{\n- NDIS_STATUS status;\n- OvsFlow *flow;\n- OvsForwardingContext ovsFwdCtx = { 0 };\n- UINT64 hash = 0;\n- ASSERT(layers);\n-\n- OvsInitForwardingCtx(&ovsFwdCtx, switchContext, curNbl,\n- srcPortNo, 0,\n- NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(curNbl),\n- completionList, layers, TRUE);\n- ASSERT(ovsFwdCtx.switchContext);\n-\n- flow = OvsLookupFlow(&ovsFwdCtx.switchContext->datapath, key, &hash, FALSE);\n- if (flow) {\n- UINT32 level = OvsDeferredActionsLevelGet();\n-\n- if (level > DEFERRED_ACTION_EXEC_LEVEL) {\n- OvsCompleteNBLForwardingCtx(&ovsFwdCtx,\n- L\"OVS-Dropped due to deferred actions execution level limit \\\n- reached\");\n- ovsActionStats.deferredActionsExecLimit++;\n- ovsFwdCtx.curNbl = NULL;\n- return NDIS_STATUS_FAILURE;\n- }\n-\n- OvsFlowUsed(flow, ovsFwdCtx.curNbl, &ovsFwdCtx.layers);\n- ovsFwdCtx.switchContext->datapath.hits++;\n-\n- OvsDeferredActionsLevelInc();\n-\n- status = OvsDoExecuteActions(ovsFwdCtx.switchContext,\n- ovsFwdCtx.completionList,\n- ovsFwdCtx.curNbl,\n- ovsFwdCtx.srcVportNo,\n- ovsFwdCtx.sendFlags,\n- key, &hash, &ovsFwdCtx.layers,\n- flow->actions, flow->actionsLen);\n- ovsFwdCtx.curNbl = NULL;\n-\n- OvsDeferredActionsLevelDec();\n- } else {\n- POVS_VPORT_ENTRY vport = NULL;\n- LIST_ENTRY missedPackets;\n- UINT32 num = 0;\n-\n- ovsFwdCtx.switchContext->datapath.misses++;\n- InitializeListHead(&missedPackets);\n- vport = OvsFindVportByPortNo(switchContext, srcPortNo);\n- if (vport == NULL || vport->ovsState != OVS_STATE_CONNECTED) {\n- OvsCompleteNBLForwardingCtx(&ovsFwdCtx,\n- L\"OVS-Dropped due to port removal\");\n- ovsActionStats.noVport++;\n- return NDIS_STATUS_SUCCESS;\n- }\n- status = OvsCreateAndAddPackets(NULL, 0, OVS_PACKET_CMD_MISS,\n- vport, key, ovsFwdCtx.curNbl,\n- OvsIsExternalVportByPortId(switchContext,\n- vport->portId),\n- &ovsFwdCtx.layers,\n- ovsFwdCtx.switchContext,\n- &missedPackets, &num);\n- if (num) {\n- OvsQueuePackets(&missedPackets, num);\n- }\n- if (status == NDIS_STATUS_SUCCESS) {\n- /* Complete the packet since it was copied to user buffer. */\n- OvsCompleteNBLForwardingCtx(&ovsFwdCtx,\n- L\"OVS-Dropped since packet was copied to userspace\");\n- ovsActionStats.flowMiss++;\n- } else {\n- OvsCompleteNBLForwardingCtx(&ovsFwdCtx,\n- L\"OVS-Dropped due to failure to queue to userspace\");\n- ovsActionStats.failedFlowMiss++;\n- status = NDIS_STATUS_FAILURE;\n- }\n- }\n-\n- return status;\n-}\ndiff --git a/datapath-windows/ovsext/Actions.h b/datapath-windows/ovsext/Actions.h\ndeleted file mode 100644\nindex 7329d0ed0..000000000\n--- a/datapath-windows/ovsext/Actions.h\n+++ /dev/null\n@@ -1,141 +0,0 @@\n-/*\n- * Copyright (c) 2016 Cloudbase Solutions Srl\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#ifndef __ACTIONS_H_\n-#define __ACTIONS_H_ 1\n-\n-#include \"Switch.h\"\n-#include \"PacketIO.h\"\n-\n-\n-/*\n- * There a lot of data that needs to be maintained while executing the pipeline\n- * as dictated by the actions of a flow, across different functions at different\n- * levels. Such data is put together in a 'context' structure. Care should be\n- * exercised while adding new members to the structure - only add ones that get\n- * used across multiple stages in the pipeline/get used in multiple functions.\n- */\n-typedef struct OvsForwardingContext {\n- POVS_SWITCH_CONTEXT switchContext;\n- /* The NBL currently used in the pipeline. */\n- PNET_BUFFER_LIST curNbl;\n- /* NDIS forwarding detail for 'curNbl'. */\n- PNDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO fwdDetail;\n- /* Array of destination ports for 'curNbl'. */\n- PNDIS_SWITCH_FORWARDING_DESTINATION_ARRAY destinationPorts;\n- /* send flags while sending 'curNbl' into NDIS. */\n- ULONG sendFlags;\n- /* Total number of output ports, used + unused, in 'curNbl'. */\n- UINT32 destPortsSizeIn;\n- /* Total number of used output ports in 'curNbl'. */\n- UINT32 destPortsSizeOut;\n- /*\n- * If 'curNbl' is not owned by OVS, they need to be tracked, if they need to\n- * be freed/completed.\n- */\n- OvsCompletionList *completionList;\n- /*\n- * vport number of 'curNbl' when it is passed from the PIF bridge to the INT\n- * bridge. ie. during tunneling on the Rx side.\n- */\n- UINT32 srcVportNo;\n-\n- /*\n- * Tunnel key:\n- * - specified in actions during tunneling Tx\n- * - extracted from an NBL during tunneling Rx\n- */\n- OvsIPTunnelKey tunKey;\n-\n- /*\n- * Tunneling - Tx:\n- * To store the output port, when it is a tunneled port. We don't foresee\n- * multiple tunneled ports as outport for any given NBL.\n- */\n- POVS_VPORT_ENTRY tunnelTxNic;\n-\n- /*\n- * Tunneling - Rx:\n- * Points to the Internal port on the PIF Bridge, if the packet needs to be\n- * de-tunneled.\n- */\n- POVS_VPORT_ENTRY tunnelRxNic;\n-\n- /* header information */\n- OVS_PACKET_HDR_INFO layers;\n-} OvsForwardingContext;\n-\n-NDIS_STATUS\n-OvsActionsExecute(POVS_SWITCH_CONTEXT switchContext,\n- OvsCompletionList *completionList,\n- PNET_BUFFER_LIST curNbl,\n- UINT32 srcVportNo,\n- ULONG sendFlags,\n- OvsFlowKey *key,\n- UINT64 *hash,\n- OVS_PACKET_HDR_INFO *layers,\n- const PNL_ATTR actions,\n- int actionsLen);\n-\n-NDIS_STATUS\n-OvsDoExecuteActions(POVS_SWITCH_CONTEXT switchContext,\n- OvsCompletionList *completionList,\n- PNET_BUFFER_LIST curNbl,\n- UINT32 srcVportNo,\n- ULONG sendFlags,\n- OvsFlowKey *key,\n- UINT64 *hash,\n- OVS_PACKET_HDR_INFO *layers,\n- const PNL_ATTR actions,\n- int actionsLen);\n-\n-NDIS_STATUS\n-OvsDoRecirc(POVS_SWITCH_CONTEXT switchContext,\n- OvsCompletionList *completionList,\n- PNET_BUFFER_LIST curNbl,\n- OvsFlowKey *key,\n- UINT32 srcPortNo,\n- OVS_PACKET_HDR_INFO *layers);\n-\n-PUINT8 OvsGetHeaderBySize(OvsForwardingContext *ovsFwdCtx,\n- UINT32 size);\n-\n-NDIS_STATUS\n-OvsUpdateUdpPorts(OvsForwardingContext *ovsFwdCtx,\n- OvsFlowKey *key,\n- const struct ovs_key_udp *udpAttr);\n-\n-NDIS_STATUS\n-OvsUpdateTcpPorts(OvsForwardingContext *ovsFwdCtx,\n- OvsFlowKey *key,\n- const struct ovs_key_tcp *tcpAttr);\n-\n-NDIS_STATUS\n-OvsUpdateIPv4Header(OvsForwardingContext *ovsFwdCtx,\n- OvsFlowKey *key,\n- const struct ovs_key_ipv4 *ipAttr);\n-\n-NDIS_STATUS\n-OvsUpdateAddressAndPort(OvsForwardingContext *ovsFwdCtx,\n- UINT32 newAddr, UINT16 newPort,\n- BOOLEAN isSource, BOOLEAN isTx);\n-\n-NDIS_STATUS\n-OvsUpdateAddressAndPortForIpv6(OvsForwardingContext *ovsFwdCtx,\n- struct in6_addr newAddr, UINT16 newPort,\n- BOOLEAN isSource, BOOLEAN isTx);\n-\n-#endif /* __ACTIONS_H_ */\ndiff --git a/datapath-windows/ovsext/Atomic.h b/datapath-windows/ovsext/Atomic.h\ndeleted file mode 100644\nindex 1e45d9f89..000000000\n--- a/datapath-windows/ovsext/Atomic.h\n+++ /dev/null\n@@ -1,32 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#ifndef __ATOMIC_H_\n-#define __ATOMIC_H_ 1\n-\n-static __inline UINT64\n-atomic_add64(UINT64 *ptr, UINT32 val)\n-{\n- return InterlockedAdd64((LONGLONG volatile *) ptr, (LONGLONG) val);\n-}\n-\n-static __inline UINT64\n-atomic_inc64(UINT64 *ptr)\n-{\n- return InterlockedIncrement64((LONGLONG volatile *) ptr);\n-}\n-\n-#endif /* __ATOMIC_H_ */\ndiff --git a/datapath-windows/ovsext/BufferMgmt.c b/datapath-windows/ovsext/BufferMgmt.c\ndeleted file mode 100644\nindex 5c52757a0..000000000\n--- a/datapath-windows/ovsext/BufferMgmt.c\n+++ /dev/null\n@@ -1,2244 +0,0 @@\n-/*\n- * Copyright (c) 2014, 2016 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-/*\n- * ****************************************************************************\n- *\n- * Simple Buffer Management framework for OVS\n- *\n- * It introduces four NDIS buffer pools\n- * **Fix size net buffer list pool--this is used for small buffer\n- * One allocation will include NBL + NB + MDL + Data + CONTEXT.\n- *\n- * **Variable size net buffer list pool--this is used for variable size\n- * buffer. The allocation of net buffer list will include NBL + NB +\n- * CONTEXT, a separate allocation of MDL + data buffer is required.\n- *\n- * **NBL only net buffer list pool-- this is used for partial copy\n- * (or clone). In this case we can not allocate net buffer list and\n- * net buffer at the same time.\n- *\n- * **Net buffer pool-- this is required when net buffer need to be\n- * allocated separately.\n- *\n- * A Buffer context is defined to track the buffer specific information\n- * so that during NBL completion, proper action can be taken. Please see\n- * code for details.\n- *\n- * Here is the usage of the management API\n- * All external NBL should be initialized its NBL context by calling\n- * OvsInitExternalNBLContext()\n- *\n- * After the external NBL context is initialized, it can call the following\n- * API to allocate, copy or partial copy NBL.\n- *\n- * OvsAllocateFixSizeNBL()\n- * OvsAllocateVariableSizeNBL()\n- *\n- * OvsPartialCopyNBL()\n- * OvsPartialCopyToMultipleNBLs()\n- *\n- * OvsFullCopyNBL()\n- * OvsFullCopyToMultipleNBLs()\n- *\n- * See code comments for detail description of the functions.\n- *\n- * All NBLs is completed through\n- * OvsCompleteNBL()\n- * If this API return non NULL value, then the returned NBL should be\n- * returned to upper layer by calling\n- * NdisFSendNetBufferListsComplete() if the buffer is from upper\n- * layer. In case of WFP, it can call the corresponding completion routine\n- * to return the NBL to the framework.\n- *\n- * NOTE:\n- * 1. Copy or partial copy will not copy destination port array\n- * 2. Copy or partial copy will copy src port id and index\n- * 3. New Allocated NBL will have src port set to default port id\n- * 4. If original packet has direction flag set, the copied or partial\n- * copied NBL will still be in same direction.\n- * 5. When you advance or retreate the buffer, you may need to update\n- * relevant meta data to keep it consistent.\n- *\n- * ****************************************************************************\n- */\n-\n-#include \"precomp.h\"\n-#include \"jhash.h\"\n-#include \"Debug.h\"\n-#include \"Flow.h\"\n-#include \"Offload.h\"\n-#include \"NetProto.h\"\n-#include \"PacketIO.h\"\n-#include \"PacketParser.h\"\n-#include \"Switch.h\"\n-#include \"Vport.h\"\n-\n-#ifdef OVS_DBG_MOD\n-#undef OVS_DBG_MOD\n-#endif\n-#define OVS_DBG_MOD OVS_DBG_BUFMGMT\n-/*\n- * --------------------------------------------------------------------------\n- * OvsInitBufferPool --\n- *\n- * Allocate NBL and NB pool\n- *\n- * XXX: more optimization may be done for buffer management include local cache\n- * of NBL, NB, data, context, MDL.\n- * --------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsInitBufferPool(PVOID ovsContext)\n-{\n- POVS_NBL_POOL ovsPool;\n- POVS_SWITCH_CONTEXT context = (POVS_SWITCH_CONTEXT)ovsContext;\n- NET_BUFFER_LIST_POOL_PARAMETERS nblParam;\n- NET_BUFFER_POOL_PARAMETERS nbParam;\n-\n- C_ASSERT(MEMORY_ALLOCATION_ALIGNMENT >= 8);\n-\n- OVS_LOG_TRACE(\"Enter: context: %p\", context);\n-\n- ovsPool = &context->ovsPool;\n- RtlZeroMemory(ovsPool, sizeof (OVS_NBL_POOL));\n- ovsPool->ndisHandle = context->NdisFilterHandle;\n- ovsPool->ndisContext = context->NdisSwitchContext;\n- /*\n- * fix size NBL pool includes\n- * NBL + NB + MDL + DATA + Context\n- * This is mainly used for Packet execute or slow path when copy is\n- * required and size is less than OVS_DEFAULT_DATA_SIZE. We expect\n- * Most of packet from user space will use this Pool. (This is\n- * true for all bfd and cfm packet.\n- */\n- RtlZeroMemory(&nblParam, sizeof (nblParam));\n- OVS_INIT_OBJECT_HEADER(&nblParam.Header,\n- NDIS_OBJECT_TYPE_DEFAULT,\n- NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1,\n- NDIS_SIZEOF_NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1);\n- nblParam.ContextSize = OVS_DEFAULT_NBL_CONTEXT_SIZE;\n- nblParam.PoolTag = OVS_FIX_SIZE_NBL_POOL_TAG;\n- nblParam.fAllocateNetBuffer = TRUE;\n- nblParam.DataSize = OVS_DEFAULT_DATA_SIZE + OVS_DEFAULT_HEADROOM_SIZE;\n-\n- ovsPool->fixSizePool =\n- NdisAllocateNetBufferListPool(context->NdisSwitchContext, &nblParam);\n- if (ovsPool->fixSizePool == NULL) {\n- goto pool_cleanup;\n- }\n-\n- /*\n- * Zero Size NBL Pool includes\n- * NBL + NB + Context\n- * This is mainly for packet with large data Size, in this case MDL and\n- * Data will be allocate separately.\n- */\n- RtlZeroMemory(&nblParam, sizeof (nblParam));\n- OVS_INIT_OBJECT_HEADER(&nblParam.Header,\n- NDIS_OBJECT_TYPE_DEFAULT,\n- NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1,\n- NDIS_SIZEOF_NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1);\n-\n- nblParam.ContextSize = OVS_DEFAULT_NBL_CONTEXT_SIZE;\n- nblParam.PoolTag = OVS_VARIABLE_SIZE_NBL_POOL_TAG;\n- nblParam.fAllocateNetBuffer = TRUE;\n- nblParam.DataSize = 0;\n-\n- ovsPool->zeroSizePool =\n- NdisAllocateNetBufferListPool(context->NdisSwitchContext, &nblParam);\n- if (ovsPool->zeroSizePool == NULL) {\n- goto pool_cleanup;\n- }\n-\n- /*\n- * NBL only pool just includes\n- * NBL (+ context)\n- * This is mainly used for clone and partial copy\n- */\n- RtlZeroMemory(&nblParam, sizeof (nblParam));\n- OVS_INIT_OBJECT_HEADER(&nblParam.Header,\n- NDIS_OBJECT_TYPE_DEFAULT,\n- NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1,\n- NDIS_SIZEOF_NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1);\n-\n- nblParam.ContextSize = OVS_DEFAULT_NBL_CONTEXT_SIZE;\n- nblParam.PoolTag = OVS_NBL_ONLY_POOL_TAG;\n- nblParam.fAllocateNetBuffer = FALSE;\n- nblParam.DataSize = 0;\n-\n- ovsPool->nblOnlyPool =\n- NdisAllocateNetBufferListPool(context->NdisSwitchContext, &nblParam);\n- if (ovsPool->nblOnlyPool == NULL) {\n- goto pool_cleanup;\n- }\n-\n- /* nb Pool\n- * NB only pool, used for copy\n- */\n-\n- OVS_INIT_OBJECT_HEADER(&nbParam.Header,\n- NDIS_OBJECT_TYPE_DEFAULT,\n- NET_BUFFER_POOL_PARAMETERS_REVISION_1,\n- NDIS_SIZEOF_NET_BUFFER_POOL_PARAMETERS_REVISION_1);\n- nbParam.PoolTag = OVS_NET_BUFFER_POOL_TAG;\n- nbParam.DataSize = 0;\n- ovsPool->nbPool =\n- NdisAllocateNetBufferPool(context->NdisSwitchContext, &nbParam);\n- if (ovsPool->nbPool == NULL) {\n- goto pool_cleanup;\n- }\n- OVS_LOG_TRACE(\"Exit: fixSizePool: %p zeroSizePool: %p nblOnlyPool: %p\"\n- \"nbPool: %p\", ovsPool->fixSizePool, ovsPool->zeroSizePool,\n- ovsPool->nblOnlyPool, ovsPool->nbPool);\n- return NDIS_STATUS_SUCCESS;\n-\n-pool_cleanup:\n- OvsCleanupBufferPool(context);\n- OVS_LOG_TRACE(\"Exit: Fail to initialize ovs buffer pool\");\n- return NDIS_STATUS_RESOURCES;\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsCleanupBufferPool --\n- * Free Buffer pool for NBL and NB.\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-OvsCleanupBufferPool(PVOID ovsContext)\n-{\n- POVS_NBL_POOL ovsPool;\n- POVS_SWITCH_CONTEXT context = (POVS_SWITCH_CONTEXT)ovsContext;\n- ovsPool = &context->ovsPool;\n- OVS_LOG_TRACE(\"Enter: context: %p\", context);\n-#ifdef DBG\n- ASSERT(ovsPool->fixNBLCount == 0);\n- ASSERT(ovsPool->zeroNBLCount == 0);\n- ASSERT(ovsPool->nblOnlyCount == 0);\n- ASSERT(ovsPool->nbCount == 0);\n- ASSERT(ovsPool->sysNBLCount == 0);\n- ASSERT(ovsPool->fragNBLCount == 0);\n-#endif\n-\n- if (ovsPool->fixSizePool) {\n- NdisFreeNetBufferListPool(ovsPool->fixSizePool);\n- ovsPool->fixSizePool = NULL;\n- }\n- if (ovsPool->zeroSizePool) {\n- NdisFreeNetBufferListPool(ovsPool->zeroSizePool);\n- ovsPool->zeroSizePool = NULL;\n- }\n- if (ovsPool->nblOnlyPool) {\n- NdisFreeNetBufferListPool(ovsPool->nblOnlyPool);\n- ovsPool->nblOnlyPool = NULL;\n- }\n- if (ovsPool->nbPool) {\n- NdisFreeNetBufferPool(ovsPool->nbPool);\n- ovsPool->nbPool = NULL;\n- }\n- OVS_LOG_TRACE(\"Exit: cleanup OVS Buffer pool\");\n-}\n-\n-\n-static VOID\n-OvsInitNBLContext(POVS_BUFFER_CONTEXT ctx,\n- UINT16 flags,\n- UINT32 origDataLength,\n- UINT32 srcPortNo,\n- UINT16 mru)\n-{\n- ctx->magic = OVS_CTX_MAGIC;\n- ctx->refCount = 1;\n- ctx->flags = flags;\n- ctx->srcPortNo = srcPortNo;\n- ctx->origDataLength = origDataLength;\n- ctx->mru = mru;\n- ctx->pendingSend = 0;\n-}\n-\n-\n-static VOID\n-OvsDumpForwardingDetails(PNET_BUFFER_LIST nbl)\n-{\n-#if OVS_DBG_DEFAULT >= OVS_DBG_LOUD\n- PNDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO info;\n- info = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(nbl);\n- if (info == NULL) {\n- return;\n- }\n- OVS_LOG_INFO(\"nbl: %p, numAvailableDest: %d, srcId:%d, srcIndex: %d \"\n- \"isDataSafe: %s, safeDataSize: %d\",\n- nbl, info->NumAvailableDestinations, info->SourcePortId,\n- info->SourceNicIndex,\n- info->IsPacketDataSafe ? \"TRUE\" : \"FALSE\",\n- info->IsPacketDataSafe ? 0 : info->SafePacketDataSize);\n-#else\n- UNREFERENCED_PARAMETER(nbl);\n-#endif\n-}\n-\n-static VOID\n-OvsDumpNBLContext(PNET_BUFFER_LIST nbl)\n-{\n-#if OVS_DBG_DEFAULT >= OVS_DBG_LOUD\n- PNET_BUFFER_LIST_CONTEXT ctx = nbl->Context;\n- if (ctx == NULL) {\n- OVS_LOG_INFO(\"No Net Buffer List context\");\n- return;\n- }\n- while (ctx) {\n- OVS_LOG_INFO(\"nbl: %p, ctx: %p, TotalSize: %d, Offset: %d\",\n- nbl, ctx, ctx->Size, ctx->Offset);\n- ctx = ctx->Next;\n- }\n-#else\n- UNREFERENCED_PARAMETER(nbl);\n-#endif\n-}\n-\n-\n-static VOID\n-OvsDumpMDLChain(PMDL mdl)\n-{\n- PMDL tmp;\n- tmp = mdl;\n- while (tmp) {\n- OVS_LOG_INFO(\"MDL: %p, Size: %d, MappedSystemVa: %p, StartVa: %p\"\n- \" ByteCount: %d, ByteOffset: %d\",\n- tmp, tmp->Size, tmp->MappedSystemVa,\n- tmp->StartVa, tmp->ByteCount, tmp->ByteOffset);\n- tmp = tmp->Next;\n- }\n-}\n-\n-\n-static VOID\n-OvsDumpNetBuffer(PNET_BUFFER nb)\n-{\n- OVS_LOG_INFO(\"NET_BUFFER: %p, ChecksumBias: %d Handle: %p, MDLChain: %p \"\n- \"CurrMDL: %p, CurrOffset: %d, DataLen: %d, Offset: %d\",\n- nb,\n- NET_BUFFER_CHECKSUM_BIAS(nb), nb->NdisPoolHandle,\n- NET_BUFFER_FIRST_MDL(nb),\n- NET_BUFFER_CURRENT_MDL(nb),\n- NET_BUFFER_CURRENT_MDL_OFFSET(nb),\n- NET_BUFFER_DATA_LENGTH(nb),\n- NET_BUFFER_DATA_OFFSET(nb));\n- OvsDumpMDLChain(NET_BUFFER_FIRST_MDL(nb));\n-}\n-\n-\n-static VOID\n-OvsDumpNetBufferList(PNET_BUFFER_LIST nbl)\n-{\n-#if OVS_DBG_DEFAULT >= OVS_DBG_LOUD\n- PNET_BUFFER nb;\n- OVS_LOG_INFO(\"NBL: %p, parent: %p, SrcHandle: %p, ChildCount:%d \"\n- \"poolHandle: %p\",\n- nbl, nbl->ParentNetBufferList,\n- nbl->SourceHandle, nbl->ChildRefCount,\n- nbl->NdisPoolHandle);\n- OvsDumpNBLContext(nbl);\n- nb = NET_BUFFER_LIST_FIRST_NB(nbl);\n- while (nb) {\n- OvsDumpNetBuffer(nb);\n- nb = NET_BUFFER_NEXT_NB(nb);\n- }\n-#else\n- UNREFERENCED_PARAMETER(nbl);\n-#endif\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsAllocateFixSizeNBL --\n- *\n- * Allocate fix size NBL which include\n- * NBL + NB + MBL + Data + Context\n- * Please note:\n- * * Forwarding Context is allocated, but forwarding detail information\n- * is not initailized.\n- * * The headroom can not be larger than OVS_DEFAULT_HEADROOM_SIZE(128\n- * byte).\n- * --------------------------------------------------------------------------\n- */\n-PNET_BUFFER_LIST\n-OvsAllocateFixSizeNBL(PVOID ovsContext,\n- UINT32 size,\n- UINT32 headRoom)\n-{\n- PNET_BUFFER_LIST nbl = NULL;\n- POVS_SWITCH_CONTEXT context = (POVS_SWITCH_CONTEXT)ovsContext;\n- POVS_BUFFER_CONTEXT ctx;\n- POVS_NBL_POOL ovsPool = &context->ovsPool;\n- NDIS_STATUS status;\n- UINT32 line;\n- PNDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO info;\n-\n- if ((headRoom + size) > OVS_FIX_NBL_DATA_SIZE || size == 0) {\n- line = __LINE__;\n- goto allocate_done;\n- }\n-\n- nbl = NdisAllocateNetBufferList(ovsPool->fixSizePool,\n- (UINT16)sizeof (OVS_BUFFER_CONTEXT),\n- (UINT16)OVS_DEFAULT_NBL_CONTEXT_FILL);\n-\n- if (nbl == NULL) {\n- line = __LINE__;\n- goto allocate_done;\n- }\n-\n- nbl->SourceHandle = ovsPool->ndisHandle;\n- status = context->NdisSwitchHandlers.\n- AllocateNetBufferListForwardingContext(ovsPool->ndisContext, nbl);\n-\n- if (status != NDIS_STATUS_SUCCESS) {\n- NdisFreeNetBufferList(nbl);\n- nbl = NULL;\n- line = __LINE__;\n- goto allocate_done;\n- }\n- info = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(nbl);\n- ASSERT(info);\n- info->IsPacketDataSafe = TRUE;\n- info->SourcePortId = NDIS_SWITCH_DEFAULT_PORT_ID;\n-\n- status = NdisRetreatNetBufferDataStart(NET_BUFFER_LIST_FIRST_NB(nbl),\n- size, 0, NULL);\n- ASSERT(status == NDIS_STATUS_SUCCESS);\n-\n-#ifdef DBG\n- InterlockedIncrement((LONG volatile *)&ovsPool->fixNBLCount);\n- OvsDumpNetBufferList(nbl);\n- OvsDumpForwardingDetails(nbl);\n-#endif\n-\n- ctx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl);\n- ASSERT(ctx);\n-\n- OvsInitNBLContext(ctx, OVS_BUFFER_FROM_FIX_SIZE_POOL |\n- OVS_BUFFER_PRIVATE_FORWARD_CONTEXT, size,\n- OVS_DPPORT_NUMBER_INVALID, 0);\n- line = __LINE__;\n-allocate_done:\n- OVS_LOG_LOUD(\"Allocate Fix NBL: %p, line: %d\", nbl, line);\n- return nbl;\n-}\n-\n-\n-static PMDL\n-OvsAllocateMDLAndData(NDIS_HANDLE ndisHandle,\n- UINT32 dataSize)\n-{\n- PMDL mdl;\n- PVOID data;\n-\n- data = OvsAllocateMemoryWithTag(dataSize, OVS_MDL_POOL_TAG);\n- if (data == NULL) {\n- return NULL;\n- }\n-\n- mdl = NdisAllocateMdl(ndisHandle, data, dataSize);\n- if (mdl == NULL) {\n- OvsFreeMemoryWithTag(data, OVS_MDL_POOL_TAG);\n- }\n-\n- return mdl;\n-}\n-\n-\n-static VOID\n-OvsFreeMDLAndData(PMDL mdl)\n-{\n- PVOID data;\n-\n- data = MmGetMdlVirtualAddress(mdl);\n- NdisFreeMdl(mdl);\n- OvsFreeMemoryWithTag(data, OVS_MDL_POOL_TAG);\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsAllocateVariableSizeNBL --\n- *\n- * Allocate variable size NBL, the NBL looks like\n- * NBL + NB + Context\n- * MDL + Data\n- * --------------------------------------------------------------------------\n- */\n-PNET_BUFFER_LIST\n-OvsAllocateVariableSizeNBL(PVOID ovsContext,\n- UINT32 size,\n- UINT32 headRoom)\n-{\n- PNET_BUFFER_LIST nbl = NULL;\n- POVS_SWITCH_CONTEXT context = (POVS_SWITCH_CONTEXT)ovsContext;\n- POVS_NBL_POOL ovsPool = &context->ovsPool;\n- POVS_BUFFER_CONTEXT ctx;\n- UINT32 realSize;\n- PMDL mdl;\n- NDIS_STATUS status;\n- PNDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO info;\n- if (size == 0) {\n- return NULL;\n- }\n- realSize = MEM_ALIGN_SIZE(size + headRoom);\n-\n- mdl = OvsAllocateMDLAndData(ovsPool->ndisHandle, realSize);\n- if (mdl == NULL) {\n- return NULL;\n- }\n-\n- nbl = NdisAllocateNetBufferAndNetBufferList(ovsPool->zeroSizePool,\n- (UINT16)sizeof (OVS_BUFFER_CONTEXT),\n- (UINT16)OVS_DEFAULT_NBL_CONTEXT_FILL,\n- mdl, realSize, 0);\n- if (nbl == NULL) {\n- OvsFreeMDLAndData(mdl);\n- return NULL;\n- }\n-\n- nbl->SourceHandle = ovsPool->ndisHandle;\n- status = context->NdisSwitchHandlers.\n- AllocateNetBufferListForwardingContext(ovsPool->ndisContext, nbl);\n-\n- if (status != NDIS_STATUS_SUCCESS) {\n- /*\n- * do we need to remove mdl from nbl XXX\n- */\n- OvsFreeMDLAndData(mdl);\n- NdisFreeNetBufferList(nbl);\n- return NULL;\n- }\n-\n- info = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(nbl);\n- ASSERT(info);\n- info->IsPacketDataSafe = TRUE;\n- info->SourcePortId = NDIS_SWITCH_DEFAULT_PORT_ID;\n- status = NdisRetreatNetBufferDataStart(NET_BUFFER_LIST_FIRST_NB(nbl),\n- size, 0, NULL);\n- ASSERT(status == NDIS_STATUS_SUCCESS);\n-\n-#ifdef DBG\n- InterlockedIncrement((LONG volatile *)&ovsPool->zeroNBLCount);\n- OvsDumpNetBufferList(nbl);\n- OvsDumpForwardingDetails(nbl);\n-#endif\n-\n- ctx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl);\n-\n- OvsInitNBLContext(ctx, OVS_BUFFER_PRIVATE_MDL | OVS_BUFFER_PRIVATE_DATA |\n- OVS_BUFFER_PRIVATE_FORWARD_CONTEXT |\n- OVS_BUFFER_FROM_ZERO_SIZE_POOL,\n- size, OVS_DPPORT_NUMBER_INVALID, 0);\n-\n- OVS_LOG_LOUD(\"Allocate variable size NBL: %p\", nbl);\n- return nbl;\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsInitExternalNBLContext --\n- *\n- * For NBL not allocated by OVS, it will allocate and initialize\n- * the NBL context.\n- * --------------------------------------------------------------------------\n- */\n-POVS_BUFFER_CONTEXT\n-OvsInitExternalNBLContext(PVOID ovsContext,\n- PNET_BUFFER_LIST nbl,\n- BOOLEAN isRecv)\n-{\n- NDIS_HANDLE poolHandle;\n- POVS_SWITCH_CONTEXT context = (POVS_SWITCH_CONTEXT)ovsContext;\n- POVS_BUFFER_CONTEXT ctx;\n- PNET_BUFFER nb;\n- NDIS_STATUS status;\n- UINT16 flags;\n-\n- poolHandle = NdisGetPoolFromNetBufferList(nbl);\n-\n- if (poolHandle == context->ovsPool.ndisHandle ||\n- nbl->SourceHandle == context->ovsPool.ndisHandle) {\n- return (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl);\n- }\n- status = NdisAllocateNetBufferListContext(nbl, sizeof (OVS_BUFFER_CONTEXT),\n- OVS_DEFAULT_NBL_CONTEXT_FILL,\n- OVS_OTHER_POOL_TAG);\n- if (status != NDIS_STATUS_SUCCESS) {\n- return NULL;\n- }\n-#ifdef DBG\n- OvsDumpNBLContext(nbl);\n- InterlockedIncrement((LONG volatile *)&context->ovsPool.sysNBLCount);\n-#endif\n- flags = isRecv ? OVS_BUFFER_RECV_BUFFER : OVS_BUFFER_SEND_BUFFER;\n- flags |= OVS_BUFFER_NEED_COMPLETE | OVS_BUFFER_PRIVATE_CONTEXT;\n- ctx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl);\n-\n- nb = NET_BUFFER_LIST_FIRST_NB(nbl);\n- /*\n- * we use first nb to decide whether we need advance or retreat during\n- * complete.\n- */\n- OvsInitNBLContext(ctx, flags, NET_BUFFER_DATA_LENGTH(nb),\n- OVS_DPPORT_NUMBER_INVALID, 0);\n- return ctx;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsAllocateNBLContext\n- *\n- * Create NBL buffer context and forwarding context.\n- * --------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsAllocateNBLContext(POVS_SWITCH_CONTEXT context,\n- PNET_BUFFER_LIST nbl)\n-{\n- POVS_NBL_POOL ovsPool = &context->ovsPool;\n- NDIS_STATUS status;\n-\n- status = NdisAllocateNetBufferListContext(nbl,\n- sizeof (OVS_BUFFER_CONTEXT),\n- OVS_DEFAULT_NBL_CONTEXT_FILL,\n- OVS_OTHER_POOL_TAG);\n- if (status != NDIS_STATUS_SUCCESS) {\n- return NDIS_STATUS_FAILURE;\n- }\n-\n- nbl->SourceHandle = ovsPool->ndisHandle;\n- status = context->NdisSwitchHandlers.\n- AllocateNetBufferListForwardingContext(ovsPool->ndisContext, nbl);\n-\n- if (status != NDIS_STATUS_SUCCESS) {\n- NdisFreeNetBufferListContext(nbl, sizeof (OVS_BUFFER_CONTEXT));\n- return NDIS_STATUS_FAILURE;\n- }\n- return status;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsFreeNBLContext\n- *\n- * Free the NBL buffer context and forwarding context.\n- * --------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsFreeNBLContext(POVS_SWITCH_CONTEXT context,\n- PNET_BUFFER_LIST nbl)\n-{\n- POVS_NBL_POOL ovsPool = &context->ovsPool;\n-\n- context->NdisSwitchHandlers.\n- FreeNetBufferListForwardingContext(ovsPool->ndisContext, nbl);\n- NdisFreeNetBufferListContext(nbl, sizeof (OVS_BUFFER_CONTEXT));\n-\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsCopyNBLInfo\n- *\n- * Copy NBL info from src to dst\n- * --------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsCopyNBLInfo(PNET_BUFFER_LIST srcNbl, PNET_BUFFER_LIST dstNbl,\n- POVS_BUFFER_CONTEXT srcCtx, UINT32 copySize,\n- BOOLEAN copyNblInfo)\n-{\n- PNDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO srcInfo, dstInfo;\n- NDIS_STATUS status = NDIS_STATUS_SUCCESS;\n-\n- srcInfo = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(srcNbl);\n- dstInfo = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(dstNbl);\n- if (srcInfo) {\n-#ifdef OVS_USE_COPY_NET_BUFFER_LIST_INFO\n- status = context->NdisSwitchHandlers.\n- CopyNetBufferListInfo(ovsPool->ndisContext, dstNbl, srcNbl, 0);\n-\n- if (status != NDIS_STATUS_SUCCESS) {\n- return status;\n- }\n-#else\n- dstInfo->SourcePortId = srcInfo->SourcePortId;\n- dstInfo->SourceNicIndex = srcInfo->SourceNicIndex;\n- if (copyNblInfo) {\n- if (srcCtx->flags & OVS_BUFFER_RECV_BUFFER) {\n- NdisCopyReceiveNetBufferListInfo(dstNbl, srcNbl);\n- } else if (srcCtx->flags & OVS_BUFFER_SEND_BUFFER) {\n- NdisCopySendNetBufferListInfo(dstNbl, srcNbl);\n- }\n- }\n-#endif\n- dstInfo->IsPacketDataSafe = srcInfo->IsPacketDataSafe;\n- if (!srcInfo->IsPacketDataSafe && copySize >\n- srcInfo->SafePacketDataSize) {\n- srcInfo->SafePacketDataSize = copySize;\n- }\n- } else {\n- /*\n- * Assume all data are safe\n- */\n- dstInfo->IsPacketDataSafe = TRUE;\n- dstInfo->SourcePortId = NDIS_SWITCH_DEFAULT_PORT_ID;\n- }\n- return status;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsPartialCopyNBL --\n- *\n- * Partial copy NBL, if there is multiple NB in NBL, each one will be\n- * copied. We also reserve headroom for the new NBL.\n- *\n- * Please note,\n- * NBL should have OVS_BUFFER_CONTEXT setup before calling\n- * this function.\n- * The NBL should already have ref to itself so that during copy\n- * it will not be freed.\n- * --------------------------------------------------------------------------\n- */\n-PNET_BUFFER_LIST\n-OvsPartialCopyNBL(PVOID ovsContext,\n- PNET_BUFFER_LIST nbl,\n- UINT32 copySize,\n- UINT32 headRoom,\n- BOOLEAN copyNblInfo)\n-{\n- PNET_BUFFER_LIST newNbl;\n- POVS_SWITCH_CONTEXT context = (POVS_SWITCH_CONTEXT)ovsContext;\n- NDIS_STATUS status;\n- PNET_BUFFER srcNb, dstNb;\n- ULONG byteCopied;\n- POVS_NBL_POOL ovsPool = &context->ovsPool;\n- POVS_BUFFER_CONTEXT srcCtx, dstCtx;\n- UINT16 flags;\n-\n- srcCtx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl);\n- if (srcCtx == NULL || srcCtx->magic != OVS_CTX_MAGIC) {\n- OVS_LOG_INFO(\"src nbl must have ctx initialized\");\n- ASSERT(srcCtx && srcCtx->magic == OVS_CTX_MAGIC);\n- return NULL;\n- }\n-\n- if (copySize) {\n- NdisAdvanceNetBufferListDataStart(nbl, copySize, FALSE, NULL);\n- }\n- newNbl = NdisAllocateCloneNetBufferList(nbl, ovsPool->nblOnlyPool,\n- NULL, 0);\n- if (copySize) {\n- status = NdisRetreatNetBufferListDataStart(nbl, copySize, 0,\n- NULL, NULL);\n- ASSERT(status == NDIS_STATUS_SUCCESS);\n- }\n-\n- if (newNbl == NULL) {\n- return NULL;\n- }\n-\n- /*\n- * Allocate private memory for copy\n- */\n- if (copySize + headRoom) {\n- status = NdisRetreatNetBufferListDataStart(newNbl, copySize + headRoom,\n- 0, NULL, NULL);\n- if (status != NDIS_STATUS_SUCCESS) {\n- goto retreat_error;\n- }\n-\n- if (headRoom) {\n- NdisAdvanceNetBufferListDataStart(newNbl, headRoom, FALSE, NULL);\n- }\n- if (copySize) {\n- srcNb = NET_BUFFER_LIST_FIRST_NB(nbl);\n- dstNb = NET_BUFFER_LIST_FIRST_NB(newNbl);\n-\n- while (srcNb) {\n- status = NdisCopyFromNetBufferToNetBuffer(dstNb, 0, copySize,\n- srcNb, 0,\n- &byteCopied);\n- if (status != NDIS_STATUS_SUCCESS || copySize != byteCopied) {\n- goto nbl_context_error;\n- }\n- srcNb = NET_BUFFER_NEXT_NB(srcNb);\n- dstNb = NET_BUFFER_NEXT_NB(dstNb);\n- }\n- }\n- }\n-\n- status = OvsAllocateNBLContext(context, newNbl);\n- if (status != NDIS_STATUS_SUCCESS) {\n- goto nbl_context_error;\n- }\n-\n- status = OvsCopyNBLInfo(nbl, newNbl, srcCtx, copySize, copyNblInfo);\n- if (status != NDIS_STATUS_SUCCESS) {\n- goto copy_list_info_error;\n- }\n-\n-#ifdef DBG\n- InterlockedIncrement((LONG volatile *)&ovsPool->nblOnlyCount);\n-#endif\n-\n- newNbl->ParentNetBufferList = nbl;\n-\n- dstCtx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(newNbl);\n- ASSERT(dstCtx != NULL);\n-\n- flags = srcCtx->flags & (OVS_BUFFER_RECV_BUFFER | OVS_BUFFER_SEND_BUFFER);\n-\n- flags |= OVS_BUFFER_FROM_NBL_ONLY_POOL | OVS_BUFFER_PRIVATE_CONTEXT |\n- OVS_BUFFER_PRIVATE_FORWARD_CONTEXT;\n-\n- srcNb = NET_BUFFER_LIST_FIRST_NB(nbl);\n- ASSERT(srcNb);\n- OvsInitNBLContext(dstCtx, flags, NET_BUFFER_DATA_LENGTH(srcNb) - copySize,\n- OVS_DPPORT_NUMBER_INVALID, srcCtx->mru);\n-\n- InterlockedIncrement((LONG volatile *)&srcCtx->refCount);\n-\n-#ifdef DBG\n- OvsDumpNetBufferList(nbl);\n- OvsDumpForwardingDetails(nbl);\n-\n- OvsDumpNetBufferList(newNbl);\n- OvsDumpForwardingDetails(newNbl);\n-#endif\n-\n- OVS_LOG_LOUD(\"Partial Copy new NBL: %p\", newNbl);\n- return newNbl;\n-\n-copy_list_info_error:\n- OvsFreeNBLContext(context, newNbl);\n-nbl_context_error:\n- if (copySize) {\n- NdisAdvanceNetBufferListDataStart(newNbl, copySize, TRUE, NULL);\n- }\n-retreat_error:\n- NdisFreeCloneNetBufferList(newNbl, 0);\n- return NULL;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsPartialCopyToMultipleNBLs --\n- *\n- * This is similar to OvsPartialCopyNBL() except that each NB will\n- * have its own NBL.\n- * --------------------------------------------------------------------------\n- */\n-PNET_BUFFER_LIST\n-OvsPartialCopyToMultipleNBLs(PVOID ovsContext,\n- PNET_BUFFER_LIST nbl,\n- UINT32 copySize,\n- UINT32 headRoom,\n- BOOLEAN copyNblInfo)\n-{\n- PNET_BUFFER nb, nextNb = NULL, firstNb, prevNb;\n- POVS_SWITCH_CONTEXT context = (POVS_SWITCH_CONTEXT)ovsContext;\n- PNET_BUFFER_LIST firstNbl = NULL, newNbl, prevNbl = NULL;\n-\n- nb = NET_BUFFER_LIST_FIRST_NB(nbl);\n- if (NET_BUFFER_NEXT_NB(nb) == NULL) {\n- return OvsPartialCopyNBL(context, nbl, copySize, headRoom, copyNblInfo);\n- }\n-\n- firstNb = nb;\n- prevNb = nb;\n-\n- while (nb) {\n- nextNb = NET_BUFFER_NEXT_NB(nb);\n- NET_BUFFER_NEXT_NB(nb) = NULL;\n-\n- NET_BUFFER_LIST_FIRST_NB(nbl) = nb;\n-\n- newNbl = OvsPartialCopyNBL(context, nbl, copySize, headRoom,\n- copyNblInfo);\n- if (newNbl == NULL) {\n- goto cleanup;\n- }\n- if (prevNbl == NULL) {\n- firstNbl = newNbl;\n- } else {\n- NET_BUFFER_LIST_NEXT_NBL(prevNbl) = newNbl;\n- NET_BUFFER_NEXT_NB(prevNb) = nb;\n- }\n- prevNbl = newNbl;\n- prevNb = nb;\n- nb = nextNb;\n- }\n- NET_BUFFER_LIST_FIRST_NB(nbl) = firstNb;\n- return firstNbl;\n-\n-cleanup:\n- NET_BUFFER_NEXT_NB(prevNb) = nb;\n- NET_BUFFER_NEXT_NB(nb) = nextNb;\n- NET_BUFFER_LIST_FIRST_NB(nbl) = firstNb;\n-\n- newNbl = firstNbl;\n- while (newNbl) {\n- firstNbl = NET_BUFFER_LIST_NEXT_NBL(newNbl);\n- NET_BUFFER_LIST_NEXT_NBL(newNbl) = NULL;\n- OvsCompleteNBL(context, newNbl, TRUE);\n- newNbl = firstNbl;\n- }\n- return NULL;\n-}\n-\n-\n-static PNET_BUFFER_LIST\n-OvsCopySinglePacketNBL(PVOID ovsContext,\n- PNET_BUFFER_LIST nbl,\n- PNET_BUFFER nb,\n- UINT32 headRoom,\n- BOOLEAN copyNblInfo)\n-{\n- UINT32 size;\n- ULONG copiedSize;\n- POVS_SWITCH_CONTEXT context = (POVS_SWITCH_CONTEXT)ovsContext;\n- PNET_BUFFER_LIST newNbl;\n- PNET_BUFFER newNb;\n- NDIS_STATUS status;\n- POVS_BUFFER_CONTEXT srcCtx, dstCtx;\n-\n- size = NET_BUFFER_DATA_LENGTH(nb);\n- if ((size + headRoom) <= OVS_FIX_NBL_DATA_SIZE) {\n- newNbl = OvsAllocateFixSizeNBL(context, size, headRoom);\n- } else {\n- newNbl = OvsAllocateVariableSizeNBL(context, size, headRoom);\n- }\n- if (newNbl == NULL) {\n- return NULL;\n- }\n- newNb = NET_BUFFER_LIST_FIRST_NB(newNbl);\n- status = NdisCopyFromNetBufferToNetBuffer(newNb, 0, size, nb, 0,\n- &copiedSize);\n-\n- srcCtx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl);\n- if (status == NDIS_STATUS_SUCCESS) {\n- status = OvsCopyNBLInfo(nbl, newNbl, srcCtx, copiedSize, copyNblInfo);\n- }\n-\n- if (status != NDIS_STATUS_SUCCESS || copiedSize != size) {\n- OvsCompleteNBL(context, newNbl, TRUE);\n- return NULL;\n- }\n-\n- dstCtx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(newNbl);\n- ASSERT(dstCtx && srcCtx);\n- ASSERT(srcCtx->magic == OVS_CTX_MAGIC && dstCtx->magic == OVS_CTX_MAGIC);\n-\n- dstCtx->flags |= srcCtx->flags & (OVS_BUFFER_RECV_BUFFER |\n- OVS_BUFFER_SEND_BUFFER);\n-#ifdef DBG\n- OvsDumpNetBufferList(newNbl);\n- OvsDumpForwardingDetails(newNbl);\n-#endif\n- OVS_LOG_LOUD(\"Copy single nb to new NBL: %p\", newNbl);\n- return newNbl;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsFullCopyNBL --\n- *\n- * Copy the NBL to a new NBL including data.\n- *\n- * Notes:\n- * The NBL can have multiple NBs, but the final result is one NBL.\n- * --------------------------------------------------------------------------\n- */\n-PNET_BUFFER_LIST\n-OvsFullCopyNBL(PVOID ovsContext,\n- PNET_BUFFER_LIST nbl,\n- UINT32 headRoom,\n- BOOLEAN copyNblInfo)\n-{\n- POVS_SWITCH_CONTEXT context = (POVS_SWITCH_CONTEXT)ovsContext;\n- POVS_NBL_POOL ovsPool = &context->ovsPool;\n- PNET_BUFFER_LIST newNbl;\n- PNET_BUFFER nb, newNb, firstNb = NULL, prevNb = NULL;\n- POVS_BUFFER_CONTEXT dstCtx, srcCtx;\n- PMDL mdl;\n- NDIS_STATUS status;\n- UINT32 size, totalSize;\n- ULONG copiedSize;\n- UINT16 flags;\n- PNDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO dstInfo;\n-\n- srcCtx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl);\n- if (srcCtx == NULL || srcCtx->magic != OVS_CTX_MAGIC) {\n- OVS_LOG_INFO(\"src nbl must have ctx initialized\");\n- ASSERT(srcCtx && srcCtx->magic == OVS_CTX_MAGIC);\n- return NULL;\n- }\n-\n- nb = NET_BUFFER_LIST_FIRST_NB(nbl);\n- if (nb == NULL) {\n- return NULL;\n- }\n-\n- if (NET_BUFFER_NEXT_NB(nb) == NULL) {\n- return OvsCopySinglePacketNBL(context, nbl, nb, headRoom, copyNblInfo);\n- }\n-\n- newNbl = NdisAllocateNetBufferList(ovsPool->nblOnlyPool,\n- (UINT16)sizeof (OVS_BUFFER_CONTEXT),\n- (UINT16)OVS_DEFAULT_NBL_CONTEXT_FILL);\n- if (newNbl == NULL) {\n- return NULL;\n- }\n-\n- while (nb) {\n- size = NET_BUFFER_DATA_LENGTH(nb);\n- totalSize = MEM_ALIGN_SIZE(size + headRoom);\n- mdl = OvsAllocateMDLAndData(ovsPool->ndisHandle, totalSize);\n-\n- if (mdl == NULL) {\n- goto nblcopy_error;\n- }\n- newNb = NdisAllocateNetBuffer(ovsPool->nbPool, mdl, totalSize, 0);\n- if (newNb == NULL) {\n- OvsFreeMDLAndData(mdl);\n- goto nblcopy_error;\n- }\n- if (firstNb == NULL) {\n- firstNb = newNb;\n- } else {\n- NET_BUFFER_NEXT_NB(prevNb) = newNb;\n- }\n- prevNb = newNb;\n-#ifdef DBG\n- InterlockedIncrement((LONG volatile *)&ovsPool->nbCount);\n-#endif\n- status = NdisRetreatNetBufferDataStart(newNb, size, 0, NULL);\n- ASSERT(status == NDIS_STATUS_SUCCESS);\n-\n- status = NdisCopyFromNetBufferToNetBuffer(newNb, 0, size, nb, 0,\n- &copiedSize);\n- if (status != NDIS_STATUS_SUCCESS || size != copiedSize) {\n- goto nblcopy_error;\n- }\n-\n- nb = NET_BUFFER_NEXT_NB(nb);\n- }\n-\n- NET_BUFFER_LIST_FIRST_NB(newNbl) = firstNb;\n-\n- newNbl->SourceHandle = ovsPool->ndisHandle;\n- status = context->NdisSwitchHandlers.\n- AllocateNetBufferListForwardingContext(ovsPool->ndisContext, newNbl);\n-\n- if (status != NDIS_STATUS_SUCCESS) {\n- goto nblcopy_error;\n- }\n-\n- status = OvsCopyNBLInfo(nbl, newNbl, srcCtx, 0, copyNblInfo);\n- if (status != NDIS_STATUS_SUCCESS) {\n- goto nblcopy_error;\n- }\n-\n- dstInfo = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(newNbl);\n- dstInfo->IsPacketDataSafe = TRUE;\n-\n- dstCtx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(newNbl);\n-\n- flags = srcCtx->flags & (OVS_BUFFER_RECV_BUFFER | OVS_BUFFER_SEND_BUFFER);\n-\n- flags |= OVS_BUFFER_PRIVATE_MDL | OVS_BUFFER_PRIVATE_DATA |\n- OVS_BUFFER_PRIVATE_NET_BUFFER | OVS_BUFFER_FROM_NBL_ONLY_POOL |\n- OVS_BUFFER_PRIVATE_FORWARD_CONTEXT;\n-\n- OvsInitNBLContext(dstCtx, flags, NET_BUFFER_DATA_LENGTH(firstNb),\n- OVS_DPPORT_NUMBER_INVALID, srcCtx->mru);\n-\n-#ifdef DBG\n- OvsDumpNetBufferList(nbl);\n- OvsDumpForwardingDetails(nbl);\n- InterlockedIncrement((LONG volatile *)&ovsPool->nblOnlyCount);\n-#endif\n- OVS_LOG_LOUD(\"newNbl: %p\", newNbl);\n- return newNbl;\n-\n-nblcopy_error:\n- while (firstNb) {\n-#ifdef DBG\n- InterlockedDecrement((LONG volatile *)&ovsPool->nbCount);\n-#endif\n- prevNb = firstNb;\n- firstNb = NET_BUFFER_NEXT_NB(prevNb);\n- mdl = NET_BUFFER_FIRST_MDL(prevNb);\n- NET_BUFFER_FIRST_MDL(prevNb) = NULL;\n- NdisFreeNetBuffer(prevNb);\n- OvsFreeMDLAndData(mdl);\n- }\n- NdisFreeNetBufferList(newNbl);\n- OVS_LOG_ERROR(\"OvsFullCopyNBL failed\");\n- return NULL;\n-}\n-\n-NDIS_STATUS\n-GetIpHeaderInfo(PNET_BUFFER_LIST curNbl,\n- const POVS_PACKET_HDR_INFO hdrInfo,\n- UINT32 *hdrSize)\n-{\n- EthHdr *eth;\n- IPHdr *ipHdr;\n- IPv6Hdr *ipv6Hdr;\n- PNET_BUFFER curNb;\n-\n- curNb = NET_BUFFER_LIST_FIRST_NB(curNbl);\n- ASSERT(NET_BUFFER_NEXT_NB(curNb) == NULL);\n- eth = (EthHdr *)NdisGetDataBuffer(curNb,\n- hdrInfo->l4Offset,\n- NULL, 1, 0);\n- if (eth == NULL) {\n- return NDIS_STATUS_INVALID_PACKET;\n- }\n-\n- if (hdrInfo->isIPv6) {\n- ipv6Hdr = (IPv6Hdr *)((PCHAR)eth + hdrInfo->l3Offset);\n- *hdrSize = (UINT32)(hdrInfo->l4Offset);\n- } else {\n- ipHdr = (IPHdr *)((PCHAR)eth + hdrInfo->l3Offset);\n- *hdrSize = (UINT32)(hdrInfo->l3Offset + (ipHdr->ihl * 4));\n- }\n-\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * GetSegmentHeaderInfo\n- *\n- * Extract header size and sequence number for the segment.\n- * --------------------------------------------------------------------------\n- */\n-static NDIS_STATUS\n-GetSegmentHeaderInfo(PNET_BUFFER_LIST nbl,\n- const POVS_PACKET_HDR_INFO hdrInfo,\n- UINT32 *hdrSize, UINT32 *seqNumber)\n-{\n- TCPHdr tcpStorage;\n- const TCPHdr *tcp;\n-\n- /* Parse the orginal Eth/IP/TCP header */\n- tcp = OvsGetPacketBytes(nbl, sizeof *tcp, hdrInfo->l4Offset, &tcpStorage);\n- if (tcp == NULL) {\n- return NDIS_STATUS_FAILURE;\n- }\n- *seqNumber = ntohl(tcp->seq);\n- *hdrSize = hdrInfo->l4Offset + TCP_HDR_LEN(tcp);\n-\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-static VOID\n-FixFragmentHeader4(UINT16 fragmentSize, UINT16 offset, const EthHdr *dstEth,\n- BOOLEAN lastPacket)\n-{\n- IPHdr *dstIP = NULL;\n-\n- dstIP = (IPHdr *)((PCHAR)dstEth + sizeof(*dstEth));\n- dstIP->tot_len = htons(fragmentSize + dstIP->ihl * 4);\n- if (lastPacket) {\n- dstIP->frag_off = htons(offset & IP_OFFSET);\n- } else {\n- dstIP->frag_off = htons((offset & IP_OFFSET) | IP_MF);\n- }\n-\n- dstIP->check = 0;\n- dstIP->check = IPChecksum((UINT8 *)dstIP, dstIP->ihl * 4, 0);\n-}\n-\n-static VOID\n-FixFragmentHeader6(UINT16 offset, const EthHdr *dstEth,\n- UINT32 fragmentIdent,\n- BOOLEAN lastPacket)\n-{\n- IPv6Hdr *dstIP = NULL;\n- UINT8 nextHdr;\n- IPv6ExtHdr *extHdr;\n-\n- dstIP = (IPv6Hdr *)((PCHAR)dstEth + sizeof(*dstEth));\n- extHdr = (IPv6ExtHdr *)((PCHAR)dstIP + sizeof(IPv6Hdr));\n- nextHdr = dstIP->nexthdr;\n- while (nextHdr != SOCKET_IPPROTO_FRAGMENT) {\n- nextHdr = extHdr->nextHeader;\n- extHdr = (IPv6ExtHdr *)((PCHAR)extHdr + OVS_IPV6_OPT_LEN(extHdr));\n- if (!extHdr) {\n- break;\n- }\n- }\n-\n- if (nextHdr == SOCKET_IPPROTO_FRAGMENT) {\n- IPv6FragHdr *fragHdr = (IPv6FragHdr *)extHdr;\n- fragHdr->reserved = 0x00;\n- fragHdr->offlg &= htons(0x00);\n- fragHdr->ident = fragmentIdent;\n- if (lastPacket) {\n- fragHdr->offlg |= htons(offset << 3);\n- } else {\n- fragHdr->offlg |= htons(0x01);\n- fragHdr->offlg |= htons(offset << 3) ;\n- }\n- } else {\n- if (!extHdr) {\n- ASSERT(! \"Invalid fragment packet.\");\n- }\n- }\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * FixFragmentHeader\n- *\n- * Fix IP length, Offset, IP checksum.\n- * --------------------------------------------------------------------------\n- */\n-static NDIS_STATUS\n-FixFragmentHeader(PNET_BUFFER nb, UINT16 fragmentSize, BOOLEAN lastPacket,\n- UINT16 offset, UINT32 fragmentIdent)\n-{\n- EthHdr *dstEth = NULL;\n- PMDL mdl = NULL;\n- PUINT8 bufferStart = NULL;\n-\n- mdl = NET_BUFFER_FIRST_MDL(nb);\n-\n- bufferStart = (PUINT8)OvsGetMdlWithLowPriority(mdl);\n- if (!bufferStart) {\n- return NDIS_STATUS_RESOURCES;\n- }\n- dstEth = (EthHdr *)(bufferStart + NET_BUFFER_CURRENT_MDL_OFFSET(nb));\n-\n- switch (dstEth->Type) {\n- case ETH_TYPE_IPV4_NBO:\n- {\n- IPHdr *dstIP = NULL;\n- ASSERT((INT)MmGetMdlByteCount(mdl) - NET_BUFFER_CURRENT_MDL_OFFSET(nb)\n- >= sizeof(EthHdr) + sizeof(IPHdr));\n- dstIP = (IPHdr *)((PCHAR)dstEth + sizeof(*dstEth));\n- ASSERT((INT)MmGetMdlByteCount(mdl) - NET_BUFFER_CURRENT_MDL_OFFSET(nb)\n- >= sizeof(EthHdr) + dstIP->ihl * 4);\n- FixFragmentHeader4(fragmentSize, offset, dstEth, lastPacket);\n- break;\n- }\n- case ETH_TYPE_IPV6_NBO:\n- {\n- ASSERT((INT)MmGetMdlByteCount(mdl) - NET_BUFFER_CURRENT_MDL_OFFSET(nb)\n- >= sizeof(EthHdr) + sizeof(IPv6Hdr));\n- FixFragmentHeader6(offset, dstEth, fragmentIdent,\n- lastPacket);\n- break;\n- }\n- default:\n- OVS_LOG_ERROR(\"Invalid eth type: %d\\n\", dstEth->Type);\n- ASSERT(! \"Invalid eth type\");\n- }\n-\n- return STATUS_SUCCESS;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * FixSegmentHeader\n- *\n- * Fix IP length, IP checksum, TCP sequence number and TCP checksum\n- * in the segment.\n- * --------------------------------------------------------------------------\n- */\n-static NDIS_STATUS\n-FixSegmentHeader(PNET_BUFFER nb, UINT16 segmentSize, UINT32 seqNumber,\n- BOOLEAN lastPacket, UINT16 packetCounter)\n-{\n- EthHdr *dstEth = NULL;\n- TCPHdr *dstTCP = NULL;\n- PMDL mdl = NULL;\n- PUINT8 bufferStart = NULL;\n-\n- mdl = NET_BUFFER_FIRST_MDL(nb);\n-\n- bufferStart = (PUINT8)OvsGetMdlWithLowPriority(mdl);\n- if (!bufferStart) {\n- return NDIS_STATUS_RESOURCES;\n- }\n- dstEth = (EthHdr *)(bufferStart + NET_BUFFER_CURRENT_MDL_OFFSET(nb));\n-\n- switch (dstEth->Type) {\n- case ETH_TYPE_IPV4_NBO:\n- {\n- IPHdr *dstIP = NULL;\n-\n- ASSERT((INT)MmGetMdlByteCount(mdl) - NET_BUFFER_CURRENT_MDL_OFFSET(nb)\n- >= sizeof(EthHdr) + sizeof(IPHdr) + sizeof(TCPHdr));\n- dstIP = (IPHdr *)((PCHAR)dstEth + sizeof(*dstEth));\n- dstTCP = (TCPHdr *)((PCHAR)dstIP + dstIP->ihl * 4);\n- ASSERT((INT)MmGetMdlByteCount(mdl) - NET_BUFFER_CURRENT_MDL_OFFSET(nb)\n- >= sizeof(EthHdr) + dstIP->ihl * 4 + TCP_HDR_LEN(dstTCP));\n-\n- /* Fix IP length and checksum */\n- ASSERT(dstIP->protocol == IPPROTO_TCP);\n- dstIP->tot_len = htons(segmentSize + dstIP->ihl * 4 + TCP_HDR_LEN(dstTCP));\n- dstIP->id += packetCounter;\n- dstIP->check = 0;\n- dstIP->check = IPChecksum((UINT8 *)dstIP, dstIP->ihl * 4, 0);\n- dstTCP->seq = htonl(seqNumber);\n-\n- /*\n- * Set the TCP FIN and PSH bit only for the last packet\n- * More information can be found under:\n- * https://msdn.microsoft.com/en-us/library/windows/hardware/ff568840%28v=vs.85%29.aspx\n- */\n- if (dstTCP->fin) {\n- dstTCP->fin = lastPacket;\n- }\n- if (dstTCP->psh) {\n- dstTCP->psh = lastPacket;\n- }\n- UINT16 csumLength = segmentSize + TCP_HDR_LEN(dstTCP);\n- dstTCP->check = IPPseudoChecksum(&dstIP->saddr,\n- &dstIP->daddr,\n- IPPROTO_TCP,\n- csumLength);\n- dstTCP->check = CalculateChecksumNB(nb,\n- csumLength,\n- sizeof(*dstEth) + dstIP->ihl * 4);\n- break;\n- }\n- case ETH_TYPE_IPV6_NBO:\n- {\n- IPv6Hdr *dstIP = NULL;\n-\n- ASSERT((INT)MmGetMdlByteCount(mdl) - NET_BUFFER_CURRENT_MDL_OFFSET(nb)\n- >= sizeof(EthHdr) + sizeof(IPv6Hdr) + sizeof(TCPHdr));\n- dstIP = (IPv6Hdr *)((PCHAR)dstEth + sizeof(*dstEth));\n- dstTCP = (TCPHdr *)((PCHAR)dstIP + sizeof(IPv6Hdr));\n- ASSERT((INT)MmGetMdlByteCount(mdl) - NET_BUFFER_CURRENT_MDL_OFFSET(nb)\n- >= sizeof(EthHdr) + sizeof(IPv6Hdr) + TCP_HDR_LEN(dstTCP));\n-\n- /* Fix IP length */\n- ASSERT(dstIP->nexthdr == IPPROTO_TCP);\n- dstIP->payload_len = htons(segmentSize + sizeof(IPv6Hdr) + TCP_HDR_LEN(dstTCP));\n-\n- dstTCP->seq = htonl(seqNumber);\n- if (dstTCP->fin) {\n- dstTCP->fin = lastPacket;\n- }\n- if (dstTCP->psh) {\n- dstTCP->psh = lastPacket;\n- }\n-\n- UINT16 csumLength = segmentSize + TCP_HDR_LEN(dstTCP);\n- dstTCP->check = IPv6PseudoChecksum((UINT32*)&dstIP->saddr,\n- (UINT32*)&dstIP->daddr,\n- IPPROTO_TCP,\n- csumLength);\n- dstTCP->check = CalculateChecksumNB(nb,\n- csumLength,\n- sizeof(*dstEth) + sizeof(IPv6Hdr));\n- break;\n- }\n- default:\n- OVS_LOG_ERROR(\"Invalid eth type: %d\\n\", dstEth->Type);\n- ASSERT(! \"Invalid eth type\");\n- }\n-\n- return STATUS_SUCCESS;\n-}\n-\n- /*\n- * --------------------------------------------------------------------------\n- * OvsTcpSegmentNBL --\n- * Wrapper function to Fragment a given NBL based on MSS\n- * --------------------------------------------------------------------------\n- */\n-PNET_BUFFER_LIST\n-OvsTcpSegmentNBL(PVOID ovsContext,\n- PNET_BUFFER_LIST nbl,\n- POVS_PACKET_HDR_INFO hdrInfo,\n- UINT32 mss,\n- UINT32 headRoom,\n- BOOLEAN isIpFragment)\n-{\n- return OvsFragmentNBL(ovsContext, nbl, hdrInfo, mss, headRoom, isIpFragment);\n-}\n-\n-NDIS_STATUS\n-OvsFigureIPV6ExtHdrLayout(PNET_BUFFER_LIST nbl,\n- POVS_PACKET_HDR_INFO hdrInfo,\n- UINT16 *beforeFragmentExtFieldLen)\n-{\n- EthHdr *eth;\n- IPv6Hdr *ipv6Hdr;\n- IPv6ExtHdr *extHdr;\n- PNET_BUFFER curNb;\n- UINT8 nextHdr = 0;\n- UINT16 offset = 0;\n- BOOLEAN foundRouterHeader = FALSE;\n- UINT16 extFieldLen = 0;\n-\n- curNb = NET_BUFFER_LIST_FIRST_NB(nbl);\n- ASSERT(NET_BUFFER_NEXT_NB(curNb) == NULL);\n- eth = (EthHdr *)NdisGetDataBuffer(curNb,\n- hdrInfo->l4Offset,\n- NULL, 1, 0);\n- if (!eth) {\n- OVS_LOG_ERROR(\"Invalid packet.\");\n- return NDIS_STATUS_INVALID_PACKET;\n- }\n-\n- ipv6Hdr = (IPv6Hdr *)((PCHAR)eth + hdrInfo->l3Offset);\n- nextHdr = ipv6Hdr->nexthdr;\n- extHdr = (IPv6ExtHdr *)((PCHAR)ipv6Hdr + sizeof(*ipv6Hdr));\n- extFieldLen = hdrInfo->l4Offset - hdrInfo->l3Offset - sizeof(IPv6Hdr);\n-\n- while (offset <= extFieldLen) {\n- switch (nextHdr) {\n- case SOCKET_IPPROTO_HOPOPTS:\n- *beforeFragmentExtFieldLen += OVS_IPV6_OPT_LEN(extHdr);\n- break;\n- case SOCKET_IPPROTO_ROUTING:\n- *beforeFragmentExtFieldLen += OVS_IPV6_OPT_LEN(extHdr);\n- foundRouterHeader = TRUE;\n- break;\n- case SOCKET_IPPROTO_DSTOPTS:\n- if (foundRouterHeader) {\n- /* In the ipv6 extension field, dst option field must\n- * appear with routeing option filed. */\n- *beforeFragmentExtFieldLen += OVS_IPV6_OPT_LEN(extHdr);\n- return NDIS_STATUS_SUCCESS;\n- } else {\n- /* dst opts field not appear with routing field,\n- * this represent this dst option field is\n- * bebind fragment. */\n- return NDIS_STATUS_SUCCESS;\n- }\n- break;\n- default:\n- return NDIS_STATUS_SUCCESS;\n- }\n-\n- offset += OVS_IPV6_OPT_LEN(extHdr);\n- nextHdr = extHdr->nextHeader;\n- extHdr = (IPv6ExtHdr *)((PCHAR)extHdr + OVS_IPV6_OPT_LEN(extHdr));\n- }\n-\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * function name -- FixIPV6ExtHdrField\n- * This function mainly used to fix IPv6 extension field, because we only\n- * add fragment field in the header, not fix the next header filed,\n- * this function is used to fix that issue.\n- * --------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-FixIPV6ExtHdrField(PNET_BUFFER nb, UINT16 l3Offset, UINT16 l4Offset,\n- UINT16 fragmentSize)\n-{\n- EthHdr *eth;\n- IPv6Hdr *ipv6Hdr = NULL;\n- IPv6ExtHdr *extHdr = NULL;\n- IPv6ExtHdr *lastExtHdr = NULL;\n- IPv6FragHdr *frgHdr = NULL;\n- UINT8 nextHdr = 0;\n- UINT16 offset = 0;\n- BOOLEAN exitLookup = FALSE;\n- BOOLEAN foundRouterHeader = FALSE;\n- PMDL mdl = NULL;\n- PUINT8 bufferStart = NULL;\n- UINT16 extFieldLen = 0;\n-\n- mdl = NET_BUFFER_FIRST_MDL(nb);\n- bufferStart = (PUINT8)OvsGetMdlWithLowPriority(mdl);\n- if (!bufferStart) {\n- OVS_LOG_ERROR(\"Return, buffer start null.\");\n- return STATUS_NDIS_INVALID_PACKET;\n- }\n- eth = (EthHdr *)(bufferStart + NET_BUFFER_CURRENT_MDL_OFFSET(nb));\n- ipv6Hdr = (IPv6Hdr *)((PCHAR)eth+ l3Offset);\n- nextHdr = ipv6Hdr->nexthdr;\n- lastExtHdr = NULL;\n- extHdr = (IPv6ExtHdr *)((PCHAR)ipv6Hdr + sizeof(*ipv6Hdr));\n- extFieldLen = l4Offset - l3Offset - sizeof(IPv6Hdr);\n- ipv6Hdr->payload_len = htons(extFieldLen + fragmentSize);\n-\n- while (offset <= extFieldLen) {\n- switch (nextHdr) {\n- case SOCKET_IPPROTO_HOPOPTS:\n- break;\n- case SOCKET_IPPROTO_ROUTING:\n- foundRouterHeader = TRUE;\n- break;\n- case SOCKET_IPPROTO_DSTOPTS:\n- if (foundRouterHeader) {\n- frgHdr = (IPv6FragHdr *)((PCHAR)extHdr + offset);\n- frgHdr->nextHeader = ipv6Hdr->nexthdr;\n- ipv6Hdr->nexthdr = SOCKET_IPPROTO_FRAGMENT;\n-\n- } else {\n- /* This dest option field was appear behind\n- * fragment field. */\n- if (lastExtHdr) {\n- frgHdr = (IPv6FragHdr *)extHdr;\n- frgHdr->nextHeader = lastExtHdr->nextHeader;\n- lastExtHdr->nextHeader = SOCKET_IPPROTO_FRAGMENT;\n- } else {\n- frgHdr = (IPv6FragHdr *)((PCHAR)extHdr + offset);\n- frgHdr->nextHeader = ipv6Hdr->nexthdr;\n- ipv6Hdr->nexthdr = SOCKET_IPPROTO_FRAGMENT;\n- }\n- }\n- exitLookup = TRUE;\n- break;\n- default:\n- if (!offset) {\n- frgHdr = (IPv6FragHdr *)((PCHAR)extHdr + offset);\n- frgHdr->nextHeader = ipv6Hdr->nexthdr;\n- ipv6Hdr->nexthdr = SOCKET_IPPROTO_FRAGMENT;\n- } else {\n- frgHdr = (IPv6FragHdr *)extHdr;\n- frgHdr->nextHeader = lastExtHdr->nextHeader;\n- lastExtHdr->nextHeader = SOCKET_IPPROTO_FRAGMENT;\n- }\n- exitLookup = TRUE;\n- break;\n- }\n-\n- if (exitLookup) {\n- break;\n- }\n-\n- offset += OVS_IPV6_OPT_LEN(extHdr);\n- nextHdr = extHdr->nextHeader;\n- lastExtHdr = extHdr;\n- extHdr = (IPv6ExtHdr *)((PCHAR)extHdr + OVS_IPV6_OPT_LEN(extHdr));\n- }\n-\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-UINT32\n-GenFragIdent6(PNET_BUFFER_LIST nbl, POVS_PACKET_HDR_INFO hdrInfo)\n-{\n- EthHdr *eth;\n- IPv6Hdr *ipv6Hdr;\n- PNET_BUFFER curNb;\n- UINT32 srcHash;\n- UINT32 dstHash;\n- UINT32 randNumber;\n- LARGE_INTEGER randomSeed;\n-\n- curNb = NET_BUFFER_LIST_FIRST_NB(nbl);\n- ASSERT(NET_BUFFER_NEXT_NB(curNb) == NULL);\n- eth = (EthHdr *)NdisGetDataBuffer(curNb,\n- hdrInfo->l4Offset,\n- NULL, 1, 0);\n- ipv6Hdr = (IPv6Hdr *)((PCHAR)eth + hdrInfo->l3Offset);\n- KeQuerySystemTime(&randomSeed);\n- randNumber = randomSeed.LowPart * OVS_FRAG_MAGIC_NUMBER + 1;\n-\n- srcHash = OvsJhashBytes((UINT32 *)(&(ipv6Hdr->saddr)), 4, randNumber);\n- dstHash = OvsJhashBytes((UINT32 *)(&(ipv6Hdr->daddr)), 4, srcHash);\n- return dstHash;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsFragmentNBL --\n- *\n- * Fragment NBL payload, and prepend each segment with Ether/IP/TCP header.\n- * Leave headRoom for additional encap.\n- *\n- * Please note,\n- * NBL should have OVS_BUFFER_CONTEXT setup before calling\n- * this function.\n- * The NBL should already have ref to itself so that during copy\n- * it will not be freed.\n- * Currently this API assert there is only one NB in an NBL, it needs\n- * to be fixed if we receive multiple NBs in an NBL.\n- * --------------------------------------------------------------------------\n- */\n-PNET_BUFFER_LIST\n-OvsFragmentNBL(PVOID ovsContext,\n- PNET_BUFFER_LIST nbl,\n- POVS_PACKET_HDR_INFO hdrInfo,\n- UINT32 fragmentSize,\n- UINT32 headRoom,\n- BOOLEAN isIpFragment)\n-{\n- POVS_SWITCH_CONTEXT context = (POVS_SWITCH_CONTEXT)ovsContext;\n-#ifdef DBG\n- POVS_NBL_POOL ovsPool = &context->ovsPool;\n-#endif\n- POVS_BUFFER_CONTEXT dstCtx, srcCtx;\n- UINT32 size, hdrSize, nblSize, seqNumber = 0;\n- PNET_BUFFER_LIST newNbl;\n- PNET_BUFFER nb, newNb;\n- NDIS_STATUS status;\n- UINT16 segmentSize;\n- ULONG copiedSize = 0;\n- UINT16 offset = 0, packetCounter = 0;\n- UINT16 beforeFragHdrLen = 0;\n- UINT32 fragmentIdent = 0;\n- UINT16 ip6StdHeaderLen = 0;\n-\n- srcCtx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl);\n- if (srcCtx == NULL || srcCtx->magic != OVS_CTX_MAGIC) {\n- OVS_LOG_INFO(\"src nbl must have ctx initialized\");\n- ASSERT(srcCtx && srcCtx->magic == OVS_CTX_MAGIC);\n- return NULL;\n- }\n-\n- nb = NET_BUFFER_LIST_FIRST_NB(nbl);\n- ASSERT(NET_BUFFER_NEXT_NB(nb) == NULL);\n-\n- if (hdrInfo->isIPv6 && isIpFragment) {\n- /* 1. We need to calculate the header length before\n- * fragment and after fragment.\n- * */\n- status = OvsFigureIPV6ExtHdrLayout(nbl, hdrInfo,\n- &beforeFragHdrLen);\n- if (status != NDIS_STATUS_SUCCESS) {\n- OVS_LOG_ERROR(\"Figure out ipv6 header layout error.\");\n- return NULL;\n- }\n- ip6StdHeaderLen = hdrInfo->l3Offset + sizeof(IPv6Hdr);\n- }\n-\n- /* Figure out the header size */\n- if (isIpFragment) {\n- status = GetIpHeaderInfo(nbl, hdrInfo, &hdrSize);\n- } else {\n- status = GetSegmentHeaderInfo(nbl, hdrInfo, &hdrSize, &seqNumber);\n- }\n- if (status != NDIS_STATUS_SUCCESS) {\n- OVS_LOG_INFO(\"Cannot parse NBL header\");\n- return NULL;\n- }\n- /* Get the NBL size. */\n- if (isIpFragment) {\n- if (hdrInfo->isIPv6) {\n- nblSize = fragmentSize - hdrSize - sizeof(IPv6FragHdr);\n- } else {\n- nblSize = fragmentSize - hdrSize;\n- }\n- } else {\n- nblSize = fragmentSize;\n- }\n-\n- size = NET_BUFFER_DATA_LENGTH(nb) - hdrSize;\n- if (hdrInfo->isIPv6) {\n- /* Because if we want to divide ipv6 info fragments,\n- * we need add a fragment header in packet, thus we will\n- * allocate more memory(contain fragment header) for the packet. */\n- UINT32 dataOffset = hdrSize + sizeof(IPv6FragHdr) + headRoom;\n- newNbl = NdisAllocateFragmentNetBufferList(nbl, NULL, NULL, hdrSize,\n- nblSize,\n- dataOffset,\n- 0, 0);\n- } else {\n- newNbl = NdisAllocateFragmentNetBufferList(nbl, NULL, NULL, hdrSize,\n- nblSize, hdrSize + headRoom,\n- 0, 0);\n- }\n-\n- if (newNbl == NULL) {\n- return NULL;\n- }\n-\n- /* Generate fragment identification */\n- if (isIpFragment && hdrInfo->isIPv6) {\n- fragmentIdent = GenFragIdent6(nbl, hdrInfo);\n- }\n-\n- for (newNb = NET_BUFFER_LIST_FIRST_NB(newNbl); newNb != NULL;\n- newNb = NET_BUFFER_NEXT_NB(newNb)) {\n- segmentSize = (size > nblSize ? nblSize : size) & 0xffff;\n- if (headRoom) {\n- NdisAdvanceNetBufferDataStart(newNb, headRoom, FALSE, NULL);\n- }\n-\n- if (NET_BUFFER_LIST_FIRST_NB(newNbl) == newNb) {\n- if (hdrInfo->isIPv6) {\n- /* When it is first ipv6 packet, we need copy all of ip\n- * ext header Copy headers before fragment.\n- * */\n- status = NdisCopyFromNetBufferToNetBuffer(newNb, 0,\n- ip6StdHeaderLen,\n- nb, 0 , &copiedSize);\n- if (status != NDIS_STATUS_SUCCESS ||\n- (hdrInfo->l3Offset + sizeof(IPv6Hdr)) != copiedSize) {\n- goto nblcopy_error;\n- }\n-\n- if (beforeFragHdrLen) {\n- status = NdisCopyFromNetBufferToNetBuffer(newNb,\n- ip6StdHeaderLen,\n- beforeFragHdrLen,\n- nb,\n- ip6StdHeaderLen,\n- &copiedSize);\n- if (status != NDIS_STATUS_SUCCESS ||\n- beforeFragHdrLen != copiedSize) {\n- goto nblcopy_error;\n- }\n- }\n- /* Copy fragment headers. */\n- /* Copy headers after fragments. */\n-\n- UINT32 behindFragHdrLen = hdrSize - hdrInfo->l3Offset\n- - sizeof(IPv6Hdr)\n- - beforeFragHdrLen;\n- if (behindFragHdrLen > 0) {\n- status = NdisCopyFromNetBufferToNetBuffer(newNb,\n- (ip6StdHeaderLen\n- + beforeFragHdrLen\n- + sizeof(IPv6FragHdr)),\n- behindFragHdrLen,\n- nb,\n- ip6StdHeaderLen\n- + beforeFragHdrLen,\n- &copiedSize);\n- if (status != NDIS_STATUS_SUCCESS ||\n- behindFragHdrLen != copiedSize) {\n- goto nblcopy_error;\n- }\n- }\n-\n- /* Fix IPv6 opt fields. */\n- status = FixIPV6ExtHdrField(newNb,\n- hdrInfo->l3Offset,\n- hdrInfo->l4Offset + sizeof(IPv6FragHdr),\n- segmentSize);\n- if (status != NDIS_STATUS_SUCCESS) {\n- OVS_LOG_ERROR(\"Invalid reassemble packet.\");\n- goto nblcopy_error;\n- }\n- } else {\n- /* Now copy the eth/IP/TCP header and fix up */\n- status = NdisCopyFromNetBufferToNetBuffer(newNb, 0, hdrSize,\n- nb, 0, &copiedSize);\n- if (status != NDIS_STATUS_SUCCESS || hdrSize != copiedSize) {\n- goto nblcopy_error;\n- }\n- }\n- } else {\n- if (hdrInfo->isIPv6) {\n- /* Because ipv6 fragment not first packet, doesn't exist\n- * header after fragment, thus release some data space*/\n- UINT32 behindFragHdrLen = (hdrSize - hdrInfo->l3Offset\n- - sizeof(IPv6Hdr) - beforeFragHdrLen);\n- if (behindFragHdrLen > 0) {\n- NdisAdvanceNetBufferDataStart(newNb,\n- behindFragHdrLen,\n- FALSE, NULL);\n- }\n-\n- /* When it is not first ipv6 packet, we only need copy before\n- * ipv6 segment. */\n- status = NdisCopyFromNetBufferToNetBuffer(newNb, 0,\n- ip6StdHeaderLen,\n- nb, 0 , &copiedSize);\n- if (status != NDIS_STATUS_SUCCESS ||\n- (hdrInfo->l3Offset + sizeof(IPv6Hdr)) != copiedSize) {\n- goto nblcopy_error;\n- }\n-\n- if (beforeFragHdrLen) {\n- status = NdisCopyFromNetBufferToNetBuffer(newNb,\n- ip6StdHeaderLen,\n- beforeFragHdrLen,\n- nb,\n- ip6StdHeaderLen,\n- &copiedSize);\n- if (status != NDIS_STATUS_SUCCESS ||\n- beforeFragHdrLen != copiedSize) {\n- goto nblcopy_error;\n- }\n- }\n-\n- status = FixIPV6ExtHdrField(newNb, hdrInfo->l3Offset,\n- (ip6StdHeaderLen +\n- beforeFragHdrLen +\n- sizeof(IPv6FragHdr)),\n- segmentSize);\n- if (status != NDIS_STATUS_SUCCESS) {\n- OVS_LOG_ERROR(\"Invalid reassemble packet.\");\n- goto nblcopy_error;\n- }\n- } else {\n- status = NdisCopyFromNetBufferToNetBuffer(newNb, 0, hdrSize,\n- nb, 0, &copiedSize);\n- if (status != NDIS_STATUS_SUCCESS ||\n- hdrSize != copiedSize) {\n- goto nblcopy_error;\n- }\n- }\n- }\n-\n- if (isIpFragment) {\n- status = FixFragmentHeader(newNb, segmentSize,\n- NET_BUFFER_NEXT_NB(newNb) == NULL,\n- offset, fragmentIdent);\n- } else {\n- status = FixSegmentHeader(newNb, segmentSize, seqNumber,\n- NET_BUFFER_NEXT_NB(newNb) == NULL,\n- packetCounter);\n- }\n-\n- if (status != NDIS_STATUS_SUCCESS) {\n- OVS_LOG_INFO(\"nbl copy error.\");\n- goto nblcopy_error;\n- }\n-\n- /* Move on to the next segment */\n- if (isIpFragment) {\n- if (NET_BUFFER_LIST_FIRST_NB(newNbl) == newNb &&\n- hdrInfo->isIPv6) {\n- offset += (segmentSize) / 8;\n- offset += (UINT16)((hdrSize - ip6StdHeaderLen -\n- beforeFragHdrLen) / 8);\n- } else {\n- offset += (segmentSize) / 8;\n- }\n- } else {\n- seqNumber += segmentSize;\n- }\n- size -= segmentSize;\n- packetCounter++;\n- }\n-\n- status = OvsAllocateNBLContext(context, newNbl);\n- if (status != NDIS_STATUS_SUCCESS) {\n- goto nblcopy_error;\n- }\n-\n- status = OvsCopyNBLInfo(nbl, newNbl, srcCtx, hdrSize + headRoom, FALSE);\n- if (status != NDIS_STATUS_SUCCESS) {\n- goto nbl_context_error;\n- }\n-\n- if (isIpFragment) {\n- /*Copy with Flag - NDIS_SWITCH_COPY_NBL_INFO_FLAGS_PRESERVE_DESTINATIONS.*/\n- status = context->NdisSwitchHandlers.\n- CopyNetBufferListInfo(context->ovsPool.ndisContext, newNbl, nbl, 1);\n-\n- if (status != NDIS_STATUS_SUCCESS) {\n- goto nbl_context_error;\n- }\n- }\n- newNbl->ParentNetBufferList = nbl;\n-\n- /* Remember it's a fragment NBL so we can free it properly */\n- dstCtx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(newNbl);\n- ASSERT(dstCtx != NULL);\n- dstCtx->flags = OVS_BUFFER_FRAGMENT | OVS_BUFFER_PRIVATE_CONTEXT |\n- OVS_BUFFER_PRIVATE_FORWARD_CONTEXT | OVS_BUFFER_SEND_BUFFER;\n- dstCtx->refCount = 1;\n- dstCtx->magic = OVS_CTX_MAGIC;\n- dstCtx->dataOffsetDelta = hdrSize + headRoom;\n- dstCtx->mru = 0;\n-\n- InterlockedIncrement((LONG volatile *)&srcCtx->refCount);\n-#ifdef DBG\n- InterlockedIncrement((LONG volatile *)&ovsPool->fragNBLCount);\n-\n- OvsDumpNetBufferList(nbl);\n- OvsDumpForwardingDetails(nbl);\n-\n- OvsDumpNetBufferList(newNbl);\n- OvsDumpForwardingDetails(newNbl);\n-#endif\n- OVS_LOG_TRACE(\"Fragment nbl %p to newNbl: %p\", nbl, newNbl);\n- return newNbl;\n-\n-nbl_context_error:\n- OvsFreeNBLContext(context, newNbl);\n-nblcopy_error:\n-#ifdef DBG\n- InterlockedDecrement((LONG volatile *)&ovsPool->fragNBLCount);\n-#endif\n- NdisFreeFragmentNetBufferList(newNbl, hdrSize + headRoom, 0);\n- return NULL;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsAllocateNBLFromBuffer --\n- *\n- * This function allocates all the stuff necessary for creating an NBL from the\n- * input buffer of specified length, namely, a nonpaged data buffer of size\n- * length, an MDL from it, and a NB and NBL from it. It does not allocate an NBL\n- * context yet. It also copies data from the specified buffer to the NBL.\n- * --------------------------------------------------------------------------\n- */\n-PNET_BUFFER_LIST\n-OvsAllocateNBLFromBuffer(PVOID context,\n- PVOID buffer,\n- ULONG length)\n-{\n- POVS_SWITCH_CONTEXT switchContext = (POVS_SWITCH_CONTEXT)context;\n- UINT8 *data = NULL;\n- PNET_BUFFER_LIST nbl = NULL;\n- PNET_BUFFER nb;\n- PMDL mdl;\n-\n- if (length > OVS_DEFAULT_DATA_SIZE) {\n- nbl = OvsAllocateVariableSizeNBL(switchContext, length,\n- OVS_DEFAULT_HEADROOM_SIZE);\n-\n- } else {\n- nbl = OvsAllocateFixSizeNBL(switchContext, length,\n- OVS_DEFAULT_HEADROOM_SIZE);\n- }\n- if (nbl == NULL) {\n- return NULL;\n- }\n-\n- nb = NET_BUFFER_LIST_FIRST_NB(nbl);\n- mdl = NET_BUFFER_CURRENT_MDL(nb);\n- data = (PUINT8)OvsGetMdlWithLowPriority(mdl)\n- + NET_BUFFER_CURRENT_MDL_OFFSET(nb);\n- if (!data) {\n- OvsCompleteNBL(switchContext, nbl, TRUE);\n- return NULL;\n- }\n-\n- NdisMoveMemory(data, buffer, length);\n-\n- return nbl;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsFullCopyToMultipleNBLs --\n- *\n- * Copy NBL to multiple NBLs, each NB will have its own NBL\n- * --------------------------------------------------------------------------\n- */\n-PNET_BUFFER_LIST\n-OvsFullCopyToMultipleNBLs(PVOID ovsContext,\n- PNET_BUFFER_LIST nbl,\n- UINT32 headRoom,\n- BOOLEAN copyNblInfo)\n-{\n-\n- POVS_SWITCH_CONTEXT context = (POVS_SWITCH_CONTEXT)ovsContext;\n- PNET_BUFFER_LIST firstNbl, currNbl, newNbl;\n- PNET_BUFFER nb;\n- POVS_BUFFER_CONTEXT srcCtx;\n-\n- srcCtx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl);\n- if (srcCtx == NULL || srcCtx->magic != OVS_CTX_MAGIC) {\n- OVS_LOG_INFO(\"src nbl must have ctx initialized\");\n- ASSERT(srcCtx && srcCtx->magic == OVS_CTX_MAGIC);\n- return NULL;\n- }\n-\n- nb = NET_BUFFER_LIST_FIRST_NB(nbl);\n- newNbl = OvsCopySinglePacketNBL(context, nbl, nb, headRoom, copyNblInfo);\n-\n- if (newNbl == NULL || NET_BUFFER_NEXT_NB(nb) == NULL) {\n- return newNbl;\n- } else {\n- firstNbl = newNbl;\n- currNbl = newNbl;\n- }\n-\n- while (nb) {\n- newNbl = OvsCopySinglePacketNBL(context, nbl, nb, headRoom,\n- copyNblInfo);\n- if (newNbl == NULL) {\n- goto copymultiple_error;\n- }\n- NET_BUFFER_LIST_NEXT_NBL(currNbl) = newNbl;\n- currNbl = newNbl;\n- nb = NET_BUFFER_NEXT_NB(nb);\n- }\n- return firstNbl;\n-\n-copymultiple_error:\n- while (firstNbl) {\n- currNbl = firstNbl;\n- firstNbl = NET_BUFFER_LIST_NEXT_NBL(firstNbl);\n- NET_BUFFER_LIST_NEXT_NBL(currNbl) = NULL;\n- OvsCompleteNBL(context, currNbl, TRUE);\n- }\n- return NULL;\n-\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsCompleteNBL --\n- *\n- * This function tries to free the NBL allocated by OVS buffer\n- * management module. If it trigger the completion of the parent\n- * NBL, it will recursively call itself. If it trigger the completion\n- * of external NBL, it will be returned to the caller. The caller\n- * is responsible to call API to return to upper layer.\n- * --------------------------------------------------------------------------\n- */\n-PNET_BUFFER_LIST\n-OvsCompleteNBL(PVOID switch_ctx,\n- PNET_BUFFER_LIST nbl,\n- BOOLEAN updateRef)\n-{\n- POVS_BUFFER_CONTEXT ctx;\n- UINT16 flags;\n- UINT32 dataOffsetDelta;\n- PNET_BUFFER_LIST parent;\n- NDIS_STATUS status;\n- NDIS_HANDLE poolHandle;\n- LONG value;\n- POVS_SWITCH_CONTEXT context = (POVS_SWITCH_CONTEXT)switch_ctx;\n- POVS_NBL_POOL ovsPool = &context->ovsPool;\n- PNET_BUFFER nb;\n-\n-\n- ctx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl);\n-\n- ASSERT(ctx && ctx->magic == OVS_CTX_MAGIC);\n-\n- OVS_LOG_TRACE(\"Enter: nbl: %p, ctx: %p, refCount: %d, updateRef:%d\",\n- nbl, ctx, ctx->refCount, updateRef);\n-\n- if (updateRef) {\n- value = InterlockedDecrement((LONG volatile *)&ctx->refCount);\n- if (value != 0) {\n- return NULL;\n- }\n- } else {\n- /*\n- * This is a special case, the refCount must be zero\n- */\n- ASSERT(ctx->refCount == 0);\n- }\n-\n- nb = NET_BUFFER_LIST_FIRST_NB(nbl);\n-\n- flags = ctx->flags;\n- dataOffsetDelta = ctx->dataOffsetDelta;\n- if (!(flags & OVS_BUFFER_FRAGMENT) &&\n- NET_BUFFER_DATA_LENGTH(nb) != ctx->origDataLength) {\n- UINT32 diff;\n- if (NET_BUFFER_DATA_LENGTH(nb) < ctx->origDataLength) {\n- diff = ctx->origDataLength -NET_BUFFER_DATA_LENGTH(nb);\n- status = NdisRetreatNetBufferListDataStart(nbl, diff, 0,\n- NULL, NULL);\n- ASSERT(status == NDIS_STATUS_SUCCESS);\n- } else {\n- diff = NET_BUFFER_DATA_LENGTH(nb) - ctx->origDataLength;\n- NdisAdvanceNetBufferListDataStart(nbl, diff, TRUE, NULL);\n- }\n- }\n-\n- if (flags & OVS_BUFFER_PRIVATE_CONTEXT) {\n- NdisFreeNetBufferListContext(nbl, sizeof (OVS_BUFFER_CONTEXT));\n- }\n-\n- if (flags & OVS_BUFFER_NEED_COMPLETE) {\n- /*\n- * return to caller for completion\n- */\n-#ifdef DBG\n- InterlockedDecrement((LONG volatile *)&ovsPool->sysNBLCount);\n-#endif\n- return nbl;\n- }\n-\n- if (flags & OVS_BUFFER_PRIVATE_FORWARD_CONTEXT) {\n- context->NdisSwitchHandlers.\n- FreeNetBufferListForwardingContext(ovsPool->ndisContext, nbl);\n- }\n-\n- if (flags & (OVS_BUFFER_PRIVATE_MDL | OVS_BUFFER_PRIVATE_DATA)) {\n- PNET_BUFFER nbTemp = NET_BUFFER_LIST_FIRST_NB(nbl);\n- while (nbTemp) {\n- PMDL mdl = NET_BUFFER_FIRST_MDL(nbTemp);\n- if (mdl) {\n- ASSERT(mdl->Next == NULL);\n- OvsFreeMDLAndData(mdl);\n- }\n- NET_BUFFER_FIRST_MDL(nbTemp) = NULL;\n- nbTemp = NET_BUFFER_NEXT_NB(nbTemp);\n- }\n- }\n-\n- if (flags & OVS_BUFFER_PRIVATE_NET_BUFFER) {\n- PNET_BUFFER nbTemp, nextNb;\n-\n- nbTemp = NET_BUFFER_LIST_FIRST_NB(nbl);\n- while (nbTemp) {\n- nextNb = NET_BUFFER_NEXT_NB(nbTemp);\n- NdisFreeNetBuffer(nbTemp);\n-#ifdef DBG\n- InterlockedDecrement((LONG volatile *)&ovsPool->nbCount);\n-#endif\n- nbTemp = nextNb;\n- }\n- NET_BUFFER_LIST_FIRST_NB(nbl) = NULL;\n- }\n-\n- parent = nbl->ParentNetBufferList;\n-\n- poolHandle = NdisGetPoolFromNetBufferList(nbl);\n- if (flags & OVS_BUFFER_FROM_FIX_SIZE_POOL) {\n- ASSERT(poolHandle == ovsPool->fixSizePool);\n-#ifdef DBG\n- InterlockedDecrement((LONG volatile *)&ovsPool->fixNBLCount);\n-#endif\n- NdisFreeNetBufferList(nbl);\n- } else if (flags & OVS_BUFFER_FROM_ZERO_SIZE_POOL) {\n- ASSERT(poolHandle == ovsPool->zeroSizePool);\n-#ifdef DBG\n- InterlockedDecrement((LONG volatile *)&ovsPool->zeroNBLCount);\n-#endif\n- NdisFreeNetBufferList(nbl);\n- } else if (flags & OVS_BUFFER_FROM_NBL_ONLY_POOL) {\n- ASSERT(poolHandle == ovsPool->nblOnlyPool);\n-#ifdef DBG\n- InterlockedDecrement((LONG volatile *)&ovsPool->nblOnlyCount);\n-#endif\n- NdisFreeCloneNetBufferList(nbl, 0);\n- } else if (flags & OVS_BUFFER_FRAGMENT) {\n- OVS_LOG_TRACE(\"Free fragment %p parent %p\", nbl, parent);\n-#ifdef DBG\n- InterlockedDecrement((LONG volatile *)&ovsPool->fragNBLCount);\n-#endif\n- NdisFreeFragmentNetBufferList(nbl, dataOffsetDelta, 0);\n- }\n-\n- if (parent != NULL) {\n- ctx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(parent);\n- ASSERT(ctx && ctx->magic == OVS_CTX_MAGIC);\n- UINT16 pendingSend = 1, exchange = 0;\n- value = InterlockedDecrement((LONG volatile *)&ctx->refCount);\n- InterlockedCompareExchange16((SHORT volatile *)&pendingSend, exchange, (SHORT)ctx->pendingSend);\n- if (value == 1 && pendingSend == exchange) {\n- InterlockedExchange16((SHORT volatile *)&ctx->pendingSend, 0);\n- OvsSendNBLIngress(context, parent, ctx->sendFlags);\n- } else if (value == 0) {\n- return OvsCompleteNBL(context, parent, FALSE);\n- }\n- }\n- return NULL;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsSetCtxSourcePortNo --\n- * Setter function which stores the source port of an NBL in the NBL\n- * Context Info.\n- * --------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsSetCtxSourcePortNo(PNET_BUFFER_LIST nbl,\n- UINT32 portNo)\n-{\n- POVS_BUFFER_CONTEXT ctx;\n- ctx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl);\n- if (ctx == NULL) {\n- ASSERT(ctx && ctx->magic == OVS_CTX_MAGIC);\n- return STATUS_INVALID_PARAMETER;\n- }\n-\n- ctx->srcPortNo = portNo;\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsGetCtxSourcePortNo --\n- * Get source port of an NBL from its Context Info.\n- * --------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsGetCtxSourcePortNo(PNET_BUFFER_LIST nbl,\n- UINT32 *portNo)\n-{\n- POVS_BUFFER_CONTEXT ctx;\n- ctx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl);\n- if (ctx == NULL || portNo == NULL) {\n- ASSERT(ctx && ctx->magic == OVS_CTX_MAGIC);\n- return STATUS_INVALID_PARAMETER;\n- }\n- *portNo = ctx->srcPortNo;\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsCreateNewNBLsFromMultipleNBs --\n- * Creates an NBL chain where each NBL has a single NB,\n- * from an NBL which has multiple NBs.\n- * Sets 'curNbl' and 'lastNbl' to the first and last NBL in the\n- * newly created NBL chain respectively, and completes the original NBL.\n- * --------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsCreateNewNBLsFromMultipleNBs(POVS_SWITCH_CONTEXT switchContext,\n- PNET_BUFFER_LIST *curNbl,\n- PNET_BUFFER_LIST *lastNbl)\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n- PNET_BUFFER_LIST newNbls = NULL;\n- PNET_BUFFER_LIST nbl = NULL;\n- BOOLEAN error = TRUE;\n-\n- do {\n- /* Create new NBLs from curNbl with multiple net buffers. */\n- newNbls = OvsPartialCopyToMultipleNBLs(switchContext,\n- *curNbl, 0, 0, TRUE);\n- if (NULL == newNbls) {\n- OVS_LOG_ERROR(\"Failed to allocate NBLs with single NB.\");\n- status = NDIS_STATUS_RESOURCES;\n- break;\n- }\n-\n- nbl = newNbls;\n- while (nbl) {\n- *lastNbl = nbl;\n- nbl = NET_BUFFER_LIST_NEXT_NBL(nbl);\n- }\n-\n- (*curNbl)->Next = NULL;\n-\n- OvsCompleteNBL(switchContext, *curNbl, TRUE);\n-\n- *curNbl = newNbls;\n-\n- error = FALSE;\n- } while (error);\n-\n- return status;\n-}\ndiff --git a/datapath-windows/ovsext/BufferMgmt.h b/datapath-windows/ovsext/BufferMgmt.h\ndeleted file mode 100644\nindex 90d2360f7..000000000\n--- a/datapath-windows/ovsext/BufferMgmt.h\n+++ /dev/null\n@@ -1,151 +0,0 @@\n-/*\n- * Copyright (c) 2014, 2016 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#ifndef __BUFFER_MGMT_H_\n-#define __BUFFER_MGMT_H_ 1\n-\n-#define MEM_ALIGN MEMORY_ALLOCATION_ALIGNMENT\n-#define MEM_ALIGN_SIZE(_x) ((MEM_ALIGN - 1 + (_x))/MEM_ALIGN * MEM_ALIGN)\n-#define OVS_CTX_MAGIC 0xabcd\n-#define OVS_DEFAULT_NBL_CONTEXT_SIZE sizeof(OVS_BUFFER_CONTEXT)\n-#define OVS_DEFAULT_NBL_CONTEXT_FILL 0\n-#define OVS_DEFAULT_DATA_SIZE 256\n-#define OVS_DEFAULT_HEADROOM_SIZE 128\n-#define OVS_FIX_NBL_DATA_SIZE (OVS_DEFAULT_DATA_SIZE + OVS_DEFAULT_HEADROOM_SIZE)\n-#define OVS_IPV6_OPT_LEN(p) (((p)->hdrExtLen+1) << 3)\n-#define OVS_FRAG_MAGIC_NUMBER 0x8088405\n-\n-\n-\n-/* Default we copy 18 bytes, to make sure ethernet header and vlan is in\n- * continuous buffer */\n-#define OVS_DEFAULT_COPY_SIZE 18\n-\n-enum {\n- OVS_BUFFER_NEED_COMPLETE = BIT16(0),\n- OVS_BUFFER_PRIVATE_MDL = BIT16(1),\n- OVS_BUFFER_PRIVATE_DATA = BIT16(2),\n- OVS_BUFFER_PRIVATE_NET_BUFFER = BIT16(3),\n- OVS_BUFFER_PRIVATE_FORWARD_CONTEXT = BIT16(4),\n- OVS_BUFFER_PRIVATE_CONTEXT = BIT16(5),\n- OVS_BUFFER_FROM_FIX_SIZE_POOL = BIT16(6),\n- OVS_BUFFER_FROM_ZERO_SIZE_POOL = BIT16(7),\n- OVS_BUFFER_FROM_NBL_ONLY_POOL = BIT16(8),\n- OVS_BUFFER_RECV_BUFFER = BIT16(9),\n- OVS_BUFFER_SEND_BUFFER = BIT16(10),\n- OVS_BUFFER_FRAGMENT = BIT16(11),\n-};\n-\n-typedef union _OVS_BUFFER_CONTEXT {\n- struct dummy {\n- UINT16 magic;\n- UINT16 flags;\n- UINT32 srcPortNo;\n- UINT32 refCount;\n- union {\n- UINT32 origDataLength;\n- UINT32 dataOffsetDelta;\n- };\n- ULONG sendFlags;\n- UINT16 mru;\n- UINT16 pendingSend; /* Indicates packet can be sent or not. */\n- };\n-\n- CHAR value[MEM_ALIGN_SIZE(sizeof(struct dummy))];\n-} OVS_BUFFER_CONTEXT, *POVS_BUFFER_CONTEXT;\n-\n-typedef struct _OVS_NBL_POOL {\n- NDIS_SWITCH_CONTEXT ndisContext;\n- NDIS_HANDLE ndisHandle;\n- NDIS_HANDLE fixSizePool; // data size of 256\n- NDIS_HANDLE zeroSizePool; // no data, NBL + NB + Context\n- NDIS_HANDLE nblOnlyPool; // NBL + context for clone\n- NDIS_HANDLE nbPool; // NB for clone\n-#ifdef DBG\n- LONG fixNBLCount;\n- LONG zeroNBLCount;\n- LONG nblOnlyCount;\n- LONG nbCount;\n- LONG sysNBLCount;\n- LONG fragNBLCount;\n-#endif\n-} OVS_NBL_POOL, *POVS_NBL_POOL;\n-\n-\n-NDIS_STATUS OvsInitBufferPool(PVOID context);\n-\n-VOID OvsCleanupBufferPool(PVOID context);\n-\n-PNET_BUFFER_LIST OvsAllocateFixSizeNBL(PVOID context,\n- UINT32 size,\n- UINT32 headRoom);\n-\n-PNET_BUFFER_LIST OvsAllocateVariableSizeNBL(PVOID context,\n- UINT32 size,\n- UINT32 headRoom);\n-\n-POVS_BUFFER_CONTEXT OvsInitExternalNBLContext(PVOID context,\n- PNET_BUFFER_LIST nbl,\n- BOOLEAN isRecv);\n-\n-PNET_BUFFER_LIST OvsPartialCopyNBL(PVOID context,\n- PNET_BUFFER_LIST nbl,\n- UINT32 copySize,\n- UINT32 headRoom,\n- BOOLEAN copyNblInfo);\n-PNET_BUFFER_LIST OvsPartialCopyToMultipleNBLs(PVOID context,\n- PNET_BUFFER_LIST nbl,\n- UINT32 copySize,\n- UINT32 headRoom,\n- BOOLEAN copyNblInfo);\n-\n-PNET_BUFFER_LIST OvsFullCopyNBL(PVOID context, PNET_BUFFER_LIST nbl,\n- UINT32 headRoom, BOOLEAN copyNblInfo);\n-\n-PNET_BUFFER_LIST OvsTcpSegmentNBL(PVOID context,\n- PNET_BUFFER_LIST nbl,\n- POVS_PACKET_HDR_INFO hdrInfo,\n- UINT32 MSS,\n- UINT32 headRoom,\n- BOOLEAN isIpFragment);\n-\n-PNET_BUFFER_LIST OvsFragmentNBL(PVOID context,\n- PNET_BUFFER_LIST nbl,\n- POVS_PACKET_HDR_INFO hdrInfo,\n- UINT32 MSS,\n- UINT32 headRoom,\n- BOOLEAN isIpFragment);\n-\n-PNET_BUFFER_LIST OvsAllocateNBLFromBuffer(PVOID context,\n- PVOID buffer,\n- ULONG length);\n-\n-PNET_BUFFER_LIST OvsFullCopyToMultipleNBLs(PVOID context, PNET_BUFFER_LIST nbl,\n- UINT32 headRoom,\n- BOOLEAN copyNblInfo);\n-\n-PNET_BUFFER_LIST OvsCompleteNBL(PVOID context, PNET_BUFFER_LIST nbl,\n- BOOLEAN updateRef);\n-\n-NDIS_STATUS OvsSetCtxSourcePortNo(PNET_BUFFER_LIST nbl, UINT32 portNo);\n-\n-NDIS_STATUS OvsGetCtxSourcePortNo(PNET_BUFFER_LIST nbl, UINT32 *portNo);\n-\n-NTSTATUS OvsCreateNewNBLsFromMultipleNBs(PVOID context,\n- PNET_BUFFER_LIST *curNbl,\n- PNET_BUFFER_LIST *lastNbl);\n-\n-#endif /* __BUFFER_MGMT_H_ */\ndiff --git a/datapath-windows/ovsext/Conntrack-ftp.c b/datapath-windows/ovsext/Conntrack-ftp.c\ndeleted file mode 100644\nindex 6775496cf..000000000\n--- a/datapath-windows/ovsext/Conntrack-ftp.c\n+++ /dev/null\n@@ -1,365 +0,0 @@\n-/*\n- * Copyright (c) 2016 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#include <string.h>\n-#include \"Conntrack.h\"\n-#include \"PacketParser.h\"\n-#include \"util.h\"\n-\n-/* Eg: 227 Entering Passive Mode (a1,a2,a3,a4,p1,p2)*/\n-#define FTP_PASV_RSP_PREFIX \"227\"\n-#define FTP_EXTEND_PASV_RSP_PREFIX \"229\"\n-#define FTP_EXTEND_ACTIVE_RSP_PREFIX \"200\"\n-\n-typedef enum FTP_TYPE {\n- FTP_TYPE_PASV = 1,\n- FTP_TYPE_ACTIVE,\n- FTP_EXTEND_TYPE_PASV,\n- FTP_EXTEND_TYPE_ACTIVE\n-} FTP_TYPE;\n-\n-static __inline UINT32\n-OvsStrncmp(const char *s1, const char *s2, size_t n)\n-{\n- if (!s1 || !s2) {\n- return 0;\n- }\n-\n- const char *s2end = s2 + n;\n- while (s2 < s2end && *s2 != '\\0' && toupper(*s1) == toupper(*s2)) {\n- s1++, s2++;\n- }\n-\n- if (s2end == s2) {\n- return 0;\n- }\n-\n- return (UINT32)(toupper(*s1) - toupper(*s2));\n-}\n-\n-static __inline VOID\n-OvsStrlcpy(char *dest, const char *src, size_t size)\n-{\n- /* XXX Replace ret with strlen(src) instead. */\n- size_t ret = size;\n- if (size) {\n- size_t len = (ret >= size) ? size - 1 : ret;\n- memcpy(dest, src, len);\n- dest[len] = '\\0';\n- }\n-}\n-\n-/*\n- *---------------------------------------------------------------------------\n- * OvsCtExtractNumbers\n- * Returns an array of numbers after parsing the string.\n- * Eg: PASV: 192,168,0,1,5,6 -> {192,168,0,1,5,6}\n- * EPRT: 192.168.0.1 -> {192,168,0,1}\n- *\n- *---------------------------------------------------------------------------\n- */\n-static __inline NDIS_STATUS\n-OvsCtExtractNumbers(char *buf,\n- UINT32 bufLen,\n- UINT32 arr[],\n- UINT32 arrLen,\n- char delimiter)\n-{\n- if (!buf) {\n- return NDIS_STATUS_INVALID_PACKET;\n- }\n-\n- UINT32 i = 0;\n-\n- while (*buf != '\\0') {\n- if (i >= bufLen || i >= arrLen) {\n- /* Non-standard FTP command */\n- return NDIS_STATUS_INVALID_PARAMETER;\n- }\n-\n- /* Parse the number */\n- if (*buf >= '0' && *buf <= '9') {\n- arr[i] = arr[i] * 10 + *buf - '0';\n- } else if (*buf == delimiter) {\n- i++;\n- } else {\n- /* End of FTP response is either ) or \\r\\n */\n- if (*buf == ')' || *buf == '\\r' || *buf == '\\n') {\n- return NDIS_STATUS_SUCCESS;\n- }\n- /* Could be non-numerals or space */\n- }\n- buf++;\n- }\n-\n- /* Parsing ended without the correct format */\n- return NDIS_STATUS_INVALID_PARAMETER;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsCtHandleFtp\n- * Extract the FTP control data from the packet and created a related\n- * entry if it's a valid connection. This method doesn't support extended\n- * FTP yet. Supports PORT and PASV commands.\n- * Eg:\n- * 'PORT 192,168,137,103,192,22\\r\\n' -> '192.168.137.103' and 49174\n- * '227 Entering Passive Mode (192,168,137,104,194,14)\\r\\n' gets extracted\n- * to '192.168.137.104' and 49678\n- *----------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsCtHandleFtp(PNET_BUFFER_LIST curNbl, OvsFlowKey *key,\n- OVS_PACKET_HDR_INFO *layers, UINT64 currentTime,\n- POVS_CT_ENTRY entry)\n-{\n- NDIS_STATUS status = NDIS_STATUS_SUCCESS;\n- FTP_TYPE ftpType = 0;\n- const char *buf;\n- char temp[256] = { 0 };\n- char ftpMsg[256] = { 0 };\n- UINT32 len;\n- TCPHdr tcpStorage;\n- const TCPHdr *tcp;\n- tcp = OvsGetTcpHeader(curNbl, layers, &tcpStorage, &len);\n- if (!tcp) {\n- return NDIS_STATUS_INVALID_PACKET;\n- }\n-\n- if (len > sizeof(temp)) {\n- /* We only care up to 256 */\n- len = sizeof(temp);\n- }\n-\n- buf = OvsGetPacketBytes(curNbl, len,\n- layers->l4Offset + TCP_HDR_LEN(tcp),\n- temp);\n- if (buf == NULL) {\n- return NDIS_STATUS_INVALID_PACKET;\n- }\n-\n- OvsStrlcpy((char *)ftpMsg, (char *)buf, min(len, sizeof(ftpMsg)));\n- char *req = NULL;\n-\n- if ((len >= 5) && (OvsStrncmp(\"PORT\", ftpMsg, 4) == 0)) {\n- ftpType = FTP_TYPE_ACTIVE;\n- req = ftpMsg + 4;\n- } else if ((len >= 5) && (OvsStrncmp(\"EPRT\", ftpMsg, 4) == 0)) {\n- ftpType = FTP_EXTEND_TYPE_ACTIVE;\n- req = ftpMsg + 4;\n- }\n-\n- if ((len >= 4) && (OvsStrncmp(FTP_PASV_RSP_PREFIX, ftpMsg, 3) == 0)) {\n- ftpType = FTP_TYPE_PASV;\n- /* There are various formats for PASV command. We try to support\n- * some of them. This has been addressed by RFC 2428 - EPSV.\n- * Eg:\n- * 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2).\n- * 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2\n- * 227 Entering Passive Mode. h1,h2,h3,h4,p1,p2\n- * 227 =h1,h2,h3,h4,p1,p2\n- */\n- char *paren;\n- paren = strchr(ftpMsg, '(');\n- if (paren) {\n- req = paren + 1;\n- } else {\n- /* PASV command without ( */\n- req = ftpMsg + 3;\n- }\n- } else if ((len >= 4) && (\n- OvsStrncmp(FTP_EXTEND_PASV_RSP_PREFIX, ftpMsg, 3) == 0)) {\n- ftpType = FTP_EXTEND_TYPE_PASV;\n- /* The ftp extended passive mode only contain port info, ip address\n- * is same with the network protocol used by control connection.\n- * 229 Entering Extended Passive Mode (|||port|)\n- * */\n- char *paren;\n- paren = strchr(ftpMsg, '|');\n- if (paren) {\n- req = paren + 3;\n- } else {\n- /* Not a valid EPSV packet. */\n- return NDIS_STATUS_INVALID_PACKET;\n- }\n-\n- if (!(*req > '0' && * req < '9')) {\n- /* Not a valid port number. */\n- return NDIS_STATUS_INVALID_PACKET;\n- }\n- }\n-\n- if (req == NULL) {\n- /* Not a PORT/PASV control packet */\n- return NDIS_STATUS_SUCCESS;\n- }\n-\n- struct ct_addr clientIp = {0}, serverIp = {0};\n- UINT16 port = 0;\n-\n- if (ftpType == FTP_TYPE_ACTIVE || ftpType == FTP_TYPE_PASV) {\n- UINT32 arr[6] = {0};\n- status = OvsCtExtractNumbers(req, len, arr, 6, ',');\n-\n- if (status != NDIS_STATUS_SUCCESS) {\n- return status;\n- }\n-\n- UINT32 ip = ntohl((arr[0] << 24) | (arr[1] << 16) |\n- (arr[2] << 8) | arr[3]);\n- port = ntohs(((arr[4] << 8) | arr[5]));\n-\n- if (ftpType == FTP_TYPE_ACTIVE) {\n- serverIp.ipv4 = key->ipKey.nwDst;\n- clientIp.ipv4 = ip;\n- }\n-\n- if (ftpType == FTP_TYPE_PASV) {\n- serverIp.ipv4 = ip;\n- clientIp.ipv4 = key->ipKey.nwDst;\n- }\n- } else {\n- if (ftpType == FTP_EXTEND_TYPE_ACTIVE) {\n- /** In ftp active mode, we need to parse string like below:\n- * \" |2|20::1|50778|\", 2 represent address is ipv6, 1 represent\n- * address family is ipv4, \"20::1\" is ipv6 address, 50779 is port\n- * client need to listen.\n- * **/\n- char *curHdr = NULL;\n- char *nextHdr = NULL;\n- int index = 0;\n- int isIpv6AddressFamily = 0;\n- char ftpStr[512] = {0x00};\n-\n- RtlCopyMemory(ftpStr, req, strlen(req));\n- for (curHdr = ftpStr; *curHdr != '|'; curHdr++);\n- curHdr = curHdr + 1;;\n- do {\n- /** index == 0 parse address family,\n- * index == 1 parse address,\n- * index == 2 parse port **/\n- for (nextHdr = curHdr; *nextHdr != '|'; nextHdr++);\n- *nextHdr = '\\0';\n-\n- if (*curHdr == '0' || !curHdr || index > 2) {\n- break;\n- }\n-\n- if (index == 0 && *curHdr == '1') {\n- isIpv6AddressFamily = 0;\n- } else if (index == 0 && *curHdr == '2') {\n- isIpv6AddressFamily = 1;\n- }\n-\n- if (index == 1 && isIpv6AddressFamily) {\n- OvsIpv6StringToAddress(curHdr, &clientIp.ipv6);\n- }\n-\n- if (index == 2) {\n- for (char *tmp = curHdr; *tmp != '\\0'; tmp++) {\n- port = port * 10 + (*tmp - '0');\n- }\n- port = htons(port);\n- }\n-\n- curHdr = nextHdr + 1;\n- index++;\n- } while (1);\n-\n- if (index < 2) { /* Not valid packet due to less than three parameter */\n- return NDIS_STATUS_SUCCESS;\n- }\n- serverIp.ipv6 = key->ipv6Key.ipv6Dst;\n- }\n-\n- if (ftpType == FTP_EXTEND_TYPE_PASV) {\n- /* Here used to parse the string \"229 Entering Extended Passive Mode (|||50522|),\n- * 50522 is the port we want\". */\n- char *tmp = req;\n- while (*tmp != '|' && *tmp != '\\0') {\n- port = port * 10 + (*tmp - '0');\n- tmp++;\n- }\n-\n- port = htons(port);\n-\n- serverIp.ipv6 = key->ipv6Key.ipv6Src;\n- clientIp.ipv6 = key->ipv6Key.ipv6Dst;\n- }\n- }\n-\n- switch (ftpType) {\n- case FTP_TYPE_PASV:\n- /* Ensure that the command states Server's IP address */\n- OvsCtRelatedEntryCreate(key->ipKey.nwProto,\n- key->l2.dlType,\n- /* Server's IP */\n- serverIp,\n- /* Use intended client's IP */\n- clientIp,\n- /* Dynamic port opened on server */\n- port,\n- /* We don't know the client port */\n- 0,\n- currentTime,\n- entry);\n- break;\n- case FTP_TYPE_ACTIVE:\n- OvsCtRelatedEntryCreate(key->ipKey.nwProto,\n- key->l2.dlType,\n- /* Server's default IP address */\n- serverIp,\n- /* Client's IP address */\n- clientIp,\n- /* FTP Data Port is 20 */\n- ntohs(IPPORT_FTP_DATA),\n- /* Port opened up on Client */\n- port,\n- currentTime,\n- entry);\n- break;\n- case FTP_EXTEND_TYPE_PASV:\n- OvsCtRelatedEntryCreate(key->ipv6Key.nwProto,\n- key->l2.dlType,\n- serverIp,\n- clientIp,\n- port,\n- 0,\n- currentTime,\n- entry);\n- break;\n- case FTP_EXTEND_TYPE_ACTIVE:\n- OvsCtRelatedEntryCreate(key->ipv6Key.nwProto,\n- key->l2.dlType,\n- /* Server's default IP address */\n- serverIp,\n- /* Client's IP address */\n- clientIp,\n- /* FTP Data Port is 20 */\n- ntohs(IPPORT_FTP_DATA),\n- /* Port opened up on Client */\n- port,\n- currentTime,\n- entry);\n- break;\n- default:\n- OVS_LOG_ERROR(\"invalid ftp type:%d\", ftpType);\n- status = NDIS_STATUS_INVALID_PARAMETER;\n- break;\n- }\n-\n- return status;\n-}\ndiff --git a/datapath-windows/ovsext/Conntrack-icmp.c b/datapath-windows/ovsext/Conntrack-icmp.c\ndeleted file mode 100644\nindex 081eb73d9..000000000\n--- a/datapath-windows/ovsext/Conntrack-icmp.c\n+++ /dev/null\n@@ -1,105 +0,0 @@\n-/*\n- * Copyright (c) 2016 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#include \"NetProto.h\"\n-#include \"Conntrack.h\"\n-#include <stddef.h>\n-\n-enum icmp_state {\n- ICMPS_FIRST,\n- ICMPS_REPLY,\n-};\n-\n-struct conn_icmp {\n- struct OVS_CT_ENTRY up;\n- enum icmp_state state;\n-};\n-C_ASSERT(offsetof(struct conn_icmp, up) == 0);\n-\n-static const enum ct_timeout icmp_timeouts[] = {\n- [ICMPS_FIRST] = 60 * CT_INTERVAL_SEC,\n- [ICMPS_REPLY] = 30 * CT_INTERVAL_SEC,\n-};\n-\n-static __inline struct conn_icmp *\n-OvsCastConntrackEntryToIcmpEntry(OVS_CT_ENTRY* conn)\n-{\n- return CONTAINER_OF(conn, struct conn_icmp, up);\n-}\n-\n-enum CT_UPDATE_RES\n-OvsConntrackUpdateIcmpEntry(OVS_CT_ENTRY* conn_,\n- BOOLEAN reply,\n- UINT64 now)\n-{\n- struct conn_icmp *conn = OvsCastConntrackEntryToIcmpEntry(conn_);\n-\n- if (reply && conn->state != ICMPS_REPLY) {\n- conn->state = ICMPS_REPLY;\n- }\n-\n- OvsConntrackUpdateExpiration(&conn->up, now,\n- icmp_timeouts[conn->state]);\n-\n- return CT_UPDATE_VALID;\n-}\n-\n-BOOLEAN\n-OvsConntrackValidateIcmpPacket(const ICMPHdr *icmp)\n-{\n- if (!icmp) {\n- OVS_LOG_TRACE(\"Invalid ICMP packet detected, header cannot be NULL\");\n- return FALSE;\n- }\n-\n- return icmp->type == ICMP4_ECHO_REQUEST\n- || icmp->type == ICMP4_INFO_REQUEST\n- || icmp->type == ICMP4_TIMESTAMP_REQUEST;\n-}\n-\n-BOOLEAN\n-OvsConntrackValidateIcmp6Packet(const ICMPHdr *icmp)\n-{\n- if (!icmp) {\n- OVS_LOG_TRACE(\"Invalid ICMP packet detected, header cannot be NULL\");\n- return FALSE;\n- }\n-\n- return icmp->type == ICMP6_ECHO_REQUEST ||\n- icmp->type == ICMP6_PACKET_TOO_BIG ||\n- icmp->type == ICMP6_DST_UNREACH ||\n- icmp->type == ICMP6_TIME_EXCEEDED ||\n- icmp->type == ICMP6_PARAM_PROB;\n-}\n-\n-OVS_CT_ENTRY *\n-OvsConntrackCreateIcmpEntry(UINT64 now)\n-{\n- struct conn_icmp *conn;\n-\n- conn = OvsAllocateMemoryWithTag(sizeof(struct conn_icmp),\n- OVS_CT_POOL_TAG);\n- if (!conn) {\n- return NULL;\n- }\n- conn->up = (OVS_CT_ENTRY) {0};\n- conn->state = ICMPS_FIRST;\n-\n- OvsConntrackUpdateExpiration(&conn->up, now,\n- icmp_timeouts[conn->state]);\n-\n- return &conn->up;\n-}\ndiff --git a/datapath-windows/ovsext/Conntrack-nat.c b/datapath-windows/ovsext/Conntrack-nat.c\ndeleted file mode 100644\nindex 497354ec8..000000000\n--- a/datapath-windows/ovsext/Conntrack-nat.c\n+++ /dev/null\n@@ -1,523 +0,0 @@\n-#include \"Conntrack-nat.h\"\n-#include \"Jhash.h\"\n-\n-PLIST_ENTRY ovsNatTable = NULL;\n-PLIST_ENTRY ovsUnNatTable = NULL;\n-static NDIS_SPIN_LOCK ovsCtNatLock;\n-static ULONG ovsNatEntries;\n-/*\n- *---------------------------------------------------------------------------\n- * OvsHashNatKey\n- * Hash NAT related fields in a Conntrack key.\n- *---------------------------------------------------------------------------\n- */\n-static __inline UINT32\n-OvsHashNatKey(const OVS_CT_KEY *key)\n-{\n- UINT32 hash = 0;\n-#define HASH_ADD(field) \\\n- hash = OvsJhashBytes(&key->field, sizeof(key->field), hash)\n-\n- HASH_ADD(src.addr.ipv4_aligned);\n- HASH_ADD(dst.addr.ipv4_aligned);\n- HASH_ADD(src.port);\n- HASH_ADD(dst.port);\n- HASH_ADD(zone);\n- /* icmp_id and port overlap in the union */\n- HASH_ADD(src.icmp_type);\n- HASH_ADD(dst.icmp_type);\n- HASH_ADD(src.icmp_code);\n- HASH_ADD(dst.icmp_code);\n-\n-#undef HASH_ADD\n- return hash;\n-}\n-\n-/*\n- *---------------------------------------------------------------------------\n- * OvsNatKeyAreSame\n- * Compare NAT related fields in a Conntrack key.\n- *---------------------------------------------------------------------------\n- */\n-static __inline BOOLEAN\n-OvsNatKeyAreSame(const OVS_CT_KEY *key1, const OVS_CT_KEY *key2)\n-{\n-#define FIELD_COMPARE(field) \\\n- if (key1->field != key2->field) return FALSE\n-\n- FIELD_COMPARE(src.port);\n- FIELD_COMPARE(dst.port);\n- FIELD_COMPARE(zone);\n- /* icmp_id and port overlap in the union */\n- FIELD_COMPARE(src.icmp_type);\n- FIELD_COMPARE(dst.icmp_type);\n- FIELD_COMPARE(src.icmp_code);\n- FIELD_COMPARE(dst.icmp_code);\n-\n- if (memcmp(&(key1->src.addr), &(key2->src.addr), sizeof(struct ct_addr))) {\n- return FALSE;\n- }\n-\n- if (memcmp(&(key1->dst.addr), &(key2->dst.addr), sizeof(struct ct_addr))) {\n- return FALSE;\n- }\n-\n- return TRUE;\n-#undef FIELD_COMPARE\n-}\n-\n-/*\n- *---------------------------------------------------------------------------\n- * OvsNatGetBucket\n- * Returns the row of NAT table that has the same hash as the given NAT\n- * hash key. If isReverse is TRUE, returns the row of reverse NAT table\n- * instead.\n- *---------------------------------------------------------------------------\n- */\n-static __inline PLIST_ENTRY\n-OvsNatGetBucket(const OVS_CT_KEY *key, BOOLEAN isReverse)\n-{\n- uint32_t hash = OvsHashNatKey(key);\n- if (isReverse) {\n- return &ovsUnNatTable[hash & NAT_HASH_TABLE_MASK];\n- } else {\n- return &ovsNatTable[hash & NAT_HASH_TABLE_MASK];\n- }\n-}\n-\n-/*\n- *---------------------------------------------------------------------------\n- * OvsNatInit\n- * Initialize NAT related resources.\n- *---------------------------------------------------------------------------\n- */\n-NTSTATUS OvsNatInit()\n-{\n- ASSERT(ovsNatTable == NULL);\n-\n- /* Init the Hash Buffer */\n- ovsNatTable = OvsAllocateMemoryWithTag(\n- sizeof(LIST_ENTRY) * NAT_HASH_TABLE_SIZE,\n- OVS_CT_POOL_TAG);\n- if (ovsNatTable == NULL) {\n- return STATUS_INSUFFICIENT_RESOURCES;\n- }\n-\n- ovsUnNatTable = OvsAllocateMemoryWithTag(\n- sizeof(LIST_ENTRY) * NAT_HASH_TABLE_SIZE,\n- OVS_CT_POOL_TAG);\n- if (ovsUnNatTable == NULL) {\n- OvsFreeMemoryWithTag(ovsNatTable, OVS_CT_POOL_TAG);\n- return STATUS_INSUFFICIENT_RESOURCES;\n- }\n-\n- for (int i = 0; i < NAT_HASH_TABLE_SIZE; i++) {\n- InitializeListHead(&ovsNatTable[i]);\n- InitializeListHead(&ovsUnNatTable[i]);\n- }\n-\n- NdisAllocateSpinLock(&ovsCtNatLock);\n- ovsNatEntries = 0;\n- return STATUS_SUCCESS;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsNatFlush\n- * Flushes out all NAT entries that match the given zone.\n- *----------------------------------------------------------------------------\n- */\n-VOID OvsNatFlush(UINT16 zone)\n-{\n- PLIST_ENTRY link, next;\n- if (!ovsNatEntries) {\n- return;\n- }\n-\n- NdisAcquireSpinLock(&ovsCtNatLock);\n- for (int i = 0; i < NAT_HASH_TABLE_SIZE; i++) {\n- LIST_FORALL_SAFE(&ovsNatTable[i], link, next) {\n- POVS_NAT_ENTRY entry =\n- CONTAINING_RECORD(link, OVS_NAT_ENTRY, link);\n- /* zone is a non-zero value */\n- if (!zone || zone == entry->key.zone) {\n- OvsNatDeleteEntry(entry);\n- }\n- }\n- }\n- NdisReleaseSpinLock(&ovsCtNatLock);\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsNatCleanup\n- * Releases all NAT related resources.\n- *----------------------------------------------------------------------------\n- */\n-VOID OvsNatCleanup()\n-{\n- if (ovsNatTable == NULL) {\n- NdisFreeSpinLock(&ovsCtNatLock);\n- return;\n- }\n-\n- NdisAcquireSpinLock(&ovsCtNatLock);\n- OvsFreeMemoryWithTag(ovsNatTable, OVS_CT_POOL_TAG);\n- OvsFreeMemoryWithTag(ovsUnNatTable, OVS_CT_POOL_TAG);\n- ovsNatTable = NULL;\n- ovsUnNatTable = NULL;\n- NdisReleaseSpinLock(&ovsCtNatLock);\n- NdisFreeSpinLock(&ovsCtNatLock);\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsNatPacket\n- * Performs NAT operation on the packet by replacing the source/destinaton\n- * address/port based on natAction. If reverse is TRUE, perform unNAT\n- * instead.\n- *----------------------------------------------------------------------------\n- */\n-VOID\n-OvsNatPacket(OvsForwardingContext *ovsFwdCtx,\n- const OVS_CT_ENTRY *entry,\n- UINT16 natAction,\n- OvsFlowKey *key,\n- BOOLEAN reverse)\n-{\n- UINT32 natFlag;\n- const struct ct_endpoint* endpoint;\n-\n- /* When it is NAT, only entry->rev_key contains NATTED address;\n- When it is unNAT, only entry->key contains the UNNATTED address;*/\n- const OVS_CT_KEY *ctKey = reverse ? &entry->key : &entry->rev_key;\n- BOOLEAN isSrcNat;\n-\n- if (!(natAction & (NAT_ACTION_SRC | NAT_ACTION_DST))) {\n- return;\n- }\n- isSrcNat = (((natAction & NAT_ACTION_SRC) && !reverse) ||\n- ((natAction & NAT_ACTION_DST) && reverse));\n-\n- if (isSrcNat) {\n- /* Flag is set to SNAT for SNAT case and the reverse DNAT case */\n- natFlag = OVS_CS_F_SRC_NAT;\n- /* Note that ctKey is the key in the other direction, so\n- endpoint has to be reverted, i.e. ctKey->dst for SNAT\n- and ctKey->src for DNAT */\n- endpoint = &ctKey->dst;\n- } else {\n- natFlag = OVS_CS_F_DST_NAT;\n- endpoint = &ctKey->src;\n- }\n- key->ct.state |= natFlag;\n- if (ctKey->dl_type == htons(ETH_TYPE_IPV4)) {\n- OvsUpdateAddressAndPort(ovsFwdCtx,\n- endpoint->addr.ipv4_aligned,\n- endpoint->port, isSrcNat,\n- !reverse);\n- if (isSrcNat) {\n- key->ipKey.nwSrc = endpoint->addr.ipv4_aligned;\n- } else {\n- key->ipKey.nwDst = endpoint->addr.ipv4_aligned;\n- }\n- } else if (ctKey->dl_type == htons(ETH_TYPE_IPV6)) {\n- OvsUpdateAddressAndPortForIpv6(ovsFwdCtx,\n- endpoint->addr.ipv6,\n- endpoint->port, isSrcNat,\n- !reverse);\n- if (isSrcNat) {\n- key->ipv6Key.ipv6Src = endpoint->addr.ipv6;\n- } else {\n- key->ipv6Key.ipv6Dst = endpoint->addr.ipv6;\n- }\n- }\n- if (natAction & (NAT_ACTION_SRC_PORT | NAT_ACTION_DST_PORT)) {\n- if (ctKey->dl_type == htons(ETH_TYPE_IPV4)) {\n- if (isSrcNat) {\n- if (key->ipKey.l4.tpSrc != 0) {\n- key->ipKey.l4.tpSrc = endpoint->port;\n- }\n- } else {\n- if (key->ipKey.l4.tpDst != 0) {\n- key->ipKey.l4.tpDst = endpoint->port;\n- }\n- }\n- } else if (ctKey->dl_type == htons(ETH_TYPE_IPV6)) {\n- if (isSrcNat) {\n- if (key->ipv6Key.l4.tpSrc != 0) {\n- key->ipv6Key.l4.tpSrc = endpoint->port;\n- }\n- } else {\n- if (key->ipv6Key.l4.tpDst != 0) {\n- key->ipv6Key.l4.tpDst = endpoint->port;\n- }\n- }\n- }\n- }\n-}\n-\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsNatHashRange\n- * Compute hash for a range of addresses specified in natInfo.\n- *----------------------------------------------------------------------------\n- */\n-static UINT32 OvsNatHashRange(const OVS_CT_ENTRY *entry, UINT32 basis)\n-{\n- UINT32 hash = basis;\n-#define HASH_ADD(field) \\\n- hash = OvsJhashBytes(&field, sizeof(field), hash)\n-\n- HASH_ADD(entry->natInfo.minAddr);\n- HASH_ADD(entry->natInfo.maxAddr);\n- HASH_ADD(entry->key.dl_type);\n- HASH_ADD(entry->key.nw_proto);\n- HASH_ADD(entry->key.zone);\n-#undef HASH_ADD\n- return hash;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsNatAddEntry\n- * Add an entry to the NAT table. Also updates the reverse NAT lookup\n- * table.\n- *----------------------------------------------------------------------------\n- */\n-VOID\n-OvsNatAddEntry(OVS_NAT_ENTRY* entry)\n-{\n- NdisAcquireSpinLock(&ovsCtNatLock);\n- InsertHeadList(OvsNatGetBucket(&entry->key, FALSE),\n- &entry->link);\n- InsertHeadList(OvsNatGetBucket(&entry->value, TRUE),\n- &entry->reverseLink);\n- NdisReleaseSpinLock(&ovsCtNatLock);\n- NdisInterlockedIncrement((PLONG)&ovsNatEntries);\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsNatTranslateCtEntry\n- * Update an Conntrack entry with NAT information. Translated address and\n- * port will be generated and write back to the conntrack entry as a\n- * result.\n- * Note: For ICMP, only address is translated.\n- *----------------------------------------------------------------------------\n- */\n-BOOLEAN\n-OvsNatTranslateCtEntry(OVS_CT_ENTRY *entry)\n-{\n- const uint16_t MIN_NAT_EPHEMERAL_PORT = 1024;\n- const uint16_t MAX_NAT_EPHEMERAL_PORT = 65535;\n-\n- uint16_t minPort;\n- uint16_t maxPort;\n- uint16_t firstPort;\n- uint32_t addrDelta = 0;\n- uint32_t addrIndex;\n- struct ct_addr ctAddr, maxCtAddr;\n- uint16_t port;\n- BOOLEAN allPortsTried;\n- BOOLEAN originalPortsTried;\n- struct ct_addr firstAddr;\n-\n- uint32_t hash = OvsNatHashRange(entry, 0);\n-\n- if ((entry->natInfo.natAction & NAT_ACTION_SRC) &&\n- (!(entry->natInfo.natAction & NAT_ACTION_SRC_PORT))) {\n- firstPort = minPort = maxPort = ntohs(entry->key.src.port);\n- } else if ((entry->natInfo.natAction & NAT_ACTION_DST) &&\n- (!(entry->natInfo.natAction & NAT_ACTION_DST_PORT))) {\n- firstPort = minPort = maxPort = ntohs(entry->key.dst.port);\n- } else {\n- uint16_t portDelta = entry->natInfo.maxPort - entry->natInfo.minPort;\n- uint16_t portIndex = (uint16_t) hash % (portDelta + 1);\n- firstPort = entry->natInfo.minPort + portIndex;\n- minPort = entry->natInfo.minPort;\n- maxPort = entry->natInfo.maxPort;\n- }\n-\n- memset(&ctAddr, 0, sizeof ctAddr);\n- memset(&maxCtAddr, 0, sizeof maxCtAddr);\n- maxCtAddr = entry->natInfo.maxAddr;\n-\n- if (entry->key.dl_type == htons(ETH_TYPE_IPV4)) {\n- addrDelta = ntohl(entry->natInfo.maxAddr.ipv4_aligned) -\n- ntohl(entry->natInfo.minAddr.ipv4_aligned);\n- addrIndex = hash % (addrDelta + 1);\n- ctAddr.ipv4_aligned = htonl(\n- ntohl(entry->natInfo.minAddr.ipv4_aligned) + addrIndex);\n- } else {\n- /** Current, only support nat single address**/\n- ctAddr.ipv6_aligned = entry->natInfo.minAddr.ipv6_aligned;\n- }\n-\n- port = firstPort;\n- allPortsTried = FALSE;\n- originalPortsTried = FALSE;\n- firstAddr = ctAddr;\n- for (;;) {\n- if (entry->natInfo.natAction & NAT_ACTION_SRC) {\n- entry->rev_key.dst.addr = ctAddr;\n- if (entry->rev_key.nw_proto != IPPROTO_ICMP) {\n- entry->rev_key.dst.port = htons(port);\n- }\n- } else {\n- entry->rev_key.src.addr = ctAddr;\n- if (entry->rev_key.nw_proto != IPPROTO_ICMP) {\n- entry->rev_key.src.port = htons(port);\n- }\n- }\n-\n- OVS_NAT_ENTRY *natEntry = OvsNatLookup(&entry->rev_key, TRUE);\n-\n- if (!natEntry) {\n- natEntry = OvsAllocateMemoryWithTag(sizeof(*natEntry),\n- OVS_CT_POOL_TAG);\n- if (!natEntry) {\n- return FALSE;\n- }\n- memcpy(&natEntry->key, &entry->key,\n- sizeof natEntry->key);\n- memcpy(&natEntry->value, &entry->rev_key,\n- sizeof natEntry->value);\n- natEntry->ctEntry = entry;\n- OvsNatAddEntry(natEntry);\n- return TRUE;\n- } else if (!allPortsTried) {\n- if (minPort == maxPort) {\n- allPortsTried = TRUE;\n- } else if (port == maxPort) {\n- port = minPort;\n- } else {\n- port++;\n- }\n- if (port == firstPort) {\n- allPortsTried = TRUE;\n- }\n- } else {\n- if (memcmp(&ctAddr, &maxCtAddr, sizeof ctAddr)) {\n- if (entry->key.dl_type == htons(ETH_TYPE_IPV4)) {\n- ctAddr.ipv4_aligned = htonl(\n- ntohl(ctAddr.ipv4_aligned) + 1);\n- } else {\n- /** When all ports was used, return fails indicate exceed range. **/\n- uint32_t addr[8] = {0};\n- uint16_t *tmpAddr = (uint16_t *)&(ctAddr.ipv6_aligned);\n- for (int m = 0; m < 8; m++) {\n- addr[m] = tmpAddr[m];\n- }\n-\n- uint16_t carry = 1, i = 8;\n- while (carry && i)\n- {\n- addr[i-1] += carry;\n- if (addr[i-1] > 0xffff || !addr[i-1])\n- {\n- carry = 1;\n- addr[i-1] &= 0xffff;\n- } else carry = 0;\n- i--;\n- }\n-\n- if (carry) {\n- OVS_LOG_INFO(\"Ipv6 address incremented overflow.\");\n- return FALSE;\n- }\n-\n- for (int m = 0; m < 8; m++) {\n- tmpAddr[m] = (uint16_t)addr[m];\n- }\n- }\n- } else {\n- ctAddr = entry->natInfo.minAddr;\n- }\n- if (!memcmp(&ctAddr, &firstAddr, sizeof ctAddr)) {\n- if (!originalPortsTried) {\n- originalPortsTried = TRUE;\n- ctAddr = entry->natInfo.minAddr;\n- minPort = MIN_NAT_EPHEMERAL_PORT;\n- maxPort = MAX_NAT_EPHEMERAL_PORT;\n- } else {\n- break;\n- }\n- }\n- firstPort = minPort;\n- port = firstPort;\n- allPortsTried = FALSE;\n- }\n- }\n- return FALSE;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsNatLookup\n- * Look up a NAT entry with the given key in the NAT table.\n- * If reverse is TRUE, look up a NAT entry with the given value instead.\n- *----------------------------------------------------------------------------\n- */\n-POVS_NAT_ENTRY\n-OvsNatLookup(const OVS_CT_KEY *ctKey, BOOLEAN reverse)\n-{\n- PLIST_ENTRY link;\n- POVS_NAT_ENTRY entry;\n-\n- if (!ovsNatEntries) {\n- return NULL;\n- }\n-\n- NdisAcquireSpinLock(&ovsCtNatLock);\n- LIST_FORALL(OvsNatGetBucket(ctKey, reverse), link) {\n- if (reverse) {\n- entry = CONTAINING_RECORD(link, OVS_NAT_ENTRY, reverseLink);\n-\n- if (OvsNatKeyAreSame(ctKey, &entry->value)) {\n- NdisReleaseSpinLock(&ovsCtNatLock);\n- return entry;\n- }\n- } else {\n- entry = CONTAINING_RECORD(link, OVS_NAT_ENTRY, link);\n-\n- if (OvsNatKeyAreSame(ctKey, &entry->key)) {\n- NdisReleaseSpinLock(&ovsCtNatLock);\n- return entry;\n- }\n- }\n- }\n- NdisReleaseSpinLock(&ovsCtNatLock);\n- return NULL;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsNatDeleteEntry\n- * Delete a NAT entry.\n- *----------------------------------------------------------------------------\n- */\n-VOID\n-OvsNatDeleteEntry(POVS_NAT_ENTRY entry)\n-{\n- if (entry == NULL) {\n- return;\n- }\n- RemoveEntryList(&entry->link);\n- RemoveEntryList(&entry->reverseLink);\n- OvsFreeMemoryWithTag(entry, OVS_CT_POOL_TAG);\n- NdisInterlockedDecrement((PLONG)&ovsNatEntries);\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsNatDeleteKey\n- * Delete a NAT entry with the given key.\n- *----------------------------------------------------------------------------\n- */\n-VOID\n-OvsNatDeleteKey(const OVS_CT_KEY *key)\n-{\n- OvsNatDeleteEntry(OvsNatLookup(key, FALSE));\n-}\ndiff --git a/datapath-windows/ovsext/Conntrack-nat.h b/datapath-windows/ovsext/Conntrack-nat.h\ndeleted file mode 100644\nindex 445a29dcc..000000000\n--- a/datapath-windows/ovsext/Conntrack-nat.h\n+++ /dev/null\n@@ -1,39 +0,0 @@\n-#ifndef _CONNTRACK_NAT_H\n-#define _CONNTRACK_NAT_H\n-\n-#include \"precomp.h\"\n-#include \"Flow.h\"\n-#include \"Debug.h\"\n-#include <stddef.h>\n-#include \"Conntrack.h\"\n-\n-#define NAT_HASH_TABLE_SIZE ((UINT32)1 << 10)\n-#define NAT_HASH_TABLE_MASK (NAT_HASH_TABLE_SIZE - 1)\n-\n-typedef struct OVS_NAT_ENTRY {\n- LIST_ENTRY link;\n- LIST_ENTRY reverseLink;\n- OVS_CT_KEY key;\n- OVS_CT_KEY value;\n- POVS_CT_ENTRY ctEntry;\n-} OVS_NAT_ENTRY, *POVS_NAT_ENTRY;\n-\n-__inline static BOOLEAN OvsIsForwardNat(UINT16 natAction) {\n- return !!(natAction & (NAT_ACTION_SRC | NAT_ACTION_DST));\n-}\n-\n-NTSTATUS OvsNatInit();\n-VOID OvsNatFlush(UINT16 zone);\n-\n-VOID OvsNatAddEntry(OVS_NAT_ENTRY* entry);\n-\n-VOID OvsNatDeleteEntry(POVS_NAT_ENTRY entry);\n-VOID OvsNatDeleteKey(const OVS_CT_KEY *key);\n-VOID OvsNatCleanup();\n-\n-POVS_NAT_ENTRY OvsNatLookup(const OVS_CT_KEY *ctKey, BOOLEAN reverse);\n-BOOLEAN OvsNatTranslateCtEntry(OVS_CT_ENTRY *ctEntry);\n-VOID OvsNatPacket(OvsForwardingContext *ovsFwdCtx, const OVS_CT_ENTRY *entry,\n- UINT16 natAction, OvsFlowKey *key, BOOLEAN reverse);\n-\n-#endif\ndiff --git a/datapath-windows/ovsext/Conntrack-other.c b/datapath-windows/ovsext/Conntrack-other.c\ndeleted file mode 100644\nindex 8580415a6..000000000\n--- a/datapath-windows/ovsext/Conntrack-other.c\n+++ /dev/null\n@@ -1,81 +0,0 @@\n-/*\n- * Copyright (c) 2015, 2016 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#include \"Conntrack.h\"\n-#include <stddef.h>\n-\n-enum other_state {\n- OTHERS_FIRST,\n- OTHERS_MULTIPLE,\n- OTHERS_BIDIR,\n-};\n-\n-struct conn_other {\n- struct OVS_CT_ENTRY up;\n- enum other_state state;\n-};\n-C_ASSERT(offsetof(struct conn_other, up) == 0);\n-\n-static const long long other_timeouts[] = {\n- [OTHERS_FIRST] = 60 * CT_INTERVAL_SEC,\n- [OTHERS_MULTIPLE] = 60 * CT_INTERVAL_SEC,\n- [OTHERS_BIDIR] = 30 * CT_INTERVAL_SEC,\n-};\n-\n-static __inline struct conn_other*\n-OvsCastConntrackEntryToOtherEntry(OVS_CT_ENTRY *conn)\n-{\n- ASSERT(conn);\n- return CONTAINER_OF(conn, struct conn_other, up);\n-}\n-\n-enum CT_UPDATE_RES\n-OvsConntrackUpdateOtherEntry(OVS_CT_ENTRY *conn_,\n- BOOLEAN reply,\n- UINT64 now)\n-{\n- ASSERT(conn_);\n- struct conn_other *conn = OvsCastConntrackEntryToOtherEntry(conn_);\n- enum CT_UPDATE_RES ret = CT_UPDATE_VALID;\n-\n- if (reply && conn->state != OTHERS_BIDIR) {\n- conn->state = OTHERS_BIDIR;\n- } else if (conn->state == OTHERS_FIRST) {\n- conn->state = OTHERS_MULTIPLE;\n- ret = CT_UPDATE_VALID_NEW;\n- }\n-\n- OvsConntrackUpdateExpiration(&conn->up, now,\n- other_timeouts[conn->state]);\n-\n- return ret;\n-}\n-\n-OVS_CT_ENTRY *\n-OvsConntrackCreateOtherEntry(UINT64 now)\n-{\n- struct conn_other *conn;\n- conn = OvsAllocateMemoryWithTag(sizeof(struct conn_other),\n- OVS_CT_POOL_TAG);\n- if (!conn) {\n- return NULL;\n- }\n- conn->up = (OVS_CT_ENTRY) {0};\n- conn->state = OTHERS_FIRST;\n- OvsConntrackUpdateExpiration(&conn->up, now,\n- other_timeouts[conn->state]);\n- return &conn->up;\n-}\ndiff --git a/datapath-windows/ovsext/Conntrack-related.c b/datapath-windows/ovsext/Conntrack-related.c\ndeleted file mode 100644\nindex 99b1553da..000000000\n--- a/datapath-windows/ovsext/Conntrack-related.c\n+++ /dev/null\n@@ -1,361 +0,0 @@\n-/*\n- * Copyright (c) 2016 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#include \"Conntrack.h\"\n-#include \"Jhash.h\"\n-\n-static PLIST_ENTRY ovsCtRelatedTable; /* Holds related entries */\n-static ULONG ctTotalRelatedEntries;\n-static OVS_CT_THREAD_CTX ctRelThreadCtx;\n-static PNDIS_RW_LOCK_EX ovsCtRelatedLockObj;\n-extern POVS_SWITCH_CONTEXT gOvsSwitchContext;\n-KSTART_ROUTINE OvsCtRelatedEntryCleaner;\n-\n-static __inline UINT32\n-OvsExtractCtRelatedKeyHash(OVS_CT_KEY *key)\n-{\n- UINT32 hsrc, hdst,hash;\n- hsrc = OvsJhashBytes((UINT32*) &key->src, sizeof(key->src), 0);\n- hdst = OvsJhashBytes((UINT32*) &key->dst, sizeof(key->dst), 0);\n- hash = hsrc ^ hdst; /* TO identify reverse traffic */\n- return hash;\n-}\n-\n-static __inline BOOLEAN\n-OvsCtRelatedKeyAreSame(OVS_CT_KEY incomingKey, OVS_CT_KEY entryKey)\n-{\n- /* FTP PASV - Client initiates the connection from unknown port */\n- if ((incomingKey.dl_type == entryKey.dl_type) &&\n- (incomingKey.dl_type == htons(ETH_TYPE_IPV4)) &&\n- (incomingKey.nw_proto == IPPROTO_TCP) &&\n- (incomingKey.dst.addr.ipv4 == entryKey.src.addr.ipv4) &&\n- (incomingKey.dst.port == entryKey.src.port) &&\n- (incomingKey.src.addr.ipv4 == entryKey.dst.addr.ipv4) &&\n- (incomingKey.nw_proto == entryKey.nw_proto)) {\n- return TRUE;\n- }\n-\n- if ((incomingKey.dl_type == entryKey.dl_type) &&\n- (incomingKey.dl_type == htons(ETH_TYPE_IPV6)) &&\n- (incomingKey.nw_proto == IPPROTO_TCP) &&\n- !memcmp(&(incomingKey.dst.addr.ipv6), &(entryKey.src.addr.ipv6),\n- sizeof(incomingKey.dst.addr.ipv6)) &&\n- (incomingKey.dst.port == entryKey.src.port) &&\n- !memcmp(&(incomingKey.src.addr.ipv6), &(entryKey.dst.addr.ipv6),\n- sizeof(incomingKey.src.addr.ipv6)) &&\n- (incomingKey.nw_proto == entryKey.nw_proto)) {\n- return TRUE;\n- }\n-\n- /* FTP ACTIVE - Server initiates the connection */\n- /* Some ftp server, such as pyftpdlib, may use random (>1024) data port\n- * except 20. In this case, the incomingKey's src port is different with\n- * entryKey's src port.\n- */\n- if ((incomingKey.dl_type == entryKey.dl_type) &&\n- (incomingKey.dl_type == htons(ETH_TYPE_IPV4)) &&\n- (incomingKey.nw_proto == IPPROTO_TCP) &&\n- (incomingKey.src.addr.ipv4 == entryKey.src.addr.ipv4) &&\n- (incomingKey.dst.addr.ipv4 == entryKey.dst.addr.ipv4) &&\n- (incomingKey.dst.port == entryKey.dst.port) &&\n- (incomingKey.nw_proto == entryKey.nw_proto)) {\n- return TRUE;\n- }\n-\n- if ((incomingKey.dl_type == entryKey.dl_type) &&\n- (incomingKey.dl_type == htons(ETH_TYPE_IPV6)) &&\n- (incomingKey.nw_proto == IPPROTO_TCP) &&\n- !memcmp(&(incomingKey.src.addr.ipv6), &(entryKey.src.addr.ipv6),\n- sizeof(incomingKey.src.addr.ipv6)) &&\n- !memcmp(&(incomingKey.dst.addr.ipv6), &(entryKey.dst.addr.ipv6),\n- sizeof(incomingKey.src.addr.ipv6)) &&\n- (incomingKey.dst.port == entryKey.dst.port) &&\n- (incomingKey.nw_proto == entryKey.nw_proto)) {\n- return TRUE;\n- }\n-\n- /* Tftp protocol */\n- if ((incomingKey.dl_type == entryKey.dl_type) &&\n- (incomingKey.dl_type == htons(ETH_TYPE_IPV4)) &&\n- (incomingKey.nw_proto == IPPROTO_UDP) &&\n- !memcmp(&(incomingKey.src.addr.ipv4), &(entryKey.src.addr.ipv4),\n- sizeof(incomingKey.src.addr.ipv4)) &&\n- !memcmp(&(incomingKey.dst.addr.ipv4), &(entryKey.dst.addr.ipv4),\n- sizeof(incomingKey.dst.addr.ipv4)) &&\n- (incomingKey.dst.port == entryKey.dst.port) &&\n- (incomingKey.nw_proto == entryKey.nw_proto)) {\n- return TRUE;\n- }\n-\n- if ((incomingKey.dl_type == entryKey.dl_type) &&\n- (incomingKey.dl_type == htons(ETH_TYPE_IPV6)) &&\n- (incomingKey.nw_proto == IPPROTO_UDP) &&\n- !memcmp(&(incomingKey.src.addr.ipv6), &(entryKey.src.addr.ipv6),\n- sizeof(incomingKey.src.addr.ipv6)) &&\n- !memcmp(&(incomingKey.dst.addr.ipv6), &(entryKey.dst.addr.ipv6),\n- sizeof(incomingKey.dst.addr.ipv6)) &&\n- (incomingKey.dst.port == entryKey.dst.port) &&\n- (incomingKey.nw_proto == entryKey.nw_proto)) {\n- return TRUE;\n- }\n-\n- return FALSE;\n-}\n-\n-/*\n- *---------------------------------------------------------------------------\n- * OvsCtRelatedLookup\n- * Checks the related connections table for an entry that matches the\n- * incoming connection. If there is a matching entry, then it returns\n- * the pointer to the original control connection.\n- *\n- *---------------------------------------------------------------------------\n- */\n-POVS_CT_ENTRY\n-OvsCtRelatedLookup(OVS_CT_KEY key, UINT64 currentTime)\n-{\n- PLIST_ENTRY link, next;\n- POVS_CT_REL_ENTRY entry;\n- LOCK_STATE_EX lockState;\n-\n- if (!ctTotalRelatedEntries) {\n- return NULL;\n- }\n-\n- NdisAcquireRWLockRead(ovsCtRelatedLockObj, &lockState, 0);\n- for (int i = 0; i < CT_HASH_TABLE_SIZE; i++) {\n- /* XXX - Scan the table based on the hash instead */\n- LIST_FORALL_SAFE(&ovsCtRelatedTable[i], link, next) {\n- entry = CONTAINING_RECORD(link, OVS_CT_REL_ENTRY, link);\n- if (entry->expiration > currentTime) {\n- if (OvsCtRelatedKeyAreSame(key, entry->key)) {\n- NdisReleaseRWLock(ovsCtRelatedLockObj, &lockState);\n- return entry->parent;\n- }\n- }\n- }\n- }\n- NdisReleaseRWLock(ovsCtRelatedLockObj, &lockState);\n- return NULL;\n-}\n-\n-static __inline VOID\n-OvsCtRelatedEntryDelete(POVS_CT_REL_ENTRY entry)\n-{\n- RemoveEntryList(&entry->link);\n- OvsFreeMemoryWithTag(entry, OVS_CT_POOL_TAG);\n- NdisInterlockedDecrement((PLONG)&ctTotalRelatedEntries);\n-}\n-\n-NDIS_STATUS\n-OvsCtRelatedEntryCreate(UINT8 ipProto,\n- UINT16 dl_type,\n- struct ct_addr serverIp,\n- struct ct_addr clientIp,\n- UINT16 serverPort,\n- UINT16 clientPort,\n- UINT64 currentTime,\n- POVS_CT_ENTRY parent)\n-{\n- LOCK_STATE_EX lockState;\n- POVS_CT_REL_ENTRY entry;\n- entry = OvsAllocateMemoryWithTag(sizeof(OVS_CT_REL_ENTRY),\n- OVS_CT_POOL_TAG);\n- if (!entry) {\n- return NDIS_STATUS_RESOURCES;\n- }\n-\n- RtlZeroMemory(entry, sizeof(struct OVS_CT_REL_ENTRY));\n- entry->expiration = currentTime + (CT_INTERVAL_SEC * 60);\n- entry->key.nw_proto = ipProto;\n- entry->key.dl_type = dl_type;\n- entry->key.src.port = serverPort;\n- entry->key.dst.port = clientPort;\n- entry->parent = parent;\n- if (dl_type == htons(ETH_TYPE_IPV6)) {\n- entry->key.src.addr.ipv6 = serverIp.ipv6;\n- entry->key.dst.addr.ipv6 = clientIp.ipv6;\n- } else {\n- entry->key.src.addr.ipv4 = serverIp.ipv4;\n- entry->key.dst.addr.ipv4 = clientIp.ipv4;\n- }\n-\n- UINT32 hash = OvsExtractCtRelatedKeyHash(&entry->key);\n- NdisAcquireRWLockWrite(ovsCtRelatedLockObj, &lockState, 0);\n- InsertHeadList(&ovsCtRelatedTable[hash & CT_HASH_TABLE_MASK],\n- &entry->link);\n- NdisInterlockedIncrement((PLONG)&ctTotalRelatedEntries);\n- NdisReleaseRWLock(ovsCtRelatedLockObj, &lockState);\n-\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-static __inline NDIS_STATUS\n-OvsCtRelatedFlush()\n-{\n- PLIST_ENTRY link, next;\n- POVS_CT_REL_ENTRY entry;\n- LOCK_STATE_EX lockState;\n-\n- if (ctTotalRelatedEntries) {\n- NdisAcquireRWLockWrite(ovsCtRelatedLockObj, &lockState, 0);\n- for (int i = 0; i < CT_HASH_TABLE_SIZE; i++) {\n- LIST_FORALL_SAFE(&ovsCtRelatedTable[i], link, next) {\n- entry = CONTAINING_RECORD(link, OVS_CT_REL_ENTRY, link);\n- OvsCtRelatedEntryDelete(entry);\n- }\n- }\n- NdisReleaseRWLock(ovsCtRelatedLockObj, &lockState);\n- }\n-\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-/* XXX - Create a wrapper for managing Tables used by Connection Trackers */\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsCtRelatedEntryCleaner\n- * Runs periodically and cleans up the related connections tracker\n- *----------------------------------------------------------------------------\n- */\n-VOID\n-OvsCtRelatedEntryCleaner(PVOID data)\n-{\n- POVS_CT_THREAD_CTX context = (POVS_CT_THREAD_CTX)data;\n- PLIST_ENTRY link, next;\n- POVS_CT_REL_ENTRY entry;\n- LOCK_STATE_EX lockState;\n- BOOLEAN success = TRUE;\n-\n- while (success) {\n- if (ovsCtRelatedLockObj == NULL) {\n- /* Lock has been freed by 'OvsCleanupCtRelated()' */\n- break;\n- }\n-\n- if (context->exit) {\n- break;\n- }\n-\n- /* Set the timeout for the thread and cleanup */\n- UINT64 currentTime, threadSleepTimeout;\n- NdisGetCurrentSystemTime((LARGE_INTEGER *)¤tTime);\n- threadSleepTimeout = currentTime + CT_CLEANUP_INTERVAL;\n-\n- if (ctTotalRelatedEntries) {\n- NdisAcquireRWLockWrite(ovsCtRelatedLockObj, &lockState, 0);\n- for (int i = 0; i < CT_HASH_TABLE_SIZE; i++) {\n- LIST_FORALL_SAFE(&ovsCtRelatedTable[i], link, next) {\n- entry = CONTAINING_RECORD(link, OVS_CT_REL_ENTRY, link);\n- if (entry->expiration < currentTime) {\n- OvsCtRelatedEntryDelete(entry);\n- }\n- }\n- }\n- NdisReleaseRWLock(ovsCtRelatedLockObj, &lockState);\n- }\n- KeWaitForSingleObject(&context->event, Executive, KernelMode,\n- FALSE, (LARGE_INTEGER *)&threadSleepTimeout);\n- }\n-\n- PsTerminateSystemThread(STATUS_SUCCESS);\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsInitCtRelated\n- * Initialize the components used by Related Connections Tracker\n- *----------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsInitCtRelated(POVS_SWITCH_CONTEXT context)\n-{\n- NTSTATUS status;\n- HANDLE threadHandle = NULL;\n- ctTotalRelatedEntries = 0;\n-\n- /* Init the sync-lock */\n- ovsCtRelatedLockObj = NdisAllocateRWLock(context->NdisFilterHandle);\n- if (ovsCtRelatedLockObj == NULL) {\n- return STATUS_INSUFFICIENT_RESOURCES;\n- }\n-\n- /* Init the Hash Buffer */\n- ovsCtRelatedTable = OvsAllocateMemoryWithTag(sizeof(LIST_ENTRY)\n- * CT_HASH_TABLE_SIZE,\n- OVS_CT_POOL_TAG);\n- if (ovsCtRelatedTable == NULL) {\n- NdisFreeRWLock(ovsCtRelatedLockObj);\n- ovsCtRelatedLockObj = NULL;\n- return STATUS_INSUFFICIENT_RESOURCES;\n- }\n-\n- for (int i = 0; i < CT_HASH_TABLE_SIZE; i++) {\n- InitializeListHead(&ovsCtRelatedTable[i]);\n- }\n-\n- /* Init CT Cleaner Thread */\n- KeInitializeEvent(&ctRelThreadCtx.event, NotificationEvent, FALSE);\n- status = PsCreateSystemThread(&threadHandle, SYNCHRONIZE, NULL, NULL,\n- NULL, OvsCtRelatedEntryCleaner,\n- &ctRelThreadCtx);\n-\n- if (status != STATUS_SUCCESS) {\n- NdisFreeRWLock(ovsCtRelatedLockObj);\n- ovsCtRelatedLockObj = NULL;\n-\n- OvsFreeMemoryWithTag(ovsCtRelatedTable, OVS_CT_POOL_TAG);\n- ovsCtRelatedTable = NULL;\n-\n- return status;\n- }\n-\n- ObReferenceObjectByHandle(threadHandle, SYNCHRONIZE, NULL, KernelMode,\n- &ctRelThreadCtx.threadObject, NULL);\n- ZwClose(threadHandle);\n- threadHandle = NULL;\n- return STATUS_SUCCESS;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsCleanupCtRelated\n- * Cleanup memory and thread that were spawned for tracking related entry\n- *----------------------------------------------------------------------------\n- */\n-VOID\n-OvsCleanupCtRelated(VOID)\n-{\n- LOCK_STATE_EX lockState;\n- NdisAcquireRWLockWrite(ovsCtRelatedLockObj, &lockState, 0);\n- ctRelThreadCtx.exit = 1;\n- KeSetEvent(&ctRelThreadCtx.event, 0, FALSE);\n- NdisReleaseRWLock(ovsCtRelatedLockObj, &lockState);\n-\n- KeWaitForSingleObject(ctRelThreadCtx.threadObject, Executive,\n- KernelMode, FALSE, NULL);\n- ObDereferenceObject(ctRelThreadCtx.threadObject);\n-\n- if (ovsCtRelatedTable) {\n- OvsCtRelatedFlush();\n- OvsFreeMemoryWithTag(ovsCtRelatedTable, OVS_CT_POOL_TAG);\n- ovsCtRelatedTable = NULL;\n- }\n-\n- NdisFreeRWLock(ovsCtRelatedLockObj);\n- ovsCtRelatedLockObj = NULL;\n-}\ndiff --git a/datapath-windows/ovsext/Conntrack-tcp.c b/datapath-windows/ovsext/Conntrack-tcp.c\ndeleted file mode 100644\nindex 77370531c..000000000\n--- a/datapath-windows/ovsext/Conntrack-tcp.c\n+++ /dev/null\n@@ -1,632 +0,0 @@\n-/*-\n- * Copyright (c) 2001 Daniel Hartmeier\n- * Copyright (c) 2002 - 2008 Henning Brauer\n- * Copyright (c) 2012 Gleb Smirnoff <glebius@FreeBSD.org>\n- * Copyright (c) 2015, 2016 VMware, Inc.\n- * All rights reserved.\n- *\n- * Redistribution and use in source and binary forms, with or without\n- * modification, are permitted provided that the following conditions\n- * are met:\n- *\n- * - Redistributions of source code must retain the above copyright\n- * notice, this list of conditions and the following disclaimer.\n- * - Redistributions in binary form must reproduce the above\n- * copyright notice, this list of conditions and the following\n- * disclaimer in the documentation and/or other materials provided\n- * with the distribution.\n- *\n- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n- * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS\n- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\n- * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\n- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\n- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\n- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n- * POSSIBILITY OF SUCH DAMAGE.\n- *\n- * Effort sponsored in part by the Defense Advanced Research Projects\n- * Agency (DARPA) and Air Force Research Laboratory, Air Force\n- * Materiel Command, USAF, under agreement number F30602-01-2-0537.\n- *\n- * $OpenBSD: pf.c,v 1.634 2009/02/27 12:37:45 henning Exp $\n- */\n-\n-#include \"Conntrack.h\"\n-#include \"NetProto.h\"\n-#include \"PacketParser.h\"\n-#include <stddef.h>\n-\n-struct tcp_peer {\n- enum ct_dpif_tcp_state state;\n- uint32_t seqlo; /* Max sequence number sent */\n- uint32_t seqhi; /* Max the other end ACKd + win */\n- uint16_t max_win;/* largest window (pre scaling) */\n- uint8_t wscale; /* window scaling factor */\n-};\n-\n-struct conn_tcp {\n- struct OVS_CT_ENTRY up;\n- struct tcp_peer peer[2];\n-};\n-C_ASSERT(offsetof(struct conn_tcp, up) == 0);\n-\n-enum {\n- TCPOPT_EOL,\n- TCPOPT_NOP,\n- TCPOPT_WINDOW = 3,\n-};\n-\n-/* TCP sequence numbers are 32 bit integers operated\n- * on with modular arithmetic. These macros can be\n- * used to compare such integers. */\n-#define SEQ_LT(a,b) ((int)((a)-(b)) < 0)\n-#define SEQ_LEQ(a,b) ((int)((a)-(b)) <= 0)\n-#define SEQ_GT(a,b) ((int)((a)-(b)) > 0)\n-#define SEQ_GEQ(a,b) ((int)((a)-(b)) >= 0)\n-\n-#define SEQ_MIN(a, b) ((SEQ_LT(a, b)) ? (a) : (b))\n-#define SEQ_MAX(a, b) ((SEQ_GT(a, b)) ? (a) : (b))\n-\n-#define TCP_FIN 0x001\n-#define TCP_SYN 0x002\n-#define TCP_RST 0x004\n-#define TCP_PSH 0x008\n-#define TCP_ACK 0x010\n-#define TCP_URG 0x020\n-#define TCP_ECE 0x040\n-#define TCP_CWR 0x080\n-#define TCP_NS 0x100\n-\n-#define CT_DPIF_TCP_FLAGS \\\n- CT_DPIF_TCP_FLAG(WINDOW_SCALE) \\\n- CT_DPIF_TCP_FLAG(SACK_PERM) \\\n- CT_DPIF_TCP_FLAG(CLOSE_INIT) \\\n- CT_DPIF_TCP_FLAG(BE_LIBERAL) \\\n- CT_DPIF_TCP_FLAG(DATA_UNACKNOWLEDGED) \\\n- CT_DPIF_TCP_FLAG(MAXACK_SET) \\\n-\n-enum ct_dpif_tcp_flags_count_ {\n-#define CT_DPIF_TCP_FLAG(FLAG) FLAG##_COUNT_,\n- CT_DPIF_TCP_FLAGS\n-#undef CT_DPIF_TCP_FLAG\n-};\n-\n-enum ct_dpif_tcp_flags {\n-#define CT_DPIF_TCP_FLAG(FLAG) CT_DPIF_TCPF_##FLAG = (1 << \\\n- FLAG##_COUNT_),\n- CT_DPIF_TCP_FLAGS\n-#undef CT_DPIF_TCP_FLAG\n-};\n-\n-\n-#define CT_DPIF_TCP_STATES \\\n- CT_DPIF_TCP_STATE(CLOSED) \\\n- CT_DPIF_TCP_STATE(LISTEN) \\\n- CT_DPIF_TCP_STATE(SYN_SENT) \\\n- CT_DPIF_TCP_STATE(SYN_RECV) \\\n- CT_DPIF_TCP_STATE(ESTABLISHED) \\\n- CT_DPIF_TCP_STATE(CLOSE_WAIT) \\\n- CT_DPIF_TCP_STATE(FIN_WAIT_1) \\\n- CT_DPIF_TCP_STATE(CLOSING) \\\n- CT_DPIF_TCP_STATE(LAST_ACK) \\\n- CT_DPIF_TCP_STATE(FIN_WAIT_2) \\\n- CT_DPIF_TCP_STATE(TIME_WAIT)\n-\n-enum ct_dpif_tcp_state {\n-#define CT_DPIF_TCP_STATE(STATE) CT_DPIF_TCPS_##STATE,\n- CT_DPIF_TCP_STATES\n-#undef CT_DPIF_TCP_STATE\n-};\n-\n-#define TCP_MAX_WSCALE 14\n-#define CT_WSCALE_FLAG 0x80\n-#define CT_WSCALE_UNKNOWN 0x40\n-#define CT_WSCALE_MASK 0xf\n-\n-/* pf does this in in pf_normalize_tcp(), and it is called only if scrub\n- * is enabled. We're not scrubbing, but this check seems reasonable. */\n-static __inline BOOLEAN\n-OvsCtInvalidTcpFlags(uint16_t flags)\n-{\n- if (flags & TCP_SYN) {\n- if (flags & TCP_RST || flags & TCP_FIN) {\n- return TRUE;\n- }\n- } else {\n- /* Illegal packet */\n- if (!(flags & (TCP_ACK|TCP_RST))) {\n- return TRUE;\n- }\n- }\n-\n- if (!(flags & TCP_ACK)) {\n- /* These flags are only valid if ACK is set */\n- if ((flags & TCP_FIN) || (flags & TCP_PSH) || (flags & TCP_URG)) {\n- return TRUE;\n- }\n- }\n-\n- return FALSE;\n-}\n-\n-static __inline uint8_t\n-OvsTcpGetWscale(const TCPHdr *tcp)\n-{\n- int len = tcp->doff * 4 - sizeof *tcp;\n- const uint8_t *opt = (const uint8_t *)(tcp + 1);\n- uint8_t wscale = 0;\n- uint8_t optlen;\n-\n- while (len >= 3) {\n- switch (*opt) {\n- case TCPOPT_EOL:\n- return wscale;\n- case TCPOPT_NOP:\n- opt++;\n- len--;\n- break;\n- case TCPOPT_WINDOW:\n- wscale = MIN(opt[2], TCP_MAX_WSCALE);\n- wscale |= CT_WSCALE_FLAG;\n- /* fall through */\n- default:\n- optlen = opt[1];\n- if (optlen < 2) {\n- optlen = 2;\n- }\n- len -= optlen;\n- opt += optlen;\n- }\n- }\n-\n- return wscale;\n-}\n-\n-static __inline struct conn_tcp*\n-OvsCastConntrackEntryToTcpEntry(OVS_CT_ENTRY* conn)\n-{\n- return CONTAINER_OF(conn, struct conn_tcp, up);\n-}\n-\n-enum CT_UPDATE_RES\n-OvsConntrackUpdateTcpEntry(OVS_CT_ENTRY* conn_,\n- const TCPHdr *tcp,\n- BOOLEAN reply,\n- UINT64 now,\n- UINT32 tcpPayloadLen)\n-{\n- struct conn_tcp *conn = OvsCastConntrackEntryToTcpEntry(conn_);\n- /* The peer that sent 'pkt' */\n- struct tcp_peer *src = &conn->peer[reply ? 1 : 0];\n- /* The peer that should receive 'pkt' */\n- struct tcp_peer *dst = &conn->peer[reply ? 0 : 1];\n- uint8_t sws = 0, dws = 0;\n- UINT16 tcp_flags = ntohs(tcp->flags);\n- uint16_t win = ntohs(tcp->window);\n- uint32_t ack, end, seq, orig_seq;\n- int ackskew;\n-\n- if (OvsCtInvalidTcpFlags(tcp_flags)) {\n- return CT_UPDATE_INVALID;\n- }\n-\n- if ((tcp_flags & (TCP_SYN|TCP_ACK)) == TCP_SYN) {\n- if (dst->state >= CT_DPIF_TCPS_FIN_WAIT_2\n- && src->state >= CT_DPIF_TCPS_FIN_WAIT_2) {\n- src->state = dst->state = CT_DPIF_TCPS_CLOSED;\n- return CT_UPDATE_NEW;\n- } else if (src->state <= CT_DPIF_TCPS_SYN_SENT) {\n- src->state = CT_DPIF_TCPS_SYN_SENT;\n- OvsConntrackUpdateExpiration(&conn->up, now,\n- 30 * CT_INTERVAL_SEC);\n- return CT_UPDATE_VALID_NEW;\n- }\n- }\n-\n- if (src->wscale & CT_WSCALE_FLAG\n- && dst->wscale & CT_WSCALE_FLAG\n- && !(tcp_flags & TCP_SYN)) {\n-\n- sws = src->wscale & CT_WSCALE_MASK;\n- dws = dst->wscale & CT_WSCALE_MASK;\n-\n- } else if (src->wscale & CT_WSCALE_UNKNOWN\n- && dst->wscale & CT_WSCALE_UNKNOWN\n- && !(tcp_flags & TCP_SYN)) {\n-\n- sws = TCP_MAX_WSCALE;\n- dws = TCP_MAX_WSCALE;\n- }\n-\n- /*\n- * Sequence tracking algorithm from Guido van Rooij's paper:\n- * http://www.madison-gurkha.com/publications/tcp_filtering/\n- * tcp_filtering.ps\n- */\n-\n- orig_seq = seq = ntohl(tcp->seq);\n- if (src->state < CT_DPIF_TCPS_SYN_SENT) {\n- /* First packet from this end. Set its state */\n-\n- ack = ntohl(tcp->ack_seq);\n-\n- end = seq + tcpPayloadLen;\n- if (tcp_flags & TCP_SYN) {\n- end++;\n- if (dst->wscale & CT_WSCALE_FLAG) {\n- src->wscale = OvsTcpGetWscale(tcp);\n- if (src->wscale & CT_WSCALE_FLAG) {\n- /* Remove scale factor from initial window */\n- sws = src->wscale & CT_WSCALE_MASK;\n- win = DIV_ROUND_UP((uint32_t) win, 1 << sws);\n- dws = dst->wscale & CT_WSCALE_MASK;\n- } else {\n- /* fixup other window */\n- dst->max_win <<= dst->wscale & CT_WSCALE_MASK;\n- /* in case of a retrans SYN|ACK */\n- dst->wscale = 0;\n- }\n- }\n- }\n- if (tcp_flags & TCP_FIN) {\n- end++;\n- }\n-\n- src->seqlo = seq;\n- src->state = CT_DPIF_TCPS_SYN_SENT;\n- /*\n- * May need to slide the window (seqhi may have been set by\n- * the crappy stack check or if we picked up the connection\n- * after establishment)\n- */\n- if (src->seqhi == 1 ||\n- SEQ_GEQ(end + MAX(1, dst->max_win << dws), src->seqhi)) {\n- src->seqhi = end + MAX(1, dst->max_win << dws);\n- }\n- if (win > src->max_win) {\n- src->max_win = win;\n- }\n-\n- } else {\n- ack = ntohl(tcp->ack_seq);\n- end = seq + tcpPayloadLen;\n- if (tcp_flags & TCP_SYN) {\n- end++;\n- }\n- if (tcp_flags & TCP_FIN) {\n- end++;\n- }\n- }\n-\n- if ((tcp_flags & TCP_ACK) == 0) {\n- /* Let it pass through the ack skew check */\n- ack = dst->seqlo;\n- } else if ((ack == 0\n- && (tcp_flags & (TCP_ACK|TCP_RST)) == (TCP_ACK|TCP_RST))\n- /* broken tcp stacks do not set ack */) {\n- /* Many stacks (ours included) will set the ACK number in an\n- * FIN|ACK if the SYN times out -- no sequence to ACK. */\n- ack = dst->seqlo;\n- }\n-\n- if (seq == end) {\n- /* Ease sequencing restrictions on no data packets */\n- seq = src->seqlo;\n- end = seq;\n- }\n-\n- ackskew = dst->seqlo - ack;\n-#define MAXACKWINDOW (0xffff + 1500) /* 1500 is an arbitrary fudge factor */\n- if (SEQ_GEQ(src->seqhi, end)\n- /* Last octet inside other's window space */\n- && SEQ_GEQ(seq, src->seqlo - (dst->max_win << dws))\n- /* Retrans: not more than one window back */\n- && (ackskew >= -MAXACKWINDOW)\n- /* Acking not more than one reassembled fragment backwards */\n- && (ackskew <= (MAXACKWINDOW << sws))\n- /* Acking not more than one window forward */\n- && ((tcp_flags & TCP_RST) == 0 || orig_seq == src->seqlo\n- || (orig_seq == src->seqlo + 1)\n- || (orig_seq + 1 == src->seqlo))) {\n- /* Require an exact/+1 sequence match on resets when possible */\n-\n- /* update max window */\n- if (src->max_win < win) {\n- src->max_win = win;\n- }\n- /* synchronize sequencing */\n- if (SEQ_GT(end, src->seqlo)) {\n- src->seqlo = end;\n- }\n- /* slide the window of what the other end can send */\n- if (SEQ_GEQ(ack + (win << sws), dst->seqhi)) {\n- dst->seqhi = ack + MAX((win << sws), 1);\n- }\n-\n- /* update states */\n- if (tcp_flags & TCP_SYN && src->state < CT_DPIF_TCPS_SYN_SENT) {\n- src->state = CT_DPIF_TCPS_SYN_SENT;\n- }\n- if (tcp_flags & TCP_FIN && src->state < CT_DPIF_TCPS_CLOSING) {\n- src->state = CT_DPIF_TCPS_CLOSING;\n- }\n- if (tcp_flags & TCP_ACK) {\n- if (dst->state == CT_DPIF_TCPS_SYN_SENT) {\n- dst->state = CT_DPIF_TCPS_ESTABLISHED;\n- } else if (dst->state == CT_DPIF_TCPS_CLOSING) {\n- dst->state = CT_DPIF_TCPS_FIN_WAIT_2;\n- }\n- }\n- if (tcp_flags & TCP_RST) {\n- src->state = dst->state = CT_DPIF_TCPS_TIME_WAIT;\n- }\n-\n- if (src->state >= CT_DPIF_TCPS_FIN_WAIT_2\n- && dst->state >= CT_DPIF_TCPS_FIN_WAIT_2) {\n- OvsConntrackUpdateExpiration(&conn->up, now,\n- 30 * CT_INTERVAL_SEC);\n- } else if (src->state >= CT_DPIF_TCPS_CLOSING\n- && dst->state >= CT_DPIF_TCPS_CLOSING) {\n- OvsConntrackUpdateExpiration(&conn->up, now,\n- 45 * CT_INTERVAL_SEC);\n- } else if (src->state < CT_DPIF_TCPS_ESTABLISHED\n- || dst->state < CT_DPIF_TCPS_ESTABLISHED) {\n- OvsConntrackUpdateExpiration(&conn->up, now,\n- 30 * CT_INTERVAL_SEC);\n- } else if (src->state >= CT_DPIF_TCPS_CLOSING\n- || dst->state >= CT_DPIF_TCPS_CLOSING) {\n- OvsConntrackUpdateExpiration(&conn->up, now,\n- 15 * 60 * CT_INTERVAL_SEC);\n- } else {\n- OvsConntrackUpdateExpiration(&conn->up, now,\n- 24 * 60 * 60 * CT_INTERVAL_SEC);\n- }\n- } else if ((dst->state < CT_DPIF_TCPS_SYN_SENT\n- || dst->state >= CT_DPIF_TCPS_FIN_WAIT_2\n- || src->state >= CT_DPIF_TCPS_FIN_WAIT_2)\n- && SEQ_GEQ(src->seqhi + MAXACKWINDOW, end)\n- /* Within a window forward of the originating packet */\n- && SEQ_GEQ(seq, src->seqlo - MAXACKWINDOW)) {\n- /* Within a window backward of the originating packet */\n-\n- /*\n- * This currently handles three situations:\n- * 1) Stupid stacks will shotgun SYNs before their peer\n- * replies.\n- * 2) When PF catches an already established stream (the\n- * firewall rebooted, the state table was flushed, routes\n- * changed...)\n- * 3) Packets get funky immediately after the connection\n- * closes (this should catch Solaris spurious ACK|FINs\n- * that web servers like to spew after a close)\n- *\n- * This must be a little more careful than the above code\n- * since packet floods will also be caught here. We don't\n- * update the TTL here to mitigate the damage of a packet\n- * flood and so the same code can handle awkward establishment\n- * and a loosened connection close.\n- * In the establishment case, a correct peer response will\n- * validate the connection, go through the normal state code\n- * and keep updating the state TTL.\n- */\n-\n- /* update max window */\n- if (src->max_win < win) {\n- src->max_win = win;\n- }\n- /* synchronize sequencing */\n- if (SEQ_GT(end, src->seqlo)) {\n- src->seqlo = end;\n- }\n- /* slide the window of what the other end can send */\n- if (SEQ_GEQ(ack + (win << sws), dst->seqhi)) {\n- dst->seqhi = ack + MAX((win << sws), 1);\n- }\n-\n- /*\n- * Cannot set dst->seqhi here since this could be a shotgunned\n- * SYN and not an already established connection.\n- */\n-\n- if (tcp_flags & TCP_FIN && src->state < CT_DPIF_TCPS_CLOSING) {\n- src->state = CT_DPIF_TCPS_CLOSING;\n- }\n-\n- if (tcp_flags & TCP_RST) {\n- src->state = dst->state = CT_DPIF_TCPS_TIME_WAIT;\n- }\n- } else {\n- return CT_UPDATE_INVALID;\n- }\n-\n- return CT_UPDATE_VALID;\n-}\n-\n-BOOLEAN\n-OvsConntrackValidateTcpPacket(const TCPHdr *tcp)\n-{\n- if (!tcp) {\n- OVS_LOG_TRACE(\"Invalid TCP packet detected, header cannot be NULL\");\n- return FALSE;\n- }\n-\n- UINT16 tcp_flags = ntohs(tcp->flags);\n-\n- if (OvsCtInvalidTcpFlags(tcp_flags)) {\n- OVS_LOG_TRACE(\"Invalid TCP packet detected, tcp_flags %hu\", tcp_flags);\n- return FALSE;\n- }\n-\n- /* A syn+ack is not allowed to create a connection. We want to allow\n- * totally new connections (syn) or already established, not partially\n- * open (syn+ack). */\n- if ((tcp_flags & TCP_SYN) && (tcp_flags & TCP_ACK)) {\n- OVS_LOG_TRACE(\"Invalid TCP packet detected, SYN+ACK flags not allowed,\"\n- \"tcp_flags %hu\", tcp_flags);\n- return FALSE;\n- }\n-\n- return TRUE;\n-}\n-\n-OVS_CT_ENTRY *\n-OvsConntrackCreateTcpEntry(const TCPHdr *tcp,\n- UINT64 now,\n- UINT32 tcpPayloadLen)\n-{\n- struct conn_tcp* newconn;\n- struct tcp_peer *src, *dst;\n-\n- newconn = OvsAllocateMemoryWithTag(sizeof(struct conn_tcp),\n- OVS_CT_POOL_TAG);\n- if (!newconn) {\n- return NULL;\n- }\n-\n- newconn->up = (OVS_CT_ENTRY) {0};\n- src = &newconn->peer[0];\n- dst = &newconn->peer[1];\n-\n- src->seqlo = ntohl(tcp->seq);\n- src->seqhi = src->seqlo + tcpPayloadLen + 1;\n-\n- if (tcp->flags & TCP_SYN) {\n- src->seqhi++;\n- src->wscale = OvsTcpGetWscale(tcp);\n- } else {\n- src->wscale = CT_WSCALE_UNKNOWN;\n- dst->wscale = CT_WSCALE_UNKNOWN;\n- }\n- src->max_win = MAX(ntohs(tcp->window), 1);\n- if (src->wscale & CT_WSCALE_MASK) {\n- /* Remove scale factor from initial window */\n- uint8_t sws = src->wscale & CT_WSCALE_MASK;\n- src->max_win = DIV_ROUND_UP((uint32_t) src->max_win, 1 << sws);\n- }\n- if (tcp->flags & TCP_FIN) {\n- src->seqhi++;\n- }\n- dst->seqhi = 1;\n- dst->max_win = 1;\n- src->state = CT_DPIF_TCPS_SYN_SENT;\n- dst->state = CT_DPIF_TCPS_CLOSED;\n-\n- OvsConntrackUpdateExpiration(&newconn->up, now, CT_ENTRY_TIMEOUT);\n-\n- return &newconn->up;\n-}\n-\n-static __inline uint8_t\n-OvsCtTcpPeerToProtoInfoFlags(const struct tcp_peer *peer)\n-{\n- uint8_t res = 0;\n-\n- if (peer->wscale & CT_WSCALE_FLAG) {\n- res |= CT_DPIF_TCPF_WINDOW_SCALE;\n- }\n-\n- if (peer->wscale & CT_WSCALE_UNKNOWN) {\n- res |= CT_DPIF_TCPF_BE_LIBERAL;\n- }\n-\n- return res;\n-}\n-\n-NDIS_STATUS\n-OvsCtMapTcpProtoInfoToNl(PNL_BUFFER nlBuf, OVS_CT_ENTRY *conn_)\n-{\n- struct conn_tcp *conn = OvsCastConntrackEntryToTcpEntry(conn_);\n- NDIS_STATUS status = NDIS_STATUS_SUCCESS;\n- UINT32 offset = 0;\n-\n- offset = NlMsgStartNested(nlBuf, CTA_PROTOINFO_TCP);\n- if (!offset) {\n- return NDIS_STATUS_FAILURE;\n- }\n-\n- if (!NlMsgPutTailU8(nlBuf, CTA_PROTOINFO_TCP_STATE,\n- conn->peer[0].state)) {\n- status = NDIS_STATUS_FAILURE;\n- goto done;\n- }\n- if (!NlMsgPutTailU8(nlBuf, CTA_PROTOINFO_TCP_WSCALE_ORIGINAL,\n- (conn->peer[0].wscale & CT_WSCALE_MASK))) {\n- status = NDIS_STATUS_FAILURE;\n- goto done;\n- }\n- if (!NlMsgPutTailU8(nlBuf, CTA_PROTOINFO_TCP_WSCALE_REPLY,\n- (conn->peer[1].wscale & CT_WSCALE_MASK))) {\n- status = NDIS_STATUS_FAILURE;\n- goto done;\n- }\n- if (!NlMsgPutTailU16(nlBuf, CTA_PROTOINFO_TCP_FLAGS_ORIGINAL,\n- OvsCtTcpPeerToProtoInfoFlags(&conn->peer[0]))) {\n- status = NDIS_STATUS_FAILURE;\n- goto done;\n- }\n- if (!NlMsgPutTailU16(nlBuf, CTA_PROTOINFO_TCP_FLAGS_REPLY,\n- OvsCtTcpPeerToProtoInfoFlags(&conn->peer[1]))) {\n- status = NDIS_STATUS_FAILURE;\n- goto done;\n- }\n-\n-done:\n- NlMsgEndNested(nlBuf, offset);\n- return status;\n-}\n-\n-NDIS_STATUS\n-OvsCtHandleTftp(PNET_BUFFER_LIST curNbl, OvsFlowKey *key,\n- OVS_PACKET_HDR_INFO *layers, UINT64 currentTime,\n- POVS_CT_ENTRY entry)\n-{\n- UDPHdr udpStorage;\n- const UDPHdr *udp = NULL;\n- struct ct_addr serverIp;\n- struct ct_addr clientIp;\n- NDIS_STATUS status = NDIS_STATUS_SUCCESS;\n-\n- udp = OvsGetUdp(curNbl, layers->l4Offset, &udpStorage);\n- if (!udp) {\n- return NDIS_STATUS_INVALID_PACKET;\n- }\n-\n- RtlZeroMemory(&serverIp, sizeof(serverIp));\n- RtlZeroMemory(&clientIp, sizeof(clientIp));\n-\n- if (OvsCtRelatedLookup(entry->key, currentTime)) {\n- return NDIS_STATUS_SUCCESS;\n- }\n-\n- if (layers->isIPv4) {\n- serverIp.ipv4 = key->ipKey.nwDst;\n- clientIp.ipv4 = key->ipKey.nwSrc;\n- status = OvsCtRelatedEntryCreate(key->ipKey.nwProto,\n- key->l2.dlType,\n- serverIp,\n- clientIp,\n- 0,\n- udp->source,\n- currentTime,\n- entry);\n- } else {\n- serverIp.ipv6 = key->ipv6Key.ipv6Dst;\n- clientIp.ipv6 = key->ipv6Key.ipv6Src;\n- status = OvsCtRelatedEntryCreate(key->ipv6Key.nwProto,\n- key->l2.dlType,\n- serverIp,\n- clientIp,\n- 0,\n- udp->source,\n- currentTime,\n- entry);\n- }\n-\n- return status;\n-}\n-\ndiff --git a/datapath-windows/ovsext/Conntrack.c b/datapath-windows/ovsext/Conntrack.c\ndeleted file mode 100644\nindex 39ba5cc10..000000000\n--- a/datapath-windows/ovsext/Conntrack.c\n+++ /dev/null\n@@ -1,2351 +0,0 @@\n-/*\n- * Copyright (c) 2015, 2016 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#include \"Conntrack.h\"\n-#include \"IpFragment.h\"\n-#include \"Ip6Fragment.h\"\n-#include \"Jhash.h\"\n-#include \"PacketParser.h\"\n-#include \"Event.h\"\n-#include \"Conntrack-nat.h\"\n-#include \"IpHelper.h\"\n-\n-#pragma warning(push)\n-#pragma warning(disable:4311)\n-\n-#define WINDOWS_TICK 10000000\n-#define SEC_TO_UNIX_EPOCH 11644473600LL\n-#define SEC_TO_NANOSEC 1000000000LL\n-#define CT_MAX_ZONE (UINT16_MAX + 1)\n-\n-KSTART_ROUTINE OvsConntrackEntryCleaner;\n-static PLIST_ENTRY ovsConntrackTable;\n-static OVS_CT_THREAD_CTX ctThreadCtx;\n-static PNDIS_RW_LOCK_EX *ovsCtBucketLock = NULL;\n-static NDIS_SPIN_LOCK ovsCtZoneLock;\n-static POVS_CT_ZONE_INFO zoneInfo = NULL;\n-extern POVS_SWITCH_CONTEXT gOvsSwitchContext;\n-static ULONG ctTotalEntries;\n-static ULONG defaultCtLimit;\n-\n-static __inline OvsCtFlush(UINT16 zone, struct ovs_key_ct_tuple_ipv4 *tuple);\n-static __inline NDIS_STATUS\n-MapNlToCtTuple(POVS_MESSAGE msgIn, PNL_ATTR attr,\n- struct ovs_key_ct_tuple_ipv4 *ct_tuple);\n-/*\n- *----------------------------------------------------------------------------\n- * OvsInitConntrack\n- * Initialize the components used by Connection Tracking\n- *----------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsInitConntrack(POVS_SWITCH_CONTEXT context)\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n- HANDLE threadHandle = NULL;\n- ctTotalEntries = 0;\n- UINT32 numBucketLocks = CT_HASH_TABLE_SIZE;\n-\n- /* Init the Hash Buffer */\n- ovsConntrackTable = OvsAllocateMemoryWithTag(sizeof(LIST_ENTRY)\n- * CT_HASH_TABLE_SIZE,\n- OVS_CT_POOL_TAG);\n- if (ovsConntrackTable == NULL) {\n- return STATUS_INSUFFICIENT_RESOURCES;\n- }\n-\n- ovsCtBucketLock = OvsAllocateMemoryWithTag(sizeof(PNDIS_RW_LOCK_EX)\n- * CT_HASH_TABLE_SIZE,\n- OVS_CT_POOL_TAG);\n- if (ovsCtBucketLock == NULL) {\n- status = STATUS_INSUFFICIENT_RESOURCES;\n- goto freeTable;\n- }\n-\n- for (UINT32 i = 0; i < CT_HASH_TABLE_SIZE; i++) {\n- InitializeListHead(&ovsConntrackTable[i]);\n- ovsCtBucketLock[i] = NdisAllocateRWLock(context->NdisFilterHandle);\n- if (ovsCtBucketLock[i] == NULL) {\n- status = STATUS_INSUFFICIENT_RESOURCES;\n- numBucketLocks = i;\n- goto freeBucketLock;\n- }\n- }\n-\n- /* Init CT Cleaner Thread */\n- KeInitializeEvent(&ctThreadCtx.event, NotificationEvent, FALSE);\n- status = PsCreateSystemThread(&threadHandle, SYNCHRONIZE, NULL, NULL,\n- NULL, OvsConntrackEntryCleaner,\n- &ctThreadCtx);\n-\n- if (status != STATUS_SUCCESS) {\n- goto freeBucketLock;\n- }\n-\n- ObReferenceObjectByHandle(threadHandle, SYNCHRONIZE, NULL, KernelMode,\n- &ctThreadCtx.threadObject, NULL);\n- ZwClose(threadHandle);\n- threadHandle = NULL;\n-\n- zoneInfo = OvsAllocateMemoryWithTag(sizeof(OVS_CT_ZONE_INFO) *\n- CT_MAX_ZONE, OVS_CT_POOL_TAG);\n- if (zoneInfo == NULL) {\n- status = STATUS_INSUFFICIENT_RESOURCES;\n- goto freeBucketLock;\n- }\n-\n- NdisAllocateSpinLock(&ovsCtZoneLock);\n- defaultCtLimit = CT_MAX_ENTRIES;\n- for (UINT32 i = 0; i < CT_MAX_ZONE; i++) {\n- zoneInfo[i].entries = 0;\n- zoneInfo[i].limit = defaultCtLimit;\n- }\n-\n- status = OvsNatInit();\n-\n- if (status != STATUS_SUCCESS) {\n- OvsCleanupConntrack();\n- }\n- return STATUS_SUCCESS;\n-\n-freeBucketLock:\n- for (UINT32 i = 0; i < numBucketLocks; i++) {\n- if (ovsCtBucketLock[i] != NULL) {\n- NdisFreeRWLock(ovsCtBucketLock[i]);\n- }\n- }\n- OvsFreeMemoryWithTag(ovsCtBucketLock, OVS_CT_POOL_TAG);\n- ovsCtBucketLock = NULL;\n-freeTable:\n- OvsFreeMemoryWithTag(ovsConntrackTable, OVS_CT_POOL_TAG);\n- ovsConntrackTable = NULL;\n- return status;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsCleanupConntrack\n- * Cleanup memory and thread that were spawned for Connection tracking\n- *----------------------------------------------------------------------------\n- */\n-VOID\n-OvsCleanupConntrack(VOID)\n-{\n- ctThreadCtx.exit = 1;\n- KeSetEvent(&ctThreadCtx.event, 0, FALSE);\n- KeWaitForSingleObject(ctThreadCtx.threadObject, Executive,\n- KernelMode, FALSE, NULL);\n- ObDereferenceObject(ctThreadCtx.threadObject);\n-\n- /* Force flush all entries before removing */\n- OvsCtFlush(0, NULL);\n-\n- if (ovsConntrackTable) {\n- OvsFreeMemoryWithTag(ovsConntrackTable, OVS_CT_POOL_TAG);\n- ovsConntrackTable = NULL;\n- }\n-\n- for (UINT32 i = 0; i < CT_HASH_TABLE_SIZE; i++) {\n- /* Disabling the uninitialized memory warning because it should\n- * always be initialized during OvsInitConntrack */\n-#pragma warning(suppress: 6001)\n- if (ovsCtBucketLock[i] != NULL) {\n- NdisFreeRWLock(ovsCtBucketLock[i]);\n- }\n- }\n- OvsFreeMemoryWithTag(ovsCtBucketLock, OVS_CT_POOL_TAG);\n- ovsCtBucketLock = NULL;\n- OvsNatCleanup();\n- NdisFreeSpinLock(&ovsCtZoneLock);\n- if (zoneInfo) {\n- OvsFreeMemoryWithTag(zoneInfo, OVS_CT_POOL_TAG);\n- }\n-}\n-\n-VOID\n-OvsCtSetZoneLimit(int zone, ULONG value) {\n- NdisAcquireSpinLock(&ovsCtZoneLock);\n- if (zone == -1) {\n- /* Set default limit for all zones. */\n- defaultCtLimit = value;\n- for (UINT32 i = 0; i < CT_MAX_ZONE; i++) {\n- zoneInfo[i].limit = value;\n- }\n- } else {\n- zoneInfo[(UINT16)zone].limit = value;\n- }\n- NdisReleaseSpinLock(&ovsCtZoneLock);\n-}\n-\n-static uint32_t\n-OvsCtEndpointHashAdd(uint32_t hash, const struct ct_endpoint *ep)\n-{\n- BUILD_ASSERT_DECL(sizeof *ep % 4 == 0);\n- return OvsJhashBytes((UINT32 *)ep, sizeof *ep, hash);\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsCtHashKey\n- * Compute hash using 5-tuple and zone.\n- *----------------------------------------------------------------------------\n- */\n-UINT32\n-OvsCtHashKey(const OVS_CT_KEY *key)\n-{\n- UINT32 hsrc, hdst, hash;\n- hsrc = ntohl(key->src.port);\n- hdst = ntohl(key->dst.port);\n- hsrc = OvsCtEndpointHashAdd(hsrc, &key->src);\n- hdst = OvsCtEndpointHashAdd(hdst, &key->dst);\n- hash = hsrc ^ hdst; /* TO identify reverse traffic */\n- hash = hash | (key->zone + key->nw_proto);\n- hash = OvsJhashWords((uint32_t*) &hash, 1, hash);\n- return hash;\n-}\n-\n-static __inline VOID\n-OvsCtKeyReverse(OVS_CT_KEY *key)\n-{\n- struct ct_endpoint tmp;\n- tmp = key->src;\n- key->src = key->dst;\n- key->dst = tmp;\n-}\n-\n-static __inline VOID\n-OvsCtUpdateFlowKey(struct OvsFlowKey *key,\n- UINT32 state,\n- UINT16 zone,\n- UINT32 mark,\n- struct ovs_key_ct_labels *labels)\n-{\n- key->ct.state = state | OVS_CS_F_TRACKED;\n- key->ct.zone = zone;\n- key->ct.mark = mark;\n- if (labels) {\n- NdisMoveMemory(&key->ct.labels, labels,\n- sizeof(struct ovs_key_ct_labels));\n- } else {\n- memset(&key->ct.labels, 0,\n- sizeof(struct ovs_key_ct_labels));\n- }\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsPostCtEventEntry\n- * Assumes ct entry lock is acquired\n- * XXX Refactor OvsPostCtEvent() as it does not require ct entry lock.\n- *----------------------------------------------------------------------------\n- */\n-static __inline VOID\n-OvsPostCtEventEntry(POVS_CT_ENTRY entry, UINT8 type)\n-{\n- OVS_CT_EVENT_ENTRY ctEventEntry = {0};\n- NdisMoveMemory(&ctEventEntry.entry, entry, sizeof(OVS_CT_ENTRY));\n- ctEventEntry.type = type;\n- OvsPostCtEvent(&ctEventEntry);\n-}\n-\n-static __inline VOID\n-OvsCtIncrementCounters(POVS_CT_ENTRY entry, BOOLEAN reply, PNET_BUFFER_LIST nbl)\n-{\n- NdisAcquireSpinLock(&(entry->lock));\n- if (reply) {\n- entry->rev_key.byteCount+= OvsPacketLenNBL(nbl);\n- entry->rev_key.packetCount++;\n- } else {\n- entry->key.byteCount += OvsPacketLenNBL(nbl);\n- entry->key.packetCount++;\n- }\n- NdisReleaseSpinLock(&(entry->lock));\n-}\n-\n-static __inline BOOLEAN\n-OvsCtAddEntry(POVS_CT_ENTRY entry,\n- OvsConntrackKeyLookupCtx *ctx,\n- PNAT_ACTION_INFO natInfo, UINT64 now)\n-{\n- LOCK_STATE_EX lockState;\n- NdisMoveMemory(&entry->key, &ctx->key, sizeof(OVS_CT_KEY));\n- NdisMoveMemory(&entry->rev_key, &ctx->key, sizeof(OVS_CT_KEY));\n- OvsCtKeyReverse(&entry->rev_key);\n-\n- /* NatInfo is always initialized to be disabled, so that if NAT action\n- * fails, we will not end up deleting an non-existent NAT entry.\n- */\n- if (natInfo == NULL) {\n- entry->natInfo.natAction = NAT_ACTION_NONE;\n- } else {\n- if (OvsIsForwardNat(natInfo->natAction)) {\n- entry->natInfo = *natInfo;\n- if (!OvsNatTranslateCtEntry(entry)) {\n- return FALSE;\n- }\n- ctx->hash = OvsCtHashKey(&entry->key);\n- } else {\n- entry->natInfo.natAction = natInfo->natAction;\n- }\n- }\n-\n- entry->timestampStart = now;\n- NdisAllocateSpinLock(&(entry->lock));\n- UINT32 bucketIdx = ctx->hash & CT_HASH_TABLE_MASK;\n- NdisAcquireRWLockWrite(ovsCtBucketLock[bucketIdx], &lockState, 0);\n- InsertHeadList(&ovsConntrackTable[bucketIdx],\n- &entry->link);\n-\n- NdisInterlockedIncrement((PLONG)&ctTotalEntries);\n- NdisInterlockedIncrement((PLONG)&zoneInfo[ctx->key.zone].entries);\n- NdisReleaseRWLock(ovsCtBucketLock[bucketIdx], &lockState);\n- return TRUE;\n-}\n-\n-static __inline POVS_CT_ENTRY\n-OvsCtEntryCreate(OvsForwardingContext *fwdCtx,\n- UINT8 ipProto,\n- OVS_PACKET_HDR_INFO *layers,\n- OvsConntrackKeyLookupCtx *ctx,\n- OvsFlowKey *key,\n- PNAT_ACTION_INFO natInfo,\n- BOOLEAN commit,\n- UINT64 currentTime,\n- BOOLEAN *entryCreated)\n-{\n- POVS_CT_ENTRY entry = NULL;\n- UINT32 state = 0;\n- POVS_CT_ENTRY parentEntry;\n- PNET_BUFFER_LIST curNbl = fwdCtx->curNbl;\n-\n- *entryCreated = FALSE;\n- state |= OVS_CS_F_NEW;\n- switch (ipProto) {\n- case IPPROTO_TCP:\n- {\n- UINT32 tcpPayloadLen;\n- TCPHdr tcpStorage;\n- const TCPHdr *tcp;\n- tcp = OvsGetTcpHeader(curNbl, layers, &tcpStorage, &tcpPayloadLen);\n- if (!OvsConntrackValidateTcpPacket(tcp)) {\n- state = OVS_CS_F_INVALID;\n- break;\n- }\n-\n- if (commit) {\n- entry = OvsConntrackCreateTcpEntry(tcp, currentTime,\n- tcpPayloadLen);\n- }\n- break;\n- }\n- case IPPROTO_ICMPV6:\n- {\n- ICMPHdr storage;\n- const ICMPHdr *icmp;\n- icmp = OvsGetIcmp(curNbl, layers->l4Offset, &storage);\n- if (!OvsConntrackValidateIcmp6Packet(icmp)) {\n- if (icmp) {\n- OVS_LOG_TRACE(\"Invalid ICMP6 packet detected, icmp->type %u\",\n- icmp->type);\n- }\n- state = OVS_CS_F_INVALID;\n- break;\n- }\n-\n- if (commit) {\n- entry = OvsConntrackCreateIcmpEntry(currentTime);\n- }\n- break;\n- }\n-\n- case IPPROTO_ICMP:\n- {\n- ICMPHdr storage;\n- const ICMPHdr *icmp;\n- icmp = OvsGetIcmp(curNbl, layers->l4Offset, &storage);\n- if (!OvsConntrackValidateIcmpPacket(icmp)) {\n- if(icmp) {\n- OVS_LOG_TRACE(\"Invalid ICMP packet detected, icmp->type %u\",\n- icmp->type);\n- }\n- state = OVS_CS_F_INVALID;\n- break;\n- }\n-\n- if (commit) {\n- entry = OvsConntrackCreateIcmpEntry(currentTime);\n- }\n- break;\n- }\n- case IPPROTO_UDP:\n- {\n- if (commit) {\n- entry = OvsConntrackCreateOtherEntry(currentTime);\n- }\n- break;\n- }\n- default:\n- OVS_LOG_TRACE(\"Invalid packet detected, protocol not supported\"\n- \" ipProto %u\", ipProto);\n- state = OVS_CS_F_INVALID;\n- break;\n- }\n-\n- parentEntry = OvsCtRelatedLookup(ctx->key, currentTime);\n- if (parentEntry != NULL && state != OVS_CS_F_INVALID) {\n- state |= OVS_CS_F_RELATED;\n- }\n- if (state != OVS_CS_F_INVALID && commit) {\n- if (entry) {\n- entry->parent = parentEntry;\n- if (OvsCtAddEntry(entry, ctx, natInfo, currentTime)) {\n- *entryCreated = TRUE;\n- } else {\n- /* Unable to add entry to the list */\n- OvsFreeMemoryWithTag(entry, OVS_CT_POOL_TAG);\n- state = OVS_CS_F_INVALID;\n- entry = NULL;\n- }\n- } else {\n- /* OvsAllocateMemoryWithTag returned NULL; treat as invalid */\n- state = OVS_CS_F_INVALID;\n- }\n- }\n-\n- OvsCtUpdateFlowKey(key, state, ctx->key.zone, 0, NULL);\n- if (entry) {\n- OvsCtIncrementCounters(entry, ctx->reply, curNbl);\n- }\n- return entry;\n-}\n-\n-static enum CT_UPDATE_RES\n-OvsCtUpdateEntry(OVS_CT_ENTRY* entry,\n- PNET_BUFFER_LIST nbl,\n- UINT8 ipProto,\n- OVS_PACKET_HDR_INFO *layers,\n- BOOLEAN reply,\n- UINT64 now)\n-{\n- CT_UPDATE_RES status;\n- switch (ipProto) {\n- case IPPROTO_TCP:\n- {\n- UINT32 tcpPayloadLen;\n- TCPHdr tcpStorage;\n- const TCPHdr *tcp;\n- tcp = OvsGetTcpHeader(nbl, layers, &tcpStorage, &tcpPayloadLen);\n- if (!tcp) {\n- status = CT_UPDATE_INVALID;\n- break;\n- }\n- NdisAcquireSpinLock(&(entry->lock));\n- status = OvsConntrackUpdateTcpEntry(entry, tcp, reply, now,\n- tcpPayloadLen);\n- NdisReleaseSpinLock(&(entry->lock));\n- break;\n- }\n- case IPPROTO_ICMP:\n- {\n- NdisAcquireSpinLock(&(entry->lock));\n- status = OvsConntrackUpdateIcmpEntry(entry, reply, now);\n- NdisReleaseSpinLock(&(entry->lock));\n- break;\n- }\n-\n- case IPPROTO_ICMPV6:\n- {\n- NdisAcquireSpinLock(&(entry->lock));\n- status = OvsConntrackUpdateIcmpEntry(entry, reply, now);\n- NdisReleaseSpinLock(&(entry->lock));\n- break;\n- }\n-\n- case IPPROTO_UDP:\n- {\n- NdisAcquireSpinLock(&(entry->lock));\n- status = OvsConntrackUpdateOtherEntry(entry, reply, now);\n- NdisReleaseSpinLock(&(entry->lock));\n- break;\n- }\n- default:\n- status = CT_UPDATE_INVALID;\n- break;\n- }\n- return status;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsCtEntryExpired\n- * Assumes ct entry lock is acquired\n- *----------------------------------------------------------------------------\n- */\n-static __inline BOOLEAN\n-OvsCtEntryExpired(POVS_CT_ENTRY entry)\n-{\n- UINT64 currentTime;\n- NdisGetCurrentSystemTime((LARGE_INTEGER *)¤tTime);\n- return entry->expiration < currentTime;\n-}\n-\n-static __inline VOID\n-OvsCtEntryDelete(POVS_CT_ENTRY entry, BOOLEAN forceDelete)\n-{\n- if (entry == NULL) {\n- return;\n- }\n- KIRQL irql = KeGetCurrentIrql();\n- OVS_ACQUIRE_SPIN_LOCK(&(entry->lock), irql);\n- if (forceDelete || OvsCtEntryExpired(entry)) {\n- if (entry->natInfo.natAction) {\n- OvsNatDeleteKey(&entry->key);\n- }\n- NdisInterlockedDecrement((PLONG)&zoneInfo[entry->key.zone].entries);\n- OvsPostCtEventEntry(entry, OVS_EVENT_CT_DELETE);\n- RemoveEntryList(&entry->link);\n- OVS_RELEASE_SPIN_LOCK(&(entry->lock), irql);\n- NdisFreeSpinLock(&(entry->lock));\n- if (entry->helper_name) {\n- OvsFreeMemoryWithTag(entry->helper_name, OVS_CT_POOL_TAG);\n- }\n- OvsFreeMemoryWithTag(entry, OVS_CT_POOL_TAG);\n- NdisInterlockedDecrement((PLONG)&ctTotalEntries);\n- return;\n- }\n- OVS_RELEASE_SPIN_LOCK(&(entry->lock), irql);\n-}\n-\n-static __inline NDIS_STATUS\n-OvsDetectCtPacket(OvsForwardingContext *fwdCtx,\n- OvsFlowKey *key)\n-{\n- NDIS_STATUS status = NDIS_STATUS_SUCCESS;\n- OvsFlowKey newFlowKey = { 0 };\n-\n- switch (ntohs(key->l2.dlType)) {\n- case ETH_TYPE_IPV4:\n- if (key->ipKey.nwFrag != OVS_FRAG_TYPE_NONE) {\n- status = OvsProcessIpv4Fragment(fwdCtx->switchContext,\n- &fwdCtx->curNbl,\n- fwdCtx->completionList,\n- fwdCtx->fwdDetail->SourcePortId,\n- &fwdCtx->layers,\n- key->tunKey.tunnelId);\n- if (status == NDIS_STATUS_SUCCESS) {\n- /* After the Ipv4 Fragment is reassembled, update flow key as\n- L3 and L4 headers are not correct */\n- status = OvsExtractFlow(fwdCtx->curNbl, fwdCtx->srcVportNo,\n- &newFlowKey, &fwdCtx->layers,\n- !OvsIphIsZero(&(fwdCtx->tunKey.dst)) ?\n- &(fwdCtx->tunKey) : NULL);\n- if (status != NDIS_STATUS_SUCCESS) {\n- OVS_LOG_ERROR(\"Extract flow failed Nbl %p\", fwdCtx->curNbl);\n- return status;\n- }\n- *key = newFlowKey;\n- }\n- return status;\n- }\n- if (key->ipKey.nwProto == IPPROTO_TCP\n- || key->ipKey.nwProto == IPPROTO_UDP\n- || key->ipKey.nwProto == IPPROTO_ICMP) {\n- return NDIS_STATUS_SUCCESS;\n- }\n- return NDIS_STATUS_NOT_SUPPORTED;\n- case ETH_TYPE_IPV6:\n- if (key->ipv6Key.nwFrag != OVS_FRAG_TYPE_NONE) {\n- status = OvsProcessIpv6Fragment(fwdCtx->switchContext,\n- &fwdCtx->curNbl,\n- fwdCtx->completionList,\n- fwdCtx->fwdDetail->SourcePortId,\n- &fwdCtx->layers,\n- key->tunKey.tunnelId, key);\n- if (status == NDIS_STATUS_SUCCESS) {\n- status = OvsExtractFlow(fwdCtx->curNbl, fwdCtx->srcVportNo,\n- &newFlowKey, &fwdCtx->layers,\n- !OvsIphIsZero(&(fwdCtx->tunKey.dst)) ?\n- &(fwdCtx->tunKey) : NULL);\n- if (status != NDIS_STATUS_SUCCESS) {\n- OVS_LOG_ERROR(\"Extract flow for ipv6 failed Nbl %p\",\n- fwdCtx->curNbl);\n- return status;\n- }\n- *key = newFlowKey;\n- }\n- return status;\n- }\n-\n- if (key->ipv6Key.nwProto == IPPROTO_ICMPV6\n- || key->ipv6Key.nwProto == IPPROTO_TCP\n- || key->ipv6Key.nwProto == IPPROTO_UDP) {\n- return NDIS_STATUS_SUCCESS;\n- }\n- return NDIS_STATUS_NOT_SUPPORTED;\n- }\n-\n- return NDIS_STATUS_NOT_SUPPORTED;\n-}\n-\n-BOOLEAN\n-OvsCtEndpointsAreSame(OVS_CT_KEY ctxKey, OVS_CT_KEY entryKey)\n-{\n- return ((NdisEqualMemory(&ctxKey.src, &entryKey.src,\n- sizeof(struct ct_endpoint))) &&\n- (NdisEqualMemory(&ctxKey.dst, &entryKey.dst,\n- sizeof(struct ct_endpoint))));\n-}\n-\n-POVS_CT_ENTRY\n-OvsCtLookup(OvsConntrackKeyLookupCtx *ctx)\n-{\n- PLIST_ENTRY link;\n- POVS_CT_ENTRY entry;\n- BOOLEAN reply = FALSE;\n- POVS_CT_ENTRY found = NULL;\n- LOCK_STATE_EX lockStateTable;\n- UINT32 bucketIdx;\n-\n- if (!ctTotalEntries) {\n- return found;\n- }\n-\n- /* Reverse NAT must be performed before OvsCtLookup, so here\n- * we simply need to flip the src and dst in key and compare\n- * they are equal. Note that flipped key is not equal to\n- * rev_key due to NAT effect.\n- */\n- OVS_CT_KEY revCtxKey = ctx->key;\n- OvsCtKeyReverse(&revCtxKey);\n-\n- KIRQL irql = KeGetCurrentIrql();\n- bucketIdx = ctx->hash & CT_HASH_TABLE_MASK;\n- NdisAcquireRWLockRead(ovsCtBucketLock[bucketIdx], &lockStateTable, 0);\n- LIST_FORALL(&ovsConntrackTable[bucketIdx], link) {\n- entry = CONTAINING_RECORD(link, OVS_CT_ENTRY, link);\n- OVS_ACQUIRE_SPIN_LOCK(&(entry->lock), irql);\n-\n- if ((ctx->key.dl_type != entry->key.dl_type) ||\n- (ctx->key.nw_proto != entry->key.nw_proto) ||\n- (ctx->key.zone != entry->key.zone)) {\n- OVS_RELEASE_SPIN_LOCK(&(entry->lock), irql);\n- continue;\n- }\n-\n- if (OvsCtEndpointsAreSame(ctx->key, entry->key)) {\n- found = entry;\n- reply = FALSE;\n- }\n-\n- if (!found && OvsCtEndpointsAreSame(revCtxKey, entry->key)) {\n- found = entry;\n- reply = TRUE;\n- }\n-\n- if (found) {\n- if (OvsCtEntryExpired(found)) {\n- found = NULL;\n- } else {\n- ctx->reply = reply;\n- }\n- OVS_RELEASE_SPIN_LOCK(&(entry->lock), irql);\n- break;\n- }\n- OVS_RELEASE_SPIN_LOCK(&(entry->lock), irql);\n- }\n-\n- NdisReleaseRWLock(ovsCtBucketLock[bucketIdx], &lockStateTable);\n- ctx->entry = found;\n- return found;\n-}\n-\n-const TCPHdr*\n-OvsGetTcpHeader(PNET_BUFFER_LIST nbl,\n- OVS_PACKET_HDR_INFO *layers,\n- VOID *storage,\n- UINT32 *tcpPayloadLen)\n-{\n- IPHdr *ipHdr;\n- IPv6Hdr *ipv6Hdr;\n- TCPHdr *tcp;\n- VOID *dest = storage;\n- uint16_t ipv6ExtLength = 0;\n-\n- if (layers->isIPv6) {\n- ipv6Hdr = NdisGetDataBuffer(NET_BUFFER_LIST_FIRST_NB(nbl),\n- layers->l4Offset + sizeof(TCPHdr),\n- NULL, 1, 0);\n- if (ipv6Hdr == NULL) {\n- return NULL;\n- }\n-\n- tcp = (TCPHdr *)((PCHAR)ipv6Hdr + layers->l4Offset);\n- ipv6Hdr = (IPv6Hdr *)((PCHAR)ipv6Hdr + layers->l3Offset);\n- if (tcp->doff * 4 >= sizeof *tcp) {\n- NdisMoveMemory(dest, tcp, sizeof(TCPHdr));\n- ipv6ExtLength = layers->l4Offset - layers->l3Offset - sizeof(IPv6Hdr);\n- *tcpPayloadLen = (ntohs(ipv6Hdr->payload_len) - ipv6ExtLength - TCP_HDR_LEN(tcp));\n- return storage;\n- }\n- } else {\n- ipHdr = NdisGetDataBuffer(NET_BUFFER_LIST_FIRST_NB(nbl),\n- layers->l4Offset + sizeof(TCPHdr),\n- NULL, 1 /*no align*/, 0);\n- if (ipHdr == NULL) {\n- return NULL;\n- }\n-\n- ipHdr = (IPHdr *)((PCHAR)ipHdr + layers->l3Offset);\n- tcp = (TCPHdr *)((PCHAR)ipHdr + ipHdr->ihl * 4);\n-\n- if (tcp->doff * 4 >= sizeof *tcp) {\n- NdisMoveMemory(dest, tcp, sizeof(TCPHdr));\n- *tcpPayloadLen = TCP_DATA_LENGTH(ipHdr, tcp);\n- return storage;\n- }\n- }\n- return NULL;\n-}\n-\n-static UINT8\n-OvsReverseIcmpType(UINT8 type)\n-{\n- switch (type) {\n- case ICMP4_ECHO_REQUEST:\n- return ICMP4_ECHO_REPLY;\n- case ICMP4_ECHO_REPLY:\n- return ICMP4_ECHO_REQUEST;\n- case ICMP4_TIMESTAMP_REQUEST:\n- return ICMP4_TIMESTAMP_REPLY;\n- case ICMP4_TIMESTAMP_REPLY:\n- return ICMP4_TIMESTAMP_REQUEST;\n- case ICMP4_INFO_REQUEST:\n- return ICMP4_INFO_REPLY;\n- case ICMP4_INFO_REPLY:\n- return ICMP4_INFO_REQUEST;\n- case ICMP6_ECHO_REQUEST:\n- return ICMP6_ECHO_REPLY;\n- case ICMP6_ECHO_REPLY:\n- return ICMP6_ECHO_REQUEST;\n- default:\n- return 0;\n- }\n-}\n-\n-static __inline void\n-OvsPickupCtTupleAsLookupKey(POVS_CT_KEY ctKey, UINT16 zone, OvsFlowKey *flowKey)\n-{\n- UINT32 ipAddrSrc = 0, ipAddrDst = 0;\n-\n- if (!flowKey || !ctKey) return;\n-\n- if (flowKey->l2.dlType == htons(ETH_TYPE_IPV4)) {\n- ipAddrSrc = flowKey->ct.tuple_ipv4.ipv4_src;\n- ipAddrDst = flowKey->ct.tuple_ipv4.ipv4_dst;\n-\n- if ((ipAddrSrc > 0 && ipAddrDst > 0) &&\n- (zone == flowKey->ct.zone)) {\n- /* if the ct tuple_ipv4 in flowKey is not null and ct.zone is same with\n- * zone parameter pickup the tuple_ipv4 value as the lookup key\n- */\n- ctKey->src.addr.ipv4 = flowKey->ct.tuple_ipv4.ipv4_src;\n- ctKey->dst.addr.ipv4 = flowKey->ct.tuple_ipv4.ipv4_dst;\n- ctKey->nw_proto = flowKey->ct.tuple_ipv4.ipv4_proto;\n- ctKey->src.port = flowKey->ct.tuple_ipv4.src_port;\n- ctKey->dst.port = flowKey->ct.tuple_ipv4.dst_port;\n- }\n- }\n-}\n-\n-static __inline NDIS_STATUS\n-OvsCtSetupLookupCtx(OvsFlowKey *flowKey,\n- UINT16 zone,\n- OvsConntrackKeyLookupCtx *ctx,\n- PNET_BUFFER_LIST curNbl,\n- UINT32 l4Offset)\n-{\n- const OVS_NAT_ENTRY *natEntry;\n- ctx->key.zone = zone;\n- ctx->key.dl_type = flowKey->l2.dlType;\n- ctx->related = FALSE;\n-\n- /* Extract L3 and L4*/\n- if (flowKey->l2.dlType == htons(ETH_TYPE_IPV4)) {\n- ctx->key.src.addr.ipv4 = flowKey->ipKey.nwSrc;\n- ctx->key.dst.addr.ipv4 = flowKey->ipKey.nwDst;\n- ctx->key.nw_proto = flowKey->ipKey.nwProto;\n-\n- ctx->key.src.port = flowKey->ipKey.l4.tpSrc;\n- ctx->key.dst.port = flowKey->ipKey.l4.tpDst;\n-\n- if (flowKey->ipKey.nwProto == IPPROTO_ICMP) {\n- ICMPHdr icmpStorage;\n- const ICMPHdr *icmp;\n- icmp = OvsGetIcmp(curNbl, l4Offset, &icmpStorage);\n- ASSERT(icmp);\n-\n- /* Related bit is set when ICMP has an error */\n- /* XXX parse out the appropriate src and dst from inner pkt */\n- switch (icmp->type) {\n- case ICMP4_ECHO_REQUEST:\n- case ICMP4_ECHO_REPLY:\n- case ICMP4_TIMESTAMP_REQUEST:\n- case ICMP4_TIMESTAMP_REPLY:\n- case ICMP4_INFO_REQUEST:\n- case ICMP4_INFO_REPLY:\n- if (icmp->code != 0) {\n- return NDIS_STATUS_INVALID_PACKET;\n- }\n- /* Separate ICMP connection: identified using id */\n- ctx->key.dst.icmp_id = ntohs(icmp->fields.echo.id);\n- ctx->key.src.icmp_id = ntohs(icmp->fields.echo.id);\n- ctx->key.src.icmp_type = icmp->type;\n- ctx->key.dst.icmp_type = OvsReverseIcmpType(icmp->type);\n- break;\n- case ICMP4_DEST_UNREACH:\n- case ICMP4_TIME_EXCEEDED:\n- case ICMP4_PARAM_PROB:\n- case ICMP4_SOURCE_QUENCH:\n- case ICMP4_REDIRECT: {\n- ctx->related = TRUE;\n- break;\n- }\n- default:\n- ctx->related = FALSE;\n- }\n- }\n- } else if (flowKey->l2.dlType == htons(ETH_TYPE_IPV6)) {\n- ctx->key.src.addr.ipv6 = flowKey->ipv6Key.ipv6Src;\n- ctx->key.dst.addr.ipv6 = flowKey->ipv6Key.ipv6Dst;\n- ctx->key.nw_proto = flowKey->ipv6Key.nwProto;\n-\n- ctx->key.src.port = flowKey->ipv6Key.l4.tpSrc;\n- ctx->key.dst.port = flowKey->ipv6Key.l4.tpDst;\n- if (flowKey->ipv6Key.nwProto == IPPROTO_ICMPV6) {\n- ICMPHdr icmpStorage;\n- const ICMPHdr *icmp;\n- icmp = OvsGetIcmp(curNbl, l4Offset, &icmpStorage);\n- ASSERT(icmp);\n-\n- switch (icmp->type) {\n- case ICMP6_ECHO_REQUEST:\n- case ICMP6_ECHO_REPLY: {\n- ctx->key.dst.icmp_id = ntohs(icmp->fields.echo.id);\n- ctx->key.src.icmp_id = ntohs(icmp->fields.echo.id);\n- ctx->key.src.icmp_type = icmp->type;\n- ctx->key.dst.icmp_type = OvsReverseIcmpType(icmp->type);\n- break;\n- }\n- case ICMP6_DST_UNREACH:\n- case ICMP6_TIME_EXCEEDED:\n- case ICMP6_PARAM_PROB:\n- case ICMP6_PACKET_TOO_BIG: {\n- Ipv6Key ipv6Key;\n- OVS_PACKET_HDR_INFO layers;\n- OvsExtractLayers(curNbl, &layers);\n- layers.l3Offset = layers.l7Offset;\n- NDIS_STATUS status = OvsParseIPv6(curNbl, &ipv6Key, &layers);\n- if (status != NDIS_STATUS_SUCCESS) {\n- return NDIS_STATUS_INVALID_PACKET;\n- }\n- ctx->key.src.addr.ipv6 = ipv6Key.ipv6Src;\n- ctx->key.dst.addr.ipv6 = ipv6Key.ipv6Dst;\n- ctx->key.nw_proto = ipv6Key.nwProto;\n- if (ipv6Key.nwProto == SOCKET_IPPROTO_TCP) {\n- OvsParseTcp(curNbl, &(ipv6Key.l4), &layers);\n- } else if (ipv6Key.nwProto == SOCKET_IPPROTO_UDP) {\n- OvsParseUdp(curNbl, &(ipv6Key.l4), &layers);\n- } else if (ipv6Key.nwProto == SOCKET_IPPROTO_SCTP) {\n- OvsParseSctp(curNbl, &ipv6Key.l4, &layers);\n- }\n- ctx->key.src.port = ipv6Key.l4.tpSrc;\n- ctx->key.dst.port = ipv6Key.l4.tpDst;\n- OvsCtKeyReverse(&ctx->key);\n- ctx->related = TRUE;\n- break;\n- }\n- default:\n- ctx->related = FALSE;\n- }\n- }\n- } else {\n- return NDIS_STATUS_INVALID_PACKET;\n- }\n-\n- /* It's only designed for unNat traffic, when reverse traffic comes,\n- * find the unNat table, if found the nat entry, based on the nat entry\n- * restore the conntrack, it will be stored in the ctx->key and then use the\n- * ctx->key lookup the conntrack table to find the corresponded\n- * entry with the traffic.*/\n- natEntry = OvsNatLookup(&ctx->key, TRUE);\n- if (natEntry) {\n- /* initial direction 20::1 -> 20::9, reverse direction 21::3 -> 20::1\n- * 20::9 could be regarded as nat ip, before convert, ctx->key value\n- * is \"21::3 -> 20::1\", after convert, ctx->key value is\n- * \"20::9->20::1\" */\n- ctx->key = natEntry->ctEntry->key;\n- OvsCtKeyReverse(&ctx->key);\n- } else {\n- if (OvsNatLookup(&ctx->key, FALSE)) {\n- /* Do nothing here, this branch here used to exclude traffic\n- * described in https://github.com/openvswitch/ovs-issues/issues/237\n- * */\n- } else if (flowKey->l2.dlType == htons(ETH_TYPE_IPV4)) {\n- OvsPickupCtTupleAsLookupKey(&(ctx->key), zone, flowKey);\n- }\n- }\n-\n- ctx->hash = OvsCtHashKey(&ctx->key);\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-static __inline BOOLEAN\n-OvsDetectFtpPacket(OvsFlowKey *key) {\n- return (key->ipKey.nwProto == IPPROTO_TCP &&\n- (ntohs(key->ipKey.l4.tpDst) == IPPORT_FTP ||\n- ntohs(key->ipKey.l4.tpSrc) == IPPORT_FTP));\n-}\n-\n-static __inline BOOLEAN\n-OvsDetectFtp6Packet(OvsFlowKey *key) {\n- return (key->ipv6Key.nwProto == IPPROTO_TCP &&\n- (ntohs(key->ipv6Key.l4.tpDst) == IPPORT_FTP ||\n- ntohs(key->ipv6Key.l4.tpSrc) == IPPORT_FTP));\n-}\n-\n-static __inline BOOLEAN\n-OvsDetectTftpPacket(OvsFlowKey *key) {\n- return (key->ipKey.nwProto == IPPROTO_UDP &&\n- (ntohs(key->ipKey.l4.tpDst) == IPPORT_TFTP));\n-}\n-\n-static __inline BOOLEAN\n-OvsDetectTftp6Packet(OvsFlowKey *key) {\n- return (key->ipv6Key.nwProto == IPPROTO_UDP &&\n- (ntohs(key->ipv6Key.l4.tpDst) == IPPORT_TFTP));\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsProcessConntrackEntry\n- * Check the TCP flags and set the ct_state of the entry\n- *----------------------------------------------------------------------------\n- */\n-static __inline POVS_CT_ENTRY\n-OvsProcessConntrackEntry(OvsForwardingContext *fwdCtx,\n- OVS_PACKET_HDR_INFO *layers,\n- OvsConntrackKeyLookupCtx *ctx,\n- OvsFlowKey *key,\n- UINT16 zone,\n- NAT_ACTION_INFO *natInfo,\n- BOOLEAN commit,\n- UINT64 currentTime,\n- BOOLEAN *entryCreated)\n-{\n- POVS_CT_ENTRY entry = ctx->entry;\n- UINT32 state = 0;\n- PNET_BUFFER_LIST curNbl = fwdCtx->curNbl;\n- LOCK_STATE_EX lockStateTable;\n-\n- *entryCreated = FALSE;\n-\n- /* If an entry was found, update the state based on TCP flags */\n- if (ctx->related) {\n- state |= OVS_CS_F_RELATED;\n- if (ctx->reply) {\n- state |= OVS_CS_F_REPLY_DIR;\n- }\n- } else {\n- CT_UPDATE_RES result;\n- UINT32 bucketIdx;\n-\n- if (layers->isIPv6) {\n- result = OvsCtUpdateEntry(entry, curNbl, key->ipv6Key.nwProto, layers,\n- ctx->reply, currentTime);\n- } else {\n- result = OvsCtUpdateEntry(entry, curNbl, key->ipKey.nwProto, layers,\n- ctx->reply, currentTime);\n- }\n-\n- switch (result) {\n- case CT_UPDATE_VALID:\n- state |= OVS_CS_F_ESTABLISHED;\n- /** when the ct state is established, at least\n- * request/reply two packets go through,\n- * so the ct_state shouldn't contain new.**/\n- state &= ~OVS_CS_F_NEW;\n- if (ctx->reply) {\n- state |= OVS_CS_F_REPLY_DIR;\n- }\n- break;\n- case CT_UPDATE_INVALID:\n- state |= OVS_CS_F_INVALID;\n- break;\n- case CT_UPDATE_NEW:\n- //Delete and update the Conntrack\n- bucketIdx = ctx->hash & CT_HASH_TABLE_MASK;\n- NdisAcquireRWLockWrite(ovsCtBucketLock[bucketIdx], &lockStateTable, 0);\n- OvsCtEntryDelete(ctx->entry, TRUE);\n- NdisReleaseRWLock(ovsCtBucketLock[bucketIdx], &lockStateTable);\n- ctx->entry = NULL;\n-\n- if (layers->isIPv6) {\n- entry = OvsCtEntryCreate(fwdCtx, key->ipv6Key.nwProto, layers,\n- ctx, key, natInfo, commit, currentTime,\n- entryCreated);\n- } else {\n- entry = OvsCtEntryCreate(fwdCtx, key->ipKey.nwProto, layers,\n- ctx, key, natInfo, commit, currentTime,\n- entryCreated);\n- }\n-\n- if (!entry) {\n- return NULL;\n- }\n- break;\n- case CT_UPDATE_VALID_NEW:\n- state |= OVS_CS_F_NEW;\n- break;\n- }\n- }\n- if (entry) {\n- NdisAcquireSpinLock(&(entry->lock));\n- if ((layers->isIPv6 && key->ipv6Key.nwProto == IPPROTO_TCP) ||\n- (!(layers->isIPv6) && key->ipKey.nwProto == IPPROTO_TCP) ||\n- (layers->isIPv6 && key->ipv6Key.nwProto == IPPROTO_UDP) ||\n- (!(layers->isIPv6) && key->ipKey.nwProto == IPPROTO_UDP)) {\n- /* Update the related bit if there is a parent */\n- if (entry->parent) {\n- state |= OVS_CS_F_RELATED;\n- } else {\n- POVS_CT_ENTRY parentEntry;\n- parentEntry = OvsCtRelatedLookup(ctx->key, currentTime);\n- entry->parent = parentEntry;\n- if (parentEntry != NULL) {\n- state |= OVS_CS_F_RELATED;\n- }\n- }\n- }\n-\n- /* Copy mark and label from entry into flowKey. If actions specify\n- different mark and label, update the flowKey. */\n- OvsCtUpdateFlowKey(key, state, zone, entry->mark, &entry->labels);\n- NdisReleaseSpinLock(&(entry->lock));\n- } else {\n- OvsCtUpdateFlowKey(key, state, zone, 0, NULL);\n- }\n- return entry;\n-}\n-\n-static __inline VOID\n-OvsConntrackSetMark(OvsFlowKey *key,\n- POVS_CT_ENTRY entry,\n- MD_MARK *mark,\n- BOOLEAN *markChanged)\n-{\n- POVS_CT_ENTRY parent = entry->parent;\n- BOOLEAN changed = FALSE;\n- UINT32 newMark = 0;\n-\n- if (parent && parent->mark) {\n- newMark = parent->mark;\n- changed = TRUE;\n- } else if (mark) {\n- newMark = mark->value | (entry->mark & ~(mark->mask));\n- changed = TRUE;\n- }\n-\n- if (changed && entry->mark != newMark) {\n- entry->mark = newMark;\n- key->ct.mark = newMark;\n- *markChanged = TRUE;\n- }\n-}\n-\n-static __inline BOOLEAN\n-OvsConntrackIsLabelsNonZero(const struct ovs_key_ct_labels *labels)\n-{\n- UINT8 i;\n-\n- for (i = 0; i < OVS_CT_LABELS_LEN_32; i++) {\n- if (labels->ct_labels_32[i]) {\n- return TRUE;\n- }\n- }\n-\n- return FALSE;\n-}\n-\n-static __inline void\n-OvsConntrackSetLabels(OvsFlowKey *key,\n- POVS_CT_ENTRY entry,\n- MD_LABELS *labels,\n- BOOLEAN *labelChanged)\n-{\n- POVS_CT_ENTRY parent = entry->parent;\n-\n- /* Inherit master's labels at labels initialization, if any. */\n- if (!OvsConntrackIsLabelsNonZero(&entry->labels) &&\n- parent && OvsConntrackIsLabelsNonZero(&parent->labels)) {\n- RtlCopyMemory(&entry->labels, &parent->labels, OVS_CT_LABELS_LEN);\n- *labelChanged = TRUE;\n- }\n-\n- /* Update labels according to value of ct_label in ct commit */\n- if (labels && OvsConntrackIsLabelsNonZero(&labels->mask)) {\n- UINT8 i;\n- UINT32 *dst = entry->labels.ct_labels_32;\n- for (i = 0; i < OVS_CT_LABELS_LEN_32; i++) {\n- dst[i] = (dst[i] & ~(labels->mask.ct_labels_32[i])) |\n- (labels->value.ct_labels_32[i] & labels->mask.ct_labels_32[i]);\n- }\n-\n- *labelChanged = TRUE;\n- }\n-\n- /* Update flow key's ct labels */\n- NdisMoveMemory(&key->ct.labels, &entry->labels, OVS_CT_LABELS_LEN);\n-}\n-\n-static void\n-OvsCtSetMarkLabel(OvsFlowKey *key,\n- POVS_CT_ENTRY entry,\n- MD_MARK *mark,\n- MD_LABELS *labels,\n- BOOLEAN *triggerUpdateEvent)\n-{\n- OvsConntrackSetMark(key, entry, mark, triggerUpdateEvent);\n- OvsConntrackSetLabels(key, entry, labels, triggerUpdateEvent);\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsCtUpdateTuple\n- * Assumes ct entry lock is acquired\n- *----------------------------------------------------------------------------\n- */\n-static __inline void\n-OvsCtUpdateTuple(OvsFlowKey *key, OVS_CT_KEY *ctKey)\n-{\n- key->ct.tuple_ipv4.ipv4_src = ctKey->src.addr.ipv4_aligned;\n- key->ct.tuple_ipv4.ipv4_dst = ctKey->dst.addr.ipv4_aligned;\n- key->ct.tuple_ipv4.ipv4_proto = ctKey->nw_proto;\n-\n- /* Orig tuple Port is overloaded to take in ICMP-Type & Code */\n- /* This mimics the behavior in lib/conntrack.c*/\n- key->ct.tuple_ipv4.src_port = ctKey->nw_proto != IPPROTO_ICMP ?\n- ctKey->src.port :\n- htons(ctKey->src.icmp_type);\n- key->ct.tuple_ipv4.dst_port = ctKey->nw_proto != IPPROTO_ICMP ?\n- ctKey->dst.port :\n- htons(ctKey->src.icmp_code);\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsCtUpdateTupleV6 name --\n- * Update origin tuple for ipv6 packet.\n- * --------------------------------------------------------------------------\n- */\n-static __inline void\n-OvsCtUpdateTupleV6(OvsFlowKey *key, OVS_CT_KEY *ctKey)\n-{\n- RtlCopyMemory(&key->ct.tuple_ipv6.ipv6_src, &ctKey->src.addr.ipv6_aligned, sizeof(key->ct.tuple_ipv6.ipv6_src));\n- RtlCopyMemory(&key->ct.tuple_ipv6.ipv6_dst, &ctKey->dst.addr.ipv6_aligned, sizeof(key->ct.tuple_ipv6.ipv6_dst));\n- key->ct.tuple_ipv6.ipv6_proto = ctKey->nw_proto;\n-\n- /* Orig tuple Port is overloaded to take in ICMP-Type & Code */\n- /* This mimics the behavior in lib/conntrack.c*/\n- key->ct.tuple_ipv6.src_port = ctKey->nw_proto != IPPROTO_ICMPV6 ?\n- ctKey->src.port :\n- htons(ctKey->src.icmp_type);\n- key->ct.tuple_ipv6.dst_port = ctKey->nw_proto != IPPROTO_ICMPV6 ?\n- ctKey->dst.port :\n- htons(ctKey->src.icmp_code);\n-}\n-\n-static __inline NDIS_STATUS\n-OvsCtExecute_(OvsForwardingContext *fwdCtx,\n- OvsFlowKey *key,\n- OVS_PACKET_HDR_INFO *layers,\n- BOOLEAN commit,\n- BOOLEAN force,\n- UINT16 zone,\n- MD_MARK *mark,\n- MD_LABELS *labels,\n- PCHAR helper,\n- PNAT_ACTION_INFO natInfo,\n- BOOLEAN postUpdateEvent)\n-{\n- NDIS_STATUS status = NDIS_STATUS_SUCCESS;\n- BOOLEAN triggerUpdateEvent = FALSE;\n- BOOLEAN entryCreated = FALSE;\n- POVS_CT_ENTRY entry = NULL;\n- POVS_CT_ENTRY parent = NULL;\n- PNET_BUFFER_LIST curNbl = fwdCtx->curNbl;\n- OvsConntrackKeyLookupCtx ctx = { 0 };\n- CT_HELPER_METHOD helpMethod = CT_HELPER_NONE;\n- LOCK_STATE_EX lockStateTable;\n- UINT64 currentTime;\n- NdisGetCurrentSystemTime((LARGE_INTEGER *) ¤tTime);\n-\n- /* Retrieve the Conntrack Key related fields from packet */\n- OvsCtSetupLookupCtx(key, zone, &ctx, curNbl, layers->l4Offset);\n-\n- /* Lookup Conntrack entries for a matching entry */\n- entry = OvsCtLookup(&ctx);\n-\n- /* Delete entry in reverse direction if 'force' is specified */\n- if (force && ctx.reply && entry) {\n- UINT32 bucketIdx = ctx.hash & CT_HASH_TABLE_MASK;\n- NdisAcquireRWLockWrite(ovsCtBucketLock[bucketIdx], &lockStateTable, 0);\n- OvsCtEntryDelete(entry, TRUE);\n- NdisReleaseRWLock(ovsCtBucketLock[bucketIdx], &lockStateTable);\n- entry = NULL;\n- }\n-\n- if (entry) {\n- /* Increment stats for the entry if it wasn't tracked previously or\n- * if they are on different zones\n- */\n- if ((entry->key.zone != key->ct.zone ||\n- (!(key->ct.state & OVS_CS_F_TRACKED)))) {\n- OvsCtIncrementCounters(entry, ctx.reply, curNbl);\n- }\n- /* Process the entry and update CT flags */\n- entry = OvsProcessConntrackEntry(fwdCtx, layers, &ctx, key,\n- zone, natInfo, commit, currentTime,\n- &entryCreated);\n-\n- } else {\n- if (commit && (ctTotalEntries >= CT_MAX_ENTRIES ||\n- zoneInfo[ctx.key.zone].entries >= zoneInfo[ctx.key.zone].limit)) {\n- /* Don't proceed with processing if the max limit has been hit.\n- * This blocks only new entries from being created and doesn't\n- * affect existing connections.\n- */\n- OVS_LOG_ERROR(\"Conntrack Limit hit: zone(%u), zoneLimit(%lu),\"\n- \"zoneEntries(%lu), ctTotalEntries(%lu)\",\n- zone, zoneInfo[ctx.key.zone].limit,\n- zoneInfo[ctx.key.zone].entries, ctTotalEntries);\n- return NDIS_STATUS_RESOURCES;\n- }\n- /* If no matching entry was found, create one and add New state */\n- if (key->l2.dlType == htons(ETH_TYPE_IPV6)) {\n- entry = OvsCtEntryCreate(fwdCtx, key->ipv6Key.nwProto,\n- layers, &ctx,\n- key, natInfo, commit, currentTime,\n- &entryCreated);\n- } else {\n- entry = OvsCtEntryCreate(fwdCtx, key->ipKey.nwProto,\n- layers, &ctx,\n- key, natInfo, commit, currentTime,\n- &entryCreated);\n- }\n- }\n-\n- if (entry == NULL) {\n- return status;\n- }\n-\n- /*\n- * Note that natInfo is not the same as entry->natInfo here. natInfo\n- * is decided by action in the openflow rule, entry->natInfo is decided\n- * when the entry is created. In the reverse NAT case, natInfo is\n- * NAT_ACTION_REVERSE, yet entry->natInfo is NAT_ACTION_SRC or\n- * NAT_ACTION_DST without NAT_ACTION_REVERSE\n- */\n- KIRQL irql = KeGetCurrentIrql();\n- OVS_ACQUIRE_SPIN_LOCK(&(entry->lock), irql);\n- if (natInfo->natAction != NAT_ACTION_NONE) {\n- OvsNatPacket(fwdCtx, entry, entry->natInfo.natAction,\n- key, ctx.reply);\n- }\n-\n- OvsCtSetMarkLabel(key, entry, mark, labels, &triggerUpdateEvent);\n-\n- if (helper && RtlEqualMemory(helper, \"ftp\", sizeof(\"ftp\"))) {\n- helpMethod = CT_HELPER_FTP;\n- } else if (helper && RtlEqualMemory(helper, \"tftp\", sizeof(\"tftp\"))) {\n- helpMethod = CT_HELPER_TFTP;\n- }\n-\n- /* This code section was added to compatible with the old version,\n- * because old version regard all traffic to port 21 as ftp traffic,\n- * no need to add alg field in ct. Thus, the code was added to keep the\n- * same behavior for ftp and tftp.*/\n- if (layers->isIPv6) {\n- if (OvsDetectFtp6Packet(key)) {\n- helpMethod = CT_HELPER_FTP;\n- }\n-\n- if (OvsDetectTftp6Packet(key)) {\n- helpMethod = CT_HELPER_TFTP;\n- }\n- } else {\n- if (OvsDetectFtpPacket(key)) {\n- helpMethod = CT_HELPER_FTP;\n- }\n-\n- if (OvsDetectTftpPacket(key)) {\n- helpMethod = CT_HELPER_TFTP;\n- }\n- }\n-\n- if (helpMethod == CT_HELPER_FTP) {\n- status = OvsCtHandleFtp(curNbl, key, layers, currentTime, entry);\n- if (status != NDIS_STATUS_SUCCESS) {\n- OVS_LOG_ERROR(\"Error while parsing the FTP packet\");\n- }\n- }\n-\n- if (helpMethod == CT_HELPER_TFTP) {\n- status = OvsCtHandleTftp(curNbl, key, layers, currentTime, entry);\n- if (status != NDIS_STATUS_SUCCESS) {\n- OVS_LOG_ERROR(\"Error while parsing the TFTP packet\");\n- }\n- }\n-\n- parent = entry->parent;\n- /* The entry should have the same helper name with parent's */\n- if (!entry->helper_name &&\n- (helper || (parent && parent->helper_name))) {\n- helper = helper ? helper : parent->helper_name;\n- entry->helper_name = OvsAllocateMemoryWithTag(strlen(helper) + 1,\n- OVS_CT_POOL_TAG);\n- if (!entry->helper_name) {\n- OVS_LOG_ERROR(\"Error while allocating memory\");\n- OVS_RELEASE_SPIN_LOCK(&(entry->lock), irql);\n- return NDIS_STATUS_RESOURCES;\n- }\n- memcpy(entry->helper_name, helper, strlen(helper) + 1);\n- }\n-\n- /* Add original tuple information to flow Key */\n- if (entry->key.dl_type == ntohs(ETH_TYPE_IPV4)) {\n- if (parent != NULL) {\n- OVS_ACQUIRE_SPIN_LOCK(&(parent->lock), irql);\n- OvsCtUpdateTuple(key, &parent->key);\n- OVS_RELEASE_SPIN_LOCK(&(parent->lock), irql);\n- } else {\n- OvsCtUpdateTuple(key, &entry->key);\n- }\n- } else if (entry->key.dl_type == ntohs(ETH_TYPE_IPV6)) {\n- if (parent != NULL) {\n- OVS_ACQUIRE_SPIN_LOCK(&(parent->lock), irql);\n- OvsCtUpdateTupleV6(key, &parent->key);\n- OVS_RELEASE_SPIN_LOCK(&(parent->lock), irql);\n- } else {\n- OvsCtUpdateTupleV6(key, &entry->key);\n- }\n- }\n-\n- if (entryCreated) {\n- OvsPostCtEventEntry(entry, OVS_EVENT_CT_NEW);\n- } else if (postUpdateEvent && triggerUpdateEvent) {\n- OvsPostCtEventEntry(entry, OVS_EVENT_CT_UPDATE);\n- }\n-\n- OVS_RELEASE_SPIN_LOCK(&(entry->lock), irql);\n- return status;\n-}\n-\n-/*\n- *---------------------------------------------------------------------------\n- * OvsExecuteConntrackAction\n- * Executes Conntrack actions XXX - Add more\n- * For the Ipv4 fragments, consume the orginal fragment NBL\n- *---------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsExecuteConntrackAction(OvsForwardingContext *fwdCtx,\n- OvsFlowKey *key,\n- const PNL_ATTR a)\n-{\n- BOOLEAN commit = FALSE;\n- BOOLEAN force = FALSE;\n- BOOLEAN postUpdateEvent = FALSE;\n- UINT16 zone = 0;\n- UINT32 eventmask = 0;\n- MD_MARK *mark = NULL;\n- MD_LABELS *labels = NULL;\n- PCHAR helper = NULL;\n- NAT_ACTION_INFO natActionInfo;\n- OVS_PACKET_HDR_INFO *layers = &fwdCtx->layers;\n- NDIS_STATUS status;\n-\n- memset(&natActionInfo, 0, sizeof natActionInfo);\n- status = OvsDetectCtPacket(fwdCtx, key);\n- if (status != NDIS_STATUS_SUCCESS) {\n- return status;\n- }\n-\n- PNL_ATTR ctAttr = NULL;\n- INT left;\n-\n- NL_NESTED_FOR_EACH (ctAttr, left, a) {\n- switch(NlAttrType(ctAttr)) {\n- case OVS_CT_ATTR_ZONE:\n- zone = NlAttrGetU16(ctAttr);\n- break;\n- case OVS_CT_ATTR_COMMIT:\n- commit = TRUE;\n- break;\n- case OVS_CT_ATTR_MARK:\n- mark = NlAttrGet(ctAttr);\n- break;\n- case OVS_CT_ATTR_LABELS:\n- labels = NlAttrGet(ctAttr);\n- break;\n- case OVS_CT_ATTR_HELPER:\n- helper = NlAttrGetString(ctAttr);\n- if (helper == NULL) {\n- return NDIS_STATUS_INVALID_PARAMETER;\n- }\n- if (strcmp(\"ftp\", helper) != 0 && strcmp(\"tftp\", helper) != 0) {\n- /* Only support FTP/TFTP */\n- return NDIS_STATUS_NOT_SUPPORTED;\n- }\n- break;\n- case OVS_CT_ATTR_FORCE_COMMIT:\n- force = TRUE;\n- /* Force implicitly means commit */\n- commit = TRUE;\n- break;\n- case OVS_CT_ATTR_EVENTMASK:\n- eventmask = NlAttrGetU32(ctAttr);\n- /* Only mark and label updates are supported. */\n- if (eventmask & (1 << IPCT_MARK | 1 << IPCT_LABEL))\n- postUpdateEvent = TRUE;\n- break;\n- case OVS_CT_ATTR_NAT:\n- natActionInfo.natAction = NAT_ACTION_NONE;\n- /* Pares Nested NAT attributes. */\n- PNL_ATTR natAttr;\n- unsigned int natLeft;\n- BOOLEAN hasMinIp = FALSE;\n- BOOLEAN hasMinPort = FALSE;\n- BOOLEAN hasMaxIp = FALSE;\n- BOOLEAN hasMaxPort = FALSE;\n- NL_NESTED_FOR_EACH_UNSAFE (natAttr, natLeft, ctAttr) {\n- enum ovs_nat_attr subtype = NlAttrType(natAttr);\n- switch(subtype) {\n- case OVS_NAT_ATTR_SRC:\n- case OVS_NAT_ATTR_DST:\n- natActionInfo.natAction |=\n- ((subtype == OVS_NAT_ATTR_SRC)\n- ? NAT_ACTION_SRC : NAT_ACTION_DST);\n- break;\n- case OVS_NAT_ATTR_IP_MIN:\n- memcpy(&natActionInfo.minAddr,\n- NlAttrData(natAttr), NlAttrGetSize(natAttr));\n- hasMinIp = TRUE;\n- break;\n- case OVS_NAT_ATTR_IP_MAX:\n- memcpy(&natActionInfo.maxAddr,\n- NlAttrData(natAttr), NlAttrGetSize(natAttr));\n- hasMaxIp = TRUE;\n- break;\n- case OVS_NAT_ATTR_PROTO_MIN:\n- natActionInfo.minPort = NlAttrGetU16(natAttr);\n- hasMinPort = TRUE;\n- break;\n- case OVS_NAT_ATTR_PROTO_MAX:\n- natActionInfo.maxPort = NlAttrGetU16(natAttr);\n- hasMaxPort = TRUE;\n- break;\n- case OVS_NAT_ATTR_PERSISTENT:\n- case OVS_NAT_ATTR_PROTO_HASH:\n- case OVS_NAT_ATTR_PROTO_RANDOM:\n- break;\n- }\n- }\n- if (natActionInfo.natAction == NAT_ACTION_NONE) {\n- natActionInfo.natAction = NAT_ACTION_REVERSE;\n- }\n- if (hasMinIp && !hasMaxIp) {\n- memcpy(&natActionInfo.maxAddr,\n- &natActionInfo.minAddr,\n- sizeof(natActionInfo.maxAddr));\n- }\n- if (hasMinPort && !hasMaxPort) {\n- natActionInfo.maxPort = natActionInfo.minPort;\n- }\n- if (hasMinPort || hasMaxPort) {\n- if (natActionInfo.natAction & NAT_ACTION_SRC) {\n- natActionInfo.natAction |= NAT_ACTION_SRC_PORT;\n- } else if (natActionInfo.natAction & NAT_ACTION_DST) {\n- natActionInfo.natAction |= NAT_ACTION_DST_PORT;\n- }\n- }\n- break;\n- default:\n- OVS_LOG_TRACE(\"Invalid netlink attr type: %u\", NlAttrType(ctAttr));\n- break;\n- }\n- }\n- /* If newNbl is not allocated, use the current Nbl*/\n- status = OvsCtExecute_(fwdCtx, key, layers,\n- commit, force, zone, mark, labels, helper, &natActionInfo,\n- postUpdateEvent);\n- return status;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsConntrackEntryCleaner\n- * Runs periodically and cleans up the connection tracker\n- *----------------------------------------------------------------------------\n- */\n-VOID\n-OvsConntrackEntryCleaner(PVOID data)\n-{\n-\n- POVS_CT_THREAD_CTX context = (POVS_CT_THREAD_CTX)data;\n- PLIST_ENTRY link, next;\n- POVS_CT_ENTRY entry;\n- LOCK_STATE_EX lockState;\n- BOOLEAN success = TRUE;\n-\n- while (success) {\n- if (context->exit) {\n- break;\n- }\n-\n- /* Set the timeout for the thread and cleanup */\n- INT64 threadSleepTimeout = -CT_CLEANUP_INTERVAL;\n-\n- if (ctTotalEntries) {\n- for (UINT32 i = 0; i < CT_HASH_TABLE_SIZE; i++) {\n- NdisAcquireRWLockWrite(ovsCtBucketLock[i], &lockState, 0);\n- LIST_FORALL_SAFE(&ovsConntrackTable[i], link, next) {\n- entry = CONTAINING_RECORD(link, OVS_CT_ENTRY, link);\n- OvsCtEntryDelete(entry, FALSE);\n- }\n- NdisReleaseRWLock(ovsCtBucketLock[i], &lockState);\n- }\n- }\n- KeWaitForSingleObject(&context->event, Executive, KernelMode,\n- FALSE, (LARGE_INTEGER *)&threadSleepTimeout);\n- }\n-\n- PsTerminateSystemThread(STATUS_SUCCESS);\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsCtFlush\n- * Flushes out all Conntrack Entries that match any of the arguments\n- *----------------------------------------------------------------------------\n- */\n-static __inline NDIS_STATUS\n-OvsCtFlush(UINT16 zone, struct ovs_key_ct_tuple_ipv4 *tuple)\n-{\n- PLIST_ENTRY link, next;\n- POVS_CT_ENTRY entry;\n- LOCK_STATE_EX lockState;\n-\n- if (ctTotalEntries) {\n- for (UINT32 i = 0; i < CT_HASH_TABLE_SIZE; i++) {\n- LIST_FORALL_SAFE(&ovsConntrackTable[i], link, next) {\n- NdisAcquireRWLockWrite(ovsCtBucketLock[i], &lockState, 0);\n- entry = CONTAINING_RECORD(link, OVS_CT_ENTRY, link);\n- if (tuple) {\n- if (tuple->ipv4_proto != IPPROTO_ICMP &&\n- tuple->ipv4_src == entry->key.src.addr.ipv4_aligned &&\n- tuple->ipv4_dst == entry->key.dst.addr.ipv4_aligned &&\n- tuple->ipv4_proto == entry->key.nw_proto &&\n- tuple->src_port == entry->key.src.port &&\n- tuple->dst_port == entry->key.dst.port &&\n- (zone ? entry->key.zone == zone: TRUE)) {\n- OvsCtEntryDelete(entry, TRUE);\n- } else if (tuple->ipv4_src == entry->key.src.addr.ipv4_aligned &&\n- tuple->ipv4_dst == entry->key.dst.addr.ipv4_aligned &&\n- tuple->ipv4_proto == entry->key.nw_proto &&\n- tuple->src_port == entry->key.src.icmp_type &&\n- tuple->dst_port == entry->key.src.icmp_code &&\n- (zone ? entry->key.zone == zone: TRUE)) {\n- OvsCtEntryDelete(entry, TRUE);\n- }\n- } else if (!zone || zone == entry->key.zone) {\n- OvsCtEntryDelete(entry, TRUE);\n- }\n- NdisReleaseRWLock(ovsCtBucketLock[i], &lockState);\n- }\n- }\n- }\n-\n- OvsNatFlush(zone);\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-NTSTATUS\n-OvsCtDeleteCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen)\n-{\n- POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;\n- POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer;\n- PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);\n- PNL_ATTR ctAttrs[__CTA_MAX];\n- UINT32 attrOffset = NLMSG_HDRLEN + NF_GEN_MSG_HDRLEN + OVS_HDRLEN;\n- NL_ERROR nlError = NL_ERROR_SUCCESS;\n- NTSTATUS status;\n- UINT16 zone = 0;\n- struct ovs_key_ct_tuple_ipv4 *ct_tuple = NULL;\n- NL_BUFFER nlBuf;\n- UINT16 nlmsgType;\n- PNL_MSG_HDR nlMsg;\n-\n- static const NL_POLICY ctAttrPolicy[] = {\n- [CTA_TUPLE_ORIG] = {.type = NL_A_NESTED, .optional = TRUE},\n- [CTA_ZONE] = {.type = NL_A_BE16, .optional = TRUE },\n- };\n-\n- if ((NlAttrParse(nlMsgHdr, attrOffset, NlNfMsgAttrsLen(nlMsgHdr),\n- ctAttrPolicy, ARRAY_SIZE(ctAttrPolicy),\n- ctAttrs, ARRAY_SIZE(ctAttrs)))\n- != TRUE) {\n- OVS_LOG_ERROR(\"Ct attr parsing failed for msg: %p\", nlMsgHdr);\n- status = STATUS_INVALID_PARAMETER;\n- goto done;\n- }\n-\n- if (ctAttrs[CTA_ZONE]) {\n- zone = ntohs(NlAttrGetU16(ctAttrs[CTA_ZONE]));\n- }\n-\n- if (ctAttrs[CTA_TUPLE_ORIG]) {\n- ct_tuple = OvsAllocateMemoryWithTag(sizeof(struct ovs_key_ct_tuple_ipv4),\n- OVS_CT_POOL_TAG);\n- if (ct_tuple == NULL) {\n- status = STATUS_INSUFFICIENT_RESOURCES;\n- goto done;\n- }\n- /* Parse ct tuple. */\n- status = MapNlToCtTuple(msgIn, ctAttrs[CTA_TUPLE_ORIG], ct_tuple);\n- if (status != STATUS_SUCCESS) {\n- goto done;\n- }\n- }\n-\n- status = OvsCtFlush(zone, ct_tuple);\n- if (status == STATUS_SUCCESS) {\n- nlmsgType = (NFNL_SUBSYS_CTNETLINK << 8 | IPCTNL_MSG_CT_DELETE);\n- NlBufInit(&nlBuf,\n- usrParamsCtx->outputBuffer,\n- usrParamsCtx->outputLength);\n- if (!NlFillOvsMsgForNfGenMsg(&nlBuf, nlmsgType, NLM_F_CREATE,\n- msgIn->nlMsg.nlmsgSeq,\n- msgIn->nlMsg.nlmsgPid,\n- AF_UNSPEC,\n- msgIn->nfGenMsg.version,\n- 0)) {\n- status = STATUS_INVALID_PARAMETER;\n- }\n- nlMsg = (PNL_MSG_HDR)NlBufAt(&nlBuf, 0, 0);\n- nlMsg->nlmsgLen = NlBufSize(&nlBuf);\n- *replyLen = msgOut->nlMsg.nlmsgLen;\n- }\n-\n-done:\n- if (ct_tuple) {\n- OvsFreeMemoryWithTag(ct_tuple, OVS_CT_POOL_TAG);\n- }\n-\n- nlError = NlMapStatusToNlErr(status);\n- if (nlError != NL_ERROR_SUCCESS) {\n- POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)\n- usrParamsCtx->outputBuffer;\n-\n- ASSERT(msgError);\n- NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);\n- ASSERT(*replyLen != 0);\n- status = STATUS_SUCCESS;\n- }\n-\n- return status;\n-}\n-\n-static __inline NDIS_STATUS\n-MapNlToCtTuple(POVS_MESSAGE msgIn, PNL_ATTR ctAttr,\n- struct ovs_key_ct_tuple_ipv4 *ct_tuple) {\n-\n- PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);\n- PNL_ATTR ctTupleAttrs[__CTA_MAX];\n- UINT32 attrOffset;\n- static const NL_POLICY ctTuplePolicy[] = {\n- [CTA_TUPLE_IP] = { .type = NL_A_NESTED, .optional = FALSE },\n- [CTA_TUPLE_PROTO] = { .type = NL_A_NESTED, .optional = FALSE},\n- };\n-\n- static const NL_POLICY ctTupleIpPolicy[] = {\n- [CTA_IP_V4_SRC] = { .type = NL_A_BE32, .optional = TRUE },\n- [CTA_IP_V4_DST] = { .type = NL_A_BE32, .optional = TRUE },\n- [CTA_IP_V6_SRC] = { .type = NL_A_BE32,.optional = TRUE },\n- [CTA_IP_V6_DST] = { .type = NL_A_BE32,.optional = TRUE },\n- };\n-\n- static const NL_POLICY ctTupleProtoPolicy[] = {\n- [CTA_PROTO_NUM] = { .type = NL_A_U8, .optional = FALSE },\n- [CTA_PROTO_SRC_PORT] = { .type = NL_A_BE16, .optional = TRUE },\n- [CTA_PROTO_DST_PORT] = { .type = NL_A_BE16, .optional = TRUE },\n- [CTA_PROTO_ICMP_TYPE] = { .type = NL_A_U8, .optional = TRUE },\n- [CTA_PROTO_ICMP_CODE] = { .type = NL_A_U8, .optional = TRUE },\n- [CTA_PROTO_ICMPV6_ID] = { .type = NL_A_BE16,.optional = TRUE },\n- [CTA_PROTO_ICMPV6_TYPE] = { .type = NL_A_U8,.optional = TRUE },\n- [CTA_PROTO_ICMPV6_CODE] = { .type = NL_A_U8,.optional = TRUE },\n- };\n-\n- if (!ctAttr) {\n- return STATUS_INVALID_PARAMETER;\n- }\n-\n- attrOffset = (UINT32)((PCHAR) ctAttr - (PCHAR)nlMsgHdr);\n- if ((NlAttrParseNested(nlMsgHdr, attrOffset, NlAttrLen(ctAttr),\n- ctTuplePolicy, ARRAY_SIZE(ctTuplePolicy),\n- ctTupleAttrs, ARRAY_SIZE(ctTupleAttrs)))\n- != TRUE) {\n- OVS_LOG_ERROR(\"CTA_TUPLE attr parsing failed for msg: %p\", nlMsgHdr);\n- return STATUS_INVALID_PARAMETER;\n- }\n-\n- if (ctTupleAttrs[CTA_TUPLE_IP]) {\n- PNL_ATTR ctTupleIpAttrs[__CTA_MAX];\n- attrOffset = (UINT32)((PCHAR) ctTupleAttrs[CTA_TUPLE_IP] - (PCHAR)nlMsgHdr);\n- if ((NlAttrParseNested(nlMsgHdr, attrOffset, NlAttrLen(ctTupleAttrs[CTA_TUPLE_IP]),\n- ctTupleIpPolicy, ARRAY_SIZE(ctTupleIpPolicy),\n- ctTupleIpAttrs, ARRAY_SIZE(ctTupleIpAttrs)))\n- != TRUE) {\n- OVS_LOG_ERROR(\"CTA_TUPLE_IP attr parsing failed for msg: %p\", nlMsgHdr);\n- return STATUS_INVALID_PARAMETER;\n- }\n-\n- if (ctTupleIpAttrs[CTA_IP_V4_SRC] && ctTupleIpAttrs[CTA_IP_V4_DST]) {\n- ct_tuple->ipv4_src = NlAttrGetU32(ctTupleIpAttrs[CTA_IP_V4_SRC]);\n- ct_tuple->ipv4_dst = NlAttrGetU32(ctTupleIpAttrs[CTA_IP_V4_DST]);\n- }\n- }\n-\n- if (ctTupleAttrs[CTA_TUPLE_PROTO]) {\n- PNL_ATTR ctTupleProtoAttrs[__CTA_MAX];\n- attrOffset = (UINT32)((PCHAR) ctTupleAttrs[CTA_TUPLE_PROTO] - (PCHAR)nlMsgHdr);\n- if ((NlAttrParseNested(nlMsgHdr, attrOffset, NlAttrLen(ctTupleAttrs[CTA_TUPLE_PROTO]),\n- ctTupleProtoPolicy, ARRAY_SIZE(ctTupleProtoPolicy),\n- ctTupleProtoAttrs, ARRAY_SIZE(ctTupleProtoAttrs)))\n- != TRUE) {\n- OVS_LOG_ERROR(\"CTA_TUPLE_PROTO attr parsing failed for msg: %p\", nlMsgHdr);\n- return STATUS_INVALID_PARAMETER;\n- }\n-\n- if (ctTupleProtoAttrs[CTA_PROTO_NUM]) {\n- ct_tuple->ipv4_proto = NlAttrGetU8 (ctTupleProtoAttrs[CTA_PROTO_NUM]);\n- if (ctTupleProtoAttrs[CTA_PROTO_SRC_PORT] && ctTupleProtoAttrs[CTA_PROTO_DST_PORT]) {\n- ct_tuple->src_port = NlAttrGetU16(ctTupleProtoAttrs[CTA_PROTO_SRC_PORT]);\n- ct_tuple->dst_port = NlAttrGetU16(ctTupleProtoAttrs[CTA_PROTO_DST_PORT]);\n- } else if (ctTupleProtoAttrs[CTA_PROTO_ICMP_TYPE] &&\n- ctTupleProtoAttrs[CTA_PROTO_ICMP_CODE] ) {\n- ct_tuple->src_port = NlAttrGetU8(ctTupleProtoAttrs[CTA_PROTO_ICMP_TYPE]);\n- ct_tuple->dst_port = NlAttrGetU8(ctTupleProtoAttrs[CTA_PROTO_ICMP_CODE]);\n- } else if (ctTupleProtoAttrs[CTA_PROTO_ICMPV6_TYPE] &&\n- ctTupleProtoAttrs[CTA_PROTO_ICMPV6_CODE] ) {\n- ct_tuple->src_port = NlAttrGetU8(ctTupleProtoAttrs[CTA_PROTO_ICMPV6_TYPE]);\n- ct_tuple->dst_port = NlAttrGetU8(ctTupleProtoAttrs[CTA_PROTO_ICMPV6_CODE]);\n- }\n- }\n- }\n-\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-static __inline NDIS_STATUS\n-MapIpTupleToNl(PNL_BUFFER nlBuf, OVS_CT_KEY *key)\n-{\n- NDIS_STATUS status = NDIS_STATUS_SUCCESS;\n- UINT32 offset = 0;\n-\n- offset = NlMsgStartNested(nlBuf, CTA_TUPLE_IP);\n- if (!offset) {\n- return NDIS_STATUS_FAILURE;\n- }\n-\n- if (key->dl_type == ntohs(ETH_TYPE_IPV4)) {\n- if (!NlMsgPutTailU32(nlBuf, CTA_IP_V4_SRC, key->src.addr.ipv4)) {\n- status = NDIS_STATUS_FAILURE;\n- goto done;\n- }\n- if (!NlMsgPutTailU32(nlBuf, CTA_IP_V4_DST, key->dst.addr.ipv4)) {\n- status = NDIS_STATUS_FAILURE;\n- goto done;\n- }\n- } else if (key->dl_type == ntohs(ETH_TYPE_IPV6)) {\n- if (!NlMsgPutTailUnspec(nlBuf, CTA_IP_V6_SRC,\n- (PCHAR)(&key->src.addr.ipv6),\n- sizeof(key->src.addr.ipv6))) {\n- status = NDIS_STATUS_FAILURE;\n- goto done;\n- }\n- if (!NlMsgPutTailUnspec(nlBuf, CTA_IP_V6_DST,\n- (PCHAR)(&key->dst.addr.ipv6),\n- sizeof(key->dst.addr.ipv6))) {\n- status = NDIS_STATUS_FAILURE;\n- goto done;\n- }\n- }\n-\n-done:\n- NlMsgEndNested(nlBuf, offset);\n- return status;\n-}\n-\n-static __inline NDIS_STATUS\n-MapProtoTupleToNl(PNL_BUFFER nlBuf, OVS_CT_KEY *key)\n-{\n- NDIS_STATUS status = NDIS_STATUS_SUCCESS;\n- UINT32 offset = 0;\n-\n- offset = NlMsgStartNested(nlBuf, CTA_TUPLE_PROTO);\n- if (!offset) {\n- return NDIS_STATUS_FAILURE;\n- }\n-\n- if (!NlMsgPutTailU8(nlBuf, CTA_PROTO_NUM, key->nw_proto)) {\n- status = NDIS_STATUS_FAILURE;\n- goto done;\n- }\n-\n- if (key->dl_type == ntohs(ETH_TYPE_IPV4)\n- || key->dl_type == ntohs(ETH_TYPE_IPV6)) {\n- /* ICMP and ICMPv6 Type, Code and ID are currently not tracked */\n- if (key->nw_proto == IPPROTO_ICMP) {\n- if (!NlMsgPutTailU16(nlBuf, CTA_PROTO_ICMP_ID,\n- htons(key->src.icmp_id))) {\n- status = NDIS_STATUS_FAILURE;\n- goto done;\n- }\n- if (!NlMsgPutTailU8(nlBuf, CTA_PROTO_ICMP_TYPE,\n- key->src.icmp_type)) {\n- status = NDIS_STATUS_FAILURE;\n- goto done;\n- }\n- if (!NlMsgPutTailU8(nlBuf, CTA_PROTO_ICMP_CODE,\n- key->src.icmp_code)) {\n- status = NDIS_STATUS_FAILURE;\n- goto done;\n- }\n- } else if (key->nw_proto == IPPROTO_ICMPV6) {\n- if (!NlMsgPutTailU16(nlBuf, CTA_PROTO_ICMPV6_ID, htons(key->src.icmp_id))) {\n- status = NDIS_STATUS_FAILURE;\n- goto done;\n- }\n- if (!NlMsgPutTailU8(nlBuf, CTA_PROTO_ICMPV6_TYPE, key->src.icmp_type)) {\n- status = NDIS_STATUS_FAILURE;\n- goto done;\n- }\n- if (!NlMsgPutTailU8(nlBuf, CTA_PROTO_ICMPV6_CODE, key->src.icmp_code)) {\n- status = NDIS_STATUS_FAILURE;\n- goto done;\n- }\n- } else if (key->nw_proto == IPPROTO_TCP\n- || key->nw_proto == IPPROTO_UDP) {\n- if (!NlMsgPutTailU16(nlBuf, CTA_PROTO_SRC_PORT,\n- key->src.port)) {\n- status = NDIS_STATUS_FAILURE;\n- goto done;\n- }\n- if (!NlMsgPutTailU16(nlBuf, CTA_PROTO_DST_PORT,\n- key->dst.port)) {\n- status = NDIS_STATUS_FAILURE;\n- goto done;\n- }\n- }\n- }\n-\n-done:\n- NlMsgEndNested(nlBuf, offset);\n- return status;\n-}\n-\n-static __inline NDIS_STATUS\n-MapCtKeyTupleToNl(PNL_BUFFER nlBuf,\n- UINT16 tupleType,\n- OVS_CT_KEY *key)\n-{\n- NDIS_STATUS status = NDIS_STATUS_SUCCESS;\n- UINT32 offset = 0;\n-\n- offset = NlMsgStartNested(nlBuf, tupleType);\n- if (!offset) {\n- return NDIS_STATUS_FAILURE;\n- }\n-\n- status = MapIpTupleToNl(nlBuf, key);\n- if (status != NDIS_STATUS_SUCCESS) {\n- goto done;\n- }\n-\n- status = MapProtoTupleToNl(nlBuf, key);\n- if (status != NDIS_STATUS_SUCCESS) {\n- goto done;\n- }\n-\n-done:\n- NlMsgEndNested(nlBuf, offset);\n- return status;\n-}\n-\n-static __inline NDIS_STATUS\n-MapCtCounterToNl(PNL_BUFFER nlBuf,\n- UINT16 counterType,\n- OVS_CT_KEY *key)\n-{\n- NDIS_STATUS status = NDIS_STATUS_SUCCESS;\n- UINT32 offset = 0;\n-\n- offset = NlMsgStartNested(nlBuf, counterType);\n- if (!offset) {\n- return NDIS_STATUS_FAILURE;\n- }\n-\n- if (!NlMsgPutTailU64(nlBuf, CTA_COUNTERS_PACKETS,\n- htonll(key->packetCount))) {\n- status = NDIS_STATUS_FAILURE;\n- goto done;\n- }\n-\n- if (!NlMsgPutTailU64(nlBuf, CTA_COUNTERS_BYTES,\n- htonll(key->byteCount))) {\n- status = NDIS_STATUS_FAILURE;\n- goto done;\n- }\n-\n-done:\n- NlMsgEndNested(nlBuf, offset);\n- return status;\n-}\n-\n-/* Userspace expects system time to be Unix timestamp in Nano Seconds */\n-static __inline unsigned\n-WindowsTickToUnixSeconds(long long windowsTicks)\n-{\n- /*\n- * Windows epoch starts 1601-01-01T00:00:00Z. It's 11644473600 seconds\n- * before the UNIX/Linux epoch (1970-01-01T00:00:00Z). Windows ticks are\n- * in 100 nanoseconds\n- */\n- return (unsigned)((windowsTicks / WINDOWS_TICK\n- - SEC_TO_UNIX_EPOCH));\n-}\n-\n-NTSTATUS\n-OvsCreateNlMsgFromCtEntry(POVS_CT_ENTRY entry,\n- PVOID outBuffer,\n- UINT32 outBufLen,\n- UINT8 eventType,\n- UINT32 nlmsgSeq,\n- UINT32 nlmsgPid,\n- UINT8 nfGenVersion,\n- UINT32 dpIfIndex)\n-{\n- NL_BUFFER nlBuf;\n- BOOLEAN ok;\n- PNL_MSG_HDR nlMsg;\n- UINT32 timeout;\n- NDIS_STATUS status;\n- UINT64 currentTime, expiration;\n- UINT16 nlmsgType;\n- UINT16 nlmsgFlags = NLM_F_CREATE;\n- NdisGetCurrentSystemTime((LARGE_INTEGER *)¤tTime);\n- UINT8 nfgenFamily = 0;\n-\n- if (entry->key.dl_type == htons(ETH_TYPE_IPV4)) {\n- nfgenFamily = AF_INET;\n- } else if (entry->key.dl_type == htons(ETH_TYPE_IPV6)) {\n- nfgenFamily = AF_INET6;\n- }\n-\n- NlBufInit(&nlBuf, outBuffer, outBufLen);\n- /* Mimic netfilter */\n- if (eventType == OVS_EVENT_CT_NEW || eventType == OVS_EVENT_CT_UPDATE) {\n- nlmsgType = (UINT16) (NFNL_SUBSYS_CTNETLINK << 8 | IPCTNL_MSG_CT_NEW);\n- } else if (eventType == OVS_EVENT_CT_DELETE) {\n- nlmsgType = (UINT16) (NFNL_SUBSYS_CTNETLINK << 8 | IPCTNL_MSG_CT_DELETE);\n- } else {\n- return STATUS_INVALID_PARAMETER;\n- }\n-\n- if (eventType == OVS_EVENT_CT_UPDATE) {\n- /* In netlink-conntrack.c IPCTNL_MSG_CT_NEW msg type is used to\n- * differentiate between OVS_EVENT_CT_NEW and OVS_EVENT_CT_UPDATE\n- * events based on nlmsgFlags, unset it to notify an update event.\n- */\n- nlmsgFlags = 0;\n- }\n- ok = NlFillOvsMsgForNfGenMsg(&nlBuf, nlmsgType, nlmsgFlags,\n- nlmsgSeq, nlmsgPid, nfgenFamily,\n- nfGenVersion, dpIfIndex);\n- if (!ok) {\n- return STATUS_INVALID_BUFFER_SIZE;\n- }\n-\n- status = MapCtKeyTupleToNl(&nlBuf, CTA_TUPLE_ORIG, &entry->key);\n- if (status != NDIS_STATUS_SUCCESS) {\n- return STATUS_UNSUCCESSFUL;\n- }\n-\n- status = MapCtKeyTupleToNl(&nlBuf, CTA_TUPLE_REPLY, &entry->rev_key);\n- if (status != NDIS_STATUS_SUCCESS) {\n- return STATUS_UNSUCCESSFUL;\n- }\n-\n- status = MapCtCounterToNl(&nlBuf, CTA_COUNTERS_ORIG, &entry->key);\n- if (status != NDIS_STATUS_SUCCESS) {\n- return STATUS_UNSUCCESSFUL;\n- }\n-\n- status = MapCtCounterToNl(&nlBuf, CTA_COUNTERS_REPLY, &entry->rev_key);\n- if (status != NDIS_STATUS_SUCCESS) {\n- return STATUS_UNSUCCESSFUL;\n- }\n-\n- if (entry->key.zone) {\n- if (!NlMsgPutTailU16(&nlBuf, CTA_ZONE, htons(entry->key.zone))) {\n- return STATUS_INVALID_BUFFER_SIZE;\n- }\n- }\n-\n- if (entry->mark) {\n- if (!NlMsgPutTailU32(&nlBuf, CTA_MARK, htonl(entry->mark))) {\n- return STATUS_INVALID_BUFFER_SIZE;\n- }\n- }\n-\n- if (entry->labels.ct_labels) {\n- ok = NlMsgPutTailUnspec(&nlBuf, CTA_LABELS,\n- (PCHAR)(&entry->labels),\n- sizeof(entry->labels));\n- if (!ok) {\n- return STATUS_INVALID_BUFFER_SIZE;\n- }\n- }\n-\n- if (entry->expiration > currentTime) {\n- expiration = entry->expiration - currentTime;\n- timeout = (UINT32) (expiration / CT_INTERVAL_SEC);\n- if (!NlMsgPutTailU32(&nlBuf, CTA_TIMEOUT, htonl(timeout))) {\n- return STATUS_INVALID_BUFFER_SIZE;\n- }\n- }\n-\n- if (entry->key.nw_proto == IPPROTO_TCP) {\n- /* Add ProtoInfo for TCP */\n- UINT32 offset;\n- offset = NlMsgStartNested(&nlBuf, CTA_PROTOINFO);\n- if (!offset) {\n- return NDIS_STATUS_FAILURE;\n- }\n-\n- status = OvsCtMapTcpProtoInfoToNl(&nlBuf, entry);\n- NlMsgEndNested(&nlBuf, offset);\n- if (status != NDIS_STATUS_SUCCESS) {\n- return STATUS_UNSUCCESSFUL;\n- }\n- }\n-\n- if (entry->helper_name) {\n- UINT32 offset;\n- offset = NlMsgStartNested(&nlBuf, CTA_HELP);\n- if (!offset) {\n- return NDIS_STATUS_FAILURE;\n- }\n- if (!NlMsgPutTailString(&nlBuf, CTA_HELP_NAME, entry->helper_name)) {\n- return STATUS_INVALID_BUFFER_SIZE;\n- }\n- NlMsgEndNested(&nlBuf, offset);\n- }\n-\n- if (entry->parent) {\n- status = MapCtKeyTupleToNl(&nlBuf, CTA_TUPLE_MASTER,\n- &((POVS_CT_ENTRY)entry->parent)->key);\n- if (status != NDIS_STATUS_SUCCESS) {\n- return STATUS_UNSUCCESSFUL;\n- }\n- }\n-\n- /* CTA_STATUS is required but not implemented. Default to 0 */\n- if (!NlMsgPutTailU32(&nlBuf, CTA_STATUS, 0)) {\n- return STATUS_INVALID_BUFFER_SIZE;\n- }\n-\n- /* Mimic netfilter - nf_conntrack_netlink.c:\n- *\n- * int ctnetlink_dump_id(struct sk_buff *skb, const struct nf_conn *ct) {\n- * NLA_PUT_BE32(skb, CTA_ID, htonl((unsigned long)ct));\n- * return 0;\n- * }\n- *\n- */\n- if(!NlMsgPutTailU32(&nlBuf, CTA_ID, htonl((UINT32) entry))) {\n- return STATUS_INVALID_BUFFER_SIZE;\n- }\n-\n- if (entry->timestampStart) {\n- UINT32 offset;\n- offset = NlMsgStartNested(&nlBuf, CTA_TIMESTAMP);\n- if (!offset) {\n- return NDIS_STATUS_FAILURE;\n- }\n- UINT64 start;\n- start = WindowsTickToUnixSeconds(entry->timestampStart);\n- start = start * SEC_TO_NANOSEC;\n- if (!NlMsgPutTailU64(&nlBuf, CTA_TIMESTAMP_START, htonll(start))) {\n- NlMsgEndNested(&nlBuf, offset);\n- return STATUS_INVALID_BUFFER_SIZE;\n- }\n-\n- NlMsgEndNested(&nlBuf, offset);\n- }\n-\n- nlMsg = (PNL_MSG_HDR)NlBufAt(&nlBuf, 0, 0);\n- nlMsg->nlmsgLen = NlBufSize(&nlBuf);\n- return STATUS_SUCCESS;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsCtDumpCmdHandler --\n- * Handler for IPCTNL_MSG_CT_GET command.\n- *\n- * XXX - Try to consolidate dump handler patterns around dumpState usage\n- * The following dumpHandler is similar to one vport.c uses\n- *----------------------------------------------------------------------------\n-*/\n-NTSTATUS\n-OvsCtDumpCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen)\n-{\n- NTSTATUS rc;\n- /* Setup Dump Start if it's OVS_WRITE_DEV_OP and return */\n- if (usrParamsCtx->devOp == OVS_WRITE_DEV_OP) {\n- *replyLen = 0;\n- OvsSetupDumpStart(usrParamsCtx);\n- return STATUS_SUCCESS;\n- }\n-\n- POVS_OPEN_INSTANCE instance =\n- (POVS_OPEN_INSTANCE)usrParamsCtx->ovsInstance;\n- POVS_MESSAGE msgIn;\n-\n- ASSERT(usrParamsCtx->devOp == OVS_READ_DEV_OP);\n- if (instance->dumpState.ovsMsg == NULL) {\n- ASSERT(FALSE);\n- return STATUS_INVALID_DEVICE_STATE;\n- }\n-\n- /* Output buffer has been validated while validating read dev op. */\n- ASSERT(usrParamsCtx->outputBuffer != NULL);\n- msgIn = instance->dumpState.ovsMsg;\n- UINT32 inBucket = instance->dumpState.index[0];\n- UINT32 inIndex = instance->dumpState.index[1];\n- UINT32 i = CT_HASH_TABLE_SIZE;\n- UINT32 outIndex = 0;\n- KIRQL irql = KeGetCurrentIrql();\n- LOCK_STATE_EX lockStateTable;\n-\n- if (ctTotalEntries) {\n- for (i = inBucket; i < CT_HASH_TABLE_SIZE; i++) {\n- PLIST_ENTRY head, link;\n- NdisAcquireRWLockRead(ovsCtBucketLock[i], &lockStateTable, 0);\n- head = &ovsConntrackTable[i];\n- POVS_CT_ENTRY entry = NULL;\n-\n- outIndex = 0;\n- LIST_FORALL(head, link) {\n- /*\n- * if one or more dumps were previously done on this same\n- * bucket, inIndex will be > 0, so we'll need to reply with\n- * the inIndex + 1 ct-entry from the bucket.\n- */\n- if (outIndex >= inIndex) {\n- entry = CONTAINING_RECORD(link, OVS_CT_ENTRY, link);\n- OVS_ACQUIRE_SPIN_LOCK(&(entry->lock), irql);\n- rc = OvsCreateNlMsgFromCtEntry(entry,\n- usrParamsCtx->outputBuffer,\n- usrParamsCtx->outputLength,\n- OVS_EVENT_CT_NEW,\n- msgIn->nlMsg.nlmsgSeq,\n- msgIn->nlMsg.nlmsgPid,\n- msgIn->nfGenMsg.version,\n- 0);\n- OVS_RELEASE_SPIN_LOCK(&(entry->lock), irql);\n- if (rc != NDIS_STATUS_SUCCESS) {\n- NdisReleaseRWLock(ovsCtBucketLock[i], &lockStateTable);\n- return STATUS_UNSUCCESSFUL;\n- }\n-\n- ++outIndex;\n- break;\n- }\n-\n- ++outIndex;\n- }\n- NdisReleaseRWLock(ovsCtBucketLock[i], &lockStateTable);\n- if (entry) {\n- break;\n- }\n-\n- /*\n- * if no ct-entry was found above, check the next bucket, beginning\n- * with the first (i.e. index 0) elem from within that bucket\n- */\n- inIndex = 0;\n- }\n- }\n- instance->dumpState.index[0] = i;\n- instance->dumpState.index[1] = outIndex;\n- /* if i < CT_HASH_TABLE_SIZE => entry was found */\n- if (i < CT_HASH_TABLE_SIZE) {\n- POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer;\n- *replyLen = msgOut->nlMsg.nlmsgLen;\n- } else {\n- /* if i >= CT_HASH_TABLE_SIZE => entry was not found => dump done */\n- *replyLen = 0;\n- FreeUserDumpState(instance);\n- }\n-\n- return STATUS_SUCCESS;\n-}\n-\n-static NTSTATUS\n-OvsCreateNlMsgFromCtLimit(POVS_MESSAGE msgIn,\n- PVOID outBuffer,\n- UINT32 outBufLen,\n- PCHAR attr,\n- UINT32 numAttrs,\n- int dpIfIndex)\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n- NL_BUFFER nlBuffer;\n- PNL_MSG_HDR nlMsg;\n- PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);\n-\n- NlBufInit(&nlBuffer, outBuffer, outBufLen);\n-\n- if (!NlFillOvsMsg(&nlBuffer, msgIn->nlMsg.nlmsgType, NLM_F_MULTI,\n- msgIn->nlMsg.nlmsgSeq, msgIn->nlMsg.nlmsgPid,\n- msgIn->genlMsg.cmd, msgIn->genlMsg.version,\n- dpIfIndex)) {\n- return STATUS_INVALID_BUFFER_SIZE;\n- }\n-\n- if (genlMsgHdr->cmd == OVS_CT_LIMIT_CMD_GET && numAttrs) {\n- POVS_CT_ZONE_LIMIT zoneLimitAttr = (POVS_CT_ZONE_LIMIT) attr;\n- UINT32 offset = NlMsgStartNested(&nlBuffer, OVS_CT_LIMIT_ATTR_ZONE_LIMIT);\n- if (!offset) {\n- /* Starting the nested attribute failed. */\n- status = STATUS_INVALID_BUFFER_SIZE;\n- goto done;\n- }\n-\n- /* Insert OVS_CT_ZONE_LIMIT attributes.*/\n- for (UINT32 i = 0; i < numAttrs; i++) {\n- if (zoneLimitAttr) {\n- zoneLimitAttr->limit = zoneInfo[zoneLimitAttr->zone_id].limit;\n- zoneLimitAttr->count = zoneInfo[zoneLimitAttr->zone_id].entries;\n- if (zoneLimitAttr->zone_id == -1) {\n- zoneLimitAttr->limit = defaultCtLimit;\n- }\n- NlMsgPutTail(&nlBuffer, (const PCHAR)zoneLimitAttr,\n- sizeof(OVS_CT_ZONE_LIMIT));\n- } else {\n- status = STATUS_INVALID_PARAMETER;\n- break;\n- }\n- zoneLimitAttr = (POVS_CT_ZONE_LIMIT)((PCHAR) zoneLimitAttr +\n- sizeof(OVS_CT_ZONE_LIMIT));\n- }\n- NlMsgEndNested(&nlBuffer, offset);\n- }\n-\n-done:\n- nlMsg = (PNL_MSG_HDR)NlBufAt(&nlBuffer, 0, 0);\n- nlMsg->nlmsgLen = NlBufSize(&nlBuffer);\n-\n- return status;\n-}\n-\n-NTSTATUS\n-OvsCtLimitHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen)\n-{\n- NTSTATUS status;\n- POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;\n- POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer;\n- PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);\n- PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);\n- POVS_HDR ovsHdr = &(msgIn->ovsHdr);\n- PCHAR attr = NULL;\n- UINT32 numAttrs = 0;\n- UINT32 attrOffset = NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN;\n-\n- static const NL_POLICY ovsCtLimitPolicy[] = {\n- [OVS_CT_LIMIT_ATTR_ZONE_LIMIT] = { .type = NL_A_NESTED, .optional = TRUE }\n- };\n- PNL_ATTR nlAttrs[ARRAY_SIZE(ovsCtLimitPolicy)];\n-\n- if ((NlAttrParse(nlMsgHdr, attrOffset, NlMsgAttrsLen(nlMsgHdr),\n- ovsCtLimitPolicy, ARRAY_SIZE(ovsCtLimitPolicy),\n- nlAttrs, ARRAY_SIZE(nlAttrs)))\n- != TRUE) {\n- OVS_LOG_ERROR(\"Attr Parsing failed for msg: %p\", nlMsgHdr);\n- return STATUS_INVALID_PARAMETER;\n- }\n-\n- if (nlAttrs[OVS_CT_LIMIT_ATTR_ZONE_LIMIT]) {\n- numAttrs = NlAttrGetSize(nlAttrs[OVS_CT_LIMIT_ATTR_ZONE_LIMIT])/sizeof(OVS_CT_ZONE_LIMIT);\n- attr = NlAttrGet(nlAttrs[OVS_CT_LIMIT_ATTR_ZONE_LIMIT]);\n- }\n-\n- if (genlMsgHdr->cmd == OVS_CT_LIMIT_CMD_SET ||\n- genlMsgHdr->cmd == OVS_CT_LIMIT_CMD_DEL) {\n- POVS_CT_ZONE_LIMIT zoneLimitAttr = (POVS_CT_ZONE_LIMIT)attr;\n- for (UINT32 i = 0; i < numAttrs; i++) {\n- /* Parse zone limit attributes. */\n- if (zoneLimitAttr) {\n- if (genlMsgHdr->cmd == OVS_CT_LIMIT_CMD_DEL) {\n- zoneLimitAttr->limit = CT_MAX_ENTRIES;\n- }\n- OvsCtSetZoneLimit(zoneLimitAttr->zone_id, zoneLimitAttr->limit);\n- } else {\n- OVS_LOG_ERROR(\"Failed to get zone limit attribute at index(%u),\"\n- \" numAttrs(%u)\", i, numAttrs);\n- return STATUS_INVALID_PARAMETER;\n- }\n- zoneLimitAttr = (POVS_CT_ZONE_LIMIT)((PCHAR) zoneLimitAttr +\n- sizeof(OVS_CT_ZONE_LIMIT));\n- }\n- }\n-\n- /* Output buffer has been validated while validating transact dev op. */\n- ASSERT(msgOut != NULL && usrParamsCtx->outputLength >= sizeof *msgOut);\n- status = OvsCreateNlMsgFromCtLimit(msgIn, msgOut,\n- usrParamsCtx->outputLength,\n- attr, numAttrs, ovsHdr->dp_ifindex);\n- *replyLen = msgOut->nlMsg.nlmsgLen;\n-\n- return status;\n-}\n-\n-#pragma warning(pop)\ndiff --git a/datapath-windows/ovsext/Conntrack.h b/datapath-windows/ovsext/Conntrack.h\ndeleted file mode 100644\nindex deb51c0bc..000000000\n--- a/datapath-windows/ovsext/Conntrack.h\n+++ /dev/null\n@@ -1,233 +0,0 @@\n-/*\n- * Copyright (c) 2015, 2016 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#ifndef __OVS_CONNTRACK_H_\n-#define __OVS_CONNTRACK_H_ 1\n-\n-#include \"precomp.h\"\n-#include \"Actions.h\"\n-#include \"Debug.h\"\n-#include \"Flow.h\"\n-#include <stddef.h>\n-\n-#ifdef OVS_DBG_MOD\n-#undef OVS_DBG_MOD\n-#endif\n-#define OVS_DBG_MOD OVS_DBG_CONTRK\n-\n-struct ct_addr {\n- union {\n- ovs_be32 ipv4;\n- struct in6_addr ipv6;\n- uint32_t ipv4_aligned;\n- struct in6_addr ipv6_aligned;\n- };\n-};\n-\n-struct ct_endpoint {\n- struct ct_addr addr;\n- union {\n- struct {\n- ovs_be16 port;\n- uint16 pad_port;\n- };\n- struct {\n- ovs_be16 icmp_id;\n- uint8_t icmp_type;\n- uint8_t icmp_code;\n- };\n- };\n-};\n-\n-typedef enum CT_UPDATE_RES {\n- CT_UPDATE_INVALID,\n- CT_UPDATE_VALID,\n- CT_UPDATE_NEW,\n- CT_UPDATE_VALID_NEW,\n-} CT_UPDATE_RES;\n-\n-/* Metadata mark for masked write to conntrack mark */\n-typedef struct MD_MARK {\n- UINT32 value;\n- UINT32 mask;\n-} MD_MARK;\n-\n-/* Metadata label for masked write to conntrack label. */\n-typedef struct MD_LABELS {\n- struct ovs_key_ct_labels value;\n- struct ovs_key_ct_labels mask;\n-} MD_LABELS;\n-\n-typedef enum _NAT_ACTION {\n- NAT_ACTION_NONE = 0,\n- NAT_ACTION_REVERSE = 1 << 0,\n- NAT_ACTION_SRC = 1 << 1,\n- NAT_ACTION_SRC_PORT = 1 << 2,\n- NAT_ACTION_DST = 1 << 3,\n- NAT_ACTION_DST_PORT = 1 << 4,\n-} NAT_ACTION;\n-\n-typedef enum _CT_HELPER_METHOD {\n- CT_HELPER_NONE = 0,\n- CT_HELPER_FTP = 1,\n- CT_HELPER_TFTP = 2,\n-} CT_HELPER_METHOD;\n-\n-typedef struct _OVS_CT_KEY {\n- struct ct_endpoint src;\n- struct ct_endpoint dst;\n- UINT16 dl_type;\n- UINT8 nw_proto;\n- UINT16 zone;\n- UINT64 packetCount;\n- UINT64 byteCount;\n-} OVS_CT_KEY, *POVS_CT_KEY;\n-\n-typedef struct _NAT_ACTION_INFO {\n- struct ct_addr minAddr;\n- struct ct_addr maxAddr;\n- uint16_t minPort;\n- uint16_t maxPort;\n- uint16_t natAction;\n-} NAT_ACTION_INFO, *PNAT_ACTION_INFO;\n-\n-typedef struct OVS_CT_ENTRY {\n- NDIS_SPIN_LOCK lock; /* Protects OVS_CT_ENTRY. */\n- OVS_CT_KEY key;\n- OVS_CT_KEY rev_key;\n- UINT64 expiration;\n- LIST_ENTRY link;\n- UINT32 mark;\n- UINT64 timestampStart;\n- struct ovs_key_ct_labels labels;\n- NAT_ACTION_INFO natInfo;\n- PVOID parent; /* Points to main connection */\n- PCHAR helper_name;\n-} OVS_CT_ENTRY, *POVS_CT_ENTRY;\n-\n-typedef struct OVS_CT_REL_ENTRY {\n- OVS_CT_KEY key;\n- POVS_CT_ENTRY parent;\n- UINT64 expiration;\n- LIST_ENTRY link;\n-} OVS_CT_REL_ENTRY, *POVS_CT_REL_ENTRY;\n-\n-typedef struct _OVS_CT_THREAD_CTX {\n- KEVENT event;\n- PVOID threadObject;\n- UINT32 exit;\n-} OVS_CT_THREAD_CTX, *POVS_CT_THREAD_CTX;\n-\n-typedef struct OvsConntrackKeyLookupCtx {\n- OVS_CT_KEY key;\n- POVS_CT_ENTRY entry;\n- UINT32 hash;\n- BOOLEAN reply;\n- BOOLEAN related;\n-} OvsConntrackKeyLookupCtx;\n-\n-/* Per zone strucuture. */\n-typedef struct _OVS_CT_ZONE_INFO {\n- ULONG limit;\n- ULONG entries;\n-} OVS_CT_ZONE_INFO, *POVS_CT_ZONE_INFO;\n-\n-typedef struct _OVS_CT_ZONE_LIMIT {\n- int zone_id;\n- ULONG limit;\n- ULONG count;\n-} OVS_CT_ZONE_LIMIT, *POVS_CT_ZONE_LIMIT;\n-\n-#define CT_MAX_ENTRIES 1 << 21\n-#define CT_HASH_TABLE_SIZE ((UINT32)1 << 10)\n-#define CT_HASH_TABLE_MASK (CT_HASH_TABLE_SIZE - 1)\n-#define CT_INTERVAL_SEC 10000000LL //1s\n-#define CT_ENTRY_TIMEOUT (2 * 60 * CT_INTERVAL_SEC) // 2m\n-#define CT_CLEANUP_INTERVAL (2 * 60 * CT_INTERVAL_SEC) // 2m\n-\n-\n-/* Given POINTER, the address of the given MEMBER in a STRUCT object, returns\n- the STRUCT object. */\n-#define CONTAINER_OF(POINTER, STRUCT, MEMBER) \\\n- ((STRUCT *) (void *) ((char *) (POINTER) - \\\n- offsetof (STRUCT, MEMBER)))\n-\n-static __inline void\n-OvsConntrackUpdateExpiration(OVS_CT_ENTRY *ctEntry,\n- long long now,\n- long long interval)\n-{\n- ctEntry->expiration = now + interval;\n-}\n-\n-const TCPHdr* OvsGetTcpHeader(PNET_BUFFER_LIST nbl, OVS_PACKET_HDR_INFO *layers,\n- VOID *storage, UINT32 *tcpPayloadLen);\n-\n-VOID OvsCleanupConntrack(VOID);\n-NTSTATUS OvsInitConntrack(POVS_SWITCH_CONTEXT context);\n-\n-NDIS_STATUS OvsExecuteConntrackAction(OvsForwardingContext *fwdCtx,\n- OvsFlowKey *key,\n- const PNL_ATTR a);\n-BOOLEAN OvsConntrackValidateTcpPacket(const TCPHdr *tcp);\n-BOOLEAN OvsConntrackValidateIcmpPacket(const ICMPHdr *icmp);\n-BOOLEAN OvsConntrackValidateIcmp6Packet(const ICMPHdr *icmp);\n-OVS_CT_ENTRY * OvsConntrackCreateTcpEntry(const TCPHdr *tcp,\n- UINT64 now,\n- UINT32 tcpPayloadLen);\n-NDIS_STATUS OvsCtMapTcpProtoInfoToNl(PNL_BUFFER nlBuf,\n- OVS_CT_ENTRY *conn_);\n-OVS_CT_ENTRY * OvsConntrackCreateOtherEntry(UINT64 now);\n-OVS_CT_ENTRY * OvsConntrackCreateIcmpEntry(UINT64 now);\n-enum CT_UPDATE_RES OvsConntrackUpdateTcpEntry(OVS_CT_ENTRY* conn_,\n- const TCPHdr *tcp,\n- BOOLEAN reply,\n- UINT64 now,\n- UINT32 tcpPayloadLen);\n-enum CT_UPDATE_RES OvsConntrackUpdateOtherEntry(OVS_CT_ENTRY *conn_,\n- BOOLEAN reply,\n- UINT64 now);\n-enum CT_UPDATE_RES OvsConntrackUpdateIcmpEntry(OVS_CT_ENTRY* conn_,\n- BOOLEAN reply,\n- UINT64 now);\n-NTSTATUS OvsCreateNlMsgFromCtEntry(POVS_CT_ENTRY entry,\n- PVOID outBuffer,\n- UINT32 outBufLen,\n- UINT8 eventType,\n- UINT32 nlmsgSeq,\n- UINT32 nlmsgPid,\n- UINT8 nfGenVersion,\n- UINT32 dpIfIndex);\n-\n-/* Tracking related connections */\n-NTSTATUS OvsInitCtRelated(POVS_SWITCH_CONTEXT context);\n-VOID OvsCleanupCtRelated(VOID);\n-NDIS_STATUS OvsCtRelatedEntryCreate(UINT8 ipProto,\n- UINT16 dl_type,\n- struct ct_addr serverIp,\n- struct ct_addr clientIp,\n- UINT16 serverPort,\n- UINT16 clientPort,\n- UINT64 currentTime,\n- POVS_CT_ENTRY parent);\n-POVS_CT_ENTRY OvsCtRelatedLookup(OVS_CT_KEY key, UINT64 currentTime);\n-NDIS_STATUS OvsCtHandleFtp(PNET_BUFFER_LIST curNbl, OvsFlowKey *key,\n- OVS_PACKET_HDR_INFO *layers, UINT64 currentTime,\n- POVS_CT_ENTRY entry);\n-NDIS_STATUS OvsCtHandleTftp(PNET_BUFFER_LIST curNbl, OvsFlowKey *key,\n- OVS_PACKET_HDR_INFO *layers, UINT64 currentTime,\n- POVS_CT_ENTRY entry);\n-#endif /* __OVS_CONNTRACK_H_ */\ndiff --git a/datapath-windows/ovsext/Datapath.c b/datapath-windows/ovsext/Datapath.c\ndeleted file mode 100644\nindex 37db5bd17..000000000\n--- a/datapath-windows/ovsext/Datapath.c\n+++ /dev/null\n@@ -1,1927 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-/*\n- * XXX: OVS_USE_NL_INTERFACE is being used to keep the legacy DPIF interface\n- * alive while we transition over to the netlink based interface.\n- * OVS_USE_NL_INTERFACE = 0 => legacy inteface to use with dpif-windows.c\n- * OVS_USE_NL_INTERFACE = 1 => netlink inteface to use with ported dpif-linux.c\n- */\n-\n-#include \"precomp.h\"\n-#include \"Switch.h\"\n-#include \"User.h\"\n-#include \"Datapath.h\"\n-#include \"Event.h\"\n-#include \"NetProto.h\"\n-#include \"Flow.h\"\n-\n-#ifdef OVS_DBG_MOD\n-#undef OVS_DBG_MOD\n-#endif\n-#define OVS_DBG_MOD OVS_DBG_DATAPATH\n-#include \"Debug.h\"\n-\n-#define NETLINK_FAMILY_NAME_LEN 48\n-\n-\n-/*\n- * Netlink messages are grouped by family (aka type), and each family supports\n- * a set of commands, and can be passed both from kernel -> userspace or\n- * vice-versa. To call into the kernel, userspace uses a device operation which\n- * is outside of a netlink message.\n- *\n- * Each command results in the invocation of a handler function to implement the\n- * request functionality.\n- *\n- * Expectedly, only certain combinations of (device operation, netlink family,\n- * command) are valid.\n- *\n- * Here, we implement the basic infrastructure to perform validation on the\n- * incoming message, version checking, and also to invoke the corresponding\n- * handler to do the heavy-lifting.\n- */\n-\n-/*\n- * Handler for a given netlink command. Not all the parameters are used by all\n- * the handlers.\n- */\n-typedef NTSTATUS(NetlinkCmdHandler)(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen);\n-\n-typedef struct _NETLINK_CMD {\n- UINT16 cmd;\n- NetlinkCmdHandler *handler;\n- UINT32 supportedDevOp; /* Supported device operations. */\n- BOOLEAN validateDpIndex; /* Does command require a valid DP argument. */\n-} NETLINK_CMD, *PNETLINK_CMD;\n-\n-/* A netlink family is a group of commands. */\n-typedef struct _NETLINK_FAMILY {\n- CHAR *name;\n- UINT16 id;\n- UINT8 version;\n- UINT8 pad1;\n- UINT16 maxAttr;\n- UINT16 pad2;\n- NETLINK_CMD *cmds; /* Array of netlink commands and handlers. */\n- UINT16 opsCount;\n-} NETLINK_FAMILY, *PNETLINK_FAMILY;\n-\n-/* Handlers for the various netlink commands. */\n-static NetlinkCmdHandler OvsPendEventCmdHandler,\n- OvsSubscribeEventCmdHandler,\n- OvsReadEventCmdHandler,\n- OvsNewDpCmdHandler,\n- OvsGetDpCmdHandler,\n- OvsSetDpCmdHandler,\n- OvsSockPropCmdHandler;\n-\n-NetlinkCmdHandler OvsGetNetdevCmdHandler,\n- OvsGetVportCmdHandler,\n- OvsSetVportCmdHandler,\n- OvsNewVportCmdHandler,\n- OvsDeleteVportCmdHandler,\n- OvsPendPacketCmdHandler,\n- OvsSubscribePacketCmdHandler,\n- OvsReadPacketCmdHandler,\n- OvsCtDeleteCmdHandler,\n- OvsCtDumpCmdHandler,\n- OvsCtLimitHandler,\n- OvsMeterFeatureProbe,\n- OvsNewMeterCmdHandler,\n- OvsMeterDestroy,\n- OvsMeterGet;\n-\n-static NTSTATUS HandleGetDpTransaction(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen);\n-static NTSTATUS HandleGetDpDump(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen);\n-static NTSTATUS HandleDpTransactionCommon(\n- POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen);\n-static NTSTATUS OvsGetPidHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen);\n-\n-/*\n- * The various netlink families, along with the supported commands. Most of\n- * these families and commands are part of the openvswitch specification for a\n- * netlink datapath. In addition, each platform can implement a few families\n- * and commands as extensions.\n- */\n-\n-/* Netlink control family: this is a Windows specific family. */\n-NETLINK_CMD nlControlFamilyCmdOps[] = {\n- { .cmd = OVS_CTRL_CMD_WIN_PEND_REQ,\n- .handler = OvsPendEventCmdHandler,\n- .supportedDevOp = OVS_WRITE_DEV_OP,\n- .validateDpIndex = TRUE,\n- },\n- { .cmd = OVS_CTRL_CMD_WIN_PEND_PACKET_REQ,\n- .handler = OvsPendPacketCmdHandler,\n- .supportedDevOp = OVS_WRITE_DEV_OP,\n- .validateDpIndex = TRUE,\n- },\n- { .cmd = OVS_CTRL_CMD_MC_SUBSCRIBE_REQ,\n- .handler = OvsSubscribeEventCmdHandler,\n- .supportedDevOp = OVS_WRITE_DEV_OP,\n- .validateDpIndex = TRUE,\n- },\n- { .cmd = OVS_CTRL_CMD_PACKET_SUBSCRIBE_REQ,\n- .handler = OvsSubscribePacketCmdHandler,\n- .supportedDevOp = OVS_WRITE_DEV_OP,\n- .validateDpIndex = TRUE,\n- },\n- { .cmd = OVS_CTRL_CMD_EVENT_NOTIFY,\n- .handler = OvsReadEventCmdHandler,\n- .supportedDevOp = OVS_READ_DEV_OP,\n- .validateDpIndex = FALSE,\n- },\n- { .cmd = OVS_CTRL_CMD_READ_NOTIFY,\n- .handler = OvsReadPacketCmdHandler,\n- .supportedDevOp = OVS_READ_DEV_OP,\n- .validateDpIndex = FALSE,\n- },\n- { .cmd = OVS_CTRL_CMD_SOCK_PROP,\n- .handler = OvsSockPropCmdHandler,\n- .supportedDevOp = OVS_TRANSACTION_DEV_OP,\n- .validateDpIndex = FALSE,\n- }\n-};\n-\n-NETLINK_FAMILY nlControlFamilyOps = {\n- .name = OVS_WIN_CONTROL_FAMILY,\n- .id = OVS_WIN_NL_CTRL_FAMILY_ID,\n- .version = OVS_WIN_CONTROL_VERSION,\n- .maxAttr = OVS_WIN_CONTROL_ATTR_MAX,\n- .cmds = nlControlFamilyCmdOps,\n- .opsCount = ARRAY_SIZE(nlControlFamilyCmdOps)\n-};\n-\n-/* Netlink datapath family. */\n-NETLINK_CMD nlDatapathFamilyCmdOps[] = {\n- { .cmd = OVS_DP_CMD_NEW,\n- .handler = OvsNewDpCmdHandler,\n- .supportedDevOp = OVS_TRANSACTION_DEV_OP,\n- .validateDpIndex = FALSE\n- },\n- { .cmd = OVS_DP_CMD_GET,\n- .handler = OvsGetDpCmdHandler,\n- .supportedDevOp = OVS_WRITE_DEV_OP | OVS_READ_DEV_OP |\n- OVS_TRANSACTION_DEV_OP,\n- .validateDpIndex = FALSE\n- },\n- { .cmd = OVS_DP_CMD_SET,\n- .handler = OvsSetDpCmdHandler,\n- .supportedDevOp = OVS_WRITE_DEV_OP | OVS_READ_DEV_OP |\n- OVS_TRANSACTION_DEV_OP,\n- .validateDpIndex = TRUE\n- }\n-};\n-\n-NETLINK_FAMILY nlDatapathFamilyOps = {\n- .name = OVS_DATAPATH_FAMILY,\n- .id = OVS_WIN_NL_DATAPATH_FAMILY_ID,\n- .version = OVS_DATAPATH_VERSION,\n- .maxAttr = OVS_DP_ATTR_MAX,\n- .cmds = nlDatapathFamilyCmdOps,\n- .opsCount = ARRAY_SIZE(nlDatapathFamilyCmdOps)\n-};\n-\n-/* Netlink packet family. */\n-\n-NETLINK_CMD nlPacketFamilyCmdOps[] = {\n- { .cmd = OVS_PACKET_CMD_EXECUTE,\n- .handler = OvsNlExecuteCmdHandler,\n- .supportedDevOp = OVS_TRANSACTION_DEV_OP,\n- .validateDpIndex = TRUE\n- }\n-};\n-\n-NETLINK_FAMILY nlPacketFamilyOps = {\n- .name = OVS_PACKET_FAMILY,\n- .id = OVS_WIN_NL_PACKET_FAMILY_ID,\n- .version = OVS_PACKET_VERSION,\n- .maxAttr = OVS_PACKET_ATTR_MAX,\n- .cmds = nlPacketFamilyCmdOps,\n- .opsCount = ARRAY_SIZE(nlPacketFamilyCmdOps)\n-};\n-\n-/* Netlink vport family. */\n-NETLINK_CMD nlVportFamilyCmdOps[] = {\n- { .cmd = OVS_VPORT_CMD_GET,\n- .handler = OvsGetVportCmdHandler,\n- .supportedDevOp = OVS_WRITE_DEV_OP | OVS_READ_DEV_OP |\n- OVS_TRANSACTION_DEV_OP,\n- .validateDpIndex = TRUE\n- },\n- { .cmd = OVS_VPORT_CMD_NEW,\n- .handler = OvsNewVportCmdHandler,\n- .supportedDevOp = OVS_TRANSACTION_DEV_OP,\n- .validateDpIndex = TRUE\n- },\n- { .cmd = OVS_VPORT_CMD_SET,\n- .handler = OvsSetVportCmdHandler,\n- .supportedDevOp = OVS_TRANSACTION_DEV_OP,\n- .validateDpIndex = TRUE\n- },\n- { .cmd = OVS_VPORT_CMD_DEL,\n- .handler = OvsDeleteVportCmdHandler,\n- .supportedDevOp = OVS_TRANSACTION_DEV_OP,\n- .validateDpIndex = TRUE\n- },\n-};\n-\n-NETLINK_FAMILY nlVportFamilyOps = {\n- .name = OVS_VPORT_FAMILY,\n- .id = OVS_WIN_NL_VPORT_FAMILY_ID,\n- .version = OVS_VPORT_VERSION,\n- .maxAttr = OVS_VPORT_ATTR_MAX,\n- .cmds = nlVportFamilyCmdOps,\n- .opsCount = ARRAY_SIZE(nlVportFamilyCmdOps)\n-};\n-\n-/* Netlink flow family. */\n-\n-NETLINK_CMD nlFlowFamilyCmdOps[] = {\n- { .cmd = OVS_FLOW_CMD_NEW,\n- .handler = OvsFlowNlCmdHandler,\n- .supportedDevOp = OVS_TRANSACTION_DEV_OP,\n- .validateDpIndex = TRUE\n- },\n- { .cmd = OVS_FLOW_CMD_SET,\n- .handler = OvsFlowNlCmdHandler,\n- .supportedDevOp = OVS_TRANSACTION_DEV_OP,\n- .validateDpIndex = TRUE\n- },\n- { .cmd = OVS_FLOW_CMD_DEL,\n- .handler = OvsFlowNlCmdHandler,\n- .supportedDevOp = OVS_TRANSACTION_DEV_OP,\n- .validateDpIndex = TRUE\n- },\n- { .cmd = OVS_FLOW_CMD_GET,\n- .handler = OvsFlowNlGetCmdHandler,\n- .supportedDevOp = OVS_TRANSACTION_DEV_OP |\n- OVS_WRITE_DEV_OP | OVS_READ_DEV_OP,\n- .validateDpIndex = TRUE\n- },\n-};\n-\n-NETLINK_FAMILY nlFLowFamilyOps = {\n- .name = OVS_FLOW_FAMILY,\n- .id = OVS_WIN_NL_FLOW_FAMILY_ID,\n- .version = OVS_FLOW_VERSION,\n- .maxAttr = OVS_FLOW_ATTR_MAX,\n- .cmds = nlFlowFamilyCmdOps,\n- .opsCount = ARRAY_SIZE(nlFlowFamilyCmdOps)\n-};\n-\n-/* Netlink Ct family. */\n-NETLINK_CMD nlCtFamilyCmdOps[] = {\n- { .cmd = IPCTNL_MSG_CT_DELETE,\n- .handler = OvsCtDeleteCmdHandler,\n- .supportedDevOp = OVS_TRANSACTION_DEV_OP,\n- .validateDpIndex = FALSE\n- },\n- { .cmd = IPCTNL_MSG_CT_GET,\n- .handler = OvsCtDumpCmdHandler,\n- .supportedDevOp = OVS_WRITE_DEV_OP | OVS_READ_DEV_OP,\n- .validateDpIndex = FALSE\n- }\n-};\n-\n-NETLINK_FAMILY nlCtFamilyOps = {\n- .name = OVS_CT_FAMILY, /* Keep this for consistency*/\n- .id = OVS_WIN_NL_CT_FAMILY_ID, /* Keep this for consistency*/\n- .version = OVS_CT_VERSION, /* Keep this for consistency*/\n- .maxAttr = OVS_NL_CT_ATTR_MAX,\n- .cmds = nlCtFamilyCmdOps,\n- .opsCount = ARRAY_SIZE(nlCtFamilyCmdOps)\n-};\n-\n-/* Netlink Meter family */\n-NETLINK_CMD nlMeterFamilyCmdOps[] = {\n- { .cmd = OVS_METER_CMD_FEATURES,\n- .handler = OvsMeterFeatureProbe,\n- .supportedDevOp = OVS_TRANSACTION_DEV_OP |\n- OVS_WRITE_DEV_OP | OVS_READ_DEV_OP,\n- .validateDpIndex = FALSE\n- },\n- { .cmd = OVS_METER_CMD_SET,\n- .handler = OvsNewMeterCmdHandler,\n- .supportedDevOp = OVS_TRANSACTION_DEV_OP |\n- OVS_WRITE_DEV_OP | OVS_READ_DEV_OP,\n- .validateDpIndex = FALSE\n- },\n- { .cmd = OVS_METER_CMD_GET,\n- .handler = OvsMeterGet,\n- .supportedDevOp = OVS_TRANSACTION_DEV_OP |\n- OVS_WRITE_DEV_OP | OVS_READ_DEV_OP,\n- .validateDpIndex = FALSE\n- },\n- { .cmd = OVS_METER_CMD_DEL,\n- .handler = OvsMeterDestroy,\n- .supportedDevOp = OVS_TRANSACTION_DEV_OP |\n- OVS_WRITE_DEV_OP | OVS_READ_DEV_OP,\n- .validateDpIndex = FALSE\n- },\n-};\n-\n-NETLINK_FAMILY nlMeterFamilyOps = {\n- .name = OVS_METER_FAMILY,\n- .id = OVS_WIN_NL_METER_FAMILY_ID,\n- .version = OVS_METER_VERSION,\n- .maxAttr = __OVS_METER_ATTR_MAX,\n- .cmds = nlMeterFamilyCmdOps,\n- .opsCount = ARRAY_SIZE(nlMeterFamilyCmdOps)\n-};\n-\n-/* Netlink netdev family. */\n-NETLINK_CMD nlNetdevFamilyCmdOps[] = {\n- { .cmd = OVS_WIN_NETDEV_CMD_GET,\n- .handler = OvsGetNetdevCmdHandler,\n- .supportedDevOp = OVS_TRANSACTION_DEV_OP,\n- .validateDpIndex = FALSE\n- },\n-};\n-\n-NETLINK_FAMILY nlNetdevFamilyOps = {\n- .name = OVS_WIN_NETDEV_FAMILY,\n- .id = OVS_WIN_NL_NETDEV_FAMILY_ID,\n- .version = OVS_WIN_NETDEV_VERSION,\n- .maxAttr = OVS_WIN_NETDEV_ATTR_MAX,\n- .cmds = nlNetdevFamilyCmdOps,\n- .opsCount = ARRAY_SIZE(nlNetdevFamilyCmdOps)\n-};\n-\n-\n-/* Netlink conntrack limit family. */\n-NETLINK_CMD nlCtLimitFamilyCmdOps[] = {\n- { .cmd = OVS_CT_LIMIT_CMD_GET,\n- .handler = OvsCtLimitHandler,\n- .supportedDevOp = OVS_TRANSACTION_DEV_OP,\n- .validateDpIndex = FALSE\n- },\n- { .cmd = OVS_CT_LIMIT_CMD_SET,\n- .handler = OvsCtLimitHandler,\n- .supportedDevOp = OVS_TRANSACTION_DEV_OP,\n- .validateDpIndex = FALSE\n- },\n- { .cmd = OVS_CT_LIMIT_CMD_DEL,\n- .handler = OvsCtLimitHandler,\n- .supportedDevOp = OVS_TRANSACTION_DEV_OP,\n- .validateDpIndex = FALSE\n- },\n-};\n-\n-NETLINK_FAMILY nlCtLimitFamilyOps = {\n- .name = OVS_CT_LIMIT_FAMILY,\n- .id = OVS_WIN_NL_CTLIMIT_FAMILY_ID,\n- .version = OVS_CT_LIMIT_VERSION,\n- .maxAttr = OVS_CT_LIMIT_ATTR_MAX,\n- .cmds = nlCtLimitFamilyCmdOps,\n- .opsCount = ARRAY_SIZE(nlCtLimitFamilyCmdOps)\n-};\n-static NTSTATUS MapIrpOutputBuffer(PIRP irp,\n- UINT32 bufferLength,\n- UINT32 requiredLength,\n- PVOID *buffer);\n-static NTSTATUS ValidateNetlinkCmd(UINT32 devOp,\n- POVS_OPEN_INSTANCE instance,\n- POVS_MESSAGE ovsMsg,\n- UINT32 ovsMgsLength,\n- NETLINK_FAMILY *nlFamilyOps);\n-static NTSTATUS InvokeNetlinkCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- NETLINK_FAMILY *nlFamilyOps,\n- UINT32 *replyLen);\n-\n-/* Handles to the device object for communication with userspace. */\n-NDIS_HANDLE gOvsDeviceHandle;\n-PDEVICE_OBJECT gOvsDeviceObject;\n-\n-_Dispatch_type_(IRP_MJ_CREATE)\n-_Dispatch_type_(IRP_MJ_CLOSE)\n-DRIVER_DISPATCH OvsOpenCloseDevice;\n-\n-_Dispatch_type_(IRP_MJ_CLEANUP)\n-DRIVER_DISPATCH OvsCleanupDevice;\n-\n-_Dispatch_type_(IRP_MJ_DEVICE_CONTROL)\n-DRIVER_DISPATCH OvsDeviceControl;\n-\n-#ifdef ALLOC_PRAGMA\n-#pragma alloc_text(INIT, OvsCreateDeviceObject)\n-#pragma alloc_text(PAGE, OvsOpenCloseDevice)\n-#pragma alloc_text(PAGE, OvsCleanupDevice)\n-#pragma alloc_text(PAGE, OvsDeviceControl)\n-#endif // ALLOC_PRAGMA\n-\n-/*\n- * We might hit this limit easily since userspace opens a netlink descriptor for\n- * each thread, and at least one descriptor per vport. Revisit this later.\n- */\n-#define OVS_MAX_OPEN_INSTANCES 512\n-#define OVS_SYSTEM_DP_NAME \"ovs-system\"\n-\n-POVS_OPEN_INSTANCE ovsOpenInstanceArray[OVS_MAX_OPEN_INSTANCES];\n-UINT32 ovsNumberOfOpenInstances;\n-extern POVS_SWITCH_CONTEXT gOvsSwitchContext;\n-\n-NDIS_SPIN_LOCK ovsCtrlLockObj;\n-PNDIS_SPIN_LOCK gOvsCtrlLock;\n-\n-NTSTATUS\n-InitUserDumpState(POVS_OPEN_INSTANCE instance,\n- POVS_MESSAGE ovsMsg)\n-{\n- /* Clear the dumpState from a previous dump sequence. */\n- ASSERT(instance->dumpState.ovsMsg == NULL);\n- ASSERT(ovsMsg);\n-\n- instance->dumpState.ovsMsg =\n- (POVS_MESSAGE)OvsAllocateMemoryWithTag(sizeof(OVS_MESSAGE),\n- OVS_DATAPATH_POOL_TAG);\n- if (instance->dumpState.ovsMsg == NULL) {\n- return STATUS_NO_MEMORY;\n- }\n- RtlCopyMemory(instance->dumpState.ovsMsg, ovsMsg,\n- sizeof *instance->dumpState.ovsMsg);\n- RtlZeroMemory(instance->dumpState.index,\n- sizeof instance->dumpState.index);\n-\n- return STATUS_SUCCESS;\n-}\n-\n-VOID\n-FreeUserDumpState(POVS_OPEN_INSTANCE instance)\n-{\n- if (instance->dumpState.ovsMsg != NULL) {\n- OvsFreeMemoryWithTag(instance->dumpState.ovsMsg,\n- OVS_DATAPATH_POOL_TAG);\n- RtlZeroMemory(&instance->dumpState, sizeof instance->dumpState);\n- }\n-}\n-\n-NDIS_STATUS\n-OvsInit()\n-{\n- NDIS_STATUS status = NDIS_STATUS_SUCCESS;\n-\n- gOvsCtrlLock = &ovsCtrlLockObj;\n- NdisAllocateSpinLock(gOvsCtrlLock);\n- OvsInitEventQueue();\n-\n- status = OvsPerCpuDataInit();\n-\n- return status;\n-}\n-\n-VOID\n-OvsCleanup()\n-{\n- OvsPerCpuDataCleanup();\n- OvsCleanupEventQueue();\n- if (gOvsCtrlLock) {\n- NdisFreeSpinLock(gOvsCtrlLock);\n- gOvsCtrlLock = NULL;\n- }\n-}\n-\n-_Use_decl_annotations_\n-VOID\n-OvsAcquireCtrlLock()\n-{\n- NdisAcquireSpinLock(gOvsCtrlLock);\n-}\n-\n-_Use_decl_annotations_\n-VOID\n-OvsReleaseCtrlLock()\n-{\n- NdisReleaseSpinLock(gOvsCtrlLock);\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Creates the communication device between user and kernel, and also\n- * initializes the data associated data structures.\n- * --------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsCreateDeviceObject(NDIS_HANDLE ovsExtDriverHandle)\n-{\n- NDIS_STATUS status = NDIS_STATUS_SUCCESS;\n- UNICODE_STRING deviceName;\n- UNICODE_STRING symbolicDeviceName;\n- PDRIVER_DISPATCH dispatchTable[IRP_MJ_MAXIMUM_FUNCTION+1];\n- NDIS_DEVICE_OBJECT_ATTRIBUTES deviceAttributes;\n- OVS_LOG_TRACE(\"ovsExtDriverHandle: %p\", ovsExtDriverHandle);\n-\n- RtlZeroMemory(dispatchTable,\n- (IRP_MJ_MAXIMUM_FUNCTION + 1) * sizeof (PDRIVER_DISPATCH));\n- dispatchTable[IRP_MJ_CREATE] = OvsOpenCloseDevice;\n- dispatchTable[IRP_MJ_CLOSE] = OvsOpenCloseDevice;\n- dispatchTable[IRP_MJ_CLEANUP] = OvsCleanupDevice;\n- dispatchTable[IRP_MJ_DEVICE_CONTROL] = OvsDeviceControl;\n-\n- NdisInitUnicodeString(&deviceName, OVS_DEVICE_NAME_NT);\n- NdisInitUnicodeString(&symbolicDeviceName, OVS_DEVICE_NAME_DOS);\n-\n- RtlZeroMemory(&deviceAttributes, sizeof (NDIS_DEVICE_OBJECT_ATTRIBUTES));\n-\n- OVS_INIT_OBJECT_HEADER(&deviceAttributes.Header,\n- NDIS_OBJECT_TYPE_DEVICE_OBJECT_ATTRIBUTES,\n- NDIS_DEVICE_OBJECT_ATTRIBUTES_REVISION_1,\n- sizeof (NDIS_DEVICE_OBJECT_ATTRIBUTES));\n-\n- deviceAttributes.DeviceName = &deviceName;\n- deviceAttributes.SymbolicName = &symbolicDeviceName;\n- deviceAttributes.MajorFunctions = dispatchTable;\n- deviceAttributes.ExtensionSize = sizeof (OVS_DEVICE_EXTENSION);\n-\n- status = NdisRegisterDeviceEx(ovsExtDriverHandle,\n- &deviceAttributes,\n- &gOvsDeviceObject,\n- &gOvsDeviceHandle);\n- if (status == NDIS_STATUS_SUCCESS) {\n- OvsRegisterSystemProvider((PVOID)gOvsDeviceObject);\n- } else {\n- OVS_LOG_ERROR(\"Failed to regiser pseudo device, error: 0x%08x\",\n- status);\n- }\n-\n- OVS_LOG_TRACE(\"DeviceObject: %p\", gOvsDeviceObject);\n- return status;\n-}\n-\n-\n-VOID\n-OvsDeleteDeviceObject()\n-{\n- if (gOvsDeviceHandle) {\n-#ifdef DBG\n- POVS_DEVICE_EXTENSION ovsExt = (POVS_DEVICE_EXTENSION)\n- NdisGetDeviceReservedExtension(gOvsDeviceObject);\n- if (ovsExt) {\n- ASSERT(ovsExt->numberOpenInstance == 0);\n- }\n-#endif\n-\n- ASSERT(gOvsDeviceObject);\n- NdisDeregisterDeviceEx(gOvsDeviceHandle);\n- gOvsDeviceHandle = NULL;\n- gOvsDeviceObject = NULL;\n-\n- OvsUnregisterSystemProvider();\n- }\n-}\n-\n-POVS_OPEN_INSTANCE\n-OvsGetOpenInstance(PFILE_OBJECT fileObject,\n- UINT32 dpNo)\n-{\n- LOCK_STATE_EX lockState;\n- POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)fileObject->FsContext;\n- ASSERT(instance);\n- ASSERT(instance->fileObject == fileObject);\n- NdisAcquireRWLockWrite(gOvsSwitchContext->dispatchLock, &lockState, 0);\n-\n- if (gOvsSwitchContext->dpNo != dpNo) {\n- instance = NULL;\n- }\n-\n- NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState);\n- return instance;\n-}\n-\n-\n-POVS_OPEN_INSTANCE\n-OvsFindOpenInstance(PFILE_OBJECT fileObject)\n-{\n- UINT32 i, j;\n- for (i = 0, j = 0; i < OVS_MAX_OPEN_INSTANCES &&\n- j < ovsNumberOfOpenInstances; i++) {\n- if (ovsOpenInstanceArray[i]) {\n- if (ovsOpenInstanceArray[i]->fileObject == fileObject) {\n- return ovsOpenInstanceArray[i];\n- }\n- j++;\n- }\n- }\n- return NULL;\n-}\n-\n-NTSTATUS\n-OvsAddOpenInstance(POVS_DEVICE_EXTENSION ovsExt,\n- PFILE_OBJECT fileObject)\n-{\n- POVS_OPEN_INSTANCE instance =\n- (POVS_OPEN_INSTANCE)OvsAllocateMemoryWithTag(sizeof(OVS_OPEN_INSTANCE),\n- OVS_DATAPATH_POOL_TAG);\n- UINT32 i;\n-\n- if (instance == NULL) {\n- return STATUS_NO_MEMORY;\n- }\n- OvsAcquireCtrlLock();\n- ASSERT(OvsFindOpenInstance(fileObject) == NULL);\n-\n- if (ovsNumberOfOpenInstances >= OVS_MAX_OPEN_INSTANCES) {\n- OvsReleaseCtrlLock();\n- OvsFreeMemoryWithTag(instance, OVS_DATAPATH_POOL_TAG);\n- return STATUS_INSUFFICIENT_RESOURCES;\n- }\n- RtlZeroMemory(instance, sizeof (OVS_OPEN_INSTANCE));\n-\n- for (i = 0; i < OVS_MAX_OPEN_INSTANCES; i++) {\n- if (ovsOpenInstanceArray[i] == NULL) {\n- ovsOpenInstanceArray[i] = instance;\n- ovsNumberOfOpenInstances++;\n- instance->cookie = i;\n- break;\n- }\n- }\n- ASSERT(i < OVS_MAX_OPEN_INSTANCES);\n- instance->fileObject = fileObject;\n- ASSERT(fileObject->FsContext == NULL);\n- instance->pid = (UINT32)InterlockedIncrement((LONG volatile *)&ovsExt->pidCount);\n- if (instance->pid == 0) {\n- /* XXX: check for rollover. */\n- }\n- fileObject->FsContext = instance;\n- OvsReleaseCtrlLock();\n- return STATUS_SUCCESS;\n-}\n-\n-static VOID\n-OvsCleanupOpenInstance(PFILE_OBJECT fileObject)\n-{\n- POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)fileObject->FsContext;\n- ASSERT(instance);\n- ASSERT(fileObject == instance->fileObject);\n- OvsCleanupEvent(instance);\n- OvsCleanupPacketQueue(instance);\n-}\n-\n-VOID\n-OvsRemoveOpenInstance(PFILE_OBJECT fileObject)\n-{\n- POVS_OPEN_INSTANCE instance;\n- ASSERT(fileObject->FsContext);\n- instance = (POVS_OPEN_INSTANCE)fileObject->FsContext;\n- ASSERT(instance->cookie < OVS_MAX_OPEN_INSTANCES);\n-\n- OvsAcquireCtrlLock();\n- fileObject->FsContext = NULL;\n- ASSERT(ovsOpenInstanceArray[instance->cookie] == instance);\n- ovsOpenInstanceArray[instance->cookie] = NULL;\n- ovsNumberOfOpenInstances--;\n- OvsReleaseCtrlLock();\n- ASSERT(instance->eventQueue == NULL);\n- ASSERT (instance->packetQueue == NULL);\n- FreeUserDumpState(instance);\n- OvsFreeMemoryWithTag(instance, OVS_DATAPATH_POOL_TAG);\n-}\n-\n-NTSTATUS\n-OvsCompleteIrpRequest(PIRP irp,\n- ULONG_PTR infoPtr,\n- NTSTATUS status)\n-{\n- irp->IoStatus.Information = infoPtr;\n- irp->IoStatus.Status = status;\n- IoCompleteRequest(irp, IO_NO_INCREMENT);\n- return status;\n-}\n-\n-\n-NTSTATUS\n-OvsOpenCloseDevice(PDEVICE_OBJECT deviceObject,\n- PIRP irp)\n-{\n- PIO_STACK_LOCATION irpSp;\n- NTSTATUS status = STATUS_SUCCESS;\n- PFILE_OBJECT fileObject;\n- POVS_DEVICE_EXTENSION ovsExt =\n- (POVS_DEVICE_EXTENSION)NdisGetDeviceReservedExtension(deviceObject);\n-\n-#pragma warning(suppress: 28118)\n- PAGED_CODE();\n- ASSERT(deviceObject == gOvsDeviceObject);\n- ASSERT(ovsExt != NULL);\n-\n- irpSp = IoGetCurrentIrpStackLocation(irp);\n- fileObject = irpSp->FileObject;\n- OVS_LOG_TRACE(\"DeviceObject: %p, fileObject:%p, instance: %u\",\n- deviceObject, fileObject,\n- ovsExt->numberOpenInstance);\n-\n- switch (irpSp->MajorFunction) {\n- case IRP_MJ_CREATE:\n- status = OvsAddOpenInstance(ovsExt, fileObject);\n- if (STATUS_SUCCESS == status) {\n- InterlockedIncrement((LONG volatile *)&ovsExt->numberOpenInstance);\n- }\n- break;\n- case IRP_MJ_CLOSE:\n- ASSERT(ovsExt->numberOpenInstance > 0);\n- OvsRemoveOpenInstance(fileObject);\n- InterlockedDecrement((LONG volatile *)&ovsExt->numberOpenInstance);\n- break;\n- default:\n- ASSERT(0);\n- }\n- return OvsCompleteIrpRequest(irp, (ULONG_PTR)0, status);\n-}\n-\n-_Use_decl_annotations_\n-NTSTATUS\n-OvsCleanupDevice(PDEVICE_OBJECT deviceObject,\n- PIRP irp)\n-{\n-#pragma warning(suppress: 28118)\n- PAGED_CODE();\n- PIO_STACK_LOCATION irpSp;\n- PFILE_OBJECT fileObject;\n-\n- NTSTATUS status = STATUS_SUCCESS;\n-#ifdef DBG\n- POVS_DEVICE_EXTENSION ovsExt =\n- (POVS_DEVICE_EXTENSION)NdisGetDeviceReservedExtension(deviceObject);\n- if (ovsExt) {\n- ASSERT(ovsExt->numberOpenInstance > 0);\n- }\n-#else\n- UNREFERENCED_PARAMETER(deviceObject);\n-#endif\n- ASSERT(deviceObject == gOvsDeviceObject);\n- irpSp = IoGetCurrentIrpStackLocation(irp);\n- fileObject = irpSp->FileObject;\n-\n- ASSERT(irpSp->MajorFunction == IRP_MJ_CLEANUP);\n-\n- OvsCleanupOpenInstance(fileObject);\n-\n- return OvsCompleteIrpRequest(irp, (ULONG_PTR)0, status);\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * IOCTL function handler for the device.\n- * --------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsDeviceControl(PDEVICE_OBJECT deviceObject,\n- PIRP irp)\n-{\n- PIO_STACK_LOCATION irpSp;\n- NTSTATUS status = STATUS_SUCCESS;\n- PFILE_OBJECT fileObject;\n- PVOID inputBuffer = NULL;\n- PVOID outputBuffer = NULL;\n- UINT32 inputBufferLen, outputBufferLen;\n- UINT32 code, replyLen = 0;\n- POVS_OPEN_INSTANCE instance;\n- UINT32 devOp;\n- OVS_MESSAGE ovsMsgReadOp;\n- POVS_MESSAGE ovsMsg;\n- UINT32 ovsMsgLength = 0;\n- NETLINK_FAMILY *nlFamilyOps;\n- OVS_USER_PARAMS_CONTEXT usrParamsCtx;\n-\n-#pragma warning(suppress: 28118)\n- PAGED_CODE();\n-#ifdef DBG\n- POVS_DEVICE_EXTENSION ovsExt =\n- (POVS_DEVICE_EXTENSION)NdisGetDeviceReservedExtension(deviceObject);\n- ASSERT(deviceObject == gOvsDeviceObject);\n- ASSERT(ovsExt);\n- ASSERT(ovsExt->numberOpenInstance > 0);\n-#else\n- UNREFERENCED_PARAMETER(deviceObject);\n-#endif\n-\n- irpSp = IoGetCurrentIrpStackLocation(irp);\n-\n- ASSERT(irpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL);\n- ASSERT(irpSp->FileObject != NULL);\n-\n- fileObject = irpSp->FileObject;\n- instance = (POVS_OPEN_INSTANCE)fileObject->FsContext;\n- code = irpSp->Parameters.DeviceIoControl.IoControlCode;\n- inputBufferLen = irpSp->Parameters.DeviceIoControl.InputBufferLength;\n- outputBufferLen = irpSp->Parameters.DeviceIoControl.OutputBufferLength;\n- inputBuffer = irp->AssociatedIrp.SystemBuffer;\n-\n- /* Check if the extension is enabled. */\n- if (NULL == gOvsSwitchContext) {\n- status = STATUS_NOT_FOUND;\n- goto exit;\n- }\n-\n- if (!OvsAcquireSwitchContext()) {\n- status = STATUS_NOT_FOUND;\n- goto exit;\n- }\n-\n- /*\n- * Validate the input/output buffer arguments depending on the type of the\n- * operation.\n- */\n- switch (code) {\n- case OVS_IOCTL_GET_PID:\n- /* Both input buffer and output buffer use the same location. */\n- outputBuffer = irp->AssociatedIrp.SystemBuffer;\n- if (outputBufferLen != 0) {\n- InitUserParamsCtx(irp, instance, 0, NULL,\n- inputBuffer, inputBufferLen,\n- outputBuffer, outputBufferLen,\n- &usrParamsCtx);\n-\n- ASSERT(outputBuffer);\n- } else {\n- status = STATUS_NDIS_INVALID_LENGTH;\n- goto done;\n- }\n-\n- status = OvsGetPidHandler(&usrParamsCtx, &replyLen);\n- goto done;\n-\n- case OVS_IOCTL_TRANSACT:\n- /* Both input buffer and output buffer are mandatory. */\n- if (outputBufferLen != 0) {\n- ASSERT(sizeof(OVS_MESSAGE_ERROR) >= sizeof *ovsMsg);\n- status = MapIrpOutputBuffer(irp, outputBufferLen,\n- sizeof(OVS_MESSAGE_ERROR),\n- &outputBuffer);\n- if (status != STATUS_SUCCESS) {\n- goto done;\n- }\n- ASSERT(outputBuffer);\n- } else {\n- status = STATUS_NDIS_INVALID_LENGTH;\n- goto done;\n- }\n-\n- if (inputBufferLen < sizeof (*ovsMsg)) {\n- status = STATUS_NDIS_INVALID_LENGTH;\n- goto done;\n- }\n-\n- ovsMsg = inputBuffer;\n- ovsMsgLength = inputBufferLen;\n- devOp = OVS_TRANSACTION_DEV_OP;\n- break;\n-\n- case OVS_IOCTL_READ_EVENT:\n- case OVS_IOCTL_READ_PACKET:\n- /*\n- * Output buffer is mandatory. These IOCTLs are used to read events and\n- * packets respectively. It is convenient to have separate ioctls.\n- */\n- if (outputBufferLen != 0) {\n- status = MapIrpOutputBuffer(irp, outputBufferLen,\n- sizeof(OVS_MESSAGE_ERROR),\n- &outputBuffer);\n- if (status != STATUS_SUCCESS) {\n- goto done;\n- }\n- ASSERT(outputBuffer);\n- } else {\n- status = STATUS_NDIS_INVALID_LENGTH;\n- goto done;\n- }\n- inputBuffer = NULL;\n- inputBufferLen = 0;\n-\n- ovsMsg = &ovsMsgReadOp;\n- RtlZeroMemory(ovsMsg, sizeof *ovsMsg);\n- ovsMsg->nlMsg.nlmsgLen = sizeof *ovsMsg;\n- ovsMsg->nlMsg.nlmsgType = nlControlFamilyOps.id;\n- ovsMsg->nlMsg.nlmsgPid = instance->pid;\n-\n- /* An \"artificial\" command so we can use NL family function table*/\n- ovsMsg->genlMsg.cmd = (code == OVS_IOCTL_READ_EVENT) ?\n- OVS_CTRL_CMD_EVENT_NOTIFY :\n- OVS_CTRL_CMD_READ_NOTIFY;\n- ovsMsg->genlMsg.version = nlControlFamilyOps.version;\n- ovsMsgLength = outputBufferLen;\n-\n- devOp = OVS_READ_DEV_OP;\n- break;\n-\n- case OVS_IOCTL_READ:\n- /* Output buffer is mandatory. */\n- if (outputBufferLen != 0) {\n- status = MapIrpOutputBuffer(irp, outputBufferLen,\n- sizeof(OVS_MESSAGE_ERROR),\n- &outputBuffer);\n- if (status != STATUS_SUCCESS) {\n- goto done;\n- }\n- ASSERT(outputBuffer);\n- } else {\n- status = STATUS_NDIS_INVALID_LENGTH;\n- goto done;\n- }\n-\n- /*\n- * Operate in the mode that read ioctl is similar to ReadFile(). This\n- * might change as the userspace code gets implemented.\n- */\n- inputBuffer = NULL;\n- inputBufferLen = 0;\n-\n- /*\n- * For implementing read (ioctl or otherwise), we need to store some\n- * state in the instance to indicate the command that started the dump\n- * operation. The state can setup 'ovsMsgReadOp' appropriately. Note\n- * that 'ovsMsgReadOp' is needed only in this function to call into the\n- * appropriate handler. The handler itself can access the state in the\n- * instance.\n- *\n- * In the absence of a dump start, return 0 bytes.\n- */\n- if (instance->dumpState.ovsMsg == NULL) {\n- replyLen = 0;\n- status = STATUS_SUCCESS;\n- goto done;\n- }\n- RtlCopyMemory(&ovsMsgReadOp, instance->dumpState.ovsMsg,\n- sizeof (ovsMsgReadOp));\n-\n- /* Create an NL message for consumption. */\n- ovsMsg = &ovsMsgReadOp;\n- ovsMsgLength = sizeof (ovsMsgReadOp);\n- devOp = OVS_READ_DEV_OP;\n-\n- break;\n-\n- case OVS_IOCTL_WRITE:\n- /* Input buffer is mandatory. */\n- if (inputBufferLen < sizeof (*ovsMsg)) {\n- status = STATUS_NDIS_INVALID_LENGTH;\n- goto done;\n- }\n-\n- ovsMsg = inputBuffer;\n- ovsMsgLength = inputBufferLen;\n- devOp = OVS_WRITE_DEV_OP;\n- break;\n-\n- default:\n- status = STATUS_INVALID_DEVICE_REQUEST;\n- goto done;\n- }\n-\n- ASSERT(ovsMsg);\n- switch (ovsMsg->nlMsg.nlmsgType) {\n- case NFNL_TYPE_CT_GET:\n- case NFNL_TYPE_CT_DEL:\n- nlFamilyOps = &nlCtFamilyOps;\n- break;\n- case OVS_WIN_NL_METER_FAMILY_ID:\n- nlFamilyOps = &nlMeterFamilyOps;\n- break;\n- case OVS_WIN_NL_CTRL_FAMILY_ID:\n- nlFamilyOps = &nlControlFamilyOps;\n- break;\n- case OVS_WIN_NL_DATAPATH_FAMILY_ID:\n- nlFamilyOps = &nlDatapathFamilyOps;\n- break;\n- case OVS_WIN_NL_FLOW_FAMILY_ID:\n- nlFamilyOps = &nlFLowFamilyOps;\n- break;\n- case OVS_WIN_NL_PACKET_FAMILY_ID:\n- nlFamilyOps = &nlPacketFamilyOps;\n- break;\n- case OVS_WIN_NL_VPORT_FAMILY_ID:\n- nlFamilyOps = &nlVportFamilyOps;\n- break;\n- case OVS_WIN_NL_NETDEV_FAMILY_ID:\n- nlFamilyOps = &nlNetdevFamilyOps;\n- break;\n- case OVS_WIN_NL_CTLIMIT_FAMILY_ID:\n- nlFamilyOps = &nlCtLimitFamilyOps;\n- break;\n- default:\n- status = STATUS_INVALID_PARAMETER;\n- goto done;\n- }\n-\n- /*\n- * For read operation, avoid duplicate validation since 'ovsMsg' is either\n- * \"artificial\" or was copied from a previously validated 'ovsMsg'.\n- */\n- if (devOp != OVS_READ_DEV_OP) {\n- status = ValidateNetlinkCmd(devOp, instance, ovsMsg,\n- ovsMsgLength, nlFamilyOps);\n- if (status != STATUS_SUCCESS) {\n- goto done;\n- }\n- }\n-\n- InitUserParamsCtx(irp, instance, devOp, ovsMsg,\n- inputBuffer, inputBufferLen,\n- outputBuffer, outputBufferLen,\n- &usrParamsCtx);\n-\n- status = InvokeNetlinkCmdHandler(&usrParamsCtx, nlFamilyOps, &replyLen);\n-\n-done:\n- OvsReleaseSwitchContext(gOvsSwitchContext);\n-\n-exit:\n- /* Should not complete a pending IRP unless proceesing is completed. */\n- if (status == STATUS_PENDING) {\n- return status;\n- }\n- return OvsCompleteIrpRequest(irp, (ULONG_PTR)replyLen, status);\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Function to validate a netlink command. Only certain combinations of\n- * (device operation, netlink family, command) are valid.\n- * --------------------------------------------------------------------------\n- */\n-static NTSTATUS\n-ValidateNetlinkCmd(UINT32 devOp,\n- POVS_OPEN_INSTANCE instance,\n- POVS_MESSAGE ovsMsg,\n- UINT32 ovsMsgLength,\n- NETLINK_FAMILY *nlFamilyOps)\n-{\n- NTSTATUS status = STATUS_INVALID_PARAMETER;\n- UINT16 i;\n-\n- // We need to ensure we have enough data to process\n- if (NlMsgSize(&ovsMsg->nlMsg) > ovsMsgLength) {\n- status = STATUS_INVALID_PARAMETER;\n- goto done;\n- }\n-\n- /*\n- * Verify if the Netlink message is part of Netfilter Netlink\n- * This is currently used by Conntrack\n- */\n- if (IS_NFNL_CMD(ovsMsg->nlMsg.nlmsgType)) {\n-\n- /* Validate Netfilter Netlink version is 0 */\n- if (ovsMsg->nfGenMsg.version != NFNETLINK_V0) {\n- status = STATUS_INVALID_PARAMETER;\n- goto done;\n- }\n-\n- /* Validate Netfilter Netlink Subsystem */\n- if (NFNL_SUBSYS_ID(ovsMsg->nlMsg.nlmsgType)\n- != NFNL_SUBSYS_CTNETLINK) {\n- status = STATUS_INVALID_PARAMETER;\n- goto done;\n- }\n-\n- /* Exit the function because there aren't any other validations */\n- status = STATUS_SUCCESS;\n- goto done;\n- }\n-\n- for (i = 0; i < nlFamilyOps->opsCount; i++) {\n- if (nlFamilyOps->cmds[i].cmd == ovsMsg->genlMsg.cmd) {\n- /* Validate if the command is valid for the device operation. */\n- if ((devOp & nlFamilyOps->cmds[i].supportedDevOp) == 0) {\n- status = STATUS_INVALID_PARAMETER;\n- goto done;\n- }\n-\n- /* Validate the version. */\n- if (nlFamilyOps->version > ovsMsg->genlMsg.version) {\n- status = STATUS_INVALID_PARAMETER;\n- goto done;\n- }\n-\n- /* Validate the DP for commands that require a DP. */\n- if (nlFamilyOps->cmds[i].validateDpIndex == TRUE) {\n- if (ovsMsg->ovsHdr.dp_ifindex !=\n- (INT)gOvsSwitchContext->dpNo) {\n- status = STATUS_INVALID_PARAMETER;\n- goto done;\n- }\n- }\n-\n- /* Validate the PID. */\n- if (ovsMsg->nlMsg.nlmsgPid != instance->pid) {\n- status = STATUS_INVALID_PARAMETER;\n- goto done;\n- }\n-\n- status = STATUS_SUCCESS;\n- break;\n- }\n- }\n-\n- // validate all NlAttrs\n- if (!NlValidateAllAttrs(&ovsMsg->nlMsg, sizeof(*ovsMsg),\n- NlMsgAttrsLen((PNL_MSG_HDR)ovsMsg),\n- NULL, 0)) {\n- status = STATUS_INVALID_PARAMETER;\n- goto done;\n- }\n-\n-done:\n- return status;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Function to invoke the netlink command handler. The function also stores\n- * the return value of the handler function to construct a 'NL_ERROR' message,\n- * and in turn returns success to the caller.\n- * --------------------------------------------------------------------------\n- */\n-static NTSTATUS\n-InvokeNetlinkCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- NETLINK_FAMILY *nlFamilyOps,\n- UINT32 *replyLen)\n-{\n- NTSTATUS status = STATUS_INVALID_PARAMETER;\n- UINT16 i;\n- UINT8 cmd;\n-\n- if (IS_NFNL_CMD(usrParamsCtx->ovsMsg->nlMsg.nlmsgType)) {\n- /* If nlMsg is of type Netfilter-Netlink parse the Cmd accordingly */\n- cmd = NFNL_MSG_TYPE(usrParamsCtx->ovsMsg->nlMsg.nlmsgType);\n- } else {\n- cmd = usrParamsCtx->ovsMsg->genlMsg.cmd;\n- }\n-\n- for (i = 0; i < nlFamilyOps->opsCount; i++) {\n- if (nlFamilyOps->cmds[i].cmd == cmd) {\n- NetlinkCmdHandler *handler = nlFamilyOps->cmds[i].handler;\n- ASSERT(handler);\n- if (handler) {\n- status = handler(usrParamsCtx, replyLen);\n- }\n- break;\n- }\n- }\n-\n- /*\n- * Netlink socket semantics dictate that the return value of the netlink\n- * function should be an error ONLY under fatal conditions. If the message\n- * made it all the way to the handler function, it is not a fatal condition.\n- * Absorb the error returned by the handler function into a 'struct\n- * NL_ERROR' and populate the 'output buffer' to return to userspace.\n- *\n- * This behavior is obviously applicable only to netlink commands that\n- * specify an 'output buffer'. For other commands, we return the error as\n- * is.\n- *\n- * 'STATUS_PENDING' is a special return value and userspace is equipped to\n- * handle it.\n- */\n- if (status != STATUS_SUCCESS && status != STATUS_PENDING) {\n- if (usrParamsCtx->devOp != OVS_WRITE_DEV_OP && *replyLen == 0) {\n- NL_ERROR nlError = NlMapStatusToNlErr(status);\n- OVS_MESSAGE msgInTmp = { 0 };\n- POVS_MESSAGE msgIn = NULL;\n- POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)\n- usrParamsCtx->outputBuffer;\n-\n- if (!IS_NFNL_CMD(usrParamsCtx->ovsMsg->nlMsg.nlmsgType) &&\n- (usrParamsCtx->ovsMsg->genlMsg.cmd == OVS_CTRL_CMD_EVENT_NOTIFY ||\n- usrParamsCtx->ovsMsg->genlMsg.cmd == OVS_CTRL_CMD_READ_NOTIFY)) {\n- /* There's no input buffer associated with such requests. */\n- NL_BUFFER nlBuffer;\n- msgIn = &msgInTmp;\n- NlBufInit(&nlBuffer, (PCHAR)msgIn, sizeof *msgIn);\n- NlFillNlHdr(&nlBuffer, nlFamilyOps->id, 0, 0,\n- usrParamsCtx->ovsInstance->pid);\n- } else {\n- msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;\n- }\n-\n- ASSERT(msgIn);\n- ASSERT(msgError);\n- NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);\n- ASSERT(*replyLen != 0);\n- }\n-\n- if (*replyLen != 0) {\n- status = STATUS_SUCCESS;\n- }\n- }\n-\n-#ifdef DBG\n- if (usrParamsCtx->devOp != OVS_WRITE_DEV_OP) {\n- ASSERT(status == STATUS_PENDING || *replyLen != 0 || status == STATUS_SUCCESS);\n- }\n-#endif\n-\n- return status;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Handler for 'OVS_IOCTL_GET_PID'.\n- *\n- * Each handle on the device is assigned a unique PID when the handle is\n- * created. This function passes the PID to userspace using METHOD_BUFFERED\n- * method.\n- * --------------------------------------------------------------------------\n- */\n-static NTSTATUS\n-OvsGetPidHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen)\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n- PUINT32 msgOut = (PUINT32)usrParamsCtx->outputBuffer;\n-\n- if (usrParamsCtx->outputLength >= sizeof *msgOut) {\n- POVS_OPEN_INSTANCE instance =\n- (POVS_OPEN_INSTANCE)usrParamsCtx->ovsInstance;\n-\n- RtlZeroMemory(msgOut, sizeof *msgOut);\n- RtlCopyMemory(msgOut, &instance->pid, sizeof(*msgOut));\n- *replyLen = sizeof *msgOut;\n- } else {\n- *replyLen = sizeof *msgOut;\n- status = STATUS_NDIS_INVALID_LENGTH;\n- }\n-\n- return status;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Utility function to fill up information about the datapath in a reply to\n- * userspace.\n- * --------------------------------------------------------------------------\n- */\n-static NTSTATUS\n-OvsDpFillInfo(POVS_SWITCH_CONTEXT ovsSwitchContext,\n- POVS_MESSAGE msgIn,\n- PNL_BUFFER nlBuf)\n-{\n- BOOLEAN writeOk;\n- OVS_MESSAGE msgOutTmp;\n- OVS_DATAPATH *datapath = &ovsSwitchContext->datapath;\n- PNL_MSG_HDR nlMsg;\n-\n- ASSERT(NlBufAt(nlBuf, 0, 0) != 0 && NlBufRemLen(nlBuf) >= sizeof *msgIn);\n-\n- msgOutTmp.nlMsg.nlmsgType = OVS_WIN_NL_DATAPATH_FAMILY_ID;\n- msgOutTmp.nlMsg.nlmsgFlags = 0; /* XXX: ? */\n- msgOutTmp.nlMsg.nlmsgSeq = msgIn->nlMsg.nlmsgSeq;\n- msgOutTmp.nlMsg.nlmsgPid = msgIn->nlMsg.nlmsgPid;\n-\n- msgOutTmp.genlMsg.cmd = OVS_DP_CMD_GET;\n- msgOutTmp.genlMsg.version = nlDatapathFamilyOps.version;\n- msgOutTmp.genlMsg.reserved = 0;\n-\n- msgOutTmp.ovsHdr.dp_ifindex = ovsSwitchContext->dpNo;\n-\n- writeOk = NlMsgPutHead(nlBuf, (PCHAR)&msgOutTmp, sizeof msgOutTmp);\n- if (writeOk) {\n- writeOk = NlMsgPutTailString(nlBuf, OVS_DP_ATTR_NAME,\n- OVS_SYSTEM_DP_NAME);\n- }\n- if (writeOk) {\n- OVS_DP_STATS dpStats;\n-\n- dpStats.n_hit = datapath->hits;\n- dpStats.n_missed = datapath->misses;\n- dpStats.n_lost = datapath->lost;\n- dpStats.n_flows = datapath->nFlows;\n- writeOk = NlMsgPutTailUnspec(nlBuf, OVS_DP_ATTR_STATS,\n- (PCHAR)&dpStats, sizeof dpStats);\n- }\n- nlMsg = (PNL_MSG_HDR)NlBufAt(nlBuf, 0, 0);\n- nlMsg->nlmsgLen = NlBufSize(nlBuf);\n-\n- return writeOk ? STATUS_SUCCESS : STATUS_INVALID_BUFFER_SIZE;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Handler for queueing an IRP used for event notification. The IRP is\n- * completed when a port state changes. STATUS_PENDING is returned on\n- * success. User mode keep a pending IRP at all times.\n- * --------------------------------------------------------------------------\n- */\n-static NTSTATUS\n-OvsPendEventCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen)\n-{\n- NDIS_STATUS status;\n-\n- UNREFERENCED_PARAMETER(replyLen);\n-\n- POVS_OPEN_INSTANCE instance =\n- (POVS_OPEN_INSTANCE)usrParamsCtx->ovsInstance;\n- POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;\n- OVS_EVENT_POLL poll;\n-\n- poll.dpNo = msgIn->ovsHdr.dp_ifindex;\n- status = OvsWaitEventIoctl(usrParamsCtx->irp, instance->fileObject,\n- &poll, sizeof poll);\n- return status;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Handler for the subscription for the event queue\n- * --------------------------------------------------------------------------\n- */\n-static NTSTATUS\n-OvsSubscribeEventCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen)\n-{\n- NDIS_STATUS status;\n- OVS_EVENT_SUBSCRIBE request;\n- BOOLEAN rc;\n- UINT8 join;\n- UINT32 mcastGrp;\n- PNL_ATTR attrs[2];\n- const NL_POLICY policy[] = {\n- [OVS_NL_ATTR_MCAST_GRP] = {.type = NL_A_U32 },\n- [OVS_NL_ATTR_MCAST_JOIN] = {.type = NL_A_U8 },\n- };\n-\n- UNREFERENCED_PARAMETER(replyLen);\n-\n- POVS_OPEN_INSTANCE instance =\n- (POVS_OPEN_INSTANCE)usrParamsCtx->ovsInstance;\n- POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;\n-\n- rc = NlAttrParse(&msgIn->nlMsg, sizeof (*msgIn),\n- NlMsgAttrsLen((PNL_MSG_HDR)msgIn), policy, ARRAY_SIZE(policy),\n- attrs, ARRAY_SIZE(attrs));\n- if (!rc) {\n- status = STATUS_INVALID_PARAMETER;\n- goto done;\n- }\n-\n- mcastGrp = NlAttrGetU32(attrs[OVS_NL_ATTR_MCAST_GRP]);\n- join = NlAttrGetU8(attrs[OVS_NL_ATTR_MCAST_JOIN]);\n- request.dpNo = msgIn->ovsHdr.dp_ifindex;\n- request.subscribe = join;\n- request.mcastGrp = mcastGrp;\n- request.protocol = instance->protocol;\n- request.mask = 0;\n-\n- /* We currently support Vport and CT related events */\n- if (instance->protocol == NETLINK_GENERIC) {\n- request.mask = OVS_EVENT_MASK_ALL;\n- } else if (instance->protocol == NETLINK_NETFILTER) {\n- if (mcastGrp == NFNLGRP_CONNTRACK_NEW) {\n- request.mask = OVS_EVENT_CT_NEW;\n- }\n- if (mcastGrp == NFNLGRP_CONNTRACK_DESTROY) {\n- request.mask = OVS_EVENT_CT_DELETE;\n- }\n- if (mcastGrp == NFNLGRP_CONNTRACK_UPDATE) {\n- request.mask = OVS_EVENT_CT_UPDATE;\n- }\n- }\n-\n- status = OvsSubscribeEventIoctl(instance->fileObject, &request,\n- sizeof request);\n-done:\n- return status;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Command Handler for 'OVS_DP_CMD_NEW'.\n- * --------------------------------------------------------------------------\n- */\n-static NTSTATUS\n-OvsNewDpCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen)\n-{\n- return HandleDpTransactionCommon(usrParamsCtx, replyLen);\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Command Handler for 'OVS_DP_CMD_GET'.\n- *\n- * The function handles both the dump based as well as the transaction based\n- * 'OVS_DP_CMD_GET' command. In the dump command, it handles the initial\n- * call to setup dump state, as well as subsequent calls to continue dumping\n- * data.\n- * --------------------------------------------------------------------------\n- */\n-static NTSTATUS\n-OvsGetDpCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen)\n-{\n- if (usrParamsCtx->devOp == OVS_TRANSACTION_DEV_OP) {\n- return HandleDpTransactionCommon(usrParamsCtx, replyLen);\n- } else {\n- return HandleGetDpDump(usrParamsCtx, replyLen);\n- }\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Function for handling the transaction based 'OVS_DP_CMD_GET' command.\n- * --------------------------------------------------------------------------\n- */\n-static NTSTATUS\n-HandleGetDpTransaction(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen)\n-{\n- return HandleDpTransactionCommon(usrParamsCtx, replyLen);\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Function for handling the dump-based 'OVS_DP_CMD_GET' command.\n- * --------------------------------------------------------------------------\n- */\n-static NTSTATUS\n-HandleGetDpDump(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen)\n-{\n- POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer;\n- POVS_OPEN_INSTANCE instance =\n- (POVS_OPEN_INSTANCE)usrParamsCtx->ovsInstance;\n-\n- if (usrParamsCtx->devOp == OVS_WRITE_DEV_OP) {\n- *replyLen = 0;\n- OvsSetupDumpStart(usrParamsCtx);\n- } else {\n- NL_BUFFER nlBuf;\n- NTSTATUS status;\n- POVS_MESSAGE msgIn = instance->dumpState.ovsMsg;\n-\n- ASSERT(usrParamsCtx->devOp == OVS_READ_DEV_OP);\n-\n- if (instance->dumpState.ovsMsg == NULL) {\n- ASSERT(FALSE);\n- return STATUS_INVALID_DEVICE_STATE;\n- }\n-\n- /* Dump state must have been deleted after previous dump operation. */\n- ASSERT(instance->dumpState.index[0] == 0);\n-\n- /* Output buffer has been validated while validating read dev op. */\n- ASSERT(msgOut != NULL && usrParamsCtx->outputLength >= sizeof *msgOut);\n-\n- NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,\n- usrParamsCtx->outputLength);\n-\n- status = OvsDpFillInfo(gOvsSwitchContext, msgIn, &nlBuf);\n-\n- if (status != STATUS_SUCCESS) {\n- *replyLen = 0;\n- FreeUserDumpState(instance);\n- return status;\n- }\n-\n- /* Increment the dump index. */\n- instance->dumpState.index[0] = 1;\n- *replyLen = msgOut->nlMsg.nlmsgLen;\n-\n- /* Free up the dump state, since there's no more data to continue. */\n- FreeUserDumpState(instance);\n- }\n-\n- return STATUS_SUCCESS;\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Command Handler for 'OVS_DP_CMD_SET'.\n- * --------------------------------------------------------------------------\n- */\n-static NTSTATUS\n-OvsSetDpCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen)\n-{\n- return HandleDpTransactionCommon(usrParamsCtx, replyLen);\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Function for handling transaction based 'OVS_DP_CMD_NEW', 'OVS_DP_CMD_GET'\n- * and 'OVS_DP_CMD_SET' commands.\n- *\n- * 'OVS_DP_CMD_NEW' is implemented to keep userspace code happy. Creation of a\n- * new datapath is not supported currently.\n- * --------------------------------------------------------------------------\n- */\n-static NTSTATUS\n-HandleDpTransactionCommon(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen)\n-{\n- POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;\n- POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer;\n- NTSTATUS status = STATUS_SUCCESS;\n- NL_BUFFER nlBuf;\n- NL_ERROR nlError = NL_ERROR_SUCCESS;\n- static const NL_POLICY ovsDatapathSetPolicy[] = {\n- [OVS_DP_ATTR_NAME] = { .type = NL_A_STRING, .maxLen = IFNAMSIZ },\n- [OVS_DP_ATTR_UPCALL_PID] = { .type = NL_A_U32, .optional = TRUE },\n- [OVS_DP_ATTR_USER_FEATURES] = { .type = NL_A_U32, .optional = TRUE },\n- };\n- PNL_ATTR dpAttrs[ARRAY_SIZE(ovsDatapathSetPolicy)];\n-\n- UNREFERENCED_PARAMETER(msgOut);\n-\n- /* input buffer has been validated while validating write dev op. */\n- ASSERT(msgIn != NULL && usrParamsCtx->inputLength >= sizeof *msgIn);\n-\n- /* Parse any attributes in the request. */\n- if (usrParamsCtx->ovsMsg->genlMsg.cmd == OVS_DP_CMD_SET ||\n- usrParamsCtx->ovsMsg->genlMsg.cmd == OVS_DP_CMD_NEW) {\n- if (!NlAttrParse((PNL_MSG_HDR)msgIn,\n- NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN,\n- NlMsgAttrsLen((PNL_MSG_HDR)msgIn),\n- ovsDatapathSetPolicy,\n- ARRAY_SIZE(ovsDatapathSetPolicy),\n- dpAttrs, ARRAY_SIZE(dpAttrs))) {\n- return STATUS_INVALID_PARAMETER;\n- }\n-\n- /*\n- * XXX: Not clear at this stage if there's any role for the\n- * OVS_DP_ATTR_UPCALL_PID and OVS_DP_ATTR_USER_FEATURES attributes passed\n- * from userspace.\n- */\n-\n- } else {\n- RtlZeroMemory(dpAttrs, sizeof dpAttrs);\n- }\n-\n- /* Output buffer has been validated while validating transact dev op. */\n- ASSERT(msgOut != NULL && usrParamsCtx->outputLength >= sizeof *msgOut);\n-\n- NlBufInit(&nlBuf, usrParamsCtx->outputBuffer, usrParamsCtx->outputLength);\n-\n- if (dpAttrs[OVS_DP_ATTR_NAME] != NULL) {\n- if (!OvsCompareString(NlAttrGet(dpAttrs[OVS_DP_ATTR_NAME]),\n- OVS_SYSTEM_DP_NAME)) {\n-\n- /* Creation of new datapaths is not supported. */\n- if (usrParamsCtx->ovsMsg->genlMsg.cmd == OVS_DP_CMD_SET) {\n- nlError = NL_ERROR_NOTSUPP;\n- goto cleanup;\n- }\n-\n- nlError = NL_ERROR_NODEV;\n- goto cleanup;\n- }\n- } else if ((UINT32)msgIn->ovsHdr.dp_ifindex != gOvsSwitchContext->dpNo) {\n- nlError = NL_ERROR_NODEV;\n- goto cleanup;\n- }\n-\n- if (usrParamsCtx->ovsMsg->genlMsg.cmd == OVS_DP_CMD_NEW) {\n- nlError = NL_ERROR_EXIST;\n- goto cleanup;\n- }\n-\n- status = OvsDpFillInfo(gOvsSwitchContext, msgIn, &nlBuf);\n-\n- *replyLen = NlBufSize(&nlBuf);\n-\n-cleanup:\n- if (nlError != NL_ERROR_SUCCESS) {\n- POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)\n- usrParamsCtx->outputBuffer;\n-\n- ASSERT(msgError);\n- NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);\n- ASSERT(*replyLen != 0);\n- }\n-\n- return STATUS_SUCCESS;\n-}\n-\n-\n-NTSTATUS\n-OvsSetupDumpStart(POVS_USER_PARAMS_CONTEXT usrParamsCtx)\n-{\n- POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;\n- POVS_OPEN_INSTANCE instance =\n- (POVS_OPEN_INSTANCE)usrParamsCtx->ovsInstance;\n-\n- /* input buffer has been validated while validating write dev op. */\n- ASSERT(msgIn != NULL && usrParamsCtx->inputLength >= sizeof *msgIn);\n-\n- /* A write operation that does not indicate dump start is invalid. */\n- if ((msgIn->nlMsg.nlmsgFlags & NLM_F_DUMP) != NLM_F_DUMP) {\n- return STATUS_INVALID_PARAMETER;\n- }\n- /* XXX: Handle other NLM_F_* flags in the future. */\n-\n- /*\n- * This operation should be setting up the dump state. If there's any\n- * previous state, clear it up so as to set it up afresh.\n- */\n- FreeUserDumpState(instance);\n-\n- return InitUserDumpState(instance, msgIn);\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Utility function to map the output buffer in an IRP. The buffer is assumed\n- * to have been passed down using METHOD_OUT_DIRECT (Direct I/O).\n- * --------------------------------------------------------------------------\n- */\n-static NTSTATUS\n-MapIrpOutputBuffer(PIRP irp,\n- UINT32 bufferLength,\n- UINT32 requiredLength,\n- PVOID *buffer)\n-{\n- ASSERT(irp);\n- ASSERT(buffer);\n- ASSERT(bufferLength);\n- ASSERT(requiredLength);\n- if (!buffer || !irp || bufferLength == 0 || requiredLength == 0) {\n- return STATUS_INVALID_PARAMETER;\n- }\n-\n- if (bufferLength < requiredLength) {\n- return STATUS_NDIS_INVALID_LENGTH;\n- }\n- if (irp->MdlAddress == NULL) {\n- return STATUS_INVALID_PARAMETER;\n- }\n- *buffer = OvsGetMdlWithLowPriority(irp->MdlAddress);\n- if (*buffer == NULL) {\n- return STATUS_INSUFFICIENT_RESOURCES;\n- }\n-\n- return STATUS_SUCCESS;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Utility function to fill up information about the state of a port in a reply\n- * to* userspace.\n- * --------------------------------------------------------------------------\n- */\n-static NTSTATUS\n-OvsPortFillInfo(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- POVS_VPORT_EVENT_ENTRY eventEntry,\n- PNL_BUFFER nlBuf)\n-{\n- NTSTATUS status;\n- BOOLEAN ok;\n- OVS_MESSAGE msgOutTmp;\n- PNL_MSG_HDR nlMsg;\n-\n- ASSERT(NlBufAt(nlBuf, 0, 0) != 0 && nlBuf->bufRemLen >= sizeof msgOutTmp);\n-\n- msgOutTmp.nlMsg.nlmsgType = OVS_WIN_NL_VPORT_FAMILY_ID;\n- msgOutTmp.nlMsg.nlmsgFlags = 0; /* XXX: ? */\n-\n- /* driver intiated messages should have zerp seq number*/\n- msgOutTmp.nlMsg.nlmsgSeq = 0;\n- msgOutTmp.nlMsg.nlmsgPid = usrParamsCtx->ovsInstance->pid;\n-\n- msgOutTmp.genlMsg.version = nlVportFamilyOps.version;\n- msgOutTmp.genlMsg.reserved = 0;\n-\n- /* we don't have netdev yet, treat link up/down a adding/removing a port*/\n- if (eventEntry->type & (OVS_EVENT_LINK_UP | OVS_EVENT_CONNECT)) {\n- msgOutTmp.genlMsg.cmd = OVS_VPORT_CMD_NEW;\n- } else if (eventEntry->type &\n- (OVS_EVENT_LINK_DOWN | OVS_EVENT_DISCONNECT)) {\n- msgOutTmp.genlMsg.cmd = OVS_VPORT_CMD_DEL;\n- } else {\n- ASSERT(FALSE);\n- return STATUS_UNSUCCESSFUL;\n- }\n- msgOutTmp.ovsHdr.dp_ifindex = gOvsSwitchContext->dpNo;\n-\n- ok = NlMsgPutHead(nlBuf, (PCHAR)&msgOutTmp, sizeof msgOutTmp);\n- if (!ok) {\n- status = STATUS_INVALID_BUFFER_SIZE;\n- goto cleanup;\n- }\n-\n- ok = NlMsgPutTailU32(nlBuf, OVS_VPORT_ATTR_PORT_NO, eventEntry->portNo) &&\n- NlMsgPutTailU32(nlBuf, OVS_VPORT_ATTR_TYPE, eventEntry->ovsType) &&\n- NlMsgPutTailU32(nlBuf, OVS_VPORT_ATTR_UPCALL_PID,\n- eventEntry->upcallPid) &&\n- NlMsgPutTailString(nlBuf, OVS_VPORT_ATTR_NAME, eventEntry->ovsName);\n- if (!ok) {\n- status = STATUS_INVALID_BUFFER_SIZE;\n- goto cleanup;\n- }\n-\n- /* XXXX Should we add the port stats attributes?*/\n- nlMsg = (PNL_MSG_HDR)NlBufAt(nlBuf, 0, 0);\n- nlMsg->nlmsgLen = NlBufSize(nlBuf);\n- status = STATUS_SUCCESS;\n-\n-cleanup:\n- return status;\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Handler for reading events from the driver event queue. This handler is\n- * executed when user modes issues a socket receive on a socket assocaited\n- * with the MC group for events.\n- * XXX user mode should read multiple events in one system call\n- * --------------------------------------------------------------------------\n- */\n-static NTSTATUS\n-OvsReadEventCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen)\n-{\n- POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer;\n- POVS_OPEN_INSTANCE instance =\n- (POVS_OPEN_INSTANCE)usrParamsCtx->ovsInstance;\n- NL_BUFFER nlBuf;\n- NTSTATUS status;\n-\n- ASSERT(usrParamsCtx->devOp == OVS_READ_DEV_OP);\n-\n- /* Should never read events with a dump socket */\n- ASSERT(instance->dumpState.ovsMsg == NULL);\n-\n- /* Must have an event queue */\n- ASSERT(instance->eventQueue != NULL);\n-\n- /* Output buffer has been validated while validating read dev op. */\n- ASSERT(msgOut != NULL && usrParamsCtx->outputLength >= sizeof *msgOut);\n-\n- if (instance->protocol == NETLINK_NETFILTER) {\n- if (!instance->mcastMask) {\n- status = STATUS_SUCCESS;\n- *replyLen = 0;\n- goto cleanup;\n- }\n-\n- OVS_CT_EVENT_ENTRY ctEventEntry;\n- status = OvsRemoveCtEventEntry(usrParamsCtx->ovsInstance,\n- &ctEventEntry);\n-\n- if (status != STATUS_SUCCESS) {\n- /* If there were not elements, read should return no data. */\n- status = STATUS_SUCCESS;\n- *replyLen = 0;\n- goto cleanup;\n- }\n-\n- /* Driver intiated messages should have zero seq number */\n- status = OvsCreateNlMsgFromCtEntry(&ctEventEntry.entry,\n- usrParamsCtx->outputBuffer,\n- usrParamsCtx->outputLength,\n- ctEventEntry.type,\n- 0, /* No input msg */\n- usrParamsCtx->ovsInstance->pid,\n- NFNETLINK_V0,\n- gOvsSwitchContext->dpNo);\n- if (status == NDIS_STATUS_SUCCESS) {\n- *replyLen = msgOut->nlMsg.nlmsgLen;\n- }\n- } else if (instance->protocol == NETLINK_GENERIC) {\n- NlBufInit(&nlBuf,\n- usrParamsCtx->outputBuffer,\n- usrParamsCtx->outputLength);\n-\n- OVS_VPORT_EVENT_ENTRY eventEntry;\n- /* remove vport event entry from the vport event queue */\n- status = OvsRemoveVportEventEntry(usrParamsCtx->ovsInstance,\n- &eventEntry);\n- if (status != STATUS_SUCCESS) {\n- /* If there were not elements, read should return no data. */\n- status = STATUS_SUCCESS;\n- *replyLen = 0;\n- goto cleanup;\n- }\n-\n- status = OvsPortFillInfo(usrParamsCtx, &eventEntry, &nlBuf);\n- if (status == NDIS_STATUS_SUCCESS) {\n- *replyLen = NlBufSize(&nlBuf);\n- }\n- } else {\n- status = STATUS_INVALID_PARAMETER;\n- }\n-\n-cleanup:\n- return status;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Command Handler for 'OVS_CTRL_CMD_SOCK_PROP'.\n- *\n- * Handler to set and verify socket properties between userspace and kernel.\n- *\n- * Protocol is passed down by the userspace. It refers to the NETLINK family\n- * and could be of different types (NETLINK_GENERIC/NETLINK_NETFILTER etc.,)\n- * This function parses out the protocol and adds it to the open instance.\n- *\n- * PID is generated by the kernel and is set in userspace after querying the\n- * kernel for it. This function does not modify PID set in the kernel,\n- * instead it verifies if it was sent down correctly.\n- *\n- * XXX -This method can be modified to handle all Socket properties thereby\n- * eliminating the use of OVS_IOCTL_GET_PID\n- *\n- * --------------------------------------------------------------------------\n- */\n-static NTSTATUS\n-OvsSockPropCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen)\n-{\n- static const NL_POLICY ovsSocketPolicy[] = {\n- [OVS_NL_ATTR_SOCK_PROTO] = { .type = NL_A_U32, .optional = TRUE },\n- [OVS_NL_ATTR_SOCK_PID] = { .type = NL_A_U32, .optional = TRUE }\n- };\n- PNL_ATTR attrs[ARRAY_SIZE(ovsSocketPolicy)];\n-\n- if (usrParamsCtx->outputLength < sizeof(OVS_MESSAGE)) {\n- return STATUS_NDIS_INVALID_LENGTH;\n- }\n-\n- NL_BUFFER nlBuf;\n- POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;\n- POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer;\n- POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)usrParamsCtx->ovsInstance;\n- UINT32 protocol;\n- PNL_MSG_HDR nlMsg;\n- UINT32 pid;\n-\n- /* Parse the input */\n- if (!NlAttrParse((PNL_MSG_HDR)msgIn,\n- NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN,\n- NlMsgAttrsLen((PNL_MSG_HDR)msgIn),\n- ovsSocketPolicy,\n- ARRAY_SIZE(ovsSocketPolicy),\n- attrs,\n- ARRAY_SIZE(attrs))) {\n- return STATUS_INVALID_PARAMETER;\n- }\n-\n- /* Set the Protocol if it was passed down */\n- if (attrs[OVS_NL_ATTR_SOCK_PROTO]) {\n- protocol = NlAttrGetU32(attrs[OVS_NL_ATTR_SOCK_PROTO]);\n- if (protocol) {\n- instance->protocol = protocol;\n- }\n- }\n-\n- /* Verify if the PID sent down matches the kernel */\n- if (attrs[OVS_NL_ATTR_SOCK_PID]) {\n- pid = NlAttrGetU32(attrs[OVS_NL_ATTR_SOCK_PID]);\n- if (pid != instance->pid) {\n- OVS_LOG_ERROR(\"Received invalid pid:%d expected:%d\",\n- pid, instance->pid);\n- return STATUS_INVALID_PARAMETER;\n- }\n- }\n-\n- /* Prepare the output */\n- NlBufInit(&nlBuf, usrParamsCtx->outputBuffer, usrParamsCtx->outputLength);\n- if(!NlFillOvsMsg(&nlBuf, msgIn->nlMsg.nlmsgType, NLM_F_MULTI,\n- msgIn->nlMsg.nlmsgSeq, msgIn->nlMsg.nlmsgPid,\n- msgIn->genlMsg.cmd, msgIn->genlMsg.version,\n- gOvsSwitchContext->dpNo)){\n- return STATUS_INVALID_BUFFER_SIZE;\n- }\n-\n- if (!NlMsgPutTailU32(&nlBuf, OVS_NL_ATTR_SOCK_PID,\n- instance->pid)) {\n- return STATUS_INVALID_BUFFER_SIZE;\n- }\n-\n- if (!NlMsgPutTailU32(&nlBuf, OVS_NL_ATTR_SOCK_PROTO,\n- instance->protocol)) {\n- return STATUS_INVALID_BUFFER_SIZE;\n- }\n-\n- nlMsg = (PNL_MSG_HDR)NlBufAt(&nlBuf, 0, 0);\n- nlMsg->nlmsgLen = NlBufSize(&nlBuf);\n- *replyLen = msgOut->nlMsg.nlmsgLen;\n-\n- return STATUS_SUCCESS;\n-}\ndiff --git a/datapath-windows/ovsext/Datapath.h b/datapath-windows/ovsext/Datapath.h\ndeleted file mode 100644\nindex 427682627..000000000\n--- a/datapath-windows/ovsext/Datapath.h\n+++ /dev/null\n@@ -1,133 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-/*\n- * XXX: OVS_USE_NL_INTERFACE is being used to keep the legacy DPIF interface\n- * alive while we transition over to the netlink based interface.\n- * OVS_USE_NL_INTERFACE = 0 => legacy inteface to use with dpif-windows.c\n- * OVS_USE_NL_INTERFACE = 1 => netlink inteface to use with ported dpif-linux.c\n- */\n-\n-#ifndef __DATAPATH_H_\n-#define __DATAPATH_H_ 1\n-\n-/*\n- * Device operations to tag netlink commands with. This is a bitmask since it\n- * is possible that a particular command can be invoked via different device\n- * operations.\n- */\n-#define OVS_READ_DEV_OP (1 << 0)\n-#define OVS_WRITE_DEV_OP (1 << 1)\n-#define OVS_TRANSACTION_DEV_OP (1 << 2)\n-\n-typedef struct _OVS_DEVICE_EXTENSION {\n- INT numberOpenInstance;\n- INT pidCount;\n-} OVS_DEVICE_EXTENSION, *POVS_DEVICE_EXTENSION;\n-\n-// forward declaration\n-typedef struct _OVS_USER_PACKET_QUEUE OVS_USER_PACKET_QUEUE,\n- *POVS_USER_PACKET_QUEUE;\n-\n-/*\n- * Private context for each handle on the device.\n- */\n-typedef struct _OVS_OPEN_INSTANCE {\n- UINT32 cookie;\n- PFILE_OBJECT fileObject;\n- PVOID eventQueue;\n- POVS_USER_PACKET_QUEUE packetQueue;\n- UINT32 pid;\n- UINT32 protocol; /* Refers to NETLINK Family (eg. NETLINK_GENERIC)*/\n- UINT32 mcastMask; /* Mask of subscribed Mcast Groups */\n-\n- struct {\n- POVS_MESSAGE ovsMsg; /* OVS message passed during dump start. */\n- UINT32 index[2]; /* markers to continue dump from. One or more\n- * of them may be used. Eg. in flow dump, the\n- * markers can store the row and the column\n- * indices. */\n- } dumpState; /* data to support dump commands. */\n- LIST_ENTRY pidLink; /* Links the instance to\n- * pidHashArray */\n-} OVS_OPEN_INSTANCE, *POVS_OPEN_INSTANCE;\n-\n-NDIS_STATUS OvsCreateDeviceObject(NDIS_HANDLE ovsExtDriverHandle);\n-VOID OvsDeleteDeviceObject();\n-NDIS_STATUS OvsInit();\n-VOID OvsCleanup();\n-\n-POVS_OPEN_INSTANCE OvsGetOpenInstance(PFILE_OBJECT fileObject,\n- UINT32 dpNo);\n-\n-NTSTATUS OvsCompleteIrpRequest(PIRP irp, ULONG_PTR infoPtr, NTSTATUS status);\n-\n-_IRQL_raises_(DISPATCH_LEVEL)\n-_IRQL_saves_global_(OldIrql, gOvsCtrlLock)\n-_Acquires_lock_(gOvsCtrlLock)\n-VOID OvsAcquireCtrlLock();\n-\n-_IRQL_requires_(DISPATCH_LEVEL)\n-_IRQL_restores_global_(OldIrql, gOvsCtrlLock)\n-_Requires_lock_held_(gOvsCtrlLock)\n-_Releases_lock_(gOvsCtrlLock)\n-VOID OvsReleaseCtrlLock();\n-\n-/*\n- * Utility structure and functions to collect in one place all the parameters\n- * passed during a call from userspace.\n- */\n-typedef struct _OVS_USER_PARAMS_CONTEXT {\n- PIRP irp; /* The IRP used for the userspace call. */\n- POVS_OPEN_INSTANCE ovsInstance; /* Private data of the device handle. */\n- UINT32 devOp; /* Device operation of the userspace call. */\n- POVS_MESSAGE ovsMsg; /* OVS message that userspace passed down. */\n- PVOID inputBuffer; /* Input data specified by userspace. Maybe NULL. */\n- UINT32 inputLength; /* Length of input buffer. */\n- PVOID outputBuffer; /* Output buffer specified by userspace for reading\n- * data. Maybe NULL. */\n- UINT32 outputLength; /* Length of output buffer. */\n-} OVS_USER_PARAMS_CONTEXT, *POVS_USER_PARAMS_CONTEXT;\n-\n-static __inline VOID\n-InitUserParamsCtx(PIRP irp,\n- POVS_OPEN_INSTANCE ovsInstance,\n- UINT32 devOp,\n- POVS_MESSAGE ovsMsg,\n- PVOID inputBuffer,\n- UINT32 inputLength,\n- PVOID outputBuffer,\n- UINT32 outputLength,\n- POVS_USER_PARAMS_CONTEXT usrParamsCtx)\n-{\n- usrParamsCtx->irp = irp;\n- usrParamsCtx->ovsInstance = ovsInstance;\n- usrParamsCtx->devOp = devOp;\n- usrParamsCtx->ovsMsg = ovsMsg;\n- usrParamsCtx->inputBuffer = inputBuffer;\n- usrParamsCtx->inputLength = inputLength;\n- usrParamsCtx->outputBuffer = outputBuffer;\n- usrParamsCtx->outputLength = outputLength;\n-}\n-\n-NTSTATUS InitUserDumpState(POVS_OPEN_INSTANCE instance,\n- POVS_MESSAGE ovsMsg);\n-\n-VOID FreeUserDumpState(POVS_OPEN_INSTANCE instance);\n-\n-NTSTATUS OvsSetupDumpStart(POVS_USER_PARAMS_CONTEXT usrParamsCtx);\n-\n-#endif /* __DATAPATH_H_ */\ndiff --git a/datapath-windows/ovsext/Debug.c b/datapath-windows/ovsext/Debug.c\ndeleted file mode 100644\nindex c3d14ae54..000000000\n--- a/datapath-windows/ovsext/Debug.c\n+++ /dev/null\n@@ -1,59 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#include \"precomp.h\"\n-\n-#include \"Debug.h\"\n-#ifdef DBG\n-#define OVS_DBG_DEFAULT OVS_DBG_INFO\n-#else\n-#define OVS_DBG_DEFAULT OVS_DBG_ERROR\n-#endif\n-\n-UINT32 ovsLogFlags = 0xffffffff;\n-UINT32 ovsLogLevel = OVS_DBG_DEFAULT;\n-BUILD_ASSERT(OVS_DBG_LAST < 31); /* 'ovsLogLevel' is 32 bits. */\n-\n-#define OVS_LOG_BUFFER_SIZE 384\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsLog --\n- * Utility function to log to the Windows debug console.\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-OvsLog(UINT32 level,\n- UINT32 flag,\n- CHAR *funcName,\n- UINT32 line,\n- CHAR *format,\n- ...)\n-{\n- va_list args;\n- CHAR buf[OVS_LOG_BUFFER_SIZE];\n-\n- if (level > ovsLogLevel || (ovsLogFlags & flag) == 0) {\n- return;\n- }\n-\n- buf[0] = 0;\n- va_start(args, format);\n- RtlStringCbVPrintfA(buf, sizeof (buf), format, args);\n- va_end(args);\n-\n- DbgPrintEx(DPFLTR_IHVNETWORK_ID, level, \"%s:%lu %s\\n\", funcName, line, buf);\n-}\ndiff --git a/datapath-windows/ovsext/Debug.h b/datapath-windows/ovsext/Debug.h\ndeleted file mode 100644\nindex 6660a98fa..000000000\n--- a/datapath-windows/ovsext/Debug.h\n+++ /dev/null\n@@ -1,76 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#ifndef __DEBUG_H_\n-#define __DEBUG_H_ 1\n-\n-#define OVS_DBG_INIT BIT32(0)\n-#define OVS_DBG_SWITCH BIT32(1)\n-#define OVS_DBG_VPORT BIT32(2)\n-#define OVS_DBG_FLOW BIT32(3)\n-#define OVS_DBG_QOS BIT32(4)\n-#define OVS_DBG_USER BIT32(5)\n-#define OVS_DBG_EXECUTE BIT32(6)\n-#define OVS_DBG_EVENT BIT32(7)\n-#define OVS_DBG_DISPATCH BIT32(8)\n-#define OVS_DBG_OID BIT32(9)\n-#define OVS_DBG_STATUS BIT32(10)\n-#define OVS_DBG_CHECKSUM BIT32(11)\n-#define OVS_DBG_VXLAN BIT32(12)\n-#define OVS_DBG_GRE BIT32(13)\n-#define OVS_DBG_ACTION BIT32(14)\n-#define OVS_DBG_DATAPATH BIT32(15)\n-#define OVS_DBG_PROPERTY BIT32(16)\n-#define OVS_DBG_IPHELPER BIT32(17)\n-#define OVS_DBG_BUFMGMT BIT32(18)\n-#define OVS_DBG_OTHERS BIT32(19)\n-#define OVS_DBG_NETLINK BIT32(20)\n-#define OVS_DBG_TUNFLT BIT32(21)\n-#define OVS_DBG_CONTRK BIT32(22)\n-#define OVS_DBG_GENEVE BIT32(23)\n-#define OVS_DBG_IPFRAG BIT32(24)\n-\n-#define OVS_DBG_LAST 24 /* Set this to the last defined module number. */\n-/* Please add above OVS_DBG_LAST. */\n-\n-#define OVS_DBG_ERROR DPFLTR_ERROR_LEVEL\n-#define OVS_DBG_WARN DPFLTR_WARNING_LEVEL\n-#define OVS_DBG_TRACE DPFLTR_TRACE_LEVEL\n-#define OVS_DBG_INFO DPFLTR_INFO_LEVEL\n-#define OVS_DBG_LOUD (DPFLTR_INFO_LEVEL + 1)\n-\n-\n-\n-VOID OvsLog(UINT32 level, UINT32 flag, CHAR *funcName,\n- UINT32 line, CHAR *format, ...);\n-\n-\n-#define OVS_LOG_LOUD(_format, ...) \\\n- OvsLog(OVS_DBG_LOUD, OVS_DBG_MOD, __FUNCTION__, __LINE__, _format, __VA_ARGS__)\n-\n-#define OVS_LOG_INFO(_format, ...) \\\n- OvsLog(OVS_DBG_INFO, OVS_DBG_MOD, __FUNCTION__, __LINE__, _format, __VA_ARGS__)\n-\n-#define OVS_LOG_TRACE(_format, ...) \\\n- OvsLog(OVS_DBG_TRACE, OVS_DBG_MOD, __FUNCTION__, __LINE__, _format, __VA_ARGS__)\n-\n-#define OVS_LOG_ERROR(_format, ...) \\\n- OvsLog(OVS_DBG_ERROR, OVS_DBG_MOD, __FUNCTION__, __LINE__, _format, __VA_ARGS__)\n-\n-#define OVS_LOG_WARN(_format, ...) \\\n- OvsLog(OVS_DBG_WARN, OVS_DBG_MOD, __FUNCTION__, __LINE__, _format, __VA_ARGS__)\n-\n-#endif /* __DEBUG_H_ */\ndiff --git a/datapath-windows/ovsext/DpInternal.h b/datapath-windows/ovsext/DpInternal.h\ndeleted file mode 100644\nindex 6af5748e1..000000000\n--- a/datapath-windows/ovsext/DpInternal.h\n+++ /dev/null\n@@ -1,371 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#ifndef __DP_INTERNAL_H_\n-#define __DP_INTERNAL_H_ 1\n-\n-#include <netioapi.h>\n-#define IFNAMSIZ IF_NAMESIZE\n-#include \"../ovsext/Netlink/Netlink.h\"\n-\n-#define OVS_DP_NUMBER ((uint32_t) 0)\n-\n-typedef __declspec(align(8)) uint64_t Ovs64AlignedU64;\n-typedef __declspec(align(8)) ovs_be64 Ovs64AlignedBe64;\n-#pragma pack(push, 1)\n-\n-#define OVS_MAX_PORT_NAME_LENGTH IFNAMSIZ\n-\n-typedef struct _OVS_VPORT_GET {\n- uint32_t dpNo;\n- uint32_t portNo;\n- char name[OVS_MAX_PORT_NAME_LENGTH];\n-} OVS_VPORT_GET, *POVS_VPORT_GET;\n-\n-#define OVS_MAX_VM_UUID_LEN 128\n-#define OVS_MAX_VIF_UUID_LEN 128\n-\n-typedef struct _OVS_VPORT_EXT_INFO {\n- uint32_t dpNo;\n- uint32_t portNo;\n- uint8_t macAddress[ETH_ADDR_LEN];\n- uint8_t permMACAddress[ETH_ADDR_LEN];\n- uint8_t vmMACAddress[ETH_ADDR_LEN];\n- uint16_t nicIndex;\n- uint32_t portId;\n- uint32_t type;\n- uint32_t mtu;\n- char name[OVS_MAX_PORT_NAME_LENGTH];\n- uint32_t status;\n- char vmUUID[OVS_MAX_VM_UUID_LEN];\n- char vifUUID[OVS_MAX_VIF_UUID_LEN];\n-} OVS_VPORT_EXT_INFO, *POVS_VPORT_EXT_INFO;\n-\n-\n-/* Flows. */\n-#define OVSWIN_VLAN_CFI 0x1000\n-\n-/* Used for OvsFlowKey's dlType member for frames that have no Ethernet type,\n- * that is, pure 802.2 frames. */\n-#define OVSWIN_DL_TYPE_NONE 0x5ff\n-\n-typedef struct L4Key {\n- ovs_be16 tpSrc; /* TCP/UDP/SCTP source port. */\n- ovs_be16 tpDst; /* TCP/UDP/SCTP destination port. */\n-} L4Key;\n-\n-typedef struct Ipkey {\n- ovs_be32 nwSrc; /* IPv4 source address. */\n- ovs_be32 nwDst; /* IPv4 destination address. */\n- uint8_t nwProto; /* IP protocol or low 8 bits of ARP opcode. */\n- uint8_t nwTos; /* IP ToS (including DSCP and ECN). */\n- uint8_t nwTtl; /* IP TTL/Hop Limit. */\n- uint8_t nwFrag; /* FLOW_FRAG_* flags. */\n- L4Key l4;\n-} IpKey; /* Size of 16 byte. */\n-\n-typedef struct ArpKey {\n- ovs_be32 nwSrc; /* IPv4 source address. */\n- ovs_be32 nwDst; /* IPv4 destination address. */\n- uint8_t arpSha[6]; /* ARP/ND source hardware address. */\n- uint8_t arpTha[6]; /* ARP/ND target hardware address. */\n- uint8_t nwProto; /* IP protocol or low 8 bits of ARP opcode. */\n- uint8_t pad[3];\n-} ArpKey; /* Size of 24 byte. */\n-\n-typedef struct Ipv6Key {\n- struct in6_addr ipv6Src; /* IPv6 source address. */\n- struct in6_addr ipv6Dst; /* IPv6 destination address. */\n- ovs_be32 ipv6Label; /* IPv6 flow label. */\n- uint8_t nwProto; /* IP protocol or low 8 bits of ARP opcode. */\n- uint8_t nwTos; /* IP ToS (including DSCP and ECN). */\n- uint8_t nwTtl; /* IP TTL/Hop Limit. */\n- uint8_t nwFrag; /* FLOW_FRAG_* flags. */\n- L4Key l4;\n- uint32_t pad;\n-} Ipv6Key; /* Size of 48 byte. */\n-\n-typedef struct Icmp6Key {\n- struct in6_addr ipv6Src; /* IPv6 source address. */\n- struct in6_addr ipv6Dst; /* IPv6 destination address. */\n- ovs_be32 ipv6Label; /* IPv6 flow label. */\n- uint8_t nwProto; /* IP protocol or low 8 bits of ARP opcode. */\n- uint8_t nwTos; /* IP ToS (including DSCP and ECN). */\n- uint8_t nwTtl; /* IP TTL/Hop Limit. */\n- uint8_t nwFrag; /* FLOW_FRAG_* flags. */\n- L4Key l4;\n- uint8_t arpSha[6]; /* ARP/ND source hardware address. */\n- uint8_t arpTha[6]; /* ARP/ND target hardware address. */\n- struct in6_addr ndTarget; /* IPv6 neighbor discovery (ND) target. */\n-} Icmp6Key; /* Size of 72 byte. */\n-\n-typedef struct VlanKey {\n- ovs_be16 vlanTci; /* If 802.1Q, TCI | VLAN_CFI; otherwise 0. */\n- ovs_be16 vlanTpid; /* Vlan type. Generally 802.1q or 802.1ad.*/\n-} VlanKey;\n-\n-typedef struct L2Key {\n- uint32_t inPort; /* Port number of input port. */\n- union {\n- struct {\n- uint16_t offset;\n- uint16_t keyLen;\n- };\n- uint32_t val;\n- };\n- uint8_t dlSrc[6]; /* Ethernet source address. */\n- uint8_t dlDst[6]; /* Ethernet destination address. */\n- ovs_be16 dlType; /* Ethernet frame type. */\n- struct VlanKey vlanKey; /* VLAN header. */\n- uint16_t pad[3]; /* Padding 6 bytes. */\n-} L2Key; /* Size of 32 byte. */\n-\n-/* Number of packet attributes required to store OVS tunnel key. */\n-#define NUM_PKT_ATTR_REQUIRED 35\n-#define TUN_OPT_MAX_LEN 255\n-\n-typedef union OvsIPTunnelKey {\n- /* Options should always be the first member of tunnel key.\n- * They are stored at the end of the array if they are less than the\n- * maximum size. This allows us to get the benefits of variable length\n- * matching for small options.\n- */\n- struct {\n- UINT8 tunOpts[TUN_OPT_MAX_LEN]; /* Tunnel options. */\n- UINT8 tunOptLen; /* Tunnel option length in byte. */\n-\n- SOCKADDR_INET dst; /* IPv4/6 destination address. */\n- SOCKADDR_INET src; /* IPv4/6 source address. */\n- ovs_be64 tunnelId;\n- uint16_t flags;\n- uint8_t tos;\n- uint8_t ttl;\n- union {\n- uint32_t pad;\n- struct {\n- ovs_be16 dst_port;\n- uint16_t flow_hash;\n- };\n- };\n- };\n- uint64_t attr[NUM_PKT_ATTR_REQUIRED];\n-} OvsIPTunnelKey; /* Size of 280+40-8= 312 byte. */\n-\n-static __inline uint8_t\n-IPTunnelKeyGetOptionsOffset(const OvsIPTunnelKey *key)\n-{\n- return TUN_OPT_MAX_LEN - key->tunOptLen;\n-}\n-\n-static __inline uint8_t *\n-IPTunnelKeyGetOptions(OvsIPTunnelKey *key)\n-{\n- return key->tunOpts + IPTunnelKeyGetOptionsOffset(key);\n-}\n-\n-static __inline uint16_t\n-IPTunnelKeyGetRealSize(OvsIPTunnelKey *key)\n-{\n- return sizeof(OvsIPTunnelKey) - IPTunnelKeyGetOptionsOffset(key);\n-}\n-\n-typedef struct MplsKey {\n- ovs_be32 lse; /* MPLS topmost label stack entry. */\n- uint8 pad[4];\n-} MplsKey; /* Size of 8 bytes. */\n-\n-typedef __declspec(align(8)) struct OvsFlowKey {\n- OvsIPTunnelKey tunKey; /* 280 bytes? */\n- L2Key l2; /* 32 bytes */\n- union {\n- /* These headers are mutually exclusive. */\n- IpKey ipKey; /* size 16 */\n- ArpKey arpKey; /* size 24 */\n- Ipv6Key ipv6Key; /* size 48 */\n- Icmp6Key icmp6Key; /* size 72 */\n- MplsKey mplsKey; /* size 8 */\n- };\n- UINT32 recircId; /* Recirculation ID. */\n- UINT32 dpHash; /* Datapath calculated hash value. */\n- struct {\n- /* Connection tracking fields. */\n- UINT16 zone;\n- UINT32 mark;\n- UINT32 state;\n- struct ovs_key_ct_labels labels;\n- struct ovs_key_ct_tuple_ipv4 tuple_ipv4;\n- struct ovs_key_ct_tuple_ipv6 tuple_ipv6;\n- } ct; /* Connection Tracking Flags */\n-} OvsFlowKey;\n-\n-#define OVS_WIN_IP_TUNNEL_KEY_SIZE (sizeof (OvsIPTunnelKey))\n-#define OVS_L2_KEY_SIZE (sizeof (L2Key))\n-#define OVS_IP_KEY_SIZE (sizeof (IpKey))\n-#define OVS_IPV6_KEY_SIZE (sizeof (Ipv6Key))\n-#define OVS_ARP_KEY_SIZE (sizeof (ArpKey))\n-#define OVS_ICMPV6_KEY_SIZE (sizeof (Icmp6Key))\n-#define OVS_MPLS_KEY_SIZE (sizeof (MplsKey))\n-#define OVS_TUPLE_IPV6 (sizeof (struct ovs_key_ct_tuple_ipv6))\n-\n-typedef struct OvsFlowStats {\n- Ovs64AlignedU64 packetCount;\n- Ovs64AlignedU64 byteCount;\n- uint64_t used;\n- uint8_t tcpFlags;\n-} OvsFlowStats;\n-\n-typedef struct OvsFlowInfo {\n- OvsFlowKey key;\n- struct OvsFlowStats stats;\n- uint32_t actionsLen;\n- PNL_ATTR actions;\n-} OvsFlowInfo;\n-\n-enum GetFlags {\n- FLOW_GET_KEY = 0x00000001,\n- FLOW_GET_STATS = 0x00000010,\n- FLOW_GET_ACTIONS = 0x00000100,\n-};\n-\n-typedef struct OvsFlowDumpInput {\n- uint32_t dpNo;\n- uint32_t position[2]; /* Offset hint to the start of flow dump. */\n- /* 0 - index of the hash table.\n- * 1 - nth element in the hash table index. */\n- uint32_t getFlags; /* Information to get in addition to keys. */\n- uint32_t actionsLen;\n-} OvsFlowDumpInput;\n-\n-\n-typedef struct OvsFlowDumpOutput {\n- /* Hint for the next flow dump operation. */\n- uint32_t position[2];\n-\n- /* #flows (currently 0 or 1). In case the buffer is too small to output all\n- * actions, this field indicates actual size needed to dump all actions. */\n- uint32_t n;\n-\n- OvsFlowInfo flow;\n-} OvsFlowDumpOutput;\n-\n-typedef struct OvsFlowGetInput {\n- uint32_t dpNo;\n- OvsFlowKey key;\n- uint32_t getFlags; /* Information to get in addition to keys. */\n- uint32_t actionsLen; /* Sizeof of buffer for actions. */\n-} OvsFlowGetInput;\n-\n-typedef struct OvsFlowGetOutput {\n- OvsFlowInfo info; /* Variable length. */\n-} OvsFlowGetOutput;\n-\n-\n-typedef enum OvsFlowPutFlags {\n- OVSWIN_FLOW_PUT_CREATE = 1 << 0,\n- OVSWIN_FLOW_PUT_MODIFY = 1 << 1,\n- OVSWIN_FLOW_PUT_DELETE = 1 << 2,\n-\n- OVSWIN_FLOW_PUT_CLEAR = 1 << 3\n-} OvsFlowPutFlags;\n-\n-\n-typedef struct OvsFlowPut {\n- uint32_t dpNo;\n- uint32_t actionsLen;\n- OvsFlowKey key;\n- uint32_t flags;\n- PNL_ATTR actions;\n-} OvsFlowPut;\n-\n-#define OVS_MIN_PACKET_SIZE 60\n-typedef struct _OVS_PACKET_INFO {\n- uint32_t totalLen;\n- uint32_t userDataLen;\n- uint32_t packetLen;\n- uint32_t queue;\n- uint32_t inPort;\n- uint32_t cmd;\n- OvsIPTunnelKey tunnelKey;\n- uint8_t *payload;\n- /* Includes user data defined as chain of netlink attributes followed by the\n- * packet data. */\n- uint8_t data[0];\n-} OVS_PACKET_INFO, *POVS_PACKET_INFO;\n-\n-typedef struct OvsPacketExecute {\n- uint32_t dpNo;\n- uint32_t inPort;\n- uint16 mru;\n- uint32_t packetLen;\n- uint32_t actionsLen;\n- PNL_MSG_HDR nlMsgHdr;\n- PCHAR packetBuf;\n- PNL_ATTR actions;\n- PNL_ATTR *keyAttrs;\n-} OvsPacketExecute;\n-\n-\n-typedef struct _OVS_EVENT_SUBSCRIBE {\n- uint32_t cookie;\n- uint32_t dpNo;\n- uint32_t subscribe;\n- uint32_t mask;\n- uint32_t mcastGrp;\n- uint32_t protocol;\n-} OVS_EVENT_SUBSCRIBE, *POVS_EVENT_SUBSCRIBE;\n-\n-typedef struct _OVS_EVENT_POLL {\n- uint32_t cookie;\n- uint32_t dpNo;\n-} OVS_EVENT_POLL, *POVS_EVENT_POLL;\n-\n-enum {\n- OVS_EVENT_CONNECT = ((uint32_t)0x1 << 0),\n- OVS_EVENT_DISCONNECT = ((uint32_t)0x1 << 1),\n- OVS_EVENT_LINK_UP = ((uint32_t)0x1 << 2),\n- OVS_EVENT_LINK_DOWN = ((uint32_t)0x1 << 3),\n- OVS_EVENT_MAC_CHANGE = ((uint32_t)0x1 << 4),\n- OVS_EVENT_MTU_CHANGE = ((uint32_t)0x1 << 5),\n- OVS_EVENT_MASK_ALL = 0x3f,\n-};\n-\n-enum {\n- OVS_EVENT_CT_NEW = (1 << 0),\n- OVS_EVENT_CT_DELETE = (1 << 1),\n- OVS_EVENT_CT_UPDATE = (1 << 2),\n- OVS_EVENT_CT_MASK_ALL = 0x7\n-};\n-\n-/* Supported mcast event groups */\n-enum OVS_MCAST_EVENT_TYPES {\n- OVS_MCAST_VPORT_EVENT,\n- OVS_MCAST_CT_EVENT,\n- __OVS_MCAST_EVENT_TYPES_MAX\n-};\n-#define OVS_MCAST_EVENT_TYPES_MAX (__OVS_MCAST_EVENT_TYPES_MAX \\\n- - OVS_MCAST_VPORT_EVENT)\n-\n-typedef struct _OVS_VPORT_EVENT_ENTRY {\n- UINT32 portNo;\n- OVS_VPORT_TYPE ovsType;\n- UINT32 upcallPid;\n- CHAR ovsName[OVS_MAX_PORT_NAME_LENGTH];\n- UINT32 type;\n-} OVS_VPORT_EVENT_ENTRY, *POVS_VPORT_EVENT_ENTRY;\n-\n-#pragma pack(pop)\n-\n-#endif /* __DP_INTERNAL_H_ */\ndiff --git a/datapath-windows/ovsext/Driver.c b/datapath-windows/ovsext/Driver.c\ndeleted file mode 100644\nindex 0d23adaf7..000000000\n--- a/datapath-windows/ovsext/Driver.c\n+++ /dev/null\n@@ -1,204 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#include \"precomp.h\"\n-#include \"Switch.h\"\n-#include \"User.h\"\n-#include \"Datapath.h\"\n-\n-#ifdef OVS_DBG_MOD\n-#undef OVS_DBG_MOD\n-#endif\n-#define OVS_DBG_MOD OVS_DBG_DRIVER\n-#include \"Debug.h\"\n-\n-/* Global handles. XXX: Some of them need not be global. */\n-/*\n- * Maps to DriverObject and FilterDriverContext parameters in the NDIS filter\n- * driver functions.\n- * DriverObject is specified by NDIS.\n- * FilterDriverContext is specified by the filter driver.\n- */\n-NDIS_HANDLE gOvsExtDriverObject;\n-\n-/*\n- * Maps to NdisFilterHandle parameter in the NDIS filter driver functions.\n- * NdisFilterHandle is returned by NDISFRegisterFilterDriver.\n- */\n-NDIS_HANDLE gOvsExtDriverHandle;\n-\n-/*\n- * Maps to FilterModuleContext parameter in the NDIS filter driver functions.\n- * FilterModuleContext is a allocated by the driver in the FilterAttach\n- * function.\n- */\n-extern POVS_SWITCH_CONTEXT gOvsSwitchContext;\n-\n-static PWCHAR ovsExtFriendlyName = L\"Open vSwitch Extension\";\n-static PWCHAR ovsExtServiceName = L\"OVSExt\";\n-NDIS_STRING ovsExtGuidUC;\n-NDIS_STRING ovsExtFriendlyNameUC;\n-\n-static PWCHAR ovsExtGuidStr = L\"{583CC151-73EC-4A6A-8B47-578297AD7623}\";\n-static const GUID ovsExtGuid = {\n- 0x583cc151,\n- 0x73ec,\n- 0x4a6a,\n- {0x8b, 0x47, 0x57, 0x82, 0x97, 0xad, 0x76, 0x23}\n-};\n-\n-DRIVER_INITIALIZE DriverEntry;\n-\n-/* Declarations of callback functions for the filter driver. */\n-DRIVER_UNLOAD OvsExtUnload;\n-FILTER_NET_PNP_EVENT OvsExtNetPnPEvent;\n-FILTER_STATUS OvsExtStatus;\n-\n-FILTER_ATTACH OvsExtAttach;\n-FILTER_DETACH OvsExtDetach;\n-FILTER_RESTART OvsExtRestart;\n-FILTER_PAUSE OvsExtPause;\n-\n-FILTER_SEND_NET_BUFFER_LISTS OvsExtSendNBL;\n-FILTER_SEND_NET_BUFFER_LISTS_COMPLETE OvsExtSendNBLComplete;\n-FILTER_CANCEL_SEND_NET_BUFFER_LISTS OvsExtCancelSendNBL;\n-FILTER_RECEIVE_NET_BUFFER_LISTS OvsExtReceiveNBL;\n-FILTER_RETURN_NET_BUFFER_LISTS OvsExtReturnNBL;\n-\n-FILTER_OID_REQUEST OvsExtOidRequest;\n-FILTER_OID_REQUEST_COMPLETE OvsExtOidRequestComplete;\n-FILTER_CANCEL_OID_REQUEST OvsExtCancelOidRequest;\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Init/Load function for the OVSEXT filter Driver.\n- * --------------------------------------------------------------------------\n- */\n-NTSTATUS\n-DriverEntry(PDRIVER_OBJECT driverObject,\n- PUNICODE_STRING registryPath)\n-{\n- NDIS_STATUS status;\n- NDIS_FILTER_DRIVER_CHARACTERISTICS driverChars;\n-\n- UNREFERENCED_PARAMETER(registryPath);\n-\n- /* Initialize driver associated data structures. */\n- status = OvsInit();\n- if (status != NDIS_STATUS_SUCCESS) {\n- goto cleanup;\n- }\n-\n- gOvsExtDriverObject = driverObject;\n-\n- RtlZeroMemory(&driverChars, sizeof driverChars);\n- driverChars.Header.Type = NDIS_OBJECT_TYPE_FILTER_DRIVER_CHARACTERISTICS;\n- driverChars.Header.Size = sizeof driverChars;\n- driverChars.Header.Revision = NDIS_FILTER_CHARACTERISTICS_REVISION_2;\n- driverChars.MajorNdisVersion = NDIS_FILTER_MAJOR_VERSION;\n- driverChars.MinorNdisVersion = NDIS_FILTER_MINOR_VERSION;\n- driverChars.MajorDriverVersion = 1;\n- driverChars.MinorDriverVersion = 0;\n- driverChars.Flags = 0;\n-\n- RtlInitUnicodeString(&driverChars.ServiceName, ovsExtServiceName);\n- RtlInitUnicodeString(&ovsExtFriendlyNameUC, ovsExtFriendlyName);\n- RtlInitUnicodeString(&ovsExtGuidUC, ovsExtGuidStr);\n-\n- driverChars.FriendlyName = ovsExtFriendlyNameUC;\n- driverChars.UniqueName = ovsExtGuidUC;\n-\n- driverChars.AttachHandler = OvsExtAttach;\n- driverChars.DetachHandler = OvsExtDetach;\n- driverChars.RestartHandler = OvsExtRestart;\n- driverChars.PauseHandler = OvsExtPause;\n-\n- driverChars.SendNetBufferListsHandler = OvsExtSendNBL;\n- driverChars.SendNetBufferListsCompleteHandler = OvsExtSendNBLComplete;\n- driverChars.CancelSendNetBufferListsHandler = OvsExtCancelSendNBL;\n- driverChars.ReceiveNetBufferListsHandler = NULL;\n- driverChars.ReturnNetBufferListsHandler = NULL;\n-\n- driverChars.OidRequestHandler = OvsExtOidRequest;\n- driverChars.OidRequestCompleteHandler = OvsExtOidRequestComplete;\n- driverChars.CancelOidRequestHandler = OvsExtCancelOidRequest;\n-\n- driverChars.DevicePnPEventNotifyHandler = NULL;\n- driverChars.NetPnPEventHandler = OvsExtNetPnPEvent;\n- driverChars.StatusHandler = NULL;\n-\n- driverObject->DriverUnload = OvsExtUnload;\n-\n- gOvsExtDriverHandle = NULL;\n- status = NdisFRegisterFilterDriver(driverObject,\n- (NDIS_HANDLE)gOvsExtDriverObject,\n- &driverChars,\n- &gOvsExtDriverHandle);\n- if (status != NDIS_STATUS_SUCCESS) {\n- goto cleanup;\n- }\n-\n- /* Create the communication channel for userspace. */\n- status = OvsCreateDeviceObject(gOvsExtDriverHandle);\n- if (status != NDIS_STATUS_SUCCESS) {\n- NdisFDeregisterFilterDriver(gOvsExtDriverHandle);\n- gOvsExtDriverHandle = NULL;\n- goto cleanup;\n- }\n-\n-cleanup:\n- if (status != NDIS_STATUS_SUCCESS){\n- OvsCleanup();\n- }\n-\n- return status;\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Un-init/Unload function for the OVS intermediate Driver.\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-OvsExtUnload(struct _DRIVER_OBJECT *driverObject)\n-{\n- UNREFERENCED_PARAMETER(driverObject);\n-\n- OvsDeleteDeviceObject();\n-\n- NdisFDeregisterFilterDriver(gOvsExtDriverHandle);\n-\n- /* Release driver associated data structures. */\n- OvsCleanup();\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Implements filter driver's FilterStatus function.\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-OvsExtStatus(NDIS_HANDLE filterModuleContext,\n- PNDIS_STATUS_INDICATION statusIndication)\n-{\n- UNREFERENCED_PARAMETER(statusIndication);\n- POVS_SWITCH_CONTEXT switchObject = (POVS_SWITCH_CONTEXT)filterModuleContext;\n-\n- NdisFIndicateStatus(switchObject->NdisFilterHandle, statusIndication);\n-}\ndiff --git a/datapath-windows/ovsext/Ethernet.h b/datapath-windows/ovsext/Ethernet.h\ndeleted file mode 100644\nindex 1d69d475e..000000000\n--- a/datapath-windows/ovsext/Ethernet.h\n+++ /dev/null\n@@ -1,452 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#ifndef __ETHERNET_H_\n-#define __ETHERNET_H_ 1\n-\n-#define ETH_LADRF_LEN 2\n-#define ETH_ADDR_LENGTH 6\n-\n-typedef UINT8 Eth_Address[ETH_ADDR_LENGTH];\n-\n-#define ETH_ADDR_FMT_STR \"%02x:%02x:%02x:%02x:%02x:%02x\"\n-#define ETH_ADDR_FMT_ARGS(a) ((UINT8 *)a)[0], ((UINT8 *)a)[1], ((UINT8 *)a)[2], \\\n- ((UINT8 *)a)[3], ((UINT8 *)a)[4], ((UINT8 *)a)[5]\n-\n-#define ETH_MAX_EXACT_MULTICAST_ADDRS 32\n-\n-typedef enum Eth_RxMode {\n- ETH_FILTER_UNICAST = 0x0001, /* pass unicast (directed) frames */\n- ETH_FILTER_MULTICAST = 0x0002, /* pass some multicast frames */\n- ETH_FILTER_ALLMULTI = 0x0004, /* pass *all* multicast frames */\n- ETH_FILTER_BROADCAST = 0x0008, /* pass broadcast frames */\n- ETH_FILTER_PROMISC = 0x0010, /* pass all frames (ie no filter) */\n- ETH_FILTER_USE_LADRF = 0x0020, /* use the LADRF for multicast filtering */\n- ETH_FILTER_SINK = 0x10000 /* pass not-matched unicast frames */\n-} Eth_RxMode;\n-\n-/* filter flags printf helpers */\n-#define ETH_FILTER_FLAG_FMT_STR \"%s%s%s%s%s%s%s\"\n-#define ETH_FILTER_FLAG_FMT_ARGS(f) (f) & ETH_FILTER_UNICAST ? \" UNICAST\" : \"\", \\\n- (f) & ETH_FILTER_MULTICAST ? \" MULTICAST\" : \"\", \\\n- (f) & ETH_FILTER_ALLMULTI ? \" ALLMULTI\" : \"\", \\\n- (f) & ETH_FILTER_BROADCAST ? \" BROADCAST\" : \"\", \\\n- (f) & ETH_FILTER_PROMISC ? \" PROMISC\" : \"\", \\\n- (f) & ETH_FILTER_USE_LADRF ? \" USE_LADRF\" : \"\", \\\n- (f) & ETH_FILTER_SINK ? \" SINK\" : \"\"\n-\n-/* Ethernet header type */\n-typedef enum {\n- ETH_HEADER_TYPE_DIX,\n- ETH_HEADER_TYPE_802_1PQ,\n- ETH_HEADER_TYPE_802_3,\n- ETH_HEADER_TYPE_802_1PQ_802_3,\n-} Eth_HdrType;\n-\n-/* DIX type fields we care about */\n-typedef enum {\n- ETH_TYPE_IPV4 = 0x0800,\n- ETH_TYPE_IPV6 = 0x86DD,\n- ETH_TYPE_ARP = 0x0806,\n- ETH_TYPE_RARP = 0x8035,\n- ETH_TYPE_LLDP = 0x88CC,\n- ETH_TYPE_CDP = 0x2000,\n- ETH_TYPE_802_1PQ = 0x8100, // not really a DIX type, but used as such\n- ETH_TYPE_LLC = 0xFFFF, // 0xFFFF is IANA reserved, used to mark LLC\n- ETH_TYPE_MPLS = 0x8847,\n- ETH_TYPE_MPLS_MCAST = 0x8848,\n-} Eth_DixType;\n-\n-typedef enum {\n- ETH_TYPE_IPV4_NBO = 0x0008,\n- ETH_TYPE_IPV6_NBO = 0xDD86,\n- ETH_TYPE_ARP_NBO = 0x0608,\n- ETH_TYPE_RARP_NBO = 0x3580,\n- ETH_TYPE_LLDP_NBO = 0xCC88,\n- ETH_TYPE_CDP_NBO = 0x0020,\n- ETH_TYPE_AKIMBI_NBO = 0xDE88,\n- ETH_TYPE_802_1PQ_NBO = 0x0081, // not really a DIX type, but used as such\n-} Eth_DixTypeNBO;\n-\n-/* low two bits of the LLC control byte */\n-typedef enum {\n- ETH_LLC_CONTROL_IFRAME = 0x0, // both 0x0 and 0x2, only low bit of 0 needed\n- ETH_LLC_CONTROL_SFRAME = 0x1,\n- ETH_LLC_CONTROL_UFRAME = 0x3,\n-} Eth_LLCControlBits;\n-\n-#define ETH_LLC_CONTROL_UFRAME_MASK (0x3)\n-\n-typedef struct Eth_DIX {\n- UINT16 typeNBO; // indicates the higher level protocol\n-} Eth_DIX;\n-\n-/*\n- * LLC header come in two varieties: 8 bit control and 16 bit control.\n- * when the lower two bits of the first byte's control are '11', this\n- * indicated the 8 bit control field.\n- */\n-typedef struct Eth_LLC8 {\n- UINT8 dsap;\n- UINT8 ssap;\n- UINT8 control;\n-} Eth_LLC8;\n-\n-typedef struct Eth_LLC16 {\n- UINT8 dsap;\n- UINT8 ssap;\n- UINT16 control;\n-} Eth_LLC16;\n-\n-typedef struct Eth_SNAP {\n- UINT8 snapOrg[3];\n- Eth_DIX snapType;\n-} Eth_SNAP;\n-\n-typedef struct Eth_802_3 {\n- UINT16 lenNBO; // length of the frame\n- Eth_LLC8 llc; // LLC header\n- Eth_SNAP snap; // SNAP header\n-} Eth_802_3;\n-\n-// 802.1p QOS/priority tags\n-enum {\n- ETH_802_1_P_BEST_EFFORT = 0,\n- ETH_802_1_P_BACKGROUND = 1,\n- ETH_802_1_P_EXCELLENT_EFFORT = 2,\n- ETH_802_1_P_CRITICAL_APPS = 3,\n- ETH_802_1_P_VIDEO = 4,\n- ETH_802_1_P_VOICE = 5,\n- ETH_802_1_P_INTERNETWORK_CONROL = 6,\n- ETH_802_1_P_NETWORK_CONTROL = 7\n-};\n-\n-typedef struct Eth_802_1pq_Tag {\n- UINT16 typeNBO; // always ETH_TYPE_802_1PQ\n- UINT16 vidHi:4, // 802.1q vlan ID high nibble\n- canonical:1, // bit order? (should always be 0)\n- priority:3, // 802.1p priority tag\n- vidLo:8; // 802.1q vlan ID low byte\n-} Eth_802_1pq_Tag;\n-\n-typedef struct Eth_802_1pq {\n- Eth_802_1pq_Tag tag; // VLAN/QOS tag\n- union {\n- Eth_DIX dix; // DIX header follows\n- Eth_802_3 e802_3; // or 802.3 header follows\n- };\n-} Eth_802_1pq;\n-\n-typedef struct Eth_Header {\n- Eth_Address dst; // all types of ethernet frame have dst first\n- Eth_Address src; // and the src next (at least all the ones we'll see)\n- union {\n- Eth_DIX dix; // followed by a DIX header...\n- Eth_802_3 e802_3; // ...or an 802.3 header\n- Eth_802_1pq e802_1pq; // ...or an 802.1[pq] tag and a header\n- };\n-} Eth_Header;\n-\n-#define ETH_BROADCAST_ADDRESS { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }\n-\n-static Eth_Address netEthBroadcastAddr = ETH_BROADCAST_ADDRESS;\n-\n-/*\n- * simple predicate for 1536 boundary.\n- * the parameter is a network ordered UINT16, which is compared to 0x06,\n- * testing for \"length\" values greater than or equal to 0x0600 (1536)\n- */\n-\n-#define ETH_TYPENOT8023(x) (((x) & 0xff) >= 0x06)\n-\n-/*\n- * header length macros\n- *\n- * first two are typical: ETH_HEADER_LEN_DIX, ETH_HEADER_LEN_802_1PQ\n- * last two are suspicious, due to 802.3 incompleteness\n- */\n-\n-#define ETH_HEADER_LEN_DIX (sizeof(Eth_Address) + \\\n- sizeof(Eth_Address) + \\\n- sizeof(Eth_DIX))\n-#define ETH_HEADER_LEN_802_1PQ (sizeof(Eth_Address) + \\\n- sizeof(Eth_Address) + \\\n- sizeof(Eth_802_1pq_Tag) + \\\n- sizeof(Eth_DIX))\n-#define ETH_HEADER_LEN_802_2_LLC (sizeof(Eth_Address) + \\\n- sizeof(Eth_Address) + \\\n- sizeof(UINT16) + \\\n- sizeof(Eth_LLC8))\n-#define ETH_HEADER_LEN_802_2_LLC16 (sizeof(Eth_Address) + \\\n- sizeof(Eth_Address) + \\\n- sizeof(UINT16) + \\\n- sizeof(Eth_LLC16))\n-#define ETH_HEADER_LEN_802_3 (sizeof(Eth_Address) + \\\n- sizeof(Eth_Address) + \\\n- sizeof(Eth_802_3))\n-#define ETH_HEADER_LEN_802_1PQ_LLC (sizeof(Eth_Address) + \\\n- sizeof(Eth_Address) + \\\n- sizeof(Eth_802_1pq_Tag) + \\\n- sizeof(UINT16) + \\\n- sizeof(Eth_LLC8))\n-#define ETH_HEADER_LEN_802_1PQ_LLC16 (sizeof(Eth_Address) + \\\n- sizeof(Eth_Address) + \\\n- sizeof(Eth_802_1pq_Tag) + \\\n- sizeof(UINT16) + \\\n- sizeof(Eth_LLC16))\n-#define ETH_HEADER_LEN_802_1PQ_802_3 (sizeof(Eth_Address) + \\\n- sizeof(Eth_Address) + \\\n- sizeof(Eth_802_1pq_Tag) + \\\n- sizeof(Eth_802_3))\n-\n-#define ETH_MIN_HEADER_LEN (ETH_HEADER_LEN_DIX)\n-#define ETH_MAX_HEADER_LEN (ETH_HEADER_LEN_802_1PQ_802_3)\n-\n-#define ETH_MIN_FRAME_LEN 60\n-#define ETH_MAX_STD_MTU 1500\n-#define ETH_MAX_STD_FRAMELEN (ETH_MAX_STD_MTU + ETH_MAX_HEADER_LEN)\n-#define ETH_MAX_JUMBO_MTU 9000\n-#define ETH_MAX_JUMBO_FRAMELEN (ETH_MAX_JUMBO_MTU + ETH_MAX_HEADER_LEN)\n-\n-#define ETH_DEFAULT_MTU 1500\n-\n-#define ETH_FCS_LEN 4\n-#define ETH_VLAN_LEN sizeof(Eth_802_1pq_Tag)\n-\n-\n-/*\n- *----------------------------------------------------------------------------\n- * Do the two ethernet addresses match?\n- *----------------------------------------------------------------------------\n- */\n-static __inline BOOLEAN\n-Eth_IsAddrMatch(const Eth_Address addr1, const Eth_Address addr2)\n-{\n- return !memcmp(addr1, addr2, ETH_ADDR_LENGTH);\n-}\n-\n-\n-/*\n- *----------------------------------------------------------------------------\n- * Is the address the broadcast address?\n- *----------------------------------------------------------------------------\n- */\n-static __inline BOOLEAN\n-Eth_IsBroadcastAddr(const Eth_Address addr)\n-{\n- return Eth_IsAddrMatch(addr, netEthBroadcastAddr);\n-}\n-\n-\n-/*\n- *----------------------------------------------------------------------------\n- * Is the address a unicast address?\n- *----------------------------------------------------------------------------\n- */\n-static __inline BOOLEAN\n-Eth_IsUnicastAddr(const Eth_Address addr)\n-{\n- // broadcast and multicast frames always have the low bit set in byte 0\n- return !(((CHAR *)addr)[0] & 0x1);\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * Is the address the all-zeros address?\n- *----------------------------------------------------------------------------\n- */\n-static __inline BOOLEAN\n-Eth_IsNullAddr(const Eth_Address addr)\n-{\n- return ((addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]) == 0);\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- *\n- * Eth_HeaderType --\n- * return an Eth_HdrType depending on the eth header\n- * contents. will not work in all cases, especially since it\n- * requres ETH_HEADER_LEN_802_1PQ bytes to determine the type\n- *\n- * HeaderType isn't sufficient to determine the length of\n- * the eth header. for 802.3 header, its not clear without\n- * examination, whether a SNAP is included\n- *\n- * returned type:\n- *\n- * ETH_HEADER_TYPE_DIX: typical 14 byte eth header\n- * ETH_HEADER_TYPE_802_1PQ: DIX+vlan tagging\n- * ETH_HEADER_TYPE_802_3: 802.3 eth header\n- * ETH_HEADER_TYPE_802_1PQ_802_3: 802.3 + vlan tag\n- *\n- * the test for DIX was moved from a 1500 boundary to a 1536\n- * boundary, since the vmxnet2 MTU was updated to 1514. when\n- * W2K8 attempted to send LLC frames, these were interpreted\n- * as DIX frames instead of the correct 802.3 type\n- *\n- * these links may help if they're valid:\n- *\n- * http://standards.ieee.org/regauth/ethertype/type-tut.html\n- * http://standards.ieee.org/regauth/ethertype/type-pub.html\n- *\n- * Results:\n- * Eth_HdrType value\n- *\n- *----------------------------------------------------------------------------\n- */\n-static __inline Eth_HdrType\n-Eth_HeaderType(const Eth_Header *eh)\n-{\n- /*\n- * we use 1536 (IEEE 802.3-std mentions 1536, but iana indicates\n- * type of 0-0x5dc are 802.3) instead of some #def symbol to prevent\n- * inadvertant reuse of the same macro for buffer size decls.\n- */\n- if (ETH_TYPENOT8023(eh->dix.typeNBO)) {\n- if (eh->dix.typeNBO != ETH_TYPE_802_1PQ_NBO) {\n- /* typical case */\n- return ETH_HEADER_TYPE_DIX;\n- }\n-\n- /* some type of 802.1pq tagged frame */\n- if (ETH_TYPENOT8023(eh->e802_1pq.dix.typeNBO)) {\n- /* vlan tagging with dix style type */\n- return ETH_HEADER_TYPE_802_1PQ;\n- }\n-\n- /* vlan tagging with 802.3 header */\n- return ETH_HEADER_TYPE_802_1PQ_802_3;\n- }\n-\n- /* assume 802.3 */\n- return ETH_HEADER_TYPE_802_3;\n-}\n-\n-\n-/*\n- *----------------------------------------------------------------------------\n- *\n- * Eth_EncapsulatedPktType --\n- * Get the encapsulated (layer 3) frame type.\n- * for LLC frames without SNAP, we don't have\n- * an encapsulated type, and return ETH_TYPE_LLC.\n- *\n- * IANA reserves 0xFFFF, which we reuse to indicate\n- * ETH_TYPE_LLC.\n- *\n- * Results:\n- * NBO frame type.\n- *\n- *----------------------------------------------------------------------------\n- */\n-static __inline UINT16\n-Eth_EncapsulatedPktType(const Eth_Header *eh)\n-{\n- Eth_HdrType type = Eth_HeaderType(eh);\n-\n- switch (type) {\n- case ETH_HEADER_TYPE_DIX: return eh->dix.typeNBO;\n- case ETH_HEADER_TYPE_802_1PQ: return eh->e802_1pq.dix.typeNBO;\n- case ETH_HEADER_TYPE_802_3:\n- /*\n- * Documentation describes SNAP headers as having ONLY\n- * 0x03 as the control fields, not just the lower two bits\n- * This prevents the use of Eth_IsLLCControlUFormat.\n- */\n- if ((eh->e802_3.llc.dsap == 0xaa) && (eh->e802_3.llc.ssap == 0xaa) &&\n- (eh->e802_3.llc.control == ETH_LLC_CONTROL_UFRAME)) {\n- return eh->e802_3.snap.snapType.typeNBO;\n- } else {\n- // LLC, no snap header, then no type\n- return ETH_TYPE_LLC;\n- }\n-\n- case ETH_HEADER_TYPE_802_1PQ_802_3:\n- if ((eh->e802_1pq.e802_3.llc.dsap == 0xaa) &&\n- (eh->e802_1pq.e802_3.llc.ssap == 0xaa) &&\n- (eh->e802_1pq.e802_3.llc.control == ETH_LLC_CONTROL_UFRAME)) {\n- return eh->e802_1pq.e802_3.snap.snapType.typeNBO;\n- } else {\n- // tagged LLC, no snap header, then no type\n- return ETH_TYPE_LLC;\n- }\n- }\n-\n- ASSERT(FALSE);\n- return 0;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * Is the frame of the requested protocol type or is it an 802.1[pq]\n- * encapsulation of such a frame?\n- *----------------------------------------------------------------------------\n- */\n-static __inline BOOLEAN\n-Eth_IsDixType(const Eth_Header *eh, const Eth_DixTypeNBO type)\n-{\n- return Eth_EncapsulatedPktType(eh) == type;\n-}\n-\n-\n-/*\n- *----------------------------------------------------------------------------\n- * Is the frame an IPV4 frame?\n- *----------------------------------------------------------------------------\n- */\n-static __inline BOOLEAN\n-Eth_IsIPV4(const Eth_Header *eh)\n-{\n- return Eth_IsDixType(eh, ETH_TYPE_IPV4_NBO);\n-}\n-\n-\n-/*\n- *----------------------------------------------------------------------------\n- * Is the frame an IPV6 frame?\n- *----------------------------------------------------------------------------\n- */\n-static __inline BOOLEAN\n-Eth_IsIPV6(const Eth_Header *eh)\n-{\n- return Eth_IsDixType(eh, ETH_TYPE_IPV6_NBO);\n-}\n-\n-\n-/*\n- *----------------------------------------------------------------------------\n- * Is the frame an ARP frame?\n- *----------------------------------------------------------------------------\n- */\n-static __inline BOOLEAN\n-Eth_IsARP(const Eth_Header *eh)\n-{\n- return Eth_IsDixType(eh, ETH_TYPE_ARP_NBO);\n-}\n-\n-\n-/*\n- *----------------------------------------------------------------------------\n- * Does the frame contain an 802.1[pq] tag?\n- *----------------------------------------------------------------------------\n- */\n-static __inline BOOLEAN\n-Eth_IsFrameTagged(const Eth_Header *eh)\n-{\n- return (eh->dix.typeNBO == ETH_TYPE_802_1PQ_NBO);\n-}\n-#endif /* __ETHERNET_H_ */\ndiff --git a/datapath-windows/ovsext/Event.c b/datapath-windows/ovsext/Event.c\ndeleted file mode 100644\nindex 69cdb431b..000000000\n--- a/datapath-windows/ovsext/Event.c\n+++ /dev/null\n@@ -1,626 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#include \"precomp.h\"\n-\n-#include \"Datapath.h\"\n-#include \"Vport.h\"\n-#include \"Event.h\"\n-\n-#ifdef OVS_DBG_MOD\n-#undef OVS_DBG_MOD\n-#endif\n-#define OVS_DBG_MOD OVS_DBG_EVENT\n-#include \"Debug.h\"\n-\n-LIST_ENTRY ovsEventQueueArr[OVS_MCAST_EVENT_TYPES_MAX];\n-static NDIS_SPIN_LOCK eventQueueLockArr[OVS_MCAST_EVENT_TYPES_MAX];\n-UINT32 ovsNumEventQueueArr[OVS_MCAST_EVENT_TYPES_MAX];\n-DRIVER_CANCEL OvsCancelIrp;\n-\n-NTSTATUS\n-OvsInitEventQueue()\n-{\n- for (int i = 0; i < OVS_MCAST_EVENT_TYPES_MAX; i++) {\n- InitializeListHead(&ovsEventQueueArr[i]);\n- NdisAllocateSpinLock(&eventQueueLockArr[i]);\n- }\n- return STATUS_SUCCESS;\n-}\n-\n-VOID\n-OvsCleanupEventQueue()\n-{\n- for (int i = 0; i < OVS_MCAST_EVENT_TYPES_MAX; i++) {\n- ASSERT(IsListEmpty(&ovsEventQueueArr[i]));\n- ASSERT(ovsNumEventQueueArr[i] == 0);\n- NdisFreeSpinLock(&eventQueueLockArr[i]);\n- }\n-}\n-\n-_IRQL_raises_(DISPATCH_LEVEL)\n-_IRQL_saves_global_(OldIrql, eventQueueLockArr[eventId])\n-_Acquires_lock_(eventQueueLockArr[eventId])\n-static __inline VOID\n-OvsAcquireEventQueueLock(int eventId)\n-{\n- NdisAcquireSpinLock(&eventQueueLockArr[eventId]);\n-}\n-\n-_IRQL_requires_(DISPATCH_LEVEL)\n-_IRQL_restores_global_(OldIrql, eventQueueLockArr[eventId])\n-_Requires_lock_held_(eventQueueLockArr[eventId])\n-_Releases_lock_(eventQueueLockArr[eventId])\n-static __inline VOID\n-OvsReleaseEventQueueLock(int eventId)\n-{\n- NdisReleaseSpinLock(&eventQueueLockArr[eventId]);\n-}\n-\n-NDIS_STATUS\n-OvsGetMcastEventId(UINT32 protocol, UINT32 mcastMask, UINT32 *eventId)\n-{\n- switch (protocol) {\n- case NETLINK_GENERIC:\n- *eventId = OVS_MCAST_VPORT_EVENT;\n- return NDIS_STATUS_SUCCESS;\n- case NETLINK_NETFILTER:\n- if ((mcastMask & OVS_EVENT_CT_NEW)\n- || (mcastMask & OVS_EVENT_CT_DELETE)\n- || (mcastMask & OVS_EVENT_CT_UPDATE)) {\n- *eventId = OVS_MCAST_CT_EVENT;\n- return NDIS_STATUS_SUCCESS;\n- }\n- break;\n- default:\n- goto error;\n- }\n-\n-error:\n- return NDIS_STATUS_INVALID_PARAMETER;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Cleanup the event queue of the OpenInstance.\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-OvsCleanupEvent(POVS_OPEN_INSTANCE instance)\n-{\n- POVS_EVENT_QUEUE queue;\n- PIRP irp = NULL;\n- UINT32 eventId;\n- queue = (POVS_EVENT_QUEUE)instance->eventQueue;\n- if (queue) {\n- POVS_EVENT_QUEUE_ELEM elem;\n- PLIST_ENTRY link, next;\n-\n- /* Handle the error */\n- OvsGetMcastEventId(instance->protocol, instance->mcastMask, &eventId);\n- OvsAcquireEventQueueLock(eventId);\n- RemoveEntryList(&queue->queueLink);\n- ovsNumEventQueueArr[eventId]--;\n- if (queue->pendingIrp) {\n- PDRIVER_CANCEL cancelRoutine;\n- irp = queue->pendingIrp;\n- cancelRoutine = IoSetCancelRoutine(irp, NULL);\n- queue->pendingIrp = NULL;\n- if (cancelRoutine == NULL) {\n- irp = NULL;\n- }\n- }\n- instance->eventQueue = NULL;\n- OvsReleaseEventQueueLock(eventId);\n- if (irp) {\n- OvsCompleteIrpRequest(irp, 0, STATUS_SUCCESS);\n- }\n-\n- LIST_FORALL_SAFE(&queue->elemList, link, next) {\n- elem = CONTAINING_RECORD(link, OVS_EVENT_QUEUE_ELEM, link);\n- OvsFreeMemoryWithTag(elem, OVS_EVENT_POOL_TAG);\n- }\n- OvsFreeMemoryWithTag(queue, OVS_EVENT_POOL_TAG);\n- }\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * When event is generated, we need to post the event to all\n- * the event queues. If there is pending Irp waiting for event\n- * complete the Irp to wakeup the user thread.\n- *\n- * Side effects: User thread may be woken up.\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-OvsPostVportEvent(POVS_VPORT_EVENT_ENTRY event)\n-{\n- POVS_EVENT_QUEUE_ELEM elem;\n- POVS_EVENT_QUEUE queue;\n- PLIST_ENTRY link;\n- LIST_ENTRY list;\n- PLIST_ENTRY entry;\n- PIRP irp;\n-\n- InitializeListHead(&list);\n-\n- OVS_LOG_TRACE(\"Enter: portNo: %#x, status: %#x\", event->portNo,\n- event->type);\n-\n- OvsAcquireEventQueueLock(OVS_MCAST_VPORT_EVENT);\n-\n- LIST_FORALL(&ovsEventQueueArr[OVS_MCAST_VPORT_EVENT], link) {\n- queue = CONTAINING_RECORD(link, OVS_EVENT_QUEUE, queueLink);\n- if ((event->type & queue->mask) == 0) {\n- continue;\n- }\n- event->type &= queue->mask;\n-\n- elem = (POVS_EVENT_QUEUE_ELEM)OvsAllocateMemoryWithTag(\n- sizeof(*elem), OVS_EVENT_POOL_TAG);\n-\n- if (elem == NULL) {\n- OVS_LOG_WARN(\"Fail to allocate memory for event\");\n- OvsReleaseEventQueueLock(OVS_MCAST_VPORT_EVENT);\n- return;\n- }\n-\n- RtlCopyMemory(&elem->vportEvent, event, sizeof elem->vportEvent);\n- InsertTailList(&queue->elemList, &elem->link);\n- queue->numElems++;\n- OVS_LOG_INFO(\"Queue: %p, numElems: %d\",\n- queue, queue->numElems);\n-\n- if (queue->pendingIrp != NULL) {\n- PDRIVER_CANCEL cancelRoutine;\n- irp = queue->pendingIrp;\n- queue->pendingIrp = NULL;\n- cancelRoutine = IoSetCancelRoutine(irp, NULL);\n- if (cancelRoutine) {\n- InsertTailList(&list, &irp->Tail.Overlay.ListEntry);\n- }\n- }\n- }\n- OvsReleaseEventQueueLock(OVS_MCAST_VPORT_EVENT);\n- while (!IsListEmpty(&list)) {\n- entry = RemoveHeadList(&list);\n- irp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.ListEntry);\n- OVS_LOG_INFO(\"Wakeup thread with IRP: %p\", irp);\n- OvsCompleteIrpRequest(irp, 0, STATUS_SUCCESS);\n- }\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Subscribe for event notification.\n- *\n- * Results:\n- * STATUS_SUCCESS for valid request and enough resource.\n- * STATUS_NO_RESOURCES for queue allocation failure\n- * STATUS_INVALID_PARAMETER for invalid request\n- *\n- * Side effects:\n- * Event queue is created for the current open instance.\n- * --------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsSubscribeEventIoctl(PFILE_OBJECT fileObject,\n- PVOID inputBuffer,\n- UINT32 inputLength)\n-{\n- POVS_EVENT_SUBSCRIBE request = (POVS_EVENT_SUBSCRIBE)inputBuffer;\n- NTSTATUS status = STATUS_SUCCESS;\n- POVS_OPEN_INSTANCE instance;\n- POVS_EVENT_QUEUE queue = NULL;\n- UINT32 eventId;\n-\n- OVS_LOG_TRACE(\"Enter: fileObject: %p, inputLength: %d\", fileObject,\n- inputLength);\n-\n- if (request->protocol == NETLINK_GENERIC) {\n- if (inputLength < sizeof (OVS_EVENT_SUBSCRIBE) ||\n- (request->mask & OVS_EVENT_MASK_ALL) == 0) {\n- OVS_LOG_TRACE(\"Exit: subscribe failed with invalid request.\");\n- return STATUS_INVALID_PARAMETER;\n- }\n- }\n-\n- status = OvsGetMcastEventId(request->protocol, request->mask, &eventId);\n- if (status != NDIS_STATUS_SUCCESS) {\n- return STATUS_INVALID_PARAMETER;\n- }\n-\n- instance = OvsGetOpenInstance(fileObject, request->dpNo);\n- OvsAcquireEventQueueLock(eventId);\n-\n- if (instance == NULL) {\n- status = STATUS_INVALID_PARAMETER;\n- OVS_LOG_WARN(\"can not find open instance\");\n- goto done_event_subscribe;\n- }\n-\n- /*\n- * XXX for now, we don't allow change mask.\n- */\n- queue = (POVS_EVENT_QUEUE)instance->eventQueue;\n- if (request->subscribe && queue) {\n- if (request->protocol == NETLINK_GENERIC\n- && queue->mask != request->mask) {\n- status = STATUS_INVALID_PARAMETER;\n- OVS_LOG_WARN(\"Can not change mask when the queue is subscribed\");\n- goto done_event_subscribe;\n- }\n- if (request->protocol == NETLINK_NETFILTER) {\n- if (queue->mask == request->mask) {\n- /* Resubscribing to subscribed event */\n- status = STATUS_SUCCESS;\n- goto done_event_subscribe;\n- } else {\n- /* Update the instance and queue mask to reflect this */\n- queue->mask |= request->mask;\n- instance->mcastMask |= request->mask;\n- }\n- status = STATUS_SUCCESS;\n- goto done_event_subscribe;\n- }\n- } else if (!request->subscribe && queue == NULL) {\n- status = STATUS_SUCCESS;\n- goto done_event_subscribe;\n- }\n-\n- if (request->subscribe) {\n- queue = (POVS_EVENT_QUEUE)OvsAllocateMemoryWithTag(\n- sizeof(OVS_EVENT_QUEUE), OVS_EVENT_POOL_TAG);\n- if (queue == NULL) {\n- status = STATUS_NO_MEMORY;\n- OVS_LOG_WARN(\"Fail to allocate event queue\");\n- goto done_event_subscribe;\n- }\n- InitializeListHead(&queue->elemList);\n- queue->mask = request->mask;\n- queue->mcastEventId = eventId;\n- queue->pendingIrp = NULL;\n- queue->numElems = 0;\n- InsertHeadList(&ovsEventQueueArr[eventId], &queue->queueLink);\n- ovsNumEventQueueArr[eventId]++;\n- instance->eventQueue = queue;\n- instance->mcastMask = request->mask;\n- queue->instance = instance;\n- } else {\n- queue = (POVS_EVENT_QUEUE)instance->eventQueue;\n- queue->mask &= ~(request->mask);\n- instance->mcastMask &= ~(request->mask);\n- if (!queue->mask) {\n- /* No other mcast group exists */\n- RemoveEntryList(&queue->queueLink);\n- ovsNumEventQueueArr[eventId]--;\n- instance->eventQueue = NULL;\n- instance->mcastMask = 0;\n- }\n- }\n-done_event_subscribe:\n- if (!request->subscribe && queue && !queue->mask) {\n- POVS_EVENT_QUEUE_ELEM elem;\n- PLIST_ENTRY link, next;\n- PIRP irp = NULL;\n- if (queue->pendingIrp) {\n- PDRIVER_CANCEL cancelRoutine;\n- irp = queue->pendingIrp;\n- queue->pendingIrp = NULL;\n- cancelRoutine = IoSetCancelRoutine(irp, NULL);\n- if (cancelRoutine == NULL) {\n- irp = NULL;\n- }\n- }\n- OvsReleaseEventQueueLock(eventId);\n- if (irp) {\n- OvsCompleteIrpRequest(queue->pendingIrp, 0, STATUS_SUCCESS);\n- }\n- LIST_FORALL_SAFE(&queue->elemList, link, next) {\n- elem = CONTAINING_RECORD(link, OVS_EVENT_QUEUE_ELEM, link);\n- OvsFreeMemoryWithTag(elem, OVS_EVENT_POOL_TAG);\n- }\n- OvsFreeMemoryWithTag(queue, OVS_EVENT_POOL_TAG);\n- } else {\n- OvsReleaseEventQueueLock(eventId);\n- }\n- OVS_LOG_TRACE(\"Exit: subscribe event with status: %#x.\", status);\n- return status;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Cancel wait IRP for event\n- *\n- * Please note, when this routine is called, it is always guaranteed that\n- * IRP is valid.\n- *\n- * Side effects: Pending IRP is completed.\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-OvsCancelIrp(PDEVICE_OBJECT deviceObject,\n- PIRP irp)\n-{\n- PIO_STACK_LOCATION irpSp;\n- PFILE_OBJECT fileObject;\n- POVS_EVENT_QUEUE queue;\n- POVS_OPEN_INSTANCE instance;\n- UINT32 eventId;\n- NDIS_STATUS status;\n-\n- UNREFERENCED_PARAMETER(deviceObject);\n-\n- IoReleaseCancelSpinLock(irp->CancelIrql);\n-\n- irpSp = IoGetCurrentIrpStackLocation(irp);\n- fileObject = irpSp->FileObject;\n-\n- if (fileObject == NULL) {\n- goto done;\n- }\n-\n- instance = (POVS_OPEN_INSTANCE)fileObject->FsContext;\n- if (instance == NULL) {\n- goto done;\n- }\n-\n- status = OvsGetMcastEventId(instance->protocol,\n- instance->mcastMask,\n- &eventId);\n- if (status != NDIS_STATUS_SUCCESS) {\n- goto done;\n- }\n-\n- OvsAcquireEventQueueLock(eventId);\n- if (instance->eventQueue == NULL) {\n- OvsReleaseEventQueueLock(eventId);\n- goto done;\n- }\n-\n- queue = instance->eventQueue;\n- if (queue->pendingIrp == irp) {\n- queue->pendingIrp = NULL;\n- }\n- OvsReleaseEventQueueLock(eventId);\n-done:\n- OvsCompleteIrpRequest(irp, 0, STATUS_CANCELLED);\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Wait for event.\n- *\n- * Results:\n- * STATUS_SUCCESS for valid request\n- * STATUS_DEVICE_BUSY if already in waiting state.\n- * STATUS_INVALID_PARAMETER for invalid request\n- * STATUS_PENDING wait for event\n- *\n- * Side effects:\n- * May return pending to IO manager.\n- * --------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsWaitEventIoctl(PIRP irp,\n- PFILE_OBJECT fileObject,\n- PVOID inputBuffer,\n- UINT32 inputLength)\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n- POVS_EVENT_POLL poll;\n- POVS_EVENT_QUEUE queue;\n- POVS_OPEN_INSTANCE instance;\n- BOOLEAN cancelled = FALSE;\n- PDRIVER_CANCEL cancelRoutine;\n- UINT32 eventId;\n-\n- OVS_LOG_TRACE(\"Enter: inputLength: %u\", inputLength);\n-\n- if (inputLength < sizeof (OVS_EVENT_POLL)) {\n- OVS_LOG_TRACE(\"Exit: Invalid input buffer length.\");\n- return STATUS_INVALID_PARAMETER;\n- }\n- poll = (POVS_EVENT_POLL)inputBuffer;\n-\n- instance = OvsGetOpenInstance(fileObject, poll->dpNo);\n- if (instance == NULL) {\n- OVS_LOG_TRACE(\"Exit: Can not find open instance, dpNo: %d\",\n- poll->dpNo);\n- return STATUS_INVALID_PARAMETER;\n- }\n-\n- status = OvsGetMcastEventId(instance->protocol,\n- instance->mcastMask,\n- &eventId);\n- if (status != NDIS_STATUS_SUCCESS) {\n- return STATUS_INVALID_PARAMETER;\n- }\n- OvsAcquireEventQueueLock(eventId);\n-\n- queue = (POVS_EVENT_QUEUE)instance->eventQueue;\n- if (queue == NULL) {\n- OVS_LOG_TRACE(\"Exit: Event queue does not exist\");\n- status = STATUS_INVALID_PARAMETER;\n- goto unlock;\n- }\n- if (queue->pendingIrp) {\n- OVS_LOG_TRACE(\"Exit: Event queue already in pending state\");\n- status = STATUS_DEVICE_BUSY;\n- goto unlock;\n- }\n-\n- IoMarkIrpPending(irp);\n- IoSetCancelRoutine(irp, OvsCancelIrp);\n- if (irp->Cancel) {\n- cancelRoutine = IoSetCancelRoutine(irp, NULL);\n- if (cancelRoutine) {\n- cancelled = TRUE;\n- }\n- } else {\n- queue->pendingIrp = irp;\n- status = STATUS_PENDING;\n- }\n-\n-unlock:\n- OvsReleaseEventQueueLock(eventId);\n- if (cancelled) {\n- OvsCompleteIrpRequest(irp, 0, STATUS_CANCELLED);\n- OVS_LOG_INFO(\"Event IRP cancelled: %p\", irp);\n- }\n- OVS_LOG_TRACE(\"Exit: return status: %#x\", status);\n- return status;\n-}\n-\n-/*\n- *--------------------------------------------------------------------------\n- * Poll event queued in the event queue.always synchronous.\n- *\n- * Results:\n- * STATUS_SUCCESS event was dequeued\n- * STATUS_UNSUCCESSFUL the queue is empty.\n- * --------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsRemoveVportEventEntry(POVS_OPEN_INSTANCE instance,\n- POVS_VPORT_EVENT_ENTRY entry)\n-{\n- NTSTATUS status = STATUS_UNSUCCESSFUL;\n- POVS_EVENT_QUEUE queue;\n- POVS_EVENT_QUEUE_ELEM elem;\n-\n- OvsAcquireEventQueueLock(OVS_MCAST_VPORT_EVENT);\n-\n- queue = (POVS_EVENT_QUEUE)instance->eventQueue;\n-\n- if (queue == NULL) {\n- ASSERT(queue);\n- goto remove_event_done;\n- }\n-\n- if (queue->numElems) {\n- elem = (POVS_EVENT_QUEUE_ELEM)RemoveHeadList(&queue->elemList);\n- *entry = elem->vportEvent;\n- OvsFreeMemoryWithTag(elem, OVS_EVENT_POOL_TAG);\n- queue->numElems--;\n- status = STATUS_SUCCESS;\n- }\n-\n-remove_event_done:\n- OvsReleaseEventQueueLock(OVS_MCAST_VPORT_EVENT);\n- return status;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsPostCtEvent - used to post a Conntrack related event\n- *\n- * Side effects: User thread may be woken up.\n- * XXX - Try to consolidate PostEvent for Vport/Ct events\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-OvsPostCtEvent(POVS_CT_EVENT_ENTRY ctEvent)\n-{\n- POVS_EVENT_QUEUE_ELEM elem;\n- POVS_EVENT_QUEUE queue;\n- PLIST_ENTRY link;\n- LIST_ENTRY list;\n- PLIST_ENTRY entry;\n- PIRP irp;\n-\n- InitializeListHead(&list);\n-\n- OvsAcquireEventQueueLock(OVS_MCAST_CT_EVENT);\n-\n- LIST_FORALL(&ovsEventQueueArr[OVS_MCAST_CT_EVENT], link) {\n- queue = CONTAINING_RECORD(link, OVS_EVENT_QUEUE, queueLink);\n- if ((ctEvent->type & queue->mask) == 0) {\n- continue;\n- }\n- ctEvent->type &= queue->mask;\n-\n- elem = (POVS_EVENT_QUEUE_ELEM)OvsAllocateMemoryWithTag(\n- sizeof(*elem), OVS_EVENT_POOL_TAG);\n-\n- if (elem == NULL) {\n- OvsReleaseEventQueueLock(OVS_MCAST_CT_EVENT);\n- return;\n- }\n-\n- RtlCopyMemory(&elem->ctEvent, ctEvent, sizeof elem->ctEvent);\n- InsertTailList(&queue->elemList, &elem->link);\n- queue->numElems++;\n-\n- if (queue->pendingIrp != NULL) {\n- PDRIVER_CANCEL cancelRoutine;\n- irp = queue->pendingIrp;\n- queue->pendingIrp = NULL;\n- cancelRoutine = IoSetCancelRoutine(irp, NULL);\n- if (cancelRoutine) {\n- InsertTailList(&list, &irp->Tail.Overlay.ListEntry);\n- }\n- }\n- }\n-\n- OvsReleaseEventQueueLock(OVS_MCAST_CT_EVENT);\n- while (!IsListEmpty(&list)) {\n- entry = RemoveHeadList(&list);\n- irp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.ListEntry);\n- OvsCompleteIrpRequest(irp, 0, STATUS_SUCCESS);\n- }\n-}\n-\n-/*\n- *--------------------------------------------------------------------------\n- * Poll event queued in the event queue.always synchronous.\n- *\n- * Results:\n- * STATUS_SUCCESS event was dequeued\n- * STATUS_UNSUCCESSFUL the queue is empty.\n- * --------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsRemoveCtEventEntry(POVS_OPEN_INSTANCE instance,\n- POVS_CT_EVENT_ENTRY entry)\n-{\n- NTSTATUS status = STATUS_UNSUCCESSFUL;\n- POVS_EVENT_QUEUE queue;\n- POVS_EVENT_QUEUE_ELEM elem;\n-\n- OvsAcquireEventQueueLock(OVS_MCAST_CT_EVENT);\n-\n- queue = (POVS_EVENT_QUEUE)instance->eventQueue;\n-\n- if (queue == NULL) {\n- ASSERT(queue);\n- goto remove_event_done;\n- }\n-\n- if (queue->numElems) {\n- elem = (POVS_EVENT_QUEUE_ELEM)RemoveHeadList(&queue->elemList);\n- *entry = elem->ctEvent;\n- OvsFreeMemoryWithTag(elem, OVS_EVENT_POOL_TAG);\n- queue->numElems--;\n- status = STATUS_SUCCESS;\n- }\n-\n-remove_event_done:\n- OvsReleaseEventQueueLock(OVS_MCAST_CT_EVENT);\n- return status;\n-}\ndiff --git a/datapath-windows/ovsext/Event.h b/datapath-windows/ovsext/Event.h\ndeleted file mode 100644\nindex b57946334..000000000\n--- a/datapath-windows/ovsext/Event.h\n+++ /dev/null\n@@ -1,67 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#ifndef __EVENT_H_\n-#define __EVENT_H_ 1\n-#include \"Conntrack.h\"\n-\n-typedef struct _OVS_CT_EVENT_ENTRY {\n- OVS_CT_ENTRY entry;\n- UINT8 type;\n- UINT64 pad[10];\n-} OVS_CT_EVENT_ENTRY, *POVS_CT_EVENT_ENTRY;\n-\n-typedef struct _OVS_EVENT_QUEUE_ELEM {\n- LIST_ENTRY link;\n- union {\n- OVS_VPORT_EVENT_ENTRY vportEvent;\n- OVS_CT_EVENT_ENTRY ctEvent;\n- };\n-} OVS_EVENT_QUEUE_ELEM, *POVS_EVENT_QUEUE_ELEM;\n-\n-typedef struct _OVS_EVENT_QUEUE {\n- LIST_ENTRY queueLink;\n- LIST_ENTRY elemList;\n- UINT32 mask;\n- UINT32 mcastEventId;\n- UINT32 protocol;\n- UINT16 numElems;\n- BOOLEAN pollAll;\n- PIRP pendingIrp;\n- PVOID instance;\n-} OVS_EVENT_QUEUE, *POVS_EVENT_QUEUE;\n-\n-NTSTATUS OvsInitEventQueue(VOID);\n-VOID OvsCleanupEventQueue(VOID);\n-\n-struct _OVS_OPEN_INSTANCE;\n-\n-VOID OvsCleanupEvent(struct _OVS_OPEN_INSTANCE *instance);\n-VOID OvsPostVportEvent(POVS_VPORT_EVENT_ENTRY event);\n-VOID OvsPostCtEvent(POVS_CT_EVENT_ENTRY ctEvent);\n-NTSTATUS OvsSubscribeEventIoctl(PFILE_OBJECT fileObject, PVOID inputBuffer,\n- UINT32 inputLength);\n-NTSTATUS OvsPollEventIoctl(PFILE_OBJECT fileObject, PVOID inputBuffer,\n- UINT32 inputLength, PVOID outputBuffer,\n- UINT32 outputLength, UINT32 *replyLen);\n-NTSTATUS OvsWaitEventIoctl(PIRP irp, PFILE_OBJECT fileObject,\n- PVOID inputBuffer, UINT32 inputLength);\n-NTSTATUS OvsRemoveVportEventEntry(POVS_OPEN_INSTANCE instance,\n- POVS_VPORT_EVENT_ENTRY entry);\n-NTSTATUS OvsRemoveCtEventEntry(POVS_OPEN_INSTANCE instance,\n- POVS_CT_EVENT_ENTRY entry);\n-\n-#endif /* __EVENT_H_ */\ndiff --git a/datapath-windows/ovsext/Flow.c b/datapath-windows/ovsext/Flow.c\ndeleted file mode 100644\nindex 86e809fc1..000000000\n--- a/datapath-windows/ovsext/Flow.c\n+++ /dev/null\n@@ -1,3388 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#include \"precomp.h\"\n-#include \"NetProto.h\"\n-#include \"Util.h\"\n-#include \"Jhash.h\"\n-#include \"Flow.h\"\n-#include \"PacketParser.h\"\n-#include \"Datapath.h\"\n-#include \"Geneve.h\"\n-#include \"IpHelper.h\"\n-#include <ip2string.h>\n-\n-#ifdef OVS_DBG_MOD\n-#undef OVS_DBG_MOD\n-#endif\n-#define OVS_DBG_MOD OVS_DBG_FLOW\n-#include \"Debug.h\"\n-\n-#pragma warning( push )\n-#pragma warning( disable:4127 )\n-\n-extern POVS_SWITCH_CONTEXT gOvsSwitchContext;\n-extern UINT64 ovsTimeIncrementPerTick;\n-\n-static NTSTATUS ReportFlowInfo(OvsFlow *flow, UINT32 getFlags,\n- OvsFlowInfo *info);\n-static NTSTATUS HandleFlowPut(OvsFlowPut *put,\n- OVS_DATAPATH *datapath,\n- struct OvsFlowStats *stats);\n-static NTSTATUS OvsPrepareFlow(OvsFlow **flow, const OvsFlowPut *put,\n- UINT64 hash);\n-static VOID RemoveFlow(OVS_DATAPATH *datapath, OvsFlow **flow);\n-static VOID DeleteAllFlows(OVS_DATAPATH *datapath);\n-static NTSTATUS AddFlow(OVS_DATAPATH *datapath, OvsFlow *flow);\n-static VOID FreeFlow(OvsFlow *flow);\n-static VOID __inline *GetStartAddrNBL(const NET_BUFFER_LIST *_pNB);\n-static NTSTATUS _MapNlToFlowPut(POVS_MESSAGE msgIn, PNL_ATTR keyAttr,\n- PNL_ATTR actionAttr,\n- PNL_ATTR flowAttrClear,\n- OvsFlowPut *mappedFlow);\n-static VOID _MapKeyAttrToFlowPut(PNL_ATTR *keyAttrs,\n- PNL_ATTR *tunnelAttrs,\n- OvsFlowKey *destKey);\n-\n-static VOID _MapNlToFlowPutFlags(PGENL_MSG_HDR genlMsgHdr,\n- PNL_ATTR flowAttrClear,\n- OvsFlowPut *mappedFlow);\n-\n-static NTSTATUS _FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen);\n-static NTSTATUS _FlowNlDumpCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen);\n-static NTSTATUS _MapFlowInfoToNl(PNL_BUFFER nlBuf,\n- OvsFlowInfo *flowInfo);\n-static NTSTATUS _MapFlowStatsToNlStats(PNL_BUFFER nlBuf,\n- OvsFlowStats *flowStats);\n-static NTSTATUS _MapFlowActionToNlAction(PNL_BUFFER nlBuf,\n- uint32_t actionsLen,\n- PNL_ATTR actions);\n-\n-static NTSTATUS _MapFlowIpv4KeyToNlKey(PNL_BUFFER nlBuf,\n- IpKey *ipv4FlowPutKey);\n-static NTSTATUS _MapFlowIpv6KeyToNlKey(PNL_BUFFER nlBuf,\n- Ipv6Key *ipv6FlowPutKey,\n- Icmp6Key *ipv6FlowPutIcmpKey);\n-static NTSTATUS _MapFlowArpKeyToNlKey(PNL_BUFFER nlBuf,\n- ArpKey *arpFlowPutKey);\n-static NTSTATUS _MapFlowMplsKeyToNlKey(PNL_BUFFER nlBuf,\n- MplsKey *mplsFlowPutKey);\n-\n-static NTSTATUS OvsDoDumpFlows(OvsFlowDumpInput *dumpInput,\n- OvsFlowDumpOutput *dumpOutput,\n- UINT32 *replyLen);\n-static NTSTATUS OvsProbeSupportedFeature(POVS_MESSAGE msgIn,\n- PNL_ATTR keyAttr);\n-UINT16 OvsGetFlowIPL2Offset(const OvsIPTunnelKey *tunKey);\n-\n-#define OVS_FLOW_TABLE_SIZE 2048\n-#define OVS_FLOW_TABLE_MASK (OVS_FLOW_TABLE_SIZE -1)\n-#define HASH_BUCKET(hash) ((hash) & OVS_FLOW_TABLE_MASK)\n-\n-/* Flow family related netlink policies */\n-\n-/* For Parsing attributes in FLOW_* commands */\n-const NL_POLICY nlFlowPolicy[] = {\n- [OVS_FLOW_ATTR_KEY] = {.type = NL_A_NESTED, .optional = FALSE},\n- [OVS_FLOW_ATTR_MASK] = {.type = NL_A_NESTED, .optional = TRUE},\n- [OVS_FLOW_ATTR_ACTIONS] = {.type = NL_A_NESTED, .optional = TRUE},\n- [OVS_FLOW_ATTR_STATS] = {.type = NL_A_UNSPEC,\n- .minLen = sizeof(struct ovs_flow_stats),\n- .maxLen = sizeof(struct ovs_flow_stats),\n- .optional = TRUE},\n- [OVS_FLOW_ATTR_TCP_FLAGS] = {NL_A_U8, .optional = TRUE},\n- [OVS_FLOW_ATTR_USED] = {NL_A_U64, .optional = TRUE},\n- [OVS_FLOW_ATTR_PROBE] = {.type = NL_A_FLAG, .optional = TRUE}\n-};\n-\n-/* For Parsing nested OVS_FLOW_ATTR_KEY attributes. */\n-\n-const NL_POLICY nlFlowKeyPolicy[] = {\n- [OVS_KEY_ATTR_ENCAP] = {.type = NL_A_VAR_LEN, .optional = TRUE},\n- [OVS_KEY_ATTR_PRIORITY] = {.type = NL_A_UNSPEC, .minLen = 4,\n- .maxLen = 4, .optional = TRUE},\n- [OVS_KEY_ATTR_IN_PORT] = {.type = NL_A_UNSPEC, .minLen = 4,\n- .maxLen = 4, .optional = TRUE},\n- [OVS_KEY_ATTR_ETHERNET] = {.type = NL_A_UNSPEC,\n- .minLen = sizeof(struct ovs_key_ethernet),\n- .maxLen = sizeof(struct ovs_key_ethernet),\n- .optional = TRUE},\n- [OVS_KEY_ATTR_VLAN] = {.type = NL_A_UNSPEC, .minLen = 2,\n- .maxLen = 2, .optional = TRUE},\n- [OVS_KEY_ATTR_ETHERTYPE] = {.type = NL_A_UNSPEC, .minLen = 2,\n- .maxLen = 2, .optional = TRUE},\n- [OVS_KEY_ATTR_IPV4] = {.type = NL_A_UNSPEC,\n- .minLen = sizeof(struct ovs_key_ipv4),\n- .maxLen = sizeof(struct ovs_key_ipv4),\n- .optional = TRUE},\n- [OVS_KEY_ATTR_IPV6] = {.type = NL_A_UNSPEC,\n- .minLen = sizeof(struct ovs_key_ipv6),\n- .maxLen = sizeof(struct ovs_key_ipv6),\n- .optional = TRUE},\n- [OVS_KEY_ATTR_TCP] = {.type = NL_A_UNSPEC,\n- .minLen = sizeof(struct ovs_key_tcp),\n- .maxLen = sizeof(struct ovs_key_tcp),\n- .optional = TRUE},\n- [OVS_KEY_ATTR_UDP] = {.type = NL_A_UNSPEC,\n- .minLen = sizeof(struct ovs_key_udp),\n- .maxLen = sizeof(struct ovs_key_udp),\n- .optional = TRUE},\n- [OVS_KEY_ATTR_ICMP] = {.type = NL_A_UNSPEC,\n- .minLen = sizeof(struct ovs_key_icmp),\n- .maxLen = sizeof(struct ovs_key_icmp),\n- .optional = TRUE},\n- [OVS_KEY_ATTR_ICMPV6] = {.type = NL_A_UNSPEC,\n- .minLen = sizeof(struct ovs_key_icmpv6),\n- .maxLen = sizeof(struct ovs_key_icmpv6),\n- .optional = TRUE},\n- [OVS_KEY_ATTR_ARP] = {.type = NL_A_UNSPEC,\n- .minLen = sizeof(struct ovs_key_arp),\n- .maxLen = sizeof(struct ovs_key_arp),\n- .optional = TRUE},\n- [OVS_KEY_ATTR_ND] = {.type = NL_A_UNSPEC,\n- .minLen = sizeof(struct ovs_key_nd),\n- .maxLen = sizeof(struct ovs_key_nd),\n- .optional = TRUE},\n- [OVS_KEY_ATTR_SKB_MARK] = {.type = NL_A_UNSPEC, .minLen = 4,\n- .maxLen = 4, .optional = TRUE},\n- [OVS_KEY_ATTR_TUNNEL] = {.type = NL_A_VAR_LEN, .optional = TRUE},\n- [OVS_KEY_ATTR_SCTP] = {.type = NL_A_UNSPEC,\n- .minLen = sizeof(struct ovs_key_sctp),\n- .maxLen = sizeof(struct ovs_key_sctp),\n- .optional = TRUE},\n- [OVS_KEY_ATTR_TCP_FLAGS] = {.type = NL_A_UNSPEC,\n- .minLen = 2, .maxLen = 2,\n- .optional = TRUE},\n- [OVS_KEY_ATTR_DP_HASH] = {.type = NL_A_UNSPEC, .minLen = 4,\n- .maxLen = 4, .optional = TRUE},\n- [OVS_KEY_ATTR_RECIRC_ID] = {.type = NL_A_UNSPEC, .minLen = 4,\n- .maxLen = 4, .optional = TRUE},\n- [OVS_KEY_ATTR_MPLS] = {.type = NL_A_VAR_LEN, .optional = TRUE},\n- [OVS_KEY_ATTR_CT_STATE] = {.type = NL_A_UNSPEC, .minLen = 4,\n- .maxLen = 4, .optional = TRUE},\n- [OVS_KEY_ATTR_CT_ZONE] = {.type = NL_A_UNSPEC, .minLen = 2,\n- .maxLen = 2, .optional = TRUE},\n- [OVS_KEY_ATTR_CT_MARK] = {.type = NL_A_UNSPEC, .minLen = 4,\n- .maxLen = 4, .optional = TRUE},\n- [OVS_KEY_ATTR_CT_LABELS] = {.type = NL_A_UNSPEC,\n- .minLen = sizeof(struct ovs_key_ct_labels),\n- .maxLen = sizeof(struct ovs_key_ct_labels),\n- .optional = TRUE},\n- [OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4] = {.type = NL_A_UNSPEC,\n- .minLen = sizeof(struct ovs_key_ct_tuple_ipv4),\n- .maxLen = sizeof(struct ovs_key_ct_tuple_ipv4),\n- .optional = TRUE},\n- [OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6] = {.type = NL_A_UNSPEC,\n- .minLen = OVS_TUPLE_IPV6,\n- .maxLen = OVS_TUPLE_IPV6,\n- .optional = TRUE}\n-};\n-const UINT32 nlFlowKeyPolicyLen = ARRAY_SIZE(nlFlowKeyPolicy);\n-\n-/* For Parsing nested OVS_KEY_ATTR_TUNNEL attributes */\n-const NL_POLICY nlFlowTunnelKeyPolicy[] = {\n- [OVS_TUNNEL_KEY_ATTR_ID] = {.type = NL_A_UNSPEC, .minLen = 8,\n- .maxLen = 8, .optional = TRUE},\n- [OVS_TUNNEL_KEY_ATTR_IPV4_SRC] = {.type = NL_A_UNSPEC, .minLen = 4,\n- .maxLen = 4, .optional = TRUE},\n- [OVS_TUNNEL_KEY_ATTR_IPV4_DST] = {.type = NL_A_UNSPEC, .minLen = 4 ,\n- .maxLen = 4, .optional = TRUE},\n- [OVS_TUNNEL_KEY_ATTR_IPV6_DST] = {.type = NL_A_UNSPEC, .minLen = 16,\n- .maxLen = 16, .optional = TRUE},\n- [OVS_TUNNEL_KEY_ATTR_IPV6_SRC] = {.type = NL_A_UNSPEC, .minLen = 16,\n- .maxLen = 16, .optional = TRUE},\n- [OVS_TUNNEL_KEY_ATTR_TOS] = {.type = NL_A_UNSPEC, .minLen = 1,\n- .maxLen = 1, .optional = TRUE},\n- [OVS_TUNNEL_KEY_ATTR_TTL] = {.type = NL_A_UNSPEC, .minLen = 1,\n- .maxLen = 1, .optional = TRUE},\n- [OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT] = {.type = NL_A_UNSPEC, .minLen = 0,\n- .maxLen = 0, .optional = TRUE},\n- [OVS_TUNNEL_KEY_ATTR_CSUM] = {.type = NL_A_UNSPEC, .minLen = 0,\n- .maxLen = 0, .optional = TRUE},\n- [OVS_TUNNEL_KEY_ATTR_OAM] = {.type = NL_A_UNSPEC, .minLen = 0,\n- .maxLen = 0, .optional = TRUE},\n- [OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS] = {.type = NL_A_VAR_LEN,\n- .optional = TRUE}\n-};\n-const UINT32 nlFlowTunnelKeyPolicyLen = ARRAY_SIZE(nlFlowTunnelKeyPolicy);\n-\n-/* For Parsing nested OVS_FLOW_ATTR_ACTIONS attributes */\n-const NL_POLICY nlFlowActionPolicy[] = {\n- [OVS_ACTION_ATTR_OUTPUT] = {.type = NL_A_UNSPEC, .minLen = sizeof(UINT32),\n- .maxLen = sizeof(UINT32), .optional = TRUE},\n- [OVS_ACTION_ATTR_USERSPACE] = {.type = NL_A_VAR_LEN, .optional = TRUE},\n- [OVS_ACTION_ATTR_PUSH_VLAN] = {.type = NL_A_UNSPEC,\n- .minLen =\n- sizeof(struct ovs_action_push_vlan),\n- .maxLen =\n- sizeof(struct ovs_action_push_vlan),\n- .optional = TRUE},\n- [OVS_ACTION_ATTR_POP_VLAN] = {.type = NL_A_UNSPEC, .optional = TRUE},\n- [OVS_ACTION_ATTR_PUSH_MPLS] = {.type = NL_A_UNSPEC,\n- .minLen =\n- sizeof(struct ovs_action_push_mpls),\n- .maxLen =\n- sizeof(struct ovs_action_push_mpls),\n- .optional = TRUE},\n- [OVS_ACTION_ATTR_POP_MPLS] = {.type = NL_A_UNSPEC,\n- .minLen = sizeof(UINT16),\n- .maxLen = sizeof(UINT16),\n- .optional = TRUE},\n- [OVS_ACTION_ATTR_RECIRC] = {.type = NL_A_UNSPEC,\n- .minLen = sizeof(UINT32),\n- .maxLen = sizeof(UINT32),\n- .optional = TRUE},\n- [OVS_ACTION_ATTR_HASH] = {.type = NL_A_UNSPEC,\n- .minLen = sizeof(struct ovs_action_hash),\n- .maxLen = sizeof(struct ovs_action_hash),\n- .optional = TRUE},\n- [OVS_ACTION_ATTR_SET] = {.type = NL_A_VAR_LEN, .optional = TRUE},\n- [OVS_ACTION_ATTR_SAMPLE] = {.type = NL_A_VAR_LEN, .optional = TRUE},\n- [OVS_ACTION_ATTR_CT] = {.type = NL_A_VAR_LEN, .optional = TRUE}\n-};\n-\n-/*\n- *----------------------------------------------------------------------------\n- * Netlink interface for flow commands.\n- *----------------------------------------------------------------------------\n- */\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsFlowNewCmdHandler --\n- * Handler for OVS_FLOW_CMD_NEW/SET/DEL command.\n- * It also handles FLUSH case (DEL w/o any key in input)\n- *----------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsFlowNlCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen)\n-{\n- NTSTATUS rc = STATUS_SUCCESS;\n- BOOLEAN ok = FALSE;\n- POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;\n- POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer;\n- PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);\n- PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);\n- POVS_HDR ovsHdr = &(msgIn->ovsHdr);\n- PNL_ATTR flowAttrs[__OVS_FLOW_ATTR_MAX];\n- UINT32 attrOffset = NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN;\n- OvsFlowPut mappedFlow;\n- OvsFlowStats stats;\n- struct ovs_flow_stats replyStats;\n- NL_ERROR nlError = NL_ERROR_SUCCESS;\n- NL_BUFFER nlBuf;\n-\n- RtlZeroMemory(&mappedFlow, sizeof(OvsFlowPut));\n- RtlZeroMemory(&stats, sizeof(stats));\n- RtlZeroMemory(&replyStats, sizeof(replyStats));\n-\n- if (!(usrParamsCtx->outputBuffer)) {\n- /* No output buffer */\n- rc = STATUS_INVALID_BUFFER_SIZE;\n- goto done;\n- }\n-\n- /* FLOW_DEL command w/o any key input is a flush case.\n- If we don't have any attr, we treat this as a flush command*/\n- if ((genlMsgHdr->cmd == OVS_FLOW_CMD_DEL) &&\n- (!NlMsgAttrsLen(nlMsgHdr))) {\n-\n- rc = OvsFlushFlowIoctl(ovsHdr->dp_ifindex);\n-\n- if (rc == STATUS_SUCCESS) {\n- /* XXX: refactor this code. */\n- /* So far so good. Prepare the reply for userspace */\n- NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,\n- usrParamsCtx->outputLength);\n-\n- /* Prepare nl Msg headers */\n- ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,\n- nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,\n- genlMsgHdr->cmd, OVS_FLOW_VERSION,\n- ovsHdr->dp_ifindex);\n- if (ok) {\n- *replyLen = msgOut->nlMsg.nlmsgLen;\n- } else {\n- rc = STATUS_INVALID_BUFFER_SIZE;\n- }\n- }\n-\n- goto done;\n- }\n-\n- /* Get all the top level Flow attributes */\n- if ((NlAttrParse(nlMsgHdr, attrOffset, NlMsgAttrsLen(nlMsgHdr),\n- nlFlowPolicy, ARRAY_SIZE(nlFlowPolicy),\n- flowAttrs, ARRAY_SIZE(flowAttrs)))\n- != TRUE) {\n- OVS_LOG_ERROR(\"Attr Parsing failed for msg: %p\",\n- nlMsgHdr);\n- rc = STATUS_INVALID_PARAMETER;\n- goto done;\n- }\n-\n- if (flowAttrs[OVS_FLOW_ATTR_PROBE]) {\n- rc = OvsProbeSupportedFeature(msgIn, flowAttrs[OVS_FLOW_ATTR_KEY]);\n- if (rc != STATUS_SUCCESS) {\n- nlError = NlMapStatusToNlErr(rc);\n- goto done;\n- }\n- }\n-\n- if ((rc = _MapNlToFlowPut(msgIn, flowAttrs[OVS_FLOW_ATTR_KEY],\n- flowAttrs[OVS_FLOW_ATTR_ACTIONS],\n- flowAttrs[OVS_FLOW_ATTR_CLEAR],\n- &mappedFlow))\n- != STATUS_SUCCESS) {\n- OVS_LOG_ERROR(\"Conversion to OvsFlowPut failed\");\n- goto done;\n- }\n-\n- rc = OvsPutFlowIoctl(&mappedFlow, sizeof (struct OvsFlowPut),\n- &stats);\n- if (rc != STATUS_SUCCESS) {\n- OVS_LOG_ERROR(\"OvsPutFlowIoctl failed.\");\n- /*\n- * Report back to the userspace the flow could not be modified,\n- * created or deleted\n- */\n- nlError = NL_ERROR_NOENT;\n- if (rc == STATUS_DUPLICATE_NAME) {\n- nlError = NL_ERROR_EXIST;\n- }\n- goto done;\n- }\n-\n- replyStats.n_packets = stats.packetCount;\n- replyStats.n_bytes = stats.byteCount;\n-\n- /* So far so good. Prepare the reply for userspace */\n- NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,\n- usrParamsCtx->outputLength);\n-\n- /* Prepare nl Msg headers */\n- ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,\n- nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,\n- genlMsgHdr->cmd, OVS_FLOW_VERSION,\n- ovsHdr->dp_ifindex);\n- if (!ok) {\n- rc = STATUS_INVALID_BUFFER_SIZE;\n- goto done;\n- } else {\n- rc = STATUS_SUCCESS;\n- }\n-\n- /* Append OVS_FLOW_ATTR_KEY attribute. This is need i.e. for flow delete*/\n- if (!NlMsgPutNested(&nlBuf, OVS_FLOW_ATTR_KEY,\n- NlAttrData(flowAttrs[OVS_FLOW_ATTR_KEY]),\n- NlAttrGetSize(flowAttrs[OVS_FLOW_ATTR_KEY]))) {\n- OVS_LOG_ERROR(\"Adding OVS_FLOW_ATTR_KEY attribute failed.\");\n- rc = STATUS_INVALID_BUFFER_SIZE;\n- goto done;\n- }\n-\n- /* Append OVS_FLOW_ATTR_STATS attribute */\n- if (!NlMsgPutTailUnspec(&nlBuf, OVS_FLOW_ATTR_STATS,\n- (PCHAR)(&replyStats), sizeof(replyStats))) {\n- OVS_LOG_ERROR(\"Adding OVS_FLOW_ATTR_STATS attribute failed.\");\n- rc = STATUS_INVALID_BUFFER_SIZE;\n- goto done;\n- }\n-\n- msgOut->nlMsg.nlmsgLen = NLMSG_ALIGN(NlBufSize(&nlBuf));\n- *replyLen = msgOut->nlMsg.nlmsgLen;\n-\n-done:\n-\n- if (nlError != NL_ERROR_SUCCESS) {\n- POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)\n- usrParamsCtx->outputBuffer;\n-\n- ASSERT(msgError);\n- NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);\n- ASSERT(*replyLen != 0);\n- rc = STATUS_SUCCESS;\n- }\n-\n- return rc;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsFlowNlGetCmdHandler --\n- * Handler for OVS_FLOW_CMD_GET/DUMP commands.\n- *----------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsFlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen)\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n-\n- if (usrParamsCtx->devOp == OVS_TRANSACTION_DEV_OP) {\n- status = _FlowNlGetCmdHandler(usrParamsCtx, replyLen);\n- } else {\n- status = _FlowNlDumpCmdHandler(usrParamsCtx, replyLen);\n- }\n-\n- return status;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * _FlowNlGetCmdHandler --\n- * Handler for OVS_FLOW_CMD_GET command.\n- *----------------------------------------------------------------------------\n- */\n-NTSTATUS\n-_FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen)\n-{\n- NTSTATUS rc = STATUS_SUCCESS;\n- POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;\n- PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);\n- POVS_HDR ovsHdr = &(msgIn->ovsHdr);\n- PNL_MSG_HDR nlMsgOutHdr = NULL;\n- UINT32 attrOffset = NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN;\n- PNL_ATTR nlAttrs[__OVS_FLOW_ATTR_MAX];\n-\n- OvsFlowGetInput getInput;\n- OvsFlowGetOutput getOutput;\n- NL_BUFFER nlBuf;\n- PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX];\n- PNL_ATTR tunnelAttrs[__OVS_TUNNEL_KEY_ATTR_MAX];\n- PNL_ATTR encapAttrs[__OVS_KEY_ATTR_MAX];\n-\n- NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,\n- usrParamsCtx->outputLength);\n- RtlZeroMemory(&getInput, sizeof(OvsFlowGetInput));\n- RtlZeroMemory(&getOutput, sizeof(OvsFlowGetOutput));\n- UINT32 keyAttrOffset = 0;\n- UINT32 tunnelKeyAttrOffset = 0;\n- UINT32 encapOffset = 0;\n- BOOLEAN ok;\n- NL_ERROR nlError = NL_ERROR_SUCCESS;\n-\n- if (usrParamsCtx->inputLength > usrParamsCtx->outputLength) {\n- /* Should not be the case.\n- * We'll be copying the flow keys back from\n- * input buffer to output buffer. */\n- rc = STATUS_INVALID_PARAMETER;\n- OVS_LOG_ERROR(\"inputLength: %d GREATER THEN outputLength: %d\",\n- usrParamsCtx->inputLength, usrParamsCtx->outputLength);\n- goto done;\n- }\n-\n- /* Get all the top level Flow attributes */\n- if ((NlAttrParse(nlMsgHdr, attrOffset, NlMsgAttrsLen(nlMsgHdr),\n- nlFlowPolicy, ARRAY_SIZE(nlFlowPolicy),\n- nlAttrs, ARRAY_SIZE(nlAttrs)))\n- != TRUE) {\n- OVS_LOG_ERROR(\"Attr Parsing failed for msg: %p\",\n- nlMsgHdr);\n- rc = STATUS_INVALID_PARAMETER;\n- goto done;\n- }\n-\n- keyAttrOffset = (UINT32)((PCHAR) nlAttrs[OVS_FLOW_ATTR_KEY] -\n- (PCHAR)nlMsgHdr);\n-\n- /* Get flow keys attributes */\n- if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset,\n- NlAttrLen(nlAttrs[OVS_FLOW_ATTR_KEY]),\n- nlFlowKeyPolicy, ARRAY_SIZE(nlFlowKeyPolicy),\n- keyAttrs, ARRAY_SIZE(keyAttrs)))\n- != TRUE) {\n- OVS_LOG_ERROR(\"Key Attr Parsing failed for msg: %p\",\n- nlMsgHdr);\n- rc = STATUS_INVALID_PARAMETER;\n- goto done;\n- }\n-\n- if (keyAttrs[OVS_KEY_ATTR_ENCAP]) {\n- encapOffset = (UINT32)((PCHAR) (keyAttrs[OVS_KEY_ATTR_ENCAP])\n- - (PCHAR)nlMsgHdr);\n-\n- if ((NlAttrParseNested(nlMsgHdr, encapOffset,\n- NlAttrLen(keyAttrs[OVS_KEY_ATTR_ENCAP]),\n- nlFlowKeyPolicy,\n- ARRAY_SIZE(nlFlowKeyPolicy),\n- encapAttrs, ARRAY_SIZE(encapAttrs)))\n- != TRUE) {\n- OVS_LOG_ERROR(\"Encap Key Attr Parsing failed for msg: %p\",\n- nlMsgHdr);\n- rc = STATUS_INVALID_PARAMETER;\n- goto done;\n- }\n- }\n-\n- if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {\n- tunnelKeyAttrOffset = (UINT32)((PCHAR)\n- (keyAttrs[OVS_KEY_ATTR_TUNNEL])\n- - (PCHAR)nlMsgHdr);\n-\n- /* Get tunnel keys attributes */\n- if ((NlAttrParseNested(nlMsgHdr, tunnelKeyAttrOffset,\n- NlAttrLen(keyAttrs[OVS_KEY_ATTR_TUNNEL]),\n- nlFlowTunnelKeyPolicy,\n- ARRAY_SIZE(nlFlowTunnelKeyPolicy),\n- tunnelAttrs, ARRAY_SIZE(tunnelAttrs)))\n- != TRUE) {\n- OVS_LOG_ERROR(\"Tunnel key Attr Parsing failed for msg: %p\",\n- nlMsgHdr);\n- rc = STATUS_INVALID_PARAMETER;\n- goto done;\n- }\n- }\n-\n- _MapKeyAttrToFlowPut(keyAttrs, tunnelAttrs,\n- &(getInput.key));\n- ASSERT(keyAttrs[OVS_KEY_ATTR_IN_PORT]);\n-\n- if (encapOffset) {\n- _MapKeyAttrToFlowPut(encapAttrs, tunnelAttrs,\n- &(getInput.key));\n- }\n-\n- getInput.dpNo = ovsHdr->dp_ifindex;\n- getInput.getFlags = FLOW_GET_STATS | FLOW_GET_ACTIONS;\n-\n- /* 4th argument is a no op.\n- * We are keeping this argument to be compatible\n- * with our dpif-windows based interface. */\n- rc = OvsGetFlowIoctl(&getInput, &getOutput);\n- if (rc != STATUS_SUCCESS) {\n- OVS_LOG_ERROR(\"OvsGetFlowIoctl failed.\");\n- /*\n- * Report back to the userspace the flow could not be found\n- */\n- nlError = NL_ERROR_NOENT;\n- goto done;\n- }\n-\n- /* Lets prepare the reply. */\n- nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, 0, 0));\n-\n- /* Input already has all the attributes for the flow key.\n- * Lets copy the values back. */\n- ok = NlMsgPutTail(&nlBuf, (PCHAR)(usrParamsCtx->inputBuffer),\n- usrParamsCtx->inputLength);\n- if (!ok) {\n- OVS_LOG_ERROR(\"Could not copy the data to the buffer tail\");\n- goto done;\n- }\n-\n- rc = _MapFlowStatsToNlStats(&nlBuf, &((getOutput.info).stats));\n- if (rc != STATUS_SUCCESS) {\n- OVS_LOG_ERROR(\"_OvsFlowMapFlowKeyToNlStats failed.\");\n- goto done;\n- }\n-\n- rc = _MapFlowActionToNlAction(&nlBuf, ((getOutput.info).actionsLen),\n- getOutput.info.actions);\n- if (rc != STATUS_SUCCESS) {\n- OVS_LOG_ERROR(\"_MapFlowActionToNlAction failed.\");\n- goto done;\n- }\n-\n- NlMsgSetSize(nlMsgOutHdr, NlBufSize(&nlBuf));\n- NlMsgAlignSize(nlMsgOutHdr);\n- *replyLen += NlMsgSize(nlMsgOutHdr);\n-\n-done:\n- if (nlError != NL_ERROR_SUCCESS) {\n- POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)\n- usrParamsCtx->outputBuffer;\n-\n- ASSERT(msgError);\n- NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);\n- ASSERT(*replyLen != 0);\n- rc = STATUS_SUCCESS;\n- }\n-\n- return rc;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * _FlowNlDumpCmdHandler --\n- * Handler for OVS_FLOW_CMD_DUMP command.\n- *----------------------------------------------------------------------------\n- */\n-NTSTATUS\n-_FlowNlDumpCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen)\n-{\n- NTSTATUS rc = STATUS_SUCCESS;\n- UINT32 temp = 0; /* To keep compiler happy for calling OvsDoDumpFlows */\n- NL_ERROR nlError = NL_ERROR_SUCCESS;\n- POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)\n- (usrParamsCtx->ovsInstance);\n- POVS_MESSAGE msgIn = instance->dumpState.ovsMsg;\n-\n- if (usrParamsCtx->devOp == OVS_WRITE_DEV_OP) {\n- /* Dump Start */\n- OvsSetupDumpStart(usrParamsCtx);\n- goto done;\n- }\n-\n- PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);\n- PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);\n- POVS_HDR ovsHdr = &(msgIn->ovsHdr);\n- PNL_MSG_HDR nlMsgOutHdr = NULL;\n- UINT32 hdrOffset = 0;\n-\n- /* Get Next */\n- OvsFlowDumpOutput dumpOutput;\n- OvsFlowDumpInput dumpInput;\n- NL_BUFFER nlBuf;\n-\n- NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,\n- usrParamsCtx->outputLength);\n-\n- ASSERT(usrParamsCtx->devOp == OVS_READ_DEV_OP);\n- ASSERT(usrParamsCtx->outputLength);\n-\n- RtlZeroMemory(&dumpInput, sizeof(OvsFlowDumpInput));\n- RtlZeroMemory(&dumpOutput, sizeof(OvsFlowDumpOutput));\n-\n- dumpInput.dpNo = ovsHdr->dp_ifindex;\n- dumpInput.getFlags = FLOW_GET_KEY | FLOW_GET_STATS | FLOW_GET_ACTIONS;\n-\n- /* Lets provide as many flows to userspace as possible. */\n- do {\n- dumpInput.position[0] = instance->dumpState.index[0];\n- dumpInput.position[1] = instance->dumpState.index[1];\n-\n- rc = OvsDoDumpFlows(&dumpInput, &dumpOutput, &temp);\n- if (rc != STATUS_SUCCESS) {\n- OVS_LOG_ERROR(\"OvsDoDumpFlows failed with rc: %d\", rc);\n- /*\n- * Report back to the userspace the flows could not be found\n- */\n- nlError = NL_ERROR_NOENT;\n- break;\n- }\n-\n- /* Done with Dump, send NLMSG_DONE */\n- if (!(dumpOutput.n)) {\n- BOOLEAN ok;\n-\n- OVS_LOG_INFO(\"Dump Done\");\n-\n- nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, NlBufSize(&nlBuf), 0));\n- ok = NlFillNlHdr(&nlBuf, NLMSG_DONE, NLM_F_MULTI,\n- nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid);\n-\n- if (!ok) {\n- rc = STATUS_INVALID_BUFFER_SIZE;\n- OVS_LOG_ERROR(\"Unable to prepare DUMP_DONE reply.\");\n- break;\n- } else {\n- rc = STATUS_SUCCESS;\n- }\n-\n- NlMsgAlignSize(nlMsgOutHdr);\n- *replyLen += NlMsgSize(nlMsgOutHdr);\n-\n- FreeUserDumpState(instance);\n- break;\n- } else {\n- BOOLEAN ok;\n-\n- hdrOffset = NlBufSize(&nlBuf);\n- nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, hdrOffset, 0));\n-\n- /* Netlink header */\n- ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, NLM_F_MULTI,\n- nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,\n- genlMsgHdr->cmd, genlMsgHdr->version,\n- ovsHdr->dp_ifindex);\n-\n- if (!ok) {\n- /* Reset rc to success so that we can\n- * send already added messages to user space. */\n- rc = STATUS_SUCCESS;\n- break;\n- }\n-\n- /* Time to add attributes */\n- rc = _MapFlowInfoToNl(&nlBuf, &(dumpOutput.flow));\n- if (rc != STATUS_SUCCESS) {\n- /* Adding the attribute failed, we are out of\n- space in the buffer, remove the appended OVS header */\n- NlMsgSetSize(nlMsgOutHdr,\n- NlMsgSize(nlMsgOutHdr) -\n- sizeof(struct _OVS_MESSAGE));\n-\n- /* Reset rc to success so that we can\n- * send already added messages to user space. */\n- rc = STATUS_SUCCESS;\n- break;\n- }\n-\n- NlMsgSetSize(nlMsgOutHdr, NlBufSize(&nlBuf) - hdrOffset);\n- NlMsgAlignSize(nlMsgOutHdr);\n- *replyLen += NlMsgSize(nlMsgOutHdr);\n- instance->dumpState.index[0] = dumpOutput.position[0];\n- instance->dumpState.index[1] = dumpOutput.position[1];\n- }\n- } while(TRUE);\n-\n-done:\n- if (nlError != NL_ERROR_SUCCESS) {\n- POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)\n- usrParamsCtx->outputBuffer;\n- ASSERT(msgError);\n- NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);\n- ASSERT(*replyLen != 0);\n- rc = STATUS_SUCCESS;\n- }\n-\n- return rc;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * _MapFlowInfoToNl --\n- * Maps OvsFlowInfo to Netlink attributes.\n- *----------------------------------------------------------------------------\n- */\n-static NTSTATUS\n-_MapFlowInfoToNl(PNL_BUFFER nlBuf, OvsFlowInfo *flowInfo)\n-{\n- NTSTATUS rc;\n-\n- rc = MapFlowKeyToNlKey(nlBuf, &(flowInfo->key), OVS_FLOW_ATTR_KEY,\n- OVS_KEY_ATTR_TUNNEL);\n- if (rc != STATUS_SUCCESS) {\n- goto done;\n- }\n-\n- rc = _MapFlowStatsToNlStats(nlBuf, &(flowInfo->stats));\n- if (rc != STATUS_SUCCESS) {\n- goto done;\n- }\n-\n- rc = _MapFlowActionToNlAction(nlBuf, flowInfo->actionsLen,\n- flowInfo->actions);\n- if (rc != STATUS_SUCCESS) {\n- goto done;\n- }\n-\n-done:\n- return rc;\n-}\n-\n-UINT64\n-OvsFlowUsedTime(UINT64 flowUsed)\n-{\n- UINT64 currentMs, iddleMs;\n- LARGE_INTEGER tickCount;\n-\n- KeQueryTickCount(&tickCount);\n- iddleMs = tickCount.QuadPart - flowUsed;\n- iddleMs *= ovsTimeIncrementPerTick;\n- currentMs = KeQueryPerformanceCounter(&tickCount).QuadPart * 1000 /\n- tickCount.QuadPart;\n- return currentMs - iddleMs;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * _MapFlowStatsToNlStats --\n- * Maps OvsFlowStats to OVS_FLOW_ATTR_STATS attribute.\n- *----------------------------------------------------------------------------\n- */\n-static NTSTATUS\n-_MapFlowStatsToNlStats(PNL_BUFFER nlBuf, OvsFlowStats *flowStats)\n-{\n- NTSTATUS rc = STATUS_SUCCESS;\n- struct ovs_flow_stats replyStats;\n-\n- replyStats.n_packets = flowStats->packetCount;\n- replyStats.n_bytes = flowStats->byteCount;\n-\n- if (flowStats->used &&\n- !NlMsgPutTailU64(nlBuf, OVS_FLOW_ATTR_USED,\n- OvsFlowUsedTime(flowStats->used))\n- ) {\n- rc = STATUS_INVALID_BUFFER_SIZE;\n- goto done;\n- }\n-\n- if (!NlMsgPutTailUnspec(nlBuf, OVS_FLOW_ATTR_STATS,\n- (PCHAR)(&replyStats),\n- sizeof(struct ovs_flow_stats))) {\n- rc = STATUS_INVALID_BUFFER_SIZE;\n- goto done;\n- }\n-\n- if (!NlMsgPutTailU8(nlBuf, OVS_FLOW_ATTR_TCP_FLAGS, flowStats->tcpFlags)) {\n- rc = STATUS_INVALID_BUFFER_SIZE;\n- goto done;\n- }\n-\n-done:\n- return rc;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * _MapFlowActionToNlAction --\n- * Maps flow actions to OVS_FLOW_ATTR_ACTION attribute.\n- *----------------------------------------------------------------------------\n- */\n-static NTSTATUS\n-_MapFlowActionToNlAction(PNL_BUFFER nlBuf, uint32_t actionsLen,\n- PNL_ATTR actions)\n-{\n- NTSTATUS rc = STATUS_SUCCESS;\n- UINT32 offset = 0;\n-\n- offset = NlMsgStartNested(nlBuf, OVS_FLOW_ATTR_ACTIONS);\n- if (!offset) {\n- /* Starting the nested attribute failed. */\n- rc = STATUS_INVALID_BUFFER_SIZE;\n- goto error_nested_start;\n- }\n-\n- if (!NlBufCopyAtTail(nlBuf, (PCHAR)actions, actionsLen)) {\n- /* Adding a nested attribute failed. */\n- rc = STATUS_INVALID_BUFFER_SIZE;\n- goto done;\n- }\n-\n-done:\n- NlMsgEndNested(nlBuf, offset);\n-error_nested_start:\n- return rc;\n-\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * MapFlowKeyToNlKey --\n- * Maps OvsFlowKey to OVS_FLOW_ATTR_KEY attribute.\n- *----------------------------------------------------------------------------\n- */\n-NTSTATUS\n-MapFlowKeyToNlKey(PNL_BUFFER nlBuf,\n- OvsFlowKey *flowKey,\n- UINT16 keyType,\n- UINT16 tunKeyType)\n-{\n- NTSTATUS rc = STATUS_SUCCESS;\n- struct ovs_key_ethernet ethKey;\n- UINT32 offset = 0, encap_offset = 0;\n-\n- offset = NlMsgStartNested(nlBuf, keyType);\n- if (!offset) {\n- /* Starting the nested attribute failed. */\n- rc = STATUS_UNSUCCESSFUL;\n- goto error_nested_start;\n- }\n-\n- if (!NlMsgPutTailU32(nlBuf, OVS_KEY_ATTR_RECIRC_ID,\n- flowKey->recircId)) {\n- rc = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n-\n- if (!NlMsgPutTailU32(nlBuf, OVS_KEY_ATTR_CT_STATE,\n- flowKey->ct.state)) {\n- rc = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n- if (!NlMsgPutTailU16(nlBuf, OVS_KEY_ATTR_CT_ZONE,\n- flowKey->ct.zone)) {\n- rc = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n- if (!NlMsgPutTailU32(nlBuf, OVS_KEY_ATTR_CT_MARK,\n- flowKey->ct.mark)) {\n- rc = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n- if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_CT_LABELS,\n- (PCHAR)(&flowKey->ct.labels),\n- sizeof(struct ovs_key_ct_labels))) {\n- rc = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n- if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4,\n- (PCHAR)(&flowKey->ct.tuple_ipv4),\n- sizeof(struct ovs_key_ct_tuple_ipv4))) {\n- rc = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n-\n- if (flowKey->dpHash) {\n- if (!NlMsgPutTailU32(nlBuf, OVS_KEY_ATTR_DP_HASH,\n- flowKey->dpHash)) {\n- rc = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n- }\n-\n- /* Ethernet header */\n- RtlCopyMemory(&(ethKey.eth_src), flowKey->l2.dlSrc, ETH_ADDR_LEN);\n- RtlCopyMemory(&(ethKey.eth_dst), flowKey->l2.dlDst, ETH_ADDR_LEN);\n-\n- if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ETHERNET,\n- (PCHAR)(ðKey),\n- sizeof(struct ovs_key_ethernet))) {\n- rc = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n-\n- if (!NlMsgPutTailU32(nlBuf, OVS_KEY_ATTR_IN_PORT,\n- flowKey->l2.inPort)) {\n- rc = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n-\n- if (!NlMsgPutTailU16(nlBuf, OVS_KEY_ATTR_ETHERTYPE,\n- flowKey->l2.vlanKey.vlanTci == 0 ? flowKey->l2.dlType :\n- flowKey->l2.vlanKey.vlanTpid)) {\n- rc = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n-\n- if (flowKey->l2.vlanKey.vlanTci ||\n- flowKey->l2.dlType == ETH_TYPE_802_1PQ) {\n- if (!NlMsgPutTailU16(nlBuf, OVS_KEY_ATTR_VLAN,\n- flowKey->l2.vlanKey.vlanTci)) {\n- rc = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n-\n- /* Add encap attributes. */\n- encap_offset = NlMsgStartNested(nlBuf, OVS_KEY_ATTR_ENCAP);\n- if (!encap_offset) {\n- /* Starting the nested attribute failed. */\n- rc = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n-\n- /* Add packet Ethernet Type*/\n- if (!NlMsgPutTailU16(nlBuf, OVS_KEY_ATTR_ETHERTYPE,\n- flowKey->l2.dlType)) {\n- rc = STATUS_UNSUCCESSFUL;\n- goto encap;\n- }\n- }\n-\n- /* ==== L3 + L4 ==== */\n- switch (ntohs(flowKey->l2.dlType)) {\n- case ETH_TYPE_IPV4: {\n- IpKey *ipv4FlowPutKey = &(flowKey->ipKey);\n- rc = _MapFlowIpv4KeyToNlKey(nlBuf, ipv4FlowPutKey);\n- break;\n- }\n-\n- case ETH_TYPE_IPV6: {\n- Ipv6Key *ipv6FlowPutKey = &(flowKey->ipv6Key);\n- Icmp6Key *icmpv6FlowPutKey = &(flowKey->icmp6Key);\n- rc = _MapFlowIpv6KeyToNlKey(nlBuf, ipv6FlowPutKey,\n- icmpv6FlowPutKey);\n- break;\n- }\n-\n- case ETH_TYPE_ARP:\n- case ETH_TYPE_RARP: {\n- ArpKey *arpFlowPutKey = &(flowKey->arpKey);\n- rc = _MapFlowArpKeyToNlKey(nlBuf, arpFlowPutKey);\n- break;\n- }\n-\n- case ETH_TYPE_MPLS:\n- case ETH_TYPE_MPLS_MCAST: {\n- MplsKey *mplsFlowPutKey = &(flowKey->mplsKey);\n- rc = _MapFlowMplsKeyToNlKey(nlBuf, mplsFlowPutKey);\n- break;\n- }\n-\n- default:\n- break;\n- }\n-\n- if (rc != STATUS_SUCCESS) {\n- goto done;\n- }\n-\n- if (!OvsIphIsZero(&(flowKey->tunKey.dst))) {\n- rc = MapFlowTunKeyToNlKey(nlBuf, &(flowKey->tunKey),\n- tunKeyType);\n- if (rc != STATUS_SUCCESS) {\n- goto done;\n- }\n- }\n-encap:\n- if (encap_offset) {\n- NlMsgEndNested(nlBuf, encap_offset);\n- }\n-\n-done:\n- NlMsgEndNested(nlBuf, offset);\n-error_nested_start:\n- return rc;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * MapFlowTunKeyToNlKey --\n- * Maps OvsIPTunnelKey to OVS_TUNNEL_KEY_ATTR_ID attribute.\n- *----------------------------------------------------------------------------\n- */\n-NTSTATUS\n-MapFlowTunKeyToNlKey(PNL_BUFFER nlBuf,\n- OvsIPTunnelKey*tunKey,\n- UINT16 tunKeyType)\n-{\n- NTSTATUS rc = STATUS_SUCCESS;\n- UINT32 offset = 0;\n-\n- offset = NlMsgStartNested(nlBuf, tunKeyType);\n- if (!offset) {\n- /* Starting the nested attribute failed. */\n- rc = STATUS_UNSUCCESSFUL;\n- goto error_nested_start;\n- }\n-\n- if (!NlMsgPutTailU64(nlBuf, OVS_TUNNEL_KEY_ATTR_ID,\n- tunKey->tunnelId)) {\n- rc = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n-\n-\n- if (!OvsIphIsZero(&tunKey->dst)) {\n- if (tunKey->dst.si_family == AF_INET) {\n- if (!NlMsgPutTailU32(nlBuf, OVS_TUNNEL_KEY_ATTR_IPV4_DST,\n- tunKey->dst.Ipv4.sin_addr.s_addr)) {\n- rc = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n- } else if (tunKey->dst.si_family == AF_INET6) {\n- if (!NlMsgPutTailUnspec(nlBuf, OVS_TUNNEL_KEY_ATTR_IPV6_DST,\n- (PCHAR)&tunKey->dst.Ipv6.sin6_addr,\n- sizeof(tunKey->dst.Ipv6.sin6_addr))) {\n- rc = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n- }\n- }\n-\n- if (!OvsIphIsZero(&tunKey->src)) {\n- if (tunKey->src.si_family == AF_INET) {\n- if (!NlMsgPutTailU32(nlBuf, OVS_TUNNEL_KEY_ATTR_IPV4_SRC,\n- tunKey->src.Ipv4.sin_addr.s_addr)) {\n- rc = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n- } else if (tunKey->src.si_family == AF_INET6) {\n- if (!NlMsgPutTailUnspec(nlBuf, OVS_TUNNEL_KEY_ATTR_IPV6_SRC,\n- (PCHAR)&tunKey->src.Ipv6.sin6_addr,\n- sizeof(tunKey->src.Ipv6.sin6_addr))) {\n- rc = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n- }\n- }\n-\n- if (!NlMsgPutTailU8(nlBuf, OVS_TUNNEL_KEY_ATTR_TOS,\n- tunKey->tos)) {\n- rc = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n-\n- if (!NlMsgPutTailU8(nlBuf, OVS_TUNNEL_KEY_ATTR_TTL,\n- tunKey->ttl)) {\n- rc = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n-\n- if (tunKey->tunOptLen > 0 &&\n- !NlMsgPutTailUnspec(nlBuf, OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS,\n- (PCHAR)IPTunnelKeyGetOptions(tunKey),\n- tunKey->tunOptLen)) {\n- rc = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n-\n- if (!NlMsgPutTailU16(nlBuf, OVS_TUNNEL_KEY_ATTR_TP_SRC,\n- tunKey->flow_hash)) {\n- rc = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n-\n- if (!NlMsgPutTailU16(nlBuf, OVS_TUNNEL_KEY_ATTR_TP_DST,\n- tunKey->dst_port)) {\n- rc = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n-\n-done:\n- NlMsgEndNested(nlBuf, offset);\n-error_nested_start:\n- return rc;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * _MapFlowTunKeyToNlKey --\n- * Maps OvsIPv4FlowPutKey to OVS_KEY_ATTR_IPV4 attribute.\n- *----------------------------------------------------------------------------\n- */\n-static NTSTATUS\n-_MapFlowIpv4KeyToNlKey(PNL_BUFFER nlBuf, IpKey *ipv4FlowPutKey)\n-{\n- NTSTATUS rc = STATUS_SUCCESS;\n- struct ovs_key_ipv4 ipv4Key;\n-\n- ipv4Key.ipv4_src = ipv4FlowPutKey->nwSrc;\n- ipv4Key.ipv4_dst = ipv4FlowPutKey->nwDst;\n- ipv4Key.ipv4_proto = ipv4FlowPutKey->nwProto;\n- ipv4Key.ipv4_tos = ipv4FlowPutKey->nwTos;\n- ipv4Key.ipv4_ttl = ipv4FlowPutKey->nwTtl;\n- ipv4Key.ipv4_frag = ipv4FlowPutKey->nwFrag;\n-\n- if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_IPV4,\n- (PCHAR)(&ipv4Key),\n- sizeof(struct ovs_key_ipv4))) {\n- rc = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n-\n- switch (ipv4Key.ipv4_proto) {\n- case IPPROTO_TCP: {\n- struct ovs_key_tcp tcpKey;\n- tcpKey.tcp_src = ipv4FlowPutKey->l4.tpSrc;\n- tcpKey.tcp_dst = ipv4FlowPutKey->l4.tpDst;\n- if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_TCP,\n- (PCHAR)(&tcpKey),\n- sizeof(tcpKey))) {\n- rc = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n- break;\n- }\n-\n- case IPPROTO_UDP: {\n- struct ovs_key_udp udpKey;\n- udpKey.udp_src = ipv4FlowPutKey->l4.tpSrc;\n- udpKey.udp_dst = ipv4FlowPutKey->l4.tpDst;\n- if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_UDP,\n- (PCHAR)(&udpKey),\n- sizeof(udpKey))) {\n- rc = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n- break;\n- }\n-\n- case IPPROTO_SCTP: {\n- struct ovs_key_sctp sctpKey;\n- sctpKey.sctp_src = ipv4FlowPutKey->l4.tpSrc;\n- sctpKey.sctp_dst = ipv4FlowPutKey->l4.tpDst;\n- if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_SCTP,\n- (PCHAR)(&sctpKey),\n- sizeof(sctpKey))) {\n- rc = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n- break;\n- }\n-\n- case IPPROTO_ICMP: {\n- struct ovs_key_icmp icmpKey;\n- icmpKey.icmp_type = (__u8)ntohs(ipv4FlowPutKey->l4.tpSrc);\n- icmpKey.icmp_code = (__u8)ntohs(ipv4FlowPutKey->l4.tpDst);\n-\n- if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ICMP,\n- (PCHAR)(&icmpKey),\n- sizeof(icmpKey))) {\n- rc = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n- break;\n- }\n-\n- default:\n- break;\n- }\n-\n-done:\n- return rc;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * _MapFlowIpv6KeyToNlKey --\n- * Maps _MapFlowIpv6KeyToNlKey to OVS_KEY_ATTR_IPV6 attribute.\n- *----------------------------------------------------------------------------\n- */\n-static NTSTATUS\n-_MapFlowIpv6KeyToNlKey(PNL_BUFFER nlBuf, Ipv6Key *ipv6FlowPutKey,\n- Icmp6Key *icmpv6FlowPutKey)\n-{\n- NTSTATUS rc = STATUS_SUCCESS;\n- struct ovs_key_ipv6 ipv6Key;\n-\n- RtlCopyMemory(&(ipv6Key.ipv6_src), &ipv6FlowPutKey->ipv6Src,\n- sizeof ipv6Key.ipv6_src);\n- RtlCopyMemory(&(ipv6Key.ipv6_dst), &ipv6FlowPutKey->ipv6Dst,\n- sizeof ipv6Key.ipv6_dst);\n-\n- ipv6Key.ipv6_label = ipv6FlowPutKey->ipv6Label;\n- ipv6Key.ipv6_proto = ipv6FlowPutKey->nwProto;\n- ipv6Key.ipv6_tclass = ipv6FlowPutKey->nwTos;\n- ipv6Key.ipv6_hlimit = ipv6FlowPutKey->nwTtl;\n- ipv6Key.ipv6_frag = ipv6FlowPutKey->nwFrag;\n-\n- if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_IPV6,\n- (PCHAR)(&ipv6Key),\n- sizeof(ipv6Key))) {\n- rc = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n-\n- switch (ipv6Key.ipv6_proto) {\n- case IPPROTO_TCP: {\n- struct ovs_key_tcp tcpKey;\n- tcpKey.tcp_src = ipv6FlowPutKey->l4.tpSrc;\n- tcpKey.tcp_dst = ipv6FlowPutKey->l4.tpDst;\n- if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_TCP,\n- (PCHAR)(&tcpKey),\n- sizeof(tcpKey))) {\n- rc = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n- break;\n- }\n-\n- case IPPROTO_UDP: {\n- struct ovs_key_udp udpKey;\n- udpKey.udp_src = ipv6FlowPutKey->l4.tpSrc;\n- udpKey.udp_dst = ipv6FlowPutKey->l4.tpDst;\n- if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_UDP,\n- (PCHAR)(&udpKey),\n- sizeof(udpKey))) {\n- rc = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n- break;\n- }\n-\n- case IPPROTO_SCTP: {\n- struct ovs_key_sctp sctpKey;\n- sctpKey.sctp_src = ipv6FlowPutKey->l4.tpSrc;\n- sctpKey.sctp_dst = ipv6FlowPutKey->l4.tpDst;\n- if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_SCTP,\n- (PCHAR)(&sctpKey),\n- sizeof(sctpKey))) {\n- rc = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n- break;\n- }\n-\n- case IPPROTO_ICMPV6: {\n- struct ovs_key_icmpv6 icmpV6Key;\n- struct ovs_key_nd ndKey;\n-\n- icmpV6Key.icmpv6_type = (__u8)ntohs(icmpv6FlowPutKey->l4.tpSrc);\n- icmpV6Key.icmpv6_code = (__u8)ntohs(icmpv6FlowPutKey->l4.tpDst);\n-\n- if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ICMPV6,\n- (PCHAR)(&icmpV6Key),\n- sizeof(icmpV6Key))) {\n- rc = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n-\n- RtlCopyMemory(&(ndKey.nd_target), &icmpv6FlowPutKey->ndTarget,\n- sizeof(icmpv6FlowPutKey->ndTarget));\n- RtlCopyMemory(&(ndKey.nd_sll), &icmpv6FlowPutKey->arpSha,\n- ETH_ADDR_LEN);\n- RtlCopyMemory(&(ndKey.nd_tll), &icmpv6FlowPutKey->arpTha,\n- ETH_ADDR_LEN);\n- if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ND,\n- (PCHAR)(&ndKey),\n- sizeof(ndKey))) {\n- rc = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n-\n- break;\n- }\n-\n- default:\n- break;\n- }\n-\n-done:\n- return rc;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * _MapFlowArpKeyToNlKey --\n- * Maps _MapFlowArpKeyToNlKey to OVS_KEY_ATTR_ARP attribute.\n- *----------------------------------------------------------------------------\n- */\n-static NTSTATUS\n-_MapFlowArpKeyToNlKey(PNL_BUFFER nlBuf, ArpKey *arpFlowPutKey)\n-{\n- NTSTATUS rc = STATUS_SUCCESS;\n- struct ovs_key_arp arpKey;\n-\n- arpKey.arp_sip = arpFlowPutKey->nwSrc;\n- arpKey.arp_tip = arpFlowPutKey->nwDst;\n-\n- RtlCopyMemory(&(arpKey.arp_sha), arpFlowPutKey->arpSha, ETH_ADDR_LEN);\n- RtlCopyMemory(&(arpKey.arp_tha), arpFlowPutKey->arpTha, ETH_ADDR_LEN);\n-\n- /*\n- * Flow_Extract() stores 'nwProto' in host order for ARP since 'nwProto' is\n- * 1 byte field and the ARP opcode is 2 bytes, and all of the kernel code\n- * understand this while looking at an ARP key.\n- * While we pass up the ARP key to userspace, convert from host order to\n- * network order. Likewise, when processing an ARP key from userspace,\n- * convert from network order to host order.\n- *\n- * It is important to note that the flow table stores the ARP opcode field\n- * in host order.\n- */\n- arpKey.arp_op = htons(arpFlowPutKey->nwProto);\n-\n- if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ARP,\n- (PCHAR)(&arpKey),\n- sizeof(arpKey))) {\n- rc = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n-\n-done:\n- return rc;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * _MapFlowMplsKeyToNlKey --\n- * Maps _MapFlowMplsKeyToNlKey to OVS_KEY_ATTR_MPLS attribute.\n- *----------------------------------------------------------------------------\n- */\n-static NTSTATUS\n-_MapFlowMplsKeyToNlKey(PNL_BUFFER nlBuf, MplsKey *mplsFlowPutKey)\n-{\n- NTSTATUS rc = STATUS_SUCCESS;\n- struct ovs_key_mpls *mplsKey;\n-\n- mplsKey = (struct ovs_key_mpls *)\n- NlMsgPutTailUnspecUninit(nlBuf, OVS_KEY_ATTR_MPLS, sizeof(*mplsKey));\n- if (!mplsKey) {\n- rc = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n-\n- mplsKey->mpls_lse = mplsFlowPutKey->lse;\n-\n-done:\n- return rc;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * _MapNlToFlowPut --\n- * Maps input netlink message to OvsFlowPut.\n- *----------------------------------------------------------------------------\n- */\n-static NTSTATUS\n-_MapNlToFlowPut(POVS_MESSAGE msgIn, PNL_ATTR keyAttr,\n- PNL_ATTR actionAttr, PNL_ATTR flowAttrClear,\n- OvsFlowPut *mappedFlow)\n-{\n- NTSTATUS rc = STATUS_SUCCESS;\n- PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);\n- PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);\n- POVS_HDR ovsHdr = &(msgIn->ovsHdr);\n-\n- UINT32 keyAttrOffset = (UINT32)((PCHAR)keyAttr - (PCHAR)nlMsgHdr);\n- UINT32 tunnelKeyAttrOffset;\n- UINT32 encapOffset = 0;\n-\n- PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX] = {NULL};\n- PNL_ATTR tunnelAttrs[__OVS_TUNNEL_KEY_ATTR_MAX] = {NULL};\n- PNL_ATTR encapAttrs[__OVS_KEY_ATTR_MAX] = { NULL };\n-\n- /* Get flow keys attributes */\n- if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset, NlAttrLen(keyAttr),\n- nlFlowKeyPolicy, ARRAY_SIZE(nlFlowKeyPolicy),\n- keyAttrs, ARRAY_SIZE(keyAttrs)))\n- != TRUE) {\n- OVS_LOG_ERROR(\"Key Attr Parsing failed for msg: %p\",\n- nlMsgHdr);\n- rc = STATUS_INVALID_PARAMETER;\n- goto done;\n- }\n-\n- if (keyAttrs[OVS_KEY_ATTR_ENCAP]) {\n- encapOffset = (UINT32)((PCHAR)(keyAttrs[OVS_KEY_ATTR_ENCAP])\n- - (PCHAR)nlMsgHdr);\n-\n- if ((NlAttrParseNested(nlMsgHdr, encapOffset,\n- NlAttrLen(keyAttrs[OVS_KEY_ATTR_ENCAP]),\n- nlFlowKeyPolicy,\n- ARRAY_SIZE(nlFlowKeyPolicy),\n- encapAttrs, ARRAY_SIZE(encapAttrs)))\n- != TRUE) {\n- OVS_LOG_ERROR(\"Encap Key Attr Parsing failed for msg: %p\",\n- nlMsgHdr);\n- rc = STATUS_INVALID_PARAMETER;\n- goto done;\n- }\n- }\n-\n- if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {\n- tunnelKeyAttrOffset = (UINT32)((PCHAR)\n- (keyAttrs[OVS_KEY_ATTR_TUNNEL])\n- - (PCHAR)nlMsgHdr);\n-\n- /* Get tunnel keys attributes */\n- if ((NlAttrParseNested(nlMsgHdr, tunnelKeyAttrOffset,\n- NlAttrLen(keyAttrs[OVS_KEY_ATTR_TUNNEL]),\n- nlFlowTunnelKeyPolicy,\n- ARRAY_SIZE(nlFlowTunnelKeyPolicy),\n- tunnelAttrs, ARRAY_SIZE(tunnelAttrs)))\n- != TRUE) {\n- OVS_LOG_ERROR(\"Tunnel key Attr Parsing failed for msg: %p\",\n- nlMsgHdr);\n- rc = STATUS_INVALID_PARAMETER;\n- goto done;\n- }\n- }\n-\n- _MapKeyAttrToFlowPut(keyAttrs, tunnelAttrs,\n- &(mappedFlow->key));\n- ASSERT(keyAttrs[OVS_KEY_ATTR_IN_PORT]);\n-\n- if (encapOffset) {\n- _MapKeyAttrToFlowPut(encapAttrs, tunnelAttrs,\n- &(mappedFlow->key));\n- }\n-\n- /* Map the action */\n- if (actionAttr) {\n- mappedFlow->actionsLen = NlAttrGetSize(actionAttr);\n- mappedFlow->actions = NlAttrGet(actionAttr);\n- }\n-\n- mappedFlow->dpNo = ovsHdr->dp_ifindex;\n-\n- _MapNlToFlowPutFlags(genlMsgHdr, flowAttrClear,\n- mappedFlow);\n-\n-done:\n- return rc;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * _MapNlToFlowPutFlags --\n- * Maps netlink message to OvsFlowPut->flags.\n- *----------------------------------------------------------------------------\n- */\n-static VOID\n-_MapNlToFlowPutFlags(PGENL_MSG_HDR genlMsgHdr,\n- PNL_ATTR flowAttrClear, OvsFlowPut *mappedFlow)\n-{\n- uint32_t flags = 0;\n-\n- switch (genlMsgHdr->cmd) {\n- case OVS_FLOW_CMD_NEW:\n- flags |= OVSWIN_FLOW_PUT_CREATE;\n- break;\n- case OVS_FLOW_CMD_DEL:\n- flags |= OVSWIN_FLOW_PUT_DELETE;\n- break;\n- case OVS_FLOW_CMD_SET:\n- flags |= OVSWIN_FLOW_PUT_MODIFY;\n- break;\n- default:\n- ASSERT(0);\n- }\n-\n- if (flowAttrClear) {\n- flags |= OVSWIN_FLOW_PUT_CLEAR;\n- }\n-\n- mappedFlow->flags = flags;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * _MapKeyAttrToFlowPut --\n- * Converts FLOW_KEY attribute to OvsFlowPut->key.\n- *----------------------------------------------------------------------------\n- */\n-static VOID\n-_MapKeyAttrToFlowPut(PNL_ATTR *keyAttrs,\n- PNL_ATTR *tunnelAttrs,\n- OvsFlowKey *destKey)\n-{\n- MapTunAttrToFlowPut(keyAttrs, tunnelAttrs, destKey);\n-\n- if (keyAttrs[OVS_KEY_ATTR_RECIRC_ID]) {\n- destKey->recircId = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_RECIRC_ID]);\n- }\n-\n- if (keyAttrs[OVS_KEY_ATTR_DP_HASH]) {\n- destKey->dpHash = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_DP_HASH]);\n- }\n-\n- if (keyAttrs[OVS_KEY_ATTR_CT_STATE]) {\n- destKey->ct.state = (NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_CT_STATE]));\n- }\n-\n- if (keyAttrs[OVS_KEY_ATTR_CT_ZONE]) {\n- destKey->ct.zone = (NlAttrGetU16(keyAttrs[OVS_KEY_ATTR_CT_ZONE]));\n- }\n-\n- if (keyAttrs[OVS_KEY_ATTR_CT_MARK]) {\n- destKey->ct.mark = (NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_CT_MARK]));\n- }\n-\n- if (keyAttrs[OVS_KEY_ATTR_CT_LABELS]) {\n- const struct ovs_key_ct_labels *ct_labels;\n- ct_labels = NlAttrGet(keyAttrs[OVS_KEY_ATTR_CT_LABELS]);\n- NdisMoveMemory(&destKey->ct.labels, ct_labels,\n- sizeof(struct ovs_key_ct_labels));\n- }\n-\n- if (keyAttrs[OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4]) {\n- const struct ovs_key_ct_tuple_ipv4 *tuple_ipv4;\n- tuple_ipv4 = NlAttrGet(keyAttrs[OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4]);\n- NdisMoveMemory(&destKey->ct.tuple_ipv4, tuple_ipv4,\n- sizeof(struct ovs_key_ct_tuple_ipv4));\n- }\n-\n- if (keyAttrs[OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6]) {\n- const struct ovs_key_ct_tuple_ipv6 *tuple_ipv6;\n- tuple_ipv6 = NlAttrGet(keyAttrs[OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6]);\n- NdisMoveMemory(&destKey->ct.tuple_ipv6, tuple_ipv6,\n- sizeof(struct ovs_key_ct_tuple_ipv6));\n- }\n-\n- /* ===== L2 headers ===== */\n- if (keyAttrs[OVS_KEY_ATTR_IN_PORT]) {\n- destKey->l2.inPort = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_IN_PORT]);\n- }\n-\n- if (keyAttrs[OVS_KEY_ATTR_ETHERNET]) {\n- const struct ovs_key_ethernet *eth_key;\n- eth_key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ETHERNET]);\n- RtlCopyMemory(destKey->l2.dlSrc, eth_key->eth_src, ETH_ADDR_LEN);\n- RtlCopyMemory(destKey->l2.dlDst, eth_key->eth_dst, ETH_ADDR_LEN);\n- }\n-\n- /* TODO: Ideally ETHERTYPE should not be optional.\n- * But during vswitchd bootup we are seeing FLOW_ADD\n- * requests with no ETHERTYPE attributes.\n- * Need to verify this. */\n- if (keyAttrs[OVS_KEY_ATTR_ETHERTYPE]) {\n- destKey->l2.dlType = (NlAttrGetU16(keyAttrs\n- [OVS_KEY_ATTR_ETHERTYPE]));\n- }\n-\n- if (keyAttrs[OVS_KEY_ATTR_VLAN]) {\n- destKey->l2.vlanKey.vlanTci = NlAttrGetU16(keyAttrs[OVS_KEY_ATTR_VLAN]);\n- if (destKey->l2.vlanKey.vlanTci != 0) {\n- /* set TPID to dlType. */\n- destKey->l2.vlanKey.vlanTpid = destKey->l2.dlType;\n- }\n- }\n-\n- /* ==== L3 + L4. ==== */\n- destKey->l2.keyLen = OVS_WIN_IP_TUNNEL_KEY_SIZE + OVS_L2_KEY_SIZE\n- - destKey->l2.offset;\n-\n- switch (ntohs(destKey->l2.dlType)) {\n- case ETH_TYPE_IPV4: {\n-\n- if (keyAttrs[OVS_KEY_ATTR_IPV4]) {\n- const struct ovs_key_ipv4 *ipv4Key;\n-\n- ipv4Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_IPV4]);\n- IpKey *ipv4FlowPutKey = &(destKey->ipKey);\n- ipv4FlowPutKey->nwSrc = ipv4Key->ipv4_src;\n- ipv4FlowPutKey->nwDst = ipv4Key->ipv4_dst;\n- ipv4FlowPutKey->nwProto = ipv4Key->ipv4_proto;\n- ipv4FlowPutKey->nwTos = ipv4Key->ipv4_tos;\n- ipv4FlowPutKey->nwTtl = ipv4Key->ipv4_ttl;\n- ipv4FlowPutKey->nwFrag = ipv4Key->ipv4_frag;\n-\n- if (keyAttrs[OVS_KEY_ATTR_TCP]) {\n- const struct ovs_key_tcp *tcpKey;\n- tcpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_TCP]);\n- ipv4FlowPutKey->l4.tpSrc = tcpKey->tcp_src;\n- ipv4FlowPutKey->l4.tpDst = tcpKey->tcp_dst;\n- }\n-\n- if (keyAttrs[OVS_KEY_ATTR_UDP]) {\n- const struct ovs_key_udp *udpKey;\n- udpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_UDP]);\n- ipv4FlowPutKey->l4.tpSrc = udpKey->udp_src;\n- ipv4FlowPutKey->l4.tpDst = udpKey->udp_dst;\n- }\n-\n- if (keyAttrs[OVS_KEY_ATTR_SCTP]) {\n- const struct ovs_key_sctp *sctpKey;\n- sctpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_SCTP]);\n- ipv4FlowPutKey->l4.tpSrc = sctpKey->sctp_src;\n- ipv4FlowPutKey->l4.tpDst = sctpKey->sctp_dst;\n- }\n-\n- if (keyAttrs[OVS_KEY_ATTR_ICMP]) {\n- const struct ovs_key_icmp *icmpKey;\n- icmpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ICMP]);\n- ipv4FlowPutKey->l4.tpSrc = htons(icmpKey->icmp_type);\n- ipv4FlowPutKey->l4.tpDst = htons(icmpKey->icmp_code);\n- }\n-\n- destKey->l2.keyLen += OVS_IP_KEY_SIZE;\n- }\n- break;\n- }\n- case ETH_TYPE_IPV6: {\n-\n- if (keyAttrs[OVS_KEY_ATTR_IPV6]) {\n- const struct ovs_key_ipv6 *ipv6Key;\n-\n- ipv6Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_IPV6]);\n- Ipv6Key *ipv6FlowPutKey = &(destKey->ipv6Key);\n-\n- RtlCopyMemory(&ipv6FlowPutKey->ipv6Src, ipv6Key->ipv6_src,\n- sizeof ipv6Key->ipv6_src);\n- RtlCopyMemory(&ipv6FlowPutKey->ipv6Dst, ipv6Key->ipv6_dst,\n- sizeof ipv6Key->ipv6_dst);\n-\n- ipv6FlowPutKey->ipv6Label = ipv6Key->ipv6_label;\n- ipv6FlowPutKey->nwProto = ipv6Key->ipv6_proto;\n- ipv6FlowPutKey->nwTos = ipv6Key->ipv6_tclass;\n- ipv6FlowPutKey->nwTtl = ipv6Key->ipv6_hlimit;\n- ipv6FlowPutKey->nwFrag = ipv6Key->ipv6_frag;\n-\n- if (keyAttrs[OVS_KEY_ATTR_TCP]) {\n- const struct ovs_key_tcp *tcpKey;\n- tcpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_TCP]);\n- ipv6FlowPutKey->l4.tpSrc = tcpKey->tcp_src;\n- ipv6FlowPutKey->l4.tpDst = tcpKey->tcp_dst;\n- }\n-\n- if (keyAttrs[OVS_KEY_ATTR_UDP]) {\n- const struct ovs_key_udp *udpKey;\n- udpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_UDP]);\n- ipv6FlowPutKey->l4.tpSrc = udpKey->udp_src;\n- ipv6FlowPutKey->l4.tpDst = udpKey->udp_dst;\n- }\n-\n- if (keyAttrs[OVS_KEY_ATTR_SCTP]) {\n- const struct ovs_key_sctp *sctpKey;\n- sctpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_SCTP]);\n- ipv6FlowPutKey->l4.tpSrc = sctpKey->sctp_src;\n- ipv6FlowPutKey->l4.tpDst = sctpKey->sctp_dst;\n- }\n-\n- if (keyAttrs[OVS_KEY_ATTR_ICMPV6]) {\n- const struct ovs_key_icmpv6 *icmpv6Key;\n-\n- Icmp6Key *icmp6FlowPutKey= &(destKey->icmp6Key);\n-\n- icmpv6Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ICMPV6]);\n-\n- icmp6FlowPutKey->l4.tpSrc = htons(icmpv6Key->icmpv6_type);\n- icmp6FlowPutKey->l4.tpDst = htons(icmpv6Key->icmpv6_code);\n-\n- if (keyAttrs[OVS_KEY_ATTR_ND]) {\n- const struct ovs_key_nd *ndKey;\n-\n- ndKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ND]);\n- RtlCopyMemory(&icmp6FlowPutKey->ndTarget,\n- ndKey->nd_target,\n- sizeof (icmp6FlowPutKey->ndTarget));\n- RtlCopyMemory(icmp6FlowPutKey->arpSha,\n- ndKey->nd_sll, ETH_ADDR_LEN);\n- RtlCopyMemory(icmp6FlowPutKey->arpTha,\n- ndKey->nd_tll, ETH_ADDR_LEN);\n- }\n-\n- destKey->l2.keyLen += OVS_ICMPV6_KEY_SIZE;\n-\n- } else {\n-\n- destKey->l2.keyLen += OVS_IPV6_KEY_SIZE;\n- }\n-\n- ipv6FlowPutKey->pad = 0;\n- }\n- break;\n- }\n- case ETH_TYPE_ARP:\n- case ETH_TYPE_RARP: {\n-\n- if (keyAttrs[OVS_KEY_ATTR_ARP]) {\n- ArpKey *arpFlowPutKey = &destKey->arpKey;\n- const struct ovs_key_arp *arpKey;\n-\n- arpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ARP]);\n-\n- arpFlowPutKey->nwSrc = arpKey->arp_sip;\n- arpFlowPutKey->nwDst = arpKey->arp_tip;\n-\n- RtlCopyMemory(arpFlowPutKey->arpSha, arpKey->arp_sha,\n- ETH_ADDR_LEN);\n- RtlCopyMemory(arpFlowPutKey->arpTha, arpKey->arp_tha,\n- ETH_ADDR_LEN);\n- /* Kernel datapath assumes 'arpFlowPutKey->nwProto' to be in host\n- * order. */\n- arpFlowPutKey->nwProto = (UINT8)ntohs((arpKey->arp_op));\n- arpFlowPutKey->pad[0] = 0;\n- arpFlowPutKey->pad[1] = 0;\n- arpFlowPutKey->pad[2] = 0;\n- destKey->l2.keyLen += OVS_ARP_KEY_SIZE;\n- }\n- break;\n- }\n- case ETH_TYPE_MPLS:\n- case ETH_TYPE_MPLS_MCAST: {\n-\n- if (keyAttrs[OVS_KEY_ATTR_MPLS]) {\n- MplsKey *mplsFlowPutKey = &destKey->mplsKey;\n- const struct ovs_key_mpls *mplsKey;\n-\n- mplsKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_MPLS]);\n-\n- mplsFlowPutKey->lse = mplsKey->mpls_lse;\n- mplsFlowPutKey->pad[0] = 0;\n- mplsFlowPutKey->pad[1] = 0;\n- mplsFlowPutKey->pad[2] = 0;\n- mplsFlowPutKey->pad[3] = 0;\n- destKey->l2.keyLen += OVS_MPLS_KEY_SIZE;\n- }\n- break;\n- }\n- }\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsTunnelAttrToGeneveOptions --\n- * Converts OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS attribute to tunKey->tunOpts.\n- *----------------------------------------------------------------------------\n- */\n-static __inline NTSTATUS\n-OvsTunnelAttrToGeneveOptions(PNL_ATTR attr,\n- OvsIPTunnelKey *tunKey)\n-{\n- UINT32 optLen = NlAttrGetSize(attr);\n- GeneveOptionHdr *option;\n- BOOLEAN isCritical = FALSE;\n- if (optLen > TUN_OPT_MAX_LEN) {\n- OVS_LOG_ERROR(\"Geneve option length err (len %d, max %Iu).\",\n- optLen, TUN_OPT_MAX_LEN);\n- return STATUS_INFO_LENGTH_MISMATCH;\n- } else if (optLen % 4 != 0) {\n- OVS_LOG_ERROR(\"Geneve opt len %d is not a multiple of 4.\", optLen);\n- return STATUS_INFO_LENGTH_MISMATCH;\n- }\n- tunKey->tunOptLen = (UINT8)optLen;\n- option = (GeneveOptionHdr *)NlAttrData(attr);\n- while (optLen > 0) {\n- UINT32 len;\n- if (optLen < sizeof(*option)) {\n- return STATUS_INFO_LENGTH_MISMATCH;\n- }\n- len = sizeof(*option) + option->length * 4;\n- if (len > optLen) {\n- return STATUS_INFO_LENGTH_MISMATCH;\n- }\n- if (option->type & GENEVE_CRIT_OPT_TYPE) {\n- isCritical = TRUE;\n- }\n- option = (GeneveOptionHdr *)((UINT8 *)option + len);\n- optLen -= len;\n- }\n- memcpy(IPTunnelKeyGetOptions(tunKey), NlAttrData(attr), tunKey->tunOptLen);\n- if (isCritical) {\n- tunKey->flags |= OVS_TNL_F_CRT_OPT;\n- }\n- return STATUS_SUCCESS;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsTunnelAttrToIPTunnelKey --\n- * Converts OVS_KEY_ATTR_TUNNEL attribute to tunKey.\n- *----------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsTunnelAttrToIPTunnelKey(PNL_ATTR attr,\n- OvsIPTunnelKey *tunKey)\n-{\n- PNL_ATTR a;\n- INT rem;\n- INT hasOpt = 0;\n- NTSTATUS status;\n-\n- memset(tunKey, 0, OVS_WIN_IP_TUNNEL_KEY_SIZE);\n- ASSERT(NlAttrType(attr) == OVS_KEY_ATTR_TUNNEL);\n-\n- NL_ATTR_FOR_EACH_UNSAFE(a, rem, NlAttrData(attr),\n- NlAttrGetSize(attr)) {\n- switch (NlAttrType(a)) {\n- case OVS_TUNNEL_KEY_ATTR_ID:\n- tunKey->tunnelId = NlAttrGetBe64(a);\n- tunKey->flags |= OVS_TNL_F_KEY;\n- break;\n- case OVS_TUNNEL_KEY_ATTR_IPV4_SRC:\n- tunKey->src.si_family = AF_INET;\n- tunKey->src.Ipv4.sin_addr.s_addr = NlAttrGetBe32(a);\n- break;\n- case OVS_TUNNEL_KEY_ATTR_IPV4_DST:\n- tunKey->dst.si_family = AF_INET;\n- tunKey->dst.Ipv4.sin_addr.s_addr = NlAttrGetBe32(a);\n- break;\n- case OVS_TUNNEL_KEY_ATTR_IPV6_SRC:\n- tunKey->src.si_family = AF_INET6;\n- RtlCopyMemory(&tunKey->src.Ipv6.sin6_addr,\n- NlAttrGetUnspec(a,\n- sizeof(tunKey->src.Ipv6.sin6_addr)),\n- sizeof(tunKey->src.Ipv6.sin6_addr));\n- break;\n- case OVS_TUNNEL_KEY_ATTR_IPV6_DST:\n- tunKey->dst.si_family = AF_INET6;\n- RtlCopyMemory(&tunKey->dst.Ipv6.sin6_addr,\n- NlAttrGetUnspec(a,\n- sizeof(tunKey->dst.Ipv6.sin6_addr)),\n- sizeof(tunKey->dst.Ipv6.sin6_addr));\n- break;\n- case OVS_TUNNEL_KEY_ATTR_TOS:\n- tunKey->tos = NlAttrGetU8(a);\n- break;\n- case OVS_TUNNEL_KEY_ATTR_TTL:\n- tunKey->ttl = NlAttrGetU8(a);\n- break;\n- case OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT:\n- tunKey->flags |= OVS_TNL_F_DONT_FRAGMENT;\n- break;\n- case OVS_TUNNEL_KEY_ATTR_CSUM:\n- tunKey->flags |= OVS_TNL_F_CSUM;\n- break;\n- case OVS_TUNNEL_KEY_ATTR_OAM:\n- tunKey->flags |= OVS_TNL_F_OAM;\n- break;\n- case OVS_TUNNEL_KEY_ATTR_TP_DST:\n- tunKey->dst_port = NlAttrGetBe16(a);\n- break;\n- case OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS:\n- if (hasOpt) {\n- /* Duplicate options attribute is not allowed. */\n- return NDIS_STATUS_FAILURE;\n- }\n- status = OvsTunnelAttrToGeneveOptions(a, tunKey);\n- if (!SUCCEEDED(status)) {\n- return status;\n- }\n- tunKey->flags |= OVS_TNL_F_GENEVE_OPT;\n- hasOpt = 1;\n- break;\n- default:\n- // XXX: Support OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS\n- return STATUS_INVALID_PARAMETER;\n- }\n- }\n-\n- return STATUS_SUCCESS;\n-}\n-\n-\n-/*\n- *----------------------------------------------------------------------------\n- * MapTunAttrToFlowPut --\n- * Converts FLOW_TUNNEL_KEY attribute to OvsFlowKey->tunKey.\n- *----------------------------------------------------------------------------\n- */\n-VOID\n-MapTunAttrToFlowPut(PNL_ATTR *keyAttrs,\n- PNL_ATTR *tunAttrs,\n- OvsFlowKey *destKey)\n-{\n- memset(&destKey->tunKey, 0, OVS_WIN_IP_TUNNEL_KEY_SIZE);\n- if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {\n- /* XXX: This blocks performs same functionality as\n- OvsTunnelAttrToIPv4TunnelKey. Consider refactoring the code.*/\n- if (tunAttrs[OVS_TUNNEL_KEY_ATTR_ID]) {\n- destKey->tunKey.tunnelId =\n- NlAttrGetU64(tunAttrs[OVS_TUNNEL_KEY_ATTR_ID]);\n- destKey->tunKey.flags |= OVS_TNL_F_KEY;\n- }\n-\n- if (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_DST]) {\n- destKey->tunKey.dst.si_family = AF_INET;\n- destKey->tunKey.dst.Ipv4.sin_addr.s_addr =\n- NlAttrGetU32(tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_DST]);\n- }\n-\n- if (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_SRC]) {\n- destKey->tunKey.src.si_family = AF_INET;\n- destKey->tunKey.src.Ipv4.sin_addr.s_addr =\n- NlAttrGetU32(tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_SRC]);\n- }\n-\n- if (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV6_DST]) {\n- destKey->tunKey.dst.si_family = AF_INET6;\n- RtlCopyMemory(&destKey->tunKey.dst.Ipv6.sin6_addr,\n- NlAttrGetUnspec(\n- tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV6_DST],\n- sizeof(destKey->tunKey.dst.Ipv6.sin6_addr)),\n- sizeof(destKey->tunKey.dst.Ipv6.sin6_addr));\n- }\n-\n- if (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV6_SRC]) {\n- destKey->tunKey.src.si_family = AF_INET6;\n- RtlCopyMemory(&destKey->tunKey.src.Ipv6.sin6_addr,\n- NlAttrGetUnspec(\n- tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV6_SRC],\n- sizeof(destKey->tunKey.src.Ipv6.sin6_addr)),\n- sizeof(destKey->tunKey.src.Ipv6.sin6_addr));\n- }\n-\n- if (tunAttrs[OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT]) {\n- destKey->tunKey.flags |= OVS_TNL_F_DONT_FRAGMENT;\n- }\n-\n- if (tunAttrs[OVS_TUNNEL_KEY_ATTR_CSUM]) {\n- destKey->tunKey.flags |= OVS_TNL_F_CSUM;\n- }\n-\n- if (tunAttrs[OVS_TUNNEL_KEY_ATTR_TOS]) {\n- destKey->tunKey.tos =\n- NlAttrGetU8(tunAttrs[OVS_TUNNEL_KEY_ATTR_TOS]);\n- }\n-\n- if (tunAttrs[OVS_TUNNEL_KEY_ATTR_TTL]) {\n- destKey->tunKey.ttl =\n- NlAttrGetU8(tunAttrs[OVS_TUNNEL_KEY_ATTR_TTL]);\n- }\n-\n- if (tunAttrs[OVS_TUNNEL_KEY_ATTR_OAM]) {\n- destKey->tunKey.flags |= OVS_TNL_F_OAM;\n- }\n-\n- if (tunAttrs[OVS_TUNNEL_KEY_ATTR_TP_DST]) {\n- destKey->tunKey.dst_port =\n- NlAttrGetU16(tunAttrs[OVS_TUNNEL_KEY_ATTR_TP_DST]);\n- }\n-\n- if (tunAttrs[OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS]) {\n- NTSTATUS status = OvsTunnelAttrToGeneveOptions(\n- tunAttrs[OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS],\n- &destKey->tunKey);\n- if (SUCCEEDED(status)) {\n- destKey->tunKey.flags |= OVS_TNL_F_GENEVE_OPT;\n- }\n- }\n- destKey->l2.offset = OvsGetFlowIPL2Offset(&(destKey->tunKey));\n- } else {\n- destKey->l2.offset = OvsGetFlowIPL2Offset(NULL);\n- }\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsDeleteFlowTable --\n- * Results:\n- * NDIS_STATUS_SUCCESS always.\n- *----------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsDeleteFlowTable(OVS_DATAPATH *datapath)\n-{\n- if (datapath == NULL || datapath->flowTable == NULL) {\n- return NDIS_STATUS_SUCCESS;\n- }\n-\n- DeleteAllFlows(datapath);\n- OvsFreeMemoryWithTag(datapath->flowTable, OVS_FLOW_POOL_TAG);\n- datapath->flowTable = NULL;\n-\n- if (datapath->lock == NULL) {\n- return NDIS_STATUS_SUCCESS;\n- }\n-\n- NdisFreeRWLock(datapath->lock);\n-\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsAllocateFlowTable --\n- * Results:\n- * NDIS_STATUS_SUCCESS on success.\n- * NDIS_STATUS_RESOURCES if memory couldn't be allocated\n- *----------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsAllocateFlowTable(OVS_DATAPATH *datapath,\n- POVS_SWITCH_CONTEXT switchContext)\n-{\n- PLIST_ENTRY bucket;\n- int i;\n-\n- datapath->flowTable = OvsAllocateMemoryWithTag(\n- OVS_FLOW_TABLE_SIZE * sizeof(LIST_ENTRY), OVS_FLOW_POOL_TAG);\n- if (!datapath->flowTable) {\n- return NDIS_STATUS_RESOURCES;\n- }\n- for (i = 0; i < OVS_FLOW_TABLE_SIZE; i++) {\n- bucket = &(datapath->flowTable[i]);\n- InitializeListHead(bucket);\n- }\n- datapath->lock = NdisAllocateRWLock(switchContext->NdisFilterHandle);\n-\n- if (!datapath->lock) {\n- return NDIS_STATUS_RESOURCES;\n- }\n-\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-\n-/*\n- *----------------------------------------------------------------------------\n- * GetStartAddrNBL --\n- * Get the virtual address of the frame.\n- *\n- * Results:\n- * Virtual address of the frame.\n- *----------------------------------------------------------------------------\n- */\n-static __inline VOID *\n-GetStartAddrNBL(const NET_BUFFER_LIST *_pNB)\n-{\n- PMDL curMdl;\n- PUINT8 curBuffer;\n- PEthHdr curHeader;\n-\n- ASSERT(_pNB);\n-\n- // Ethernet Header is a guaranteed safe access.\n- curMdl = (NET_BUFFER_LIST_FIRST_NB(_pNB))->CurrentMdl;\n- curBuffer = OvsGetMdlWithLowPriority(curMdl);\n- if (!curBuffer) {\n- return NULL;\n- }\n-\n- curHeader = (PEthHdr)\n- (curBuffer + (NET_BUFFER_LIST_FIRST_NB(_pNB))->CurrentMdlOffset);\n-\n- return (VOID *) curHeader;\n-}\n-\n-VOID\n-OvsFlowUsed(OvsFlow *flow,\n- const NET_BUFFER_LIST *packet,\n- const POVS_PACKET_HDR_INFO layers)\n-{\n- LARGE_INTEGER tickCount;\n-\n- KeQueryTickCount(&tickCount);\n- flow->used = tickCount.QuadPart;\n- flow->packetCount++;\n- flow->byteCount += OvsPacketLenNBL(packet);\n- flow->tcpFlags |= OvsGetTcpFlags(packet, &flow->key, layers);\n-}\n-\n-\n-VOID\n-DeleteAllFlows(OVS_DATAPATH *datapath)\n-{\n- INT i;\n- PLIST_ENTRY bucket;\n-\n- for (i = 0; i < OVS_FLOW_TABLE_SIZE; i++) {\n- PLIST_ENTRY next;\n- bucket = &(datapath->flowTable[i]);\n- while (!IsListEmpty(bucket)) {\n- OvsFlow *flow;\n- next = bucket->Flink;\n- flow = CONTAINING_RECORD(next, OvsFlow, ListEntry);\n- RemoveFlow(datapath, &flow);\n- }\n- }\n-}\n-\n-NDIS_STATUS\n-OvsGetFlowMetadata(OvsFlowKey *key,\n- PNL_ATTR *keyAttrs)\n-{\n- NDIS_STATUS status = NDIS_STATUS_SUCCESS;\n-\n- if (keyAttrs[OVS_KEY_ATTR_RECIRC_ID]) {\n- key->recircId = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_RECIRC_ID]);\n- }\n-\n- if (keyAttrs[OVS_KEY_ATTR_DP_HASH]) {\n- key->dpHash = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_DP_HASH]);\n- }\n-\n- if (keyAttrs[OVS_KEY_ATTR_CT_STATE]) {\n- key->ct.state = (NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_CT_STATE]));\n- }\n-\n- if (keyAttrs[OVS_KEY_ATTR_CT_ZONE]) {\n- key->ct.zone = (NlAttrGetU16(keyAttrs[OVS_KEY_ATTR_CT_ZONE]));\n- }\n-\n- if (keyAttrs[OVS_KEY_ATTR_CT_MARK]) {\n- key->ct.mark = (NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_CT_MARK]));\n- }\n-\n- if (keyAttrs[OVS_KEY_ATTR_CT_LABELS]) {\n- const struct ovs_key_ct_labels *ct_labels;\n- ct_labels = NlAttrGet(keyAttrs[OVS_KEY_ATTR_CT_LABELS]);\n- NdisMoveMemory(&key->ct.labels, ct_labels,\n- sizeof(struct ovs_key_ct_labels));\n- }\n-\n- if (keyAttrs[OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4]) {\n- const struct ovs_key_ct_tuple_ipv4 *tuple_ipv4;\n- tuple_ipv4 = NlAttrGet(keyAttrs[OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4]);\n- NdisMoveMemory(&key->ct.tuple_ipv4, tuple_ipv4,\n- sizeof(struct ovs_key_ct_tuple_ipv4));\n- }\n-\n- if (keyAttrs[OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6]) {\n- const struct ovs_key_ct_tuple_ipv6 *tuple_ipv6;\n- tuple_ipv6 = NlAttrGet(keyAttrs[OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6]);\n- NdisMoveMemory(&key->ct.tuple_ipv6, tuple_ipv6,\n- sizeof(struct ovs_key_ct_tuple_ipv6));\n- }\n-\n- return status;\n-}\n-\n-UINT16\n-OvsGetFlowIPL2Offset(const OvsIPTunnelKey *tunKey)\n-{\n- if (tunKey != NULL) {\n- // Align with int64 boundary\n- if (tunKey->tunOptLen == 0) {\n- return (TUN_OPT_MAX_LEN + 1) / 8 * 8;\n- }\n- return IPTunnelKeyGetOptionsOffset(tunKey) / 8 * 8;\n- } else {\n- return OVS_WIN_IP_TUNNEL_KEY_SIZE;\n- }\n-}\n-\n-/*\n-*----------------------------------------------------------------------------\n-* Initializes 'layers' members from 'packet'\n-*\n-* Initializes 'layers' header pointers as follows:\n-*\n-* - layers->l2 to the start of the Ethernet header.\n-*\n-* - layers->l3 to just past the Ethernet header, or just past the\n-* vlan_header if one is present, to the first byte of the payload of the\n-* Ethernet frame.\n-*\n-* - layers->l4 to just past the IPv4 header, if one is present and has a\n-* correct length, and otherwise NULL.\n-*\n-* - layers->l7 to just past the TCP, UDP, SCTP or ICMP header, if one is\n-* present and has a correct length, and otherwise NULL.\n-*\n-* - layers->isIPv4/isIPv6/isTcp/isUdp/isSctp based on the packet type\n-*\n-* Returns NDIS_STATUS_SUCCESS normally.\n-* Fails only if packet data cannot be accessed.\n-* (e.g. if OvsParseIPv6() returns an error).\n-*----------------------------------------------------------------------------\n-*/\n-NDIS_STATUS\n-OvsExtractLayers(const NET_BUFFER_LIST *packet,\n- POVS_PACKET_HDR_INFO layers)\n-{\n- struct Eth_Header *eth;\n- UINT8 offset = 0;\n- PVOID vlanTagValue;\n- ovs_be16 dlType;\n-\n- layers->value = 0;\n-\n- /* Link layer. */\n- eth = (Eth_Header *)GetStartAddrNBL((NET_BUFFER_LIST *)packet);\n-\n- /*\n- * vlan_tci.\n- */\n- vlanTagValue = NET_BUFFER_LIST_INFO(packet, Ieee8021QNetBufferListInfo);\n- if (!vlanTagValue) {\n- if (eth->dix.typeNBO == ETH_TYPE_802_1PQ_NBO) {\n- offset = sizeof(Eth_802_1pq_Tag);\n- }\n-\n- /*\n- * XXX Please note after this point, src mac and dst mac should\n- * not be accessed through eth\n- */\n- eth = (Eth_Header *)((UINT8 *)eth + offset);\n- }\n-\n- /*\n- * dl_type.\n- *\n- * XXX assume that at least the first\n- * 12 bytes of received packets are mapped. This code has the stronger\n- * assumption that at least the first 22 bytes of 'packet' is mapped (if my\n- * arithmetic is right).\n- */\n- if (ETH_TYPENOT8023(eth->dix.typeNBO)) {\n- dlType = eth->dix.typeNBO;\n- layers->l3Offset = ETH_HEADER_LEN_DIX + offset;\n- } else if (OvsPacketLenNBL(packet) >= ETH_HEADER_LEN_802_3 &&\n- eth->e802_3.llc.dsap == 0xaa &&\n- eth->e802_3.llc.ssap == 0xaa &&\n- eth->e802_3.llc.control == ETH_LLC_CONTROL_UFRAME &&\n- eth->e802_3.snap.snapOrg[0] == 0x00 &&\n- eth->e802_3.snap.snapOrg[1] == 0x00 &&\n- eth->e802_3.snap.snapOrg[2] == 0x00) {\n- dlType = eth->e802_3.snap.snapType.typeNBO;\n- layers->l3Offset = ETH_HEADER_LEN_802_3 + offset;\n- } else {\n- dlType = htons(OVSWIN_DL_TYPE_NONE);\n- layers->l3Offset = ETH_HEADER_LEN_DIX + offset;\n- }\n-\n- /* Network layer. */\n- if (dlType == htons(ETH_TYPE_IPV4)) {\n- struct IPHdr ip_storage;\n- const struct IPHdr *nh;\n-\n- layers->isIPv4 = 1;\n- nh = OvsGetIp(packet, layers->l3Offset, &ip_storage);\n- if (nh) {\n- layers->l4Offset = layers->l3Offset + nh->ihl * 4;\n-\n- if (!(nh->frag_off & htons(IP_OFFSET))) {\n- if (nh->protocol == SOCKET_IPPROTO_TCP) {\n- OvsParseTcp(packet, NULL, layers);\n- } else if (nh->protocol == SOCKET_IPPROTO_UDP) {\n- OvsParseUdp(packet, NULL, layers);\n- } else if (nh->protocol == SOCKET_IPPROTO_SCTP) {\n- OvsParseSctp(packet, NULL, layers);\n- } else if (nh->protocol == SOCKET_IPPROTO_ICMP) {\n- ICMPHdr icmpStorage;\n- const ICMPHdr *icmp;\n-\n- icmp = OvsGetIcmp(packet, layers->l4Offset, &icmpStorage);\n- if (icmp) {\n- layers->l7Offset = layers->l4Offset + sizeof *icmp;\n- }\n- layers->isIcmp = 1;\n- }\n- }\n- } else {\n- /* Invalid network header */\n- return NDIS_STATUS_INVALID_PACKET;\n- }\n- } else if (dlType == htons(ETH_TYPE_IPV6)) {\n- NDIS_STATUS status;\n- Ipv6Key ipv6Key;\n-\n- status = OvsParseIPv6(packet, &ipv6Key, layers);\n- if (status != NDIS_STATUS_SUCCESS) {\n- return status;\n- }\n- layers->isIPv6 = 1;\n-\n- if (ipv6Key.nwProto == SOCKET_IPPROTO_TCP) {\n- OvsParseTcp(packet, &(ipv6Key.l4), layers);\n- } else if (ipv6Key.nwProto == SOCKET_IPPROTO_UDP) {\n- OvsParseUdp(packet, &(ipv6Key.l4), layers);\n- } else if (ipv6Key.nwProto == SOCKET_IPPROTO_SCTP) {\n- OvsParseSctp(packet, &ipv6Key.l4, layers);\n- } else if (ipv6Key.nwProto == SOCKET_IPPROTO_ICMPV6) {\n- Icmp6Key icmp6Key;\n- OvsParseIcmpV6(packet, NULL, &icmp6Key, layers);\n- }\n- } else if (OvsEthertypeIsMpls(dlType)) {\n- MPLSHdr mplsStorage;\n- const MPLSHdr *mpls;\n-\n- /*\n- * In the presence of an MPLS label stack the end of the L2\n- * header and the beginning of the L3 header differ.\n- *\n- * A network packet may contain multiple MPLS labels, but we\n- * are only interested in the topmost label stack entry.\n- *\n- * Advance network header to the beginning of the L3 header.\n- * layers->l3Offset corresponds to the end of the L2 header.\n- */\n- for (UINT32 i = 0; i < FLOW_MAX_MPLS_LABELS; i++) {\n- mpls = OvsGetMpls(packet, layers->l3Offset, &mplsStorage);\n- if (!mpls) {\n- break;\n- }\n-\n- layers->l3Offset += MPLS_HLEN;\n- layers->l4Offset += MPLS_HLEN;\n-\n- if (mpls->lse & htonl(MPLS_BOS_MASK)) {\n- /*\n- * Bottom of Stack bit is set, which means there are no\n- * remaining MPLS labels in the packet.\n- */\n- break;\n- }\n- }\n- }\n-\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-/*\n-*----------------------------------------------------------------------------\n-* Initializes 'flow' members from 'packet', 'skb_priority', 'tun_id', and\n-* 'ofp_in_port'.\n-*\n-* Initializes 'packet' header pointers as follows:\n-*\n-* - packet->l2 to the start of the Ethernet header.\n-*\n-* - packet->l3 to just past the Ethernet header, or just past the\n-* vlan_header if one is present, to the first byte of the payload of the\n-* Ethernet frame.\n-*\n-* - packet->l4 to just past the IPv4 header, if one is present and has a\n-* correct length, and otherwise NULL.\n-*\n-* - packet->l7 to just past the TCP, UDP, SCTP or ICMP header, if one is\n-* present and has a correct length, and otherwise NULL.\n-*\n-* Returns NDIS_STATUS_SUCCESS normally.\n-* Fails only if packet data cannot be accessed.\n-* (e.g. if Pkt_CopyBytesOut() returns an error).\n-*----------------------------------------------------------------------------\n-*/\n-NDIS_STATUS\n-OvsExtractFlow(const NET_BUFFER_LIST *packet,\n- UINT32 inPort,\n- OvsFlowKey *flow,\n- POVS_PACKET_HDR_INFO layers,\n- OvsIPTunnelKey *tunKey)\n-{\n- struct Eth_Header *eth;\n- UINT8 offset = 0;\n- PVOID vlanTagValue;\n-\n- layers->value = 0;\n-\n- if (tunKey) {\n- ASSERT(!OvsIphIsZero(&(tunKey->dst)));\n- UINT8 optOffset = IPTunnelKeyGetOptionsOffset(tunKey);\n- RtlMoveMemory(((UINT8 *)&flow->tunKey) + optOffset,\n- ((UINT8 *)tunKey) + optOffset,\n- IPTunnelKeyGetRealSize(tunKey));\n- } else {\n- RtlZeroMemory(&flow->tunKey.dst,\n- sizeof(flow->tunKey.dst));\n- }\n- flow->l2.offset = OvsGetFlowIPL2Offset(tunKey);\n- flow->l2.inPort = inPort;\n-\n- if (OvsPacketLenNBL(packet) < ETH_HEADER_LEN_DIX) {\n- flow->l2.keyLen = OVS_WIN_IP_TUNNEL_KEY_SIZE + 8 - flow->l2.offset;\n- return NDIS_STATUS_SUCCESS;\n- }\n-\n- /* Link layer. */\n- eth = (Eth_Header *)GetStartAddrNBL((NET_BUFFER_LIST *)packet);\n- RtlCopyMemory(flow->l2.dlSrc, eth->src, ETH_ADDR_LENGTH);\n- RtlCopyMemory(flow->l2.dlDst, eth->dst, ETH_ADDR_LENGTH);\n-\n- /*\n- * vlan_tci.\n- */\n- vlanTagValue = NET_BUFFER_LIST_INFO(packet, Ieee8021QNetBufferListInfo);\n- if (vlanTagValue) {\n- PNDIS_NET_BUFFER_LIST_8021Q_INFO vlanTag =\n- (PNDIS_NET_BUFFER_LIST_8021Q_INFO)(PVOID *)&vlanTagValue;\n- flow->l2.vlanKey.vlanTci = htons(vlanTag->TagHeader.VlanId | OVSWIN_VLAN_CFI |\n- (vlanTag->TagHeader.UserPriority << 13));\n- flow->l2.vlanKey.vlanTpid = htons(ETH_TYPE_802_1PQ);\n- } else {\n- if (eth->dix.typeNBO == ETH_TYPE_802_1PQ_NBO) {\n- Eth_802_1pq_Tag *tag= (Eth_802_1pq_Tag *)ð->dix.typeNBO;\n- flow->l2.vlanKey.vlanTci = htons(((UINT16)tag->priority << 13) |\n- OVSWIN_VLAN_CFI | ((UINT16)tag->vidHi << 8) | tag->vidLo);\n- flow->l2.vlanKey.vlanTpid = htons(ETH_TYPE_802_1PQ);\n- offset = sizeof (Eth_802_1pq_Tag);\n- } else {\n- /* Initialize vlan key to 0 for non vlan packets. */\n- flow->l2.vlanKey.vlanTci = 0;\n- flow->l2.vlanKey.vlanTpid = 0;\n- }\n- /*\n- * XXX Please note after this point, src mac and dst mac should\n- * not be accessed through eth\n- */\n- eth = (Eth_Header *)((UINT8 *)eth + offset);\n- }\n-\n- /*\n- * dl_type.\n- *\n- * XXX assume that at least the first\n- * 12 bytes of received packets are mapped. This code has the stronger\n- * assumption that at least the first 22 bytes of 'packet' is mapped (if my\n- * arithmetic is right).\n- */\n- if (ETH_TYPENOT8023(eth->dix.typeNBO)) {\n- flow->l2.dlType = eth->dix.typeNBO;\n- layers->l3Offset = ETH_HEADER_LEN_DIX + offset;\n- } else if (OvsPacketLenNBL(packet) >= ETH_HEADER_LEN_802_3 &&\n- eth->e802_3.llc.dsap == 0xaa &&\n- eth->e802_3.llc.ssap == 0xaa &&\n- eth->e802_3.llc.control == ETH_LLC_CONTROL_UFRAME &&\n- eth->e802_3.snap.snapOrg[0] == 0x00 &&\n- eth->e802_3.snap.snapOrg[1] == 0x00 &&\n- eth->e802_3.snap.snapOrg[2] == 0x00) {\n- flow->l2.dlType = eth->e802_3.snap.snapType.typeNBO;\n- layers->l3Offset = ETH_HEADER_LEN_802_3 + offset;\n- } else {\n- flow->l2.dlType = htons(OVSWIN_DL_TYPE_NONE);\n- layers->l3Offset = ETH_HEADER_LEN_DIX + offset;\n- }\n-\n- flow->l2.keyLen = OVS_WIN_IP_TUNNEL_KEY_SIZE + OVS_L2_KEY_SIZE\n- - flow->l2.offset;\n- /* Network layer. */\n- if (flow->l2.dlType == htons(ETH_TYPE_IPV4)) {\n- struct IPHdr ip_storage;\n- const struct IPHdr *nh;\n- IpKey *ipKey = &flow->ipKey;\n-\n- flow->l2.keyLen += OVS_IP_KEY_SIZE;\n- layers->isIPv4 = 1;\n- nh = OvsGetIp(packet, layers->l3Offset, &ip_storage);\n- if (nh) {\n- layers->l4Offset = layers->l3Offset + nh->ihl * 4;\n-\n- ipKey->nwSrc = nh->saddr;\n- ipKey->nwDst = nh->daddr;\n- ipKey->nwProto = nh->protocol;\n-\n- ipKey->nwTos = nh->tos;\n- if (nh->frag_off & htons(IP_MF | IP_OFFSET)) {\n- ipKey->nwFrag = OVS_FRAG_TYPE_FIRST;\n- if (nh->frag_off & htons(IP_OFFSET)) {\n- ipKey->nwFrag = OVS_FRAG_TYPE_LATER;\n- }\n- } else {\n- ipKey->nwFrag = OVS_FRAG_TYPE_NONE;\n- }\n-\n- ipKey->nwTtl = nh->ttl;\n- ipKey->l4.tpSrc = 0;\n- ipKey->l4.tpDst = 0;\n-\n- if (!(nh->frag_off & htons(IP_OFFSET))) {\n- if (ipKey->nwProto == SOCKET_IPPROTO_TCP) {\n- OvsParseTcp(packet, &ipKey->l4, layers);\n- } else if (ipKey->nwProto == SOCKET_IPPROTO_UDP) {\n- OvsParseUdp(packet, &ipKey->l4, layers);\n- } else if (ipKey->nwProto == SOCKET_IPPROTO_SCTP) {\n- OvsParseSctp(packet, &ipKey->l4, layers);\n- } else if (ipKey->nwProto == SOCKET_IPPROTO_ICMP) {\n- ICMPHdr icmpStorage;\n- const ICMPHdr *icmp;\n-\n- icmp = OvsGetIcmp(packet, layers->l4Offset, &icmpStorage);\n- if (icmp) {\n- ipKey->l4.tpSrc = htons(icmp->type);\n- ipKey->l4.tpDst = htons(icmp->code);\n- layers->l7Offset = layers->l4Offset + sizeof *icmp;\n- }\n- }\n- }\n- } else {\n- /* Invalid network header */\n- ((UINT64 *)ipKey)[0] = 0;\n- ((UINT64 *)ipKey)[1] = 0;\n- return NDIS_STATUS_INVALID_PACKET;\n- }\n- } else if (flow->l2.dlType == htons(ETH_TYPE_IPV6)) {\n- NDIS_STATUS status;\n- flow->l2.keyLen += OVS_IPV6_KEY_SIZE;\n- status = OvsParseIPv6(packet, &flow->ipv6Key, layers);\n- if (status != NDIS_STATUS_SUCCESS) {\n- RtlZeroMemory(&flow->ipv6Key, sizeof (Ipv6Key));\n- return status;\n- }\n- layers->isIPv6 = 1;\n- flow->ipv6Key.l4.tpSrc = 0;\n- flow->ipv6Key.l4.tpDst = 0;\n- flow->ipv6Key.pad = 0;\n-\n- if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_TCP) {\n- OvsParseTcp(packet, &(flow->ipv6Key.l4), layers);\n- } else if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_UDP) {\n- OvsParseUdp(packet, &(flow->ipv6Key.l4), layers);\n- } else if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_SCTP) {\n- OvsParseSctp(packet, &flow->ipv6Key.l4, layers);\n- } else if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_ICMPV6) {\n- OvsParseIcmpV6(packet, &flow->ipv6Key, &flow->icmp6Key, layers);\n- flow->l2.keyLen += (OVS_ICMPV6_KEY_SIZE - OVS_IPV6_KEY_SIZE);\n- }\n- } else if (flow->l2.dlType == htons(ETH_TYPE_ARP)) {\n- EtherArp arpStorage;\n- const EtherArp *arp;\n- ArpKey *arpKey = &flow->arpKey;\n- ((UINT64 *)arpKey)[0] = 0;\n- ((UINT64 *)arpKey)[1] = 0;\n- ((UINT64 *)arpKey)[2] = 0;\n- flow->l2.keyLen += OVS_ARP_KEY_SIZE;\n- arp = OvsGetArp(packet, layers->l3Offset, &arpStorage);\n- if (arp && arp->ea_hdr.ar_hrd == htons(1) &&\n- arp->ea_hdr.ar_pro == htons(ETH_TYPE_IPV4) &&\n- arp->ea_hdr.ar_hln == ETH_ADDR_LENGTH &&\n- arp->ea_hdr.ar_pln == 4) {\n- /* We only match on the lower 8 bits of the opcode. */\n- if (ntohs(arp->ea_hdr.ar_op) <= 0xff) {\n- arpKey->nwProto = (UINT8)ntohs(arp->ea_hdr.ar_op);\n- }\n- if (arpKey->nwProto == ARPOP_REQUEST\n- || arpKey->nwProto == ARPOP_REPLY) {\n- RtlCopyMemory(&arpKey->nwSrc, arp->arp_spa, 4);\n- RtlCopyMemory(&arpKey->nwDst, arp->arp_tpa, 4);\n- RtlCopyMemory(arpKey->arpSha, arp->arp_sha, ETH_ADDR_LENGTH);\n- RtlCopyMemory(arpKey->arpTha, arp->arp_tha, ETH_ADDR_LENGTH);\n- }\n- }\n- } else if (OvsEthertypeIsMpls(flow->l2.dlType)) {\n- MPLSHdr mplsStorage;\n- const MPLSHdr *mpls;\n- MplsKey *mplsKey = &flow->mplsKey;\n- ((UINT64 *)mplsKey)[0] = 0;\n- flow->l2.keyLen += OVS_MPLS_KEY_SIZE;\n-\n- /*\n- * In the presence of an MPLS label stack the end of the L2\n- * header and the beginning of the L3 header differ.\n- *\n- * A network packet may contain multiple MPLS labels, but we\n- * are only interested in the topmost label stack entry.\n- *\n- * Advance network header to the beginning of the L3 header.\n- * layers->l3Offset corresponds to the end of the L2 header.\n- */\n- for (UINT32 i = 0; i < FLOW_MAX_MPLS_LABELS; i++) {\n- mpls = OvsGetMpls(packet, layers->l3Offset, &mplsStorage);\n- if (!mpls) {\n- break;\n- }\n-\n- /* Keep only the topmost MPLS label stack entry. */\n- if (i == 0) {\n- mplsKey->lse = mpls->lse;\n- }\n-\n- layers->l3Offset += MPLS_HLEN;\n- layers->l4Offset += MPLS_HLEN;\n-\n- if (mpls->lse & htonl(MPLS_BOS_MASK)) {\n- /*\n- * Bottom of Stack bit is set, which means there are no\n- * remaining MPLS labels in the packet.\n- */\n- break;\n- }\n- }\n- }\n-\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-__inline BOOLEAN\n-FlowMemoryEqual(UINT64 *src, UINT64 *dst, UINT32 size)\n-{\n- UINT32 i;\n- ASSERT((size & 0x7) == 0);\n- ASSERT(((UINT64)src & 0x7) == 0);\n- ASSERT(((UINT64)dst & 0x7) == 0);\n- for (i = 0; i < (size >> 3); i++) {\n- if (src[i] != dst[i]) {\n- return FALSE;\n- }\n- }\n- return TRUE;\n-}\n-\n-__inline BOOLEAN\n-FlowEqual(OvsFlow *srcFlow,\n- const OvsFlowKey *dstKey,\n- UINT8 *dstStart,\n- UINT64 hash,\n- UINT32 offset,\n- UINT16 size)\n-{\n- return (srcFlow->hash == hash &&\n- srcFlow->key.l2.val == dstKey->l2.val &&\n- srcFlow->key.recircId == dstKey->recircId &&\n- srcFlow->key.dpHash == dstKey->dpHash &&\n- srcFlow->key.ct.state == dstKey->ct.state &&\n- srcFlow->key.ct.zone == dstKey->ct.zone &&\n- srcFlow->key.ct.mark == dstKey->ct.mark &&\n- !memcmp(&srcFlow->key.ct.labels, &dstKey->ct.labels,\n- sizeof(struct ovs_key_ct_labels)) &&\n- !memcmp(&srcFlow->key.ct.tuple_ipv4, &dstKey->ct.tuple_ipv4,\n- sizeof(struct ovs_key_ct_tuple_ipv4)) &&\n- !memcmp(&srcFlow->key.ct.tuple_ipv6, &dstKey->ct.tuple_ipv6,\n- sizeof(struct ovs_key_ct_tuple_ipv6)) &&\n- FlowMemoryEqual((UINT64 *)((UINT8 *)&srcFlow->key + offset),\n- (UINT64 *) dstStart,\n- size));\n-}\n-\n-/*\n- * ----------------------------------------------------------------------------\n- * AddFlow --\n- * Add a flow to flow table.\n- *\n- * Results:\n- * NDIS_STATUS_SUCCESS if no same flow in the flow table.\n- * ----------------------------------------------------------------------------\n- */\n-NTSTATUS\n-AddFlow(OVS_DATAPATH *datapath, OvsFlow *flow)\n-{\n- PLIST_ENTRY head;\n-\n- if (OvsLookupFlow(datapath, &flow->key, &flow->hash, TRUE) != NULL) {\n- return STATUS_INVALID_HANDLE;\n- }\n-\n- head = &(datapath->flowTable[HASH_BUCKET(flow->hash)]);\n- /*\n- * We need fence here to make sure flow's nextPtr is updated before\n- * head->nextPtr is updated.\n- */\n- KeMemoryBarrier();\n-\n- //KeAcquireSpinLock(&FilterDeviceExtension->NblQueueLock, &oldIrql);\n- InsertTailList(head, &flow->ListEntry);\n- //KeReleaseSpinLock(&FilterDeviceExtension->NblQueueLock, oldIrql);\n-\n- datapath->nFlows++;\n-\n- return STATUS_SUCCESS;\n-}\n-\n-\n-/* ----------------------------------------------------------------------------\n- * RemoveFlow --\n- * Remove a flow from flow table, and added to wait list\n- * ----------------------------------------------------------------------------\n- */\n-VOID\n-RemoveFlow(OVS_DATAPATH *datapath,\n- OvsFlow **flow)\n-{\n- OvsFlow *f = *flow;\n- *flow = NULL;\n-\n- ASSERT(datapath->nFlows);\n- datapath->nFlows--;\n- // Remove the flow from queue\n- RemoveEntryList(&f->ListEntry);\n- FreeFlow(f);\n-}\n-\n-\n-/*\n- * ----------------------------------------------------------------------------\n- * OvsLookupFlow --\n- *\n- * Find flow from flow table based on flow key.\n- * Caller should either hold portset handle or should\n- * have a flowRef in datapath or Acquired datapath.\n- *\n- * Results:\n- * Flow pointer if lookup successful.\n- * NULL if not exists.\n- * ----------------------------------------------------------------------------\n- */\n-OvsFlow *\n-OvsLookupFlow(OVS_DATAPATH *datapath,\n- const OvsFlowKey *key,\n- UINT64 *hash,\n- BOOLEAN hashValid)\n-{\n- PLIST_ENTRY link, head;\n- UINT16 offset = key->l2.offset;\n- UINT16 size = key->l2.keyLen;\n- UINT8 *start;\n-\n- ASSERT(!OvsIphIsZero(&(key->tunKey.dst)) || offset == sizeof(OvsIPTunnelKey));\n- ASSERT(OvsIphIsZero(&(key->tunKey.dst)) || offset == OvsGetFlowIPL2Offset(&key->tunKey));\n-\n- start = (UINT8 *)key + offset;\n-\n- if (!hashValid) {\n- *hash = OvsJhashBytes(start, size, 0);\n- if (key->recircId) {\n- *hash = OvsJhashWords((UINT32*)hash, 1, key->recircId);\n- }\n- if (key->dpHash) {\n- *hash = OvsJhashWords((UINT32*)hash, 1, key->dpHash);\n- }\n- if (key->ct.state) {\n- *hash = OvsJhashWords((UINT32*)hash, 1, key->ct.state);\n- }\n- if (key->ct.zone) {\n- *hash = OvsJhashWords((UINT32*)hash, 1, key->ct.zone);\n- }\n- if (key->ct.mark) {\n- *hash = OvsJhashWords((UINT32*)hash, 1, key->ct.mark);\n- }\n- if (key->ct.labels.ct_labels) {\n- UINT32 lblHash = OvsJhashBytes(&key->ct.labels,\n- sizeof(struct ovs_key_ct_labels),\n- 0);\n- *hash = OvsJhashWords((UINT32*)hash, 1, lblHash);\n- }\n- if (key->ct.tuple_ipv4.ipv4_proto) {\n- UINT32 tupleHash = OvsJhashBytes(\n- &key->ct.tuple_ipv4,\n- sizeof(struct ovs_key_ct_tuple_ipv4),\n- 0);\n- *hash = OvsJhashWords((UINT32*)hash, 1, tupleHash);\n- }\n-\n- if (key->ct.tuple_ipv6.ipv6_proto) {\n- UINT32 tupleHash = OvsJhashBytes(&key->ct.tuple_ipv6,\n- sizeof(struct ovs_key_ct_tuple_ipv6),\n- 0);\n- *hash = OvsJhashWords((UINT32*)hash, 1, tupleHash);\n- }\n- }\n-\n- head = &datapath->flowTable[HASH_BUCKET(*hash)];\n- link = head->Flink;\n- while (link != head) {\n- OvsFlow *flow = CONTAINING_RECORD(link, OvsFlow, ListEntry);\n-\n- if (FlowEqual(flow, key, start, *hash, offset, size)) {\n- return flow;\n- }\n- link = link->Flink;\n- }\n- return NULL;\n-}\n-\n-\n-/*\n- * ----------------------------------------------------------------------------\n- * OvsHashFlow --\n- * Calculate the hash for the given flow key.\n- * ----------------------------------------------------------------------------\n- */\n-UINT64\n-OvsHashFlow(const OvsFlowKey *key)\n-{\n- UINT16 offset = key->l2.offset;\n- UINT16 size = key->l2.keyLen;\n- UINT8 *start;\n-\n- ASSERT(!OvsIphIsZero(&(key->tunKey.dst)) || offset == sizeof(OvsIPTunnelKey));\n- ASSERT(OvsIphIsZero(&(key->tunKey.dst)) || offset == OvsGetFlowIPL2Offset(&key->tunKey));\n- start = (UINT8 *)key + offset;\n- return OvsJhashBytes(start, size, 0);\n-}\n-\n-\n-/*\n- * ----------------------------------------------------------------------------\n- * FreeFlow --\n- * Free a flow and its actions.\n- * ----------------------------------------------------------------------------\n- */\n-VOID\n-FreeFlow(OvsFlow *flow)\n-{\n- ASSERT(flow);\n- OvsFreeMemoryWithTag(flow, OVS_FLOW_POOL_TAG);\n-}\n-\n-NTSTATUS\n-OvsDoDumpFlows(OvsFlowDumpInput *dumpInput,\n- OvsFlowDumpOutput *dumpOutput,\n- UINT32 *replyLen)\n-{\n- UINT32 dpNo;\n- OVS_DATAPATH *datapath = NULL;\n- OvsFlow *flow;\n- PLIST_ENTRY node, head;\n- UINT32 column = 0;\n- UINT32 rowIndex, columnIndex;\n- LOCK_STATE_EX dpLockState;\n- NTSTATUS status = STATUS_SUCCESS;\n- BOOLEAN findNextNonEmpty = FALSE;\n-\n- dpNo = dumpInput->dpNo;\n- if (gOvsSwitchContext->dpNo != dpNo) {\n- status = STATUS_INVALID_PARAMETER;\n- goto exit;\n- }\n-\n- rowIndex = dumpInput->position[0];\n- if (rowIndex >= OVS_FLOW_TABLE_SIZE) {\n- dumpOutput->n = 0;\n- *replyLen = sizeof(*dumpOutput);\n- goto exit;\n- }\n-\n- columnIndex = dumpInput->position[1];\n-\n- datapath = &gOvsSwitchContext->datapath;\n- ASSERT(datapath);\n- OvsAcquireDatapathRead(datapath, &dpLockState, FALSE);\n-\n- head = &datapath->flowTable[rowIndex];\n- node = head->Flink;\n-\n- while (column < columnIndex) {\n- if (node == head) {\n- break;\n- }\n- node = node->Flink;\n- column++;\n- }\n-\n- if (node == head) {\n- findNextNonEmpty = TRUE;\n- columnIndex = 0;\n- }\n-\n- if (findNextNonEmpty) {\n- while (head == node) {\n- if (++rowIndex >= OVS_FLOW_TABLE_SIZE) {\n- dumpOutput->n = 0;\n- goto dp_unlock;\n- }\n- head = &datapath->flowTable[rowIndex];\n- node = head->Flink;\n- }\n- }\n-\n- ASSERT(node != head);\n- ASSERT(rowIndex < OVS_FLOW_TABLE_SIZE);\n-\n- flow = CONTAINING_RECORD(node, OvsFlow, ListEntry);\n- status = ReportFlowInfo(flow, dumpInput->getFlags, &dumpOutput->flow);\n-\n- if (status == STATUS_BUFFER_TOO_SMALL) {\n- dumpOutput->n = sizeof(OvsFlowDumpOutput) + flow->actionsLen;\n- *replyLen = sizeof(*dumpOutput);\n- } else {\n- dumpOutput->n = 1; //one flow reported.\n- *replyLen = sizeof(*dumpOutput) + dumpOutput->flow.actionsLen;\n- }\n-\n- dumpOutput->position[0] = rowIndex;\n- dumpOutput->position[1] = ++columnIndex;\n-\n-dp_unlock:\n- OvsReleaseDatapath(datapath, &dpLockState);\n-\n-exit:\n- return status;\n-}\n-\n-static NTSTATUS\n-ReportFlowInfo(OvsFlow *flow,\n- UINT32 getFlags,\n- OvsFlowInfo *info)\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n-\n- if (getFlags & FLOW_GET_KEY) {\n- // always copy the tunnel key part\n- RtlCopyMemory(&info->key, &flow->key,\n- flow->key.l2.keyLen + flow->key.l2.offset);\n- }\n-\n- if (getFlags & FLOW_GET_STATS) {\n- OvsFlowStats *stats = &info->stats;\n- stats->packetCount = flow->packetCount;\n- stats->byteCount = flow->byteCount;\n- stats->used = flow->used;\n- stats->tcpFlags = flow->tcpFlags;\n- }\n-\n- if (getFlags & FLOW_GET_ACTIONS) {\n- if (flow->actionsLen == 0) {\n- info->actionsLen = 0;\n- } else {\n- info->actions = flow->actions;\n- info->actionsLen = flow->actionsLen;\n- }\n- }\n-\n- info->key.recircId = flow->key.recircId;\n- info->key.dpHash = flow->key.dpHash;\n- info->key.ct.state = flow->key.ct.state;\n- info->key.ct.zone = flow->key.ct.zone;\n- info->key.ct.mark = flow->key.ct.mark;\n- NdisMoveMemory(&info->key.ct.labels,\n- &flow->key.ct.labels,\n- sizeof(struct ovs_key_ct_labels));\n- NdisMoveMemory(&info->key.ct.tuple_ipv4,\n- &flow->key.ct.tuple_ipv4,\n- sizeof(struct ovs_key_ct_tuple_ipv4));\n- NdisMoveMemory(&info->key.ct.tuple_ipv6,\n- &flow->key.ct.tuple_ipv6,\n- sizeof(struct ovs_key_ct_tuple_ipv6));\n- return status;\n-}\n-\n-NTSTATUS\n-OvsPutFlowIoctl(PVOID inputBuffer,\n- UINT32 inputLength,\n- struct OvsFlowStats *stats)\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n- OVS_DATAPATH *datapath = NULL;\n- ULONG actionsLen;\n- OvsFlowPut *put;\n- UINT32 dpNo;\n- LOCK_STATE_EX dpLockState;\n-\n- if ((inputLength < sizeof(OvsFlowPut)) || (inputBuffer == NULL)) {\n- return STATUS_INFO_LENGTH_MISMATCH;\n- }\n-\n- put = (OvsFlowPut *)inputBuffer;\n- if (put->actionsLen > 0) {\n- actionsLen = put->actionsLen;\n- } else {\n- actionsLen = 0;\n- }\n-\n- dpNo = put->dpNo;\n- if (gOvsSwitchContext->dpNo != dpNo) {\n- status = STATUS_INVALID_PARAMETER;\n- goto exit;\n- }\n-\n- datapath = &gOvsSwitchContext->datapath;\n- ASSERT(datapath);\n- OvsAcquireDatapathWrite(datapath, &dpLockState, FALSE);\n- status = HandleFlowPut(put, datapath, stats);\n- OvsReleaseDatapath(datapath, &dpLockState);\n-\n-exit:\n- return status;\n-}\n-\n-\n-/* Handles flow add, modify as well as delete */\n-static NTSTATUS\n-HandleFlowPut(OvsFlowPut *put,\n- OVS_DATAPATH *datapath,\n- struct OvsFlowStats *stats)\n-{\n- BOOLEAN mayCreate, mayModify, mayDelete;\n- OvsFlow *KernelFlow;\n- UINT64 hash;\n- NTSTATUS status = STATUS_SUCCESS;\n-\n- mayCreate = (put->flags & OVSWIN_FLOW_PUT_CREATE) != 0;\n- mayModify = (put->flags & OVSWIN_FLOW_PUT_MODIFY) != 0;\n- mayDelete = (put->flags & OVSWIN_FLOW_PUT_DELETE) != 0;\n-\n- if ((mayCreate || mayModify) == mayDelete) {\n- return STATUS_INVALID_PARAMETER;\n- }\n-\n- KernelFlow = OvsLookupFlow(datapath, &put->key, &hash, FALSE);\n- if (!KernelFlow) {\n- if (!mayCreate) {\n- return STATUS_INVALID_PARAMETER;\n- }\n-\n- status = OvsPrepareFlow(&KernelFlow, put, hash);\n- if (status != STATUS_SUCCESS) {\n- return STATUS_UNSUCCESSFUL;\n- }\n-\n- status = AddFlow(datapath, KernelFlow);\n- if (status != STATUS_SUCCESS) {\n- FreeFlow(KernelFlow);\n- return STATUS_UNSUCCESSFUL;\n- }\n-\n-#if DBG\n- /* Validate the flow addition */\n- {\n- UINT64 newHash;\n- OvsFlow *flow = OvsLookupFlow(datapath, &put->key, &newHash,\n- FALSE);\n- ASSERT(flow);\n- ASSERT(newHash == hash);\n- if (!flow || newHash != hash) {\n- return STATUS_UNSUCCESSFUL;\n- }\n- }\n-#endif\n- } else {\n- stats->packetCount = KernelFlow->packetCount;\n- stats->byteCount = KernelFlow->byteCount;\n- stats->tcpFlags = KernelFlow->tcpFlags;\n- stats->used = KernelFlow->used;\n-\n- if (mayModify) {\n- OvsFlow *newFlow;\n- status = OvsPrepareFlow(&newFlow, put, hash);\n- if (status != STATUS_SUCCESS) {\n- return STATUS_UNSUCCESSFUL;\n- }\n-\n- if ((put->flags & OVSWIN_FLOW_PUT_CLEAR) == 0) {\n- newFlow->packetCount = KernelFlow->packetCount;\n- newFlow->byteCount = KernelFlow->byteCount;\n- newFlow->tcpFlags = KernelFlow->tcpFlags;\n- newFlow->used = KernelFlow->used;\n- }\n- RemoveFlow(datapath, &KernelFlow);\n- status = AddFlow(datapath, newFlow);\n- ASSERT(status == STATUS_SUCCESS);\n-\n-#if DBG\n- /* Validate the flow addition */\n- {\n- UINT64 newHash;\n- OvsFlow *testflow = OvsLookupFlow(datapath, &put->key,\n- &newHash, FALSE);\n- ASSERT(testflow);\n- ASSERT(newHash == hash);\n- if (!testflow || newHash != hash) {\n- FreeFlow(newFlow);\n- return STATUS_UNSUCCESSFUL;\n- }\n- }\n-#endif\n- } else {\n- if (mayDelete) {\n- if (KernelFlow) {\n- RemoveFlow(datapath, &KernelFlow);\n- }\n- } else {\n- /* Return duplicate if an identical flow already exists. */\n- return STATUS_DUPLICATE_NAME;\n- }\n- }\n- }\n- return STATUS_SUCCESS;\n-}\n-\n-static NTSTATUS\n-OvsPrepareFlow(OvsFlow **flow,\n- const OvsFlowPut *put,\n- UINT64 hash)\n-{\n- OvsFlow *localFlow = *flow;\n- NTSTATUS status = STATUS_SUCCESS;\n-\n- do {\n- *flow = localFlow =\n- OvsAllocateMemoryWithTag(sizeof(OvsFlow) + put->actionsLen,\n- OVS_FLOW_POOL_TAG);\n- if (localFlow == NULL) {\n- status = STATUS_NO_MEMORY;\n- break;\n- }\n-\n- localFlow->key = put->key;\n- localFlow->actionsLen = put->actionsLen;\n- if (put->actionsLen) {\n- NdisMoveMemory((PUCHAR)localFlow->actions, put->actions,\n- put->actionsLen);\n- }\n- localFlow->userActionsLen = 0; // 0 indicate no conversion is made\n- localFlow->used = 0;\n- localFlow->packetCount = 0;\n- localFlow->byteCount = 0;\n- localFlow->tcpFlags = 0;\n- localFlow->hash = hash;\n- } while(FALSE);\n-\n- return status;\n-}\n-\n-NTSTATUS\n-OvsGetFlowIoctl(PVOID inputBuffer,\n- PVOID outputBuffer)\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n- OVS_DATAPATH *datapath = NULL;\n- OvsFlow *flow;\n- UINT32 getFlags, getActionsLen;\n- OvsFlowGetInput *getInput;\n- OvsFlowGetOutput *getOutput;\n- UINT64 hash;\n- UINT32 dpNo;\n- LOCK_STATE_EX dpLockState;\n-\n- getInput = (OvsFlowGetInput *) inputBuffer;\n- getFlags = getInput->getFlags;\n- getActionsLen = getInput->actionsLen;\n-\n- if (outputBuffer == NULL) {\n- return STATUS_INFO_LENGTH_MISMATCH;\n- }\n-\n- dpNo = getInput->dpNo;\n- if (gOvsSwitchContext->dpNo != dpNo) {\n- status = STATUS_INVALID_PARAMETER;\n- goto exit;\n- }\n-\n- datapath = &gOvsSwitchContext->datapath;\n- ASSERT(datapath);\n- OvsAcquireDatapathRead(datapath, &dpLockState, FALSE);\n- flow = OvsLookupFlow(datapath, &getInput->key, &hash, FALSE);\n- if (!flow) {\n- status = STATUS_INVALID_PARAMETER;\n- goto dp_unlock;\n- }\n-\n- getOutput = (OvsFlowGetOutput *)outputBuffer;\n- ReportFlowInfo(flow, getFlags, &getOutput->info);\n-\n-dp_unlock:\n- OvsReleaseDatapath(datapath, &dpLockState);\n-exit:\n- return status;\n-}\n-\n-NTSTATUS\n-OvsFlushFlowIoctl(UINT32 dpNo)\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n- OVS_DATAPATH *datapath = NULL;\n- LOCK_STATE_EX dpLockState;\n-\n- if (gOvsSwitchContext->dpNo != dpNo) {\n- status = STATUS_INVALID_PARAMETER;\n- goto exit;\n- }\n-\n- datapath = &gOvsSwitchContext->datapath;\n- ASSERT(datapath);\n- OvsAcquireDatapathWrite(datapath, &dpLockState, FALSE);\n- DeleteAllFlows(datapath);\n- OvsReleaseDatapath(datapath, &dpLockState);\n-\n-exit:\n- return status;\n-}\n-\n-UINT32\n-OvsFlowKeyAttrSize(void)\n-{\n- return NlAttrTotalSize(4) /* OVS_KEY_ATTR_PRIORITY */\n- + NlAttrTotalSize(0) /* OVS_KEY_ATTR_TUNNEL */\n- + OvsTunKeyAttrSize()\n- + NlAttrTotalSize(4) /* OVS_KEY_ATTR_IN_PORT */\n- + NlAttrTotalSize(4) /* OVS_KEY_ATTR_SKB_MARK */\n- + NlAttrTotalSize(4) /* OVS_KEY_ATTR_DP_HASH */\n- + NlAttrTotalSize(4) /* OVS_KEY_ATTR_RECIRC_ID */\n- + NlAttrTotalSize(4) /* OVS_KEY_ATTR_CT_STATE */\n- + NlAttrTotalSize(2) /* OVS_KEY_ATTR_CT_ZONE */\n- + NlAttrTotalSize(4) /* OVS_KEY_ATTR_CT_MARK */\n- + NlAttrTotalSize(16) /* OVS_KEY_ATTR_CT_LABELS */\n- + NlAttrTotalSize(13) /* OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4 */\n- + NlAttrTotalSize(12) /* OVS_KEY_ATTR_ETHERNET */\n- + NlAttrTotalSize(2) /* OVS_KEY_ATTR_ETHERTYPE */\n- + NlAttrTotalSize(4) /* OVS_KEY_ATTR_VLAN */\n- + NlAttrTotalSize(0) /* OVS_KEY_ATTR_ENCAP */\n- + NlAttrTotalSize(2) /* OVS_KEY_ATTR_ETHERTYPE */\n- + NlAttrTotalSize(40) /* OVS_KEY_ATTR_IPV6 */\n- + NlAttrTotalSize(2) /* OVS_KEY_ATTR_ICMPV6 */\n- + NlAttrTotalSize(28); /* OVS_KEY_ATTR_ND */\n-}\n-\n-UINT32\n-OvsTunKeyAttrSize(void)\n-{\n- /* Whenever adding new OVS_TUNNEL_KEY_ FIELDS, we should consider\n- * updating this function.\n- */\n- return NlAttrTotalSize(8) /* OVS_TUNNEL_KEY_ATTR_ID */\n- + NlAttrTotalSize(4) /* OVS_TUNNEL_KEY_ATTR_IPV4_SRC */\n- + NlAttrTotalSize(4) /* OVS_TUNNEL_KEY_ATTR_IPV4_DST */\n- + NlAttrTotalSize(16) /* OVS_TUNNEL_KEY_ATTR_IPV6_SRC */\n- + NlAttrTotalSize(16) /* OVS_TUNNEL_KEY_ATTR_IPV6_DST */\n- + NlAttrTotalSize(1) /* OVS_TUNNEL_KEY_ATTR_TOS */\n- + NlAttrTotalSize(1) /* OVS_TUNNEL_KEY_ATTR_TTL */\n- + NlAttrTotalSize(0) /* OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT */\n- + NlAttrTotalSize(0) /* OVS_TUNNEL_KEY_ATTR_CSUM */\n- + NlAttrTotalSize(0) /* OVS_TUNNEL_KEY_ATTR_OAM */\n- + NlAttrTotalSize(256) /* OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS */\n- + NlAttrTotalSize(2) /* OVS_TUNNEL_KEY_ATTR_TP_SRC */\n- + NlAttrTotalSize(2); /* OVS_TUNNEL_KEY_ATTR_TP_DST */\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsProbeSupportedFeature --\n- * Verifies if the probed feature is supported.\n- *\n- * Results:\n- * STATUS_SUCCESS if the probed feature is supported.\n- *----------------------------------------------------------------------------\n- */\n-static NTSTATUS\n-OvsProbeSupportedFeature(POVS_MESSAGE msgIn,\n- PNL_ATTR keyAttr)\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n- PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);\n-\n- UINT32 keyAttrOffset = (UINT32)((PCHAR)keyAttr - (PCHAR)nlMsgHdr);\n- UINT32 encapOffset = 0;\n- PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX] = { NULL };\n- PNL_ATTR encapAttrs[__OVS_KEY_ATTR_MAX] = { NULL };\n-\n- /* Get flow keys attributes */\n- if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset, NlAttrLen(keyAttr),\n- nlFlowKeyPolicy, ARRAY_SIZE(nlFlowKeyPolicy),\n- keyAttrs, ARRAY_SIZE(keyAttrs)))\n- != TRUE) {\n- OVS_LOG_ERROR(\"Key Attr Parsing failed for msg: %p\",\n- nlMsgHdr);\n- status = STATUS_INVALID_PARAMETER;\n- goto done;\n- }\n-\n- if (keyAttrs[OVS_KEY_ATTR_ENCAP]) {\n- encapOffset = (UINT32)((PCHAR)(keyAttrs[OVS_KEY_ATTR_ENCAP])\n- - (PCHAR)nlMsgHdr);\n-\n- /* Get tunnel keys attributes */\n- if ((NlAttrParseNested(nlMsgHdr, encapOffset,\n- NlAttrLen(keyAttrs[OVS_KEY_ATTR_ENCAP]),\n- nlFlowKeyPolicy,\n- ARRAY_SIZE(nlFlowKeyPolicy),\n- encapAttrs, ARRAY_SIZE(encapAttrs)))\n- != TRUE) {\n- OVS_LOG_ERROR(\"Encap Key Attr Parsing failed for msg: %p\",\n- nlMsgHdr);\n- status = STATUS_INVALID_PARAMETER;\n- goto done;\n- }\n- }\n-\n- if (keyAttrs[OVS_KEY_ATTR_MPLS] &&\n- keyAttrs[OVS_KEY_ATTR_ETHERTYPE]) {\n- ovs_be16 ethType = NlAttrGetU16(keyAttrs[OVS_KEY_ATTR_ETHERTYPE]);\n-\n- if (OvsEthertypeIsMpls(ethType)) {\n- if (!OvsCountMplsLabels(keyAttrs[OVS_KEY_ATTR_MPLS])) {\n- OVS_LOG_ERROR(\"Maximum supported MPLS labels exceeded.\");\n- status = STATUS_INVALID_MESSAGE;\n- }\n- } else {\n- OVS_LOG_ERROR(\"Wrong ethertype for MPLS attribute.\");\n- status = STATUS_INVALID_PARAMETER;\n- }\n- } else if (keyAttrs[OVS_KEY_ATTR_RECIRC_ID]) {\n- UINT32 recircId = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_RECIRC_ID]);\n-\n- if (!recircId) {\n- OVS_LOG_ERROR(\"Invalid recirculation ID.\");\n- status = STATUS_INVALID_PARAMETER;\n- }\n- } else if (keyAttrs[OVS_KEY_ATTR_CT_STATE]) {\n- UINT32 state = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_CT_STATE]);\n- if (!state) {\n- status = STATUS_INVALID_PARAMETER;\n- OVS_LOG_ERROR(\"Invalid state specified.\");\n- }\n- } else if (keyAttrs[OVS_KEY_ATTR_CT_ZONE]) {\n- UINT16 zone = (NlAttrGetU16(keyAttrs[OVS_KEY_ATTR_CT_ZONE]));\n- if (!zone) {\n- OVS_LOG_ERROR(\"Invalid zone specified.\");\n- status = STATUS_INVALID_PARAMETER;\n- }\n- } else if (keyAttrs[OVS_KEY_ATTR_CT_MARK]) {\n- UINT32 mark = (NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_CT_MARK]));\n- if (!mark) {\n- OVS_LOG_ERROR(\"Invalid ct mark specified.\");\n- status = STATUS_INVALID_PARAMETER;\n- }\n- } else if (keyAttrs[OVS_KEY_ATTR_CT_LABELS]) {\n- const struct ovs_key_ct_labels *ct_labels;\n- ct_labels = NlAttrGet(keyAttrs[OVS_KEY_ATTR_CT_LABELS]);\n- if (!ct_labels->ct_labels) {\n- OVS_LOG_ERROR(\"Invalid ct label specified.\");\n- status = STATUS_INVALID_PARAMETER;\n- }\n- } else if (keyAttrs[OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4]) {\n- const struct ovs_key_ct_tuple_ipv4 *ct_tuple_ipv4;\n- ct_tuple_ipv4 = NlAttrGet(keyAttrs[OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4]);\n- if (!ct_tuple_ipv4) {\n- OVS_LOG_ERROR(\"Invalid ct_tuple_ipv4.\");\n- status = STATUS_INVALID_PARAMETER;\n- }\n- } else if (keyAttrs[OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6]) {\n- const struct ovs_key_ct_tuple_ipv6 *ct_tuple_ipv6;\n- ct_tuple_ipv6 = NlAttrGet(keyAttrs[OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6]);\n- if (!ct_tuple_ipv6) {\n- OVS_LOG_ERROR(\"Invalid ct_tuple_ipv6.\");\n- status = STATUS_INVALID_PARAMETER;\n- }\n- } else {\n- OVS_LOG_ERROR(\"Feature not supported.\");\n- status = STATUS_INVALID_PARAMETER;\n- }\n-\n-done:\n- return status;\n-}\n-\n-#pragma warning( pop )\ndiff --git a/datapath-windows/ovsext/Flow.h b/datapath-windows/ovsext/Flow.h\ndeleted file mode 100644\nindex ea3396f08..000000000\n--- a/datapath-windows/ovsext/Flow.h\n+++ /dev/null\n@@ -1,105 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#ifndef __FLOW_H_\n-#define __FLOW_H_ 1\n-\n-#include \"precomp.h\"\n-#include \"Switch.h\"\n-#include \"User.h\"\n-#include \"NetProto.h\"\n-#include \"Datapath.h\"\n-\n-typedef struct _OvsFlow {\n- LIST_ENTRY ListEntry; // In Datapath's flowTable.\n- OvsFlowKey key;\n- UINT64 hash;\n- UINT32 actionsLen;\n- UINT8 tcpFlags;\n- UINT64 used;\n- UINT64 packetCount;\n- UINT64 byteCount;\n- UINT32 userActionsLen; // used for flow query\n- UINT32 actionBufferLen; // used for flow reuse\n- NL_ATTR actions[1];\n-} OvsFlow;\n-\n-\n-typedef struct _OvsLayers {\n- UINT32 l3Ofs; // IPv4, IPv6, ARP, or other L3 header.\n- UINT32 l4Ofs; // TCP, UDP, SCTP, ICMP, ICMPv6, or other L4 header.\n- UINT32 l7Ofs; // L4 protocol's payload.\n-} OvsLayers;\n-\n-extern UINT64 ovsTimeIncrementPerTick;\n-\n-NDIS_STATUS OvsDeleteFlowTable(OVS_DATAPATH *datapath);\n-NDIS_STATUS OvsAllocateFlowTable(OVS_DATAPATH *datapath,\n- POVS_SWITCH_CONTEXT switchContext);\n-\n-NDIS_STATUS OvsGetFlowMetadata(OvsFlowKey *key,\n- PNL_ATTR *keyAttrs);\n-NDIS_STATUS OvsExtractLayers(const NET_BUFFER_LIST *packet,\n- POVS_PACKET_HDR_INFO layers);\n-NDIS_STATUS OvsExtractFlow(const NET_BUFFER_LIST *pkt, UINT32 inPort,\n- OvsFlowKey *flow, POVS_PACKET_HDR_INFO layers,\n- OvsIPTunnelKey *tunKey);\n-OvsFlow* OvsLookupFlow(OVS_DATAPATH *datapath, const OvsFlowKey *key,\n- UINT64 *hash, BOOLEAN hashValid);\n-OvsFlow* OvsLookupFlowRecirc(OVS_DATAPATH *datapath,\n- const OvsFlowKey *key,\n- UINT64 *hash);\n-UINT64 OvsHashFlow(const OvsFlowKey *key);\n-VOID OvsFlowUsed(OvsFlow *flow, const NET_BUFFER_LIST *pkt,\n- const POVS_PACKET_HDR_INFO layers);\n-\n-NTSTATUS OvsDumpFlowIoctl(PVOID inputBuffer, UINT32 inputLength,\n- PVOID outputBuffer, UINT32 outputLength,\n- UINT32 *replyLen);\n-NTSTATUS OvsPutFlowIoctl(PVOID inputBuffer, UINT32 inputLength,\n- struct OvsFlowStats *stats);\n-NTSTATUS OvsGetFlowIoctl(PVOID inputBuffer, PVOID outputBuffer);\n-NTSTATUS OvsFlushFlowIoctl(UINT32 dpNo);\n-\n-NTSTATUS OvsFlowNlCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen);\n-NTSTATUS OvsFlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen);\n-NTSTATUS MapFlowKeyToNlKey(PNL_BUFFER nlBuf, OvsFlowKey *flowKey,\n- UINT16 keyType, UINT16 tunKeyType);\n-NTSTATUS MapFlowTunKeyToNlKey(PNL_BUFFER nlBuf, OvsIPTunnelKey *tunKey,\n- UINT16 tunKeyType);\n-VOID MapTunAttrToFlowPut(PNL_ATTR *keyAttrs, PNL_ATTR *tunAttrs,\n- OvsFlowKey *destKey);\n-UINT32 OvsFlowKeyAttrSize(void);\n-UINT32 OvsTunKeyAttrSize(void);\n-NTSTATUS\n-OvsTunnelAttrToIPTunnelKey(PNL_ATTR attr, OvsIPTunnelKey *tunKey);\n-\n-UINT16 OvsGetFlowIPL2Offset(const OvsIPTunnelKey *tunKey);\n-\n-/* Flags for tunneling */\n-#define OVS_TNL_F_DONT_FRAGMENT (1 << 0)\n-#define OVS_TNL_F_CSUM (1 << 1)\n-#define OVS_TNL_F_KEY (1 << 2)\n-#define OVS_TNL_F_OAM (1 << 3)\n-#define OVS_TNL_F_CRT_OPT (1 << 4)\n-#define OVS_TNL_F_GENEVE_OPT (1 << 5)\n-#define OVS_TNL_F_VXLAN_OPT (1 << 6)\n-\n-#define OVS_TNL_HAS_OPTIONS (OVS_TNL_F_GENEVE_OPT | OVS_TNL_F_VXLAN_OPT)\n-\n-#endif /* __FLOW_H_ */\ndiff --git a/datapath-windows/ovsext/Geneve.c b/datapath-windows/ovsext/Geneve.c\ndeleted file mode 100644\nindex 793cee36b..000000000\n--- a/datapath-windows/ovsext/Geneve.c\n+++ /dev/null\n@@ -1,440 +0,0 @@\n-/*\n- * Copyright (c) 2016 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#include \"precomp.h\"\n-\n-#include \"Atomic.h\"\n-#include \"Debug.h\"\n-#include \"Flow.h\"\n-#include \"IpHelper.h\"\n-#include \"Jhash.h\"\n-#include \"NetProto.h\"\n-#include \"Offload.h\"\n-#include \"PacketIO.h\"\n-#include \"PacketParser.h\"\n-#include \"Geneve.h\"\n-#include \"Switch.h\"\n-#include \"User.h\"\n-#include \"Util.h\"\n-#include \"Vport.h\"\n-\n-#ifdef OVS_DBG_MOD\n-#undef OVS_DBG_MOD\n-#endif\n-#define OVS_DBG_MOD OVS_DBG_GENEVE\n-\n-\n-NTSTATUS OvsInitGeneveTunnel(POVS_VPORT_ENTRY vport,\n- UINT16 udpDestPort)\n-{\n- POVS_GENEVE_VPORT genevePort;\n-\n- genevePort = (POVS_GENEVE_VPORT)\n- OvsAllocateMemoryWithTag(sizeof(*genevePort), OVS_GENEVE_POOL_TAG);\n- if (!genevePort) {\n- OVS_LOG_ERROR(\"Insufficient memory, can't allocate GENEVE_VPORT\");\n- return STATUS_INSUFFICIENT_RESOURCES;\n- }\n-\n- RtlZeroMemory(genevePort, sizeof(*genevePort));\n- genevePort->dstPort = udpDestPort;\n- vport->priv = (PVOID) genevePort;\n- return STATUS_SUCCESS;\n-}\n-\n-VOID\n-OvsCleanupGeneveTunnel(POVS_VPORT_ENTRY vport)\n-{\n- if (vport->ovsType != OVS_VPORT_TYPE_GENEVE ||\n- vport->priv == NULL) {\n- return;\n- }\n-\n- OvsFreeMemoryWithTag(vport->priv, OVS_GENEVE_POOL_TAG);\n- vport->priv = NULL;\n-}\n-\n-NDIS_STATUS OvsEncapGeneve(POVS_VPORT_ENTRY vport,\n- PNET_BUFFER_LIST curNbl,\n- OvsIPTunnelKey* tunKey,\n- POVS_SWITCH_CONTEXT switchContext,\n- POVS_PACKET_HDR_INFO layers,\n- PNET_BUFFER_LIST *newNbl,\n- POVS_FWD_INFO switchFwdInfo)\n-{\n- NTSTATUS status;\n- OVS_FWD_INFO fwdInfo;\n- PNET_BUFFER curNb;\n- PMDL curMdl;\n- PUINT8 bufferStart;\n- EthHdr* ethHdr;\n- IPHdr* ipHdr = NULL;\n- IPv6Hdr* ipv6Hdr = NULL;\n- UDPHdr* udpHdr = NULL;\n- GeneveHdr* geneveHdr;\n- GeneveOptionHdr* optHdr;\n- POVS_GENEVE_VPORT vportGeneve;\n- UINT32 headRoom = 0;\n-\n- UINT32 packetLength;\n- ULONG mss = 0;\n- NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo;\n-\n- if (tunKey->dst.si_family == AF_INET) {\n- headRoom = OvsGetGeneveTunHdrMinSize() + tunKey->tunOptLen;\n- }\n- else if (tunKey->dst.si_family == AF_INET6) {\n- headRoom = OvsGetGeneveIPv6TunHdrMinSize() + tunKey->tunOptLen;\n- }\n-\n- status = OvsLookupIPhFwdInfo(tunKey->src, tunKey->dst, &fwdInfo);\n- if (status != STATUS_SUCCESS) {\n- OvsFwdIPHelperRequest(NULL, 0, tunKey, NULL, NULL, NULL);\n- // return NDIS_STATUS_PENDING;\n- /*\n- * XXX: Don't know if the completionList will make any sense when\n- * accessed in the callback. Make sure the caveats are known.\n- *\n- * XXX: This code will work once we are able to grab locks in the\n- * callback.\n- */\n- return NDIS_STATUS_FAILURE;\n- }\n- RtlCopyMemory(switchFwdInfo->value, fwdInfo.value, sizeof fwdInfo.value);\n-\n- curNb = NET_BUFFER_LIST_FIRST_NB(curNbl);\n- packetLength = NET_BUFFER_DATA_LENGTH(curNb);\n-\n- if (layers->isTcp) {\n- mss = OVSGetTcpMSS(curNbl);\n-\n- OVS_LOG_TRACE(\"MSS %u packet len %u\", mss,\n- packetLength);\n- if (mss) {\n- OVS_LOG_TRACE(\"l4Offset %d\", layers->l4Offset);\n- *newNbl = OvsTcpSegmentNBL(switchContext, curNbl, layers,\n- mss, headRoom, FALSE);\n- if (*newNbl == NULL) {\n- OVS_LOG_ERROR(\"Unable to segment NBL\");\n- return NDIS_STATUS_FAILURE;\n- }\n- /* Clear out LSO flags after this point */\n- NET_BUFFER_LIST_INFO(*newNbl, TcpLargeSendNetBufferListInfo) = 0;\n- }\n- }\n-\n- vportGeneve = (POVS_GENEVE_VPORT) GetOvsVportPriv(vport);\n- ASSERT(vportGeneve != NULL);\n-\n- /* If we didn't split the packet above, make a copy now */\n- if (*newNbl == NULL) {\n- *newNbl = OvsPartialCopyNBL(switchContext, curNbl, 0, headRoom,\n- FALSE /*NBL info*/);\n- if (*newNbl == NULL) {\n- OVS_LOG_ERROR(\"Unable to copy NBL\");\n- return NDIS_STATUS_FAILURE;\n- }\n- csumInfo.Value = NET_BUFFER_LIST_INFO(curNbl,\n- TcpIpChecksumNetBufferListInfo);\n- status = OvsApplySWChecksumOnNB(layers, *newNbl, &csumInfo);\n-\n- if (status != NDIS_STATUS_SUCCESS) {\n- goto ret_error;\n- }\n- }\n-\n- curNbl = *newNbl;\n- for (curNb = NET_BUFFER_LIST_FIRST_NB(curNbl); curNb != NULL;\n- curNb = curNb->Next) {\n- status = NdisRetreatNetBufferDataStart(curNb, headRoom, 0, NULL);\n- if (status != NDIS_STATUS_SUCCESS) {\n- goto ret_error;\n- }\n-\n- curMdl = NET_BUFFER_CURRENT_MDL(curNb);\n- bufferStart = (PUINT8)OvsGetMdlWithLowPriority(curMdl);\n- if (!bufferStart) {\n- status = NDIS_STATUS_RESOURCES;\n- goto ret_error;\n- }\n-\n- bufferStart += NET_BUFFER_CURRENT_MDL_OFFSET(curNb);\n- if (NET_BUFFER_NEXT_NB(curNb)) {\n- OVS_LOG_TRACE(\"nb length %u next %u\",\n- NET_BUFFER_DATA_LENGTH(curNb),\n- NET_BUFFER_DATA_LENGTH(curNb->Next));\n- }\n-\n- /* L2 header */\n- ethHdr = (EthHdr *)bufferStart;\n- NdisMoveMemory(ethHdr->Destination, fwdInfo.dstMacAddr,\n- sizeof ethHdr->Destination);\n- NdisMoveMemory(ethHdr->Source, fwdInfo.srcMacAddr,\n- sizeof ethHdr->Source);\n-\n- if (tunKey->dst.si_family == AF_INET) {\n- ethHdr->Type = htons(ETH_TYPE_IPV4);\n- } else if (tunKey->dst.si_family == AF_INET6) {\n- ethHdr->Type = htons(ETH_TYPE_IPV6);\n- }\n-\n- if (tunKey->dst.si_family == AF_INET) {\n- /* IP header */\n- ipHdr = (IPHdr *)((PCHAR)ethHdr + sizeof *ethHdr);\n-\n- ipHdr->ihl = sizeof *ipHdr / 4;\n- ipHdr->version = IPPROTO_IPV4;\n- ipHdr->tos = tunKey->tos;\n- ipHdr->tot_len = htons(NET_BUFFER_DATA_LENGTH(curNb) - sizeof *ethHdr);\n- ipHdr->id = (uint16)atomic_add64(&vportGeneve->ipId,\n- NET_BUFFER_DATA_LENGTH(curNb));\n- ipHdr->frag_off = (tunKey->flags & OVS_TNL_F_DONT_FRAGMENT) ?\n- IP_DF_NBO : 0;\n- ipHdr->ttl = tunKey->ttl ? tunKey->ttl : GENEVE_DEFAULT_TTL;\n- ipHdr->protocol = IPPROTO_UDP;\n- ASSERT(OvsIphAddrEquals(&tunKey->dst, &fwdInfo.dstIphAddr));\n- ASSERT(OvsIphAddrEquals(&tunKey->src, &fwdInfo.srcIphAddr) || OvsIphIsZero(&tunKey->src));\n- ipHdr->saddr = fwdInfo.srcIphAddr.Ipv4.sin_addr.s_addr;\n- ipHdr->daddr = fwdInfo.dstIphAddr.Ipv4.sin_addr.s_addr;\n- ipHdr->check = 0;\n- } else if (tunKey->dst.si_family == AF_INET6) {\n- /* IPv6 header */\n- ipv6Hdr = (IPv6Hdr *)((PCHAR)ethHdr + sizeof *ethHdr);\n-\n- ipv6Hdr->version = IPV6;\n- ipv6Hdr->priority = 0;\n- ipv6Hdr->flow_lbl[0] = 0;\n- ipv6Hdr->flow_lbl[1] = 0;\n- ipv6Hdr->flow_lbl[2] = 0;\n- ipv6Hdr->payload_len = htons(NET_BUFFER_DATA_LENGTH(curNb) - sizeof *ethHdr - sizeof *ipv6Hdr);\n- ipv6Hdr->hop_limit = tunKey->ttl ? tunKey->ttl : GENEVE_DEFAULT_TTL;\n- ipv6Hdr->nexthdr = IPPROTO_UDP;\n- ASSERT(OvsIphAddrEquals(&(tunKey->dst), &(fwdInfo.dstIphAddr)));\n- ASSERT(OvsIphAddrEquals(&(tunKey->src), &(fwdInfo.srcIphAddr)) || OvsIphIsZero(&(tunKey->src)));\n- RtlCopyMemory(&ipv6Hdr->saddr, &fwdInfo.srcIphAddr.Ipv6.sin6_addr,\n- sizeof(ipv6Hdr->saddr));\n- RtlCopyMemory(&ipv6Hdr->daddr, &fwdInfo.dstIphAddr.Ipv6.sin6_addr,\n- sizeof(ipv6Hdr->daddr));\n- }\n-\n- /* UDP header */\n-\n- if (tunKey->dst.si_family == AF_INET) {\n- udpHdr = (UDPHdr *)((PCHAR)ipHdr + sizeof *ipHdr);\n- } else if (tunKey->dst.si_family == AF_INET6) {\n- udpHdr = (UDPHdr *)((PCHAR)ipv6Hdr + sizeof *ipv6Hdr);\n- }\n-\n- ASSERT(udpHdr);\n- udpHdr->source = htons(tunKey->flow_hash | MAXINT16);\n- udpHdr->dest = tunKey->dst_port ? tunKey->dst_port :\n- htons(vportGeneve->dstPort);\n- udpHdr->len = htons(NET_BUFFER_DATA_LENGTH(curNb) - headRoom +\n- sizeof *udpHdr + sizeof *geneveHdr +\n- tunKey->tunOptLen);\n- if (tunKey->flags & OVS_TNL_F_CSUM) {\n- UINT16 udpChksumLen = 0;\n- if (tunKey->dst.si_family == AF_INET) {\n- udpChksumLen = (UINT16) NET_BUFFER_DATA_LENGTH(curNb) -\n- sizeof *ipHdr - sizeof *ethHdr;\n- udpHdr->check = IPPseudoChecksum(&ipHdr->saddr, &ipHdr->daddr,\n- IPPROTO_UDP, udpChksumLen);\n- } else if (tunKey->dst.si_family == AF_INET6) {\n- udpChksumLen = (UINT16) NET_BUFFER_DATA_LENGTH(curNb) -\n- sizeof *ipv6Hdr - sizeof *ethHdr;\n-\n- udpHdr->check = IPv6PseudoChecksum((UINT32*)&ipv6Hdr->saddr,\n- (UINT32*)&ipv6Hdr->daddr,\n- IPPROTO_UDP, udpChksumLen);\n- }\n- } else {\n- udpHdr->check = 0;\n- }\n- /* Geneve header */\n- geneveHdr = (GeneveHdr *)((PCHAR)udpHdr + sizeof *udpHdr);\n- geneveHdr->version = GENEVE_VER;\n- geneveHdr->optLen = tunKey->tunOptLen / 4;\n- geneveHdr->oam = !!(tunKey->flags & OVS_TNL_F_OAM);\n- geneveHdr->critical = !!(tunKey->flags & OVS_TNL_F_CRT_OPT);\n- geneveHdr->reserved1 = 0;\n- geneveHdr->protocol = ETH_P_TEB_NBO;\n- geneveHdr->vni = GENEVE_TUNNELID_TO_VNI(tunKey->tunnelId);\n- geneveHdr->reserved2 = 0;\n-\n- /* Geneve header options */\n- optHdr = (GeneveOptionHdr *)(geneveHdr + 1);\n- memcpy(optHdr, IPTunnelKeyGetOptions(tunKey), tunKey->tunOptLen);\n-\n- csumInfo.Value = 0;\n- csumInfo.Transmit.IpHeaderChecksum = 1;\n-\n- if (tunKey->dst.si_family == AF_INET) {\n- csumInfo.Transmit.IsIPv4 = 1;\n- } else if (tunKey->dst.si_family == AF_INET6) {\n- csumInfo.Transmit.IsIPv4 = 0;\n- csumInfo.Transmit.IsIPv6 = 1;\n- csumInfo.Transmit.IpHeaderChecksum = 0;\n- }\n-\n- if (tunKey->flags & OVS_TNL_F_CSUM) {\n- csumInfo.Transmit.UdpChecksum = 1;\n- }\n- NET_BUFFER_LIST_INFO(curNbl,\n- TcpIpChecksumNetBufferListInfo) = csumInfo.Value;\n- }\n-\n- return STATUS_SUCCESS;\n-\n-ret_error:\n- OvsCompleteNBL(switchContext, *newNbl, TRUE);\n- *newNbl = NULL;\n- return status;\n-}\n-\n-NDIS_STATUS OvsDecapGeneve(POVS_SWITCH_CONTEXT switchContext,\n- PNET_BUFFER_LIST curNbl,\n- OvsIPTunnelKey *tunKey,\n- PNET_BUFFER_LIST *newNbl)\n-{\n- PNET_BUFFER curNb;\n- PMDL curMdl;\n- EthHdr *ethHdr;\n- IPHdr *ipHdr;\n- IPv6Hdr *ipv6Hdr;\n- UDPHdr *udpHdr;\n- GeneveHdr *geneveHdr;\n- UINT32 tunnelSize;\n- UINT32 packetLength;\n- PUINT8 bufferStart;\n- PVOID optStart;\n- NDIS_STATUS status;\n- OVS_PACKET_HDR_INFO layers = { 0 };\n-\n- status = OvsExtractLayers(curNbl, &layers);\n- if (status != NDIS_STATUS_SUCCESS) {\n- return status;\n- }\n-\n- /* Check the length of the UDP payload */\n- curNb = NET_BUFFER_LIST_FIRST_NB(curNbl);\n- tunnelSize = OvsGetGeneveTunHdrSizeFromLayers(&layers);\n- packetLength = NET_BUFFER_DATA_LENGTH(curNb);\n- if (packetLength <= tunnelSize) {\n- return NDIS_STATUS_INVALID_LENGTH;\n- }\n-\n- /*\n- * Create a copy of the NBL so that we have all the headers in one MDL.\n- */\n- *newNbl = OvsPartialCopyNBL(switchContext, curNbl,\n- tunnelSize, 0,\n- TRUE /*copy NBL info */);\n-\n- if (*newNbl == NULL) {\n- return NDIS_STATUS_RESOURCES;\n- }\n-\n- /* XXX: Handle VLAN header. */\n- curNbl = *newNbl;\n- curNb = NET_BUFFER_LIST_FIRST_NB(curNbl);\n- curMdl = NET_BUFFER_CURRENT_MDL(curNb);\n- bufferStart = (PUINT8)OvsGetMdlWithLowPriority(curMdl)\n- + NET_BUFFER_CURRENT_MDL_OFFSET(curNb);\n- if (!bufferStart) {\n- status = NDIS_STATUS_RESOURCES;\n- goto dropNbl;\n- }\n-\n- ethHdr = (EthHdr *)bufferStart;\n- /* XXX: Handle IP options. */\n-\n- if (layers.isIPv4) {\n- ipHdr = (IPHdr *)(bufferStart + layers.l3Offset);\n- tunKey->src.si_family = AF_INET;\n- tunKey->src.Ipv4.sin_addr.s_addr = ipHdr->saddr;\n- tunKey->dst.si_family = AF_INET;\n- tunKey->dst.Ipv4.sin_addr.s_addr = ipHdr->daddr;\n- tunKey->tos = ipHdr->tos;\n- tunKey->ttl = ipHdr->ttl;\n- tunKey->pad = 0;\n- } else if (layers.isIPv6) {\n- ipv6Hdr = (IPv6Hdr *)(bufferStart + layers.l3Offset);\n- tunKey->src.si_family = AF_INET6;\n- RtlCopyMemory(&(tunKey->src.Ipv6.sin6_addr), &ipv6Hdr->saddr,\n- sizeof(tunKey->src.Ipv6.sin6_addr));\n- tunKey->dst.si_family = AF_INET6;\n- RtlCopyMemory(&(tunKey->dst.Ipv6.sin6_addr), &ipv6Hdr->daddr,\n- sizeof(tunKey->dst.Ipv6.sin6_addr));\n- tunKey->tos = 0;/*???*/\n- tunKey->ttl = ipv6Hdr->hop_limit;\n- tunKey->pad = 0;\n- }\n- udpHdr = (UDPHdr *)(bufferStart + layers.l4Offset);\n- /* Validate if NIC has indicated checksum failure. */\n- status = OvsValidateUDPChecksum(curNbl, udpHdr->check == 0);\n- if (status != NDIS_STATUS_SUCCESS) {\n- goto dropNbl;\n- }\n-\n- /* Calculate and verify UDP checksum if NIC didn't do it. */\n- if (udpHdr->check != 0) {\n- status = OvsCalculateUDPChecksum(curNbl, curNb, ethHdr, udpHdr,\n- packetLength, &layers);\n- tunKey->flags |= OVS_TNL_F_CSUM;\n- if (status != NDIS_STATUS_SUCCESS) {\n- goto dropNbl;\n- }\n- }\n-\n- geneveHdr = (GeneveHdr *)((PCHAR)udpHdr + sizeof *udpHdr);\n- if (geneveHdr->protocol != ETH_P_TEB_NBO) {\n- status = STATUS_NDIS_INVALID_PACKET;\n- goto dropNbl;\n- }\n- /* Update tunnelKey flags. */\n- tunKey->flags = OVS_TNL_F_KEY | (geneveHdr->oam ? OVS_TNL_F_OAM : 0) |\n- (geneveHdr->critical ? OVS_TNL_F_CRT_OPT : 0);\n-\n- tunKey->tunnelId = GENEVE_VNI_TO_TUNNELID(geneveHdr->vni);\n- tunKey->tunOptLen = (uint8)geneveHdr->optLen * 4;\n- if (tunKey->tunOptLen > TUN_OPT_MAX_LEN ||\n- packetLength < tunnelSize + tunKey->tunOptLen) {\n- status = NDIS_STATUS_INVALID_LENGTH;\n- goto dropNbl;\n- }\n- /* Clear out the receive flag for the inner packet. */\n- NET_BUFFER_LIST_INFO(curNbl, TcpIpChecksumNetBufferListInfo) = 0;\n-\n- NdisAdvanceNetBufferDataStart(curNb, tunnelSize, FALSE, NULL);\n- if (tunKey->tunOptLen > 0) {\n- optStart = NdisGetDataBuffer(curNb, tunKey->tunOptLen,\n- IPTunnelKeyGetOptions(tunKey), 1, 0);\n-\n- /* If data is contiguous in the buffer, NdisGetDataBuffer will not copy\n- data to the storage. Manual copy is needed. */\n- if (optStart != IPTunnelKeyGetOptions(tunKey)) {\n- memcpy(IPTunnelKeyGetOptions(tunKey), optStart, tunKey->tunOptLen);\n- }\n- NdisAdvanceNetBufferDataStart(curNb, tunKey->tunOptLen, FALSE, NULL);\n- tunKey->flags |= OVS_TNL_F_GENEVE_OPT;\n- }\n- return NDIS_STATUS_SUCCESS;\n-\n-dropNbl:\n- OvsCompleteNBL(switchContext, *newNbl, TRUE);\n- *newNbl = NULL;\n- return status;\n-}\ndiff --git a/datapath-windows/ovsext/Geneve.h b/datapath-windows/ovsext/Geneve.h\ndeleted file mode 100644\nindex 6307479d1..000000000\n--- a/datapath-windows/ovsext/Geneve.h\n+++ /dev/null\n@@ -1,146 +0,0 @@\n-/*\n- * Copyright (c) 2016 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-\n-#ifndef __GENEVE_H_\n-#define __GENEVE_H_ 1\n-\n-#include \"NetProto.h\"\n-\n-typedef union _OVS_FWD_INFO *POVS_FWD_INFO;\n-\n-typedef struct _OVS_GENEVE_VPORT {\n- UINT16 dstPort;\n- UINT64 filterID;\n- UINT64 ipId;\n- /*\n- * To be filled\n- */\n-} OVS_GENEVE_VPORT, *POVS_GENEVE_VPORT;\n-\n-/* Geneve Header:\n- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n- * |Ver| Opt Len |O|C| Rsvd. | Protocol Type |\n- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n- * | Virtual Network Identifier (VNI) | Reserved |\n- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n- * | Variable Length Options |\n- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n- *\n- * Option Header:\n- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n- * | Option Class | Type |R|R|R| Length |\n- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n- * | Variable Option Data |\n- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n- */\n-typedef struct GeneveHdr {\n- /* Length of options fields in int32 excluding the common header */\n- UINT32 optLen : 6;\n- /* Version. */\n- UINT32 version:2;\n- /* Reserved. */\n- UINT32 reserved1 : 6;\n- /* Critical options present */\n- UINT32 critical : 1;\n- /* This packet contains a control message instead of a data payload */\n- UINT32 oam:1;\n- /* Protocol Type. */\n- UINT32 protocol:16;\n- /* VNI */\n- UINT32 vni:24;\n- /* Reserved. */\n- UINT32 reserved2:8;\n-} GeneveHdr;\n-\n-typedef struct GeneveOptionHdr {\n- /* Namespace for the 'type' field. */\n- UINT32 optionClass:16;\n- /* Format of data contained in the option. */\n- UINT32 type:8;\n- /* Length of option in int32 excluding the option header. */\n- UINT32 length:5;\n- /* Reserved. */\n- UINT32 reserved:3;\n-} GeneveOptionHdr;\n-\n-#define GENEVE_CRIT_OPT_TYPE (1 << 7)\n-\n-NTSTATUS OvsInitGeneveTunnel(POVS_VPORT_ENTRY vport,\n- UINT16 udpDestPort);\n-\n-VOID OvsCleanupGeneveTunnel(POVS_VPORT_ENTRY vport);\n-\n-\n-NDIS_STATUS OvsEncapGeneve(POVS_VPORT_ENTRY vport,\n- PNET_BUFFER_LIST curNbl,\n- OvsIPTunnelKey *tunKey,\n- POVS_SWITCH_CONTEXT switchContext,\n- POVS_PACKET_HDR_INFO layers,\n- PNET_BUFFER_LIST *newNbl,\n- POVS_FWD_INFO switchFwdInfo);\n-\n-NDIS_STATUS OvsDecapGeneve(POVS_SWITCH_CONTEXT switchContext,\n- PNET_BUFFER_LIST curNbl,\n- OvsIPTunnelKey *tunKey,\n- PNET_BUFFER_LIST *newNbl);\n-\n-static __inline UINT32\n-OvsGetGeneveTunHdrMinSize(VOID)\n-{\n- /* XXX: Can L2 include VLAN at all? */\n- return sizeof (EthHdr) + sizeof (IPHdr) + sizeof (UDPHdr) +\n- sizeof (GeneveHdr);\n-}\n-\n-static __inline UINT32\n-OvsGetGeneveTunHdrMaxSize(VOID)\n-{\n- /* XXX: Can L2 include VLAN at all? */\n- return OvsGetGeneveTunHdrMinSize() + TUN_OPT_MAX_LEN;\n-}\n-\n-static __inline UINT32\n-OvsGetGeneveIPv6TunHdrMinSize(VOID)\n-{\n- /* XXX: Can L2 include VLAN at all? */\n- return sizeof (EthHdr) + sizeof (IPv6Hdr) + sizeof (UDPHdr) +\n- sizeof (GeneveHdr);\n-}\n-\n-static __inline UINT32\n-OvsGetGeneveIPv6TunHdrMaxSize(VOID)\n-{\n- /* XXX: Can L2 include VLAN at all? */\n- return OvsGetGeneveIPv6TunHdrMinSize() + TUN_OPT_MAX_LEN;\n-}\n-\n-static __inline UINT32\n-OvsGetGeneveTunHdrSizeFromLayers(POVS_PACKET_HDR_INFO layers)\n-{\n- return layers->l7Offset + sizeof(GeneveHdr);\n-}\n-\n-#define GENEVE_UDP_PORT 6081\n-#define GENEVE_UDP_PORT_NBO 0xC117\n-#define GENEVE_VER 0\n-#define GENEVE_DEFAULT_TTL 64\n-#define GENEVE_ID_IS_VALID(geneveID) (0 < (geneveID) && (vxlanID) <= 0xffffff)\n-#define GENEVE_TUNNELID_TO_VNI(_tID) (UINT32)(((UINT64)(_tID)) >> 40)\n-#define GENEVE_VNI_TO_TUNNELID(_vni) (((UINT64)(_vni)) << 40)\n-#define ETH_P_TEB_NBO 0x5865 /* Trans Ether Bridging */\n-\n-#endif /* __GENEVE_H_ */\ndiff --git a/datapath-windows/ovsext/Gre.c b/datapath-windows/ovsext/Gre.c\ndeleted file mode 100644\nindex 54725dd17..000000000\n--- a/datapath-windows/ovsext/Gre.c\n+++ /dev/null\n@@ -1,456 +0,0 @@\n-/*\n- * Copyright (c) 2015, 2016 Cloudbase Solutions Srl\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#include \"precomp.h\"\n-\n-#include \"Atomic.h\"\n-#include \"Debug.h\"\n-#include \"Flow.h\"\n-#include \"Gre.h\"\n-#include \"IpHelper.h\"\n-#include \"NetProto.h\"\n-#include \"Offload.h\"\n-#include \"PacketIO.h\"\n-#include \"PacketParser.h\"\n-#include \"Switch.h\"\n-#include \"User.h\"\n-#include \"Util.h\"\n-#include \"Vport.h\"\n-\n-#ifdef OVS_DBG_MOD\n-#undef OVS_DBG_MOD\n-#endif\n-#define OVS_DBG_MOD OVS_DBG_GRE\n-\n-static NDIS_STATUS\n-OvsDoEncapGre(POVS_VPORT_ENTRY vport, PNET_BUFFER_LIST curNbl,\n- const OvsIPTunnelKey *tunKey,\n- const POVS_FWD_INFO fwdInfo,\n- POVS_PACKET_HDR_INFO layers,\n- POVS_SWITCH_CONTEXT switchContext,\n- PNET_BUFFER_LIST *newNbl);\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsInitGreTunnel --\n- * Initialize GRE tunnel module.\n- * --------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsInitGreTunnel(POVS_VPORT_ENTRY vport)\n-{\n- POVS_GRE_VPORT grePort;\n-\n- grePort = (POVS_GRE_VPORT)OvsAllocateMemoryWithTag(sizeof(*grePort),\n- OVS_GRE_POOL_TAG);\n- if (!grePort) {\n- OVS_LOG_ERROR(\"Insufficient memory, can't allocate OVS_GRE_VPORT\");\n- return STATUS_INSUFFICIENT_RESOURCES;\n- }\n-\n- RtlZeroMemory(grePort, sizeof(*grePort));\n- vport->priv = (PVOID)grePort;\n- return STATUS_SUCCESS;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsCleanupGreTunnel --\n- * Cleanup GRE Tunnel module.\n- * --------------------------------------------------------------------------\n- */\n-void\n-OvsCleanupGreTunnel(POVS_VPORT_ENTRY vport)\n-{\n- if (vport->ovsType != OVS_VPORT_TYPE_GRE ||\n- vport->priv == NULL) {\n- return;\n- }\n-\n- OvsFreeMemoryWithTag(vport->priv, OVS_GRE_POOL_TAG);\n- vport->priv = NULL;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsEncapGre --\n- * Encapsulates a packet with an GRE header.\n- * --------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsEncapGre(POVS_VPORT_ENTRY vport,\n- PNET_BUFFER_LIST curNbl,\n- OvsIPTunnelKey *tunKey,\n- POVS_SWITCH_CONTEXT switchContext,\n- POVS_PACKET_HDR_INFO layers,\n- PNET_BUFFER_LIST *newNbl,\n- POVS_FWD_INFO switchFwdInfo)\n-{\n- OVS_FWD_INFO fwdInfo;\n- NDIS_STATUS status;\n-\n- if (tunKey->dst.si_family != AF_INET) {\n- /*V6 tunnel support will be supported later*/\n- return NDIS_STATUS_FAILURE;\n- }\n-\n- status = OvsLookupIPhFwdInfo(tunKey->src, tunKey->dst, &fwdInfo);\n- if (status != STATUS_SUCCESS) {\n- OvsFwdIPHelperRequest(NULL, 0, tunKey, NULL, NULL, NULL);\n- return NDIS_STATUS_FAILURE;\n- }\n-\n- RtlCopyMemory(switchFwdInfo->value, fwdInfo.value, sizeof fwdInfo.value);\n-\n- status = OvsDoEncapGre(vport, curNbl, tunKey, &fwdInfo, layers,\n- switchContext, newNbl);\n- return status;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsDoEncapGre --\n- * Internal utility function which actually does the GRE encap.\n- * --------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsDoEncapGre(POVS_VPORT_ENTRY vport,\n- PNET_BUFFER_LIST curNbl,\n- const OvsIPTunnelKey *tunKey,\n- const POVS_FWD_INFO fwdInfo,\n- POVS_PACKET_HDR_INFO layers,\n- POVS_SWITCH_CONTEXT switchContext,\n- PNET_BUFFER_LIST *newNbl)\n-{\n- NDIS_STATUS status;\n- PNET_BUFFER curNb;\n- PMDL curMdl;\n- PUINT8 bufferStart;\n- EthHdr *ethHdr;\n- IPHdr *ipHdr;\n- PGREHdr greHdr;\n- POVS_GRE_VPORT vportGre;\n- PCHAR pChk = NULL;\n- UINT32 headRoom = GreTunHdrSize(OvsTunnelFlagsToGreFlags(tunKey->flags));\n-#if DBG\n- UINT32 counterHeadRoom;\n-#endif\n- UINT32 packetLength;\n- ULONG mss = 0;\n- ASSERT(*newNbl == NULL);\n-\n- curNb = NET_BUFFER_LIST_FIRST_NB(curNbl);\n- packetLength = NET_BUFFER_DATA_LENGTH(curNb);\n-\n- if (layers->isTcp) {\n- mss = OVSGetTcpMSS(curNbl);\n-\n- OVS_LOG_TRACE(\"MSS %u packet len %u\", mss,\n- packetLength);\n- if (mss) {\n- OVS_LOG_TRACE(\"l4Offset %d\", layers->l4Offset);\n- *newNbl = OvsTcpSegmentNBL(switchContext, curNbl, layers,\n- mss, headRoom, FALSE);\n- if (*newNbl == NULL) {\n- OVS_LOG_ERROR(\"Unable to segment NBL\");\n- return NDIS_STATUS_FAILURE;\n- }\n- /* Clear out LSO flags after this point */\n- NET_BUFFER_LIST_INFO(*newNbl, TcpLargeSendNetBufferListInfo) = 0;\n- }\n- }\n-\n- vportGre = (POVS_GRE_VPORT)GetOvsVportPriv(vport);\n- ASSERT(vportGre);\n-\n- /* If we didn't split the packet above, make a copy now */\n- if (*newNbl == NULL) {\n- *newNbl = OvsPartialCopyNBL(switchContext, curNbl, 0, headRoom,\n- FALSE /*NBL info*/);\n- if (*newNbl == NULL) {\n- OVS_LOG_ERROR(\"Unable to copy NBL\");\n- return NDIS_STATUS_FAILURE;\n- }\n-\n- NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo;\n- csumInfo.Value = NET_BUFFER_LIST_INFO(curNbl,\n- TcpIpChecksumNetBufferListInfo);\n-\n- status = OvsApplySWChecksumOnNB(layers, *newNbl, &csumInfo);\n- if (status != NDIS_STATUS_SUCCESS) {\n- goto ret_error;\n- }\n- }\n-\n- curNbl = *newNbl;\n- for (curNb = NET_BUFFER_LIST_FIRST_NB(curNbl); curNb != NULL;\n- curNb = curNb->Next) {\n-#if DBG\n- counterHeadRoom = headRoom;\n-#endif\n- status = NdisRetreatNetBufferDataStart(curNb, headRoom, 0, NULL);\n- if (status != NDIS_STATUS_SUCCESS) {\n- goto ret_error;\n- }\n-\n- curMdl = NET_BUFFER_CURRENT_MDL(curNb);\n- bufferStart = (PUINT8)OvsGetMdlWithLowPriority(curMdl);\n- if (!bufferStart) {\n- status = NDIS_STATUS_RESOURCES;\n- goto ret_error;\n- }\n-\n- bufferStart += NET_BUFFER_CURRENT_MDL_OFFSET(curNb);\n- if (NET_BUFFER_NEXT_NB(curNb)) {\n- OVS_LOG_TRACE(\"nb length %u next %u\",\n- NET_BUFFER_DATA_LENGTH(curNb),\n- NET_BUFFER_DATA_LENGTH(curNb->Next));\n- }\n-\n- /* L2 header */\n- ethHdr = (EthHdr *)bufferStart;\n- NdisMoveMemory(ethHdr->Destination, fwdInfo->dstMacAddr,\n- sizeof ethHdr->Destination);\n- NdisMoveMemory(ethHdr->Source, fwdInfo->srcMacAddr,\n- sizeof ethHdr->Source);\n- ethHdr->Type = htons(ETH_TYPE_IPV4);\n-#if DBG\n- counterHeadRoom -= sizeof *ethHdr;\n-#endif\n-\n- /* IP header */\n- ipHdr = (IPHdr *)((PCHAR)ethHdr + sizeof *ethHdr);\n-\n- ipHdr->ihl = sizeof *ipHdr / 4;\n- ipHdr->version = IPPROTO_IPV4;\n- ipHdr->tos = tunKey->tos;\n- ipHdr->tot_len = htons(NET_BUFFER_DATA_LENGTH(curNb) - sizeof *ethHdr);\n- ipHdr->id = (uint16)atomic_add64(&vportGre->ipId,\n- NET_BUFFER_DATA_LENGTH(curNb));\n- ipHdr->frag_off = (tunKey->flags & OVS_TNL_F_DONT_FRAGMENT) ?\n- IP_DF_NBO : 0;\n- ipHdr->ttl = tunKey->ttl ? tunKey->ttl : 64;\n- ipHdr->protocol = IPPROTO_GRE;\n- ASSERT(OvsIphAddrEquals(&tunKey->dst, &fwdInfo->dstIphAddr));\n- ASSERT(OvsIphAddrEquals(&tunKey->src, &fwdInfo->srcIphAddr) ||\n- OvsIphIsZero(&tunKey->src));\n- ipHdr->saddr = fwdInfo->srcIphAddr.Ipv4.sin_addr.s_addr;\n- ipHdr->daddr = fwdInfo->dstIphAddr.Ipv4.sin_addr.s_addr;\n-\n- ipHdr->check = 0;\n- ipHdr->check = IPChecksum((UINT8 *)ipHdr, sizeof *ipHdr, 0);\n-#if DBG\n- counterHeadRoom -= sizeof *ipHdr;\n-#endif\n-\n- /* GRE header */\n- greHdr = (GREHdr *)((PCHAR)ipHdr + sizeof *ipHdr);\n- greHdr->flags = OvsTunnelFlagsToGreFlags(tunKey->flags);\n- greHdr->protocolType = GRE_NET_TEB;\n-#if DBG\n- counterHeadRoom -= sizeof *greHdr;\n-#endif\n-\n- PCHAR currentOffset = (PCHAR)greHdr + sizeof *greHdr;\n-\n- if (tunKey->flags & OVS_TNL_F_CSUM) {\n- RtlZeroMemory(currentOffset, 4);\n- pChk = currentOffset;\n- currentOffset += 4;\n-#if DBG\n- counterHeadRoom -= 4;\n-#endif\n- }\n-\n- if (tunKey->flags & OVS_TNL_F_KEY) {\n- RtlZeroMemory(currentOffset, 4);\n- UINT32 key = (tunKey->tunnelId >> 32);\n- RtlCopyMemory(currentOffset, &key, sizeof key);\n- currentOffset += 4;\n-#if DBG\n- counterHeadRoom -= 4;\n-#endif\n- }\n-\n- /* Checksum needs to be done after the GRE header has been set */\n- if (tunKey->flags & OVS_TNL_F_CSUM) {\n- ASSERT(pChk);\n- UINT16 chksum =\n- CalculateChecksumNB(curNb,\n- (UINT16)(NET_BUFFER_DATA_LENGTH(curNb) -\n- sizeof *ipHdr - sizeof *ethHdr),\n- sizeof *ipHdr + sizeof *ethHdr);\n- RtlCopyMemory(pChk, &chksum, 2);\n- }\n-\n-#if DBG\n- ASSERT(counterHeadRoom == 0);\n-#endif\n-\n- }\n- return STATUS_SUCCESS;\n-\n-ret_error:\n- OvsCompleteNBL(switchContext, *newNbl, TRUE);\n- *newNbl = NULL;\n- return status;\n-}\n-\n-NDIS_STATUS\n-OvsDecapGre(POVS_SWITCH_CONTEXT switchContext,\n- PNET_BUFFER_LIST curNbl,\n- OvsIPTunnelKey *tunKey,\n- PNET_BUFFER_LIST *newNbl)\n-{\n- PNET_BUFFER curNb;\n- PMDL curMdl;\n- EthHdr *ethHdr;\n- IPHdr *ipHdr;\n- GREHdr *greHdr;\n- UINT32 tunnelSize, packetLength;\n- UINT32 headRoom = 0;\n- UINT32 maxGreLen;\n- PUINT8 bufferStart;\n- NDIS_STATUS status = NDIS_STATUS_SUCCESS;\n- PCHAR tempBuf = NULL;\n- OVS_PACKET_HDR_INFO layers;\n-\n- ASSERT(*newNbl == NULL);\n-\n- *newNbl = NULL;\n-\n- status = OvsExtractLayers(curNbl, &layers);\n- if (status != NDIS_STATUS_SUCCESS) {\n- return status;\n- }\n-\n- curNb = NET_BUFFER_LIST_FIRST_NB(curNbl);\n- packetLength = NET_BUFFER_DATA_LENGTH(curNb);\n- curMdl = NET_BUFFER_CURRENT_MDL(curNb);\n- tunnelSize = GreTunHdrSizeFromLayers(0, &layers);\n- if (packetLength <= tunnelSize) {\n- return NDIS_STATUS_INVALID_LENGTH;\n- }\n-\n- maxGreLen = GreMaxLengthFromLayers(&layers);\n- /* Get a contiguous buffer for the maximum length of a GRE header */\n- bufferStart = NdisGetDataBuffer(curNb, maxGreLen, NULL, 1, 0);\n- if (!bufferStart) {\n- /* Documentation is unclear on where the packet can be fragmented.\n- * For the moment allocate the buffer needed to get the maximum length\n- * of a GRE header contiguous */\n- tempBuf = OvsAllocateMemoryWithTag(maxGreLen, OVS_GRE_POOL_TAG);\n- if (!tempBuf) {\n- status = NDIS_STATUS_RESOURCES;\n- goto end;\n- }\n- RtlZeroMemory(tempBuf, maxGreLen);\n- bufferStart = NdisGetDataBuffer(curNb, maxGreLen, tempBuf,\n- 1, 0);\n- if (!bufferStart) {\n- status = NDIS_STATUS_RESOURCES;\n- goto end;\n- }\n- }\n-\n- ethHdr = (EthHdr *)bufferStart;\n- headRoom += layers.l3Offset;\n-\n- ipHdr = (IPHdr *)(bufferStart + layers.l3Offset);\n- tunKey->src.Ipv4.sin_addr.s_addr = ipHdr->saddr;\n- tunKey->src.Ipv4.sin_family = AF_INET;\n- tunKey->dst.Ipv4.sin_addr.s_addr = ipHdr->daddr;\n- tunKey->dst.Ipv4.sin_family = AF_INET;\n-\n- tunKey->tos = ipHdr->tos;\n- tunKey->ttl = ipHdr->ttl;\n- tunKey->pad = 0;\n- headRoom += sizeof *ipHdr;\n-\n- greHdr = (GREHdr *)(bufferStart + layers.l4Offset);\n- headRoom += sizeof *greHdr;\n-\n- tunnelSize = GreTunHdrSizeFromLayers(greHdr->flags, &layers);\n-\n- /* Verify the packet length after looking at the GRE flags*/\n- if (packetLength <= tunnelSize) {\n- status = NDIS_STATUS_INVALID_LENGTH;\n- goto end;\n- }\n-\n- /* Validate if GRE header protocol type. */\n- if (greHdr->protocolType != GRE_NET_TEB) {\n- status = STATUS_NDIS_INVALID_PACKET;\n- goto end;\n- }\n-\n- PCHAR currentOffset = (PCHAR)greHdr + sizeof *greHdr;\n-\n- if (greHdr->flags & GRE_CSUM) {\n- tunKey->flags |= OVS_TNL_F_CSUM;\n- UINT16 prevChksum = *((UINT16 *)currentOffset);\n- RtlZeroMemory(currentOffset, 2);\n- UINT16 chksum =\n- CalculateChecksumNB(curNb,\n- (UINT16)(NET_BUFFER_DATA_LENGTH(curNb) -\n- layers.l4Offset),\n- layers.l4Offset);\n- if (prevChksum != chksum) {\n- status = STATUS_NDIS_INVALID_PACKET;\n- goto end;\n- }\n- RtlCopyMemory(currentOffset, &prevChksum, 2);\n- currentOffset += 4;\n- headRoom += 4;\n- }\n-\n- if (greHdr->flags & GRE_KEY) {\n- tunKey->flags |= OVS_TNL_F_KEY;\n- UINT32 key = 0;\n- RtlCopyMemory(&key, currentOffset, 4);\n- tunKey->tunnelId = (UINT64)key << 32;\n- currentOffset += 4;\n- headRoom += 4;\n- }\n-\n- /*\n- * Create a copy of the NBL so that we have all the headers in one MDL.\n- */\n- *newNbl = OvsPartialCopyNBL(switchContext, curNbl,\n- tunnelSize, 0,\n- TRUE /*copy NBL info */);\n-\n- if (*newNbl == NULL) {\n- status = NDIS_STATUS_RESOURCES;\n- goto end;\n- }\n-\n- curNbl = *newNbl;\n- curNb = NET_BUFFER_LIST_FIRST_NB(curNbl);\n-\n- /* Clear out the receive flag for the inner packet. */\n- NET_BUFFER_LIST_INFO(curNbl, TcpIpChecksumNetBufferListInfo) = 0;\n- NdisAdvanceNetBufferDataStart(curNb, GreTunHdrSize(greHdr->flags), FALSE,\n- NULL);\n- ASSERT(headRoom == GreTunHdrSize(greHdr->flags));\n-\n-end:\n- if (tempBuf) {\n- OvsFreeMemoryWithTag(tempBuf, OVS_GRE_POOL_TAG);\n- tempBuf = NULL;\n- }\n- return status;\n-}\ndiff --git a/datapath-windows/ovsext/Gre.h b/datapath-windows/ovsext/Gre.h\ndeleted file mode 100644\nindex 144b6195e..000000000\n--- a/datapath-windows/ovsext/Gre.h\n+++ /dev/null\n@@ -1,122 +0,0 @@\n-/*\n- * Copyright (c) 2015, 2016 Cloudbase Solutions Srl\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#ifndef __GRE_H_\n-#define __GRE_H_ 1\n-\n-#include \"Flow.h\"\n-#include \"IpHelper.h\"\n-#include \"NetProto.h\"\n-\n-typedef union _OVS_FWD_INFO *POVS_FWD_INFO;\n-\n-typedef struct _OVS_GRE_VPORT {\n- UINT64 ipId;\n- /*\n- * To be filled\n- */\n-} OVS_GRE_VPORT, *POVS_GRE_VPORT;\n-\n-\n-/* GRE RFC 2890 header based on http://tools.ietf.org/html/rfc2890\n- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\n- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n- * |C| |K|S| Reserved0 | Ver | Protocol Type |\n- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n- * | Checksum (optional) | Reserved1 (Optional) |\n- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n- * | Key (optional) |\n- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n- * | Sequence Number (Optional) |\n- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n- */\n-\n-typedef struct GREHdr {\n- UINT16 flags;\n- UINT16 protocolType;\n-} GREHdr, *PGREHdr;\n-\n-/* Transparent Ethernet Bridging */\n-#define GRE_NET_TEB 0x5865\n-/* GRE Flags*/\n-#define GRE_CSUM 0x0080\n-#define GRE_KEY 0x0020\n-/* The maximum GRE header length that we can process */\n-#define OVS_MAX_GRE_LGTH (sizeof(EthHdr) + sizeof(IPHdr) + sizeof(GREHdr) + 12)\n-\n-NTSTATUS OvsInitGreTunnel(POVS_VPORT_ENTRY vport);\n-\n-VOID OvsCleanupGreTunnel(POVS_VPORT_ENTRY vport);\n-\n-\n-void OvsCleanupGreTunnel(POVS_VPORT_ENTRY vport);\n-\n-NDIS_STATUS OvsEncapGre(POVS_VPORT_ENTRY vport,\n- PNET_BUFFER_LIST curNbl,\n- OvsIPTunnelKey *tunKey,\n- POVS_SWITCH_CONTEXT switchContext,\n- POVS_PACKET_HDR_INFO layers,\n- PNET_BUFFER_LIST *newNbl,\n- POVS_FWD_INFO switchFwdInfo);\n-\n-NDIS_STATUS OvsDecapGre(POVS_SWITCH_CONTEXT switchContext,\n- PNET_BUFFER_LIST curNbl,\n- OvsIPTunnelKey *tunKey,\n- PNET_BUFFER_LIST *newNbl);\n-\n-static __inline UINT16\n-OvsTunnelFlagsToGreFlags(UINT16 tunnelflags)\n-{\n- UINT16 flags = 0;\n-\n- if (tunnelflags & OVS_TNL_F_CSUM) {\n- flags |= GRE_CSUM;\n- }\n-\n- if (tunnelflags & OVS_TNL_F_KEY) {\n- flags |= GRE_KEY;\n- }\n-\n- return flags;\n-}\n-\n-static __inline UINT32\n-GreTunHdrSize(UINT16 flags)\n-{\n- UINT32 sum = sizeof(EthHdr) + sizeof(IPHdr) + sizeof(GREHdr);\n- sum += (flags & GRE_CSUM) ? 4 : 0;\n- sum += (flags & GRE_KEY) ? 4 : 0;\n-\n- return sum;\n-}\n-\n-static __inline UINT32\n-GreTunHdrSizeFromLayers(UINT16 flags, POVS_PACKET_HDR_INFO layers)\n-{\n- UINT32 sum = layers->l4Offset + sizeof(GREHdr);\n- sum += (flags & GRE_CSUM) ? 4 : 0;\n- sum += (flags & GRE_KEY) ? 4 : 0;\n-\n- return sum;\n-}\n-\n-static __inline UINT32\n-GreMaxLengthFromLayers(POVS_PACKET_HDR_INFO layers)\n-{\n- return (layers->l4Offset + sizeof(GREHdr) + 12);\n-}\n-\n-#endif /*__GRE_H_ */\ndiff --git a/datapath-windows/ovsext/Ip6Fragment.c b/datapath-windows/ovsext/Ip6Fragment.c\ndeleted file mode 100644\nindex 0b710905d..000000000\n--- a/datapath-windows/ovsext/Ip6Fragment.c\n+++ /dev/null\n@@ -1,808 +0,0 @@\n-/*\n- * Copyright (c) 2022 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#include \"Conntrack.h\"\n-#include \"Ip6Fragment.h\"\n-#include \"Util.h\"\n-#include \"Jhash.h\"\n-#include \"NetProto.h\"\n-#include \"PacketParser.h\"\n-\n-static OVS_IP6FRAG_THREAD_CTX ip6FragThreadCtx;\n-static PNDIS_RW_LOCK_EX ovsIp6FragmentHashLockObj;\n-static UINT64 ip6TotalEntries;\n-static PLIST_ENTRY OvsIp6FragTable;\n-\n-#define MIN_FRAGMENT_SIZE 400\n-#define MAX_IPDATAGRAM_SIZE 65535\n-#define MAX_FRAGMENTS MAX_IPDATAGRAM_SIZE/MIN_FRAGMENT_SIZE + 1\n-\n-static __inline UINT32\n-OvsGetIP6FragmentHash(POVS_IP6FRAG_KEY fragKey)\n-{\n- UINT32 arr[11];\n- arr[0] = (UINT32)fragKey->id;\n- arr[1] = (UINT32)(((UINT32*)(&(fragKey->sAddr)))[0]);\n- arr[2] = (UINT32)(((UINT32*)(&(fragKey->sAddr)))[1]);\n- arr[3] = (UINT32)(((UINT32*)(&(fragKey->sAddr)))[2]);\n- arr[4] = (UINT32)(((UINT32*)(&(fragKey->sAddr)))[3]);\n- arr[5] = (UINT32)(((UINT32*)(&(fragKey->dAddr)))[0]);\n- arr[6] = (UINT32)(((UINT32*)(&(fragKey->dAddr)))[1]);\n- arr[7] = (UINT32)(((UINT32*)(&(fragKey->dAddr)))[2]);\n- arr[8] = (UINT32)(((UINT32*)(&(fragKey->dAddr)))[3]);\n- arr[9] = (UINT32)((fragKey->tunnelId & 0xFFFFFFFF00000000LL) >> 32);\n- arr[10] = (UINT32)(fragKey->tunnelId & 0xFFFFFFFFLL);\n- return OvsJhashWords(arr, 11, OVS_HASH_BASIS);\n-}\n-\n-static VOID\n-OvsIp6FragmentEntryDelete(POVS_IP6FRAG_ENTRY entry, BOOLEAN checkExpiry)\n-{\n- NdisAcquireSpinLock(&(entry->lockObj));\n- if (!entry->markedForDelete && checkExpiry) {\n- UINT64 currentTime;\n- NdisGetCurrentSystemTime((LARGE_INTEGER *)¤tTime);\n- if (entry->expiration > currentTime) {\n- NdisReleaseSpinLock(&(entry->lockObj));\n- return;\n- }\n- }\n-\n- POVS_FRAGMENT6_LIST head = entry->head;\n- POVS_FRAGMENT6_LIST temp = NULL;\n- while (head) {\n- temp = head;\n- head = head->next;\n- OvsFreeMemoryWithTag(temp->pbuff, OVS_IP6FRAG_POOL_TAG);\n- OvsFreeMemoryWithTag(temp, OVS_IP6FRAG_POOL_TAG);\n- }\n- RemoveEntryList(&entry->link);\n- ip6TotalEntries--;\n- NdisReleaseSpinLock(&(entry->lockObj));\n- NdisFreeSpinLock(&(entry->lockObj));\n- if (entry->beforeFragHdrLen > 0) {\n- OvsFreeMemoryWithTag(entry->beforeFragHdrBuf, OVS_IP6FRAG_POOL_TAG);\n- }\n-\n- if (entry->fragHdrLen > 0) {\n- OvsFreeMemoryWithTag(entry->fragHdrBuf, OVS_IP6FRAG_POOL_TAG);\n- }\n-\n- if (entry->behindFragHdrLen > 0) {\n- OvsFreeMemoryWithTag(entry->behindFragHdrBuf, OVS_IP6FRAG_POOL_TAG);\n- }\n-\n- OvsFreeMemoryWithTag(entry, OVS_IP6FRAG_POOL_TAG);\n-}\n-\n-static VOID\n-OvsIp6FragmentEntryCleaner(PVOID data)\n-{\n- POVS_IP6FRAG_THREAD_CTX context = (POVS_IP6FRAG_THREAD_CTX)data;\n- PLIST_ENTRY link, next;\n- POVS_IP6FRAG_ENTRY entry;\n- LOCK_STATE_EX lockState;\n- BOOLEAN success = TRUE;\n-\n- while (success) {\n- if (ovsIp6FragmentHashLockObj == NULL) {\n- /* Lock has been freed by 'OvsCleanupIpFragment()' */\n- break;\n- }\n- NdisAcquireRWLockWrite(ovsIp6FragmentHashLockObj, &lockState, 0);\n- if (context->exit) {\n- NdisReleaseRWLock(ovsIp6FragmentHashLockObj, &lockState);\n- break;\n- }\n-\n- /* Set the timeout for the thread and cleanup. */\n- UINT64 currentTime, threadSleepTimeout;\n- NdisGetCurrentSystemTime((LARGE_INTEGER *)¤tTime);\n- threadSleepTimeout = currentTime + IP6FRAG_CLEANUP_INTERVAL;\n- for (int i = 0; i < IP6_FRAG_HASH_TABLE_SIZE && ip6TotalEntries; i++) {\n- LIST_FORALL_SAFE(&OvsIp6FragTable[i], link, next) {\n- entry = CONTAINING_RECORD(link, OVS_IP6FRAG_ENTRY, link);\n- OvsIp6FragmentEntryDelete(entry, TRUE);\n- }\n- }\n-\n- NdisReleaseRWLock(ovsIp6FragmentHashLockObj, &lockState);\n- KeWaitForSingleObject(&context->event, Executive, KernelMode,\n- FALSE, (LARGE_INTEGER *)&threadSleepTimeout);\n- }\n-\n- PsTerminateSystemThread(STATUS_SUCCESS);\n-}\n-\n-NDIS_STATUS OvsInitIp6Fragment(POVS_SWITCH_CONTEXT context)\n-{\n- NDIS_STATUS status;\n- HANDLE threadHandle = NULL;\n-\n- OVS_LOG_INFO(\"Init ipv6 fragment.\");\n- ovsIp6FragmentHashLockObj = NdisAllocateRWLock(context->NdisFilterHandle);\n- if (ovsIp6FragmentHashLockObj == NULL) {\n- return STATUS_INSUFFICIENT_RESOURCES;\n- }\n-\n- /* Init the Hash Buffer */\n- OvsIp6FragTable = OvsAllocateMemoryWithTag(sizeof(LIST_ENTRY)\n- * IP6_FRAG_HASH_TABLE_SIZE,\n- OVS_IP6FRAG_POOL_TAG);\n- if (OvsIp6FragTable == NULL) {\n- NdisFreeRWLock(ovsIp6FragmentHashLockObj);\n- ovsIp6FragmentHashLockObj = NULL;\n- return STATUS_INSUFFICIENT_RESOURCES;\n- }\n-\n-\n- for (int i = 0; i < IP6_FRAG_HASH_TABLE_SIZE; i++) {\n- InitializeListHead(&OvsIp6FragTable[i]);\n- }\n-\n- /* Init Cleaner Thread */\n- KeInitializeEvent(&ip6FragThreadCtx.event, NotificationEvent, FALSE);\n- status = PsCreateSystemThread(&threadHandle, SYNCHRONIZE, NULL, NULL,\n- NULL, OvsIp6FragmentEntryCleaner,\n- &ip6FragThreadCtx);\n-\n- if (status != STATUS_SUCCESS) {\n- OvsFreeMemoryWithTag(OvsIp6FragTable, OVS_IPFRAG_POOL_TAG);\n- OvsIp6FragTable = NULL;\n- NdisFreeRWLock(ovsIp6FragmentHashLockObj);\n- ovsIp6FragmentHashLockObj = NULL;\n- return status;\n- }\n-\n- ObReferenceObjectByHandle(threadHandle, SYNCHRONIZE, NULL, KernelMode,\n- &ip6FragThreadCtx.threadObject, NULL);\n- ZwClose(threadHandle);\n- threadHandle = NULL;\n- return STATUS_SUCCESS;\n-}\n-\n-static __inline POVS_IP6FRAG_ENTRY\n-OvsLookupIP6Frag(POVS_IP6FRAG_KEY fragKey, UINT32 hash)\n-{\n- POVS_IP6FRAG_ENTRY entry;\n- PLIST_ENTRY link;\n- LOCK_STATE_EX lockState;\n-\n- NdisAcquireRWLockRead(ovsIp6FragmentHashLockObj, &lockState, 0);\n- LIST_FORALL(&OvsIp6FragTable[hash & IP6_FRAG_HASH_TABLE_MASK], link) {\n- entry = CONTAINING_RECORD(link, OVS_IP6FRAG_ENTRY, link);\n- NdisAcquireSpinLock(&(entry->lockObj));\n- if (RtlCompareMemory(&entry->fragKey.dAddr, &fragKey->dAddr,\n- sizeof(fragKey->dAddr)) == sizeof(fragKey->dAddr) &&\n- RtlCompareMemory(&entry->fragKey.sAddr, &fragKey->sAddr,\n- sizeof(fragKey->sAddr)) == sizeof(fragKey->sAddr) &&\n- entry->fragKey.id == fragKey->id &&\n- entry->fragKey.tunnelId == fragKey->tunnelId) {\n- NdisReleaseSpinLock(&(entry->lockObj));\n- NdisReleaseRWLock(ovsIp6FragmentHashLockObj, &lockState);\n- return entry;\n- }\n- NdisReleaseSpinLock(&(entry->lockObj));\n- }\n- NdisReleaseRWLock(ovsIp6FragmentHashLockObj, &lockState);\n- return NULL;\n-}\n-\n-VOID OvsCleanupIp6Fragment(VOID)\n-{\n- PLIST_ENTRY link, next;\n- POVS_IP6FRAG_ENTRY entry;\n- LOCK_STATE_EX lockState;\n-\n- ip6FragThreadCtx.exit = 1;\n- KeSetEvent(&ip6FragThreadCtx.event, 0, FALSE);\n- KeWaitForSingleObject(ip6FragThreadCtx.threadObject, Executive,\n- KernelMode, FALSE, NULL);\n- ObDereferenceObject(ip6FragThreadCtx.threadObject);\n- NdisAcquireRWLockWrite(ovsIp6FragmentHashLockObj, &lockState, 0);\n- if (OvsIp6FragTable) {\n- for (int i = 0; i < IP6_FRAG_HASH_TABLE_SIZE && ip6TotalEntries; i++) {\n- LIST_FORALL_SAFE(&OvsIp6FragTable[i], link, next) {\n- entry = CONTAINING_RECORD(link, OVS_IP6FRAG_ENTRY, link);\n- OvsIp6FragmentEntryDelete(entry, FALSE);\n- }\n- }\n- OvsFreeMemoryWithTag(OvsIp6FragTable, OVS_IP6FRAG_POOL_TAG);\n- OvsIp6FragTable = NULL;\n- }\n- NdisReleaseRWLock(ovsIp6FragmentHashLockObj, &lockState);\n- NdisFreeRWLock(ovsIp6FragmentHashLockObj);\n- ovsIp6FragmentHashLockObj = NULL;\n-}\n-\n-PCHAR\n-OvsBuildNewIpv6Hdr(EthHdr *eth, POVS_IP6FRAG_ENTRY entry,\n- POVS_PACKET_HDR_INFO layers,\n- UINT32 *pktLen)\n-{\n- IPv6Hdr *ipHdr = NULL;\n- IPv6Hdr *newIpHdr = NULL;\n- PCHAR ipv6StdPtr = NULL;\n- PCHAR packetBuf = NULL;\n- UINT32 packetLen = 0;\n-\n- ipHdr = (IPv6Hdr *)((PCHAR)eth + layers->l3Offset);\n- if (layers->l4Offset + entry->totalLen > MAX_IPDATAGRAM_SIZE) {\n- return NULL;\n- }\n-\n- packetLen = (layers->l3Offset + sizeof(IPv6Hdr) +\n- entry->beforeFragHdrLen + entry->behindFragHdrLen + entry->totalLen);\n- packetBuf = (CHAR*)OvsAllocateMemoryWithTag(packetLen, OVS_IP6FRAG_POOL_TAG);\n- if (packetBuf == NULL) {\n- return NULL;\n- }\n- *pktLen = packetLen;\n-\n- NdisMoveMemory(packetBuf, eth, layers->l3Offset + sizeof(IPv6Hdr));\n- IPv6ExtHdr *extHdr = (IPv6ExtHdr *)((PCHAR)packetBuf + layers->l3Offset +\n- sizeof(IPv6Hdr));\n- ipv6StdPtr = (PCHAR)extHdr;\n- newIpHdr = (IPv6Hdr *)(packetBuf + layers->l3Offset);\n- newIpHdr->payload_len = htons(entry->beforeFragHdrLen +\n- entry->behindFragHdrLen + entry->totalLen);\n-\n- /* Copy extension header to new packet buf. */\n- if (entry->beforeFragHdrLen > 0) {\n- NdisMoveMemory(ipv6StdPtr, entry->beforeFragHdrBuf,\n- entry->beforeFragHdrLen);\n- }\n-\n- if (entry->behindFragHdrLen > 0) {\n- NdisMoveMemory((ipv6StdPtr + entry->beforeFragHdrLen),\n- entry->behindFragHdrBuf,\n- entry->behindFragHdrLen);\n- }\n-\n- /* Fix next header. */\n- if (entry->beforeFragHdrLen > 0) {\n- extHdr = (IPv6ExtHdr *)((PCHAR)extHdr + entry->priorFragEleOffset);\n- extHdr->nextHeader = ((IPv6FragHdr *)(entry->fragHdrBuf))->nextHeader;\n- }\n-\n- if (entry->beforeFragHdrLen == 0) {\n- if (entry->behindFragHdrLen == 0) {\n- newIpHdr->nexthdr = entry->fragKey.protocol;\n- } else {\n- newIpHdr->nexthdr = ((IPv6FragHdr *)(entry->fragHdrBuf))->nextHeader;\n- }\n- }\n-\n- return packetBuf;\n-}\n-\n-\n-NDIS_STATUS\n-OvsIpv6Reassemble(POVS_SWITCH_CONTEXT switchContext,\n- PNET_BUFFER_LIST *curNbl,\n- OvsCompletionList *completionList,\n- NDIS_SWITCH_PORT_ID sourcePort,\n- POVS_IP6FRAG_ENTRY entry,\n- POVS_PACKET_HDR_INFO layers)\n-{\n- NDIS_STATUS status = NDIS_STATUS_SUCCESS;\n- NDIS_STRING filterReason;\n- POVS_BUFFER_CONTEXT ctx;\n- PNET_BUFFER curNb;\n- EthHdr *eth;\n- CHAR *packetBuf;\n- POVS_FRAGMENT6_LIST head = NULL;\n- PNET_BUFFER_LIST newNbl = NULL;\n- UINT16 packetHeaderLen;\n- UINT32 packetLen;\n-\n- curNb = NET_BUFFER_LIST_FIRST_NB(*curNbl);\n- ASSERT(NET_BUFFER_NEXT_NB(curNb) == NULL);\n-\n- OVS_LOG_INFO(\"Process ipv6 reassemble, entry total length is %d.\",\n- entry->totalLen);\n- eth = (EthHdr*)NdisGetDataBuffer(curNb, layers->l4Offset,\n- NULL, 1, 0);\n- if (!eth) {\n- return NDIS_STATUS_INVALID_PACKET;\n- }\n-\n- packetBuf = OvsBuildNewIpv6Hdr(eth, entry, layers, &packetLen);\n- if (!packetBuf) {\n- return NDIS_STATUS_INVALID_PACKET;\n- }\n-\n- head = entry->head;\n- packetHeaderLen = (layers->l3Offset + sizeof(IPv6Hdr) +\n- entry->beforeFragHdrLen + entry->behindFragHdrLen);\n- while (head) {\n- if ((UINT32)(packetHeaderLen + (head->offset * 8) + head->len) > packetLen) {\n- status = NDIS_STATUS_INVALID_DATA;\n- goto cleanup;\n- }\n- NdisMoveMemory(packetBuf + packetHeaderLen + (head->offset * 8),\n- head->pbuff, head->len);\n- head = head->next;\n- }\n- /* Create new nbl from the flat buffer */\n- newNbl = OvsAllocateNBLFromBuffer(switchContext, packetBuf, packetLen);\n- if (newNbl == NULL) {\n- OVS_LOG_ERROR(\"Insufficient resources, failed to allocate newNbl\");\n- status = NDIS_STATUS_RESOURCES;\n- goto cleanup;\n- }\n-\n- /* Complete the fragment NBL */\n- ctx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(*curNbl);\n- if (ctx->flags & OVS_BUFFER_NEED_COMPLETE) {\n- RtlInitUnicodeString(&filterReason, L\"Complete last fragment\");\n- OvsAddPktCompletionList(completionList, TRUE, sourcePort, *curNbl, 1,\n- &filterReason);\n- } else {\n- OvsCompleteNBL(switchContext, *curNbl, TRUE);\n- }\n- /* Store mru in the ovs buffer context. */\n- ctx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(newNbl);\n- ctx->mru = entry->mru;\n- *curNbl = newNbl;\n-cleanup:\n- OvsFreeMemoryWithTag(packetBuf, OVS_IP6FRAG_POOL_TAG);\n- entry->markedForDelete = TRUE;\n- return status;\n-}\n-\n-NDIS_STATUS\n-OvsProcessIpv6Fragment(POVS_SWITCH_CONTEXT switchContext,\n- PNET_BUFFER_LIST *curNbl,\n- OvsCompletionList *completionList,\n- NDIS_SWITCH_PORT_ID sourcePort,\n- POVS_PACKET_HDR_INFO layers, ovs_be64 tunnelId,\n- OvsFlowKey *key)\n-{\n- NDIS_STATUS status = NDIS_STATUS_PENDING;\n- PNET_BUFFER curNb;\n- UINT32 hash;\n- UINT64 currentTime;\n- EthHdr *eth;\n- IPv6Hdr *ip6Hdr = NULL;\n- OVS_IP6FRAG_KEY frag6Key;\n- POVS_IP6FRAG_ENTRY entry;\n- POVS_FRAGMENT6_LIST fragStorage;\n- LOCK_STATE_EX htLockState;\n- IP6_PktExtHeader_Meta pktMeta = {0};\n-\n- curNb = NET_BUFFER_LIST_FIRST_NB(*curNbl);\n- ASSERT(NET_BUFFER_NEXT_NB(curNb) == NULL);\n-\n- OVS_LOG_INFO(\"Process ipv6 fragment.\");\n- eth = (EthHdr*)NdisGetDataBuffer(curNb, layers->l4Offset,\n- NULL, 1, 0);\n- if (eth == NULL) {\n- return NDIS_STATUS_INVALID_PACKET;\n- }\n-\n- ip6Hdr = (IPv6Hdr *)((PCHAR)eth + layers->l3Offset);\n- status = OvsGetPacketMeta(&pktMeta, eth, key, layers);\n- if (status != NDIS_STATUS_SUCCESS) {\n- return status;\n- }\n-\n- fragStorage = (POVS_FRAGMENT6_LIST)\n- OvsAllocateMemoryWithTag(sizeof(OVS_FRAGMENT6_LIST),\n- OVS_IP6FRAG_POOL_TAG);\n- if (fragStorage == NULL) {\n- OVS_LOG_ERROR(\"Insufficient resources, fail to allocate fragStorage\");\n- return NDIS_STATUS_RESOURCES;\n- }\n-\n- fragStorage->len = pktMeta.dataPayloadLen;\n- fragStorage->offset = pktMeta.fragOffset;\n- fragStorage->next = NULL;\n- fragStorage->pbuff = (CHAR *)OvsAllocateMemoryWithTag(fragStorage->len,\n- OVS_IP6FRAG_POOL_TAG);\n- if (fragStorage->pbuff == NULL) {\n- OVS_LOG_ERROR(\"Insufficient resources, fail to allocate pbuff\");\n- OvsFreeMemoryWithTag(fragStorage, OVS_IP6FRAG_POOL_TAG);\n- return NDIS_STATUS_RESOURCES;\n- }\n-\n- if (OvsGetPacketBytes(*curNbl, pktMeta.dataPayloadLen,\n- layers->l4Offset,\n- fragStorage->pbuff) == NULL) {\n- status = NDIS_STATUS_RESOURCES;\n- OVS_LOG_ERROR(\"Get packet bytes fail, pkt len is %d, offset is %d.\",\n- pktMeta.dataPayloadLen, layers->l4Offset);\n- goto payload_copy_error;\n- }\n-\n- frag6Key.sAddr = ip6Hdr->saddr;\n- frag6Key.dAddr = ip6Hdr->daddr;\n- frag6Key.tunnelId = tunnelId;\n- frag6Key.id = pktMeta.ident;\n-\n- hash = OvsGetIP6FragmentHash(&frag6Key);\n- entry = OvsLookupIP6Frag(&frag6Key, hash);\n- if (entry == NULL) {\n- entry = (POVS_IP6FRAG_ENTRY)\n- OvsAllocateMemoryWithTag(sizeof(OVS_IP6FRAG_ENTRY),\n- OVS_IP6FRAG_POOL_TAG);\n- if (entry == NULL) {\n- status = NDIS_STATUS_RESOURCES;\n- goto payload_copy_error;\n- }\n- /* Copy the fragmeny key. */\n- NdisZeroMemory(entry, sizeof(OVS_IP6FRAG_ENTRY));\n- NdisMoveMemory(&(entry->fragKey), &frag6Key, sizeof(OVS_IP6FRAG_KEY));\n- /* Init MRU. */\n- entry->mru = pktMeta.pktMru;\n- entry->recvdLen = fragStorage->len;\n- entry->head = entry->tail = fragStorage;\n- entry->numFragments = 1;\n-\n- if (!pktMeta.fragOffset) {\n- /* First packet, fragment offset is 0 */\n- OVS_LOG_INFO(\"before fragment extension header len:%d \"\n- \"fragment extension header len:%d \"\n- \"behind fragment extension header len :%d \"\n- \"last element before fragment offset %d\",\n- pktMeta.beforeFragExtHdrLen,\n- pktMeta.fragExtHdrLen,\n- pktMeta.behindFragExtHdrLen,\n- pktMeta.priorFragEleOffset);\n- /* We could get all ext header info from first fragment packet. */\n- status = OvsStorageIpv6ExtHeader(entry, pktMeta.beforeFragExtHdrLen,\n- pktMeta.fragExtHdrLen,\n- pktMeta.behindFragExtHdrLen,\n- pktMeta.priorFragEleOffset,\n- (PCHAR) eth, layers);\n- if (status != NDIS_STATUS_SUCCESS) {\n- OVS_LOG_INFO(\"StorageIpv6 header fails, parse failed.\");\n- OvsFreeMemoryWithTag(entry, OVS_IP6FRAG_POOL_TAG);\n- goto payload_copy_error;\n- }\n-\n- entry->fragKey.protocol = pktMeta.protocol;\n- OVS_LOG_INFO(\"First packet, protocol is %d.\",\n- entry->fragKey.protocol);\n- }\n-\n- if (!pktMeta.flags) {\n- /* It's the last fragment, it demonstrates the packet was arrived\n- * out of order, we calculate the complte packet total length. */\n- entry->totalLen = pktMeta.fragOffset * 8 + pktMeta.dataPayloadLen;\n- }\n-\n- NdisGetCurrentSystemTime((LARGE_INTEGER *)¤tTime);\n- entry->expiration = currentTime + IP6FRAG_ENTRY_TIMEOUT;\n-\n- /* Init the sync-lock. */\n- NdisAllocateSpinLock(&(entry->lockObj));\n- NdisAcquireRWLockWrite(ovsIp6FragmentHashLockObj, &htLockState, 0);\n- InsertHeadList(&OvsIp6FragTable[hash & IP6_FRAG_HASH_TABLE_MASK],\n- &entry->link);\n-\n- ip6TotalEntries++;\n- NdisReleaseRWLock(ovsIp6FragmentHashLockObj, &htLockState);\n- return NDIS_STATUS_PENDING;\n- } else {\n- /* Acquire the entry lock. */\n- NdisAcquireSpinLock(&(entry->lockObj));\n- NdisGetCurrentSystemTime((LARGE_INTEGER *)¤tTime);\n- if (currentTime > entry->expiration ||\n- (entry->numFragments == MAX_FRAGMENTS)) {\n- /* Mark the entry for delete. */\n- OVS_LOG_ERROR(\"Will delete the fragment numbers.\");\n- entry->markedForDelete = TRUE;\n- goto fragment_error;\n- }\n-\n- if (!pktMeta.fragOffset) {\n- status = OvsStorageIpv6ExtHeader(entry, pktMeta.behindFragExtHdrLen,\n- pktMeta.fragExtHdrLen,\n- pktMeta.behindFragExtHdrLen,\n- pktMeta.priorFragEleOffset,\n- (PCHAR) eth,\n- layers);\n- if (status != NDIS_STATUS_SUCCESS) {\n- OVS_LOG_ERROR(\"IPv6 Extension header not valid.\");\n- goto fragment_error;\n- }\n-\n- entry->fragKey.protocol = pktMeta.protocol;\n- }\n-\n- if (!pktMeta.flags) {\n- entry->totalLen = pktMeta.fragOffset * 8 + pktMeta.dataPayloadLen;\n- }\n-\n- /* Find the element offset just large than fragment and insert the\n- * fragment before it. */\n- POVS_FRAGMENT6_LIST next = entry->head;\n- POVS_FRAGMENT6_LIST prev = entry->tail;\n- if (prev != NULL && prev->offset < pktMeta.fragOffset) {\n- next = NULL;\n- goto found;\n- }\n- prev = NULL;\n- for (next = entry->head; next != NULL; next = next->next) {\n- if (next->offset > fragStorage->offset) {\n- break;\n- }\n- prev = next;\n- }\n-found:\n- /*Check for overlap. */\n- if (prev) {\n- /* i bytes overlap. */\n- int i = ((prev->offset * 8) + prev->len) - (fragStorage->offset * 8);\n- if (i > 0) {\n- OVS_LOG_ERROR(\"IPv6 fragment error, prev offset %d, pre len \"\n- \"%d, frag offset %d\",\n- prev->offset, prev->len, fragStorage->offset);\n- goto fragment_error;\n- }\n- }\n- if (next) {\n- /* i bytes overlap. */\n- int i = ((fragStorage->offset * 8) + fragStorage->len) -\n- (next->offset * 8);\n- if (i > 0) {\n- OVS_LOG_ERROR(\"IPv6 fragment error, frag offset %d, frag \"\n- \"len %d, next offset %d.\",\n- fragStorage->offset, fragStorage->len,\n- next->offset);\n- goto fragment_error;\n- }\n- }\n-\n- if (entry->recvdLen + fragStorage->len > entry->recvdLen) {\n- entry->recvdLen += fragStorage->len;\n- } else {\n- /* Overflow, ignore the fragment.*/\n- OVS_LOG_ERROR(\"IPv6 fragment error, entry recv len %d, frag \"\n- \"len %d.\", entry->recvdLen, fragStorage->len);\n- goto fragment_error;\n- }\n-\n- /*Insert. */\n- if (prev) {\n- prev->next = fragStorage;\n- fragStorage->next = next;\n- } else {\n- fragStorage->next = next;\n- entry->head = fragStorage;\n- }\n- if (!next) {\n- entry->tail = fragStorage;\n- }\n-\n- /*Update Maximum Receive Unit */\n- entry->mru = entry->mru > pktMeta.pktMru ? entry->mru : pktMeta.pktMru;\n- entry->numFragments++;\n-\n- OVS_LOG_INFO(\"Max mru is %d, entry total length %d, entry recv length %d, \"\n- \"extension header length is %d\", entry->mru,\n- entry->totalLen, entry->recvdLen,\n- entry->behindFragHdrLen);\n- if (entry->recvdLen == (entry->totalLen - entry->behindFragHdrLen)) {\n- /* when exist ipv6 extension field behind ipv6 fragment field,\n- * the ipv6 extension field will be regard as \"data\", the totalLen\n- * represent the \"fragment data length\" + \"ipv6 extension length\n- * behind fragment\". However, the recvdLen only represents the\n- * data length, thus when we judge is or not receive a complete\n- * packet, we should use\n- * (entry->totalLen - entry->behindFragHdrLen) == entry->recvdLen */\n- status = OvsIpv6Reassemble(switchContext, curNbl, completionList,\n- sourcePort, entry, layers);\n- }\n- NdisReleaseSpinLock(&(entry->lockObj));\n- return status;\n- }\n-\n-fragment_error:\n- status = NDIS_STATUS_INVALID_PACKET;\n- /* Release the entry lock. */\n- NdisReleaseSpinLock(&(entry->lockObj));\n-\n-payload_copy_error:\n- OVS_LOG_ERROR(\"Payload error, exits.\");\n- OvsFreeMemoryWithTag(fragStorage->pbuff, OVS_IP6FRAG_POOL_TAG);\n- OvsFreeMemoryWithTag(fragStorage, OVS_IP6FRAG_POOL_TAG);\n- return status;\n-}\n-\n-NDIS_STATUS\n-OvsGetPacketMeta(PIP6_PktExtHeader_Meta pktMeta, EthHdr *eth,\n- OvsFlowKey *key, POVS_PACKET_HDR_INFO layers)\n-{\n- IPv6Hdr *ip6Hdr = NULL;\n- IPv6ExtHdr *extHdr = NULL;\n- UINT8 nextHdr;\n-\n- ip6Hdr = (IPv6Hdr *)((PCHAR)eth + layers->l3Offset);\n- if (!ip6Hdr) {\n- return NDIS_STATUS_INVALID_PACKET;\n- }\n-\n- nextHdr = ip6Hdr->nexthdr;\n- pktMeta->firstHdr = nextHdr;\n-\n- if ((nextHdr == SOCKET_IPPROTO_HOPOPTS) ||\n- (nextHdr == SOCKET_IPPROTO_ROUTING) ||\n- (nextHdr == SOCKET_IPPROTO_DSTOPTS) ||\n- (nextHdr == SOCKET_IPPROTO_FRAGMENT)) {\n- extHdr = (IPv6ExtHdr *)((PCHAR)ip6Hdr + sizeof(IPv6Hdr));\n- pktMeta->firstHdrPtr = extHdr;\n- } else {\n- return NDIS_STATUS_INVALID_PACKET;\n- }\n-\n- for (;;) {\n- if ((nextHdr != SOCKET_IPPROTO_HOPOPTS)\n- && (nextHdr != SOCKET_IPPROTO_ROUTING)\n- && (nextHdr != SOCKET_IPPROTO_DSTOPTS)\n- && (nextHdr != SOCKET_IPPROTO_AH)\n- && (nextHdr != SOCKET_IPPROTO_FRAGMENT)) {\n- /*\n- * It's either a terminal header (e.g., TCP, UDP, Icmpv6) or one we\n- * don't understand. In either case, we're done with the\n- * packet, so use it to fill in 'nw_proto'.\n- */\n- pktMeta->protocol = nextHdr;\n- break;\n- }\n-\n- if (nextHdr == SOCKET_IPPROTO_HOPOPTS ||\n- nextHdr == SOCKET_IPPROTO_ROUTING ||\n- nextHdr == SOCKET_IPPROTO_DSTOPTS ||\n- nextHdr == SOCKET_IPPROTO_AH) {\n- UINT8 len = extHdr->hdrExtLen;\n- nextHdr = extHdr->nextHeader;\n- if (nextHdr == SOCKET_IPPROTO_FRAGMENT) {\n- pktMeta->beforeFragElePtr = (PCHAR)(extHdr);\n- }\n-\n- if (nextHdr == SOCKET_IPPROTO_AH) {\n- extHdr = (IPv6ExtHdr *)((PCHAR)extHdr + (len + 2) * 4);\n- pktMeta->extHdrTotalLen += ((len + 2) * 4);\n- } else {\n- extHdr = (IPv6ExtHdr *)((PCHAR)extHdr + (len + 1) * 8);\n- pktMeta->extHdrTotalLen += ((len + 1) * 8);\n- }\n- } else if (nextHdr == SOCKET_IPPROTO_FRAGMENT) {\n- IPv6FragHdr *fragHdr = (IPv6FragHdr *)extHdr;\n- pktMeta->ident = fragHdr->ident;\n- pktMeta->beforeFragExtHdrLen = pktMeta->extHdrTotalLen;\n- pktMeta->fragExtHdrLen = sizeof(IPv6FragHdr);\n- pktMeta->extHdrTotalLen += sizeof(IPv6FragHdr);\n- pktMeta->fragOffset = (ntohs(fragHdr->offlg)\n- & IP6F_OFF_HOST_ORDER_MASK) >> 3;\n- pktMeta->flags = ntohs(fragHdr->offlg) & 0x01;\n- nextHdr = extHdr->nextHeader;\n- extHdr = (IPv6ExtHdr *)((PCHAR)extHdr + sizeof(IPv6FragHdr));\n- if (key->ipv6Key.nwFrag == OVS_FRAG_TYPE_LATER) {\n- pktMeta->protocol = SOCKET_IPPROTO_FRAGMENT;\n- break;\n- }\n- }\n- }\n-\n- pktMeta->dataPayloadLen = (ntohs(ip6Hdr->payload_len) -\n- pktMeta->extHdrTotalLen);\n- OVS_LOG_INFO(\"playload len %d, extotalLen %d, datapyaload len %d.\",\n- ntohs(ip6Hdr->payload_len),\n- pktMeta->extHdrTotalLen,\n- pktMeta->dataPayloadLen);\n- pktMeta->behindFragExtHdrLen = (pktMeta->extHdrTotalLen -\n- pktMeta->beforeFragExtHdrLen -\n- pktMeta->fragExtHdrLen);\n- pktMeta->pktMru = (layers->l3Offset + sizeof(IPv6Hdr) +\n- ntohs(ip6Hdr->payload_len));\n- if (pktMeta->beforeFragElePtr) {\n- pktMeta->priorFragEleOffset = (UINT16)((PCHAR)pktMeta->beforeFragElePtr -\n- (PCHAR)pktMeta->firstHdrPtr);\n- }\n-\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-/*\n- *-----------------------------------------------------------------------------\n- * OvsStorageIpv6ExtHeader --\n- * In some scenario, we need to storage the ipv6 option header, this\n- * function is used to do it, we could divide ipv6 option field into\n- * three parts, including \"option field before fragment\n- * field\", \"fragment field\", \"option field behind fragment field\". The\n- * reason store extension header is that it's convenient to copy the\n- * specified to the fragment header.\n- *-----------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsStorageIpv6ExtHeader(POVS_IP6FRAG_ENTRY entry,\n- UINT16 beforeFragHdrLen,\n- UINT16 fragHdrLen,\n- UINT16 behindFragHdrLen,\n- UINT16 priorFragEleOffset,\n- CHAR *pktBuf,\n- POVS_PACKET_HDR_INFO layers)\n-{\n- NDIS_STATUS status = NDIS_STATUS_SUCCESS;\n-\n- if (beforeFragHdrLen) {\n- entry->beforeFragHdrBuf =\n- OvsAllocateMemoryWithTag(beforeFragHdrLen,\n- OVS_IP6FRAG_POOL_TAG);\n- if (entry->beforeFragHdrBuf == NULL) {\n- goto beforeFragHdrError;\n- }\n- entry->beforeFragHdrLen = beforeFragHdrLen;\n- entry->priorFragEleOffset = priorFragEleOffset;\n- }\n-\n- if (fragHdrLen) {\n- entry->fragHdrBuf = OvsAllocateMemoryWithTag(fragHdrLen,\n- OVS_IP6FRAG_POOL_TAG);\n- if (entry->fragHdrBuf == NULL) {\n- goto fragHdrError;\n- }\n- entry->fragHdrLen = fragHdrLen;\n- }\n-\n- if (behindFragHdrLen) {\n- entry->behindFragHdrBuf =\n- OvsAllocateMemoryWithTag(behindFragHdrLen,\n- OVS_IP6FRAG_POOL_TAG);\n- if (entry->behindFragHdrBuf == NULL) {\n- goto behindFragHdrError;\n- }\n- entry->behindFragHdrLen = behindFragHdrLen;\n- }\n-\n- if (entry->beforeFragHdrLen) {\n- NdisMoveMemory(entry->beforeFragHdrBuf,\n- pktBuf + layers->l3Offset + sizeof(IPv6Hdr),\n- entry->beforeFragHdrLen);\n- }\n-\n- if (entry->fragHdrLen) {\n- NdisMoveMemory(entry->fragHdrBuf,\n- (pktBuf + layers->l3Offset +\n- sizeof(IPv6Hdr) + beforeFragHdrLen),\n- entry->fragHdrLen);\n- }\n-\n- if (entry->behindFragHdrLen) {\n- NdisMoveMemory(entry->behindFragHdrBuf,\n- (pktBuf + layers->l3Offset + sizeof(IPv6Hdr)\n- + beforeFragHdrLen + fragHdrLen),\n- entry->behindFragHdrLen);\n- }\n-\n- return status;\n-\n-behindFragHdrError:\n-fragHdrError:\n- if (entry->fragHdrBuf) {\n- OvsFreeMemoryWithTag(entry->fragHdrBuf, OVS_IP6FRAG_POOL_TAG);\n- }\n-beforeFragHdrError:\n- if (entry->beforeFragHdrBuf) {\n- OvsFreeMemoryWithTag(entry->beforeFragHdrBuf, OVS_IP6FRAG_POOL_TAG);\n- }\n- status = NDIS_STATUS_RESOURCES;\n- OVS_LOG_ERROR(\"Storage header fails due to header.\");\n- return status;\n-}\ndiff --git a/datapath-windows/ovsext/Ip6Fragment.h b/datapath-windows/ovsext/Ip6Fragment.h\ndeleted file mode 100644\nindex f978bf5c3..000000000\n--- a/datapath-windows/ovsext/Ip6Fragment.h\n+++ /dev/null\n@@ -1,111 +0,0 @@\n-/*\n- * Copyright (c) 2022 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#ifndef __IP6FRAGMENT_H_\n-#define __IP6FRAGMENT_H_ 1\n-#include \"PacketIO.h\"\n-\n-typedef struct _OVS_FRAGMENT6_LIST {\n- CHAR *pbuff;\n- UINT16 len; /* Fragment data length. */\n- UINT16 offset; /* Fragment data offset. */\n- struct _OVS_FRAGMENT6_LIST *next;\n-} OVS_FRAGMENT6_LIST, *POVS_FRAGMENT6_LIST;\n-\n-typedef struct _OVS_IP6FRAG_KEY {\n- UINT8 protocol;\n- UINT8 pad_1[3]; /* Align the structure to address boundaries.*/\n- UINT32 id;\n- struct in6_addr sAddr;\n- struct in6_addr dAddr;\n- ovs_be64 tunnelId;\n-} OVS_IP6FRAG_KEY, *POVS_IP6FRAG_KEY;\n-\n-typedef struct _OVS_IP6FRAG_ENTRY {\n- NDIS_SPIN_LOCK lockObj; /* To access the entry. */\n- BOOLEAN markedForDelete;\n- UINT8 numFragments;\n- UINT16 totalLen; /* The packet data total length(not\n- * include ipv6 header and opt header length) before\n- * fragment */\n- UINT16 recvdLen; /* Total data length packet contains has received */\n- UINT16 mru; /* Max receive unit(it's the whole ethernet frame\n- * packet length), it will be used in sent out before forward */\n- UINT64 expiration;\n- /* refer https://www.rfc-editor.org/rfc/rfc8200.html */\n- PCHAR beforeFragHdrBuf;/* ipv6 extension header buf before fragment field */\n- UINT16 beforeFragHdrLen;\n- UINT16 priorFragEleOffset;/* The last element before fragment field offset */\n- PCHAR fragHdrBuf;\n- UINT16 fragHdrLen;\n- PCHAR behindFragHdrBuf;/* ipv6 extension header buf behind fragment field */\n- UINT16 behindFragHdrLen;\n- OVS_IP6FRAG_KEY fragKey;\n- POVS_FRAGMENT6_LIST head;\n- POVS_FRAGMENT6_LIST tail;\n- LIST_ENTRY link;\n-} OVS_IP6FRAG_ENTRY, *POVS_IP6FRAG_ENTRY;\n-\n-typedef struct _IP6_PktExtHeader_Meta {\n- UINT8 firstHdr;\n- UINT8 protocol;\n- UINT16 beforeFragExtHdrLen;\n- UINT16 fragExtHdrLen;\n- UINT16 behindFragExtHdrLen;\n- UINT16 extHdrTotalLen;\n- UINT16 dataPayloadLen;/* Ipv6 data length, not include extension header */\n- UINT16 fragOffset;\n- UINT16 priorFragEleOffset;\n- UINT16 flags;\n- UINT16 pktMru;\n- UINT32 ident;\n- PCHAR beforeFragElePtr;\n- IPv6ExtHdr *firstHdrPtr;\n-} IP6_PktExtHeader_Meta, *PIP6_PktExtHeader_Meta;\n-\n-typedef struct _OVS_IP6FRAG_THREAD_CTX {\n- KEVENT event;\n- PVOID threadObject;\n- UINT32 exit;\n-} OVS_IP6FRAG_THREAD_CTX, *POVS_IP6FRAG_THREAD_CTX;\n-\n-#define IP6_FRAG_HASH_TABLE_SIZE ((UINT32)1 << 10)\n-#define IP6_FRAG_HASH_TABLE_MASK (IP6_FRAG_HASH_TABLE_SIZE - 1)\n-\n-#define IP6FRAG_ENTRY_TIMEOUT 300000000LL\n-#define IP6FRAG_CLEANUP_INTERVAL IP6FRAG_ENTRY_TIMEOUT * 2 /*1m.*/\n-\n-NDIS_STATUS OvsProcessIpv6Fragment(POVS_SWITCH_CONTEXT switchContext,\n- PNET_BUFFER_LIST *curNbl,\n- OvsCompletionList *completionList,\n- NDIS_SWITCH_PORT_ID sourcePort,\n- POVS_PACKET_HDR_INFO layers,\n- ovs_be64 tunnelId, OvsFlowKey *key);\n-NDIS_STATUS OvsStorageIpv6ExtHeader(POVS_IP6FRAG_ENTRY entry,\n- UINT16 beforeFragHdrLen,\n- UINT16 fragHdrLen,\n- UINT16 behindFragHdrLen,\n- UINT16 priorFragEleOffset,\n- CHAR *pktBuf,\n- POVS_PACKET_HDR_INFO layers);\n-NDIS_STATUS OvsInitIp6Fragment(POVS_SWITCH_CONTEXT context);\n-VOID OvsCleanupIp6Fragment(VOID);\n-NDIS_STATUS OvsGetPacketMeta(PIP6_PktExtHeader_Meta pktMeta, EthHdr *eth,\n- OvsFlowKey *key, POVS_PACKET_HDR_INFO layers);\n-PCHAR OvsBuildNewIpv6Hdr(EthHdr *eth, POVS_IP6FRAG_ENTRY entry,\n- POVS_PACKET_HDR_INFO layers, UINT32 *pktLen);\n-\n-#endif //_IP6FRAGMENT_H_\ndiff --git a/datapath-windows/ovsext/IpFragment.c b/datapath-windows/ovsext/IpFragment.c\ndeleted file mode 100644\nindex afb8e50d6..000000000\n--- a/datapath-windows/ovsext/IpFragment.c\n+++ /dev/null\n@@ -1,526 +0,0 @@\n-/*\n- * Copyright (c) 2017 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#include \"Conntrack.h\"\n-#include \"Debug.h\"\n-#include \"IpFragment.h\"\n-#include \"Jhash.h\"\n-#include \"Offload.h\"\n-#include \"PacketParser.h\"\n-\n-#ifdef OVS_DBG_MOD\n-#undef OVS_DBG_MOD\n-#endif\n-#define OVS_DBG_MOD OVS_DBG_IPFRAG\n-\n-#define MIN_FRAGMENT_SIZE 400\n-#define MAX_IPDATAGRAM_SIZE 65535\n-#define MAX_FRAGMENTS MAX_IPDATAGRAM_SIZE/MIN_FRAGMENT_SIZE + 1\n-\n-/* Function declarations */\n-static KSTART_ROUTINE OvsIpFragmentEntryCleaner;\n-static VOID OvsIpFragmentEntryDelete(POVS_IPFRAG_ENTRY entry, BOOLEAN checkExpiry);\n-\n-/* Global and static variables */\n-static OVS_IPFRAG_THREAD_CTX ipFragThreadCtx;\n-static PNDIS_RW_LOCK_EX ovsIpFragmentHashLockObj;\n-static UINT64 ipTotalEntries;\n-static PLIST_ENTRY OvsIpFragTable;\n-\n-NDIS_STATUS\n-OvsInitIpFragment(POVS_SWITCH_CONTEXT context)\n-{\n-\n- NDIS_STATUS status;\n- HANDLE threadHandle = NULL;\n-\n- /* Init the sync-lock */\n- ovsIpFragmentHashLockObj = NdisAllocateRWLock(context->NdisFilterHandle);\n- if (ovsIpFragmentHashLockObj == NULL) {\n- return STATUS_INSUFFICIENT_RESOURCES;\n- }\n-\n- /* Init the Hash Buffer */\n- OvsIpFragTable = OvsAllocateMemoryWithTag(sizeof(LIST_ENTRY)\n- * IP_FRAG_HASH_TABLE_SIZE,\n- OVS_IPFRAG_POOL_TAG);\n- if (OvsIpFragTable == NULL) {\n- NdisFreeRWLock(ovsIpFragmentHashLockObj);\n- ovsIpFragmentHashLockObj = NULL;\n- return STATUS_INSUFFICIENT_RESOURCES;\n- }\n-\n- for (int i = 0; i < IP_FRAG_HASH_TABLE_SIZE; i++) {\n- InitializeListHead(&OvsIpFragTable[i]);\n- }\n-\n- /* Init Cleaner Thread */\n- KeInitializeEvent(&ipFragThreadCtx.event, NotificationEvent, FALSE);\n- status = PsCreateSystemThread(&threadHandle, SYNCHRONIZE, NULL, NULL,\n- NULL, OvsIpFragmentEntryCleaner,\n- &ipFragThreadCtx);\n-\n- if (status != STATUS_SUCCESS) {\n- OvsFreeMemoryWithTag(OvsIpFragTable, OVS_IPFRAG_POOL_TAG);\n- OvsIpFragTable = NULL;\n- NdisFreeRWLock(ovsIpFragmentHashLockObj);\n- ovsIpFragmentHashLockObj = NULL;\n- return status;\n- }\n-\n- ObReferenceObjectByHandle(threadHandle, SYNCHRONIZE, NULL, KernelMode,\n- &ipFragThreadCtx.threadObject, NULL);\n- ZwClose(threadHandle);\n- threadHandle = NULL;\n- return STATUS_SUCCESS;\n-}\n-\n-static __inline UINT32\n-OvsGetIPFragmentHash(POVS_IPFRAG_KEY fragKey)\n-{\n- UINT32 arr[6];\n- arr[0] = (UINT32)fragKey->protocol;\n- arr[1] = (UINT32)fragKey->id;\n- arr[2] = (UINT32)fragKey->sAddr;\n- arr[3] = (UINT32)fragKey->dAddr;\n- arr[4] = (UINT32)((fragKey->tunnelId & 0xFFFFFFFF00000000LL) >> 32);\n- arr[5] = (UINT32)(fragKey->tunnelId & 0xFFFFFFFFLL);\n- return OvsJhashWords(arr, 6, OVS_HASH_BASIS);\n-}\n-\n-static __inline POVS_IPFRAG_ENTRY\n-OvsLookupIPFrag(POVS_IPFRAG_KEY fragKey, UINT32 hash)\n-{\n- POVS_IPFRAG_ENTRY entry;\n- PLIST_ENTRY link;\n- LOCK_STATE_EX lockState;\n-\n- NdisAcquireRWLockRead(ovsIpFragmentHashLockObj, &lockState, 0);\n- LIST_FORALL(&OvsIpFragTable[hash & IP_FRAG_HASH_TABLE_MASK], link) {\n- entry = CONTAINING_RECORD(link, OVS_IPFRAG_ENTRY, link);\n- NdisAcquireSpinLock(&(entry->lockObj));\n- if (entry->fragKey.dAddr == fragKey->dAddr &&\n- entry->fragKey.sAddr == fragKey->sAddr &&\n- entry->fragKey.id == fragKey->id &&\n- entry->fragKey.protocol == fragKey->protocol &&\n- entry->fragKey.tunnelId == fragKey->tunnelId) {\n- NdisReleaseSpinLock(&(entry->lockObj));\n- NdisReleaseRWLock(ovsIpFragmentHashLockObj, &lockState);\n- return entry;\n- }\n- NdisReleaseSpinLock(&(entry->lockObj));\n- }\n- NdisReleaseRWLock(ovsIpFragmentHashLockObj, &lockState);\n- return NULL;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsIpv4Reassemble\n- * Reassemble the ipv4 fragments and return newNbl on success.\n- * Should be called after acquiring the lockObj for the entry.\n- *----------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsIpv4Reassemble(POVS_SWITCH_CONTEXT switchContext,\n- PNET_BUFFER_LIST *curNbl,\n- OvsCompletionList *completionList,\n- NDIS_SWITCH_PORT_ID sourcePort,\n- POVS_IPFRAG_ENTRY entry,\n- POVS_PACKET_HDR_INFO layers)\n-{\n- NDIS_STATUS status = NDIS_STATUS_SUCCESS;\n- NDIS_STRING filterReason;\n- POVS_BUFFER_CONTEXT ctx;\n- PNET_BUFFER curNb;\n- EthHdr *eth;\n- IPHdr *ipHdr, *newIpHdr;\n- CHAR *packetBuf;\n- POVS_FRAGMENT_LIST head = NULL;\n- PNET_BUFFER_LIST newNbl = NULL;\n- UINT16 ipHdrLen, packetHeader;\n- UINT32 packetLen;\n-\n- curNb = NET_BUFFER_LIST_FIRST_NB(*curNbl);\n- ASSERT(NET_BUFFER_NEXT_NB(curNb) == NULL);\n-\n- eth = (EthHdr*)NdisGetDataBuffer(curNb, layers->l4Offset,\n- NULL, 1, 0);\n- if (eth == NULL) {\n- return NDIS_STATUS_INVALID_PACKET;\n- }\n-\n- ipHdr = (IPHdr *)((PCHAR)eth + layers->l3Offset);\n- ipHdrLen = ipHdr->ihl * 4;\n- if (ipHdrLen + entry->totalLen > MAX_IPDATAGRAM_SIZE) {\n- return NDIS_STATUS_INVALID_LENGTH;\n- }\n- packetLen = layers->l3Offset + ipHdrLen + entry->totalLen;\n- packetBuf = (CHAR*)OvsAllocateMemoryWithTag(packetLen,\n- OVS_IPFRAG_POOL_TAG);\n- if (packetBuf == NULL) {\n- OVS_LOG_ERROR(\"Insufficient resources, failed to allocate packetBuf\");\n- return NDIS_STATUS_RESOURCES;\n- }\n-\n- /* copy Ethernet header */\n- NdisMoveMemory(packetBuf, eth, layers->l3Offset);\n- /* copy ipv4 header to packet buff */\n- NdisMoveMemory(packetBuf + layers->l3Offset, ipHdr, ipHdrLen);\n-\n- /* update new ip header */\n- newIpHdr = (IPHdr *)(packetBuf + layers->l3Offset);\n- newIpHdr->frag_off = 0;\n- newIpHdr->tot_len = htons(packetLen - layers->l3Offset);\n- newIpHdr->check = 0;\n- newIpHdr->check = IPChecksum((UINT8 *)packetBuf + layers->l3Offset,\n- ipHdrLen, 0);\n- packetHeader = layers->l3Offset + ipHdrLen;\n- head = entry->head;\n- while (head) {\n- if ((UINT32)(packetHeader + head->offset) > packetLen) {\n- status = NDIS_STATUS_INVALID_DATA;\n- goto cleanup;\n- }\n- NdisMoveMemory(packetBuf + packetHeader + head->offset,\n- head->pbuff, head->len);\n- head = head->next;\n- }\n- /* Create new nbl from the flat buffer */\n- newNbl = OvsAllocateNBLFromBuffer(switchContext, packetBuf, packetLen);\n- if (newNbl == NULL) {\n- OVS_LOG_ERROR(\"Insufficient resources, failed to allocate newNbl\");\n- status = NDIS_STATUS_RESOURCES;\n- goto cleanup;\n- }\n-\n- /* Complete the fragment NBL */\n- ctx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(*curNbl);\n- if (ctx->flags & OVS_BUFFER_NEED_COMPLETE) {\n- RtlInitUnicodeString(&filterReason, L\"Complete last fragment\");\n- OvsAddPktCompletionList(completionList, TRUE, sourcePort, *curNbl, 1,\n- &filterReason);\n- } else {\n- OvsCompleteNBL(switchContext, *curNbl, TRUE);\n- }\n- /* Store mru in the ovs buffer context. */\n- ctx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(newNbl);\n- ctx->mru = entry->mru;\n- *curNbl = newNbl;\n-cleanup:\n- OvsFreeMemoryWithTag(packetBuf, OVS_IPFRAG_POOL_TAG);\n- entry->markedForDelete = TRUE;\n- return status;\n-}\n-/*\n- *----------------------------------------------------------------------------\n- * OvsProcessIpv4Fragment\n- * Reassemble the fragments once all the fragments are received and\n- * return NDIS_STATUS_PENDING for the pending fragments\n- * XXX - Instead of copying NBls, Keep the NBLs in limbo state.\n- *----------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsProcessIpv4Fragment(POVS_SWITCH_CONTEXT switchContext,\n- PNET_BUFFER_LIST *curNbl,\n- OvsCompletionList *completionList,\n- NDIS_SWITCH_PORT_ID sourcePort,\n- POVS_PACKET_HDR_INFO layers,\n- ovs_be64 tunnelId)\n-{\n- NDIS_STATUS status = NDIS_STATUS_PENDING;\n- PNET_BUFFER curNb;\n- UINT16 offset, flags;\n- UINT16 payloadLen, ipHdrLen;\n- UINT32 hash;\n- UINT64 currentTime;\n- EthHdr *eth;\n- IPHdr *ipHdr;\n- OVS_IPFRAG_KEY fragKey;\n- POVS_IPFRAG_ENTRY entry;\n- POVS_FRAGMENT_LIST fragStorage;\n- LOCK_STATE_EX htLockState;\n-\n- curNb = NET_BUFFER_LIST_FIRST_NB(*curNbl);\n- ASSERT(NET_BUFFER_NEXT_NB(curNb) == NULL);\n-\n- eth = (EthHdr*)NdisGetDataBuffer(curNb, layers->l4Offset,\n- NULL, 1, 0);\n- if (eth == NULL) {\n- return NDIS_STATUS_INVALID_PACKET;\n- }\n-\n- ipHdr = (IPHdr *)((PCHAR)eth + layers->l3Offset);\n- ipHdrLen = ipHdr->ihl * 4;\n- payloadLen = ntohs(ipHdr->tot_len) - ipHdrLen;\n- offset = ntohs(ipHdr->frag_off) & IP_OFFSET;\n- offset <<= 3;\n- flags = ntohs(ipHdr->frag_off) & IP_MF;\n-\n- /*Copy fragment specific fields. */\n- fragKey.protocol = ipHdr->protocol;\n- fragKey.id = ipHdr->id;\n- fragKey.sAddr = ipHdr->saddr;\n- fragKey.dAddr = ipHdr->daddr;\n- fragKey.tunnelId = tunnelId;\n- /* Padding. */\n- NdisZeroMemory(&fragKey.pad_1, 3);\n- fragKey.pad_2 = 0;\n-\n- fragStorage = (POVS_FRAGMENT_LIST )\n- OvsAllocateMemoryWithTag(sizeof(OVS_FRAGMENT_LIST),\n- OVS_IPFRAG_POOL_TAG);\n- if (fragStorage == NULL) {\n- OVS_LOG_ERROR(\"Insufficient resources, fail to allocate fragStorage\");\n- return NDIS_STATUS_RESOURCES;\n- }\n-\n- fragStorage->pbuff = (CHAR *)OvsAllocateMemoryWithTag(payloadLen,\n- OVS_IPFRAG_POOL_TAG);\n- if (fragStorage->pbuff == NULL) {\n- OVS_LOG_ERROR(\"Insufficient resources, fail to allocate pbuff\");\n- OvsFreeMemoryWithTag(fragStorage, OVS_IPFRAG_POOL_TAG);\n- return NDIS_STATUS_RESOURCES;\n- }\n-\n- /* Copy payload from nbl to fragment storage. */\n- if (OvsGetPacketBytes(*curNbl, payloadLen, layers->l3Offset + ipHdrLen,\n- fragStorage->pbuff) == NULL) {\n- status = NDIS_STATUS_RESOURCES;\n- goto payload_copy_error;\n- }\n- fragStorage->len = payloadLen;\n- fragStorage->offset = offset;\n- fragStorage->next = NULL;\n- hash = OvsGetIPFragmentHash(&fragKey);\n- entry = OvsLookupIPFrag(&fragKey, hash);\n- if (entry == NULL) {\n- entry = (POVS_IPFRAG_ENTRY)\n- OvsAllocateMemoryWithTag(sizeof(OVS_IPFRAG_ENTRY),\n- OVS_IPFRAG_POOL_TAG);\n- if (entry == NULL) {\n- status = NDIS_STATUS_RESOURCES;\n- goto payload_copy_error;\n- }\n- /* Copy the fragmeny key. */\n- NdisZeroMemory(entry, sizeof(OVS_IPFRAG_ENTRY));\n- NdisMoveMemory(&(entry->fragKey), &fragKey,\n- sizeof(OVS_IPFRAG_KEY));\n- /* Init MRU. */\n- entry->mru = layers->l3Offset + ipHdrLen + payloadLen;\n- entry->recvdLen += fragStorage->len;\n- entry->head = entry->tail = fragStorage;\n- entry->numFragments = 1;\n- if (!flags) {\n- entry->totalLen = offset + payloadLen;\n- }\n- NdisGetCurrentSystemTime((LARGE_INTEGER *)¤tTime);\n- entry->expiration = currentTime + IPFRAG_ENTRY_TIMEOUT;\n-\n- /* Init the sync-lock. */\n- NdisAllocateSpinLock(&(entry->lockObj));\n- NdisAcquireRWLockWrite(ovsIpFragmentHashLockObj, &htLockState, 0);\n- InsertHeadList(&OvsIpFragTable[hash & IP_FRAG_HASH_TABLE_MASK],\n- &entry->link);\n-\n- ipTotalEntries++;\n- NdisReleaseRWLock(ovsIpFragmentHashLockObj, &htLockState);\n- return NDIS_STATUS_PENDING;\n- } else {\n- /* Acquire the entry lock. */\n- NdisAcquireSpinLock(&(entry->lockObj));\n- NdisGetCurrentSystemTime((LARGE_INTEGER *)¤tTime);\n- if (currentTime > entry->expiration || entry->numFragments == MAX_FRAGMENTS) {\n- /* Mark the entry for delete. */\n- entry->markedForDelete = TRUE;\n- goto fragment_error;\n- }\n- POVS_FRAGMENT_LIST next = entry->head;\n- POVS_FRAGMENT_LIST prev = entry->tail;\n- if (prev != NULL && prev->offset < offset) {\n- next = NULL;\n- goto found;\n- }\n- prev = NULL;\n- for (next = entry->head; next != NULL; next = next->next) {\n- if (next->offset > fragStorage->offset) {\n- break;\n- }\n- prev = next;\n- }\n-found:\n- /*Check for overlap. */\n- if (prev) {\n- /* i bytes overlap. */\n- int i = (prev->offset + prev->len) - fragStorage->offset;\n- if (i > 0) {\n- goto fragment_error;\n- }\n- }\n- if (next) {\n- /* i bytes overlap. */\n- int i = (fragStorage->offset + fragStorage->len) - next->offset;\n- if (i > 0) {\n- goto fragment_error;\n- }\n- }\n-\n- if (entry->recvdLen + fragStorage->len > entry->recvdLen) {\n- entry->recvdLen += fragStorage->len;\n- } else {\n- /* Overflow, ignore the fragment.*/\n- goto fragment_error;\n- }\n-\n- /*Insert. */\n- if (prev) {\n- prev->next = fragStorage;\n- fragStorage->next = next;\n- } else {\n- fragStorage->next = next;\n- entry->head = fragStorage;\n- }\n- if (!next) {\n- entry->tail = fragStorage;\n- }\n-\n- /*Update Maximum Receive Unit */\n- entry->mru = entry->mru > (layers->l3Offset + ipHdrLen + payloadLen) ?\n- entry->mru : (layers->l3Offset + ipHdrLen + payloadLen);\n- entry->numFragments++;\n- if (!flags) {\n- entry->totalLen = offset + payloadLen;\n- }\n- if (entry->recvdLen == entry->totalLen) {\n- status = OvsIpv4Reassemble(switchContext, curNbl, completionList,\n- sourcePort, entry, layers);\n- }\n- NdisReleaseSpinLock(&(entry->lockObj));\n- return status;\n- }\n-fragment_error:\n- status = NDIS_STATUS_INVALID_PACKET;\n- /* Release the entry lock. */\n- NdisReleaseSpinLock(&(entry->lockObj));\n-payload_copy_error:\n- OvsFreeMemoryWithTag(fragStorage->pbuff, OVS_IPFRAG_POOL_TAG);\n- OvsFreeMemoryWithTag(fragStorage, OVS_IPFRAG_POOL_TAG);\n- return status;\n-}\n-\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsIpFragmentEntryCleaner\n- * Runs periodically and cleans up the Ip Fragment table\n- * Interval is selected as twice the entry timeout\n- *----------------------------------------------------------------------------\n- */\n-static VOID\n-OvsIpFragmentEntryCleaner(PVOID data)\n-{\n-\n- POVS_IPFRAG_THREAD_CTX context = (POVS_IPFRAG_THREAD_CTX)data;\n- PLIST_ENTRY link, next;\n- POVS_IPFRAG_ENTRY entry;\n- LOCK_STATE_EX lockState;\n- BOOLEAN success = TRUE;\n-\n- while (success) {\n- if (ovsIpFragmentHashLockObj == NULL) {\n- /* Lock has been freed by 'OvsCleanupIpFragment()' */\n- break;\n- }\n- NdisAcquireRWLockWrite(ovsIpFragmentHashLockObj, &lockState, 0);\n- if (context->exit) {\n- NdisReleaseRWLock(ovsIpFragmentHashLockObj, &lockState);\n- break;\n- }\n-\n- /* Set the timeout for the thread and cleanup. */\n- UINT64 currentTime, threadSleepTimeout;\n- NdisGetCurrentSystemTime((LARGE_INTEGER *)¤tTime);\n- threadSleepTimeout = currentTime + IPFRAG_CLEANUP_INTERVAL;\n- for (int i = 0; i < IP_FRAG_HASH_TABLE_SIZE && ipTotalEntries; i++) {\n- LIST_FORALL_SAFE(&OvsIpFragTable[i], link, next) {\n- entry = CONTAINING_RECORD(link, OVS_IPFRAG_ENTRY, link);\n- OvsIpFragmentEntryDelete(entry, TRUE);\n- }\n- }\n-\n- NdisReleaseRWLock(ovsIpFragmentHashLockObj, &lockState);\n- KeWaitForSingleObject(&context->event, Executive, KernelMode,\n- FALSE, (LARGE_INTEGER *)&threadSleepTimeout);\n- }\n-\n- PsTerminateSystemThread(STATUS_SUCCESS);\n-}\n-\n-static VOID\n-OvsIpFragmentEntryDelete(POVS_IPFRAG_ENTRY entry, BOOLEAN checkExpiry)\n-{\n- NdisAcquireSpinLock(&(entry->lockObj));\n- if (!entry->markedForDelete && checkExpiry) {\n- UINT64 currentTime;\n- NdisGetCurrentSystemTime((LARGE_INTEGER *)¤tTime);\n- if (entry->expiration > currentTime) {\n- NdisReleaseSpinLock(&(entry->lockObj));\n- return;\n- }\n- }\n-\n- POVS_FRAGMENT_LIST head = entry->head;\n- POVS_FRAGMENT_LIST temp = NULL;\n- while (head) {\n- temp = head;\n- head = head->next;\n- OvsFreeMemoryWithTag(temp->pbuff, OVS_IPFRAG_POOL_TAG);\n- OvsFreeMemoryWithTag(temp, OVS_IPFRAG_POOL_TAG);\n- }\n- RemoveEntryList(&entry->link);\n- ipTotalEntries--;\n- NdisReleaseSpinLock(&(entry->lockObj));\n- NdisFreeSpinLock(&(entry->lockObj));\n- OvsFreeMemoryWithTag(entry, OVS_IPFRAG_POOL_TAG);\n-}\n-\n-VOID\n-OvsCleanupIpFragment(VOID)\n-{\n- PLIST_ENTRY link, next;\n- POVS_IPFRAG_ENTRY entry;\n- LOCK_STATE_EX lockState;\n-\n- ipFragThreadCtx.exit = 1;\n- KeSetEvent(&ipFragThreadCtx.event, 0, FALSE);\n- KeWaitForSingleObject(ipFragThreadCtx.threadObject, Executive,\n- KernelMode, FALSE, NULL);\n- ObDereferenceObject(ipFragThreadCtx.threadObject);\n- NdisAcquireRWLockWrite(ovsIpFragmentHashLockObj, &lockState, 0);\n- if (OvsIpFragTable) {\n- for (int i = 0; i < IP_FRAG_HASH_TABLE_SIZE && ipTotalEntries; i++) {\n- LIST_FORALL_SAFE(&OvsIpFragTable[i], link, next) {\n- entry = CONTAINING_RECORD(link, OVS_IPFRAG_ENTRY, link);\n- OvsIpFragmentEntryDelete(entry, FALSE);\n- }\n- }\n- OvsFreeMemoryWithTag(OvsIpFragTable, OVS_IPFRAG_POOL_TAG);\n- OvsIpFragTable = NULL;\n- }\n- NdisReleaseRWLock(ovsIpFragmentHashLockObj, &lockState);\n- NdisFreeRWLock(ovsIpFragmentHashLockObj);\n- ovsIpFragmentHashLockObj = NULL;\n- }\ndiff --git a/datapath-windows/ovsext/IpFragment.h b/datapath-windows/ovsext/IpFragment.h\ndeleted file mode 100644\nindex 433bad876..000000000\n--- a/datapath-windows/ovsext/IpFragment.h\n+++ /dev/null\n@@ -1,75 +0,0 @@\n-/*\n- * Copyright (c) 2017 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#ifndef __IPFRAGMENT_H_\n-#define __IPFRAGMENT_H_ 1\n-#include \"PacketIO.h\"\n-\n-typedef struct _OVS_FRAGMENT_LIST {\n- CHAR *pbuff;\n- UINT16 len;\n- UINT16 offset;\n- struct _OVS_FRAGMENT_LIST *next;\n-} OVS_FRAGMENT_LIST, *POVS_FRAGMENT_LIST;\n-\n-typedef struct _OVS_IPFRAG_KEY {\n- UINT8 protocol;\n- UINT8 pad_1[3]; /* Align the structure to address boundaries.*/\n- UINT16 id;\n- UINT16 pad_2; /* Align the structure to address boundaries.*/\n- UINT32 sAddr;\n- UINT32 dAddr;\n- ovs_be64 tunnelId;\n-} OVS_IPFRAG_KEY, *POVS_IPFRAG_KEY;\n-\n-typedef struct _OVS_IPFRAG_ENTRY {\n- NDIS_SPIN_LOCK lockObj; /* To access the entry. */\n- BOOLEAN markedForDelete;\n- UINT8 numFragments;\n- UINT16 totalLen;\n- UINT16 recvdLen;\n- UINT16 mru;\n- UINT64 expiration;\n- OVS_IPFRAG_KEY fragKey;\n- POVS_FRAGMENT_LIST head;\n- POVS_FRAGMENT_LIST tail;\n- LIST_ENTRY link;\n-} OVS_IPFRAG_ENTRY, *POVS_IPFRAG_ENTRY;\n-\n-typedef struct _OVS_IPFRAG_THREAD_CTX {\n- KEVENT event;\n- PVOID threadObject;\n- UINT32 exit;\n-} OVS_IPFRAG_THREAD_CTX, *POVS_IPFRAG_THREAD_CTX;\n-\n-#define IP_FRAG_HASH_TABLE_SIZE ((UINT32)1 << 10)\n-#define IP_FRAG_HASH_TABLE_MASK (IP_FRAG_HASH_TABLE_SIZE - 1)\n-/*30s -Sufficient time to receive all fragments.*/\n-#define IPFRAG_ENTRY_TIMEOUT 300000000LL\n-#define IPFRAG_CLEANUP_INTERVAL IPFRAG_ENTRY_TIMEOUT * 2 /*1m.*/\n-PNET_BUFFER_LIST OvsIpv4FragmentNBL(PVOID ovsContext,\n- PNET_BUFFER_LIST nbl,\n- UINT16 mru);\n-\n-NDIS_STATUS OvsProcessIpv4Fragment(POVS_SWITCH_CONTEXT switchContext,\n- PNET_BUFFER_LIST *curNbl,\n- OvsCompletionList *completionList,\n- NDIS_SWITCH_PORT_ID sourcePort,\n- POVS_PACKET_HDR_INFO layers,\n- ovs_be64 tunnelId);\n-NDIS_STATUS OvsInitIpFragment(POVS_SWITCH_CONTEXT context);\n-VOID OvsCleanupIpFragment(VOID);\n-#endif /* __IPFRAGMENT_H_ */\ndiff --git a/datapath-windows/ovsext/IpHelper.c b/datapath-windows/ovsext/IpHelper.c\ndeleted file mode 100644\nindex b8866bed9..000000000\n--- a/datapath-windows/ovsext/IpHelper.c\n+++ /dev/null\n@@ -1,2257 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#include \"precomp.h\"\n-#include \"IpHelper.h\"\n-#include \"Switch.h\"\n-#include \"Jhash.h\"\n-#include <ip2string.h>\n-\n-extern POVS_SWITCH_CONTEXT gOvsSwitchContext;\n-\n-#ifdef OVS_DBG_MOD\n-#undef OVS_DBG_MOD\n-#endif\n-#define OVS_DBG_MOD OVS_DBG_IPHELPER\n-#include \"Debug.h\"\n-\n-/*\n- * IpHelper supports multiple internal adapters.\n- */\n-\n-KSTART_ROUTINE OvsStartIpHelper;\n-\n-/* Contains the entries of internal adapter objects. */\n-static LIST_ENTRY ovsInstanceList;\n-\n-/* Passive-level lock used to protect the internal adapter object list. */\n-static ERESOURCE ovsInstanceListLock;\n-\n-/*\n- * FWD_ENTRY --------> IPFORWARD_ENTRY\n- * |\n- * |--------------------------------------> IPENIGH_ENTRY\n- *\n- * IPFORWARD_ENTRY ------> FWD_ENTRY LIST with same IPFORWARD\n- *\n- * IPNEIGH_ENTRY ------> FWD_ENTRY LIST with same IPNEIGH\n- *\n- */\n-\n-static PLIST_ENTRY ovsFwdHashTable; // based on DST IP\n-static PLIST_ENTRY ovsRouteHashTable; // based on DST PREFIX\n-static PLIST_ENTRY ovsNeighHashTable; // based on DST IP\n-static LIST_ENTRY ovsSortedIPNeighList;\n-static UINT32 ovsNumFwdEntries;\n-\n-\n-static PNDIS_RW_LOCK_EX ovsTableLock;\n-static NDIS_SPIN_LOCK ovsIpHelperLock;\n-\n-static LIST_ENTRY ovsIpHelperRequestList;\n-static UINT32 ovsNumIpHelperRequests;\n-\n-static HANDLE ipInterfaceNotificationHandle;\n-static HANDLE ipRouteNotificationHandle;\n-static HANDLE unicastIPNotificationHandle;\n-\n-static OVS_IP_HELPER_THREAD_CONTEXT ovsIpHelperThreadContext;\n-\n-static POVS_IPFORWARD_ENTRY OvsLookupIPForwardEntry(PIP_ADDRESS_PREFIX prefix);\n-static VOID OvsRemoveIPForwardEntry(POVS_IPFORWARD_ENTRY ipf);\n-static VOID OvsRemoveAllFwdEntriesWithSrc(SOCKADDR_INET ipAddr);\n-static VOID OvsRemoveIPNeighEntriesWithInstance(POVS_IPHELPER_INSTANCE instance);\n-static VOID OvsCleanupIpHelperRequestList(VOID);\n-static VOID OvsCleanupFwdTable(VOID);\n-static VOID OvsAddToSortedNeighList(POVS_IPNEIGH_ENTRY ipn);\n-static POVS_IPHELPER_INSTANCE OvsIpHelperAllocateInstance(\n- POVS_IP_HELPER_REQUEST request);\n-static VOID OvsIpHelperDeleteInstance(POVS_IPHELPER_INSTANCE instance);\n-\n-\n-static VOID\n-OvsDumpMessageWithGuid(char* message, GUID guid)\n-{\n- OVS_LOG_INFO(message, guid.Data1, guid.Data2, guid.Data3,\n- *(UINT16 *)guid.Data4, guid.Data4[2], guid.Data4[3],\n- guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);\n-}\n-\n-static VOID\n-OvsDumpIfRow(PMIB_IF_ROW2 ifRow)\n-{\n- OVS_LOG_INFO(\"InterfaceLuid: NetLuidIndex: %d, type: %d\",\n- ifRow->InterfaceLuid.Info.NetLuidIndex,\n- ifRow->InterfaceLuid.Info.IfType);\n- OVS_LOG_INFO(\"InterfaceIndex: %d\", ifRow->InterfaceIndex);\n-\n- OvsDumpMessageWithGuid(\"Interface GUID: \"\n- \"%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x\",\n- ifRow->InterfaceGuid);\n- OVS_LOG_INFO(\"Perm MAC Address: %02x:%02x:%02x:%02x:%02x:%02x\",\n- ifRow->PermanentPhysicalAddress[0],\n- ifRow->PermanentPhysicalAddress[1],\n- ifRow->PermanentPhysicalAddress[2],\n- ifRow->PermanentPhysicalAddress[3],\n- ifRow->PermanentPhysicalAddress[4],\n- ifRow->PermanentPhysicalAddress[5]);\n-}\n-\n-static VOID\n-OvsDumpIfTable(PMIB_IF_TABLE2 ifTable)\n-{\n- PMIB_IF_ROW2 ifRow;\n- UINT32 i;\n-\n- OVS_LOG_INFO(\"======Number of entries: %d========\", ifTable->NumEntries);\n-\n- for (i = 0; i < ifTable->NumEntries; i++) {\n- ifRow = &ifTable->Table[i];\n- OvsDumpIfRow(ifRow);\n- }\n-}\n-\n-\n-NTSTATUS\n-OvsGetIfEntry(GUID *interfaceGuid, PMIB_IF_ROW2 ifEntry)\n-{\n- NTSTATUS status;\n- PMIB_IF_TABLE2 ifTable;\n- UINT32 i;\n-\n- if (interfaceGuid == NULL || ifEntry == NULL) {\n- return STATUS_INVALID_PARAMETER;\n- }\n-\n- status = GetIfTable2Ex(MibIfTableNormal, &ifTable);\n-\n- if (status != STATUS_SUCCESS) {\n- OVS_LOG_INFO(\"Fail to get if table, status: %x\", status);\n- return status;\n- }\n- status = STATUS_NOT_FOUND;\n-\n- for (i = 0; i < ifTable->NumEntries; i++) {\n- PMIB_IF_ROW2 ifRow;\n-\n- ifRow = &ifTable->Table[i];\n- if (!memcmp(interfaceGuid, &ifRow->InterfaceGuid, sizeof (GUID))) {\n- RtlCopyMemory(ifEntry, ifRow, sizeof (MIB_IF_ROW2));\n- status = STATUS_SUCCESS;\n- OvsDumpIfRow(ifEntry);\n- break;\n- }\n- }\n-\n- FreeMibTable(ifTable);\n- return status;\n-}\n-\n-\n-static VOID\n-OvsDumpIPInterfaceEntry(PMIB_IPINTERFACE_ROW ipRow)\n-{\n- OVS_LOG_INFO(\"InterfaceLuid: NetLuidIndex: %d, type: %d\",\n- ipRow->InterfaceLuid.Info.NetLuidIndex,\n- ipRow->InterfaceLuid.Info.IfType);\n- OVS_LOG_INFO(\"InterfaceIndex: %d\", ipRow->InterfaceIndex);\n-\n- OVS_LOG_INFO(\"MaxReassembleSize: %u\", ipRow->MaxReassemblySize);\n-}\n-\n-\n-NTSTATUS\n-OvsGetIPInterfaceEntry(NET_LUID luid,\n- PMIB_IPINTERFACE_ROW ipRow)\n-{\n- NTSTATUS status;\n-\n- if (ipRow == NULL) {\n- return STATUS_INVALID_PARAMETER;\n- }\n-\n- ipRow->Family = AF_INET;\n- ipRow->InterfaceLuid.Value = luid.Value;\n-\n- status = GetIpInterfaceEntry(ipRow);\n-\n- if (status != STATUS_SUCCESS) {\n- OVS_LOG_INFO(\"Fail to get internal IP Interface mib row, status: %x\",\n- status);\n- return status;\n- }\n- OvsDumpIPInterfaceEntry(ipRow);\n- return status;\n-}\n-\n-static __inline VOID\n-OvsDumpIpAddrDesc(char *desc, char *andMsg, char *tailMsg,\n- const SOCKADDR_INET *IpAddress)\n-{\n- if (IpAddress->si_family == AF_INET) {\n- UINT32 ipAddr = 0;\n- ipAddr = IpAddress->Ipv4.sin_addr.s_addr;\n- OVS_LOG_INFO(\"%s: %d.%d.%d.%d%s%s\", desc,\n- ipAddr & 0xff, (ipAddr >> 8) & 0xff,\n- (ipAddr >> 16) & 0xff, ipAddr >> 24,\n- andMsg?andMsg:\"\", tailMsg?tailMsg:\"\");\n- } else if (IpAddress->si_family == AF_INET6) {\n- struct in6_addr *pAddr = NULL;\n- char wszAddr[256] = {0};\n-\n- pAddr = (struct in6_addr *)&(IpAddress->Ipv6.sin6_addr);\n- if (!RtlIpv6AddressToStringA(pAddr, wszAddr)) {\n- OVS_LOG_INFO(\"%s Ipv6 Address got failed\\n\", desc);\n- } else {\n- OVS_LOG_INFO(\"%s(IPv6): %s%s%s\", desc, wszAddr,\n- andMsg?andMsg:\"\", tailMsg?tailMsg:\"\");\n- }\n- }\n-}\n-\n-static __inline VOID\n-OvsDumpIpAddrMsg(char *desc, const SOCKADDR_INET *IpAddress)\n-{\n- OvsDumpIpAddrDesc(desc, NULL, NULL, IpAddress);\n-}\n-\n-static __inline VOID\n-OvsDumpIpAddrMsgStatus(char *descV4, char *descV6, NTSTATUS status,\n- const SOCKADDR_INET *IpAddress)\n-{\n- if (!descV4 || !descV6 || !IpAddress) {\n- return;\n- }\n-\n- if (IpAddress->si_family == AF_INET) {\n- UINT32 ipAddr = IpAddress->Ipv4.sin_addr.s_addr;\n- OVS_LOG_INFO(\"%s: %d.%d.%d.%d, status: %x\", descV4,\n- ipAddr & 0xff, (ipAddr >> 8) & 0xff,\n- (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff, status);\n- } else if (IpAddress->si_family == AF_INET6) {\n- struct in6_addr *pAddr = NULL;\n- char wszAddr[256] = {0};\n- pAddr = (struct in6_addr*)&(IpAddress->Ipv6.sin6_addr);\n- if (!RtlIpv6AddressToStringA(pAddr, wszAddr)) {\n- OVS_LOG_INFO(\"Ipv6 Address got failed\\n\");\n- } else {\n- OVS_LOG_INFO(\"%s: %s, status: %x\",\n- descV6, wszAddr, status);\n- }\n- }\n-\n-}\n-\n-static __inline VOID\n-OvsDumpIpAddrDescStatus(char *desc, NTSTATUS status,\n- const SOCKADDR_INET *IpAddress)\n-{\n- OvsDumpIpAddrMsgStatus(desc, desc, status, IpAddress);\n-}\n-\n-\n-static VOID\n-OvsDumpIPEntry(PMIB_UNICASTIPADDRESS_ROW ipRow)\n-{\n- OVS_LOG_INFO(\"InterfaceLuid: NetLuidIndex: %d, type: %d\",\n- ipRow->InterfaceLuid.Info.NetLuidIndex,\n- ipRow->InterfaceLuid.Info.IfType);\n-\n- OVS_LOG_INFO(\"InterfaceIndex: %d\", ipRow->InterfaceIndex);\n-\n- OVS_LOG_INFO(\"Address.si_family: %d\", ipRow->Address.si_family);\n- OvsDumpIpAddrMsg(\"Unicast Address\", &(ipRow->Address));\n-}\n-\n-\n-NTSTATUS\n-OvsGetIPEntry(NET_LUID interfaceLuid,\n- PMIB_UNICASTIPADDRESS_ROW ipEntry)\n-{\n- PMIB_UNICASTIPADDRESS_TABLE ipTable;\n- NTSTATUS status;\n- UINT32 i;\n-\n- if (ipEntry == NULL) {\n- return STATUS_INVALID_PARAMETER;\n- }\n-\n- status = GetUnicastIpAddressTable(AF_UNSPEC, &ipTable);\n-\n- if (status != STATUS_SUCCESS) {\n- OVS_LOG_INFO(\"Fail to get unicast address table, status: %x\", status);\n- return status;\n- }\n-\n- status = STATUS_NOT_FOUND;\n-\n- for (i = 0; i < ipTable->NumEntries; i++) {\n- PMIB_UNICASTIPADDRESS_ROW ipRow;\n-\n- ipRow = &ipTable->Table[i];\n- if (ipRow->InterfaceLuid.Value == interfaceLuid.Value) {\n- RtlCopyMemory(ipEntry, ipRow, sizeof (*ipRow));\n- OvsDumpIPEntry(ipEntry);\n- status = STATUS_SUCCESS;\n- break;\n- }\n- }\n-\n- FreeMibTable(ipTable);\n- return status;\n-}\n-\n-#ifdef OVS_ENABLE_IPPATH\n-static VOID\n-OvsDumpIPPath(PMIB_IPPATH_ROW ipPath)\n-{\n- UINT32 ipAddr = ipPath->Source.Ipv4.sin_addr.s_addr;\n-\n- OVS_LOG_INFO(\"Source: %d.%d.%d.%d\",\n- ipAddr & 0xff, (ipAddr >> 8) & 0xff,\n- (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff);\n-\n- ipAddr = ipPath->Destination.Ipv4.sin_addr.s_addr;\n- OVS_LOG_INFO(\"Destination: %d.%d.%d.%d\",\n- ipAddr & 0xff, (ipAddr >> 8) & 0xff,\n- (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff);\n-\n- ipAddr = ipPath->CurrentNextHop.Ipv4.sin_addr.s_addr;\n- OVS_LOG_INFO(\"NextHop: %d.%d.%d.%d\",\n- ipAddr & 0xff, (ipAddr >> 8) & 0xff,\n- (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff);\n-}\n-\n-\n-NTSTATUS\n-OvsGetIPPathEntry(PMIB_IPPATH_ROW ipPath)\n-{\n- NTSTATUS status;\n- UINT32 ipAddr = ipPath->Destination.Ipv4.sin_addr.s_addr;\n-\n- status = GetIpPathEntry(ipPath);\n-\n- if (status != STATUS_SUCCESS) {\n- OVS_LOG_INFO(\"Fail to get IP path to %d.%d.%d.%d, status:%x\",\n- ipAddr & 0xff, (ipAddr >> 8) & 0xff,\n- (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff, status);\n- return status;\n- }\n- OvsDumpIPPath(ipPath);\n- return status;\n-}\n-#endif\n-\n-static VOID\n-OvsDumpRoute(const SOCKADDR_INET *sourceAddress,\n- const SOCKADDR_INET *destinationAddress,\n- PMIB_IPFORWARD_ROW2 route)\n-{\n- OvsDumpIpAddrMsg(\"Destination\", destinationAddress);\n- OvsDumpIpAddrMsg(\"Source\", sourceAddress);\n- OvsDumpIpAddrMsg(\"NextHop\", &(route->NextHop));\n-}\n-\n-NTSTATUS\n-OvsGetRoute(SOCKADDR_INET *destinationAddress,\n- PMIB_IPFORWARD_ROW2 route,\n- SOCKADDR_INET *sourceAddress,\n- POVS_IPHELPER_INSTANCE *instance,\n- POVS_VPORT_ENTRY* vport,\n- SOCKADDR_INET srcIp)\n-{\n- NTSTATUS status = STATUS_NETWORK_UNREACHABLE;\n- NTSTATUS result = STATUS_SUCCESS;\n- PLIST_ENTRY head, link, next;\n- ULONG minMetric = MAXULONG;\n-\n-\n- if (destinationAddress == NULL || route == NULL) {\n- return STATUS_INVALID_PARAMETER;\n- }\n-\n- ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE);\n- head = &(ovsInstanceList);\n- LIST_FORALL_SAFE(head, link, next) {\n- SOCKADDR_INET crtSrcAddr = { 0 };\n- MIB_IPFORWARD_ROW2 crtRoute = { 0 };\n- POVS_IPHELPER_INSTANCE crtInstance = NULL;\n- WCHAR interfaceName[IF_MAX_STRING_SIZE + 1];\n-#ifdef DBG\n- char ansiIfname[256] = { 0 };\n- size_t strLen = 0;\n-#endif\n- crtInstance = CONTAINING_RECORD(link, OVS_IPHELPER_INSTANCE, link);\n-\n- ExAcquireResourceExclusiveLite(&crtInstance->lock, TRUE);\n- result = GetBestRoute2(&crtInstance->internalRow.InterfaceLuid, 0,\n- NULL, destinationAddress, 0, &crtRoute,\n- &crtSrcAddr);\n-\n- if (result != STATUS_SUCCESS) {\n- ExReleaseResourceLite(&crtInstance->lock);\n- continue;\n- }\n-\n-#ifdef DBG\n- RtlZeroMemory(ansiIfname, 256);\n-\n- status =\n- ConvertInterfaceLuidToAlias(&crtInstance->internalRow.InterfaceLuid,\n- interfaceName,\n- IF_MAX_STRING_SIZE + 1);\n-\n- if (NT_SUCCESS(status)) {\n- status = RtlStringCbLengthW(interfaceName, IF_MAX_STRING_SIZE,\n- &strLen);\n- }\n-\n- OvsConvertWcharToAnsiStr(interfaceName, strLen, ansiIfname, 256);\n- OVS_LOG_INFO(\"the interface name is %s\", ansiIfname);\n-#endif\n- if (minMetric > crtRoute.Metric &&\n- (OvsIphIsZero(&srcIp) || OvsIphAddrEquals(&srcIp, &crtSrcAddr))) {\n- status = STATUS_SUCCESS;\n- size_t len = 0;\n- minMetric = crtRoute.Metric;\n- LOCK_STATE_EX lockState;\n-\n- RtlCopyMemory(sourceAddress, &crtSrcAddr, sizeof(*sourceAddress));\n- RtlCopyMemory(route, &crtRoute, sizeof(*route));\n- *instance = crtInstance;\n-\n- status =\n- ConvertInterfaceLuidToAlias(&crtInstance->internalRow.InterfaceLuid,\n- interfaceName,\n- IF_MAX_STRING_SIZE + 1);\n- if (NT_SUCCESS(status)) {\n- status = RtlStringCbLengthW(interfaceName, IF_MAX_STRING_SIZE,\n- &len);\n- }\n-#ifdef DBG\n- RtlZeroMemory(ansiIfname, 256);\n- OvsConvertWcharToAnsiStr(interfaceName, len, ansiIfname, 256);\n- OVS_LOG_INFO(\"the found interface name is %s\", ansiIfname);\n-#endif\n- if (gOvsSwitchContext != NULL && NT_SUCCESS(status)) {\n- NdisAcquireRWLockRead(gOvsSwitchContext->dispatchLock,\n- &lockState, 0);\n- *vport = OvsFindVportByHvNameW(gOvsSwitchContext,\n- interfaceName,\n- len);\n-#ifdef DBG\n- if (*vport) {\n- OVS_LOG_INFO(\"match the ovs port ovsName: %s\", (*vport)->ovsName);\n- } else {\n- OVS_LOG_INFO(\"not get the ovs port\");\n- }\n-#endif\n- NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState);\n- }\n- }\n- ExReleaseResourceLite(&crtInstance->lock);\n- }\n- ExReleaseResourceLite(&ovsInstanceListLock);\n-\n- OvsDumpRoute(sourceAddress, destinationAddress, route);\n-\n- return status;\n-}\n-\n-static VOID\n-OvsDumpIPNeigh(PMIB_IPNET_ROW2 ipNeigh)\n-{\n- OvsDumpIpAddrMsg(\"Neigh\", &(ipNeigh->Address));\n- OVS_LOG_INFO(\"MAC Address: %02x:%02x:%02x:%02x:%02x:%02x\",\n- ipNeigh->PhysicalAddress[0],\n- ipNeigh->PhysicalAddress[1],\n- ipNeigh->PhysicalAddress[2],\n- ipNeigh->PhysicalAddress[3],\n- ipNeigh->PhysicalAddress[4],\n- ipNeigh->PhysicalAddress[5]);\n-}\n-\n-\n-NTSTATUS\n-OvsGetIPNeighEntry(PMIB_IPNET_ROW2 ipNeigh)\n-{\n- NTSTATUS status;\n-\n- ASSERT(ipNeigh);\n-\n- status = GetIpNetEntry2(ipNeigh);\n-\n- if (status != STATUS_SUCCESS) {\n- OvsDumpIpAddrMsgStatus(\"Fail to get ARP entry\",\n- \"Fail to get neighbour entry\",\n- status, &(ipNeigh->Address));\n- return status;\n- }\n- if (ipNeigh->State == NlnsReachable ||\n- ipNeigh->State == NlnsPermanent) {\n- OvsDumpIPNeigh(ipNeigh);\n- return STATUS_SUCCESS;\n- }\n- return STATUS_FWP_TCPIP_NOT_READY;\n-}\n-\n-\n-NTSTATUS\n-OvsResolveIPNeighEntry(PMIB_IPNET_ROW2 ipNeigh)\n-{\n- NTSTATUS status;\n-\n- ASSERT(ipNeigh);\n- status = ResolveIpNetEntry2(ipNeigh, NULL);\n-\n- if (status != STATUS_SUCCESS) {\n- OvsDumpIpAddrMsgStatus(\"Fail to get ARP entry\",\n- \"Fail to get neighbour entry\",\n- status, &(ipNeigh->Address));\n- return status;\n- }\n-\n- if (ipNeigh->State == NlnsReachable ||\n- ipNeigh->State == NlnsPermanent) {\n- OvsDumpIPNeigh(ipNeigh);\n- return STATUS_SUCCESS;\n- }\n- return STATUS_FWP_TCPIP_NOT_READY;\n-}\n-\n-\n-NTSTATUS\n-OvsGetOrResolveIPNeigh(PMIB_IF_ROW2 ipRow,\n- SOCKADDR_INET ipAddr,\n- PMIB_IPNET_ROW2 ipNeigh)\n-{\n- NTSTATUS status;\n-\n- ASSERT(ipNeigh);\n-\n- RtlZeroMemory(ipNeigh, sizeof (*ipNeigh));\n- ipNeigh->InterfaceLuid.Value = ipRow->InterfaceLuid.Value;\n- ipNeigh->InterfaceIndex = ipRow->InterfaceIndex;\n- OvsCopyIphAddress(&(ipNeigh->Address), &ipAddr);\n-\n- status = OvsGetIPNeighEntry(ipNeigh);\n-\n- if (status != STATUS_SUCCESS) {\n- RtlZeroMemory(ipNeigh, sizeof (*ipNeigh));\n- ipNeigh->InterfaceLuid.Value = ipRow->InterfaceLuid.Value;\n- ipNeigh->InterfaceIndex = ipRow->InterfaceIndex;\n- OvsCopyIphAddress(&(ipNeigh->Address), &ipAddr);\n- status = OvsResolveIPNeighEntry(ipNeigh);\n- }\n- return status;\n-}\n-\n-static __inline BOOLEAN\n-OvsCheckInstanceRow(PMIB_IF_ROW2 instanceRow,\n- PNET_LUID netLuid,\n- NET_IFINDEX ifIndex)\n-{\n- return (instanceRow->InterfaceLuid.Info.NetLuidIndex ==\n- netLuid->Info.NetLuidIndex &&\n- instanceRow->InterfaceLuid.Info.IfType ==\n- netLuid->Info.IfType &&\n- instanceRow->InterfaceIndex ==\n- ifIndex);\n-}\n-\n-static VOID\n-OvsUpdateIpInterfaceNotification(PMIB_IPINTERFACE_ROW ipRow)\n-{\n- PLIST_ENTRY head, link, next;\n-\n- ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE);\n- head = &(ovsInstanceList);\n- LIST_FORALL_SAFE(head, link, next) {\n- POVS_IPHELPER_INSTANCE instance = NULL;\n-\n- instance = CONTAINING_RECORD(link, OVS_IPHELPER_INSTANCE, link);\n-\n- ExAcquireResourceExclusiveLite(&instance->lock, TRUE);\n- if (OvsCheckInstanceRow(&instance->internalRow,\n- &ipRow->InterfaceLuid,\n- ipRow->InterfaceIndex)) {\n-\n- /*\n- * Update the IP Interface Row\n- */\n- RtlCopyMemory(&instance->internalIPRow, ipRow,\n- sizeof(PMIB_IPINTERFACE_ROW));\n- instance->isIpConfigured = TRUE;\n-\n- OVS_LOG_INFO(\"IP Interface with NetLuidIndex: %d, type: %d is %s\",\n- ipRow->InterfaceLuid.Info.NetLuidIndex,\n- ipRow->InterfaceLuid.Info.IfType,\n- \"modified\");\n-\n- ExReleaseResourceLite(&instance->lock);\n- break;\n- }\n- ExReleaseResourceLite(&instance->lock);\n- }\n- ExReleaseResourceLite(&ovsInstanceListLock);\n-}\n-\n-static VOID\n-OvsAddIpInterfaceNotification(PMIB_IPINTERFACE_ROW ipRow)\n-{\n- PLIST_ENTRY head, link, next;\n- BOOLEAN found = FALSE;\n-\n- ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE);\n- head = &(ovsInstanceList);\n- LIST_FORALL_SAFE(head, link, next) {\n- POVS_IPHELPER_INSTANCE instance = NULL;\n-\n- instance = CONTAINING_RECORD(link, OVS_IPHELPER_INSTANCE, link);\n-\n- ExAcquireResourceExclusiveLite(&instance->lock, TRUE);\n- if (OvsCheckInstanceRow(&instance->internalRow, &ipRow->InterfaceLuid,\n- ipRow->InterfaceIndex)) {\n-\n- instance->isIpConfigured = FALSE;\n- ExReleaseResourceLite(&instance->lock);\n-\n- found = TRUE;\n-\n- break;\n- }\n- ExReleaseResourceLite(&instance->lock);\n- }\n- ExReleaseResourceLite(&ovsInstanceListLock);\n-\n- if (found != TRUE) {\n- NTSTATUS status;\n- POVS_IPHELPER_INSTANCE instance = NULL;\n- MIB_UNICASTIPADDRESS_ROW ipEntry;\n- BOOLEAN error = TRUE;\n- LOCK_STATE_EX lockState;\n-\n- instance = (POVS_IPHELPER_INSTANCE)OvsAllocateMemoryWithTag(\n- sizeof(*instance), OVS_IPHELPER_POOL_TAG);\n- if (instance == NULL) {\n- goto error;\n- }\n- RtlZeroMemory(instance, sizeof(*instance));\n-\n- InitializeListHead(&instance->link);\n- ExInitializeResourceLite(&instance->lock);\n- WCHAR interfaceName[IF_MAX_STRING_SIZE + 1];\n- status = ConvertInterfaceLuidToAlias(&ipRow->InterfaceLuid,\n- interfaceName,\n- IF_MAX_STRING_SIZE + 1);\n- if (gOvsSwitchContext == NULL || !NT_SUCCESS(status)) {\n- goto error;\n- }\n- NdisAcquireRWLockRead(gOvsSwitchContext->dispatchLock, &lockState, 0);\n- POVS_VPORT_ENTRY vport = OvsFindVportByHvNameW(gOvsSwitchContext,\n- interfaceName,\n- sizeof(WCHAR) *\n- wcslen(interfaceName));\n-\n- if (vport != NULL) {\n- RtlCopyMemory(&instance->netCfgId,\n- &vport->netCfgInstanceId,\n- sizeof(instance->netCfgId));\n- instance->portNo = vport->portNo;\n- }\n- NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState);\n- RtlZeroMemory(&instance->internalRow, sizeof(MIB_IF_ROW2));\n- RtlZeroMemory(&instance->internalIPRow, sizeof(MIB_IPINTERFACE_ROW));\n- status = OvsGetIfEntry(&instance->netCfgId,\n- &instance->internalRow);\n-\n- if (status != STATUS_SUCCESS) {\n- OvsDumpMessageWithGuid(\"Fail to get IF entry for internal port with GUID\"\n- \" %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x\",\n- instance->netCfgId);\n- goto error;\n- }\n-\n- status = OvsGetIPInterfaceEntry(instance->internalRow.InterfaceLuid,\n- &instance->internalIPRow);\n-\n- if (status == STATUS_SUCCESS) {\n- instance->isIpConfigured = TRUE;\n- } else {\n- goto error;\n- }\n-\n- status = OvsGetIPEntry(instance->internalRow.InterfaceLuid, &ipEntry);\n- if (status != STATUS_SUCCESS) {\n- OvsDumpMessageWithGuid(\"Failed to get IP entry for internal port with GUID\"\n- \" %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x\",\n- instance->netCfgId);\n- }\n-\n- ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE);\n- InsertHeadList(&ovsInstanceList, &instance->link);\n- ExReleaseResourceLite(&ovsInstanceListLock);\n-\n- error = FALSE;\n-\n-error:\n- if (error) {\n- OvsIpHelperDeleteInstance(instance);\n- }\n- }\n-}\n-\n-static VOID\n-OvsRemoveIpInterfaceNotification(PMIB_IPINTERFACE_ROW ipRow)\n-{\n- PLIST_ENTRY head, link, next;\n-\n- ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE);\n- head = &(ovsInstanceList);\n- LIST_FORALL_SAFE(head, link, next) {\n- POVS_IPHELPER_INSTANCE instance = NULL;\n-\n- instance = CONTAINING_RECORD(link, OVS_IPHELPER_INSTANCE, link);\n-\n- ExAcquireResourceExclusiveLite(&instance->lock, TRUE);\n- if (OvsCheckInstanceRow(&instance->internalRow, &ipRow->InterfaceLuid,\n- ipRow->InterfaceIndex)) {\n-\n- instance->isIpConfigured = FALSE;\n- RemoveEntryList(&instance->link);\n-\n- ExReleaseResourceLite(&instance->lock);\n- OvsIpHelperDeleteInstance(instance);\n-\n- OVS_LOG_INFO(\"IP Interface with NetLuidIndex: %d, type: %d is \"\\\n- \"deleted\",\n- ipRow->InterfaceLuid.Info.NetLuidIndex,\n- ipRow->InterfaceLuid.Info.IfType);\n-\n- break;\n- }\n- ExReleaseResourceLite(&instance->lock);\n- }\n- ExReleaseResourceLite(&ovsInstanceListLock);\n-\n- if (IsListEmpty(&ovsInstanceList)) {\n- OvsCleanupIpHelperRequestList();\n- OvsCleanupFwdTable();\n- }\n-}\n-\n-static VOID\n-OvsChangeCallbackIpInterface(PVOID context,\n- PMIB_IPINTERFACE_ROW ipRow,\n- MIB_NOTIFICATION_TYPE notificationType)\n-{\n- UNREFERENCED_PARAMETER(context);\n- switch (notificationType) {\n- case MibParameterNotification:\n- OvsUpdateIpInterfaceNotification(ipRow);\n- break;\n- case MibAddInstance:\n- OvsAddIpInterfaceNotification(ipRow);\n- break;\n-\n- case MibDeleteInstance:\n- OvsRemoveIpInterfaceNotification(ipRow);\n- break;\n- case MibInitialNotification:\n- OVS_LOG_INFO(\"Got Initial notification for IP Interface change.\");\n- default:\n- return;\n- }\n-}\n-\n-\n-static VOID\n-OvsChangeCallbackIpRoute(PVOID context,\n- PMIB_IPFORWARD_ROW2 ipRoute,\n- MIB_NOTIFICATION_TYPE notificationType)\n-{\n- UINT32 ipAddr, nextHop;\n- struct in6_addr *pAddr = NULL, *pNextHop = NULL;\n- char wszAddr[256] = { 0 };\n- char wszNextHop[256] = { 0 };\n-\n- UNREFERENCED_PARAMETER(context);\n- switch (notificationType) {\n- case MibAddInstance:\n-\n- ASSERT(ipRoute);\n- if (ipRoute->DestinationPrefix.Prefix.si_family == AF_INET) {\n- ipAddr = ipRoute->DestinationPrefix.Prefix.Ipv4.sin_addr.s_addr;\n- nextHop = ipRoute->NextHop.Ipv4.sin_addr.s_addr;\n- OVS_LOG_INFO(\"IPRoute: To %d.%d.%d.%d/%d through %d.%d.%d.%d added\",\n- ipAddr & 0xff, (ipAddr >> 8) & 0xff,\n- (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff,\n- ipRoute->DestinationPrefix.PrefixLength,\n- nextHop & 0xff, (nextHop >> 8) & 0xff,\n- (nextHop >> 16) & 0xff, (nextHop >> 24) & 0xff);\n- } else if (ipRoute->DestinationPrefix.Prefix.si_family == AF_INET6) {\n- pAddr = (struct in6_addr *)&(ipRoute->DestinationPrefix.Prefix.Ipv6.sin6_addr);\n- if (!RtlIpv6AddressToStringA(pAddr, wszAddr)) {\n- OVS_LOG_INFO(\"DestinationPrefix Ipv6 Address got failed\\n\");\n- } else {\n- pNextHop = (struct in6_addr *)&(ipRoute->NextHop.Ipv6.sin6_addr);\n- if (!RtlIpv6AddressToStringA(pNextHop, wszNextHop)) {\n- OVS_LOG_INFO(\"NextHop Ipv6 Address got failed\\n\");\n- } else {\n- OVS_LOG_INFO(\"IPRoute: To %s/%d through %s added\",\n- wszAddr, ipRoute->DestinationPrefix.PrefixLength,\n- wszNextHop);\n- }\n- }\n- }\n- break;\n-\n- case MibParameterNotification:\n- case MibDeleteInstance:\n- {\n- ASSERT(ipRoute);\n-\n- POVS_IPFORWARD_ENTRY ipf;\n- LOCK_STATE_EX lockState;\n-\n- NdisAcquireRWLockWrite(ovsTableLock, &lockState, 0);\n- ipf = OvsLookupIPForwardEntry(&ipRoute->DestinationPrefix);\n- if (ipf != NULL) {\n- OvsRemoveIPForwardEntry(ipf);\n- }\n- NdisReleaseRWLock(ovsTableLock, &lockState);\n-\n- if (ipRoute->DestinationPrefix.Prefix.si_family == AF_INET) {\n- ipAddr = ipRoute->DestinationPrefix.Prefix.Ipv4.sin_addr.s_addr;\n- nextHop = ipRoute->NextHop.Ipv4.sin_addr.s_addr;\n-\n- OVS_LOG_INFO(\"IPRoute: To %d.%d.%d.%d/%d through %d.%d.%d.%d %s.\",\n- ipAddr & 0xff, (ipAddr >> 8) & 0xff,\n- (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff,\n- ipRoute->DestinationPrefix.PrefixLength,\n- nextHop & 0xff, (nextHop >> 8) & 0xff,\n- (nextHop >> 16) & 0xff, (nextHop >> 24) & 0xff,\n- notificationType == MibDeleteInstance ? \"deleted\" :\n- \"modified\");\n- } else if (ipRoute->DestinationPrefix.Prefix.si_family == AF_INET6) {\n- pAddr = (struct in6_addr *)&(ipRoute->DestinationPrefix.Prefix.Ipv6.sin6_addr);\n- if (!RtlIpv6AddressToStringA(pAddr, wszAddr)) {\n- OVS_LOG_INFO(\"DestinationPrefix Ipv6 Address got failed\\n\");\n- } else {\n- pNextHop = (struct in6_addr *)&(ipRoute->NextHop.Ipv6.sin6_addr);\n- if (!RtlIpv6AddressToStringA(pNextHop, wszNextHop)) {\n- OVS_LOG_INFO(\"NextHop Ipv6 Address got failed\\n\");\n- } else {\n- OVS_LOG_INFO(\"IPRoute: To %s/%d through %s %s.\",\n- wszAddr, ipRoute->DestinationPrefix.PrefixLength,\n- wszNextHop, notificationType == MibDeleteInstance ? \"deleted\" :\n- \"modified\");\n- }\n- }\n- }\n- break;\n- }\n-\n- case MibInitialNotification:\n- OVS_LOG_INFO(\"Get Initial notification for IP Route change.\");\n- default:\n- return;\n- }\n-}\n-\n-\n-static VOID\n-OvsChangeCallbackUnicastIpAddress(PVOID context,\n- PMIB_UNICASTIPADDRESS_ROW unicastRow,\n- MIB_NOTIFICATION_TYPE notificationType)\n-{\n- SOCKADDR_INET iphAddr = { 0 };\n-\n- UNREFERENCED_PARAMETER(context);\n- switch (notificationType) {\n- case MibParameterNotification:\n- case MibAddInstance:\n- {\n- PLIST_ENTRY head, link, next;\n-\n- ASSERT(unicastRow);\n- OvsCopyIphAddress(&iphAddr, &(unicastRow->Address));\n-\n- ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE);\n- head = &(ovsInstanceList);\n- LIST_FORALL_SAFE(head, link, next) {\n- POVS_IPHELPER_INSTANCE instance = NULL;\n-\n- instance = CONTAINING_RECORD(link, OVS_IPHELPER_INSTANCE, link);\n-\n- ExAcquireResourceExclusiveLite(&instance->lock, TRUE);\n- if (instance->isIpConfigured &&\n- OvsCheckInstanceRow(&instance->internalRow,\n- &unicastRow->InterfaceLuid,\n- unicastRow->InterfaceIndex)) {\n- OvsCopyIphAddress(&(instance->ipAddress), &(unicastRow->Address));\n-\n- OvsDumpIpAddrDesc(\"IP Address\", \" is \",\n- notificationType == MibAddInstance ?\n- \"added\": \"modified\",\n- &(unicastRow->Address));\n- ExReleaseResourceLite(&instance->lock);\n- break;\n- }\n- ExReleaseResourceLite(&instance->lock);\n- }\n- ExReleaseResourceLite(&ovsInstanceListLock);\n-\n- break;\n- }\n-\n- case MibDeleteInstance:\n- {\n- PLIST_ENTRY head, link, next;\n- LOCK_STATE_EX lockState;\n- BOOLEAN found = FALSE;\n-\n- ASSERT(unicastRow);\n- OvsCopyIphAddress(&iphAddr, &(unicastRow->Address));\n-\n- ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE);\n- head = &(ovsInstanceList);\n- LIST_FORALL_SAFE(head, link, next) {\n- POVS_IPHELPER_INSTANCE instance = NULL;\n-\n- instance = CONTAINING_RECORD(link, OVS_IPHELPER_INSTANCE, link);\n-\n- ExAcquireResourceExclusiveLite(&instance->lock, TRUE);\n- if (instance->isIpConfigured &&\n- OvsCheckInstanceRow(&instance->internalRow,\n- &unicastRow->InterfaceLuid,\n- unicastRow->InterfaceIndex)) {\n-\n- found = TRUE;\n-\n- ExReleaseResourceLite(&instance->lock);\n- break;\n- }\n- ExReleaseResourceLite(&instance->lock);\n- }\n- ExReleaseResourceLite(&ovsInstanceListLock);\n-\n- if (found) {\n- NdisAcquireRWLockWrite(ovsTableLock, &lockState, 0);\n- OvsRemoveAllFwdEntriesWithSrc(iphAddr);\n- NdisReleaseRWLock(ovsTableLock, &lockState);\n-\n- OvsDumpIpAddrMsg(\"IP Address removed\", &(unicastRow->Address));\n- }\n-\n- break;\n- }\n-\n- case MibInitialNotification:\n- OVS_LOG_INFO(\"Get Initial notification for Unicast IP Address change.\");\n- default:\n- return;\n- }\n-}\n-\n-\n-static VOID\n-OvsCancelChangeNotification()\n-{\n- if (ipInterfaceNotificationHandle != NULL) {\n- CancelMibChangeNotify2(ipInterfaceNotificationHandle);\n- ipInterfaceNotificationHandle = NULL;\n- }\n- if (ipRouteNotificationHandle != NULL) {\n- CancelMibChangeNotify2(ipRouteNotificationHandle);\n- ipRouteNotificationHandle = NULL;\n- }\n- if (unicastIPNotificationHandle != NULL) {\n- CancelMibChangeNotify2(unicastIPNotificationHandle);\n- unicastIPNotificationHandle = NULL;\n- }\n-}\n-\n-\n-static NTSTATUS\n-OvsRegisterChangeNotification()\n-{\n- NTSTATUS status;\n- UINT dummy = 0;\n-\n-\n- status = NotifyIpInterfaceChange(AF_UNSPEC, OvsChangeCallbackIpInterface,\n- NULL, TRUE,\n- &ipInterfaceNotificationHandle);\n- if (status != STATUS_SUCCESS) {\n- OVS_LOG_ERROR(\"Fail to register Notify IP interface change, status:%x.\",\n- status);\n- return status;\n- }\n-\n- /* The CallerContext is dummy and should never be used */\n- status = NotifyRouteChange2(AF_UNSPEC, OvsChangeCallbackIpRoute, &dummy,\n- TRUE, &ipRouteNotificationHandle);\n- if (status != STATUS_SUCCESS) {\n- OVS_LOG_ERROR(\"Failed to register IP route change, status: %x.\",\n- status);\n- goto register_cleanup;\n- }\n- status = NotifyUnicastIpAddressChange(AF_UNSPEC,\n- OvsChangeCallbackUnicastIpAddress,\n- NULL, TRUE,\n- &unicastIPNotificationHandle);\n- if (status != STATUS_SUCCESS) {\n- OVS_LOG_ERROR(\"Failed to register UNICAST IP change, status: %x.\",\n- status);\n- }\n-register_cleanup:\n- if (status != STATUS_SUCCESS) {\n- OvsCancelChangeNotification();\n- }\n-\n- return status;\n-}\n-\n-\n-static POVS_IPNEIGH_ENTRY\n-OvsLookupIPNeighEntry(SOCKADDR_INET ipAddr)\n-{\n- PLIST_ENTRY link;\n-\n- UINT32 hash = OvsJhashIphHdr(&ipAddr);\n-\n- LIST_FORALL(&ovsNeighHashTable[hash & OVS_NEIGH_HASH_TABLE_MASK], link) {\n- POVS_IPNEIGH_ENTRY entry;\n-\n- entry = CONTAINING_RECORD(link, OVS_IPNEIGH_ENTRY, link);\n- if (OvsIphAddrEquals(&(entry->ipAddr), &ipAddr)) {\n- return entry;\n- }\n- }\n- return NULL;\n-}\n-\n-static UINT32\n-OvsHashIPPrefix(PIP_ADDRESS_PREFIX prefix)\n-{\n- UINT32 hash = 0;\n-\n- if (prefix->Prefix.si_family == AF_INET) {\n- UINT64 words = (UINT64)prefix->Prefix.Ipv4.sin_addr.s_addr << 32 |\n- (UINT32)prefix->PrefixLength;\n- hash = OvsJhashWords((UINT32 *)&words, 2, OVS_HASH_BASIS);\n- } else if (prefix->Prefix.si_family == AF_INET6) {\n- UCHAR words[20] = { 0 };\n- RtlCopyMemory(words, prefix->Prefix.Ipv6.sin6_addr.u.Byte,\n- sizeof(prefix->Prefix.Ipv6.sin6_addr.u.Byte));\n- *((UINT32*)(&words[16])) = (UINT32)prefix->PrefixLength;\n- hash = OvsJhashBytes((UINT32 *)words, 5, OVS_HASH_BASIS);\n- }\n- return hash;\n-}\n-\n-static POVS_IPFORWARD_ENTRY\n-OvsLookupIPForwardEntry(PIP_ADDRESS_PREFIX prefix)\n-{\n- PLIST_ENTRY link;\n- UINT32 hash;\n- hash = OvsHashIPPrefix(prefix);\n- LIST_FORALL(&ovsRouteHashTable[hash & OVS_ROUTE_HASH_TABLE_MASK], link) {\n- POVS_IPFORWARD_ENTRY ipfEntry;\n-\n- ipfEntry = CONTAINING_RECORD(link, OVS_IPFORWARD_ENTRY, link);\n- if (OvsIphAddrEquals(&ipfEntry->prefix.Prefix, &prefix->Prefix)) {\n- return ipfEntry;\n- }\n- }\n- return NULL;\n-}\n-\n-\n-static POVS_FWD_ENTRY\n-OvsLookupIPFwdEntry(SOCKADDR_INET srcIp, SOCKADDR_INET dstIp)\n-{\n- PLIST_ENTRY link;\n- UINT32 hash = 0;\n- hash = OvsJhashIphHdr(&dstIp);\n-\n- LIST_FORALL(&ovsFwdHashTable[hash & OVS_FWD_HASH_TABLE_MASK], link) {\n- POVS_FWD_ENTRY entry;\n-\n- entry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, link);\n-\n- if (OvsIphAddrEquals(&(entry->info.dstIphAddr), &dstIp) &&\n- (OvsIphIsZero(&srcIp) || OvsIphAddrEquals(&(entry->info.srcIphAddr), &srcIp))) {\n- return entry;\n- }\n- }\n- return NULL;\n-}\n-\n-\n-NTSTATUS\n-OvsLookupIPhFwdInfo(SOCKADDR_INET srcIp,\n- SOCKADDR_INET dstIp,\n- POVS_FWD_INFO info)\n-{\n- POVS_FWD_ENTRY entry;\n- LOCK_STATE_EX lockState;\n- NTSTATUS status = STATUS_NOT_FOUND;\n-\n- NdisAcquireRWLockRead(ovsTableLock, &lockState, 0);\n- entry = OvsLookupIPFwdEntry(srcIp, dstIp);\n- if (entry) {\n- RtlCopyMemory(info->value, entry->info.value,\n- sizeof entry->info.value);\n- OvsCopyIphAddress(&info->dstIphAddr, &(entry->info.dstIphAddr));\n- status = STATUS_SUCCESS;\n- }\n- NdisReleaseRWLock(ovsTableLock, &lockState);\n- return status;\n-}\n-\n-static POVS_IPNEIGH_ENTRY\n-OvsCreateIPNeighEntry(PMIB_IPNET_ROW2 ipNeigh,\n- POVS_IPHELPER_INSTANCE instance)\n-{\n-\n- POVS_IPNEIGH_ENTRY entry;\n- UINT64 timeVal;\n-\n- ASSERT(ipNeigh != NULL);\n- entry = (POVS_IPNEIGH_ENTRY)OvsAllocateMemoryWithTag(\n- sizeof(OVS_IPNEIGH_ENTRY), OVS_IPHELPER_POOL_TAG);\n- if (entry == NULL) {\n- return NULL;\n- }\n-\n- RtlZeroMemory(entry, sizeof (OVS_IPNEIGH_ENTRY));\n- OvsCopyIphAddress(&(entry->ipAddr), &(ipNeigh->Address));\n- KeQuerySystemTime((LARGE_INTEGER *)&timeVal);\n- entry->timeout = timeVal + OVS_IPNEIGH_TIMEOUT;\n- RtlCopyMemory(entry->macAddr, ipNeigh->PhysicalAddress,\n- ETH_ADDR_LEN);\n- InitializeListHead(&entry->fwdList);\n- entry->instance = instance;\n-\n- return entry;\n-}\n-\n-\n-static POVS_IPFORWARD_ENTRY\n-OvsCreateIPForwardEntry(PMIB_IPFORWARD_ROW2 ipRoute)\n-{\n- POVS_IPFORWARD_ENTRY entry;\n-\n- ASSERT(ipRoute);\n-\n- entry = (POVS_IPFORWARD_ENTRY)OvsAllocateMemoryWithTag(\n- sizeof(OVS_IPFORWARD_ENTRY), OVS_IPHELPER_POOL_TAG);\n- if (entry == NULL) {\n- return NULL;\n- }\n-\n- RtlZeroMemory(entry, sizeof (OVS_IPFORWARD_ENTRY));\n- RtlCopyMemory(&entry->prefix, &ipRoute->DestinationPrefix,\n- sizeof (IP_ADDRESS_PREFIX));\n- OvsCopyIphAddress(&(entry->nextHop), &(ipRoute->NextHop));\n- InitializeListHead(&entry->fwdList);\n-\n- return entry;\n-}\n-\n-\n-static POVS_FWD_ENTRY\n-OvsCreateFwdEntry(POVS_FWD_INFO fwdInfo)\n-{\n- POVS_FWD_ENTRY entry;\n-\n- entry = (POVS_FWD_ENTRY)OvsAllocateMemoryWithTag(\n- sizeof(OVS_FWD_ENTRY), OVS_IPHELPER_POOL_TAG);\n- if (entry == NULL) {\n- return NULL;\n- }\n-\n- RtlZeroMemory(entry, sizeof (OVS_FWD_ENTRY));\n- RtlCopyMemory(&entry->info, fwdInfo, sizeof (OVS_FWD_INFO));\n- return entry;\n-}\n-\n-\n-static VOID\n-OvsRemoveFwdEntry(POVS_FWD_ENTRY fwdEntry)\n-{\n- POVS_IPFORWARD_ENTRY ipf;\n- POVS_IPNEIGH_ENTRY ipn;\n-\n- ipf = fwdEntry->ipf;\n- ipn = fwdEntry->ipn;\n-\n- RemoveEntryList(&fwdEntry->link);\n- ovsNumFwdEntries--;\n-\n- RemoveEntryList(&fwdEntry->ipfLink);\n- ipf->refCount--;\n-\n- RemoveEntryList(&fwdEntry->ipnLink);\n- ipn->refCount--;\n-\n- if (ipf->refCount == 0) {\n- ASSERT(IsListEmpty(&ipf->fwdList));\n- RemoveEntryList(&ipf->link);\n- OvsFreeMemoryWithTag(ipf, OVS_IPHELPER_POOL_TAG);\n- }\n-\n- if (ipn->refCount == 0) {\n- ASSERT(IsListEmpty(&ipn->fwdList));\n- RemoveEntryList(&ipn->link);\n- NdisAcquireSpinLock(&ovsIpHelperLock);\n- RemoveEntryList(&ipn->slink);\n- NdisReleaseSpinLock(&ovsIpHelperLock);\n- OvsFreeMemoryWithTag(ipn, OVS_IPHELPER_POOL_TAG);\n- }\n-\n- OvsFreeMemoryWithTag(fwdEntry, OVS_IPHELPER_POOL_TAG);\n-}\n-\n-\n-static VOID\n-OvsRemoveIPForwardEntry(POVS_IPFORWARD_ENTRY ipf)\n-{\n- PLIST_ENTRY link, next;\n-\n- ipf->refCount++;\n-\n- LIST_FORALL_SAFE(&ipf->fwdList, link, next) {\n- POVS_FWD_ENTRY fwdEntry;\n-\n- fwdEntry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, ipfLink);\n- OvsRemoveFwdEntry(fwdEntry);\n- }\n- ASSERT(ipf->refCount == 1);\n-\n- RemoveEntryList(&ipf->link);\n- OvsFreeMemoryWithTag(ipf, OVS_IPHELPER_POOL_TAG);\n-}\n-\n-\n-static VOID\n-OvsRemoveIPNeighEntry(POVS_IPNEIGH_ENTRY ipn)\n-{\n- PLIST_ENTRY link, next;\n-\n- ipn->refCount++;\n-\n- LIST_FORALL_SAFE(&ipn->fwdList, link, next) {\n- POVS_FWD_ENTRY fwdEntry;\n-\n- fwdEntry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, ipnLink);\n- OvsRemoveFwdEntry(fwdEntry);\n- }\n-\n- if (ipn->refCount == 1) {\n- RemoveEntryList(&ipn->link);\n- NdisAcquireSpinLock(&ovsIpHelperLock);\n- RemoveEntryList(&ipn->slink);\n- NdisReleaseSpinLock(&ovsIpHelperLock);\n- OvsFreeMemoryWithTag(ipn, OVS_IPHELPER_POOL_TAG);\n- }\n-}\n-\n-\n-static VOID\n-OvsAddToSortedNeighList(POVS_IPNEIGH_ENTRY ipn)\n-{\n- PLIST_ENTRY link;\n-\n- if (!IsListEmpty(&ovsSortedIPNeighList)) {\n- link = ovsSortedIPNeighList.Blink;\n- POVS_IPNEIGH_ENTRY entry;\n- entry = CONTAINING_RECORD(link, OVS_IPNEIGH_ENTRY, slink);\n- if (entry->timeout > ipn->timeout) {\n- ipn->timeout++;\n- }\n- }\n- InsertTailList(&ovsSortedIPNeighList, &ipn->slink);\n-}\n-\n-\n-static VOID\n-OvsAddIPFwdCache(POVS_FWD_ENTRY fwdEntry,\n- POVS_IPFORWARD_ENTRY ipf,\n- POVS_IPNEIGH_ENTRY ipn)\n-\n-{\n- UINT32 hash;\n-\n- if (ipn->refCount == 0) {\n- NdisAcquireSpinLock(&ovsIpHelperLock);\n- OvsAddToSortedNeighList(ipn);\n- NdisReleaseSpinLock(&ovsIpHelperLock);\n- hash = OvsJhashIphHdr(&ipn->ipAddr);\n-\n- InsertHeadList(&ovsNeighHashTable[hash & OVS_NEIGH_HASH_TABLE_MASK],\n- &ipn->link);\n- }\n- if (ipf->refCount == 0) {\n- hash = OvsHashIPPrefix(&ipf->prefix);\n- InsertHeadList(&ovsRouteHashTable[hash & OVS_ROUTE_HASH_TABLE_MASK],\n- &ipf->link);\n- }\n-\n- InsertHeadList(&ipf->fwdList, &fwdEntry->ipfLink);\n- ipf->refCount++;\n- fwdEntry->ipf = ipf;\n-\n- InsertHeadList(&ipn->fwdList, &fwdEntry->ipnLink);\n- ipn->refCount++;\n- fwdEntry->ipn = ipn;\n-\n- hash = OvsJhashIphHdr(&(fwdEntry->info.dstIphAddr));\n-\n- InsertHeadList(&ovsFwdHashTable[hash & OVS_FWD_HASH_TABLE_MASK],\n- &fwdEntry->link);\n- ovsNumFwdEntries++;\n-}\n-\n-static VOID\n-OvsRemoveAllFwdEntriesWithSrc(SOCKADDR_INET ipAddr)\n-{\n- UINT32 i;\n- PLIST_ENTRY link, next;\n-\n- for (i = 0; i < OVS_FWD_HASH_TABLE_SIZE; i++) {\n- LIST_FORALL_SAFE(&ovsFwdHashTable[i], link, next) {\n- POVS_FWD_ENTRY fwdEntry;\n-\n- fwdEntry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, link);\n-\n- if (OvsIphAddrEquals(&(fwdEntry->info.srcIphAddr), &ipAddr)) {\n- OvsRemoveFwdEntry(fwdEntry);\n- }\n- }\n- }\n-}\n-\n-static VOID\n-OvsRemoveIPNeighEntriesWithInstance(POVS_IPHELPER_INSTANCE instance)\n-{\n- if (ovsNumFwdEntries) {\n- POVS_IPNEIGH_ENTRY ipn;\n- PLIST_ENTRY link, next;\n- LIST_FORALL_SAFE(&ovsSortedIPNeighList, link, next) {\n- ipn = CONTAINING_RECORD(link, OVS_IPNEIGH_ENTRY, slink);\n- POVS_IPHELPER_INSTANCE ipnInstance = ipn->instance;\n- if (ipnInstance == instance) {\n- OvsRemoveIPNeighEntry(ipn);\n- }\n- }\n- }\n-}\n-\n-static VOID\n-OvsCleanupFwdTable(VOID)\n-{\n- PLIST_ENTRY link, next;\n- UINT32 i;\n- LOCK_STATE_EX lockState;\n-\n- NdisAcquireRWLockWrite(ovsTableLock, &lockState, 0);\n- if (ovsNumFwdEntries) {\n- LIST_FORALL_SAFE(&ovsSortedIPNeighList, link, next) {\n- POVS_IPNEIGH_ENTRY ipn;\n-\n- ipn = CONTAINING_RECORD(link, OVS_IPNEIGH_ENTRY, slink);\n- OvsRemoveIPNeighEntry(ipn);\n- }\n- }\n- for (i = 0; i < OVS_FWD_HASH_TABLE_SIZE; i++) {\n- ASSERT(IsListEmpty(&ovsFwdHashTable[i]));\n- }\n- for (i = 0; i < OVS_ROUTE_HASH_TABLE_SIZE; i++) {\n- ASSERT(IsListEmpty(&ovsRouteHashTable[i]));\n- }\n- NdisReleaseRWLock(ovsTableLock, &lockState);\n-}\n-\n-\n-static VOID\n-OvsCleanupIpHelperRequestList(VOID)\n-{\n- LIST_ENTRY list;\n- PLIST_ENTRY next, link;\n-\n- NdisAcquireSpinLock(&ovsIpHelperLock);\n- InitializeListHead(&list);\n- OvsAppendList(&list, &ovsIpHelperRequestList);\n- ovsNumIpHelperRequests = 0;\n- NdisReleaseSpinLock(&ovsIpHelperLock);\n-\n- LIST_FORALL_SAFE(&list, link, next) {\n- POVS_IP_HELPER_REQUEST request;\n-\n- request = CONTAINING_RECORD(link, OVS_IP_HELPER_REQUEST, link);\n-\n- if (request->command == OVS_IP_HELPER_FWD_REQUEST &&\n- request->fwdReq.cb) {\n- request->fwdReq.cb(request->fwdReq.nbl,\n- request->fwdReq.inPort,\n- &request->fwdReq.tunnelKey,\n- request->fwdReq.cbData1,\n- request->fwdReq.cbData2,\n- STATUS_DEVICE_NOT_READY,\n- NULL);\n- }\n- OvsFreeMemoryWithTag(request, OVS_IPHELPER_POOL_TAG);\n- }\n-}\n-\n-\n-\n-static VOID\n-OvsWakeupIPHelper(VOID)\n-{\n- KeSetEvent(&ovsIpHelperThreadContext.event, 0, FALSE);\n-}\n-\n-VOID\n-OvsInternalAdapterDown(UINT32 portNo,\n- GUID netCfgInstanceId)\n-{\n- POVS_IP_HELPER_REQUEST request;\n-\n- request = (POVS_IP_HELPER_REQUEST)OvsAllocateMemoryWithTag(\n- sizeof(OVS_IP_HELPER_REQUEST), OVS_IPHELPER_POOL_TAG);\n- if (request == NULL) {\n- OVS_LOG_ERROR(\"Fail to initialize Internal Adapter\");\n- return;\n- }\n- RtlZeroMemory(request, sizeof (OVS_IP_HELPER_REQUEST));\n- RtlCopyMemory(&request->instanceReq.netCfgInstanceId,\n- &netCfgInstanceId,\n- sizeof(netCfgInstanceId));\n- request->command = OVS_IP_HELPER_INTERNAL_ADAPTER_DOWN;\n- request->instanceReq.portNo = portNo;\n-\n- NdisAcquireSpinLock(&ovsIpHelperLock);\n- InsertHeadList(&ovsIpHelperRequestList, &request->link);\n- ovsNumIpHelperRequests++;\n- if (ovsNumIpHelperRequests == 1) {\n- OvsWakeupIPHelper();\n- }\n- NdisReleaseSpinLock(&ovsIpHelperLock);\n-}\n-\n-\n-VOID\n-OvsInternalAdapterUp(UINT32 portNo,\n- GUID *netCfgInstanceId)\n-{\n- POVS_IP_HELPER_REQUEST request;\n-\n- request = (POVS_IP_HELPER_REQUEST)OvsAllocateMemoryWithTag(\n- sizeof(OVS_IP_HELPER_REQUEST), OVS_IPHELPER_POOL_TAG);\n- if (request == NULL) {\n- OVS_LOG_ERROR(\"Fail to initialize Internal Adapter\");\n- return;\n- }\n- RtlZeroMemory(request, sizeof (OVS_IP_HELPER_REQUEST));\n- RtlCopyMemory(&request->instanceReq.netCfgInstanceId,\n- netCfgInstanceId,\n- sizeof(*netCfgInstanceId));\n- request->command = OVS_IP_HELPER_INTERNAL_ADAPTER_UP;\n- request->instanceReq.portNo = portNo;\n-\n- NdisAcquireSpinLock(&ovsIpHelperLock);\n- InsertHeadList(&ovsIpHelperRequestList, &request->link);\n- ovsNumIpHelperRequests++;\n- if (ovsNumIpHelperRequests == 1) {\n- NdisReleaseSpinLock(&ovsIpHelperLock);\n- OvsWakeupIPHelper();\n- } else {\n- NdisReleaseSpinLock(&ovsIpHelperLock);\n- }\n-}\n-\n-\n-static POVS_IPHELPER_INSTANCE\n-OvsIpHelperAllocateInstance(POVS_IP_HELPER_REQUEST request)\n-{\n- POVS_IPHELPER_INSTANCE instance = NULL;\n-\n- instance = (POVS_IPHELPER_INSTANCE)OvsAllocateMemoryWithTag(\n- sizeof(*instance), OVS_IPHELPER_POOL_TAG);\n- if (instance) {\n- RtlZeroMemory(instance, sizeof(*instance));\n-\n- RtlCopyMemory(&instance->netCfgId,\n- &request->instanceReq.netCfgInstanceId,\n- sizeof(instance->netCfgId));\n- instance->portNo = request->instanceReq.portNo;\n-\n- InitializeListHead(&instance->link);\n- ExInitializeResourceLite(&instance->lock);\n- }\n-\n- return instance;\n-}\n-\n-\n-static VOID\n-OvsIpHelperDeleteInstance(POVS_IPHELPER_INSTANCE instance)\n-{\n- if (instance) {\n- ExDeleteResourceLite(&instance->lock);\n- OvsFreeMemoryWithTag(instance, OVS_IPHELPER_POOL_TAG);\n- }\n-}\n-\n-\n-static VOID\n-OvsIpHelperDeleteAllInstances()\n-{\n- PLIST_ENTRY head, link, next;\n-\n- ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE);\n- head = &ovsInstanceList;\n- if (!IsListEmpty(head)) {\n- LIST_FORALL_SAFE(head, link, next) {\n- POVS_IPHELPER_INSTANCE instance = NULL;\n- instance = CONTAINING_RECORD(link, OVS_IPHELPER_INSTANCE, link);\n-\n- ExAcquireResourceExclusiveLite(&instance->lock, TRUE);\n-\n- instance->isIpConfigured = FALSE;\n- RemoveEntryList(&instance->link);\n-\n- ExReleaseResourceLite(&instance->lock);\n-\n- OvsIpHelperDeleteInstance(instance);\n- }\n- }\n- ExReleaseResourceLite(&ovsInstanceListLock);\n-}\n-\n-\n-static VOID\n-OvsHandleInternalAdapterUp(POVS_IP_HELPER_REQUEST request)\n-{\n- NTSTATUS status;\n- POVS_IPHELPER_INSTANCE instance = NULL;\n- MIB_UNICASTIPADDRESS_ROW ipEntry;\n- BOOLEAN error = TRUE;\n-\n- do {\n- instance = OvsIpHelperAllocateInstance(request);\n- if (instance == NULL) {\n- break;\n- }\n- RtlZeroMemory(&instance->internalRow, sizeof(MIB_IF_ROW2));\n- RtlZeroMemory(&instance->internalIPRow, sizeof(MIB_IPINTERFACE_ROW));\n- status = OvsGetIfEntry(&instance->netCfgId,\n- &instance->internalRow);\n-\n- if (status != STATUS_SUCCESS) {\n- OvsDumpMessageWithGuid(\"Fail to get IF entry for internal port with GUID\"\n- \" %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x\",\n- instance->netCfgId);\n- break;\n- }\n-\n- status = OvsGetIPInterfaceEntry(instance->internalRow.InterfaceLuid,\n- &instance->internalIPRow);\n-\n- if (status == STATUS_SUCCESS) {\n- instance->isIpConfigured = TRUE;\n- } else {\n- break;\n- }\n-\n- status = OvsGetIPEntry(instance->internalRow.InterfaceLuid, &ipEntry);\n- if (status != STATUS_SUCCESS) {\n- OvsDumpMessageWithGuid(\"Fail to get IP entry for internal port with GUID\"\n- \" %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x\",\n- instance->netCfgId);\n- }\n-\n- ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE);\n- InsertHeadList(&ovsInstanceList, &instance->link);\n- ExReleaseResourceLite(&ovsInstanceListLock);\n-\n- error = FALSE;\n- } while (error);\n-\n- OvsFreeMemoryWithTag(request, OVS_IPHELPER_POOL_TAG);\n- if (error) {\n- OvsIpHelperDeleteInstance(instance);\n- }\n-}\n-\n-\n-static NTSTATUS\n-OvsEnqueueIpHelperRequest(POVS_IP_HELPER_REQUEST request)\n-{\n- if (IsListEmpty(&ovsInstanceList)) {\n- OvsFreeMemoryWithTag(request, OVS_IPHELPER_POOL_TAG);\n- return STATUS_NDIS_ADAPTER_NOT_READY;\n- } else {\n- NdisAcquireSpinLock(&ovsIpHelperLock);\n- InsertHeadList(&ovsIpHelperRequestList, &request->link);\n- ovsNumIpHelperRequests++;\n- if (ovsNumIpHelperRequests == 1) {\n- OvsWakeupIPHelper();\n- }\n- NdisReleaseSpinLock(&ovsIpHelperLock);\n- return STATUS_SUCCESS;\n- }\n-}\n-\n-\n-NTSTATUS\n-OvsFwdIPHelperRequest(PNET_BUFFER_LIST nbl,\n- UINT32 inPort,\n- const OvsIPTunnelKey *tunnelKey,\n- OvsIPHelperCallback cb,\n- PVOID cbData1,\n- PVOID cbData2)\n-{\n- POVS_IP_HELPER_REQUEST request;\n-\n- request = (POVS_IP_HELPER_REQUEST)OvsAllocateMemoryWithTag(\n- sizeof(OVS_IP_HELPER_REQUEST), OVS_IPHELPER_POOL_TAG);\n-\n- if (request == NULL) {\n- return STATUS_INSUFFICIENT_RESOURCES;\n- }\n- request->command = OVS_IP_HELPER_FWD_REQUEST;\n- request->fwdReq.nbl = nbl;\n- request->fwdReq.inPort = inPort;\n- RtlCopyMemory(&request->fwdReq.tunnelKey, tunnelKey,\n- sizeof (*tunnelKey));\n- request->fwdReq.cb = cb;\n- request->fwdReq.cbData1 = cbData1;\n- request->fwdReq.cbData2 = cbData2;\n- return OvsEnqueueIpHelperRequest(request);\n-}\n-\n-static VOID\n-OvsHandleFwdRequest(POVS_IP_HELPER_REQUEST request)\n-{\n- NTSTATUS status;\n- MIB_IPFORWARD_ROW2 ipRoute;\n- MIB_IPNET_ROW2 ipNeigh;\n- OVS_FWD_INFO fwdInfo;\n- SOCKADDR_INET iphAddr;\n- SOCKADDR_INET srcAddr;\n- POVS_FWD_ENTRY fwdEntry = NULL;\n- POVS_IPFORWARD_ENTRY ipf = NULL;\n- POVS_IPNEIGH_ENTRY ipn = NULL;\n- LOCK_STATE_EX lockState;\n- BOOLEAN newIPF = FALSE;\n- BOOLEAN newIPN = FALSE;\n- BOOLEAN newFWD = FALSE;\n- POVS_IPHELPER_INSTANCE instance = NULL;\n-\n- RtlZeroMemory(&fwdInfo, sizeof(OVS_FWD_INFO));\n-\n- status = OvsLookupIPhFwdInfo(request->fwdReq.tunnelKey.src,\n- request->fwdReq.tunnelKey.dst,\n- &fwdInfo);\n- if (status == STATUS_SUCCESS) {\n- goto fwd_handle_nbl;\n- }\n-\n- /* find IPRoute */\n- RtlZeroMemory(&srcAddr, sizeof(srcAddr));\n- RtlZeroMemory(&iphAddr, sizeof(iphAddr));\n- RtlZeroMemory(&ipRoute, sizeof (MIB_IPFORWARD_ROW2));\n- status = OvsGetRoute(&request->fwdReq.tunnelKey.dst, &ipRoute, &srcAddr,\n- &instance, &fwdInfo.vport,\n- request->fwdReq.tunnelKey.src);\n- if (!OvsIphIsZero(&(request->fwdReq.tunnelKey.src)) &&\n- !OvsIphAddrEquals(&(request->fwdReq.tunnelKey.src), &srcAddr)) {\n- OvsDumpIpAddrDescStatus(\"Fail to get route to\",\n- status, &(request->fwdReq.tunnelKey.dst));\n- goto fwd_handle_nbl;\n- }\n- if (status != STATUS_SUCCESS || instance == NULL) {\n- OvsDumpIpAddrDescStatus(\"Fail to get route to\",\n- status, &(request->fwdReq.tunnelKey.dst));\n- goto fwd_handle_nbl;\n- }\n-\n- ExAcquireResourceExclusiveLite(&instance->lock, TRUE);\n- /* find IPNeigh */\n- OvsCopyIphAddress(&iphAddr, &(ipRoute.NextHop));\n- if (!OvsIphIsZero(&iphAddr)) {\n- NdisAcquireRWLockWrite(ovsTableLock, &lockState, 0);\n- ipn = OvsLookupIPNeighEntry(iphAddr);\n- if (ipn) {\n- goto fwd_request_done;\n- }\n- NdisReleaseRWLock(ovsTableLock, &lockState);\n- }\n-\n- RtlZeroMemory(&ipNeigh, sizeof (ipNeigh));\n- ipNeigh.InterfaceLuid.Value = instance->internalRow.InterfaceLuid.Value;\n- if (OvsIphIsZero(&iphAddr)) {\n- OvsCopyIphAddress(&iphAddr, &(request->fwdReq.tunnelKey.dst));\n- }\n- status = OvsGetOrResolveIPNeigh(&instance->internalRow,\n- iphAddr, &ipNeigh);\n- if (status != STATUS_SUCCESS) {\n- ExReleaseResourceLite(&instance->lock);\n- goto fwd_handle_nbl;\n- }\n-\n- NdisAcquireRWLockWrite(ovsTableLock, &lockState, 0);\n-\n-fwd_request_done:\n-\n- /*\n- * Initialize ipf\n- */\n- ipf = OvsLookupIPForwardEntry(&ipRoute.DestinationPrefix);\n- if (ipf == NULL) {\n- ipf = OvsCreateIPForwardEntry(&ipRoute);\n- if (ipf == NULL) {\n- NdisReleaseRWLock(ovsTableLock, &lockState);\n- ExReleaseResourceLite(&instance->lock);\n- status = STATUS_INSUFFICIENT_RESOURCES;\n- goto fwd_handle_nbl;\n- }\n- newIPF = TRUE;\n- } else {\n- PLIST_ENTRY link;\n- link = ipf->fwdList.Flink;\n- fwdEntry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, ipfLink);\n- if (!OvsIphAddrEquals(&(fwdEntry->info.srcIphAddr), &srcAddr)) {\n- OvsRemoveFwdEntry(fwdEntry);\n- NdisReleaseRWLock(ovsTableLock, &lockState);\n- ExReleaseResourceLite(&instance->lock);\n- status = STATUS_INSUFFICIENT_RESOURCES;\n- goto fwd_handle_nbl;\n- }\n- OvsCopyIphAddress(&srcAddr, &(fwdEntry->info.srcIphAddr));\n- }\n-\n- /*\n- * initialize ipn\n- */\n- if (ipn == NULL) {\n- ipn = OvsLookupIPNeighEntry(iphAddr);\n- if (ipn == NULL) {\n- ipn = OvsCreateIPNeighEntry(&ipNeigh, instance);\n- if (ipn == NULL) {\n- NdisReleaseRWLock(ovsTableLock, &lockState);\n- ExReleaseResourceLite(&instance->lock);\n- status = STATUS_INSUFFICIENT_RESOURCES;\n- goto fwd_handle_nbl;\n- }\n- newIPN = TRUE;\n- }\n- }\n-\n- /*\n- * initialize fwdEntry\n- */\n- OvsCopyIphAddress(&fwdInfo.dstIphAddr, &(request->fwdReq.tunnelKey.dst));\n- OvsCopyIphAddress(&fwdInfo.srcIphAddr, &srcAddr);\n- RtlCopyMemory(fwdInfo.dstMacAddr, ipn->macAddr, ETH_ADDR_LEN);\n- RtlCopyMemory(fwdInfo.srcMacAddr, instance->internalRow.PhysicalAddress,\n- ETH_ADDR_LEN);\n- fwdInfo.srcPortNo = request->fwdReq.inPort;\n-\n- fwdEntry = OvsCreateFwdEntry(&fwdInfo);\n- if (fwdEntry == NULL) {\n- NdisReleaseRWLock(ovsTableLock, &lockState);\n- ExReleaseResourceLite(&instance->lock);\n- status = STATUS_INSUFFICIENT_RESOURCES;\n- goto fwd_handle_nbl;\n- }\n- newFWD = TRUE;\n-\n- if (status == STATUS_SUCCESS) {\n- /*\n- * Cache the result\n- */\n- OvsAddIPFwdCache(fwdEntry, ipf, ipn);\n- NdisReleaseRWLock(ovsTableLock, &lockState);\n- ExReleaseResourceLite(&instance->lock);\n- }\n-\n-fwd_handle_nbl:\n-\n- if (status != STATUS_SUCCESS) {\n- if (newFWD) {\n- ASSERT(fwdEntry != NULL);\n- OvsFreeMemoryWithTag(fwdEntry, OVS_IPHELPER_POOL_TAG);\n- }\n- if (newIPF) {\n- ASSERT(ipf && ipf->refCount == 0);\n- OvsFreeMemoryWithTag(ipf, OVS_IPHELPER_POOL_TAG);\n- }\n- if (newIPN) {\n- ASSERT(ipn && ipn->refCount == 0);\n- OvsFreeMemoryWithTag(ipn, OVS_IPHELPER_POOL_TAG);\n- }\n- OvsCopyIphAddress(&iphAddr, &(request->fwdReq.tunnelKey.dst));\n- OvsDumpIpAddrMsg(\"Fail to handle IP helper request for dst\", &iphAddr);\n- }\n- if (request->fwdReq.cb) {\n- request->fwdReq.cb(request->fwdReq.nbl,\n- request->fwdReq.inPort,\n- &request->fwdReq.tunnelKey,\n- request->fwdReq.cbData1,\n- request->fwdReq.cbData2,\n- status,\n- status == STATUS_SUCCESS ? &fwdInfo : NULL);\n- }\n- OvsFreeMemoryWithTag(request, OVS_IPHELPER_POOL_TAG);\n-}\n-\n-static VOID\n-OvsUpdateIPNeighEntry(SOCKADDR_INET ipAddr,\n- PMIB_IPNET_ROW2 ipNeigh,\n- NTSTATUS status)\n-{\n- UINT64 timeVal;\n- POVS_IPNEIGH_ENTRY ipn;\n- LOCK_STATE_EX lockState;\n- KeQuerySystemTime((LARGE_INTEGER *)&timeVal);\n- /*\n- * if mac changed, update all relevant fwdEntry\n- */\n- if (status != STATUS_SUCCESS) {\n- NdisAcquireRWLockWrite(ovsTableLock, &lockState, 0);\n- } else {\n- NdisAcquireRWLockRead(ovsTableLock, &lockState, 0);\n- }\n- ipn = OvsLookupIPNeighEntry(ipAddr);\n- if (ipn == NULL) {\n- NdisReleaseRWLock(ovsTableLock, &lockState);\n- return;\n- }\n- if (status != STATUS_SUCCESS) {\n- OvsRemoveIPNeighEntry(ipn);\n- NdisReleaseRWLock(ovsTableLock, &lockState);\n- return;\n- }\n-\n- if (memcmp((const PVOID)ipn->macAddr,\n- (const PVOID)ipNeigh->PhysicalAddress,\n- (size_t)ETH_ADDR_LEN)) {\n- PLIST_ENTRY link;\n- NdisReleaseRWLock(ovsTableLock, &lockState);\n- /*\n- * need update, release and acquire write lock\n- * This is not the common case.\n- */\n-\n- NdisAcquireRWLockWrite(ovsTableLock, &lockState, 0);\n- ipn = OvsLookupIPNeighEntry(ipAddr);\n-\n- if (ipn == NULL) {\n- NdisReleaseRWLock(ovsTableLock, &lockState);\n- return;\n- }\n-\n- LIST_FORALL(&ipn->fwdList, link) {\n- POVS_FWD_ENTRY fwdEntry;\n- fwdEntry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, ipnLink);\n- RtlCopyMemory(fwdEntry->info.dstMacAddr,\n- ipNeigh->PhysicalAddress, ETH_ADDR_LEN);\n- }\n- }\n- /*\n- * update timeout and move to the end of\n- * the sorted list\n- */\n-\n- NdisAcquireSpinLock(&ovsIpHelperLock);\n- RemoveEntryList(&ipn->slink);\n- ipn->timeout = timeVal + OVS_IPNEIGH_TIMEOUT;\n- OvsAddToSortedNeighList(ipn);\n- NdisReleaseSpinLock(&ovsIpHelperLock);\n- NdisReleaseRWLock(ovsTableLock, &lockState);\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * IP Helper system thread handles the following requests:\n- * 1. Intialize Internal port row when internal port is connected\n- * 2. Handle FWD request\n- * 3. Handle IP Neigh timeout\n- *\n- * IP Interface, unicast address, and IP route change will be handled\n- * by the revelant callbacks.\n- *----------------------------------------------------------------------------\n- */\n-VOID\n-OvsStartIpHelper(PVOID data)\n-{\n- POVS_IP_HELPER_THREAD_CONTEXT context = (POVS_IP_HELPER_THREAD_CONTEXT)data;\n- POVS_IP_HELPER_REQUEST req;\n- POVS_IPNEIGH_ENTRY ipn;\n- PLIST_ENTRY link;\n- UINT64 timeVal, timeout;\n- PLARGE_INTEGER threadSleepTimeout;\n-\n- OVS_LOG_INFO(\"Start the IP Helper Thread, context: %p\", context);\n-\n- NdisAcquireSpinLock(&ovsIpHelperLock);\n- while (!context->exit) {\n-\n- threadSleepTimeout = NULL;\n- timeout = 0;\n- while (!IsListEmpty(&ovsIpHelperRequestList)) {\n- if (context->exit) {\n- goto ip_helper_wait;\n- }\n- link = ovsIpHelperRequestList.Flink;\n- RemoveEntryList(link);\n- ovsNumIpHelperRequests--;\n- NdisReleaseSpinLock(&ovsIpHelperLock);\n- req = CONTAINING_RECORD(link, OVS_IP_HELPER_REQUEST, link);\n- switch (req->command) {\n- case OVS_IP_HELPER_INTERNAL_ADAPTER_UP:\n- OvsHandleInternalAdapterUp(req);\n- break;\n- case OVS_IP_HELPER_INTERNAL_ADAPTER_DOWN:\n- {\n- PLIST_ENTRY head, current, next;\n- UINT32 portNo = req->instanceReq.portNo;\n- GUID netCfgInstanceId = req->instanceReq.netCfgInstanceId;\n-\n- ExAcquireResourceExclusiveLite(&ovsInstanceListLock, TRUE);\n- head = &ovsInstanceList;\n- LIST_FORALL_SAFE(head, current, next) {\n- POVS_IPHELPER_INSTANCE instance = NULL;\n- LOCK_STATE_EX lockState;\n-\n- instance = CONTAINING_RECORD(current, OVS_IPHELPER_INSTANCE,\n- link);\n-\n- ExAcquireResourceExclusiveLite(&instance->lock, TRUE);\n- if (instance->portNo == portNo &&\n- IsEqualGUID(&instance->netCfgId, &netCfgInstanceId)) {\n-\n- NdisAcquireRWLockWrite(ovsTableLock, &lockState, 0);\n- OvsRemoveIPNeighEntriesWithInstance(instance);\n- NdisReleaseRWLock(ovsTableLock, &lockState);\n-\n- RemoveEntryList(&instance->link);\n-\n- ExReleaseResourceLite(&instance->lock);\n-\n- OvsIpHelperDeleteInstance(instance);\n- break;\n- }\n- ExReleaseResourceLite(&instance->lock);\n- }\n-\n- if (IsListEmpty(&ovsInstanceList)) {\n- OvsCleanupIpHelperRequestList();\n-\n- OvsCleanupFwdTable();\n- }\n- ExReleaseResourceLite(&ovsInstanceListLock);\n- }\n- case OVS_IP_HELPER_FWD_REQUEST:\n- OvsHandleFwdRequest(req);\n- break;\n- default:\n- OvsFreeMemoryWithTag(req, OVS_IPHELPER_POOL_TAG);\n- }\n- NdisAcquireSpinLock(&ovsIpHelperLock);\n- }\n-\n- /* for now, let us hold the lock here, if this cause any issue\n- * we will change to use IpHelper lock only to protect\n- * IPN\n- */\n- while (!IsListEmpty(&ovsSortedIPNeighList)) {\n- SOCKADDR_INET ipAddr;\n- if (context->exit) {\n- goto ip_helper_wait;\n- }\n- link = ovsSortedIPNeighList.Flink;\n- ipn = CONTAINING_RECORD(link, OVS_IPNEIGH_ENTRY, slink);\n- KeQuerySystemTime((LARGE_INTEGER *)&timeVal);\n- if (ipn->timeout > timeVal) {\n- timeout = ipn->timeout;\n- threadSleepTimeout = (PLARGE_INTEGER)&timeout;\n- break;\n- }\n- RtlCopyMemory(&ipAddr, &ipn->ipAddr, sizeof(ipAddr));\n- MIB_IPNET_ROW2 ipNeigh;\n- NTSTATUS status;\n- POVS_IPHELPER_INSTANCE instance = ipn->instance;\n- NdisReleaseSpinLock(&ovsIpHelperLock);\n-\n- if (instance) {\n- ExAcquireResourceExclusiveLite(&instance->lock, TRUE);\n-\n- status = OvsGetOrResolveIPNeigh(&instance->internalRow,\n- ipAddr, &ipNeigh);\n- OvsUpdateIPNeighEntry(ipAddr, &ipNeigh, status);\n-\n- ExReleaseResourceLite(&instance->lock);\n- }\n- NdisAcquireSpinLock(&ovsIpHelperLock);\n- }\n- if (!IsListEmpty(&ovsIpHelperRequestList)) {\n- continue;\n- }\n-\n-ip_helper_wait:\n- if (context->exit) {\n- break;\n- }\n-\n- KeClearEvent(&context->event);\n- NdisReleaseSpinLock(&ovsIpHelperLock);\n-\n- /*\n- * Wait indefinitely for the thread to be woken up.\n- * Passing NULL as the Timeout value in the below\n- * call to KeWaitForSingleObject achieves this.\n- */\n- KeWaitForSingleObject(&context->event, Executive, KernelMode,\n- FALSE, threadSleepTimeout);\n- NdisAcquireSpinLock(&ovsIpHelperLock);\n- }\n- NdisReleaseSpinLock(&ovsIpHelperLock);\n- OvsCleanupFwdTable();\n- OvsCleanupIpHelperRequestList();\n- OVS_LOG_INFO(\"Terminating the OVS IP Helper system thread\");\n-\n- PsTerminateSystemThread(STATUS_SUCCESS);\n-}\n-\n-\n-NTSTATUS\n-OvsInitIpHelper(NDIS_HANDLE ndisFilterHandle)\n-{\n- NTSTATUS status = NDIS_STATUS_SUCCESS;\n- HANDLE threadHandle;\n- UINT32 i;\n-\n- status = ExInitializeResourceLite(&ovsInstanceListLock);\n- if (status != NDIS_STATUS_SUCCESS) {\n- return status;\n- }\n- InitializeListHead(&ovsInstanceList);\n-\n- ovsFwdHashTable = (PLIST_ENTRY)OvsAllocateMemoryWithTag(\n- sizeof(LIST_ENTRY) * OVS_FWD_HASH_TABLE_SIZE, OVS_IPHELPER_POOL_TAG);\n-\n- ovsRouteHashTable = (PLIST_ENTRY)OvsAllocateMemoryWithTag(\n- sizeof(LIST_ENTRY) * OVS_ROUTE_HASH_TABLE_SIZE, OVS_IPHELPER_POOL_TAG);\n-\n- ovsNeighHashTable = (PLIST_ENTRY)OvsAllocateMemoryWithTag(\n- sizeof(LIST_ENTRY) * OVS_NEIGH_HASH_TABLE_SIZE, OVS_IPHELPER_POOL_TAG);\n-\n- InitializeListHead(&ovsSortedIPNeighList);\n-\n- ovsTableLock = NdisAllocateRWLock(ndisFilterHandle);\n- NdisAllocateSpinLock(&ovsIpHelperLock);\n-\n- InitializeListHead(&ovsIpHelperRequestList);\n- ovsNumIpHelperRequests = 0;\n- ipInterfaceNotificationHandle = NULL;\n- ipRouteNotificationHandle = NULL;\n- unicastIPNotificationHandle = NULL;\n-\n- if (ovsFwdHashTable == NULL ||\n- ovsRouteHashTable == NULL ||\n- ovsNeighHashTable == NULL ||\n- ovsTableLock == NULL) {\n- status = STATUS_INSUFFICIENT_RESOURCES;\n- goto init_cleanup;\n- }\n-\n- for (i = 0; i < OVS_FWD_HASH_TABLE_SIZE; i++) {\n- InitializeListHead(&ovsFwdHashTable[i]);\n- }\n-\n- for (i = 0; i < OVS_ROUTE_HASH_TABLE_SIZE; i++) {\n- InitializeListHead(&ovsRouteHashTable[i]);\n- }\n-\n- for (i = 0; i < OVS_NEIGH_HASH_TABLE_SIZE; i++) {\n- InitializeListHead(&ovsNeighHashTable[i]);\n- }\n-\n-\n- KeInitializeEvent(&ovsIpHelperThreadContext.event, NotificationEvent,\n- FALSE);\n- status = OvsRegisterChangeNotification();\n- ovsIpHelperThreadContext.exit = 0;\n- if (status == STATUS_SUCCESS) {\n- status = PsCreateSystemThread(&threadHandle, SYNCHRONIZE,\n- NULL, NULL, NULL, OvsStartIpHelper,\n- &ovsIpHelperThreadContext);\n- if (status != STATUS_SUCCESS) {\n- goto init_cleanup;\n- }\n- ObReferenceObjectByHandle(threadHandle, SYNCHRONIZE, NULL,\n- KernelMode,\n- &ovsIpHelperThreadContext.threadObject,\n- NULL);\n- ZwClose(threadHandle);\n- }\n-\n-init_cleanup:\n-\n- if (status != STATUS_SUCCESS) {\n- OvsCancelChangeNotification();\n- if (ovsFwdHashTable) {\n- OvsFreeMemoryWithTag(ovsFwdHashTable, OVS_IPHELPER_POOL_TAG);\n- ovsFwdHashTable = NULL;\n- }\n- if (ovsRouteHashTable) {\n- OvsFreeMemoryWithTag(ovsRouteHashTable, OVS_IPHELPER_POOL_TAG);\n- ovsRouteHashTable = NULL;\n- }\n- if (ovsNeighHashTable) {\n- OvsFreeMemoryWithTag(ovsNeighHashTable, OVS_IPHELPER_POOL_TAG);\n- ovsNeighHashTable = NULL;\n- }\n- if (ovsTableLock) {\n- NdisFreeRWLock(ovsTableLock);\n- ovsTableLock = NULL;\n- }\n- ExDeleteResourceLite(&ovsInstanceListLock);\n- NdisFreeSpinLock(&ovsIpHelperLock);\n- }\n- return status;\n-}\n-\n-\n-VOID\n-OvsCleanupIpHelper(VOID)\n-{\n- OvsCancelChangeNotification();\n-\n- NdisAcquireSpinLock(&ovsIpHelperLock);\n- ovsIpHelperThreadContext.exit = 1;\n- OvsWakeupIPHelper();\n- NdisReleaseSpinLock(&ovsIpHelperLock);\n-\n- KeWaitForSingleObject(ovsIpHelperThreadContext.threadObject, Executive,\n- KernelMode, FALSE, NULL);\n- ObDereferenceObject(ovsIpHelperThreadContext.threadObject);\n-\n- OvsFreeMemoryWithTag(ovsFwdHashTable, OVS_IPHELPER_POOL_TAG);\n- OvsFreeMemoryWithTag(ovsRouteHashTable, OVS_IPHELPER_POOL_TAG);\n- OvsFreeMemoryWithTag(ovsNeighHashTable, OVS_IPHELPER_POOL_TAG);\n-\n- NdisFreeRWLock(ovsTableLock);\n- NdisFreeSpinLock(&ovsIpHelperLock);\n-\n- OvsIpHelperDeleteAllInstances();\n- ExDeleteResourceLite(&ovsInstanceListLock);\n-}\n-\n-VOID\n-OvsCancelFwdIpHelperRequest(PNET_BUFFER_LIST nbl)\n-{\n- PLIST_ENTRY link, next;\n- POVS_IP_HELPER_REQUEST req;\n- LIST_ENTRY list;\n- InitializeListHead(&list);\n-\n- NdisAcquireSpinLock(&ovsIpHelperLock);\n- LIST_FORALL_SAFE(&ovsIpHelperRequestList, link, next) {\n- req = CONTAINING_RECORD(link, OVS_IP_HELPER_REQUEST, link);\n- if (req->command == OVS_IP_HELPER_FWD_REQUEST &&\n- (nbl == NULL || req->fwdReq.nbl == nbl)) {\n- RemoveEntryList(link);\n- InsertHeadList(&list, link);\n- if (nbl != NULL) {\n- break;\n- }\n- }\n- }\n- NdisReleaseSpinLock(&ovsIpHelperLock);\n-\n- LIST_FORALL_SAFE(&list, link, next) {\n- req = CONTAINING_RECORD(link, OVS_IP_HELPER_REQUEST, link);\n- if (req->fwdReq.cb) {\n- req->fwdReq.cb(req->fwdReq.nbl, req->fwdReq.inPort,\n- &req->fwdReq.tunnelKey,\n- req->fwdReq.cbData1,\n- req->fwdReq.cbData2,\n- STATUS_DEVICE_NOT_READY,\n- NULL);\n- }\n- OvsFreeMemoryWithTag(req, OVS_IPHELPER_POOL_TAG);\n- }\n-}\n-\n-uint32_t\n-OvsJhashIphHdr(const SOCKADDR_INET *iphAddr)\n-{\n- UINT32 hash = 0;\n-\n- if (!iphAddr) return 0;\n-\n- if (iphAddr->si_family == AF_INET) {\n- hash = OvsJhashWords((UINT32*)&iphAddr->Ipv4.sin_addr.s_addr,\n- 1, OVS_HASH_BASIS);\n- } else if (iphAddr->si_family == AF_INET6) {\n- hash = OvsJhashWords((UINT32 *)&(iphAddr->Ipv6.sin6_addr.u.Byte),\n- 4, OVS_HASH_BASIS);\n- }\n-\n- return hash;\n-}\n-\n-NTSTATUS\n-OvsConvertWcharToAnsiStr(WCHAR *wStr, size_t wlen,\n- CHAR* str,\n- size_t maxStrLen)\n-{\n- ANSI_STRING astr;\n- UNICODE_STRING ustr;\n- NTSTATUS status;\n- size_t size;\n-\n- ustr.Buffer = wStr;\n- ustr.Length = (UINT16)wlen;\n- ustr.MaximumLength = IF_MAX_STRING_SIZE;\n-\n- astr.Buffer = str;\n- astr.MaximumLength = (UINT16)maxStrLen;\n- astr.Length = 0;\n-\n- size = RtlUnicodeStringToAnsiSize(&ustr);\n- if (size > maxStrLen) {\n- return STATUS_BUFFER_OVERFLOW;\n- }\n-\n- status = RtlUnicodeStringToAnsiString(&astr, &ustr, FALSE);\n-\n- ASSERT(status == STATUS_SUCCESS);\n- if (status != STATUS_SUCCESS) {\n- return status;\n- }\n- ASSERT(astr.Length <= (UINT16)maxStrLen);\n- str[astr.Length] = 0;\n- return STATUS_SUCCESS;\n-}\ndiff --git a/datapath-windows/ovsext/IpHelper.h b/datapath-windows/ovsext/IpHelper.h\ndeleted file mode 100644\nindex f6955a06e..000000000\n--- a/datapath-windows/ovsext/IpHelper.h\n+++ /dev/null\n@@ -1,234 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#ifndef __IP_HELPER_H_\n-#define __IP_HELPER_H_ 1\n-\n-#include <ntddk.h>\n-#include <netioapi.h>\n-#include \"Vport.h\"\n-\n-#define OVS_FWD_HASH_TABLE_SIZE ((UINT32)1 << 10)\n-#define OVS_FWD_HASH_TABLE_MASK (OVS_FWD_HASH_TABLE_SIZE - 1)\n-\n-#define OVS_ROUTE_HASH_TABLE_SIZE ((UINT32)1 << 8)\n-#define OVS_ROUTE_HASH_TABLE_MASK (OVS_ROUTE_HASH_TABLE_SIZE - 1)\n-\n-#define OVS_NEIGH_HASH_TABLE_SIZE ((UINT32)1 << 8)\n-#define OVS_NEIGH_HASH_TABLE_MASK (OVS_NEIGH_HASH_TABLE_SIZE - 1)\n-\n-#define OVS_IPNEIGH_TIMEOUT 100000000 // 10 s\n-\n- /*\n- * This structure is used to define each adapter instance.\n- *\n- * Note:\n- * Only when the internal IP is configured and virtual\n- * internal port is connected, the IP helper request can be\n- * queued.\n- *\n- * We only keep internal IP for reference, it will not be used for determining\n- * SRC IP of the Tunnel.\n- *\n- * The lock must not raise the IRQL higher than PASSIVE_LEVEL in order for the\n- * route manipulation functions, i.e. GetBestRoute, to work.\n- */\n-\n-typedef struct _OVS_IPHELPER_INSTANCE\n-{\n- LIST_ENTRY link;\n-\n- BOOLEAN isIpConfigured;\n- UINT32 portNo;\n- GUID netCfgId;\n- MIB_IF_ROW2 internalRow;\n- MIB_IPINTERFACE_ROW internalIPRow;\n- SOCKADDR_INET ipAddress;\n- ERESOURCE lock;\n-} OVS_IPHELPER_INSTANCE, *POVS_IPHELPER_INSTANCE;\n-\n-\n-typedef struct _OVS_IPNEIGH_ENTRY {\n- UINT8 macAddr[ETH_ADDR_LEN];\n- UINT16 refCount;\n- SOCKADDR_INET ipAddr;\n- UINT32 pad;\n- UINT64 timeout;\n- LIST_ENTRY link;\n- LIST_ENTRY slink;\n- LIST_ENTRY fwdList;\n- POVS_IPHELPER_INSTANCE instance;\n-} OVS_IPNEIGH_ENTRY, *POVS_IPNEIGH_ENTRY;\n-\n-typedef struct _OVS_IPFORWARD_ENTRY {\n- IP_ADDRESS_PREFIX prefix;\n- SOCKADDR_INET nextHop;\n- UINT16 refCount;\n- LIST_ENTRY link;\n- LIST_ENTRY fwdList;\n-} OVS_IPFORWARD_ENTRY, *POVS_IPFORWARD_ENTRY;\n-\n-typedef union _OVS_FWD_INFO {\n- struct {\n- SOCKADDR_INET dstIphAddr;\n- SOCKADDR_INET srcIphAddr;\n- UINT8 dstMacAddr[ETH_ADDR_LEN];\n- UINT8 srcMacAddr[ETH_ADDR_LEN];\n- UINT32 srcPortNo;\n- POVS_VPORT_ENTRY vport;\n- };\n- UINT64 value[10];\n-} OVS_FWD_INFO, *POVS_FWD_INFO;\n-\n-typedef struct _OVS_FWD_ENTRY {\n- OVS_FWD_INFO info;\n- POVS_IPFORWARD_ENTRY ipf;\n- POVS_IPNEIGH_ENTRY ipn;\n- LIST_ENTRY link;\n- LIST_ENTRY ipfLink;\n- LIST_ENTRY ipnLink;\n-} OVS_FWD_ENTRY, *POVS_FWD_ENTRY;\n-\n-enum {\n- OVS_IP_HELPER_INTERNAL_ADAPTER_UP,\n- OVS_IP_HELPER_INTERNAL_ADAPTER_DOWN,\n- OVS_IP_HELPER_FWD_REQUEST,\n-};\n-\n-typedef VOID (*OvsIPHelperCallback)(PNET_BUFFER_LIST nbl,\n- UINT32 inPort,\n- PVOID tunnelKey,\n- PVOID cbData1,\n- PVOID cbData2,\n- NTSTATUS status,\n- POVS_FWD_INFO fwdInfo);\n-\n-typedef struct _OVS_FWD_REQUEST_INFO {\n- PNET_BUFFER_LIST nbl;\n- UINT32 inPort;\n- OvsIPTunnelKey tunnelKey;\n- OvsIPHelperCallback cb;\n- PVOID cbData1;\n- PVOID cbData2;\n-} OVS_FWD_REQUEST_INFO, *POVS_FWD_REQUEST_INFO;\n-\n-typedef struct _OVS_INSTANCE_REQUEST_INFO {\n- GUID netCfgInstanceId;\n- UINT32 portNo;\n-} OVS_INSTANCE_REQUEST_INFO, *POVS_INSTANCE_REQUEST_INFO;\n-\n-typedef struct _OVS_IP_HELPER_REQUEST {\n- LIST_ENTRY link;\n- UINT32 command;\n- union {\n- OVS_FWD_REQUEST_INFO fwdReq;\n- OVS_INSTANCE_REQUEST_INFO instanceReq;\n- };\n-} OVS_IP_HELPER_REQUEST, *POVS_IP_HELPER_REQUEST;\n-\n-\n-typedef struct _OVS_IP_HELPER_THREAD_CONTEXT {\n- KEVENT event;\n- PVOID threadObject;\n- UINT32 exit;\n-} OVS_IP_HELPER_THREAD_CONTEXT, *POVS_IP_HELPER_THREAD_CONTEXT;\n-\n-NTSTATUS OvsInitIpHelper(NDIS_HANDLE ndisFilterHandle);\n-VOID OvsCleanupIpHelper(VOID);\n-\n-VOID OvsInternalAdapterUp(UINT32 portNo, GUID *netCfgInstanceId);\n-VOID OvsInternalAdapterDown(UINT32 portNo, GUID netCfgInstanceId);\n-\n-NTSTATUS OvsFwdIPHelperRequest(PNET_BUFFER_LIST nbl, UINT32 inPort,\n- const PVOID tunnelKey,\n- OvsIPHelperCallback cb,\n- PVOID cbData1,\n- PVOID cbData2);\n-\n-VOID OvsCancelFwdIpHelperRequest(PNET_BUFFER_LIST nbl);\n-\n-NTSTATUS\n-OvsLookupIPhFwdInfo(SOCKADDR_INET srcIp, SOCKADDR_INET dstIp,\n- POVS_FWD_INFO info);\n-\n-static __inline BOOLEAN\n-OvsIphAddrEquals(const SOCKADDR_INET *src, const SOCKADDR_INET *dst)\n-{\n- BOOLEAN addrEqual = FALSE;\n- if (!src || !dst) return FALSE;\n-\n- if (src->si_family == AF_INET &&\n- dst->si_family == AF_INET) {\n- addrEqual = (src->Ipv4.sin_addr.s_addr == dst->Ipv4.sin_addr.s_addr);\n- } else if(src->si_family == AF_INET6 &&\n- dst->si_family == AF_INET6) {\n- if (RtlEqualMemory(&src->Ipv6.sin6_addr,\n- &dst->Ipv6.sin6_addr,\n- sizeof(src->Ipv6.sin6_addr))) {\n- addrEqual = TRUE;\n- }\n- }\n- return addrEqual;\n-}\n-\n-/* check if the pointers to SOCKADDR_INET is zero*/\n-static __inline BOOLEAN\n-OvsIphIsZero(const SOCKADDR_INET *ipAddr)\n-{\n- BOOLEAN isZero = FALSE;\n- UCHAR zeros[16] = { 0 };\n- if (!ipAddr) return FALSE;\n-\n- if (ipAddr->si_family == AF_INET ||\n- ipAddr->si_family == AF_UNSPEC) {\n- isZero = (ipAddr->Ipv4.sin_addr.s_addr == 0);\n- } else if(ipAddr->si_family == AF_INET6) {\n- if (RtlEqualMemory(&ipAddr->Ipv6.sin6_addr.u.Byte,\n- &zeros,\n- sizeof(ipAddr->Ipv6.sin6_addr))) {\n- isZero = TRUE;\n- }\n- }\n- return isZero;\n-}\n-\n-/* Copy the content from the pointer to SOCKADDR_INET\n- * To the pointer to SOCKADDR_INET\n- */\n-static __inline void\n-OvsCopyIphAddress(SOCKADDR_INET *dstAddr, const SOCKADDR_INET *srcAddr)\n-{\n- if (!srcAddr || !dstAddr) return;\n-\n- dstAddr->si_family = srcAddr->si_family;\n-\n- if (srcAddr->si_family == AF_INET) {\n- dstAddr->Ipv4.sin_addr.s_addr = srcAddr->Ipv4.sin_addr.s_addr;\n- } else if (srcAddr->si_family == AF_INET6) {\n- RtlCopyMemory(&dstAddr->Ipv6, &srcAddr->Ipv6,\n- sizeof(srcAddr->Ipv6));\n- }\n- return;\n-}\n-\n-/* compute the hash value based on SOCKADDR_INET*/\n-uint32_t\n-OvsJhashIphHdr(const SOCKADDR_INET *iphAddr);\n-\n-NTSTATUS\n-OvsConvertWcharToAnsiStr(WCHAR* wStr, size_t wlen,\n- CHAR* str, size_t maxStrLen);\n-#endif /* __IP_HELPER_H_ */\ndiff --git a/datapath-windows/ovsext/Jhash.c b/datapath-windows/ovsext/Jhash.c\ndeleted file mode 100644\nindex f42104d57..000000000\n--- a/datapath-windows/ovsext/Jhash.c\n+++ /dev/null\n@@ -1,131 +0,0 @@\n-/*\n- * Copyright (c) 2008, 2009, 2010, 2012, 2014 Nicira, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#include \"precomp.h\"\n-\n-static __inline UINT32\n-GetUnalignedU32(const UINT32 *p_)\n-{\n- const UINT8 *p = (const UINT8 *)p_;\n- return ntohl((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);\n-}\n-\n-/* This is the public domain lookup3 hash by Bob Jenkins from\n- * http://burtleburtle.net/bob/c/lookup3.c, modified for style. */\n-\n-static __inline UINT32\n-JhashRot(UINT32 x, INT k)\n-{\n- return (x << k) | (x >> (32 - k));\n-}\n-\n-static __inline VOID\n-JhashMix(UINT32 *a, UINT32 *b, UINT32 *c)\n-{\n- *a -= *c; *a ^= JhashRot(*c, 4); *c += *b;\n- *b -= *a; *b ^= JhashRot(*a, 6); *a += *c;\n- *c -= *b; *c ^= JhashRot(*b, 8); *b += *a;\n- *a -= *c; *a ^= JhashRot(*c, 16); *c += *b;\n- *b -= *a; *b ^= JhashRot(*a, 19); *a += *c;\n- *c -= *b; *c ^= JhashRot(*b, 4); *b += *a;\n-}\n-\n-static __inline VOID\n-JhashFinal(UINT32 *a, UINT32 *b, UINT32 *c)\n-{\n- *c ^= *b; *c -= JhashRot(*b, 14);\n- *a ^= *c; *a -= JhashRot(*c, 11);\n- *b ^= *a; *b -= JhashRot(*a, 25);\n- *c ^= *b; *c -= JhashRot(*b, 16);\n- *a ^= *c; *a -= JhashRot(*c, 4);\n- *b ^= *a; *b -= JhashRot(*a, 14);\n- *c ^= *b; *c -= JhashRot(*b, 24);\n-}\n-\n-/* Returns the Jenkins hash of the 'n' 32-bit words at 'p', starting from\n- * 'basis'. 'p' must be properly aligned.\n- *\n- * Use hash_words() instead, unless you're computing a hash function whose\n- * value is exposed \"on the wire\" so we don't want to change it. */\n-UINT32\n-OvsJhashWords(const UINT32 *p, SIZE_T n, UINT32 basis)\n-{\n- UINT32 a, b, c;\n-\n- a = b = c = 0xdeadbeef + (((UINT32) n) << 2) + basis;\n-\n- while (n > 3) {\n- a += p[0];\n- b += p[1];\n- c += p[2];\n- JhashMix(&a, &b, &c);\n- n -= 3;\n- p += 3;\n- }\n-\n- switch (n) {\n- case 3:\n- c += p[2];\n- /* fall through */\n- case 2:\n- b += p[1];\n- /* fall through */\n- case 1:\n- a += p[0];\n- JhashFinal(&a, &b, &c);\n- /* fall through */\n- case 0:\n- break;\n- }\n- return c;\n-}\n-\n-/* Returns the Jenkins hash of the 'n' bytes at 'p', starting from 'basis'.\n- *\n- * Use hash_bytes() instead, unless you're computing a hash function whose\n- * value is exposed \"on the wire\" so we don't want to change it. */\n-UINT32\n-OvsJhashBytes(const VOID *p_, SIZE_T n, UINT32 basis)\n-{\n- const UINT32 *p = p_;\n- UINT32 a, b, c;\n-\n- a = b = c = 0xdeadbeef + (UINT32)n + basis;\n-\n- while (n >= 12) {\n- a += GetUnalignedU32(p);\n- b += GetUnalignedU32(p + 1);\n- c += GetUnalignedU32(p + 2);\n- JhashMix(&a, &b, &c);\n- n -= 12;\n- p += 3;\n- }\n-\n- if (n) {\n- UINT32 tmp[3];\n-\n- tmp[0] = tmp[1] = tmp[2] = 0;\n- memcpy(tmp, p, n);\n- a += tmp[0];\n- b += tmp[1];\n-#pragma warning(suppress: 6385)\n- /* Suppress buffer overflow, it is either zero or some random value */\n- c += tmp[2];\n- JhashFinal(&a, &b, &c);\n- }\n-\n- return c;\n-}\ndiff --git a/datapath-windows/ovsext/Jhash.h b/datapath-windows/ovsext/Jhash.h\ndeleted file mode 100644\nindex eb3d4cd1b..000000000\n--- a/datapath-windows/ovsext/Jhash.h\n+++ /dev/null\n@@ -1,30 +0,0 @@\n-/*\n- * Copyright (c) 2008, 2009, 2010, 2012, 2014 Nicira, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#ifndef __JHASH_H_\n-#define __JHASH_H_ 1\n-\n-/* This is the public domain lookup3 hash by Bob Jenkins from\n- * http://burtleburtle.net/bob/c/lookup3.c, modified for style.\n- *\n- * Use the functions in hash.h instead if you can. These are here just for\n- * places where we've exposed a hash function \"on the wire\" and don't want it\n- * to change. */\n-\n-uint32_t OvsJhashWords(const uint32_t *, size_t n_word, uint32_t basis);\n-uint32_t OvsJhashBytes(const void *, size_t n_bytes, uint32_t basis);\n-\n-#endif /* __JHASH_H_ */\ndiff --git a/datapath-windows/ovsext/Meter.c b/datapath-windows/ovsext/Meter.c\ndeleted file mode 100644\nindex d99631ba0..000000000\n--- a/datapath-windows/ovsext/Meter.c\n+++ /dev/null\n@@ -1,540 +0,0 @@\n-/*\n- * Copyright (c) 2022 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#include \"Meter.h\"\n-#include \"precomp.h\"\n-#include \"Switch.h\"\n-#include \"User.h\"\n-#include \"Datapath.h\"\n-#include \"Event.h\"\n-#include \"NetProto.h\"\n-#include \"Flow.h\"\n-#include \"PacketParser.h\"\n-#include \"Util.h\"\n-\n-static PNDIS_RW_LOCK_EX meterGlobalTableLock;\n-PLIST_ENTRY meterGlobalTable;\n-\n-const NL_POLICY nlMeterPolicy[OVS_METER_ATTR_MAX + 1] = {\n- [OVS_METER_ATTR_ID] = { .type = NL_A_U32, },\n- [OVS_METER_ATTR_KBPS] = { .type = NL_A_FLAG, .optional = TRUE },\n- [OVS_METER_ATTR_STATS] = { .minLen = sizeof(struct ovs_flow_stats),\n- .maxLen = sizeof(struct ovs_flow_stats),\n- .optional = TRUE },\n- [OVS_METER_ATTR_BANDS] = { .type = NL_A_NESTED, .optional = TRUE },\n- [OVS_METER_ATTR_USED] = { .type = NL_A_U64, .optional = TRUE },\n- [OVS_METER_ATTR_CLEAR] = { .type = NL_A_FLAG, .optional = TRUE },\n- [OVS_METER_ATTR_MAX_METERS] = { .type = NL_A_U32, .optional = TRUE },\n- [OVS_METER_ATTR_MAX_BANDS] = { .type = NL_A_U32, .optional = TRUE },\n-};\n-\n-const NL_POLICY bandPolicy[OVS_BAND_ATTR_MAX + 1] = {\n- [OVS_BAND_ATTR_TYPE] = { .type = NL_A_U32, .optional = FALSE },\n- [OVS_BAND_ATTR_RATE] = { .type = NL_A_U32, .optional = TRUE },\n- [OVS_BAND_ATTR_BURST] = { .type = NL_A_U32, .optional = TRUE },\n- [OVS_BAND_ATTR_STATS] = { .minLen = sizeof(struct ovs_flow_stats),\n- .maxLen = sizeof(struct ovs_flow_stats),\n- .optional = TRUE },\n-};\n-\n-NTSTATUS\n-OvsInitMeter(POVS_SWITCH_CONTEXT context)\n-{\n- UINT32 maxEntry = METER_HASH_BUCKET_MAX;\n-\n- meterGlobalTableLock = NdisAllocateRWLock(context->NdisFilterHandle);\n- if (meterGlobalTableLock == NULL) {\n- return STATUS_INSUFFICIENT_RESOURCES;\n- }\n-\n- meterGlobalTable = OvsAllocateMemoryWithTag(sizeof(LIST_ENTRY) * maxEntry,\n- OVS_METER_TAG);\n- if (!meterGlobalTable) {\n- NdisFreeRWLock(meterGlobalTableLock);\n- return NDIS_STATUS_RESOURCES;\n- }\n-\n- for (UINT32 index = 0; index < maxEntry; index++) {\n- InitializeListHead(&meterGlobalTable[index]);\n- }\n-\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-NDIS_STATUS\n-FillBandIntoMeter(PNL_ATTR meterAttrs[], DpMeter *meter, PNL_MSG_HDR nlMsgHdr)\n-{\n- PNL_ATTR a = NULL;\n- INT rem = 0;\n- UINT32 bandMaxDelta = 0;\n- UINT32 attrOffset = 0;\n- DpMeterBand *band = NULL;\n- PNL_ATTR bandAttrs[OVS_BAND_ATTR_MAX + 1];\n- UINT16 nBands = 0;\n-\n- band = meter->bands;\n- NL_ATTR_FOR_EACH(a, rem, NlAttrData(meterAttrs[OVS_METER_ATTR_BANDS]),\n- NlAttrGetSize(meterAttrs[OVS_METER_ATTR_BANDS])) {\n- RtlZeroMemory(bandAttrs, sizeof(bandAttrs));\n- attrOffset = (UINT32)((PCHAR)NlAttrData(a) - (PCHAR)nlMsgHdr);\n- if (!NlAttrParse(nlMsgHdr,\n- attrOffset,\n- NlAttrGetSize(a),\n- bandPolicy, ARRAY_SIZE(bandPolicy),\n- bandAttrs, ARRAY_SIZE(bandAttrs))) {\n- return STATUS_INVALID_PARAMETER;\n- }\n-\n- if (bandAttrs[OVS_BAND_ATTR_TYPE]) {\n- band->type = NlAttrGetU32(bandAttrs[OVS_BAND_ATTR_TYPE]);\n- }\n-\n- if (bandAttrs[OVS_BAND_ATTR_RATE]) {\n- band->rate = NlAttrGetU32(bandAttrs[OVS_BAND_ATTR_RATE]);\n- }\n-\n- if (bandAttrs[OVS_BAND_ATTR_BURST]) {\n- band->burst_size = NlAttrGetU32(bandAttrs[OVS_BAND_ATTR_BURST]);\n- }\n-\n- band->bucket = (band->burst_size + band->rate) * 1000;\n- bandMaxDelta = (UINT32)((band->bucket / band->rate) / 10);\n- if (bandMaxDelta > meter->maxDelta) {\n- meter->maxDelta = bandMaxDelta;\n- }\n-\n- nBands++;\n- band++;\n- }\n-\n- meter->nBands = nBands;\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-NDIS_STATUS\n-OvsNewMeterCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen)\n-{\n- DpMeter *meter = NULL;\n- POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;\n- PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);\n- PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);\n- POVS_HDR ovsHdr = &(msgIn->ovsHdr);\n- LOCK_STATE_EX lockState;\n- PNL_ATTR meterAttrs[ARRAY_SIZE(nlMeterPolicy)];\n- ASSERT(usrParamsCtx->inputBuffer != NULL);\n- PNL_MSG_HDR nlMsgOutHdr = NULL;\n- NL_BUFFER nlBuf;\n- NL_ERROR nlError = NL_ERROR_SUCCESS;\n-\n- if (!NlAttrParse((PNL_MSG_HDR)msgIn,\n- NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN,\n- NlMsgAttrsLen((PNL_MSG_HDR)msgIn),\n- nlMeterPolicy, ARRAY_SIZE(nlMeterPolicy),\n- meterAttrs, ARRAY_SIZE(meterAttrs))) {\n- nlError = NL_ERROR_NOMSG;\n- goto Done;\n- }\n-\n- meter = OvsAllocateMemoryWithTag(sizeof(*meter), OVS_METER_TAG);\n- if (!meter) {\n- nlError = NL_ERROR_NOMEM;\n- goto Done;\n- }\n-\n- RtlZeroMemory(meter, sizeof(*meter));\n- meter->id = NlAttrGetU32(meterAttrs[OVS_METER_ATTR_ID]);\n- meter->kbps = meterAttrs[OVS_METER_ATTR_KBPS] ? 1 : 0;\n- meter->keepStatus = meterAttrs[OVS_METER_ATTR_CLEAR] ? 1 : 0;\n- if (meter->keepStatus && meterAttrs[OVS_METER_ATTR_STATS]) {\n- meter->stats = *(struct ovs_flow_stats *)NlAttrData(\n- meterAttrs[OVS_METER_ATTR_STATS]);\n- }\n-\n- if (FillBandIntoMeter(meterAttrs, meter, nlMsgHdr) != NDIS_STATUS_SUCCESS) {\n- nlError = NL_ERROR_NOMSG;\n- OvsFreeMemoryWithTag(meter, OVS_METER_TAG);\n- goto Done;\n- }\n-\n- NdisAcquireRWLockWrite(meterGlobalTableLock, &lockState, 0);\n- InsertHeadList(&meterGlobalTable[meter->id & (METER_HASH_BUCKET_MAX - 1)],\n- &(meter->link));\n- NdisReleaseRWLock(meterGlobalTableLock, &lockState);\n-\n- NlBufInit(&nlBuf, usrParamsCtx->outputBuffer, usrParamsCtx->outputLength);\n- nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, 0, 0));\n- if (!NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,\n- nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,\n- genlMsgHdr->cmd, OVS_METER_CMD_GET,\n- ovsHdr->dp_ifindex)) {\n- nlError = NL_ERROR_NOMSG;\n- goto Done;\n- }\n-\n- if (!buildOvsMeterReplyMsg(&nlBuf, meter)) {\n- nlError = NL_ERROR_NOMEM;\n- goto Done;\n- }\n-\n- NlMsgSetSize(nlMsgOutHdr, NlBufSize(&nlBuf));\n- NlMsgAlignSize(nlMsgOutHdr);\n- *replyLen += NlMsgSize(nlMsgOutHdr);\n-\n-Done:\n- if (nlError != NL_ERROR_SUCCESS) {\n- POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)\n- usrParamsCtx->outputBuffer;\n-\n- ASSERT(msgError);\n- NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);\n- ASSERT(*replyLen != 0);\n- }\n-\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-NDIS_STATUS OvsMeterFeatureProbe(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen)\n-{\n- POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;\n- PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);\n- POVS_HDR ovsHdr = &(msgIn->ovsHdr);\n- PNL_MSG_HDR nlMsgOutHdr = NULL;\n- BOOLEAN ok = FALSE;\n- PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);\n- NL_BUFFER nlBuf;\n- NL_ERROR nlError = NL_ERROR_SUCCESS;\n- UINT32 bandsOffset = 0;\n- UINT32 bandAttrOffset = 0;\n-\n- NlBufInit(&nlBuf, usrParamsCtx->outputBuffer, usrParamsCtx->outputLength);\n- nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, 0, 0));\n- ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,\n- nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,\n- genlMsgHdr->cmd, OVS_METER_CMD_FEATURES,\n- ovsHdr->dp_ifindex);\n- if (!ok) {\n- nlError = NL_ERROR_NOMSG;\n- goto Done;\n- }\n-\n- if (!NlMsgPutTailU32(&nlBuf, OVS_METER_ATTR_MAX_METERS, UINT32_MAX)) {\n- nlError = NL_ERROR_NOMSG;\n- goto Done;\n- }\n-\n- if (!NlMsgPutTailU32(&nlBuf, OVS_METER_ATTR_MAX_BANDS, OVS_MAX_BANDS)) {\n- nlError = NL_ERROR_NOMSG;\n- goto Done;\n- }\n-\n- bandsOffset = NlMsgStartNested(&nlBuf, OVS_METER_ATTR_BANDS);\n- bandAttrOffset = NlMsgStartNested(&nlBuf, OVS_METER_ATTR_UNSPEC);\n- if (!NlMsgPutTailU32(&nlBuf, OVS_BAND_ATTR_TYPE,\n- OVS_METER_BAND_TYPE_DROP)) {\n- nlError = NL_ERROR_NOMSG;\n- goto Done;\n-\n- }\n- NlMsgEndNested(&nlBuf, bandAttrOffset);\n- NlMsgEndNested(&nlBuf, bandsOffset);\n-\n- NlMsgSetSize(nlMsgOutHdr, NlBufSize(&nlBuf));\n- NlMsgAlignSize(nlMsgOutHdr);\n- *replyLen += NlMsgSize(nlMsgOutHdr);\n-\n-Done:\n- if (nlError != NL_ERROR_SUCCESS) {\n- POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)\n- usrParamsCtx->outputBuffer;\n-\n- ASSERT(msgError);\n- NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);\n- ASSERT(*replyLen != 0);\n- }\n-\n- return STATUS_SUCCESS;\n-}\n-\n-BOOLEAN\n-buildOvsMeterReplyMsg(NL_BUFFER *nlBuf, DpMeter *dpMeter)\n-{\n- BOOLEAN ok = FALSE;\n- UINT32 bandAttrOffset;\n- UINT32 bandsOffset;\n-\n- /* Add meter element. */\n- ok = NlMsgPutTailU32(nlBuf, OVS_METER_ATTR_ID, dpMeter->id);\n- if (!ok) {\n- OVS_LOG_ERROR(\"Could not add meter id %d.\", dpMeter->id);\n- return ok;\n- }\n-\n- ok = NlMsgPutTailUnspec(nlBuf, OVS_METER_ATTR_STATS,\n- (PCHAR)&(dpMeter->stats),\n- sizeof(dpMeter->stats));\n- if (!ok) {\n- OVS_LOG_ERROR(\"Could not add ovs meter stats.\");\n- return ok;\n- }\n-\n- bandsOffset = NlMsgStartNested(nlBuf, OVS_METER_ATTR_BANDS);\n- for (int index = 0; index < dpMeter->nBands; index++) {\n- bandAttrOffset = NlMsgStartNested(nlBuf, OVS_BAND_ATTR_UNSPEC);\n- ok = NlMsgPutTailUnspec(nlBuf, OVS_BAND_ATTR_STATS,\n- (PCHAR)&(dpMeter->bands[index].stats),\n- sizeof(dpMeter->bands[index].stats));\n- NlMsgEndNested(nlBuf, bandAttrOffset);\n- if (!ok) {\n- break;\n- }\n- }\n-\n- NlMsgEndNested(nlBuf, bandsOffset);\n- return ok;\n-}\n-\n-NDIS_STATUS\n-OvsMeterGet(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen)\n-{\n- POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;\n- PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);\n- POVS_HDR ovsHdr = &(msgIn->ovsHdr);\n- PNL_MSG_HDR nlMsgOutHdr = NULL;\n- PNL_ATTR meterAttrs[ARRAY_SIZE(nlMeterPolicy)];\n- UINT32 meterId = 0;\n- DpMeter *dpMeter = NULL;\n- BOOLEAN ok = FALSE;\n- PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);\n- NL_BUFFER nlBuf;\n- NL_ERROR nlError = NL_ERROR_SUCCESS;\n- LOCK_STATE_EX lockState;\n-\n- if (!NlAttrParse((PNL_MSG_HDR)msgIn,\n- NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN,\n- NlMsgAttrsLen((PNL_MSG_HDR)msgIn),\n- nlMeterPolicy, ARRAY_SIZE(nlMeterPolicy),\n- meterAttrs, ARRAY_SIZE(meterAttrs))) {\n- nlError = NL_ERROR_NOMSG;\n- goto Done;\n- }\n-\n- NlBufInit(&nlBuf, usrParamsCtx->outputBuffer, usrParamsCtx->outputLength);\n- meterId = NlAttrGetU32(meterAttrs[OVS_METER_ATTR_ID]);\n-\n- /* Reply message header */\n- nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, 0, 0));\n- ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,\n- nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,\n- genlMsgHdr->cmd, OVS_METER_CMD_GET,\n- ovsHdr->dp_ifindex);\n- if (!ok) {\n- nlError = NL_ERROR_NOMSG;\n- goto Done;\n- }\n-\n- NdisAcquireRWLockRead(meterGlobalTableLock, &lockState, 0);\n- dpMeter = OvsMeterLookup(meterId);\n- if (!dpMeter) {\n- OVS_LOG_WARN(\"Has not find %d associated meter\", meterId);\n- nlError = NL_ERROR_EXIST;\n- NdisReleaseRWLock(meterGlobalTableLock, &lockState);\n- goto Done;\n- }\n-\n- if (!buildOvsMeterReplyMsg(&nlBuf, dpMeter)) {\n- nlError = NL_ERROR_NOMEM;\n- OVS_LOG_ERROR(\"Could not build ovs meter reply msg.\");\n- NdisReleaseRWLock(meterGlobalTableLock, &lockState);\n- goto Done;\n- }\n-\n- NdisReleaseRWLock(meterGlobalTableLock, &lockState);\n- NlMsgSetSize(nlMsgOutHdr, NlBufSize(&nlBuf));\n- NlMsgAlignSize(nlMsgOutHdr);\n- *replyLen += NlMsgSize(nlMsgOutHdr);\n-\n-Done:\n- if (nlError != NL_ERROR_SUCCESS) {\n- POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)\n- usrParamsCtx->outputBuffer;\n-\n- ASSERT(msgError);\n- NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);\n- ASSERT(*replyLen != 0);\n- }\n-\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-NDIS_STATUS\n-OvsMeterDestroy(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen)\n-{\n- POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;\n- PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);\n- POVS_HDR ovsHdr = &(msgIn->ovsHdr);\n- PNL_MSG_HDR nlMsgOutHdr = NULL;\n- PNL_ATTR meterAttrs[ARRAY_SIZE(nlMeterPolicy)];\n- PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);\n- LOCK_STATE_EX lockState;\n- UINT32 meterId = 0;\n- BOOLEAN ok;\n- NL_BUFFER nlBuf;\n- NL_ERROR nlError = NL_ERROR_SUCCESS;\n-\n- if (!NlAttrParse((PNL_MSG_HDR)msgIn,\n- NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN,\n- NlMsgAttrsLen((PNL_MSG_HDR)msgIn),\n- nlMeterPolicy, ARRAY_SIZE(nlMeterPolicy),\n- meterAttrs, ARRAY_SIZE(meterAttrs))) {\n- return STATUS_INVALID_PARAMETER;\n- }\n-\n- NlBufInit(&nlBuf, usrParamsCtx->outputBuffer, usrParamsCtx->outputLength);\n-\n- meterId = NlAttrGetU32(meterAttrs[OVS_METER_ATTR_ID]);\n- nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, 0, 0));\n- ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,\n- nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,\n- genlMsgHdr->cmd, OVS_METER_CMD_DEL,\n- ovsHdr->dp_ifindex);\n- if (!ok) {\n- nlError = NL_ERROR_NOMEM;\n- goto Done;\n- }\n-\n- NdisAcquireRWLockWrite(meterGlobalTableLock, &lockState, 0);\n- PLIST_ENTRY head = &meterGlobalTable[meterId & (METER_HASH_BUCKET_MAX - 1)];\n- PLIST_ENTRY link, next;\n- DpMeter *entry = NULL;\n-\n- LIST_FORALL_SAFE(head, link, next) {\n- entry = CONTAINING_RECORD(link, DpMeter, link);\n- if (entry->id == meterId) {\n- if (!buildOvsMeterReplyMsg(&nlBuf, entry)) {\n- nlError = NL_ERROR_NOMEM;\n- NdisReleaseRWLock(meterGlobalTableLock, &lockState);\n- goto Done;\n- }\n- RemoveEntryList(&entry->link);\n- OvsFreeMemoryWithTag(entry, OVS_METER_TAG);\n- break;\n- }\n- }\n-\n- NdisReleaseRWLock(meterGlobalTableLock, &lockState);\n- NlMsgSetSize(nlMsgOutHdr, NlBufSize(&nlBuf));\n- NlMsgAlignSize(nlMsgOutHdr);\n- *replyLen += NlMsgSize(nlMsgOutHdr);\n-\n-Done:\n- if (nlError != NL_ERROR_SUCCESS) {\n- POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)\n- usrParamsCtx->outputBuffer;\n-\n- ASSERT(msgError);\n- NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);\n- ASSERT(*replyLen != 0);\n- }\n-\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-\n-\n-DpMeter*\n-OvsMeterLookup(UINT32 meterId)\n-{\n- PLIST_ENTRY head = &meterGlobalTable[meterId & (METER_HASH_BUCKET_MAX - 1)];\n- PLIST_ENTRY link, next;\n- DpMeter *entry = NULL;\n-\n- LIST_FORALL_SAFE(head, link, next) {\n- entry = CONTAINING_RECORD(link, DpMeter, link);\n- if (entry->id == meterId) {\n- return entry;\n- }\n- }\n-\n- return NULL;\n-}\n-\n-BOOLEAN\n-OvsMeterExecute(OvsForwardingContext *fwdCtx, UINT32 meterId)\n-{\n- DpMeter *dpMeter;\n- DpMeterBand *band;\n- UINT32 longDeltaMs;\n- UINT32 deltaMs;\n- UINT64 currentTime;\n- LOCK_STATE_EX lockState;\n- UINT32 cost;\n- UINT32 bandExceededRate = 0;\n- INT32 bandExceedIndex = -1;\n- UINT64 maxBucketSize = 0;\n-\n- NdisAcquireRWLockRead(meterGlobalTableLock, &lockState, 0);\n- dpMeter = OvsMeterLookup(meterId);\n- if (!dpMeter) {\n- OVS_LOG_ERROR(\"Not found meter id %d associated meter.\", meterId);\n- NdisReleaseRWLock(meterGlobalTableLock, &lockState);\n- return FALSE;\n- }\n-\n- NdisGetCurrentSystemTime((LARGE_INTEGER *)¤tTime);\n- /* currentTime represent count of 100-nanosecond intervals, to convert it to\n- * ms, we need to divide 10000. */\n- longDeltaMs = (UINT32)((currentTime - dpMeter->used) / 10000);\n- deltaMs = longDeltaMs > dpMeter->maxDelta ? dpMeter->maxDelta :\n- longDeltaMs;\n- dpMeter->used = currentTime;\n- dpMeter->stats.n_packets += 1;\n- dpMeter->stats.n_bytes += OvsPacketLenNBL(fwdCtx->curNbl);\n- cost = dpMeter->kbps ? OvsPacketLenNBL(fwdCtx->curNbl) * 8 : 1000;\n- for (int index = 0; index < dpMeter->nBands; index++) {\n- band = &(dpMeter->bands[index]);\n- maxBucketSize = (band->burst_size + band->rate) * 1000LL;\n- band->bucket += deltaMs * band->rate;\n- if (band->bucket > maxBucketSize) {\n- band->bucket = maxBucketSize;\n- }\n-\n- if (band->bucket >= cost) {\n- band->bucket -= cost;\n- band->stats.n_packets += 1;\n- band->stats.n_bytes += OvsPacketLenNBL(fwdCtx->curNbl);\n- } else if (band->rate > bandExceededRate) {\n- bandExceededRate = band->rate;\n- bandExceedIndex = index;\n- }\n- }\n-\n- if (bandExceedIndex >= 0) {\n- band = &(dpMeter->bands[bandExceedIndex]);\n- band->stats.n_packets += 1;\n- band->stats.n_bytes += OvsPacketLenNBL(fwdCtx->curNbl);\n- if (band->type == OVS_METER_BAND_TYPE_DROP) {\n- NdisReleaseRWLock(meterGlobalTableLock, &lockState);\n- return TRUE;\n- }\n- }\n-\n- NdisReleaseRWLock(meterGlobalTableLock, &lockState);\n- return FALSE;\n-}\ndiff --git a/datapath-windows/ovsext/Meter.h b/datapath-windows/ovsext/Meter.h\ndeleted file mode 100644\nindex bc94489a5..000000000\n--- a/datapath-windows/ovsext/Meter.h\n+++ /dev/null\n@@ -1,68 +0,0 @@\n-/*\n- * Copyright (c) 2022 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#ifndef OVS_METER_H\n-#define OVS_METER_H\n-\n-#include \"precomp.h\"\n-#include \"Switch.h\"\n-#include \"User.h\"\n-#include \"Datapath.h\"\n-#include \"Event.h\"\n-#include \"NetProto.h\"\n-#include \"Netlink/Netlink.h\"\n-#include \"Flow.h\"\n-\n-#define OVS_MAX_BANDS 1\n-#define OVS_MAX_METERS 32\n-#define METER_HASH_BUCKET_MAX 1024\n-\n-typedef struct _DpMeterBand {\n- UINT32 type;\n- UINT32 rate;\n- UINT32 burst_size;\n- UINT64 bucket;\n- struct ovs_flow_stats stats;\n-} DpMeterBand;\n-\n-typedef struct _DpMeter {\n- LIST_ENTRY link;\n- UINT32 id;\n- UINT16 kbps:1;\n- UINT16 keepStatus:1;\n- UINT16 nBands;\n- UINT32 maxDelta;\n- UINT64 used;\n- struct ovs_flow_stats stats;\n- DpMeterBand bands[OVS_MAX_BANDS];\n-} DpMeter;\n-\n-NTSTATUS OvsInitMeter(POVS_SWITCH_CONTEXT context);\n-NDIS_STATUS OvsNewMeterCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen);\n-NDIS_STATUS OvsMeterFeatureProbe(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n-UINT32 *replyLen);\n-\n-NDIS_STATUS OvsMeterDestroy(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen);\n-DpMeter* OvsMeterLookup(UINT32 meterId);\n-BOOLEAN\n-OvsMeterExecute(OvsForwardingContext *fwdCtx, UINT32 meterId);\n-BOOLEAN\n-buildOvsMeterReplyMsg(NL_BUFFER *nlBuf, DpMeter *dpMeter);\n-\n-\n-#endif //OVS_METER_H\ndiff --git a/datapath-windows/ovsext/Mpls.h b/datapath-windows/ovsext/Mpls.h\ndeleted file mode 100644\nindex 084613f1a..000000000\n--- a/datapath-windows/ovsext/Mpls.h\n+++ /dev/null\n@@ -1,80 +0,0 @@\n-/*\n- * Copyright (c) 2015 Cloudbase Solutions Srl\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#ifndef __MPLS_H_\n-#define __MPLS_H_ 1\n-\n-#include \"precomp.h\"\n-#include \"Ethernet.h\"\n-\n-/*\n- * MPLS definitions\n- */\n-#define FLOW_MAX_MPLS_LABELS 3\n-\n-#define MPLS_HLEN 4\n-#define MPLS_BOS_MASK 0x00000100\n-\n-/* Reference: RFC 5462, RFC 3032\n- *\n- * 0 1 2 3\n- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\n- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n- * | Label | TC |S| TTL |\n- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n- *\n- *\tLabel: Label Value, 20 bits\n- *\tTC: Traffic Class field, 3 bits\n- *\tS: Bottom of Stack, 1 bit\n- *\tTTL: Time to Live, 8 bits\n- */\n-\n-typedef struct MPLSHdr {\n- ovs_be32 lse;\n-} MPLSHdr;\n-\n-__inline BOOLEAN\n-OvsEthertypeIsMpls(ovs_be16 ethertype)\n-{\n- return ethertype == htons(ETH_TYPE_MPLS) ||\n- ethertype == htons(ETH_TYPE_MPLS_MCAST);\n-}\n-\n-/* Returns the number of MPLS LSEs present in 'a'\n- *\n- * Counts 'flow''s MPLS label stack entries (LESs) stopping at the first\n- * entry that has the bottom of stack (BOS) bit set. If no such entry exists,\n- * then zero is returned, meaning that the maximum number of supported\n- * MPLS LSEs exceeded.\n- */\n-__inline UINT32\n-OvsCountMplsLabels(PNL_ATTR a)\n-{\n- const MPLSHdr *mpls = NlAttrGet(a);\n- UINT32 count = 0;\n- BOOLEAN bos = FALSE;\n-\n- for (count = 0; count < FLOW_MAX_MPLS_LABELS; count++) {\n- if ((mpls + count)->lse & htonl(MPLS_BOS_MASK)) {\n- bos = TRUE;\n- break;\n- }\n- }\n-\n- return bos ? ++count : 0;\n-}\n-\n-#endif /* __MPLS_H_ */\ndiff --git a/datapath-windows/ovsext/NetProto.h b/datapath-windows/ovsext/NetProto.h\ndeleted file mode 100644\nindex 39726c203..000000000\n--- a/datapath-windows/ovsext/NetProto.h\n+++ /dev/null\n@@ -1,439 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#ifndef __NET_PROTO_H_\n-#define __NET_PROTO_H_ 1\n-\n-#include \"precomp.h\"\n-#include \"Ethernet.h\"\n-#include \"Mpls.h\"\n-\n-#define ETH_HEADER_LENGTH 14\n-#define ETH_ADDR_LENGTH 6\n-/*\n- * There is a more inclusive definition of ethernet header (Eth_Header) in\n- * OvsEth.h that is used for packet parsing. For simple cases, , use the following definition.\n- */\n-typedef struct EthHdr {\n- UINT8 Destination[ETH_ADDR_LENGTH];\n- UINT8 Source[ETH_ADDR_LENGTH];\n- UINT16 Type;\n-} EthHdr, *PEthHdr;\n-\n-#define IPV4 4\n-#define IPV6 6\n-\n-#define IP_HDR_MIN_LENGTH 20\n-#define TCP_HDR_MIN_LENGTH 20\n-#define TCP_CSUM_OFFSET 16\n-#define UDP_HDR_MIN_LENGTH 8\n-#define UDP_CSUM_OFFSET 6\n-#define ICMP_HDR_MIN_LENGTH 8\n-#define ICMP_CSUM_OFFSET 2\n-#define INET_CSUM_LENGTH (sizeof(UINT16))\n-\n-#define PACKET_MAX_LENGTH 64*1024 // 64K\n-\n-#define IP4_UNITS_TO_BYTES(x) ((x) << 2)\n-#define IP4_BYTES_TO_UNITS(x) ((x) >> 2)\n-\n-// length unit for ip->ihl, tcp->doff\n-typedef UINT32 IP4UnitLength;\n-\n-#define IP4_LENGTH_UNIT (sizeof(IP4UnitLength))\n-#define IP4_HDR_MIN_LENGTH_IN_UNITS (IP_HDR_MIN_LENGTH / IP4_LENGTH_UNIT)\n-#define TCP_HDR_MIN_LENGTH_IN_UNITS (TCP_HDR_MIN_LENGTH / IP4_LENGTH_UNIT)\n-\n-#define IP4_IHL_NO_OPTIONS IP4_HDR_MIN_LENGTH_IN_UNITS\n-#define IP4_HDR_LEN(iph) IP4_UNITS_TO_BYTES((iph)->ihl)\n-\n-// length unit for ip->frag_off\n-typedef UINT64 IP4FragUnitLength;\n-\n-#define IP4_FRAG_UNIT_LENGTH (sizeof(IP4FragUnitLength))\n-\n-// length UINT for ipv6 header length.\n-typedef UINT64 IP6UnitLength;\n-\n-#define TCP_HDR_LEN(tcph) ((tcph)->doff * 4)\n-#define TCP_DATA_LENGTH(iph, tcph) (ntohs(iph->tot_len) - \\\n- IP4_HDR_LEN(iph) - TCP_HDR_LEN(tcph))\n-\n-#define TCP_DATA_OFFSET_NO_OPTIONS TCP_HDR_MIN_LENGTH_IN_UNITS\n-#define TCP_DATA_OFFSET_WITH_TIMESTAMP 8\n-\n-/*\n- * This is the maximum value for the length field in the IP header. The meaning\n- * varies with IP protocols:\n- * IPv4: the total ip length (including ip header and extention)\n- * IPv6: the IP payload length (including IP extensions)\n- */\n-#define IP_MAX_PACKET 0xFFFF\n-\n-#define IPPROTO_ICMP 1\n-#define IPPROTO_IGMP 2\n-#define IPPROTO_UDP 17\n-#define IPPROTO_GRE 47\n-#define IPPROTO_TCP 6\n-#define IPPROTO_SCTP 132\n-#define IPPROTO_RSVD 0xff\n-\n-#define IPPROTO_HOPOPTS 0 /* Hop-by-hop option header */\n-#define IPPROTO_IPV6 41 /* IPv6 in IPv6 */\n-#define IPPROTO_ROUTING 43 /* Routing header */\n-#define IPPROTO_FRAGMENT 44 /* Fragmentation/reassembly header */\n-#define IPPROTO_GRE 47 /* General Routing Encapsulation */\n-#define IPPROTO_ESP 50 /* Encap. Security Payload */\n-#define IPPROTO_AH 51 /* Authentication header */\n-#define IPPROTO_ICMPV6 58 /* ICMP for IPv6 */\n-#define IPPROTO_NONE 59 /* No next header */\n-#define IPPROTO_DSTOPTS 60 /* Destination options header */\n-#define IPPROTO_ETHERIP 97 /* etherIp tunneled protocol */\n-\n-/* IPv6 Neighbor discovery option header. */\n-#define ND_OPT_SOURCE_LINKADDR 1\n-#define ND_OPT_TARGET_LINKADDR 2\n-\n-/* Collides with MS definition (opposite order) */\n-#define IP6F_OFF_HOST_ORDER_MASK 0xfff8\n-\n-#define ARPOP_REQUEST 1 /* ARP request. */\n-#define ARPOP_REPLY 2 /* ARP reply. */\n-#define RARPOP_REQUEST 3 /* RARP request. */\n-#define RARPOP_REPLY 4 /* RARP reply. */\n-\n- /* all ARP NBO's assume short ar_op */\n-#define ARPOP_REQUEST_NBO 0x0100 /* NBO ARP request. */\n-#define ARPOP_REPLY_NBO 0x0200 /* NBO ARP reply. */\n-#define RARPOP_REQUEST_NBO 0x0300 /* NBO RARP request. */\n-#define RARPOP_REPLY_NBO 0x0300 /* NBO RARP reply. */\n-\n-/* ICMPv4 types. */\n-#define ICMP4_ECHO_REPLY 0 /* Echo Reply */\n-#define ICMP4_DEST_UNREACH 3 /* Destination Unreachable */\n-#define ICMP4_SOURCE_QUENCH 4 /* Source Quench */\n-#define ICMP4_REDIRECT 5 /* Redirect (change route) */\n-#define ICMP4_ECHO_REQUEST 8 /* Echo Request */\n-#define ICMP4_ROUTER_ADVERT 9 /* Router Advert */\n-#define ICMP4_ROUTER_SOLICIT 10 /* Router Solicit */\n-#define ICMP4_TIME_EXCEEDED 11 /* Time Exceeded */\n-#define ICMP4_PARAM_PROB 12 /* Parameter Problem */\n-#define ICMP4_TIMESTAMP_REQUEST 13 /* Timestamp Request */\n-#define ICMP4_TIMESTAMP_REPLY 14 /* Timestamp Reply */\n-#define ICMP4_INFO_REQUEST 15 /* Information Request */\n-#define ICMP4_INFO_REPLY 16 /* Information Reply */\n-#define ICMP4_MASK_REQUEST 17 /* Address Mask Request */\n-#define ICMP4_MASK_REPLY 18 /* Address Mask Reply */\n-\n-/* ICMPv6 types. */\n-#define ICMP6_DST_UNREACH 1\n-#define ICMP6_PACKET_TOO_BIG 2\n-#define ICMP6_TIME_EXCEEDED 3\n-#define ICMP6_PARAM_PROB 4\n-#define ICMP6_ECHO_REQUEST 128\n-#define ICMP6_ECHO_REPLY 129\n-#define ICMP6_MEMBERSHIP_QUERY 130\n-#define ICMP6_MEMBERSHIP_REPORT 131\n-#define ICMP6_MEMBERSHIP_REDUCTION 132\n-#define ND_ROUTER_SOLICIT 133\n-#define ND_ROUTER_ADVERT 134\n-#define ND_NEIGHBOR_SOLICIT 135 /* neighbor solicitation */\n-#define ND_NEIGHBOR_ADVERT 136 /* neighbor advertisment */\n-#define ND_REDIRECT 137\n-\n-\n-/* IGMP related constants */\n-#define IGMP_UNKNOWN 0x00 /* For IGMP packets where we don't know the type */\n- /* Eg: Fragmented packets without the header */\n-\n-/* Constants from RFC 3376 */\n-#define IGMP_QUERY 0x11 /* IGMP Host Membership Query. */\n-#define IGMP_V1REPORT 0x12 /* IGMPv1 Host Membership Report. */\n-#define IGMP_V2REPORT 0x16 /* IGMPv2 Host Membership Report. */\n-#define IGMP_V3REPORT 0x22 /* IGMPv3 Host Membership Report. */\n-#define IGMP_V2LEAVE 0x17 /* IGMPv2 Leave. */\n-\n-/* Constants from RFC 2710 and RFC 3810 */\n-#define MLD_QUERY 0x82 /* Multicast Listener Query. */\n-#define MLD_V1REPORT 0x83 /* Multicast Listener V1 Report. */\n-#define MLD_V2REPORT 0x8F /* Multicast Listener V2 Report. */\n-#define MLD_DONE 0x84 /* Multicast Listener Done. */\n-\n-/* IPv4 offset flags */\n-#define IP_CE 0x8000 /* Flag: \"Congestion\" */\n-#define IP_DF 0x4000 /* Flag: \"Don't Fragment\" */\n-#define IP_MF 0x2000 /* Flag: \"More Fragments\" */\n-#define IP_OFFSET 0x1FFF /* \"Fragment Offset\" part */\n-\n-#define IP_OFFSET_NBO 0xFF1F /* \"Fragment Offset\" part, NBO */\n-#define IP_DF_NBO 0x0040 /* NBO version of don't fragment */\n-#define IP_MF_NBO 0x0020 /* NBO version of more fragments */\n-\n-#define IPOPT_RTRALT 0x94\n-\n-/* IP Explicit Congestion Notification bits (TOS field) */\n-#define IP_ECN_NOT_ECT 0\n-#define IP_ECN_ECT_1 1\n-#define IP_ECN_ECT_0 2\n-#define IP_ECN_CE 3\n-#define IP_ECN_MASK 3\n-\n-/* TCP options */\n-#define TCP_OPT_NOP 1 /* Padding */\n-#define TCP_OPT_EOL 0 /* End of options */\n-#define TCP_OPT_MSS 2 /* Segment size negotiating */\n-#define TCP_OPT_WINDOW 3 /* Window scaling */\n-#define TCP_OPT_SACK_PERM 4 /* SACK Permitted */\n-#define TCP_OPT_SACK 5 /* SACK Block */\n-#define TCP_OPT_TIMESTAMP 8 /* Better RTT estimations/PAWS */\n-#define TCP_OPT_MD5SIG 19 /* MD5 Signature (RFC2385) */\n-\n-#define TCP_OPT_LEN_MSS 4\n-#define TCP_OPT_LEN_WINDOW 3\n-#define TCP_OPT_LEN_SACK_PERM 2\n-#define TCP_OPT_LEN_TIMESTAMP 10\n-#define TCP_OPT_LEN_MD5SIG 18\n-\n-#define SOCKET_IPPROTO_HOPOPTS IPPROTO_HOPOPTS\n-#define SOCKET_IPPROTO_ROUTING IPPROTO_ROUTING\n-#define SOCKET_IPPROTO_FRAGMENT IPPROTO_FRAGMENT\n-#define SOCKET_IPPROTO_AH IPPROTO_AH\n-#define SOCKET_IPPROTO_ICMPV6 IPPROTO_ICMPV6\n-#define SOCKET_IPPROTO_NONE IPPROTO_NONE\n-#define SOCKET_IPPROTO_DSTOPTS IPPROTO_DSTOPTS\n-#define SOCKET_IPPROTO_EON 80\n-#define SOCKET_IPPROTO_ETHERIP IPPROTO_ETHERIP\n-#define SOCKET_IPPROTO_ENCAP 98\n-#define SOCKET_IPPROTO_PIM 103\n-#define SOCKET_IPPROTO_IPCOMP 108\n-#define SOCKET_IPPROTO_CARP 112\n-#define SOCKET_IPPROTO_PFSYNC 240\n-#define SOCKET_IPPROTO_RAW IPPROTO_RSVD\n-\n-typedef union _OVS_PACKET_HDR_INFO {\n- struct {\n- UINT16 l3Offset;\n- UINT16 l4Offset;\n- union {\n- UINT16 l7Offset;\n- UINT16 l4PayLoad;\n- };\n- UINT16 isIPv4:1;\n- UINT16 isIPv6:1;\n- UINT16 isTcp:1;\n- UINT16 isUdp:1;\n- UINT16 isSctp:1;\n- UINT16 tcpCsumNeeded:1;\n- UINT16 udpCsumNeeded:1;\n- UINT16 udpCsumZero:1;\n- UINT16 isIcmp:1;\n- UINT16 pad:7;\n- } ;\n- UINT64 value;\n-} OVS_PACKET_HDR_INFO, *POVS_PACKET_HDR_INFO;\n-\n-typedef struct IPHdr {\n- UINT8 ihl:4,\n- version:4;\n- union {\n- struct {\n- UINT8 ecn:2,\n- dscp:6;\n- };\n- UINT8 tos;\n- };\n- UINT16 tot_len;\n- UINT16 id;\n- UINT16 frag_off;\n- UINT8 ttl;\n- UINT8 protocol;\n- UINT16 check;\n- UINT32 saddr;\n- UINT32 daddr;\n-} IPHdr;\n-\n-\n- /*\n- * IPv6 fixed header\n- *\n- * BEWARE, it is incorrect. The first 4 bits of flow_lbl\n- * are glued to priority now, forming \"class\".\n- */\n-\n-typedef struct IPv6Hdr {\n- UINT8 priority:4,\n- version:4;\n- UINT8 flow_lbl[3];\n-\n- UINT16 payload_len;\n- UINT8 nexthdr;\n- UINT8 hop_limit;\n-\n- struct in6_addr saddr;\n- struct in6_addr daddr;\n-} IPv6Hdr;\n-\n-// Generic IPv6 extension header\n-typedef struct IPv6ExtHdr {\n- UINT8 nextHeader; // type of the next header\n- UINT8 hdrExtLen; // length of header extensions (beyond 8 bytes)\n- UINT16 optPad1;\n- UINT32 optPad2;\n-} IPv6ExtHdr;\n-\n-typedef struct IPv6FragHdr {\n- UINT8 nextHeader;\n- UINT8 reserved;\n- UINT16 offlg;\n- UINT32 ident;\n-} IPv6FragHdr;\n-\n-typedef struct IPv6OptHdr {\n- UINT8 nextHdr;\n- UINT8 hdrLen;\n-} IPv6OptHdr;\n-\n-typedef struct IPv6NdOptHdr {\n- UINT8 type;\n- UINT8 len;\n-} IPv6NdOptHdr;\n-\n-typedef struct ICMPHdr {\n- UINT8 type;\n- UINT8 code;\n- UINT16 checksum;\n- union {\n- struct {\n- UINT16 id;\n- UINT16 seq;\n- } echo;\n- struct {\n- UINT16 empty;\n- UINT16 mtu;\n- } frag;\n- UINT32 gateway;\n- } fields;\n-} ICMPHdr;\n-\n-typedef struct ICMPEcho {\n- UINT16 id;\n- UINT16 seq;\n-} ICMPEcho;\n-\n-typedef struct UDPHdr {\n- UINT16 source;\n- UINT16 dest;\n- UINT16 len;\n- UINT16 check;\n-} UDPHdr;\n-\n-typedef struct TCPHdr {\n- UINT16 source;\n- UINT16 dest;\n- UINT32 seq;\n- UINT32 ack_seq;\n- union {\n- struct {\n- UINT16 res1:4,\n- doff:4,\n- fin:1,\n- syn:1,\n- rst:1,\n- psh:1,\n- ack:1,\n- urg:1,\n- ece:1,\n- cwr:1;\n- };\n- UINT16 flags;\n- };\n- UINT16 window;\n- UINT16 check;\n- UINT16 urg_ptr;\n-} TCPHdr;\n-\n-typedef struct SCTPHdr {\n- UINT16 source;\n- UINT16 dest;\n- UINT32 vtag;\n- UINT32 check;\n-} SCTPHdr;\n-\n-typedef struct PseudoHdr {\n- UINT32 sourceIPAddr;\n- UINT32 destIPAddr;\n- UINT8 zero;\n- UINT8 protocol;\n- UINT16 length;\n-} PseudoHdr;\n-\n-typedef struct PseudoHdrIPv6 {\n- UINT8 sourceIPAddr[16];\n- UINT8 destIPAddr[16];\n- UINT8 zero;\n- UINT8 protocol;\n- UINT16 length;\n-} PseudoHdrIPv6;\n-\n-\n-struct ArpHdr {\n- UINT16 ar_hrd; /* Format of hardware address. */\n- UINT16 ar_pro; /* Format of protocol address. */\n- UINT8 ar_hln; /* Length of hardware address. */\n- UINT8 ar_pln; /* Length of protocol address. */\n- UINT16 ar_op; /* ARP opcode (command). */\n-};\n-\n-typedef struct EtherArp {\n- struct ArpHdr ea_hdr; /* fixed-size header */\n- Eth_Address arp_sha; /* sender hardware address */\n- UINT8 arp_spa[4]; /* sender protocol address */\n- Eth_Address arp_tha; /* target hardware address */\n- UINT8 arp_tpa[4]; /* target protocol address */\n-} EtherArp;\n-\n-typedef struct IGMPHdr {\n- UINT8 type;\n- UINT8 maxResponseTime;\n- UINT16 csum;\n- UINT8 groupAddr[4];\n-} IGMPHdr;\n-\n-typedef struct IGMPV3Trailer {\n- UINT8 qrv:3,\n- s:1,\n- resv:4;\n- UINT8 qqic;\n- UINT16 numSources;\n-} IGMPV3Trailer;\n-\n-typedef struct IPOpt {\n- UINT8 type;\n- UINT8 length;\n- UINT16 value;\n-} IPOpt;\n-\n-/*\n- * IP protocol types\n- */\n-#define SOCKET_IPPROTO_IP 0\n-#define SOCKET_IPPROTO_ICMP 1\n-#define SOCKET_IPPROTO_TCP 6\n-#define SOCKET_IPPROTO_UDP 17\n-#define SOCKET_IPPROTO_GRE 47\n-#define SOCKET_IPPROTO_SCTP 132\n-\n-#endif /* __NET_PROTO_H_ */\ndiff --git a/datapath-windows/ovsext/Netlink/Netlink.c b/datapath-windows/ovsext/Netlink/Netlink.c\ndeleted file mode 100644\nindex f4a005048..000000000\n--- a/datapath-windows/ovsext/Netlink/Netlink.c\n+++ /dev/null\n@@ -1,1236 +0,0 @@\n-/*\n- * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#include \"precomp.h\"\n-#include \"NetlinkProto.h\"\n-#include \"Netlink.h\"\n-\n-#ifdef OVS_DBG_MOD\n-#undef OVS_DBG_MOD\n-#endif\n-#define OVS_DBG_MOD OVS_DBG_NETLINK\n-#include \"Debug.h\"\n-\n-/* ==========================================================================\n- * This file provides simple netlink get, put and validation APIs.\n- * Most of the code is on similar lines as userspace netlink implementation.\n- *\n- * TODO: Convert these methods to inline.\n- * ==========================================================================\n- */\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Prepare netlink message headers. This API adds\n- * NL_MSG_HDR + GENL_HDR + OVS_HDR to the tail of input NLBuf.\n- * Attributes should be added by caller.\n- * ---------------------------------------------------------------------------\n- */\n-BOOLEAN\n-NlFillOvsMsg(PNL_BUFFER nlBuf, UINT16 nlmsgType,\n- UINT16 nlmsgFlags, UINT32 nlmsgSeq,\n- UINT32 nlmsgPid, UINT8 genlCmd,\n- UINT8 genlVer, UINT32 dpNo)\n-{\n- BOOLEAN writeOk;\n- OVS_MESSAGE msgOut;\n- UINT32 offset = NlBufSize(nlBuf);\n-\n- /* To keep compiler happy for release build. */\n- UNREFERENCED_PARAMETER(offset);\n- ASSERT(NlBufAt(nlBuf, offset, 0) != 0);\n-\n- msgOut.nlMsg.nlmsgType = nlmsgType;\n- msgOut.nlMsg.nlmsgFlags = nlmsgFlags;\n- msgOut.nlMsg.nlmsgSeq = nlmsgSeq;\n- msgOut.nlMsg.nlmsgPid = nlmsgPid;\n- msgOut.nlMsg.nlmsgLen = sizeof(struct _OVS_MESSAGE);\n-\n- msgOut.genlMsg.cmd = genlCmd;\n- msgOut.genlMsg.version = genlVer;\n- msgOut.genlMsg.reserved = 0;\n-\n- msgOut.ovsHdr.dp_ifindex = dpNo;\n-\n- writeOk = NlMsgPutTail(nlBuf, (PCHAR)(&msgOut),\n- sizeof (struct _OVS_MESSAGE));\n-\n- return writeOk;\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Prepare netlink message headers. This API adds\n- * NL_MSG_HDR + GENL_HDR + OVS_HDR to the tail of input NLBuf.\n- * Attributes should be added by caller.\n- * ---------------------------------------------------------------------------\n- */\n-BOOLEAN\n-NlFillOvsMsgForNfGenMsg(PNL_BUFFER nlBuf, UINT16 nlmsgType,\n- UINT16 nlmsgFlags, UINT32 nlmsgSeq,\n- UINT32 nlmsgPid, UINT8 nfgenFamily,\n- UINT8 nfGenVersion, UINT32 dpNo)\n-{\n- BOOLEAN writeOk;\n- OVS_MESSAGE msgOut;\n- UINT32 offset = NlBufSize(nlBuf);\n-\n- /* To keep compiler happy for release build. */\n- UNREFERENCED_PARAMETER(offset);\n- ASSERT(NlBufAt(nlBuf, offset, 0) != 0);\n-\n- msgOut.nlMsg.nlmsgType = nlmsgType;\n- msgOut.nlMsg.nlmsgFlags = nlmsgFlags;\n- msgOut.nlMsg.nlmsgSeq = nlmsgSeq;\n- msgOut.nlMsg.nlmsgPid = nlmsgPid;\n- msgOut.nlMsg.nlmsgLen = sizeof(struct _OVS_MESSAGE);\n-\n- msgOut.nfGenMsg.nfgenFamily = nfgenFamily;\n- msgOut.nfGenMsg.version = nfGenVersion;\n- msgOut.nfGenMsg.resId = 0;\n-\n- msgOut.ovsHdr.dp_ifindex = dpNo;\n-\n- writeOk = NlMsgPutTail(nlBuf, (PCHAR)(&msgOut),\n- sizeof (struct _OVS_MESSAGE));\n-\n- return writeOk;\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Prepare NL_MSG_HDR only. This API appends a NL_MSG_HDR to the tail of\n- * input NlBuf.\n- * ---------------------------------------------------------------------------\n- */\n-BOOLEAN\n-NlFillNlHdr(PNL_BUFFER nlBuf, UINT16 nlmsgType,\n- UINT16 nlmsgFlags, UINT32 nlmsgSeq,\n- UINT32 nlmsgPid)\n-{\n- BOOLEAN writeOk;\n- NL_MSG_HDR msgOut;\n- UINT32 offset = NlBufSize(nlBuf);\n-\n- /* To keep compiler happy for release build. */\n- UNREFERENCED_PARAMETER(offset);\n- ASSERT(NlBufAt(nlBuf, offset, 0) != 0);\n-\n- msgOut.nlmsgType = nlmsgType;\n- msgOut.nlmsgFlags = nlmsgFlags;\n- msgOut.nlmsgSeq = nlmsgSeq;\n- msgOut.nlmsgPid = nlmsgPid;\n- msgOut.nlmsgLen = sizeof(struct _NL_MSG_HDR);\n-\n- writeOk = NlMsgPutTail(nlBuf, (PCHAR)(&msgOut),\n- sizeof(struct _NL_MSG_HDR));\n-\n- return writeOk;\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Prepare a 'OVS_MESSAGE_ERROR' message.\n- * ---------------------------------------------------------------------------\n- */\n-VOID\n-NlBuildErrorMsg(POVS_MESSAGE msgIn, POVS_MESSAGE_ERROR msgError,\n- UINT errorCode, UINT32 *replyLen)\n-{\n- NL_BUFFER nlBuffer;\n-\n- ASSERT(errorCode != NL_ERROR_PENDING);\n-\n- NlBufInit(&nlBuffer, (PCHAR)msgError, sizeof *msgError);\n- NlFillNlHdr(&nlBuffer, NLMSG_ERROR, 0,\n- msgIn->nlMsg.nlmsgSeq, msgIn->nlMsg.nlmsgPid);\n-\n- msgError->errorMsg.error = errorCode;\n- msgError->errorMsg.nlMsg = msgIn->nlMsg;\n- msgError->nlMsg.nlmsgLen = sizeof(OVS_MESSAGE_ERROR);\n-\n- *replyLen = msgError->nlMsg.nlmsgLen;\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Adds Netlink Header to the NL_BUF.\n- * ---------------------------------------------------------------------------\n- */\n-BOOLEAN\n-NlMsgPutNlHdr(PNL_BUFFER buf, PNL_MSG_HDR nlMsg)\n-{\n- if ((NlBufCopyAtOffset(buf, (PCHAR)nlMsg, NLMSG_HDRLEN, 0))) {\n- return TRUE;\n- }\n-\n- return FALSE;\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Adds Genl Header to the NL_BUF.\n- * ---------------------------------------------------------------------------\n- */\n-BOOLEAN\n-NlMsgPutGenlHdr(PNL_BUFFER buf, PGENL_MSG_HDR genlMsg)\n-{\n- if ((NlBufCopyAtOffset(buf, (PCHAR)genlMsg, GENL_HDRLEN, NLMSG_HDRLEN))) {\n- return TRUE;\n- }\n-\n- return FALSE;\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Adds OVS Header to the NL_BUF.\n- * ---------------------------------------------------------------------------\n- */\n-BOOLEAN\n-NlMsgPutOvsHdr(PNL_BUFFER buf, POVS_HDR ovsHdr)\n-{\n- if ((NlBufCopyAtOffset(buf, (PCHAR)ovsHdr, OVS_HDRLEN,\n- GENL_HDRLEN + NLMSG_HDRLEN))) {\n- return TRUE;\n- }\n-\n- return FALSE;\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Adds data of length 'len' to the tail end of NL_BUF.\n- * Refer nl_msg_put for more details.\n- * ---------------------------------------------------------------------------\n- */\n-BOOLEAN\n-NlMsgPutTail(PNL_BUFFER buf, const PCHAR data, UINT32 len)\n-{\n- len = NLMSG_ALIGN(len);\n- if (NlBufCopyAtTail(buf, data, len)) {\n- return TRUE;\n- }\n-\n- return FALSE;\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * memsets length 'len' at tail end of NL_BUF.\n- * Refer nl_msg_put_uninit for more details.\n- * ---------------------------------------------------------------------------\n- */\n-PCHAR\n-NlMsgPutTailUninit(PNL_BUFFER buf, UINT32 len)\n-{\n- len = NLMSG_ALIGN(len);\n- return NlBufCopyAtTailUninit(buf, len);\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Adds an attribute to the tail end of buffer. It does\n- * not copy the attribute payload.\n- * Refer nl_msg_put_unspec_uninit for more details.\n- * ---------------------------------------------------------------------------\n- */\n-PCHAR\n-NlMsgPutTailUnspecUninit(PNL_BUFFER buf, UINT16 type, UINT16 len)\n-{\n- PCHAR ret = NULL;\n- UINT16 totalLen = NLA_HDRLEN + len;\n- PNL_ATTR nla = (PNL_ATTR)(NlMsgPutTailUninit(buf, totalLen));\n-\n- if (!nla) {\n- goto done;\n- }\n-\n- ret = (PCHAR)(nla + 1);\n- nla->nlaLen = totalLen;\n- nla->nlaType = type;\n-\n-done:\n- return ret;\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Adds an attribute to the tail end of buffer. It copies attribute\n- * payload as well.\n- * Refer nl_msg_put_unspec for more details.\n- * ---------------------------------------------------------------------------\n- */\n-BOOLEAN\n-NlMsgPutTailUnspec(PNL_BUFFER buf, UINT16 type, PCHAR data, UINT16 len)\n-{\n- BOOLEAN ret = TRUE;\n- PCHAR nlaData = NlMsgPutTailUnspecUninit(buf, type, len);\n-\n- if (!nlaData) {\n- ret = FALSE;\n- goto done;\n- }\n-\n- RtlCopyMemory(nlaData, data, len);\n-\n-done:\n- return ret;\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Adds an attribute of 'type' and no payload at the tail end of buffer.\n- * Refer nl_msg_put_flag for more details.\n- * ---------------------------------------------------------------------------\n- */\n-BOOLEAN\n-NlMsgPutTailFlag(PNL_BUFFER buf, UINT16 type)\n-{\n- BOOLEAN ret = TRUE;\n- PCHAR nlaData = NlMsgPutTailUnspecUninit(buf, type, 0);\n-\n- if (!nlaData) {\n- ret = FALSE;\n- }\n-\n- return ret;\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Adds an attribute of 'type' and 8 bit payload at the tail end of buffer.\n- * Refer nl_msg_put_u8 for more details.\n- * ---------------------------------------------------------------------------\n- */\n-BOOLEAN\n-NlMsgPutTailU8(PNL_BUFFER buf, UINT16 type, UINT8 value)\n-{\n- return (NlMsgPutTailUnspec(buf, type, (PCHAR)(&value), sizeof(value)));\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Adds an attribute of 'type' and 16 bit payload at the tail end of buffer.\n- * Refer nl_msg_put_u16 for more details.\n- * ---------------------------------------------------------------------------\n- */\n-BOOLEAN\n-NlMsgPutTailU16(PNL_BUFFER buf, UINT16 type, UINT16 value)\n-{\n- return (NlMsgPutTailUnspec(buf, type, (PCHAR)(&value), sizeof(value)));\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Adds an attribute of 'type' and 32 bit payload at the tail end of buffer.\n- * Refer nl_msg_put_u32 for more details.\n- * ---------------------------------------------------------------------------\n- */\n-BOOLEAN\n-NlMsgPutTailU32(PNL_BUFFER buf, UINT16 type, UINT32 value)\n-{\n- return (NlMsgPutTailUnspec(buf, type, (PCHAR)(&value), sizeof(value)));\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Adds an attribute of 'type' and 64 bit payload at the tail end of buffer.\n- * Refer nl_msg_put_u64 for more details.\n- * ---------------------------------------------------------------------------\n- */\n-BOOLEAN\n-NlMsgPutTailU64(PNL_BUFFER buf, UINT16 type, UINT64 value)\n-{\n- return (NlMsgPutTailUnspec(buf, type, (PCHAR)(&value), sizeof(value)));\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Adds an attribute of 'type' and string payload.\n- * Refer nl_msg_put_string for more details.\n- * ---------------------------------------------------------------------------\n- */\n-BOOLEAN\n-NlMsgPutTailString(PNL_BUFFER buf, UINT16 type, PCHAR value)\n-{\n- size_t strLen = strlen(value) + 1;\n-#ifdef DBG\n- /* Attribute length should come within 16 bits (NL_ATTR).\n- * Not a likely case, hence validation only in debug mode. */\n- if ((strLen + PAD_SIZE(strLen, NLA_ALIGNTO)) > MAXUINT16) {\n- return FALSE;\n- }\n-#endif\n-\n- /* typecast to keep compiler happy */\n- return (NlMsgPutTailUnspec(buf, type, value,\n- (UINT16)strLen));\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Adds data of length 'len' to the head of NL_BUF.\n- * Refer nl_msg_push for more details.\n- * ---------------------------------------------------------------------------\n- */\n-BOOLEAN\n-NlMsgPutHead(PNL_BUFFER buf, const PCHAR data, UINT32 len)\n-{\n- len = NLMSG_ALIGN(len);\n- if (NlBufCopyAtHead(buf, data, len)) {\n- return TRUE;\n- }\n-\n- return FALSE;\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * memsets length 'len' at head of NL_BUF.\n- * Refer nl_msg_push_uninit for more details.\n- * ---------------------------------------------------------------------------\n- */\n-PCHAR\n-NlMsgPutHeadUninit(PNL_BUFFER buf, UINT32 len)\n-{\n- len = NLMSG_ALIGN(len);\n- return NlBufCopyAtHeadUninit(buf, len);\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Adds an attribute to the head of buffer. It does\n- * not copy the attribute payload.\n- * Refer nl_msg_push_unspec_uninit for more details.\n- * ---------------------------------------------------------------------------\n- */\n-PCHAR\n-NlMsgPutHeadUnspecUninit(PNL_BUFFER buf, UINT16 type, UINT16 len)\n-{\n- PCHAR ret = NULL;\n- UINT16 totalLen = NLA_HDRLEN + len;\n- PNL_ATTR nla = (PNL_ATTR)(NlMsgPutHeadUninit(buf, totalLen));\n-\n- if (!nla) {\n- goto done;\n- }\n-\n- ret = (PCHAR)(nla + 1);\n- nla->nlaLen = totalLen;\n- nla->nlaType = type;\n-\n-done:\n- return ret;\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Adds an attribute to the head of buffer. It copies attribute\n- * payload as well.\n- * Refer nl_msg_push_unspec for more details.\n- * ---------------------------------------------------------------------------\n- */\n-BOOLEAN\n-NlMsgPutHeadUnspec(PNL_BUFFER buf, UINT16 type, PCHAR data, UINT16 len)\n-{\n- BOOLEAN ret = TRUE;\n- PCHAR nlaData = NlMsgPutHeadUnspecUninit(buf, type, len);\n-\n- if (!nlaData) {\n- ret = FALSE;\n- goto done;\n- }\n-\n- RtlCopyMemory(nlaData, data, len);\n-\n-done:\n- return ret;\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Adds an attribute of 'type' and no payload at the head of buffer.\n- * Refer nl_msg_push_flag for more details.\n- * ---------------------------------------------------------------------------\n- */\n-BOOLEAN\n-NlMsgPutHeadFlag(PNL_BUFFER buf, UINT16 type)\n-{\n- BOOLEAN ret = TRUE;\n- PCHAR nlaData = NlMsgPutHeadUnspecUninit(buf, type, 0);\n-\n- if (!nlaData) {\n- ret = FALSE;\n- }\n-\n- return ret;\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Adds an attribute of 'type' and 8 bit payload at the head of buffer.\n- * Refer nl_msg_push_u8 for more details.\n- * ---------------------------------------------------------------------------\n- */\n-BOOLEAN\n-NlMsgPutHeadU8(PNL_BUFFER buf, UINT16 type, UINT8 value)\n-{\n- return (NlMsgPutHeadUnspec(buf, type, (PCHAR)(&value), sizeof(value)));\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Adds an attribute of 'type' and 16 bit payload at the head of buffer.\n- * Refer nl_msg_push_u16 for more details.\n- * ---------------------------------------------------------------------------\n- */\n-BOOLEAN\n-NlMsgPutHeadU16(PNL_BUFFER buf, UINT16 type, UINT16 value)\n-{\n- return (NlMsgPutHeadUnspec(buf, type, (PCHAR)(&value), sizeof(value)));\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Adds an attribute of 'type' and 32 bit payload at the head of buffer.\n- * Refer nl_msg_push_u32 for more details.\n- * ---------------------------------------------------------------------------\n- */\n-BOOLEAN\n-NlMsgPutHeadU32(PNL_BUFFER buf, UINT16 type, UINT32 value)\n-{\n- return (NlMsgPutHeadUnspec(buf, type, (PCHAR)(&value), sizeof(value)));\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Adds an attribute of 'type' and 64 bit payload at the head of buffer.\n- * Refer nl_msg_push_u64 for more details.\n- * ---------------------------------------------------------------------------\n- */\n-BOOLEAN\n-NlMsgPutHeadU64(PNL_BUFFER buf, UINT16 type, UINT64 value)\n-{\n- return (NlMsgPutHeadUnspec(buf, type, (PCHAR)(&value), sizeof(value)));\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Adds an attribute of 'type' and string payload.\n- * Refer nl_msg_push_string for more details.\n- * ---------------------------------------------------------------------------\n- */\n-BOOLEAN\n-NlMsgPutHeadString(PNL_BUFFER buf, UINT16 type, PCHAR value)\n-{\n- size_t strLen = strlen(value) + 1;\n-#ifdef DBG\n- /* Attribute length should come within 16 bits (NL_ATTR).\n- * Not a likely case, hence validation only in debug mode. */\n- if ((strLen + PAD_SIZE(strLen, NLA_ALIGNTO)) > MAXUINT16) {\n- return FALSE;\n- }\n-#endif\n-\n- /* typecast to keep compiler happy */\n- return (NlMsgPutHeadUnspec(buf, type, value,\n- (UINT16)strLen));\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Adds the header for nested netlink attributes. It\n- * returns the offset of this header. If addition of header fails\n- * then returned value of offset will be zero.\n- * Refer nl_msg_start_nested for more details.\n- * ---------------------------------------------------------------------------\n- */\n-UINT32\n-NlMsgStartNested(PNL_BUFFER buf, UINT16 type)\n-{\n- UINT32 offset = NlBufSize(buf);\n- PCHAR nlaData = NULL;\n-\n- nlaData = NlMsgPutTailUnspecUninit(buf, type, 0);\n-\n- if (!nlaData) {\n- /* Value zero must be reated as error by the caller.\n- * This is because an attribute can never be added\n- * at offset zero, it will always come after NL_MSG_HDR,\n- * GENL_HDR and OVS_HEADER. */\n- offset = 0;\n- }\n-\n- return offset;\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Finalizes the nested netlink attribute by updating the nla_len.\n- * offset should be the one returned by NlMsgStartNested.\n- * Refer nl_msg_end_nested for more details.\n- * ---------------------------------------------------------------------------\n- */\n-VOID\n-NlMsgEndNested(PNL_BUFFER buf, UINT32 offset)\n-{\n- PNL_ATTR attr = (PNL_ATTR)(NlBufAt(buf, offset, sizeof *attr));\n-\n- /* Typecast to keep compiler happy.\n- * Attribute length would never exceed MAX UINT16.*/\n- attr->nlaLen = (UINT16)(NlBufSize(buf) - offset);\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Appends a nested Netlink attribute of the given 'type', with the 'size'\n- * bytes of content starting at 'data', to 'msg'.\n- * Refer nl_msg_put_nested for more details.\n- * --------------------------------------------------------------------------\n- */\n-BOOLEAN\n-NlMsgPutNested(PNL_BUFFER buf, UINT16 type,\n- const PVOID data, UINT32 size)\n-{\n- UINT32 offset = NlMsgStartNested(buf, type);\n- BOOLEAN ret;\n-\n- ASSERT(offset);\n-\n- ret = NlMsgPutTail(buf, data, size);\n-\n- ASSERT(ret);\n-\n- NlMsgEndNested(buf, offset);\n-\n- return ret;\n-}\n-\n-/* Accessing netlink message payload */\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Netlink message accessing the payload.\n- * ---------------------------------------------------------------------------\n- */\n-PVOID\n-NlMsgAt(const PNL_MSG_HDR nlh, UINT32 offset)\n-{\n- return ((PCHAR)nlh + offset);\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Returns the size of netlink message.\n- * ---------------------------------------------------------------------------\n- */\n-UINT32\n-NlMsgSize(const PNL_MSG_HDR nlh)\n-{\n- return nlh->nlmsgLen;\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Aligns the size of Netlink message.\n- * ---------------------------------------------------------------------------\n- */\n-VOID\n-NlMsgAlignSize(const PNL_MSG_HDR nlh)\n-{\n- nlh->nlmsgLen = NLMSG_ALIGN(nlh->nlmsgLen);\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Sets the size of Netlink message.\n- * ---------------------------------------------------------------------------\n- */\n-VOID\n-NlMsgSetSize(const PNL_MSG_HDR nlh, UINT32 msgLen)\n-{\n- nlh->nlmsgLen = msgLen;\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Returns pointer to nlmsg payload.\n- * ---------------------------------------------------------------------------\n- */\n-PCHAR\n-NlHdrPayload(const PNL_MSG_HDR nlh)\n-{\n- return ((PCHAR)nlh + NLMSG_HDRLEN);\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Returns length of nlmsg payload.\n- * ---------------------------------------------------------------------------\n- */\n-UINT32\n-NlHdrPayloadLen(const PNL_MSG_HDR nlh)\n-{\n- return nlh->nlmsgLen - NLMSG_HDRLEN;\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Returns pointer to nlmsg attributes.\n- * ---------------------------------------------------------------------------\n- */\n-PNL_ATTR\n-NlMsgAttrs(const PNL_MSG_HDR nlh)\n-{\n- return (PNL_ATTR) (NlHdrPayload(nlh) + GENL_HDRLEN + OVS_HDRLEN);\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Returns size of to nlmsg attributes.\n- * ---------------------------------------------------------------------------\n- */\n-UINT32\n-NlMsgAttrsLen(const PNL_MSG_HDR nlh)\n-{\n- return NlHdrPayloadLen(nlh) - GENL_HDRLEN - OVS_HDRLEN;\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Returns size of to nfnlmsg attributes.\n- * ---------------------------------------------------------------------------\n- */\n-UINT32\n-NlNfMsgAttrsLen(const PNL_MSG_HDR nlh)\n-{\n- return NlHdrPayloadLen(nlh) - NF_GEN_MSG_HDRLEN - OVS_HDRLEN;\n-}\n-\n-/* Netlink message parse. */\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Returns next netlink message in the stream.\n- * ---------------------------------------------------------------------------\n- */\n-PNL_MSG_HDR\n-NlMsgNext(const PNL_MSG_HDR nlh)\n-{\n- return (PNL_MSG_HDR)((PCHAR)nlh +\n- NLMSG_ALIGN(nlh->nlmsgLen));\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Netlink Attr helper APIs.\n- * ---------------------------------------------------------------------------\n- */\n-INT\n-NlAttrIsValid(const PNL_ATTR nla, UINT32 maxlen)\n-{\n- return (maxlen >= sizeof *nla\n- && nla->nlaLen >= sizeof *nla\n- && nla->nlaLen <= maxlen);\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Returns alligned length of the attribute.\n- * ---------------------------------------------------------------------------\n- */\n-UINT32\n-NlAttrLenPad(const PNL_ATTR nla, UINT32 maxlen)\n-{\n- UINT32 len = NLA_ALIGN(nla->nlaLen);\n-\n- return len <= maxlen ? len : nla->nlaLen;\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Default minimum payload size for each type of attribute.\n- * ---------------------------------------------------------------------------\n- */\n-UINT32\n-NlAttrMinLen(NL_ATTR_TYPE type)\n-{\n- switch (type) {\n- case NL_A_NO_ATTR: return 0;\n- case NL_A_UNSPEC: return 0;\n- case NL_A_U8: return 1;\n- case NL_A_U16: return 2;\n- case NL_A_U32: return 4;\n- case NL_A_U64: return 8;\n- case NL_A_STRING: return 1;\n- case NL_A_FLAG: return 0;\n- case NL_A_NESTED: return 0;\n- case N_NL_ATTR_TYPES:\n- default:\n- OVS_LOG_WARN(\"Unsupprted attribute type: %d\", type);\n- ASSERT(0);\n- }\n-\n- /* To keep compiler happy */\n- return 0;\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Default maximum payload size for each type of attribute.\n- * ---------------------------------------------------------------------------\n- */\n-UINT32\n-NlAttrMaxLen(NL_ATTR_TYPE type)\n-{\n- switch (type) {\n- case NL_A_NO_ATTR: return SIZE_MAX;\n- case NL_A_UNSPEC: return SIZE_MAX;\n- case NL_A_U8: return 1;\n- case NL_A_U16: return 2;\n- case NL_A_U32: return 4;\n- case NL_A_U64: return 8;\n- case NL_A_STRING: return MAXUINT16;\n- case NL_A_FLAG: return SIZE_MAX;\n- case NL_A_NESTED: return SIZE_MAX;\n- case N_NL_ATTR_TYPES:\n- default:\n- OVS_LOG_WARN(\"Unsupprted attribute type: %d\", type);\n- ASSERT(0);\n- }\n-\n- /* To keep compiler happy */\n- return 0;\n-}\n-\n-/* Netlink attribute iteration. */\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Returns the next attribute.\n- * ---------------------------------------------------------------------------\n- */\n-PNL_ATTR\n-NlAttrNext(const PNL_ATTR nla)\n-{\n- return (PNL_ATTR)((UINT8 *)nla + NLA_ALIGN(nla->nlaLen));\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Returns the bits of 'nla->nlaType' that are significant for determining\n- * its type.\n- * --------------------------------------------------------------------------\n- */\n-UINT16\n-NlAttrType(const PNL_ATTR nla)\n-{\n- return nla->nlaType & NLA_TYPE_MASK;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Returns the netlink attribute data.\n- * --------------------------------------------------------------------------\n- */\n-PVOID\n-NlAttrData(const PNL_ATTR nla)\n-{\n- return ((PCHAR)nla + NLA_HDRLEN);\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Returns the number of bytes in the payload of attribute 'nla'.\n- * ---------------------------------------------------------------------------\n- */\n-UINT32\n-NlAttrGetSize(const PNL_ATTR nla)\n-{\n- return nla->nlaLen - NLA_HDRLEN;\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Returns the first byte in the payload of attribute 'nla'.\n- * ---------------------------------------------------------------------------\n- */\n-const PVOID\n-NlAttrGet(const PNL_ATTR nla)\n-{\n- ASSERT(nla->nlaLen >= NLA_HDRLEN);\n- return nla + 1;\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Asserts that 'nla''s payload is at least 'size' bytes long, and returns the\n- * first byte of the payload.\n- * ---------------------------------------------------------------------------\n- */\n-const\n-PVOID NlAttrGetUnspec(const PNL_ATTR nla, UINT32 size)\n-{\n- UNREFERENCED_PARAMETER(size);\n- ASSERT(nla->nlaLen >= NLA_HDRLEN + size);\n- return nla + 1;\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Returns the 64-bit network byte order value in 'nla''s payload.\n- *\n- * Asserts that 'nla''s payload is at least 8 bytes long.\n- * ---------------------------------------------------------------------------\n- */\n-BE64\n-NlAttrGetBe64(const PNL_ATTR nla)\n-{\n- return NL_ATTR_GET_AS(nla, BE64);\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Returns the 32-bit network byte order value in 'nla''s payload.\n- *\n- * Asserts that 'nla''s payload is at least 4 bytes long.\n- * ---------------------------------------------------------------------------\n- */\n-BE32\n-NlAttrGetBe32(const PNL_ATTR nla)\n-{\n- return NL_ATTR_GET_AS(nla, BE32);\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Returns the 16-bit network byte order value in 'nla''s payload.\n- *\n- * Asserts that 'nla''s payload is at least 2 bytes long.\n- * ---------------------------------------------------------------------------\n- */\n-BE16\n-NlAttrGetBe16(const PNL_ATTR nla)\n-{\n- return NL_ATTR_GET_AS(nla, BE16);\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Returns the 8-bit network byte order value in 'nla''s payload.\n- *\n- * Asserts that 'nla''s payload is at least 1 byte long.\n- * ---------------------------------------------------------------------------\n- */\n-BE8\n-NlAttrGetBe8(const PNL_ATTR nla)\n-{\n- return NL_ATTR_GET_AS(nla, BE8);\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Returns the 8-bit value in 'nla''s payload.\n- * ---------------------------------------------------------------------------\n- */\n-UINT8\n-NlAttrGetU8(const PNL_ATTR nla)\n-{\n- return NL_ATTR_GET_AS(nla, UINT8);\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Returns the 16-bit host byte order value in 'nla''s payload.\n- * Asserts that 'nla''s payload is at least 2 bytes long.\n- * ---------------------------------------------------------------------------\n- */\n-UINT16\n-NlAttrGetU16(const PNL_ATTR nla)\n-{\n- return NL_ATTR_GET_AS(nla, UINT16);\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Returns the 32-bit host byte order value in 'nla''s payload.\n- * Asserts that 'nla''s payload is at least 4 bytes long.\n- * ---------------------------------------------------------------------------\n- */\n-UINT32\n-NlAttrGetU32(const PNL_ATTR nla)\n-{\n- return NL_ATTR_GET_AS(nla, UINT32);\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Returns the 64-bit host byte order value in 'nla''s payload.\n- * Asserts that 'nla''s payload is at least 8 bytes long.\n- * ---------------------------------------------------------------------------\n- */\n-UINT64\n-NlAttrGetU64(const PNL_ATTR nla)\n-{\n- return NL_ATTR_GET_AS(nla, UINT64);\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Returns the string value in 'nla''s payload.\n- * Returns NULL if it is not a proper '\\0' terminated string.\n- * ---------------------------------------------------------------------------\n- */\n-PCHAR\n-NlAttrGetString(const PNL_ATTR nla)\n-{\n- ASSERT(nla->nlaLen >= NLA_HDRLEN);\n- if (!memchr(NlAttrGet(nla), '\\0', NlAttrGetSize(nla))) {\n- return NULL;\n- }\n- return NlAttrGet(nla);\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Validate the netlink attribute against the policy\n- * ---------------------------------------------------------------------------\n- */\n-BOOLEAN\n-NlAttrValidate(const PNL_ATTR nla, const PNL_POLICY policy)\n-{\n- UINT32 minLen;\n- UINT32 maxLen;\n- UINT32 len;\n- BOOLEAN ret = FALSE;\n-\n- if ((policy->type == NL_A_NO_ATTR) ||\n- (policy->type == NL_A_VAR_LEN) ||\n- (policy->type == NL_A_NESTED)) {\n- /* Do not validate anything for attributes of type var length */\n- ret = TRUE;\n- goto done;\n- }\n-\n- /* Figure out min and max length. */\n- minLen = policy->minLen;\n- if (!minLen) {\n- minLen = NlAttrMinLen(policy->type);\n- }\n- maxLen = policy->maxLen;\n- if (!maxLen) {\n- maxLen = NlAttrMaxLen(policy->type);\n- }\n-\n- /* Verify length. */\n- len = NlAttrGetSize(nla);\n- if (len < minLen || len > maxLen) {\n- OVS_LOG_WARN(\"Attribute: %p, len: %d, not in valid range, \"\n- \"min: %d, max: %d\", nla, len, minLen, maxLen);\n- goto done;\n- }\n-\n- /* Strings must be null terminated and must not have embedded nulls. */\n- if (policy->type == NL_A_STRING) {\n- if (((PCHAR) nla)[nla->nlaLen - 1]) {\n- OVS_LOG_WARN(\"Attributes %p lacks null at the end\", nla);\n- goto done;\n- }\n-\n- if (memchr(nla + 1, '\\0', len - 1) != NULL) {\n- OVS_LOG_WARN(\"Attributes %p has bad length\", nla);\n- goto done;\n- }\n- }\n-\n- ret = TRUE;\n-\n-done:\n- return ret;\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Returns an attribute of type 'type' from a series of\n- * attributes.\n- * ---------------------------------------------------------------------------\n- */\n-const PNL_ATTR\n-NlAttrFind__(const PNL_ATTR attrs, UINT32 size, UINT16 type)\n-{\n- PNL_ATTR iter = NULL;\n- PNL_ATTR ret = NULL;\n- INT left;\n-\n- NL_ATTR_FOR_EACH (iter, left, attrs, size) {\n- if (NlAttrType(iter) == type) {\n- ret = iter;\n- goto done;\n- }\n- }\n-\n-done:\n- return ret;\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Returns the first Netlink attribute within 'nla' with the specified\n- * 'type'.\n- *\n- * This function does not validate the attribute's length.\n- * ---------------------------------------------------------------------------\n- */\n-const PNL_ATTR\n-NlAttrFindNested(const PNL_ATTR nla, UINT16 type)\n-{\n- return NlAttrFind__((const PNL_ATTR)(NlAttrGet(nla)),\n- NlAttrGetSize(nla), type);\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * Traverses all attributes in received buffer in order to insure all are valid\n- *----------------------------------------------------------------------------\n- */\n-BOOLEAN NlValidateAllAttrs(const PNL_MSG_HDR nlMsg, UINT32 attrOffset,\n- UINT32 totalAttrLen,\n- const NL_POLICY policy[], const UINT32 numPolicy)\n-{\n- PNL_ATTR nla;\n- INT left;\n- BOOLEAN ret = TRUE;\n-\n- if ((NlMsgSize(nlMsg) < attrOffset)) {\n- OVS_LOG_WARN(\"No attributes in nlMsg: %p at offset: %d\",\n- nlMsg, attrOffset);\n- ret = FALSE;\n- goto done;\n- }\n-\n- NL_ATTR_FOR_EACH_UNSAFE(nla, left, NlMsgAt(nlMsg, attrOffset),\n- totalAttrLen)\n- {\n- if (!NlAttrIsValid(nla, left)) {\n- ret = FALSE;\n- goto done;\n- }\n-\n- UINT16 type = NlAttrType(nla);\n- if (type < numPolicy && policy[type].type != NL_A_NO_ATTR) {\n- /* Typecasting to keep the compiler happy */\n- const PNL_POLICY e = (const PNL_POLICY)(&policy[type]);\n- if (!NlAttrValidate(nla, e)) {\n- ret = FALSE;\n- goto done;\n- }\n- }\n- }\n-\n-done:\n- return ret;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * Parses the netlink message at a given offset (attrOffset)\n- * as a series of attributes. A pointer to the attribute with type\n- * 'type' is stored in attrs at index 'type'. policy is used to define the\n- * attribute type validation parameters.\n- * 'nla_offset' should be NLMSG_HDRLEN + GENL_HDRLEN + OVS_HEADER\n- *\n- * Returns BOOLEAN to indicate success/failure.\n- *----------------------------------------------------------------------------\n- */\n-BOOLEAN\n-NlAttrParse(const PNL_MSG_HDR nlMsg, UINT32 attrOffset,\n- UINT32 totalAttrLen,\n- const NL_POLICY policy[], const UINT32 numPolicy,\n- PNL_ATTR attrs[], UINT32 numAttrs)\n-{\n- PNL_ATTR nla;\n- INT left;\n- UINT32 iter;\n- BOOLEAN ret = FALSE;\n- UINT32 numPolicyAttr = MIN(numPolicy, numAttrs);\n-\n- RtlZeroMemory(attrs, numAttrs * sizeof *attrs);\n-\n- if ((NlMsgSize(nlMsg) < attrOffset)) {\n- OVS_LOG_WARN(\"No attributes in nlMsg: %p at offset: %d\",\n- nlMsg, attrOffset);\n- goto done;\n- }\n-\n- NL_ATTR_FOR_EACH (nla, left, NlMsgAt(nlMsg, attrOffset),\n- totalAttrLen)\n- {\n- UINT16 type = NlAttrType(nla);\n- if (type < numPolicyAttr && policy[type].type != NL_A_NO_ATTR) {\n- /* Typecasting to keep the compiler happy */\n- const PNL_POLICY e = (const PNL_POLICY)(&policy[type]);\n- if (!NlAttrValidate(nla, e)) {\n- goto done;\n- }\n-\n- if (attrs[type]) {\n- OVS_LOG_WARN(\"Duplicate attribute in nlMsg: %p, \"\n- \"type: %u\", nlMsg, type);\n- }\n-\n- attrs[type] = nla;\n- }\n- }\n-\n- if (left) {\n- OVS_LOG_ERROR(\"Attributes followed by garbage\");\n- goto done;\n- }\n-\n- for (iter = 0; iter < numPolicyAttr; iter++) {\n- const PNL_POLICY e = (const PNL_POLICY)(&policy[iter]);\n- if (!e->optional && e->type != NL_A_NO_ATTR && !attrs[iter]) {\n- OVS_LOG_ERROR(\"Required attr:%d missing\", iter);\n- goto done;\n- }\n- }\n-\n- ret = TRUE;\n-\n-done:\n- return ret;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * Parses the netlink message for nested attributes. attrOffset must be the\n- * offset of nla which is the header of the nested attribute series.\n- * Refer nl_parse_nested for more details.\n- *\n- * Returns BOOLEAN to indicate success/failure.\n- *----------------------------------------------------------------------------\n- */\n-BOOLEAN\n-NlAttrParseNested(const PNL_MSG_HDR nlMsg, UINT32 attrOffset,\n- UINT32 totalAttrLen,\n- const NL_POLICY policy[], const UINT32 numPolicy,\n- PNL_ATTR attrs[], UINT32 numAttrs)\n-{\n- return NlAttrParse(nlMsg, attrOffset + NLA_HDRLEN,\n- totalAttrLen - NLA_HDRLEN, policy, numPolicy,\n- attrs, numAttrs);\n-}\ndiff --git a/datapath-windows/ovsext/Netlink/Netlink.h b/datapath-windows/ovsext/Netlink/Netlink.h\ndeleted file mode 100644\nindex 964c0e5f5..000000000\n--- a/datapath-windows/ovsext/Netlink/Netlink.h\n+++ /dev/null\n@@ -1,243 +0,0 @@\n-/*\n- * Copyright (c) 2008, 2009, 2010, 2011, 2013, 2014 Nicira, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#ifndef __NETLINK_H_\n-#define __NETLINK_H_ 1\n-\n-#include \"Types.h\"\n-#include \"NetlinkProto.h\"\n-#include \"NetlinkBuf.h\"\n-#include \"..\\..\\include\\OvsDpInterface.h\"\n-\n-/*\n- * Structure of any message passed between userspace and kernel.\n- */\n-typedef struct _OVS_MESSAGE {\n- NL_MSG_HDR nlMsg;\n- union {\n- GENL_MSG_HDR genlMsg;\n- NF_GEN_MSG_HDR nfGenMsg;\n- };\n- OVS_HDR ovsHdr;\n- /* Variable length nl_attrs follow. */\n-} OVS_MESSAGE, *POVS_MESSAGE;\n-BUILD_ASSERT_DECL(sizeof(GENL_MSG_HDR) == sizeof(NF_GEN_MSG_HDR));\n-\n-/*\n- * Structure of an error message sent as a reply from kernel.\n- */\n-typedef struct _OVS_MESSAGE_ERROR {\n- NL_MSG_HDR nlMsg;\n- NL_MSG_ERR errorMsg;\n-} OVS_MESSAGE_ERROR, *POVS_MESSAGE_ERROR;\n-\n-/* Netlink attribute types. */\n-typedef enum\n-{\n- NL_A_NO_ATTR = 0,\n- NL_A_VAR_LEN,\n- NL_A_UNSPEC,\n- NL_A_U8,\n- NL_A_U16,\n- NL_A_BE16 = NL_A_U16,\n- NL_A_U32,\n- NL_A_BE32 = NL_A_U32,\n- NL_A_U64,\n- NL_A_BE64 = NL_A_U64,\n- NL_A_STRING,\n- NL_A_FLAG,\n- NL_A_NESTED,\n- N_NL_ATTR_TYPES\n-} NL_ATTR_TYPE;\n-\n-/* Netlink attribute policy.\n- * Specifies the policy for parsing for netlink attribute. */\n-typedef struct _NL_POLICY\n-{\n- NL_ATTR_TYPE type;\n- UINT32 minLen;\n- UINT32 maxLen;\n- BOOLEAN optional;\n-} NL_POLICY, *PNL_POLICY;\n-\n-/* This macro is careful to check for attributes with bad lengths. */\n-#define NL_ATTR_FOR_EACH(ITER, LEFT, ATTRS, ATTRS_LEN) \\\n- for ((ITER) = (ATTRS), (LEFT) = (ATTRS_LEN); \\\n- ((INT)LEFT) >= (INT)NLA_ALIGN(sizeof(NL_ATTR)) && \\\n- NlAttrIsValid(ITER, LEFT); \\\n- (LEFT) -= NlAttrLenPad(ITER, LEFT), (ITER) = NlAttrNext(ITER))\n-\n-/* This macro does not check for attributes with bad lengths. It should only\n- * be used with messages from trusted sources or with messages that have\n- * already been validated (e.g. with NL_ATTR_FOR_EACH). */\n-#define NL_ATTR_FOR_EACH_UNSAFE(ITER, LEFT, ATTRS, ATTRS_LEN) \\\n- for ((ITER) = (ATTRS), (LEFT) = (ATTRS_LEN); \\\n- ((INT)LEFT) >= (INT)NLA_ALIGN(sizeof(NL_ATTR)); \\\n- (LEFT) -= NLA_ALIGN((ITER)->nlaLen), (ITER) = NlAttrNext(ITER))\n-\n-#define NL_ATTR_GET_AS(NLA, TYPE) \\\n- (*(TYPE*) NlAttrGetUnspec(nla, sizeof(TYPE)))\n-\n-BOOLEAN NlFillOvsMsg(PNL_BUFFER nlBuf,\n- UINT16 nlmsgType, UINT16 nlmsgFlags,\n- UINT32 nlmsgSeq, UINT32 nlmsgPid,\n- UINT8 genlCmd, UINT8 genlVer, UINT32 dpNo);\n-BOOLEAN NlFillOvsMsgForNfGenMsg(PNL_BUFFER nlBuf, UINT16 nlmsgType,\n- UINT16 nlmsgFlags, UINT32 nlmsgSeq,\n- UINT32 nlmsgPid, UINT8 nfgenFamily,\n- UINT8 nfGenVersion, UINT32 dpNo);\n-BOOLEAN NlFillNlHdr(PNL_BUFFER nlBuf,\n- UINT16 nlmsgType, UINT16 nlmsgFlags,\n- UINT32 nlmsgSeq, UINT32 nlmsgPid);\n-\n-VOID NlBuildErrorMsg(POVS_MESSAGE msgIn, POVS_MESSAGE_ERROR msgError,\n- UINT errorCode, UINT32 *msgLen);\n-\n-/* Netlink message accessing the payload */\n-PVOID NlMsgAt(const PNL_MSG_HDR nlh, UINT32 offset);\n-UINT32 NlMsgSize(const PNL_MSG_HDR nlh);\n-VOID NlMsgAlignSize(const PNL_MSG_HDR nlh);\n-VOID NlMsgSetSize(const PNL_MSG_HDR nlh, UINT32 msgLen);\n-PCHAR NlHdrPayload(const PNL_MSG_HDR nlh);\n-UINT32 NlHdrPayloadLen(const PNL_MSG_HDR nlh);\n-PNL_ATTR NlMsgAttrs(const PNL_MSG_HDR nlh);\n-UINT32 NlMsgAttrsLen(const PNL_MSG_HDR nlh);\n-UINT32 NlNfMsgAttrsLen(const PNL_MSG_HDR nlh);\n-\n-/* Netlink message parse */\n-PNL_MSG_HDR NlMsgNext(const PNL_MSG_HDR nlh);\n-INT NlAttrIsValid(const PNL_ATTR nla, UINT32 maxlen);\n-UINT32 NlAttrLenPad(const PNL_ATTR nla, UINT32 maxlen);\n-\n-/* Netlink attribute parsing. */\n-UINT32 NlAttrMinLen(NL_ATTR_TYPE type);\n-UINT32 NlAttrMinLen(NL_ATTR_TYPE type);\n-PNL_ATTR NlAttrNext(const PNL_ATTR nla);\n-UINT16 NlAttrType(const PNL_ATTR nla);\n-PVOID NlAttrData(const PNL_ATTR nla);\n-UINT32 NlAttrGetSize(const PNL_ATTR nla);\n-const PVOID NlAttrGet(const PNL_ATTR nla);\n-const PVOID NlAttrGetUnspec(const PNL_ATTR nla, UINT32 size);\n-BE64 NlAttrGetBe64(const PNL_ATTR nla);\n-BE32 NlAttrGetBe32(const PNL_ATTR nla);\n-BE16 NlAttrGetBe16(const PNL_ATTR nla);\n-UINT8 NlAttrGetU8(const PNL_ATTR nla);\n-UINT16 NlAttrGetU16(const PNL_ATTR nla);\n-UINT32 NlAttrGetU32(const PNL_ATTR nla);\n-UINT64 NlAttrGetU64(const PNL_ATTR nla);\n-PCHAR NlAttrGetString(const PNL_ATTR nla);\n-const PNL_ATTR NlAttrFind__(const PNL_ATTR attrs,\n- UINT32 size, UINT16 type);\n-const PNL_ATTR NlAttrFindNested(const PNL_ATTR nla,\n- UINT16 type);\n-BOOLEAN NlAttrParse(const PNL_MSG_HDR nlMsg, UINT32 attrOffset,\n- UINT32 totalAttrLen, const NL_POLICY policy[],\n- const UINT32 numPolicy, PNL_ATTR attrs[],\n- UINT32 numAttrs);\n-BOOLEAN NlAttrParseNested(const PNL_MSG_HDR nlMsg, UINT32 attrOffset,\n- UINT32 totalAttrLen, const NL_POLICY policy[],\n- const UINT32 numPolicy, PNL_ATTR attrs[],\n- UINT32 numAttrs);\n-/*\n- * --------------------------------------------------------------------------\n- * Returns the length of attribute.\n- * --------------------------------------------------------------------------\n- */\n-static __inline UINT16\n-NlAttrLen(const PNL_ATTR nla)\n-{\n- return nla->nlaLen;\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Default maximum payload size for each type of attribute.\n- * ---------------------------------------------------------------------------\n- */\n-UINT32\n-static __inline NlAttrSize(UINT32 payloadSize)\n-{\n- return NLA_HDRLEN + payloadSize;\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Total length including padding.\n- * ---------------------------------------------------------------------------\n- */\n-UINT32\n-static __inline NlAttrTotalSize(UINT32 payloadSize)\n-{\n- return NLA_ALIGN(NlAttrSize(payloadSize));\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Returns true if the last attribute is reached.\n- * ---------------------------------------------------------------------------\n- */\n-BOOLEAN\n-static __inline NlAttrIsLast(const PNL_ATTR nla, int rem)\n-{\n- return nla->nlaLen == rem;\n-}\n-\n-/* Netlink attribute validation */\n-BOOLEAN NlAttrValidate(const PNL_ATTR, const PNL_POLICY);\n-\n-/* Netlink attribute stream validation */\n-BOOLEAN NlValidateAllAttrs(const PNL_MSG_HDR nlMsg, UINT32 attrOffset,\n- UINT32 totalAttrLen,\n- const NL_POLICY policy[], const UINT32 numPolicy);\n-\n-/* Put APis */\n-BOOLEAN NlMsgPutNlHdr(PNL_BUFFER buf, PNL_MSG_HDR nlMsg);\n-BOOLEAN NlMsgPutGenlHdr(PNL_BUFFER buf, PGENL_MSG_HDR genlMsg);\n-BOOLEAN NlMsgPutOvsHdr(PNL_BUFFER buf, POVS_HDR ovsHdr);\n-\n-BOOLEAN NlMsgPutTail(PNL_BUFFER buf, const PCHAR data, UINT32 len);\n-PCHAR NlMsgPutTailUninit(PNL_BUFFER buf, UINT32 len);\n-PCHAR NlMsgPutTailUnspecUninit(PNL_BUFFER buf, UINT16 type, UINT16 len);\n-BOOLEAN NlMsgPutTailUnspec(PNL_BUFFER buf, UINT16 type, PCHAR data, UINT16 len);\n-BOOLEAN NlMsgPutTailFlag(PNL_BUFFER buf, UINT16 type);\n-BOOLEAN NlMsgPutTailU8(PNL_BUFFER buf, UINT16 type, UINT8 value);\n-BOOLEAN NlMsgPutTailU16(PNL_BUFFER buf, UINT16 type, UINT16 value);\n-BOOLEAN NlMsgPutTailU32(PNL_BUFFER buf, UINT16 type, UINT32 value);\n-BOOLEAN NlMsgPutTailU64(PNL_BUFFER buf, UINT16 type, UINT64 value);\n-BOOLEAN NlMsgPutTailString(PNL_BUFFER buf, UINT16 type, PCHAR value);\n-\n-BOOLEAN NlMsgPutHead(PNL_BUFFER buf, const PCHAR data, UINT32 len);\n-PCHAR NlMsgPutHeadUninit(PNL_BUFFER buf, UINT32 len);\n-PCHAR NlMsgPutHeadUnspecUninit(PNL_BUFFER buf, UINT16 type, UINT16 len);\n-BOOLEAN NlMsgPutHeadUnspec(PNL_BUFFER buf, UINT16 type, PCHAR data, UINT16 len);\n-BOOLEAN NlMsgPutHeadFlag(PNL_BUFFER buf, UINT16 type);\n-BOOLEAN NlMsgPutHeadU8(PNL_BUFFER buf, UINT16 type, UINT8 value);\n-BOOLEAN NlMsgPutHeadU16(PNL_BUFFER buf, UINT16 type, UINT16 value);\n-BOOLEAN NlMsgPutHeadU32(PNL_BUFFER buf, UINT16 type, UINT32 value);\n-BOOLEAN NlMsgPutHeadU64(PNL_BUFFER buf, UINT16 type, UINT64 value);\n-BOOLEAN NlMsgPutHeadString(PNL_BUFFER buf, UINT16 type, PCHAR value);\n-UINT32 NlMsgStartNested(PNL_BUFFER buf, UINT16 type);\n-VOID NlMsgEndNested(PNL_BUFFER buf, UINT32 offset);\n-BOOLEAN NlMsgPutNested(PNL_BUFFER buf, UINT16 type,\n- const PVOID data, UINT32 size);\n-\n-/* These variants are convenient for iterating nested attributes. */\n-#define NL_NESTED_FOR_EACH(ITER, LEFT, A) \\\n- NL_ATTR_FOR_EACH(ITER, LEFT, NlAttrGet(A), NlAttrGetSize(A))\n-#define NL_NESTED_FOR_EACH_UNSAFE(ITER, LEFT, A) \\\n- NL_ATTR_FOR_EACH_UNSAFE(ITER, LEFT, NlAttrGet(A), NlAttrGetSize(A))\n-\n-#endif /* __NETLINK_H_ */\ndiff --git a/datapath-windows/ovsext/Netlink/NetlinkBuf.c b/datapath-windows/ovsext/Netlink/NetlinkBuf.c\ndeleted file mode 100644\nindex 639b6e50d..000000000\n--- a/datapath-windows/ovsext/Netlink/NetlinkBuf.c\n+++ /dev/null\n@@ -1,351 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-/* ==========================================================================\n- * This is a simple buffer mangement framework specific for netlink protocol.\n- * The name could be confused with ovsext/BufferMgmt.c. Ovsext/BufferMgmt.c\n- * deals with buffer mgmt for NBLs. Where as this framework deals with\n- * management of buffer that holds a netlink message.\n- *\n- * This framework provides APIs for putting/accessing data in a buffer. These\n- * APIs are used by driver's netlink protocol implementation.\n- *\n- * We can see this framework as a subset of ofpbuf in ovs userspace.\n- *\n- * This framework is NOT a generic buffer management framework (ofpbuf\n- * is a generic buffer mgmt framework) and provides only the functioanlities\n- * which would be useful for netlink protocol. Some of the key features are:\n- *\n- * a. It DOES NOT support automatic buffer reallocation.\n- * i. A netlink input/output message is a static buffer.\n- * b. The unused space is at the tail.\n- * c. There is no notion of headdroom.\n- * ==========================================================================\n- */\n-#include <ndis.h>\n-#include <netiodef.h>\n-#include <intsafe.h>\n-#include <ntintsafe.h>\n-#include <ntstrsafe.h>\n-\n-#ifdef OVS_DBG_MOD\n-#undef OVS_DBG_MOD\n-#endif\n-#define OVS_DBG_MOD OVS_DBG_NETLINK\n-#include \"Debug.h\"\n-#include \"NetlinkBuf.h\"\n-\n-/* Returns used space in the buffer */\n-#define NL_BUF_USED_SPACE(_buf) (_buf->bufLen - \\\n- _buf->bufRemLen)\n-\n-/* Validates that offset is within buffer boundaries and will not\n- * create holes in the buffer.*/\n-#define NL_BUF_IS_VALID_OFFSET(_buf, _offset) (_offset <= \\\n- NL_BUF_TAIL_OFFSET(_buf) ? 1 : 0)\n-\n-/* Validates if new data of size _size can be added at offset _offset.\n- * This macor assumes that offset validation has been done.*/\n-#define NL_BUF_CAN_ADD(_buf, _size, _offset) (((_offset + _size <= \\\n- _buf->bufLen) && (_size \\\n- <= _buf->bufRemLen)) ? \\\n- 1 : 0)\n-\n-/* Returns the offset of tail wrt buffer head */\n-#define NL_BUF_TAIL_OFFSET(_buf) (_buf->tail - _buf->head)\n-\n-static __inline VOID\n-_NlBufCopyAtTailUnsafe(PNL_BUFFER nlBuf, PCHAR data, UINT32 len);\n-static __inline VOID\n-_NlBufCopyAtOffsetUnsafe(PNL_BUFFER nlBuf, PCHAR data,\n- UINT32 len, UINT32 offset);\n-\n-/*\n- * --------------------------------------------------------------------------\n- * NlBufInit --\n- *\n- * Initializes NL_BUF with buffer pointer and length.\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-NlBufInit(PNL_BUFFER nlBuf, PCHAR base, UINT32 size)\n-{\n- ASSERT(nlBuf);\n- nlBuf->head = nlBuf->tail = base;\n- nlBuf->bufLen = nlBuf->bufRemLen = size;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * NlBufDeInit --\n- *\n- * Resets the buffer variables to NULL.\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-NlBufDeInit(PNL_BUFFER nlBuf)\n-{\n- ASSERT(nlBuf);\n- nlBuf->head = nlBuf->tail = NULL;\n- nlBuf->bufLen = nlBuf->bufRemLen = 0;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * NlBufCopyAtTail --\n- *\n- * Copies the data to the tail end of the buffer.\n- * --------------------------------------------------------------------------\n- */\n-BOOLEAN\n-NlBufCopyAtTail(PNL_BUFFER nlBuf, PCHAR data, UINT32 len)\n-{\n- BOOLEAN ret = TRUE;\n-\n- ASSERT(nlBuf);\n-\n- /* Check if we have enough space */\n- if (!NL_BUF_CAN_ADD(nlBuf, len, NL_BUF_TAIL_OFFSET(nlBuf))) {\n- ret = FALSE;\n- goto done;\n- }\n-\n- _NlBufCopyAtTailUnsafe(nlBuf, data, len);\n-\n-done:\n- return ret;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * NlBufCopyAtHead --\n- *\n- * Copies the data to the head of the buffer.\n- * It can be seen as special case of NlBufCopyAtOffset with input\n- * offset zero.\n- * --------------------------------------------------------------------------\n- */\n-BOOLEAN\n-NlBufCopyAtHead(PNL_BUFFER nlBuf, PCHAR data, UINT32 len)\n-{\n- BOOLEAN ret = TRUE;\n-\n- ASSERT(nlBuf);\n-\n- /* Check if we have enough space */\n- if (!NL_BUF_CAN_ADD(nlBuf, len, 0)) {\n- ret = FALSE;\n- goto done;\n- }\n-\n- if (nlBuf->head == nlBuf->tail) {\n- /* same as inserting in tail */\n- _NlBufCopyAtTailUnsafe(nlBuf, data, len);\n- goto done;\n- }\n-\n- _NlBufCopyAtOffsetUnsafe(nlBuf, data, len, 0);\n-\n-done:\n- return ret;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * NlBufCopyAtOffset --\n- *\n- * Inserts data at input offset in the buffer.\n- * If the offset is earlier then tail end then it first creates\n- * space of size input length at input offset by moving the existing\n- * data forward.\n- * --------------------------------------------------------------------------\n- */\n-BOOLEAN\n-NlBufCopyAtOffset(PNL_BUFFER nlBuf, PCHAR data, UINT32 len, UINT32 offset)\n-{\n- PCHAR dest = NULL;\n- BOOLEAN ret = TRUE;\n-\n- ASSERT(nlBuf);\n-\n- /* Check if input offset is valid and has enough space */\n- if ((!NL_BUF_IS_VALID_OFFSET(nlBuf, offset)) ||\n- (!NL_BUF_CAN_ADD(nlBuf, len, offset))) {\n- ret = FALSE;\n- goto done;\n- }\n-\n- dest = nlBuf->head + offset;\n-\n- if (dest == nlBuf->tail) {\n- /* same as inserting in tail */\n- _NlBufCopyAtTailUnsafe(nlBuf, data, len);\n- goto done;\n- }\n-\n- _NlBufCopyAtOffsetUnsafe(nlBuf, data, len, offset);\n-\n-done:\n- return ret;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * NlBufCopyAtTailUninit --\n- *\n- * Memsets the buffer portion of length len at tail end with zero.\n- * --------------------------------------------------------------------------\n- */\n-PCHAR\n-NlBufCopyAtTailUninit(PNL_BUFFER nlBuf, UINT32 len)\n-{\n- PCHAR ret;\n-\n- ret = nlBuf->tail;\n- if ((NlBufCopyAtTail(nlBuf, NULL, len)) == FALSE) {\n- ret = NULL;\n- }\n-\n- return ret;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * NlBufCopyAtHeadUninit --\n- *\n- * Memsets the buffer portion of length len at head with zero.\n- * --------------------------------------------------------------------------\n- */\n-PCHAR\n-NlBufCopyAtHeadUninit(PNL_BUFFER nlBuf, UINT32 len)\n-{\n- PCHAR ret = NULL;\n-\n- if ((NlBufCopyAtHead(nlBuf, NULL, len)) == FALSE) {\n- goto done;\n- }\n-\n- ret = nlBuf->head;\n-\n-done:\n- return ret;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * NlBufCopyAtOffsetUninit --\n- *\n- * Memsets the buffer portion of length len at head with zero.\n- *\n- * If the offset is earlier then tail end then it first creates\n- * space of size input length at input offset by moving the existing\n- * data forward.\n- * --------------------------------------------------------------------------\n- */\n-PCHAR\n-NlBufCopyAtOffsetUninit(PNL_BUFFER nlBuf, UINT32 len, UINT32 offset)\n-{\n- PCHAR ret = NULL;\n-\n- if ((NlBufCopyAtOffset(nlBuf, NULL, len, offset)) == FALSE) {\n- goto done;\n- }\n-\n- ret = nlBuf->head + offset;\n-\n-done:\n- return ret;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * NlBufAt --\n- *\n- * Returns pointer to buffer at input offset.\n- * bufLen is used to verify that expected data length\n- * is within valid boundaries. Here by boundaries we mean\n- * within head and tail.\n- * --------------------------------------------------------------------------\n- */\n-PCHAR\n-NlBufAt(PNL_BUFFER nlBuf, UINT32 offset, UINT32 bufLen)\n-{\n- PCHAR ret = NULL;\n-\n- ASSERT(nlBuf);\n-\n- if ((!NL_BUF_IS_VALID_OFFSET(nlBuf, offset))) {\n- goto done;\n- }\n-\n- /* Check if requested buffer is within head and tail */\n- if ((offset + bufLen) > NL_BUF_USED_SPACE(nlBuf)) {\n- goto done;\n- }\n-\n- ret = nlBuf->head + offset;\n-done:\n- return ret;\n-}\n-\n-/* *_Unsafe functions does not do any validation. */\n-\n-/*\n- * --------------------------------------------------------------------------\n- * _NlBufCopyAtTailUnsafe --\n- *\n- * Helper function for NlBufCopyAtTail.\n- * --------------------------------------------------------------------------\n- */\n-static __inline VOID\n-_NlBufCopyAtTailUnsafe(PNL_BUFFER nlBuf, PCHAR data, UINT32 len)\n-{\n- if (data) {\n- RtlCopyMemory(nlBuf->tail, data, len);\n- } else {\n- RtlZeroMemory(nlBuf->tail, len);\n- }\n-\n- nlBuf->tail += len;\n- nlBuf->bufRemLen -= len;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * _NlBufCopyAtOffsetUnsafe --\n- *\n- * Helper function for NlBufCopyAtOffset.\n- * --------------------------------------------------------------------------\n- */\n-static __inline VOID\n-_NlBufCopyAtOffsetUnsafe(PNL_BUFFER nlBuf, PCHAR data,\n- UINT32 len, UINT32 offset)\n-{\n- PCHAR dest = NULL;\n-\n- dest = nlBuf->head + offset;\n-\n- RtlMoveMemory(dest+len, dest, NL_BUF_USED_SPACE(nlBuf) - offset);\n-\n- if (data) {\n- RtlCopyMemory(dest, data, len);\n- } else {\n- RtlZeroMemory(dest, len);\n- }\n-\n- nlBuf->tail += len;\n- nlBuf->bufRemLen -= len;\n-}\ndiff --git a/datapath-windows/ovsext/Netlink/NetlinkBuf.h b/datapath-windows/ovsext/Netlink/NetlinkBuf.h\ndeleted file mode 100644\nindex c52b9cc26..000000000\n--- a/datapath-windows/ovsext/Netlink/NetlinkBuf.h\n+++ /dev/null\n@@ -1,69 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#ifndef __NETLINK_BUF_H_\n-#define __NETLINK_BUF_H_ 1\n-\n-typedef struct _NL_BUF {\n- PCHAR head; /* start address of the buffer */\n- PCHAR tail; /* first empty byte of the buffer */\n- UINT32 bufLen; /* original length of buffer */\n- UINT32 bufRemLen; /* remaining length of buffer */\n-} NL_BUFFER, *PNL_BUFFER;\n-\n-VOID NlBufInit(PNL_BUFFER nlBuf, PCHAR base, UINT32 size);\n-VOID NlBufDeInit(PNL_BUFFER nlBuf);\n-\n-BOOLEAN NlBufCopyAtTail(PNL_BUFFER nlBuf, PCHAR data, UINT32 len);\n-BOOLEAN NlBufCopyAtHead(PNL_BUFFER nlBuf, PCHAR data, UINT32 len);\n-BOOLEAN NlBufCopyAtOffset(PNL_BUFFER nlBuf, PCHAR data,\n- UINT32 len, UINT32 offset);\n-\n-PCHAR NlBufCopyAtTailUninit(PNL_BUFFER nlBuf, UINT32 len);\n-PCHAR NlBufCopyAtHeadUninit(PNL_BUFFER nlBuf, UINT32 len);\n-PCHAR NlBufCopyAtOffsetUninit(PNL_BUFFER nlBuf, UINT32 len, UINT32 offset);\n-\n-PCHAR NlBufAt(PNL_BUFFER nlBuf, UINT32 offset, UINT32 len);\n-\n-/*\n- * --------------------------------------------------------------------------\n- * NlBufSize --\n- *\n- * Returns the used size of buffer.\n- * --------------------------------------------------------------------------\n- */\n-static __inline UINT32\n-NlBufSize(PNL_BUFFER nlBuf)\n-{\n- ASSERT(nlBuf);\n- return (nlBuf->bufLen - nlBuf->bufRemLen);\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * NlBufRemLen --\n- *\n- * Returns the unused size of buffer.\n- * --------------------------------------------------------------------------\n- */\n-static __inline UINT32\n-NlBufRemLen(PNL_BUFFER nlBuf)\n-{\n- ASSERT(nlBuf);\n- return (nlBuf->bufRemLen);\n-}\n-\n-#endif /* __NETLINK_BUF_H_ */\ndiff --git a/datapath-windows/ovsext/Netlink/NetlinkError.h b/datapath-windows/ovsext/Netlink/NetlinkError.h\ndeleted file mode 100644\nindex 36115c802..000000000\n--- a/datapath-windows/ovsext/Netlink/NetlinkError.h\n+++ /dev/null\n@@ -1,241 +0,0 @@\n-/*\n-* Copyright 2014 Cloudbase Solutions Srl\n-*\n-* Licensed under the Apache License, Version 2.0 (the \"License\");\n-* you may not use this file except in compliance with the License.\n-* You may obtain a copy of the License at\n-*\n-* http://www.apache.org/licenses/LICENSE-2.0\n-*\n-* Unless required by applicable law or agreed to in writing, software\n-* distributed under the License is distributed on an \"AS IS\" BASIS,\n-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n-* See the License for the specific language governing permissions and\n-* limitations under the License.\n-*/\n-\n-#pragma once\n-\n-#include \"precomp.h\"\n-\n-/*\n- * These are error codes to be used by netlink transactional operations.\n- * The error code is assigned to the \"error\" field (INT) of the NL_MSG_ERR\n- * struct.\n-*/\n-\n-typedef enum _NL_ERROR_\n-{\n- NL_ERROR_SUCCESS = 0,\n- /* The operation is not permitted */\n- NL_ERROR_PERM = ((ULONG)-1),\n- /* There is no such file or directory */\n- NL_ERROR_NOENT = ((ULONG)-2),\n- /* There is no such process */\n- NL_ERROR_SRCH = ((ULONG)-3),\n- /* An interrupted system call / interrupted function */\n- NL_ERROR_INTR = ((ULONG)-4),\n- /* An I/O error */\n- NL_ERROR_IO = ((ULONG)-5),\n- /* There is no such device or address */\n- NL_ERROR_NXIO = ((ULONG)-6),\n- /* The argument list is too long */\n- NL_ERROR_2BIG = ((ULONG)-7),\n- /* Executable file format error */\n- NL_ERROR_NOEXEC = ((ULONG)-8),\n- /* A bad file descriptor / number */\n- NL_ERROR_BADF = ((ULONG)-9),\n- /* Have no child processes */\n- NL_ERROR_CHILD = ((ULONG)-10),\n- /* resource unavailable => try again later */\n- NL_ERROR_AGAIN = ((ULONG)-11),\n- /* We're out of memory */\n- NL_ERROR_NOMEM = ((ULONG)-12),\n- /* Permission is denied */\n- NL_ERROR_ACCES = ((ULONG)-13),\n- /* A bad address */\n- NL_ERROR_FAULT = ((ULONG)-14),\n-\n- /* The device or the resource is busy */\n- NL_ERROR_BUSY = ((ULONG)-16),\n- /* The file exists */\n- NL_ERROR_EXIST = ((ULONG)-17),\n- /* A cross-device link */\n- NL_ERROR_XDEV = ((ULONG)-18),\n- /* There is no such device */\n- NL_ERROR_NODEV = ((ULONG)-19),\n- /* It is not a directory, nor a symbolic link to a directory. */\n- NL_ERROR_NOTDIR = ((ULONG)-20),\n- /* This is a directory */\n- NL_ERROR_ISDIR = ((ULONG)-21),\n- /* An invalid argument */\n- NL_ERROR_INVAL = ((ULONG)-22),\n- /*\n- * There are too many files open in system (i.e. no room for another file\n- * descriptor)\n- */\n- NL_ERROR_NFILE = ((ULONG)-23),\n- /* The file descriptor value is too large. */\n- NL_ERROR_MFILE = ((ULONG)-24),\n- /* And Inappropriate I/O control operation. Or, this is not a typewriter */\n- NL_ERROR_NOTTY = ((ULONG)-25),\n-\n- /* The file is too large */\n- NL_ERROR_FBIG = ((ULONG)-27),\n- /* There is no space left on the device */\n- NL_ERROR_NOSPC = ((ULONG)-28),\n- /* This is an invalid seek */\n- NL_ERROR_SPIPE = ((ULONG)-29),\n- /* A read-only file system */\n- NL_ERROR_ROFS = ((ULONG)-30),\n- /* There are too many links */\n- NL_ERROR_MLINK = ((ULONG)-31),\n- /* A broken pipe */\n- NL_ERROR_PIPE = ((ULONG)-32),\n- /* The mathematics argument is out of the domain of the function. */\n- NL_ERROR_DOM = ((ULONG)-33),\n- /* The result is too large / cannot be represented */\n- NL_ERROR_RANGE = ((ULONG)-34),\n- /* A resource deadlock would occur */\n- NL_ERROR_DEADLK = ((ULONG)-36),\n-\n- /* The file name is too long */\n- NL_ERROR_NAMETOOLONG = ((ULONG)-38),\n- /* There are no locks available */\n- NL_ERROR_NOLCK = ((ULONG)-39),\n-\n- /* The function is not implemented / not supported */\n- NL_ERROR_NOSYS = ((ULONG)-40),\n- /* The directory is not empty */\n- NL_ERROR_NOTEMPTY = ((ULONG)-41),\n- /* The byte sequence is illegal */\n- NL_ERROR_ILSEQ = ((ULONG)-42),\n-\n- NL_ERROR_STRUNCATE = ((ULONG)-80),\n-\n- /* The address is already in use */\n- NL_ERROR_ADDRINUSE = ((ULONG)-100),\n- /* The requested address cannot be assigned: is is not available */\n- NL_ERROR_ADDRNOTAVAIL = ((ULONG)-101),\n- /* the address family is not supported by the protocol */\n- NL_ERROR_AFNOSUPPORT = ((ULONG)-102),\n- /* The operation / connection is already in progress */\n- NL_ERROR_ALREADY = ((ULONG)-103),\n- /* The message is bad */\n- NL_ERROR_BADMSG = ((ULONG)-104),\n- /* The operation was canceled */\n- NL_ERROR_CANCELED = ((ULONG)-105),\n- /* The software has caused a connection abort */\n- NL_ERROR_CONNABORTED = ((ULONG)-106),\n- /*The connection was refused */\n- NL_ERROR_CONNREFUSED = ((ULONG)-107),\n- /* The connection was reset by the peer */\n- NL_ERROR_CONNRESET = ((ULONG)-108),\n- /* The destination address is required */\n- NL_ERROR_DESTADDRREQ = ((ULONG)-109),\n- /*The host is unreachable */\n- NL_ERROR_HOSTUNREACH = ((ULONG)-110),\n- /* The identifier was removed */\n- NL_ERROR_IDRM = ((ULONG)-111),\n- /* The operations is in progress */\n- NL_ERROR_INPROGRESS = ((ULONG)-112),\n- /* The socket is already connected */\n- NL_ERROR_ISCONN = ((ULONG)-113),\n- /* There are too many levels of symbolic links. */\n- NL_ERROR_LOOP = ((ULONG)-114),\n- /*The message is too large */\n- NL_ERROR_MSGSIZE = ((ULONG)-115),\n- /* The network is down */\n- NL_ERROR_NETDOWN = ((ULONG)-116),\n- /* The network has dropped connection because of a reset (i.e. the\n- * connection was aborted by the network)\n- */\n- NL_ERROR_NETRESET = ((ULONG)-117),\n- /* The network is unreachable */\n- NL_ERROR_NETUNREACH = ((ULONG)-118),\n- /* There is no buffer space available */\n- NL_ERROR_NOBUFS = ((ULONG)-119),\n- /* There is no data available (on the stream head read queue) */\n- NL_ERROR_NODATA = ((ULONG)-120),\n- /* The link has been severed (it's reserved in posix) */\n- NL_ERROR_NOLINK = ((ULONG)-121),\n- /* There is no message of the desired type */\n- NL_ERROR_NOMSG = ((ULONG)-122),\n- /* The protocol is not available */\n- NL_ERROR_NOPROTOOPT = ((ULONG)-123),\n- /* We're out of streams resources */\n- NL_ERROR_NOSR = ((ULONG)-124),\n- /* This is not a stream */\n- NL_ERROR_NOSTR = ((ULONG)-125),\n- /* The socket is not connected */\n- NL_ERROR_NOTCONN = ((ULONG)-126),\n- /* The state is not recoverable */\n- NL_ERROR_NOTRECOVERABLE = ((ULONG)-127),\n- /* This is not a socket */\n- NL_ERROR_NOTSOCK = ((ULONG)-128),\n- /* The operation is not supported */\n- NL_ERROR_NOTSUPP = ((ULONG)-129),\n- /* The operation is not supported on socket */\n- NL_ERROR_OPNOTSUPP = ((ULONG)-130),\n-\n- NL_ERROR_OTHER = ((ULONG)-131),\n- /* The value is too large for the data type */\n- NL_ERROR_OVERFLOW = ((ULONG)-132),\n- /* The previous owner died */\n- NL_ERROR_OWNERDEAD = ((ULONG)-133),\n- /* A protocol error */\n- NL_ERROR_PROTO = ((ULONG)-134),\n- /* The protocol is not supported */\n- NL_ERROR_PROTONOSUPPORT = ((ULONG)-135),\n- /* This is a wrong protocol type for the socket */\n- NL_ERROR_PROTOTYPE = ((ULONG)-136),\n- /* The timer has expired (or, the stream ioctl has timed out) */\n- NL_ERROR_TIME = ((ULONG)-137),\n- /* The connection has timed out */\n- NL_ERROR_TIMEDOUT = ((ULONG)-138),\n- /* The given text file is busy */\n- NL_ERROR_TXTBSY = ((ULONG)-139),\n- /* The operation would block */\n- NL_ERROR_WOULDBLOCK = ((ULONG)-140),\n- /* The operation is not finished */\n- NL_ERROR_PENDING = ((ULONG)-141),\n-} NL_ERROR;\n-\n-static __inline\n-NlMapStatusToNlErr(NTSTATUS status)\n-{\n- NL_ERROR ret;\n-\n- switch (status)\n- {\n- case STATUS_NOT_SUPPORTED:\n- ret = NL_ERROR_NOTSUPP;\n- break;\n- case STATUS_INSUFFICIENT_RESOURCES:\n- ret = NL_ERROR_NOMEM;\n- break;\n- case STATUS_SUCCESS:\n- ret = NL_ERROR_SUCCESS;\n- break;\n- case STATUS_PENDING:\n- ret = NL_ERROR_PENDING;\n- break;\n- case STATUS_CANCELLED:\n- ret = NL_ERROR_CANCELED;\n- break;\n- case STATUS_INVALID_PARAMETER:\n- ret = NL_ERROR_INVAL;\n- break;\n- case STATUS_OBJECT_NAME_EXISTS:\n- ret = NL_ERROR_EXIST;\n- break;\n- case STATUS_INVALID_MESSAGE:\n- ret = NL_ERROR_BADMSG;\n- break;\n- default:\n- ret = NL_ERROR_OTHER;\n- break;\n- }\n-\n- return ret;\n-}\ndiff --git a/datapath-windows/ovsext/Netlink/NetlinkProto.h b/datapath-windows/ovsext/Netlink/NetlinkProto.h\ndeleted file mode 100644\nindex b32f6f7fb..000000000\n--- a/datapath-windows/ovsext/Netlink/NetlinkProto.h\n+++ /dev/null\n@@ -1,135 +0,0 @@\n-/*\n- * Copyright (c) 2008, 2010, 2011, 2014 Nicira, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#ifndef __NETLINK_PROTO_H_\n-#define __NETLINK_PROTO_H_ 1\n-\n-/* Netlink protocol definitions.\n- *\n- * Netlink is a message framing format described in RFC 3549 and used heavily\n- * in Linux to access the network stack. Open vSwitch uses AF_NETLINK sockets\n- * for this purpose on Linux. On Windows platform too, Open vSwitch uses\n- * netlink message format for userspace-kernelspace communication.\n- *\n- * This header provides access to the Netlink message framing definitions\n- * regardless of platform.\n- */\n-#include \"Types.h\"\n-\n-#define BUILD_ASSERT(EXPR) \\\n- typedef char AssertOnCompileFailed[(EXPR) ? 1: -1]\n-#define BUILD_ASSERT_DECL(EXPR) BUILD_ASSERT(EXPR)\n-\n-/* Returns X / Y, rounding up. X must be nonnegative to round correctly. */\n-#define DIV_ROUND_UP(X, Y) (((X) + ((Y) - 1)) / (Y))\n-\n-/* Returns X rounded up to the nearest multiple of Y. */\n-#define ROUND_UP(X, Y) (DIV_ROUND_UP(X, Y) * (Y))\n-\n-/* Returns the least number that, when added to X, yields a multiple of Y. */\n-#define PAD_SIZE(X, Y) (ROUND_UP(X, Y) - (X))\n-\n-/* Netlink message */\n-\n-/* nlmsg_flags bits. */\n-#define NLM_F_REQUEST 0x001\n-#define NLM_F_MULTI 0x002\n-#define NLM_F_ACK 0x004\n-#define NLM_F_ECHO 0x008\n-\n-/* GET request flag.*/\n-#define NLM_F_ROOT 0x100\n-#define NLM_F_MATCH 0x200\n-#define NLM_F_ATOMIC 0x400\n-#define NLM_F_DUMP (NLM_F_ROOT | NLM_F_MATCH)\n-\n-/* NEW request flags. */\n-#define NLM_F_REPLACE 0x100\n-#define NLM_F_EXCL 0x200\n-#define NLM_F_CREATE 0x400\n-\n-/* nlmsg_type values. */\n-#define NLMSG_NOOP 1\n-#define NLMSG_ERROR 2\n-#define NLMSG_DONE 3\n-#define NLMSG_OVERRUN 4\n-\n-#define NLMSG_MIN_TYPE 0x10\n-\n-#define MAX_LINKS 32\n-\n-#define NLMSG_ALIGNTO 4\n-#define NLMSG_ALIGN(SIZE) ROUND_UP(SIZE, NLMSG_ALIGNTO)\n-\n-#define NLA_ALIGNTO 4\n-#define NLA_ALIGN(SIZE) ROUND_UP(SIZE, NLA_ALIGNTO)\n-\n-typedef struct ovs_header OVS_HDR, *POVS_HDR;\n-\n-typedef struct _NL_MSG_HDR {\n- UINT32 nlmsgLen;\n- UINT16 nlmsgType;\n- UINT16 nlmsgFlags;\n- UINT32 nlmsgSeq;\n- UINT32 nlmsgPid;\n-} NL_MSG_HDR, *PNL_MSG_HDR;\n-BUILD_ASSERT_DECL(sizeof(NL_MSG_HDR) == 16);\n-\n-typedef struct _NlMsgErr\n-{\n- INT error;\n- NL_MSG_HDR nlMsg;\n-} NL_MSG_ERR, *PNL_MSG_ERR;\n-BUILD_ASSERT_DECL(sizeof(NL_MSG_ERR) == 20);\n-\n-typedef struct _GENL_MSG_HDR {\n- UINT8 cmd;\n- UINT8 version;\n- UINT16 reserved;\n-} GENL_MSG_HDR, *PGENL_MSG_HDR;\n-BUILD_ASSERT_DECL(sizeof(GENL_MSG_HDR) == 4);\n-\n-/* Netfilter Generic Message */\n-typedef struct _NF_GEN_MSG_HDR {\n- UINT8 nfgenFamily; /* AF_xxx */\n- UINT8 version; /* nfnetlink version */\n- UINT16 resId; /* resource id */\n-} NF_GEN_MSG_HDR, *PNF_GEN_MSG_HDR;\n-BUILD_ASSERT_DECL(sizeof(NF_GEN_MSG_HDR) == 4);\n-\n-/* Netlink attributes */\n-typedef struct _NL_ATTR {\n- UINT16 nlaLen;\n- UINT16 nlaType;\n-} NL_ATTR, *PNL_ATTR;\n-BUILD_ASSERT_DECL(sizeof(NL_ATTR) == 4);\n-\n-#ifndef NLA_TYPE_MASK\n-#define NLA_F_NESTED (1 << 15)\n-#define NLA_F_NET_BYTEORDER (1 << 14)\n-#define NLA_TYPE_MASK ~(NLA_F_NESTED | NLA_F_NET_BYTEORDER)\n-#endif\n-\n-#define NLMSG_HDRLEN ((INT) NLMSG_ALIGN(sizeof(NL_MSG_HDR)))\n-#define GENL_HDRLEN NLMSG_ALIGN(sizeof(GENL_MSG_HDR))\n-#define NF_GEN_MSG_HDRLEN NLMSG_ALIGN(sizeof(NF_GEN_MSG_HDR))\n-#define OVS_HDRLEN NLMSG_ALIGN(sizeof(OVS_HDR))\n-#define NLA_HDRLEN ((UINT16) NLA_ALIGN(sizeof(NL_ATTR)))\n-\n-#define NETLINK_NETFILTER 12\n-#define NETLINK_GENERIC 16\n-\n-#endif /* NetlinProto.h */\ndiff --git a/datapath-windows/ovsext/Offload.c b/datapath-windows/ovsext/Offload.c\ndeleted file mode 100644\nindex 1fd7ebaa6..000000000\n--- a/datapath-windows/ovsext/Offload.c\n+++ /dev/null\n@@ -1,780 +0,0 @@\n-/*\n- * Copyright (c) 2014, 2016 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#include \"precomp.h\"\n-#include \"Debug.h\"\n-#include \"Flow.h\"\n-#include \"Offload.h\"\n-#include \"PacketParser.h\"\n-\n-#ifdef OVS_DBG_MOD\n-#undef OVS_DBG_MOD\n-#endif\n-#define OVS_DBG_MOD OVS_DBG_CHECKSUM\n-\n-#ifndef htons\n-#define htons(_x) (((UINT16)(_x) >> 8) + (((UINT16)(_x) << 8) & 0xff00))\n-#endif\n-\n-#ifndef swap64\n-#define swap64(_x) ((((UINT64)(_x) >> 8) & 0x00ff00ff00ff00ff) + \\\n- (((UINT64)(_x) << 8) & 0xff00ff00ff00ff00))\n-#endif\n-\n-#define fold64(_x) \\\n- _x = ((_x) >> 32) + ((_x) & 0xffffffff); \\\n- _x = (UINT32)(((_x) >> 32) + (_x)); \\\n- _x = ((_x) >> 16) + ((_x) & 0xffff); \\\n- _x = (UINT16)(((_x) >> 16) + (_x))\n-\n-#define fold32(_x) \\\n- _x = ((_x) >> 16) + ((_x) & 0xffff); \\\n- _x = (UINT16)(((_x) >> 16) + (_x))\n-\n-\n-/*\n- *----------------------------------------------------------------------------\n- * CalculateOnesComplement --\n- *\n- * Given the start address and buffer length, calculate the 1's complement\n- * This routine can be used when multiple buffers are used for a packets.\n- *\n- * PLEASE NOTE, even though the last parameter is UINT64, but the assumption\n- * is it will not overflowed after adding the extra data.\n- * ------------------------------------------------\n- *\n- * Result:\n- * As name indicate, the final data is not 1's complemnent\n- *----------------------------------------------------------------------------\n- */\n-UINT64\n-CalculateOnesComplement(UINT8 *start,\n- UINT16 totalLength,\n- UINT64 initial,\n- BOOLEAN isEvenStart)\n-{\n- UINT64 sum = 0, val64;\n- UINT64 *src = (UINT64 *)start;\n- while (totalLength > 7) {\n- val64 = *src;\n- sum += val64;\n- if (sum < val64) sum++;\n- src++;\n- totalLength -= 8;\n- }\n-\n- start = (UINT8 *)src;\n-\n- if (totalLength > 3) {\n- UINT32 val = *(UINT32 *)start;\n- sum += val;\n- if (sum < val) sum++;\n- start += 4;\n- totalLength -= 4;\n- }\n-\n- if (totalLength > 1) {\n- UINT16 val = *(UINT16 *)start;\n- sum += val;\n- if (sum < val) sum++;\n- start += 2;\n- totalLength -= 2;\n- }\n-\n- if (totalLength > 0) {\n- UINT8 val = *start;\n- sum += val;\n- if (sum < val) sum++;\n- start += 1;\n- totalLength -= 1;\n- }\n- ASSERT(totalLength == 0);\n-\n- if (!isEvenStart) {\n- sum = _byteswap_uint64(sum);\n- }\n-\n- sum += initial;\n- if (sum < initial) sum++;\n-\n- return sum;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * CalculateChecksum --\n- *\n- * Given the start point, and length, calculate the checksum\n- * as 1's complement of 1's comlement.\n- *\n- * This assume the checksum field is initailized properly.\n- *\n- * Input Parameter:\n- * ptr: point to the data to be checksumed\n- * totalLength: total length of the data\n- * initial: inital value to remit the checksum. Please note this\n- * value should be network byte order value.\n- *\n- * The last parameter may be useful where you don't want to set\n- * checksum field to zero, in that case you can pass ~checksum,\n- * this is equivalent of set checksum field to zero.\n- *\n- * Result:\n- * The result can be assigned to checksum field directly.\n- *----------------------------------------------------------------------------\n- */\n-UINT16\n-CalculateChecksum(UINT8 *ptr,\n- UINT16 totalLength,\n- UINT16 initial)\n-{\n- UINT64 sum = CalculateOnesComplement(ptr, totalLength, initial, TRUE);\n- fold64(sum);\n- return (UINT16)~sum;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * CopyAndCalculateOnesComplement --\n- *\n- * Given the start address and buffer length, calculate the 1's complement\n- * at same time, copt the data from src to dst.\n- *\n- * This routine can be used when multiple buffers are used for a packets.\n- *\n- * PLEASE NOTE, even though the last parameter is UINT64, but the assumption\n- * is it will not overflowed after adding the extra data.\n- * ------------------------------------------------\n- *\n- * Result:\n- * As name indicate, the final data is not 1's complemnent\n- *----------------------------------------------------------------------------\n- */\n-UINT64\n-CopyAndCalculateOnesComplement(UINT8 *dst,\n- UINT8 *src,\n- UINT16 length,\n- UINT64 initial,\n- BOOLEAN isEvenStart)\n-{\n- UINT64 sum =0, val;\n- UINT64 *src64, *dst64;\n- union {\n- UINT32 val;\n- UINT8 b8[4];\n- } tmp;\n-\n- src64 = (UINT64 *)src;\n- dst64 = (UINT64 *)dst;\n-\n- while (length > 7) {\n- val = *src64;\n- *dst64 = val;\n- sum += (val >> 32) + (val & 0xffffffff);\n- src64++;\n- dst64++;\n- length -= 8;\n- }\n-\n- if (length > 3) {\n- val = *(UINT32 *)src64;\n- *(UINT32 *)dst64 = (UINT32)val;\n- sum += (UINT32)val;\n- dst64 = (UINT64 *)((UINT8 *)dst64 + 4);\n- src64 = (UINT64 *)((UINT8 *)src64 + 4);\n- length -= 4;\n- }\n- src = (UINT8 *)src64;\n- dst = (UINT8 *)dst64;\n- tmp.val = 0;\n- switch (length) {\n- case 3:\n- dst[2] = src[2];\n- tmp.b8[2] = src[2];\n- case 2:\n- dst[1] = src[1];\n- tmp.b8[1] = src[1];\n- case 1:\n- dst[0] = src[0];\n- tmp.b8[0] = src[0];\n- sum += tmp.val;\n- }\n- sum = (isEvenStart ? sum : swap64(sum)) + initial;\n- return sum;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * CopyAndCalculateChecksum --\n- *\n- * This is similar to CalculateChecksum, except it will also copy data to\n- * destination address.\n- *----------------------------------------------------------------------------\n- */\n-UINT16\n-CopyAndCalculateChecksum(UINT8 *dst,\n- UINT8 *src,\n- UINT16 length,\n- UINT16 initial)\n-{\n-\n- UINT64 sum = CopyAndCalculateOnesComplement(dst, src, length, initial,\n- TRUE);\n- fold64(sum);\n- return (UINT16)~sum;\n-}\n-\n-\n-/*\n- *----------------------------------------------------------------------------\n- * IPChecksum --\n- *\n- * Give IP header, calculate the IP checksum.\n- * We assume IP checksum field is initialized properly\n- *\n- * Input Pramater:\n- * ipHdr: IP header start point\n- * length: IP header length (potentially include IP options)\n- * initial: same as CalculateChecksum\n- *\n- * Result:\n- * The result is already 1's complement, so can be assigned\n- * to checksum field directly\n- *----------------------------------------------------------------------------\n- */\n-UINT16\n-IPChecksum(UINT8 *ipHdr,\n- UINT16 length,\n- UINT16 initial)\n-{\n- UINT32 sum = initial;\n- UINT16 *ptr = (UINT16 *)ipHdr;\n- ASSERT((length & 0x3) == 0);\n- while (length > 1) {\n- sum += ptr[0];\n- ptr++;\n- length -= 2;\n- }\n- fold32(sum);\n- return (UINT16)~sum;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * IPPseudoChecksum --\n- *\n- * Give src and dst IP address, protocol value and total\n- * upper layer length(not include IP header, but include\n- * upller layer protocol header, for example it include\n- * TCP header for TCP checksum), calculate the pseudo\n- * checksum, please note this checksum is just 1's complement\n- * addition.\n- *\n- * Input Parameter:\n- * src: please note it is in network byte order\n- * dst: same as src\n- * protocol: protocol value in IP header\n- * totalLength: total length of upper layer data including\n- * header.\n- *\n- * Result:\n- *\n- * This value should be put in TCP checksum field before\n- * calculating TCP checksum using CalculateChecksum with\n- * initial value of 0.\n- *----------------------------------------------------------------------------\n- */\n-UINT16\n-IPPseudoChecksum(UINT32 *src,\n- UINT32 *dst,\n- UINT8 protocol,\n- UINT16 totalLength)\n-{\n- UINT32 sum = (UINT32)htons(totalLength) + htons(protocol);\n- sum += (*src >> 16) + (*src & 0xffff);\n- sum += (*dst >> 16) + (*dst & 0xffff);\n- fold32(sum);\n- return (UINT16)sum;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * IPv6PseudoChecksum --\n- *\n- * Given IPv6 src and dst address, upper layer protocol and total\n- * upper layer protocol data length including upper layer header\n- * part, calculate the pseudo checksum for upper layer protocol\n- * checksum.\n- *\n- * please note this checksum is just 1's complement addition.\n- *\n- * Input Parameter:\n- * src: src IPv6 address in network byte order\n- * dst: dst IPv6 address.\n- * protocol: upper layer protocol\n- * totalLength: total length of upper layer data. Please note this is\n- * in host byte order.\n- *\n- * Result:\n- *\n- * Place in upper layer checksum field before calculate upper layer\n- * checksum.\n- *----------------------------------------------------------------------------\n- */\n-UINT16\n-IPv6PseudoChecksum(UINT32 *src,\n- UINT32 *dst,\n- UINT8 protocol,\n- UINT16 totalLength)\n-{\n- UINT64 sum = (UINT32)htons(totalLength) + htons(protocol);\n- sum += (UINT64)src[0] + src[1] + src[2] + src[3];\n- sum += (UINT64)dst[0] + dst[1] + dst[2] + dst[3];\n- fold64(sum);\n- return (UINT16)sum;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * ChecksumUpdate32 --\n- *\n- * Given old checksum value (as it is in checksum field),\n- * prev value of the relevant field in network byte order\n- * new value of the relevant field in the network byte order\n- * calculate the new checksum.\n- * Please check relevant RFC for reference.\n- *\n- * Input Pramater:\n- * oldSum: old checksum value in checksum field\n- * prev: previous value of relevant 32 bit feld in network\n- * byte order.\n- * new: new value of the relevant 32 bit field in network\n- * byte order.\n- *\n- * Result:\n- * new checksum value to be placed in the checksum field.\n- *----------------------------------------------------------------------------\n- */\n-UINT16\n-ChecksumUpdate32(UINT16 oldSum,\n- UINT32 prev,\n- UINT32 newValue)\n-{\n- UINT32 sum = ~prev;\n- sum = (sum >> 16) + (sum & 0xffff);\n- sum += (newValue >> 16) + (newValue & 0xffff);\n- sum += (UINT16)~oldSum;\n- fold32(sum);\n- return (UINT16)~sum;\n-}\n-\n-\n-/*\n- *----------------------------------------------------------------------------\n- * ChecksumUpdate16 --\n- *\n- * Given old checksum value (as it is in checksum field),\n- * prev value of the relevant field in network byte order\n- * new value of the relevant field in the network byte order\n- * calculate the new checksum.\n- * Please check relevant RFC for reference.\n- *\n- * Input Pramater:\n- * oldSum: old checksum value in checksum field\n- * prev: previous value of relevant 32 bit feld in network\n- * byte order.\n- * new: new value of the relevant 32 bit field in network\n- * byte order.\n- *\n- * Result:\n- * new checksum value to be placed in the checksum field.\n- *----------------------------------------------------------------------------\n- */\n-UINT16\n-ChecksumUpdate16(UINT16 oldSum,\n- UINT16 prev,\n- UINT16 newValue)\n-{\n- UINT32 sum = (UINT16)~oldSum;\n- sum += (UINT32)((UINT16)~prev) + newValue;\n- fold32(sum);\n- return (UINT16)~sum;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * CalculateChecksumNB --\n- *\n- * Calculates checksum over a length of bytes contained in an NB.\n- *\n- * nb : NB which contains the packet bytes.\n- * csumDataLen : Length of bytes to be checksummed.\n- * offset : offset to the first bytes of the data stream to be\n- * checksumed.\n- *\n- * Result:\n- * return 0, if there is a failure.\n- *----------------------------------------------------------------------------\n- */\n-UINT16\n-CalculateChecksumNB(const PNET_BUFFER nb,\n- UINT16 csumDataLen,\n- UINT32 offset)\n-{\n- ULONG mdlLen;\n- UINT16 csLen;\n- PUCHAR src;\n- UINT64 csum = 0;\n- PMDL currentMdl;\n- ULONG firstMdlLen;\n- /* Running count of bytes in remainder of the MDLs including current. */\n- ULONG packetLen;\n- BOOLEAN swapEnd = 1 & csumDataLen;\n-\n- if ((nb == NULL) || (csumDataLen == 0)\n- || (offset >= NET_BUFFER_DATA_LENGTH(nb))\n- || (offset + csumDataLen > NET_BUFFER_DATA_LENGTH(nb))) {\n- OVS_LOG_ERROR(\"Invalid parameters - csum length %u, offset %u,\"\n- \"pkt%s len %u\", csumDataLen, offset, nb? \"\":\"(null)\",\n- nb? NET_BUFFER_DATA_LENGTH(nb) : 0);\n- return 0;\n- }\n-\n- currentMdl = NET_BUFFER_CURRENT_MDL(nb);\n- packetLen = NET_BUFFER_DATA_LENGTH(nb);\n- firstMdlLen =\n- MmGetMdlByteCount(currentMdl) - NET_BUFFER_CURRENT_MDL_OFFSET(nb);\n-\n- firstMdlLen = MIN(firstMdlLen, packetLen);\n- if (offset < firstMdlLen) {\n- src = (PUCHAR)OvsGetMdlWithLowPriority(currentMdl);\n- if (!src) {\n- return 0;\n- }\n- src += (NET_BUFFER_CURRENT_MDL_OFFSET(nb) + offset);\n- mdlLen = firstMdlLen - offset;\n- packetLen -= firstMdlLen;\n- ASSERT((INT)packetLen >= 0);\n- } else {\n- offset -= firstMdlLen;\n- packetLen -= firstMdlLen;\n- ASSERT((INT)packetLen >= 0);\n- currentMdl = NDIS_MDL_LINKAGE(currentMdl);\n- mdlLen = MmGetMdlByteCount(currentMdl);\n- mdlLen = MIN(mdlLen, packetLen);\n-\n- while (offset >= mdlLen) {\n- offset -= mdlLen;\n- packetLen -= mdlLen;\n- ASSERT((INT)packetLen >= 0);\n- currentMdl = NDIS_MDL_LINKAGE(currentMdl);\n- mdlLen = MmGetMdlByteCount(currentMdl);\n- mdlLen = MIN(mdlLen, packetLen);\n- }\n-\n- src = (PUCHAR)OvsGetMdlWithLowPriority(currentMdl);\n- if (!src) {\n- return 0;\n- }\n-\n- src += offset;\n- mdlLen -= offset;\n- }\n-\n- while (csumDataLen && (currentMdl != NULL)) {\n- ASSERT(mdlLen < 65536);\n- csLen = MIN((UINT16) mdlLen, csumDataLen);\n-\n- csum = CalculateOnesComplement(src, csLen, csum, !(1 & csumDataLen));\n- fold64(csum);\n-\n- csumDataLen -= csLen;\n- currentMdl = NDIS_MDL_LINKAGE(currentMdl);\n- if (csumDataLen && currentMdl) {\n- src = OvsGetMdlWithLowPriority(currentMdl);\n- if (!src) {\n- return 0;\n- }\n-\n- mdlLen = MmGetMdlByteCount(currentMdl);\n- mdlLen = MIN(mdlLen, packetLen);\n- /* packetLen does not include the current MDL from here on. */\n- packetLen -= mdlLen;\n- ASSERT((INT)packetLen >= 0);\n- }\n- }\n-\n- fold64(csum);\n- ASSERT(csumDataLen == 0);\n- ASSERT((csum & ~0xffff) == 0);\n- csum = (UINT16)~csum;\n- if (swapEnd) {\n- return _byteswap_ushort((UINT16)csum);\n- }\n- return (UINT16)csum;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsValidateIPChecksum\n- * --------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsValidateIPChecksum(PNET_BUFFER_LIST curNbl,\n- POVS_PACKET_HDR_INFO hdrInfo)\n-{\n- NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo;\n- uint16_t checksum, hdrChecksum;\n- struct IPHdr ip_storage;\n- const IPHdr *ipHdr;\n-\n- if (!hdrInfo->isIPv4) {\n- /*need check add v6 check logic*/\n- return NDIS_STATUS_SUCCESS;\n- }\n-\n- /* First check if NIC has indicated checksum failure. */\n- csumInfo.Value = NET_BUFFER_LIST_INFO(curNbl,\n- TcpIpChecksumNetBufferListInfo);\n- if (csumInfo.Receive.IpChecksumFailed) {\n- return NDIS_STATUS_FAILURE;\n- }\n-\n- /* Next, check if the NIC did not validate the RX checksum. */\n- if (!csumInfo.Receive.IpChecksumSucceeded) {\n- ipHdr = OvsGetIp(curNbl, hdrInfo->l3Offset, &ip_storage);\n- if (ipHdr) {\n- ip_storage = *ipHdr;\n- hdrChecksum = ipHdr->check;\n- ip_storage.check = 0;\n- checksum = IPChecksum((uint8 *)&ip_storage, ipHdr->ihl * 4, 0);\n- if (checksum != hdrChecksum) {\n- return NDIS_STATUS_FAILURE;\n- }\n- } else {\n- /* Invalid network header */\n- return NDIS_STATUS_FAILURE;\n- }\n- }\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsValidateUDPChecksum\n- *----------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsValidateUDPChecksum(PNET_BUFFER_LIST curNbl, BOOLEAN udpCsumZero)\n-{\n- NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo;\n-\n- csumInfo.Value = NET_BUFFER_LIST_INFO(curNbl,\n- TcpIpChecksumNetBufferListInfo);\n-\n- if (udpCsumZero) {\n- /* Zero is valid checksum. */\n- csumInfo.Receive.UdpChecksumFailed = 0;\n- NET_BUFFER_LIST_INFO(curNbl, TcpIpChecksumNetBufferListInfo) =\n- csumInfo.Value;\n- return NDIS_STATUS_SUCCESS;\n- }\n-\n- /* First check if NIC has indicated UDP checksum failure. */\n- if (csumInfo.Receive.UdpChecksumFailed) {\n- return NDIS_STATUS_INVALID_PACKET;\n- }\n-\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsCalculateUDPChecksum\n- * Calculate UDP checksum\n- *----------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsCalculateUDPChecksum(PNET_BUFFER_LIST curNbl,\n- PNET_BUFFER curNb,\n- EthHdr *ethHdr,\n- UDPHdr *udpHdr,\n- UINT32 packetLength,\n- POVS_PACKET_HDR_INFO layers)\n-{\n- NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo;\n- UINT16 checkSum;\n-\n- csumInfo.Value = NET_BUFFER_LIST_INFO(curNbl, TcpIpChecksumNetBufferListInfo);\n-\n- /* Next check if UDP checksum has been calculated. */\n- if (!csumInfo.Receive.UdpChecksumSucceeded) {\n- UINT32 l4Payload = packetLength - layers->l4Offset;\n-\n- checkSum = udpHdr->check;\n-\n- switch (ethHdr->Type) {\n- case ETH_TYPE_IPV4_NBO: {\n- IPHdr *ipHdr = (IPHdr *)((PCHAR)ethHdr + layers->l3Offset);\n-\n- udpHdr->check = 0;\n- udpHdr->check =\n- IPPseudoChecksum((UINT32 *)&ipHdr->saddr,\n- (UINT32 *)&ipHdr->daddr,\n- IPPROTO_UDP, (UINT16)l4Payload);\n- udpHdr->check =\n- CalculateChecksumNB(curNb, (UINT16)l4Payload,\n- layers->l4Offset);\n- break;\n- }\n- case ETH_TYPE_IPV6_NBO: {\n- IPv6Hdr *ipv6Hdr = (IPv6Hdr *)((PCHAR)ethHdr + layers->l3Offset);\n-\n- udpHdr->check = 0;\n- udpHdr->check =\n- IPv6PseudoChecksum((UINT32 *)&ipv6Hdr->saddr,\n- (UINT32 *)&ipv6Hdr->daddr,\n- IPPROTO_UDP, (UINT16)l4Payload);\n- udpHdr->check =\n- CalculateChecksumNB(curNb, (UINT16)l4Payload,\n- layers->l4Offset);\n- break;\n- }\n- default:\n- OVS_LOG_ERROR(\"Invalid eth type: %d\\n\", ethHdr->Type);\n- ASSERT(!\"Invalid eth type\");\n- }\n-\n- if (checkSum != udpHdr->check) {\n- OVS_LOG_ERROR(\"UDP checksum incorrect, expected %u, got %u\",\n- udpHdr->check, checkSum);\n- return NDIS_STATUS_INVALID_PACKET;\n- }\n- }\n-\n- csumInfo.Receive.UdpChecksumSucceeded = 1;\n- NET_BUFFER_LIST_INFO(curNbl, TcpIpChecksumNetBufferListInfo) = csumInfo.Value;\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-/*\n- * OvsApplySWChecksumOnNB --\n- *\n- * This function calculates and sets the required software offloads given by\n- * csumInfo for a given NBL(nbl). If the given net buffer list 'nbl'\n- * has multiple net buffers, we assume that they are part of the same\n- * connection with the same offsets defined in 'layers'.\n- *\n- */\n-NDIS_STATUS\n-OvsApplySWChecksumOnNB(POVS_PACKET_HDR_INFO layers,\n- PNET_BUFFER_LIST nbl,\n- PNDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo)\n-{\n- PNET_BUFFER curNb;\n- PMDL curMdl;\n- PUINT8 bufferStart;\n- UINT32 packetLength = 0;\n- ASSERT(nbl != NULL);\n-\n- for (curNb = NET_BUFFER_LIST_FIRST_NB(nbl); curNb != NULL;\n- curNb = curNb->Next) {\n- packetLength = NET_BUFFER_DATA_LENGTH(curNb);\n- curMdl = NET_BUFFER_CURRENT_MDL(curNb);\n- bufferStart = (PUINT8)OvsGetMdlWithLowPriority(curMdl);\n- if (!bufferStart) {\n- return NDIS_STATUS_RESOURCES;\n- }\n-\n- bufferStart += NET_BUFFER_CURRENT_MDL_OFFSET(curNb);\n-\n- if (layers->isIPv4) {\n- IPHdr *ip = (IPHdr *)(bufferStart + layers->l3Offset);\n-\n- if (csumInfo->Transmit.IpHeaderChecksum) {\n- ip->check = 0;\n- ip->check = IPChecksum((UINT8 *)ip, 4 * ip->ihl, 0);\n- }\n-\n- if (layers->isTcp && csumInfo->Transmit.TcpChecksum) {\n- UINT16 csumLength = (UINT16)(packetLength - layers->l4Offset);\n- TCPHdr *tcp = (TCPHdr *)(bufferStart + layers->l4Offset);\n- tcp->check = IPPseudoChecksum(&ip->saddr, &ip->daddr,\n- IPPROTO_TCP, csumLength);\n- tcp->check = CalculateChecksumNB(curNb, csumLength,\n- (UINT32)(layers->l4Offset));\n- } else if (layers->isUdp && csumInfo->Transmit.UdpChecksum) {\n- UINT16 csumLength = (UINT16)(packetLength - layers->l4Offset);\n- UDPHdr *udp = (UDPHdr *)((PCHAR)ip + sizeof *ip);\n- udp->check = IPPseudoChecksum(&ip->saddr, &ip->daddr,\n- IPPROTO_UDP, csumLength);\n- udp->check = CalculateChecksumNB(curNb, csumLength,\n- (UINT32)(layers->l4Offset));\n- }\n- } else if (layers->isIPv6) {\n- IPv6Hdr *ip = (IPv6Hdr *)(bufferStart + layers->l3Offset);\n-\n- if (layers->isTcp && csumInfo->Transmit.TcpChecksum) {\n- UINT16 csumLength = (UINT16)(packetLength - layers->l4Offset);\n- TCPHdr *tcp = (TCPHdr *)(bufferStart + layers->l4Offset);\n- tcp->check = IPv6PseudoChecksum((UINT32 *) &ip->saddr,\n- (UINT32 *) &ip->daddr,\n- IPPROTO_TCP, csumLength);\n- tcp->check = CalculateChecksumNB(curNb, csumLength,\n- (UINT32)(layers->l4Offset));\n- } else if (layers->isUdp && csumInfo->Transmit.UdpChecksum) {\n- UINT16 csumLength = (UINT16)(packetLength - layers->l4Offset);\n- UDPHdr *udp = (UDPHdr *)((PCHAR)ip + sizeof *ip);\n- udp->check = IPv6PseudoChecksum((UINT32 *) &ip->saddr,\n- (UINT32 *) &ip->daddr,\n- IPPROTO_UDP, csumLength);\n- udp->check = CalculateChecksumNB(curNb, csumLength,\n- (UINT32)(layers->l4Offset));\n- }\n- }\n- }\n-\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-/*\n- * OVSGetTcpMSS --\n- *\n- * This function returns the maximum segment size of the given NBL. It takes\n- * into consideration both LSO v1 and v2.\n- */\n-ULONG\n-OVSGetTcpMSS(PNET_BUFFER_LIST nbl)\n-{\n- NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO lsoInfo;\n- ASSERT(nbl != NULL);\n-\n- lsoInfo.Value = NET_BUFFER_LIST_INFO(nbl,\n- TcpLargeSendNetBufferListInfo);\n- switch (lsoInfo.Transmit.Type) {\n- case NDIS_TCP_LARGE_SEND_OFFLOAD_V1_TYPE:\n- return lsoInfo.LsoV1Transmit.MSS;\n- break;\n- case NDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE:\n- return lsoInfo.LsoV2Transmit.MSS;\n- break;\n- default:\n- OVS_LOG_ERROR(\"Unknown LSO transmit type:%d\",\n- lsoInfo.Transmit.Type);\n- return 0;\n- }\n-}\ndiff --git a/datapath-windows/ovsext/Offload.h b/datapath-windows/ovsext/Offload.h\ndeleted file mode 100644\nindex c389e255a..000000000\n--- a/datapath-windows/ovsext/Offload.h\n+++ /dev/null\n@@ -1,53 +0,0 @@\n-/*\n- * Copyright (c) 2014, 2016 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#ifndef __OFFLOAD_H_\n-#define __OFFLOAD_H_ 1\n-\n-typedef union _OVS_PACKET_HDR_INFO *POVS_PACKET_HDR_INFO;\n-\n-UINT16 CalculateChecksum(UINT8 *ptr, UINT16 length, UINT16 initial);\n-UINT16 CopyAndCalculateChecksum(UINT8 *dst, UINT8 *src, UINT16 length,\n- UINT16 initial);\n-UINT16 IPChecksum(UINT8 *ipHdr, UINT16 length, UINT16 initial);\n-UINT16 IPPseudoChecksum(UINT32 *src, UINT32 *dst, UINT8 protocol,\n- UINT16 totalLength);\n-UINT16 IPv6PseudoChecksum(UINT32 *src, UINT32 *dst, UINT8 protocol,\n- UINT16 totalLength);\n-UINT16 ChecksumUpdate32(UINT16 oldSum, UINT32 prev, UINT32 newValue);\n-UINT16 ChecksumUpdate16(UINT16 oldSum, UINT16 prev, UINT16 newValue);\n-UINT16 CalculateChecksumNB(const PNET_BUFFER nb, UINT16 csumDataLen,\n- UINT32 offset);\n-NDIS_STATUS OvsValidateIPChecksum(PNET_BUFFER_LIST curNbl,\n- POVS_PACKET_HDR_INFO hdrInfo);\n-NDIS_STATUS OvsValidateUDPChecksum(PNET_BUFFER_LIST curNbl,\n- BOOLEAN udpCsumZero);\n-NDIS_STATUS\n-OvsCalculateUDPChecksum(PNET_BUFFER_LIST curNbl,\n- PNET_BUFFER curNb,\n- EthHdr *ethHdr,\n- UDPHdr *udpHdr,\n- UINT32 packetLength,\n- POVS_PACKET_HDR_INFO layers);\n-\n-ULONG OVSGetTcpMSS(PNET_BUFFER_LIST nbl);\n-\n-NDIS_STATUS OvsApplySWChecksumOnNB(POVS_PACKET_HDR_INFO layers,\n- PNET_BUFFER_LIST nbl,\n- PNDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO\n- csumInfo);\n-\n-#endif /* __OFFLOAD_H_ */\ndiff --git a/datapath-windows/ovsext/Oid.c b/datapath-windows/ovsext/Oid.c\ndeleted file mode 100644\nindex 7c7ffe750..000000000\n--- a/datapath-windows/ovsext/Oid.c\n+++ /dev/null\n@@ -1,882 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#include \"precomp.h\"\n-#include \"Switch.h\"\n-#include \"Vport.h\"\n-#include \"NetProto.h\"\n-#include \"User.h\"\n-#include \"Flow.h\"\n-#include \"Event.h\"\n-#include \"User.h\"\n-#include \"Oid.h\"\n-\n-/* Due to an imported header file */\n-#pragma warning( disable:4505 )\n-\n-#ifdef OVS_DBG_MOD\n-#undef OVS_DBG_MOD\n-#endif\n-#define OVS_DBG_MOD OVS_DBG_DISPATCH\n-#include \"Debug.h\"\n-\n-typedef struct _OVS_OID_CONTEXT {\n- NDIS_EVENT oidComplete;\n- NDIS_STATUS status;\n-} OVS_OID_CONTEXT, *POVS_OID_CONTEXT;\n-\n-\n-VOID\n-OvsExtOidRequestComplete(NDIS_HANDLE filterModuleContext,\n- PNDIS_OID_REQUEST oidRequest,\n- NDIS_STATUS status);\n-static VOID\n-OvsOidRequestCompleteMethod(POVS_SWITCH_CONTEXT switchObject,\n- PNDIS_OID_REQUEST oidRequest,\n- PNDIS_OID_REQUEST origOidRequest,\n- NDIS_STATUS status);\n-static VOID\n-OvsOidRequestCompleteSetInfo(POVS_SWITCH_CONTEXT switchObject,\n- PNDIS_OID_REQUEST oidRequest,\n- PNDIS_OID_REQUEST origOidRequest,\n- NDIS_STATUS status);\n-static VOID\n-OvsOidRequestCompleteQuery(POVS_SWITCH_CONTEXT switchObject,\n- PNDIS_OID_REQUEST oidRequest,\n- PNDIS_OID_REQUEST origOidRequest,\n- NDIS_STATUS status);\n-\n-static NDIS_STATUS\n-OvsProcessSetOidPortProp(POVS_SWITCH_CONTEXT switchObject,\n- PNDIS_OID_REQUEST oidRequest);\n-static NDIS_STATUS\n-OvsProcessSetOidPort(POVS_SWITCH_CONTEXT switchObject,\n- PNDIS_OID_REQUEST oidRequest);\n-static NDIS_STATUS\n-OvsProcessSetOidNic(POVS_SWITCH_CONTEXT switchObject,\n- PNDIS_OID_REQUEST oidRequest);\n-\n-__inline BOOLEAN\n-OvsCheckOidHeaderFunc(PNDIS_OBJECT_HEADER header,\n- LONG propRev,\n- LONG propSize)\n-{\n- return header->Type != NDIS_OBJECT_TYPE_DEFAULT ||\n- header->Revision < propRev ||\n- header->Size < propSize;\n-}\n-\n-#define OvsCheckOidHeader(_hdr, _rev) \\\n- OvsCheckOidHeaderFunc(_hdr, _rev, ##NDIS_SIZEOF_##_rev)\n-\n-static __inline VOID\n-OvsOidSetOrigRequest(PNDIS_OID_REQUEST clonedRequest,\n- PNDIS_OID_REQUEST origRequest)\n-{\n- *(PVOID*)(&clonedRequest->SourceReserved[0]) = origRequest;\n-}\n-\n-static __inline PNDIS_OID_REQUEST\n-OvsOidGetOrigRequest(PNDIS_OID_REQUEST clonedRequest)\n-{\n- return *((PVOID*)(&clonedRequest->SourceReserved[0]));\n-}\n-\n-static __inline VOID\n-OvsOidSetContext(PNDIS_OID_REQUEST clonedRequest,\n- POVS_OID_CONTEXT origRequest)\n-{\n- *(PVOID*)(&clonedRequest->SourceReserved[8]) = origRequest;\n-}\n-\n-static __inline POVS_OID_CONTEXT\n-OvsOidGetContext(PNDIS_OID_REQUEST clonedRequest)\n-{\n- return *((PVOID*)(&clonedRequest->SourceReserved[8]));\n-}\n-\n-static NDIS_STATUS\n-OvsProcessSetOidPortProp(POVS_SWITCH_CONTEXT switchObject,\n- PNDIS_OID_REQUEST oidRequest)\n-{\n- NDIS_STATUS status = NDIS_STATUS_SUCCESS;\n- struct _SET *setInfo = &(oidRequest->DATA.SET_INFORMATION);\n- PNDIS_SWITCH_PORT_PROPERTY_PARAMETERS portPropParam =\n- setInfo->InformationBuffer;\n- BOOLEAN checkFailed = TRUE;\n-\n- UNREFERENCED_PARAMETER(switchObject);\n-\n- if (setInfo->Oid == OID_SWITCH_PORT_PROPERTY_DELETE) {\n- checkFailed = OvsCheckOidHeader(\n- (PNDIS_OBJECT_HEADER)portPropParam,\n- NDIS_SWITCH_PORT_PROPERTY_DELETE_PARAMETERS_REVISION_1);\n- } else {\n- /* it must be a add or update request */\n- checkFailed = OvsCheckOidHeader(\n- (PNDIS_OBJECT_HEADER)portPropParam,\n- NDIS_SWITCH_PORT_PROPERTY_PARAMETERS_REVISION_1);\n- }\n-\n- if (checkFailed) {\n- status = NDIS_STATUS_INVALID_PARAMETER;\n- goto done;\n- }\n-\n- if (portPropParam->PropertyType == NdisSwitchPortPropertyTypeVlan) {\n- status = NDIS_STATUS_NOT_SUPPORTED;\n- goto done;\n- }\n-\n-done:\n- return status;\n-}\n-\n-static NDIS_STATUS\n-OvsProcessSetOidPort(POVS_SWITCH_CONTEXT switchObject,\n- PNDIS_OID_REQUEST oidRequest)\n-{\n- NDIS_STATUS status = NDIS_STATUS_SUCCESS;\n- struct _SET *setInfo = &(oidRequest->DATA.SET_INFORMATION);\n- PNDIS_SWITCH_PORT_PARAMETERS portParam = setInfo->InformationBuffer;\n-\n- if (OvsCheckOidHeader((PNDIS_OBJECT_HEADER)portParam,\n- NDIS_SWITCH_PORT_PARAMETERS_REVISION_1)) {\n- status = NDIS_STATUS_NOT_SUPPORTED;\n- goto done;\n- }\n-\n- if (portParam->IsValidationPort) {\n- /* Validation ports are used internally by the Hyper-V switch\n- * to validate and verify settings. We must skip handling them,\n- * and return STATUS_SUCCESS as the OID result\n- */\n- return NDIS_STATUS_SUCCESS;\n- }\n-\n- switch(setInfo->Oid) {\n- case OID_SWITCH_PORT_CREATE:\n- status = HvCreatePort(switchObject, portParam, 0);\n- break;\n- case OID_SWITCH_PORT_UPDATED:\n- status = HvUpdatePort(switchObject, portParam);\n- break;\n- case OID_SWITCH_PORT_TEARDOWN:\n- HvTeardownPort(switchObject, portParam);\n- break;\n- case OID_SWITCH_PORT_DELETE:\n- HvDeletePort(switchObject, portParam);\n- break;\n- default:\n- break;\n- }\n-\n-done:\n- return status;\n-}\n-\n-static NDIS_STATUS\n-OvsProcessSetOidNic(POVS_SWITCH_CONTEXT switchObject,\n- PNDIS_OID_REQUEST oidRequest)\n-{\n- NDIS_STATUS status = NDIS_STATUS_SUCCESS;\n- struct _SET *setInfo = &(oidRequest->DATA.SET_INFORMATION);\n- PNDIS_SWITCH_NIC_PARAMETERS nicParam = setInfo->InformationBuffer;\n-\n- if (OvsCheckOidHeader((PNDIS_OBJECT_HEADER)nicParam,\n- NDIS_SWITCH_NIC_PARAMETERS_REVISION_1)) {\n- status = NDIS_STATUS_NOT_SUPPORTED;\n- goto done;\n- }\n-\n- switch(setInfo->Oid) {\n- case OID_SWITCH_NIC_CREATE:\n- status = HvCreateNic(switchObject, nicParam);\n- break;\n- case OID_SWITCH_NIC_CONNECT:\n- HvConnectNic(switchObject, nicParam);\n- break;\n- case OID_SWITCH_NIC_UPDATED:\n- HvUpdateNic(switchObject, nicParam);\n- break;\n- case OID_SWITCH_NIC_DISCONNECT:\n- HvDisconnectNic(switchObject, nicParam);\n- break;\n- case OID_SWITCH_NIC_DELETE:\n- HvDeleteNic(switchObject, nicParam);\n- break;\n- default:\n- break;\n- }\n-\n-done:\n- return status;\n-\n-}\n-\n-static NDIS_STATUS\n-OvsProcessSetOid(POVS_SWITCH_CONTEXT switchObject,\n- PNDIS_OID_REQUEST oidRequest,\n- PBOOLEAN complete)\n-{\n- NDIS_STATUS status = NDIS_STATUS_SUCCESS;\n- struct _SET *setInfo = &(oidRequest->DATA.SET_INFORMATION);\n-\n- *complete = FALSE;\n-\n- OVS_LOG_TRACE(\"Enter: oidRequest %p, Oid: %lu\",\n- oidRequest, setInfo->Oid);\n-\n- /* Verify the basic Oid paramters first */\n- if (setInfo->InformationBufferLength &&\n- (setInfo->InformationBufferLength < sizeof(NDIS_OBJECT_HEADER))) {\n- status = NDIS_STATUS_INVALID_OID;\n- OVS_LOG_INFO(\"Invalid input %d\", setInfo->InformationBufferLength);\n- goto error;\n- }\n-\n- /* Documentation does not specify what should be done\n- * if informationBuffer is not present. Although it mentions the\n- * structure type informationBUffer points to for each oid request,\n- * but it does not explicitly mention that it is a MUST.\n- * hence we are following this scenario same way as what sample code\n- * mentions. */\n- if (!(setInfo->InformationBufferLength)) {\n- /* We cannot do anything about this oid request,\n- * lets just pass it down. */\n- OVS_LOG_INFO(\"Buffer Length Zero\");\n- goto done;\n- }\n-\n- switch(setInfo->Oid) {\n- case OID_SWITCH_PORT_PROPERTY_ADD:\n- case OID_SWITCH_PORT_PROPERTY_UPDATE:\n- case OID_SWITCH_PORT_PROPERTY_DELETE:\n- status = OvsProcessSetOidPortProp(switchObject, oidRequest);\n- break;\n-\n- case OID_SWITCH_PORT_CREATE:\n- case OID_SWITCH_PORT_UPDATED:\n- case OID_SWITCH_PORT_TEARDOWN:\n- case OID_SWITCH_PORT_DELETE:\n- status = OvsProcessSetOidPort(switchObject, oidRequest);\n- break;\n-\n- case OID_SWITCH_NIC_CREATE:\n- case OID_SWITCH_NIC_CONNECT:\n- case OID_SWITCH_NIC_UPDATED:\n- case OID_SWITCH_NIC_DISCONNECT:\n- case OID_SWITCH_NIC_DELETE:\n- status = OvsProcessSetOidNic(switchObject, oidRequest);\n- break;\n-\n- default:\n- /* Non handled OID request */\n- break;\n- }\n-\n- if (status != NDIS_STATUS_SUCCESS) {\n- goto error;\n- }\n-\n- goto done;\n-\n-error:\n- *complete = TRUE;\n-done:\n- OVS_LOG_TRACE(\"Exit: status %8x.\", status);\n- return status;\n-}\n-\n-static NDIS_STATUS\n-OvsProcessMethodOid(POVS_SWITCH_CONTEXT switchObject,\n- PNDIS_OID_REQUEST oidRequest,\n- PBOOLEAN complete,\n- PULONG bytesNeededParam)\n-{\n- NDIS_STATUS status = NDIS_STATUS_SUCCESS;\n- struct _METHOD *methodInfo = &(oidRequest->DATA.METHOD_INFORMATION);\n- struct _SET *nicReqSetInfo = NULL;\n- PNDIS_OBJECT_HEADER header = NULL;\n- PNDIS_OID_REQUEST nicOidRequest = NULL;\n-\n- UNREFERENCED_PARAMETER(switchObject);\n-\n- OVS_LOG_TRACE(\"Enter: oidRequest %p, Oid: %lu\",\n- oidRequest, methodInfo->Oid);\n-\n- *complete = FALSE;\n- *bytesNeededParam = 0;\n- header = methodInfo->InformationBuffer;\n-\n- switch(methodInfo->Oid) {\n- /* We deal with only OID_SWITCH_NIC_REQUEST as of now */\n- case OID_SWITCH_NIC_REQUEST:\n- if (OvsCheckOidHeader(header,\n- NDIS_SWITCH_NIC_OID_REQUEST_REVISION_1)) {\n- OVS_LOG_INFO(\"Check Header failed\");\n- status = NDIS_STATUS_NOT_SUPPORTED;\n- *complete = TRUE;\n- goto done;\n- }\n-\n- nicOidRequest = (((PNDIS_SWITCH_NIC_OID_REQUEST)header)->OidRequest);\n- nicReqSetInfo = &(nicOidRequest->DATA.SET_INFORMATION);\n-\n- /* Fail the SR-IOV VF case */\n- if ((nicOidRequest->RequestType == NdisRequestSetInformation) &&\n- (nicReqSetInfo->Oid == OID_NIC_SWITCH_ALLOCATE_VF)) {\n- OVS_LOG_INFO(\"We do not support Oid: \"\n- \"OID_NIC_SWITCH_ALLOCATE_VF\");\n- status = NDIS_STATUS_FAILURE;\n- *complete = TRUE;\n- }\n- break;\n- default:\n- /* No op */\n- break;\n- }\n-\n-done:\n- OVS_LOG_TRACE(\"Exit: status %8x.\", status);\n- return status;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Implements filter driver's FilterOidRequest function.\n- * --------------------------------------------------------------------------\n- */\n-\n-NDIS_STATUS\n-OvsExtOidRequest(NDIS_HANDLE filterModuleContext,\n- PNDIS_OID_REQUEST oidRequest)\n-{\n- POVS_SWITCH_CONTEXT switchObject = (POVS_SWITCH_CONTEXT)filterModuleContext;\n- NDIS_STATUS status;\n- PNDIS_OID_REQUEST clonedOidRequest = NULL;\n- struct _METHOD *methodInfo = &(oidRequest->DATA.METHOD_INFORMATION);\n- BOOLEAN completeOid = FALSE;\n- ULONG bytesNeeded = 0;\n-\n- OVS_LOG_TRACE(\"Enter: oidRequest %p, reqType: %d\",\n- oidRequest, oidRequest->RequestType);\n- status = NdisAllocateCloneOidRequest(switchObject->NdisFilterHandle,\n- oidRequest, OVS_MEMORY_TAG,\n- &clonedOidRequest);\n- if (status != NDIS_STATUS_SUCCESS) {\n- goto done;\n- }\n-\n- NdisInterlockedIncrement(&(switchObject->pendingOidCount));\n-\n- /* set the original oid request in cloned one. */\n- OvsOidSetOrigRequest(clonedOidRequest, oidRequest);\n- OvsOidSetContext(clonedOidRequest, NULL);\n-\n- switch(clonedOidRequest->RequestType) {\n- case NdisRequestSetInformation:\n- status = OvsProcessSetOid(switchObject, clonedOidRequest,\n- &completeOid);\n- break;\n- case NdisRequestMethod:\n- status = OvsProcessMethodOid(switchObject, clonedOidRequest,\n- &completeOid, &bytesNeeded);\n- break;\n- default:\n- /* We do not handle other request types as of now.\n- * We are just a passthrough for those. */\n- break;\n- }\n-\n- if (completeOid == TRUE) {\n- /* dont leave any reference back to original request,\n- * even if we are freeing it up. */\n- OVS_LOG_INFO(\"Complete True oidRequest %p.\", oidRequest);\n- OvsOidSetOrigRequest(clonedOidRequest, NULL);\n- NdisFreeCloneOidRequest(switchObject->NdisFilterHandle,\n- clonedOidRequest);\n- methodInfo->BytesNeeded = bytesNeeded;\n- NdisInterlockedDecrement(&switchObject->pendingOidCount);\n- goto done;\n- }\n-\n- /* pass the request down */\n- status = NdisFOidRequest(switchObject->NdisFilterHandle, clonedOidRequest);\n- if (status != NDIS_STATUS_PENDING) {\n- OvsExtOidRequestComplete(switchObject, clonedOidRequest, status);\n- /* sample code says so */\n- status = NDIS_STATUS_PENDING;\n- }\n-\n-done:\n- OVS_LOG_TRACE(\"Exit: status %8x.\", status);\n- return status;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Implements filter driver's FilterOidRequestComplete function.\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-OvsExtOidRequestComplete(NDIS_HANDLE filterModuleContext,\n- PNDIS_OID_REQUEST oidRequest,\n- NDIS_STATUS status)\n-{\n- POVS_SWITCH_CONTEXT switchObject = (POVS_SWITCH_CONTEXT)filterModuleContext;\n- PNDIS_OID_REQUEST origReq = OvsOidGetOrigRequest(oidRequest);\n- POVS_OID_CONTEXT oidContext = OvsOidGetContext(oidRequest);\n-\n- /* Only one of the two should be set */\n- ASSERT(origReq != NULL || oidContext != NULL);\n- ASSERT(oidContext != NULL || origReq != NULL);\n-\n- OVS_LOG_TRACE(\"Enter: oidRequest %p, reqType: %d\",\n- oidRequest, oidRequest->RequestType);\n-\n- if (origReq == NULL) {\n- NdisInterlockedDecrement(&(switchObject->pendingOidCount));\n- oidContext->status = status;\n- NdisSetEvent(&oidContext->oidComplete);\n- OVS_LOG_INFO(\"Internally generated request\");\n- goto done;\n- }\n-\n- switch(oidRequest->RequestType) {\n- case NdisRequestMethod:\n- OvsOidRequestCompleteMethod(switchObject, oidRequest,\n- origReq, status);\n- break;\n-\n- case NdisRequestSetInformation:\n- OvsOidRequestCompleteSetInfo(switchObject, oidRequest,\n- origReq, status);\n- break;\n-\n- case NdisRequestQueryInformation:\n- case NdisRequestQueryStatistics:\n- default:\n- OvsOidRequestCompleteQuery(switchObject, oidRequest,\n- origReq, status);\n- break;\n- }\n-\n- OvsOidSetOrigRequest(oidRequest, NULL);\n-\n- NdisFreeCloneOidRequest(switchObject->NdisFilterHandle, oidRequest);\n- NdisFOidRequestComplete(switchObject->NdisFilterHandle, origReq, status);\n- NdisInterlockedDecrement(&(switchObject->pendingOidCount));\n-\n-done:\n- OVS_LOG_TRACE(\"Exit\");\n-}\n-\n-static VOID\n-OvsOidRequestCompleteMethod(POVS_SWITCH_CONTEXT switchObject,\n- PNDIS_OID_REQUEST oidRequest,\n- PNDIS_OID_REQUEST origOidRequest,\n- NDIS_STATUS status)\n-{\n- UNREFERENCED_PARAMETER(status);\n- UNREFERENCED_PARAMETER(switchObject);\n-\n- struct _METHOD *methodInfo = &(oidRequest->DATA.METHOD_INFORMATION);\n- struct _METHOD *origMethodInfo = &(origOidRequest->DATA.\n- METHOD_INFORMATION);\n-\n- OVS_LOG_TRACE(\"Enter: oidRequest %p, Oid: %lu\",\n- oidRequest, methodInfo->Oid);\n-\n- origMethodInfo->OutputBufferLength = methodInfo->OutputBufferLength;\n- origMethodInfo->BytesRead = methodInfo->BytesRead;\n- origMethodInfo->BytesNeeded = methodInfo->BytesNeeded;\n- origMethodInfo->BytesWritten = methodInfo->BytesWritten;\n-\n- OVS_LOG_TRACE(\"Exit\");\n-}\n-\n-static VOID\n-OvsOidRequestCompleteSetInfo(POVS_SWITCH_CONTEXT switchObject,\n- PNDIS_OID_REQUEST oidRequest,\n- PNDIS_OID_REQUEST origOidRequest,\n- NDIS_STATUS status)\n-{\n- struct _SET *setInfo = &(oidRequest->DATA.SET_INFORMATION);\n- struct _SET *origSetInfo = &(origOidRequest->DATA.SET_INFORMATION);\n- PNDIS_OBJECT_HEADER origHeader = origSetInfo->InformationBuffer;\n-\n- OVS_LOG_TRACE(\"Enter: oidRequest %p, Oid: %lu\",\n- oidRequest, setInfo->Oid);\n-\n- origSetInfo->BytesRead = setInfo->BytesRead;\n- origSetInfo->BytesNeeded = setInfo->BytesNeeded;\n-\n- if (status != NDIS_STATUS_SUCCESS) {\n-\n- switch(setInfo->Oid) {\n- case OID_SWITCH_PORT_CREATE:\n- HvDeletePort(switchObject,\n- (PNDIS_SWITCH_PORT_PARAMETERS)origHeader);\n- break;\n-\n- case OID_SWITCH_NIC_CREATE:\n- HvDeleteNic(switchObject,\n- (PNDIS_SWITCH_NIC_PARAMETERS)origHeader);\n- break;\n-\n- default:\n- break;\n- }\n- }\n-\n- OVS_LOG_TRACE(\"Exit\");\n-}\n-\n-static VOID\n-OvsOidRequestCompleteQuery(POVS_SWITCH_CONTEXT switchObject,\n- PNDIS_OID_REQUEST oidRequest,\n- PNDIS_OID_REQUEST origOidRequest,\n- NDIS_STATUS status)\n-{\n- UNREFERENCED_PARAMETER(switchObject);\n- UNREFERENCED_PARAMETER(status);\n-\n- struct _QUERY *queryInfo = &((oidRequest->DATA).QUERY_INFORMATION);\n- struct _QUERY *origQueryInfo = &((origOidRequest->DATA).QUERY_INFORMATION);\n-\n- OVS_LOG_TRACE(\"Enter: oidRequest %p, Oid: %lu\",\n- oidRequest, queryInfo->Oid);\n-\n- origQueryInfo->BytesWritten = queryInfo->BytesWritten;\n- origQueryInfo->BytesNeeded = queryInfo->BytesNeeded;\n-\n- OVS_LOG_TRACE(\"Exit\");\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Implements filter driver's FilterCancelOidRequest function.\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-OvsExtCancelOidRequest(NDIS_HANDLE filterModuleContext,\n- PVOID requestId)\n-{\n- OVS_LOG_TRACE(\"Enter: requestId: %p\", requestId);\n-\n- UNREFERENCED_PARAMETER(filterModuleContext);\n- UNREFERENCED_PARAMETER(requestId);\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Utility function to issue the specified OID to the NDIS stack. The OID is\n- * directed towards the miniport edge of the extensible switch.\n- * An OID that gets issued may not complete immediately, and in such cases, the\n- * function waits for the OID to complete. Thus, this function must not be\n- * called at the PASSIVE_LEVEL.\n- * --------------------------------------------------------------------------\n- */\n-static NDIS_STATUS\n-OvsIssueOidRequest(POVS_SWITCH_CONTEXT switchContext,\n- NDIS_REQUEST_TYPE oidType,\n- UINT32 oidRequestEnum,\n- PVOID oidInputBuffer,\n- UINT32 inputSize,\n- PVOID oidOutputBuffer,\n- UINT32 outputSize,\n- UINT32 *outputSizeNeeded)\n-{\n- NDIS_STATUS status;\n- PNDIS_OID_REQUEST oidRequest;\n- POVS_OID_CONTEXT oidContext;\n- ULONG OvsExtOidRequestId = 'ISVO';\n-\n- DBG_UNREFERENCED_PARAMETER(inputSize);\n- DBG_UNREFERENCED_PARAMETER(oidInputBuffer);\n-\n- OVS_LOG_TRACE(\"Enter: switchContext: %p, oidType: %d\",\n- switchContext, oidType);\n-\n- ASSERT(oidInputBuffer == NULL || inputSize != 0);\n- ASSERT(oidOutputBuffer == NULL || outputSize != 0);\n- ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);\n-\n- oidRequest = OvsAllocateMemoryWithTag(sizeof *oidRequest,\n- OVS_OID_POOL_TAG);\n- if (!oidRequest) {\n- status = NDIS_STATUS_RESOURCES;\n- goto done;\n- }\n-\n- oidContext = OvsAllocateMemoryWithTag(sizeof *oidContext,\n- OVS_OID_POOL_TAG);\n- if (!oidContext) {\n- OvsFreeMemoryWithTag(oidRequest, OVS_OID_POOL_TAG);\n- status = NDIS_STATUS_RESOURCES;\n- goto done;\n- }\n-\n- RtlZeroMemory(oidRequest, sizeof *oidRequest);\n- RtlZeroMemory(oidContext, sizeof *oidContext);\n-\n- oidRequest->Header.Type = NDIS_OBJECT_TYPE_OID_REQUEST;\n- oidRequest->Header.Revision = NDIS_OID_REQUEST_REVISION_1;\n- oidRequest->Header.Size = NDIS_SIZEOF_OID_REQUEST_REVISION_1;\n-\n- oidRequest->RequestType = oidType;\n- oidRequest->PortNumber = 0;\n- oidRequest->Timeout = 0;\n- oidRequest->RequestId = (PVOID)OvsExtOidRequestId;\n-\n- switch(oidType) {\n- case NdisRequestQueryInformation:\n- oidRequest->DATA.QUERY_INFORMATION.Oid = oidRequestEnum;\n- oidRequest->DATA.QUERY_INFORMATION.InformationBuffer = oidOutputBuffer;\n- oidRequest->DATA.QUERY_INFORMATION.InformationBufferLength = outputSize;\n- break;\n- default:\n- ASSERT(FALSE);\n- status = NDIS_STATUS_INVALID_PARAMETER;\n- break;\n- }\n-\n- /*\n- * We make use of the SourceReserved field in the OID request to store\n- * pointers to the original OID (if any), and also context for completion\n- * (if any).\n- */\n- oidContext->status = NDIS_STATUS_SUCCESS;\n- NdisInitializeEvent(&oidContext->oidComplete);\n-\n- OvsOidSetOrigRequest(oidRequest, NULL);\n- OvsOidSetContext(oidRequest, oidContext);\n-\n- NdisInterlockedIncrement(&(switchContext->pendingOidCount));\n- status = NdisFOidRequest(switchContext->NdisFilterHandle, oidRequest);\n- if (status == NDIS_STATUS_PENDING) {\n- NdisWaitEvent(&oidContext->oidComplete, 0);\n- } else {\n- NdisInterlockedDecrement(&(switchContext->pendingOidCount));\n- }\n-\n- if (status == NDIS_STATUS_INVALID_LENGTH ||\n- oidContext->status == NDIS_STATUS_INVALID_LENGTH) {\n- switch(oidType) {\n- case NdisRequestQueryInformation:\n- *outputSizeNeeded = oidRequest->DATA.QUERY_INFORMATION.BytesNeeded;\n- }\n- }\n-\n- status = oidContext->status;\n- ASSERT(status != NDIS_STATUS_PENDING);\n-\n- OvsFreeMemoryWithTag(oidRequest, OVS_OID_POOL_TAG);\n- OvsFreeMemoryWithTag(oidContext, OVS_OID_POOL_TAG);\n-\n-done:\n- OVS_LOG_TRACE(\"Exit: status %8x.\", status);\n- return status;\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Utility function to query if the extensible switch has completed activation\n- * successfully.\n- * --------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsQuerySwitchActivationComplete(POVS_SWITCH_CONTEXT switchContext,\n- BOOLEAN *switchActive)\n-{\n- NDIS_STATUS status;\n- PNDIS_SWITCH_PARAMETERS switchParams;\n- UINT32 outputSizeNeeded;\n-\n- OVS_LOG_TRACE(\"Enter: switchContext: %p, switchActive: %p\",\n- switchContext, switchActive);\n-\n- switchParams = OvsAllocateMemoryWithTag(sizeof *switchParams,\n- OVS_OID_POOL_TAG);\n- if (!switchParams) {\n- status = NDIS_STATUS_RESOURCES;\n- goto done;\n- }\n-\n- /*\n- * Even though 'switchParms' is supposed to be populated by the OID, it\n- * needs to be initialized nevertheless. Otherwise, OID returns\n- * NDIS_STATUS_INVALID_PARAMETER. This is not clear in the documentation.\n- */\n- RtlZeroMemory(switchParams, sizeof *switchParams);\n- switchParams->Header.Revision = NDIS_SWITCH_PARAMETERS_REVISION_1;\n- switchParams->Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\n- switchParams->Header.Size = NDIS_SIZEOF_NDIS_SWITCH_PARAMETERS_REVISION_1;\n-\n- status = OvsIssueOidRequest(switchContext, NdisRequestQueryInformation,\n- OID_SWITCH_PARAMETERS, NULL, 0,\n- (PVOID)switchParams, sizeof *switchParams,\n- &outputSizeNeeded);\n-\n- ASSERT(status != NDIS_STATUS_INVALID_LENGTH);\n- ASSERT(status != NDIS_STATUS_PENDING);\n- if (status == NDIS_STATUS_SUCCESS) {\n- ASSERT(switchParams->Header.Type == NDIS_OBJECT_TYPE_DEFAULT);\n- ASSERT(switchParams->Header.Revision == NDIS_SWITCH_PARAMETERS_REVISION_1);\n- ASSERT(switchParams->Header.Size ==\n- NDIS_SIZEOF_NDIS_SWITCH_PARAMETERS_REVISION_1);\n- *switchActive = switchParams->IsActive;\n- }\n-\n- OvsFreeMemoryWithTag(switchParams, OVS_OID_POOL_TAG);\n-\n-done:\n- OVS_LOG_TRACE(\"Exit: status %8x, switchActive: %d.\",\n- status, *switchActive);\n- return status;\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Utility function to get the array of ports on the extensible switch. Upon\n- * success, the caller needs to free the returned array.\n- * --------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsGetPortsOnSwitch(POVS_SWITCH_CONTEXT switchContext,\n- PNDIS_SWITCH_PORT_ARRAY *portArrayOut)\n-{\n- PNDIS_SWITCH_PORT_ARRAY portArray;\n- UINT32 arraySize = sizeof *portArray;\n- NDIS_STATUS status = NDIS_STATUS_FAILURE;\n-\n- OVS_LOG_TRACE(\"Enter: switchContext: %p, portArray: %p\",\n- switchContext, portArrayOut);\n- do {\n- UINT32 reqdArraySize;\n-\n- portArray = OvsAllocateMemoryWithTag(arraySize, OVS_OID_POOL_TAG);\n- if (!portArray) {\n- status = NDIS_STATUS_RESOURCES;\n- goto done;\n- }\n-\n- /*\n- * Even though 'portArray' is supposed to be populated by the OID, it\n- * needs to be initialized nevertheless. Otherwise, OID returns\n- * NDIS_STATUS_INVALID_PARAMETER. This is not clear in the documentation.\n- */\n- RtlZeroMemory(portArray, sizeof *portArray);\n- portArray->Header.Revision = NDIS_SWITCH_PORT_ARRAY_REVISION_1;\n- portArray->Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\n- portArray->Header.Size = NDIS_SIZEOF_NDIS_SWITCH_PORT_ARRAY_REVISION_1;\n-\n- status = OvsIssueOidRequest(switchContext, NdisRequestQueryInformation,\n- OID_SWITCH_PORT_ARRAY, NULL, 0,\n- (PVOID)portArray, arraySize,\n- &reqdArraySize);\n- if (status == NDIS_STATUS_SUCCESS) {\n- *portArrayOut = portArray;\n- break;\n- }\n-\n- OvsFreeMemoryWithTag(portArray, OVS_OID_POOL_TAG);\n- arraySize = reqdArraySize;\n- if (status != NDIS_STATUS_INVALID_LENGTH) {\n- break;\n- }\n- } while(status == NDIS_STATUS_INVALID_LENGTH);\n-\n-done:\n- OVS_LOG_TRACE(\"Exit: status %8x.\", status);\n- return status;\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Utility function to get the array of nics on the extensible switch. Upon\n- * success, the caller needs to free the returned array.\n- * --------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsGetNicsOnSwitch(POVS_SWITCH_CONTEXT switchContext,\n- PNDIS_SWITCH_NIC_ARRAY *nicArrayOut)\n-{\n- PNDIS_SWITCH_NIC_ARRAY nicArray;\n- UINT32 arraySize = sizeof *nicArray;\n- NDIS_STATUS status = NDIS_STATUS_FAILURE;\n-\n- OVS_LOG_TRACE(\"Enter: switchContext: %p, nicArray: %p\",\n- switchContext, nicArrayOut);\n-\n- do {\n- UINT32 reqdArraySize;\n-\n- nicArray = OvsAllocateMemoryWithTag(arraySize, OVS_OID_POOL_TAG);\n- if (!nicArray) {\n- status = NDIS_STATUS_RESOURCES;\n- goto done;\n- }\n-\n- /*\n- * Even though 'nicArray' is supposed to be populated by the OID, it\n- * needs to be initialized nevertheless. Otherwise, OID returns\n- * NDIS_STATUS_INVALID_PARAMETER. This is not clear in the documentation.\n- */\n- RtlZeroMemory(nicArray, sizeof *nicArray);\n- nicArray->Header.Revision = NDIS_SWITCH_NIC_ARRAY_REVISION_1;\n- nicArray->Header.Type = NDIS_OBJECT_TYPE_DEFAULT;\n- nicArray->Header.Size = NDIS_SIZEOF_NDIS_SWITCH_NIC_ARRAY_REVISION_1;\n-\n- status = OvsIssueOidRequest(switchContext, NdisRequestQueryInformation,\n- OID_SWITCH_NIC_ARRAY, NULL, 0,\n- (PVOID)nicArray, arraySize,\n- &reqdArraySize);\n- if (status == NDIS_STATUS_SUCCESS) {\n- *nicArrayOut = nicArray;\n- break;\n- }\n-\n- OvsFreeMemoryWithTag(nicArray, OVS_OID_POOL_TAG);\n- arraySize = reqdArraySize;\n- if (status != NDIS_STATUS_INVALID_LENGTH) {\n- break;\n- }\n- } while(status == NDIS_STATUS_INVALID_LENGTH);\n-\n-done:\n- OVS_LOG_TRACE(\"Exit: status %8x.\", status);\n- return status;\n-}\n-\n-VOID OvsFreeSwitchPortsArray(PNDIS_SWITCH_PORT_ARRAY portsArray)\n-{\n- if (portsArray) {\n- OvsFreeMemoryWithTag(portsArray, OVS_OID_POOL_TAG);\n- }\n-}\n-\n-VOID OvsFreeSwitchNicsArray(PNDIS_SWITCH_NIC_ARRAY nicsArray)\n-{\n- if (nicsArray) {\n- OvsFreeMemoryWithTag(nicsArray, OVS_OID_POOL_TAG);\n- }\n-}\ndiff --git a/datapath-windows/ovsext/Oid.h b/datapath-windows/ovsext/Oid.h\ndeleted file mode 100644\nindex ffa4d60cb..000000000\n--- a/datapath-windows/ovsext/Oid.h\n+++ /dev/null\n@@ -1,29 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#ifndef __OID_H_\n-#define __OID_H_ 1\n-\n-NDIS_STATUS OvsQuerySwitchActivationComplete(POVS_SWITCH_CONTEXT switchContext,\n- BOOLEAN *switchActive);\n-NDIS_STATUS OvsGetPortsOnSwitch(POVS_SWITCH_CONTEXT switchContext,\n- PNDIS_SWITCH_PORT_ARRAY *portArrayOut);\n-NDIS_STATUS OvsGetNicsOnSwitch(POVS_SWITCH_CONTEXT switchContext,\n- PNDIS_SWITCH_NIC_ARRAY *nicArrayOut);\n-VOID OvsFreeSwitchPortsArray(PNDIS_SWITCH_PORT_ARRAY portsArray);\n-VOID OvsFreeSwitchNicsArray(PNDIS_SWITCH_NIC_ARRAY nicsArray);\n-\n-#endif /* __OID_H_ */\ndiff --git a/datapath-windows/ovsext/PacketIO.c b/datapath-windows/ovsext/PacketIO.c\ndeleted file mode 100644\nindex 2a206305e..000000000\n--- a/datapath-windows/ovsext/PacketIO.c\n+++ /dev/null\n@@ -1,586 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-/*\n- * This file contains the implementation of the datapath/forwarding\n- * functionality of the OVS.\n- */\n-\n-#include \"precomp.h\"\n-\n-#include \"Actions.h\"\n-#include \"Switch.h\"\n-#include \"Vport.h\"\n-#include \"NetProto.h\"\n-#include \"User.h\"\n-#include \"PacketIO.h\"\n-#include \"Flow.h\"\n-#include \"Event.h\"\n-#include \"User.h\"\n-\n-/* Due to an imported header file */\n-#pragma warning( disable:4505 )\n-\n-#ifdef OVS_DBG_MOD\n-#undef OVS_DBG_MOD\n-#endif\n-#define OVS_DBG_MOD OVS_DBG_DISPATCH\n-#include \"Debug.h\"\n-\n-extern NDIS_STRING ovsExtGuidUC;\n-extern NDIS_STRING ovsExtFriendlyNameUC;\n-\n-static VOID OvsFinalizeCompletionList(OvsCompletionList *completionList);\n-static VOID OvsCompleteNBLIngress(POVS_SWITCH_CONTEXT switchContext,\n- PNET_BUFFER_LIST netBufferLists,\n- ULONG sendCompleteFlags,\n- BOOLEAN isSendComplete);\n-\n-VOID\n-OvsInitCompletionList(OvsCompletionList *completionList,\n- POVS_SWITCH_CONTEXT switchContext,\n- ULONG sendCompleteFlags)\n-{\n- ASSERT(completionList);\n- completionList->dropNbl = NULL;\n- completionList->dropNblNext = &completionList->dropNbl;\n- completionList->switchContext = switchContext;\n- completionList->sendCompleteFlags = sendCompleteFlags;\n-}\n-\n-/* Utility function used to complete an NBL. */\n-VOID\n-OvsAddPktCompletionList(OvsCompletionList *completionList,\n- BOOLEAN incoming,\n- NDIS_SWITCH_PORT_ID sourcePort,\n- PNET_BUFFER_LIST netBufferList,\n- UINT32 netBufferListCount,\n- PNDIS_STRING filterReason)\n-{\n- POVS_BUFFER_CONTEXT ctx;\n-\n- /* XXX: We handle one NBL at a time. */\n- ASSERT(netBufferList->Next == NULL);\n-\n- /* Make sure it has a context. */\n- ctx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(netBufferList);\n- ASSERT(ctx && ctx->magic == OVS_CTX_MAGIC);\n-\n- completionList->switchContext->NdisSwitchHandlers.ReportFilteredNetBufferLists(\n- completionList->switchContext->NdisSwitchContext, &ovsExtGuidUC,\n- &ovsExtFriendlyNameUC, sourcePort,\n- incoming ? NDIS_SWITCH_REPORT_FILTERED_NBL_FLAGS_IS_INCOMING : 0,\n- netBufferListCount, netBufferList, filterReason);\n-\n- *completionList->dropNblNext = netBufferList;\n- completionList->dropNblNext = &netBufferList->Next;\n- ASSERT(completionList->dropNbl);\n-}\n-\n-static __inline VOID\n-OvsReportNBLIngressError(POVS_SWITCH_CONTEXT switchContext,\n- PNET_BUFFER_LIST nblList,\n- PNDIS_STRING filterReason,\n- NDIS_STATUS error)\n-{\n- PNET_BUFFER_LIST nbl = nblList;\n- while (nbl) {\n- PNDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO fwdDetail;\n- fwdDetail = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(nbl);\n-\n- nbl->Status = error;\n-\n- /* This can be optimized by batching NBL's from the same\n- * SourcePortId. */\n- switchContext->NdisSwitchHandlers.ReportFilteredNetBufferLists(\n- switchContext->NdisSwitchContext, &ovsExtGuidUC,\n- &ovsExtFriendlyNameUC, fwdDetail->SourcePortId,\n- NDIS_SWITCH_REPORT_FILTERED_NBL_FLAGS_IS_INCOMING,\n- 1 /*Nbl count.*/, nbl, filterReason);\n-\n- nbl = NET_BUFFER_LIST_NEXT_NBL(nbl);\n- }\n-}\n-\n-static __inline ULONG\n-OvsGetSendCompleteFlags(ULONG sendFlags)\n-{\n- BOOLEAN dispatch, sameSource;\n- ULONG sendCompleteFlags;\n-\n- dispatch = NDIS_TEST_SEND_AT_DISPATCH_LEVEL(sendFlags);\n- sendCompleteFlags = (dispatch ?\n- NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL : 0);\n- sameSource = NDIS_TEST_SEND_FLAG(sendFlags,\n- NDIS_SEND_FLAGS_SWITCH_SINGLE_SOURCE);\n- sendCompleteFlags |= (sameSource ?\n- NDIS_SEND_COMPLETE_FLAGS_SWITCH_SINGLE_SOURCE : 0);\n-\n- return sendCompleteFlags;\n-}\n-\n-VOID\n-OvsSendNBLIngress(POVS_SWITCH_CONTEXT switchContext,\n- PNET_BUFFER_LIST netBufferLists,\n- ULONG sendFlags)\n-{\n- if (switchContext->dataFlowState == OvsSwitchPaused) {\n- /* If a filter module is in the Paused state, the filter driver must not\n- * originate any send requests for that filter module. If NDIS calls\n- * FilterSendNetBufferLists, the driver must not call\n- * NdisFSendNetBufferLists to pass on the data until the driver is\n- * restarted. The driver should call NdisFSendNetBufferListsComplete\n- * immediately to complete the send operation. It should set the\n- * complete status in each NET_BUFFER_LIST structure to\n- * NDIS_STATUS_PAUSED.\n- *\n- * http://msdn.microsoft.com/en-us/library/windows/hardware/\n- * ff549966(v=vs.85).aspx */\n- NDIS_STRING filterReason;\n- ULONG sendCompleteFlags = OvsGetSendCompleteFlags(sendFlags);\n-\n- RtlInitUnicodeString(&filterReason,\n- L\"Switch state PAUSED, drop before FSendNBL.\");\n- OvsReportNBLIngressError(switchContext, netBufferLists, &filterReason,\n- NDIS_STATUS_PAUSED);\n- OvsCompleteNBLIngress(switchContext, netBufferLists,\n- sendCompleteFlags, FALSE);\n- return;\n- }\n-\n- ASSERT(switchContext->dataFlowState == OvsSwitchRunning);\n-\n- POVS_BUFFER_CONTEXT ctx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(netBufferLists);\n- LONG refCount = 1, exchange = 0;\n- InterlockedCompareExchange((LONG volatile *)&refCount, exchange, (LONG)ctx->refCount);\n- if (refCount != exchange) {\n- InterlockedExchange((LONG volatile *)&ctx->sendFlags, sendFlags);\n- InterlockedExchange16((SHORT volatile *)&ctx->pendingSend, 1);\n- return;\n- }\n-\n- InterlockedExchange16((SHORT volatile *)&ctx->pendingSend, 0);\n- NdisFSendNetBufferLists(switchContext->NdisFilterHandle, netBufferLists,\n- NDIS_DEFAULT_PORT_NUMBER, sendFlags);\n-}\n-\n-static __inline BOOLEAN\n-OvsCheckNBLSingleSource(PNET_BUFFER_LIST netBufferLists)\n-{\n- UINT32 sourcePortId = 0;\n- BOOLEAN singleSource = TRUE;\n- PNET_BUFFER_LIST curNbl = netBufferLists;\n- PNDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO info;\n-\n- while (curNbl != NULL) {\n- info = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(curNbl);\n- if (info == NULL) {\n- /* We are not able to determine the source port ID */\n- singleSource = FALSE;\n- OVS_LOG_INFO(\"nbl %p has no source port\", curNbl);\n- break;\n- }\n- if (curNbl == netBufferLists) {\n- sourcePortId = info->SourcePortId;\n- } else if (info->SourcePortId != sourcePortId) {\n- singleSource = FALSE;\n- OVS_LOG_INFO(\"Source port in nbl %p is %u, not from %u\",\n- curNbl, info->SourcePortId, sourcePortId);\n- break;\n- }\n- curNbl = NET_BUFFER_LIST_NEXT_NBL(curNbl);\n- }\n-\n- return singleSource;\n-}\n-\n-/*\n- * SendNetBufferListsCompleteHandler releases the NetBufferLists with flag\n- * NDIS_SEND_COMPLETE_FLAGS_SWITCH_SINGLE_SOURCE if all the NBLs have same\n- * source port, for cloned NBLs, source port might be changed, although the\n- * cloned NBLs have same source port, there parent NBLs may have different\n- * source ports, so we should have a check before passing the flag to\n- * NdisFSendNetBufferListsComplete.\n- */\n-static __inline VOID\n-OvsCompleteUpperLayerNBL(NDIS_HANDLE ndisHandle,\n- PNET_BUFFER_LIST netBufferLists,\n- ULONG sendCompleteFlags,\n- BOOLEAN isSendComplete)\n-{\n- BOOLEAN singleSource = TRUE;\n- PNET_BUFFER_LIST curNbl, nextNbl;\n-\n- /* To check whether the NBLs are from the same source port */\n- if (isSendComplete &&\n- (sendCompleteFlags & NDIS_SEND_COMPLETE_FLAGS_SWITCH_SINGLE_SOURCE)) {\n- singleSource = OvsCheckNBLSingleSource(netBufferLists);\n- }\n-\n- if (singleSource) {\n- NdisFSendNetBufferListsComplete(ndisHandle,\n- netBufferLists,\n- sendCompleteFlags);\n- } else {\n- /*\n- * Not from a single source port, releasing the NBls without flag\n- * NDIS_SEND_COMPLETE_FLAGS_SWITCH_SINGLE_SOURCE doesn't help, so\n- * let's release them one by one.\n- */\n- for (curNbl = netBufferLists; curNbl != NULL; curNbl = nextNbl) {\n- nextNbl = NET_BUFFER_LIST_NEXT_NBL(curNbl);\n- NET_BUFFER_LIST_NEXT_NBL(curNbl) = NULL;\n- NdisFSendNetBufferListsComplete(ndisHandle,\n- curNbl,\n- sendCompleteFlags);\n- }\n- }\n-}\n-\n-static __inline VOID\n-OvsStartNBLIngressError(POVS_SWITCH_CONTEXT switchContext,\n- PNET_BUFFER_LIST nblList,\n- ULONG sendCompleteFlags,\n- PNDIS_STRING filterReason,\n- NDIS_STATUS error)\n-{\n- ASSERT(error);\n- OvsReportNBLIngressError(switchContext, nblList, filterReason, error);\n- OvsCompleteUpperLayerNBL(switchContext->NdisFilterHandle, nblList,\n- sendCompleteFlags, FALSE);\n-}\n-\n-static VOID\n-OvsAppendNativeForwardedPacket(POVS_SWITCH_CONTEXT switchContext,\n- PNET_BUFFER_LIST curNbl,\n- PNET_BUFFER_LIST *nativeNbls,\n- ULONG flags,\n- BOOLEAN isRecv)\n-{\n- POVS_BUFFER_CONTEXT ctx = { 0 };\n- NDIS_STRING filterReason;\n-\n- *nativeNbls = curNbl;\n-\n- ctx = OvsInitExternalNBLContext(switchContext, curNbl, isRecv);\n- if (ctx == NULL) {\n- RtlInitUnicodeString(&filterReason,\n- L\"Cannot allocate native NBL context.\");\n-\n- OvsStartNBLIngressError(switchContext, curNbl, flags, &filterReason,\n- NDIS_STATUS_RESOURCES);\n- }\n-}\n-\n-static VOID\n-OvsStartNBLIngress(POVS_SWITCH_CONTEXT switchContext,\n- PNET_BUFFER_LIST netBufferLists,\n- ULONG SendFlags)\n-{\n- NDIS_SWITCH_PORT_ID sourcePort = 0;\n- NDIS_SWITCH_NIC_INDEX sourceIndex = 0;\n- PNDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO fwdDetail;\n- PNET_BUFFER_LIST curNbl = NULL, nextNbl = NULL, lastNbl = NULL;\n- ULONG sendCompleteFlags;\n- UCHAR dispatch;\n- LOCK_STATE_EX lockState, dpLockState;\n- NDIS_STATUS status;\n- NDIS_STRING filterReason;\n- LIST_ENTRY missedPackets;\n- UINT32 num = 0;\n- OvsCompletionList completionList;\n-#if (NDIS_SUPPORT_NDIS640)\n- PNET_BUFFER_LIST nativeForwardedNbls = NULL;\n- PNET_BUFFER_LIST *nextNativeForwardedNbl = &nativeForwardedNbls;\n-#endif\n-\n- dispatch = NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags)?\n- NDIS_RWL_AT_DISPATCH_LEVEL : 0;\n- sendCompleteFlags = OvsGetSendCompleteFlags(SendFlags);\n- SendFlags |= NDIS_SEND_FLAGS_SWITCH_DESTINATION_GROUP;\n-\n- InitializeListHead(&missedPackets);\n- OvsInitCompletionList(&completionList, switchContext, sendCompleteFlags);\n-\n- for (curNbl = netBufferLists; curNbl != NULL; curNbl = nextNbl) {\n- POVS_VPORT_ENTRY vport = NULL;\n- UINT32 portNo = 0;\n- OVS_DATAPATH *datapath = &switchContext->datapath;\n- OVS_PACKET_HDR_INFO layers = { 0 };\n- OvsFlowKey key = { 0 };\n- UINT64 hash = 0;\n- PNET_BUFFER curNb = NULL;\n- POVS_BUFFER_CONTEXT ctx = NULL;\n-\n- nextNbl = curNbl->Next;\n- curNbl->Next = NULL;\n-\n- fwdDetail = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(curNbl);\n- sourcePort = fwdDetail->SourcePortId;\n- sourceIndex = (NDIS_SWITCH_NIC_INDEX)fwdDetail->SourceNicIndex;\n-\n-#if (NDIS_SUPPORT_NDIS640)\n- if (fwdDetail->NativeForwardingRequired) {\n- /* Add current NBL to those that require native forwarding. */\n- OvsAppendNativeForwardedPacket(\n- switchContext,\n- curNbl,\n- nextNativeForwardedNbl,\n- sendCompleteFlags,\n- OvsIsExternalVportByPortId(switchContext, sourcePort));\n- continue;\n- }\n-#endif /* NDIS_SUPPORT_NDIS640 */\n-\n- ctx = OvsInitExternalNBLContext(switchContext, curNbl,\n- OvsIsExternalVportByPortId(switchContext, sourcePort));\n- if (ctx == NULL) {\n- RtlInitUnicodeString(&filterReason,\n- L\"Cannot allocate external NBL context.\");\n-\n- OvsStartNBLIngressError(switchContext, curNbl,\n- sendCompleteFlags, &filterReason,\n- NDIS_STATUS_RESOURCES);\n- continue;\n- }\n-\n- /* Ethernet Header is a guaranteed safe access. */\n- curNb = NET_BUFFER_LIST_FIRST_NB(curNbl);\n- if (curNb->Next != NULL) {\n- /* Create a NET_BUFFER_LIST for each NET_BUFFER. */\n- status = OvsCreateNewNBLsFromMultipleNBs(switchContext,\n- &curNbl,\n- &lastNbl);\n- if (!NT_SUCCESS(status)) {\n- RtlInitUnicodeString(&filterReason,\n- L\"Cannot allocate NBLs with single NB.\");\n-\n- OvsAddPktCompletionList(&completionList, TRUE, sourcePort,\n- curNbl, 0, &filterReason);\n- continue;\n- }\n-\n- lastNbl->Next = nextNbl;\n- nextNbl = curNbl->Next;\n- curNbl->Next = NULL;\n- }\n- {\n- OvsFlow *flow;\n-\n- /* Take the DispatchLock so none of the VPORTs disconnect while\n- * we are setting destination ports.\n- *\n- * XXX: acquire/release the dispatch lock for a \"batch\" of packets\n- * rather than for each packet. */\n- NdisAcquireRWLockRead(switchContext->dispatchLock, &lockState,\n- dispatch);\n-\n- vport = OvsFindVportByPortIdAndNicIndex(switchContext, sourcePort,\n- sourceIndex);\n- if (vport == NULL || vport->ovsState != OVS_STATE_CONNECTED) {\n- RtlInitUnicodeString(&filterReason,\n- L\"OVS-Cannot forward packet from unknown source port\");\n- goto dropit;\n- } else {\n- portNo = vport->portNo;\n- }\n-\n- vport->stats.rxPackets++;\n- vport->stats.rxBytes += NET_BUFFER_DATA_LENGTH(curNb);\n-\n- status = OvsExtractFlow(curNbl, vport->portNo, &key, &layers, NULL);\n- if (status != NDIS_STATUS_SUCCESS) {\n- RtlInitUnicodeString(&filterReason, L\"OVS-Flow extract failed\");\n- goto dropit;\n- }\n-\n- ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);\n- OvsAcquireDatapathRead(datapath, &dpLockState, TRUE);\n-\n- flow = OvsLookupFlow(datapath, &key, &hash, FALSE);\n- if (flow) {\n- OvsFlowUsed(flow, curNbl, &layers);\n- datapath->hits++;\n- /* If successful, OvsActionsExecute() consumes the NBL.\n- * Otherwise, it adds it to the completionList. No need to\n- * check the return value. */\n- OvsActionsExecute(switchContext, &completionList, curNbl,\n- portNo, SendFlags, &key, &hash, &layers,\n- flow->actions, flow->actionsLen);\n- OvsReleaseDatapath(datapath, &dpLockState);\n- NdisReleaseRWLock(switchContext->dispatchLock, &lockState);\n- continue;\n- } else {\n- OvsReleaseDatapath(datapath, &dpLockState);\n-\n- datapath->misses++;\n- status = OvsCreateAndAddPackets(NULL, 0, OVS_PACKET_CMD_MISS,\n- vport, &key, curNbl,\n- OvsIsExternalVportByPortId(switchContext, sourcePort),\n- &layers, switchContext, &missedPackets, &num);\n- if (status == NDIS_STATUS_SUCCESS) {\n- /* Complete the packet since it was copied to user\n- * buffer. */\n- RtlInitUnicodeString(&filterReason,\n- L\"OVS-Dropped since packet was copied to userspace\");\n- } else {\n- RtlInitUnicodeString(&filterReason,\n- L\"OVS-Dropped due to failure to queue to userspace\");\n- }\n- goto dropit;\n- }\n-\n-dropit:\n- OvsAddPktCompletionList(&completionList, TRUE, sourcePort, curNbl, 0,\n- &filterReason);\n- NdisReleaseRWLock(switchContext->dispatchLock, &lockState);\n- }\n- }\n-\n-#if (NDIS_SUPPORT_NDIS640)\n- if (nativeForwardedNbls) {\n- /* This is NVGRE encapsulated traffic and is forwarded to NDIS\n- * in order to be handled by the HNV module. */\n- OvsSendNBLIngress(switchContext, nativeForwardedNbls, SendFlags);\n- }\n-#endif /* NDIS_SUPPORT_NDIS640 */\n-\n- /* Queue the missed packets. */\n- OvsQueuePackets(&missedPackets, num);\n- OvsFinalizeCompletionList(&completionList);\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Implements filter driver's FilterSendNetBufferLists Function.\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-OvsExtSendNBL(NDIS_HANDLE filterModuleContext,\n- PNET_BUFFER_LIST netBufferLists,\n- NDIS_PORT_NUMBER portNumber,\n- ULONG sendFlags)\n-{\n- UNREFERENCED_PARAMETER(portNumber);\n-\n- /* 'filterModuleContext' is the switch context that gets created in the\n- * AttachHandler. */\n- POVS_SWITCH_CONTEXT switchContext;\n- switchContext = (POVS_SWITCH_CONTEXT) filterModuleContext;\n-\n- if (switchContext->dataFlowState == OvsSwitchPaused) {\n- NDIS_STRING filterReason;\n- ULONG sendCompleteFlags = OvsGetSendCompleteFlags(sendFlags);\n-\n- RtlInitUnicodeString(&filterReason,\n- L\"Switch state PAUSED, drop on ingress.\");\n- OvsStartNBLIngressError(switchContext, netBufferLists,\n- sendCompleteFlags, &filterReason,\n- NDIS_STATUS_PAUSED);\n- return;\n- }\n-\n- ASSERT(switchContext->dataFlowState == OvsSwitchRunning);\n-\n- OvsStartNBLIngress(switchContext, netBufferLists, sendFlags);\n-}\n-\n-static VOID\n-OvsCompleteNBLIngress(POVS_SWITCH_CONTEXT switchContext,\n- PNET_BUFFER_LIST netBufferLists,\n- ULONG sendCompleteFlags,\n- BOOLEAN isSendComplete)\n-{\n- PNET_BUFFER_LIST curNbl = NULL, nextNbl = NULL;\n- OvsCompletionList newList;\n-\n- newList.dropNbl = NULL;\n- newList.dropNblNext = &newList.dropNbl;\n-\n- for (curNbl = netBufferLists; curNbl != NULL; curNbl = nextNbl) {\n- nextNbl = curNbl->Next;\n- curNbl->Next = NULL;\n-\n- curNbl = OvsCompleteNBL(switchContext, curNbl, TRUE);\n- if (curNbl != NULL) {\n- /* NBL originated from the upper layer. */\n- *newList.dropNblNext = curNbl;\n- newList.dropNblNext = &curNbl->Next;\n- }\n- }\n-\n- /* Complete the NBL's that were sent by the upper layer. */\n- if (newList.dropNbl != NULL) {\n- OvsCompleteUpperLayerNBL(switchContext->NdisFilterHandle,\n- newList.dropNbl,\n- sendCompleteFlags,\n- isSendComplete);\n- }\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Implements filter driver's FilterSendNetBufferListsComplete function.\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-OvsExtSendNBLComplete(NDIS_HANDLE filterModuleContext,\n- PNET_BUFFER_LIST netBufferLists,\n- ULONG sendCompleteFlags)\n-{\n- OvsCompleteNBLIngress((POVS_SWITCH_CONTEXT)filterModuleContext,\n- netBufferLists, sendCompleteFlags, TRUE);\n-}\n-\n-\n-VOID\n-OvsFinalizeCompletionList(OvsCompletionList *completionList)\n-{\n- if (completionList->dropNbl != NULL) {\n- OvsCompleteNBLIngress(completionList->switchContext,\n- completionList->dropNbl,\n- completionList->sendCompleteFlags,\n- FALSE);\n-\n- completionList->dropNbl = NULL;\n- completionList->dropNblNext = &completionList->dropNbl;\n- }\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Implements filter driver's FilterCancelSendNetBufferLists function.\n- *\n- * \"If a filter driver specifies a FilterSendNetBufferLists function and it\n- * queues send requests, it must also specify a\n- * FilterCancelSendNetBufferLists function.\"\n- *\n- * http://msdn.microsoft.com/en-us/library/windows/hardware/\n- * ff549966(v=vs.85).aspx\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-OvsExtCancelSendNBL(NDIS_HANDLE filterModuleContext,\n- PVOID CancelId)\n-{\n- UNREFERENCED_PARAMETER(filterModuleContext);\n- UNREFERENCED_PARAMETER(CancelId);\n-\n- /* All send requests get completed synchronously, so there is no need to\n- * implement this callback. */\n-}\ndiff --git a/datapath-windows/ovsext/PacketIO.h b/datapath-windows/ovsext/PacketIO.h\ndeleted file mode 100644\nindex a7c1f7668..000000000\n--- a/datapath-windows/ovsext/PacketIO.h\n+++ /dev/null\n@@ -1,51 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#ifndef __PACKETIO_H_\n-#define __PACKETIO_H_ 1\n-\n-typedef union _OVS_PACKET_HDR_INFO OVS_PACKET_HDR_INFO;\n-\n-/*\n- * Data structures and utility functions to help manage a list of packets to be\n- * completed (dropped).\n- */\n-typedef struct OvsCompletionList {\n- PNET_BUFFER_LIST dropNbl;\n- PNET_BUFFER_LIST *dropNblNext;\n- POVS_SWITCH_CONTEXT switchContext;\n- ULONG sendCompleteFlags;\n-} OvsCompletionList;\n-\n-VOID OvsInitCompletionList(OvsCompletionList *completionList,\n- POVS_SWITCH_CONTEXT switchContext,\n- ULONG sendCompleteFlags);\n-VOID OvsAddPktCompletionList(OvsCompletionList *completionList,\n- BOOLEAN incoming,\n- NDIS_SWITCH_PORT_ID sourcePort,\n- PNET_BUFFER_LIST netBufferList,\n- UINT32 netBufferListCount,\n- PNDIS_STRING filterReason);\n-\n-\n-/*\n- * Functions related to packet processing.\n- */\n-VOID OvsSendNBLIngress(POVS_SWITCH_CONTEXT switchContext,\n- PNET_BUFFER_LIST netBufferLists,\n- ULONG sendFlags);\n-\n-#endif /* __PACKETIO_H_ */\ndiff --git a/datapath-windows/ovsext/PacketParser.c b/datapath-windows/ovsext/PacketParser.c\ndeleted file mode 100644\nindex e89ff0641..000000000\n--- a/datapath-windows/ovsext/PacketParser.c\n+++ /dev/null\n@@ -1,332 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#include \"PacketParser.h\"\n-\n-//XXX consider moving to NdisGetDataBuffer.\n-const VOID *\n-OvsGetPacketBytes(const NET_BUFFER_LIST *nbl,\n- UINT32 len,\n- UINT32 srcOffset,\n- VOID *storage)\n-{\n- NDIS_STATUS status = NDIS_STATUS_SUCCESS;\n- PNET_BUFFER netBuffer = NET_BUFFER_LIST_FIRST_NB(nbl);\n- PMDL currentMdl;\n- BOOLEAN firstMDL = TRUE;\n- ULONG destOffset = 0;\n- VOID *dest = storage;\n- const UINT32 copyLen = len;\n- ULONG packetLen;\n-\n- packetLen = NET_BUFFER_DATA_LENGTH(netBuffer);\n- // Start copy from current MDL\n- currentMdl = NET_BUFFER_CURRENT_MDL(netBuffer);\n-\n- // Data on current MDL may be offset from start of MDL\n- while (destOffset < copyLen && currentMdl) {\n- PUCHAR srcMemory = OvsGetMdlWithLowPriority(currentMdl);\n- ULONG length = MmGetMdlByteCount(currentMdl);\n- if (!srcMemory) {\n- status = NDIS_STATUS_RESOURCES;\n- break;\n- }\n-\n- if (firstMDL) {\n- ULONG mdlOffset = NET_BUFFER_CURRENT_MDL_OFFSET(netBuffer);\n- srcMemory += mdlOffset;\n- length -= mdlOffset;\n- firstMDL = FALSE;\n- }\n- length = MIN(length, packetLen);\n- packetLen -= length;\n- ASSERT((INT)packetLen >= 0);\n-\n- if (srcOffset >= length) {\n- currentMdl = NDIS_MDL_LINKAGE(currentMdl);\n- srcOffset -= length;\n- continue;\n- } else {\n- srcMemory += srcOffset;\n- length -= srcOffset;\n- srcOffset = 0;\n- }\n-\n- length = min(length, copyLen-destOffset);\n-\n- NdisMoveMemory((PUCHAR)dest+destOffset, srcMemory, length);\n- destOffset += length;\n-\n- currentMdl = NDIS_MDL_LINKAGE(currentMdl);\n- }\n-\n- if (destOffset == copyLen) {\n- ASSERT(status == NDIS_STATUS_SUCCESS);\n- return storage;\n- }\n-\n- return NULL;\n-}\n-\n-NDIS_STATUS\n-OvsParseIPv6(const NET_BUFFER_LIST *packet,\n- Ipv6Key *ipv6Key,\n- POVS_PACKET_HDR_INFO layers)\n-{\n- UINT16 ofs = layers->l3Offset;\n- IPv6Hdr ipv6HdrStorage;\n- const IPv6Hdr *nh;\n- UINT32 nextHdr;\n-\n- nh = OvsGetPacketBytes(packet, sizeof *nh, ofs, &ipv6HdrStorage);\n- if (!nh) {\n- return NDIS_STATUS_FAILURE;\n- }\n-\n- nextHdr = nh->nexthdr;\n- RtlCopyMemory(&ipv6Key->ipv6Src, nh->saddr.s6_addr, 16);\n- RtlCopyMemory(&ipv6Key->ipv6Dst, nh->daddr.s6_addr, 16);\n-\n- ipv6Key->nwTos = ((nh->flow_lbl[0] & 0xF0) >> 4) | (nh->priority << 4);\n- ipv6Key->ipv6Label =\n- ((nh->flow_lbl[0] & 0x0F) << 16) | (nh->flow_lbl[1] << 8) | nh->flow_lbl[2];\n- ipv6Key->nwTtl = nh->hop_limit;\n- ipv6Key->nwProto = SOCKET_IPPROTO_NONE;\n- ipv6Key->nwFrag = OVS_FRAG_TYPE_NONE;\n-\n- // Parse extended headers and compute L4 offset\n- ofs += sizeof(IPv6Hdr);\n- for (;;) {\n- if ((nextHdr != SOCKET_IPPROTO_HOPOPTS)\n- && (nextHdr != SOCKET_IPPROTO_ROUTING)\n- && (nextHdr != SOCKET_IPPROTO_DSTOPTS)\n- && (nextHdr != SOCKET_IPPROTO_AH)\n- && (nextHdr != SOCKET_IPPROTO_FRAGMENT)) {\n- /*\n- * It's either a terminal header (e.g., TCP, UDP) or one we\n- * don't understand. In either case, we're done with the\n- * packet, so use it to fill in 'nw_proto'.\n- */\n- break;\n- }\n-\n- if (nextHdr == SOCKET_IPPROTO_HOPOPTS\n- || nextHdr == SOCKET_IPPROTO_ROUTING\n- || nextHdr == SOCKET_IPPROTO_DSTOPTS\n- || nextHdr == SOCKET_IPPROTO_AH) {\n- IPv6ExtHdr extHdrStorage;\n- const IPv6ExtHdr *extHdr;\n- UINT8 len;\n-\n- extHdr = OvsGetPacketBytes(packet, sizeof *extHdr, ofs, &extHdrStorage);\n- if (!extHdr) {\n- return NDIS_STATUS_FAILURE;\n- }\n-\n- len = extHdr->hdrExtLen;\n- ofs += nextHdr == SOCKET_IPPROTO_AH ? (len + 2) * 4 : (len + 1) * 8;\n- nextHdr = extHdr->nextHeader;\n- if (OvsPacketLenNBL(packet) < ofs) {\n- return NDIS_STATUS_FAILURE;\n- }\n- } else if (nextHdr == SOCKET_IPPROTO_FRAGMENT) {\n- IPv6FragHdr fragHdrStorage;\n- const IPv6FragHdr *fragHdr;\n-\n- fragHdr = OvsGetPacketBytes(packet, sizeof *fragHdr, ofs,\n- &fragHdrStorage);\n- if (!fragHdr) {\n- return NDIS_STATUS_FAILURE;\n- }\n-\n- nextHdr = fragHdr->nextHeader;\n- ofs += sizeof *fragHdr;\n-\n- /* We only process the first fragment. */\n- if (fragHdr->offlg != htons(0)) {\n- if ((ntohs(fragHdr->offlg) & IP6F_OFF_HOST_ORDER_MASK) == htons(0)) {\n- ipv6Key->nwFrag = OVS_FRAG_TYPE_FIRST;\n- } else {\n- ipv6Key->nwFrag = OVS_FRAG_TYPE_LATER;\n- nextHdr = SOCKET_IPPROTO_FRAGMENT;\n- break;\n- }\n- } else {\n- ipv6Key->nwFrag = OVS_FRAG_TYPE_NONE;\n- }\n- }\n- }\n-\n- ipv6Key->nwProto = (UINT8)nextHdr;\n- layers->l4Offset = ofs;\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-VOID\n-OvsParseTcp(const NET_BUFFER_LIST *packet,\n- L4Key *flow,\n- POVS_PACKET_HDR_INFO layers)\n-{\n- TCPHdr tcpStorage;\n- const TCPHdr *tcp = OvsGetTcp(packet, layers->l4Offset, &tcpStorage);\n- if (tcp) {\n- if (flow) {\n- flow->tpSrc = tcp->source;\n- flow->tpDst = tcp->dest;\n- }\n- if (layers) {\n- layers->isTcp = 1;\n- layers->l7Offset = layers->l4Offset + 4 * tcp->doff;\n- }\n- }\n-}\n-\n-VOID\n-OvsParseSctp(const NET_BUFFER_LIST *packet,\n- L4Key *flow,\n- POVS_PACKET_HDR_INFO layers)\n-{\n- SCTPHdr sctpStorage;\n- const SCTPHdr *sctp = OvsGetSctp(packet, layers->l4Offset, &sctpStorage);\n- if (sctp) {\n- if (flow) {\n- flow->tpSrc = sctp->source;\n- flow->tpDst = sctp->dest;\n- }\n- if (layers) {\n- layers->isSctp = 1;\n- layers->l7Offset = layers->l4Offset + sizeof *sctp;\n- }\n- }\n-}\n-\n-VOID\n-OvsParseUdp(const NET_BUFFER_LIST *packet,\n- L4Key *flow,\n- POVS_PACKET_HDR_INFO layers)\n-{\n- UDPHdr udpStorage;\n- const UDPHdr *udp = OvsGetUdp(packet, layers->l4Offset, &udpStorage);\n- if (udp) {\n- if (flow) {\n- flow->tpSrc = udp->source;\n- flow->tpDst = udp->dest;\n- }\n- if (layers) {\n- layers->isUdp = 1;\n- if (udp->check == 0) {\n- layers->udpCsumZero = 1;\n- }\n- layers->l7Offset = layers->l4Offset + sizeof *udp;\n- }\n- }\n-}\n-\n-NDIS_STATUS\n-OvsParseIcmpV6(const NET_BUFFER_LIST *packet,\n- Ipv6Key *ipv6Key,\n- Icmp6Key *icmp6Key,\n- POVS_PACKET_HDR_INFO layers)\n-{\n- UINT16 ofs = layers->l4Offset;\n- ICMPHdr icmpStorage;\n- const ICMPHdr *icmp;\n-\n- memset(&icmp6Key->ndTarget, 0, sizeof(icmp6Key->ndTarget));\n- memset(icmp6Key->arpSha, 0, sizeof(icmp6Key->arpSha));\n- memset(icmp6Key->arpTha, 0, sizeof(icmp6Key->arpTha));\n-\n- icmp = OvsGetIcmp(packet, ofs, &icmpStorage);\n- if (!icmp) {\n- return NDIS_STATUS_FAILURE;\n- }\n- ofs += sizeof *icmp;\n-\n- /*\n- * The ICMPv6 type and code fields use the 16-bit transport port\n- * fields, so we need to store them in 16-bit network byte order.\n- */\n- if (ipv6Key) {\n- ipv6Key->l4.tpSrc = htons(icmp->type);\n- ipv6Key->l4.tpDst = htons(icmp->code);\n- }\n-\n- if (icmp->code == 0 &&\n- (icmp->type == ND_NEIGHBOR_SOLICIT ||\n- icmp->type == ND_NEIGHBOR_ADVERT)) {\n- struct in6_addr ndTargetStorage;\n- const struct in6_addr *ndTarget;\n-\n- ndTarget = OvsGetPacketBytes(packet, sizeof *ndTarget, ofs,\n- &ndTargetStorage);\n- if (!ndTarget) {\n- return NDIS_STATUS_FAILURE;\n- }\n- icmp6Key->ndTarget = *ndTarget;\n-\n- while ((UINT32)(ofs + 8) <= OvsPacketLenNBL(packet)) {\n- /*\n- * The minimum size of an option is 8 bytes, which also is\n- * the size of Ethernet link-layer options.\n- */\n- IPv6NdOptHdr ndOptStorage;\n- const IPv6NdOptHdr *ndOpt;\n- UINT16 optLen;\n-\n- ndOpt = OvsGetPacketBytes(packet, sizeof *ndOpt, ofs, &ndOptStorage);\n- if (!ndOpt) {\n- return NDIS_STATUS_FAILURE;\n- }\n-\n- optLen = ndOpt->len * 8;\n- if (!optLen || (UINT32)(ofs + optLen) > OvsPacketLenNBL(packet)) {\n- goto invalid;\n- }\n-\n- /*\n- * Store the link layer address if the appropriate option is\n- * provided. It is considered an error if the same link\n- * layer option is specified twice.\n- */\n- if (ndOpt->type == ND_OPT_SOURCE_LINKADDR && optLen == 8) {\n- if (Eth_IsNullAddr(icmp6Key->arpSha)) {\n- memcpy(icmp6Key->arpSha, ndOpt + 1, ETH_ADDR_LENGTH);\n- } else {\n- goto invalid;\n- }\n- } else if (ndOpt->type == ND_OPT_TARGET_LINKADDR && optLen == 8) {\n- if (Eth_IsNullAddr(icmp6Key->arpTha)) {\n- memcpy(icmp6Key->arpTha, ndOpt + 1, ETH_ADDR_LENGTH);\n- } else {\n- goto invalid;\n- }\n- }\n-\n- ofs += optLen;\n- }\n- }\n-\n- layers->l7Offset = ofs;\n- layers->isIcmp = 1;\n- return NDIS_STATUS_SUCCESS;\n-\n-invalid:\n- RtlZeroMemory(&icmp6Key->ndTarget, sizeof(icmp6Key->ndTarget));\n- RtlZeroMemory(icmp6Key->arpSha, sizeof(icmp6Key->arpSha));\n- RtlZeroMemory(icmp6Key->arpTha, sizeof(icmp6Key->arpTha));\n-\n- return NDIS_STATUS_FAILURE;\n-}\ndiff --git a/datapath-windows/ovsext/PacketParser.h b/datapath-windows/ovsext/PacketParser.h\ndeleted file mode 100644\nindex 0d5c0a6cb..000000000\n--- a/datapath-windows/ovsext/PacketParser.h\n+++ /dev/null\n@@ -1,170 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#ifndef __PACKET_PARSER_H_\n-#define __PACKET_PARSER_H_ 1\n-\n-#define MIN_IPV4_HLEN 20\n-\n-#include \"precomp.h\"\n-#include \"NetProto.h\"\n-\n-const VOID* OvsGetPacketBytes(const NET_BUFFER_LIST *_pNB, UINT32 len,\n- UINT32 SrcOffset, VOID *storage);\n-NDIS_STATUS OvsParseIPv6(const NET_BUFFER_LIST *packet, Ipv6Key *key,\n- POVS_PACKET_HDR_INFO layers);\n-VOID OvsParseTcp(const NET_BUFFER_LIST *packet, L4Key *flow,\n- POVS_PACKET_HDR_INFO layers);\n-VOID OvsParseUdp(const NET_BUFFER_LIST *packet, L4Key *flow,\n- POVS_PACKET_HDR_INFO layers);\n-VOID OvsParseSctp(const NET_BUFFER_LIST *packet, L4Key *flow,\n- POVS_PACKET_HDR_INFO layers);\n-NDIS_STATUS OvsParseIcmpV6(const NET_BUFFER_LIST *packet,\n- Ipv6Key *ipv6Key,\n- Icmp6Key *flow,\n- POVS_PACKET_HDR_INFO layers);\n-\n-static __inline ULONG\n-OvsPacketLenNBL(const NET_BUFFER_LIST *_pNB)\n-{\n- INT length = 0;\n- NET_BUFFER *nb;\n-\n- nb = NET_BUFFER_LIST_FIRST_NB(_pNB);\n- ASSERT(nb);\n- while(nb) {\n- length += NET_BUFFER_DATA_LENGTH(nb);\n- nb = NET_BUFFER_NEXT_NB(nb);\n- }\n-\n- return length;\n-}\n-\n-/*\n- * Returns the ctl field from the TCP header in 'packet', or 0 if the field\n- * can't be read. The caller must have ensured that 'packet' contains a TCP\n- * header.\n- *\n- * We can't just use TCPHdr, from netProto.h, for this because that\n- * breaks the flags down into individual bit-fields. We can't even use\n- * offsetof because that will try to take the address of a bit-field,\n- * which C does not allow.\n- */\n-static UINT16\n-OvsGetTcpCtl(const NET_BUFFER_LIST *packet, // IN\n- const POVS_PACKET_HDR_INFO layers) // IN\n-{\n-#define TCP_CTL_OFS 12 // Offset of \"ctl\" field in TCP header.\n-#define TCP_FLAGS(CTL) ((CTL) & 0x3f) // Obtain TCP flags from CTL.\n-\n- const UINT16 *ctl;\n- UINT16 storage;\n-\n- ctl = OvsGetPacketBytes(packet, sizeof *ctl, layers->l4Offset + TCP_CTL_OFS,\n- &storage);\n- return ctl ? *ctl : 0;\n-}\n-\n-\n-static UINT8\n-OvsGetTcpFlags(const NET_BUFFER_LIST *packet, // IN\n- const OvsFlowKey *key, // IN\n- const POVS_PACKET_HDR_INFO layers) // IN\n-{\n- UNREFERENCED_PARAMETER(key); // should be removed later\n-\n- if (layers->isTcp) {\n- return TCP_FLAGS(OvsGetTcpCtl(packet, layers));\n- } else {\n- return 0;\n- }\n-}\n-\n-static const EtherArp *\n-OvsGetArp(const NET_BUFFER_LIST *packet,\n- UINT32 ofs,\n- EtherArp *storage)\n-{\n- return OvsGetPacketBytes(packet, sizeof *storage, ofs, storage);\n-}\n-\n-static const IPHdr *\n-OvsGetIp(const NET_BUFFER_LIST *packet,\n- UINT32 ofs,\n- IPHdr *storage)\n-{\n- const IPHdr *ip = OvsGetPacketBytes(packet, sizeof *ip, ofs, storage);\n- if (ip) {\n- int ipLen = ip->ihl * 4;\n- if (ipLen < MIN_IPV4_HLEN ||\n- ipLen > MAX_IPV4_HLEN ||\n- OvsPacketLenNBL(packet) < ofs + ipLen) {\n- /* IP header is invalid, flag it */\n- return NULL;\n- } else {\n- return ip;\n- }\n- }\n- return NULL;\n-}\n-\n-static const TCPHdr *\n-OvsGetTcp(const NET_BUFFER_LIST *packet,\n- UINT32 ofs,\n- TCPHdr *storage)\n-{\n- const TCPHdr *tcp = OvsGetPacketBytes(packet, sizeof *tcp, ofs, storage);\n- if (tcp) {\n- int tcpLen = tcp->doff * 4;\n- if (tcpLen >= sizeof *tcp && OvsPacketLenNBL(packet) >= ofs + tcpLen) {\n- return tcp;\n- }\n- }\n- return NULL;\n-}\n-\n-static const UDPHdr *\n-OvsGetUdp(const NET_BUFFER_LIST *packet,\n- UINT32 ofs,\n- UDPHdr *storage)\n-{\n- return OvsGetPacketBytes(packet, sizeof *storage, ofs, storage);\n-}\n-\n-static const SCTPHdr *\n-OvsGetSctp(const NET_BUFFER_LIST *packet,\n- UINT32 ofs,\n- SCTPHdr *storage)\n-{\n- return OvsGetPacketBytes(packet, sizeof *storage, ofs, storage);\n-}\n-\n-static const ICMPHdr *\n-OvsGetIcmp(const NET_BUFFER_LIST *packet,\n- UINT32 ofs,\n- ICMPHdr *storage)\n-{\n- return OvsGetPacketBytes(packet, sizeof *storage, ofs, storage);\n-}\n-\n-static const MPLSHdr *\n-OvsGetMpls(const NET_BUFFER_LIST *packet,\n- UINT32 ofs,\n- MPLSHdr *storage)\n-{\n- return OvsGetPacketBytes(packet, sizeof *storage, ofs, storage);\n-}\n-#endif /* __PACKET_PARSER_H_ */\ndiff --git a/datapath-windows/ovsext/Recirc.c b/datapath-windows/ovsext/Recirc.c\ndeleted file mode 100644\nindex 7a688c874..000000000\n--- a/datapath-windows/ovsext/Recirc.c\n+++ /dev/null\n@@ -1,344 +0,0 @@\n-/*\n- * Copyright (c) 2016 Cloudbase Solutions Srl\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#include \"Recirc.h\"\n-#include \"Flow.h\"\n-#include \"Jhash.h\"\n-\n-/*\n- * --------------------------------------------------------------------------\n- * '_OVS_DEFERRED_ACTION_QUEUE' structure is responsible for keeping track of\n- * all deferred actions. The maximum number of deferred actions should not\n- * exceed 'DEFERRED_ACTION_QUEUE_SIZE'.\n- * --------------------------------------------------------------------------\n- */\n-typedef struct _OVS_DEFERRED_ACTION_QUEUE {\n- UINT32 head;\n- UINT32 tail;\n- OVS_DEFERRED_ACTION deferredActions[DEFERRED_ACTION_QUEUE_SIZE];\n-} OVS_DEFERRED_ACTION_QUEUE, *POVS_DEFERRED_ACTION_QUEUE;\n-\n-typedef struct _OVS_DEFERRED_ACTION_DATA {\n- OVS_DEFERRED_ACTION_QUEUE queue;\n- UINT32 level;\n-} OVS_DEFERRED_ACTION_DATA, *POVS_DEFERRED_ACTION_DATA;\n-\n-static POVS_DEFERRED_ACTION_DATA deferredData = NULL;\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsDeferredActionsInit --\n- * The function allocates all necessary deferred actions resources.\n- * --------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsDeferredActionsInit()\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n- ULONG count = KeQueryMaximumProcessorCountEx(ALL_PROCESSOR_GROUPS);\n-\n- deferredData = OvsAllocateMemoryPerCpu(sizeof(*deferredData),\n- count,\n- OVS_RECIRC_POOL_TAG);\n- if (!deferredData) {\n- status = NDIS_STATUS_RESOURCES;\n- }\n-\n- return status;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsDeferredActionsCleanup --\n- * The function frees all deferred actions resources.\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-OvsDeferredActionsCleanup()\n-{\n- if (deferredData) {\n- OvsFreeMemoryWithTag(deferredData, OVS_RECIRC_POOL_TAG);\n- deferredData = NULL;\n- }\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsDeferredActionsQueueGet --\n- * The function returns the deferred action queue corresponding to the\n- * current processor.\n- * --------------------------------------------------------------------------\n- */\n-POVS_DEFERRED_ACTION_QUEUE\n-OvsDeferredActionsQueueGet()\n-{\n- POVS_DEFERRED_ACTION_QUEUE queue = NULL;\n- ULONG index = 0;\n- KIRQL oldIrql = KeGetCurrentIrql();\n-\n- if (oldIrql < DISPATCH_LEVEL) {\n- KeRaiseIrqlToDpcLevel();\n- }\n-\n- index = KeGetCurrentProcessorNumberEx(NULL);\n- queue = &deferredData[index].queue;\n-\n- if (oldIrql < DISPATCH_LEVEL) {\n- KeLowerIrql(oldIrql);\n- }\n-\n- return queue;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsDeferredActionsLevelGet --\n- * The function returns the deferred action execution level corresponding\n- * to the current processor.\n- * --------------------------------------------------------------------------\n- */\n-UINT32\n-OvsDeferredActionsLevelGet()\n-{\n- UINT32 level = 0;\n- ULONG index = 0;\n- KIRQL oldIrql = KeGetCurrentIrql();\n-\n- if (oldIrql < DISPATCH_LEVEL) {\n- KeRaiseIrqlToDpcLevel();\n- }\n-\n- index = KeGetCurrentProcessorNumberEx(NULL);\n- level = deferredData[index].level;\n-\n- if (oldIrql < DISPATCH_LEVEL) {\n- KeLowerIrql(oldIrql);\n- }\n-\n- return level;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsDeferredActionsLevelInc --\n- * The function increments the deferred action execution level\n- * corresponding to the current processor.\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-OvsDeferredActionsLevelInc()\n-{\n- ULONG index = 0;\n- KIRQL oldIrql = KeGetCurrentIrql();\n-\n- if (oldIrql < DISPATCH_LEVEL) {\n- KeRaiseIrqlToDpcLevel();\n- }\n-\n- index = KeGetCurrentProcessorNumberEx(NULL);\n- deferredData[index].level++;\n-\n- if (oldIrql < DISPATCH_LEVEL) {\n- KeLowerIrql(oldIrql);\n- }\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsDeferredActionsLevelDec --\n- * The function decrements the deferred action execution level\n- * corresponding to the current processor.\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-OvsDeferredActionsLevelDec()\n-{\n- ULONG index = 0;\n- KIRQL oldIrql = KeGetCurrentIrql();\n-\n- if (oldIrql < DISPATCH_LEVEL) {\n- KeRaiseIrqlToDpcLevel();\n- }\n-\n- index = KeGetCurrentProcessorNumberEx(NULL);\n- deferredData[index].level--;\n-\n- if (oldIrql < DISPATCH_LEVEL) {\n- KeLowerIrql(oldIrql);\n- }\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsDeferredActionsQueueInit --\n- * The function resets the queue to be ready for the next packet.\n- * --------------------------------------------------------------------------\n- */\n-static\n-VOID\n-OvsDeferredActionsQueueInit(POVS_DEFERRED_ACTION_QUEUE queue)\n-{\n- queue->head = 0;\n- queue->tail = 0;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsDeferredActionsQueueIsEmpty --\n- * The function verifies if the queue is empty.\n- * --------------------------------------------------------------------------\n- */\n-static\n-BOOLEAN\n-OvsDeferredActionsQueueIsEmpty(const POVS_DEFERRED_ACTION_QUEUE queue)\n-{\n- return (queue->head == queue->tail);\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsDeferredActionsQueuePop --\n- * The function pops the next queue element.\n- * --------------------------------------------------------------------------\n- */\n-static\n-POVS_DEFERRED_ACTION\n-OvsDeferredActionsQueuePop(POVS_DEFERRED_ACTION_QUEUE queue)\n-{\n- POVS_DEFERRED_ACTION deferredAction = NULL;\n- KIRQL oldIrql = KeGetCurrentIrql();\n-\n- if (oldIrql < DISPATCH_LEVEL) {\n- KeRaiseIrqlToDpcLevel();\n- }\n-\n- if (OvsDeferredActionsQueueIsEmpty(queue)) {\n- /* Reset the queue for the next packet. */\n- OvsDeferredActionsQueueInit(queue);\n- } else {\n- deferredAction = &queue->deferredActions[queue->tail++];\n- }\n-\n- if (oldIrql < DISPATCH_LEVEL) {\n- KeLowerIrql(oldIrql);\n- }\n-\n- return deferredAction;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsDeferredActionsQueuePush --\n- * The function pushes the current element in the deferred actions queue.\n- * --------------------------------------------------------------------------\n- */\n-static\n-POVS_DEFERRED_ACTION\n-OvsDeferredActionsQueuePush(POVS_DEFERRED_ACTION_QUEUE queue)\n-{\n- POVS_DEFERRED_ACTION deferredAction = NULL;\n- KIRQL oldIrql = KeGetCurrentIrql();\n-\n- if (oldIrql < DISPATCH_LEVEL) {\n- KeRaiseIrqlToDpcLevel();\n- }\n-\n- if (queue->head < DEFERRED_ACTION_QUEUE_SIZE) {\n- deferredAction = &queue->deferredActions[queue->head++];\n- }\n-\n- if (oldIrql < DISPATCH_LEVEL) {\n- KeLowerIrql(oldIrql);\n- }\n-\n- return deferredAction;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsAddDeferredActions --\n- * This function adds the deferred action to the current CPU queue and\n- * returns the new queue entry if the queue is not already full.\n- * --------------------------------------------------------------------------\n- */\n-POVS_DEFERRED_ACTION\n-OvsAddDeferredActions(PNET_BUFFER_LIST nbl,\n- OvsFlowKey *key,\n- POVS_PACKET_HDR_INFO layers,\n- const PNL_ATTR actions)\n-{\n- POVS_DEFERRED_ACTION_QUEUE queue = OvsDeferredActionsQueueGet();\n- POVS_DEFERRED_ACTION deferredAction = NULL;\n- OVS_PACKET_HDR_INFO layersInit = { 0 };\n-\n- deferredAction = OvsDeferredActionsQueuePush(queue);\n- if (deferredAction) {\n- deferredAction->nbl = nbl;\n- deferredAction->actions = actions;\n- deferredAction->key = *key;\n- if (layers) {\n- deferredAction->layers = *layers;\n- } else {\n- deferredAction->layers = layersInit;\n- }\n- }\n-\n- return deferredAction;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsProcessDeferredActions --\n- * This function processes all deferred actions contained in the queue\n- * corresponding to the current CPU.\n- * --------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsProcessDeferredActions(POVS_SWITCH_CONTEXT switchContext,\n- OvsCompletionList *completionList,\n- UINT32 portNo,\n- ULONG sendFlags)\n-{\n- NDIS_STATUS status = NDIS_STATUS_SUCCESS;\n- POVS_DEFERRED_ACTION_QUEUE queue = OvsDeferredActionsQueueGet();\n- POVS_DEFERRED_ACTION deferredAction = NULL;\n- POVS_PACKET_HDR_INFO layersDeferred = NULL;\n-\n- /* Process all deferred actions. */\n- while ((deferredAction = OvsDeferredActionsQueuePop(queue)) != NULL) {\n- layersDeferred = &(deferredAction->layers);\n-\n- if (deferredAction->actions) {\n- status = OvsDoExecuteActions(switchContext,\n- completionList,\n- deferredAction->nbl,\n- portNo,\n- sendFlags,\n- &deferredAction->key, NULL,\n- layersDeferred, deferredAction->actions,\n- NlAttrGetSize(deferredAction->actions));\n- } else {\n- status = OvsDoRecirc(switchContext,\n- completionList,\n- deferredAction->nbl,\n- &deferredAction->key,\n- portNo,\n- layersDeferred);\n- }\n- }\n-\n- return status;\n-}\ndiff --git a/datapath-windows/ovsext/Recirc.h b/datapath-windows/ovsext/Recirc.h\ndeleted file mode 100644\nindex b2d02a65c..000000000\n--- a/datapath-windows/ovsext/Recirc.h\n+++ /dev/null\n@@ -1,107 +0,0 @@\n-/*\n- * Copyright (c) 2016 Cloudbase Solutions Srl\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#ifndef __RECIRC_H_\n-#define __RECIRC_H_ 1\n-\n-#include \"Actions.h\"\n-#include \"NetProto.h\"\n-\n-#define DEFERRED_ACTION_QUEUE_SIZE 10\n-#define DEFERRED_ACTION_EXEC_LEVEL 4\n-\n-typedef struct _OVS_DEFERRED_ACTION {\n- PNET_BUFFER_LIST nbl;\n- PNL_ATTR actions;\n- OvsFlowKey key;\n- OVS_PACKET_HDR_INFO layers;\n-} OVS_DEFERRED_ACTION, *POVS_DEFERRED_ACTION;\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsProcessDeferredActions --\n- * This function processes all deferred actions contained in the queue\n- * corresponding to the current CPU.\n- * --------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsProcessDeferredActions(POVS_SWITCH_CONTEXT switchContext,\n- OvsCompletionList *completionList,\n- UINT32 portNo,\n- ULONG sendFlags);\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsAddDeferredActions --\n- * This function adds the deferred action to the current CPU queue and\n- * returns the new queue entry if the queue is not already full.\n- * --------------------------------------------------------------------------\n- */\n-POVS_DEFERRED_ACTION\n-OvsAddDeferredActions(PNET_BUFFER_LIST packet,\n- OvsFlowKey *key,\n- POVS_PACKET_HDR_INFO layers,\n- const PNL_ATTR actions);\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsDeferredActionsInit --\n- * The function allocates all necessary deferred actions resources.\n- * --------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsDeferredActionsInit();\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsDeferredActionsCleanup --\n- * The function frees all deferred actions resources.\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-OvsDeferredActionsCleanup();\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsDeferredActionsLevelGet --\n- * The function returns the deferred action execution level corresponding\n- * to the current processor.\n- * --------------------------------------------------------------------------\n- */\n-UINT32\n-OvsDeferredActionsLevelGet();\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsDeferredActionsLevelInc --\n- * The function increments the deferred action execution level\n- * corresponding to the current processor.\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-OvsDeferredActionsLevelInc();\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsDeferredActionsLevelDec --\n- * The function decrements the deferred action execution level\n- * corresponding to the current processor.\n- * --------------------------------------------------------------------------\n-*/\n-VOID\n-OvsDeferredActionsLevelDec();\n-\n-#endif /* __RECIRC_H_ */\ndiff --git a/datapath-windows/ovsext/Switch.c b/datapath-windows/ovsext/Switch.c\ndeleted file mode 100644\nindex 294c6773d..000000000\n--- a/datapath-windows/ovsext/Switch.c\n+++ /dev/null\n@@ -1,649 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-/*\n- * This file contains the implementation of the management functionality of the\n- * OVS.\n- */\n-\n-#include \"precomp.h\"\n-#include \"Conntrack.h\"\n-#include \"Switch.h\"\n-#include \"Vport.h\"\n-#include \"Event.h\"\n-#include \"Meter.h\"\n-#include \"Flow.h\"\n-#include \"IpHelper.h\"\n-#include \"Oid.h\"\n-#include \"IpFragment.h\"\n-#include \"Ip6Fragment.h\"\n-\n-#ifdef OVS_DBG_MOD\n-#undef OVS_DBG_MOD\n-#endif\n-#define OVS_DBG_MOD OVS_DBG_SWITCH\n-#include \"Debug.h\"\n-\n-POVS_SWITCH_CONTEXT gOvsSwitchContext;\n-LONG volatile gOvsInAttach;\n-UINT64 ovsTimeIncrementPerTick;\n-\n-extern NDIS_HANDLE gOvsExtDriverHandle;\n-extern NDIS_HANDLE gOvsExtDriverObject;\n-extern PDEVICE_OBJECT gOvsDeviceObject;\n-\n-/*\n- * Reference count used to prevent premature deallocation of the global switch\n- * context structure, gOvsSwitchContext.\n- */\n-volatile LONG gOvsSwitchContextRefCount = 0;\n-\n-static NDIS_STATUS OvsCreateSwitch(NDIS_HANDLE ndisFilterHandle,\n- POVS_SWITCH_CONTEXT *switchContextOut);\n-static NDIS_STATUS OvsInitSwitchContext(POVS_SWITCH_CONTEXT switchContext);\n-static VOID OvsDeleteSwitch(POVS_SWITCH_CONTEXT switchContext);\n-static VOID OvsUninitSwitchContext(POVS_SWITCH_CONTEXT switchContext);\n-static NDIS_STATUS OvsActivateSwitch(POVS_SWITCH_CONTEXT switchContext);\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Implements filter driver's FilterAttach function.\n- *\n- * This function allocates the switch context, and initializes its necessary\n- * members.\n- * --------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsExtAttach(NDIS_HANDLE ndisFilterHandle,\n- NDIS_HANDLE filterDriverContext,\n- PNDIS_FILTER_ATTACH_PARAMETERS attachParameters)\n-{\n- NDIS_STATUS status = NDIS_STATUS_FAILURE;\n- NDIS_FILTER_ATTRIBUTES ovsExtAttributes;\n- POVS_SWITCH_CONTEXT switchContext = NULL;\n-\n- UNREFERENCED_PARAMETER(filterDriverContext);\n-\n- OVS_LOG_TRACE(\"Enter: ndisFilterHandle %p\", ndisFilterHandle);\n-\n- ASSERT(filterDriverContext == (NDIS_HANDLE)gOvsExtDriverObject);\n- if (attachParameters->MiniportMediaType != NdisMedium802_3) {\n- status = NDIS_STATUS_INVALID_PARAMETER;\n- goto cleanup;\n- }\n-\n- if (gOvsExtDriverHandle == NULL) {\n- OVS_LOG_TRACE(\"Exit: OVSEXT driver is not loaded.\");\n- ASSERT(FALSE);\n- goto cleanup;\n- }\n-\n- if (gOvsSwitchContext) {\n- OVS_LOG_TRACE(\"Exit: Failed to create OVS Switch, only one datapath is\"\n- \"supported, %p.\", gOvsSwitchContext);\n- goto cleanup;\n- }\n-\n- if (InterlockedCompareExchange(&gOvsInAttach, 1, 0)) {\n- /* Just fail the request. */\n- OVS_LOG_TRACE(\"Exit: Failed to create OVS Switch, since another attach\"\n- \"instance is in attach process.\");\n- goto cleanup;\n- }\n-\n- status = OvsInitIpHelper(ndisFilterHandle);\n- if (status != STATUS_SUCCESS) {\n- OVS_LOG_ERROR(\"Exit: Failed to initialize IP helper.\");\n- goto cleanup;\n- }\n-\n- status = OvsCreateSwitch(ndisFilterHandle, &switchContext);\n- if (status != NDIS_STATUS_SUCCESS) {\n- OvsCleanupIpHelper();\n- goto cleanup;\n- }\n- ASSERT(switchContext);\n-\n- /*\n- * Register the switch context with NDIS so NDIS can pass it back to the\n- * FilterXXX callback functions as the 'FilterModuleContext' parameter.\n- */\n- RtlZeroMemory(&ovsExtAttributes, sizeof(NDIS_FILTER_ATTRIBUTES));\n- ovsExtAttributes.Header.Revision = NDIS_FILTER_ATTRIBUTES_REVISION_1;\n- ovsExtAttributes.Header.Size = sizeof(NDIS_FILTER_ATTRIBUTES);\n- ovsExtAttributes.Header.Type = NDIS_OBJECT_TYPE_FILTER_ATTRIBUTES;\n- ovsExtAttributes.Flags = 0;\n-\n- NDIS_DECLARE_FILTER_MODULE_CONTEXT(OVS_SWITCH_CONTEXT);\n- status = NdisFSetAttributes(ndisFilterHandle, switchContext, &ovsExtAttributes);\n- if (status != NDIS_STATUS_SUCCESS) {\n- OVS_LOG_ERROR(\"Failed to set attributes.\");\n- OvsCleanupIpHelper();\n- goto cleanup;\n- }\n-\n- /* Setup the state machine. */\n- switchContext->controlFlowState = OvsSwitchAttached;\n- switchContext->dataFlowState = OvsSwitchPaused;\n-\n- gOvsSwitchContextRefCount = 1;\n- gOvsSwitchContext = switchContext;\n- KeMemoryBarrier();\n-\n-cleanup:\n- InterlockedExchange(&gOvsInAttach, 0);\n- if (status != NDIS_STATUS_SUCCESS) {\n- if (switchContext != NULL) {\n- OvsDeleteSwitch(switchContext);\n- }\n- }\n- OVS_LOG_TRACE(\"Exit: status %x\", status);\n-\n- return status;\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * This function allocated the switch context, and initializes its necessary\n- * members.\n- * --------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsCreateSwitch(NDIS_HANDLE ndisFilterHandle,\n- POVS_SWITCH_CONTEXT *switchContextOut)\n-{\n- NDIS_STATUS status;\n- POVS_SWITCH_CONTEXT switchContext;\n- NDIS_SWITCH_CONTEXT hostSwitchContext;\n- NDIS_SWITCH_OPTIONAL_HANDLERS hostSwitchHandler;\n-\n- OVS_LOG_TRACE(\"Enter: Create switch object\");\n-\n- switchContext = (POVS_SWITCH_CONTEXT) OvsAllocateMemoryWithTag(\n- sizeof(OVS_SWITCH_CONTEXT), OVS_SWITCH_POOL_TAG);\n- if (switchContext == NULL) {\n- status = NDIS_STATUS_RESOURCES;\n- goto create_switch_done;\n- }\n- RtlZeroMemory(switchContext, sizeof(OVS_SWITCH_CONTEXT));\n-\n- /* Initialize the switch. */\n- hostSwitchHandler.Header.Type = NDIS_OBJECT_TYPE_SWITCH_OPTIONAL_HANDLERS;\n- hostSwitchHandler.Header.Size = NDIS_SIZEOF_SWITCH_OPTIONAL_HANDLERS_REVISION_1;\n- hostSwitchHandler.Header.Revision = NDIS_SWITCH_OPTIONAL_HANDLERS_REVISION_1;\n-\n- status = NdisFGetOptionalSwitchHandlers(ndisFilterHandle,\n- &hostSwitchContext,\n- &hostSwitchHandler);\n- if (status != NDIS_STATUS_SUCCESS) {\n- OVS_LOG_ERROR(\"OvsExtAttach: Extension is running in \"\n- \"non-switch environment.\");\n- OvsFreeMemoryWithTag(switchContext, OVS_SWITCH_POOL_TAG);\n- goto create_switch_done;\n- }\n-\n- switchContext->NdisFilterHandle = ndisFilterHandle;\n- switchContext->NdisSwitchContext = hostSwitchContext;\n- RtlCopyMemory(&switchContext->NdisSwitchHandlers, &hostSwitchHandler,\n- sizeof(NDIS_SWITCH_OPTIONAL_HANDLERS));\n-\n- status = OvsInitSwitchContext(switchContext);\n- if (status != NDIS_STATUS_SUCCESS) {\n- OvsFreeMemoryWithTag(switchContext, OVS_SWITCH_POOL_TAG);\n- switchContext = NULL;\n- goto create_switch_done;\n- }\n-\n- status = OvsInitTunnelFilter(gOvsExtDriverObject, gOvsDeviceObject);\n- if (status != NDIS_STATUS_SUCCESS) {\n- OvsUninitSwitchContext(switchContext);\n- goto create_switch_done;\n- }\n-\n- status = OvsInitConntrack(switchContext);\n- if (status != STATUS_SUCCESS) {\n- OvsUninitSwitchContext(switchContext);\n- OVS_LOG_ERROR(\"Exit: Failed to initialize Connection tracking\");\n- goto create_switch_done;\n- }\n-\n- status = OvsInitCtRelated(switchContext);\n- if (status != STATUS_SUCCESS) {\n- OvsUninitSwitchContext(switchContext);\n- OVS_LOG_ERROR(\"Exit: Failed to initialize Connection tracking\");\n- }\n-\n- status = OvsInitIpFragment(switchContext);\n- if (status != STATUS_SUCCESS) {\n- OvsUninitSwitchContext(switchContext);\n- OVS_LOG_ERROR(\"Exit: Failed to initialize Ip Fragment\");\n- goto create_switch_done;\n- }\n-\n- status = OvsInitIp6Fragment(switchContext);\n- if (status != STATUS_SUCCESS) {\n- OvsUninitSwitchContext(switchContext);\n- OVS_LOG_ERROR(\"Exit: Failed to initialize Ip6 Fragment\");\n- goto create_switch_done;\n- }\n- \n- status = OvsInitMeter(switchContext);\n- if (status != STATUS_SUCCESS) {\n- OvsUninitSwitchContext(switchContext);\n- OVS_LOG_ERROR(\"Exit: Failed to initialize Ovs meter.\");\n- goto create_switch_done;\n- }\n-\n- *switchContextOut = switchContext;\n-\n-create_switch_done:\n- OVS_LOG_TRACE(\"Exit: switchContext: %p status: %#lx\",\n- switchContext, status);\n- return status;\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Implements filter driver's FilterDetach function.\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-OvsExtDetach(NDIS_HANDLE filterModuleContext)\n-{\n- POVS_SWITCH_CONTEXT switchContext = (POVS_SWITCH_CONTEXT)filterModuleContext;\n-\n- OVS_LOG_TRACE(\"Enter: filterModuleContext %p\", filterModuleContext);\n-\n- ASSERT(switchContext->dataFlowState == OvsSwitchPaused);\n- switchContext->controlFlowState = OvsSwitchDetached;\n- KeMemoryBarrier();\n- while(switchContext->pendingOidCount > 0) {\n- NdisMSleep(1000);\n- }\n- OvsDeleteSwitch(switchContext);\n- OvsCleanupIpHelper();\n- OvsCleanupConntrack();\n- OvsCleanupCtRelated();\n- OvsCleanupIpFragment();\n- OvsCleanupIp6Fragment();\n-\n- /* This completes the cleanup, and a new attach can be handled now. */\n-\n- OVS_LOG_TRACE(\"Exit: OvsDetach Successfully\");\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * This function deletes the switch by freeing all memory previously allocated.\n- * XXX need synchronization with other path.\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-OvsDeleteSwitch(POVS_SWITCH_CONTEXT switchContext)\n-{\n- UINT32 dpNo = (UINT32) -1;\n-\n- OVS_LOG_TRACE(\"Enter: switchContext:%p\", switchContext);\n-\n- if (switchContext)\n- {\n- dpNo = switchContext->dpNo;\n- OvsClearAllSwitchVports(switchContext);\n- OvsUninitTunnelFilter(gOvsExtDriverObject);\n- OvsUninitSwitchContext(switchContext);\n- }\n- OVS_LOG_TRACE(\"Exit: deleted switch %p dpNo: %d\", switchContext, dpNo);\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Implements filter driver's FilterRestart function.\n- * --------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsExtRestart(NDIS_HANDLE filterModuleContext,\n- PNDIS_FILTER_RESTART_PARAMETERS filterRestartParameters)\n-{\n- POVS_SWITCH_CONTEXT switchContext = (POVS_SWITCH_CONTEXT)filterModuleContext;\n- NDIS_STATUS status = NDIS_STATUS_SUCCESS;\n- BOOLEAN switchActive;\n-\n- UNREFERENCED_PARAMETER(filterRestartParameters);\n-\n- OVS_LOG_TRACE(\"Enter: filterModuleContext %p\",\n- filterModuleContext);\n-\n- /* Activate the switch if this is the first restart. */\n- if (!switchContext->isActivated && !switchContext->isActivateFailed) {\n- status = OvsQuerySwitchActivationComplete(switchContext,\n- &switchActive);\n- if (status != NDIS_STATUS_SUCCESS) {\n- switchContext->isActivateFailed = TRUE;\n- status = NDIS_STATUS_RESOURCES;\n- goto cleanup;\n- }\n-\n- if (switchActive) {\n- status = OvsActivateSwitch(switchContext);\n-\n- if (status != NDIS_STATUS_SUCCESS) {\n- OVS_LOG_WARN(\"Failed to activate switch, dpNo:%d\",\n- switchContext->dpNo);\n- status = NDIS_STATUS_RESOURCES;\n- goto cleanup;\n- }\n- }\n- }\n-\n- ASSERT(switchContext->dataFlowState == OvsSwitchPaused);\n- switchContext->dataFlowState = OvsSwitchRunning;\n-\n-cleanup:\n- OVS_LOG_TRACE(\"Exit: Restart switch:%p, dpNo: %d, status: %#x\",\n- switchContext, switchContext->dpNo, status);\n- return status;\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Implements filter driver's FilterPause function\n- * --------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsExtPause(NDIS_HANDLE filterModuleContext,\n- PNDIS_FILTER_PAUSE_PARAMETERS pauseParameters)\n-{\n- POVS_SWITCH_CONTEXT switchContext = (POVS_SWITCH_CONTEXT)filterModuleContext;\n-\n- UNREFERENCED_PARAMETER(pauseParameters);\n- OVS_LOG_TRACE(\"Enter: filterModuleContext %p\",\n- filterModuleContext);\n-\n- switchContext->dataFlowState = OvsSwitchPaused;\n- KeMemoryBarrier();\n- while(switchContext->pendingOidCount > 0) {\n- NdisMSleep(1000);\n- }\n-\n- OVS_LOG_TRACE(\"Exit: OvsExtPause Successfully\");\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-static NDIS_STATUS\n-OvsInitSwitchContext(POVS_SWITCH_CONTEXT switchContext)\n-{\n- int i;\n- NTSTATUS status;\n-\n- OVS_LOG_TRACE(\"Enter: switchContext: %p\", switchContext);\n-\n- switchContext->dispatchLock =\n- NdisAllocateRWLock(switchContext->NdisFilterHandle);\n-\n- switchContext->portNoHashArray = (PLIST_ENTRY)OvsAllocateMemoryWithTag(\n- sizeof(LIST_ENTRY) * OVS_MAX_VPORT_ARRAY_SIZE, OVS_SWITCH_POOL_TAG);\n- switchContext->ovsPortNameHashArray = (PLIST_ENTRY)OvsAllocateMemoryWithTag(\n- sizeof(LIST_ENTRY) * OVS_MAX_VPORT_ARRAY_SIZE, OVS_SWITCH_POOL_TAG);\n- switchContext->portIdHashArray= (PLIST_ENTRY)OvsAllocateMemoryWithTag(\n- sizeof(LIST_ENTRY) * OVS_MAX_VPORT_ARRAY_SIZE, OVS_SWITCH_POOL_TAG);\n- switchContext->pidHashArray = (PLIST_ENTRY)OvsAllocateMemoryWithTag(\n- sizeof(LIST_ENTRY) * OVS_MAX_PID_ARRAY_SIZE, OVS_SWITCH_POOL_TAG);\n- switchContext->tunnelVportsArray = (PLIST_ENTRY)OvsAllocateMemoryWithTag(\n- sizeof(LIST_ENTRY) * OVS_MAX_VPORT_ARRAY_SIZE, OVS_SWITCH_POOL_TAG);\n- status = OvsAllocateFlowTable(&switchContext->datapath, switchContext);\n-\n- if (status == NDIS_STATUS_SUCCESS) {\n- status = OvsInitBufferPool(switchContext);\n- }\n- if (status != NDIS_STATUS_SUCCESS ||\n- switchContext->dispatchLock == NULL ||\n- switchContext->portNoHashArray == NULL ||\n- switchContext->ovsPortNameHashArray == NULL ||\n- switchContext->portIdHashArray== NULL ||\n- switchContext->pidHashArray == NULL ||\n- switchContext->tunnelVportsArray == NULL) {\n- if (switchContext->dispatchLock) {\n- NdisFreeRWLock(switchContext->dispatchLock);\n- }\n- if (switchContext->portNoHashArray) {\n- OvsFreeMemoryWithTag(switchContext->portNoHashArray,\n- OVS_SWITCH_POOL_TAG);\n- }\n- if (switchContext->ovsPortNameHashArray) {\n- OvsFreeMemoryWithTag(switchContext->ovsPortNameHashArray,\n- OVS_SWITCH_POOL_TAG);\n- }\n- if (switchContext->portIdHashArray) {\n- OvsFreeMemoryWithTag(switchContext->portIdHashArray,\n- OVS_SWITCH_POOL_TAG);\n- }\n- if (switchContext->pidHashArray) {\n- OvsFreeMemoryWithTag(switchContext->pidHashArray,\n- OVS_SWITCH_POOL_TAG);\n- }\n-\n- if (switchContext->tunnelVportsArray) {\n- OvsFreeMemory(switchContext->tunnelVportsArray);\n- }\n-\n- OvsDeleteFlowTable(&switchContext->datapath);\n- OvsCleanupBufferPool(switchContext);\n-\n- OVS_LOG_TRACE(\"Exit: Failed to init switchContext\");\n- return NDIS_STATUS_RESOURCES;\n- }\n-\n- for (i = 0; i < OVS_MAX_VPORT_ARRAY_SIZE; i++) {\n- InitializeListHead(&switchContext->ovsPortNameHashArray[i]);\n- InitializeListHead(&switchContext->portIdHashArray[i]);\n- InitializeListHead(&switchContext->portNoHashArray[i]);\n- InitializeListHead(&switchContext->tunnelVportsArray[i]);\n- }\n-\n- for (i = 0; i < OVS_MAX_PID_ARRAY_SIZE; i++) {\n- InitializeListHead(&switchContext->pidHashArray[i]);\n- }\n-\n- NdisAllocateSpinLock(&(switchContext->pidHashLock));\n- switchContext->isActivated = FALSE;\n- switchContext->isActivateFailed = FALSE;\n- switchContext->dpNo = OVS_DP_NUMBER;\n- ovsTimeIncrementPerTick = KeQueryTimeIncrement() / 10000;\n-\n- OVS_LOG_TRACE(\"Exit: Succesfully initialized switchContext: %p\",\n- switchContext);\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-static VOID\n-OvsUninitSwitchContext(POVS_SWITCH_CONTEXT switchContext)\n-{\n- OvsReleaseSwitchContext(switchContext);\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Frees up the contents of and also the switch context.\n- * --------------------------------------------------------------------------\n- */\n-static VOID\n-OvsDeleteSwitchContext(POVS_SWITCH_CONTEXT switchContext)\n-{\n- OVS_LOG_TRACE(\"Enter: Delete switchContext:%p\", switchContext);\n-\n- /* We need to do cleanup for tunnel port here. */\n- ASSERT(switchContext->numHvVports == 0);\n- ASSERT(switchContext->numNonHvVports == 0);\n-\n- NdisFreeRWLock(switchContext->dispatchLock);\n- switchContext->dispatchLock = NULL;\n- NdisFreeSpinLock(&(switchContext->pidHashLock));\n- OvsFreeMemoryWithTag(switchContext->ovsPortNameHashArray,\n- OVS_SWITCH_POOL_TAG);\n- switchContext->ovsPortNameHashArray = NULL;\n- OvsFreeMemoryWithTag(switchContext->portIdHashArray,\n- OVS_SWITCH_POOL_TAG);\n- switchContext->portIdHashArray = NULL;\n- OvsFreeMemoryWithTag(switchContext->portNoHashArray,\n- OVS_SWITCH_POOL_TAG);\n- switchContext->portNoHashArray = NULL;\n- OvsFreeMemoryWithTag(switchContext->pidHashArray,\n- OVS_SWITCH_POOL_TAG);\n- switchContext->pidHashArray = NULL;\n- OvsFreeMemory(switchContext->tunnelVportsArray);\n- switchContext->tunnelVportsArray = NULL;\n- OvsDeleteFlowTable(&switchContext->datapath);\n- OvsCleanupBufferPool(switchContext);\n-\n- OvsFreeMemoryWithTag(switchContext, OVS_SWITCH_POOL_TAG);\n- OVS_LOG_TRACE(\"Exit: Delete switchContext: %p\", switchContext);\n-}\n-\n-VOID\n-OvsReleaseSwitchContext(POVS_SWITCH_CONTEXT switchContext)\n-{\n- LONG ref = 0;\n- LONG newRef = 0;\n- LONG icxRef = 0;\n-\n- do {\n- ref = InterlockedAdd(&gOvsSwitchContextRefCount, 0);\n- newRef = (0 == ref) ? 0 : ref - 1;\n- icxRef = InterlockedCompareExchange(&gOvsSwitchContextRefCount,\n- newRef,\n- ref);\n- } while (icxRef != ref);\n-\n- if (ref == 1) {\n- OvsDeleteSwitchContext(switchContext);\n- gOvsSwitchContext = NULL;\n- }\n-}\n-\n-BOOLEAN\n-OvsAcquireSwitchContext(VOID)\n-{\n- LONG ref = 0;\n- LONG newRef = 0;\n- LONG icxRef = 0;\n- BOOLEAN ret = FALSE;\n-\n- do {\n- ref = InterlockedAdd(&gOvsSwitchContextRefCount, 0);\n- newRef = (0 == ref) ? 0 : ref + 1;\n- icxRef = InterlockedCompareExchange(&gOvsSwitchContextRefCount,\n- newRef,\n- ref);\n- } while (icxRef != ref);\n-\n- if (ref != 0) {\n- ret = TRUE;\n- }\n-\n- return ret;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * This function activates the switch by initializing it with all the runtime\n- * state. First it queries all of the MAC addresses set as custom switch policy\n- * to allow sends from, and adds tme to the property list. Then it queries the\n- * NIC list and verifies it can support all of the NICs currently connected to\n- * the switch, and adds the NICs to the NIC list.\n- * --------------------------------------------------------------------------\n- */\n-static NDIS_STATUS\n-OvsActivateSwitch(POVS_SWITCH_CONTEXT switchContext)\n-{\n- NDIS_STATUS status;\n-\n- ASSERT(!switchContext->isActivated);\n-\n- switchContext->isActivated = TRUE;\n-\n- OVS_LOG_TRACE(\"Enter: activate switch %p, dpNo: %ld\",\n- switchContext, switchContext->dpNo);\n-\n- status = OvsAddConfiguredSwitchPorts(switchContext);\n-\n- if (status != NDIS_STATUS_SUCCESS) {\n- OVS_LOG_WARN(\"Failed to add configured switch ports\");\n- goto cleanup;\n-\n- }\n- status = OvsInitConfiguredSwitchNics(switchContext);\n-\n- if (status != NDIS_STATUS_SUCCESS) {\n- OVS_LOG_WARN(\"Failed to add configured vports\");\n- OvsClearAllSwitchVports(switchContext);\n- goto cleanup;\n- }\n-\n-cleanup:\n- if (status != NDIS_STATUS_SUCCESS) {\n- switchContext->isActivated = FALSE;\n- }\n-\n- OVS_LOG_TRACE(\"Exit: activate switch:%p, isActivated: %s, status = %lx\",\n- switchContext,\n- (switchContext->isActivated ? \"TRUE\" : \"FALSE\"), status);\n- return status;\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Implements filter driver's FilterNetPnPEvent function.\n- * --------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsExtNetPnPEvent(NDIS_HANDLE filterModuleContext,\n- PNET_PNP_EVENT_NOTIFICATION netPnPEvent)\n-{\n- NDIS_STATUS status = NDIS_STATUS_SUCCESS;\n- POVS_SWITCH_CONTEXT switchContext = (POVS_SWITCH_CONTEXT)filterModuleContext;\n-\n- OVS_LOG_TRACE(\"Enter: filterModuleContext: %p, NetEvent: %d\",\n- filterModuleContext, (netPnPEvent->NetPnPEvent).NetEvent);\n- /*\n- * NetEventSwitchActivate provides an asynchronous notification of\n- * the switch completing activation.\n- */\n- if (netPnPEvent->NetPnPEvent.NetEvent == NetEventSwitchActivate) {\n- ASSERT(switchContext->isActivated == FALSE);\n- if (switchContext->isActivated == FALSE) {\n- status = OvsActivateSwitch(switchContext);\n- OVS_LOG_TRACE(\"OvsExtNetPnPEvent: activated switch: %p \"\n- \"status: %s\", switchContext,\n- status ? \"TRUE\" : \"FALSE\");\n- }\n- } else if (netPnPEvent->NetPnPEvent.NetEvent == NetEventFilterPreDetach) {\n- switchContext->dataFlowState = OvsSwitchPaused;\n- KeMemoryBarrier();\n- }\n-\n- status = NdisFNetPnPEvent(switchContext->NdisFilterHandle,\n- netPnPEvent);\n- OVS_LOG_TRACE(\"Exit: OvsExtNetPnPEvent\");\n-\n- return status;\n-}\ndiff --git a/datapath-windows/ovsext/Switch.h b/datapath-windows/ovsext/Switch.h\ndeleted file mode 100644\nindex 806ee7820..000000000\n--- a/datapath-windows/ovsext/Switch.h\n+++ /dev/null\n@@ -1,233 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-/*\n- * This file contains the definition of the switch object for the OVS.\n- */\n-\n-#ifndef __SWITCH_H_\n-#define __SWITCH_H_ 1\n-\n-#include \"NetProto.h\"\n-#include \"BufferMgmt.h\"\n-#include \"TunnelIntf.h\"\n-#define OVS_MAX_VPORT_ARRAY_SIZE 1024\n-#define OVS_MAX_PID_ARRAY_SIZE 1024\n-\n-#define OVS_VPORT_MASK (OVS_MAX_VPORT_ARRAY_SIZE - 1)\n-#define OVS_PID_MASK (OVS_MAX_PID_ARRAY_SIZE - 1)\n-\n-#define OVS_INTERNAL_VPORT_DEFAULT_INDEX 0\n-\n-//Tunnel port indicies\n-#define RESERVED_START_INDEX1 1\n-#define OVS_TUNNEL_INDEX_START RESERVED_START_INDEX1\n-#define OVS_VXLAN_VPORT_INDEX 2\n-#define OVS_GRE_VPORT_INDEX 3\n-#define OVS_TUNNEL_INDEX_END OVS_GRE_VPORT_INDEX\n-\n-#define OVS_MAX_PHYS_ADAPTERS 32\n-#define OVS_MAX_IP_VPOR 32\n-\n-#define OVS_HASH_BASIS 0x13578642\n-\n-typedef struct _OVS_VPORT_ENTRY *POVS_VPORT_ENTRY;\n-\n-typedef struct _OVS_DATAPATH\n-{\n- PLIST_ENTRY flowTable; // Contains OvsFlows.\n- UINT32 nFlows; // Number of entries in flowTable.\n-\n- // List_Links queues[64]; // Hash table of queue IDs.\n-\n- /* Statistics. */\n- UINT64 hits; // Number of flow table hits.\n- UINT64 misses; // Number of flow table misses.\n- UINT64 lost; // Number of dropped misses.\n-\n- /* Used to protect the flows in the flowtable. */\n- PNDIS_RW_LOCK_EX lock;\n-} OVS_DATAPATH, *POVS_DATAPATH;\n-\n-/*\n- * OVS_SWITCH_CONTEXT\n- *\n- * The context allocated per switch., For OVS, we only\n- * support one switch which corresponding to one datapath.\n- * Each datapath can have multiple logical bridges configured\n- * which is maintained by vswitchd.\n- */\n-\n-typedef enum OVS_SWITCH_DATAFLOW_STATE\n-{\n- OvsSwitchPaused,\n- OvsSwitchRunning\n-} OVS_SWITCH_DATAFLOW_STATE, *POVS_SWITCH_DATAFLOW_STATE;\n-\n-typedef enum OVS_SWITCH_CONTROFLOW_STATE\n-{\n- OvsSwitchUnknown,\n- OvsSwitchAttached,\n- OvsSwitchDetached\n-} OVS_SWITCH_CONTROLFLOW_STATE, *POVS_SWITCH_CONTROLFLOW_STATE;\n-\n-// XXX: Take care of alignment and grouping members by cacheline\n-typedef struct _OVS_SWITCH_CONTEXT\n-{\n- /* Coarse and fine-grained switch states. */\n- OVS_SWITCH_DATAFLOW_STATE dataFlowState;\n- OVS_SWITCH_CONTROLFLOW_STATE controlFlowState;\n- BOOLEAN isActivated;\n- BOOLEAN isActivateFailed;\n-\n- UINT32 dpNo;\n-\n- /*\n- * 'virtualExternalVport' represents default external interface. This is\n- * a virtual interface. The friendly name of such an interface has\n- * been observed to be: \"Microsoft Default External Interface\". This NIC\n- * has 'NicIndex' == 0.\n- *\n- * The \"real\" physical external NIC has 'NicIndex' > 0. For each\n- * external interface, virtual or physical, NDIS gives an NIC level\n- * OID callback. Note that, even though there are multiple \"NICs\",\n- * there's only one underlying Hyper-V port. Thus, we get a single\n- * NDIS port-level callback, but multiple NDIS NIC-level callbacks.\n- *\n- * The virtual external NIC can be accessed at 'virtualExternalVport', and\n- * is assigned the name \"external.defaultAdapter\". The virtual external\n- * NIC is not inserted into the 'portIdHashArray' since the port must not\n- * be exposed to OVS userspace.\n- *\n- * The physical external NICs are assigned names \"external.%INDEX%\",\n- * where '%INDEX%' represents the 'NicIndex' of the NIC.\n- *\n- * While adding a physical external NIC in OvsInitConfiguredSwitchNics(),\n- * some required properties of the vport are available only at the\n- * NDIS port-level. So, these are copied from 'virtualExternalVport'.\n- * The vport created for the physical external NIC is inserted into the\n- * 'portIdHashArray'.\n- *\n- * When the virtual external NIC is torn down or deleted, the\n- * corresponding physical external ports are also torn down or\n- * deleted. The number of physical external NICs is tracked by\n- * 'numPhysicalNics'.\n- */\n- NDIS_SWITCH_PORT_ID virtualExternalPortId;\n- POVS_VPORT_ENTRY virtualExternalVport; /* the virtual adapter\n- * vport */\n- INT32 countInternalVports; /* the number of internal\n- * vports */\n- UINT32 ipHelperBoundVportNo; /* vportNo bound to\n- * IpHelper */\n-\n- /*\n- * 'portIdHashArray' ONLY contains ports that exist on the Hyper-V switch,\n- * namely: VIF (vNIC) ports, external port and Hyper-V internal port.\n- * 'numHvVports' counts the ports in 'portIdHashArray'. If a port got\n- * deleted on the Hyper-V switch, it gets deleted from 'portIdHashArray'.\n- * The port itself will not get deallocated if it has been added from OVS\n- * userspace. 'numHvVports' is decremented when the port is deallocated.\n- *\n- * 'portNoHashArray' ONLY contains ports that are added from OVS userspace,\n- * regardless of whether that port exists on the Hyper-V switch or not.\n- * Tunnel ports and bridge-internal ports are examples of ports that do not\n- * exist on the Hyper-V switch, and 'numNonHvVports' counts such ports in\n- * 'portNoHashArray'.\n- *\n- * 'tunnelVportsArray' contains tunnel ports that are added from OVS\n- * userspace. Currently only VXLAN tunnels are added in this list.\n- *\n- * 'ovsPortNameHashArray' contains the same entries as 'portNoHashArray' but\n- * hashed on a different key.\n- */\n- PLIST_ENTRY portIdHashArray; // based on Hyper-V portId\n- PLIST_ENTRY portNoHashArray; // based on ovs port number\n- PLIST_ENTRY tunnelVportsArray; // based on ovs dst port number\n- PLIST_ENTRY ovsPortNameHashArray; // based on ovsName\n- PLIST_ENTRY pidHashArray; // based on packet pids\n- NDIS_SPIN_LOCK pidHashLock; // Lock for pidHash table\n-\n- UINT32 numPhysicalNics; // the number of physical\n- // external NICs.\n- UINT32 numHvVports;\n- UINT32 numNonHvVports;\n-\n- /* Lock taken over the switch. This protects the ports on the switch. */\n- PNDIS_RW_LOCK_EX dispatchLock;\n-\n- /* The flowtable. */\n- OVS_DATAPATH datapath;\n-\n- /* Handle to the OVSExt filter driver. Same as 'gOvsExtDriverHandle'. */\n- NDIS_HANDLE NdisFilterHandle;\n-\n- /* Handle and callbacks exposed by the underlying hyper-v switch. */\n- NDIS_SWITCH_CONTEXT NdisSwitchContext;\n- NDIS_SWITCH_OPTIONAL_HANDLERS NdisSwitchHandlers;\n-\n- volatile LONG pendingInjectedNblCount;\n- volatile LONG pendingOidCount;\n-\n- OVS_NBL_POOL ovsPool;\n-} OVS_SWITCH_CONTEXT, *POVS_SWITCH_CONTEXT;\n-\n-\n-_IRQL_raises_(DISPATCH_LEVEL)\n-_IRQL_saves_global_(OldIrql, lockState)\n-_Acquires_lock_(datapath->lock)\n-static __inline VOID\n-OvsAcquireDatapathRead(OVS_DATAPATH *datapath,\n- LOCK_STATE_EX *lockState,\n- BOOLEAN dispatch)\n-{\n- ASSERT(datapath);\n- NdisAcquireRWLockRead(datapath->lock, lockState,\n- dispatch ? NDIS_RWL_AT_DISPATCH_LEVEL : 0);\n-}\n-\n-_IRQL_raises_(DISPATCH_LEVEL)\n-_IRQL_saves_global_(OldIrql, lockState)\n-_Acquires_lock_(datapath->lock)\n-static __inline VOID\n-OvsAcquireDatapathWrite(OVS_DATAPATH *datapath,\n- LOCK_STATE_EX *lockState,\n- BOOLEAN dispatch)\n-{\n- ASSERT(datapath);\n- NdisAcquireRWLockWrite(datapath->lock, lockState,\n- dispatch ? NDIS_RWL_AT_DISPATCH_LEVEL : 0);\n-}\n-\n-_IRQL_requires_(DISPATCH_LEVEL)\n-_IRQL_restores_global_(OldIrql, lockState)\n-_Requires_lock_held_(datapath->lock)\n-_Releases_lock_(datapath->lock)\n-static __inline VOID\n-OvsReleaseDatapath(OVS_DATAPATH *datapath,\n- LOCK_STATE_EX *lockState)\n-{\n- ASSERT(datapath);\n- NdisReleaseRWLock(datapath->lock, lockState);\n-}\n-\n-BOOLEAN\n-OvsAcquireSwitchContext(VOID);\n-\n-VOID\n-OvsReleaseSwitchContext(POVS_SWITCH_CONTEXT switchContext);\n-\n-#endif /* __SWITCH_H_ */\ndiff --git a/datapath-windows/ovsext/Tunnel.c b/datapath-windows/ovsext/Tunnel.c\ndeleted file mode 100644\nindex 5725d275a..000000000\n--- a/datapath-windows/ovsext/Tunnel.c\n+++ /dev/null\n@@ -1,338 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-/*\n- * OvsTunnel.c\n- * WFP Classified callback function and Action code for injecting a packet to the vswitch\n- */\n-\n-#include \"precomp.h\"\n-\n-#pragma warning(push)\n-#pragma warning(disable:4201) // unnamed struct/union\n-#include <fwpsk.h>\n-#pragma warning(pop)\n-\n-#pragma warning( push )\n-#pragma warning( disable:4127 )\n-\n-#include <fwpmk.h>\n-#include \"Tunnel.h\"\n-#include \"Switch.h\"\n-#include \"Vport.h\"\n-#include \"Event.h\"\n-#include \"User.h\"\n-#include \"Vxlan.h\"\n-#include \"PacketIO.h\"\n-#include \"NetProto.h\"\n-#include \"Flow.h\"\n-#include \"Actions.h\"\n-\n-extern POVS_SWITCH_CONTEXT gOvsSwitchContext;\n-\n-static NTSTATUS\n-OvsInjectPacketThroughActions(PNET_BUFFER_LIST pNbl,\n- OVS_TUNNEL_PENDED_PACKET *packet);\n-\n-NTSTATUS\n-OvsTunnelNotify(FWPS_CALLOUT_NOTIFY_TYPE notifyType,\n- const GUID *filterKey,\n- const FWPS_FILTER *filter)\n-{\n- UNREFERENCED_PARAMETER(notifyType);\n- UNREFERENCED_PARAMETER(filterKey);\n- UNREFERENCED_PARAMETER(filter);\n-\n- return STATUS_SUCCESS;\n-}\n-\n-static NTSTATUS\n-OvsTunnelAnalyzePacket(OVS_TUNNEL_PENDED_PACKET *packet)\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n- UINT32 packetLength = 0;\n- ULONG bytesCopied = 0;\n- NET_BUFFER_LIST *copiedNBL = NULL;\n- NET_BUFFER *netBuffer;\n- NDIS_STATUS ndisStatus;\n-\n- /*\n- * For inbound net buffer list, we can assume it contains only one\n- * net buffer (unless it was an re-assembeled fragments). in both cases\n- * the first net buffer should include all headers, we assert if the retreat fails\n- */\n- netBuffer = NET_BUFFER_LIST_FIRST_NB(packet->netBufferList);\n-\n- /* Drop the packet from the host stack */\n- packet->classifyOut->actionType = FWP_ACTION_BLOCK;\n- packet->classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;\n-\n- /* Adjust the net buffer list offset to the start of the IP header */\n- ndisStatus = NdisRetreatNetBufferDataStart(netBuffer,\n- packet->ipHeaderSize +\n- packet->transportHeaderSize,\n- 0, NULL);\n- ASSERT(ndisStatus == NDIS_STATUS_SUCCESS);\n-\n- /* Single NBL element for WFP */\n- ASSERT(packet->netBufferList->Next == NULL);\n-\n- /* Note that the copy will inherit the original net buffer list's offset */\n- packetLength = NET_BUFFER_DATA_LENGTH(netBuffer);\n- copiedNBL = OvsAllocateVariableSizeNBL(gOvsSwitchContext, packetLength,\n- OVS_DEFAULT_HEADROOM_SIZE);\n-\n- if (copiedNBL == NULL) {\n- goto analyzeDone;\n- }\n-\n- status = NdisCopyFromNetBufferToNetBuffer(NET_BUFFER_LIST_FIRST_NB(copiedNBL),\n- 0, packetLength,\n- netBuffer, 0, &bytesCopied);\n- if (status != NDIS_STATUS_SUCCESS || packetLength != bytesCopied) {\n- goto analyzeFreeNBL;\n- }\n-\n- status = OvsInjectPacketThroughActions(copiedNBL,\n- packet);\n- goto analyzeDone;\n-\n- /* Undo the adjustment on the original net buffer list */\n-analyzeFreeNBL:\n- OvsCompleteNBL(gOvsSwitchContext, copiedNBL, TRUE);\n-analyzeDone:\n- NdisAdvanceNetBufferDataStart(netBuffer,\n- packet->transportHeaderSize + packet->ipHeaderSize,\n- FALSE,\n- NULL);\n- return status;\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * This is the classifyFn function of the datagram-data callout. It\n- * allocates a packet structure to store the classify and meta data and\n- * it references the net buffer list for out-of-band modification and\n- * re-injection. The packet structure will be queued to the global packet\n- * queue. The worker thread will then be signaled, if idle, to process\n- * the queue.\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-OvsTunnelClassify(const FWPS_INCOMING_VALUES *inFixedValues,\n- const FWPS_INCOMING_METADATA_VALUES *inMetaValues,\n- VOID *layerData,\n- const VOID *classifyContext,\n- const FWPS_FILTER *filter,\n- UINT64 flowContext,\n- FWPS_CLASSIFY_OUT *classifyOut)\n-{\n- OVS_TUNNEL_PENDED_PACKET packetStorage;\n- OVS_TUNNEL_PENDED_PACKET *packet = &packetStorage;\n- FWP_DIRECTION direction;\n-\n- UNREFERENCED_PARAMETER(classifyContext);\n- UNREFERENCED_PARAMETER(filter);\n- UNREFERENCED_PARAMETER(flowContext);\n-\n- ASSERT(layerData != NULL);\n-\n- /* We don't have the necessary right to alter the packet flow */\n- if ((classifyOut->rights & FWPS_RIGHT_ACTION_WRITE) == 0) {\n- /* XXX TBD revisit protect against other filters owning this packet */\n- ASSERT(FALSE);\n- goto Exit;\n- }\n-\n- RtlZeroMemory(packet, sizeof(OVS_TUNNEL_PENDED_PACKET));\n-\n- /* classifyOut cannot be accessed from a different thread context */\n- packet->classifyOut = classifyOut;\n-\n- if (inFixedValues->layerId == FWPS_LAYER_DATAGRAM_DATA_V4) {\n- direction =\n- inFixedValues->incomingValue[FWPS_FIELD_DATAGRAM_DATA_V4_DIRECTION].\\\n- value.uint32;\n- }\n- else {\n- ASSERT(inFixedValues->layerId == FWPS_LAYER_DATAGRAM_DATA_V6);\n- direction =\n- inFixedValues->incomingValue[FWPS_FIELD_DATAGRAM_DATA_V6_DIRECTION].\\\n- value.uint32;\n- }\n-\n- packet->netBufferList = layerData;\n-\n- ASSERT(FWPS_IS_METADATA_FIELD_PRESENT(inMetaValues,\n- FWPS_METADATA_FIELD_COMPARTMENT_ID));\n-\n- ASSERT(direction == FWP_DIRECTION_INBOUND);\n-\n- ASSERT(FWPS_IS_METADATA_FIELD_PRESENT(\n- inMetaValues,\n- FWPS_METADATA_FIELD_IP_HEADER_SIZE));\n- ASSERT(FWPS_IS_METADATA_FIELD_PRESENT(\n- inMetaValues,\n- FWPS_METADATA_FIELD_TRANSPORT_HEADER_SIZE));\n-\n- packet->ipHeaderSize = inMetaValues->ipHeaderSize;\n- packet->transportHeaderSize = inMetaValues->transportHeaderSize;\n-\n- ASSERT(inFixedValues->incomingValue[FWPS_FIELD_DATAGRAM_DATA_V4_IP_PROTOCOL].value.uint8 == IPPROTO_UDP );\n- OvsTunnelAnalyzePacket(packet);\n-\n-Exit:\n- ;\n-}\n-\n-\n-static NTSTATUS\n-OvsInjectPacketThroughActions(PNET_BUFFER_LIST pNbl,\n- OVS_TUNNEL_PENDED_PACKET *packet)\n-{\n- NTSTATUS status;\n- OvsIPTunnelKey tunKey = {0};\n- NET_BUFFER *pNb;\n- ULONG sendCompleteFlags = 0;\n- BOOLEAN dispatch;\n- PNDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO fwdDetail;\n- LOCK_STATE_EX lockState, dpLockState;\n- LIST_ENTRY missedPackets;\n- OvsCompletionList completionList;\n- KIRQL irql;\n- ULONG SendFlags = NDIS_SEND_FLAGS_SWITCH_DESTINATION_GROUP;\n- OVS_DATAPATH *datapath = &gOvsSwitchContext->datapath;\n-\n- ASSERT(gOvsSwitchContext);\n-\n- /* Fill the tunnel key */\n- status = OvsSlowPathDecapVxlan(pNbl, &tunKey);\n-\n- if(!NT_SUCCESS(status)) {\n- goto dropit;\n- }\n-\n- pNb = NET_BUFFER_LIST_FIRST_NB(pNbl);\n-\n- NdisAdvanceNetBufferDataStart(pNb,\n- packet->transportHeaderSize + packet->ipHeaderSize +\n- sizeof(VXLANHdr),\n- FALSE,\n- NULL);\n-\n- /* Most likely (always) dispatch irql */\n- irql = KeGetCurrentIrql();\n-\n- /* dispatch is used for datapath lock as well */\n- dispatch = (irql == DISPATCH_LEVEL) ? NDIS_RWL_AT_DISPATCH_LEVEL : 0;\n- if (dispatch) {\n- sendCompleteFlags |= NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL;\n- }\n-\n- InitializeListHead(&missedPackets);\n- OvsInitCompletionList(&completionList, gOvsSwitchContext,\n- sendCompleteFlags);\n-\n- {\n- POVS_VPORT_ENTRY vport = NULL;\n- UINT32 portNo = 0;\n- OVS_PACKET_HDR_INFO layers = { 0 };\n- OvsFlowKey key = { 0 };\n- UINT64 hash = 0;\n- PNET_BUFFER curNb = NULL;\n- OvsFlow *flow = NULL;\n-\n- fwdDetail = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(pNbl);\n-\n- /*\n- * XXX WFP packets contain a single NBL structure.\n- * Reassembeled packet \"may\" have multiple NBs, however, a simple test shows\n- * that the packet still has a single NB (after reassemble)\n- * We still need to check if the Ethernet header of the innet packet is in a single MD\n- */\n-\n- curNb = NET_BUFFER_LIST_FIRST_NB(pNbl);\n- ASSERT(curNb->Next == NULL);\n-\n- NdisAcquireRWLockRead(gOvsSwitchContext->dispatchLock, &lockState, dispatch);\n-\n- /* Lock the flowtable for the duration of accessing the flow */\n- OvsAcquireDatapathRead(datapath, &dpLockState, NDIS_RWL_AT_DISPATCH_LEVEL);\n-\n- SendFlags |= NDIS_SEND_FLAGS_DISPATCH_LEVEL;\n-\n- vport = OvsFindTunnelVportByDstPortAndType(gOvsSwitchContext,\n- htons(tunKey.dst_port),\n- OVS_VPORT_TYPE_VXLAN);\n-\n- if (vport == NULL){\n- status = STATUS_UNSUCCESSFUL;\n- goto unlockAndDrop;\n- }\n-\n- ASSERT(vport->ovsType == OVS_VPORT_TYPE_VXLAN);\n-\n- portNo = vport->portNo;\n-\n- status = OvsExtractFlow(pNbl, portNo, &key, &layers, &tunKey);\n- if (status != NDIS_STATUS_SUCCESS) {\n- goto unlockAndDrop;\n- }\n-\n- flow = OvsLookupFlow(datapath, &key, &hash, FALSE);\n- if (flow) {\n- OvsFlowUsed(flow, pNbl, &layers);\n- datapath->hits++;\n-\n- OvsActionsExecute(gOvsSwitchContext, &completionList, pNbl,\n- portNo, SendFlags, &key, &hash, &layers,\n- flow->actions, flow->actionsLen);\n-\n- OvsReleaseDatapath(datapath, &dpLockState);\n- } else {\n- POVS_PACKET_QUEUE_ELEM elem;\n-\n- datapath->misses++;\n- elem = OvsCreateQueueNlPacket(NULL, 0, OVS_PACKET_CMD_MISS,\n- vport, &key, NULL, pNbl, curNb,\n- TRUE, &layers);\n- if (elem) {\n- /* Complete the packet since it was copied to user buffer. */\n- InsertTailList(&missedPackets, &elem->link);\n- OvsQueuePackets(&missedPackets, 1);\n- } else {\n- status = STATUS_INSUFFICIENT_RESOURCES;\n- }\n- goto unlockAndDrop;\n- }\n-\n- NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState);\n-\n- }\n-\n- return status;\n-\n-unlockAndDrop:\n- OvsReleaseDatapath(datapath, &dpLockState);\n- NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState);\n-dropit:\n- pNbl = OvsCompleteNBL(gOvsSwitchContext, pNbl, TRUE);\n- ASSERT(pNbl == NULL);\n- return status;\n-}\n-\n-#pragma warning(pop)\ndiff --git a/datapath-windows/ovsext/Tunnel.h b/datapath-windows/ovsext/Tunnel.h\ndeleted file mode 100644\nindex 2c45e35fd..000000000\n--- a/datapath-windows/ovsext/Tunnel.h\n+++ /dev/null\n@@ -1,51 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#ifndef __TUNNEL_H_\n-#define __TUNNEL_H_ 1\n-\n-//\n-// OVS_TUNNEL_PENDED_PACKET is the object type we used to store all information\n-// needed for out-of-band packet modification and re-injection. This type\n-// also points back to the flow context the packet belongs to.\n-\n-typedef struct OVS_TUNNEL_PENDED_PACKET_\n-{\n- /* Common fields for inbound and outbound traffic */\n- NET_BUFFER_LIST *netBufferList;\n-\n- UINT32 ipHeaderSize;\n- UINT32 transportHeaderSize;\n- FWPS_CLASSIFY_OUT *classifyOut;\n-} OVS_TUNNEL_PENDED_PACKET;\n-\n-//\n-// Shared function prototypes\n-//\n-VOID OvsTunnelClassify(const FWPS_INCOMING_VALUES *inFixedValues,\n- const FWPS_INCOMING_METADATA_VALUES *inMetaValues,\n- VOID *layerData,\n- const VOID *classifyContext,\n- const FWPS_FILTER *filter,\n- UINT64 flowContext,\n- FWPS_CLASSIFY_OUT *classifyOut);\n-\n-\n-NTSTATUS OvsTunnelNotify(FWPS_CALLOUT_NOTIFY_TYPE notifyType,\n- const GUID *filterKey,\n- const FWPS_FILTER *filter);\n-\n-#endif /* __TUNNEL_H_ */\ndiff --git a/datapath-windows/ovsext/TunnelFilter.c b/datapath-windows/ovsext/TunnelFilter.c\ndeleted file mode 100644\nindex 9939415fb..000000000\n--- a/datapath-windows/ovsext/TunnelFilter.c\n+++ /dev/null\n@@ -1,1656 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#include \"precomp.h\"\n-\n-#pragma warning(push)\n-#pragma warning(disable:4201) // unnamed struct/union\n-#ifdef OVS_DBG_MOD\n-#undef OVS_DBG_MOD\n-#endif\n-#define OVS_DBG_MOD OVS_DBG_TUNFLT\n-#include \"Debug.h\"\n-\n-\n-#include <fwpsk.h>\n-\n-#pragma warning(pop)\n-\n-#include <fwpmk.h>\n-#include <ws2ipdef.h>\n-#include <in6addr.h>\n-#include <ip2string.h>\n-\n-#include \"Tunnel.h\"\n-#include \"Switch.h\"\n-#include \"Vport.h\"\n-#include \"Event.h\"\n-#include \"User.h\"\n-#include \"Vxlan.h\"\n-\n-\n-#define INITGUID\n-#include <guiddef.h>\n-\n-/* Infinite timeout */\n-#define INFINITE 0xFFFFFFFF\n-\n-/* The provider name should always match the provider string from the install\n- * file. */\n-#define OVS_TUNNEL_PROVIDER_NAME L\"The Linux Foundation (R)\"\n-\n-/* The provider description should always contain the OVS service description\n- * string from the install file. */\n-#define OVS_TUNNEL_PROVIDER_DESC L\"Open vSwitch Extension tunnel provider\"\n-\n-/* The session name isn't required but it's useful for diagnostics. */\n-#define OVS_TUNNEL_SESSION_NAME L\"OVS tunnel session\"\n-\n-/* Maximum number of tunnel threads to be created. */\n-#define OVS_TUNFLT_MAX_THREADS 8\n-\n-/*\n- * Callout and sublayer GUIDs\n- */\n-\n-/* b16b0a6e-2b2a-41a3-8b39-bd3ffc855ff8 */\n-DEFINE_GUID(\n- OVS_TUNNEL_CALLOUT_V4,\n- 0xb16b0a6e,\n- 0x2b2a,\n- 0x41a3,\n- 0x8b, 0x39, 0xbd, 0x3f, 0xfc, 0x85, 0x5f, 0xf8\n- );\n-\n-/* 0104fd7e-c825-414e-94c9-f0d525bbc169 */\n-DEFINE_GUID(\n- OVS_TUNNEL_SUBLAYER,\n- 0x0104fd7e,\n- 0xc825,\n- 0x414e,\n- 0x94, 0xc9, 0xf0, 0xd5, 0x25, 0xbb, 0xc1, 0x69\n- );\n-\n-/* 6fc957d7-14e7-47c7-812b-4668be994ba1 */\n-DEFINE_GUID(\n- OVS_TUNNEL_PROVIDER_KEY,\n- 0x6fc957d7,\n- 0x14e7,\n- 0x47c7,\n- 0x81, 0x2b, 0x46, 0x68, 0xbe, 0x99, 0x4b, 0xa1\n- );\n-\n-/* bfd4814c-9650-4de3-a536-1eedb9e9ba6a */\n-DEFINE_GUID(\n- OVS_TUNNEL_FILTER_KEY,\n- 0xbfd4814c,\n- 0x9650,\n- 0x4de3,\n- 0xa5, 0x36, 0x1e, 0xed, 0xb9, 0xe9, 0xba, 0x6a\n- );\n-\n-/*\n- * Callout driver type definitions\n- */\n-typedef enum _OVS_TUNFLT_OPERATION {\n- OVS_TUN_FILTER_CREATE = 0,\n- OVS_TUN_FILTER_DELETE\n-} OVS_TUNFLT_OPERATION;\n-\n-typedef struct _OVS_TUNFLT_REQUEST {\n- LIST_ENTRY entry;\n- /* Tunnel filter destination port. */\n- UINT16 port;\n- /* XXX: We also need to specify the tunnel L4 protocol, because there are\n- * different protocols that can use the same destination port.*/\n- union {\n- /* Tunnel filter identification used for filter deletion. */\n- UINT64 delID;\n- /* Pointer used to return filter ID to the caller on filter creation. */\n- PUINT64 addID;\n- } filterID;\n- /* Requested operation to be performed. */\n- OVS_TUNFLT_OPERATION operation;\n- /* Current I/O request to be completed when requested\n- * operation is finished. */\n- PIRP irp;\n- /* Callback function called before completing the IRP. */\n- PFNTunnelVportPendingOp callback;\n- /* Context passed to the callback function. */\n- PVOID context;\n-} OVS_TUNFLT_REQUEST, *POVS_TUNFLT_REQUEST;\n-\n-typedef struct _OVS_TUNFLT_REQUEST_LIST {\n- /* SpinLock for syncronizing access to the requests list. */\n- NDIS_SPIN_LOCK spinlock;\n- /* Head of the requests list. */\n- LIST_ENTRY head;\n- /* Number of requests in the list. This variable is used by\n- * InterlockedCompareExchange function and needs to be aligned\n- * at 32-bit boundaries. */\n- UINT32 numEntries;\n-} OVS_TUNFLT_REQUEST_LIST, *POVS_TUNFLT_REQUEST_LIST;\n-\n-typedef struct _OVS_TUNFLT_THREAD_CONTEXT {\n- /* Thread identification. */\n- UINT threadID;\n- /* Thread initialization flag. */\n- UINT32 isInitialized;\n- /* Thread's engine session handle. */\n- HANDLE engineSession;\n- /* Reference of the thread object. */\n- PVOID threadObject;\n- /* Requests queue list. */\n- OVS_TUNFLT_REQUEST_LIST listRequests;\n- /* Event signaling that there are requests to process. */\n- KEVENT requestEvent;\n- /* Event for stopping thread execution. */\n- KEVENT stopEvent;\n-} OVS_TUNFLT_THREAD_CONTEXT, *POVS_TUNFLT_THREAD_CONTEXT;\n-\n-KSTART_ROUTINE OvsTunnelFilterThreadProc;\n-\n-static NTSTATUS OvsTunnelFilterStartThreads();\n-static NTSTATUS OvsTunnelFilterThreadStart(POVS_TUNFLT_THREAD_CONTEXT threadCtx);\n-static VOID OvsTunnelFilterStopThreads();\n-static VOID OvsTunnelFilterThreadStop(POVS_TUNFLT_THREAD_CONTEXT threadCtx,\n- BOOLEAN signalEvent);\n-static NTSTATUS OvsTunnelFilterThreadInit(POVS_TUNFLT_THREAD_CONTEXT threadCtx);\n-static VOID OvsTunnelFilterThreadUninit(POVS_TUNFLT_THREAD_CONTEXT threadCtx);\n-static VOID OvsTunnelFilterSetIrpContext(POVS_TUNFLT_REQUEST_LIST listRequests,\n- POVS_TUNFLT_REQUEST request);\n-DRIVER_CANCEL OvsTunnelFilterCancelIrp;\n-\n-/*\n- * Callout driver global variables\n- */\n-\n-/* Pointer to the device object that must be create before we can register our\n- * callout to the base filtering engine. */\n-static PDEVICE_OBJECT gDeviceObject = NULL;\n-/* Handle to an open session to the filter engine that is used for adding\n- * tunnel's callout. */\n-static HANDLE gEngineHandle = NULL;\n-/* A pointer to the received handle that is associated with the registration of\n- * the OvsTunnelProviderBfeCallback callback. */\n-static HANDLE gTunnelProviderBfeHandle = NULL;\n-/* A pointer to the received handle that is associated with the registration of\n- * the OvsTunnelInitBfeCallback callback. */\n-static HANDLE gTunnelInitBfeHandle = NULL;\n-/* Runtime identifier for tunnel's callout which is retrieved at tunnel\n- * initialization phase when the callout is registered. This ID is then used\n- * for removing the callout object from the system at tunnel\n- * uninitialization phase. */\n-static UINT32 gCalloutIdV4 = 0;\n-/* Array used for storing tunnel thread's private data. */\n-static OVS_TUNFLT_THREAD_CONTEXT gTunnelThreadCtx[OVS_TUNFLT_MAX_THREADS] = { 0 };\n-\n-/*\n- * Callout driver implementation.\n- */\n-\n-NTSTATUS\n-OvsTunnelEngineOpen(HANDLE *engineSession)\n-{\n- NTSTATUS status;\n- FWPM_SESSION session = { 0 };\n-\n- /*\n- * Set an infinite wait timeout, so we don't have to handle FWP_E_TIMEOUT\n- * errors while waiting to acquire the transaction lock.\n- */\n- session.txnWaitTimeoutInMSec = INFINITE;\n-\n- /* The authentication service should always be RPC_C_AUTHN_DEFAULT. */\n- status = FwpmEngineOpen(NULL,\n- RPC_C_AUTHN_DEFAULT,\n- NULL,\n- &session,\n- engineSession);\n- if (!NT_SUCCESS(status)) {\n- OVS_LOG_ERROR(\"Failed to open filtering engine session, status: %x.\",\n- status);\n- }\n-\n- return status;\n-}\n-\n-VOID\n-OvsTunnelEngineClose(HANDLE *engineSession)\n-{\n- if (*engineSession) {\n- FwpmEngineClose(*engineSession);\n- *engineSession = NULL;\n- }\n-}\n-\n-VOID\n-OvsTunnelAddSystemProvider(HANDLE engineSession)\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n- BOOLEAN inTransaction = FALSE;\n- FWPM_PROVIDER provider = { 0 };\n-\n- do {\n- status = FwpmTransactionBegin(engineSession, 0);\n- if (!NT_SUCCESS(status)) {\n- break;\n- }\n- inTransaction = TRUE;\n-\n- memset(&provider, 0, sizeof(provider));\n- provider.providerKey = OVS_TUNNEL_PROVIDER_KEY;\n- provider.displayData.name = OVS_TUNNEL_PROVIDER_NAME;\n- provider.displayData.description = OVS_TUNNEL_PROVIDER_DESC;\n- /*\n- * Since we always want the provider to be present, it's easiest to add\n- * it as persistent object during driver load.\n- */\n- provider.flags = FWPM_PROVIDER_FLAG_PERSISTENT;\n-\n- status = FwpmProviderAdd(engineSession,\n- &provider,\n- NULL);\n- if (!NT_SUCCESS(status)) {\n- if (STATUS_FWP_ALREADY_EXISTS != status) {\n- OVS_LOG_ERROR(\"Failed to add WFP provider, status: %x.\",\n- status);\n- break;\n- }\n- }\n-\n- status = FwpmTransactionCommit(engineSession);\n- if (!NT_SUCCESS(status)) {\n- break;\n- }\n-\n- inTransaction = FALSE;\n- } while (inTransaction);\n-\n- if (inTransaction){\n- FwpmTransactionAbort(engineSession);\n- }\n-}\n-\n-VOID\n-OvsTunnelRemoveSystemProvider(HANDLE engineSession)\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n- BOOLEAN inTransaction = FALSE;\n-\n- do {\n- status = FwpmTransactionBegin(engineSession, 0);\n- if (!NT_SUCCESS(status)) {\n- break;\n- }\n- inTransaction = TRUE;\n-\n- status = FwpmProviderDeleteByKey(engineSession,\n- &OVS_TUNNEL_PROVIDER_KEY);\n- if (!NT_SUCCESS(status)) {\n- break;\n- }\n-\n- status = FwpmTransactionCommit(engineSession);\n- if (!NT_SUCCESS(status)) {\n- break;\n- }\n-\n- inTransaction = FALSE;\n- } while (inTransaction);\n-\n- if (inTransaction){\n- FwpmTransactionAbort(engineSession);\n- }\n-}\n-\n-NTSTATUS\n-OvsTunnelAddFilter(HANDLE engineSession,\n- PWSTR filterName,\n- const PWSTR filterDesc,\n- USHORT remotePort,\n- FWP_DIRECTION direction,\n- UINT64 context,\n- const GUID *filterKey,\n- const GUID *layerKey,\n- const GUID *calloutKey,\n- UINT64 *filterID)\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n- FWPM_FILTER filter = {0};\n- FWPM_FILTER_CONDITION filterConditions[3] = {0};\n- UINT conditionIndex;\n-\n- if (filterKey) {\n- filter.filterKey = *filterKey;\n- }\n- filter.layerKey = *layerKey;\n- filter.displayData.name = (wchar_t*)filterName;\n- filter.displayData.description = (wchar_t*)filterDesc;\n-\n- filter.action.type = FWP_ACTION_CALLOUT_TERMINATING;\n- filter.action.calloutKey = *calloutKey;\n- filter.filterCondition = filterConditions;\n- filter.subLayerKey = OVS_TUNNEL_SUBLAYER;\n- filter.weight.type = FWP_EMPTY; // auto-weight.\n- filter.rawContext = context;\n-\n- conditionIndex = 0;\n-\n- filterConditions[conditionIndex].fieldKey = FWPM_CONDITION_DIRECTION;\n- filterConditions[conditionIndex].matchType = FWP_MATCH_EQUAL;\n- filterConditions[conditionIndex].conditionValue.type = FWP_UINT32;\n- filterConditions[conditionIndex].conditionValue.uint32 = direction;\n-\n- conditionIndex++;\n-\n- filterConditions[conditionIndex].fieldKey = FWPM_CONDITION_IP_LOCAL_PORT;\n- filterConditions[conditionIndex].matchType = FWP_MATCH_EQUAL;\n- filterConditions[conditionIndex].conditionValue.type = FWP_UINT16;\n- filterConditions[conditionIndex].conditionValue.uint16 = remotePort;\n-\n- conditionIndex++;\n-\n- filter.numFilterConditions = conditionIndex;\n-\n- status = FwpmFilterAdd(engineSession,\n- &filter,\n- NULL,\n- filterID);\n-\n- return status;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * This function registers callouts for intercepting UDP traffic at WFP\n- * FWPM_LAYER_DATAGRAM_DATA_V4 layer.\n- * --------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsTunnelRegisterDatagramDataCallouts(const GUID *layerKey,\n- const GUID *calloutKey,\n- VOID *deviceObject,\n- UINT32 *calloutId)\n-{\n- NTSTATUS status;\n-\n- FWPS_CALLOUT sCallout = {0};\n- FWPM_CALLOUT mCallout = {0};\n-\n- FWPM_DISPLAY_DATA displayData = {0};\n-\n- BOOLEAN calloutRegistered = FALSE;\n-\n- sCallout.calloutKey = *calloutKey;\n- sCallout.classifyFn = OvsTunnelClassify;\n- sCallout.notifyFn = OvsTunnelNotify;\n-#if FLOW_CONTEXT\n- /* Currently we don't associate a context with the flow */\n- sCallout.flowDeleteFn = OvsTunnelFlowDelete;\n- sCallout.flags = FWP_CALLOUT_FLAG_CONDITIONAL_ON_FLOW;\n-#endif\n-\n- status = FwpsCalloutRegister(deviceObject, &sCallout, calloutId);\n- if (!NT_SUCCESS(status)) {\n- goto Exit;\n- }\n- calloutRegistered = TRUE;\n-\n- displayData.name = L\"Datagram-Data OVS Callout\";\n- displayData.description = L\"Proxies destination address/port for UDP\";\n-\n- mCallout.calloutKey = *calloutKey;\n- mCallout.displayData = displayData;\n- mCallout.applicableLayer = *layerKey;\n-\n- status = FwpmCalloutAdd(gEngineHandle, &mCallout, NULL, NULL);\n- if (!NT_SUCCESS(status)) {\n- if (STATUS_FWP_ALREADY_EXISTS != status) {\n- OVS_LOG_ERROR(\"Failed to add WFP callout, status: %x.\",\n- status);\n- goto Exit;\n- }\n- status = STATUS_SUCCESS;\n- }\n-\n-Exit:\n-\n- if (!NT_SUCCESS(status)){\n- if (calloutRegistered) {\n- FwpsCalloutUnregisterById(*calloutId);\n- *calloutId = 0;\n- }\n- }\n-\n- return status;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * This function registers non-dynamic callouts for intercepting UDP traffic.\n- * Callouts will be removed during un-initializing phase.\n- * --------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsTunnelRegisterCallouts(VOID *deviceObject)\n-{\n- NTSTATUS status;\n- BOOLEAN inTransaction = FALSE;\n- FWPM_SUBLAYER OvsTunnelSubLayer;\n-\n- status = FwpmTransactionBegin(gEngineHandle, 0);\n- if (!NT_SUCCESS(status)) {\n- goto Exit;\n- }\n- inTransaction = TRUE;\n-\n- RtlZeroMemory(&OvsTunnelSubLayer, sizeof(FWPM_SUBLAYER));\n-\n- OvsTunnelSubLayer.subLayerKey = OVS_TUNNEL_SUBLAYER;\n- OvsTunnelSubLayer.displayData.name = L\"Datagram-Data OVS Sub-Layer\";\n- OvsTunnelSubLayer.displayData.description =\n- L\"Sub-Layer for use by Datagram-Data OVS callouts\";\n- OvsTunnelSubLayer.flags = 0;\n- OvsTunnelSubLayer.weight = FWP_EMPTY; /* auto-weight */\n-\n- status = FwpmSubLayerAdd(gEngineHandle, &OvsTunnelSubLayer, NULL);\n- if (!NT_SUCCESS(status)) {\n- if (STATUS_FWP_ALREADY_EXISTS != status) {\n- OVS_LOG_ERROR(\"Failed to add WFP sublayer, status: %x.\",\n- status);\n- goto Exit;\n- }\n- }\n-\n- /* In order to use this callout a socket must be opened. */\n- status = OvsTunnelRegisterDatagramDataCallouts(&FWPM_LAYER_DATAGRAM_DATA_V4,\n- &OVS_TUNNEL_CALLOUT_V4,\n- deviceObject,\n- &gCalloutIdV4);\n- if (!NT_SUCCESS(status)) {\n- goto Exit;\n- }\n-\n- status = FwpmTransactionCommit(gEngineHandle);\n- if (!NT_SUCCESS(status)){\n- goto Exit;\n- }\n- inTransaction = FALSE;\n-\n-Exit:\n-\n- if (!NT_SUCCESS(status)) {\n- if (inTransaction) {\n- FwpmTransactionAbort(gEngineHandle);\n- }\n- }\n-\n- return status;\n-}\n-\n-VOID\n-OvsTunnelUnregisterCallouts()\n-{\n- FwpsCalloutUnregisterById(gCalloutIdV4);\n- FwpmSubLayerDeleteByKey(gEngineHandle, &OVS_TUNNEL_SUBLAYER);\n- FwpmCalloutDeleteById(gEngineHandle, gCalloutIdV4);\n-}\n-\n-VOID\n-OvsTunnelFilterUninitialize(PDRIVER_OBJECT driverObject)\n-{\n- UNREFERENCED_PARAMETER(driverObject);\n-\n- OvsTunnelFilterStopThreads();\n-\n- OvsTunnelUnregisterCallouts();\n- OvsTunnelEngineClose(&gEngineHandle);\n-\n- if (gDeviceObject) {\n- IoDeleteDevice(gDeviceObject);\n- }\n-}\n-\n-\n-NTSTATUS\n-OvsTunnelFilterInitialize(PDRIVER_OBJECT driverObject)\n-{\n- NTSTATUS status;\n- UNICODE_STRING deviceName;\n-\n- RtlInitUnicodeString(&deviceName,\n- L\"\\\\Device\\\\OvsTunnelFilter\");\n-\n- status = IoCreateDevice(driverObject,\n- 0,\n- &deviceName,\n- FILE_DEVICE_NETWORK,\n- 0,\n- FALSE,\n- &gDeviceObject);\n-\n- if (!NT_SUCCESS(status)){\n- OVS_LOG_ERROR(\"Failed to create tunnel filter device, status: %x.\",\n- status);\n- goto Exit;\n- }\n-\n- status = OvsTunnelFilterStartThreads();\n- if (!NT_SUCCESS(status)){\n- goto Exit;\n- }\n-\n- status = OvsTunnelEngineOpen(&gEngineHandle);\n- if (!NT_SUCCESS(status)){\n- goto Exit;\n- }\n-\n- status = OvsTunnelRegisterCallouts(gDeviceObject);\n- if (!NT_SUCCESS(status)) {\n- OVS_LOG_ERROR(\"Failed to register callout, status: %x.\",\n- status);\n- }\n-\n-Exit:\n-\n- if (!NT_SUCCESS(status)){\n- OvsTunnelFilterUninitialize(driverObject);\n- }\n-\n- return status;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * This function adds OVS system provider to the system if the BFE (Base\n- * Filtering Engine) is running.\n- * --------------------------------------------------------------------------\n- */\n-VOID NTAPI\n-OvsTunnelProviderBfeCallback(PVOID context,\n- FWPM_SERVICE_STATE bfeState)\n-{\n- HANDLE engineSession = NULL;\n-\n- DBG_UNREFERENCED_PARAMETER(context);\n-\n- if (FWPM_SERVICE_RUNNING == bfeState) {\n- OvsTunnelEngineOpen(&engineSession);\n- if (engineSession) {\n- OvsTunnelAddSystemProvider(engineSession);\n- }\n- OvsTunnelEngineClose(&engineSession);\n- }\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * This function registers the OvsTunnelProviderBfeCallback callback that is\n- * called whenever there is a change to the state of base filtering engine.\n- * --------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsSubscribeTunnelProviderBfeStateChanges(PVOID deviceObject)\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n-\n- if (!gTunnelProviderBfeHandle) {\n- status = FwpmBfeStateSubscribeChanges(deviceObject,\n- OvsTunnelProviderBfeCallback,\n- NULL,\n- &gTunnelProviderBfeHandle);\n- if (!NT_SUCCESS(status)) {\n- OVS_LOG_ERROR(\n- \"Failed to subscribe BFE tunnel provider callback, status: %x.\",\n- status);\n- }\n- }\n-\n- return status;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * This function unregisters the OvsTunnelProviderBfeCallback callback that\n- * was previously registered by OvsSubscribeTunnelProviderBfeStateChanges\n- * function.\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-OvsUnsubscribeTunnelProviderBfeStateChanges()\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n-\n- if (gTunnelProviderBfeHandle) {\n- status = FwpmBfeStateUnsubscribeChanges(gTunnelProviderBfeHandle);\n- if (!NT_SUCCESS(status)) {\n- OVS_LOG_ERROR(\n- \"Failed to unsubscribe BFE tunnel provider callback, status: %x.\",\n- status);\n- }\n- gTunnelProviderBfeHandle = NULL;\n- }\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * This function registers the OVS system provider if the BFE (Base Filtering\n- * Engine) is running.\n- * Otherwise, it will register the OvsTunnelProviderBfeCallback callback.\n-\n- * Note: Before calling FwpmBfeStateGet, the callout driver must call the\n- * FwpmBfeStateSubscribeChanges function to register the callback function\n- * to be called whenever the state of the filter engine changes.\n- *\n- * Register WFP system provider call hierarchy:\n- * <DriverEntry>\n- * <OvsCreateDeviceObject>\n- * <OvsRegisterSystemProvider>\n- * <OvsSubscribeTunnelProviderBfeStateChanges>\n- * --> registers OvsTunnelProviderBfeCallback callback\n- * <OvsTunnelProviderBfeCallback>\n- * --> if BFE is running:\n- * <OvsTunnelAddSystemProvider>\n- * --> if BFE is running:\n- * <OvsTunnelAddSystemProvider>\n- * <OvsUnsubscribeTunnelProviderBfeStateChanges>\n- * --> unregisters OvsTunnelProviderBfeCallback callback\n- *\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-OvsRegisterSystemProvider(PVOID deviceObject)\n-{\n- NTSTATUS status;\n- HANDLE engineSession = NULL;\n-\n- status = OvsSubscribeTunnelProviderBfeStateChanges(deviceObject);\n- if (NT_SUCCESS(status)) {\n- if (FWPM_SERVICE_RUNNING == FwpmBfeStateGet()) {\n- OvsTunnelEngineOpen(&engineSession);\n- if (engineSession) {\n- OvsTunnelAddSystemProvider(engineSession);\n- }\n- OvsTunnelEngineClose(&engineSession);\n-\n- OvsUnsubscribeTunnelProviderBfeStateChanges();\n- }\n- }\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * This function removes the OVS system provider and unregisters the\n- * OvsTunnelProviderBfeCallback callback from BFE (Base Filtering Engine).\n- *\n- * Unregister WFP system provider call hierarchy:\n- * <OvsExtUnload>\n- * <OvsDeleteDeviceObject>\n- * <OvsUnregisterSystemProvider>\n- * <OvsTunnelRemoveSystemProvider>\n- * <OvsUnsubscribeTunnelProviderBfeStateChanges>\n- * --> unregisters OvsTunnelProviderBfeCallback callback\n- *\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-OvsUnregisterSystemProvider()\n-{\n- HANDLE engineSession = NULL;\n-\n- OvsTunnelEngineOpen(&engineSession);\n- if (engineSession) {\n- OvsTunnelRemoveSystemProvider(engineSession);\n- }\n- OvsTunnelEngineClose(&engineSession);\n-\n- OvsUnsubscribeTunnelProviderBfeStateChanges();\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * This function initializes the tunnel filter if the BFE is running.\n- * --------------------------------------------------------------------------\n- */\n-VOID NTAPI\n-OvsTunnelInitBfeCallback(PVOID context,\n- FWPM_SERVICE_STATE bfeState)\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n- PDRIVER_OBJECT driverObject = (PDRIVER_OBJECT) context;\n-\n- if (FWPM_SERVICE_RUNNING == bfeState) {\n- status = OvsTunnelFilterInitialize(driverObject);\n- if (!NT_SUCCESS(status)) {\n- OVS_LOG_ERROR(\n- \"Failed to initialize tunnel filter, status: %x.\",\n- status);\n- }\n- }\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * This function registers the OvsTunnelInitBfeCallback callback that is\n- * called whenever there is a change to the state of base filtering engine.\n- * --------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsSubscribeTunnelInitBfeStateChanges(PDRIVER_OBJECT driverObject,\n- PVOID deviceObject)\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n-\n- if (!gTunnelInitBfeHandle) {\n- status = FwpmBfeStateSubscribeChanges(deviceObject,\n- OvsTunnelInitBfeCallback,\n- driverObject,\n- &gTunnelInitBfeHandle);\n- if (!NT_SUCCESS(status)) {\n- OVS_LOG_ERROR(\n- \"Failed to subscribe BFE tunnel init callback, status: %x.\",\n- status);\n- }\n- }\n-\n- return status;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * This function unregisters the OvsTunnelInitBfeCallback callback that\n- * was previously registered by OvsSubscribeTunnelInitBfeStateChanges\n- * function.\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-OvsUnsubscribeTunnelInitBfeStateChanges()\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n-\n- if (gTunnelInitBfeHandle) {\n- status = FwpmBfeStateUnsubscribeChanges(gTunnelInitBfeHandle);\n- if (!NT_SUCCESS(status)) {\n- OVS_LOG_ERROR(\n- \"Failed to unsubscribe BFE tunnel init callback, status: %x.\",\n- status);\n- }\n- gTunnelInitBfeHandle = NULL;\n- }\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * This function initializes the OVS tunnel filter if the BFE (Base Filtering\n- * Engine) is running.\n- * Otherwise, it will register the OvsTunnelInitBfeCallback callback.\n-\n- * Note: Before calling FwpmBfeStateGet, the callout driver must call the\n- * FwpmBfeStateSubscribeChanges function to register the callback function\n- * to be called whenever the state of the filter engine changes.\n- *\n- * Initialize OVS tunnel filter call hierarchy:\n- * <OvsExtAttach>\n- * <OvsCreateSwitch>\n- * <OvsInitTunnelFilter>\n- * <OvsSubscribeTunnelInitBfeStateChanges>\n- * --> registers OvsTunnelInitBfeCallback callback\n- * <OvsTunnelInitBfeCallback>\n- * --> if BFE is running:\n- * <OvsTunnelFilterInitialize>\n- * <IoCreateDevice>\n- * <OvsTunnelFilterStartThreads>\n- * <OvsTunnelRegisterCallouts>\n- * --> if BFE is running:\n- * <OvsTunnelFilterInitialize>\n- * <IoCreateDevice>\n- * <OvsTunnelFilterStartThreads>\n- * <OvsTunnelRegisterCallouts>\n- * <OvsUnsubscribeTunnelInitBfeStateChanges>\n- * --> unregisters OvsTunnelInitBfeCallback callback\n- *\n- * --------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsInitTunnelFilter(PDRIVER_OBJECT driverObject, PVOID deviceObject)\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n-\n- if (deviceObject) {\n- status = OvsSubscribeTunnelInitBfeStateChanges(driverObject, deviceObject);\n- if (NT_SUCCESS(status)) {\n- if (FWPM_SERVICE_RUNNING == FwpmBfeStateGet()) {\n- status = OvsTunnelFilterInitialize(driverObject);\n- if (!NT_SUCCESS(status)) {\n- /* XXX: We need to decide what actions to take in case of\n- * failure to initialize tunnel filter. */\n- ASSERT(status == NDIS_STATUS_SUCCESS);\n- OVS_LOG_ERROR(\n- \"Failed to initialize tunnel filter, status: %x.\",\n- status);\n- }\n- OvsUnsubscribeTunnelInitBfeStateChanges();\n- }\n- }\n- } else {\n- status = OvsTunnelFilterInitialize(driverObject);\n- }\n-\n- return status;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * This function uninitializes the OVS tunnel filter and unregisters the\n- * OvsTunnelInitBfeCallback callback from BFE.\n- *\n- * Uninitialize OVS tunnel filter call hierarchy:\n- * <OvsExtDetach>\n- * <OvsDeleteSwitch>\n- * <OvsUninitTunnelFilter>\n- * <OvsTunnelFilterUninitialize>\n- * <OvsTunnelFilterStopThreads>\n- * <OvsTunnelUnregisterCallouts>\n- * <IoDeleteDevice>\n- * <OvsUnsubscribeTunnelInitBfeStateChanges>\n- * --> unregisters OvsTunnelInitBfeCallback callback\n- *\n- * --------------------------------------------------------------------------\n- */\n-VOID OvsUninitTunnelFilter(PDRIVER_OBJECT driverObject)\n-{\n- OvsTunnelFilterUninitialize(driverObject);\n- OvsUnsubscribeTunnelInitBfeStateChanges();\n-}\n-\n-NTSTATUS\n-OvsTunnelAddFilterEx(HANDLE engineSession,\n- UINT32 filterPort,\n- UINT64 *filterID)\n-{\n- NTSTATUS status;\n-\n- status = OvsTunnelAddFilter(engineSession,\n- L\"Datagram-Data OVS Filter (Inbound)\",\n- L\"address/port for UDP\",\n- (USHORT)filterPort,\n- FWP_DIRECTION_INBOUND,\n- 0,\n- NULL,\n- &FWPM_LAYER_DATAGRAM_DATA_V4,\n- &OVS_TUNNEL_CALLOUT_V4,\n- filterID);\n- if (!NT_SUCCESS(status)) {\n- OVS_LOG_ERROR(\"Failed to add tunnel filter for port: %d, status: %x.\",\n- filterPort, status);\n- } else {\n- OVS_LOG_INFO(\"Filter added, filter port: %d, filter ID: %d.\",\n- filterPort, *filterID);\n- }\n-\n- return status;\n-}\n-\n-NTSTATUS\n-OvsTunnelRemoveFilterEx(HANDLE engineSession,\n- UINT64 filterID)\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n- BOOLEAN error = TRUE;\n-\n- do {\n- if (filterID == 0) {\n- OVS_LOG_INFO(\"No tunnel filter to remove.\");\n- break;\n- }\n-\n- status = FwpmFilterDeleteById(engineSession, filterID);\n- if (!NT_SUCCESS(status)) {\n- OVS_LOG_ERROR(\"Failed to remove tunnel with filter ID: %d,\\\n- status: %x.\", filterID, status);\n- break;\n- }\n- OVS_LOG_INFO(\"Filter removed, filter ID: %d.\",\n- filterID);\n-\n- error = FALSE;\n- } while (error);\n-\n- return status;\n-}\n-\n-NTSTATUS\n-OvsTunnelFilterExecuteAction(HANDLE engineSession,\n- POVS_TUNFLT_REQUEST request)\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n-\n- switch (request->operation)\n- {\n- case OVS_TUN_FILTER_CREATE:\n- status = OvsTunnelAddFilterEx(engineSession,\n- request->port,\n- request->filterID.addID);\n- break;\n- case OVS_TUN_FILTER_DELETE:\n- status = OvsTunnelRemoveFilterEx(engineSession,\n- request->filterID.delID);\n- break;\n- default:\n- status = STATUS_NOT_SUPPORTED;\n- break;\n- }\n-\n- return status;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * This function pops the head request from the queue while holding the\n- * queue lock. If the request has already been cancelled or is about to be\n- * cancelled, the function retrieves the next valid request.\n- *\n- * Returns a pointer to the OVS_TUNFLT_REQUEST_LIST request object retrieved\n- * from the queue.\n- * --------------------------------------------------------------------------\n- */\n-POVS_TUNFLT_REQUEST\n-OvsTunnelFilterRequestPop(POVS_TUNFLT_REQUEST_LIST listRequests)\n-{\n- POVS_TUNFLT_REQUEST request = NULL;\n- PLIST_ENTRY link, next, head;\n-\n- NdisAcquireSpinLock(&listRequests->spinlock);\n-\n- if (!IsListEmpty(&listRequests->head)) {\n- head = &listRequests->head;\n- LIST_FORALL_SAFE(head, link, next) {\n- PDRIVER_CANCEL oldCancelRoutine;\n-\n- request = CONTAINING_RECORD(link, OVS_TUNFLT_REQUEST, entry);\n- if (request->irp) {\n- oldCancelRoutine = IoSetCancelRoutine(request->irp, NULL);\n- if (oldCancelRoutine == NULL) {\n- /*\n- * The Cancel routine for the current IRP is running. The\n- * request is to be completed by the Cancel routine. Leave\n- * this request alone and go to the next one.\n- */\n- continue;\n- } else {\n- /*\n- * The Cancel routine cannot run now and cannot already have\n- * started to run. This request can be processed.\n- */\n- }\n- }\n-\n- RemoveEntryList(&request->entry);\n- listRequests->numEntries--;\n- break;\n- }\n- }\n-\n- NdisReleaseSpinLock(&listRequests->spinlock);\n-\n- return request;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * This function pushes the received request to the queue, marks the IRP as\n- * pending and sets its Cancel routine, while holding the queue lock.\n- *\n- * Returns STATUS_CANCELLED if the IRP has already been cancelled. Otherwise,\n- * STATUS_SUCCESS is returned.\n- * --------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsTunnelFilterRequestPush(POVS_TUNFLT_REQUEST_LIST listRequests,\n- POVS_TUNFLT_REQUEST request)\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n- PIRP irp = request->irp;\n- PDRIVER_CANCEL oldCancelRoutine;\n- BOOLEAN cancelled = FALSE;\n-\n- NdisAcquireSpinLock(&listRequests->spinlock);\n-\n- if (irp) {\n- /*\n- * Mark the IRP pending to indicate that the request may complete on\n- * a different thread.\n- */\n- IoMarkIrpPending(irp);\n-\n- /*\n- * Set the Cancel routine for the pending IRP, before checking the\n- * Cancel flag.\n- */\n- oldCancelRoutine = IoSetCancelRoutine(irp, OvsTunnelFilterCancelIrp);\n- ASSERT(oldCancelRoutine == NULL);\n-\n- if (irp->Cancel) {\n- /*\n- * The IRP has already been cancelled.\n- * Determine wheather the Cancel routine has started to run.\n- */\n- oldCancelRoutine = IoSetCancelRoutine(irp, NULL);\n- if (oldCancelRoutine) {\n- /*\n- * The I/O Manager has not called the Cancel routine and it\n- * won't be called anymore, because we just set it to NULL.\n- * Return STATUS_CANCELLED and complete the request after\n- * releasing the lock.\n- */\n- status = STATUS_CANCELLED;\n- cancelled = TRUE;\n- } else {\n- /*\n- * The Cancel routine has already started to run, but it is\n- * blocked while it waits for the queue lock. Release the lock\n- * and return STATUS_SUCCESS to avoid completing the request.\n- * It will be completed in the Cancel routine.\n- */\n- }\n- } else {\n- /*\n- * The IRP has not been cancelled, so set its context used in the\n- * Cancel routine.\n- */\n- OvsTunnelFilterSetIrpContext(listRequests, request);\n- }\n- }\n-\n- if (!cancelled) {\n- InsertTailList(&listRequests->head, &(request->entry));\n- listRequests->numEntries++;\n- }\n-\n- NdisReleaseSpinLock(&listRequests->spinlock);\n-\n- return status;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * This function pushes the received request to the corresponding thread\n- * request queue. The arrival of the new request is signaled to the thread,\n- * in order to start processing it.\n- *\n- * Note:\n- * If the thread is not initialized, no operation is performed.\n- *\n- * For a uniform distribution of requests to thread queues, a thread index is\n- * calculated based on the received destination port.\n- * --------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsTunnelFilterThreadPush(POVS_TUNFLT_REQUEST request)\n-{\n- NTSTATUS status = STATUS_REQUEST_ABORTED;\n- UINT32 count = OVS_TUNFLT_MAX_THREADS;\n- UINT32 threadIndex;\n-\n- threadIndex = request->port % OVS_TUNFLT_MAX_THREADS;\n-\n- while (count--) {\n- if (gTunnelThreadCtx[threadIndex].isInitialized) {\n-\n- status = OvsTunnelFilterRequestPush(\n- &gTunnelThreadCtx[threadIndex].listRequests,\n- request);\n-\n- if (NT_SUCCESS(status)) {\n- KeSetEvent(&gTunnelThreadCtx[threadIndex].requestEvent,\n- IO_NO_INCREMENT,\n- FALSE);\n- }\n-\n- break;\n- } else {\n- OVS_LOG_INFO(\"OVS tunnel filter thread %d not initialized.\",\n- threadIndex);\n- }\n-\n- threadIndex = (threadIndex + 1) % OVS_TUNFLT_MAX_THREADS;\n- }\n-\n- return status;\n-}\n-\n-VOID\n-OvsTunnelFilterCompleteRequest(PIRP irp,\n- PFNTunnelVportPendingOp callback,\n- PVOID context,\n- NTSTATUS status)\n-{\n- UINT32 replyLen = 0;\n-\n- if (callback) {\n- callback(context, status, &replyLen);\n- /* Release the context passed to the callback function. */\n- OvsFreeMemory(context);\n- }\n-\n- if (irp) {\n- OvsCompleteIrpRequest(irp, (ULONG_PTR)replyLen, status);\n- }\n-}\n-\n-VOID\n-OvsTunnelFilterRequestListProcess(POVS_TUNFLT_THREAD_CONTEXT threadCtx)\n-{\n- POVS_TUNFLT_REQUEST request = NULL;\n- NTSTATUS status = STATUS_SUCCESS;\n- BOOLEAN inTransaction = FALSE;\n-\n- do {\n- if (!InterlockedCompareExchange(\n- (LONG volatile *)&threadCtx->listRequests.numEntries, 0, 0)) {\n- OVS_LOG_INFO(\"Nothing to do... request list is empty.\");\n- break;\n- }\n-\n- status = FwpmTransactionBegin(threadCtx->engineSession, 0);\n- if (!NT_SUCCESS(status)) {\n- OVS_LOG_ERROR(\"Failed to start transaction, status: %x.\",\n- status);\n- break;\n- }\n- inTransaction = TRUE;\n-\n- while (NULL !=\n- (request = OvsTunnelFilterRequestPop(&threadCtx->listRequests))) {\n-\n- status = OvsTunnelFilterExecuteAction(threadCtx->engineSession,\n- request);\n-\n- /* Complete the IRP with the last operation status. */\n- OvsTunnelFilterCompleteRequest(request->irp,\n- request->callback,\n- request->context,\n- status);\n-\n- OvsFreeMemory(request);\n- request = NULL;\n- }\n-\n- status = FwpmTransactionCommit(threadCtx->engineSession);\n- if (!NT_SUCCESS(status)) {\n- OVS_LOG_ERROR(\"Failed to commit transaction, status: %x.\",\n- status);\n- break;\n- }\n-\n- inTransaction = FALSE;\n- } while (inTransaction);\n-\n- if (inTransaction) {\n- FwpmTransactionAbort(threadCtx->engineSession);\n- OVS_LOG_ERROR(\"Failed to execute request, status: %x.\\\n- Transaction aborted.\", status);\n- }\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * System thread routine that processes thread's requests queue. The thread\n- * routine initializes thread's necessary data and waits on two events,\n- * requestEvent and stopEvent. Whenever a request is pushed to the thread's\n- * queue, the requestEvent is signaled and the thread routine starts processing\n- * the arrived requests. When stopEvent is signaled, all subsequent requests\n- * are completed with STATUS_CANCELED, without being added to the thread's\n- * queue, and the routine finishes processing all existing requests from the\n- * queue before uninitializing the thread and exiting.\n- *----------------------------------------------------------------------------\n- */\n-_Use_decl_annotations_\n-VOID\n-OvsTunnelFilterThreadProc(PVOID context)\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n- POVS_TUNFLT_THREAD_CONTEXT threadCtx = (POVS_TUNFLT_THREAD_CONTEXT)context;\n- PKEVENT eventArray[2] = { 0 };\n- ULONG count = 0;\n- BOOLEAN exit = FALSE;\n- BOOLEAN error = TRUE;\n-\n- OVS_LOG_INFO(\"Starting OVS Tunnel system thread %d.\",\n- threadCtx->threadID);\n-\n- eventArray[0] = &threadCtx->stopEvent;\n- eventArray[1] = &threadCtx->requestEvent;\n- count = ARRAY_SIZE(eventArray);\n-\n- do {\n- status = OvsTunnelFilterThreadInit(threadCtx);\n- if (!NT_SUCCESS(status)) {\n- OVS_LOG_ERROR(\"Failed to initialize tunnel filter thread %d.\",\n- threadCtx->threadID);\n- break;\n- }\n-\n- do {\n- status = KeWaitForMultipleObjects(count,\n- (PVOID)eventArray,\n- WaitAny,\n- Executive,\n- KernelMode,\n- FALSE,\n- NULL,\n- NULL);\n- switch (status) {\n- case STATUS_WAIT_1:\n- /* Start processing requests. */\n- OvsTunnelFilterRequestListProcess(threadCtx);\n- break;\n- default:\n- /* Finish processing the remaining requests and exit. */\n- OvsTunnelFilterRequestListProcess(threadCtx);\n- exit = TRUE;\n- break;\n- }\n- } while (!exit);\n-\n- OvsTunnelFilterThreadUninit(threadCtx);\n-\n- error = FALSE;\n- } while (error);\n-\n- OVS_LOG_INFO(\"Terminating OVS Tunnel system thread %d.\",\n- threadCtx->threadID);\n-\n- PsTerminateSystemThread(STATUS_SUCCESS);\n-};\n-\n-static NTSTATUS\n-OvsTunnelFilterStartThreads()\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n-\n- for (UINT index = 0; index < OVS_TUNFLT_MAX_THREADS; index++) {\n- gTunnelThreadCtx[index].threadID = index;\n-\n- status = OvsTunnelFilterThreadStart(&gTunnelThreadCtx[index]);\n- if (!NT_SUCCESS(status)) {\n- OVS_LOG_ERROR(\"Failed to start tunnel filter thread %d.\", index);\n- break;\n- }\n- }\n-\n- return status;\n-}\n-\n-static NTSTATUS\n-OvsTunnelFilterThreadStart(POVS_TUNFLT_THREAD_CONTEXT threadCtx)\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n- HANDLE threadHandle = NULL;\n- BOOLEAN error = TRUE;\n-\n- do {\n- status = PsCreateSystemThread(&threadHandle,\n- SYNCHRONIZE,\n- NULL,\n- NULL,\n- NULL,\n- OvsTunnelFilterThreadProc,\n- threadCtx);\n- if (!NT_SUCCESS(status)) {\n- OVS_LOG_ERROR(\"Failed to create tunnel thread, status: %x.\",\n- status);\n- break;\n- }\n-\n- ObReferenceObjectByHandle(threadHandle,\n- SYNCHRONIZE,\n- NULL,\n- KernelMode,\n- &threadCtx->threadObject,\n- NULL);\n- ZwClose(threadHandle);\n- threadHandle = NULL;\n-\n- error = FALSE;\n- } while (error);\n-\n- return status;\n-}\n-\n-static VOID\n-OvsTunnelFilterStopThreads()\n-{\n- /* Signal all threads to stop and ignore all subsequent requests. */\n- for (UINT index = 0; index < OVS_TUNFLT_MAX_THREADS; index++) {\n- OvsTunnelFilterThreadStop(&gTunnelThreadCtx[index], TRUE);\n- }\n-\n- /* Wait for all threads to finish processing the requests. */\n- for (UINT index = 0; index < OVS_TUNFLT_MAX_THREADS; index++) {\n- OvsTunnelFilterThreadStop(&gTunnelThreadCtx[index], FALSE);\n- }\n-}\n-\n-static VOID\n-OvsTunnelFilterThreadStop(POVS_TUNFLT_THREAD_CONTEXT threadCtx,\n- BOOLEAN signalEvent)\n-{\n- if (threadCtx->isInitialized) {\n-\n- if (signalEvent) {\n- /* Signal stop thread event. */\n- OVS_LOG_INFO(\"Received stop event for OVS Tunnel system thread %d.\",\n- threadCtx->threadID);\n- KeSetEvent(&threadCtx->stopEvent, IO_NO_INCREMENT, FALSE);\n- } else {\n- /* Wait for the tunnel thread to finish. */\n- KeWaitForSingleObject(threadCtx->threadObject,\n- Executive,\n- KernelMode,\n- FALSE,\n- NULL);\n-\n- ObDereferenceObject(threadCtx->threadObject);\n- }\n- }\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * This function initializes thread's necessary data. Each thread has its own\n- * session object to the BFE that is used for processing the requests from\n- * the thread's queue.\n- * --------------------------------------------------------------------------\n- */\n-static NTSTATUS\n-OvsTunnelFilterThreadInit(POVS_TUNFLT_THREAD_CONTEXT threadCtx)\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n- BOOLEAN error = TRUE;\n-\n- do {\n- /* Create thread's engine session object. */\n- status = OvsTunnelEngineOpen(&threadCtx->engineSession);\n- if (!NT_SUCCESS(status)) {\n- break;\n- }\n-\n- NdisAllocateSpinLock(&threadCtx->listRequests.spinlock);\n-\n- InitializeListHead(&threadCtx->listRequests.head);\n-\n- KeInitializeEvent(&threadCtx->stopEvent,\n- NotificationEvent,\n- FALSE);\n-\n- KeInitializeEvent(&threadCtx->requestEvent,\n- SynchronizationEvent,\n- FALSE);\n-\n- threadCtx->isInitialized = TRUE;\n-\n- error = FALSE;\n- } while (error);\n-\n- return status;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * This function uninitializes thread's private data. Thread's engine session\n- * handle is closed and set to NULL.\n- * --------------------------------------------------------------------------\n- */\n-static VOID\n-OvsTunnelFilterThreadUninit(POVS_TUNFLT_THREAD_CONTEXT threadCtx)\n-{\n- if (threadCtx->engineSession) {\n- /* Close thread's FWPM session. */\n- OvsTunnelEngineClose(&threadCtx->engineSession);\n-\n- NdisFreeSpinLock(&threadCtx->listRequests.spinlock);\n-\n- threadCtx->isInitialized = FALSE;\n- }\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * This function creates a new tunnel filter request and push it to a thread\n- * queue. If the thread stop event is signaled, the request is completed with\n- * STATUS_REQUEST_ABORTED without pushing it to any queue.\n- * --------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsTunnelFilterQueueRequest(PIRP irp,\n- UINT16 remotePort,\n- UINT64 *filterID,\n- OVS_TUNFLT_OPERATION operation,\n- PFNTunnelVportPendingOp callback,\n- PVOID tunnelContext)\n-{\n- POVS_TUNFLT_REQUEST request = NULL;\n- NTSTATUS status = STATUS_PENDING;\n- NTSTATUS result = STATUS_SUCCESS;\n- BOOLEAN error = TRUE;\n- UINT64 timeout = 0;\n-\n- do {\n- /* Verify if the stop event was signaled. */\n- if (STATUS_SUCCESS == KeWaitForSingleObject(\n- &gTunnelThreadCtx[0].stopEvent,\n- Executive,\n- KernelMode,\n- FALSE,\n- (LARGE_INTEGER *)&timeout)) {\n- /* The stop event is signaled. Completed the IRP with\n- * STATUS_REQUEST_ABORTED. */\n- status = STATUS_REQUEST_ABORTED;\n- break;\n- }\n-\n- if (NULL == filterID) {\n- OVS_LOG_ERROR(\"Invalid request.\");\n- status = STATUS_INVALID_PARAMETER;\n- break;\n- }\n-\n- request = (POVS_TUNFLT_REQUEST)\n- OvsAllocateMemoryWithTag(sizeof(*request),\n- OVS_TUNFLT_POOL_TAG);\n- if (NULL == request) {\n- OVS_LOG_ERROR(\"Failed to allocate list item.\");\n- status = STATUS_INSUFFICIENT_RESOURCES;\n- break;\n- }\n-\n- request->port = remotePort;\n- request->operation = operation;\n- switch (operation) {\n- case OVS_TUN_FILTER_CREATE:\n- request->filterID.addID = filterID;\n- break;\n- case OVS_TUN_FILTER_DELETE:\n- request->filterID.delID = *filterID;\n- break;\n- }\n- request->irp = irp;\n- request->callback = callback;\n- request->context = tunnelContext;\n-\n- result = OvsTunnelFilterThreadPush(request);\n- if (!NT_SUCCESS(result)) {\n- status = result;\n- break;\n- }\n-\n- error = FALSE;\n- } while (error);\n-\n- if (error) {\n- OvsTunnelFilterCompleteRequest(irp,\n- callback,\n- tunnelContext,\n- status);\n- if (request) {\n- OvsFreeMemory(request);\n- request = NULL;\n- }\n- }\n-\n- return status;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * This function adds a new WFP filter for the received port and returns the\n- * ID of the created WFP filter.\n- *\n- * Note:\n- * All necessary calls to the WFP filtering engine must be running at IRQL =\n- * PASSIVE_LEVEL. Because the function is called at IRQL = DISPATCH_LEVEL,\n- * we register an OVS_TUN_FILTER_CREATE request that will be processed by\n- * the tunnel filter thread routine at IRQL = PASSIVE_LEVEL.\n- *\n- * OVS VXLAN port add call hierarchy:\n- * <OvsNewVportCmdHandler>\n- * <OvsInitTunnelVport>\n- * <OvsInitVxlanTunnel>\n- * <OvsTunnelFilterCreate>\n- * <OvsTunnelFilterQueueRequest>\n- * --> if thread STOP event is signalled:\n- * --> Complete request with STATUS_CANCELLED\n- * --> EXIT\n- * <OvsTunnelFilterThreadPush>\n- * --> add the request to one of tunnel thread queues\n- *\n- * --------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsTunnelFilterCreate(PIRP irp,\n- UINT16 filterPort,\n- UINT64 *filterID,\n- PFNTunnelVportPendingOp callback,\n- PVOID tunnelContext)\n-{\n- return OvsTunnelFilterQueueRequest(irp,\n- filterPort,\n- filterID,\n- OVS_TUN_FILTER_CREATE,\n- callback,\n- tunnelContext);\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * This function removes a WFP filter using the received filter ID.\n- *\n- * Note:\n- * All necessary calls to the WFP filtering engine must be running at IRQL =\n- * PASSIVE_LEVEL. Because the function is called at IRQL = DISPATCH_LEVEL,\n- * we register an OVS_TUN_FILTER_DELETE request that will be processed by\n- * the tunnel filter thread routine at IRQL = PASSIVE_LEVEL.\n- *\n- * OVS VXLAN port delete call hierarchy:\n- * <OvsDeleteVportCmdHandler>\n- * <OvsRemoveAndDeleteVport>\n- * <OvsCleanupVxlanTunnel>\n- * <OvsTunnelFilterDelete>\n- * <OvsTunnelFilterQueueRequest>\n- * --> if thread STOP event is signalled:\n- * --> Complete request with STATUS_CANCELLED\n- * --> EXIT\n- * <OvsTunnelFilterThreadPush>\n- * --> add the request to one of tunnel thread queues\n- *\n- * --------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsTunnelFilterDelete(PIRP irp,\n- UINT64 filterID,\n- PFNTunnelVportPendingOp callback,\n- PVOID tunnelContext)\n-{\n- return OvsTunnelFilterQueueRequest(irp,\n- 0,\n- &filterID,\n- OVS_TUN_FILTER_DELETE,\n- callback,\n- tunnelContext);\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * This function sets the context for the IRP. The context is used by the\n- * Cancel routine, in order to identify the request object, corresponding to\n- * the IRP, to be completed and to have access to the queue lock to remove\n- * the request link from the queue.\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-OvsTunnelFilterSetIrpContext(POVS_TUNFLT_REQUEST_LIST listRequests,\n- POVS_TUNFLT_REQUEST request)\n-{\n- PIRP irp = request->irp;\n-\n- if (irp) {\n- /* Set the IRP's DriverContext to be used for later. */\n- irp->Tail.Overlay.DriverContext[0] = (PVOID)request;\n- irp->Tail.Overlay.DriverContext[1] = (PVOID)listRequests;\n- }\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * This function is the Cancel routine to be called by the I/O Manager in the\n- * case the IRP is canceled.\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-OvsTunnelFilterCancelIrp(PDEVICE_OBJECT DeviceObject,\n- PIRP irp)\n-{\n- POVS_TUNFLT_REQUEST request =\n- (POVS_TUNFLT_REQUEST)irp->Tail.Overlay.DriverContext[0];\n- POVS_TUNFLT_REQUEST_LIST listRequests =\n- (POVS_TUNFLT_REQUEST_LIST)irp->Tail.Overlay.DriverContext[1];\n-\n- DBG_UNREFERENCED_PARAMETER(DeviceObject);\n-\n- /* Release the global cancel spinlock. */\n- IoReleaseCancelSpinLock(irp->CancelIrql);\n-\n- /* Clear the cancel routine from the IRP. */\n- IoSetCancelRoutine(irp, NULL);\n-\n- NdisAcquireSpinLock(&listRequests->spinlock);\n-\n- /* Remove the request from the corresponding tunnel filter thread queue. */\n- RemoveEntryList(&request->entry);\n- listRequests->numEntries--;\n-\n- NdisReleaseSpinLock(&listRequests->spinlock);\n-\n- /* We are done with this IRP, so complete it with STATUS_CANCELLED. */\n- OvsTunnelFilterCompleteRequest(request->irp,\n- request->callback,\n- request->context,\n- STATUS_CANCELLED);\n-\n- OvsFreeMemory(request);\n-}\ndiff --git a/datapath-windows/ovsext/TunnelIntf.h b/datapath-windows/ovsext/TunnelIntf.h\ndeleted file mode 100644\nindex 6a3730172..000000000\n--- a/datapath-windows/ovsext/TunnelIntf.h\n+++ /dev/null\n@@ -1,44 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#ifndef __TUNNEL_INTF_H_\n-#define __TUNNEL_INTF_H_ 1\n-\n-typedef VOID(*PFNTunnelVportPendingOp)(PVOID context,\n- NTSTATUS status,\n- UINT32 *replyLen);\n-\n-/* Tunnel callout driver load/unload functions */\n-NTSTATUS OvsInitTunnelFilter(PDRIVER_OBJECT driverObject, PVOID deviceObject);\n-\n-VOID OvsUninitTunnelFilter(PDRIVER_OBJECT driverObject);\n-\n-VOID OvsRegisterSystemProvider(PVOID deviceObject);\n-\n-VOID OvsUnregisterSystemProvider();\n-\n-NTSTATUS OvsTunnelFilterCreate(PIRP irp,\n- UINT16 filterPort,\n- UINT64 *filterID,\n- PFNTunnelVportPendingOp callback,\n- PVOID context);\n-\n-NTSTATUS OvsTunnelFilterDelete(PIRP irp,\n- UINT64 filterID,\n- PFNTunnelVportPendingOp callback,\n- PVOID context);\n-\n-#endif /* __TUNNEL_INTF_H_ */\ndiff --git a/datapath-windows/ovsext/Types.h b/datapath-windows/ovsext/Types.h\ndeleted file mode 100644\nindex 4da335a11..000000000\n--- a/datapath-windows/ovsext/Types.h\n+++ /dev/null\n@@ -1,53 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#ifndef __TYPES_H_\n-#define __TYPES_H_ 1\n-\n-/* Defines the userspace specific data types\n- * for files included from user space. */\n-typedef unsigned long long uint64, uint64_t, ovs_be64, u64;\n-typedef long long int64, int64_t;\n-typedef unsigned int uint32, uint32_t, ovs_be32, u32;\n-typedef unsigned short uint16, uint16_t, ovs_be16, u16;\n-typedef unsigned char uint8, uint8_t, u8;\n-typedef uint64 __u64, __be64;\n-typedef uint32 __u32, __be32;\n-typedef uint16 __u16, __be16;\n-typedef uint8 __u8;\n-typedef union ovs_u128 {\n- uint32_t u32[4];\n- struct {\n- uint64_t lo, hi;\n- } u64;\n-} ovs_u128;\n-\n-/* Defines the userspace specific data types for file\n- * included within kernel only. */\n-typedef UINT8 BE8;\n-typedef UINT16 BE16;\n-typedef UINT32 BE32;\n-typedef UINT64 BE64;\n-\n-typedef uint32_t ofp_port_t;\n-typedef uint32_t odp_port_t;\n-typedef uint32_t ofp11_port_t;\n-\n-#define ETH_ALEN 6\n-\n-#define SIZE_MAX MAXUINT32\n-\n-#endif /* __TYPES_H_ */\ndiff --git a/datapath-windows/ovsext/User.c b/datapath-windows/ovsext/User.c\ndeleted file mode 100644\nindex 36af34f5e..000000000\n--- a/datapath-windows/ovsext/User.c\n+++ /dev/null\n@@ -1,1310 +0,0 @@\n-/*\n- * Copyright (c) 2014, 2016 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-/*\n- * OvsUser.c\n- * Manage packet queue for packet miss for userAction.\n- */\n-\n-\n-#include \"precomp.h\"\n-\n-#include \"Actions.h\"\n-#include \"Datapath.h\"\n-#include \"Debug.h\"\n-#include \"Event.h\"\n-#include \"Flow.h\"\n-#include \"Jhash.h\"\n-#include \"NetProto.h\"\n-#include \"Offload.h\"\n-#include \"PacketIO.h\"\n-#include \"Switch.h\"\n-#include \"TunnelIntf.h\"\n-#include \"User.h\"\n-#include \"Vport.h\"\n-\n-#ifdef OVS_DBG_MOD\n-#undef OVS_DBG_MOD\n-#endif\n-#define OVS_DBG_MOD OVS_DBG_USER\n-\n-POVS_PACKET_QUEUE_ELEM OvsGetNextPacket(POVS_OPEN_INSTANCE instance);\n-extern PNDIS_SPIN_LOCK gOvsCtrlLock;\n-extern POVS_SWITCH_CONTEXT gOvsSwitchContext;\n-OVS_USER_STATS ovsUserStats;\n-\n-static VOID _MapNlAttrToOvsPktExec(PNL_MSG_HDR nlMsgHdr, PNL_ATTR *nlAttrs,\n- PNL_ATTR *keyAttrs,\n- OvsPacketExecute *execute);\n-extern NL_POLICY nlFlowKeyPolicy[];\n-extern UINT32 nlFlowKeyPolicyLen;\n-extern NL_POLICY nlFlowTunnelKeyPolicy[];\n-extern UINT32 nlFlowTunnelKeyPolicyLen;\n-DRIVER_CANCEL OvsCancelIrpDatapath;\n-\n-_IRQL_raises_(DISPATCH_LEVEL)\n-_IRQL_saves_global_(OldIrql, gOvsSwitchContext->pidHashLock)\n-_Acquires_lock_(gOvsSwitchContext->pidHashLock)\n-static __inline VOID\n-OvsAcquirePidHashLock()\n-{\n- NdisAcquireSpinLock(&(gOvsSwitchContext->pidHashLock));\n-}\n-\n-_IRQL_requires_(DISPATCH_LEVEL)\n-_IRQL_restores_global_(OldIrql, gOvsSwitchContext->pidHashLock)\n-_Requires_lock_held_(gOvsSwitchContext->pidHashLock)\n-_Releases_lock_(gOvsSwitchContext->pidHashLock)\n-static __inline VOID\n-OvsReleasePidHashLock()\n-{\n- NdisReleaseSpinLock(&(gOvsSwitchContext->pidHashLock));\n-}\n-\n-\n-static VOID\n-OvsPurgePacketQueue(POVS_USER_PACKET_QUEUE queue,\n- POVS_OPEN_INSTANCE instance)\n-{\n- PLIST_ENTRY link, next;\n- LIST_ENTRY tmp;\n- POVS_PACKET_QUEUE_ELEM elem;\n-\n- InitializeListHead(&tmp);\n- NdisAcquireSpinLock(&queue->queueLock);\n- if (queue->instance != instance) {\n- NdisReleaseSpinLock(&queue->queueLock);\n- return;\n- }\n-\n- if (queue->numPackets) {\n- OvsAppendList(&tmp, &queue->packetList);\n- queue->numPackets = 0;\n- }\n- NdisReleaseSpinLock(&queue->queueLock);\n- LIST_FORALL_SAFE(&tmp, link, next) {\n- RemoveEntryList(link);\n- elem = CONTAINING_RECORD(link, OVS_PACKET_QUEUE_ELEM, link);\n- OvsFreeMemoryWithTag(elem, OVS_USER_POOL_TAG);\n- }\n-}\n-\n-VOID\n-OvsCleanupPacketQueue(POVS_OPEN_INSTANCE instance)\n-{\n- POVS_USER_PACKET_QUEUE queue;\n- POVS_PACKET_QUEUE_ELEM elem;\n- PLIST_ENTRY link, next;\n- LIST_ENTRY tmp;\n- PIRP irp = NULL;\n-\n- ASSERT(instance);\n- InitializeListHead(&tmp);\n- queue = (POVS_USER_PACKET_QUEUE)instance->packetQueue;\n- if (queue) {\n- PDRIVER_CANCEL cancelRoutine;\n- NdisAcquireSpinLock(&queue->queueLock);\n- ASSERT(queue->instance == instance);\n- /* XXX Should not happen */\n- if (queue->instance != instance) {\n- NdisReleaseSpinLock(&queue->queueLock);\n- NdisFreeSpinLock(&queue->queueLock);\n- return;\n- }\n-\n- if (queue->numPackets) {\n- OvsAppendList(&tmp, &queue->packetList);\n- queue->numPackets = 0;\n- }\n- queue->instance = NULL;\n- instance->packetQueue = NULL;\n- irp = queue->pendingIrp;\n- queue->pendingIrp = NULL;\n- if (irp) {\n- cancelRoutine = IoSetCancelRoutine(irp, NULL);\n- if (cancelRoutine == NULL) {\n- irp = NULL;\n- }\n- }\n- NdisReleaseSpinLock(&queue->queueLock);\n- NdisFreeSpinLock(&queue->queueLock);\n- }\n- LIST_FORALL_SAFE(&tmp, link, next) {\n- RemoveEntryList(link);\n- elem = CONTAINING_RECORD(link, OVS_PACKET_QUEUE_ELEM, link);\n- OvsFreeMemoryWithTag(elem, OVS_USER_POOL_TAG);\n- }\n- if (irp) {\n- OvsCompleteIrpRequest(irp, 0, STATUS_SUCCESS);\n- }\n- if (queue) {\n- OvsFreeMemoryWithTag(queue, OVS_USER_POOL_TAG);\n- }\n-\n- /* Verify if gOvsSwitchContext exists. */\n- if (gOvsSwitchContext) {\n- /* Remove the instance from pidHashArray */\n- OvsAcquirePidHashLock();\n- OvsDelPidInstance(gOvsSwitchContext, instance->pid);\n- OvsReleasePidHashLock();\n- }\n-}\n-\n-NTSTATUS\n-OvsSubscribeDpIoctl(PVOID instanceP,\n- UINT32 pid,\n- UINT8 join)\n-{\n- POVS_USER_PACKET_QUEUE queue;\n- POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)instanceP;\n-\n- if (instance->packetQueue && !join) {\n- /* unsubscribe */\n- OvsCleanupPacketQueue(instance);\n- } else if (instance->packetQueue == NULL && join) {\n- queue = (POVS_USER_PACKET_QUEUE) OvsAllocateMemoryWithTag(\n- sizeof *queue, OVS_USER_POOL_TAG);\n- if (queue == NULL) {\n- return STATUS_NO_MEMORY;\n- }\n- InitializeListHead(&(instance->pidLink));\n- instance->packetQueue = queue;\n- RtlZeroMemory(queue, sizeof (*queue));\n- NdisAllocateSpinLock(&queue->queueLock);\n- NdisAcquireSpinLock(&queue->queueLock);\n- InitializeListHead(&queue->packetList);\n- queue->pid = pid;\n- queue->instance = instance;\n- instance->packetQueue = queue;\n- NdisReleaseSpinLock(&queue->queueLock);\n-\n- OvsAcquirePidHashLock();\n- /* Insert the instance to pidHashArray */\n- OvsAddPidInstance(gOvsSwitchContext, pid, instance);\n- OvsReleasePidHashLock();\n-\n- } else {\n- /* user mode should call only once for subscribe */\n- return STATUS_INVALID_PARAMETER;\n- }\n-\n- return STATUS_SUCCESS;\n-}\n-\n-\n-NTSTATUS\n-OvsReadDpIoctl(PFILE_OBJECT fileObject,\n- PVOID outputBuffer,\n- UINT32 outputLength,\n- UINT32 *replyLen)\n-{\n- POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)fileObject->FsContext;\n- POVS_PACKET_QUEUE_ELEM elem;\n- UINT32 len;\n-\n-#define TCP_CSUM_OFFSET 16\n-#define UDP_CSUM_OFFSET 6\n- ASSERT(instance);\n-\n- if (instance->packetQueue == NULL) {\n- return STATUS_INVALID_PARAMETER;\n- }\n- if (outputLength < (sizeof (OVS_PACKET_INFO) + OVS_MIN_PACKET_SIZE)) {\n- return STATUS_BUFFER_TOO_SMALL;\n- }\n-\n- elem = OvsGetNextPacket(instance);\n- if (elem) {\n- /*\n- * XXX revisit this later\n- */\n- len = elem->packet.totalLen > outputLength ? outputLength :\n- elem->packet.totalLen;\n-\n- if ((elem->hdrInfo.tcpCsumNeeded || elem->hdrInfo.udpCsumNeeded) &&\n- len == elem->packet.totalLen) {\n- UINT16 sum, *ptr;\n- UINT16 size = (UINT16)(elem->packet.payload - elem->packet.data +\n- elem->hdrInfo.l4Offset);\n- RtlCopyMemory(outputBuffer, &elem->packet.data, size);\n- ASSERT(len - size >= elem->hdrInfo.l4PayLoad);\n- sum = CopyAndCalculateChecksum((UINT8 *)outputBuffer + size,\n- (UINT8 *)&elem->packet.data + size,\n- elem->hdrInfo.l4PayLoad, 0);\n- ptr =(UINT16 *)((UINT8 *)outputBuffer + size +\n- (elem->hdrInfo.tcpCsumNeeded ?\n- TCP_CSUM_OFFSET : UDP_CSUM_OFFSET));\n- *ptr = sum;\n- ovsUserStats.l4Csum++;\n- } else {\n- RtlCopyMemory(outputBuffer, &elem->packet.data, len);\n- }\n-\n- *replyLen = len;\n- OvsFreeMemoryWithTag(elem, OVS_USER_POOL_TAG);\n- }\n- return STATUS_SUCCESS;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsNlExecuteCmdHandler --\n- * Handler for OVS_PACKET_CMD_EXECUTE command.\n- *----------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsNlExecuteCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen)\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n- POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;\n- POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer;\n- PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);\n- PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);\n- POVS_HDR ovsHdr = &(msgIn->ovsHdr);\n-\n- PNL_ATTR nlAttrs[__OVS_PACKET_ATTR_MAX];\n- PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX] = {NULL};\n-\n- UINT32 attrOffset = NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN;\n- UINT32 keyAttrOffset = 0;\n- OvsPacketExecute execute;\n- NL_ERROR nlError = NL_ERROR_SUCCESS;\n- NL_BUFFER nlBuf;\n-\n- static const NL_POLICY nlPktExecPolicy[] = {\n- [OVS_PACKET_ATTR_PACKET] = {.type = NL_A_UNSPEC, .optional = FALSE},\n- [OVS_PACKET_ATTR_KEY] = {.type = NL_A_UNSPEC, .optional = FALSE},\n- [OVS_PACKET_ATTR_ACTIONS] = {.type = NL_A_UNSPEC, .optional = FALSE},\n- [OVS_PACKET_ATTR_USERDATA] = {.type = NL_A_UNSPEC, .optional = TRUE},\n- [OVS_PACKET_ATTR_EGRESS_TUN_KEY] = {.type = NL_A_UNSPEC,\n- .optional = TRUE},\n- [OVS_PACKET_ATTR_MRU] = { .type = NL_A_U16, .optional = TRUE }\n- };\n-\n- RtlZeroMemory(&execute, sizeof(OvsPacketExecute));\n-\n- /* Get all the top level Flow attributes */\n- if ((NlAttrParse(nlMsgHdr, attrOffset, NlMsgAttrsLen(nlMsgHdr),\n- nlPktExecPolicy, ARRAY_SIZE(nlPktExecPolicy),\n- nlAttrs, ARRAY_SIZE(nlAttrs)))\n- != TRUE) {\n- OVS_LOG_ERROR(\"Attr Parsing failed for msg: %p\",\n- nlMsgHdr);\n- status = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n-\n- keyAttrOffset = (UINT32)((PCHAR)nlAttrs[OVS_PACKET_ATTR_KEY] -\n- (PCHAR)nlMsgHdr);\n-\n- /* Get flow keys attributes */\n- if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset,\n- NlAttrLen(nlAttrs[OVS_PACKET_ATTR_KEY]),\n- nlFlowKeyPolicy, nlFlowKeyPolicyLen,\n- keyAttrs, ARRAY_SIZE(keyAttrs))) != TRUE) {\n- OVS_LOG_ERROR(\"Key Attr Parsing failed for msg: %p\", nlMsgHdr);\n- status = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n-\n- if (keyAttrs[OVS_KEY_ATTR_ENCAP]) {\n- UINT32 encapOffset = 0;\n- PNL_ATTR encapAttrs[__OVS_KEY_ATTR_MAX];\n- encapOffset = (UINT32)((PCHAR)(keyAttrs[OVS_KEY_ATTR_ENCAP])\n- - (PCHAR)nlMsgHdr);\n-\n- if ((NlAttrParseNested(nlMsgHdr, encapOffset,\n- NlAttrLen(keyAttrs[OVS_KEY_ATTR_ENCAP]),\n- nlFlowKeyPolicy,\n- nlFlowKeyPolicyLen,\n- encapAttrs, ARRAY_SIZE(encapAttrs)))\n- != TRUE) {\n- OVS_LOG_ERROR(\"Encap Key Attr Parsing failed for msg: %p\",\n- nlMsgHdr);\n- status = STATUS_UNSUCCESSFUL;\n- goto done;\n- }\n- }\n-\n- execute.dpNo = ovsHdr->dp_ifindex;\n-\n- _MapNlAttrToOvsPktExec(nlMsgHdr, nlAttrs, keyAttrs, &execute);\n-\n- status = OvsExecuteDpIoctl(&execute);\n-\n- /* Default reply that we want to send */\n- if (status == STATUS_SUCCESS) {\n- BOOLEAN ok;\n-\n- NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,\n- usrParamsCtx->outputLength);\n-\n- /* Prepare nl Msg headers */\n- ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,\n- nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,\n- genlMsgHdr->cmd, OVS_PACKET_VERSION,\n- ovsHdr->dp_ifindex);\n-\n- if (ok) {\n- *replyLen = msgOut->nlMsg.nlmsgLen;\n- } else {\n- status = STATUS_INVALID_BUFFER_SIZE;\n- }\n- } else {\n- /* Map NTSTATUS to NL_ERROR */\n- nlError = NlMapStatusToNlErr(status);\n-\n- /* As of now there are no transactional errors in the implementation.\n- * Once we have them then we need to map status to correct\n- * nlError value, so that below mentioned code gets hit. */\n- if ((nlError != NL_ERROR_SUCCESS) &&\n- (usrParamsCtx->outputBuffer)) {\n-\n- POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)\n- usrParamsCtx->outputBuffer;\n-\n- ASSERT(msgError);\n- NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);\n- status = STATUS_SUCCESS;\n- goto done;\n- }\n- }\n-\n-done:\n- return status;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * _MapNlAttrToOvsPktExec --\n- * Maps input Netlink attributes to OvsPacketExecute.\n- *----------------------------------------------------------------------------\n- */\n-static VOID\n-_MapNlAttrToOvsPktExec(PNL_MSG_HDR nlMsgHdr, PNL_ATTR *nlAttrs,\n- PNL_ATTR *keyAttrs, OvsPacketExecute *execute)\n-{\n- execute->packetBuf = NlAttrGet(nlAttrs[OVS_PACKET_ATTR_PACKET]);\n- execute->packetLen = NlAttrGetSize(nlAttrs[OVS_PACKET_ATTR_PACKET]);\n-\n- execute->nlMsgHdr = nlMsgHdr;\n-\n- execute->actions = NlAttrGet(nlAttrs[OVS_PACKET_ATTR_ACTIONS]);\n- execute->actionsLen = NlAttrGetSize(nlAttrs[OVS_PACKET_ATTR_ACTIONS]);\n-\n- //TODO revisit and understand if this check is needed\n- if (keyAttrs[OVS_KEY_ATTR_IN_PORT]) {\n- execute->inPort = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_IN_PORT]);\n- }\n- execute->keyAttrs = keyAttrs;\n-\n- if (nlAttrs[OVS_PACKET_ATTR_MRU]) {\n- execute->mru = NlAttrGetU16(nlAttrs[OVS_PACKET_ATTR_MRU]);\n- }\n-}\n-\n-NTSTATUS\n-OvsExecuteDpIoctl(OvsPacketExecute *execute)\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n- NTSTATUS ndisStatus = STATUS_SUCCESS;\n- LOCK_STATE_EX lockState;\n- PNET_BUFFER_LIST pNbl = NULL;\n- PNL_ATTR actions = NULL;\n- PNDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO fwdDetail;\n- OvsFlowKey key = { 0 };\n- OVS_PACKET_HDR_INFO layers = { 0 };\n- POVS_VPORT_ENTRY vport = NULL;\n- PNL_ATTR tunnelAttrs[__OVS_TUNNEL_KEY_ATTR_MAX];\n- OvsFlowKey tempTunKey = {0};\n- POVS_BUFFER_CONTEXT ctx;\n-\n- if (execute->packetLen == 0) {\n- status = STATUS_INVALID_PARAMETER;\n- goto exit;\n- }\n-\n- actions = execute->actions;\n-\n- ASSERT(actions);\n-\n- /*\n- * Allocate the NBL, copy the data from the userspace buffer. Allocate\n- * also, the forwarding context for the packet.\n- */\n- pNbl = OvsAllocateNBLFromBuffer(gOvsSwitchContext, execute->packetBuf,\n- execute->packetLen);\n- if (pNbl == NULL) {\n- status = STATUS_NO_MEMORY;\n- goto exit;\n- }\n-\n- fwdDetail = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(pNbl);\n- // XXX: Figure out if any of the other members of fwdDetail need to be set.\n-\n- status = OvsGetFlowMetadata(&key, execute->keyAttrs);\n- if (status != STATUS_SUCCESS) {\n- goto dropit;\n- }\n-\n- if (execute->keyAttrs[OVS_KEY_ATTR_TUNNEL]) {\n- UINT32 tunnelKeyAttrOffset;\n-\n- tunnelKeyAttrOffset = (UINT32)((PCHAR)\n- (execute->keyAttrs[OVS_KEY_ATTR_TUNNEL])\n- - (PCHAR)execute->nlMsgHdr);\n-\n- /* Get tunnel keys attributes */\n- if ((NlAttrParseNested(execute->nlMsgHdr, tunnelKeyAttrOffset,\n- NlAttrLen(execute->keyAttrs[OVS_KEY_ATTR_TUNNEL]),\n- nlFlowTunnelKeyPolicy, nlFlowTunnelKeyPolicyLen,\n- tunnelAttrs, ARRAY_SIZE(tunnelAttrs)))\n- != TRUE) {\n- OVS_LOG_ERROR(\"Tunnel key Attr Parsing failed for msg: %p\",\n- execute->nlMsgHdr);\n- status = STATUS_INVALID_PARAMETER;\n- goto dropit;\n- }\n-\n- MapTunAttrToFlowPut(execute->keyAttrs, tunnelAttrs, &tempTunKey);\n- }\n-\n- ndisStatus = OvsExtractFlow(pNbl, execute->inPort, &key, &layers,\n- OvsIphIsZero(&tempTunKey.tunKey.dst)? NULL :\n- &tempTunKey.tunKey);\n-\n- if (ndisStatus != NDIS_STATUS_SUCCESS) {\n- /* Invalid network header */\n- goto dropit;\n- }\n-\n- ctx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(pNbl);\n- ctx->mru = execute->mru;\n-\n- if (ndisStatus == NDIS_STATUS_SUCCESS) {\n- NdisAcquireRWLockRead(gOvsSwitchContext->dispatchLock, &lockState, 0);\n- vport = OvsFindVportByPortNo(gOvsSwitchContext, execute->inPort);\n- if (vport) {\n- fwdDetail->SourcePortId = vport->portId;\n- fwdDetail->SourceNicIndex = vport->nicIndex;\n- } else {\n- fwdDetail->SourcePortId = NDIS_SWITCH_DEFAULT_PORT_ID;\n- fwdDetail->SourceNicIndex = 0;\n- }\n- ndisStatus = OvsActionsExecute(gOvsSwitchContext, NULL, pNbl,\n- vport ? vport->portNo :\n- OVS_DPPORT_NUMBER_INVALID,\n- NDIS_SEND_FLAGS_SWITCH_DESTINATION_GROUP,\n- &key, NULL, &layers, actions,\n- execute->actionsLen);\n- pNbl = NULL;\n- NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState);\n- }\n- if (ndisStatus != NDIS_STATUS_SUCCESS) {\n- if (ndisStatus == NDIS_STATUS_NOT_SUPPORTED) {\n- status = STATUS_NOT_SUPPORTED;\n- } else {\n- status = STATUS_UNSUCCESSFUL;\n- }\n- }\n-\n-dropit:\n- if (pNbl) {\n- OvsCompleteNBL(gOvsSwitchContext, pNbl, TRUE);\n- }\n-exit:\n- return status;\n-}\n-\n-\n-NTSTATUS\n-OvsPurgeDpIoctl(PFILE_OBJECT fileObject)\n-{\n- POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)fileObject->FsContext;\n- POVS_USER_PACKET_QUEUE queue = (POVS_USER_PACKET_QUEUE)instance->packetQueue;\n-\n- if (queue == NULL) {\n- return STATUS_INVALID_PARAMETER;\n- }\n- OvsPurgePacketQueue(queue, instance);\n- return STATUS_SUCCESS;\n-}\n-\n-VOID\n-OvsCancelIrpDatapath(PDEVICE_OBJECT deviceObject,\n- PIRP irp)\n-{\n- PIO_STACK_LOCATION irpSp;\n- PFILE_OBJECT fileObject;\n- POVS_OPEN_INSTANCE instance;\n- POVS_USER_PACKET_QUEUE queue = NULL;\n-\n- UNREFERENCED_PARAMETER(deviceObject);\n-\n- IoReleaseCancelSpinLock(irp->CancelIrql);\n- irpSp = IoGetCurrentIrpStackLocation(irp);\n- fileObject = irpSp->FileObject;\n-\n- if (fileObject == NULL) {\n- goto done;\n- }\n- NdisAcquireSpinLock(gOvsCtrlLock);\n- instance = (POVS_OPEN_INSTANCE)fileObject->FsContext;\n- if (instance) {\n- queue = instance->packetQueue;\n- }\n- if (instance == NULL || queue == NULL) {\n- NdisReleaseSpinLock(gOvsCtrlLock);\n- goto done;\n- }\n- NdisReleaseSpinLock(gOvsCtrlLock);\n- NdisAcquireSpinLock(&queue->queueLock);\n- if (queue->pendingIrp == irp) {\n- queue->pendingIrp = NULL;\n- }\n- NdisReleaseSpinLock(&queue->queueLock);\n-done:\n- OvsCompleteIrpRequest(irp, 0, STATUS_CANCELLED);\n-}\n-\n-\n-NTSTATUS\n-OvsWaitDpIoctl(PIRP irp, PFILE_OBJECT fileObject)\n-{\n- POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)fileObject->FsContext;\n- POVS_USER_PACKET_QUEUE queue =\n- (POVS_USER_PACKET_QUEUE)instance->packetQueue;\n- NTSTATUS status = STATUS_SUCCESS;\n- BOOLEAN cancelled = FALSE;\n-\n- if (queue == NULL) {\n- return STATUS_INVALID_PARAMETER;\n- }\n- NdisAcquireSpinLock(&queue->queueLock);\n- if (queue->instance != instance) {\n- NdisReleaseSpinLock(&queue->queueLock);\n- return STATUS_INVALID_PARAMETER;\n- }\n- if (queue->pendingIrp) {\n- NdisReleaseSpinLock(&queue->queueLock);\n- return STATUS_DEVICE_BUSY;\n- }\n- if (queue->numPackets == 0) {\n- PDRIVER_CANCEL cancelRoutine;\n- IoMarkIrpPending(irp);\n- IoSetCancelRoutine(irp, OvsCancelIrpDatapath);\n- if (irp->Cancel) {\n- cancelRoutine = IoSetCancelRoutine(irp, NULL);\n- if (cancelRoutine) {\n- cancelled = TRUE;\n- }\n- } else {\n- queue->pendingIrp = irp;\n- }\n- status = STATUS_PENDING;\n- }\n- NdisReleaseSpinLock(&queue->queueLock);\n- if (cancelled) {\n- OvsCompleteIrpRequest(irp, 0, STATUS_CANCELLED);\n- OVS_LOG_INFO(\"Datapath IRP cancelled: %p\", irp);\n- }\n- return status;\n-}\n-\n-\n-POVS_PACKET_QUEUE_ELEM\n-OvsGetNextPacket(POVS_OPEN_INSTANCE instance)\n-{\n- POVS_USER_PACKET_QUEUE queue;\n- PLIST_ENTRY link;\n- queue = (POVS_USER_PACKET_QUEUE)instance->packetQueue;\n- if (queue == NULL) {\n- return NULL;\n- }\n- NdisAcquireSpinLock(&queue->queueLock);\n- if (queue->instance != instance || queue->numPackets == 0) {\n- NdisReleaseSpinLock(&queue->queueLock);\n- return NULL;\n- }\n- link = RemoveHeadList(&queue->packetList);\n- queue->numPackets--;\n- NdisReleaseSpinLock(&queue->queueLock);\n- return CONTAINING_RECORD(link, OVS_PACKET_QUEUE_ELEM, link);\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Given a pid, returns the corresponding USER_PACKET_QUEUE.\n- * ---------------------------------------------------------------------------\n- */\n-POVS_USER_PACKET_QUEUE\n-OvsGetQueue(UINT32 pid)\n-{\n- POVS_OPEN_INSTANCE instance;\n- POVS_USER_PACKET_QUEUE ret = NULL;\n-\n- instance = OvsGetPidInstance(gOvsSwitchContext, pid);\n-\n- if (instance) {\n- ret = instance->packetQueue;\n- }\n-\n- return ret;\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Given a pid, returns the corresponding instance.\n- * pidHashLock must be acquired before calling this API.\n- * ---------------------------------------------------------------------------\n- */\n-POVS_OPEN_INSTANCE\n-OvsGetPidInstance(POVS_SWITCH_CONTEXT switchContext, UINT32 pid)\n-{\n- POVS_OPEN_INSTANCE instance;\n- PLIST_ENTRY head, link;\n- UINT32 hash = OvsJhashBytes((const VOID *)&pid, sizeof(pid),\n- OVS_HASH_BASIS);\n- head = &(switchContext->pidHashArray[hash & OVS_PID_MASK]);\n- LIST_FORALL(head, link) {\n- instance = CONTAINING_RECORD(link, OVS_OPEN_INSTANCE, pidLink);\n- if (instance->pid == pid) {\n- return instance;\n- }\n- }\n- return NULL;\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Given a pid and an instance. This API adds instance to pidHashArray.\n- * pidHashLock must be acquired before calling this API.\n- * ---------------------------------------------------------------------------\n- */\n-VOID\n-OvsAddPidInstance(POVS_SWITCH_CONTEXT switchContext, UINT32 pid,\n- POVS_OPEN_INSTANCE instance)\n-{\n- PLIST_ENTRY head;\n- UINT32 hash = OvsJhashBytes((const VOID *)&pid, sizeof(pid),\n- OVS_HASH_BASIS);\n- head = &(switchContext->pidHashArray[hash & OVS_PID_MASK]);\n- InsertHeadList(head, &(instance->pidLink));\n-}\n-\n-/*\n- * ---------------------------------------------------------------------------\n- * Given a pid and an instance. This API removes instance from pidHashArray.\n- * pidHashLock must be acquired before calling this API.\n- * ---------------------------------------------------------------------------\n- */\n-VOID\n-OvsDelPidInstance(POVS_SWITCH_CONTEXT switchContext, UINT32 pid)\n-{\n- POVS_OPEN_INSTANCE instance = OvsGetPidInstance(switchContext, pid);\n-\n- if (instance) {\n- RemoveEntryList(&(instance->pidLink));\n- }\n-}\n-\n-VOID\n-OvsQueuePackets(PLIST_ENTRY packetList,\n- UINT32 numElems)\n-{\n- POVS_USER_PACKET_QUEUE upcallQueue = NULL;\n- POVS_PACKET_QUEUE_ELEM elem;\n- PLIST_ENTRY link;\n- UINT32 num = 0;\n- LIST_ENTRY dropPackets;\n-\n- OVS_LOG_LOUD(\"Enter: numELems: %u\", numElems);\n-\n- InitializeListHead(&dropPackets);\n-\n- while (!IsListEmpty(packetList)) {\n- link = RemoveHeadList(packetList);\n- elem = CONTAINING_RECORD(link, OVS_PACKET_QUEUE_ELEM, link);\n-\n- ASSERT(elem);\n-\n- OvsAcquirePidHashLock();\n-\n- upcallQueue = OvsGetQueue(elem->upcallPid);\n- if (!upcallQueue) {\n- /* No upcall queue found, drop this packet. */\n- InsertTailList(&dropPackets, &elem->link);\n- } else {\n- NdisAcquireSpinLock(&upcallQueue->queueLock);\n-\n- if (upcallQueue->instance == NULL) {\n- InsertTailList(&dropPackets, &elem->link);\n- } else {\n- InsertTailList(&upcallQueue->packetList, &elem->link);\n- upcallQueue->numPackets++;\n- if (upcallQueue->pendingIrp) {\n- PIRP irp = upcallQueue->pendingIrp;\n- PDRIVER_CANCEL cancelRoutine;\n- upcallQueue->pendingIrp = NULL;\n- cancelRoutine = IoSetCancelRoutine(irp, NULL);\n- if (cancelRoutine != NULL) {\n- OvsCompleteIrpRequest(irp, 0, STATUS_SUCCESS);\n- }\n- }\n- }\n- NdisReleaseSpinLock(&upcallQueue->queueLock);\n- }\n- OvsReleasePidHashLock();\n- }\n-\n- while (!IsListEmpty(&dropPackets)) {\n- link = RemoveHeadList(&dropPackets);\n- elem = CONTAINING_RECORD(link, OVS_PACKET_QUEUE_ELEM, link);\n- OvsFreeMemoryWithTag(elem, OVS_USER_POOL_TAG);\n- num++;\n- }\n-\n- OVS_LOG_LOUD(\"Exit: drop %u packets\", num);\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsCreateAndAddPackets --\n- *\n- * Create a packet and forwarded to user space.\n- *\n- * This function would fragment packet if needed, and queue\n- * each segment to user space.\n- *----------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsCreateAndAddPackets(PVOID userData,\n- UINT32 userDataLen,\n- UINT32 cmd,\n- POVS_VPORT_ENTRY vport,\n- OvsFlowKey *key,\n- PNET_BUFFER_LIST nbl,\n- BOOLEAN isRecv,\n- POVS_PACKET_HDR_INFO hdrInfo,\n- POVS_SWITCH_CONTEXT switchContext,\n- LIST_ENTRY *list,\n- UINT32 *num)\n-{\n- POVS_PACKET_QUEUE_ELEM elem;\n- PNET_BUFFER_LIST newNbl = NULL;\n- PNET_BUFFER nb;\n-\n- if (hdrInfo->isTcp) {\n- NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO tsoInfo;\n- UINT32 packetLength;\n-\n- tsoInfo.Value = NET_BUFFER_LIST_INFO(nbl,\n- TcpLargeSendNetBufferListInfo);\n- nb = NET_BUFFER_LIST_FIRST_NB(nbl);\n- packetLength = NET_BUFFER_DATA_LENGTH(nb);\n-\n- OVS_LOG_TRACE(\"MSS %u packet len %u\",\n- tsoInfo.LsoV1Transmit.MSS, packetLength);\n- if (tsoInfo.LsoV1Transmit.MSS) {\n- OVS_LOG_TRACE(\"l4Offset %d\", hdrInfo->l4Offset);\n- newNbl = OvsTcpSegmentNBL(switchContext, nbl, hdrInfo,\n- tsoInfo.LsoV1Transmit.MSS , 0, FALSE);\n- if (newNbl == NULL) {\n- return NDIS_STATUS_FAILURE;\n- }\n- nbl = newNbl;\n- }\n- }\n-\n- nb = NET_BUFFER_LIST_FIRST_NB(nbl);\n- while (nb) {\n- elem = OvsCreateQueueNlPacket(userData, userDataLen,\n- cmd, vport, key, NULL, nbl, nb,\n- isRecv, hdrInfo);\n- if (elem) {\n- InsertTailList(list, &elem->link);\n- (*num)++;\n- }\n- nb = NET_BUFFER_NEXT_NB(nb);\n- }\n- if (newNbl) {\n- OvsCompleteNBL(switchContext, newNbl, TRUE);\n- }\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-static __inline UINT32\n-OvsGetUpcallMsgSize(PVOID userData,\n- UINT32 userDataLen,\n- OvsIPTunnelKey *tunnelKey,\n- UINT32 payload)\n-{\n- UINT32 size = NLMSG_ALIGN(sizeof(struct ovs_header)) +\n- NlAttrSize(payload) +\n- NlAttrSize(OvsFlowKeyAttrSize());\n-\n- /* OVS_PACKET_ATTR_USERDATA */\n- if (userData) {\n- size += NlAttrTotalSize(userDataLen);\n- }\n- /* OVS_PACKET_ATTR_EGRESS_TUN_KEY */\n- /* Is it included in the flow key attr XXX */\n- if (tunnelKey) {\n- size += NlAttrTotalSize(OvsTunKeyAttrSize());\n- }\n- return size;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * This function completes the IP Header csum. record the L4 payload offset and\n- * if there is a need to calculate the TCP or UDP csum. The actual csum will be\n- * caluculated simopultaneossly with the copy of the payload to the destination\n- * buffer when the packet is read.\n- *----------------------------------------------------------------------------\n- */\n-static VOID\n-OvsCompletePacketHeader(UINT8 *packet,\n- BOOLEAN isRecv,\n- NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo,\n- POVS_PACKET_HDR_INFO hdrInfoIn,\n- POVS_PACKET_HDR_INFO hdrInfoOut)\n-{\n- if ((isRecv && csumInfo.Receive.IpChecksumValueInvalid) ||\n- (!isRecv && csumInfo.Transmit.IsIPv4 &&\n- csumInfo.Transmit.IpHeaderChecksum)) {\n- PIPV4_HEADER ipHdr = (PIPV4_HEADER)(packet + hdrInfoOut->l3Offset);\n- ASSERT(hdrInfoIn->isIPv4);\n- ASSERT(ipHdr->Version == 4);\n- ipHdr->HeaderChecksum = IPChecksum((UINT8 *)ipHdr,\n- ipHdr->HeaderLength << 2,\n- (UINT16)~ipHdr->HeaderChecksum);\n- ovsUserStats.ipCsum++;\n- }\n- ASSERT(hdrInfoIn->tcpCsumNeeded == 0 && hdrInfoOut->udpCsumNeeded == 0);\n- /*\n- * calculate TCP/UDP pseudo checksum\n- */\n- if (isRecv && csumInfo.Receive.TcpChecksumValueInvalid) {\n- /*\n- * Only this case, we need to reclaculate pseudo checksum\n- * all other cases, it is assumed the pseudo checksum is\n- * filled already.\n- *\n- */\n- PTCP_HDR tcpHdr = (PTCP_HDR)(packet + hdrInfoIn->l4Offset);\n- if (hdrInfoIn->isIPv4) {\n- PIPV4_HEADER ipHdr = (PIPV4_HEADER)(packet + hdrInfoIn->l3Offset);\n- hdrInfoOut->l4PayLoad = (UINT16)(ntohs(ipHdr->TotalLength) -\n- (ipHdr->HeaderLength << 2));\n- tcpHdr->th_sum = IPPseudoChecksum((UINT32 *)&ipHdr->SourceAddress,\n- (UINT32 *)&ipHdr->DestinationAddress,\n- IPPROTO_TCP, hdrInfoOut->l4PayLoad);\n- } else {\n- PIPV6_HEADER ipv6Hdr = (PIPV6_HEADER)(packet +\n- hdrInfoIn->l3Offset);\n- hdrInfoOut->l4PayLoad =\n- (UINT16)(ntohs(ipv6Hdr->PayloadLength) +\n- hdrInfoIn->l3Offset + sizeof(IPV6_HEADER)-\n- hdrInfoIn->l4Offset);\n- ASSERT(hdrInfoIn->isIPv6);\n- tcpHdr->th_sum =\n- IPv6PseudoChecksum((UINT32 *)&ipv6Hdr->SourceAddress,\n- (UINT32 *)&ipv6Hdr->DestinationAddress,\n- IPPROTO_TCP, hdrInfoOut->l4PayLoad);\n- }\n- hdrInfoOut->tcpCsumNeeded = 1;\n- ovsUserStats.recalTcpCsum++;\n- } else if (!isRecv) {\n- if (hdrInfoIn->isTcp && csumInfo.Transmit.TcpChecksum) {\n- hdrInfoOut->tcpCsumNeeded = 1;\n- } else if (hdrInfoIn->isUdp && csumInfo.Transmit.UdpChecksum) {\n- hdrInfoOut->udpCsumNeeded = 1;\n- }\n- if (hdrInfoOut->tcpCsumNeeded || hdrInfoOut->udpCsumNeeded) {\n-#ifdef DBG\n- UINT16 sum, *ptr;\n- UINT8 proto =\n- hdrInfoOut->tcpCsumNeeded ? IPPROTO_TCP : IPPROTO_UDP;\n-#endif\n- if (hdrInfoIn->isIPv4) {\n- PIPV4_HEADER ipHdr = (PIPV4_HEADER)(packet +\n- hdrInfoIn->l3Offset);\n- hdrInfoOut->l4PayLoad = (UINT16)(ntohs(ipHdr->TotalLength) -\n- (ipHdr->HeaderLength << 2));\n-#ifdef DBG\n- sum = IPPseudoChecksum((UINT32 *)&ipHdr->SourceAddress,\n- (UINT32 *)&ipHdr->DestinationAddress,\n- proto, hdrInfoOut->l4PayLoad);\n-#endif\n- } else {\n- PIPV6_HEADER ipv6Hdr = (PIPV6_HEADER)(packet +\n- hdrInfoIn->l3Offset);\n- hdrInfoOut->l4PayLoad =\n- (UINT16)(ntohs(ipv6Hdr->PayloadLength) +\n- hdrInfoIn->l3Offset + sizeof(IPV6_HEADER)-\n- hdrInfoIn->l4Offset);\n- ASSERT(hdrInfoIn->isIPv6);\n-#ifdef DBG\n- sum = IPv6PseudoChecksum((UINT32 *)&ipv6Hdr->SourceAddress,\n- (UINT32 *)&ipv6Hdr->DestinationAddress,\n- proto, hdrInfoOut->l4PayLoad);\n-#endif\n- }\n-#ifdef DBG\n- ptr = (UINT16 *)(packet + hdrInfoIn->l4Offset +\n- (hdrInfoOut->tcpCsumNeeded ?\n- TCP_CSUM_OFFSET : UDP_CSUM_OFFSET));\n- ASSERT(*ptr == sum);\n-#endif\n- }\n- }\n-}\n-\n-static NTSTATUS\n-OvsGetPid(POVS_VPORT_ENTRY vport, PNET_BUFFER nb, UINT32 *pid)\n-{\n- UNREFERENCED_PARAMETER(nb);\n-\n- ASSERT(vport);\n-\n- /* XXX select a pid from an array of pids using a flow based hash */\n- *pid = vport->upcallPid;\n- return STATUS_SUCCESS;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsCreateQueueNlPacket --\n- *\n- * Create a packet which will be forwarded to user space.\n- *\n- * InputParameter:\n- * userData: when cmd is user action, this field contain\n- * user action data.\n- * userDataLen: as name indicated\n- * cmd: either miss or user action\n- * inPort: datapath port id from which the packet is received.\n- * key: flow Key with a tunnel key if available\n- * nbl: the NET_BUFFER_LIST which contain the packet\n- * nb: the packet\n- * isRecv: This is used to decide how to interprete the csum info\n- * hdrInfo: include hdr info initialized during flow extraction.\n- *\n- * Results:\n- * NULL if fail to create the packet\n- * The packet element otherwise\n- *----------------------------------------------------------------------------\n- */\n-POVS_PACKET_QUEUE_ELEM\n-OvsCreateQueueNlPacket(PVOID userData,\n- UINT32 userDataLen,\n- UINT32 cmd,\n- POVS_VPORT_ENTRY vport,\n- OvsFlowKey *key,\n- OvsIPTunnelKey *tunnelKey,\n- PNET_BUFFER_LIST nbl,\n- PNET_BUFFER nb,\n- BOOLEAN isRecv,\n- POVS_PACKET_HDR_INFO hdrInfo)\n-{\n-#define VLAN_TAG_SIZE 4\n- UINT32 allocLen, dataLen, extraLen = 0;\n- POVS_PACKET_QUEUE_ELEM elem;\n- UINT8 *src, *dst;\n- NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo;\n- PNDIS_NET_BUFFER_LIST_8021Q_INFO vlanInfo = NULL;\n- PVOID vlanTag;\n- UINT32 pid;\n- UINT32 nlMsgSize;\n- NL_BUFFER nlBuf;\n- PNL_MSG_HDR nlMsg;\n- POVS_BUFFER_CONTEXT ctx;\n-\n- if (vport == NULL){\n- /* No vport is not fatal. */\n- return NULL;\n- }\n-\n- OvsGetPid(vport, nb, &pid);\n-\n- if (!pid) {\n- /*\n- * There is no userspace queue created yet, so there is no point for\n- * creating a new packet to be queued.\n- */\n- return NULL;\n- }\n-\n- csumInfo.Value = NET_BUFFER_LIST_INFO(nbl, TcpIpChecksumNetBufferListInfo);\n-\n- if (isRecv && (csumInfo.Receive.TcpChecksumFailed ||\n- (csumInfo.Receive.UdpChecksumFailed && !hdrInfo->udpCsumZero) ||\n- csumInfo.Receive.IpChecksumFailed)) {\n- OVS_LOG_INFO(\"Packet dropped due to checksum failure.\");\n- ovsUserStats.dropDuetoChecksum++;\n- return NULL;\n- }\n-\n- vlanTag = NET_BUFFER_LIST_INFO(nbl, Ieee8021QNetBufferListInfo);\n- if (vlanTag) {\n- vlanInfo = (PNDIS_NET_BUFFER_LIST_8021Q_INFO)(PVOID *)&vlanTag;\n- if (vlanInfo->Value) {\n- extraLen = VLAN_TAG_SIZE;\n- }\n- }\n-\n- dataLen = NET_BUFFER_DATA_LENGTH(nb);\n-\n- if (NlAttrSize(dataLen) > MAXUINT16) {\n- return NULL;\n- }\n-\n- nlMsgSize = OvsGetUpcallMsgSize(userData, userDataLen, tunnelKey,\n- dataLen + extraLen);\n-\n- allocLen = sizeof (OVS_PACKET_QUEUE_ELEM) + nlMsgSize;\n- elem = (POVS_PACKET_QUEUE_ELEM)OvsAllocateMemoryWithTag(allocLen,\n- OVS_USER_POOL_TAG);\n- if (elem == NULL) {\n- ovsUserStats.dropDuetoResource++;\n- return NULL;\n- }\n- elem->hdrInfo.value = hdrInfo->value;\n- elem->upcallPid = pid;\n- elem->packet.totalLen = nlMsgSize;\n- /* XXX remove queueid */\n- elem->packet.queue = 0;\n- /* XXX no need as the length is already in the NL attrib */\n- elem->packet.userDataLen = userDataLen;\n- elem->packet.inPort = vport->portNo;\n- elem->packet.cmd = cmd;\n- if (cmd == (UINT32)OVS_PACKET_CMD_MISS) {\n- ovsUserStats.miss++;\n- } else if (cmd == (UINT32)OVS_PACKET_CMD_ACTION) {\n- ovsUserStats.action++;\n- } else {\n- ASSERT(FALSE);\n- goto fail;\n- }\n- /* XXX Should we have both packetLen and TotalLen*/\n- elem->packet.packetLen = dataLen + extraLen;\n-\n- NlBufInit(&nlBuf, (PCHAR)elem->packet.data, nlMsgSize);\n-\n- /*\n- * Initialize the OVS header\n- * Since we are pre allocating memory for the NL buffer\n- * the attribute settings should not fail\n- */\n- if (!NlFillOvsMsg(&nlBuf, OVS_WIN_NL_PACKET_FAMILY_ID, 0,\n- 0, pid, (UINT8)cmd, OVS_PACKET_VERSION,\n- gOvsSwitchContext->dpNo)) {\n- goto fail;\n- }\n-\n- if (MapFlowKeyToNlKey(&nlBuf, key, OVS_PACKET_ATTR_KEY,\n- OVS_KEY_ATTR_TUNNEL) != STATUS_SUCCESS) {\n- goto fail;\n- }\n-\n- /* Set MRU attribute */\n- ctx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl);\n- if (ctx->mru != 0) {\n- if (!NlMsgPutTailU16(&nlBuf, OVS_PACKET_ATTR_MRU, (UINT16)ctx->mru)) {\n- goto fail;\n- }\n- }\n-\n- /* Set OVS_PACKET_ATTR_EGRESS_TUN_KEY attribute */\n- if (tunnelKey) {\n- if (MapFlowTunKeyToNlKey(&nlBuf, tunnelKey,\n- OVS_PACKET_ATTR_EGRESS_TUN_KEY) != STATUS_SUCCESS) {\n- goto fail;\n- }\n- }\n- if (userData){\n- if (!NlMsgPutTailUnspec(&nlBuf, OVS_PACKET_ATTR_USERDATA,\n- userData, (UINT16)userDataLen)) {\n- goto fail;\n- }\n- }\n-\n- /*\n- * Make space for the payload to be copied and set the attribute\n- * XXX Uninit set initilizes the buffer with xero, we don't actually need\n- * that the payload to be initailized\n- */\n- dst = (UINT8 *)NlMsgPutTailUnspecUninit(&nlBuf, OVS_PACKET_ATTR_PACKET,\n- (UINT16)(dataLen + extraLen));\n- if (!dst) {\n- goto fail;\n- }\n-\n- /* Store the payload for csum calculation when packet is read */\n- elem->packet.payload = dst;\n- dst += extraLen;\n-\n- src = NdisGetDataBuffer(nb, dataLen, dst, 1, 0);\n- if (src == NULL) {\n- ovsUserStats.dropDuetoResource++;\n- goto fail;\n- } else if (src != dst) {\n- /* Copy the data from the NDIS buffer to dst. */\n- RtlCopyMemory(dst, src, dataLen);\n- }\n-\n- /* Set csum if was offloaded */\n- OvsCompletePacketHeader(dst, isRecv, csumInfo, hdrInfo, &elem->hdrInfo);\n-\n- /*\n- * Finally insert VLAN tag\n- */\n- if (extraLen) {\n- dst = elem->packet.payload;\n- src = dst + extraLen;\n- ((UINT32 *)dst)[0] = ((UINT32 *)src)[0];\n- ((UINT32 *)dst)[1] = ((UINT32 *)src)[1];\n- ((UINT32 *)dst)[2] = ((UINT32 *)src)[2];\n- dst += 12;\n- ((UINT16 *)dst)[0] = htons(0x8100);\n- ((UINT16 *)dst)[1] = htons(vlanInfo->TagHeader.VlanId |\n- (vlanInfo->TagHeader.CanonicalFormatId << 12) |\n- (vlanInfo->TagHeader.UserPriority << 13));\n- elem->hdrInfo.l3Offset += VLAN_TAG_SIZE;\n- elem->hdrInfo.l4Offset += VLAN_TAG_SIZE;\n- ovsUserStats.vlanInsert++;\n- }\n-\n- nlMsg = (PNL_MSG_HDR)NlBufAt(&nlBuf, 0, 0);\n- nlMsg->nlmsgLen = NlBufSize(&nlBuf);\n- /* 'totalLen' should be size of valid data. */\n- elem->packet.totalLen = nlMsg->nlmsgLen;\n-\n- return elem;\n-fail:\n- OvsFreeMemoryWithTag(elem, OVS_USER_POOL_TAG);\n- return NULL;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Handler for the subscription for a packet queue\n- * --------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsSubscribePacketCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen)\n-{\n- NDIS_STATUS status;\n- BOOLEAN rc;\n- UINT8 join;\n- UINT32 pid;\n- const NL_POLICY policy[] = {\n- [OVS_NL_ATTR_PACKET_PID] = {.type = NL_A_U32 },\n- [OVS_NL_ATTR_PACKET_SUBSCRIBE] = {.type = NL_A_U8 }\n- };\n- PNL_ATTR attrs[ARRAY_SIZE(policy)];\n-\n- UNREFERENCED_PARAMETER(replyLen);\n-\n- POVS_OPEN_INSTANCE instance =\n- (POVS_OPEN_INSTANCE)usrParamsCtx->ovsInstance;\n- POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;\n-\n- rc = NlAttrParse(&msgIn->nlMsg, sizeof (*msgIn),\n- NlMsgAttrsLen((PNL_MSG_HDR)msgIn), policy, ARRAY_SIZE(policy),\n- attrs, ARRAY_SIZE(attrs));\n- if (!rc) {\n- status = STATUS_INVALID_PARAMETER;\n- goto done;\n- }\n-\n- join = NlAttrGetU8(attrs[OVS_NL_ATTR_PACKET_SUBSCRIBE]);\n- pid = NlAttrGetU32(attrs[OVS_NL_ATTR_PACKET_PID]);\n-\n- /* The socket subscribed with must be the same socket we perform receive*/\n- ASSERT(pid == instance->pid);\n-\n- status = OvsSubscribeDpIoctl(instance, pid, join);\n-\n- /*\n- * XXX Need to add this instance to a global data structure\n- * which hold all packet based instances. The data structure (hash)\n- * should be searched through the pid field of the instance for\n- * placing the missed packet into the correct queue\n- */\n-done:\n- return status;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Handler for queueing an IRP used for missed packet notification. The IRP is\n- * completed when a packet received and mismatched. STATUS_PENDING is returned\n- * on success. User mode keep a pending IRP at all times.\n- * --------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsPendPacketCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen)\n-{\n- UNREFERENCED_PARAMETER(replyLen);\n-\n- POVS_OPEN_INSTANCE instance =\n- (POVS_OPEN_INSTANCE)usrParamsCtx->ovsInstance;\n-\n- /*\n- * XXX access to packet queue must be through acquiring a lock as user mode\n- * could unsubscribe and the instnace will be freed.\n- */\n- return OvsWaitDpIoctl(usrParamsCtx->irp, instance->fileObject);\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Handler for reading missed pacckets from the driver event queue. This\n- * handler is executed when user modes issues a socket receive on a socket\n- * --------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsReadPacketCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen)\n-{\n-#ifdef DBG\n- POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer;\n-#endif\n- POVS_OPEN_INSTANCE instance =\n- (POVS_OPEN_INSTANCE)usrParamsCtx->ovsInstance;\n- NTSTATUS status;\n-\n- ASSERT(usrParamsCtx->devOp == OVS_READ_DEV_OP);\n-\n- /* Should never read events with a dump socket */\n- ASSERT(instance->dumpState.ovsMsg == NULL);\n-\n- /* Must have an packet queue */\n- ASSERT(instance->packetQueue != NULL);\n-\n- /* Output buffer has been validated while validating read dev op. */\n- ASSERT(msgOut != NULL && usrParamsCtx->outputLength >= sizeof *msgOut);\n-\n- /* Read a packet from the instance queue */\n- status = OvsReadDpIoctl(instance->fileObject, usrParamsCtx->outputBuffer,\n- usrParamsCtx->outputLength, replyLen);\n- return status;\n-}\ndiff --git a/datapath-windows/ovsext/User.h b/datapath-windows/ovsext/User.h\ndeleted file mode 100644\nindex ca27827d6..000000000\n--- a/datapath-windows/ovsext/User.h\n+++ /dev/null\n@@ -1,130 +0,0 @@\n- /*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-/* This file contains structures and function definitions necessary for\n- * forwarding packet to user space.\n- */\n-\n-#ifndef __USER_H_\n-#define __USER_H_ 1\n-\n-\n-#include \"Datapath.h\"\n-\n-/*\n- * Even we have more cores, I don't think we need\n- * more than 32 queues for processing packets to\n- * userspace\n- */\n-#define OVS_DEFAULT_PACKET_QUEUE 1\n-#define OVS_MAX_PACKET_QUEUE_LEN 4096\n-\n-/*\n- * Only when OVS_PER_VPORT_QUEUE_CTRL is defined\n- * we will apply this constraint\n- */\n-#define OVS_MAX_PACKETS_PER_VPORT 128\n-#define OVS_MAX_PACKETS_PER_TUNNEL 1024\n-\n-typedef struct _OVS_USER_PACKET_QUEUE {\n- UINT32 pid;\n- UINT32 numPackets;\n- LIST_ENTRY packetList;\n- PVOID instance;\n- PIRP pendingIrp;\n- NDIS_SPIN_LOCK queueLock;\n-} OVS_USER_PACKET_QUEUE, *POVS_USER_PACKET_QUEUE;\n-\n-typedef struct _OVS_PACKET_QUEUE_ELEM {\n- UINT32 upcallPid;\n- LIST_ENTRY link;\n- OVS_PACKET_HDR_INFO hdrInfo;\n- OVS_PACKET_INFO packet;\n-} OVS_PACKET_QUEUE_ELEM, *POVS_PACKET_QUEUE_ELEM;\n-\n-struct _OVS_OPEN_INSTANCE;\n-\n-typedef struct _OVS_USER_STATS {\n- UINT64 miss;\n- UINT64 action;\n- UINT32 dropDuetoResource;\n- UINT32 dropDuetoChecksum;\n- UINT32 ipCsum;\n- UINT32 recalTcpCsum;\n- UINT32 vlanInsert;\n- UINT32 l4Csum;\n-} OVS_USER_STATS, *POVS_USER_STATS;\n-\n-VOID OvsCleanupPacketQueue(struct _OVS_OPEN_INSTANCE *instance);\n-\n-POVS_PACKET_QUEUE_ELEM OvsCreateQueueNlPacket(PVOID userData,\n- UINT32 userDataLen,\n- UINT32 cmd, \n- POVS_VPORT_ENTRY vport,\n- OvsFlowKey *key,\n- OvsIPTunnelKey *tunnelKey,\n- PNET_BUFFER_LIST nbl,\n- PNET_BUFFER nb,\n- BOOLEAN isRecv,\n- POVS_PACKET_HDR_INFO hdrInfo);\n-\n-VOID OvsQueuePackets(PLIST_ENTRY packetList, UINT32 numElems);\n-NTSTATUS OvsCreateAndAddPackets(PVOID userData,\n- UINT32 userDataLen,\n- UINT32 cmd,\n- POVS_VPORT_ENTRY vport,\n- OvsFlowKey *key,\n- PNET_BUFFER_LIST nbl,\n- BOOLEAN isRecv,\n- POVS_PACKET_HDR_INFO hdrInfo,\n- POVS_SWITCH_CONTEXT switchContext,\n- LIST_ENTRY *list,\n- UINT32 *num);\n-\n-NTSTATUS OvsSubscribeDpIoctl(PVOID instanceP,\n- UINT32 pid,\n- UINT8 join);\n-\n-NTSTATUS OvsReadDpIoctl(PFILE_OBJECT fileObject,\n- PVOID outputBuffer,\n- UINT32 outputLength,\n- UINT32 *replyLen);\n-NTSTATUS OvsExecuteDpIoctl(OvsPacketExecute *execute);\n-NTSTATUS OvsPurgeDpIoctl(PFILE_OBJECT fileObject);\n-\n-NTSTATUS OvsWaitDpIoctl(PIRP irp, PFILE_OBJECT fileObject);\n-\n-NTSTATUS OvsNlExecuteCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen);\n-\n-POVS_OPEN_INSTANCE\n-OvsGetPidInstance(POVS_SWITCH_CONTEXT switchContext, UINT32 pid);\n-\n-VOID\n-OvsAddPidInstance(POVS_SWITCH_CONTEXT switchContext, UINT32 pid,\n- POVS_OPEN_INSTANCE instance);\n-\n-VOID\n-OvsDelPidInstance(POVS_SWITCH_CONTEXT switchContext, UINT32 pid);\n-\n-NTSTATUS OvsReadPacketCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen);\n-NTSTATUS OvsSubscribePacketCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen);\n-NTSTATUS OvsPendPacketCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen);\n-\n-#endif /* __USER_H_ */\ndiff --git a/datapath-windows/ovsext/Util.c b/datapath-windows/ovsext/Util.c\ndeleted file mode 100644\nindex d703b2468..000000000\n--- a/datapath-windows/ovsext/Util.c\n+++ /dev/null\n@@ -1,182 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#include \"precomp.h\"\n-#include \"Recirc.h\"\n-#ifdef OVS_DBG_MOD\n-#undef OVS_DBG_MOD\n-#endif\n-#define OVS_DBG_MOD OVS_DBG_OTHERS\n-\n-#include \"Debug.h\"\n-\n-extern NDIS_HANDLE gOvsExtDriverHandle;\n-\n-_Use_decl_annotations_\n-VOID*\n-OvsAllocateMemoryWithTag(size_t size, ULONG tag)\n-{\n- return NdisAllocateMemoryWithTagPriority(gOvsExtDriverHandle,\n- (UINT32)size, tag, NormalPoolPriority);\n-}\n-\n-VOID\n-OvsFreeMemoryWithTag(VOID *ptr, ULONG tag)\n-{\n- ASSERT(ptr);\n- NdisFreeMemoryWithTagPriority(gOvsExtDriverHandle, ptr, tag);\n-}\n-\n-_Use_decl_annotations_\n-VOID *\n-OvsAllocateMemory(size_t size)\n-{\n- return NdisAllocateMemoryWithTagPriority(gOvsExtDriverHandle,\n- (UINT32)size, OVS_MEMORY_TAG, NormalPoolPriority);\n-}\n-\n-_Use_decl_annotations_\n-VOID *\n-OvsAllocateAlignedMemory(size_t size, UINT16 align)\n-{\n- ASSERT((align == 8) || (align == 16));\n-\n- if ((align == 8) || (align == 16)) {\n- /*\n- * XXX: NdisAllocateMemory*() functions don't talk anything about\n- * alignment. Hence using ExAllocatePool*();\n- */\n- return (VOID *)ExAllocatePoolWithTagPriority(NonPagedPoolNx, size,\n- OVS_MEMORY_TAG,\n- NormalPoolPriority);\n- }\n-\n- /* Invalid user input. */\n- return NULL;\n-}\n-\n-VOID\n-OvsFreeMemory(VOID *ptr)\n-{\n- ASSERT(ptr);\n- NdisFreeMemoryWithTagPriority(gOvsExtDriverHandle, ptr, OVS_MEMORY_TAG);\n-}\n-\n-VOID\n-OvsFreeAlignedMemory(VOID *ptr)\n-{\n- ASSERT(ptr);\n- ExFreePoolWithTag(ptr, OVS_MEMORY_TAG);\n-}\n-\n-VOID\n-OvsAppendList(PLIST_ENTRY dst, PLIST_ENTRY src)\n-{\n- PLIST_ENTRY srcFirst, srcLast, dstLast;\n- if (IsListEmpty(src)) {\n- return;\n- }\n- srcFirst = src->Flink;\n- srcLast = src->Blink;\n- dstLast = dst->Blink;\n-\n- dstLast->Flink = srcFirst;\n- srcFirst->Blink = dstLast;\n-\n- srcLast->Flink = dst;\n- dst->Blink = srcLast;\n-\n- src->Flink = src;\n- src->Blink = src;\n-}\n-\n-BOOLEAN\n-OvsCompareString(PVOID string1, PVOID string2)\n-{\n- /*\n- * Not a super-efficient string compare since we walk over the strings\n- * twice: to initialize, and then to do the comparison.\n- */\n- STRING str1, str2;\n-\n- RtlInitString(&str1, string1);\n- RtlInitString(&str2, string2);\n- return RtlEqualString(&str1, &str2, FALSE);\n-}\n-\n-VOID *\n-OvsAllocateMemoryPerCpu(size_t size,\n- size_t count,\n- ULONG tag)\n-{\n- VOID *ptr = NULL;\n-\n- ASSERT(KeQueryActiveGroupCount() == 1);\n-\n- if (!count) {\n- count = KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS);\n- }\n-\n- ptr = OvsAllocateMemoryWithTag(count * size, tag);\n- if (ptr) {\n- RtlZeroMemory(ptr, count * size);\n- }\n-\n- return ptr;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsPerCpuDataInit --\n- * The function allocates necessary per-processor resources.\n- * --------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsPerCpuDataInit()\n-{\n- return OvsDeferredActionsInit();\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsPerCpuDataCleanup --\n- * The function frees all per-processor resources.\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-OvsPerCpuDataCleanup()\n-{\n- OvsDeferredActionsCleanup();\n-}\n-\n-NTSTATUS\n-OvsIpv6StringToAddress(const char* ip6String, struct in6_addr *ipv6Addr)\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n- char *terminator = NULL;\n-\n- status = RtlIpv6StringToAddressA(ip6String, &terminator, ipv6Addr);\n- return status;\n-}\n-\n-char *\n-OvsIpv6AddressToString(struct in6_addr ipv6Addr, char* ip6String)\n-{\n- char *returnedIpv6Str = NULL;\n-\n- returnedIpv6Str = RtlIpv6AddressToStringA((&ipv6Addr), ip6String);\n- return returnedIpv6Str;\n-}\n\\ No newline at end of file\ndiff --git a/datapath-windows/ovsext/Util.h b/datapath-windows/ovsext/Util.h\ndeleted file mode 100644\nindex 95114e9f2..000000000\n--- a/datapath-windows/ovsext/Util.h\n+++ /dev/null\n@@ -1,210 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#ifndef __UTIL_H_\n-#define __UTIL_H_ 1\n-\n-#define OVS_MEMORY_TAG 'TSVO'\n-#define OVS_FIX_SIZE_NBL_POOL_TAG 'FSVO'\n-#define OVS_VARIABLE_SIZE_NBL_POOL_TAG 'VSVO'\n-#define OVS_NBL_ONLY_POOL_TAG 'OSVO'\n-#define OVS_NET_BUFFER_POOL_TAG 'NSVO'\n-#define OVS_OTHER_POOL_TAG 'MSVO'\n-#define OVS_MDL_POOL_TAG 'BSVO'\n-#define OVS_DATAPATH_POOL_TAG 'DSVO'\n-#define OVS_EVENT_POOL_TAG 'ESVO'\n-#define OVS_FLOW_POOL_TAG 'LSVO'\n-#define OVS_VXLAN_POOL_TAG 'XSVO'\n-#define OVS_IPHELPER_POOL_TAG 'HSVO'\n-#define OVS_OID_POOL_TAG 'ASVO'\n-#define OVS_SWITCH_POOL_TAG 'SSVO'\n-#define OVS_USER_POOL_TAG 'USVO'\n-#define OVS_VPORT_POOL_TAG 'PSVO'\n-#define OVS_GRE_POOL_TAG 'GSVO'\n-#define OVS_TUNFLT_POOL_TAG 'WSVO'\n-#define OVS_RECIRC_POOL_TAG 'CSVO'\n-#define OVS_CT_POOL_TAG 'CTVO'\n-#define OVS_METER_TAG 'MEVO'\n-#define OVS_GENEVE_POOL_TAG 'GNVO'\n-#define OVS_IPFRAG_POOL_TAG 'FGVO'\n-#define OVS_IP6FRAG_POOL_TAG 'F6VO'\n-\n-_IRQL_requires_max_(DISPATCH_LEVEL)\n-VOID *OvsAllocateMemory(size_t size);\n-\n-_IRQL_requires_max_(DISPATCH_LEVEL)\n-VOID *OvsAllocateMemoryWithTag(size_t size, ULONG tag);\n-\n-_IRQL_requires_max_(DISPATCH_LEVEL)\n-VOID *OvsAllocateAlignedMemory(size_t size, UINT16 align);\n-\n-VOID *OvsAllocateMemoryPerCpu(size_t size, size_t count, ULONG tag);\n-VOID OvsFreeMemory(VOID *ptr);\n-VOID OvsFreeMemoryWithTag(VOID *ptr, ULONG tag);\n-VOID OvsFreeAlignedMemory(VOID *ptr);\n-\n-#define LIST_FORALL(_headPtr, _itemPtr) \\\n- for (_itemPtr = (_headPtr)->Flink; \\\n- _itemPtr != _headPtr; \\\n- _itemPtr = (_itemPtr)->Flink)\n-\n-#define LIST_FORALL_SAFE(_headPtr, _itemPtr, _nextPtr) \\\n- for (_itemPtr = (_headPtr)->Flink, _nextPtr = (_itemPtr)->Flink; \\\n- _itemPtr != _headPtr; \\\n- _itemPtr = _nextPtr, _nextPtr = (_itemPtr)->Flink)\n-\n-#define LIST_FORALL_REVERSE(_headPtr, _itemPtr) \\\n- for (_itemPtr = (_headPtr)->Blink; \\\n- _itemPtr != _headPtr; \\\n- _itemPtr = (_itemPtr)->Blink)\n-\n-#define LIST_FORALL_REVERSE_SAFE(_headPtr, _itemPtr, _nextPtr) \\\n- for (_itemPtr = (_headPtr)->Blink, _nextPtr = (_itemPtr)->Blink; \\\n- _itemPtr != _headPtr; \\\n- _itemPtr = _nextPtr, _nextPtr = (_itemPtr)->Blink)\n-\n-VOID OvsAppendList(PLIST_ENTRY dst, PLIST_ENTRY src);\n-\n-#define MAX(_a, _b) ((_a) > (_b) ? (_a) : (_b))\n-#define MIN(_a, _b) ((_a) > (_b) ? (_b) : (_a))\n-#define ARRAY_SIZE(_x) ((sizeof(_x))/sizeof (_x)[0])\n-#define OVS_SWITCH_PORT_ID_INVALID (NDIS_SWITCH_PORT_ID)(-1)\n-\n-#ifndef htons\n-#define htons(_x) _byteswap_ushort((USHORT)(_x))\n-#define ntohs(_x) _byteswap_ushort((USHORT)(_x))\n-#define htonl(_x) _byteswap_ulong((ULONG)(_x))\n-#define ntohl(_x) _byteswap_ulong((ULONG)(_x))\n-#define htonll(_x) ((1==htonl(1)) ? (_x) : \\\n- ((uint64_t) htonl(_x) << 32) | htonl(_x >> 32))\n-#define ntohll(_x) ((1==ntohl(1)) ? (_x) : \\\n- ((uint64_t) ntohl(_x) << 32) | ntohl(_x >> 32))\n-#endif\n-\n-#define OVS_INIT_OBJECT_HEADER(_obj, _type, _revision, _size) \\\n- { \\\n- PNDIS_OBJECT_HEADER hdrp = _obj; \\\n- hdrp->Type = _type; \\\n- hdrp->Revision = _revision; \\\n- hdrp->Size = _size; \\\n- }\n-\n-\n-#define BIT16(_x) ((UINT16)0x1 << (_x))\n-#define BIT32(_x) ((UINT32)0x1 << (_x))\n-\n-#define OVS_ACQUIRE_SPIN_LOCK(_pLock, _dispatchLevel) \\\n-{ \\\n- if (_dispatchLevel) { \\\n- NdisDprAcquireSpinLock(_pLock); \\\n- } else { \\\n- NdisAcquireSpinLock(_pLock); \\\n- } \\\n-}\n-\n-#define OVS_RELEASE_SPIN_LOCK(_pLock, _dispatchLevel) \\\n-{ \\\n- if (_dispatchLevel) { \\\n- NdisDprReleaseSpinLock(_pLock); \\\n- } else { \\\n- NdisReleaseSpinLock(_pLock); \\\n- } \\\n-}\n-\n-BOOLEAN OvsCompareString(PVOID string1, PVOID string2);\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsPerCpuDataInit --\n- * The function allocates necessary per-processor resources.\n- * --------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsPerCpuDataInit();\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsPerCpuDataCleanup --\n- * The function frees all per-processor resources.\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-OvsPerCpuDataCleanup();\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsIpv6StringToAddress --\n- * The function was used to convert ip6string to binary ipv6 address.\n- * --------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsIpv6StringToAddress(const char* ip6String, struct in6_addr *ipv6Addr);\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * OvsIpv6AddressToString --\n- * The function convert bindary ipv6Addr to string.\n- * --------------------------------------------------------------------------\n- */\n-char *\n-OvsIpv6AddressToString(struct in6_addr ipv6Addr, char* ip6String);\n-\n-\n-static LARGE_INTEGER seed;\n-\n-/*\n- *----------------------------------------------------------------------------\n- * SRand --\n- * This function sets the starting seed value for the pseudorandom number\n- * generator.\n- *----------------------------------------------------------------------------\n- */\n-static __inline\n-VOID SRand()\n-{\n- KeQuerySystemTime(&seed);\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * Rand --\n- * This function generates a pseudorandom number between 0 to UINT_MAX.\n- *----------------------------------------------------------------------------\n- */\n-static __inline\n-UINT32 Rand()\n-{\n- return seed.LowPart *= 0x8088405 + 1;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsGetMdlWithLowPriority --\n- * Return the nonpaged system-space virtual address for the given MDL\n- * `curMdl` using low page priority and no executable memory.\n- *----------------------------------------------------------------------------\n- */\n-\n-static __inline\n-PVOID OvsGetMdlWithLowPriority(PMDL curMdl)\n-{\n-return\tMmGetSystemAddressForMdlSafe(curMdl,\n- LowPagePriority | MdlMappingNoExecute);\n-}\n-\n-#endif /* __UTIL_H_ */\ndiff --git a/datapath-windows/ovsext/Vport.c b/datapath-windows/ovsext/Vport.c\ndeleted file mode 100644\nindex 3422d27ed..000000000\n--- a/datapath-windows/ovsext/Vport.c\n+++ /dev/null\n@@ -1,2830 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#include \"precomp.h\"\n-\n-#include \"Datapath.h\"\n-#include \"Event.h\"\n-#include \"Gre.h\"\n-#include \"IpHelper.h\"\n-#include \"Jhash.h\"\n-#include \"Oid.h\"\n-#include \"Switch.h\"\n-#include \"User.h\"\n-#include \"Vport.h\"\n-#include \"Vxlan.h\"\n-#include \"Geneve.h\"\n-\n-#ifdef OVS_DBG_MOD\n-#undef OVS_DBG_MOD\n-#endif\n-#define OVS_DBG_MOD OVS_DBG_VPORT\n-#include \"Debug.h\"\n-\n-#define VPORT_NIC_ENTER(_nic) \\\n- OVS_LOG_TRACE(\"Enter: PortId: %x, NicIndex: %d\", _nic->PortId, \\\n- _nic->NicIndex)\n-\n-#define VPORT_NIC_EXIT(_nic) \\\n- OVS_LOG_TRACE(\"Exit: PortId: %x, NicIndex: %d\", _nic->PortId, \\\n- _nic->NicIndex)\n-\n-#define VPORT_PORT_ENTER(_port) \\\n- OVS_LOG_TRACE(\"Enter: PortId: %x\", _port->PortId)\n-\n-#define VPORT_PORT_EXIT(_port) \\\n- OVS_LOG_TRACE(\"Exit: PortId: %x\", _port->PortId)\n-\n-#define OVS_VPORT_DEFAULT_WAIT_TIME_MICROSEC 100\n-\n-/* Context structure used to pass back and forth information to the tunnel\n- * filter threads. */\n-typedef struct _OVS_TUNFLT_INIT_CONTEXT {\n- POVS_SWITCH_CONTEXT switchContext;\n- UINT32 outputLength;\n- PVOID outputBuffer;\n- PVOID inputBuffer;\n- POVS_VPORT_ENTRY vport;\n- BOOLEAN hvSwitchPort;\n- BOOLEAN hvDelete;\n- BOOLEAN ovsDelete;\n-} OVS_TUNFLT_INIT_CONTEXT, *POVS_TUNFLT_INIT_CONTEXT;\n-\n-\n-extern POVS_SWITCH_CONTEXT gOvsSwitchContext;\n-\n-static VOID OvsInitVportWithPortParam(POVS_VPORT_ENTRY vport,\n- PNDIS_SWITCH_PORT_PARAMETERS portParam);\n-static VOID OvsInitVportWithNicParam(POVS_SWITCH_CONTEXT switchContext,\n- POVS_VPORT_ENTRY vport, PNDIS_SWITCH_NIC_PARAMETERS nicParam);\n-static VOID OvsCopyPortParamsFromVport(POVS_VPORT_ENTRY vport,\n- PNDIS_SWITCH_PORT_PARAMETERS portParam);\n-static __inline VOID OvsWaitActivate(POVS_SWITCH_CONTEXT switchContext,\n- ULONG sleepMicroSec);\n-static NTSTATUS OvsGetExtInfoIoctl(POVS_VPORT_GET vportGet,\n- POVS_VPORT_EXT_INFO extInfo);\n-static NTSTATUS CreateNetlinkMesgForNetdev(POVS_VPORT_EXT_INFO info,\n- POVS_MESSAGE msgIn,\n- PVOID outBuffer,\n- UINT32 outBufLen,\n- int dpIfIndex);\n-static VOID UpdateSwitchCtxWithVport(POVS_SWITCH_CONTEXT switchContext,\n- POVS_VPORT_ENTRY vport, BOOLEAN newPort);\n-static NTSTATUS OvsRemoveTunnelVport(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- POVS_SWITCH_CONTEXT switchContext,\n- POVS_VPORT_ENTRY vport,\n- BOOLEAN hvDelete,\n- BOOLEAN ovsDelete);\n-static VOID OvsTunnelVportPendingInit(PVOID context,\n- NTSTATUS status,\n- UINT32 *replyLen);\n-static VOID OvsTunnelVportPendingRemove(PVOID context,\n- NTSTATUS status,\n- UINT32 *replyLen);\n-static NTSTATUS GetNICAlias(PNDIS_SWITCH_NIC_PARAMETERS nicParam,\n- IF_COUNTED_STRING *portFriendlyName);\n-static NTSTATUS OvsConvertIfCountedStrToAnsiStr(PIF_COUNTED_STRING wStr,\n- CHAR *str,\n- UINT16 maxStrLen);\n-_Requires_lock_held_(switchContext->dispatchLock)\n-static VOID OvsBindVportWithIpHelper(POVS_VPORT_ENTRY vport,\n- POVS_SWITCH_CONTEXT switchContext);\n-_Requires_lock_held_(switchContext->dispatchLock)\n-static VOID OvsUnBindVportWithIpHelper(POVS_VPORT_ENTRY vport,\n- POVS_SWITCH_CONTEXT switchContext);\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Creates a Vport entry for a Hyper-V switch port. 'nicIndex' is typically\n- * associated with a NIC than a port. We use it here for the special case\n- * where we need to create a Vport for an external NIC with NicIndex > 0.\n- * --------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-HvCreatePort(POVS_SWITCH_CONTEXT switchContext,\n- PNDIS_SWITCH_PORT_PARAMETERS portParam,\n- NDIS_SWITCH_NIC_INDEX nicIndex)\n-{\n- POVS_VPORT_ENTRY vport;\n- LOCK_STATE_EX lockState;\n- NDIS_STATUS status = NDIS_STATUS_SUCCESS;\n- BOOLEAN newPort = FALSE;\n-\n- VPORT_PORT_ENTER(portParam);\n-\n- NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0);\n- /* Lookup by port ID. */\n- vport = OvsFindVportByPortIdAndNicIndex(switchContext,\n- portParam->PortId, nicIndex);\n- if (vport != NULL) {\n- OVS_LOG_ERROR(\"Port add failed due to duplicate port name, \"\n- \"port Id: %u\", portParam->PortId);\n- status = STATUS_DATA_NOT_ACCEPTED;\n- goto create_port_done;\n- }\n-\n- /*\n- * Lookup by port name to see if this port with this name had been added\n- * (and deleted) previously.\n- */\n- vport = OvsFindVportByHvNameW(switchContext,\n- portParam->PortFriendlyName.String,\n- portParam->PortFriendlyName.Length);\n- if (vport && vport->isAbsentOnHv == FALSE) {\n- OVS_LOG_ERROR(\"Port add failed since a port already exists on \"\n- \"the specified port Id: %u, ovsName: %s\",\n- portParam->PortId, vport->ovsName);\n- status = STATUS_DATA_NOT_ACCEPTED;\n- goto create_port_done;\n- }\n-\n- if (vport != NULL) {\n- ASSERT(vport->isAbsentOnHv);\n- ASSERT(vport->portNo != OVS_DPPORT_NUMBER_INVALID);\n-\n- /*\n- * It should be possible to simply just mark this port as \"not deleted\"\n- * given that the port Id and the name are the same and also provided\n- * that the other properties that we cache have not changed.\n- */\n- if (vport->portType != portParam->PortType) {\n- OVS_LOG_INFO(\"Port add failed due to PortType change, port Id: %u\"\n- \" old: %u, new: %u\", portParam->PortId,\n- vport->portType, portParam->PortType);\n- status = STATUS_DATA_NOT_ACCEPTED;\n- goto create_port_done;\n- }\n- vport->isAbsentOnHv = FALSE;\n- } else {\n- vport = (POVS_VPORT_ENTRY)OvsAllocateVport();\n- if (vport == NULL) {\n- status = NDIS_STATUS_RESOURCES;\n- goto create_port_done;\n- }\n- newPort = TRUE;\n- }\n- OvsInitVportWithPortParam(vport, portParam);\n- vport->nicIndex = nicIndex;\n- UpdateSwitchCtxWithVport(switchContext, vport, newPort);\n-\n-create_port_done:\n- NdisReleaseRWLock(switchContext->dispatchLock, &lockState);\n- VPORT_PORT_EXIT(portParam);\n- return status;\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Function to process updates to a port on the Hyper-Vs witch.\n- * --------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-HvUpdatePort(POVS_SWITCH_CONTEXT switchContext,\n- PNDIS_SWITCH_PORT_PARAMETERS portParam)\n-{\n- POVS_VPORT_ENTRY vport;\n- LOCK_STATE_EX lockState;\n- OVS_VPORT_STATE ovsState;\n- NDIS_SWITCH_NIC_STATE nicState;\n-\n- VPORT_PORT_ENTER(portParam);\n-\n- NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0);\n- vport = OvsFindVportByPortIdAndNicIndex(switchContext,\n- portParam->PortId, 0);\n- /*\n- * Update properties only for NETDEV ports for supprting PS script\n- */\n- if (vport == NULL) {\n- goto update_port_done;\n- }\n-\n- /* Store the nic and the OVS states as Nic Create won't be called */\n- ovsState = vport->ovsState;\n- nicState = vport->nicState;\n-\n- /*\n- * Currently only the port friendly name is being updated\n- * Make sure that no other properties are changed\n- */\n- ASSERT(portParam->PortId == vport->portId);\n- ASSERT(portParam->PortState == vport->portState);\n- ASSERT(portParam->PortType == vport->portType);\n-\n- /*\n- * Call the set parameters function the handle all properties\n- * change in a single place in case future version supports change of\n- * other properties\n- */\n- OvsInitVportWithPortParam(vport, portParam);\n- /* Retore the nic and OVS states */\n- vport->nicState = nicState;\n- vport->ovsState = ovsState;\n-\n-update_port_done:\n- NdisReleaseRWLock(switchContext->dispatchLock, &lockState);\n- VPORT_PORT_EXIT(portParam);\n-\n- /* Must always return success */\n- return NDIS_STATUS_SUCCESS;\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Function to process teardown of a port on the Hyper-V switch.\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-HvTeardownPort(POVS_SWITCH_CONTEXT switchContext,\n- PNDIS_SWITCH_PORT_PARAMETERS portParam)\n-{\n- POVS_VPORT_ENTRY vport;\n- LOCK_STATE_EX lockState;\n-\n- VPORT_PORT_ENTER(portParam);\n-\n- NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0);\n- vport = OvsFindVportByPortIdAndNicIndex(switchContext,\n- portParam->PortId, 0);\n- if (vport) {\n- /* add assertion here */\n- vport->portState = NdisSwitchPortStateTeardown;\n- vport->ovsState = OVS_STATE_PORT_TEAR_DOWN;\n- } else {\n- OVS_LOG_WARN(\"Vport not present.\");\n- }\n- NdisReleaseRWLock(switchContext->dispatchLock, &lockState);\n-\n- VPORT_PORT_EXIT(portParam);\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Function to process deletion of a port on the Hyper-V switch.\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-HvDeletePort(POVS_SWITCH_CONTEXT switchContext,\n- PNDIS_SWITCH_PORT_PARAMETERS portParams)\n-{\n- POVS_VPORT_ENTRY vport;\n- LOCK_STATE_EX lockState;\n-\n- VPORT_PORT_ENTER(portParams);\n-\n- NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0);\n- vport = OvsFindVportByPortIdAndNicIndex(switchContext,\n- portParams->PortId, 0);\n-\n- /*\n- * XXX: we can only destroy and remove the port if its datapath port\n- * counterpart was deleted. If the datapath port counterpart is present,\n- * we only mark the vport for deletion, so that a netlink command vport\n- * delete will delete the vport.\n- */\n- if (vport) {\n- OVS_VPORT_EVENT_ENTRY event;\n-\n- event.portNo = vport->portNo;\n- event.ovsType = vport->ovsType;\n- event.upcallPid = vport->upcallPid;\n- RtlCopyMemory(&event.ovsName, &vport->ovsName, sizeof event.ovsName);\n- event.type = OVS_EVENT_LINK_DOWN;\n- OvsRemoveAndDeleteVport(NULL, switchContext, vport, TRUE, FALSE);\n- OvsPostVportEvent(&event);\n- } else {\n- OVS_LOG_WARN(\"Vport not present.\");\n- }\n- NdisReleaseRWLock(switchContext->dispatchLock, &lockState);\n-\n- VPORT_PORT_EXIT(portParams);\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Function to process addition of a NIC connection on the Hyper-V switch.\n- * XXX: Posting an event to DPIF is incorrect here. However, it might be useful\n- * to post an event to netdev-windows.c.\n- * --------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-HvCreateNic(POVS_SWITCH_CONTEXT switchContext,\n- PNDIS_SWITCH_NIC_PARAMETERS nicParam)\n-{\n- POVS_VPORT_ENTRY vport;\n- NDIS_STATUS status = NDIS_STATUS_SUCCESS;\n- IF_COUNTED_STRING portFriendlyName = {0};\n- LOCK_STATE_EX lockState;\n-\n- VPORT_NIC_ENTER(nicParam);\n-\n- /* Wait for lists to be initialized. */\n- OvsWaitActivate(switchContext, OVS_VPORT_DEFAULT_WAIT_TIME_MICROSEC);\n-\n- if (!switchContext->isActivated) {\n- OVS_LOG_WARN(\"Switch is not activated yet.\");\n- /* Veto the creation of nic */\n- status = NDIS_STATUS_NOT_SUPPORTED;\n- goto done;\n- }\n-\n- if (OvsIsInternalNIC(nicParam->NicType) ||\n- OvsIsRealExternalNIC(nicParam->NicType, nicParam->NicIndex)) {\n- GetNICAlias(nicParam, &portFriendlyName);\n- }\n-\n- NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0);\n- /*\n- * There can be one or more NICs for the external port. We create a vport\n- * structure for each such NIC, and each NIC inherits a lot of properties\n- * from the parent external port.\n- */\n- if (OvsIsRealExternalNIC(nicParam->NicType, nicParam->NicIndex)) {\n- /* The VPORT can be bound to OVS datapath already. Search for it\n- * using its friendly name and if not found allocate a new port\n- */\n- ASSERT(OvsFindVportByPortIdAndNicIndex(switchContext,\n- nicParam->PortId,\n- nicParam->NicIndex) == NULL);\n- char convertString[256];\n- RtlZeroMemory(convertString, 256);\n- NdisReleaseRWLock(switchContext->dispatchLock, &lockState);\n- status = OvsConvertIfCountedStrToAnsiStr(&portFriendlyName,\n- convertString,\n- OVS_MAX_PORT_NAME_LENGTH);\n- NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0);\n- if (status != NDIS_STATUS_SUCCESS) {\n- goto add_nic_done;\n- }\n- POVS_VPORT_ENTRY ovsVport = OvsFindVportByOvsName(switchContext,\n- convertString);\n- if (ovsVport != NULL) {\n- UpdateSwitchCtxWithVport(switchContext, ovsVport, FALSE);\n- } else {\n- NDIS_SWITCH_PORT_PARAMETERS portParam;\n- POVS_VPORT_ENTRY virtExtVport =\n- (POVS_VPORT_ENTRY)switchContext->virtualExternalVport;\n-\n- ASSERT(virtExtVport);\n- OvsCopyPortParamsFromVport(virtExtVport, &portParam);\n- NdisReleaseRWLock(switchContext->dispatchLock, &lockState);\n- status = HvCreatePort(switchContext, &portParam,\n- nicParam->NicIndex);\n- NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0);\n- if (status != NDIS_STATUS_SUCCESS) {\n- goto add_nic_done;\n- }\n- }\n- }\n-\n- vport = OvsFindVportByPortIdAndNicIndex(switchContext, nicParam->PortId,\n- nicParam->NicIndex);\n-\n- if (vport == NULL) {\n- OVS_LOG_ERROR(\"Create NIC without Switch Port,\"\n- \" PortId: %x, NicIndex: %d\",\n- nicParam->PortId, nicParam->NicIndex);\n- status = NDIS_STATUS_INVALID_PARAMETER;\n- goto add_nic_done;\n- }\n- OvsInitVportWithNicParam(switchContext, vport, nicParam);\n- if (OvsIsInternalNIC(nicParam->NicType) ||\n- OvsIsRealExternalNIC(nicParam->NicType, nicParam->NicIndex)) {\n- RtlCopyMemory(&vport->portFriendlyName, &portFriendlyName,\n- sizeof portFriendlyName);\n- }\n-\n-add_nic_done:\n- NdisReleaseRWLock(switchContext->dispatchLock, &lockState);\n-\n-done:\n- VPORT_NIC_EXIT(nicParam);\n- OVS_LOG_TRACE(\"Exit: status %8x.\\n\", status);\n-\n- return status;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Function to process connection event of a NIC on the Hyper-V switch.\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-HvConnectNic(POVS_SWITCH_CONTEXT switchContext,\n- PNDIS_SWITCH_NIC_PARAMETERS nicParam)\n-{\n- LOCK_STATE_EX lockState;\n- POVS_VPORT_ENTRY vport;\n-\n- VPORT_NIC_ENTER(nicParam);\n-\n- /* Wait for lists to be initialized. */\n- OvsWaitActivate(switchContext, OVS_VPORT_DEFAULT_WAIT_TIME_MICROSEC);\n-\n- if (!switchContext->isActivated) {\n- OVS_LOG_WARN(\"Switch is not activated yet.\");\n- goto done;\n- }\n-\n- NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0);\n- vport = OvsFindVportByPortIdAndNicIndex(switchContext,\n- nicParam->PortId,\n- nicParam->NicIndex);\n-\n- if (!vport) {\n- OVS_LOG_WARN(\"Vport not present.\");\n- NdisReleaseRWLock(switchContext->dispatchLock, &lockState);\n- ASSERT(0);\n- goto done;\n- }\n-\n- vport->ovsState = OVS_STATE_CONNECTED;\n- vport->nicState = NdisSwitchNicStateConnected;\n-\n- if (nicParam->NicType == NdisSwitchNicTypeInternal) {\n- OvsBindVportWithIpHelper(vport, switchContext);\n- }\n-\n- NdisReleaseRWLock(switchContext->dispatchLock, &lockState);\n-done:\n- VPORT_NIC_EXIT(nicParam);\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Function to process updates to a NIC on the Hyper-V switch.\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-HvUpdateNic(POVS_SWITCH_CONTEXT switchContext,\n- PNDIS_SWITCH_NIC_PARAMETERS nicParam)\n-{\n- POVS_VPORT_ENTRY vport;\n- LOCK_STATE_EX lockState;\n- UINT32 event = 0;\n- IF_COUNTED_STRING portFriendlyName = {0};\n- BOOLEAN nameChanged = FALSE;\n- BOOLEAN aliasLookup = FALSE;\n-\n- VPORT_NIC_ENTER(nicParam);\n-\n- /* Wait for lists to be initialized. */\n- OvsWaitActivate(switchContext, OVS_VPORT_DEFAULT_WAIT_TIME_MICROSEC);\n-\n- if (!switchContext->isActivated) {\n- OVS_LOG_WARN(\"Switch is not activated yet.\");\n- goto update_nic_done;\n- }\n-\n- /* GetNICAlias() must be called outside of a lock. */\n- if (nicParam->NicType == NdisSwitchNicTypeInternal ||\n- OvsIsRealExternalNIC(nicParam->NicType, nicParam->NicIndex)) {\n- GetNICAlias(nicParam, &portFriendlyName);\n- aliasLookup = TRUE;\n- }\n-\n- NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0);\n- vport = OvsFindVportByPortIdAndNicIndex(switchContext,\n- nicParam->PortId,\n- nicParam->NicIndex);\n- if (vport == NULL) {\n- NdisReleaseRWLock(switchContext->dispatchLock, &lockState);\n- OVS_LOG_WARN(\"Vport search failed.\");\n- goto update_nic_done;\n- }\n- switch (nicParam->NicType) {\n- case NdisSwitchNicTypeExternal:\n- case NdisSwitchNicTypeInternal:\n- RtlCopyMemory(&vport->netCfgInstanceId, &nicParam->NetCfgInstanceId,\n- sizeof (GUID));\n- if (aliasLookup) {\n- if (RtlCompareMemory(&vport->portFriendlyName,\n- &portFriendlyName, vport->portFriendlyName.Length) !=\n- vport->portFriendlyName.Length) {\n- RtlCopyMemory(&vport->portFriendlyName, &portFriendlyName,\n- sizeof portFriendlyName);\n- nameChanged = TRUE;\n- }\n- }\n- break;\n- case NdisSwitchNicTypeSynthetic:\n- case NdisSwitchNicTypeEmulated:\n- if (!RtlEqualMemory(vport->vmMacAddress, nicParam->VMMacAddress,\n- sizeof (vport->vmMacAddress))) {\n- event |= OVS_EVENT_MAC_CHANGE;\n- RtlCopyMemory(vport->vmMacAddress, nicParam->VMMacAddress,\n- sizeof (vport->vmMacAddress));\n- }\n- break;\n- default:\n- ASSERT(0);\n- }\n- if (!RtlEqualMemory(vport->permMacAddress, nicParam->PermanentMacAddress,\n- sizeof (vport->permMacAddress))) {\n- RtlCopyMemory(vport->permMacAddress, nicParam->PermanentMacAddress,\n- sizeof (vport->permMacAddress));\n- event |= OVS_EVENT_MAC_CHANGE;\n- }\n- if (!RtlEqualMemory(vport->currMacAddress, nicParam->CurrentMacAddress,\n- sizeof (vport->currMacAddress))) {\n- RtlCopyMemory(vport->currMacAddress, nicParam->CurrentMacAddress,\n- sizeof (vport->currMacAddress));\n- event |= OVS_EVENT_MAC_CHANGE;\n- }\n-\n- if (vport->mtu != nicParam->MTU) {\n- vport->mtu = nicParam->MTU;\n- event |= OVS_EVENT_MTU_CHANGE;\n- }\n- vport->numaNodeId = nicParam->NumaNodeId;\n-\n- if (nameChanged) {\n- OVS_VPORT_EVENT_ENTRY evt;\n- evt.portNo = vport->portNo;\n- evt.ovsType = vport->ovsType;\n- evt.upcallPid = vport->upcallPid;\n- RtlCopyMemory(&evt.ovsName, &vport->ovsName, sizeof evt.ovsName);\n- evt.type = OVS_EVENT_LINK_DOWN;\n- OvsRemoveAndDeleteVport(NULL, switchContext, vport, FALSE, TRUE);\n- OvsPostVportEvent(&evt);\n- }\n-\n- NdisReleaseRWLock(switchContext->dispatchLock, &lockState);\n-\n- /*\n- * XXX: Not sure what kind of event to post here. DPIF is not interested in\n- * changes to MAC address. Netdev-windows might be intrested, though.\n- * That said, if the name chagnes, not clear what kind of event to be\n- * posted. We might have to delete the vport, and have userspace recreate\n- * it.\n- */\n-\n-update_nic_done:\n- VPORT_NIC_EXIT(nicParam);\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Function to process disconnect event of a NIC on the Hyper-V switch.\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-HvDisconnectNic(POVS_SWITCH_CONTEXT switchContext,\n- PNDIS_SWITCH_NIC_PARAMETERS nicParam)\n-{\n- POVS_VPORT_ENTRY vport;\n- LOCK_STATE_EX lockState;\n- BOOLEAN isInternalPort = FALSE;\n- OVS_VPORT_EVENT_ENTRY event;\n-\n- VPORT_NIC_ENTER(nicParam);\n-\n- /* Wait for lists to be initialized. */\n- OvsWaitActivate(switchContext, OVS_VPORT_DEFAULT_WAIT_TIME_MICROSEC);\n-\n- if (!switchContext->isActivated) {\n- OVS_LOG_WARN(\"Switch is not activated yet.\");\n- goto done;\n- }\n-\n- NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0);\n- vport = OvsFindVportByPortIdAndNicIndex(switchContext,\n- nicParam->PortId,\n- nicParam->NicIndex);\n-\n- if (!vport) {\n- OVS_LOG_WARN(\"Vport not present.\");\n- NdisReleaseRWLock(switchContext->dispatchLock, &lockState);\n- goto done;\n- }\n-\n- vport->nicState = NdisSwitchNicStateDisconnected;\n- vport->ovsState = OVS_STATE_NIC_CREATED;\n-\n- if (vport->ovsType == OVS_VPORT_TYPE_INTERNAL) {\n- isInternalPort = TRUE;\n- }\n-\n- event.portNo = vport->portNo;\n- event.ovsType = vport->ovsType;\n- event.upcallPid = vport->upcallPid;\n- RtlCopyMemory(&event.ovsName, &vport->ovsName, sizeof event.ovsName);\n- event.type = OVS_EVENT_LINK_DOWN;\n- OvsPostVportEvent(&event);\n-\n- /*\n- * Delete the port from the hash tables accessible to userspace. After this\n- * point, userspace should not be able to access this port.\n- */\n- if (OvsIsRealExternalVport(vport)) {\n- OvsRemoveAndDeleteVport(NULL, switchContext, vport, FALSE, TRUE);\n- }\n-\n- if (isInternalPort) {\n- OvsUnBindVportWithIpHelper(vport, switchContext);\n- /*\n- * Don't delete the port from the hash tables here for internal port\n- * because the internal port cannot be recreated in HvCreateNic(). It\n- * only can be created in HvCreatePort() by issuing\n- * OID_SWITCH_PORT_CREATE. We should wait extensible switch interface\n- * to issue OID_SWITCH_PORT_TEARDOWN and OID_SWITCH_PORT_DELETE to\n- * delete the internal port.\n- */\n- }\n- NdisReleaseRWLock(switchContext->dispatchLock, &lockState);\n-\n-done:\n- VPORT_NIC_EXIT(nicParam);\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Function to process delete event of a NIC on the Hyper-V switch.\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-HvDeleteNic(POVS_SWITCH_CONTEXT switchContext,\n- PNDIS_SWITCH_NIC_PARAMETERS nicParam)\n-{\n- LOCK_STATE_EX lockState;\n- POVS_VPORT_ENTRY vport;\n-\n- VPORT_NIC_ENTER(nicParam);\n- /* Wait for lists to be initialized. */\n- OvsWaitActivate(switchContext, OVS_VPORT_DEFAULT_WAIT_TIME_MICROSEC);\n-\n- if (!switchContext->isActivated) {\n- OVS_LOG_WARN(\"Switch is not activated yet.\");\n- goto done;\n- }\n-\n- NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0);\n- vport = OvsFindVportByPortIdAndNicIndex(switchContext,\n- nicParam->PortId,\n- nicParam->NicIndex);\n-\n- if (!vport) {\n- OVS_LOG_WARN(\"Vport not present.\");\n- NdisReleaseRWLock(switchContext->dispatchLock, &lockState);\n- goto done;\n- }\n-\n- vport->nicState = NdisSwitchNicStateUnknown;\n- vport->ovsState = OVS_STATE_PORT_CREATED;\n-\n- if (OvsIsRealExternalVport(vport)) {\n- /* This vport was created in HvCreateNic(). */\n- OvsRemoveAndDeleteVport(NULL, switchContext, vport, TRUE, FALSE);\n- }\n-\n- NdisReleaseRWLock(switchContext->dispatchLock, &lockState);\n-\n-done:\n- VPORT_NIC_EXIT(nicParam);\n-}\n-\n-/*\n- * OVS Vport related functionality.\n- */\n-_Use_decl_annotations_\n-POVS_VPORT_ENTRY\n-OvsFindVportByPortNo(POVS_SWITCH_CONTEXT switchContext,\n- UINT32 portNo)\n-{\n- POVS_VPORT_ENTRY vport;\n- PLIST_ENTRY head, link;\n- UINT32 hash = OvsJhashBytes((const VOID *)&portNo, sizeof(portNo),\n- OVS_HASH_BASIS);\n- head = &(switchContext->portNoHashArray[hash & OVS_VPORT_MASK]);\n- LIST_FORALL(head, link) {\n- vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, portNoLink);\n- if (vport->portNo == portNo) {\n- return vport;\n- }\n- }\n- return NULL;\n-}\n-\n-\n-POVS_VPORT_ENTRY\n-OvsFindTunnelVportByDstPortAndType(POVS_SWITCH_CONTEXT switchContext,\n- UINT16 dstPort,\n- OVS_VPORT_TYPE ovsPortType)\n-{\n- POVS_VPORT_ENTRY vport;\n- PLIST_ENTRY head, link;\n- UINT32 hash = OvsJhashBytes((const VOID *)&dstPort, sizeof(dstPort),\n- OVS_HASH_BASIS);\n- head = &(switchContext->tunnelVportsArray[hash & OVS_VPORT_MASK]);\n- LIST_FORALL(head, link) {\n- vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, tunnelVportLink);\n- if (GetPortFromPriv(vport) == dstPort &&\n- vport->ovsType == ovsPortType) {\n- return vport;\n- }\n- }\n- return NULL;\n-}\n-\n-POVS_VPORT_ENTRY\n-OvsFindTunnelVportByDstPortAndNWProto(POVS_SWITCH_CONTEXT switchContext,\n- UINT16 dstPort,\n- UINT8 nwProto)\n-{\n- POVS_VPORT_ENTRY vport;\n- PLIST_ENTRY head, link;\n- UINT32 hash = OvsJhashBytes((const VOID *)&dstPort, sizeof(dstPort),\n- OVS_HASH_BASIS);\n- head = &(switchContext->tunnelVportsArray[hash & OVS_VPORT_MASK]);\n- LIST_FORALL(head, link) {\n- vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, tunnelVportLink);\n- if (GetPortFromPriv(vport) == dstPort) {\n- switch (nwProto) {\n- case IPPROTO_UDP:\n- if (vport->ovsType != OVS_VPORT_TYPE_GENEVE &&\n- vport->ovsType != OVS_VPORT_TYPE_VXLAN) {\n- continue;\n- }\n- break;\n- case IPPROTO_GRE:\n- break;\n- default:\n- continue;\n- }\n- return vport;\n- }\n- }\n- return NULL;\n-}\n-\n-POVS_VPORT_ENTRY\n-OvsFindTunnelVportByPortType(POVS_SWITCH_CONTEXT switchContext,\n- OVS_VPORT_TYPE ovsPortType)\n-{\n- POVS_VPORT_ENTRY vport;\n- PLIST_ENTRY head, link;\n- UINT16 dstPort = 0;\n- UINT32 hash = OvsJhashBytes((const VOID *)&dstPort, sizeof(dstPort),\n- OVS_HASH_BASIS);\n- head = &(switchContext->tunnelVportsArray[hash & OVS_VPORT_MASK]);\n- LIST_FORALL(head, link) {\n- vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, tunnelVportLink);\n- if (vport->ovsType == ovsPortType) {\n- return vport;\n- }\n- }\n- return NULL;\n-}\n-\n-_Use_decl_annotations_\n-POVS_VPORT_ENTRY\n-OvsFindVportByOvsName(POVS_SWITCH_CONTEXT switchContext,\n- PSTR name)\n-{\n- POVS_VPORT_ENTRY vport;\n- PLIST_ENTRY head, link;\n- UINT32 hash;\n- SIZE_T length = strlen(name) + 1;\n-\n- hash = OvsJhashBytes((const VOID *)name, length, OVS_HASH_BASIS);\n- head = &(switchContext->ovsPortNameHashArray[hash & OVS_VPORT_MASK]);\n-\n- LIST_FORALL(head, link) {\n- vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, ovsNameLink);\n- if (!strcmp(name, vport->ovsName)) {\n- return vport;\n- }\n- }\n-\n- return NULL;\n-}\n-\n-/* OvsFindVportByHvName: \"name\" is assumed to be null-terminated */\n-_Use_decl_annotations_\n-POVS_VPORT_ENTRY\n-OvsFindVportByHvNameW(POVS_SWITCH_CONTEXT switchContext,\n- PWSTR wsName, SIZE_T wstrSize)\n-{\n- POVS_VPORT_ENTRY vport = NULL;\n- PLIST_ENTRY head, link;\n- UINT i;\n-\n- for (i = 0; i < OVS_MAX_VPORT_ARRAY_SIZE; i++) {\n- head = &(switchContext->portIdHashArray[i]);\n- LIST_FORALL(head, link) {\n- vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, portIdLink);\n-\n- /*\n- * NOTE about portFriendlyName:\n- * If the string is NULL-terminated, the Length member does not\n- * include the terminating NULL character.\n- */\n- if (vport->portFriendlyName.Length == wstrSize &&\n- RtlEqualMemory(wsName, vport->portFriendlyName.String,\n- vport->portFriendlyName.Length)) {\n- goto Cleanup;\n- }\n-\n- vport = NULL;\n- }\n- }\n-\n- /*\n- * Look in the list of ports that were added from the Hyper-V switch and\n- * deleted.\n- */\n- if (vport == NULL) {\n- for (i = 0; i < OVS_MAX_VPORT_ARRAY_SIZE; i++) {\n- head = &(switchContext->portNoHashArray[i]);\n- LIST_FORALL(head, link) {\n- vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, portNoLink);\n- if (vport->portFriendlyName.Length == wstrSize &&\n- RtlEqualMemory(wsName, vport->portFriendlyName.String,\n- vport->portFriendlyName.Length)) {\n- goto Cleanup;\n- }\n-\n- vport = NULL;\n- }\n- }\n- }\n-\n-Cleanup:\n- return vport;\n-}\n-\n-_Use_decl_annotations_\n-POVS_VPORT_ENTRY\n-OvsFindVportByHvNameA(POVS_SWITCH_CONTEXT switchContext,\n- PSTR name)\n-{\n- POVS_VPORT_ENTRY vport = NULL;\n- /* 'portFriendlyName' is not NUL-terminated. */\n- SIZE_T length = strlen(name);\n- SIZE_T wstrSize = length * sizeof(WCHAR);\n- UINT i;\n-\n- PWSTR wsName = OvsAllocateMemoryWithTag(wstrSize, OVS_VPORT_POOL_TAG);\n- if (!wsName) {\n- return NULL;\n- }\n- for (i = 0; i < length; i++) {\n- wsName[i] = name[i];\n- }\n- vport = OvsFindVportByHvNameW(switchContext, wsName, wstrSize);\n- OvsFreeMemoryWithTag(wsName, OVS_VPORT_POOL_TAG);\n- return vport;\n-}\n-\n-_Use_decl_annotations_\n-POVS_VPORT_ENTRY\n-OvsFindVportByPortIdAndNicIndex(POVS_SWITCH_CONTEXT switchContext,\n- NDIS_SWITCH_PORT_ID portId,\n- NDIS_SWITCH_NIC_INDEX index)\n-{\n- if (switchContext->virtualExternalVport &&\n- portId == switchContext->virtualExternalPortId &&\n- index == switchContext->virtualExternalVport->nicIndex) {\n- return (POVS_VPORT_ENTRY)switchContext->virtualExternalVport;\n- } else {\n- PLIST_ENTRY head, link;\n- POVS_VPORT_ENTRY vport;\n- UINT32 hash;\n- hash = OvsJhashWords((UINT32 *)&portId, 1, OVS_HASH_BASIS);\n- head = &(switchContext->portIdHashArray[hash & OVS_VPORT_MASK]);\n- LIST_FORALL(head, link) {\n- vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, portIdLink);\n- if (portId == vport->portId && index == vport->nicIndex) {\n- return vport;\n- }\n- }\n- return NULL;\n- }\n-}\n-\n-BOOLEAN OvsIsExternalVportByPortId(POVS_SWITCH_CONTEXT switchContext,\n- NDIS_SWITCH_PORT_ID portId)\n-{\n- return (portId == switchContext->virtualExternalPortId);\n-}\n-\n-POVS_VPORT_ENTRY\n-OvsAllocateVport(VOID)\n-{\n- POVS_VPORT_ENTRY vport;\n- vport = (POVS_VPORT_ENTRY)OvsAllocateMemoryWithTag(\n- sizeof(OVS_VPORT_ENTRY), OVS_VPORT_POOL_TAG);\n- if (vport == NULL) {\n- return NULL;\n- }\n- RtlZeroMemory(vport, sizeof (OVS_VPORT_ENTRY));\n- vport->ovsState = OVS_STATE_UNKNOWN;\n- vport->isAbsentOnHv = FALSE;\n- vport->portNo = OVS_DPPORT_NUMBER_INVALID;\n-\n- InitializeListHead(&vport->ovsNameLink);\n- InitializeListHead(&vport->portIdLink);\n- InitializeListHead(&vport->portNoLink);\n-\n- return vport;\n-}\n-\n-static VOID\n-OvsInitVportWithPortParam(POVS_VPORT_ENTRY vport,\n- PNDIS_SWITCH_PORT_PARAMETERS portParam)\n-{\n- vport->portType = portParam->PortType;\n- vport->portState = portParam->PortState;\n- vport->portId = portParam->PortId;\n- vport->nicState = NdisSwitchNicStateUnknown;\n- vport->isExternal = FALSE;\n-\n- switch (vport->portType) {\n- case NdisSwitchPortTypeExternal:\n- vport->isExternal = TRUE;\n- vport->ovsType = OVS_VPORT_TYPE_NETDEV;\n- break;\n- case NdisSwitchPortTypeInternal:\n- vport->ovsType = OVS_VPORT_TYPE_INTERNAL;\n- break;\n- case NdisSwitchPortTypeSynthetic:\n- case NdisSwitchPortTypeEmulated:\n- vport->ovsType = OVS_VPORT_TYPE_NETDEV;\n- break;\n- }\n- RtlCopyMemory(&vport->hvPortName, &portParam->PortName,\n- sizeof (NDIS_SWITCH_PORT_NAME));\n- /* For external and internal ports, 'portFriendlyName' is overwritten\n- * later. */\n- RtlCopyMemory(&vport->portFriendlyName, &portParam->PortFriendlyName,\n- sizeof(NDIS_SWITCH_PORT_FRIENDLYNAME));\n-\n- switch (vport->portState) {\n- case NdisSwitchPortStateCreated:\n- vport->ovsState = OVS_STATE_PORT_CREATED;\n- break;\n- case NdisSwitchPortStateTeardown:\n- vport->ovsState = OVS_STATE_PORT_TEAR_DOWN;\n- break;\n- case NdisSwitchPortStateDeleted:\n- vport->ovsState = OVS_STATE_PORT_DELETED;\n- break;\n- }\n-}\n-\n-\n-static VOID\n-OvsInitVportWithNicParam(POVS_SWITCH_CONTEXT switchContext,\n- POVS_VPORT_ENTRY vport,\n- PNDIS_SWITCH_NIC_PARAMETERS nicParam)\n-{\n- ASSERT(vport->portId == nicParam->PortId);\n-\n- UNREFERENCED_PARAMETER(switchContext);\n-\n- RtlCopyMemory(vport->permMacAddress, nicParam->PermanentMacAddress,\n- sizeof (vport->permMacAddress));\n- RtlCopyMemory(vport->currMacAddress, nicParam->CurrentMacAddress,\n- sizeof (vport->currMacAddress));\n-\n- if (nicParam->NicType == NdisSwitchNicTypeSynthetic ||\n- nicParam->NicType == NdisSwitchNicTypeEmulated) {\n- RtlCopyMemory(vport->vmMacAddress, nicParam->VMMacAddress,\n- sizeof (vport->vmMacAddress));\n- RtlCopyMemory(&vport->vmName, &nicParam->VmName,\n- sizeof (nicParam->VmName));\n- } else {\n- RtlCopyMemory(&vport->netCfgInstanceId, &nicParam->NetCfgInstanceId,\n- sizeof (nicParam->NetCfgInstanceId));\n- RtlCopyMemory(&vport->nicFriendlyName, &nicParam->NicFriendlyName,\n- sizeof (nicParam->NicFriendlyName));\n- }\n- RtlCopyMemory(&vport->nicName, &nicParam->NicName,\n- sizeof (nicParam->NicName));\n- vport->mtu = nicParam->MTU;\n- vport->nicState = nicParam->NicState;\n- vport->nicIndex = nicParam->NicIndex;\n- vport->nicType = nicParam->NicType;\n- vport->numaNodeId = nicParam->NumaNodeId;\n-\n- switch (vport->nicState) {\n- case NdisSwitchNicStateCreated:\n- vport->ovsState = OVS_STATE_NIC_CREATED;\n- break;\n- case NdisSwitchNicStateConnected:\n- vport->ovsState = OVS_STATE_CONNECTED;\n- break;\n- case NdisSwitchNicStateDisconnected:\n- vport->ovsState = OVS_STATE_NIC_CREATED;\n- break;\n- case NdisSwitchNicStateDeleted:\n- vport->ovsState = OVS_STATE_PORT_CREATED;\n- break;\n- }\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Populates 'portParam' based on 'vport'.\n- * --------------------------------------------------------------------------\n- */\n-static VOID\n-OvsCopyPortParamsFromVport(POVS_VPORT_ENTRY vport,\n- PNDIS_SWITCH_PORT_PARAMETERS portParam)\n-{\n- portParam->Flags = 0;\n- portParam->PortId = vport->portId;\n- RtlCopyMemory(&portParam->PortName, &vport->hvPortName,\n- sizeof (NDIS_SWITCH_PORT_NAME));\n- RtlCopyMemory(&portParam->PortFriendlyName,\n- &vport->portFriendlyName,\n- sizeof(NDIS_SWITCH_PORT_FRIENDLYNAME));\n- portParam->PortType = vport->portType;\n- portParam->IsValidationPort = FALSE;\n- portParam->PortState = vport->portState;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Initializes a tunnel vport.\n- * --------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsInitTunnelVport(PVOID userContext,\n- POVS_VPORT_ENTRY vport,\n- OVS_VPORT_TYPE ovsType,\n- UINT16 dstPort)\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n- POVS_USER_PARAMS_CONTEXT usrParamsCtx =\n- (POVS_USER_PARAMS_CONTEXT)userContext;\n-\n- vport->ovsType = ovsType;\n- vport->ovsState = OVS_STATE_PORT_CREATED;\n- switch (ovsType) {\n- case OVS_VPORT_TYPE_GRE:\n- status = OvsInitGreTunnel(vport);\n- break;\n- case OVS_VPORT_TYPE_VXLAN:\n- {\n- POVS_TUNFLT_INIT_CONTEXT tunnelContext = NULL;\n-\n- tunnelContext = OvsAllocateMemoryWithTag(sizeof(*tunnelContext),\n- OVS_VPORT_POOL_TAG);\n- if (tunnelContext == NULL) {\n- status = STATUS_INSUFFICIENT_RESOURCES;\n- break;\n- }\n- tunnelContext->inputBuffer = usrParamsCtx->inputBuffer;\n- tunnelContext->outputBuffer = usrParamsCtx->outputBuffer;\n- tunnelContext->outputLength = usrParamsCtx->outputLength;\n- tunnelContext->vport = vport;\n-\n- status = OvsInitVxlanTunnel(usrParamsCtx->irp,\n- vport,\n- dstPort,\n- OvsTunnelVportPendingInit,\n- (PVOID)tunnelContext);\n- if (status != STATUS_PENDING) {\n- OvsFreeMemoryWithTag(tunnelContext, OVS_VPORT_POOL_TAG);\n- tunnelContext = NULL;\n- }\n- break;\n- }\n- case OVS_VPORT_TYPE_GENEVE:\n- status = OvsInitGeneveTunnel(vport, dstPort);\n- break;\n- default:\n- ASSERT(0);\n- }\n- return status;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * For external and internal vports 'portFriendlyName' parameter, provided by\n- * Hyper-V, is overwritten with the interface alias name and NIC friendly name\n- * equivalent.\n- * --------------------------------------------------------------------------\n- */\n-static NTSTATUS\n-GetNICAlias(PNDIS_SWITCH_NIC_PARAMETERS nicParam,\n- IF_COUNTED_STRING *portFriendlyName)\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n- WCHAR interfaceName[IF_MAX_STRING_SIZE + 1];\n- NET_LUID interfaceLuid;\n- size_t len;\n-\n- if (nicParam->NicType == NdisSwitchNicTypeInternal) {\n- RtlCopyMemory(portFriendlyName, &nicParam->NicFriendlyName,\n- sizeof nicParam->NicFriendlyName);\n- return status;\n- }\n-\n- status = ConvertInterfaceGuidToLuid(&nicParam->NetCfgInstanceId,\n- &interfaceLuid);\n- if (status == STATUS_SUCCESS) {\n- /*\n- * Must be called from PASSIVE_LEVEL. Resulted in a\n- * STATUS_INVALID_DEVICE_REQUEST if not.\n- */\n- status = ConvertInterfaceLuidToAlias(&interfaceLuid, interfaceName,\n- IF_MAX_STRING_SIZE + 1);\n- if (status == STATUS_SUCCESS) {\n- RtlStringCbPrintfW(portFriendlyName->String,\n- IF_MAX_STRING_SIZE, L\"%s\", interfaceName);\n- status = RtlStringCbLengthW(portFriendlyName->String,\n- IF_MAX_STRING_SIZE, &len);\n- if (!NT_SUCCESS(status)) {\n- OVS_LOG_ERROR(\"Failed to get the length of the string,\"\n- \"status: %x\", status);\n- return status;\n- }\n- portFriendlyName->Length = (USHORT)len;\n- } else {\n- OVS_LOG_ERROR(\"Fail to convert interface LUID to alias, status: %x\",\n- status);\n- }\n- } else {\n- OVS_LOG_ERROR(\"Fail to convert interface GUID to LUID, status: %x\",\n- status);\n- }\n-\n- return status;\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Functionality common to any port on the Hyper-V switch. This function is not\n- * to be called for a port that is not on the Hyper-V switch.\n- *\n- * Inserts the port into 'portIdHashArray' and caches the pointer in the\n- * 'switchContext' if needed.\n- * --------------------------------------------------------------------------\n- */\n-static VOID\n-UpdateSwitchCtxWithVport(POVS_SWITCH_CONTEXT switchContext,\n- POVS_VPORT_ENTRY vport,\n- BOOLEAN newPort)\n-{\n- UINT32 hash;\n-\n- switch (vport->portType) {\n- case NdisSwitchPortTypeExternal:\n- if (vport->nicIndex == 0) {\n- switchContext->virtualExternalPortId = vport->portId;\n- switchContext->virtualExternalVport = vport;\n- } else if (newPort == TRUE) {\n- switchContext->numPhysicalNics++;\n- }\n- break;\n- case NdisSwitchPortTypeInternal:\n- switchContext->countInternalVports++;\n- break;\n- case NdisSwitchPortTypeSynthetic:\n- case NdisSwitchPortTypeEmulated:\n- break;\n- }\n-\n- /*\n- * It is important to not insert vport corresponding to virtual external\n- * port into the 'portIdHashArray' since the port should not be exposed to\n- * OVS userspace.\n- */\n- if (vport->portType == NdisSwitchPortTypeExternal &&\n- vport->nicIndex == 0) {\n- return;\n- }\n-\n- /*\n- * NOTE: OvsJhashWords has portId as \"1\" word. This should be ok, even\n- * though sizeof(NDIS_SWITCH_PORT_ID) = 4, not 2, because the\n- * hyper-v switch seems to use only 2 bytes out of 4.\n- */\n- hash = OvsJhashWords(&vport->portId, 1, OVS_HASH_BASIS);\n- InsertHeadList(&switchContext->portIdHashArray[hash & OVS_VPORT_MASK],\n- &vport->portIdLink);\n- if (newPort) {\n- switchContext->numHvVports++;\n- }\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Functionality common to any port added from OVS userspace.\n- *\n- * Inserts the port into 'portNoHashArray', 'ovsPortNameHashArray' and in\n- * 'tunnelVportsArray' if appropriate.\n- * --------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-InitOvsVportCommon(POVS_SWITCH_CONTEXT switchContext,\n- POVS_VPORT_ENTRY vport)\n-{\n- UINT32 hash;\n-\n- switch(vport->ovsType) {\n- case OVS_VPORT_TYPE_GRE:\n- case OVS_VPORT_TYPE_VXLAN:\n- case OVS_VPORT_TYPE_GENEVE:\n- {\n- UINT16 dstPort = GetPortFromPriv(vport);\n- hash = OvsJhashBytes(&dstPort,\n- sizeof(dstPort),\n- OVS_HASH_BASIS);\n- InsertHeadList(\n- &gOvsSwitchContext->tunnelVportsArray[hash & OVS_VPORT_MASK],\n- &vport->tunnelVportLink);\n- switchContext->numNonHvVports++;\n- break;\n- }\n- default:\n- break;\n- }\n-\n- /*\n- * Insert the port into the hash array of ports: by port number and ovs\n- * and ovs (datapath) port name.\n- * NOTE: OvsJhashWords has portNo as \"1\" word. This is ok, because the\n- * portNo is stored in 2 bytes only (max port number = MAXUINT16).\n- */\n- hash = OvsJhashWords(&vport->portNo, 1, OVS_HASH_BASIS);\n- InsertHeadList(&gOvsSwitchContext->portNoHashArray[hash & OVS_VPORT_MASK],\n- &vport->portNoLink);\n-\n- hash = OvsJhashBytes(vport->ovsName, strlen(vport->ovsName) + 1,\n- OVS_HASH_BASIS);\n- InsertHeadList(\n- &gOvsSwitchContext->ovsPortNameHashArray[hash & OVS_VPORT_MASK],\n- &vport->ovsNameLink);\n-\n- return STATUS_SUCCESS;\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Provides functionality that is partly complementatry to\n- * InitOvsVportCommon()/UpdateSwitchCtxWithVport().\n- *\n- * 'hvDelete' indicates if caller is removing the vport as a result of the\n- * port being removed on the Hyper-V switch.\n- * 'ovsDelete' indicates if caller is removing the vport as a result of the\n- * port being removed from OVS userspace.\n- * --------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsRemoveAndDeleteVport(PVOID usrParamsContext,\n- POVS_SWITCH_CONTEXT switchContext,\n- POVS_VPORT_ENTRY vport,\n- BOOLEAN hvDelete,\n- BOOLEAN ovsDelete)\n-{\n- POVS_USER_PARAMS_CONTEXT usrParamsCtx =\n- (POVS_USER_PARAMS_CONTEXT)usrParamsContext;\n- BOOLEAN hvSwitchPort = FALSE;\n- BOOLEAN deletedOnOvs = FALSE;\n- BOOLEAN deletedOnHv = FALSE;\n-\n- switch (vport->ovsType) {\n- case OVS_VPORT_TYPE_INTERNAL:\n- if (hvDelete && vport->isAbsentOnHv == FALSE) {\n- switchContext->countInternalVports--;\n- ASSERT(switchContext->countInternalVports >= 0);\n- OvsUnBindVportWithIpHelper(vport, switchContext);\n- }\n- hvSwitchPort = TRUE;\n- break;\n- case OVS_VPORT_TYPE_VXLAN:\n- {\n- NTSTATUS status;\n- status = OvsRemoveTunnelVport(usrParamsCtx, switchContext, vport,\n- hvDelete, ovsDelete);\n- if (status != STATUS_SUCCESS) {\n- return status;\n- }\n- }\n- case OVS_VPORT_TYPE_GENEVE:\n- OvsCleanupGeneveTunnel(vport);\n- break;\n- case OVS_VPORT_TYPE_GRE:\n- OvsCleanupGreTunnel(vport);\n- break;\n- case OVS_VPORT_TYPE_NETDEV:\n- if (vport->isExternal) {\n- if (vport->nicIndex == 0) {\n- /* Such a vport is not part of any of the hash tables, since it\n- * is not exposed to userspace. See Vport.h for explanation. */\n- ASSERT(hvDelete == TRUE);\n- ASSERT(switchContext->numPhysicalNics == 0);\n- switchContext->virtualExternalPortId = 0;\n- switchContext->virtualExternalVport = NULL;\n- OvsFreeMemoryWithTag(vport, OVS_VPORT_POOL_TAG);\n- return STATUS_SUCCESS;\n- }\n- }\n- hvSwitchPort = TRUE;\n- default:\n- break;\n- }\n-\n- /*\n- * 'hvDelete' == TRUE indicates that the port should be removed from the\n- * 'portIdHashArray', while 'ovsDelete' == TRUE indicates that the port\n- * should be removed from 'portNoHashArray' and the 'ovsPortNameHashArray'.\n- *\n- * Both 'hvDelete' and 'ovsDelete' can be set to TRUE by the caller.\n- */\n- if (vport->isAbsentOnHv == TRUE) {\n- deletedOnHv = TRUE;\n- }\n- if (vport->portNo == OVS_DPPORT_NUMBER_INVALID) {\n- deletedOnOvs = TRUE;\n- }\n-\n- if (hvDelete && !deletedOnHv) {\n- vport->isAbsentOnHv = TRUE;\n-\n- if (vport->isExternal) {\n- ASSERT(vport->nicIndex != 0);\n- ASSERT(switchContext->numPhysicalNics);\n- switchContext->numPhysicalNics--;\n- }\n-\n- /* Remove the port from the relevant lists. */\n- RemoveEntryList(&vport->portIdLink);\n- InitializeListHead(&vport->portIdLink);\n- deletedOnHv = TRUE;\n- }\n- if (ovsDelete && !deletedOnOvs) {\n- vport->portNo = OVS_DPPORT_NUMBER_INVALID;\n- vport->ovsName[0] = '\\0';\n-\n- /* Remove the port from the relevant lists. */\n- RemoveEntryList(&vport->ovsNameLink);\n- InitializeListHead(&vport->ovsNameLink);\n- RemoveEntryList(&vport->portNoLink);\n- InitializeListHead(&vport->portNoLink);\n- if (OvsIsTunnelVportType(vport->ovsType)) {\n- RemoveEntryList(&vport->tunnelVportLink);\n- InitializeListHead(&vport->tunnelVportLink);\n- }\n-\n- deletedOnOvs = TRUE;\n- }\n-\n- /*\n- * Deallocate the port if it has been deleted on the Hyper-V switch as well\n- * as OVS userspace.\n- */\n- if (deletedOnHv && deletedOnOvs) {\n- if (hvSwitchPort) {\n- switchContext->numHvVports--;\n- } else {\n- switchContext->numNonHvVports--;\n- }\n- OvsFreeMemoryWithTag(vport, OVS_VPORT_POOL_TAG);\n- }\n-\n- return STATUS_SUCCESS;\n-}\n-\n-static NTSTATUS\n-OvsRemoveTunnelVport(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- POVS_SWITCH_CONTEXT switchContext,\n- POVS_VPORT_ENTRY vport,\n- BOOLEAN hvDelete,\n- BOOLEAN ovsDelete)\n-{\n- POVS_TUNFLT_INIT_CONTEXT tunnelContext = NULL;\n- PIRP irp = NULL;\n-\n- tunnelContext = OvsAllocateMemoryWithTag(sizeof(*tunnelContext),\n- OVS_VPORT_POOL_TAG);\n- if (tunnelContext == NULL) {\n- return STATUS_INSUFFICIENT_RESOURCES;\n- }\n- RtlZeroMemory(tunnelContext, sizeof(*tunnelContext));\n-\n- tunnelContext->switchContext = switchContext;\n- tunnelContext->hvSwitchPort = FALSE;\n- tunnelContext->hvDelete = hvDelete;\n- tunnelContext->ovsDelete = ovsDelete;\n- tunnelContext->vport = vport;\n-\n- if (usrParamsCtx) {\n- tunnelContext->inputBuffer = usrParamsCtx->inputBuffer;\n- tunnelContext->outputBuffer = usrParamsCtx->outputBuffer;\n- tunnelContext->outputLength = usrParamsCtx->outputLength;\n- irp = usrParamsCtx->irp;\n- }\n-\n- return OvsCleanupVxlanTunnel(irp, vport, OvsTunnelVportPendingRemove,\n- tunnelContext);\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Enumerates the ports on the Hyper-V switch.\n- * --------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsAddConfiguredSwitchPorts(POVS_SWITCH_CONTEXT switchContext)\n-{\n- NDIS_STATUS status = NDIS_STATUS_SUCCESS;\n- ULONG arrIndex;\n- PNDIS_SWITCH_PORT_PARAMETERS portParam;\n- PNDIS_SWITCH_PORT_ARRAY portArray = NULL;\n-\n- OVS_LOG_TRACE(\"Enter: switchContext:%p\", switchContext);\n-\n- status = OvsGetPortsOnSwitch(switchContext, &portArray);\n- if (status != NDIS_STATUS_SUCCESS) {\n- goto cleanup;\n- }\n-\n- for (arrIndex = 0; arrIndex < portArray->NumElements; arrIndex++) {\n- portParam = NDIS_SWITCH_PORT_AT_ARRAY_INDEX(portArray, arrIndex);\n-\n- if (portParam->IsValidationPort) {\n- continue;\n- }\n-\n- status = HvCreatePort(switchContext, portParam, 0);\n- if (status != STATUS_SUCCESS && status != STATUS_DATA_NOT_ACCEPTED) {\n- break;\n- }\n- }\n-\n-cleanup:\n- if (status != NDIS_STATUS_SUCCESS) {\n- OvsClearAllSwitchVports(switchContext);\n- }\n-\n- OvsFreeSwitchPortsArray(portArray);\n-\n- OVS_LOG_TRACE(\"Exit: status: %x\", status);\n-\n- return status;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Enumerates the NICs on the Hyper-V switch.\n- * --------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsInitConfiguredSwitchNics(POVS_SWITCH_CONTEXT switchContext)\n-{\n- NDIS_STATUS status = NDIS_STATUS_SUCCESS;\n- PNDIS_SWITCH_NIC_ARRAY nicArray = NULL;\n- ULONG arrIndex;\n- PNDIS_SWITCH_NIC_PARAMETERS nicParam;\n-\n- OVS_LOG_TRACE(\"Enter: switchContext: %p\", switchContext);\n- /*\n- * Now, get NIC list.\n- */\n- status = OvsGetNicsOnSwitch(switchContext, &nicArray);\n- if (status != NDIS_STATUS_SUCCESS) {\n- goto cleanup;\n- }\n- for (arrIndex = 0; arrIndex < nicArray->NumElements; ++arrIndex) {\n- nicParam = NDIS_SWITCH_NIC_AT_ARRAY_INDEX(nicArray, arrIndex);\n-\n- /*\n- * XXX: Check if the port is configured with a VLAN. Disallow such a\n- * configuration, since we don't support tag-in-tag.\n- * XXX: Check if the port is connected to a VF. Disconnect the VF in\n- * such a case.\n- */\n-\n- status = HvCreateNic(switchContext, nicParam);\n- if (status == NDIS_STATUS_SUCCESS) {\n- HvConnectNic(switchContext, nicParam);\n- }\n- }\n-cleanup:\n-\n- OvsFreeSwitchNicsArray(nicArray);\n-\n- OVS_LOG_TRACE(\"Exit: status: %x\", status);\n- return status;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Deletes ports added from the Hyper-V switch as well as OVS usersapce. The\n- * function deletes ports in 'portIdHashArray'. This will delete most of the\n- * ports that are in the 'portNoHashArray' as well. Any remaining ports\n- * are deleted by walking the 'portNoHashArray'.\n- * --------------------------------------------------------------------------\n- */\n-VOID\n-OvsClearAllSwitchVports(POVS_SWITCH_CONTEXT switchContext)\n-{\n- for (UINT hash = 0; hash < OVS_MAX_VPORT_ARRAY_SIZE; hash++) {\n- PLIST_ENTRY head, link, next;\n-\n- head = &(switchContext->portIdHashArray[hash & OVS_VPORT_MASK]);\n- LIST_FORALL_SAFE(head, link, next) {\n- POVS_VPORT_ENTRY vport;\n- vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, portIdLink);\n- OvsRemoveAndDeleteVport(NULL, switchContext, vport, TRUE, TRUE);\n- }\n- }\n-\n- /*\n- * Remove 'virtualExternalVport' as well. This port is not part of the\n- * 'portIdHashArray'.\n- */\n- if (switchContext->virtualExternalVport) {\n- OvsRemoveAndDeleteVport(NULL, switchContext,\n- (POVS_VPORT_ENTRY)switchContext->virtualExternalVport, TRUE, TRUE);\n- }\n-\n-\n- for (UINT hash = 0; hash < OVS_MAX_VPORT_ARRAY_SIZE; hash++) {\n- PLIST_ENTRY head, link, next;\n- head = &(switchContext->portNoHashArray[hash & OVS_VPORT_MASK]);\n- LIST_FORALL_SAFE(head, link, next) {\n- POVS_VPORT_ENTRY vport;\n- vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, portNoLink);\n- ASSERT(OvsIsTunnelVportType(vport->ovsType) ||\n- vport->isAbsentOnHv == TRUE);\n- OvsRemoveAndDeleteVport(NULL, switchContext, vport, TRUE, TRUE);\n- }\n- }\n-\n- ASSERT(switchContext->virtualExternalVport == NULL);\n- ASSERT(switchContext->countInternalVports == 0);\n-}\n-\n-\n-NTSTATUS\n-OvsConvertIfCountedStrToAnsiStr(PIF_COUNTED_STRING wStr,\n- CHAR *str,\n- UINT16 maxStrLen)\n-{\n- ANSI_STRING astr;\n- UNICODE_STRING ustr;\n- NTSTATUS status;\n- UINT32 size;\n-\n- ustr.Buffer = wStr->String;\n- ustr.Length = wStr->Length;\n- ustr.MaximumLength = IF_MAX_STRING_SIZE;\n-\n- astr.Buffer = str;\n- astr.MaximumLength = maxStrLen;\n- astr.Length = 0;\n-\n- size = RtlUnicodeStringToAnsiSize(&ustr);\n- if (size > maxStrLen) {\n- return STATUS_BUFFER_OVERFLOW;\n- }\n-\n- status = RtlUnicodeStringToAnsiString(&astr, &ustr, FALSE);\n-\n- ASSERT(status == STATUS_SUCCESS);\n- if (status != STATUS_SUCCESS) {\n- return status;\n- }\n- ASSERT(astr.Length <= maxStrLen);\n- str[astr.Length] = 0;\n- return STATUS_SUCCESS;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Utility function that populates a 'OVS_VPORT_EXT_INFO' structure for the\n- * specified vport.\n- * --------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsGetExtInfoIoctl(POVS_VPORT_GET vportGet,\n- POVS_VPORT_EXT_INFO extInfo)\n-{\n- POVS_VPORT_ENTRY vport;\n- LOCK_STATE_EX lockState;\n- NTSTATUS status = STATUS_SUCCESS;\n- BOOLEAN doConvert = FALSE;\n-\n- RtlZeroMemory(extInfo, sizeof (POVS_VPORT_EXT_INFO));\n- NdisAcquireRWLockRead(gOvsSwitchContext->dispatchLock, &lockState, 0);\n- if (vportGet->portNo == 0) {\n- vport = OvsFindVportByHvNameA(gOvsSwitchContext, vportGet->name);\n- if (vport == NULL) {\n- /* If the port is not a Hyper-V port and it has been added earlier,\n- * we'll find it in 'ovsPortNameHashArray'. */\n- vport = OvsFindVportByOvsName(gOvsSwitchContext, vportGet->name);\n- }\n- } else {\n- vport = OvsFindVportByPortNo(gOvsSwitchContext, vportGet->portNo);\n- }\n- if (vport == NULL || (vport->ovsState != OVS_STATE_CONNECTED &&\n- vport->ovsState != OVS_STATE_NIC_CREATED)) {\n- NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState);\n- if (vportGet->portNo) {\n- OVS_LOG_WARN(\"vport %u does not exist any more\", vportGet->portNo);\n- } else {\n- OVS_LOG_WARN(\"vport %s does not exist any more\", vportGet->name);\n- }\n- status = STATUS_DEVICE_DOES_NOT_EXIST;\n- goto ext_info_done;\n- }\n- extInfo->dpNo = vportGet->dpNo;\n- extInfo->portNo = vport->portNo;\n- RtlCopyMemory(extInfo->macAddress, vport->currMacAddress,\n- sizeof (vport->currMacAddress));\n- RtlCopyMemory(extInfo->permMACAddress, vport->permMacAddress,\n- sizeof (vport->permMacAddress));\n- if (vport->ovsType == OVS_VPORT_TYPE_NETDEV) {\n- RtlCopyMemory(extInfo->vmMACAddress, vport->vmMacAddress,\n- sizeof (vport->vmMacAddress));\n- }\n- extInfo->nicIndex = vport->nicIndex;\n- extInfo->portId = vport->portId;\n- extInfo->type = vport->ovsType;\n- extInfo->mtu = vport->mtu;\n- /*\n- * TO be revisit XXX\n- */\n- if (vport->ovsState == OVS_STATE_NIC_CREATED) {\n- extInfo->status = OVS_EVENT_CONNECT | OVS_EVENT_LINK_DOWN;\n- } else if (vport->ovsState == OVS_STATE_CONNECTED) {\n- extInfo->status = OVS_EVENT_CONNECT | OVS_EVENT_LINK_UP;\n- } else {\n- extInfo->status = OVS_EVENT_DISCONNECT;\n- }\n- if (extInfo->type == OVS_VPORT_TYPE_NETDEV &&\n- (vport->ovsState == OVS_STATE_NIC_CREATED ||\n- vport->ovsState == OVS_STATE_CONNECTED)) {\n- doConvert = TRUE;\n- } else {\n- extInfo->vmUUID[0] = 0;\n- extInfo->vifUUID[0] = 0;\n- }\n- NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState);\n- if (doConvert) {\n- status = OvsConvertIfCountedStrToAnsiStr(&vport->portFriendlyName,\n- extInfo->name,\n- OVS_MAX_PORT_NAME_LENGTH);\n- if (status != STATUS_SUCCESS) {\n- OVS_LOG_INFO(\"Fail to convert NIC name.\");\n- extInfo->name[0] = 0;\n- }\n-\n- status = OvsConvertIfCountedStrToAnsiStr(&vport->vmName,\n- extInfo->vmUUID,\n- OVS_MAX_VM_UUID_LEN);\n- if (status != STATUS_SUCCESS) {\n- OVS_LOG_INFO(\"Fail to convert VM name.\");\n- extInfo->vmUUID[0] = 0;\n- }\n-\n- status = OvsConvertIfCountedStrToAnsiStr(&vport->nicName,\n- extInfo->vifUUID,\n- OVS_MAX_VIF_UUID_LEN);\n- if (status != STATUS_SUCCESS) {\n- OVS_LOG_INFO(\"Fail to convert nic UUID\");\n- extInfo->vifUUID[0] = 0;\n- }\n- /*\n- * for now ignore status\n- */\n- status = STATUS_SUCCESS;\n- }\n-\n-ext_info_done:\n- return status;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Command Handler for 'OVS_WIN_NETDEV_CMD_GET'.\n- * --------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsGetNetdevCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen)\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n- POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;\n- POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer;\n- NL_ERROR nlError = NL_ERROR_SUCCESS;\n- OVS_VPORT_GET vportGet;\n- OVS_VPORT_EXT_INFO info;\n-\n- static const NL_POLICY ovsNetdevPolicy[] = {\n- [OVS_WIN_NETDEV_ATTR_NAME] = { .type = NL_A_STRING,\n- .minLen = 2,\n- .maxLen = IFNAMSIZ },\n- };\n- PNL_ATTR netdevAttrs[ARRAY_SIZE(ovsNetdevPolicy)];\n-\n- /* input buffer has been validated while validating transaction dev op. */\n- ASSERT(usrParamsCtx->inputBuffer != NULL &&\n- usrParamsCtx->inputLength > sizeof *msgIn);\n-\n- if (msgOut == NULL || usrParamsCtx->outputLength < sizeof *msgOut) {\n- return STATUS_INVALID_BUFFER_SIZE;\n- }\n-\n- if (!NlAttrParse((PNL_MSG_HDR)msgIn,\n- NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN,\n- NlMsgAttrsLen((PNL_MSG_HDR)msgIn),\n- ovsNetdevPolicy, ARRAY_SIZE(ovsNetdevPolicy),\n- netdevAttrs, ARRAY_SIZE(netdevAttrs))) {\n- return STATUS_INVALID_PARAMETER;\n- }\n-\n- vportGet.portNo = 0;\n- RtlCopyMemory(&vportGet.name, NlAttrGet(netdevAttrs[OVS_VPORT_ATTR_NAME]),\n- NlAttrGetSize(netdevAttrs[OVS_VPORT_ATTR_NAME]));\n-\n- status = OvsGetExtInfoIoctl(&vportGet, &info);\n- if (status == STATUS_DEVICE_DOES_NOT_EXIST) {\n- nlError = NL_ERROR_NODEV;\n- goto cleanup;\n- }\n-\n- status = CreateNetlinkMesgForNetdev(&info, msgIn,\n- usrParamsCtx->outputBuffer, usrParamsCtx->outputLength,\n- gOvsSwitchContext->dpNo);\n- if (status == STATUS_SUCCESS) {\n- *replyLen = msgOut->nlMsg.nlmsgLen;\n- }\n-\n-cleanup:\n- if (nlError != NL_ERROR_SUCCESS) {\n- POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)\n- usrParamsCtx->outputBuffer;\n-\n- ASSERT(msgError);\n- NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);\n- ASSERT(*replyLen != 0);\n- }\n-\n- return STATUS_SUCCESS;\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Utility function to construct an OVS_MESSAGE for the specified vport. The\n- * OVS_MESSAGE contains the output of a netdev command.\n- * --------------------------------------------------------------------------\n- */\n-static NTSTATUS\n-CreateNetlinkMesgForNetdev(POVS_VPORT_EXT_INFO info,\n- POVS_MESSAGE msgIn,\n- PVOID outBuffer,\n- UINT32 outBufLen,\n- int dpIfIndex)\n-{\n- NL_BUFFER nlBuffer;\n- BOOLEAN ok;\n- PNL_MSG_HDR nlMsg;\n- UINT32 netdevFlags = 0;\n-\n- NlBufInit(&nlBuffer, outBuffer, outBufLen);\n-\n- ok = NlFillOvsMsg(&nlBuffer, msgIn->nlMsg.nlmsgType, NLM_F_MULTI,\n- msgIn->nlMsg.nlmsgSeq, msgIn->nlMsg.nlmsgPid,\n- msgIn->genlMsg.cmd, msgIn->genlMsg.version,\n- dpIfIndex);\n- if (!ok) {\n- return STATUS_INVALID_BUFFER_SIZE;\n- }\n-\n- ok = NlMsgPutTailU32(&nlBuffer, OVS_WIN_NETDEV_ATTR_PORT_NO,\n- info->portNo);\n- if (!ok) {\n- return STATUS_INVALID_BUFFER_SIZE;\n- }\n-\n- ok = NlMsgPutTailU32(&nlBuffer, OVS_WIN_NETDEV_ATTR_TYPE, info->type);\n- if (!ok) {\n- return STATUS_INVALID_BUFFER_SIZE;\n- }\n-\n- ok = NlMsgPutTailString(&nlBuffer, OVS_WIN_NETDEV_ATTR_NAME,\n- info->name);\n- if (!ok) {\n- return STATUS_INVALID_BUFFER_SIZE;\n- }\n-\n- ok = NlMsgPutTailUnspec(&nlBuffer, OVS_WIN_NETDEV_ATTR_MAC_ADDR,\n- (PCHAR)info->macAddress, sizeof (info->macAddress));\n- if (!ok) {\n- return STATUS_INVALID_BUFFER_SIZE;\n- }\n-\n- ok = NlMsgPutTailU32(&nlBuffer, OVS_WIN_NETDEV_ATTR_MTU, info->mtu);\n- if (!ok) {\n- return STATUS_INVALID_BUFFER_SIZE;\n- }\n-\n- if (info->status != OVS_EVENT_CONNECT) {\n- netdevFlags = OVS_WIN_NETDEV_IFF_UP;\n- }\n- ok = NlMsgPutTailU32(&nlBuffer, OVS_WIN_NETDEV_ATTR_IF_FLAGS,\n- netdevFlags);\n- if (!ok) {\n- return STATUS_INVALID_BUFFER_SIZE;\n- }\n-\n- /*\n- * XXX: add netdev_stats when we have the definition available in the\n- * kernel.\n- */\n-\n- nlMsg = (PNL_MSG_HDR)NlBufAt(&nlBuffer, 0, 0);\n- nlMsg->nlmsgLen = NlBufSize(&nlBuffer);\n-\n- return STATUS_SUCCESS;\n-}\n-\n-static __inline VOID\n-OvsWaitActivate(POVS_SWITCH_CONTEXT switchContext, ULONG sleepMicroSec)\n-{\n- while ((!switchContext->isActivated) &&\n- (!switchContext->isActivateFailed)) {\n- /* Wait for the switch to be active and\n- * the list of ports in OVS to be initialized. */\n- NdisMSleep(sleepMicroSec);\n- }\n-}\n-\n-static NTSTATUS\n-OvsCreateMsgFromVport(POVS_VPORT_ENTRY vport,\n- POVS_MESSAGE msgIn,\n- PVOID outBuffer,\n- UINT32 outBufLen,\n- int dpIfIndex)\n-{\n- NL_BUFFER nlBuffer;\n- OVS_VPORT_FULL_STATS vportStats;\n- BOOLEAN ok;\n- PNL_MSG_HDR nlMsg;\n-\n- NlBufInit(&nlBuffer, outBuffer, outBufLen);\n-\n- ok = NlFillOvsMsg(&nlBuffer, msgIn->nlMsg.nlmsgType, NLM_F_MULTI,\n- msgIn->nlMsg.nlmsgSeq, msgIn->nlMsg.nlmsgPid,\n- msgIn->genlMsg.cmd, msgIn->genlMsg.version,\n- dpIfIndex);\n- if (!ok) {\n- return STATUS_INVALID_BUFFER_SIZE;\n- }\n-\n- ok = NlMsgPutTailU32(&nlBuffer, OVS_VPORT_ATTR_PORT_NO, vport->portNo);\n- if (!ok) {\n- return STATUS_INVALID_BUFFER_SIZE;\n- }\n-\n- ok = NlMsgPutTailU32(&nlBuffer, OVS_VPORT_ATTR_TYPE, vport->ovsType);\n- if (!ok) {\n- return STATUS_INVALID_BUFFER_SIZE;\n- }\n-\n- ok = NlMsgPutTailString(&nlBuffer, OVS_VPORT_ATTR_NAME, vport->ovsName);\n- if (!ok) {\n- return STATUS_INVALID_BUFFER_SIZE;\n- }\n-\n- /*\n- * XXX: when we implement OVS_DP_ATTR_USER_FEATURES in datapath,\n- * we'll need to check the OVS_DP_F_VPORT_PIDS flag: if it is set,\n- * it means we have an array of pids, instead of a single pid.\n- * ATM we assume we have one pid only.\n- */\n-\n- ok = NlMsgPutTailU32(&nlBuffer, OVS_VPORT_ATTR_UPCALL_PID,\n- vport->upcallPid);\n- if (!ok) {\n- return STATUS_INVALID_BUFFER_SIZE;\n- }\n-\n- /*stats*/\n- vportStats.rxPackets = vport->stats.rxPackets;\n- vportStats.rxBytes = vport->stats.rxBytes;\n- vportStats.txPackets = vport->stats.txPackets;\n- vportStats.txBytes = vport->stats.txBytes;\n- vportStats.rxErrors = vport->errStats.rxErrors;\n- vportStats.txErrors = vport->errStats.txErrors;\n- vportStats.rxDropped = vport->errStats.rxDropped;\n- vportStats.txDropped = vport->errStats.txDropped;\n-\n- ok = NlMsgPutTailUnspec(&nlBuffer, OVS_VPORT_ATTR_STATS,\n- (PCHAR)&vportStats,\n- sizeof(OVS_VPORT_FULL_STATS));\n- if (!ok) {\n- return STATUS_INVALID_BUFFER_SIZE;\n- }\n-\n- /*\n- * XXX: when vxlan udp dest port becomes configurable, we will also need\n- * to add vport options\n- */\n-\n- nlMsg = (PNL_MSG_HDR)NlBufAt(&nlBuffer, 0, 0);\n- nlMsg->nlmsgLen = NlBufSize(&nlBuffer);\n-\n- return STATUS_SUCCESS;\n-}\n-\n-static NTSTATUS\n-OvsGetVportDumpNext(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen)\n-{\n- POVS_MESSAGE msgIn;\n- POVS_OPEN_INSTANCE instance =\n- (POVS_OPEN_INSTANCE)usrParamsCtx->ovsInstance;\n- LOCK_STATE_EX lockState;\n- UINT32 i = OVS_MAX_VPORT_ARRAY_SIZE;\n-\n- /*\n- * XXX: this function shares some code with other dump command(s).\n- * In the future, we will need to refactor the dump functions\n- */\n-\n- ASSERT(usrParamsCtx->devOp == OVS_READ_DEV_OP);\n-\n- if (instance->dumpState.ovsMsg == NULL) {\n- ASSERT(FALSE);\n- return STATUS_INVALID_DEVICE_STATE;\n- }\n-\n- /* Output buffer has been validated while validating read dev op. */\n- ASSERT(usrParamsCtx->outputBuffer != NULL);\n-\n- msgIn = instance->dumpState.ovsMsg;\n-\n- /*\n- * XXX: when we implement OVS_DP_ATTR_USER_FEATURES in datapath,\n- * we'll need to check the OVS_DP_F_VPORT_PIDS flag: if it is set,\n- * it means we have an array of pids, instead of a single pid.\n- * ATM we assume we have one pid only.\n- */\n- NdisAcquireRWLockRead(gOvsSwitchContext->dispatchLock, &lockState, 0);\n-\n- if (gOvsSwitchContext->numHvVports > 0 ||\n- gOvsSwitchContext->numNonHvVports > 0) {\n- /* inBucket: the bucket, used for lookup */\n- UINT32 inBucket = instance->dumpState.index[0];\n- /* inIndex: index within the given bucket, used for lookup */\n- UINT32 inIndex = instance->dumpState.index[1];\n- /* the bucket to be used for the next dump operation */\n- UINT32 outBucket = 0;\n- /* the index within the outBucket to be used for the next dump */\n- UINT32 outIndex = 0;\n-\n- for (i = inBucket; i < OVS_MAX_VPORT_ARRAY_SIZE; i++) {\n- PLIST_ENTRY head, link;\n- head = &(gOvsSwitchContext->portNoHashArray[i]);\n- POVS_VPORT_ENTRY vport = NULL;\n-\n- outIndex = 0;\n- LIST_FORALL(head, link) {\n-\n- /*\n- * if one or more dumps were previously done on this same bucket,\n- * inIndex will be > 0, so we'll need to reply with the\n- * inIndex + 1 vport from the bucket.\n- */\n- if (outIndex >= inIndex) {\n- vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, portNoLink);\n-\n- ASSERT(vport->portNo != OVS_DPPORT_NUMBER_INVALID);\n- OvsCreateMsgFromVport(vport, msgIn,\n- usrParamsCtx->outputBuffer,\n- usrParamsCtx->outputLength,\n- gOvsSwitchContext->dpNo);\n- ++outIndex;\n- break;\n- }\n-\n- ++outIndex;\n- }\n-\n- if (vport) {\n- break;\n- }\n-\n- /*\n- * if no vport was found above, check the next bucket, beginning\n- * with the first (i.e. index 0) elem from within that bucket\n- */\n- inIndex = 0;\n- }\n-\n- outBucket = i;\n-\n- /* XXX: what about NLMSG_DONE (as msg type)? */\n- instance->dumpState.index[0] = outBucket;\n- instance->dumpState.index[1] = outIndex;\n- }\n-\n- NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState);\n-\n- /* if i < OVS_MAX_VPORT_ARRAY_SIZE => vport was found */\n- if (i < OVS_MAX_VPORT_ARRAY_SIZE) {\n- POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer;\n- *replyLen = msgOut->nlMsg.nlmsgLen;\n- } else {\n- /*\n- * if i >= OVS_MAX_VPORT_ARRAY_SIZE => vport was not found =>\n- * it's dump done\n- */\n- *replyLen = 0;\n- /* Free up the dump state, since there's no more data to continue. */\n- FreeUserDumpState(instance);\n- }\n-\n- return STATUS_SUCCESS;\n-}\n-\n-static NTSTATUS\n-OvsGetVport(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen)\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n- LOCK_STATE_EX lockState;\n-\n- POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;\n- POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer;\n- POVS_VPORT_ENTRY vport = NULL;\n- NL_ERROR nlError = NL_ERROR_SUCCESS;\n- PCHAR portName = NULL;\n- UINT32 portNameLen = 0;\n- UINT32 portNumber = OVS_DPPORT_NUMBER_INVALID;\n-\n- static const NL_POLICY ovsVportPolicy[] = {\n- [OVS_VPORT_ATTR_PORT_NO] = { .type = NL_A_U32, .optional = TRUE },\n- [OVS_VPORT_ATTR_NAME] = { .type = NL_A_STRING,\n- .minLen = 2,\n- .maxLen = IFNAMSIZ,\n- .optional = TRUE},\n- };\n- PNL_ATTR vportAttrs[ARRAY_SIZE(ovsVportPolicy)];\n-\n- /* input buffer has been validated while validating write dev op. */\n- ASSERT(usrParamsCtx->inputBuffer != NULL);\n-\n- if (!NlAttrParse((PNL_MSG_HDR)msgIn,\n- NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN,\n- NlMsgAttrsLen((PNL_MSG_HDR)msgIn),\n- ovsVportPolicy, ARRAY_SIZE(ovsVportPolicy),\n- vportAttrs, ARRAY_SIZE(vportAttrs))) {\n- return STATUS_INVALID_PARAMETER;\n- }\n-\n- /* Output buffer has been validated while validating transact dev op. */\n- ASSERT(msgOut != NULL && usrParamsCtx->outputLength >= sizeof *msgOut);\n-\n- NdisAcquireRWLockRead(gOvsSwitchContext->dispatchLock, &lockState, 0);\n- if (vportAttrs[OVS_VPORT_ATTR_NAME] != NULL) {\n- portName = NlAttrGet(vportAttrs[OVS_VPORT_ATTR_NAME]);\n- portNameLen = NlAttrGetSize(vportAttrs[OVS_VPORT_ATTR_NAME]);\n-\n- /* the port name is expected to be null-terminated */\n- ASSERT(portName[portNameLen - 1] == '\\0');\n-\n- vport = OvsFindVportByOvsName(gOvsSwitchContext, portName);\n- } else if (vportAttrs[OVS_VPORT_ATTR_PORT_NO] != NULL) {\n- portNumber = NlAttrGetU32(vportAttrs[OVS_VPORT_ATTR_PORT_NO]);\n-\n- vport = OvsFindVportByPortNo(gOvsSwitchContext, portNumber);\n- } else {\n- nlError = NL_ERROR_INVAL;\n- NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState);\n- goto Cleanup;\n- }\n-\n- if (!vport) {\n- nlError = NL_ERROR_NODEV;\n- NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState);\n- goto Cleanup;\n- }\n-\n- status = OvsCreateMsgFromVport(vport, msgIn, usrParamsCtx->outputBuffer,\n- usrParamsCtx->outputLength,\n- gOvsSwitchContext->dpNo);\n- NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState);\n-\n- *replyLen = msgOut->nlMsg.nlmsgLen;\n-\n-Cleanup:\n- if (nlError != NL_ERROR_SUCCESS) {\n- POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)\n- usrParamsCtx->outputBuffer;\n-\n- ASSERT(msgError);\n- NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);\n- ASSERT(*replyLen != 0);\n- }\n-\n- return STATUS_SUCCESS;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Command Handler for 'OVS_VPORT_CMD_GET'.\n- *\n- * The function handles the initial call to setup the dump state, as well as\n- * subsequent calls to continue dumping data.\n- * --------------------------------------------------------------------------\n-*/\n-NTSTATUS\n-OvsGetVportCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen)\n-{\n- *replyLen = 0;\n-\n- switch (usrParamsCtx->devOp) {\n- case OVS_WRITE_DEV_OP:\n- return OvsSetupDumpStart(usrParamsCtx);\n-\n- case OVS_READ_DEV_OP:\n- return OvsGetVportDumpNext(usrParamsCtx, replyLen);\n-\n- case OVS_TRANSACTION_DEV_OP:\n- return OvsGetVport(usrParamsCtx, replyLen);\n-\n- default:\n- return STATUS_INVALID_DEVICE_REQUEST;\n- }\n-\n-}\n-\n-static UINT32\n-OvsComputeVportNo(POVS_SWITCH_CONTEXT switchContext)\n-{\n- /* we are not allowed to create the port OVS_DPPORT_NUMBER_LOCAL */\n- for (ULONG i = OVS_DPPORT_NUMBER_LOCAL + 1; i < MAXUINT16; ++i) {\n- POVS_VPORT_ENTRY vport;\n-\n- vport = OvsFindVportByPortNo(switchContext, i);\n- if (!vport) {\n- return i;\n- }\n- }\n-\n- return OVS_DPPORT_NUMBER_INVALID;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Command Handler for 'OVS_VPORT_CMD_NEW'.\n- * --------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsNewVportCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen)\n-{\n- NDIS_STATUS status = STATUS_SUCCESS;\n- LOCK_STATE_EX lockState;\n-\n- NL_ERROR nlError = NL_ERROR_SUCCESS;\n- POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;\n- POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer;\n- POVS_VPORT_ENTRY vport = NULL;\n- PCHAR portName;\n- ULONG portNameLen;\n- UINT32 portType;\n- BOOLEAN vportAllocated = FALSE, vportInitialized = FALSE;\n-\n- static const NL_POLICY ovsVportPolicy[] = {\n- [OVS_VPORT_ATTR_PORT_NO] = { .type = NL_A_U32, .optional = TRUE },\n- [OVS_VPORT_ATTR_TYPE] = { .type = NL_A_U32, .optional = FALSE },\n- [OVS_VPORT_ATTR_NAME] = { .type = NL_A_STRING, .maxLen = IFNAMSIZ,\n- .optional = FALSE},\n- [OVS_VPORT_ATTR_UPCALL_PID] = { .type = NL_A_UNSPEC,\n- .optional = FALSE },\n- [OVS_VPORT_ATTR_OPTIONS] = { .type = NL_A_NESTED, .optional = TRUE },\n- };\n-\n- PNL_ATTR vportAttrs[ARRAY_SIZE(ovsVportPolicy)];\n-\n- /* input buffer has been validated while validating write dev op. */\n- ASSERT(usrParamsCtx->inputBuffer != NULL);\n-\n- /* Output buffer has been validated while validating transact dev op. */\n- ASSERT(msgOut != NULL && usrParamsCtx->outputLength >= sizeof *msgOut);\n-\n- if (!NlAttrParse((PNL_MSG_HDR)msgIn,\n- NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN,\n- NlMsgAttrsLen((PNL_MSG_HDR)msgIn),\n- ovsVportPolicy, ARRAY_SIZE(ovsVportPolicy),\n- vportAttrs, ARRAY_SIZE(vportAttrs))) {\n- return STATUS_INVALID_PARAMETER;\n- }\n-\n- portName = NlAttrGet(vportAttrs[OVS_VPORT_ATTR_NAME]);\n- portNameLen = NlAttrGetSize(vportAttrs[OVS_VPORT_ATTR_NAME]);\n- portType = NlAttrGetU32(vportAttrs[OVS_VPORT_ATTR_TYPE]);\n-\n- /* we are expecting null terminated strings to be passed */\n- ASSERT(portName[portNameLen - 1] == '\\0');\n-\n- NdisAcquireRWLockWrite(gOvsSwitchContext->dispatchLock, &lockState, 0);\n-\n- vport = OvsFindVportByOvsName(gOvsSwitchContext, portName);\n- if (vport) {\n- nlError = NL_ERROR_EXIST;\n- goto Cleanup;\n- }\n-\n- if (portType == OVS_VPORT_TYPE_NETDEV ||\n- portType == OVS_VPORT_TYPE_INTERNAL) {\n- /* External and internal ports can also be looked up like VIF ports. */\n- vport = OvsFindVportByHvNameA(gOvsSwitchContext, portName);\n- } else {\n- ASSERT(OvsIsTunnelVportType(portType));\n-\n- vport = (POVS_VPORT_ENTRY)OvsAllocateVport();\n- if (vport == NULL) {\n- nlError = NL_ERROR_NOMEM;\n- goto Cleanup;\n- }\n- vportAllocated = TRUE;\n-\n- if (OvsIsTunnelVportType(portType)) {\n- UINT16 transportPortDest = 0;\n- UINT8 nwProto = IPPROTO_NONE;\n- POVS_VPORT_ENTRY dupVport;\n-\n- switch (portType) {\n- case OVS_VPORT_TYPE_GRE:\n- nwProto = IPPROTO_GRE;\n- break;\n- case OVS_VPORT_TYPE_VXLAN:\n- transportPortDest = VXLAN_UDP_PORT;\n- nwProto = IPPROTO_UDP;\n- break;\n- case OVS_VPORT_TYPE_GENEVE:\n- transportPortDest = GENEVE_UDP_PORT;\n- break;\n- default:\n- nlError = NL_ERROR_INVAL;\n- goto Cleanup;\n- }\n-\n- if (vportAttrs[OVS_VPORT_ATTR_OPTIONS]) {\n- PNL_ATTR attr = NlAttrFindNested(vportAttrs[OVS_VPORT_ATTR_OPTIONS],\n- OVS_TUNNEL_ATTR_DST_PORT);\n- if (attr) {\n- transportPortDest = NlAttrGetU16(attr);\n- }\n- }\n-\n- /*\n- * We don't allow two tunnel ports on identical N/W protocol and\n- * L4 port number. This is applicable even if the two ports are of\n- * different tunneling types.\n- */\n- dupVport =\n- OvsFindTunnelVportByDstPortAndNWProto(gOvsSwitchContext,\n- transportPortDest,\n- nwProto);\n- if (dupVport) {\n- OVS_LOG_ERROR(\"Vport for N/W proto and port already exists,\"\n- \" type: %u, dst port: %u, name: %s\", dupVport->ovsType,\n- transportPortDest, dupVport->ovsName);\n- goto Cleanup;\n- }\n-\n- status = OvsInitTunnelVport(usrParamsCtx,\n- vport,\n- portType,\n- transportPortDest);\n-\n- nlError = NlMapStatusToNlErr(status);\n- }\n-\n- vportInitialized = TRUE;\n-\n- if (nlError == NL_ERROR_SUCCESS) {\n- vport->ovsState = OVS_STATE_CONNECTED;\n- vport->nicState = NdisSwitchNicStateConnected;\n-\n- /*\n- * Allow the vport to be deleted, because there is no\n- * corresponding hyper-v switch part.\n- */\n- vport->isAbsentOnHv = TRUE;\n- } else {\n- goto Cleanup;\n- }\n- }\n-\n- if (!vport) {\n- nlError = NL_ERROR_INVAL;\n- goto Cleanup;\n- }\n- if (vport->portNo != OVS_DPPORT_NUMBER_INVALID) {\n- nlError = NL_ERROR_EXIST;\n- goto Cleanup;\n- }\n-\n- if (vportAttrs[OVS_VPORT_ATTR_PORT_NO] != NULL) {\n- /*\n- * XXX: when we implement the limit for ovs port number to be\n- * MAXUINT16, we'll need to check the port number received from the\n- * userspace.\n- */\n- vport->portNo = NlAttrGetU32(vportAttrs[OVS_VPORT_ATTR_PORT_NO]);\n- } else {\n- vport->portNo = OvsComputeVportNo(gOvsSwitchContext);\n- if (vport->portNo == OVS_DPPORT_NUMBER_INVALID) {\n- nlError = NL_ERROR_NOMEM;\n- goto Cleanup;\n- }\n- }\n-\n- /* The ovs port name must be uninitialized. */\n- ASSERT(vport->ovsName[0] == '\\0');\n- ASSERT(portNameLen <= OVS_MAX_PORT_NAME_LENGTH);\n-\n- RtlCopyMemory(vport->ovsName, portName, portNameLen);\n- /* if we don't have options, then vport->portOptions will be NULL */\n- vport->portOptions = vportAttrs[OVS_VPORT_ATTR_OPTIONS];\n-\n- /*\n- * XXX: when we implement OVS_DP_ATTR_USER_FEATURES in datapath,\n- * we'll need to check the OVS_DP_F_VPORT_PIDS flag: if it is set,\n- * it means we have an array of pids, instead of a single pid.\n- * ATM we assume we have one pid only.\n- */\n- vport->upcallPid = NlAttrGetU32(vportAttrs[OVS_VPORT_ATTR_UPCALL_PID]);\n-\n- status = InitOvsVportCommon(gOvsSwitchContext, vport);\n- ASSERT(status == STATUS_SUCCESS);\n-\n- status = OvsCreateMsgFromVport(vport, msgIn, usrParamsCtx->outputBuffer,\n- usrParamsCtx->outputLength,\n- gOvsSwitchContext->dpNo);\n-\n- *replyLen = msgOut->nlMsg.nlmsgLen;\n- OVS_LOG_INFO(\"Created new vport, name: %s, type: %u\", vport->ovsName,\n- vport->ovsType);\n-\n-Cleanup:\n- NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState);\n-\n- if ((nlError != NL_ERROR_SUCCESS) && (nlError != NL_ERROR_PENDING)) {\n- POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)\n- usrParamsCtx->outputBuffer;\n-\n- if (vport && vportAllocated == TRUE) {\n- if (vportInitialized == TRUE) {\n- if (OvsIsTunnelVportType(portType)) {\n- switch (vport->ovsType) {\n- case OVS_VPORT_TYPE_VXLAN:\n- OvsCleanupVxlanTunnel(NULL, vport, NULL, NULL);\n- break;\n- case OVS_VPORT_TYPE_GENEVE:\n- OvsCleanupGeneveTunnel(vport);\n- break;\n- default:\n- ASSERT(!\"Invalid tunnel port type\");\n- }\n- }\n- }\n- OvsFreeMemoryWithTag(vport, OVS_VPORT_POOL_TAG);\n- }\n-\n- ASSERT(msgError);\n- NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);\n- ASSERT(*replyLen != 0);\n- }\n-\n- return (status == STATUS_PENDING) ? STATUS_PENDING : STATUS_SUCCESS;\n-}\n-\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Command Handler for 'OVS_VPORT_CMD_SET'.\n- * --------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsSetVportCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen)\n-{\n- NDIS_STATUS status = STATUS_SUCCESS;\n- LOCK_STATE_EX lockState;\n-\n- POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;\n- POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer;\n- POVS_VPORT_ENTRY vport = NULL;\n- NL_ERROR nlError = NL_ERROR_SUCCESS;\n-\n- static const NL_POLICY ovsVportPolicy[] = {\n- [OVS_VPORT_ATTR_PORT_NO] = { .type = NL_A_U32, .optional = TRUE },\n- [OVS_VPORT_ATTR_TYPE] = { .type = NL_A_U32, .optional = TRUE },\n- [OVS_VPORT_ATTR_NAME] = { .type = NL_A_STRING, .maxLen = IFNAMSIZ,\n- .optional = TRUE },\n- [OVS_VPORT_ATTR_UPCALL_PID] = { .type = NL_A_UNSPEC,\n- .optional = TRUE },\n- [OVS_VPORT_ATTR_STATS] = { .type = NL_A_UNSPEC,\n- .minLen = sizeof(OVS_VPORT_FULL_STATS),\n- .maxLen = sizeof(OVS_VPORT_FULL_STATS),\n- .optional = TRUE },\n- [OVS_VPORT_ATTR_OPTIONS] = { .type = NL_A_NESTED, .optional = TRUE },\n- };\n- PNL_ATTR vportAttrs[ARRAY_SIZE(ovsVportPolicy)];\n-\n- ASSERT(usrParamsCtx->inputBuffer != NULL);\n-\n- if (!NlAttrParse((PNL_MSG_HDR)msgIn,\n- NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN,\n- NlMsgAttrsLen((PNL_MSG_HDR)msgIn),\n- ovsVportPolicy, ARRAY_SIZE(ovsVportPolicy),\n- vportAttrs, ARRAY_SIZE(vportAttrs))) {\n- return STATUS_INVALID_PARAMETER;\n- }\n-\n- /* Output buffer has been validated while validating transact dev op. */\n- ASSERT(msgOut != NULL && usrParamsCtx->outputLength >= sizeof *msgOut);\n-\n- NdisAcquireRWLockWrite(gOvsSwitchContext->dispatchLock, &lockState, 0);\n- if (vportAttrs[OVS_VPORT_ATTR_NAME] != NULL) {\n- PSTR portName = NlAttrGet(vportAttrs[OVS_VPORT_ATTR_NAME]);\n-#ifdef DBG\n- UINT32 portNameLen = NlAttrGetSize(vportAttrs[OVS_VPORT_ATTR_NAME]);\n-#endif\n- /* the port name is expected to be null-terminated */\n- ASSERT(portName[portNameLen - 1] == '\\0');\n-\n- vport = OvsFindVportByOvsName(gOvsSwitchContext, portName);\n- } else if (vportAttrs[OVS_VPORT_ATTR_PORT_NO] != NULL) {\n- vport = OvsFindVportByPortNo(gOvsSwitchContext,\n- NlAttrGetU32(vportAttrs[OVS_VPORT_ATTR_PORT_NO]));\n- }\n-\n- if (!vport) {\n- nlError = NL_ERROR_NODEV;\n- goto Cleanup;\n- }\n-\n- /*\n- * XXX: when we implement OVS_DP_ATTR_USER_FEATURES in datapath,\n- * we'll need to check the OVS_DP_F_VPORT_PIDS flag: if it is set,\n- * it means we have an array of pids, instead of a single pid.\n- * Currently, we support only one pid.\n- */\n- if (vportAttrs[OVS_VPORT_ATTR_UPCALL_PID]) {\n- vport->upcallPid = NlAttrGetU32(vportAttrs[OVS_VPORT_ATTR_UPCALL_PID]);\n- }\n-\n- if (vportAttrs[OVS_VPORT_ATTR_TYPE]) {\n- OVS_VPORT_TYPE type = NlAttrGetU32(vportAttrs[OVS_VPORT_ATTR_TYPE]);\n- if (type != vport->ovsType) {\n- nlError = NL_ERROR_INVAL;\n- goto Cleanup;\n- }\n- }\n-\n- if (vportAttrs[OVS_VPORT_ATTR_OPTIONS]) {\n- OVS_LOG_ERROR(\"Vport options not supported\");\n- nlError = NL_ERROR_NOTSUPP;\n- goto Cleanup;\n- }\n-\n- status = OvsCreateMsgFromVport(vport, msgIn, usrParamsCtx->outputBuffer,\n- usrParamsCtx->outputLength,\n- gOvsSwitchContext->dpNo);\n-\n- *replyLen = msgOut->nlMsg.nlmsgLen;\n-\n-Cleanup:\n- NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState);\n-\n- if (nlError != NL_ERROR_SUCCESS) {\n- POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)\n- usrParamsCtx->outputBuffer;\n-\n- ASSERT(msgError);\n- NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);\n- ASSERT(*replyLen != 0);\n- }\n-\n- return STATUS_SUCCESS;\n-}\n-\n-/*\n- * --------------------------------------------------------------------------\n- * Command Handler for 'OVS_VPORT_CMD_DEL'.\n- * --------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsDeleteVportCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,\n- UINT32 *replyLen)\n-{\n- NDIS_STATUS status = STATUS_SUCCESS;\n- LOCK_STATE_EX lockState;\n-\n- POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;\n- POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer;\n- POVS_VPORT_ENTRY vport = NULL;\n- NL_ERROR nlError = NL_ERROR_SUCCESS;\n- PSTR portName = NULL;\n- UINT32 portNameLen = 0;\n-\n- static const NL_POLICY ovsVportPolicy[] = {\n- [OVS_VPORT_ATTR_PORT_NO] = { .type = NL_A_U32, .optional = TRUE },\n- [OVS_VPORT_ATTR_NAME] = { .type = NL_A_STRING, .maxLen = IFNAMSIZ,\n- .optional = TRUE },\n- };\n- PNL_ATTR vportAttrs[ARRAY_SIZE(ovsVportPolicy)];\n-\n- ASSERT(usrParamsCtx->inputBuffer != NULL);\n-\n- if (!NlAttrParse((PNL_MSG_HDR)msgIn,\n- NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN,\n- NlMsgAttrsLen((PNL_MSG_HDR)msgIn),\n- ovsVportPolicy, ARRAY_SIZE(ovsVportPolicy),\n- vportAttrs, ARRAY_SIZE(vportAttrs))) {\n- return STATUS_INVALID_PARAMETER;\n- }\n-\n- /* Output buffer has been validated while validating transact dev op. */\n- ASSERT(msgOut != NULL && usrParamsCtx->outputLength >= sizeof *msgOut);\n-\n- NdisAcquireRWLockWrite(gOvsSwitchContext->dispatchLock, &lockState, 0);\n- if (vportAttrs[OVS_VPORT_ATTR_NAME] != NULL) {\n- portName = NlAttrGet(vportAttrs[OVS_VPORT_ATTR_NAME]);\n- portNameLen = NlAttrGetSize(vportAttrs[OVS_VPORT_ATTR_NAME]);\n-\n- /* the port name is expected to be null-terminated */\n- ASSERT(portName[portNameLen - 1] == '\\0');\n-\n- vport = OvsFindVportByOvsName(gOvsSwitchContext, portName);\n- }\n- else if (vportAttrs[OVS_VPORT_ATTR_PORT_NO] != NULL) {\n- vport = OvsFindVportByPortNo(gOvsSwitchContext,\n- NlAttrGetU32(vportAttrs[OVS_VPORT_ATTR_PORT_NO]));\n- }\n-\n- if (!vport) {\n- nlError = NL_ERROR_NODEV;\n- goto Cleanup;\n- }\n-\n- status = OvsCreateMsgFromVport(vport, msgIn, usrParamsCtx->outputBuffer,\n- usrParamsCtx->outputLength,\n- gOvsSwitchContext->dpNo);\n-\n- *replyLen = msgOut->nlMsg.nlmsgLen;\n-\n- /*\n- * Mark the port as deleted from OVS userspace. If the port does not exist\n- * on the Hyper-V switch, it gets deallocated. Otherwise, it stays.\n- */\n- status = OvsRemoveAndDeleteVport(usrParamsCtx,\n- gOvsSwitchContext,\n- vport,\n- FALSE,\n- TRUE);\n- if (status) {\n- nlError = NlMapStatusToNlErr(status);\n- }\n-\n-Cleanup:\n- NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState);\n-\n- if ((nlError != NL_ERROR_SUCCESS) && (nlError != NL_ERROR_PENDING)) {\n- POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)\n- usrParamsCtx->outputBuffer;\n-\n- ASSERT(msgError);\n- NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);\n- ASSERT(*replyLen != 0);\n- }\n-\n- return (status == STATUS_PENDING) ? STATUS_PENDING : STATUS_SUCCESS;\n-}\n-\n-static VOID\n-OvsTunnelVportPendingRemove(PVOID context,\n- NTSTATUS status,\n- UINT32 *replyLen)\n-{\n- POVS_TUNFLT_INIT_CONTEXT tunnelContext =\n- (POVS_TUNFLT_INIT_CONTEXT) context;\n- POVS_SWITCH_CONTEXT switchContext = tunnelContext->switchContext;\n- POVS_VPORT_ENTRY vport = tunnelContext->vport;\n- POVS_MESSAGE msgIn = (POVS_MESSAGE)tunnelContext->inputBuffer;\n- POVS_MESSAGE msgOut = (POVS_MESSAGE)tunnelContext->outputBuffer;\n- NL_ERROR nlError = NlMapStatusToNlErr(status);\n- LOCK_STATE_EX lockState;\n-\n- NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0);\n-\n- if (msgIn && msgOut) {\n- /* Check the received status to reply to the caller. */\n- if (STATUS_SUCCESS == status) {\n- OvsCreateMsgFromVport(vport,\n- msgIn,\n- msgOut,\n- tunnelContext->outputLength,\n- switchContext->dpNo);\n-\n- *replyLen = msgOut->nlMsg.nlmsgLen;\n- } else {\n- POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)msgOut;\n- ASSERT(msgError);\n- NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);\n- ASSERT(*replyLen != 0);\n- }\n- }\n-\n- ASSERT(vport->isAbsentOnHv == TRUE);\n- ASSERT(vport->portNo != OVS_DPPORT_NUMBER_INVALID);\n-\n- /* Remove the port from the relevant lists. */\n- switchContext->numNonHvVports--;\n- RemoveEntryList(&vport->ovsNameLink);\n- RemoveEntryList(&vport->portNoLink);\n- RemoveEntryList(&vport->tunnelVportLink);\n-\n- if (vport->priv) {\n- OvsFreeMemoryWithTag(vport->priv, OVS_VXLAN_POOL_TAG);\n- vport->priv = NULL;\n- }\n-\n- OvsFreeMemoryWithTag(vport, OVS_VPORT_POOL_TAG);\n-\n- NdisReleaseRWLock(switchContext->dispatchLock, &lockState);\n-}\n-\n-static VOID\n-OvsTunnelVportPendingInit(PVOID context,\n- NTSTATUS status,\n- UINT32 *replyLen)\n-{\n- POVS_TUNFLT_INIT_CONTEXT tunnelContext =\n- (POVS_TUNFLT_INIT_CONTEXT) context;\n- POVS_VPORT_ENTRY vport = tunnelContext->vport;\n- POVS_MESSAGE msgIn = (POVS_MESSAGE)tunnelContext->inputBuffer;\n- POVS_MESSAGE msgOut = (POVS_MESSAGE)tunnelContext->outputBuffer;\n- PCHAR portName;\n- ULONG portNameLen = 0;\n- UINT32 portType = 0;\n- NL_ERROR nlError = NL_ERROR_SUCCESS;\n- BOOLEAN error = TRUE;\n-\n- do {\n- if (!NT_SUCCESS(status)) {\n- nlError = NlMapStatusToNlErr(status);\n- break;\n- }\n-\n- static const NL_POLICY ovsVportPolicy[] = {\n- [OVS_VPORT_ATTR_PORT_NO] = { .type = NL_A_U32, .optional = TRUE },\n- [OVS_VPORT_ATTR_TYPE] = { .type = NL_A_U32, .optional = FALSE },\n- [OVS_VPORT_ATTR_NAME] = { .type = NL_A_STRING, .maxLen = IFNAMSIZ,\n- .optional = FALSE },\n- [OVS_VPORT_ATTR_UPCALL_PID] = { .type = NL_A_UNSPEC,\n- .optional = FALSE },\n- [OVS_VPORT_ATTR_OPTIONS] = { .type = NL_A_NESTED, .optional = TRUE },\n- };\n-\n- PNL_ATTR vportAttrs[ARRAY_SIZE(ovsVportPolicy)];\n-\n- /* input buffer has been validated while validating write dev op. */\n- ASSERT(msgIn != NULL);\n-\n- /* Output buffer has been validated while validating transact dev op. */\n- ASSERT(msgOut != NULL && tunnelContext->outputLength >= sizeof *msgOut);\n-\n- if (!NlAttrParse((PNL_MSG_HDR)msgIn,\n- NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN,\n- NlMsgAttrsLen((PNL_MSG_HDR)msgIn),\n- ovsVportPolicy, ARRAY_SIZE(ovsVportPolicy),\n- vportAttrs, ARRAY_SIZE(vportAttrs))) {\n- nlError = NL_ERROR_INVAL;\n- break;\n- }\n-\n- portName = NlAttrGet(vportAttrs[OVS_VPORT_ATTR_NAME]);\n- portNameLen = NlAttrGetSize(vportAttrs[OVS_VPORT_ATTR_NAME]);\n- portType = NlAttrGetU32(vportAttrs[OVS_VPORT_ATTR_TYPE]);\n-\n- if (vport->portNo != OVS_DPPORT_NUMBER_INVALID) {\n- nlError = NL_ERROR_EXIST;\n- break;\n- }\n-\n- vport->ovsState = OVS_STATE_CONNECTED;\n- vport->nicState = NdisSwitchNicStateConnected;\n-\n- /*\n- * Allow the vport to be deleted, because there is no\n- * corresponding hyper-v switch part.\n- */\n- vport->isAbsentOnHv = TRUE;\n-\n- if (vportAttrs[OVS_VPORT_ATTR_PORT_NO] != NULL) {\n- /*\n- * XXX: when we implement the limit for OVS port number to be\n- * MAXUINT16, we'll need to check the port number received from the\n- * userspace.\n- */\n- vport->portNo =\n- NlAttrGetU32(vportAttrs[OVS_VPORT_ATTR_PORT_NO]);\n- } else {\n- vport->portNo =\n- OvsComputeVportNo(gOvsSwitchContext);\n- if (vport->portNo == OVS_DPPORT_NUMBER_INVALID) {\n- nlError = NL_ERROR_NOMEM;\n- break;\n- }\n- }\n-\n- /* The ovs port name must be uninitialized. */\n- ASSERT(vport->ovsName[0] == '\\0');\n- ASSERT(portNameLen <= OVS_MAX_PORT_NAME_LENGTH);\n-\n- RtlCopyMemory(vport->ovsName, portName, portNameLen);\n- /* if we don't have options, then vport->portOptions will be NULL */\n- vport->portOptions = vportAttrs[OVS_VPORT_ATTR_OPTIONS];\n-\n- /*\n- * XXX: when we implement OVS_DP_ATTR_USER_FEATURES in datapath,\n- * we'll need to check the OVS_DP_F_VPORT_PIDS flag: if it is set,\n- * it means we have an array of pids, instead of a single pid.\n- * ATM we assume we have one pid only.\n- */\n- vport->upcallPid =\n- NlAttrGetU32(vportAttrs[OVS_VPORT_ATTR_UPCALL_PID]);\n-\n- status = InitOvsVportCommon(gOvsSwitchContext, vport);\n- ASSERT(status == STATUS_SUCCESS);\n-\n- OvsCreateMsgFromVport(vport,\n- msgIn,\n- msgOut,\n- tunnelContext->outputLength,\n- gOvsSwitchContext->dpNo);\n-\n- *replyLen = msgOut->nlMsg.nlmsgLen;\n-\n- error = FALSE;\n- } while (error);\n-\n- if (error) {\n- POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)msgOut;\n-\n- OvsCleanupVxlanTunnel(NULL, vport, NULL, NULL);\n- OvsFreeMemory(vport);\n-\n- ASSERT(msgError);\n- NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);\n- ASSERT(*replyLen != 0);\n- }\n-}\n-\n-_Use_decl_annotations_\n-static VOID\n-OvsBindVportWithIpHelper(POVS_VPORT_ENTRY vport,\n- POVS_SWITCH_CONTEXT switchContext)\n-{\n- OVS_LOG_TRACE(\"OvsBindVportWithIpHelper: %d\", vport->portNo);\n- ASSERT(switchContext->ipHelperBoundVportNo == 0);\n- switchContext->ipHelperBoundVportNo = vport->portNo;\n- OvsInternalAdapterUp(vport->portNo, &vport->netCfgInstanceId);\n-}\n-\n-_Use_decl_annotations_\n-static VOID\n-OvsUnBindVportWithIpHelper(POVS_VPORT_ENTRY vport,\n- POVS_SWITCH_CONTEXT switchContext)\n-{\n- OVS_LOG_TRACE(\"OvsUnBindVportWithIpHelper: %d\", vport->portNo);\n- ASSERT(switchContext->ipHelperBoundVportNo == vport->portNo);\n- switchContext->ipHelperBoundVportNo = 0;\n- OvsInternalAdapterDown(vport->portNo, vport->netCfgInstanceId);\n-}\ndiff --git a/datapath-windows/ovsext/Vport.h b/datapath-windows/ovsext/Vport.h\ndeleted file mode 100644\nindex a399d6cf2..000000000\n--- a/datapath-windows/ovsext/Vport.h\n+++ /dev/null\n@@ -1,275 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#ifndef __VPORT_H_\n-#define __VPORT_H_ 1\n-\n-#include \"Gre.h\"\n-#include \"Switch.h\"\n-#include \"VxLan.h\"\n-#include \"Geneve.h\"\n-\n-#define OVS_MAX_DPPORTS MAXUINT16\n-#define OVS_DPPORT_NUMBER_INVALID OVS_MAX_DPPORTS\n-/*\n- * The local port (0) is a reserved port, that is not allowed to be\n- * created by the netlink command vport add. On linux, this port is created\n- * at netlink command datapath new. However, on windows, we do not need to\n- * create it, and more, we shouldn't. The userspace attempts to create two\n- * internal vports, the LOCAL port (0) and the internal port (with any other\n- * port number). The non-LOCAL internal port is used in the userspace when it\n- * requests the internal port.\n- */\n-#define OVS_DPPORT_NUMBER_LOCAL 0\n-\n-/*\n- * A Vport, or Virtual Port, is a port on the OVS. It can be one of the\n- * following types. Some of the Vports are \"real\" ports on the hyper-v switch,\n- * and some are not:\n- * - VIF port (VM's NIC)\n- * - External Adapters (physical NIC)\n- * - Internal Adapter (Virtual adapter exposed on the host).\n- * - Tunnel ports created by OVS userspace.\n- */\n-\n-typedef enum {\n- OVS_STATE_UNKNOWN,\n- OVS_STATE_PORT_CREATED,\n- OVS_STATE_NIC_CREATED,\n- OVS_STATE_CONNECTED,\n- OVS_STATE_PORT_TEAR_DOWN,\n- OVS_STATE_PORT_DELETED,\n-} OVS_VPORT_STATE;\n-\n-typedef struct _OVS_VPORT_STATS {\n- UINT64 rxPackets;\n- UINT64 txPackets;\n- UINT64 rxBytes;\n- UINT64 txBytes;\n-} OVS_VPORT_STATS;\n-\n-typedef struct _OVS_VPORT_ERR_STATS {\n- UINT64 rxErrors;\n- UINT64 txErrors;\n- UINT64 rxDropped;\n- UINT64 txDropped;\n-} OVS_VPORT_ERR_STATS;\n-\n-/* used for vport netlink commands. */\n-typedef struct _OVS_VPORT_FULL_STATS {\n- OVS_VPORT_STATS;\n- OVS_VPORT_ERR_STATS;\n-}OVS_VPORT_FULL_STATS;\n-/*\n- * Each internal, external adapter or vritual adapter has\n- * one vport entry. In addition, we have one vport for each\n- * tunnel type, such as vxlan, gre\n- */\n-typedef struct _OVS_VPORT_ENTRY {\n- LIST_ENTRY ovsNameLink;\n- LIST_ENTRY portIdLink;\n- LIST_ENTRY portNoLink;\n- LIST_ENTRY tunnelVportLink;\n-\n- OVS_VPORT_STATE ovsState;\n- OVS_VPORT_TYPE ovsType;\n- OVS_VPORT_STATS stats;\n- OVS_VPORT_ERR_STATS errStats;\n- UINT32 portNo;\n- UINT32 mtu;\n- /* ovsName is the ovs (datapath) port name - it is null terminated. */\n- CHAR ovsName[OVS_MAX_PORT_NAME_LENGTH];\n-\n- PVOID priv;\n- NDIS_SWITCH_PORT_ID portId;\n- NDIS_SWITCH_NIC_INDEX nicIndex;\n- NDIS_SWITCH_NIC_TYPE nicType;\n- UINT16 numaNodeId;\n- NDIS_SWITCH_PORT_STATE portState;\n- NDIS_SWITCH_NIC_STATE nicState;\n- NDIS_SWITCH_PORT_TYPE portType;\n-\n- UINT8 permMacAddress[ETH_ADDR_LEN];\n- UINT8 currMacAddress[ETH_ADDR_LEN];\n- UINT8 vmMacAddress[ETH_ADDR_LEN];\n-\n- NDIS_SWITCH_PORT_NAME hvPortName;\n- IF_COUNTED_STRING portFriendlyName;\n- NDIS_SWITCH_NIC_NAME nicName;\n- NDIS_SWITCH_NIC_FRIENDLYNAME nicFriendlyName;\n- NDIS_VM_NAME vmName;\n- GUID netCfgInstanceId;\n- BOOLEAN isExternal;\n- UINT32 upcallPid; /* netlink upcall port id */\n- PNL_ATTR portOptions;\n- BOOLEAN isAbsentOnHv; /* Is this port present on the\n- Hyper-V switch? */\n-} OVS_VPORT_ENTRY, *POVS_VPORT_ENTRY;\n-\n-struct _OVS_SWITCH_CONTEXT;\n-\n-_Requires_lock_held_(switchContext->dispatchLock)\n-POVS_VPORT_ENTRY OvsFindVportByPortNo(POVS_SWITCH_CONTEXT switchContext,\n- UINT32 portNo);\n-/* \"name\" is null-terminated */\n-_Requires_lock_held_(switchContext->dispatchLock)\n-POVS_VPORT_ENTRY OvsFindVportByOvsName(POVS_SWITCH_CONTEXT switchContext,\n- PSTR name);\n-_Requires_lock_held_(switchContext->dispatchLock)\n-POVS_VPORT_ENTRY OvsFindVportByHvNameA(POVS_SWITCH_CONTEXT switchContext,\n- PSTR name);\n-_Requires_lock_held_(switchContext->dispatchLock)\n-POVS_VPORT_ENTRY OvsFindVportByHvNameW(POVS_SWITCH_CONTEXT switchContext,\n- PWSTR wsName, SIZE_T wstrSize);\n-_Requires_lock_held_(switchContext->dispatchLock)\n-POVS_VPORT_ENTRY OvsFindVportByPortIdAndNicIndex(POVS_SWITCH_CONTEXT switchContext,\n- NDIS_SWITCH_PORT_ID portId,\n- NDIS_SWITCH_NIC_INDEX index);\n-BOOLEAN OvsIsExternalVportByPortId(POVS_SWITCH_CONTEXT switchContext,\n- NDIS_SWITCH_PORT_ID portId);\n-POVS_VPORT_ENTRY OvsFindTunnelVportByDstPortAndType(POVS_SWITCH_CONTEXT switchContext,\n- UINT16 dstPort,\n- OVS_VPORT_TYPE ovsPortType);\n-POVS_VPORT_ENTRY OvsFindTunnelVportByDstPortAndNWProto(POVS_SWITCH_CONTEXT switchContext,\n- UINT16 dstPort,\n- UINT8 nwProto);\n-POVS_VPORT_ENTRY OvsFindTunnelVportByPortType(POVS_SWITCH_CONTEXT switchContext,\n- OVS_VPORT_TYPE ovsPortType);\n-\n-NDIS_STATUS OvsAddConfiguredSwitchPorts(struct _OVS_SWITCH_CONTEXT *switchContext);\n-NDIS_STATUS OvsInitConfiguredSwitchNics(struct _OVS_SWITCH_CONTEXT *switchContext);\n-\n-VOID OvsClearAllSwitchVports(struct _OVS_SWITCH_CONTEXT *switchContext);\n-\n-NDIS_STATUS HvCreateNic(POVS_SWITCH_CONTEXT switchContext,\n- PNDIS_SWITCH_NIC_PARAMETERS nicParam);\n-NDIS_STATUS HvCreatePort(POVS_SWITCH_CONTEXT switchContext,\n- PNDIS_SWITCH_PORT_PARAMETERS portParam,\n- NDIS_SWITCH_NIC_INDEX nicIndex);\n-NDIS_STATUS HvUpdatePort(POVS_SWITCH_CONTEXT switchContext,\n- PNDIS_SWITCH_PORT_PARAMETERS portParam);\n-VOID HvTeardownPort(POVS_SWITCH_CONTEXT switchContext,\n- PNDIS_SWITCH_PORT_PARAMETERS portParam);\n-VOID HvDeletePort(POVS_SWITCH_CONTEXT switchContext,\n- PNDIS_SWITCH_PORT_PARAMETERS portParam);\n-VOID HvConnectNic(POVS_SWITCH_CONTEXT switchContext,\n- PNDIS_SWITCH_NIC_PARAMETERS nicParam);\n-VOID HvUpdateNic(POVS_SWITCH_CONTEXT switchContext,\n- PNDIS_SWITCH_NIC_PARAMETERS nicParam);\n-VOID HvDeleteNic(POVS_SWITCH_CONTEXT switchContext,\n- PNDIS_SWITCH_NIC_PARAMETERS nicParam);\n-VOID HvDisconnectNic(POVS_SWITCH_CONTEXT switchContext,\n- PNDIS_SWITCH_NIC_PARAMETERS nicParam);\n-\n-static __inline BOOLEAN\n-OvsIsTunnelVportType(OVS_VPORT_TYPE ovsType)\n-{\n- return ovsType == OVS_VPORT_TYPE_VXLAN ||\n- ovsType == OVS_VPORT_TYPE_GENEVE ||\n- ovsType == OVS_VPORT_TYPE_GRE;\n-}\n-\n-\n-static __inline PVOID\n-GetOvsVportPriv(POVS_VPORT_ENTRY ovsVport)\n-{\n- return ovsVport->priv;\n-}\n-\n-static __inline BOOLEAN\n-OvsIsInternalVportType(OVS_VPORT_TYPE ovsType)\n-{\n- return ovsType == OVS_VPORT_TYPE_INTERNAL;\n-}\n-\n-static __inline BOOLEAN\n-OvsIsVirtualExternalVport(POVS_VPORT_ENTRY vport)\n-{\n- return vport->nicType == NdisSwitchNicTypeExternal &&\n- vport->nicIndex == 0;\n-}\n-\n-static __inline BOOLEAN\n-OvsIsRealExternalVport(POVS_VPORT_ENTRY vport)\n-{\n- return vport->nicType == NdisSwitchNicTypeExternal &&\n- vport->nicIndex != 0;\n-}\n-\n-static __inline BOOLEAN\n-OvsIsInternalNIC(NDIS_SWITCH_NIC_TYPE nicType)\n-{\n- return nicType == NdisSwitchNicTypeInternal;\n-}\n-\n-static __inline BOOLEAN\n-OvsIsRealExternalNIC(NDIS_SWITCH_NIC_TYPE nicType,\n- NDIS_SWITCH_NIC_INDEX nicIndex)\n-{\n- return nicType == NdisSwitchNicTypeExternal &&\n- nicIndex != 0;\n-}\n-\n-NTSTATUS OvsRemoveAndDeleteVport(PVOID usrParamsCtx,\n- POVS_SWITCH_CONTEXT switchContext,\n- POVS_VPORT_ENTRY vport,\n- BOOLEAN hvDelete, BOOLEAN ovsDelete);\n-static __inline POVS_VPORT_ENTRY\n-OvsGetExternalVport(POVS_SWITCH_CONTEXT switchContext)\n-{\n- return switchContext->virtualExternalVport;\n-}\n-\n-static __inline UINT32\n-OvsGetExternalMtu(POVS_SWITCH_CONTEXT switchContext)\n-{\n- ASSERT(OvsGetExternalVport(switchContext));\n- return ((POVS_VPORT_ENTRY) OvsGetExternalVport(switchContext))->mtu;\n-}\n-\n-static __inline UINT16\n-GetPortFromPriv(POVS_VPORT_ENTRY vport)\n-{\n- UINT16 dstPort = 0;\n- PVOID vportPriv = GetOvsVportPriv(vport);\n-\n- /* XXX would better to have a common tunnel \"parent\" structure */\n- ASSERT(vportPriv);\n- switch(vport->ovsType) {\n- case OVS_VPORT_TYPE_GRE:\n- break;\n- case OVS_VPORT_TYPE_VXLAN:\n- dstPort = ((POVS_VXLAN_VPORT)vportPriv)->dstPort;\n- break;\n- case OVS_VPORT_TYPE_GENEVE:\n- dstPort = ((POVS_GENEVE_VPORT)vportPriv)->dstPort;\n- break;\n- default:\n- ASSERT(! \"Port is not a tunnel port\");\n- }\n- ASSERT(dstPort || vport->ovsType == OVS_VPORT_TYPE_GRE);\n- return dstPort;\n-}\n-\n-NDIS_STATUS InitOvsVportCommon(POVS_SWITCH_CONTEXT switchContext,\n- POVS_VPORT_ENTRY vport);\n-NTSTATUS OvsInitTunnelVport(PVOID usrParamsCtx, POVS_VPORT_ENTRY vport,\n- OVS_VPORT_TYPE ovsType, UINT16 dstport);\n-NTSTATUS OvsInitBridgeInternalVport(POVS_VPORT_ENTRY vport);\n-\n-POVS_VPORT_ENTRY OvsAllocateVport(VOID);\n-\n-#endif /* __VPORT_H_ */\ndiff --git a/datapath-windows/ovsext/Vxlan.c b/datapath-windows/ovsext/Vxlan.c\ndeleted file mode 100644\nindex b268e7de2..000000000\n--- a/datapath-windows/ovsext/Vxlan.c\n+++ /dev/null\n@@ -1,577 +0,0 @@\n-/*\n- * Copyright (c) 2014, 2016 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#include \"precomp.h\"\n-\n-#include \"Atomic.h\"\n-#include \"Debug.h\"\n-#include \"Flow.h\"\n-#include \"IpHelper.h\"\n-#include \"NetProto.h\"\n-#include \"Offload.h\"\n-#include \"PacketIO.h\"\n-#include \"PacketParser.h\"\n-#include \"Switch.h\"\n-#include \"User.h\"\n-#include \"Vport.h\"\n-#include \"Vxlan.h\"\n-\n-#pragma warning( push )\n-#pragma warning( disable:4127 )\n-\n-\n-#ifdef OVS_DBG_MOD\n-#undef OVS_DBG_MOD\n-#endif\n-#define OVS_DBG_MOD OVS_DBG_VXLAN\n-\n-/* Helper macro to check if a VXLAN ID is valid. */\n-#define VXLAN_ID_IS_VALID(vxlanID) (0 < (vxlanID) && (vxlanID) <= 0xffffff)\n-#define VXLAN_TUNNELID_TO_VNI(_tID) (UINT32)(((UINT64)(_tID)) >> 40)\n-#define VXLAN_VNI_TO_TUNNELID(_vni) (((UINT64)(_vni)) << 40)\n-#define IP_DF_NBO 0x0040\n-#define VXLAN_DEFAULT_TTL 64\n-#define VXLAN_MULTICAST_TTL 64\n-#define VXLAN_DEFAULT_INSTANCE_ID 1\n-\n-/* Move to a header file */\n-extern POVS_SWITCH_CONTEXT gOvsSwitchContext;\n-\n-/*\n- *----------------------------------------------------------------------------\n- * This function verifies if the VXLAN tunnel already exists, in order to\n- * avoid sending a duplicate request to the WFP base filtering engine.\n- *----------------------------------------------------------------------------\n- */\n-static BOOLEAN\n-OvsIsTunnelFilterCreated(POVS_SWITCH_CONTEXT switchContext,\n- UINT16 udpPortDest)\n-{\n- for (UINT hash = 0; hash < OVS_MAX_VPORT_ARRAY_SIZE; hash++) {\n- PLIST_ENTRY head, link, next;\n-\n- head = &(switchContext->portNoHashArray[hash & OVS_VPORT_MASK]);\n- LIST_FORALL_SAFE(head, link, next) {\n- POVS_VPORT_ENTRY vport = NULL;\n- POVS_VXLAN_VPORT vxlanPort = NULL;\n- vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, portNoLink);\n- vxlanPort = (POVS_VXLAN_VPORT)vport->priv;\n- if (vxlanPort) {\n- if ((udpPortDest == vxlanPort->dstPort)) {\n- /* The VXLAN tunnel was already created. */\n- return TRUE;\n- }\n- }\n- }\n- }\n-\n- return FALSE;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * This function allocates and initializes the OVS_VXLAN_VPORT. The function\n- * also creates a WFP tunnel filter for the necessary destination port. The\n- * tunnel filter create request is passed to the tunnel filter threads that\n- * will complete the request at a later time when IRQL is lowered to\n- * PASSIVE_LEVEL.\n- *\n- * udpDestPort: the vxlan is set as payload to a udp frame. If the destination\n- * port of an udp frame is udpDestPort, we understand it to be vxlan.\n- *----------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsInitVxlanTunnel(PIRP irp,\n- POVS_VPORT_ENTRY vport,\n- UINT16 udpDestPort,\n- PFNTunnelVportPendingOp callback,\n- PVOID tunnelContext)\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n- POVS_VXLAN_VPORT vxlanPort = NULL;\n-\n- vxlanPort = OvsAllocateMemoryWithTag(sizeof (*vxlanPort),\n- OVS_VXLAN_POOL_TAG);\n- if (vxlanPort == NULL) {\n- return STATUS_INSUFFICIENT_RESOURCES;\n- }\n-\n- RtlZeroMemory(vxlanPort, sizeof(*vxlanPort));\n- vxlanPort->dstPort = udpDestPort;\n- vport->priv = (PVOID)vxlanPort;\n-\n- if (!OvsIsTunnelFilterCreated(gOvsSwitchContext, udpDestPort)) {\n- status = OvsTunnelFilterCreate(irp,\n- udpDestPort,\n- &vxlanPort->filterID,\n- callback,\n- tunnelContext);\n- } else {\n- status = STATUS_OBJECT_NAME_EXISTS;\n- }\n-\n- return status;\n-}\n-\n-/*\n- *----------------------------------------------------------------------------\n- * This function releases the OVS_VXLAN_VPORT. The function also deletes the\n- * WFP tunnel filter previously created. The tunnel filter delete request is\n- * passed to the tunnel filter threads that will complete the request at a\n- * later time when IRQL is lowered to PASSIVE_LEVEL.\n- *----------------------------------------------------------------------------\n- */\n-NTSTATUS\n-OvsCleanupVxlanTunnel(PIRP irp,\n- POVS_VPORT_ENTRY vport,\n- PFNTunnelVportPendingOp callback,\n- PVOID tunnelContext)\n-{\n- NTSTATUS status = STATUS_SUCCESS;\n- POVS_VXLAN_VPORT vxlanPort = NULL;\n-\n- if (vport->ovsType != OVS_VPORT_TYPE_VXLAN ||\n- vport->priv == NULL) {\n- return STATUS_SUCCESS;\n- }\n-\n- vxlanPort = (POVS_VXLAN_VPORT)vport->priv;\n-\n- if (vxlanPort->filterID != 0) {\n- status = OvsTunnelFilterDelete(irp,\n- vxlanPort->filterID,\n- callback,\n- tunnelContext);\n- } else {\n- OvsFreeMemoryWithTag(vport->priv, OVS_VXLAN_POOL_TAG);\n- vport->priv = NULL;\n- }\n-\n- return status;\n-}\n-\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsDoEncapVxlan\n- * Encapsulates the packet.\n- *----------------------------------------------------------------------------\n- */\n-static __inline NDIS_STATUS\n-OvsDoEncapVxlan(POVS_VPORT_ENTRY vport,\n- PNET_BUFFER_LIST curNbl,\n- OvsIPTunnelKey *tunKey,\n- POVS_FWD_INFO fwdInfo,\n- POVS_PACKET_HDR_INFO layers,\n- POVS_SWITCH_CONTEXT switchContext,\n- PNET_BUFFER_LIST *newNbl)\n-{\n- NDIS_STATUS status;\n- PNET_BUFFER curNb;\n- PMDL curMdl;\n- PUINT8 bufferStart;\n- EthHdr *ethHdr;\n- IPHdr *ipHdr;\n- UDPHdr *udpHdr;\n- VXLANHdr *vxlanHdr;\n- POVS_VXLAN_VPORT vportVxlan;\n- UINT32 packetLength;\n- ULONG mss = 0;\n- NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo;\n- UINT32 headRoom =\n- OvsGetVxlanTunHdrSize(fwdInfo->dstIphAddr.si_family == AF_INET ?\n- TRUE : FALSE);\n- ASSERT(OvsIphAddrEquals(&tunKey->dst, &fwdInfo->dstIphAddr));\n- ASSERT(OvsIphAddrEquals(&tunKey->src, &fwdInfo->srcIphAddr) ||\n- OvsIphIsZero(&tunKey->src));\n-\n- curNb = NET_BUFFER_LIST_FIRST_NB(curNbl);\n- packetLength = NET_BUFFER_DATA_LENGTH(curNb);\n-\n- if (layers->isTcp) {\n- mss = OVSGetTcpMSS(curNbl);\n-\n- OVS_LOG_TRACE(\"MSS %u packet len %u\", mss,\n- packetLength);\n- if (mss) {\n- OVS_LOG_TRACE(\"l4Offset %d\", layers->l4Offset);\n- *newNbl = OvsTcpSegmentNBL(switchContext, curNbl, layers,\n- mss, headRoom, FALSE);\n- if (*newNbl == NULL) {\n- OVS_LOG_ERROR(\"Unable to segment NBL\");\n- return NDIS_STATUS_FAILURE;\n- }\n- /* Clear out LSO flags after this point */\n- NET_BUFFER_LIST_INFO(*newNbl, TcpLargeSendNetBufferListInfo) = 0;\n- }\n- }\n-\n- vportVxlan = (POVS_VXLAN_VPORT) GetOvsVportPriv(vport);\n- ASSERT(vportVxlan);\n-\n- /* If we didn't split the packet above, make a copy now */\n- if (*newNbl == NULL) {\n- *newNbl = OvsPartialCopyNBL(switchContext, curNbl, 0, headRoom,\n- FALSE /*NBL info*/);\n- if (*newNbl == NULL) {\n- OVS_LOG_ERROR(\"Unable to copy NBL\");\n- return NDIS_STATUS_FAILURE;\n- }\n- csumInfo.Value = NET_BUFFER_LIST_INFO(curNbl,\n- TcpIpChecksumNetBufferListInfo);\n- status = OvsApplySWChecksumOnNB(layers, *newNbl, &csumInfo);\n-\n- if (status != NDIS_STATUS_SUCCESS) {\n- goto ret_error;\n- }\n- }\n-\n- curNbl = *newNbl;\n- for (curNb = NET_BUFFER_LIST_FIRST_NB(curNbl); curNb != NULL;\n- curNb = curNb->Next) {\n- status = NdisRetreatNetBufferDataStart(curNb, headRoom, 0, NULL);\n- if (status != NDIS_STATUS_SUCCESS) {\n- goto ret_error;\n- }\n-\n- curMdl = NET_BUFFER_CURRENT_MDL(curNb);\n- bufferStart = (PUINT8)OvsGetMdlWithLowPriority(curMdl);\n- if (!bufferStart) {\n- status = NDIS_STATUS_RESOURCES;\n- goto ret_error;\n- }\n-\n- bufferStart += NET_BUFFER_CURRENT_MDL_OFFSET(curNb);\n- if (NET_BUFFER_NEXT_NB(curNb)) {\n- OVS_LOG_TRACE(\"nb length %u next %u\",\n- NET_BUFFER_DATA_LENGTH(curNb),\n- NET_BUFFER_DATA_LENGTH(curNb->Next));\n- }\n-\n- /* L2 header */\n- ethHdr = (EthHdr *)bufferStart;\n- NdisMoveMemory(ethHdr->Destination, fwdInfo->dstMacAddr,\n- sizeof ethHdr->Destination);\n- NdisMoveMemory(ethHdr->Source, fwdInfo->srcMacAddr,\n- sizeof ethHdr->Source);\n- ethHdr->Type = htons(ETH_TYPE_IPV4);\n-\n- /* IP header */\n- if (fwdInfo->dstIphAddr.si_family == AF_INET) {\n- ipHdr = (IPHdr *)((PCHAR)ethHdr + sizeof *ethHdr);\n-\n- ipHdr->ihl = sizeof *ipHdr / 4;\n- ipHdr->version = IPPROTO_IPV4;\n- ipHdr->tos = tunKey->tos;\n- ipHdr->tot_len = htons(NET_BUFFER_DATA_LENGTH(curNb) - sizeof *ethHdr);\n- ipHdr->id = (uint16)atomic_add64(&vportVxlan->ipId,\n- NET_BUFFER_DATA_LENGTH(curNb));\n- ipHdr->frag_off = (tunKey->flags & OVS_TNL_F_DONT_FRAGMENT) ?\n- IP_DF_NBO : 0;\n- ipHdr->ttl = tunKey->ttl ? tunKey->ttl : VXLAN_DEFAULT_TTL;\n- ipHdr->protocol = IPPROTO_UDP;\n- ASSERT(OvsIphAddrEquals(&tunKey->dst, &fwdInfo->dstIphAddr));\n- ASSERT(OvsIphAddrEquals(&tunKey->src, &fwdInfo->srcIphAddr) ||\n- OvsIphIsZero(&tunKey->src));\n-\n- ipHdr->saddr = fwdInfo->srcIphAddr.Ipv4.sin_addr.s_addr;\n- ipHdr->daddr = fwdInfo->dstIphAddr.Ipv4.sin_addr.s_addr;\n-\n- ipHdr->check = 0;\n-\n- /* UDP header */\n- udpHdr = (UDPHdr *)((PCHAR)ipHdr + sizeof *ipHdr);\n- udpHdr->source = htons(tunKey->flow_hash | MAXINT16);\n- udpHdr->dest = tunKey->dst_port ? tunKey->dst_port :\n- htons(vportVxlan->dstPort);\n- udpHdr->len = htons(NET_BUFFER_DATA_LENGTH(curNb) - headRoom +\n- sizeof *udpHdr + sizeof *vxlanHdr);\n-\n- if (tunKey->flags & OVS_TNL_F_CSUM) {\n- udpHdr->check = IPPseudoChecksum(&ipHdr->saddr, &ipHdr->daddr,\n- IPPROTO_UDP, ntohs(udpHdr->len));\n- } else {\n- udpHdr->check = 0;\n- }\n-\n- /* VXLAN header */\n- vxlanHdr = (VXLANHdr *)((PCHAR)udpHdr + sizeof *udpHdr);\n- vxlanHdr->flags1 = 0;\n- vxlanHdr->locallyReplicate = 0;\n- vxlanHdr->flags2 = 0;\n- vxlanHdr->reserved1 = 0;\n- vxlanHdr->vxlanID = VXLAN_TUNNELID_TO_VNI(tunKey->tunnelId);\n- vxlanHdr->instanceID = 1;\n- vxlanHdr->reserved2 = 0;\n- } else {\n- status = NDIS_STATUS_FAILURE;\n- goto ret_error;\n- }\n- }\n-\n- csumInfo.Value = 0;\n- if (fwdInfo->dstIphAddr.si_family == AF_INET) {\n- csumInfo.Transmit.IpHeaderChecksum = 1;\n- csumInfo.Transmit.IsIPv4 = 1;\n- } else {\n- csumInfo.Transmit.IsIPv6 = 1;\n- }\n- if (tunKey->flags & OVS_TNL_F_CSUM) {\n- csumInfo.Transmit.UdpChecksum = 1;\n- }\n- NET_BUFFER_LIST_INFO(curNbl,\n- TcpIpChecksumNetBufferListInfo) = csumInfo.Value;\n-\n-\n- return STATUS_SUCCESS;\n-\n-ret_error:\n- OvsCompleteNBL(switchContext, *newNbl, TRUE);\n- *newNbl = NULL;\n- return status;\n-}\n-\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsEncapVxlan --\n- * Encapsulates the packet if L2/L3 for destination resolves. Otherwise,\n- * enqueues a callback that does encapsulation after resolution.\n- *----------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsEncapVxlan(POVS_VPORT_ENTRY vport,\n- PNET_BUFFER_LIST curNbl,\n- OvsIPTunnelKey *tunKey,\n- POVS_SWITCH_CONTEXT switchContext,\n- POVS_PACKET_HDR_INFO layers,\n- PNET_BUFFER_LIST *newNbl,\n- POVS_FWD_INFO switchFwdInfo)\n-{\n- NTSTATUS status;\n- OVS_FWD_INFO fwdInfo;\n-\n- if (tunKey->dst.si_family != AF_INET) {\n- /*V6 tunnel support will be supported later*/\n- return NDIS_STATUS_FAILURE;\n- }\n-\n- status = OvsLookupIPhFwdInfo(tunKey->src, tunKey->dst, &fwdInfo);\n- if (status != STATUS_SUCCESS) {\n- OvsFwdIPHelperRequest(NULL, 0, tunKey, NULL, NULL, NULL);\n- /*\n- * XXX: Don't know if the completionList will make any sense when\n- * accessed in the callback. Make sure the caveats are known.\n- *\n- * XXX: This code will work once we are able to grab locks in the\n- * callback.\n- */\n- return NDIS_STATUS_FAILURE;\n- }\n-\n- RtlCopyMemory(switchFwdInfo->value, fwdInfo.value, sizeof fwdInfo.value);\n-\n- return OvsDoEncapVxlan(vport, curNbl, tunKey, &fwdInfo, layers,\n- switchContext, newNbl);\n-}\n-\n-\n-/*\n- *----------------------------------------------------------------------------\n- * OvsDecapVxlan\n- * Decapsulates to tunnel header in 'curNbl' and puts into 'tunKey'.\n- *----------------------------------------------------------------------------\n- */\n-NDIS_STATUS\n-OvsDecapVxlan(POVS_SWITCH_CONTEXT switchContext,\n- PNET_BUFFER_LIST curNbl,\n- OvsIPTunnelKey *tunKey,\n- PNET_BUFFER_LIST *newNbl)\n-{\n- PNET_BUFFER curNb;\n- PMDL curMdl;\n- EthHdr *ethHdr;\n- IPHdr *ipHdr;\n- UDPHdr *udpHdr;\n- VXLANHdr *vxlanHdr;\n- UINT32 tunnelSize, packetLength;\n- PUINT8 bufferStart;\n- NDIS_STATUS status;\n- OVS_PACKET_HDR_INFO layers = { 0 };\n-\n- status = OvsExtractLayers(curNbl, &layers);\n- if (status != NDIS_STATUS_SUCCESS) {\n- return status;\n- }\n-\n- /* Check the length of the UDP payload */\n- curNb = NET_BUFFER_LIST_FIRST_NB(curNbl);\n- packetLength = NET_BUFFER_DATA_LENGTH(curNb);\n- tunnelSize = OvsGetVxlanTunHdrSizeFromLayers(&layers);\n- if (packetLength < tunnelSize) {\n- return NDIS_STATUS_INVALID_LENGTH;\n- }\n-\n- /*\n- * Create a copy of the NBL so that we have all the headers in one MDL.\n- */\n- *newNbl = OvsPartialCopyNBL(switchContext, curNbl,\n- tunnelSize, 0,\n- TRUE /*copy NBL info */);\n-\n- if (*newNbl == NULL) {\n- return NDIS_STATUS_RESOURCES;\n- }\n-\n- /* XXX: Handle VLAN header. */\n- curNbl = *newNbl;\n- curNb = NET_BUFFER_LIST_FIRST_NB(curNbl);\n- curMdl = NET_BUFFER_CURRENT_MDL(curNb);\n- bufferStart = (PUINT8)OvsGetMdlWithLowPriority(curMdl)\n- + NET_BUFFER_CURRENT_MDL_OFFSET(curNb);\n- if (!bufferStart) {\n- status = NDIS_STATUS_RESOURCES;\n- goto dropNbl;\n- }\n-\n- ethHdr = (EthHdr *)bufferStart;\n- if (ethHdr->Type == ETH_TYPE_IPV4_NBO) {\n- /* XXX: Handle IP options. */\n- ipHdr = (IPHdr *)(bufferStart + layers.l3Offset);\n- tunKey->src.Ipv4.sin_addr.s_addr = ipHdr->saddr;\n- tunKey->src.si_family = AF_INET;\n- tunKey->dst.Ipv4.sin_addr.s_addr = ipHdr->daddr;\n- tunKey->dst.si_family = AF_INET;\n- tunKey->tos = ipHdr->tos;\n- tunKey->ttl = ipHdr->ttl;\n- tunKey->pad = 0;\n- } else {\n- IPv6Hdr *ipv6Hdr;\n- ASSERT(ethHdr->Type == ETH_TYPE_IPV6_NBO);\n- ipv6Hdr = (IPv6Hdr *)((PCHAR)ethHdr + sizeof(*ethHdr));\n- RtlCopyMemory(&tunKey->src.Ipv6.sin6_addr, &ipv6Hdr->saddr, sizeof(ipv6Hdr->saddr));\n- tunKey->src.si_family = AF_INET6;\n- RtlCopyMemory(&tunKey->dst.Ipv6.sin6_addr, &ipv6Hdr->daddr, sizeof(ipv6Hdr->saddr));\n- tunKey->dst.si_family = AF_INET6;\n- tunKey->tos = (ipv6Hdr->priority << 4) |\n- ((ipv6Hdr->flow_lbl[0] & 0xF0) >> 4);\n- tunKey->ttl = ipv6Hdr->hop_limit;\n- tunKey->pad = 0;\n- }\n- udpHdr = (UDPHdr *)(bufferStart + layers.l4Offset);\n-\n- /* Validate if NIC has indicated checksum failure. */\n- status = OvsValidateUDPChecksum(curNbl, udpHdr->check == 0);\n- if (status != NDIS_STATUS_SUCCESS) {\n- goto dropNbl;\n- }\n-\n- /* Calculate and verify UDP checksum if NIC didn't do it. */\n- if (udpHdr->check != 0) {\n- tunKey->flags |= OVS_TNL_F_CSUM;\n- status = OvsCalculateUDPChecksum(curNbl, curNb, ethHdr, udpHdr,\n- packetLength, &layers);\n- if (status != NDIS_STATUS_SUCCESS) {\n- goto dropNbl;\n- }\n- }\n-\n- vxlanHdr = (VXLANHdr *)((PCHAR)udpHdr + sizeof *udpHdr);\n- if (vxlanHdr->instanceID) {\n- tunKey->flags |= OVS_TNL_F_KEY;\n- tunKey->tunnelId = VXLAN_VNI_TO_TUNNELID(vxlanHdr->vxlanID);\n- } else {\n- tunKey->flags &= ~OVS_TNL_F_KEY;\n- tunKey->tunnelId = 0;\n- }\n-\n- /* Clear out the receive flag for the inner packet. */\n- NET_BUFFER_LIST_INFO(curNbl, TcpIpChecksumNetBufferListInfo) = 0;\n- NdisAdvanceNetBufferDataStart(curNb, tunnelSize, FALSE, NULL);\n- return NDIS_STATUS_SUCCESS;\n-\n-dropNbl:\n- OvsCompleteNBL(switchContext, *newNbl, TRUE);\n- *newNbl = NULL;\n- return status;\n-}\n-\n-\n-NDIS_STATUS\n-OvsSlowPathDecapVxlan(const PNET_BUFFER_LIST packet,\n- OvsIPTunnelKey *tunnelKey)\n-{\n- NDIS_STATUS status = NDIS_STATUS_FAILURE;\n- UDPHdr udpStorage;\n- const UDPHdr *udp;\n- VXLANHdr *VxlanHeader;\n- VXLANHdr VxlanHeaderBuffer;\n- struct IPHdr ip_storage;\n- const struct IPHdr *nh;\n- OVS_PACKET_HDR_INFO layers;\n-\n- layers.value = 0;\n-\n- do {\n- nh = OvsGetIp(packet, layers.l3Offset, &ip_storage);\n- if (nh) {\n- layers.l4Offset = layers.l3Offset + nh->ihl * 4;\n- } else {\n- status = NDIS_STATUS_INVALID_PACKET;\n- break;\n- }\n-\n- /* make sure it's a VXLAN packet */\n- udp = OvsGetUdp(packet, layers.l4Offset, &udpStorage);\n- if (udp) {\n- layers.l7Offset = layers.l4Offset + sizeof *udp;\n- if (udp->check != 0) {\n- tunnelKey->flags |= OVS_TNL_F_CSUM;\n- }\n- } else {\n- break;\n- }\n-\n- VxlanHeader = (VXLANHdr *)OvsGetPacketBytes(packet,\n- sizeof(*VxlanHeader),\n- layers.l7Offset,\n- &VxlanHeaderBuffer);\n-\n- if (VxlanHeader) {\n- tunnelKey->src.Ipv4.sin_addr.s_addr = nh->saddr;\n- tunnelKey->src.si_family = AF_INET;\n- tunnelKey->dst.Ipv4.sin_addr.s_addr = nh->daddr;\n- tunnelKey->dst.si_family = AF_INET;\n- tunnelKey->ttl = nh->ttl;\n- tunnelKey->tos = nh->tos;\n- if (VxlanHeader->instanceID) {\n- tunnelKey->flags |= OVS_TNL_F_KEY;\n- tunnelKey->tunnelId = VXLAN_VNI_TO_TUNNELID(VxlanHeader->vxlanID);\n- } else {\n- tunnelKey->flags &= ~OVS_TNL_F_KEY;\n- tunnelKey->tunnelId = 0;\n- }\n- } else {\n- break;\n- }\n- status = NDIS_STATUS_SUCCESS;\n-\n- } while(FALSE);\n-\n- return status;\n-}\n-\n-#pragma warning( pop )\ndiff --git a/datapath-windows/ovsext/Vxlan.h b/datapath-windows/ovsext/Vxlan.h\ndeleted file mode 100644\nindex 1cd35f6ae..000000000\n--- a/datapath-windows/ovsext/Vxlan.h\n+++ /dev/null\n@@ -1,97 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#ifndef __VXLAN_H_\n-#define __VXLAN_H_ 1\n-\n-#include \"IpHelper.h\"\n-#include \"NetProto.h\"\n-\n-typedef union _OVS_FWD_INFO *POVS_FWD_INFO;\n-\n-typedef struct _OVS_VXLAN_VPORT {\n- UINT16 dstPort;\n- UINT64 filterID;\n- UINT64 ipId;\n- /*\n- * To be filled\n- */\n-} OVS_VXLAN_VPORT, *POVS_VXLAN_VPORT;\n-\n-/* VXLAN header. */\n-typedef struct VXLANHdr {\n- /* Flags. */\n- UINT32 flags1:2;\n- /* Packet needs replication to multicast group (used for multicast proxy).\n- */\n- UINT32 locallyReplicate:1;\n- /* Instance ID flag, must be set to 1. */\n- UINT32 instanceID:1;\n- /* Flags. */\n- UINT32 flags2:4;\n- /* Reserved. */\n- UINT32 reserved1:24;\n- /* VXLAN ID. */\n- UINT32 vxlanID:24;\n- /* Reserved. */\n- UINT32 reserved2:8;\n-} VXLANHdr;\n-\n-NTSTATUS OvsInitVxlanTunnel(PIRP irp,\n- POVS_VPORT_ENTRY vport,\n- UINT16 udpDestPort,\n- PFNTunnelVportPendingOp callback,\n- PVOID tunnelContext);\n-\n-NTSTATUS OvsCleanupVxlanTunnel(PIRP irp,\n- POVS_VPORT_ENTRY vport,\n- PFNTunnelVportPendingOp callback,\n- PVOID tunnelContext);\n-\n-NDIS_STATUS OvsSlowPathDecapVxlan(const PNET_BUFFER_LIST packet,\n- OvsIPTunnelKey *tunnelKey);\n-\n-NDIS_STATUS OvsEncapVxlan(POVS_VPORT_ENTRY vport,\n- PNET_BUFFER_LIST curNbl,\n- OvsIPTunnelKey *tunKey,\n- POVS_SWITCH_CONTEXT switchContext,\n- POVS_PACKET_HDR_INFO layers,\n- PNET_BUFFER_LIST *newNbl,\n- POVS_FWD_INFO switchFwdInfo);\n-\n-NDIS_STATUS OvsDecapVxlan(POVS_SWITCH_CONTEXT switchContext,\n- PNET_BUFFER_LIST curNbl,\n- OvsIPTunnelKey *tunKey,\n- PNET_BUFFER_LIST *newNbl);\n-\n-static __inline UINT32\n-OvsGetVxlanTunHdrSize(BOOLEAN isIpv4)\n-{\n- /* XXX: Can L2 include VLAN at all? */\n- return sizeof(EthHdr) + (isIpv4 ? sizeof(IPHdr) : sizeof(IPv6Hdr)) +\n- sizeof (UDPHdr) + sizeof (VXLANHdr);\n-}\n-\n-static __inline UINT32\n-OvsGetVxlanTunHdrSizeFromLayers(POVS_PACKET_HDR_INFO layers)\n-{\n- return layers->l7Offset + sizeof(VXLANHdr);\n-}\n-\n-#define VXLAN_UDP_PORT 4789\n-#define VXLAN_UDP_PORT_NBO 0xB512\n-\n-#endif /* __VXLAN_H_ */\ndiff --git a/datapath-windows/ovsext/ovsext.inf b/datapath-windows/ovsext/ovsext.inf\ndeleted file mode 100644\nindex e68b94a36..000000000\n--- a/datapath-windows/ovsext/ovsext.inf\n+++ /dev/null\n@@ -1,84 +0,0 @@\n-;\n-; Copyright (c) VMware. All Rights Reserved.\n-;\n-\n-[version]\n-Signature = \"$Windows NT$\"\n-Class = NetService\n-ClassGUID = {4D36E974-E325-11CE-BFC1-08002BE10318}\n-Provider = %OVS%\n-CatalogFile = ovsext.cat\n-DriverVer = 10/10/2013,1.0\n-\n-[Manufacturer]\n-%OVS%=OVS,NTx86,NTia64,NTamd64\n-\n-[OVS.NTx86]\n-%OVSExt_Desc%=Install, OVSExt\n-\n-[OVS.NTia64]\n-%OVSExt_Desc%=Install, OVSExt\n-\n-[OVS.NTamd64]\n-%OVSExt_Desc%=Install, OVSExt\n-\n-;-------------------------------------------------------------------------\n-; Installation Section\n-;-------------------------------------------------------------------------\n-[Install]\n-AddReg=Inst_Ndi\n-Characteristics=0x40000\n-NetCfgInstanceId=\"{583CC151-73EC-4A6A-8B47-578297AD7623}\"\n-Copyfiles = OVSExt.copyfiles.sys\n-\n-[SourceDisksNames]\n-1=%OVSExt_Desc%,\"\",,\n-\n-[SourceDisksFiles]\n-OVSExt.sys=1\n-\n-[DestinationDirs]\n-DefaultDestDir=12\n-OVSExt.copyfiles.sys=12\n-\n-[OVSExt.copyfiles.sys]\n-OVSExt.sys,,,2\n-\n-\n-;-------------------------------------------------------------------------\n-; Ndi installation support\n-;-------------------------------------------------------------------------\n-[Inst_Ndi]\n-HKR, Ndi,Service,,\"OVSExt\"\n-HKR, Ndi,CoServices,0x00010000,\"OVSExt\"\n-HKR, Ndi,HelpText,,%OVSExt_HelpText%\n-HKR, Ndi,FilterClass,,\"ms_switch_forward\"\n-HKR, Ndi,FilterType,0x00010001,0x00000002\n-HKR, Ndi\\Interfaces,UpperRange,,\"noupper\"\n-HKR, Ndi\\Interfaces,LowerRange,,\"nolower\"\n-HKR, Ndi\\Interfaces, FilterMediaTypes,,\"vmnetextension\"\n-HKR, Ndi,FilterRunType, 0x00010001, 2 ; optional\n-\n-;-------------------------------------------------------------------------\n-; Service installation support, common.EventLog here is to demonstrate how to\n-; write an enent log\n-;-------------------------------------------------------------------------\n-[Install.Services]\n-AddService=OVSExt,,OVSExt_Service_Inst;, common.EventLog\n-\n-[OVSExt_Service_Inst]\n-DisplayName = %OVSExt_Desc%\n-ServiceType = 1 ;SERVICE_KERNEL_DRIVER\n-StartType = 1 ;SERVICE_SYSTEM_START\n-ErrorControl = 1 ;SERVICE_ERROR_NORMAL\n-ServiceBinary = %12%\\OVSExt.sys\n-LoadOrderGroup = NDIS\n-Description = %OVSExt_Desc%\n-\n-[Install.Remove.Services]\n-DelService=OVSExt,0x200\n-\n-[Strings]\n-OVS = \"The Linux Foundation (R)\"\n-OVSExt_Desc = \"Open vSwitch Extension\"\n-OVSExt_HelpText = \"Open vSwitch forwarding switch extension\"\ndiff --git a/datapath-windows/ovsext/ovsext.rc b/datapath-windows/ovsext/ovsext.rc\ndeleted file mode 100644\nindex e6334c231..000000000\n--- a/datapath-windows/ovsext/ovsext.rc\n+++ /dev/null\n@@ -1,89 +0,0 @@\n-// Microsoft Visual C++ generated resource script.\n-//\n-#include \"resource.h\"\n-/////////////////////////////////////////////////////////////////////////////\n-// English (United States) resources\n-\n-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\n-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US\n-#pragma code_page(1252)\n-\n-#define STR(x) #x\n-#define VER_TO_STR(v) STR(v)\n-/////////////////////////////////////////////////////////////////////////////\n-//\n-// Version\n-//\n-\n-VS_VERSION_INFO VERSIONINFO\n- FILEVERSION VersionWithCommas\n- PRODUCTVERSION VersionWithCommas\n- FILEFLAGSMASK 0x3fL\n-#ifdef _DEBUG\n- FILEFLAGS 0x9L\n-#else\n- FILEFLAGS 0x8L\n-#endif\n- FILEOS 0x40004L\n- FILETYPE 0x3L\n- FILESUBTYPE 0x6L\n-BEGIN\n- BLOCK \"StringFileInfo\"\n- BEGIN\n- BLOCK \"000004b0\"\n- BEGIN\n- VALUE \"CompanyName\", \"The Linux Foundation (R)\"\n- VALUE \"FileDescription\", \"Open vSwitch Extension\"\n- VALUE \"FileVersion\", VER_TO_STR(VersionWithDots)\n- VALUE \"InternalName\", \"OVSExt.SYS\"\n- VALUE \"LegalCopyright\", \"Licensed under the Apache License, Version 2.0 (the \"\"License\"\")\"\n- VALUE \"OriginalFilename\", \"OVSExt.SYS\"\n- VALUE \"ProductName\", \"Open vSwitch\"\n- VALUE \"ProductVersion\", VER_TO_STR(VersionWithDots)\n- END\n- END\n- BLOCK \"VarFileInfo\"\n- BEGIN\n- VALUE \"Translation\", 0x0, 1200\n- END\n-END\n-\n-\n-#ifdef APSTUDIO_INVOKED\n-/////////////////////////////////////////////////////////////////////////////\n-//\n-// TEXTINCLUDE\n-//\n-\n-1 TEXTINCLUDE\n-BEGIN\n- \"resource.h\\0\"\n-END\n-\n-2 TEXTINCLUDE\n-BEGIN\n- \"\\0\"\n-END\n-\n-3 TEXTINCLUDE\n-BEGIN\n- \"\\r\\n\"\n- \"\\0\"\n-END\n-\n-#endif // APSTUDIO_INVOKED\n-\n-#endif // English (United States) resources\n-/////////////////////////////////////////////////////////////////////////////\n-\n-\n-\n-#ifndef APSTUDIO_INVOKED\n-/////////////////////////////////////////////////////////////////////////////\n-//\n-// Generated from the TEXTINCLUDE 3 resource.\n-//\n-\n-\n-/////////////////////////////////////////////////////////////////////////////\n-#endif // not APSTUDIO_INVOKED\ndiff --git a/datapath-windows/ovsext/ovsext.vcxproj b/datapath-windows/ovsext/ovsext.vcxproj\ndeleted file mode 100644\nindex e1c43fd56..000000000\n--- a/datapath-windows/ovsext/ovsext.vcxproj\n+++ /dev/null\n@@ -1,457 +0,0 @@\n-<?xml version=\"1.0\" encoding=\"utf-8\"?>\n-<Project DefaultTargets=\"Build\" ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n- <ItemGroup Label=\"ProjectConfigurations\">\n- <ProjectConfiguration Include=\"Win10 Debug|x64\">\n- <Configuration>Win10 Debug</Configuration>\n- <Platform>x64</Platform>\n- </ProjectConfiguration>\n- <ProjectConfiguration Include=\"Win10 Release|x64\">\n- <Configuration>Win10 Release</Configuration>\n- <Platform>x64</Platform>\n- </ProjectConfiguration>\n- <ProjectConfiguration Include=\"Win10Analyze|x64\">\n- <Configuration>Win10Analyze</Configuration>\n- <Platform>x64</Platform>\n- </ProjectConfiguration>\n- <ProjectConfiguration Include=\"Win8.1 Debug|x64\">\n- <Configuration>Win8.1 Debug</Configuration>\n- <Platform>x64</Platform>\n- </ProjectConfiguration>\n- <ProjectConfiguration Include=\"Win8 Debug|x64\">\n- <Configuration>Win8 Debug</Configuration>\n- <Platform>x64</Platform>\n- </ProjectConfiguration>\n- <ProjectConfiguration Include=\"Win8.1 Release|x64\">\n- <Configuration>Win8.1 Release</Configuration>\n- <Platform>x64</Platform>\n- </ProjectConfiguration>\n- <ProjectConfiguration Include=\"Win8 Release|x64\">\n- <Configuration>Win8 Release</Configuration>\n- <Platform>x64</Platform>\n- </ProjectConfiguration>\n- <ProjectConfiguration Include=\"Win8.1Analyze|x64\">\n- <Configuration>Win8.1Analyze</Configuration>\n- <Platform>x64</Platform>\n- </ProjectConfiguration>\n- <ProjectConfiguration Include=\"Win8Analyze|x64\">\n- <Configuration>Win8Analyze</Configuration>\n- <Platform>x64</Platform>\n- </ProjectConfiguration>\n- </ItemGroup>\n- <PropertyGroup Label=\"PropertySheets\">\n- <DriverType>WDM</DriverType>\n- <ConfigurationType>Driver</ConfigurationType>\n- </PropertyGroup>\n- <PropertyGroup Label=\"Globals\">\n- <VCTargetsPath Condition=\"'$(VCTargetsPath11)' != '' and '$(VisualStudioVersion)' == '11.0'\">$(VCTargetsPath11)</VCTargetsPath>\n- <Configuration>Win8 Debug</Configuration>\n- <Platform Condition=\"'$(Platform)' == ''\">Win32</Platform>\n- <SampleGuid>{0D37F250-E766-44C7-90B4-D7E07E77D1AA}</SampleGuid>\n- <PlatformToolsetVer Condition=\"$(WindowsSdkDir.EndsWith('\\Windows Kits\\10\\'))\">10.0</PlatformToolsetVer>\n- <PlatformToolsetVer Condition=\"$(WindowsSdkDir.EndsWith('\\Windows Kits\\8.1\\'))\">8.1</PlatformToolsetVer>\n- </PropertyGroup>\n- <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n- <PropertyGroup Label=\"Globals\">\n- <ProjectGuid>{63FE215D-98BE-4440-8081-C6160EFB80FA}</ProjectGuid>\n- <RootNamespace>$(MSBuildProjectName)</RootNamespace>\n- </PropertyGroup>\n- <PropertyGroup Label=\"Configuration\" Condition=\"'$(Configuration)|$(Platform)'=='Win8.1 Debug|x64'\">\n- <TargetVersion>WindowsV6.3</TargetVersion>\n- <UseDebugLibraries>True</UseDebugLibraries>\n- <PlatformToolsetVer Condition=\"'$(PlatformToolsetVer)' == ''\">8.1</PlatformToolsetVer>\n- <PlatformToolset>WindowsKernelModeDriver$(PlatformToolsetVer)</PlatformToolset>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8.1Analyze|x64'\" Label=\"Configuration\">\n- <TargetVersion>WindowsV6.3</TargetVersion>\n- <UseDebugLibraries>True</UseDebugLibraries>\n- <PlatformToolsetVer Condition=\"'$(PlatformToolsetVer)' == ''\">8.1</PlatformToolsetVer>\n- <PlatformToolset>WindowsKernelModeDriver$(PlatformToolsetVer)</PlatformToolset>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win10 Debug|x64'\" Label=\"Configuration\">\n- <TargetVersion>\n- </TargetVersion>\n- <UseDebugLibraries>True</UseDebugLibraries>\n- <PlatformToolsetVer Condition=\"'$(PlatformToolsetVer)' == ''\">10.0</PlatformToolsetVer>\n- <PlatformToolset>WindowsKernelModeDriver$(PlatformToolsetVer)</PlatformToolset>\n- <DriverTargetPlatform>Desktop</DriverTargetPlatform>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win10Analyze|x64'\" Label=\"Configuration\">\n- <TargetVersion />\n- <UseDebugLibraries>True</UseDebugLibraries>\n- <PlatformToolsetVer Condition=\"'$(PlatformToolsetVer)' == ''\">10.0</PlatformToolsetVer>\n- <PlatformToolset>WindowsKernelModeDriver$(PlatformToolsetVer)</PlatformToolset>\n- <DriverTargetPlatform>Desktop</DriverTargetPlatform>\n- </PropertyGroup>\n- <PropertyGroup Label=\"Configuration\" Condition=\"'$(Configuration)|$(Platform)'=='Win8 Debug|x64'\">\n- <TargetVersion>Windows8</TargetVersion>\n- <UseDebugLibraries>True</UseDebugLibraries>\n- <PlatformToolsetVer Condition=\"'$(PlatformToolsetVer)' == ''\">8.1</PlatformToolsetVer>\n- <PlatformToolset>WindowsKernelModeDriver$(PlatformToolsetVer)</PlatformToolset>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8Analyze|x64'\" Label=\"Configuration\">\n- <TargetVersion>Windows8</TargetVersion>\n- <UseDebugLibraries>True</UseDebugLibraries>\n- <PlatformToolsetVer Condition=\"'$(PlatformToolsetVer)' == ''\">8.1</PlatformToolsetVer>\n- <PlatformToolset>WindowsKernelModeDriver$(PlatformToolsetVer)</PlatformToolset>\n- </PropertyGroup>\n- <PropertyGroup Label=\"Configuration\" Condition=\"'$(Configuration)|$(Platform)'=='Win8.1 Release|x64'\">\n- <TargetVersion>WindowsV6.3</TargetVersion>\n- <UseDebugLibraries>False</UseDebugLibraries>\n- <PlatformToolsetVer Condition=\"'$(PlatformToolsetVer)' == ''\">8.1</PlatformToolsetVer>\n- <PlatformToolset>WindowsKernelModeDriver$(PlatformToolsetVer)</PlatformToolset>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win10 Release|x64'\" Label=\"Configuration\">\n- <TargetVersion>\n- </TargetVersion>\n- <UseDebugLibraries>False</UseDebugLibraries>\n- <PlatformToolsetVer Condition=\"'$(PlatformToolsetVer)' == ''\">10.0</PlatformToolsetVer>\n- <PlatformToolset>WindowsKernelModeDriver$(PlatformToolsetVer)</PlatformToolset>\n- <DriverTargetPlatform>Desktop</DriverTargetPlatform>\n- </PropertyGroup>\n- <PropertyGroup Label=\"Configuration\" Condition=\"'$(Configuration)|$(Platform)'=='Win8 Release|x64'\">\n- <TargetVersion>Windows8</TargetVersion>\n- <UseDebugLibraries>False</UseDebugLibraries>\n- <PlatformToolsetVer Condition=\"'$(PlatformToolsetVer)' == ''\">8.1</PlatformToolsetVer>\n- <PlatformToolset>WindowsKernelModeDriver$(PlatformToolsetVer)</PlatformToolset>\n- </PropertyGroup>\n- <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n- <PropertyGroup>\n- <OutDir>$(IntDir)</OutDir>\n- </PropertyGroup>\n- <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Win8 Release|x64'\">\n- <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" />\n- </ImportGroup>\n- <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Win10 Release|x64'\" Label=\"PropertySheets\">\n- <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" />\n- </ImportGroup>\n- <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8.1 Release|x64'\" Label=\"PropertySheets\">\n- <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" />\n- </ImportGroup>\n- <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Win8 Debug|x64'\">\n- <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" />\n- </ImportGroup>\n- <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8Analyze|x64'\" Label=\"PropertySheets\">\n- <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" />\n- </ImportGroup>\n- <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8.1 Debug|x64'\" Label=\"PropertySheets\">\n- <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" />\n- </ImportGroup>\n- <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8.1Analyze|x64'\" Label=\"PropertySheets\">\n- <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" />\n- </ImportGroup>\n- <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Win10 Debug|x64'\" Label=\"PropertySheets\">\n- <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" />\n- </ImportGroup>\n- <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Win10Analyze|x64'\" Label=\"PropertySheets\">\n- <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" />\n- </ImportGroup>\n- <ItemGroup Label=\"WrappedTaskItems\">\n- <ClInclude Include=\"..\\include\\OvsDpInterfaceCtExt.h\" />\n- <ClInclude Include=\"..\\include\\OvsDpInterfaceExt.h\" />\n- <ClInclude Include=\"Actions.h\" />\n- <ClInclude Include=\"Atomic.h\" />\n- <ClInclude Include=\"BufferMgmt.h\" />\n- <ClInclude Include=\"Conntrack-nat.h\" />\n- <ClInclude Include=\"Conntrack.h\" />\n- <ClInclude Include=\"Datapath.h\" />\n- <ClInclude Include=\"Debug.h\" />\n- <ClInclude Include=\"DpInternal.h\" />\n- <ClInclude Include=\"Ethernet.h\" />\n- <ClInclude Include=\"Event.h\" />\n- <ClInclude Include=\"Flow.h\" />\n- <ClInclude Include=\"Geneve.h\" />\n- <ClInclude Include=\"Gre.h\" />\n- <ClInclude Include=\"IpFragment.h\" />\n- <ClInclude Include=\"Ip6Fragment.h\" />\n- <ClInclude Include=\"IpHelper.h\" />\n- <ClInclude Include=\"Jhash.h\" />\n- <ClInclude Include=\"Meter.h\" />\n- <ClInclude Include=\"Mpls.h\" />\n- <ClInclude Include=\"Netlink/Netlink.h\" />\n- <ClInclude Include=\"Netlink/NetlinkBuf.h\" />\n- <ClInclude Include=\"Netlink/NetlinkProto.h\" />\n- <ClInclude Include=\"Netlink/NetlinkError.h\" />\n- <ClInclude Include=\"NetProto.h\" />\n- <ClInclude Include=\"Offload.h\" />\n- <ClInclude Include=\"Oid.h\" />\n- <ClInclude Include=\"PacketIO.h\" />\n- <ClInclude Include=\"PacketParser.h\" />\n- <ClInclude Include=\"precomp.h\" />\n- <ClInclude Include=\"Recirc.h\" />\n- <ClInclude Include=\"resource.h\" />\n- <ClInclude Include=\"Switch.h\" />\n- <ClInclude Include=\"Tunnel.h\" />\n- <ClInclude Include=\"TunnelIntf.h\" />\n- <ClInclude Include=\"Types.h\" />\n- <ClInclude Include=\"User.h\" />\n- <ClInclude Include=\"Util.h\" />\n- <ClInclude Include=\"Vport.h\" />\n- <ClInclude Include=\"Vxlan.h\" />\n- </ItemGroup>\n- <PropertyGroup>\n- <TargetName>OVSExt</TargetName>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win10 Release|x64'\">\n- <Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>\n- <ExternalIncludePath>$(CRT_IncludePath);$(KM_IncludePath);</ExternalIncludePath>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win10 Debug|x64'\">\n- <Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>\n- <ExternalIncludePath>$(CRT_IncludePath);$(KM_IncludePath);</ExternalIncludePath>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win10Analyze|x64'\">\n- <Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>\n- <CodeAnalysisRuleSet>..\\misc\\DriverRecommendedRules.ruleset</CodeAnalysisRuleSet>\n- <RunCodeAnalysis>true</RunCodeAnalysis>\n- <ExternalIncludePath>$(CRT_IncludePath);$(KM_IncludePath);</ExternalIncludePath>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8.1Analyze|x64'\">\n- <RunCodeAnalysis>true</RunCodeAnalysis>\n- <CodeAnalysisRuleSet>..\\misc\\DriverRecommendedRules.ruleset</CodeAnalysisRuleSet>\n- <ExternalIncludePath>$(CRT_IncludePath);$(KM_IncludePath);</ExternalIncludePath>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8Analyze|x64'\">\n- <RunCodeAnalysis>true</RunCodeAnalysis>\n- <CodeAnalysisRuleSet>..\\misc\\DriverRecommendedRules.ruleset</CodeAnalysisRuleSet>\n- <ExternalIncludePath>$(CRT_IncludePath);$(KM_IncludePath);</ExternalIncludePath>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8 Debug|x64'\">\n- <ExternalIncludePath>$(CRT_IncludePath);$(KM_IncludePath);</ExternalIncludePath>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8 Release|x64'\">\n- <ExternalIncludePath>$(CRT_IncludePath);$(KM_IncludePath);</ExternalIncludePath>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8.1 Debug|x64'\">\n- <ExternalIncludePath>$(CRT_IncludePath);$(KM_IncludePath);</ExternalIncludePath>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8.1 Release|x64'\">\n- <ExternalIncludePath>$(CRT_IncludePath);$(KM_IncludePath);</ExternalIncludePath>\n- </PropertyGroup>\n- <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8 Release|x64'\">\n- <ClCompile>\n- <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1;NDIS630=1</PreprocessorDefinitions>\n- </ClCompile>\n- <Midl>\n- <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1;NDIS630=1</PreprocessorDefinitions>\n- </Midl>\n- <ResourceCompile>\n- <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1;NDIS630=1</PreprocessorDefinitions>\n- </ResourceCompile>\n- </ItemDefinitionGroup>\n- <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8.1 Release|x64'\">\n- <ClCompile>\n- <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1;NDIS640=1</PreprocessorDefinitions>\n- </ClCompile>\n- <Midl>\n- <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1;NDIS640=1</PreprocessorDefinitions>\n- </Midl>\n- <ResourceCompile>\n- <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1;NDIS640=1</PreprocessorDefinitions>\n- </ResourceCompile>\n- </ItemDefinitionGroup>\n- <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Win10 Release|x64'\">\n- <ClCompile>\n- <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1;NDIS640=1</PreprocessorDefinitions>\n- </ClCompile>\n- <Midl>\n- <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1;NDIS640=1</PreprocessorDefinitions>\n- </Midl>\n- <ResourceCompile>\n- <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1;NDIS640=1</PreprocessorDefinitions>\n- </ResourceCompile>\n- </ItemDefinitionGroup>\n- <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8 Debug|x64'\">\n- <ClCompile>\n- <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1;NDIS630=1</PreprocessorDefinitions>\n- </ClCompile>\n- <Midl>\n- <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1;NDIS630=1</PreprocessorDefinitions>\n- </Midl>\n- <ResourceCompile>\n- <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1;NDIS630=1</PreprocessorDefinitions>\n- </ResourceCompile>\n- </ItemDefinitionGroup>\n- <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8Analyze|x64'\">\n- <ClCompile>\n- <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1;NDIS630=1</PreprocessorDefinitions>\n- </ClCompile>\n- <Midl>\n- <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1;NDIS630=1</PreprocessorDefinitions>\n- </Midl>\n- <ResourceCompile>\n- <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1;NDIS630=1</PreprocessorDefinitions>\n- </ResourceCompile>\n- </ItemDefinitionGroup>\n- <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8.1 Debug|x64'\">\n- <ClCompile>\n- <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1;NDIS640=1</PreprocessorDefinitions>\n- </ClCompile>\n- <Midl>\n- <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1;NDIS640=1</PreprocessorDefinitions>\n- </Midl>\n- <ResourceCompile>\n- <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1;NDIS640=1</PreprocessorDefinitions>\n- </ResourceCompile>\n- </ItemDefinitionGroup>\n- <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8.1Analyze|x64'\">\n- <ClCompile>\n- <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1;NDIS640=1</PreprocessorDefinitions>\n- </ClCompile>\n- <Midl>\n- <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1;NDIS640=1</PreprocessorDefinitions>\n- </Midl>\n- <ResourceCompile>\n- <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1;NDIS640=1</PreprocessorDefinitions>\n- </ResourceCompile>\n- </ItemDefinitionGroup>\n- <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Win10 Debug|x64'\">\n- <ClCompile>\n- <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1;NDIS640=1</PreprocessorDefinitions>\n- </ClCompile>\n- <Midl>\n- <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1;NDIS640=1</PreprocessorDefinitions>\n- </Midl>\n- <ResourceCompile>\n- <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1;NDIS640=1</PreprocessorDefinitions>\n- </ResourceCompile>\n- </ItemDefinitionGroup>\n- <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Win10Analyze|x64'\">\n- <ClCompile>\n- <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1;NDIS640=1</PreprocessorDefinitions>\n- </ClCompile>\n- <Midl>\n- <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1;NDIS640=1</PreprocessorDefinitions>\n- </Midl>\n- <ResourceCompile>\n- <PreprocessorDefinitions>%(PreprocessorDefinitions);NDIS_WDM=1;NDIS640=1</PreprocessorDefinitions>\n- </ResourceCompile>\n- </ItemDefinitionGroup>\n- <ItemDefinitionGroup>\n- <Link>\n- <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\\ndis.lib;$(DDK_LIB_PATH)\\fwpkclnt.lib;$(SDK_LIB_PATH)\\uuid.lib;$(DDK_LIB_PATH)\\netio.lib</AdditionalDependencies>\n- </Link>\n- <ClCompile>\n- <TreatWarningAsError>true</TreatWarningAsError>\n- <WarningLevel>Level4</WarningLevel>\n- <ExceptionHandling>\n- </ExceptionHandling>\n- <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Win8 Debug|x64'\">.;$(IntDir);%(AdditionalIncludeDirectories);..\\..</AdditionalIncludeDirectories>\n- <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Win8Analyze|x64'\">.;$(IntDir);%(AdditionalIncludeDirectories);..\\..</AdditionalIncludeDirectories>\n- <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Win8.1 Debug|x64'\">.;$(IntDir);%(AdditionalIncludeDirectories);..\\..</AdditionalIncludeDirectories>\n- <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Win8.1Analyze|x64'\">.;$(IntDir);%(AdditionalIncludeDirectories);..\\..</AdditionalIncludeDirectories>\n- <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Win10 Debug|x64'\">.;$(IntDir);%(AdditionalIncludeDirectories);..\\..;$(MSBuildProjectDirectory)</AdditionalIncludeDirectories>\n- <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Win10Analyze|x64'\">.;$(IntDir);%(AdditionalIncludeDirectories);..\\..;$(MSBuildProjectDirectory)</AdditionalIncludeDirectories>\n- <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Win8 Release|x64'\">.;$(IntDir);%(AdditionalIncludeDirectories);..\\..</AdditionalIncludeDirectories>\n- <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Win8.1 Release|x64'\">.;$(IntDir);%(AdditionalIncludeDirectories);..\\..</AdditionalIncludeDirectories>\n- <AdditionalIncludeDirectories Condition=\"'$(Configuration)|$(Platform)'=='Win10 Release|x64'\">.;$(IntDir);%(AdditionalIncludeDirectories);..\\..;$(MSBuildProjectDirectory)</AdditionalIncludeDirectories>\n- <MultiProcessorCompilation Condition=\"'$(Configuration)|$(Platform)'=='Win8 Release|x64'\">true</MultiProcessorCompilation>\n- <MultiProcessorCompilation Condition=\"'$(Configuration)|$(Platform)'=='Win8 Debug|x64'\">true</MultiProcessorCompilation>\n- <MultiProcessorCompilation Condition=\"'$(Configuration)|$(Platform)'=='Win8Analyze|x64'\">true</MultiProcessorCompilation>\n- <MultiProcessorCompilation Condition=\"'$(Configuration)|$(Platform)'=='Win8.1 Debug|x64'\">true</MultiProcessorCompilation>\n- <MultiProcessorCompilation Condition=\"'$(Configuration)|$(Platform)'=='Win8.1Analyze|x64'\">true</MultiProcessorCompilation>\n- <MultiProcessorCompilation Condition=\"'$(Configuration)|$(Platform)'=='Win10 Debug|x64'\">true</MultiProcessorCompilation>\n- <MultiProcessorCompilation Condition=\"'$(Configuration)|$(Platform)'=='Win10Analyze|x64'\">true</MultiProcessorCompilation>\n- <MultiProcessorCompilation Condition=\"'$(Configuration)|$(Platform)'=='Win8.1 Release|x64'\">true</MultiProcessorCompilation>\n- <MultiProcessorCompilation Condition=\"'$(Configuration)|$(Platform)'=='Win10 Release|x64'\">true</MultiProcessorCompilation>\n- <EnablePREfast Condition=\"'$(Configuration)|$(Platform)'=='Win8.1Analyze|x64'\">true</EnablePREfast>\n- <EnablePREfast Condition=\"'$(Configuration)|$(Platform)'=='Win8Analyze|x64'\">true</EnablePREfast>\n- <EnablePREfast Condition=\"'$(Configuration)|$(Platform)'=='Win10Analyze|x64'\">true</EnablePREfast>\n- </ClCompile>\n- <Inf>\n- <TimeStamp Condition=\"'$(Configuration)|$(Platform)'=='Win8 Debug|x64'\">$(Version)</TimeStamp>\n- <TimeStamp Condition=\"'$(Configuration)|$(Platform)'=='Win8Analyze|x64'\">$(Version)</TimeStamp>\n- </Inf>\n- <Inf>\n- <TimeStamp Condition=\"'$(Configuration)|$(Platform)'=='Win8.1 Debug|x64'\">$(Version)</TimeStamp>\n- <TimeStamp Condition=\"'$(Configuration)|$(Platform)'=='Win8.1Analyze|x64'\">$(Version)</TimeStamp>\n- </Inf>\n- <Inf>\n- <TimeStamp Condition=\"'$(Configuration)|$(Platform)'=='Win10 Debug|x64'\">$(Version)</TimeStamp>\n- <TimeStamp Condition=\"'$(Configuration)|$(Platform)'=='Win10Analyze|x64'\">$(Version)</TimeStamp>\n- </Inf>\n- <Inf>\n- <TimeStamp Condition=\"'$(Configuration)|$(Platform)'=='Win8 Release|x64'\">$(Version)</TimeStamp>\n- </Inf>\n- <Inf>\n- <TimeStamp Condition=\"'$(Configuration)|$(Platform)'=='Win8.1 Release|x64'\">$(Version)</TimeStamp>\n- </Inf>\n- <Inf>\n- <TimeStamp Condition=\"'$(Configuration)|$(Platform)'=='Win10 Release|x64'\">$(Version)</TimeStamp>\n- </Inf>\n- <DriverSign>\n- <FileDigestAlgorithm Condition=\"'$(Configuration)|$(Platform)'=='Win8 Release|x64'\">SHA256</FileDigestAlgorithm>\n- <FileDigestAlgorithm Condition=\"'$(Configuration)|$(Platform)'=='Win8 Debug|x64'\">SHA256</FileDigestAlgorithm>\n- <FileDigestAlgorithm Condition=\"'$(Configuration)|$(Platform)'=='Win8Analyze|x64'\">SHA256</FileDigestAlgorithm>\n- <FileDigestAlgorithm Condition=\"'$(Configuration)|$(Platform)'=='Win8.1 Debug|x64'\">SHA256</FileDigestAlgorithm>\n- <FileDigestAlgorithm Condition=\"'$(Configuration)|$(Platform)'=='Win8.1 Release|x64'\">SHA256</FileDigestAlgorithm>\n- <FileDigestAlgorithm Condition=\"'$(Configuration)|$(Platform)'=='Win8.1Analyze|x64'\">SHA256</FileDigestAlgorithm>\n- <FileDigestAlgorithm Condition=\"'$(Configuration)|$(Platform)'=='Win10Analyze|x64'\">SHA256</FileDigestAlgorithm>\n- <FileDigestAlgorithm Condition=\"'$(Configuration)|$(Platform)'=='Win10 Debug|x64'\">SHA256</FileDigestAlgorithm>\n- <FileDigestAlgorithm Condition=\"'$(Configuration)|$(Platform)'=='Win10 Release|x64'\">SHA256</FileDigestAlgorithm>\n- </DriverSign>\n- </ItemDefinitionGroup>\n- <ItemGroup>\n- <ClCompile Include=\"Actions.c\" />\n- <ClCompile Include=\"BufferMgmt.c\" />\n- <ClCompile Include=\"Conntrack-nat.c\" />\n- <ClCompile Include=\"Conntrack-related.c\" />\n- <ClCompile Include=\"Conntrack-ftp.c\" />\n- <ClCompile Include=\"Conntrack-icmp.c\" />\n- <ClCompile Include=\"Conntrack-other.c\" />\n- <ClCompile Include=\"Conntrack-tcp.c\" />\n- <ClCompile Include=\"Conntrack.c\" />\n- <ClCompile Include=\"Debug.c\" />\n- <ClCompile Include=\"Driver.c\" />\n- <ClCompile Include=\"Event.c\" />\n- <ClCompile Include=\"Flow.c\" />\n- <ClCompile Include=\"Geneve.c\" />\n- <ClCompile Include=\"Gre.c\" />\n- <ClCompile Include=\"IpFragment.c\" />\n- <ClCompile Include=\"Ip6Fragment.c\" />\n- <ClCompile Include=\"IpHelper.c\" />\n- <ClCompile Include=\"Jhash.c\" />\n- <ClCompile Include=\"Meter.c\" />\n- <ClCompile Include=\"Netlink/Netlink.c\" />\n- <ClCompile Include=\"Netlink/NetlinkBuf.c\" />\n- <ClCompile Include=\"Datapath.c\" />\n- <ClCompile Include=\"Offload.c\" />\n- <ClCompile Include=\"Oid.c\" />\n- <ClCompile Include=\"PacketIO.c\" />\n- <ClCompile Include=\"PacketParser.c\" />\n- <ClCompile Include=\"precompsrc.c\">\n- <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n- <PreCompiledHeaderFile>precomp.h</PreCompiledHeaderFile>\n- <PreCompiledHeader>Create</PreCompiledHeader>\n- <PreCompiledHeaderOutputFile>$(IntDir)\\precomp.h.pch</PreCompiledHeaderOutputFile>\n- </ClCompile>\n- <ClCompile Include=\"Recirc.c\" />\n- <ClCompile Include=\"Switch.c\" />\n- <ClCompile Include=\"Tunnel.c\" />\n- <ClCompile Include=\"TunnelFilter.c\" />\n- <ClCompile Include=\"User.c\" />\n- <ClCompile Include=\"Util.c\" />\n- <ClCompile Include=\"Vport.c\" />\n- <ClCompile Include=\"Vxlan.c\" />\n- <ResourceCompile Include=\"ovsext.rc\">\n- <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Win8 Release|x64'\">%(PreprocessorDefinitions);NDIS_WDM=1;NDIS630=1;VersionWithDots=$(Version);VersionWithCommas=$(Version.Replace('.',','))</PreprocessorDefinitions>\n- <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Win8 Debug|x64'\">%(PreprocessorDefinitions);NDIS_WDM=1;NDIS630=1;VersionWithDots=$(Version);VersionWithCommas=$(Version.Replace('.',','))</PreprocessorDefinitions>\n- <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Win8Analyze|x64'\">%(PreprocessorDefinitions);NDIS_WDM=1;NDIS630=1;VersionWithDots=$(Version);VersionWithCommas=$(Version.Replace('.',','))</PreprocessorDefinitions>\n- <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Win8.1 Release|x64'\">%(PreprocessorDefinitions);NDIS_WDM=1;NDIS640=1;VersionWithDots=$(Version);VersionWithCommas=$(Version.Replace('.',','))</PreprocessorDefinitions>\n- <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Win8.1 Debug|x64'\">%(PreprocessorDefinitions);NDIS_WDM=1;NDIS640=1;VersionWithDots=$(Version);VersionWithCommas=$(Version.Replace('.',','))</PreprocessorDefinitions>\n- <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Win8.1Analyze|x64'\">%(PreprocessorDefinitions);NDIS_WDM=1;NDIS640=1;VersionWithDots=$(Version);VersionWithCommas=$(Version.Replace('.',','))</PreprocessorDefinitions>\n- <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Win10 Release|x64'\">%(PreprocessorDefinitions);NDIS_WDM=1;NDIS640=1;VersionWithDots=$(Version);VersionWithCommas=$(Version.Replace('.',','))</PreprocessorDefinitions>\n- <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Win10 Debug|x64'\">%(PreprocessorDefinitions);NDIS_WDM=1;NDIS640=1;VersionWithDots=$(Version);VersionWithCommas=$(Version.Replace('.',','))</PreprocessorDefinitions>\n- <PreprocessorDefinitions Condition=\"'$(Configuration)|$(Platform)'=='Win10Analyze|x64'\">%(PreprocessorDefinitions);NDIS_WDM=1;NDIS640=1;VersionWithDots=$(Version);VersionWithCommas=$(Version.Replace('.',','))</PreprocessorDefinitions>\n- </ResourceCompile>\n- </ItemGroup>\n- <ItemGroup>\n- <Inf Exclude=\"@(Inf)\" Include=\"*.inf\" />\n- <FilesToPackage Include=\"$(TargetPath)\" />\n- </ItemGroup>\n- <ItemGroup>\n- <None Exclude=\"@(None)\" Include=\"*.txt;*.htm;*.html\" />\n- <None Exclude=\"@(None)\" Include=\"*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2\" />\n- <None Exclude=\"@(None)\" Include=\"*.def;*.bat;*.hpj;*.asmx\" />\n- </ItemGroup>\n- <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n-</Project>\ndiff --git a/datapath-windows/ovsext/ovsext.vcxproj.user b/datapath-windows/ovsext/ovsext.vcxproj.user\ndeleted file mode 100644\nindex 5b0c53539..000000000\n--- a/datapath-windows/ovsext/ovsext.vcxproj.user\n+++ /dev/null\n@@ -1,30 +0,0 @@\n-<?xml version=\"1.0\" encoding=\"utf-8\"?>\n-<Project ToolsVersion=\"12.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8 Debug|x64'\">\n- <SignMode>TestSign</SignMode>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8Analyze|x64'\">\n- <SignMode>TestSign</SignMode>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8.1 Debug|x64'\">\n- <SignMode>TestSign</SignMode>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8.1Analyze|x64'\">\n- <SignMode>TestSign</SignMode>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win10 Debug|x64'\">\n- <SignMode>TestSign</SignMode>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win10Analyze|x64'\">\n- <SignMode>TestSign</SignMode>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8 Release|x64'\">\n- <SignMode>TestSign</SignMode>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win8.1 Release|x64'\">\n- <SignMode>TestSign</SignMode>\n- </PropertyGroup>\n- <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Win10 Release|x64'\">\n- <SignMode>TestSign</SignMode>\n- </PropertyGroup>\n-</Project>\n\\ No newline at end of file\ndiff --git a/datapath-windows/ovsext/precomp.h b/datapath-windows/ovsext/precomp.h\ndeleted file mode 100644\nindex e9f62f6ab..000000000\n--- a/datapath-windows/ovsext/precomp.h\n+++ /dev/null\n@@ -1,34 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#include <ndis.h>\n-#include <netiodef.h>\n-#include <intsafe.h>\n-#include <ntintsafe.h>\n-#include <ntstrsafe.h>\n-#include <ip2string.h>\n-\n-#include \"Types.h\"\n-\n-#include \"..\\include\\OvsDpInterface.h\"\n-\n-#include \"Util.h\"\n-#include \"Netlink/NetlinkError.h\"\n-#include \"Netlink/Netlink.h\"\n-#include \"Netlink/NetlinkProto.h\"\n-#include \"..\\include\\OvsDpInterfaceExt.h\"\n-#include \"..\\include\\OvsDpInterfaceCtExt.h\"\n-#include \"DpInternal.h\"\ndiff --git a/datapath-windows/ovsext/precompsrc.c b/datapath-windows/ovsext/precompsrc.c\ndeleted file mode 100644\nindex 133b6872d..000000000\n--- a/datapath-windows/ovsext/precompsrc.c\n+++ /dev/null\n@@ -1,17 +0,0 @@\n-/*\n- * Copyright (c) 2014 VMware, Inc.\n- *\n- * Licensed under the Apache License, Version 2.0 (the \"License\");\n- * you may not use this file except in compliance with the License.\n- * You may obtain a copy of the License at:\n- *\n- * http://www.apache.org/licenses/LICENSE-2.0\n- *\n- * Unless required by applicable law or agreed to in writing, software\n- * distributed under the License is distributed on an \"AS IS\" BASIS,\n- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n- * See the License for the specific language governing permissions and\n- * limitations under the License.\n- */\n-\n-#include \"precomp.h\"\ndiff --git a/datapath-windows/ovsext/resource.h b/datapath-windows/ovsext/resource.h\ndeleted file mode 100644\nindex 2b35211e4..000000000\n--- a/datapath-windows/ovsext/resource.h\n+++ /dev/null\n@@ -1,1576 +0,0 @@\n-//{{NO_DEPENDENCIES}}\n-// Microsoft Visual C++ generated include file.\n-// Used by ovsext.rc\n-//\n-#define SW_HIDE 0\n-#define HIDE_WINDOW 0\n-#define WM_NULL 0x0000\n-#define WA_INACTIVE 0\n-#define HTNOWHERE 0\n-#define SMTO_NORMAL 0x0000\n-#define ICON_SMALL 0\n-#define SIZE_RESTORED 0\n-#define BN_CLICKED 0\n-#define BST_UNCHECKED 0x0000\n-#define HDS_HORZ 0x0000\n-#define TBSTYLE_BUTTON 0x0000\n-#define TBS_HORZ 0x0000\n-#define TBS_BOTTOM 0x0000\n-#define TBS_RIGHT 0x0000\n-#define LVS_ICON 0x0000\n-#define LVS_ALIGNTOP 0x0000\n-#define TCS_TABS 0x0000\n-#define TCS_SINGLELINE 0x0000\n-#define TCS_RIGHTJUSTIFY 0x0000\n-#define DTS_SHORTDATEFORMAT 0x0000\n-#define PGS_VERT 0x00000000\n-#define LANG_NEUTRAL 0x00\n-#define SUBLANG_NEUTRAL 0x00\n-#define SORT_DEFAULT 0x0\n-#define SORT_JAPANESE_XJIS 0x0\n-#define SORT_CHINESE_BIG5 0x0\n-#define SORT_CHINESE_PRCP 0x0\n-#define SORT_KOREAN_KSC 0x0\n-#define SORT_HUNGARIAN_DEFAULT 0x0\n-#define SORT_GEORGIAN_TRADITIONAL 0x0\n-#define _USE_DECLSPECS_FOR_SAL 0\n-#define _USE_ATTRIBUTES_FOR_SAL 0\n-#define __drv_typeConst 0\n-#define VER_DEBUG 0\n-#define VER_PRERELEASE 0\n-#define WINAPI_PARTITION_APP 1\n-#define CREATEPROCESS_MANIFEST_RESOURCE_ID 1\n-#define MINIMUM_RESERVED_MANIFEST_RESOURCE_ID 1\n-#define SW_SHOWNORMAL 1\n-#define SW_NORMAL 1\n-#define SHOW_OPENWINDOW 1\n-#define SW_PARENTCLOSING 1\n-#define VK_LBUTTON 0x01\n-#define WM_CREATE 0x0001\n-#define WA_ACTIVE 1\n-#define PWR_OK 1\n-#define PWR_SUSPENDREQUEST 1\n-#define NFR_ANSI 1\n-#define UIS_SET 1\n-#define UISF_HIDEFOCUS 0x1\n-#define XBUTTON1 0x0001\n-#define WMSZ_LEFT 1\n-#define HTCLIENT 1\n-#define SMTO_BLOCK 0x0001\n-#define MA_ACTIVATE 1\n-#define ICON_BIG 1\n-#define SIZE_MINIMIZED 1\n-#define MK_LBUTTON 0x0001\n-#define TME_HOVER 0x00000001\n-#define CS_VREDRAW 0x0001\n-#define CF_TEXT 1\n-#define SCF_ISSECURE 0x00000001\n-#define IDOK 1\n-#define BN_PAINT 1\n-#define BST_CHECKED 0x0001\n-#define TBSTYLE_SEP 0x0001\n-#define TTS_ALWAYSTIP 0x01\n-#define TBS_AUTOTICKS 0x0001\n-#define UDS_WRAP 0x0001\n-#define PBS_SMOOTH 0x01\n-#define LWS_TRANSPARENT 0x0001\n-#define LVS_REPORT 0x0001\n-#define TVS_HASBUTTONS 0x0001\n-#define TVS_EX_NOSINGLECOLLAPSE 0x0001\n-#define TCS_SCROLLOPPOSITE 0x0001\n-#define ACS_CENTER 0x0001\n-#define MCS_DAYSTATE 0x0001\n-#define DTS_UPDOWN 0x0001\n-#define PGS_HORZ 0x00000001\n-#define NFS_EDIT 0x0001\n-#define BCSIF_GLYPH 0x0001\n-#define BCSS_NOSPLIT 0x0001\n-#define LANG_ARABIC 0x01\n-#define SUBLANG_DEFAULT 0x01\n-#define SUBLANG_AFRIKAANS_SOUTH_AFRICA 0x01\n-#define SUBLANG_ALBANIAN_ALBANIA 0x01\n-#define SUBLANG_ALSATIAN_FRANCE 0x01\n-#define SUBLANG_AMHARIC_ETHIOPIA 0x01\n-#define SUBLANG_ARABIC_SAUDI_ARABIA 0x01\n-#define SUBLANG_ARMENIAN_ARMENIA 0x01\n-#define SUBLANG_ASSAMESE_INDIA 0x01\n-#define SUBLANG_AZERI_LATIN 0x01\n-#define SUBLANG_AZERBAIJANI_AZERBAIJAN_LATIN 0x01\n-#define SUBLANG_BANGLA_INDIA 0x01\n-#define SUBLANG_BASHKIR_RUSSIA 0x01\n-#define SUBLANG_BASQUE_BASQUE 0x01\n-#define SUBLANG_BELARUSIAN_BELARUS 0x01\n-#define SUBLANG_BENGALI_INDIA 0x01\n-#define SUBLANG_BRETON_FRANCE 0x01\n-#define SUBLANG_BULGARIAN_BULGARIA 0x01\n-#define SUBLANG_CATALAN_CATALAN 0x01\n-#define SUBLANG_CENTRAL_KURDISH_IRAQ 0x01\n-#define SUBLANG_CHEROKEE_CHEROKEE 0x01\n-#define SUBLANG_CHINESE_TRADITIONAL 0x01\n-#define SUBLANG_CORSICAN_FRANCE 0x01\n-#define SUBLANG_CZECH_CZECH_REPUBLIC 0x01\n-#define SUBLANG_CROATIAN_CROATIA 0x01\n-#define SUBLANG_DANISH_DENMARK 0x01\n-#define SUBLANG_DARI_AFGHANISTAN 0x01\n-#define SUBLANG_DIVEHI_MALDIVES 0x01\n-#define SUBLANG_DUTCH 0x01\n-#define SUBLANG_ENGLISH_US 0x01\n-#define SUBLANG_ESTONIAN_ESTONIA 0x01\n-#define SUBLANG_FAEROESE_FAROE_ISLANDS 0x01\n-#define SUBLANG_FILIPINO_PHILIPPINES 0x01\n-#define SUBLANG_FINNISH_FINLAND 0x01\n-#define SUBLANG_FRENCH 0x01\n-#define SUBLANG_FRISIAN_NETHERLANDS 0x01\n-#define SUBLANG_GALICIAN_GALICIAN 0x01\n-#define SUBLANG_GEORGIAN_GEORGIA 0x01\n-#define SUBLANG_GERMAN 0x01\n-#define SUBLANG_GREEK_GREECE 0x01\n-#define SUBLANG_GREENLANDIC_GREENLAND 0x01\n-#define SUBLANG_GUJARATI_INDIA 0x01\n-#define SUBLANG_HAUSA_NIGERIA_LATIN 0x01\n-#define SUBLANG_HAWAIIAN_US 0x01\n-#define SUBLANG_HEBREW_ISRAEL 0x01\n-#define SUBLANG_HINDI_INDIA 0x01\n-#define SUBLANG_HUNGARIAN_HUNGARY 0x01\n-#define SUBLANG_ICELANDIC_ICELAND 0x01\n-#define SUBLANG_IGBO_NIGERIA 0x01\n-#define SUBLANG_INDONESIAN_INDONESIA 0x01\n-#define SUBLANG_INUKTITUT_CANADA 0x01\n-#define SUBLANG_ITALIAN 0x01\n-#define SUBLANG_JAPANESE_JAPAN 0x01\n-#define SUBLANG_KANNADA_INDIA 0x01\n-#define SUBLANG_KAZAK_KAZAKHSTAN 0x01\n-#define SUBLANG_KHMER_CAMBODIA 0x01\n-#define SUBLANG_KICHE_GUATEMALA 0x01\n-#define SUBLANG_KINYARWANDA_RWANDA 0x01\n-#define SUBLANG_KONKANI_INDIA 0x01\n-#define SUBLANG_KOREAN 0x01\n-#define SUBLANG_KYRGYZ_KYRGYZSTAN 0x01\n-#define SUBLANG_LAO_LAO 0x01\n-#define SUBLANG_LATVIAN_LATVIA 0x01\n-#define SUBLANG_LITHUANIAN 0x01\n-#define SUBLANG_LUXEMBOURGISH_LUXEMBOURG 0x01\n-#define SUBLANG_MACEDONIAN_MACEDONIA 0x01\n-#define SUBLANG_MALAY_MALAYSIA 0x01\n-#define SUBLANG_MALAYALAM_INDIA 0x01\n-#define SUBLANG_MALTESE_MALTA 0x01\n-#define SUBLANG_MAORI_NEW_ZEALAND 0x01\n-#define SUBLANG_MAPUDUNGUN_CHILE 0x01\n-#define SUBLANG_MARATHI_INDIA 0x01\n-#define SUBLANG_MOHAWK_MOHAWK 0x01\n-#define SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA 0x01\n-#define SUBLANG_NEPALI_NEPAL 0x01\n-#define SUBLANG_NORWEGIAN_BOKMAL 0x01\n-#define SUBLANG_OCCITAN_FRANCE 0x01\n-#define SUBLANG_ODIA_INDIA 0x01\n-#define SUBLANG_ORIYA_INDIA 0x01\n-#define SUBLANG_PASHTO_AFGHANISTAN 0x01\n-#define SUBLANG_PERSIAN_IRAN 0x01\n-#define SUBLANG_POLISH_POLAND 0x01\n-#define SUBLANG_PORTUGUESE_BRAZILIAN 0x01\n-#define SUBLANG_PUNJABI_INDIA 0x01\n-#define SUBLANG_QUECHUA_BOLIVIA 0x01\n-#define SUBLANG_ROMANIAN_ROMANIA 0x01\n-#define SUBLANG_ROMANSH_SWITZERLAND 0x01\n-#define SUBLANG_RUSSIAN_RUSSIA 0x01\n-#define SUBLANG_SAKHA_RUSSIA 0x01\n-#define SUBLANG_SAMI_NORTHERN_NORWAY 0x01\n-#define SUBLANG_SANSKRIT_INDIA 0x01\n-#define SUBLANG_SCOTTISH_GAELIC 0x01\n-#define SUBLANG_SERBIAN_CROATIA 0x01\n-#define SUBLANG_SINDHI_INDIA 0x01\n-#define SUBLANG_SINHALESE_SRI_LANKA 0x01\n-#define SUBLANG_SOTHO_NORTHERN_SOUTH_AFRICA 0x01\n-#define SUBLANG_SLOVAK_SLOVAKIA 0x01\n-#define SUBLANG_SLOVENIAN_SLOVENIA 0x01\n-#define SUBLANG_SPANISH 0x01\n-#define SUBLANG_SWAHILI_KENYA 0x01\n-#define SUBLANG_SWEDISH 0x01\n-#define SUBLANG_SYRIAC_SYRIA 0x01\n-#define SUBLANG_TAJIK_TAJIKISTAN 0x01\n-#define SUBLANG_TAMIL_INDIA 0x01\n-#define SUBLANG_TATAR_RUSSIA 0x01\n-#define SUBLANG_TELUGU_INDIA 0x01\n-#define SUBLANG_THAI_THAILAND 0x01\n-#define SUBLANG_TIBETAN_PRC 0x01\n-#define SUBLANG_TIGRINYA_ETHIOPIA 0x01\n-#define SUBLANG_TSWANA_SOUTH_AFRICA 0x01\n-#define SUBLANG_TURKISH_TURKEY 0x01\n-#define SUBLANG_TURKMEN_TURKMENISTAN 0x01\n-#define SUBLANG_UIGHUR_PRC 0x01\n-#define SUBLANG_UKRAINIAN_UKRAINE 0x01\n-#define SUBLANG_UPPER_SORBIAN_GERMANY 0x01\n-#define SUBLANG_URDU_PAKISTAN 0x01\n-#define SUBLANG_UZBEK_LATIN 0x01\n-#define SUBLANG_VIETNAMESE_VIETNAM 0x01\n-#define SUBLANG_WELSH_UNITED_KINGDOM 0x01\n-#define SUBLANG_WOLOF_SENEGAL 0x01\n-#define SUBLANG_XHOSA_SOUTH_AFRICA 0x01\n-#define SUBLANG_YAKUT_RUSSIA 0x01\n-#define SUBLANG_YI_PRC 0x01\n-#define SUBLANG_YORUBA_NIGERIA 0x01\n-#define SUBLANG_ZULU_SOUTH_AFRICA 0x01\n-#define SORT_INVARIANT_MATH 0x1\n-#define SORT_JAPANESE_UNICODE 0x1\n-#define SORT_CHINESE_UNICODE 0x1\n-#define SORT_KOREAN_UNICODE 0x1\n-#define SORT_GERMAN_PHONE_BOOK 0x1\n-#define SORT_HUNGARIAN_TECHNICAL 0x1\n-#define SORT_GEORGIAN_MODERN 0x1\n-#define __drv_typeCond 1\n-#define VS_VERSION_INFO 1\n-#define VFFF_ISSHAREDFILE 0x0001\n-#define VFF_CURNEDEST 0x0001\n-#define VIFF_FORCEINSTALL 0x0001\n-#define WINAPI_FAMILY_PC_APP 2\n-#define ISOLATIONAWARE_MANIFEST_RESOURCE_ID 2\n-#define SW_SHOWMINIMIZED 2\n-#define SHOW_ICONWINDOW 2\n-#define SW_OTHERZOOM 2\n-#define VK_RBUTTON 0x02\n-#define WM_DESTROY 0x0002\n-#define WA_CLICKACTIVE 2\n-#define PWR_SUSPENDRESUME 2\n-#define NFR_UNICODE 2\n-#define UIS_CLEAR 2\n-#define UISF_HIDEACCEL 0x2\n-#define XBUTTON2 0x0002\n-#define WMSZ_RIGHT 2\n-#define HTCAPTION 2\n-#define SMTO_ABORTIFHUNG 0x0002\n-#define MA_ACTIVATEANDEAT 2\n-#define ICON_SMALL2 2\n-#define SIZE_MAXIMIZED 2\n-#define MK_RBUTTON 0x0002\n-#define TME_LEAVE 0x00000002\n-#define CS_HREDRAW 0x0002\n-#define CF_BITMAP 2\n-#define IDCANCEL 2\n-#define BN_HILITE 2\n-#define BST_INDETERMINATE 0x0002\n-#define HDS_BUTTONS 0x0002\n-#define TBSTYLE_CHECK 0x0002\n-#define TTS_NOPREFIX 0x02\n-#define TBS_VERT 0x0002\n-#define UDS_SETBUDDYINT 0x0002\n-#define LWS_IGNORERETURN 0x0002\n-#define LVS_SMALLICON 0x0002\n-#define TVS_HASLINES 0x0002\n-#define TVS_EX_MULTISELECT 0x0002\n-#define TCS_BOTTOM 0x0002\n-#define TCS_RIGHT 0x0002\n-#define ACS_TRANSPARENT 0x0002\n-#define MCS_MULTISELECT 0x0002\n-#define DTS_SHOWNONE 0x0002\n-#define PGS_AUTOSCROLL 0x00000002\n-#define NFS_STATIC 0x0002\n-#define BCSIF_IMAGE 0x0002\n-#define BCSS_STRETCH 0x0002\n-#define LANG_BULGARIAN 0x02\n-#define SUBLANG_SYS_DEFAULT 0x02\n-#define SUBLANG_ARABIC_IRAQ 0x02\n-#define SUBLANG_AZERI_CYRILLIC 0x02\n-#define SUBLANG_AZERBAIJANI_AZERBAIJAN_CYRILLIC 0x02\n-#define SUBLANG_BANGLA_BANGLADESH 0x02\n-#define SUBLANG_BENGALI_BANGLADESH 0x02\n-#define SUBLANG_CHINESE_SIMPLIFIED 0x02\n-#define SUBLANG_DUTCH_BELGIAN 0x02\n-#define SUBLANG_ENGLISH_UK 0x02\n-#define SUBLANG_FRENCH_BELGIAN 0x02\n-#define SUBLANG_FULAH_SENEGAL 0x02\n-#define SUBLANG_GERMAN_SWISS 0x02\n-#define SUBLANG_INUKTITUT_CANADA_LATIN 0x02\n-#define SUBLANG_IRISH_IRELAND 0x02\n-#define SUBLANG_ITALIAN_SWISS 0x02\n-#define SUBLANG_KASHMIRI_SASIA 0x02\n-#define SUBLANG_KASHMIRI_INDIA 0x02\n-#define SUBLANG_LOWER_SORBIAN_GERMANY 0x02\n-#define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0x02\n-#define SUBLANG_MONGOLIAN_PRC 0x02\n-#define SUBLANG_NEPALI_INDIA 0x02\n-#define SUBLANG_NORWEGIAN_NYNORSK 0x02\n-#define SUBLANG_PORTUGUESE 0x02\n-#define SUBLANG_PULAR_SENEGAL 0x02\n-#define SUBLANG_PUNJABI_PAKISTAN 0x02\n-#define SUBLANG_QUECHUA_ECUADOR 0x02\n-#define SUBLANG_SAMI_NORTHERN_SWEDEN 0x02\n-#define SUBLANG_SERBIAN_LATIN 0x02\n-#define SUBLANG_SINDHI_PAKISTAN 0x02\n-#define SUBLANG_SINDHI_AFGHANISTAN 0x02\n-#define SUBLANG_SPANISH_MEXICAN 0x02\n-#define SUBLANG_SWEDISH_FINLAND 0x02\n-#define SUBLANG_TAMAZIGHT_ALGERIA_LATIN 0x02\n-#define SUBLANG_TAMIL_SRI_LANKA 0x02\n-#define SUBLANG_TIGRIGNA_ERITREA 0x02\n-#define SUBLANG_TIGRINYA_ERITREA 0x02\n-#define SUBLANG_TSWANA_BOTSWANA 0x02\n-#define SUBLANG_URDU_INDIA 0x02\n-#define SUBLANG_UZBEK_CYRILLIC 0x02\n-#define SUBLANG_VALENCIAN_VALENCIA 0x02\n-#define SORT_CHINESE_PRC 0x2\n-#define __drv_typeBitset 2\n-#define VFF_FILEINUSE 0x0002\n-#define VIFF_DONTDELETEOLD 0x0002\n-#define WINAPI_FAMILY_PHONE_APP 3\n-#define ISOLATIONAWARE_NOSTATICIMPORT_MANIFEST_RESOURCE_ID 3\n-#define SW_SHOWMAXIMIZED 3\n-#define SW_MAXIMIZE 3\n-#define SHOW_FULLSCREEN 3\n-#define SW_PARENTOPENING 3\n-#define VK_CANCEL 0x03\n-#define WM_MOVE 0x0003\n-#define PWR_CRITICALRESUME 3\n-#define NF_QUERY 3\n-#define UIS_INITIALIZE 3\n-#define WMSZ_TOP 3\n-#define HTSYSMENU 3\n-#define MA_NOACTIVATE 3\n-#define SIZE_MAXSHOW 3\n-#define CF_METAFILEPICT 3\n-#define IDABORT 3\n-#define BN_UNHILITE 3\n-#define LVS_LIST 0x0003\n-#define LVS_TYPEMASK 0x0003\n-#define LANG_CATALAN 0x03\n-#define LANG_VALENCIAN 0x03\n-#define SUBLANG_CUSTOM_DEFAULT 0x03\n-#define SUBLANG_ARABIC_EGYPT 0x03\n-#define SUBLANG_CHINESE_HONGKONG 0x03\n-#define SUBLANG_ENGLISH_AUS 0x03\n-#define SUBLANG_FRENCH_CANADIAN 0x03\n-#define SUBLANG_GERMAN_AUSTRIAN 0x03\n-#define SUBLANG_QUECHUA_PERU 0x03\n-#define SUBLANG_SAMI_NORTHERN_FINLAND 0x03\n-#define SUBLANG_SERBIAN_CYRILLIC 0x03\n-#define SUBLANG_SPANISH_MODERN 0x03\n-#define SORT_CHINESE_BOPOMOFO 0x3\n-#define __drv_typeExpr 3\n-#define VER_PRODUCTMINORVERSION 3\n-#define SW_SHOWNOACTIVATE 4\n-#define SHOW_OPENNOACTIVATE 4\n-#define SW_OTHERUNZOOM 4\n-#define VK_MBUTTON 0x04\n-#define NF_REQUERY 4\n-#define UISF_ACTIVE 0x4\n-#define WMSZ_TOPLEFT 4\n-#define HTGROWBOX 4\n-#define MA_NOACTIVATEANDEAT 4\n-#define SIZE_MAXHIDE 4\n-#define MK_SHIFT 0x0004\n-#define CF_SYLK 4\n-#define IDRETRY 4\n-#define BN_DISABLE 4\n-#define BST_PUSHED 0x0004\n-#define HDS_HOTTRACK 0x0004\n-#define TBSTYLE_GROUP 0x0004\n-#define TBS_TOP 0x0004\n-#define TBS_LEFT 0x0004\n-#define UDS_ALIGNRIGHT 0x0004\n-#define PBS_VERTICAL 0x04\n-#define LWS_NOPREFIX 0x0004\n-#define LVS_SINGLESEL 0x0004\n-#define TVS_LINESATROOT 0x0004\n-#define TVS_EX_DOUBLEBUFFER 0x0004\n-#define TCS_MULTISELECT 0x0004\n-#define ACS_AUTOPLAY 0x0004\n-#define MCS_WEEKNUMBERS 0x0004\n-#define DTS_LONGDATEFORMAT 0x0004\n-#define PGS_DRAGNDROP 0x00000004\n-#define NFS_LISTCOMBO 0x0004\n-#define BCSIF_STYLE 0x0004\n-#define BCSS_ALIGNLEFT 0x0004\n-#define LANG_CHINESE 0x04\n-#define LANG_CHINESE_SIMPLIFIED 0x04\n-#define SUBLANG_CUSTOM_UNSPECIFIED 0x04\n-#define SUBLANG_ARABIC_LIBYA 0x04\n-#define SUBLANG_CHINESE_SINGAPORE 0x04\n-#define SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN 0x04\n-#define SUBLANG_ENGLISH_CAN 0x04\n-#define SUBLANG_FRENCH_SWISS 0x04\n-#define SUBLANG_GERMAN_LUXEMBOURG 0x04\n-#define SUBLANG_SAMI_LULE_NORWAY 0x04\n-#define SUBLANG_SPANISH_GUATEMALA 0x04\n-#define SUBLANG_TAMAZIGHT_MOROCCO_TIFINAGH 0x04\n-#define SORT_JAPANESE_RADICALSTROKE 0x4\n-#define SORT_CHINESE_RADICALSTROKE 0x4\n-#define VFF_BUFFTOOSMALL 0x0004\n-#define SW_SHOW 5\n-#define VK_XBUTTON1 0x05\n-#define WM_SIZE 0x0005\n-#define WMSZ_TOPRIGHT 5\n-#define HTMENU 5\n-#define CF_DIF 5\n-#define IDIGNORE 5\n-#define BN_DOUBLECLICKED 5\n-#define LANG_CZECH 0x05\n-#define SUBLANG_UI_CUSTOM_DEFAULT 0x05\n-#define SUBLANG_ARABIC_ALGERIA 0x05\n-#define SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN 0x05\n-#define SUBLANG_CHINESE_MACAU 0x05\n-#define SUBLANG_ENGLISH_NZ 0x05\n-#define SUBLANG_FRENCH_LUXEMBOURG 0x05\n-#define SUBLANG_GERMAN_LIECHTENSTEIN 0x05\n-#define SUBLANG_SAMI_LULE_SWEDEN 0x05\n-#define SUBLANG_SPANISH_COSTA_RICA 0x05\n-#define SW_MINIMIZE 6\n-#define VK_XBUTTON2 0x06\n-#define WM_ACTIVATE 0x0006\n-#define WMSZ_BOTTOM 6\n-#define HTHSCROLL 6\n-#define CF_TIFF 6\n-#define IDYES 6\n-#define BN_SETFOCUS 6\n-#define LANG_DANISH 0x06\n-#define SUBLANG_ARABIC_MOROCCO 0x06\n-#define SUBLANG_ENGLISH_EIRE 0x06\n-#define SUBLANG_FRENCH_MONACO 0x06\n-#define SUBLANG_SAMI_SOUTHERN_NORWAY 0x06\n-#define SUBLANG_SERBIAN_BOSNIA_HERZEGOVINA_LATIN 0x06\n-#define SUBLANG_SPANISH_PANAMA 0x06\n-#define VER_PRODUCTMAJORVERSION 6\n-#define SW_SHOWMINNOACTIVE 7\n-#define WM_SETFOCUS 0x0007\n-#define WMSZ_BOTTOMLEFT 7\n-#define HTVSCROLL 7\n-#define CF_OEMTEXT 7\n-#define IDNO 7\n-#define BN_KILLFOCUS 7\n-#define LANG_GERMAN 0x07\n-#define SUBLANG_ARABIC_TUNISIA 0x07\n-#define SUBLANG_ENGLISH_SOUTH_AFRICA 0x07\n-#define SUBLANG_SAMI_SOUTHERN_SWEDEN 0x07\n-#define SUBLANG_SERBIAN_BOSNIA_HERZEGOVINA_CYRILLIC 0x07\n-#define SUBLANG_SPANISH_DOMINICAN_REPUBLIC 0x07\n-#define SW_SHOWNA 8\n-#define VK_BACK 0x08\n-#define WM_KILLFOCUS 0x0008\n-#define WMSZ_BOTTOMRIGHT 8\n-#define HTMINBUTTON 8\n-#define SMTO_NOTIMEOUTIFNOTHUNG 0x0008\n-#define MK_CONTROL 0x0008\n-#define CS_DBLCLKS 0x0008\n-#define CF_DIB 8\n-#define IDCLOSE 8\n-#define BST_FOCUS 0x0008\n-#define HDS_HIDDEN 0x0008\n-#define TBSTYLE_DROPDOWN 0x0008\n-#define TBS_BOTH 0x0008\n-#define UDS_ALIGNLEFT 0x0008\n-#define PBS_MARQUEE 0x08\n-#define LWS_USEVISUALSTYLE 0x0008\n-#define LVS_SHOWSELALWAYS 0x0008\n-#define TVS_EDITLABELS 0x0008\n-#define TVS_EX_NOINDENTSTATE 0x0008\n-#define TCS_FLATBUTTONS 0x0008\n-#define ACS_TIMER 0x0008\n-#define MCS_NOTODAYCIRCLE 0x0008\n-#define NFS_BUTTON 0x0008\n-#define BCSIF_SIZE 0x0008\n-#define BCSS_IMAGE 0x0008\n-#define LANG_GREEK 0x08\n-#define SUBLANG_ARABIC_OMAN 0x08\n-#define SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC 0x08\n-#define SUBLANG_ENGLISH_JAMAICA 0x08\n-#define SUBLANG_SAMI_SKOLT_FINLAND 0x08\n-#define SUBLANG_SPANISH_VENEZUELA 0x08\n-#define SW_RESTORE 9\n-#define VK_TAB 0x09\n-#define HTMAXBUTTON 9\n-#define CF_PALETTE 9\n-#define IDHELP 9\n-#define DTS_TIMEFORMAT 0x0009\n-#define LANG_ENGLISH 0x09\n-#define SUBLANG_ARABIC_YEMEN 0x09\n-#define SUBLANG_ENGLISH_CARIBBEAN 0x09\n-#define SUBLANG_SAMI_INARI_FINLAND 0x09\n-#define SUBLANG_SERBIAN_SERBIA_LATIN 0x09\n-#define SUBLANG_SPANISH_COLOMBIA 0x09\n-#define SW_SHOWDEFAULT 10\n-#define WM_ENABLE 0x000A\n-#define HTLEFT 10\n-#define CF_PENDATA 10\n-#define IDTRYAGAIN 10\n-#define HELP_CONTEXTMENU 0x000a\n-#define LANG_SPANISH 0x0a\n-#define SUBLANG_ARABIC_SYRIA 0x0a\n-#define SUBLANG_ENGLISH_BELIZE 0x0a\n-#define SUBLANG_SERBIAN_SERBIA_CYRILLIC 0x0a\n-#define SUBLANG_SPANISH_PERU 0x0a\n-#define SW_FORCEMINIMIZE 11\n-#define SW_MAX 11\n-#define WM_SETREDRAW 0x000B\n-#define HTRIGHT 11\n-#define CF_RIFF 11\n-#define IDCONTINUE 11\n-#define HELP_FINDER 0x000b\n-#define LANG_FINNISH 0x0b\n-#define SUBLANG_ARABIC_JORDAN 0x0b\n-#define SUBLANG_ENGLISH_TRINIDAD 0x0b\n-#define SUBLANG_SERBIAN_MONTENEGRO_LATIN 0x0b\n-#define SUBLANG_SPANISH_ARGENTINA 0x0b\n-#define VK_CLEAR 0x0C\n-#define WM_SETTEXT 0x000C\n-#define HTTOP 12\n-#define CF_WAVE 12\n-#define HELP_WM_HELP 0x000c\n-#define DTS_SHORTDATECENTURYFORMAT 0x000C\n-#define LANG_FRENCH 0x0c\n-#define SUBLANG_ARABIC_LEBANON 0x0c\n-#define SUBLANG_ENGLISH_ZIMBABWE 0x0c\n-#define SUBLANG_SERBIAN_MONTENEGRO_CYRILLIC 0x0c\n-#define SUBLANG_SPANISH_ECUADOR 0x0c\n-#define VK_RETURN 0x0D\n-#define WM_GETTEXT 0x000D\n-#define HTTOPLEFT 13\n-#define CF_UNICODETEXT 13\n-#define HELP_SETPOPUP_POS 0x000d\n-#define LANG_HEBREW 0x0d\n-#define SUBLANG_ARABIC_KUWAIT 0x0d\n-#define SUBLANG_ENGLISH_PHILIPPINES 0x0d\n-#define SUBLANG_SPANISH_CHILE 0x0d\n-#define WM_GETTEXTLENGTH 0x000E\n-#define HTTOPRIGHT 14\n-#define CF_ENHMETAFILE 14\n-#define LANG_HUNGARIAN 0x0e\n-#define SUBLANG_ARABIC_UAE 0x0e\n-#define SUBLANG_SPANISH_URUGUAY 0x0e\n-#define WM_PAINT 0x000F\n-#define HTBOTTOM 15\n-#define CF_HDROP 15\n-#define LANG_ICELANDIC 0x0f\n-#define SUBLANG_ARABIC_BAHRAIN 0x0f\n-#define SUBLANG_SPANISH_PARAGUAY 0x0f\n-#define MAXIMUM_RESERVED_MANIFEST_RESOURCE_ID 16\n-#define VK_SHIFT 0x10\n-#define WM_CLOSE 0x0010\n-#define HTBOTTOMLEFT 16\n-#define WVR_ALIGNTOP 0x0010\n-#define MK_MBUTTON 0x0010\n-#define TME_NONCLIENT 0x00000010\n-#define CF_LOCALE 16\n-#define HELP_TCARD_DATA 0x0010\n-#define TBSTYLE_AUTOSIZE 0x0010\n-#define TTS_NOANIMATE 0x10\n-#define TBS_NOTICKS 0x0010\n-#define UDS_AUTOBUDDY 0x0010\n-#define PBS_SMOOTHREVERSE 0x10\n-#define LWS_USECUSTOMTEXT 0x0010\n-#define LVS_SORTASCENDING 0x0010\n-#define TVS_DISABLEDRAGDROP 0x0010\n-#define TVS_EX_RICHTOOLTIP 0x0010\n-#define TCS_FORCEICONLEFT 0x0010\n-#define MCS_NOTODAY 0x0010\n-#define DTS_APPCANPARSE 0x0010\n-#define NFS_ALL 0x0010\n-#define LANG_ITALIAN 0x10\n-#define SUBLANG_ARABIC_QATAR 0x10\n-#define SUBLANG_ENGLISH_INDIA 0x10\n-#define SUBLANG_SPANISH_BOLIVIA 0x10\n-#define VK_CONTROL 0x11\n-#define WM_QUERYENDSESSION 0x0011\n-#define HTBOTTOMRIGHT 17\n-#define CF_DIBV5 17\n-#define HELP_TCARD_OTHER_CALLER 0x0011\n-#define LANG_JAPANESE 0x11\n-#define SUBLANG_ENGLISH_MALAYSIA 0x11\n-#define SUBLANG_SPANISH_EL_SALVADOR 0x11\n-#define VK_MENU 0x12\n-#define WM_QUIT 0x0012\n-#define HTBORDER 18\n-#define CF_MAX 18\n-#define LANG_KOREAN 0x12\n-#define SUBLANG_ENGLISH_SINGAPORE 0x12\n-#define SUBLANG_SPANISH_HONDURAS 0x12\n-#define VK_PAUSE 0x13\n-#define WM_QUERYOPEN 0x0013\n-#define HTOBJECT 19\n-#define LANG_DUTCH 0x13\n-#define SUBLANG_SPANISH_NICARAGUA 0x13\n-#define VK_CAPITAL 0x14\n-#define WM_ERASEBKGND 0x0014\n-#define HTCLOSE 20\n-#define LANG_NORWEGIAN 0x14\n-#define SUBLANG_SPANISH_PUERTO_RICO 0x14\n-#define _SAL_VERSION 20\n-#define VK_KANA 0x15\n-#define VK_HANGEUL 0x15\n-#define VK_HANGUL 0x15\n-#define WM_SYSCOLORCHANGE 0x0015\n-#define HTHELP 21\n-#define LANG_POLISH 0x15\n-#define SUBLANG_SPANISH_US 0x15\n-#define WM_ENDSESSION 0x0016\n-#define LANG_PORTUGUESE 0x16\n-#define VK_JUNJA 0x17\n-#define LANG_ROMANSH 0x17\n-#define RT_MANIFEST 24\n-#define VK_FINAL 0x18\n-#define WM_SHOWWINDOW 0x0018\n-#define LANG_ROMANIAN 0x18\n-#define VK_HANJA 0x19\n-#define VK_KANJI 0x19\n-#define LANG_RUSSIAN 0x19\n-#define WM_WININICHANGE 0x001A\n-#define LANG_BOSNIAN 0x1a\n-#define LANG_CROATIAN 0x1a\n-#define LANG_SERBIAN 0x1a\n-#define VK_ESCAPE 0x1B\n-#define WM_DEVMODECHANGE 0x001B\n-#define LANG_SLOVAK 0x1b\n-#define VK_CONVERT 0x1C\n-#define WM_ACTIVATEAPP 0x001C\n-#define LANG_ALBANIAN 0x1c\n-#define VK_NONCONVERT 0x1D\n-#define WM_FONTCHANGE 0x001D\n-#define LANG_SWEDISH 0x1d\n-#define VK_ACCEPT 0x1E\n-#define WM_TIMECHANGE 0x001E\n-#define LANG_THAI 0x1e\n-#define VK_MODECHANGE 0x1F\n-#define WM_CANCELMODE 0x001F\n-#define LANG_TURKISH 0x1f\n-#define VK_SPACE 0x20\n-#define WM_SETCURSOR 0x0020\n-#define SMTO_ERRORONEXIT 0x0020\n-#define WVR_ALIGNLEFT 0x0020\n-#define MK_XBUTTON1 0x0020\n-#define CS_OWNDC 0x0020\n-#define TBSTYLE_NOPREFIX 0x0020\n-#define TTS_NOFADE 0x20\n-#define TBS_ENABLESELRANGE 0x0020\n-#define UDS_ARROWKEYS 0x0020\n-#define LWS_RIGHT 0x0020\n-#define LVS_SORTDESCENDING 0x0020\n-#define TVS_SHOWSELALWAYS 0x0020\n-#define TVS_EX_AUTOHSCROLL 0x0020\n-#define TCS_FORCELABELLEFT 0x0020\n-#define DTS_RIGHTALIGN 0x0020\n-#define NFS_USEFONTASSOC 0x0020\n-#define LANG_URDU 0x20\n-#define VK_PRIOR 0x21\n-#define WM_MOUSEACTIVATE 0x0021\n-#define LANG_INDONESIAN 0x21\n-#define VK_NEXT 0x22\n-#define WM_CHILDACTIVATE 0x0022\n-#define LANG_UKRAINIAN 0x22\n-#define VK_END 0x23\n-#define WM_QUEUESYNC 0x0023\n-#define LANG_BELARUSIAN 0x23\n-#define VK_HOME 0x24\n-#define WM_GETMINMAXINFO 0x0024\n-#define LANG_SLOVENIAN 0x24\n-#define VK_LEFT 0x25\n-#define LANG_ESTONIAN 0x25\n-#define VK_UP 0x26\n-#define WM_PAINTICON 0x0026\n-#define LANG_LATVIAN 0x26\n-#define VK_RIGHT 0x27\n-#define WM_ICONERASEBKGND 0x0027\n-#define LANG_LITHUANIAN 0x27\n-#define VK_DOWN 0x28\n-#define WM_NEXTDLGCTL 0x0028\n-#define LANG_TAJIK 0x28\n-#define VK_SELECT 0x29\n-#define LANG_FARSI 0x29\n-#define LANG_PERSIAN 0x29\n-#define VK_PRINT 0x2A\n-#define WM_SPOOLERSTATUS 0x002A\n-#define LANG_VIETNAMESE 0x2a\n-#define VK_EXECUTE 0x2B\n-#define WM_DRAWITEM 0x002B\n-#define LANG_ARMENIAN 0x2b\n-#define VK_SNAPSHOT 0x2C\n-#define WM_MEASUREITEM 0x002C\n-#define LANG_AZERI 0x2c\n-#define LANG_AZERBAIJANI 0x2c\n-#define VK_INSERT 0x2D\n-#define WM_DELETEITEM 0x002D\n-#define LANG_BASQUE 0x2d\n-#define VK_DELETE 0x2E\n-#define WM_VKEYTOITEM 0x002E\n-#define LANG_LOWER_SORBIAN 0x2e\n-#define LANG_UPPER_SORBIAN 0x2e\n-#define VK_HELP 0x2F\n-#define WM_CHARTOITEM 0x002F\n-#define LANG_MACEDONIAN 0x2f\n-#define WM_SETFONT 0x0030\n-#define WM_GETFONT 0x0031\n-#define WM_SETHOTKEY 0x0032\n-#define LANG_TSWANA 0x32\n-#define WM_GETHOTKEY 0x0033\n-#define LANG_XHOSA 0x34\n-#define LANG_ZULU 0x35\n-#define LANG_AFRIKAANS 0x36\n-#define WM_QUERYDRAGICON 0x0037\n-#define LANG_GEORGIAN 0x37\n-#define LANG_FAEROESE 0x38\n-#define WM_COMPAREITEM 0x0039\n-#define LANG_HINDI 0x39\n-#define LANG_MALTESE 0x3a\n-#define LANG_SAMI 0x3b\n-#define LANG_IRISH 0x3c\n-#define WM_GETOBJECT 0x003D\n-#define LANG_MALAY 0x3e\n-#define LANG_KAZAK 0x3f\n-#define WVR_ALIGNBOTTOM 0x0040\n-#define MK_XBUTTON2 0x0040\n-#define CS_CLASSDC 0x0040\n-#define HDS_DRAGDROP 0x0040\n-#define BTNS_SHOWTEXT 0x0040\n-#define TTS_BALLOON 0x40\n-#define TBS_FIXEDLENGTH 0x0040\n-#define UDS_HORZ 0x0040\n-#define LVS_SHAREIMAGELISTS 0x0040\n-#define TVS_RTLREADING 0x0040\n-#define TVS_EX_FADEINOUTEXPANDOS 0x0040\n-#define TCS_HOTTRACK 0x0040\n-#define MCS_NOTRAILINGDATES 0x0040\n-#define LANG_KYRGYZ 0x40\n-#define WM_COMPACTING 0x0041\n-#define LANG_SWAHILI 0x41\n-#define LANG_TURKMEN 0x42\n-#define LANG_UZBEK 0x43\n-#define WM_COMMNOTIFY 0x0044\n-#define LANG_TATAR 0x44\n-#define LANG_BANGLA 0x45\n-#define LANG_BENGALI 0x45\n-#define WM_WINDOWPOSCHANGING 0x0046\n-#define LANG_PUNJABI 0x46\n-#define WM_WINDOWPOSCHANGED 0x0047\n-#define LANG_GUJARATI 0x47\n-#define WM_POWER 0x0048\n-#define LANG_ODIA 0x48\n-#define LANG_ORIYA 0x48\n-#define LANG_TAMIL 0x49\n-#define WM_COPYDATA 0x004A\n-#define LANG_TELUGU 0x4a\n-#define WM_CANCELJOURNAL 0x004B\n-#define LANG_KANNADA 0x4b\n-#define LANG_MALAYALAM 0x4c\n-#define LANG_ASSAMESE 0x4d\n-#define WM_NOTIFY 0x004E\n-#define LANG_MARATHI 0x4e\n-#define LANG_SANSKRIT 0x4f\n-#define WM_INPUTLANGCHANGEREQUEST 0x0050\n-#define LANG_MONGOLIAN 0x50\n-#define WM_INPUTLANGCHANGE 0x0051\n-#define LANG_TIBETAN 0x51\n-#define WM_TCARD 0x0052\n-#define LANG_WELSH 0x52\n-#define WM_HELP 0x0053\n-#define LANG_KHMER 0x53\n-#define WM_USERCHANGED 0x0054\n-#define LANG_LAO 0x54\n-#define WM_NOTIFYFORMAT 0x0055\n-#define LANG_GALICIAN 0x56\n-#define LANG_KONKANI 0x57\n-#define LANG_MANIPURI 0x58\n-#define LANG_SINDHI 0x59\n-#define LANG_SYRIAC 0x5a\n-#define VK_LWIN 0x5B\n-#define LANG_SINHALESE 0x5b\n-#define VK_RWIN 0x5C\n-#define LANG_CHEROKEE 0x5c\n-#define VK_APPS 0x5D\n-#define LANG_INUKTITUT 0x5d\n-#define LANG_AMHARIC 0x5e\n-#define VK_SLEEP 0x5F\n-#define LANG_TAMAZIGHT 0x5f\n-#define VK_NUMPAD0 0x60\n-#define LANG_KASHMIRI 0x60\n-#define VK_NUMPAD1 0x61\n-#define LANG_NEPALI 0x61\n-#define VK_NUMPAD2 0x62\n-#define LANG_FRISIAN 0x62\n-#define VK_NUMPAD3 0x63\n-#define LANG_PASHTO 0x63\n-#define WINAPI_FAMILY_DESKTOP_APP 100\n-#define VK_NUMPAD4 0x64\n-#define LANG_FILIPINO 0x64\n-#define VS_USER_DEFINED 100\n-#define VK_NUMPAD5 0x65\n-#define LANG_DIVEHI 0x65\n-#define VK_NUMPAD6 0x66\n-#define VK_NUMPAD7 0x67\n-#define LANG_FULAH 0x67\n-#define LANG_PULAR 0x67\n-#define VK_NUMPAD8 0x68\n-#define LANG_HAUSA 0x68\n-#define VK_NUMPAD9 0x69\n-#define VK_MULTIPLY 0x6A\n-#define LANG_YORUBA 0x6a\n-#define VK_ADD 0x6B\n-#define LANG_QUECHUA 0x6b\n-#define VK_SEPARATOR 0x6C\n-#define LANG_SOTHO 0x6c\n-#define VK_SUBTRACT 0x6D\n-#define LANG_BASHKIR 0x6d\n-#define VK_DECIMAL 0x6E\n-#define LANG_LUXEMBOURGISH 0x6e\n-#define VK_DIVIDE 0x6F\n-#define LANG_GREENLANDIC 0x6f\n-#define VK_F1 0x70\n-#define LANG_IGBO 0x70\n-#define VK_F2 0x71\n-#define VK_F3 0x72\n-#define VK_F4 0x73\n-#define LANG_TIGRIGNA 0x73\n-#define LANG_TIGRINYA 0x73\n-#define VK_F5 0x74\n-#define VK_F6 0x75\n-#define LANG_HAWAIIAN 0x75\n-#define VK_F7 0x76\n-#define VK_F8 0x77\n-#define VK_F9 0x78\n-#define WHEEL_DELTA 120\n-#define LANG_YI 0x78\n-#define VK_F10 0x79\n-#define VK_F11 0x7A\n-#define LANG_MAPUDUNGUN 0x7a\n-#define VK_F12 0x7B\n-#define WM_CONTEXTMENU 0x007B\n-#define VK_F13 0x7C\n-#define WM_STYLECHANGING 0x007C\n-#define LANG_MOHAWK 0x7c\n-#define VK_F14 0x7D\n-#define WM_STYLECHANGED 0x007D\n-#define VK_F15 0x7E\n-#define WM_DISPLAYCHANGE 0x007E\n-#define LANG_BRETON 0x7e\n-#define VK_F16 0x7F\n-#define WM_GETICON 0x007F\n-#define LANG_INVARIANT 0x7f\n-#define VK_F17 0x80\n-#define WM_SETICON 0x0080\n-#define WVR_ALIGNRIGHT 0x0080\n-#define CS_PARENTDC 0x0080\n-#define CF_OWNERDISPLAY 0x0080\n-#define HDS_FULLDRAG 0x0080\n-#define BTNS_WHOLEDROPDOWN 0x0080\n-#define TTS_CLOSE 0x80\n-#define TBS_NOTHUMB 0x0080\n-#define UDS_NOTHOUSANDS 0x0080\n-#define LVS_NOLABELWRAP 0x0080\n-#define TVS_NOTOOLTIPS 0x0080\n-#define TVS_EX_PARTIALCHECKBOXES 0x0080\n-#define TCS_VERTICAL 0x0080\n-#define MCS_SHORTDAYSOFWEEK 0x0080\n-#define LANG_UIGHUR 0x80\n-#define VK_F18 0x81\n-#define WM_NCCREATE 0x0081\n-#define CF_DSPTEXT 0x0081\n-#define LANG_MAORI 0x81\n-#define VK_F19 0x82\n-#define WM_NCDESTROY 0x0082\n-#define CF_DSPBITMAP 0x0082\n-#define LANG_OCCITAN 0x82\n-#define VK_F20 0x83\n-#define WM_NCCALCSIZE 0x0083\n-#define CF_DSPMETAFILEPICT 0x0083\n-#define LANG_CORSICAN 0x83\n-#define VK_F21 0x84\n-#define WM_NCHITTEST 0x0084\n-#define LANG_ALSATIAN 0x84\n-#define VK_F22 0x85\n-#define WM_NCPAINT 0x0085\n-#define LANG_SAKHA 0x85\n-#define LANG_YAKUT 0x85\n-#define VK_F23 0x86\n-#define WM_NCACTIVATE 0x0086\n-#define LANG_KICHE 0x86\n-#define VK_F24 0x87\n-#define WM_GETDLGCODE 0x0087\n-#define LANG_KINYARWANDA 0x87\n-#define WM_SYNCPAINT 0x0088\n-#define LANG_WOLOF 0x88\n-#define LANG_DARI 0x8c\n-#define CF_DSPENHMETAFILE 0x008E\n-#define VK_NUMLOCK 0x90\n-#define VK_SCROLL 0x91\n-#define LANG_SCOTTISH_GAELIC 0x91\n-#define VK_OEM_NEC_EQUAL 0x92\n-#define VK_OEM_FJ_JISHO 0x92\n-#define LANG_CENTRAL_KURDISH 0x92\n-#define VK_OEM_FJ_MASSHOU 0x93\n-#define VK_OEM_FJ_TOUROKU 0x94\n-#define VK_OEM_FJ_LOYA 0x95\n-#define VK_OEM_FJ_ROYA 0x96\n-#define VK_LSHIFT 0xA0\n-#define WM_NCMOUSEMOVE 0x00A0\n-#define VK_RSHIFT 0xA1\n-#define WM_NCLBUTTONDOWN 0x00A1\n-#define VK_LCONTROL 0xA2\n-#define WM_NCLBUTTONUP 0x00A2\n-#define VK_RCONTROL 0xA3\n-#define WM_NCLBUTTONDBLCLK 0x00A3\n-#define VK_LMENU 0xA4\n-#define WM_NCRBUTTONDOWN 0x00A4\n-#define VK_RMENU 0xA5\n-#define WM_NCRBUTTONUP 0x00A5\n-#define VK_BROWSER_BACK 0xA6\n-#define WM_NCRBUTTONDBLCLK 0x00A6\n-#define VK_BROWSER_FORWARD 0xA7\n-#define WM_NCMBUTTONDOWN 0x00A7\n-#define VK_BROWSER_REFRESH 0xA8\n-#define WM_NCMBUTTONUP 0x00A8\n-#define VK_BROWSER_STOP 0xA9\n-#define WM_NCMBUTTONDBLCLK 0x00A9\n-#define VK_BROWSER_SEARCH 0xAA\n-#define VK_BROWSER_FAVORITES 0xAB\n-#define WM_NCXBUTTONDOWN 0x00AB\n-#define VK_BROWSER_HOME 0xAC\n-#define WM_NCXBUTTONUP 0x00AC\n-#define VK_VOLUME_MUTE 0xAD\n-#define WM_NCXBUTTONDBLCLK 0x00AD\n-#define VK_VOLUME_DOWN 0xAE\n-#define VK_VOLUME_UP 0xAF\n-#define VK_MEDIA_NEXT_TRACK 0xB0\n-#define EM_GETSEL 0x00B0\n-#define VK_MEDIA_PREV_TRACK 0xB1\n-#define EM_SETSEL 0x00B1\n-#define VK_MEDIA_STOP 0xB2\n-#define EM_GETRECT 0x00B2\n-#define VK_MEDIA_PLAY_PAUSE 0xB3\n-#define EM_SETRECT 0x00B3\n-#define VK_LAUNCH_MAIL 0xB4\n-#define EM_SETRECTNP 0x00B4\n-#define VK_LAUNCH_MEDIA_SELECT 0xB5\n-#define EM_SCROLL 0x00B5\n-#define VK_LAUNCH_APP1 0xB6\n-#define EM_LINESCROLL 0x00B6\n-#define VK_LAUNCH_APP2 0xB7\n-#define EM_SCROLLCARET 0x00B7\n-#define EM_GETMODIFY 0x00B8\n-#define EM_SETMODIFY 0x00B9\n-#define VK_OEM_1 0xBA\n-#define EM_GETLINECOUNT 0x00BA\n-#define VK_OEM_PLUS 0xBB\n-#define EM_LINEINDEX 0x00BB\n-#define VK_OEM_COMMA 0xBC\n-#define EM_SETHANDLE 0x00BC\n-#define VK_OEM_MINUS 0xBD\n-#define EM_GETHANDLE 0x00BD\n-#define VK_OEM_PERIOD 0xBE\n-#define EM_GETTHUMB 0x00BE\n-#define VK_OEM_2 0xBF\n-#define VK_OEM_3 0xC0\n-#define EM_LINELENGTH 0x00C1\n-#define EM_REPLACESEL 0x00C2\n-#define EM_GETLINE 0x00C4\n-#define EM_LIMITTEXT 0x00C5\n-#define EM_CANUNDO 0x00C6\n-#define EM_UNDO 0x00C7\n-#define EM_FMTLINES 0x00C8\n-#define EM_LINEFROMCHAR 0x00C9\n-#define EM_SETTABSTOPS 0x00CB\n-#define EM_SETPASSWORDCHAR 0x00CC\n-#define EM_EMPTYUNDOBUFFER 0x00CD\n-#define EM_GETFIRSTVISIBLELINE 0x00CE\n-#define EM_SETREADONLY 0x00CF\n-#define EM_SETWORDBREAKPROC 0x00D0\n-#define EM_GETWORDBREAKPROC 0x00D1\n-#define EM_GETPASSWORDCHAR 0x00D2\n-#define EM_SETMARGINS 0x00D3\n-#define EM_GETMARGINS 0x00D4\n-#define EM_GETLIMITTEXT 0x00D5\n-#define EM_POSFROMCHAR 0x00D6\n-#define EM_CHARFROMPOS 0x00D7\n-#define EM_SETIMESTATUS 0x00D8\n-#define EM_GETIMESTATUS 0x00D9\n-#define VK_OEM_4 0xDB\n-#define VK_OEM_5 0xDC\n-#define VK_OEM_6 0xDD\n-#define VK_OEM_7 0xDE\n-#define VK_OEM_8 0xDF\n-#define VK_OEM_AX 0xE1\n-#define VK_OEM_102 0xE2\n-#define VK_ICO_HELP 0xE3\n-#define VK_ICO_00 0xE4\n-#define VK_PROCESSKEY 0xE5\n-#define VK_ICO_CLEAR 0xE6\n-#define VK_PACKET 0xE7\n-#define VK_OEM_RESET 0xE9\n-#define VK_OEM_JUMP 0xEA\n-#define VK_OEM_PA1 0xEB\n-#define VK_OEM_PA2 0xEC\n-#define VK_OEM_PA3 0xED\n-#define VK_OEM_WSCTRL 0xEE\n-#define VK_OEM_CUSEL 0xEF\n-#define VK_OEM_ATTN 0xF0\n-#define BM_GETCHECK 0x00F0\n-#define VK_OEM_FINISH 0xF1\n-#define BM_SETCHECK 0x00F1\n-#define VK_OEM_COPY 0xF2\n-#define BM_GETSTATE 0x00F2\n-#define VK_OEM_AUTO 0xF3\n-#define BM_SETSTATE 0x00F3\n-#define VK_OEM_ENLW 0xF4\n-#define BM_SETSTYLE 0x00F4\n-#define VK_OEM_BACKTAB 0xF5\n-#define BM_CLICK 0x00F5\n-#define VK_ATTN 0xF6\n-#define BM_GETIMAGE 0x00F6\n-#define VK_CRSEL 0xF7\n-#define BM_SETIMAGE 0x00F7\n-#define VK_EXSEL 0xF8\n-#define BM_SETDONTCLICK 0x00F8\n-#define VK_EREOF 0xF9\n-#define VK_PLAY 0xFA\n-#define VK_ZOOM 0xFB\n-#define VK_NONAME 0xFC\n-#define VK_PA1 0xFD\n-#define VK_OEM_CLEAR 0xFE\n-#define WM_INPUT_DEVICE_CHANGE 0x00FE\n-#define SUBVERSION_MASK 0x000000FF\n-#define WM_INPUT 0x00FF\n-#define WM_KEYFIRST 0x0100\n-#define WM_KEYDOWN 0x0100\n-#define WVR_HREDRAW 0x0100\n-#define HDS_FILTERBAR 0x0100\n-#define TBSTYLE_TOOLTIPS 0x0100\n-#define RBS_TOOLTIPS 0x00000100\n-#define TTS_USEVISUALSTYLE 0x100\n-#define SBARS_SIZEGRIP 0x0100\n-#define TBS_TOOLTIPS 0x0100\n-#define UDS_HOTTRACK 0x0100\n-#define LVS_AUTOARRANGE 0x0100\n-#define TVS_CHECKBOXES 0x0100\n-#define TVS_EX_EXCLUSIONCHECKBOXES 0x0100\n-#define TCS_BUTTONS 0x0100\n-#define MCS_NOSELCHANGEONNAV 0x0100\n-#define WM_KEYUP 0x0101\n-#define WM_CHAR 0x0102\n-#define WM_DEADCHAR 0x0103\n-#define WM_SYSKEYDOWN 0x0104\n-#define WM_SYSKEYUP 0x0105\n-#define WM_SYSCHAR 0x0106\n-#define WM_SYSDEADCHAR 0x0107\n-#define WM_UNICHAR 0x0109\n-#define WM_KEYLAST 0x0109\n-#define WM_IME_STARTCOMPOSITION 0x010D\n-#define WM_IME_ENDCOMPOSITION 0x010E\n-#define WM_IME_COMPOSITION 0x010F\n-#define WM_IME_KEYLAST 0x010F\n-#define WM_INITDIALOG 0x0110\n-#define WM_COMMAND 0x0111\n-#define WM_SYSCOMMAND 0x0112\n-#define WM_TIMER 0x0113\n-#define WM_HSCROLL 0x0114\n-#define WM_VSCROLL 0x0115\n-#define WM_INITMENU 0x0116\n-#define WM_INITMENUPOPUP 0x0117\n-#define WM_GESTURE 0x0119\n-#define WM_GESTURENOTIFY 0x011A\n-#define WM_MENUSELECT 0x011F\n-#define WM_MENUCHAR 0x0120\n-#define WM_ENTERIDLE 0x0121\n-#define WM_MENURBUTTONUP 0x0122\n-#define WM_MENUDRAG 0x0123\n-#define WM_MENUGETOBJECT 0x0124\n-#define WM_UNINITMENUPOPUP 0x0125\n-#define WM_MENUCOMMAND 0x0126\n-#define WM_CHANGEUISTATE 0x0127\n-#define WM_UPDATEUISTATE 0x0128\n-#define WM_QUERYUISTATE 0x0129\n-#define WM_CTLCOLORMSGBOX 0x0132\n-#define WM_CTLCOLOREDIT 0x0133\n-#define WM_CTLCOLORLISTBOX 0x0134\n-#define WM_CTLCOLORBTN 0x0135\n-#define WM_CTLCOLORDLG 0x0136\n-#define WM_CTLCOLORSCROLLBAR 0x0137\n-#define WM_CTLCOLORSTATIC 0x0138\n-#define MN_GETHMENU 0x01E1\n-#define _WIN32_IE_IE20 0x0200\n-#define WM_MOUSEFIRST 0x0200\n-#define WM_MOUSEMOVE 0x0200\n-#define WVR_VREDRAW 0x0200\n-#define CS_NOCLOSE 0x0200\n-#define CF_PRIVATEFIRST 0x0200\n-#define HDS_FLAT 0x0200\n-#define TBSTYLE_WRAPABLE 0x0200\n-#define RBS_VARHEIGHT 0x00000200\n-#define TBS_REVERSED 0x0200\n-#define LVS_EDITLABELS 0x0200\n-#define TVS_TRACKSELECT 0x0200\n-#define TVS_EX_DIMMEDCHECKBOXES 0x0200\n-#define TCS_MULTILINE 0x0200\n-#define WM_LBUTTONDOWN 0x0201\n-#define WM_LBUTTONUP 0x0202\n-#define WM_LBUTTONDBLCLK 0x0203\n-#define WM_RBUTTONDOWN 0x0204\n-#define WM_RBUTTONUP 0x0205\n-#define WM_RBUTTONDBLCLK 0x0206\n-#define WM_MBUTTONDOWN 0x0207\n-#define WM_MBUTTONUP 0x0208\n-#define WM_MBUTTONDBLCLK 0x0209\n-#define WM_MOUSEWHEEL 0x020A\n-#define WM_XBUTTONDOWN 0x020B\n-#define WM_XBUTTONUP 0x020C\n-#define WM_XBUTTONDBLCLK 0x020D\n-#define WM_MOUSEHWHEEL 0x020E\n-#define WM_MOUSELAST 0x020E\n-#define WM_PARENTNOTIFY 0x0210\n-#define WM_ENTERMENULOOP 0x0211\n-#define WM_EXITMENULOOP 0x0212\n-#define WM_NEXTMENU 0x0213\n-#define WM_SIZING 0x0214\n-#define WM_CAPTURECHANGED 0x0215\n-#define WM_MOVING 0x0216\n-#define WM_POWERBROADCAST 0x0218\n-#define WM_DEVICECHANGE 0x0219\n-#define WM_MDICREATE 0x0220\n-#define WM_MDIDESTROY 0x0221\n-#define WM_MDIACTIVATE 0x0222\n-#define WM_MDIRESTORE 0x0223\n-#define WM_MDINEXT 0x0224\n-#define WM_MDIMAXIMIZE 0x0225\n-#define WM_MDITILE 0x0226\n-#define WM_MDICASCADE 0x0227\n-#define WM_MDIICONARRANGE 0x0228\n-#define WM_MDIGETACTIVE 0x0229\n-#define WM_MDISETMENU 0x0230\n-#define WM_ENTERSIZEMOVE 0x0231\n-#define WM_EXITSIZEMOVE 0x0232\n-#define WM_DROPFILES 0x0233\n-#define WM_MDIREFRESHMENU 0x0234\n-#define WM_POINTERDEVICECHANGE 0x238\n-#define WM_POINTERDEVICEINRANGE 0x239\n-#define WM_POINTERDEVICEOUTOFRANGE 0x23A\n-#define WM_TOUCH 0x0240\n-#define WM_NCPOINTERUPDATE 0x0241\n-#define WM_NCPOINTERDOWN 0x0242\n-#define WM_NCPOINTERUP 0x0243\n-#define WM_POINTERUPDATE 0x0245\n-#define WM_POINTERDOWN 0x0246\n-#define WM_POINTERUP 0x0247\n-#define WM_POINTERENTER 0x0249\n-#define WM_POINTERLEAVE 0x024A\n-#define WM_POINTERACTIVATE 0x024B\n-#define WM_POINTERCAPTURECHANGED 0x024C\n-#define WM_TOUCHHITTESTING 0x024D\n-#define WM_POINTERWHEEL 0x024E\n-#define WM_POINTERHWHEEL 0x024F\n-#define DM_POINTERHITTEST 0x0250\n-#define WM_IME_SETCONTEXT 0x0281\n-#define WM_IME_NOTIFY 0x0282\n-#define WM_IME_CONTROL 0x0283\n-#define WM_IME_COMPOSITIONFULL 0x0284\n-#define WM_IME_SELECT 0x0285\n-#define WM_IME_CHAR 0x0286\n-#define WM_IME_REQUEST 0x0288\n-#define WM_IME_KEYDOWN 0x0290\n-#define WM_IME_KEYUP 0x0291\n-#define WM_NCMOUSEHOVER 0x02A0\n-#define WM_MOUSEHOVER 0x02A1\n-#define WM_NCMOUSELEAVE 0x02A2\n-#define WM_MOUSELEAVE 0x02A3\n-#define WM_WTSSESSION_CHANGE 0x02B1\n-#define WM_TABLET_FIRST 0x02c0\n-#define WM_TABLET_LAST 0x02df\n-#define WM_DPICHANGED 0x02E0\n-#define CF_PRIVATELAST 0x02FF\n-#define _WIN32_IE_IE30 0x0300\n-#define WM_CUT 0x0300\n-#define CF_GDIOBJFIRST 0x0300\n-#define WM_COPY 0x0301\n-#define _WIN32_IE_IE302 0x0302\n-#define WM_PASTE 0x0302\n-#define WM_CLEAR 0x0303\n-#define WM_UNDO 0x0304\n-#define WM_RENDERFORMAT 0x0305\n-#define WM_RENDERALLFORMATS 0x0306\n-#define WM_DESTROYCLIPBOARD 0x0307\n-#define WM_DRAWCLIPBOARD 0x0308\n-#define WM_PAINTCLIPBOARD 0x0309\n-#define WM_VSCROLLCLIPBOARD 0x030A\n-#define WM_SIZECLIPBOARD 0x030B\n-#define WM_ASKCBFORMATNAME 0x030C\n-#define WM_CHANGECBCHAIN 0x030D\n-#define WM_HSCROLLCLIPBOARD 0x030E\n-#define WM_QUERYNEWPALETTE 0x030F\n-#define WM_PALETTEISCHANGING 0x0310\n-#define WM_PALETTECHANGED 0x0311\n-#define WM_HOTKEY 0x0312\n-#define WM_PRINT 0x0317\n-#define WM_PRINTCLIENT 0x0318\n-#define WM_APPCOMMAND 0x0319\n-#define WM_THEMECHANGED 0x031A\n-#define WM_CLIPBOARDUPDATE 0x031D\n-#define WM_DWMCOMPOSITIONCHANGED 0x031E\n-#define WM_DWMNCRENDERINGCHANGED 0x031F\n-#define WM_DWMCOLORIZATIONCOLORCHANGED 0x0320\n-#define WM_DWMWINDOWMAXIMIZEDCHANGE 0x0321\n-#define WM_DWMSENDICONICTHUMBNAIL 0x0323\n-#define WM_DWMSENDICONICLIVEPREVIEWBITMAP 0x0326\n-#define WM_GETTITLEBARINFOEX 0x033F\n-#define WM_HANDHELDFIRST 0x0358\n-#define WM_HANDHELDLAST 0x035F\n-#define WM_AFXFIRST 0x0360\n-#define WM_AFXLAST 0x037F\n-#define WM_PENWINFIRST 0x0380\n-#define WM_PENWINLAST 0x038F\n-#define WM_DDE_FIRST 0x03E0\n-#define CF_GDIOBJLAST 0x03FF\n-#define _WIN32_WINNT_NT4 0x0400\n-#define _WIN32_IE_IE40 0x0400\n-#define WM_USER 0x0400\n-#define WVR_VALIDRECTS 0x0400\n-#define HDS_CHECKBOXES 0x0400\n-#define TBSTYLE_ALTDRAG 0x0400\n-#define RBS_BANDBORDERS 0x00000400\n-#define TBS_DOWNISLEFT 0x0400\n-#define LVS_OWNERDRAWFIXED 0x0400\n-#define TVS_SINGLEEXPAND 0x0400\n-#define TVS_EX_DRAWIMAGEASYNC 0x0400\n-#define TCS_FIXEDWIDTH 0x0400\n-#define ctlFirst 0x0400\n-#define psh1 0x0400\n-#define _WIN32_IE_IE401 0x0401\n-#define psh2 0x0401\n-#define psh3 0x0402\n-#define psh4 0x0403\n-#define psh5 0x0404\n-#define psh6 0x0405\n-#define psh7 0x0406\n-#define psh8 0x0407\n-#define psh9 0x0408\n-#define psh10 0x0409\n-#define psh11 0x040a\n-#define psh12 0x040b\n-#define psh13 0x040c\n-#define psh14 0x040d\n-#define psh15 0x040e\n-#define psh16 0x040f\n-#define _WIN32_WINDOWS 0x0410\n-#define chx1 0x0410\n-#define chx2 0x0411\n-#define chx3 0x0412\n-#define chx4 0x0413\n-#define chx5 0x0414\n-#define chx6 0x0415\n-#define chx7 0x0416\n-#define chx8 0x0417\n-#define chx9 0x0418\n-#define chx10 0x0419\n-#define chx11 0x041a\n-#define chx12 0x041b\n-#define chx13 0x041c\n-#define chx14 0x041d\n-#define chx15 0x041e\n-#define chx16 0x041f\n-#define rad1 0x0420\n-#define rad2 0x0421\n-#define rad3 0x0422\n-#define rad4 0x0423\n-#define rad5 0x0424\n-#define rad6 0x0425\n-#define rad7 0x0426\n-#define rad8 0x0427\n-#define rad9 0x0428\n-#define rad10 0x0429\n-#define rad11 0x042a\n-#define rad12 0x042b\n-#define rad13 0x042c\n-#define rad14 0x042d\n-#define rad15 0x042e\n-#define rad16 0x042f\n-#define grp1 0x0430\n-#define grp2 0x0431\n-#define grp3 0x0432\n-#define grp4 0x0433\n-#define frm1 0x0434\n-#define frm2 0x0435\n-#define frm3 0x0436\n-#define frm4 0x0437\n-#define rct1 0x0438\n-#define rct2 0x0439\n-#define rct3 0x043a\n-#define rct4 0x043b\n-#define ico1 0x043c\n-#define ico2 0x043d\n-#define ico3 0x043e\n-#define ico4 0x043f\n-#define stc1 0x0440\n-#define stc2 0x0441\n-#define stc3 0x0442\n-#define stc4 0x0443\n-#define stc5 0x0444\n-#define stc6 0x0445\n-#define stc7 0x0446\n-#define stc8 0x0447\n-#define stc9 0x0448\n-#define stc10 0x0449\n-#define stc11 0x044a\n-#define stc12 0x044b\n-#define stc13 0x044c\n-#define stc14 0x044d\n-#define stc15 0x044e\n-#define stc16 0x044f\n-#define stc17 0x0450\n-#define stc18 0x0451\n-#define stc19 0x0452\n-#define stc20 0x0453\n-#define stc21 0x0454\n-#define stc22 0x0455\n-#define stc23 0x0456\n-#define stc24 0x0457\n-#define stc25 0x0458\n-#define stc26 0x0459\n-#define stc27 0x045a\n-#define stc28 0x045b\n-#define stc29 0x045c\n-#define stc30 0x045d\n-#define stc31 0x045e\n-#define stc32 0x045f\n-#define lst1 0x0460\n-#define lst2 0x0461\n-#define lst3 0x0462\n-#define lst4 0x0463\n-#define lst5 0x0464\n-#define lst6 0x0465\n-#define lst7 0x0466\n-#define lst8 0x0467\n-#define lst9 0x0468\n-#define lst10 0x0469\n-#define lst11 0x046a\n-#define lst12 0x046b\n-#define lst13 0x046c\n-#define lst14 0x046d\n-#define lst15 0x046e\n-#define lst16 0x046f\n-#define cmb1 0x0470\n-#define cmb2 0x0471\n-#define cmb3 0x0472\n-#define cmb4 0x0473\n-#define cmb5 0x0474\n-#define cmb6 0x0475\n-#define cmb7 0x0476\n-#define cmb8 0x0477\n-#define cmb9 0x0478\n-#define cmb10 0x0479\n-#define cmb11 0x047a\n-#define cmb12 0x047b\n-#define cmb13 0x047c\n-#define cmb14 0x047d\n-#define cmb15 0x047e\n-#define cmb16 0x047f\n-#define edt1 0x0480\n-#define edt2 0x0481\n-#define edt3 0x0482\n-#define edt4 0x0483\n-#define edt5 0x0484\n-#define edt6 0x0485\n-#define edt7 0x0486\n-#define edt8 0x0487\n-#define edt9 0x0488\n-#define edt10 0x0489\n-#define edt11 0x048a\n-#define edt12 0x048b\n-#define edt13 0x048c\n-#define edt14 0x048d\n-#define edt15 0x048e\n-#define edt16 0x048f\n-#define scr1 0x0490\n-#define scr2 0x0491\n-#define scr3 0x0492\n-#define scr4 0x0493\n-#define scr5 0x0494\n-#define scr6 0x0495\n-#define scr7 0x0496\n-#define scr8 0x0497\n-#define ctl1 0x04A0\n-#define ctlLast 0x04ff\n-#define _WIN32_WINNT_WIN2K 0x0500\n-#define _WIN32_IE_IE50 0x0500\n-#define _WIN32_WINNT_WINXP 0x0501\n-#define _WIN32_IE_IE501 0x0501\n-#define _WIN32_WINNT_WS03 0x0502\n-#define _WIN32_IE_IE55 0x0550\n-#define _WIN32_WINNT_WIN6 0x0600\n-#define _WIN32_WINNT_VISTA 0x0600\n-#define _WIN32_WINNT_WS08 0x0600\n-#define _WIN32_WINNT_LONGHORN 0x0600\n-#define _WIN32_IE_IE60 0x0600\n-#define FILEOPENORD 1536\n-#define _WIN32_WINNT_WIN7 0x0601\n-#define _WIN32_IE_IE60SP1 0x0601\n-#define MULTIFILEOPENORD 1537\n-#define _WIN32_WINNT_WIN8 0x0602\n-#define _WIN32_IE_WS03 0x0602\n-#define PRINTDLGORD 1538\n-#define _WIN32_WINNT_WINBLUE 0x0603\n-#define _WIN32_IE_IE60SP2 0x0603\n-#define PRNSETUPDLGORD 1539\n-#define VER_PRODUCTVERSION_W 0x0603\n-#define FINDDLGORD 1540\n-#define REPLACEDLGORD 1541\n-#define FONTDLGORD 1542\n-#define FORMATDLGORD31 1543\n-#define FORMATDLGORD30 1544\n-#define RUNDLGORD 1545\n-#define PAGESETUPDLGORD 1546\n-#define NEWFILEOPENORD 1547\n-#define PRINTDLGEXORD 1549\n-#define PAGESETUPDLGORDMOTIF 1550\n-#define COLORMGMTDLGORD 1551\n-#define NEWFILEOPENV2ORD 1552\n-#define NEWFILEOPENV3ORD 1553\n-#define NEWFORMATDLGWITHLINK 1591\n-#define IDC_MANAGE_LINK 1592\n-#define _WIN32_IE_IE70 0x0700\n-#define _WIN32_IE_IE80 0x0800\n-#define CS_SAVEBITS 0x0800\n-#define HDS_NOSIZING 0x0800\n-#define TBSTYLE_FLAT 0x0800\n-#define RBS_FIXEDORDER 0x00000800\n-#define SBARS_TOOLTIPS 0x0800\n-#define SBT_TOOLTIPS 0x0800\n-#define TBS_NOTIFYBEFOREMOVE 0x0800\n-#define LVS_ALIGNLEFT 0x0800\n-#define TVS_INFOTIP 0x0800\n-#define TCS_RAGGEDRIGHT 0x0800\n-#define _WIN32_IE_IE90 0x0900\n-#define _WIN32_IE_IE100 0x0A00\n-#define _WIN32_IE 0x0A00\n-#define LVS_ALIGNMASK 0x0c00\n-#define CS_BYTEALIGNCLIENT 0x1000\n-#define HDS_OVERFLOW 0x1000\n-#define TBSTYLE_LIST 0x1000\n-#define RBS_REGISTERDROP 0x00001000\n-#define TBS_TRANSPARENTBKGND 0x1000\n-#define LVS_OWNERDATA 0x1000\n-#define TVS_FULLROWSELECT 0x1000\n-#define TCS_FOCUSONBUTTONDOWN 0x1000\n-#define CS_BYTEALIGNWINDOW 0x2000\n-#define TBSTYLE_CUSTOMERASE 0x2000\n-#define RBS_AUTOSIZE 0x00002000\n-#define LVS_NOSCROLL 0x2000\n-#define TVS_NOSCROLL 0x2000\n-#define TCS_OWNERDRAWFIXED 0x2000\n-#define VER_PRODUCTBUILD 9600\n-#define CS_GLOBALCLASS 0x4000\n-#define TBSTYLE_REGISTERDROP 0x4000\n-#define RBS_VERTICALGRIPPER 0x00004000\n-#define LVS_NOCOLUMNHEADER 0x4000\n-#define TVS_NONEVENHEIGHT 0x4000\n-#define TCS_TOOLTIPS 0x4000\n-#define VER_PRODUCTBUILD_QFE 17298\n-#define VER_PACKAGEBUILD_QFE 17298\n-#define IDH_NO_HELP 28440\n-#define IDH_MISSING_CONTEXT 28441\n-#define IDH_GENERIC_HELP_BUTTON 28442\n-#define IDH_OK 28443\n-#define IDH_CANCEL 28444\n-#define IDH_HELP 28445\n-#define LANG_BOSNIAN_NEUTRAL 0x781a\n-#define LANG_CHINESE_TRADITIONAL 0x7c04\n-#define LANG_SERBIAN_NEUTRAL 0x7c1a\n-#define IDTIMEOUT 32000\n-#define OCR_NORMAL 32512\n-#define OIC_SAMPLE 32512\n-#define IDI_APPLICATION 32512\n-#define OCR_IBEAM 32513\n-#define OIC_HAND 32513\n-#define IDI_HAND 32513\n-#define OCR_WAIT 32514\n-#define OIC_QUES 32514\n-#define IDI_QUESTION 32514\n-#define OCR_CROSS 32515\n-#define OIC_BANG 32515\n-#define IDI_EXCLAMATION 32515\n-#define OCR_UP 32516\n-#define OIC_NOTE 32516\n-#define IDI_ASTERISK 32516\n-#define OIC_WINLOGO 32517\n-#define IDI_WINLOGO 32517\n-#define OIC_SHIELD 32518\n-#define IDI_SHIELD 32518\n-#define OCR_SIZE 32640\n-#define OCR_ICON 32641\n-#define OCR_SIZENWSE 32642\n-#define OCR_SIZENESW 32643\n-#define OCR_SIZEWE 32644\n-#define OCR_SIZENS 32645\n-#define OCR_SIZEALL 32646\n-#define OCR_ICOCUR 32647\n-#define OCR_NO 32648\n-#define OCR_HAND 32649\n-#define OCR_APPSTARTING 32650\n-#define OBM_LFARROWI 32734\n-#define OBM_RGARROWI 32735\n-#define OBM_DNARROWI 32736\n-#define OBM_UPARROWI 32737\n-#define OBM_COMBO 32738\n-#define OBM_MNARROW 32739\n-#define OBM_LFARROWD 32740\n-#define OBM_RGARROWD 32741\n-#define OBM_DNARROWD 32742\n-#define OBM_UPARROWD 32743\n-#define OBM_RESTORED 32744\n-#define OBM_ZOOMD 32745\n-#define OBM_REDUCED 32746\n-#define OBM_RESTORE 32747\n-#define OBM_ZOOM 32748\n-#define OBM_REDUCE 32749\n-#define OBM_LFARROW 32750\n-#define OBM_RGARROW 32751\n-#define OBM_DNARROW 32752\n-#define OBM_UPARROW 32753\n-#define OBM_CLOSE 32754\n-#define OBM_OLD_RESTORE 32755\n-#define OBM_OLD_ZOOM 32756\n-#define OBM_OLD_REDUCE 32757\n-#define OBM_BTNCORNERS 32758\n-#define OBM_CHECKBOXES 32759\n-#define OBM_CHECK 32760\n-#define OBM_BTSIZE 32761\n-#define OBM_OLD_LFARROW 32762\n-#define OBM_OLD_RGARROW 32763\n-#define OBM_OLD_DNARROW 32764\n-#define OBM_OLD_UPARROW 32765\n-#define OBM_SIZE 32766\n-#define OBM_OLD_CLOSE 32767\n-#define WM_APP 0x8000\n-#define HELP_TCARD 0x8000\n-#define TBSTYLE_TRANSPARENT 0x8000\n-#define RBS_DBLCLKTOGGLE 0x00008000\n-#define LVS_NOSORTHEADER 0x8000\n-#define TVS_NOHSCROLL 0x8000\n-#define TCS_FOCUSNEVER 0x8000\n-#define SC_SIZE 0xF000\n-#define SC_SEPARATOR 0xF00F\n-#define SC_MOVE 0xF010\n-#define SC_MINIMIZE 0xF020\n-#define SC_MAXIMIZE 0xF030\n-#define SC_NEXTWINDOW 0xF040\n-#define SC_PREVWINDOW 0xF050\n-#define SC_CLOSE 0xF060\n-#define SC_VSCROLL 0xF070\n-#define SC_HSCROLL 0xF080\n-#define SC_MOUSEMENU 0xF090\n-#define SC_KEYMENU 0xF100\n-#define SC_ARRANGE 0xF110\n-#define SC_RESTORE 0xF120\n-#define SC_TASKLIST 0xF130\n-#define SC_SCREENSAVE 0xF140\n-#define SC_HOTKEY 0xF150\n-#define SC_DEFAULT 0xF160\n-#define SC_MONITORPOWER 0xF170\n-#define SC_CONTEXTHELP 0xF180\n-#define LVS_TYPESTYLEMASK 0xfc00\n-#define SPVERSION_MASK 0x0000FF00\n-#define HTERROR -2\n-#define PWR_FAIL -1\n-#define UNICODE_NOCHAR 0xFFFF\n-#define HTTRANSPARENT -1\n-\n-// Next default values for new objects\n-//\n-#ifdef APSTUDIO_INVOKED\n-#ifndef APSTUDIO_READONLY_SYMBOLS\n-#define _APS_NEXT_RESOURCE_VALUE 101\n-#define _APS_NEXT_COMMAND_VALUE 40001\n-#define _APS_NEXT_CONTROL_VALUE 1000\n-#define _APS_NEXT_SYMED_VALUE 101\n-#endif\n-#endif\ndiff --git a/debian/copyright.in b/debian/copyright.in\nindex 71e89c49c..cf7213935 100644\n--- a/debian/copyright.in\n+++ b/debian/copyright.in\n@@ -92,7 +92,6 @@ License: GPL-2\n \n Files: lib/getopt_long.c\n include/windows/getopt.h\n- datapath-windows/ovsext/Conntrack-tcp.c\n lib/conntrack-tcp.c\n Copyright: (c) 2001 Daniel Hartmeier\n (c) 2002 - 2008 Henning Brauer\ndiff --git a/m4/openvswitch.m4 b/m4/openvswitch.m4\nindex 060070475..ddff0cada 100644\n--- a/m4/openvswitch.m4\n+++ b/m4/openvswitch.m4\n@@ -159,57 +159,6 @@ AC_DEFUN([OVS_CHECK_WIN32],\n #endif])\n fi])\n \n-dnl OVS_CHECK_WINDOWS\n-dnl\n-dnl Configure Visual Studio solution build\n-AC_DEFUN([OVS_CHECK_VISUAL_STUDIO_DDK], [\n-if test \"$WIN32\" = yes; then\n- AC_ARG_WITH([vstudiotarget],\n- [AS_HELP_STRING([--with-vstudiotarget=target_type],\n- [Target type: Debug/Release])],\n- [\n- case \"$withval\" in\n- \"Release\") ;;\n- \"Debug\") ;;\n- *) AC_MSG_ERROR([No valid Visual Studio configuration found]) ;;\n- esac\n-\n- VSTUDIO_CONFIG=$withval\n- ], [\n- VSTUDIO_CONFIG=\"Debug\"\n- ]\n- )\n-\n- AC_SUBST([VSTUDIO_CONFIG])\n-\n- AC_ARG_WITH([vstudiotargetver],\n- [AS_HELP_STRING([--with-vstudiotargetver=target_ver1,target_ver2],\n- [Target versions: Win8,Win8.1,Win10])],\n- [\n- targetver=`echo \"$withval\" | tr -s , ' ' `\n- for ver in $targetver; do\n- case \"$ver\" in\n- \"Win8\") VSTUDIO_WIN8=true ;;\n- \"Win8.1\") VSTUDIO_WIN8_1=true ;;\n- \"Win10\") VSTUDIO_WIN10=true ;;\n- *) AC_MSG_ERROR([No valid Visual Studio target version found]) ;;\n- esac\n- done\n-\n- ], [\n- VSTUDIO_WIN8=true\n- VSTUDIO_WIN8_1=true\n- VSTUDIO_WIN10=true\n- ]\n- )\n- AC_DEFINE([VSTUDIO_DDK], [1], [System uses the Visual Studio build target.])\n-fi\n-AM_CONDITIONAL([VSTUDIO_WIN8], [test -n \"$VSTUDIO_WIN8\"])\n-AM_CONDITIONAL([VSTUDIO_WIN8_1], [test -n \"$VSTUDIO_WIN8_1\"])\n-AM_CONDITIONAL([VSTUDIO_WIN10], [test -n \"$VSTUDIO_WIN10\"])\n-AM_CONDITIONAL([VSTUDIO_DDK], [test -n \"$VSTUDIO_CONFIG\"])\n-])\n-\n dnl Checks for Netlink support.\n AC_DEFUN([OVS_CHECK_NETLINK],\n [AC_CHECK_HEADER([linux/netlink.h],\ndiff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml\nindex b7a5afc0a..8cbc01877 100644\n--- a/vswitchd/vswitch.xml\n+++ b/vswitchd/vswitch.xml\n@@ -2666,8 +2666,8 @@\n The names of interfaces implemented as Linux and BSD network\n devices, including interfaces with type <code>internal</code>,\n <code>tap</code>, or <code>system</code> plus the different types\n- of tunnel ports, are limited to 15 bytes. Windows limits these\n- names to 255 bytes.\n+ of tunnel ports, are limited to 15 bytes. In general, different\n+ datapath implementations may have different limitations.\n </li>\n \n <li>\n@@ -6218,13 +6218,12 @@ ovs-vsctl add-port br0 p1 -- \\\n <p>\n A datapath is responsible for providing the packet handling in Open\n vSwitch. There are two primary datapath implementations used by\n- Open vSwitch: kernel and userspace. Kernel datapath\n- implementations are available for Linux and Hyper-V, and selected\n- as <code>system</code> in the <ref column=\"datapath_type\"/> column\n- of the <ref table=\"Bridge\"/> table. The userspace datapath is used\n- by DPDK and AF-XDP, and is selected as <code>netdev</code> in the\n- <ref column=\"datapath_type\"/> column of the <ref table=\"Bridge\"/>\n- table.\n+ Open vSwitch: kernel and userspace. Kernel datapath implementation is\n+ available for Linux and selected as <code>system</code> in the\n+ <ref column=\"datapath_type\"/> column of the <ref table=\"Bridge\"/> table.\n+ The userspace datapath is used by DPDK and AF-XDP, and is selected as\n+ <code>netdev</code> in the <ref column=\"datapath_type\"/> column of the\n+ <ref table=\"Bridge\"/> table.\n </p>\n <p>\n A datapath of a particular type is shared by all the bridges that use\n@@ -6262,23 +6261,22 @@ ovs-vsctl add-port br0 p1 -- \\\n </li>\n \n <li>\n- Other datapaths (such as the Hyper-V kernel datapath) currently\n- report <code><unknown></code>.\n+ Other datapaths currently report <code><unknown></code>.\n </li>\n </ul>\n \n <p>\n A version discrepancy between <code>ovs-vswitchd</code> and the\n datapath in use is not normally cause for alarm. The Open vSwitch\n- kernel datapaths for Linux and Hyper-V, in particular, are designed\n- for maximum inter-version compatibility: any userspace version works\n- with with any kernel version. Some reasons do exist to insist on\n- particular user/kernel pairings. First, newer kernel versions add\n- new features, that can only be used by new-enough userspace, e.g.\n- VXLAN tunneling requires certain minimal userspace and kernel\n- versions. Second, as an extension to the first reason, some newer\n- kernel versions add new features for enhancing performance that only\n- new-enough userspace versions can take advantage of.\n+ kernel datapaths for Linux, in particular, is designed for maximum\n+ inter-version compatibility: any userspace version works with any\n+ kernel version. Some reasons do exist to insist on particular\n+ user/kernel pairings. First, newer kernel versions add new features,\n+ that can only be used by new-enough userspace, e.g. VXLAN tunneling\n+ requires certain minimal userspace and kernel versions. Second, as\n+ an extension to the first reason, some newer kernel versions add new\n+ features for enhancing performance that only new-enough userspace\n+ versions can take advantage of.\n </p>\n </column>\n \n@@ -6295,10 +6293,9 @@ ovs-vsctl add-port br0 p1 -- \\\n features. For the <code>netdev</code> datapath, the\n capabilities are fixed for a given version of Open vSwitch\n because this datapath is built into the\n- <code>ovs-vswitchd</code> binary. The Linux kernel and\n- Windows and other datapaths, which are external to OVS\n- userspace, can vary in version and capabilities independently\n- from <code>ovs-vswitchd</code>.\n+ <code>ovs-vswitchd</code> binary. The Linux kernel and other\n+ datapaths, which are external to OVS userspace, can vary in version\n+ and capabilities independently from <code>ovs-vswitchd</code>.\n </p>\n \n <p>\n", "prefixes": [ "ovs-dev", "4/5" ] }