]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
dtrace: add ip SDT provider
authorAlan Maguire <alan.maguire@oracle.com>
Mon, 23 Jan 2017 15:28:35 +0000 (15:28 +0000)
committerKris Van Hees <kris.van.hees@oracle.com>
Sat, 4 Mar 2017 02:01:43 +0000 (21:01 -0500)
This gives probe points ip:::receive, ip:::send, ip:::drop-in, and
ip:::drop-out, with parameters compatible with the Solaris
implementation.

Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
Acked-by: Nick Alcock <nick.alcock@oracle.com>
Reviewed-by: HÃ¥kon Bugge <haakon.bugge@oracle.com>
Orabug: 25557554

net/ipv4/ip_input.c
net/ipv4/ip_output.c
net/ipv4/raw.c
net/ipv6/ip6_input.c
net/ipv6/ip6_output.c
net/ipv6/mcast.c
net/ipv6/ndisc.c
net/ipv6/output_core.c
net/ipv6/raw.c

index 2db4c8773c1b405da48758db66969060df2f0812..e3b756ab7ae655c95c5165b3fb4f7f32eacd3951 100644 (file)
 #include <net/xfrm.h>
 #include <linux/mroute.h>
 #include <linux/netlink.h>
+#include <linux/sdt.h>
 
 /*
  *     Process Router Attention IP option (RFC 2113)
@@ -244,15 +245,25 @@ static int ip_local_deliver_finish(struct sock *sk, struct sk_buff *skb)
  */
 int ip_local_deliver(struct sk_buff *skb)
 {
+       struct iphdr *iph = ip_hdr(skb);
+
        /*
         *      Reassemble IP fragments.
         */
 
-       if (ip_is_fragment(ip_hdr(skb))) {
+       if (ip_is_fragment(iph)) {
                if (ip_defrag(skb, IP_DEFRAG_LOCAL_DELIVER))
                        return 0;
        }
 
+       DTRACE_IP(receive,
+           struct sk_buff * : pktinfo_t *, skb,
+           struct sock * : csinfo_t *, skb->sk,
+           void_ip_t * : ipinfo_t *, iph,
+           struct net_device * : ifinfo_t *, skb->dev,
+           struct iphdr * : ipv4info_t *, iph,
+           struct ipv6hdr * : ipv6info_t *, NULL);
+
        return NF_HOOK(NFPROTO_IPV4, NF_INET_LOCAL_IN, NULL, skb,
                       skb->dev, NULL,
                       ip_local_deliver_finish);
@@ -261,8 +272,9 @@ int ip_local_deliver(struct sk_buff *skb)
 static inline bool ip_rcv_options(struct sk_buff *skb)
 {
        struct ip_options *opt;
-       const struct iphdr *iph;
+       const struct iphdr *iph = NULL;
        struct net_device *dev = skb->dev;
+       const char *dropreason;
 
        /* It looks as overkill, because not all
           IP options require packet mangling.
@@ -272,6 +284,7 @@ static inline bool ip_rcv_options(struct sk_buff *skb)
                                              --ANK (980813)
        */
        if (skb_cow(skb, skb_headroom(skb))) {
+               dropreason = "copy-on-write failed";
                IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS);
                goto drop;
        }
@@ -281,6 +294,7 @@ static inline bool ip_rcv_options(struct sk_buff *skb)
        opt->optlen = iph->ihl*4 - sizeof(struct iphdr);
 
        if (ip_options_compile(dev_net(dev), opt, skb)) {
+               dropreason = "invalid options";
                IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INHDRERRORS);
                goto drop;
        }
@@ -294,16 +308,28 @@ static inline bool ip_rcv_options(struct sk_buff *skb)
                                        net_info_ratelimited("source route option %pI4 -> %pI4\n",
                                                             &iph->saddr,
                                                             &iph->daddr);
+                               dropreason = "invalid source route options";
                                goto drop;
                        }
                }
 
-               if (ip_options_rcv_srr(skb))
+               if (ip_options_rcv_srr(skb)) {
+                       dropreason = "invalid options";
                        goto drop;
+               }
        }
 
        return false;
 drop:
+       DTRACE_IP(drop__in,
+           struct sk_buff * : pktinfo_t *, skb,
+           struct sock * : csinfo_t *, skb->sk,
+           void_ip_t * : ipinfo_t *, iph,
+           struct net_device * : ifinfo_t *, skb->dev,
+           struct iphdr * : ipv4info_t *, iph,
+           struct ipv6hdr * : ipv6info_t *, NULL,
+           char * : string, dropreason);
+
        return true;
 }
 
@@ -376,8 +402,9 @@ drop:
  */
 int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
 {
-       const struct iphdr *iph;
+       const struct iphdr *iph = NULL;
        u32 len;
+       const char *dropreason = "header invalid";
 
        /* When the interface is in promisc. mode, drop all the crap
         * that it receives, do not try to analyse it.
@@ -390,8 +417,9 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
 
        skb = skb_share_check(skb, GFP_ATOMIC);
        if (!skb) {
+               dropreason = "could not clone shared buffer";
                IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS);
-               goto out;
+               goto drop;
        }
 
        if (!pskb_may_pull(skb, sizeof(struct iphdr)))
@@ -430,6 +458,7 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
 
        len = ntohs(iph->tot_len);
        if (skb->len < len) {
+               dropreason = "packet too short";
                IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INTRUNCATEDPKTS);
                goto drop;
        } else if (len < (iph->ihl*4))
@@ -440,6 +469,7 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
         * Note this now means skb->len holds ntohs(iph->tot_len).
         */
        if (pskb_trim_rcsum(skb, len)) {
+               dropreason = "could not trim buffer";
                IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS);
                goto drop;
        }
@@ -458,10 +488,20 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
 
 csum_error:
        IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_CSUMERRORS);
+       dropreason = "checksum error";
 inhdr_error:
        IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INHDRERRORS);
+
 drop:
