关于go:goPacket抓包性能调优

36次阅读

共计 1712 个字符,预计需要花费 5 分钟才能阅读完成。

背景

因为业务状况,须要抓取 sip 数据进行剖析,应用 gopacket 的 pcap 库进行抓包时,当有大批量数据时会呈现抓包数据不齐全的状况。

调研状况

参考该文章: https://blog.csdn.net/rong_to…
发现解决该问题能够有两种计划: 1. mmap 2.pf_ring

  1. pf_ring 该计划须要装置指定的网卡驱动程序,在我这边的业务场景中不实用。
  2. mmap libcap 在 1.1 版本时默认反对 mmap, 然而在调整了各种参数,抓包还是有失落的状况,所以退而求其次,应用 afpacket,该包底层应用的 unix.mmap, 间接应用 mmap 抓包。afpacket 有个问题是抓 127.0.0.1 地址的包,抓到的数据会是双份的,抓外网 ip 的包 OK。

afPacket 应用调优

  1. 网卡开启混淆模式,抓包应用混淆模式
  2. 调整 snapshot 大小最大为 65535
  3. 抓包超时工夫为 -1.

具体的代码为:
参数设置:

    szFrame, szBlock, numBlocks, err := afpacket.AfpacketComputeSize(1024, 65535, os.Getpagesize())
    if err != nil {return err}
    server.handle, err = afpacket.NewAfpacketHandle("eth0",
        szFrame, szBlock, numBlocks, false, -1*time.Millisecond)
    if err != nil {return err}

抓包代码:

    source := gopacket.ZeroCopyPacketDataSource(server.handle)
    dlc := gopacket.DecodingLayerContainer(gopacket.DecodingLayerMap(nil))

for {
select {case <-ctx.Done():
return 
default: 
  d, _, err := source.ZeroCopyReadPacketData()
            if err != nil {fmt.Println("ReadPacketData err:", err)
                continue
            }
            data := make([]byte, len(d))
            copy(data, d)
            var eth layers.Ethernet
            var ip4 layers.IPv4
            var udp layers.UDP
            dlc = dlc.Put(&eth)
            dlc = dlc.Put(&ip4)
            dlc = dlc.Put(&udp)
            dlc = dlc.Put(layers.NewSIP()) 
            decoder := dlc.LayersDecoder(layers.LayerTypeEthernet, gopacket.NilDecodeFeedback)
            decodedLayers := make([]gopacket.LayerType, 0, 10)
            _, err = decoder(data, &decodedLayers)
           if udp.NextLayerType() == gopacket.LayerTypePayload {// udp 解决}else if udp.NextLayerType() == layers.LayerTypeSIP {// sip 解决}
      }
}  

这里有几个留神点:

  1. 如果把 dlc := gopacket.DecodingLayerContainer(gopacket.DecodingLayerMap(nil))
    放到 default 内,每个包都从新生成一下编码对象,会影响数据处理性能,抓包还是会失落。
    这里应用的 DecodingLayerMap 是因为可能更新编码构造体内的对象。
  2. dlc = dlc.Put(layers.NewSIP()) 如果换成 dlc = dlc.Put(&layers.SIP),会报错,起因是 sip 构造体内的 Hearder 是 map 类型,未初始化。
  3. udp 业务解决时要及时,业务解决较慢时会导致抓包阻塞,抓包数据失落。
  4. ZeroCopyReadPacketData 该构造体返回的后果不平安,要 copy 一份防止数据被批改。如果换成 ReadPacketData,还是会呈现丢包的状况,目前没找到起因。

正文完
 0