blob: dfedaf3cebb02286d0fb304ab1d27cb0bb2e880c [file] [log] [blame]
/*
* Copyright 2017-present Open Networking Laboratory
*
* 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.
*
*/
package org.onosproject.ui.impl;
import org.onosproject.ui.impl.topo.util.ServicesBundle;
import org.onosproject.ui.topo.AbstractTopoMonitor;
import org.onosproject.ui.topo.TopoUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Timer;
import java.util.TimerTask;
import static org.onosproject.ui.impl.TrafficMonitorBase.Mode.IDLE;
/**
* Base superclass for traffic monitor (both 'classic' and 'topo2' versions).
*/
public abstract class TrafficMonitorBase extends AbstractTopoMonitor {
private final Logger log = LoggerFactory.getLogger(getClass());
// 4 Kilo Bytes as threshold
static final double BPS_THRESHOLD = 4 * TopoUtils.N_KILO;
/**
* Designates the different modes of operation.
*/
public enum Mode {
IDLE,
ALL_FLOW_TRAFFIC_BYTES,
ALL_PORT_TRAFFIC_BIT_PS,
ALL_PORT_TRAFFIC_PKT_PS,
DEV_LINK_FLOWS,
RELATED_INTENTS,
SELECTED_INTENT
}
/**
* Number of milliseconds between invocations of sending traffic data.
*/
protected final long trafficPeriod;
/**
* Holds references to services.
*/
protected final ServicesBundle services;
/**
* Current operating mode.
*/
protected Mode mode = Mode.IDLE;
private final Timer timer;
private TimerTask trafficTask = null;
/**
* Constructs the monitor, initializing the task period and
* services bundle reference.
*
* @param trafficPeriod traffic task period in ms
* @param servicesBundle bundle of services
*/
protected TrafficMonitorBase(long trafficPeriod,
ServicesBundle servicesBundle) {
this.trafficPeriod = trafficPeriod;
this.services = servicesBundle;
timer = new Timer("uiTopo-" + getClass().getSimpleName());
}
/**
* Initiates monitoring of traffic for a given mode.
* This causes a background traffic task to be
* scheduled to repeatedly compute and transmit the appropriate traffic
* data to the client.
* <p>
* The monitoring mode is expected to be one of:
* <ul>
* <li>ALL_FLOW_TRAFFIC_BYTES</li>
* <li>ALL_PORT_TRAFFIC_BIT_PS</li>
* <li>ALL_PORT_TRAFFIC_PKT_PS</li>
* <li>SELECTED_INTENT</li>
* </ul>
*
* @param mode the monitoring mode
*/
public synchronized void monitor(Mode mode) {
this.mode = mode;
switch (mode) {
case ALL_FLOW_TRAFFIC_BYTES:
clearSelection();
scheduleTask();
sendAllFlowTraffic();
break;
case ALL_PORT_TRAFFIC_BIT_PS:
clearSelection();
scheduleTask();
sendAllPortTrafficBits();
break;
case ALL_PORT_TRAFFIC_PKT_PS:
clearSelection();
scheduleTask();
sendAllPortTrafficPackets();
break;
case SELECTED_INTENT:
sendSelectedIntentTraffic();
scheduleTask();
break;
default:
log.warn("Unexpected call to monitor({})", mode);
clearAll();
break;
}
}
/**
* Subclass should compile and send appropriate highlights data showing
* flow traffic (bytes on links).
*/
protected abstract void sendAllFlowTraffic();
/**
* Subclass should compile and send appropriate highlights data showing
* bits per second, as computed using port stats.
*/
protected abstract void sendAllPortTrafficBits();
/**
* Subclass should compile and send appropriate highlights data showing
* packets per second, as computed using port stats.
*/
protected abstract void sendAllPortTrafficPackets();
/**
* Subclass should compile and send appropriate highlights data showing
* number of flows traversing links for the "selected" device(s).
*/
protected abstract void sendDeviceLinkFlows();
/**
* Subclass should compile and send appropriate highlights data showing
* traffic traversing links for the "selected" intent.
*/
protected abstract void sendSelectedIntentTraffic();
/**
* Subclass should send a "clear highlights" event.
*/
protected abstract void sendClearHighlights();
/**
* Subclasses should clear any selection state.
*/
protected abstract void clearSelection();
/**
* Sets the mode to IDLE, clears the selection, cancels the background
* task, and sends a clear highlights event to the client.
*/
protected void clearAll() {
this.mode = Mode.IDLE;
clearSelection();
cancelTask();
sendClearHighlights();
}
/**
* Schedules the background monitor task to run.
*/
protected synchronized void scheduleTask() {
if (trafficTask == null) {
log.debug("Starting up background traffic task...");
trafficTask = new TrafficUpdateTask();
timer.schedule(trafficTask, trafficPeriod, trafficPeriod);
} else {
log.debug("(traffic task already running)");
}
}
/**
* Cancels the background monitor task.
*/
protected synchronized void cancelTask() {
if (trafficTask != null) {
trafficTask.cancel();
trafficTask = null;
}
}
/**
* Stops monitoring. (Invokes {@link #clearAll}, if not idle).
*/
public synchronized void stopMonitoring() {
log.debug("STOP monitoring");
if (mode != IDLE) {
clearAll();
}
}
// =======================================================================
// === Background Task
// Provides periodic update of traffic information to the client
private class TrafficUpdateTask extends TimerTask {
@Override
public void run() {
try {
switch (mode) {
case ALL_FLOW_TRAFFIC_BYTES:
sendAllFlowTraffic();
break;
case ALL_PORT_TRAFFIC_BIT_PS:
sendAllPortTrafficBits();
break;
case ALL_PORT_TRAFFIC_PKT_PS:
sendAllPortTrafficPackets();
break;
case DEV_LINK_FLOWS:
sendDeviceLinkFlows();
break;
case SELECTED_INTENT:
sendSelectedIntentTraffic();
break;
default:
// RELATED_INTENTS and IDLE modes should never invoke
// the background task, but if they do, they have
// nothing to do
break;
}
} catch (Exception e) {
log.warn("Unable to process traffic task due to {}", e.getMessage());
log.warn("Boom!", e);
}
}
}
}