【发布时间】:2012-01-08 10:39:28
【问题描述】:
我想提高数据包传输性能。在此之前我使用原始套接字,现在我研究 packet_mmap。 我已经从另一台 PC 的内核模块中捕获了数据包(帧),并将其放入当前 PC,现在我想通过以下转发将它们重新传输到本地接口。 我有 packet_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=not null size of sent data。但是没有数据路由到目的主机。
所以,我问 - 我应该将什么数据传递给环形缓冲区,现在我包含标头 ip、tcp,我应该包含 MAC 标头吗? - 可能我必须设置额外的标志来路由我的数据包。
【问题讨论】:
-
现在我可以使用 tshark 查看我发送的数据包....但它们无法到达目的地...我 ping 并看到 ping 回复但 ping 程序没有收到数据包。而且我不知道我应该使用什么接口来传输,真实的还是本地的?
-
您好,我可以获取您用来使用 PACKET_MMAP 从用户空间发送数据包的示例应用程序
标签: linux sockets network-programming