ONOS 二层转发应用
org.onosproject.fwd
应用应该说是ONOS中最核心的应用了,要想让我们创建的Mininet虚拟网络实现二层互通,就需要激活这个官方应用,因此从这个应用中我们能够学习到ONOS对网络的抽象方式,以及二层转发功能实现方式。截至本文发布之时ONOS的最新版本是1.13.0-SNAPSHOT
,因此这里的源码也截至最新开发版。首先我们还是看一下应用的pom.xml
文件。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.onosproject</groupId>
<artifactId>onos-apps</artifactId>
<version>1.13.0-SNAPSHOT</version>
</parent>
<artifactId>onos-app-fwd</artifactId>
<packaging>bundle</packaging>
<description>Reactive forwarding application using flow subsystem</description>
<properties>
<onos.app.name>org.onosproject.fwd</onos.app.name>
<onos.app.title>Reactive Forwarding App</onos.app.title>
<onos.app.category>Traffic Steering</onos.app.category>
<onos.app.url>http://onosproject.org</onos.app.url>
<onos.app.readme>Reactive forwarding application using flow subsystem.</onos.app.readme>
</properties>
<dependencies>
...
</dependencies>
</project>
根据简介,我们可以得知这里的二层转发方式是使用Flow子系统来实现的,具体细化一下应该是FlowObjectiveService
。更加详尽的介绍我们可以在BUCK
文件中找到(值得一提的是,ONOS已经使用BUCK作为默认构建方式,虽然Maven仍然可以使用)。
Provisions traffic between end-stations using hop-by-hop flow programming by intercepting packets for which there are currently no matching flow objectives on the data plane.
The paths paved in this manner are short-lived, i.e. they expire a few seconds after the flow on whose behalf they were programmed stops.
The application relies on the ONOS path service to compute the shortest paths.
In the event of negative topology events (link loss, device disconnect, etc.), the application will proactively invalidate any paths that it had programmed to lead through the resources that are no longer available.
应用结构
org.onosproject.fwd
下包含几个文件
MacAddressCompleter.java
ReactiveForwarding.java
ReactiveForwardingCommand.java
ReactiveForwardMetrics.java
MacAddressCompleter
public class MacAddressCompleter implements Completer {
@Override
public int complete(String buffer, int cursor, List<String> candidates) {
// Delegate string completer
StringsCompleter delegate = new StringsCompleter();
EventuallyConsistentMap<MacAddress, ReactiveForwardMetrics> macAddress;
// Fetch our service and feed it's offerings to the string completer
ReactiveForwarding reactiveForwardingService = AbstractShellCommand.get(ReactiveForwarding.class);
macAddress = reactiveForwardingService.getMacAddress();
SortedSet<String> strings = delegate.getStrings();
for (MacAddress key : macAddress.keySet()) {
strings.add(key.toString());
}
// Now let the completer do the work for figuring out what to offer.
return delegate.complete(buffer, cursor, candidates);
}
}
很容易看出来,这个类是用来CLI下补全MAC地址的,在resources/OSGI-INF.blueprint/shell-config.xml
文件中我们可以看到命令的定义方式。
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
<command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
<command>
<action class="org.onosproject.fwd.ReactiveForwardingCommand"/>
<completers>
<ref component-id="MacAddressCompleter"/>
</completers>
</command>
</command-bundle>
<bean id="MacAddressCompleter" class="org.onosproject.fwd.MacAddressCompleter"/>
</blueprint>
将Completer
声明为一个bean,引用在org.onosproject.fwd.ReactiveForwardingCommand
中。那么我们接下来看一下Command的实现。
ReactiveForwardingCommand
@Command(scope = "onos", name = "reactive-fwd-metrics",
description = "List all the metrics of reactive fwd app based on mac address")
public class ReactiveForwardingCommand extends AbstractShellCommand {
@Argument(index = 0, name = "mac", description = "One Mac Address",
required = false, multiValued = false)
String mac = null;
@Override
protected void execute() {
ReactiveForwarding reactiveForwardingService = AbstractShellCommand.get(ReactiveForwarding.class);
MacAddress macAddress = null;
if (mac != null) {
macAddress = MacAddress.valueOf(mac);
}
reactiveForwardingService.printMetric(macAddress);
}
}
可以看到,这里用注解创建了一个CLI命令,名为onos:reactive-fwd-metrics
,后面加mac地址,可以打印出对应主机的metrics。
onos> onos:reactive-fwd-metrics aa:0e:a8:c8:c9:a8
-----------------------------------------------------------------------------------------
MACADDRESS Metrics
AA:0E:A8:C8:C9:A8 null
ReactiveForwardMetrics
public class ReactiveForwardMetrics {
private Long replyPacket = null;
private Long inPacket = null;
private Long droppedPacket = null;
private Long forwardedPacket = null;
private MacAddress macAddress;
}
可以看到,ReactiveForwardMetrics
这个应用是用来统计Packet的处理情况的,上面的代码中省略了对数量进行更新的函数以及toString
函数。
ReactiveForwarding
这个类是fwd应用中最核心的文件,实现了转发的具体逻辑。