We are going to practice how to add flow entry in ONOS in this tutorial. Besides, we are going to use the example program (SimpleForwarding.java).
We provide an example code (SimpleForwarding.java) which includes the following parts.
activateprocessorinstallRulepacketOutflooddeactivate
The workflow of SimpleForwarding.java is as follow.
- Activate the processor
- When the packet forwarded in controller, the processer start to process the packet
- Flood the packet or install forwardign rule in flow table
@Activate
protected void activate() {
appId = coreService.regirsterApplication("nctu_nss.app");
packetService.addProcessor(processor, PacketProcessor.director(2));
TrafficSelector.Builder.selector = DefaultTrafficSelector.builder();
selector.matchEthType(Ethernet.TYPE_IPV4).matchEthType(Ethernet.TYPE_ARP);
packetService.requestPackets(selector.build(), PacketPriority.REACTIVE, appId);
log.info("Started");
}The above code is in SimpleForwarding.java and the descriptions are as follow.
- Register the app and get
appIdwhich is a globle variableappId = coreService.registerApplication("nctu_nss.app");
- Create a flow entry with matching the type of Ethernet is ARP or IPv4
packetService.addProcessor(processor, PacketProcessor.director(2)); TrafficSelector.Builder.selector = DefaultTrafficSelector.builder(); selector.matchEthType(Ethernet.TYPE_IPV4).matchEthType(Ethernet.TYPE_ARP);
- Add the flow created above into switch
packetService.requestPackets(selector.build(), PacketPriority.REACTIVE, appId);
- The flow entry will be as follow:
Match Priority Action Ethernet_Type=ARP REACTIVE(5) Output=Controller Ethernet_Type=IPV4 REACTIVE(5) Output=Controller
- The flow entry will be as follow:
private class ReactivePacketProcessor implements PacketProcessor {
@Override
public void process(PacketContext context) {
// Stop processing if the packet has been handled, since we cannot do anymore to it.
if (context.isHandled()) {
return;
}
InboundPacket pkt = context.inPacket();
Ethernet ethPkt = pkt.parsed();
if (ethPkt == null) {
return;
}
HostId srcId = HostId.hostId(ethPkt.getSourceMAC());
HostId dstId = HostId.hostId(ethPkt.getDestinationMAC());
// Do we know who this is for? If not, flood and bail.
Host dst = hostService.getHost(dstId);
if (dst == null || ethPkt.getEtherType() == Ethernet.TYPE_ARP) {
flood(context);l
return;
}
installRule(context, srcId, dstId);
}
}The above code is in SimpleForwarding.java and the descriptions are as follow.
- Stop processing if the packet has been handled
if (context.isHandled()) { return; }
- Parser the input packet
InboundPacket pkt = context.inPacket(); Ethernet ethPkt = pkt.parsed(); if (ethPkt == null) { return; }
- Get the source and the destination MAC address from the packet
HostId srcId = HostId.hostId(ethPkt.getSourceMAC()); HostId dstId = HostId.hostId(ethPkt.getDestinationMAC());
- If the type of Ethernet is ARP, then flood; else install the forwarding rule
// Do we know who this is for? If not, flood and bail. Host dst = hostService.getHost(dstId); if (dst == null || ethPkt.getEtherType() == Ethernet.TYPE_ARP) { flood(context);l return; } installRule(context, srcId, dstId);
private void installRule(PacketContext context, HostId, srcId, HostId dstId) {
Ethernet inPkt = context.inPacket().parsed();
TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
Host dst = hostService.getHost(dstId);
Host src = hostService.getHost(srcId);
if (src == null || dst == null) {
return;
} else {
selectorBuilder.matchEthSrc(inPkt.getSourceMAC())
.matchEthDst(inPkt.getDestinationMAC());
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
.setOutput(dst.location().port())
.build()
ForwardingObjective forwardingObjective = DefaultForwardingObjective.builder()
.withSelector(selectorBuilder.build())
.withTreatment(treatment)
.withPriority(10)
.withFlag(ForwardingObjective.Flag.VERSATILE)
.fromApp(appId)
.makeTemporary(10) // Timeout
.add();
flowObjectiveService.forward(context.inPacket().receivedFrom().deviceId(), forwardingObjective);
packetOut(context, PortNumber.TABLE);
}
}The above code is in SimpleForwarding.java and the descriptions are as follow. The differences of "keyword" between OpenFlow and ONOS is as follow:
| ONOS | OpenFlow |
|---|---|
| TrafficSelector | Match |
| TrafficTreatment | Action |
- Parse the input packet
Ethernet inPkt = context.inPacket().parsed();
- Build a traffic selector for matching rule
TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
- Find out the source host and the destination host are in the topology via
HostServiceHost dst = hostService.getHost(dstId); Host src = hostService.getHost(srcId);
- To use
HostService, you need to activate the appHost Location Provider. - The app
Host Location Providerwill add some default rule in the system and forward the ARP packets to ONOS controller. Thus, you can ignore the ARP packets inprocessor
- To use
- If the source and the destination host are existed in the topology, then create a flow entry with the mathcing rule via
TrafficSelectorand the action viaTrafficTreatment.selectorBuilder.matchEthSrc(inPkt.getSourceMAC()) .matchEthDst(inPkt.getDestinationMAC()); TrafficTreatment treatment = DefaultTrafficTreatment.builder() .setOutput(dst.location().port()) .build(); ForwardingObjective forwardingObjective = DefaultForwardingObjective.builder() .withSelector(selectorBuilder.build()) .withTreatment(treatment) .withPriority(10) .withFlag(ForwardingObjective.Flag.VERSATILE) .fromApp(appId) .makeTemporary(10) //timeout .add();
- Add the flow entry via
FlowObjectiveServiceflowObjectiveService.forward(context.inPacket().receivedFrom().deviceId(), forwardingObjective);
- Set the number of port for packet-out to make the packet be processed by the flow table with rules
packetOut(context, PortNumber.TABLE);
private void packetOut(PacketContext context, PortNumber portNumber) {
context.treatmentBuilder().setOutput(portNumber);
context.send();
}The above code is in SimpleForwarding.java and the descriptions are as follow.
- Set the number of port for the traffic treatment
context.treatmentBuilder().setOutput(portNumber);
- Trigger the outbound packet to be sent
context.send();
private void flood(PacketContext context) {
if (topologyService.isBroadcastPoint(topologyService.currentTopology(), context.inPacket().receivedFrom())) {
packetOut(context, PortNumber.FLOOD);
} else {
context.block();
}
}The above code is in SimpleForwarding.java and the descriptions are as follow.
- Check whether broadcast is allowed for traffic received on the specifed connection point
if (topologyService.isBroadcastPoint(topologyService.currentTopology(), context.inPacket().receivedFrom()))
- If the connection is in the topology, then flood via
packetOutpacketOut(context, PortNumber.FLOOD);
- Otherwise, block the outbound packet from being sent
context.block();
@Deactivate
protected void deactivate() {
packetService.removeProcessor(processor);
processor = null;
log.info("Stopped");
}The above code is in SimpleForwarding.java and the descriptions are as follow.
- Remove the processor of packets service
packetService.removeProcessor(processor);
- Make the processor point at
nullto end the appprocessor = null;
You can refer to the tutorial "Build a ONOS App With Maven"
- Build a template with Maven (take few minutes)
# Make sure your current directory is the place you want to place your repository mvn archetype:generate -DarchetypeGroupId=org.onosproject -DarchetypeArtifactId=onos-bundle-archetype - During the building, it may ask you set some information about this repository (e.g., maintainer, name, etc.)
groupidis the name of your organization.artifactIdis the name of this app.
Define value for property 'groupId': nctu_nss Define value for property 'artifactId': simple-forwarding Define value for property 'version' 1.0-SNAPSHOT: : Define value for property 'package' nctu_nss : Confirm properties configuration: groupId: nctu_nss artifactId: simple-forwarding version: 1.0-SNAPSHOT package: nctu_nss Y: : y
- If succeed, you will see the following messsage:
[INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 25.497 s [INFO] Finished at: 2018-12-15T20:10:06+08:00 [INFO] Final Memory: 19M/310M [INFO] ------------------------------------------------------------------------
- Modify
pom.xml<!-- The following is an example! --> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <onos.version>2.0.0-b1</onos.version> <onos.app.name>nctu_nss.simple-forwarding</onos.app.name> <onos.app.title>Simple Forwarding</onos.app.title> <onos.app.origin>NCTU NSSLAB</onos.app.origin> <!-- <onos.app.category>default</onos.app.category> <onos.app.url>http://onosproject.org</onos.app.url> <onos.app.readme>ONOS OSGi bundle archetype.</onos.app.readme> --> </properties>
- Add the following scripts in the tag
<dependencies>ofpom.xml<!-- Add the dependency here! --> <dependency> <groupId>org.apache.felix</groupId> <artifactId>org.apache.felix.scr.annotations</artifactId> <version>1.12.0</version> </dependency>
- Replace the file
./simple-forwarding/src/main/java/nctu_nss/AppComponent.javato./SimpleForwarding.java - Rename the file
./simple-forwarding/src/test/java/nctu_nss/AppComponentTest.javato./simple-forwarding/src/test/java/nctu_nss/SimpleForwardingTest.java - Modify the file
./simple-forwarding/src/test/java/nctu_nss/SimpleForwardingTest.javaas followpublic class SimpleForwardingTest { private SimpleForwarding component; @Before public void setUp() { //component = new SimpleForwarding(); //component.activate(); } @After public void tearDown() { //component.deactivate(); } @Test public void basics() { } }
- Make sure you have already commented the code in above before compiling; otherwise, the compilation may go wrong!
- Compile the app with Maven (take few minutes)
# Make sure your current directory is in ./simple-forwarding/ $ mvn clean install - If succeed, you will get message as follow:
[INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 3.984 s [INFO] Finished at: 2018-12-15T17:34:39+08:00 [INFO] Final Memory: 31M/458M [INFO] ------------------------------------------------------------------------
- The compiled app will be put in
./simple-forwarding/target/.
- The compiled app will be put in
- How to activate the app with ONOS GUI? Please refer to the section 2.5 in the tutorial "Build a ONOS App With Maven"
ONOS code is hosted and maintained using Gerrit. Code on GitHub is only a mirror. The ONOS project does NOT accepte code through pull request on GitHub. To contribute to ONOS, please refer to Sample Gerrrit Workflow. It should includes most of things you'll need to get your contribution started!
Apache License 2.0