[Toc]
## 1. Ryu Controller Set up
```
sudo apt update
sudo apt install software-properties-common
sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt-get install virtualenv python3.9 python3.9-distutils
git clone https://github.com/faucetsdn/ryu.git
virtualenv -p`which python3.9` ryu-venv
source ryu-venv/bin/activate
pip3.9 install ryu
pip3.9 uninstall eventlet
pip3.9 install eventlet==0.30.2
ryu-manager ryu/ryu/app/simple_switch_13.py
```

#### Tham khảo
https://askubuntu.com/questions/1318846/how-do-i-install-python-3-9
https://github.com/faucetsdn/ryu/issues/169
https://www.linkedin.com/pulse/installing-ryu-sdn-controller-ubuntu-step-by-step-developer-kamran-g5gdf/
https://ryu.readthedocs.io/en/latest/getting_started.html
## 2. Build OpenvSwitch
```
./boot.sh
./configure
make -j$(nproc)
sudo make install
ovs-vsctl --version
```
## 3. Xây dựng các xe với Mininet-wifi
- Test kết nối giữa ryu controller và mininet-wifi:
```
*** Máy Ryu ***
sudo ufw allow 6633/tcp
source ryu-venv/bin/activate
ryu-manager ryu.app.simple_switch --ofp-listen-host 0.0.0.0
sumo -c osm.sumocfg --verbose --remote-port 8813 --tripinfo-output tripinfos.xml --no-step-log --delay 1000
```

```
*** Máy Mininet-wifi ***
sudo mn --topo single,3 --mac --controller=remote,ip=192.168.5.159,port=6633 --switch ovsk
```

