<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.technet.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Network Monitor : Experts</title><link>http://blogs.technet.com/netmon/archive/tags/Experts/default.aspx</link><description>Tags: Experts</description><dc:language>en</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Reassembling Packets with the Network Monitor API</title><link>http://blogs.technet.com/netmon/archive/2009/10/12/reassembling-packets-with-the-network-monitor-api.aspx</link><pubDate>Mon, 12 Oct 2009 18:00:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3286257</guid><dc:creator>PaulELong</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.technet.com/netmon/comments/3286257.aspx</comments><wfw:commentRss>http://blogs.technet.com/netmon/commentrss.aspx?PostID=3286257</wfw:commentRss><description>&lt;P&gt;Network traffic by nature is fragmented. Limits of various network packet sizes force protocols to chop up data into multiple frames. When you capture data or read it from a trace with the API (NMAPI) you see only the fragments by default. But as the engine is collecting packets, it can be configured to pass up the reassembled payloads as well. For an intro to how assembly works in the UI, please see the &lt;A href="http://blogs.technet.com/netmon/archive/2008/07/11/nm3-tv-video-help-for-using-nm3.aspx" mce_href="http://blogs.technet.com/netmon/archive/2008/07/11/nm3-tv-video-help-for-using-nm3.aspx"&gt;video on reassembly&lt;/A&gt;. We also released a recent &lt;A href="http://channel9.msdn.com/posts/MichaelHawker/Microsoft-Network-Monitor-Experts-Day-Part-5-Advanced-API/" mce_href="http://channel9.msdn.com/posts/MichaelHawker/Microsoft-Network-Monitor-Experts-Day-Part-5-Advanced-API/"&gt;video on Channel 9&lt;/A&gt; which has some information about the API and reassembly. I would also recommend reading the "Introduction to the Network Monitor API" in the help file for a general background.&lt;/P&gt;
&lt;H3&gt;Configuring the Parser&lt;/H3&gt;
&lt;P&gt;The first step is to configure your parser to reassemble. Your API tool for breaking apart a frame is called the Frame Parser object. But to create a frame parser, you start by creating a Frame Parser Configuration. This configuration allows you to add data fields and properties. But it also allows you configure your parser for Reassembly and Conversations. In this case Reassembly might depend on Conversations, so we will enable them both. Here's how I setup my Parser Configuration and Frame Parser.&lt;/P&gt;
&lt;DIV style="BORDER-BOTTOM: silver 1px solid; TEXT-ALIGN: left; BORDER-LEFT: silver 1px solid; PADDING-BOTTOM: 4px; LINE-HEIGHT: 12pt; BACKGROUND-COLOR: #f4f4f4; MARGIN: 20px 0px 10px; PADDING-LEFT: 4px; WIDTH: 97.5%; PADDING-RIGHT: 4px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; MAX-HEIGHT: 200px; FONT-SIZE: 8pt; OVERFLOW: auto; BORDER-TOP: silver 1px solid; CURSOR: text; BORDER-RIGHT: silver 1px solid; PADDING-TOP: 4px" id=codeSnippetWrapper&gt;&lt;PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px" id=codeSnippet&gt;&lt;SPAN style="COLOR: #008000"&gt;// Returns a frame parser with a filter and one data field.&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: #008000"&gt;// INVALID_HANDLE_VALUE indicates failure.&lt;/SPAN&gt;&lt;BR&gt;HANDLE&lt;BR&gt;MyLoadNPL(&lt;SPAN style="COLOR: #0000ff"&gt;void&lt;/SPAN&gt;)&lt;BR&gt;{&lt;BR&gt;    HANDLE myFrameParser = INVALID_HANDLE_VALUE;&lt;BR&gt;    ULONG ret;&lt;BR&gt;&lt;BR&gt;    &lt;SPAN style="COLOR: #008000"&gt;// Use NULL to load default NPL set.&lt;/SPAN&gt;&lt;BR&gt;    ret = NmLoadNplParser(NULL, NmAppendRegisteredNplSets, MyParserBuild, 0, &amp;amp;g_NplParser);&lt;BR&gt;&lt;BR&gt;    &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt;(ret == ERROR_SUCCESS){&lt;BR&gt;        ret = NmCreateFrameParserConfiguration(g_NplParser, MyParserBuild, 0, &amp;amp;g_FrameParserConfig);&lt;BR&gt;&lt;BR&gt;        &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt;(ret == ERROR_SUCCESS)&lt;BR&gt;        {&lt;BR&gt;            &lt;SPAN style="COLOR: #008000"&gt;// Order is important here, must turn on Conversations before Reasembly.&lt;/SPAN&gt;&lt;BR&gt;            ret = NmConfigConversation(g_FrameParserConfig, NmConversationOptionNone , &lt;SPAN style="COLOR: #0000ff"&gt;TRUE&lt;/SPAN&gt;);&lt;BR&gt;            &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt;(ret != ERROR_SUCCESS)&lt;BR&gt;            {&lt;BR&gt;                wprintf(L&lt;SPAN style="COLOR: #006080"&gt;"Failed to config reassembly, error 0x%X\n"&lt;/SPAN&gt;, ret);&lt;BR&gt;            }&lt;BR&gt;&lt;BR&gt;            ret = NmConfigReassembly(g_FrameParserConfig, NmReassemblyOptionNone , &lt;SPAN style="COLOR: #0000ff"&gt;TRUE&lt;/SPAN&gt;);&lt;BR&gt;            &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt;(ret != ERROR_SUCCESS)&lt;BR&gt;            {&lt;BR&gt;                wprintf(L&lt;SPAN style="COLOR: #006080"&gt;"Failed to config reassembly, error 0x%X\n"&lt;/SPAN&gt;, ret);&lt;BR&gt;            }&lt;BR&gt;&lt;BR&gt;            &lt;SPAN style="COLOR: #008000"&gt;// Property so we can show the highest protocol description.&lt;/SPAN&gt;&lt;BR&gt;            ret = NmAddProperty(g_FrameParserConfig, L&lt;SPAN style="COLOR: #006080"&gt;"property.Description"&lt;/SPAN&gt;, &amp;amp;g_DescPropID);&lt;BR&gt;            &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt;(ret != ERROR_SUCCESS)&lt;BR&gt;            {&lt;BR&gt;                wprintf(L&lt;SPAN style="COLOR: #006080"&gt;"Failed to add field, error 0x%X\n"&lt;/SPAN&gt;, ret);&lt;BR&gt;            }&lt;BR&gt;&lt;BR&gt;            ret = NmCreateFrameParser(g_FrameParserConfig, &amp;amp;myFrameParser, NmParserOptimizeNone);&lt;BR&gt;&lt;BR&gt;            &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt;(ret != ERROR_SUCCESS)&lt;BR&gt;            {&lt;BR&gt;                wprintf(L&lt;SPAN style="COLOR: #006080"&gt;"Failed to create frame parser, error 0x%X\n"&lt;/SPAN&gt;, ret);&lt;BR&gt;                NmCloseHandle(g_FrameParserConfig);&lt;BR&gt;                NmCloseHandle(g_NplParser);&lt;BR&gt;                &lt;SPAN style="COLOR: #0000ff"&gt;return&lt;/SPAN&gt; INVALID_HANDLE_VALUE;&lt;BR&gt;            }&lt;BR&gt;        }&lt;BR&gt;        &lt;SPAN style="COLOR: #0000ff"&gt;else&lt;/SPAN&gt;&lt;BR&gt;        {&lt;BR&gt;            wprintf(L&lt;SPAN style="COLOR: #006080"&gt;"Unable to load parser config, error 0x%X\n"&lt;/SPAN&gt;, ret);&lt;BR&gt;            NmCloseHandle(g_NplParser);&lt;BR&gt;            &lt;SPAN style="COLOR: #0000ff"&gt;return&lt;/SPAN&gt; INVALID_HANDLE_VALUE;&lt;BR&gt;        }&lt;BR&gt;&lt;BR&gt;    }&lt;BR&gt;    &lt;SPAN style="COLOR: #0000ff"&gt;else&lt;/SPAN&gt;&lt;BR&gt;    {&lt;BR&gt;        wprintf(L&lt;SPAN style="COLOR: #006080"&gt;"Unable to load NPL\n"&lt;/SPAN&gt;);&lt;BR&gt;        &lt;SPAN style="COLOR: #0000ff"&gt;return&lt;/SPAN&gt; INVALID_HANDLE_VALUE;&lt;BR&gt;    }&lt;BR&gt;&lt;BR&gt;    &lt;SPAN style="COLOR: #0000ff"&gt;return&lt;/SPAN&gt;(myFrameParser);&lt;BR&gt;}&lt;/PRE&gt;&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;After creating your Frame Parser Configuration Object, you'll want to set any options first. This will let the engine optimize properly when adding other things like properties and data fields. It's also important that you turn on conversations before reassembly. Placing them in the wrong order will turn off Reassembly&lt;A&gt;&lt;/A&gt;&lt;A&gt; due to a bug in our &lt;/A&gt;&lt;A&gt;API&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;Above we also added a property so that I can show the description of the current frame. This is not necessary for reassembly to work, but it helps us understand the example.&lt;/P&gt;
&lt;H3&gt;Parsing the Frames&lt;/H3&gt;
&lt;P&gt;&lt;A&gt;It is up to the parsers (NPL) to mark each frames fragment type: &lt;I&gt;First=1&lt;/I&gt;, &lt;I&gt;Middle=2&lt;/I&gt;, &lt;I&gt;Last=3&lt;/I&gt; or &lt;I&gt;None=0.&lt;/I&gt; The engine tracks these fragments and returns a new inserted raw frame once a &lt;I&gt;Last&lt;/I&gt; fragment is detected for a specific protocol.&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;When you parse a raw frame using NmParseFrame, the last parameter passed is a pointer to a HANDLE that will contain an InsertedRawFrame if one is present. Otherwise this value will be set to &lt;I&gt;INVALID_HANDLE_VALUE&lt;/I&gt; for any frame that doesn't return a reassembled payload. For frames that do have a reassembled payload, the handle returned will contain a raw frame. You can now use your frame parser to parse this raw frame.&lt;/P&gt;
&lt;P&gt;The main part of my code simply retrieves frames from the capture file iteratively and calls ParseFrame, which does all the work. If an inserted frame is found, the function calls itself. The function is recursive because the handles for a RawFrame, ParsedFrame and InsertedRawFrame have to be closed in the order they were opened. There are other ways to do this, but for this example a recursive routine was the easiest. You will also want to insure the frames are in order. For instance you could use NmOpenCaptureFileInOrder to make sure the TCP frames are ordered correctly.&lt;/P&gt;
&lt;P&gt;In my case I parse and display all the frames so that you can get a feel for the pattern that occurs as frames fragments are marked by the engine. It also helps to shows how fragmentation looks at different protocol layers. If you were interested in only the reassembled frames or frames that are not fragmented to begin with, you could identify those as having a fragment type of &lt;I&gt;None&lt;/I&gt; and no &lt;I&gt;InsertedRawFrame&lt;/I&gt;.&lt;/P&gt;
&lt;P&gt;Here's the recursive frame parsing routine:&lt;/P&gt;
&lt;DIV style="BORDER-BOTTOM: silver 1px solid; TEXT-ALIGN: left; BORDER-LEFT: silver 1px solid; PADDING-BOTTOM: 4px; LINE-HEIGHT: 12pt; BACKGROUND-COLOR: #f4f4f4; MARGIN: 20px 0px 10px; PADDING-LEFT: 4px; WIDTH: 97.5%; PADDING-RIGHT: 4px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; MAX-HEIGHT: 200px; FONT-SIZE: 8pt; OVERFLOW: auto; BORDER-TOP: silver 1px solid; CURSOR: text; BORDER-RIGHT: silver 1px solid; PADDING-TOP: 4px" id=codeSnippetWrapper&gt;&lt;PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px" id=codeSnippet&gt;&lt;SPAN style="COLOR: #008000"&gt;// Recursive Parsing routine.  If an inserted frame is found, the recusive routine is called again.  This&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: #008000"&gt;// allows us to close our handles in the order there were created.&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: #0000ff"&gt;void&lt;/SPAN&gt;&lt;BR&gt;MyParseFrame(HANDLE frameParser, HANDLE rawFrame, ULONG curFrame, PULONG reassembleFrames, &lt;SPAN style="COLOR: #0000ff"&gt;int&lt;/SPAN&gt; reassembleCount)&lt;BR&gt;{&lt;BR&gt;    ULONG ret;&lt;BR&gt;    HANDLE ParsedFrame = INVALID_HANDLE_VALUE;&lt;BR&gt;    HANDLE InsRawFrame = INVALID_HANDLE_VALUE;&lt;BR&gt;&lt;BR&gt;    &lt;SPAN style="COLOR: #008000"&gt;// NmUseFrameNumber and valid unique frame numbers are neccessary for Reassembly to work properly.&lt;/SPAN&gt;&lt;BR&gt;    ret = NmParseFrame(frameParser, rawFrame, curFrame + *reassembleFrames, NmFieldDisplayStringRequired | NmUseFrameNumberParameter, &amp;amp;ParsedFrame, &amp;amp;InsRawFrame); &lt;BR&gt;    &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt;(ret == ERROR_SUCCESS)&lt;BR&gt;    {&lt;BR&gt;        &lt;SPAN style="COLOR: #008000"&gt;// Returns the highest level protocol description just to show which&lt;/SPAN&gt;&lt;BR&gt;        &lt;SPAN style="COLOR: #008000"&gt;// frame we are working on.&lt;/SPAN&gt;&lt;BR&gt;        PBYTE buf = GetDescription(frameParser);&lt;BR&gt;&lt;BR&gt;        &lt;SPAN style="COLOR: #008000"&gt;// Get the fragment information which helps understand what is happening,&lt;/SPAN&gt;&lt;BR&gt;        &lt;SPAN style="COLOR: #008000"&gt;// but not needed for reassembly to work.&lt;/SPAN&gt;&lt;BR&gt;        NM_FRAGMENTATION_INFO FragInfo;&lt;BR&gt;        GetFragType(ParsedFrame, &amp;amp;FragInfo);&lt;BR&gt;&lt;BR&gt;        wprintf(L&lt;SPAN style="COLOR: #006080"&gt;"%5d-%d: %5d      %-5.5s-%d    %-.45s\n"&lt;/SPAN&gt;, curFrame+1, reassembleCount, curFrame+(*reassembleFrames)+1, FragInfo.FragmentedProtocolName, FragInfo.FragmentType, buf);&lt;BR&gt;&lt;BR&gt;        free(buf);&lt;BR&gt;&lt;BR&gt;        &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt;(InsRawFrame != INVALID_HANDLE_VALUE)&lt;BR&gt;        {&lt;BR&gt;            (*reassembleFrames)++;&lt;BR&gt;            MyParseFrame(frameParser, InsRawFrame, curFrame, reassembleFrames, reassembleCount+1);&lt;BR&gt;&lt;BR&gt;            NmCloseHandle(InsRawFrame);&lt;BR&gt;        }&lt;BR&gt;    }&lt;BR&gt;&lt;BR&gt;    NmCloseHandle(ParsedFrame);&lt;BR&gt;    NmCloseHandle(InsRawFrame);&lt;BR&gt;}&lt;/PRE&gt;&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;When doing reassembly you must add the Frame Number parameter. It must also be unique, so you have to remember to increment when adding and parsing the reassembled frames. The GetFragType uses NmGetFrameFragmentInfo API call to determine the fragment type and protocol. You can look at the full example below to see how it works in details, but those ancillary pieces are pretty straight forward.&lt;/P&gt;
&lt;H3&gt;Looking at an Example&lt;/H3&gt;
&lt;P&gt;Below is the partial output for an example capture. In my notation, the Frame# contains a number after the dash that shows when multiple iterations occur on a frame. The Reassem# is the frame number that would appear in a reassembled trace in the UI and is what is used to seed each frame with a unique frame number.&lt;/P&gt;
&lt;DIV style="BORDER-BOTTOM: silver 1px solid; TEXT-ALIGN: left; BORDER-LEFT: silver 1px solid; PADDING-BOTTOM: 4px; LINE-HEIGHT: 12pt; BACKGROUND-COLOR: #f4f4f4; MARGIN: 20px 0px 10px; PADDING-LEFT: 4px; WIDTH: 97.5%; PADDING-RIGHT: 4px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; MAX-HEIGHT: 200px; FONT-SIZE: 8pt; OVERFLOW: auto; BORDER-TOP: silver 1px solid; CURSOR: text; BORDER-RIGHT: silver 1px solid; PADDING-TOP: 4px" id=codeSnippetWrapper&gt;&lt;PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px" id=codeSnippet&gt;Frame# Reassem# FragType Description&lt;BR&gt;&lt;BR&gt;5-0: 5 TCP -1 HTTP:Response, HTTP/1.1, Status: Bad gateway,&lt;BR&gt;&lt;BR&gt;6-0: 6 TCP -2 TCP:[Continuation to #5]Flags=...A...., SrcPo&lt;BR&gt;&lt;BR&gt;7-0: 7 -0 TCP:Flags=...A...., SrcPort=49382, DstPort=HT&lt;BR&gt;&lt;BR&gt;8-0: 8 TCP -3 TCP:[Continuation to #5]Flags=...AP..., SrcPo&lt;BR&gt;&lt;BR&gt;8-1: 9 -0 HTTP:Response, HTTP/1.1, Status: Bad gateway,&lt;BR&gt;&lt;BR&gt;...&lt;BR&gt;&lt;/PRE&gt;&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;In original frames 5-8, you can see a typical TCP fragmentation. Frame 5 is a TCP First fragment. Frame 6 is a middle fragment and frame 7 is traveling in the opposite direction so it's not part of this reassembly stream. Frame 8 is the last frame in the reassembled TCP payload which is marked as the &lt;I&gt;Last&lt;/I&gt; fragment. This is where the Inserted Raw Frame is valid and the recursive call to parse the frame would occur. Frame 8-1, is the parsed inserted frame which you can see matches the description of frame #5, but if you looked at it, there would be two differences.&lt;/P&gt;
&lt;P&gt;First, since it's an inserted frame it will have a PayloadHeader structure as its top protocol. This is a protocol we manufactured to take the place of the carrying protocol, in this case TCP. Having a duplicate TCP frame would confuse our parsers and perhaps the user as well. So this header takes it place and calls HTTP directly.&lt;/P&gt;
&lt;P&gt;Second, this frame will have a larger payload. It will consist of all the payload data from frame 5, 6, and 8.&lt;/P&gt;
&lt;H3&gt;Two Level Reassembly&lt;/H3&gt;
&lt;P&gt;In this next example, both TCP and HTTP has fragmented data.&lt;/P&gt;
&lt;DIV style="BORDER-BOTTOM: silver 1px solid; TEXT-ALIGN: left; BORDER-LEFT: silver 1px solid; PADDING-BOTTOM: 4px; LINE-HEIGHT: 12pt; BACKGROUND-COLOR: #f4f4f4; MARGIN: 20px 0px 10px; PADDING-LEFT: 4px; WIDTH: 97.5%; PADDING-RIGHT: 4px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; MAX-HEIGHT: 200px; FONT-SIZE: 8pt; OVERFLOW: auto; BORDER-TOP: silver 1px solid; CURSOR: text; BORDER-RIGHT: silver 1px solid; PADDING-TOP: 4px" id=codeSnippetWrapper&gt;&lt;PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px" id=codeSnippet&gt;...&lt;BR&gt;&lt;BR&gt;33-0: 36 TCP -1 HTTP:Response, HTTP/1.1, Status: Ok, URL: htt&lt;BR&gt;&lt;BR&gt;34-0: 37 TCP -2 TCP:[Continuation to #36]Flags=...A...., SrcP&lt;BR&gt;&lt;BR&gt;35-0: 38 -0 TCP:Flags=...A...., SrcPort=49384, DstPort=HT&lt;BR&gt;&lt;BR&gt;36-0: 39 TCP -3 TCP:[Continuation to #36]Flags=...AP..., SrcP&lt;BR&gt;&lt;BR&gt;36-1: 40 HTTP -1 HTTP:Response, HTTP/1.1, Status: Ok, URL: htt&lt;BR&gt;&lt;BR&gt;37-0: 41 TCP -1 HTTP:HTTP Payload, URL: http:&lt;SPAN style="COLOR: #008000"&gt;//www.google.com&lt;/SPAN&gt;&lt;BR&gt;&lt;BR&gt;38-0: 42 -0 TCP:Flags=...A...., SrcPort=49384, DstPort=HT&lt;BR&gt;&lt;BR&gt;39-0: 43 TCP -2 TCP:[Continuation to #41]Flags=...A...., SrcP&lt;BR&gt;&lt;BR&gt;40-0: 44 TCP -2 TCP:[Continuation to #41]Flags=...A...., SrcP&lt;BR&gt;&lt;BR&gt;41-0: 45 -0 TCP:Flags=...A...., SrcPort=49384, DstPort=HT&lt;BR&gt;&lt;BR&gt;42-0: 46 TCP -3 TCP:[Continuation to #41]Flags=...AP..., SrcP&lt;BR&gt;&lt;BR&gt;42-1: 47 HTTP -3 HTTP:HTTP Payload, URL: http:&lt;SPAN style="COLOR: #008000"&gt;//www.google.com&lt;/SPAN&gt;&lt;BR&gt;&lt;BR&gt;42-2: 48 -0 HTTP:Response, HTTP/1.1, Status: Ok, URL: htt&lt;BR&gt;&lt;BR&gt;...&lt;BR&gt;&lt;/PRE&gt;&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;Frames 33-36 make up the first HTTP fragment. As you can see, the inserted frame at 36-1 is a &lt;I&gt;First&lt;/I&gt; fragment, but the protocol is now HTTP. Frames 37-42 make up the next HTTP fragment which is inserted at frame 42-1. This inserted frame is the HTTP &lt;I&gt;Last&lt;/I&gt; fragment so now there is yet another inserted raw frame that we must iterate through and parse. Frame 42-2 is the final reassembled frame and contains the original HTTP Response in its entirety. The description matches frame 33 because it the data starts with payload in that frame but it also includes the payloads from frames 34, 36, 37, 39, 40, and 42. However, from the engines point of view, it really collects the payloads from frame 36-1 and 42-1. But each of these is made up from the fragmented frames mentioned above.&lt;/P&gt;
&lt;H3&gt;The Whole Shebang&lt;/H3&gt;
&lt;P&gt;Below I've placed the entire source code for the example described in this blog. While it depends on which protocols you are interested in, having access to the reassembled data can provide you with the big picture especially when focusing on application layer traffic.&lt;/P&gt;
&lt;DIV style="BORDER-BOTTOM: silver 1px solid; TEXT-ALIGN: left; BORDER-LEFT: silver 1px solid; PADDING-BOTTOM: 4px; LINE-HEIGHT: 12pt; BACKGROUND-COLOR: #f4f4f4; MARGIN: 20px 0px 10px; PADDING-LEFT: 4px; WIDTH: 97.5%; PADDING-RIGHT: 4px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; MAX-HEIGHT: 200px; FONT-SIZE: 8pt; OVERFLOW: auto; BORDER-TOP: silver 1px solid; CURSOR: text; BORDER-RIGHT: silver 1px solid; PADDING-TOP: 4px" id=codeSnippetWrapper&gt;&lt;PRE style="BORDER-BOTTOM-STYLE: none; TEXT-ALIGN: left; PADDING-BOTTOM: 0px; LINE-HEIGHT: 12pt; BORDER-RIGHT-STYLE: none; BACKGROUND-COLOR: #f4f4f4; MARGIN: 0em; PADDING-LEFT: 0px; WIDTH: 100%; PADDING-RIGHT: 0px; FONT-FAMILY: 'Courier New', courier, monospace; DIRECTION: ltr; BORDER-TOP-STYLE: none; COLOR: black; FONT-SIZE: 8pt; BORDER-LEFT-STYLE: none; OVERFLOW: visible; PADDING-TOP: 0px" id=codeSnippet&gt;&lt;SPAN style="COLOR: #cc6633"&gt;#include&lt;/SPAN&gt; &lt;SPAN style="COLOR: #006080"&gt;"stdafx.h"&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: #cc6633"&gt;#include&lt;/SPAN&gt; &lt;SPAN style="COLOR: #006080"&gt;"windows.h"&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: #cc6633"&gt;#include&lt;/SPAN&gt; &lt;SPAN style="COLOR: #006080"&gt;"stdio.h"&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: #cc6633"&gt;#include&lt;/SPAN&gt; &lt;SPAN style="COLOR: #006080"&gt;"stdlib.h"&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: #cc6633"&gt;#include&lt;/SPAN&gt; &lt;SPAN style="COLOR: #006080"&gt;"objbase.h"&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: #cc6633"&gt;#include&lt;/SPAN&gt; &lt;SPAN style="COLOR: #006080"&gt;"ntddndis.h"&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: #cc6633"&gt;#include&lt;/SPAN&gt; &lt;SPAN style="COLOR: #006080"&gt;"NMApi.h"&lt;/SPAN&gt;&lt;BR&gt;&lt;BR&gt;HANDLE g_NplParser = INVALID_HANDLE_VALUE;&lt;BR&gt;HANDLE g_FrameParserConfig = INVALID_HANDLE_VALUE;&lt;BR&gt;&lt;BR&gt;ULONG g_DescPropID = 0;    &lt;SPAN style="COLOR: #008000"&gt;// Global Description Property ID.&lt;/SPAN&gt;&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: #008000"&gt;// Callback for parser building messages&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: #0000ff"&gt;void&lt;/SPAN&gt; __stdcall&lt;BR&gt;MyParserBuild(PVOID Context, ULONG StatusCode, LPCWSTR lpDescription, ULONG ErrorType)&lt;BR&gt;{&lt;BR&gt;    wprintf(L&lt;SPAN style="COLOR: #006080"&gt;"%s\n"&lt;/SPAN&gt;, lpDescription);&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: #008000"&gt;// Returns a frame parser with a filter and one data field.&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: #008000"&gt;// INVALID_HANDLE_VALUE indicates failure.&lt;/SPAN&gt;&lt;BR&gt;HANDLE&lt;BR&gt;MyLoadNPL(&lt;SPAN style="COLOR: #0000ff"&gt;void&lt;/SPAN&gt;)&lt;BR&gt;{&lt;BR&gt;    HANDLE myFrameParser = INVALID_HANDLE_VALUE;&lt;BR&gt;    ULONG ret;&lt;BR&gt;&lt;BR&gt;    &lt;SPAN style="COLOR: #008000"&gt;// Use NULL to load default NPL set.&lt;/SPAN&gt;&lt;BR&gt;    ret = NmLoadNplParser(NULL, NmAppendRegisteredNplSets, MyParserBuild, 0, &amp;amp;g_NplParser);&lt;BR&gt;&lt;BR&gt;    &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt;(ret == ERROR_SUCCESS){&lt;BR&gt;        ret = NmCreateFrameParserConfiguration(g_NplParser, MyParserBuild, 0, &amp;amp;g_FrameParserConfig);&lt;BR&gt;&lt;BR&gt;        &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt;(ret == ERROR_SUCCESS)&lt;BR&gt;        {&lt;BR&gt;            &lt;SPAN style="COLOR: #008000"&gt;// Order is important here, must turn on Conversations before Reasembly.&lt;/SPAN&gt;&lt;BR&gt;            ret = NmConfigConversation(g_FrameParserConfig, NmConversationOptionNone , &lt;SPAN style="COLOR: #0000ff"&gt;TRUE&lt;/SPAN&gt;);&lt;BR&gt;            &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt;(ret != ERROR_SUCCESS)&lt;BR&gt;            {&lt;BR&gt;                wprintf(L&lt;SPAN style="COLOR: #006080"&gt;"Failed to config reassembly, error 0x%X\n"&lt;/SPAN&gt;, ret);&lt;BR&gt;            }&lt;BR&gt;&lt;BR&gt;            ret = NmConfigReassembly(g_FrameParserConfig, NmReassemblyOptionNone , &lt;SPAN style="COLOR: #0000ff"&gt;TRUE&lt;/SPAN&gt;);&lt;BR&gt;            &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt;(ret != ERROR_SUCCESS)&lt;BR&gt;            {&lt;BR&gt;                wprintf(L&lt;SPAN style="COLOR: #006080"&gt;"Failed to config reassembly, error 0x%X\n"&lt;/SPAN&gt;, ret);&lt;BR&gt;            }&lt;BR&gt;&lt;BR&gt;            &lt;SPAN style="COLOR: #008000"&gt;// Property so we can show the highest protocol description.&lt;/SPAN&gt;&lt;BR&gt;            ret = NmAddProperty(g_FrameParserConfig, L&lt;SPAN style="COLOR: #006080"&gt;"property.Description"&lt;/SPAN&gt;, &amp;amp;g_DescPropID);&lt;BR&gt;            &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt;(ret != ERROR_SUCCESS)&lt;BR&gt;            {&lt;BR&gt;                wprintf(L&lt;SPAN style="COLOR: #006080"&gt;"Failed to add field, error 0x%X\n"&lt;/SPAN&gt;, ret);&lt;BR&gt;            }&lt;BR&gt;&lt;BR&gt;            ret = NmCreateFrameParser(g_FrameParserConfig, &amp;amp;myFrameParser, NmParserOptimizeNone);&lt;BR&gt;&lt;BR&gt;            &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt;(ret != ERROR_SUCCESS)&lt;BR&gt;            {&lt;BR&gt;                wprintf(L&lt;SPAN style="COLOR: #006080"&gt;"Failed to create frame parser, error 0x%X\n"&lt;/SPAN&gt;, ret);&lt;BR&gt;                NmCloseHandle(g_FrameParserConfig);&lt;BR&gt;                NmCloseHandle(g_NplParser);&lt;BR&gt;                &lt;SPAN style="COLOR: #0000ff"&gt;return&lt;/SPAN&gt; INVALID_HANDLE_VALUE;&lt;BR&gt;            }&lt;BR&gt;        }&lt;BR&gt;        &lt;SPAN style="COLOR: #0000ff"&gt;else&lt;/SPAN&gt;&lt;BR&gt;        {&lt;BR&gt;            wprintf(L&lt;SPAN style="COLOR: #006080"&gt;"Unable to load parser config, error 0x%X\n"&lt;/SPAN&gt;, ret);&lt;BR&gt;            NmCloseHandle(g_NplParser);&lt;BR&gt;            &lt;SPAN style="COLOR: #0000ff"&gt;return&lt;/SPAN&gt; INVALID_HANDLE_VALUE;&lt;BR&gt;        }&lt;BR&gt;&lt;BR&gt;    }&lt;BR&gt;    &lt;SPAN style="COLOR: #0000ff"&gt;else&lt;/SPAN&gt;&lt;BR&gt;    {&lt;BR&gt;        wprintf(L&lt;SPAN style="COLOR: #006080"&gt;"Unable to load NPL\n"&lt;/SPAN&gt;);&lt;BR&gt;        &lt;SPAN style="COLOR: #0000ff"&gt;return&lt;/SPAN&gt; INVALID_HANDLE_VALUE;&lt;BR&gt;    }&lt;BR&gt;&lt;BR&gt;    &lt;SPAN style="COLOR: #0000ff"&gt;return&lt;/SPAN&gt;(myFrameParser);&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: #0000ff"&gt;void&lt;/SPAN&gt;&lt;BR&gt;UnLoadNPL(&lt;SPAN style="COLOR: #0000ff"&gt;void&lt;/SPAN&gt;)&lt;BR&gt;{&lt;BR&gt;    NmCloseHandle(g_NplParser);&lt;BR&gt;    NmCloseHandle(g_FrameParserConfig);&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;ULONG&lt;BR&gt;GetFragType(HANDLE parsedFrame, NM_FRAGMENTATION_INFO *FragInfo)&lt;BR&gt;{&lt;BR&gt;    ULONG ret;&lt;BR&gt;&lt;BR&gt;    FragInfo-&amp;gt;Size = &lt;SPAN style="COLOR: #0000ff"&gt;sizeof&lt;/SPAN&gt;(FragInfo);&lt;BR&gt;    ret = NmGetFrameFragmentInfo(parsedFrame, FragInfo);&lt;BR&gt;&lt;BR&gt;    &lt;SPAN style="COLOR: #0000ff"&gt;return&lt;/SPAN&gt; ret;&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;PBYTE&lt;BR&gt;GetDescription(HANDLE frameParser)&lt;BR&gt;{&lt;BR&gt;    ULONG ret;&lt;BR&gt;    NM_PROPERTY_INFO PropInfo;&lt;BR&gt;&lt;BR&gt;    &lt;SPAN style="COLOR: #008000"&gt;// Find out the size of the description property so we can allocate a buffer.&lt;/SPAN&gt;&lt;BR&gt;    &lt;SPAN style="COLOR: #008000"&gt;// MUST intialize the size and name pointer or NmGetPropertyInfo will fail.&lt;/SPAN&gt;&lt;BR&gt;    PropInfo.Size = &lt;SPAN style="COLOR: #0000ff"&gt;sizeof&lt;/SPAN&gt;(PropInfo);&lt;BR&gt;    PropInfo.Name = NULL;&lt;BR&gt;    ret = NmGetPropertyInfo(frameParser, g_DescPropID, &amp;amp;PropInfo);&lt;BR&gt;    &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt;(ret != ERROR_SUCCESS)&lt;BR&gt;    {&lt;BR&gt;        wprintf(L&lt;SPAN style="COLOR: #006080"&gt;"Error calling NmGetPropertyInfo, %d\n"&lt;/SPAN&gt;, ret);&lt;BR&gt;        &lt;SPAN style="COLOR: #0000ff"&gt;return&lt;/SPAN&gt; NULL;&lt;BR&gt;    }&lt;BR&gt;&lt;BR&gt;    ULONG retlen = 0;&lt;BR&gt;    NmPropertyValueType propType;&lt;BR&gt;    &lt;SPAN style="COLOR: #008000"&gt;// Add size of WCHAR for null terminator&lt;/SPAN&gt;&lt;BR&gt;    PBYTE buf = (PBYTE)malloc(PropInfo.ValueSize + &lt;SPAN style="COLOR: #0000ff"&gt;sizeof&lt;/SPAN&gt;(WCHAR));&lt;BR&gt;    ret = NmGetPropertyValueById(frameParser, g_DescPropID, PropInfo.ValueSize, buf, &amp;amp;retlen, &amp;amp;propType);&lt;BR&gt;    &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt;(ret != ERROR_SUCCESS)&lt;BR&gt;    {&lt;BR&gt;        wprintf(L&lt;SPAN style="COLOR: #006080"&gt;"Error calling NmGetPropertyValueById, %d\n"&lt;/SPAN&gt;, ret);&lt;BR&gt;        &lt;SPAN style="COLOR: #0000ff"&gt;return&lt;/SPAN&gt; NULL;&lt;BR&gt;    }&lt;BR&gt;&lt;BR&gt;    &lt;SPAN style="COLOR: #0000ff"&gt;return&lt;/SPAN&gt; buf;&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: #008000"&gt;// Recursive Parsing routine.  If an inserted frame is found, the recusive routine is called again.  This&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: #008000"&gt;// allows us to close our handles in the order there were created.&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: #0000ff"&gt;void&lt;/SPAN&gt;&lt;BR&gt;MyParseFrame(HANDLE frameParser, HANDLE rawFrame, ULONG curFrame, PULONG reassembleFrames, &lt;SPAN style="COLOR: #0000ff"&gt;int&lt;/SPAN&gt; reassembleCount)&lt;BR&gt;{&lt;BR&gt;    ULONG ret;&lt;BR&gt;    HANDLE ParsedFrame = INVALID_HANDLE_VALUE;&lt;BR&gt;    HANDLE InsRawFrame = INVALID_HANDLE_VALUE;&lt;BR&gt;&lt;BR&gt;    &lt;SPAN style="COLOR: #008000"&gt;// NmUseFrameNumber and valid unique frame numbers are neccessary for Reassembly to work properly.&lt;/SPAN&gt;&lt;BR&gt;    ret = NmParseFrame(frameParser, rawFrame, curFrame + *reassembleFrames, NmFieldDisplayStringRequired | NmUseFrameNumberParameter, &amp;amp;ParsedFrame, &amp;amp;InsRawFrame); &lt;BR&gt;    &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt;(ret == ERROR_SUCCESS)&lt;BR&gt;    {&lt;BR&gt;        &lt;SPAN style="COLOR: #008000"&gt;// Returns the highest level protocol description just to show which&lt;/SPAN&gt;&lt;BR&gt;        &lt;SPAN style="COLOR: #008000"&gt;// frame we are working on.&lt;/SPAN&gt;&lt;BR&gt;        PBYTE buf = GetDescription(frameParser);&lt;BR&gt;&lt;BR&gt;        &lt;SPAN style="COLOR: #008000"&gt;// Get the fragment information which helps understand what is happening,&lt;/SPAN&gt;&lt;BR&gt;        &lt;SPAN style="COLOR: #008000"&gt;// but not needed for reassembly to work.&lt;/SPAN&gt;&lt;BR&gt;        NM_FRAGMENTATION_INFO FragInfo;&lt;BR&gt;        GetFragType(ParsedFrame, &amp;amp;FragInfo);&lt;BR&gt;&lt;BR&gt;        wprintf(L&lt;SPAN style="COLOR: #006080"&gt;"%5d-%d: %5d      %-5.5s-%d    %-.45s\n"&lt;/SPAN&gt;, curFrame+1, reassembleCount, curFrame+(*reassembleFrames)+1, FragInfo.FragmentedProtocolName, FragInfo.FragmentType, buf);&lt;BR&gt;&lt;BR&gt;        free(buf);&lt;BR&gt;&lt;BR&gt;        &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt;(InsRawFrame != INVALID_HANDLE_VALUE)&lt;BR&gt;        {&lt;BR&gt;            (*reassembleFrames)++;&lt;BR&gt;            MyParseFrame(frameParser, InsRawFrame, curFrame, reassembleFrames, reassembleCount+1);&lt;BR&gt;&lt;BR&gt;            NmCloseHandle(InsRawFrame);&lt;BR&gt;        }&lt;BR&gt;    }&lt;BR&gt;&lt;BR&gt;    NmCloseHandle(ParsedFrame);&lt;BR&gt;    NmCloseHandle(InsRawFrame);&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;&lt;SPAN style="COLOR: #0000ff"&gt;int&lt;/SPAN&gt; __cdecl wmain(&lt;SPAN style="COLOR: #0000ff"&gt;int&lt;/SPAN&gt; argc, WCHAR* argv[])&lt;BR&gt;{&lt;BR&gt;    ULONG ret = ERROR_SUCCESS;&lt;BR&gt;    &lt;SPAN style="COLOR: #008000"&gt;// The first paramryrt should be a file.&lt;/SPAN&gt;&lt;BR&gt;    &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt;(argc &amp;lt;= 1){&lt;BR&gt;        wprintf(L&lt;SPAN style="COLOR: #006080"&gt;"Expect a file name as the only command line parameter\n"&lt;/SPAN&gt;);&lt;BR&gt;        &lt;SPAN style="COLOR: #0000ff"&gt;return&lt;/SPAN&gt; -1;&lt;BR&gt;    }&lt;BR&gt;&lt;BR&gt;    &lt;SPAN style="COLOR: #008000"&gt;// Open the specified capture file.&lt;/SPAN&gt;&lt;BR&gt;    HANDLE myCaptureFile = INVALID_HANDLE_VALUE;&lt;BR&gt;    &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt;(ERROR_SUCCESS == NmOpenCaptureFile(argv[1], &amp;amp;myCaptureFile))&lt;BR&gt;    {&lt;BR&gt;        &lt;SPAN style="COLOR: #008000"&gt;// Initialize the parser engine and return a frame parser.&lt;/SPAN&gt;&lt;BR&gt;        HANDLE myFrameParser = MyLoadNPL();&lt;BR&gt;        &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt;(myFrameParser != INVALID_HANDLE_VALUE)&lt;BR&gt;        {&lt;BR&gt;            ULONG myFrameCount = 0;&lt;BR&gt;            ret = NmGetFrameCount(myCaptureFile, &amp;amp;myFrameCount); &lt;BR&gt;            &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt;(ret == ERROR_SUCCESS)&lt;BR&gt;            {&lt;BR&gt;                ULONG totReassembledFrames = 0;&lt;BR&gt;                HANDLE myRawFrame = INVALID_HANDLE_VALUE;&lt;BR&gt;&lt;BR&gt;                wprintf(L&lt;SPAN style="COLOR: #006080"&gt;"Frame#   Reassem#  FragType    Description\n"&lt;/SPAN&gt;);&lt;BR&gt;                &lt;SPAN style="COLOR: #0000ff"&gt;for&lt;/SPAN&gt;(ULONG i = 0; i &amp;lt; myFrameCount; i++)&lt;BR&gt;                {&lt;BR&gt;                    HANDLE myParsedFrame = INVALID_HANDLE_VALUE;&lt;BR&gt;                    ret = NmGetFrame(myCaptureFile, i, &amp;amp;myRawFrame); &lt;BR&gt;                    &lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt;(ret == ERROR_SUCCESS)&lt;BR&gt;                    {&lt;BR&gt;                        MyParseFrame(myFrameParser, myRawFrame, i, &amp;amp;totReassembledFrames, 0);&lt;BR&gt;&lt;BR&gt;                        NmCloseHandle(myRawFrame);&lt;BR&gt;                    }&lt;BR&gt;                    &lt;SPAN style="COLOR: #0000ff"&gt;else&lt;/SPAN&gt;&lt;BR&gt;                    {&lt;BR&gt;                        &lt;SPAN style="COLOR: #008000"&gt;// Print an error, but continue to loop.&lt;/SPAN&gt;&lt;BR&gt;                        wprintf(L&lt;SPAN style="COLOR: #006080"&gt;"Errors getting raw frame %d\n"&lt;/SPAN&gt;, i+1);&lt;BR&gt;                    }&lt;BR&gt;                }&lt;BR&gt;            }&lt;BR&gt;&lt;BR&gt;            NmCloseHandle(myFrameParser);&lt;BR&gt;        }&lt;BR&gt;        &lt;SPAN style="COLOR: #0000ff"&gt;else&lt;/SPAN&gt;&lt;BR&gt;        {&lt;BR&gt;            wprintf(L&lt;SPAN style="COLOR: #006080"&gt;"Errors creating frame parser\n"&lt;/SPAN&gt;);&lt;BR&gt;        }&lt;BR&gt;&lt;BR&gt;        NmCloseHandle(myCaptureFile);&lt;BR&gt;    }&lt;BR&gt;    &lt;SPAN style="COLOR: #0000ff"&gt;else&lt;/SPAN&gt;&lt;BR&gt;    {&lt;BR&gt;        wprintf(L&lt;SPAN style="COLOR: #006080"&gt;"Errors openning capture file\n"&lt;/SPAN&gt;);&lt;BR&gt;    }&lt;BR&gt;&lt;BR&gt;    &lt;SPAN style="COLOR: #008000"&gt;// Release global handles.&lt;/SPAN&gt;&lt;BR&gt;    UnLoadNPL();&lt;BR&gt;&lt;BR&gt;    &lt;SPAN style="COLOR: #0000ff"&gt;return&lt;/SPAN&gt; 0;&lt;BR&gt;}&lt;/PRE&gt;&lt;BR&gt;&lt;/DIV&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3286257" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/netmon/archive/tags/Experts/default.aspx">Experts</category></item><item><title>Top Users Expert for Network Monitor 3.3</title><link>http://blogs.technet.com/netmon/archive/2009/04/30/top-users-expert-for-network-monitor-3-3.aspx</link><pubDate>Fri, 01 May 2009 00:48:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3233754</guid><dc:creator>PaulELong</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.technet.com/netmon/comments/3233754.aspx</comments><wfw:commentRss>http://blogs.technet.com/netmon/commentrss.aspx?PostID=3233754</wfw:commentRss><description>&lt;P&gt;One of the major new features in Network Monitor 3.3 is the ability to run experts directly from the UI. And now NMTopUsers is available from our &lt;A href="http://www.codeplex.com/NMExperts" mce_href="http://www.codeplex.com/NMExperts"&gt;Experts Portal&lt;/A&gt;.&amp;nbsp; Plus as it's a CodePlex project, we have opened the source code as well. It's a fairly simple C# project which uses the NMAPI to access data from a trace. You can view and download the source code if you are interested in more details.&lt;/P&gt;
&lt;H3&gt;What Does NMTopUsers Do?&lt;/H3&gt;
&lt;P&gt;The problem we are trying to solve is a way to quickly identify the heaviest users of network traffic. For instance you might want to understand if there's a computer on your network that is hogging all the bandwidth. You might also want to identify a chatty machine which could be an indication that it has been infected with a virus or adware.&lt;/P&gt;
&lt;P&gt;There are actually two experts in one here. The Endpoint version shows traffic for each machine address, IPv4, or IPv6 address on your network. The Conversation version, on the other hand, shows traffic based on a pair of machines, IPv4, or IPv6 addresses so you can understand the traffic involved between machines.&lt;/P&gt;
&lt;H3&gt;How Does NMTopUsers Work?&lt;/H3&gt;
&lt;P&gt;Once you've installed the expert by running the MSI, "Top Users by Endpoint" and/or "Top Users by Conversation" will appear in the experts menu. Once you run the expert a new window will show up and display a data grid. The data will depend on any display filters applied or conversation tree nodes you might have selected. The data grid contains a list of nodes or conversations and then statics on the frames and bytes that have been sent and/or received.&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.technet.com/blogfiles/netmon/WindowsLiveWriter/TopUsersExpertforNetworkMonitor3.3_FA67/TopUsers_4.jpg" mce_href="http://blogs.technet.com/blogfiles/netmon/WindowsLiveWriter/TopUsersExpertforNetworkMonitor3.3_FA67/TopUsers_4.jpg"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; DISPLAY: inline; BORDER-TOP: 0px; BORDER-RIGHT: 0px" title=TopUsers border=0 alt=TopUsers src="http://blogs.technet.com/blogfiles/netmon/WindowsLiveWriter/TopUsersExpertforNetworkMonitor3.3_FA67/TopUsers_thumb_1.jpg" width=660 height=323 mce_src="http://blogs.technet.com/blogfiles/netmon/WindowsLiveWriter/TopUsersExpertforNetworkMonitor3.3_FA67/TopUsers_thumb_1.jpg"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;By default the data is sorted by Total Bytes. But you can click on any column header to sort by that column.&lt;/P&gt;
&lt;P&gt;The Address Type drop-down lets you select which types of addresses you want to see. By default we only show IPv4 addresses, but you can add Machine addresses and IPv6 addresses as well.&lt;/P&gt;
&lt;P&gt;The Tree View allows you to see the IPv4 and IPv6 address as they relate to the Machine addresses that they belong too. But as you can imagine this option is only available if you've enabled the Machine address type. Also if you've re-sorted on a different column in the Tree View, you can reset to the original order by using the Reset Tree button.&lt;/P&gt;
&lt;P&gt;Finally you can create a Pie or Bar chart of the information. While sometimes this can be cluttered due to the number of addresses, it can give you a high level overview of the usage. Keep in mind that the Bar chart can't display if you have Machine Addresses selected and multiple IPv4 or IPv6 addresses for a single machine address. This is because the bar chart attempts to line up each IPv4/IPv6 address with its matching Machine address and this doesn't make sense with multiple IP addresses.&lt;/P&gt;
&lt;H3&gt;Give it a Run&lt;/H3&gt;
&lt;P&gt;Please go to the &lt;A href="http://www.codeplex.com/NMExperts" mce_href="http://www.codeplex.com/NMExperts"&gt;Experts Portal&lt;/A&gt; and download both Top Users for Conversations and Endpoint. Try it out!&lt;/P&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3233754" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/netmon/archive/tags/Release/default.aspx">Release</category><category domain="http://blogs.technet.com/netmon/archive/tags/Experts/default.aspx">Experts</category><category domain="http://blogs.technet.com/netmon/archive/tags/tshoot/default.aspx">tshoot</category></item><item><title>Network Monitor 3.3 Beta Available on Connect</title><link>http://blogs.technet.com/netmon/archive/2009/03/04/network-monitor-3-3-beta-available-on-connect.aspx</link><pubDate>Wed, 04 Mar 2009 23:25:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3209270</guid><dc:creator>PaulELong</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.technet.com/netmon/comments/3209270.aspx</comments><wfw:commentRss>http://blogs.technet.com/netmon/commentrss.aspx?PostID=3209270</wfw:commentRss><description>&lt;P&gt;It’s time again for a new Beta version of Network Monitor. Using your feedback we’ve added some compelling new features! One in particular is the ability to launch experts from the UI. And what use would this be without something to launch? We’ll also be releasing some cool experts, like Top Users and Simple Search. In fact Simple Search is already available, just use the Experts menu from a saved trace to connect to our Experts landing page. Return every so often to see what is new. 
&lt;H3&gt;What’s an Expert? What is Simple Search?&lt;/H3&gt;
&lt;P&gt;An expert is a tool, run separately from Network Monitor that performs expert analysis on your trace data. For instance, Simple Search will allow you to search all trace data for strings and better yet, regular expressions! Need to find an email address or phone number, but don’t know exactly which one? A regular expression, using Simple Search, lets you find this type of string. Just launch the expert from the menu and search away. 
&lt;P&gt;&lt;A href="http://blogs.technet.com/blogfiles/netmon/WindowsLiveWriter/NetworkMonitor3.3BetaAvailableonConnect_D8FE/simplesearchnew.jpg" atomicselection="true"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; MARGIN: 10px 10px 0px 30px; BORDER-TOP: 0px; BORDER-RIGHT: 0px" border=0 alt=simplesearchnew src="http://blogs.technet.com/blogfiles/netmon/WindowsLiveWriter/NetworkMonitor3.3BetaAvailableonConnect_D8FE/simplesearchnew_thumb.jpg" width=240 height=214&gt;&lt;/A&gt; 
&lt;P&gt;But there’s so much more, so let’s list out what else is new. 
&lt;H3&gt;What’s New in NM3.3 Beta&lt;/H3&gt;
&lt;UL&gt;
&lt;LI&gt;Ability to capture on WWAN and Tunnel interfaces on Win7 
&lt;LI&gt;Critical fixes to NM3.3 to operate correctly with Hyper-V 
&lt;LI&gt;Right-click add to alias.&amp;nbsp; &amp;nbsp;Right-click a frame in the Frame Summary window with an IPv4, IPv6, or MAC address to add that address as a new alias.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;A href="http://blogs.technet.com/blogfiles/netmon/WindowsLiveWriter/NetworkMonitor3.3BetaAvailableonConnect_D8FE/CreateAlias.jpg" atomicselection="true" mce_href="http://blogs.technet.com/blogfiles/netmon/WindowsLiveWriter/NetworkMonitor3.3BetaAvailableonConnect_D8FE/CreateAlias.jpg"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; MARGIN: 10px 10px 0px 40px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" border=0 alt=CreateAlias src="http://blogs.technet.com/blogfiles/netmon/WindowsLiveWriter/NetworkMonitor3.3BetaAvailableonConnect_D8FE/CreateAlias_thumb.jpg" width=640 height=172 mce_src="http://blogs.technet.com/blogfiles/netmon/WindowsLiveWriter/NetworkMonitor3.3BetaAvailableonConnect_D8FE/CreateAlias_thumb.jpg"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Right click go to definition:&amp;nbsp; Right-click a field in the Frame Details windows and select Go To Data Field Definition or Go To Data Type Definition to see where the field is defined in the NPL parsers. 
&lt;LI&gt;Auto-scroll.&amp;nbsp;&amp;nbsp; See the most recent traffic as it comes in.&amp;nbsp; In a live capture, click the Autoscroll button on the main toolbar to have the Frame Summary window automatically scroll down to display the most recent frames as they come in.&amp;nbsp; Click Autoscroll again to freeze the view in its present location. 
&lt;LI&gt;Experts available online:&amp;nbsp; Experts are stand-alone applications that analyze Network Monitor capture data.&amp;nbsp; &amp;nbsp;Various experts are available online at &amp;nbsp;&lt;A href="http://go.microsoft.com/fwlink/?LinkID=133950" mce_href="http://go.microsoft.com/fwlink/?LinkID=133950"&gt;http://go.microsoft.com/fwlink/?LinkID=133950&lt;/A&gt;. 
&lt;LI&gt;Frame Comments:&amp;nbsp; Attach comments to frames in a saved capture file.&amp;nbsp; Select the Frame Comments tab in the lower-right window to add, view, edit, or delete comments.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;A href="http://blogs.technet.com/blogfiles/netmon/WindowsLiveWriter/NetworkMonitor3.3BetaAvailableonConnect_D8FE/FrameComments.jpg" atomicselection="true" mce_href="http://blogs.technet.com/blogfiles/netmon/WindowsLiveWriter/NetworkMonitor3.3BetaAvailableonConnect_D8FE/FrameComments.jpg"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; MARGIN: 10px 10px 0px 40px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" border=0 alt=FrameComments src="http://blogs.technet.com/blogfiles/netmon/WindowsLiveWriter/NetworkMonitor3.3BetaAvailableonConnect_D8FE/FrameComments_thumb.jpg" width=640 height=387 mce_src="http://blogs.technet.com/blogfiles/netmon/WindowsLiveWriter/NetworkMonitor3.3BetaAvailableonConnect_D8FE/FrameComments_thumb.jpg"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;API Extensions:&amp;nbsp;&amp;nbsp; API methods have been added to enable access to conversation information, properties, field display strings, and comments.&amp;nbsp; 
&lt;LI&gt;Ability to open ETL files and correlate information by Network Tracing scenario.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;A href="http://blogs.technet.com/blogfiles/netmon/WindowsLiveWriter/NetworkMonitor3.3BetaAvailableonConnect_D8FE/ETL_1.jpg" atomicselection="true" mce_href="http://blogs.technet.com/blogfiles/netmon/WindowsLiveWriter/NetworkMonitor3.3BetaAvailableonConnect_D8FE/ETL_1.jpg"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; MARGIN: 10px 10px 0px 40px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" border=0 alt=ETL src="http://blogs.technet.com/blogfiles/netmon/WindowsLiveWriter/NetworkMonitor3.3BetaAvailableonConnect_D8FE/ETL_thumb_1.jpg" width=640 height=370 mce_src="http://blogs.technet.com/blogfiles/netmon/WindowsLiveWriter/NetworkMonitor3.3BetaAvailableonConnect_D8FE/ETL_thumb_1.jpg"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;See our Release Notes for a complete list of new features and known issues. &lt;/LI&gt;&lt;/UL&gt;
&lt;H3&gt;Gimme, Gimme, Gimme!&lt;/H3&gt;
&lt;P&gt;The Beta is available on our connect site at &lt;A href="https://connect.microsoft.com/site/sitehome.aspx?SiteID=216" mce_href="https://connect.microsoft.com/site/sitehome.aspx?SiteID=216"&gt;https://connect.microsoft.com/site/sitehome.aspx?SiteID=216&lt;/A&gt;. But it is only available as a download if you join Connect. By joining you’ll also get updated when we release and be able to file bugs with us if you find issues. So give NM3.3 Beta a test drive and please let us know what you think! 
&lt;P&gt;Provide feedback at &lt;A href="http://go.microsoft.com/fwlink/?LinkID=142458" mce_href="http://go.microsoft.com/fwlink/?LinkID=142458"&gt;http://go.microsoft.com/fwlink/?LinkID=142458&lt;/A&gt; (you will need to login with your Connect Network Monitor credentials to see the Beta survey). Our voting website, input.microsoft.com has an expired certificate that we are working to renew.&amp;nbsp; For now, you can tell your browser to ignore the expired certificate as we address this problem.&lt;/P&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3209270" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/netmon/archive/tags/Release/default.aspx">Release</category><category domain="http://blogs.technet.com/netmon/archive/tags/Experts/default.aspx">Experts</category></item><item><title>Using Columns and Properties</title><link>http://blogs.technet.com/netmon/archive/2007/03/01/using-columns-and-properties.aspx</link><pubDate>Thu, 01 Mar 2007 20:26:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:667019</guid><dc:creator>PaulELong</dc:creator><slash:comments>7</slash:comments><comments>http://blogs.technet.com/netmon/comments/667019.aspx</comments><wfw:commentRss>http://blogs.technet.com/netmon/commentrss.aspx?PostID=667019</wfw:commentRss><description>&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;You might have had an occasion to add a new column in Network Monitor 3.0. But the list of available choices might be quite daunting. What you may not know, however, is that the list is derived from properties in the NPL script that makes up each parser. This means you can add any kind of information you want as a column. 
&lt;P&gt;This blog will attempt to show you some of the more useful columns you can add. But we will also explore the creation of properties in NPL for more advanced analysis. 
&lt;H4&gt;The Skinny on Columns&lt;/H4&gt;
&lt;P&gt;It’s probably important to give some background about how columns work in NM3. A common misconception is that the column information is actually the data, but in reality it’s a string describing the data. That means that what’s in the Source Column is not the hex data for 192.168.0.1, but a string that describes it. 
&lt;P&gt;This is important because a property is just a variable in NPL that can change based on other factors. For instance the Source column can display the Hardware Address, IPv4 Address, or IPv4 Address based on the frame in question. But in each case, the property is still just a string representation. 
&lt;H4&gt;Time Related Properties&lt;/H4&gt;
&lt;P&gt;For starters, let’s display what the default column layout is. 
&lt;P&gt;&lt;A href="http://blogs.technet.com/blogfiles/netmon/WindowsLiveWriter/UsingColumnsandProperties_AEF7/clip_image0021%5B3%5D.jpg" mce_href="http://blogs.technet.com/blogfiles/netmon/WindowsLiveWriter/UsingColumnsandProperties_AEF7/clip_image0021%5B3%5D.jpg" atomicselection="true"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; MARGIN: 10px 10px 0px 65px; BORDER-TOP: 0px; BORDER-RIGHT: 0px" border=0 src="http://blogs.technet.com/blogfiles/netmon/WindowsLiveWriter/UsingColumnsandProperties_AEF7/clip_image0021_thumb.jpg" width=640 height=30 mce_src="http://blogs.technet.com/blogfiles/netmon/WindowsLiveWriter/UsingColumnsandProperties_AEF7/clip_image0021_thumb.jpg"&gt;&lt;/A&gt; 
&lt;P&gt;By default, NM3 show “Time Offset” as one of its columns. But it’s often useful to see either the Time of Day or the Time Delta (time from last packet). Well both of these items are available for addition. To add these in, right mouse click any of the column headers and select “Choose Columns…”. 
&lt;P&gt;&lt;A href="http://blogs.technet.com/blogfiles/netmon/WindowsLiveWriter/UsingColumnsandProperties_AEF7/clip_image004%5B4%5D.jpg" mce_href="http://blogs.technet.com/blogfiles/netmon/WindowsLiveWriter/UsingColumnsandProperties_AEF7/clip_image004%5B4%5D.jpg" atomicselection="true"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; MARGIN: 10px 10px 0px 100px; BORDER-TOP: 0px; BORDER-RIGHT: 0px" border=0 src="http://blogs.technet.com/blogfiles/netmon/WindowsLiveWriter/UsingColumnsandProperties_AEF7/clip_image004_thumb%5B1%5D.jpg" width=240 height=71 mce_src="http://blogs.technet.com/blogfiles/netmon/WindowsLiveWriter/UsingColumnsandProperties_AEF7/clip_image004_thumb%5B1%5D.jpg"&gt;&lt;/A&gt; 
&lt;P&gt;Note that you can also save the current column layout as the default for new sessions, or restore the default column layout. Once you select the menu item, you will see a dialog like the one below. 
&lt;P&gt;&lt;A href="http://blogs.technet.com/blogfiles/netmon/WindowsLiveWriter/UsingColumnsandProperties_AEF7/clip_image006%5B3%5D.jpg" mce_href="http://blogs.technet.com/blogfiles/netmon/WindowsLiveWriter/UsingColumnsandProperties_AEF7/clip_image006%5B3%5D.jpg" atomicselection="true"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; MARGIN: 10px 10px 0px 100px; BORDER-TOP: 0px; BORDER-RIGHT: 0px" border=0 src="http://blogs.technet.com/blogfiles/netmon/WindowsLiveWriter/UsingColumnsandProperties_AEF7/clip_image006_thumb.jpg" width=640 height=389 mce_src="http://blogs.technet.com/blogfiles/netmon/WindowsLiveWriter/UsingColumnsandProperties_AEF7/clip_image006_thumb.jpg"&gt;&lt;/A&gt; 
&lt;P&gt;On the left is a list of column headers you can add, and on the right, your currently enabled column headers. To add a column, select the column on the left and hit add. Or to remove, click on an item on the right and select remove. You can also order the columns using the Move Up/Move Down buttons. It is also possible to move the columns around from the Frame Summary by drag and dropping the columns around, so you don’t need to go to the Choose Frame Summary Columns dialog to do this. 
&lt;H4&gt;Finding the Column to Add&lt;/H4&gt;
&lt;P&gt;The first problem you may encounter is that the list is huge, which is why I want to highlight some of the more useful headers you can add without NPL modification. But you still have to find the column, which you could do by just scrolling through the list. But there is a faster way! If you start typing a few of the letters, it should get you to that section more quickly. So, in this example I want to show you how to add the “Time of Day” and “Time Delta” columns. So first click in the Disabled Columns portion of the dialog, and start typing “T I m e” without the spaces, and you see that the items that start with Time appear. The first one you can see is “Time Delta”, so let’s add this to the list by clicking the “Add” button. Then also click on the “Time Of Day” and add it. 
&lt;P&gt;&lt;A href="http://blogs.technet.com/blogfiles/netmon/WindowsLiveWriter/UsingColumnsandProperties_AEF7/clip_image008%5B2%5D.jpg" mce_href="http://blogs.technet.com/blogfiles/netmon/WindowsLiveWriter/UsingColumnsandProperties_AEF7/clip_image008%5B2%5D.jpg" atomicselection="true"&gt;&lt;IMG style="BORDER-BOTTOM: 0px; BORDER-LEFT: 0px; MARGIN: 10px 10px 0px 100px; BORDER-TOP: 0px; BORDER-RIGHT: 0px" border=0 src="http://blogs.technet.com/blogfiles/netmon/WindowsLiveWriter/UsingColumnsandProperties_AEF7/clip_image008%5B1%5D.jpg" width=205 height=240 mce_src="http://blogs.technet.com/blogfiles/netmon/WindowsLiveWriter/UsingColumnsandProperties_AEF7/clip_image008%5B1%5D.jpg"&gt;&lt;/A&gt; 
&lt;P&gt;Once you click OK from the dialog, you should now see the new columns appear. The “Time Of Day” column will show you the time when the frame was captured. The “Time Delta” displays the time from the last frame. This is updated when a filter is applied, so if frames 1 and 2 are 1 second apart, and frames 2 and 2 are 1 second apart, a filter which only shows frames 1 and 3 will display a time delta of 2 seconds. For example given the following data: 
&lt;P&gt;
&lt;TABLE style="WIDTH: 665px; HEIGHT: 88px" border=1 width=665&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD&gt;&amp;nbsp;Time Of Day&lt;/TD&gt;
&lt;TD&gt;&amp;nbsp;Time Delta&lt;/TD&gt;
&lt;TD&gt;&amp;nbsp;Frame&lt;/TD&gt;
&lt;TD&gt;&amp;nbsp;Time Offset&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;&amp;nbsp;15:41:35.331&lt;/TD&gt;
&lt;TD&gt;&amp;nbsp;0.000000&lt;/TD&gt;
&lt;TD&gt;&amp;nbsp;1&lt;/TD&gt;
&lt;TD&gt;&amp;nbsp;0.000000&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;&amp;nbsp;15:41:36.331&lt;/TD&gt;
&lt;TD&gt;&amp;nbsp;1.000000&lt;/TD&gt;
&lt;TD&gt;&amp;nbsp;2&lt;/TD&gt;
&lt;TD&gt;&amp;nbsp;1.000000&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;&amp;nbsp;15:41:37.331&lt;/TD&gt;
&lt;TD&gt;&amp;nbsp;1.000000&lt;/TD&gt;
&lt;TD&gt;&amp;nbsp;3&lt;/TD&gt;
&lt;TD&gt;&amp;nbsp;2.000000&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;/P&gt;
&lt;P&gt;If filter that includes frames 2 and 3 are added, the resulting Rime Delta column would look as follows. &lt;/P&gt;
&lt;P&gt;
&lt;TABLE style="WIDTH: 669px; HEIGHT: 67px" border=1 width=669&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD&gt;&amp;nbsp;Time Of Day&lt;/TD&gt;
&lt;TD&gt;&amp;nbsp;Time Delta&lt;/TD&gt;
&lt;TD&gt;&amp;nbsp;Frame&lt;/TD&gt;
&lt;TD&gt;&amp;nbsp;Time Offset&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;&amp;nbsp;15:41:35.331&lt;/TD&gt;
&lt;TD&gt;&amp;nbsp;0.000000&lt;/TD&gt;
&lt;TD&gt;&amp;nbsp;1&lt;/TD&gt;
&lt;TD&gt;&amp;nbsp;0.000000&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;&amp;nbsp;15:41:37.331&lt;/TD&gt;
&lt;TD&gt;&amp;nbsp;2.000000&lt;/TD&gt;
&lt;TD&gt;&amp;nbsp;3&lt;/TD&gt;
&lt;TD&gt;&amp;nbsp;2.000000&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;Note: If you try to filter on the property for Time Delta in NM3.0, say to find all frames with a delta greater than 1 second, you won’t return any frames. We currently don’t have a way to properly apply this property in a filter. We hope to address this in future version of Network Monitor. 
&lt;H4&gt;Other Useful Properties&lt;/H4&gt;
&lt;P&gt;So I wanted to provide a list of other useful properties and their descriptions. This should provide you a reference of some of the more popular column entries. 
&lt;H5&gt;TCPDescription&lt;/H5&gt;
&lt;P&gt;It’s often useful to always see the TCP Description rather than the upper protocols. By default, NM3 shows the highest level protocol in the Frame Summary Description field. So by adding the TCPDescription property to the columns, you can always see this information. This is very useful for t-shooting strictly TCP problems. 
&lt;H5&gt;Other Protocol Description Fields&lt;/H5&gt;
&lt;P&gt;As with TCP, you may want to see other protocol header rather than other upper level protocols. For instance SMBDescription or HTTPDescription, could be added as columns. 
&lt;H5&gt;TCPAckNumber, TCPSequenceRange, and TCPFlags&lt;/H5&gt;
&lt;P&gt;These three properties are also great for t-shooting TCP issues. You may actually find this more useful than the TCP Description as the column information lines up the ACK/SEQ number for easy reference. 
&lt;H5&gt;SourceNetworkAddress and DestinationNetworkAddress&lt;/H5&gt;
&lt;P&gt;The way the Source/Destination columns are populated today, you don’t always see the real IPv4 or IPv6 address. Instead we show this based on the following rules. If a higher numbered item exists, we show that item. 
&lt;OL&gt;
&lt;LI&gt;Alias for the IP address 
&lt;LI&gt;Resolved Name of IP address 
&lt;LI&gt;Real IP address 
&lt;LI&gt;Hardware Address&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;So in cases where you’d like to see the real IP address and a resolved name exists, turning off the aliases doesn’t show you the real IP address. So you view the real IP address all the time by adding these columns. 
&lt;H5&gt;SourceHardwareAddress and DestinationHardwareAddress&lt;/H5&gt;
&lt;P&gt;Like the IP address, the Source and Destination Hardware addresses don’t always show up because of the same rules above. So adding these columns will allow you to always see the Hardware Addresses. 
&lt;H4&gt;Creating Your Own Properties&lt;/H4&gt;
&lt;P&gt;On occasion you might find it useful to create your own properties for viewing as a column in NM3. There may be a frame summary data field that you want to show up as a column. You might also want to combine a few data fields and create a column that combines that information. So let’s create a few example properties to show you how this is done. 
&lt;H5&gt;IPv4 Identification: Adding just a simple property&lt;/H5&gt;
&lt;P&gt;In this case we’ll create a property for IPv4’s Identification field. This is the field that uniquely tags an IPv4 packet and can be used to associate the same frame from two different captures. We’ll start by opening ipv4.npl. In NM3, you can do this in the parsers tab by searching for the file in the Parser Files in the Object View. Once you find IPv4.npl, double click it to edit. Next, search for the field called Identification, it should look like this: 
&lt;BLOCKQUOTE&gt;&lt;PRE class=csharpcode&gt;UINT16 TotalLength;
UINT16 Identification;

