systemtap的网络监控脚本

stap自带的与网络相关的probe如下,可用于检测一系列网络活动
netdev.close/open--关闭打开设备时调用;dev_name--涉及的设备名
netdev.receive--从网络设备接收的数据;参数:protocl--数据包的协议;dev_name--设备名,诸如eth0;length--接收buffer的长度
netdev.rx--当设备即将接收数据包时调用;参数:protocol--数据包协议;dev_name--接收的设备名
netdev.transmit--发送数据的网络设备;protocol/dev_name/length/truesize--传送的数据大小


socket.aio_read--通过sock_aio_read接收信息时调用;size信息大小type套接字类型protocol协议名
socket.aio_write--通过sock_aio_write发送信息时调用;size信息大小type套接字类型protocol协议名
socket.create--创建套接字;type套接字类型protocol协议名
socket.receive--套接字接收信息;success发送是否成功1失败0size信息大小type套接字类型protocol协议名
socket.send--发送信息;success发送是否成功1失败0size信息大小type套接字类型protocol协议名
socket.sendmsg--正在发送信息的套接字;


tcp.disconnect--退出TCP连接;dport/sport目标/源端口;saddr/daddr源IP/目标IP;
tcp.disconnect.return
tcp.receive--接收TCP包;protocol协议名dport/sport/saddr/daddr/ack/fin/syn
tcp.recvmsg--正在接收TCP信息;
tcp.sendmsg--正在发送TCP信息;


netfilter.ip.local_in--Called on an incoming IP packet addressed to the local computer
netfilter.ip.local_out-- Called on an outgoing IP packet
netfilter.ip.forward - Called on an incoming IP packet addressed to some other computer


例1
network/netfilter_drop.stp
丢弃接收的TCP/UDP前N个包
# stap -g netfilter_drop.stp TCP 1 -c "sleep 2"
#! /usr/bin/env stap
global drop_count
#将网络协议从数字转换为等义字符串,6=TCP 17=UDP
function convert_protocol(proto_n) {
   proto_s="Other"
   if (proto_n==6)
     proto_s="TCP"
   else if(proto_n==17)
     proto_s="UDP"
   return proto_s
}
probe netfilter.ipv4.local_in {
#传入参数length--包长度 nf_stop--将此包定义为stop, verdict--该包最终处理决定
  if(convert_protocol(protocol)
==@1 || @1=="ALL") {
    if(@count(drop_count[@1])>=$2 && $2 !=0)
      exit()
    else {
      $verdict=nf_stop
      drop_count[@1]<< #使用聚集数组,可同时对其执行count/sum操作
   }
  }
}
probe begin {
#判断参数1参数2是否符合标准
  if (@1 !='TCP' || @1 !='UDP' && @1 !='ALL') || ($2<0) {
    printf("Please enter \"TCP\", \"UDP\" or \"ALL\" on the command line, followed by the number of packets to drop.\n")
    exit()
  }
  else
    printf("Dropping packets! Ctrl+C to stop")
}
probe end{
   foreach(proto in drop_count)
     printf("%d %s packets drop, total %d bytes\n",@count(drop_count[proto]),proto,@sum(drop_count[proto]))
}

 


例2
在后台运行,将内核的tcp cwnd覆盖为10,用于改善web server的延迟
#! /usr/bin/stap -g
probe kernel.function("tcp_init_cwnd").return {
  r = $return
  if( r>0 && r<10)
    $return =10;
  counts[r,$return] <<< 1
}
global counts # will be automatically summarized at shutdown
该脚本起始于
http://blog.yufeng.info/archives/1173
tcp_init_cwnd.stp
probe kernel.function("tcp_init_cwnd").return
{
$return = $1
}
#设成7个mss
$ sudo stap -p4 -g -m initcwnd tcp_init_cwnd.stp 7
initcwnd.ko
加载到远端机器
$ sudo insmod initcwnd.ko


例3
network/netdev.stp
跟踪网卡活动,提交和接收包以及更改配置
#! /usr/bin/env stap
probe netdev.get_stats ? {
  printf("%s was asked for stats structure\n", dev)
}
probe netdev.register {
  printf("registering netdev_name\n",dev_name)
}
probe netdev.unregister{
  printf("unregistering netdev_name\n",dev_name)
}
probe netdev.ioctl{
  printf("netdev ioctl raised with param:%d and arg:%s\n",cmd,arg)
}
probe netdev.set_promiscuity {
 if (enable)
  printf("Device %s entering in promiscuous mode\n", dev_name)
 else
  printf("Device %s leaving promiscuous mode\n", dev_name)
}
probe netdev.change_rx_flag ? {
 printf("Device %s is changing its RX flags to %d\n", dev_name, flags)
}
probe netdev.change_mtu {
 printf("Changing MTU on device %s from %d to %d\n", dev_name,
    old_mtu, new_mtu)
}
probe netdev.change_mac {
 printf("Changing MAC address on device %s from %s to %s\n",
    dev_name, old_mac, new_mac)
}
probe netdev.transmit {
 printf("Device %s is sending (queued) a packet with protocol %d\n", dev_name, protocol)
}
probe netdev.hard_transmit {
 printf("Device %s is sending (hard) a packet with protocol %d\n", dev_name, protocol)
}
probe netdev.rx {
 printf("Device %s received a packet with protocol %d\n", dev_name, protocol)
}


