1 | % SDN / OpenFlow tutorial |
---|
2 | % |
---|
3 | % First SDN Application |
---|
4 | |
---|
5 | # Introduction |
---|
6 | |
---|
7 | In this lab we will connect write our first SDN application and run it on the controller. |
---|
8 | |
---|
9 | # Goals |
---|
10 | |
---|
11 | * Write an SDN application using the Ryu framework |
---|
12 | * Start the application on the controller. |
---|
13 | |
---|
14 | # Notes |
---|
15 | |
---|
16 | * Commands preceded with "$" imply that you should execute the command as |
---|
17 | a general user - not as root. |
---|
18 | * Commands preceded with "#" imply that you should be working as root. |
---|
19 | * Commands with more specific command lines (e.g. "RTR-GW>" or "mysql>") |
---|
20 | imply that you are executing commands on remote equipment, or within |
---|
21 | another program. |
---|
22 | |
---|
23 | # Installation |
---|
24 | |
---|
25 | ## A very simple switch. |
---|
26 | |
---|
27 | Open up a terminal on the controller and create the following file |
---|
28 | |
---|
29 | $ vi ~/l2.py |
---|
30 | |
---|
31 | It should contain the following |
---|
32 | |
---|
33 | from ryu.base import app_manager |
---|
34 | from ryu.controller import mac_to_port |
---|
35 | from ryu.controller import ofp_event |
---|
36 | from ryu.controller.handler import MAIN_DISPATCHER |
---|
37 | from ryu.controller.handler import set_ev_cls |
---|
38 | from ryu.ofproto import ofproto_v1_3 |
---|
39 | from ryu.lib.mac import haddr_to_bin |
---|
40 | from ryu.lib.packet import packet |
---|
41 | from ryu.lib.packet import ethernet |
---|
42 | |
---|
43 | class L2Switch(app_manager.RyuApp): |
---|
44 | def __init__(self, *args, **kwargs): |
---|
45 | super(L2Switch, self).__init__(*args, **kwargs) |
---|
46 | |
---|
47 | @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER) |
---|
48 | def packet_in_handler(self, ev): |
---|
49 | msg = ev.msg |
---|
50 | dp = msg.datapath |
---|
51 | ofp = dp.ofproto |
---|
52 | ofp_parser = dp.ofproto_parser |
---|
53 | in_port = msg.match['in_port'] |
---|
54 | |
---|
55 | actions = [ofp_parser.OFPActionOutput(ofp.OFPP_FLOOD)] |
---|
56 | out = ofp_parser.OFPPacketOut( |
---|
57 | datapath=dp, buffer_id=msg.buffer_id, in_port=in_port, |
---|
58 | actions=actions) |
---|
59 | dp.send_msg(out) |
---|
60 | |
---|
61 | |
---|
62 | With one window open on your controller, and the other window on your datapath element, start this application on the controller with the following command. |
---|
63 | |
---|
64 | $ ryu-manager --verbose ~/l2.py |
---|
65 | |
---|
66 | Then run the following on the datapath element |
---|
67 | |
---|
68 | # /root/bootovs-rb532.sh |
---|
69 | |
---|
70 | |
---|
71 | Once everything has started you can confirm that the datapath element has contacted the controller |
---|
72 | |
---|
73 | 2014-01-28T04:56:02Z|00030|rconn|INFO|br0<->tcp:10.10.0.1:6633: connected |
---|
74 | |
---|
75 | Every time a packet arrives on either of the datapath ports the following message will be printed on the controller screen |
---|
76 | |
---|
77 | EVENT ofp_event->L2Switch EventOFPPacketIn |
---|
78 | EVENT ofp_event->L2Switch EventOFPPacketIn |
---|
79 | EVENT ofp_event->L2Switch EventOFPPacketIn |
---|
80 | EVENT ofp_event->L2Switch EventOFPPacketIn |
---|
81 | EVENT ofp_event->L2Switch EventOFPPacketIn |
---|
82 | EVENT ofp_event->L2Switch EventOFPPacketIn |
---|
83 | |
---|
84 | You can confirm this by having someone plug a laptop into the rb532 |
---|
85 | |
---|
86 | |
---|
87 | ## A more complicated switch |
---|
88 | |
---|
89 | git clone https://code.google.com/r/dean-nsss/ |
---|
90 | |
---|
91 | ryu-manager --verbose ./dean-nsss/simple_switch_13.py |
---|
92 | |
---|
93 | |
---|
94 | On the datapath element run the monitor_flows command |
---|
95 | |
---|
96 | $ ./monitor_flows.sh |
---|
97 | |
---|
98 | This should give the output similar to the following |
---|
99 | |
---|
100 | Tue Jan 28 05:01:57 UTC 2014 |
---|
101 | OFPST_FLOW reply (OF1.3) (xid=0x2): |
---|
102 | cookie=0x0, duration=10.535s, table=0, n_packets=27, n_bytes=4624, priority=1,in_port=1,dl_src=3c:07:54:49:ee:97 actions=goto_table:1 |
---|
103 | cookie=0x0, duration=93.21s, table=1, n_packets=3, n_bytes=1026, priority=10,dl_dst=ff:ff:ff:ff:ff:ff actions=ALL |
---|
104 | cookie=0x0, duration=93.21s, table=1, n_packets=0, n_bytes=0, priority=5,dl_type=0x88cc actions=drop |
---|
105 | cookie=0x0, duration=93.21s, table=1, n_packets=0, n_bytes=0, priority=5,dl_type=0x05ff actions=drop |
---|
106 | cookie=0x0, duration=93.21s, table=1, n_packets=15, n_bytes=3058, priority=11,dl_dst=33:33:00:00:00:00/ff:ff:00:00:00:00 actions=ALL |
---|
107 | cookie=0x0, duration=93.21s, table=1, n_packets=0, n_bytes=0, priority=10,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=ALL |
---|
108 | cookie=0x0, duration=93.21s, table=1, n_packets=9, n_bytes=540, priority=0 actions=FLOOD,CONTROLLER:64 |
---|
109 | |
---|
110 | --End |
---|