+       DTRACE_IP(drop__in,
+           struct sk_buff * : pktinfo_t *, skb,
+           struct sock * : csinfo_t *, skb ? skb->sk : NULL,
+           void_ip_t * : ipinfo_t *, iph,
+           struct net_device * : ifinfo_t *, dev,
+           struct iphdr * : ipv4info_t *, iph,
+           void * : ipv6info_t *, NULL,
+           char * : string, dropreason);
+
        kfree_skb(skb);
-out:
        return NET_RX_DROP;
 }
index fe16f418e775e2c4cd97735866de948e55ecb0db..3326ba9c04280d5cc533877e8efbd586fbe62a34 100644 (file)
@@ -79,6 +79,7 @@
 #include <linux/mroute.h>
 #include <linux/netlink.h>
 #include <linux/tcp.h>
+#include <linux/sdt.h>
 
 int sysctl_ip_default_ttl __read_mostly = IPDEFTTL;
 EXPORT_SYMBOL(sysctl_ip_default_ttl);
@@ -97,6 +98,15 @@ int __ip_local_out_sk(struct sock *sk, struct sk_buff *skb)
 
        iph->tot_len = htons(skb->len);
        ip_send_check(iph);
+
+       DTRACE_IP(send,
+           struct sk_buff * :  pktinfo_t *, skb,
+           struct sock * : csinfo_t *, sk,
+           void_ip_t * : ipinfo_t *, iph,
+           struct net_device * : ifinfo_t *, skb->dev,
+           struct iphdr * : ipv4info_t *, iph,
+           struct ipv6hdr * : ipv6info_t *, NULL);
+
        return nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT, sk, skb, NULL,
                       skb_dst(skb)->dev, dst_output_sk);
 }
