/*******************************************************************************
- * Copyright (c) 2013, 2015 École Polytechnique de Montréal
+ * 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 v1.0 which
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.jdt.annotation.NonNull;
-import org.eclipse.tracecompass.internal.lttng2.kernel.core.TcpEventStrings;
+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.ITmfEventField;
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.trace.ITmfTraceWithPreDefinedEvents;
import org.eclipse.tracecompass.tmf.core.trace.TmfEventTypeCollectionHelper;
-import com.google.common.collect.ImmutableSet;
-
/**
- * Class to match tcp type events. This class applies to traces obtained with
- * the full network tracepoint data available from an experimental branch of
- * lttng-modules. This branch is often rebased on lttng-modules master and is
- * available at
- * http://git.dorsal.polymtl.ca/~gbastien?p=lttng-modules.git;a=summary
- * net_data_experimental branch.
+ * 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 String @NonNull [] KEY_SEQ = { TcpEventStrings.TRANSPORT_FIELDS, TcpEventStrings.TYPE_TCP, TcpEventStrings.SEQ };
- private static final String @NonNull [] KEY_ACKSEQ = { TcpEventStrings.TRANSPORT_FIELDS, TcpEventStrings.TYPE_TCP, TcpEventStrings.ACKSEQ };
- private static final String @NonNull [] KEY_FLAGS = { TcpEventStrings.TRANSPORT_FIELDS, TcpEventStrings.TYPE_TCP, TcpEventStrings.FLAGS };
-
- private static final ImmutableSet<String> REQUIRED_EVENTS = ImmutableSet.of(
- TcpEventStrings.NET_DEV_QUEUE,
- TcpEventStrings.NETIF_RECEIVE_SKB);
-
- private static boolean canMatchPacket(final ITmfEvent event) {
- TmfEventField field = (TmfEventField) event.getContent();
+ private static final Map<IKernelAnalysisEventLayout, Set<String>> REQUIRED_EVENTS = new HashMap<>();
- String[] tcp_data = { TcpEventStrings.TRANSPORT_FIELDS, TcpEventStrings.TYPE_TCP };
- ITmfEventField data = field.getField(tcp_data);
- if (data != null) {
- return (data.getValue() != null);
- }
- return false;
- }
+ /** 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.get(layout);
+ if (events == null) {
+ events = new HashSet<>();
+ events.addAll(layout.eventsNetworkSend());
+ events.addAll(layout.eventsNetworkReceive());
+ REQUIRED_EVENTS.put(layout, events);
+ }
+
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(REQUIRED_EVENTS);
+ traceEvents.retainAll(events);
return !traceEvents.isEmpty();
}
*/
@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 (evname.equals(TcpEventStrings.NETIF_RECEIVE_SKB) && canMatchPacket(event)) {
+ if (layout.eventsNetworkReceive().contains(evname)) {
return Direction.EFFECT;
- } else if (evname.equals(TcpEventStrings.NET_DEV_QUEUE) && canMatchPacket(event)) {
+ } else if (layout.eventsNetworkSend().contains(evname)) {
return Direction.CAUSE;
}
return null;
@Override
public IEventMatchingKey getEventKey(ITmfEvent event) {
- TmfEventField field = (TmfEventField) event.getContent();
- ITmfEventField data;
-
- long seq = -1, ackseq = -1, flags = -1;
- data = field.getField(KEY_SEQ);
- if (data != null) {
- seq = (long) data.getValue();
- } else {
+ IKernelAnalysisEventLayout layout = TRACE_LAYOUTS.get(event.getTrace());
+ if (layout == null) {
return null;
}
- data = field.getField(KEY_ACKSEQ);
- if (data != null) {
- ackseq = (long) data.getValue();
- } else {
- return null;
- }
- data = field.getField(KEY_FLAGS);
- if (data != null) {
- flags = (long) data.getValue();
- } else {
+
+ 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(seq, ackseq, flags);
-
+ IEventMatchingKey key = new TcpEventKey(sequence, ack, flags);
return key;
+
}
}