Examples - UofG-netlab/BPFabric GitHub Wiki
Learning Switch
- Function:
learningswitch.o
- Controller: N/A
This implements a traditional learning switch in BPFabric. It requires a single table of type hash with the key being the MAC address of incoming traffic and the value being the source port for this packet.
If the source MAC address of the packet is a unicast, the MAC address and the port from which this packet arrived from is added to the inports
table.
If the destination address is broadcast or multicast the packet is flooded to all the other ports of the switch. Otherwise it looks for a port matching the destination MAC address. If a port is found the packet is forwarded to that port, if it doesn't the packet is flooded to all other ports.
This function always result in a forward decision and hence will stop the execution of the pipeline.
Centralised Learning Switch
- Function:
learningswitch_centralized.o
- Controller:
simplyswitch.py
This implements a learning switch but where the decision making is done by the controller. It requires the same map as above, mapping a MAC address to a port.
If the MAC address of the source or the destination is unknown the packet is sent to the controller for it to make a decision.
An example controller implementation is provided. The controller listens for a PacketIn
message containing the packet that couldn't be forwarded. The controller check if the packet is unicast and if so stores locally the mapping between the MAC address and the input port of the packet on the switch and uses the Southbound API to add an entry to the inports table.
It then check the destination MAC address, if it's broadcast or multicast it sends the packet back to the switch to be flooded, if the MAC is know it is sent to the specific matching port.
This implementation is highly similar to the learning switch above, but the main difference is that the data plane does not make any decision. The controller is responsible for making the decision and therefore can make decisions based on the global view of the network instead of just the local information available at the switch.
Wire
- Function:
wire.o
- Controller: N/A
A very simple function that only exchange traffic between the first two interfaces on the switch. If traffic comes from port 0 then send it to port 1, and vice-versa.
Traffic Count
- Function:
trafficcount.o
- Controller: N/A
This implements a traffic counter. It counts the number of packets and bytes coming from each source MAC address to this switch. This relies on a map trafficcount
with 256 entries. The key is the source MAC address and the value is a structure with the number of bytes and packets from this MAC address.
For each packet it looks if an entry already exists in the map. If not it create a new entry initialised at 0. It then increments the counter for the number of packets and bytes based on the current packet.
This is a purely passive function and does not make any forwarding decision. The return value will always be NEXT
to pass the packet to the next stage of the pipeline.
Traffic Histogram
- Function:
traffichist.o
- Controller:
traffichist.py
or N/A
This function creates a histogram of the distribution of the packet sizes. The histogram contains 24 buckets and each bucket has a granularity of 64 bytes. The histogram is implemented as a simple array of 24 elements.
When a packet is received, the packet length is divided by 64 to get a bucket index between 0 and 23. From this index the entry in the array is retrieved and incremented by one.
For instance if a packet of 500 bytes arrives, the index is calculated as 7
(500 / 64 as integer). The entry at array 7
is retrieved and incremented by 1.
From the controller your can now issue a TableListRequest
for this function and retrieve the distribution of packets at this switch. With only the example above, fetching the table will show a value of 1 at index 7 meaning that there has been 1 packet of size between 448 and 511 bytes.
EWMA
- Function:
ewma.o
- Controller:
ewma.py
This function calculated the exponentially weighted moving average (EWMA) of the traffic for each port. For each port it stores a structure of the volume (in bytes), the number of packets, the predicted volume, the last time a packet from this port was received and a counter.
When a packet is received, the structure is retrieved from the map and the volume and packet count for this port. If it's been more than 5 seconds since we have received a packet from this switch we calculate the new EWMA for this port and notify the controller of the value.
The controller implementation waits for Notify
events and plot the predicted volume against the measured volume.
Flow Arrival
- Function:
flowarrival.o
- Controller:
flowarrival.py
This function counts the TCP flow arrival in 5 seconds window. That state is stored in a 1 element array containing the time of the first packet in this window, and the number of TCP flows that have started and number of flows that have finished.
When a packet is received, the function check if it's a TCP packet. If not the function directly passes control to the next function. If it's TCP it checks the TCP flags, if the SYN
flag is set the number of arrival is increased, if the FIN
or RST
flags are set the number of departures are incremented.
If the time between the first packet in this window and the current packet is greater than 5 seconds the controller is notified of the arrival rate and the stats are cleared and a new window started with the current packet as first packet in the window.
Inter Arrival
- Function:
interarrival.o
- Controller:
interarrival.py
This function measures the interarrival time between packets at this switch. To measure this it uses a an array of 1 element to store the last time a packet was received, the number of packet received and the number of packets with an arrival time greater than the histogram. It uses a single array as an histogram with the index in the histogram as the time range bucket for the arrival of this packet.
When a packet is received, it retrieve the current state from the state table. It then calculates the time delta between the current packet and the previous one. From this time bucket it derives an index in the histogram.
If the index calculated is valid for the number of buckets allocated then the counter for this bucket is incremented, otherwise the overflow count is incremented. The time of the current packet is stored for the next packet and the counter of packets is incremented.
Every 64 packets, the controller is notified of the current inter arrival rate.
Latency
- Function:
latency.o
- Controller:
latency.py
This function passively measures the latency of a network by measuring the time between a TCP SYN, the SYN ACK response from the server and first ACK after that.
It uses a hash table with a key that is a flow tuple made of the source and destination IP and the source and destination port.
When a packet is received, it check if it's a TCP packet if not the packet is passed to the next function in the pipeline. If it's a TCP packet it checks and record the time of the SYN, SYN|ACK and first ACK packet.
When the first ACK packet is received the controller is notified of the latency and the entry is removed from the table.
Mirror
- Function:
mirror.o
- Controller: N/A
This function showcases the bpf_mirror
call. Assuming a switch with at least three ports, it mirror the first 100 bytes of any packet coming from port 1 to port 2.
This function doesn't take any forwarding decision and passes control to the next stage in the pipeline.