@@ -858,6 +868,7 @@ static int __ip_append_data(struct sock *sk,
        int csummode = CHECKSUM_NONE;
        struct rtable *rt = (struct rtable *)cork->dst;
        u32 tskey = 0;
+       const char *dropreason;
 
        skb = skb_peek_tail(queue);
 
@@ -874,9 +885,13 @@ static int __ip_append_data(struct sock *sk,
        maxnonfragsize = ip_sk_ignore_df(sk) ? 0xFFFF : mtu;
 
        if (cork->length + length > maxnonfragsize - fragheaderlen) {
+               struct iphdr *iph = ip_hdr(skb);
+
                ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport,
                               mtu - (opt ? opt->optlen : 0));
-               return -EMSGSIZE;
+               dropreason = "packet too big";
+               err = -EMSGSIZE;
+               goto error2;
        }
 
        /*
@@ -897,8 +912,10 @@ static int __ip_append_data(struct sock *sk,
                err = ip_ufo_append_data(sk, queue, getfrag, from, length,
                                         hh_len, fragheaderlen, transhdrlen,
                                         maxfraglen, flags);
-               if (err)
+               if (err) {
+                       dropreason = "could not offload UDP fragmentation";
                        goto error;
+               }
                return 0;
        }
 
@@ -967,8 +984,10 @@ alloc_new_skb:
                                        skb = sock_wmalloc(sk,
                                                           alloclen + hh_len + 15, 1,
                                                           sk->sk_allocation);
-                               if (unlikely(!skb))
+                               if (unlikely(!skb)) {
+                                       dropreason = "no buffers";
                                        err = -ENOBUFS;
+                               }
                        }
                        if (!skb)
                                goto error;
@@ -1008,7 +1027,9 @@ alloc_new_skb:
                        copy = datalen - transhdrlen - fraggap;
                        if (copy > 0 && getfrag(from, data + transhdrlen, offset, copy, fraggap, skb) < 0) {
                                err = -EFAULT;
+                               dropreason = "could not fragment packet";
                                kfree_skb(skb);
+                               skb = NULL;
                                goto error;
                        }
 
@@ -1035,6 +1056,7 @@ alloc_new_skb:
                        if (getfrag(from, skb_put(skb, copy),
                                        offset, copy, off, skb) < 0) {
                                __skb_trim(skb, off);
+                               dropreason = "could not fragment packet";
                                err = -EFAULT;
                                goto error;
                        }
@@ -1042,14 +1064,18 @@ alloc_new_skb:
                        int i = skb_shinfo(skb)->nr_frags;
 
                        err = -ENOMEM;
-                       if (!sk_page_frag_refill(sk, pfrag))
+                       if (!sk_page_frag_refill(sk, pfrag)) {
+                               dropreason = "no memory";
                                goto error;
+                       }
 
                        if (!skb_can_coalesce(skb, i, pfrag->page,
                                              pfrag->offset)) {
                                err = -EMSGSIZE;
-                               if (i == MAX_SKB_FRAGS)
+                               if (i == MAX_SKB_FRAGS) {
+                                       dropreason = "too many fragments";
                                        goto error;
+                               }
 
                                __skb_fill_page_desc(skb, i, pfrag->page,
                                                     pfrag->offset, 0);
@@ -1059,8 +1085,10 @@ alloc_new_skb:
                        copy = min_t(int, copy, pfrag->size - pfrag->offset);
                        if (getfrag(from,
                                    page_address(pfrag->page) + pfrag->offset,
-                                   offset, copy, skb->len, skb) < 0)
+                                   offset, copy, skb->len, skb) < 0) {
+                               dropreason = "could not framgent packet";
                                goto error_efault;
+                       }
 
                        pfrag->offset += copy;
                        skb_frag_size_add(&skb_shinfo(skb)->frags[i - 1], copy);
@@ -1080,6 +1108,16 @@ error_efault:
 error:
        cork->length -= length;
        IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTDISCARDS);
+error2:
+       DTRACE_IP(drop__out,
+           struct sk_buff * : pktinfo_t *, skb,
+           struct sock * : csinfo_t *, skb ? skb->sk : NULL,
+           void_ip_t * : ipinfo_t *, skb ? ip_hdr(skb) : NULL,
+           struct net_device * : ifinfo_t *, skb ? skb->dev : NULL,
+           struct iphdr * : ipv4info_t *, skb ? ip_hdr(skb) : NULL,
+           struct ipv6hdr * : ipv6info_t *, NULL,
+           char * : string, dropreason);
+
        return err;
 }
 
@@ -1173,6 +1211,8 @@ ssize_t   ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page,
        int len;
        int err;
        unsigned int maxfraglen, fragheaderlen, fraggap, maxnonfragsize;
+       struct iphdr *iph;
+       const char *dropreason;
 
        if (inet->hdrincl)
                return -EPERM;
@@ -1238,6 +1278,7 @@ ssize_t   ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page,
                        alloclen = fragheaderlen + hh_len + fraggap + 15;
                        skb = sock_wmalloc(sk, alloclen, 1, sk->sk_allocation);
                        if (unlikely(!skb)) {
+                               dropreason = "no buffers";
                                err = -ENOBUFS;
                                goto error;
                        }
@@ -1282,6 +1323,7 @@ ssize_t   ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page,
                        get_page(page);
                        skb_fill_page_desc(skb, i, page, offset, len);
                } else {
+                       dropreason = "packet too big";
                        err = -EMSGSIZE;
                        goto error;
                }
@@ -1304,6 +1346,16 @@ ssize_t  ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page,
 error:
        cork->length -= size;
        IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTDISCARDS);
+       iph = skb ? ip_hdr(skb) : NULL;
+       DTRACE_IP(drop__out,
+           struct sk_buff * : pktinfo_t *, skb,
+           struct sock * : csinfo_t *, skb ? skb->sk : NULL,
+           void_ip_t * : ipinfo_t *, iph,
+           struct net_device * : ifinfo_t *, skb ? skb->dev : NULL,
+           struct iphdr * : ipv4info_t *, iph,
+           struct ipv6hdr * : ipv6info_t *, NULL,
+           char * : string, dropreason);
+
        return err;
 }
 
@@ -1420,8 +1472,21 @@ int ip_send_skb(struct net *net, struct sk_buff *skb)
        if (err) {
                if (err > 0)
                        err = net_xmit_errno(err);
-               if (err)
+               if (err) {
+                       struct iphdr *iph = ip_hdr(skb);
+
                        IP_INC_STATS(net, IPSTATS_MIB_OUTDISCARDS);
+                       DTRACE_IP(drop__out,
+                           struct sk_buff * : pktinfo_t *, skb,
+                           struct sock * : csinfo_t *, skb->sk,
+                           void_ip_t * : ipinfo_t *, iph,
+                           struct net_device * : ifinfo_t *, skb->dev,
+                           struct iphdr * : ipv4info_t *, iph,
+                           struct ipv6hdr * : ipv6info_t *, NULL,
+                           char * : string, "packet too short");
+               }
+
+
        }
 
        return err;
index c77aac75759d94fc2dca10aee4f83d7ece21b1a7..3e24498e8ffccc36ee59218c20b7d9a36f7f6e3c 100644 (file)
@@ -79,6 +79,7 @@
 #include <linux/netfilter_ipv4.h>
 #include <linux/compat.h>
 #include <linux/uio.h>
+#include <linux/sdt.h>
 
 struct raw_frag_vec {
        struct msghdr *msg;
@@ -411,6 +412,14 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4,
                icmp_out_count(net, ((struct icmphdr *)
                        skb_transport_header(skb))->type);
 
+       DTRACE_IP(send,
+           struct sk_buff * :  pktinfo_t *, skb,
+           struct sock * : csinfo_t *, sk,
+           void_ip_t * : ipinfo_t *, iph,
+           struct net_device * : ifinfo_t *, skb->dev,
+           struct iphdr * : ipv4info_t *, iph,
+           struct ipv6hdr * : ipv6info_t *, NULL);
+
        err = NF_HOOK(NFPROTO_IPV4, NF_INET_LOCAL_OUT, sk, skb,
                      NULL, rt->dst.dev, dst_output_sk);
        if (err > 0)
index 57990c929cd8156ebac52c648deb50fd3f74ab82..cfbbca384b469ea3a38987d1b923d5949f2fa925 100644 (file)
@@ -45,6 +45,7 @@
 #include <net/addrconf.h>
 #include <net/xfrm.h>
 #include <net/inet_ecn.h>
+#include <linux/sdt.h>
 
 int ip6_rcv_finish(struct sock *sk, struct sk_buff *skb)
 {
@@ -63,10 +64,11 @@ int ip6_rcv_finish(struct sock *sk, struct sk_buff *skb)
 
 int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
 {
-       const struct ipv6hdr *hdr;
+       const struct ipv6hdr *hdr = NULL;
        u32 pkt_len;
        struct inet6_dev *idev;
        struct net *net = dev_net(skb->dev);
+       const char *dropreason = "header invalid";
 
        if (skb->pkt_type == PACKET_OTHERHOST) {
                kfree_skb(skb);
@@ -82,6 +84,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
        if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL ||
            !idev || unlikely(idev->cnf.disable_ipv6)) {
                IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INDISCARDS);
+               dropreason = "could not clone shared buffer";
                goto drop;
        }
 
@@ -100,8 +103,10 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
         */
        IP6CB(skb)->iif = skb_dst(skb) ? ip6_dst_idev(skb_dst(skb))->dev->ifindex : dev->ifindex;
 
-       if (unlikely(!pskb_may_pull(skb, sizeof(*hdr))))
+       if (unlikely(!pskb_may_pull(skb, sizeof(*hdr)))) {
+               hdr = ipv6_hdr(skb);
                goto err;
+       }
 
        hdr = ipv6_hdr(skb);
 
@@ -118,8 +123,10 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
         * of loopback must be dropped.
         */
        if (!(dev->flags & IFF_LOOPBACK) &&
-           ipv6_addr_loopback(&hdr->daddr))
+           ipv6_addr_loopback(&hdr->daddr)) {
+               dropreason = "loopback destination received on inteface";
                goto err;
+       }
 
        /* RFC4291 Errata ID: 3480
         * Interface-Local scope spans only a single interface on a
@@ -130,8 +137,10 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
        if (!(skb->pkt_type == PACKET_LOOPBACK ||
              dev->flags & IFF_LOOPBACK) &&
            ipv6_addr_is_multicast(&hdr->daddr) &&
-           IPV6_ADDR_MC_SCOPE(&hdr->daddr) == 1)
+           IPV6_ADDR_MC_SCOPE(&hdr->daddr) == 1) {
+               dropreason = "interface-local scope received from other node";
                goto err;
+       }
 
        /* RFC4291 2.7
         * Nodes must not originate a packet to a multicast address whose scope
@@ -139,16 +148,21 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
         * must be silently dropped.
         */
        if (ipv6_addr_is_multicast(&hdr->daddr) &&
-           IPV6_ADDR_MC_SCOPE(&hdr->daddr) == 0)
+           IPV6_ADDR_MC_SCOPE(&hdr->daddr) == 0) {
+               dropreason =
+                   "packet to multicast address with reserved scope 0";
                goto err;
+       }
 
        /*
         * RFC4291 2.7
         * Multicast addresses must not be used as source addresses in IPv6
         * packets or appear in any Routing header.
         */
