Linux网络之疑难杂症集合

1. Intel X710网卡,VF口统计不准

问题

  1. sar -n DEV 1 每两秒更新一次收包数量
  2. ethtool -S ethx 实时更新

原因:

  1. sar/ifconfig 数据来自 /proc/net/dev
  2. /proc/net/dev数据来自驱动内部统计
  3. iavf驱动每2秒执行一次watchdog_task,其中会将VF收包统计更新到netdev->stats

内核iavf驱动主要逻辑

1
2
queue_delayed_work(iavf_wq, &adapter->watchdog_task, HZ * 2);
iavf_request_stats(adapter);

Intel原厂工程师:

  • get stats是一个低优先级任务 无必要去实时更新
  • 2s只是开发这个驱动的工程师的一个经验值
  • 在我看来1s周期也问题不大, 但永远也解不了你的问题 因为改为1s 你 0.5s统计也依然gap,改为100ms 你用50ms去查询也一样有gap,你明白我表达的意思
  • 不是改小周期就好,需要考虑到get statistic是要访问到nic的hw registers ,属于i/o操作 过于频繁快速 会影响网卡性能
  • 因为收发都要频繁访问硬件
  • i/o操作是排它的 下一个访问要等上一次访问完成。 包括还需要走的pcie资源也一样

2. raw socket发包失败

问题

PF_PACKET RAW_SOCK,在网口down/up操作时,网口重新up口,第一个包会发送失败

原因:

  1. ifconfig ethX down时,会设置sk->sk_err为NETDOWN
  2. ifconfig ethX up后,第一次进入packet_snd函数 sock_alloc_send_pskb会检查sock_error
  3. 此时第一次分配skb直接返回错误,因此会失败

解决方案有2个:

  1. 只有第一个包会发送失败,因此发包失败时需要重试
  2. 网口down/up时重建socket,此时不会发送失败

3. raw socket收到杂包

原始流程:

1
2
3
4
5
6
7
1. syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW, int(Htons(syscall.ETH_P_ALL)))
2. syscall.Bind
3. SO_ATTACH_FILTER
4. go recvPacket()

现象:
1. 每次启动时都会收到几个杂包

原因:

  1. 设置bpf过滤器生效之前,会有少量包进入socket缓冲区
  2. 一般情况下,业务逻辑会自己过滤收到的数据包,收到杂包也没问题
  3. 此时想直接在内核中过滤,不在业务中过滤(不好的行为)
  4. 需要收好几个协议的数据包,创建socket不可指定单一协议

处理,有以下方案:

  1. 业务中增加过滤操作
  2. 设置过滤规则后,清空缓冲区,启动收包协程
  3. 调整socket创建和设置流程, 如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    1. syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW, 0)
    2. SO_ATTACH_FILTER
    3. syscall.Bind(
    4. go recvPacket()

    说明:
    1. socket指定协议0,raw socket在创建时不加入pt_type列表,也即不会收包
    2. 先设置bpf规则,使之在收包之前生效
    3. 执行bind操作,绑定网口,此时会加入pt_type列表,也即开始收包
    4. 启动收包协程,此时收包即无杂包了