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.


2 comments:

  1. Thanks a lot for you clear explanation. Awaiting for your next post on test scenario and controlled traffic.

    ReplyDelete
  2. I'm using the l2_switch_v1_3.py above on my Ryu, and my Ryu and LINC connect OK, and the LINC has 3 ports created... but I never see a flow table being created. Anyone have this issue?

    ReplyDelete