例4
nettop.stp
按照网络接收或发送次数降序排列,每5秒打印一次
global ifxmit,ifrecv
global ifmerged
probe netdev.transmit {
  ifxmit[pid(),dev_name,execname(),uid()] <<< length  --将发送的包长度存放到ifxmit
}
probe netdev.receive {
  ifrecv[pid(),dev_name,execname(),uid()] <<< length  --将接受的包长度存放到ifrecv
}
function print_activity {
  printf("%5s %5s %-7s %7s %7s %7s %7s %-15s\n",
          "PID", "UID", "DEV", "XMIT_PK", "RECV_PK",
          "XMIT_KB", "RECV_KB", "COMMAND")
  foreach ([pid,dev,exec,uid] in ifxmit) {--遍历ifxmit,计算相同属性进程发送和接受包的总次数
    ifmerged[pid,dev,exec,uid] += @count(ifxmit[pid,dev,exec,uid]); 
  }
  foreach ([pid,dev,exec,uid] in ifrecv) {
    ifmerge[pid,dev,exec,uid] += @count(ifrecv[pid,dev,exec,uid]);
  }
  foreach ([pid,dev,exec,uid] in ifmerge -) {--按发送+接收次数降序排列
    n_xmit = @count(ifxmit[pid,dev,exec,uid]);--发送次数
    n_recv = @count(ifrecv[pid,dev,exec,uid]);--接收次数
    printf("%5d %5d %-7s %7d %7d %7d %7d %-15s\n",
            pid, uid, dev, n_xmit, n_recv,
            n_xmit ? @sum(ifxmit[pid, dev, exec, uid])/1024 : 0,
            n_recv ? @sum(ifrecv[pid, dev, exec, uid])/1024 : 0,
            exec)
  }
  delete ifmerged
  delete ifxmit
  delete ifrecv
}


probe timer,ms(5000), end, error {
  print_activity()
}


以下为输出
PID UID DEV XMIT_PK RECV_PK XMIT_KB RECV_KB COMMAND
2886 4 eth0 79 0 5 0 cups-polld
11362 0 eth0 0 61 0 5 firefox
0 0 eth0 3 32 0 3 swapper
2886 4 lo 4 4 0 0 cups-polld
11178 0 eth0 3 0 0 0 synergyc
PID UID DEV XMIT_PK RECV_PK XMIT_KB RECV_KB COMMAND
0 0 eth0 0 6 0 0 swapper
2886 4 lo 2 2 0 0 cups-polld
11178 0 eth0 3 0 0 0 synergyc
3611 0 eth0 0 1 0 0 Xorg


例5
socket-trace.stp
跟踪有关net/socket.c的内核调用
#! /usr/bin/env stap
probe kernel.function("
*@net/socket.c").call {
printf ("%s -> %s\n", thread_indent(1), ppfunc())
}
probe kernel.function("
*@net/socket.c").return {
printf ("%s }
输出如下
0 Xorg(3611): -> sock_poll
3 Xorg(3611): 0 Xorg(3611): -> sock_poll
3 Xorg(3611): 0 gnome-terminal(11106): -> sock_poll
5 gnome-terminal(11106): 0 scim-bridge(3883): -> sock_poll
3 scim-bridge(3883): 0 scim-bridge(3883): -> sys_socketcall
4 scim-bridge(3883): -> sys_recv
8 scim-bridge(3883): -> sys_recvfrom


例6
监控接受到的TCP数据包
#! /usr/bin/env stap
// A TCP dump like example
probe begin, timer.s(1) {
printf("-----------------------------------------------------------------\n")
printf(" Source IP Dest IP SPort DPort U A P R S F \n")
printf("-----------------------------------------------------------------\n")
}
probe tcp.receive {
printf(" %15s %15s %5d %5d %d %d %d %d %d %d\n",
saddr, daddr, sport, dport, urg, ack, psh, rst, syn, fin)
}
输出如下
-----------------------------------------------------------------
Source IP Dest IP SPort DPort U A P R S F
-----------------------------------------------------------------
209.85.229.147 10.0.2.15 80 20373 0 1 1 0 0 0
92.122.126.240 10.0.2.15 80 53214 0 1 0 0 1 0
92.122.126.240 10.0.2.15 80 53214 0 1 0 0 0 0
209.85.229.118 10.0.2.15 80 63433 0 1 0 0 1 0


例7
监控内核丢弃的网络包
dropwatch.stp
#! /usr/bin/env stap
global locations
probe begin { printf("Monitoring for dropped packets\n") }
probe end { printf("Stopping dropped packet monitor\n") }
probe kernel.trace("kfree_skb") { locations[$location] <<< 1}
probe timer.sec(5) {
  foreach(l in locations-) {
    printf("%d packets dropped at %s\n", @count(loactions[l]),symname(l))
  }
}
--kfree_skb跟踪内核丢弃网络包,有2个参数:$skb指向被释放的buffer的指针;$location被释放的内核代码位置;
运行stap --all-modules dropwatch.stp
注:如果--all-modules不可用,则symname只会打印出raw地址,此时可以使用/boot/System.map-`uname -r`查看其对应的function
Monitoring for dropped packets
1762 packets dropped at unix_stream_recvmsg
4 packets dropped at tun_do_read
2 packets dropped at nf_hook_slow


例8
监控新建的TCP连接
#! /usr/bin/env stap
probe begin {
printf("%6s %16s %6s %6s %16s\n",
"UID", "CMD", "PID", "PORT", "IP_SOURCE")
}
probe kernel.function("tcp_accept").return?,
kernel.function("inet_csk_accept").return? {
sock = $return
if (sock != 0)
printf("%6d %16s %6d %6d %16s\n", uid(), execname(), pid(),
inet_get_local_port(sock), inet_get_ip_source(sock))
}
输出如下
UID CMD PID PORT IP_SOURCE
0 sshd 3165 22 10.64.0.227
0 sshd 3165 22 10.64.0.227
/usr/share/systemtap/testsuite/systemtap.examples/

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/15480802/viewspace-762002/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/15480802/viewspace-762002/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值