现在的位置: 首页 > 综合 > 正文

绑定和分配mmap内核空间(bind_ring)–(七) 绑定和分配mmap内核空间(bind_ring)–(七)

2014年10月06日 ⁄ 综合 ⁄ 共 2754字 ⁄ 字号 评论关闭

绑定和分配mmap内核空间(bind_ring)--(七)

分类: libpcap+PF_RING源码分析 372人阅读 评论(0) 收藏 举报

用户态在创建了套接字后,接下来就调用bind函数,绑定套接字,而PF_RING实际做的就是为RING分配相应的空间。也就是说,一个套接字,都有一个与之对应的RING。在前面我们已经提到  sock->ops = &ring_ops;这样当应用空间调用bind函数中,内核调用ring_bind函数;即当系统调用bind触发时,内核ring_bind函数就触发了。下面讲解ring_bind函数;

/* Bind to a device */

static int ring_bind(struct socket*sock, struct sockaddr *sa, int addr_len)

{

 struct sock *sk = sock->sk;

 if(enable_debug)

   printk("[PF_RING] ring_bind() called\n");

  /*

   *     Check legality

  */

 if(addr_len != sizeof(struct sockaddr))

   return -EINVAL;

 if(sa->sa_family != PF_RING)

   return -EINVAL;

 if(sa->sa_data == NULL)

   return -EINVAL;

  /* Safety check: add trailing zero if missing*/

 sa->sa_data[sizeof(sa->sa_data) - 1] = '\0';

  if(enable_debug)

   printk("[PF_RING] searching device %s\n", sa->sa_data);

#if 0

 if(strcmp(sa->sa_data, "any") == 0)

   dev = &any_dev;

 else {

   if((dev = __dev_get_by_name(

#if(LINUX_VERSION_CODE >=KERNEL_VERSION(2,6,24))

                            &init_net,

#endif

                            sa->sa_data))== NULL) {

      if(enable_debug)

       printk("[PF_RING]search failed\n");

      return(-EINVAL);

   }

 }

#endif

 return(packet_ring_bind(sk,sa->sa_data));

}

 

ring_bind 函数前面都是一系列的判断,主要起作用的还是packet_ring_bind函数,函数定义如下:

static int packet_ring_bind(structsock *sk, char *dev_name)

{

 struct pf_ring_socket *pfr = ring_sk(sk);

 struct list_head *ptr, *tmp_ptr;

 ring_device_element *dev = NULL;

 if(dev_name == NULL)

   return(-EINVAL);

 list_for_each_safe(ptr, tmp_ptr, &ring_aware_device_list) {

   ring_device_element *dev_ptr = list_entry(ptr, ring_device_element,device_list);

   if(strcmp(dev_ptr->dev->name, dev_name) == 0) {

      dev = dev_ptr;

      break;

   }

 }

 

 if((dev == NULL) || (dev->dev->type != ARPHRD_ETHER))

   return(-EINVAL);

 if(enable_debug)

   printk("[PF_RING] packet_ring_bind(%s, bucket_len=%d)called\n",

          dev->dev->name, pfr->bucket_len);

 

  /* Remove old binding (by default binding tonone)

     BEFORE binding to a new device

  */

 ring_proc_remove(pfr);

 

  /*

IMPORTANT

Leave this statementhere as last one. In fact when

    the ring_netdev != &none_device_elementthe socket is ready to be used.

  */

 pfr->ring_netdev = dev;

 

  /* Timeto rebind to a new device */

 ring_proc_add(pfr);

  /*As the 'struct net_device' does not containthe number

    of RX queues, we can guess that its numberis the same as the number

    of TX queues. After the first packet hasbeen received by the adapter

    the num of RX queues is updated with thereal value

  */

#if(LINUX_VERSION_CODE >=KERNEL_VERSION(2,6,31))

 pfr->num_rx_channels =pfr->ring_netdev->dev->real_num_tx_queues;

#else

 pfr->num_rx_channels = 1;

#endif

 if(dev == &any_device_element)

   num_any_rings++;

 else {

   if(dev->dev->ifindex < MAX_NUM_IFIDX)

     num_rings_per_device[dev->dev->ifindex]++;

   else

      printk("[PF_RING] INTERNAL ERROR:ifindex %d for %s is > than MAX_NUM_IFIDX\n",

            dev->dev->ifindex, dev->dev->name);

 }

 return(0);

}

 

这个函数的主要作用是创建一个环状缓冲区的socket,然后对socket进行绑定。

【上篇】
【下篇】

抱歉!评论已关闭.