blob: 1b14875905f03457fa844adcde2e3cd56f8d2f83 [file] [log] [blame]
package net.onrc.onos.ofcontroller.devicemanager;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.floodlightcontroller.core.FloodlightContext;
import net.floodlightcontroller.core.IFloodlightProviderService;
import net.floodlightcontroller.core.IOFMessageListener;
import net.floodlightcontroller.core.IOFSwitch;
import net.floodlightcontroller.core.IUpdate;
import net.floodlightcontroller.core.module.FloodlightModuleContext;
import net.floodlightcontroller.core.module.FloodlightModuleException;
import net.floodlightcontroller.core.module.IFloodlightModule;
import net.floodlightcontroller.core.module.IFloodlightService;
import net.floodlightcontroller.packet.ARP;
import net.floodlightcontroller.packet.DHCP;
import net.floodlightcontroller.packet.Ethernet;
import net.floodlightcontroller.packet.IPv4;
import net.floodlightcontroller.packet.UDP;
import net.floodlightcontroller.util.MACAddress;
import net.onrc.onos.ofcontroller.core.IDeviceStorage;
import net.onrc.onos.ofcontroller.core.internal.DeviceStorageImpl;
import org.openflow.protocol.OFMessage;
import org.openflow.protocol.OFPacketIn;
import org.openflow.protocol.OFType;
public class OnosDeviceManager implements IFloodlightModule, IOFMessageListener,
IOnosDeviceService {
private IDeviceStorage deviceStorage;
private IFloodlightProviderService floodlightProvider;
private class OnosDeviceUpdate implements IUpdate {
private OnosDevice device;
public OnosDeviceUpdate(OnosDevice device) {
this.device = device;
}
@Override
public void dispatch() {
deviceStorage.addOnosDevice(device);
}
}
@Override
public String getName() {
return "onosdevicemanager";
}
@Override
public boolean isCallbackOrderingPrereq(OFType type, String name) {
// We want link discovery to consume LLDP first otherwise we'll
// end up reading bad device info from LLDP packets
return type == OFType.PACKET_IN && "linkdiscovery".equals(name);
}
@Override
public boolean isCallbackOrderingPostreq(OFType type, String name) {
return type == OFType.PACKET_IN &&
("proxyarpmanager".equals(name) || "onosforwarding".equals(name));
}
@Override
public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
if (msg.getType().equals(OFType.PACKET_IN)) {
OFPacketIn pi = (OFPacketIn) msg;
Ethernet eth = IFloodlightProviderService.bcStore.
get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
return processPacketIn(sw, pi, eth);
}
return Command.CONTINUE;
}
private Command processPacketIn(IOFSwitch sw, OFPacketIn pi, Ethernet eth) {
// Extract source entity information
OnosDevice srcDevice =
getSourceDeviceFromPacket(eth, sw.getId(), pi.getInPort());
if (srcDevice == null)
return Command.STOP;
floodlightProvider.publishUpdate(new OnosDeviceUpdate(srcDevice));
return Command.CONTINUE;
}
/**
* Get IP address from packet if the packet is either an ARP
* or a DHCP packet
* @param eth
* @param dlAddr
* @return
*/
private int getSrcNwAddr(Ethernet eth, long dlAddr) {
if (eth.getPayload() instanceof ARP) {
ARP arp = (ARP) eth.getPayload();
if ((arp.getProtocolType() == ARP.PROTO_TYPE_IP) &&
(Ethernet.toLong(arp.getSenderHardwareAddress()) == dlAddr)) {
return IPv4.toIPv4Address(arp.getSenderProtocolAddress());
}
} else if (eth.getPayload() instanceof IPv4) {
IPv4 ipv4 = (IPv4) eth.getPayload();
if (ipv4.getPayload() instanceof UDP) {
UDP udp = (UDP)ipv4.getPayload();
if (udp.getPayload() instanceof DHCP) {
DHCP dhcp = (DHCP)udp.getPayload();
if (dhcp.getOpCode() == DHCP.OPCODE_REPLY) {
return ipv4.getSourceAddress();
}
}
}
}
return 0;
}
/**
* Parse an entity from an {@link Ethernet} packet.
* @param eth the packet to parse
* @param sw the switch on which the packet arrived
* @param pi the original packetin
* @return the entity from the packet
*/
private OnosDevice getSourceDeviceFromPacket(Ethernet eth,
long swdpid,
short port) {
byte[] dlAddrArr = eth.getSourceMACAddress();
long dlAddr = Ethernet.toLong(dlAddrArr);
// Ignore broadcast/multicast source
if ((dlAddrArr[0] & 0x1) != 0)
return null;
short vlan = eth.getVlanID();
int nwSrc = getSrcNwAddr(eth, dlAddr);
return new OnosDevice(MACAddress.valueOf(dlAddr),
((vlan >= 0) ? vlan : null),
((nwSrc != 0) ? nwSrc : null),
swdpid,
port,
new Date());
}
@Override
public Collection<Class<? extends IFloodlightService>> getModuleServices() {
List<Class<? extends IFloodlightService>> services =
new ArrayList<Class<? extends IFloodlightService>>();
services.add(IOnosDeviceService.class);
return services;
}
@Override
public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
Map<Class<? extends IFloodlightService>, IFloodlightService> impls =
new HashMap<Class<? extends IFloodlightService>, IFloodlightService>();
impls.put(IOnosDeviceService.class, this);
return impls;
}
@Override
public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
List<Class<? extends IFloodlightService>> dependencies =
new ArrayList<Class<? extends IFloodlightService>>();
dependencies.add(IFloodlightProviderService.class);
return dependencies;
}
@Override
public void init(FloodlightModuleContext context)
throws FloodlightModuleException {
floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
deviceStorage = new DeviceStorageImpl();
deviceStorage.init("","");
}
@Override
public void startUp(FloodlightModuleContext context) {
floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
}
}