Showing posts with label LINC. Show all posts
Showing posts with label LINC. Show all posts

Monday, 10 June 2013

OpenFlow Switch on Raspberry Pi Part 4: Ryu config to make LINC a L2 switch

This is part 4 in the series of building an OpenFlow switch on the Raspberry Pi.  In  part 3 of this OpenFlow series we had built our switch, installed the Ryu controller and got the switch to connect to the controller.

Before carry on it's worth expanding a bit more on the Ryu controller. It's an OpenSource controller developed by NTT in Japan and released under the commercially friendly Apache2 licence.

When we started the controller in the last post it was in fact useless. The controller is a little unusual since it is in-fact a framework for control. It effectively allows you to build network APIs (Application Programmer Interfaces). You need to write your own business logic to define what you want the network to do. This business logic is defined in fairly short python programmes.  I'm not a python programmer and have never learnt - I will have to get my 15 year old son to teach me how to programme in python!

You can think of these python scripts as apps - potentially there could be an app store for the network equivalent to iTunes.

Fortunately we have some ready made python scripts available which we can use with ryu and at least do some useful things.

Before we shutdown ryu and get it to use one of these scripts let's see what state LINC is in to confirm that the ryu controller has in-fact done nothing!

The LINC switch uses Erlang syntax so the commands may seem complex and unfamiliar.

 The command to view the forwarding table on LINC is:

(linc@raspberrypi)1> ets:tab2list(linc:lookup(0, flow_table_0)).

The response is:
[]

An empty table. The switch doesn't know what to do with any packets that arrive since the forwarding table is empty.

OK lets shutdown ryu by doing CTRL-C.

We now need to use one of the python scripts which came with LINC. There are also scripts which came with ryu but they don't all work with LINC.

You can either use the script at:

https://github.com/FlowForwarding/LINC-Switch/blob/master/scripts/ryu/l2_switch_v1_3.py

Copy and paste this into a file called l2_switch_v1_3.py on the computer where your controller is running or copy the script in the LINC installation directory.  This python switch allows LINC to function as a layer 2 switch.  It could alternatively be an app to turn it into a firewall or whatever network device you dream up!
LINC-Switch/scripts/ryu/l2_switch_v13.py 

We now need to restart ryu with the python script

$  LINC-Switch/scripts/ryu/l2_switch_v13.py

In my case ryu now reports:

installing new source mac received from port 4
installing new source mac received from port 4
installing new source mac received from port 4

Let's now look at LINC. In the console we have

10:08:40.542 [info] Created port: {port,4,[{queues_status,disabled},{queues,[]},{config,{port_configuration,undefined,up,false,false,false}},{features,{features,undefined,'100Mb-FD',true,copper,unsupported}},{queues,[]},{interface,"eth0"}]}
10:08:40.780 [info] Created port: {port,3,[{queues_status,disabled},{queues,[]},{config,{port_configuration,undefined,up,false,false,false}},{features,{features,undefined,'100Mb-FD',true,copper,unsupported}},{queues,[]},{interface,"wlan0"}]}
10:08:41.020 [info] Created port: {port,2,[{queues_status,disabled},{queues,[]},{config,{port_configuration,undefined,up,false,false,false}},{features,{features,undefined,'100Mb-FD',true,copper,unsupported}},{queues,[]},{interface,"eth2"}]}
10:08:41.289 [info] Created port: {port,1,[{queues_status,disabled},{queues,[]},{config,{port_configuration,undefined,up,false,false,false}},{features,{features,undefined,'100Mb-FD',true,copper,unsupported}},{queues,[]},{interface,"eth1"}]}
10:08:41.307 [info] Connected to controller 192.168.1.4:6633/0 using OFP v4

