...
As a reference, our collection of additions/modifications can be summarized in the following directory layout:
Code Block | ||
---|---|---|
| ||
${ONOS_ROOT}/apps/pom.xml (apps parent POM) | | | /ifwd/pom.xml (application POM) | | | /src/main/java/org/onosproject/ifwd/IntentReactiveForwarding.java (the application) | | | | | /package-info.java (optional documentation/annotations) | | | /test/java/org/onosproject/ifwd/ (Unit tests go here) | /core/api/src/main/java/org/onosproject/net/apps/ForwardingMapService.java (the service interface) | /cli/src/main/java/org/onosproject/cli/net/ForwardingMapCommand.java (the command) | /resources/OSGI-INF/blueprint/shell-config.xml (Karaf shell configuration) |
Conventions
${ONOS_ROOT} refers to the project root directory for ONOS. For example, if the project directory is ~/onos_next, cd ${ONOS_ROOT}
is equivalent to cd ~/onos_next
.
...
We start by defining a new interface for the service in the onos-api package (${ONOS_ROOT}/core/api/src/main/java/org/onosproject/net/). We also create a new directory, apps/, for our service interface to reside in. The interface is added to this location so that the cli package that implements the commands has access to it.
...
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
/* * Copyright 2014 Open Networking Laboratory * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.onlab.onosonosproject.ifwd; import java.util.Collections; import java.util.concurrent.ConcurrentHashMapMap; import java.util.concurrent.ConcurrentMapConcurrentHashMap; import java.util.concurrent.MapConcurrentMap; import org.apache.felix.scr.annotations.Activate; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Deactivate; import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.ReferenceCardinality; import org.apache.felix.scr.annotations.Service; import org.onlabonosproject.onos.core.ApplicationId; import org.onlabonosproject.onos.core.CoreService; import org.onlab.onosonosproject.net.Host; import org.onlab.onosonosproject.net.HostId; import org.onlab.onosonosproject.net.PortNumber; import org.onlabonosproject.onos.net.apps.ForwardingMapService; import org.onlabonosproject.onos.net.flow.DefaultTrafficSelector; import org.onlab.onosonosproject.net.flow.DefaultTrafficTreatment; import org.onlabonosproject.onos.net.flow.TrafficSelector; import org.onlab.onosonosproject.net.flow.TrafficTreatment; import org.onlabonosproject.onos.net.host.HostService; import org.onlabonosproject.onos.net.intent.HostToHostIntent; import org.onlabonosproject.onos.net.intent.IntentService; import org.onlabonosproject.onos.net.packet.DefaultOutboundPacket; import org.onlab.onosonosproject.net.packet.InboundPacket; import org.onlabonosproject.onos.net.packet.OutboundPacket; import org.onlabonosproject.onos.net.packet.PacketContext; import org.onlabonosproject.onos.net.packet.PacketProcessor; import org.onlab.onosonosproject.net.packet.PacketService; import org.onlabonosproject.onos.net.topology.TopologyService; import org.onlab.packet.Ethernet; import org.slf4j.Logger; import static org.slf4j.LoggerFactory.getLogger; @Component(immediate = true) @Service public class IntentReactiveForwarding implements ForwardingMapService { private final Logger log = getLogger(getClass()); @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected CoreService coreService; // ...<snip>... // Install a rule forwarding the packet to the specified port. private void setUpConnectivity(PacketContext context, HostId srcId, HostId dstId) { TrafficSelector selector = DefaultTrafficSelector.builder().build(); TrafficTreatment treatment = DefaultTrafficTreatment.builder().build(); HostToHostIntent intent = new HostToHostIntent(appId, srcId, dstId, selector, treatment); intentService.submit(intent); } // the new service method, to be filled out @Override public Map<HostId, HostId> getEndPoints() { return null; } } |
...
Although we won't be using it here in this manner in this tutorial, the @Service
annotation enables another class to reference the service through the @Reference
annotation:
...
The CLI commands are defined in the project directory ${ONOS_ROOT}/cli/. There are two types of commands, with their source files located in the following locations:
- ${ONOS_ROOT}/cli/src/main/java/org/onlabonosproject/onos/cli - Commands related to system configuration and monitoring
- ${ONOS_ROOT}/cli/src/main/java/org/onlabonosproject/onos/cli/net - Commands related to network configuration and monitoring
Since our command will display network-related information, we will add our command to the second second net directory.
1. Create a command class.
...
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
/* * Copyright 2014 Open Networking Laboratory * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.onlabonosproject.onos.cli.net; import org.apache.karaf.shell.commands.Argument; import org.apache.karaf.shell.commands.Command; import org.onlabonosproject.onos.cli.AbstractShellCommand; import org.onlab.onos.onosproject.net.HostId; import org.onosproject.net.HostIdapps.ForwardingMapService; /** * Lists * A demo service that lists the endpoints for which intents are installed. */ @Command(scope = "onos", name = "fwdmap", description = "Lists the endpoints for which intents are installed") public class ForwardingMapCommand extends AbstractShellCommand { @Argument(index = 0, name = "hostId", description = "Host ID of source", required = false, multiValued = false) private HostId hostId = null; @Override protected void execute() { } } |
...
Code Block | ||||
---|---|---|---|---|
| ||||
/* * Copyright 2014 Open Networking Laboratory * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.onlabonosproject.onos.cli.net; import java.util.Map; import org.apache.karaf.shell.commands.Argument; import org.apache.karaf.shell.commands.Command; import org.onlabonosproject.onos.cli.AbstractShellCommand; import org.onlabonosproject.onos.net.HostId; import org.onlabonosproject.onos.net.apps.ForwardingMapService; /** * ListsA demo service that lists the endpoints for which intents are installed. */ @Command(scope = "onos", name = "fwdmap", description = "Lists the endpoints for which intents are installed") public class ForwardingMapCommand extends AbstractShellCommand { // formatted string for output to CLI private static final String FMT = "src=%s, dst=%s"; // the String to hold the optional argument @Argument(index = 0, name = "hostId", description = "Host ID of source", required = false, multiValued = false) private String hostId = null; // reference to our service private ForwardingMapService service; // to hold the service's response private Map<HostId, HostId> hmap; @Override protected void execute() { // get a reference to our service service = get(ForwardingMapService.class); /* * getEndPoints() returns an empty map even if it contains nothing, so * we don't need to check for null hmap here. */ hmap = service.getEndPoints(); // check for an argument, then display information accordingly if (hostId != null) { // we were given a hostId to filter on, print only those that match HostId host = HostId.hostId(hostId); for (Map.Entry<HostId, HostId> el : hmap.entrySet()) { if (el.getKey().equals(hostId)) { print(FMT, el.getKey(), el.getValue()); } } } else { // print everything we have for (Map.Entry<HostId, HostId> el : hmap.entrySet()) { print(FMT, el.getKey(), el.getValue()); } } } } |
...
Next, we need to tell Karaf about our new command by editing shell-config.xml, located in ${ONOS_ROOT}/cli/src/main/resources/OSGI-INF/blueprint/. We add the following to the contents between the <command-bundle></command-bundle>
clause in the file:
Code Block | ||||
---|---|---|---|---|
| ||||
<command> <!--Our command implementation's FQDN--> <action class="org.onlab.onosonosproject.cli.net.ForwardingMapCommand"/> <!--A command completer for Host IDs--> <completers> <ref component-id="hostIdCompleter"/> <null/> </completers> </command> |
...
Code Block | ||
---|---|---|
| ||
$ cd ${ONOS_ROOT} $ mvn clean install $ karaf clean |
...
Code Block | ||
---|---|---|
| ||
onos> fwdmap onos> |
Generate So, generate traffic on Mininet:
Code Block | ||
---|---|---|
| ||
mininet> pingall *** Ping: testing ping reachability h1 -> h2 h3 h4 h2 -> h1 h3 h4 h3 -> h1 h2 h4 h4 -> h1 h2 h3 *** Results: 0% dropped (12/12 received) |
...
Code Block | ||
---|---|---|
| ||
onos> fwdmap 00:00:00:00:00:04/-1 src=00:00:00:00:00:04/-1, dst=00:00:00:00:00:03/-1 |
Since we We had also configured autocomplete, so we are presented with the available options when we hit Tab:
Code Block | ||
---|---|---|
| ||
onos> fwdmap <tab> onos> fwdmap 00:00:00:00:00:0 00:00:00:00:00:01/-1 00:00:00:00:00:02/-1 00:00:00:00:00:03/-1 00:00:00:00:00:04/-1 |
What next?
- Check out the Documentation Set for deep dives into the architecture or the development process.
...
Return To : Tutorials and Walkthroughs
...