diff options
Diffstat (limited to 'doc/guides/sample_app_ug')
38 files changed, 2183 insertions, 651 deletions
diff --git a/doc/guides/sample_app_ug/cmd_line.rst b/doc/guides/sample_app_ug/cmd_line.rst index 02a295ff..36c7971c 100644 --- a/doc/guides/sample_app_ug/cmd_line.rst +++ b/doc/guides/sample_app_ug/cmd_line.rst @@ -96,7 +96,7 @@ To run the application in linuxapp environment, issue the following command: .. code-block:: console - $ ./build/cmdline -c f -n 4 + $ ./build/cmdline -l 0-3 -n 4 Refer to the *DPDK Getting Started Guide* for general information on running applications and the Environment Abstraction Layer (EAL) options. diff --git a/doc/guides/sample_app_ug/dist_app.rst b/doc/guides/sample_app_ug/dist_app.rst index e242748f..1cae4739 100644 --- a/doc/guides/sample_app_ug/dist_app.rst +++ b/doc/guides/sample_app_ug/dist_app.rst @@ -96,7 +96,7 @@ Running the Application .. code-block:: console - $ ./build/distributor_app -c 0x4003fe -n 4 -- -p f + $ ./build/distributor_app -l 1-9,22 -n 4 -- -p f #. Refer to the DPDK Getting Started Guide for general information on running applications and the Environment Abstraction Layer (EAL) options. @@ -104,33 +104,35 @@ Running the Application Explanation ----------- -The distributor application consists of three types of threads: a receive -thread (lcore_rx()), a set of worker threads(lcore_worker()) -and a transmit thread(lcore_tx()). How these threads work together is shown -in :numref:`figure_dist_app` below. The main() function launches threads of these three types. -Each thread has a while loop which will be doing processing and which is -terminated only upon SIGINT or ctrl+C. The receive and transmit threads -communicate using a software ring (rte_ring structure). - -The receive thread receives the packets using rte_eth_rx_burst() and gives -them to the distributor (using rte_distributor_process() API) which will -be called in context of the receive thread itself. The distributor distributes -the packets to workers threads based on the tagging of the packet - -indicated by the hash field in the mbuf. For IP traffic, this field is -automatically filled by the NIC with the "usr" hash value for the packet, -which works as a per-flow tag. +The distributor application consists of four types of threads: a receive +thread (``lcore_rx()``), a distributor thread (``lcore_dist()``), a set of +worker threads (``lcore_worker()``), and a transmit thread(``lcore_tx()``). +How these threads work together is shown in :numref:`figure_dist_app` below. +The ``main()`` function launches threads of these four types. Each thread +has a while loop which will be doing processing and which is terminated +only upon SIGINT or ctrl+C. + +The receive thread receives the packets using ``rte_eth_rx_burst()`` and will +enqueue them to an rte_ring. The distributor thread will dequeue the packets +from the ring and assign them to workers (using ``rte_distributor_process()`` API). +This assignment is based on the tag (or flow ID) of the packet - indicated by +the hash field in the mbuf. For IP traffic, this field is automatically filled +by the NIC with the "usr" hash value for the packet, which works as a per-flow +tag. The distributor thread communicates with the worker threads using a +cache-line swapping mechanism, passing up to 8 mbuf pointers at a time +(one cache line) to each worker. More than one worker thread can exist as part of the application, and these worker threads do simple packet processing by requesting packets from the distributor, doing a simple XOR operation on the input port mbuf field (to indicate the output port which will be used later for packet transmission) -and then finally returning the packets back to the distributor in the RX thread. +and then finally returning the packets back to the distributor thread. -Meanwhile, the receive thread will call the distributor api -rte_distributor_returned_pkts() to get the packets processed, and will enqueue -them to a ring for transfer to the TX thread for transmission on the output port. -The transmit thread will dequeue the packets from the ring and transmit them on -the output port specified in packet mbuf. +The distributor thread will then call the distributor api +``rte_distributor_returned_pkts()`` to get the processed packets, and will enqueue +them to another rte_ring for transfer to the TX thread for transmission on the +output port. The transmit thread will dequeue the packets from the ring and +transmit them on the output port specified in packet mbuf. Users who wish to terminate the running of the application have to press ctrl+C (or send SIGINT to the app). Upon this signal, a signal handler provided @@ -153,8 +155,10 @@ the line "#define DEBUG" defined in start of the application in main.c to enable Statistics ---------- -Upon SIGINT (or) ctrl+C, the print_stats() function displays the count of packets -processed at the different stages in the application. +The main function will print statistics on the console every second. These +statistics include the number of packets enqueued and dequeued at each stage +in the application, and also key statistics per worker, including how many +packets of each burst size (1-8) were sent to each worker thread. Application Initialization -------------------------- diff --git a/doc/guides/sample_app_ug/ethtool.rst b/doc/guides/sample_app_ug/ethtool.rst index 4d1697e8..67797954 100644 --- a/doc/guides/sample_app_ug/ethtool.rst +++ b/doc/guides/sample_app_ug/ethtool.rst @@ -47,7 +47,7 @@ To compile the application: .. code-block:: console export RTE_SDK=/path/to/rte_sdk - cd ${RTE_SD}/examples/ethtool + cd ${RTE_SDK}/examples/ethtool #. Set the target (a default target is used if not specified). For example: diff --git a/doc/guides/sample_app_ug/exception_path.rst b/doc/guides/sample_app_ug/exception_path.rst index 161b6e0f..e505fb32 100644 --- a/doc/guides/sample_app_ug/exception_path.rst +++ b/doc/guides/sample_app_ug/exception_path.rst @@ -102,7 +102,7 @@ Refer to the *DPDK Getting Started Guide* for general information on running app and the Environment Abstraction Layer (EAL) options. The number of bits set in each bitmask must be the same. -The coremask -c parameter of the EAL options should include IN_CORES and OUT_CORES. +The coremask -c or the corelist -l parameter of the EAL options should include IN_CORES and OUT_CORES. The same bit must not be set in IN_CORES and OUT_CORES. The affinities between ports and cores are set beginning with the least significant bit of each mask, that is, the port represented by the lowest bit in PORTMASK is read from by the core represented by the lowest bit in IN_CORES, @@ -112,7 +112,7 @@ For example to run the application with two ports and four cores: .. code-block:: console - ./build/exception_path -c f -n 4 -- -p 3 -i 3 -o c + ./build/exception_path -l 0-3 -n 4 -- -p 3 -i 3 -o c Getting Statistics ~~~~~~~~~~~~~~~~~~ diff --git a/doc/guides/sample_app_ug/hello_world.rst b/doc/guides/sample_app_ug/hello_world.rst index 72e1e115..f4753af0 100644 --- a/doc/guides/sample_app_ug/hello_world.rst +++ b/doc/guides/sample_app_ug/hello_world.rst @@ -65,7 +65,7 @@ To run the example in a linuxapp environment: .. code-block:: console - $ ./build/helloworld -c f -n 4 + $ ./build/helloworld -l 0-3 -n 4 Refer to *DPDK Getting Started Guide* for general information on running applications and the Environment Abstraction Layer (EAL) options. diff --git a/doc/guides/sample_app_ug/img/dist_app.svg b/doc/guides/sample_app_ug/img/dist_app.svg index 4714c7db..944f4377 100644 --- a/doc/guides/sample_app_ug/img/dist_app.svg +++ b/doc/guides/sample_app_ug/img/dist_app.svg @@ -1,8 +1,7 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> - <!-- # BSD LICENSE -# Copyright (c) <2014>, Intel Corporation +# Copyright (c) <2014-2017>, Intel Corporation # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -47,8 +46,8 @@ height="379.53668" id="svg4090" version="1.1" - inkscape:version="0.48.5 r10040" - sodipodi:docname="New document 2"> + inkscape:version="0.92.1 r15371" + sodipodi:docname="dist_app.svg"> <defs id="defs4092"> <marker @@ -200,8 +199,8 @@ inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="1" - inkscape:cx="339.92174" - inkscape:cy="120.32038" + inkscape:cx="401.32873" + inkscape:cy="130.13572" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="false" @@ -210,8 +209,8 @@ fit-margin-right="0" fit-margin-bottom="0" inkscape:window-width="1920" - inkscape:window-height="1017" - inkscape:window-x="-8" + inkscape:window-height="1137" + inkscape:window-x="1912" inkscape:window-y="-8" inkscape:window-maximized="1" /> <metadata @@ -222,7 +221,7 @@ <dc:format>image/svg+xml</dc:format> <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> - <dc:title></dc:title> + <dc:title /> </cc:Work> </rdf:RDF> </metadata> @@ -232,40 +231,33 @@ id="layer1" transform="translate(-35.078263,-28.308125)"> <rect - style="fill:none;stroke:#000000;stroke-width:0.99999988;stroke-opacity:0.98412697" + style="fill:none;stroke:#000000;stroke-width:0.81890059;stroke-opacity:0.98412697" id="rect10443" - width="152.9641" - height="266.92566" - x="122.95611" - y="34.642567" /> - <rect - style="fill:none;stroke:#000000;stroke-width:1;stroke-opacity:0.98412697" - id="rect10445" - width="124.71397" - height="46.675529" - x="435.7746" - y="28.808125" /> + width="152.96732" + height="178.99617" + x="124.50176" + y="128.95552" /> <rect style="fill:none;stroke:#000000;stroke-width:0.99999988;stroke-opacity:0.98412697" id="rect10445-2" width="124.71397" height="46.675529" - x="435.42999" - y="103.92654" /> + x="437.00507" + y="133.06113" /> <rect style="fill:none;stroke:#000000;stroke-width:0.99999988;stroke-opacity:0.98412697" id="rect10445-0" width="124.71397" height="46.675529" x="436.80811" - y="178.31572" /> + y="193.87207" /> <rect style="fill:none;stroke:#000000;stroke-width:0.99999988;stroke-opacity:0.98412697" id="rect10445-9" width="124.71397" height="46.675529" x="436.80811" - y="246.87038" /> + y="256.06277" /> <rect style="fill:none;stroke:#000000;stroke-width:0.99999988;stroke-opacity:0.98412697" id="rect10445-7" @@ -274,203 +266,241 @@ x="135.7057" y="360.66928" /> <path - style="fill:none;stroke:#000000;stroke-width:0.99200004;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow1Mstart)" - d="M 277.293,44.129101 433.02373,43.388655" - id="path10486" - inkscape:connector-type="polyline" - inkscape:connector-curvature="3" /> - <path - style="fill:none;stroke:#000000;stroke-width:0.99200004;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow1Mstart)" - d="m 277.83855,110.78109 155.73073,-0.74044" + style="fill:none;stroke:#000000;stroke-width:0.99566948;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow1Mstart)" + d="M 278.89497,147.51907 436.5713,146.78234" id="path10486-2" inkscape:connector-type="polyline" inkscape:connector-curvature="3" /> <path - style="fill:none;stroke:#000000;stroke-width:0.99200004;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow1Mstart)" - d="m 278.48623,189.32721 155.73073,-0.74042" + style="fill:none;stroke:#000000;stroke-width:0.99290925;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow1Mstart)" + d="m 279.37092,206.8834 156.80331,-0.73671" id="path10486-1" inkscape:connector-type="polyline" inkscape:connector-curvature="3" /> <path - style="fill:none;stroke:#000000;stroke-width:0.99200004;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow1Mstart)" - d="m 278.48623,255.19448 155.73073,-0.74043" + style="fill:none;stroke:#000000;stroke-width:0.99379504;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow1Mstart)" + d="m 279.19738,270.88669 157.15478,-0.73638" id="path10486-4" inkscape:connector-type="polyline" inkscape:connector-curvature="3" /> <path - style="fill:none;stroke:#000000;stroke-width:0.99200004;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3;stroke-opacity:1;stroke-dasharray:none;marker-start:none;marker-mid:none;marker-end:url(#Arrow1Mend)" - d="M 277.11852,66.041829 432.84924,65.301384" - id="path10486-0" - inkscape:connector-type="polyline" - inkscape:connector-curvature="3" /> - <path - style="fill:none;stroke:#000000;stroke-width:0.99200004;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3;stroke-opacity:1;stroke-dasharray:none;marker-start:none;marker-mid:none;marker-end:url(#Arrow1Mend)" - d="M 277.46746,136.71727 433.1982,135.97682" + style="fill:none;stroke:#000000;stroke-width:0.99820405;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1;marker-start:none;marker-mid:none;marker-end:url(#Arrow1Mend)" + d="m 277.17846,166.20347 158.11878,-0.73842" id="path10486-0-4" inkscape:connector-type="polyline" inkscape:connector-curvature="3" /> <path - style="fill:none;stroke:#000000;stroke-width:0.99200004;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3;stroke-opacity:1;stroke-dasharray:none;marker-start:none;marker-mid:none;marker-end:url(#Arrow1Mend)" - d="m 276.77843,210.37709 155.73073,-0.74044" + style="fill:none;stroke:#000000;stroke-width:0.99410033;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1;marker-start:none;marker-mid:none;marker-end:url(#Arrow1Mend)" + d="m 277.47049,225.92925 157.32298,-0.73606" id="path10486-0-7" inkscape:connector-type="polyline" inkscape:connector-curvature="3" /> <path - style="fill:none;stroke:#000000;stroke-width:0.99200004;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3;stroke-opacity:1;stroke-dasharray:none;marker-start:none;marker-mid:none;marker-end:url(#Arrow1Mend)" - d="M 277.46746,282.5783 433.1982,281.83785" + style="fill:none;stroke:#000000;stroke-width:0.99566948;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1;marker-start:none;marker-mid:none;marker-end:url(#Arrow1Mend)" + d="M 277.70474,289.26714 435.38107,288.5304" id="path10486-0-77" inkscape:connector-type="polyline" inkscape:connector-curvature="3" /> <text xml:space="preserve" - style="font-size:9.32312489px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans" - x="348.03241" - y="34.792767" + style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none" + x="345.02322" + y="134.82103" id="text11995" - sodipodi:linespacing="125%" - transform="scale(0.93992342,1.0639165)"><tspan + transform="scale(0.93992339,1.0639165)"><tspan sodipodi:role="line" id="tspan11997" - x="348.03241" - y="34.792767">Request packet</tspan></text> + x="345.02322" + y="134.82103" + style="font-size:9.32312489px;line-height:1.25;font-family:sans-serif">Request burst</tspan></text> <text xml:space="preserve" - style="font-size:9.32312489px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans" - x="349.51935" - y="74.044792" + style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none" + x="346.38663" + y="164.76628" id="text11995-7" - sodipodi:linespacing="125%" - transform="scale(0.93992342,1.0639165)"><tspan + transform="scale(0.93992339,1.0639165)"><tspan sodipodi:role="line" id="tspan11997-3" - x="349.51935" - y="74.044792">Mbuf pointer</tspan></text> + x="346.38663" + y="164.76628" + style="font-size:9.32312489px;line-height:1.25;font-family:sans-serif">Mbuf Pointers</tspan></text> <text xml:space="preserve" - style="font-size:9.32312489px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans" - x="504.26611" - y="52.165989" + style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none" + x="502.36844" + y="151.66222" id="text11995-7-3" - sodipodi:linespacing="125%" - transform="scale(0.93992342,1.0639165)"><tspan + transform="scale(0.93992339,1.0639165)"><tspan sodipodi:role="line" id="tspan11997-3-5" - x="504.26611" - y="52.165989">WorkerThread1</tspan></text> + x="502.36844" + y="151.66222" + style="font-size:9.32312489px;line-height:1.25;font-family:sans-serif">WorkerThread1</tspan></text> <text xml:space="preserve" - style="font-size:9.32312489px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans" - x="501.65793" - y="121.54361" + style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none" + x="499.40103" + y="207.94502" id="text11995-7-3-9" - sodipodi:linespacing="125%" - transform="scale(0.93992342,1.0639165)"><tspan + transform="scale(0.93992339,1.0639165)"><tspan sodipodi:role="line" id="tspan11997-3-5-9" - x="501.65793" - y="121.54361">WorkerThread2</tspan></text> + x="499.40103" + y="207.94502" + style="font-size:9.32312489px;line-height:1.25;font-family:sans-serif">WorkerThread2</tspan></text> <text xml:space="preserve" - style="font-size:9.32312489px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans" - x="499.45868" - y="191.46367" - id="text11995-7-3-8" - sodipodi:linespacing="125%" - transform="scale(0.93992342,1.0639165)"><tspan - sodipodi:role="line" - id="tspan11997-3-5-1" - x="499.45868" - y="191.46367">WorkerThread3</tspan></text> - <text - xml:space="preserve" - style="font-size:9.32312489px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans" + style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none" x="500.1918" - y="257.9563" + y="266.59644" id="text11995-7-3-82" - sodipodi:linespacing="125%" - transform="scale(0.93992342,1.0639165)"><tspan + transform="scale(0.9399234,1.0639165)"><tspan sodipodi:role="line" id="tspan11997-3-5-6" x="500.1918" - y="257.9563">WorkerThreadN</tspan></text> + y="266.59644" + style="font-size:9.32312489px;line-height:1.25;font-family:sans-serif">WorkerThreadN</tspan></text> <text xml:space="preserve" - style="font-size:9.32312489px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans" + style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none" x="193.79703" y="362.85193" id="text11995-7-3-6" - sodipodi:linespacing="125%" transform="scale(0.93992342,1.0639165)"><tspan sodipodi:role="line" id="tspan11997-3-5-0" x="193.79703" - y="362.85193">TX thread</tspan></text> + y="362.85193" + style="font-size:9.32312489px;line-height:1.25;font-family:sans-serif">TX thread</tspan></text> <text xml:space="preserve" - style="font-size:9.32312489px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans" - x="162.2476" - y="142.79382" + style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none" + x="175.78905" + y="207.26257" id="text11995-7-3-3" - sodipodi:linespacing="125%" - transform="scale(0.93992342,1.0639165)"><tspan + transform="scale(0.9399234,1.0639165)"><tspan sodipodi:role="line" id="tspan11997-3-5-8" - x="162.2476" - y="142.79382">RX thread & Distributor</tspan></text> + x="175.78905" + y="207.26257" + style="font-size:9.32312489px;line-height:1.25;font-family:sans-serif">Distributor Thread</tspan></text> <path - style="fill:none;stroke:#000000;stroke-width:0.75945646;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3;stroke-opacity:1;stroke-dasharray:none;marker-start:none;marker-mid:none;marker-end:url(#Arrow1Mend)" - d="m 35.457991,109.77995 85.546359,-0.79004" + style="fill:none;stroke:#000000;stroke-width:0.75945646;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1;marker-start:none;marker-mid:none;marker-end:url(#Arrow1Mend)" + d="m 49.600127,54.625621 85.546363,-0.79004" id="path10486-0-4-5" inkscape:connector-type="polyline" inkscape:connector-curvature="3" /> <path - style="fill:none;stroke:#000000;stroke-width:0.75945646;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3;stroke-opacity:1;stroke-dasharray:none;marker-start:none;marker-mid:none;marker-end:url(#Arrow1Mend)" + style="fill:none;stroke:#000000;stroke-width:0.75945646;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:1;marker-start:none;marker-mid:none;marker-end:url(#Arrow1Mend)" d="m 135.70569,384.00706 -85.546361,0.79003" id="path10486-0-4-5-7" inkscape:connector-type="polyline" inkscape:connector-curvature="3" /> <text xml:space="preserve" - style="font-size:9.32312489px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans" - x="58.296661" - y="96.037407" + style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none" + x="73.342712" + y="44.196564" id="text11995-7-8" - sodipodi:linespacing="125%" - transform="scale(0.93992342,1.0639165)"><tspan + transform="scale(0.9399234,1.0639165)"><tspan sodipodi:role="line" id="tspan11997-3-3" - x="58.296661" - y="96.037407">Mbufs In</tspan></text> + x="73.342712" + y="44.196564" + style="font-size:9.32312489px;line-height:1.25;font-family:sans-serif">Mbufs In</tspan></text> <text xml:space="preserve" - style="font-size:9.32312489px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans" + style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none" x="83.4814" y="352.62543" id="text11995-7-8-5" - sodipodi:linespacing="125%" transform="scale(0.93992342,1.0639165)"><tspan sodipodi:role="line" id="tspan11997-3-3-1" x="83.4814" - y="352.62543">Mbufs Out</tspan></text> + y="352.62543" + style="font-size:9.32312489px;line-height:1.25;font-family:sans-serif">Mbufs Out</tspan></text> <path - style="fill:none;stroke:#000000;stroke-width:1.05720723;stroke-miterlimit:3;stroke-opacity:0.98412697;stroke-dasharray:none" - d="m 171.68192,303.16236 0.21464,30.4719 -8.6322,0.40574 -11.33877,0.1956 25.75778,14.79103 23.25799,11.11792 18.87014,-7.32926 31.83305,-17.26495 -10.75831,-0.32986 -10.37586,-0.44324 -0.22443,-31.54093 z" + style="fill:none;stroke:#000000;stroke-width:1.01068497;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:0.98412697" + d="m 171.68192,308.06701 0.21464,27.84908 -8.6322,0.37082 -11.33877,0.17876 25.75778,13.51792 23.25799,10.16096 18.87014,-6.69841 31.83305,-15.77889 -10.75831,-0.30147 -10.37586,-0.40509 -0.22443,-28.8261 z" id="path12188" inkscape:connector-curvature="0" - inkscape:transform-center-y="7.6863474" + inkscape:transform-center-y="7.0247597" sodipodi:nodetypes="cccccccccccc" /> <text xml:space="preserve" - style="font-size:9.32312489px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans" + style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none" x="193.68871" y="309.26349" id="text11995-7-3-6-2" - sodipodi:linespacing="125%" transform="scale(0.93992342,1.0639165)"><tspan sodipodi:role="line" x="193.68871" y="309.26349" - id="tspan12214">SW Ring</tspan></text> + id="tspan12214" + style="font-size:9.32312489px;line-height:1.25;font-family:sans-serif">SW Ring</tspan></text> + <path + style="fill:none;stroke:#000000;stroke-width:1.02106845;stroke-miterlimit:3;stroke-dasharray:none;stroke-opacity:0.98412697" + d="m 173.27214,75.568236 0.21464,28.424254 -8.6322,0.37848 -11.33877,0.18245 25.75778,13.79709 23.25799,10.37083 18.87013,-6.83675 31.83305,-16.10478 -10.75831,-0.30769 -10.37586,-0.41345 -0.22443,-29.421453 z" + id="path12188-5" + inkscape:connector-curvature="0" + inkscape:transform-center-y="7.1698404" + sodipodi:nodetypes="cccccccccccc" /> + <rect + style="fill:none;stroke:#000000;stroke-width:0.99999988;stroke-opacity:0.98412697" + id="rect10445-7-7" + width="124.71397" + height="46.675529" + x="138.18427" + y="28.832333" /> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none" + x="190.80019" + y="51.17778" + id="text11995-7-3-6-6" + transform="scale(0.93992339,1.0639165)"><tspan + sodipodi:role="line" + id="tspan11997-3-5-0-4" + x="190.80019" + y="51.17778" + style="font-size:9.32312489px;line-height:1.25;font-family:sans-serif">RX thread</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none" + x="196.38097" + y="90.224785" + id="text11995-7-3-6-2-9" + transform="scale(0.93992339,1.0639165)"><tspan + sodipodi:role="line" + x="196.38097" + y="90.224785" + id="tspan12214-8" + style="font-size:9.32312489px;line-height:1.25;font-family:sans-serif">SW Ring</tspan></text> + <rect + style="fill:none;stroke:#000000;stroke-width:0.99999988;stroke-opacity:0.98412697" + id="rect10445-7-7-5" + width="124.71397" + height="46.675529" + x="327.86566" + y="29.009106" /> + <text + xml:space="preserve" + style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none" + x="387.27209" + y="45.36227" + id="text11995-7-3-6-6-3" + transform="scale(0.93992339,1.0639165)"><tspan + sodipodi:role="line" + id="tspan11997-3-5-0-4-4" + x="387.27209" + y="45.36227" + style="font-size:9.32312489px;line-height:1.25;font-family:sans-serif">Stats thread</tspan><tspan + sodipodi:role="line" + x="387.27209" + y="57.016178" + style="font-size:9.32312489px;line-height:1.25;font-family:sans-serif" + id="tspan165">(to console)</tspan></text> </g> </svg> diff --git a/doc/guides/sample_app_ug/img/server_node_efd.svg b/doc/guides/sample_app_ug/img/server_node_efd.svg new file mode 100644 index 00000000..9aee30bc --- /dev/null +++ b/doc/guides/sample_app_ug/img/server_node_efd.svg @@ -0,0 +1,1254 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<!-- Generated by Microsoft Visio, SVG Export efd_i6.svg Page-1 --> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events" + xmlns:v="http://schemas.microsoft.com/visio/2003/SVGExtensions/" width="8.2496in" height="5.89673in" + viewBox="0 0 593.971 424.565" xml:space="preserve" color-interpolation-filters="sRGB" class="st27"> + <v:documentProperties v:langID="1033" v:viewMarkup="false"> + <v:userDefs> + <v:ud v:nameU="msvSubprocessMaster" v:prompt="" v:val="VT4(Rectangle)"/> + <v:ud v:nameU="msvNoAutoConnect" v:val="VT0(1):26"/> + </v:userDefs> + </v:documentProperties> + + <style type="text/css"> + <![CDATA[ + .st1 {visibility:visible} + .st2 {fill:#5b9bd5;fill-opacity:0.22;filter:url(#filter_2);stroke:#5b9bd5;stroke-opacity:0.22} + .st3 {fill:#5b9bd5;stroke:#c7c8c8;stroke-width:0.25} + .st4 {fill:#feffff;font-family:Calibri;font-size:0.833336em} + .st5 {fill:#feffff;font-family:Calibri;font-size:0.75em} + .st6 {fill:none;filter:url(#filter_2);stroke:#5b9bd5;stroke-opacity:0.22} + .st7 {fill:none;stroke:#2e75b5;stroke-width:2.25} + .st8 {fill:#305497;stroke:#2e75b5;stroke-width:1} + .st9 {fill:#feffff;font-family:Calibri;font-size:0.833336em;font-weight:bold} + .st10 {fill:#5b9bd5;fill-opacity:0.22;filter:url(#filter_2)} + .st11 {fill:#5b9bd5} + .st12 {stroke:#c7c8c8;stroke-width:0.25} + .st13 {fill:#acccea;stroke:#c7c8c8;stroke-width:0.25} + .st14 {fill:#feffff;font-family:Calibri;font-size:1.00001em;font-weight:bold} + .st15 {fill:#ed7d31;stroke:#c7c8c8;stroke-width:0.25} + .st16 {fill:#deebf6;stroke:#c7c8c8;stroke-width:0.25} + .st17 {marker-end:url(#mrkr5-212);stroke:#ff0000;stroke-linecap:round;stroke-linejoin:round;stroke-width:1} + .st18 {fill:#ff0000;fill-opacity:1;stroke:#ff0000;stroke-opacity:1;stroke-width:0.28409090909091} + .st19 {fill:none;stroke:#2e75b5;stroke-width:1} + .st20 {fill:#5b9bd5;font-family:Calibri;font-size:1.00001em} + .st21 {fill:none;stroke:none;stroke-width:0.25} + .st22 {font-size:1em} + .st23 {fill:#ffffff} + .st24 {stroke:#5b9bd5;stroke-dasharray:1.5,3;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5} + .st25 {marker-end:url(#mrkr5-444);stroke:#5b9bd5;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5} + .st26 {fill:#5b9bd5;fill-opacity:1;stroke:#5b9bd5;stroke-opacity:1;stroke-width:0.37313432835821} + .st27 {fill:none;fill-rule:evenodd;font-size:12px;overflow:visible;stroke-linecap:square;stroke-miterlimit:3} + ]]> + </style> + + <defs id="Markers"> + <g id="lend5"> + <path d="M 2 1 L 0 0 L 1.98117 -0.993387 C 1.67173 -0.364515 1.67301 0.372641 1.98465 1.00043 " style="stroke:none"/> + </g> + <marker id="mrkr5-212" class="st18" v:arrowType="5" v:arrowSize="2" v:setback="5.8" refX="-5.8" orient="auto" + markerUnits="strokeWidth" overflow="visible"> + <use xlink:href="#lend5" transform="scale(-3.52,-3.52) "/> + </marker> + <marker id="mrkr5-444" class="st26" v:arrowType="5" v:arrowSize="2" v:setback="4.69" refX="-4.69" orient="auto" + markerUnits="strokeWidth" overflow="visible"> + <use xlink:href="#lend5" transform="scale(-2.68,-2.68) "/> + </marker> + </defs> + <defs id="Filters"> + <filter id="filter_2"> + <feGaussianBlur stdDeviation="2"/> + </filter> + </defs> + <g v:mID="0" v:index="1" v:groupContext="foregroundPage"> + <v:userDefs> + <v:ud v:nameU="msvThemeOrder" v:val="VT0(0):26"/> + </v:userDefs> + <title>Page-1</title> + <v:pageProperties v:drawingScale="1" v:pageScale="1" v:drawingUnits="0" v:shadowOffsetX="9" v:shadowOffsetY="-9"/> + <g id="shape3-1" v:mID="3" v:groupContext="shape" transform="translate(319.501,-335.688)"> + <title>Rectangle.58</title> + <desc>Key 1</desc> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <v:textBlock v:margins="rect(4,4,4,4)"/> + <v:textRect cx="15.75" cy="415.565" width="31.5" height="18"/> + <g id="shadow3-2" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="31.5" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="31.5" height="18" class="st3"/> + <text x="4.74" y="418.56" class="st4" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Key 1</text> </g> + <g id="shape4-7" v:mID="4" v:groupContext="shape" transform="translate(353.251,-335.688)"> + <title>Rectangle.59</title> + <desc>Action 1</desc> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <v:textBlock v:margins="rect(4,4,4,4)"/> + <v:textRect cx="21.375" cy="415.565" width="42.75" height="18"/> + <g id="shadow4-8" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="42.75" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="42.75" height="18" class="st3"/> + <text x="4.62" y="418.56" class="st4" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Action 1</text> </g> + <g id="shape5-13" v:mID="5" v:groupContext="shape" transform="translate(400.501,-335.688)"> + <title>Rectangle.60</title> + <desc>Key 2</desc> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <v:textBlock v:margins="rect(4,4,4,4)"/> + <v:textRect cx="15.75" cy="415.565" width="31.5" height="18"/> + <g id="shadow5-14" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="31.5" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="31.5" height="18" class="st3"/> + <text x="4.74" y="418.56" class="st4" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Key 2</text> </g> + <g id="shape6-19" v:mID="6" v:groupContext="shape" transform="translate(434.251,-335.688)"> + <title>Rectangle.61</title> + <desc>Action 2</desc> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <v:textBlock v:margins="rect(4,4,4,4)"/> + <v:textRect cx="21.375" cy="415.565" width="42.75" height="18"/> + <g id="shadow6-20" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="42.75" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="42.75" height="18" class="st3"/> + <text x="4.62" y="418.56" class="st4" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Action 2</text> </g> + <g id="shape7-25" v:mID="7" v:groupContext="shape" transform="translate(481.501,-335.688)"> + <title>Rectangle.62</title> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <g id="shadow7-26" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="31.5" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="31.5" height="18" class="st3"/> + </g> + <g id="shape8-30" v:mID="8" v:groupContext="shape" transform="translate(515.251,-335.688)"> + <title>Rectangle.63</title> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <g id="shadow8-31" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="42.75" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="42.75" height="18" class="st3"/> + </g> + <g id="shape9-35" v:mID="9" v:groupContext="shape" transform="translate(319.501,-313.188)"> + <title>Rectangle.64</title> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <g id="shadow9-36" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="31.5" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="31.5" height="18" class="st3"/> + </g> + <g id="shape10-40" v:mID="10" v:groupContext="shape" transform="translate(353.251,-313.188)"> + <title>Rectangle.65</title> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <g id="shadow10-41" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="42.75" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="42.75" height="18" class="st3"/> + </g> + <g id="shape11-45" v:mID="11" v:groupContext="shape" transform="translate(400.501,-313.188)"> + <title>Rectangle.66</title> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <g id="shadow11-46" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="31.5" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="31.5" height="18" class="st3"/> + </g> + <g id="shape12-50" v:mID="12" v:groupContext="shape" transform="translate(434.251,-313.188)"> + <title>Rectangle.67</title> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <g id="shadow12-51" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="42.75" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="42.75" height="18" class="st3"/> + </g> + <g id="shape13-55" v:mID="13" v:groupContext="shape" transform="translate(481.501,-313.188)"> + <title>Rectangle.68</title> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <g id="shadow13-56" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="31.5" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="31.5" height="18" class="st3"/> + </g> + <g id="shape14-60" v:mID="14" v:groupContext="shape" transform="translate(515.251,-313.188)"> + <title>Rectangle.69</title> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <g id="shadow14-61" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="42.75" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="42.75" height="18" class="st3"/> + </g> + <g id="shape15-65" v:mID="15" v:groupContext="shape" transform="translate(319.501,-277.188)"> + <title>Rectangle.70</title> + <desc>Key x</desc> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <v:textBlock v:margins="rect(4,4,4,4)"/> + <v:textRect cx="15.75" cy="415.565" width="31.5" height="18"/> + <g id="shadow15-66" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="31.5" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="31.5" height="18" class="st3"/> + <text x="5.11" y="418.56" class="st4" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Key x</text> </g> + <g id="shape16-71" v:mID="16" v:groupContext="shape" transform="translate(353.251,-277.188)"> + <title>Rectangle.71</title> + <desc>Action x</desc> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <v:textBlock v:margins="rect(4,4,4,4)"/> + <v:textRect cx="21.375" cy="415.565" width="42.75" height="18"/> + <g id="shadow16-72" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="42.75" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="42.75" height="18" class="st3"/> + <text x="4.99" y="418.56" class="st4" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Action x</text> </g> + <g id="shape17-77" v:mID="17" v:groupContext="shape" transform="translate(400.501,-277.188)"> + <title>Rectangle.72</title> + <desc>Key y</desc> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <v:textBlock v:margins="rect(4,4,4,4)"/> + <v:textRect cx="15.75" cy="415.565" width="31.5" height="18"/> + <g id="shadow17-78" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="31.5" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="31.5" height="18" class="st3"/> + <text x="5.01" y="418.56" class="st4" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Key y</text> </g> + <g id="shape18-83" v:mID="18" v:groupContext="shape" transform="translate(434.251,-277.188)"> + <title>Rectangle.73</title> + <desc>Action y</desc> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <v:textBlock v:margins="rect(4,4,4,4)"/> + <v:textRect cx="21.375" cy="415.565" width="42.75" height="18"/> + <g id="shadow18-84" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="42.75" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="42.75" height="18" class="st3"/> + <text x="4.89" y="418.56" class="st4" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Action y</text> </g> + <g id="shape19-89" v:mID="19" v:groupContext="shape" transform="translate(481.501,-277.188)"> + <title>Rectangle.74</title> + <desc>Key z</desc> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <v:textBlock v:margins="rect(4,4,4,4)"/> + <v:textRect cx="15.75" cy="415.565" width="31.5" height="18"/> + <g id="shadow19-90" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="31.5" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="31.5" height="18" class="st3"/> + <text x="5.3" y="418.56" class="st4" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Key z</text> </g> + <g id="shape20-95" v:mID="20" v:groupContext="shape" transform="translate(515.251,-277.188)"> + <title>Rectangle.75</title> + <desc>Action z</desc> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <v:textBlock v:margins="rect(4,4,4,4)"/> + <v:textRect cx="21.375" cy="415.565" width="42.75" height="18"/> + <g id="shadow20-96" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="42.75" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="42.75" height="18" class="st3"/> + <text x="5.18" y="418.56" class="st4" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Action z</text> </g> + <g id="shape21-101" v:mID="21" v:groupContext="shape" transform="translate(319.501,-240.687)"> + <title>Rectangle.76</title> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <g id="shadow21-102" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="31.5" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="31.5" height="18" class="st3"/> + </g> + <g id="shape22-106" v:mID="22" v:groupContext="shape" transform="translate(353.251,-240.687)"> + <title>Rectangle.77</title> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <g id="shadow22-107" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="42.75" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="42.75" height="18" class="st3"/> + </g> + <g id="shape23-111" v:mID="23" v:groupContext="shape" transform="translate(400.501,-240.687)"> + <title>Rectangle.78</title> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <g id="shadow23-112" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="31.5" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="31.5" height="18" class="st3"/> + </g> + <g id="shape24-116" v:mID="24" v:groupContext="shape" transform="translate(434.251,-240.687)"> + <title>Rectangle.79</title> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <g id="shadow24-117" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="42.75" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="42.75" height="18" class="st3"/> + </g> + <g id="shape25-121" v:mID="25" v:groupContext="shape" transform="translate(481.501,-240.687)"> + <title>Rectangle.80</title> + <desc>Key N</desc> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <v:textBlock v:margins="rect(4,4,4,4)"/> + <v:textRect cx="15.75" cy="415.565" width="31.5" height="18"/> + <g id="shadow25-122" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="31.5" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="31.5" height="18" class="st3"/> + <text x="5.21" y="418.26" class="st5" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Key N</text> </g> + <g id="shape26-127" v:mID="26" v:groupContext="shape" transform="translate(515.251,-240.687)"> + <title>Rectangle.81</title> + <desc>Action N</desc> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <v:textBlock v:margins="rect(4,4,4,4)"/> + <v:textRect cx="21.375" cy="415.565" width="42.75" height="18"/> + <g id="shadow26-128" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="42.75" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="42.75" height="18" class="st3"/> + <text x="5.67" y="418.26" class="st5" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Action N</text> </g> + <g id="shape27-133" v:mID="27" v:groupContext="shape" transform="translate(317.251,-231.687)"> + <title>Rectangle.82</title> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <g id="shadow27-134" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="289.065" width="245.25" height="135.5" class="st6"/> + </g> + <rect x="0" y="289.065" width="245.25" height="135.5" class="st7"/> + </g> + <g id="shape28-138" v:mID="28" v:groupContext="shape" transform="translate(328.501,-362.688)"> + <title>Sheet.28</title> + <desc>Local Table for N Specific Flows Serviced at Node 1</desc> + <v:textBlock v:margins="rect(4,4,4,4)"/> + <v:textRect cx="110.423" cy="418.94" width="220.85" height="11.25"/> + <rect x="0" y="413.315" width="220.846" height="11.25" class="st8"/> + <text x="5.77" y="421.94" class="st9" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Local Table for N Specific Flows Serviced at Node 1</text> </g> + <g id="group34-141" transform="translate(66.0294,-165.569)" v:mID="34" v:groupContext="group"> + <v:custProps> + <v:cp v:nameU="AssetNumber" v:lbl="Asset Number" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="SerialNumber" v:lbl="Serial Number" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="Location" v:lbl="Location" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" + v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="Building" v:lbl="Building" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" + v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="Room" v:lbl="Room" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" + v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="Manufacturer" v:lbl="Manufacturer" v:prompt="" v:type="0" v:format="" v:sortKey="Equipment" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="ProductNumber" v:lbl="Product Number" v:prompt="" v:type="0" v:format="" v:sortKey="Equipment" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="PartNumber" v:lbl="Part Number" v:prompt="" v:type="0" v:format="" v:sortKey="Equipment" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="ProductDescription" v:lbl="Product Description" v:prompt="" v:type="0" v:format="" + v:sortKey="Equipment" v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="NetworkName" v:lbl="Network Name" v:prompt="" v:type="0" v:format="" v:sortKey="Network" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="IPAddress" v:lbl="IP Address" v:prompt="" v:type="0" v:format="" v:sortKey="Network" v:invis="false" + v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="SubnetMask" v:lbl="Subnet Mask" v:prompt="" v:type="0" v:format="" v:sortKey="Network" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="AdminInterface" v:lbl="Administrative Interface" v:prompt="" v:type="0" v:format="" + v:sortKey="Network" v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="NumberofPorts" v:lbl="Number of Ports" v:prompt="" v:type="0" v:format="" v:sortKey="Network" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="CommunityString" v:lbl="Community String" v:prompt="" v:type="0" v:format="" v:sortKey="Network" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="NetworkDescription" v:lbl="Network Description" v:prompt="" v:type="0" v:format="" + v:sortKey="Network" v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="MACAddress" v:lbl="MAC Address" v:prompt="" v:type="0" v:format="" v:sortKey="Network" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="ShapeClass" v:lbl="ShapeClass" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="true" + v:ask="false" v:langID="1033" v:cal="0" v:val="VT4(Equipment)"/> + <v:cp v:nameU="ShapeType" v:lbl="ShapeType" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="true" + v:ask="false" v:langID="1033" v:cal="0" v:val="VT4(Device)"/> + <v:cp v:nameU="SubShapeType" v:lbl="SubShapeType" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="true" + v:ask="false" v:langID="1033" v:cal="0" v:val="VT4(Load balancer)"/> + </v:custProps> + <v:userDefs> + <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/> + <v:ud v:nameU="ShapeClass" v:prompt="" v:val="VT0(5):26"/> + <v:ud v:nameU="SolSH" v:prompt="" v:val="VT15({BF0433D9-CD73-4EB5-8390-8653BE590246}):41"/> + <v:ud v:nameU="visLegendShape" v:prompt="" v:val="VT0(2):26"/> + </v:userDefs> + <title>Load balancer</title> + <g id="shape35-142" v:mID="35" v:groupContext="shape" transform="translate(0,-7.33146)"> + <title>Sheet.35</title> + <g id="shadow35-143" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <path d="M54 367.23 L18 367.23 L0 377.86 L0 424.56 L72 424.56 L72 377.86 L54 367.23 Z" class="st10"/> + <path d="M0 377.86 L72 377.86" class="st6"/> + <path d="M54 367.23 L18 367.23 L0 377.86 L0 424.56 L72 424.56 L72 377.86 L54 367.23" class="st6"/> + </g> + <path d="M54 367.23 L18 367.23 L0 377.86 L0 424.56 L72 424.56 L72 377.86 L54 367.23 Z" class="st11"/> + <path d="M0 377.86 L72 377.86" class="st12"/> + <path d="M54 367.23 L18 367.23 L0 377.86 L0 424.56 L72 424.56 L72 377.86 L54 367.23" class="st12"/> + </g> + <g id="shape36-152" v:mID="36" v:groupContext="shape" transform="translate(8.03054,-12.9324)"> + <title>Sheet.36</title> + <g id="shadow36-153" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <path d="M45.34 421.81 L41.2 422.66 L44.12 424.56 L49.68 423.16 L48.75 417.51 L45.8 415.59 L46.69 419.68 L36.97 + 413.34 L35.6 415.45 L45.34 421.81 ZM50.83 405.36 L39.2 405.36 L39.2 407.88 L50.8 407.88 L47.82 410.83 + L51.34 410.83 L55.21 406.61 L51.32 402.39 L47.83 402.39 L50.83 405.36 ZM46.49 392.01 L36.75 398.37 + L38.13 400.48 L47.84 394.14 L46.96 398.23 L49.91 396.31 L50.84 390.66 L45.28 389.26 L42.36 391.16 + L46.49 392.01 ZM27.71 397.16 C22.66 397.16 18.58 401.25 18.58 406.29 C18.58 411.33 22.66 415.42 + 27.71 415.42 C32.75 415.42 36.84 411.33 36.84 406.29 C36.84 401.25 32.75 397.16 27.71 397.16 ZM27.71 + 400.04 C31.15 400.04 33.96 402.84 33.96 406.29 C33.96 409.74 31.15 412.54 27.71 412.54 C24.26 412.54 + 21.46 409.74 21.46 406.29 C21.46 402.84 24.26 400.04 27.71 400.04 ZM11.64 405.04 L0 405.04 L0 407.56 + L11.6 407.56 L8.62 410.51 L12.14 410.51 L16.01 406.29 L12.12 402.07 L8.64 402.07 L11.64 405.04 Z" + class="st2"/> + </g> + <path d="M45.34 421.81 L41.2 422.66 L44.12 424.56 L49.68 423.16 L48.75 417.51 L45.8 415.59 L46.69 419.68 L36.97 413.34 + L35.6 415.45 L45.34 421.81 ZM50.83 405.36 L39.2 405.36 L39.2 407.88 L50.8 407.88 L47.82 410.83 L51.34 + 410.83 L55.21 406.61 L51.32 402.39 L47.83 402.39 L50.83 405.36 ZM46.49 392.01 L36.75 398.37 L38.13 400.48 + L47.84 394.14 L46.96 398.23 L49.91 396.31 L50.84 390.66 L45.28 389.26 L42.36 391.16 L46.49 392.01 ZM27.71 + 397.16 C22.66 397.16 18.58 401.25 18.58 406.29 C18.58 411.33 22.66 415.42 27.71 415.42 C32.75 415.42 + 36.84 411.33 36.84 406.29 C36.84 401.25 32.75 397.16 27.71 397.16 ZM27.71 400.04 C31.15 400.04 33.96 + 402.84 33.96 406.29 C33.96 409.74 31.15 412.54 27.71 412.54 C24.26 412.54 21.46 409.74 21.46 406.29 + C21.46 402.84 24.26 400.04 27.71 400.04 ZM11.64 405.04 L0 405.04 L0 407.56 L11.6 407.56 L8.62 410.51 + L12.14 410.51 L16.01 406.29 L12.12 402.07 L8.64 402.07 L11.64 405.04 Z" class="st13"/> + </g> + </g> + <g id="shape37-157" v:mID="37" v:groupContext="shape" transform="translate(21.0294,-45.4375)"> + <title>Rectangle</title> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <g id="shadow37-158" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="336.433" width="135" height="88.1315" class="st2"/> + </g> + <rect x="0" y="336.433" width="135" height="88.1315" class="st3"/> + </g> + <g id="shape38-162" v:mID="38" v:groupContext="shape" transform="translate(34.693,-126.438)"> + <title>Sheet.38</title> + <desc>EFD Table</desc> + <v:textBlock v:margins="rect(4,4,4,4)"/> + <v:textRect cx="49.3364" cy="415.565" width="98.68" height="18"/> + <rect x="0" y="406.565" width="98.6728" height="18" class="st8"/> + <text x="24.87" y="419.17" class="st14" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>EFD Table</text> </g> + <g id="shape39-165" v:mID="39" v:groupContext="shape" transform="translate(30.0294,-99.4375)"> + <title>Rectangle.39</title> + <desc>Group_id</desc> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <v:textBlock v:margins="rect(4,4,4,4)"/> + <v:textRect cx="26.9182" cy="415.565" width="53.84" height="18"/> + <g id="shadow39-166" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="53.8364" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="53.8364" height="18" class="st15"/> + <text x="7.87" y="418.56" class="st4" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Group_id</text> </g> + <g id="shape40-171" v:mID="40" v:groupContext="shape" transform="translate(93.193,-99.4375)"> + <title>Rectangle.40</title> + <desc>Hash index</desc> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <v:textBlock v:margins="rect(4,4,4,4)"/> + <v:textRect cx="26.9182" cy="415.565" width="53.84" height="18"/> + <g id="shadow40-172" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="53.8364" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="53.8364" height="18" class="st15"/> + <text x="4.64" y="418.56" class="st4" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Hash index</text> </g> + <g id="shape41-177" v:mID="41" v:groupContext="shape" transform="translate(30.193,-82.4275)"> + <title>Rectangle.41</title> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <g id="shadow41-178" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="413.315" width="53.8364" height="11.25" class="st2"/> + </g> + <rect x="0" y="413.315" width="53.8364" height="11.25" class="st16"/> + </g> + <g id="shape42-182" v:mID="42" v:groupContext="shape" transform="translate(30.193,-66.8125)"> + <title>Rectangle.42</title> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <g id="shadow42-183" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="413.315" width="53.8364" height="11.25" class="st2"/> + </g> + <rect x="0" y="413.315" width="53.8364" height="11.25" class="st16"/> + </g> + <g id="shape43-187" v:mID="43" v:groupContext="shape" transform="translate(30.1112,-52.1875)"> + <title>Rectangle.43</title> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <g id="shadow43-188" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="413.315" width="53.8364" height="11.25" class="st2"/> + </g> + <rect x="0" y="413.315" width="53.8364" height="11.25" class="st16"/> + </g> + <g id="shape44-192" v:mID="44" v:groupContext="shape" transform="translate(93.0294,-81.4375)"> + <title>Rectangle.44</title> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <g id="shadow44-193" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="413.315" width="53.8364" height="11.25" class="st2"/> + </g> + <rect x="0" y="413.315" width="53.8364" height="11.25" class="st16"/> + </g> + <g id="shape45-197" v:mID="45" v:groupContext="shape" transform="translate(93.193,-66.8125)"> + <title>Rectangle.45</title> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <g id="shadow45-198" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="413.315" width="53.8364" height="11.25" class="st2"/> + </g> + <rect x="0" y="413.315" width="53.8364" height="11.25" class="st16"/> + </g> + <g id="shape46-202" v:mID="46" v:groupContext="shape" transform="translate(93.193,-52.1875)"> + <title>Rectangle.46</title> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <g id="shadow46-203" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="413.315" width="53.8364" height="11.25" class="st2"/> + </g> + <rect x="0" y="413.315" width="53.8364" height="11.25" class="st16"/> + </g> + <g id="shape47-207" v:mID="47" v:groupContext="shape" transform="translate(374.924,544.022) rotate(135)"> + <title>Sheet.47</title> + <path d="M-0 417.75 A40.674 18.0151 -156.2 0 0 40.24 422.15 L40.49 421.89" class="st17"/> + </g> + <g id="shape48-213" v:mID="48" v:groupContext="shape" transform="translate(21.0294,-19)"> + <title>Sheet.48</title> + <desc>Supports X*N Flows</desc> + <v:textBlock v:margins="rect(4,4,4,4)"/> + <v:textRect cx="67.5" cy="415.565" width="135" height="18"/> + <rect x="0" y="406.565" width="135" height="18" class="st19"/> + <text x="19.05" y="419.17" class="st20" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Supports X*N Flows</text> </g> + <g id="shape49-216" v:mID="49" v:groupContext="shape" transform="translate(48.0294,-229.938)"> + <title>Sheet.49</title> + <desc>Frontend Server or Load Balancer</desc> + <v:textBlock v:margins="rect(4,4,4,4)"/> + <v:textRect cx="54" cy="400.94" width="108" height="47.25"/> + <rect x="0" y="377.315" width="108" height="47.25" class="st21"/> + <text x="14.56" y="397.34" class="st20" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Frontend Server<v:newlineChar/><tspan + x="13.16" dy="1.2em" class="st22">or Load Balancer </tspan> </text> </g> + <g id="group51-220" transform="translate(223.876,-310.938)" v:mID="51" v:groupContext="group"> + <v:custProps> + <v:cp v:nameU="AssetNumber" v:lbl="Asset Number" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="SerialNumber" v:lbl="Serial Number" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="Location" v:lbl="Location" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" + v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="Building" v:lbl="Building" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" + v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="Room" v:lbl="Room" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" + v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="Manufacturer" v:lbl="Manufacturer" v:prompt="" v:type="0" v:format="" v:sortKey="Equipment" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="ProductNumber" v:lbl="Product Number" v:prompt="" v:type="0" v:format="" v:sortKey="Equipment" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="PartNumber" v:lbl="Part Number" v:prompt="" v:type="0" v:format="" v:sortKey="Equipment" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="ProductDescription" v:lbl="Product Description" v:prompt="" v:type="0" v:format="" + v:sortKey="Equipment" v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="NetworkName" v:lbl="Network Name" v:prompt="" v:type="0" v:format="" v:sortKey="Network" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="IPAddress" v:lbl="IP Address" v:prompt="" v:type="0" v:format="" v:sortKey="Network" v:invis="false" + v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="SubnetMask" v:lbl="Subnet Mask" v:prompt="" v:type="0" v:format="" v:sortKey="Network" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="AdminInterface" v:lbl="Administrative Interface" v:prompt="" v:type="0" v:format="" + v:sortKey="Network" v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="NumberofPorts" v:lbl="Number of Ports" v:prompt="" v:type="0" v:format="" v:sortKey="Network" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="CommunityString" v:lbl="Community String" v:prompt="" v:type="0" v:format="" v:sortKey="Network" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="NetworkDescription" v:lbl="Network Description" v:prompt="" v:type="0" v:format="" + v:sortKey="Network" v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="MACAddress" v:lbl="MAC Address" v:prompt="" v:type="0" v:format="" v:sortKey="Network" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="CPU" v:lbl="CPU" v:prompt="" v:type="0" v:format="" v:sortKey="Workstation" v:invis="false" + v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="Memory" v:lbl="Memory" v:prompt="" v:type="0" v:format="" v:sortKey="Workstation" v:invis="false" + v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="OperatingSystem" v:lbl="Operating System" v:prompt="" v:type="0" v:format="" v:sortKey="Workstation" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="HardDriveSize" v:lbl="Hard Drive Capacity" v:prompt="" v:type="0" v:format="" + v:sortKey="Workstation" v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="Department" v:lbl="Department" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="false" + v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="ShapeClass" v:lbl="ShapeClass" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="true" + v:ask="false" v:langID="1033" v:cal="0" v:val="VT4(Equipment)"/> + <v:cp v:nameU="ShapeType" v:lbl="ShapeType" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="true" + v:ask="false" v:langID="1033" v:cal="0" v:val="VT4(Server)"/> + <v:cp v:nameU="BelongsTo" v:lbl="Belongs To" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="true" + v:ask="false" v:langID="1033" v:cal="0"/> + </v:custProps> + <v:userDefs> + <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/> + <v:ud v:nameU="ShapeClass" v:prompt="" v:val="VT0(5):26"/> + <v:ud v:nameU="SolSH" v:prompt="" v:val="VT15({BF0433D9-CD73-4EB5-8390-8653BE590246}):41"/> + <v:ud v:nameU="visLegendShape" v:prompt="" v:val="VT0(2):26"/> + </v:userDefs> + <title>Server</title> + <g id="shape52-221" v:mID="52" v:groupContext="shape" transform="translate(13.0183,0)"> + <title>Sheet.52</title> + <g id="shadow52-222" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="352.565" width="45.9634" height="72" class="st2"/> + </g> + <rect x="0" y="352.565" width="45.9634" height="72" class="st3"/> + </g> + <g id="shape53-226" v:mID="53" v:groupContext="shape" transform="translate(47.371,-30.7354)"> + <title>Sheet.53</title> + <g id="shadow53-227" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <ellipse cx="2.77848" cy="421.786" rx="2.77848" ry="2.77848" class="st2"/> + </g> + <ellipse cx="2.77848" cy="421.786" rx="2.77848" ry="2.77848" class="st13"/> + </g> + <g id="shape54-231" v:mID="54" v:groupContext="shape" transform="translate(30.51,-11.8022)"> + <title>Sheet.54</title> + <v:userDefs> + <v:ud v:nameU="SurroundingRegionColor" v:prompt="" v:val="VT5(1)"/> + <v:ud v:nameU="SurroundingRegionColor" v:prompt="" v:val="VT5(#5b9bd5)"/> + </v:userDefs> + <g id="shadow54-232" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <path d="M-0 424.56 L22.42 424.56 L22.42 422.76 L-0 422.76 L-0 424.56 ZM-0 419.11 L22.42 419.11 L22.42 417.31 + L-0 417.31 L-0 419.11 ZM-0 413.65 L22.42 413.65 L22.42 411.84 L-0 411.84 L-0 413.65 Z" + class="st10"/> + </g> + <path d="M-0 424.56 L22.42 424.56 L22.42 422.76 L-0 422.76 L-0 424.56 ZM-0 419.11 L22.42 419.11 L22.42 417.31 L-0 + 417.31 L-0 419.11 ZM-0 413.65 L22.42 413.65 L22.42 411.84 L-0 411.84 L-0 413.65 Z" class="st23"/> + </g> + </g> + <g id="shape59-239" v:mID="59" v:groupContext="shape" transform="translate(277.876,-373.938)"> + <title>Sheet.59</title> + <path d="M-0 424.56 A111.108 53.2538 42.31 0 1 93.83 421.21 L94.14 421.41" class="st17"/> + </g> + <g id="shape60-244" v:mID="60" v:groupContext="shape" transform="translate(205.876,-283.938)"> + <title>Sheet.60</title> + <desc>Backend Server 1</desc> + <v:textBlock v:margins="rect(4,4,4,4)"/> + <v:textRect cx="54" cy="408.124" width="108" height="32.8815"/> + <rect x="0" y="391.683" width="108" height="32.8815" class="st21"/> + <text x="11.93" y="411.72" class="st20" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Backend Server 1</text> </g> + <g id="group61-247" transform="translate(223.876,-207.438)" v:mID="61" v:groupContext="group"> + <v:custProps> + <v:cp v:nameU="AssetNumber" v:lbl="Asset Number" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="SerialNumber" v:lbl="Serial Number" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="Location" v:lbl="Location" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" + v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="Building" v:lbl="Building" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" + v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="Room" v:lbl="Room" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" + v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="Manufacturer" v:lbl="Manufacturer" v:prompt="" v:type="0" v:format="" v:sortKey="Equipment" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="ProductNumber" v:lbl="Product Number" v:prompt="" v:type="0" v:format="" v:sortKey="Equipment" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="PartNumber" v:lbl="Part Number" v:prompt="" v:type="0" v:format="" v:sortKey="Equipment" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="ProductDescription" v:lbl="Product Description" v:prompt="" v:type="0" v:format="" + v:sortKey="Equipment" v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="NetworkName" v:lbl="Network Name" v:prompt="" v:type="0" v:format="" v:sortKey="Network" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="IPAddress" v:lbl="IP Address" v:prompt="" v:type="0" v:format="" v:sortKey="Network" v:invis="false" + v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="SubnetMask" v:lbl="Subnet Mask" v:prompt="" v:type="0" v:format="" v:sortKey="Network" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="AdminInterface" v:lbl="Administrative Interface" v:prompt="" v:type="0" v:format="" + v:sortKey="Network" v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="NumberofPorts" v:lbl="Number of Ports" v:prompt="" v:type="0" v:format="" v:sortKey="Network" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="CommunityString" v:lbl="Community String" v:prompt="" v:type="0" v:format="" v:sortKey="Network" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="NetworkDescription" v:lbl="Network Description" v:prompt="" v:type="0" v:format="" + v:sortKey="Network" v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="MACAddress" v:lbl="MAC Address" v:prompt="" v:type="0" v:format="" v:sortKey="Network" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="CPU" v:lbl="CPU" v:prompt="" v:type="0" v:format="" v:sortKey="Workstation" v:invis="false" + v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="Memory" v:lbl="Memory" v:prompt="" v:type="0" v:format="" v:sortKey="Workstation" v:invis="false" + v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="OperatingSystem" v:lbl="Operating System" v:prompt="" v:type="0" v:format="" v:sortKey="Workstation" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="HardDriveSize" v:lbl="Hard Drive Capacity" v:prompt="" v:type="0" v:format="" + v:sortKey="Workstation" v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="Department" v:lbl="Department" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="false" + v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="ShapeClass" v:lbl="ShapeClass" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="true" + v:ask="false" v:langID="1033" v:cal="0" v:val="VT4(Equipment)"/> + <v:cp v:nameU="ShapeType" v:lbl="ShapeType" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="true" + v:ask="false" v:langID="1033" v:cal="0" v:val="VT4(Server)"/> + <v:cp v:nameU="BelongsTo" v:lbl="Belongs To" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="true" + v:ask="false" v:langID="1033" v:cal="0"/> + </v:custProps> + <v:userDefs> + <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/> + <v:ud v:nameU="ShapeClass" v:prompt="" v:val="VT0(5):26"/> + <v:ud v:nameU="SolSH" v:prompt="" v:val="VT15({BF0433D9-CD73-4EB5-8390-8653BE590246}):41"/> + <v:ud v:nameU="visLegendShape" v:prompt="" v:val="VT0(2):26"/> + </v:userDefs> + <title>Server.61</title> + <g id="shape62-248" v:mID="62" v:groupContext="shape" transform="translate(13.0183,0)"> + <title>Sheet.62</title> + <g id="shadow62-249" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="352.565" width="45.9634" height="72" class="st2"/> + </g> + <rect x="0" y="352.565" width="45.9634" height="72" class="st3"/> + </g> + <g id="shape63-253" v:mID="63" v:groupContext="shape" transform="translate(47.371,-30.7354)"> + <title>Sheet.63</title> + <g id="shadow63-254" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <ellipse cx="2.77848" cy="421.786" rx="2.77848" ry="2.77848" class="st2"/> + </g> + <ellipse cx="2.77848" cy="421.786" rx="2.77848" ry="2.77848" class="st13"/> + </g> + <g id="shape64-258" v:mID="64" v:groupContext="shape" transform="translate(30.51,-11.8022)"> + <title>Sheet.64</title> + <v:userDefs> + <v:ud v:nameU="SurroundingRegionColor" v:prompt="" v:val="VT5(1)"/> + <v:ud v:nameU="SurroundingRegionColor" v:prompt="" v:val="VT5(#5b9bd5)"/> + </v:userDefs> + <g id="shadow64-259" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <path d="M-0 424.56 L22.42 424.56 L22.42 422.76 L-0 422.76 L-0 424.56 ZM-0 419.11 L22.42 419.11 L22.42 417.31 + L-0 417.31 L-0 419.11 ZM-0 413.65 L22.42 413.65 L22.42 411.84 L-0 411.84 L-0 413.65 Z" + class="st10"/> + </g> + <path d="M-0 424.56 L22.42 424.56 L22.42 422.76 L-0 422.76 L-0 424.56 ZM-0 419.11 L22.42 419.11 L22.42 417.31 L-0 + 417.31 L-0 419.11 ZM-0 413.65 L22.42 413.65 L22.42 411.84 L-0 411.84 L-0 413.65 Z" class="st23"/> + </g> + </g> + <g id="shape65-266" v:mID="65" v:groupContext="shape" transform="translate(205.876,-180.437)"> + <title>Sheet.65</title> + <desc>Backend Server 2</desc> + <v:textBlock v:margins="rect(4,4,4,4)"/> + <v:textRect cx="54" cy="408.124" width="108" height="32.8815"/> + <rect x="0" y="391.683" width="108" height="32.8815" class="st21"/> + <text x="11.93" y="411.72" class="st20" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Backend Server 2</text> </g> + <g id="group66-269" transform="translate(219.029,-58.9375)" v:mID="66" v:groupContext="group"> + <v:custProps> + <v:cp v:nameU="AssetNumber" v:lbl="Asset Number" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="SerialNumber" v:lbl="Serial Number" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="Location" v:lbl="Location" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" + v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="Building" v:lbl="Building" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" + v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="Room" v:lbl="Room" v:prompt="" v:type="0" v:format="" v:sortKey="Asset" v:invis="false" + v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="Manufacturer" v:lbl="Manufacturer" v:prompt="" v:type="0" v:format="" v:sortKey="Equipment" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="ProductNumber" v:lbl="Product Number" v:prompt="" v:type="0" v:format="" v:sortKey="Equipment" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="PartNumber" v:lbl="Part Number" v:prompt="" v:type="0" v:format="" v:sortKey="Equipment" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="ProductDescription" v:lbl="Product Description" v:prompt="" v:type="0" v:format="" + v:sortKey="Equipment" v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="NetworkName" v:lbl="Network Name" v:prompt="" v:type="0" v:format="" v:sortKey="Network" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="IPAddress" v:lbl="IP Address" v:prompt="" v:type="0" v:format="" v:sortKey="Network" v:invis="false" + v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="SubnetMask" v:lbl="Subnet Mask" v:prompt="" v:type="0" v:format="" v:sortKey="Network" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="AdminInterface" v:lbl="Administrative Interface" v:prompt="" v:type="0" v:format="" + v:sortKey="Network" v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="NumberofPorts" v:lbl="Number of Ports" v:prompt="" v:type="0" v:format="" v:sortKey="Network" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="CommunityString" v:lbl="Community String" v:prompt="" v:type="0" v:format="" v:sortKey="Network" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="NetworkDescription" v:lbl="Network Description" v:prompt="" v:type="0" v:format="" + v:sortKey="Network" v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="MACAddress" v:lbl="MAC Address" v:prompt="" v:type="0" v:format="" v:sortKey="Network" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="CPU" v:lbl="CPU" v:prompt="" v:type="0" v:format="" v:sortKey="Workstation" v:invis="false" + v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="Memory" v:lbl="Memory" v:prompt="" v:type="0" v:format="" v:sortKey="Workstation" v:invis="false" + v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="OperatingSystem" v:lbl="Operating System" v:prompt="" v:type="0" v:format="" v:sortKey="Workstation" + v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="HardDriveSize" v:lbl="Hard Drive Capacity" v:prompt="" v:type="0" v:format="" + v:sortKey="Workstation" v:invis="false" v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="Department" v:lbl="Department" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="false" + v:ask="false" v:langID="1033" v:cal="0"/> + <v:cp v:nameU="ShapeClass" v:lbl="ShapeClass" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="true" + v:ask="false" v:langID="1033" v:cal="0" v:val="VT4(Equipment)"/> + <v:cp v:nameU="ShapeType" v:lbl="ShapeType" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="true" + v:ask="false" v:langID="1033" v:cal="0" v:val="VT4(Server)"/> + <v:cp v:nameU="BelongsTo" v:lbl="Belongs To" v:prompt="" v:type="0" v:format="" v:sortKey="" v:invis="true" + v:ask="false" v:langID="1033" v:cal="0"/> + </v:custProps> + <v:userDefs> + <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/> + <v:ud v:nameU="ShapeClass" v:prompt="" v:val="VT0(5):26"/> + <v:ud v:nameU="SolSH" v:prompt="" v:val="VT15({BF0433D9-CD73-4EB5-8390-8653BE590246}):41"/> + <v:ud v:nameU="visLegendShape" v:prompt="" v:val="VT0(2):26"/> + </v:userDefs> + <title>Server.66</title> + <g id="shape67-270" v:mID="67" v:groupContext="shape" transform="translate(13.0183,0)"> + <title>Sheet.67</title> + <g id="shadow67-271" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="352.565" width="45.9634" height="72" class="st2"/> + </g> + <rect x="0" y="352.565" width="45.9634" height="72" class="st3"/> + </g> + <g id="shape68-275" v:mID="68" v:groupContext="shape" transform="translate(47.371,-30.7354)"> + <title>Sheet.68</title> + <g id="shadow68-276" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <ellipse cx="2.77848" cy="421.786" rx="2.77848" ry="2.77848" class="st2"/> + </g> + <ellipse cx="2.77848" cy="421.786" rx="2.77848" ry="2.77848" class="st13"/> + </g> + <g id="shape69-280" v:mID="69" v:groupContext="shape" transform="translate(30.51,-11.8022)"> + <title>Sheet.69</title> + <v:userDefs> + <v:ud v:nameU="SurroundingRegionColor" v:prompt="" v:val="VT5(1)"/> + <v:ud v:nameU="SurroundingRegionColor" v:prompt="" v:val="VT5(#5b9bd5)"/> + </v:userDefs> + <g id="shadow69-281" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <path d="M-0 424.56 L22.42 424.56 L22.42 422.76 L-0 422.76 L-0 424.56 ZM-0 419.11 L22.42 419.11 L22.42 417.31 + L-0 417.31 L-0 419.11 ZM-0 413.65 L22.42 413.65 L22.42 411.84 L-0 411.84 L-0 413.65 Z" + class="st10"/> + </g> + <path d="M-0 424.56 L22.42 424.56 L22.42 422.76 L-0 422.76 L-0 424.56 ZM-0 419.11 L22.42 419.11 L22.42 417.31 L-0 + 417.31 L-0 419.11 ZM-0 413.65 L22.42 413.65 L22.42 411.84 L-0 411.84 L-0 413.65 Z" class="st23"/> + </g> + </g> + <g id="shape70-288" v:mID="70" v:groupContext="shape" transform="translate(201.029,-26.056)"> + <title>Sheet.70</title> + <desc>Backend Server X</desc> + <v:textBlock v:margins="rect(4,4,4,4)"/> + <v:textRect cx="54" cy="408.124" width="108" height="32.8815"/> + <rect x="0" y="391.683" width="108" height="32.8815" class="st21"/> + <text x="11.86" y="411.72" class="st20" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Backend Server X</text> </g> + <g id="shape71-291" v:mID="71" v:groupContext="shape" transform="translate(684.44,239.627) rotate(90)"> + <title>Sheet.71</title> + <path d="M0 424.56 L45 424.56" class="st24"/> + </g> + <g id="shape72-294" v:mID="72" v:groupContext="shape" transform="translate(6.85967,-22.443) rotate(-38.1076)"> + <title>Sheet.72</title> + <path d="M-0 424.56 A96.1331 44.4001 55.03 0 1 68.24 420.56 L68.51 420.79" class="st17"/> + </g> + <g id="shape73-299" v:mID="73" v:groupContext="shape" transform="translate(328.501,-135.937)"> + <title>Rectangle.73</title> + <desc>Key 1</desc> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <v:textBlock v:margins="rect(4,4,4,4)"/> + <v:textRect cx="15.75" cy="415.565" width="31.5" height="18"/> + <g id="shadow73-300" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="31.5" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="31.5" height="18" class="st3"/> + <text x="4.74" y="418.56" class="st4" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Key 1</text> </g> + <g id="shape74-305" v:mID="74" v:groupContext="shape" transform="translate(362.251,-135.937)"> + <title>Rectangle.74</title> + <desc>Action 1</desc> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <v:textBlock v:margins="rect(4,4,4,4)"/> + <v:textRect cx="21.375" cy="415.565" width="42.75" height="18"/> + <g id="shadow74-306" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="42.75" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="42.75" height="18" class="st3"/> + <text x="4.62" y="418.56" class="st4" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Action 1</text> </g> + <g id="shape75-311" v:mID="75" v:groupContext="shape" transform="translate(409.501,-135.937)"> + <title>Rectangle.75</title> + <desc>Key 2</desc> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <v:textBlock v:margins="rect(4,4,4,4)"/> + <v:textRect cx="15.75" cy="415.565" width="31.5" height="18"/> + <g id="shadow75-312" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="31.5" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="31.5" height="18" class="st3"/> + <text x="4.74" y="418.56" class="st4" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Key 2</text> </g> + <g id="shape76-317" v:mID="76" v:groupContext="shape" transform="translate(443.251,-135.937)"> + <title>Rectangle.76</title> + <desc>Action 2</desc> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <v:textBlock v:margins="rect(4,4,4,4)"/> + <v:textRect cx="21.375" cy="415.565" width="42.75" height="18"/> + <g id="shadow76-318" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="42.75" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="42.75" height="18" class="st3"/> + <text x="4.62" y="418.56" class="st4" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Action 2</text> </g> + <g id="shape77-323" v:mID="77" v:groupContext="shape" transform="translate(490.501,-135.937)"> + <title>Rectangle.77</title> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <g id="shadow77-324" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="31.5" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="31.5" height="18" class="st3"/> + </g> + <g id="shape78-328" v:mID="78" v:groupContext="shape" transform="translate(524.251,-135.937)"> + <title>Rectangle.78</title> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <g id="shadow78-329" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="42.75" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="42.75" height="18" class="st3"/> + </g> + <g id="shape79-333" v:mID="79" v:groupContext="shape" transform="translate(328.501,-113.437)"> + <title>Rectangle.79</title> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <g id="shadow79-334" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="31.5" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="31.5" height="18" class="st3"/> + </g> + <g id="shape80-338" v:mID="80" v:groupContext="shape" transform="translate(362.251,-113.437)"> + <title>Rectangle.80</title> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <g id="shadow80-339" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="42.75" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="42.75" height="18" class="st3"/> + </g> + <g id="shape81-343" v:mID="81" v:groupContext="shape" transform="translate(409.501,-113.437)"> + <title>Rectangle.81</title> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <g id="shadow81-344" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="31.5" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="31.5" height="18" class="st3"/> + </g> + <g id="shape82-348" v:mID="82" v:groupContext="shape" transform="translate(443.251,-113.437)"> + <title>Rectangle.82</title> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <g id="shadow82-349" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="42.75" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="42.75" height="18" class="st3"/> + </g> + <g id="shape83-353" v:mID="83" v:groupContext="shape" transform="translate(490.501,-113.437)"> + <title>Rectangle.83</title> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <g id="shadow83-354" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="31.5" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="31.5" height="18" class="st3"/> + </g> + <g id="shape84-358" v:mID="84" v:groupContext="shape" transform="translate(524.251,-113.437)"> + <title>Rectangle.84</title> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <g id="shadow84-359" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="42.75" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="42.75" height="18" class="st3"/> + </g> + <g id="shape85-363" v:mID="85" v:groupContext="shape" transform="translate(328.501,-77.4375)"> + <title>Rectangle.85</title> + <desc>Key x</desc> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <v:textBlock v:margins="rect(4,4,4,4)"/> + <v:textRect cx="15.75" cy="415.565" width="31.5" height="18"/> + <g id="shadow85-364" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="31.5" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="31.5" height="18" class="st3"/> + <text x="5.11" y="418.56" class="st4" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Key x</text> </g> + <g id="shape86-369" v:mID="86" v:groupContext="shape" transform="translate(362.251,-77.4375)"> + <title>Rectangle.86</title> + <desc>Action x</desc> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <v:textBlock v:margins="rect(4,4,4,4)"/> + <v:textRect cx="21.375" cy="415.565" width="42.75" height="18"/> + <g id="shadow86-370" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="42.75" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="42.75" height="18" class="st3"/> + <text x="4.99" y="418.56" class="st4" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Action x</text> </g> + <g id="shape87-375" v:mID="87" v:groupContext="shape" transform="translate(409.501,-77.4375)"> + <title>Rectangle.87</title> + <desc>Key y</desc> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <v:textBlock v:margins="rect(4,4,4,4)"/> + <v:textRect cx="15.75" cy="415.565" width="31.5" height="18"/> + <g id="shadow87-376" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="31.5" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="31.5" height="18" class="st3"/> + <text x="5.01" y="418.56" class="st4" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Key y</text> </g> + <g id="shape88-381" v:mID="88" v:groupContext="shape" transform="translate(443.251,-77.4375)"> + <title>Rectangle.88</title> + <desc>Action y</desc> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <v:textBlock v:margins="rect(4,4,4,4)"/> + <v:textRect cx="21.375" cy="415.565" width="42.75" height="18"/> + <g id="shadow88-382" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="42.75" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="42.75" height="18" class="st3"/> + <text x="4.89" y="418.56" class="st4" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Action y</text> </g> + <g id="shape89-387" v:mID="89" v:groupContext="shape" transform="translate(490.501,-77.4375)"> + <title>Rectangle.89</title> + <desc>Key z</desc> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <v:textBlock v:margins="rect(4,4,4,4)"/> + <v:textRect cx="15.75" cy="415.565" width="31.5" height="18"/> + <g id="shadow89-388" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="31.5" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="31.5" height="18" class="st3"/> + <text x="5.3" y="418.56" class="st4" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Key z</text> </g> + <g id="shape90-393" v:mID="90" v:groupContext="shape" transform="translate(524.251,-77.4375)"> + <title>Rectangle.90</title> + <desc>Action z</desc> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <v:textBlock v:margins="rect(4,4,4,4)"/> + <v:textRect cx="21.375" cy="415.565" width="42.75" height="18"/> + <g id="shadow90-394" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="42.75" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="42.75" height="18" class="st3"/> + <text x="5.18" y="418.56" class="st4" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Action z</text> </g> + <g id="shape91-399" v:mID="91" v:groupContext="shape" transform="translate(328.501,-40.9375)"> + <title>Rectangle.91</title> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <g id="shadow91-400" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="31.5" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="31.5" height="18" class="st3"/> + </g> + <g id="shape92-404" v:mID="92" v:groupContext="shape" transform="translate(362.251,-40.9375)"> + <title>Rectangle.92</title> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <g id="shadow92-405" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="42.75" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="42.75" height="18" class="st3"/> + </g> + <g id="shape93-409" v:mID="93" v:groupContext="shape" transform="translate(409.501,-40.9375)"> + <title>Rectangle.93</title> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <g id="shadow93-410" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="31.5" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="31.5" height="18" class="st3"/> + </g> + <g id="shape94-414" v:mID="94" v:groupContext="shape" transform="translate(443.251,-40.9375)"> + <title>Rectangle.94</title> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <g id="shadow94-415" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="42.75" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="42.75" height="18" class="st3"/> + </g> + <g id="shape95-419" v:mID="95" v:groupContext="shape" transform="translate(490.501,-40.9375)"> + <title>Rectangle.95</title> + <desc>Key N</desc> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <v:textBlock v:margins="rect(4,4,4,4)"/> + <v:textRect cx="15.75" cy="415.565" width="31.5" height="18"/> + <g id="shadow95-420" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="31.5" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="31.5" height="18" class="st3"/> + <text x="5.21" y="418.26" class="st5" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Key N</text> </g> + <g id="shape96-425" v:mID="96" v:groupContext="shape" transform="translate(524.251,-40.9375)"> + <title>Rectangle.96</title> + <desc>Action N</desc> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <v:textBlock v:margins="rect(4,4,4,4)"/> + <v:textRect cx="21.375" cy="415.565" width="42.75" height="18"/> + <g id="shadow96-426" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="406.565" width="42.75" height="18" class="st2"/> + </g> + <rect x="0" y="406.565" width="42.75" height="18" class="st3"/> + <text x="5.67" y="418.26" class="st5" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Action N</text> </g> + <g id="shape97-431" v:mID="97" v:groupContext="shape" transform="translate(326.251,-31.9375)"> + <title>Rectangle.97</title> + <v:userDefs> + <v:ud v:nameU="visVersion" v:val="VT0(15):26"/> + </v:userDefs> + <g id="shadow97-432" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279" v:shadowType="1" + transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1"> + <rect x="0" y="289.065" width="245.25" height="135.5" class="st6"/> + </g> + <rect x="0" y="289.065" width="245.25" height="135.5" class="st7"/> + </g> + <g id="shape98-436" v:mID="98" v:groupContext="shape" transform="translate(337.501,-162.938)"> + <title>Sheet.98</title> + <desc>Local Table for N Specific Flows Serviced at Node X</desc> + <v:textBlock v:margins="rect(4,4,4,4)"/> + <v:textRect cx="110.423" cy="418.94" width="220.85" height="11.25"/> + <rect x="0" y="413.315" width="220.846" height="11.25" class="st8"/> + <text x="5.55" y="421.94" class="st9" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Local Table for N Specific Flows Serviced at Node X</text> </g> + <g id="shape99-439" v:mID="99" v:groupContext="shape" transform="translate(-204.342,-29.4449) rotate(-53.7462)"> + <title>Sheet.99</title> + <path d="M0 424.56 L160.37 424.56" class="st25"/> + </g> + <g id="shape100-445" v:mID="100" v:groupContext="shape" transform="translate(-37.6568,-164.882) rotate(-24.444)"> + <title>Sheet.100</title> + <path d="M0 424.56 L101.71 424.56" class="st25"/> + </g> + <g id="shape101-450" v:mID="101" v:groupContext="shape" transform="translate(464.049,-50.8578) rotate(50.099)"> + <title>Sheet.101</title> + <path d="M0 424.56 L139.8 424.56" class="st25"/> + </g> + <g id="shape102-455" v:mID="102" v:groupContext="shape" transform="translate(372.376,-207.438)"> + <title>Sheet.102</title> + <desc>Supports N Flows</desc> + <v:textBlock v:margins="rect(4,4,4,4)"/> + <v:textRect cx="67.5" cy="415.565" width="135" height="18"/> + <rect x="0" y="406.565" width="135" height="18" class="st19"/> + <text x="25.15" y="419.17" class="st20" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Supports N Flows</text> </g> + </g> +</svg> diff --git a/doc/guides/sample_app_ug/index.rst b/doc/guides/sample_app_ug/index.rst index 775e2f70..02611ef8 100644 --- a/doc/guides/sample_app_ug/index.rst +++ b/doc/guides/sample_app_ug/index.rst @@ -57,10 +57,10 @@ Sample Applications User Guides l3_forward_virtual link_status_intr load_balancer + server_node_efd multi_process qos_metering qos_scheduler - intel_quickassist quota_watermark timer packet_ordering @@ -108,8 +108,6 @@ Sample Applications User Guides :numref:`figure_qos_sched_app_arch` :ref:`figure_qos_sched_app_arch` -:numref:`figure_quickassist_block_diagram` :ref:`figure_quickassist_block_diagram` - :numref:`figure_pipeline_overview` :ref:`figure_pipeline_overview` :numref:`figure_ring_pipeline_perf_setup` :ref:`figure_ring_pipeline_perf_setup` @@ -132,6 +130,8 @@ Sample Applications User Guides :numref:`figure_ptpclient_highlevel` :ref:`figure_ptpclient_highlevel` +:numref:`figure_efd_sample_app_overview` :ref:`figure_efd_sample_app_overview` + **Tables** :numref:`table_qos_metering_1` :ref:`table_qos_metering_1` diff --git a/doc/guides/sample_app_ug/intel_quickassist.rst b/doc/guides/sample_app_ug/intel_quickassist.rst deleted file mode 100644 index 04d1593d..00000000 --- a/doc/guides/sample_app_ug/intel_quickassist.rst +++ /dev/null @@ -1,221 +0,0 @@ -.. BSD LICENSE - Copyright(c) 2010-2014 Intel Corporation. All rights reserved. - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - * Neither the name of Intel Corporation nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -Intel® QuickAssist Technology Sample Application -================================================ - -This sample application demonstrates the use of the cryptographic operations provided -by the Intel® QuickAssist Technology from within the DPDK environment. -Therefore, building and running this application requires having both the DPDK and -the QuickAssist Technology Software Library installed, as well as at least one -Intel® QuickAssist Technology hardware device present in the system. - -For this sample application, there is a dependency on either of: - -* Intel® Communications Chipset 8900 to 8920 Series Software for Linux* package - -* Intel® Communications Chipset 8925 to 8955 Series Software for Linux* package - -Overview --------- - -An overview of the application is provided in :numref:`figure_quickassist_block_diagram`. -For simplicity, only two NIC ports and one Intel® QuickAssist Technology device are shown in this diagram, -although the number of NIC ports and Intel® QuickAssist Technology devices can be different. - -.. _figure_quickassist_block_diagram: - -.. figure:: img/quickassist_block_diagram.* - - Intel® QuickAssist Technology Application Block Diagram - - -The application allows the configuration of the following items: - -* Number of NIC ports - -* Number of logical cores (lcores) - -* Mapping of NIC RX queues to logical cores - -Each lcore communicates with every cryptographic acceleration engine in the system through a pair of dedicated input - output queues. -Each lcore has a dedicated NIC TX queue with every NIC port in the system. -Therefore, each lcore reads packets from its NIC RX queues and cryptographic accelerator output queues and -writes packets to its NIC TX queues and cryptographic accelerator input queues. - -Each incoming packet that is read from a NIC RX queue is either directly forwarded to its destination NIC TX port (forwarding path) -or first sent to one of the Intel® QuickAssist Technology devices for either encryption or decryption -before being sent out on its destination NIC TX port (cryptographic path). - -The application supports IPv4 input packets only. -For each input packet, the decision between the forwarding path and -the cryptographic path is taken at the classification stage based on the value of the IP source address field read from the input packet. -Assuming that the IP source address is A.B.C.D, then if: - -* D = 0: the forwarding path is selected (the packet is forwarded out directly) - -* D = 1: the cryptographic path for encryption is selected (the packet is first encrypted and then forwarded out) - -* D = 2: the cryptographic path for decryption is selected (the packet is first decrypted and then forwarded out) - -For the cryptographic path cases (D = 1 or D = 2), byte C specifies the cipher algorithm and -byte B the cryptographic hash algorithm to be used for the current packet. -Byte A is not used and can be any value. -The cipher and cryptographic hash algorithms supported by this application are listed in the crypto.h header file. - -For each input packet, the destination NIC TX port is decided at the forwarding stage (executed after the cryptographic stage, -if enabled for the packet) by looking at the RX port index of the dst_ports[ ] array, -which was initialized at startup, being the outport the adjacent enabled port. -For example, if ports 1,3,5 and 6 are enabled, for input port 1, outport port will be 3 and vice versa, -and for input port 5, output port will be 6 and vice versa. - -For the cryptographic path, it is the payload of the IPv4 packet that is encrypted or decrypted. - -Setup -~~~~~ - -Building and running this application requires having both the DPDK package and -the QuickAssist Technology Software Library installed, -as well as at least one Intel® QuickAssist Technology hardware device present in the system. - -For more details on how to build and run DPDK and Intel® QuickAssist Technology applications, -please refer to the following documents: - -* *DPDK Getting Started Guide* - -* Intel® Communications Chipset 8900 to 8920 Series Software for Linux* Getting Started Guide (440005) - -* Intel® Communications Chipset 8925 to 8955 Series Software for Linux* Getting Started Guide (523128) - -For more details on the actual platforms used to validate this application, as well as performance numbers, -please refer to the Test Report, which is accessible by contacting your Intel representative. - -Building the Application ------------------------- - -Steps to build the application: - -#. Set up the following environment variables: - - .. code-block:: console - - export RTE_SDK=<Absolute path to the DPDK installation folder> - export ICP_ROOT=<Absolute path to the Intel QAT installation folder> - -#. Set the target (a default target is used if not specified). For example: - - .. code-block:: console - - export RTE_TARGET=x86_64-native-linuxapp-gcc - - Refer to the *DPDK Getting Started Guide* for possible RTE_TARGET values. - -#. Build the application: - - .. code-block:: console - - cd ${RTE_SDK}/examples/dpdk_qat - make - -Running the Application ------------------------ - -Intel® QuickAssist Technology Configuration Files -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The Intel® QuickAssist Technology configuration files used by the application are located in the config_files folder in the application folder. -There following sets of configuration files are included in the DPDK package: - -* Stargo CRB (single CPU socket): located in the stargo folder - - * dh89xxcc_qa_dev0.conf - -* Shumway CRB (dual CPU socket): located in the shumway folder - - * dh89xxcc_qa_dev0.conf - - * dh89xxcc_qa_dev1.conf - -* Coleto Creek: located in the coleto folder - - * dh895xcc_qa_dev0.conf - -The relevant configuration file(s) must be copied to the /etc/ directory. - -Please note that any change to these configuration files requires restarting the Intel® -QuickAssist Technology driver using the following command: - -.. code-block:: console - - # service qat_service restart - -Refer to the following documents for information on the Intel® QuickAssist Technology configuration files: - -* Intel® Communications Chipset 8900 to 8920 Series Software Programmer's Guide - -* Intel® Communications Chipset 8925 to 8955 Series Software Programmer's Guide - -* Intel® Communications Chipset 8900 to 8920 Series Software for Linux* Getting Started Guide. - -* Intel® Communications Chipset 8925 to 8955 Series Software for Linux* Getting Started Guide. - -Traffic Generator Setup and Application Startup -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The application has a number of command line options: - - dpdk_qat [EAL options] -- -p PORTMASK [--no-promisc] [--config '(port,queue,lcore)[,(port,queue,lcore)]'] - -where, - -* -p PORTMASK: Hexadecimal bitmask of ports to configure - -* --no-promisc: Disables promiscuous mode for all ports, - so that only packets with the Ethernet MAC destination address set to the Ethernet address of the port are accepted. - By default promiscuous mode is enabled so that packets are accepted regardless of the packet's Ethernet MAC destination address. - -* --config'(port,queue,lcore)[,(port,queue,lcore)]': determines which queues from which ports are mapped to which cores. - -Refer to the :doc:`l3_forward` for more detailed descriptions of the --config command line option. - -As an example, to run the application with two ports and two cores, -which are using different Intel® QuickAssist Technology execution engines, -performing AES-CBC-128 encryption with AES-XCBC-MAC-96 hash, the following settings can be used: - -* Traffic generator source IP address: 0.9.6.1 - -* Command line: - - .. code-block:: console - - ./build/dpdk_qat -c 0xff -n 2 -- -p 0x3 --config '(0,0,1),(1,0,2)' - -Refer to the *DPDK Test Report* for more examples of traffic generator setup and the application startup command lines. -If no errors are generated in response to the startup commands, the application is running correctly. diff --git a/doc/guides/sample_app_ug/ip_frag.rst b/doc/guides/sample_app_ug/ip_frag.rst index 0c8da194..bd1fe2dc 100644 --- a/doc/guides/sample_app_ug/ip_frag.rst +++ b/doc/guides/sample_app_ug/ip_frag.rst @@ -111,7 +111,7 @@ To run the example in linuxapp environment with 2 lcores (2,4) over 2 ports(0,2) .. code-block:: console - ./build/ip_fragmentation -c 0x14 -n 3 -- -p 5 + ./build/ip_fragmentation -l 2,4 -n 3 -- -p 5 EAL: coremask set to 14 EAL: Detected lcore 0 on socket 0 EAL: Detected lcore 1 on socket 1 @@ -140,7 +140,7 @@ To run the example in linuxapp environment with 1 lcore (4) over 2 ports(0,2) wi .. code-block:: console - ./build/ip_fragmentation -c 0x10 -n 3 -- -p 5 -q 2 + ./build/ip_fragmentation -l 4 -n 3 -- -p 5 -q 2 To test the application, flows should be set up in the flow generator that match the values in the l3fwd_ipv4_route_array and/or l3fwd_ipv6_route_array table. diff --git a/doc/guides/sample_app_ug/ip_reassembly.rst b/doc/guides/sample_app_ug/ip_reassembly.rst index 3c5cc708..cc9e5911 100644 --- a/doc/guides/sample_app_ug/ip_reassembly.rst +++ b/doc/guides/sample_app_ug/ip_reassembly.rst @@ -102,7 +102,7 @@ To run the example in linuxapp environment with 2 lcores (2,4) over 2 ports(0,2) .. code-block:: console - ./build/ip_reassembly -c 0x14 -n 3 -- -p 5 + ./build/ip_reassembly -l 2,4 -n 3 -- -p 5 EAL: coremask set to 14 EAL: Detected lcore 0 on socket 0 EAL: Detected lcore 1 on socket 1 @@ -133,7 +133,7 @@ To run the example in linuxapp environment with 1 lcore (4) over 2 ports(0,2) wi .. code-block:: console - ./build/ip_reassembly -c 0x10 -n 3 -- -p 5 -q 2 + ./build/ip_reassembly -l 4 -n 3 -- -p 5 -q 2 To test the application, flows should be set up in the flow generator that match the values in the l3fwd_ipv4_route_array and/or l3fwd_ipv6_route_array table. diff --git a/doc/guides/sample_app_ug/ipv4_multicast.rst b/doc/guides/sample_app_ug/ipv4_multicast.rst index 72da8c42..3e30f509 100644 --- a/doc/guides/sample_app_ug/ipv4_multicast.rst +++ b/doc/guides/sample_app_ug/ipv4_multicast.rst @@ -113,7 +113,7 @@ Typically, to run the IPv4 Multicast sample application, issue the following com .. code-block:: console - ./build/ipv4_multicast -c 0x00f -n 3 -- -p 0x3 -q 1 + ./build/ipv4_multicast -l 0-3 -n 3 -- -p 0x3 -q 1 In this command: @@ -145,12 +145,12 @@ Memory pools for indirect buffers are initialized differently from the memory po .. code-block:: c - packet_pool = rte_mempool_create("packet_pool", NB_PKT_MBUF, PKT_MBUF_SIZE, 32, sizeof(struct rte_pktmbuf_pool_private), - rte_pktmbuf_pool_init, NULL, rte_pktmbuf_init, NULL, rte_socket_id(), 0); - - header_pool = rte_mempool_create("header_pool", NB_HDR_MBUF, HDR_MBUF_SIZE, 32, 0, NULL, NULL, rte_pktmbuf_init, NULL, rte_socket_id(), 0); - clone_pool = rte_mempool_create("clone_pool", NB_CLONE_MBUF, - CLONE_MBUF_SIZE, 32, 0, NULL, NULL, rte_pktmbuf_init, NULL, rte_socket_id(), 0); + packet_pool = rte_pktmbuf_pool_create("packet_pool", NB_PKT_MBUF, 32, + 0, PKT_MBUF_DATA_SIZE, rte_socket_id()); + header_pool = rte_pktmbuf_pool_create("header_pool", NB_HDR_MBUF, 32, + 0, HDR_MBUF_DATA_SIZE, rte_socket_id()); + clone_pool = rte_pktmbuf_pool_create("clone_pool", NB_CLONE_MBUF, 32, + 0, 0, rte_socket_id()); The reason for this is because indirect buffers are not supposed to hold any packet data and therefore can be initialized with lower amount of reserved memory for each buffer. diff --git a/doc/guides/sample_app_ug/keep_alive.rst b/doc/guides/sample_app_ug/keep_alive.rst index 38973779..fe908206 100644 --- a/doc/guides/sample_app_ug/keep_alive.rst +++ b/doc/guides/sample_app_ug/keep_alive.rst @@ -114,7 +114,7 @@ To run the application in linuxapp environment with 4 lcores, 16 ports .. code-block:: console - ./build/l2fwd-keepalive -c f -n 4 -- -q 8 -p ffff -K 10 + ./build/l2fwd-keepalive -l 0-3 -n 4 -- -q 8 -p ffff -K 10 Refer to the *DPDK Getting Started Guide* for general information on running applications and the Environment Abstraction Layer (EAL) diff --git a/doc/guides/sample_app_ug/kernel_nic_interface.rst b/doc/guides/sample_app_ug/kernel_nic_interface.rst index 2ae9b702..619a7b52 100644 --- a/doc/guides/sample_app_ug/kernel_nic_interface.rst +++ b/doc/guides/sample_app_ug/kernel_nic_interface.rst @@ -180,7 +180,7 @@ Where: Refer to *DPDK Getting Started Guide* for general information on running applications and the Environment Abstraction Layer (EAL) options. -The -c coremask parameter of the EAL options should include the lcores indicated by the lcore_rx and lcore_tx, +The -c coremask or -l corelist parameter of the EAL options should include the lcores indicated by the lcore_rx and lcore_tx, but does not need to include lcores indicated by lcore_kthread as they are used to pin the kernel thread on. The -p PORTMASK parameter should include the ports indicated by the port in --config, neither more nor less. @@ -199,7 +199,7 @@ and one lcore of kernel thread for each port: .. code-block:: console - ./build/kni -c 0xf0 -n 4 -- -P -p 0x3 -config="(0,4,6,8),(1,5,7,9)" + ./build/kni -l 4-7 -n 4 -- -P -p 0x3 -config="(0,4,6,8),(1,5,7,9)" KNI Operations -------------- diff --git a/doc/guides/sample_app_ug/l2_forward_cat.rst b/doc/guides/sample_app_ug/l2_forward_cat.rst index 285c3c74..b0c2e109 100644 --- a/doc/guides/sample_app_ug/l2_forward_cat.rst +++ b/doc/guides/sample_app_ug/l2_forward_cat.rst @@ -108,13 +108,13 @@ To run the example in a ``linuxapp`` environment and enable CAT on cpus 0-2: .. code-block:: console - ./build/l2fwd-cat -c 2 -n 4 -- --l3ca="0x3@(0-2)" + ./build/l2fwd-cat -l 1 -n 4 -- --l3ca="0x3@(0-2)" or to enable CAT and CDP on cpus 1,3: .. code-block:: console - ./build/l2fwd-cat -c 2 -n 4 -- --l3ca="(0x00C00,0x00300)@(1,3)" + ./build/l2fwd-cat -l 1 -n 4 -- --l3ca="(0x00C00,0x00300)@(1,3)" If CDP is not supported it will fail with following error message: @@ -242,4 +242,4 @@ relevant CPUs via ``pqos_l3ca_assoc_set(...)`` calls. ``atexit(...)`` is used to register ``cat_exit(...)`` to be called on a clean exit. ``cat_exit(...)`` performs a simple CAT clean-up, by associating -COS 0 to all involved CPUs via ``pqos_l3ca_assoc_set(...)`` calls.
\ No newline at end of file +COS 0 to all involved CPUs via ``pqos_l3ca_assoc_set(...)`` calls. diff --git a/doc/guides/sample_app_ug/l2_forward_crypto.rst b/doc/guides/sample_app_ug/l2_forward_crypto.rst index 723376c5..d6df36b5 100644 --- a/doc/guides/sample_app_ug/l2_forward_crypto.rst +++ b/doc/guides/sample_app_ug/l2_forward_crypto.rst @@ -1,5 +1,5 @@ .. BSD LICENSE - Copyright(c) 2016 Intel Corporation. All rights reserved. + Copyright(c) 2016-2017 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without @@ -89,7 +89,7 @@ The application requires a number of command line options: [--cipher_key_random_size SIZE] [--iv IV] [--iv_random_size SIZE] / [--auth_algo ALGO] [--auth_op GENERATE/VERIFY] [--auth_key KEY] / [--auth_key_random_size SIZE] [--aad AAD] [--aad_random_size SIZE] / - [--digest size SIZE] [--sessionless] + [--digest size SIZE] [--sessionless] [--cryptodev_mask MASK] where, @@ -113,7 +113,7 @@ where, (default is Cipher->Hash) -* cipher_algo: select the ciphering algorithm (default is AES CBC) +* cipher_algo: select the ciphering algorithm (default is aes-cbc) * cipher_op: select the ciphering operation to perform: ENCRYPT or DECRYPT @@ -133,7 +133,7 @@ where, Note that if --iv is used, this will be ignored. -* auth_algo: select the authentication algorithm (default is SHA1-HMAC) +* auth_algo: select the authentication algorithm (default is sha1-hmac) * cipher_op: select the authentication operation to perform: GENERATE or VERIFY @@ -157,6 +157,11 @@ where, * sessionless: no crypto session will be created. +* cryptodev_mask: A hexadecimal bitmask of the cryptodevs to be used by the + application. + + (default is all cryptodevs). + The application requires that crypto devices capable of performing the specified crypto operation are available on application initialization. @@ -167,11 +172,11 @@ To run the application in linuxapp environment with 2 lcores, 2 ports and 2 cryp .. code-block:: console - $ ./build/l2fwd-crypto -c 0x3 -n 4 --vdev "cryptodev_aesni_mb_pmd" \ + $ ./build/l2fwd-crypto -l 0-1 -n 4 --vdev "cryptodev_aesni_mb_pmd" \ --vdev "cryptodev_aesni_mb_pmd" -- -p 0x3 --chain CIPHER_HASH \ - --cipher_op ENCRYPT --cipher_algo AES_CBC \ + --cipher_op ENCRYPT --cipher_algo aes-cbc \ --cipher_key 00:01:02:03:04:05:06:07:08:09:0a:0b:0c:0d:0e:0f \ - --auth_op GENERATE --auth_algo AES_XCBC_MAC \ + --auth_op GENERATE --auth_algo aes-xcbc-mac \ --auth_key 10:11:12:13:14:15:16:17:18:19:1a:1b:1c:1d:1e:1f Refer to the *DPDK Getting Started Guide* for general information on running applications diff --git a/doc/guides/sample_app_ug/l2_forward_job_stats.rst b/doc/guides/sample_app_ug/l2_forward_job_stats.rst index 2444e36e..1029cc8f 100644 --- a/doc/guides/sample_app_ug/l2_forward_job_stats.rst +++ b/doc/guides/sample_app_ug/l2_forward_job_stats.rst @@ -140,7 +140,7 @@ thousands separator printing, issue the command: .. code-block:: console - $ ./build/l2fwd-jobstats -c f -n 4 -- -q 8 -p ffff -l + $ ./build/l2fwd-jobstats -l 0-3 -n 4 -- -q 8 -p ffff -l Refer to the *DPDK Getting Started Guide* for general information on running applications and the Environment Abstraction Layer (EAL) options. @@ -193,36 +193,25 @@ and the application to store network packet data: .. code-block:: c /* create the mbuf pool */ - l2fwd_pktmbuf_pool = - rte_mempool_create("mbuf_pool", NB_MBUF, - MBUF_SIZE, 32, - sizeof(struct rte_pktmbuf_pool_private), - rte_pktmbuf_pool_init, NULL, - rte_pktmbuf_init, NULL, - rte_socket_id(), 0); + l2fwd_pktmbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", NB_MBUF, + MEMPOOL_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, + rte_socket_id()); if (l2fwd_pktmbuf_pool == NULL) rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n"); The rte_mempool is a generic structure used to handle pools of objects. -In this case, it is necessary to create a pool that will be used by the driver, -which expects to have some reserved space in the mempool structure, -sizeof(struct rte_pktmbuf_pool_private) bytes. -The number of allocated pkt mbufs is NB_MBUF, with a size of MBUF_SIZE each. -A per-lcore cache of 32 mbufs is kept. +In this case, it is necessary to create a pool that will be used by the driver. +The number of allocated pkt mbufs is NB_MBUF, with a data room size of +RTE_MBUF_DEFAULT_BUF_SIZE each. +A per-lcore cache of MEMPOOL_CACHE_SIZE mbufs is kept. The memory is allocated in rte_socket_id() socket, but it is possible to extend this code to allocate one mbuf pool per socket. -Two callback pointers are also given to the rte_mempool_create() function: - -* The first callback pointer is to rte_pktmbuf_pool_init() and is used - to initialize the private data of the mempool, which is needed by the driver. - This function is provided by the mbuf API, but can be copied and extended by the developer. - -* The second callback pointer given to rte_mempool_create() is the mbuf initializer. - The default is used, that is, rte_pktmbuf_init(), which is provided in the rte_mbuf library. - If a more complex application wants to extend the rte_pktmbuf structure for its own needs, - a new function derived from rte_pktmbuf_init( ) can be created. +The rte_pktmbuf_pool_create() function uses the default mbuf pool and mbuf +initializers, respectively rte_pktmbuf_pool_init() and rte_pktmbuf_init(). +An advanced application may want to use the mempool API to create the +mbuf pool with more control. Driver Initialization ~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/guides/sample_app_ug/l2_forward_real_virtual.rst b/doc/guides/sample_app_ug/l2_forward_real_virtual.rst index cf15d1c3..f579c8fe 100644 --- a/doc/guides/sample_app_ug/l2_forward_real_virtual.rst +++ b/doc/guides/sample_app_ug/l2_forward_real_virtual.rst @@ -150,7 +150,7 @@ updating enabled, issue the command: .. code-block:: console - $ ./build/l2fwd -c f -n 4 -- -q 8 -p ffff + $ ./build/l2fwd -l 0-3 -n 4 -- -q 8 -p ffff Refer to the *DPDK Getting Started Guide* for general information on running applications and the Environment Abstraction Layer (EAL) options. @@ -207,31 +207,25 @@ and the application to store network packet data: /* create the mbuf pool */ - l2fwd_pktmbuf_pool = rte_mempool_create("mbuf_pool", NB_MBUF, MBUF_SIZE, 32, sizeof(struct rte_pktmbuf_pool_private), - rte_pktmbuf_pool_init, NULL, rte_pktmbuf_init, NULL, SOCKET0, 0); + l2fwd_pktmbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", NB_MBUF, + MEMPOOL_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, + rte_socket_id()); if (l2fwd_pktmbuf_pool == NULL) rte_panic("Cannot init mbuf pool\n"); The rte_mempool is a generic structure used to handle pools of objects. -In this case, it is necessary to create a pool that will be used by the driver, -which expects to have some reserved space in the mempool structure, -sizeof(struct rte_pktmbuf_pool_private) bytes. -The number of allocated pkt mbufs is NB_MBUF, with a size of MBUF_SIZE each. +In this case, it is necessary to create a pool that will be used by the driver. +The number of allocated pkt mbufs is NB_MBUF, with a data room size of +RTE_MBUF_DEFAULT_BUF_SIZE each. A per-lcore cache of 32 mbufs is kept. The memory is allocated in NUMA socket 0, but it is possible to extend this code to allocate one mbuf pool per socket. -Two callback pointers are also given to the rte_mempool_create() function: - -* The first callback pointer is to rte_pktmbuf_pool_init() and is used - to initialize the private data of the mempool, which is needed by the driver. - This function is provided by the mbuf API, but can be copied and extended by the developer. - -* The second callback pointer given to rte_mempool_create() is the mbuf initializer. - The default is used, that is, rte_pktmbuf_init(), which is provided in the rte_mbuf library. - If a more complex application wants to extend the rte_pktmbuf structure for its own needs, - a new function derived from rte_pktmbuf_init( ) can be created. +The rte_pktmbuf_pool_create() function uses the default mbuf pool and mbuf +initializers, respectively rte_pktmbuf_pool_init() and rte_pktmbuf_init(). +An advanced application may want to use the mempool API to create the +mbuf pool with more control. .. _l2_fwd_app_dvr_init: @@ -244,7 +238,7 @@ in the *DPDK Programmer's Guide* - Rel 1.4 EAR and the *DPDK API Reference*. .. code-block:: c - if (rte_eal_pci_probe() < 0) + if (rte_pci_probe() < 0) rte_exit(EXIT_FAILURE, "Cannot probe PCI\n"); nb_ports = rte_eth_dev_count(); @@ -285,7 +279,7 @@ Observe that: * rte_igb_pmd_init_all() simultaneously registers the driver as a PCI driver and as an Ethernet* Poll Mode Driver. -* rte_eal_pci_probe() parses the devices on the PCI bus and initializes recognized devices. +* rte_pci_probe() parses the devices on the PCI bus and initializes recognized devices. The next step is to configure the RX and TX queues. For each port, there is only one RX queue (only one lcore is able to poll a given port). diff --git a/doc/guides/sample_app_ug/l3_forward.rst b/doc/guides/sample_app_ug/l3_forward.rst index ab916b97..6a6b8fbe 100644 --- a/doc/guides/sample_app_ug/l3_forward.rst +++ b/doc/guides/sample_app_ug/l3_forward.rst @@ -129,43 +129,33 @@ Where, * ``--parse-ptype:`` Optional, set to use software to analyze packet type. Without this option, hardware will check the packet type. -For example, consider a dual processor socket platform where cores 0-7 and 16-23 appear on socket 0, while cores 8-15 and 24-31 appear on socket 1. -Let's say that the programmer wants to use memory from both NUMA nodes, the platform has only two ports, one connected to each NUMA node, -and the programmer wants to use two cores from each processor socket to do the packet processing. +For example, consider a dual processor socket platform with 8 physical cores, where cores 0-7 and 16-23 appear on socket 0, +while cores 8-15 and 24-31 appear on socket 1. -To enable L3 forwarding between two ports, using two cores, cores 1 and 2, from each processor, -while also taking advantage of local memory access by optimizing around NUMA, the programmer must enable two queues from each port, -pin to the appropriate cores and allocate memory from the appropriate NUMA node. This is achieved using the following command: +To enable L3 forwarding between two ports, assuming that both ports are in the same socket, using two cores, cores 1 and 2, +(which are in the same socket too), use the following command: .. code-block:: console - ./build/l3fwd -c 606 -n 4 -- -p 0x3 --config="(0,0,1),(0,1,2),(1,0,9),(1,1,10)" + ./build/l3fwd -l 1,2 -n 4 -- -p 0x3 --config="(0,0,1),(1,0,2)" In this command: -* The -c option enables cores 0, 1, 2, 3 +* The -l option enables cores 1, 2 * The -p option enables ports 0 and 1 -* The --config option enables two queues on each port and maps each (port,queue) pair to a specific core. - Logic to enable multiple RX queues using RSS and to allocate memory from the correct NUMA nodes - is included in the application and is done transparently. +* The --config option enables one queue on each port and maps each (port,queue) pair to a specific core. The following table shows the mapping in this example: +----------+-----------+-----------+-------------------------------------+ | **Port** | **Queue** | **lcore** | **Description** | | | | | | +----------+-----------+-----------+-------------------------------------+ -| 0 | 0 | 0 | Map queue 0 from port 0 to lcore 0. | +| 0 | 0 | 1 | Map queue 0 from port 0 to lcore 1. | | | | | | +----------+-----------+-----------+-------------------------------------+ -| 0 | 1 | 2 | Map queue 1 from port 0 to lcore 2. | -| | | | | -+----------+-----------+-----------+-------------------------------------+ -| 1 | 0 | 1 | Map queue 0 from port 1 to lcore 1. | -| | | | | -+----------+-----------+-----------+-------------------------------------+ -| 1 | 1 | 3 | Map queue 1 from port 1 to lcore 3. | +| 1 | 0 | 2 | Map queue 0 from port 1 to lcore 2. | | | | | | +----------+-----------+-----------+-------------------------------------+ diff --git a/doc/guides/sample_app_ug/l3_forward_access_ctrl.rst b/doc/guides/sample_app_ug/l3_forward_access_ctrl.rst index 4049e019..a6aa4fb1 100644 --- a/doc/guides/sample_app_ug/l3_forward_access_ctrl.rst +++ b/doc/guides/sample_app_ug/l3_forward_access_ctrl.rst @@ -306,48 +306,35 @@ where, * --no-numa: optional, disables numa awareness -As an example, consider a dual processor socket platform where cores 0, 2, 4, 6, 8 and 10 appear on socket 0, -while cores 1, 3, 5, 7, 9 and 11 appear on socket 1. -Let's say that the user wants to use memory from both NUMA nodes, -the platform has only two ports and the user wants to use two cores from each processor socket to do the packet processing. +For example, consider a dual processor socket platform with 8 physical cores, where cores 0-7 and 16-23 appear on socket 0, +while cores 8-15 and 24-31 appear on socket 1. -To enable L3 forwarding between two ports, using two cores from each processor, -while also taking advantage of local memory access by optimizing around NUMA, -the user must enable two queues from each port, -pin to the appropriate cores and allocate memory from the appropriate NUMA node. -This is achieved using the following command: +To enable L3 forwarding between two ports, assuming that both ports are in the same socket, using two cores, cores 1 and 2, +(which are in the same socket too), use the following command: .. code-block:: console - ./build/l3fwd-acl -c f -n 4 -- -p 0x3 --config="(0,0,0),(0,1,2),(1,0,1),(1,1,3)" --rule_ipv4="./rule_ipv4.db" -- rule_ipv6="./rule_ipv6.db" --scalar + ./build/l3fwd-acl -l 1,2 -n 4 -- -p 0x3 --config="(0,0,1),(1,0,2)" --rule_ipv4="./rule_ipv4.db" -- rule_ipv6="./rule_ipv6.db" --scalar In this command: -* The -c option enables cores 0, 1, 2, 3 +* The -l option enables cores 1, 2 * The -p option enables ports 0 and 1 -* The --config option enables two queues on each port and maps each (port,queue) pair to a specific core. - Logic to enable multiple RX queues using RSS and to allocate memory from the correct NUMA nodes is included in the application - and is done transparently. +* The --config option enables one queue on each port and maps each (port,queue) pair to a specific core. The following table shows the mapping in this example: - +----------+------------+-----------+------------------------------------------------+ - | **Port** | **Queue** | **lcore** | **Description** | - | | | | | - +==========+============+===========+================================================+ - | 0 | 0 | 0 | Map queue 0 from port 0 to lcore 0. | - | | | | | - +----------+------------+-----------+------------------------------------------------+ - | 0 | 1 | 2 | Map queue 1 from port 0 to lcore 2. | - | | | | | - +----------+------------+-----------+------------------------------------------------+ - | 1 | 0 | 1 | Map queue 0 from port 1 to lcore 1. | - | | | | | - +----------+------------+-----------+------------------------------------------------+ - | 1 | 1 | 3 | Map queue 1 from port 1 to lcore 3. | - | | | | | - +----------+------------+-----------+------------------------------------------------+ + +----------+------------+-----------+-------------------------------------+ + | **Port** | **Queue** | **lcore** | **Description** | + | | | | | + +==========+============+===========+=====================================+ + | 0 | 0 | 1 | Map queue 0 from port 0 to lcore 1. | + | | | | | + +----------+------------+-----------+-------------------------------------+ + | 1 | 0 | 2 | Map queue 0 from port 1 to lcore 2. | + | | | | | + +----------+------------+-----------+-------------------------------------+ * The --rule_ipv4 option specifies the reading of IPv4 rules sets from the ./ rule_ipv4.db file. diff --git a/doc/guides/sample_app_ug/l3_forward_virtual.rst b/doc/guides/sample_app_ug/l3_forward_virtual.rst index fa04722e..5f9d8948 100644 --- a/doc/guides/sample_app_ug/l3_forward_virtual.rst +++ b/doc/guides/sample_app_ug/l3_forward_virtual.rst @@ -110,40 +110,33 @@ where, * --no-numa: optional, disables numa awareness -For example, consider a dual processor socket platform where cores 0,2,4,6, 8, and 10 appear on socket 0, -while cores 1,3,5,7,9, and 11 appear on socket 1. -Let's say that the programmer wants to use memory from both NUMA nodes, -the platform has only two ports and the programmer wants to use one core from each processor socket to do the packet processing -since only one Rx/Tx queue pair can be used in virtualization mode. +For example, consider a dual processor socket platform with 8 physical cores, where cores 0-7 and 16-23 appear on socket 0, +while cores 8-15 and 24-31 appear on socket 1. -To enable L3 forwarding between two ports, using one core from each processor, -while also taking advantage of local memory accesses by optimizing around NUMA, -the programmer can pin to the appropriate cores and allocate memory from the appropriate NUMA node. -This is achieved using the following command: +To enable L3 forwarding between two ports, assuming that both ports are in the same socket, using two cores, cores 1 and 2, +(which are in the same socket too), use the following command: .. code-block:: console - ./build/l3fwd-vf -c 0x03 -n 3 -- -p 0x3 --config="(0,0,0),(1,0,1)" + ./build/l3fwd-vf -l 1,2 -n 4 -- -p 0x3 --config="(0,0,1),(1,0,2)" In this command: -* The -c option enables cores 0 and 1 +* The -l option enables cores 1 and 2 * The -p option enables ports 0 and 1 * The --config option enables one queue on each port and maps each (port,queue) pair to a specific core. - Logic to enable multiple RX queues using RSS and to allocate memory from the correct NUMA nodes - is included in the application and is done transparently. The following table shows the mapping in this example: +----------+-----------+-----------+------------------------------------+ | **Port** | **Queue** | **lcore** | **Description** | | | | | | +==========+===========+===========+====================================+ - | 0 | 0 | 0 | Map queue 0 from port 0 to lcore 0 | + | 0 | 0 | 1 | Map queue 0 from port 0 to lcore 1 | | | | | | +----------+-----------+-----------+------------------------------------+ - | 1 | 1 | 1 | Map queue 0 from port 1 to lcore 1 | + | 1 | 0 | 2 | Map queue 0 from port 1 to lcore 2 | | | | | | +----------+-----------+-----------+------------------------------------+ diff --git a/doc/guides/sample_app_ug/link_status_intr.rst b/doc/guides/sample_app_ug/link_status_intr.rst index 779df97d..f9af4749 100644 --- a/doc/guides/sample_app_ug/link_status_intr.rst +++ b/doc/guides/sample_app_ug/link_status_intr.rst @@ -104,7 +104,7 @@ issue the command: .. code-block:: console - $ ./build/link_status_interrupt -c f -n 4-- -q 8 -p ffff + $ ./build/link_status_interrupt -l 0-3 -n 4-- -q 8 -p ffff Refer to the *DPDK Getting Started Guide* for general information on running applications and the Environment Abstraction Layer (EAL) options. @@ -138,7 +138,7 @@ To fully understand this code, it is recommended to study the chapters that rela .. code-block:: c - if (rte_eal_pci_probe() < 0) + if (rte_pci_probe() < 0) rte_exit(EXIT_FAILURE, "Cannot probe PCI\n"); nb_ports = rte_eth_dev_count(); @@ -171,7 +171,7 @@ To fully understand this code, it is recommended to study the chapters that rela Observe that: -* rte_eal_pci_probe() parses the devices on the PCI bus and initializes recognized devices. +* rte_pci_probe() parses the devices on the PCI bus and initializes recognized devices. The next step is to configure the RX and TX queues. For each port, there is only one RX queue (only one lcore is able to poll a given port). diff --git a/doc/guides/sample_app_ug/load_balancer.rst b/doc/guides/sample_app_ug/load_balancer.rst index fdd8cbd3..e101a5f2 100644 --- a/doc/guides/sample_app_ug/load_balancer.rst +++ b/doc/guides/sample_app_ug/load_balancer.rst @@ -178,7 +178,7 @@ Example: .. code-block:: console - ./load_balancer -c 0xf8 -n 4 -- --rx "(0,0,3),(1,0,3)" --tx "(0,3),(1,3)" --w "4,5,6,7" --lpm "1.0.0.0/24=>0; 1.0.1.0/24=>1;" --pos-lb 29 + ./load_balancer -l 3-7 -n 4 -- --rx "(0,0,3),(1,0,3)" --tx "(0,3),(1,3)" --w "4,5,6,7" --lpm "1.0.0.0/24=>0; 1.0.1.0/24=>1;" --pos-lb 29 There is a single I/O lcore (lcore 3) that handles RX and TX for two NIC ports (ports 0 and 1) that handles packets to/from four worker lcores (lcores 4, 5, 6 and 7) that diff --git a/doc/guides/sample_app_ug/multi_process.rst b/doc/guides/sample_app_ug/multi_process.rst index 35714905..d4df2fa7 100644 --- a/doc/guides/sample_app_ug/multi_process.rst +++ b/doc/guides/sample_app_ug/multi_process.rst @@ -82,11 +82,11 @@ Running the Application ^^^^^^^^^^^^^^^^^^^^^^^ To run the application, start one copy of the simple_mp binary in one terminal, -passing at least two cores in the coremask, as follows: +passing at least two cores in the coremask/corelist, as follows: .. code-block:: console - ./build/simple_mp -c 3 -n 4 --proc-type=primary + ./build/simple_mp -l 0-1 -n 4 --proc-type=primary For the first DPDK process run, the proc-type flag can be omitted or set to auto, since all DPDK processes will default to being a primary instance, @@ -95,7 +95,7 @@ The process should start successfully and display a command prompt as follows: .. code-block:: console - $ ./build/simple_mp -c 3 -n 4 --proc-type=primary + $ ./build/simple_mp -l 0-1 -n 4 --proc-type=primary EAL: coremask set to 3 EAL: Detected lcore 0 on socket 0 EAL: Detected lcore 1 on socket 0 @@ -119,11 +119,11 @@ The process should start successfully and display a command prompt as follows: simple_mp > To run the secondary process to communicate with the primary process, -again run the same binary setting at least two cores in the coremask: +again run the same binary setting at least two cores in the coremask/corelist: .. code-block:: console - ./build/simple_mp -c C -n 4 --proc-type=secondary + ./build/simple_mp -l 2-3 -n 4 --proc-type=secondary When running a secondary process such as that shown above, the proc-type parameter can again be specified as auto. However, omitting the parameter altogether will cause the process to try and start as a primary rather than secondary process. @@ -229,10 +229,10 @@ the following commands can be used (assuming run as root): .. code-block:: console - # ./build/symmetric_mp -c 2 -n 4 --proc-type=auto -- -p 3 --num-procs=4 --proc-id=0 - # ./build/symmetric_mp -c 4 -n 4 --proc-type=auto -- -p 3 --num-procs=4 --proc-id=1 - # ./build/symmetric_mp -c 8 -n 4 --proc-type=auto -- -p 3 --num-procs=4 --proc-id=2 - # ./build/symmetric_mp -c 10 -n 4 --proc-type=auto -- -p 3 --num-procs=4 --proc-id=3 + # ./build/symmetric_mp -l 1 -n 4 --proc-type=auto -- -p 3 --num-procs=4 --proc-id=0 + # ./build/symmetric_mp -l 2 -n 4 --proc-type=auto -- -p 3 --num-procs=4 --proc-id=1 + # ./build/symmetric_mp -l 3 -n 4 --proc-type=auto -- -p 3 --num-procs=4 --proc-id=2 + # ./build/symmetric_mp -l 4 -n 4 --proc-type=auto -- -p 3 --num-procs=4 --proc-id=3 .. note:: @@ -254,7 +254,7 @@ How the Application Works ^^^^^^^^^^^^^^^^^^^^^^^^^ The initialization calls in both the primary and secondary instances are the same for the most part, -calling the rte_eal_init(), 1 G and 10 G driver initialization and then rte_eal_pci_probe() functions. +calling the rte_eal_init(), 1 G and 10 G driver initialization and then rte_pci_probe() functions. Thereafter, the initialization done depends on whether the process is configured as a primary or secondary instance. In the primary instance, a memory pool is created for the packet mbufs and the network ports to be used are initialized - @@ -318,8 +318,8 @@ In addition to the EAL parameters, the application- specific parameters are: .. note:: - In the server process, a single thread, the master thread, that is, the lowest numbered lcore in the coremask, performs all packet I/O. - If a coremask is specified with more than a single lcore bit set in it, + In the server process, a single thread, the master thread, that is, the lowest numbered lcore in the coremask/corelist, performs all packet I/O. + If a coremask/corelist is specified with more than a single lcore bit set in it, an additional lcore will be used for a thread to periodically print packet count statistics. Since the server application stores configuration data in shared memory, including the network ports to be used, @@ -329,9 +329,9 @@ the following commands could be used: .. code-block:: console - # ./mp_server/build/mp_server -c 6 -n 4 -- -p 3 -n 2 - # ./mp_client/build/mp_client -c 8 -n 4 --proc-type=auto -- -n 0 - # ./mp_client/build/mp_client -c 10 -n 4 --proc-type=auto -- -n 1 + # ./mp_server/build/mp_server -l 1-2 -n 4 -- -p 3 -n 2 + # ./mp_client/build/mp_client -l 3 -n 4 --proc-type=auto -- -n 0 + # ./mp_client/build/mp_client -l 4 -n 4 --proc-type=auto -- -n 1 .. note:: @@ -524,7 +524,7 @@ The command is as follows: .. code-block:: console - #./build/l2fwd_fork -c 1c -n 4 -- -p 3 -f + #./build/l2fwd_fork -l 2-4 -n 4 -- -p 3 -f This example provides another -f option to specify the use of floating process. If not specified, the example will use a pinned process to perform the L2 forwarding task. diff --git a/doc/guides/sample_app_ug/netmap_compatibility.rst b/doc/guides/sample_app_ug/netmap_compatibility.rst index 41f05186..030fd980 100644 --- a/doc/guides/sample_app_ug/netmap_compatibility.rst +++ b/doc/guides/sample_app_ug/netmap_compatibility.rst @@ -104,7 +104,7 @@ Porting Netmap applications typically involves two major steps: Since the ``compat_netmap`` functions have the same signature as the usual libc calls, the change is trivial in most cases. -The usual DPDK initialization code involving ``rte_eal_init()`` and ``rte_eal_pci_probe()`` +The usual DPDK initialization code involving ``rte_eal_init()`` and ``rte_pci_probe()`` has to be added to the Netmap application in the same way it is used in all other DPDK sample applications. Please refer to the *DPDK Programmer's Guide* and example source code for details about initialization. diff --git a/doc/guides/sample_app_ug/performance_thread.rst b/doc/guides/sample_app_ug/performance_thread.rst index d7d9b084..a55a6246 100644 --- a/doc/guides/sample_app_ug/performance_thread.rst +++ b/doc/guides/sample_app_ug/performance_thread.rst @@ -107,6 +107,7 @@ The application has a number of command line options:: --tx(lcore,thread)[,(lcore,thread)] [--enable-jumbo] [--max-pkt-len PKTLEN]] [--no-numa] [--hash-entry-num] [--ipv6] [--no-lthreads] [--stat-lcore lcore] + [--parse-ptype] Where: @@ -142,6 +143,9 @@ Where: * ``--stat-lcore``: optional, run CPU load stats collector on the specified lcore. +* ``--parse-ptype:`` optional, set to use software to analyze packet type. + Without this option, hardware will check the packet type. + The parameters of the ``--rx`` and ``--tx`` options are: * ``--rx`` parameters @@ -183,14 +187,14 @@ in ``--rx/--tx`` are used to affinitize threads to the selected scheduler. For example, the following places every l-thread on different lcores:: - l3fwd-thread -c ff -n 2 -- -P -p 3 \ + l3fwd-thread -l 0-7 -n 2 -- -P -p 3 \ --rx="(0,0,0,0)(1,0,1,1)" \ --tx="(2,0)(3,1)" The following places RX l-threads on lcore 0 and TX l-threads on lcore 1 and 2 and so on:: - l3fwd-thread -c ff -n 2 -- -P -p 3 \ + l3fwd-thread -l 0-7 -n 2 -- -P -p 3 \ --rx="(0,0,0,0)(1,0,0,1)" \ --tx="(1,0)(2,1)" @@ -206,7 +210,7 @@ place every RX and TX thread on different lcores. For example, the following places every EAL thread on different lcores:: - l3fwd-thread -c ff -n 2 -- -P -p 3 \ + l3fwd-thread -l 0-7 -n 2 -- -P -p 3 \ --rx="(0,0,0,0)(1,0,1,1)" \ --tx="(2,0)(3,1)" \ --no-lthreads @@ -218,7 +222,7 @@ parameter is used. The following places RX EAL threads on lcore 0 and TX EAL threads on lcore 1 and 2 and so on:: - l3fwd-thread -c ff -n 2 --lcores="(0,1)@0,(2,3)@1" -- -P -p 3 \ + l3fwd-thread -l 0-7 -n 2 --lcores="(0,1)@0,(2,3)@1" -- -P -p 3 \ --rx="(0,0,0,0)(1,0,1,1)" \ --tx="(2,0)(3,1)" \ --no-lthreads @@ -232,13 +236,13 @@ and its corresponding EAL threads command line can be realized as follows: a) Start every thread on different scheduler (1:1):: - l3fwd-thread -c ff -n 2 -- -P -p 3 \ + l3fwd-thread -l 0-7 -n 2 -- -P -p 3 \ --rx="(0,0,0,0)(1,0,1,1)" \ --tx="(2,0)(3,1)" EAL thread equivalent:: - l3fwd-thread -c ff -n 2 -- -P -p 3 \ + l3fwd-thread -l 0-7 -n 2 -- -P -p 3 \ --rx="(0,0,0,0)(1,0,1,1)" \ --tx="(2,0)(3,1)" \ --no-lthreads @@ -247,13 +251,13 @@ b) Start all threads on one core (N:1). Start 4 L-threads on lcore 0:: - l3fwd-thread -c ff -n 2 -- -P -p 3 \ + l3fwd-thread -l 0-7 -n 2 -- -P -p 3 \ --rx="(0,0,0,0)(1,0,0,1)" \ --tx="(0,0)(0,1)" Start 4 EAL threads on cpu-set 0:: - l3fwd-thread -c ff -n 2 --lcores="(0-3)@0" -- -P -p 3 \ + l3fwd-thread -l 0-7 -n 2 --lcores="(0-3)@0" -- -P -p 3 \ --rx="(0,0,0,0)(1,0,0,1)" \ --tx="(2,0)(3,1)" \ --no-lthreads @@ -262,14 +266,14 @@ c) Start threads on different cores (N:M). Start 2 L-threads for RX on lcore 0, and 2 L-threads for TX on lcore 1:: - l3fwd-thread -c ff -n 2 -- -P -p 3 \ + l3fwd-thread -l 0-7 -n 2 -- -P -p 3 \ --rx="(0,0,0,0)(1,0,0,1)" \ --tx="(1,0)(1,1)" Start 2 EAL threads for RX on cpu-set 0, and 2 EAL threads for TX on cpu-set 1:: - l3fwd-thread -c ff -n 2 --lcores="(0-1)@0,(2-3)@1" -- -P -p 3 \ + l3fwd-thread -l 0-7 -n 2 --lcores="(0-1)@0,(2-3)@1" -- -P -p 3 \ --rx="(0,0,0,0)(1,0,1,1)" \ --tx="(2,0)(3,1)" \ --no-lthreads diff --git a/doc/guides/sample_app_ug/ptpclient.rst b/doc/guides/sample_app_ug/ptpclient.rst index 6e425b79..d3ef1d11 100644 --- a/doc/guides/sample_app_ug/ptpclient.rst +++ b/doc/guides/sample_app_ug/ptpclient.rst @@ -119,7 +119,7 @@ To run the example in a ``linuxapp`` environment: .. code-block:: console - ./build/ptpclient -c 2 -n 4 -- -p 0x1 -T 0 + ./build/ptpclient -l 1 -n 4 -- -p 0x1 -T 0 Refer to *DPDK Getting Started Guide* for general information on running applications and the Environment Abstraction Layer (EAL) options. @@ -171,15 +171,8 @@ used by the application: .. code-block:: c - mbuf_pool = rte_mempool_create("MBUF_POOL", - NUM_MBUFS * nb_ports, - MBUF_SIZE, - MBUF_CACHE_SIZE, - sizeof(struct rte_pktmbuf_pool_private), - rte_pktmbuf_pool_init, NULL, - rte_pktmbuf_init, NULL, - rte_socket_id(), - 0); + mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", NUM_MBUFS * nb_ports, + MBUF_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); Mbufs are the packet buffer structure used by DPDK. They are explained in detail in the "Mbuf Library" section of the *DPDK Programmer's Guide*. diff --git a/doc/guides/sample_app_ug/qos_scheduler.rst b/doc/guides/sample_app_ug/qos_scheduler.rst index 7f9e9259..a6654cb5 100644 --- a/doc/guides/sample_app_ug/qos_scheduler.rst +++ b/doc/guides/sample_app_ug/qos_scheduler.rst @@ -289,7 +289,7 @@ The following is an example command with a single packet flow configuration: .. code-block:: console - ./qos_sched -c a2 -n 4 -- --pfc "3,2,5,7" --cfg ./profile.cfg + ./qos_sched -l 1,5,7 -n 4 -- --pfc "3,2,5,7" --cfg ./profile.cfg This example uses a single packet flow configuration which creates one RX thread on lcore 5 reading from port 3 and a worker thread on lcore 7 writing to port 2. @@ -298,12 +298,12 @@ Another example with 2 packet flow configurations using different ports but shar .. code-block:: console - ./qos_sched -c c6 -n 4 -- --pfc "3,2,2,6,7" --pfc "1,0,2,6,7" --cfg ./profile.cfg + ./qos_sched -l 1,2,6,7 -n 4 -- --pfc "3,2,2,6,7" --pfc "1,0,2,6,7" --cfg ./profile.cfg Note that independent cores for the packet flow configurations for each of the RX, WT and TX thread are also supported, providing flexibility to balance the work. -The EAL coremask is constrained to contain the default mastercore 1 and the RX, WT and TX cores only. +The EAL coremask/corelist is constrained to contain the default mastercore 1 and the RX, WT and TX cores only. Explanation ----------- diff --git a/doc/guides/sample_app_ug/quota_watermark.rst b/doc/guides/sample_app_ug/quota_watermark.rst index c56683aa..2c3a4320 100644 --- a/doc/guides/sample_app_ug/quota_watermark.rst +++ b/doc/guides/sample_app_ug/quota_watermark.rst @@ -1,5 +1,5 @@ .. BSD LICENSE - Copyright(c) 2010-2014 Intel Corporation. All rights reserved. + Copyright(c) 2010-2017 Intel Corporation. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without @@ -31,11 +31,13 @@ Quota and Watermark Sample Application ====================================== -The Quota and Watermark sample application is a simple example of packet processing using Data Plane Development Kit (DPDK) that -showcases the use of a quota as the maximum number of packets enqueue/dequeue at a time and low and high watermarks -to signal low and high ring usage respectively. +The Quota and Watermark sample application is a simple example of packet +processing using Data Plane Development Kit (DPDK) that showcases the use +of a quota as the maximum number of packets enqueue/dequeue at a time and +low and high thresholds, or watermarks, to signal low and high ring usage +respectively. -Additionally, it shows how ring watermarks can be used to feedback congestion notifications to data producers by +Additionally, it shows how the thresholds can be used to feedback congestion notifications to data producers by temporarily stopping processing overloaded rings and sending Ethernet flow control frames. This sample application is split in two parts: @@ -64,7 +66,7 @@ each stage of which being connected by rings, as shown in :numref:`figure_pipeli An adjustable quota value controls how many packets are being moved through the pipeline per enqueue and dequeue. -Adjustable watermark values associated with the rings control a back-off mechanism that +Adjustable threshold values associated with the rings control a back-off mechanism that tries to prevent the pipeline from being overloaded by: * Stopping enqueuing on rings for which the usage has crossed the high watermark threshold @@ -136,7 +138,7 @@ issue the following command: .. code-block:: console - ./qw/build/qw -c f -n 4 -- -p 5 + ./qw/build/qw -l 0-3 -n 4 -- -p 5 Refer to the *DPDK Getting Started Guide* for general information on running applications and the Environment Abstraction Layer (EAL) options. @@ -157,7 +159,7 @@ To run the application in a linuxapp environment on logical core 0, issue the fo .. code-block:: console - ./qwctl/build/qwctl -c 1 -n 4 --proc-type=secondary + ./qwctl/build/qwctl -l 0 -n 4 --proc-type=secondary Refer to the *DPDK Getting Started* Guide for general information on running applications and the Environment Abstraction Layer (EAL) options. @@ -202,9 +204,9 @@ Then, a call to init_dpdk(), defined in init.c, is made to initialize the poll m /* Bind the drivers to usable devices */ - ret = rte_eal_pci_probe(); + ret = rte_pci_probe(); if (ret < 0) - rte_exit(EXIT_FAILURE, "rte_eal_pci_probe(): error %d\n", ret); + rte_exit(EXIT_FAILURE, "rte_pci_probe(): error %d\n", ret); if (rte_eth_dev_count() < 2) rte_exit(EXIT_FAILURE, "Not enough Ethernet port available\n"); @@ -216,25 +218,26 @@ in the *DPDK Getting Started Guide* and the *DPDK API Reference*. Shared Variables Setup ^^^^^^^^^^^^^^^^^^^^^^ -The quota and low_watermark shared variables are put into an rte_memzone using a call to setup_shared_variables(): +The quota and high and low watermark shared variables are put into an rte_memzone using a call to setup_shared_variables(): .. code-block:: c void setup_shared_variables(void) { - const struct rte_memzone *qw_memzone; - - qw_memzone = rte_memzone_reserve(QUOTA_WATERMARK_MEMZONE_NAME, 2 * sizeof(int), rte_socket_id(), RTE_MEMZONE_2MB); + const struct rte_memzone *qw_memzone; - if (qw_memzone == NULL) - rte_exit(EXIT_FAILURE, "%s\n", rte_strerror(rte_errno)); + qw_memzone = rte_memzone_reserve(QUOTA_WATERMARK_MEMZONE_NAME, + 3 * sizeof(int), rte_socket_id(), 0); + if (qw_memzone == NULL) + rte_exit(EXIT_FAILURE, "%s\n", rte_strerror(rte_errno)); - quota = qw_memzone->addr; - low_watermark = (unsigned int *) qw_memzone->addr + sizeof(int); - } + quota = qw_memzone->addr; + low_watermark = (unsigned int *) qw_memzone->addr + 1; + high_watermark = (unsigned int *) qw_memzone->addr + 2; + } -These two variables are initialized to a default value in main() and +These three variables are initialized to a default value in main() and can be changed while qw is running using the qwctl control program. Application Arguments @@ -254,32 +257,24 @@ It contains a set of mbuf objects that are used by the driver and the applicatio .. code-block:: c /* Create a pool of mbuf to store packets */ - - mbuf_pool = rte_mempool_create("mbuf_pool", MBUF_PER_POOL, MBUF_SIZE, 32, sizeof(struct rte_pktmbuf_pool_private), - rte_pktmbuf_pool_init, NULL, rte_pktmbuf_init, NULL, rte_socket_id(), 0); + mbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", MBUF_PER_POOL, 32, 0, + MBUF_DATA_SIZE, rte_socket_id()); if (mbuf_pool == NULL) rte_panic("%s\n", rte_strerror(rte_errno)); The rte_mempool is a generic structure used to handle pools of objects. -In this case, it is necessary to create a pool that will be used by the driver, -which expects to have some reserved space in the mempool structure, sizeof(struct rte_pktmbuf_pool_private) bytes. +In this case, it is necessary to create a pool that will be used by the driver. -The number of allocated pkt mbufs is MBUF_PER_POOL, with a size of MBUF_SIZE each. +The number of allocated pkt mbufs is MBUF_PER_POOL, with a data room size +of MBUF_DATA_SIZE each. A per-lcore cache of 32 mbufs is kept. The memory is allocated in on the master lcore's socket, but it is possible to extend this code to allocate one mbuf pool per socket. -Two callback pointers are also given to the rte_mempool_create() function: - -* The first callback pointer is to rte_pktmbuf_pool_init() and is used to initialize the private data of the mempool, - which is needed by the driver. - This function is provided by the mbuf API, but can be copied and extended by the developer. - -* The second callback pointer given to rte_mempool_create() is the mbuf initializer. - -The default is used, that is, rte_pktmbuf_init(), which is provided in the rte_mbuf library. -If a more complex application wants to extend the rte_pktmbuf structure for its own needs, -a new function derived from rte_pktmbuf_init() can be created. +The rte_pktmbuf_pool_create() function uses the default mbuf pool and mbuf +initializers, respectively rte_pktmbuf_pool_init() and rte_pktmbuf_init(). +An advanced application may want to use the mempool API to create the +mbuf pool with more control. Ports Configuration and Pairing ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -357,27 +352,37 @@ This is done using the following code: /* Process each port round robin style */ for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) { - if (!is_bit_set(port_id, portmask)) - continue; - - ring = rings[lcore_id][port_id]; - - if (ring_state[port_id] != RING_READY) { - if (rte_ring_count(ring) > *low_watermark) - continue; - else - ring_state[port_id] = RING_READY; - } - - /* Enqueue received packets on the RX ring */ - - nb_rx_pkts = rte_eth_rx_burst(port_id, 0, pkts, *quota); - - ret = rte_ring_enqueue_bulk(ring, (void *) pkts, nb_rx_pkts); - if (ret == -EDQUOT) { - ring_state[port_id] = RING_OVERLOADED; - send_pause_frame(port_id, 1337); - } + if (!is_bit_set(port_id, portmask)) + continue; + + ring = rings[lcore_id][port_id]; + + if (ring_state[port_id] != RING_READY) { + if (rte_ring_count(ring) > *low_watermark) + continue; + else + ring_state[port_id] = RING_READY; + } + + /* Enqueue received packets on the RX ring */ + nb_rx_pkts = rte_eth_rx_burst(port_id, 0, pkts, + (uint16_t) *quota); + ret = rte_ring_enqueue_bulk(ring, (void *) pkts, + nb_rx_pkts, &free); + if (RING_SIZE - free > *high_watermark) { + ring_state[port_id] = RING_OVERLOADED; + send_pause_frame(port_id, 1337); + } + + if (ret == 0) { + + /* + * Return mbufs to the pool, + * effectively dropping packets + */ + for (i = 0; i < nb_rx_pkts; i++) + rte_pktmbuf_free(pkts[i]); + } } For each port in the port mask, the corresponding ring's pointer is fetched into ring and that ring's state is checked: @@ -398,30 +403,40 @@ This thread is running on most of the logical cores to create and arbitrarily lo previous_lcore_id = get_previous_lcore_id(lcore_id); for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) { - if (!is_bit_set(port_id, portmask)) - continue; - - tx = rings[lcore_id][port_id]; - rx = rings[previous_lcore_id][port_id]; - if (ring_state[port_id] != RING_READY) { - if (rte_ring_count(tx) > *low_watermark) - continue; - else - ring_state[port_id] = RING_READY; - } - - /* Dequeue up to quota mbuf from rx */ - - nb_dq_pkts = rte_ring_dequeue_burst(rx, pkts, *quota); - - if (unlikely(nb_dq_pkts < 0)) - continue; - - /* Enqueue them on tx */ - - ret = rte_ring_enqueue_bulk(tx, pkts, nb_dq_pkts); - if (ret == -EDQUOT) - ring_state[port_id] = RING_OVERLOADED; + if (!is_bit_set(port_id, portmask)) + continue; + + tx = rings[lcore_id][port_id]; + rx = rings[previous_lcore_id][port_id]; + + if (ring_state[port_id] != RING_READY) { + if (rte_ring_count(tx) > *low_watermark) + continue; + else + ring_state[port_id] = RING_READY; + } + + /* Dequeue up to quota mbuf from rx */ + nb_dq_pkts = rte_ring_dequeue_burst(rx, pkts, + *quota, NULL); + if (unlikely(nb_dq_pkts < 0)) + continue; + + /* Enqueue them on tx */ + ret = rte_ring_enqueue_bulk(tx, pkts, + nb_dq_pkts, &free); + if (RING_SIZE - free > *high_watermark) + ring_state[port_id] = RING_OVERLOADED; + + if (ret == 0) { + + /* + * Return mbufs to the pool, + * effectively dropping packets + */ + for (i = 0; i < nb_dq_pkts; i++) + rte_pktmbuf_free(pkts[i]); + } } The thread's logic works mostly like receive_stage(), @@ -490,5 +505,6 @@ low_watermark from the rte_memzone previously created by qw. quota = qw_memzone->addr; - low_watermark = (unsigned int *) qw_memzone->addr + sizeof(int); + low_watermark = (unsigned int *) qw_memzone->addr + 1; + high_watermark = (unsigned int *) qw_memzone->addr + 2; } diff --git a/doc/guides/sample_app_ug/rxtx_callbacks.rst b/doc/guides/sample_app_ug/rxtx_callbacks.rst index 9df57ed5..8d1bb86f 100644 --- a/doc/guides/sample_app_ug/rxtx_callbacks.rst +++ b/doc/guides/sample_app_ug/rxtx_callbacks.rst @@ -85,7 +85,7 @@ To run the example in a ``linuxapp`` environment: .. code-block:: console - ./build/rxtx_callbacks -c 2 -n 4 + ./build/rxtx_callbacks -l 1 -n 4 Refer to *DPDK Getting Started Guide* for general information on running applications and the Environment Abstraction Layer (EAL) options. diff --git a/doc/guides/sample_app_ug/server_node_efd.rst b/doc/guides/sample_app_ug/server_node_efd.rst new file mode 100644 index 00000000..c2a5f20a --- /dev/null +++ b/doc/guides/sample_app_ug/server_node_efd.rst @@ -0,0 +1,494 @@ +.. BSD LICENSE + Copyright(c) 2016-2017 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Server-Node EFD Sample Application +================================== + +This sample application demonstrates the use of EFD library as a flow-level +load balancer, for more information about the EFD Library please refer to the +DPDK programmer's guide. + +This sample application is a variant of the +:ref:`client-server sample application <multi_process_app>` +where a specific target node is specified for every and each flow +(not in a round-robin fashion as the original load balancing sample application). + +Overview +-------- + +The architecture of the EFD flow-based load balancer sample application is +presented in the following figure. + +.. _figure_efd_sample_app_overview: + +.. figure:: img/server_node_efd.* + + Using EFD as a Flow-Level Load Balancer + +As shown in :numref:`figure_efd_sample_app_overview`, +the sample application consists of a front-end node (server) +using the EFD library to create a load-balancing table for flows, +for each flow a target backend worker node is specified. The EFD table does not +store the flow key (unlike a regular hash table), and hence, it can +individually load-balance millions of flows (number of targets * maximum number +of flows fit in a flow table per target) while still fitting in CPU cache. + +It should be noted that although they are referred to as nodes, the frontend +server and worker nodes are processes running on the same platform. + +Front-end Server +~~~~~~~~~~~~~~~~ + +Upon initializing, the frontend server node (process) creates a flow +distributor table (based on the EFD library) which is populated with flow +information and its intended target node. + +The sample application assigns a specific target node_id (process) for each of +the IP destination addresses as follows: + +.. code-block:: c + + node_id = i % num_nodes; /* Target node id is generated */ + ip_dst = rte_cpu_to_be_32(i); /* Specific ip destination address is + assigned to this target node */ + +then the pair of <key,target> is inserted into the flow distribution table. + +The main loop of the server process receives a burst of packets, then for +each packet, a flow key (IP destination address) is extracted. The flow +distributor table is looked up and the target node id is returned. Packets are +then enqueued to the specified target node id. + +It should be noted that flow distributor table is not a membership test table. +I.e. if the key has already been inserted the target node id will be correct, +but for new keys the flow distributor table will return a value (which can be +valid). + +Backend Worker Nodes +~~~~~~~~~~~~~~~~~~~~ + +Upon initializing, the worker node (process) creates a flow table (a regular +hash table that stores the key default size 1M flows) which is populated with +only the flow information that is serviced at this node. This flow key is +essential to point out new keys that have not been inserted before. + +The worker node's main loop is simply receiving packets then doing a hash table +lookup. If a match occurs then statistics are updated for flows serviced by +this node. If no match is found in the local hash table then this indicates +that this is a new flow, which is dropped. + + +Compiling the Application +------------------------- + +The sequence of steps used to build the application is: + +#. Export the required environment variables: + + .. code-block:: console + + export RTE_SDK=/path/to/rte_sdk + export RTE_TARGET=x86_64-native-linuxapp-gcc + +#. Build the application executable file: + + .. code-block:: console + + cd ${RTE_SDK}/examples/server_node_efd/ + make + + For more details on how to build the DPDK libraries and sample + applications, + please refer to the *DPDK Getting Started Guide.* + + +Running the Application +----------------------- + +The application has two binaries to be run: the front-end server +and the back-end node. + +The frontend server (server) has the following command line options:: + + ./server [EAL options] -- -p PORTMASK -n NUM_NODES -f NUM_FLOWS + +Where, + +* ``-p PORTMASK:`` Hexadecimal bitmask of ports to configure +* ``-n NUM_NODES:`` Number of back-end nodes that will be used +* ``-f NUM_FLOWS:`` Number of flows to be added in the EFD table (1 million, by default) + +The back-end node (node) has the following command line options:: + + ./node [EAL options] -- -n NODE_ID + +Where, + +* ``-n NODE_ID:`` Node ID, which cannot be equal or higher than NUM_MODES + + +First, the server app must be launched, with the number of nodes that will be run. +Once it has been started, the node instances can be run, with different NODE_ID. +These instances have to be run as secondary processes, with ``--proc-type=secondary`` +in the EAL options, which will attach to the primary process memory, and therefore, +they can access the queues created by the primary process to distribute packets. + +To successfully run the application, the command line used to start the +application has to be in sync with the traffic flows configured on the traffic +generator side. + +For examples of application command lines and traffic generator flows, please +refer to the DPDK Test Report. For more details on how to set up and run the +sample applications provided with DPDK package, please refer to the +:ref:`DPDK Getting Started Guide for Linux <linux_gsg>` and +:ref:`DPDK Getting Started Guide for FreeBSD <freebsd_gsg>`. + + +Explanation +----------- + +As described in previous sections, there are two processes in this example. + +The first process, the front-end server, creates and populates the EFD table, +which is used to distribute packets to nodes, which the number of flows +specified in the command line (1 million, by default). + + +.. code-block:: c + + static void + create_efd_table(void) + { + uint8_t socket_id = rte_socket_id(); + + /* create table */ + efd_table = rte_efd_create("flow table", num_flows * 2, sizeof(uint32_t), + 1 << socket_id, socket_id); + + if (efd_table == NULL) + rte_exit(EXIT_FAILURE, "Problem creating the flow table\n"); + } + + static void + populate_efd_table(void) + { + unsigned int i; + int32_t ret; + uint32_t ip_dst; + uint8_t socket_id = rte_socket_id(); + uint64_t node_id; + + /* Add flows in table */ + for (i = 0; i < num_flows; i++) { + node_id = i % num_nodes; + + ip_dst = rte_cpu_to_be_32(i); + ret = rte_efd_update(efd_table, socket_id, + (void *)&ip_dst, (efd_value_t)node_id); + if (ret < 0) + rte_exit(EXIT_FAILURE, "Unable to add entry %u in " + "EFD table\n", i); + } + + printf("EFD table: Adding 0x%x keys\n", num_flows); + } + +After initialization, packets are received from the enabled ports, and the IPv4 +address from the packets is used as a key to look up in the EFD table, +which tells the node where the packet has to be distributed. + +.. code-block:: c + + static void + process_packets(uint32_t port_num __rte_unused, struct rte_mbuf *pkts[], + uint16_t rx_count, unsigned int socket_id) + { + uint16_t i; + uint8_t node; + efd_value_t data[EFD_BURST_MAX]; + const void *key_ptrs[EFD_BURST_MAX]; + + struct ipv4_hdr *ipv4_hdr; + uint32_t ipv4_dst_ip[EFD_BURST_MAX]; + + for (i = 0; i < rx_count; i++) { + /* Handle IPv4 header.*/ + ipv4_hdr = rte_pktmbuf_mtod_offset(pkts[i], struct ipv4_hdr *, + sizeof(struct ether_hdr)); + ipv4_dst_ip[i] = ipv4_hdr->dst_addr; + key_ptrs[i] = (void *)&ipv4_dst_ip[i]; + } + + rte_efd_lookup_bulk(efd_table, socket_id, rx_count, + (const void **) key_ptrs, data); + for (i = 0; i < rx_count; i++) { + node = (uint8_t) ((uintptr_t)data[i]); + + if (node >= num_nodes) { + /* + * Node is out of range, which means that + * flow has not been inserted + */ + flow_dist_stats.drop++; + rte_pktmbuf_free(pkts[i]); + } else { + flow_dist_stats.distributed++; + enqueue_rx_packet(node, pkts[i]); + } + } + + for (i = 0; i < num_nodes; i++) + flush_rx_queue(i); + } + +The burst of packets received is enqueued in temporary buffers (per node), +and enqueued in the shared ring between the server and the node. +After this, a new burst of packets is received and this process is +repeated infinitely. + +.. code-block:: c + + static void + flush_rx_queue(uint16_t node) + { + uint16_t j; + struct node *cl; + + if (cl_rx_buf[node].count == 0) + return; + + cl = &nodes[node]; + if (rte_ring_enqueue_bulk(cl->rx_q, (void **)cl_rx_buf[node].buffer, + cl_rx_buf[node].count, NULL) != cl_rx_buf[node].count){ + for (j = 0; j < cl_rx_buf[node].count; j++) + rte_pktmbuf_free(cl_rx_buf[node].buffer[j]); + cl->stats.rx_drop += cl_rx_buf[node].count; + } else + cl->stats.rx += cl_rx_buf[node].count; + + cl_rx_buf[node].count = 0; + } + +The second process, the back-end node, receives the packets from the shared +ring with the server and send them out, if they belong to the node. + +At initialization, it attaches to the server process memory, to have +access to the shared ring, parameters and statistics. + +.. code-block:: c + + rx_ring = rte_ring_lookup(get_rx_queue_name(node_id)); + if (rx_ring == NULL) + rte_exit(EXIT_FAILURE, "Cannot get RX ring - " + "is server process running?\n"); + + mp = rte_mempool_lookup(PKTMBUF_POOL_NAME); + if (mp == NULL) + rte_exit(EXIT_FAILURE, "Cannot get mempool for mbufs\n"); + + mz = rte_memzone_lookup(MZ_SHARED_INFO); + if (mz == NULL) + rte_exit(EXIT_FAILURE, "Cannot get port info structure\n"); + info = mz->addr; + tx_stats = &(info->tx_stats[node_id]); + filter_stats = &(info->filter_stats[node_id]); + +Then, the hash table that contains the flows that will be handled +by the node is created and populated. + +.. code-block:: c + + static struct rte_hash * + create_hash_table(const struct shared_info *info) + { + uint32_t num_flows_node = info->num_flows / info->num_nodes; + char name[RTE_HASH_NAMESIZE]; + struct rte_hash *h; + + /* create table */ + struct rte_hash_parameters hash_params = { + .entries = num_flows_node * 2, /* table load = 50% */ + .key_len = sizeof(uint32_t), /* Store IPv4 dest IP address */ + .socket_id = rte_socket_id(), + .hash_func_init_val = 0, + }; + + snprintf(name, sizeof(name), "hash_table_%d", node_id); + hash_params.name = name; + h = rte_hash_create(&hash_params); + + if (h == NULL) + rte_exit(EXIT_FAILURE, + "Problem creating the hash table for node %d\n", + node_id); + return h; + } + + static void + populate_hash_table(const struct rte_hash *h, const struct shared_info *info) + { + unsigned int i; + int32_t ret; + uint32_t ip_dst; + uint32_t num_flows_node = 0; + uint64_t target_node; + + /* Add flows in table */ + for (i = 0; i < info->num_flows; i++) { + target_node = i % info->num_nodes; + if (target_node != node_id) + continue; + + ip_dst = rte_cpu_to_be_32(i); + + ret = rte_hash_add_key(h, (void *) &ip_dst); + if (ret < 0) + rte_exit(EXIT_FAILURE, "Unable to add entry %u " + "in hash table\n", i); + else + num_flows_node++; + + } + + printf("Hash table: Adding 0x%x keys\n", num_flows_node); + } + +After initialization, packets are dequeued from the shared ring +(from the server) and, like in the server process, +the IPv4 address from the packets is used as a key to look up in the hash table. +If there is a hit, packet is stored in a buffer, to be eventually transmitted +in one of the enabled ports. If key is not there, packet is dropped, since the +flow is not handled by the node. + +.. code-block:: c + + static inline void + handle_packets(struct rte_hash *h, struct rte_mbuf **bufs, uint16_t num_packets) + { + struct ipv4_hdr *ipv4_hdr; + uint32_t ipv4_dst_ip[PKT_READ_SIZE]; + const void *key_ptrs[PKT_READ_SIZE]; + unsigned int i; + int32_t positions[PKT_READ_SIZE] = {0}; + + for (i = 0; i < num_packets; i++) { + /* Handle IPv4 header.*/ + ipv4_hdr = rte_pktmbuf_mtod_offset(bufs[i], struct ipv4_hdr *, + sizeof(struct ether_hdr)); + ipv4_dst_ip[i] = ipv4_hdr->dst_addr; + key_ptrs[i] = &ipv4_dst_ip[i]; + } + /* Check if packets belongs to any flows handled by this node */ + rte_hash_lookup_bulk(h, key_ptrs, num_packets, positions); + + for (i = 0; i < num_packets; i++) { + if (likely(positions[i] >= 0)) { + filter_stats->passed++; + transmit_packet(bufs[i]); + } else { + filter_stats->drop++; + /* Drop packet, as flow is not handled by this node */ + rte_pktmbuf_free(bufs[i]); + } + } + } + +Finally, note that both processes updates statistics, such as transmitted, received +and dropped packets, which are shown and refreshed by the server app. + +.. code-block:: c + + static void + do_stats_display(void) + { + unsigned int i, j; + const char clr[] = {27, '[', '2', 'J', '\0'}; + const char topLeft[] = {27, '[', '1', ';', '1', 'H', '\0'}; + uint64_t port_tx[RTE_MAX_ETHPORTS], port_tx_drop[RTE_MAX_ETHPORTS]; + uint64_t node_tx[MAX_NODES], node_tx_drop[MAX_NODES]; + + /* to get TX stats, we need to do some summing calculations */ + memset(port_tx, 0, sizeof(port_tx)); + memset(port_tx_drop, 0, sizeof(port_tx_drop)); + memset(node_tx, 0, sizeof(node_tx)); + memset(node_tx_drop, 0, sizeof(node_tx_drop)); + + for (i = 0; i < num_nodes; i++) { + const struct tx_stats *tx = &info->tx_stats[i]; + + for (j = 0; j < info->num_ports; j++) { + const uint64_t tx_val = tx->tx[info->id[j]]; + const uint64_t drop_val = tx->tx_drop[info->id[j]]; + + port_tx[j] += tx_val; + port_tx_drop[j] += drop_val; + node_tx[i] += tx_val; + node_tx_drop[i] += drop_val; + } + } + + /* Clear screen and move to top left */ + printf("%s%s", clr, topLeft); + + printf("PORTS\n"); + printf("-----\n"); + for (i = 0; i < info->num_ports; i++) + printf("Port %u: '%s'\t", (unsigned int)info->id[i], + get_printable_mac_addr(info->id[i])); + printf("\n\n"); + for (i = 0; i < info->num_ports; i++) { + printf("Port %u - rx: %9"PRIu64"\t" + "tx: %9"PRIu64"\n", + (unsigned int)info->id[i], info->rx_stats.rx[i], + port_tx[i]); + } + + printf("\nSERVER\n"); + printf("-----\n"); + printf("distributed: %9"PRIu64", drop: %9"PRIu64"\n", + flow_dist_stats.distributed, flow_dist_stats.drop); + + printf("\nNODES\n"); + printf("-------\n"); + for (i = 0; i < num_nodes; i++) { + const unsigned long long rx = nodes[i].stats.rx; + const unsigned long long rx_drop = nodes[i].stats.rx_drop; + const struct filter_stats *filter = &info->filter_stats[i]; + + printf("Node %2u - rx: %9llu, rx_drop: %9llu\n" + " tx: %9"PRIu64", tx_drop: %9"PRIu64"\n" + " filter_passed: %9"PRIu64", " + "filter_drop: %9"PRIu64"\n", + i, rx, rx_drop, node_tx[i], node_tx_drop[i], + filter->passed, filter->drop); + } + + printf("\n"); + } diff --git a/doc/guides/sample_app_ug/skeleton.rst b/doc/guides/sample_app_ug/skeleton.rst index e832c132..c39b0332 100644 --- a/doc/guides/sample_app_ug/skeleton.rst +++ b/doc/guides/sample_app_ug/skeleton.rst @@ -74,7 +74,7 @@ To run the example in a ``linuxapp`` environment: .. code-block:: console - ./build/basicfwd -c 2 -n 4 + ./build/basicfwd -l 1 -n 4 Refer to *DPDK Getting Started Guide* for general information on running applications and the Environment Abstraction Layer (EAL) options. diff --git a/doc/guides/sample_app_ug/tep_termination.rst b/doc/guides/sample_app_ug/tep_termination.rst index 88e08cf9..087823b1 100644 --- a/doc/guides/sample_app_ug/tep_termination.rst +++ b/doc/guides/sample_app_ug/tep_termination.rst @@ -169,7 +169,7 @@ Running the Sample Code .. code-block:: console - user@target:~$ ./build/app/tep_termination -c f -n 4 --huge-dir /mnt/huge -- + user@target:~$ ./build/app/tep_termination -l 0-3 -n 4 --huge-dir /mnt/huge -- -p 0x1 --dev-basename tep-termination --nb-devices 4 --udp-port 4789 --filter-type 1 @@ -191,7 +191,7 @@ The default value is 2. .. code-block:: console - user@target:~$ ./build/app/tep_termination -c f -n 4 --huge-dir /mnt/huge -- + user@target:~$ ./build/app/tep_termination -l 0-3 -n 4 --huge-dir /mnt/huge -- --nb-devices 2 **Tunneling UDP port.** @@ -201,7 +201,7 @@ The default value is 4789. .. code-block:: console - user@target:~$ ./build/app/tep_termination -c f -n 4 --huge-dir /mnt/huge -- + user@target:~$ ./build/app/tep_termination -l 0-3 -n 4 --huge-dir /mnt/huge -- --nb-devices 2 --udp-port 4789 **Filter Type.** @@ -212,7 +212,7 @@ The default value is 1, which means the filter type of inner MAC and tenant ID i .. code-block:: console - user@target:~$ ./build/app/tep_termination -c f -n 4 --huge-dir /mnt/huge -- + user@target:~$ ./build/app/tep_termination -l 0-3 -n 4 --huge-dir /mnt/huge -- --nb-devices 2 --udp-port 4789 --filter-type 1 **TX Checksum.** @@ -222,7 +222,7 @@ The default value is 0, which means the checksum offload is disabled. .. code-block:: console - user@target:~$ ./build/app/tep_termination -c f -n 4 --huge-dir /mnt/huge -- + user@target:~$ ./build/app/tep_termination -l 0-3 -n 4 --huge-dir /mnt/huge -- --nb-devices 2 --tx-checksum **TCP segment size.** @@ -232,7 +232,7 @@ The default value is 0, which means TSO offload is disabled. .. code-block:: console - user@target:~$ ./build/app/tep_termination -c f -n 4 --huge-dir /mnt/huge -- + user@target:~$ ./build/app/tep_termination -l 0-3 -n 4 --huge-dir /mnt/huge -- --tx-checksum --tso-segsz 800 **Decapsulation option.** @@ -242,7 +242,7 @@ The default value is 1. .. code-block:: console - user@target:~$ ./build/app/tep_termination -c f -n 4 --huge-dir /mnt/huge -- + user@target:~$ ./build/app/tep_termination -l 0-3 -n 4 --huge-dir /mnt/huge -- --nb-devices 4 --udp-port 4789 --decap 1 **Encapsulation option.** @@ -252,7 +252,7 @@ The default value is 1. .. code-block:: console - user@target:~$ ./build/app/tep_termination -c f -n 4 --huge-dir /mnt/huge -- + user@target:~$ ./build/app/tep_termination -l 0-3 -n 4 --huge-dir /mnt/huge -- --nb-devices 4 --udp-port 4789 --encap 1 diff --git a/doc/guides/sample_app_ug/test_pipeline.rst b/doc/guides/sample_app_ug/test_pipeline.rst index fd288139..95c7e0fc 100644 --- a/doc/guides/sample_app_ug/test_pipeline.rst +++ b/doc/guides/sample_app_ug/test_pipeline.rst @@ -90,7 +90,7 @@ The application execution command line is: ./test-pipeline [EAL options] -- -p PORTMASK --TABLE_TYPE -The -c EAL CPU core mask option has to contain exactly 3 CPU cores. +The -c or -l EAL CPU coremask/corelist option has to contain exactly 3 CPU cores. The first CPU core in the core mask is assigned for core A, the second for core B and the third for core C. The PORTMASK parameter must contain 2 or 4 ports. diff --git a/doc/guides/sample_app_ug/timer.rst b/doc/guides/sample_app_ug/timer.rst index e4de359d..00b69532 100644 --- a/doc/guides/sample_app_ug/timer.rst +++ b/doc/guides/sample_app_ug/timer.rst @@ -65,7 +65,7 @@ To run the example in linuxapp environment: .. code-block:: console - $ ./build/timer -c f -n 4 + $ ./build/timer -l 0-3 -n 4 Refer to the *DPDK Getting Started Guide* for general information on running applications and the Environment Abstraction Layer (EAL) options. diff --git a/doc/guides/sample_app_ug/vhost.rst b/doc/guides/sample_app_ug/vhost.rst index 1f6d0d96..a2a3909e 100644 --- a/doc/guides/sample_app_ug/vhost.rst +++ b/doc/guides/sample_app_ug/vhost.rst @@ -75,7 +75,7 @@ Start the vswitch example .. code-block:: console - ./vhost-switch -c f -n 4 --socket-mem 1024 \ + ./vhost-switch -l 0-3 -n 4 --socket-mem 1024 \ -- --socket-file /tmp/sock0 --client \ ... @@ -115,13 +115,13 @@ could be done by: .. code-block:: console modprobe uio_pci_generic - $RTE_SDK/tools/dpdk-devbind.py -b=uio_pci_generic 0000:00:04.0 + $RTE_SDK/usertools/dpdk-devbind.py -b=uio_pci_generic 0000:00:04.0 Then start testpmd for packet forwarding testing. .. code-block:: console - ./x86_64-native-gcc/app/testpmd -c 0x3 -- -i + ./x86_64-native-gcc/app/testpmd -l 0-1 -- -i > start tx_first Inject packets diff --git a/doc/guides/sample_app_ug/vm_power_management.rst b/doc/guides/sample_app_ug/vm_power_management.rst index aa02c156..05c26b03 100644 --- a/doc/guides/sample_app_ug/vm_power_management.rst +++ b/doc/guides/sample_app_ug/vm_power_management.rst @@ -220,7 +220,7 @@ on cores 0 & 1 on a system with 4 memory channels: .. code-block:: console - ./build/vm_power_mgr -c 0x3 -n 4 + ./build/vm_power_mgr -l 0-1 -n 4 After successful initialization the user is presented with VM Power Manager CLI: @@ -342,7 +342,7 @@ for example to run on cores 0,1,2,3 on a system with 4 memory channels: .. code-block:: console - ./build/guest_vm_power_mgr -c 0xf -n 4 + ./build/guest_vm_power_mgr -l 0-3 -n 4 After successful initialization the user is presented with VM Power Manager Guest CLI: diff --git a/doc/guides/sample_app_ug/vmdq_dcb_forwarding.rst b/doc/guides/sample_app_ug/vmdq_dcb_forwarding.rst index bf55fdad..70e1d19e 100644 --- a/doc/guides/sample_app_ug/vmdq_dcb_forwarding.rst +++ b/doc/guides/sample_app_ug/vmdq_dcb_forwarding.rst @@ -114,7 +114,7 @@ To run the example in a linuxapp environment: .. code-block:: console - user@target:~$ ./build/vmdq_dcb -c f -n 4 -- -p 0x3 --nb-pools 32 --nb-tcs 4 + user@target:~$ ./build/vmdq_dcb -l 0-3 -n 4 -- -p 0x3 --nb-pools 32 --nb-tcs 4 Refer to the *DPDK Getting Started Guide* for general information on running applications and the Environment Abstraction Layer (EAL) options. |