发送广播数据包时出现SO_PRIORITY问题

时间:2018-11-10 15:11:05

标签: c sockets queue broadcast wireless

与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, ...

非常感谢您。

0 个答案:

没有答案
相关问题