package net.floodlightcontroller.core.internal;

/**
 *    Copyright 2012, Big Switch Networks, Inc.
 *    Originally created by David Erickson, Stanford University
 *
 *    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.
 **/

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import net.floodlightcontroller.core.FloodlightContext;
import net.floodlightcontroller.core.IFloodlightProviderService;
import net.floodlightcontroller.core.IFloodlightProviderService.Role;
import net.floodlightcontroller.core.IOFMessageListener;
import net.floodlightcontroller.core.IOFSwitch;
import net.floodlightcontroller.core.SwitchDriverSubHandshakeAlreadyStarted;
import net.floodlightcontroller.core.SwitchDriverSubHandshakeCompleted;
import net.floodlightcontroller.core.SwitchDriverSubHandshakeNotStarted;
import net.floodlightcontroller.core.annotations.LogMessageDoc;
import net.floodlightcontroller.core.web.serializers.DPIDSerializer;
import net.floodlightcontroller.debugcounter.IDebugCounter;
import net.floodlightcontroller.debugcounter.IDebugCounterService;
import net.floodlightcontroller.debugcounter.IDebugCounterService.CounterException;
import net.floodlightcontroller.debugcounter.IDebugCounterService.CounterType;
import net.floodlightcontroller.debugcounter.NullDebugCounter;
import net.floodlightcontroller.threadpool.IThreadPoolService;
import net.floodlightcontroller.util.LinkedHashSetWrapper;
import net.floodlightcontroller.util.OrderedCollection;
import net.floodlightcontroller.util.TimedCache;

import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonProperty;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.jboss.netty.channel.Channel;
import org.projectfloodlight.openflow.protocol.OFActionType;
import org.projectfloodlight.openflow.protocol.OFCapabilities;
import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFFactories;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFPortConfig;
import org.projectfloodlight.openflow.protocol.OFPortDesc;
import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFPortReason;
import org.projectfloodlight.openflow.protocol.OFPortState;
import org.projectfloodlight.openflow.protocol.OFPortStatus;
import org.projectfloodlight.openflow.protocol.OFStatsReply;
import org.projectfloodlight.openflow.protocol.OFStatsRequest;
import org.projectfloodlight.openflow.protocol.OFType;
import org.projectfloodlight.openflow.protocol.OFVersion;
import org.projectfloodlight.openflow.types.DatapathId;
import org.projectfloodlight.openflow.types.OFAuxId;
import org.projectfloodlight.openflow.types.OFGroup;
import org.projectfloodlight.openflow.types.OFPort;
import org.projectfloodlight.openflow.types.TableId;
import org.projectfloodlight.openflow.types.U64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * This is the internal representation of an openflow switch.
 */
public class OFSwitchImplBase implements IOFSwitch {
    // TODO: should we really do logging in the class or should we throw
    // exception that can then be handled by callers?
    protected final static Logger log = LoggerFactory.getLogger(OFSwitchImplBase.class);

    private static final String HA_CHECK_SWITCH =
            "Check the health of the indicated switch.  If the problem " +
                    "persists or occurs repeatedly, it likely indicates a defect " +
                    "in the switch HA implementation.";

    protected ConcurrentMap<Object, Object> attributes;
    protected IFloodlightProviderService floodlightProvider;
    protected IThreadPoolService threadPool;
    protected Date connectedSince;
    protected String stringId;
    protected Channel channel;
    // transaction id used for messages sent out to this switch from
    // this controller instance. This xid has significance only between this
    // controller<->switch pair.
    protected AtomicInteger transactionIdSource;

    // generation id used for roleRequest messages sent to switches (see section
    // 6.3.5 of the OF1.3.4 spec). This generationId has significance between
    // all the controllers that this switch is connected to; and only for role
    // request messages with role MASTER or SLAVE. The set of Controllers that
    // this switch is connected to should coordinate the next generation id,
    // via transactional semantics.
    protected long generationIdSource;

    // Lock to protect modification of the port maps. We only need to
    // synchronize on modifications. For read operations we are fine since
    // we rely on ConcurrentMaps which works for our use case.
    //private Object portLock; XXX S remove this

    // Map port numbers to the appropriate OFPortDesc
    protected ConcurrentHashMap<Integer, OFPortDesc> portsByNumber;
    // Map port names to the appropriate OFPhyiscalPort
    // XXX: The OF spec doesn't specify if port names need to be unique but
    //      according it's always the case in practice.
    protected ConcurrentHashMap<String, OFPortDesc> portsByName;
    protected Map<Integer, OFStatisticsFuture> statsFutureMap;
    protected Map<Integer, IOFMessageListener> iofMsgListenersMap; // XXX S why is this needed?
    protected Map<Integer, OFFeaturesReplyFuture> featuresFutureMap;
    protected boolean connected;
    protected Role role;
    protected TimedCache<Long> timedCache;
    protected ReentrantReadWriteLock listenerLock;
    protected ConcurrentMap<Short, Long> portBroadcastCacheHitMap;
    /**
     * When sending a role request message, the role request is added
     * to this queue. If a role reply is received this queue is checked to
     * verify that the reply matches the expected reply. We require in order
     * delivery of replies. That's why we use a Queue.
     * The RoleChanger uses a timeout to ensure we receive a timely reply.
     * <p/>
     * Need to synchronize on this instance if a request is sent, received,
     * checked.
     */
    protected LinkedList<PendingRoleRequestEntry> pendingRoleRequests;

