Zadanie 3: sterownik urządzenia ZSONet¶
Data ogłoszenia: 30.04.2024
Termin oddania: 04.06.2024 (ostateczny 18.06.2024)
Materiały dodatkowe¶
Symulator urządzenia: https://gitlab.uw.edu.pl/zso/2024z/qemu-zsonet.git (branch
zsonet)Do rozwiązania przydatny jest plik zsonet.h z powyższego repozytorium
Obraz maszyny: https://students.mimuw.edu.pl/ZSO/PUBLIC-SO/zso2024_debian12.qcow2.xz
z3-tst-2024.tar.gztesty do zadania
Wprowadzenie¶
Zadanie polega na napisaniu sterownika do urządzenia ZSONet - prostej karty sieciowej - oraz programu pozwalającego na użycie urządzenia do wysyłania danych do wielu odbiorców z wykorzystaniem io_uring.
Urządzenie powinno być dostępne dla użytkownika jako interfejs sieciowy - w szczególności po jego podłączeniu zgodnie z instrukcjami i załadowaniu modułu system powinien mieć dostęp do internetu.
Interfejs sterownika¶
Urządzenie ZSONet powinno implementować następujące operacje, o których przeznaczeniu można przeczytać
w dokumentacji struktur pci_driver i net_device_ops:
pci_driver.probepci_driver.removenet_device_ops.ndo_opennet_device_ops.ndo_stopnet_device_ops.ndo_get_stats64: powinno udostępniać następujące statystyki:rx_packetstx_packetsrx_bytestx_bytesrx_droppedtx_droppedrx_missed_errors
net_device_ops.ndo_start_xmit
Za zadanie można uzyskać do 10 punktów. Na ocenę zadania składają się dwie części:
wynik testów (od 0 do 10 punktów)
ocena kodu rozwiązania (od 0 do -10 punktów)
Program io_uring - transmiter¶
Program ma służyć do wysyłania danych do wielu odbiorców. Program dostaje adresy odbiorców
w argumentach w formacie <ip>:<port>, a następnie każdą linię z stdin (wraz ze znakiem
nowej linii) wysyła po TCP do każdego z odbiorców za pomocą io_uring (liburing).
Jeśli wysyłamy dane do n odbiorców, program powinien na każdą linię wykonywac o(n)
syscalli --- należy wykorzystać dawaną przez io_uring możliwość przygotowania wielu
komend i przekazania ich do wykonania jednym syscallem. Program powinien zakończyć
działanie po napotkaniu końca stdin.
Program powinien ponownie nawiązywać zerwane połączenia w następujący sposób: jeśli wysyłanie ostatniej linii X do danego odbiorcy się nie powiodło, po odczytaniu następnej linii Y program jednokrotnie próbuje utworzyć socket, połączyć się z tym odbiorcą oraz wysłać do niego linię Y. Jeśli się to uda, dalsza komunikacja z tym odbiorcą przebiega standardowo; w przeciwnym wypadku kolejna próba połączenia powinna nastąpić przy wysyłaniu kolejnej linii Z.
Tworzenie socketów, nawiązywanie połączenia, wysyłanie danych oraz zamykanie socketów powinno odbywać się poprzez io_uring.
W przypadku błędu przy tworzeniu socketa, nawiązywaniu połączenia, wysyłaniu danych lub zamykaniu socketa program powinien wypisać na stderr następujący komunikat:
<ip>:<port> - <socket|connect|send|close> error: <strerror(kod błędu)>
Program powinien w szczególności działać ze sterownikiem ZSONet.
Forma rozwiązania¶
Jako rozwiązanie należy dostarczyć paczkę o nazwie ab123456.tar.gz
(gdzie ab123456 jest loginem na students). Po rozpakowaniu paczka
powinna tworzyć katalog ab123456 z dwoma podkatalogami: zsonet
i transmitter.
Sterownik powinien zostać zrealizowany jako moduł jądra Linux w wersji
6.7.6. Moduł zawierający sterownik powinien nazywać się zsonet.ko.
W katalogu zsonet powinny znajdować się:
źródła modułu
pliki Makefile i Kbuild pozwalające na zbudowanie modułu
krótki opis rozwiązania
Transmiter należy napisać w C lub C++. Po kompilacji powinien znajdować się
w pliku wykonywalnym o nazwie transmitter. Program powinien kompilować się
na dostarczonej maszynie wirtualnej.
W katalogu transmitter powinny znajdować się:
źródła programu
plik Makefile kompilujący rozwiązanie
Rozwiązania prosimy nadsyłać na adres w.ciszewski@mimuw.edu.pl z kopią
do a.jackowski@mimuw.edu.pl oraz m.matraszek@mimuw.edu.pl.
Prosimy o umieszczenie [ZSO] w tytule wiadomości.
QEMU¶
Do użycia urządzenia ZSONet wymagana jest zmodyfikowana wersja qemu, dostępna w wersji źródłowej.
Aby skompilować zmodyfikowaną wersję qemu, należy:
Sklonować repozytorium https://gitlab.uw.edu.pl/zso/2024z/qemu-zsonet.git
git checkout zsonetUpewnić się, że są zainstalowane zależności:
ncurses,libsdl,curl, a w niektórych dystrybucjach takżencurses-dev,libsdl-dev,curl-dev(nazwy pakietów mogą się nieco różnić w zależności od dystrybucji)Uruchomić
./configurez opcjami wedle uznania (patrz./configure --help). Zalecamy flagi:--target-list=x86_64-softmmu --enable-virtfs --enable-gtk
cd buildWykonać
make(lubninja, jeśli mamy zainstalowane)Zainstalować wykonując
make install, lub uruchomić bezpośrednio (binarka tobuild/qemu-system-x86_64).
Aby zmodyfikowane qemu emulowało urządzenie ZSONet, należy przekazać mu opcje
-netdev user,id=net_backend -device zsonet,netdev=net_backend.
Warto ponadto użyć do tego zadania innego obrazu maszyny: https://students.mimuw.edu.pl/ZSO/PUBLIC-SO/zso2024_debian12.qcow2.xz. Na obrazie używanym dotychczas jest zainstalowany Debian 11, w którym dostępna jest stara wersja liburing bez możliwości tworzenia socketów.
Wskazówki¶
Ze względu na charakter komunikacji sieciowej interfejs pliku nie pasuje dobrze do urządzeń
sieciowych. Z tego powodu w Linuksie dla urządzeń sieciowych nie tworzy się pliku w /dev.
Urządzenie sieciowe jest reprezentowane przez strukturę net_device. Następujące funkcje i makra
mogą się przydać podczas jego inicjalizacji:
alloc_etherdev- alokuje strukturęnet_devicefree_netdev- zwalnia strukturęnet_deviceSET_NETDEV_DEV- pozwala powiązaćnet_devicez fizycznym urządzeniem (pci_dev.dev)eth_hw_addr_set- ustawia adres MACregister_netdev- rejestruje urządzenie sieciowe w systemieunregister_netdev- wyrejestrowuje urządzenie sieciowe z systemuwarto też ustawić pola
min_mtuorazmax_mtunetdev_priv- daje dostęp do prywatnych danych sterownika
Oprócz tego istotne są funkcje:
netif_start_queue- informuje system podczas włączania interfejsu, że sterownik może przyjmować ramki do wysyłanianetif_stop_queue- wstrzymuje przekazywanie do sterownika ramek do wysłanianetif_wake_queue- wznawia przekazywanie do sterownika ramek do wysłania
Podczas wysyłania przydatne mogą być:
skb_copy_and_csum_dev- wpisuje do bufora dane ze strukturysk_buffwraz z sumą kontrolną (FCS)dev_kfree_skb_any,dev_consume_skb_any,dev_consume_skb_any_reason- zwalnia wykorzystanysk_buffdo sterownika należy zapewnienie, by wysyłane ramki nie miały rozmiaru mniejszego niż minimalny dla Ethernetu (60 bajtów nie licząc) - mniejsze ramki należy uzupełnić zerami
Podczas odbierania przydatne mogą być:
netdev_alloc_skb- alokujesk_buffskb_copy_to_linear_data,skb_copy_to_linear_data_offset- wpisuje dosk_buffdane z bufora (należy tam umieścić również sumę kontrolną)skb_put- oznacza obszarsk_buffzawierający ramkęnależy też uzupełnić pole
skb.protocolużywająceth_type_transnetif_rx- przekazuje ramkę do systemu