{"id":577,"date":"2016-04-07T11:23:57","date_gmt":"2016-04-07T11:23:57","guid":{"rendered":"http:\/\/nenadnoveljic.com\/blog\/?p=577"},"modified":"2018-05-17T16:16:10","modified_gmt":"2018-05-17T16:16:10","slug":"emulex-hba-driver-performance-analysis-packet-flow","status":"publish","type":"post","link":"https:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-analysis-packet-flow\/","title":{"rendered":"Emulex HBA Driver Performance Analysis (2) \u2013 Packet Flow"},"content":{"rendered":"<h1>Introduction<\/h1>\n<p>In the <a href=\"http:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-measuring-latency\/\">previous\u00a0installment<\/a>\u00a0I described how to measure end-to-end latency on the HBA device driver. In this article I&#8217;ll explore the workflow within the Emulex HBA driver code. Since I couldn&#8217;t find any documentation on Internet I used DTrace and the driver&#8217;s source code to figure this out.<\/p>\n<h1>Stack Fishing<\/h1>\n<p>First, the call stacks will be collected to get an initial idea about the packet\u00a0processing workflow\u00a0in the code. In the <a href=\"http:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-measuring-latency\/\">previous post<\/a>\u00a0we learned which modules participate in the I\/O processing (emlxs, fbt and fcp):<\/p>\n<pre><code>dtrace -n 'fbt:emlxs::entry,fbt:scsi::entry,fbt:fctl::entry,fbt:fcp::entry { @[stack()] = count(); }'<\/code><\/pre>\n<p>Three different types of stack can be identified for processing the following stages of the I\/O life-cycle: I\/O start, I\/O done and I\/O interrupt handling.<\/p>\n<h2>I\/O Start Stack<\/h2>\n<p>The I\/O start stack can be recognized by the functions like scsi_transport and scsi_start:<\/p>\n<pre><code>[...truncated...]\r\nemlxs`emlxs_sli4_bde_setup+0x233\r\nemlxs`emlxs_sli4_prep_fcp_iocb+0x10a\r\nemlxs`emlxs_send_fcp_cmd+0x137\r\nemlxs`emlxs_fca_transport+0x256\r\nfctl`fc_ulp_transport+0x22a\r\nfcp`fcp_transport+0x27\r\n<span style=\"color: #ff0000;\">fcp`fcp_scsi_start<\/span>+0x149\r\n<span style=\"color: #ff0000;\">scsi`scsi_transport<\/span>+0x233\r\nscsi_vhci`vhci_scsi_start+0x45d\r\n<span style=\"color: #ff0000;\">scsi`scsi_transport<\/span>+0x2b2\r\nsd`sd_start_cmds+0x34f\r\nsd`sd_core_iostart+0x186\r\nsd`sd_mapblockaddr_iostart+0x1ef\r\nsd`sd_xbuf_strategy+0x4e\r\nsd`xbuf_iostart+0x1e2\r\nsd`ddi_xbuf_qstrategy+0xd7\r\nsd`sdstrategy+0x175\r\ngenunix`bdev_strategy+0x66\r\ngenunix`ldi_strategy+0x56\r\nzfs`vdev_disk_strategy+0x158\r\n[...truncated...]<\/code><\/pre>\n<h2>I\/O Done Stack<\/h2>\n<p>The I\/O done stack can be recognized by the functions *destroy_pkt and\u00a0*uninit_packet:<\/p>\n<pre><code>[...truncated...]\r\n<span style=\"color: #ff0000;\">fctl`fc_ulp_uninit_packet<\/span>+0x2f\r\nfcp`fcp_pkt_teardown+0x8b\r\n<span style=\"color: #ff0000;\">scsi`scsi_cache_destroy_pkt<\/span>+0x46\r\n<span style=\"color: #ff0000;\">scsi`scsi_destroy_pkt<\/span>+0x21\r\n<span style=\"color: #ff0000;\">scsi_vhci`vhci_scsi_destroy_pkt<\/span>+0x2f\r\n<span style=\"color: #ff0000;\">scsi`scsi_destroy_pkt<\/span>+0x21\r\nsd`sd_destroypkt_for_buf+0x20\r\nsd`sd_return_command+0x17c\r\nsd`sdintr+0x584\r\nscsi`scsi_hba_pkt_comp+0x293\r\nscsi_vhci`vhci_intr+0x7df\r\nscsi`scsi_hba_pkt_comp+0x293\r\nfcp`fcp_post_callback+0x19\r\nfcp`fcp_cmd_callback+0x72\r\nemlxs`emlxs_handle_fcp_event+0x9fa\r\nemlxs`emlxs_proc_channel_event+0x647\r\nemlxs`emlxs_proc_channel+0x62\r\nemlxs`emlxs_thread+0x169\r\nunix`thread_start+0x8\r\n[...truncated...]<\/code><\/pre>\n<h2>Interrupt Stack<\/h2>\n<p>The interrupt handler can be recognized by the function switch_sp_and_call which is the solaris Kernel function for dispatching interrupts (see <a href=\"http:\/\/mishrasdiary.blogspot.ch\/2009\/03\/solaris-apic-implementation-with.html\">this blog post by Saurabh Mishra<\/a>):<\/p>\n<pre><code>[...truncated...]\r\nemlxs`emlxs_mem_put+0x9d\r\nemlxs`emlxs_sli4_free_xri+0xe1\r\nemlxs`emlxs_sli4_process_wqe_cmpl+0xff\r\nemlxs`emlxs_sli4_process_cq+0x139\r\nemlxs`emlxs_sli4_process_eq+0xda\r\n<span style=\"color: #ff0000;\">emlxs`emlxs_sli4_msi_intr<\/span>+0x7f\r\napix`apix_dispatch_by_vector+0x89\r\napix`apix_dispatch_lowlevel+0x32\r\n<span style=\"color: #ff0000;\">unix`switch_sp_and_call<\/span>+0x13\r\n[...truncated...]<\/code><\/pre>\n<p>The first Emulex device driver&#8217;s function on the stack is emlxs_sli4_msi_intr, which should be the interrupt handler. According to the manual\u00a0<a href=\"https:\/\/docs.oracle.com\/cd\/E36784_01\/html\/E36860\/fvzqn.html#scrolltoc\" target=\"_blank\">Writing Device Drivers for Oracle\u00ae Solaris 11.2<\/a> , the device driver&#8217;s interrupt handler must be registered in the driver&#8217;s attach entry point. This can be confirmed by looking into the source code:<\/p>\n<pre><code>emlxs_hba.c:\r\nemlxs_msi_add(emlxs_hba_t *hba)\r\n{\r\n[...truncated...]\r\n ret =\r\n   ddi_intr_add_handler(htable[i], EMLXS_SLI_MSI_INTR,\r\n     (char *)hba, (char *)((unsigned long)i));\r\n[...truncated...]\r\n\r\nemlxs_fc.h:\r\n#define      EMLXS_INTR_ADD(_hba)    emlxs_msi_add(_hba)\r\n#define      EMLXS_SLI_MSI_INTR      (hba-&gt;sli_api.sli_msi_intr)\r\n#define\u00a0\u00a0\u00a0\u00a0\u00a0 EMLXS_SLI_ONLINE\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0(hba-&gt;sli_api.sli_online)\r\n\r\nemlxs_sli4.c:\r\nemlxs_sli4_online(emlxs_hba_t *hba)\r\n{\r\n...\r\n...\r\nif (EMLXS_INTR_ADD(hba) != DDI_SUCCESS) {\r\n...\r\n\r\nemlxs_sli_api_t emlxs_sli4_api = {\r\n...\r\n        emlxs_sli4_online,\r\n...\r\n        emlxs_sli4_msi_intr,\r\n...};\r\n\r\nemlxs_hba.c:\r\nhba-&gt;sli_api = emlxs_sli4_api;\r\n<\/code><\/pre>\n<h1>Workflow<\/h1>\n<p>The following model\u00a0of the workflow can be deduced from the findings above:<\/p>\n<p>I\/O start -&gt;\u00a0I\/O interrupt handler -&gt; I\/O complete<\/p>\n<p>As for the next step, we will build a DTrace script to verify this assumption. The DTrace script will follow a single packet through the hba driver&#8217;s execution workflow. To be able to do this, we have to identify one function on each stack which fullfils the following requirements:<br \/>\n&#8211; the packet can be unambigously identified by one of the arguments,<br \/>\n&#8211; the function gets executed once and only once for each I\/O operation.<br \/>\nFor the IO start and stop stacks these functions and arguments have already been identified in the <a href=\"http:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-measuring-latency\/\">previous blog post<\/a> (I&#8217;ve chosen the address of the pkt variable as\u00a0the key for the associative arrays used to track the packet across different threads):<\/p>\n<pre><code>fctl.c:fc_ulp_transport(opaque_t port_handle, fc_packet_t *pkt)\r\nfctl.c:fc_ulp_uninit_packet(opaque_t port_handle, fc_packet_t *pkt)<\/code><\/pre>\n<p>The same is required for the I\/O interrupt stack. First, it makes sense to find out which functions on the I\/O interrupt stack get executed for each I\/O . This can be done by counting function calls and comparing them with the number of exections of fc_<wbr \/>ulp_transport, for which we already know that gets fired for each I\/O operation:<\/p>\n<pre><code>dtrace -n 'fbt:emlxs::entry,fbt:fctl:fc_ulp_transport:entry { @[probefunc] = count(); }'\r\n[...truncated...]\r\nemlxs_sli4_free_xri          39334\r\n[...truncated...]\r\n<span style=\"color: #ff0000;\">emlxs_sli4_process_wqe_cmpl  39334<\/span>\r\n[...truncated...]\r\n<span style=\"color: #ff0000;\">fc_ulp_transport             39334<\/span>\r\n[...truncated...]\r\nemlxs_mem_put                39340\r\n[...truncated...]\r\nemlxs_sli4_cqid_to_index     39828\r\nemlxs_sli4_msi_intr          39828\r\nemlxs_sli4_process_cq        39828\r\nemlxs_sli4_process_eq        39828\r\n[...truncated...]\r\n<\/code><\/pre>\n<p>emlxs_sli4_process_wqe_cmpl is the first function on the stack which executes for each I\/O operation. At the first glance,\u00a0it&#8217;s arguments don&#8217;t look promising:<\/p>\n<pre><code>emlxs_sli4.c: \r\nemlxs_sli4_process_wqe_cmpl(emlxs_hba_t *hba, CQ_DESC_t *cq, CQE_CmplWQ_t *cqe)<\/code><\/pre>\n<p>I&#8217;ll examine the first couple of lines in the source code:<\/p>\n<pre><code>   emlxs_buf_t *sbp;\r\n[...truncated...]\r\n  request_tag = cqe-&gt;RequestTag;\r\n[...truncated...]\r\n  sbp = hba-&gt;fc_table[request_tag];\r\n<\/code><\/pre>\n<p>cq is some structure that gets passed to the function\u00a0for each I\/O. It contains emlxs_buf_t *sbp<br \/>\nwhich looks like the buffer which is likely to remain the same during the entire life-cycle of the packet. Let&#8217;s examine the structure of this buffer:<\/p>\n<pre><code>emlxs_fc.h\r\n[...truncated...]\r\ntypedef struct emlxs_buf\r\n{\r\n  fc_packet_t      *pkt;   \/* scsi_pkt reference *\/\r\n[...truncated...]<\/code><\/pre>\n<p>Bingo! The buffer variable contains the reference to the scsi packet variable which can be used as the key for the associative arrays which store the timing information when the packet gets processed\u00a0in\u00a0\u00a0different threads. By looking at the code above, we can deduce how to dereference the pointer to pkt in the DTrace entry probe of the emlxs_sli4_process_wqe_cmpl function:<\/p>\n<pre><code>(int64_t)args[0]-&gt;fc_table[args[2]-&gt;RequestTag]-&gt;pkt<\/code><\/pre>\n<p>Now, all the information is there to build the emlxssnoop.d script which will be used to verify the assumption about the packet flow I made previously:<\/p>\n<pre><code>#!\/usr\/sbin\/dtrace -Cs\r\n\r\n\/* emlxssnoop.d *\/\r\n\r\n#pragma D option quiet\r\n\u00a0\r\n#define PRINT_PKT(pkt,milestone) \\\r\n\u00a0 printf(\"%d %-18d %-15s %-15s \\n\",timestamp,pkt,milestone,probefunc)\r\n\u00a0\r\nfbt::fc_ulp_transport:entry\r\n{\r\n\u00a0 PRINT_PKT(arg1,\"START\");\r\n}\r\n\u00a0\r\nfbt::emlxs_sli4_process_wqe_cmpl:entry\r\n{\r\n\u00a0 PRINT_PKT((int64_t)args[0]-&gt;fc_table[args[2]-&gt;RequestTag]-&gt;pkt,\"INTERRUPT\");\r\n}\r\n\u00a0\r\nfbt::fc_ulp_uninit_packet:entry\r\n{\r\n\u00a0 PRINT_PKT(arg1,\"DONE\");\r\n}<\/code><\/pre>\n<p>By running the script with the command below, we get the timestamp at each processing stage for each packet in the output file emlxssnoop.log:<\/p>\n<pre><code>dtrace -Cs emlxssnoop.d &gt; emlxssnoop.log<\/code><\/pre>\n<p>We can pick any buffer (for example 67553736358984) and then sort the output on the timestamp to see that the packet flows through the driver code in the assumed order:<\/p>\n<pre><code>grep 67553736358984 emlxssnoop.log | sort \r\n[...truncated...]\r\n<span style=\"color: #0000ff;\">26733383288531382 -67553736358984  START        fc_ulp_transport\r\n26733383294539371 -67553736358984  INTERRUPT    emlxs_sli4_process_wqe_cmpl\r\n26733383294605233 -67553736358984  DONE         fc_ulp_uninit_packet\r\n<\/span><span style=\"color: #ff6600;\">26733383479942799 -67553736358984  START        fc_ulp_transport\r\n26733383480366376 -67553736358984  INTERRUPT    emlxs_sli4_process_wqe_cmpl\r\n26733383480393173 -67553736358984  DONE         fc_ulp_uninit_packet<\/span>\r\n<span style=\"color: #0000ff;\">26733383491508798 -67553736358984  START        fc_ulp_transport\r\n26733383491570635 -67553736358984  INTERRUPT    emlxs_sli4_process_wqe_cmpl\r\n26733383491623284 -67553736358984  DONE         fc_ulp_uninit_packet\r\n<\/span>[...truncated...]<\/code><\/pre>\n<h1>Conclusion<\/h1>\n<p>In this installment we learned which threads participate in the processing of packets and in which order they process them: start, interrupt and done. I offered the method for testing the model. By doing so, the foundation is laid for further exploring of the\u00a0internal functioning of the Emulex driver.<\/p>\n<p>In the next blog post, I&#8217;ll describe the methodology and provide the scripts for measuring the elapsed time per packet\u00a0during different stages of the I\/O, which is the key point for\u00a0analysing the driver performance.<\/p>\n<p>Stay tuned!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The blog post describes how to explore the SCSI packet flow through different processing stages in the Emulex HBA driver. <a href=\"https:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-analysis-packet-flow\/\" class=\"more-link\">Continue Reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"footnotes":""},"categories":[24,15,14],"tags":[],"class_list":["post-577","post","type-post","status-publish","format-standard","hentry","category-dtrace","category-emulex","category-solaris"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Emulex HBA Driver Performance Analysis (2) \u2013 Packet Flow - All-round Database Topics<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-analysis-packet-flow\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Emulex HBA Driver Performance Analysis (2) \u2013 Packet Flow - All-round Database Topics\" \/>\n<meta property=\"og:description\" content=\"The blog post describes how to explore the SCSI packet flow through different processing stages in the Emulex HBA driver. Continue Reading &rarr;\" \/>\n<meta property=\"og:url\" content=\"https:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-analysis-packet-flow\/\" \/>\n<meta property=\"og:site_name\" content=\"All-round Database Topics\" \/>\n<meta property=\"article:published_time\" content=\"2016-04-07T11:23:57+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2018-05-17T16:16:10+00:00\" \/>\n<meta name=\"author\" content=\"Nenad Noveljic\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@NenadNoveljic\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Nenad Noveljic\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/emulex-hba-driver-performance-analysis-packet-flow\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/emulex-hba-driver-performance-analysis-packet-flow\\\/\"},\"author\":{\"name\":\"Nenad Noveljic\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/#\\\/schema\\\/person\\\/51458d9dd86dbbdd19f5add451d44efa\"},\"headline\":\"Emulex HBA Driver Performance Analysis (2) \u2013 Packet Flow\",\"datePublished\":\"2016-04-07T11:23:57+00:00\",\"dateModified\":\"2018-05-17T16:16:10+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/emulex-hba-driver-performance-analysis-packet-flow\\\/\"},\"wordCount\":796,\"commentCount\":0,\"articleSection\":[\"DTrace\",\"Emulex\",\"Solaris\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/emulex-hba-driver-performance-analysis-packet-flow\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/emulex-hba-driver-performance-analysis-packet-flow\\\/\",\"url\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/emulex-hba-driver-performance-analysis-packet-flow\\\/\",\"name\":\"Emulex HBA Driver Performance Analysis (2) \u2013 Packet Flow - All-round Database Topics\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/#website\"},\"datePublished\":\"2016-04-07T11:23:57+00:00\",\"dateModified\":\"2018-05-17T16:16:10+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/#\\\/schema\\\/person\\\/51458d9dd86dbbdd19f5add451d44efa\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/emulex-hba-driver-performance-analysis-packet-flow\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/emulex-hba-driver-performance-analysis-packet-flow\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/emulex-hba-driver-performance-analysis-packet-flow\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Emulex HBA Driver Performance Analysis (2) \u2013 Packet Flow\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/\",\"name\":\"All-round Database Topics\",\"description\":\"Nenad Noveljic\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/#\\\/schema\\\/person\\\/51458d9dd86dbbdd19f5add451d44efa\",\"name\":\"Nenad Noveljic\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/a97b796613ea48ec8a7b79c8ffe1c685dcffc920c68121f6238d5caab5070670?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/a97b796613ea48ec8a7b79c8ffe1c685dcffc920c68121f6238d5caab5070670?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/a97b796613ea48ec8a7b79c8ffe1c685dcffc920c68121f6238d5caab5070670?s=96&d=mm&r=g\",\"caption\":\"Nenad Noveljic\"},\"sameAs\":[\"nenad-noveljic-9b746a6\",\"https:\\\/\\\/x.com\\\/NenadNoveljic\"],\"url\":\"https:\\\/\\\/nenadnoveljic.com\\\/blog\\\/author\\\/nenad\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Emulex HBA Driver Performance Analysis (2) \u2013 Packet Flow - All-round Database Topics","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-analysis-packet-flow\/","og_locale":"en_US","og_type":"article","og_title":"Emulex HBA Driver Performance Analysis (2) \u2013 Packet Flow - All-round Database Topics","og_description":"The blog post describes how to explore the SCSI packet flow through different processing stages in the Emulex HBA driver. Continue Reading &rarr;","og_url":"https:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-analysis-packet-flow\/","og_site_name":"All-round Database Topics","article_published_time":"2016-04-07T11:23:57+00:00","article_modified_time":"2018-05-17T16:16:10+00:00","author":"Nenad Noveljic","twitter_card":"summary_large_image","twitter_creator":"@NenadNoveljic","twitter_misc":{"Written by":"Nenad Noveljic","Est. reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-analysis-packet-flow\/#article","isPartOf":{"@id":"https:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-analysis-packet-flow\/"},"author":{"name":"Nenad Noveljic","@id":"https:\/\/nenadnoveljic.com\/blog\/#\/schema\/person\/51458d9dd86dbbdd19f5add451d44efa"},"headline":"Emulex HBA Driver Performance Analysis (2) \u2013 Packet Flow","datePublished":"2016-04-07T11:23:57+00:00","dateModified":"2018-05-17T16:16:10+00:00","mainEntityOfPage":{"@id":"https:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-analysis-packet-flow\/"},"wordCount":796,"commentCount":0,"articleSection":["DTrace","Emulex","Solaris"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-analysis-packet-flow\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-analysis-packet-flow\/","url":"https:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-analysis-packet-flow\/","name":"Emulex HBA Driver Performance Analysis (2) \u2013 Packet Flow - All-round Database Topics","isPartOf":{"@id":"https:\/\/nenadnoveljic.com\/blog\/#website"},"datePublished":"2016-04-07T11:23:57+00:00","dateModified":"2018-05-17T16:16:10+00:00","author":{"@id":"https:\/\/nenadnoveljic.com\/blog\/#\/schema\/person\/51458d9dd86dbbdd19f5add451d44efa"},"breadcrumb":{"@id":"https:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-analysis-packet-flow\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-analysis-packet-flow\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/nenadnoveljic.com\/blog\/emulex-hba-driver-performance-analysis-packet-flow\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/nenadnoveljic.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Emulex HBA Driver Performance Analysis (2) \u2013 Packet Flow"}]},{"@type":"WebSite","@id":"https:\/\/nenadnoveljic.com\/blog\/#website","url":"https:\/\/nenadnoveljic.com\/blog\/","name":"All-round Database Topics","description":"Nenad Noveljic","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/nenadnoveljic.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/nenadnoveljic.com\/blog\/#\/schema\/person\/51458d9dd86dbbdd19f5add451d44efa","name":"Nenad Noveljic","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/a97b796613ea48ec8a7b79c8ffe1c685dcffc920c68121f6238d5caab5070670?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/a97b796613ea48ec8a7b79c8ffe1c685dcffc920c68121f6238d5caab5070670?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/a97b796613ea48ec8a7b79c8ffe1c685dcffc920c68121f6238d5caab5070670?s=96&d=mm&r=g","caption":"Nenad Noveljic"},"sameAs":["nenad-noveljic-9b746a6","https:\/\/x.com\/NenadNoveljic"],"url":"https:\/\/nenadnoveljic.com\/blog\/author\/nenad\/"}]}},"_links":{"self":[{"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/posts\/577","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/comments?post=577"}],"version-history":[{"count":1,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/posts\/577\/revisions"}],"predecessor-version":[{"id":706,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/posts\/577\/revisions\/706"}],"wp:attachment":[{"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/media?parent=577"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/categories?post=577"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nenadnoveljic.com\/blog\/wp-json\/wp\/v2\/tags?post=577"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}