From patchwork Wed Jan 23 16:52:27 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Vishal Deep Ajmera X-Patchwork-Id: 1030071 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=ericsson.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ericsson.com header.i=@ericsson.com header.b="X7y6o9Uz"; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ericsson.com header.i=@ericsson.com header.b="gUloOYNZ"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 43lBJp1nMKz9s3q for ; Thu, 24 Jan 2019 03:56:42 +1100 (AEDT) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 344785C17; Wed, 23 Jan 2019 16:56:06 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id DE59B42C6 for ; Wed, 23 Jan 2019 16:52:37 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from sessmg22.ericsson.net (sessmg22.ericsson.net [193.180.251.58]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 0E6E1828 for ; Wed, 23 Jan 2019 16:52:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; d=ericsson.com; s=mailgw201801; c=relaxed/relaxed; q=dns/txt; i=@ericsson.com; t=1548262353; x=1550854353; h=From:Sender:Reply-To:Subject:Date:Message-ID:To:CC:MIME-Version:Content-Type: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=tnmoHSlQ5oGRAahLk0LMTXcCVmg1siLVhym2DHc+9rw=; b=X7y6o9Uzajm/zdLeLP5XY3WDnN6YlvwoPYuFmbbU2r4fKGSd8pHTqqXv9vkjxtH4 wJ8IrEyqri06y7bg1WSSAOyO/yvoBoxBxo2rM2L9o3Js6Om8Gt4E9b4OidP9eEU2 uYymLSYKEQKkZ6x8c2n2h6GZm+ntCsmQ5VEZ54JUSeQ=; X-AuditID: c1b4fb3a-5c9c29e00000672c-c4-5c489bd19c81 Received: from ESESSMB504.ericsson.se (Unknown_Domain [153.88.183.122]) by sessmg22.ericsson.net (Symantec Mail Security) with SMTP id 6F.61.26412.1DB984C5; Wed, 23 Jan 2019 17:52:33 +0100 (CET) Received: from ESESSMB504.ericsson.se (153.88.183.192) by ESESSMB504.ericsson.se (153.88.183.192) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1466.3; Wed, 23 Jan 2019 17:52:28 +0100 Received: from EUR03-DB5-obe.outbound.protection.outlook.com (153.88.183.157) by ESESSMB504.ericsson.se (153.88.183.165) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1466.3 via Frontend Transport; Wed, 23 Jan 2019 17:52:28 +0100 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ericsson.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=tnmoHSlQ5oGRAahLk0LMTXcCVmg1siLVhym2DHc+9rw=; b=gUloOYNZDEFV9JrxUE3mE3iXlt/tFYxPqYfIKpW4vXk2OHS/Wqf0hdDXG/08U6dFqC/psVw+9797u2J4BhNSP2Y98rlxFyXGuO1Qw9RUJztqSkNr7EfroMwiNlaUH/LUt8Yel/l2aWiEIakIGtsqrXKtZ4KpFXR3k4XsyY+2YA0= Received: from HE1PR0701MB2698.eurprd07.prod.outlook.com (10.168.188.17) by HE1PR0701MB2747.eurprd07.prod.outlook.com (10.168.188.141) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1580.5; Wed, 23 Jan 2019 16:52:27 +0000 Received: from HE1PR0701MB2698.eurprd07.prod.outlook.com ([fe80::4d74:46d7:e081:b4ed]) by HE1PR0701MB2698.eurprd07.prod.outlook.com ([fe80::4d74:46d7:e081:b4ed%9]) with mapi id 15.20.1558.016; Wed, 23 Jan 2019 16:52:27 +0000 From: Vishal Deep Ajmera To: "dev@openvswitch.org" Thread-Topic: [PATCH v3] Support for match & set ICMPv6 reserved and options type fields Thread-Index: AQHUszwFRWHPIk1IPkCxFes8Yy8nvQ== Date: Wed, 23 Jan 2019 16:52:27 +0000 Message-ID: <1548291226-4686-2-git-send-email-vishal.deep.ajmera@ericsson.com> References: <1548291226-4686-1-git-send-email-vishal.deep.ajmera@ericsson.com> In-Reply-To: <1548291226-4686-1-git-send-email-vishal.deep.ajmera@ericsson.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-clientproxiedby: BM1PR01CA0137.INDPRD01.PROD.OUTLOOK.COM (2603:1096:b00:40::31) To HE1PR0701MB2698.eurprd07.prod.outlook.com (2603:10a6:3:98::17) authentication-results: spf=none (sender IP is ) smtp.mailfrom=vishal.deep.ajmera@ericsson.com; x-ms-exchange-messagesentrepresentingtype: 1 x-mailer: git-send-email 1.9.1 x-originating-ip: [125.16.213.150] x-ms-publictraffictype: Email x-microsoft-exchange-diagnostics: 1; HE1PR0701MB2747; 6:eWhtxIQjXdnnLy6RJhX2u47j1iDh9EBMeqhSmkS0jTvozGECm7+lL1zFUxYm3YEqyv7i07R/5BaUPpOPmaVFO5A1QkYdiJnRE1T9fFQ4AJagCYGegWcXp0obfr95BOtKgT50hx2hgJhX6rczFY/5ApjGNXgPbDFQj3WNjTCUMyRrBwjUamm5BXO8D/psaVRhVErOObI48uhxFWDgR8yU2AhTCg4k6WOn0WXfz6cTuiE7+4B4CHLuLtPPBtvK82wIgVPoA0Hg+/u6pXCwczUI6usKufXEcEr9IKlWmKIXJGaRtlbgIUKrteFaKACpIPI49RMUz5LmBH+qMco3yegO/n9G/iR29YwoJiheonDcdrVjYVG2lZaavSO8gsrEPhmh6KV1Wq7Itc6qDEQBtqEkbBovHICCDnnqLuNGJ9uU1uEwiBRo/0rVmQXd0gYguIUE1+ttxyVgdATtXUbf1ZNnug==; 5:oXVF3DdaHtaCBhClIl0VeCKnYz+q4jtuQYkwGKQ91xm5UdcPP1SS1mcBabJdVVgp13/ji9iqp381zaYR3u7zQGuqBbCZJeYcjYZpFAiv+nKno1icBF5otkB5rR8qjAtos8Ztl11bQZZBc8n6VtfdK9LW2mx6Irc106nnIX37yj7z6G+cLABtwxLFbV7+7QcRbGOIESuRff8I6WIHhfEH+g==; 7:YB7JdXyLh6Pc7fj8qXtjVCRlmoU5P329o3szzgoRE4jYkXNUdflpzD1b+RmofWZwxOQ3etmOyCUSWbqKf+6koZ1lhmJ9I3uK1pnwDwLXzBTPzeNJt+XJtvOiHAoS+sdI+qxuqHNXBNWI++g1XtLo3w== x-ms-office365-filtering-correlation-id: b48dd4b3-9b1e-41b3-3d20-08d6815327a4 x-microsoft-antispam: BCL:0; PCL:0; RULEID:(2390118)(7020095)(4652040)(8989299)(5600110)(711020)(4605077)(4534185)(7168020)(4627221)(201703031133081)(201702281549075)(8990200)(2017052603328)(7153060)(7193020); SRVR:HE1PR0701MB2747; x-ms-traffictypediagnostic: HE1PR0701MB2747: x-microsoft-antispam-prvs: x-forefront-prvs: 0926B0E013 x-forefront-antispam-report: SFV:NSPM; SFS:(10009020)(346002)(376002)(366004)(136003)(396003)(39860400002)(199004)(189003)(316002)(7736002)(54906003)(36756003)(5640700003)(305945005)(6486002)(6436002)(6916009)(66066001)(14454004)(2501003)(68736007)(478600001)(476003)(6116002)(3846002)(86362001)(186003)(25786009)(11346002)(446003)(55236004)(26005)(102836004)(6506007)(386003)(2906002)(14444005)(71200400001)(4326008)(107886003)(71190400001)(50226002)(2616005)(8936002)(97736004)(1730700003)(81166006)(81156014)(52116002)(2351001)(76176011)(99286004)(106356001)(105586002)(8676002)(30864003)(53946003)(53936002)(6512007)(256004)(486006)(569006); DIR:OUT; SFP:1101; SCL:1; SRVR:HE1PR0701MB2747; H:HE1PR0701MB2698.eurprd07.prod.outlook.com; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; A:1; MX:1; received-spf: None (protection.outlook.com: ericsson.com does not designate permitted sender hosts) x-ms-exchange-senderadcheck: 1 x-microsoft-antispam-message-info: tZAfT1xwzFijoFl+37tnYNQq5v/S2+hT3GuSfzPFOg3LqdPnnAGICqjPB5KHqzIugLPP8EWQHGNn6B1+rKt5uflCRYS/LYvyEfC0XIvP42eTY+m/V3iM0cuHnqMqJgIfCsNZNPmnIZ9IEGWAkPNBgCmIUp4GpCUcitu3TBmxp23A8dlIw2X6+D73ltr5iAxCinDoECbICWzQnmW1uo4erwFDJcXpJgbtxM3FbosR8ea1tBxPINePRd0TIig6JtJ/yg6JmuWEwwNdHLWegTUCzJqcETtJen/Lyb2wtjI4h17NuZg0QjrzpROV3WT6hx5e9slHROCsM11KFvIvT4vGP+RsQAJ3WwVURj2BRTssXktziubSpN3S4JNS2I7C18NuOy1tg8cjkUyCFo6pNjENjAtrumcpJn4fvpYpFppIW60= spamdiagnosticoutput: 1:99 spamdiagnosticmetadata: NSPM Content-ID: <9F2C9E61C4ED994C9A825870B1C4CE74@eurprd07.prod.outlook.com> MIME-Version: 1.0 X-MS-Exchange-CrossTenant-Network-Message-Id: b48dd4b3-9b1e-41b3-3d20-08d6815327a4 X-MS-Exchange-CrossTenant-originalarrivaltime: 23 Jan 2019 16:52:25.8420 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-id: 92e84ceb-fbfd-47ab-be52-080c6b87953f X-MS-Exchange-Transport-CrossTenantHeadersStamped: HE1PR0701MB2747 X-OriginatorOrg: ericsson.com X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFmpjleLIzCtJLcpLzFFi42KZGbG9SvfibI8Yg6m/JSyOnt7D7MDo8ezm f8YAxigum5TUnMyy1CJ9uwSujN67r9gK2rqZK9ZumMvUwPilgbmLkZNDQsBEovHXeiCbi0NI 4AijxMfdj5kgnG+MEi3zbrODVAkJLGGS2DqLESTBIjCBWeLJhefMEInpTBJftztDdDxjlLjT +Risg03ASuLXlH4WEFtEQF/iUM9ZMJtZoESi+dgnoBUcHMICoRJ3/2tDlERJnHp9gQnC1pNo XDqXEaSERUBV4tdFLZAwr4CfxPVnL8E6hYDsF216IGFOAX+JfZ1PWUFsRgExie+n1jBBLBKX uPVkPhPEkwISS/ach3pYVOLl43+sIBdLCExnlLix/SwjRHOSxJstfxghinQkzl5/AmXLSSxe fZkNwlaSuLhmMTuELStxaX43I8SgFnaJNe3tUNt8JX5u+g+VeMIo0faqGW7q8Qlboex8iX/N 3xknMBrPQnLtLKDnmAU0Jdbv0ocIe0g0HTrJCmErSkzpfsg+CxwWghInZz5hWcDIuopRtDi1 uDg33chIL7UoM7m4OD9PLy+1ZBMjMHUc3PLbagfjweeOhxgFOBiVeHhrJnjECLEmlhVX5h5i lOBgVhLhdb3oFiPEm5JYWZValB9fVJqTWnyIUZqDRUmc94+QYIyQQHpiSWp2ampBahFMlomD U6qBUelp/f/LtjuC2gIPxm9xPfBQ7PSPgqSwVX2vw1YyrhbziDA3VuGsmy/3+D1vg910/UkT DPgrd1RrXew/9vjE3jwhDQsunk8f6l0WRmhl/Fh5NGnuvPm//L7xOqUvfZ/SYaCkMjHyAWtt r+v+O4oq260m/tpiJRbl8Mm0ddtcu8T9Uzb+n9cnpMRSnJFoqMVcVJwIAM1ZNRAZAwAA X-Spam-Status: No, score=-4.3 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Cc: Ashvin Lakshmikantha Subject: [ovs-dev] [PATCH v3] Support for match & set ICMPv6 reserved and options type fields X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org Currently OVS supports all ARP protocol fields as OXM match fields to implement the relevant ARP procedures for IPv4. This includes support for matching copying and setting ARP fields. In IPv6 ARP has been replaced by ICMPv6 neighbor discovery (ND) procedures, neighbor advertisement and neighbor solicitation. The support for ICMPv6 fields in OVS is not complete for the use cases equivalent to ARP in IPv4. OVS lacks support for matching, copying and setting the “ND option type” and “ND reserved” fields. Without these user cannot implement all ICMPv6 ND procedures for IPv6 support. This commit adds additional OXM fields to OVS for ICMPv6 “ND option type“ and ICMPv6 “ND reserved” using the OXM extension mechanism. This allows support for parsing these fields from an ICMPv6 packet header and extending the OpenFlow protocol with specifications for these new OXM fields for matching, copying and setting. Signed-off-by: Vishal Deep Ajmera Co-authored-by: Ashvin Lakshmikantha Signed-off-by: Ashvin Lakshmikantha --- NEWS | 2 + build-aux/extract-ofp-fields | 1 + datapath/linux/compat/include/linux/openvswitch.h | 8 ++ include/openvswitch/flow.h | 6 +- include/openvswitch/match.h | 3 + include/openvswitch/meta-flow.h | 28 +++++ lib/flow.c | 58 +++++++++-- lib/match.c | 21 ++++ lib/meta-flow.c | 38 +++++++ lib/meta-flow.xml | 12 +++ lib/nx-match.c | 8 ++ lib/odp-execute.c | 32 ++++++ lib/odp-util.c | 120 +++++++++++++++++++++- lib/packets.c | 33 ++++++ lib/packets.h | 3 + ofproto/ofproto-dpif-sflow.c | 1 + tests/ofproto.at | 4 +- 17 files changed, 364 insertions(+), 14 deletions(-) diff --git a/NEWS b/NEWS index 358c9b9..6ffac90 100644 --- a/NEWS +++ b/NEWS @@ -13,6 +13,8 @@ Post-v2.10.0 * Add option for simple round-robin based Rxq to PMD assignment. It can be set with pmd-rxq-assign. * Add support for DPDK 18.11 + * ICMPv6 ND enhancements: support for match and set ND options type + and reserved fields. - Add 'symmetric_l3' hash function. - OVS now honors 'updelay' and 'downdelay' for bonds with LACP configured. - ovs-vswitchd: diff --git a/build-aux/extract-ofp-fields b/build-aux/extract-ofp-fields index 3592594..e159a1d 100755 --- a/build-aux/extract-ofp-fields +++ b/build-aux/extract-ofp-fields @@ -71,6 +71,7 @@ OXM_CLASSES = {"NXM_OF_": (0, 0x0000, 'extension'), "OXM_OF_": (0, 0x8000, 'standard'), "OXM_OF_PKT_REG": (0, 0x8001, 'standard'), "ONFOXM_ET_": (0x4f4e4600, 0xffff, 'standard'), + "ERICOXM_OF_": (0, 0x1000, 'extension'), # This is the experimenter OXM class for Nicira, which is the # one that OVS would be using instead of NXM_OF_ and NXM_NX_ diff --git a/datapath/linux/compat/include/linux/openvswitch.h b/datapath/linux/compat/include/linux/openvswitch.h index 9b087f1..d5aa09d 100644 --- a/datapath/linux/compat/include/linux/openvswitch.h +++ b/datapath/linux/compat/include/linux/openvswitch.h @@ -375,6 +375,7 @@ enum ovs_key_attr { #ifndef __KERNEL__ /* Only used within userspace data path. */ OVS_KEY_ATTR_PACKET_TYPE, /* be32 packet type */ + OVS_KEY_ATTR_ND_EXTENSIONS, /* struct ovs_key_nd_extensions */ #endif __OVS_KEY_ATTR_MAX @@ -489,6 +490,13 @@ struct ovs_key_nd { __u8 nd_tll[ETH_ALEN]; }; +#ifndef __KERNEL__ +struct ovs_key_nd_extensions { + __be32 nd_reserved; + __u8 nd_options_type; +}; +#endif + #define OVS_CT_LABELS_LEN_32 4 #define OVS_CT_LABELS_LEN (OVS_CT_LABELS_LEN_32 * sizeof(__u32)) struct ovs_key_ct_labels { diff --git a/include/openvswitch/flow.h b/include/openvswitch/flow.h index 5d2cf09..57b6c92 100644 --- a/include/openvswitch/flow.h +++ b/include/openvswitch/flow.h @@ -144,7 +144,8 @@ struct flow { struct in6_addr nd_target; /* IPv6 neighbor discovery (ND) target. */ struct eth_addr arp_sha; /* ARP/ND source hardware address. */ struct eth_addr arp_tha; /* ARP/ND target hardware address. */ - ovs_be16 tcp_flags; /* TCP flags. With L3 to avoid matching L4. */ + ovs_be16 tcp_flags; /* TCP flags/ICMPv6 ND options type. + * With L3 to avoid matching L4. */ ovs_be16 pad2; /* Pad to 64 bits. */ struct ovs_key_nsh nsh; /* Network Service Header keys */ @@ -153,7 +154,8 @@ struct flow { ovs_be16 tp_dst; /* TCP/UDP/SCTP destination port/ICMP code. */ ovs_be16 ct_tp_src; /* CT original tuple source port/ICMP type. */ ovs_be16 ct_tp_dst; /* CT original tuple dst port/ICMP code. */ - ovs_be32 igmp_group_ip4; /* IGMP group IPv4 address. + ovs_be32 igmp_group_ip4; /* IGMP group IPv4 address/ICMPv6 ND reserved + * field. * Keep last for BUILD_ASSERT_DECL below. */ ovs_be32 pad3; /* Pad to 64 bits. */ }; diff --git a/include/openvswitch/match.h b/include/openvswitch/match.h index e8c80dd..05ecee7 100644 --- a/include/openvswitch/match.h +++ b/include/openvswitch/match.h @@ -219,6 +219,9 @@ void match_set_nd_target(struct match *, const struct in6_addr *); void match_set_nd_target_masked(struct match *, const struct in6_addr *, const struct in6_addr *); +void match_set_nd_reserved(struct match *, ovs_be32); +void match_set_nd_options_type(struct match *, uint8_t); + bool match_equal(const struct match *, const struct match *); uint32_t match_hash(const struct match *, uint32_t basis); diff --git a/include/openvswitch/meta-flow.h b/include/openvswitch/meta-flow.h index ffd8945..65d99f4 100644 --- a/include/openvswitch/meta-flow.h +++ b/include/openvswitch/meta-flow.h @@ -1796,6 +1796,34 @@ enum OVS_PACKED_ENUM mf_field_id { */ MFF_ND_TLL, + /* "nd_reserved". + * + * The reserved field in IPv6 Neighbor Discovery message. + * + * Type: be32. + * Maskable: no. + * Formatting: decimal. + * Prerequisites: ND. + * Access: read/write. + * NXM: none. + * OXM: ERICOXM_OF_ICMPV6_ND_RESERVED(1) since v2.11. + */ + MFF_ND_RESERVED, + + /* "nd_options_type". + * + * The type of the option in IPv6 Neighbor Discovery message. + * + * Type: u8. + * Maskable: no. + * Formatting: decimal. + * Prerequisites: ND. + * Access: read/write. + * NXM: none. + * OXM: ERICOXM_OF_ICMPV6_ND_OPTIONS_TYPE(2) since v2.11. + */ + MFF_ND_OPTIONS_TYPE, + /* ## ---- ## */ /* ## NSH ## */ /* ## ---- ## */ diff --git a/lib/flow.c b/lib/flow.c index c60446f..a83a840 100644 --- a/lib/flow.c +++ b/lib/flow.c @@ -396,13 +396,14 @@ parse_ethertype(const void **datap, size_t *sizep) } /* Returns 'true' if the packet is an ND packet. In that case the '*nd_target' - * and 'arp_buf[]' are filled in. If the packet is not an ND pacet, 'false' is - * returned and no values are filled in on '*nd_target' or 'arp_buf[]'. */ + * and 'arp_buf[]' are filled in. If the packet is not an ND packet, 'false' + * is returned and no values are filled in on '*nd_target' or 'arp_buf[]'. */ static inline bool parse_icmpv6(const void **datap, size_t *sizep, const struct icmp6_hdr *icmp, - const struct in6_addr **nd_target, - struct eth_addr arp_buf[2]) + uint32_t *rso_flags, const struct in6_addr **nd_target, + struct eth_addr arp_buf[2], uint8_t *opt_type) { + const uint32_t *reserved; if (icmp->icmp6_code != 0 || (icmp->icmp6_type != ND_NEIGHBOR_SOLICIT && icmp->icmp6_type != ND_NEIGHBOR_ADVERT)) { @@ -411,6 +412,15 @@ parse_icmpv6(const void **datap, size_t *sizep, const struct icmp6_hdr *icmp, arp_buf[0] = eth_addr_zero; arp_buf[1] = eth_addr_zero; + *opt_type = 0; + + reserved = data_try_pull(datap, sizep, sizeof(uint32_t)); + if (OVS_UNLIKELY(!reserved)) { + /* Invalid ND packet. */ + return false; + } + *rso_flags = *reserved; + *nd_target = data_try_pull(datap, sizep, sizeof **nd_target); if (OVS_UNLIKELY(!*nd_target)) { return true; @@ -432,12 +442,20 @@ parse_icmpv6(const void **datap, size_t *sizep, const struct icmp6_hdr *icmp, if (lla_opt->type == ND_OPT_SOURCE_LINKADDR && opt_len == 8) { if (OVS_LIKELY(eth_addr_is_zero(arp_buf[0]))) { arp_buf[0] = lla_opt->mac; + /* We use only first option type present in ND packet. */ + if (*opt_type == 0) { + *opt_type = lla_opt->type; + } } else { goto invalid; } } else if (lla_opt->type == ND_OPT_TARGET_LINKADDR && opt_len == 8) { if (OVS_LIKELY(eth_addr_is_zero(arp_buf[1]))) { arp_buf[1] = lla_opt->mac; + /* We use only first option type present in ND packet. */ + if (*opt_type == 0) { + *opt_type = lla_opt->type; + } } else { goto invalid; } @@ -987,18 +1005,38 @@ miniflow_extract(struct dp_packet *packet, struct miniflow *dst) if (OVS_LIKELY(size >= sizeof(struct icmp6_hdr))) { const struct in6_addr *nd_target; struct eth_addr arp_buf[2]; - const struct icmp6_hdr *icmp = data_pull(&data, &size, - sizeof *icmp); - if (parse_icmpv6(&data, &size, icmp, &nd_target, arp_buf)) { + /* This will populate whether we received Option 1 + * or Option 2. */ + uint8_t opt_type; + /* This holds the ND Reserved field. */ + uint32_t rso_flags; + const struct icmp6_hdr *icmp = data_pull(&data, + &size,ICMP6_HEADER_LEN); + if (parse_icmpv6(&data, &size, icmp, + &rso_flags, &nd_target, arp_buf, &opt_type)) { if (nd_target) { miniflow_push_words(mf, nd_target, nd_target, sizeof *nd_target / sizeof(uint64_t)); } miniflow_push_macs(mf, arp_sha, arp_buf); - miniflow_pad_to_64(mf, arp_tha); + /* Populate options field and set the padding + * accordingly. */ + if (opt_type != 0) { + miniflow_push_be16(mf, tcp_flags, htons(opt_type)); + /* Pad to align with 64 bits. + * This will zero out the pad3 field. */ + miniflow_pad_to_64(mf, tcp_flags); + } else { + /* Pad to align with 64 bits. + * This will zero out the tcp_flags & pad3 field. */ + miniflow_pad_to_64(mf, arp_tha); + } miniflow_push_be16(mf, tp_src, htons(icmp->icmp6_type)); miniflow_push_be16(mf, tp_dst, htons(icmp->icmp6_code)); miniflow_pad_to_64(mf, tp_dst); + /* Fill ND reserved field. */ + miniflow_push_be32(mf, igmp_group_ip4, htonl(rso_flags)); + miniflow_pad_to_64(mf, igmp_group_ip4); } else { /* ICMPv6 but not ND. */ miniflow_push_be16(mf, tp_src, htons(icmp->icmp6_type)); @@ -1927,6 +1965,8 @@ flow_wc_map(const struct flow *flow, struct flowmap *map) FLOWMAP_SET(map, nd_target); FLOWMAP_SET(map, arp_sha); FLOWMAP_SET(map, arp_tha); + FLOWMAP_SET(map, tcp_flags); + FLOWMAP_SET(map, igmp_group_ip4); } else { FLOWMAP_SET(map, ct_nw_proto); FLOWMAP_SET(map, ct_ipv6_src); @@ -2968,6 +3008,8 @@ flow_compose_l4(struct dp_packet *p, const struct flow *flow, struct icmp6_hdr *icmp = dp_packet_put_zeros(p, sizeof *icmp); icmp->icmp6_type = ntohs(flow->tp_src); icmp->icmp6_code = ntohs(flow->tp_dst); + uint32_t *reserved = &icmp->icmp6_dataun.icmp6_un_data32[0]; + *reserved = ntohl(flow->igmp_group_ip4); if (icmp->icmp6_code == 0 && (icmp->icmp6_type == ND_NEIGHBOR_SOLICIT || diff --git a/lib/match.c b/lib/match.c index a1407a8..052daee 100644 --- a/lib/match.c +++ b/lib/match.c @@ -1080,6 +1080,19 @@ match_set_nd_target_masked(struct match *match, match->wc.masks.nd_target = *mask; } +void +match_set_nd_reserved (struct match *match, ovs_be32 value) +{ + match->flow.igmp_group_ip4 = value; + match->wc.masks.igmp_group_ip4 = OVS_BE32_MAX; +} + +void +match_set_nd_options_type(struct match *match, uint8_t option) +{ + match_set_tcp_flags(match, htons(option)); +} + /* Returns true if 'a' and 'b' wildcard the same fields and have the same * values for fixed fields, otherwise false. */ bool @@ -1688,6 +1701,14 @@ match_format(const struct match *match, &wc->masks.nd_target); format_eth_masked(s, "nd_sll", f->arp_sha, wc->masks.arp_sha); format_eth_masked(s, "nd_tll", f->arp_tha, wc->masks.arp_tha); + if (wc->masks.igmp_group_ip4) { + format_be32_masked(s,"nd_reserved", f->igmp_group_ip4, + wc->masks.igmp_group_ip4); + } + if (wc->masks.tcp_flags) { + format_be16_masked(s,"nd_options_type", f->tcp_flags, + wc->masks.tcp_flags); + } } else { format_be16_masked(s, "tp_src", f->tp_src, wc->masks.tp_src); format_be16_masked(s, "tp_dst", f->tp_dst, wc->masks.tp_dst); diff --git a/lib/meta-flow.c b/lib/meta-flow.c index b6d9e92..1f5c011 100644 --- a/lib/meta-flow.c +++ b/lib/meta-flow.c @@ -344,6 +344,11 @@ mf_is_all_wild(const struct mf_field *mf, const struct flow_wildcards *wc) case MFF_ND_TARGET: return ipv6_mask_is_any(&wc->masks.nd_target); + case MFF_ND_RESERVED: + return !wc->masks.igmp_group_ip4; + case MFF_ND_OPTIONS_TYPE: + return !wc->masks.tcp_flags; + case MFF_IP_FRAG: return !(wc->masks.nw_frag & FLOW_NW_FRAG_MASK); @@ -571,6 +576,8 @@ mf_is_value_valid(const struct mf_field *mf, const union mf_value *value) case MFF_ND_TARGET: case MFF_ND_SLL: case MFF_ND_TLL: + case MFF_ND_RESERVED: + case MFF_ND_OPTIONS_TYPE: return true; case MFF_IN_PORT_OXM: @@ -909,9 +916,14 @@ mf_get_value(const struct mf_field *mf, const struct flow *flow, break; case MFF_TCP_FLAGS: + case MFF_ND_OPTIONS_TYPE: value->be16 = flow->tcp_flags; break; + case MFF_ND_RESERVED: + value->be32 = flow->igmp_group_ip4; + break; + case MFF_ICMPV4_TYPE: case MFF_ICMPV6_TYPE: value->u8 = ntohs(flow->tp_src); @@ -1259,6 +1271,14 @@ mf_set_value(const struct mf_field *mf, match_set_nd_target(match, &value->ipv6); break; + case MFF_ND_RESERVED: + match_set_nd_reserved(match, value->be32); + break; + + case MFF_ND_OPTIONS_TYPE: + match_set_nd_options_type(match, value->u8); + break; + case MFF_NSH_FLAGS: MATCH_SET_FIELD_UINT8(match, nsh.flags, value->u8); break; @@ -1668,6 +1688,14 @@ mf_set_flow_value(const struct mf_field *mf, flow->nd_target = value->ipv6; break; + case MFF_ND_RESERVED: + flow->igmp_group_ip4 = value->be32; + break; + + case MFF_ND_OPTIONS_TYPE: + flow->tcp_flags = htons(value->u8); + break; + case MFF_NSH_FLAGS: flow->nsh.flags = value->u8; break; @@ -1823,6 +1851,8 @@ mf_is_pipeline_field(const struct mf_field *mf) case MFF_ND_TARGET: case MFF_ND_SLL: case MFF_ND_TLL: + case MFF_ND_RESERVED: + case MFF_ND_OPTIONS_TYPE: case MFF_NSH_FLAGS: case MFF_NSH_TTL: case MFF_NSH_MDTYPE: @@ -2150,6 +2180,11 @@ mf_set_wild(const struct mf_field *mf, struct match *match, char **err_str) match->wc.masks.arp_tha = eth_addr_zero; break; + case MFF_ND_RESERVED: + match->wc.masks.igmp_group_ip4 = htonl(0); + match->flow.igmp_group_ip4 = htonl(0); + break; + case MFF_TCP_SRC: case MFF_UDP_SRC: case MFF_SCTP_SRC: @@ -2169,6 +2204,7 @@ mf_set_wild(const struct mf_field *mf, struct match *match, char **err_str) break; case MFF_TCP_FLAGS: + case MFF_ND_OPTIONS_TYPE: match->wc.masks.tcp_flags = htons(0); match->flow.tcp_flags = htons(0); break; @@ -2285,6 +2321,8 @@ mf_set(const struct mf_field *mf, case MFF_ICMPV4_CODE: case MFF_ICMPV6_TYPE: case MFF_ICMPV6_CODE: + case MFF_ND_RESERVED: + case MFF_ND_OPTIONS_TYPE: return OFPUTIL_P_NONE; case MFF_DP_HASH: diff --git a/lib/meta-flow.xml b/lib/meta-flow.xml index 0b5c1d0..31db761 100644 --- a/lib/meta-flow.xml +++ b/lib/meta-flow.xml @@ -4586,6 +4586,18 @@ r r c c c. title="ICMPv6 Neighbor Discovery Source Ethernet Address"/> + +

+ This is used to set the R,S,O bits in Neighbor Advertisement Messages +

+ +

+ A value of 1 indicates that the option is Source Link Layer. + A value of 2 indicates that the options is Target Link Layer. + See RFC 4861 for further details. +

References

diff --git a/lib/nx-match.c b/lib/nx-match.c index 8f98032..17caff0 100644 --- a/lib/nx-match.c +++ b/lib/nx-match.c @@ -990,8 +990,16 @@ nxm_put_ip(struct nxm_put_ctx *ctx, ntohs(flow->tp_dst)); } if (is_nd(flow, NULL)) { + if (match->wc.masks.igmp_group_ip4) { + nxm_put_32(ctx, MFF_ND_RESERVED, oxm, + flow->igmp_group_ip4); + } nxm_put_ipv6(ctx, MFF_ND_TARGET, oxm, &flow->nd_target, &match->wc.masks.nd_target); + if (match->wc.masks.tcp_flags) { + nxm_put_8(ctx, MFF_ND_OPTIONS_TYPE, oxm, + ntohs(flow->tcp_flags)); + } if (flow->tp_src == htons(ND_NEIGHBOR_SOLICIT)) { nxm_put_eth_masked(ctx, MFF_ND_SLL, oxm, flow->arp_sha, match->wc.masks.arp_sha); diff --git a/lib/odp-execute.c b/lib/odp-execute.c index 3b6890e..5d07133 100644 --- a/lib/odp-execute.c +++ b/lib/odp-execute.c @@ -228,6 +228,23 @@ set_arp(struct dp_packet *packet, const struct ovs_key_arp *key, } static void +odp_set_nd_ext(struct dp_packet *packet, const struct ovs_key_nd_extensions + *key, const struct ovs_key_nd_extensions *mask) +{ + const struct ovs_nd_msg *ns = dp_packet_l4(packet); + ovs_16aligned_be32 reserved = ns->rso_flags; + uint8_t opt_type = ns->options[0].type; + + if (mask->nd_reserved) { + put_16aligned_be32(&reserved, key->nd_reserved); + } + if (mask->nd_options_type) { + opt_type = key->nd_options_type; + } + packet_set_nd_ext(packet, reserved, opt_type); +} + +static void odp_set_nd(struct dp_packet *packet, const struct ovs_key_nd *key, const struct ovs_key_nd *mask) { @@ -438,6 +455,16 @@ odp_execute_set_action(struct dp_packet *packet, const struct nlattr *a) } break; + case OVS_KEY_ATTR_ND_EXTENSIONS: + if (OVS_LIKELY(dp_packet_get_nd_payload(packet))) { + const struct ovs_key_nd_extensions *nd_ext_key + = nl_attr_get_unspec(a, sizeof(struct ovs_key_nd_extensions)); + ovs_16aligned_be32 rso_flags; + put_16aligned_be32(&rso_flags, nd_ext_key->nd_reserved); + packet_set_nd_ext(packet, rso_flags, nd_ext_key->nd_options_type); + } + break; + case OVS_KEY_ATTR_DP_HASH: md->dp_hash = nl_attr_get_u32(a); break; @@ -540,6 +567,11 @@ odp_execute_masked_set_action(struct dp_packet *packet, get_mask(a, struct ovs_key_nd)); break; + case OVS_KEY_ATTR_ND_EXTENSIONS: + odp_set_nd_ext(packet, nl_attr_get(a), + get_mask(a, struct ovs_key_nd_extensions)); + break; + case OVS_KEY_ATTR_DP_HASH: md->dp_hash = nl_attr_get_u32(a) | (md->dp_hash & ~*get_mask(a, uint32_t)); diff --git a/lib/odp-util.c b/lib/odp-util.c index 1e8c5f1..2d7c856 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -173,6 +173,7 @@ ovs_key_attr_to_string(enum ovs_key_attr attr, char *namebuf, size_t bufsize) case OVS_KEY_ATTR_ICMPV6: return "icmpv6"; case OVS_KEY_ATTR_ARP: return "arp"; case OVS_KEY_ATTR_ND: return "nd"; + case OVS_KEY_ATTR_ND_EXTENSIONS: return "nd_ext"; case OVS_KEY_ATTR_MPLS: return "mpls"; case OVS_KEY_ATTR_DP_HASH: return "dp_hash"; case OVS_KEY_ATTR_RECIRC_ID: return "recirc_id"; @@ -2500,6 +2501,7 @@ const struct attr_len_tbl ovs_flow_key_attr_lens[OVS_KEY_ATTR_MAX + 1] = { [OVS_KEY_ATTR_ICMPV6] = { .len = sizeof(struct ovs_key_icmpv6) }, [OVS_KEY_ATTR_ARP] = { .len = sizeof(struct ovs_key_arp) }, [OVS_KEY_ATTR_ND] = { .len = sizeof(struct ovs_key_nd) }, + [OVS_KEY_ATTR_ND_EXTENSIONS] = { .len = sizeof(struct ovs_key_nd_extensions) }, [OVS_KEY_ATTR_CT_STATE] = { .len = 4 }, [OVS_KEY_ATTR_CT_ZONE] = { .len = 2 }, [OVS_KEY_ATTR_CT_MARK] = { .len = 4 }, @@ -2950,6 +2952,7 @@ odp_mask_is_constant__(enum ovs_key_attr attr, const void *mask, size_t size, case OVS_KEY_ATTR_ICMP: case OVS_KEY_ATTR_ICMPV6: case OVS_KEY_ATTR_ND: + case OVS_KEY_ATTR_ND_EXTENSIONS: case OVS_KEY_ATTR_SKB_MARK: case OVS_KEY_ATTR_TUNNEL: case OVS_KEY_ATTR_SCTP: @@ -4044,6 +4047,21 @@ format_odp_key_attr__(const struct nlattr *a, const struct nlattr *ma, ds_chomp(ds, ','); break; } + case OVS_KEY_ATTR_ND_EXTENSIONS: { + const struct ovs_key_nd_extensions *mask = ma ? nl_attr_get(ma) : NULL; + const struct ovs_key_nd_extensions *key = nl_attr_get(a); + + bool first = true; + format_be32_masked(ds, &first, "nd_reserved", key->nd_reserved, + OVS_BE32_MAX); + ds_put_char(ds, ','); + + format_u8u(ds, "nd_options_type", key->nd_options_type, + MASK(mask, nd_options_type), verbose); + + ds_chomp(ds, ','); + break; + } case OVS_KEY_ATTR_NSH: { format_odp_nsh_attr(a, ma, ds); break; @@ -5550,6 +5568,11 @@ parse_odp_key_mask_attr(struct parse_odp_context *context, const char *s, SCAN_FIELD("tll=", eth, nd_tll); } SCAN_END(OVS_KEY_ATTR_ND); + SCAN_BEGIN("nd_ext(", struct ovs_key_nd_extensions) { + SCAN_FIELD("reserved=", be32, nd_reserved); + SCAN_FIELD("nd_options_type=", u8, nd_options_type); + } SCAN_END(OVS_KEY_ATTR_ND_EXTENSIONS); + struct packet_type { ovs_be16 ns; ovs_be16 id; @@ -5927,14 +5950,25 @@ odp_flow_key_from_flow__(const struct odp_flow_key_parms *parms, * xlate_wc_finish() for details. */ && (!export_mask || (data->tp_src == htons(0xff) && data->tp_dst == htons(0xff)))) { - struct ovs_key_nd *nd_key; - + struct ovs_key_nd_extensions *nd_ext_key; nd_key = nl_msg_put_unspec_uninit(buf, OVS_KEY_ATTR_ND, sizeof *nd_key); nd_key->nd_target = data->nd_target; nd_key->nd_sll = data->arp_sha; nd_key->nd_tll = data->arp_tha; + + /* Add ND Extensions Attr only if reserved field + * or options type is set. */ + if (data->igmp_group_ip4 != 0 || + data->tcp_flags != 0) { + nd_ext_key = + nl_msg_put_unspec_uninit(buf, + OVS_KEY_ATTR_ND_EXTENSIONS, + sizeof *nd_ext_key); + nd_ext_key->nd_reserved = data->igmp_group_ip4; + nd_ext_key->nd_options_type = ntohs(data->tcp_flags); + } } } } @@ -6118,6 +6152,7 @@ odp_key_to_dp_packet(const struct nlattr *key, size_t key_len, case OVS_KEY_ATTR_ICMPV6: case OVS_KEY_ATTR_ARP: case OVS_KEY_ATTR_ND: + case OVS_KEY_ATTR_ND_EXTENSIONS: case OVS_KEY_ATTR_SCTP: case OVS_KEY_ATTR_TCP_FLAGS: case OVS_KEY_ATTR_MPLS: @@ -6557,6 +6592,35 @@ parse_l2_5_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1], } } } + if (present_attrs & + (UINT64_C(1) << OVS_KEY_ATTR_ND_EXTENSIONS)) { + const struct ovs_key_nd_extensions *nd_ext_key; + if (!is_mask) { + expected_attrs |= + UINT64_C(1) << OVS_KEY_ATTR_ND_EXTENSIONS; + } + + nd_ext_key = + nl_attr_get(attrs[OVS_KEY_ATTR_ND_EXTENSIONS]); + flow->igmp_group_ip4 = nd_ext_key->nd_reserved; + flow->tcp_flags = htons(nd_ext_key->nd_options_type); + + if (is_mask) { + /* Even though 'tp_src' and 'tp_dst' are 16 bits wide, + * ICMP type and code are 8 bits wide. Therefore, an + * exact match looks like htons(0xff), not + * htons(0xffff). See xlate_wc_finish() for details. + * */ + if (!is_all_zeros(nd_ext_key, sizeof *nd_ext_key) && + (flow->tp_src != htons(0xff) || + flow->tp_dst != htons(0xff))) { + return ODP_FIT_ERROR; + } else { + expected_attrs |= + UINT64_C(1) << OVS_KEY_ATTR_ND_EXTENSIONS; + } + } + } } } } else if (src_flow->nw_proto == IPPROTO_IGMP @@ -7453,6 +7517,24 @@ put_nd_key(const struct ovs_key_nd *nd, struct flow *flow) flow->arp_tha = nd->nd_tll; } +static void +get_nd_extensions_key(const struct flow *flow, + struct ovs_key_nd_extensions *nd_ext) +{ + /* ND Extensions key has padding, clear it. */ + memset(nd_ext, 0, sizeof *nd_ext); + nd_ext->nd_reserved = flow->igmp_group_ip4; + nd_ext->nd_options_type = ntohs(flow->tcp_flags); +} + +static void +put_nd_extensions_key(const struct ovs_key_nd_extensions *nd_ext, + struct flow *flow) +{ + flow->igmp_group_ip4 = nd_ext->nd_reserved; + flow->tcp_flags = htons(nd_ext->nd_options_type); +} + static enum slow_path_reason commit_set_nd_action(const struct flow *flow, struct flow *base_flow, struct ofpbuf *odp_actions, @@ -7475,10 +7557,33 @@ commit_set_nd_action(const struct flow *flow, struct flow *base_flow, } static enum slow_path_reason +commit_set_nd_extensions_action(const struct flow *flow, + struct flow *base_flow, + struct ofpbuf *odp_actions, + struct flow_wildcards *wc, bool use_masked) +{ + struct ovs_key_nd_extensions key, mask, base; + + get_nd_extensions_key(flow, &key); + get_nd_extensions_key(base_flow, &base); + get_nd_extensions_key(&wc->masks, &mask); + + if (commit(OVS_KEY_ATTR_ND_EXTENSIONS, use_masked, &key, + &base, &mask, sizeof key, odp_actions)) { + put_nd_extensions_key(&base, base_flow); + put_nd_extensions_key(&mask, &wc->masks); + return SLOW_ACTION; + } + return 0; +} + +static enum slow_path_reason commit_set_nw_action(const struct flow *flow, struct flow *base, struct ofpbuf *odp_actions, struct flow_wildcards *wc, bool use_masked) { + uint32_t reason; + /* Check if 'flow' really has an L3 header. */ if (!flow->nw_proto) { return 0; @@ -7491,7 +7596,16 @@ commit_set_nw_action(const struct flow *flow, struct flow *base, case ETH_TYPE_IPV6: commit_set_ipv6_action(flow, base, odp_actions, wc, use_masked); - return commit_set_nd_action(flow, base, odp_actions, wc, use_masked); + if (base->nw_proto == IPPROTO_ICMPV6) { + /* Commit extended attrs first to make sure + correct options are added.*/ + reason = commit_set_nd_extensions_action(flow, base, + odp_actions, wc, use_masked); + reason |= commit_set_nd_action(flow, base, odp_actions, + wc, use_masked); + return reason; + } + break; case ETH_TYPE_ARP: return commit_set_arp_action(flow, base, odp_actions, wc); diff --git a/lib/packets.c b/lib/packets.c index 2d6f77b..f5a2005 100644 --- a/lib/packets.c +++ b/lib/packets.c @@ -1282,6 +1282,39 @@ packet_set_icmp(struct dp_packet *packet, uint8_t type, uint8_t code) } void +packet_set_nd_ext(struct dp_packet *packet, const ovs_16aligned_be32 rso_flags, + const uint8_t opt_type) +{ + struct ovs_nd_msg *ns; + struct ovs_nd_lla_opt *opt; + int bytes_remain = dp_packet_l4_size(packet); + struct ovs_16aligned_ip6_hdr * nh = dp_packet_l3(packet); + uint32_t pseudo_hdr_csum = 0; + + if (OVS_UNLIKELY(bytes_remain < sizeof(*ns))) { + return; + } + + if (nh) { + pseudo_hdr_csum = packet_csum_pseudoheader6(nh); + } + + ns = dp_packet_l4(packet); + opt = &ns->options[0]; + + /* set RSO flags and option type */ + ns->rso_flags = rso_flags; + opt->type = opt_type; + + /* recalculate checksum */ + ovs_be16 *csum_value = &(ns->icmph.icmp6_cksum); + *csum_value = 0; + *csum_value = csum_finish(csum_continue(pseudo_hdr_csum, + &(ns->icmph), bytes_remain)); + +} + +void packet_set_nd(struct dp_packet *packet, const struct in6_addr *target, const struct eth_addr sll, const struct eth_addr tll) { diff --git a/lib/packets.h b/lib/packets.h index 09a0ac3..fcd90b3 100644 --- a/lib/packets.h +++ b/lib/packets.h @@ -1543,6 +1543,9 @@ void packet_set_sctp_port(struct dp_packet *, ovs_be16 src, ovs_be16 dst); void packet_set_icmp(struct dp_packet *, uint8_t type, uint8_t code); void packet_set_nd(struct dp_packet *, const struct in6_addr *target, const struct eth_addr sll, const struct eth_addr tll); +void packet_set_nd_ext(struct dp_packet *packet, + const ovs_16aligned_be32 rso_flags, + const uint8_t opt_type); void packet_format_tcp_flags(struct ds *, uint16_t); const char *packet_tcp_flag_to_string(uint32_t flag); diff --git a/ofproto/ofproto-dpif-sflow.c b/ofproto/ofproto-dpif-sflow.c index 7da3175..bc4ffee 100644 --- a/ofproto/ofproto-dpif-sflow.c +++ b/ofproto/ofproto-dpif-sflow.c @@ -1055,6 +1055,7 @@ sflow_read_set_action(const struct nlattr *attr, case OVS_KEY_ATTR_ICMPV6: case OVS_KEY_ATTR_ARP: case OVS_KEY_ATTR_ND: + case OVS_KEY_ATTR_ND_EXTENSIONS: case OVS_KEY_ATTR_CT_STATE: case OVS_KEY_ATTR_CT_ZONE: case OVS_KEY_ATTR_CT_MARK: diff --git a/tests/ofproto.at b/tests/ofproto.at index 6a2cf27..a426e47 100644 --- a/tests/ofproto.at +++ b/tests/ofproto.at @@ -2445,7 +2445,7 @@ head_table () { actions: output group set_field strip_vlan push_vlan mod_nw_ttl dec_ttl set_mpls_ttl dec_mpls_ttl push_mpls pop_mpls set_queue supported on Set-Field: tun_id tun_src tun_dst tun_ipv6_src tun_ipv6_dst tun_flags tun_gbp_id tun_gbp_flags tun_erspan_idx tun_erspan_ver tun_erspan_dir tun_erspan_hwid tun_metadata0 dnl tun_metadata1 tun_metadata2 tun_metadata3 tun_metadata4 tun_metadata5 tun_metadata6 tun_metadata7 tun_metadata8 tun_metadata9 tun_metadata10 tun_metadata11 tun_metadata12 tun_metadata13 tun_metadata14 tun_metadata15 tun_metadata16 tun_metadata17 tun_metadata18 tun_metadata19 tun_metadata20 tun_metadata21 tun_metadata22 tun_metadata23 tun_metadata24 tun_metadata25 tun_metadata26 tun_metadata27 tun_metadata28 tun_metadata29 tun_metadata30 tun_metadata31 tun_metadata32 tun_metadata33 tun_metadata34 tun_metadata35 tun_metadata36 tun_metadata37 tun_metadata38 tun_metadata39 tun_metadata40 tun_metadata41 tun_metadata42 tun_metadata43 tun_metadata44 tun_metadata45 tun_metadata46 tun_metadata47 tun_metadata48 tun_metadata49 tun_metadata50 tun_metadata51 tun_metadata52 tun_metadata53 tun_metadata54 tun_metadata55 tun_metadata56 tun_metadata57 tun_metadata58 tun_metadata59 tun_metadata60 tun_metadata61 tun_metadata62 tun_metadata63 dnl -metadata in_port in_port_oxm pkt_mark ct_mark ct_label reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 reg10 reg11 reg12 reg13 reg14 reg15 xreg0 xreg1 xreg2 xreg3 xreg4 xreg5 xreg6 xreg7 xxreg0 xxreg1 xxreg2 xxreg3 eth_src eth_dst vlan_tci vlan_vid vlan_pcp mpls_label mpls_tc mpls_ttl ip_src ip_dst ipv6_src ipv6_dst ipv6_label nw_tos ip_dscp nw_ecn nw_ttl arp_op arp_spa arp_tpa arp_sha arp_tha tcp_src tcp_dst udp_src udp_dst sctp_src sctp_dst icmp_type icmp_code icmpv6_type icmpv6_code nd_target nd_sll nd_tll nsh_flags nsh_spi nsh_si nsh_c1 nsh_c2 nsh_c3 nsh_c4 nsh_ttl +metadata in_port in_port_oxm pkt_mark ct_mark ct_label reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 reg10 reg11 reg12 reg13 reg14 reg15 xreg0 xreg1 xreg2 xreg3 xreg4 xreg5 xreg6 xreg7 xxreg0 xxreg1 xxreg2 xxreg3 eth_src eth_dst vlan_tci vlan_vid vlan_pcp mpls_label mpls_tc mpls_ttl ip_src ip_dst ipv6_src ipv6_dst ipv6_label nw_tos ip_dscp nw_ecn nw_ttl arp_op arp_spa arp_tpa arp_sha arp_tha tcp_src tcp_dst udp_src udp_dst sctp_src sctp_dst icmp_type icmp_code icmpv6_type icmpv6_code nd_target nd_sll nd_tll nd_reserved nd_options_type nsh_flags nsh_spi nsh_si nsh_c1 nsh_c2 nsh_c3 nsh_c4 nsh_ttl matching: dp_hash: arbitrary mask recirc_id: exact match or wildcard @@ -2611,6 +2611,8 @@ metadata in_port in_port_oxm pkt_mark ct_mark ct_label reg0 reg1 reg2 reg3 reg4 nd_target: arbitrary mask nd_sll: arbitrary mask nd_tll: arbitrary mask + nd_reserved: exact match or wildcard + nd_options_type: exact match or wildcard nsh_flags: arbitrary mask nsh_mdtype: exact match or wildcard nsh_np: exact match or wildcard