UINT16 FragmentFlags
{
…&lt;/PRE&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Now we add in a property by placing it in square brackets above the data field we want to create a property for.&amp;nbsp;&amp;nbsp; 
&lt;BLOCKQUOTE&gt;
&lt;DIV class=csharpcode-wrapper&gt;&lt;PRE class=csharpcode&gt;UINT16 TotalLength;
&lt;STRONG&gt;[IPv4Identification]&lt;/STRONG&gt;
UINT16 Identification;

UINT16 FragmentFlags
{
…&lt;/PRE&gt;&lt;/DIV&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Now save your changed NPL, and reload the parser. From the menu select Tools, Reload parsers. Once the build is complete you can load a trace with IPv4 traffic and add the column you just created. 
&lt;H5&gt;TCP Port Pair: Adding a derived property with two data fields&lt;/H5&gt;
&lt;P&gt;In this example, we are going to get a bit fancier. We will create a property that shows both the source and destination port in Hex, along with the friendly port name. Remember that since a property is just a string, we can set it to anything we want. The property does not have to only represent one value. 
&lt;P&gt;So in this case we will edit TCP.NPL like we did IPv4.NPL before and look for this section of code. 
&lt;BLOCKQUOTE&gt;&lt;PRE class=csharpcode&gt;UINT16 SrcPort = PortNameTable(&lt;SPAN class=kwrd&gt;this&lt;/SPAN&gt;);
[Pair = Port, DestinationPort]
UINT16 DstPort = PortNameTable(&lt;SPAN class=kwrd&gt;this&lt;/SPAN&gt;);

&lt;/PRE&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;We’ll want to add in our property right before the last data field we will reference. In this case there is already a bracketed section above DstPort, but these directive sections can have multiple lines separated by a comma. So we will change this to&amp;nbsp;&amp;nbsp; 
&lt;BLOCKQUOTE&gt;
&lt;DIV class=csharpcode-wrapper&gt;
&lt;DIV class=csharpcode-wrapper&gt;&lt;PRE class=csharpcode&gt;UINT16 SrcPort = PortNameTable(&lt;SPAN class=kwrd&gt;this&lt;/SPAN&gt;);
[
    Pair = Port, DestinationPort,
    TcpPortDesc=FormatString(“%d (%s) -&amp;gt; %d (%s)”, 
    SrcPort, 
    PortNameTable(SrcPort),
    DestPort,
    PortNameTable(DstPort))
]
UINT16 DstPort = PortNameTable(&lt;SPAN class=kwrd&gt;this&lt;/SPAN&gt;);

&lt;/PRE&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;As you see we’ve called our new property TcpPortDesc and we are using FormatString, which is like printf in C, to format the way our property will look. We have 4 parameters for FormatString, the first two are the Source port and friendly name, and the second two are for the destination. We use PortNameTable to convert the number of the port to a descriptive string. PortNameTable is just a table that has already been defined for you in GlobalTables.NPL. Tables are simple structures that given one value, we convert and return a different value. 
&lt;P&gt;Once you add in this new column, as described before, you will see a column that displays as follows: 
&lt;BLOCKQUOTE&gt;
&lt;P&gt;0x50 (HTTP(80)) -&amp;gt; 0xC0E6 (49382)&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;H5&gt;TCPPayload Info: Adding a property to display TCP payload as ASCII&lt;/H5&gt;
&lt;P&gt;Often you want to look at the TCP data as ASCII. For FTP conversations, the text reads like a story. But we must also work around a bug in NM3 which limits the text in a field to 0x103 bytes. So what we’ll do is limit the text when we collect it. 
&lt;P&gt;Here’s the original section of TCP.NPL we are going to modify. 
&lt;BLOCKQUOTE&gt;
&lt;DIV class=csharpcode-wrapper&gt;&lt;PRE class=csharpcode&gt;&lt;SPAN class=rem&gt;//This maybe useful for TCP payload data filter for all TCP based protocols&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;//A possible filter maybe: Property.TCPPayload.Contains("*****")&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;//[TCPPayload = AsciiString(frameData, offset, TCPPayloadLength)]&lt;/SPAN&gt;
[
DataFieldFrameLength = frameOffset + TCPPayloadLength,
&lt;/PRE&gt;&lt;/DIV&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;In this case the statement for the entire payload is commented out. You can see that this property may be useful to enable if you want to search TCP Payloads using something like 
&lt;BLOCKQUOTE&gt;
&lt;P&gt;Property.TCPPayload.Contains(“Anything”)&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;So we are going to enable this property and add another. Let’s change the code to this: 
&lt;BLOCKQUOTE&gt;
&lt;DIV class=csharpcode-wrapper&gt;&lt;PRE class=csharpcode&gt;&lt;SPAN class=rem&gt;//This maybe useful for TCP payload data filter for all TCP based protocols&lt;/SPAN&gt;
&lt;SPAN class=rem&gt;//A possible filter maybe: Property.TCPPayload.Contains("*****")&lt;/SPAN&gt;
[
TCPPayload = AsciiString(FrameData, FrameOffset, TCPPayloadLength),
TCPPayloadDisp = AsciiString(FrameData, FrameOffset, 0x103),
DataFieldFrameLength = frameOffset + TCPPayloadLength,
&lt;/PRE&gt;&lt;/DIV&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;This adds in two new properties. The first, TCPPayload, will allow us to do searching like described above. The first parameter is the data we are going to search in. When you use FrameData, it means the current frame information. The second parameter is the offset in the buffer, and another global property FrameOffset points to the current location in the frame. The final parameter is the length, and the property TCPPayloadLength holds that value for TCP. 
&lt;P&gt;But we can’t use TCPPayload for display because if the length is greater than 0x103 bytes, it won’t get displayed at all. For TCPPayloadDisp we fix this by explicitly setting the length. 
&lt;H4&gt;It’s All About What You Want to See&lt;/H4&gt;
&lt;P&gt;Using columns for displaying useful information can save you time and help you t-shoot problems. Perhaps in future version of NM3 we’ll have a way to define standard column setups so you can switch from you TCP T-shooting setup to your SMB t-shooting column setup. Also we do plan to provide some organization to the properties to make it easier to find things in that long list.&lt;/P&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=667019" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/netmon/archive/tags/NPL/default.aspx">NPL</category><category domain="http://blogs.technet.com/netmon/archive/tags/Experts/default.aspx">Experts</category><category domain="http://blogs.technet.com/netmon/archive/tags/tshoot/default.aspx">tshoot</category></item><item><title>Part 2: TCP Performance Expert and General Trouble Shooting</title><link>http://blogs.technet.com/netmon/archive/2007/01/26/part-2-tcp-performance-expert-and-general-trouble-shooting.aspx</link><pubDate>Fri, 26 Jan 2007 21:58:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:610973</guid><dc:creator>PaulELong</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.technet.com/netmon/comments/610973.aspx</comments><wfw:commentRss>http://blogs.technet.com/netmon/commentrss.aspx?PostID=610973</wfw:commentRss><description>&lt;P&gt;Performance issues are one of the more difficult problems to trouble shoot. Without a baseline, it's often hard to determine if something is really slower. But TCP does contain some built-in behavioral patterns that can be used as a signal to tell you something may be wrong with your network. &lt;/P&gt;
&lt;P&gt;So the purpose of this article is to provide some indicators in TCP you can look at to investigate and a way to provide a simple graph of TCP traffic that can help you determine if there is a problem and if so what kind. &lt;/P&gt;
&lt;H1&gt;TCP Clues &lt;/H1&gt;
&lt;P&gt;TCP is the layer that is in charge of making sure your packet gets delivered. It tags each packet with a sequence number and when something is missing, the client informs the sender. Below I've listed some general things you can filter on in NM3 to give you clues to see if your network is working properly. &lt;/P&gt;
&lt;H2&gt;TCP Retransmits: &lt;/H2&gt;
&lt;P&gt;When dissecting a TCP trace, one of the more obvious problems you can spot are TCP retransmits. A retransmit occurs when a client detects a missing packet. From the sender's perspective, he now has sent the packet twice, so the second packet is called a retransmit. While a certain number of retransmits may occur without causing problem, excessive retransmits may be an indication that your network is sick. In NM3, you can search for retransmitted frames by using the following filter. &lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;STRONG&gt;Property.TCPRetransmit &lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;One you apply the filter, all frames that have been retransmitted will be displayed. Also each displayed frame will tell you the original frame that it is a retransmit of in the TCP Frame Summary. Some level of retransmits may be acceptable, but varies based on your network topology. Here's an example of how it displays in NM3: &lt;/P&gt;
&lt;DIV&gt;
&lt;TABLE class="" style="BORDER-COLLAPSE: collapse" border=0&gt;
&lt;COLGROUP&gt;
&lt;COL style="WIDTH: 52px"&gt;
&lt;COL style="WIDTH: 78px"&gt;
&lt;COL style="WIDTH: 55px"&gt;
&lt;COL style="WIDTH: 83px"&gt;
&lt;COL style="WIDTH: 370px"&gt;&lt;/COLGROUP&gt;
&lt;TBODY vAlign=top&gt;
&lt;TR&gt;
&lt;TD class="" style="BORDER-RIGHT: black 0.5pt solid; PADDING-RIGHT: 7px; BORDER-TOP: black 0.5pt solid; PADDING-LEFT: 7px; BORDER-LEFT: black 0.5pt solid; BORDER-BOTTOM: black 0.5pt solid"&gt;
&lt;P&gt;Frame&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" style="BORDER-RIGHT: black 0.5pt solid; PADDING-RIGHT: 7px; BORDER-TOP: black 0.5pt solid; PADDING-LEFT: 7px; BORDER-LEFT: medium none; BORDER-BOTTOM: black 0.5pt solid"&gt;
&lt;P&gt;Time Offs&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" style="BORDER-RIGHT: black 0.5pt solid; PADDING-RIGHT: 7px; BORDER-TOP: black 0.5pt solid; PADDING-LEFT: 7px; BORDER-LEFT: medium none; BORDER-BOTTOM: black 0.5pt solid"&gt;
&lt;P&gt;Source&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" style="BORDER-RIGHT: black 0.5pt solid; PADDING-RIGHT: 7px; BORDER-TOP: black 0.5pt solid; PADDING-LEFT: 7px; BORDER-LEFT: medium none; BORDER-BOTTOM: black 0.5pt solid"&gt;
&lt;P&gt;Destination&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" style="BORDER-RIGHT: black 0.5pt solid; PADDING-RIGHT: 7px; BORDER-TOP: black 0.5pt solid; PADDING-LEFT: 7px; BORDER-LEFT: medium none; BORDER-BOTTOM: black 0.5pt solid"&gt;
&lt;P&gt;Description&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class="" style="BORDER-RIGHT: black 0.5pt solid; PADDING-RIGHT: 7px; BORDER-TOP: medium none; PADDING-LEFT: 7px; BORDER-LEFT: black 0.5pt solid; BORDER-BOTTOM: black 0.5pt solid"&gt;
&lt;P&gt;457&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" style="BORDER-RIGHT: black 0.5pt solid; PADDING-RIGHT: 7px; BORDER-TOP: medium none; PADDING-LEFT: 7px; BORDER-LEFT: medium none; BORDER-BOTTOM: black 0.5pt solid"&gt;
&lt;P&gt;16.375976&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" style="BORDER-RIGHT: black 0.5pt solid; PADDING-RIGHT: 7px; BORDER-TOP: medium none; PADDING-LEFT: 7px; BORDER-LEFT: medium none; BORDER-BOTTOM: black 0.5pt solid"&gt;
&lt;P&gt;Sndr&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" style="BORDER-RIGHT: black 0.5pt solid; PADDING-RIGHT: 7px; BORDER-TOP: medium none; PADDING-LEFT: 7px; BORDER-LEFT: medium none; BORDER-BOTTOM: black 0.5pt solid"&gt;
&lt;P&gt;Rcvr&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" style="BORDER-RIGHT: black 0.5pt solid; PADDING-RIGHT: 7px; BORDER-TOP: medium none; PADDING-LEFT: 7px; BORDER-LEFT: medium none; BORDER-BOTTOM: black 0.5pt solid"&gt;
&lt;P&gt;TCP: [Continuation to #402]Flags=....A..., SrcPort=1236, DstPort=Microsoft-DS(445), Len=1460, Seq=658111387 - 658112847, Ack=2995420839, Win=65484 (scale factor 0) = 65484&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class="" style="BORDER-RIGHT: black 0.5pt solid; PADDING-RIGHT: 7px; BORDER-TOP: medium none; PADDING-LEFT: 7px; BORDER-LEFT: black 0.5pt solid; BORDER-BOTTOM: black 0.5pt solid"&gt;
&lt;P&gt;464&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" style="BORDER-RIGHT: black 0.5pt solid; PADDING-RIGHT: 7px; BORDER-TOP: medium none; PADDING-LEFT: 7px; BORDER-LEFT: medium none; BORDER-BOTTOM: black 0.5pt solid"&gt;
&lt;P&gt;16.577148&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" style="BORDER-RIGHT: black 0.5pt solid; PADDING-RIGHT: 7px; BORDER-TOP: medium none; PADDING-LEFT: 7px; BORDER-LEFT: medium none; BORDER-BOTTOM: black 0.5pt solid"&gt;
&lt;P&gt;Sndr&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" style="BORDER-RIGHT: black 0.5pt solid; PADDING-RIGHT: 7px; BORDER-TOP: medium none; PADDING-LEFT: 7px; BORDER-LEFT: medium none; BORDER-BOTTOM: black 0.5pt solid"&gt;
&lt;P&gt;Rcvr&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" style="BORDER-RIGHT: black 0.5pt solid; PADDING-RIGHT: 7px; BORDER-TOP: medium none; PADDING-LEFT: 7px; BORDER-LEFT: medium none; BORDER-BOTTOM: black 0.5pt solid"&gt;
&lt;P&gt;TCP: [ReTransmit #457][Continuation to #402]Flags=....A..., SrcPort=1236, DstPort=Microsoft-DS(445), Len=1460, Seq=658111387 - 658112847, Ack=2995420839, Win=65484 (scale factor 0) = 65484&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;/DIV&gt;
&lt;H2&gt;TCP Fast Retransmits &lt;/H2&gt;
&lt;P&gt;In some cases you may see multiple ACKs one after another in quick succession. The receiver can send these ACKs to the sender to indicate it is missing a TCP sequence range. Normally, a timeout would occur for the acknowledgement of a particular sequence before a retransmit occurs. However, if the TCP sender supports fast retransmit then it will occur after receiving these multiple ACKs. A retransmission generated by fast retransmit also changes the back-off algorithm used. If a retransmit occurs due to a timeout, then the sender reverts back to "slow start." However, if a retransmit occurs because of a fast retransmit then the sender goes into "congestion avoidance." [See RFC 2581 for more information on Congestion Avoidance and Slow Start.] &lt;/P&gt;
&lt;P&gt;The response is called a "Fast Retransmit". This can be the behavior you see from one side when packets get lost in another segment of your network. In NM3 you can search for Fast Retransmits with this filter. &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Property.TCPFastRetransmits &lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;An example of a Fast retransmit looks like this: &lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;STRONG&gt;TCP: [Request Fast-Retransmits #370]Flags=....A..., SrcPort=1268, DstPort=LDAP(389), Len=0, Seq=2021124596, Ack=1458852541, Win=64240 (scale factor 0) = 0 &lt;/STRONG&gt;&lt;/P&gt;
&lt;H2&gt;TCP SACK option &lt;/H2&gt;
&lt;P&gt;The SACK option (selective acknowledgments) is like an ACK, but the difference is that it can keep track of multiple sections of missing data. A normal ACK acknowledges the last consecutive sequence number that it received. In contrast a SACK can keep track of multiple missing segments. The SACK option contains multiple segments relating which pieces it has acknowledged and which are now lost. The number of segments is constrained to the amount of space available for TCP options. You can filter on these as well to see if your network is losing packets. &lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;STRONG&gt;tcp.TCPOptions.Option.SACK &lt;/STRONG&gt;&lt;/P&gt;
&lt;H2&gt;TCP Resets &lt;/H2&gt;
&lt;P&gt;Resets aren't always a sign that something is wrong. You should try to look at the traffic around a reset to determine if it looks normal or not. Resets can occur when an application shuts down, or if a router is configure to block a port. But they also occur when a problem occurs in a TCP session. So these can sometimes be an indication that something is wrong. The filter to find resets is: &lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;STRONG&gt;tcp.Flags.Reset &lt;/STRONG&gt;&lt;/P&gt;
&lt;H1&gt;Where's Waldo – Spotting a bad TCP Connection &lt;/H1&gt;
&lt;P&gt;Being able to take a trace and visualize it can be a useful way to look for performance issues. Most humans are better at looking at a picture and finding differences than analyzing data. Especially the large sequence numbers involved with TCP traffic. &lt;/P&gt;
&lt;H2&gt;Limitations with this Expert &lt;/H2&gt;
&lt;P&gt;Unfortunately, there are limitations to that amount of data this expert can deal with. The specific limitations will be due to the memory/CPU power of the machine you are work on. Excel, which this expert relies on, isn't build to plot 1000's of points. So you may want to limit that amount of data you try to analyze. For the following examples, a 500 MB file was transferred from the client to the server. &lt;/P&gt;
&lt;H1&gt;Using the TCP Expert &lt;/H1&gt;
&lt;P&gt;If you are familiar with the Part 1, (http://blogs.technet.com/netmon/archive/2006/11/30/part-1-poor-man-s-expert-using-excel-top-users.aspx), expert that locates the Top Users, then the procedure is much the same. Once you have the Excel Sheet Ready and the NM3 columns aligned, it's just a matter of copying the data in to the clipboard and hitting a button which launches a macro in Excel and creates the graphs we will examine later on. &lt;/P&gt;
&lt;H2&gt;Setting Up Your Excel Spreadsheet &lt;/H2&gt;
&lt;P&gt;Basically you just create a new spreadsheet, create a new macro (TCPPerf) and edit it, then paste the code at the bottom of this article. Once you complete this step, you can then take one of the sheets, (I delete all but one of them), and give it a default name like TCPPerf. And finally, create a button on this sheet and attach the TCPPerf macro to it. &lt;/P&gt;
&lt;P style="TEXT-ALIGN: center" mce_keep="true"&gt;&lt;IMG style="WIDTH: 242px; HEIGHT: 157px" height=157 src="http://blogs.technet.com/photos/paulelong/images/610397/original.aspx" width=242 mce_src="http://blogs.technet.com/photos/paulelong/images/610397/original.aspx"&gt;&lt;/P&gt;
&lt;H2&gt;Grabbing the data to Analyze from Network Monitor &lt;/H2&gt;
&lt;P&gt;This section describes how to prepare NM3 so we get the necessary columns for our calculations to appear. In NM3 we can add columns for any property that is exposed by the parsers. Actually you can also add any properties you want as well, so basically any piece of data is fair game. In the case of TCP, we want to add in the Seq/Ack Numbers as well as the Window Size and Payload length. So specifically add in columns for TCP Seq Number, TCP Ack Number, Windows Size, and TCPPayload Length in that order. Place them right after Time Offset. The resulting layout should look as follows. &lt;/P&gt;
&lt;P style="TEXT-ALIGN: center" mce_keep="true"&gt;&lt;IMG style="WIDTH: 182px; HEIGHT: 234px" height=234 src="http://blogs.technet.com/photos/paulelong/images/610395/original.aspx" width=182 mce_src="http://blogs.technet.com/photos/paulelong/images/610395/original.aspx"&gt;&lt;/P&gt;
&lt;P&gt;After opening an existing trace or taking a new one, the next step is to filter down the specific data you want to analyze. In my case, I copied a file from my machine to a server. Since Window Size is negotiated in the TCP 3-way handshake, I made sure to disconnect to my client from the server so that may trace contains the entire conversation. I did this from the server in Computer Management under Shared Folders, Sessions. You can simply right click the session in question and select Close Session. Obviously you don't want to do this if you have something important occurring between this session and the server. &lt;/P&gt;
&lt;P&gt;In NM3 it's easy to filter the conversations down, by using the Conversation Tree on the left. [Note: This requires that conversations are enabled when the trace is opened or a capture is started. You can set this option from the Start Page.] &lt;/P&gt;
&lt;P style="TEXT-ALIGN: center" mce_keep="true"&gt;&lt;IMG style="WIDTH: 285px; HEIGHT: 124px" height=124 src="http://blogs.technet.com/photos/paulelong/images/610394/original.aspx" width=285 mce_src="http://blogs.technet.com/photos/paulelong/images/610394/original.aspx"&gt;&lt;/P&gt;
&lt;P&gt;Once you find the IP address pair, you can select each TCP conversation below, and look for the traffic relating to your copy. This traffic will appear as a bunch of SMB Reads (or SMB Writes if you copy to the server), intermixed with a bunch of TCP Continuation traffic. &lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;STRONG&gt;SMB: R; Write Andx, FID = 0x4004 (\t1_up.tst@#24), 61440 bytes &lt;/STRONG&gt;&lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;STRONG&gt;SMB: C; Write Andx, FID = 0x4004 (\t1_up.tst@#24), 61440 bytes at Offset 184320 &lt;/STRONG&gt;&lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;STRONG&gt;TCP: [Continuation to #256]Flags=....A..., SrcPort=1236, DstPort=Microsoft-DS(445), Len=1460, Seq=657940191 - 657941651, Ack=2995420737, Win=64118 (scale factor 0) = 64118 &lt;/STRONG&gt;&lt;/P&gt;
&lt;P style="MARGIN-LEFT: 36pt"&gt;&lt;STRONG&gt;TCP: [Continuation to #256]Flags=....A..., SrcPort=1236, DstPort=Microsoft-DS(445), Len=1460, Seq=657941651 - 657943111, Ack=2995420737, Win=64118 (scale factor 0) = 64118 &lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Once you have located and selected the appropriate TCP Conversation, highlight all the frames involved and copy them to the clipboard. I often use keystrokes, so I did this by selecting the first frame, hit Shift+Ctrl+End, and then right mouse click and copied them to the clipboard. &lt;/P&gt;
&lt;P&gt;Now you simply open the Excel Spread sheet you created earlier and click the button. This will results in 4 sheets. The first sheet, PerfData, is just a copy of the data from NM3, plus some new columns that are based off this data. The second sheet, TCPPerf_PerfData, is data copied from the first sheet so that we can sort based off the data we calculated. The final two sheets contain the charts for each side of the transfer. The chart is named based on the machine adress that is sending the data. &lt;/P&gt;
&lt;H1&gt;Interpreting the Data &lt;/H1&gt;
&lt;P&gt;Since the resulting data we'll examine is a graph, it's useful to examine different graphs that are a result of different issues so we can refer to these examples as an indicator to the type of problem we may have. In my tests, I have duplicated the following situations: Increased Round Trip Time, Packet Loss, Small Window Size, and Bandwidth Reduction. All traces are taken from the sender (client) which is sending data to the server. &lt;/P&gt;
&lt;P&gt;The data is graphed so that the left side axis contains the sequence numbers scaled for Length and UnACKed data. The right side axis is the scaled for the Window Size. Two different scales are used because often the Window size is much larger than the data being sent. UnACKed data is data which have been sent by the sender but has not been acknowledged by the receiver after the TCP timeout expires. &lt;/P&gt;
&lt;H1&gt;The Graphs &lt;/H1&gt;
&lt;P&gt;Each test was a copy of around a 500 Meg file from my machine to a server. I used the CMD prompt to do the copy to avoid unwanted Explorer traffic. So we'll start by looking at a base line capture. In this case the Round-Trip-Delay is less than a millisecond, and there are no packets lost. The bandwidth is around 100 MB. &lt;/P&gt;
&lt;H2&gt;Baseline - &amp;lt; 1 Millisecond RTT, 100 MB, No Packet Loss &lt;/H2&gt;
&lt;P mce_keep="true"&gt;&lt;IMG style="WIDTH: 627px; HEIGHT: 423px" height=423 src="http://blogs.technet.com/photos/paulelong/images/610393/original.aspx" width=627 mce_src="http://blogs.technet.com/photos/paulelong/images/610393/original.aspx"&gt;&lt;/P&gt;
&lt;P&gt;In many of the examples I change the horizontal axis min/max so that the data isn't so compressed. You may find it useful to adjust both the max/min scales on the X-axis depending on how much extra trace traffic you took in your original trace. &lt;/P&gt;
&lt;P&gt;The pink line represents the length of the data we are sending. For the most part it's a full packet size of 1480. The only reason it dips any lower than that is because SMB sends 61440 bytes of info (0xF000), so the dip at the end is the remainder. &lt;/P&gt;
&lt;P&gt;Let's look at the UnACKed data (yellow line). The client continues to send data as fast as it can until it reaches the advertised window size (blue line). Note that since the scales for Window Size and Packet size can be vastly different, window size is put on the right vertical Axis. In this case, however, they happen to line up. This is helpful, because it shows that we keep sending data until the UnACKed data reaches the max advertised window size. Once we get to this point, we have to wait for an ACK from the server before we send more data. So we get in a state where we have to wait for an ACK before sending more data. Then once this particular SMB command completes, another delay occurs while waiting for the SMB response which for the next WRITE command. &lt;/P&gt;
&lt;P&gt;Since our RTT is very low, we tend to see little effect of this delay. But note that if we had a larger window size we would have been able to even send more data before waiting for an ACK and thus improve the transfer time. &lt;/P&gt;
&lt;H2&gt;100 Millisecond RTT, 100 MB &lt;/H2&gt;
&lt;P mce_keep="true"&gt;&lt;IMG style="WIDTH: 623px; HEIGHT: 421px" height=421 src="http://blogs.technet.com/photos/paulelong/images/610389/original.aspx" width=623 mce_src="http://blogs.technet.com/photos/paulelong/images/610389/original.aspx"&gt;&lt;/P&gt;
&lt;P&gt;In this sample, I purposely set the Round Trip Time to 100 Milliseconds. The basic effect is that anything that requires a response before it can continue, will incur a 100 millisecond delay. So this will certainly affect the time required to transfer the 500 MB file. As you can see here, a total of about 4 seconds is needed now. Another side affect is that since it's slower, the server is able to keep up with the request so the amount of UnACKed data is generally lower. &lt;/P&gt;
&lt;H2&gt;100 Millisecond RTT DownStream, 100 MB, 5376 Window Size &lt;/H2&gt;
&lt;P mce_keep="true"&gt;&lt;IMG style="WIDTH: 627px; HEIGHT: 424px" height=424 src="http://blogs.technet.com/photos/paulelong/images/610388/original.aspx" width=627 mce_src="http://blogs.technet.com/photos/paulelong/images/610388/original.aspx"&gt;&lt;/P&gt;
&lt;P&gt;In this example we've cut the Windows size down to 5376 bytes. I've zoomed into a small segment of the entire transfer to show the details. The main thing to note is that we cannot fill the pipe up more than two segments. This means the number of segments we have to wait for an ACK for goes up, thus the total time to transfer also goes up. You can see here, for instance that there are many times we have to wait the return ACK before we can send a new packet (about 20 as compared to 5 in the baseline capture). &lt;/P&gt;
&lt;H2&gt;Down Stream 100 Millisecond RTT, %5 Packet Loss &lt;/H2&gt;
&lt;P mce_keep="true"&gt;&lt;IMG src="http://blogs.technet.com/photos/paulelong/images/610390/original.aspx" mce_src="http://blogs.technet.com/photos/paulelong/images/610390/original.aspx"&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;Now we'll add in some packet loss. In this case the loss is on the Down Stream side, which means that responses from the server never make it to the client. Remember that the client is where the capture is being taken, so the resulting trace won't show any retransmits. Since the server's ACKs are being dropped, the client is affected because he cannot move his sliding window due to the fact that he thinks there is more unACKed data than there truly is. Thus the client has a difficult time sending data at a rate that fills the server's receive window. This is shown in the graph by the slow approach of the UnACKed data to the servers advertised window size. &lt;/SPAN&gt;&lt;/P&gt;
&lt;H2&gt;Down Stream 100 Millisecond RTT, Up Stream %5 Packet Loss &lt;/H2&gt;
&lt;P mce_keep="true"&gt;&lt;IMG style="WIDTH: 623px; HEIGHT: 421px" height=421 src="http://blogs.technet.com/photos/paulelong/images/610392/original.aspx" width=623 mce_src="http://blogs.technet.com/photos/paulelong/images/610392/original.aspx"&gt;&lt;/P&gt;
&lt;P&gt;The difference between this graph and the one above it is that in this case the packet loss is on the Up Stream side. So now the client does have to send retransmits, because now the server is complaining that data is missing to the client, instead of the other way around. So now the graph shows up inverted because data to the client can never fill up the window. Instead the client has to resend old data that has been lost. So this resets the UnACKed data to something lower than it was before. &lt;/P&gt;
&lt;H2&gt;56K Bandwidth Up and Down Stream &lt;/H2&gt;
&lt;P mce_keep="true"&gt;&lt;IMG style="WIDTH: 624px; HEIGHT: 420px" height=420 src="http://blogs.technet.com/photos/paulelong/images/610387/original.aspx" width=624 mce_src="http://blogs.technet.com/photos/paulelong/images/610387/original.aspx"&gt;&lt;/P&gt;
&lt;P&gt;The final example is to show the difference when bandwidth is reduced. This is similar to the baseline test, but the main difference is the time line below is much longer. For each SMB Write it takes around 10 seconds. Another difference is that since there is a RTT delay inherent in this connection, you don't see much overlap once we hit the window size. Basically every request has enough of a delay so the we see a acknowledgement before sending the next TCP segment. So we tend to stay right at the Window edge rather than fluctuating, like we do in the baseline test. &lt;/P&gt;
&lt;H1&gt;TCPPerf Macro Code &lt;/H1&gt;
&lt;P&gt;You should be able to copy this into Excel's Macro Editor. The one problem I can foresee is that if formatting in your browser causes the text to wrap, Excel will complain. So keep this in mind. &lt;/P&gt;
&lt;P&gt;A general overview of this code is that it copies the text from the clipboard and creates some columns to calculate UnACKed data and Advertised Window. We must also recalculate the Seq/Ack columns as there are not represented as numbers (they are numbers with hex in parens). Then we copy all the formulated data to another sheet so we can sort the resulting data. And finally we create a chart for the both sides of the conversation. &lt;/P&gt;
&lt;P&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;Sub TCPPerf()&lt;BR&gt;&amp;nbsp; ' TCPPerf Macro&lt;BR&gt;&lt;BR&gt;&amp;nbsp; Application.ScreenUpdating = False&lt;BR&gt;&amp;nbsp; Application.Calculation = xlManual&lt;BR&gt;&lt;BR&gt;&amp;nbsp; ' You can name your sheet different for multiple traces. The resulting&lt;BR&gt;&amp;nbsp; ' sheet is created based on this name.&lt;BR&gt;&amp;nbsp; CurSheet = ActiveSheet.Name&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;&amp;nbsp; ' Populate the column headers&lt;BR&gt;&amp;nbsp; [A1].Value = "Frame"&lt;BR&gt;&amp;nbsp; [B1].Value = "Time"&lt;BR&gt;&amp;nbsp; [C1].Value = "TCPSeqData"&lt;BR&gt;&amp;nbsp; [D1].Value = "TCPAckData"&lt;BR&gt;&amp;nbsp; [E1].Value = "Window"&lt;BR&gt;&amp;nbsp; [F1].Value = "Len"&lt;BR&gt;&amp;nbsp; [G1].Value = "ConvID"&lt;BR&gt;&amp;nbsp; [H1].Value = "Source"&lt;BR&gt;&amp;nbsp; [I1].Value = "Dest"&lt;BR&gt;&amp;nbsp; [J1].Value = "Prot"&lt;BR&gt;&amp;nbsp; [K1].Value = "Desc"&lt;BR&gt;&amp;nbsp; [L1].Value = "Seq"&lt;BR&gt;&amp;nbsp; [M1].Value = "Ack"&lt;BR&gt;&amp;nbsp; [N1].Value = "Unack"&lt;BR&gt;&amp;nbsp; [O1].Value = "SrcData"&lt;BR&gt;&amp;nbsp; [P1].Value = "DstData"&lt;BR&gt;&amp;nbsp;&amp;nbsp;[Q1].Value = "SrcWindow"&lt;BR&gt;&amp;nbsp; [R1].Value = "DstWindow"&lt;BR&gt;&amp;nbsp;&amp;nbsp;[S1].Value = "AdvertisedWindow"&lt;BR&gt;&lt;BR&gt;&amp;nbsp; ' Paste In Data from clipboard&lt;BR&gt;&amp;nbsp; Range("A2").Select&lt;BR&gt;&amp;nbsp; ActiveSheet.Paste&lt;BR&gt;&lt;BR&gt;&amp;nbsp; ' Find Last Row in Data and save in LastRow&lt;BR&gt;&amp;nbsp; Range("A2").Select&lt;BR&gt;&lt;BR&gt;&amp;nbsp; Selection.End(xlDown).Select&lt;BR&gt;&amp;nbsp; Dim LastRow As Integer&lt;BR&gt;&amp;nbsp; LastRow = ActiveCell.Row&lt;BR&gt;&lt;BR&gt;&amp;nbsp; ' Next take the text version of Seq/Ack from NM and convert to a number&lt;BR&gt;&amp;nbsp; Call SeqAckForm(LastRow)&lt;BR&gt;&lt;BR&gt;&amp;nbsp; ' Create a column for UnAck'd data populate with calculation&lt;BR&gt;&amp;nbsp; Call UnAckData(LastRow)&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;' Create a column that gets the Src/Dest Seq and Advertised Window data&lt;BR&gt;&amp;nbsp;&amp;nbsp;' depending on the sender.&lt;BR&gt;&amp;nbsp; Call SrcDestData(LastRow)&lt;BR&gt;&lt;BR&gt;&amp;nbsp; ' Since we diabled calculations, cause one to occur now before we&lt;BR&gt;&amp;nbsp; ' copy data around.&lt;BR&gt;&amp;nbsp; Calculate&lt;BR&gt;&lt;BR&gt;&amp;nbsp; ' Define the name of the sheet we'll use to build our chart from&lt;BR&gt;&amp;nbsp; DataSheetName = "TCPPerf_" + CurSheet&lt;BR&gt;&lt;BR&gt;&amp;nbsp; ' Transfer the data and calculated data to a new chart so we can sort.&lt;BR&gt;&amp;nbsp; Call TransferData(LastRow, CurSheet, DataSheetName)&lt;BR&gt;&lt;BR&gt;&amp;nbsp; ' Build two charts, one for each client/server&lt;BR&gt;&amp;nbsp; Call BuildCharts(LastRow, DataSheetName)&lt;BR&gt;&amp;nbsp; Application.Calculation = xlAutomatic&lt;BR&gt;&amp;nbsp; Application.ScreenUpdating = True&lt;BR&gt;&lt;BR&gt;End Sub&lt;BR&gt;&lt;BR&gt;Sub SeqAckForm(LastRow)&lt;BR&gt;'&lt;BR&gt;' SeqAckForm Macro&lt;BR&gt;'&lt;BR&gt;&amp;nbsp; ' Just cut off the number at the first space and convert to a Number.&lt;BR&gt;&amp;nbsp; [L2].Value = "=VALUE(MID(RC[-9], 1, FIND("" "", RC[-9])))"&lt;BR&gt;&amp;nbsp; Range("L2").Select&lt;BR&gt;&amp;nbsp; Selection.AutoFill Destination:=Range("L2:L" &amp;amp; LastRow), _&lt;BR&gt;&amp;nbsp; Type:=xlFillDefault&lt;BR&gt;&lt;BR&gt;&amp;nbsp; [M2].Value = "=VALUE(MID(RC[-9], 1, FIND("" "", RC[-9])))"&lt;BR&gt;&amp;nbsp; Range("M2").Select&lt;BR&gt;&amp;nbsp; Selection.AutoFill Destination:=Range("M2:M" &amp;amp; LastRow), _&lt;BR&gt;&amp;nbsp; Type:=xlFillDefault&lt;BR&gt;End Sub&lt;BR&gt;&lt;BR&gt;Sub SrcDestData(LastRow)&lt;BR&gt;&amp;nbsp; ' If the Source matches the first source, then take this seq, otherwise&lt;BR&gt;&amp;nbsp; ' take the last value found.&lt;BR&gt;&amp;nbsp; [O2].Value = "=IF(H2=H$2, O1, M2)"&lt;BR&gt;&amp;nbsp; Range("O2").Select&lt;BR&gt;&amp;nbsp; Selection.AutoFill Destination:=Range("O2:O" &amp;amp; LastRow), _&lt;BR&gt;&amp;nbsp; &amp;nbsp; Type:=xlFillDefault&lt;BR&gt;&lt;BR&gt;&amp;nbsp; ' If the Source matches the first dest, then take this seq, otherwise&lt;BR&gt;&amp;nbsp; ' take the last value we found.&lt;BR&gt;&amp;nbsp; [P2].Value = "=IF(H2=I$2, IF(P1&amp;lt;&amp;gt;0, P1, L2), M2)"&lt;BR&gt;&amp;nbsp; Range("P2").Select&lt;BR&gt;&amp;nbsp; Selection.AutoFill Destination:=Range("P2:P" &amp;amp; LastRow), _&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Type:=xlFillDefault&lt;BR&gt;&lt;BR&gt;&amp;nbsp; ' If the Source matches the first source, then take window to be the&lt;BR&gt;&amp;nbsp; ' src window, otherwise take the last value we found.&lt;BR&gt;&amp;nbsp; [Q2].Value = "=IF(H2=H$2, Q1, E2)"&lt;BR&gt;&amp;nbsp; Range("Q2").Select&lt;BR&gt;&amp;nbsp; Selection.AutoFill Destination:=Range("Q2:Q" &amp;amp; LastRow), _&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Type:=xlFillDefault&lt;BR&gt;&lt;BR&gt;&amp;nbsp; ' If the Source matches the first dest, then take window to be the&lt;BR&gt;&amp;nbsp; ' src window, otherwise take the last value we found.&lt;BR&gt;&amp;nbsp; [R2].Value = "=IF(H2=I$2, R1, E2)"&lt;BR&gt;&amp;nbsp; Range("R2").Select&lt;BR&gt;&amp;nbsp; Selection.AutoFill Destination:=Range("R2:R" &amp;amp; LastRow), _&lt;BR&gt;&amp;nbsp; Type:=xlFillDefault&lt;BR&gt;&lt;BR&gt;&amp;nbsp; ' Now get the advertised window size from the other side based on which&lt;BR&gt;&amp;nbsp; ' is the source address&lt;BR&gt;&amp;nbsp; [S2].Value = "=IF(H2=H$2, Q2, R2)"&lt;BR&gt;&amp;nbsp; Range("S2").Select&lt;BR&gt;&amp;nbsp; Selection.AutoFill Destination:=Range("S2:S" &amp;amp; LastRow), _&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Type:=xlFillDefault&lt;BR&gt;End Sub&lt;BR&gt;&lt;BR&gt;Sub UnAckData(LastRow)&lt;BR&gt;&amp;nbsp; ' Calculate the Unack'd data by looking at the seq/ack columns we created&lt;BR&gt;&amp;nbsp; ' before and the len field.&lt;BR&gt;&amp;nbsp; [N2].Value = _&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "=IF(IF(H2=H$2,L2+F2-O2,L2+F2-P2)&amp;lt;0,-1,IF(H2=H$2,L2+F2-O2,L2+F2-P2))"&lt;BR&gt;&amp;nbsp; Range("N2").Select&lt;BR&gt;&amp;nbsp; Selection.AutoFill Destination:=Range("N2:N" &amp;amp; LastRow), _&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Type:=xlFillDefault&lt;BR&gt;End Sub&lt;BR&gt;&lt;BR&gt;Sub TransferData(LastRow, OriginalSheetName, DataSheetName)&lt;BR&gt;' TransferData Macro&lt;BR&gt;'&lt;BR&gt;&amp;nbsp; ' Add a new sheet for new data and charts.&lt;BR&gt;&amp;nbsp; Sheets.Add&lt;BR&gt;&amp;nbsp; ActiveSheet.Name = DataSheetName&lt;BR&gt;&lt;BR&gt;&amp;nbsp; ' Copy all of the various columns we need from the original sheet.&lt;BR&gt;&amp;nbsp; ' This is done so that when we resort the data, we reference the&lt;BR&gt;&amp;nbsp; ' formula results.&lt;BR&gt;&lt;BR&gt;&amp;nbsp; Sheets(OriginalSheetName).Select&lt;BR&gt;&amp;nbsp; Range("B1:B" &amp;amp; LastRow).Copy&lt;BR&gt;&amp;nbsp; Sheets(DataSheetName).Select&lt;BR&gt;&amp;nbsp; Range("A1").Select&lt;BR&gt;&amp;nbsp; ActiveSheet.Paste&lt;BR&gt;&lt;BR&gt;&amp;nbsp; Sheets(OriginalSheetName).Select&lt;BR&gt;&amp;nbsp; Range("F1:F" &amp;amp; LastRow).Copy&lt;BR&gt;&amp;nbsp; Sheets(DataSheetName).Select&lt;BR&gt;&amp;nbsp; Range("C1").Select&lt;BR&gt;&amp;nbsp; ActiveSheet.Paste&lt;BR&gt;&lt;BR&gt;&amp;nbsp; Sheets(OriginalSheetName).Select&lt;BR&gt;&amp;nbsp;&amp;nbsp;Range("N1:N" &amp;amp; LastRow).Copy&lt;BR&gt;&amp;nbsp; Sheets(DataSheetName).Select&lt;BR&gt;&amp;nbsp; Range("D1").Select&lt;BR&gt;&amp;nbsp; Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, _&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SkipBlanks:=False, Transpose:=False&lt;BR&gt;&lt;BR&gt;&amp;nbsp; Sheets(OriginalSheetName).Select&lt;BR&gt;&amp;nbsp; Range("H1:H" &amp;amp; LastRow).Copy&lt;BR&gt;&amp;nbsp; Sheets(DataSheetName).Select&lt;BR&gt;&amp;nbsp; Range("E1").Select&lt;BR&gt;&amp;nbsp; ActiveSheet.Paste&lt;BR&gt;&lt;BR&gt;&amp;nbsp; Sheets(OriginalSheetName).Select&lt;BR&gt;&amp;nbsp; Range("L1:M" &amp;amp; LastRow).Copy&lt;BR&gt;&amp;nbsp; Sheets(DataSheetName).Select&lt;BR&gt;&amp;nbsp; Range("F1").Select&lt;BR&gt;&amp;nbsp; Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, _&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SkipBlanks:=False, Transpose:=False&lt;BR&gt;&lt;BR&gt;&amp;nbsp; Sheets(OriginalSheetName).Select&lt;BR&gt;&amp;nbsp; Range("A1:A" &amp;amp; LastRow).Copy&lt;BR&gt;&amp;nbsp; Sheets(DataSheetName).Select&lt;BR&gt;&amp;nbsp; Range("H1").Select&lt;BR&gt;&amp;nbsp; ActiveSheet.Paste&lt;BR&gt;&lt;BR&gt;&amp;nbsp; Sheets(OriginalSheetName).Select&lt;BR&gt;&amp;nbsp; Range("S1:S" &amp;amp; LastRow).Copy&lt;BR&gt;&amp;nbsp; Sheets(DataSheetName).Select&lt;BR&gt;&amp;nbsp; Range("B1").Select&lt;BR&gt;&amp;nbsp; Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, _&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SkipBlanks:=False, Transpose:=False&lt;BR&gt;&lt;BR&gt;&amp;nbsp; ' Now sort this data by Source so we can split and create 2 charts.&lt;BR&gt;&amp;nbsp; Range("A1:I" &amp;amp; LastRow).Select&lt;BR&gt;&amp;nbsp; Selection.Sort Key1:=Range("E2"), Order1:=xlAscending, Header:=xlGuess, _&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom, _&lt;BR&gt;&amp;nbsp; DataOption1:=xlSortNormal&lt;BR&gt;End Sub&lt;BR&gt;&lt;BR&gt;Sub BuildCharts(LastRow, MainSheetName)&lt;BR&gt;&amp;nbsp; ' Find where the source changes to destination.&lt;BR&gt;&amp;nbsp; Range("A1:G1").Copy&lt;BR&gt;&lt;BR&gt;&amp;nbsp; For Each Cell In Range("E2:E" &amp;amp; LastRow)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; If Cell.Value &amp;lt;&amp;gt; [E2] Then&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Exit For&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; End If&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Cell.Select&lt;BR&gt;&amp;nbsp; Next&lt;BR&gt;&lt;BR&gt;&amp;nbsp; ' Paste in the original column headers&lt;BR&gt;&amp;nbsp; CurCellRow = Selection.Row + 1&lt;BR&gt;&amp;nbsp; Range(CurCellRow &amp;amp; ":" &amp;amp; CurCellRow).Insert Shift:=xlDown&lt;BR&gt;&lt;BR&gt;&amp;nbsp; ' Create two names for each chart based on the the senders name.&lt;BR&gt;&amp;nbsp; ChartName1 = Range("E" &amp;amp; (CurCellRow - 1)).Value&lt;BR&gt;&amp;nbsp; ChartName2 = Range("E" &amp;amp; (CurCellRow + 2)).Value&lt;BR&gt;&amp;nbsp; Range("A1:D" &amp;amp; CurCellRow).Select&lt;BR&gt;&lt;BR&gt;&amp;nbsp; ' Now create a chart for each address.&lt;BR&gt;&amp;nbsp; Call Chart(1, CurCellRow - 1, ChartName1, MainSheetName)&lt;BR&gt;&amp;nbsp; Call Chart(CurCellRow, LastRow + 1, ChartName2, MainSheetName)&lt;BR&gt;End Sub&lt;BR&gt;&lt;BR&gt;Sub Chart(FirstRow, LastRow, Name, MainSheetName)&lt;BR&gt;&amp;nbsp; ' Set the range of the data we will use for our chart.&lt;BR&gt;&amp;nbsp; MinScale = Range(MainSheetName &amp;amp; "!A" &amp;amp; FirstRow + 1).Value&lt;BR&gt;&amp;nbsp; Sheets.Add&lt;BR&gt;&lt;BR&gt;&amp;nbsp; ' Create a Name for this chart and set teh active sheet to that name.&lt;BR&gt;&amp;nbsp; TopUsersChart1Sheet = "Chart_" + Name + CurSheet&lt;BR&gt;&amp;nbsp; ActiveSheet.Name = TopUsersChart1Sheet&lt;BR&gt;&lt;BR&gt;&amp;nbsp; ' Add in a new chart.&lt;BR&gt;&amp;nbsp; Charts.Add&lt;BR&gt;&amp;nbsp; ActiveChart.Location Where:=xlLocationAsObject, Name:=TopUsersChart1Sheet&lt;BR&gt;&amp;nbsp; ActiveChart.ChartType = xlXYScatterLines&lt;BR&gt;&amp;nbsp; ActiveChart.SetSourceData Source:= _&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Range(MainSheetName &amp;amp; "!$A" &amp;amp; FirstRow &amp;amp; ":$D" &amp;amp; LastRow)&lt;BR&gt;&lt;BR&gt;&amp;nbsp; ' Create a secondary access&lt;BR&gt;&amp;nbsp; ActiveChart.SeriesCollection(1).AxisGroup = 2&lt;BR&gt;&lt;BR&gt;&amp;nbsp; ' Set the min/max scale based on the time in the first/last row.&lt;BR&gt;&amp;nbsp; ActiveChart.Axes(xlCategory).MinimumScale = _&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Range(MainSheetName &amp;amp; "!A" &amp;amp; FirstRow + 1).Value&lt;BR&gt;&amp;nbsp; ActiveChart.Axes(xlCategory).MaximumScale = _&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Range(MainSheetName &amp;amp; "!A" &amp;amp; LastRow).Value&lt;BR&gt;&lt;BR&gt;&amp;nbsp; ' Make the min Y scale -1&lt;BR&gt;&amp;nbsp; ActiveChart.Axes(xlValue).MinimumScale = -1&lt;BR&gt;&lt;BR&gt;&amp;nbsp; ' Make the long time lables slant a bit.&lt;BR&gt;&amp;nbsp; ActiveChart.Axes(xlCategory).TickLabels.Orientation = -25&lt;BR&gt;End Sub&lt;BR&gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;BR&gt;
&lt;H1&gt;And Much More… &lt;/H1&gt;
&lt;P&gt;The general idea here is that you can take the TCP data and look at it in a graphic form to help you to see at a high level if there's a problem. There are so many other things that one could add. Resets could be added in to visually indicate those in the graph. You could also create other graphs to represent the seq/ack responses that would give you another view of the data. But hopefully this will give you a simple tool and some specific filters to spot check performance issues on your network. &lt;/P&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=610973" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/netmon/archive/tags/Filtering/default.aspx">Filtering</category><category domain="http://blogs.technet.com/netmon/archive/tags/Experts/default.aspx">Experts</category><category domain="http://blogs.technet.com/netmon/archive/tags/tshoot/default.aspx">tshoot</category></item><item><title>Part 1: Poor Man’s Expert Using Excel – Top Users</title><link>http://blogs.technet.com/netmon/archive/2006/11/30/part-1-poor-man-s-expert-using-excel-top-users.aspx</link><pubDate>Fri, 01 Dec 2006 01:36:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:536052</guid><dc:creator>PaulELong</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.technet.com/netmon/comments/536052.aspx</comments><wfw:commentRss>http://blogs.technet.com/netmon/commentrss.aspx?PostID=536052</wfw:commentRss><description>&lt;P&gt;One item we are evaluating for future versions of Network Monitor are experts. These are the tools that among other things, allow you to get a high level view of a problem. But using a simple new feature in the released version of NM3 will allow us to do some simple expert-like analysis. &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Cut and Paste of Multiple Frame Summaries &lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;NM3 allows you to select multiple frames, then right-click those frames and store the resulting output in the clipboard buffer. The resulting data is tab delimited and based on the columns you have showing in your frame summary. This is the key to creating simple experts with Excel. This TAB delimited data can be imported into Excel and manipulated to pull the information we want to summarize. &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;The Top Users Expert &lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;The idea of this simple expert is to display the chattiest machines on your network. So it basically sorts the Source/Destination/Protocol fields and provides a count of each. This expert provides the top users that send and receive data. It also shows a protocol usage, but only at the top most level. So while this may not be as useful as a count of all protocols used, this still may help show where most of your bandwidth is being used protocol wise. &lt;/P&gt;
&lt;P&gt;This expert can be useful to find a machine that is infected with a virus and attempting to pass that virus on to another machine. It can also identify a machine that is overloaded with requests and thus the center of a bottle neck. &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;How it works &lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;You start by selecting the frames you want in NM3. Then right click those frames and select Copy. You could also just type Ctrl+C to copy these frames into the clipboard. Next you run Excel and paste the data, starting at line number 2. This is so we can add column headers for the data. Then you create 3 pivot tables, one each for Source/Destination/Protocol. For each pivot table, you select the appropriate column for the row data and row count. Once you do this you can sort the data, and the count of the highest users appears at the top. &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Devil's in the Details &lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;So rather than explaining each step, I'll annotate a Macro I created to do this job. If you cut and paste this macro into Excel and run, it will copy the data in the clipboard, and create the column labels, and then create a new page with the 3 pivot tables. NOTE: the data is assumed to be in the default layout (Frame Number, Time Offset, ConvID, Source, Destination, Protocol Name, Description). If you have a different layout, you'll have to modify the columns section in this macro. &lt;/P&gt;
&lt;P&gt;This macro was created for Excel 2003. It should be easy to modify for future versions as well. In Excel 2003, I go to Tools, Macros. Then I typed in a name, TopUsers, and hit create. This gives me a blank macro, which you can populate with the following information. &lt;/P&gt;
&lt;P&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Courier New"&gt;&lt;BR&gt;Sub TopUsers()&lt;BR&gt;&amp;nbsp; ' This creates the text for each column heading&lt;BR&gt;&amp;nbsp; ' Match these to your column layout in NM3.&lt;BR&gt;&amp;nbsp; [A1].Value = "Frame"&lt;BR&gt;&amp;nbsp; [B1].Value = "Time"&lt;BR&gt;&amp;nbsp; [C1].Value = "ConvID" &lt;BR&gt;&amp;nbsp; [D1].Value = "Source"&lt;BR&gt;&amp;nbsp; [E1].Value = "Dest" &lt;BR&gt;&amp;nbsp; [F1].Value = "Protocol Name" &lt;BR&gt;&amp;nbsp; [G1].Value = "Description"&lt;BR&gt;&lt;BR&gt;&amp;nbsp; ' Now make Cell A2 the current one and Past the clipboard results into Excel. &lt;BR&gt;&amp;nbsp; Range("A2").Select&lt;BR&gt;&amp;nbsp; ActiveSheet.Paste &lt;BR&gt;&lt;BR&gt;&amp;nbsp; ' Get the range of all the data you've pasted in. &lt;BR&gt;&amp;nbsp; Dim CapRange As Range &lt;BR&gt;&amp;nbsp; Set CapRange = ActiveSheet.UsedRange&lt;BR&gt;&lt;BR&gt;&amp;nbsp; ' You can name your sheet different for multiple traces. The resulting &lt;BR&gt;&amp;nbsp; ' sheet is created based on this name. &lt;BR&gt;&amp;nbsp; CurSheet = ActiveSheet.Name &lt;BR&gt;&amp;nbsp; &lt;BR&gt;&amp;nbsp; ' Add a new sheet and define a variable for its name. Set it to the active sheet. &lt;BR&gt;&amp;nbsp; Sheets.Add &lt;BR&gt;&lt;BR&gt;&amp;nbsp; TopUsersSheet = "TopUsers_" + CurSheet &lt;BR&gt;&amp;nbsp; ActiveSheet.Name = TopUsersSheet&lt;BR&gt;&lt;BR&gt;&amp;nbsp; ' Create Source Pivot Table &lt;BR&gt;&amp;nbsp; ActiveWorkbook.PivotCaches.Add(SourceType:=xlDatabase, SourceData:= _ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CapRange).CreatePivotTable _ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; TableDestination:=TopUsersSheet + "!R3C1", TableName:="Source" &lt;BR&gt;&amp;nbsp; &lt;BR&gt;&amp;nbsp; ' Add Count of Source as xlCount of this Pivot Table. &lt;BR&gt;&amp;nbsp; ActiveSheet.PivotTables("Source").AddDataField ActiveSheet.PivotTables( _ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Source").PivotFields("Source"), "Count of Source", xlCount&lt;BR&gt;&lt;BR&gt;&amp;nbsp; ' Add Source as xlRowField of this Pivot Table. &lt;BR&gt;&amp;nbsp; With ActiveSheet.PivotTables("Source").PivotFields("Source") &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Orientation = xlRowField &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Position = 1 &lt;BR&gt;&amp;nbsp; End With &lt;BR&gt;&lt;BR&gt;&amp;nbsp; ' Sort data based on the Count.&lt;BR&gt;&amp;nbsp; ActiveSheet.PivotTables("Source").PivotFields("Source").AutoSort _ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; xlDescending, "Count of Source"&lt;BR&gt;&lt;BR&gt;&amp;nbsp; ' Create Dest Pivot Table, same as Source &lt;BR&gt;&amp;nbsp; ActiveWorkbook.PivotCaches.Add(SourceType:=xlDatabase, SourceData:= _ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CapRange).CreatePivotTable _&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; TableDestination:=TopUsersSheet + "!R3C4", TableName:="Dest" &lt;BR&gt;&lt;BR&gt;&amp;nbsp; ActiveSheet.PivotTables("Dest").AddDataField ActiveSheet.PivotTables( _ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Dest").PivotFields("Dest"), "Count of Dest", xlCount &lt;BR&gt;&lt;BR&gt;&amp;nbsp; With ActiveSheet.PivotTables("Dest").PivotFields("Dest")&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Orientation = xlRowField&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Position = 1 &lt;BR&gt;&amp;nbsp; End With &lt;BR&gt;&lt;BR&gt;&amp;nbsp; ActiveSheet.PivotTables("Dest").PivotFields("Dest").AutoSort _&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; xlDescending, "Count of Dest"&lt;BR&gt;&lt;BR&gt;&amp;nbsp; ' Create Prot Pivot Table Same as Source &lt;BR&gt;&lt;BR&gt;&amp;nbsp; ActiveWorkbook.PivotCaches.Add(SourceType:=xlDatabase, SourceData:= _ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CapRange).CreatePivotTable _ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; TableDestination:=TopUsersSheet + "!R3C7", TableName:="Protocols" &lt;BR&gt;&lt;BR&gt;&amp;nbsp; ActiveSheet.PivotTables("Protocols").AddDataField ActiveSheet.PivotTables( _ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Protocols").PivotFields("Protocol Name"), "Count of Prot", xlCount &lt;BR&gt;&lt;BR&gt;&amp;nbsp; With ActiveSheet.PivotTables("Protocols").PivotFields("Protocol Name") &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Orientation = xlRowField &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Position = 1 &lt;BR&gt;&amp;nbsp; End With &lt;BR&gt;&lt;BR&gt;&amp;nbsp; ActiveSheet.PivotTables("Protocols").PivotFields("Protocol Name").AutoSort _ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; xlDescending, "Count of Prot" &lt;BR&gt;&lt;BR&gt;&amp;nbsp; ' Label each of our tables.&lt;BR&gt;&amp;nbsp; [A2].Value = "Source Addresses"&lt;BR&gt;&amp;nbsp; [D2].Value = "Destination Addresses"&lt;BR&gt;&amp;nbsp; [G2].Value = "Top Protocols, highest level only" &lt;BR&gt;End Sub &lt;BR&gt;&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;&lt;STRONG&gt;Adding a Button for Flare &lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;To make things even easier to use, I added a button on the main page. All it does is call the TopUsers macro. So you just copy the data in NM3, and click the button in Excel. Magically, the new sheet is populated with the table showing you the top users. &lt;/P&gt;
&lt;P&gt;So to do this, I insert a picture. In my case I used an autoshape that looks like a rounded rectangle. But any picture will do, as long as you can assign a macro to it. To assign the macro, I just right clicked the shape and chose, Assign Macro. I also added some text to my rectangle like, "Copy Frame Summary in NM3 and then Click Here". &lt;/P&gt;
&lt;P style="TEXT-ALIGN: center" mce_keep="true"&gt;&lt;IMG style="WIDTH: 186px; HEIGHT: 104px" height=104 src="http://blogs.technet.com/photos/paulelong/images/536054/original.aspx" width=186 mce_src="http://blogs.technet.com/photos/paulelong/images/536054/original.aspx"&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;More to Come &lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;While this is a simplistic expert, it should be possible to create more complicated ones. NM3 allows you to add columns to the interface. The columns you can choose are based on properties exposed the by the parsers. And you can go one step further by adding properties to the parsers. Stay tuned for a more complex example!&lt;/P&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=536052" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/netmon/archive/tags/Experts/default.aspx">Experts</category><category domain="http://blogs.technet.com/netmon/archive/tags/tshoot/default.aspx">tshoot</category></item><item><title>NPL – The Power Behind the Parsers</title><link>http://blogs.technet.com/netmon/archive/2006/10/04/NPL-_1320_-The-Power-Behind-the-Parsers.aspx</link><pubDate>Thu, 05 Oct 2006 00:15:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:462117</guid><dc:creator>PaulELong</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.technet.com/netmon/comments/462117.aspx</comments><wfw:commentRss>http://blogs.technet.com/netmon/commentrss.aspx?PostID=462117</wfw:commentRss><description>&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;I always found it frustrating to use an application, only to find something didn’t work exactly like I expected it to.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And in the world of network sniffers, it seems that I always find a problem with a particular protocol or some output that I wish displayed a little differently.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;With Network Monitor 3.0, you have the ability to modify the source which describes the protocols!&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This in turn allows you to control what shows up in the frame summary and frame details.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And furthermore, allows you to define what is available for columns in the frame summary.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Did chills just go up your spine?&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;The NPL language resembles C++ mixed with IDL’ish (interface description language).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;For more complicated changes, this may not be for the faint of heart.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But as you might be a protocol geek, like me, the leap from understanding how protocols work to how NPL works may not be that big a stretch.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And for making simple changes, like summary line modifications, I think it’s in the grasp of most network Admins.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;So what can NPL do for me?&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;While I don’t intend this Blog entry to be a “How to Program in NPL in 5 minutes” I do want to give you an idea of the power in NPL, and perhaps peak your interest.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In future Blogs I do plan to highlight some of the details of NPL, but this will just be a taste.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;So here is a list of simple modifications you can make by changing the NPLs&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.75in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo1; tab-stops: list .75in"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;·&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;Fix a parser so it displays the network data correctly&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.75in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo1; tab-stops: list .75in"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;·&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;Create a new parser for your proprietary protocol&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.75in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo1; tab-stops: list .75in"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;·&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;Modify the summary description for your specific needs&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.75in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo1; tab-stops: list .75in"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;·&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;Add a new available column with some aggregated data&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.75in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo1; tab-stops: list .75in"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;·&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;Change the port a particular protocol uses&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;A common problem: “No silly, we do HTTP traffic on port 8888, not 80 or 8080!”&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;While changing port mappings for protocols could be something revealed in the user interface, we haven’t gotten that far in Network Monitor 3.0 yet.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I expect we should address this specific problem on different fronts, i.e. a UI for each protocol, and some way to handle dynamic port allocations.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And there are also some heuristics we can use to identify protocols as well.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But today, there is a fairly simple way to modify the NPL script for protocols on non-standard ports.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;NPL borrows a construct from C called a switch statement.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And while it has an overloaded syntax, the basics are the same.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;A switch statement works by taking a specific data field and then “switching” on different cases depending on the data field’s value.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So if the value is 100 you do one thing and if it’s 200 you do something else.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;In the context of our problem, making HTTP traffic appear on port 8888, the switch statement is used to decide which protocol to use based on the TCP port number defined.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So as you may imagine, TCP.NPL has a switch statement telling it what protocol to use next based on the protocol number defined in the TCP layer.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;So here it is, well part of it:&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 0.5in; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;switch(Port)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;case&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;20:&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;case&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;21:&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;FTP Ftp;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;case&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;23:&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;TELNET Telnet;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;…&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;case&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;80:&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;case 8080:&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Struct&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Switch&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Case AsciiString( FrameData, FrameOffset, 4 ) == "COPY":&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Case AsciiString( FrameData, FrameOffset, 4 ) == "LOCK":&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;…&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;OK, now I know you are probably saying, FTP looks straight forward and so does Telnet, but the stuff below ports 80 and 8080 is starting to look hairy.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Well, for our purposes we really don’t care about the info in the case statement.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;All we are going to do is add another port in the list after 80 and 8080.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And here it is…&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;case&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;80:&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;case 8080:&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;case 8888:&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;Struct&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;The way the case statement works is that if any of the values (80, 8080, or 8888) match; it will execute the code directly underneath it until the next case.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Technically in NPL you only have one statement per set of cases, and in this case the “Struct”.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;Once you make the change and save TCP.NPL, just go to the Tools Menu and select Reload Parsers.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Once the reload finishes you can reload your trace and now any traffic on port 8888 can be parsed as HTTP.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;Can I get a column to display the TCP Sequence Number?&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;You can probably create a column to display anything you want.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;You simply define a property in NPL, and it will be available to you in the UI in the column chooser once you rebuild the parsers.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;A property is simply a variable that is not part of the traced data.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So in this case we are going to create a property that stores the TCP sequence number.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;[MyNewTCPSeqNumber]&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;UINT32 SequenceNumber;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;The “UINT32 SequenceNumber;” was already there so all we added was the “[MyNewTCPSeqNumber]” line.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The way the “[ ]” bracket section works it that it always applies the line right below/next to it.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;And you can enter multiple statements separated by commas.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In this simple case you type a property name and the value of the property is set based on how SequenceNumber is displayed.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The display of SequenceNumber is based on the default for UINT32, but I’ll leave the details of that for some other discussion.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;So, you could get even fancier by using FormatString.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;[MyNewTCPSeqNumber = FormatString(“Seq = %d”, SequenceNumber)]&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;UINT32 SequenceNumber;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;Since the column name is already MyNewSequenceNumber, this is a bit of overkill, but I wanted to show you a simple example of FormatString. This way you can contrive any kind of complex data you want for your column data.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;In TCP.NPL we already have defined a property called “TCPSeqNumber” for.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;But feel free to change this to something else, or add another property by using a comma to separate them.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;[&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;MyNewTCPSeqNumber,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;TCPSeqNumber&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;]&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;UINT32 SequenceNumber;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;Conclusion&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"&gt;This should give you a feeling for the power that NPL can pack.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If your interest is peaked and you want to learn more, you can start with the ParserLanguage.doc included with Network Monitor 3.0.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I’m sure folks will find interesting ways to extend our parsers, as well as write their own.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In fact there’s no reason you couldn’t write a parser for something other than network data, given you could get your data in the Network Monitor file format.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The possibilities are endless.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=462117" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/netmon/archive/tags/NPL/default.aspx">NPL</category><category domain="http://blogs.technet.com/netmon/archive/tags/Experts/default.aspx">Experts</category></item></channel></rss>