Wysyłanie małych pakietów UDP z jądra Linux do LOOPBACK

Sytuacja: mój kod jest włamany do sterownika jądra Linux. Chcę powiadomić aplikację w przestrzeni użytkownika o godnych uwagi surowych zdarzeniach, zanim zostaną wystrzelone do głównego systemu.

Kroki rozwiązania: Znalazłem fajny przykład wysyłania pakietów UDP z przestrzeni jądra tutaj:http://kernelnewbies.org/Simple_UDP_Server. Używają INADDR_LOOPBACK jako adresu docelowego, który jest dokładnie tym, czego chcę.

Ponieważ jest to kontekst przerwań, zdecydowałem się użyć kolejki roboczej do wysłania pakietów (dostałem BUG: Planowanie bez atomów). Więc mój kod wysyłania jest oparty na kernelnewbies kod owinięty w strukturę kolejki pracy odpalony INIT_WORK i schedule_work na głównym procesie. Nie deklaruję własnej kolejki pracy.

Nie używam Netpoll API jakoto pytanie sugeruje, że nie można wysyłać danych zi do localhosta. „Nie możesz wysłać do siebie”

Problem: Dane wysyłane z jądra i odbierane z mojego odbiornika UDP rzadko pasują do siebie. Nie mam pojęcia, dlaczego tak się dzieje.

Kod fałszywych danych do testowania, w tym definicja struktury kolejki roboczej:

static struct socket *sock_send;
static struct sockaddr_in addr_send;

static struct ksocket_workmessage {
    unsigned char *buf;
    int len;
    struct work_struct workmessage;
} workmsg;


unsigned char testmsg[] = {'T', 'e', 's', 't', 'i', 'n', 'g', 'm', 's', 'g', '\0'};
workmsg.buf = testmsg;
workmsg.len = 11;
INIT_WORK(&workmsg.workmessage, handle_workmessage);
schedule_work(&workmsg.workmessage);

Wysłanie rzeczywistego pakietu jest podobne do „int ksocket_send” z przykładu kernelnewbies. Jedyną różnicą jest to, że mój send_socket jest statyczny i muszę pobrać buf i len z container_of z kolejki roboczej. Pracuję w całkowicie statycznym kontekście. Moja metoda handle_workmessage jest również statyczna:

static void handle_workmessage(struct work_struct *work)
{
        struct msghdr msg;
        struct iovec iov;
        mm_segment_t oldfs;
        int size = 0;

        struct ksocket_workmessage *workmsg = container_of(work, struct ksocket_workmessage, workmessage);


        if (sock_send->sk==NULL)
             return;

        iov.iov_base = workmsg->buf;
        iov.iov_len = workmsg->len;

        msg.msg_flags = 0;
        msg.msg_name = &addr_send;
        msg.msg_namelen  = sizeof(struct sockaddr_in);
        msg.msg_control = NULL;
        msg.msg_controllen = 0;
        msg.msg_iov = &iov;
        msg.msg_iovlen = 1;
        msg.msg_control = NULL;

        oldfs = get_fs();
        set_fs(KERNEL_DS);
        size = sock_sendmsg(sock_send,&msg,workmsg->len);
        set_fs(oldfs);
}

Koniec odbioru wygląda tak:

int main(int argc, char**argv)
{
int sockfd,n;
struct sockaddr_in servaddr;
socklen_t len;
unsigned char mesg[1000];

sockfd=socket(AF_INET,SOCK_DGRAM,0);

bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
servaddr.sin_port=htons(REC_PORT);
bind(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));

for (;;)
{
  n = recv(sockfd,mesg,1000,0);
  printf("-------------------------------------------------------\n");
  mesg[n] = 0;
  printf("Received the following: %d bytes\n", n);
  printf("%s",mesg);
  printf("%c",mesg[0]);
  printf(",%c",mesg[1]);
  printf(",%c",mesg[2]);
  printf(",%c",mesg[3]);
  printf(",%c",mesg[4]);
  printf(",%c",mesg[5]);
  printf(",%c",mesg[6]);
  printf(",%c",mesg[7]);
  printf(",%c",mesg[8]);
  printf(",%c\n",mesg[9]);
  //printf("%c\n",mesg[0]);
  printf("-------------------------------------------------------\n");
  memset(mesg, 0, sizeof(mesg));
 }
}

