Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVincent Perot2014-08-12 20:14:45 +0000
committerBernd Hufmann2014-08-14 19:46:26 +0000
commite534f27ee5e1776748fd22be580f814b89227cb7 (patch)
tree8ae21d967a1a03359e5992bca9def40a6967818f
parentf37c59426ca09601fc8c5ae4b64e6fd87751389b (diff)
downloadorg.eclipse.linuxtools-e534f27ee5e1776748fd22be580f814b89227cb7.tar.gz
org.eclipse.linuxtools-e534f27ee5e1776748fd22be580f814b89227cb7.tar.xz
org.eclipse.linuxtools-e534f27ee5e1776748fd22be580f814b89227cb7.zip
pcap: update the developer guide
Change-Id: I8322e19a4f54e903ef603f6b265e7c2341f244d8 Signed-off-by: Vincent Perot <vincent.perot@ericsson.com> Reviewed-on: https://git.eclipse.org/r/31473 Tested-by: Hudson CI Reviewed-by: Patrick Tasse <patrick.tasse@gmail.com> Reviewed-by: Bernd Hufmann <bernd.hufmann@ericsson.com> Tested-by: Bernd Hufmann <bernd.hufmann@ericsson.com>
-rw-r--r--lttng/org.eclipse.linuxtools.tmf.help/doc/Developer-Guide.mediawiki606
1 files changed, 605 insertions, 1 deletions
diff --git a/lttng/org.eclipse.linuxtools.tmf.help/doc/Developer-Guide.mediawiki b/lttng/org.eclipse.linuxtools.tmf.help/doc/Developer-Guide.mediawiki
index 217f8ca0aa..9ea088131a 100644
--- a/lttng/org.eclipse.linuxtools.tmf.help/doc/Developer-Guide.mediawiki
+++ b/lttng/org.eclipse.linuxtools.tmf.help/doc/Developer-Guide.mediawiki
@@ -996,6 +996,20 @@ Sent by statistic providers when new statistics data has been processed.
Received by statistics viewers and any component that needs to be notified of a statistics update.
+=== TmfPacketStreamSelected ===
+
+''Purpose''
+
+This signal is used to indicate that the user has selected a packet stream to analyze.
+
+''Senders''
+
+Sent by the Stream List View when the user selects a new packet stream.
+
+''Receivers''
+
+Received by views that analyze packet streams.
+
== Debugging ==
TMF has built-in Eclipse tracing support for the debugging of signal interaction between components. To enable it, open the '''Run/Debug Configuration...''' dialog, select a configuration, click the '''Tracing''' tab, select the plug-in '''org.eclipse.linuxtools.tmf.core''', and check the '''signal''' item.
@@ -1022,7 +1036,7 @@ trace:
20 s, sys_close, fd = 5
Now let's say we want to implement an analysis module which will track the
-amount of bytes read and written to eachfile. Here, of course the sys_read is
+amount of bytes read and written to each file. Here, of course the sys_read is
interesting. However, by just looking at that event, we have no information on
which file is being read, only its fd (5) is known. To get the match
fd5 = /home/user/myfile, we have to go back to the sys_open event which happens
@@ -3671,3 +3685,593 @@ System time (Elapsed time): The time between the start and the end of the execut
Kernel time: Time spent in kernel mode
Used Java Heap: It is the difference between the memory used at the beginning of the execution and at the end. This metric may be useful to calculate the overall size occupied by the data generated by the test run, by forcing a garbage collection before taking the metrics at the beginning and at the end of the execution. But it will not show the memory used throughout the execution. There can be a large standard deviation. The reason for this is that when benchmarking methods that trigger tasks in different threads, like signals and/or analysis, these other threads might be in various states at each run of the test, which will impact the memory usage calculated. When using this metric, either make sure the method to test does not trigger external threads or make sure you wait for them to finish.
+
+= Network Tracing =
+
+== Adding a protocol ==
+
+Supporting a new network protocol in TMF is straightforward. Minimal effort is required to support new protocols. In this tutorial, the UDP protocol will be added to the list of supported protocols.
+
+=== Architecture ===
+
+All the TMF pcap-related code is divided in three projects (not considering the tests plugins):
+* '''org.eclipse.linuxtools.pcap.core''', which contains the parser that will read pcap files and constructs the different packets from a ByteBuffer. It also contains means to build packet streams, which are conversation (list of packets) between two endpoints. To add a protocol, almost all of the work will be in that project.
+* '''org.eclipse.linuxtools.tmf.pcap.core''', which contains TMF-specific concepts and act as a wrapper between TMF and the pcap parsing library. It only depends on org.eclipse.linuxtools.tmf.core and org.eclipse.pcap.core. To add a protocol, one file must be edited in this project.
+* '''org.eclipse.linuxtools.tmf.pcap.ui''', which contains all TMF pcap UI-specific concepts, such as the views and perspectives. No work is needed in that project.
+
+=== UDP Packet Structure ===
+
+The UDP is a transport-layer protocol that does not guarantee message delivery nor in-order message reception. A UDP packet (datagram) has the following [http://en.wikipedia.org/wiki/User_Datagram_Protocol#Packet_structure structure]:
+
+{| class="wikitable" style="margin: 0 auto; text-align: center;"
+|-
+! style="border-bottom:none; border-right:none;"| ''Offsets''
+! style="border-left:none;"| Octet
+! colspan="8" | 0
+! colspan="8" | 1
+! colspan="8" | 2
+! colspan="8" | 3
+|-
+! style="border-top: none" | Octet
+! <tt>Bit</tt>!!<tt>&nbsp;0</tt>!!<tt>&nbsp;1</tt>!!<tt>&nbsp;2</tt>!!<tt>&nbsp;3</tt>!!<tt>&nbsp;4</tt>!!<tt>&nbsp;5</tt>!!<tt>&nbsp;6</tt>!!<tt>&nbsp;7</tt>!!<tt>&nbsp;8</tt>!!<tt>&nbsp;9</tt>!!<tt>10</tt>!!<tt>11</tt>!!<tt>12</tt>!!<tt>13</tt>!!<tt>14</tt>!!<tt>15</tt>!!<tt>16</tt>!!<tt>17</tt>!!<tt>18</tt>!!<tt>19</tt>!!<tt>20</tt>!!<tt>21</tt>!!<tt>22</tt>!!<tt>23</tt>!!<tt>24</tt>!!<tt>25</tt>!!<tt>26</tt>!!<tt>27</tt>!!<tt>28</tt>!!<tt>29</tt>!!<tt>30</tt>!!<tt>31</tt>
+|-
+! 0
+!<tt> 0</tt>
+| colspan="16" style="background:#fdd;"| Source port || colspan="16"| Destination port
+|-
+! 4
+!<tt>32</tt>
+| colspan="16"| Length || colspan="16" style="background:#fdd;"| Checksum
+|}
+
+Knowing that, we can define an UDPPacket class that contains those fields.
+
+=== Creating the UDPPacket ===
+
+First, in org.eclipse.linuxtools.pcap.core, create a new package named '''org.eclipse.linuxtools.pcap.core.protocol.name''' with name being the name of the new protocol. In our case name is udp so we create the package '''org.eclipse.linuxtools.pcap.core.protocol.udp'''. All our work is going in this package.
+
+In this package, we create a new class named UDPPacket that extends Packet. All new protocol must define a packet type that extends the abstract class Packet. We also add different fields:
+* ''Packet'' '''fChildPacket''', which is the packet encapsulated by this UDP packet, if it exists. This field will be initialized by findChildPacket().
+* ''ByteBuffer'' '''fPayload''', which is the payload of this packet. Basically, it is the UDP packet without its header.
+* ''int'' '''fSourcePort''', which is an unsigned 16-bits field, that contains the source port of the packet (see packet structure).
+* ''int'' '''fDestinationPort''', which is an unsigned 16-bits field, that contains the destination port of the packet (see packet structure).
+* ''int'' '''fTotalLength''', which is an unsigned 16-bits field, that contains the total length (header + payload) of the packet.
+* ''int'' '''fChecksum''', which is an unsigned 16-bits field, that contains a checksum to verify the integrity of the data.
+* ''UDPEndpoint'' '''fSourceEndpoint''', which contains the source endpoint of the UDPPacket. The UDPEndpoint class will be created later in this tutorial.
+* ''UDPEndpoint'' '''fDestinationEndpoint''', which contains the destination endpoint of the UDPPacket.
+* ''ImmutableMap<String, String>'' '''fFields''', which is a map that contains all the packet fields (see in data structure) which assign a field name with its value. Those values will be displayed on the UI.
+
+We also create the UDPPacket(PcapFile file, @Nullable Packet parent, ByteBuffer packet) constructor. The parameters are:
+* ''PcapFile'' '''file''', which is the pcap file to which this packet belongs.
+* ''Packet'' '''parent''', which is the packet encasulating this UDPPacket
+* ''ByteBuffer'' '''packet''', which is a ByteBuffer that contains all the data necessary to initialize the fields of this UDPPacket. We will retrieve bytes from it during object construction.
+
+The following class is obtained:
+
+<pre>
+package org.eclipse.linuxtools.pcap.core.protocol.udp;
+
+import java.nio.ByteBuffer;
+import java.util.Map;
+
+import org.eclipse.linuxtools.pcap.core.endpoint.ProtocolEndpoint;
+import org.eclipse.linuxtools.pcap.core.packet.BadPacketException;
+import org.eclipse.linuxtools.pcap.core.packet.Packet;
+
+public class UDPPacket extends Packet {
+
+ private final @Nullable Packet fChildPacket;
+ private final @Nullable ByteBuffer fPayload;
+
+ private final int fSourcePort;
+ private final int fDestinationPort;
+ private final int fTotalLength;
+ private final int fChecksum;
+
+ private @Nullable UDPEndpoint fSourceEndpoint;
+ private @Nullable UDPEndpoint fDestinationEndpoint;
+
+ private @Nullable ImmutableMap<String, String> fFields;
+
+ /**
+ * Constructor of the UDP Packet class.
+ *
+ * @param file
+ * The file that contains this packet.
+ * @param parent
+ * The parent packet of this packet (the encapsulating packet).
+ * @param packet
+ * The entire packet (header and payload).
+ * @throws BadPacketException
+ * Thrown when the packet is erroneous.
+ */
+ public UDPPacket(PcapFile file, @Nullable Packet parent, ByteBuffer packet) throws BadPacketException {
+ super(file, parent, Protocol.UDP);
+ // TODO Auto-generated constructor stub
+ }
+
+
+ @Override
+ public Packet getChildPacket() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public ByteBuffer getPayload() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public boolean validate() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ protected Packet findChildPacket() throws BadPacketException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public ProtocolEndpoint getSourceEndpoint() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public ProtocolEndpoint getDestinationEndpoint() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Map<String, String> getFields() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getLocalSummaryString() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ protected String getSignificationString() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+}
+</pre>
+
+Now, we implement the constructor. It is done in four steps:
+* We initialize fSourceEndpoint, fDestinationEndpoint and fFields to null, since those are lazy-loaded. This allows faster construction of the packet and thus faster parsing.
+* We initialize fSourcePort, fDestinationPort, fTotalLength, fChecksum using ByteBuffer packet. Thanks to the packet data structure, we can simply retrieve packet.getShort() to get the value. Since there is no unsigned in Java, special care is taken to avoid negative number. We use the utility method ConversionHelper.unsignedShortToInt() to convert it to an integer, and initialize the fields.
+* Now that the header is parsed, we take the rest of the ByteBuffer packet to initialize the payload, if there is one. To do this, we simply generate a new ByteBuffer starting from the current position.
+* We initialize the field fChildPacket using the method findChildPacket()
+
+The following constructor is obtained:
+<pre>
+ public UDPPacket(PcapFile file, @Nullable Packet parent, ByteBuffer packet) throws BadPacketException {
+ super(file, parent, Protocol.UDP);
+
+ // The endpoints and fFields are lazy loaded. They are defined in the get*Endpoint()
+ // methods.
+ fSourceEndpoint = null;
+ fDestinationEndpoint = null;
+ fFields = null;
+
+ // Initialize the fields from the ByteBuffer
+ packet.order(ByteOrder.BIG_ENDIAN);
+ packet.position(0);
+
+ fSourcePort = ConversionHelper.unsignedShortToInt(packet.getShort());
+ fDestinationPort = ConversionHelper.unsignedShortToInt(packet.getShort());
+ fTotalLength = ConversionHelper.unsignedShortToInt(packet.getShort());
+ fChecksum = ConversionHelper.unsignedShortToInt(packet.getShort());
+
+ // Initialize the payload
+ if (packet.array().length - packet.position() > 0) {
+ byte[] array = new byte[packet.array().length - packet.position()];
+ packet.get(array);
+
+ ByteBuffer payload = ByteBuffer.wrap(array);
+ payload.order(ByteOrder.BIG_ENDIAN);
+ payload.position(0);
+ fPayload = payload;
+ } else {
+ fPayload = null;
+ }
+
+ // Find child
+ fChildPacket = findChildPacket();
+
+ }
+</pre>
+
+Then, we implement the following methods:
+* ''public Packet'' '''getChildPacket()''': simple getter of fChildPacket
+* ''public ByteBuffer'' '''getPayload()''': simple getter of fPayload
+* ''public boolean'' '''validate()''': method that checks if the packet is valid. In our case, the packet is valid if the retrieved checksum fChecksum and the real checksum (that we can compute using the fields and payload of UDPPacket) are the same.
+* ''protected Packet'' '''findChildPacket()''': method that create a new packet if a encapsulated protocol is found. For instance, based on the fDestinationPort, it could determine what the encapsulated protocol is and creates a new packet object.
+* ''public ProtocolEndpoint'' '''getSourceEndpoint()''': method that initializes and returns the source endpoint.
+* ''public ProtocolEndpoint'' '''getDestinationEndpoint()''': method that initializes and returns the destination endpoint.
+* ''public Map<String, String>'' '''getFields()''': method that initializes and returns the map containing the fields matched to their value.
+* ''public String'' '''getLocalSummaryString()''': method that returns a string summarizing the most important fields of the packet. There is no need to list all the fields, just the most important one. This will be displayed on UI.
+* ''protected String'' '''getSignificationString()''': method that returns a string describing the meaning of the packet. If there is no particular meaning, it is possible to return getLocalSummaryString().
+* public boolean'' '''equals(Object obj)''': Object's equals method.
+* public int'' '''hashCode()''': Object's hashCode method.
+
+We get the following code:
+<pre>
+ @Override
+ public @Nullable Packet getChildPacket() {
+ return fChildPacket;
+ }
+
+ @Override
+ public @Nullable ByteBuffer getPayload() {
+ return fPayload;
+ }
+
+ /**
+ * Getter method that returns the UDP Source Port.
+ *
+ * @return The source Port.
+ */
+ public int getSourcePort() {
+ return fSourcePort;
+ }
+
+ /**
+ * Getter method that returns the UDP Destination Port.
+ *
+ * @return The destination Port.
+ */
+ public int getDestinationPort() {
+ return fDestinationPort;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * See http://www.iana.org/assignments/service-names-port-numbers/service-
+ * names-port-numbers.xhtml or
+ * http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers
+ */
+ @Override
+ protected @Nullable Packet findChildPacket() throws BadPacketException {
+ // When more protocols are implemented, we can simply do a switch on the fDestinationPort field to find the child packet.
+ // For instance, if the destination port is 80, then chances are the HTTP protocol is encapsulated. We can create a new HTTP
+ // packet (after some verification that it is indeed the HTTP protocol).
+ ByteBuffer payload = fPayload;
+ if (payload == null) {
+ return null;
+ }
+
+ return new UnknownPacket(getPcapFile(), this, payload);
+ }
+
+ @Override
+ public boolean validate() {
+ // Not yet implemented. ATM, we consider that all packets are valid.
+ // TODO Implement it. We can compute the real checksum and compare it to fChecksum.
+ return true;
+ }
+
+ @Override
+ public UDPEndpoint getSourceEndpoint() {
+ @Nullable
+ UDPEndpoint endpoint = fSourceEndpoint;
+ if (endpoint == null) {
+ endpoint = new UDPEndpoint(this, true);
+ }
+ fSourceEndpoint = endpoint;
+ return fSourceEndpoint;
+ }
+
+ @Override
+ public UDPEndpoint getDestinationEndpoint() {
+ @Nullable UDPEndpoint endpoint = fDestinationEndpoint;
+ if (endpoint == null) {
+ endpoint = new UDPEndpoint(this, false);
+ }
+ fDestinationEndpoint = endpoint;
+ return fDestinationEndpoint;
+ }
+
+ @Override
+ public Map<String, String> getFields() {
+ ImmutableMap<String, String> map = fFields;
+ if (map == null) {
+ @SuppressWarnings("null")
+ @NonNull ImmutableMap<String, String> newMap = ImmutableMap.<String, String> builder()
+ .put("Source Port", String.valueOf(fSourcePort)) //$NON-NLS-1$
+ .put("Destination Port", String.valueOf(fDestinationPort)) //$NON-NLS-1$
+ .put("Length", String.valueOf(fTotalLength) + " bytes") //$NON-NLS-1$ //$NON-NLS-2$
+ .put("Checksum", String.format("%s%04x", "0x", fChecksum)) //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ .build();
+ fFields = newMap;
+ return newMap;
+ }
+ return map;
+ }
+
+ @Override
+ public String getLocalSummaryString() {
+ return "Src Port: " + fSourcePort + ", Dst Port: " + fDestinationPort; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ @Override
+ protected String getSignificationString() {
+ return "Source Port: " + fSourcePort + ", Destination Port: " + fDestinationPort; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + fChecksum;
+ final Packet child = fChildPacket;
+ if (child != null) {
+ result = prime * result + child.hashCode();
+ } else {
+ result = prime * result;
+ }
+ result = prime * result + fDestinationPort;
+ final ByteBuffer payload = fPayload;
+ if (payload != null) {
+ result = prime * result + payload.hashCode();
+ } else {
+ result = prime * result;
+ }
+ result = prime * result + fSourcePort;
+ result = prime * result + fTotalLength;
+ return result;
+ }
+
+ @Override
+ public boolean equals(@Nullable Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ UDPPacket other = (UDPPacket) obj;
+ if (fChecksum != other.fChecksum) {
+ return false;
+ }
+ final Packet child = fChildPacket;
+ if (child != null) {
+ if (!child.equals(other.fChildPacket)) {
+ return false;
+ }
+ } else {
+ if (other.fChildPacket != null) {
+ return false;
+ }
+ }
+ if (fDestinationPort != other.fDestinationPort) {
+ return false;
+ }
+ final ByteBuffer payload = fPayload;
+ if (payload != null) {
+ if (!payload.equals(other.fPayload)) {
+ return false;
+ }
+ } else {
+ if (other.fPayload != null) {
+ return false;
+ }
+ }
+ if (fSourcePort != other.fSourcePort) {
+ return false;
+ }
+ if (fTotalLength != other.fTotalLength) {
+ return false;
+ }
+ return true;
+ }
+</pre>
+
+The UDPPacket class is implemented. We now have the define the UDPEndpoint.
+
+=== Creating the UDPEndpoint ===
+
+For the UDP protocol, an endpoint will be its source or its destination port, depending if it is the source endpoint or destination endpoint. Knowing that, we can create our UDPEndpoint class.
+
+We create in our package a new class named UDPEndpoint that extends ProtocolEndpoint. We also add a field: fPort, which contains the source or destination port. We finally add a constructor public ExampleEndpoint(Packet packet, boolean isSourceEndpoint):
+* ''Packet'' '''packet''': the packet to build the endpoint from.
+* ''boolean'' '''isSourceEndpoint''': whether the endpoint is the source endpoint or destination endpoint.
+
+We obtain the following unimplemented class:
+
+<pre>
+package org.eclipse.linuxtools.pcap.core.protocol.udp;
+
+import org.eclipse.linuxtools.pcap.core.endpoint.ProtocolEndpoint;
+import org.eclipse.linuxtools.pcap.core.packet.Packet;
+
+public class UDPEndpoint extends ProtocolEndpoint {
+
+ private final int fPort;
+
+ public UDPEndpoint(Packet packet, boolean isSourceEndpoint) {
+ super(packet, isSourceEndpoint);
+ // TODO Auto-generated constructor stub
+ }
+
+ @Override
+ public int hashCode() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
+</pre>
+
+For the constructor, we simply initialize fPort. If isSourceEndpoint is true, then we take packet.getSourcePort(), else we take packet.getDestinationPort().
+
+<pre>
+ /**
+ * Constructor of the {@link UDPEndpoint} class. It takes a packet to get
+ * its endpoint. Since every packet has two endpoints (source and
+ * destination), the isSourceEndpoint parameter is used to specify which
+ * endpoint to take.
+ *
+ * @param packet
+ * The packet that contains the endpoints.
+ * @param isSourceEndpoint
+ * Whether to take the source or the destination endpoint of the
+ * packet.
+ */
+ public UDPEndpoint(UDPPacket packet, boolean isSourceEndpoint) {
+ super(packet, isSourceEndpoint);
+ fPort = isSourceEndpoint ? packet.getSourcePort() : packet.getDestinationPort();
+ }
+</pre>
+
+Then we implement the methods:
+* ''public int'' '''hashCode()''': method that returns an integer based on the fields value. In our case, it will return an integer depending on fPort, and the parent endpoint that we can retrieve with getParentEndpoint().
+* ''public boolean'' '''equals(Object obj)''': method that returns true if two objects are equals. In our case, two UDPEndpoints are equal if they both have the same fPort and have the same parent endpoint that we can retrieve with getParentEndpoint().
+* ''public String'' '''toString()''': method that returns a description of the UDPEndpoint as a string. In our case, it will be a concatenation of the string of the parent endpoint and fPort as a string.
+
+<pre>
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ ProtocolEndpoint endpoint = getParentEndpoint();
+ if (endpoint == null) {
+ result = 0;
+ } else {
+ result = endpoint.hashCode();
+ }
+ result = prime * result + fPort;
+ return result;
+ }
+
+ @Override
+ public boolean equals(@Nullable Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof UDPEndpoint)) {
+ return false;
+ }
+
+ UDPEndpoint other = (UDPEndpoint) obj;
+
+ // Check on layer
+ boolean localEquals = (fPort == other.fPort);
+ if (!localEquals) {
+ return false;
+ }
+
+ // Check above layers.
+ ProtocolEndpoint endpoint = getParentEndpoint();
+ if (endpoint != null) {
+ return endpoint.equals(other.getParentEndpoint());
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ ProtocolEndpoint endpoint = getParentEndpoint();
+ if (endpoint == null) {
+ @SuppressWarnings("null")
+ @NonNull String ret = String.valueOf(fPort);
+ return ret;
+ }
+ return endpoint.toString() + '/' + fPort;
+ }
+</pre>
+
+=== Registering the UDP protocol ===
+
+The last step is to register the new protocol. There are three places where the protocol has to be registered. First, the parser has to know that a new protocol has been added. This is defined in the enum org.eclipse.linuxtools.pcap.core.protocol.Protocol. Simply add the protocol name here, along with a few arguments:
+* ''String'' '''longname''', which is the long version of name of the protocol. In our case, it is "User Datagram Protocol".
+* ''String'' '''shortName''', which is the shortened name of the protocol. In our case, it is "UDP".
+* ''int'' '''layer''', which is the layer to which the protocol belongs in the OSI model. In our case, this is the layer 4.
+* ''boolean'' '''supportsStream''', which defines whether or not the protocol supports packet streams. In our case, this is set to true.
+
+Thus, the following line is added in the Prtotocol enum:
+<pre>
+ UDP("User Datagram Protocol", "udp", ProtocolValues.LAYER_4, true),
+</pre>
+
+Also, TMF has to know about the new protocol. This is defined in org.eclipse.linuxtools.tmf.pcap.core.protocol.TmfProtocol. We simply add it with the '''EXACT SAME NAME''' as in the Protocol enum. Thus, the following line is added in the TmfProtocol enum:
+<pre>
+ UDP,
+</pre>
+
+Finally, all the protocols that could be the parent of the new protocol (in our case, IPv4 and IPv6) have to be notified of the new protocol. This is done by modifying the findChildPacket() method of the packet class of those protocols. For instance, in IPv4Packet, we add a case in the switch statement of findChildPacket, if the Protocol number matches UDP's protocol number at the network layer:
+<pre>
+ @Override
+ protected @Nullable Packet findChildPacket() throws BadPacketException {
+ ByteBuffer payload = fPayload;
+ if (payload == null) {
+ return null;
+ }
+
+ switch (fIpDatagramProtocol) {
+ case IPProtocolNumberHelper.PROTOCOL_NUMBER_TCP:
+ return new TCPPacket(getPcapFile(), this, payload);
+ case IPProtocolNumberHelper.PROTOCOL_NUMBER_UDP:
+ return new UDPPacket(getPcapFile(), this, payload);
+ default:
+ return new UnknownPacket(getPcapFile(), this, payload);
+ }
+ }
+</pre>
+
+The new protocol has been added. Running TMF should work just fine, and the new protocol is now recognized.
+
+== Adding stream-based views ==
+
+To add a stream-based View, simply monitor the TmfPacketStreamSelectedSignal in your view. It contains the new stream that you can retrieve with signal.getStream(). You must then make an event request to the current trace to get the events, and use the stream to filter the events of interest. Therefore, you must also monitor TmfTraceOpenedSignal, TmfTraceClosedSignal and TmfTraceSelectedSignal. Examples of stream-based views include a view that represents the packets as a sequence diagram, or that shows the TCP connection state based on the packets SYN/ACK/FIN/RST flags. A (very very very early) draft of such a view can be found at https://git.eclipse.org/r/#/c/31054/.
+
+== TODO ==
+
+* Add more protocols. At the moment, only four protocols are supported. The following protocols would need to be implemented: ARP, SLL, WLAN, USB, IPv6, ICMP, ICMPv6, IGMP, IGMPv6, SCTP, DNS, FTP, HTTP, RTP, SIP, SSH and Telnet. Other VoIP protocols would be nice.
+* Add a network graph view. It would be useful to produce graphs that are meaningful to network engineers, and that they could use (for presentation purpose, for instance). We could use the XML-based analysis to do that!
+* Add a Stream Diagram view. This view would represent a stream as a Sequence Diagram. It would be updated when a TmfNewPacketStreamSignal is thrown. It would be easy to see the packet exchange and the time delta between each packet. Also, when a packet is selected in the Stream Diagram, it should be selected in the event table and its content should be shown in the Properties View. See https://git.eclipse.org/r/#/c/31054/ for a draft of such a view.
+* Make adding protocol more "plugin-ish", via extension points for instance. This would make it easier to support new protocols, without modifying the source code.
+* Control dumpcap directly from eclipse, similar to how LTTng is controlled in the Control View.
+* Support pcapng. See: http://www.winpcap.org/ntar/draft/PCAP-DumpFileFormat.html for the file format.
+* Add SWTBOT tests to org.eclipse.linuxtools.tmf.pcap.ui
+* Add a Raw Viewer, similar to Wireshark. We could use the “Show Raw” in the event editor to do that.
+* Externalize strings in org.eclipse.linuxtools.pcap.core. At the moment, all the strings are hardcoded. It would be good to externalize them all. \ No newline at end of file

Back to the top