Commit 7fdd551b authored by Thomas Holterbach's avatar Thomas Holterbach
Browse files
parents 454d4bcb 530792f6
......@@ -241,6 +241,8 @@ Only requirements from [PyPI][pypi] are allowed, i.e. requirements that you can
[pypi]: https://pypi.org
## Building the topology and running scenarios
To make operating the network with routers, switches, and a controller as easy as possible, we have prepared the script `cli.sh` for you.
......@@ -459,41 +461,42 @@ If you do not specify a traffic scenario, the `default` scenario is used.
Runs traffic and failure scenarios. The arguments are the same as for `run-pipeline`.
## Frequently Asked Questions (FAQ)
**Which links can fail in the network?**
#### Which links can fail in the network?
All the links but the ones between the switches and the hosts.
**Are we allowed to use `ovs-vsctl` to check if a link is up or down?**
#### Are we allowed to use `ovs-vsctl` to check if a link is up or down?
No. We give more detail in this [section](#controller) of the README.
**Are we allowed to configure the hosts?**
#### Are we allowed to configure the hosts?
No. And if you do so, your host configuration will not be used when we will run your solution on our server. You can only configure your network via the configuration files available in the `configuration` directory.
**Does the packet reception rate (PRR) take into account reordering?**
#### Does the packet reception rate (PRR) take into account reordering?
No, it does not.
**The controller returns an error when I want to use P4 digests.**
#### The controller returns an error when I want to use P4 digests.
This is because the optimized switch is compiled with the digest capability disabled.
Fortunately, you can still use `copy_to_cpu` to send message from the data plane to the control plane. We show how to use `copy_to_cpu` in this [example](https://github.com/nsg-ethz/p4-learning/tree/master/examples/copy_to_cpu).
**Can you install iperf on the hosts?**
#### Can you install iperf on the hosts?
You should use `iperf3` instead of `iperf`, it is installed on all the hosts as well as the routers and switches.
**A ping with TOS set to 128 (`ping -Q 128 1.0.0.2`) returns an error.**
#### A ping with TOS set to 128 (`ping -Q 128 1.0.0.2`) returns an error.
You can use `ping -Q 0x80`, this should work just fine.
**I can't reach the expected bandwidth with `iperf3` and UDP traffic.**
#### I can't reach the expected bandwidth with `iperf3` and UDP traffic.
This is the expected behavior. The problem with `iperf3` is that it sends sequences of bursts of UDP packets, instead of sending UDP packets constantly. Because of that, the queues used in the devices will quickly become full upon a burst of UDP packets, and many packets will then be dropped.
If you want to measure the available bandwidth with UDP traffic, we provide the `udp.py` script that is available on every host in the `/home` directory.
If you want to measure the available bandwidth with UDP traffic, we provide the `upd.py` script that is available on every host in the `/home` directory.
You can start a UDP flow sending 4Mbps during 5sec with the following command.
```
......@@ -502,7 +505,7 @@ python3 -i udp.py
```
Here, the packets will have a size of 1500 bytes, and will be sent one by one (batch_size=1).
If you want to see how many packets arrived, you can run the following command on the destination node, where the first parameter is the source IP and the second parameter is the destination port.
If you want to see how many packets arrived=, you can run the following command one the destination node, where the first parameter is the source IP and the second parameter is the destination port.
```
python3 -i udp.py
......@@ -511,7 +514,8 @@ python3 -i udp.py
Then with `ctrl+c` you can see the number of received packets.
**Iperf3 does not set the TOS field correctly.**
#### Iperf3 does not set the TOS field correctly.
`iperf3` can only use TOS values that are multiple of 4 (with the option `-S` or `--tos`). If you want to use a TOS value that is not multiple of 4, you can use the `udp.py` script that we provide with the `tos` option on the sender side. For instance if you want to use a TOS of 27:
......@@ -520,13 +524,52 @@ python3 -i udp.py
>>> send_udp_flow("2.0.0.1", rate="4M", duration=5, packet_size=1500, batch_size=1, tos=27)
```
#### How can I configure feature X from the lecture in FRRouting?
FRRouting does not support everything you have seen during the lecture, or some features that you have seen in configuration examples for real routers. Check the [FRRouting Documentation](http://docs.frrouting.org/en/latest/index.html) to see which features are available. To safe yourselves some time searching, we collect known limitations below:
OSPF does not support LFAs (loop-free alternates).
#### The routers do not forward MPLS packets although I have configured them to do so.
In the MPLS exercise, we used `0x8848` for the ethertype, which means `MPLS multicast label switched packet`. Actually, you need to use instead the ethertype `0x8847`, which means `MPLS label switched packet`, otherwise the routers will not process the MPLS packets. We have updated the MPLS exercise solution, but make sure to also update your P4 code.
#### Why can't I clasisfy packets at switch nodes
Switch nodes run `bmv2` (the p4 switch software implementation) which sends and receives packets from the interfaces
using `libpcap` and uses binds using `raw` sockets and `ETH_P_ALL`. That makes `iptables` not to intercept any packet. Furthermore, and more importantly for us when using the `tc filter` we can not match to `protocol ip` anymore since the packet protocol is unknown by the underlying structures. Thus, to make `tc filter` in our switch interfaces we have to replace:
Does not work:
`tc filter add dev intf parent 1: protocol ip prio 1 u32 match ip dsfield 1 0xff flowid 1:10`
Works:
`tc filter add dev intf parent 1: protocol all prio 1 u32 match ip dsfield 1 0xff flowid 1:10`
#### Why I don't get the expected results when using TC even though I think I did it all correct?
When trying to do `tc` it is very important you also rate limit the traffic to the interface maximum, otherwise your priorities, fair queueing, etc wont work. Why so? your device interfaces have “unlimited” bw, we do all the rate limiting in some middle nodes we added. Thus, if you use priorities or Fair queueing packets are dequeued so fast that its like having nothing, therefore you must rate limit at the same time you use priorities, or other things.
**Important:** if you use `htb` make sure the sum of children `rates` does not exceed the parent `rate` otherwise child nodes will be able to send above the limit. Futhremore, remember that the `rate` is just the guaranteed `rate` for a given class, you can set the sum of rates to be at max the parent `rate` (or link bw) or you can set it to a lower number. This is very important to avoid lower prioity traffic to steal some bandwidth to higher priority traffic classes.
#### What I am allowed to send from the switch to the controller and viceversa?
You can send any packet or clone/mirror packets to the controller as much as you want with only one limitation. You are not allowed to buffer normal traffic in the controller and then inject it back to the network. Also you are not allowed to use the controller as a forwarding node. For example forwarding normal traffic like `S1->Controller->S6`.
You are allowed to inject as many packets (be careful with cpu and bandwidth usage) from the controller to switches. You can use those packets to either `clock` the switches or make switches forward them somewhere.
#### How can I send packets from the switch without being blocked?
To send packets to the controller you can either forward a packet to the cpu port (but then you lose that traffic packet)
or you clone a packet. You can find an example here https://github.com/nsg-ethz/p4-learning/tree/master/exercises/04-L2_Learning. You can see that to receive packets we use `scapy` and the `sniff` function https://github.com/nsg-ethz/p4-learning/blob/master/exercises/04-L2_Learning/solution/l2_learning_controller.py#L123. You are free to use that or any other function or python library to get packets from interfaces. However, keep in mind that `sniff` will block your programm execution. You can either listent to multiple interfaces at the same time or you can use `Threads` to deal with all the switches in parallel.
**How can I configure feature X from the lecture in FRRouting?**
#### How can I get a switch cpu port name ?
FRRouting does not support everything you have seen during the lecture, or some features that you have seen in configuration examples for real routers. Check the [FRRouting Documentation](http://docs.frrouting.org/en/latest/index.html) to see which features are available. To save yourselves some time searching, we collect known limitations below:
- OSPF does not support LFAs (loop-free alternates).
For that use the topology object, you can either use `topo.get_cpu_port_intf(sw_name)` or `topo.get_ctl_cpu_intf(sw_name)`.
#### How can I send packets from the controller to the switch ?
**The routers do not forward MPLS packets although I have configured them to do so.**
To send packets from the controller to the switch you need to `inject` raw packets to the respective switch
`cpu` port interface. To get the name use the topology object.
In the MPLS exercise, we used `0x8848` for the ethertype, which means `MPLS multicast label switched packet`. Actually, you need to use instead the ethertype `0x8847`, which means `MPLS label switched packet`, otherwise the routers will not proces the packet. We have updated the MPLS exercise solution, but make sure to also update your P4 code.
\ No newline at end of file
You can send packets using any python tool/library that allows sending `raw` packets. You can use `scapy`, `raw` linux sockets. For simplicity, we recommend
you to use `scapy` and the `sendp` function (https://0xbharath.github.io/art-of-packet-crafting-with-scapy/scapy/sending_recieving/index.html). However, if you need
more performance you can use python raw sockets (https://sira.dev/2019/06/24/layer-2-socket-programming.html).
\ No newline at end of file
......@@ -138,7 +138,7 @@ function start-switches
function controller
{
if [ $# -ne 1 ]; then
if [ $# -lt 1 ]; then
traffic="default"
else
traffic=$1
......
src, dst, sport, dport, tos, rate, duration, packet_size, start_time
h1, h2, 5000, 5001, 128, 1M, 50, 1500, 5
h2, h3, 5000, 5002, 64, 6M, 50, 1500, 5
h3, h4, 5000, 5003, 64, 6M, 50, 1500, 5
h4, h5, 5000, 5004, 32, 12M, 50, 1500, 5
h5, h6, 5000, 5005, 32, 12M, 50, 1500, 5
h6, h1, 5000, 5006, 32, 12M, 50, 1500, 5
h1, h2, 5000, 5001, 128, 1M, 50, 1450, 5
h2, h3, 5000, 5002, 64, 6M, 50, 1450, 5
h3, h4, 5000, 5003, 64, 6M, 50, 1450, 5
h4, h5, 5000, 5004, 32, 12M, 50, 1450, 5
h5, h6, 5000, 5005, 32, 12M, 50, 1450, 5
h6, h1, 5000, 5006, 32, 12M, 50, 1450, 5
src, dst, sport, dport, tos, rate, duration, packet_size, start_time
h2, h3,5000, 5001, 128, 1M, 50, 1500, 5
h5, h2, 5000, 5002, 64, 6M, 50, 1500, 5
h6, h4, 5000, 5003, 64, 6M, 50, 1500, 5
h4, h6, 5000, 5004, 32, 12M, 50, 1500, 5
h1, h5, 5000, 5005, 32, 12M, 50, 1500, 5
h3, h1, 5000, 5006, 32, 12M, 50, 1500, 5
h2, h3,5000, 5001, 128, 1M, 50, 1450, 5
h5, h2, 5000, 5002, 64, 6M, 50, 1450, 5
h6, h4, 5000, 5003, 64, 6M, 50, 1450, 5
h4, h6, 5000, 5004, 32, 12M, 50, 1450, 5
h1, h5, 5000, 5005, 32, 12M, 50, 1450, 5
h3, h1, 5000, 5006, 32, 12M, 50, 1450, 5
src, dst, sport, dport, tos, rate, duration, packet_size, start_time
h6, h2, 5000, 5001, 128, 1M, 50, 1500, 5
h2, h4, 5000, 5002, 64, 6M, 50, 1500, 5
h1, h3, 5000, 5003, 64, 6M, 50, 1500, 5
h3, h5, 5000, 5004, 32, 12M, 50, 1500, 5
h4, h6, 5000, 5005, 32, 12M, 50, 1500, 5
h5, h1, 5000, 5006, 32, 12M, 50, 1500, 5
h6, h2, 5000, 5001, 128, 1M, 50, 1450, 5
h2, h4, 5000, 5002, 64, 6M, 50, 1450, 5
h1, h3, 5000, 5003, 64, 6M, 50, 1450, 5
h3, h5, 5000, 5004, 32, 12M, 50, 1450, 5
h4, h6, 5000, 5005, 32, 12M, 50, 1450, 5
h5, h1, 5000, 5006, 32, 12M, 50, 1450, 5
src, dst, sport, dport, tos, rate, duration, packet_size, start_time
h1, h4, 5000, 5001, 128, 1M, 50, 1500, 5
h2, h5, 5000, 5002, 64, 6M, 50, 1500, 5
h3, h6, 5000, 5003, 64, 6M, 50, 1500, 5
h4, h1, 5000, 5004, 32, 12M, 50, 1500, 5
h5, h2, 5000, 5005, 32, 12M, 50, 1500, 5
h6, h3, 5000, 5006, 32, 12M, 50, 1500, 5
h1, h4, 5000, 5001, 128, 1M, 50, 1450, 5
h2, h5, 5000, 5002, 64, 6M, 50, 1450, 5
h3, h6, 5000, 5003, 64, 6M, 50, 1450, 5
h4, h1, 5000, 5004, 32, 12M, 50, 1450, 5
h5, h2, 5000, 5005, 32, 12M, 50, 1450, 5
h6, h3, 5000, 5006, 32, 12M, 50, 1450, 5
src, dst, sport, dport, tos, rate, duration, packet_size, start_time
h1, h4, 5000, 5001, 128, 12M, 50, 1500, 5
h2, h5, 5000, 5002, 64, 12M, 50, 1500, 5
h3, h6, 5000, 5003, 64, 12M, 50, 1500, 5
h4, h1, 5000, 5004, 32, 12M, 50, 1500, 5
h5, h2, 5000, 5005, 32, 12M, 50, 1500, 5
h6, h3, 5000, 5006, 32, 12M, 50, 1500, 5
h1, h4, 5000, 5001, 128, 12M, 50, 1450, 5
h2, h5, 5000, 5002, 64, 12M, 50, 1450, 5
h3, h6, 5000, 5003, 64, 12M, 50, 1450, 5
h4, h1, 5000, 5004, 32, 12M, 50, 1450, 5
h5, h2, 5000, 5005, 32, 12M, 50, 1450, 5
h6, h3, 5000, 5006, 32, 12M, 50, 1450, 5
src, dst, sport, dport, tos, rate, duration, packet_size, start_time
h1, h4, 6001, 5001, 32, 6M, 50, 1500, 5
h2, h5, 6001, 5002, 64, 6M, 50, 1500, 5
h3, h6, 6001, 5003, 64, 6M, 50, 1500, 5
h4, h1, 6001, 5004, 32, 6M, 50, 1500, 5
h5, h2, 6001, 5005, 32, 6M, 50, 1500, 5
h6, h3, 6001, 5006, 32, 4M, 50, 1500, 5
h1, h4, 6002, 5007, 32, 6M, 50, 1500, 5
h2, h5, 6002, 5008, 32, 6M, 50, 1500, 5
h3, h6, 6002, 5009, 32, 6M, 50, 1500, 5
h4, h1, 6002, 5010, 64, 6M, 50, 1500, 5
h5, h2, 6002, 5011, 64, 6M, 50, 1500, 5
h6, h3, 6002, 5012, 128, 1M, 50, 1500, 5
h1, h4, 6001, 5001, 32, 6M, 50, 1450, 5
h2, h5, 6001, 5002, 64, 6M, 50, 1450, 5
h3, h6, 6001, 5003, 64, 6M, 50, 1450, 5
h4, h1, 6001, 5004, 32, 6M, 50, 1450, 5
h5, h2, 6001, 5005, 32, 6M, 50, 1450, 5
h6, h3, 6001, 5006, 32, 4M, 50, 1450, 5
h1, h4, 6002, 5007, 32, 6M, 50, 1450, 5
h2, h5, 6002, 5008, 32, 6M, 50, 1450, 5
h3, h6, 6002, 5009, 32, 6M, 50, 1450, 5
h4, h1, 6002, 5010, 64, 6M, 50, 1450, 5
h5, h2, 6002, 5011, 64, 6M, 50, 1450, 5
h6, h3, 6002, 5012, 128, 1M, 50, 1450, 5
......@@ -82,6 +82,8 @@ class AppRunner(object):
print("Starting P4 switch {}.\n".format(switch_name))
args = [self.switch_bin]
for intf_name, port_num in self.topo.get_interfaces_to_port(switch_name).items():
if 'cpu' in intf_name:
intf_name = "switch-cpu"
args.extend(["-i", str(port_num)+"@"+intf_name])
shared_base_path = HOSTS_SHARED_PATH
......
......@@ -220,7 +220,7 @@ class MiniInternetTopoBuilder(object):
interfaces_to_node[intf_name] = host_name
if node_type == "switch":
interfaces_to_port["switch-cpu"] = intf_index
interfaces_to_port[nodes[node]["ctl_cpu_intf"]] = intf_index
nodes[node]["interfaces_to_port"] = interfaces_to_port
nodes[node]["interfaces_to_node"] = interfaces_to_node
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment