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.net.SocketAddress;
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 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.OFFlowDelete.Builder;
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;
    // XXX Consider removing the following 2 maps - not used anymore
    protected Map<Integer, IOFMessageListener> iofMsgListenersMap;
    protected Map<Integer, OFFeaturesReplyFuture> featuresFutureMap;
    protected boolean connected;
    protected Role role;
    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.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 SocketAddress getChannelSocketAddress(){
        return channel.getRemoteAddress();
    }

    @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);
    }

    protected 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
        Builder builder = getFactory()
                .buildFlowDelete()
                .setOutPort(OFPort.ANY);

        if (ofversion.wireVersion >= OFVersion.OF_13.wireVersion) {
            builder.setOutGroup(OFGroup.ANY)
                   .setTableId(TableId.ALL);
        }

        OFMessage fm = builder.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();
    }

    public String getSwitchDriverState() {
        return "";
    }

}
