Skip to content

Commit

Permalink
Adds Load Balancer NF (#227)
Browse files Browse the repository at this point in the history
This adds a new NF to our collection, the Load Balancer NF.  The Load Balancer NF is an L3, round-robin load balancer that distributes network traffic across multiple backend servers.

This NF takes advantage of the ONVM NFLib Flow Table to maintain a list of network flows.  Using the flow table and the source NIC port of a packet, the Load Balancer NF is able to decide how to route it: either load balancer to backend server or vice versa.  If incoming traffic does not have a pre-existing entry in the flow table, one will be created and subsequent traffic in that flow will be routed accordingly.  For detailed information about using the NF and how it works, please read the corresponding README in the NF directory.

The Load Balancer NF performs advanced operation on the network traffic to determine how to route them.  With this requirement, we add several new APIs to the OpenNetVM NFLib to aid NF development.

New NFLib APIs:

  * `int onvm_pkt_parse_ip(char* ip_str, uint32_t* dest)` - Parses IP Addresses in dotted decimal form (192.168.1.1) to decimal form (3232235777)
  * `int onvm_pkt_parse_mac(char * mac_str, uint8_t* dest)` - Parses MAC Addresses in string form (11:22:33:44:55:66) to an array of six octets
  * `uint32 onvm_pkt_get_checksum_offload_flags(uint8_t port_id)` - Determine if the NIC port supports checksum offloading
  * `void onvm_pkt_set_checksums(struct rte_mbuf* pkt)` - Recalculate and set packet checksums
  * `static uint16_t calculate_tcpudp_cksum(const struct ipv4_hdr *ip, const void *l4_hdr, const uint32_t l3_len, uint8_t protocol)` - Calculates the TCP or UDP checksum based on the provided headers
  * `static uint16_t calculate_ip_cksum(const struct ipv4_hdr *ip, const uint32_t l3_len)` - Calculates the IP checksum based on the provided headers
  * `#define ONVM_PKT_GET_FLAGS(tcp, flags)` - Gets the TCP flags from the provided header
  * `#define ONVM_PKT_SET_FLAGS(tcp, flags)` - Sets the TCP flags of the provided header

Commit log:

* Initial commit for load_balancer NF

  - Layer 3 round-robin load balancer
  - Using onvm_flow_table to keep track of flows
  - Using tcp_helper for pkt checksum recalculation
  - Config values are currently hard coded in the .c file
  - Still has testing values and debug prints

* Added basic config file parsing

  - Config file has Number of entries
    -- Each entry has ip and mac or backend server

* Removed debug printing, added some comments

* Added config filename parsing, more error checks

* Better code structure, style fixes

* Remove hard coded mac for client

* Added client/server iface name args

  - Added parsing of the interface information, mathing interface to onvm ports id
  - Multiple name changes
  - This removes hard coded port values

* Minor updates

* README, config example

* Clearing up flow entries after expiration timeout

  - This mimics the flow_tracker NF logic of terminatin old flows
  - Old flow termination happens when flow table gets full, should also be cleaned up on some timeout

* Change flow_table returns, fixed mac iface id bug

  - Change return of table_lookup to int value, flow_info is now passed as an argument
  - Fixed mac iface mac comparison with onvm_mgr
  - Fixed wrong client/server port id refernces in packet_handler

* Added arp table print

* Minor printing changes

* Moved to a no-modification client ip style

  - This allows the load balancer to handle multiple clients
  - Now instead of modifying the client ip to send it to the backend server we add a routing rule to the backend server
  - Remove hard coded port switching with !port

* Documentation for the NF

* Moved global variables to loadbalance struct

* Moved checksum helper function to onvm_pkt_helper

* Change year in Makefile

* Requested changes: macro functions, readme changes

* Removed unused pkt_copy func

* Parse ip/mac functions, change macro functions
  • Loading branch information
koolzz authored and nks5295 committed Nov 16, 2017
1 parent 00c1515 commit 92b77d0
Show file tree
Hide file tree
Showing 9 changed files with 955 additions and 1 deletion.
2 changes: 1 addition & 1 deletion examples/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ $(error "Please define RTE_SDK environment variable")
endif

# To add new examples, append the directory name to this variable
examples = bridge basic_monitor simple_forward speed_tester flow_table test_flow_dir aes_encrypt aes_decrypt flow_tracker
examples = bridge basic_monitor simple_forward speed_tester flow_table test_flow_dir aes_encrypt aes_decrypt flow_tracker load_balancer

ifeq ($(NDPI_HOME),)
$(warning "Skipping ndpi_stats NF as NDPI_HOME is not set")
Expand Down
2 changes: 2 additions & 0 deletions examples/load_balancer/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
load_balancer/
build/
68 changes: 68 additions & 0 deletions examples/load_balancer/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# openNetVM
# https://github.com/sdnfv/openNetVM
#
# BSD LICENSE
#
# Copyright(c)
# 2015-2017 George Washington University
# 2015-2017 University of California Riverside
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# The name of the author may not be used to endorse or promote
# products derived from this software without specific prior
# written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

ifeq ($(RTE_SDK),)
$(error "Please define RTE_SDK environment variable")
endif

RTE_TARGET ?= x86_64-native-linuxapp-gcc

# Default target, can be overriden by command line or environment
include $(RTE_SDK)/mk/rte.vars.mk

# binary name
APP = load_balancer

# all source are stored in SRCS-y
SRCS-y := load_balancer.c

# OpenNetVM path
ONVM= $(SRCDIR)/../../onvm

#CFLAGS += $(USER_FLAGS)
CFLAGS += $(WERROR_FLAGS) -O3 $(USER_FLAGS)

CFLAGS += -I$(ONVM)/onvm_nflib
CFLAGS += -I$(ONVM)/onvm_mgr
LDFLAGS += $(ONVM)/onvm_nflib/onvm_nflib/$(RTE_TARGET)/libonvm.a

# workaround for a gcc bug with noreturn attribute
# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603
ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y)
CFLAGS_main.o += -Wno-return-type
endif

include $(RTE_SDK)/mk/rte.extapp.mk
48 changes: 48 additions & 0 deletions examples/load_balancer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
Load Balancer NF
==

This NF acts as a layer 3, round-robin load balancer. When a packet arrives the NF checks whether it is from an already existing flow. If not, it creates a new flow entry and assigns it to the destination backend server. The NF decides what to do with the packet based on which port it arrived at. It is also setup to clean the flow table whenever it fills up.

App Specific Instuctions
--
**Setting up dpdk interfaces**
This NF requires 2 DPDK interfaces to work, both can be setup using the `openNetVM/dpdk/tools/dpdk-setup-iface.sh` script.

**Server Config**
The server config needs to have the total number of backend servers with their ip and mac address combination, an example config file `server.conf` is provided.

**Server Configuration**
The backend servers need to be configured to forward traffic back to the load balancer, this can be done using ip routes on the server machine.
An example usage for LB server port at 10.0.0.37 with clients matching 11.0.0.0/24 using iface p2p1.
```sudo ip route add 11.0.0.0/24 via 10.0.0.37 dev p2p1```

**This NF should be run with the ARP NF**
The Load Balancer NF needs to respond to client and server ARP requests. As `onvm_mgr` currently doesn't resolve arp requests, an ARP NF with the LB NF as destination is used.

An example usage of the ARP&LB NF, with the Load Balancer using dpdk0 - 10.0.0.37 and dpdk1 - 11.0.0.37 for client, server ports respecively.
```
ARP NF
./go.sh 4 1 2 -s 10.0.0.37,11.0.0.37
LB NF
./go.sh 5 2 dpdk0 dpdk1 server.conf
```


Compilation and Execution
--
```
make
./go.sh CORELIST SERVICE_ID CLIENT_IFACE SERVER_IFACE SERVER_CONFIG [PRINT_DELAY]
OR
sudo ./load_balancer/x86_64-native-linuxapp-gcc/forward -l CORELIST -n 3 --proc-type=secondary -- -r SERVICE_ID -- -c CLIENT_IFACE -s SERVER_IFACE -f SERVER_CONFIG [-p PRINT_DELAY]
```

App Specific Arguments
--
- `CLIENT_IFACE` : name of the client interface
- `SERVER_IFACE` : name of the server interface
- `SERVER_CONFIG` : backend server config file
- `-p <print_delay>`: number of packets between each print, e.g. `-p 1` prints every packets.
34 changes: 34 additions & 0 deletions examples/load_balancer/go.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/bin/bash

function usage {
echo "$0 CPU-LIST SERVICE-ID CLIENT_IFACE SERVER_IFACE SERVER_CONFIG [-p PRINT] [-n NF-ID]"
echo "$0 5 1 dpdk0 dpdk1 example.conf --> core 5, with Service ID 1, dpdk0 as Client interface, dpdk1 as Server interface, example.conf config"
echo "$0 3,7,9 1 server.conf 1000 --> cores 3,7, and 9, with Service ID 1, server.conf as backend conf, and Print Rate of 1000"
exit 1
}

SCRIPT=$(readlink -f "$0")
SCRIPTPATH=$(dirname "$SCRIPT")
cpu=$1
service=$2
client=$3
server=$4
config=$5

shift 5

if [ -z $config ]
then
usage
fi

while getopts ":p:n:" opt; do
case $opt in
p) print="-p $OPTARG";;
n) instance="-n $OPTARG";;
\?) echo "Unknown option -$OPTARG" && usage
;;
esac
done

exec sudo $SCRIPTPATH/build/load_balancer -l $cpu -n 3 --proc-type=secondary -- -r $service $instance -- -c $client -s $server -f $config $print
Loading

0 comments on commit 92b77d0

Please sign in to comment.