/* * Copyright 2015-present 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.bgprouter; import org.onlab.packet.Ethernet; import org.onlab.packet.ICMP; import org.onlab.packet.IPv4; import org.onlab.packet.IpAddress; import org.onosproject.incubator.net.intf.Interface; import org.onosproject.incubator.net.intf.InterfaceService; import org.onosproject.net.ConnectPoint; import org.onosproject.net.flow.DefaultTrafficTreatment; import org.onosproject.net.flow.TrafficTreatment; import org.onosproject.net.host.InterfaceIpAddress; import org.onosproject.net.packet.DefaultOutboundPacket; import org.onosproject.net.packet.InboundPacket; import org.onosproject.net.packet.OutboundPacket; import org.onosproject.net.packet.PacketContext; import org.onosproject.net.packet.PacketProcessor; import org.onosproject.net.packet.PacketService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.nio.ByteBuffer; public class IcmpHandler { private static final Logger log = LoggerFactory.getLogger(IcmpHandler.class); private final PacketService packetService; private final InterfaceService interfaceService; private final IcmpProcessor processor = new IcmpProcessor(); public IcmpHandler(InterfaceService interfaceService, PacketService packetService) { this.interfaceService = interfaceService; this.packetService = packetService; } public void start() { packetService.addProcessor(processor, PacketProcessor.director(4)); } public void stop() { packetService.removeProcessor(processor); } private void processPacketIn(InboundPacket pkt) { boolean ipMatches = false; Ethernet ethernet = pkt.parsed(); IPv4 ipv4 = (IPv4) ethernet.getPayload(); ConnectPoint connectPoint = pkt.receivedFrom(); IpAddress destIpAddress = IpAddress.valueOf(ipv4.getDestinationAddress()); Interface targetInterface = interfaceService.getMatchingInterface(destIpAddress); if (targetInterface == null) { log.trace("No matching interface for {}", destIpAddress); return; } for (InterfaceIpAddress interfaceIpAddress: targetInterface.ipAddresses()) { if (interfaceIpAddress.ipAddress().equals(destIpAddress)) { ipMatches = true; break; } } if (((ICMP) ipv4.getPayload()).getIcmpType() == ICMP.TYPE_ECHO_REQUEST && ipMatches) { sendIcmpResponse(ethernet, connectPoint); } } private void sendIcmpResponse(Ethernet icmpRequest, ConnectPoint outport) { Ethernet icmpReplyEth = new Ethernet(); IPv4 icmpRequestIpv4 = (IPv4) icmpRequest.getPayload(); IPv4 icmpReplyIpv4 = new IPv4(); int destAddress = icmpRequestIpv4.getDestinationAddress(); icmpReplyIpv4.setDestinationAddress(icmpRequestIpv4.getSourceAddress()); icmpReplyIpv4.setSourceAddress(destAddress); icmpReplyIpv4.setTtl((byte) 64); icmpReplyIpv4.setChecksum((short) 0); ICMP icmpReply = new ICMP(); icmpReply.setPayload(((ICMP) icmpRequestIpv4.getPayload()).getPayload()); icmpReply.setIcmpType(ICMP.TYPE_ECHO_REPLY); icmpReply.setIcmpCode(ICMP.SUBTYPE_ECHO_REPLY); icmpReply.setChecksum((short) 0); icmpReplyIpv4.setPayload(icmpReply); icmpReplyEth.setPayload(icmpReplyIpv4); icmpReplyEth.setEtherType(Ethernet.TYPE_IPV4); icmpReplyEth.setDestinationMACAddress(icmpRequest.getSourceMACAddress()); icmpReplyEth.setSourceMACAddress(icmpRequest.getDestinationMACAddress()); icmpReplyEth.setVlanID(icmpRequest.getVlanID()); sendPacketOut(outport, icmpReplyEth); } private void sendPacketOut(ConnectPoint outport, Ethernet payload) { TrafficTreatment treatment = DefaultTrafficTreatment.builder(). setOutput(outport.port()).build(); OutboundPacket packet = new DefaultOutboundPacket(outport.deviceId(), treatment, ByteBuffer.wrap(payload.serialize())); packetService.emit(packet); } /** * Packet processor responsible receiving and filtering ICMP packets. */ private class IcmpProcessor implements PacketProcessor { @Override public void process(PacketContext context) { // Stop processing if the packet has been handled, since we // can't do any more to it. if (context.isHandled()) { return; } Ethernet packet = context.inPacket().parsed(); if (packet == null) { return; } if (packet.getEtherType() == Ethernet.TYPE_IPV4) { IPv4 ipv4Packet = (IPv4) packet.getPayload(); if (ipv4Packet.getProtocol() == IPv4.PROTOCOL_ICMP) { processPacketIn(context.inPacket()); } } } } }