-       if (ipv6_addr_is_multicast(&hdr->saddr))
+       if (ipv6_addr_is_multicast(&hdr->saddr)) {
+               dropreason = "multicast source address in IPv6 packet";
                goto err;
+       }
 
        skb->transport_header = skb->network_header + sizeof(*hdr);
        IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr);
@@ -160,10 +174,12 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
                if (pkt_len + sizeof(struct ipv6hdr) > skb->len) {
                        IP6_INC_STATS_BH(net,
                                         idev, IPSTATS_MIB_INTRUNCATEDPKTS);
+                       dropreason = "packet too short";
                        goto drop;
                }
                if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr))) {
                        IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INHDRERRORS);
+                       dropreason = "could not trim buffer";
                        goto drop;
                }
                hdr = ipv6_hdr(skb);
@@ -188,6 +204,15 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
 err:
        IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INHDRERRORS);
 drop:
+       DTRACE_IP(drop__in,
+           struct sk_buff * : pktinfo_t *, skb,
+           struct sock * : csinfo_t *, skb ? skb->sk : NULL,
+           void_ip_t * : ipinfo_t *, hdr,
+           struct net_device * : ifinfo_t *, skb ? skb->dev : NULL,
+           struct iphdr * : ipv4info_t *, NULL,
+            struct ipv6hdr * : ipv6info_t *, hdr,
+            char * : string, dropreason);
+
        rcu_read_unlock();
        kfree_skb(skb);
        return NET_RX_DROP;
@@ -206,6 +231,8 @@ static int ip6_input_finish(struct sock *sk, struct sk_buff *skb)
        unsigned int nhoff;
        int nexthdr;
        bool raw;
