|
|
|
@@ -14,7 +14,7 @@ would be in a single pod of a fat tree topology.
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
Switch s1 will be configured with a P4 program that implements a
|
|
|
|
|
simple stateful firewall (`firewall.p4`), the rest of the switches will run the
|
|
|
|
|
simple stateful firewall (`firewall.p4`), the rest of the switches will run the
|
|
|
|
|
basic IPv4 router program (`basic.p4`) from the previous exercise.
|
|
|
|
|
|
|
|
|
|
The firewall on s1 should have the following functionality:
|
|
|
|
@@ -62,21 +62,21 @@ up a switch in Mininet to test its behavior.
|
|
|
|
|
[pod-topo/topology.json](./pod-topo/topology.json)
|
|
|
|
|
|
|
|
|
|
2. You should now see a Mininet command prompt. Try to run some iperf
|
|
|
|
|
TCP flows between the hosts. TCP flows within the internal
|
|
|
|
|
TCP flows between the hosts. TCP flows within the internal
|
|
|
|
|
network should work:
|
|
|
|
|
```bash
|
|
|
|
|
mininet> iperf h1 h2
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
TCP flows from hosts in the internal network to the outside hosts
|
|
|
|
|
TCP flows from hosts in the internal network to the outside hosts
|
|
|
|
|
should also work:
|
|
|
|
|
```bash
|
|
|
|
|
mininet> iperf h1 h3
|
|
|
|
|
```
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
TCP flows from the outside hosts to hosts inside the
|
|
|
|
|
internal network should NOT work. However, since the firewall is not
|
|
|
|
|
implemented yet, the following should work:
|
|
|
|
|
TCP flows from the outside hosts to hosts inside the
|
|
|
|
|
internal network should NOT work. However, since the firewall is not
|
|
|
|
|
implemented yet, the following should work:
|
|
|
|
|
```bash
|
|
|
|
|
mininet> iperf h3 h1
|
|
|
|
|
```
|
|
|
|
@@ -118,11 +118,11 @@ logic replaced by `TODO` comments. Your implementation should follow
|
|
|
|
|
the structure given in this file --- replace each `TODO` with logic
|
|
|
|
|
implementing the missing piece.
|
|
|
|
|
|
|
|
|
|
**High-level Approach:** We will use a bloom filter with two hash functions
|
|
|
|
|
to check if a packet coming into the internal network is a part of
|
|
|
|
|
an already established TCP connection. We will use two different register
|
|
|
|
|
arrays for the bloom filter, each to be updated by a hash function.
|
|
|
|
|
Using different register arrays makes our design amenable to high-speed
|
|
|
|
|
**High-level Approach:** We will use a bloom filter with two hash functions
|
|
|
|
|
to check if a packet coming into the internal network is a part of
|
|
|
|
|
an already established TCP connection. We will use two different register
|
|
|
|
|
arrays for the bloom filter, each to be updated by a hash function.
|
|
|
|
|
Using different register arrays makes our design amenable to high-speed
|
|
|
|
|
P4 targets that typically allow only one access to a register array per packet.
|
|
|
|
|
|
|
|
|
|
A complete `firewall.p4` will contain the following components:
|
|
|
|
@@ -130,32 +130,32 @@ A complete `firewall.p4` will contain the following components:
|
|
|
|
|
1. Header type definitions for Ethernet (`ethernet_t`), IPv4 (`ipv4_t`) and TCP (`tcp_t`).
|
|
|
|
|
2. Parsers for Ethernet, IPv4 and TCP that populate `ethernet_t`, `ipv4_t` and `tcp_t` fields.
|
|
|
|
|
3. An action to drop a packet, using `mark_to_drop()`.
|
|
|
|
|
4. An action (called `compute_hashes`) to compute the bloom filter's two hashes using hash
|
|
|
|
|
algorithms `crc16` and `crc32`. The hashes will be computed on the packet 5-tuple consisting
|
|
|
|
|
of IPv4 source and destination addresses, source and destination port numbers and
|
|
|
|
|
4. An action (called `compute_hashes`) to compute the bloom filter's two hashes using hash
|
|
|
|
|
algorithms `crc16` and `crc32`. The hashes will be computed on the packet 5-tuple consisting
|
|
|
|
|
of IPv4 source and destination addresses, source and destination port numbers and
|
|
|
|
|
the IPv4 protocol type.
|
|
|
|
|
5. An action (`ipv4_forward`) and a table (`ipv4_lpm`) that will perform basic
|
|
|
|
|
5. An action (`ipv4_forward`) and a table (`ipv4_lpm`) that will perform basic
|
|
|
|
|
IPv4 forwarding (adopted from `basic.p4`).
|
|
|
|
|
6. An action (called `set_direction`) that will simply set a one-bit direction variable
|
|
|
|
|
6. An action (called `set_direction`) that will simply set a one-bit direction variable
|
|
|
|
|
as per the action's parameter.
|
|
|
|
|
7. A table (called `check_ports`) that will read the ingress and egress port of a packet
|
|
|
|
|
(after IPv4 forwarding) and invoke `set_direction`. The direction will be set to `1`,
|
|
|
|
|
7. A table (called `check_ports`) that will read the ingress and egress port of a packet
|
|
|
|
|
(after IPv4 forwarding) and invoke `set_direction`. The direction will be set to `1`,
|
|
|
|
|
if the packet is incoming into the internal network. Otherwise, the direction will be set to `0`.
|
|
|
|
|
To achieve this, the file `pod-topo/s1-runtime.json` contains the appropriate control plane
|
|
|
|
|
entries for the `check_ports` table.
|
|
|
|
|
8. A control that will:
|
|
|
|
|
1. First apply the table `ipv4_lpm` if the packet has a valid IPv4 header.
|
|
|
|
|
2. Then if the TCP header is valid, apply the `check_ports` table to determine the direction.
|
|
|
|
|
3. Apply the `compute_hashes` action to compute the two hash values which are the bit positions
|
|
|
|
|
in the two register arrays of the bloom filter (`reg_pos_one` and `reg_pos_two`).
|
|
|
|
|
When the direction is `1` i.e. the packet is incoming into the internal network,
|
|
|
|
|
`compute_hashes` will be invoked by swapping the source and destination IPv4 addresses
|
|
|
|
|
and the source and destination ports. This is to check against bloom filter's set bits
|
|
|
|
|
3. Apply the `compute_hashes` action to compute the two hash values which are the bit positions
|
|
|
|
|
in the two register arrays of the bloom filter (`reg_pos_one` and `reg_pos_two`).
|
|
|
|
|
When the direction is `1` i.e. the packet is incoming into the internal network,
|
|
|
|
|
`compute_hashes` will be invoked by swapping the source and destination IPv4 addresses
|
|
|
|
|
and the source and destination ports. This is to check against bloom filter's set bits
|
|
|
|
|
when the TCP connection was initially made from the internal network.
|
|
|
|
|
4. **TODO:** If the TCP packet is going out of the internal network and is a SYN packet,
|
|
|
|
|
set both the bloom filter arrays at the computed bit positions (`reg_pos_one` and `reg_pos_two`).
|
|
|
|
|
Else, if the TCP packet is entering the internal network,
|
|
|
|
|
read both the bloom filter arrays at the computed bit positions and drop the packet if
|
|
|
|
|
4. **TODO:** If the TCP packet is going out of the internal network and is a SYN packet,
|
|
|
|
|
set both the bloom filter arrays at the computed bit positions (`reg_pos_one` and `reg_pos_two`).
|
|
|
|
|
Else, if the TCP packet is entering the internal network,
|
|
|
|
|
read both the bloom filter arrays at the computed bit positions and drop the packet if
|
|
|
|
|
either is not set.
|
|
|
|
|
9. A deparser that emits the Ethernet, IPv4 and TCP headers in the right order.
|
|
|
|
|
10. A `package` instantiation supplied with the parser, control, and deparser.
|
|
|
|
@@ -171,18 +171,18 @@ h3 and h1 should be blocked by the firewall.
|
|
|
|
|
|
|
|
|
|
### Food for thought
|
|
|
|
|
|
|
|
|
|
You may have noticed that in this simple stateful firewall, we are adding
|
|
|
|
|
new TCP connections to the bloom filter (based on outgoing SYN packets).
|
|
|
|
|
However, we are not removing them in case of TCP connection teardown
|
|
|
|
|
(FIN packets). How would you implement the removal of TCP connections that are
|
|
|
|
|
You may have noticed that in this simple stateful firewall, we are adding
|
|
|
|
|
new TCP connections to the bloom filter (based on outgoing SYN packets).
|
|
|
|
|
However, we are not removing them in case of TCP connection teardown
|
|
|
|
|
(FIN packets). How would you implement the removal of TCP connections that are
|
|
|
|
|
no longer active?
|
|
|
|
|
|
|
|
|
|
Things to consider:
|
|
|
|
|
- Can we simply set the bloom filter array bits to `0` on
|
|
|
|
|
receiving a FIN packet? What happens when there is one hash collision in
|
|
|
|
|
Things to consider:
|
|
|
|
|
- Can we simply set the bloom filter array bits to `0` on
|
|
|
|
|
receiving a FIN packet? What happens when there is one hash collision in
|
|
|
|
|
the bloom filter arrays between two _active_ TCP connections?
|
|
|
|
|
- How can we modify our bloom filter structure so that the deletion
|
|
|
|
|
operation can be properly supported?
|
|
|
|
|
- How can we modify our bloom filter structure so that the deletion
|
|
|
|
|
operation can be properly supported?
|
|
|
|
|
|
|
|
|
|
### Troubleshooting
|
|
|
|
|
|
|
|
|
|