}
 EXPORT_SYMBOL(icmp_global_allow);
 
+static bool icmpv4_mask_allow(struct net *net, int type, int code)
+{
+       if (type > NR_ICMP_TYPES)
+               return true;
+
+       /* Don't limit PMTU discovery. */
+       if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED)
+               return true;
+
+       /* Limit if icmp type is enabled in ratemask. */
+       if (!((1 << type) & net->ipv4.sysctl_icmp_ratemask))
+               return true;
+
+       return false;
+}
+
+static bool icmpv4_global_allow(struct net *net, int type, int code)
+{
+       if (icmpv4_mask_allow(net, type, code))
+               return true;
+
+       if (icmp_global_allow())
+               return true;
+
+       return false;
+}
+
 /*
  *     Send an ICMP frame.
  */
                               struct flowi4 *fl4, int type, int code)
 {
        struct dst_entry *dst = &rt->dst;
+       struct inet_peer *peer;
        bool rc = true;
+       int vif;
 
-       if (type > NR_ICMP_TYPES)
-               goto out;
-
-       /* Don't limit PMTU discovery. */
-       if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED)
+       if (icmpv4_mask_allow(net, type, code))
                goto out;
 
        /* No rate limit on loopback */
        if (dst->dev && (dst->dev->flags&IFF_LOOPBACK))
                goto out;
 
-       /* Limit if icmp type is enabled in ratemask. */
-       if (!((1 << type) & net->ipv4.sysctl_icmp_ratemask))
-               goto out;
-
-       rc = false;
-       if (icmp_global_allow()) {
-               int vif = l3mdev_master_ifindex(dst->dev);
-               struct inet_peer *peer;
-
-               peer = inet_getpeer_v4(net->ipv4.peers, fl4->daddr, vif, 1);
-               rc = inet_peer_xrlim_allow(peer,
-                                          net->ipv4.sysctl_icmp_ratelimit);
-               if (peer)
-                       inet_putpeer(peer);
-       }
+       vif = l3mdev_master_ifindex(dst->dev);
+       peer = inet_getpeer_v4(net->ipv4.peers, fl4->daddr, vif, 1);
+       rc = inet_peer_xrlim_allow(peer, net->ipv4.sysctl_icmp_ratelimit);
+       if (peer)
+               inet_putpeer(peer);
 out:
        return rc;
 }
        struct inet_sock *inet;
        __be32 daddr, saddr;
        u32 mark = IP4_REPLY_MARK(net, skb->mark);
+       int type = icmp_param->data.icmph.type;
+       int code = icmp_param->data.icmph.code;
 
        if (ip_options_echo(&icmp_param->replyopts.opt.opt, skb))
                return;
                return;
        inet = inet_sk(sk);
 
+       /* global icmp_msgs_per_sec */
+       if (!icmpv4_global_allow(net, type, code))
+               goto out_unlock;
+
        icmp_param->data.icmph.checksum = 0;
 
        inet->tos = ip_hdr(skb)->tos;
        rt = ip_route_output_key(net, &fl4);
        if (IS_ERR(rt))
                goto out_unlock;
-       if (icmpv4_xrlim_allow(net, rt, &fl4, icmp_param->data.icmph.type,
-                              icmp_param->data.icmph.code))
+       if (icmpv4_xrlim_allow(net, rt, &fl4, type, code))
                icmp_push_reply(icmp_param, &fl4, &ipc, &rt);
        ip_rt_put(rt);
 out_unlock:
 
        sk = icmp_xmit_lock(net);
        if (!sk)
-               return;
+               goto out;
+
+       /* Check global sysctl_icmp_msgs_per_sec ratelimit */
+       if (!icmpv4_global_allow(net, type, code))
+               goto out_unlock;
 
        /*
         *      Construct source address and options.
        if (IS_ERR(rt))
                goto out_unlock;
 
+       /* peer icmp_ratelimit */
        if (!icmpv4_xrlim_allow(net, rt, &fl4, type, code))
                goto ende;
 
 
        return false;
 }
 
+static bool icmpv6_mask_allow(int type)
+{
+       /* Informational messages are not limited. */
+       if (type & ICMPV6_INFOMSG_MASK)
+               return true;
+
+       /* Do not limit pmtu discovery, it would break it. */
+       if (type == ICMPV6_PKT_TOOBIG)
+               return true;
+
+       return false;
+}
+
+static bool icmpv6_global_allow(int type)
+{
+       if (icmpv6_mask_allow(type))
+               return true;
+
+       if (icmp_global_allow())
+               return true;
+
+       return false;
+}
+
 /*
  * Check the ICMP output rate limit
  */
        struct dst_entry *dst;
        bool res = false;
 
-       /* Informational messages are not limited. */
-       if (type & ICMPV6_INFOMSG_MASK)
-               return true;
-
-       /* Do not limit pmtu discovery, it would break it. */
-       if (type == ICMPV6_PKT_TOOBIG)
+       if (icmpv6_mask_allow(type))
                return true;
 
        /*
        } else {
                struct rt6_info *rt = (struct rt6_info *)dst;
                int tmo = net->ipv6.sysctl.icmpv6_time;
+               struct inet_peer *peer;
 
                /* Give more bandwidth to wider prefixes. */
                if (rt->rt6i_dst.plen < 128)
                        tmo >>= ((128 - rt->rt6i_dst.plen)>>5);
 
-               if (icmp_global_allow()) {
-                       struct inet_peer *peer;
-
-                       peer = inet_getpeer_v6(net->ipv6.peers,
-                                              &fl6->daddr, 1);
-                       res = inet_peer_xrlim_allow(peer, tmo);
-                       if (peer)
-                               inet_putpeer(peer);
-               }
+               peer = inet_getpeer_v6(net->ipv6.peers, &fl6->daddr, 1);
+               res = inet_peer_xrlim_allow(peer, tmo);
+               if (peer)
+                       inet_putpeer(peer);
        }
        dst_release(dst);
        return res;
        sk = icmpv6_xmit_lock(net);
        if (!sk)
                return;
+
+       if (!icmpv6_global_allow(type))
+               goto out;
+
        sk->sk_mark = mark;
        np = inet6_sk(sk);