2016-06-24 16 views
0

Ich versuche ein benutzerdefiniertes Transportprotokoll zu implementieren, das auf UDP ausgeführt wird. Ich möchte den Header für dieses Protokoll am Anfang des UDP-Datenfelds hinzufügen, kurz bevor die Daten aus dem Benutzerbereich in skbuff kopiert werden. Ich möchte diese Daten auch verarbeiten, bevor UDP sie an den Socket weitergibt, damit ich sie extrahieren kann den Header und führen die erforderliche Verarbeitung im Kernel aus. SoHinzufügen von benutzerdefinierten Daten am Anfang des UDP-Datagramm-Datenfelds (im Linux-Kernel)

  1. Wie stelle ich sicher, dass meine Header (sagen wir struct new_header) am Anfang der Daten in der udp_sendmsg() Funktion hinzugefügt wird. Ich gehe davon aus, dass dies in das Datenfeld von skbuff kopiert werden sollte, bevor irgendwelche tatsächlichen Daten aus dem Benutzerbereich dorthin kopiert werden, oder spätestens, bevor die UDP-Prüfsumme für die Daten berechnet wird. Wo genau passiert das im Code?
  2. Wo genau in udp_recvmsg() Funktion ist die Daten an die Steckdose übergeben? Ich denke es ist skb_copy_datagram_iovec().

Antwort

1

Wie kann ich sicherstellen, dass meine Header (struct new_header sagen) am Anfang der Daten in der udp_sendmsg() Funktion hinzugefügt. Ich nehme an, dass in das Datenfeld von Skbuff kopiert werden sollte, bevor irgendwelche tatsächlichen Daten von Benutzerraum zu ihm oder spätestens kopiert werden, bevor die UDP Prüfsumme auf den Daten berechnet wird. Wo genau passiert das in der Code?

2 Optionen, die Sie betrachten können:
1. Wenn Sie Ihr Protokoll in User-Space implementieren, dann können Sie einfach, auf Kernel verwenden UDP-Sockets zu sprechen und Protokoll decap zu tun, nachdem Sie Datagramms von UDP-Sockets oder encap erhalten bevor Sie Daten an den UDP-Socket senden.
2.Wenn Sie Ihr Protokoll im Kernelraum implementieren wollen. Dann müssen Sie Ihren eigenen Socket-Typ implementieren. Sie können einige Tunnel-Socket-Codes auschecken, die bereits in der Kernel-Quelle als Beispiel existierten (zB L2TP). Sobald Sie Ihren Socket-Typ im Kernel registriert haben, werden Ihre Socket-Daten, die vom Userspace an den Kernel-Space gesendet werden, von Ihrem encap-Code verarbeitet (etwas, das äquivalent zu udp_sendmsg() ist), und dann dekapieren Sie den Code wiederum mit upd_sendmsg() der Netzwerkstapel.

Wo genau in udp_recvmsg() Funktion ist die Daten an die Steckdose übergeben? Ich denke, es ist skb_copy_datagram_iovec().

Nicht sicher, welche Version des Kernels Sie betrachten. Für Kernel 4.6 ist es skb_copy_datagram_msg() -> skb_copy_datagram_iter(). Dies ist, wo das Datagramm zu einem Buff kopiert wird und dann zum Benutzerbereich zurückkehrt.
Tatsächlich wird udp_recvmsg() aufgerufen, wenn der Benutzerbereich versucht, Daten vom Socket zu empfangen, also befindet sich udp_recvmsg() bereits im Socketzusammenhang. Der Netzwerkstapel übergibt das Datagramm an Socket in sock_queue_rcv_skb(), indem das Datagramm in sk_receive_queue gesetzt wird.

Anrufkette im Kernel 4.6 wie folgt aus:

__udp4_lib_rcv --> 
    udp_queue_rcv_skb(sk, skb); --> sock_queue_rcv_skb() 

die userpsace dann durch die Daten erhalten:

recv(); 
... ... 
-------system call --------- 
... ... 
udp_recvmsg --> 
__skb_recv_datagram --> 
__skb_try_recv_datagram --> (get the datagram from sk_receive_queue) 
+0

Vielen Dank für die aufwendige Antwort, dass die meisten meiner Zweifel erklärt, dachte der Rest I durch gehen durch den Code.Ich fand es einfacher, den benutzerdefinierten Header am Ende des Datagramms in der Funktion 'udp_send_skb' hinzuzufügen, da er nahtlos funktioniert, auch wenn die Verkorkung aktiviert ist (ich beabsichtige, alle Funktionen von UDP zu verwenden). –