diff options
Diffstat (limited to 'framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IpHandler.java')
-rw-r--r-- | framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IpHandler.java | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IpHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IpHandler.java new file mode 100644 index 00000000..81d00f50 --- /dev/null +++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IpHandler.java @@ -0,0 +1,152 @@ +/* + * 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.segmentrouting; + +import org.onlab.packet.Ethernet; +import org.onlab.packet.IPv4; +import org.onlab.packet.Ip4Address; +import org.onosproject.net.ConnectPoint; +import org.onosproject.net.DeviceId; +import org.onosproject.net.Host; +import org.onosproject.net.flow.DefaultTrafficTreatment; +import org.onosproject.net.flow.TrafficTreatment; +import org.onosproject.net.packet.DefaultOutboundPacket; +import org.onosproject.net.packet.InboundPacket; +import org.onosproject.net.packet.OutboundPacket; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.nio.ByteBuffer; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; + +import static com.google.common.base.Preconditions.checkNotNull; + +public class IpHandler { + + private static Logger log = LoggerFactory.getLogger(IpHandler.class); + private SegmentRoutingManager srManager; + private DeviceConfiguration config; + private ConcurrentHashMap<Ip4Address, ConcurrentLinkedQueue<IPv4>> ipPacketQueue; + + /** + * Creates an IpHandler object. + * + * @param srManager SegmentRoutingManager object + */ + public IpHandler(SegmentRoutingManager srManager) { + this.srManager = srManager; + this.config = checkNotNull(srManager.deviceConfiguration); + ipPacketQueue = new ConcurrentHashMap<Ip4Address, ConcurrentLinkedQueue<IPv4>>(); + } + + /** + * Processes incoming IP packets. + * + * If it is an IP packet for known host, then forward it to the host. + * If it is an IP packet for unknown host in subnet, then send an ARP request + * to the subnet. + * + * @param pkt incoming packet + */ + public void processPacketIn(InboundPacket pkt) { + Ethernet ethernet = pkt.parsed(); + IPv4 ipv4 = (IPv4) ethernet.getPayload(); + + ConnectPoint connectPoint = pkt.receivedFrom(); + DeviceId deviceId = connectPoint.deviceId(); + Ip4Address destinationAddress = + Ip4Address.valueOf(ipv4.getDestinationAddress()); + + // IP packet for know hosts + if (!srManager.hostService.getHostsByIp(destinationAddress).isEmpty()) { + forwardPackets(deviceId, destinationAddress); + + // IP packet for unknown host in the subnet of the router + } else if (config.inSameSubnet(deviceId, destinationAddress)) { + srManager.arpHandler.sendArpRequest(deviceId, destinationAddress, connectPoint); + + // IP packets for unknown host + } else { + log.debug("ICMP request for unknown host {} which is not in the subnet", + destinationAddress); + // Do nothing + } + } + + /** + * Adds the IP packet to a buffer. + * The packets are forwarded to corresponding destination when the destination + * MAC address is known via ARP response. + * + * @param ipPacket IP packet to add to the buffer + */ + public void addToPacketBuffer(IPv4 ipPacket) { + + // Better not buffer TPC packets due to out-of-order packet transfer + if (ipPacket.getProtocol() == IPv4.PROTOCOL_TCP) { + return; + } + + Ip4Address destIpAddress = Ip4Address.valueOf(ipPacket.getDestinationAddress()); + + if (ipPacketQueue.get(destIpAddress) == null) { + ConcurrentLinkedQueue<IPv4> queue = new ConcurrentLinkedQueue<IPv4>(); + queue.add(ipPacket); + ipPacketQueue.put(destIpAddress, queue); + } else { + ipPacketQueue.get(destIpAddress).add(ipPacket); + } + } + + /** + * Forwards IP packets in the buffer to the destination IP address. + * It is called when the controller finds the destination MAC address + * via ARP responsees. + * + * @param deviceId switch device ID + * @param destIpAddress destination IP address + */ + public void forwardPackets(DeviceId deviceId, Ip4Address destIpAddress) { + if (ipPacketQueue.get(destIpAddress) == null) { + return; + } + + for (IPv4 ipPacket : ipPacketQueue.get(destIpAddress)) { + Ip4Address destAddress = Ip4Address.valueOf(ipPacket.getDestinationAddress()); + if (ipPacket != null && config.inSameSubnet(deviceId, destAddress)) { + ipPacket.setTtl((byte) (ipPacket.getTtl() - 1)); + ipPacket.setChecksum((short) 0); + for (Host dest: srManager.hostService.getHostsByIp(destIpAddress)) { + Ethernet eth = new Ethernet(); + eth.setDestinationMACAddress(dest.mac()); + eth.setSourceMACAddress(config.getDeviceMac(deviceId)); + eth.setEtherType(Ethernet.TYPE_IPV4); + eth.setPayload(ipPacket); + + TrafficTreatment treatment = DefaultTrafficTreatment.builder(). + setOutput(dest.location().port()).build(); + OutboundPacket packet = new DefaultOutboundPacket(deviceId, + treatment, ByteBuffer.wrap(eth.serialize())); + srManager.packetService.emit(packet); + ipPacketQueue.get(destIpAddress).remove(ipPacket); + } + ipPacketQueue.get(destIpAddress).remove(ipPacket); + } + } + } + +} |