    /** OpenFlow version for this switch */
    protected OFVersion ofversion;
    // Description stats reply describing this switch
    private OFDescStatsReply switchDescription;
    // Switch features from initial featuresReply
    protected Set<OFCapabilities> capabilities;
    protected int buffers;
    protected Set<OFActionType> actions;
    protected byte tables;
    protected DatapathId datapathId;
	private OFAuxId auxId;

    private IDebugCounterService debugCounters;
	private boolean debugCountersRegistered;
	@SuppressWarnings("unused")
    private IDebugCounter ctrSwitch, ctrSwitchPktin, ctrSwitchWrite,
    ctrSwitchPktinDrops, ctrSwitchWriteDrops;

	protected boolean startDriverHandshakeCalled = false;
	private boolean flowTableFull = false;

	private final PortManager portManager;



    protected static final ThreadLocal<Map<OFSwitchImplBase, List<OFMessage>>> local_msg_buffer =
		new ThreadLocal<Map<OFSwitchImplBase, List<OFMessage>>>() {
	@Override
	protected Map<OFSwitchImplBase, List<OFMessage>> initialValue() {
		return new WeakHashMap<OFSwitchImplBase, List<OFMessage>>();
	}
    };


	private static final String BASE = "switchbase";

    protected static class PendingRoleRequestEntry {
        protected int xid;
        protected Role role;
        // cookie is used to identify the role "generation". roleChanger uses
        protected long cookie;

        public PendingRoleRequestEntry(int xid, Role role, long cookie) {
            this.xid = xid;
            this.role = role;
            this.cookie = cookie;
        }
    }

    public OFSwitchImplBase() {
        this.stringId = null;
        this.attributes = new ConcurrentHashMap<Object, Object>();
        this.connectedSince = new Date();
        this.transactionIdSource = new AtomicInteger();
        this.generationIdSource = 0; // XXX S this is wrong; should be negotiated
        // XXX S no need this.portLock = new Object();
        this.portsByNumber = new ConcurrentHashMap<Integer, OFPortDesc>();
        this.portsByName = new ConcurrentHashMap<String, OFPortDesc>();
        this.connected = true;
        this.statsFutureMap = new ConcurrentHashMap<Integer, OFStatisticsFuture>();
        this.featuresFutureMap = new ConcurrentHashMap<Integer, OFFeaturesReplyFuture>();
        this.iofMsgListenersMap = new ConcurrentHashMap<Integer, IOFMessageListener>();
        this.role = null;
        this.timedCache = new TimedCache<Long>(100, 5 * 1000);  // 5 seconds interval
        this.listenerLock = new ReentrantReadWriteLock();
        this.pendingRoleRequests = new LinkedList<OFSwitchImplBase.PendingRoleRequestEntry>();
        this.portManager = new PortManager();
        // by default the base impl declares no support for Nx_role_requests.
        // OF1.0 switches like OVS that do support these messages should set the
        // attribute in the associated switch driver.
        setAttribute(SWITCH_SUPPORTS_NX_ROLE, false);

    }

    //*******************************************
    //    Setters and Getters
    //*******************************************

    @Override
    public Object getAttribute(String name) {
        if (this.attributes.containsKey(name)) {
            return this.attributes.get(name);
        }
        return null;
    }

    @Override
    public ConcurrentMap<Object, Object> getAttributes() {
        return this.attributes;
    }

    @Override
    public void setAttribute(String name, Object value) {
        this.attributes.put(name, value);
        return;
    }

    @Override
    public Object removeAttribute(String name) {
        return this.attributes.remove(name);
    }

    @Override
    public boolean hasAttribute(String name) {
        return this.attributes.containsKey(name);
    }

    @Override
    @JsonSerialize(using = DPIDSerializer.class)
    @JsonProperty("dpid")
    public long getId() {
        if (this.stringId == null)
            throw new RuntimeException("Features reply has not yet been set");
        return this.datapathId.getLong();
    }

    @JsonIgnore
    @Override
    public String getStringId() {
        return stringId;
    }

    @Override
    public OFFactory getFactory() {
        return OFFactories.getFactory(ofversion);
    }

    @Override
    public OFVersion getOFVersion() {
        return ofversion;
    }

    @Override
    public void setOFVersion(OFVersion ofv) {
        ofversion = ofv;
    }

    /**
     * @param floodlightProvider the floodlightProvider to set
     */
    @JsonIgnore
    @Override
    public void setFloodlightProvider(IFloodlightProviderService floodlightProvider) {
        this.floodlightProvider = floodlightProvider;
    }

    @JsonIgnore
    @Override
    public void setThreadPoolService(IThreadPoolService tp) {
        this.threadPool = tp;
    }

    @Override
    @JsonIgnore
    public void setDebugCounterService(IDebugCounterService debugCounters)
            throws CounterException {
        this.debugCounters = debugCounters;
        registerOverloadCounters();
    }

