У меня возникают некоторые проблемы с SO_PRIORITY при использовании setsockopt ().
Мое сомнение связано с очередями MAC-уровня WME и приоритетом сокета при отправке пакетов (определяя, среди прочего, время AIFS вместо DIFS). Я могу установить определенный приоритет с помощью:
setsockopt (SFD, SOL_SOCKET, SO_PRIORITY, и вверх, SizeOf (вверх))
где «вверх» - желаемый приоритет пользователя (например, up = 4 для использования очереди AC_VO).
Похоже, это работает как с необработанными сокетами, так и с сокетами дейтаграмм IP.
Проблема в том, что очереди MAC правильно используются только при отправке одноадресных пакетов (которые фактически подтверждаются); при отправке широковещательных (или многоадресных) данных, как мне требуется, используется только очередь «AC_BE» (up = 0), независимо от того, что я установил с SO_PRIORITY.
Ты знаешь почему? Я на самом деле хочу правильно использовать эти очереди и для широковещательной передачи, поскольку это может быть очень полезно для исследовательской работы, которую я делаю.
Это часть кода, который я использую для отправки пакетов (здесь используется необработанный сокет, но то же самое происходит с не необработанными сокетами, как с дейтаграммами AF_INET):
// Open socket
sFd=socket(AF_PACKET,SOCK_RAW,htons(ETH_P_ALL));
if(sFd==-1) {
perror("socket() error");
exit(EXIT_FAILURE);
}
// Getting WLAN interface index using a custom library (wlanLookup() and macAddrTypeGet() functions
ret_wlanl_val=wlanLookup(devname,&ifindex,srcmacaddr,0);
if(ret_wlanl_val<=0) {
fprintf(stderr,"wlanLookup() error.\n");
rs_printerror(stderr,ret_wlanl_val);
close(sFd);
exit(EXIT_FAILURE);
}
if(macAddrTypeGet(srcmacaddr)==MAC_BROADCAST) {
fprintf(stderr,"Could not retrieve source MAC address.\n");
close(sFd);
exit(EXIT_FAILURE);
}
// Prepare sockaddr_ll structure
bzero(&addrll,sizeof(addrll));
addrll.sll_ifindex=ifindex;
addrll.sll_family=AF_PACKET;
addrll.sll_protocol=htons(ETH_P_ALL);
// Bind to the wireless interface
if(bind(sFd,(struct sockaddr *) &addrll,sizeof(addrll))<0) {
perror("Cannot bind to interface: bind() error");
close(sFd);
exit(EXIT_FAILURE);
}
// Print AC corresponding to selected UP (and handle possible wrong UP)
up=atoi(argv[3]);
switch(up) {
case 0:
case 3:
fprintf(stdout,"AC_BE is selected, with UP: %d.\n",up);
break;
case 1:
case 2:
fprintf(stdout,"AC_BK is selected, with UP: %d.\n",up);
break;
case 4:
case 5:
fprintf(stdout,"AC_VI is selected, with UP: %d.\n",up);
break;
case 6:
case 7:
fprintf(stdout,"AC_VO is selected, with UP: %d.\n",up);
break;
default:
fprintf(stderr,"Wrong UP specified. AC_BE will be used.\n");
up=0;
break;
}
// Set user priority using socket layer options (does not work with broadcast?)
if(setsockopt(sFd,SOL_SOCKET,SO_PRIORITY,&up,sizeof(up))!=0) {
perror("setsockopt() for SO_PRIORITY error");
close(sFd);
exit(EXIT_FAILURE);
}
// Set broadcast permission using socket layer options (is this really required?)
if(setsockopt(sFd,SOL_SOCKET,SO_BROADCAST,(void *) &broadPerm,sizeof(broadPerm))!=0) {
perror("setsockopt() for SO_BROADCAST error");
close(sFd);
exit(EXIT_FAILURE);
}
//... Prepare payload, headers and timer to periodically send data...
while(1) {
// poll waiting for events happening on the timer descriptor (i.e. wait for timer expiration)
if(poll(&timerMon,1,INDEFINITE_BLOCK)>0) {
// "Clear the event" by performing a read() on a junk variable
read(clockFd,&junk,sizeof(junk));
// Send brodcast data (if verbose==1, print '.' for each sent datagram)
// Prepare datagram
// ... Prepare datagram to be sent (contained in "ethernetpacket", with size "finalpktsize")
if(sendto(sFd,ethernetpacket,finalpktsize,0,(struct sockaddr *)&addrll,sizeof(struct sockaddr_ll))!=finalpktsize) {
perror("sendto() for sending broadcasted data failed");
fprintf(stderr,"The program will be terminated now");
break;
}
if(verbose) {
fprintf(stdout,".");
fflush(stdout);
}
}
}
//... free variables, close socket, ...
Большое спасибо заранее.