blob: a0cacc8563932674d9465ec6188363cc4e4149b6 [file] [log] [blame]
/*
* Copyright 2016 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.provider.of.message.impl;
import com.codahale.metrics.Meter;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.onlab.metrics.MetricsComponent;
import org.onlab.metrics.MetricsFeature;
import org.onlab.metrics.MetricsService;
import org.onosproject.cpman.ControlMessage;
import org.onosproject.cpman.DefaultControlMessage;
import org.onosproject.cpman.message.ControlMessageProviderService;
import org.onosproject.net.DeviceId;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFType;
import org.slf4j.Logger;
import java.util.Map;
import java.util.Set;
import static org.onosproject.provider.of.message.impl.OpenFlowControlMessageMapper.lookupControlMessageType;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Collects the OpenFlow messages and aggregates using MetricsService.
*/
public class OpenFlowControlMessageAggregator implements Runnable {
private final Logger log = getLogger(getClass());
private static final Set<OFType> OF_TYPE_SET =
ImmutableSet.of(OFType.PACKET_IN, OFType.PACKET_OUT, OFType.FLOW_MOD,
OFType.FLOW_REMOVED, OFType.STATS_REQUEST, OFType.STATS_REPLY);
private final Map<OFType, Meter> rateMeterMap = Maps.newHashMap();
private final Map<OFType, Meter> countMeterMap = Maps.newHashMap();
private final DeviceId deviceId;
private final ControlMessageProviderService providerService;
private static final String RATE_NAME = "rate";
private static final String COUNT_NAME = "count";
private Set<ControlMessage> controlMessages = Sets.newConcurrentHashSet();
// TODO: this needs to be configurable
private static final int EXECUTE_PERIOD_IN_SECOND = 60;
/**
* Generates an OpenFlow message aggregator instance.
* The instance is for aggregating a specific OpenFlow message
* type of an OpenFlow switch.
*
* @param metricsService metrics service reference object
* @param providerService control message provider service reference object
* @param deviceId device identification
*/
public OpenFlowControlMessageAggregator(MetricsService metricsService,
ControlMessageProviderService providerService,
DeviceId deviceId) {
MetricsComponent mc = metricsService.registerComponent(deviceId.toString());
OF_TYPE_SET.forEach(type -> {
MetricsFeature metricsFeature = mc.registerFeature(type.toString());
Meter rateMeter = metricsService.createMeter(mc, metricsFeature, RATE_NAME);
Meter countMeter = metricsService.createMeter(mc, metricsFeature, COUNT_NAME);
rateMeterMap.put(type, rateMeter);
countMeterMap.put(type, countMeter);
});
this.deviceId = deviceId;
this.providerService = providerService;
}
/**
* Increments the meter rate by n, and the meter count by 1.
*
* @param msg OpenFlow message
*/
public void increment(OFMessage msg) {
rateMeterMap.get(msg.getType()).mark(msg.toString().length());
countMeterMap.get(msg.getType()).mark(1);
}
@Override
public void run() {
// update 1 minute statistic information of all control messages
OF_TYPE_SET.forEach(type -> controlMessages.add(
new DefaultControlMessage(lookupControlMessageType(type),
deviceId, getLoad(type), getRate(type), getCount(type),
System.currentTimeMillis())));
log.debug("sent aggregated control message");
providerService.updateStatsInfo(deviceId, ImmutableSet.copyOf(controlMessages));
controlMessages.clear();
}
/**
* Returns the average load value.
*
* @param type OpenFlow message type
* @return load value
*/
private long getLoad(OFType type) {
if (countMeterMap.get(type).getOneMinuteRate() == 0D) {
return 0L;
}
return (long) (rateMeterMap.get(type).getOneMinuteRate() /
countMeterMap.get(type).getOneMinuteRate());
}
/**
* Returns the average meter rate within recent 1 minute.
*
* @param type OpenFlow message type
* @return rate value
*/
private long getRate(OFType type) {
return (long) rateMeterMap.get(type).getOneMinuteRate();
}
/**
* Returns the average meter count within recent 1 minute.
*
* @param type OpenFlow message type
* @return count value
*/
private long getCount(OFType type) {
return (long) (countMeterMap.get(type).getOneMinuteRate()
* EXECUTE_PERIOD_IN_SECOND);
}
}