    /* (non-Javadoc)
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        return "OFSwitchImpl [" + ((channel != null) ? channel.getRemoteAddress() : "?")
			+ " DPID[" + ((stringId != null) ? stringId : "?") + "]]";
    }


    //*******************************************
    //    Channel related methods
    //*******************************************

    @JsonIgnore
    @Override
    public void setChannel(Channel channel) {
        this.channel = channel;
    }

    @Override
    public void write(OFMessage m, FloodlightContext bc) throws IOException {
        Map<OFSwitchImplBase, List<OFMessage>> msg_buffer_map = local_msg_buffer.get();
        List<OFMessage> msg_buffer = msg_buffer_map.get(this);
        if (msg_buffer == null) {
            msg_buffer = new ArrayList<OFMessage>();
            msg_buffer_map.put(this, msg_buffer);
        }
        // XXX S will change when iFloodlight provider changes
        //this.floodlightProvider.handleOutgoingMessage(this, m, bc);
        msg_buffer.add(m);

        if ((msg_buffer.size() >= Controller.BATCH_MAX_SIZE) ||
                ((m.getType() != OFType.PACKET_OUT) && (m.getType() != OFType.FLOW_MOD))) {
            this.write(msg_buffer);
            msg_buffer.clear();
        }
    }

    @Override
    @LogMessageDoc(level = "WARN",
            message = "Sending OF message that modifies switch " +
                    "state while in the slave role: {switch}",
            explanation = "An application has sent a message to a switch " +
                    "that is not valid when the switch is in a slave role",
            recommendation = LogMessageDoc.REPORT_CONTROLLER_BUG)
    public void write(List<OFMessage> msglist,
                      FloodlightContext bc) throws IOException {
        for (OFMessage m : msglist) {
            if (role == Role.SLAVE) {
                switch (m.getType()) {
                    case PACKET_OUT:
                    case FLOW_MOD:
                    case PORT_MOD:
                        log.warn("Sending OF message that modifies switch " +
                                "state while in the slave role: {}",
                                m.getType().name());
                        break;
                    default:
                        break;
                }
            }
            // XXX S again
            //this.floodlightProvider.handleOutgoingMessage(this, m, bc);
        }
        this.write(msglist);
    }

    public void write(List<OFMessage> msglist) throws IOException {
        this.channel.write(msglist);
    }

    @Override
    public void disconnectSwitch() {
        channel.close();
    }

    @Override
    public Date getConnectedSince() {
        return connectedSince;
    }

    @JsonIgnore
    @Override
    public int getNextTransactionId() {
        return this.transactionIdSource.incrementAndGet();
    }

    @JsonIgnore
    @Override
    public synchronized boolean isConnected() {
        return connected;
    }

    @Override
    @JsonIgnore
    public synchronized void setConnected(boolean connected) {
        this.connected = connected;
    }



    //*******************************************
    //    Switch features related methods
    //*******************************************

    /**
     * Set the features reply for this switch from the handshake
     */
    protected void setFeaturesReply(OFFeaturesReply featuresReply) {
	if (featuresReply == null) {
		log.error("Error setting featuresReply for switch: {}", getStringId());
		return;
	}
	this.datapathId = featuresReply.getDatapathId();
	this.capabilities = featuresReply.getCapabilities();
	this.buffers = (int) featuresReply.getNBuffers();
	this.tables = (byte) featuresReply.getNTables();
	this.stringId = this.datapathId.toString();
	if (ofversion == OFVersion.OF_13) {
		auxId = featuresReply.getAuxiliaryId();
		if (!auxId.equals(OFAuxId.MAIN)) {
			log.warn("This controller does not handle auxiliary connections. "
					+ "Aux connection id {} received from switch {}",
					auxId, getStringId());
		}
	}

	if (ofversion == OFVersion.OF_10) {
		this.actions = featuresReply.getActions();
		portManager.compareAndUpdatePorts(featuresReply.getPorts(), true);
	}
    }

    /**
     * Set the port descriptions for this switch from the handshake for
     * an OF1.3 switch.
     */
    protected void setPortDescReply(OFPortDescStatsReply pdrep) {
	if (ofversion != OFVersion.OF_13) return;
	if (pdrep == null) {
		log.error("Error setting ports description for switch: {}", getStringId());
		return;
	}
	portManager.updatePorts(pdrep.getEntries());
    }

    @Override
    public int getNumBuffers() {
        return buffers;
    }
    @Override
    public Set<OFActionType> getActions() {
        return actions;
    }
    @Override
    public  Set<OFCapabilities> getCapabilities() {
        return capabilities;
    }
    @Override
    public byte getNumTables() {
        return tables;
    }

//    public Future<OFFeaturesReply> getFeaturesReplyFromSwitch()
//            throws IOException {
//    	// XXX S fix this later
//    	OFMessage request = floodlightProvider.getOFMessageFactory_13()
//    			.buildFeaturesRequest()
//    			.setXid(getNextTransactionId())
//    			.build();
//    	OFFeaturesReplyFuture future =
//                new OFFeaturesReplyFuture(threadPool, this, (int) request.getXid());
//        this.featuresFutureMap.put((int) request.getXid(), future);
//        this.channel.write(Collections.singletonList(request));
//        return future;
//
//    }
//
//    public void deliverOFFeaturesReply(OFMessage reply) {
//        OFFeaturesReplyFuture future = this.featuresFutureMap.get(reply.getXid());
//        if (future != null) {
//            future.deliverFuture(this, reply);
//            // The future will ultimately unregister itself and call
//            // cancelFeaturesReply
//            return;
//        }
//        log.error("Switch {}: received unexpected featureReply", this);
//    }

