Einführung in Xdp und ein einfaches Beispiel für einen GTTP-Tunnel

       Es gibt viele Möglichkeiten / Tools für die Netzwerkentwicklung. Wenn Sie sorgfältig darüber nachdenken, sollten Sie diese in die folgenden Kategorien einteilen.

  1. Hardwarespezifische
           integrierte Schaltkreise: Asic-
           programmierbare Hardware (Application Specific Integrated Circuit) mit fester Verarbeitungslogik, dargestellt durch Schaltchips: wie FPGA, NP; es gibt auch relativ neue Broadcom-OF-DPA, die Openflow unterstützen, und Barfuß-Tofino, der P4 unterstützt .
  2. Software-
           Kernel-Modus: Treiber, TCP / IP-Protokollstapel, XDP-
           Benutzermodus: Socket, Tun, Tan-
           Benutzer / Kernel-Kombination: DPDK, Netmap
           Im Vergleich zu anderen Netzwerkentwicklungsmethoden / -tools wurde XDP später angezeigt . Geben Sie also zunächst eine kurze Einführung in XDP.

Einführung in XDP

       XDP (eXpress Data Path) wurde erstmals in der Linux-Kernel 4.8-Version veröffentlicht, die auf der eBPF-Implementierung basiert. Apropos eBPF: Zu Beginn muss BPF (Berkeley Packet Filter, Berkeley Packet Filter) eingeführt werden. BPF wurde sehr früh in den Linux-Kernel eingeführt. Für mich oder wahrscheinlich die meisten Leute, als ich zum ersten Mal von BPF hörte, wurde geschätzt, dass ich tcpdump, libpcap usw. und die BPF-Syntax zur Erfassung von Netzwerkpaketen verwendet habe. Wie nachstehend

'host 192.168.0.1 and (port 80 or port 8080)'

       Die ursprüngliche Verwendung von BPF ist in der Tat hier. Normalerweise besteht die Paketerfassung darin, das Kommunikationsproblem einer bestimmten Netzwerkanwendung zu analysieren und zu lokalisieren, dh nicht den gesamten Datenverkehr auf der Netzwerkkarte zu berücksichtigen. Wenn Sie die Netzwerkdaten der Beziehung aus einer großen Anzahl von Netzwerknachrichten herausfiltern möchten. Eine Möglichkeit besteht darin, dass der Kernel alle Netzwerknachrichten an den Benutzermodus sendet und ein Benutzermodusprogramm zum Filtern verwendet wird. Die Mängel dieser Methode liegen auf der Hand. Jede Nachricht muss über den Kernel an die Speicherkopie im Benutzermodus gesendet werden. Daher stellt die BPF-Methode einen Filtertyp bereit, der dynamisch in einen BPF-Zielcode (Zwischencode) codiert wird, und schließlich vervollständigt die virtuelle Kernel-BPF-Maschine die Ausführung des BPF-Zielcodes, dh vervollständigt die Funktion der Nachrichtenfilterung. BPF sendet nur die Pakete, die die Filterbedingungen erfüllen, an den Benutzermodus.
Fügen Sie hier eine Bildbeschreibung ein
       Der oben eingeführte BPF wird jetzt als klassischer BPF bezeichnet. Zitiere Wiki-Informationen.
       "EBPF wurde von Alexei Starovoitov entworfen, als er bei PluMgrid arbeitete. Dieses Unternehmen konzentrierte sich auf die Erforschung neuer Wege zum Entwerfen softwaredefinierter Netzwerklösungen. Als es nur ein Vorschlag war, half Daniel Borkmann, ein Kernel-Ingenieur bei Red Hat, bei der Modifizierung. Kann den Kernel-Code eingeben und die vorhandene BPF-Implementierung vollständig ersetzen. Dies ist das erste größere Update von BPF seit zwei Jahrzehnten, wodurch BPF zu einer universellen virtuellen Maschine wird. "Zu
       diesem Zeitpunkt öffnete der Linux-Kernel ein Fenster für Entwickler. Dieses Fenster verbessert nicht nur die Beobachtbarkeit des Systems, z. B. die Unterstützung von kprobes, uprobes, tracepoints und perf_events. (Hinweis: Persönliche Meinung, ebpfs Beitrag zur Systembeobachtbarkeit ist weitaus größer als die Netzwerkverarbeitung).
       Das folgende Bild gibt eine gute Einführung in die Zusammensetzung und die Gesamtverarbeitung von XDP.
