PF_Ring性能提升使用说明

pf_ring通过用户态、内核态共享内存达到提高包处理效率的目的。

1、PF_Ring加载的3种模式,模式0和调用libpcap性能相同,模式1和模式2相当于0 coyp性能会提升,官网http://www.ntop.org/products/pf_ring/。

As of PF_RING 4.1, when inserting the pf_ring module it is possible to specify three operational modes:

  • Transparent Mode 0: standard NAPI polling
    insmod pf_ring.ko transparent_mode=0
  • Transparent Mode 1: PF_RING-aware driver copies the packets into PF_RING, while the same packet is still passed to NAPI
    insmod pf_ring.ko transparent_mode=1
  • Transparent Mode 2: PF_RING-aware driver copies the packets into PF_RING, the packet is not passed to NAPI
    insmod pf_ring.ko transparent_mode=2

2、整理一下pf_ring是如何通过mmap来实现共享内存的。
mmap注册

kernel/pf_ring.c:7861

点击(此处)折叠或打开

  1. static struct proto_ops ring_ops = {
  2. .family = PF_RING,
  3. .owner = THIS_MODULE,

  4. /* Operations that make no sense on ring sockets. */
  5. .connect = sock_no_connect,
  6. .socketpair = sock_no_socketpair,
  7. .accept = sock_no_accept,
  8. .getname = sock_no_getname,
  9. .listen = sock_no_listen,
  10. .shutdown = sock_no_shutdown,
  11. .sendpage = sock_no_sendpage,

  12. /* Now the operations that really occur. */
  13. .release = ring_release,
  14. .bind = ring_bind,
  15. .mmap = ring_mmap,
  16. .poll = ring_poll,
  17. .setsockopt = ring_setsockopt,
  18. .getsockopt = ring_getsockopt,
  19. .ioctl = ring_ioctl,
  20. .recvmsg = ring_recvmsg,
  21. .sendmsg = ring_sendmsg,
  22. };

这样,当用户态调用mmap时,将会调用ring_mmap函数。

用户态调用
userland/lib/pfring_mod.c:162

点击(此处)折叠或打开

  1. ring->buffer = (char *)mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE,
  2. MAP_SHARED, ring->fd, 0);

  3. if(ring->buffer == MAP_FAILED) {
  4. printf("mmap() failed: try with a smaller snaplen\n");
  5. close(ring->fd);
  6. return -1;
  7. }

  8. ring->slots_info = (FlowSlotInfo *)ring->buffer;
  9. if(ring->slots_info->version != RING_FLOWSLOT_VERSION) {
  10. printf("Wrong RING version: "
  11. "kernel is %i, libpfring was compiled with %i\n",
  12. ring->slots_info->version, RING_FLOWSLOT_VERSION);
  13. close(ring->fd);
  14. return -1;
  15. }
  16. memSlotsLen = ring->slots_info->tot_mem;
  17. munmap(ring->buffer, PAGE_SIZE);

  18. ring->buffer = (char *)mmap(NULL, memSlotsLen,
  19. PROT_READ|PROT_WRITE,
  20. MAP_SHARED, ring->fd, 0);

  21. /* printf("mmap len %u\n", memSlotsLen); */

  22. if(ring->buffer == MAP_FAILED) {
  23. printf("mmap() failed");
  24. close(ring->fd);
  25. return -1;
  26. }

  27. ring->slots_info = (FlowSlotInfo *)ring->buffer;
  28. ring->slots = (char *)(ring->buffer+sizeof(FlowSlotInfo));
首先通过mmap出一个页,读出ring的相关信息(包括memSlot长度),进而将所有的共享区域全部map出来。

内核态实现

用户态调用了mmap后,内核态对应的实现函数是ring_mmap。
调用链是ring_alloc_mem => ring_alloc_mem => allocate_shared_memory => vmalloc_user
分配完映射的内存后
ring_mmap => do_memory_mmap => remap_vmalloc_range
完成映射过程.

你可能感兴趣的:(Linux,Develop)