From 2947f0c6b7596263aad92d31b2800f4ecd875f98 Mon Sep 17 00:00:00 2001 From: Yi-Ting Shih Date: Wed, 8 Oct 2025 19:44:08 +0800 Subject: [PATCH] Feat: done --- lab3_111550013.zip | Bin 0 -> 15907 bytes lab3_111550013/ProxyArp/pom.xml | 92 ++++++++ .../nycu/winlab/ProxyArp/AppComponent.java | 171 +++++++++++++++ .../nycu/winlab/ProxyArp/package-info.java | 20 ++ .../winlab/proxyarp/AppComponentTest.java | 46 ++++ lab3_111550013/bridge-app/pom.xml | 93 ++++++++ .../java/nycu/winlab/bridge/AppComponent.java | 205 ++++++++++++++++++ .../nycu/winlab/bridge/SomeInterface.java | 22 ++ .../java/nycu/winlab/bridge/package-info.java | 20 ++ .../nycu/winlab/bridge/AppComponentTest.java | 47 ++++ 10 files changed, 716 insertions(+) create mode 100644 lab3_111550013.zip create mode 100644 lab3_111550013/ProxyArp/pom.xml create mode 100644 lab3_111550013/ProxyArp/src/main/java/nycu/winlab/ProxyArp/AppComponent.java create mode 100644 lab3_111550013/ProxyArp/src/main/java/nycu/winlab/ProxyArp/package-info.java create mode 100644 lab3_111550013/ProxyArp/src/test/java/nycu/winlab/proxyarp/AppComponentTest.java create mode 100644 lab3_111550013/bridge-app/pom.xml create mode 100644 lab3_111550013/bridge-app/src/main/java/nycu/winlab/bridge/AppComponent.java create mode 100644 lab3_111550013/bridge-app/src/main/java/nycu/winlab/bridge/SomeInterface.java create mode 100644 lab3_111550013/bridge-app/src/main/java/nycu/winlab/bridge/package-info.java create mode 100644 lab3_111550013/bridge-app/src/test/java/nycu/winlab/bridge/AppComponentTest.java diff --git a/lab3_111550013.zip b/lab3_111550013.zip new file mode 100644 index 0000000000000000000000000000000000000000..96b0bd5bb2c674aed5e460cbac4bef11c3ddd16b GIT binary patch literal 15907 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 literal 0 HcmV?d00001 diff --git a/lab3_111550013/ProxyArp/pom.xml b/lab3_111550013/ProxyArp/pom.xml new file mode 100644 index 0000000..39ebe03 --- /dev/null +++ b/lab3_111550013/ProxyArp/pom.xml @@ -0,0 +1,92 @@ + + + + 4.0.0 + + + org.onosproject + onos-dependencies + 2.7.0 + + + nycu.winlab + ProxyArp + 1.0-SNAPSHOT + bundle + + ONOS OSGi bundle archetype + http://onosproject.org + + + nycu.winlab.ProxyArp + Proxy Arp App + Winlab, NCTU + default + http://onosproject.org + ONOS OSGi bundle archetype. + + + + + org.onosproject + onos-api + ${onos.version} + provided + + + + org.onosproject + onlab-osgi + ${onos.version} + provided + + + + org.onosproject + onlab-misc + ${onos.version} + provided + + + + org.onosproject + onos-api + ${onos.version} + test + tests + + + + + + + org.onosproject + onos-maven-plugin + + + + org.apache.maven.plugins + maven-checkstyle-plugin + + + true + + + + + + diff --git a/lab3_111550013/ProxyArp/src/main/java/nycu/winlab/ProxyArp/AppComponent.java b/lab3_111550013/ProxyArp/src/main/java/nycu/winlab/ProxyArp/AppComponent.java new file mode 100644 index 0000000..8807ca6 --- /dev/null +++ b/lab3_111550013/ProxyArp/src/main/java/nycu/winlab/ProxyArp/AppComponent.java @@ -0,0 +1,171 @@ +/* + * Copyright 2025-present 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. + */ +package nycu.winlab; + +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; +import org.osgi.service.component.annotations.ReferenceCardinality; + +import org.onosproject.core.ApplicationId; +import org.onosproject.core.CoreService; + +import org.onosproject.net.packet.PacketContext; +import org.onosproject.net.packet.PacketProcessor; +import org.onosproject.net.packet.PacketService; +import org.onosproject.net.packet.InboundPacket; +import org.onosproject.net.packet.OutboundPacket; +import org.onosproject.net.packet.DefaultOutboundPacket; +import org.onosproject.net.packet.PacketPriority; + +import org.onosproject.net.edge.EdgePortService; +import org.onosproject.net.ConnectPoint; + +import org.onosproject.net.flow.DefaultTrafficSelector; +import org.onosproject.net.flow.DefaultTrafficTreatment; +import org.onosproject.net.flow.TrafficTreatment; +import org.onosproject.net.flow.TrafficSelector; + +import org.onlab.packet.Ethernet; +import org.onlab.packet.ARP; +import org.onlab.packet.Ip4Address; +import org.onlab.packet.MacAddress; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import java.nio.ByteBuffer; + +/** + * Skeletal ONOS application component. + */ +@Component(immediate = true) +public class AppComponent { + + private final Logger log = LoggerFactory.getLogger(getClass()); + + @Reference(cardinality = ReferenceCardinality.MANDATORY) + private CoreService coreService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY) + private PacketService packetService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY) + private EdgePortService edgePortService; + + private ApplicationId appId; + private final PacketProcessor processor = new ProxyArpProcessor(); + private final Map arpTable = new ConcurrentHashMap<>(); + private final Map macTable = new ConcurrentHashMap<>(); + + private TrafficSelector arpSelector; + + @Activate + protected void activate() { + arpSelector = DefaultTrafficSelector.builder(). + matchEthType(Ethernet.TYPE_ARP). + build(); + + appId = coreService.registerApplication("nycu.winlab.ProxyArp"); + packetService.addProcessor(processor, PacketProcessor.director(3)); + packetService.requestPackets(arpSelector, PacketPriority.REACTIVE, appId); + log.info("Started"); + } + + @Deactivate + protected void deactivate() { + packetService.cancelPackets(arpSelector, PacketPriority.REACTIVE, appId); + packetService.removeProcessor(processor); + log.info("Stopped"); + } + + private class ProxyArpProcessor implements PacketProcessor { + private void sendPacket(Ethernet ethPacket, ConnectPoint outPort) { + TrafficTreatment treatment = DefaultTrafficTreatment.builder(). + setOutput(outPort.port()). + build(); + + OutboundPacket outPacket = new DefaultOutboundPacket( + outPort.deviceId(), + treatment, + ByteBuffer.wrap(ethPacket.serialize()) + ); + + packetService.emit(outPacket); + } + + @Override + public void process(PacketContext context) { + if (context.isHandled()) { + return; + } + + InboundPacket packet = context.inPacket(); + Ethernet ethPacket = packet.parsed(); + + if (ethPacket == null) { + return; + } + + ARP arpPacket = (ARP) ethPacket.getPayload(); + + if (arpPacket.getProtocolType() != ARP.PROTO_TYPE_IP) { + return; + } + + ConnectPoint inPort = packet.receivedFrom(); + MacAddress srcMac = ethPacket.getSourceMAC(); + Ip4Address srcIp = Ip4Address.valueOf(arpPacket. + getSenderProtocolAddress()); + Ip4Address dstIp = Ip4Address.valueOf(arpPacket. + getTargetProtocolAddress()); + + macTable.putIfAbsent(srcMac, inPort); + arpTable.putIfAbsent(srcIp, srcMac); + + if (arpPacket.getOpCode() == ARP.OP_REQUEST) { + MacAddress dstMac = arpTable.get(dstIp); + if (dstMac == null) { + for (ConnectPoint cp: edgePortService.getEdgePoints()) { + if (!cp.equals(inPort)) { + sendPacket(ethPacket, cp); + } + } + log.info("TABLE MISS. Send request to edge ports"); + } else { + Ethernet arpReply = ARP.buildArpReply(dstIp, dstMac, ethPacket); + sendPacket(arpReply, inPort); + log.info("TABLE HIT. Requested MAC = {}", dstMac); + } + } + if (arpPacket.getOpCode() == ARP.OP_REPLY) { + arpTable.put(srcIp, srcMac); + macTable.put(srcMac, inPort); + + MacAddress dstMac = arpTable.get(dstIp); + ConnectPoint outPort = macTable.get(dstMac); + + if (outPort != null) { + sendPacket(ethPacket, outPort); + } + } + } + } +} diff --git a/lab3_111550013/ProxyArp/src/main/java/nycu/winlab/ProxyArp/package-info.java b/lab3_111550013/ProxyArp/src/main/java/nycu/winlab/ProxyArp/package-info.java new file mode 100644 index 0000000..ac0ccd0 --- /dev/null +++ b/lab3_111550013/ProxyArp/src/main/java/nycu/winlab/ProxyArp/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2025-present 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. + */ + +/** + * ONOS application archetype. + */ +package nycu.winlab.ProxyArp; diff --git a/lab3_111550013/ProxyArp/src/test/java/nycu/winlab/proxyarp/AppComponentTest.java b/lab3_111550013/ProxyArp/src/test/java/nycu/winlab/proxyarp/AppComponentTest.java new file mode 100644 index 0000000..e67cc2e --- /dev/null +++ b/lab3_111550013/ProxyArp/src/test/java/nycu/winlab/proxyarp/AppComponentTest.java @@ -0,0 +1,46 @@ +/* + * Copyright 2025-present 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. + */ +package nycu.winlab; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.onosproject.cfg.ComponentConfigAdapter; + +/** + * Set of tests of the ONOS application component. + */ +public class AppComponentTest { + + private AppComponent component; + + @Before + public void setUp() { + component = new AppComponent(); + component.activate(); + } + + @After + public void tearDown() { + component.deactivate(); + } + + @Test + public void basics() { + + } + +} diff --git a/lab3_111550013/bridge-app/pom.xml b/lab3_111550013/bridge-app/pom.xml new file mode 100644 index 0000000..5d82dd2 --- /dev/null +++ b/lab3_111550013/bridge-app/pom.xml @@ -0,0 +1,93 @@ + + + + 4.0.0 + + + org.onosproject + onos-dependencies + 2.7.0 + + + nycu.winlab + bridge-app + 1.0-SNAPSHOT + bundle + + ONOS OSGi bundle archetype + http://onosproject.org + + + nctu.winlab.bridge + Learning Bridge App + Winlab, NCTU + default + http://onosproject.org + ONOS OSGi bundle archetype. + + + + + org.onosproject + onos-api + ${onos.version} + provided + + + + org.onosproject + onlab-osgi + ${onos.version} + provided + + + + org.onosproject + onlab-misc + ${onos.version} + provided + + + + org.onosproject + onos-api + ${onos.version} + test + tests + + + + + + + org.onosproject + onos-maven-plugin + + + + org.apache.maven.plugins + maven-checkstyle-plugin + + + + + + diff --git a/lab3_111550013/bridge-app/src/main/java/nycu/winlab/bridge/AppComponent.java b/lab3_111550013/bridge-app/src/main/java/nycu/winlab/bridge/AppComponent.java new file mode 100644 index 0000000..e296bcf --- /dev/null +++ b/lab3_111550013/bridge-app/src/main/java/nycu/winlab/bridge/AppComponent.java @@ -0,0 +1,205 @@ +/* + * Copyright 2025-present 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. + */ +package nycu.winlab.bridge; + +import org.onosproject.cfg.ComponentConfigService; +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; +import org.osgi.service.component.annotations.ReferenceCardinality; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.onosproject.core.ApplicationId; +import org.onosproject.core.CoreService; + +import org.onosproject.net.flow.FlowRuleService; +import org.onosproject.net.flow.DefaultTrafficSelector; +import org.onosproject.net.flow.DefaultTrafficTreatment; +import org.onosproject.net.flow.TrafficSelector; +import org.onosproject.net.flow.TrafficTreatment; + +import org.onosproject.net.flowobjective.DefaultForwardingObjective; +import org.onosproject.net.flowobjective.FlowObjectiveService; +import org.onosproject.net.flowobjective.ForwardingObjective; + +import org.onosproject.net.packet.InboundPacket; +import org.onosproject.net.packet.PacketContext; +import org.onosproject.net.packet.PacketProcessor; +import org.onosproject.net.packet.PacketPriority; +import org.onosproject.net.packet.PacketService; + +import org.onlab.packet.Ethernet; +import org.onlab.packet.MacAddress; + +import org.onosproject.net.ConnectPoint; +import org.onosproject.net.DeviceId; +import org.onosproject.net.PortNumber; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Skeletal ONOS application component. + */ +@Component(immediate = true) +public class AppComponent { + private final Logger log = LoggerFactory.getLogger(getClass()); + + /** Some configurable property. */ + private String someProperty; + + @Reference(cardinality = ReferenceCardinality.MANDATORY) + protected ComponentConfigService cfgService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY) + protected PacketService packetService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY) + protected CoreService coreService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY) + protected FlowRuleService flowRuleService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY) + protected FlowObjectiveService flowObjectiveService; + + private static final int FLOWRULE_PRIORITY = 30; + private static final int FLOWRULE_TIMEOUT = 30; + + private ApplicationId appId; + private final PacketProcessor processor = new BridgePacketProcessor(); + private final Map> macTables = + new ConcurrentHashMap<>(); + + private TrafficSelector ipv4Selector; + private TrafficSelector arpSelector; + + @Activate + protected void activate() { + appId = coreService.registerApplication("nycu.winlab.bridge"); + packetService.addProcessor(processor, PacketProcessor.director(2)); + + ipv4Selector = DefaultTrafficSelector.builder(). + matchEthType(Ethernet.TYPE_IPV4). + build(); + + arpSelector = DefaultTrafficSelector.builder(). + matchEthType(Ethernet.TYPE_ARP). + build(); + + packetService.requestPackets(ipv4Selector, PacketPriority.REACTIVE, appId); + packetService.requestPackets(arpSelector, PacketPriority.REACTIVE, appId); + + log.info("Started"); + } + + @Deactivate + protected void deactivate() { + cfgService.unregisterProperties(getClass(), false); + + packetService.cancelPackets(ipv4Selector, PacketPriority.REACTIVE, appId); + packetService.cancelPackets(arpSelector, PacketPriority.REACTIVE, appId); + + packetService.removeProcessor(processor); + flowRuleService.removeFlowRulesById(appId); + macTables.clear(); + log.info("Stopped"); + } + + private class BridgePacketProcessor implements PacketProcessor { + private void installFlowRule( + DeviceId deviceId, + MacAddress srcMac, + MacAddress dstMac, + PortNumber outPort + ) { + TrafficSelector selector = DefaultTrafficSelector.builder(). + matchEthSrc(srcMac). + matchEthDst(dstMac). + build(); + + TrafficTreatment treatment = DefaultTrafficTreatment.builder(). + setOutput(outPort). + build(); + + ForwardingObjective forwardingObjective = + DefaultForwardingObjective.builder(). + withSelector(selector). + withTreatment(treatment). + withPriority(FLOWRULE_PRIORITY). + withFlag(ForwardingObjective.Flag.VERSATILE). + makeTemporary(FLOWRULE_TIMEOUT). + fromApp(appId). + add(); + + flowObjectiveService.forward(deviceId, forwardingObjective); + } + + @Override + public void process(PacketContext context) { + if (context.isHandled()) { + return; + } + + InboundPacket packet = context.inPacket(); + Ethernet ethPacket = packet.parsed(); + + if (ethPacket == null) { + return; + } + + ConnectPoint cp = packet.receivedFrom(); + DeviceId deviceId = cp.deviceId(); + PortNumber inPort = cp.port(); + MacAddress srcMac = ethPacket.getSourceMAC(); + MacAddress dstMac = ethPacket.getDestinationMAC(); + + macTables.computeIfAbsent(deviceId, k -> new ConcurrentHashMap<>()); + Map macTable = macTables.get(cp.deviceId()); + + if (!macTable.containsKey(srcMac)) { + macTable.put(srcMac, inPort); + log.info("Add an entry to the port table of `{}`. " + + "MAC address: `{}` => Port: `{}`.", + deviceId, srcMac, inPort); + } + + PortNumber outPort = macTable.get(dstMac); + + if (outPort == null) { + context.treatmentBuilder().setOutput(PortNumber.FLOOD); + context.send(); + + log.info("MAC address `{}` is missed on `{}`. Flood the packet.", + dstMac, deviceId); + } else { + if (!outPort.equals(inPort)) { + installFlowRule(deviceId, srcMac, dstMac, outPort); + context.treatmentBuilder().setOutput(outPort); + context.send(); + + log.info("MAC address `{}` is matched on `{}`. Install a flow rule.", + dstMac, deviceId); + } else { + context.block(); + } + } + } + + } +} diff --git a/lab3_111550013/bridge-app/src/main/java/nycu/winlab/bridge/SomeInterface.java b/lab3_111550013/bridge-app/src/main/java/nycu/winlab/bridge/SomeInterface.java new file mode 100644 index 0000000..94a3b63 --- /dev/null +++ b/lab3_111550013/bridge-app/src/main/java/nycu/winlab/bridge/SomeInterface.java @@ -0,0 +1,22 @@ +/* + * Copyright 2025-present 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. + */ +package nycu.winlab.bridge; + +public interface SomeInterface { + + void someMethod(); + +} \ No newline at end of file diff --git a/lab3_111550013/bridge-app/src/main/java/nycu/winlab/bridge/package-info.java b/lab3_111550013/bridge-app/src/main/java/nycu/winlab/bridge/package-info.java new file mode 100644 index 0000000..ab96195 --- /dev/null +++ b/lab3_111550013/bridge-app/src/main/java/nycu/winlab/bridge/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2025-present 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. + */ + +/** + * ONOS application archetype. + */ +package nycu.winlab.bridge; \ No newline at end of file diff --git a/lab3_111550013/bridge-app/src/test/java/nycu/winlab/bridge/AppComponentTest.java b/lab3_111550013/bridge-app/src/test/java/nycu/winlab/bridge/AppComponentTest.java new file mode 100644 index 0000000..3d47cd4 --- /dev/null +++ b/lab3_111550013/bridge-app/src/test/java/nycu/winlab/bridge/AppComponentTest.java @@ -0,0 +1,47 @@ +/* + * Copyright 2025-present 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. + */ +package nycu.winlab.bridge; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.onosproject.cfg.ComponentConfigAdapter; + +/** + * Set of tests of the ONOS application component. + */ +public class AppComponentTest { + + private AppComponent component; + + @Before + public void setUp() { + component = new AppComponent(); + component.cfgService = new ComponentConfigAdapter(); + component.activate(); + } + + @After + public void tearDown() { + component.deactivate(); + } + + @Test + public void basics() { + + } + +}