+       struct ipv6hdr *hdr;
+       const char *dropreason = "header invalid";
 
        /*
         *      Parse extension headers
@@ -238,12 +265,16 @@ resubmit:
                        if (ipv6_addr_is_multicast(&hdr->daddr) &&
                            !ipv6_chk_mcast_addr(skb->dev, &hdr->daddr,
                            &hdr->saddr) &&
-                           !ipv6_is_mld(skb, nexthdr, skb_network_header_len(skb)))
+                           !ipv6_is_mld(skb, nexthdr, skb_network_header_len(skb))) {
+                               dropreason = "destination is multicast";
                                goto discard;
+                       }
                }
                if (!(ipprot->flags & INET6_PROTO_NOPOLICY) &&
-                   !xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
+                   !xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
+                       dropreason = "policy failure";
                        goto discard;
+               }
 
                ret = ipprot->handler(skb);
                if (ret > 0)
@@ -269,6 +300,17 @@ resubmit:
 
 discard:
        IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INDISCARDS);
+
+       hdr = ipv6_hdr(skb);
+       DTRACE_IP(drop__in,
+           struct sk_buff * : pktinfo_t *, skb,
+           struct sock * : csinfo_t *, skb->sk,
+           void_ip_t * : ipinfo_t *, hdr,
+           struct net_device * : ifinfo_t *, skb->dev,
+           struct iphdr * : ipv4info_t *, NULL,
+           struct ipv6hdr * : ipv6info_t *, hdr,
+           char * : string, dropreason);
+
        rcu_read_unlock();
        kfree_skb(skb);
        return 0;
@@ -277,6 +319,16 @@ discard:
 
 int ip6_input(struct sk_buff *skb)
 {
+       struct ipv6hdr *hdr = ipv6_hdr(skb);
+
+       DTRACE_IP(receive,
+           struct sk_buff * : pktinfo_t *, skb,
+           struct sock * : csinfo_t *, skb->sk,
+           void_ip_t * : ipinfo_t *, hdr,
+           struct net_device * : ifinfo_t *, skb->dev,
+           struct iphdr * : ipv4info_t *, NULL,
+           struct ipv6hdr * : ipv6info_t *, hdr);
+
        return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_IN, NULL, skb,
                       skb->dev, NULL,
                       ip6_input_finish);
index 06bf4010d3ed78b6ee39db07010090479a43e303..4abbd63e6f8d39425c023f1ae9bd2a75abce0227 100644 (file)
@@ -55,6 +55,7 @@
 #include <net/xfrm.h>
 #include <net/checksum.h>
 #include <linux/mroute6.h>
+#include <linux/sdt.h>
 
 static int ip6_finish_output2(struct sock *sk, struct sk_buff *skb)
 {
@@ -86,6 +87,16 @@ static int ip6_finish_output2(struct sock *sk, struct sk_buff *skb)
                                        dev_loopback_xmit);
 
                        if (ipv6_hdr(skb)->hop_limit == 0) {
+                               DTRACE_IP(drop__out,
+                                   struct sk_buff * : pktinfo_t *, skb,
+                                   struct sock * : csinfo_t *, skb->sk,
+                                   void_ip_t * : ipinfo_t *, ipv6_hdr(skb),
+                                   struct net_device * : ifinfo_t *, skb->dev,
+                                   struct iphdr * : ipv4info_t *, NULL,
+                                   struct ipv6hdr * : ipv6info_t *,
+                                   ipv6_hdr(skb),
+                                   char * : string, "hoplimit exceeded");
+
                                IP6_INC_STATS(dev_net(dev), idev,
                                              IPSTATS_MIB_OUTDISCARDS);
                                kfree_skb(skb);
@@ -137,6 +148,15 @@ int ip6_output(struct sock *sk, struct sk_buff *skb)
        struct net_device *dev = skb_dst(skb)->dev;
        struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb));
        if (unlikely(idev->cnf.disable_ipv6)) {
+               DTRACE_IP(drop__out,
+                   struct sk_buff * : pktinfo_t *, skb,
+                   struct sock * : csinfo_t *, skb->sk,
+                   void_ip_t * : ipinfo_t *, NULL,
+                   struct net_device * : ifinfo_t *, skb->dev,
+                   struct iphdr * : ipv4info_t *, NULL,
+                   struct ipv6hdr * : ipv6info_t *, NULL,
+                   char * : string, "IPv6 is disabled");
+
                IP6_INC_STATS(dev_net(dev), idev,
                              IPSTATS_MIB_OUTDISCARDS);
                kfree_skb(skb);
@@ -179,6 +199,15 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
                if (skb_headroom(skb) < head_room) {
                        struct sk_buff *skb2 = skb_realloc_headroom(skb, head_room);
                        if (!skb2) {
+                               DTRACE_IP(drop__out,
+                                   struct sk_buff * : pktinfo_t *, skb,
+                                   struct sock * : csinfo_t *, skb->sk,
+                                   void_ip_t * : ipinfo_t *, NULL,
+                                   struct net_device * : ifinfo_t *, skb->dev,
+                                   struct iphdr * : ipv4info_t *, NULL,
+                                   struct ipv6hdr * : ipv6info_t *, NULL,
+                                   char * : string, "out of memory");
+
                                IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
                                              IPSTATS_MIB_OUTDISCARDS);
                                kfree_skb(skb);
@@ -224,6 +253,14 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
        if ((skb->len <= mtu) || skb->ignore_df || skb_is_gso(skb)) {
                IP6_UPD_PO_STATS(net, ip6_dst_idev(skb_dst(skb)),
                              IPSTATS_MIB_OUT, skb->len);
+               DTRACE_IP(send,
+                   struct sk_buff * : pktinfo_t *, skb,
+                   struct sock * : csinfo_t *, skb->sk,
+                   void_ip_t * : ipinfo_t *, hdr,
+                   struct net_device * : ifinfo_t *, skb->dev,
+                   struct iphdr *: ipv4info_t *, NULL,
+                   struct ipv6hdr * : ipv6info_t *, hdr);
+
                return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, sk, skb,
                               NULL, dst->dev, dst_output_sk);
        }
@@ -369,22 +406,32 @@ int ip6_forward(struct sk_buff *skb)
        struct inet6_skb_parm *opt = IP6CB(skb);
        struct net *net = dev_net(dst->dev);
        u32 mtu;
+       const char *dropreason;
 
-       if (net->ipv6.devconf_all->forwarding == 0)
+       if (net->ipv6.devconf_all->forwarding == 0) {
+               dropreason = "forwarding disabled";
                goto error;
+       }
 
-       if (skb->pkt_type != PACKET_HOST)
+       if (skb->pkt_type != PACKET_HOST) {
+               dropreason = "non-host packet type cannot be forwarded";
                goto drop;
+       }
 
-       if (unlikely(skb->sk))
+       if (unlikely(skb->sk)) {
+               dropreason = "socket found for packet to be forwarded";
                goto drop;
+       }
 
-       if (skb_warn_if_lro(skb))
+       if (skb_warn_if_lro(skb)) {
+               dropreason = "LRO warning";
                goto drop;
+       }
 
        if (!xfrm6_policy_check(NULL, XFRM_POLICY_FWD, skb)) {
                IP6_INC_STATS_BH(net, ip6_dst_idev(dst),
                                 IPSTATS_MIB_INDISCARDS);
+               dropreason = "forwarding disabled by policy";
                goto drop;
        }
 
@@ -414,6 +461,16 @@ int ip6_forward(struct sk_buff *skb)
        if (hdr->hop_limit <= 1) {
                /* Force OUTPUT device used as source address */
                skb->dev = dst->dev;
+
+               DTRACE_IP(drop__out,
+                   struct sk_buff * : pktinfo_t *, skb,
+                   struct sock * : csinfo_t *, skb->sk,
+                   void_ip_t * : ipinfo_t *, hdr,
+                   struct net_device * : ifinfo_t *, skb->dev,
+                   struct iphdr * : ipv4info_t *, NULL,
+                   struct ipv6hdr * : ipv6info_t *, hdr,
+                   char * : string, "hoplimit exceeded");
+
                icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, 0);
                IP6_INC_STATS_BH(net, ip6_dst_idev(dst),
                                 IPSTATS_MIB_INHDRERRORS);
