blob: 0ce91e1f0416006fc84f0f640d7123ae8a1c8781 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013, 2016 École Polytechnique de Montréal
*
* All rights reserved. This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0 which
* accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Geneviève Bastien - Initial implementation and API
* Patrick Tasse - Remove getSubField
*******************************************************************************/
package org.eclipse.tracecompass.internal.lttng2.kernel.core.event.matching;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelAnalysisEventLayout;
import org.eclipse.tracecompass.analysis.os.linux.core.trace.IKernelTrace;
import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
import org.eclipse.tracecompass.tmf.core.event.TmfEventField;
import org.eclipse.tracecompass.tmf.core.event.matching.IEventMatchingKey;
import org.eclipse.tracecompass.tmf.core.event.matching.ITmfMatchEventDefinition;
import org.eclipse.tracecompass.tmf.core.event.matching.TcpEventKey;
import org.eclipse.tracecompass.tmf.core.event.matching.TmfEventMatching.Direction;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTraceWithPreDefinedEvents;
import org.eclipse.tracecompass.tmf.core.trace.TmfEventTypeCollectionHelper;
/**
* Class to match tcp events. They use the main kernel's tracepoints
* netif_receive_skb and net_dev_queue to check if they have a TCP header and
* use the sequence, acknowledge and flags fields to match packets
*
* @author Geneviève Bastien
*/
public class TcpLttngEventMatching implements ITmfMatchEventDefinition {
private static final Map<IKernelAnalysisEventLayout, Set<String>> REQUIRED_EVENTS = new HashMap<>();
/** Use a weak hash map so that traces can be garbage collected */
private static final Map<ITmfTrace, IKernelAnalysisEventLayout> TRACE_LAYOUTS = new WeakHashMap<>();
@Override
public boolean canMatchTrace(ITmfTrace trace) {
// Get the events that this trace needs to have
if (!(trace instanceof IKernelTrace)) {
// Not a kernel trace, we cannot know what events to use, return
// false
return false;
}
IKernelAnalysisEventLayout layout = ((IKernelTrace) trace).getKernelEventLayout();
TRACE_LAYOUTS.put(trace, layout);
Set<String> events = REQUIRED_EVENTS.computeIfAbsent(layout, eventLayout -> {
Set<String> eventsSet = new HashSet<>();
eventsSet.addAll(eventLayout.eventsNetworkSend());
eventsSet.addAll(eventLayout.eventsNetworkReceive());
return eventsSet;
});
if (!(trace instanceof ITmfTraceWithPreDefinedEvents)) {
// No predefined events, suppose events are present
return true;
}
ITmfTraceWithPreDefinedEvents ktrace = (ITmfTraceWithPreDefinedEvents) trace;
Set<String> traceEvents = TmfEventTypeCollectionHelper.getEventNames(ktrace.getContainedEventTypes());
traceEvents.retainAll(events);
return !traceEvents.isEmpty();
}
/**
* @since 1.0
*/
@Override
public Direction getDirection(ITmfEvent event) {
IKernelAnalysisEventLayout layout = TRACE_LAYOUTS.get(event.getTrace());
if (layout == null) {
return null;
}
String evname = event.getName();
/* Is the event a tcp socket in or out event */
if (layout.eventsNetworkReceive().contains(evname)) {
return Direction.EFFECT;
} else if (layout.eventsNetworkSend().contains(evname)) {
return Direction.CAUSE;
}
return null;
}
@Override
public IEventMatchingKey getEventKey(ITmfEvent event) {
IKernelAnalysisEventLayout layout = TRACE_LAYOUTS.get(event.getTrace());
if (layout == null) {
return null;
}
TmfEventField content = (TmfEventField) event.getContent();
Long sequence = content.getFieldValue(Long.class, layout.fieldPathTcpSeq());
Long ack = content.getFieldValue(Long.class, layout.fieldPathTcpAckSeq());
Long flags = content.getFieldValue(Long.class, layout.fieldPathTcpFlags());
if (sequence == null || ack == null || flags == null) {
return null;
}
IEventMatchingKey key = new TcpEventKey(sequence, ack, flags);
return key;
}
}