Fügen Sie hier eine Bildbeschreibung ein
1) Schreiben Sie den BPF-Code im Benutzermodus und kompilieren Sie ihn in ein BPF-Objekt.
2) Der BPF-Loader lädt BPF auf die virtuelle BPF-Maschine herunter (diese virtuelle Maschine ist keine virtuelle Kvm-Maschine, und ich persönlich verstehe sie als ähnlich wie jvm).
3) Verschiedene Aktionscode-Rückkehrcodes , Definiert die nachfolgende Verarbeitungsmethode der Nachricht:
XDP_PASS: die Nachricht weiter an den Protokollstapel gesendet werden
XDP_DROP: Paketverlust
XDP_ABORTED: Paketverlust und Tracepoint Ausnahme
XDP_TX: Weiterleiten der Nachricht von der Netzwerkkarte empfangenen
XDP_REDIRECT: Die Nachricht an einem anderen Netzwerkkarte oder gesendet an den User - Modus umgeleitet wird AF_XDP Socke
       Sorgfältige Haben Sie festgestellt, dass XDP nur Pakete in Empfangsrichtung verarbeiten kann, aber keine Pakete in Senderichtung des Computers? Dies scheint weniger flexibel zu sein als Netfilter. Als Zwischen-Netzwerkweiterleitungsgerät verarbeitet XDP jedoch nur Pakete in Empfangsrichtung, was in Ordnung zu sein scheint. Das Folgende ist ein einfaches Beispiel für eine XDP-Anwendung, die auf der Verarbeitung des UPF-Verarbeitungs-GTPU-Tunnels des mobilen Kernnetzwerks basiert. Der Code befindet sich unter https://github.com/801room/upf-xdp. Der vollständige Spielzeugcode, aber die grundlegenden technischen Punkte und Lösungen sollten berücksichtigt werden.

Einfaches Beispiel

Fügen Sie hier eine Bildbeschreibung ein
       Der Code ist in zwei Teile unterteilt. Ein Teil ist für unterwegs geschrieben, lädt das BPF-Objekt in den Kernel und bindet es an die angegebene Netzwerkkarte. Außerdem kann die Karte so eingestellt werden, dass sie mit dem bpf-Objekt als Steuerebene interagiert.

err := bpf.LoadElf(elf)
…
xdp := bpf.GetProgramByName("upf_input")
…
err = xdp.Attach(iface)

Der andere Teil wird in c geschrieben und als Datenebene in ein BPF-Objekt kompiliert.

SEC("xdp")
int upf_input(struct xdp_md *ctx)
{
  void *data = (void *)(long)ctx->data;
  struct ethhdr *eth = data;
  return eth_handle(ctx, eth);
}

       Der Compiler kompiliert SEC ("xdp") in einen Abschnitt in elf, bpf.GetProgramByName sucht nach diesem Abschnitt und findet den Funktionseintrag.
       Der folgende Code wird Schicht für Schicht aus der zweiten Schicht verarbeitet, es gibt jedoch keine spezielle Erklärung. Es sollte beachtet werden, dass es in xdp keine Schleifen ohne Grenzen geben kann und es keine globalen Variablen geben kann. Wenn Sie auf den Inhalt der Nachricht zugreifen, überprüfen Sie zuerst die effektive Grenze des Zugriffs. Der folgende Code meldet beispielsweise einen Fehler beim Laden von bpf.

static u32 eth_handle(struct xdp_md *ctx, struct ethhdr *ethh)
{
  u16 eth_type;
  u64 offset;
  struct vlan_hdr *vlan_hdr;
  eth_type = htons(ethh->h_proto);
  switch(eth_type) { 
  ...
  }
}

Dieser Code muss vor dem Zugriff geändert werden, um festzustellen, ob er außerhalb des Bereichs liegt.

static u32 eth_handle(struct xdp_md *ctx, struct ethhdr *ethh)
{
  void *data_end = (void *)(long)ctx->data_end;
  u16 eth_type;
  u64 offset;
  struct vlan_hdr *vlan_hdr;
  offset = sizeof(*ethh);
  if((void *)ethh + offset > data_end) {
    bpf_debug("Cannot parse L2\n");
    return XDP_PASS;
  }
  eth_type = htons(ethh->h_proto);
  switch(eth_type) { 
  ...
  }
}

       Schließlich möchte ich über bpf_xdp_adjust_head () sprechen, diese Funktion kann den Nachrichtenkopf ändern, drücken oder ziehen. Siehe die Definition spezifischer bpf-bezogener Funktionen.
https://man7.org/linux/man-pages/man7/bpf-helpers.7.html

Zusammenfassung

       Im Vergleich zu P4 hat Xdp für Linux-Netzwerkentwickler einen viel niedrigeren Schwellenwert und eine viel niedrigere Lernkurve. Für einfache Weiterleitungs- und ACL-Funktionen. Die Verwendung von xdp ist schnell und einfach. Wenn es wie Tunnelkapselung / -entkapselung verarbeitet wird, sollte xdp auch praktisch sein.
       Und genau wie bei P4 kann es für eine eingehende Nachrichtenanalyse und komplexe Richtlinienkontrolle etwas schwierig sein. Das ultimative Ziel des Autors ist es, einen UPF zu schreiben. Nach einer kurzen Untersuchung von P4 und XDP wollen wir VPP gehorsam annehmen.

Ich denke du magst

Origin blog.csdn.net/weixin_38667434/article/details/109278940
Empfohlen
Rangfolge