diff --git a/src/main/java/net/floodlightcontroller/debugevent/Event.java b/src/main/java/net/floodlightcontroller/debugevent/Event.java index ebbeb650ff771b8040074c589c4ffcd438afae42..381008543d6e34aac972c38739de530db7553024 100644 --- a/src/main/java/net/floodlightcontroller/debugevent/Event.java +++ b/src/main/java/net/floodlightcontroller/debugevent/Event.java @@ -3,10 +3,12 @@ package net.floodlightcontroller.debugevent; import java.lang.reflect.Field; import java.text.SimpleDateFormat; import java.util.HashMap; +import java.util.List; import java.util.Map; import net.floodlightcontroller.debugevent.IDebugEventService.EventColumn; import net.floodlightcontroller.debugevent.IDebugEventService.EventFieldType; +import net.floodlightcontroller.devicemanager.SwitchPort; import net.floodlightcontroller.packet.IPv4; import org.openflow.util.HexString; @@ -135,6 +137,48 @@ public class Event { retMap.put(ec.name(), HexString.toHexString((Long) obj, 6)); } else if (ec.description() == EventFieldType.IPv4) { retMap.put(ec.name(), IPv4.fromIPv4Address((Integer) obj)); + } else if (ec.description() == EventFieldType.LIST_IPV4) { + @SuppressWarnings("unchecked") + List<Integer> ipv4Addresses = (List<Integer>)obj; + StringBuilder ipv4AddressesStr = new StringBuilder(); + if (ipv4Addresses.size() == 0) { + ipv4AddressesStr.append("--"); + } else { + for (Integer ipv4Addr : ipv4Addresses) { + ipv4AddressesStr.append(IPv4.fromIPv4Address(ipv4Addr.intValue())); + ipv4AddressesStr.append(" "); + } + } + retMap.put(ec.name(), ipv4AddressesStr.toString()); + } else if (ec.description() == + EventFieldType.LIST_ATTACHMENT_POINT) { + @SuppressWarnings("unchecked") + List<SwitchPort> aps = (List<SwitchPort>)obj; + StringBuilder apsStr = new StringBuilder(); + if (aps.size() == 0) { + apsStr.append("--"); + } else { + for (SwitchPort ap : aps) { + apsStr.append(HexString.toHexString(ap.getSwitchDPID())); + apsStr.append("/"); + apsStr.append(ap.getPort()); + apsStr.append(" "); + } + } + retMap.put(ec.name(), apsStr.toString()); + } else if (ec.description() == EventFieldType.LIST_VLAN) { + @SuppressWarnings("unchecked") + List<Short> vlanIds = (List<Short>)obj; + StringBuilder vlanIdsStr = new StringBuilder(); + if (vlanIds.size() == 0) { + vlanIdsStr.append("--"); + } else { + for (Short vlanId : vlanIds) { + vlanIdsStr.append(vlanId.toString()); + vlanIdsStr.append(" "); + } + } + retMap.put(ec.name(), vlanIdsStr.toString()); } else { retMap.put(ec.name(), obj.toString()); } diff --git a/src/main/java/net/floodlightcontroller/debugevent/IDebugEventService.java b/src/main/java/net/floodlightcontroller/debugevent/IDebugEventService.java index 7146c8ffe236e23dd330df2b5c739871f8ac7c5d..ad54a7a8345cdc942cc91c865634bc59d9222c49 100644 --- a/src/main/java/net/floodlightcontroller/debugevent/IDebugEventService.java +++ b/src/main/java/net/floodlightcontroller/debugevent/IDebugEventService.java @@ -25,7 +25,8 @@ public interface IDebugEventService extends IFloodlightService { * Describes the type of field obtained from reflection */ enum EventFieldType { - DPID, IPv4, MAC, STRING, OBJECT, PRIMITIVE + DPID, IPv4, MAC, STRING, OBJECT, PRIMITIVE, LIST_IPV4, + LIST_ATTACHMENT_POINT, LIST_VLAN } /** diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java index 5223fb6ed1ad6a47749510bb1f7715dde9dfd2e0..a678e1e5a2f2739b16372c588c8433961bcd2550 100755 --- a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java +++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java @@ -18,6 +18,7 @@ package net.floodlightcontroller.devicemanager.internal; import java.util.ArrayList; +import java.util.Arrays; import java.util.Calendar; import java.util.Collection; import java.util.Collections; @@ -57,6 +58,13 @@ import net.floodlightcontroller.debugcounter.IDebugCounterService; import net.floodlightcontroller.debugcounter.IDebugCounterService.CounterException; import net.floodlightcontroller.debugcounter.NullDebugCounter; import net.floodlightcontroller.debugcounter.IDebugCounterService.CounterType; +import net.floodlightcontroller.debugevent.IDebugEventService; +import net.floodlightcontroller.debugevent.IDebugEventService.EventColumn; +import net.floodlightcontroller.debugevent.IDebugEventService.EventFieldType; +import net.floodlightcontroller.debugevent.IDebugEventService.EventType; +import net.floodlightcontroller.debugevent.IDebugEventService.MaxEventsRegistered; +import net.floodlightcontroller.debugevent.IEventUpdater; +import net.floodlightcontroller.debugevent.NullDebugEvent; import net.floodlightcontroller.devicemanager.IDevice; import net.floodlightcontroller.devicemanager.IDeviceService; import net.floodlightcontroller.devicemanager.IEntityClass; @@ -162,6 +170,12 @@ IFlowReconcileListener, IInfoProvider { public IDebugCounter cntConsolidateStoreDevicesRemoved; public IDebugCounter cntTransitionToMaster; + /** + * Debug Events + */ + private IDebugEventService debugEvents; + private IEventUpdater<DeviceEvent> evDevice; + private boolean isMaster = false; static final String DEVICE_SYNC_STORE_NAME = @@ -659,6 +673,69 @@ IFlowReconcileListener, IInfoProvider { } } + // *************** + // IDeviceListener + // *************** + private class DeviceDebugEventLogger implements IDeviceListener { + @Override + public String getName() { + return "deviceDebugEventLogger"; + } + + @Override + public boolean isCallbackOrderingPrereq(String type, String name) { + return false; + } + + @Override + public boolean isCallbackOrderingPostreq(String type, String name) { + return false; + } + + @Override + public void deviceAdded(IDevice device) { + generateDeviceEvent(device, "host-added"); + } + + @Override + public void deviceRemoved(IDevice device) { + generateDeviceEvent(device, "host-removed"); + } + + @Override + public void deviceMoved(IDevice device) { + generateDeviceEvent(device, "host-moved"); + } + + @Override + public void deviceIPV4AddrChanged(IDevice device) { + generateDeviceEvent(device, "host-ipv4-addr-changed"); + } + + @Override + public void deviceVlanChanged(IDevice device) { + generateDeviceEvent(device, "host-vlan-changed"); + } + + private void generateDeviceEvent(IDevice device, String reason) { + List<Integer> ipv4Addresses = + new ArrayList<Integer>(Arrays.asList(device.getIPv4Addresses())); + List<SwitchPort> oldAps = + new ArrayList<SwitchPort>(Arrays.asList(device.getOldAP())); + List<SwitchPort> currentAps = + new ArrayList<SwitchPort>(Arrays.asList(device.getAttachmentPoints())); + List<Short> vlanIds = + new ArrayList<Short>(Arrays.asList(device.getVlanId())); + + evDevice.updateEventNoFlush( + new DeviceEvent(device.getMACAddress(), + ipv4Addresses, + oldAps, + currentAps, + vlanIds, reason)); + } + } + // ************* // IInfoProvider // ************* @@ -832,10 +909,27 @@ IFlowReconcileListener, IInfoProvider { this.flowReconcileEngine = fmc.getServiceImpl(IFlowReconcileEngineService.class); this.entityClassifier = fmc.getServiceImpl(IEntityClassifierService.class); this.debugCounters = fmc.getServiceImpl(IDebugCounterService.class); + this.debugEvents = fmc.getServiceImpl(IDebugEventService.class); this.syncService = fmc.getServiceImpl(ISyncService.class); this.deviceSyncManager = new DeviceSyncManager(); this.haListenerDelegate = new HAListenerDelegate(); registerDeviceManagerDebugCounters(); + registerDeviceManagerDebugEvents(); + this.addListener(new DeviceDebugEventLogger()); + } + + private void registerDeviceManagerDebugEvents() throws FloodlightModuleException { + if (debugEvents == null) { + debugEvents = new NullDebugEvent(); + } + try { + evDevice = + debugEvents.registerEvent(PACKAGE, "hostevent", + "Host added, removed, updated, or moved", + EventType.ALWAYS_LOG, DeviceEvent.class, 500); + } catch (MaxEventsRegistered e) { + throw new FloodlightModuleException("Max events registered", e); + } } @Override @@ -2493,4 +2587,37 @@ IFlowReconcileListener, IInfoProvider { IHAListener getHAListener() { return this.haListenerDelegate; } + + /** + * Device Event Class used to log Device related events + */ + private class DeviceEvent { + @EventColumn(name = "MAC", description = EventFieldType.MAC) + private final long macAddress; + @EventColumn(name = "IPs", description = EventFieldType.LIST_IPV4) + private final List<Integer> ipv4Addresses; + @EventColumn(name = "Old Attachment Points", + description = EventFieldType.LIST_ATTACHMENT_POINT) + private final List<SwitchPort> oldAttachmentPoints; + @EventColumn(name = "Current Attachment Points", + description = EventFieldType.LIST_ATTACHMENT_POINT) + private final List<SwitchPort> currentAttachmentPoints; + @EventColumn(name = "VLAN IDs", description = EventFieldType.LIST_VLAN) + private final List<Short> vlanIds; + @EventColumn(name = "Reason", description = EventFieldType.STRING) + private final String reason; + + public DeviceEvent(long macAddress, List<Integer> ipv4Addresses, + List<SwitchPort> oldAttachmentPoints, + List<SwitchPort> currentAttachmentPoints, + List<Short> vlanIds, String reason) { + super(); + this.macAddress = macAddress; + this.ipv4Addresses = ipv4Addresses; + this.oldAttachmentPoints = oldAttachmentPoints; + this.currentAttachmentPoints = currentAttachmentPoints; + this.vlanIds = vlanIds; + this.reason = reason; + } + } }