[{flow_entry,{0,#Ref<0.0.0.897>},
             0,
             {ofp_match,[]},
             <<0,0,0,0,0,0,0,0>>,
             [],
             {1370,599721,348915},
             {infinity,0,0},
             {infinity,0,0},
             [{ofp_instruction_write_actions,4,
                                             [{ofp_action_output,16,controller,65535}]}]}]


(linc@raspberrypi)5> ets:tab2list(linc:lookup(0, flow_table_0)).

We now have something in the flow table

[{flow_entry,{0,#Ref<0.0.0.1215>},
             0,
             {ofp_match,[]},
             <<0,0,0,0,0,0,0,0>>,
             [],
             {1370,600106,318986},
             {infinity,0,0},
             {infinity,0,0},
             [{ofp_instruction_write_actions,4,
                                             [{ofp_action_output,16,controller,65535}]}]},
 {flow_entry,{123,#Ref<0.0.0.1219>},
             123,
             {ofp_match,[{ofp_field,openflow_basic,in_port,false,
                                    <<0,0,0,4>>,
                                    undefined},
                         {ofp_field,openflow_basic,eth_src,false,
                                    <<192,63,14,164,241,229>>,
                                    undefined}]},
             <<0,0,0,0,0,0,0,0>>,
             [],
             {1370,600110,573684},
             {infinity,0,0},
             {infinity,0,0},
             [{ofp_instruction_goto_table,6,1}]},
 {flow_entry,{123,#Ref<0.0.0.1223>},
             123,
             {ofp_match,[{ofp_field,openflow_basic,in_port,false,
                                    <<0,0,0,4>>,
                                    undefined},
                         {ofp_field,openflow_basic,eth_src,false,
                                    <<0,31,208,172,255,21>>,
                                    undefined}]},
             <<0,0,0,0,0,0,0,0>>,
             [],
             {1370,600110,817008},
             {infinity,0,0},
             {infinity,0,0},
             [{ofp_instruction_goto_table,6,1}]},
 {flow_entry,{123,#Ref<0.0.0.1254>},
             123,
             {ofp_match,[{ofp_field,openflow_basic,in_port,false,
                                    <<0,0,0,4>>,
                                    undefined},
                         {ofp_field,openflow_basic,eth_src,false,
                                    <<116,240,109,81,22,170>>,
                                    undefined}]},
             <<0,0,0,0,0,0,0,0>>,
             [],
             {1370,600112,591632},
             {infinity,0,0},
             {infinity,0,0},
             [{ofp_instruction_goto_table,6,1}]}]

Yours will probably look different. In the next post we'll do a little test scenario and controlled traffic.


Thursday, 6 June 2013

OpenFlow Switch on Raspberry Pi Part 3: Ryu OpenFlow controller connected to LINC switch

Back to the cheapest OpenFlow switch in the world based on the Raspberry Pi.

So far we've built our OpenFlow switch, installed Erlang and installed the LINC OpenFlow switch.

The switch isn't much use without a controller.  There are a number of OpenFlow switches out there. Beacon, Flashlight, Ryu and more.

Beacon is rather old so doesn't work with LINC which supports the latest protocols. For my OpenFlow lab I'm going to use the NTT ryu controller.

Ryu is written in python so should work on your platform. It's even possible to run it on the Raspberry Pi but for now I'm running it on an OpenSuse machine.

The Ryu webpage is  http://osrg.github.io/ryu/  and the download page takes you to Ryu's github page at https://github.com/osrg/ryu

If you have an up-to-date python installation you may be able to install Ryu with the simple command

pip install ryu
If you're like me you're installation will need some work to make it install!

I didn't have pip (the python package installer) so I had to install "distribute" first

$ wget http://python-distribute.org/distribute_setup.py
$ python distribute_setup.py

Then I had to install pip

$ wget http://pypi.python.org/packages/source/p/pip/pip-0.7.2.tar.gz
$ tar xzf pip-0.7.2.tar.gz
$ cd pip-0.7.2
$  python setup.py install

Then I installed ryu

$ pip install ryu

You may be lucky and it runs.
$ pip install ryu

I was not so lucky.  I was missing the gevent python library

$  pip install gevent

However it wouldn't install so I had to install the python-devel RPM next
I then installed a bunch of missing python libraries

$ pip install gevent
$ pip install webob
$ pip install routes

Finally gevent worked !
$ pip install gevent
$ ryu-manager
loading app ryu.controller.ofp_handler
instantiating app ryu.controller.ofp_handler

Yes a running OpenFlow controller !!
Although LINC supports auto controller configuration using OF Config, we'll set it up manually.

Now we have a running controller on a machine, we need to find the IP address of the machine. On Linux
the command is /sbin/ifconfig -a

My address is 192.168.1.4

On windows machines you need a cmd prompt and type ipconfig /all to find the IP address

We now need to edit the LINC config file to point it at the controller.
To edit the file on the Pi

pi@raspberrypi ~/LINC-Switch $ sudo vi rel/linc/releases/1.0/sys.config

      %% Configuration of the controllers switch will connect to. Ideally
       %% this list should be empty and assignement should be handled by an
       %% OF-Config client.
       %% Default OFP controller port is 6633.
       {controllers,
        [
         {"Switch0-DefaultController", "192.168.1.4", 6633, tcp}
        ]},

       %% Configure ports available to the switch when using the
       %% userspace backend according to your system setup.
       %% * Under Linux all TAP interfaces must be set up beforehand
       %%   as persistent.
       %% * Under MacOSX TAP interfaces are created during node
       %%   startup (which requires setting an ip parameter).

 This line is commented out with a %% by default so the %% needs to be removed and the correct IP address inserted.

OK time to let the switch connect to the controller!

pi@raspberrypi ~/LINC-Switch $ sudo rel/linc/bin/linc console
Exec: /home/pi/LINC-Switch/rel/linc/erts-5.9.3.1/bin/erlexec -boot /home/pi/LINC-Switch/rel/linc/releases/1.0/linc -mode embedded -config /home/pi/LINC-Switch/rel/linc/releases/1.0/sys.config -args_file /home/pi/LINC-Switch/rel/linc/releases/1.0/vm.args -- console
Root: /home/pi/LINC-Switch/rel/linc

Erlang R15B03 (erts-5.9.3.1) [source] [async-threads:0] [kernel-poll:false]

20:52:02.873 [info] Application lager started on node linc@raspberrypi
20:52:02.883 [info] Application ssh started on node linc@raspberrypi
20:52:02.912 [info] Application enetconf started on node linc@raspberrypi
20:52:02.927 [info] Application linc started on node linc@raspberrypi
Eshell V5.9.3.1  (abort with ^G)
(linc@raspberrypi)1>
(linc@raspberrypi)1> 20:52:03.230 [info] Created port: {port,4,[{queues_status,disabled},{queues,[]},{config,{port_configuration,undefined,up,false,false,false}},{features,{features,undefined,'100Mb-FD',true,copper,unsupported}},{queues,[]},{interface,"eth0"}]}
20:52:03.481 [info] Created port: {port,3,[{queues_status,disabled},{queues,[]},{config,{port_configuration,undefined,up,false,false,false}},{features,{features,undefined,'100Mb-FD',true,copper,unsupported}},{queues,[]},{interface,"wlan0"}]}
20:52:03.736 [info] Created port: {port,2,[{queues_status,disabled},{queues,[]},{config,{port_configuration,undefined,up,false,false,false}},{features,{features,undefined,'100Mb-FD',true,copper,unsupported}},{queues,[]},{interface,"eth2"}]}
20:52:03.974 [info] Created port: {port,1,[{queues_status,disabled},{queues,[]},{config,{port_configuration,undefined,up,false,false,false}},{features,{features,undefined,'100Mb-FD',true,copper,unsupported}},{queues,[]},{interface,"eth1"}]}
20:52:04.020 [info] Connected to controller 192.168.1.4:6633/0 using OFP v4

(linc@raspberrypi)1>

Success!

In my next post in this series we'll start doing some useful experiments.

Thursday, 23 May 2013

OpenFlow Switch on Raspberry Pi Part 3: Configuration and getting it running

In part 1 I showed what hardware you need to turn your Raspberry Pi into an OpenFlow switch by  adding USB to Ethernet adaptors.

In part 2 I showed how to install Erlang and install the LINC OpenFlow switch

In this part we start with configuring the switch.

The first thing we need to do is identify what networking ports we have on our Pi.

We use the command ifconfig -a to find out what Ethernet ports we have

pi@raspberrypi ~ $ ifconfig -a

eth0      Link encap:Ethernet  HWaddr b8:27:eb:21:08:6a
          inet addr:192.168.1.19  Bcast:192.168.1.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:121 errors:0 dropped:0 overruns:0 frame:0
          TX packets:83 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:11559 (11.2 KiB)  TX bytes:11040 (10.7 KiB)

eth1      Link encap:Ethernet  HWaddr 00:e0:4c:53:44:58
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0  carrier:0  
          collisions:0  txqueuelen:1000                                                                               
           RX bytes:0 (0.0 B)  TX bytes:0 (0.0B)   

eth2      Link encap:Ethernet  HWaddr 00:e0:4c:53:44:58
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

wlan0     Link encap:Ethernet  HWaddr 00:0b:81:89:5e:bf
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)


Port eth0 is the native Ethernet port on the Pi and the USB based Ethernet ports are showing up as eth1, eth2 and wlan0.  If you've added more or different ports for your hardware, your port numbers will differ.

We now need to edit the LINC config file so that it knows what ports it has access to.
If the version you have downloaded is higher than 1.0 you'll need to change the line below

pi@raspberrypi ~/LINC-Switch $ sudo vi rel/linc/releases/1.0/sys.config

We now need to edit the section of the file to declare the ports which form part of the switch

       {ports,
        [
         %% - regular hardware interface
         {port, 1, [{interface, "eth1"}]},
         {port, 2, [{interface, "eth2"}]},
         {port, 3, [{interface, "wlan0"}]},
         {port, 4, [{interface, "eth0"}]}
         %% - hardware interface with explicit type
         %% {port, 1, [{interface, "net0"}, {type, eth}]},
         %% - regular tap interface
         %% {port, 2, [{interface, "tap0"}]},
         %% - tap interface under MacOSX with dynamically assigned IP
         %% {port, 3, [{interface, "tap1"}, {ip, "10.0.0.1"}]},
         %% - tap interface with explicit type
         %% {port, 4, [{interface, "net1"}, {type, tap}]}
        ]},

Note that the last active port shouldn't have a comma after it

We can now start the OpenFlow switch for the first time

pi@raspberrypi ~/LINC-Switch $ sudo rel/linc/bin/linc console

Exec: /home/pi/LINC-Switch/rel/linc/erts-5.9.3.1/bin/erlexec -boot /home/pi/LINC-Switch/rel/linc/releases/1.0/linc -mode embedded -config /home/pi/LINC-Switch/rel/linc/releases/1.0/sys.config -args_file /home/pi/LINC-Switch/rel/linc/releases/1.0/vm.args -- console
Root: /home/pi/LINC-Switch/rel/linc
Erlang R15B03 (erts-5.9.3.1) [source] [async-threads:0] [kernel-poll:false]

21:18:47.473 [info] Application lager started on node linc@raspberrypi
21:18:47.483 [info] Application ssh started on node linc@raspberrypi
21:18:47.542 [info] Application enetconf started on node linc@raspberrypi
21:18:47.557 [info] Application linc started on node linc@raspberrypi
Eshell V5.9.3.1  (abort with ^G)
(linc@raspberrypi)1> 21:18:47.957 [info] Created port: {port,4,[{queues_status,disabled},{queues,[]},{config,{port_configuration,undefined,up,false,false,false}},{features,{features,undefined,'100Mb-FD',true,copper,unsupported}},{interface,"eth0"}]}
21:18:48.197 [info] Created port: {port,3,[{queues_status,disabled},{queues,[]},{config,{port_configuration,undefined,up,false,false,false}},{features,{features,undefined,'100Mb-FD',true,copper,unsupported}},{queues,[]},{interface,"wlan0"}]}
21:18:48.435 [info] Created port: {port,2,[{queues_status,disabled},{queues,[]},{config,{port_configuration,undefined,up,false,false,false}},{features,{features,undefined,'100Mb-FD',true,copper,unsupported}},{queues,[]},{interface,"eth2"}]}
21:18:48.704 [info] Created port: {port,1,[{queues_status,disabled},{queues,[]},{config,{port_configuration,undefined,up,false,false,false}},{features,{features,undefined,'100Mb-FD',true,copper,unsupported}},{queues,[]},{interface,"eth1"}]}

(linc@raspberrypi)1>
You can see LINC has created the ports defined in the config file and ended with the Erlang prompt.

OK. Let's shutdown the switch. We use the Erlang command  init:stop().

(linc@raspberrypi)1> init:stop().
ok

In the next post we'll get an OpenFlow controller running and start talking to the switch.

Tuesday, 21 May 2013

OpenFlow Switch on Raspberry Pi Part 2: Installing the OpenFlow switch on the hardware

In the first article I introduced the concept of building the worlds cheapest OpenFlow switch based on the Raspberry Pi. A 4 port switch was constructed from about £50 worth of hardware.

We are now going to install the open source software on the Pi to get ourselves a functioning switch.

The software we are going to use is one which I've been involved with for about 18 months which is the LINC OpenFlow switch.  This switch is written in Erlang and can be downloaded for free from flowforwarding.org

First we need to install Erlang on our Raspberry Pi.  I have assumed your Pi is running Raspbian - if not you'll need to download the image onto a new SD card.

First you need a command prompt on your Pi as we need to edit some files

pi@raspberrypi ~ $ sudo vi /etc/apt/sources.list

Insert into this file:

deb http://binaries.erlang-solutions.com/debian wheezy contrib

Then at the command prompt type

pi@raspberrypi ~ $ wget -O - http://binaries.erlang-solutions.com/debian/erlang_solutions.asc |sudo apt-key add -
pi@raspberrypi ~ $ sudo apt-get update
pi@raspberrypi ~ $ sudo apt-get install esl-erlang

Assuming there were no problems, you should now have Erlang installed on your Pi.

We now need to install LINC.

First we need to install a few more libraries

pi@raspberrypi ~ $ sudo apt-get install git-core bridge-utils libpcap0.8 libpcap-dev libcap2-bin uml-utilities

Now we need to clone the LINC switch

pi@raspberrypi ~ $ sudo git clone https://github.com/FlowForwarding/LINC-Switch/
pi@raspberrypi ~ $ cd LINC_Switch

Now we need to compile the switch software

pi@raspberrypi ~ $ sudo make

 We now have a LINC OpenFlow switch installed on our Raspberry Pi hardware.

In the next blog I will cover how to configure it and start it up

Cheapest OpenFlow switch in the world. Using the Raspberry Pi as an OpenFlow switch.

If you want to learn about OpenFlow, there is no better way than to experiment.

So how do you experiment when this stuff is new?

Simple. Copy Google and build your own network!

I am currently building my own OpenFlow switch so I can build my an OpenFlow lab and start experimenting. The goals for my DIY switch are that it has to be cheap, easy to build and useful.

Thankfully lots of other amazing people have done all the hard work for me.  You'll be able to build your own OpenFlow switch for about £50.

I'm using the Raspberry Pi which you can buy for around £30. The Raspberry Pi is a small ARM based computer running Linux. It has an HDMI port, composite video, Ethernet port and 2xUSB ports.

OK you might be thinking this isn't going to make much of a router when it only has 1x Ethernet port!

To solve that problem I'm using a USB hub and have bought some USB to Ethernet adapters for about £3 each and a WiFi dongle based on the RTL8188CUS chipset for about £8.

Assuming you have a USB mouse, USB keyboard, a monitor or TV with a HDMI port + HDMI cable and a USB hub then the cost for 3xEthernet + 1xWiFi switch/router will be £44.

Here's mine:


The Raspberry Pi recognised the USB to Ethernet adaptors and dongle straight-off so no messing around with drivers.

This isn't going to be fastest router/switch on the planet. Firstly running Ethernet over USB is slow anyway and these adaptors are USB 1.1 (what do you expect for £3) so they will max out at about 6Mbit/s anyway.
The Raspberry Pi is hardly a high spec computer either and in addition we will be running the switch software in user space.

[Post blog note.  These USB to Ethernet adaptors are pretty crap. The Chinese manufacturer has programmed them all with the same MAC address....It's not the end of the world - you can over-ride it with ifconfig but still bloody annoying. AlsoI'd recommend the RT5370 WiFi dongles over the RTL8188CUS - I had problems getting the RTL to work in Access Point mode.  See this blog post for more details on both of these points.]

The purpose of this switch is not speed. It's to learn.

In future articles I will explain how to  install the software on your Raspberry Pi, get your controller and start experimenting.

I'm also experimenting with the slightly more expensive RouterBoard 450GL. This is custom built low-end 5 port router for about £80.  This is a little more involved to hack and will be covered in later articles.