Overview
OpenFlow is the first and most widely deployed Software-Defined Networking (SDN) protocol, defining a standard interface between the control plane (SDN controller) and the data plane (network switches). It allows a centralized controller to add, modify, and delete flow entries in a switch’s flow table, determining how packets are forwarded, dropped, modified, or sent to the controller for further processing. OpenFlow effectively decouples the network intelligence from the forwarding hardware, enabling programmable, vendor-neutral network control.
Defined by the Open Networking Foundation (ONF), OpenFlow supports multiple table pipelines where packets are matched against rules based on header fields (MAC, IP, TCP/UDP ports, VLAN, MPLS, etc.) and processed with actions like forwarding to a port, modifying headers, metering, or sending to a group table for multipath or failover. OpenFlow is implemented in hardware switches from major vendors, software switches like Open vSwitch, and controllers including ONOS, OpenDaylight, Ryu, and Floodlight. It is fundamental to data center networking, network virtualization, and traffic engineering.
Installation
Open vSwitch (OpenFlow Switch)
# Ubuntu/Debian
sudo apt update
sudo apt install openvswitch-switch
# CentOS/RHEL
sudo yum install openvswitch
# Start OVS
sudo systemctl start openvswitch-switch
sudo systemctl enable openvswitch-switch
# Verify
ovs-vsctl --version
Ryu Controller (Python-based)
pip install ryu
# Verify
ryu-manager --version
OpenDaylight Controller
# Download Karaf distribution
wget https://nexus.opendaylight.org/content/repositories/opendaylight.release/org/opendaylight/integration/karaf/0.18.3/karaf-0.18.3.tar.gz
tar xzf karaf-0.18.3.tar.gz
cd karaf-0.18.3/bin
./karaf
# Install OpenFlow plugin
feature:install odl-openflowplugin-flow-services-ui
OpenFlow Concepts
Flow Table Structure
| Field | Description |
|---|
| Match Fields | Packet header fields to match |
| Priority | Higher value = higher priority |
| Counters | Packet/byte counters |
| Instructions | Actions to apply to matching packets |
| Timeouts | Idle and hard timeout values |
| Cookie | Controller-defined opaque identifier |
| Flags | Modify flow entry behavior |
Match Fields (OpenFlow 1.3+)
| Field | OXM Name | Description |
|---|
| Ingress Port | in_port | Switch input port |
| Ethernet Src | eth_src/dl_src | Source MAC address |
| Ethernet Dst | eth_dst/dl_dst | Destination MAC |
| Ethernet Type | eth_type/dl_type | EtherType |
| VLAN ID | vlan_vid/dl_vlan | 802.1Q VLAN ID |
| IP Src | ipv4_src/nw_src | Source IPv4 address |
| IP Dst | ipv4_dst/nw_dst | Destination IPv4 address |
| IP Protocol | ip_proto/nw_proto | IP protocol number |
| TCP Src Port | tcp_src/tp_src | TCP source port |
| TCP Dst Port | tcp_dst/tp_dst | TCP destination port |
| UDP Src Port | udp_src | UDP source port |
| UDP Dst Port | udp_dst | UDP destination port |
| MPLS Label | mpls_label | MPLS label value |
Actions
| Action | Description |
|---|
output:PORT | Forward packet to port |
output:CONTROLLER | Send to controller |
output:FLOOD | Flood to all ports except ingress |
output:ALL | Send to all ports |
output:IN_PORT | Send back to ingress port |
drop | Drop packet (no actions) |
mod_dl_src:MAC | Modify source MAC |
mod_dl_dst:MAC | Modify destination MAC |
mod_nw_src:IP | Modify source IP |
mod_nw_dst:IP | Modify destination IP |
mod_tp_src:PORT | Modify source port |
mod_tp_dst:PORT | Modify destination port |
push_vlan:0x8100 | Push VLAN tag |
pop_vlan | Pop VLAN tag |
set_field:VALUE | Set a header field |
group:ID | Apply group table entry |
meter:ID | Apply meter for rate limiting |
OVS Flow Management
ovs-ofctl Commands
# Show switch information
sudo ovs-ofctl show s1
sudo ovs-ofctl dump-desc s1
# Dump all flows
sudo ovs-ofctl dump-flows s1
sudo ovs-ofctl dump-flows s1 --no-stats
# Dump flows with specific OpenFlow version
sudo ovs-ofctl -O OpenFlow13 dump-flows s1
# Add flow rules
sudo ovs-ofctl add-flow s1 "priority=100,in_port=1,actions=output:2"
sudo ovs-ofctl add-flow s1 "priority=100,in_port=2,actions=output:1"
# Add flow matching on IP
sudo ovs-ofctl add-flow s1 \
"priority=200,dl_type=0x0800,nw_dst=10.0.0.2,actions=output:2"
# Add flow matching on TCP port
sudo ovs-ofctl add-flow s1 \
"priority=300,dl_type=0x0800,nw_proto=6,tp_dst=80,actions=output:3"
# Add flow with VLAN tagging
sudo ovs-ofctl add-flow s1 \
"priority=150,in_port=1,actions=push_vlan:0x8100,set_field:100->vlan_vid,output:2"
# Add flow with header modification
sudo ovs-ofctl add-flow s1 \
"priority=200,dl_type=0x0800,nw_dst=10.0.0.1,actions=mod_dl_dst:00:11:22:33:44:55,output:2"
# Delete flows
sudo ovs-ofctl del-flows s1 # Delete all flows
sudo ovs-ofctl del-flows s1 "in_port=1" # Delete matching flows
sudo ovs-ofctl del-flows s1 --strict "priority=100,in_port=1"
# Modify existing flow
sudo ovs-ofctl mod-flows s1 "priority=100,in_port=1,actions=output:3"
# Add flow with timeout
sudo ovs-ofctl add-flow s1 \
"priority=100,idle_timeout=60,hard_timeout=300,in_port=1,actions=output:2"
# Send packet to controller on table miss
sudo ovs-ofctl add-flow s1 "priority=0,actions=output:CONTROLLER:65535"
Port Statistics
# Dump port statistics
sudo ovs-ofctl dump-ports s1
sudo ovs-ofctl dump-ports-desc s1
# Dump table statistics
sudo ovs-ofctl dump-tables s1
# Monitor OpenFlow messages
sudo ovs-ofctl monitor s1
sudo ovs-ofctl snoop s1
OVS Bridge Management
# Create bridge with specific OpenFlow version
sudo ovs-vsctl add-br s1 -- set bridge s1 protocols=OpenFlow13
# Set controller
sudo ovs-vsctl set-controller s1 tcp:127.0.0.1:6653
# Multiple controllers
sudo ovs-vsctl set-controller s1 tcp:10.0.0.1:6653 tcp:10.0.0.2:6653
# Set fail mode (standalone = act as L2 switch, secure = drop all)
sudo ovs-vsctl set-fail-mode s1 secure
# Show controller connection status
sudo ovs-vsctl get-controller s1
sudo ovs-ofctl dump-desc s1
Multi-Table Pipeline (OpenFlow 1.3+)
# Table 0: Classification
sudo ovs-ofctl -O OpenFlow13 add-flow s1 \
"table=0,priority=100,dl_type=0x0800,actions=goto_table:1"
sudo ovs-ofctl -O OpenFlow13 add-flow s1 \
"table=0,priority=100,dl_type=0x0806,actions=FLOOD"
sudo ovs-ofctl -O OpenFlow13 add-flow s1 \
"table=0,priority=0,actions=drop"
# Table 1: Routing
sudo ovs-ofctl -O OpenFlow13 add-flow s1 \
"table=1,priority=100,nw_dst=10.0.1.0/24,actions=goto_table:2"
sudo ovs-ofctl -O OpenFlow13 add-flow s1 \
"table=1,priority=100,nw_dst=10.0.2.0/24,actions=set_field:00:aa:bb:cc:dd:02->eth_dst,goto_table:2"
# Table 2: Output
sudo ovs-ofctl -O OpenFlow13 add-flow s1 \
"table=2,priority=100,eth_dst=00:aa:bb:cc:dd:01,actions=output:1"
sudo ovs-ofctl -O OpenFlow13 add-flow s1 \
"table=2,priority=100,eth_dst=00:aa:bb:cc:dd:02,actions=output:2"
Group Tables
# Select group (load balancing)
sudo ovs-ofctl -O OpenFlow13 add-group s1 \
"group_id=1,type=select,bucket=output:1,bucket=output:2,bucket=output:3"
# Failover group (fast failover)
sudo ovs-ofctl -O OpenFlow13 add-group s1 \
"group_id=2,type=ff,bucket=watch_port:1,output:1,bucket=watch_port:2,output:2"
# All group (multicast)
sudo ovs-ofctl -O OpenFlow13 add-group s1 \
"group_id=3,type=all,bucket=output:1,bucket=output:2"
# Use group in flow
sudo ovs-ofctl -O OpenFlow13 add-flow s1 \
"priority=100,dl_type=0x0800,nw_dst=10.0.0.0/24,actions=group:1"
# Dump groups
sudo ovs-ofctl -O OpenFlow13 dump-groups s1
sudo ovs-ofctl -O OpenFlow13 dump-group-stats s1
Advanced Usage
Metering (Rate Limiting)
# Create meter (1 Mbps rate limit)
sudo ovs-ofctl -O OpenFlow13 add-meter s1 \
"meter=1,kbps,band=type=drop,rate=1000"
# Apply meter to flow
sudo ovs-ofctl -O OpenFlow13 add-flow s1 \
"priority=100,dl_type=0x0800,nw_src=10.0.0.1,actions=meter:1,output:2"
# Dump meters
sudo ovs-ofctl -O OpenFlow13 dump-meters s1
QoS with OpenFlow
# Create queues
sudo ovs-vsctl set port s1-eth1 qos=@newqos -- \
--id=@newqos create qos type=linux-htb queues=0=@q0,1=@q1 -- \
--id=@q0 create queue other-config:max-rate=1000000000 -- \
--id=@q1 create queue other-config:max-rate=100000000
# Direct traffic to queue
sudo ovs-ofctl add-flow s1 \
"priority=200,dl_type=0x0800,nw_proto=6,tp_dst=80,actions=set_queue:1,output:1"
Troubleshooting
| Issue | Solution |
|---|
| Controller not connecting | Check TCP/6653, verify set-controller |
| Flows not matching packets | Check priority ordering, use dump-flows |
| Packets being dropped | Verify table-miss entry exists (priority=0) |
| OpenFlow version mismatch | Set protocols on bridge, use -O flag |
| High controller load | Reduce packet-in rate, add proactive flows |
| Group table not working | Requires OpenFlow 1.1+, check switch support |
| Meter not applying | Requires OF1.3+, check meter support |
| Stale flows | Use idle_timeout or periodic cleanup |
Debugging
# Monitor all OpenFlow messages
sudo ovs-ofctl monitor s1 watch:
# Trace packet through pipeline
sudo ovs-appctl ofproto/trace s1 \
"in_port=1,dl_src=00:11:22:33:44:55,dl_dst=00:aa:bb:cc:dd:ee,dl_type=0x0800,nw_src=10.0.0.1,nw_dst=10.0.0.2,nw_proto=6,tp_src=12345,tp_dst=80"
# Show OVS logs
sudo ovs-appctl vlog/list
sudo ovs-appctl vlog/set ofproto:dbg
# Check connection status
sudo ovs-vsctl show
sudo ovs-appctl bridge/dump-flows s1