TraceCode org.onosproject.fwd

吳建興
14 min readApr 3, 2019

--

Hello!

這次ㄧ樣來追一下程式碼,當作課堂的筆記。這堂課是交通大學的軟體定義網路,蠻有趣的一堂課。

這次主要想追的程式碼是onos中fwd這個app裡的ReactiveForwarding.java這個檔案。有些偷懶的就直接把function的用途寫在上面,不一行行寫註解了。甚至有些作業用不到的function,就直接不寫了,因為這篇還沒打完作業就寫完了,有點懶得繼續下去XDD

Code

完整的code可以看這裡

/**
* Sample reactive forwarding application.
*/
@Component(immediate = true)
@Service(value = ReactiveForwarding.class)
public class ReactiveForwarding {
private static final int DEFAULT_TIMEOUT = 10;
private static final int DEFAULT_PRIORITY = 10;
private final Logger log = getLogger(getClass());
//用於提供網絡拓補信息
@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 FlowRuleService flowRuleService;
//用於新增flow rule
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected FlowObjectiveService flowObjectiveService;
//在使用onos的各種服務前,要先向CoreService註冊
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CoreService coreService;
//追蹤整個系統各個組件的配置
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ComponentConfigService cfgService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected StorageService storageService;
//封包進來的時候,進行處理的handler
private ReactivePacketProcessor processor = new ReactivePacketProcessor();
//metrics:記錄所有host的資訊
private EventuallyConsistentMap<MacAddress, ReactiveForwardMetrics> metrics;
//ONOS下,每個app都要有自己的appId
private ApplicationId appId;
//一些設定
@Property(name = "packetOutOnly", boolValue = false,
label = "Enable packet-out only forwarding; default is false")
private boolean packetOutOnly = false;
@Property(name = "packetOutOfppTable", boolValue = false,
label = "Enable first packet forwarding using OFPP_TABLE port " +"instead of PacketOut with actual port; default is false")
private boolean packetOutOfppTable = false;
.
.
.
//Entity capable of receiving network topology related events
private final TopologyListener topologyListener = new InternalTopologyListener();
private ExecutorService blackHoleExecutor;
//@Activate - marks a method as the method to call during the component startup routine.
@Activate
public void activate(ComponentContext context) {
//一個快速高效的反序列化框架
KryoNamespace.Builder metricSerializer = KryoNamespace.newBuilder()
.register(KryoNamespaces.API)
.register(ReactiveForwardMetrics.class)
.register(MultiValuedTimestamp.class);
metrics = storageService.<MacAddress, ReactiveForwardMetrics>eventuallyConsistentMapBuilder()
.withName("metrics-fwd")
.withSerializer(metricSerializer)
.withTimestampProvider((key, metricsData) -> new
MultiValuedTimestamp<>(new WallClockTimestamp(), System.nanoTime()))
.build();
//topology有改變的話,就可以call(?) blackHoleExecutor = newSingleThreadExecutor(groupedThreads("onos/app/fwd",
"black-hole-fixer",
log));
//追蹤整個系統各個組件的配置
cfgService.registerProperties(getClass());
//註冊appId
appId = coreService.registerApplication("org.onosproject.fwd");
//ReactivePacketProcessor(這裡的變數是processor).process裡定義了接收到封包要做什麼動作
packetService.addProcessor(processor, PacketProcessor.director(2));
//當拓墣改變的話,會呼叫
topologyService.addListener(topologyListener);
//In this way the application components can continue to use the standard and well-understood OSGi configuration via ComponentContext.
readComponentConfiguration(context);
//想要攔截哪些種類的封包
requestIntercepts();
log.info("Started", appId.id());
}
/**
* Request packet in via packet service.
*
* 在擷取的時候,指定想要擷取哪些封包
*/
private void requestIntercepts() {
//Abstraction of a slice of network traffic.
//Builder of traffic selector entities.
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
selector.matchEthType(Ethernet.TYPE_IPV4);

//要求讓ipv4的封包都packet in進來
packetService.requestPackets(selector.build(), PacketPriority.REACTIVE, appId);

selector.matchEthType(Ethernet.TYPE_IPV6);
if (ipv6Forwarding) {
packetService.requestPackets(selector.build(),
PacketPriority.REACTIVE, appId);
} else {
packetService.cancelPackets(selector.build(), PacketPriority.REACTIVE, appId);
}
}