    @Override
    public void cancelFeaturesReply(int transactionId) {
        this.featuresFutureMap.remove(transactionId);
    }

    @JsonIgnore
    public void setSwitchDescription(OFDescStatsReply desc) {
	switchDescription = desc;
    }

    @Override
    @JsonIgnore
    public OFDescStatsReply getSwitchDescription() {
	return switchDescription;
    }

    //*******************************************
    //    Switch port handling
    //*******************************************

    @Override
    @JsonIgnore
    public Collection<OFPortDesc> getEnabledPorts() {
        return portManager.getEnabledPorts();
    }

    @Override
    @JsonIgnore
    public Collection<Integer> getEnabledPortNumbers() {
        return portManager.getEnabledPortNumbers();
    }

    @Override
    public OFPortDesc getPort(int portNumber) {
        return portManager.getPort(portNumber);
    }

    @Override
    public OFPortDesc getPort(String portName) {
        return portManager.getPort(portName);
    }

    @Override
    @JsonIgnore
    public OrderedCollection<PortChangeEvent> processOFPortStatus(OFPortStatus ps) {
        return portManager.handlePortStatusMessage(ps);
    }

    @Override
    @JsonProperty("ports")
    public Collection<OFPortDesc> getPorts() {
	return portManager.getPorts();
    }

    @Override
    public boolean portEnabled(int portNumber) {
        return isEnabled(portManager.getPort(portNumber));
    }

    @Override
    public boolean portEnabled(String portName) {
	return isEnabled(portManager.getPort(portName));
    }

    private boolean isEnabled(OFPortDesc p) {
	return (p != null &&
			!p.getState().contains(OFPortState.LINK_DOWN) &&
			!p.getState().contains(OFPortState.BLOCKED) &&
                !p.getConfig().contains(OFPortConfig.PORT_DOWN));
    }

    @Override
    public OrderedCollection<PortChangeEvent> comparePorts(Collection<OFPortDesc> ports) {
        return portManager.comparePorts(ports);
    }

    @Override
    @JsonIgnore
    public OrderedCollection<PortChangeEvent> setPorts(Collection<OFPortDesc> ports) {
        return portManager.updatePorts(ports);
    }

    /**
     * Manages the ports of this switch.
     *
     * Provides methods to query and update the stored ports. The class ensures
     * that every port name and port number is unique. When updating ports
     * the class checks if port number <-> port name mappings have change due
     * to the update. If a new port P has number and port that are inconsistent
     * with the previous mapping(s) the class will delete all previous ports
     * with name or number of the new port and then add the new port.
     *
     * Port names are stored as-is but they are compared case-insensitive
     *
     * The methods that change the stored ports return a list of
     * PortChangeEvents that represent the changes that have been applied
     * to the port list so that IOFSwitchListeners can be notified about the
     * changes.
     *
     * Implementation notes:
     * - We keep several different representations of the ports to allow for
     *   fast lookups
     * - Ports are stored in unchangeable lists. When a port is modified new
     *   data structures are allocated.
     * - We use a read-write-lock for synchronization, so multiple readers are
     *   allowed.
     * - All port numbers have int representation (no more shorts)
     */
    protected class PortManager {
        private final ReentrantReadWriteLock lock;
        private List<OFPortDesc> portList;
        private List<OFPortDesc> enabledPortList;
        private List<Integer> enabledPortNumbers;
        private Map<Integer,OFPortDesc> portsByNumber;
        private Map<String,OFPortDesc> portsByName;

        public PortManager() {
            this.lock = new ReentrantReadWriteLock();
            this.portList = Collections.emptyList();
            this.enabledPortList = Collections.emptyList();
            this.enabledPortNumbers = Collections.emptyList();
            this.portsByName = Collections.emptyMap();
            this.portsByNumber = Collections.emptyMap();
        }

        /**
         * Set the internal data structure storing this switch's port
         * to the ports specified by newPortsByNumber
         *
         * CALLER MUST HOLD WRITELOCK
         *
         * @param newPortsByNumber
         * @throws IllegaalStateException if called without holding the
         * writelock
         */
        private void updatePortsWithNewPortsByNumber(
                Map<Integer,OFPortDesc> newPortsByNumber) {
            if (!lock.writeLock().isHeldByCurrentThread()) {
                throw new IllegalStateException("Method called without " +
                                                "holding writeLock");
            }
            Map<String,OFPortDesc> newPortsByName =
                    new HashMap<String, OFPortDesc>();
            List<OFPortDesc> newPortList =
                    new ArrayList<OFPortDesc>();
            List<OFPortDesc> newEnabledPortList =
                    new ArrayList<OFPortDesc>();
            List<Integer> newEnabledPortNumbers = new ArrayList<Integer>();

            for(OFPortDesc p: newPortsByNumber.values()) {
                newPortList.add(p);
                newPortsByName.put(p.getName().toLowerCase(), p);
                if (isEnabled(p)) {
                    newEnabledPortList.add(p);
                    newEnabledPortNumbers.add(p.getPortNo().getPortNumber());
                }
            }
            portsByName = Collections.unmodifiableMap(newPortsByName);
            portsByNumber =
                    Collections.unmodifiableMap(newPortsByNumber);
            enabledPortList =
                    Collections.unmodifiableList(newEnabledPortList);
            enabledPortNumbers =
                    Collections.unmodifiableList(newEnabledPortNumbers);
            portList = Collections.unmodifiableList(newPortList);
        }

