/*
* Copyright (c) 2013 Big Switch Networks, Inc.
*
* Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html
*
* 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.sdnplatform.netvirt.virtualrouting.internal;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import org.openflow.protocol.OFMessage;
import org.openflow.protocol.OFPacketIn;
import org.openflow.protocol.OFType;
import org.openflow.util.HexString;
import org.sdnplatform.core.ListenerContext;
import org.sdnplatform.core.IControllerService;
import org.sdnplatform.core.IOFMessageListener;
import org.sdnplatform.core.IOFSwitch;
import org.sdnplatform.core.annotations.LogMessageCategory;
import org.sdnplatform.devicemanager.IDevice;
import org.sdnplatform.devicemanager.IDeviceService;
import org.sdnplatform.netvirt.virtualrouting.IICMPListener;
import org.sdnplatform.netvirt.virtualrouting.IICMPListener.ICMPCommand;
import org.sdnplatform.packet.Ethernet;
import org.sdnplatform.packet.ICMP;
import org.sdnplatform.packet.IPv4;
import org.sdnplatform.routing.RoutingDecision;
import org.sdnplatform.routing.IRoutingDecision.RoutingAction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Manages ICMP requests.
* @author wilmo119
*
*/
@LogMessageCategory("Network Virtualization")
public class IcmpManager implements IOFMessageListener {
protected static Logger logger = LoggerFactory.getLogger(IcmpManager.class);
protected Set<IICMPListener> icmpListeners;
public IcmpManager() {
icmpListeners = new CopyOnWriteArraySet<IICMPListener>();
}
public void addIcmpListener(IICMPListener il) {
icmpListeners.add(il);
if (logger.isDebugEnabled()) {
logger.debug("Added icmp listener: {}", il.getName());
}
}
@Override
public Command receive(IOFSwitch sw, OFMessage msg,
ListenerContext cntx) {
switch (msg.getType()) {
case PACKET_IN:
return this.processPacketInMessage(sw, (OFPacketIn) msg, cntx);
default:
return Command.CONTINUE;
}
}
private Command processPacketInMessage(IOFSwitch sw, OFPacketIn pi,
ListenerContext cntx) {
Ethernet eth =
IControllerService.bcStore.get(cntx,
IControllerService.CONTEXT_PI_PAYLOAD);
if (eth.getEtherType() != Ethernet.TYPE_IPv4)
return Command.CONTINUE;
IPv4 ipv4 = (IPv4) eth.getPayload();
if (!(ipv4.getPayload() instanceof ICMP))
return Command.CONTINUE;
ICMP icmp = (ICMP) ipv4.getPayload();
if (logger.isTraceEnabled()) {
long srcMac = Ethernet.toLong(eth.getSourceMACAddress());
long dstMac = Ethernet.toLong(eth.getDestinationMACAddress());
int srcIp = ipv4.getSourceAddress();
int dstIp = ipv4.getDestinationAddress();
logger.trace("Got ICMP: {}::{} -> {}::{}",
new Object[] { HexString.toHexString(srcMac),
IPv4.fromIPv4Address(srcIp),
HexString.toHexString(dstMac),
IPv4.fromIPv4Address(dstIp) });
logger.trace("ICMP type: {} code: {}", icmp.getIcmpType(),
icmp.getIcmpCode());
}
for (IICMPListener il : icmpListeners) {
ICMPCommand ret = null;
if (icmp.getIcmpType() == ICMP.ECHO_REQUEST) {
ret = il.ICMPRequestHandler(sw, pi, cntx);
} else if (icmp.getIcmpType() == ICMP.ECHO_REPLY) {
ret = il.ICMPReplyHandler(sw, pi, cntx);
}
if (ret == null || ret == ICMPCommand.CONTINUE) {
continue;
} else if (ret == ICMPCommand.STOP) {
IDevice srcDevice = IDeviceService.fcStore.get(cntx,
IDeviceService.CONTEXT_SRC_DEVICE);
RoutingAction ra = RoutingAction.NONE;
RoutingDecision vrd = new RoutingDecision(sw.getId(),
pi.getInPort(),
srcDevice, ra);
vrd.addToContext(cntx);
return Command.STOP;
}
}
return Command.CONTINUE;
}
@Override
public String getName() {
return "icmpmanager";
}
@Override
public boolean isCallbackOrderingPrereq(OFType type, String name) {
return false;
}
@Override
public boolean isCallbackOrderingPostreq(OFType type, String name) {
return false;
}
}