second try
[vsorcdistro/.git] / mininet / util / nox-patches / 0001-OpenFlow-tutorial-port-nox-destiny.patch
1 From 5c9610ffb88c89b0f36359ad3c7547831482a3ff Mon Sep 17 00:00:00 2001
2 From: Bob Lantz <rlantz@cs.stanford.edu>
3 Date: Fri, 3 Feb 2012 14:48:58 -0800
4 Subject: [PATCH] OpenFlow tutorial port nox-destiny.
5
6 ---
7  src/nox/coreapps/examples/Makefile.am            |    2 +-
8  src/nox/coreapps/examples/tutorial/Makefile.am   |   25 ++++
9  src/nox/coreapps/examples/tutorial/meta.json     |   12 ++
10  src/nox/coreapps/examples/tutorial/pytutorial.py |   67 +++++++++++
11  src/nox/coreapps/examples/tutorial/tutorial.cc   |  134 ++++++++++++++++++++++
12  5 files changed, 239 insertions(+), 1 deletions(-)
13  create mode 100644 src/nox/coreapps/examples/tutorial/Makefile.am
14  create mode 100644 src/nox/coreapps/examples/tutorial/__init__.py
15  create mode 100644 src/nox/coreapps/examples/tutorial/meta.json
16  create mode 100644 src/nox/coreapps/examples/tutorial/pytutorial.py
17  create mode 100644 src/nox/coreapps/examples/tutorial/tutorial.cc
18
19 diff --git a/src/nox/coreapps/examples/Makefile.am b/src/nox/coreapps/examples/Makefile.am
20 index 126f32e..1a0458c 100644
21 --- a/src/nox/coreapps/examples/Makefile.am
22 +++ b/src/nox/coreapps/examples/Makefile.am
23 @@ -1,6 +1,6 @@
24  include ../../../Make.vars 
25  
26 -SUBDIRS = t
27 +SUBDIRS = tutorial t
28  
29  EXTRA_DIST =\
30         meta.json\
31 diff --git a/src/nox/coreapps/examples/tutorial/Makefile.am b/src/nox/coreapps/examples/tutorial/Makefile.am
32 new file mode 100644
33 index 0000000..51cf921
34 --- /dev/null
35 +++ b/src/nox/coreapps/examples/tutorial/Makefile.am
36 @@ -0,0 +1,25 @@
37 +include ../../../../Make.vars 
38 +
39 +EXTRA_DIST =\
40 +       meta.xml \
41 +       __init__.py \
42 +       pytutorial.py
43 +
44 +if PY_ENABLED
45 +AM_CPPFLAGS += $(PYTHON_CPPFLAGS)
46 +endif # PY_ENABLED 
47 +
48 +pkglib_LTLIBRARIES =           \
49 +       tutorial.la
50 +
51 +tutorial_la_CPPFLAGS = $(AM_CPPFLAGS) -I $(top_srcdir)/src/nox -I $(top_srcdir)/src/nox/coreapps/
52 +tutorial_la_SOURCES = tutorial.cc
53 +tutorial_la_LDFLAGS = -module -export-dynamic
54 +
55 +NOX_RUNTIMEFILES = meta.json \
56 +       __init__.py \
57 +       pytutorial.py
58 +
59 +all-local: nox-all-local
60 +clean-local: nox-clean-local 
61 +install-exec-hook: nox-install-local
62 diff --git a/src/nox/coreapps/examples/tutorial/__init__.py b/src/nox/coreapps/examples/tutorial/__init__.py
63 new file mode 100644
64 index 0000000..e69de29
65 diff --git a/src/nox/coreapps/examples/tutorial/meta.json b/src/nox/coreapps/examples/tutorial/meta.json
66 new file mode 100644
67 index 0000000..7a9f227
68 --- /dev/null
69 +++ b/src/nox/coreapps/examples/tutorial/meta.json
70 @@ -0,0 +1,12 @@
71 +{
72 +    "components": [
73 +        {
74 +            "name": "tutorial",
75 +            "library": "tutorial" 
76 +        },
77 +        {
78 +            "name": "pytutorial",
79 +            "python": "nox.coreapps.examples.tutorial.pytutorial" 
80 +        }
81 +    ]
82 +}
83 diff --git a/src/nox/coreapps/examples/tutorial/pytutorial.py b/src/nox/coreapps/examples/tutorial/pytutorial.py
84 new file mode 100644
85 index 0000000..1e21c0b
86 --- /dev/null
87 +++ b/src/nox/coreapps/examples/tutorial/pytutorial.py
88 @@ -0,0 +1,67 @@
89 +# Tutorial Controller
90 +# Starts as a hub, and your job is to turn this into a learning switch.
91 +
92 +import logging
93 +
94 +from nox.lib.core import *
95 +import nox.lib.openflow as openflow
96 +from nox.lib.packet.ethernet import ethernet
97 +from nox.lib.packet.packet_utils import mac_to_str, mac_to_int
98 +
99 +log = logging.getLogger('nox.coreapps.tutorial.pytutorial')
100 +
101 +
102 +class pytutorial(Component):
103 +
104 +    def __init__(self, ctxt):
105 +        Component.__init__(self, ctxt)
106 +        # Use this table to store MAC addresses in the format of your choice;
107 +        # Functions already imported, including mac_to_str, and mac_to_int,
108 +        # should prove useful for converting the byte array provided by NOX
109 +        # for packet MAC destination fields.
110 +        # This table is initialized to empty when your module starts up.
111 +        self.mac_to_port = {} # key: MAC addr; value: port
112 +
113 +    def learn_and_forward(self, dpid, inport, packet, buf, bufid):
114 +        """Learn MAC src port mapping, then flood or send unicast."""
115 +        
116 +        # Initial hub behavior: flood packet out everything but input port.
117 +        # Comment out the line below when starting the exercise.
118 +        self.send_openflow(dpid, bufid, buf, openflow.OFPP_FLOOD, inport)
119 +
120 +        # Starter psuedocode for learning switch exercise below: you'll need to
121 +        # replace each pseudocode line with more specific Python code.
122 +
123 +        # Learn the port for the source MAC
124 +        #self.mac_to_port = <fill in>
125 +        #if (destination MAC of the packet is known):
126 +            # Send unicast packet to known output port
127 +            #self.send_openflow( <fill in params> )
128 +            # Later, only after learning controller works: 
129 +            # push down flow entry and remove the send_openflow command above.
130 +            #self.install_datapath_flow( <fill in params> )
131 +        #else:
132 +            #flood packet out everything but the input port
133 +            #self.send_openflow(dpid, bufid, buf, openflow.OFPP_FLOOD, inport)
134 +
135 +    def packet_in_callback(self, dpid, inport, reason, len, bufid, packet):
136 +        """Packet-in handler""" 
137 +        if not packet.parsed:
138 +            log.debug('Ignoring incomplete packet')
139 +        else:
140 +            self.learn_and_forward(dpid, inport, packet, packet.arr, bufid)    
141 +
142 +        return CONTINUE
143 +
144 +    def install(self):
145 +        self.register_for_packet_in(self.packet_in_callback)
146 +    
147 +    def getInterface(self):
148 +        return str(pytutorial)
149 +
150 +def getFactory():
151 +    class Factory:
152 +        def instance(self, ctxt):
153 +            return pytutorial(ctxt)
154 +
155 +    return Factory()
156 diff --git a/src/nox/coreapps/examples/tutorial/tutorial.cc b/src/nox/coreapps/examples/tutorial/tutorial.cc
157 new file mode 100644
158 index 0000000..e7240cc
159 --- /dev/null
160 +++ b/src/nox/coreapps/examples/tutorial/tutorial.cc
161 @@ -0,0 +1,134 @@
162 +#include "component.hh"
163 +#include "config.h"
164 +#include "packet-in.hh"
165 +#include "flow.hh"
166 +#include "assert.hh"
167 +#include "netinet++/ethernetaddr.hh"
168 +#include "netinet++/ethernet.hh"
169 +#include <boost/shared_array.hpp>
170 +#include <boost/bind.hpp>
171 +#ifdef LOG4CXX_ENABLED
172 +#include <boost/format.hpp>
173 +#include "log4cxx/logger.h"
174 +#else
175 +#include "vlog.hh"
176 +#endif
177 +
178 +using namespace std;
179 +using namespace vigil;
180 +using namespace vigil::container;
181 +
182 +namespace
183 +{
184 +  static Vlog_module lg("tutorial");
185
186 +  /** Learning switch.
187 +   */
188 +  class tutorial
189 +    : public Component 
190 +  {
191 +  public:
192 +    /** Constructor.
193 +     */
194 +    tutorial(const Context* c, const json_object* node)
195 +      : Component(c) 
196 +    { }
197 +    
198 +    /** Configuration.
199 +     * Add handler for packet-in event.
200 +     */
201 +    void configure(const Configuration*) 
202 +    {
203 +      register_handler<Packet_in_event>
204 +       (boost::bind(&tutorial::handle, this, _1));
205 +    }
206 +    
207 +    /** Just simply install.
208 +     */
209 +    void install() 
210 +    {
211 +      lg.dbg(" Install called ");
212 +    }
213 +
214 +    /** Function to setup flow.
215 +     */
216 +    void setup_flow(Flow& flow, datapathid datapath_id , 
217 +                   uint32_t buffer_id, uint16_t out_port)
218 +    {
219 +      ofp_flow_mod* ofm;
220 +      size_t size = sizeof *ofm + sizeof(ofp_action_output);
221 +      boost::shared_array<char> raw_of(new char[size]);
222 +      ofm = (ofp_flow_mod*) raw_of.get();
223 +
224 +      ofm->header.version = OFP_VERSION;
225 +      ofm->header.type = OFPT_FLOW_MOD;
226 +      ofm->header.length = htons(size);
227 +      ofm->match.wildcards = htonl(0);
228 +      ofm->match.in_port = htons(flow.in_port);
229 +      ofm->match.dl_vlan = flow.dl_vlan;
230 +      memcpy(ofm->match.dl_src, flow.dl_src.octet, sizeof ofm->match.dl_src);
231 +      memcpy(ofm->match.dl_dst, flow.dl_dst.octet, sizeof ofm->match.dl_dst);
232 +      ofm->match.dl_type = flow.dl_type;
233 +      ofm->match.nw_src = flow.nw_src;
234 +      ofm->match.nw_dst = flow.nw_dst;
235 +      ofm->match.nw_proto = flow.nw_proto;
236 +      ofm->match.tp_src = flow.tp_src;
237 +      ofm->match.tp_dst = flow.tp_dst;
238 +      ofm->command = htons(OFPFC_ADD);
239 +      ofm->buffer_id = htonl(buffer_id);
240 +      ofm->idle_timeout = htons(5);
241 +      ofm->hard_timeout = htons(OFP_FLOW_PERMANENT);
242 +      ofm->priority = htons(OFP_DEFAULT_PRIORITY);
243 +      ofp_action_output& action = *((ofp_action_output*)ofm->actions);
244 +      memset(&action, 0, sizeof(ofp_action_output));
245 +      action.type = htons(OFPAT_OUTPUT);
246 +      action.len = htons(sizeof(ofp_action_output));
247 +      action.max_len = htons(0);
248 +      action.port = htons(out_port);
249 +      send_openflow_command(datapath_id, &ofm->header, true);
250 +    }
251 +
252 +    /** Function to handle packets.
253 +     * @param datapath_id datapath id of switch
254 +     * @param in_port port packet is received
255 +     * @param buffer_id buffer id of packet
256 +     * @param source source mac address in host order
257 +     * @param destination destination mac address in host order
258 +     */
259 +    void handle_packet(datapathid datapath_id, uint16_t in_port, uint32_t buffer_id, 
260 +                      uint64_t source, uint64_t destination)
261 +    {
262 +      send_openflow_packet(datapath_id, buffer_id, OFPP_FLOOD,
263 +                          in_port, true);
264 +    }
265 +
266 +    /** Packet-on handler.
267 +     */
268 +    Disposition handle(const Event& e)
269 +    {
270 +      const Packet_in_event& pi = assert_cast<const Packet_in_event&>(e);
271 +      uint32_t buffer_id = pi.buffer_id;
272 +      Flow flow(pi.in_port, *pi.get_buffer());
273 +
274 +      // drop LLDP packets
275 +      if (flow.dl_type == ethernet::LLDP)
276 +        return CONTINUE;
277 +
278 +      // pass handle of unicast packet, else flood
279 +      if (!flow.dl_src.is_multicast())
280 +       handle_packet(pi.datapath_id, pi.in_port, buffer_id, 
281 +                     flow.dl_src.hb_long(), flow.dl_dst.hb_long());
282 +      else
283 +       send_openflow_packet(pi.datapath_id, buffer_id, OFPP_FLOOD,
284 +                            pi.in_port, true);
285 +      
286 +      return CONTINUE;
287 +    }
288 +    
289 +  private:
290 +};
291 +
292 +REGISTER_COMPONENT(container::Simple_component_factory<tutorial>,
293 +                   tutorial);
294 +
295 +} // unnamed namespace
296 -- 
297 1.7.5.4
298