        /**
         * Handle a OFPortStatus delete message for the given port.
         * Updates the internal port maps/lists of this switch and returns
         * the PortChangeEvents caused by the delete. If the given port
         * exists as it, it will be deleted. If the name<->number for the
         * given port is inconsistent with the ports stored by this switch
         * the method will delete all ports with the number or name of the
         * given port.
         *
         * This method will increment error/warn counters and log
         *
         * @param delPort the port from the port status message that should
         * be deleted.
         * @return ordered collection of port changes applied to this switch
         */
        private OrderedCollection<PortChangeEvent> handlePortStatusDelete(
				OFPortDesc delPort) {
            lock.writeLock().lock();
            OrderedCollection<PortChangeEvent> events =
                    new LinkedHashSetWrapper<PortChangeEvent>();
            try {
                Map<Integer,OFPortDesc> newPortByNumber =
                        new HashMap<Integer, OFPortDesc>(portsByNumber);
                OFPortDesc prevPort =
                        portsByNumber.get(delPort.getPortNo().getPortNumber());
                if (prevPort == null) {
                    // so such port. Do we have a port with the name?
                    prevPort = portsByName.get(delPort.getName());
                    if (prevPort != null) {
                        newPortByNumber.remove(prevPort.getPortNo().getPortNumber());
                        events.add(new PortChangeEvent(prevPort,
                                                       PortChangeType.DELETE));
                    }
                } else if (prevPort.getName().equals(delPort.getName())) {
                    // port exists with consistent name-number mapping
                    newPortByNumber.remove(delPort.getPortNo().getPortNumber());
                    events.add(new PortChangeEvent(delPort,
                                                   PortChangeType.DELETE));
                } else {
                    // port with same number exists but its name differs. This
                    // is weird. The best we can do is to delete the existing
                    // port(s) that have delPort's name and number.
                    newPortByNumber.remove(delPort.getPortNo().getPortNumber());
                    events.add(new PortChangeEvent(prevPort,
                                                   PortChangeType.DELETE));
                    // is there another port that has delPort's name?
                    prevPort = portsByName.get(delPort.getName().toLowerCase());
                    if (prevPort != null) {
                        newPortByNumber.remove(prevPort.getPortNo().getPortNumber());
                        events.add(new PortChangeEvent(prevPort,
                                                       PortChangeType.DELETE));
                    }
                }
                updatePortsWithNewPortsByNumber(newPortByNumber);
                return events;
            } finally {
                lock.writeLock().unlock();
            }
        }

        /**
         * Handle a OFPortStatus message, update the internal data structures
         * that store ports and return the list of OFChangeEvents.
         *
         * This method will increment error/warn counters and log
         *
         * @param ps
         * @return
         */
        public OrderedCollection<PortChangeEvent> handlePortStatusMessage(OFPortStatus ps) {
            if (ps == null) {
                throw new NullPointerException("OFPortStatus message must " +
                                               "not be null");
            }
            lock.writeLock().lock();
            try {
                OFPortReason reason = ps.getReason();
                if (reason == null) {
                    throw new IllegalArgumentException("Unknown PortStatus " +
                            "reason code " + ps.getReason());
                }

                if (log.isDebugEnabled()) {
                    log.debug("Handling OFPortStatus: {} for {}",
                              reason, ps);
                }

                if (reason == OFPortReason.DELETE)
                        return handlePortStatusDelete(ps.getDesc());

                // We handle ADD and MODIFY the same way. Since OpenFlow
                // doesn't specify what uniquely identifies a port the
                // notion of ADD vs. MODIFY can also be hazy. So we just
                // compare the new port to the existing ones.
                Map<Integer,OFPortDesc> newPortByNumber =
                    new HashMap<Integer, OFPortDesc>(portsByNumber);
                OrderedCollection<PortChangeEvent> events =
				getSinglePortChanges(ps.getDesc());
                for (PortChangeEvent e: events) {
                    switch(e.type) {
                        case DELETE:
                            newPortByNumber.remove(e.port.getPortNo().getPortNumber());
                            break;
                        case ADD:
                            if (reason != OFPortReason.ADD) {
                                // weird case
                            }
                            newPortByNumber.put(e.port.getPortNo().getPortNumber(),
                                    e.port);
                            break;
                        case DOWN:
                            newPortByNumber.put(e.port.getPortNo().getPortNumber(),
                                    e.port);
                            break;
                        case OTHER_UPDATE:
                            newPortByNumber.put(e.port.getPortNo().getPortNumber(),
                                    e.port);
                            break;
                        case UP:
                            newPortByNumber.put(e.port.getPortNo().getPortNumber(),
					e.port);
                            break;
                    }
                }
                updatePortsWithNewPortsByNumber(newPortByNumber);
                return events;
            } finally {
                lock.writeLock().unlock();
            }

        }

