Skip to content

Instantly share code, notes, and snippets.

@djoreilly
Last active December 30, 2023 14:28
Show Gist options
  • Star 14 You must be signed in to star a gist
  • Fork 10 You must be signed in to fork a gist
  • Save djoreilly/1cf74c684cf03da06ea6 to your computer and use it in GitHub Desktop.
Save djoreilly/1cf74c684cf03da06ea6 to your computer and use it in GitHub Desktop.
Open vSwitch Lab

#Open vSwitch Lab

Get started with Open vSwitch, flows and OpenFlow controllers.

##Pre-reqs

Linux system with OVS installed.

##Setup

Use this script to add a bridge with ports for testing. The interfaces are moved into IP namespaces to isolate them from the main namespace and from each other.

#!/bin/bash

if [ $# -ne 2 ]; then
    echo "usage: $0 port_num ovs_br"
    exit 1
fi

set -xe

port=p$1
ns=ns$1
br=$2
mac=00:00:00:00:00:0$1
ip=10.0.0.${1}/24

ovs-vsctl --may-exist add-br $br
ovs-vsctl add-port $br $port
ovs-vsctl set Interface $port type=internal
ip netns add $ns
ip link set $port netns $ns
ip netns exec $ns ip link set $port address $mac
ip netns exec $ns ip address add $ip dev $port
ip netns exec $ns sysctl -w net.ipv6.conf.${port}.disable_ipv6=1
ip netns exec $ns ip link set $port up

Call script like:

# sh add-port.sh 1 br0
# sh add-port.sh 2 br0

Then the bridge should look like:

# ovs-vsctl show
e3784497-dc8f-432d-9a2c-923148962c73
    Bridge "br0"
        Port "p2"
            Interface "p2"
                type: internal
        Port "br0"
            Interface "br0"
                type: internal
        Port "p1"
            Interface "p1"
                type: internal

##Test 1 - the NORMAL flow

####Test connectivity:

# ip netns exec ns1 ping -c1 10.0.0.2

####Show flows

# ovs-ofctl dump-flows br0
NXST_FLOW reply (xid=0x4):
 cookie=0x0, duration=560.596s, table=0, n_packets=10, n_bytes=828, idle_age=551, priority=0 actions=NORMAL

This flow gets created by default when you create a bridge.. The NORMAL flow causes the bridge to behave like a simple MAC learning switch. It applies to all ports because no in_port was specified and that is like a wildcard for all ports

####Show the mac table

# ovs-appctl fdb/show br0
 port  VLAN  MAC                Age
    1     0  00:00:00:00:00:01    9
    2     0  00:00:00:00:00:02    9

####Delete all flows

# ovs-ofctl del-flows br0

and ping again - it should fail this time.

####Re-add the NORMAL flow

# ovs-ofctl add-flow br0 actions=NORMAL

##Test 2 - forwarding by port numbers

####Delete all flows

# ovs-ofctl del-flows br0

####Find ofport numbers (OpenFlow port numbers)

# ovs-ofctl show br0

####Add the flows

# ovs-ofctl add-flow br0 in_port=1,actions=output:2
# ovs-ofctl add-flow br0 in_port=2,actions=output:1

####Test

# ip netns exec ns1 ping -c1 10.0.0.2

####Test 3 - forward by destination mac address

####Delete all flows

# ovs-ofctl del-flows br0

####Add the flows

# ovs-ofctl add-flow br0 dl_dst=00:00:00:00:00:01,actions=output:1
# ovs-ofctl add-flow br0 dl_dst=00:00:00:00:00:02,actions=output:2
# ovs-ofctl add-flow br0 dl_dst=ff:ff:ff:ff:ff:ff,actions=flood

####Test

# ip netns exec ns1 ping -c1 10.0.0.2

Use dump-flows and watch the packet counters. Wait several minutes for the ARP cache in the namespaces to expire or delete those entries, and ping again. That should cause the broadcast/flood flow to happen on next ping.

##OVS with an external OpenFlow controller

###Setup

Install the Ryu controller from here

####Start Ryu with the sample L2 learning module

$ ryu-manager ryu/ryu/app/simple_switch.py
loading app ryu/ryu/app/simple_switch.py
loading app ryu.controller.ofp_handler
instantiating app ryu/ryu/app/simple_switch.py of SimpleSwitch
instantiating app ryu.controller.ofp_handler of OFPHandler

####Point the test bridge at it

# ovs-vsctl set-controller br0 tcp:127.0.0.1:6633    

####Check there are no flows yet

# ovs-ofctl dump-flows br0
NXST_FLOW reply (xid=0x4):

####Send some data

# ip netns exec ns1 ping -c1 10.0.0.2

####Check that the controller added new flows

# ovs-ofctl dump-flows br0
NXST_FLOW reply (xid=0x4):
 cookie=0x0, duration=5.808s, table=0, n_packets=1, n_bytes=42, idle_age=0, in_port=2,dl_dst=00:00:00:00:00:01 actions=output:1
 cookie=0x0, duration=0.808s, table=0, n_packets=0, n_bytes=0, idle_age=0, in_port=1,dl_dst=00:00:00:00:00:02 actions=output:2

####Check controller console for new log messages

packet in 270705776096578 00:00:00:00:00:01 00:00:00:00:00:02 1
packet in 270705776096578 00:00:00:00:00:02 00:00:00:00:00:01 2
packet in 270705776096578 00:00:00:00:00:01 00:00:00:00:00:02 1

####Study and change the sample code

See here

@Gemstone123
Copy link

how to add rule if i want to forward packets from one virtual machine to other if one machine ping google and forward those packets to other machine?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment