From 7e79d1351cd29636f3977799b8f027a248b5d775 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Fri, 3 Feb 2012 18:26:24 -0800 Subject: [PATCH] Changes (OVS 1.2.2, NOX destiny) for installation on Ubuntu 11.10 oneiric. --- util/install.sh | 56 ++-- ...1-OpenFlow-tutorial-port-nox-destiny.patch | 298 ++++++++++++++++++ util/nox-patches/README | 1 + 3 files changed, 330 insertions(+), 25 deletions(-) create mode 100644 util/nox-patches/0001-OpenFlow-tutorial-port-nox-destiny.patch create mode 100644 util/nox-patches/README diff --git a/util/install.sh b/util/install.sh index ef76354..292bd26 100755 --- a/util/install.sh +++ b/util/install.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# Mininet install script for Debian +# Mininet install script for Ubuntu (and Debian Lenny) # Brandon Heller (brandonh@stanford.edu) # Fail on error @@ -35,9 +35,10 @@ KERNEL_IMAGE_OLD=linux-image-2.6.26-2-686 DRIVERS_DIR=/lib/modules/${KERNEL_NAME}/kernel/drivers/net -OVS_RELEASE=v1.1.1 -OVS_DIR=~/openvswitch -OVS_KMOD=openvswitch_mod.ko +OVS_RELEASE=v1.2.2 +OVS_SRC=~/openvswitch +OVS_BUILD=$OVS_SRC/build-$KERNEL_NAME +OVS_KMODS=($OVS_BUILD/datapath/linux/{openvswitch_mod.ko,brcompat_mod.ko}) function kernel { echo "Install Mininet-compatible kernel" @@ -151,12 +152,12 @@ function of { sudo sh -c "echo 'blacklist net-pf-10\nblacklist ipv6' >> $BLACKLIST" } -# Install OpenVSwitch +# Install Open vSwitch # Instructions derived from OVS INSTALL, INSTALL.OpenFlow and README files. function ovs { - echo "Installing OpenVSwitch..." + echo "Installing Open vSwitch..." - if [ "$DIST" = "Debian" ]; then + if [ "$DIST" = "Debian" && `lsb-release -c` == "lenny" ]; then sudo aptitude -y install pkg-config gcc make git-core python-dev libssl-dev # Install Autoconf 2.63+ backport from Debian Backports repo: # Instructions from http://backports.org/dokuwiki/doku.php?id=instructions @@ -173,7 +174,7 @@ function ovs { # Install OVS from release cd ~/ git clone git://openvswitch.org/openvswitch - cd $OVS_DIR + cd $OVS_SRC git checkout $OVS_RELEASE ./boot.sh BUILDDIR=/lib/modules/${KERNEL_NAME}/build @@ -181,10 +182,14 @@ function ovs { echo "Creating build sdirectory $BUILDDIR" sudo mkdir -p $BUILDDIR fi - opts="--with-l26=$BUILDDIR" - ./configure $opts + opts="--with-linux=$BUILDDIR" + mkdir -p $OVS_BUILD + cd $OVS_BUILD + ../configure $opts make sudo make install + # openflowd is deprecated, but for now copy it in + sudo cp tests/test-openflowd /usr/local/bin/ovs-openflowd } # Install NOX with tutorial files @@ -193,7 +198,7 @@ function nox { # Install NOX deps: sudo apt-get -y install autoconf automake g++ libtool python python-twisted \ - swig libxerces-c2-dev libssl-dev make + swig libssl-dev make if [ "$DIST" = "Debian" ]; then sudo apt-get -y install libboost1.35-dev elif [ "$DIST" = "Ubuntu" ]; then @@ -204,21 +209,22 @@ function nox { # Install NOX optional deps: sudo apt-get install -y libsqlite3-dev python-simplejson - # Install NOX: + # Fetch NOX destiny cd ~/ - git clone git://openflowswitch.org/nox-tutorial noxcore + git clone git://noxrepo.org/nox noxcore cd noxcore + git checkout -b destiny remotes/origin/destiny - # With later autoconf versions this doesn't quite work: - ./boot.sh --apps-core || true - if [ "$DIST" = "Debian" ]; then - # So use this instead: - autoreconf --install --force - fi + # Apply patches + git checkout -b tutorial-destiny + git am ~/mininet/util/nox-patches/*.patch + + # Build + ./boot.sh mkdir build cd build - ../configure --with-python=yes - make + ../configure + make -j3 #make check # Add NOX_CORE_DIR env var: @@ -299,7 +305,7 @@ function other { function modprobe { echo "Setting up modprobe for OVS kmod..." - sudo cp $OVS_DIR/datapath/linux-2.6/$OVS_KMOD $DRIVERS_DIR + sudo cp $OVS_KMODS $DRIVERS_DIR sudo depmod -a ${KERNEL_NAME} } @@ -353,11 +359,11 @@ function usage { printf 'Usage: %s [-acdfhkmntvxy]\n\n' $(basename $0) >&2 printf 'This install script attempts to install useful packages\n' >&2 - printf 'for Mininet. It should (hopefully) work on Ubuntu 10.04 and\n' >&2 - printf 'Debian 5.0 (Lenny). If you run into trouble, try\n' >&2 + printf 'for Mininet. It should (hopefully) work on Ubuntu 10.04, 11.10\n' >&2 + printf 'and Debian 5.0 (Lenny). If you run into trouble, try\n' >&2 printf 'installing one thing at a time, and looking at the \n' >&2 printf 'specific installation function in this script.\n\n' >&2 - + printf 'options:\n' >&2 printf -- ' -a: (default) install (A)ll packages - good luck!\n' >&2 printf -- ' -b: install controller (B)enchmark (oflops)\n' >&2 diff --git a/util/nox-patches/0001-OpenFlow-tutorial-port-nox-destiny.patch b/util/nox-patches/0001-OpenFlow-tutorial-port-nox-destiny.patch new file mode 100644 index 0000000..881fc55 --- /dev/null +++ b/util/nox-patches/0001-OpenFlow-tutorial-port-nox-destiny.patch @@ -0,0 +1,298 @@ +From 5c9610ffb88c89b0f36359ad3c7547831482a3ff Mon Sep 17 00:00:00 2001 +From: Bob Lantz +Date: Fri, 3 Feb 2012 14:48:58 -0800 +Subject: [PATCH] OpenFlow tutorial port nox-destiny. + +--- + src/nox/coreapps/examples/Makefile.am | 2 +- + src/nox/coreapps/examples/tutorial/Makefile.am | 25 ++++ + src/nox/coreapps/examples/tutorial/meta.json | 12 ++ + src/nox/coreapps/examples/tutorial/pytutorial.py | 67 +++++++++++ + src/nox/coreapps/examples/tutorial/tutorial.cc | 134 ++++++++++++++++++++++ + 5 files changed, 239 insertions(+), 1 deletions(-) + create mode 100644 src/nox/coreapps/examples/tutorial/Makefile.am + create mode 100644 src/nox/coreapps/examples/tutorial/__init__.py + create mode 100644 src/nox/coreapps/examples/tutorial/meta.json + create mode 100644 src/nox/coreapps/examples/tutorial/pytutorial.py + create mode 100644 src/nox/coreapps/examples/tutorial/tutorial.cc + +diff --git a/src/nox/coreapps/examples/Makefile.am b/src/nox/coreapps/examples/Makefile.am +index 126f32e..1a0458c 100644 +--- a/src/nox/coreapps/examples/Makefile.am ++++ b/src/nox/coreapps/examples/Makefile.am +@@ -1,6 +1,6 @@ + include ../../../Make.vars + +-SUBDIRS = t ++SUBDIRS = tutorial t + + EXTRA_DIST =\ + meta.json\ +diff --git a/src/nox/coreapps/examples/tutorial/Makefile.am b/src/nox/coreapps/examples/tutorial/Makefile.am +new file mode 100644 +index 0000000..51cf921 +--- /dev/null ++++ b/src/nox/coreapps/examples/tutorial/Makefile.am +@@ -0,0 +1,25 @@ ++include ../../../../Make.vars ++ ++EXTRA_DIST =\ ++ meta.xml \ ++ __init__.py \ ++ pytutorial.py ++ ++if PY_ENABLED ++AM_CPPFLAGS += $(PYTHON_CPPFLAGS) ++endif # PY_ENABLED ++ ++pkglib_LTLIBRARIES = \ ++ tutorial.la ++ ++tutorial_la_CPPFLAGS = $(AM_CPPFLAGS) -I $(top_srcdir)/src/nox -I $(top_srcdir)/src/nox/coreapps/ ++tutorial_la_SOURCES = tutorial.cc ++tutorial_la_LDFLAGS = -module -export-dynamic ++ ++NOX_RUNTIMEFILES = meta.json \ ++ __init__.py \ ++ pytutorial.py ++ ++all-local: nox-all-local ++clean-local: nox-clean-local ++install-exec-hook: nox-install-local +diff --git a/src/nox/coreapps/examples/tutorial/__init__.py b/src/nox/coreapps/examples/tutorial/__init__.py +new file mode 100644 +index 0000000..e69de29 +diff --git a/src/nox/coreapps/examples/tutorial/meta.json b/src/nox/coreapps/examples/tutorial/meta.json +new file mode 100644 +index 0000000..7a9f227 +--- /dev/null ++++ b/src/nox/coreapps/examples/tutorial/meta.json +@@ -0,0 +1,12 @@ ++{ ++ "components": [ ++ { ++ "name": "tutorial", ++ "library": "tutorial" ++ }, ++ { ++ "name": "pytutorial", ++ "python": "nox.coreapps.examples.tutorial.pytutorial" ++ } ++ ] ++} +diff --git a/src/nox/coreapps/examples/tutorial/pytutorial.py b/src/nox/coreapps/examples/tutorial/pytutorial.py +new file mode 100644 +index 0000000..1e21c0b +--- /dev/null ++++ b/src/nox/coreapps/examples/tutorial/pytutorial.py +@@ -0,0 +1,67 @@ ++# Tutorial Controller ++# Starts as a hub, and your job is to turn this into a learning switch. ++ ++import logging ++ ++from nox.lib.core import * ++import nox.lib.openflow as openflow ++from nox.lib.packet.ethernet import ethernet ++from nox.lib.packet.packet_utils import mac_to_str, mac_to_int ++ ++log = logging.getLogger('nox.coreapps.tutorial.pytutorial') ++ ++ ++class pytutorial(Component): ++ ++ def __init__(self, ctxt): ++ Component.__init__(self, ctxt) ++ # Use this table to store MAC addresses in the format of your choice; ++ # Functions already imported, including mac_to_str, and mac_to_int, ++ # should prove useful for converting the byte array provided by NOX ++ # for packet MAC destination fields. ++ # This table is initialized to empty when your module starts up. ++ self.mac_to_port = {} # key: MAC addr; value: port ++ ++ def learn_and_forward(self, dpid, inport, packet, buf, bufid): ++ """Learn MAC src port mapping, then flood or send unicast.""" ++ ++ # Initial hub behavior: flood packet out everything but input port. ++ # Comment out the line below when starting the exercise. ++ self.send_openflow(dpid, bufid, buf, openflow.OFPP_FLOOD, inport) ++ ++ # Starter psuedocode for learning switch exercise below: you'll need to ++ # replace each pseudocode line with more specific Python code. ++ ++ # Learn the port for the source MAC ++ #self.mac_to_port = ++ #if (destination MAC of the packet is known): ++ # Send unicast packet to known output port ++ #self.send_openflow( ) ++ # Later, only after learning controller works: ++ # push down flow entry and remove the send_openflow command above. ++ #self.install_datapath_flow( ) ++ #else: ++ #flood packet out everything but the input port ++ #self.send_openflow(dpid, bufid, buf, openflow.OFPP_FLOOD, inport) ++ ++ def packet_in_callback(self, dpid, inport, reason, len, bufid, packet): ++ """Packet-in handler""" ++ if not packet.parsed: ++ log.debug('Ignoring incomplete packet') ++ else: ++ self.learn_and_forward(dpid, inport, packet, packet.arr, bufid) ++ ++ return CONTINUE ++ ++ def install(self): ++ self.register_for_packet_in(self.packet_in_callback) ++ ++ def getInterface(self): ++ return str(pytutorial) ++ ++def getFactory(): ++ class Factory: ++ def instance(self, ctxt): ++ return pytutorial(ctxt) ++ ++ return Factory() +diff --git a/src/nox/coreapps/examples/tutorial/tutorial.cc b/src/nox/coreapps/examples/tutorial/tutorial.cc +new file mode 100644 +index 0000000..e7240cc +--- /dev/null ++++ b/src/nox/coreapps/examples/tutorial/tutorial.cc +@@ -0,0 +1,134 @@ ++#include "component.hh" ++#include "config.h" ++#include "packet-in.hh" ++#include "flow.hh" ++#include "assert.hh" ++#include "netinet++/ethernetaddr.hh" ++#include "netinet++/ethernet.hh" ++#include ++#include ++#ifdef LOG4CXX_ENABLED ++#include ++#include "log4cxx/logger.h" ++#else ++#include "vlog.hh" ++#endif ++ ++using namespace std; ++using namespace vigil; ++using namespace vigil::container; ++ ++namespace ++{ ++ static Vlog_module lg("tutorial"); ++ ++ /** Learning switch. ++ */ ++ class tutorial ++ : public Component ++ { ++ public: ++ /** Constructor. ++ */ ++ tutorial(const Context* c, const json_object* node) ++ : Component(c) ++ { } ++ ++ /** Configuration. ++ * Add handler for packet-in event. ++ */ ++ void configure(const Configuration*) ++ { ++ register_handler ++ (boost::bind(&tutorial::handle, this, _1)); ++ } ++ ++ /** Just simply install. ++ */ ++ void install() ++ { ++ lg.dbg(" Install called "); ++ } ++ ++ /** Function to setup flow. ++ */ ++ void setup_flow(Flow& flow, datapathid datapath_id , ++ uint32_t buffer_id, uint16_t out_port) ++ { ++ ofp_flow_mod* ofm; ++ size_t size = sizeof *ofm + sizeof(ofp_action_output); ++ boost::shared_array raw_of(new char[size]); ++ ofm = (ofp_flow_mod*) raw_of.get(); ++ ++ ofm->header.version = OFP_VERSION; ++ ofm->header.type = OFPT_FLOW_MOD; ++ ofm->header.length = htons(size); ++ ofm->match.wildcards = htonl(0); ++ ofm->match.in_port = htons(flow.in_port); ++ ofm->match.dl_vlan = flow.dl_vlan; ++ memcpy(ofm->match.dl_src, flow.dl_src.octet, sizeof ofm->match.dl_src); ++ memcpy(ofm->match.dl_dst, flow.dl_dst.octet, sizeof ofm->match.dl_dst); ++ ofm->match.dl_type = flow.dl_type; ++ ofm->match.nw_src = flow.nw_src; ++ ofm->match.nw_dst = flow.nw_dst; ++ ofm->match.nw_proto = flow.nw_proto; ++ ofm->match.tp_src = flow.tp_src; ++ ofm->match.tp_dst = flow.tp_dst; ++ ofm->command = htons(OFPFC_ADD); ++ ofm->buffer_id = htonl(buffer_id); ++ ofm->idle_timeout = htons(5); ++ ofm->hard_timeout = htons(OFP_FLOW_PERMANENT); ++ ofm->priority = htons(OFP_DEFAULT_PRIORITY); ++ ofp_action_output& action = *((ofp_action_output*)ofm->actions); ++ memset(&action, 0, sizeof(ofp_action_output)); ++ action.type = htons(OFPAT_OUTPUT); ++ action.len = htons(sizeof(ofp_action_output)); ++ action.max_len = htons(0); ++ action.port = htons(out_port); ++ send_openflow_command(datapath_id, &ofm->header, true); ++ } ++ ++ /** Function to handle packets. ++ * @param datapath_id datapath id of switch ++ * @param in_port port packet is received ++ * @param buffer_id buffer id of packet ++ * @param source source mac address in host order ++ * @param destination destination mac address in host order ++ */ ++ void handle_packet(datapathid datapath_id, uint16_t in_port, uint32_t buffer_id, ++ uint64_t source, uint64_t destination) ++ { ++ send_openflow_packet(datapath_id, buffer_id, OFPP_FLOOD, ++ in_port, true); ++ } ++ ++ /** Packet-on handler. ++ */ ++ Disposition handle(const Event& e) ++ { ++ const Packet_in_event& pi = assert_cast(e); ++ uint32_t buffer_id = pi.buffer_id; ++ Flow flow(pi.in_port, *pi.get_buffer()); ++ ++ // drop LLDP packets ++ if (flow.dl_type == ethernet::LLDP) ++ return CONTINUE; ++ ++ // pass handle of unicast packet, else flood ++ if (!flow.dl_src.is_multicast()) ++ handle_packet(pi.datapath_id, pi.in_port, buffer_id, ++ flow.dl_src.hb_long(), flow.dl_dst.hb_long()); ++ else ++ send_openflow_packet(pi.datapath_id, buffer_id, OFPP_FLOOD, ++ pi.in_port, true); ++ ++ return CONTINUE; ++ } ++ ++ private: ++}; ++ ++REGISTER_COMPONENT(container::Simple_component_factory, ++ tutorial); ++ ++} // unnamed namespace +-- +1.7.5.4 + diff --git a/util/nox-patches/README b/util/nox-patches/README new file mode 100644 index 0000000..5c8dce8 --- /dev/null +++ b/util/nox-patches/README @@ -0,0 +1 @@ +This patch adds the OpenFlow tutorial module source code to nox-destiny.