        /**
         * Given a new or modified port newPort, returns the list of
         * PortChangeEvents to "transform" the current ports stored by
         * this switch to include / represent the new port. The ports stored
         * by this switch are <b>NOT</b> updated.
         *
         * This method acquires the readlock and is thread-safe by itself.
         * Most callers will need to acquire the write lock before calling
         * this method though (if the caller wants to update the ports stored
         * by this switch)
         *
         * @param newPort the new or modified port.
         * @return the list of changes
         */
        public OrderedCollection<PortChangeEvent> getSinglePortChanges(
			OFPortDesc newPort) {
            lock.readLock().lock();
            try {
                OrderedCollection<PortChangeEvent> events =
                        new LinkedHashSetWrapper<PortChangeEvent>();
                // Check if we have a port by the same number in our
                // old map.
                OFPortDesc prevPort =
                        portsByNumber.get(newPort.getPortNo().getPortNumber());
                if (newPort.equals(prevPort)) {
                    // nothing has changed
                    return events;
                }

                if (prevPort != null &&
                        prevPort.getName().equals(newPort.getName())) {
                    // A simple modify of a existing port
                    // A previous port with this number exists and it's name
                    // also matches the new port. Find the differences
                    if (isEnabled(prevPort) && !isEnabled(newPort)) {
                        events.add(new PortChangeEvent(newPort,
                                                       PortChangeType.DOWN));
                    } else if (!isEnabled(prevPort) && isEnabled(newPort)) {
                        events.add(new PortChangeEvent(newPort,
                                                       PortChangeType.UP));
                    } else {
                        events.add(new PortChangeEvent(newPort,
                                   PortChangeType.OTHER_UPDATE));
                    }
                    return events;
                }

                if (prevPort != null) {
                    // There exists a previous port with the same port
                    // number but the port name is different (otherwise we would
                    // never have gotten here)
                    // Remove the port. Name-number mapping(s) have changed
                    events.add(new PortChangeEvent(prevPort,
                                                   PortChangeType.DELETE));
                }

                // We now need to check if there exists a previous port sharing
                // the same name as the new/updated port.
                prevPort = portsByName.get(newPort.getName().toLowerCase());
                if (prevPort != null) {
                    // There exists a previous port with the same port
                    // name but the port number is different (otherwise we
                    // never have gotten here).
                    // Remove the port. Name-number mapping(s) have changed
                    events.add(new PortChangeEvent(prevPort,
                                                   PortChangeType.DELETE));
                }

                // We always need to add the new port. Either no previous port
                // existed or we just deleted previous ports with inconsistent
                // name-number mappings
                events.add(new PortChangeEvent(newPort, PortChangeType.ADD));
                return events;
            } finally {
                lock.readLock().unlock();
            }
        }

        /**
         * Compare the current ports of this switch to the newPorts list and
         * return the changes that would be applied to transfort the current
         * ports to the new ports. No internal data structures are updated
         * see {@link #compareAndUpdatePorts(List, boolean)}
         *
         * @param newPorts the list of new ports
         * @return The list of differences between the current ports and
         * newPortList
         */
        public OrderedCollection<PortChangeEvent> comparePorts(
			Collection<OFPortDesc> newPorts) {
            return compareAndUpdatePorts(newPorts, false);
        }

        /**
         * Compare the current ports of this switch to the newPorts list and
         * return the changes that would be applied to transform the current
         * ports to the new ports. No internal data structures are updated
         * see {@link #compareAndUpdatePorts(List, boolean)}
         *
         * @param newPorts the list of new ports
         * @return The list of differences between the current ports and
         * newPortList
         */
        public OrderedCollection<PortChangeEvent> updatePorts(
			Collection<OFPortDesc> newPorts) {
            return compareAndUpdatePorts(newPorts, true);
        }

