{"id":8793,"date":"2024-06-24T13:09:01","date_gmt":"2024-06-24T20:09:01","guid":{"rendered":"https:\/\/visualgdb.com\/w\/?p=8793"},"modified":"2024-06-24T13:11:58","modified_gmt":"2024-06-24T20:11:58","slug":"using-software-tracing-to-record-network-packets-on-stm32","status":"publish","type":"post","link":"https:\/\/visualgdb.com\/tutorials\/tracing\/embedded\/http\/","title":{"rendered":"Using Software Tracing to Record Network Packets on STM32"},"content":{"rendered":"<p>This tutorial shows how to use VisualGDB&#8217;s Software Tracing feature to analyze the real-time behavior of a simple HTTP server running on the STMF7-Discovery board. We will first trace the DHCP logic, quickly showing which functions are being called, then will modify the tracepoints to record the incoming and outgoing DHCP packets, and will finally show how to use tracing to record the URLs of all pages requested by the HTTP client.<\/p>\n<p>Before you begin, install VisualGDB 6.0 or later.<\/p>\n<ol>\n<li>Start Visual Studio and open the VisualGDB Embedded Project Wizard:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/01-emb.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8767\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/01-emb.png\" alt=\"\" width=\"1014\" height=\"675\" \/><\/a><\/li>\n<li>Enter the name and location of your project:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/02-prjname-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8794\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/02-prjname-1.png\" alt=\"\" width=\"1014\" height=\"675\" \/><\/a><\/li>\n<li>Select the default options (new embedded application -&gt; Advanced CMake):<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/03-cmake-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8795\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/03-cmake-1.png\" alt=\"\" width=\"886\" height=\"693\" \/><\/a><\/li>\n<li>Select the latest ARM toolchain and pick your device:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/04-dev.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8796\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/04-dev.png\" alt=\"\" width=\"886\" height=\"693\" \/><\/a><\/li>\n<li>On the next page pick <strong>STM32CubeMX Samples-&gt;LwIP-&gt;LwIP_HTTP_Server_Netconn_RTOS<\/strong>:<br \/>\n<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/05-lwip.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8797\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/05-lwip.png\" alt=\"\" width=\"1231\" height=\"795\" \/><\/a><\/li>\n<li>Finally, configure the debugging settings and click &#8220;Finish&#8221; to create the project:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/06-stlink-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8798\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/06-stlink-1.png\" alt=\"\" width=\"947\" height=\"693\" \/><\/a><\/li>\n<li>Press F5 to build the project and start debugging it. Once it obtains an IP address from the DHCP server, try opening it in the browser. If everything goes well, you should see the following page:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/07-tcp.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8799\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/07-tcp.png\" alt=\"\" width=\"1164\" height=\"647\" \/><\/a><\/li>\n<li>Now we will show how to use Software Tracing to see what functions are running on the target, and record the details of their execution. Open the <strong>Debug-&gt;Windows-&gt;Tracepoints<\/strong> window, type &#8220;dhcp&#8221; in the filter, select all functions (Ctrl+A) and press space to trace all of them:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/08-dhcp.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8800\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/08-dhcp.png\" alt=\"\" width=\"1231\" height=\"795\" \/><\/a><\/li>\n<li>In order to avoid any memory overhead, VisualGDB didn&#8217;t reserve any memory for the trace data before we set the first tracepoint, so you would need to restart the debug session to begin tracing:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/09-start.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8801\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/09-start.png\" alt=\"\" width=\"1231\" height=\"795\" \/><\/a>You can configure this behavior (i.e. always reserve tracing memory) via <strong>VisualGDB Project Properties -&gt; Software Tracing<\/strong>.<\/li>\n<li>Once the debug session is started again, VisualGDB will show that <strong>dhcp_fine_tmr()<\/strong> is running all the time, while functions like <strong>dhcp_recv()<\/strong> executed a couple of times and stopped:<br \/>\n<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/10-tracepoints.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8802\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/10-tracepoints.png\" alt=\"\" width=\"1231\" height=\"795\" \/><\/a><\/li>\n<li>Select the tracepoint for <strong>dhcp_recv()<\/strong> and configure it to record <strong>addr-&gt;addr<\/strong> as <strong>IP Address<\/strong> and <strong>port <\/strong>as <strong>UInt16<\/strong>:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/11-data.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8803\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/11-data.png\" alt=\"\" width=\"1231\" height=\"795\" \/> <\/a><\/li>\n<li>Also enable recording of <strong>p-&gt;payload<\/strong> as a dynamic array of <strong>[p-&gt;len]<\/strong> elements: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/12-len.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8804\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/12-len.png\" alt=\"\" width=\"1231\" height=\"795\" \/><\/a><\/li>\n<li>Click <strong>Apply<\/strong> and VisualGDB will automatically patch the trace program in the FLASH memory:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/14-patch.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8805\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/14-patch.png\" alt=\"\" width=\"1231\" height=\"795\" \/><\/a><\/li>\n<li>We can also record the specific DHCP options contained in the packets. It will be redundant since we are already recording entire packets, but will allow seeing what is going on quicker. Set a tracepoint in the option byte check in <strong>dhcp_parse_reply()<\/strong> and set it to record <strong>op<\/strong>:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/15-op.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8806\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/15-op.png\" alt=\"\" width=\"1231\" height=\"795\" \/><\/a><\/li>\n<li>Similarly,record <strong>dhcp_option()<\/strong> to keep a track of the options in the outgoing packet:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/16-op2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8807\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/16-op2.png\" alt=\"\" width=\"1231\" height=\"795\" \/><\/a><\/li>\n<li>Place another tracepoint in <strong>dhcp_bind()<\/strong> after it has computed the address of <strong>struct dhcp<\/strong> and record all fields of it:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/17-bound.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8808\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/17-bound.png\" alt=\"\" width=\"1231\" height=\"795\" \/><\/a><\/li>\n<li>Reconnect the network cable to force another DHCP communication and check the traced events. Select all of them and click &#8220;Export selected events&#8221;:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/18-export.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8809\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/18-export.png\" alt=\"\" width=\"1231\" height=\"795\" \/><\/a>VisualGDB will produce a text file with records showing the incoming and outgoing DHCP communication:\n<pre>=== udp_sendto_if_src ===\r\n    p = {...}\r\n        len = 308\r\n    payload = 0x2004808c [01 01 06 00 ... 00]\r\n    dst_ip = 0x08022910\r\n        addr = 255.255.255.255\r\n    dst_port = 67\r\n=== dhcp_recv ===\r\n    p = {...}\r\n        len = 576\r\n        payload = 0x20003862 [02 01 06 00 ... 00]\r\n    addr = {...}\r\n        addr = 192.168.0.2\r\n    port = 67\r\n=== Parse option ===\r\n    op = 53\r\n=== Parse option ===\r\n    op = 51\r\n=== Parse option ===\r\n    op = 54\r\n=== Parse option ===\r\n    op = 1\r\n=== Parse option ===\r\n    op = 3<\/pre>\n<p>In this example, you see how the server (192.168.0.2) sent a packet containing the <strong>Msg Type (53)<\/strong>, <strong>Address Time (51)<\/strong>, <strong>DHCP Server ID (54)<\/strong>,<strong> Subnet Mask (1)<\/strong> and <strong>Router (3)<\/strong> options. We did not record the value of each option in this example, but it can be easily done by adding another tracepoint.<\/li>\n<li>You can also let VisualGDB create tables with the data from relevant tracepoints. Create a new table view as shown below:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/19-newview.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8810\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/19-newview.png\" alt=\"\" width=\"1231\" height=\"795\" \/><\/a><\/li>\n<li>Drag the option values from the tracepoints recording them into one column, then add another column for the incoming\/outgoing packet length, and yet another one for DHCP state. VisualGDB will show the same information in a more compact form:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/20-options.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8811\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/20-options.png\" alt=\"\" width=\"1231\" height=\"795\" \/><\/a><\/li>\n<li>Click the &#8220;export tracepoint set&#8221; button on the toolbar and enter a name for the set. VisualGDB will save the tracepoints (with their configuration) and remove them from the list:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/21-export.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8812\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/21-export.png\" alt=\"\" width=\"1231\" height=\"795\" \/><\/a>Next time you want to trace DHCP logic, you can simply import the tracepoint set via the context menu.<\/li>\n<li>Now we will show how to record the URLs of all pages requested by the HTTP clients. Go to <strong>http_server_serve()<\/strong>, set a tracepoint on the first URL comparison and record <strong>buf<\/strong> as a null-terminated string:<br \/>\n<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/22-buf.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8813\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/22-buf.png\" alt=\"\" width=\"1231\" height=\"795\" \/><\/a><\/li>\n<li>Refresh the page and observe how VisualGDB recorded new events. Then, create another table view:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/23-newview.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8814\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/23-newview.png\" alt=\"\" width=\"1231\" height=\"795\" \/><\/a><\/li>\n<li>Drag the [string] value from one of the events into the bottom part of the view and VisualGDB will display a table containing all requests recorded by the tracing logic:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/24-rqlist.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8815\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/24-rqlist.png\" alt=\"\" width=\"1231\" height=\"795\" \/><\/a>You can record any other information together with the request as well (e.g. remote IP address, exact timestamp, etc.) to get a detailed view of what the firmware is doing without ever having to stop it.<\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial shows how to use VisualGDB&#8217;s Software Tracing feature to analyze the real-time behavior of a simple HTTP server<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[247],"tags":[101,204,249],"_links":{"self":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/8793"}],"collection":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/comments?post=8793"}],"version-history":[{"count":4,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/8793\/revisions"}],"predecessor-version":[{"id":8887,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/8793\/revisions\/8887"}],"wp:attachment":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/media?parent=8793"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/categories?post=8793"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/tags?post=8793"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}