ONOS-ifwd源码分析,参考资料:https://www.sdnlab.com/10297.html
在之前的文章中,介绍了ONOS-sample-apps的获取,但是将其生成的oar文件导入到ONOS-2.0及其以上版本的时候,是不能够运行的,本文在参考了一些资料的基础上,解决ifwd模块对ONOS版本的不兼容问题,并且对ifwd的源码进行分析学习。
1.源码的修改
1.将import里面的apache服务修改成osgi组件,如下
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.Modified;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
将以上代码修改为
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
2.修改Reference服务的关键字参数,将
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected TopologyService topologyService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected PacketService packetService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected HostService hostService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected DeviceService deviceService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected FlowRuleService flowRuleService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected StatisticStore statisticStore;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected FlowObjectiveService flowObjectiveService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CoreService coreService;
修改为:
@Reference(cardinality = ReferenceCardinality.MANDATORY)
protected CoreService coreService;
@Reference(cardinality = ReferenceCardinality.MANDATORY)
protected TopologyService topologyService;
@Reference(cardinality = ReferenceCardinality.MANDATORY)
protected PacketService packetService;
@Reference(cardinality = ReferenceCardinality.MANDATORY)
protected IntentService intentService;
@Reference(cardinality = ReferenceCardinality.MANDATORY)
protected HostService hostService;
@Reference(cardinality = ReferenceCardinality.MANDATORY)
protected FlowRuleService flowRuleService;
@Reference(cardinality = ReferenceCardinality.MANDATORY)
protected FlowObjectiveService flowObjectiveService;
2.POM文件的修改
由于ifwd模块在拉取下来的时候,pom文件的onos版本是1.8.0版本的,以及依赖也有一些缺失。可以直接粘贴复制我修改后的pom文件:
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2014-2016 Open Networking Foundation
~
~ 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.
-->
<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-dependencies</artifactId>
<version>1.8.0</version>
<relativePath/><!-- parent is remote -->
</parent>
<artifactId>onos-app-ifwd</artifactId>
<version>1.8.0-SNAPSHOT</version>
<packaging>bundle</packaging>
<description>Reactive forwarding application using intent service (experimental)</description>
<properties>
<onos.version>2.0.0</onos.version>
<onos.app.name>org.onosproject.ifwd</onos.app.name>
<onos.app.origin>ON.Lab</onos.app.origin>
<onos.app.title>Reactive Forwarding App (Intent)</onos.app.title>
<onos.app.category>Traffic Steering</onos.app.category>
<onos.app.url>http://onosproject.org</onos.app.url>
</properties>
<dependencies>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-api</artifactId>
<version>${onos.version}</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-core-common</artifactId>
<version>${parent.version}</version>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr.annotations</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.onosproject</groupId>
<artifactId>onos-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3.ifwd模块的运行测试
在IDEA执行mvn clean compile
,mvn install
,然后在ONOS-WEB-UI界面上将对应的oar模块导入,启动openflow模块,然后启动Mininet进行连通性测试。
4.ifwd源码分析
1.Karaf技术相关解析:由于ONOS控制器是使用Karaf技术的,而在ifwd模块中,会使用到Karaf加载模块。下面对源码中Karaf组件加载的关键字进行说明。
Component(immediate = true) – 声明一个类作为组件激活,并且强制立即激活
Activate – 标记一个方法作为组件启动时调用
Deactivate – 标记一个方法作为组件关闭时调用
Reference(Cardinality = ReferenceCardinality.MANDATORY_UNARY) – 标记一个服务作为一个应用程序的依赖,并且在该应用程序启动之前,需要这样服务的一个实例被提前加载。
更多信息:http://felix.apache.org/documentation/subprojects/apache-felix-maven-scr-plugin/scr-annotations.html。
@Reference(cardinality = ReferenceCardinality.MANDATORY)
protected CoreService coreService;
@Reference(cardinality = ReferenceCardinality.MANDATORY)
protected TopologyService topologyService;
@Reference(cardinality = ReferenceCardinality.MANDATORY)
protected PacketService packetService;
@Reference(cardinality = ReferenceCardinality.MANDATORY)
protected IntentService intentService;
@Reference(cardinality = ReferenceCardinality.MANDATORY)
protected HostService hostService;
@Reference(cardinality = ReferenceCardinality.MANDATORY)
protected FlowRuleService flowRuleService;
@Reference(cardinality = ReferenceCardinality.MANDATORY)
protected FlowObjectiveService flowObjectiveService;
@Reference(cardinality = ReferenceCardinality.MANDATORY)
protected PortStatisticsService portStatisticsService;
@Reference(cardinality = ReferenceCardinality.MANDATORY)
protected LinkService linkService;
@Reference(cardinality = ReferenceCardinality.MANDATORY)
protected DeviceService deviceService;
对于上面的源码,翻译过来就是在运作ifwd的其他代码的时候,Karaf会先激活并且调用ONOS的核心服务,拓扑服务,包服务,意图网络服务,主机服务,流表规则服务,流对象服务,端口服务,链路服务,设备服务。
private ApplicationId appId;
由于应用程序在使用ONOS提供服务的时候,都需要有一个application ID,因此要定义一个appId,后面注册的时候使用。
private ReactivePacketProcessor processor = new ReactivePacketProcessor();
这里新建了一个包处理对象,用于后面对接受报文的处理。
private static final int DROP_RULE_TIMEOUT = 300;
private static final EnumSet<IntentState> WITHDRAWN_STATES = EnumSet.of(IntentState.WITHDRAWN,
IntentState.WITHDRAWING,
IntentState.WITHDRAW_REQ);
这里定义了流表的持续时间,以及一个枚举,用于说明IntenState的状态
IntentState:表示一个意图在其生命周期当中可能达到的状态
IntentState.WITHDRAWN:表示这个意图成功被撤回
IntentState.WITHDRAWING:表示这个意图正在被撤回
IntentState.WITHDRAW_REQ:表示一个应用程序请求撤回一个意图
@Activate
public void activate() {
appId = coreService.registerApplication("org.onosproject.ifwd");
packetService.addProcessor(processor, PacketProcessor.director(2));
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
selector.matchEthType(Ethernet.TYPE_IPV4);
packetService.requestPackets(selector.build(), PacketPriority.REACTIVE, appId);
log.info("Started");
}
标记该代码块在组件启动时要先调用,向核心服务注册一个ApplicationId,决定包处理器的优先级,新建一个流选择处理器,并且指定处理的包的IP类型为IPV4。最后是调用packetService.requestPackets方法,输出对应的参数。
这样子,在该模块启动的时候,当接受到包的时候,就能够根据我们设定好的方法进行报文的处理。
@Deactivate
public void deactivate() {
packetService.removeProcessor(processor);
processor = null;
log.info("Stopped");
}
标记该代码块在该组件关闭的时候调同。主要完成的工作是将包处理器移除并且置空。
private class ReactivePacketProcessor implements PacketProcessor {
@Override
public void process(PacketContext context) {
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());
Host dst = hostService.getHost(dstId);
if (dst == null) {
flood(context);
return;
}
setUpConnectivity(context, srcId, dstId);
forwardPacketToDst(context, dst);
}
}
在该代码块,对包处理器进行覆写,以定义我们想要的包转发行为。
一、定义处理方法,需要输入数据包作为参数:
1.判断该包是否已经被处理,若已被处理,则返回
2.将正在处理的入站数据包传递给pkt
3.用以太类型的ethPkt接收入站数据包的解析类型
4.如果该包的解析类型为空,则返回
5.获取该包的源MAC地址,目的MAC地址
6.根据目的MAC地址,在拓扑上精准确定目的主机,若目的主机为空,则调用flood方法,对包进行洪泛
7.目的主机不为空,调用setUpConnectivity方法,在目的节点与源节点之间建立连接
8.调用forwardPacketToDst方法,对包进行转发
private void flood(PacketContext context) {
if (topologyService.isBroadcastPoint(topologyService.currentTopology(),
context.inPacket().receivedFrom())) {
packetOut(context, PortNumber.FLOOD);
} else {
context.block();
}
}
private void packetOut(PacketContext context, PortNumber portNumber) {
context.treatmentBuilder().setOutput(portNumber);
context.send();
}
下面对flood方法及其需要用到的方法packetOut进行学习分析
flood方法,需要输入的参数是PacketContext
1.判断设备上的端口是否为收到该包的端口,如果不是的话,调用packetOut方法
2.若设备上的端口是收到该包的端口,阻塞该端口
packetOut方法,需要输入的参数是PacketContext,PortNumber
1.新建一个流量处理生成器,再输入对应的端口参数
2.发送该包
setUpConnectivity利用了ONOS-intent-framework,具体的学习分析以及心得在后面跟大家分享。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)