- 论坛徽章:
- 0
|
小弟最近在研究零拷贝发送。所以需要直接调用dev_queue_xmit 进行发送。 可是之前调用dev_queue_xmit 都能正常发送,今天突然出现死机。这里贴出代码,希望哪位大大能够帮忙看一下。- data = kmap(fifo_item->page);
- fifo_item->kernel_vir_addr = (unsigned long)data;
- data += offset;
- block_header = (struct UBM_block_header_t*)data;
- size = block_header->end - block_header->head;
- /* build skb head*/
- skb_orig = kmem_cache_alloc(skbuff_head_cache, GFP_KERNEL & ~__GFP_DMA);
- if (assemble_skb(skb_orig,size,data+block_header->head)<0){
- res = -1;
- kmem_cache_free(skbuff_head_cache, skb_orig);
- goto out;
- }
- skb = skb_clone(skb_orig, GFP_ATOMIC & ~__GFP_DMA);
- if (NULL == skb){
- res = -1;
- kmem_cache_free(skbuff_head_cache, skb_orig);
- goto out;
- }
-
- /*init send infomation in UBM fifo item */
- fifo_item->send_info.skb_orig = skb_orig;
- fifo_item->send_info.sleeping_task = current;
- fifo_item->send_info.status = status;
- /*build skb body*/
- skb->dev = dev;
- skb->pkt_type = PACKET_OTHERHOST;//PACKET_OUTGOING;
- skb->protocol = __constant_htons(ETH_P_IP);
- skb->ip_summed = CHECKSUM_NONE;
- skb->destructor = UBM_skb_destroy;
- skb->priority = 0;
- skb->next = NULL;
-
- skb_reserve (skb,size);
- skb_push(skb, block_header->tail - block_header->data);
- skb_push (skb, block_header->data - block_header->transport_header);
- skb_reset_transport_header(skb);
- if (sockfd < 0){
- skb_push (skb, block_header->transport_header - block_header->network_header);
- skb_reset_network_header(skb);
- iph = ip_hdr(skb);
- ip_send_check(iph);
- skb_push(skb, block_header->network_header - block_header->mac_header);
- skb_reset_mac_header(skb);
- res = dev_queue_xmit(skb);
- if (res != NETDEV_TX_OK)
- MSG_DEBUG("Failed to send");
- else
- MSG_DEBUG("Send out");
- }
- else{
- inet->inet_daddr = daddr;
- ubm_sock->sk->sk_protocol = ULP_PROTOCOL_NUMBER;
- skb->sk = ubm_sock->sk;
- res = ip_queue_xmit(skb);
- if (res != NETDEV_TX_OK)
- MSG_DEBUG("Failed to send, res : %d\n",res);
- else{
- MSG_DEBUG("Send out %lu, res : %d\n", send_counter++,res);
- }
- }
复制代码 blockhead 是一个用户空间结构。在发送页面当中。他的head,tail,data,end 是数据相对于数据头部的偏移量。在调试的时候,输出信息正确。CLONE SKB 的原因是我的数据区处于用户空间。为了防止内核释放掉SKB的数据区,所以克隆。然后当实际释放的时候,克隆的SKB会KUNMAP掉数据区,并且释放原SKB的头部。assemble_skb 负责组合SKB 头 与数据区,并且初始化skb_shared_info信息。 dev 是在网络设备启动时初始话的,在之前有检测是否为空。 奇怪的是,如果我通过提交SOCK信息,并且调用ip_queue_xmit,那么就一切正常。但是调用dev_queue_xmit就死机。另外就是,我通过实验发现当我调用ip_queue_xmit的时候,如果我发包速度非常快,那么前N个包会丢失,但返回信息是正常的。有哪位大大知道这是怎么回事。谢谢了。 |
|