        /**
         * Compare the current ports stored in this switch instance with the
         * new port list given and return the differences in the form of
         * PortChangeEvents. If the doUpdate flag is true, newPortList will
         * replace the current list of this switch (and update the port maps)
         *
         * Implementation note:
         * Since this method can optionally modify the current ports and
         * since it's not possible to upgrade a read-lock to a write-lock
         * we need to hold the write-lock for the entire operation. If this
         * becomes a problem and if compares() are common we can consider
         * splitting in two methods but this requires lots of code duplication
         *
         * @param newPorts the list of new ports.
         * @param doUpdate If true the newPortList will replace the current
         * port list for this switch. If false this switch will not be changed.
         * @return The list of differences between the current ports and
         * newPorts
         * @throws NullPointerException if newPortsList is null
         * @throws IllegalArgumentException if either port names or port numbers
         * are duplicated in the newPortsList.
         */
        private OrderedCollection<PortChangeEvent> compareAndUpdatePorts(
                Collection<OFPortDesc> newPorts, boolean doUpdate) {
            if (newPorts == null) {
                throw new NullPointerException("newPortsList must not be null");
            }
            lock.writeLock().lock();
            try {
                OrderedCollection<PortChangeEvent> events =
                        new LinkedHashSetWrapper<PortChangeEvent>();

                Map<Integer,OFPortDesc> newPortsByNumber =
                        new HashMap<Integer, OFPortDesc>();
                Map<String,OFPortDesc> newPortsByName =
                        new HashMap<String, OFPortDesc>();
                List<OFPortDesc> newEnabledPortList =
                        new ArrayList<OFPortDesc>();
                List<Integer> newEnabledPortNumbers =
                        new ArrayList<Integer>();
                List<OFPortDesc> newPortsList =
                        new ArrayList<OFPortDesc>(newPorts);

                for (OFPortDesc p: newPortsList) {
                    if (p == null) {
                        throw new NullPointerException("portList must not " +
                                "contain null values");
                    }

                    // Add the port to the new maps and lists and check
                    // that every port is unique
                    OFPortDesc duplicatePort;
                    duplicatePort = newPortsByNumber.put(
				p.getPortNo().getPortNumber(), p);
                    if (duplicatePort != null) {
                        String msg = String.format("Cannot have two ports " +
                                "with the same number: %s <-> %s",
                                p, duplicatePort);
                        throw new IllegalArgumentException(msg);
                    }
                    duplicatePort =
                            newPortsByName.put(p.getName().toLowerCase(), p);
                    if (duplicatePort != null) {
                        String msg = String.format("Cannot have two ports " +
                                "with the same name: %s <-> %s",
                                p.toString().substring(0,80),
                                duplicatePort.toString().substring(0, 80));
                        throw new IllegalArgumentException(msg);
                    }
                    if (isEnabled(p)) {
                        newEnabledPortList.add(p);
                        newEnabledPortNumbers.add(p.getPortNo().getPortNumber());
                    }

                    // get changes
                    events.addAll(getSinglePortChanges(p));
                }
                // find deleted ports
                // We need to do this after looping through all the new ports
                // to we can handle changed name<->number mappings correctly
                // We could pull it into the loop of we address this but
                // it's probably not worth it
                for (OFPortDesc oldPort: this.portList) {
                    if (!newPortsByNumber.containsKey(oldPort.getPortNo().getPortNumber())) {
                        PortChangeEvent ev =
                                new PortChangeEvent(oldPort,
                                                    PortChangeType.DELETE);
                        events.add(ev);
                    }
                }


                if (doUpdate) {
                    portsByName = Collections.unmodifiableMap(newPortsByName);
                    portsByNumber =
                            Collections.unmodifiableMap(newPortsByNumber);
                    enabledPortList =
                            Collections.unmodifiableList(newEnabledPortList);
                    enabledPortNumbers =
                            Collections.unmodifiableList(newEnabledPortNumbers);
                    portList = Collections.unmodifiableList(newPortsList);
                }
                return events;
            } finally {
                lock.writeLock().unlock();
            }
        }

        public OFPortDesc getPort(String name) {
            if (name == null) {
                throw new NullPointerException("Port name must not be null");
            }
            lock.readLock().lock();
            try {
                return portsByName.get(name.toLowerCase());
            } finally {
                lock.readLock().unlock();
            }
        }

        public OFPortDesc getPort(int portNumber) {
            lock.readLock().lock();
            try {
                return portsByNumber.get(portNumber);
            } finally {
                lock.readLock().unlock();
            }
        }

        public List<OFPortDesc> getPorts() {
            lock.readLock().lock();
            try {
                return portList;
            } finally {
                lock.readLock().unlock();
            }
        }

        public List<OFPortDesc> getEnabledPorts() {
            lock.readLock().lock();
            try {
                return enabledPortList;
            } finally {
                lock.readLock().unlock();
            }
        }

        public List<Integer> getEnabledPortNumbers() {
            lock.readLock().lock();
            try {
                return enabledPortNumbers;
            } finally {
                lock.readLock().unlock();
            }
        }
    }


	//*******************************************
    //    Switch stats handling
    //*******************************************

    @Override
    public Future<List<OFStatsReply>> getStatistics(OFStatsRequest<?> request)
		throws IOException {
        OFStatisticsFuture future = new OFStatisticsFuture(threadPool, this,
			(int)request.getXid());
        log.info("description STAT REQUEST XID {}", request.getXid());
        this.statsFutureMap.put((int)request.getXid(), future);

        this.channel.write(Collections.singletonList(request));
        return future;
    }

    @Override
    public void deliverStatisticsReply(OFMessage reply) {
        OFStatisticsFuture future = this.statsFutureMap.get((int)reply.getXid());
        if (future != null) {
            future.deliverFuture(this, reply);
            // The future will ultimately unregister itself and call
            // cancelStatisticsReply
            return;
        }
        // Transaction id was not found in statsFutureMap.check the other map
        IOFMessageListener caller = this.iofMsgListenersMap.get(reply.getXid());
        if (caller != null) {
		caller.receive(this, reply, null);
        }
    }

    @Override
    public void cancelStatisticsReply(int transactionId) {
        if (null == this.statsFutureMap.remove(transactionId)) {
            this.iofMsgListenersMap.remove(transactionId);
        }
    }

    @Override
    public void cancelAllStatisticsReplies() {
        /* we don't need to be synchronized here. Even if another thread
         * modifies the map while we're cleaning up the future will eventuall
         * timeout */
        for (OFStatisticsFuture f : statsFutureMap.values()) {
            f.cancel(true);
        }
        statsFutureMap.clear();
        iofMsgListenersMap.clear();
    }


    //*******************************************
    //    Switch role handling
    //*******************************************

    // XXX S this is completely wrong. The generation id should be obtained
    // after coordinating with all controllers connected to this switch.
    // ie. should be part of registry service (account for 1.3 vs 1.0)
    // For now we are just generating this locally and keeping it constant.
    public U64 getNextGenerationId() {
        //TODO: Pankaj, fix nextGenerationId as part of Registry interface
	return U64.of(generationIdSource);
    }

    @Override
    public Role getRole() {
        return role;
    }

