Recuperando o SO_INCOMING_CPU de um soquete UDP?

0

A API de soquete fornece uma opção SO_INCOMING_CPU , cujos detalhes são fornecidos no homem página :

   SO_INCOMING_CPU (gettable since Linux 3.19, settable since Linux 4.4)
         Sets or gets the CPU affinity of a socket.  Expects an integer
         flag.

             int cpu = 1;
             setsockopt(fd, SOL_SOCKET, SO_INCOMING_CPU, &cpu, sizeof(cpu));

         Because all of the packets for a single stream (i.e., all
         packets for the same 4-tuple) arrive on the single RX queue
         that is associated with a particular CPU, the typical use case
         is to employ one listening process per RX queue, with the
         incoming flow being handled by a listener on the same CPU that
         is handling the RX queue.  This provides optimal NUMA behavior
         and keeps CPU caches hot.

Eu tenho um servidor que cria um soquete UDP, vincula a interface e recv() s dados. Eu quero pegar o SO_INCOMING_CPU deste soquete. Isso é possível?

Eu escrevi um programa de teste e o programa de teste retorna consistentemente -1.

Eu fiz uma depuração de printk() , e parece que o problema é que não há um inet_daddr associado ao soquete: link

Acho que isso faz sentido: o UDP é sem conexão e, como tal, o soquete pode receber pacotes de qualquer endereço. E acho que li em algum lugar que a afinidade da CPU de um soquete é uma função da tupla 4 e, assim, o soquete não tem necessariamente uma afinidade de CPU fixa.

No entanto, dado o fato de que existe um código para inicializar a afinidade da CPU no udp.c, acho que pode estar faltando alguma coisa.

Existe alguma maneira de obter SO_INCOMING_CPU trabalhando com um soquete UDP do lado do servidor?

Aqui está o programa de teste (ligeiramente desleixado) que mencionei:

#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>

int main()
{
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);

    if (sockfd < 0)
    {  
        perror("Error opening socket");
        return 0;
    }

    struct sockaddr_in myaddr;

    memset((char *)&myaddr, 0, sizeof(myaddr));
    myaddr.sin_family = AF_INET;
    myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    myaddr.sin_port = htons(4242);

    if (bind(sockfd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) {
        perror("bind failed");
        return 0;
    }

    #define BUFSIZE 20
    unsigned char buf[BUFSIZE];     /* receive buffer */
    struct sockaddr_in remaddr;     /* remote address */
    socklen_t addrlen = sizeof(remaddr);            /* length of addresses */
    int recvlen = recvfrom(sockfd, buf, BUFSIZE, 0, (struct sockaddr *)&remaddr, &addrlen);

    sleep(1);

    int cpu = 0;
    socklen_t len = sizeof(cpu);
    int ret = getsockopt(sockfd, SOL_SOCKET, SO_INCOMING_CPU, &cpu, &len);

    // Sample Output: Incoming CPU is -1 (ret = 0, recvlen = 5)
    printf("Incoming CPU is %d (ret = %d, recvlen = %d)\n", cpu, ret, recvlen);
}
    
por John Saxton 20.11.2018 / 08:07

0 respostas