Wyjście wygląda na uszkodzone, mimo że zawsze wysyłam dokładnie ten sam komunikat do celów testowych:

-------------------------------------------------------
Received the following: 11 bytes
�}|�ingmsg�,},|,�,i,n,g,m,s,g
-------------------------------------------------------
-------------------------------------------------------
Received the following: 11 bytes
����d����,�,�,�,d,�,�,�,,
-------------------------------------------------------
-------------------------------------------------------
Received the following: 11 bytes
�}|�ingmsg�,},|,�,i,n,g,m,s,g
-------------------------------------------------------
-------------------------------------------------------
Received the following: 11 bytes
,�,�,�,�,2,k,�,�,�
-------------------------------------------------------
-------------------------------------------------------
Received the following: 11 bytes
�<����,<,�,�,�,,,,
                    ,=
-------------------------------------------------------
-------------------------------------------------------
Received the following: 11 bytes
�}|�ingmsg�,},|,�,i,n,g,m,s,g
-------------------------------------------------------
-------------------------------------------------------
Received the following: 11 bytes
�}|�ingmsg�,},|,�,i,n,g,m,s,g
-------------------------------------------------------
-------------------------------------------------------
Received the following: 11 bytes


,,%,�,,,,,,
-------------------------------------------------------
-------------------------------------------------------
Received the following: 11 bytes
TestingmsgT,e,s,t,i,n,g,m,s,g
-------------------------------------------------------
-------------------------------------------------------
Received the following: 11 bytes
�}|�ingmsg�,},|,�,i,n,g,m,s,g
-------------------------------------------------------
-------------------------------------------------------
Received the following: 11 bytes
 ����Vk��1k ,�,�,�,�,V,k,�,�,1
-------------------------------------------------------
-------------------------------------------------------
Received the following: 11 bytes
TestingmsgT,e,s,t,i,n,g,m,s,g
-------------------------------------------------------
-------------------------------------------------------
Received the following: 11 bytes
,,,,,�,,�,,
-------------------------------------------------------
-------------------------------------------------------
Received the following: 11 bytes
,,
  ,�,,,,,�,<
-------------------------------------------------------
-------------------------------------------------------
Received the following: 11 bytes
�}|�ingmsg�,},|,�,i,n,g,m,s,g
-------------------------------------------------------

Co mogłoby być tego przyczyną? Ponieważ czasami działa z oczekiwanym wynikiem „TestingmsgT, e, s, t, i, n, g, m, s, g”, nie powinno to być ograniczeniem technicznym. Fragmentacja pakietów również nie powinna mieć miejsca, ponieważ wysyłam tylko 11 bajtów. Nie ma też utraty pakietów. Za każdym razem, gdy wysyłam pakiet, jest on również odbierany.

AKTUALIZACJA: TO DZIAŁA .. ale nie wiem dlaczego Po pierwsze, dzięki za komentarz z alk, że zapomniałem o oczywistości. Aby zalogować się tuż przed wysłaniem danych. Zrobiłem log przed wywołaniem schedule_work. Teraz loguję się bezpośrednio w mojej metodzie wysyłania workmsg-> buf przed zapisaniem nawet do wskaźnika pustki * z iov. Dane są już tam zepsute.

Struktura ksocket_workmessage miała char *, moje dane były char [] i przypisane do wskaźnika struktury.

Teraz zmieniłem typ danych w mojej strukturze ksocket_workmessage:

struct ksocket_workmessage {
        unsigned char buf[11];
        int len;
        struct work_struct workmessage;
} workmsg;

Ponieważ nie mam już wskaźnika, nie mogłem utworzyć mojego niepodpisanego znaku testmsg [], więc poszedłem bezpośrednio przypisać buf:

workmsg.buf[0] = 'T';
workmsg.buf[1] = 'e';
workmsg.buf[2] = 's';
workmsg.buf[3] = 't';
workmsg.buf[4] = 'i';
workmsg.buf[5] = 'n';
workmsg.buf[6] = 'g';
workmsg.buf[7] = 'm';
workmsg.buf[8] = 's';
workmsg.buf[9] = 'g';
workmsg.buf[10] = '\0';

Jeśli ktoś mógłby mi powiedzieć, gdzie zawiodło moje początkowe podejście, chętnie zaakceptuję to jako poprawną odpowiedź.

questionAnswers(1)

yourAnswerToTheQuestion