    @JsonIgnore
    @Override
    public void setRole(Role role) {
        this.role = role;
    }


    //*******************************************
    //    Switch utility methods
    //*******************************************

    private void registerOverloadCounters() throws CounterException {
        if (debugCountersRegistered) {
            return;
        }
        if (debugCounters == null) {
            log.error("Debug Counter Service not found");
            debugCounters = new NullDebugCounter();
            debugCountersRegistered = true;
        }
        // every level of the hierarchical counter has to be registered
        // even if they are not used
        ctrSwitch = debugCounters.registerCounter(
                                   BASE , stringId,
                                   "Counter for this switch",
                                   CounterType.ALWAYS_COUNT);
        ctrSwitchPktin = debugCounters.registerCounter(
                                   BASE, stringId + "/pktin",
                                   "Packet in counter for this switch",
                                   CounterType.ALWAYS_COUNT);
        ctrSwitchWrite = debugCounters.registerCounter(
                                   BASE, stringId + "/write",
                                   "Write counter for this switch",
                                   CounterType.ALWAYS_COUNT);
        ctrSwitchPktinDrops = debugCounters.registerCounter(
                                   BASE, stringId + "/pktin/drops",
                                   "Packet in throttle drop count",
                                   CounterType.ALWAYS_COUNT,
                                   IDebugCounterService.CTR_MDATA_WARN);
        ctrSwitchWriteDrops = debugCounters.registerCounter(
                                   BASE, stringId + "/write/drops",
                                   "Switch write throttle drop count",
                                   CounterType.ALWAYS_COUNT,
                                   IDebugCounterService.CTR_MDATA_WARN);
    }

    @Override
    public void startDriverHandshake() throws IOException {
	log.debug("Starting driver handshake for sw {}", getStringId());
        if (startDriverHandshakeCalled)
            throw new SwitchDriverSubHandshakeAlreadyStarted();
        startDriverHandshakeCalled = true;
    }

    @Override
    public boolean isDriverHandshakeComplete() {
        if (!startDriverHandshakeCalled)
            throw new SwitchDriverSubHandshakeNotStarted();
        return true;
    }

    @Override
    public void processDriverHandshakeMessage(OFMessage m) {
        if (startDriverHandshakeCalled)
            throw new SwitchDriverSubHandshakeCompleted(m);
        else
            throw new SwitchDriverSubHandshakeNotStarted();
    }

    @Override
    @JsonIgnore
    @LogMessageDoc(level="WARN",
        message="Switch {switch} flow table is full",
        explanation="The controller received flow table full " +
                "message from the switch, could be caused by increased " +
                "traffic pattern",
                recommendation=LogMessageDoc.REPORT_CONTROLLER_BUG)
    public void setTableFull(boolean isFull) {
        if (isFull && !flowTableFull) {
            floodlightProvider.addSwitchEvent(this.datapathId.getLong(),
                    "SWITCH_FLOW_TABLE_FULL " +
                    "Table full error from switch", false);
            log.warn("Switch {} flow table is full", stringId);
        }
        flowTableFull  = isFull;
    }

    @Override
    @LogMessageDoc(level = "ERROR",
            message = "Failed to clear all flows on switch {switch}",
            explanation = "An I/O error occured while trying to clear " +
                    "flows on the switch.",
            recommendation = LogMessageDoc.CHECK_SWITCH)
    public void clearAllFlowMods() {
        // Delete all pre-existing flows

        // by default if match is not specified, then an empty list of matches
        // is sent, resulting in a wildcard-all flows
        // XXX fix this later to be sure it works for both 1.0 and 1.3
        OFMessage fm = getFactory()
						.buildFlowDelete()
						.setOutPort(OFPort.ANY)
						.setOutGroup(OFGroup.ANY)
						.setTableId(TableId.ALL)
						.build();

        try {
            channel.write(Collections.singletonList(fm));
        } catch (Exception e) {
            log.error("Failed to clear all flows on switch " + this, e);
        }
    }

    @Override
    public void flush() {
        Map<OFSwitchImplBase, List<OFMessage>> msg_buffer_map = local_msg_buffer.get();
        List<OFMessage> msglist = msg_buffer_map.get(this);
        if ((msglist != null) && (msglist.size() > 0)) {
            try {
                this.write(msglist);
            } catch (IOException e) {
		log.error("Failed flushing messages", e);
            }
            msglist.clear();
        }
    }

    public static void flush_all() {
        Map<OFSwitchImplBase, List<OFMessage>> msg_buffer_map = local_msg_buffer.get();
        for (OFSwitchImplBase sw : msg_buffer_map.keySet()) {
            sw.flush();
        }
    }

    /**
     * Return a read lock that must be held while calling the listeners for
     * messages from the switch. Holding the read lock prevents the active
     * switch list from being modified out from under the listeners.
     *
     * @return listener read lock
     */
    @JsonIgnore
    public Lock getListenerReadLock() {
        return listenerLock.readLock();
    }

    /**
     * Return a write lock that must be held when the controllers modifies the
     * list of active switches. This is to ensure that the active switch list
     * doesn't change out from under the listeners as they are handling a
     * message from the switch.
     *
     * @return listener write lock
     */
    @JsonIgnore
    public Lock getListenerWriteLock() {
        return listenerLock.writeLock();
    }
}
