| /* |
| * 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; |
| } |
| } |