get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/1.2/patches/2235228/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2235228,
    "url": "http://patchwork.ozlabs.org/api/1.2/patches/2235228/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/openvswitch/patch/f0b2f642d1e198b28f179dac9016f4e7b5bbe072.1778261956.git.tredaelli@redhat.com/",
    "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": "<f0b2f642d1e198b28f179dac9016f4e7b5bbe072.1778261956.git.tredaelli@redhat.com>",
    "list_archive_url": null,
    "date": "2026-05-08T22:08:37",
    "name": "[ovs-dev,v3,5/6] lib/dp-packet: Fold the 'packets' module into dp-packets.",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "7d66c14132fcb9ed2daaf19f51c0a2845fe66ff5",
    "submitter": {
        "id": 70949,
        "url": "http://patchwork.ozlabs.org/api/1.2/people/70949/?format=api",
        "name": "Timothy Redaelli",
        "email": "tredaelli@redhat.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/openvswitch/patch/f0b2f642d1e198b28f179dac9016f4e7b5bbe072.1778261956.git.tredaelli@redhat.com/mbox/",
    "series": [
        {
            "id": 503454,
            "url": "http://patchwork.ozlabs.org/api/1.2/series/503454/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/openvswitch/list/?series=503454",
            "date": "2026-05-08T22:08:32",
            "name": "libopenvswitch: Restructure the massive OVS library into two parts.",
            "version": 3,
            "mbox": "http://patchwork.ozlabs.org/series/503454/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2235228/comments/",
    "check": "success",
    "checks": "http://patchwork.ozlabs.org/api/patches/2235228/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<ovs-dev-bounces@openvswitch.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "dev@openvswitch.org"
        ],
        "Delivered-To": [
            "patchwork-incoming@legolas.ozlabs.org",
            "ovs-dev@lists.linuxfoundation.org"
        ],
        "Authentication-Results": [
            "legolas.ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=GhOXJuuN;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org\n (client-ip=2605:bc80:3010::133; helo=smtp2.osuosl.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org)",
            "smtp2.osuosl.org;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key)\n header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=GhOXJuuN",
            "smtp4.osuosl.org; dmarc=pass (p=quarantine dis=none)\n header.from=redhat.com",
            "smtp4.osuosl.org;\n dkim=fail reason=\"signature verification failed\" (1024-bit key)\n header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=GhOXJuuN"
        ],
        "Received": [
            "from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133])\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 4gC3GN26lRz1yHW\n\tfor <incoming@patchwork.ozlabs.org>; Sat, 09 May 2026 08:10:36 +1000 (AEST)",
            "from localhost (localhost [127.0.0.1])\n\tby smtp2.osuosl.org (Postfix) with ESMTP id DB2EA4143C;\n\tFri,  8 May 2026 22:10:34 +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 poAYM7h-kZb7; Fri,  8 May 2026 22:10:26 +0000 (UTC)",
            "from lists.linuxfoundation.org (lf-lists.osuosl.org\n [IPv6:2605:bc80:3010:104::8cd3:938])\n\tby smtp2.osuosl.org (Postfix) with ESMTPS id C0D5E413F7;\n\tFri,  8 May 2026 22:10:26 +0000 (UTC)",
            "from lf-lists.osuosl.org (localhost [127.0.0.1])\n\tby lists.linuxfoundation.org (Postfix) with ESMTP id A9F0BC04EB;\n\tFri,  8 May 2026 22:10:26 +0000 (UTC)",
            "from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137])\n by lists.linuxfoundation.org (Postfix) with ESMTP id 1E609C04EB\n for <dev@openvswitch.org>; Fri,  8 May 2026 22:10:26 +0000 (UTC)",
            "from localhost (localhost [127.0.0.1])\n by smtp4.osuosl.org (Postfix) with ESMTP id 6B8E94218D\n for <dev@openvswitch.org>; Fri,  8 May 2026 22:10:09 +0000 (UTC)",
            "from smtp4.osuosl.org ([127.0.0.1])\n by localhost (smtp4.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id q2cQuPODCqDp for <dev@openvswitch.org>;\n Fri,  8 May 2026 22:10:03 +0000 (UTC)",
            "from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.133.124])\n by smtp4.osuosl.org (Postfix) with ESMTPS id 43FF042183\n for <dev@openvswitch.org>; Fri,  8 May 2026 22:10:03 +0000 (UTC)",
            "from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com\n (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by\n relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3,\n cipher=TLS_AES_256_GCM_SHA384) id us-mta-322-3zfzGypFOs2KFkgUgo_H9A-1; Fri,\n 08 May 2026 18:09:59 -0400",
            "from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com\n (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest\n SHA256)\n (No client certificate requested)\n by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS\n id C00A81800451\n for <dev@openvswitch.org>; Fri,  8 May 2026 22:09:58 +0000 (UTC)",
            "from aldebaran.netbird.cloud (unknown [10.44.32.34])\n by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP\n id 84EF23002D30; Fri,  8 May 2026 22:09:57 +0000 (UTC)"
        ],
        "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 smtp2.osuosl.org C0D5E413F7",
            "OpenDKIM Filter v2.11.0 smtp4.osuosl.org 43FF042183"
        ],
        "Received-SPF": "Pass (mailfrom) identity=mailfrom; client-ip=170.10.133.124;\n helo=us-smtp-delivery-124.mimecast.com; envelope-from=tredaelli@redhat.com;\n receiver=<UNKNOWN>",
        "DMARC-Filter": "OpenDMARC Filter v1.4.2 smtp4.osuosl.org 43FF042183",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1778278202;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:content-type:content-type:\n content-transfer-encoding:content-transfer-encoding:\n in-reply-to:in-reply-to:references:references;\n bh=1w9VbvpWWu0qU8mJ5gW0HsmQeXPA/yD2OOmMOJbSOZE=;\n b=GhOXJuuNNv/542m8m4RKa/8slFTEfkRPHuuH7mpT3FEO00R5yRagmqCiZLTk4gYGzwjuQM\n UZSLBLd+MZxDhxcEn0fd40RJeBeTz7OclB4/UK0V47IqkyOaMvFcR3ucsUhpBSA0/CXgk2\n TZP607Y7+iY3ieQ8aopNzGNFTBpCFek=",
        "X-MC-Unique": "3zfzGypFOs2KFkgUgo_H9A-1",
        "X-Mimecast-MFC-AGG-ID": "3zfzGypFOs2KFkgUgo_H9A_1778278198",
        "To": "dev@openvswitch.org",
        "Date": "Sat,  9 May 2026 00:08:37 +0200",
        "Message-ID": "\n <f0b2f642d1e198b28f179dac9016f4e7b5bbe072.1778261956.git.tredaelli@redhat.com>",
        "In-Reply-To": "<cover.1778261956.git.tredaelli@redhat.com>",
        "References": "<cover.1778261956.git.tredaelli@redhat.com>",
        "MIME-Version": "1.0",
        "X-Scanned-By": "MIMEDefang 3.4.1 on 10.30.177.4",
        "X-Mimecast-Spam-Score": "0",
        "X-Mimecast-MFC-PROC-ID": "MQl3Y3He__icIGv8OaF_-HvoUONWFuhpvDtgq-E-kH0_1778278198",
        "X-Mimecast-Originator": "redhat.com",
        "Subject": "[ovs-dev] [PATCH v3 5/6] lib/dp-packet: Fold the 'packets' module\n into dp-packets.",
        "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>",
        "From": "Timothy Redaelli via dev <ovs-dev@openvswitch.org>",
        "Reply-To": "Timothy Redaelli <tredaelli@redhat.com>",
        "Content-Type": "text/plain; charset=\"us-ascii\"",
        "Content-Transfer-Encoding": "7bit",
        "Errors-To": "ovs-dev-bounces@openvswitch.org",
        "Sender": "\"dev\" <ovs-dev-bounces@openvswitch.org>"
    },
    "content": "The leftover packets module was almost completely dealing with\ndp-packet work anyway, so fold it into the dp-packets translation\nunit to keep things consistent.  During this process, also move\nsome of the packet metadata stuff out and remove the packets\ntranslation unit.\n\nThere were some additional cleanups here where packets.h was\npulling in all sorts of other dependencies into translation units\nthat didn't actually need them.  So the .c files are widely\nupdated to include just those headers they need (based on compiler\nwarnings).\n\nFinally, there's a weird quirk in eth_push_vlan where a memmove\noptimization bug seems to pop up, so add a comment on why there\nare two warnings disabled.  The dp_packet_resize_l2 calling order\nseems to matter, and an alternative is to force it to never\ninline that function, but it seems worse to just disabling the\nwarnings.\n\nCo-authored-by: Aaron Conole <aconole@redhat.com>\nSigned-off-by: Aaron Conole <aconole@redhat.com>\nSigned-off-by: Timothy Redaelli <tredaelli@redhat.com>\n---\n lib/automake.mk                    |    2 -\n lib/bfd.c                          |    1 -\n lib/bfd.h                          |    2 +-\n lib/cfm.c                          |    1 -\n lib/cfm.h                          |    1 -\n lib/classifier.c                   |    1 -\n lib/conntrack-private.h            |    1 -\n lib/conntrack.h                    |    2 +-\n lib/ct-dpif.c                      |    1 +\n lib/ct-dpif.h                      |    3 +-\n lib/dhcp.h                         |    1 -\n lib/dp-packet.c                    | 1474 +++++++++++++++++++++++++++\n lib/dp-packet.h                    |  110 +-\n lib/dpctl.c                        |    1 -\n lib/dpif-netdev-extract-avx512.c   |    1 -\n lib/dpif-netdev-lookup.c           |    1 +\n lib/dpif-netdev-private-extract.c  |    1 +\n lib/dpif-netdev-private-flow.h     |    1 +\n lib/dpif-netdev.c                  |    1 -\n lib/dpif-netdev.h                  |    1 -\n lib/dpif-netlink-rtnl.c            |    1 +\n lib/dpif-netlink.c                 |    1 -\n lib/dpif-offload-dpdk-netdev.c     |    3 +-\n lib/dpif-offload-dpdk.c            |    3 +\n lib/dpif.c                         |    1 -\n lib/dpif.h                         |    1 -\n lib/flow.c                         |   14 +-\n lib/flow.h                         |  157 ++-\n lib/ipf.c                          |    2 +-\n lib/lacp.c                         |    1 -\n lib/lacp.h                         |    6 +-\n lib/lldp/lldp.c                    |    1 -\n lib/lldp/lldpd-structs.h           |    1 -\n lib/lldp/lldpd.c                   |    1 -\n lib/lldp/lldpd.h                   |    1 -\n lib/mac-learning.c                 |    2 +\n lib/mac-learning.h                 |    1 -\n lib/match.c                        |    1 -\n lib/mcast-snooping.h               |    1 -\n lib/meta-flow.c                    |    1 -\n lib/multipath.c                    |    1 -\n lib/netdev-afxdp.c                 |    1 -\n lib/netdev-bsd.c                   |    1 -\n lib/netdev-dpdk.c                  |    1 -\n lib/netdev-dummy.c                 |    1 -\n lib/netdev-linux.c                 |    1 -\n lib/netdev-native-tnl.c            |    4 +-\n lib/netdev-native-tnl.h            |    1 -\n lib/netdev-provider.h              |    1 -\n lib/netdev-vport.c                 |    1 -\n lib/netdev-windows.c               |    1 -\n lib/netdev.c                       |    1 -\n lib/netdev.h                       |    1 -\n lib/nx-match.c                     |    2 +-\n lib/odp-execute-avx512.c           |    2 +-\n lib/odp-execute-private.c          |    1 +\n lib/odp-execute.c                  |    1 -\n lib/odp-util.c                     |    2 +-\n lib/odp-util.h                     |    1 +\n lib/ofp-ct.c                       |    2 +\n lib/ofp-ed-props.c                 |    2 -\n lib/ofp-match.c                    |    2 +\n lib/ofp-parse.c                    |    2 +-\n lib/ofp-print.c                    |    1 -\n lib/ofp-util.c                     |    1 -\n lib/ovs-lldp.c                     |    1 -\n lib/ovs-lldp.h                     |    1 -\n lib/ovs-router.c                   |    1 -\n lib/packets.c                      | 1494 ----------------------------\n lib/packets.h                      |  286 ------\n lib/pcap-file.c                    |    1 -\n lib/route-table-bsd.c              |    2 +-\n lib/route-table.c                  |    1 -\n lib/rstp-common.h                  |    1 -\n lib/rstp-state-machines.c          |    1 -\n lib/rstp.c                         |    1 -\n lib/rtnetlink.c                    |    2 +-\n lib/smap.c                         |    2 +-\n lib/socket-util.c                  |    2 +-\n lib/stp.c                          |    1 -\n lib/stream-ssl.c                   |    2 +-\n lib/stream-tcp.c                   |    1 -\n lib/stream-unix.c                  |    1 -\n lib/stream.c                       |    1 -\n lib/tc.c                           |    1 -\n lib/tnl-neigh-cache.c              |    1 -\n lib/tnl-neigh-cache.h              |    1 -\n lib/tnl-ports.h                    |    1 -\n lib/tun-metadata.c                 |    1 -\n lib/vconn.c                        |    1 -\n ofproto/bond.c                     |    1 -\n ofproto/bond.h                     |    1 -\n ofproto/in-band.c                  |    1 -\n ofproto/netflow.c                  |    1 -\n ofproto/ofproto-dpif-ipfix.c       |    1 -\n ofproto/ofproto-dpif-monitor.h     |    1 -\n ofproto/ofproto-dpif-sflow.c       |    1 -\n ofproto/ofproto-dpif-upcall.c      |    1 -\n ofproto/ofproto-dpif-xlate-cache.c |    1 -\n ofproto/ofproto-dpif-xlate.c       |    1 -\n ofproto/ofproto.c                  |    1 -\n ofproto/tunnel.c                   |    1 -\n tests/test-classifier.c            |    2 +-\n tests/test-conntrack.c             |    1 +\n tests/test-csum.c                  |    2 +-\n tests/test-lib-route-table.c       |    3 +-\n tests/test-netflow.c               |    2 +-\n tests/test-netlink-conntrack.c     |    2 +\n tests/test-packets.c               |    2 +-\n tests/test-rstp.c                  |    1 -\n tests/test-sflow.c                 |    2 +-\n tests/test-stp.c                   |    1 -\n utilities/ovs-ofctl.c              |    2 +-\n vswitchd/bridge.c                  |    1 -\n 114 files changed, 1801 insertions(+), 1882 deletions(-)\n delete mode 100644 lib/packets.c\n delete mode 100644 lib/packets.h",
    "diff": "diff --git a/lib/automake.mk b/lib/automake.mk\nindex 879300b4a..dd38762ad 100644\n--- a/lib/automake.mk\n+++ b/lib/automake.mk\n@@ -307,8 +307,6 @@ lib_libopenvswitch_la_SOURCES = \\\n \tlib/ovsdb-types.h \\\n \tlib/ox-stat.c \\\n \tlib/ox-stat.h \\\n-\tlib/packets.c \\\n-\tlib/packets.h \\\n \tlib/pcap-file.c \\\n \tlib/pcap-file.h \\\n \tlib/perf-counter.h \\\ndiff --git a/lib/bfd.c b/lib/bfd.c\nindex b2d32b8ab..97aa75366 100644\n--- a/lib/bfd.c\n+++ b/lib/bfd.c\n@@ -38,7 +38,6 @@\n #include \"openvswitch/ofpbuf.h\"\n #include \"ovs-thread.h\"\n #include \"openvswitch/types.h\"\n-#include \"packets.h\"\n #include \"openvswitch/poll-loop.h\"\n #include \"random.h\"\n #include \"seq.h\"\ndiff --git a/lib/bfd.h b/lib/bfd.h\nindex 9d32327fb..fe626c7cd 100644\n--- a/lib/bfd.h\n+++ b/lib/bfd.h\n@@ -21,7 +21,7 @@\n #include <stdbool.h>\n #include <inttypes.h>\n \n-#include \"packets.h\"\n+#include \"net-proto.h\"\n \n struct bfd;\n struct dpif_flow_stats;\ndiff --git a/lib/cfm.c b/lib/cfm.c\nindex 5a24a6a7d..328f84bc6 100644\n--- a/lib/cfm.c\n+++ b/lib/cfm.c\n@@ -31,7 +31,6 @@\n #include \"openvswitch/hmap.h\"\n #include \"netdev.h\"\n #include \"ovs-atomic.h\"\n-#include \"packets.h\"\n #include \"openvswitch/poll-loop.h\"\n #include \"random.h\"\n #include \"seq.h\"\ndiff --git a/lib/cfm.h b/lib/cfm.h\nindex 5710c9952..8b7bdf047 100644\n--- a/lib/cfm.h\n+++ b/lib/cfm.h\n@@ -20,7 +20,6 @@\n \n #include \"openvswitch/hmap.h\"\n #include \"openvswitch/types.h\"\n-#include \"packets.h\"\n \n struct flow;\n struct dp_packet;\ndiff --git a/lib/classifier.c b/lib/classifier.c\nindex 7db731bef..436bea622 100644\n--- a/lib/classifier.c\n+++ b/lib/classifier.c\n@@ -24,7 +24,6 @@\n #include \"openvswitch/dynamic-string.h\"\n #include \"net-proto.h\"\n #include \"odp-util.h\"\n-#include \"packets.h\"\n #include \"util.h\"\n \n struct trie_ctx;\ndiff --git a/lib/conntrack-private.h b/lib/conntrack-private.h\nindex f1132e8aa..576b26df2 100644\n--- a/lib/conntrack-private.h\n+++ b/lib/conntrack-private.h\n@@ -28,7 +28,6 @@\n #include \"openvswitch/hmap.h\"\n #include \"openvswitch/list.h\"\n #include \"openvswitch/types.h\"\n-#include \"packets.h\"\n #include \"rculist.h\"\n #include \"unaligned.h\"\n #include \"dp-packet.h\"\ndiff --git a/lib/conntrack.h b/lib/conntrack.h\nindex c3136e955..da5c024c6 100644\n--- a/lib/conntrack.h\n+++ b/lib/conntrack.h\n@@ -29,7 +29,6 @@\n #include \"openvswitch/types.h\"\n #include \"ovs-atomic.h\"\n #include \"ovs-thread.h\"\n-#include \"packets.h\"\n #include \"hindex.h\"\n \n /* Userspace connection tracker\n@@ -62,6 +61,7 @@\n  */\n \n struct dp_packet_batch;\n+struct dp_packet;\n \n struct conntrack;\n \ndiff --git a/lib/ct-dpif.c b/lib/ct-dpif.c\nindex 5a836b668..75d2a1c7f 100644\n--- a/lib/ct-dpif.c\n+++ b/lib/ct-dpif.c\n@@ -20,6 +20,7 @@\n #include <errno.h>\n \n #include \"ct-dpif.h\"\n+#include \"openvswitch/dynamic-string.h\"\n #include \"openvswitch/ofp-ct.h\"\n #include \"openvswitch/ofp-parse.h\"\n #include \"openvswitch/vlog.h\"\ndiff --git a/lib/ct-dpif.h b/lib/ct-dpif.h\nindex c3786d5ae..f3e74ed76 100644\n--- a/lib/ct-dpif.h\n+++ b/lib/ct-dpif.h\n@@ -17,8 +17,8 @@\n #ifndef CT_DPIF_H\n #define CT_DPIF_H\n \n+#include \"openvswitch/list.h\"\n #include \"openvswitch/types.h\"\n-#include \"packets.h\"\n \n struct ofp_ct_match;\n \n@@ -228,6 +228,7 @@ enum {\n     CT_STATS_MAX,\n };\n \n+struct ds;\n struct dpif;\n struct dpif_ipf_status;\n struct ipf_dump_ctx;\ndiff --git a/lib/dhcp.h b/lib/dhcp.h\nindex c904af6c4..b7ab2fa6d 100644\n--- a/lib/dhcp.h\n+++ b/lib/dhcp.h\n@@ -18,7 +18,6 @@\n #define DHCP_H 1\n \n #include <stdint.h>\n-#include \"packets.h\"\n #include \"util.h\"\n \n /* Ports used by DHCP. */\ndiff --git a/lib/dp-packet.c b/lib/dp-packet.c\nindex ac8fbe3b9..b5d5d9b91 100644\n--- a/lib/dp-packet.c\n+++ b/lib/dp-packet.c\n@@ -15,13 +15,21 @@\n  */\n \n #include <config.h>\n+#include <sys/types.h>\n+#include <sys/socket.h>\n+#include <netinet/in.h>\n+#include <netinet/ip6.h>\n+#include <netinet/icmp6.h>\n #include <stdlib.h>\n #include <string.h>\n \n+#include \"crc32c.h\"\n #include \"dp-packet.h\"\n+#include \"dp-packet-gso.h\"\n #include \"netdev-afxdp.h\"\n #include \"netdev-dpdk.h\"\n #include \"netdev-provider.h\"\n+#include \"net-proto.h\"\n #include \"openvswitch/dynamic-string.h\"\n #include \"util.h\"\n \n@@ -665,3 +673,1469 @@ dp_packet_ol_send_prepare(struct dp_packet *p, uint64_t flags)\n         }\n     }\n }\n+\n+\f\n+\n+\n+/* Fills 'b' with a Reverse ARP packet with Ethernet source address 'eth_src'.\n+ * This function is used by Open vSwitch to compose packets in cases where\n+ * context is important but content doesn't (or shouldn't) matter.\n+ *\n+ * The returned packet has enough headroom to insert an 802.1Q VLAN header if\n+ * desired. */\n+void\n+compose_rarp(struct dp_packet *b, const struct eth_addr eth_src)\n+{\n+    struct eth_header *eth;\n+    struct arp_eth_header *arp;\n+\n+    dp_packet_clear(b);\n+    dp_packet_prealloc_tailroom(b, 2 + ETH_HEADER_LEN + VLAN_HEADER_LEN\n+                             + ARP_ETH_HEADER_LEN);\n+    dp_packet_reserve(b, 2 + VLAN_HEADER_LEN);\n+    eth = dp_packet_put_uninit(b, sizeof *eth);\n+    eth->eth_dst = eth_addr_broadcast;\n+    eth->eth_src = eth_src;\n+    eth->eth_type = htons(ETH_TYPE_RARP);\n+\n+    arp = dp_packet_put_uninit(b, sizeof *arp);\n+    arp->ar_hrd = htons(ARP_HRD_ETHERNET);\n+    arp->ar_pro = htons(ARP_PRO_IP);\n+    arp->ar_hln = sizeof arp->ar_sha;\n+    arp->ar_pln = sizeof arp->ar_spa;\n+    arp->ar_op = htons(ARP_OP_RARP);\n+    arp->ar_sha = eth_src;\n+    put_16aligned_be32(&arp->ar_spa, htonl(0));\n+    arp->ar_tha = eth_src;\n+    put_16aligned_be32(&arp->ar_tpa, htonl(0));\n+\n+    dp_packet_set_l3(b, arp);\n+    b->packet_type = htonl(PT_ETH);\n+}\n+\n+/* Insert VLAN header according to given TCI. Packet passed must be Ethernet\n+ * packet.  Ignores the CFI bit of 'tci' using 0 instead.\n+ *\n+ * Also adjusts the layer offsets accordingly. */\n+void\n+eth_push_vlan(struct dp_packet *packet, ovs_be16 tpid, ovs_be16 tci)\n+{\n+    struct vlan_eth_header *veh;\n+\n+    /* Insert new 802.1Q header. */\n+    veh = dp_packet_resize_l2(packet, VLAN_HEADER_LEN);\n+    /* GCC cannot determine the buffer size through dp_packet_resize_l2 when\n+     * both functions are in the same translation unit, causing a false\n+     * positive around memmove.  An alternative to this would be to disable\n+     * inlining the dp_packet_resize_l2, but that seems excessive in this\n+     * case. */\n+#if __GNUC__ && !__clang__\n+#pragma GCC diagnostic push\n+#pragma GCC diagnostic ignored \"-Warray-bounds\"\n+    /* Also, newer versions of GCC include a stringop overread check */\n+#if __GNUC__ > 11\n+#pragma GCC diagnostic ignored \"-Wstringop-overread\"\n+#endif\n+#endif\n+    memmove(veh, (char *) veh + VLAN_HEADER_LEN, 2 * ETH_ADDR_LEN);\n+#if __GNUC__ && !__clang__\n+#pragma GCC diagnostic pop\n+#endif\n+    veh->veth_type = tpid;\n+    veh->veth_tci = tci & htons(~VLAN_CFI);\n+}\n+\n+/* Removes outermost VLAN header (if any is present) from 'packet'.\n+ *\n+ * 'packet->l2_5' should initially point to 'packet''s outer-most VLAN header\n+ * or may be NULL if there are no VLAN headers. */\n+void\n+eth_pop_vlan(struct dp_packet *packet)\n+{\n+    struct vlan_eth_header *veh = dp_packet_eth(packet);\n+\n+    if (veh && dp_packet_size(packet) >= sizeof *veh\n+        && eth_type_vlan(veh->veth_type)) {\n+\n+        memmove((char *) veh + VLAN_HEADER_LEN, veh, 2 * ETH_ADDR_LEN);\n+        dp_packet_resize_l2(packet, -VLAN_HEADER_LEN);\n+    }\n+}\n+\n+/* Push Ethernet header onto 'packet' assuming it is layer 3 */\n+void\n+push_eth(struct dp_packet *packet, const struct eth_addr *dst,\n+         const struct eth_addr *src)\n+{\n+    struct eth_header *eh;\n+\n+    ovs_assert(!dp_packet_is_eth(packet));\n+    eh = dp_packet_resize_l2(packet, ETH_HEADER_LEN);\n+    eh->eth_dst = *dst;\n+    eh->eth_src = *src;\n+    eh->eth_type = pt_ns_type_be(packet->packet_type);\n+    packet->packet_type = htonl(PT_ETH);\n+}\n+\n+/* Removes Ethernet header, including VLAN header, from 'packet'.\n+ *\n+ * Previous to calling this function, 'ofpbuf_l3(packet)' must not be NULL */\n+void\n+pop_eth(struct dp_packet *packet)\n+{\n+    char *l2_5 = dp_packet_l2_5(packet);\n+    char *l3 = dp_packet_l3(packet);\n+    ovs_be16 ethertype;\n+    int increment;\n+\n+    ovs_assert(dp_packet_is_eth(packet));\n+    ovs_assert(l3 != NULL);\n+\n+    if (l2_5) {\n+        increment = packet->l2_5_ofs;\n+        ethertype = *(ALIGNED_CAST(ovs_be16 *, (l2_5 - 2)));\n+    } else {\n+        increment = packet->l3_ofs;\n+        ethertype = *(ALIGNED_CAST(ovs_be16 *, (l3 - 2)));\n+    }\n+\n+    dp_packet_resize_l2(packet, -increment);\n+    packet->packet_type = PACKET_TYPE_BE(OFPHTN_ETHERTYPE, ntohs(ethertype));\n+}\n+\n+/* Set ethertype of the packet. */\n+static void\n+set_ethertype(struct dp_packet *packet, ovs_be16 eth_type)\n+{\n+    struct eth_header *eh = dp_packet_eth(packet);\n+\n+    if (!eh) {\n+        return;\n+    }\n+\n+    if (eth_type_vlan(eh->eth_type)) {\n+        ovs_be16 *p;\n+        char *l2_5 = dp_packet_l2_5(packet);\n+\n+        p = ALIGNED_CAST(ovs_be16 *,\n+                         (l2_5 ? l2_5 : (char *) dp_packet_l3(packet)) - 2);\n+        *p = eth_type;\n+    } else {\n+        eh->eth_type = eth_type;\n+    }\n+}\n+\n+static bool is_mpls(struct dp_packet *packet)\n+{\n+    return packet->l2_5_ofs != UINT16_MAX;\n+}\n+\n+/* Set MPLS label stack entry to outermost MPLS header.*/\n+void\n+set_mpls_lse(struct dp_packet *packet, ovs_be32 mpls_lse)\n+{\n+    /* Packet type should be MPLS to set label stack entry. */\n+    if (is_mpls(packet)) {\n+        struct mpls_hdr *mh = dp_packet_l2_5(packet);\n+\n+        /* Update mpls label stack entry. */\n+        put_16aligned_be32(&mh->mpls_lse, mpls_lse);\n+    }\n+}\n+\n+/* Push MPLS label stack entry 'lse' onto 'packet' as the outermost MPLS\n+ * header.  If 'packet' does not already have any MPLS labels, then its\n+ * Ethertype is changed to 'ethtype' (which must be an MPLS Ethertype). */\n+void\n+push_mpls(struct dp_packet *packet, ovs_be16 ethtype, ovs_be32 lse)\n+{\n+    char * header;\n+    size_t len;\n+\n+    if (!eth_type_mpls(ethtype)) {\n+        return;\n+    }\n+\n+    if (!is_mpls(packet)) {\n+        /* Set MPLS label stack offset. */\n+        packet->l2_5_ofs = packet->l3_ofs;\n+    }\n+\n+    set_ethertype(packet, ethtype);\n+\n+    /* Push new MPLS shim header onto packet. */\n+    len = packet->l2_5_ofs;\n+    header = dp_packet_resize_l2_5(packet, MPLS_HLEN);\n+    memmove(header, header + MPLS_HLEN, len);\n+    memcpy(header + len, &lse, sizeof lse);\n+\n+    pkt_metadata_init_conn(&packet->md);\n+}\n+\n+void\n+add_mpls(struct dp_packet *packet, ovs_be16 ethtype, ovs_be32 lse,\n+         bool l3_encap)\n+{\n+    if (!eth_type_mpls(ethtype)) {\n+        return;\n+    }\n+\n+    if (!l3_encap) {\n+        struct mpls_hdr *header = dp_packet_resize_l2(packet, MPLS_HLEN);\n+\n+        put_16aligned_be32(&header->mpls_lse, lse);\n+        packet->l2_5_ofs = 0;\n+        packet->packet_type = PACKET_TYPE_BE(OFPHTN_ETHERTYPE,\n+                                             ntohs(ethtype));\n+    } else {\n+        size_t len;\n+        char *header;\n+\n+        if (!is_mpls(packet)) {\n+            /* Set MPLS label stack offset. */\n+            packet->l2_5_ofs = packet->l3_ofs;\n+        }\n+        set_ethertype(packet, ethtype);\n+\n+        /* Push new MPLS shim header onto packet. */\n+        len = packet->l2_5_ofs;\n+        header = dp_packet_resize_l2_5(packet, MPLS_HLEN);\n+        memmove(header, header + MPLS_HLEN, len);\n+        memcpy(header + len, &lse, sizeof lse);\n+    }\n+    pkt_metadata_init_conn(&packet->md);\n+}\n+\n+/* If 'packet' is an MPLS packet, removes its outermost MPLS label stack entry.\n+ * If the label that was removed was the only MPLS label, changes 'packet''s\n+ * Ethertype to 'ethtype' (which ordinarily should not be an MPLS\n+ * Ethertype). */\n+void\n+pop_mpls(struct dp_packet *packet, ovs_be16 ethtype)\n+{\n+    if (is_mpls(packet)) {\n+        struct mpls_hdr *mh = dp_packet_l2_5(packet);\n+        size_t len = packet->l2_5_ofs;\n+\n+        set_ethertype(packet, ethtype);\n+        if (get_16aligned_be32(&mh->mpls_lse) & htonl(MPLS_BOS_MASK)) {\n+            dp_packet_set_l2_5(packet, NULL);\n+        }\n+        /* Shift the l2 header forward. */\n+        memmove((char *) dp_packet_data(packet) + MPLS_HLEN,\n+                dp_packet_data(packet), len);\n+        dp_packet_resize_l2_5(packet, -MPLS_HLEN);\n+\n+        /* Invalidate offload flags as they are not valid after\n+         * decapsulation of MPLS header. */\n+        dp_packet_reset_offload(packet);\n+\n+        /* packet_type must be reset for the MPLS packets with no l2 header */\n+        if (!len) {\n+            if (ethtype == htons(ETH_TYPE_TEB)) {\n+                /* The inner packet must be classified as ethernet if the\n+                 * ethtype is ETH_TYPE_TEB. */\n+                packet->packet_type = htonl(PT_ETH);\n+            } else {\n+                packet->packet_type = PACKET_TYPE_BE(OFPHTN_ETHERTYPE,\n+                                                     ntohs(ethtype));\n+            }\n+        }\n+    }\n+}\n+\n+void\n+push_nsh(struct dp_packet *packet, const struct nsh_hdr *nsh_hdr_src)\n+{\n+    struct nsh_hdr *nsh;\n+    size_t length = nsh_hdr_len(nsh_hdr_src);\n+    uint8_t next_proto;\n+\n+    switch (ntohl(packet->packet_type)) {\n+        case PT_ETH:\n+            next_proto = NSH_P_ETHERNET;\n+            break;\n+        case PT_IPV4:\n+            next_proto = NSH_P_IPV4;\n+            break;\n+        case PT_IPV6:\n+            next_proto = NSH_P_IPV6;\n+            break;\n+        case PT_NSH:\n+            next_proto = NSH_P_NSH;\n+            break;\n+        default:\n+            OVS_NOT_REACHED();\n+    }\n+\n+    nsh = (struct nsh_hdr *) dp_packet_resize_l2(packet, length);\n+    memcpy(nsh, nsh_hdr_src, length);\n+    nsh->next_proto = next_proto;\n+    packet->packet_type = htonl(PT_NSH);\n+    dp_packet_reset_offsets(packet);\n+    packet->l3_ofs = 0;\n+}\n+\n+bool\n+pop_nsh(struct dp_packet *packet)\n+{\n+    struct nsh_hdr *nsh = (struct nsh_hdr *) dp_packet_l3(packet);\n+    size_t length;\n+    uint32_t next_pt;\n+\n+    if (packet->packet_type == htonl(PT_NSH) && nsh) {\n+        switch (nsh->next_proto) {\n+            case NSH_P_ETHERNET:\n+                next_pt = PT_ETH;\n+                break;\n+            case NSH_P_IPV4:\n+                next_pt = PT_IPV4;\n+                break;\n+            case NSH_P_IPV6:\n+                next_pt = PT_IPV6;\n+                break;\n+            case NSH_P_NSH:\n+                next_pt = PT_NSH;\n+                break;\n+            default:\n+                /* Unknown inner packet type. Drop packet. */\n+                return false;\n+        }\n+\n+        length = nsh_hdr_len(nsh);\n+        dp_packet_reset_packet(packet, length);\n+        packet->packet_type = htonl(next_pt);\n+        /* Packet must be recirculated for further processing. */\n+    }\n+    return true;\n+}\n+\n+/* Converts hex digits in 'hex' to an Ethernet packet in '*packetp'.  The\n+ * caller must free '*packetp'.  On success, returns NULL.  On failure, returns\n+ * an error message and stores NULL in '*packetp'.\n+ *\n+ * Aligns the L3 header of '*packetp' on a 32-bit boundary. */\n+const char *\n+eth_from_hex(const char *hex, struct dp_packet **packetp)\n+{\n+    struct dp_packet *packet;\n+\n+    /* Use 2 bytes of headroom to 32-bit align the L3 header. */\n+    packet = *packetp = dp_packet_new_with_headroom(strlen(hex) / 2, 2);\n+\n+    if (dp_packet_put_hex(packet, hex, NULL)[0] != '\\0') {\n+        dp_packet_delete(packet);\n+        *packetp = NULL;\n+        return \"Trailing garbage in packet data\";\n+    }\n+\n+    if (dp_packet_size(packet) < ETH_HEADER_LEN) {\n+        dp_packet_delete(packet);\n+        *packetp = NULL;\n+        return \"Packet data too short for Ethernet\";\n+    }\n+\n+    return NULL;\n+}\n+\n+/* Populates 'b' with an Ethernet II packet headed with the given 'eth_dst',\n+ * 'eth_src' and 'eth_type' parameters.  A payload of 'size' bytes is allocated\n+ * in 'b' and returned.  This payload may be populated with appropriate\n+ * information by the caller.  Sets 'b''s 'frame' pointer and 'l3' offset to\n+ * the Ethernet header and payload respectively.  Aligns b->l3 on a 32-bit\n+ * boundary.\n+ *\n+ * The returned packet has enough headroom to insert an 802.1Q VLAN header if\n+ * desired. */\n+void *\n+eth_compose(struct dp_packet *b, const struct eth_addr eth_dst,\n+            const struct eth_addr eth_src, uint16_t eth_type,\n+            size_t size)\n+{\n+    void *data;\n+    struct eth_header *eth;\n+\n+\n+    dp_packet_clear(b);\n+\n+    /* The magic 2 here ensures that the L3 header (when it is added later)\n+     * will be 32-bit aligned. */\n+    dp_packet_prealloc_tailroom(b,\n+            2 + ETH_HEADER_LEN + VLAN_HEADER_LEN + size);\n+    dp_packet_reserve(b, 2 + VLAN_HEADER_LEN);\n+    eth = dp_packet_put_uninit(b, ETH_HEADER_LEN);\n+    data = dp_packet_put_zeros(b, size);\n+\n+    eth->eth_dst = eth_dst;\n+    eth->eth_src = eth_src;\n+    eth->eth_type = htons(eth_type);\n+\n+    b->packet_type = htonl(PT_ETH);\n+    dp_packet_set_l3(b, data);\n+\n+    return data;\n+}\n+\n+void\n+packet_set_ipv4_addr(struct dp_packet *packet,\n+                     ovs_16aligned_be32 *addr, ovs_be32 new_addr)\n+{\n+    struct ip_header *nh = dp_packet_l3(packet);\n+    ovs_be32 old_addr = get_16aligned_be32(addr);\n+    size_t l4_size = dp_packet_l4_size(packet);\n+\n+    pkt_metadata_init_conn(&packet->md);\n+\n+    if (nh->ip_proto == IPPROTO_TCP && l4_size >= TCP_HEADER_LEN) {\n+        if (dp_packet_l4_checksum_valid(packet)) {\n+            dp_packet_l4_checksum_set_partial(packet);\n+        } else {\n+            struct tcp_header *th = dp_packet_l4(packet);\n+            th->tcp_csum = recalc_csum32(th->tcp_csum, old_addr, new_addr);\n+        }\n+    } else if (nh->ip_proto == IPPROTO_UDP && l4_size >= UDP_HEADER_LEN ) {\n+        if (dp_packet_l4_checksum_valid(packet)) {\n+            dp_packet_l4_checksum_set_partial(packet);\n+        } else {\n+            struct udp_header *uh = dp_packet_l4(packet);\n+            if (uh->udp_csum) {\n+                uh->udp_csum = recalc_csum32(uh->udp_csum, old_addr, new_addr);\n+                if (!uh->udp_csum) {\n+                    uh->udp_csum = htons(0xffff);\n+                }\n+            }\n+        }\n+    }\n+\n+    if (dp_packet_ip_checksum_valid(packet)) {\n+        dp_packet_ip_checksum_set_partial(packet);\n+    } else {\n+        nh->ip_csum = recalc_csum32(nh->ip_csum, old_addr, new_addr);\n+    }\n+    put_16aligned_be32(addr, new_addr);\n+}\n+\n+/* Returns true, if packet contains at least one routing header where\n+ * segements_left > 0.\n+ *\n+ * This function assumes that L3 and L4 offsets are set in the packet. */\n+bool\n+packet_rh_present(struct dp_packet *packet, uint8_t *nexthdr, bool *first_frag)\n+{\n+    const struct ovs_16aligned_ip6_hdr *nh;\n+    size_t len;\n+    size_t remaining;\n+    uint8_t *data = dp_packet_l3(packet);\n+\n+    remaining = packet->l4_ofs - packet->l3_ofs;\n+    if (remaining < sizeof *nh) {\n+        return false;\n+    }\n+    nh = ALIGNED_CAST(struct ovs_16aligned_ip6_hdr *, data);\n+    data += sizeof *nh;\n+    remaining -= sizeof *nh;\n+    *nexthdr = nh->ip6_nxt;\n+\n+    while (1) {\n+        if ((*nexthdr != IPPROTO_HOPOPTS)\n+                && (*nexthdr != IPPROTO_ROUTING)\n+                && (*nexthdr != IPPROTO_DSTOPTS)\n+                && (*nexthdr != IPPROTO_AH)\n+                && (*nexthdr != IPPROTO_FRAGMENT)) {\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+            break;\n+        }\n+\n+        /* We only verify that at least 8 bytes of the next header are\n+         * available, but many of these headers are longer.  Ensure that\n+         * accesses within the extension header are within those first 8\n+         * bytes. All extension headers are required to be at least 8\n+         * bytes. */\n+        if (remaining < 8) {\n+            return false;\n+        }\n+\n+        if (*nexthdr == IPPROTO_AH) {\n+            /* A standard AH definition isn't available, but the fields\n+             * we care about are in the same location as the generic\n+             * option header--only the header length is calculated\n+             * differently. */\n+            const struct ip6_ext *ext_hdr = (struct ip6_ext *) data;\n+\n+            *nexthdr = ext_hdr->ip6e_nxt;\n+            len = (ext_hdr->ip6e_len + 2) * 4;\n+        } else if (*nexthdr == IPPROTO_FRAGMENT) {\n+            const struct ovs_16aligned_ip6_frag *frag_hdr\n+                = ALIGNED_CAST(struct ovs_16aligned_ip6_frag *, data);\n+\n+            *first_frag = !(frag_hdr->ip6f_offlg & IP6F_OFF_MASK) &&\n+                           (frag_hdr->ip6f_offlg & IP6F_MORE_FRAG);\n+            *nexthdr = frag_hdr->ip6f_nxt;\n+            len = sizeof *frag_hdr;\n+        } else if (*nexthdr == IPPROTO_ROUTING) {\n+            const struct ip6_rthdr *rh = (struct ip6_rthdr *) data;\n+\n+            if (rh->ip6r_segleft > 0) {\n+                return true;\n+            }\n+\n+            *nexthdr = rh->ip6r_nxt;\n+            len = (rh->ip6r_len + 1) * 8;\n+        } else {\n+            const struct ip6_ext *ext_hdr = (struct ip6_ext *) data;\n+\n+            *nexthdr = ext_hdr->ip6e_nxt;\n+            len = (ext_hdr->ip6e_len + 1) * 8;\n+        }\n+\n+        if (remaining < len) {\n+            return false;\n+        }\n+        remaining -= len;\n+        data += len;\n+    }\n+\n+    return false;\n+}\n+\n+static void\n+packet_update_csum128(struct dp_packet *packet, uint8_t proto,\n+                      ovs_16aligned_be32 addr[4],\n+                      const struct in6_addr *new_addr)\n+{\n+    size_t l4_size = dp_packet_l4_size(packet);\n+\n+    if (proto == IPPROTO_TCP && l4_size >= TCP_HEADER_LEN) {\n+        if (dp_packet_l4_checksum_valid(packet)) {\n+            dp_packet_l4_checksum_set_partial(packet);\n+        } else {\n+            struct tcp_header *th = dp_packet_l4(packet);\n+\n+            th->tcp_csum = recalc_csum128(th->tcp_csum, addr, new_addr);\n+        }\n+    } else if (proto == IPPROTO_UDP && l4_size >= UDP_HEADER_LEN) {\n+        if (dp_packet_l4_checksum_valid(packet)) {\n+            dp_packet_l4_checksum_set_partial(packet);\n+        } else {\n+            struct udp_header *uh = dp_packet_l4(packet);\n+\n+            if (uh->udp_csum) {\n+                uh->udp_csum = recalc_csum128(uh->udp_csum, addr, new_addr);\n+                if (!uh->udp_csum) {\n+                    uh->udp_csum = htons(0xffff);\n+                }\n+            }\n+        }\n+    } else if (proto == IPPROTO_ICMPV6 &&\n+               l4_size >= sizeof(struct icmp6_header)) {\n+        struct icmp6_header *icmp = dp_packet_l4(packet);\n+\n+        icmp->icmp6_cksum = recalc_csum128(icmp->icmp6_cksum, addr, new_addr);\n+    }\n+}\n+\n+void\n+packet_set_ipv6_addr(struct dp_packet *packet, uint8_t proto,\n+                     ovs_16aligned_be32 addr[4],\n+                     const struct in6_addr *new_addr,\n+                     bool recalculate_csum)\n+{\n+    if (recalculate_csum) {\n+        packet_update_csum128(packet, proto, addr, new_addr);\n+    }\n+    memcpy(addr, new_addr, sizeof(ovs_be32[4]));\n+    pkt_metadata_init_conn(&packet->md);\n+}\n+\n+/* Modifies the IPv4 header fields of 'packet' to be consistent with 'src',\n+ * 'dst', 'tos', and 'ttl'.  Updates 'packet''s L4 checksums as appropriate.\n+ * 'packet' must contain a valid IPv4 packet with correctly populated l[347]\n+ * markers. */\n+void\n+packet_set_ipv4(struct dp_packet *packet, ovs_be32 src, ovs_be32 dst,\n+                uint8_t tos, uint8_t ttl)\n+{\n+    struct ip_header *nh = dp_packet_l3(packet);\n+\n+    if (get_16aligned_be32(&nh->ip_src) != src) {\n+        packet_set_ipv4_addr(packet, &nh->ip_src, src);\n+    }\n+\n+    if (get_16aligned_be32(&nh->ip_dst) != dst) {\n+        packet_set_ipv4_addr(packet, &nh->ip_dst, dst);\n+    }\n+\n+    if (nh->ip_tos != tos) {\n+        uint8_t *field = &nh->ip_tos;\n+\n+        if (dp_packet_ip_checksum_valid(packet)) {\n+            dp_packet_ip_checksum_set_partial(packet);\n+        } else {\n+            nh->ip_csum = recalc_csum16(nh->ip_csum, htons((uint16_t) *field),\n+                                        htons((uint16_t) tos));\n+        }\n+\n+        *field = tos;\n+    }\n+\n+    if (nh->ip_ttl != ttl) {\n+        uint8_t *field = &nh->ip_ttl;\n+\n+        if (dp_packet_ip_checksum_valid(packet)) {\n+            dp_packet_ip_checksum_set_partial(packet);\n+        } else {\n+            nh->ip_csum = recalc_csum16(nh->ip_csum, htons(*field << 8),\n+                                        htons(ttl << 8));\n+        }\n+\n+        *field = ttl;\n+    }\n+}\n+\n+/* Modifies the IPv6 header fields of 'packet' to be consistent with 'src',\n+ * 'dst', 'traffic class', and 'next hop'.  Updates 'packet''s L4 checksums as\n+ * appropriate. 'packet' must contain a valid IPv6 packet with correctly\n+ * populated l[34] offsets. */\n+void\n+packet_set_ipv6(struct dp_packet *packet, const struct in6_addr *src,\n+                const struct in6_addr *dst, uint8_t key_tc, ovs_be32 key_fl,\n+                uint8_t key_hl)\n+{\n+    struct ovs_16aligned_ip6_hdr *nh = dp_packet_l3(packet);\n+    bool recalc_csum = true;\n+    uint8_t proto = 0;\n+    bool rh_present;\n+\n+    rh_present = packet_rh_present(packet, &proto, &recalc_csum);\n+\n+    if (memcmp(&nh->ip6_src, src, sizeof(ovs_be32[4]))) {\n+        packet_set_ipv6_addr(packet, proto, nh->ip6_src.be32,\n+                             src, recalc_csum);\n+    }\n+\n+    if (memcmp(&nh->ip6_dst, dst, sizeof(ovs_be32[4]))) {\n+        packet_set_ipv6_addr(packet, proto, nh->ip6_dst.be32, dst,\n+                             !rh_present && recalc_csum);\n+    }\n+\n+    ip_set_ipv6_tc(&nh->ip6_flow, key_tc);\n+    ip_set_ipv6_flow_label(&nh->ip6_flow, key_fl);\n+    nh->ip6_hlim = key_hl;\n+}\n+\n+static void\n+packet_set_port(ovs_be16 *port, ovs_be16 new_port, ovs_be16 *csum)\n+{\n+    if (*port != new_port) {\n+        if (csum) {\n+            *csum = recalc_csum16(*csum, *port, new_port);\n+        }\n+        *port = new_port;\n+    }\n+}\n+\n+/* Sets the TCP source and destination port ('src' and 'dst' respectively) of\n+ * the TCP header contained in 'packet'.  'packet' must be a valid TCP packet\n+ * with its l4 offset properly populated. */\n+void\n+packet_set_tcp_port(struct dp_packet *packet, ovs_be16 src, ovs_be16 dst)\n+{\n+    struct tcp_header *th = dp_packet_l4(packet);\n+    ovs_be16 *csum = NULL;\n+\n+    if (dp_packet_l4_checksum_valid(packet)) {\n+        dp_packet_l4_checksum_set_partial(packet);\n+    } else {\n+        csum = &th->tcp_csum;\n+    }\n+\n+    packet_set_port(&th->tcp_src, src, csum);\n+    packet_set_port(&th->tcp_dst, dst, csum);\n+    pkt_metadata_init_conn(&packet->md);\n+}\n+\n+/* Sets the UDP source and destination port ('src' and 'dst' respectively) of\n+ * the UDP header contained in 'packet'.  'packet' must be a valid UDP packet\n+ * with its l4 offset properly populated. */\n+void\n+packet_set_udp_port(struct dp_packet *packet, ovs_be16 src, ovs_be16 dst)\n+{\n+    struct udp_header *uh = dp_packet_l4(packet);\n+\n+    if (dp_packet_l4_checksum_valid(packet)) {\n+        dp_packet_l4_checksum_set_partial(packet);\n+        packet_set_port(&uh->udp_src, src, NULL);\n+        packet_set_port(&uh->udp_dst, dst, NULL);\n+    } else {\n+        ovs_be16 *csum = uh->udp_csum ? &uh->udp_csum : NULL;\n+\n+        packet_set_port(&uh->udp_src, src, csum);\n+        packet_set_port(&uh->udp_dst, dst, csum);\n+\n+        if (csum && !uh->udp_csum) {\n+            uh->udp_csum = htons(0xffff);\n+        }\n+    }\n+\n+    pkt_metadata_init_conn(&packet->md);\n+}\n+\n+/* Sets the SCTP source and destination port ('src' and 'dst' respectively) of\n+ * the SCTP header contained in 'packet'.  'packet' must be a valid SCTP packet\n+ * with its l4 offset properly populated. */\n+void\n+packet_set_sctp_port(struct dp_packet *packet, ovs_be16 src, ovs_be16 dst)\n+{\n+    struct sctp_header *sh = dp_packet_l4(packet);\n+\n+    if (dp_packet_l4_checksum_valid(packet)) {\n+        dp_packet_l4_checksum_set_partial(packet);\n+        sh->sctp_src = src;\n+        sh->sctp_dst = dst;\n+    } else {\n+        ovs_be32 old_csum, old_correct_csum, new_csum;\n+        uint16_t tp_len = dp_packet_l4_size(packet);\n+\n+        old_csum = get_16aligned_be32(&sh->sctp_csum);\n+        put_16aligned_be32(&sh->sctp_csum, 0);\n+        old_correct_csum = crc32c((void *) sh, tp_len);\n+\n+        sh->sctp_src = src;\n+        sh->sctp_dst = dst;\n+\n+        new_csum = crc32c((void *) sh, tp_len);\n+        put_16aligned_be32(&sh->sctp_csum, old_csum ^ old_correct_csum\n+                           ^ new_csum);\n+    }\n+\n+    pkt_metadata_init_conn(&packet->md);\n+}\n+\n+/* Sets the ICMP type and code of the ICMP header contained in 'packet'.\n+ * 'packet' must be a valid ICMP packet with its l4 offset properly\n+ * populated. */\n+void\n+packet_set_icmp(struct dp_packet *packet, uint8_t type, uint8_t code)\n+{\n+    struct icmp_header *ih = dp_packet_l4(packet);\n+    ovs_be16 orig_tc = htons(ih->icmp_type << 8 | ih->icmp_code);\n+    ovs_be16 new_tc = htons(type << 8 | code);\n+\n+    if (orig_tc != new_tc) {\n+        ih->icmp_type = type;\n+        ih->icmp_code = code;\n+\n+        ih->icmp_csum = recalc_csum16(ih->icmp_csum, orig_tc, new_tc);\n+    }\n+    pkt_metadata_init_conn(&packet->md);\n+}\n+\n+/* Sets the ICMP id of the ICMP header contained in 'packet'.\n+ * 'packet' must be a valid ICMP packet with its l4 offset properly\n+ * populated. */\n+void\n+packet_set_icmp_id(struct dp_packet *packet, ovs_be16 icmp_id)\n+{\n+    struct icmp_header *ih = dp_packet_l4(packet);\n+\n+    if (!ih || dp_packet_l4_size(packet) < ICMP_HEADER_LEN) {\n+        return;\n+    }\n+\n+    ovs_be16 orig_ic = ih->icmp_fields.echo.id;\n+\n+    if (icmp_id != orig_ic) {\n+        ih->icmp_fields.echo.id = icmp_id;\n+        ih->icmp_csum = recalc_csum16(ih->icmp_csum, orig_ic, icmp_id);\n+    }\n+\n+    pkt_metadata_init_conn(&packet->md);\n+}\n+\n+uint8_t\n+packet_get_icmp_type(const struct dp_packet *packet)\n+{\n+    struct icmp_header *ih = dp_packet_l4(packet);\n+\n+    if (!ih || dp_packet_l4_size(packet) < ICMP_HEADER_LEN) {\n+        return 0;\n+    }\n+\n+    return ih->icmp_type;\n+}\n+\n+uint8_t\n+packet_get_ip_proto(const struct dp_packet *packet)\n+{\n+    struct eth_header *l2 = dp_packet_eth(packet);\n+    uint8_t ip_proto;\n+\n+    if (l2->eth_type == htons(ETH_TYPE_IPV6)) {\n+        struct ovs_16aligned_ip6_hdr *nh6 = dp_packet_l3(packet);\n+        ip_proto = nh6->ip6_ctlun.ip6_un1.ip6_un1_nxt;\n+    } else {\n+        struct ip_header *l3_hdr = dp_packet_l3(packet);\n+        ip_proto = l3_hdr->ip_proto;\n+    }\n+\n+    return ip_proto;\n+}\n+\n+bool\n+packet_is_icmpv4_info_message(const struct dp_packet *packet)\n+{\n+    uint8_t ip_proto, icmp_type;\n+\n+    ip_proto = packet_get_ip_proto(packet);\n+    if (ip_proto != IPPROTO_ICMP) {\n+        return false;\n+    }\n+\n+    icmp_type = packet_get_icmp_type(packet);\n+    if (icmp_type == ICMP4_ECHO_REQUEST ||\n+        icmp_type == ICMP4_ECHO_REPLY ||\n+        icmp_type == ICMP4_TIMESTAMP ||\n+        icmp_type == ICMP4_TIMESTAMPREPLY ||\n+        icmp_type == ICMP4_INFOREQUEST ||\n+        icmp_type == ICMP4_INFOREPLY) {\n+        return true;\n+    }\n+\n+    return false;\n+}\n+\n+/* Sets the IGMP type to IGMP_HOST_MEMBERSHIP_QUERY and populates the\n+ * v3 query header fields in 'packet'. 'packet' must be a valid IGMPv3\n+ * query packet with its l4 offset properly populated.\n+ */\n+void\n+packet_set_igmp3_query(struct dp_packet *packet, uint8_t max_resp,\n+                       ovs_be32 group, bool srs, uint8_t qrv, uint8_t qqic)\n+{\n+    struct igmpv3_query_header *igh = dp_packet_l4(packet);\n+    ovs_be16 orig_type_max_resp =\n+        htons(igh->type << 8 | igh->max_resp);\n+    ovs_be16 new_type_max_resp =\n+        htons(IGMP_HOST_MEMBERSHIP_QUERY << 8 | max_resp);\n+\n+    if (orig_type_max_resp != new_type_max_resp) {\n+        igh->type = IGMP_HOST_MEMBERSHIP_QUERY;\n+        igh->max_resp = max_resp;\n+        igh->csum = recalc_csum16(igh->csum, orig_type_max_resp,\n+                                  new_type_max_resp);\n+    }\n+\n+    ovs_be32 old_group = get_16aligned_be32(&igh->group);\n+\n+    if (old_group != group) {\n+        put_16aligned_be32(&igh->group, group);\n+        igh->csum = recalc_csum32(igh->csum, old_group, group);\n+    }\n+\n+    /* See RFC 3376 4.1.6. */\n+    if (qrv > 7) {\n+        qrv = 0;\n+    }\n+\n+    ovs_be16 orig_srs_qrv_qqic = htons(igh->srs_qrv << 8 | igh->qqic);\n+    ovs_be16 new_srs_qrv_qqic = htons(srs << 11 | qrv << 8 | qqic);\n+\n+    if (orig_srs_qrv_qqic != new_srs_qrv_qqic) {\n+        igh->srs_qrv = (srs << 3 | qrv);\n+        igh->qqic = qqic;\n+        igh->csum = recalc_csum16(igh->csum, orig_srs_qrv_qqic,\n+                                  new_srs_qrv_qqic);\n+    }\n+}\n+\n+void\n+packet_set_nd_ext(struct dp_packet *packet, const ovs_16aligned_be32 rso_flags,\n+                  const uint8_t opt_type)\n+{\n+    struct ovs_nd_msg *ns;\n+    struct ovs_nd_lla_opt *opt;\n+    int bytes_remain = dp_packet_l4_size(packet);\n+    struct ovs_16aligned_ip6_hdr * nh = dp_packet_l3(packet);\n+    uint32_t pseudo_hdr_csum = 0;\n+\n+    if (OVS_UNLIKELY(bytes_remain < sizeof(*ns))) {\n+        return;\n+    }\n+\n+    if (nh) {\n+        pseudo_hdr_csum = ip_csum_pseudoheader6(nh);\n+    }\n+\n+    ns = dp_packet_l4(packet);\n+    opt = &ns->options[0];\n+\n+    /* set RSO flags and option type */\n+    ns->rso_flags = rso_flags;\n+    opt->type = opt_type;\n+\n+    /* recalculate checksum */\n+    ovs_be16 *csum_value = &(ns->icmph.icmp6_cksum);\n+    *csum_value = 0;\n+    *csum_value = csum_finish(csum_continue(pseudo_hdr_csum,\n+                              &(ns->icmph), bytes_remain));\n+\n+}\n+\n+void\n+packet_set_nd(struct dp_packet *packet, const struct in6_addr *target,\n+              const struct eth_addr sll, const struct eth_addr tll)\n+{\n+    struct ovs_nd_msg *ns;\n+    struct ovs_nd_lla_opt *opt;\n+    int bytes_remain = dp_packet_l4_size(packet);\n+\n+    if (OVS_UNLIKELY(bytes_remain < sizeof(*ns))) {\n+        return;\n+    }\n+\n+    ns = dp_packet_l4(packet);\n+    opt = &ns->options[0];\n+    bytes_remain -= sizeof(*ns);\n+\n+    if (memcmp(&ns->target, target, sizeof(ovs_be32[4]))) {\n+        packet_set_ipv6_addr(packet, IPPROTO_ICMPV6, ns->target.be32, target,\n+                             true);\n+    }\n+\n+    while (bytes_remain >= ND_LLA_OPT_LEN && opt->len != 0\n+           && bytes_remain >= (opt->len * ND_LLA_OPT_LEN)) {\n+        if (opt->type == ND_OPT_SOURCE_LINKADDR && opt->len == 1) {\n+            if (!eth_addr_equals(opt->mac, sll)) {\n+                ovs_be16 *csum = &(ns->icmph.icmp6_cksum);\n+\n+                *csum = recalc_csum48(*csum, opt->mac, sll);\n+                opt->mac = sll;\n+            }\n+\n+            /* A packet can only contain one SLL or TLL option */\n+            break;\n+        } else if (opt->type == ND_OPT_TARGET_LINKADDR && opt->len == 1) {\n+            if (!eth_addr_equals(opt->mac, tll)) {\n+                ovs_be16 *csum = &(ns->icmph.icmp6_cksum);\n+\n+                *csum = recalc_csum48(*csum, opt->mac, tll);\n+                opt->mac = tll;\n+            }\n+\n+            /* A packet can only contain one SLL or TLL option */\n+            break;\n+        }\n+\n+        opt += opt->len;\n+        bytes_remain -= opt->len * ND_LLA_OPT_LEN;\n+    }\n+}\n+\n+#define ARP_PACKET_SIZE  (2 + ETH_HEADER_LEN + VLAN_HEADER_LEN + \\\n+                          ARP_ETH_HEADER_LEN)\n+\n+/* Clears 'b' and replaces its contents by an ARP frame with the specified\n+ * 'arp_op', 'arp_sha', 'arp_tha', 'arp_spa', and 'arp_tpa'.  The outer\n+ * Ethernet frame is initialized with Ethernet source 'arp_sha' and destination\n+ * 'arp_tha', except that destination ff:ff:ff:ff:ff:ff is used instead if\n+ * 'broadcast' is true.  Points the L3 header to the ARP header. */\n+void\n+compose_arp(struct dp_packet *b, uint16_t arp_op,\n+            const struct eth_addr arp_sha, const struct eth_addr arp_tha,\n+            bool broadcast, ovs_be32 arp_spa, ovs_be32 arp_tpa)\n+{\n+    compose_arp__(b);\n+\n+    struct eth_header *eth = dp_packet_eth(b);\n+    eth->eth_dst = broadcast ? eth_addr_broadcast : arp_tha;\n+    eth->eth_src = arp_sha;\n+\n+    struct arp_eth_header *arp = dp_packet_l3(b);\n+    arp->ar_op = htons(arp_op);\n+    arp->ar_sha = arp_sha;\n+    arp->ar_tha = arp_tha;\n+    put_16aligned_be32(&arp->ar_spa, arp_spa);\n+    put_16aligned_be32(&arp->ar_tpa, arp_tpa);\n+}\n+\n+/* Clears 'b' and replaces its contents by an ARP frame.  Sets the fields in\n+ * the Ethernet and ARP headers that are fixed for ARP frames to those fixed\n+ * values, and zeroes the other fields.  Points the L3 header to the ARP\n+ * header. */\n+void\n+compose_arp__(struct dp_packet *b)\n+{\n+    dp_packet_clear(b);\n+    dp_packet_prealloc_tailroom(b, ARP_PACKET_SIZE);\n+    dp_packet_reserve(b, 2 + VLAN_HEADER_LEN);\n+\n+    struct eth_header *eth = dp_packet_put_zeros(b, sizeof *eth);\n+    eth->eth_type = htons(ETH_TYPE_ARP);\n+\n+    struct arp_eth_header *arp = dp_packet_put_zeros(b, sizeof *arp);\n+    arp->ar_hrd = htons(ARP_HRD_ETHERNET);\n+    arp->ar_pro = htons(ARP_PRO_IP);\n+    arp->ar_hln = sizeof arp->ar_sha;\n+    arp->ar_pln = sizeof arp->ar_spa;\n+\n+    dp_packet_set_l3(b, arp);\n+\n+    b->packet_type = htonl(PT_ETH);\n+}\n+\n+/* This function expects packet with ethernet header with correct\n+ * l3 pointer set. */\n+void *\n+compose_ipv6(struct dp_packet *packet, uint8_t proto,\n+             const struct in6_addr *src, const struct in6_addr *dst,\n+             uint8_t key_tc, ovs_be32 key_fl, uint8_t key_hl, int size)\n+{\n+    struct ovs_16aligned_ip6_hdr *nh;\n+    void *data;\n+\n+    nh = dp_packet_l3(packet);\n+    nh->ip6_vfc = 0x60;\n+    nh->ip6_nxt = proto;\n+    nh->ip6_plen = htons(size);\n+    data = dp_packet_put_zeros(packet, size);\n+    dp_packet_set_l4(packet, data);\n+    packet_set_ipv6(packet, src, dst, key_tc, key_fl, key_hl);\n+    return data;\n+}\n+\n+/* Compose an IPv6 Neighbor Discovery Neighbor Solicitation message. */\n+void\n+compose_nd_ns(struct dp_packet *b, const struct eth_addr eth_src,\n+              const struct in6_addr *ipv6_src, const struct in6_addr *ipv6_dst)\n+{\n+    struct in6_addr sn_addr;\n+    struct eth_addr eth_dst;\n+    struct ovs_nd_msg *ns;\n+    struct ovs_nd_lla_opt *lla_opt;\n+    uint32_t icmp_csum;\n+\n+    in6_addr_solicited_node(&sn_addr, ipv6_dst);\n+    ipv6_multicast_to_ethernet(&eth_dst, &sn_addr);\n+\n+    eth_compose(b, eth_dst, eth_src, ETH_TYPE_IPV6, IPV6_HEADER_LEN);\n+    ns = compose_ipv6(b, IPPROTO_ICMPV6, ipv6_src, &sn_addr,\n+                      0, 0, 255, ND_MSG_LEN + ND_LLA_OPT_LEN);\n+\n+    ns->icmph.icmp6_type = ND_NEIGHBOR_SOLICIT;\n+    ns->icmph.icmp6_code = 0;\n+    put_16aligned_be32(&ns->rso_flags, htonl(0));\n+\n+    lla_opt = &ns->options[0];\n+    lla_opt->type = ND_OPT_SOURCE_LINKADDR;\n+    lla_opt->len = 1;\n+\n+    packet_set_nd(b, ipv6_dst, eth_src, eth_addr_zero);\n+\n+    ns->icmph.icmp6_cksum = 0;\n+    icmp_csum = ip_csum_pseudoheader6(dp_packet_l3(b));\n+    ns->icmph.icmp6_cksum = csum_finish(\n+        csum_continue(icmp_csum, ns, ND_MSG_LEN + ND_LLA_OPT_LEN));\n+}\n+\n+/* Compose an IPv6 Neighbor Discovery Neighbor Advertisement message. */\n+void\n+compose_nd_na(struct dp_packet *b,\n+              const struct eth_addr eth_src, const struct eth_addr eth_dst,\n+              const struct in6_addr *ipv6_src, const struct in6_addr *ipv6_dst,\n+              ovs_be32 rso_flags)\n+{\n+    struct ovs_nd_msg *na;\n+    struct ovs_nd_lla_opt *lla_opt;\n+    uint32_t icmp_csum;\n+\n+    eth_compose(b, eth_dst, eth_src, ETH_TYPE_IPV6, IPV6_HEADER_LEN);\n+    na = compose_ipv6(b, IPPROTO_ICMPV6, ipv6_src, ipv6_dst,\n+                      0, 0, 255, ND_MSG_LEN + ND_LLA_OPT_LEN);\n+\n+    na->icmph.icmp6_type = ND_NEIGHBOR_ADVERT;\n+    na->icmph.icmp6_code = 0;\n+    put_16aligned_be32(&na->rso_flags, rso_flags);\n+\n+    lla_opt = &na->options[0];\n+    lla_opt->type = ND_OPT_TARGET_LINKADDR;\n+    lla_opt->len = 1;\n+\n+    packet_set_nd(b, ipv6_src, eth_addr_zero, eth_src);\n+\n+    na->icmph.icmp6_cksum = 0;\n+    icmp_csum = ip_csum_pseudoheader6(dp_packet_l3(b));\n+    na->icmph.icmp6_cksum = csum_finish(csum_continue(\n+        icmp_csum, na, ND_MSG_LEN + ND_LLA_OPT_LEN));\n+}\n+\n+/* Compose an IPv6 Neighbor Discovery Router Advertisement message with\n+ * Source Link-layer Address Option and MTU Option.\n+ * Caller can call packet_put_ra_prefix_opt to append Prefix Information\n+ * Options to composed messags in 'b'. */\n+void\n+compose_nd_ra(struct dp_packet *b,\n+              const struct eth_addr eth_src, const struct eth_addr eth_dst,\n+              const struct in6_addr *ipv6_src, const struct in6_addr *ipv6_dst,\n+              uint8_t cur_hop_limit, uint8_t mo_flags,\n+              ovs_be16 router_lt, ovs_be32 reachable_time,\n+              ovs_be32 retrans_timer, uint32_t mtu)\n+{\n+    /* Don't compose Router Advertisement packet with MTU Option if mtu\n+     * value is 0. */\n+    bool with_mtu = mtu != 0;\n+    size_t mtu_opt_len = with_mtu ? ND_MTU_OPT_LEN : 0;\n+\n+    eth_compose(b, eth_dst, eth_src, ETH_TYPE_IPV6, IPV6_HEADER_LEN);\n+\n+    struct ovs_ra_msg *ra = compose_ipv6(\n+        b, IPPROTO_ICMPV6, ipv6_src, ipv6_dst, 0, 0, 255,\n+        RA_MSG_LEN + ND_LLA_OPT_LEN + mtu_opt_len);\n+    ra->icmph.icmp6_type = ND_ROUTER_ADVERT;\n+    ra->icmph.icmp6_code = 0;\n+    ra->cur_hop_limit = cur_hop_limit;\n+    ra->mo_flags = mo_flags;\n+    ra->router_lifetime = router_lt;\n+    ra->reachable_time = reachable_time;\n+    ra->retrans_timer = retrans_timer;\n+\n+    struct ovs_nd_lla_opt *lla_opt = ra->options;\n+    lla_opt->type = ND_OPT_SOURCE_LINKADDR;\n+    lla_opt->len = 1;\n+    lla_opt->mac = eth_src;\n+\n+    if (with_mtu) {\n+        /* ovs_nd_mtu_opt has the same size with ovs_nd_lla_opt. */\n+        struct ovs_nd_mtu_opt *mtu_opt\n+            = (struct ovs_nd_mtu_opt *)(lla_opt + 1);\n+        mtu_opt->type = ND_OPT_MTU;\n+        mtu_opt->len = 1;\n+        mtu_opt->reserved = 0;\n+        put_16aligned_be32(&mtu_opt->mtu, htonl(mtu));\n+    }\n+\n+    ra->icmph.icmp6_cksum = 0;\n+    uint32_t icmp_csum = ip_csum_pseudoheader6(dp_packet_l3(b));\n+    ra->icmph.icmp6_cksum = csum_finish(csum_continue(\n+        icmp_csum, ra, RA_MSG_LEN + ND_LLA_OPT_LEN + mtu_opt_len));\n+}\n+\n+/* Append an IPv6 Neighbor Discovery Prefix Information option to a\n+ * Router Advertisement message. */\n+void\n+packet_put_ra_prefix_opt(struct dp_packet *b,\n+                         uint8_t plen, uint8_t la_flags,\n+                         ovs_be32 valid_lifetime, ovs_be32 preferred_lifetime,\n+                         const ovs_be128 prefix)\n+{\n+    size_t prev_l4_size = dp_packet_l4_size(b);\n+    struct ovs_16aligned_ip6_hdr *nh = dp_packet_l3(b);\n+    nh->ip6_plen = htons(prev_l4_size + ND_PREFIX_OPT_LEN);\n+\n+    struct ovs_nd_prefix_opt *prefix_opt =\n+        dp_packet_put_uninit(b, sizeof *prefix_opt);\n+    prefix_opt->type = ND_OPT_PREFIX_INFORMATION;\n+    prefix_opt->len = 4;\n+    prefix_opt->prefix_len = plen;\n+    prefix_opt->la_flags = la_flags;\n+    put_16aligned_be32(&prefix_opt->valid_lifetime, valid_lifetime);\n+    put_16aligned_be32(&prefix_opt->preferred_lifetime, preferred_lifetime);\n+    put_16aligned_be32(&prefix_opt->reserved, 0);\n+    memcpy(prefix_opt->prefix.be32, prefix.be32, sizeof(ovs_be32[4]));\n+\n+    struct ovs_ra_msg *ra = dp_packet_l4(b);\n+    ra->icmph.icmp6_cksum = 0;\n+    uint32_t icmp_csum = ip_csum_pseudoheader6(dp_packet_l3(b));\n+    ra->icmph.icmp6_cksum = csum_finish(csum_continue(\n+        icmp_csum, ra, prev_l4_size + ND_PREFIX_OPT_LEN));\n+}\n+\n+void\n+IP_ECN_set_ce(struct dp_packet *pkt, bool is_ipv6)\n+{\n+    if (is_ipv6) {\n+        ovs_16aligned_be32 *ip6 = dp_packet_l3(pkt);\n+\n+        put_16aligned_be32(ip6, get_16aligned_be32(ip6) |\n+                                htonl(IP_ECN_CE << 20));\n+    } else {\n+        struct ip_header *nh = dp_packet_l3(pkt);\n+        uint8_t tos = nh->ip_tos;\n+\n+        tos |= IP_ECN_CE;\n+        if (nh->ip_tos != tos) {\n+            if (dp_packet_ip_checksum_valid(pkt)) {\n+                dp_packet_ip_checksum_set_partial(pkt);\n+            } else {\n+                nh->ip_csum = recalc_csum16(nh->ip_csum, htons(nh->ip_tos),\n+                                            htons((uint16_t) tos));\n+            }\n+\n+            nh->ip_tos = tos;\n+        }\n+    }\n+}\n+\n+/* Set TCP checksum field in packet 'p' with complete checksum.\n+ * The packet must have the L3 and L4 offsets. */\n+void\n+packet_tcp_complete_csum(struct dp_packet *p, bool inner)\n+{\n+    struct tcp_header *tcp;\n+    size_t tcp_sz;\n+    void *ip_hdr;\n+\n+    if (inner) {\n+        tcp = dp_packet_inner_l4(p);\n+        ip_hdr = dp_packet_inner_l3(p);\n+        tcp_sz = dp_packet_inner_l4_size(p);\n+    } else {\n+        tcp = dp_packet_l4(p);\n+        ip_hdr = dp_packet_l3(p);\n+        tcp_sz = dp_packet_l4_size(p);\n+    }\n+\n+    ovs_assert(tcp);\n+    ovs_assert(ip_hdr);\n+\n+    tcp->tcp_csum = 0;\n+    if (IP_VER(((const struct ip_header *) ip_hdr)->ip_ihl_ver) == 4) {\n+        struct ip_header *ip = ip_hdr;\n+\n+        tcp->tcp_csum = csum_finish(csum_continue(ip_csum_pseudoheader(ip),\n+                                                  tcp, tcp_sz));\n+    } else {\n+        struct ovs_16aligned_ip6_hdr *ip6 = ip_hdr;\n+\n+        tcp->tcp_csum = ip_csum_upperlayer6(ip6, tcp, ip6->ip6_nxt,\n+                                                tcp_sz);\n+    }\n+\n+    if (inner) {\n+        dp_packet_inner_l4_checksum_set_good(p);\n+    } else {\n+        dp_packet_l4_checksum_set_good(p);\n+    }\n+}\n+\n+/* Set UDP checksum field in packet 'p' with complete checksum.\n+ * The packet must have the L3 and L4 offsets. */\n+void\n+packet_udp_complete_csum(struct dp_packet *p, bool inner)\n+{\n+    struct udp_header *udp;\n+    size_t udp_sz;\n+    void *ip_hdr;\n+\n+    if (inner) {\n+        udp = dp_packet_inner_l4(p);\n+        ip_hdr = dp_packet_inner_l3(p);\n+        udp_sz = dp_packet_inner_l4_size(p);\n+    } else {\n+        udp = dp_packet_l4(p);\n+        ip_hdr = dp_packet_l3(p);\n+        udp_sz = dp_packet_l4_size(p);\n+    }\n+\n+    ovs_assert(udp);\n+    ovs_assert(ip_hdr);\n+\n+    /* Skip csum calculation if the udp_csum is zero. */\n+    if (!udp->udp_csum) {\n+        goto out;\n+    }\n+\n+    udp->udp_csum = 0;\n+    if (IP_VER(((const struct ip_header *) ip_hdr)->ip_ihl_ver) == 4) {\n+        struct ip_header *ip = ip_hdr;\n+\n+        udp->udp_csum = csum_finish(csum_continue(ip_csum_pseudoheader(ip),\n+                                                  udp, udp_sz));\n+    } else {\n+        struct ovs_16aligned_ip6_hdr *ip6 = ip_hdr;\n+\n+        udp->udp_csum = ip_csum_upperlayer6(ip6, udp, ip6->ip6_nxt,\n+                                                udp_sz);\n+    }\n+\n+    if (!udp->udp_csum) {\n+        udp->udp_csum = htons(0xffff);\n+    }\n+\n+out:\n+    if (inner) {\n+        dp_packet_inner_l4_checksum_set_good(p);\n+    } else {\n+        dp_packet_l4_checksum_set_good(p);\n+    }\n+}\n+\n+/* This helper computes a \"constant\" UDP checksum without looking at the\n+ * L4 payload.\n+ *\n+ * This is possible when L4 is either TCP or UDP: the L4 payload checksum\n+ * is either computed in SW or in HW later, but its contribution to the\n+ * outer checksum is cancelled by the L4 payload being part of the global\n+ * packet sum. */\n+bool\n+packet_udp_tunnel_csum(struct dp_packet *p)\n+{\n+    struct ip_header *inner_ip;\n+    const void *inner_l4_data;\n+    char *after_inner_l4_csum;\n+    size_t inner_l4_csum_off;\n+    struct udp_header *udp;\n+    ovs_be16 inner_l4_csum;\n+    uint32_t partial_csum;\n+    struct ip_header *ip;\n+    uint32_t inner_csum;\n+    uint16_t tso_segsz;\n+    bool inner_ipv4;\n+    void *inner_l4;\n+\n+    inner_ip = dp_packet_inner_l3(p);\n+    inner_l4 = dp_packet_inner_l4(p);\n+    ip = dp_packet_l3(p);\n+    udp = dp_packet_l4(p);\n+\n+    if (dp_packet_inner_l4_proto_tcp(p)) {\n+        inner_l4_csum_off = offsetof(struct tcp_header, tcp_csum);\n+        inner_l4_data = dp_packet_get_inner_tcp_payload(p);\n+        if (!inner_l4_data) {\n+            /* Malformed packet. */\n+            return false;\n+        }\n+    } else if (dp_packet_inner_l4_proto_udp(p)) {\n+        inner_l4_csum_off = offsetof(struct udp_header, udp_csum);\n+        inner_l4_data = (char *) inner_l4 + sizeof (struct udp_header);\n+        if (((struct udp_header *) inner_l4)->udp_csum == 0) {\n+            /* There is no nested checksum.\n+             * No choice but compute a full checksum. */\n+            return false;\n+        }\n+    } else {\n+        /* This optimisation applies only to inner TCP/UDP. */\n+        return false;\n+    }\n+\n+    if (!dp_packet_inner_l4_checksum_valid(p)) {\n+        /* We have no idea about the contribution of the payload data\n+         * and what the L4 checksum put in the packet data looks like.\n+         * Simpler is to let a full checksum happen. */\n+        return false;\n+    }\n+\n+    inner_ipv4 = IP_VER(inner_ip->ip_ihl_ver) == 4;\n+    if (inner_ipv4) {\n+        inner_csum = ip_csum_pseudoheader(inner_ip);\n+    } else {\n+        struct ovs_16aligned_ip6_hdr *inner_ip6 = dp_packet_inner_l3(p);\n+\n+        inner_csum = ip_csum_pseudoheader6(inner_ip6);\n+    }\n+\n+    inner_csum = csum_continue(inner_csum, inner_l4, inner_l4_csum_off);\n+    after_inner_l4_csum = (char *) inner_l4 + inner_l4_csum_off + 2;\n+    inner_l4_csum = csum_finish(csum_continue(inner_csum, after_inner_l4_csum,\n+        (char *) inner_l4_data - after_inner_l4_csum));\n+    /* Important: for inner UDP, a null inner_l4_csum here should in theory be\n+     * replaced with 0xffff.  However, since the only use of inner_l4_csum is\n+     * for the final outer checksum with a csum_add16() below, we can skip this\n+     * entirely because adding 0xffff will have the same effect as adding 0x0\n+     * after reducing in csum_finish. */\n+\n+    udp->udp_csum = 0;\n+    if (IP_VER(ip->ip_ihl_ver) == 4) {\n+        partial_csum = ip_csum_pseudoheader(ip);\n+    } else {\n+        struct ovs_16aligned_ip6_hdr *ip6 = dp_packet_l3(p);\n+\n+        partial_csum = ip_csum_pseudoheader6(ip6);\n+    }\n+\n+    partial_csum = csum_continue(partial_csum, udp,\n+        (char *) inner_ip - (char *) udp);\n+    if (!inner_ipv4 || !dp_packet_inner_ip_checksum_valid(p)) {\n+        /* IPv6 has no checksum, so for inner IPv6, we need to sum the header.\n+         *\n+         * In IPv4 case, if inner checksum is already good or HW offload\n+         * has been requested, the (final) sum of the IPv4 header will be 0.\n+         * Otherwise, we need to sum the header like for IPv6. */\n+        partial_csum = csum_continue(partial_csum, inner_ip,\n+            (char *) inner_l4 - (char *) inner_ip);\n+    }\n+    partial_csum = csum_continue(partial_csum, inner_l4, inner_l4_csum_off);\n+    partial_csum = csum_add16(partial_csum, inner_l4_csum);\n+    partial_csum = csum_continue(partial_csum, after_inner_l4_csum,\n+        (char *) inner_l4_data - after_inner_l4_csum);\n+    udp->udp_csum = csum_finish(partial_csum);\n+    tso_segsz = dp_packet_get_tso_segsz(p);\n+    if (tso_segsz) {\n+        uint16_t payload_len = dp_packet_get_inner_tcp_payload_length(p);\n+\n+        ovs_assert(payload_len == tso_segsz * dp_packet_gso_nr_segs(p));\n+\n+        /* The pseudo header used in the outer UDP checksum is dependent on\n+         * the ip_tot_len / ip6_plen which was a reflection of the TSO frame\n+         * size. The segmented packet will be shorter. */\n+        udp->udp_csum = recalc_csum16(udp->udp_csum, htons(payload_len),\n+                                      htons(tso_segsz));\n+\n+        /* When segmenting the packet, various headers get updated:\n+         * - inner L3\n+         *   - for IPv4, ip_tot_len is updated, BUT it is not affecting the\n+         *     outer UDP checksum because the IPv4 header itself contains\n+         *     a checksum that compensates for this update,\n+         *   - for IPv6, ip6_plen is updated, and this must be considered,\n+         * - inner L4\n+         *   - inner pseudo header used in the TCP checksum is dependent on\n+         *     the inner ip_tot_len / ip6_plen,\n+         *   - TCP seq number is updated,\n+         *   - the HW may change some TCP flags (think PSH/FIN),\n+         *   BUT the TCP checksum will compensate for those updates,\n+         *\n+         * Summary: we only care about the inner IPv6 header update.\n+         */\n+        if (IP_VER(inner_ip->ip_ihl_ver) != 4) {\n+            udp->udp_csum = recalc_csum16(udp->udp_csum, htons(payload_len),\n+                                          htons(tso_segsz));\n+        }\n+    }\n+    if (!udp->udp_csum) {\n+        udp->udp_csum = htons(0xffff);\n+    }\n+    dp_packet_l4_checksum_set_good(p);\n+\n+    return true;\n+}\n+\n+/* Set SCTP checksum field in packet 'p' with complete checksum.\n+ * The packet must have the L3 and L4 offsets. */\n+void\n+packet_sctp_complete_csum(struct dp_packet *p, bool inner)\n+{\n+    struct sctp_header *sh;\n+    uint16_t tp_len;\n+    ovs_be32 csum;\n+\n+    if (inner) {\n+        sh = dp_packet_inner_l4(p);\n+        tp_len = dp_packet_inner_l4_size(p);\n+    } else {\n+        sh = dp_packet_l4(p);\n+        tp_len = dp_packet_l4_size(p);\n+    }\n+\n+    ovs_assert(sh);\n+\n+    put_16aligned_be32(&sh->sctp_csum, 0);\n+    csum = crc32c((void *) sh, tp_len);\n+    put_16aligned_be32(&sh->sctp_csum, csum);\n+\n+    if (inner) {\n+        dp_packet_inner_l4_checksum_set_good(p);\n+    } else {\n+        dp_packet_l4_checksum_set_good(p);\n+    }\n+}\ndiff --git a/lib/dp-packet.h b/lib/dp-packet.h\nindex 55114d0b3..7e02d6561 100644\n--- a/lib/dp-packet.h\n+++ b/lib/dp-packet.h\n@@ -17,22 +17,34 @@\n #ifndef DPBUF_H\n #define DPBUF_H 1\n \n+#include <inttypes.h>\n+#include <sys/types.h>\n #include <stddef.h>\n #include <stdint.h>\n+#include <string.h>\n \n #ifdef DPDK_NETDEV\n #include <rte_config.h>\n #include <rte_mbuf.h>\n #endif\n \n+#include \"compiler.h\"\n #include \"csum.h\"\n+#include \"flow.h\"\n+#include \"openvswitch/geneve.h\"\n+#include \"hash.h\"\n+#include \"openvswitch/list.h\"\n #include \"netdev-afxdp.h\"\n #include \"netdev-dpdk.h\"\n #include \"net-proto.h\"\n-#include \"openvswitch/list.h\"\n-#include \"packets.h\"\n+#include \"openvswitch/nsh.h\"\n+#include \"odp-netlink.h\"\n+#include \"openvswitch/net-proto.h\"\n+#include \"random.h\"\n+#include \"timeval.h\"\n+#include \"openvswitch/types.h\"\n #include \"util.h\"\n-#include \"flow.h\"\n+#include \"unaligned.h\"\n \n #ifdef  __cplusplus\n extern \"C\" {\n@@ -1504,6 +1516,98 @@ dp_packet_update_rss_hash_ipv6_tcp_udp(struct dp_packet *packet)\n     dp_packet_set_rss_hash(packet, hash);\n }\n \n+\n+void compose_rarp(struct dp_packet *, const struct eth_addr);\n+\n+void eth_push_vlan(struct dp_packet *, ovs_be16 tpid, ovs_be16 tci);\n+void eth_pop_vlan(struct dp_packet *);\n+\n+const char *eth_from_hex(const char *hex, struct dp_packet **packetp);\n+\n+void set_mpls_lse(struct dp_packet *, ovs_be32 label);\n+void push_mpls(struct dp_packet *packet, ovs_be16 ethtype, ovs_be32 lse);\n+void pop_mpls(struct dp_packet *, ovs_be16 ethtype);\n+void add_mpls(struct dp_packet *packet, ovs_be16 ethtype, ovs_be32 lse,\n+              bool l3_encap);\n+\n+\n+void push_eth(struct dp_packet *packet, const struct eth_addr *dst,\n+              const struct eth_addr *src);\n+void pop_eth(struct dp_packet *packet);\n+\n+void push_nsh(struct dp_packet *packet, const struct nsh_hdr *nsh_hdr_src);\n+bool pop_nsh(struct dp_packet *packet);\n+\n+void *eth_compose(struct dp_packet *, const struct eth_addr eth_dst,\n+                  const struct eth_addr eth_src, uint16_t eth_type,\n+                  size_t size);\n+void *snap_compose(struct dp_packet *, const struct eth_addr eth_dst,\n+                   const struct eth_addr eth_src,\n+                   unsigned int oui, uint16_t snap_type, size_t size);\n+void packet_set_ipv4(struct dp_packet *, ovs_be32 src, ovs_be32 dst,\n+                     uint8_t tos, uint8_t ttl);\n+void packet_set_ipv4_addr(struct dp_packet *packet, ovs_16aligned_be32 *addr,\n+                          ovs_be32 new_addr);\n+void packet_set_ipv6(struct dp_packet *, const struct in6_addr *src,\n+                     const struct in6_addr *dst, uint8_t tc,\n+                     ovs_be32 fl, uint8_t hlmit);\n+void packet_set_ipv6_addr(struct dp_packet *packet, uint8_t proto,\n+                          ovs_16aligned_be32 addr[4],\n+                          const struct in6_addr *new_addr,\n+                          bool recalculate_csum);\n+void packet_set_tcp_port(struct dp_packet *, ovs_be16 src, ovs_be16 dst);\n+void packet_set_udp_port(struct dp_packet *, ovs_be16 src, ovs_be16 dst);\n+void packet_set_sctp_port(struct dp_packet *, ovs_be16 src, ovs_be16 dst);\n+void packet_set_icmp(struct dp_packet *, uint8_t type, uint8_t code);\n+void packet_set_icmp_id(struct dp_packet *, ovs_be16 icmp_id);\n+uint8_t packet_get_icmp_type(const struct dp_packet *packet);\n+uint8_t packet_get_ip_proto(const struct dp_packet *packet);\n+bool packet_is_icmpv4_info_message(const struct dp_packet *packet);\n+void packet_set_nd(struct dp_packet *, const struct in6_addr *target,\n+                   const struct eth_addr sll, const struct eth_addr tll);\n+void packet_set_nd_ext(struct dp_packet *packet,\n+                       const ovs_16aligned_be32 rso_flags,\n+                       const uint8_t opt_type);\n+void packet_set_igmp3_query(struct dp_packet *, uint8_t max_resp,\n+                            ovs_be32 group, bool srs, uint8_t qrv,\n+                            uint8_t qqic);\n+void *compose_ipv6(struct dp_packet *packet, uint8_t proto,\n+                   const struct in6_addr *src, const struct in6_addr *dst,\n+                   uint8_t key_tc, ovs_be32 key_fl, uint8_t key_hl, int size);\n+void compose_arp__(struct dp_packet *);\n+void compose_arp(struct dp_packet *, uint16_t arp_op,\n+                 const struct eth_addr arp_sha,\n+                 const struct eth_addr arp_tha, bool broadcast,\n+                 ovs_be32 arp_spa, ovs_be32 arp_tpa);\n+void compose_nd_ns(struct dp_packet *, const struct eth_addr eth_src,\n+                   const struct in6_addr *ipv6_src,\n+                   const struct in6_addr *ipv6_dst);\n+void compose_nd_na(struct dp_packet *, const struct eth_addr eth_src,\n+                   const struct eth_addr eth_dst,\n+                   const struct in6_addr *ipv6_src,\n+                   const struct in6_addr *ipv6_dst,\n+                   ovs_be32 rso_flags);\n+void compose_nd_ra(struct dp_packet *,\n+                   const struct eth_addr eth_src,\n+                   const struct eth_addr eth_dst,\n+                   const struct in6_addr *ipv6_src,\n+                   const struct in6_addr *ipv6_dst,\n+                   uint8_t cur_hop_limit, uint8_t mo_flags,\n+                   ovs_be16 router_lt, ovs_be32 reachable_time,\n+                   ovs_be32 retrans_timer, uint32_t mtu);\n+void packet_put_ra_prefix_opt(struct dp_packet *,\n+                              uint8_t plen, uint8_t la_flags,\n+                              ovs_be32 valid_lifetime,\n+                              ovs_be32 preferred_lifetime,\n+                              const ovs_be128 router_prefix);\n+bool packet_rh_present(struct dp_packet *packet, uint8_t *nexthdr,\n+                       bool *first_frag);\n+void IP_ECN_set_ce(struct dp_packet *pkt, bool is_ipv6);\n+void packet_tcp_complete_csum(struct dp_packet *, bool is_inner);\n+void packet_udp_complete_csum(struct dp_packet *, bool is_inner);\n+bool packet_udp_tunnel_csum(struct dp_packet *);\n+void packet_sctp_complete_csum(struct dp_packet *, bool is_inner);\n+\n #ifdef  __cplusplus\n }\n #endif\ndiff --git a/lib/dpctl.c b/lib/dpctl.c\nindex 752168b5a..5be6022cb 100644\n--- a/lib/dpctl.c\n+++ b/lib/dpctl.c\n@@ -43,7 +43,6 @@\n #include \"odp-util.h\"\n #include \"openvswitch/ofpbuf.h\"\n #include \"openvswitch/ofp-ct.h\"\n-#include \"packets.h\"\n #include \"openvswitch/shash.h\"\n #include \"simap.h\"\n #include \"smap.h\"\ndiff --git a/lib/dpif-netdev-extract-avx512.c b/lib/dpif-netdev-extract-avx512.c\nindex 8741bbf29..18aa416e5 100644\n--- a/lib/dpif-netdev-extract-avx512.c\n+++ b/lib/dpif-netdev-extract-avx512.c\n@@ -48,7 +48,6 @@\n #include \"dpif-netdev-private-extract.h\"\n #include \"dpif-netdev-private-flow.h\"\n #include \"dp-packet.h\"\n-#include \"packets.h\"\n \n /* AVX512-BW level permutex2var_epi8 emulation. */\n static inline __m512i\ndiff --git a/lib/dpif-netdev-lookup.c b/lib/dpif-netdev-lookup.c\nindex 4c1379aa5..eb73f3b57 100644\n--- a/lib/dpif-netdev-lookup.c\n+++ b/lib/dpif-netdev-lookup.c\n@@ -19,6 +19,7 @@\n #include \"dpif-netdev-lookup.h\"\n \n #include \"cpu.h\"\n+#include \"openvswitch/dynamic-string.h\"\n #include \"openvswitch/vlog.h\"\n \n VLOG_DEFINE_THIS_MODULE(dpif_netdev_lookup);\ndiff --git a/lib/dpif-netdev-private-extract.c b/lib/dpif-netdev-private-extract.c\nindex ded08fd3e..116db5cec 100644\n--- a/lib/dpif-netdev-private-extract.c\n+++ b/lib/dpif-netdev-private-extract.c\n@@ -24,6 +24,7 @@\n #include \"dpif-netdev-private-dpcls.h\"\n #include \"dpif-netdev-private-extract.h\"\n #include \"dpif-netdev-private-thread.h\"\n+#include \"openvswitch/dynamic-string.h\"\n #include \"flow.h\"\n #include \"openvswitch/vlog.h\"\n #include \"ovs-thread.h\"\ndiff --git a/lib/dpif-netdev-private-flow.h b/lib/dpif-netdev-private-flow.h\nindex 308c5113f..15c2d7d1c 100644\n--- a/lib/dpif-netdev-private-flow.h\n+++ b/lib/dpif-netdev-private-flow.h\n@@ -25,6 +25,7 @@\n #include <stdint.h>\n \n #include \"cmap.h\"\n+#include \"netlink-protocol.h\"\n #include \"openvswitch/thread.h\"\n \n #ifdef  __cplusplus\ndiff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c\nindex 49f4fa2ac..2bd8dd4fb 100644\n--- a/lib/dpif-netdev.c\n+++ b/lib/dpif-netdev.c\n@@ -74,7 +74,6 @@\n #include \"openvswitch/vlog.h\"\n #include \"ovs-numa.h\"\n #include \"ovs-rcu.h\"\n-#include \"packets.h\"\n #include \"openvswitch/poll-loop.h\"\n #include \"pvector.h\"\n #include \"random.h\"\ndiff --git a/lib/dpif-netdev.h b/lib/dpif-netdev.h\nindex 6db6ed2e2..ecd450ccb 100644\n--- a/lib/dpif-netdev.h\n+++ b/lib/dpif-netdev.h\n@@ -23,7 +23,6 @@\n #include \"dpif.h\"\n #include \"openvswitch/types.h\"\n #include \"dp-packet.h\"\n-#include \"packets.h\"\n \n #ifdef  __cplusplus\n extern \"C\" {\ndiff --git a/lib/dpif-netlink-rtnl.c b/lib/dpif-netlink-rtnl.c\nindex ca803d0af..9755a9c9d 100644\n--- a/lib/dpif-netlink-rtnl.c\n+++ b/lib/dpif-netlink-rtnl.c\n@@ -24,6 +24,7 @@\n \n #include \"dpif-netlink.h\"\n #include \"netdev-vport.h\"\n+#include \"netlink.h\"\n #include \"netlink-socket.h\"\n #include \"openvswitch/vlog.h\"\n \ndiff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c\nindex f22a87934..7ddaad8df 100644\n--- a/lib/dpif-netlink.c\n+++ b/lib/dpif-netlink.c\n@@ -58,7 +58,6 @@\n #include \"openvswitch/thread.h\"\n #include \"openvswitch/usdt-probes.h\"\n #include \"openvswitch/vlog.h\"\n-#include \"packets.h\"\n #include \"random.h\"\n #include \"sset.h\"\n #include \"timeval.h\"\ndiff --git a/lib/dpif-offload-dpdk-netdev.c b/lib/dpif-offload-dpdk-netdev.c\nindex efe99065e..ed3977032 100644\n--- a/lib/dpif-offload-dpdk-netdev.c\n+++ b/lib/dpif-offload-dpdk-netdev.c\n@@ -27,13 +27,14 @@\n #include \"dpif-netdev.h\"\n #include \"dpif-offload.h\"\n #include \"dpif-offload-dpdk-private.h\"\n+#include \"openvswitch/dynamic-string.h\"\n #include \"netdev-provider.h\"\n #include \"netdev-vport.h\"\n+#include \"netlink.h\"\n #include \"odp-util.h\"\n #include \"openvswitch/match.h\"\n #include \"openvswitch/vlog.h\"\n #include \"ovs-rcu.h\"\n-#include \"packets.h\"\n #include \"uuid.h\"\n \n VLOG_DEFINE_THIS_MODULE(dpif_offload_dpdk_netdev);\ndiff --git a/lib/dpif-offload-dpdk.c b/lib/dpif-offload-dpdk.c\nindex 2991c24bb..fed8e4882 100644\n--- a/lib/dpif-offload-dpdk.c\n+++ b/lib/dpif-offload-dpdk.c\n@@ -20,11 +20,14 @@\n #include \"dpif-offload.h\"\n #include \"dpif-offload-provider.h\"\n #include \"dpif-offload-dpdk-private.h\"\n+#include \"openvswitch/dynamic-string.h\"\n #include \"id-fpool.h\"\n #include \"mov-avg.h\"\n #include \"mpsc-queue.h\"\n #include \"netdev-provider.h\"\n #include \"netdev-vport.h\"\n+#include \"net-proto.h\"\n+#include \"openvswitch/ofpbuf.h\"\n #include \"util.h\"\n #include \"uuid.h\"\n \ndiff --git a/lib/dpif.c b/lib/dpif.c\nindex 3178a24dd..f7b39179a 100644\n--- a/lib/dpif.c\n+++ b/lib/dpif.c\n@@ -35,7 +35,6 @@\n #include \"netlink.h\"\n #include \"odp-execute.h\"\n #include \"odp-util.h\"\n-#include \"packets.h\"\n #include \"route-table.h\"\n #include \"seq.h\"\n #include \"sset.h\"\ndiff --git a/lib/dpif.h b/lib/dpif.h\nindex 3e6a34a25..c419bf775 100644\n--- a/lib/dpif.h\n+++ b/lib/dpif.h\n@@ -384,7 +384,6 @@\n #include \"openflow/openflow.h\"\n #include \"openvswitch/ofp-meter.h\"\n #include \"ovs-numa.h\"\n-#include \"packets.h\"\n #include \"util.h\"\n \n #ifdef  __cplusplus\ndiff --git a/lib/flow.c b/lib/flow.c\nindex 20f7d6ea8..26e140c8d 100644\n--- a/lib/flow.c\n+++ b/lib/flow.c\n@@ -36,7 +36,6 @@\n #include \"openvswitch/match.h\"\n #include \"dp-packet.h\"\n #include \"openflow/openflow.h\"\n-#include \"packets.h\"\n #include \"odp-util.h\"\n #include \"random.h\"\n #include \"unaligned.h\"\n@@ -44,6 +43,7 @@\n #include \"openvswitch/nsh.h\"\n #include \"ovs-router.h\"\n #include \"lib/netdev-provider.h\"\n+#include \"tun-metadata.h\"\n #include \"openvswitch/vlog.h\"\n \n VLOG_DEFINE_THIS_MODULE(flow);\n@@ -3716,6 +3716,18 @@ flow_limit_vlans(int vlan_limit)\n     }\n }\n \n+struct in6_addr\n+flow_tnl_dst(const struct flow_tnl *tnl)\n+{\n+    return tnl->ip_dst ? in6_addr_mapped_ipv4(tnl->ip_dst) : tnl->ipv6_dst;\n+}\n+\n+struct in6_addr\n+flow_tnl_src(const struct flow_tnl *tnl)\n+{\n+    return tnl->ip_src ? in6_addr_mapped_ipv4(tnl->ip_src) : tnl->ipv6_src;\n+}\n+\n struct netdev *\n flow_get_tunnel_netdev(struct flow_tnl *tunnel)\n {\ndiff --git a/lib/flow.h b/lib/flow.h\nindex bf0656cac..a9be873d7 100644\n--- a/lib/flow.h\n+++ b/lib/flow.h\n@@ -30,8 +30,8 @@\n #include \"openflow/openflow.h\"\n #include \"openvswitch/flow.h\"\n #include \"net-proto.h\"\n-#include \"packets.h\"\n #include \"hash.h\"\n+#include \"odp-netlink.h\"\n #include \"util.h\"\n \n struct dpif_flow_stats;\n@@ -973,6 +973,161 @@ static inline bool is_ct_valid(const struct flow *flow,\n     return flow->ct_state & CS_VALID_MASK;\n }\n \n+/* Purely internal to OVS userspace. These flags should never be exposed to\n+ * the outside world and so aren't included in the flags mask. */\n+\n+/* Tunnel information is in userspace datapath format. */\n+#define FLOW_TNL_F_UDPIF (1 << 4)\n+\n+static inline bool\n+flow_tnl_dst_is_set(const struct flow_tnl *tnl)\n+{\n+    return tnl->ip_dst || ipv6_addr_is_set(&tnl->ipv6_dst);\n+}\n+\n+static inline bool\n+flow_tnl_src_is_set(const struct flow_tnl *tnl)\n+{\n+    return tnl->ip_src || ipv6_addr_is_set(&tnl->ipv6_src);\n+}\n+\n+struct in6_addr flow_tnl_dst(const struct flow_tnl *tnl);\n+struct in6_addr flow_tnl_src(const struct flow_tnl *tnl);\n+\n+/* Returns an offset to 'src' covering all the meaningful fields in 'src'. */\n+static inline size_t\n+flow_tnl_size(const struct flow_tnl *src)\n+{\n+    if (!flow_tnl_dst_is_set(src)) {\n+        /* Covers ip_dst and ipv6_dst only. */\n+        return offsetof(struct flow_tnl, ip_src);\n+    }\n+    if (src->flags & FLOW_TNL_F_UDPIF) {\n+        /* Datapath format, cover all options we have. */\n+        return offsetof(struct flow_tnl, metadata.opts)\n+            + src->metadata.present.len;\n+    }\n+    if (!src->metadata.present.map) {\n+        /* No TLVs, opts is irrelevant. */\n+        return offsetof(struct flow_tnl, metadata.opts);\n+    }\n+    /* Have decoded TLVs, opts is relevant. */\n+    return sizeof *src;\n+}\n+\n+/* Copy flow_tnl, but avoid copying unused portions of tun_metadata.  Unused\n+ * data in 'dst' is NOT cleared, so this must not be used in cases where the\n+ * uninitialized portion may be hashed over. */\n+static inline void\n+flow_tnl_copy__(struct flow_tnl *dst, const struct flow_tnl *src)\n+{\n+    memcpy(dst, src, flow_tnl_size(src));\n+}\n+\n+/* Fwd declare conn here. */\n+struct conn;\n+\n+/* Datapath packet metadata */\n+struct pkt_metadata {\n+PADDED_MEMBERS_CACHELINE_MARKER(CACHE_LINE_SIZE, cacheline0,\n+    uint32_t recirc_id;         /* Recirculation id carried with the\n+                                   recirculating packets. 0 for packets\n+                                   received from the wire. */\n+    uint32_t dp_hash;           /* hash value computed by the recirculation\n+                                   action. */\n+    uint32_t skb_priority;      /* Packet priority for QoS. */\n+    uint32_t pkt_mark;          /* Packet mark. */\n+    uint8_t  ct_state;          /* Connection state. */\n+    bool ct_orig_tuple_ipv6;\n+    uint16_t ct_zone;           /* Connection zone. */\n+    uint32_t ct_mark;           /* Connection mark. */\n+    ovs_u128 ct_label;          /* Connection label. */\n+    union flow_in_port in_port; /* Input port. */\n+    odp_port_t orig_in_port;    /* Originating in_port for tunneled packets */\n+    struct conn *conn;          /* Cached conntrack connection. */\n+    bool reply;                 /* True if reply direction. */\n+    bool icmp_related;          /* True if ICMP related. */\n+);\n+\n+PADDED_MEMBERS_CACHELINE_MARKER(CACHE_LINE_SIZE, cacheline1,\n+    union {                     /* Populated only for non-zero 'ct_state'. */\n+        struct ovs_key_ct_tuple_ipv4 ipv4;\n+        struct ovs_key_ct_tuple_ipv6 ipv6;   /* Used only if                */\n+    } ct_orig_tuple;                         /* 'ct_orig_tuple_ipv6' is set */\n+);\n+\n+PADDED_MEMBERS_CACHELINE_MARKER(CACHE_LINE_SIZE, cacheline2,\n+    struct flow_tnl tunnel;     /* Encapsulating tunnel parameters. Note that\n+                                 * if 'ip_dst' == 0, the rest of the fields may\n+                                 * be uninitialized. */\n+);\n+};\n+\n+BUILD_ASSERT_DECL(offsetof(struct pkt_metadata, cacheline0) == 0);\n+BUILD_ASSERT_DECL(offsetof(struct pkt_metadata, cacheline1) ==\n+                  CACHE_LINE_SIZE);\n+BUILD_ASSERT_DECL(offsetof(struct pkt_metadata, cacheline2) ==\n+                  2 * CACHE_LINE_SIZE);\n+\n+static inline void\n+pkt_metadata_init_tnl(struct pkt_metadata *md)\n+{\n+    odp_port_t orig_in_port;\n+\n+    /* Zero up through the tunnel metadata options. The length and table\n+     * are before this and as long as they are empty, the options won't\n+     * be looked at. Keep the orig_in_port field. */\n+    orig_in_port = md->in_port.odp_port;\n+    memset(md, 0, offsetof(struct pkt_metadata, tunnel.metadata.opts));\n+    md->orig_in_port = orig_in_port;\n+}\n+\n+static inline void\n+pkt_metadata_init_conn(struct pkt_metadata *md)\n+{\n+    md->conn = NULL;\n+}\n+\n+static inline void\n+pkt_metadata_init(struct pkt_metadata *md, odp_port_t port)\n+{\n+    /* This is called for every packet in userspace datapath and affects\n+     * performance if all the metadata is initialized. Hence, fields should\n+     * only be zeroed out when necessary.\n+     *\n+     * Initialize only till ct_state. Once the ct_state is zeroed out rest\n+     * of ct fields will not be looked at unless ct_state != 0.\n+     */\n+    memset(md, 0, offsetof(struct pkt_metadata, ct_orig_tuple_ipv6));\n+\n+    /* It can be expensive to zero out all of the tunnel metadata. However,\n+     * we can just zero out ip_dst and the rest of the data will never be\n+     * looked at. */\n+    md->tunnel.ip_dst = 0;\n+    md->tunnel.ipv6_dst = in6addr_any;\n+    md->in_port.odp_port = port;\n+    md->orig_in_port = port;\n+    md->conn = NULL;\n+}\n+\n+/* This function prefetches the cachelines touched by pkt_metadata_init()\n+ * and pkt_metadata_init_tnl().  For performance reasons the two functions\n+ * should be kept in sync. */\n+static inline void\n+pkt_metadata_prefetch_init(struct pkt_metadata *md)\n+{\n+    /* Prefetch cacheline0 as members till ct_state and odp_port will\n+     * be initialized later in pkt_metadata_init(). */\n+    OVS_PREFETCH(md->cacheline0);\n+\n+    /* Prefetch cacheline1 as members of this cacheline will be zeroed out\n+     * in pkt_metadata_init_tnl(). */\n+    OVS_PREFETCH(md->cacheline1);\n+\n+    /* Prefetch cachline2 as ip_dst & ipv6_dst fields will be initialized. */\n+    OVS_PREFETCH(md->cacheline2);\n+}\n+\n static inline void\n pkt_metadata_from_flow(struct pkt_metadata *md, const struct flow *flow)\n {\ndiff --git a/lib/ipf.c b/lib/ipf.c\nindex 3f60ed81c..d5caec540 100644\n--- a/lib/ipf.c\n+++ b/lib/ipf.c\n@@ -25,6 +25,7 @@\n \n #include \"coverage.h\"\n #include \"csum.h\"\n+#include \"openvswitch/dynamic-string.h\"\n #include \"ipf.h\"\n #include \"latch.h\"\n #include \"openvswitch/hmap.h\"\n@@ -32,7 +33,6 @@\n #include \"openvswitch/types.h\"\n #include \"openvswitch/vlog.h\"\n #include \"ovs-atomic.h\"\n-#include \"packets.h\"\n #include \"util.h\"\n \n VLOG_DEFINE_THIS_MODULE(ipf);\ndiff --git a/lib/lacp.c b/lib/lacp.c\nindex 3252f17eb..afc3bc092 100644\n--- a/lib/lacp.c\n+++ b/lib/lacp.c\n@@ -24,7 +24,6 @@\n #include \"openvswitch/hmap.h\"\n #include \"dp-packet.h\"\n #include \"ovs-atomic.h\"\n-#include \"packets.h\"\n #include \"openvswitch/poll-loop.h\"\n #include \"seq.h\"\n #include \"openvswitch/shash.h\"\ndiff --git a/lib/lacp.h b/lib/lacp.h\nindex 5ba17c36a..ff22b7fc5 100644\n--- a/lib/lacp.h\n+++ b/lib/lacp.h\n@@ -18,8 +18,12 @@\n #define LACP_H 1\n \n #include <stdbool.h>\n+#include <stddef.h>\n #include <stdint.h>\n-#include \"packets.h\"\n+\n+#include \"net-proto.h\"\n+\n+struct dp_packet;\n \n /* LACP Protocol Implementation. */\n \ndiff --git a/lib/lldp/lldp.c b/lib/lldp/lldp.c\nindex 6fdcfef56..ad4f69c36 100644\n--- a/lib/lldp/lldp.c\n+++ b/lib/lldp/lldp.c\n@@ -27,7 +27,6 @@\n #include <sys/types.h>\n #include \"compiler.h\"\n #include \"dp-packet.h\"\n-#include \"packets.h\"\n \n VLOG_DEFINE_THIS_MODULE(lldp);\n \ndiff --git a/lib/lldp/lldpd-structs.h b/lib/lldp/lldpd-structs.h\nindex fe5d5f9f8..500f21f90 100644\n--- a/lib/lldp/lldpd-structs.h\n+++ b/lib/lldp/lldpd-structs.h\n@@ -25,7 +25,6 @@\n #include <sys/socket.h>\n #include \"aa-structs.h\"\n #include \"lldp-const.h\"\n-#include \"packets.h\"\n \n enum {\n     LLDPD_AF_UNSPEC = 0,\ndiff --git a/lib/lldp/lldpd.c b/lib/lldp/lldpd.c\nindex 4bff7b017..e790c1a68 100644\n--- a/lib/lldp/lldpd.c\n+++ b/lib/lldp/lldpd.c\n@@ -42,7 +42,6 @@\n #include \"compiler.h\"\n #include \"openvswitch/dynamic-string.h\"\n #include \"openvswitch/list.h\"\n-#include \"packets.h\"\n #include \"timeval.h\"\n \n VLOG_DEFINE_THIS_MODULE(lldpd);\ndiff --git a/lib/lldp/lldpd.h b/lib/lldp/lldpd.h\nindex 3f5be84a2..6d70c159a 100644\n--- a/lib/lldp/lldpd.h\n+++ b/lib/lldp/lldpd.h\n@@ -28,7 +28,6 @@\n #include \"openvswitch/list.h\"\n #include \"lldpd-structs.h\"\n #include \"lldp-tlv.h\"\n-#include \"packets.h\"\n #include \"openvswitch/vlog.h\"\n \n #define ETHERTYPE_LLDP 0x88cc\ndiff --git a/lib/mac-learning.c b/lib/mac-learning.c\nindex affb2faf5..a82b79c2f 100644\n--- a/lib/mac-learning.c\n+++ b/lib/mac-learning.c\n@@ -23,8 +23,10 @@\n #include \"bitmap.h\"\n #include \"coverage.h\"\n #include \"hash.h\"\n+#include \"net-proto.h\"\n #include \"openvswitch/list.h\"\n #include \"openvswitch/poll-loop.h\"\n+#include \"random.h\"\n #include \"timeval.h\"\n #include \"unaligned.h\"\n #include \"util.h\"\ndiff --git a/lib/mac-learning.h b/lib/mac-learning.h\nindex 270fbd70d..feee7107b 100644\n--- a/lib/mac-learning.h\n+++ b/lib/mac-learning.h\n@@ -23,7 +23,6 @@\n #include \"openvswitch/list.h\"\n #include \"ovs-atomic.h\"\n #include \"ovs-thread.h\"\n-#include \"packets.h\"\n #include \"timeval.h\"\n \n /* MAC learning table\ndiff --git a/lib/match.c b/lib/match.c\nindex cb9f1740d..4526205b3 100644\n--- a/lib/match.c\n+++ b/lib/match.c\n@@ -23,7 +23,6 @@\n #include \"openvswitch/dynamic-string.h\"\n #include \"openvswitch/meta-flow.h\"\n #include \"openvswitch/ofp-port.h\"\n-#include \"packets.h\"\n #include \"tun-metadata.h\"\n #include \"openvswitch/nsh.h\"\n \ndiff --git a/lib/mcast-snooping.h b/lib/mcast-snooping.h\nindex de42cf826..f99f02193 100644\n--- a/lib/mcast-snooping.h\n+++ b/lib/mcast-snooping.h\n@@ -25,7 +25,6 @@\n #include \"openvswitch/list.h\"\n #include \"ovs-atomic.h\"\n #include \"ovs-thread.h\"\n-#include \"packets.h\"\n #include \"timeval.h\"\n \n struct mcast_snooping;\ndiff --git a/lib/meta-flow.c b/lib/meta-flow.c\nindex 6f1458d78..545c4f4bc 100644\n--- a/lib/meta-flow.c\n+++ b/lib/meta-flow.c\n@@ -29,7 +29,6 @@\n #include \"ovs-atomic.h\"\n #include \"ovs-rcu.h\"\n #include \"ovs-thread.h\"\n-#include \"packets.h\"\n #include \"random.h\"\n #include \"openvswitch/shash.h\"\n #include \"socket-util.h\"\ndiff --git a/lib/multipath.c b/lib/multipath.c\nindex 6896f94a1..56aa259e5 100644\n--- a/lib/multipath.c\n+++ b/lib/multipath.c\n@@ -27,7 +27,6 @@\n #include \"openvswitch/dynamic-string.h\"\n #include \"openvswitch/ofp-actions.h\"\n #include \"openvswitch/ofp-errors.h\"\n-#include \"packets.h\"\n #include \"util.h\"\n \f\n /* Checks that 'mp' is valid on flow.  Returns 0 if it is valid, otherwise an\ndiff --git a/lib/netdev-afxdp.c b/lib/netdev-afxdp.c\nindex 8ef2ac192..61a72af94 100644\n--- a/lib/netdev-afxdp.c\n+++ b/lib/netdev-afxdp.c\n@@ -52,7 +52,6 @@\n #include \"openvswitch/vlog.h\"\n #include \"ovs-atomic.h\"\n #include \"ovs-numa.h\"\n-#include \"packets.h\"\n #include \"socket-util.h\"\n #include \"util.h\"\n \ndiff --git a/lib/netdev-bsd.c b/lib/netdev-bsd.c\nindex d29589efd..25837b04d 100644\n--- a/lib/netdev-bsd.c\n+++ b/lib/netdev-bsd.c\n@@ -55,7 +55,6 @@\n #include \"fatal-signal.h\"\n #include \"openflow/openflow.h\"\n #include \"ovs-thread.h\"\n-#include \"packets.h\"\n #include \"openvswitch/poll-loop.h\"\n #include \"openvswitch/shash.h\"\n #include \"socket-util.h\"\ndiff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c\nindex 90d4c2c71..a5e5b9d0a 100644\n--- a/lib/netdev-dpdk.c\n+++ b/lib/netdev-dpdk.c\n@@ -66,7 +66,6 @@\n #include \"ovs-numa.h\"\n #include \"ovs-rcu.h\"\n #include \"ovs-thread.h\"\n-#include \"packets.h\"\n #include \"smap.h\"\n #include \"sset.h\"\n #include \"timeval.h\"\ndiff --git a/lib/netdev-dummy.c b/lib/netdev-dummy.c\nindex 7d3a7b968..1575afdad 100644\n--- a/lib/netdev-dummy.c\n+++ b/lib/netdev-dummy.c\n@@ -34,7 +34,6 @@\n #include \"openvswitch/ofpbuf.h\"\n #include \"openvswitch/vlog.h\"\n #include \"ovs-atomic.h\"\n-#include \"packets.h\"\n #include \"pcap-file.h\"\n #include \"openvswitch/poll-loop.h\"\n #include \"openvswitch/shash.h\"\ndiff --git a/lib/netdev-linux.c b/lib/netdev-linux.c\nindex c5ab11f5b..2d480b4b0 100644\n--- a/lib/netdev-linux.c\n+++ b/lib/netdev-linux.c\n@@ -68,7 +68,6 @@\n #include \"openflow/openflow.h\"\n #include \"ovs-atomic.h\"\n #include \"ovs-numa.h\"\n-#include \"packets.h\"\n #include \"openvswitch/poll-loop.h\"\n #include \"rtnetlink.h\"\n #include \"openvswitch/shash.h\"\ndiff --git a/lib/netdev-native-tnl.c b/lib/netdev-native-tnl.c\nindex 5e88f9f9a..4e3278479 100644\n--- a/lib/netdev-native-tnl.c\n+++ b/lib/netdev-native-tnl.c\n@@ -36,12 +36,14 @@\n #include \"coverage.h\"\n #include \"csum.h\"\n #include \"dp-packet.h\"\n+#include \"openvswitch/dynamic-string.h\"\n #include \"netdev.h\"\n+#include \"net-proto.h\"\n #include \"netdev-vport.h\"\n #include \"netdev-vport-private.h\"\n #include \"odp-netlink.h\"\n-#include \"packets.h\"\n #include \"seq.h\"\n+#include \"tun-metadata.h\"\n #include \"unaligned.h\"\n #include \"unixctl.h\"\n #include \"util.h\"\ndiff --git a/lib/netdev-native-tnl.h b/lib/netdev-native-tnl.h\nindex 47d6b6bbc..0d3841628 100644\n--- a/lib/netdev-native-tnl.h\n+++ b/lib/netdev-native-tnl.h\n@@ -21,7 +21,6 @@\n #include <stddef.h>\n #include \"compiler.h\"\n #include \"dp-packet.h\"\n-#include \"packets.h\"\n #include \"unixctl.h\"\n \n struct netdev;\ndiff --git a/lib/netdev-provider.h b/lib/netdev-provider.h\nindex 136d8188c..fc249399f 100644\n--- a/lib/netdev-provider.h\n+++ b/lib/netdev-provider.h\n@@ -24,7 +24,6 @@\n #include \"openvswitch/list.h\"\n #include \"ovs-numa.h\"\n #include \"ovs-rcu.h\"\n-#include \"packets.h\"\n #include \"seq.h\"\n #include \"openvswitch/shash.h\"\n #include \"smap.h\"\ndiff --git a/lib/netdev-vport.c b/lib/netdev-vport.c\nindex d11269d00..25b6fef2d 100644\n--- a/lib/netdev-vport.c\n+++ b/lib/netdev-vport.c\n@@ -39,7 +39,6 @@\n #include \"openvswitch/dynamic-string.h\"\n #include \"ovs-atomic.h\"\n #include \"ovs-router.h\"\n-#include \"packets.h\"\n #include \"openvswitch/poll-loop.h\"\n #include \"route-table.h\"\n #include \"simap.h\"\ndiff --git a/lib/netdev-windows.c b/lib/netdev-windows.c\nindex 3fad501e3..89e6d9f14 100644\n--- a/lib/netdev-windows.c\n+++ b/lib/netdev-windows.c\n@@ -25,7 +25,6 @@\n #include \"fatal-signal.h\"\n #include \"netdev-provider.h\"\n #include \"openvswitch/ofpbuf.h\"\n-#include \"packets.h\"\n #include \"openvswitch/poll-loop.h\"\n #include \"openvswitch/shash.h\"\n #include \"svec.h\"\ndiff --git a/lib/netdev.c b/lib/netdev.c\nindex daa428736..6ce18cf14 100644\n--- a/lib/netdev.c\n+++ b/lib/netdev.c\n@@ -45,7 +45,6 @@\n #include \"odp-netlink.h\"\n #include \"openvswitch/json.h\"\n #include \"openflow/openflow.h\"\n-#include \"packets.h\"\n #include \"openvswitch/ofp-print.h\"\n #include \"openvswitch/poll-loop.h\"\n #include \"seq.h\"\ndiff --git a/lib/netdev.h b/lib/netdev.h\nindex 40f1621ec..36beba603 100644\n--- a/lib/netdev.h\n+++ b/lib/netdev.h\n@@ -21,7 +21,6 @@\n #include \"openvswitch/types.h\"\n #include \"ovs-atomic.h\"\n #include \"ovs-rcu.h\"\n-#include \"packets.h\"\n #include \"flow.h\"\n \n #ifdef  __cplusplus\ndiff --git a/lib/nx-match.c b/lib/nx-match.c\nindex 225cd5720..12ef66916 100644\n--- a/lib/nx-match.c\n+++ b/lib/nx-match.c\n@@ -26,13 +26,13 @@\n #include \"openflow/nicira-ext.h\"\n #include \"openvswitch/dynamic-string.h\"\n #include \"openvswitch/meta-flow.h\"\n+#include \"openvswitch/nsh.h\"\n #include \"openvswitch/ofp-actions.h\"\n #include \"openvswitch/ofp-errors.h\"\n #include \"openvswitch/ofp-match.h\"\n #include \"openvswitch/ofp-port.h\"\n #include \"openvswitch/ofpbuf.h\"\n #include \"openvswitch/vlog.h\"\n-#include \"packets.h\"\n #include \"openvswitch/shash.h\"\n #include \"tun-metadata.h\"\n #include \"unaligned.h\"\ndiff --git a/lib/odp-execute-avx512.c b/lib/odp-execute-avx512.c\nindex 510a215cd..cabe069b3 100644\n--- a/lib/odp-execute-avx512.c\n+++ b/lib/odp-execute-avx512.c\n@@ -27,11 +27,11 @@\n #include \"csum.h\"\n #include \"dp-packet.h\"\n #include \"immintrin.h\"\n+#include \"netlink.h\"\n #include \"odp-execute.h\"\n #include \"odp-execute-private.h\"\n #include \"odp-netlink.h\"\n #include \"openvswitch/vlog.h\"\n-#include \"packets.h\"\n \n VLOG_DEFINE_THIS_MODULE(odp_execute_avx512);\n \ndiff --git a/lib/odp-execute-private.c b/lib/odp-execute-private.c\nindex 8b7a6b4ab..bc10a0b8f 100644\n--- a/lib/odp-execute-private.c\n+++ b/lib/odp-execute-private.c\n@@ -22,6 +22,7 @@\n #include \"cpu.h\"\n #include \"dpdk.h\"\n #include \"dp-packet.h\"\n+#include \"netlink.h\"\n #include \"odp-execute.h\"\n #include \"odp-execute-private.h\"\n #include \"odp-netlink.h\"\ndiff --git a/lib/odp-execute.c b/lib/odp-execute.c\nindex ecbda8c01..42bce3258 100644\n--- a/lib/odp-execute.c\n+++ b/lib/odp-execute.c\n@@ -32,7 +32,6 @@\n #include \"netlink.h\"\n #include \"odp-netlink.h\"\n #include \"odp-util.h\"\n-#include \"packets.h\"\n #include \"flow.h\"\n #include \"unaligned.h\"\n #include \"util.h\"\ndiff --git a/lib/odp-util.c b/lib/odp-util.c\nindex 4924aff93..42ebd6a2c 100644\n--- a/lib/odp-util.c\n+++ b/lib/odp-util.c\n@@ -33,8 +33,8 @@\n #include \"openvswitch/dynamic-string.h\"\n #include \"flow.h\"\n #include \"netlink.h\"\n+#include \"openvswitch/nsh.h\"\n #include \"openvswitch/ofpbuf.h\"\n-#include \"packets.h\"\n #include \"simap.h\"\n #include \"timeval.h\"\n #include \"tun-metadata.h\"\ndiff --git a/lib/odp-util.h b/lib/odp-util.h\nindex 85386d552..2f13afe1f 100644\n--- a/lib/odp-util.h\n+++ b/lib/odp-util.h\n@@ -32,6 +32,7 @@\n \n struct ds;\n struct nlattr;\n+struct nsh_hdr;\n struct ofpbuf;\n struct simap;\n struct pkt_metadata;\ndiff --git a/lib/ofp-ct.c b/lib/ofp-ct.c\nindex 20ce1aa20..82082e3a8 100644\n--- a/lib/ofp-ct.c\n+++ b/lib/ofp-ct.c\n@@ -25,11 +25,13 @@\n #include \"openvswitch/ofp-ct.h\"\n #include \"openflow/nicira-ext.h\"\n #include \"openvswitch/dynamic-string.h\"\n+#include \"net-proto.h\"\n #include \"openvswitch/ofp-msgs.h\"\n #include \"openvswitch/ofp-parse.h\"\n #include \"openvswitch/ofp-errors.h\"\n #include \"openvswitch/ofp-prop.h\"\n #include \"openvswitch/ofp-util.h\"\n+#include \"openvswitch/ofpbuf.h\"\n #include \"openvswitch/net-proto.h\"\n #include \"openvswitch/vlog.h\"\n \ndiff --git a/lib/ofp-ed-props.c b/lib/ofp-ed-props.c\nindex d0649da02..58f3c93ee 100644\n--- a/lib/ofp-ed-props.c\n+++ b/lib/ofp-ed-props.c\n@@ -22,8 +22,6 @@\n #include \"openvswitch/ofpbuf.h\"\n #include \"openvswitch/ofp-parse.h\"\n #include \"util.h\"\n-#include \"lib/packets.h\"\n-\n \n enum ofperr\n decode_ed_prop(const struct ofp_ed_prop_header **ofp_prop,\ndiff --git a/lib/ofp-match.c b/lib/ofp-match.c\nindex 737cc2c3e..fe89c704a 100644\n--- a/lib/ofp-match.c\n+++ b/lib/ofp-match.c\n@@ -17,12 +17,14 @@\n #include <config.h>\n #include \"openvswitch/ofp-match.h\"\n #include \"byte-order.h\"\n+#include \"openvswitch/dynamic-string.h\"\n #include \"flow.h\"\n #include \"nx-match.h\"\n #include \"openvswitch/match.h\"\n #include \"openvswitch/ofp-errors.h\"\n #include \"openvswitch/ofp-msgs.h\"\n #include \"openvswitch/ofp-port.h\"\n+#include \"openvswitch/ofpbuf.h\"\n #include \"openvswitch/net-proto.h\"\n #include \"openvswitch/vlog.h\"\n \ndiff --git a/lib/ofp-parse.c b/lib/ofp-parse.c\nindex 102b183a8..77208e486 100644\n--- a/lib/ofp-parse.c\n+++ b/lib/ofp-parse.c\n@@ -20,11 +20,11 @@\n #include \"byte-order.h\"\n #include \"openvswitch/match.h\"\n #include \"openvswitch/meta-flow.h\"\n+#include \"net-proto.h\"\n #include \"openvswitch/ofp-actions.h\"\n #include \"openvswitch/ofp-flow.h\"\n #include \"openvswitch/ofp-match.h\"\n #include \"openvswitch/ofp-table.h\"\n-#include \"packets.h\"\n #include \"socket-util.h\"\n #include \"util.h\"\n \ndiff --git a/lib/ofp-print.c b/lib/ofp-print.c\nindex 874079b84..9297dfe88 100644\n--- a/lib/ofp-print.c\n+++ b/lib/ofp-print.c\n@@ -60,7 +60,6 @@\n #include \"openvswitch/ofp-util.h\"\n #include \"openvswitch/ofpbuf.h\"\n #include \"openvswitch/type-props.h\"\n-#include \"packets.h\"\n #include \"unaligned.h\"\n #include \"util.h\"\n #include \"uuid.h\"\ndiff --git a/lib/ofp-util.c b/lib/ofp-util.c\nindex a324ceeea..4050d72d3 100644\n--- a/lib/ofp-util.c\n+++ b/lib/ofp-util.c\n@@ -45,7 +45,6 @@\n #include \"openvswitch/type-props.h\"\n #include \"openvswitch/vlog.h\"\n #include \"openflow/intel-ext.h\"\n-#include \"packets.h\"\n #include \"random.h\"\n #include \"tun-metadata.h\"\n #include \"unaligned.h\"\ndiff --git a/lib/ovs-lldp.c b/lib/ovs-lldp.c\nindex 152777248..45a8e386b 100644\n--- a/lib/ovs-lldp.c\n+++ b/lib/ovs-lldp.c\n@@ -41,7 +41,6 @@\n #include \"lldp/lldpd-structs.h\"\n #include \"netdev.h\"\n #include \"openvswitch/types.h\"\n-#include \"packets.h\"\n #include \"openvswitch/poll-loop.h\"\n #include \"smap.h\"\n #include \"unixctl.h\"\ndiff --git a/lib/ovs-lldp.h b/lib/ovs-lldp.h\nindex 661ac4e18..de2364fcd 100644\n--- a/lib/ovs-lldp.h\n+++ b/lib/ovs-lldp.h\n@@ -25,7 +25,6 @@\n #include \"openvswitch/list.h\"\n #include \"lldp/lldpd.h\"\n #include \"ovs-atomic.h\"\n-#include \"packets.h\"\n #include \"timer.h\"\n \n /* Transmit every LLDPD_TX_INTERVAL seconds. */\ndiff --git a/lib/ovs-router.c b/lib/ovs-router.c\nindex 2566386ea..2c436c83f 100644\n--- a/lib/ovs-router.c\n+++ b/lib/ovs-router.c\n@@ -39,7 +39,6 @@\n #include \"openvswitch/dynamic-string.h\"\n #include \"openvswitch/json.h\"\n #include \"netdev.h\"\n-#include \"packets.h\"\n #include \"seq.h\"\n #include \"ovs-thread.h\"\n #include \"route-table.h\"\ndiff --git a/lib/packets.c b/lib/packets.c\ndeleted file mode 100644\nindex 22229638a..000000000\n--- a/lib/packets.c\n+++ /dev/null\n@@ -1,1494 +0,0 @@\n-/*\n- * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 <config.h>\n-#include \"packets.h\"\n-#include <sys/types.h>\n-#include <netinet/in.h>\n-#include <arpa/inet.h>\n-#include <sys/socket.h>\n-#include <netinet/ip6.h>\n-#include <netinet/icmp6.h>\n-#include <stdlib.h>\n-#include <netdb.h>\n-#include \"byte-order.h\"\n-#include \"csum.h\"\n-#include \"crc32c.h\"\n-#include \"flow.h\"\n-#include \"openvswitch/hmap.h\"\n-#include \"openvswitch/dynamic-string.h\"\n-#include \"ovs-thread.h\"\n-#include \"odp-util.h\"\n-#include \"dp-packet.h\"\n-#include \"dp-packet-gso.h\"\n-#include \"unaligned.h\"\n-\n-struct in6_addr\n-flow_tnl_dst(const struct flow_tnl *tnl)\n-{\n-    return tnl->ip_dst ? in6_addr_mapped_ipv4(tnl->ip_dst) : tnl->ipv6_dst;\n-}\n-\n-struct in6_addr\n-flow_tnl_src(const struct flow_tnl *tnl)\n-{\n-    return tnl->ip_src ? in6_addr_mapped_ipv4(tnl->ip_src) : tnl->ipv6_src;\n-}\n-\n-/* Fills 'b' with a Reverse ARP packet with Ethernet source address 'eth_src'.\n- * This function is used by Open vSwitch to compose packets in cases where\n- * context is important but content doesn't (or shouldn't) matter.\n- *\n- * The returned packet has enough headroom to insert an 802.1Q VLAN header if\n- * desired. */\n-void\n-compose_rarp(struct dp_packet *b, const struct eth_addr eth_src)\n-{\n-    struct eth_header *eth;\n-    struct arp_eth_header *arp;\n-\n-    dp_packet_clear(b);\n-    dp_packet_prealloc_tailroom(b, 2 + ETH_HEADER_LEN + VLAN_HEADER_LEN\n-                             + ARP_ETH_HEADER_LEN);\n-    dp_packet_reserve(b, 2 + VLAN_HEADER_LEN);\n-    eth = dp_packet_put_uninit(b, sizeof *eth);\n-    eth->eth_dst = eth_addr_broadcast;\n-    eth->eth_src = eth_src;\n-    eth->eth_type = htons(ETH_TYPE_RARP);\n-\n-    arp = dp_packet_put_uninit(b, sizeof *arp);\n-    arp->ar_hrd = htons(ARP_HRD_ETHERNET);\n-    arp->ar_pro = htons(ARP_PRO_IP);\n-    arp->ar_hln = sizeof arp->ar_sha;\n-    arp->ar_pln = sizeof arp->ar_spa;\n-    arp->ar_op = htons(ARP_OP_RARP);\n-    arp->ar_sha = eth_src;\n-    put_16aligned_be32(&arp->ar_spa, htonl(0));\n-    arp->ar_tha = eth_src;\n-    put_16aligned_be32(&arp->ar_tpa, htonl(0));\n-\n-    dp_packet_set_l3(b, arp);\n-    b->packet_type = htonl(PT_ETH);\n-}\n-\n-/* Insert VLAN header according to given TCI. Packet passed must be Ethernet\n- * packet.  Ignores the CFI bit of 'tci' using 0 instead.\n- *\n- * Also adjusts the layer offsets accordingly. */\n-void\n-eth_push_vlan(struct dp_packet *packet, ovs_be16 tpid, ovs_be16 tci)\n-{\n-    struct vlan_eth_header *veh;\n-\n-    /* Insert new 802.1Q header. */\n-    veh = dp_packet_resize_l2(packet, VLAN_HEADER_LEN);\n-    memmove(veh, (char *)veh + VLAN_HEADER_LEN, 2 * ETH_ADDR_LEN);\n-    veh->veth_type = tpid;\n-    veh->veth_tci = tci & htons(~VLAN_CFI);\n-}\n-\n-/* Removes outermost VLAN header (if any is present) from 'packet'.\n- *\n- * 'packet->l2_5' should initially point to 'packet''s outer-most VLAN header\n- * or may be NULL if there are no VLAN headers. */\n-void\n-eth_pop_vlan(struct dp_packet *packet)\n-{\n-    struct vlan_eth_header *veh = dp_packet_eth(packet);\n-\n-    if (veh && dp_packet_size(packet) >= sizeof *veh\n-        && eth_type_vlan(veh->veth_type)) {\n-\n-        memmove((char *)veh + VLAN_HEADER_LEN, veh, 2 * ETH_ADDR_LEN);\n-        dp_packet_resize_l2(packet, -VLAN_HEADER_LEN);\n-    }\n-}\n-\n-/* Push Ethernet header onto 'packet' assuming it is layer 3 */\n-void\n-push_eth(struct dp_packet *packet, const struct eth_addr *dst,\n-         const struct eth_addr *src)\n-{\n-    struct eth_header *eh;\n-\n-    ovs_assert(!dp_packet_is_eth(packet));\n-    eh = dp_packet_resize_l2(packet, ETH_HEADER_LEN);\n-    eh->eth_dst = *dst;\n-    eh->eth_src = *src;\n-    eh->eth_type = pt_ns_type_be(packet->packet_type);\n-    packet->packet_type = htonl(PT_ETH);\n-}\n-\n-/* Removes Ethernet header, including VLAN header, from 'packet'.\n- *\n- * Previous to calling this function, 'ofpbuf_l3(packet)' must not be NULL */\n-void\n-pop_eth(struct dp_packet *packet)\n-{\n-    char *l2_5 = dp_packet_l2_5(packet);\n-    char *l3 = dp_packet_l3(packet);\n-    ovs_be16 ethertype;\n-    int increment;\n-\n-    ovs_assert(dp_packet_is_eth(packet));\n-    ovs_assert(l3 != NULL);\n-\n-    if (l2_5) {\n-        increment = packet->l2_5_ofs;\n-        ethertype = *(ALIGNED_CAST(ovs_be16 *, (l2_5 - 2)));\n-    } else {\n-        increment = packet->l3_ofs;\n-        ethertype = *(ALIGNED_CAST(ovs_be16 *, (l3 - 2)));\n-    }\n-\n-    dp_packet_resize_l2(packet, -increment);\n-    packet->packet_type = PACKET_TYPE_BE(OFPHTN_ETHERTYPE, ntohs(ethertype));\n-}\n-\n-/* Set ethertype of the packet. */\n-static void\n-set_ethertype(struct dp_packet *packet, ovs_be16 eth_type)\n-{\n-    struct eth_header *eh = dp_packet_eth(packet);\n-\n-    if (!eh) {\n-        return;\n-    }\n-\n-    if (eth_type_vlan(eh->eth_type)) {\n-        ovs_be16 *p;\n-        char *l2_5 = dp_packet_l2_5(packet);\n-\n-        p = ALIGNED_CAST(ovs_be16 *,\n-                         (l2_5 ? l2_5 : (char *)dp_packet_l3(packet)) - 2);\n-        *p = eth_type;\n-    } else {\n-        eh->eth_type = eth_type;\n-    }\n-}\n-\n-static bool is_mpls(struct dp_packet *packet)\n-{\n-    return packet->l2_5_ofs != UINT16_MAX;\n-}\n-\n-/* Set MPLS label stack entry to outermost MPLS header.*/\n-void\n-set_mpls_lse(struct dp_packet *packet, ovs_be32 mpls_lse)\n-{\n-    /* Packet type should be MPLS to set label stack entry. */\n-    if (is_mpls(packet)) {\n-        struct mpls_hdr *mh = dp_packet_l2_5(packet);\n-\n-        /* Update mpls label stack entry. */\n-        put_16aligned_be32(&mh->mpls_lse, mpls_lse);\n-    }\n-}\n-\n-/* Push MPLS label stack entry 'lse' onto 'packet' as the outermost MPLS\n- * header.  If 'packet' does not already have any MPLS labels, then its\n- * Ethertype is changed to 'ethtype' (which must be an MPLS Ethertype). */\n-void\n-push_mpls(struct dp_packet *packet, ovs_be16 ethtype, ovs_be32 lse)\n-{\n-    char * header;\n-    size_t len;\n-\n-    if (!eth_type_mpls(ethtype)) {\n-        return;\n-    }\n-\n-    if (!is_mpls(packet)) {\n-        /* Set MPLS label stack offset. */\n-        packet->l2_5_ofs = packet->l3_ofs;\n-    }\n-\n-    set_ethertype(packet, ethtype);\n-\n-    /* Push new MPLS shim header onto packet. */\n-    len = packet->l2_5_ofs;\n-    header = dp_packet_resize_l2_5(packet, MPLS_HLEN);\n-    memmove(header, header + MPLS_HLEN, len);\n-    memcpy(header + len, &lse, sizeof lse);\n-\n-    pkt_metadata_init_conn(&packet->md);\n-}\n-\n-void\n-add_mpls(struct dp_packet *packet, ovs_be16 ethtype, ovs_be32 lse,\n-         bool l3_encap)\n-{\n-    if (!eth_type_mpls(ethtype)) {\n-        return;\n-    }\n-\n-    if (!l3_encap) {\n-        struct mpls_hdr *header = dp_packet_resize_l2(packet, MPLS_HLEN);\n-\n-        put_16aligned_be32(&header->mpls_lse, lse);\n-        packet->l2_5_ofs = 0;\n-        packet->packet_type = PACKET_TYPE_BE(OFPHTN_ETHERTYPE,\n-                                             ntohs(ethtype));\n-    } else {\n-        size_t len;\n-        char *header;\n-\n-        if (!is_mpls(packet)) {\n-            /* Set MPLS label stack offset. */\n-            packet->l2_5_ofs = packet->l3_ofs;\n-        }\n-        set_ethertype(packet, ethtype);\n-\n-        /* Push new MPLS shim header onto packet. */\n-        len = packet->l2_5_ofs;\n-        header = dp_packet_resize_l2_5(packet, MPLS_HLEN);\n-        memmove(header, header + MPLS_HLEN, len);\n-        memcpy(header + len, &lse, sizeof lse);\n-    }\n-    pkt_metadata_init_conn(&packet->md);\n-}\n-\n-/* If 'packet' is an MPLS packet, removes its outermost MPLS label stack entry.\n- * If the label that was removed was the only MPLS label, changes 'packet''s\n- * Ethertype to 'ethtype' (which ordinarily should not be an MPLS\n- * Ethertype). */\n-void\n-pop_mpls(struct dp_packet *packet, ovs_be16 ethtype)\n-{\n-    if (is_mpls(packet)) {\n-        struct mpls_hdr *mh = dp_packet_l2_5(packet);\n-        size_t len = packet->l2_5_ofs;\n-\n-        set_ethertype(packet, ethtype);\n-        if (get_16aligned_be32(&mh->mpls_lse) & htonl(MPLS_BOS_MASK)) {\n-            dp_packet_set_l2_5(packet, NULL);\n-        }\n-        /* Shift the l2 header forward. */\n-        memmove((char*)dp_packet_data(packet) + MPLS_HLEN, dp_packet_data(packet), len);\n-        dp_packet_resize_l2_5(packet, -MPLS_HLEN);\n-\n-        /* Invalidate offload flags as they are not valid after\n-         * decapsulation of MPLS header. */\n-        dp_packet_reset_offload(packet);\n-\n-        /* packet_type must be reset for the MPLS packets with no l2 header */\n-        if (!len) {\n-            if (ethtype == htons(ETH_TYPE_TEB)) {\n-                /* The inner packet must be classified as ethernet if the\n-                 * ethtype is ETH_TYPE_TEB. */\n-                packet->packet_type = htonl(PT_ETH);\n-            } else {\n-                packet->packet_type = PACKET_TYPE_BE(OFPHTN_ETHERTYPE,\n-                                                     ntohs(ethtype));\n-            }\n-        }\n-    }\n-}\n-\n-void\n-push_nsh(struct dp_packet *packet, const struct nsh_hdr *nsh_hdr_src)\n-{\n-    struct nsh_hdr *nsh;\n-    size_t length = nsh_hdr_len(nsh_hdr_src);\n-    uint8_t next_proto;\n-\n-    switch (ntohl(packet->packet_type)) {\n-        case PT_ETH:\n-            next_proto = NSH_P_ETHERNET;\n-            break;\n-        case PT_IPV4:\n-            next_proto = NSH_P_IPV4;\n-            break;\n-        case PT_IPV6:\n-            next_proto = NSH_P_IPV6;\n-            break;\n-        case PT_NSH:\n-            next_proto = NSH_P_NSH;\n-            break;\n-        default:\n-            OVS_NOT_REACHED();\n-    }\n-\n-    nsh = (struct nsh_hdr *) dp_packet_resize_l2(packet, length);\n-    memcpy(nsh, nsh_hdr_src, length);\n-    nsh->next_proto = next_proto;\n-    packet->packet_type = htonl(PT_NSH);\n-    dp_packet_reset_offsets(packet);\n-    packet->l3_ofs = 0;\n-}\n-\n-bool\n-pop_nsh(struct dp_packet *packet)\n-{\n-    struct nsh_hdr *nsh = (struct nsh_hdr *) dp_packet_l3(packet);\n-    size_t length;\n-    uint32_t next_pt;\n-\n-    if (packet->packet_type == htonl(PT_NSH) && nsh) {\n-        switch (nsh->next_proto) {\n-            case NSH_P_ETHERNET:\n-                next_pt = PT_ETH;\n-                break;\n-            case NSH_P_IPV4:\n-                next_pt = PT_IPV4;\n-                break;\n-            case NSH_P_IPV6:\n-                next_pt = PT_IPV6;\n-                break;\n-            case NSH_P_NSH:\n-                next_pt = PT_NSH;\n-                break;\n-            default:\n-                /* Unknown inner packet type. Drop packet. */\n-                return false;\n-        }\n-\n-        length = nsh_hdr_len(nsh);\n-        dp_packet_reset_packet(packet, length);\n-        packet->packet_type = htonl(next_pt);\n-        /* Packet must be recirculated for further processing. */\n-    }\n-    return true;\n-}\n-\n-/* Converts hex digits in 'hex' to an Ethernet packet in '*packetp'.  The\n- * caller must free '*packetp'.  On success, returns NULL.  On failure, returns\n- * an error message and stores NULL in '*packetp'.\n- *\n- * Aligns the L3 header of '*packetp' on a 32-bit boundary. */\n-const char *\n-eth_from_hex(const char *hex, struct dp_packet **packetp)\n-{\n-    struct dp_packet *packet;\n-\n-    /* Use 2 bytes of headroom to 32-bit align the L3 header. */\n-    packet = *packetp = dp_packet_new_with_headroom(strlen(hex) / 2, 2);\n-\n-    if (dp_packet_put_hex(packet, hex, NULL)[0] != '\\0') {\n-        dp_packet_delete(packet);\n-        *packetp = NULL;\n-        return \"Trailing garbage in packet data\";\n-    }\n-\n-    if (dp_packet_size(packet) < ETH_HEADER_LEN) {\n-        dp_packet_delete(packet);\n-        *packetp = NULL;\n-        return \"Packet data too short for Ethernet\";\n-    }\n-\n-    return NULL;\n-}\n-\n-/* Populates 'b' with an Ethernet II packet headed with the given 'eth_dst',\n- * 'eth_src' and 'eth_type' parameters.  A payload of 'size' bytes is allocated\n- * in 'b' and returned.  This payload may be populated with appropriate\n- * information by the caller.  Sets 'b''s 'frame' pointer and 'l3' offset to\n- * the Ethernet header and payload respectively.  Aligns b->l3 on a 32-bit\n- * boundary.\n- *\n- * The returned packet has enough headroom to insert an 802.1Q VLAN header if\n- * desired. */\n-void *\n-eth_compose(struct dp_packet *b, const struct eth_addr eth_dst,\n-            const struct eth_addr eth_src, uint16_t eth_type,\n-            size_t size)\n-{\n-    void *data;\n-    struct eth_header *eth;\n-\n-\n-    dp_packet_clear(b);\n-\n-    /* The magic 2 here ensures that the L3 header (when it is added later)\n-     * will be 32-bit aligned. */\n-    dp_packet_prealloc_tailroom(b, 2 + ETH_HEADER_LEN + VLAN_HEADER_LEN + size);\n-    dp_packet_reserve(b, 2 + VLAN_HEADER_LEN);\n-    eth = dp_packet_put_uninit(b, ETH_HEADER_LEN);\n-    data = dp_packet_put_zeros(b, size);\n-\n-    eth->eth_dst = eth_dst;\n-    eth->eth_src = eth_src;\n-    eth->eth_type = htons(eth_type);\n-\n-    b->packet_type = htonl(PT_ETH);\n-    dp_packet_set_l3(b, data);\n-\n-    return data;\n-}\n-\n-void\n-packet_set_ipv4_addr(struct dp_packet *packet,\n-                     ovs_16aligned_be32 *addr, ovs_be32 new_addr)\n-{\n-    struct ip_header *nh = dp_packet_l3(packet);\n-    ovs_be32 old_addr = get_16aligned_be32(addr);\n-    size_t l4_size = dp_packet_l4_size(packet);\n-\n-    pkt_metadata_init_conn(&packet->md);\n-\n-    if (nh->ip_proto == IPPROTO_TCP && l4_size >= TCP_HEADER_LEN) {\n-        if (dp_packet_l4_checksum_valid(packet)) {\n-            dp_packet_l4_checksum_set_partial(packet);\n-        } else {\n-            struct tcp_header *th = dp_packet_l4(packet);\n-            th->tcp_csum = recalc_csum32(th->tcp_csum, old_addr, new_addr);\n-        }\n-    } else if (nh->ip_proto == IPPROTO_UDP && l4_size >= UDP_HEADER_LEN ) {\n-        if (dp_packet_l4_checksum_valid(packet)) {\n-            dp_packet_l4_checksum_set_partial(packet);\n-        } else {\n-            struct udp_header *uh = dp_packet_l4(packet);\n-            if (uh->udp_csum) {\n-                uh->udp_csum = recalc_csum32(uh->udp_csum, old_addr, new_addr);\n-                if (!uh->udp_csum) {\n-                    uh->udp_csum = htons(0xffff);\n-                }\n-            }\n-        }\n-    }\n-\n-    if (dp_packet_ip_checksum_valid(packet)) {\n-        dp_packet_ip_checksum_set_partial(packet);\n-    } else {\n-        nh->ip_csum = recalc_csum32(nh->ip_csum, old_addr, new_addr);\n-    }\n-    put_16aligned_be32(addr, new_addr);\n-}\n-\n-/* Returns true, if packet contains at least one routing header where\n- * segements_left > 0.\n- *\n- * This function assumes that L3 and L4 offsets are set in the packet. */\n-bool\n-packet_rh_present(struct dp_packet *packet, uint8_t *nexthdr, bool *first_frag)\n-{\n-    const struct ovs_16aligned_ip6_hdr *nh;\n-    size_t len;\n-    size_t remaining;\n-    uint8_t *data = dp_packet_l3(packet);\n-\n-    remaining = packet->l4_ofs - packet->l3_ofs;\n-    if (remaining < sizeof *nh) {\n-        return false;\n-    }\n-    nh = ALIGNED_CAST(struct ovs_16aligned_ip6_hdr *, data);\n-    data += sizeof *nh;\n-    remaining -= sizeof *nh;\n-    *nexthdr = nh->ip6_nxt;\n-\n-    while (1) {\n-        if ((*nexthdr != IPPROTO_HOPOPTS)\n-                && (*nexthdr != IPPROTO_ROUTING)\n-                && (*nexthdr != IPPROTO_DSTOPTS)\n-                && (*nexthdr != IPPROTO_AH)\n-                && (*nexthdr != IPPROTO_FRAGMENT)) {\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-            break;\n-        }\n-\n-        /* We only verify that at least 8 bytes of the next header are\n-         * available, but many of these headers are longer.  Ensure that\n-         * accesses within the extension header are within those first 8\n-         * bytes. All extension headers are required to be at least 8\n-         * bytes. */\n-        if (remaining < 8) {\n-            return false;\n-        }\n-\n-        if (*nexthdr == IPPROTO_AH) {\n-            /* A standard AH definition isn't available, but the fields\n-             * we care about are in the same location as the generic\n-             * option header--only the header length is calculated\n-             * differently. */\n-            const struct ip6_ext *ext_hdr = (struct ip6_ext *)data;\n-\n-            *nexthdr = ext_hdr->ip6e_nxt;\n-            len = (ext_hdr->ip6e_len + 2) * 4;\n-        } else if (*nexthdr == IPPROTO_FRAGMENT) {\n-            const struct ovs_16aligned_ip6_frag *frag_hdr\n-                = ALIGNED_CAST(struct ovs_16aligned_ip6_frag *, data);\n-\n-            *first_frag = !(frag_hdr->ip6f_offlg & IP6F_OFF_MASK) &&\n-                           (frag_hdr->ip6f_offlg & IP6F_MORE_FRAG);\n-            *nexthdr = frag_hdr->ip6f_nxt;\n-            len = sizeof *frag_hdr;\n-        } else if (*nexthdr == IPPROTO_ROUTING) {\n-            const struct ip6_rthdr *rh = (struct ip6_rthdr *)data;\n-\n-            if (rh->ip6r_segleft > 0) {\n-                return true;\n-            }\n-\n-            *nexthdr = rh->ip6r_nxt;\n-            len = (rh->ip6r_len + 1) * 8;\n-        } else {\n-            const struct ip6_ext *ext_hdr = (struct ip6_ext *)data;\n-\n-            *nexthdr = ext_hdr->ip6e_nxt;\n-            len = (ext_hdr->ip6e_len + 1) * 8;\n-        }\n-\n-        if (remaining < len) {\n-            return false;\n-        }\n-        remaining -= len;\n-        data += len;\n-    }\n-\n-    return false;\n-}\n-\n-static void\n-packet_update_csum128(struct dp_packet *packet, uint8_t proto,\n-                      ovs_16aligned_be32 addr[4],\n-                      const struct in6_addr *new_addr)\n-{\n-    size_t l4_size = dp_packet_l4_size(packet);\n-\n-    if (proto == IPPROTO_TCP && l4_size >= TCP_HEADER_LEN) {\n-        if (dp_packet_l4_checksum_valid(packet)) {\n-            dp_packet_l4_checksum_set_partial(packet);\n-        } else {\n-            struct tcp_header *th = dp_packet_l4(packet);\n-\n-            th->tcp_csum = recalc_csum128(th->tcp_csum, addr, new_addr);\n-        }\n-    } else if (proto == IPPROTO_UDP && l4_size >= UDP_HEADER_LEN) {\n-        if (dp_packet_l4_checksum_valid(packet)) {\n-            dp_packet_l4_checksum_set_partial(packet);\n-        } else {\n-            struct udp_header *uh = dp_packet_l4(packet);\n-\n-            if (uh->udp_csum) {\n-                uh->udp_csum = recalc_csum128(uh->udp_csum, addr, new_addr);\n-                if (!uh->udp_csum) {\n-                    uh->udp_csum = htons(0xffff);\n-                }\n-            }\n-        }\n-    } else if (proto == IPPROTO_ICMPV6 &&\n-               l4_size >= sizeof(struct icmp6_header)) {\n-        struct icmp6_header *icmp = dp_packet_l4(packet);\n-\n-        icmp->icmp6_cksum = recalc_csum128(icmp->icmp6_cksum, addr, new_addr);\n-    }\n-}\n-\n-void\n-packet_set_ipv6_addr(struct dp_packet *packet, uint8_t proto,\n-                     ovs_16aligned_be32 addr[4],\n-                     const struct in6_addr *new_addr,\n-                     bool recalculate_csum)\n-{\n-    if (recalculate_csum) {\n-        packet_update_csum128(packet, proto, addr, new_addr);\n-    }\n-    memcpy(addr, new_addr, sizeof(ovs_be32[4]));\n-    pkt_metadata_init_conn(&packet->md);\n-}\n-\n-/* Modifies the IPv4 header fields of 'packet' to be consistent with 'src',\n- * 'dst', 'tos', and 'ttl'.  Updates 'packet''s L4 checksums as appropriate.\n- * 'packet' must contain a valid IPv4 packet with correctly populated l[347]\n- * markers. */\n-void\n-packet_set_ipv4(struct dp_packet *packet, ovs_be32 src, ovs_be32 dst,\n-                uint8_t tos, uint8_t ttl)\n-{\n-    struct ip_header *nh = dp_packet_l3(packet);\n-\n-    if (get_16aligned_be32(&nh->ip_src) != src) {\n-        packet_set_ipv4_addr(packet, &nh->ip_src, src);\n-    }\n-\n-    if (get_16aligned_be32(&nh->ip_dst) != dst) {\n-        packet_set_ipv4_addr(packet, &nh->ip_dst, dst);\n-    }\n-\n-    if (nh->ip_tos != tos) {\n-        uint8_t *field = &nh->ip_tos;\n-\n-        if (dp_packet_ip_checksum_valid(packet)) {\n-            dp_packet_ip_checksum_set_partial(packet);\n-        } else {\n-            nh->ip_csum = recalc_csum16(nh->ip_csum, htons((uint16_t) *field),\n-                                        htons((uint16_t) tos));\n-        }\n-\n-        *field = tos;\n-    }\n-\n-    if (nh->ip_ttl != ttl) {\n-        uint8_t *field = &nh->ip_ttl;\n-\n-        if (dp_packet_ip_checksum_valid(packet)) {\n-            dp_packet_ip_checksum_set_partial(packet);\n-        } else {\n-            nh->ip_csum = recalc_csum16(nh->ip_csum, htons(*field << 8),\n-                                        htons(ttl << 8));\n-        }\n-\n-        *field = ttl;\n-    }\n-}\n-\n-/* Modifies the IPv6 header fields of 'packet' to be consistent with 'src',\n- * 'dst', 'traffic class', and 'next hop'.  Updates 'packet''s L4 checksums as\n- * appropriate. 'packet' must contain a valid IPv6 packet with correctly\n- * populated l[34] offsets. */\n-void\n-packet_set_ipv6(struct dp_packet *packet, const struct in6_addr *src,\n-                const struct in6_addr *dst, uint8_t key_tc, ovs_be32 key_fl,\n-                uint8_t key_hl)\n-{\n-    struct ovs_16aligned_ip6_hdr *nh = dp_packet_l3(packet);\n-    bool recalc_csum = true;\n-    uint8_t proto = 0;\n-    bool rh_present;\n-\n-    rh_present = packet_rh_present(packet, &proto, &recalc_csum);\n-\n-    if (memcmp(&nh->ip6_src, src, sizeof(ovs_be32[4]))) {\n-        packet_set_ipv6_addr(packet, proto, nh->ip6_src.be32,\n-                             src, recalc_csum);\n-    }\n-\n-    if (memcmp(&nh->ip6_dst, dst, sizeof(ovs_be32[4]))) {\n-        packet_set_ipv6_addr(packet, proto, nh->ip6_dst.be32, dst,\n-                             !rh_present && recalc_csum);\n-    }\n-\n-    ip_set_ipv6_tc(&nh->ip6_flow, key_tc);\n-    ip_set_ipv6_flow_label(&nh->ip6_flow, key_fl);\n-    nh->ip6_hlim = key_hl;\n-}\n-\n-static void\n-packet_set_port(ovs_be16 *port, ovs_be16 new_port, ovs_be16 *csum)\n-{\n-    if (*port != new_port) {\n-        if (csum) {\n-            *csum = recalc_csum16(*csum, *port, new_port);\n-        }\n-        *port = new_port;\n-    }\n-}\n-\n-/* Sets the TCP source and destination port ('src' and 'dst' respectively) of\n- * the TCP header contained in 'packet'.  'packet' must be a valid TCP packet\n- * with its l4 offset properly populated. */\n-void\n-packet_set_tcp_port(struct dp_packet *packet, ovs_be16 src, ovs_be16 dst)\n-{\n-    struct tcp_header *th = dp_packet_l4(packet);\n-    ovs_be16 *csum = NULL;\n-\n-    if (dp_packet_l4_checksum_valid(packet)) {\n-        dp_packet_l4_checksum_set_partial(packet);\n-    } else {\n-        csum = &th->tcp_csum;\n-    }\n-\n-    packet_set_port(&th->tcp_src, src, csum);\n-    packet_set_port(&th->tcp_dst, dst, csum);\n-    pkt_metadata_init_conn(&packet->md);\n-}\n-\n-/* Sets the UDP source and destination port ('src' and 'dst' respectively) of\n- * the UDP header contained in 'packet'.  'packet' must be a valid UDP packet\n- * with its l4 offset properly populated. */\n-void\n-packet_set_udp_port(struct dp_packet *packet, ovs_be16 src, ovs_be16 dst)\n-{\n-    struct udp_header *uh = dp_packet_l4(packet);\n-\n-    if (dp_packet_l4_checksum_valid(packet)) {\n-        dp_packet_l4_checksum_set_partial(packet);\n-        packet_set_port(&uh->udp_src, src, NULL);\n-        packet_set_port(&uh->udp_dst, dst, NULL);\n-    } else {\n-        ovs_be16 *csum = uh->udp_csum ? &uh->udp_csum : NULL;\n-\n-        packet_set_port(&uh->udp_src, src, csum);\n-        packet_set_port(&uh->udp_dst, dst, csum);\n-\n-        if (csum && !uh->udp_csum) {\n-            uh->udp_csum = htons(0xffff);\n-        }\n-    }\n-\n-    pkt_metadata_init_conn(&packet->md);\n-}\n-\n-/* Sets the SCTP source and destination port ('src' and 'dst' respectively) of\n- * the SCTP header contained in 'packet'.  'packet' must be a valid SCTP packet\n- * with its l4 offset properly populated. */\n-void\n-packet_set_sctp_port(struct dp_packet *packet, ovs_be16 src, ovs_be16 dst)\n-{\n-    struct sctp_header *sh = dp_packet_l4(packet);\n-\n-    if (dp_packet_l4_checksum_valid(packet)) {\n-        dp_packet_l4_checksum_set_partial(packet);\n-        sh->sctp_src = src;\n-        sh->sctp_dst = dst;\n-    } else {\n-        ovs_be32 old_csum, old_correct_csum, new_csum;\n-        uint16_t tp_len = dp_packet_l4_size(packet);\n-\n-        old_csum = get_16aligned_be32(&sh->sctp_csum);\n-        put_16aligned_be32(&sh->sctp_csum, 0);\n-        old_correct_csum = crc32c((void *) sh, tp_len);\n-\n-        sh->sctp_src = src;\n-        sh->sctp_dst = dst;\n-\n-        new_csum = crc32c((void *) sh, tp_len);\n-        put_16aligned_be32(&sh->sctp_csum, old_csum ^ old_correct_csum\n-                           ^ new_csum);\n-    }\n-\n-    pkt_metadata_init_conn(&packet->md);\n-}\n-\n-/* Sets the ICMP type and code of the ICMP header contained in 'packet'.\n- * 'packet' must be a valid ICMP packet with its l4 offset properly\n- * populated. */\n-void\n-packet_set_icmp(struct dp_packet *packet, uint8_t type, uint8_t code)\n-{\n-    struct icmp_header *ih = dp_packet_l4(packet);\n-    ovs_be16 orig_tc = htons(ih->icmp_type << 8 | ih->icmp_code);\n-    ovs_be16 new_tc = htons(type << 8 | code);\n-\n-    if (orig_tc != new_tc) {\n-        ih->icmp_type = type;\n-        ih->icmp_code = code;\n-\n-        ih->icmp_csum = recalc_csum16(ih->icmp_csum, orig_tc, new_tc);\n-    }\n-    pkt_metadata_init_conn(&packet->md);\n-}\n-\n-/* Sets the ICMP id of the ICMP header contained in 'packet'.\n- * 'packet' must be a valid ICMP packet with its l4 offset properly\n- * populated. */\n-void\n-packet_set_icmp_id(struct dp_packet *packet, ovs_be16 icmp_id)\n-{\n-    struct icmp_header *ih = dp_packet_l4(packet);\n-\n-    if (!ih || dp_packet_l4_size(packet) < ICMP_HEADER_LEN) {\n-        return;\n-    }\n-\n-    ovs_be16 orig_ic = ih->icmp_fields.echo.id;\n-\n-    if (icmp_id != orig_ic) {\n-        ih->icmp_fields.echo.id = icmp_id;\n-        ih->icmp_csum = recalc_csum16(ih->icmp_csum, orig_ic, icmp_id);\n-    }\n-\n-    pkt_metadata_init_conn(&packet->md);\n-}\n-\n-uint8_t\n-packet_get_icmp_type(const struct dp_packet *packet)\n-{\n-    struct icmp_header *ih = dp_packet_l4(packet);\n-\n-    if (!ih || dp_packet_l4_size(packet) < ICMP_HEADER_LEN) {\n-        return 0;\n-    }\n-\n-    return ih->icmp_type;\n-}\n-\n-uint8_t\n-packet_get_ip_proto(const struct dp_packet *packet)\n-{\n-    struct eth_header *l2 = dp_packet_eth(packet);\n-    uint8_t ip_proto;\n-\n-    if (l2->eth_type == htons(ETH_TYPE_IPV6)) {\n-        struct ovs_16aligned_ip6_hdr *nh6 = dp_packet_l3(packet);\n-        ip_proto = nh6->ip6_ctlun.ip6_un1.ip6_un1_nxt;\n-    } else {\n-        struct ip_header *l3_hdr = dp_packet_l3(packet);\n-        ip_proto = l3_hdr->ip_proto;\n-    }\n-\n-    return ip_proto;\n-}\n-\n-bool\n-packet_is_icmpv4_info_message(const struct dp_packet *packet)\n-{\n-    uint8_t ip_proto, icmp_type;\n-\n-    ip_proto = packet_get_ip_proto(packet);\n-    if (ip_proto != IPPROTO_ICMP) {\n-        return false;\n-    }\n-\n-    icmp_type = packet_get_icmp_type(packet);\n-    if (icmp_type == ICMP4_ECHO_REQUEST ||\n-        icmp_type == ICMP4_ECHO_REPLY ||\n-        icmp_type == ICMP4_TIMESTAMP ||\n-        icmp_type == ICMP4_TIMESTAMPREPLY ||\n-        icmp_type == ICMP4_INFOREQUEST ||\n-        icmp_type == ICMP4_INFOREPLY) {\n-        return true;\n-    }\n-\n-    return false;\n-}\n-\n-/* Sets the IGMP type to IGMP_HOST_MEMBERSHIP_QUERY and populates the\n- * v3 query header fields in 'packet'. 'packet' must be a valid IGMPv3\n- * query packet with its l4 offset properly populated.\n- */\n-void\n-packet_set_igmp3_query(struct dp_packet *packet, uint8_t max_resp,\n-                       ovs_be32 group, bool srs, uint8_t qrv, uint8_t qqic)\n-{\n-    struct igmpv3_query_header *igh = dp_packet_l4(packet);\n-    ovs_be16 orig_type_max_resp =\n-        htons(igh->type << 8 | igh->max_resp);\n-    ovs_be16 new_type_max_resp =\n-        htons(IGMP_HOST_MEMBERSHIP_QUERY << 8 | max_resp);\n-\n-    if (orig_type_max_resp != new_type_max_resp) {\n-        igh->type = IGMP_HOST_MEMBERSHIP_QUERY;\n-        igh->max_resp = max_resp;\n-        igh->csum = recalc_csum16(igh->csum, orig_type_max_resp,\n-                                  new_type_max_resp);\n-    }\n-\n-    ovs_be32 old_group = get_16aligned_be32(&igh->group);\n-\n-    if (old_group != group) {\n-        put_16aligned_be32(&igh->group, group);\n-        igh->csum = recalc_csum32(igh->csum, old_group, group);\n-    }\n-\n-    /* See RFC 3376 4.1.6. */\n-    if (qrv > 7) {\n-        qrv = 0;\n-    }\n-\n-    ovs_be16 orig_srs_qrv_qqic = htons(igh->srs_qrv << 8 | igh->qqic);\n-    ovs_be16 new_srs_qrv_qqic = htons(srs << 11 | qrv << 8 | qqic);\n-\n-    if (orig_srs_qrv_qqic != new_srs_qrv_qqic) {\n-        igh->srs_qrv = (srs << 3 | qrv);\n-        igh->qqic = qqic;\n-        igh->csum = recalc_csum16(igh->csum, orig_srs_qrv_qqic,\n-                                  new_srs_qrv_qqic);\n-    }\n-}\n-\n-void\n-packet_set_nd_ext(struct dp_packet *packet, const ovs_16aligned_be32 rso_flags,\n-                  const uint8_t opt_type)\n-{\n-    struct ovs_nd_msg *ns;\n-    struct ovs_nd_lla_opt *opt;\n-    int bytes_remain = dp_packet_l4_size(packet);\n-    struct ovs_16aligned_ip6_hdr * nh = dp_packet_l3(packet);\n-    uint32_t pseudo_hdr_csum = 0;\n-\n-    if (OVS_UNLIKELY(bytes_remain < sizeof(*ns))) {\n-        return;\n-    }\n-\n-    if (nh) {\n-        pseudo_hdr_csum = ip_csum_pseudoheader6(nh);\n-    }\n-\n-    ns = dp_packet_l4(packet);\n-    opt = &ns->options[0];\n-\n-    /* set RSO flags and option type */\n-    ns->rso_flags = rso_flags;\n-    opt->type = opt_type;\n-\n-    /* recalculate checksum */\n-    ovs_be16 *csum_value = &(ns->icmph.icmp6_cksum);\n-    *csum_value = 0;\n-    *csum_value = csum_finish(csum_continue(pseudo_hdr_csum,\n-                              &(ns->icmph), bytes_remain));\n-\n-}\n-\n-void\n-packet_set_nd(struct dp_packet *packet, const struct in6_addr *target,\n-              const struct eth_addr sll, const struct eth_addr tll)\n-{\n-    struct ovs_nd_msg *ns;\n-    struct ovs_nd_lla_opt *opt;\n-    int bytes_remain = dp_packet_l4_size(packet);\n-\n-    if (OVS_UNLIKELY(bytes_remain < sizeof(*ns))) {\n-        return;\n-    }\n-\n-    ns = dp_packet_l4(packet);\n-    opt = &ns->options[0];\n-    bytes_remain -= sizeof(*ns);\n-\n-    if (memcmp(&ns->target, target, sizeof(ovs_be32[4]))) {\n-        packet_set_ipv6_addr(packet, IPPROTO_ICMPV6, ns->target.be32, target,\n-                             true);\n-    }\n-\n-    while (bytes_remain >= ND_LLA_OPT_LEN && opt->len != 0\n-           && bytes_remain >= (opt->len * ND_LLA_OPT_LEN)) {\n-        if (opt->type == ND_OPT_SOURCE_LINKADDR && opt->len == 1) {\n-            if (!eth_addr_equals(opt->mac, sll)) {\n-                ovs_be16 *csum = &(ns->icmph.icmp6_cksum);\n-\n-                *csum = recalc_csum48(*csum, opt->mac, sll);\n-                opt->mac = sll;\n-            }\n-\n-            /* A packet can only contain one SLL or TLL option */\n-            break;\n-        } else if (opt->type == ND_OPT_TARGET_LINKADDR && opt->len == 1) {\n-            if (!eth_addr_equals(opt->mac, tll)) {\n-                ovs_be16 *csum = &(ns->icmph.icmp6_cksum);\n-\n-                *csum = recalc_csum48(*csum, opt->mac, tll);\n-                opt->mac = tll;\n-            }\n-\n-            /* A packet can only contain one SLL or TLL option */\n-            break;\n-        }\n-\n-        opt += opt->len;\n-        bytes_remain -= opt->len * ND_LLA_OPT_LEN;\n-    }\n-}\n-\n-#define ARP_PACKET_SIZE  (2 + ETH_HEADER_LEN + VLAN_HEADER_LEN + \\\n-                          ARP_ETH_HEADER_LEN)\n-\n-/* Clears 'b' and replaces its contents by an ARP frame with the specified\n- * 'arp_op', 'arp_sha', 'arp_tha', 'arp_spa', and 'arp_tpa'.  The outer\n- * Ethernet frame is initialized with Ethernet source 'arp_sha' and destination\n- * 'arp_tha', except that destination ff:ff:ff:ff:ff:ff is used instead if\n- * 'broadcast' is true.  Points the L3 header to the ARP header. */\n-void\n-compose_arp(struct dp_packet *b, uint16_t arp_op,\n-            const struct eth_addr arp_sha, const struct eth_addr arp_tha,\n-            bool broadcast, ovs_be32 arp_spa, ovs_be32 arp_tpa)\n-{\n-    compose_arp__(b);\n-\n-    struct eth_header *eth = dp_packet_eth(b);\n-    eth->eth_dst = broadcast ? eth_addr_broadcast : arp_tha;\n-    eth->eth_src = arp_sha;\n-\n-    struct arp_eth_header *arp = dp_packet_l3(b);\n-    arp->ar_op = htons(arp_op);\n-    arp->ar_sha = arp_sha;\n-    arp->ar_tha = arp_tha;\n-    put_16aligned_be32(&arp->ar_spa, arp_spa);\n-    put_16aligned_be32(&arp->ar_tpa, arp_tpa);\n-}\n-\n-/* Clears 'b' and replaces its contents by an ARP frame.  Sets the fields in\n- * the Ethernet and ARP headers that are fixed for ARP frames to those fixed\n- * values, and zeroes the other fields.  Points the L3 header to the ARP\n- * header. */\n-void\n-compose_arp__(struct dp_packet *b)\n-{\n-    dp_packet_clear(b);\n-    dp_packet_prealloc_tailroom(b, ARP_PACKET_SIZE);\n-    dp_packet_reserve(b, 2 + VLAN_HEADER_LEN);\n-\n-    struct eth_header *eth = dp_packet_put_zeros(b, sizeof *eth);\n-    eth->eth_type = htons(ETH_TYPE_ARP);\n-\n-    struct arp_eth_header *arp = dp_packet_put_zeros(b, sizeof *arp);\n-    arp->ar_hrd = htons(ARP_HRD_ETHERNET);\n-    arp->ar_pro = htons(ARP_PRO_IP);\n-    arp->ar_hln = sizeof arp->ar_sha;\n-    arp->ar_pln = sizeof arp->ar_spa;\n-\n-    dp_packet_set_l3(b, arp);\n-\n-    b->packet_type = htonl(PT_ETH);\n-}\n-\n-/* This function expects packet with ethernet header with correct\n- * l3 pointer set. */\n-void *\n-compose_ipv6(struct dp_packet *packet, uint8_t proto,\n-             const struct in6_addr *src, const struct in6_addr *dst,\n-             uint8_t key_tc, ovs_be32 key_fl, uint8_t key_hl, int size)\n-{\n-    struct ovs_16aligned_ip6_hdr *nh;\n-    void *data;\n-\n-    nh = dp_packet_l3(packet);\n-    nh->ip6_vfc = 0x60;\n-    nh->ip6_nxt = proto;\n-    nh->ip6_plen = htons(size);\n-    data = dp_packet_put_zeros(packet, size);\n-    dp_packet_set_l4(packet, data);\n-    packet_set_ipv6(packet, src, dst, key_tc, key_fl, key_hl);\n-    return data;\n-}\n-\n-/* Compose an IPv6 Neighbor Discovery Neighbor Solicitation message. */\n-void\n-compose_nd_ns(struct dp_packet *b, const struct eth_addr eth_src,\n-              const struct in6_addr *ipv6_src, const struct in6_addr *ipv6_dst)\n-{\n-    struct in6_addr sn_addr;\n-    struct eth_addr eth_dst;\n-    struct ovs_nd_msg *ns;\n-    struct ovs_nd_lla_opt *lla_opt;\n-    uint32_t icmp_csum;\n-\n-    in6_addr_solicited_node(&sn_addr, ipv6_dst);\n-    ipv6_multicast_to_ethernet(&eth_dst, &sn_addr);\n-\n-    eth_compose(b, eth_dst, eth_src, ETH_TYPE_IPV6, IPV6_HEADER_LEN);\n-    ns = compose_ipv6(b, IPPROTO_ICMPV6, ipv6_src, &sn_addr,\n-                      0, 0, 255, ND_MSG_LEN + ND_LLA_OPT_LEN);\n-\n-    ns->icmph.icmp6_type = ND_NEIGHBOR_SOLICIT;\n-    ns->icmph.icmp6_code = 0;\n-    put_16aligned_be32(&ns->rso_flags, htonl(0));\n-\n-    lla_opt = &ns->options[0];\n-    lla_opt->type = ND_OPT_SOURCE_LINKADDR;\n-    lla_opt->len = 1;\n-\n-    packet_set_nd(b, ipv6_dst, eth_src, eth_addr_zero);\n-\n-    ns->icmph.icmp6_cksum = 0;\n-    icmp_csum = ip_csum_pseudoheader6(dp_packet_l3(b));\n-    ns->icmph.icmp6_cksum = csum_finish(\n-        csum_continue(icmp_csum, ns, ND_MSG_LEN + ND_LLA_OPT_LEN));\n-}\n-\n-/* Compose an IPv6 Neighbor Discovery Neighbor Advertisement message. */\n-void\n-compose_nd_na(struct dp_packet *b,\n-              const struct eth_addr eth_src, const struct eth_addr eth_dst,\n-              const struct in6_addr *ipv6_src, const struct in6_addr *ipv6_dst,\n-              ovs_be32 rso_flags)\n-{\n-    struct ovs_nd_msg *na;\n-    struct ovs_nd_lla_opt *lla_opt;\n-    uint32_t icmp_csum;\n-\n-    eth_compose(b, eth_dst, eth_src, ETH_TYPE_IPV6, IPV6_HEADER_LEN);\n-    na = compose_ipv6(b, IPPROTO_ICMPV6, ipv6_src, ipv6_dst,\n-                      0, 0, 255, ND_MSG_LEN + ND_LLA_OPT_LEN);\n-\n-    na->icmph.icmp6_type = ND_NEIGHBOR_ADVERT;\n-    na->icmph.icmp6_code = 0;\n-    put_16aligned_be32(&na->rso_flags, rso_flags);\n-\n-    lla_opt = &na->options[0];\n-    lla_opt->type = ND_OPT_TARGET_LINKADDR;\n-    lla_opt->len = 1;\n-\n-    packet_set_nd(b, ipv6_src, eth_addr_zero, eth_src);\n-\n-    na->icmph.icmp6_cksum = 0;\n-    icmp_csum = ip_csum_pseudoheader6(dp_packet_l3(b));\n-    na->icmph.icmp6_cksum = csum_finish(csum_continue(\n-        icmp_csum, na, ND_MSG_LEN + ND_LLA_OPT_LEN));\n-}\n-\n-/* Compose an IPv6 Neighbor Discovery Router Advertisement message with\n- * Source Link-layer Address Option and MTU Option.\n- * Caller can call packet_put_ra_prefix_opt to append Prefix Information\n- * Options to composed messags in 'b'. */\n-void\n-compose_nd_ra(struct dp_packet *b,\n-              const struct eth_addr eth_src, const struct eth_addr eth_dst,\n-              const struct in6_addr *ipv6_src, const struct in6_addr *ipv6_dst,\n-              uint8_t cur_hop_limit, uint8_t mo_flags,\n-              ovs_be16 router_lt, ovs_be32 reachable_time,\n-              ovs_be32 retrans_timer, uint32_t mtu)\n-{\n-    /* Don't compose Router Advertisement packet with MTU Option if mtu\n-     * value is 0. */\n-    bool with_mtu = mtu != 0;\n-    size_t mtu_opt_len = with_mtu ? ND_MTU_OPT_LEN : 0;\n-\n-    eth_compose(b, eth_dst, eth_src, ETH_TYPE_IPV6, IPV6_HEADER_LEN);\n-\n-    struct ovs_ra_msg *ra = compose_ipv6(\n-        b, IPPROTO_ICMPV6, ipv6_src, ipv6_dst, 0, 0, 255,\n-        RA_MSG_LEN + ND_LLA_OPT_LEN + mtu_opt_len);\n-    ra->icmph.icmp6_type = ND_ROUTER_ADVERT;\n-    ra->icmph.icmp6_code = 0;\n-    ra->cur_hop_limit = cur_hop_limit;\n-    ra->mo_flags = mo_flags;\n-    ra->router_lifetime = router_lt;\n-    ra->reachable_time = reachable_time;\n-    ra->retrans_timer = retrans_timer;\n-\n-    struct ovs_nd_lla_opt *lla_opt = ra->options;\n-    lla_opt->type = ND_OPT_SOURCE_LINKADDR;\n-    lla_opt->len = 1;\n-    lla_opt->mac = eth_src;\n-\n-    if (with_mtu) {\n-        /* ovs_nd_mtu_opt has the same size with ovs_nd_lla_opt. */\n-        struct ovs_nd_mtu_opt *mtu_opt\n-            = (struct ovs_nd_mtu_opt *)(lla_opt + 1);\n-        mtu_opt->type = ND_OPT_MTU;\n-        mtu_opt->len = 1;\n-        mtu_opt->reserved = 0;\n-        put_16aligned_be32(&mtu_opt->mtu, htonl(mtu));\n-    }\n-\n-    ra->icmph.icmp6_cksum = 0;\n-    uint32_t icmp_csum = ip_csum_pseudoheader6(dp_packet_l3(b));\n-    ra->icmph.icmp6_cksum = csum_finish(csum_continue(\n-        icmp_csum, ra, RA_MSG_LEN + ND_LLA_OPT_LEN + mtu_opt_len));\n-}\n-\n-/* Append an IPv6 Neighbor Discovery Prefix Information option to a\n- * Router Advertisement message. */\n-void\n-packet_put_ra_prefix_opt(struct dp_packet *b,\n-                         uint8_t plen, uint8_t la_flags,\n-                         ovs_be32 valid_lifetime, ovs_be32 preferred_lifetime,\n-                         const ovs_be128 prefix)\n-{\n-    size_t prev_l4_size = dp_packet_l4_size(b);\n-    struct ovs_16aligned_ip6_hdr *nh = dp_packet_l3(b);\n-    nh->ip6_plen = htons(prev_l4_size + ND_PREFIX_OPT_LEN);\n-\n-    struct ovs_nd_prefix_opt *prefix_opt =\n-        dp_packet_put_uninit(b, sizeof *prefix_opt);\n-    prefix_opt->type = ND_OPT_PREFIX_INFORMATION;\n-    prefix_opt->len = 4;\n-    prefix_opt->prefix_len = plen;\n-    prefix_opt->la_flags = la_flags;\n-    put_16aligned_be32(&prefix_opt->valid_lifetime, valid_lifetime);\n-    put_16aligned_be32(&prefix_opt->preferred_lifetime, preferred_lifetime);\n-    put_16aligned_be32(&prefix_opt->reserved, 0);\n-    memcpy(prefix_opt->prefix.be32, prefix.be32, sizeof(ovs_be32[4]));\n-\n-    struct ovs_ra_msg *ra = dp_packet_l4(b);\n-    ra->icmph.icmp6_cksum = 0;\n-    uint32_t icmp_csum = ip_csum_pseudoheader6(dp_packet_l3(b));\n-    ra->icmph.icmp6_cksum = csum_finish(csum_continue(\n-        icmp_csum, ra, prev_l4_size + ND_PREFIX_OPT_LEN));\n-}\n-\n-void\n-IP_ECN_set_ce(struct dp_packet *pkt, bool is_ipv6)\n-{\n-    if (is_ipv6) {\n-        ovs_16aligned_be32 *ip6 = dp_packet_l3(pkt);\n-\n-        put_16aligned_be32(ip6, get_16aligned_be32(ip6) |\n-                                htonl(IP_ECN_CE << 20));\n-    } else {\n-        struct ip_header *nh = dp_packet_l3(pkt);\n-        uint8_t tos = nh->ip_tos;\n-\n-        tos |= IP_ECN_CE;\n-        if (nh->ip_tos != tos) {\n-            if (dp_packet_ip_checksum_valid(pkt)) {\n-                dp_packet_ip_checksum_set_partial(pkt);\n-            } else {\n-                nh->ip_csum = recalc_csum16(nh->ip_csum, htons(nh->ip_tos),\n-                                            htons((uint16_t) tos));\n-            }\n-\n-            nh->ip_tos = tos;\n-        }\n-    }\n-}\n-\n-/* Set TCP checksum field in packet 'p' with complete checksum.\n- * The packet must have the L3 and L4 offsets. */\n-void\n-packet_tcp_complete_csum(struct dp_packet *p, bool inner)\n-{\n-    struct tcp_header *tcp;\n-    size_t tcp_sz;\n-    void *ip_hdr;\n-\n-    if (inner) {\n-        tcp = dp_packet_inner_l4(p);\n-        ip_hdr = dp_packet_inner_l3(p);\n-        tcp_sz = dp_packet_inner_l4_size(p);\n-    } else {\n-        tcp = dp_packet_l4(p);\n-        ip_hdr = dp_packet_l3(p);\n-        tcp_sz = dp_packet_l4_size(p);\n-    }\n-\n-    ovs_assert(tcp);\n-    ovs_assert(ip_hdr);\n-\n-    tcp->tcp_csum = 0;\n-    if (IP_VER(((const struct ip_header *) ip_hdr)->ip_ihl_ver) == 4) {\n-        struct ip_header *ip = ip_hdr;\n-\n-        tcp->tcp_csum = csum_finish(csum_continue(ip_csum_pseudoheader(ip),\n-                                                  tcp, tcp_sz));\n-    } else {\n-        struct ovs_16aligned_ip6_hdr *ip6 = ip_hdr;\n-\n-        tcp->tcp_csum = ip_csum_upperlayer6(ip6, tcp, ip6->ip6_nxt,\n-                                                tcp_sz);\n-    }\n-\n-    if (inner) {\n-        dp_packet_inner_l4_checksum_set_good(p);\n-    } else {\n-        dp_packet_l4_checksum_set_good(p);\n-    }\n-}\n-\n-/* Set UDP checksum field in packet 'p' with complete checksum.\n- * The packet must have the L3 and L4 offsets. */\n-void\n-packet_udp_complete_csum(struct dp_packet *p, bool inner)\n-{\n-    struct udp_header *udp;\n-    size_t udp_sz;\n-    void *ip_hdr;\n-\n-    if (inner) {\n-        udp = dp_packet_inner_l4(p);\n-        ip_hdr = dp_packet_inner_l3(p);\n-        udp_sz = dp_packet_inner_l4_size(p);\n-    } else {\n-        udp = dp_packet_l4(p);\n-        ip_hdr = dp_packet_l3(p);\n-        udp_sz = dp_packet_l4_size(p);\n-    }\n-\n-    ovs_assert(udp);\n-    ovs_assert(ip_hdr);\n-\n-    /* Skip csum calculation if the udp_csum is zero. */\n-    if (!udp->udp_csum) {\n-        goto out;\n-    }\n-\n-    udp->udp_csum = 0;\n-    if (IP_VER(((const struct ip_header *) ip_hdr)->ip_ihl_ver) == 4) {\n-        struct ip_header *ip = ip_hdr;\n-\n-        udp->udp_csum = csum_finish(csum_continue(ip_csum_pseudoheader(ip),\n-                                                  udp, udp_sz));\n-    } else {\n-        struct ovs_16aligned_ip6_hdr *ip6 = ip_hdr;\n-\n-        udp->udp_csum = ip_csum_upperlayer6(ip6, udp, ip6->ip6_nxt,\n-                                                udp_sz);\n-    }\n-\n-    if (!udp->udp_csum) {\n-        udp->udp_csum = htons(0xffff);\n-    }\n-\n-out:\n-    if (inner) {\n-        dp_packet_inner_l4_checksum_set_good(p);\n-    } else {\n-        dp_packet_l4_checksum_set_good(p);\n-    }\n-}\n-\n-/* This helper computes a \"constant\" UDP checksum without looking at the\n- * L4 payload.\n- *\n- * This is possible when L4 is either TCP or UDP: the L4 payload checksum\n- * is either computed in SW or in HW later, but its contribution to the\n- * outer checksum is cancelled by the L4 payload being part of the global\n- * packet sum. */\n-bool\n-packet_udp_tunnel_csum(struct dp_packet *p)\n-{\n-    struct ip_header *inner_ip;\n-    const void *inner_l4_data;\n-    char *after_inner_l4_csum;\n-    size_t inner_l4_csum_off;\n-    struct udp_header *udp;\n-    ovs_be16 inner_l4_csum;\n-    uint32_t partial_csum;\n-    struct ip_header *ip;\n-    uint32_t inner_csum;\n-    uint16_t tso_segsz;\n-    bool inner_ipv4;\n-    void *inner_l4;\n-\n-    inner_ip = dp_packet_inner_l3(p);\n-    inner_l4 = dp_packet_inner_l4(p);\n-    ip = dp_packet_l3(p);\n-    udp = dp_packet_l4(p);\n-\n-    if (dp_packet_inner_l4_proto_tcp(p)) {\n-        inner_l4_csum_off = offsetof(struct tcp_header, tcp_csum);\n-        inner_l4_data = dp_packet_get_inner_tcp_payload(p);\n-        if (!inner_l4_data) {\n-            /* Malformed packet. */\n-            return false;\n-        }\n-    } else if (dp_packet_inner_l4_proto_udp(p)) {\n-        inner_l4_csum_off = offsetof(struct udp_header, udp_csum);\n-        inner_l4_data = (char *) inner_l4 + sizeof (struct udp_header);\n-        if (((struct udp_header *) inner_l4)->udp_csum == 0) {\n-            /* There is no nested checksum.\n-             * No choice but compute a full checksum. */\n-            return false;\n-        }\n-    } else {\n-        /* This optimisation applies only to inner TCP/UDP. */\n-        return false;\n-    }\n-\n-    if (!dp_packet_inner_l4_checksum_valid(p)) {\n-        /* We have no idea about the contribution of the payload data\n-         * and what the L4 checksum put in the packet data looks like.\n-         * Simpler is to let a full checksum happen. */\n-        return false;\n-    }\n-\n-    inner_ipv4 = IP_VER(inner_ip->ip_ihl_ver) == 4;\n-    if (inner_ipv4) {\n-        inner_csum = ip_csum_pseudoheader(inner_ip);\n-    } else {\n-        struct ovs_16aligned_ip6_hdr *inner_ip6 = dp_packet_inner_l3(p);\n-\n-        inner_csum = ip_csum_pseudoheader6(inner_ip6);\n-    }\n-\n-    inner_csum = csum_continue(inner_csum, inner_l4, inner_l4_csum_off);\n-    after_inner_l4_csum = (char *) inner_l4 + inner_l4_csum_off + 2;\n-    inner_l4_csum = csum_finish(csum_continue(inner_csum, after_inner_l4_csum,\n-        (char *) inner_l4_data - after_inner_l4_csum));\n-    /* Important: for inner UDP, a null inner_l4_csum here should in theory be\n-     * replaced with 0xffff.  However, since the only use of inner_l4_csum is\n-     * for the final outer checksum with a csum_add16() below, we can skip this\n-     * entirely because adding 0xffff will have the same effect as adding 0x0\n-     * after reducing in csum_finish. */\n-\n-    udp->udp_csum = 0;\n-    if (IP_VER(ip->ip_ihl_ver) == 4) {\n-        partial_csum = ip_csum_pseudoheader(ip);\n-    } else {\n-        struct ovs_16aligned_ip6_hdr *ip6 = dp_packet_l3(p);\n-\n-        partial_csum = ip_csum_pseudoheader6(ip6);\n-    }\n-\n-    partial_csum = csum_continue(partial_csum, udp,\n-        (char *) inner_ip - (char *) udp);\n-    if (!inner_ipv4 || !dp_packet_inner_ip_checksum_valid(p)) {\n-        /* IPv6 has no checksum, so for inner IPv6, we need to sum the header.\n-         *\n-         * In IPv4 case, if inner checksum is already good or HW offload\n-         * has been requested, the (final) sum of the IPv4 header will be 0.\n-         * Otherwise, we need to sum the header like for IPv6. */\n-        partial_csum = csum_continue(partial_csum, inner_ip,\n-            (char *) inner_l4 - (char *) inner_ip);\n-    }\n-    partial_csum = csum_continue(partial_csum, inner_l4, inner_l4_csum_off);\n-    partial_csum = csum_add16(partial_csum, inner_l4_csum);\n-    partial_csum = csum_continue(partial_csum, after_inner_l4_csum,\n-        (char *) inner_l4_data - after_inner_l4_csum);\n-    udp->udp_csum = csum_finish(partial_csum);\n-    tso_segsz = dp_packet_get_tso_segsz(p);\n-    if (tso_segsz) {\n-        uint16_t payload_len = dp_packet_get_inner_tcp_payload_length(p);\n-\n-        ovs_assert(payload_len == tso_segsz * dp_packet_gso_nr_segs(p));\n-\n-        /* The pseudo header used in the outer UDP checksum is dependent on\n-         * the ip_tot_len / ip6_plen which was a reflection of the TSO frame\n-         * size. The segmented packet will be shorter. */\n-        udp->udp_csum = recalc_csum16(udp->udp_csum, htons(payload_len),\n-                                      htons(tso_segsz));\n-\n-        /* When segmenting the packet, various headers get updated:\n-         * - inner L3\n-         *   - for IPv4, ip_tot_len is updated, BUT it is not affecting the\n-         *     outer UDP checksum because the IPv4 header itself contains\n-         *     a checksum that compensates for this update,\n-         *   - for IPv6, ip6_plen is updated, and this must be considered,\n-         * - inner L4\n-         *   - inner pseudo header used in the TCP checksum is dependent on\n-         *     the inner ip_tot_len / ip6_plen,\n-         *   - TCP seq number is updated,\n-         *   - the HW may change some TCP flags (think PSH/FIN),\n-         *   BUT the TCP checksum will compensate for those updates,\n-         *\n-         * Summary: we only care about the inner IPv6 header update.\n-         */\n-        if (IP_VER(inner_ip->ip_ihl_ver) != 4) {\n-            udp->udp_csum = recalc_csum16(udp->udp_csum, htons(payload_len),\n-                                          htons(tso_segsz));\n-        }\n-    }\n-    if (!udp->udp_csum) {\n-        udp->udp_csum = htons(0xffff);\n-    }\n-    dp_packet_l4_checksum_set_good(p);\n-\n-    return true;\n-}\n-\n-/* Set SCTP checksum field in packet 'p' with complete checksum.\n- * The packet must have the L3 and L4 offsets. */\n-void\n-packet_sctp_complete_csum(struct dp_packet *p, bool inner)\n-{\n-    struct sctp_header *sh;\n-    uint16_t tp_len;\n-    ovs_be32 csum;\n-\n-    if (inner) {\n-        sh = dp_packet_inner_l4(p);\n-        tp_len = dp_packet_inner_l4_size(p);\n-    } else {\n-        sh = dp_packet_l4(p);\n-        tp_len = dp_packet_l4_size(p);\n-    }\n-\n-    ovs_assert(sh);\n-\n-    put_16aligned_be32(&sh->sctp_csum, 0);\n-    csum = crc32c((void *) sh, tp_len);\n-    put_16aligned_be32(&sh->sctp_csum, csum);\n-\n-    if (inner) {\n-        dp_packet_inner_l4_checksum_set_good(p);\n-    } else {\n-        dp_packet_l4_checksum_set_good(p);\n-    }\n-}\ndiff --git a/lib/packets.h b/lib/packets.h\ndeleted file mode 100644\nindex 647161b4b..000000000\n--- a/lib/packets.h\n+++ /dev/null\n@@ -1,286 +0,0 @@\n-/*\n- * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 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 PACKETS_H\n-#define PACKETS_H 1\n-\n-#include <inttypes.h>\n-#include <sys/types.h>\n-#include <stdint.h>\n-#include <string.h>\n-#include \"compiler.h\"\n-#include \"openvswitch/geneve.h\"\n-#include \"openvswitch/net-proto.h\"\n-#include \"openvswitch/types.h\"\n-#include \"net-proto.h\"\n-#include \"openvswitch/nsh.h\"\n-#include \"odp-netlink.h\"\n-#include \"random.h\"\n-#include \"hash.h\"\n-#include \"tun-metadata.h\"\n-#include \"unaligned.h\"\n-#include \"util.h\"\n-#include \"timeval.h\"\n-\n-struct dp_packet;\n-struct conn;\n-struct ds;\n-\n-/* Purely internal to OVS userspace. These flags should never be exposed to\n- * the outside world and so aren't included in the flags mask. */\n-\n-/* Tunnel information is in userspace datapath format. */\n-#define FLOW_TNL_F_UDPIF (1 << 4)\n-\n-static inline bool\n-flow_tnl_dst_is_set(const struct flow_tnl *tnl)\n-{\n-    return tnl->ip_dst || ipv6_addr_is_set(&tnl->ipv6_dst);\n-}\n-\n-static inline bool\n-flow_tnl_src_is_set(const struct flow_tnl *tnl)\n-{\n-    return tnl->ip_src || ipv6_addr_is_set(&tnl->ipv6_src);\n-}\n-\n-struct in6_addr flow_tnl_dst(const struct flow_tnl *tnl);\n-struct in6_addr flow_tnl_src(const struct flow_tnl *tnl);\n-\n-/* Returns an offset to 'src' covering all the meaningful fields in 'src'. */\n-static inline size_t\n-flow_tnl_size(const struct flow_tnl *src)\n-{\n-    if (!flow_tnl_dst_is_set(src)) {\n-        /* Covers ip_dst and ipv6_dst only. */\n-        return offsetof(struct flow_tnl, ip_src);\n-    }\n-    if (src->flags & FLOW_TNL_F_UDPIF) {\n-        /* Datapath format, cover all options we have. */\n-        return offsetof(struct flow_tnl, metadata.opts)\n-            + src->metadata.present.len;\n-    }\n-    if (!src->metadata.present.map) {\n-        /* No TLVs, opts is irrelevant. */\n-        return offsetof(struct flow_tnl, metadata.opts);\n-    }\n-    /* Have decoded TLVs, opts is relevant. */\n-    return sizeof *src;\n-}\n-\n-/* Copy flow_tnl, but avoid copying unused portions of tun_metadata.  Unused\n- * data in 'dst' is NOT cleared, so this must not be used in cases where the\n- * uninitialized portion may be hashed over. */\n-static inline void\n-flow_tnl_copy__(struct flow_tnl *dst, const struct flow_tnl *src)\n-{\n-    memcpy(dst, src, flow_tnl_size(src));\n-}\n-\n-/* Datapath packet metadata */\n-struct pkt_metadata {\n-PADDED_MEMBERS_CACHELINE_MARKER(CACHE_LINE_SIZE, cacheline0,\n-    uint32_t recirc_id;         /* Recirculation id carried with the\n-                                   recirculating packets. 0 for packets\n-                                   received from the wire. */\n-    uint32_t dp_hash;           /* hash value computed by the recirculation\n-                                   action. */\n-    uint32_t skb_priority;      /* Packet priority for QoS. */\n-    uint32_t pkt_mark;          /* Packet mark. */\n-    uint8_t  ct_state;          /* Connection state. */\n-    bool ct_orig_tuple_ipv6;\n-    uint16_t ct_zone;           /* Connection zone. */\n-    uint32_t ct_mark;           /* Connection mark. */\n-    ovs_u128 ct_label;          /* Connection label. */\n-    union flow_in_port in_port; /* Input port. */\n-    odp_port_t orig_in_port;    /* Originating in_port for tunneled packets */\n-    struct conn *conn;          /* Cached conntrack connection. */\n-    bool reply;                 /* True if reply direction. */\n-    bool icmp_related;          /* True if ICMP related. */\n-);\n-\n-PADDED_MEMBERS_CACHELINE_MARKER(CACHE_LINE_SIZE, cacheline1,\n-    union {                     /* Populated only for non-zero 'ct_state'. */\n-        struct ovs_key_ct_tuple_ipv4 ipv4;\n-        struct ovs_key_ct_tuple_ipv6 ipv6;   /* Used only if                */\n-    } ct_orig_tuple;                         /* 'ct_orig_tuple_ipv6' is set */\n-);\n-\n-PADDED_MEMBERS_CACHELINE_MARKER(CACHE_LINE_SIZE, cacheline2,\n-    struct flow_tnl tunnel;     /* Encapsulating tunnel parameters. Note that\n-                                 * if 'ip_dst' == 0, the rest of the fields may\n-                                 * be uninitialized. */\n-);\n-};\n-\n-BUILD_ASSERT_DECL(offsetof(struct pkt_metadata, cacheline0) == 0);\n-BUILD_ASSERT_DECL(offsetof(struct pkt_metadata, cacheline1) ==\n-                  CACHE_LINE_SIZE);\n-BUILD_ASSERT_DECL(offsetof(struct pkt_metadata, cacheline2) ==\n-                  2 * CACHE_LINE_SIZE);\n-\n-static inline void\n-pkt_metadata_init_tnl(struct pkt_metadata *md)\n-{\n-    odp_port_t orig_in_port;\n-\n-    /* Zero up through the tunnel metadata options. The length and table\n-     * are before this and as long as they are empty, the options won't\n-     * be looked at. Keep the orig_in_port field. */\n-    orig_in_port = md->in_port.odp_port;\n-    memset(md, 0, offsetof(struct pkt_metadata, tunnel.metadata.opts));\n-    md->orig_in_port = orig_in_port;\n-}\n-\n-static inline void\n-pkt_metadata_init_conn(struct pkt_metadata *md)\n-{\n-    md->conn = NULL;\n-}\n-\n-static inline void\n-pkt_metadata_init(struct pkt_metadata *md, odp_port_t port)\n-{\n-    /* This is called for every packet in userspace datapath and affects\n-     * performance if all the metadata is initialized. Hence, fields should\n-     * only be zeroed out when necessary.\n-     *\n-     * Initialize only till ct_state. Once the ct_state is zeroed out rest\n-     * of ct fields will not be looked at unless ct_state != 0.\n-     */\n-    memset(md, 0, offsetof(struct pkt_metadata, ct_orig_tuple_ipv6));\n-\n-    /* It can be expensive to zero out all of the tunnel metadata. However,\n-     * we can just zero out ip_dst and the rest of the data will never be\n-     * looked at. */\n-    md->tunnel.ip_dst = 0;\n-    md->tunnel.ipv6_dst = in6addr_any;\n-    md->in_port.odp_port = port;\n-    md->orig_in_port = port;\n-    md->conn = NULL;\n-}\n-\n-/* This function prefetches the cachelines touched by pkt_metadata_init()\n- * and pkt_metadata_init_tnl().  For performance reasons the two functions\n- * should be kept in sync. */\n-static inline void\n-pkt_metadata_prefetch_init(struct pkt_metadata *md)\n-{\n-    /* Prefetch cacheline0 as members till ct_state and odp_port will\n-     * be initialized later in pkt_metadata_init(). */\n-    OVS_PREFETCH(md->cacheline0);\n-\n-    /* Prefetch cacheline1 as members of this cacheline will be zeroed out\n-     * in pkt_metadata_init_tnl(). */\n-    OVS_PREFETCH(md->cacheline1);\n-\n-    /* Prefetch cachline2 as ip_dst & ipv6_dst fields will be initialized. */\n-    OVS_PREFETCH(md->cacheline2);\n-}\n-\n-void compose_rarp(struct dp_packet *, const struct eth_addr);\n-\n-void eth_push_vlan(struct dp_packet *, ovs_be16 tpid, ovs_be16 tci);\n-void eth_pop_vlan(struct dp_packet *);\n-\n-const char *eth_from_hex(const char *hex, struct dp_packet **packetp);\n-\n-void set_mpls_lse(struct dp_packet *, ovs_be32 label);\n-void push_mpls(struct dp_packet *packet, ovs_be16 ethtype, ovs_be32 lse);\n-void pop_mpls(struct dp_packet *, ovs_be16 ethtype);\n-void add_mpls(struct dp_packet *packet, ovs_be16 ethtype, ovs_be32 lse,\n-              bool l3_encap);\n-\n-\n-void push_eth(struct dp_packet *packet, const struct eth_addr *dst,\n-              const struct eth_addr *src);\n-void pop_eth(struct dp_packet *packet);\n-\n-void push_nsh(struct dp_packet *packet, const struct nsh_hdr *nsh_hdr_src);\n-bool pop_nsh(struct dp_packet *packet);\n-\n-void *eth_compose(struct dp_packet *, const struct eth_addr eth_dst,\n-                  const struct eth_addr eth_src, uint16_t eth_type,\n-                  size_t size);\n-void *snap_compose(struct dp_packet *, const struct eth_addr eth_dst,\n-                   const struct eth_addr eth_src,\n-                   unsigned int oui, uint16_t snap_type, size_t size);\n-void packet_set_ipv4(struct dp_packet *, ovs_be32 src, ovs_be32 dst, uint8_t tos,\n-                     uint8_t ttl);\n-void packet_set_ipv4_addr(struct dp_packet *packet, ovs_16aligned_be32 *addr,\n-                          ovs_be32 new_addr);\n-void packet_set_ipv6(struct dp_packet *, const struct in6_addr *src,\n-                     const struct in6_addr *dst, uint8_t tc,\n-                     ovs_be32 fl, uint8_t hlmit);\n-void packet_set_ipv6_addr(struct dp_packet *packet, uint8_t proto,\n-                          ovs_16aligned_be32 addr[4],\n-                          const struct in6_addr *new_addr,\n-                          bool recalculate_csum);\n-void packet_set_tcp_port(struct dp_packet *, ovs_be16 src, ovs_be16 dst);\n-void packet_set_udp_port(struct dp_packet *, ovs_be16 src, ovs_be16 dst);\n-void packet_set_sctp_port(struct dp_packet *, ovs_be16 src, ovs_be16 dst);\n-void packet_set_icmp(struct dp_packet *, uint8_t type, uint8_t code);\n-void packet_set_icmp_id(struct dp_packet *, ovs_be16 icmp_id);\n-uint8_t packet_get_icmp_type(const struct dp_packet *packet);\n-uint8_t packet_get_ip_proto(const struct dp_packet *packet);\n-bool packet_is_icmpv4_info_message(const struct dp_packet *packet);\n-void packet_set_nd(struct dp_packet *, const struct in6_addr *target,\n-                   const struct eth_addr sll, const struct eth_addr tll);\n-void packet_set_nd_ext(struct dp_packet *packet,\n-                       const ovs_16aligned_be32 rso_flags,\n-                       const uint8_t opt_type);\n-void packet_set_igmp3_query(struct dp_packet *, uint8_t max_resp,\n-                            ovs_be32 group, bool srs, uint8_t qrv,\n-                            uint8_t qqic);\n-void *compose_ipv6(struct dp_packet *packet, uint8_t proto,\n-                   const struct in6_addr *src, const struct in6_addr *dst,\n-                   uint8_t key_tc, ovs_be32 key_fl, uint8_t key_hl, int size);\n-void compose_arp__(struct dp_packet *);\n-void compose_arp(struct dp_packet *, uint16_t arp_op,\n-                 const struct eth_addr arp_sha,\n-                 const struct eth_addr arp_tha, bool broadcast,\n-                 ovs_be32 arp_spa, ovs_be32 arp_tpa);\n-void compose_nd_ns(struct dp_packet *, const struct eth_addr eth_src,\n-                   const struct in6_addr *ipv6_src,\n-                   const struct in6_addr *ipv6_dst);\n-void compose_nd_na(struct dp_packet *, const struct eth_addr eth_src,\n-                   const struct eth_addr eth_dst,\n-                   const struct in6_addr *ipv6_src,\n-                   const struct in6_addr *ipv6_dst,\n-                   ovs_be32 rso_flags);\n-void compose_nd_ra(struct dp_packet *,\n-                   const struct eth_addr eth_src,\n-                   const struct eth_addr eth_dst,\n-                   const struct in6_addr *ipv6_src,\n-                   const struct in6_addr *ipv6_dst,\n-                   uint8_t cur_hop_limit, uint8_t mo_flags,\n-                   ovs_be16 router_lt, ovs_be32 reachable_time,\n-                   ovs_be32 retrans_timer, uint32_t mtu);\n-void packet_put_ra_prefix_opt(struct dp_packet *,\n-                              uint8_t plen, uint8_t la_flags,\n-                              ovs_be32 valid_lifetime,\n-                              ovs_be32 preferred_lifetime,\n-                              const ovs_be128 router_prefix);\n-bool packet_rh_present(struct dp_packet *packet, uint8_t *nexthdr,\n-                       bool *first_frag);\n-void IP_ECN_set_ce(struct dp_packet *pkt, bool is_ipv6);\n-void packet_tcp_complete_csum(struct dp_packet *, bool is_inner);\n-void packet_udp_complete_csum(struct dp_packet *, bool is_inner);\n-bool packet_udp_tunnel_csum(struct dp_packet *);\n-void packet_sctp_complete_csum(struct dp_packet *, bool is_inner);\n-\n-\n-#endif /* packets.h */\ndiff --git a/lib/pcap-file.c b/lib/pcap-file.c\nindex 8e4d6b3dd..ed7bede41 100644\n--- a/lib/pcap-file.c\n+++ b/lib/pcap-file.c\n@@ -26,7 +26,6 @@\n #include \"dp-packet.h\"\n #include \"flow.h\"\n #include \"openvswitch/hmap.h\"\n-#include \"packets.h\"\n #include \"timeval.h\"\n #include \"unaligned.h\"\n #include \"util.h\"\ndiff --git a/lib/route-table-bsd.c b/lib/route-table-bsd.c\nindex 34d42cfab..c551d0872 100644\n--- a/lib/route-table-bsd.c\n+++ b/lib/route-table-bsd.c\n@@ -31,8 +31,8 @@\n #include <string.h>\n #include <unistd.h>\n \n+#include \"net-proto.h\"\n #include \"ovs-router.h\"\n-#include \"packets.h\"\n #include \"openvswitch/vlog.h\"\n #include \"util.h\"\n \ndiff --git a/lib/route-table.c b/lib/route-table.c\nindex 2a13a5cc7..62884b843 100644\n--- a/lib/route-table.c\n+++ b/lib/route-table.c\n@@ -36,7 +36,6 @@\n #include \"openvswitch/list.h\"\n #include \"openvswitch/ofpbuf.h\"\n #include \"ovs-router.h\"\n-#include \"packets.h\"\n #include \"rtnetlink.h\"\n #include \"tnl-ports.h\"\n #include \"openvswitch/vlog.h\"\ndiff --git a/lib/rstp-common.h b/lib/rstp-common.h\nindex 7948842f4..382147e42 100644\n--- a/lib/rstp-common.h\n+++ b/lib/rstp-common.h\n@@ -36,7 +36,6 @@\n #include \"openvswitch/hmap.h\"\n #include \"openvswitch/list.h\"\n #include \"ovs-atomic.h\"\n-#include \"packets.h\"\n \n enum admin_port_state {\n     RSTP_ADMIN_BRIDGE_PORT_STATE_DISABLED = 0,\ndiff --git a/lib/rstp-state-machines.c b/lib/rstp-state-machines.c\nindex 7bd1f80c4..ce97de008 100644\n--- a/lib/rstp-state-machines.c\n+++ b/lib/rstp-state-machines.c\n@@ -40,7 +40,6 @@\n #include \"connectivity.h\"\n #include \"openvswitch/ofpbuf.h\"\n #include \"dp-packet.h\"\n-#include \"packets.h\"\n #include \"seq.h\"\n #include \"unixctl.h\"\n #include \"util.h\"\ndiff --git a/lib/rstp.c b/lib/rstp.c\nindex 90e809459..4dfeb5499 100644\n--- a/lib/rstp.c\n+++ b/lib/rstp.c\n@@ -42,7 +42,6 @@\n #include \"openvswitch/ofpbuf.h\"\n #include \"ofproto/ofproto.h\"\n #include \"dp-packet.h\"\n-#include \"packets.h\"\n #include \"seq.h\"\n #include \"unixctl.h\"\n #include \"util.h\"\ndiff --git a/lib/rtnetlink.c b/lib/rtnetlink.c\nindex 37078d00e..942aada80 100644\n--- a/lib/rtnetlink.c\n+++ b/lib/rtnetlink.c\n@@ -24,8 +24,8 @@\n \n #include \"netlink.h\"\n #include \"netlink-notifier.h\"\n+#include \"net-proto.h\"\n #include \"openvswitch/ofpbuf.h\"\n-#include \"packets.h\"\n \n #if IFLA_INFO_MAX < 5\n #define IFLA_INFO_SLAVE_KIND 4\ndiff --git a/lib/smap.c b/lib/smap.c\nindex 122adca27..5071625cd 100644\n--- a/lib/smap.c\n+++ b/lib/smap.c\n@@ -19,7 +19,7 @@\n \n #include \"hash.h\"\n #include \"openvswitch/json.h\"\n-#include \"packets.h\"\n+#include \"net-proto.h\"\n #include \"util.h\"\n #include \"uuid.h\"\n \ndiff --git a/lib/socket-util.c b/lib/socket-util.c\nindex c569b7d16..4fb161511 100644\n--- a/lib/socket-util.c\n+++ b/lib/socket-util.c\n@@ -36,8 +36,8 @@\n #include <sys/un.h>\n #include <unistd.h>\n #include \"openvswitch/dynamic-string.h\"\n+#include \"net-proto.h\"\n #include \"ovs-thread.h\"\n-#include \"packets.h\"\n #include \"openvswitch/poll-loop.h\"\n #include \"util.h\"\n #include \"openvswitch/vlog.h\"\ndiff --git a/lib/stp.c b/lib/stp.c\nindex f37337992..034004b43 100644\n--- a/lib/stp.c\n+++ b/lib/stp.c\n@@ -30,7 +30,6 @@\n #include \"openvswitch/ofpbuf.h\"\n #include \"ovs-atomic.h\"\n #include \"dp-packet.h\"\n-#include \"packets.h\"\n #include \"seq.h\"\n #include \"unixctl.h\"\n #include \"util.h\"\ndiff --git a/lib/stream-ssl.c b/lib/stream-ssl.c\nindex 9b468e0fa..b717ee0c5 100644\n--- a/lib/stream-ssl.c\n+++ b/lib/stream-ssl.c\n@@ -36,9 +36,9 @@\n #include \"coverage.h\"\n #include \"openvswitch/dynamic-string.h\"\n #include \"entropy.h\"\n+#include \"net-proto.h\"\n #include \"openvswitch/ofpbuf.h\"\n #include \"openflow/openflow.h\"\n-#include \"packets.h\"\n #include \"openvswitch/poll-loop.h\"\n #include \"openvswitch/shash.h\"\n #include \"socket-util.h\"\ndiff --git a/lib/stream-tcp.c b/lib/stream-tcp.c\nindex e8dc2bfaa..aa2096cb3 100644\n--- a/lib/stream-tcp.c\n+++ b/lib/stream-tcp.c\n@@ -26,7 +26,6 @@\n #include <sys/socket.h>\n #include <unistd.h>\n #include \"openvswitch/dynamic-string.h\"\n-#include \"packets.h\"\n #include \"socket-util.h\"\n #include \"util.h\"\n #include \"stream-provider.h\"\ndiff --git a/lib/stream-unix.c b/lib/stream-unix.c\nindex 0d9342bc6..ba312611c 100644\n--- a/lib/stream-unix.c\n+++ b/lib/stream-unix.c\n@@ -27,7 +27,6 @@\n #include <string.h>\n #include <unistd.h>\n #include \"ovs-atomic.h\"\n-#include \"packets.h\"\n #include \"openvswitch/poll-loop.h\"\n #include \"socket-util.h\"\n #include \"dirs.h\"\ndiff --git a/lib/stream.c b/lib/stream.c\nindex b3b21588a..efb317e53 100644\n--- a/lib/stream.c\n+++ b/lib/stream.c\n@@ -35,7 +35,6 @@\n #include \"openvswitch/vlog.h\"\n #include \"ovs-replay.h\"\n #include \"ovs-thread.h\"\n-#include \"packets.h\"\n #include \"openvswitch/poll-loop.h\"\n #include \"random.h\"\n #include \"socket-util.h\"\ndiff --git a/lib/tc.c b/lib/tc.c\nindex 4a9c6c267..16a982dc5 100644\n--- a/lib/tc.c\n+++ b/lib/tc.c\n@@ -43,7 +43,6 @@\n #include \"openvswitch/ofpbuf.h\"\n #include \"openvswitch/util.h\"\n #include \"openvswitch/vlog.h\"\n-#include \"packets.h\"\n #include \"timeval.h\"\n #include \"unaligned.h\"\n \ndiff --git a/lib/tnl-neigh-cache.c b/lib/tnl-neigh-cache.c\nindex fbefc3d51..19a4f90ee 100644\n--- a/lib/tnl-neigh-cache.c\n+++ b/lib/tnl-neigh-cache.c\n@@ -34,7 +34,6 @@\n #include \"netdev.h\"\n #include \"ovs-atomic.h\"\n #include \"ovs-thread.h\"\n-#include \"packets.h\"\n #include \"openvswitch/poll-loop.h\"\n #include \"seq.h\"\n #include \"socket-util.h\"\ndiff --git a/lib/tnl-neigh-cache.h b/lib/tnl-neigh-cache.h\nindex e16155b4d..dfa6e4b49 100644\n--- a/lib/tnl-neigh-cache.h\n+++ b/lib/tnl-neigh-cache.h\n@@ -28,7 +28,6 @@\n \n #include \"flow.h\"\n #include \"netdev.h\"\n-#include \"packets.h\"\n #include \"util.h\"\n \n int tnl_neigh_snoop(const struct flow *flow, struct flow_wildcards *wc,\ndiff --git a/lib/tnl-ports.h b/lib/tnl-ports.h\nindex 61ca0f8e2..f5da4c266 100644\n--- a/lib/tnl-ports.h\n+++ b/lib/tnl-ports.h\n@@ -21,7 +21,6 @@\n #include <sys/socket.h>\n \n #include \"flow.h\"\n-#include \"packets.h\"\n #include \"util.h\"\n \n odp_port_t tnl_port_map_lookup(struct flow *flow, struct flow_wildcards *wc);\ndiff --git a/lib/tun-metadata.c b/lib/tun-metadata.c\nindex af0bcbde8..a98bed5c5 100644\n--- a/lib/tun-metadata.c\n+++ b/lib/tun-metadata.c\n@@ -26,7 +26,6 @@\n #include \"odp-netlink.h\"\n #include \"openvswitch/ofp-match.h\"\n #include \"ovs-rcu.h\"\n-#include \"packets.h\"\n #include \"tun-metadata.h\"\n #include \"util.h\"\n \ndiff --git a/lib/vconn.c b/lib/vconn.c\nindex 040955d67..8051598fe 100644\n--- a/lib/vconn.c\n+++ b/lib/vconn.c\n@@ -36,7 +36,6 @@\n #include \"openvswitch/ofp-util.h\"\n #include \"openvswitch/ofpbuf.h\"\n #include \"openvswitch/vlog.h\"\n-#include \"packets.h\"\n #include \"openvswitch/poll-loop.h\"\n #include \"random.h\"\n #include \"util.h\"\ndiff --git a/ofproto/bond.c b/ofproto/bond.c\nindex ef481a360..a0130d7a4 100644\n--- a/ofproto/bond.c\n+++ b/ofproto/bond.c\n@@ -40,7 +40,6 @@\n #include \"openvswitch/ofp-actions.h\"\n #include \"openvswitch/ofpbuf.h\"\n #include \"openvswitch/vlog.h\"\n-#include \"packets.h\"\n #include \"openvswitch/poll-loop.h\"\n #include \"seq.h\"\n #include \"openvswitch/shash.h\"\ndiff --git a/ofproto/bond.h b/ofproto/bond.h\nindex 3aa5c640d..8c9623d4c 100644\n--- a/ofproto/bond.h\n+++ b/ofproto/bond.h\n@@ -20,7 +20,6 @@\n #include <stdbool.h>\n #include <stdint.h>\n #include \"ofproto-provider.h\"\n-#include \"packets.h\"\n \n struct flow;\n struct netdev;\ndiff --git a/ofproto/in-band.c b/ofproto/in-band.c\nindex 3992251f5..03e6c2e07 100644\n--- a/ofproto/in-band.c\n+++ b/ofproto/in-band.c\n@@ -37,7 +37,6 @@\n #include \"openvswitch/ofp-actions.h\"\n #include \"openvswitch/ofpbuf.h\"\n #include \"openvswitch/vlog.h\"\n-#include \"packets.h\"\n #include \"openvswitch/poll-loop.h\"\n #include \"timeval.h\"\n \ndiff --git a/ofproto/netflow.c b/ofproto/netflow.c\nindex aad9f9c77..17c9514c3 100644\n--- a/ofproto/netflow.c\n+++ b/ofproto/netflow.c\n@@ -30,7 +30,6 @@\n #include \"openvswitch/ofpbuf.h\"\n #include \"ofproto.h\"\n #include \"ofproto/netflow.h\"\n-#include \"packets.h\"\n #include \"openvswitch/poll-loop.h\"\n #include \"socket-util.h\"\n #include \"timeval.h\"\ndiff --git a/ofproto/ofproto-dpif-ipfix.c b/ofproto/ofproto-dpif-ipfix.c\nindex 1f561b3bc..7da664688 100644\n--- a/ofproto/ofproto-dpif-ipfix.c\n+++ b/ofproto/ofproto-dpif-ipfix.c\n@@ -29,7 +29,6 @@\n #include \"ofproto.h\"\n #include \"ofproto-dpif.h\"\n #include \"dp-packet.h\"\n-#include \"packets.h\"\n #include \"openvswitch/poll-loop.h\"\n #include \"sset.h\"\n #include \"util.h\"\ndiff --git a/ofproto/ofproto-dpif-monitor.h b/ofproto/ofproto-dpif-monitor.h\nindex 7d6d0da87..8763810db 100644\n--- a/ofproto/ofproto-dpif-monitor.h\n+++ b/ofproto/ofproto-dpif-monitor.h\n@@ -18,7 +18,6 @@\n #include <stdint.h>\n \n #include \"openflow/openflow.h\"\n-#include \"packets.h\"\n \n struct bfd;\n struct cfm;\ndiff --git a/ofproto/ofproto-dpif-sflow.c b/ofproto/ofproto-dpif-sflow.c\nindex e043d7cbc..7beee20c2 100644\n--- a/ofproto/ofproto-dpif-sflow.c\n+++ b/ofproto/ofproto-dpif-sflow.c\n@@ -31,7 +31,6 @@\n #include \"netlink.h\"\n #include \"openvswitch/ofpbuf.h\"\n #include \"ofproto.h\"\n-#include \"packets.h\"\n #include \"openvswitch/poll-loop.h\"\n #include \"ovs-router.h\"\n #include \"route-table.h\"\ndiff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c\nindex 8e4897202..6c00e4129 100644\n--- a/ofproto/ofproto-dpif-upcall.c\n+++ b/ofproto/ofproto-dpif-upcall.c\n@@ -38,7 +38,6 @@\n #include \"ofproto-dpif-xlate-cache.h\"\n #include \"ofproto-dpif-trace.h\"\n #include \"ovs-rcu.h\"\n-#include \"packets.h\"\n #include \"openvswitch/poll-loop.h\"\n #include \"seq.h\"\n #include \"tunnel.h\"\ndiff --git a/ofproto/ofproto-dpif-xlate-cache.c b/ofproto/ofproto-dpif-xlate-cache.c\nindex cb37e2462..b7da25e74 100644\n--- a/ofproto/ofproto-dpif-xlate-cache.c\n+++ b/ofproto/ofproto-dpif-xlate-cache.c\n@@ -42,7 +42,6 @@\n #include \"openvswitch/dynamic-string.h\"\n #include \"openvswitch/vlog.h\"\n #include \"ovs-router.h\"\n-#include \"packets.h\"\n #include \"tnl-neigh-cache.h\"\n #include \"util.h\"\n \ndiff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c\nindex 1ab6e47f2..b24c00c6e 100644\n--- a/ofproto/ofproto-dpif-xlate.c\n+++ b/ofproto/ofproto-dpif-xlate.c\n@@ -61,7 +61,6 @@\n #include \"openvswitch/vlog.h\"\n #include \"ovs-lldp.h\"\n #include \"ovs-router.h\"\n-#include \"packets.h\"\n #include \"tnl-neigh-cache.h\"\n #include \"tnl-ports.h\"\n #include \"tunnel.h\"\ndiff --git a/ofproto/ofproto.c b/ofproto/ofproto.c\nindex ec6d60a44..1c335808c 100644\n--- a/ofproto/ofproto.c\n+++ b/ofproto/ofproto.c\n@@ -53,7 +53,6 @@\n #include \"openvswitch/ofpbuf.h\"\n #include \"openvswitch/vlog.h\"\n #include \"ovs-rcu.h\"\n-#include \"packets.h\"\n #include \"pinsched.h\"\n #include \"openvswitch/poll-loop.h\"\n #include \"random.h\"\ndiff --git a/ofproto/tunnel.c b/ofproto/tunnel.c\nindex d8a289548..0e78a57fc 100644\n--- a/ofproto/tunnel.c\n+++ b/ofproto/tunnel.c\n@@ -26,7 +26,6 @@\n #include \"netdev.h\"\n #include \"odp-util.h\"\n #include \"openvswitch/ofpbuf.h\"\n-#include \"packets.h\"\n #include \"route-table.h\"\n #include \"seq.h\"\n #include \"smap.h\"\ndiff --git a/tests/test-classifier.c b/tests/test-classifier.c\nindex 6ac276d2e..7f66a6d9a 100644\n--- a/tests/test-classifier.c\n+++ b/tests/test-classifier.c\n@@ -35,13 +35,13 @@\n #include \"byte-order.h\"\n #include \"classifier-private.h\"\n #include \"command-line.h\"\n+#include \"openvswitch/dynamic-string.h\"\n #include \"fatal-signal.h\"\n #include \"flow.h\"\n #include \"openvswitch/vlog.h\"\n #include \"ovstest.h\"\n #include \"ovs-atomic.h\"\n #include \"ovs-thread.h\"\n-#include \"packets.h\"\n #include \"random.h\"\n #include \"timeval.h\"\n #include \"unaligned.h\"\ndiff --git a/tests/test-conntrack.c b/tests/test-conntrack.c\nindex ad7b36a98..20be2f095 100644\n--- a/tests/test-conntrack.c\n+++ b/tests/test-conntrack.c\n@@ -18,6 +18,7 @@\n #include \"conntrack.h\"\n \n #include \"dp-packet.h\"\n+#include \"openvswitch/dynamic-string.h\"\n #include \"fatal-signal.h\"\n #include \"flow.h\"\n #include \"netdev.h\"\ndiff --git a/tests/test-csum.c b/tests/test-csum.c\nindex 9f8511d81..974c0b33e 100644\n--- a/tests/test-csum.c\n+++ b/tests/test-csum.c\n@@ -26,8 +26,8 @@\n #include <stdlib.h>\n #include <string.h>\n #include \"crc32c.h\"\n+#include \"net-proto.h\"\n #include \"ovstest.h\"\n-#include \"packets.h\"\n #include \"random.h\"\n #include \"unaligned.h\"\n #include \"util.h\"\ndiff --git a/tests/test-lib-route-table.c b/tests/test-lib-route-table.c\nindex f99f056c8..df79c9df0 100644\n--- a/tests/test-lib-route-table.c\n+++ b/tests/test-lib-route-table.c\n@@ -18,13 +18,14 @@\n \n #undef NDEBUG\n \n+#include <inttypes.h>\n #include <linux/rtnetlink.h>\n #include <stdio.h>\n #include <stdlib.h>\n \n #include \"netlink-notifier.h\"\n+#include \"net-proto.h\"\n #include \"ovstest.h\"\n-#include \"packets.h\"\n #include \"route-table.h\"\n \n /* The following definition should be available in Linux 6.15 and might be\ndiff --git a/tests/test-netflow.c b/tests/test-netflow.c\nindex 7c23cff14..c03f3d06b 100644\n--- a/tests/test-netflow.c\n+++ b/tests/test-netflow.c\n@@ -25,9 +25,9 @@\n #include \"command-line.h\"\n #include \"daemon.h\"\n #include \"openvswitch/dynamic-string.h\"\n+#include \"net-proto.h\"\n #include \"openvswitch/ofpbuf.h\"\n #include \"ovstest.h\"\n-#include \"packets.h\"\n #include \"openvswitch/poll-loop.h\"\n #include \"socket-util.h\"\n #include \"unixctl.h\"\ndiff --git a/tests/test-netlink-conntrack.c b/tests/test-netlink-conntrack.c\nindex 2a62615b2..95bacf4a8 100644\n--- a/tests/test-netlink-conntrack.c\n+++ b/tests/test-netlink-conntrack.c\n@@ -19,7 +19,9 @@\n #include <stdlib.h>\n #include <linux/netfilter/nfnetlink.h>\n \n+#include \"net-proto.h\"\n #include \"ct-dpif.h\"\n+#include \"netlink.h\"\n #include \"netlink-conntrack.h\"\n #include \"netlink-notifier.h\"\n #include \"ovstest.h\"\ndiff --git a/tests/test-packets.c b/tests/test-packets.c\nindex 6151c633c..8b9f9f432 100644\n--- a/tests/test-packets.c\n+++ b/tests/test-packets.c\n@@ -16,11 +16,11 @@\n \n #include <config.h>\n #undef NDEBUG\n-#include \"packets.h\"\n #include <assert.h>\n #include <stdio.h>\n #include <stdlib.h>\n #include <string.h>\n+#include \"net-proto.h\"\n #include \"ovstest.h\"\n \n static void\ndiff --git a/tests/test-rstp.c b/tests/test-rstp.c\nindex 707ee3a6c..4a9f567fb 100644\n--- a/tests/test-rstp.c\n+++ b/tests/test-rstp.c\n@@ -10,7 +10,6 @@\n #include \"openvswitch/ofpbuf.h\"\n #include \"ovstest.h\"\n #include \"dp-packet.h\"\n-#include \"packets.h\"\n #include \"openvswitch/vlog.h\"\n \n #define MAX_PORTS 10\ndiff --git a/tests/test-sflow.c b/tests/test-sflow.c\nindex 3c617bdd1..03fac29f6 100644\n--- a/tests/test-sflow.c\n+++ b/tests/test-sflow.c\n@@ -30,9 +30,9 @@\n #include \"command-line.h\"\n #include \"daemon.h\"\n #include \"openvswitch/dynamic-string.h\"\n+#include \"net-proto.h\"\n #include \"openvswitch/ofpbuf.h\"\n #include \"ovstest.h\"\n-#include \"packets.h\"\n #include \"openvswitch/poll-loop.h\"\n #include \"socket-util.h\"\n #include \"unixctl.h\"\ndiff --git a/tests/test-stp.c b/tests/test-stp.c\nindex c85c99d67..7c2f03a46 100644\n--- a/tests/test-stp.c\n+++ b/tests/test-stp.c\n@@ -26,7 +26,6 @@\n #include \"dp-packet.h\"\n #include \"openvswitch/ofpbuf.h\"\n #include \"ovstest.h\"\n-#include \"packets.h\"\n #include \"openvswitch/vlog.h\"\n \n struct bpdu {\ndiff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c\nindex ba3458e55..8aa5f7141 100644\n--- a/utilities/ovs-ofctl.c\n+++ b/utilities/ovs-ofctl.c\n@@ -66,7 +66,6 @@\n #include \"openvswitch/shash.h\"\n #include \"openvswitch/vconn.h\"\n #include \"openvswitch/vlog.h\"\n-#include \"packets.h\"\n #include \"pcap-file.h\"\n #include \"openvswitch/poll-loop.h\"\n #include \"random.h\"\n@@ -74,6 +73,7 @@\n #include \"stream-ssl.h\"\n #include \"socket-util.h\"\n #include \"timeval.h\"\n+#include \"tun-metadata.h\"\n #include \"unixctl.h\"\n #include \"util.h\"\n \ndiff --git a/vswitchd/bridge.c b/vswitchd/bridge.c\nindex 7a68e19ac..d3c4bee24 100644\n--- a/vswitchd/bridge.c\n+++ b/vswitchd/bridge.c\n@@ -52,7 +52,6 @@\n #include \"openvswitch/vlog.h\"\n #include \"ovs-lldp.h\"\n #include \"ovs-numa.h\"\n-#include \"packets.h\"\n #include \"openvswitch/poll-loop.h\"\n #include \"seq.h\"\n #include \"sflow_api.h\"\n",
    "prefixes": [
        "ovs-dev",
        "v3",
        "5/6"
    ]
}