diff options
author | Ashlee Young <ashlee@onosfw.com> | 2015-09-09 22:15:21 -0700 |
---|---|---|
committer | Ashlee Young <ashlee@onosfw.com> | 2015-09-09 22:15:21 -0700 |
commit | 13d05bc8458758ee39cb829098241e89616717ee (patch) | |
tree | 22a4d1ce65f15952f07a3df5af4b462b4697cb3a /framework/src/onos/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VirtualPublicHosts.java | |
parent | 6139282e1e93c2322076de4b91b1c85d0bc4a8b3 (diff) |
ONOS checkin based on commit tag e796610b1f721d02f9b0e213cf6f7790c10ecd60
Change-Id: Ife8810491034fe7becdba75dda20de4267bd15cd
Diffstat (limited to 'framework/src/onos/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VirtualPublicHosts.java')
-rw-r--r-- | framework/src/onos/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VirtualPublicHosts.java | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/framework/src/onos/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VirtualPublicHosts.java b/framework/src/onos/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VirtualPublicHosts.java new file mode 100644 index 00000000..5ab650bc --- /dev/null +++ b/framework/src/onos/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VirtualPublicHosts.java @@ -0,0 +1,167 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * 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 org.onosproject.virtualbng; + +import static org.slf4j.LoggerFactory.getLogger; + +import java.nio.ByteBuffer; + +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.Reference; +import org.apache.felix.scr.annotations.ReferenceCardinality; +import org.onlab.packet.ARP; +import org.onlab.packet.Ethernet; +import org.onlab.packet.Ip4Address; +import org.onlab.packet.MacAddress; +import org.onosproject.core.ApplicationId; +import org.onosproject.core.CoreService; +import org.onosproject.net.ConnectPoint; +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.packet.DefaultOutboundPacket; +import org.onosproject.net.packet.InboundPacket; +import org.onosproject.net.packet.PacketContext; +import org.onosproject.net.packet.PacketPriority; +import org.onosproject.net.packet.PacketProcessor; +import org.onosproject.net.packet.PacketService; +import org.slf4j.Logger; + +/** + * When the upstream gateway which is outside local SDN network wants to send + * packets to our local public IP addresses, it will send out ARP requests to + * get the MAC address of each public IP address. Actually, there are no hosts + * configured with those public IP addresses, so this class is to emulate the + * behavior of the non-existed hosts and return ARP replies. + * <p> + * Since we will rewrite the destination MAC address in the switch before + * traffic packets go to the destination, so the MAC address can be any number. + * We manually configured a random MAC address for this purpose in the vBNG + * configuration file. + * </p> + */ +@Component(immediate = true) +public class VirtualPublicHosts { + private final Logger log = getLogger(getClass()); + + private static final String APP_NAME = + "org.onosproject.virtualbng.VirtualPublicHosts"; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected CoreService coreService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected PacketService packetService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected VbngConfigurationService vbngConfigService; + + private ApplicationId appId; + private ArpRequestProcessor processor = new ArpRequestProcessor(); + + @Activate + public void activate() { + appId = coreService.registerApplication(APP_NAME); + + packetService.addProcessor(processor, PacketProcessor.director(6)); + requestIntercepts(); + log.info("vBNG virtual public hosts started"); + } + + @Deactivate + public void deactivate() { + withdrawIntercepts(); + packetService.removeProcessor(processor); + processor = null; + log.info("vBNG virtual public hosts Stopped"); + } + + /** + * Request packet in via PacketService. + */ + private void requestIntercepts() { + TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); + // Only IPv4 is supported in current vBNG. + selector.matchEthType(Ethernet.TYPE_ARP); + packetService.requestPackets(selector.build(), + PacketPriority.REACTIVE, appId); + } + + /** + * Cancel request for packet in via PacketService. + */ + private void withdrawIntercepts() { + TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); + // Only IPv4 is supported in current vBNG. + selector.matchEthType(Ethernet.TYPE_ARP); + packetService.cancelPackets(selector.build(), + PacketPriority.REACTIVE, appId); + } + + /** + * This class filters out the ARP request packets, generates the ARP + * reply packets, and emits those packets. + */ + private class ArpRequestProcessor implements PacketProcessor { + @Override + public void process(PacketContext context) { + + InboundPacket pkt = context.inPacket(); + Ethernet ethPkt = pkt.parsed(); + + // Only handle the ARP packets + if (ethPkt == null || ethPkt.getEtherType() != Ethernet.TYPE_ARP) { + return; + } + ARP arpPacket = (ARP) ethPkt.getPayload(); + // Only handle ARP request packets + if (arpPacket.getOpCode() != ARP.OP_REQUEST) { + return; + } + + Ip4Address targetIpAddress = Ip4Address + .valueOf(arpPacket.getTargetProtocolAddress()); + + // Only handle an ARP request when the target IP address inside is + // an assigned public IP address + if (!vbngConfigService.isAssignedPublicIpAddress(targetIpAddress)) { + return; + } + + MacAddress virtualHostMac = + vbngConfigService.getPublicFacingMac(); + if (virtualHostMac == null) { + return; + } + + ConnectPoint srcConnectPoint = pkt.receivedFrom(); + Ethernet eth = ARP.buildArpReply(targetIpAddress, + virtualHostMac, + ethPkt); + + TrafficTreatment.Builder builder = + DefaultTrafficTreatment.builder(); + builder.setOutput(srcConnectPoint.port()); + packetService.emit(new DefaultOutboundPacket( + srcConnectPoint.deviceId(), + builder.build(), + ByteBuffer.wrap(eth.serialize()))); + } + } +} |