Проблема с SO_PRIORITY при отправке широковещательных пакетов - PullRequest
0 голосов
/ 10 ноября 2018

У меня возникают некоторые проблемы с 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, ...

Большое спасибо заранее.

...