2011-11-29 96 views
1

我想提高数据包发送性能。在此之前,我使用原始套接字,现在我学习packet_mmap。 我有数据包(帧),我已经从另一台PC的内核模块捕获,放到当前的PC,现在我想重发他们到本地接口与转发。 我有例子packet_mmap的,它集成到我的项目,但我送数据包mmap发送数据包格式

fd_socket = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); 
memset(&my_addr, 0, sizeof(struct sockaddr_ll)); 
my_addr.sll_family = PF_PACKET; 
my_addr.sll_protocol = htons(ETH_P_ALL); 
strcpy(str_devname, "eth0"); 
strncpy(s_ifr.ifr_name, str_devname, sizeof(s_ifr.ifr_name)); 
ec = ioctl(fd_socket, SIOCGIFINDEX, &s_ifr); 
i_ifindex = s_ifr.ifr_ifindex; 
memset(&my_addr, 0, sizeof(struct sockaddr_ll)); 
my_addr.sll_family = AF_PACKET; 
my_addr.sll_protocol = ETH_P_ALL; 
my_addr.sll_ifindex = i_ifindex; 
bind(fd_socket, (struct sockaddr *) &my_addr, sizeof(struct sockaddr_ll) 
s_packet_req.tp_block_size = c_buffer_sz; 
s_packet_req.tp_frame_size = c_buffer_sz; 
s_packet_req.tp_block_nr = c_buffer_nb; 
s_packet_req.tp_frame_nr = c_buffer_nb; 
size = s_packet_req.tp_block_size * s_packet_req.tp_block_nr; 
if (setsockopt(fd_socket, SOL_PACKET, PACKET_TX_RING, (char *) &s_packet_req, sizeof(s_packet_req)) < 0) { 
perror("setsockopt: PACKET_TX_RING"); 
return; 
} 

if (c_sndbuf_sz) { 
printf("send buff size = %d\n", c_sndbuf_sz); 
if (setsockopt(fd_socket, SOL_SOCKET, SO_SNDBUF, &c_sndbuf_sz, sizeof(c_sndbuf_sz)) < 0){ 
    perror("getsockopt: SO_SNDBUF"); 
    exit(1); 
} 
} 

data_offset = TPACKET_HDRLEN - sizeof(struct sockaddr_ll); 
printf("data offset = %d bytes\n", data_offset); 
ps_header_start = (tpacket_hdr *) mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_socket, 0); 
if (ps_header_start == (void*) -1) { 
perror("mmap"); 
exit(1); 
} 

然后,我填写的数据

ps_header = ((struct tpacket_hdr *) ((char *) ps_header_start + (c_buffer_sz * i_index))); 
if (!ps_header) { 
perror("ps_header") ; 
return NULL; 
} 
data = ((char*) ps_header) + data_offset; 
switch ((volatile uint32_t) ps_header->tp_status) { 
    case TP_STATUS_AVAILABLE: 
     printf("TP_STATUS_AVAILABLE, index=%d\n",i_index) ; 
     memcpy(data, packet_data, size); 

pthread_mutex_lock(&index_locker) ; 
i_index++; 
pthread_mutex_unlock(&index_locker) ; 

if (i_index >= c_buffer_nb) { 
    i_index = 0; 
    first_loop = 0; 
} 

/* update packet len */ 
ps_header->tp_len = size; 
/* set header flag to USER (trigs xmit)*/ 
ps_header->tp_status = TP_STATUS_SEND_REQUEST; 

然后我送

ec_send = sendto(fd_socket, NULL, 0, 0, (struct sockaddr *) ps_sockaddr, sizeof(struct sockaddr_ll)); 

我有没有错误,ec_send =不是发送数据的大小。但没有数据路由到目标主机。

所以,我问 - 什么数据我应该传递到环形缓冲区,现在我包含头IP,TCP,我应该包括MAC头? - 可能是我必须设置额外的标志来路由我的数据包。

+0

现在我可以使用tshark查看由我发送的数据包......但是它们无法到达目的地......我查看ping应答,但ping程序没有收到数据包。我不知道我应该用什么接口传输,真实还是本地? – SeregASM

+0

嗨,我可以得到您正在使用的示例应用程序使用PACKET_MMAP从用户空间发送数据包 – codingfreak

回答

2

您正在使用SOCK_RAW创建套接字。这意味着您有权提供第2层信息(以太网/ MAC地址)。您可以使用SOCK_DGRAM创建套接字。内核将处理第2层信息以放入下一跳的以太网地址。试试看。