From patchwork Fri Oct 14 03:57:15 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zong Kai LI X-Patchwork-Id: 682106 X-Patchwork-Delegate: jpettit@nicira.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from archives.nicira.com (archives.nicira.com [96.126.127.54]) by ozlabs.org (Postfix) with ESMTP id 3swDMS162dz9s9N for ; Fri, 14 Oct 2016 14:57:39 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b=Yc5GmqKH; dkim-atps=neutral Received: from archives.nicira.com (localhost [127.0.0.1]) by archives.nicira.com (Postfix) with ESMTP id B2A4210655; Thu, 13 Oct 2016 20:57:37 -0700 (PDT) X-Original-To: dev@openvswitch.org Delivered-To: dev@openvswitch.org Received: from mx1e4.cudamail.com (mx1.cudamail.com [69.90.118.67]) by archives.nicira.com (Postfix) with ESMTPS id E399610653 for ; Thu, 13 Oct 2016 20:57:35 -0700 (PDT) Received: from bar5.cudamail.com (unknown [192.168.21.12]) by mx1e4.cudamail.com (Postfix) with ESMTPS id 299681E00E7 for ; Thu, 13 Oct 2016 21:57:35 -0600 (MDT) X-ASG-Debug-ID: 1476417454-09eadd4cbb10180001-byXFYA Received: from mx1-pf2.cudamail.com ([192.168.24.2]) by bar5.cudamail.com with ESMTP id 6A77RGFLjD9V5Oza (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Thu, 13 Oct 2016 21:57:34 -0600 (MDT) X-Barracuda-Envelope-From: zealokii@gmail.com X-Barracuda-RBL-Trusted-Forwarder: 192.168.24.2 Received: from unknown (HELO mail-pf0-f196.google.com) (209.85.192.196) by mx1-pf2.cudamail.com with ESMTPS (AES128-SHA encrypted); 14 Oct 2016 03:57:34 -0000 Received-SPF: pass (mx1-pf2.cudamail.com: SPF record at _netblocks.google.com designates 209.85.192.196 as permitted sender) X-Barracuda-Apparent-Source-IP: 209.85.192.196 X-Barracuda-RBL-IP: 209.85.192.196 Received: by mail-pf0-f196.google.com with SMTP id s8so6304197pfj.2 for ; Thu, 13 Oct 2016 20:57:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=2ulgVwp1dZ53va7yj3ivQjg8a7vwFnFNLOJ4sYDe15Y=; b=Yc5GmqKHtefhPfjGy3T8uLWiGN6rFQP167cq5PMgINIZMHtkV6J3Pc3wb2zTz6ecnK 9+dBAbN5kAyNaZU2dl9jdIgVHAHkOIEKRJJasR1ty7WMvLU8sbHMxJI14JqaDt0BaipI 7eEfJh6hIgRdgfSeKQ+5xMznyprAxARk1PaMIwL8+XUUoMdjZD149qL2EqlCesIFtJQM R2792PiBnNjmsWnJXc94CUZg5QME4Ur8JZJ2osO2IuOk/3Z2Qs+PVX1PIfYAkNK2QEYt KTDN2OO4HZzuK/E5Sk6Ngf0LeSwje2NzfLX38WCKOAblsJ6sWoi0r6NyHkaMSSQ2Cl/8 5CeA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=2ulgVwp1dZ53va7yj3ivQjg8a7vwFnFNLOJ4sYDe15Y=; b=dqrZedzXb/alK3JX2aDQklLxuGa5t2r5HUV2PTiNlvxrmyqsKzE9yWEDOpXICtuADH kzxjMRIxsMAjrn5lZ83mbrQ4C3oawJSAj5Pq1ACgcCuX1LSsW3PSx4uC06KKaaAykhrt KvuIwmUaCrPCZkc6X4p+0n2sL8OU35IBILeoZsIMsFTnjO5HMr2q8YIyx3/vtWVXwN+Y 6lBSkKJzS/An9Gw2SVmozeJw7L1KW+0911wnVgZIV7OKRmZYk3V2cRWfX/jZPO6MPM6T iWrc+hr2nxYTwAu/9ntSj1WNKk4kbP+LfFxO12YsY0yPxNEAriln/t5uklZoCOEq/+3w /SyQ== X-Gm-Message-State: AA6/9RmMTYHEtNRhU+4RqPD2BNeUCCYQ70AL2IqvxC3MYPnBoU4q1kaymWowHD3lji49UA== X-Received: by 10.99.100.132 with SMTP id y126mr12273645pgb.67.1476417453414; Thu, 13 Oct 2016 20:57:33 -0700 (PDT) Received: from OVN-dev-lzklibj1.ibm.biz ([2401:c900:1201:2a5::2]) by smtp.gmail.com with ESMTPSA id a9sm22897948pfa.38.2016.10.13.20.57.32 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 13 Oct 2016 20:57:32 -0700 (PDT) X-CudaMail-Envelope-Sender: zealokii@gmail.com From: Zongkai LI To: dev@openvswitch.org X-CudaMail-MID: CM-E2-1012097702 X-CudaMail-DTE: 101316 X-CudaMail-Originating-IP: 209.85.192.196 Date: Fri, 14 Oct 2016 03:57:15 +0000 X-ASG-Orig-Subj: [##CM-E2-1012097702##][ovs-dev] [PATCH v3 1/7] packets: add compose_nd_ra Message-Id: <1476417441-6239-2-git-send-email-zealokii@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1476417441-6239-1-git-send-email-zealokii@gmail.com> References: <1476417441-6239-1-git-send-email-zealokii@gmail.com> X-GBUdb-Analysis: 0, 209.85.192.196, Ugly c=0.36638 p=-0.2 Source Normal X-MessageSniffer-Rules: 0-0-0-19311-c X-Barracuda-Connect: UNKNOWN[192.168.24.2] X-Barracuda-Start-Time: 1476417454 X-Barracuda-Encrypted: DHE-RSA-AES256-SHA X-Barracuda-URL: https://web.cudamail.com:443/cgi-mod/mark.cgi X-Virus-Scanned: by bsmtpd at cudamail.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using global scores of TAG_LEVEL=3.5 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=4.0 tests=BSF_SC5_MJ1963, DKIM_SIGNED, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.33701 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Subject: [ovs-dev] [PATCH v3 1/7] packets: add compose_nd_ra X-BeenThere: dev@openvswitch.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dev-bounces@openvswitch.org Sender: "dev" This patch introduces methods to compose a Router Advertisement (RA) packet, introduces flags for RA. RA packet composed structures against specification in RFC4861. Caller can use compse_nd_ra_with_sll_mtu_opts to compose a RA packet with Source Link-layer Address Option and MTU Option. Caller can use packet_put_ra_prefix_opt to append a Prefix Information Option to a RA packet. Signed-off-by: Zongkai LI --- lib/packets.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/packets.h | 59 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 147 insertions(+) diff --git a/lib/packets.c b/lib/packets.c index 990c407..7557e76 100644 --- a/lib/packets.c +++ b/lib/packets.c @@ -35,6 +35,7 @@ const struct in6_addr in6addr_exact = IN6ADDR_EXACT_INIT; const struct in6_addr in6addr_all_hosts = IN6ADDR_ALL_HOSTS_INIT; +const struct in6_addr in6addr_all_routers = IN6ADDR_ALL_ROUTERS_INIT; struct in6_addr flow_tnl_dst(const struct flow_tnl *tnl) @@ -1439,6 +1440,93 @@ compose_nd_na(struct dp_packet *b, ND_MSG_LEN + ND_OPT_LEN)); } +/* Compose an IPv6 Neighbor Discovery Router Advertisement message with + * Source Link-layer Address Option and MTU Option. + * Caller can call packet_put_ra_prefix_opt to append Prefix Information + * Options to composed messags in 'b'. */ +void +compose_nd_ra_with_sll_mtu_opts(struct dp_packet *b, + const struct eth_addr eth_src, + const struct eth_addr eth_dst, + const struct in6_addr *ipv6_src, + const struct in6_addr *ipv6_dst, + uint8_t cur_hop_limit, uint8_t mo_flags, + ovs_be16 router_lt, ovs_be32 reachable_time, + ovs_be32 retrans_timer, ovs_be32 mtu) +{ + struct ovs_ra_msg *ra; + struct ovs_nd_mtu_opt *mtu_opt; + struct ovs_nd_opt *lla_opt; + uint32_t icmp_csum; + + /* Don't compose Router Advertisement packet with MTU Option if mtu + * value is 0. */ + bool with_mtu = mtu != 0; + size_t mtu_opt_len = with_mtu ? ND_MTU_OPT_LEN : 0; + + eth_compose(b, eth_dst, eth_src, ETH_TYPE_IPV6, IPV6_HEADER_LEN); + ra = compose_ipv6(b, IPPROTO_ICMPV6, ipv6_src, ipv6_dst, 0, 0, 255, + RA_MSG_LEN + ND_OPT_LEN + mtu_opt_len); + + ra->icmph.icmp6_type = ND_ROUTER_ADVERT; + ra->icmph.icmp6_code = 0; + ra->cur_hop_limit = cur_hop_limit; + ra->mo_flags = mo_flags; + ra->router_lifetime = router_lt; + ra->reachable_time = reachable_time; + ra->retrans_timer = retrans_timer; + + lla_opt = &ra->options[0]; + lla_opt->nd_opt_type = ND_OPT_SOURCE_LINKADDR; + lla_opt->nd_opt_len = 1; + lla_opt->nd_opt_mac = eth_src; + + if (with_mtu) { + /* ovs_nd_mtu_opt has the same size with ovs_nd_opt. */ + mtu_opt = (struct ovs_nd_mtu_opt *)(lla_opt + 1); + mtu_opt->type = ND_OPT_MTU; + mtu_opt->len = 1; + mtu_opt->reserved = 0; + mtu_opt->mtu = mtu; + } + + ra->icmph.icmp6_cksum = 0; + icmp_csum = packet_csum_pseudoheader6(dp_packet_l3(b)); + ra->icmph.icmp6_cksum = csum_finish(csum_continue( + icmp_csum, ra, RA_MSG_LEN + ND_OPT_LEN + mtu_opt_len)); +} + +/* Append an IPv6 Neighbor Discovery Prefix Information option to a + * Router Advertisement message. */ +void +packet_put_ra_prefix_opt(struct dp_packet *b, + uint8_t plen, uint8_t la_flags, ovs_be32 valid_lifetime, + ovs_be32 preferred_lifetime, const ovs_be128 prefix) +{ + size_t prev_l4_size = dp_packet_l4_size(b); + struct ip6_hdr *nh = dp_packet_l3(b); + nh->ip6_plen = htons(prev_l4_size + ND_PREFIX_OPT_LEN); + + struct ovs_ra_msg *ra = dp_packet_l4(b); + struct ovs_nd_prefix_opt *prefix_opt; + uint32_t icmp_csum; + + prefix_opt = dp_packet_put_uninit(b, sizeof(struct ovs_nd_prefix_opt)); + prefix_opt->type = ND_OPT_PREFIX_INFORMATION; + prefix_opt->len = 4; + prefix_opt->prefix_len = plen; + prefix_opt->la_flags = la_flags; + prefix_opt->valid_lifetime = valid_lifetime; + prefix_opt->preferred_lifetime = preferred_lifetime; + prefix_opt->reserved = 0; + memcpy(prefix_opt->prefix.be32, prefix.be32, sizeof(ovs_be32[4])); + + ra->icmph.icmp6_cksum = 0; + icmp_csum = packet_csum_pseudoheader6(dp_packet_l3(b)); + ra->icmph.icmp6_cksum = csum_finish(csum_continue( + icmp_csum, ra, prev_l4_size + ND_PREFIX_OPT_LEN)); +} + uint32_t packet_csum_pseudoheader(const struct ip_header *ip) { diff --git a/lib/packets.h b/lib/packets.h index 21bd35c..337ddf6 100644 --- a/lib/packets.h +++ b/lib/packets.h @@ -851,6 +851,33 @@ struct ovs_nd_opt { }; BUILD_ASSERT_DECL(ND_OPT_LEN == sizeof(struct ovs_nd_opt)); +/* Neighbor Discovery option: Prefix Information. */ +#define ND_PREFIX_OPT_LEN 32 +struct ovs_nd_prefix_opt { + uint8_t type; /* ND_OPT_PREFIX_INFORMATION */ + uint8_t len; /* The length of Prefix Information Option shoulud be 4. */ + uint8_t prefix_len; + uint8_t la_flags; /* ND_PREFIX_ON_LINK and ND_PREFIX_AUTONOMOUS_ADDRESS flags. */ + ovs_be32 valid_lifetime; + ovs_be32 preferred_lifetime; + ovs_be32 reserved; /* Always should be 0. */ + union ovs_16aligned_in6_addr prefix; +}; +BUILD_ASSERT_DECL(ND_PREFIX_OPT_LEN == sizeof(struct ovs_nd_prefix_opt)); + +#define ND_PREFIX_ON_LINK 0x80 +#define ND_PREFIX_AUTONOMOUS_ADDRESS 0x40 + +/* Neighbor Discovery option: MTU. */ +#define ND_MTU_OPT_LEN 8 +struct ovs_nd_mtu_opt { + uint8_t type; /* ND_OPT_MTU */ + uint8_t len; /* The length of MTU Option shoulud be 1. */ + ovs_be16 reserved; /* Always should be 0. */ + ovs_be32 mtu; +}; +BUILD_ASSERT_DECL(ND_MTU_OPT_LEN == sizeof(struct ovs_nd_mtu_opt)); + /* Like struct nd_msg (from ndisc.h), but whereas that struct requires 32-bit * alignment, this one only requires 16-bit alignment. */ #define ND_MSG_LEN 24 @@ -862,10 +889,26 @@ struct ovs_nd_msg { }; BUILD_ASSERT_DECL(ND_MSG_LEN == sizeof(struct ovs_nd_msg)); +/* Neighbor Discovery packet flags. */ #define ND_RSO_ROUTER 0x80000000 #define ND_RSO_SOLICITED 0x40000000 #define ND_RSO_OVERRIDE 0x20000000 +#define RA_MSG_LEN 16 +struct ovs_ra_msg { + struct icmp6_header icmph; + uint8_t cur_hop_limit; + uint8_t mo_flags; /* ND_RA_MANAGED_ADDRESS and ND_RA_OTHER_CONFIG flags. */ + ovs_be16 router_lifetime; + ovs_be32 reachable_time; + ovs_be32 retrans_timer; + struct ovs_nd_opt options[0]; +}; +BUILD_ASSERT_DECL(RA_MSG_LEN == sizeof(struct ovs_ra_msg)); + +#define ND_RA_MANAGED_ADDRESS 0x80 +#define ND_RA_OTHER_CONFIG 0x40 + /* * Use the same struct for MLD and MLD2, naming members as the defined fields in * in the corresponding version of the protocol, though they are reserved in the @@ -920,6 +963,10 @@ extern const struct in6_addr in6addr_all_hosts; #define IN6ADDR_ALL_HOSTS_INIT { { { 0xff,0x02,0x00,0x00,0x00,0x00,0x00,0x00, \ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 } } } +extern const struct in6_addr in6addr_all_routers; +#define IN6ADDR_ALL_ROUTERS_INIT { { { 0xff,0x02,0x00,0x00,0x00,0x00,0x00,0x00, \ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02 } } } + static inline bool ipv6_addr_equals(const struct in6_addr *a, const struct in6_addr *b) { @@ -1118,6 +1165,18 @@ void compose_nd_na(struct dp_packet *, const struct eth_addr eth_src, const struct in6_addr *ipv6_src, const struct in6_addr *ipv6_dst, ovs_be32 rso_flags); +void compose_nd_ra_with_sll_mtu_opts(struct dp_packet *, + const struct eth_addr eth_src, + const struct eth_addr eth_dst, + const struct in6_addr *ipv6_src, + const struct in6_addr *ipv6_dst, + uint8_t cur_hop_limit, uint8_t mo_flags, + ovs_be16 router_lt, ovs_be32 reachable_time, + ovs_be32 retrans_timer, ovs_be32 mtu); +void packet_put_ra_prefix_opt(struct dp_packet *, + uint8_t plen, uint8_t la_flags, + ovs_be32 valid_lifetime, ovs_be32 preferred_lifetime, + const ovs_be128 router_prefix); uint32_t packet_csum_pseudoheader(const struct ip_header *); void IP_ECN_set_ce(struct dp_packet *pkt, bool is_ipv6);