/**
* Cancel request for packet in via packet service.
* 反正就是做跟requestIntercepts相反的事情
*/
private void withdrawIntercepts() {
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();

selector.matchEthType(Ethernet.TYPE_IPV4);
packetService.cancelPackets(selector.build(),
PacketPriority.REACTIVE, appId);
selector.matchEthType(Ethernet.TYPE_IPV6); packetService.cancelPackets(selector.build(),
PacketPriority.REACTIVE, appId);
}
/**
* Extracts properties from the component configuration context.
*
* 把一些設定從context裡面抽取出來
* @param context the component context
*/
private void readComponentConfiguration(ComponentContext context
{
}
/**
* Packet processor responsible for forwarding packets along their paths.
* 這個function來決定要怎麼轉送封包
*/
private class ReactivePacketProcessor implements PacketProcessor {
//修改父母類別的function
@Override
public void process(PacketContext context) {
}
}
// 判斷是不是 control packet(LLDP, BDDP)
// Indicates whether this is a control packet, e.g. LLDP, BDDP
private boolean isControlPacket(Ethernet eth) {
short type = eth.getEtherType();
return type == Ethernet.TYPE_LLDP || type == Ethernet.TYPE_BSN;
}
// 假如目前的點可以flood,那就flood
// Floods the specified packet if permissible.
private void flood(PacketContext context, ReactiveForwardMetrics macMetrics) {
if(topologyService.isBroadcastPoint(topologyService.currentTopology(),context.inPacket().receivedFrom())) {
packetOut(context, PortNumber.FLOOD, macMetrics);
} else {
context.block();
}
}
// Sends a packet out the specified port.
// 送出封包到指定的port
private void packetOut(PacketContext context, PortNumber portNumber, ReactiveForwardMetrics macMetrics) {
}

// Install a rule forwarding the packet to the specified port.
// 1.packetout, 2.flow_mod
// flow_mod之後要packetout,這樣才不會把封包給平白無故地丟掉
private void installRule(PacketContext context, PortNumber portNumber, ReactiveForwardMetrics macMetrics) {
}

Reference

[1]开发基于ONOS的SDN应用程序 http://sdnhub.cn/index.php/onos-application-tutorial/
[2]onos wiki https://wiki.onosproject.org/display/ONOS11/Application+tutorial
[3]Kryo https://baymaxhuang.github.io/2017/06/14/Kryo%E5%BA%8F%E5%88%97%E5%8C%96%E5%8F%8A%E5%85%B6%E5%9C%A8ONOS%E4%B8%AD%E7%9A%84%E5%BA%94%E7%94%A8/
[4]storageService https://baymaxhuang.github.io/2017/02/15/ONOS-cluster%E5%88%86%E5%B8%83%E5%BC%8F%E6%95%B0%E6%8D%AE%E5%AD%98%E5%82%A8%E5%92%8C%E4%B8%9C%E8%A5%BF%E5%90%91%E9%80%9A%E4%BF%A1/
[5]onos api http://api.onosproject.org/1.5.0/overview-summary.html
[6]ONOS源碼筆記 — 前提 https://www.twblogs.net/a/5b8a41992b71775d1ce63797
[7]newSingleThreadExecutor https://blog.csdn.net/guyuealian/article/details/51706310
[8]ONOS源码笔记 — 机制 https://blog.csdn.net/fanshuquan/article/details/51251223
[9]path http://api.onosproject.org/1.5.1/org/onosproject/net/Path.html
[10]reactive forwarding http://networkstatic.net/openflow-proactive-vs-reactive-flows/
[11]how to flow mod? https://groups.google.com/a/onosproject.org/forum/#!topic/onos-dev/5o-6kDYby6I
[12]learning-sdn https://github.com/OSE-Lab/Learning-SDN/tree/master/Controller/ONOS

--

--

吳建興
吳建興

Written by 吳建興

I want to be a good programmer.(´・ω・`)

No responses yet