@@ -429,6 +486,8 @@ int ip6_forward(struct sk_buff *skb)
                if (proxied > 0)
                        return ip6_input(skb);
                else if (proxied < 0) {
+                       dropreason = "proxy router cannot forward";
+
                        IP6_INC_STATS_BH(net, ip6_dst_idev(dst),
                                         IPSTATS_MIB_INDISCARDS);
                        goto drop;
@@ -438,6 +497,7 @@ int ip6_forward(struct sk_buff *skb)
        if (!xfrm6_route_forward(skb)) {
                IP6_INC_STATS_BH(net, ip6_dst_idev(dst),
                                 IPSTATS_MIB_INDISCARDS);
+               dropreason = "forwarding disabled for destination";
                goto drop;
        }
        dst = skb_dst(skb);
@@ -476,9 +536,12 @@ int ip6_forward(struct sk_buff *skb)
 
                /* This check is security critical. */
                if (addrtype == IPV6_ADDR_ANY ||
-                   addrtype & (IPV6_ADDR_MULTICAST | IPV6_ADDR_LOOPBACK))
+                   addrtype & (IPV6_ADDR_MULTICAST | IPV6_ADDR_LOOPBACK)) {
+                       dropreason = "invalid address type for forwarding";
                        goto error;
+               }
                if (addrtype & IPV6_ADDR_LINKLOCAL) {
+                       dropreason = "invalid address type for forwarding";
                        icmpv6_send(skb, ICMPV6_DEST_UNREACH,
                                    ICMPV6_NOT_NEIGHBOUR, 0);
                        goto error;
@@ -492,6 +555,15 @@ int ip6_forward(struct sk_buff *skb)
        if (ip6_pkt_too_big(skb, mtu)) {
                /* Again, force OUTPUT device used as source address */
                skb->dev = dst->dev;
+               DTRACE_IP(drop__out,
+                   struct sk_buff * : pktinfo_t *, skb,
+                   struct sock * : csinfo_t *, skb->sk,
+                   void_ip_t * : ipinfo_t *, hdr,
+                   struct net_device * : ifinfo_t *, skb->dev,
+                   struct iphdr * : ipv4info_t *, NULL,
+                   struct ipv6hdr * : ipv6info_t *, hdr,
+                   char * : string, "packet too big");
+
                icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
                IP6_INC_STATS_BH(net, ip6_dst_idev(dst),
                                 IPSTATS_MIB_INTOOBIGERRORS);
@@ -504,6 +576,7 @@ int ip6_forward(struct sk_buff *skb)
        if (skb_cow(skb, dst->dev->hard_header_len)) {
                IP6_INC_STATS_BH(net, ip6_dst_idev(dst),
                                 IPSTATS_MIB_OUTDISCARDS);
+               dropreason = "copy-on-write failed";
                goto drop;
        }
 
@@ -522,6 +595,15 @@ int ip6_forward(struct sk_buff *skb)
 error:
        IP6_INC_STATS_BH(net, ip6_dst_idev(dst), IPSTATS_MIB_INADDRERRORS);
 drop:
+       DTRACE_IP(drop__out,
+           struct sk_buff * : pktinfo_t *, skb,
+           struct sock * : csinfo_t *, skb->sk,
+           void_ip_t * : ipinfo_t *, hdr,
+           struct net_device * : ifinfo_t *, skb->dev,
+           struct iphdr * : ipv4info_t *, NULL,
+           struct ipv6hdr * : ipv6info_t *, hdr,
+           char * : string, dropreason);
+
        kfree_skb(skb);
        return -EINVAL;
 }
@@ -1249,6 +1331,7 @@ static int __ip6_append_data(struct sock *sk,
        struct rt6_info *rt = (struct rt6_info *)cork->dst;
        struct ipv6_txoptions *opt = v6_cork->opt;
        int csummode = CHECKSUM_NONE;
+       const char *dropreason;
 
        skb = skb_peek_tail(queue);
        if (!skb) {
@@ -1286,6 +1369,7 @@ static int __ip6_append_data(struct sock *sk,
                     sk->sk_protocol == IPPROTO_RAW)) {
                        ipv6_local_rxpmtu(sk, fl6, mtu - headersize +
                                                   sizeof(struct ipv6hdr));
+                       dropreason = "fragmentation needed but disabled";
                        goto emsgsize;
                }
 
@@ -1294,6 +1378,15 @@ emsgsize:
                        ipv6_local_error(sk, EMSGSIZE, fl6,
                                         mtu - headersize +
                                         sizeof(struct ipv6hdr));
+                       DTRACE_IP(drop__out,
+                           struct sk_buff * : pktinfo_t *, skb,
+                           struct sock * : csinfo_t *, skb->sk,
+                           void_ip_t * : ipinfo_t *, NULL,
+                           struct net_device * : ifinfo_t *, skb->dev,
+                           struct iphdr * : ipv4info_t *, NULL,
+                           struct ipv6hdr * : ipv6info_t *, NULL,
+                           char * : string, "packet too big");
+
                        return -EMSGSIZE;
                }
        }
@@ -1340,8 +1433,10 @@ emsgsize:
                err = ip6_ufo_append_data(sk, queue, getfrag, from, length,
                                          hh_len, fragheaderlen,
                                          transhdrlen, mtu, flags, rt);
-               if (err)
+               if (err) {
+                       dropreason = "could not append data";
                        goto error;
+               }
                return 0;
        }
 
@@ -1422,8 +1517,11 @@ alloc_new_skb:
                                if (unlikely(!skb))
                                        err = -ENOBUFS;
                        }
-                       if (!skb)
+                       if (!skb) {
+                               dropreason = "out of memory";
                                goto error;
+                       }
+
                        /*
                         *      Fill in the control structures
                         */
@@ -1462,10 +1560,14 @@ alloc_new_skb:
                        if (copy < 0) {
                                err = -EINVAL;
                                kfree_skb(skb);
+                               skb = NULL;
+                               dropreason = "invalid header";
                                goto error;
                        } else if (copy > 0 && getfrag(from, data + transhdrlen, offset, copy, fraggap, skb) < 0) {
                                err = -EFAULT;
+                               dropreason = "could not get fragment";
                                kfree_skb(skb);
+                               skb = NULL;
                                goto error;
                        }
 
@@ -1493,20 +1595,25 @@ alloc_new_skb:
                                                offset, copy, off, skb) < 0) {
                                __skb_trim(skb, off);
                                err = -EFAULT;
+                               dropreason = "could not get fragment";
                                goto error;
                        }
                } else {
                        int i = skb_shinfo(skb)->nr_frags;
 
                        err = -ENOMEM;
-                       if (!sk_page_frag_refill(sk, pfrag))
+                       if (!sk_page_frag_refill(sk, pfrag)) {
+                               dropreason = "out of memory";
                                goto error;
+                       }
 
                        if (!skb_can_coalesce(skb, i, pfrag->page,
                                              pfrag->offset)) {
                                err = -EMSGSIZE;
-                               if (i == MAX_SKB_FRAGS)
+                               if (i == MAX_SKB_FRAGS) {
+                                       dropreason = "too many fragments";
                                        goto error;
+                               }
 
                                __skb_fill_page_desc(skb, i, pfrag->page,
                                                     pfrag->offset, 0);
@@ -1516,8 +1623,10 @@ alloc_new_skb:
                        copy = min_t(int, copy, pfrag->size - pfrag->offset);
                        if (getfrag(from,
                                    page_address(pfrag->page) + pfrag->offset,
-                                   offset, copy, skb->len, skb) < 0)
+                                   offset, copy, skb->len, skb) < 0) {
+                               dropreason = "could not get fragment";
                                goto error_efault;
+                       }
 
                        pfrag->offset += copy;
                        skb_frag_size_add(&skb_shinfo(skb)->frags[i - 1], copy);
