ns-3.42
. Pe orice mașină virtuală cu orice distribuție de Linux instalată, sau sub WSL2, sau dacă aveți Linux pe stațiile voastre instalați pachetul de docker:
sudo apt install docker docker.io docker-compose
O dată instalat docker
e nevoie să vă adăugați userul în grupul docker. Urmați pașii de aici: https://docs.docker.com/engine/install/linux-postinstall/
Vezi și https://github.com/isrm-lab/isrm-vm-docker-img/blob/main/README.md
mkdir -p ~/isrm cd ~/isrm git clone git@github.com:isrm-lab/isrm-vm-docker-img.git cd ~/isrm/isrm-vm-docker ./build-img.sh isrm2024 ~/isrm/ns-3-dev yes # to enter console of image after build: ./enter-img.sh isrm2024
Compilare și rulare un exemplu de ns-3 pentru validarea funcționalității:
./ns3 configure --enable-examples --enable-tests ./ns3 build ./ns3 run "lab3 --numberOfNodes=2 \ --payloadSize=1400 --offeredRate=11Mbps --phyRate=DsssRate11Mbps --simulationTime=2"
Dacă vă dați shutdown/reboot sau unmount la filesystem-ul dockerului și vreți să re-rulați simulatorul ns-3:
./build-img.sh isrm2024 ~/isrm/ns-3-dev
ns-3
este un simulator de rețele (Ethernet
, Wi-Fi
, 4G
etc.) ce oferă:
UDP
/TCP
etc.)
Simulatorul este scris în C++
, iar modelele se pot dezvolta în C++
sau Python
. In cadrul laboratoarelor vom folosi și vom dezvolta modele în C++
deoarece capabilitatile si suportul oferite in ns-3
sunt mai bune decat cele pentru Python
.
Obiectiv: Acest laborator oferă o idee de bază a modului în care funcționează simulatorul:
Cele mai importante pagini de parcurs despre ns-3
la început, dar și în timpul laboratoarelor sunt:
Pentru inceput, puteti parcurge Tutorial ns-3, indeosebi urmatoarele sectiuni:
În cadrul laboratorului ne vom concentra pe simulări Wi-Fi (IEEE 802.11
). Puteti gasi exemple de simulări (în afara celor pe care le veți primi pentru laboratorul de ISRM) în ns3/examples/wireless
Ne propunem să rulăm un exemplu simplu: ns3/examples/wireless/wifi-tcp.cc
. Acesta constă dintr-o stație (STA
) care se conectează la un access point (AP
) folosind 802.11n
. Traficul este uplink
de la STA
la AP
. Putem rula orice exemplu astfel:
./enter-img.sh isrm2024 root@isrm-vm:/home/student/isrm$ ./ns3 run wifi-tcp 1.1s: 46.2797 Mbit/s 1.2s: 55.2294 Mbit/s (...) 10.8s: 55.465 Mbit/s 10.9s: 44.9843 Mbit/s Average throughput: 52.15 Mbit/s
Dacă vrem să transmitem parametrii în linia de comandă simulării (deoarece wifi-tcp
suportă), o putem face cu ghilimele:
root@isrm-vm:/home/student/isrm$ ./ns3 run "wifi-tcp --pcap --simulationTime=3" 1.1s: 45.8086 Mbit/s 1.2s: 55.3472 Mbit/s (...) 3.9s: 52.7565 Mbit/s Average throughput: 52.9017 Mbit/s
Întrucât opțiunea --pcap
activează mecanismul de pcap tracing din ns-3 (vom discuta mai târziu despre acesta), putem vizualiza cu wireshark următoarele capturi care se generează în directorul curent:
root@isrm-vm:/home/student/isrm# ls *.pcap AccessPoint-0-0.pcap Station-1-0.pcap
root@isrm-vm:/home/student/isrm$ ls *.pcap AccessPoint-0-0.pcap Station-1-0.pcap
~/.isrm2024/merge
(presupunând că ați rulat scriptul de build cu parametru numele mașinii isrm2024
)
Filtrați și afișați doar pachetele TCP. Fără a citi codul simulării și nici descrierea de la începutul sursei, ci doar PCAP-urile, care credeți că e direcția traficului? Sunt două noduri: 0 și 1 - 0→1 sau 1→0?
Station-1-0.pcap
dar în AccessPoint-0-0.pcap
îl vom putea vedea.
Acest lucru e util când vom analiza de ce se pierd pachete în WiFi
Determinați canalul routerului și frecvența centrală a lui analizând câmpurile din secțiunea 802.11 radio information
sau Radiotap Header
.
Exemplu rulare:
root@isrm-vm:/home/student/isrm$ tshark -T fields -e frame.time_epoch \ -e frame.number -e ip.src \ -r ./AccessPoint-0-0.pcap '(ip.proto == 6) && (ip.src == 10.0.0.1)' > frames.txt
-T fields
indică câmpurile din pachete care se doresc printate Colecție de câmpuri de interes:
opțiune pentru -e | semnificație |
---|---|
frame.time_epoch | timpul de la începutul simulării |
frame.number | numărul cadrului |
ip.src | adresa IP sursă |
ip.id | IP identifier field |
ip.ttl | câmpul TTL din headerul de IP |
wlan.flags | câmpul flags din headerul WLAN |
wlan.seq | numărul de secvență WLAN |
wlan.fcs_good | cadrul WLAN este validat de câmpul FCS |
(ip.proto == 6) && (ip.src == 10.0.0.1)
indică condiția de filtrare a pachetelor din .pcap - pachete de tip TCP (proto=6) și IP sursă; folosește acelasi limbaj ca și wireshark Exerciții:
tshark
cu filtrul wlan.fc.type_subtype == 0x08
extrageți și numărați câte pachete de tip beacon trimite AP-ul din captura ./AccessPoint-0-0.pcap
wc -l
frame.time_epoch
de la câteva linii consecutive și determinați la ce interval de timp (în ms
) AP-ul (access point-ul) trimite beacon-uritshark
extrageți în 2 fișiere separate, fiecare fișier având filtrul wlan.fc.type_subtype ⇐ 0x0011
(subtipul mai mic sau egal cu 0x0011) și celălalt wlan.fc.type_subtype == 0x0028
următoarele câmpuri: frame.time_epoch
, wlan_radio.phy
, frame.number
.
Mecanismul de tracing din ns-3 ne permite să logăm și în format ASCII evenimentele. Rulați simularea:
./waf --run "lab3 --numberOfNodes=2 --payloadSize=1400 \ --offeredRate=11Mbps --phyRate=DsssRate11Mbps --simulationTime=2 --tracing=true"
Vom obține două trace-uri: unul PCAP (cum am analizat mai sus) și unul text: wifi-lab3.tr
. Deschideți și inspectați fișierul.
Explicația conținutului fișierului:
Prima literă este:
r for received d for dropped + for enqueued - for dequeued t is for transmitted #Relevant for WiFi tracefiles
A doua coloană reprezintă timestamp.
A treia coloană are următoarea semnificație:
Apoi urmează o serie de nume de clase din sistemul de atribute al ns-3 (ns3::Ipv4Header, ns3::TcpHeader
) și cu o listă de trace-uri specifice clasei respective.
Ne propunem să validăm și că funcționează generarea de grafice, lucru pe care îl vom folosi la toate laboratoarele.
Descarcati fișierul de date numit plotting_data1.csv ce conține:
# comentarii # X Y 1 2 2 3 3 2 4 1
Pe baza acestor date, graficul poate fi construit folosind urmatorul template (pe care il puteti folosi si la restul laboratoarelor):
import copy import numpy as np import matplotlib import matplotlib.pyplot as plt # Calea absoluta catre fisierul de date din care citim # TODO - trebuie inlocuita cu calea corecta DATA_FILE = 'plotting_data1.csv' columns = ['x', 'y'] # Citim datele din fisier # Argumentul delimiter precizeaza care este delimitatorul dintre coloane # Argumentul skip_header precizeaza cate linii nu vor fi citite pornind cu inceputul fisierului # Argumentul names este unul foarte util deoarece permite asocierea de nume pentru coloanele din fisier si # de asemenea duce la un acces foarte usor al datelor in script. In acest exemplu, names va fi egal cu ['x', 'y'] # ceea ce inseamna ca putem accesa valorile din prima coloana prin sim_data['x']. # Argumentul dtype setat specifica modul in care vor fi interpretate coloanele (string-urile ca string-uri, float-urile ca float-uri). # In absenta acestui argument, valorile din coloane vor fi interpretate ca float. sim_data = np.genfromtxt(DATA_FILE, delimiter=' ', skip_header=2, names=columns, dtype=None) def plot_data(sim_data): data = copy.deepcopy(sim_data) # Apelul subplots poate fi folosit pentru a crea mai multe subgrafice in cadrul aceluiasi grafic sau in cadrul unor grafice diferite # Prin figsize se specifica dimensiunea graficului fig, ax = plt.subplots(figsize=(12,12)) # Valori stilistice pentru grafic ax.grid(color='b', alpha=0.5, linestyle='dashed', linewidth=0.5) # Denumirile axelor Ox si Oy, precum si titlul graficului plt.xlabel('X values') plt.ylabel('Y values') plt.title('A very nice looking plot') # Aici este construit efectiv graficul. Campul label va fi folosit in cadrul legendei graficului ax.plot(data['x'], data['y'], label='My plot') ax.legend() plt.savefig("l1t3.png") if __name__ == '__main__': plot_data(sim_data)
Verificați după rulare că în folderul din docker aveți fișierul l1t3.png
. De asemenea, pentru că folosim overlayfs puteți accesa de pe mașina fizică/virtuală din care rulați docker-ul din folderul: ~/.isrm2024/merge/l1t3.png
presupunând că la build ati folosit ca parametru numele docker image-ului isrm2024
.