org.onosproject.fwd 应用解析

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应用中最核心的文件,实现了转发的具体逻辑。

发表评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注