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.gz
testy 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.probe
pci_driver.remove
net_device_ops.ndo_open
net_device_ops.ndo_stop
net_device_ops.ndo_get_stats64
: powinno udostępniać następujące statystyki:rx_packets
tx_packets
rx_bytes
tx_bytes
rx_dropped
tx_dropped
rx_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 zsonet
Upewnić 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ć
./configure
z opcjami wedle uznania (patrz./configure --help
). Zalecamy flagi:--target-list=x86_64-softmmu --enable-virtfs --enable-gtk
cd build
Wykonać
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_device
free_netdev
- zwalnia strukturęnet_device
SET_NETDEV_DEV
- pozwala powiązaćnet_device
z 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_mtu
orazmax_mtu
netdev_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_buff
wraz z sumą kontrolną (FCS)dev_kfree_skb_any
,dev_consume_skb_any
,dev_consume_skb_any_reason
- zwalnia wykorzystanysk_buff
do 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_buff
skb_copy_to_linear_data
,skb_copy_to_linear_data_offset
- wpisuje dosk_buff
dane z bufora (należy tam umieścić również sumę kontrolną)skb_put
- oznacza obszarsk_buff
zawierający ramkęnależy też uzupełnić pole
skb.protocol
używająceth_type_trans
netif_rx
- przekazuje ramkę do systemu