- Xây dựng map site:
+ Tải SUMO: https://eclipse.dev/sumo/
```
cd tools
python osm
```
Tham khảo:https://www.krajzewicz.de/blog/sumo-scalable-osm-maps.php
```
Source code:
#!/usr/bin/env python
"""
(ryu-venv) model@model-virtual-machine:~/Desktop$ cd ryu
(ryu-venv) model@model-virtual-machine:~/Desktop/ryu$ ryu-manager ryu.app.simple_switch --ofp-listen-host 0.0.00
loading app ryu.app.simple_switch
loading app ryu.controller.ofp_handler
instantiating app ryu.app.simple_switch of SimpleSwitch
instantiating app ryu.controller.ofp_handler of OFPHandler
packet in 1152921504606846977 00:23:20:eb:1d:39 ff:ff:ff:ff:ff:ff 65534
packet in 1152921504606846978 00:23:20:d3:b1:f5 ff:ff:ff:ff:ff:ff 65534
packet in 1152921504606846979 00:23:20:d9:cd:ce ff:ff:ff:ff:ff:ff 65534
packet in 1152921504606846980 00:23:20:f8:8a:26 ff:ff:ff:ff:ff:ff 65534
packet in 1152921504606846981 00:23:20:9c:96:5e ff:ff:ff:ff:ff:ff 65534
packet in 1152921504606846982 00:23:20:e9:b3:21 ff:ff:ff:ff:ff:ff 65534
```
```
# Tăng propagation model range để xe kết nối được với nhau ở khoảng cách xa
# exp=2.0 cho phạm vi rộng hơn (~500m)
net.setPropagationModel(model="logDistance", exp=2.0)
info("*** Configuring wifi nodes (BEFORE adhoc setup)\n")
net.configureWifiNodes() # Configure wifi nodes first
info("*** Configuring adhoc network for cars\n")
# BSSID chung cho tất cả xe trong adhoc network
adhoc_bssid = '02:CA:FF:EE:BA:01'
# Set all cars to same adhoc network với BSSID chung
for idx, car in enumerate(net.cars):
wlan_iface = car.wintfs[0].name
# Step 1: Bring interface down first
car.cmd(f'ip link set {wlan_iface} down')
time.sleep(0.2)
# Step 2: Set to ibss mode
car.cmd(f'iw dev {wlan_iface} set type ibss')
time.sleep(0.2)
# Step 3: Bring interface up
car.cmd(f'ip link set {wlan_iface} up')
time.sleep(0.2)
# Step 4: Join adhoc network với BSSID cố định
car.cmd(f'iw dev {wlan_iface} ibss join vanet-adhoc 2412 HT20 fixed-freq {adhoc_bssid}')
time.sleep(0.5)
# Step 5: Flush old IP and assign new IP
car.cmd(f'ip addr flush dev {wlan_iface}')
time.sleep(0.2)
car.cmd(f'ip addr add 192.168.0.{idx+1}/24 brd 192.168.0.255 dev {wlan_iface}')
time.sleep(0.2)
# Step 6: Ensure interface is up
car.cmd(f'ip link set {wlan_iface} up')
time.sleep(0.2)
# Step 7: Also configure 10.0.0.x IP on same interface
car.cmd(f'ip addr add 10.0.0.{idx+1}/8 brd 10.255.255.255 dev {wlan_iface}')
time.sleep(0.2)
# Step 8: Disable firewall and enable forwarding
car.cmd('iptables -F')
car.cmd('iptables -P INPUT ACCEPT')
car.cmd('iptables -P FORWARD ACCEPT')
car.cmd('iptables -P OUTPUT ACCEPT')
# Step 9: Enable IP forwarding
car.cmd('echo 1 > /proc/sys/net/ipv4/ip_forward')
car.cmd(f'echo 0 > /proc/sys/net/ipv4/conf/{wlan_iface}/rp_filter')
car.cmd('echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter')
info(f" {car.name} joined adhoc (BSSID: {adhoc_bssid}) with IP 192.168.0.{idx+1} / 10.0.0.{idx+1}\n")
# Wait for all cars to join and stabilize
time.sleep(3)
info(" Adhoc network configured on channel 1 (2412 MHz) with common BSSID\n")
config_file = 'osm.sumocfg'
if not os.path.exists(config_file):
info(f"*** ERROR: {config_file} not found!\n")
return
info("*** Starting SUMO GUI with TraCI\n")
sumo_cmd = [
'sumo-gui',
'-c', 'osm.sumocfg',
'--remote-port', '8813',
'--start',
'--delay', '100',
]
sumo_process = subprocess.Popen(sumo_cmd)
info(f"*** SUMO GUI started (PID: {sumo_process.pid})\n")
time.sleep(3)
info("*** Connecting to SUMO via TraCI\n")
try:
traci.init(8813)
info("*** TraCI connected successfully!\n")
except Exception as e:
info(f"*** ERROR: TraCI connection failed: {e}\n")
sumo_process.terminate()
return
# QUAN TRỌNG: FORCE SIMULATION START qua TraCI
info("*** Auto-starting SUMO simulation via TraCI...\n")
try:
# Step simulation để spawn xe (tăng lên 500 steps = 50s để spawn đủ 4 xe)
for step in range(500):
traci.simulation.step()
current_time = traci.simulation.getTime()
vehicles = traci.vehicle.getIDList()
# Log mỗi 50 steps (5s)
if step % 50 == 0:
info(f" Time={current_time:.1f}s, Vehicles spawned: {len(vehicles)}\n")
if len(vehicles) > 0:
info(f" Vehicle IDs: {vehicles}\n")
# Thoát khi đủ 4 xe và đã chạy một chút
if len(vehicles) >= 4 and step >= 480:
info(f"*** All 4 vehicles spawned at time {current_time:.1f}s!\n")
# Step thêm 30 lần để xe chạy
for i in range(30):
traci.simulation.step()
break
except Exception as e:
info(f"*** ERROR during simulation: {e}\n")
time.sleep(2)
info("*** Configuring nodes (switches and links)\n")
net.configureNodes()
# RE-CONFIGURE ADHOC sau khi configureNodes() vì nó có thể reset interfaces
info("*** RE-CONFIGURING adhoc network after configureNodes()...\n")
for idx, car in enumerate(net.cars):
wlan_iface = car.wintfs[0].name
# Re-check and fix IBSS mode
ibss_check = car.cmd(f'iw dev {wlan_iface} info')
if 'type IBSS' not in ibss_check:
info(f" {car.name}: Re-joining adhoc network...\n")
car.cmd(f'ip link set {wlan_iface} down')
time.sleep(0.1)
car.cmd(f'iw dev {wlan_iface} set type ibss')
time.sleep(0.1)
car.cmd(f'ip link set {wlan_iface} up')
time.sleep(0.1)
car.cmd(f'iw dev {wlan_iface} ibss join vanet-adhoc 2412 HT20 fixed-freq {adhoc_bssid}')
time.sleep(0.3)
# Re-check and fix IP addresses
ip_check = car.cmd(f'ip addr show {wlan_iface}')
if f'192.168.0.{idx+1}' not in ip_check:
info(f" {car.name}: Re-adding 192.168.0.{idx+1}...\n")
car.cmd(f'ip addr add 192.168.0.{idx+1}/24 brd 192.168.0.255 dev {wlan_iface}')
if f'10.0.0.{idx+1}' not in ip_check:
info(f" {car.name}: Re-adding 10.0.0.{idx+1}...\n")
car.cmd(f'ip addr add 10.0.0.{idx+1}/8 brd 10.255.255.255 dev {wlan_iface}')
car.cmd(f'ip link set {wlan_iface} up')
info(" Adhoc network re-configured\n")
time.sleep(2)
```
```
COMMON_ROUTE = '1392111589#5 1392111589#6 1392111589#7 1392111589#8 1392111589#9 1392111589#10 1392111589#11 1392111589#12 1392111587#2 1392111587#3 1392111587#4 1392111587#5 1301575040#1 1301575040#2 1301575040#3 1301575040#4 1301575040#5 1301575040#7 1301575040#8 1301575062#0 1301575062#1 1301575041#1'
BASE_ROUTES = {
'car_01': COMMON_ROUTE,
'car_02': COMMON_ROUTE,
'car_03': COMMON_ROUTE,
'car_04': COMMON_ROUTE
}
def generate_circular_routes(loops=10):
"""Sinh route circular với 10 loops - đủ cho xe chạy ~5 phút trước khi loop"""
base_routes = {
'route_01': BASE_ROUTES['car_01'],
'route_02': BASE_ROUTES['car_02'],
'route_03': BASE_ROUTES['car_03'],
'route_04': BASE_ROUTES['car_04']
}
info(f"*** Generating circular routes with {loops} loops (Python will auto-reset for infinite loop)...\n")
circular_routes = {}
for route_id, edges in base_routes.items():
circular_routes[route_id] = ' '.join([edges] * loops)
edge_count = len(edges.split()) * loops
info(f" {route_id}: {edge_count} edges (will loop infinitely)\n")
# Tạo XML
xml_content = '''<?xml version="1.0" encoding="UTF-8"?>
<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://sumo.dlr.de/xsd/routes_file.xsd">
<!-- Vehicle Types with SMALL minGap to allow close proximity -->
<vType id="veh_passenger" vClass="passenger" color="0,0,255" speedFactor="1.0" speedDev="0.05" minGap="2.0" accel="2.6" decel="4.5"/>
<vType id="veh_attacker" vClass="passenger" color="255,0,0" speedFactor="1.0" speedDev="0.05" minGap="2.0" accel="2.6" decel="4.5"/>
<vType id="veh_honeypot" vClass="passenger" color="255,255,0" speedFactor="1.0" speedDev="0.05" minGap="2.0" accel="2.6" decel="4.5"/>
'''
for route_id, edges in circular_routes.items():
xml_content += f' <route id="{route_id}" edges="{edges}"/>\n'
xml_content += '''
<!-- Vehicles spawn close together (5s apart) on SAME ROUTE -->
<vehicle id="car_01" type="veh_passenger" route="route_01" depart="0" departLane="best" departPos="0" departSpeed="max"/>
<vehicle id="car_02" type="veh_passenger" route="route_02" depart="5" departLane="best" departPos="0" departSpeed="max"/>
<vehicle id="car_03" type="veh_attacker" route="route_03" depart="10" departLane="best" departPos="0" departSpeed="max"/>
<vehicle id="car_04" type="veh_honeypot" route="route_04" depart="15" departLane="best" departPos="0" departSpeed="max"/>
</routes>
'''
with open('osm.passenger.rou.xml', 'w') as f:
f.write(xml_content)
estimated_min = loops * 0.6
estimated_max = loops * 0.9
info(f"*** Route will loop INFINITELY (auto-reset by Python)\n")
```