Overview
An ONOS application is essentially an OSGi bundle built as a Maven project. Therefore, an ONOS application can be boiled down to a collection of Java classes and POM files (Maven Program Object Manager files, written in XML.) This tutorial discusses how to manually roll out an application from scratch, using the intent-based reactive forwarding application as an example.
By completing this tutorial, you will understand:
- The organization and structure of an application
- How to register your application with various services
- The basics of using the ONOS northbound API
- How to run an application
Conventions
Before we begin, we note that we make use of collapsible code blocks so that the page doesn't get too long and cluttered. A collapsed block has an Expand Source link that displays the contents when selected:
${ONOS_ROOT} refers to the project root directory for ONOS. For example, if the project directory is ~/onos, cd ${ONOS_ROOT}
is equivalent to cd ~/onos
.
Finally, we assume that you have checked out the ONOS source code as per Getting ONOS, set up your environment as per Environment Setup, and have imported it to some IDE, as per IDE Setup. This exercise can be done using any text editor, but an IDE makes life much easier.
Project skeleton setup
As a reference, the structure of our application can be summarized by the following directory structure:
${ONOS_ROOT}/apps/pom.xml (apps parent POM file) | /ifwd/pom.xml (application POM file) | /src/main/java/org/onosproject/ifwd/IntentReactiveForwarding.java (the application) | | | /package-info.java (optional package-wide documentation/annotations) | /test/java/org/onosproject/ifwd/ (Unit tests go here)
1. Set up a directory layout
The first step to creating a new application is to build the following directory structure. This structure follows Maven's conventions.
The application root directory is placed under apps/ of the ONOS project root:
$ mkdir -p ${ONOS_ROOT}/apps/ifwd
The application source class definitions are placed under src/main/java/... of the application root:
$ mkdir -p ${ONOS_ROOT}/apps/ifwd/src/main/java/org/onosproject/ifwd
Similarly, unit tests are placed under src/test/java/... of the application root:
$ mkdir -p ${ONOS_ROOT}/apps/ifwd/src/test/java/org/onosproject/ifwd
2. Add and edit POM files
In this case, the final bundle will be known as 'onos-app-ifwd'. This would be the name used with commands such as feature:install
from the Karaf/ONOS CLI.
Next, edit apps/pom.xml to include ifwd (note, not the bundle name, but the application root directory) as one of its child projects:
<modules> <module>tvue</module> <module>fwd</module> <module>ifwd</module> <---added here <module>foo</module> <module>mobility</module> <module>proxyarp</module> <module>config</module> <module>sdnip</module> <module>calendar</module> <module>optical</module> <module>metrics</module> <module>oecfg</module> <module>demo</module> </modules>
3. Register the Application with Karaf
Karaf runtime requires an application description called a feature to deploy the module as an OSGi bundle (see the Karaf documentation for more detail). Edit ${ONOS_ROOT}/features/features.xml to include the following snippet, which describes the feature declaration for our application.
Writing the application
Once we have a project skeleton, we can begin to write our application. The core of the forwarding app is named IntentReactiveForwarding.java, and is defined in ${ONOS_ROOT}/apps/src/main/java/org/onosproject/ifwd/ .
For the sake of documentation or package-wide annotations, a package-info.java file may be added along with the application, containing the following:
/** * Sample reactive forwarding application using intent framework. */ package org.onosproject.ifwd;
An IDE will often provide an option to generate this file.
The rest of the tutorial describes how to build out the Intent
ReactiveForwarding
class.
1. Register with Karaf to load automatically
Karaf's module loading mechanism recognizes several annotations that allow a class to register with it. In particular:
@Component(immediate = true)
- declares a class as a component to activate, and forces immediate activation.@Activate
- marks a method as the method to call during the component startup routine.@Deactivate
- marks a method as the method to call during component shutdown.@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- Marks a service as an application's dependency, and requires one instance of such a service to be loaded before this application's activation.
We first start by "wiring up" our application to Karaf:
More information about these and other annotations are available on the Felix documentation.
2. Register for Services.
Next, our application must register with CoreService to acquire an unique application ID before it can make use of ONOS's various services. It may then register with the PacketService to listen in on network traffic events (packet-ins) and to send out packets (packet-outs). In specific, the PacketService needs to be provided with an event handler (i.e., a class implementing PacketProcessor
).
Our modified activate()
and deactivate()
methods now register and deregister from these two services, and we also define a PacketProcessor implementation as an inner class:
3. Add packet handling code.
The method process()
of our handler is called by the PacketService each time it receives a network packet. This means that we can define our packet forwarding behavior in this method:
We define the helper functions used by process()
in IntentReactiveForwarding
(the outer class).
Note that, even though we are controlling OpenFlow switches with our application, we do not speak in terms of OpenFlow messages. The intent framework abstracts the protocol-specific mechanisms away.
4. Build the application.
Since the application is a project of its own, it can be built independently of the rest of ONOS by running Maven from the project root directory:
$ cd ${ONOS_ROOT}/apps/ifwd && maven clean install [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building onos-app-ifwd 1.0.0-SNAPSHOT [INFO] ------------------------------------------------------------------------ ... <more output> [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 6.258s [INFO] Finished at: Mon Dec 01 23:09:21 PST 2014 [INFO] Final Memory: 30M/316M [INFO] ------------------------------------------------------------------------ $
Our application may now be loaded and used.
Starting the application
Dynamically (at runtime)
The application can be enabled both from the ONOS CLI and the Karaf Web Console. In the first case, just type the following command in the ONOS CLI:
onos> feature:install onos-app-ifwd
Statically (at startup)
The application can be loaded by configuring org.apache.karaf.features.cfg, in the /etc folder of the Karaf installation. This configuration file contains a list of features that Karaf loads when is started (featuresBoot). We can simply add the feature onos-app-ifwd in this list:
featuresBoot=config,standard,region,package,kar,ssh,management,webconsole,onos-api,onos-core-trivial,onos-cli,onos-openflow,onos-gui,onos-rest,onos-app-mobility,onos-app-ifwd
ONOS must be restarted in this case.
What next?
- Try extending this application into a service, and extend the CLI with a command that uses it, in the CLI and Service Tutorial.
- Learn how to create application templates with Maven in the Component Template Tutorial.
- See what is involved in extending the southbound in the Provider Tutorial.
Return To : Tutorials and Walkthroughs
2 Comments
Brian Freeman
The path referenced in step 3 "ONOS_ROOT/src/main/java/org/onosproject/ifwd/ . " should be $ONOS_ROOT/apps/ifwd/src/main/java/org/onosproject/ifwd - its under apps/ifwd not just $ONOS_ROOT
References to ONOS_ROOT should be "$ONOS_ROOT"
Ayaka Koshibe
Nice catch. By the way - if you create an account, you'll be able to edit the wiki without having to wait on someone else.