From patchwork Thu Apr 25 21:08:30 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pravin B Shelar X-Patchwork-Id: 239597 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id A1FC22C00F7 for ; Fri, 26 Apr 2013 07:08:46 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1759318Ab3DYVIg (ORCPT ); Thu, 25 Apr 2013 17:08:36 -0400 Received: from na3sys009aog121.obsmtp.com ([74.125.149.145]:35210 "HELO na3sys009aog121.obsmtp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with SMTP id S1756857Ab3DYVIe (ORCPT ); Thu, 25 Apr 2013 17:08:34 -0400 Received: from mail-da0-f72.google.com ([209.85.210.72]) (using TLSv1) by na3sys009aob121.postini.com ([74.125.148.12]) with SMTP ID DSNKUXmbUdmqpfkQ+SC2/3DQm5dvt1bhbYUR@postini.com; Thu, 25 Apr 2013 14:08:33 PDT Received: by mail-da0-f72.google.com with SMTP id x28so2830605dad.3 for ; Thu, 25 Apr 2013 14:08:33 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:x-received:from:to:cc:subject:date:message-id:x-mailer :x-gm-message-state; bh=zHa0QLkC5WqLwax/CvwPZBtWLnqJNZ99kRscxP+opO0=; b=b/+GaYyMCuvO4jqx9HCWrxGBPynO0jHc2BZa+N8EE7d7LT664JnwkMs/JGAqX1+uXX L1UHjwwCWYP4KxiTmp/etN2C4SwiCpnzuHrTdhSFS1tI77y0Xw9g6B66DImgh9dkx4k9 I6QZ3XjAlrUE/y7WYrH2jIMUGAgUHv6PTVAxTt8TD5/lTogeXgXAPS6lOV1TtXOxAd1O n2FPlOMf7B1afCvQfUAttsSNTjY3wY96N1aD0EKgHeD40R639rNOoi642jZvTilCcuQi sj90iYhDY+5xKO2M7gBfUx32J5YpSFI20HZXXUezf7ahdqo0CmILSgZJzJureqv3f5S9 q72w== X-Received: by 10.68.90.197 with SMTP id by5mr13573011pbb.196.1366924113366; Thu, 25 Apr 2013 14:08:33 -0700 (PDT) X-Received: by 10.68.90.197 with SMTP id by5mr13573001pbb.196.1366924113255; Thu, 25 Apr 2013 14:08:33 -0700 (PDT) Received: from localhost ([75.98.92.113]) by mx.google.com with ESMTPSA id t1sm9577774pab.12.2013.04.25.14.08.31 for (version=TLSv1.1 cipher=RC4-SHA bits=128/128); Thu, 25 Apr 2013 14:08:32 -0700 (PDT) From: Pravin B Shelar To: davem@davemloft.net, eric.dumazet@gmail.com Cc: netdev@vger.kernel.org, Pravin B Shelar Subject: [PATCH net-next v3] ipv6: Kill ipv6 dependency of icmpv6_send(). Date: Thu, 25 Apr 2013 14:08:30 -0700 Message-Id: <1366924110-3397-1-git-send-email-pshelar@nicira.com> X-Mailer: git-send-email 1.8.2.135.g7b592fa X-Gm-Message-State: ALoCoQmu8D3GMF9gJQVf3ozKla3TEzNIr32sEGxRvQjgBhsV0fc8jiRuEh56HSnvhKZoglqSZtVxqVJknFIPJwVCwAuL5aciLrBLyVooLB/wL4EKBADF0aQHSarhsSuF6Gf8oO9dGzpN3LmkO+i3AHoPg/N5LuLh8a5dHtjkTJSXg1yuWF7nrGE= Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Following patch adds icmp-registration module for ipv6. It allows ipv6 protocol to register icmp_sender which is used for sending ipv6 icmp msgs. This extra layer allows us to kill ipv6 dependency for sending icmp packets. This patch also fixes ip_tunnel compilation problem when ip_tunnel is statically compiled in kernel but ipv6 is module Signed-off-by: Pravin B Shelar Acked-by: Eric Dumazet --- v2-v3: - Fix sparse warning. v1-v2: - Used cmpxchg() to set icmp handler. --- include/linux/icmpv6.h | 18 +++++++++++++++--- net/ipv6/Makefile | 2 +- net/ipv6/icmp.c | 35 ++++++++++++++++++++--------------- net/ipv6/ip6_icmp.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 83 insertions(+), 19 deletions(-) create mode 100644 net/ipv6/ip6_icmp.c diff --git a/include/linux/icmpv6.h b/include/linux/icmpv6.h index b4f6c29..630f453 100644 --- a/include/linux/icmpv6.h +++ b/include/linux/icmpv6.h @@ -11,9 +11,21 @@ static inline struct icmp6hdr *icmp6_hdr(const struct sk_buff *skb) #include -extern void icmpv6_send(struct sk_buff *skb, - u8 type, u8 code, - __u32 info); +#if IS_ENABLED(CONFIG_IPV6) +extern void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info); + +typedef void ip6_icmp_send_t(struct sk_buff *skb, u8 type, u8 code, __u32 info); +extern int inet6_register_icmp_sender(ip6_icmp_send_t *fn); +extern int inet6_unregister_icmp_sender(ip6_icmp_send_t *fn); + +#else + +static inline void icmpv6_send(struct sk_buff *skb, + u8 type, u8 code, __u32 info) +{ + +} +#endif extern int icmpv6_init(void); extern int icmpv6_err_convert(u8 type, u8 code, diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile index 309af19..9af088d 100644 --- a/net/ipv6/Makefile +++ b/net/ipv6/Makefile @@ -40,7 +40,7 @@ obj-$(CONFIG_IPV6_SIT) += sit.o obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o obj-$(CONFIG_IPV6_GRE) += ip6_gre.o -obj-y += addrconf_core.o exthdrs_core.o ip6_checksum.o +obj-y += addrconf_core.o exthdrs_core.o ip6_checksum.o ip6_icmp.o obj-$(CONFIG_INET) += output_core.o protocol.o $(ipv6-offload) obj-$(subst m,y,$(CONFIG_IPV6)) += inet6_hashtables.o diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 71b900c..2a53a79 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -124,15 +124,6 @@ static __inline__ void icmpv6_xmit_unlock(struct sock *sk) } /* - * Slightly more convenient version of icmpv6_send. - */ -void icmpv6_param_prob(struct sk_buff *skb, u8 code, int pos) -{ - icmpv6_send(skb, ICMPV6_PARAMPROB, code, pos); - kfree_skb(skb); -} - -/* * Figure out, may we reply to this packet with icmp error. * * We do not reply, if: @@ -332,7 +323,7 @@ static struct dst_entry *icmpv6_route_lookup(struct net *net, struct sk_buff *sk * anycast. */ if (((struct rt6_info *)dst)->rt6i_flags & RTF_ANYCAST) { - LIMIT_NETDEBUG(KERN_DEBUG "icmpv6_send: acast source\n"); + LIMIT_NETDEBUG(KERN_DEBUG "icmp6_send: acast source\n"); dst_release(dst); return ERR_PTR(-EINVAL); } @@ -381,7 +372,7 @@ relookup_failed: /* * Send an ICMP message in response to a packet in error */ -void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) +static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) { struct net *net = dev_net(skb->dev); struct inet6_dev *idev = NULL; @@ -406,7 +397,7 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) /* * Make sure we respect the rules * i.e. RFC 1885 2.4(e) - * Rule (e.1) is enforced by not using icmpv6_send + * Rule (e.1) is enforced by not using icmp6_send * in any code that processes icmp errors. */ addr_type = ipv6_addr_type(&hdr->daddr); @@ -444,7 +435,7 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) * and anycast addresses will be checked later. */ if ((addr_type == IPV6_ADDR_ANY) || (addr_type & IPV6_ADDR_MULTICAST)) { - LIMIT_NETDEBUG(KERN_DEBUG "icmpv6_send: addr_any/mcast source\n"); + LIMIT_NETDEBUG(KERN_DEBUG "icmp6_send: addr_any/mcast source\n"); return; } @@ -452,7 +443,7 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) * Never answer to a ICMP packet. */ if (is_ineligible(skb)) { - LIMIT_NETDEBUG(KERN_DEBUG "icmpv6_send: no reply to icmp error\n"); + LIMIT_NETDEBUG(KERN_DEBUG "icmp6_send: no reply to icmp error\n"); return; } @@ -529,7 +520,14 @@ out_dst_release: out: icmpv6_xmit_unlock(sk); } -EXPORT_SYMBOL(icmpv6_send); + +/* Slightly more convenient version of icmp6_send. + */ +void icmpv6_param_prob(struct sk_buff *skb, u8 code, int pos) +{ + icmp6_send(skb, ICMPV6_PARAMPROB, code, pos); + kfree_skb(skb); +} static void icmpv6_echo_reply(struct sk_buff *skb) { @@ -885,8 +883,14 @@ int __init icmpv6_init(void) err = -EAGAIN; if (inet6_add_protocol(&icmpv6_protocol, IPPROTO_ICMPV6) < 0) goto fail; + + err = inet6_register_icmp_sender(icmp6_send); + if (err) + goto sender_reg_err; return 0; +sender_reg_err: + inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6); fail: pr_err("Failed to register ICMP6 protocol\n"); unregister_pernet_subsys(&icmpv6_sk_ops); @@ -895,6 +899,7 @@ fail: void icmpv6_cleanup(void) { + inet6_unregister_icmp_sender(icmp6_send); unregister_pernet_subsys(&icmpv6_sk_ops); inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6); } diff --git a/net/ipv6/ip6_icmp.c b/net/ipv6/ip6_icmp.c new file mode 100644 index 0000000..4578e23 --- /dev/null +++ b/net/ipv6/ip6_icmp.c @@ -0,0 +1,47 @@ +#include +#include +#include +#include +#include + +#include + +#if IS_ENABLED(CONFIG_IPV6) + +static ip6_icmp_send_t __rcu *ip6_icmp_send; + +int inet6_register_icmp_sender(ip6_icmp_send_t *fn) +{ + return (cmpxchg((ip6_icmp_send_t **)&ip6_icmp_send, NULL, fn) == NULL) ? + 0 : -EBUSY; +} +EXPORT_SYMBOL(inet6_register_icmp_sender); + +int inet6_unregister_icmp_sender(ip6_icmp_send_t *fn) +{ + int ret; + + ret = (cmpxchg((ip6_icmp_send_t **)&ip6_icmp_send, fn, NULL) == fn) ? + 0 : -EINVAL; + + synchronize_net(); + + return ret; +} +EXPORT_SYMBOL(inet6_unregister_icmp_sender); + +void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) +{ + ip6_icmp_send_t *send; + + rcu_read_lock(); + send = rcu_dereference(ip6_icmp_send); + + if (!send) + goto out; + send(skb, type, code, info); +out: + rcu_read_unlock(); +} +EXPORT_SYMBOL(icmpv6_send); +#endif