@@ -1535,6 +1644,15 @@ alloc_new_skb:
 error_efault:
        err = -EFAULT;
 error:
+       DTRACE_IP(drop__out,
+           struct sk_buff * : pktinfo_t *, skb,
+           struct sock * : csinfo_t *, skb ? skb->sk : NULL,
+           void_ip_t * : ipinfo_t *, NULL,
+           struct net_device * : ifinfo_t *, skb ? skb->dev : NULL,
+           struct iphdr * : ipv4info_t *, NULL,
+           struct ipv6hdr * : ipv6info_t *, NULL,
+           char * : string, dropreason);
+
        cork->length -= length;
        IP6_INC_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS);
        return err;
@@ -1681,9 +1799,19 @@ int ip6_send_skb(struct sk_buff *skb)
        if (err) {
                if (err > 0)
                        err = net_xmit_errno(err);
-               if (err)
+               if (err) {
+                       DTRACE_IP(drop__out,
+                           struct sk_buff * : pktinfo_t *, skb,
+                           struct sock * : csinfo_t *, skb->sk,
+                           void_ip_t * : ipinfo_t *, ipv6_hdr(skb),
+                           struct net_device * : ifinfo_t *, skb->dev,
+                           struct iphdr * : ipv4info_t *, NULL,
+                           struct ipv6hdr * : ipv6info_t *, ipv6_hdr(skb),
+                           char * : string, "out of memory");
+
                        IP6_INC_STATS(net, rt->rt6i_idev,
                                      IPSTATS_MIB_OUTDISCARDS);
+               }
        }
 
        return err;
@@ -1709,9 +1837,19 @@ static void __ip6_flush_pending_frames(struct sock *sk,
        struct sk_buff *skb;
 
        while ((skb = __skb_dequeue_tail(queue)) != NULL) {
-               if (skb_dst(skb))
+               if (skb_dst(skb)) {
+                       DTRACE_IP(drop__out,
+                           struct sk_buff * : pktinfo_t *, skb,
+                           struct sock * : csinfo_t *, skb->sk,
+                           void_ip_t * : ipinfo_t *, ipv6_hdr(skb),
+                           struct net_device * : ifinfo_t *, skb->dev,
+                           struct iphdr * : ipv4info_t *, NULL,
+                           struct ipv6hdr * : ipv6info_t *,
+                           ipv6_hdr(skb),
+                           char * : string, "flushing pending frames");
                        IP6_INC_STATS(sock_net(sk), ip6_dst_idev(skb_dst(skb)),
                                      IPSTATS_MIB_OUTDISCARDS);
+               }
                kfree_skb(skb);
        }
 
index 083b2927fc67aaa3939fff42a1c6ee9f1ca70afe..63397220b675b7d614cf45e1bfe898d1196b25eb 100644 (file)
@@ -64,6 +64,8 @@
 
 #include <net/ip6_checksum.h>
 
+#include <linux/sdt.h>
+
 /* Ensure that we have struct in6_addr aligned on 32bit word. */
 static void *__mld2_query_bugs[] __attribute__((__unused__)) = {
        BUILD_BUG_ON_NULL(offsetof(struct mld2_query, mld2q_srcs) % 4),
@@ -1639,11 +1641,22 @@ static void mld_sendpack(struct sk_buff *skb)
                dst = NULL;
        }
        skb_dst_set(skb, dst);
-       if (err)
-               goto err_out;
+       if (err) {
+               kfree_skb(skb);
+               skb = NULL;
+               goto out;
+       }
 
        payload_len = skb->len;
 
+       DTRACE_IP(send,
+           struct sk_buff * : pktinfo_t *, skb,
+           struct sock * : csinfo_t *, skb->sk,
+           void_ip_t * : ipinfo_t *, ipv6_hdr(skb),
+           struct net_device * : ifinfo_t *, skb->dev,
+           struct iphdr *: ipv4info_t *, NULL,
+           struct ipv6hdr * : ipv6info_t *, ipv6_hdr(skb));
+
        err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT,
                      net->ipv6.igmp_sk, skb, NULL, skb->dev,
                      dst_output_sk);
@@ -1653,15 +1666,20 @@ out:
                ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
                IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUTMCAST, payload_len);
        } else {
+               DTRACE_IP(drop__out,
+                   struct sk_buff * : pktinfo_t *, skb,
+                   struct sock * : csinfo_t *, skb ? skb->sk : NULL,
+                   void_ip_t * : ipinfo_t *, skb ? ipv6_hdr(skb) : NULL,
+                   struct net_device * : ifinfo_t *, skb ? skb->dev : NULL,
+                   struct iphdr * : ipv4info_t *, NULL,
+                   struct ipv6hdr * : ipv6info_t *, skb ? ipv6_hdr(skb) : NULL,
+                   char * : string, "multicast send error");
+
                IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS);
        }
 
        rcu_read_unlock();
        return;
-
-err_out:
-       kfree_skb(skb);
-       goto out;
 }
 
 static int grec_size(struct ifmcaddr6 *pmc, int type, int gdel, int sdel)
