...
We start by defining a new interface for the service in the same location as our application onos-api package (~/onos-next/appscore/ifwdapi/src/main/java/org/onlab/onos/ifwd/):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 | ||||||
---|---|---|---|---|---|---|
| ||||||
package org.onlab.onos.ifwd; import java.util.Map; import org.onlab.onos.net.HostId; /** * ACopyright demonstrative2014 serviceOpen forNetworking theLaboratory intent* reactive* forwardingLicensed applicationunder to the *Apache export */ public interface ForwardingMapService { /** * Get the endpoints of the host-to-host intents that were installed * * @return maps of source to destination */ public Map<HostId, HostId> getEndPoints(); } |
2. Import the service interface.
Next, we implement our service in IntentReactiveForwarding
. We also indicate to Karaf that the application exports a service, using the the Felix SCR annotation @Service
:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
@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, the @Service
annotation enables another class to reference the service through the @Reference
annotation:
Code Block | ||||
---|---|---|---|---|
| ||||
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ForwardingMapService fwdMapService; |
3. Implement the service.
We can now define the new method. We add a new Map, endPoints
, to IntentReactiveForwarding
. The map is populated when the ReactivePacketProcessor
's process()
method finds endpoints known by the HostService.
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.onos.net.apps;
import java.util.Map;
import org.onlab.onos.net.HostId;
/**
* A demonstrative service for the intent reactive forwarding application to
* export
*/
public interface ForwardingMapService {
/**
* Get the endpoints of the host-to-host intents that were installed
*
* @return maps of source to destination
*/
public Map<HostId, HostId> getEndPoints();
} |
2. Import the service interface.
Next, we implement our service in IntentReactiveForwarding
. We also indicate to Karaf that the application exports a service, using the the Felix SCR annotation @Service
:
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.onos.ifwd;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
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.onlab.onos.core.ApplicationId;
import org.onlab.onos.core.CoreService;
import org.onlab.onos.net.Host;
import org.onlab.onos.net.HostId;
import org.onlab.onos.net.PortNumber;
import org.onlab.onos.net.apps.ForwardingMapService;
import org.onlab.onos.net.flow.DefaultTrafficSelector;
import org.onlab.onos.net.flow.DefaultTrafficTreatment;
import org.onlab.onos.net.flow.TrafficSelector;
import org.onlab.onos.net.flow.TrafficTreatment;
import org.onlab.onos.net.host.HostService;
import org.onlab.onos.net.intent.HostToHostIntent;
import org.onlab.onos.net.intent.IntentService;
import org.onlab.onos.net.packet.DefaultOutboundPacket;
import org.onlab.onos.net.packet.InboundPacket;
import org.onlab.onos.net.packet.OutboundPacket;
import org.onlab.onos.net.packet.PacketContext;
import org.onlab.onos.net.packet.PacketProcessor;
import org.onlab.onos.net.packet.PacketService;
import org.onlab.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, the @Service
annotation enables another class to reference the service through the @Reference
annotation:
Code Block | ||||
---|---|---|---|---|
| ||||
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ForwardingMapService fwdMapService; |
3. Implement the service.
We can now define the new method. We add a new Map, endPoints
, to IntentReactiveForwarding
. The map is populated when the ReactivePacketProcessor
's process()
method finds endpoints known by the HostService.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
@Component(immediate = true)
@Service
public class IntentReactiveForwarding implements ForwardingMapService {
// ...<snip>...
private ApplicationId appId;
// Map for storing found endpoints, for our service. It is protected
// so that process() can access it.
protected final HashMap<HostId, HostId> endPoints = new HashMap<>();
// ...<snip>...
/**
* Packet processor responsible for forwarding packets along their paths.
*/
private class ReactivePacketProcessor implements PacketProcessor {
@Override
public void process(PacketContext context) {
// Stop processing if the packet has been handled, since we
| ||||||
Code Block | ||||||
| ||||||
@Component(immediate = true) @Service public class IntentReactiveForwarding implements ForwardingMapService { // ...<snip>... private ApplicationId appId; // Map for storing found endpoints, for our service. It is protected // so that process() can access it. protected final HashMap<HostId, HostId> endPoints = new HashMap<>(); // ...<snip>... /** * Packet processor responsible for forwarding packets along their paths. */ private class ReactivePacketProcessor implements PacketProcessor { @Override public void process(PacketContext context) { // Stop processing if the packet has been handled, since we // can't do any more to it. if (context.isHandled()) { return; } InboundPacket pkt = context.inPacket(); Ethernet ethPkt = pkt.parsed(); // HostIdcan't srcIddo = HostId.hostId(ethPkt.getSourceMAC()); any more to it. HostId dstId =if HostId.hostId(ethPktcontext.getDestinationMACisHandled()); { // Do we know who this is for? If not, flood and bail...<snip>... Host dst = hostService.getHost(dstId); if (dst == null) { flood(context); return; } // Add found endpoints to map. endPoints.put(srcId, dstId); // Otherwise forward and be done with it. setUpConnectivity(context, srcId, dstId); forwardPacketToDst(context, dst); } } // ...<snip>... @Override public Map<HostId, HostId> getEndPoints() { // Return our map as a read-only structure. return Collections.unmodifiableMap(endPoints); } } |
...
Since our command will display network-related information, we will add our command to the second directory.
1. Create a command class.
We create the following class skeleton for our new command, tentatively named ForwardingMapCommand
. Our class is a child of AbstractShellCommand
, and the @Command
annotation is used to set its name, scope, and description.uses some command-related annotations:
@Command
- used to set a command's name, scope, and description.@Argument
- used to indicate that a variable is set by a command-line argument.
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.onos.cli.net; import org.apache.karaf.shell.commands.Argument; import org.apache.karaf.shell.commands.Command; import org.onlab.onos.cli.AbstractShellCommand; import org.onlab.onos.net.HostId; /** * 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() { } } |
The annotation enables annotations enable this particular command to be invoked as fwdmap
or onos:fwdmap
at the CLI. In addition, it can also take a host ID as an option, e.g. fwdmap 06:38:27:D5:68:88/-1
.
2. Incorporate the new service.
3. Register the command with Karaf CLI.
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 append the following to the contents between the <command-bundle></command-bundle>
clause:
...