Skip to content

Commit

Permalink
Enable IPv6 and make the topology dual-stack (#87)
Browse files Browse the repository at this point in the history
* Assign v6 addresses

* Temp commit

* More routing fixes

* It routes!

* Cleanups

* Add IP4_NAME_PREFIX/IP6_NAME_PREFIX

* Get rid of the NAME_PREFIX stuff

* Address review comments
  • Loading branch information
larseggert authored Oct 13, 2020
1 parent 5dadbeb commit 41dea6c
Show file tree
Hide file tree
Showing 14 changed files with 129 additions and 45 deletions.
65 changes: 51 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,59 @@ simulator (as found in the [sim](sim) directory), and a client and a server (as
found in the individual QUIC implementation directories, or for a simple shell,
the [endpoint](endpoint) directory).

The framework uses two networks on the host machine: `leftnet` (193.167.0.0/24)
and `rightnet` (193.167.100.0/24). `leftnet` is connected to the client docker
image, and `rightnet` is connected to the server. The ns-3 simulation sits in
the middle and forwards packets between `leftnet` and `rightnet`.
The framework uses two networks on the host machine: `leftnet` (IPv4
193.167.0.0/24, IPv6 fd00:cafe:cafe:0::/64) and `rightnet` (IPv4
193.167.100.0/24, IPv6 fd00:cafe:cafe:100::/64). `leftnet` is connected to the
client docker image, and `rightnet` is connected to the server. The ns-3
simulation sits in the middle and forwards packets between `leftnet` and
`rightnet`.

```
|‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾|
| sim |
| |
|‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾| |‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾|‾‾‾‾‾‾‾‾‾‾‾‾‾| |‾‾‾‾‾‾‾‾| |‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾|‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾| |‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾|
| client | | docker-bridge | eth0 | | | | eth1 | docker-bridge | | server |
| |-----| | |-----| ns-3 |-----| | |-----| |
| 193.167.0.100 | | 193.167.0.1 | 193.167.0.2 | | | | 193.167.100.2 | 193.167.100.1 | | 193.167.100.100 |
|_______________| |_______________|_____________| |________| |_______________|_______________| |_________________|
| |
|__________________________________________________|
+-----------------------+
| client eth0 |
| |
| 193.167.0.100 |
| fd00:cafe:cafe:0::100 |
+----------+------------+
|
|
+----------+------------+
| docker-bridge |
| |
| 193.167.0.1 |
| fd00:cafe:cafe:0::1 |
+-----------------------------------+
| | eth0 | |
| | | |
| | 193.167.0.2 | |
| | fd00:cafe:cafe:0::2 | |
| +----------+------------+ |
| | |
| | |
| +----------+------------+ |
| | ns3 | |
| +----------+------------+ |
| | |
| | |
| +----------+------------+ |
| | eth1 | |
| | | |
| | 193.167.100.2 | |
| | fd00:cafe:cafe:100::2 | sim|
+-----------------------------------+
| docker-bridge |
| |
| 193.167.100.1 |
| fd00:cafe:cafe:100::1 |
+----------+------------+
|
|
+----------+------------+
| server eth0 |
| |
| 193.167.100.100 |
|fd00:cafe:cafe:100::100|
+-----------------------+
```


Expand Down
18 changes: 16 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ services:
networks:
leftnet:
ipv4_address: 193.167.0.2
ipv6_address: fd00:cafe:cafe:0::2
rightnet:
ipv4_address: 193.167.100.2
ipv6_address: fd00:cafe:cafe:100::2

server:
build: ./$SERVER
Expand All @@ -40,8 +42,12 @@ services:
networks:
rightnet:
ipv4_address: 193.167.100.100
ipv6_address: fd00:cafe:cafe:100::100
extra_hosts:
- "client:193.167.0.100"
- "client4:193.167.0.100"
- "client6:fd00:cafe:cafe:0::100"
- "client46:193.167.0.100"
- "client46:fd00:cafe:cafe:0::100"

client:
build: ./$CLIENT
Expand All @@ -62,21 +68,29 @@ services:
networks:
leftnet:
ipv4_address: 193.167.0.100
ipv6_address: fd00:cafe:cafe:0::100
extra_hosts:
- "server:193.167.100.100"
- "server4:193.167.100.100"
- "server6:fd00:cafe:cafe:100::100"
- "server46:193.167.100.100"
- "server46:fd00:cafe:cafe:100::100"

networks:
leftnet:
driver: bridge
driver_opts:
com.docker.network.bridge.enable_ip_masquerade: 'false'
enable_ipv6: true
ipam:
config:
- subnet: 193.167.0.0/24
- subnet: fd00:cafe:cafe:0::/64
rightnet:
driver: bridge
driver_opts:
com.docker.network.bridge.enable_ip_masquerade: 'false'
enable_ipv6: true
ipam:
config:
- subnet: 193.167.100.0/24
- subnet: fd00:cafe:cafe:100::/64
2 changes: 1 addition & 1 deletion endpoint/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
FROM ubuntu:20.04

RUN apt-get update && \
apt-get install -y wget net-tools iputils-ping tcpdump ethtool iperf
apt-get install -y wget net-tools iputils-ping tcpdump ethtool iperf iproute2

COPY setup.sh .
RUN chmod +x setup.sh
Expand Down
12 changes: 12 additions & 0 deletions endpoint/setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,25 @@ echo "Setting up routes..."
# This command makes sure that the endpoints set the checksum on outgoing packets.
ethtool -K eth0 tx off

# this relies on the IPv4 address being first in the "hostname -I" output
IP=`hostname -I`
GATEWAY="${IP%.*}.2"
UNNEEDED_ROUTE="${IP%.*}.0"
echo "Endpoint's IPv4 address is $IP"

route add -net 193.167.0.0 netmask 255.255.0.0 gw $GATEWAY
# delete unused route
route del -net $UNNEEDED_ROUTE netmask 255.255.255.0

# this relies on the IPv6 address being second in the "hostname -I" output
IP=$(echo "$IP" | cut -f2 -d" ")
GATEWAY="${IP%:*}:2"
UNNEEDED_ROUTE="${IP%:*}:"
echo "Endpoint's IPv6 address is $IP"

ip -d route add fd00:cafe:cafe::/48 via $GATEWAY
# delete unused route
ip -d route del $UNNEEDED_ROUTE/64

# create the /logs and the /logs/qlog directory
mkdir -p /logs/qlog
2 changes: 2 additions & 0 deletions sim/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ ifconfig eth1 promisc
# Drop those to make sure they actually take the path through ns3.
iptables -A FORWARD -i eth0 -o eth1 -j DROP
iptables -A FORWARD -i eth1 -o eth0 -j DROP
ip6tables -A FORWARD -i eth0 -o eth1 -j DROP
ip6tables -A FORWARD -i eth1 -o eth0 -j DROP

if [[ -n "$WAITFORSERVER" ]]; then
wait-for-it-quic -t 10s $WAITFORSERVER
Expand Down
3 changes: 0 additions & 3 deletions sim/scenarios/blackhole/blackhole.cc
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,6 @@ int main(int argc, char *argv[]) {
p2p.SetQueueSize(StringValue(queue + "p"));

NetDeviceContainer devices = p2p.Install(sim.GetLeftNode(), sim.GetRightNode());
Ipv4AddressHelper ipv4;
ipv4.SetBase("193.167.50.0", "255.255.255.0");
Ipv4InterfaceContainer interfaces = ipv4.Assign(devices);

Ptr<BlackholeErrorModel> em = CreateObject<BlackholeErrorModel>();
em->Disable();
Expand Down
3 changes: 0 additions & 3 deletions sim/scenarios/corrupt-rate/corrupt-rate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,6 @@ int main(int argc, char *argv[]) {
p2p.SetQueueSize(StringValue(queue + "p"));

NetDeviceContainer devices = p2p.Install(sim.GetLeftNode(), sim.GetRightNode());
Ipv4AddressHelper ipv4;
ipv4.SetBase("193.167.50.0", "255.255.255.0");
Ipv4InterfaceContainer interfaces = ipv4.Assign(devices);

devices.Get(0)->SetAttribute("ReceiveErrorModel", PointerValue(client_corrupts));
devices.Get(1)->SetAttribute("ReceiveErrorModel", PointerValue(server_corrupts));
Expand Down
5 changes: 1 addition & 4 deletions sim/scenarios/drop-rate/drop-rate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,7 @@ int main(int argc, char *argv[]) {
p2p.SetQueueSize(StringValue(queue + "p"));

NetDeviceContainer devices = p2p.Install(sim.GetLeftNode(), sim.GetRightNode());
Ipv4AddressHelper ipv4;
ipv4.SetBase("193.167.50.0", "255.255.255.0");
Ipv4InterfaceContainer interfaces = ipv4.Assign(devices);


devices.Get(0)->SetAttribute("ReceiveErrorModel", PointerValue(client_drops));
devices.Get(1)->SetAttribute("ReceiveErrorModel", PointerValue(server_drops));

Expand Down
3 changes: 0 additions & 3 deletions sim/scenarios/droplist/droplist.cc
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,6 @@ int main(int argc, char *argv[]) {
p2p.SetQueueSize(StringValue(queue + "p"));

NetDeviceContainer devices = p2p.Install(sim.GetLeftNode(), sim.GetRightNode());
Ipv4AddressHelper ipv4;
ipv4.SetBase("193.167.50.0", "255.255.255.0");
Ipv4InterfaceContainer interfaces = ipv4.Assign(devices);

devices.Get(0)->SetAttribute("ReceiveErrorModel", PointerValue(client_drops));
devices.Get(1)->SetAttribute("ReceiveErrorModel", PointerValue(server_drops));
Expand Down
42 changes: 36 additions & 6 deletions sim/scenarios/helper/quic-network-simulator-helper.cc
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#include <cassert>
#include <csignal>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

Expand All @@ -21,7 +22,7 @@ void onSignal(int signum) {
NS_FATAL_ERROR(signum);
}

void installNetDevice(Ptr<Node> node, std::string deviceName, Mac48AddressValue macAddress, Ipv4InterfaceAddress ipv4Address) {
void installNetDevice(Ptr<Node> node, std::string deviceName, Mac48AddressValue macAddress, Ipv4InterfaceAddress ipv4Address, Ipv6InterfaceAddress ipv6Address) {
EmuFdNetDeviceHelper emu;
emu.SetDeviceName(deviceName);
NetDeviceContainer devices = emu.Install(node);
Expand All @@ -33,6 +34,13 @@ void installNetDevice(Ptr<Node> node, std::string deviceName, Mac48AddressValue
ipv4->AddAddress(interface, ipv4Address);
ipv4->SetMetric(interface, 1);
ipv4->SetUp(interface);

Ptr<Ipv6> ipv6 = node->GetObject<Ipv6>();
ipv6->SetAttribute("IpForward", BooleanValue(true));
interface = ipv6->AddInterface(device);
ipv6->AddAddress(interface, ipv6Address);
ipv6->SetMetric(interface, 1);
ipv6->SetUp(interface);
}

QuicNetworkSimulatorHelper::QuicNetworkSimulatorHelper() {
Expand All @@ -47,8 +55,24 @@ QuicNetworkSimulatorHelper::QuicNetworkSimulatorHelper() {
left_node_ = nodes.Get(0);
right_node_ = nodes.Get(1);

installNetDevice(left_node_, "eth0", Mac48AddressValue("02:51:55:49:43:00"), Ipv4InterfaceAddress("193.167.0.2", "255.255.255.0"));
installNetDevice(right_node_, "eth1", Mac48AddressValue("02:51:55:49:43:01"), Ipv4InterfaceAddress("193.167.100.2", "255.255.255.0"));
installNetDevice(left_node_, "eth0", Mac48AddressValue("02:51:55:49:43:00"), Ipv4InterfaceAddress("193.167.0.2", "255.255.255.0"), Ipv6InterfaceAddress("fd00:cafe:cafe:0::2", 64));
installNetDevice(right_node_, "eth1", Mac48AddressValue("02:51:55:49:43:01"), Ipv4InterfaceAddress("193.167.100.2", "255.255.255.0"), Ipv6InterfaceAddress("fd00:cafe:cafe:100::2", 64));
}

void massageIpv6Routing(Ptr<Node> local, Ptr<Node> peer) {
Ptr<Ipv6StaticRouting> routing = Ipv6RoutingHelper::GetRouting<Ipv6StaticRouting>(local->GetObject<Ipv6>()->GetRoutingProtocol());
Ptr<Ipv6> peer_ipv6 = peer->GetObject<Ipv6>();
Ipv6Address dst;
for (uint32_t i = 0; i < peer_ipv6->GetNInterfaces(); i++)
for (uint32_t j = 0; j < peer_ipv6->GetNAddresses(i); j++)
if (peer_ipv6->GetAddress(i, j).GetAddress().CombinePrefix(64) == "fd00:cafe:cafe:50::") {
dst = peer_ipv6->GetAddress(i, j).GetAddress();
goto done;
}

done:
assert(dst.IsInitialized());
routing->SetDefaultRoute(dst, 2);
}

void QuicNetworkSimulatorHelper::Run(Time duration) {
Expand All @@ -57,9 +81,15 @@ void QuicNetworkSimulatorHelper::Run(Time duration) {
signal(SIGKILL, onSignal);

Ipv4GlobalRoutingHelper::PopulateRoutingTables();

// Ipv6GlobalRoutingHelper does not exist - fake it
massageIpv6Routing(left_node_, right_node_);
massageIpv6Routing(right_node_, left_node_);

// write the routing table to file
Ptr<OutputStreamWrapper> routingStream = Create<OutputStreamWrapper>("dynamic-global-routing.routes", std::ios::out);
Ipv4RoutingHelper::PrintRoutingTableAllAt(Seconds(0.), routingStream);
Ipv6RoutingHelper::PrintRoutingTableAllAt(Seconds(0.), routingStream);

Simulator::Stop(duration);
RunSynchronizer();
Expand All @@ -74,8 +104,8 @@ void QuicNetworkSimulatorHelper::RunSynchronizer() const {
struct sockaddr_in addr;
bzero((char *) &addr, sizeof(addr));

addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(57832);

int res = bind(sockfd, (struct sockaddr *) &addr, sizeof(addr));
Expand Down
10 changes: 10 additions & 0 deletions sim/scenarios/helper/quic-point-to-point-helper.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "ns3/core-module.h"
#include "ns3/traffic-control-helper.h"
#include "ns3/ipv4-address-helper.h"
#include "ns3/ipv6-address-helper.h"
#include "quic-point-to-point-helper.h"

using namespace ns3;
Expand All @@ -22,5 +24,13 @@ NetDeviceContainer QuicPointToPointHelper::Install(Ptr<Node> a, Ptr<Node> b) {
tch.SetRootQueueDisc("ns3::PfifoFastQueueDisc", "MaxSize", queue_size_);
tch.Install(devices);

Ipv4AddressHelper ipv4;
ipv4.SetBase("193.167.50.0", "255.255.255.0");
ipv4.Assign(devices);

Ipv6AddressHelper ipv6;
ipv6.SetBase("fd00:cafe:cafe:50::", 64);
ipv6.Assign(devices);

return devices;
}
3 changes: 0 additions & 3 deletions sim/scenarios/rebind/rebind.cc
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,6 @@ int main(int argc, char *argv[]) {

NetDeviceContainer devices =
p2p.Install(sim.GetLeftNode(), sim.GetRightNode());
Ipv4AddressHelper ipv4;
ipv4.SetBase("193.167.50.0", "255.255.255.0");
Ipv4InterfaceContainer interfaces = ipv4.Assign(devices);

Ptr<RebindErrorModel> em = CreateObject<RebindErrorModel>();
em->SetRebindAddr(rebind_addr);
Expand Down
3 changes: 0 additions & 3 deletions sim/scenarios/simple-p2p/simple-p2p.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,6 @@ int main(int argc, char *argv[]) {
p2p.SetQueueSize(StringValue(queue + "p"));

NetDeviceContainer devices = p2p.Install(sim.GetLeftNode(), sim.GetRightNode());
Ipv4AddressHelper ipv4;
ipv4.SetBase("193.167.50.0", "255.255.255.0");
Ipv4InterfaceContainer interfaces = ipv4.Assign(devices);

sim.Run(Seconds(36000));
}
3 changes: 0 additions & 3 deletions sim/scenarios/tcp-cross-traffic/tcp-cross-traffic.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,6 @@ int main(int argc, char *argv[]) {
p2p.SetQueueSize(StringValue(queue + "p"));

NetDeviceContainer devices = p2p.Install(sim.GetLeftNode(), sim.GetRightNode());
Ipv4AddressHelper ipv4;
ipv4.SetBase("193.167.50.0", "255.255.255.0");
Ipv4InterfaceContainer interfaces = ipv4.Assign(devices);

NodeContainer nodes;
nodes.Create(2);
Expand Down

0 comments on commit 41dea6c

Please sign in to comment.