return; // only react to switch connections when master
// FIXME: should we disconnect the switch? When can this happen?
}
Long dpid = sw.getId();
counters.switchActivated.updateCounterWithFlush();
IOFSwitch oldSw = this.activeSwitches.put(dpid, sw);
// Update event history
evSwitch.updateEventWithFlush(new SwitchEvent(dpid, "connected"));
if (oldSw == sw) {
// Note == for object equality, not .equals for value
// TODO: should we wipe the flow table if
// alwaysClearFlowsOnSwAdd is set? OTOH this case should
// really never happen.
counters.errorSameSwitchReactivated.updateCounterWithFlush();
log.error("Switch {} activated but was already active", sw);
addSwitchToStore(sw);
return;
}
if (oldSw != null) {
// This happens either when we have switches with duplicate
// DPIDs or when a switch reconnects before we saw the
// disconnect
counters.switchWithSameDpidActivated.updateCounterWithFlush();
log.warn("New switch added {} for already-added switch {}",
sw, oldSw);
// We need to disconnect and remove the old switch
// TODO: we notify switch listeners that the switch has been
// removed and then we notify them that the new one has been
// added. One could argue that a switchChanged notification
// might be more appropriate in this case....
oldSw.cancelAllStatisticsReplies();
addUpdateToQueue(new SwitchUpdate(dpid,
SwitchUpdateType.REMOVED));
oldSw.disconnectOutputStream();
// Add the new switch and clear FlowMods
// TODO: if this is the same switch re-connecting rather than
// a DPID collision it would make sense to not wipe the flow
// table.
sw.clearAllFlowMods();
addUpdateToQueue(new SwitchUpdate(dpid,
SwitchUpdateType.ADDED));
addUpdateToQueue(new SwitchUpdate(dpid,
SwitchUpdateType.ACTIVATED));
addSwitchToStore(sw);
return;
}
IOFSwitch storedSwitch = this.syncedSwitches.remove(sw.getId());
if (storedSwitch == null) {
// The switch isn't known to the controller cluster. We
// need to send a switchAdded notification and clear all
// flows.
if (!swConnectCache.update(sw.getId()))
sw.clearAllFlowMods();
addUpdateToQueue(new SwitchUpdate(dpid,
SwitchUpdateType.ADDED));
addUpdateToQueue(new SwitchUpdate(dpid,
SwitchUpdateType.ACTIVATED));
counters.newSwitchActivated.updateCounterWithFlush();
} else {
// FIXME: switch was in store. check if ports or anything else
// has changed and send update.
if (alwaysClearFlowsOnSwActivate) {
sw.clearAllFlowMods();
}
if (sw.attributeEquals(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, true)) {
// We have a stored switch and the newly activated switch
// supports roles. This indicates that the switch was
// previously connected as slave. Since we don't update
// ports while slave, we need to set the ports on the
// new switch from the ports on the stored switch
// No need to send notifications, since we've dispatched
// them as we receive them from the store
sw.setPorts(storedSwitch.getPorts());
}
addUpdateToQueue(new SwitchUpdate(dpid,
SwitchUpdateType.ACTIVATED));
sendNotificationsIfSwitchDiffers(storedSwitch, sw);
counters.syncedSwitchActivated.updateCounterWithFlush();