@@ -1965,6 +1983,15 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
 
        if (!skb) {
                rcu_read_lock();
+               DTRACE_IP(drop__out,
+                   struct sk_buff * : pktinfo_t *, NULL,
+                   struct sock * : csinfo_t *, sk,
+                   void_ip_t * : ipinfo_t *, NULL,
+                   struct net_device * : ifinfo_t *, NULL,
+                   struct iphdr * : ipv4info_t *, NULL,
+                   struct ipv6hdr * : ipv6info_t *, NULL,
+                   char * : string, "out of memory");
+
                IP6_INC_STATS(net, __in6_dev_get(dev),
                              IPSTATS_MIB_OUTDISCARDS);
                rcu_read_unlock();
@@ -2004,10 +2031,21 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
        dst = icmp6_dst_alloc(skb->dev, &fl6);
        if (IS_ERR(dst)) {
                err = PTR_ERR(dst);
-               goto err_out;
+               kfree_skb(skb);
+               skb = NULL;
+               goto out;
        }
 
        skb_dst_set(skb, dst);
+
+       DTRACE_IP(send,
+           struct sk_buff * : pktinfo_t *, skb,
+           struct sock * : csinfo_t *, skb->sk,
+           void_ip_t * : ipinfo_t *, ipv6_hdr(skb),
+           struct net_device * : ifinfo_t *, skb->dev,
+           struct iphdr *: ipv4info_t *, NULL,
+           struct ipv6hdr * : ipv6info_t *, ipv6_hdr(skb));
+
        err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, sk, skb,
                      NULL, skb->dev, dst_output_sk);
 out:
@@ -2015,15 +2053,21 @@ out:
                ICMP6MSGOUT_INC_STATS(net, idev, type);
                ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS);
                IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUTMCAST, full_len);
-       } else
+       } else {
+               DTRACE_IP(drop__out,
+                   struct sk_buff * : pktinfo_t *, skb,
+                   struct sock * : csinfo_t *, skb ? skb->sk : NULL,
+                   void_ip_t * : ipinfo_t *, skb ? ipv6_hdr(skb) : NULL,
+                   struct net_device * : ifinfo_t *, skb ? skb->dev : NULL,
+                   struct iphdr * : ipv4info_t *, NULL,
+                   struct ipv6hdr * : ipv6info_t *, skb ? ipv6_hdr(skb) : NULL,
+                   char * : string, "multicast send error");
+
                IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS);
+       }
 
        rcu_read_unlock();
        return;
-
-err_out:
-       kfree_skb(skb);
-       goto out;
 }
 
 static void mld_send_initial_cr(struct inet6_dev *idev)
index 96f153c0846b7abcd9b1af995c49067efbe7064d..1ebb751b9ff51e58ad3321d24658d0094c898795 100644 (file)
@@ -71,6 +71,7 @@
 
 #include <linux/netfilter.h>
 #include <linux/netfilter_ipv6.h>
+#include <linux/sdt.h>
 
 /* Set to 3 to get tracing... */
 #define ND_DEBUG 1
@@ -463,6 +464,14 @@ static void ndisc_send_skb(struct sk_buff *skb,
        idev = __in6_dev_get(dst->dev);
        IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);
 
+       DTRACE_IP(send,
+           struct sk_buff * : pktinfo_t *, skb,
+           struct sock * : csinfo_t *, skb->sk,
+           void_ip_t * : ipinfo_t *, ipv6_hdr(skb),
+           struct net_device * : ifinfo_t *, skb->dev,
+           struct iphdr * : ipv4info_t *, NULL,
+           struct ipv6hdr * : ipv6info_t *, ipv6_hdr(skb));
+
        err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, sk, skb,
                      NULL, dst->dev,
                      dst_output_sk);
index 85892af5736491fef3978bb8b195045e8e6d2e2c..5c04e5213cab3330e46c34884df007d610bc1448 100644 (file)
@@ -8,6 +8,7 @@
 #include <net/ip6_fib.h>
 #include <net/addrconf.h>
 #include <net/secure_seq.h>
+#include <linux/sdt.h>
 
 static u32 __ipv6_select_ident(struct net *net, u32 hashrnd,
                               struct in6_addr *dst, struct in6_addr *src)
@@ -146,6 +147,14 @@ static int __ip6_local_out_sk(struct sock *sk, struct sk_buff *skb)
        ipv6_hdr(skb)->payload_len = htons(len);
        IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr);
 
+       DTRACE_IP(send,
+           struct sk_buff * : pktinfo_t *, skb,
+           struct sock * : csinfo_t *, skb->sk,
+           void_ip_t * : ipinfo_t *, ipv6_hdr(skb),
+           struct net_device * : ifinfo_t *, skb->dev,
+           struct iphdr *: ipv4info_t *, NULL,
+           struct ipv6hdr * : ipv6info_t *, ipv6_hdr(skb));
+
        return nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT, sk, skb,
                       NULL, skb_dst(skb)->dev, dst_output_sk);
 }
index 2c639aee12cb635886cbf9b1aee91372dbc727ba..ab8fabfecee50e6d455eebf11f059f10cf7e37c9 100644 (file)
@@ -62,6 +62,7 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/export.h>
+#include <linux/sdt.h>
 
 #define        ICMPV6_HDRLEN   4       /* ICMPv6 header, RFC 4443 Section 2.1 */
 
@@ -652,6 +653,14 @@ static int rawv6_send_hdrinc(struct sock *sk, struct msghdr *msg, int length,
                goto error_fault;
 
        IP6_UPD_PO_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len);
+       DTRACE_IP(send,
+           struct sk_buff * : pktinfo_t *, skb,
+           struct sock * : csinfo_t *, skb->sk,
+           void_ip_t * : ipinfo_t *, ipv6_hdr(skb),
+           struct net_device * : ifinfo_t *, skb->dev,
+           struct iphdr * : ipv4info_t *, NULL,
+           struct ipv6hdr * : ipv6info_t *, ipv6_hdr(skb));
+
        err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, sk, skb,
                      NULL, rt->dst.dev, dst_output_sk);
        if (err > 0)
@@ -664,7 +673,16 @@ out:
 error_fault:
        err = -EFAULT;
        kfree_skb(skb);
+       skb = NULL;
 error:
+       DTRACE_IP(send,
+           struct sk_buff * : pktinfo_t *, skb,
+           struct sock * : csinfo_t *, skb ? skb->sk : NULL,
+           void_ip_t * : ipinfo_t *, skb ? ipv6_hdr(skb) : NULL,
+           struct net_device * : ifinfo_t *, skb ? skb->dev : NULL,
+           struct iphdr * : ipv4info_t *, NULL,
+           struct ipv6hdr * : ipv6info_t *, skb ? ipv6_hdr(skb) : NULL);
+
        IP6_INC_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS);
        if (err == -ENOBUFS && !np->recverr)
                err = 0;