与setsockopt()一起使用时,我对SO_PRIORITY遇到了一些问题。
我的疑问是关于发送数据包时的WME MAC层队列和套接字优先级(除其他事项外,还用AIFS时间代替DIFS)。我可以通过以下方式设置特定的优先级: setsockopt(sFd,SOL_SOCKET,SO_PRIORITY,&up,sizeof(up)) 其中“ up”是所需的用户优先级(例如,使用AC_VO队列的up = 4)。 这似乎适用于原始数据报套接字和IP数据报套接字。
问题在于仅在发送单播数据包(实际上已确认)时才正确使用MAC队列;在按照我的要求发送广播(或多播)数据时,无论我用SO_PRIORITY设置什么,都只使用“ AC_BE”(up = 0)队列。
你知道为什么吗?实际上,我实际上也想将这些队列也正确地用于广播传输,因为这对于我正在进行的研究工作可能非常有用。
这是我用来发送数据包的代码的一部分(这里使用的是原始套接字,但是对于非原始套接字,与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, ...
非常感谢您。