/* * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import javax.annotation.Nullable; import org.apache.commons.lang3.tuple.Pair; import org.opendaylight.groupbasedpolicy.api.StatisticsManager; import org.opendaylight.groupbasedpolicy.dto.ConsEpgKey; import org.opendaylight.groupbasedpolicy.dto.EpgKeyDto; import org.opendaylight.groupbasedpolicy.dto.ProvEpgKey; import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.flowcache.FlowCache; import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.flowcache.FlowCacheFactory; import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.util.FlowCacheCons; import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.statistics.util.IidSflowNameUtil; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.classifiers.Classifier; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.ResolvedPolicy; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.ResolvedPolicyKey; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Preconditions; import com.google.common.collect.HashMultimap; import com.google.common.collect.SetMultimap; public class OFStatisticsManager implements AutoCloseable { // key is String (not a full IpAddress) because // we will get String from REST query to sFlow private static ConcurrentMap<String, EndpointL3> endpointL3ByIpMap = new ConcurrentHashMap<>(); private static final int CONNECT_TIMEOUT_MILLISEC = 20000; private static final int READ_TIMEOUT_MILLISEC = 30000; private static final Logger LOG = LoggerFactory.getLogger(OFStatisticsManager.class); private final ScheduledExecutorService executor; private final StatisticsManager statisticsManager; private final Set<String> flowCacheNames = new HashSet<>(); private static final SetMultimap<ContractId, Pair<ConsEpgKey, ProvEpgKey>> epgsByContractId = HashMultimap.create(); private List<ScheduledFuture<?>> collectStatsTasks = new ArrayList<>(); private static int MAX_FLOWS = 100; private static double MIN_VALUE_IN_FLOW = 0.1; private static final String AGG_MODE = "sum"; private Long delay; private String sflowCollectorUri; public OFStatisticsManager(ScheduledExecutorService executor, StatisticsManager statisticsManager) { this.executor = executor; this.statisticsManager = statisticsManager; } public synchronized void pullStatsForClassifier(InstanceIdentifier<Classifier> classifierIid, Classifier classifier) { Preconditions.checkNotNull(sflowCollectorUri); Preconditions.checkNotNull(delay); FlowCache flowCache = FlowCacheFactory.createFlowCache(classifierIid, classifier, FlowCacheCons.Value.BYTES); setStatsPulling(flowCache, classifierIid); flowCache = FlowCacheFactory.createFlowCache(classifierIid, classifier, FlowCacheCons.Value.FRAMES); setStatsPulling(flowCache, classifierIid); } private void setStatsPulling(FlowCache flowCache, InstanceIdentifier<Classifier> classifierIid) { if (flowCache == null) { LOG.trace("Flow cache is null for classifier {}", classifierIid); return; } ResolvedPolicyKey resolvedPolicyKey = classifierIid.firstKeyOf(ResolvedPolicy.class); ConsEpgKey consEpgKey = new EpgKeyDto(resolvedPolicyKey.getConsumerEpgId(), resolvedPolicyKey.getConsumerTenantId()); ProvEpgKey provEpgKey = new EpgKeyDto(resolvedPolicyKey.getProviderEpgId(), resolvedPolicyKey.getProviderTenantId()); String flowCacheName = flowCache.getName(); ContractId contractId = IidSflowNameUtil.resolveContractIdFromFlowCacheName(flowCacheName); epgsByContractId.put(contractId, Pair.of(consEpgKey, provEpgKey)); boolean isFlowCacheNew = flowCacheNames.add(flowCacheName); if (isFlowCacheNew) { SFlowRTConnection sFlowRTConnection = new SFlowRTConnection(executor, sflowCollectorUri, flowCache, new JsonRestClient(sflowCollectorUri, CONNECT_TIMEOUT_MILLISEC, READ_TIMEOUT_MILLISEC)); ScheduledFuture<?> collectStatsTask = this.executor.scheduleWithFixedDelay(new ReadGbpFlowCacheTask(flowCacheName, sFlowRTConnection, statisticsManager, MAX_FLOWS, MIN_VALUE_IN_FLOW, AGG_MODE), 0, delay, TimeUnit.SECONDS); collectStatsTasks.add(collectStatsTask); } } public synchronized static Set<Pair<ConsEpgKey, ProvEpgKey>> getEpgsForContract(ContractId contractId) { return epgsByContractId.get(contractId); } public synchronized void setSflowCollectorUri(String sflowCollectorUri) { this.sflowCollectorUri = sflowCollectorUri; } public synchronized void setDelay(Long delay) { this.delay = delay; } public static EndpointL3 getEndpointL3ForIp(@Nullable String ipAddress) { if (ipAddress == null) { return null; } return endpointL3ByIpMap.get(ipAddress); } public static void addL3Endpoint(EndpointL3 endpointL3) { endpointL3ByIpMap.put(getStringIpAddress(endpointL3.getIpAddress()), endpointL3); } public static void removeL3Endpoint(EndpointL3 endpointL3) { endpointL3ByIpMap.remove(getStringIpAddress(endpointL3.getIpAddress())); } private static String getStringIpAddress(IpAddress ipAddress) { if (ipAddress.getIpv4Address() != null) { return ipAddress.getIpv4Address().getValue(); } return ipAddress.getIpv6Address().getValue(); } @Override public synchronized void close() throws Exception { Iterator<ScheduledFuture<?>> tasksIterator = collectStatsTasks.iterator(); while (tasksIterator.hasNext()) { ScheduledFuture<?> scheduledFuture = tasksIterator.next(); scheduledFuture.cancel(false); tasksIterator.remove(); } epgsByContractId.clear(); } }