2011-11-29 2 views
1

패킷 전송 성능을 향상시키고 싶습니다. 그 전에는 원시 소켓을 사용했고 이제 packet_mmap을 연구합니다. 다른 PC의 커널 모듈에서 이미 캡처 한 패킷 (프레임)을 현재 PC에 저장하고 다음 포워딩을 통해 로컬 인터페이스에 다시 전송하려고합니다. 내가 packet_mmap의 예를 가지고 , 내 프로젝트에 통합,하지만 난 오류 없어 한패킷 mmap은 패킷 형식을 전송합니다.

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

그때 보내

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 = null이 아닌 sended 데이터의 크기. 그러나 대상 호스트에 라우팅 된 데이터가 없습니다.

그래서 내가 링 버퍼에 전달해야하는 데이터는 무엇입니까? 이제 MAC 헤더를 포함해야합니까? - 내 패킷을 라우팅하기 위해 추가 플래그를 설정해야 할 수도 있습니다.

+0

지금은 tshark ....와 함께 보낸 패킷을 볼 수 있지만 대상에 올 수 없습니다 ... 나는 ping 응답을 보지만 ping 프로그램에서받은 패킷은 없습니다. 그리고 나는 어떤 인터페이스를 사용하여 실제 또는 지역으로 전송해야하는지 알지 못합니다. – SeregASM

+0

안녕하세요, PACKET_MMAP을 사용하여 사용자 공간에서 패킷을 보내려는 샘플 애플리케이션을 구할 수 있습니까? – codingfreak

답변

2

SOCK_RAW을 사용하여 소켓을 생성하고 있습니다. 이는 사용자가 Layer-2 정보 (이더넷/MAC 주소)를 제공 할 권한이 있음을 의미합니다. SOCK_DGRAM으로 소켓을 만들 수 있습니다. 커널은 레이어 2 정보를 처리하여 다음 홉의 이더넷 주소를 저장합니다. 시도해 봐.