tcp jprobe 利用问题定位

/*
 * Here's a sample kernel module showing the use of jprobes to dump
 * the arguments of do_fork().
 *
 * For more information on theory of operation of jprobes, see
 * Documentation/kprobes.txt
 *
 * Build and insert the kernel module as done in the kprobe example.
 * You will see the trace data in /var/log/messages and on the
 * console whenever do_fork() is invoked to create a new process.
 * (Some messages may be suppressed if syslogd is configured to
 * eliminate duplicate messages.)
 */

#include <linux/kprobes.h>
#include <linux/tcp.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/sysctl.h>
#include <linux/kernel.h>
#include <net/dst.h>
#include <net/tcp.h>
#include <net/inet_common.h>
#include <linux/ipsec.h>
#include <asm/unaligned.h>
#include <net/netdma.h>
#include <linux/skbtrace.h>
#include <linux/skbuff.h>

int all_enable1 = 0;
module_param(all_enable1, int, 0644);

int all_enable2 = 0;
module_param(all_enable2, int, 0644);

void jtcp_v4_send_check(struct sock *sk, struct sk_buff *skb)
{	
    struct tcp_sock *tp = tcp_sk(sk);
    u32 saddr, daddr, seq, end_seq;
    unsigned short  source, dest;
    struct inet_sock *inet = inet_sk(sk);

    if (sk == NULL || skb == NULL)
	goto drop;

    saddr = inet->inet_saddr;
    daddr = inet->inet_daddr;
    source = ntohs(inet->inet_sport);
    dest = ntohs(inet->inet_dport);
    seq = TCP_SKB_CB(skb)->seq;
    end_seq = TCP_SKB_CB(skb)->end_seq;


	if (all_enable1 && (source == 80 || dest == 80))
		printk("%s %s %pI4 %u -> %pI4 %u seq %u-%u lost %u sck %u paout %u\n", 
				__func__, end_seq < tp->snd_nxt ? "R":"N", &saddr, source, &daddr, dest, seq, end_seq,
				tp->lost_out, tp->sacked_out, tp->packets_out);	

	if (end_seq < tp->snd_nxt && all_enable2 && (source == 80 || dest == 80)) {
		printk("%s %s %pI4 %u -> %pI4 %u seq %u-%u lost %u sck %u paout %u\n", 
				__func__, end_seq < tp->snd_nxt ? "R":"N", &saddr, source, &daddr, dest, seq, end_seq,
				tp->lost_out, tp->sacked_out, tp->packets_out);	
		dump_stack();
	}

drop:
	jprobe_return();
	return ;
}

int jtcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
{
    struct tcp_sock *tp = tcp_sk(sk);
    u32 saddr, daddr, seq, end_seq, ack_seq;
    unsigned short  source, dest;
    struct inet_sock *inet = inet_sk(sk);
    int i  = 0;
    int len = 0;
    char pf_buffer[1024] = {0};
	const unsigned char *ptr = NULL;
	struct tcp_sack_block_wire *sp_wire = NULL;
    struct tcp_sack_block sp[TCP_NUM_SACKS] ={{0,0},{0,0},{0,0},{0,0}};
	int num_sacks;

    if (sk == NULL || skb == NULL)
        goto drop;

    saddr = inet->inet_saddr;
    daddr = inet->inet_daddr;
    source = ntohs(inet->inet_sport);
    dest = ntohs(inet->inet_dport);
    seq = TCP_SKB_CB(skb)->seq;
    end_seq = TCP_SKB_CB(skb)->end_seq;
	ack_seq = TCP_SKB_CB(skb)->ack_seq;


    ptr = (skb_transport_header(skb) + TCP_SKB_CB(skb)->sacked);
    sp_wire = (struct tcp_sack_block_wire *)(ptr+2);
    num_sacks = min(TCP_NUM_SACKS, (ptr[1] - TCPOLEN_SACK_BASE) >> 3);
	if (TCP_SKB_CB(skb)->sacked) {
		for (i = 0; i < num_sacks; i++) {
			sp[i].start_seq = get_unaligned_be32(&sp_wire[i].start_seq);
			sp[i].end_seq = get_unaligned_be32(&sp_wire[i].end_seq);
	   
			if (len >= sizeof(pf_buffer) )
				break;
			sprintf(pf_buffer + len, "%u-%u,", sp[i].start_seq, sp[i].end_seq);
			len += strlen(pf_buffer);
		}
	}

    if (all_enable1 && (source == 80 || dest == 80))
        printk("%s %pI4 %u -> %pI4 %u %u seq %u lost %u sck %u paout %u sack %s\n", 
                __func__, &saddr, source, &daddr, dest, ack_seq, seq,
                tp->lost_out, tp->sacked_out, tp->packets_out, i ? pf_buffer : ""); 

drop:
    jprobe_return();
    return 0;
}

void jtcp_enter_loss(struct sock *sk, int how)
{
	printk("%s\n", __func__);

	jprobe_return();
	return;
}


static struct jprobe my_jprobe3 = {
		.entry = jtcp_enter_loss,
		.kp = {
			.symbol_name = "tcp_enter_loss",
		},
};

static struct jprobe my_jprobe1 = {
		.entry			= jtcp_v4_send_check,
		.kp = {
			.symbol_name	= "tcp_v4_send_check",
		},
};	

static struct jprobe my_jprobe2 = {
		.entry		   = jtcp_ack,
		.kp = {
			.symbol_name = "tcp_ack",
		},	
};

struct jprobe *my_jprobes[3] = {NULL, NULL, NULL};


static int __init jprobe_init(void)
{
	int ret;
	my_jprobes[0] = &my_jprobe1;
	my_jprobes[1] = &my_jprobe2;
	my_jprobes[2] = &my_jprobe3;


	ret = register_jprobes(my_jprobes, 3);
	if (ret < 0) {
		printk(KERN_INFO "1  register_jprobe failed, returned %d\n", ret);
		return -1;
	}
	printk(KERN_INFO "Planted jprobe at %p, handler addr %p\n",
	       my_jprobe1.kp.addr, my_jprobe1.entry);
	return 0;
}

static void __exit jprobe_exit(void)
{
	unregister_jprobes(my_jprobes, 3);
	printk(KERN_INFO "jprobe at %p unregistered\n", my_jprobe1.kp.addr);
}

module_init(jprobe_init)
module_exit(jprobe_exit)
MODULE_LICENSE("GPL");


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值