| /* |
| * Copyright 2015-present Open Networking Foundation |
| * |
| * 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.flow.impl; |
| |
| import com.google.common.collect.Iterables; |
| import org.onlab.osgi.DefaultServiceDirectory; |
| import org.onosproject.net.DeviceId; |
| import org.onosproject.net.driver.DriverService; |
| import org.onosproject.net.flow.FlowEntry; |
| import org.onosproject.net.flow.FlowRuleService; |
| import org.onosproject.net.flow.StoredFlowEntry; |
| import org.onosproject.net.flow.instructions.Instruction; |
| import org.onosproject.net.flow.instructions.Instructions; |
| import org.onosproject.net.statistic.DefaultLoad; |
| import org.onosproject.net.statistic.PollInterval; |
| import org.onosproject.openflow.controller.Dpid; |
| import org.onosproject.openflow.controller.OpenFlowSwitch; |
| import org.onosproject.openflow.controller.RoleState; |
| import org.projectfloodlight.openflow.protocol.OFFlowStatsRequest; |
| import org.projectfloodlight.openflow.protocol.match.Match; |
| import org.projectfloodlight.openflow.types.OFPort; |
| import org.projectfloodlight.openflow.types.TableId; |
| import org.slf4j.Logger; |
| |
| import java.util.Optional; |
| import java.util.concurrent.Executors; |
| import java.util.concurrent.ScheduledExecutorService; |
| import java.util.concurrent.ScheduledFuture; |
| import java.util.concurrent.TimeUnit; |
| |
| import static com.google.common.base.Preconditions.checkNotNull; |
| import static java.lang.Thread.sleep; |
| import static org.onlab.util.Tools.groupedThreads; |
| import static org.slf4j.LoggerFactory.getLogger; |
| |
| /** |
| * Efficiently and adaptively collects flow statistics for the specified switch. |
| */ |
| public class NewAdaptiveFlowStatsCollector implements SwitchDataCollector { |
| private final Logger log = getLogger(getClass()); |
| |
| private static final String CHECK_AND_MOVE_LOG = |
| "checkAndMoveLiveFlowInternal: flowId={}, state={}, afterLiveType={}" |
| + ", liveTime={}, life={}, bytes={}, packets={}, fromLastSeen={}" |
| + ", priority={}, selector={}, treatment={} dpid={}"; |
| |
| private static final String CHECK_AND_MOVE_COUNT_LOG = |
| "checkAndMoveLiveFlowAll: Total Flow_Count={}, " |
| + ", IMMEDIATE_FLOW_Count={}, SHORT_FLOW_Count={}" |
| + ", MID_FLOW_Count={}, LONG_FLOW_Count={}, UNKNOWN_FLOW_Count={}"; |
| |
| private static final int SLEEP_LOOP_COUNT = 10; |
| private static final int SLEEP_MS = 100; |
| |
| private final DriverService driverService; |
| private final OpenFlowSwitch sw; |
| private final DeviceId did; |
| |
| private ScheduledExecutorService adaptiveFlowStatsScheduler = |
| Executors.newScheduledThreadPool(4, groupedThreads("onos/flow", "device-stats-collector-%d", log)); |
| private ScheduledFuture<?> calAndShortFlowsThread; |
| private ScheduledFuture<?> midFlowsThread; |
| private ScheduledFuture<?> longFlowsThread; |
| |
| // Task that calculates all flowEntries' FlowLiveType and collects stats IMMEDIATE flows every calAndPollInterval |
| private CalAndShortFlowsTask calAndShortFlowsTask; |
| // Task that collects stats MID flows every 2*calAndPollInterval |
| private MidFlowsTask midFlowsTask; |
| // Task that collects stats LONG flows every 3*calAndPollInterval |
| private LongFlowsTask longFlowsTask; |
| |
| private static final int CAL_AND_POLL_TIMES = 1; // must be always 0 |
| private static final int MID_POLL_TIMES = 2; // variable greater or equal than 1 |
| private static final int LONG_POLL_TIMES = 3; // variable greater or equal than MID_POLL_TIMES |
| //TODO: make ENTIRE_POLL_TIMES configurable with enable or disable |
| // must be variable greater or equal than common multiple of MID_POLL_TIMES and LONG_POLL_TIMES |
| private static final int ENTIRE_POLL_TIMES = 6; |
| |
| private static final int DEFAULT_CAL_AND_POLL_FREQUENCY = 5; |
| private static final int MIN_CAL_AND_POLL_FREQUENCY = 2; |
| private static final int MAX_CAL_AND_POLL_FREQUENCY = 60; |
| |
| private int calAndPollInterval; // CAL_AND_POLL_TIMES * DEFAULT_CAL_AND_POLL_FREQUENCY; |
| private int midPollInterval; // MID_POLL_TIMES * DEFAULT_CAL_AND_POLL_FREQUENCY; |
| private int longPollInterval; // LONG_POLL_TIMES * DEFAULT_CAL_AND_POLL_FREQUENCY; |
| // only used for checking condition at each task if it collects entire flows from a given switch or not |
| private int entirePollInterval; // ENTIRE_POLL_TIMES * DEFAULT_CAL_AND_POLL_FREQUENCY; |
| |
| // Number of call count of each Task, |
| // for undoing collection except only entire flows collecting task in CalAndShortFlowsTask |
| private int callCountCalAndShortFlowsTask = 0; // increased CAL_AND_POLL_TIMES whenever Task is called |
| private int callCountMidFlowsTask = 0; // increased MID_POLL_TIMES whenever Task is called |
| private int callCountLongFlowsTask = 0; // increased LONG_POLL_TIMES whenever Task is called |
| |
| private boolean isFirstTimeStart = true; |
| |
| public static final long NO_FLOW_MISSING_XID = (-1); |
| private long flowMissingXid = NO_FLOW_MISSING_XID; |
| |
| private FlowRuleService flowRuleService; |
| |
| /** |
| * Creates a new adaptive collector for the given switch and default cal_and_poll frequency. |
| * |
| * @param driverService driver service reference |
| * @param sw switch to pull |
| * @param pollInterval cal and immediate poll frequency in seconds |
| */ |
| NewAdaptiveFlowStatsCollector(DriverService driverService, OpenFlowSwitch sw, int pollInterval) { |
| this.driverService = driverService; |
| this.sw = sw; |
| this.did = DeviceId.deviceId(Dpid.uri(sw.getId())); |
| |
| flowRuleService = get(FlowRuleService.class); |
| |
| initMemberVars(pollInterval); |
| } |
| |
| /** |
| * Returns the reference to the implementation of the specified service. |
| * |
| * @param serviceClass service class |
| * @param <T> type of service |
| * @return service implementation |
| * @throws org.onlab.osgi.ServiceNotFoundException if service is unavailable |
| */ |
| private static <T> T get(Class<T> serviceClass) { |
| return DefaultServiceDirectory.getService(serviceClass); |
| } |
| |
| // check calAndPollInterval validity and set all pollInterval values and finally initialize each task call count |
| private void initMemberVars(int pollInterval) { |
| if (pollInterval < MIN_CAL_AND_POLL_FREQUENCY) { |
| this.calAndPollInterval = MIN_CAL_AND_POLL_FREQUENCY; |
| } else if (pollInterval >= MAX_CAL_AND_POLL_FREQUENCY) { |
| this.calAndPollInterval = MAX_CAL_AND_POLL_FREQUENCY; |
| } else { |
| this.calAndPollInterval = pollInterval; |
| } |
| |
| calAndPollInterval = CAL_AND_POLL_TIMES * calAndPollInterval; |
| midPollInterval = MID_POLL_TIMES * calAndPollInterval; |
| longPollInterval = LONG_POLL_TIMES * calAndPollInterval; |
| entirePollInterval = ENTIRE_POLL_TIMES * calAndPollInterval; |
| |
| // Set the PollInterval values for statistic manager and others usage |
| DefaultLoad.setPollInterval(calAndPollInterval); |
| |
| PollInterval pollInterval1Instance = PollInterval.getInstance(); |
| |
| pollInterval1Instance.setPollInterval(calAndPollInterval); |
| pollInterval1Instance.setMidPollInterval(midPollInterval); |
| pollInterval1Instance.setLongPollInterval(longPollInterval); |
| pollInterval1Instance.setEntirePollInterval(entirePollInterval); |
| |
| callCountCalAndShortFlowsTask = 0; |
| callCountMidFlowsTask = 0; |
| callCountLongFlowsTask = 0; |
| |
| flowMissingXid = NO_FLOW_MISSING_XID; |
| } |
| |
| /** |
| * Adjusts adaptive poll frequency. |
| * |
| * @param pollInterval poll frequency in seconds |
| */ |
| synchronized void adjustCalAndPollInterval(int pollInterval) { |
| initMemberVars(pollInterval); |
| |
| if (calAndShortFlowsThread != null) { |
| calAndShortFlowsThread.cancel(false); |
| } |
| if (midFlowsThread != null) { |
| midFlowsThread.cancel(false); |
| } |
| if (longFlowsThread != null) { |
| longFlowsThread.cancel(false); |
| } |
| |
| calAndShortFlowsTask = new CalAndShortFlowsTask(); |
| calAndShortFlowsThread = adaptiveFlowStatsScheduler.scheduleWithFixedDelay( |
| calAndShortFlowsTask, |
| 0, |
| calAndPollInterval, |
| TimeUnit.SECONDS); |
| |
| midFlowsTask = new MidFlowsTask(); |
| midFlowsThread = adaptiveFlowStatsScheduler.scheduleWithFixedDelay( |
| midFlowsTask, |
| 0, |
| midPollInterval, |
| TimeUnit.SECONDS); |
| |
| longFlowsTask = new LongFlowsTask(); |
| longFlowsThread = adaptiveFlowStatsScheduler.scheduleWithFixedDelay( |
| longFlowsTask, |
| 0, |
| longPollInterval, |
| TimeUnit.SECONDS); |
| |
| log.debug("calAndPollInterval={} is adjusted", calAndPollInterval); |
| } |
| |
| private class CalAndShortFlowsTask implements Runnable { |
| @Override |
| public void run() { |
| if (sw.getRole() == RoleState.MASTER) { |
| log.trace("CalAndShortFlowsTask Collecting AdaptiveStats for {}", sw.getStringId()); |
| |
| if (isFirstTimeStart) { |
| // isFirstTimeStart, get entire flow stats from a given switch sw |
| log.trace("CalAndShortFlowsTask Collecting Entire AdaptiveStats at first time start for {}", |
| sw.getStringId()); |
| ofFlowStatsRequestAllSend(); |
| |
| callCountCalAndShortFlowsTask += CAL_AND_POLL_TIMES; |
| isFirstTimeStart = false; |
| } else if (callCountCalAndShortFlowsTask >= ENTIRE_POLL_TIMES) { |
| // entire_poll_times, get entire flow stats from a given switch sw |
| log.trace("CalAndShortFlowsTask Collecting Entire AdaptiveStats for {}", sw.getStringId()); |
| ofFlowStatsRequestAllSend(); |
| |
| callCountCalAndShortFlowsTask = CAL_AND_POLL_TIMES; |
| //TODO: check flows deleted in switch, but exist in controller flow table, then remove them |
| // |
| } else { |
| calAndShortFlowsTaskInternal(); |
| callCountCalAndShortFlowsTask += CAL_AND_POLL_TIMES; |
| } |
| } |
| } |
| } |
| |
| // send openflow flow stats request message with getting all flow entries to a given switch sw |
| private synchronized void ofFlowStatsRequestAllSend() { |
| OFFlowStatsRequest request = sw.factory().buildFlowStatsRequest() |
| .setMatch(sw.factory().matchWildcardAll()) |
| .setTableId(TableId.ALL) |
| .setOutPort(OFPort.NO_MASK) |
| .build(); |
| |
| // set the request xid to check the reply in OpenFlowRuleProvider |
| // After processing the reply of this request message, |
| // this must be set to NO_FLOW_MISSING_XID(-1) by provider |
| setFlowMissingXid(request.getXid()); |
| log.debug("ofFlowStatsRequestAllSend: request={}, dpid={}", |
| request.toString(), sw.getStringId()); |
| |
| sw.sendMsg(request); |
| } |
| |
| // send openflow flow stats request message with getting the specific flow entry(fe) to a given switch sw |
| private void ofFlowStatsRequestFlowSend(FlowEntry fe) { |
| // set find match |
| Match match = FlowModBuilder.builder(fe, sw.factory(), Optional.empty(), |
| Optional.of(driverService)).buildMatch(); |
| // set find tableId |
| TableId tableId = TableId.of(fe.tableId()); |
| // set output port |
| Instruction ins = fe.treatment().allInstructions().stream() |
| .filter(i -> (i.type() == Instruction.Type.OUTPUT)) |
| .findFirst() |
| .orElse(null); |
| OFPort ofPort = OFPort.NO_MASK; |
| if (ins != null) { |
| Instructions.OutputInstruction out = (Instructions.OutputInstruction) ins; |
| ofPort = OFPort.of((int) ((out.port().toLong()))); |
| } |
| |
| OFFlowStatsRequest request = sw.factory().buildFlowStatsRequest() |
| .setMatch(match) |
| .setTableId(tableId) |
| .setOutPort(ofPort) |
| .build(); |
| |
| // Wait for 1 second until the FlowRuleProvider finishes to process FlowStatReply message |
| int loop = 0; |
| boolean interrupted = false; |
| while (!interrupted && getFlowMissingXid() != NO_FLOW_MISSING_XID) { |
| if (loop++ < SLEEP_LOOP_COUNT) { |
| log.debug("ofFlowStatsRequestFlowSend: previous FlowStatsRequestAll (xid={})" + |
| " does not be processed yet, do sleep for {} ms, for {}", |
| getFlowMissingXid(), |
| SLEEP_MS, |
| sw.getStringId()); |
| try { |
| sleep(SLEEP_MS); |
| } catch (InterruptedException ie) { |
| log.debug("ofFlowStatsRequestFlowSend: Interrupted Exception = {}, for {}", |
| ie.toString(), |
| sw.getStringId()); |
| // for exiting while loop gracefully |
| interrupted = true; |
| Thread.currentThread().interrupt(); |
| } |
| } else { |
| log.debug("ofFlowStatsRequestFlowSend: previous FlowStatsRequestAll (xid={})" + |
| " does not be processed yet, for {} ms," + |
| " just set xid with NO_FLOW_MISSING_XID, for {}", |
| getFlowMissingXid(), |
| loop * SLEEP_MS, |
| sw.getStringId()); |
| |
| setFlowMissingXid(NO_FLOW_MISSING_XID); |
| break; |
| } |
| } |
| |
| sw.sendMsg(request); |
| |
| } |
| |
| private void calAndShortFlowsTaskInternal() { |
| checkAndMoveLiveFlowAll(); |
| |
| ofFlowStatsRequestInternal(FlowEntry.FlowLiveType.SHORT); |
| } |
| |
| private void ofFlowStatsRequestInternal(FlowEntry.FlowLiveType liveType) { |
| |
| Iterable<FlowEntry> flowEntries = |
| flowRuleService.getFlowEntriesByLiveType(did, liveType); |
| |
| flowEntries.forEach(fe -> { |
| ofFlowStatsRequestFlowSend(fe); |
| }); |
| } |
| |
| private class MidFlowsTask implements Runnable { |
| @Override |
| public void run() { |
| if (sw.getRole() == RoleState.MASTER) { |
| log.trace("MidFlowsTask Collecting AdaptiveStats for {}", sw.getStringId()); |
| |
| // skip collecting because CalAndShortFlowsTask collects entire flow stats from a given switch sw |
| if (callCountMidFlowsTask >= ENTIRE_POLL_TIMES) { |
| callCountMidFlowsTask = MID_POLL_TIMES; |
| } else { |
| midFlowsTaskInternal(); |
| callCountMidFlowsTask += MID_POLL_TIMES; |
| } |
| } |
| } |
| } |
| |
| private void midFlowsTaskInternal() { |
| ofFlowStatsRequestInternal(FlowEntry.FlowLiveType.MID); |
| } |
| |
| private class LongFlowsTask implements Runnable { |
| @Override |
| public void run() { |
| if (sw.getRole() == RoleState.MASTER) { |
| log.trace("LongFlowsTask Collecting AdaptiveStats for {}", sw.getStringId()); |
| |
| // skip collecting because CalAndShortFlowsTask collects entire flow stats from a given switch sw |
| if (callCountLongFlowsTask >= ENTIRE_POLL_TIMES) { |
| callCountLongFlowsTask = LONG_POLL_TIMES; |
| } else { |
| longFlowsTaskInternal(); |
| callCountLongFlowsTask += LONG_POLL_TIMES; |
| } |
| } |
| } |
| } |
| |
| private void longFlowsTaskInternal() { |
| ofFlowStatsRequestInternal(FlowEntry.FlowLiveType.LONG); |
| } |
| |
| /** |
| * Starts adaptive flow statistic collection. |
| */ |
| public synchronized void start() { |
| log.debug("Starting AdaptiveStats collection thread for {}", sw.getStringId()); |
| callCountCalAndShortFlowsTask = 0; |
| callCountMidFlowsTask = 0; |
| callCountLongFlowsTask = 0; |
| |
| isFirstTimeStart = true; |
| |
| // Initially start polling quickly. Then drop down to configured value |
| calAndShortFlowsTask = new CalAndShortFlowsTask(); |
| calAndShortFlowsThread = adaptiveFlowStatsScheduler.scheduleWithFixedDelay( |
| calAndShortFlowsTask, |
| 1, |
| calAndPollInterval, |
| TimeUnit.SECONDS); |
| |
| midFlowsTask = new MidFlowsTask(); |
| midFlowsThread = adaptiveFlowStatsScheduler.scheduleWithFixedDelay( |
| midFlowsTask, |
| 1, |
| midPollInterval, |
| TimeUnit.SECONDS); |
| |
| longFlowsTask = new LongFlowsTask(); |
| longFlowsThread = adaptiveFlowStatsScheduler.scheduleWithFixedDelay( |
| longFlowsTask, |
| 1, |
| longPollInterval, |
| TimeUnit.SECONDS); |
| |
| log.info("Started"); |
| } |
| |
| /** |
| * Stops adaptive flow statistic collection. |
| */ |
| public synchronized void stop() { |
| log.debug("Stopping AdaptiveStats collection thread for {}", sw.getStringId()); |
| if (calAndShortFlowsThread != null) { |
| calAndShortFlowsThread.cancel(true); |
| } |
| if (midFlowsThread != null) { |
| midFlowsThread.cancel(true); |
| } |
| if (longFlowsThread != null) { |
| longFlowsThread.cancel(true); |
| } |
| |
| adaptiveFlowStatsScheduler.shutdownNow(); |
| |
| isFirstTimeStart = false; |
| |
| log.info("Stopped"); |
| } |
| |
| /** |
| * Returns flowMissingXid that indicates the execution of flowMissing process or not(NO_FLOW_MISSING_XID(-1)). |
| * |
| * @return xid of missing flow |
| */ |
| public long getFlowMissingXid() { |
| return flowMissingXid; |
| } |
| |
| /** |
| * Sets flowMissingXid, namely OFFlowStatsRequest match any ALL message Id. |
| * |
| * @param flowMissingXid the OFFlowStatsRequest message Id |
| */ |
| public void setFlowMissingXid(long flowMissingXid) { |
| this.flowMissingXid = flowMissingXid; |
| } |
| |
| /** |
| * Calculates the flow live type. |
| * |
| * @param life the flow life time in seconds |
| * @return computed flow live type |
| */ |
| public FlowEntry.FlowLiveType calFlowLiveType(long life) { |
| if (life < 0) { |
| return FlowEntry.FlowLiveType.UNKNOWN; |
| } else if (life < calAndPollInterval) { |
| return FlowEntry.FlowLiveType.IMMEDIATE; |
| } else if (life < midPollInterval) { |
| return FlowEntry.FlowLiveType.SHORT; |
| } else if (life < longPollInterval) { |
| return FlowEntry.FlowLiveType.MID; |
| } else { // >= longPollInterval |
| return FlowEntry.FlowLiveType.LONG; |
| } |
| } |
| |
| /** |
| * Calculates and set the flow live type. |
| * It maybe called pushFlowMetrics of FlowRuleService for the ReplyFlowStat message |
| * at the first time and every entire polling time. |
| * |
| * @param fe the flow entry rule |
| * @return computed flow live type |
| */ |
| public FlowEntry.FlowLiveType calAndSetFlowLiveType(StoredFlowEntry fe) { |
| checkNotNull(fe); |
| |
| long life = fe.life(); |
| |
| if (life < 0) { |
| fe.setLiveType(FlowEntry.FlowLiveType.UNKNOWN); |
| } else if (life < calAndPollInterval) { |
| fe.setLiveType(FlowEntry.FlowLiveType.IMMEDIATE); |
| } else if (life < midPollInterval) { |
| fe.setLiveType(FlowEntry.FlowLiveType.SHORT); |
| } else if (life < longPollInterval) { |
| fe.setLiveType(FlowEntry.FlowLiveType.MID); |
| } else { // >= longPollInterval |
| fe.setLiveType(FlowEntry.FlowLiveType.LONG); |
| } |
| |
| return fe.liveType(); |
| } |
| |
| /** |
| * Check and move live type for all type flow entries in table at every calAndPollInterval time. |
| * |
| */ |
| private void checkAndMoveLiveFlowAll() { |
| |
| Iterable<FlowEntry> flowEntries = flowRuleService.getFlowEntries(did); |
| |
| flowEntries.forEach(fe -> { |
| checkAndMoveLiveFlowInternal((StoredFlowEntry) fe); |
| }); |
| |
| // print table counts for debug |
| if (log.isDebugEnabled()) { |
| Iterable<FlowEntry> fes; |
| synchronized (this) { |
| long totalFlowCount = flowRuleService.getFlowRuleCount(); |
| fes = flowRuleService.getFlowEntriesByLiveType( |
| did, FlowEntry.FlowLiveType.IMMEDIATE); |
| long immediateFlowCount = Iterables.size(fes); |
| fes = flowRuleService.getFlowEntriesByLiveType( |
| did, FlowEntry.FlowLiveType.SHORT); |
| long shortFlowCount = Iterables.size(fes); |
| fes = flowRuleService.getFlowEntriesByLiveType( |
| did, FlowEntry.FlowLiveType.MID); |
| long midFlowCount = Iterables.size(fes); |
| fes = flowRuleService.getFlowEntriesByLiveType( |
| did, FlowEntry.FlowLiveType.LONG); |
| long longFlowCount = Iterables.size(fes); |
| fes = flowRuleService.getFlowEntriesByLiveType( |
| did, FlowEntry.FlowLiveType.UNKNOWN); |
| long unknownFlowCount = Iterables.size(fes); |
| |
| log.trace(CHECK_AND_MOVE_COUNT_LOG, totalFlowCount, |
| immediateFlowCount, shortFlowCount, midFlowCount, longFlowCount, unknownFlowCount); |
| |
| if (immediateFlowCount < 0) { |
| log.error("Immediate flow count is negative"); |
| } |
| } |
| } |
| log.trace("checkAndMoveLiveFlowAll, AdaptiveStats for {}", sw.getStringId()); |
| } |
| |
| // check and set the flow live type based on current time |
| private boolean checkAndMoveLiveFlowInternal(StoredFlowEntry fe) { |
| long fromLastSeen = ((System.currentTimeMillis() - fe.lastSeen()) / 1000); |
| // fe.life() unit is SECOND! |
| long liveTime = fe.life() + fromLastSeen; |
| |
| FlowEntry.FlowLiveType oldLiveType = fe.liveType(); |
| |
| switch (fe.liveType()) { |
| case IMMEDIATE: |
| if (liveTime >= calAndPollInterval) { |
| fe.setLiveType(FlowEntry.FlowLiveType.SHORT); |
| } |
| break; |
| case SHORT: |
| if (liveTime >= midPollInterval) { |
| fe.setLiveType(FlowEntry.FlowLiveType.MID); |
| } |
| break; |
| case MID: |
| if (liveTime >= longPollInterval) { |
| fe.setLiveType(FlowEntry.FlowLiveType.LONG); |
| } |
| break; |
| case LONG: |
| if (fromLastSeen > entirePollInterval) { |
| log.trace("checkAndMoveLiveFlowInternal, flow may be already removed at switch."); |
| return false; |
| } |
| break; |
| case UNKNOWN: // Unknown live type is calculated and set with correct flow live type here. |
| calAndSetFlowLiveType(fe); |
| break; |
| default: |
| // Error Live Type |
| log.error("checkAndMoveLiveFlowInternal, Unknown Live Type error!" |
| + " AdaptiveStats collection thread for {}", |
| sw.getStringId()); |
| return false; |
| } |
| |
| if (log.isTraceEnabled()) { |
| log.trace(CHECK_AND_MOVE_LOG, fe.id(), fe.state(), fe.liveType(), |
| liveTime, fe.life(), fe.bytes(), fe.packets(), fromLastSeen, |
| fe.priority(), fe.selector().criteria(), fe.treatment(), |
| sw.getStringId()); |
| } |
| |
| return true; |
| } |
| } |