@@ -696,6 +696,13 @@ F: test/test/test_meter.c
F: examples/qos_meter/
F: doc/guides/sample_app_ug/qos_metering.rst
+MEMBERSHIP
+M: Yipeng Wang <yipeng1.wang@intel.com>
+M: Sameh Gobriel <sameh.gobriel@intel.com>
+F: lib/librte_membership/
+F: doc/guides/prog_guide/membership.rst
+F: test/test/test_membership*
+
Other libraries
---------------
@@ -41,3 +41,6 @@ CONFIG_RTE_ARCH_64=y
CONFIG_RTE_TOOLCHAIN="gcc"
CONFIG_RTE_TOOLCHAIN_GCC=y
+
+
+CONFIG_RTE_LIBRTE_MEMBERSHIP=y
new file mode 100644
@@ -0,0 +1,1269 @@
+<?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 memship_i1.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"
+ width="7.18709in" height="4.75757in" viewBox="0 0 517.471 342.545" xml:space="preserve" color-interpolation-filters="sRGB"
+ class="st56">
+ <style type="text/css">
+ <![CDATA[
+ .st1 {visibility:visible}
+ .st2 {fill:none;filter:url(#filter_2);stroke:#5b9bd5;stroke-opacity:0.22}
+ .st3 {fill:#5b9bd5;filter:url(#filter_2);font-family:Calibri;font-size:0.75em;opacity:0.219608}
+ .st4 {font-size:1em}
+ .st5 {fill:none;stroke:#41719c;stroke-width:3}
+ .st6 {fill:#5b9bd5;font-family:Calibri;font-size:0.75em}
+ .st7 {fill:#5b9bd5;fill-opacity:0.22;filter:url(#filter_2);stroke:#5b9bd5;stroke-opacity:0.22}
+ .st8 {fill:#5b9bd5;stroke:#c7c8c8;stroke-width:0.25}
+ .st9 {fill:none;stroke:none;stroke-width:0.25}
+ .st10 {fill:#ffffff;font-family:Calibri;font-size:0.499992em;font-weight:bold}
+ .st11 {fill:#ffffff;font-family:Calibri;font-size:0.75em;font-weight:bold}
+ .st12 {marker-end:url(#mrkr5-74);stroke:#5b9bd5;stroke-linecap:round;stroke-linejoin:round;stroke-width:1}
+ .st13 {fill:#5b9bd5;fill-opacity:1;stroke:#5b9bd5;stroke-opacity:1;stroke-width:0.28409090909091}
+ .st14 {fill:#5b9bd5;font-family:Calibri;font-size:0.666664em}
+ .st15 {stroke:#5b9bd5;stroke-linecap:round;stroke-linejoin:round;stroke-width:1}
+ .st16 {fill:#feffff;font-family:Calibri;font-size:0.499992em}
+ .st17 {fill:#deebf6;stroke:#c7c8c8;stroke-width:0.25}
+ .st18 {fill:#000000;font-family:Calibri;font-size:0.499992em}
+ .st19 {marker-end:url(#mrkr5-200);stroke:#ff0000;stroke-linecap:round;stroke-linejoin:round;stroke-width:1}
+ .st20 {fill:#ff0000;fill-opacity:1;stroke:#ff0000;stroke-opacity:1;stroke-width:0.28409090909091}
+ .st21 {fill:#ff0000;font-family:Calibri;font-size:0.666664em}
+ .st22 {fill:#5b9bd5;fill-opacity:0.22;filter:url(#filter_2)}
+ .st23 {fill:#ffffff}
+ .st24 {stroke:#0070c0;stroke-width:0.25}
+ .st25 {fill:#5b9bd5;stroke:#0070c0;stroke-width:0.25}
+ .st26 {fill:#5b9bd5;stroke:#ffffff;stroke-width:0.25}
+ .st27 {fill:#5b9bd5}
+ .st28 {stroke:#c7c8c8;stroke-width:0.25}
+ .st29 {fill:#acccea;stroke:#c7c8c8;stroke-width:0.25}
+ .st30 {fill:#5b9bd5;fill-opacity:0.22;filter:url(#filter_2);stroke:none;stroke-linecap:butt}
+ .st31 {fill:#000000;fill-opacity:0;stroke:none;stroke-linecap:butt;stroke-width:0.75}
+ .st32 {fill:url(#grad0-350);stroke:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.75}
+ .st33 {fill:url(#grad0-354);stroke:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.75}
+ .st34 {fill:url(#grad10-358);stroke:#308dda;stroke-linecap:butt;stroke-width:0.130208}
+ .st35 {fill:url(#grad7-366);stroke:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.75}
+ .st36 {fill:url(#grad3-376);stroke:#000000;stroke-linecap:butt;stroke-width:0.130208}
+ .st37 {fill:url(#grad1-383);stroke:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.75}
+ .st38 {fill:url(#grad3-396);stroke:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.75}
+ .st39 {fill:none}
+ .st40 {stroke:#308dda;stroke-linecap:butt;stroke-width:0.130208}
+ .st41 {stroke:#ffffff;stroke-linecap:butt;stroke-width:0.130208}
+ .st42 {fill:url(#grad0-424);stroke:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.75}
+ .st43 {fill:url(#grad7-437);stroke:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.75}
+ .st44 {fill:none;stroke:#c8c8c8;stroke-width:0.75}
+ .st45 {fill:#9a9a9a;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.0833333}
+ .st46 {fill:url(#grad5-456);stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.0833333}
+ .st47 {fill:url(#grad5-460);stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.0833333}
+ .st48 {stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.25}
+ .st49 {fill:url(#grad10-471);stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.0833333}
+ .st50 {stroke:#c8c8c8;stroke-width:0.75}
+ .st51 {stroke:#4f87bb;stroke-width:0.75}
+ .st52 {fill:#5b9bd5;fill-opacity:0.25;filter:url(#filter_2);stroke:#5b9bd5;stroke-opacity:0.25}
+ .st53 {fill:#4f87bb;stroke:#40709c;stroke-width:0.75}
+ .st54 {fill:none;stroke:#0070c0;stroke-width:2.25}
+ .st55 {fill:#595959;font-family:Arial;font-size:0.666664em}
+ .st56 {fill:none;fill-rule:evenodd;font-size:12px;overflow:visible;stroke-linecap:square;stroke-miterlimit:3}
+ ]]>
+ </style>
+
+ <defs id="Patterns_And_Gradients">
+ <linearGradient id="grad0-350" x1="0" y1="0" x2="1" y2="0" gradientTransform="rotate(270 0.5 0.5)">
+ <stop offset="0" stop-color="#97c2e6" stop-opacity="1"/>
+ <stop offset="1" stop-color="#4274a2" stop-opacity="1"/>
+ </linearGradient>
+ <linearGradient id="grad0-354" x1="0" y1="0" x2="1" y2="0" gradientTransform="rotate(0 0.5 0.5)">
+ <stop offset="0" stop-color="#5491d3" stop-opacity="1"/>
+ <stop offset="1" stop-color="#246ba6" stop-opacity="1"/>
+ </linearGradient>
+ <pattern id="grad10-358" x="0" y="0" width="1" height="1" patternContentUnits="objectBoundingBox">
+ <path d="M 0.5 0.5 L 0 0 L 0 1 z" style="fill:url(#grad0-359)"/>
+ <path d="M 0.5 0.5 L 1 0 L 1 1 z" style="fill:url(#grad0-360)"/>
+ <path d="M 0.5 0.5 L 0 0 L 1 0 z" style="fill:url(#grad0-361)"/>
+ <path d="M 0.5 0.5 L 0 1 L 1 1 z" style="fill:url(#grad0-362)"/>
+ </pattern>
+ <linearGradient id="grad0-359" x1="0" y1="0" x2="1" y2="0" gradientTransform="rotate(180 0.5 0.5)">
+ <stop offset="0" stop-color="#569bd3" stop-opacity="1"/>
+ <stop offset="1" stop-color="#aed0ec" stop-opacity="1"/>
+ </linearGradient>
+ <linearGradient id="grad0-360" x1="0" y1="0" x2="1" y2="0" gradientTransform="rotate(360 0.5 0.5)">
+ <stop offset="0" stop-color="#569bd3" stop-opacity="1"/>
+ <stop offset="1" stop-color="#aed0ec" stop-opacity="1"/>
+ </linearGradient>
+ <linearGradient id="grad0-361" x1="0" y1="0" x2="1" y2="0" gradientTransform="rotate(270 0.5 0.5)">
+ <stop offset="0" stop-color="#569bd3" stop-opacity="1"/>
+ <stop offset="1" stop-color="#aed0ec" stop-opacity="1"/>
+ </linearGradient>
+ <linearGradient id="grad0-362" x1="0" y1="0" x2="1" y2="0" gradientTransform="rotate(90 0.5 0.5)">
+ <stop offset="0" stop-color="#569bd3" stop-opacity="1"/>
+ <stop offset="1" stop-color="#aed0ec" stop-opacity="1"/>
+ </linearGradient>
+ <radialGradient id="grad7-366" cx="0" cy="0" r="1.4">
+ <stop offset="0" stop-color="#c0dff1" stop-opacity="1"/>
+ <stop offset="1" stop-color="#246ba6" stop-opacity="1"/>
+ </radialGradient>
+ <radialGradient id="grad3-376" cx="0.5" cy="0.5" r="0.73">
+ <stop offset="0" stop-color="#c8e5c8" stop-opacity="1"/>
+ <stop offset="1" stop-color="#19bf19" stop-opacity="1"/>
+ </radialGradient>
+ <radialGradient id="grad1-383" cx="1" cy="1" r="1.4">
+ <stop offset="0" stop-color="#5599d7" stop-opacity="1"/>
+ <stop offset="1" stop-color="#b9daf2" stop-opacity="1"/>
+ </radialGradient>
+ <radialGradient id="grad3-396" cx="0.5" cy="0.5" r="0.73">
+ <stop offset="0" stop-color="#5599d7" stop-opacity="1"/>
+ <stop offset="1" stop-color="#214383" stop-opacity="1"/>
+ </radialGradient>
+ <linearGradient id="grad0-424" x1="0" y1="0" x2="1" y2="0" gradientTransform="rotate(270 0.5 0.5)">
+ <stop offset="0" stop-color="#97c2e6" stop-opacity="1"/>
+ <stop offset="1" stop-color="#6ba4dc" stop-opacity="1"/>
+ </linearGradient>
+ <radialGradient id="grad7-437" cx="0" cy="0" r="1.4">
+ <stop offset="0" stop-color="#89bee9" stop-opacity="1"/>
+ <stop offset="1" stop-color="#b9daf2" stop-opacity="1"/>
+ </radialGradient>
+ <radialGradient id="grad5-456" cx="0.5" cy="1" r="1.1">
+ <stop offset="0" stop-color="#000000" stop-opacity="1"/>
+ <stop offset="1" stop-color="#ffffff" stop-opacity="1"/>
+ </radialGradient>
+ <radialGradient id="grad5-460" cx="0.5" cy="1" r="1.1">
+ <stop offset="0" stop-color="#ffffff" stop-opacity="1"/>
+ <stop offset="1" stop-color="#9a9a9a" stop-opacity="1"/>
+ </radialGradient>
+ <pattern id="grad10-471" x="0" y="0" width="1" height="1" patternContentUnits="objectBoundingBox">
+ <path d="M 0.5 0.5 L 0 0 L 0 1 z" style="fill:url(#grad0-472)"/>
+ <path d="M 0.5 0.5 L 1 0 L 1 1 z" style="fill:url(#grad0-473)"/>
+ <path d="M 0.5 0.5 L 0 0 L 1 0 z" style="fill:url(#grad0-474)"/>
+ <path d="M 0.5 0.5 L 0 1 L 1 1 z" style="fill:url(#grad0-475)"/>
+ </pattern>
+ <linearGradient id="grad0-472" x1="0" y1="0" x2="1" y2="0" gradientTransform="rotate(180 0.5 0.5)">
+ <stop offset="0" stop-color="#ffffff" stop-opacity="1"/>
+ <stop offset="1" stop-color="#ffcc00" stop-opacity="1"/>
+ </linearGradient>
+ <linearGradient id="grad0-473" x1="0" y1="0" x2="1" y2="0" gradientTransform="rotate(360 0.5 0.5)">
+ <stop offset="0" stop-color="#ffffff" stop-opacity="1"/>
+ <stop offset="1" stop-color="#ffcc00" stop-opacity="1"/>
+ </linearGradient>
+ <linearGradient id="grad0-474" x1="0" y1="0" x2="1" y2="0" gradientTransform="rotate(270 0.5 0.5)">
+ <stop offset="0" stop-color="#ffffff" stop-opacity="1"/>
+ <stop offset="1" stop-color="#ffcc00" stop-opacity="1"/>
+ </linearGradient>
+ <linearGradient id="grad0-475" x1="0" y1="0" x2="1" y2="0" gradientTransform="rotate(90 0.5 0.5)">
+ <stop offset="0" stop-color="#ffffff" stop-opacity="1"/>
+ <stop offset="1" stop-color="#ffcc00" stop-opacity="1"/>
+ </linearGradient>
+ </defs>
+ <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-74" class="st13" refX="-6.16" orient="auto" markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend5" transform="scale(-3.52,-3.52) "/>
+ </marker>
+ <marker id="mrkr5-200" class="st20" refX="-5.8" orient="auto" markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend5" transform="scale(-3.52,-3.52) "/>
+ </marker>
+ </defs>
+ <defs id="Filters">
+ <filter id="filter_2">
+ <feGaussianBlur stdDeviation="2"/>
+ </filter>
+ </defs>
+ <g>
+ <title>Page-1</title>
+ <g id="group165-1" transform="translate(21.7794,-24.0978)">
+ <title>Sheet.165</title>
+ <g id="group1-2" transform="translate(308.647,-25.7109)">
+ <title>Sheet.1</title>
+ <g id="shape2-3" transform="translate(13.6117,-58.9839)">
+ <title>Circle</title>
+ <desc>List 1 matching Criteria 1</desc>
+ <g id="shadow2-4" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <path d="M0 315.32 A27.2233 27.2233 0 1 1 54.45 315.32 A27.2233 27.2233 0 1 1 0 315.32 Z" class="st2"/>
+ <text x="17.73" y="307.22" class="st3">List 1 <tspan x="10.18" dy="1.2em" class="st4">matching </tspan><tspan
+ x="10.42" dy="1.2em" class="st4">Criteria </tspan>1</text> </g>
+ <path d="M0 315.32 A27.2233 27.2233 0 1 1 54.45 315.32 A27.2233 27.2233 0 1 1 0 315.32 Z" class="st5"/>
+ <text x="17.73" y="307.22" class="st6">List 1 <tspan x="10.18" dy="1.2em" class="st4">matching </tspan><tspan
+ x="10.42" dy="1.2em" class="st4">Criteria </tspan>1</text> </g>
+ <g id="shape3-15" transform="translate(58.9839,-58.9839)">
+ <title>Circle.23</title>
+ <desc>List 2</desc>
+ <g id="shadow3-16" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <path d="M0 315.32 A27.2233 27.2233 0 1 1 54.45 315.32 A27.2233 27.2233 0 1 1 0 315.32 Z" class="st2"/>
+ <text x="17.73" y="318.02" class="st3">List 2</text> </g>
+ <path d="M0 315.32 A27.2233 27.2233 0 1 1 54.45 315.32 A27.2233 27.2233 0 1 1 0 315.32 Z" class="st5"/>
+ <text x="17.73" y="318.02" class="st6">List 2</text> </g>
+ <g id="shape4-23">
+ <title>Circle.24</title>
+ <desc>List 1 matching Criteria 1</desc>
+ <g id="shadow4-24" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <path d="M0 315.32 A27.2233 27.2233 0 1 1 54.45 315.32 A27.2233 27.2233 0 1 1 0 315.32 Z" class="st2"/>
+ <text x="17.73" y="307.22" class="st3">List 1 <tspan x="10.18" dy="1.2em" class="st4">matching </tspan><tspan
+ x="10.42" dy="1.2em" class="st4">Criteria </tspan>1</text> </g>
+ <path d="M0 315.32 A27.2233 27.2233 0 1 1 54.45 315.32 A27.2233 27.2233 0 1 1 0 315.32 Z" class="st5"/>
+ <text x="17.73" y="307.22" class="st6">List 1 <tspan x="10.18" dy="1.2em" class="st4">matching </tspan><tspan
+ x="10.42" dy="1.2em" class="st4">Criteria </tspan>1</text> </g>
+ <g id="group5-35" transform="translate(50.7413,-4.53722)">
+ <title>Sheet.5</title>
+ <g id="shape6-36" transform="translate(344.2,300.5) rotate(90)">
+ <title>Triangle</title>
+ <g id="shadow6-37" transform="matrix(1,0,0,1,1.97279,-0.345598)" class="st1">
+ <path d="M42.04 342.55 L21.02 318.64 L0 342.55 L42.04 342.55 Z" class="st7"/>
+ </g>
+ <path d="M42.04 342.55 L21.02 318.64 L0 342.55 L42.04 342.55 Z" class="st8"/>
+ </g>
+ <g id="shape7-41" transform="translate(-0.884982,-14.7157)">
+ <title>Sheet.7</title>
+ <desc>Set Summary</desc>
+ <rect x="0" y="329.932" width="25.8535" height="12.6135" class="st9"/>
+ <text x="8.96" y="330.84" class="st10">Set <tspan x="5.02" dy="1.2em" class="st4">Summ</tspan><tspan
+ x="8.96" dy="1.2em" class="st4">ary</tspan></text> </g>
+ </g>
+ <g id="shape8-46" transform="translate(72.5955,0)">
+ <title>Circle.29</title>
+ <desc>List 2 matching Criteria 2</desc>
+ <g id="shadow8-47" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <path d="M0 315.32 A27.2233 27.2233 0 1 1 54.45 315.32 A27.2233 27.2233 0 1 1 0 315.32 Z" class="st2"/>
+ <text x="17.73" y="307.22" class="st3">List 2 <tspan x="10.18" dy="1.2em" class="st4">matching </tspan><tspan
+ x="10.42" dy="1.2em" class="st4">Criteria </tspan>2</text> </g>
+ <path d="M0 315.32 A27.2233 27.2233 0 1 1 54.45 315.32 A27.2233 27.2233 0 1 1 0 315.32 Z" class="st5"/>
+ <text x="17.73" y="307.22" class="st6">List 2 <tspan x="10.18" dy="1.2em" class="st4">matching </tspan><tspan
+ x="10.42" dy="1.2em" class="st4">Criteria </tspan>2</text> </g>
+ </g>
+ <g id="group9-58" transform="translate(31.6515,-49.9094)">
+ <title>Sheet.9</title>
+ <g id="group10-59" transform="translate(99.5691,0)">
+ <title>Sheet.10</title>
+ <g id="shape11-60" transform="translate(346.175,275.999) rotate(90)">
+ <title>Triangle</title>
+ <g id="shadow11-61" transform="matrix(1,0,0,1,1.97279,-0.345598)" class="st1">
+ <path d="M66.55 342.55 L33.27 290.12 L0 342.55 L66.55 342.55 Z" class="st7"/>
+ </g>
+ <path d="M66.55 342.55 L33.27 290.12 L0 342.55 L66.55 342.55 Z" class="st8"/>
+ </g>
+ <g id="shape12-65" transform="translate(355.063,285.074) rotate(90)">
+ <title>Sheet.12</title>
+ <desc>Set Summary</desc>
+ <rect x="0" y="322.581" width="48.397" height="19.9638" class="st9"/>
+ <text x="18.25" y="329.86" class="st11">Set <tspan x="6.38" dy="1.2em" class="st4">Summary</tspan></text> </g>
+ </g>
+ <g id="shape13-69" transform="translate(57.5835,-54.4467)">
+ <title>Sheet.13</title>
+ <path d="M0 342.55 L38.9 342.55" class="st12"/>
+ </g>
+ <g id="shape14-75" transform="translate(13.4863,-47.4928)">
+ <title>Sheet.14</title>
+ <desc>Flow Key</desc>
+ <rect x="0" y="324.396" width="50.6656" height="18.1489" class="st9"/>
+ <text x="10.83" y="335.87" class="st14">Flow Key</text> </g>
+ <g id="shape15-78" transform="translate(5.02911,1.60865) rotate(-26.0815)">
+ <title>Sheet.15</title>
+ <path d="M0 342.55 L39.25 342.55" class="st12"/>
+ </g>
+ <g id="shape16-83" transform="translate(155.629,-33.273)">
+ <title>Sheet.16</title>
+ <path d="M0 342.55 L38.34 342.55" class="st12"/>
+ </g>
+ <g id="shape17-88" transform="translate(304.141,0.595416) rotate(25.6934)">
+ <title>Sheet.17</title>
+ <path d="M0 342.55 L42.68 342.55" class="st12"/>
+ </g>
+ <g id="shape18-93" transform="translate(102.642,654.842) rotate(180)">
+ <title>Sheet.18</title>
+ <path d="M0 342.55 L30.14 342.55" class="st12"/>
+ </g>
+ <g id="shape19-98" transform="translate(-11.5184,-24.9928)">
+ <title>Sheet.19</title>
+ <desc>New Flow = New Assignment</desc>
+ <rect x="0" y="324.396" width="102.087" height="18.1489" class="st9"/>
+ <text x="23.75" y="331.07" class="st14">New Flow = New <tspan x="32.07" dy="1.2em" class="st4">Assignment</tspan></text> </g>
+ <g id="shape20-102" transform="translate(102.844,679.041) rotate(180)">
+ <title>Sheet.20</title>
+ <path d="M0 342.55 L30.14 342.55" class="st12"/>
+ </g>
+ <g id="shape21-107" transform="translate(-13.7684,-0.0938726)">
+ <title>Sheet.21</title>
+ <desc>Old Flow = forward to specific thread</desc>
+ <rect x="0" y="324.396" width="102.087" height="18.1489" class="st9"/>
+ <text x="15.6" y="331.07" class="st14">Old Flow = forward to <tspan x="27.2" dy="1.2em" class="st4">specific thread</tspan></text> </g>
+ <g id="shape22-111" transform="translate(541.496,275.999) rotate(90)">
+ <title>Sheet.22</title>
+ <path d="M0 335.81 C2.14 344.21 5.09 343.6 7.56 340.31 C10.62 336.25 12.94 328.1 18.15 335.81" class="st15"/>
+ </g>
+ <g id="shape23-114" transform="translate(541.496,300.198) rotate(90)">
+ <title>Sheet.23</title>
+ <path d="M0 335.81 C2.14 344.21 5.09 343.6 7.56 340.31 C10.62 336.25 12.94 328.1 18.15 335.81" class="st15"/>
+ </g>
+ <g id="shape24-117" transform="translate(541.496,324.396) rotate(90)">
+ <title>Sheet.24</title>
+ <path d="M0 335.81 C2.14 344.21 5.09 343.6 7.56 340.31 C10.62 336.25 12.94 328.1 18.15 335.81" class="st15"/>
+ </g>
+ </g>
+ <g id="group25-120" transform="translate(285.961,-178.628)">
+ <title>Sheet.25</title>
+ <g id="shape26-121" transform="translate(51.2583,-51.2583)">
+ <title>Circle</title>
+ <g id="shadow26-122" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <path d="M0 333.23 A9.3197 9.3197 0 0 1 18.64 333.23 A9.3197 9.3197 0 0 1 0 333.23 Z" class="st7"/>
+ </g>
+ <path d="M0 333.23 A9.3197 9.3197 0 0 1 18.64 333.23 A9.3197 9.3197 0 0 1 0 333.23 Z" class="st8"/>
+ </g>
+ <g id="shape27-126" transform="translate(107.177,-55.9182)">
+ <title>Circle.156</title>
+ <g id="shadow27-127" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <path d="M0 333.23 A9.3197 9.3197 0 0 1 18.64 333.23 A9.3197 9.3197 0 0 1 0 333.23 Z" class="st7"/>
+ </g>
+ <path d="M0 333.23 A9.3197 9.3197 0 0 1 18.64 333.23 A9.3197 9.3197 0 0 1 0 333.23 Z" class="st8"/>
+ </g>
+ <g id="shape28-131" transform="translate(79.2174,-83.8773)">
+ <title>Circle.157</title>
+ <g id="shadow28-132" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <path d="M0 333.23 A9.3197 9.3197 0 0 1 18.64 333.23 A9.3197 9.3197 0 0 1 0 333.23 Z" class="st7"/>
+ </g>
+ <path d="M0 333.23 A9.3197 9.3197 0 0 1 18.64 333.23 A9.3197 9.3197 0 0 1 0 333.23 Z" class="st8"/>
+ </g>
+ <g id="shape29-136" transform="translate(153.775,-51.2583)">
+ <title>Circle.158</title>
+ <g id="shadow29-137" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <path d="M0 333.23 A9.3197 9.3197 0 0 1 18.64 333.23 A9.3197 9.3197 0 0 1 0 333.23 Z" class="st7"/>
+ </g>
+ <path d="M0 333.23 A9.3197 9.3197 0 0 1 18.64 333.23 A9.3197 9.3197 0 0 1 0 333.23 Z" class="st8"/>
+ </g>
+ <g id="shape30-141" transform="translate(93.197,-18.6394)">
+ <title>Circle.159</title>
+ <g id="shadow30-142" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <path d="M0 333.23 A9.3197 9.3197 0 0 1 18.64 333.23 A9.3197 9.3197 0 0 1 0 333.23 Z" class="st7"/>
+ </g>
+ <path d="M0 333.23 A9.3197 9.3197 0 0 1 18.64 333.23 A9.3197 9.3197 0 0 1 0 333.23 Z" class="st8"/>
+ </g>
+ <g id="shape31-146" transform="translate(27.4102,-57.9329) rotate(-7.12502)">
+ <title>Sheet.31</title>
+ <path d="M0 342.55 L31.41 342.55" class="st12"/>
+ </g>
+ <g id="shape32-151" transform="translate(182.13,-60.5772) rotate(9.46232)">
+ <title>Sheet.32</title>
+ <path d="M0 342.55 L22.18 342.55" class="st12"/>
+ </g>
+ <g id="shape33-156" transform="translate(47.8843,595.237) rotate(-160.346)">
+ <title>Sheet.33</title>
+ <path d="M0 342.55 L63.11 342.55" class="st12"/>
+ </g>
+ <g id="shape34-161" transform="translate(292.945,525.785) rotate(141.977)">
+ <title>Sheet.34</title>
+ <path d="M0 342.55 L20.97 342.55" class="st12"/>
+ </g>
+ <g id="shape35-166" transform="translate(-95.8971,591.793) rotate(-145.945)">
+ <title>Sheet.35</title>
+ <path d="M0 342.55 L28.55 342.55" class="st12"/>
+ </g>
+ <g id="shape36-171" transform="translate(37.2788,2.27374E-013)">
+ <title>Rectangle.167</title>
+ <desc>SUM</desc>
+ <g id="shadow36-172" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="328.566" width="21.7305" height="13.9795" class="st7"/>
+ </g>
+ <rect x="0" y="328.566" width="21.7305" height="13.9795" class="st8"/>
+ <text x="5" y="337.36" class="st16">SUM</text> </g>
+ <g id="shape37-177" transform="translate(55.9182,2.27374E-013)">
+ <title>Rectangle.168</title>
+ <desc>Packet</desc>
+ <g id="shadow37-178" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="328.566" width="46.5985" height="13.9795" class="st7"/>
+ </g>
+ <rect x="0" y="328.566" width="46.5985" height="13.9795" class="st17"/>
+ <text x="15.18" y="337.36" class="st18">Packet</text> </g>
+ <g id="shape38-183" transform="translate(-1.65867E-013,-32.6189)">
+ <title>Rectangle.169</title>
+ <desc>SUM</desc>
+ <g id="shadow38-184" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="328.566" width="20.7593" height="13.9795" class="st7"/>
+ </g>
+ <rect x="0" y="328.566" width="20.7593" height="13.9795" class="st8"/>
+ <text x="4.51" y="337.36" class="st16">SUM</text> </g>
+ <g id="shape39-189" transform="translate(18.6394,-32.6189)">
+ <title>Rectangle.170</title>
+ <desc>Packet</desc>
+ <g id="shadow39-190" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="328.566" width="46.5985" height="13.9795" class="st7"/>
+ </g>
+ <rect x="0" y="328.566" width="46.5985" height="13.9795" class="st17"/>
+ <text x="15.18" y="337.36" class="st18">Packet</text> </g>
+ <g id="shape40-195" transform="translate(197.019,626.053) rotate(161.565)">
+ <title>Sheet.40</title>
+ <path d="M0 328.31 A55.7483 27.2427 -124.2 0 0 42.37 334.19 L42.47 333.85" class="st19"/>
+ </g>
+ <g id="shape41-201" transform="translate(154.607,584.177) rotate(161.121)">
+ <title>Sheet.41</title>
+ <path d="M0 319.39 A80.5593 29.9756 -101.99 0 0 41.7 325.37 L41.79 325.02" class="st19"/>
+ </g>
+ <g id="shape42-206" transform="translate(3.02481,-66.7025)">
+ <title>Sheet.42</title>
+ <desc>Encode ID</desc>
+ <rect x="0" y="328.566" width="38.9138" height="13.9795" class="st9"/>
+ <text x="7.51" y="333.16" class="st21">Encode <tspan x="15.99" dy="1.2em" class="st4">ID</tspan></text> </g>
+ </g>
+ <g id="group43-210" transform="translate(12.0993,-165.858)">
+ <title>Sheet.43</title>
+ <g id="group44-211" transform="translate(7.21495,-75.757)">
+ <title>User</title>
+ <g id="shape45-212" transform="translate(13.3353,-1.13687E-013)">
+ <title>Sheet.45</title>
+ <g id="shadow45-213" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <path d="M20.77 325.42 A2.63551 2.63601 -180 1 0 15.5 325.42 A2.63551 2.63601 -180 1 0 20.77 325.42 ZM20.96
+ 328.77 L15.25 328.77 C14.84 328.77 14.46 328.91 14.16 329.14 C13.95 329.31 13.78 329.52
+ 13.66 329.76 C13.54 330 13.47 330.27 13.47 330.55 L13.47 337.32 L15.03 337.32 L15.03 342.55
+ L21.12 342.55 L21.12 337.32 L22.74 337.32 L22.74 330.55 C22.74 330.14 22.6 329.76 22.36
+ 329.46 C22.2 329.25 21.99 329.08 21.75 328.96 C21.51 328.84 21.24 328.77 20.96 328.77 Z"
+ class="st22"/>
+ <path d="M20.77 325.42 A2.63551 2.63601 -180 1 0 15.5 325.42 A2.63551 2.63601 -180 1 0 20.77 325.42"
+ class="st2"/>
+ <path d="M20.96 328.77 L15.25 328.77 C14.84 328.77 14.46 328.91 14.16 329.14 C13.95 329.31 13.78 329.52
+ 13.66 329.76 C13.54 330 13.47 330.27 13.47 330.55 L13.47 337.32 L15.03 337.32 L15.03 342.55
+ L21.12 342.55 L21.12 337.32 L22.74 337.32 L22.74 330.55 C22.74 330.14 22.6 329.76 22.36
+ 329.46 C22.2 329.25 21.99 329.08 21.75 328.96 C21.51 328.84 21.24 328.77 20.96 328.77"
+ class="st2"/>
+ <path d="M18.1 342.55 L18.1 338.37" class="st2"/>
+ <path d="M15.03 337.32 L15.03 333.71" class="st2"/>
+ <path d="M21.12 337.32 L21.12 333.71" class="st2"/>
+ <path d="M0 337.32 L13.47 337.32" class="st2"/>
+ </g>
+ <path d="M20.77 325.42 A2.63551 2.63601 -180 1 0 15.5 325.42 A2.63551 2.63601 -180 1 0 20.77 325.42 ZM20.96
+ 328.77 L15.25 328.77 C14.84 328.77 14.46 328.91 14.16 329.14 C13.95 329.31 13.78 329.52 13.66
+ 329.76 C13.54 330 13.47 330.27 13.47 330.55 L13.47 337.32 L15.03 337.32 L15.03 342.55 L21.12
+ 342.55 L21.12 337.32 L22.74 337.32 L22.74 330.55 C22.74 330.14 22.6 329.76 22.36 329.46 C22.2
+ 329.25 21.99 329.08 21.75 328.96 C21.51 328.84 21.24 328.77 20.96 328.77 Z" class="st23"/>
+ <path d="M20.77 325.42 A2.63551 2.63601 -180 1 0 15.5 325.42 A2.63551 2.63601 -180 1 0 20.77 325.42"
+ class="st24"/>
+ <path d="M20.96 328.77 L15.25 328.77 C14.84 328.77 14.46 328.91 14.16 329.14 C13.95 329.31 13.78 329.52 13.66
+ 329.76 C13.54 330 13.47 330.27 13.47 330.55 L13.47 337.32 L15.03 337.32 L15.03 342.55 L21.12
+ 342.55 L21.12 337.32 L22.74 337.32 L22.74 330.55 C22.74 330.14 22.6 329.76 22.36 329.46 C22.2
+ 329.25 21.99 329.08 21.75 328.96 C21.51 328.84 21.24 328.77 20.96 328.77" class="st24"/>
+ <path d="M18.1 342.55 L18.1 338.37" class="st24"/>
+ <path d="M15.03 337.32 L15.03 333.71" class="st24"/>
+ <path d="M21.12 337.32 L21.12 333.71" class="st24"/>
+ <path d="M0 337.32 L13.47 337.32" class="st24"/>
+ </g>
+ <g id="shape46-230" transform="translate(0,-8.39743)">
+ <title>Sheet.46</title>
+ <g id="shadow46-231" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <path d="M21.09 325.52 C21.09 325.13 20.96 324.79 20.74 324.51 C20.59 324.32 20.4 324.16 20.19 324.06
+ C19.97 323.95 19.72 323.89 19.46 323.89 L3.55 323.89 C3.16 323.89 2.82 324.02 2.54 324.23
+ C2.35 324.38 2.19 324.57 2.09 324.79 C1.98 325.01 1.92 325.25 1.92 325.52 L1.92 336.04 L21.09
+ 336.04 L21.09 325.52 ZM21.18 337.33 L1.77 337.33 L0 340.51 L0 342.55 L23.06 342.55 L23.06
+ 340.51 L21.18 337.33 Z" class="st7"/>
+ </g>
+ <path d="M21.09 325.52 C21.09 325.13 20.96 324.79 20.74 324.51 C20.59 324.32 20.4 324.16 20.19 324.06 C19.97
+ 323.95 19.72 323.89 19.46 323.89 L3.55 323.89 C3.16 323.89 2.82 324.02 2.54 324.23 C2.35 324.38
+ 2.19 324.57 2.09 324.79 C1.98 325.01 1.92 325.25 1.92 325.52 L1.92 336.04 L21.09 336.04 L21.09
+ 325.52 ZM21.18 337.33 L1.77 337.33 L0 340.51 L0 342.55 L23.06 342.55 L23.06 340.51 L21.18 337.33
+ Z" class="st25"/>
+ </g>
+ <g id="shape47-235" transform="translate(3.19243,-16.175)">
+ <title>Sheet.47</title>
+ <path d="M16.62 342.55 L16.62 333.29 C16.62 333.23 16.61 333.18 16.58 333.13 C16.55 333.07 16.5 333.02 16.44
+ 332.98 C16.39 332.95 16.33 332.94 16.27 332.94 L0.35 332.94 C0.29 332.94 0.24 332.95 0.19 332.98
+ C0.13 333.01 0.08 333.07 0.04 333.12 C0.02 333.17 0 333.23 0 333.29 L0 342.55 L16.62 342.55
+ Z" class="st26"/>
+ </g>
+ <g id="shape48-237" transform="translate(1.97942,-10.81)">
+ <title>Sheet.48</title>
+ <path d="M0.96 340.83 L0 342.55 L19.06 342.55 L18.1 340.83 L0.96 340.83 Z" class="st23"/>
+ </g>
+ </g>
+ <g id="group49-240" transform="translate(7.21495,-47.1858)">
+ <title>User.7</title>
+ <g id="shape50-241" transform="translate(13.3353,-1.13687E-013)">
+ <title>Sheet.50</title>
+ <g id="shadow50-242" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <path d="M20.77 325.42 A2.63551 2.63601 -180 1 0 15.5 325.42 A2.63551 2.63601 -180 1 0 20.77 325.42 ZM20.96
+ 328.77 L15.25 328.77 C14.84 328.77 14.46 328.91 14.16 329.14 C13.95 329.31 13.78 329.52
+ 13.66 329.76 C13.54 330 13.47 330.27 13.47 330.55 L13.47 337.32 L15.03 337.32 L15.03 342.55
+ L21.12 342.55 L21.12 337.32 L22.74 337.32 L22.74 330.55 C22.74 330.14 22.6 329.76 22.36
+ 329.46 C22.2 329.25 21.99 329.08 21.75 328.96 C21.51 328.84 21.24 328.77 20.96 328.77 Z"
+ class="st22"/>
+ <path d="M20.77 325.42 A2.63551 2.63601 -180 1 0 15.5 325.42 A2.63551 2.63601 -180 1 0 20.77 325.42"
+ class="st2"/>
+ <path d="M20.96 328.77 L15.25 328.77 C14.84 328.77 14.46 328.91 14.16 329.14 C13.95 329.31 13.78 329.52
+ 13.66 329.76 C13.54 330 13.47 330.27 13.47 330.55 L13.47 337.32 L15.03 337.32 L15.03 342.55
+ L21.12 342.55 L21.12 337.32 L22.74 337.32 L22.74 330.55 C22.74 330.14 22.6 329.76 22.36
+ 329.46 C22.2 329.25 21.99 329.08 21.75 328.96 C21.51 328.84 21.24 328.77 20.96 328.77"
+ class="st2"/>
+ <path d="M18.1 342.55 L18.1 338.37" class="st2"/>
+ <path d="M15.03 337.32 L15.03 333.71" class="st2"/>
+ <path d="M21.12 337.32 L21.12 333.71" class="st2"/>
+ <path d="M0 337.32 L13.47 337.32" class="st2"/>
+ </g>
+ <path d="M20.77 325.42 A2.63551 2.63601 -180 1 0 15.5 325.42 A2.63551 2.63601 -180 1 0 20.77 325.42 ZM20.96
+ 328.77 L15.25 328.77 C14.84 328.77 14.46 328.91 14.16 329.14 C13.95 329.31 13.78 329.52 13.66
+ 329.76 C13.54 330 13.47 330.27 13.47 330.55 L13.47 337.32 L15.03 337.32 L15.03 342.55 L21.12
+ 342.55 L21.12 337.32 L22.74 337.32 L22.74 330.55 C22.74 330.14 22.6 329.76 22.36 329.46 C22.2
+ 329.25 21.99 329.08 21.75 328.96 C21.51 328.84 21.24 328.77 20.96 328.77 Z" class="st23"/>
+ <path d="M20.77 325.42 A2.63551 2.63601 -180 1 0 15.5 325.42 A2.63551 2.63601 -180 1 0 20.77 325.42"
+ class="st24"/>
+ <path d="M20.96 328.77 L15.25 328.77 C14.84 328.77 14.46 328.91 14.16 329.14 C13.95 329.31 13.78 329.52 13.66
+ 329.76 C13.54 330 13.47 330.27 13.47 330.55 L13.47 337.32 L15.03 337.32 L15.03 342.55 L21.12
+ 342.55 L21.12 337.32 L22.74 337.32 L22.74 330.55 C22.74 330.14 22.6 329.76 22.36 329.46 C22.2
+ 329.25 21.99 329.08 21.75 328.96 C21.51 328.84 21.24 328.77 20.96 328.77" class="st24"/>
+ <path d="M18.1 342.55 L18.1 338.37" class="st24"/>
+ <path d="M15.03 337.32 L15.03 333.71" class="st24"/>
+ <path d="M21.12 337.32 L21.12 333.71" class="st24"/>
+ <path d="M0 337.32 L13.47 337.32" class="st24"/>
+ </g>
+ <g id="shape51-259" transform="translate(0,-8.39743)">
+ <title>Sheet.51</title>
+ <g id="shadow51-260" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <path d="M21.09 325.52 C21.09 325.13 20.96 324.79 20.74 324.51 C20.59 324.32 20.4 324.16 20.19 324.06
+ C19.97 323.95 19.72 323.89 19.46 323.89 L3.55 323.89 C3.16 323.89 2.82 324.02 2.54 324.23
+ C2.35 324.38 2.19 324.57 2.09 324.79 C1.98 325.01 1.92 325.25 1.92 325.52 L1.92 336.04 L21.09
+ 336.04 L21.09 325.52 ZM21.18 337.33 L1.77 337.33 L0 340.51 L0 342.55 L23.06 342.55 L23.06
+ 340.51 L21.18 337.33 Z" class="st7"/>
+ </g>
+ <path d="M21.09 325.52 C21.09 325.13 20.96 324.79 20.74 324.51 C20.59 324.32 20.4 324.16 20.19 324.06 C19.97
+ 323.95 19.72 323.89 19.46 323.89 L3.55 323.89 C3.16 323.89 2.82 324.02 2.54 324.23 C2.35 324.38
+ 2.19 324.57 2.09 324.79 C1.98 325.01 1.92 325.25 1.92 325.52 L1.92 336.04 L21.09 336.04 L21.09
+ 325.52 ZM21.18 337.33 L1.77 337.33 L0 340.51 L0 342.55 L23.06 342.55 L23.06 340.51 L21.18 337.33
+ Z" class="st25"/>
+ </g>
+ <g id="shape52-264" transform="translate(3.19243,-16.175)">
+ <title>Sheet.52</title>
+ <path d="M16.62 342.55 L16.62 333.29 C16.62 333.23 16.61 333.18 16.58 333.13 C16.55 333.07 16.5 333.02 16.44
+ 332.98 C16.39 332.95 16.33 332.94 16.27 332.94 L0.35 332.94 C0.29 332.94 0.24 332.95 0.19 332.98
+ C0.13 333.01 0.08 333.07 0.04 333.12 C0.02 333.17 0 333.23 0 333.29 L0 342.55 L16.62 342.55
+ Z" class="st26"/>
+ </g>
+ <g id="shape53-266" transform="translate(1.97942,-10.81)">
+ <title>Sheet.53</title>
+ <path d="M0.96 340.83 L0 342.55 L19.06 342.55 L18.1 340.83 L0.96 340.83 Z" class="st23"/>
+ </g>
+ </g>
+ <g id="group54-269" transform="translate(7.21495,-18.6146)">
+ <title>User.12</title>
+ <g id="shape55-270" transform="translate(13.3353,-1.13687E-013)">
+ <title>Sheet.55</title>
+ <g id="shadow55-271" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <path d="M20.77 325.42 A2.63551 2.63601 -180 1 0 15.5 325.42 A2.63551 2.63601 -180 1 0 20.77 325.42 ZM20.96
+ 328.77 L15.25 328.77 C14.84 328.77 14.46 328.91 14.16 329.14 C13.95 329.31 13.78 329.52
+ 13.66 329.76 C13.54 330 13.47 330.27 13.47 330.55 L13.47 337.32 L15.03 337.32 L15.03 342.55
+ L21.12 342.55 L21.12 337.32 L22.74 337.32 L22.74 330.55 C22.74 330.14 22.6 329.76 22.36
+ 329.46 C22.2 329.25 21.99 329.08 21.75 328.96 C21.51 328.84 21.24 328.77 20.96 328.77 Z"
+ class="st22"/>
+ <path d="M20.77 325.42 A2.63551 2.63601 -180 1 0 15.5 325.42 A2.63551 2.63601 -180 1 0 20.77 325.42"
+ class="st2"/>
+ <path d="M20.96 328.77 L15.25 328.77 C14.84 328.77 14.46 328.91 14.16 329.14 C13.95 329.31 13.78 329.52
+ 13.66 329.76 C13.54 330 13.47 330.27 13.47 330.55 L13.47 337.32 L15.03 337.32 L15.03 342.55
+ L21.12 342.55 L21.12 337.32 L22.74 337.32 L22.74 330.55 C22.74 330.14 22.6 329.76 22.36
+ 329.46 C22.2 329.25 21.99 329.08 21.75 328.96 C21.51 328.84 21.24 328.77 20.96 328.77"
+ class="st2"/>
+ <path d="M18.1 342.55 L18.1 338.37" class="st2"/>
+ <path d="M15.03 337.32 L15.03 333.71" class="st2"/>
+ <path d="M21.12 337.32 L21.12 333.71" class="st2"/>
+ <path d="M0 337.32 L13.47 337.32" class="st2"/>
+ </g>
+ <path d="M20.77 325.42 A2.63551 2.63601 -180 1 0 15.5 325.42 A2.63551 2.63601 -180 1 0 20.77 325.42 ZM20.96
+ 328.77 L15.25 328.77 C14.84 328.77 14.46 328.91 14.16 329.14 C13.95 329.31 13.78 329.52 13.66
+ 329.76 C13.54 330 13.47 330.27 13.47 330.55 L13.47 337.32 L15.03 337.32 L15.03 342.55 L21.12
+ 342.55 L21.12 337.32 L22.74 337.32 L22.74 330.55 C22.74 330.14 22.6 329.76 22.36 329.46 C22.2
+ 329.25 21.99 329.08 21.75 328.96 C21.51 328.84 21.24 328.77 20.96 328.77 Z" class="st23"/>
+ <path d="M20.77 325.42 A2.63551 2.63601 -180 1 0 15.5 325.42 A2.63551 2.63601 -180 1 0 20.77 325.42"
+ class="st24"/>
+ <path d="M20.96 328.77 L15.25 328.77 C14.84 328.77 14.46 328.91 14.16 329.14 C13.95 329.31 13.78 329.52 13.66
+ 329.76 C13.54 330 13.47 330.27 13.47 330.55 L13.47 337.32 L15.03 337.32 L15.03 342.55 L21.12
+ 342.55 L21.12 337.32 L22.74 337.32 L22.74 330.55 C22.74 330.14 22.6 329.76 22.36 329.46 C22.2
+ 329.25 21.99 329.08 21.75 328.96 C21.51 328.84 21.24 328.77 20.96 328.77" class="st24"/>
+ <path d="M18.1 342.55 L18.1 338.37" class="st24"/>
+ <path d="M15.03 337.32 L15.03 333.71" class="st24"/>
+ <path d="M21.12 337.32 L21.12 333.71" class="st24"/>
+ <path d="M0 337.32 L13.47 337.32" class="st24"/>
+ </g>
+ <g id="shape56-288" transform="translate(0,-8.39743)">
+ <title>Sheet.56</title>
+ <g id="shadow56-289" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <path d="M21.09 325.52 C21.09 325.13 20.96 324.79 20.74 324.51 C20.59 324.32 20.4 324.16 20.19 324.06
+ C19.97 323.95 19.72 323.89 19.46 323.89 L3.55 323.89 C3.16 323.89 2.82 324.02 2.54 324.23
+ C2.35 324.38 2.19 324.57 2.09 324.79 C1.98 325.01 1.92 325.25 1.92 325.52 L1.92 336.04 L21.09
+ 336.04 L21.09 325.52 ZM21.18 337.33 L1.77 337.33 L0 340.51 L0 342.55 L23.06 342.55 L23.06
+ 340.51 L21.18 337.33 Z" class="st7"/>
+ </g>
+ <path d="M21.09 325.52 C21.09 325.13 20.96 324.79 20.74 324.51 C20.59 324.32 20.4 324.16 20.19 324.06 C19.97
+ 323.95 19.72 323.89 19.46 323.89 L3.55 323.89 C3.16 323.89 2.82 324.02 2.54 324.23 C2.35 324.38
+ 2.19 324.57 2.09 324.79 C1.98 325.01 1.92 325.25 1.92 325.52 L1.92 336.04 L21.09 336.04 L21.09
+ 325.52 ZM21.18 337.33 L1.77 337.33 L0 340.51 L0 342.55 L23.06 342.55 L23.06 340.51 L21.18 337.33
+ Z" class="st25"/>
+ </g>
+ <g id="shape57-293" transform="translate(3.19243,-16.175)">
+ <title>Sheet.57</title>
+ <path d="M16.62 342.55 L16.62 333.29 C16.62 333.23 16.61 333.18 16.58 333.13 C16.55 333.07 16.5 333.02 16.44
+ 332.98 C16.39 332.95 16.33 332.94 16.27 332.94 L0.35 332.94 C0.29 332.94 0.24 332.95 0.19 332.98
+ C0.13 333.01 0.08 333.07 0.04 333.12 C0.02 333.17 0 333.23 0 333.29 L0 342.55 L16.62 342.55
+ Z" class="st26"/>
+ </g>
+ <g id="shape58-295" transform="translate(1.97942,-10.81)">
+ <title>Sheet.58</title>
+ <path d="M0.96 340.83 L0 342.55 L19.06 342.55 L18.1 340.83 L0.96 340.83 Z" class="st23"/>
+ </g>
+ </g>
+ <g id="group59-298" transform="translate(171.161,-45.6707)">
+ <title>Data Center</title>
+ <g id="shape60-299">
+ <title>Sheet.60</title>
+ <g id="shadow60-300" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <ellipse cx="37.8785" cy="331.299" rx="37.8785" ry="11.246" class="st7"/>
+ </g>
+ <ellipse cx="37.8785" cy="331.299" rx="37.8785" ry="11.246" class="st8"/>
+ </g>
+ <g id="shape61-304" transform="translate(6.86487,-7.30475)">
+ <title>Sheet.61</title>
+ <g id="shadow61-305" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <path d="M54.1 311.79 L43.28 311.79 L43.28 342.55 L62.03 342.55 L62.03 311.79 L54.1 311.79 ZM43.28 332.44
+ L43.28 311.79 L51.21 311.79 L51.21 301.69 L32.33 301.69 L32.33 311.79 L40.39 311.79 L40.39
+ 332.44 L43.28 332.44 ZM40.39 301.69 L40.39 293.03 L21.64 293.03 L21.64 301.69 L29.57 301.69
+ L29.57 311.79 L32.46 311.79 L32.46 301.69 L40.39 301.69 ZM32.46 311.79 L21.64 311.79 L21.64
+ 342.55 L40.39 342.55 L40.39 311.79 L32.46 311.79 ZM10.82 311.79 L0 311.79 L0 342.55 L18.75
+ 342.55 L18.75 311.79 L10.82 311.79 ZM21.64 311.79 L29.57 311.79 L29.57 301.69 L10.82 301.69
+ L10.82 311.79 L18.75 311.79 L18.75 332.44 L21.64 332.44 L21.64 311.79 Z" class="st7"/>
+ </g>
+ <path d="M54.1 311.79 L43.28 311.79 L43.28 342.55 L62.03 342.55 L62.03 311.79 L54.1 311.79 ZM43.28 332.44
+ L43.28 311.79 L51.21 311.79 L51.21 301.69 L32.33 301.69 L32.33 311.79 L40.39 311.79 L40.39 332.44
+ L43.28 332.44 ZM40.39 301.69 L40.39 293.03 L21.64 293.03 L21.64 301.69 L29.57 301.69 L29.57
+ 311.79 L32.46 311.79 L32.46 301.69 L40.39 301.69 ZM32.46 311.79 L21.64 311.79 L21.64 342.55
+ L40.39 342.55 L40.39 311.79 L32.46 311.79 ZM10.82 311.79 L0 311.79 L0 342.55 L18.75 342.55 L18.75
+ 311.79 L10.82 311.79 ZM21.64 311.79 L29.57 311.79 L29.57 301.69 L10.82 301.69 L10.82 311.79
+ L18.75 311.79 L18.75 332.44 L21.64 332.44 L21.64 311.79 Z" class="st8"/>
+ </g>
+ <g id="shape62-309" transform="translate(20.0835,-20.5174)">
+ <title>Sheet.62</title>
+ <g id="shadow62-310" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <path d="M45.36 341.36 A1.13296 1.18615 -180 1 0 43.09 341.36 A1.13296 1.18615 -180 1 0 45.36 341.36
+ ZM23.46 341.36 A1.13296 1.18615 -180 1 0 21.2 341.36 A1.13296 1.18615 -180 1 0 23.46 341.36
+ ZM2.27 341.36 A1.13296 1.18615 -180 1 0 0 341.36 A1.13296 1.18615 -180 1 0 2.27 341.36 Z"
+ class="st22"/>
+ </g>
+ <path d="M45.36 341.36 A1.13296 1.18615 -180 1 0 43.09 341.36 A1.13296 1.18615 -180 1 0 45.36 341.36 ZM23.46
+ 341.36 A1.13296 1.18615 -180 1 0 21.2 341.36 A1.13296 1.18615 -180 1 0 23.46 341.36 ZM2.27 341.36
+ A1.13296 1.18615 -180 1 0 0 341.36 A1.13296 1.18615 -180 1 0 2.27 341.36 Z" class="st27"/>
+ </g>
+ <g id="shape63-317" transform="translate(14.2717,-12.5134)">
+ <title>Sheet.63</title>
+ <g id="shadow63-318" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <path d="M43.09 342.55 L51.17 342.55 L51.17 341.74 L43.09 341.74 L43.09 342.55 ZM43.09 340.12 L51.17
+ 340.12 L51.17 339.32 L43.09 339.32 L43.09 340.12 ZM43.09 337.69 L51.17 337.69 L51.17 336.89
+ L43.09 336.89 L43.09 337.69 ZM21.2 342.55 L29.27 342.55 L29.27 341.74 L21.2 341.74 L21.2
+ 342.55 ZM21.2 340.12 L29.27 340.12 L29.27 339.32 L21.2 339.32 L21.2 340.12 ZM21.2 337.69
+ L29.27 337.69 L29.27 336.89 L21.2 336.89 L21.2 337.69 ZM-0 342.55 L8.08 342.55 L8.08 341.74
+ L-0 341.74 L-0 342.55 ZM-0 340.12 L8.08 340.12 L8.08 339.32 L-0 339.32 L-0 340.12 ZM-0 337.69
+ L8.08 337.69 L8.08 336.89 L-0 336.89 L-0 337.69 Z" class="st22"/>
+ </g>
+ <path d="M43.09 342.55 L51.17 342.55 L51.17 341.74 L43.09 341.74 L43.09 342.55 ZM43.09 340.12 L51.17 340.12
+ L51.17 339.32 L43.09 339.32 L43.09 340.12 ZM43.09 337.69 L51.17 337.69 L51.17 336.89 L43.09
+ 336.89 L43.09 337.69 ZM21.2 342.55 L29.27 342.55 L29.27 341.74 L21.2 341.74 L21.2 342.55 ZM21.2
+ 340.12 L29.27 340.12 L29.27 339.32 L21.2 339.32 L21.2 340.12 ZM21.2 337.69 L29.27 337.69 L29.27
+ 336.89 L21.2 336.89 L21.2 337.69 ZM-0 342.55 L8.08 342.55 L8.08 341.74 L-0 341.74 L-0 342.55
+ ZM-0 340.12 L8.08 340.12 L8.08 339.32 L-0 339.32 L-0 340.12 ZM-0 337.69 L8.08 337.69 L8.08 336.89
+ L-0 336.89 L-0 337.69 Z" class="st23"/>
+ </g>
+ </g>
+ <g id="group64-325" transform="translate(59.5234,-47.1858)">
+ <title>Load balancer</title>
+ <g id="shape65-326" transform="translate(0,-1.653)">
+ <title>Sheet.65</title>
+ <g id="shadow65-327" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <path d="M12.18 329.62 L4.06 329.62 L0 332.02 L0 342.55 L16.23 342.55 L16.23 332.02 L12.18 329.62 Z"
+ class="st22"/>
+ <path d="M0 332.02 L16.23 332.02" class="st2"/>
+ <path d="M12.18 329.62 L4.06 329.62 L0 332.02 L0 342.55 L16.23 342.55 L16.23 332.02 L12.18 329.62"
+ class="st2"/>
+ </g>
+ <path d="M12.18 329.62 L4.06 329.62 L0 332.02 L0 342.55 L16.23 342.55 L16.23 332.02 L12.18 329.62 Z"
+ class="st27"/>
+ <path d="M0 332.02 L16.23 332.02" class="st28"/>
+ <path d="M12.18 329.62 L4.06 329.62 L0 332.02 L0 342.55 L16.23 342.55 L16.23 332.02 L12.18 329.62"
+ class="st28"/>
+ </g>
+ <g id="shape66-336" transform="translate(1.81062,-2.91583)">
+ <title>Sheet.66</title>
+ <g id="shadow66-337" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <path d="M10.22 341.92 L9.29 342.12 L9.95 342.55 L11.2 342.23 L10.99 340.96 L10.33 340.52 L10.53 341.44
+ L8.34 340.01 L8.03 340.49 L10.22 341.92 ZM11.46 338.22 L8.84 338.22 L8.84 338.78 L11.45
+ 338.78 L10.78 339.45 L11.57 339.45 L12.45 338.5 L11.57 337.55 L10.78 337.55 L11.46 338.22
+ ZM10.48 335.2 L8.29 336.64 L8.6 337.12 L10.79 335.68 L10.59 336.61 L11.25 336.17 L11.46
+ 334.9 L10.21 334.58 L9.55 335.01 L10.48 335.2 ZM6.25 336.37 C5.11 336.37 4.19 337.29 4.19
+ 338.43 C4.19 339.56 5.11 340.48 6.25 340.48 C7.38 340.48 8.31 339.56 8.31 338.43 C8.31 337.29
+ 7.38 336.37 6.25 336.37 ZM6.25 337.02 C7.02 337.02 7.66 337.65 7.66 338.43 C7.66 339.2 7.02
+ 339.83 6.25 339.83 C5.47 339.83 4.84 339.2 4.84 338.43 C4.84 337.65 5.47 337.02 6.25 337.02
+ ZM2.62 338.14 L0 338.14 L0 338.71 L2.62 338.71 L1.94 339.38 L2.74 339.38 L3.61 338.43 L2.73
+ 337.47 L1.95 337.47 L2.62 338.14 Z" class="st7"/>
+ </g>
+ <path d="M10.22 341.92 L9.29 342.12 L9.95 342.55 L11.2 342.23 L10.99 340.96 L10.33 340.52 L10.53 341.44 L8.34
+ 340.01 L8.03 340.49 L10.22 341.92 ZM11.46 338.22 L8.84 338.22 L8.84 338.78 L11.45 338.78 L10.78
+ 339.45 L11.57 339.45 L12.45 338.5 L11.57 337.55 L10.78 337.55 L11.46 338.22 ZM10.48 335.2 L8.29
+ 336.64 L8.6 337.12 L10.79 335.68 L10.59 336.61 L11.25 336.17 L11.46 334.9 L10.21 334.58 L9.55
+ 335.01 L10.48 335.2 ZM6.25 336.37 C5.11 336.37 4.19 337.29 4.19 338.43 C4.19 339.56 5.11 340.48
+ 6.25 340.48 C7.38 340.48 8.31 339.56 8.31 338.43 C8.31 337.29 7.38 336.37 6.25 336.37 ZM6.25
+ 337.02 C7.02 337.02 7.66 337.65 7.66 338.43 C7.66 339.2 7.02 339.83 6.25 339.83 C5.47 339.83
+ 4.84 339.2 4.84 338.43 C4.84 337.65 5.47 337.02 6.25 337.02 ZM2.62 338.14 L0 338.14 L0 338.71
+ L2.62 338.71 L1.94 339.38 L2.74 339.38 L3.61 338.43 L2.73 337.47 L1.95 337.47 L2.62 338.14 Z"
+ class="st29"/>
+ </g>
+ </g>
+ <g id="group67-341" transform="translate(104.617,-86.5795)">
+ <title>Directory server</title>
+ <g id="shape68-342" transform="translate(0,-0.451005)">
+ <title>Sheet.68</title>
+ <g id="shadow68-343" transform="matrix(1,0,0,1,0.3456,1.9728)" class="st1">
+ <path d="M0.47 329.86 L0.47 331.94 L1.46 332.57 L3.33 331.52 L15.43 338.57 L15.43 340.61 L16.42 341.24
+ L18.24 340.22 L22.24 342.55 L22.24 339.27 L36.07 331.28 L36.07 321.27 L19.64 311.85 L3.16
+ 321.13 L3.16 321.5 L0 319.68 L0 329.58 L0.47 329.86 Z" class="st30"/>
+ </g>
+ <path d="M0.47 329.86 L0.47 331.94 L1.46 332.57 L3.33 331.52 L15.43 338.57 L15.43 340.61 L16.42 341.24 L18.24
+ 340.22 L22.24 342.55 L22.24 339.27 L36.07 331.28 L36.07 321.27 L19.64 311.85 L3.16 321.13 L3.16
+ 321.5 L0 319.68 L0 329.58 L0.47 329.86 Z" class="st31"/>
+ </g>
+ <g id="shape69-347" transform="translate(3.1636,-11.8063)">
+ <title>Sheet.69</title>
+ <path d="M16.48 323.24 L32.91 332.66 L16.31 342.55 L0 333.26 L0 332.52 L16.48 323.24 Z" class="st32"/>
+ </g>
+ <g id="shape70-351" transform="translate(19.06,-3.68954)">
+ <title>Sheet.70</title>
+ <path d="M17.01 324.55 L0 334.19 L3.18 342.55 L17.01 334.56 L17.01 324.55 Z" class="st33"/>
+ </g>
+ <g id="shape71-355" transform="translate(0,-0.415652)">
+ <title>Sheet.71</title>
+ <path d="M22.24 342.55 L0 329.58 L0 319.68 L22.24 332.43 L22.24 342.55 Z" class="st34"/>
+ </g>
+ <g id="shape72-363" transform="translate(0.82443,-19.8334)">
+ <title>Sheet.72</title>
+ <path d="M1.13 341.58 a0.653986 0.653986 -180 0 0 -0.73971 -0.492434 a0.656072 0.656072 -180 0 0 -0.253101
+ 0.865731 a0.653066 0.653066 -180 0 0 0.740769 0.491375 a0.655459 0.655459 -180 0 0 0.252042
+ -0.864672 Z" class="st35"/>
+ </g>
+ <g id="shape73-367" transform="translate(3.62283,-15.1638)">
+ <title>Sheet.73</title>
+ <path d="M3.22 339.78 A1.86495 1.86495 -180 0 0 1.11 338.38 A1.8709 1.8709 -180 0 0 0.38 340.85 A1.86532
+ 1.86532 -180 0 0 2.5 342.25 A1.87264 1.87264 -180 0 0 3.22 339.78 Z" class="st35"/>
+ </g>
+ <g id="shape74-370" transform="translate(3.62283,-10.4867)">
+ <title>Sheet.74</title>
+ <path d="M3.22 339.78 A1.86495 1.86495 -180 0 0 1.11 338.38 A1.8709 1.8709 -180 0 0 0.38 340.85 A1.86532
+ 1.86532 -180 0 0 2.5 342.25 A1.87264 1.87264 -180 0 0 3.22 339.78 Z" class="st35"/>
+ </g>
+ <g id="shape75-373" transform="translate(4.52404,-16.3668)">
+ <title>Sheet.75</title>
+ <path d="M1.61 341.16 a0.931952 0.931952 -180 0 0 -1.05741 -0.702645 a0.935408 0.935408 -180 0 0 -0.361118
+ 1.23585 a0.932139 0.932139 -180 0 0 1.05794 0.702645 a0.935822 0.935822 -180 0 0 0.360589 -1.23585
+ Z" class="st36"/>
+ </g>
+ <g id="shape76-377" transform="translate(4.52404,-11.6897)">
+ <title>Sheet.76</title>
+ <path d="M1.61 341.16 a0.931952 0.931952 -180 0 0 -1.05741 -0.702645 a0.935875 0.935875 -180 0 0 -0.361118
+ 1.23585 a0.932139 0.932139 -180 0 0 1.05794 0.702645 a0.935822 0.935822 -180 0 0 0.360589 -1.23585
+ Z" class="st36"/>
+ </g>
+ <g id="shape77-380" transform="translate(7.78787,-8.83469)">
+ <title>Sheet.77</title>
+ <path d="M0 341.57 L0.05 333.6 L1.83 334.57 L1.78 342.55 L0 341.57 Z" class="st37"/>
+ </g>
+ <g id="shape78-384" transform="translate(10.204,-7.4008)">
+ <title>Sheet.78</title>
+ <path d="M0 341.57 L0.05 333.6 L1.83 334.57 L1.78 342.55 L0 341.57 Z" class="st37"/>
+ </g>
+ <g id="shape79-387" transform="translate(12.6196,-5.96639)">
+ <title>Sheet.79</title>
+ <path d="M0 341.57 L0.05 333.6 L1.83 334.57 L1.78 342.55 L0 341.57 Z" class="st37"/>
+ </g>
+ <g id="shape80-390" transform="translate(15.0357,-4.53251)">
+ <title>Sheet.80</title>
+ <path d="M0 341.57 L0.05 333.6 L1.83 334.57 L1.78 342.55 L0 341.57 Z" class="st37"/>
+ </g>
+ <g id="shape81-393" transform="translate(8.24006,-10.0631)">
+ <title>Sheet.81</title>
+ <path d="M0.85 342.24 a0.388199 0.388199 0 0 1 -0.425188 0.308698 a0.638045 0.638045 0 0 1 -0.424658 -0.573447
+ L0 336.5 a0.387575 0.387575 0 0 1 0.424658 -0.308698 a0.637725 0.637725 0 0 1 0.425188 0.573447
+ L0.85 342.24 Z" class="st38"/>
+ </g>
+ <g id="shape82-397" transform="translate(10.6556,-8.62924)">
+ <title>Sheet.82</title>
+ <path d="M0.85 342.24 a0.388199 0.388199 0 0 1 -0.425188 0.308698 a0.638045 0.638045 0 0 1 -0.424658 -0.573447
+ L0 336.5 a0.387575 0.387575 0 0 1 0.424658 -0.308698 a0.637725 0.637725 0 0 1 0.425188 0.573447
+ L0.85 342.24 Z" class="st38"/>
+ </g>
+ <g id="shape83-400" transform="translate(13.0717,-7.19483)">
+ <title>Sheet.83</title>
+ <path d="M0.85 342.24 a0.388199 0.388199 0 0 1 -0.425188 0.308698 a0.638045 0.638045 0 0 1 -0.424658 -0.573447
+ L0 336.5 a0.387575 0.387575 0 0 1 0.424658 -0.308698 a0.637725 0.637725 0 0 1 0.425188 0.573447
+ L0.85 342.24 Z" class="st38"/>
+ </g>
+ <g id="shape84-403" transform="translate(15.4873,-5.76095)">
+ <title>Sheet.84</title>
+ <path d="M0.85 342.24 a0.388502 0.388502 0 0 1 -0.425717 0.308698 a0.638367 0.638367 0 0 1 -0.424129 -0.573447
+ L0 336.5 a0.387272 0.387272 0 0 1 0.424129 -0.308698 a0.638235 0.638235 0 0 1 0.425717 0.573447
+ L0.85 342.24 Z" class="st38"/>
+ </g>
+ <g id="shape85-406" transform="translate(7.78787,-9.81214)">
+ <title>Sheet.85</title>
+ <path d="M0 342.55 L0.05 334.57 L1.83 335.55 L0 342.55 Z" class="st39"/>
+ <path d="M0 342.55 L0.05 334.57 L1.83 335.55" class="st40"/>
+ </g>
+ <g id="shape86-409" transform="translate(10.204,-8.37826)">
+ <title>Sheet.86</title>
+ <path d="M0 342.55 L0.05 334.57 L1.83 335.55 L0 342.55 Z" class="st39"/>
+ <path d="M0 342.55 L0.05 334.57 L1.83 335.55" class="st40"/>
+ </g>
+ <g id="shape87-412" transform="translate(12.6196,-6.94385)">
+ <title>Sheet.87</title>
+ <path d="M0 342.55 L0.05 334.57 L1.83 335.55 L0 342.55 Z" class="st39"/>
+ <path d="M0 342.55 L0.05 334.57 L1.83 335.55" class="st40"/>
+ </g>
+ <g id="shape88-415" transform="translate(15.0357,-5.50996)">
+ <title>Sheet.88</title>
+ <path d="M0 342.55 L0.05 334.57 L1.83 335.55 L0 342.55 Z" class="st39"/>
+ <path d="M0 342.55 L0.05 334.57 L1.83 335.55" class="st40"/>
+ </g>
+ <g id="shape89-418" transform="translate(7.78787,-4.53251)">
+ <title>Sheet.89</title>
+ <path d="M9.08 334.57 L9.03 342.55 L7.25 341.57 L9.08 334.57 ZM6.66 333.14 L6.61 341.11 L4.83 340.13 L6.66
+ 333.14 ZM4.25 331.7 L4.2 339.68 L2.42 338.7 L4.25 331.7 ZM1.83 330.27 L1.78 338.24 L0 337.27
+ L1.83 330.27 Z" class="st39"/>
+ <path d="M9.08 334.57 L9.03 342.55 L7.25 341.57M6.66 333.14 L6.61 341.11 L4.83 340.13M4.25 331.7 L4.2 339.68
+ L2.42 338.7M1.83 330.27 L1.78 338.24 L0 337.27" class="st41"/>
+ </g>
+ <g id="shape90-421" transform="translate(2.22125,-11.8454)">
+ <title>Sheet.90</title>
+ <path d="M0 341.85 L0.63 341.42 L1.42 341.78 L0.03 342.55 L0 341.85 Z" class="st42"/>
+ </g>
+ <g id="shape91-425" transform="translate(17.1796,-3.17487)">
+ <title>Sheet.91</title>
+ <path d="M0 341.85 L0.63 341.42 L1.42 341.78 L0.03 342.55 L0 341.85 Z" class="st42"/>
+ </g>
+ <g id="shape92-428" transform="translate(1.46036,-10.3893)">
+ <title>Sheet.92</title>
+ <path d="M2.12 341.35 L0 342.55 L0 333.54 L2.12 332.29 L2.12 333.41 L0.79 334.15 L0.79 341.09 L2.18 340.33
+ L2.12 341.35 Z" class="st33"/>
+ </g>
+ <g id="shape93-431" transform="translate(16.4187,-1.71875)">
+ <title>Sheet.93</title>
+ <path d="M2.12 341.35 L0 342.55 L0 333.54 L2.12 332.29 L2.12 333.41 L0.79 334.15 L0.79 341.09 L2.18 340.33
+ L2.12 341.35 Z" class="st33"/>
+ </g>
+ <g id="shape94-434" transform="translate(0.467548,-10.3893)">
+ <title>Sheet.94</title>
+ <path d="M0.99 333.54 L3.11 332.29 L2.12 331.66 L0 332.91 L0 341.92 L0.99 342.55 L0.99 333.54 Z"
+ class="st43"/>
+ </g>
+ <g id="shape95-438" transform="translate(15.4259,-1.71875)">
+ <title>Sheet.95</title>
+ <path d="M0.99 333.54 L3.11 332.29 L2.12 331.66 L0 332.91 L0 341.92 L0.99 342.55 L0.99 333.54 Z"
+ class="st43"/>
+ </g>
+ <g id="shape96-441" transform="translate(0.467548,-1.71928)">
+ <title>Sheet.96</title>
+ <path d="M17.34 339.96 L16.75 340.37 L16.75 334.15 L18.07 333.41 L18.07 332.29 L17.08 331.66 L14.96 332.91
+ L14.96 341.92 L15.95 342.55 L18.07 341.35 L18.14 340.33 L17.34 339.96 ZM2.38 331.29 L1.79 331.7
+ L1.79 325.48 L3.11 324.74 L3.11 323.62 L2.12 322.99 L0 324.24 L0 333.25 L0.99 333.87 L3.11 332.68
+ L3.18 331.66 L2.38 331.29 Z" class="st44"/>
+ </g>
+ <g id="shape97-443" transform="translate(19.9526,-8.71396)">
+ <title>Sheet.97</title>
+ <path d="M1.13 341.58 a0.653986 0.653986 -180 0 0 -0.73971 -0.492434 a0.656072 0.656072 -180 0 0 -0.253101
+ 0.865731 a0.653066 0.653066 -180 0 0 0.740769 0.491375 a0.655459 0.655459 -180 0 0 0.252042
+ -0.864672 Z" class="st35"/>
+ </g>
+ <g id="shape98-446" transform="translate(19.9526,-2.35997)">
+ <title>Sheet.98</title>
+ <path d="M1.13 341.58 a0.653986 0.653986 -180 0 0 -0.73971 -0.492434 a0.656072 0.656072 -180 0 0 -0.253101
+ 0.865731 a0.653066 0.653066 -180 0 0 0.740769 0.491375 a0.655459 0.655459 -180 0 0 0.252042
+ -0.864672 Z" class="st35"/>
+ </g>
+ <g id="shape99-449" transform="translate(0,-0.415652)">
+ <title>Sheet.99</title>
+ <path d="M36.07 331.28 L36.07 321.27 L19.64 311.85 L3.16 321.13 L3.16 321.52 L0 319.68 L0 329.58 L0.47 329.86
+ L0.47 331.94 L1.46 332.57 L3.33 331.52 L15.43 338.57 L15.43 340.61 L16.42 341.24 L18.24 340.22
+ L22.24 342.55 L22.24 339.27 L36.07 331.28 Z" class="st44"/>
+ </g>
+ <g id="shape100-451" transform="translate(27.8077,-2.86477)">
+ <title>Sheet.100</title>
+ <path d="M0.29 342.55 L6.62 338.89 A1.82805 1.82805 0 0 1 6.62 336.9 L0.29 340.55 A1.82805 1.82805 -180 0
+ 0 0.29 342.55 Z" class="st45"/>
+ </g>
+ <g id="shape101-453" transform="translate(23.5035,-4.85627)">
+ <title>Sheet.101</title>
+ <path d="M4.6 342.55 L10.92 338.89 L6.32 336.24 L0 339.89 L4.6 342.55 Z" class="st46"/>
+ </g>
+ <g id="shape102-457" transform="translate(23.3588,-2.86477)">
+ <title>Sheet.102</title>
+ <path d="M0.14 339.89 L4.74 342.55 A1.82805 1.82805 0 0 1 4.74 340.55 L0.14 337.9 A3.49826 3.49826 -180 0
+ 0 0.14 339.89 Z" class="st47"/>
+ </g>
+ <g id="shape103-461" transform="translate(25.8933,-5.98478)">
+ <title>Sheet.103</title>
+ <path d="M2.87 342.55 L0 340.89" class="st48"/>
+ <path d="M0.94 340.34 L3.82 342" class="st48"/>
+ <path d="M1.88 339.8 L4.76 341.46" class="st48"/>
+ <path d="M2.82 339.26 L5.7 340.92" class="st48"/>
+ <path d="M3.76 338.71 L6.64 340.37" class="st48"/>
+ </g>
+ <g id="shape104-468" transform="translate(23.5035,-7.51159)">
+ <title>Sheet.104</title>
+ <path d="M5.13 341.17 L11.45 337.52 A11.9345 11.9345 0 0 1 6.32 338.89 L0 342.55 A11.9345 11.9345 -180 0
+ 0 5.13 341.17 Z" class="st49"/>
+ </g>
+ <g id="shape105-476" transform="translate(30.2106,-4.74563)">
+ <title>Sheet.105</title>
+ <path d="M0.98 341.98 L0 342.55" class="st48"/>
+ <path d="M1.26 341.48 L2.24 340.92" class="st48"/>
+ <path d="M2.53 340.42 L3.51 339.86" class="st48"/>
+ </g>
+ <g id="shape106-481" transform="translate(23.3588,-2.86477)">
+ <title>Sheet.106</title>
+ <path d="M0.14 339.89 L4.74 342.55 L11.07 338.89 A1.82805 1.82805 0 0 1 11.07 336.9 L7.85 335.04 L11.6 332.87
+ A11.9345 11.9345 0 0 1 6.47 334.25 L0.14 337.9 A3.49826 3.49826 -180 0 0 0.14 339.89"
+ class="st50"/>
+ </g>
+ </g>
+ <g id="group107-484" transform="translate(104.617,-33.8201)">
+ <title>Directory server.104</title>
+ <g id="shape108-485" transform="translate(0,-0.451005)">
+ <title>Sheet.108</title>
+ <g id="shadow108-486" transform="matrix(1,0,0,1,0.3456,1.9728)" class="st1">
+ <path d="M0.47 329.86 L0.47 331.94 L1.46 332.57 L3.33 331.52 L15.43 338.57 L15.43 340.61 L16.42 341.24
+ L18.24 340.22 L22.24 342.55 L22.24 339.27 L36.07 331.28 L36.07 321.27 L19.64 311.85 L3.16
+ 321.13 L3.16 321.5 L0 319.68 L0 329.58 L0.47 329.86 Z" class="st30"/>
+ </g>
+ <path d="M0.47 329.86 L0.47 331.94 L1.46 332.57 L3.33 331.52 L15.43 338.57 L15.43 340.61 L16.42 341.24 L18.24
+ 340.22 L22.24 342.55 L22.24 339.27 L36.07 331.28 L36.07 321.27 L19.64 311.85 L3.16 321.13 L3.16
+ 321.5 L0 319.68 L0 329.58 L0.47 329.86 Z" class="st31"/>
+ </g>
+ <g id="shape109-490" transform="translate(3.1636,-11.8063)">
+ <title>Sheet.109</title>
+ <path d="M16.48 323.24 L32.91 332.66 L16.31 342.55 L0 333.26 L0 332.52 L16.48 323.24 Z" class="st32"/>
+ </g>
+ <g id="shape110-493" transform="translate(19.06,-3.68954)">
+ <title>Sheet.110</title>
+ <path d="M17.01 324.55 L0 334.19 L3.18 342.55 L17.01 334.56 L17.01 324.55 Z" class="st33"/>
+ </g>
+ <g id="shape111-496" transform="translate(0,-0.415652)">
+ <title>Sheet.111</title>
+ <path d="M22.24 342.55 L0 329.58 L0 319.68 L22.24 332.43 L22.24 342.55 Z" class="st34"/>
+ </g>
+ <g id="shape112-499" transform="translate(0.82443,-19.8334)">
+ <title>Sheet.112</title>
+ <path d="M1.13 341.58 a0.653986 0.653986 -180 0 0 -0.73971 -0.492434 a0.656072 0.656072 -180 0 0 -0.253101
+ 0.865731 a0.653066 0.653066 -180 0 0 0.740769 0.491375 a0.655459 0.655459 -180 0 0 0.252042
+ -0.864672 Z" class="st35"/>
+ </g>
+ <g id="shape113-502" transform="translate(3.62283,-15.1638)">
+ <title>Sheet.113</title>
+ <path d="M3.22 339.78 A1.86495 1.86495 -180 0 0 1.11 338.38 A1.8709 1.8709 -180 0 0 0.38 340.85 A1.86532
+ 1.86532 -180 0 0 2.5 342.25 A1.87264 1.87264 -180 0 0 3.22 339.78 Z" class="st35"/>
+ </g>
+ <g id="shape114-505" transform="translate(3.62283,-10.4867)">
+ <title>Sheet.114</title>
+ <path d="M3.22 339.78 A1.86495 1.86495 -180 0 0 1.11 338.38 A1.8709 1.8709 -180 0 0 0.38 340.85 A1.86532
+ 1.86532 -180 0 0 2.5 342.25 A1.87264 1.87264 -180 0 0 3.22 339.78 Z" class="st35"/>
+ </g>
+ <g id="shape115-508" transform="translate(4.52404,-16.3668)">
+ <title>Sheet.115</title>
+ <path d="M1.61 341.16 a0.931952 0.931952 -180 0 0 -1.05741 -0.702645 a0.935408 0.935408 -180 0 0 -0.361118
+ 1.23585 a0.932139 0.932139 -180 0 0 1.05794 0.702645 a0.935822 0.935822 -180 0 0 0.360589 -1.23585
+ Z" class="st36"/>
+ </g>
+ <g id="shape116-511" transform="translate(4.52404,-11.6897)">
+ <title>Sheet.116</title>
+ <path d="M1.61 341.16 a0.931952 0.931952 -180 0 0 -1.05741 -0.702645 a0.935875 0.935875 -180 0 0 -0.361118
+ 1.23585 a0.932139 0.932139 -180 0 0 1.05794 0.702645 a0.935822 0.935822 -180 0 0 0.360589 -1.23585
+ Z" class="st36"/>
+ </g>
+ <g id="shape117-514" transform="translate(7.78787,-8.83469)">
+ <title>Sheet.117</title>
+ <path d="M0 341.57 L0.05 333.6 L1.83 334.57 L1.78 342.55 L0 341.57 Z" class="st37"/>
+ </g>
+ <g id="shape118-517" transform="translate(10.204,-7.4008)">
+ <title>Sheet.118</title>
+ <path d="M0 341.57 L0.05 333.6 L1.83 334.57 L1.78 342.55 L0 341.57 Z" class="st37"/>
+ </g>
+ <g id="shape119-520" transform="translate(12.6196,-5.96639)">
+ <title>Sheet.119</title>
+ <path d="M0 341.57 L0.05 333.6 L1.83 334.57 L1.78 342.55 L0 341.57 Z" class="st37"/>
+ </g>
+ <g id="shape120-523" transform="translate(15.0357,-4.53251)">
+ <title>Sheet.120</title>
+ <path d="M0 341.57 L0.05 333.6 L1.83 334.57 L1.78 342.55 L0 341.57 Z" class="st37"/>
+ </g>
+ <g id="shape121-526" transform="translate(8.24006,-10.0631)">
+ <title>Sheet.121</title>
+ <path d="M0.85 342.24 a0.388199 0.388199 0 0 1 -0.425188 0.308698 a0.638045 0.638045 0 0 1 -0.424658 -0.573447
+ L0 336.5 a0.387575 0.387575 0 0 1 0.424658 -0.308698 a0.637725 0.637725 0 0 1 0.425188 0.573447
+ L0.85 342.24 Z" class="st38"/>
+ </g>
+ <g id="shape122-529" transform="translate(10.6556,-8.62924)">
+ <title>Sheet.122</title>
+ <path d="M0.85 342.24 a0.388199 0.388199 0 0 1 -0.425188 0.308698 a0.638045 0.638045 0 0 1 -0.424658 -0.573447
+ L0 336.5 a0.387575 0.387575 0 0 1 0.424658 -0.308698 a0.637725 0.637725 0 0 1 0.425188 0.573447
+ L0.85 342.24 Z" class="st38"/>
+ </g>
+ <g id="shape123-532" transform="translate(13.0717,-7.19483)">
+ <title>Sheet.123</title>
+ <path d="M0.85 342.24 a0.388199 0.388199 0 0 1 -0.425188 0.308698 a0.638045 0.638045 0 0 1 -0.424658 -0.573447
+ L0 336.5 a0.387575 0.387575 0 0 1 0.424658 -0.308698 a0.637725 0.637725 0 0 1 0.425188 0.573447
+ L0.85 342.24 Z" class="st38"/>
+ </g>
+ <g id="shape124-535" transform="translate(15.4873,-5.76095)">
+ <title>Sheet.124</title>
+ <path d="M0.85 342.24 a0.388502 0.388502 0 0 1 -0.425717 0.308698 a0.638367 0.638367 0 0 1 -0.424129 -0.573447
+ L0 336.5 a0.387272 0.387272 0 0 1 0.424129 -0.308698 a0.638235 0.638235 0 0 1 0.425717 0.573447
+ L0.85 342.24 Z" class="st38"/>
+ </g>
+ <g id="shape125-538" transform="translate(7.78787,-9.81214)">
+ <title>Sheet.125</title>
+ <path d="M0 342.55 L0.05 334.57 L1.83 335.55 L0 342.55 Z" class="st39"/>
+ <path d="M0 342.55 L0.05 334.57 L1.83 335.55" class="st40"/>
+ </g>
+ <g id="shape126-541" transform="translate(10.204,-8.37826)">
+ <title>Sheet.126</title>
+ <path d="M0 342.55 L0.05 334.57 L1.83 335.55 L0 342.55 Z" class="st39"/>
+ <path d="M0 342.55 L0.05 334.57 L1.83 335.55" class="st40"/>
+ </g>
+ <g id="shape127-544" transform="translate(12.6196,-6.94385)">
+ <title>Sheet.127</title>
+ <path d="M0 342.55 L0.05 334.57 L1.83 335.55 L0 342.55 Z" class="st39"/>
+ <path d="M0 342.55 L0.05 334.57 L1.83 335.55" class="st40"/>
+ </g>
+ <g id="shape128-547" transform="translate(15.0357,-5.50996)">
+ <title>Sheet.128</title>
+ <path d="M0 342.55 L0.05 334.57 L1.83 335.55 L0 342.55 Z" class="st39"/>
+ <path d="M0 342.55 L0.05 334.57 L1.83 335.55" class="st40"/>
+ </g>
+ <g id="shape129-550" transform="translate(7.78787,-4.53251)">
+ <title>Sheet.129</title>
+ <path d="M9.08 334.57 L9.03 342.55 L7.25 341.57 L9.08 334.57 ZM6.66 333.14 L6.61 341.11 L4.83 340.13 L6.66
+ 333.14 ZM4.25 331.7 L4.2 339.68 L2.42 338.7 L4.25 331.7 ZM1.83 330.27 L1.78 338.24 L0 337.27
+ L1.83 330.27 Z" class="st39"/>
+ <path d="M9.08 334.57 L9.03 342.55 L7.25 341.57M6.66 333.14 L6.61 341.11 L4.83 340.13M4.25 331.7 L4.2 339.68
+ L2.42 338.7M1.83 330.27 L1.78 338.24 L0 337.27" class="st41"/>
+ </g>
+ <g id="shape130-553" transform="translate(2.22125,-11.8454)">
+ <title>Sheet.130</title>
+ <path d="M0 341.85 L0.63 341.42 L1.42 341.78 L0.03 342.55 L0 341.85 Z" class="st42"/>
+ </g>
+ <g id="shape131-556" transform="translate(17.1796,-3.17487)">
+ <title>Sheet.131</title>
+ <path d="M0 341.85 L0.63 341.42 L1.42 341.78 L0.03 342.55 L0 341.85 Z" class="st42"/>
+ </g>
+ <g id="shape132-559" transform="translate(1.46036,-10.3893)">
+ <title>Sheet.132</title>
+ <path d="M2.12 341.35 L0 342.55 L0 333.54 L2.12 332.29 L2.12 333.41 L0.79 334.15 L0.79 341.09 L2.18 340.33
+ L2.12 341.35 Z" class="st33"/>
+ </g>
+ <g id="shape133-562" transform="translate(16.4187,-1.71875)">
+ <title>Sheet.133</title>
+ <path d="M2.12 341.35 L0 342.55 L0 333.54 L2.12 332.29 L2.12 333.41 L0.79 334.15 L0.79 341.09 L2.18 340.33
+ L2.12 341.35 Z" class="st33"/>
+ </g>
+ <g id="shape134-565" transform="translate(0.467548,-10.3893)">
+ <title>Sheet.134</title>
+ <path d="M0.99 333.54 L3.11 332.29 L2.12 331.66 L0 332.91 L0 341.92 L0.99 342.55 L0.99 333.54 Z"
+ class="st43"/>
+ </g>
+ <g id="shape135-568" transform="translate(15.4259,-1.71875)">
+ <title>Sheet.135</title>
+ <path d="M0.99 333.54 L3.11 332.29 L2.12 331.66 L0 332.91 L0 341.92 L0.99 342.55 L0.99 333.54 Z"
+ class="st43"/>
+ </g>
+ <g id="shape136-571" transform="translate(0.467548,-1.71928)">
+ <title>Sheet.136</title>
+ <path d="M17.34 339.96 L16.75 340.37 L16.75 334.15 L18.07 333.41 L18.07 332.29 L17.08 331.66 L14.96 332.91
+ L14.96 341.92 L15.95 342.55 L18.07 341.35 L18.14 340.33 L17.34 339.96 ZM2.38 331.29 L1.79 331.7
+ L1.79 325.48 L3.11 324.74 L3.11 323.62 L2.12 322.99 L0 324.24 L0 333.25 L0.99 333.87 L3.11 332.68
+ L3.18 331.66 L2.38 331.29 Z" class="st44"/>
+ </g>
+ <g id="shape137-573" transform="translate(19.9526,-8.71396)">
+ <title>Sheet.137</title>
+ <path d="M1.13 341.58 a0.653986 0.653986 -180 0 0 -0.73971 -0.492434 a0.656072 0.656072 -180 0 0 -0.253101
+ 0.865731 a0.653066 0.653066 -180 0 0 0.740769 0.491375 a0.655459 0.655459 -180 0 0 0.252042
+ -0.864672 Z" class="st35"/>
+ </g>
+ <g id="shape138-576" transform="translate(19.9526,-2.35997)">
+ <title>Sheet.138</title>
+ <path d="M1.13 341.58 a0.653986 0.653986 -180 0 0 -0.73971 -0.492434 a0.656072 0.656072 -180 0 0 -0.253101
+ 0.865731 a0.653066 0.653066 -180 0 0 0.740769 0.491375 a0.655459 0.655459 -180 0 0 0.252042
+ -0.864672 Z" class="st35"/>
+ </g>
+ <g id="shape139-579" transform="translate(0,-0.415652)">
+ <title>Sheet.139</title>
+ <path d="M36.07 331.28 L36.07 321.27 L19.64 311.85 L3.16 321.13 L3.16 321.52 L0 319.68 L0 329.58 L0.47 329.86
+ L0.47 331.94 L1.46 332.57 L3.33 331.52 L15.43 338.57 L15.43 340.61 L16.42 341.24 L18.24 340.22
+ L22.24 342.55 L22.24 339.27 L36.07 331.28 Z" class="st44"/>
+ </g>
+ <g id="shape140-581" transform="translate(27.8077,-2.86477)">
+ <title>Sheet.140</title>
+ <path d="M0.29 342.55 L6.62 338.89 A1.82805 1.82805 0 0 1 6.62 336.9 L0.29 340.55 A1.82805 1.82805 -180 0
+ 0 0.29 342.55 Z" class="st45"/>
+ </g>
+ <g id="shape141-583" transform="translate(23.5035,-4.85627)">
+ <title>Sheet.141</title>
+ <path d="M4.6 342.55 L10.92 338.89 L6.32 336.24 L0 339.89 L4.6 342.55 Z" class="st46"/>
+ </g>
+ <g id="shape142-586" transform="translate(23.3588,-2.86477)">
+ <title>Sheet.142</title>
+ <path d="M0.14 339.89 L4.74 342.55 A1.82805 1.82805 0 0 1 4.74 340.55 L0.14 337.9 A3.49826 3.49826 -180 0
+ 0 0.14 339.89 Z" class="st47"/>
+ </g>
+ <g id="shape143-589" transform="translate(25.8933,-5.98478)">
+ <title>Sheet.143</title>
+ <path d="M2.87 342.55 L0 340.89" class="st48"/>
+ <path d="M0.94 340.34 L3.82 342" class="st48"/>
+ <path d="M1.88 339.8 L4.76 341.46" class="st48"/>
+ <path d="M2.82 339.26 L5.7 340.92" class="st48"/>
+ <path d="M3.76 338.71 L6.64 340.37" class="st48"/>
+ </g>
+ <g id="shape144-596" transform="translate(23.5035,-7.51159)">
+ <title>Sheet.144</title>
+ <path d="M5.13 341.17 L11.45 337.52 A11.9345 11.9345 0 0 1 6.32 338.89 L0 342.55 A11.9345 11.9345 -180 0
+ 0 5.13 341.17 Z" class="st49"/>
+ </g>
+ <g id="shape145-599" transform="translate(30.2106,-4.74563)">
+ <title>Sheet.145</title>
+ <path d="M0.98 341.98 L0 342.55" class="st48"/>
+ <path d="M1.26 341.48 L2.24 340.92" class="st48"/>
+ <path d="M2.53 340.42 L3.51 339.86" class="st48"/>
+ </g>
+ <g id="shape146-604" transform="translate(23.3588,-2.86477)">
+ <title>Sheet.146</title>
+ <path d="M0.14 339.89 L4.74 342.55 L11.07 338.89 A1.82805 1.82805 0 0 1 11.07 336.9 L7.85 335.04 L11.6 332.87
+ A11.9345 11.9345 0 0 1 6.47 334.25 L0.14 337.9 A3.49826 3.49826 -180 0 0 0.14 339.89"
+ class="st50"/>
+ </g>
+ </g>
+ <g id="shape147-607" transform="translate(427.321,214.49) rotate(90)">
+ <title>Cloud</title>
+ <path d="M5.37 311.54 A8.61618 10.0654 0 0 1 9.5 292.2 A17.4727 20.4114 0 0 1 34.86 275.89 A20.0634 23.4379 0
+ 0 1 56.58 272.26 A12.5816 14.6977 0 0 1 75.21 271.05 A14.3244 16.7336 0 0 1 97.98 277.09 A10.2423
+ 11.9646 0 0 1 106.25 294.02 A12.6864 14.8197 0 0 1 95.9 318.19 A16.0049 18.6962 0 0 1 73.14 330.27
+ A18.8712 22.0444 0 0 1 42.1 335.11 A23.9217 27.9441 0 0 1 15.2 330.27 A9.43759 11.0249 0 0 1 5.37
+ 311.54 Z" class="st39"/>
+ <path d="M5.37 311.54 A8.61618 10.0654 0 0 1 9.5 292.2 A17.4727 20.4114 0 0 1 34.86 275.89 A20.0634 23.4379 0
+ 0 1 56.58 272.26 A12.5816 14.6977 0 0 1 75.21 271.05 A14.3244 16.7336 0 0 1 97.98 277.09 A10.2423
+ 11.9646 0 0 1 106.25 294.02 A12.6864 14.8197 0 0 1 95.9 318.19 A16.0049 18.6962 0 0 1 73.14 330.27
+ A18.8712 22.0444 0 0 1 42.1 335.11 A23.9217 27.9441 0 0 1 15.2 330.27 A9.43759 11.0249 0 0 1 5.37
+ 311.54" class="st51"/>
+ <path d="M11.05 312.14 A8.59237 10.0375 0 0 1 5.37 311.54" class="st51"/>
+ <path d="M40.54 332.09 A8.62978 10.0812 -180 0 0 42.1 335.11" class="st51"/>
+ <path d="M73.92 326.65 A6.96633 8.13801 0 0 1 73.14 330.27" class="st51"/>
+ <path d="M89.7 308.52 A7.30994 8.5394 0 0 1 95.9 318.19" class="st51"/>
+ <path d="M103.15 297.64 A6.67364 7.79609 -180 0 0 106.25 294.02" class="st51"/>
+ <path d="M37.96 278.3 A10.2914 12.0219 -180 0 0 34.86 275.89" class="st51"/>
+ </g>
+ <g id="shape148-616" transform="translate(110.222,-64.9346)">
+ <title>Triangle</title>
+ <desc>Set Summary</desc>
+ <g id="shadow148-617" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <path d="M31.4 342.55 L14.67 324.26 L0 342.55 L31.4 342.55 Z" class="st7"/>
+ </g>
+ <path d="M31.4 342.55 L14.67 324.26 L0 342.55 L31.4 342.55 Z" class="st8"/>
+ <text x="11.82" y="334.65" class="st16">Set <tspan x="4.11" dy="1.2em" class="st4">Summary</tspan></text> </g>
+ <g id="shape149-623" transform="translate(292.639,20.8827) rotate(45)">
+ <title>Sheet.149</title>
+ <path d="M0 342.55 L14.71 342.55" class="st12"/>
+ </g>
+ <g id="shape150-628" transform="translate(43.2897,-54.1122)">
+ <title>Sheet.150</title>
+ <path d="M0 342.55 L10.07 342.55" class="st12"/>
+ </g>
+ <g id="shape151-633" transform="translate(-112.261,8.34531) rotate(-28.1394)">
+ <title>Sheet.151</title>
+ <path d="M0 342.55 L18 342.55" class="st12"/>
+ </g>
+ <g id="shape152-638">
+ <title>Sheet.152</title>
+ <desc>Clients</desc>
+ <rect x="0" y="331.723" width="64.9346" height="10.8224" class="st9"/>
+ <text x="21.5" y="339.53" class="st14">Clients</text> </g>
+ <g id="shape153-641" transform="translate(83.578,-9.58078)">
+ <title>Sheet.153</title>
+ <desc>Distributed Cache</desc>
+ <rect x="0" y="331.723" width="84.1355" height="10.8224" class="st9"/>
+ <text x="13.1" y="339.53" class="st14">Distributed Cache</text> </g>
+ <g id="shape154-644" transform="translate(181.983,-18.6146)">
+ <title>Sheet.154</title>
+ <desc>Web Servers</desc>
+ <rect x="0" y="331.723" width="64.9346" height="10.8224" class="st9"/>
+ <text x="11.93" y="339.53" class="st14">Web Servers</text> </g>
+ <g id="shape155-647" transform="translate(96.6068,630.978) rotate(180)">
+ <title>Simple Arrow</title>
+ <g id="shadow155-648" transform="matrix(1,0,0,1,-0.345598,-1.97279)" class="st1">
+ <path d="M0 342.55 L12 330.55 L12 336.55 L16.23 336.55 L16.23 342.55 L16.23 348.54 L12 348.54 L12 354.54
+ L0 342.55 Z" class="st52"/>
+ </g>
+ <path d="M0 342.55 L12 330.55 L12 336.55 L16.23 336.55 L16.23 342.55 L16.23 348.54 L12 348.54 L12 354.54 L0 342.55
+ Z" class="st53"/>
+ </g>
+ <g id="shape156-652" transform="translate(173.159,625.567) rotate(180)">
+ <title>Simple Arrow.153</title>
+ <g id="shadow156-653" transform="matrix(1,0,0,1,-0.345598,-1.97279)" class="st1">
+ <path d="M0 342.55 L12 330.55 L12 336.55 L16.23 336.55 L16.23 342.55 L16.23 348.54 L12 348.54 L12 354.54
+ L0 342.55 Z" class="st52"/>
+ </g>
+ <path d="M0 342.55 L12 330.55 L12 336.55 L16.23 336.55 L16.23 342.55 L16.23 348.54 L12 348.54 L12 354.54 L0 342.55
+ Z" class="st53"/>
+ </g>
+ </g>
+ <g id="shape157-657" transform="translate(0,-149.475)">
+ <title>Rectangle</title>
+ <g id="shadow157-658" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="193.823" width="271.116" height="148.722" class="st2"/>
+ </g>
+ <rect x="0" y="193.823" width="271.116" height="148.722" class="st54"/>
+ </g>
+ <g id="shape158-662" transform="translate(271.116,-149.475)">
+ <title>Rectangle.158</title>
+ <g id="shadow158-663" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="193.823" width="202.104" height="148.722" class="st2"/>
+ </g>
+ <rect x="0" y="193.823" width="202.104" height="148.722" class="st54"/>
+ </g>
+ <g id="shape159-667">
+ <title>Rectangle.159</title>
+ <g id="shadow159-668" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="193.823" width="271.116" height="148.722" class="st2"/>
+ </g>
+ <rect x="0" y="193.823" width="271.116" height="148.722" class="st54"/>
+ </g>
+ <g id="shape160-672" transform="translate(271.116,0)">
+ <title>Rectangle.160</title>
+ <g id="shadow160-673" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="193.823" width="202.104" height="148.722" class="st2"/>
+ </g>
+ <rect x="0" y="193.823" width="202.104" height="148.722" class="st54"/>
+ </g>
+ <g id="shape161-677" transform="translate(83.578,-151.241)">
+ <title>Sheet.161</title>
+ <desc>(a) Distributed Web Cache</desc>
+ <g id="shadow161-678" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="325.066" width="108.709" height="17.4792" class="st7"/>
+ </g>
+ <rect x="0" y="325.066" width="108.709" height="17.4792" class="st8"/>
+ <text x="4" y="336.81" class="st55">(a) Distributed Web Cache</text> </g>
+ <g id="shape162-683" transform="translate(319.513,-151.241)">
+ <title>Sheet.162</title>
+ <desc>(b) Detecting Routing Loops</desc>
+ <g id="shadow162-684" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="325.066" width="108.709" height="17.4792" class="st7"/>
+ </g>
+ <rect x="0" y="325.066" width="108.709" height="17.4792" class="st8"/>
+ <text x="4" y="336.81" class="st55">(b) Detecting Routing Loops</text> </g>
+ <g id="shape163-689" transform="translate(77.5283,-3.35965)">
+ <title>Sheet.163</title>
+ <desc>(c) In-order Workload Scheduler</desc>
+ <g id="shadow163-690" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="325.066" width="127.042" height="17.4792" class="st7"/>
+ </g>
+ <rect x="0" y="325.066" width="127.042" height="17.4792" class="st8"/>
+ <text x="4" y="336.81" class="st55">(c) In-order Workload Scheduler</text> </g>
+ <g id="shape164-695" transform="translate(307.414,-3.35965)">
+ <title>Sheet.164</title>
+ <desc>(d) Database Semi-join Operations</desc>
+ <g id="shadow164-696" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="325.066" width="132.451" height="17.4792" class="st7"/>
+ </g>
+ <rect x="0" y="325.066" width="132.451" height="17.4792" class="st8"/>
+ <text x="4" y="336.81" class="st55">(d) Database Semi-join Operations</text> </g>
+ </g>
+ </g>
+</svg>
new file mode 100644
@@ -0,0 +1,36 @@
+<?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 memship_i2.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="4.38194in" height="1.25694in"
+ viewBox="0 0 315.5 90.5" xml:space="preserve" color-interpolation-filters="sRGB" class="st6">
+ <v:documentProperties v:langID="1033" v:viewMarkup="false"/>
+
+ <style type="text/css">
+ <![CDATA[
+ .st1 {fill:none;stroke:none;stroke-width:0.25}
+ .st2 {fill:#5b9bd5;font-family:Calibri;font-size:1.16666em}
+ .st3 {baseline-shift:32.4943%;font-size:0.649886em}
+ .st4 {font-size:1em}
+ .st5 {font-family:Cambria Math;font-size:1em}
+ .st6 {fill:none;fill-rule:evenodd;font-size:12px;overflow:visible;stroke-linecap:square;stroke-miterlimit:3}
+ ]]>
+ </style>
+
+ <g v:mID="0" v:index="1" v:groupContext="foregroundPage">
+ <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(0.25,-0.25)">
+ <title>Sheet.3</title>
+ <desc>False Positive Probability = (1-(1-1/m)kn)k ≃ (1-ekn/m)k</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="157.5" cy="45.5" width="315" height="90"/>
+ <rect x="0" y="0.5" width="315" height="90" class="st1"/>
+ <text x="8.28" y="49.82" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>False Positive Probability = (1-(1-1/m)<tspan
+ dy="-0.234em" class="st3" v:baseFontSize="14">kn</tspan><tspan dy="0.152em" class="st4">)</tspan><tspan
+ dy="-0.234em" class="st3" v:baseFontSize="14">k</tspan><tspan dy="0.152em" class="st4"> </tspan><tspan
+ class="st5">≃</tspan> (1-e<tspan dy="-0.234em" class="st3" v:baseFontSize="14">kn</tspan><tspan class="st3"
+ v:baseFontSize="14">/</tspan><tspan class="st3" v:baseFontSize="14">m</tspan><tspan dy="0.152em"
+ class="st4">)</tspan><tspan dy="-0.234em" class="st3" v:baseFontSize="14">k</tspan></text> </g>
+ </g>
+</svg>
new file mode 100644
@@ -0,0 +1,148 @@
+<?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 memship_i3.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"
+ width="4.71875in" height="2.84375in" viewBox="0 0 339.75 204.75" xml:space="preserve" color-interpolation-filters="sRGB"
+ class="st14">
+ <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 {marker-end:url(#mrkr5-32);stroke:#5b9bd5;stroke-linecap:round;stroke-linejoin:round;stroke-width:1}
+ .st5 {fill:#5b9bd5;fill-opacity:1;stroke:#5b9bd5;stroke-opacity:1;stroke-width:0.28409090909091}
+ .st6 {fill:#feffff;font-family:Calibri;font-size:0.833336em}
+ .st7 {font-size:1em}
+ .st8 {fill:#deebf6;stroke:#c7c8c8;stroke-width:0.25}
+ .st9 {fill:#000000;font-family:Calibri;font-size:0.833336em}
+ .st10 {marker-end:url(#mrkr5-84);stroke:#ff0000;stroke-linecap:round;stroke-linejoin:round;stroke-width:1}
+ .st11 {fill:#ff0000;fill-opacity:1;stroke:#ff0000;stroke-opacity:1;stroke-width:0.28409090909091}
+ .st12 {fill:none;stroke:none;stroke-width:0.25}
+ .st13 {fill:#ff0000;font-family:Calibri;font-size:1.00001em}
+ .st14 {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-32" class="st5" refX="-6.16" orient="auto" markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend5" transform="scale(-3.52,-3.52) "/>
+ </marker>
+ <marker id="mrkr5-84" class="st11" refX="-5.8" orient="auto" markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend5" transform="scale(-3.52,-3.52) "/>
+ </marker>
+ </defs>
+ <defs id="Filters">
+ <filter id="filter_2">
+ <feGaussianBlur stdDeviation="2"/>
+ </filter>
+ </defs>
+ <g>
+ <title>Page-1</title>
+ <g id="group174-1" transform="translate(3.0294,-5.3478)">
+ <title>Sheet.174</title>
+ <g id="shape155-2" transform="translate(99,-99)">
+ <title>Circle</title>
+ <g id="shadow155-3" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <path d="M0 186.75 A18 18 0 0 1 36 186.75 A18 18 0 1 1 0 186.75 Z" class="st2"/>
+ </g>
+ <path d="M0 186.75 A18 18 0 0 1 36 186.75 A18 18 0 1 1 0 186.75 Z" class="st3"/>
+ </g>
+ <g id="shape156-7" transform="translate(207,-108)">
+ <title>Circle.156</title>
+ <g id="shadow156-8" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <path d="M0 186.75 A18 18 0 0 1 36 186.75 A18 18 0 1 1 0 186.75 Z" class="st2"/>
+ </g>
+ <path d="M0 186.75 A18 18 0 0 1 36 186.75 A18 18 0 1 1 0 186.75 Z" class="st3"/>
+ </g>
+ <g id="shape157-12" transform="translate(153,-162)">
+ <title>Circle.157</title>
+ <g id="shadow157-13" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <path d="M0 186.75 A18 18 0 0 1 36 186.75 A18 18 0 1 1 0 186.75 Z" class="st2"/>
+ </g>
+ <path d="M0 186.75 A18 18 0 0 1 36 186.75 A18 18 0 1 1 0 186.75 Z" class="st3"/>
+ </g>
+ <g id="shape158-17" transform="translate(297,-99)">
+ <title>Circle.158</title>
+ <g id="shadow158-18" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <path d="M0 186.75 A18 18 0 0 1 36 186.75 A18 18 0 1 1 0 186.75 Z" class="st2"/>
+ </g>
+ <path d="M0 186.75 A18 18 0 0 1 36 186.75 A18 18 0 1 1 0 186.75 Z" class="st3"/>
+ </g>
+ <g id="shape159-22" transform="translate(180,-36)">
+ <title>Circle.159</title>
+ <g id="shadow159-23" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <path d="M0 186.75 A18 18 0 0 1 36 186.75 A18 18 0 1 1 0 186.75 Z" class="st2"/>
+ </g>
+ <path d="M0 186.75 A18 18 0 0 1 36 186.75 A18 18 0 1 1 0 186.75 Z" class="st3"/>
+ </g>
+ <g id="shape160-27" transform="translate(109.604,-115.419) rotate(-7.12502)">
+ <title>Sheet.160</title>
+ <path d="M0 204.75 L66.4 204.75" class="st4"/>
+ </g>
+ <g id="shape161-33" transform="translate(276.661,-123.214) rotate(9.46232)">
+ <title>Sheet.161</title>
+ <path d="M0 204.75 L48.58 204.75" class="st4"/>
+ </g>
+ <g id="shape162-38" transform="translate(246.135,262.572) rotate(-160.346)">
+ <title>Sheet.162</title>
+ <path d="M0 204.75 L127.63 204.75" class="st4"/>
+ </g>
+ <g id="shape163-43" transform="translate(284.391,198.775) rotate(141.977)">
+ <title>Sheet.163</title>
+ <path d="M0 204.75 L46.23 204.75" class="st4"/>
+ </g>
+ <g id="shape164-48" transform="translate(70.6118,307.655) rotate(-145.945)">
+ <title>Sheet.164</title>
+ <path d="M0 204.75 L60.88 204.75" class="st4"/>
+ </g>
+ <g id="shape167-53" transform="translate(72,0)">
+ <title>Rectangle.167</title>
+ <desc>BF of IDs</desc>
+ <g id="shadow167-54" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="177.75" width="36" height="27" class="st2"/>
+ </g>
+ <rect x="0" y="177.75" width="36" height="27" class="st3"/>
+ <text x="7.69" y="188.25" class="st6">BF of <tspan x="11.71" dy="1.2em" class="st7">IDs</tspan></text> </g>
+ <g id="shape168-60" transform="translate(108,0)">
+ <title>Rectangle.168</title>
+ <desc>Packet</desc>
+ <g id="shadow168-61" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="177.75" width="90" height="27" class="st2"/>
+ </g>
+ <rect x="0" y="177.75" width="90" height="27" class="st8"/>
+ <text x="31.47" y="194.25" class="st9">Packet</text> </g>
+ <g id="shape169-66" transform="translate(0,-63)">
+ <title>Rectangle.169</title>
+ <desc>BF of IDs</desc>
+ <g id="shadow169-67" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="177.75" width="36" height="27" class="st2"/>
+ </g>
+ <rect x="0" y="177.75" width="36" height="27" class="st3"/>
+ <text x="7.69" y="188.25" class="st6">BF of <tspan x="11.71" dy="1.2em" class="st7">IDs</tspan></text> </g>
+ <g id="shape170-73" transform="translate(36,-63)">
+ <title>Rectangle.170</title>
+ <desc>Packet</desc>
+ <g id="shadow170-74" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="177.75" width="90" height="27" class="st2"/>
+ </g>
+ <rect x="0" y="177.75" width="90" height="27" class="st8"/>
+ <text x="31.47" y="194.25" class="st9">Packet</text> </g>
+ <g id="shape171-79" transform="translate(240.248,331.493) rotate(161.565)">
+ <title>Sheet.171</title>
+ <path d="M-0 190.52 A81.3416 36.0611 -153.48 0 0 82.31 195.86 L82.49 195.55" class="st10"/>
+ </g>
+ <g id="shape172-85" transform="translate(156.426,260.029) rotate(161.565)">
+ <title>Sheet.172</title>
+ <path d="M-0 181.6 A88.1422 54.1439 -124.1 0 0 82.68 187.13 L82.83 186.81" class="st10"/>
+ </g>
+ <g id="shape173-90" transform="translate(18,-121.5)">
+ <title>Sheet.173</title>
+ <desc>Encode ID</desc>
+ <rect x="0" y="177.75" width="63" height="27" class="st12"/>
+ <text x="7.02" y="194.85" class="st13">Encode ID</text> </g>
+ </g>
+ </g>
+</svg>
new file mode 100644
@@ -0,0 +1,428 @@
+<?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 memship_i4.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="7.4375in" height="2.92253in"
+ viewBox="0 0 535.5 210.422" xml:space="preserve" color-interpolation-filters="sRGB" class="st18">
+ <v:documentProperties v:langID="1033" v:viewMarkup="false"/>
+
+ <style type="text/css">
+ <![CDATA[
+ .st1 {fill:none;stroke:#ff0000;stroke-width:0.25}
+ .st2 {fill:#5b9bd5;font-family:Calibri;font-size:1.00001em}
+ .st3 {marker-end:url(#mrkr5-10);stroke:#ff0000;stroke-linecap:round;stroke-linejoin:round;stroke-width:2.25}
+ .st4 {fill:#ff0000;fill-opacity:1;stroke:#ff0000;stroke-opacity:1;stroke-width:0.47169811320755}
+ .st5 {visibility:visible}
+ .st6 {fill:#5b9bd5;fill-opacity:0.22;filter:url(#filter_2);stroke:#5b9bd5;stroke-opacity:0.22}
+ .st7 {fill:#5b9bd5;stroke:#c7c8c8;stroke-width:0.25}
+ .st8 {fill:none;stroke:none;stroke-width:0.25}
+ .st9 {fill:#5b9bd5;font-family:Calibri;font-size:1.16666em}
+ .st10 {stroke:#5b9bd5;stroke-dasharray:1.5,3;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5}
+ .st11 {fill:#5b9bd5;fill-opacity:0.25;filter:url(#filter_2);stroke:#5b9bd5;stroke-opacity:0.25}
+ .st12 {fill:#4f87bb;stroke:#40709c;stroke-width:0.75}
+ .st13 {fill:#ffffff;font-family:Calibri;font-size:1.00001em;font-weight:bold}
+ .st14 {fill:#000000;font-family:Calibri;font-size:1.00001em}
+ .st15 {font-size:1em}
+ .st16 {marker-end:url(#mrkr5-187);stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:1}
+ .st17 {fill:#000000;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:0.28409090909091}
+ .st18 {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-10" class="st4" v:arrowType="5" v:arrowSize="2" v:setback="3.71" refX="-3.71" orient="auto"
+ markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend5" transform="scale(-2.12,-2.12) "/>
+ </marker>
+ <marker id="mrkr5-187" class="st17" 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>
+ </defs>
+ <defs id="Filters">
+ <filter id="filter_2">
+ <feGaussianBlur stdDeviation="2"/>
+ </filter>
+ </defs>
+ <g v:mID="0" v:index="1" v:groupContext="foregroundPage">
+ <title>Page-1</title>
+ <v:pageProperties v:drawingScale="1" v:pageScale="1" v:drawingUnits="0" v:shadowOffsetX="9" v:shadowOffsetY="-9"/>
+ <g id="group47-1" transform="translate(3.0294,-0.25)" v:mID="47" v:groupContext="group">
+ <title>Sheet.47</title>
+ <g id="shape1-2" v:mID="1" v:groupContext="shape" transform="translate(177.75,-191.922)">
+ <title>Sheet.1</title>
+ <desc>Element</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="54" cy="201.422" width="108" height="18"/>
+ <rect x="0" y="192.422" width="108" height="18" class="st1"/>
+ <text x="33.77" y="205.02" class="st2" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Element</text> </g>
+ <g id="shape2-5" v:mID="2" v:groupContext="shape" transform="translate(442.172,18.5) rotate(90)">
+ <title>Sheet.2</title>
+ <path d="M0 210.42 L18.65 210.42" class="st3"/>
+ </g>
+ <g id="shape3-11" v:mID="3" v:groupContext="shape" transform="translate(0,-67.0469)">
+ <title>Rectangle.54</title>
+ <v:userDefs>
+ <v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
+ </v:userDefs>
+ <g id="shadow3-12" 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="st5">
+ <rect x="0" y="196.922" width="27" height="13.5" class="st6"/>
+ </g>
+ <rect x="0" y="196.922" width="27" height="13.5" class="st7"/>
+ </g>
+ <g id="shape4-16" v:mID="4" v:groupContext="shape" transform="translate(27,-67.0469)">
+ <title>Rectangle.55</title>
+ <v:userDefs>
+ <v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
+ </v:userDefs>
+ <g id="shadow4-17" 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="st5">
+ <rect x="0" y="196.922" width="27" height="13.5" class="st6"/>
+ </g>
+ <rect x="0" y="196.922" width="27" height="13.5" class="st7"/>
+ </g>
+ <g id="shape5-21" v:mID="5" v:groupContext="shape" transform="translate(54,-67.0469)">
+ <title>Rectangle.56</title>
+ <v:userDefs>
+ <v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
+ </v:userDefs>
+ <g id="shadow5-22" 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="st5">
+ <rect x="0" y="196.922" width="27" height="13.5" class="st6"/>
+ </g>
+ <rect x="0" y="196.922" width="27" height="13.5" class="st7"/>
+ </g>
+ <g id="shape6-26" v:mID="6" v:groupContext="shape" transform="translate(0,-53.5469)">
+ <title>Rectangle.57</title>
+ <v:userDefs>
+ <v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
+ </v:userDefs>
+ <g id="shadow6-27" 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="st5">
+ <rect x="0" y="196.922" width="27" height="13.5" class="st6"/>
+ </g>
+ <rect x="0" y="196.922" width="27" height="13.5" class="st7"/>
+ </g>
+ <g id="shape7-31" v:mID="7" v:groupContext="shape" transform="translate(27,-53.5469)">
+ <title>Rectangle.58</title>
+ <v:userDefs>
+ <v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
+ </v:userDefs>
+ <g id="shadow7-32" 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="st5">
+ <rect x="0" y="196.922" width="27" height="13.5" class="st6"/>
+ </g>
+ <rect x="0" y="196.922" width="27" height="13.5" class="st7"/>
+ </g>
+ <g id="shape8-36" v:mID="8" v:groupContext="shape" transform="translate(54,-53.5469)">
+ <title>Rectangle.59</title>
+ <v:userDefs>
+ <v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
+ </v:userDefs>
+ <g id="shadow8-37" 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="st5">
+ <rect x="0" y="196.922" width="27" height="13.5" class="st6"/>
+ </g>
+ <rect x="0" y="196.922" width="27" height="13.5" class="st7"/>
+ </g>
+ <g id="shape9-41" v:mID="9" v:groupContext="shape" transform="translate(5.625,-72.6719)">
+ <title>Sheet.9</title>
+ <desc>BF-1</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="36" cy="196.922" width="72" height="27"/>
+ <rect x="0" y="183.422" width="72" height="27" class="st8"/>
+ <text x="23.29" y="201.12" class="st9" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>BF-1</text> </g>
+ <g id="shape10-44" v:mID="10" v:groupContext="shape" transform="translate(128.25,-65.0781)">
+ <title>Rectangle.74</title>
+ <v:userDefs>
+ <v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
+ </v:userDefs>
+ <g id="shadow10-45" 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="st5">
+ <rect x="0" y="196.922" width="27" height="13.5" class="st6"/>
+ </g>
+ <rect x="0" y="196.922" width="27" height="13.5" class="st7"/>
+ </g>
+ <g id="shape11-49" v:mID="11" v:groupContext="shape" transform="translate(155.25,-65.0781)">
+ <title>Rectangle.75</title>
+ <v:userDefs>
+ <v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
+ </v:userDefs>
+ <g id="shadow11-50" 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="st5">
+ <rect x="0" y="196.922" width="27" height="13.5" class="st6"/>
+ </g>
+ <rect x="0" y="196.922" width="27" height="13.5" class="st7"/>
+ </g>
+ <g id="shape12-54" v:mID="12" v:groupContext="shape" transform="translate(182.25,-65.0781)">
+ <title>Rectangle.76</title>
+ <v:userDefs>
+ <v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
+ </v:userDefs>
+ <g id="shadow12-55" 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="st5">
+ <rect x="0" y="196.922" width="27" height="13.5" class="st6"/>
+ </g>
+ <rect x="0" y="196.922" width="27" height="13.5" class="st7"/>
+ </g>
+ <g id="shape13-59" v:mID="13" v:groupContext="shape" transform="translate(128.25,-51.5781)">
+ <title>Rectangle.77</title>
+ <v:userDefs>
+ <v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
+ </v:userDefs>
+ <g id="shadow13-60" 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="st5">
+ <rect x="0" y="196.922" width="27" height="13.5" class="st6"/>
+ </g>
+ <rect x="0" y="196.922" width="27" height="13.5" class="st7"/>
+ </g>
+ <g id="shape14-64" v:mID="14" v:groupContext="shape" transform="translate(155.25,-51.5781)">
+ <title>Rectangle.78</title>
+ <v:userDefs>
+ <v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
+ </v:userDefs>
+ <g id="shadow14-65" 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="st5">
+ <rect x="0" y="196.922" width="27" height="13.5" class="st6"/>
+ </g>
+ <rect x="0" y="196.922" width="27" height="13.5" class="st7"/>
+ </g>
+ <g id="shape15-69" v:mID="15" v:groupContext="shape" transform="translate(182.25,-51.5781)">
+ <title>Rectangle.79</title>
+ <v:userDefs>
+ <v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
+ </v:userDefs>
+ <g id="shadow15-70" 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="st5">
+ <rect x="0" y="196.922" width="27" height="13.5" class="st6"/>
+ </g>
+ <rect x="0" y="196.922" width="27" height="13.5" class="st7"/>
+ </g>
+ <g id="shape16-74" v:mID="16" v:groupContext="shape" transform="translate(301.5,-65.0781)">
+ <title>Rectangle.81</title>
+ <v:userDefs>
+ <v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
+ </v:userDefs>
+ <g id="shadow16-75" 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="st5">
+ <rect x="0" y="196.922" width="27" height="13.5" class="st6"/>
+ </g>
+ <rect x="0" y="196.922" width="27" height="13.5" class="st7"/>
+ </g>
+ <g id="shape17-79" v:mID="17" v:groupContext="shape" transform="translate(328.5,-65.0781)">
+ <title>Rectangle.82</title>
+ <v:userDefs>
+ <v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
+ </v:userDefs>
+ <g id="shadow17-80" 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="st5">
+ <rect x="0" y="196.922" width="27" height="13.5" class="st6"/>
+ </g>
+ <rect x="0" y="196.922" width="27" height="13.5" class="st7"/>
+ </g>
+ <g id="shape18-84" v:mID="18" v:groupContext="shape" transform="translate(355.5,-65.0781)">
+ <title>Rectangle.83</title>
+ <v:userDefs>
+ <v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
+ </v:userDefs>
+ <g id="shadow18-85" 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="st5">
+ <rect x="0" y="196.922" width="27" height="13.5" class="st6"/>
+ </g>
+ <rect x="0" y="196.922" width="27" height="13.5" class="st7"/>
+ </g>
+ <g id="shape19-89" v:mID="19" v:groupContext="shape" transform="translate(301.5,-51.5781)">
+ <title>Rectangle.84</title>
+ <v:userDefs>
+ <v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
+ </v:userDefs>
+ <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="st5">
+ <rect x="0" y="196.922" width="27" height="13.5" class="st6"/>
+ </g>
+ <rect x="0" y="196.922" width="27" height="13.5" class="st7"/>
+ </g>
+ <g id="shape20-94" v:mID="20" v:groupContext="shape" transform="translate(328.5,-51.5781)">
+ <title>Rectangle.85</title>
+ <v:userDefs>
+ <v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
+ </v:userDefs>
+ <g id="shadow20-95" 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="st5">
+ <rect x="0" y="196.922" width="27" height="13.5" class="st6"/>
+ </g>
+ <rect x="0" y="196.922" width="27" height="13.5" class="st7"/>
+ </g>
+ <g id="shape21-99" v:mID="21" v:groupContext="shape" transform="translate(355.5,-51.5781)">
+ <title>Rectangle.86</title>
+ <v:userDefs>
+ <v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
+ </v:userDefs>
+ <g id="shadow21-100" 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="st5">
+ <rect x="0" y="196.922" width="27" height="13.5" class="st6"/>
+ </g>
+ <rect x="0" y="196.922" width="27" height="13.5" class="st7"/>
+ </g>
+ <g id="shape22-104" v:mID="22" v:groupContext="shape" transform="translate(447.75,-65.6406)">
+ <title>Rectangle.88</title>
+ <v:userDefs>
+ <v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
+ </v:userDefs>
+ <g id="shadow22-105" 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="st5">
+ <rect x="0" y="196.922" width="27" height="13.5" class="st6"/>
+ </g>
+ <rect x="0" y="196.922" width="27" height="13.5" class="st7"/>
+ </g>
+ <g id="shape23-109" v:mID="23" v:groupContext="shape" transform="translate(474.75,-65.6406)">
+ <title>Rectangle.89</title>
+ <v:userDefs>
+ <v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
+ </v:userDefs>
+ <g id="shadow23-110" 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="st5">
+ <rect x="0" y="196.922" width="27" height="13.5" class="st6"/>
+ </g>
+ <rect x="0" y="196.922" width="27" height="13.5" class="st7"/>
+ </g>
+ <g id="shape24-114" v:mID="24" v:groupContext="shape" transform="translate(501.75,-65.6406)">
+ <title>Rectangle.90</title>
+ <v:userDefs>
+ <v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
+ </v:userDefs>
+ <g id="shadow24-115" 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="st5">
+ <rect x="0" y="196.922" width="27" height="13.5" class="st6"/>
+ </g>
+ <rect x="0" y="196.922" width="27" height="13.5" class="st7"/>
+ </g>
+ <g id="shape25-119" v:mID="25" v:groupContext="shape" transform="translate(447.75,-52.1406)">
+ <title>Rectangle.91</title>
+ <v:userDefs>
+ <v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
+ </v:userDefs>
+ <g id="shadow25-120" 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="st5">
+ <rect x="0" y="196.922" width="27" height="13.5" class="st6"/>
+ </g>
+ <rect x="0" y="196.922" width="27" height="13.5" class="st7"/>
+ </g>
+ <g id="shape26-124" v:mID="26" v:groupContext="shape" transform="translate(474.75,-52.1406)">
+ <title>Rectangle.92</title>
+ <v:userDefs>
+ <v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
+ </v:userDefs>
+ <g id="shadow26-125" 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="st5">
+ <rect x="0" y="196.922" width="27" height="13.5" class="st6"/>
+ </g>
+ <rect x="0" y="196.922" width="27" height="13.5" class="st7"/>
+ </g>
+ <g id="shape27-129" v:mID="27" v:groupContext="shape" transform="translate(501.75,-52.1406)">
+ <title>Rectangle.93</title>
+ <v:userDefs>
+ <v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
+ </v:userDefs>
+ <g id="shadow27-130" 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="st5">
+ <rect x="0" y="196.922" width="27" height="13.5" class="st6"/>
+ </g>
+ <rect x="0" y="196.922" width="27" height="13.5" class="st7"/>
+ </g>
+ <g id="shape28-134" v:mID="28" v:groupContext="shape" transform="translate(213.75,-63.9531)">
+ <title>Sheet.28</title>
+ <path d="M0 210.42 L83.25 210.42" class="st10"/>
+ </g>
+ <g id="shape29-137" v:mID="29" v:groupContext="shape" transform="translate(387,-63.9531)">
+ <title>Sheet.29</title>
+ <path d="M0 210.42 L54 210.42" class="st10"/>
+ </g>
+ <g id="group31-140" transform="translate(184.5,-113.172)" v:mID="31" v:groupContext="group">
+ <title>Sheet.31</title>
+ <g id="shape32-141" v:mID="32" v:groupContext="shape" transform="translate(210.422,158.672) rotate(90)">
+ <title>Block Arrow</title>
+ <v:userDefs>
+ <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/>
+ </v:userDefs>
+ <g id="shadow32-142" v:groupContext="shadow" v:shadowOffsetX="0.345598" v:shadowOffsetY="-1.97279"
+ v:shadowType="1" transform="matrix(1,0,0,1,1.97279,-0.345598)" class="st5">
+ <path d="M0 210.42 L25.87 210.42 L51.75 163.17 L25.87 115.92 L0 115.92 L0 210.42 Z" class="st11"/>
+ </g>
+ <path d="M0 210.42 L25.87 210.42 L51.75 163.17 L25.87 115.92 L0 115.92 L0 210.42 Z" class="st12"/>
+ </g>
+ <g id="shape33-146" v:mID="33" v:groupContext="shape" transform="translate(2.25,-24.3529)">
+ <title>Sheet.33</title>
+ <desc>h1, h2 .. hk</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="45" cy="201.29" width="90" height="18.2647"/>
+ <rect x="0" y="192.157" width="90" height="18.2647" class="st8"/>
+ <text x="17.56" y="204.89" class="st13" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>h1, h2 .. hk</text> </g>
+ </g>
+ <g id="shape34-149" v:mID="34" v:groupContext="shape" transform="translate(300.24,259.242) rotate(152.323)">
+ <title>Sheet.34</title>
+ <path d="M0 210.42 L128.85 210.42" class="st3"/>
+ </g>
+ <g id="shape35-154" v:mID="35" v:groupContext="shape" transform="translate(418.903,108.413) rotate(99.7172)">
+ <title>Sheet.35</title>
+ <path d="M0 210.42 L58.31 210.42" class="st3"/>
+ </g>
+ <g id="shape36-159" v:mID="36" v:groupContext="shape" transform="translate(397.416,-68.4157) rotate(45)">
+ <title>Sheet.36</title>
+ <path d="M0 210.42 L79.16 210.42" class="st3"/>
+ </g>
+ <g id="shape37-164" v:mID="37" v:groupContext="shape" transform="translate(316.517,-127.658) rotate(15.6155)">
+ <title>Sheet.37</title>
+ <path d="M0 210.42 L200.75 210.42" class="st3"/>
+ </g>
+ <g id="shape38-169" v:mID="38" v:groupContext="shape" transform="translate(132.75,-75.2588)">
+ <title>Sheet.38</title>
+ <desc>BF-2</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="36" cy="196.922" width="72" height="27"/>
+ <rect x="0" y="183.422" width="72" height="27" class="st8"/>
+ <text x="23.29" y="201.12" class="st9" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>BF-2</text> </g>
+ <g id="shape39-172" v:mID="39" v:groupContext="shape" transform="translate(303.75,-70.7588)">
+ <title>Sheet.39</title>
+ <desc>BF-X</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="36" cy="196.922" width="72" height="27"/>
+ <rect x="0" y="183.422" width="72" height="27" class="st8"/>
+ <text x="23.2" y="201.12" class="st9" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>BF-X</text> </g>
+ <g id="shape40-175" v:mID="40" v:groupContext="shape" transform="translate(447.75,-75.2588)">
+ <title>Sheet.40</title>
+ <desc>BF-L</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="36" cy="196.922" width="72" height="27"/>
+ <rect x="0" y="183.422" width="72" height="27" class="st8"/>
+ <text x="23.89" y="201.12" class="st9" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>BF-L</text> </g>
+ <g id="shape41-178" v:mID="41" v:groupContext="shape" transform="translate(300.375,-117)">
+ <title>Sheet.41</title>
+ <desc>Hashing for lookup/Insertion into a vector of BFs happens once</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="90" cy="187.922" width="180" height="45"/>
+ <rect x="0" y="165.422" width="180" height="45" class="st8"/>
+ <text x="4.6" y="184.32" class="st14" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Hashing for lookup/Insertion into a <tspan
+ x="23.06" dy="1.2em" class="st15">vector of BFs happens once</tspan></text> </g>
+ <g id="shape44-182" v:mID="44" v:groupContext="shape" transform="translate(250.649,-151.536) rotate(-3.74012)">
+ <title>Sheet.44</title>
+ <path d="M-0 210.42 A93.4958 45.6256 42.23 0 1 79.38 207.08 L79.68 207.28" class="st16"/>
+ </g>
+ <g id="shape45-188" v:mID="45" v:groupContext="shape" transform="translate(30.375,0)">
+ <title>Sheet.45</title>
+ <desc>Lookup/Insertion is done in the series of BFs, one by one but...</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="216" cy="187.922" width="432" height="45"/>
+ <rect x="0" y="165.422" width="432" height="45" class="st8"/>
+ <text x="9.93" y="191.52" class="st14" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Lookup/Insertion is done in the series of BFs, one by one but can be optimized on IA </text> </g>
+ <g id="shape46-191" v:mID="46" v:groupContext="shape" transform="translate(118.984,-44.3256) rotate(17.0249)">
+ <title>Sheet.46</title>
+ <path d="M-0 210.42 A88.2185 43.0621 47.63 0 1 70.31 206.81 L70.6 207.02" class="st16"/>
+ </g>
+ </g>
+ </g>
+</svg>
new file mode 100644
@@ -0,0 +1,123 @@
+<?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 memship_i5.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"
+ width="4.80481in" height="2.14896in" viewBox="0 0 345.946 154.725" xml:space="preserve" color-interpolation-filters="sRGB"
+ class="st14">
+ <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:none;stroke:none;stroke-width:0.25}
+ .st5 {fill:#ffffff;font-family:Calibri;font-size:1.16666em;font-weight:bold}
+ .st6 {marker-end:url(#mrkr5-16);stroke:#5b9bd5;stroke-linecap:round;stroke-linejoin:round;stroke-width:1}
+ .st7 {fill:#5b9bd5;fill-opacity:1;stroke:#5b9bd5;stroke-opacity:1;stroke-width:0.28409090909091}
+ .st8 {fill:#5b9bd5;font-family:Calibri;font-size:1.00001em}
+ .st9 {font-size:1em}
+ .st10 {stroke:#5b9bd5;stroke-linecap:round;stroke-linejoin:round;stroke-width:1}
+ .st11 {marker-end:url(#mrkr5-66);stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.75}
+ .st12 {fill:#000000;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:0.22935779816514}
+ .st13 {fill:#000000;font-family:Calibri;font-size:1.00001em}
+ .st14 {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-16" class="st7" refX="-6.16" orient="auto" markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend5" transform="scale(-3.52,-3.52) "/>
+ </marker>
+ <marker id="mrkr5-66" class="st12" refX="-7.15" orient="auto" markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend5" transform="scale(-4.36,-4.36) "/>
+ </marker>
+ </defs>
+ <defs id="Filters">
+ <filter id="filter_2">
+ <feGaussianBlur stdDeviation="2"/>
+ </filter>
+ </defs>
+ <g>
+ <title>Page-1</title>
+ <g id="group16-1" transform="translate(18.25,-32.9751)">
+ <title>Sheet.16</title>
+ <g id="group1-2" transform="translate(147.3,0)">
+ <title>Sheet.1</title>
+ <g id="shape2-3" transform="translate(160.125,55.7251) rotate(90)">
+ <title>Triangle</title>
+ <g id="shadow2-4" transform="matrix(1,0,0,1,1.97279,-0.345598)" class="st1">
+ <path d="M99 154.73 L49.5 76.73 L0 154.73 L99 154.73 Z" class="st2"/>
+ </g>
+ <path d="M99 154.73 L49.5 76.73 L0 154.73 L99 154.73 Z" class="st3"/>
+ </g>
+ <g id="shape3-8" transform="translate(0,-34.65)">
+ <title>Sheet.3</title>
+ <desc>vBF</desc>
+ <rect x="0" y="125.025" width="72" height="29.7" class="st4"/>
+ <text x="25.55" y="144.08" class="st5">vBF </text> </g>
+ </g>
+ <g id="shape4-11" transform="translate(85.6667,-81)">
+ <title>Sheet.4</title>
+ <path d="M0 154.73 L60.87 154.73" class="st6"/>
+ </g>
+ <g id="shape5-17" transform="translate(70.3125,-76.5)">
+ <title>Sheet.5</title>
+ <desc>Flow Key</desc>
+ <rect x="0" y="127.725" width="75.375" height="27" class="st4"/>
+ <text x="15.93" y="144.83" class="st8">Flow Key</text> </g>
+ <g id="shape6-20" transform="translate(163.417,-34.105) rotate(-25.776)">
+ <title>Sheet.6</title>
+ <path d="M0 154.73 L62.14 154.73" class="st6"/>
+ </g>
+ <g id="shape7-25" transform="translate(230.7,-49.5)">
+ <title>Sheet.7</title>
+ <path d="M0 154.73 L60.87 154.73" class="st6"/>
+ </g>
+ <g id="shape8-30" transform="translate(297.099,-34.5285) rotate(25.413)">
+ <title>Sheet.8</title>
+ <path d="M0 154.73 L67.24 154.73" class="st6"/>
+ </g>
+ <g id="shape9-35" transform="translate(152.7,264.45) rotate(180)">
+ <title>Sheet.9</title>
+ <path d="M0 154.73 L47.84 154.73" class="st6"/>
+ </g>
+ <g id="shape10-40" transform="translate(1.125,-45)">
+ <title>Sheet.10</title>
+ <desc>New Flow = New Assignment</desc>
+ <rect x="0" y="127.725" width="151.875" height="27" class="st4"/>
+ <text x="5.18" y="144.83" class="st8">New Flow = New Assignment</text> </g>
+ <g id="shape11-43" transform="translate(153,300.45) rotate(180)">
+ <title>Sheet.11</title>
+ <path d="M0 154.73 L47.84 154.73" class="st6"/>
+ </g>
+ <g id="shape12-48" transform="translate(0,-9)">
+ <title>Sheet.12</title>
+ <desc>Old Flow = forward to specific thread</desc>
+ <rect x="0" y="127.725" width="151.875" height="27" class="st4"/>
+ <text x="22.77" y="137.63" class="st8">Old Flow = forward to <tspan x="40.17" dy="1.2em" class="st9">specific thread</tspan></text> </g>
+ <g id="shape13-52" transform="translate(453.988,55.7251) rotate(90)">
+ <title>Sheet.13</title>
+ <path d="M0 147.99 C3.18 156.39 7.57 155.78 11.25 152.49 C15.79 148.43 19.26 140.28 27 147.99" class="st10"/>
+ </g>
+ <g id="shape14-55" transform="translate(453.988,91.7251) rotate(90)">
+ <title>Sheet.14</title>
+ <path d="M0 147.99 C3.18 156.39 7.57 155.78 11.25 152.49 C15.79 148.43 19.26 140.28 27 147.99" class="st10"/>
+ </g>
+ <g id="shape15-58" transform="translate(453.988,127.725) rotate(90)">
+ <title>Sheet.15</title>
+ <path d="M0 147.99 C3.18 156.39 7.57 155.78 11.25 152.49 C15.79 148.43 19.26 140.28 27 147.99" class="st10"/>
+ </g>
+ </g>
+ <g id="shape17-61" transform="translate(322.234,-34.6851) rotate(44.5185)">
+ <title>Sheet.17</title>
+ <path d="M-0 154.73 A35.1884 19.2595 167.75 0 1 42.43 151.77 L42.74 151.96" class="st11"/>
+ </g>
+ <g id="shape18-67" transform="translate(186.188,-18.9001)">
+ <title>Sheet.18</title>
+ <desc>A BF corresponding to each worker thread</desc>
+ <rect x="0" y="127.725" width="118.125" height="27" class="st4"/>
+ <text x="5.14" y="137.63" class="st13">A BF corresponding to <tspan x="11.19" dy="1.2em" class="st9">each worker thread</tspan></text> </g>
+ </g>
+</svg>
new file mode 100644
@@ -0,0 +1,233 @@
+<?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 memship_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"
+ width="8.56597in" height="3.47009in" viewBox="0 0 616.75 249.847" xml:space="preserve" color-interpolation-filters="sRGB"
+ class="st16">
+ <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:1.00001em;font-weight:bold}
+ .st5 {font-size:1em}
+ .st6 {fill:#70ad47;fill-opacity:0.5;stroke:#00b050;stroke-width:1.5}
+ .st7 {fill:none;stroke:none;stroke-width:0.25}
+ .st8 {fill:#00b050;font-family:Calibri;font-size:1.00001em}
+ .st9 {fill:none;stroke:#ff0000;stroke-width:0.25}
+ .st10 {fill:#5b9bd5;font-family:Calibri;font-size:0.833336em}
+ .st11 {marker-end:url(#mrkr5-33);stroke:#ff0000;stroke-linecap:round;stroke-linejoin:round;stroke-width:2.25}
+ .st12 {fill:#ff0000;fill-opacity:1;stroke:#ff0000;stroke-opacity:1;stroke-width:0.47169811320755}
+ .st13 {fill:#5b9bd5;font-family:Calibri;font-size:1.00001em}
+ .st14 {fill:#92d050;stroke:#c7c8c8;stroke-width:0.25}
+ .st15 {fill:#5b9bd5;font-family:Calibri;font-size:1.5em;font-weight:bold}
+ .st16 {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-33" class="st12" refX="-3.71" orient="auto" markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend5" transform="scale(-2.12,-2.12) "/>
+ </marker>
+ </defs>
+ <defs id="Filters">
+ <filter id="filter_2">
+ <feGaussianBlur stdDeviation="2"/>
+ </filter>
+ </defs>
+ <g>
+ <title>Page-1</title>
+ <g id="group123-1" transform="translate(3.0294,-5.3478)">
+ <title>Sheet.123</title>
+ <g id="group121-2">
+ <title>Sheet.121</title>
+ <g id="shape49-3" transform="translate(449.422,-57.9401)">
+ <title>Rectangle.2</title>
+ <g id="shadow49-4" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="208.396" width="99.4817" height="41.4507" class="st2"/>
+ </g>
+ <rect x="0" y="208.396" width="99.4817" height="41.4507" class="st3"/>
+ </g>
+ <g id="shape50-8" transform="translate(295.177,-16.6936)">
+ <title>Rectangle.4</title>
+ <g id="shadow50-9" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="166.945" width="99.4817" height="82.9014" class="st2"/>
+ </g>
+ <rect x="0" y="166.945" width="99.4817" height="82.9014" class="st3"/>
+ </g>
+ <g id="shape52-13" transform="translate(6.07514E-013,-29.0155)">
+ <title>Rectangle.10</title>
+ <desc>Signatures for target 1</desc>
+ <g id="shadow52-14" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="179.38" width="99.4817" height="70.4662" class="st2"/>
+ </g>
+ <rect x="0" y="179.38" width="99.4817" height="70.4662" class="st3"/>
+ <text x="14.94" y="211.01" class="st4">Signatures for <tspan x="30.22" dy="1.2em" class="st5">target </tspan>1</text> </g>
+ <g id="shape53-20" transform="translate(286.887,-24.9837)">
+ <title>Sheet.53</title>
+ <rect x="0" y="237.411" width="116.062" height="12.4352" class="st6"/>
+ </g>
+ <g id="shape54-22" transform="translate(227.102,-26.6257)">
+ <title>Sheet.54</title>
+ <desc>Match 1</desc>
+ <rect x="0" y="237.411" width="66.3211" height="12.4352" class="st7"/>
+ <text x="13.06" y="247.23" class="st8">Match 1</text> </g>
+ <g id="shape55-25" transform="translate(215.225,-227.669)">
+ <title>Sheet.55</title>
+ <desc>Packet Payload</desc>
+ <rect x="0" y="233.266" width="99.4817" height="16.5803" class="st9"/>
+ <text x="19.04" y="244.56" class="st10">Packet Payload</text> </g>
+ <g id="shape56-28" transform="translate(514.813,22.1781) rotate(90)">
+ <title>Sheet.56</title>
+ <path d="M0 249.85 L16.52 249.85" class="st11"/>
+ </g>
+ <g id="shape96-34" transform="translate(6.07514E-013,-101.124)">
+ <title>Sheet.96</title>
+ <desc>Attack Signature Length 1</desc>
+ <rect x="0" y="224.976" width="99.4817" height="24.8704" class="st7"/>
+ <text x="9.53" y="233.81" class="st13">Attack Signature <tspan x="28.7" dy="1.2em" class="st5">Length </tspan>1</text> </g>
+ <g id="group114-38" transform="translate(227.979,-150.865)">
+ <title>Sheet.114</title>
+ <g id="group106-39" transform="translate(0,-24.8704)">
+ <title>Sheet.106</title>
+ <g id="shape100-40" transform="translate(3.65707E-013,-12.4352)">
+ <title>Rectangle.100</title>
+ <g id="shadow100-41" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="237.411" width="24.8704" height="12.4352" class="st2"/>
+ </g>
+ <rect x="0" y="237.411" width="24.8704" height="12.4352" class="st3"/>
+ </g>
+ <g id="shape101-45" transform="translate(24.8704,-12.4352)">
+ <title>Rectangle.101</title>
+ <g id="shadow101-46" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="237.411" width="24.8704" height="12.4352" class="st2"/>
+ </g>
+ <rect x="0" y="237.411" width="24.8704" height="12.4352" class="st3"/>
+ </g>
+ <g id="shape102-50" transform="translate(49.7409,-12.4352)">
+ <title>Rectangle.102</title>
+ <g id="shadow102-51" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="237.411" width="24.8704" height="12.4352" class="st2"/>
+ </g>
+ <rect x="0" y="237.411" width="24.8704" height="12.4352" class="st3"/>
+ </g>
+ <g id="shape103-55">
+ <title>Rectangle.103</title>
+ <g id="shadow103-56" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="237.411" width="24.8704" height="12.4352" class="st2"/>
+ </g>
+ <rect x="0" y="237.411" width="24.8704" height="12.4352" class="st3"/>
+ </g>
+ <g id="shape104-60" transform="translate(24.8704,1.42109E-013)">
+ <title>Rectangle.104</title>
+ <g id="shadow104-61" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="237.411" width="24.8704" height="12.4352" class="st2"/>
+ </g>
+ <rect x="0" y="237.411" width="24.8704" height="12.4352" class="st3"/>
+ </g>
+ <g id="shape105-65" transform="translate(49.7409,1.42109E-013)">
+ <title>Rectangle.105</title>
+ <g id="shadow105-66" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="237.411" width="24.8704" height="12.4352" class="st2"/>
+ </g>
+ <rect x="0" y="237.411" width="24.8704" height="12.4352" class="st3"/>
+ </g>
+ </g>
+ <g id="group107-70">
+ <title>Sheet.107</title>
+ <g id="shape108-71" transform="translate(3.65707E-013,-12.4352)">
+ <title>Rectangle.100</title>
+ <g id="shadow108-72" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="237.411" width="24.8704" height="12.4352" class="st2"/>
+ </g>
+ <rect x="0" y="237.411" width="24.8704" height="12.4352" class="st3"/>
+ </g>
+ <g id="shape109-76" transform="translate(24.8704,-12.4352)">
+ <title>Rectangle.101</title>
+ <g id="shadow109-77" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="237.411" width="24.8704" height="12.4352" class="st2"/>
+ </g>
+ <rect x="0" y="237.411" width="24.8704" height="12.4352" class="st3"/>
+ </g>
+ <g id="shape110-81" transform="translate(49.7409,-12.4352)">
+ <title>Rectangle.102</title>
+ <g id="shadow110-82" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="237.411" width="24.8704" height="12.4352" class="st2"/>
+ </g>
+ <rect x="0" y="237.411" width="24.8704" height="12.4352" class="st3"/>
+ </g>
+ <g id="shape111-86">
+ <title>Rectangle.103</title>
+ <g id="shadow111-87" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="237.411" width="24.8704" height="12.4352" class="st2"/>
+ </g>
+ <rect x="0" y="237.411" width="24.8704" height="12.4352" class="st14"/>
+ </g>
+ <g id="shape112-91" transform="translate(24.8704,1.42109E-013)">
+ <title>Rectangle.104</title>
+ <g id="shadow112-92" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="237.411" width="24.8704" height="12.4352" class="st2"/>
+ </g>
+ <rect x="0" y="237.411" width="24.8704" height="12.4352" class="st3"/>
+ </g>
+ <g id="shape113-96" transform="translate(49.7409,1.42109E-013)">
+ <title>Rectangle.105</title>
+ <g id="shadow113-97" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="237.411" width="24.8704" height="12.4352" class="st2"/>
+ </g>
+ <rect x="0" y="237.411" width="24.8704" height="12.4352" class="st14"/>
+ </g>
+ </g>
+ </g>
+ <g id="shape89-101" transform="translate(373.169,-144.96) rotate(19.406)">
+ <title>Sheet.89</title>
+ <path d="M0 249.85 L185.02 249.85" class="st11"/>
+ </g>
+ <g id="shape115-106" transform="translate(116.062,-1.22213E-012)">
+ <title>Rectangle.115</title>
+ <desc>Signatures for target 2</desc>
+ <g id="shadow115-107" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="150.365" width="99.4817" height="99.4817" class="st2"/>
+ </g>
+ <rect x="0" y="150.365" width="99.4817" height="99.4817" class="st3"/>
+ <text x="14.94" y="196.51" class="st4">Signatures for <tspan x="30.22" dy="1.2em" class="st5">target </tspan>2</text> </g>
+ <g id="shape116-113" transform="translate(116.062,-101.124)">
+ <title>Sheet.116</title>
+ <desc>Attack Signature Length 2</desc>
+ <rect x="0" y="224.976" width="99.4817" height="24.8704" class="st7"/>
+ <text x="9.53" y="233.81" class="st13">Attack Signature <tspan x="28.7" dy="1.2em" class="st5">Length </tspan>2</text> </g>
+ <g id="shape117-117" transform="translate(290.155,-101.124)">
+ <title>Sheet.117</title>
+ <desc>Attack Signature Length X</desc>
+ <rect x="0" y="224.976" width="99.4817" height="24.8704" class="st7"/>
+ <text x="9.53" y="233.81" class="st13">Attack Signature <tspan x="28.62" dy="1.2em" class="st5">Length X</tspan></text> </g>
+ <g id="shape118-121" transform="translate(447.668,-102.857)">
+ <title>Sheet.118</title>
+ <desc>Attack Signature Length L</desc>
+ <rect x="0" y="224.976" width="99.4817" height="24.8704" class="st7"/>
+ <text x="9.53" y="233.81" class="st13">Attack Signature <tspan x="29.22" dy="1.2em" class="st5">Length L</tspan></text> </g>
+ <g id="shape119-125" transform="translate(439.378,-65.7997)">
+ <title>Sheet.119</title>
+ <rect x="0" y="237.411" width="116.062" height="12.4352" class="st6"/>
+ </g>
+ <g id="shape120-127" transform="translate(547.149,-63.8181)">
+ <title>Sheet.120</title>
+ <desc>Match 2</desc>
+ <rect x="0" y="237.411" width="66.3211" height="12.4352" class="st7"/>
+ <text x="13.06" y="247.23" class="st8">Match 2</text> </g>
+ <g id="shape85-130" transform="translate(441.66,-55.3013) rotate(53.6564)">
+ <title>Sheet.85</title>
+ <path d="M0 249.85 L150.51 249.85" class="st11"/>
+ </g>
+ </g>
+ <g id="shape122-135" transform="translate(175.448,-169.167)">
+ <title>Sheet.122</title>
+ <desc>HTSS</desc>
+ <rect x="0" y="224.976" width="53.8859" height="24.8704" class="st7"/>
+ <text x="8.3" y="242.81" class="st15">HTSS</text> </g>
+ </g>
+ </g>
+</svg>
new file mode 100644
@@ -0,0 +1,277 @@
+<?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 memship_i7.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"
+ width="8.125in" height="3.92442in" viewBox="0 0 585 282.559" xml:space="preserve" color-interpolation-filters="sRGB"
+ class="st22">
+ <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:1.00001em;font-weight:bold}
+ .st5 {font-size:1em}
+ .st6 {fill:#70ad47;fill-opacity:0.5;stroke:#00b050;stroke-width:1.5}
+ .st7 {fill:none;stroke:none;stroke-width:0.25}
+ .st8 {fill:#00b050;font-family:Calibri;font-size:1.00001em}
+ .st9 {fill:none;stroke:#00b050;stroke-width:2.25}
+ .st10 {fill:#5b9bd5;font-family:Calibri;font-size:0.833336em}
+ .st11 {fill:#5b9bd5;font-family:Calibri;font-size:1.00001em}
+ .st12 {fill:#a8d08d;stroke:#c7c8c8;stroke-width:0.25}
+ .st13 {marker-end:url(#mrkr5-99);stroke:#ff0000;stroke-linecap:round;stroke-linejoin:round;stroke-width:2.25}
+ .st14 {fill:#ff0000;fill-opacity:1;stroke:#ff0000;stroke-opacity:1;stroke-width:0.47169811320755}
+ .st15 {marker-end:url(#mrkr5-112);stroke:#92d050;stroke-linecap:round;stroke-linejoin:round;stroke-width:2.25}
+ .st16 {fill:#92d050;fill-opacity:1;stroke:#92d050;stroke-opacity:1;stroke-width:0.47169811320755}
+ .st17 {fill:#00b050;font-family:Calibri;font-size:0.833336em;font-weight:bold}
+ .st18 {fill:none;stroke:#ff0000;stroke-width:2.25}
+ .st19 {fill:#ff0000;font-family:Calibri;font-size:0.833336em;font-weight:bold}
+ .st20 {marker-end:url(#mrkr5-140);stroke:#ff0000;stroke-linecap:round;stroke-linejoin:round;stroke-width:1}
+ .st21 {fill:#ff0000;fill-opacity:1;stroke:#ff0000;stroke-opacity:1;stroke-width:0.28409090909091}
+ .st22 {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-99" class="st14" refX="-3.71" orient="auto" markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend5" transform="scale(-2.12,-2.12) "/>
+ </marker>
+ <marker id="mrkr5-112" class="st16" refX="-3.71" orient="auto" markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend5" transform="scale(-2.12,-2.12) "/>
+ </marker>
+ <marker id="mrkr5-140" class="st21" refX="-5.8" orient="auto" markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend5" transform="scale(-3.52,-3.52) "/>
+ </marker>
+ </defs>
+ <defs id="Filters">
+ <filter id="filter_2">
+ <feGaussianBlur stdDeviation="2"/>
+ </filter>
+ </defs>
+ <g>
+ <title>Page-1</title>
+ <g id="group135-1" transform="translate(3.0294,-11.6966)">
+ <title>Sheet.135</title>
+ <g id="group121-2" transform="translate(0,-21.3235)">
+ <title>Sheet.121</title>
+ <g id="shape49-3" transform="translate(426.345,-54.965)">
+ <title>Rectangle.2</title>
+ <g id="shadow49-4" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="243.236" width="94.3736" height="39.3223" class="st2"/>
+ </g>
+ <rect x="0" y="243.236" width="94.3736" height="39.3223" class="st3"/>
+ </g>
+ <g id="shape50-8" transform="translate(280.021,-15.8364)">
+ <title>Rectangle.4</title>
+ <g id="shadow50-9" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="203.914" width="94.3736" height="78.6447" class="st2"/>
+ </g>
+ <rect x="0" y="203.914" width="94.3736" height="78.6447" class="st3"/>
+ </g>
+ <g id="shape52-13" transform="translate(5.83533E-013,-27.5256)">
+ <title>Rectangle.10</title>
+ <desc>Flow Keys Matching Mask 1</desc>
+ <g id="shadow52-14" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="215.711" width="94.3736" height="66.848" class="st2"/>
+ </g>
+ <rect x="0" y="215.711" width="94.3736" height="66.848" class="st3"/>
+ <text x="22.37" y="245.53" class="st4">Flow Keys <tspan x="4.4" dy="1.2em" class="st5">Matching Mask </tspan>1</text> </g>
+ <g id="shape53-20" transform="translate(272.156,-23.7009)">
+ <title>Sheet.53</title>
+ <rect x="0" y="270.762" width="110.103" height="11.7967" class="st6"/>
+ </g>
+ <g id="shape54-22" transform="translate(220.205,-25.2586)">
+ <title>Sheet.54</title>
+ <desc>Match</desc>
+ <rect x="0" y="270.762" width="62.9157" height="11.7967" class="st7"/>
+ <text x="15.75" y="280.26" class="st8">Match</text> </g>
+ <g id="shape55-25" transform="translate(228.07,-215.978)">
+ <title>Sheet.55</title>
+ <desc>Flow ID1</desc>
+ <rect x="0" y="266.83" width="47.4888" height="15.7289" class="st9"/>
+ <text x="6.09" y="277.69" class="st10">Flow ID1</text> </g>
+ <g id="shape96-28" transform="translate(5.83533E-013,-95.9313)">
+ <title>Sheet.96</title>
+ <desc>Flow Mask 1</desc>
+ <rect x="0" y="274.694" width="94.3736" height="7.86447" class="st7"/>
+ <text x="16.77" y="282.23" class="st11">Flow Mask 1</text> </g>
+ <g id="group114-31" transform="translate(216.273,-143.118)">
+ <title>Sheet.114</title>
+ <g id="group106-32" transform="translate(0,-23.5934)">
+ <title>Sheet.106</title>
+ <g id="shape100-33" transform="translate(3.53717E-013,-11.7967)">
+ <title>Rectangle.100</title>
+ <g id="shadow100-34" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="270.762" width="23.5934" height="11.7967" class="st2"/>
+ </g>
+ <rect x="0" y="270.762" width="23.5934" height="11.7967" class="st3"/>
+ </g>
+ <g id="shape101-38" transform="translate(23.5934,-11.7967)">
+ <title>Rectangle.101</title>
+ <g id="shadow101-39" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="270.762" width="23.5934" height="11.7967" class="st2"/>
+ </g>
+ <rect x="0" y="270.762" width="23.5934" height="11.7967" class="st3"/>
+ </g>
+ <g id="shape102-43" transform="translate(47.1868,-11.7967)">
+ <title>Rectangle.102</title>
+ <g id="shadow102-44" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="270.762" width="23.5934" height="11.7967" class="st2"/>
+ </g>
+ <rect x="0" y="270.762" width="23.5934" height="11.7967" class="st3"/>
+ </g>
+ <g id="shape103-48">
+ <title>Rectangle.103</title>
+ <g id="shadow103-49" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="270.762" width="23.5934" height="11.7967" class="st2"/>
+ </g>
+ <rect x="0" y="270.762" width="23.5934" height="11.7967" class="st3"/>
+ </g>
+ <g id="shape104-53" transform="translate(23.5934,1.13687E-013)">
+ <title>Rectangle.104</title>
+ <g id="shadow104-54" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="270.762" width="23.5934" height="11.7967" class="st2"/>
+ </g>
+ <rect x="0" y="270.762" width="23.5934" height="11.7967" class="st3"/>
+ </g>
+ <g id="shape105-58" transform="translate(47.1868,1.13687E-013)">
+ <title>Rectangle.105</title>
+ <g id="shadow105-59" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="270.762" width="23.5934" height="11.7967" class="st2"/>
+ </g>
+ <rect x="0" y="270.762" width="23.5934" height="11.7967" class="st3"/>
+ </g>
+ </g>
+ <g id="group107-63">
+ <title>Sheet.107</title>
+ <g id="shape108-64" transform="translate(3.53717E-013,-11.7967)">
+ <title>Rectangle.100</title>
+ <g id="shadow108-65" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="270.762" width="23.5934" height="11.7967" class="st2"/>
+ </g>
+ <rect x="0" y="270.762" width="23.5934" height="11.7967" class="st3"/>
+ </g>
+ <g id="shape109-69" transform="translate(23.5934,-11.7967)">
+ <title>Rectangle.101</title>
+ <g id="shadow109-70" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="270.762" width="23.5934" height="11.7967" class="st2"/>
+ </g>
+ <rect x="0" y="270.762" width="23.5934" height="11.7967" class="st3"/>
+ </g>
+ <g id="shape110-74" transform="translate(47.1868,-11.7967)">
+ <title>Rectangle.102</title>
+ <g id="shadow110-75" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="270.762" width="23.5934" height="11.7967" class="st2"/>
+ </g>
+ <rect x="0" y="270.762" width="23.5934" height="11.7967" class="st12"/>
+ </g>
+ <g id="shape111-79">
+ <title>Rectangle.103</title>
+ <g id="shadow111-80" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="270.762" width="23.5934" height="11.7967" class="st2"/>
+ </g>
+ <rect x="0" y="270.762" width="23.5934" height="11.7967" class="st3"/>
+ </g>
+ <g id="shape112-84" transform="translate(23.5934,1.13687E-013)">
+ <title>Rectangle.104</title>
+ <g id="shadow112-85" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="270.762" width="23.5934" height="11.7967" class="st2"/>
+ </g>
+ <rect x="0" y="270.762" width="23.5934" height="11.7967" class="st3"/>
+ </g>
+ <g id="shape113-89" transform="translate(47.1868,1.13687E-013)">
+ <title>Rectangle.105</title>
+ <g id="shadow113-90" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="270.762" width="23.5934" height="11.7967" class="st2"/>
+ </g>
+ <rect x="0" y="270.762" width="23.5934" height="11.7967" class="st3"/>
+ </g>
+ </g>
+ </g>
+ <g id="shape89-94" transform="translate(361.211,343.085) rotate(146.31)">
+ <title>Sheet.89</title>
+ <path d="M0 282.56 L133.43 282.56" class="st13"/>
+ </g>
+ <g id="shape115-100" transform="translate(110.103,-1.13687E-012)">
+ <title>Rectangle.115</title>
+ <desc>Flow Keys Matching Mask 2</desc>
+ <g id="shadow115-101" transform="matrix(1,0,0,1,0.345598,1.97279)" class="st1">
+ <rect x="0" y="188.185" width="94.3736" height="94.3736" class="st2"/>
+ </g>
+ <rect x="0" y="188.185" width="94.3736" height="94.3736" class="st3"/>
+ <text x="22.37" y="231.77" class="st4">Flow Keys <tspan x="4.4" dy="1.2em" class="st5">Matching Mask </tspan>2</text> </g>
+ <g id="shape85-107" transform="translate(554.606,79.2847) rotate(81.3573)">
+ <title>Sheet.85</title>
+ <path d="M0 282.56 L124.72 282.56" class="st15"/>
+ </g>
+ <g id="shape56-113" transform="translate(505.594,-56.7279) rotate(64.1257)">
+ <title>Sheet.56</title>
+ <path d="M0 282.56 L46.41 282.56" class="st15"/>
+ </g>
+ </g>
+ <g id="shape122-118" transform="translate(290.985,-176.238)">
+ <title>Sheet.122</title>
+ <desc>HTSS with False Negative (Cache)</desc>
+ <rect x="0" y="258.965" width="94.3736" height="23.5934" class="st7"/>
+ <text x="9.13" y="267.16" class="st11">HTSS with False <tspan x="5.8" dy="1.2em" class="st5">Negative </tspan>(Cache)</text> </g>
+ <g id="shape123-122" transform="translate(232.985,-247.019)">
+ <title>Sheet.123</title>
+ <desc>Active</desc>
+ <rect x="0" y="258.965" width="42.2715" height="23.5934" class="st7"/>
+ <text x="8.17" y="273.76" class="st17">Active</text> </g>
+ <g id="shape124-125" transform="translate(227.919,-121.187)">
+ <title>Sheet.124</title>
+ <desc>Target for Flow ID 1</desc>
+ <rect x="0" y="258.965" width="63.0667" height="23.5934" class="st9"/>
+ <text x="11.41" y="267.76" class="st10">Target for <tspan x="12.75" dy="1.2em" class="st5">Flow ID </tspan>1</text> </g>
+ <g id="shape125-129" transform="translate(117.816,-215.561)">
+ <title>Sheet.125</title>
+ <desc>Flow ID2</desc>
+ <rect x="0" y="266.83" width="47.4888" height="15.7289" class="st18"/>
+ <text x="6.09" y="277.69" class="st10">Flow ID2</text> </g>
+ <g id="shape126-132" transform="translate(133.696,-227.357)">
+ <title>Sheet.126</title>
+ <desc>New/Inactive</desc>
+ <rect x="0" y="258.965" width="70.7802" height="23.5934" class="st7"/>
+ <text x="7.28" y="273.76" class="st19">New/Inactive</text> </g>
+ <g id="shape127-135" transform="translate(201.302,-201.959) rotate(14.0795)">
+ <title>Sheet.127</title>
+ <path d="M0 277.29 A34.2894 18 -180 0 0 42.82 279.69 L43.15 279.55" class="st20"/>
+ </g>
+ <g id="shape128-141" transform="translate(186.231,-191.967)">
+ <title>Sheet.128</title>
+ <desc>Miss</desc>
+ <rect x="0" y="258.965" width="36.4911" height="23.5934" class="st7"/>
+ <text x="7.05" y="274.36" class="st11">Miss</text> </g>
+ <g id="shape129-144" transform="translate(110.103,-117.255)">
+ <title>Sheet.129</title>
+ <desc>Flow Mask 2</desc>
+ <rect x="0" y="274.694" width="94.3736" height="7.86447" class="st7"/>
+ <text x="16.77" y="282.23" class="st11">Flow Mask 2</text> </g>
+ <g id="shape130-147" transform="translate(126.037,-5.6568) rotate(18.2325)">
+ <title>Sheet.130</title>
+ <path d="M0 252.02 A62.209 104.269 -180 0 0 84.65 257.2 L84.84 256.9" class="st20"/>
+ </g>
+ <g id="shape131-152" transform="translate(143.013,8.06313) rotate(-3.24734)">
+ <title>Sheet.131</title>
+ <path d="M0 252.02 A98.1706 104.269 -180 0 0 134.48 256.37 L134.73 256.12" class="st20"/>
+ </g>
+ <g id="shape132-157" transform="translate(284.267,10.4726) rotate(-16.7388)">
+ <title>Sheet.132</title>
+ <path d="M-0 252.02 A96.5426 104.269 -180 0 0 132.21 256.41 L132.46 256.15" class="st20"/>
+ </g>
+ <g id="shape133-162" transform="translate(283.121,-117.255)">
+ <title>Sheet.133</title>
+ <desc>Flow Mask X</desc>
+ <rect x="0" y="274.694" width="94.3736" height="7.86447" class="st7"/>
+ <text x="16.69" y="282.23" class="st11">Flow Mask X</text> </g>
+ <g id="shape134-165" transform="translate(424.681,-117.255)">
+ <title>Sheet.134</title>
+ <desc>Flow Mask L</desc>
+ <rect x="0" y="274.694" width="94.3736" height="7.86447" class="st7"/>
+ <text x="17.29" y="282.23" class="st11">Flow Mask L</text> </g>
+ </g>
+ </g>
+</svg>
@@ -48,6 +48,7 @@ Programmer's Guide
timer_lib
hash_lib
efd_lib
+ membership_lib
lpm_lib
lpm6_lib
packet_distrib_lib
@@ -187,6 +188,19 @@ Programmer's Guide
:numref:`figure_efd11` :ref:`figure_efd11`
+:numref:`figure_membership1` :ref:`figure_membership1`
+
+:numref:`figure_membership2` :ref:`figure_membership2`
+
+:numref:`figure_membership3` :ref:`figure_membership3`
+
+:numref:`figure_membership4` :ref:`figure_membership4`
+
+:numref:`figure_membership5` :ref:`figure_membership5`
+
+:numref:`figure_membership6` :ref:`figure_membership6`
+
+:numref:`figure_membership7` :ref:`figure_membership7`
**Tables**
new file mode 100644
@@ -0,0 +1,424 @@
+.. BSD LICENSE
+ Copyright(c) 2010-2015 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.
+
+Membership Library
+=======================
+
+Introduction
+------------
+The DPDK Membership Library provides an API for DPDK applications to insert a
+new member, delete an existing member, or query the existence of a member in a
+given set, or a group of sets. For the case of a group of sets the library
+will return not only whether the element has been inserted before in one of
+the sets but also which set it belongs to. The Membership Library is an
+extension and generalization of a traditional filter structure (for example
+Bloom Filter [Memship-bloom]) that has multiple usages in a wide variety of
+workloads and applications. In general, the Membership Library is a data
+structure that provides a “set-summary” on whether a member belongs to a set,
+and as discussed in details later, there are two advantages of using such a
+set-summary rather than operating on a “full-blown” complete list of elements:
+first, it has a much smaller storage requirement than storing the whole list of
+elements themselves, and secondly checking an element membership (or other
+operations) in this set-summary is much faster than checking it for the
+original full-blown complete list of elements.
+
+We use the term “Set-Summary” in this guide to refer to the space-efficient,
+probabilistic membership data structure that is provided by the library. A
+membership test for an element will return the set this element belongs to or
+null (meaning not found) with very high probability of accuracy. Set-summary
+is a fundamental data aggregation component that can be used in many network
+(and other) applications. It is a crucial structure to address performance and
+scalability issues of diverse network applications including overlay networks,
+data-centric networks, flow table summaries, network statistics and
+traffic monitoring. A set-summary is useful for applications who need to
+include a list of elements while a complete list requires too much space
+and/or too much processing cost. In these situations, the set-summary works as
+a lossy hash-based representation of a set of members. It can dramatically
+reduce space requirement and significantly improve the performance of set
+membership queries at the cost of introducing a very small membership test error
+probability.
+
+.. _figure_membership1:
+.. figure:: img/memship_i1.*
+
+ Example Usages of Membership Library
+
+We believe that there are various usages for a Membership Library in a very
+large set of applications and workloads. Interested readers can refer to
+[Memship-survey] for a survey of possible networking usages. The above figure
+provide a small set of examples of using the Membership Library. Sub-figure(a)
+depicts a distributed web cache architecture where a collection of proxies
+attempt to share their web caches (cached from a set of backend web servers) to
+provide faster responses to clients, and the proxies uses the Membership
+Library to share summaries of what webpages they are caching. With the
+Membership Library, a proxy receiving an \http request will inquire the
+set-summary to find its location and quickly determine whether to retrieve the
+requested webpage from a nearby proxy or from a backend web server.
+Sub-figure(b) depicts another example for using the Membership Library to
+prevent routing loops which is typically done using slow TTL countdown and
+dropping packets when TTL expires. As shown in Sub-figure(b), an embedded
+set-summary in the packet header itself can be used to summarize the set of
+nodes a packet has gone through, and each node upon receiving a packet can check
+whether its id is a member of the set of visited nodes, and if it is then a
+routing loop is detected. Sub-Figure(c) presents another usage of Membership
+Library to load balance flows to worker threads with in-order guarantee where a
+set-summary is used to query if a packet belongs to an existing flow or a new
+flow. Packets belonging to a new flow are forwarded to the current least loaded
+worker thread, while those belonging to an existing flow are forwarded to the
+pre-assigned thread to guarantee in-order processing. Sub-figure(d) highlights
+yet another usage example in the database domain where a set-summary is used to
+determine joins between sets instead of creating a join by comparing each
+element of a set against the other elements in a different set, a join is done
+on the summaries since they can efficiently encode members of a given set.
+
+We are including a configurable Membership Library in DPDK to cover set
+membership functionality for both a single set and multi-set scenarios. The
+library is optimized to support the customer network applications which require
+membership checking functionality. In this guide, we will cover few set-summary
+schemes including Bloom Filter, vector of Bloom Filters, abd Hash-Table based
+set-summary schemes with and without false negative probability, followed by
+a brief discussion of the Membership Library API.
+
+Bloom Filter
+---------------
+
+The Bloom Filter (BF) [Memship-bloom] is a well-known space-efficient
+probabilistic data structure that answers set membership queries (test whether
+an element is a member of a set) with some probability of false positives and
+zero false negatives; a query for an element returns either it is "possibly in
+a set" (with very high probability) or "definitely not in a set".
+
+The BF is a method for representing a set of n elements (for example flow keys
+in network applications domain) to support membership queries. The idea of BF is
+to allocate a bit-vector v with m bits, which are initially all set to 0. Then
+it chooses k independent hash functions h1, h2, … hk with hash values range from
+1 to m to perform hashing calculations on each element. Every time when an
+element X being inserted into the set, the bits at positions h1(X), h2(X), …
+hk(X) in v are set to 1 (any particular bit might be set to 1 multiple times
+for multiple different inserted elements). Given a query for any element Y, the
+bits at positions h1(Y), h2(Y), ... hk(Y) are checked. If any of them is 0,
+then Y is definitely not in the set. Otherwise there is a high probability that
+Y is a member of the set with certain false positive probability. As shown in
+the next equation, the false positive probability can be made arbitrarily small
+by changing the number of hash functions (k) and the vector length (m).
+
+.. _figure_membership2:
+.. figure:: img/memship_i2.*
+
+ Bloom Filter False Positive Probability
+
+Without BF, an accurate membership testing could involve a costly hash table
+lookup and full element comparison. The advantage of using a BF is to simplify
+the membership test into a series of hash calculations and memory accesses for a
+small bit-vector, which can be easily optimized. Hence the lookup throughput
+(set membership test) can be significantly faster than a normal hash table
+lookup with element comparison.
+
+.. _figure_membership3:
+.. figure:: img/memship_i3.*
+
+ Detecting Routing Loops Using BF
+
+By design, BF is used for applications that need only one set, and the
+membership of elements is checked against its set-summary. The example discussed
+in the above figure is one example of potential applications that uses only one
+set to capture the node IDs that have been visited so far by the packet. Each
+node will then check this embedded BF in the packet header for its own id, and
+if the BF indicates that the current node is definitely not in the set then a
+loop-free route is guaranteed.
+
+
+Vector of Bloom Filters
+--------------------------
+
+.. _figure_membership4:
+.. figure:: img/memship_i4.*
+
+ Vector Bloom Filter (vBF) Overview
+
+Vector Bloom Filter (vBF) is another scheme supported by the Membership Library
+to support more than one set. The membership test is conducted on all of the
+set-summaries concurrently to determine which set(s) it belongs to or none of
+them. The basic idea of vBF is shown in the above figure where an element is
+used to address multiple bloom filters concurrently and the bloom filter
+index(es) with a hit is returned.
+
+.. _figure_membership5:
+.. figure:: img/memship_i5.*
+
+ vBF for Flow Scheduling to Worker Thread
+
+As previously mentioned, there are many usages of such structure. vBF is used
+for applications that needs to check membership against multiple sets
+simultaneously. The example discussed in the above figure uses a set to capture
+all flows being assigned for processing at a given worker thread. Upon receiving
+a packet the vBF is used to figure quickly if this packet belongs to a new flow
+so as to be forwarded to the current least loaded worker thread, or otherwise it
+should be queued for an existing thread to guarantee in-order processing (i.e.
+the property of vBF to indicate right away that a given flow is a new one or
+not is critical to minimize response time latency).
+
+It should be noted that vBF can be implemented using a set of single bloom
+filters with sequential lookup of each BF. However, being able to concurrently
+search all set-summaries is a big throughput advantage and the implementation
+can typically be fully optimized across different CPU architectures. For
+example, on IA prefetching and vector instructions (AVX) can be used for
+optimizations.
+
+
+Hash-Table based Set-Summaries
+---------------------------------
+
+Hash-table based set-summary (HTSS) is another scheme in the membership library.
+Cuckoo filter [Memship-cfilter] is an example of hash-table based set summary.
+HTSS can be easily extended to support multi-set membership testing like what
+vBF does. Meanwhile, HTSS can easily outperform vBF when the number of sets is
+large, since HTSS uses a single hash table for membership testing while vBF
+requires testing a series of Bloom Filters each corresponding to one set.
+
+.. _figure_membership6:
+.. figure:: img/memship_i6.*
+
+ Using HTSS for Attack Signature Matching
+
+As shown in the above figure, attack signature matching where each set
+represents a certain signature length (for correctness of this example, an
+attack signature should not be a subset of another one) in the payload is a good
+example for using HTSS with 0% false negative (i.e., when an element returns not
+found, it has a 100% certainty that it is not a member of any set). The packet
+inspection application benefits from knowing right away that the current payload
+does not match any attack signatures in the database to establish its
+legitimacy, otherwise a deep inspenction of the packet is needed.
+
+HTSS employs a similar but simpler data structure to a traditional hash table,
+and the major difference is that HTSS stores only the signatures but not the
+full keys/elements which can significantly reduce the footprint of the table.
+Along with the signature, HTSS also stores a value to indicate the target set.
+When looking up for an element, the element is hashed and the HTSS is addressed
+to retrieve the signature stored. If the signature matches then the value is
+retrieved corresponding to the index of the target set which the element belongs
+to. Because signatures can collide, HTSS can still has false positive
+probability similar to vBF. Furthermore, if elements are allowed to be
+overwritten or evicted when the hash table becomes full, it will also have a
+false negative probability. We discuss this case in the next section.
+
+Set-Summaries with False Negative Probability
+-----------------------------------------------
+
+As previously discussed, traditional set-summaries (e.g. Bloom Filters ) do not
+have a false negative probability, i.e., it is 100% certain when an element
+returns “not to be present” for a given set. However, the Membership Library
+also supports a set-summary probabilistic data structure based on HTSS which
+allows for false negative probability.
+
+
+In HTSS, when the hash table becomes full, keys/elements will fail to be added
+into the table and the hash table has to be resized to accommodate for these new
+elements, which can be expensive. However, if we allow new elements to overwrite
+or evict existing elements (as a cache typically does), then the resulting
+set-summary will begin to have false negative probability. This is because the
+element that was evicted from the set-summary may still be present in the target
+set. For subsequent inquiries the set-summary will falsely report the element
+not being in the set, hence having a false negative probability.
+
+The major usage of HTSS with false negative is to use it as a cache for
+distributing elements to different target sets. By allowing HTSS to evict old
+elements, the set-summary can keep track of the most recent elements
+(i.e. active) as a cache typically does. Old inactive elements (infrequently
+used elements) will automatically and eventually get evicted from the
+set-summary. It should be noted that given an element the lookup can always fall
+back to a sequential search of the sets if the set-summary fails to correctly
+report its existence.
+
+.. _figure_membership7:
+.. figure:: img/memship_i7.*
+
+ Using HTSS with False Negatives for Wild Card Classification
+
+HTSS with false negative (i.e. a cache) has also its wide set of applications.
+For example Wild card flow classification (e.g. ACL rules) highlighted in the
+above figure is an example of such application. In that case each target set
+represents a sub-table with rules defined by a certain flow mask. The flow masks
+are non-overlapping, and for flows matching more than one rule only the highest
+priority one is inserted in the corresponding sub-table (interested readers can
+refer to the Open vSwitch (OvS) design of Mega Flow Cache (MFC) [Memship-OvS]
+for further details) Typically the rules will have a large number of distinct
+unique masks and hence, a large number of target sets each corresponding to one
+mask. Because the active set of flows varies widely based on the network
+traffic, HTSS with false negative will act as a cache for <flowid, target ACL
+sub-table> pair for the current active set of flows. When a miss occurs (as
+shown in red in the above figure) the sub-tables will be searched sequentially
+one by one for a possible match, and when found the flow key and target
+sub-table will be inserted in the set-summary (i.e. cache insertion) so
+subsequent packets from the same flow don’t incur the overhead of the
+sequential search of sub-tables.
+
+Library API Overview
+--------------------
+The design goal of the Membership Library API is to be as generic as possible to
+support all the different types of set-summaries we discussed in previous
+sections and beyond. Fundamentally, the APIs need to include query, creation,
+insertion, deletion, and lookup. Other functions like retrieving a set-summary
+by name and destroying a certain set-summary, etc. are also needed but are very
+common, straightforward, and similar to other libraries in DPDK.
+
+Set-summary Type Query
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+*void rte\_ms\_type\_query(enum rte\_ms\_setsum\_type\*\* types)*
+
+This function intends to serve as a convenient tool to query which set-summary
+types are supported in the current version of DPDK. Since the implementations of
+the set-summaries can vary, initial versions of the Membership Library may only
+support a subset of the set-summaries we discussed previously. Programmers could
+use this API to decide which type is available to use in the current version of DPDK.
+
+Set-summary Create
+~~~~~~~~~~~~~~~~~~~~~
+
+*rte\_membership\_create(const struct rte\_membership\_parameters \*params)*
+
+This function is used to create a set-summary structure, the input parameters
+are those needed to initialize the set-summary, while the function returns the
+pointer to the created set-summary or NULL if the creation failed.
+
+Tha input argument parameters used when creating the set-summary are, *name*
+which is the name of the created set-summary, *type* which is one of the types
+supported by the library (BF, vBF, Cache or Hash Table set-summary), *num\_keys*
+which is the maximum total number of elements/keys in the set-summary structure,
+*key\_len* is the length of the element/key. *prim\_hash\_seed* and
+*sec\_hash\_seed* are the seeds of the primary and secondary hash functions,
+while *socket\_id* is the NUMA socket ID for the memory used to create the
+set-summary. The other two parameters that are
+relevant to only the BF and vBF types are *num\_target* which is the number of
+targets (i.e. number of set-summaries), and *false\_pos\_rate* which is the
+maximum allowable false positive probability by the application (in case of BF
+and vBF the two arguments num\_keys and false\_pos\_rate will used to determine
+the number of hash functions and the bit-vector size to gurantee that the actual
+false positive rate is lower than the maximum allowed).
+
+Set-summary Element Insertion
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+*rte\_membership\_add(const void *setsum, const void *key, MEMBERSHIP\_TARGET\_TYPE target\_id)*
+
+This function insert an element/key in a set-summary structure, if it fails an
+error is returned. For success the returned value is defferent based on the
+set-summary mode to provide extra information for the users. For both BF and vBF
+modes, a return value of 0 means a successful insert. For HTSS mode, the return
+value in case of success is the index of the inserted entry in the hash bucket.
+For cache mode, in case of successful insert the return value is 0 if the insert
+does not cause an eviction out of the cache (i.e. no overwriting happensto an
+existing entry) and the value of 1 is returned if an existing entry is evicted
+out of the cache.
+
+The input arguements for the function are *setsum* which is the pointer to the
+set-summary structure, *key* which is a pointer to the element/key that needs to
+be added to the set-summary, and, *target\_id* which is the target id associated
+with the key that needs to be added (for the case of BF mode the target id
+should be no larger than 1).
+
+
+Set-summary Element Lookup
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+*rte\_membership\_lookup(const void \*setsum, const void \*key, MEMBERSHIP\_TARGET\_TYPE \*target\_id)*
+
+This function looks up a single key/element in the set-summary structure. It
+returns as soon the first match is found (no further matching of subsequent
+targets, for example for the vBF mode, is performed) the return value is 1 if a
+match is found and 0 otherwise. The arguments for the function are *setsum*
+which is pointer of a set-summary structure, *key* which is a pointer to the
+element/key that needs to be looked up, *target\_id* which is used to return the
+first target set id where the key has matched, if any.
+
+*rte\_membership\_lookup\_bulk(const void \*setsum, const void \*\*keys, uint32\_t num\_keys, MEMBERSHIP\_TARGET\_TYPE \*target\_ids)*
+
+This function looks up a bulk of keys/elements elements simultaneously in the
+set-summary structure, each key lookup returns as soon as the first match is found. The
+return value is the number of keys that find a match. The arguments of the
+function are *setsum* which is a pointer to the set-summary structure, *keys* is
+a pointer to a bulk of keys that are to be looked up, *num\_keys* is the number
+of keys that will are to be looked up, *target\_ids* are the return target set
+ids for the first match found for each of the input keys.
+
+*rte\_membership\_lookup\_multi(const void \*setsum, const void \*key, MEMBERSHIP\_TARGET\_TYPE \*target\_id)*
+
+This function looks up a single key/element in the set-summary structure. It
+returns ALL the matches (possibly more than one) found for this key when it
+is matched against all target sets (This lookup function can be used with the
+vBF and HT modes of set summaries). The return value is the number of matches
+that was found for this key (for both BF and Cache modes the return value
+should be at most 1). The arguments for the function are *setsum*
+which is pointer of a set-summary structure, *key* which is a pointer to the
+element/key that needs to be looked up, *target\_id* which is used to return all
+target set ids where the key has matched, if any.
+
+*rte\_membership\_lookup\_multi\_bulk(const void \*setsum, const void \*\*keys, uint32\_t num\_keys, uint32\_t max\_match\_per\_key, uint32\_t \*match\_count, MEMBERSHIP\_TARGET\_TYPE \*target\_ids)*
+
+This function looks up a bulk of keys/elements elements simultaneously in the
+set-summary structure, each key lookup returns ALL the matches (possibly more
+than one) found for this key when it is matched against all target sets (This
+lookup function can be used with the vBF and HT modes of set summaries). The
+return value is the number of keys that find one or more matches in the
+set-summary structure. The arguments of the
+function are *setsum* which is a pointer to the set-summary structure, *keys* is
+a pointer to a bulk of keys that are to be looked up, *num\_keys* is the number
+of keys that will are to be looked up, *max\_match\_per\_key* is the possible
+max number of matches for each key, *match\_count* which is the returned number
+of matches for all the keys, and *target\_ids* are the return target set
+ids for the first match found for each of the input keys.
+
+
+Set-summary Element Delete [1]_
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+*rte\_membership\_delete(void \*setsum, const void \*key, MEMBERSHIP\_TARGET\_TYPE target\_id)*
+
+This function deletes an element/key from a set-summary structure, if it fails
+an error is returned. The input arguements for the function are *setsum* which
+is the pointer to the set-summary structure, *key* which is a pointer to the
+element/key that needs to be deleted from the set-summary, and, *target\_id*
+which is used with the vBF and HT set-summary types to delete the key from
+certain target ids.
+
+.. [1] Traditional bloom filter does not support proactive deletion. Proactive deletion may require additional implementation and performance overhead.
+
+References
+-----------
+
+[Memship-bloom] B H Bloom, "Space/Time Trade-offs in Hash Coding with Allowable Errors," Communications of the ACM, 1970.
+
+[Memship-survey] A Broder and M Mitzenmacher, "Network Applications of Bloom Filters: A Survey," in Internet Mathematics, 2005.
+
+[Memship-cfilter] B Fan, D G Andersen and M Kaminsky, "Cuckoo Filter: Practically Better Than Bloom," in Conference on emerging Networking Experiments and Technologies, 2014.
+
+[Memship-OvS] B Pfaff, "The Design and Implementation of Open vSwitch," in NSDI, 2015.
\ No newline at end of file
@@ -30,7 +30,6 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
include $(RTE_SDK)/mk/rte.vars.mk
-
DIRS-y += librte_compat
DIRS-$(CONFIG_RTE_LIBRTE_EAL) += librte_eal
DIRS-$(CONFIG_RTE_LIBRTE_RING) += librte_ring
@@ -106,6 +105,8 @@ DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder
DEPDIRS-librte_reorder := librte_eal librte_mempool librte_mbuf
DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump
DEPDIRS-librte_pdump := librte_eal librte_mempool librte_mbuf librte_ether
+DIRS-$(CONFIG_RTE_LIBRTE_MEMBERSHIP) += librte_membership
+DEPDIRS-librte_membership := librte_eal librte_mempool librte_hash librte_sched
ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni
@@ -270,6 +270,7 @@ struct logtype {
{RTE_LOGTYPE_CRYPTODEV, "cryptodev"},
{RTE_LOGTYPE_EFD, "efd"},
{RTE_LOGTYPE_EVENTDEV, "eventdev"},
+ {RTE_LOGTYPE_MEMBERSHIP, "membership"},
{RTE_LOGTYPE_USER1, "user1"},
{RTE_LOGTYPE_USER2, "user2"},
{RTE_LOGTYPE_USER3, "user3"},
@@ -87,6 +87,7 @@ struct rte_logs {
#define RTE_LOGTYPE_CRYPTODEV 17 /**< Log related to cryptodev. */
#define RTE_LOGTYPE_EFD 18 /**< Log related to EFD. */
#define RTE_LOGTYPE_EVENTDEV 19 /**< Log related to eventdev. */
+#define RTE_LOGTYPE_MEMBERSHIP 20/**< Log related to membership. */
/* these log types can be used in an application */
#define RTE_LOGTYPE_USER1 24 /**< User-defined log type 1. */
new file mode 100644
@@ -0,0 +1,48 @@
+# 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.
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_membership.a
+
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3
+
+EXPORT_MAP := rte_membership_version.map
+
+LIBABIVER := 2
+
+# all source are stored in SRCS-y
+SRCS-$(CONFIG_RTE_LIBRTE_MEMBERSHIP) += rte_membership.c rte_membership_ht.c rte_membership_cache.c rte_membership_bf.c rte_membership_vbf.c
+# install includes
+SYMLINK-$(CONFIG_RTE_LIBRTE_MEMBERSHIP)-include := rte_membership.h
+
+include $(RTE_SDK)/mk/rte.lib.mk
new file mode 100644
@@ -0,0 +1,378 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 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.
+ */
+
+#include "rte_membership.h"
+#include "rte_membership_ht.h"
+#include "rte_membership_cache.h"
+#include "rte_membership_vbf.h"
+#include "rte_membership_bf.h"
+
+
+
+#include <rte_memory.h>
+#include <rte_memzone.h>
+#include <rte_malloc.h>
+#include <rte_eal.h>
+#include <rte_eal_memconfig.h>
+#include <rte_errno.h>
+
+TAILQ_HEAD(rte_membership_list, rte_tailq_entry);
+static struct rte_tailq_elem rte_membership_tailq = {
+ .name = "RTE_MEMBERSHIP",
+};
+EAL_REGISTER_TAILQ(rte_membership_tailq)
+
+void
+rte_membership_free(void *ss)
+{
+ struct rte_membership_setsum *setsum = ss;
+ if (setsum == NULL)
+ return;
+ switch (setsum->type) {
+ case SETSUM_TYPE_HT:
+ rte_membership_free_ht(setsum);
+ break;
+ case SETSUM_TYPE_CACHE:
+ rte_membership_free_cache(setsum);
+ break;
+ case SETSUM_TYPE_BF:
+ rte_membership_free_bf(setsum);
+ break;
+ case SETSUM_TYPE_VBF:
+ rte_membership_free_vbf(setsum);
+ break;
+ default:
+ break;
+ }
+ rte_free(setsum);
+}
+
+
+void *
+rte_membership_create(const struct rte_membership_parameters *params)
+{
+ struct rte_tailq_entry *te;
+ struct rte_membership_list *membership_list = NULL;
+ struct rte_membership_setsum *setsum = NULL;
+ int ret;
+
+ if (params == NULL) {
+ return NULL;
+ }
+
+ membership_list = RTE_TAILQ_CAST(rte_membership_tailq.head,
+ rte_membership_list);
+
+ rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
+
+ TAILQ_FOREACH(te, membership_list, next) {
+ setsum = (struct rte_membership_setsum *) te->data;
+ if (strncmp(params->name, setsum->name, RTE_MEMBERSHIP_NAMESIZE) == 0)
+ break;
+ }
+ setsum = NULL;
+ if (te != NULL) {
+ rte_errno = EEXIST;
+ te = NULL;
+ goto error_unlock_exit;
+ }
+
+ te = rte_zmalloc("MEMBERSHIP_TAILQ_ENTRY", sizeof(*te), 0);
+ if (te == NULL){
+ RTE_LOG(ERR, MEMBERSHIP, "tailq entry allocation failed\n");
+ goto error_unlock_exit;
+ }
+
+
+
+ /* Create a new setsum structure */
+ setsum = (struct rte_membership_setsum *) rte_zmalloc_socket(params->name,
+ sizeof(struct rte_membership_setsum),
+ RTE_CACHE_LINE_SIZE,
+ params->socket_id);
+
+ if (setsum == NULL) {
+ RTE_LOG(ERR, MEMBERSHIP, "Create setsummary failed\n");
+ goto error_unlock_exit;
+ }
+
+ setsum->type = params->type;
+ setsum->socket_id = params->socket_id;
+ setsum->key_len = params->key_len;
+ setsum->num_target = params->num_target;
+ setsum->num_keys = params->num_keys;
+ setsum->name = params->name;
+ setsum->false_postive_rate = params->false_postive_rate;
+ setsum->prim_hash_seed = params->prim_hash_seed;
+ setsum->sec_hash_seed = params->sec_hash_seed;
+
+ switch (setsum->type) {
+ case SETSUM_TYPE_HT:
+ ret = rte_membership_create_ht(setsum);
+ break;
+ case SETSUM_TYPE_CACHE:
+ ret = rte_membership_create_cache(setsum);
+ break;
+ case SETSUM_TYPE_BF:
+ ret = rte_membership_create_bf(setsum);
+ break;
+ case SETSUM_TYPE_VBF:
+ ret = rte_membership_create_vbf(setsum);
+ break;
+ default:
+ goto error_unlock_exit;
+ }
+ if (ret < 0)
+ goto error_unlock_exit;
+
+ RTE_LOG(DEBUG, EFD, "Creating an setsummary table with mode %u\n",
+ setsum->type);
+
+ te->data = (void *)setsum;
+ TAILQ_INSERT_TAIL(membership_list, te, next);
+ rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
+ return setsum;
+
+error_unlock_exit:
+ rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
+ rte_membership_free(setsum);
+ return NULL;
+}
+
+
+int
+rte_membership_add(const void *ss, const void *key,
+ MEMBERSHIP_TARGET_TYPE target_id)
+{
+
+ const struct rte_membership_setsum *setsum = ss;
+
+ if (setsum == NULL || key == NULL)
+ return -EINVAL;
+ int ret = 0;
+ switch (setsum->type) {
+ case SETSUM_TYPE_HT:
+ ret = rte_membership_add_ht(setsum, key, target_id);
+ break;
+ case SETSUM_TYPE_CACHE:
+ ret = rte_membership_add_cache(setsum, key, target_id);
+ break;
+ case SETSUM_TYPE_BF:
+ ret = rte_membership_add_bf(setsum, key, target_id);
+ break;
+ case SETSUM_TYPE_VBF:
+ ret = rte_membership_add_vbf(setsum, key, target_id);
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+
+int
+rte_membership_lookup(const void *ss, const void *key,
+ MEMBERSHIP_TARGET_TYPE *target_id)
+{
+ const struct rte_membership_setsum *setsum = ss;
+ if (setsum == NULL || key == NULL || target_id == NULL)
+ return -EINVAL;
+
+ int ret = 0;
+ switch (setsum->type) {
+ case SETSUM_TYPE_HT:
+ ret = rte_membership_lookup_ht(setsum, key, target_id);
+ break;
+ case SETSUM_TYPE_CACHE:
+ ret = rte_membership_lookup_cache(setsum, key, target_id);
+ break;
+ case SETSUM_TYPE_BF:
+ ret = rte_membership_lookup_bf(setsum, key, target_id);
+ break;
+ case SETSUM_TYPE_VBF:
+ ret = rte_membership_lookup_vbf(setsum, key, target_id);
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+
+int
+rte_membership_lookup_bulk(const void *ss, const void **keys, uint32_t num_keys,
+ MEMBERSHIP_TARGET_TYPE *target_ids)
+{
+ const struct rte_membership_setsum *setsum = ss;
+ if (setsum == NULL || keys == NULL || target_ids == NULL)
+ return -EINVAL;
+
+ int ret = 0;
+ switch (setsum->type) {
+ case SETSUM_TYPE_HT:
+ ret = rte_membership_lookup_bulk_ht(setsum, keys, num_keys,
+ target_ids);
+ break;
+ case SETSUM_TYPE_CACHE:
+ ret = rte_membership_lookup_bulk_cache(setsum, keys, num_keys,
+ target_ids);
+ break;
+ case SETSUM_TYPE_BF:
+ ret = rte_membership_lookup_bulk_bf(setsum, keys, num_keys,
+ target_ids);
+ break;
+ case SETSUM_TYPE_VBF:
+ ret = rte_membership_lookup_bulk_vbf(setsum, keys, num_keys,
+ target_ids);
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+int
+rte_membership_lookup_multi(const void *ss, const void *key,
+ MEMBERSHIP_TARGET_TYPE *target_id)
+{
+ const struct rte_membership_setsum *setsum = ss;
+ if (setsum == NULL || key == NULL || target_id == NULL)
+ return -EINVAL;
+ int ret=0;
+ switch (setsum->type) {
+ case SETSUM_TYPE_HT:
+ ret = rte_membership_lookup_multi_ht(setsum, key, target_id);
+ break;
+ case SETSUM_TYPE_CACHE:
+ ret = rte_membership_lookup_multi_cache(setsum, key, target_id);
+ break;
+ case SETSUM_TYPE_BF:
+ ret = rte_membership_lookup_multi_bf(setsum, key, target_id);
+ break;
+ case SETSUM_TYPE_VBF:
+ ret = rte_membership_lookup_multi_vbf(setsum, key, target_id);
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+
+int
+rte_membership_lookup_multi_bulk(const void *ss, const void **keys,
+ uint32_t num_keys, uint32_t max_match_per_key, uint32_t *match_count,
+ MEMBERSHIP_TARGET_TYPE *target_ids)
+{
+ const struct rte_membership_setsum *setsum = ss;
+ if (setsum == NULL || keys == NULL || target_ids == NULL ||
+ match_count == NULL)
+ return -EINVAL;
+ int ret = 0;
+ switch (setsum->type) {
+ case SETSUM_TYPE_HT:
+ ret = rte_membership_lookup_multi_bulk_ht(setsum, keys, num_keys,
+ max_match_per_key, match_count, target_ids);
+ break;
+ case SETSUM_TYPE_CACHE:
+ ret = rte_membership_lookup_multi_bulk_cache(setsum, keys, num_keys,
+ max_match_per_key, match_count, target_ids);
+ break;
+ case SETSUM_TYPE_BF:
+ ret = rte_membership_lookup_multi_bulk_bf(setsum, keys, num_keys,
+ max_match_per_key, match_count, target_ids);
+ break;
+ case SETSUM_TYPE_VBF:
+ ret = rte_membership_lookup_multi_bulk_vbf(setsum, keys, num_keys,
+ max_match_per_key, match_count, target_ids);
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+
+int
+rte_membership_delete(void *ss, const void *key,
+ MEMBERSHIP_TARGET_TYPE target_id)
+{
+ struct rte_membership_setsum *setsum = ss;
+ if (setsum == NULL || key == NULL)
+ return -EINVAL;
+ int ret = 0;
+ switch (setsum->type) {
+ case SETSUM_TYPE_HT:
+ ret = rte_membership_delete_ht(setsum, key, target_id);
+ break;
+ case SETSUM_TYPE_CACHE:
+ ret = rte_membership_delete_cache(setsum, key, target_id);
+ break;
+ case SETSUM_TYPE_BF:
+ case SETSUM_TYPE_VBF:
+ default:
+ return -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+
+void
+rte_membership_reset(const void *ss)
+{
+ const struct rte_membership_setsum *setsum = ss;
+ if (setsum == NULL)
+ return;
+ switch (setsum->type) {
+ case SETSUM_TYPE_HT:
+ rte_membership_reset_ht(setsum);
+ break;
+ case SETSUM_TYPE_CACHE:
+ rte_membership_reset_cache(setsum);
+ break;
+ case SETSUM_TYPE_BF:
+ rte_membership_reset_bf(setsum);
+ break;
+ case SETSUM_TYPE_VBF:
+ rte_membership_reset_vbf(setsum);
+ break;
+ default:
+ break;
+ }
+}
\ No newline at end of file
new file mode 100644
@@ -0,0 +1,321 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 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.
+ */
+
+
+
+/**
+ * @file
+ * RTE Membership Library
+ *
+ * The membership library provides structures serving as set summaries of sets.
+ * There are in total four modes are provided: bloom filter (BF), vector bloom
+ * filter (vBF), cache, and hash table-based (HT) modes.
+ *
+ * Each of the mode has different behaviors but they all can be used to test keys
+ * for their memberships of one or more sets. Detailed behavior of each mode
+ * please refer to the API document.
+ */
+
+
+
+#ifndef _RTE_MEMBERSHIP_H_
+#define _RTE_MEMBERSHIP_H_
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include <stdio.h>
+#include <stdint.h>
+#include <rte_jhash.h>
+
+/* The maximum set count is 2^16-1 (we reserve 0 for invalid target) */
+typedef uint16_t MEMBERSHIP_TARGET_TYPE;
+/* Invalid or empty set ID uses 0 */
+#define RTE_MEMBERSHIP_NO_MATCH 0
+#define RTE_MEMBERSHIP_LOOKUP_BULK_MAX 16
+#define MEMBERSHIP_MAX_PUSHES 100
+
+#define MEMBERSHIP_BUCKET_ENTRIES 16
+
+
+
+/* Maximum number of characters in setsum name. */
+#define RTE_MEMBERSHIP_NAMESIZE 32
+
+/* This bit is used to choose which bucket to replace entry */
+#define MEMBERSHIP_EVICT_CHOOSE (1 << MEMBERSHIP_BUCKET_ENTRIES)
+
+#define MEMBERSHIP_PRIM_HASH(key, key_len, seed) \
+ (uint32_t)(rte_jhash(key, key_len, seed))
+
+#define MEMBERSHIP_SEC_HASH(key, key_len, seed) \
+ (uint32_t)(rte_jhash(key, key_len, seed))
+
+
+typedef uint16_t SIG_TYPE; /* signature size is 16 bit */
+#define SIG_BITMASK 0xffff /* signature mask, 16 bit */
+
+struct rte_membership_setsum;
+struct rte_membership_parameters;
+
+
+/* All different types of set summaries */
+enum rte_membership_setsum_type {
+ SETSUM_TYPE_HT = 0,
+ SETSUM_TYPE_CACHE,
+ SETSUM_TYPE_BF,
+ SETSUM_TYPE_VBF
+};
+
+
+
+struct rte_membership_setsum {
+ enum rte_membership_setsum_type type;
+ const char *name;
+ uint32_t key_len;
+ /* cache is only relevant to HT based set summary */
+ uint32_t num_keys;
+ /* num_target and false_postive_rate only relevant to BF based set summary */
+ uint32_t num_target;
+ float false_postive_rate;
+
+ uint32_t prim_hash_seed;
+ uint32_t sec_hash_seed;
+
+ int socket_id;
+
+ void *ss;
+};
+
+
+/**
+ * Parameters used when creating the set summary table.
+ */
+struct rte_membership_parameters {
+ const char *name; /* Name of the hash. */
+ enum rte_membership_setsum_type type;
+ uint32_t num_keys; /* Total hash table entries. */
+ uint32_t key_len; /* Length of hash key. */
+
+ /* num_target and false_postive_rate only relevant with BF based set summary */
+ uint32_t num_target;
+ float false_postive_rate;
+
+ uint32_t prim_hash_seed;
+ uint32_t sec_hash_seed;
+
+ int socket_id; /* NUMA Socket ID for memory. */
+};
+
+
+
+/**
+ * Create setsummary (SS) table
+ *
+ * @param params
+ * parameters to initialize the setsummary.
+ * @return
+ * return the pointer to the setsummary.
+ * return value is NULL if the creation failed.
+ */
+
+void *
+rte_membership_create(const struct rte_membership_parameters *params);
+
+
+
+/**
+ * Lookup key in setsummary (SS) table
+ * Single key lookup and return as soon as the first match found
+ * @param setsum
+ * pointer of a setsummary table
+ * @param key
+ * pointer of the key that needs to lookup
+ * @param target_id
+ * returned target set id.
+ * @return
+ * return 1 for found a match and 0 for not found a match
+ */
+
+int
+rte_membership_lookup(const void *setsum,
+ const void *key, MEMBERSHIP_TARGET_TYPE *target_id);
+
+
+/**
+ * lookup bulk of keys in setsummary (SS) table
+ * Each key lookup returns as soon as the first match found
+ * @param setsum
+ * Pointer of a setsummary table
+ * @param keys
+ * Pointer of bulk of keys that to be lookup
+ * @param num_keys
+ * Number of keys that will be lookup
+ * @param target_ids
+ * Return target ids for all the keys to the array.
+ * User should preallocate array that can contain the maximum possible number
+ * of matches.
+ * @return
+ * The number of keys that find a match.
+ */
+
+
+int
+rte_membership_lookup_bulk(const void *setsum,
+ const void **keys, uint32_t num_keys, MEMBERSHIP_TARGET_TYPE *target_ids);
+
+
+
+
+/**
+ * Lookup a key in setsummary (SS) table for multiple matches
+ * The key lookup will find all matched entries (multiple match)
+ * This is for VBF and HT modes of setsummaries.
+ * @param setsum
+ * pointer of a setsummary struct
+ * @param key
+ * The key that to be lookup
+ * @param target_id
+ * returned target ids for all the matches of the key
+ * @return
+ * The number of matches that found for the key.
+ * For BF and Cache mode, the number should be at most 1
+ */
+
+int
+rte_membership_lookup_multi(const void *setsum,
+ const void *key, MEMBERSHIP_TARGET_TYPE *target_id);
+
+
+
+
+/**
+ * Lookup a bulk of keys in setsummary (SS) table for multiple matches
+ * Each key lookup will find all matched entries (multiple match)
+ * This is for VBF and HT type of setsummaries.
+ * @param setsum
+ * pointer of a setsummary struct
+ * @param keys
+ * The keys that to be lookup
+ * @param num_keys
+ * The number of keys that will be lookup
+ * @param max_match_per_key
+ * The possible max number of matches for each key.
+ * @param match_count
+ * The number of match for all the keys.
+ * @param target_ids
+ * Return target ids for all the matches of all keys
+ * @return
+ * The number of keys that find one or more matches in the table.
+ */
+
+int
+rte_membership_lookup_multi_bulk(const void *setsum,
+ const void **keys, uint32_t num_keys, uint32_t max_match_per_key,
+ uint32_t *match_count,
+ MEMBERSHIP_TARGET_TYPE *target_ids);
+
+/**
+ * Insert key to setsummary (SS) table
+ *
+ * @param setsum
+ * pointer of a setsummary table
+ * @param key
+ * the key that needs to be added
+ * @param target_id
+ * The target id associated with the key that needs to be added.
+ * Note that for BF mode the target id should no larger than 1.
+ * @return
+ * Return error code if fail.
+ * For success we return different value for different mode for providing
+ * extra information for the users.
+ * Return 0 for BF. Return 0 for Cache mode if the add does not cause
+ * eviction, return 1 otherwise. Return the index of the inserted entry of the
+ * bucket for HT mode. Return 0 for vBF mode.
+ */
+
+int
+rte_membership_add(const void *setsum, const void *key,
+ MEMBERSHIP_TARGET_TYPE target_id);
+
+
+/**
+ * De-allocate all memory used by set summary table
+ * @param setsum
+ * Pointer to the set summary
+ */
+void
+rte_membership_free(void *setsum);
+
+
+
+/**
+ * Reset the setsummary tables. E.g. reset bits to be 0 in BF,
+ * reset target_id in each entry to be no_match
+ * @param setsum
+ * Pointer to the set summary
+ */
+void
+rte_membership_reset(const void *setsum);
+
+
+
+
+/**
+ * Detele items from the set summary
+ * @param setsum
+ * Pointer to the set summary.
+ * @param key
+ * The key to be deleted.
+ * @param target_id
+ * For HT or VBF type of setsummary, we pass this argument to only delete
+ * keys with certain target_id.
+ * @return
+ * If no entry found to delete, an error code could be returned.
+ */
+
+int
+rte_membership_delete(void *setsum, const void *key,
+ MEMBERSHIP_TARGET_TYPE target_id);
+
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_MEMBERSHIP_H_ */
\ No newline at end of file
new file mode 100644
@@ -0,0 +1,254 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright (c) 2012, Jyri J. Virkki
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. 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.
+ *
+ * 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
+ * HOLDER 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.
+ */
+
+
+/*
+ *Some of the code is modified from Jyri's libbloom library
+ *(https://github.com/jvirkki/libbloom) which is under BSD license
+ */
+
+#include "rte_membership.h"
+#include "rte_membership_bf.h"
+#include <math.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+
+#include <rte_bitmap.h>
+#include <rte_malloc.h>
+#include <rte_memory.h>
+
+
+
+struct rte_membership_bf *
+__membership_create_bf(const struct rte_membership_setsum *ss)
+{
+
+ struct rte_membership_bf *bloom;
+ double num;
+ double denom = 0.480453013918201; /* ln(2)^2 */
+ double dentries;
+ uint32_t bmp_mem_size;
+
+
+ if (ss->num_keys < 1 || ss->false_postive_rate == 0) {
+ return NULL;
+ }
+ bloom = rte_zmalloc_socket(NULL, sizeof(struct rte_membership_bf),
+ RTE_CACHE_LINE_SIZE, ss->socket_id);
+ if (bloom == NULL) {
+ RTE_LOG(ERR, EAL, "Bitmap init error\n");
+ return NULL;
+ }
+ bloom->entries = ss->num_keys;
+ bloom->error = ss->false_postive_rate;
+ num = log(bloom->error);
+
+ bloom->bpe = -(num / denom);
+
+ dentries = (double)(bloom->entries);
+ bloom->bits = rte_align32pow2((int)(dentries * bloom->bpe));
+ bloom->bucket_bitmask = bloom->bits - 1;
+
+ bloom->num_hashes = (int)ceil(0.693147180559945 * bloom->bpe); /* ln(2) */
+
+ bmp_mem_size = rte_bitmap_get_memory_footprint(bloom->bits);
+
+ bloom->bmp_array = rte_zmalloc(NULL, bmp_mem_size, RTE_CACHE_LINE_SIZE);
+ if (bloom->bmp_array == NULL) {
+ rte_free(bloom);
+ return NULL;
+ }
+
+ bloom->bmp = rte_bitmap_init(bloom->bits, bloom->bmp_array, bmp_mem_size);
+ if (bloom->bmp == NULL) {
+ RTE_LOG(ERR, EAL, "Bitmap init error\n");
+ rte_free(bloom->bmp_array);
+ rte_free(bloom);
+ return NULL;
+ }
+ return bloom;
+}
+
+
+
+int
+rte_membership_create_bf(struct rte_membership_setsum *setsum)
+{
+ struct rte_membership_bf *bloom =
+ __membership_create_bf((const struct rte_membership_setsum *)setsum);
+
+ if(bloom != NULL)
+ setsum->ss = bloom;
+ else
+ return -ENOMEM;
+ return 0;
+}
+
+
+int
+rte_membership_lookup_bf(const struct rte_membership_setsum *setsum,
+ const void *key, MEMBERSHIP_TARGET_TYPE *target_id)
+{
+ struct rte_membership_bf *bloom = setsum->ss;
+ uint32_t key_len = setsum->key_len;
+ uint32_t prim_hash_seed = setsum->prim_hash_seed;
+ uint32_t sec_hash_seed = setsum->sec_hash_seed;
+ uint32_t a = MEMBERSHIP_PRIM_HASH(key, key_len, prim_hash_seed);
+ uint32_t b = MEMBERSHIP_SEC_HASH(key, key_len, sec_hash_seed);
+ uint32_t x;
+ uint32_t i;
+
+ struct rte_bitmap *bmp = bloom->bmp;
+
+ for (i = 0; i < bloom->num_hashes; i++) {
+ x = (a + i*b) & bloom->bucket_bitmask;
+ if (rte_bitmap_get(bmp, x) == 0) {
+ return 0;
+ }
+ }
+ *target_id = 1;
+ return 1;
+}
+
+
+int
+rte_membership_lookup_multi_bf(const struct rte_membership_setsum *setsum,
+ const void *key, MEMBERSHIP_TARGET_TYPE *target_id)
+{
+ int ret = rte_membership_lookup_bf(setsum, key, target_id);
+ return ret;
+}
+
+
+int
+rte_membership_lookup_bulk_bf(const struct rte_membership_setsum* setsum,
+ const void** keys, uint32_t num_keys, MEMBERSHIP_TARGET_TYPE* target_id)
+{
+ struct rte_membership_bf* bloom = setsum->ss;
+ uint32_t key_len = setsum->key_len;
+ uint32_t prim_hash_seed = setsum->prim_hash_seed;
+ uint32_t sec_hash_seed = setsum->sec_hash_seed;
+
+ uint32_t i, j;
+ uint32_t x, a, b;
+ int ret = 0;
+ struct rte_bitmap *bmp = bloom->bmp;
+ for (i = 0; i < num_keys; i++) {
+ a = MEMBERSHIP_PRIM_HASH(keys[i], key_len, prim_hash_seed);
+ b = MEMBERSHIP_SEC_HASH(keys[i], key_len, sec_hash_seed);
+ for (j = 0; j < bloom->num_hashes; j++) {
+ x = (a + j * b) & bloom->bucket_bitmask;
+ if (rte_bitmap_get(bmp, x) == 0) {
+ target_id[i] = RTE_MEMBERSHIP_NO_MATCH;
+ break;
+ }
+ }
+ if (j == bloom->num_hashes) {
+ target_id[i] = 1;
+ ret++;
+ }
+ }
+ return ret;
+}
+
+int
+rte_membership_lookup_multi_bulk_bf(const struct rte_membership_setsum *setsum,
+ const void **keys, uint32_t num_keys, uint32_t match_per_key,
+ uint32_t *match_count, MEMBERSHIP_TARGET_TYPE *target_ids)
+{
+
+ int ret;
+ uint32_t i;
+ MEMBERSHIP_TARGET_TYPE target_id[num_keys];
+ ret = rte_membership_lookup_bulk_bf(setsum, keys, num_keys, target_id);
+ for (i = 0; i < num_keys; i++) {
+ if (target_id[i] != RTE_MEMBERSHIP_NO_MATCH) {
+ match_count[i] = 1;
+ target_ids[i*match_per_key]= target_id[i];
+ }
+ else {
+ match_count[i] = 0;
+ }
+ }
+ return ret;
+}
+
+int
+rte_membership_add_bf(const struct rte_membership_setsum *setsum,
+ const void *key, MEMBERSHIP_TARGET_TYPE target_id)
+{
+ /* bloomfilter only allows 1 bit target, hit or not since only 1 set */
+ if (target_id > 1)
+ return -EINVAL;
+ struct rte_membership_bf *bloom = setsum->ss;
+ uint32_t key_len = setsum->key_len;
+ uint32_t prim_hash_seed = setsum->prim_hash_seed;
+ uint32_t sec_hash_seed = setsum->sec_hash_seed;
+ uint32_t a = MEMBERSHIP_PRIM_HASH(key, key_len, prim_hash_seed);
+ uint32_t b = MEMBERSHIP_SEC_HASH(key, key_len, sec_hash_seed);
+ uint32_t x;
+ uint32_t i;
+
+ struct rte_bitmap *bmp = bloom->bmp;
+
+ for (i = 0; i < bloom->num_hashes; i++) {
+ x = (a + i * b) & bloom->bucket_bitmask;
+ rte_bitmap_set(bmp, x);
+ }
+ return 0;
+}
+
+
+void
+rte_membership_free_bf(struct rte_membership_setsum *setsum)
+{
+ struct rte_membership_bf *bloom = setsum->ss;
+ if (bloom != NULL) {
+ rte_free(bloom->bmp_array);
+ rte_free(bloom);
+ }
+}
+
+
+void
+rte_membership_reset_bf(const struct rte_membership_setsum *setsum)
+{
+ struct rte_membership_bf *bloom = setsum->ss;
+ if (bloom != NULL) {
+ rte_bitmap_reset(bloom->bmp_array);
+ }
+
+}
\ No newline at end of file
new file mode 100644
@@ -0,0 +1,99 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 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.
+ */
+
+#ifndef _RTE_MEMBERSHIP_BF_H_
+#define _RTE_MEMBERSHIP_BF_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rte_bitmap.h>
+
+struct rte_membership_bf
+{
+ int entries; /* number of entries expected to store in filter */
+ double error; /* expected false positive rate */
+ double bpe; /* theoretical bit per entry */
+ unsigned bits; /* actual number of bits allocated (rounded to 2pow) */
+ unsigned num_hashes; /* number of hash functions needed (optimal) */
+
+ unsigned bucket_bitmask;
+
+ void *bmp_array; /* memory chunk holding bmp */
+ struct rte_bitmap *bmp;
+};
+
+
+struct rte_membership_bf *
+__membership_create_bf(const struct rte_membership_setsum *ss);
+
+int
+rte_membership_create_bf(struct rte_membership_setsum *ss);
+
+int
+rte_membership_lookup_bf(const struct rte_membership_setsum *setsum,
+ const void *key, MEMBERSHIP_TARGET_TYPE* target_id);
+
+int
+rte_membership_lookup_multi_bf(const struct rte_membership_setsum *setsum,
+ const void *key, MEMBERSHIP_TARGET_TYPE *target_id);
+
+
+int
+rte_membership_lookup_bulk_bf(const struct rte_membership_setsum *setsum,
+ const void **key, uint32_t num_keys, MEMBERSHIP_TARGET_TYPE *target_id);
+
+
+int
+rte_membership_lookup_multi_bulk_bf(const struct rte_membership_setsum *setsum,
+ const void **keys, uint32_t num_keys, uint32_t match_per_key,
+ uint32_t *match_count,
+ MEMBERSHIP_TARGET_TYPE *target_ids);
+
+int
+rte_membership_add_bf(const struct rte_membership_setsum *setsum,
+ const void *key, MEMBERSHIP_TARGET_TYPE target_id);
+
+
+void
+rte_membership_free_bf(struct rte_membership_setsum *ss);
+
+
+void
+rte_membership_reset_bf(const struct rte_membership_setsum *setsum);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _RTE_MEMBERSHIP_BF_H_ */
new file mode 100644
@@ -0,0 +1,345 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 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.
+ */
+
+#include "rte_membership.h"
+#include "rte_membership_cache.h"
+
+#include <rte_errno.h>
+#include <rte_malloc.h>
+#include <rte_prefetch.h>
+#include <rte_random.h>
+
+
+/* The bucket struct for cuckoo distributor*/
+struct membership_cache_bucket {
+ SIG_TYPE sigs[MEMBERSHIP_BUCKET_ENTRIES]; /*2-byte signature*/
+ MEMBERSHIP_TARGET_TYPE targets[MEMBERSHIP_BUCKET_ENTRIES];/*2-byte target*/
+} __attribute__ ((packed));
+
+
+struct membership_cache_ss {
+ struct membership_cache_bucket* buckets; /*buckets array*/
+ uint32_t bucket_cnt;
+ uint32_t bucket_mask;
+};
+
+
+
+int
+rte_membership_create_cache(struct rte_membership_setsum *ss){
+ uint32_t i, j;
+ const uint32_t num_buckets = rte_align32pow2(ss->num_keys) /
+ MEMBERSHIP_BUCKET_ENTRIES;
+ struct membership_cache_ss* t;
+
+ t = (struct membership_cache_ss *)rte_zmalloc_socket(NULL,
+ sizeof(struct membership_cache_ss),
+ RTE_CACHE_LINE_SIZE, ss->socket_id);
+
+
+ struct membership_cache_bucket* buckets = rte_zmalloc_socket(NULL,
+ num_buckets * sizeof(struct membership_cache_bucket),
+ RTE_CACHE_LINE_SIZE, ss->socket_id);
+
+ t->buckets = buckets;
+ t->bucket_cnt=num_buckets;
+ t->bucket_mask = num_buckets - 1;
+ ss->ss = t;
+
+ for( i=0; i<num_buckets; i++){
+ for( j=0; j<MEMBERSHIP_BUCKET_ENTRIES; j++){
+ buckets[i].targets[j]=RTE_MEMBERSHIP_NO_MATCH;
+ }
+ }
+ return 0;
+}
+
+
+int
+rte_membership_lookup_cache(const struct rte_membership_setsum *setsum,
+ const void *key, MEMBERSHIP_TARGET_TYPE *target_id)
+{
+
+ int32_t i;
+ struct membership_cache_ss* ht = setsum->ss;
+ uint32_t prim_hash_seed = setsum->prim_hash_seed;
+ uint32_t sec_hash_seed = setsum->sec_hash_seed;
+ uint32_t bucket_mask = ht->bucket_mask;
+ struct membership_cache_bucket* buckets = ht->buckets;
+ uint32_t key_len = setsum->key_len;
+
+
+ SIG_TYPE tmp_sig = MEMBERSHIP_PRIM_HASH(key, key_len, prim_hash_seed) &
+ SIG_BITMASK;
+
+ uint32_t hash_val = MEMBERSHIP_SEC_HASH(key, key_len, sec_hash_seed);
+ uint32_t prim_bucket = hash_val & bucket_mask;
+ uint32_t sec_bucket = (hash_val >> 16) & bucket_mask;
+
+
+ for (i = 0; i < MEMBERSHIP_BUCKET_ENTRIES; i++) {
+ if(tmp_sig == buckets[prim_bucket].sigs[i] &&
+ buckets[prim_bucket].targets[i] != RTE_MEMBERSHIP_NO_MATCH) {
+ *target_id = buckets[prim_bucket].targets[i];
+ return 1;
+ }
+ }
+ for (i = 0; i < MEMBERSHIP_BUCKET_ENTRIES; i++) {
+ if(tmp_sig == buckets[sec_bucket].sigs[i] &&
+ buckets[sec_bucket].targets[i] != RTE_MEMBERSHIP_NO_MATCH) {
+ *target_id = buckets[sec_bucket].targets[i];
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int
+rte_membership_lookup_multi_cache(const struct rte_membership_setsum* setsum,
+ const void* key, MEMBERSHIP_TARGET_TYPE* target_id)
+{
+
+ int ret = rte_membership_lookup_cache(setsum, key, target_id);
+ return ret;
+}
+
+
+
+
+int
+rte_membership_lookup_bulk_cache(const struct rte_membership_setsum *setsum,
+ const void **keys, uint32_t num_keys, MEMBERSHIP_TARGET_TYPE *target_id)
+{
+ uint32_t i,j;
+ int ret = 0;
+ struct membership_cache_ss* ht = setsum->ss;
+ uint32_t prim_hash_seed = setsum->prim_hash_seed;
+ uint32_t sec_hash_seed = setsum->sec_hash_seed;
+ uint32_t bucket_mask = ht->bucket_mask;
+ struct membership_cache_bucket* buckets = ht->buckets;
+ uint32_t key_len = setsum->key_len;
+
+ SIG_TYPE tmp_sig[RTE_MEMBERSHIP_LOOKUP_BULK_MAX];
+ const struct membership_cache_bucket*
+ prim_buckets[RTE_MEMBERSHIP_LOOKUP_BULK_MAX];
+ const struct membership_cache_bucket*
+ sec_buckets[RTE_MEMBERSHIP_LOOKUP_BULK_MAX];
+
+ for( i=0; i<num_keys; i++){
+ tmp_sig[i] = MEMBERSHIP_PRIM_HASH(keys[i], key_len, prim_hash_seed) &
+ SIG_BITMASK;
+ uint32_t hash_val = MEMBERSHIP_SEC_HASH(keys[i], key_len, sec_hash_seed);
+ uint32_t prim_bucket = hash_val & bucket_mask;
+ uint32_t sec_bucket = (hash_val >> 16) & bucket_mask;
+ prim_buckets[i] = &buckets[prim_bucket];
+ sec_buckets[i] = &buckets[sec_bucket];
+ rte_prefetch0(prim_buckets[i]);
+ rte_prefetch0(sec_buckets[i]);
+ }
+
+
+ for (i = 0; i < num_keys; i++ ) {
+ for (j = 0; j < MEMBERSHIP_BUCKET_ENTRIES; j++) {
+ if(tmp_sig[i] == prim_buckets[i]->sigs[j] &&
+ prim_buckets[i]->targets[j] != RTE_MEMBERSHIP_NO_MATCH) {
+ target_id[i] = prim_buckets[i]->targets[j];
+ ret++;
+ break;
+ }
+ }
+
+ if (j == MEMBERSHIP_BUCKET_ENTRIES) {
+ for (j = 0; j < MEMBERSHIP_BUCKET_ENTRIES; j++) {
+ if(tmp_sig[i] == sec_buckets[i]->sigs[j] &&
+ sec_buckets[i]->targets[j] != RTE_MEMBERSHIP_NO_MATCH) {
+ target_id[i] = sec_buckets[i]->targets[j];
+ ret++;
+ break;
+ }
+ }
+ }
+ if (j == MEMBERSHIP_BUCKET_ENTRIES) {
+ target_id[i] = RTE_MEMBERSHIP_NO_MATCH;
+ }
+ }
+ return ret;
+}
+
+
+int
+rte_membership_lookup_multi_bulk_cache(const struct rte_membership_setsum *setsum,
+ const void **keys, uint32_t num_keys, uint32_t match_per_key,
+ uint32_t *match_count, MEMBERSHIP_TARGET_TYPE *target_ids)
+{
+ int ret;
+ uint32_t i;
+ MEMBERSHIP_TARGET_TYPE target_id[num_keys];
+ ret = rte_membership_lookup_bulk_cache(setsum, keys, num_keys, target_id);
+ for (i = 0; i < num_keys; i++) {
+ if (target_id[i] != RTE_MEMBERSHIP_NO_MATCH) {
+ match_count[i] = 1;
+ target_ids[i*match_per_key] = target_id[i];
+ }
+ else {
+ match_count[i] = 0;
+ }
+ }
+ return ret;
+}
+
+
+
+int
+rte_membership_add_cache(const struct rte_membership_setsum *setsum,
+ const void *key, MEMBERSHIP_TARGET_TYPE target_id)
+{
+ int i;
+ struct membership_cache_ss* ht = setsum->ss;
+ uint32_t prim_hash_seed = setsum->prim_hash_seed;
+ uint32_t sec_hash_seed = setsum->sec_hash_seed;
+ uint32_t bucket_mask = ht->bucket_mask;
+ struct membership_cache_bucket* buckets = ht->buckets;
+ uint32_t key_len = setsum->key_len;
+
+ SIG_TYPE tmp_sig = MEMBERSHIP_PRIM_HASH(key, key_len, prim_hash_seed) &
+ SIG_BITMASK;
+
+ uint32_t hash_val = MEMBERSHIP_SEC_HASH(key, key_len, sec_hash_seed);
+ uint32_t prim_bucket = hash_val & bucket_mask;
+ uint32_t sec_bucket = (hash_val >> 16) & bucket_mask;
+
+ /* Check if the signature already in the two buckets */
+
+ for (i = 0; i < MEMBERSHIP_BUCKET_ENTRIES; i++) {
+ if (buckets[prim_bucket].sigs[i] == tmp_sig) {
+ buckets[prim_bucket].targets[i] = target_id;
+ return 0;
+ }
+ if (buckets[sec_bucket].sigs[i] == tmp_sig) {
+ buckets[sec_bucket].targets[i] = target_id;
+ return 0;
+ }
+ }
+
+
+ /* If not then insert into one slot (prefer empty slot) */
+ for (i = 0; i < MEMBERSHIP_BUCKET_ENTRIES; i++) {
+ if(buckets[prim_bucket].targets[i] == RTE_MEMBERSHIP_NO_MATCH){
+ buckets[prim_bucket].sigs[i] = tmp_sig;
+ buckets[prim_bucket].targets[i] = target_id;
+ return 0;
+ }
+ }
+
+ /* Primary location full */
+
+ for (i = 0; i < MEMBERSHIP_BUCKET_ENTRIES; i++) {
+ if(buckets[sec_bucket].targets[i] == RTE_MEMBERSHIP_NO_MATCH){
+ buckets[sec_bucket].sigs[i] = tmp_sig;
+ buckets[sec_bucket].targets[i] = target_id;
+ return 0;
+ }
+ }
+
+ /* Then we should evict someone. */
+ /* currently it is a random eviction policy */
+
+ uint64_t random = rte_rand();
+ uint32_t evict_idx = random & (MEMBERSHIP_BUCKET_ENTRIES-1);
+ uint32_t bucket_choose = prim_bucket;
+
+ if (random & MEMBERSHIP_EVICT_CHOOSE) {
+ bucket_choose = sec_bucket;
+ }
+
+ buckets[bucket_choose].sigs[evict_idx] = tmp_sig;
+ buckets[bucket_choose].targets[evict_idx] = target_id;
+ return 1;
+}
+
+
+void
+rte_membership_free_cache(struct rte_membership_setsum* setsum){
+ rte_free(setsum->ss);
+}
+
+
+int
+rte_membership_delete_cache(struct rte_membership_setsum* setsum,
+ const void* key, MEMBERSHIP_TARGET_TYPE target_id)
+{
+ (void)target_id;
+ int i;
+ struct membership_cache_ss* ht = setsum->ss;
+ uint32_t prim_hash_seed = setsum->prim_hash_seed;
+ uint32_t sec_hash_seed = setsum->sec_hash_seed;
+ uint32_t bucket_mask = ht->bucket_mask;
+ struct membership_cache_bucket* buckets = ht->buckets;
+ uint32_t key_len = setsum->key_len;
+
+ SIG_TYPE tmp_sig = MEMBERSHIP_PRIM_HASH(key, key_len, prim_hash_seed) &
+ SIG_BITMASK;
+
+
+ uint32_t hash_val = MEMBERSHIP_SEC_HASH(key, key_len, sec_hash_seed);
+ uint32_t prim_bucket = hash_val & bucket_mask;
+ uint32_t sec_bucket = (prim_bucket ^ tmp_sig) & bucket_mask;
+
+ for (i = 0; i < MEMBERSHIP_BUCKET_ENTRIES; i++) {
+ if(tmp_sig == buckets[prim_bucket].sigs[i]) {
+ buckets[prim_bucket].targets[i] = RTE_MEMBERSHIP_NO_MATCH;
+ return 0;
+ }
+ }
+
+ for (i = 0; i < MEMBERSHIP_BUCKET_ENTRIES; i++) {
+ if (tmp_sig == buckets[sec_bucket].sigs[i]) {
+ buckets[sec_bucket].targets[i] = RTE_MEMBERSHIP_NO_MATCH;
+ return 0;
+ }
+ }
+ return -ENOENT;
+}
+
+void
+rte_membership_reset_cache(const struct rte_membership_setsum *setsum)
+{
+ uint32_t i, j;
+ struct membership_cache_ss* ht = setsum->ss;
+ /* FIXME: low efficient */
+ for (i=0; i<ht->bucket_cnt; i++) {
+ for (j=0; j<MEMBERSHIP_BUCKET_ENTRIES; j++) {
+ ht->buckets[i].targets[j]=RTE_MEMBERSHIP_NO_MATCH;
+ }
+ }
+}
\ No newline at end of file
new file mode 100644
@@ -0,0 +1,95 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 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.
+ */
+
+#ifndef _RTE_MEMBERSHIP_CACHE_H_
+#define _RTE_MEMBERSHIP_CACHE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int
+rte_membership_create_cache(struct rte_membership_setsum* ss);
+
+
+int
+rte_membership_lookup_cache(const struct rte_membership_setsum* setsum,
+ const void* key, MEMBERSHIP_TARGET_TYPE* target_id);
+
+
+int
+rte_membership_lookup_multi_cache(const struct rte_membership_setsum* setsum,
+ const void* key, MEMBERSHIP_TARGET_TYPE* target_id);
+
+
+int
+rte_membership_lookup_bulk_cache(const struct rte_membership_setsum *setsum,
+ const void **keys, uint32_t num_keys,
+ MEMBERSHIP_TARGET_TYPE* target_ids);
+
+
+
+int
+rte_membership_lookup_multi_bulk_cache(const struct rte_membership_setsum* setsum,
+ const void **keys, uint32_t num_keys, uint32_t match_per_key,
+ uint32_t *match_count, MEMBERSHIP_TARGET_TYPE *target_ids);
+
+
+
+int
+rte_membership_add_cache(const struct rte_membership_setsum* setsum,
+ const void* key, MEMBERSHIP_TARGET_TYPE target_id);
+
+void
+rte_membership_free_cache(struct rte_membership_setsum* setsum);
+
+
+
+
+int
+rte_membership_delete_cache(struct rte_membership_setsum* ss, const void* key,
+ MEMBERSHIP_TARGET_TYPE target_id);
+
+
+
+void
+rte_membership_reset_cache(const struct rte_membership_setsum *setsum);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _RTE_MEMBERSHIP_CACHE_H_ */
new file mode 100644
@@ -0,0 +1,471 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 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.
+ */
+
+#include "rte_membership.h"
+#include "rte_membership_ht.h"
+
+#include <rte_errno.h>
+#include <rte_malloc.h>
+#include <rte_prefetch.h>
+
+
+/* The bucket struct for ht setsum */
+struct membership_ht_bucket {
+ SIG_TYPE sigs[MEMBERSHIP_BUCKET_ENTRIES]; /* 2-byte signature */
+ uint8_t flags[MEMBERSHIP_BUCKET_ENTRIES];
+ MEMBERSHIP_TARGET_TYPE targets[MEMBERSHIP_BUCKET_ENTRIES];/* 2-byte target */
+} __attribute__ ((packed));
+
+
+struct membership_ht_ss {
+ struct membership_ht_bucket* buckets; /* buckets array */
+ uint32_t bucket_cnt;
+ uint32_t bucket_mask;
+
+};
+
+
+int
+rte_membership_create_ht(struct rte_membership_setsum *ss){
+ uint32_t i, j;
+ const uint32_t num_buckets = rte_align32pow2(ss->num_keys) /
+ MEMBERSHIP_BUCKET_ENTRIES;
+ struct membership_ht_ss *t;
+
+ t = (struct membership_ht_ss *)rte_zmalloc_socket(NULL,
+ sizeof(struct membership_ht_ss),
+ RTE_CACHE_LINE_SIZE, ss->socket_id);
+
+
+ struct membership_ht_bucket* buckets = rte_zmalloc_socket(NULL,
+ num_buckets * sizeof(struct membership_ht_bucket),
+ RTE_CACHE_LINE_SIZE, ss->socket_id);
+
+ t->buckets = buckets;
+ t->bucket_cnt = num_buckets;
+ t->bucket_mask = num_buckets - 1;
+
+ ss->ss = t;
+
+ for (i=0; i<num_buckets; i++) {
+ for (j=0; j<MEMBERSHIP_BUCKET_ENTRIES; j++) {
+ buckets[i].targets[j]=RTE_MEMBERSHIP_NO_MATCH;
+ }
+ }
+ return 0;
+}
+
+
+int
+rte_membership_lookup_multi_ht(const struct rte_membership_setsum* setsum,
+ const void* key, MEMBERSHIP_TARGET_TYPE* target_id)
+{
+
+ int32_t i;
+ int ret = 0;
+ struct membership_ht_ss* ht = setsum->ss;
+ uint32_t prim_hash_seed = setsum->prim_hash_seed;
+ uint32_t sec_hash_seed = setsum->sec_hash_seed;
+ uint32_t bucket_mask = ht->bucket_mask;
+ struct membership_ht_bucket* buckets = ht->buckets;
+ uint32_t key_len = setsum->key_len;
+
+
+ SIG_TYPE tmp_sig = MEMBERSHIP_PRIM_HASH(key, key_len, prim_hash_seed) &
+ SIG_BITMASK;
+
+ uint32_t hash_val = MEMBERSHIP_SEC_HASH(key, key_len, sec_hash_seed);
+ uint32_t prim_bucket = hash_val & bucket_mask;
+ uint32_t sec_bucket = (prim_bucket ^ tmp_sig) & bucket_mask;
+
+ for (i = 0; i < MEMBERSHIP_BUCKET_ENTRIES; i++) {
+ if (tmp_sig == buckets[prim_bucket].sigs[i] &&
+ buckets[prim_bucket].targets[i] != RTE_MEMBERSHIP_NO_MATCH) {
+ target_id[ret] = buckets[prim_bucket].targets[i];
+ ret++;
+ }
+ }
+
+ for (i = 0; i < MEMBERSHIP_BUCKET_ENTRIES; i++) {
+ if (tmp_sig == buckets[sec_bucket].sigs[i] &&
+ buckets[sec_bucket].targets[i] != RTE_MEMBERSHIP_NO_MATCH) {
+ target_id[ret] = buckets[sec_bucket].targets[i];
+ ret++;
+ }
+ }
+ return ret;
+}
+
+int
+rte_membership_lookup_multi_bulk_ht(const struct rte_membership_setsum *setsum,
+ const void **keys, uint32_t num_keys, uint32_t match_per_key,
+ uint32_t *match_count,
+ MEMBERSHIP_TARGET_TYPE *target_ids)
+{
+ uint32_t i,j;
+ int ret = 0;
+ struct membership_ht_ss *ht = setsum->ss;
+ uint32_t prim_hash_seed = setsum->prim_hash_seed;
+ uint32_t sec_hash_seed = setsum->sec_hash_seed;
+ uint32_t bucket_mask = ht->bucket_mask;
+ struct membership_ht_bucket* buckets = ht->buckets;
+ uint32_t key_len = setsum->key_len;
+
+ SIG_TYPE tmp_sig[RTE_MEMBERSHIP_LOOKUP_BULK_MAX] = {0};
+ const struct membership_ht_bucket*
+ prim_buckets[RTE_MEMBERSHIP_LOOKUP_BULK_MAX] = {0};
+ const struct membership_ht_bucket*
+ sec_buckets[RTE_MEMBERSHIP_LOOKUP_BULK_MAX] = {0};
+
+ for (i=0; i<num_keys; i++) {
+ tmp_sig[i] = MEMBERSHIP_PRIM_HASH(keys[i], key_len, prim_hash_seed) &
+ SIG_BITMASK;
+ uint32_t hash_val = MEMBERSHIP_SEC_HASH(keys[i], key_len, sec_hash_seed);
+ uint32_t prim_bucket = hash_val & bucket_mask;
+ uint32_t sec_bucket = (prim_bucket ^ tmp_sig[i]) & bucket_mask;
+ prim_buckets[i] = &buckets[prim_bucket];
+ sec_buckets[i] = &buckets[sec_bucket];
+ rte_prefetch0(prim_buckets[i]);
+ rte_prefetch0(sec_buckets[i]);
+ }
+
+ for (j = 0; j < num_keys; j++) {
+ uint32_t match_cnt = 0;
+ for (i = 0; i < MEMBERSHIP_BUCKET_ENTRIES; i++){
+ if(tmp_sig[j] == prim_buckets[j]->sigs[i] &&
+ prim_buckets[j]->targets[i] != RTE_MEMBERSHIP_NO_MATCH){
+ if (match_cnt >= match_per_key)
+ break;
+ target_ids[j*match_per_key+match_cnt] = prim_buckets[j]->targets[i];
+ match_cnt++;
+ }
+ }
+ for (i = 0; i < MEMBERSHIP_BUCKET_ENTRIES; i++) {
+ if (tmp_sig[j] == sec_buckets[j]->sigs[i] &&
+ sec_buckets[j]->targets[i] != RTE_MEMBERSHIP_NO_MATCH) {
+ if (match_cnt >= match_per_key)
+ break;
+ target_ids[j*match_per_key+match_cnt] = sec_buckets[j]->targets[i];
+ match_cnt++;
+ }
+ }
+ match_count[j] = match_cnt;
+ if (match_cnt != 0)
+ ret++;
+ }
+ return ret;
+}
+
+int
+rte_membership_lookup_ht(const struct rte_membership_setsum *setsum,
+ const void *key, MEMBERSHIP_TARGET_TYPE *target_id)
+{
+
+ int32_t i;
+ struct membership_ht_ss* ht = setsum->ss;
+ uint32_t prim_hash_seed = setsum->prim_hash_seed;
+ uint32_t sec_hash_seed = setsum->sec_hash_seed;
+ uint32_t bucket_mask = ht->bucket_mask;
+ struct membership_ht_bucket* buckets = ht->buckets;
+ uint32_t key_len = setsum->key_len;
+
+
+ SIG_TYPE tmp_sig = MEMBERSHIP_PRIM_HASH(key, key_len, prim_hash_seed) &
+ SIG_BITMASK;
+
+ uint32_t hash_val = MEMBERSHIP_SEC_HASH(key, key_len, sec_hash_seed);
+ uint32_t prim_bucket = hash_val & bucket_mask;
+ uint32_t sec_bucket = (prim_bucket ^ tmp_sig) & bucket_mask;
+
+ for (i = 0; i < MEMBERSHIP_BUCKET_ENTRIES; i++) {
+ if (tmp_sig == buckets[prim_bucket].sigs[i] &&
+ buckets[prim_bucket].targets[i] != RTE_MEMBERSHIP_NO_MATCH) {
+ *target_id = buckets[prim_bucket].targets[i];
+ return 1;
+ }
+ }
+ for (i = 0; i < MEMBERSHIP_BUCKET_ENTRIES; i++) {
+ if (tmp_sig == buckets[sec_bucket].sigs[i] &&
+ buckets[sec_bucket].targets[i] != RTE_MEMBERSHIP_NO_MATCH) {
+ *target_id = buckets[sec_bucket].targets[i];
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int
+rte_membership_lookup_bulk_ht(const struct rte_membership_setsum *setsum,
+ const void **keys, uint32_t num_keys, MEMBERSHIP_TARGET_TYPE *target_id)
+{
+ uint32_t i,j;
+ int ret = 0;
+ struct membership_ht_ss* ht = setsum->ss;
+ uint32_t prim_hash_seed = setsum->prim_hash_seed;
+ uint32_t sec_hash_seed = setsum->sec_hash_seed;
+ uint32_t bucket_mask = ht->bucket_mask;
+ struct membership_ht_bucket* buckets = ht->buckets;
+ uint32_t key_len = setsum->key_len;
+
+ SIG_TYPE tmp_sig[RTE_MEMBERSHIP_LOOKUP_BULK_MAX] = {0};
+ const struct membership_ht_bucket*
+ prim_buckets[RTE_MEMBERSHIP_LOOKUP_BULK_MAX] = {0};
+ const struct membership_ht_bucket*
+ sec_buckets[RTE_MEMBERSHIP_LOOKUP_BULK_MAX] = {0};
+
+ for (i = 0; i < num_keys; i++) {
+ tmp_sig[i] = MEMBERSHIP_PRIM_HASH(keys[i], key_len, prim_hash_seed) &
+ SIG_BITMASK;
+ uint32_t hash_val = MEMBERSHIP_SEC_HASH(keys[i], key_len, sec_hash_seed);
+ uint32_t prim_bucket = hash_val & bucket_mask;
+ uint32_t sec_bucket = (prim_bucket ^ tmp_sig[i]) & bucket_mask;
+ prim_buckets[i] = &buckets[prim_bucket];
+ sec_buckets[i] = &buckets[sec_bucket];
+ rte_prefetch0(prim_buckets[i]);
+ rte_prefetch0(sec_buckets[i]);
+ }
+
+ for (i = 0; i < num_keys; i++) {
+ for (j = 0; j < MEMBERSHIP_BUCKET_ENTRIES; j++) {
+ if(tmp_sig[i] == prim_buckets[i]->sigs[j] &&
+ prim_buckets[i]->targets[j] != RTE_MEMBERSHIP_NO_MATCH) {
+ target_id[i] = prim_buckets[i]->targets[j];
+ ret++;
+ break;
+ }
+ }
+
+ if (j == MEMBERSHIP_BUCKET_ENTRIES) {
+ for (j = 0; j < MEMBERSHIP_BUCKET_ENTRIES; j++) {
+ if(tmp_sig[i] == sec_buckets[i]->sigs[j] &&
+ sec_buckets[i]->targets[j] != RTE_MEMBERSHIP_NO_MATCH) {
+ target_id[i]= sec_buckets[i]->targets[j];
+ ret++;
+ break;
+ }
+ }
+ }
+
+ if (j == MEMBERSHIP_BUCKET_ENTRIES) {
+ target_id[i] = RTE_MEMBERSHIP_NO_MATCH;
+ }
+ }
+ return ret;
+}
+
+
+
+/* Search for an entry that can be pushed to its alternative location */
+static inline int
+make_space_bucket(const struct rte_membership_setsum *setsum, uint32_t bkt_num)
+{
+ static unsigned int nr_pushes;
+ unsigned i, j;
+ int ret;
+ uint32_t next_bucket_idx;
+ struct membership_ht_ss* ht = setsum->ss;
+ struct membership_ht_bucket *next_bkt[MEMBERSHIP_BUCKET_ENTRIES];
+ struct membership_ht_bucket *bkt = &ht->buckets[bkt_num];
+
+ /*
+ * Push existing item (search for bucket with space in
+ * alternative locations) to its alternative location
+ */
+ for (i = 0; i < MEMBERSHIP_BUCKET_ENTRIES; i++) {
+ /* Search for space in alternative locations */
+ next_bucket_idx = (bkt->sigs[i] ^ bkt_num) & ht->bucket_mask;
+ next_bkt[i] = &ht->buckets[next_bucket_idx];
+ for (j = 0; j < MEMBERSHIP_BUCKET_ENTRIES; j++) {
+ if (next_bkt[i]->targets[j] == RTE_MEMBERSHIP_NO_MATCH)
+ break;
+ }
+
+ if (j != MEMBERSHIP_BUCKET_ENTRIES)
+ break;
+ }
+
+ /* Alternative location has spare room (end of recursive function) */
+ if (i != MEMBERSHIP_BUCKET_ENTRIES) {
+ next_bkt[i]->sigs[j] = bkt->sigs[i];
+ next_bkt[i]->targets[j] = bkt->targets[i];
+ return i;
+ }
+
+ /* Pick entry that has not been pushed yet */
+ for (i = 0; i < MEMBERSHIP_BUCKET_ENTRIES; i++)
+ if (bkt->flags[i] == 0)
+ break;
+
+ /* All entries have been pushed, so entry cannot be added */
+ if (i == MEMBERSHIP_BUCKET_ENTRIES || nr_pushes > MEMBERSHIP_MAX_PUSHES)
+ return -ENOSPC;
+
+ /* Set flag to indicate that this entry is going to be pushed */
+ bkt->flags[i] = 1;
+
+ nr_pushes++;
+ /* Need room in alternative bucket to insert the pushed entry */
+ ret = make_space_bucket(setsum, next_bucket_idx);
+ /*
+ * After recursive function.
+ * Clear flags and insert the pushed entry
+ * in its alternative location if successful,
+ * or return error
+ */
+ bkt->flags[i] = 0;
+ nr_pushes = 0;
+ if (ret >= 0) {
+ next_bkt[i]->sigs[ret] = bkt->sigs[i];
+ next_bkt[i]->targets[ret] = bkt->targets[i];
+ return i;
+ } else
+ return ret;
+}
+
+
+
+int
+rte_membership_add_ht(const struct rte_membership_setsum* setsum,
+ const void* key, MEMBERSHIP_TARGET_TYPE target_id)
+{
+ int i;
+ int ret;
+ struct membership_ht_ss* ht = setsum->ss;
+ uint32_t prim_hash_seed = setsum->prim_hash_seed;
+ uint32_t sec_hash_seed = setsum->sec_hash_seed;
+ uint32_t bucket_mask = ht->bucket_mask;
+ struct membership_ht_bucket* buckets = ht->buckets;
+ uint32_t key_len = setsum->key_len;
+
+ SIG_TYPE tmp_sig = MEMBERSHIP_PRIM_HASH(key, key_len, prim_hash_seed) &
+ SIG_BITMASK;
+
+
+ uint32_t hash_val = MEMBERSHIP_SEC_HASH(key, key_len, sec_hash_seed);
+ uint32_t prim_bucket = hash_val & bucket_mask;
+ uint32_t sec_bucket = (prim_bucket ^ tmp_sig) & bucket_mask;
+
+
+ /* If not full then insert into one slot*/
+ for (i = 0; i < MEMBERSHIP_BUCKET_ENTRIES; i++) {
+ if (buckets[prim_bucket].targets[i] == RTE_MEMBERSHIP_NO_MATCH) {
+ buckets[prim_bucket].sigs[i] = tmp_sig;
+ buckets[prim_bucket].targets[i] = target_id;
+ ret = i;
+ return ret;
+ }
+ }
+
+ for (i = 0; i < MEMBERSHIP_BUCKET_ENTRIES; i++) {
+ if(buckets[sec_bucket].targets[i] == RTE_MEMBERSHIP_NO_MATCH){
+ buckets[sec_bucket].sigs[i] = tmp_sig;
+ buckets[sec_bucket].targets[i] = target_id;
+ ret = i;
+ return ret;
+ }
+ }
+
+
+ /* random pick prim or sec for recursive displacement */
+
+ uint32_t select_bucket = (hash_val>>31) ? prim_bucket : sec_bucket;
+ ret = make_space_bucket (setsum, select_bucket);
+
+ if (ret >= 0) {
+ buckets[select_bucket].sigs[ret] = tmp_sig;
+ buckets[select_bucket].targets[ret] = target_id;
+ return ret;
+ }
+ return ret;
+}
+
+
+void
+rte_membership_free_ht(struct rte_membership_setsum *setsum)
+{
+ rte_free(setsum->ss);
+}
+
+
+int
+rte_membership_delete_ht(struct rte_membership_setsum *setsum, const void *key,
+ MEMBERSHIP_TARGET_TYPE target_id)
+{
+ int i;
+ struct membership_ht_ss *ht = setsum->ss;
+ uint32_t prim_hash_seed = setsum->prim_hash_seed;
+ uint32_t sec_hash_seed = setsum->sec_hash_seed;
+ uint32_t bucket_mask = ht->bucket_mask;
+ struct membership_ht_bucket *buckets = ht->buckets;
+ uint32_t key_len = setsum->key_len;
+
+ SIG_TYPE tmp_sig = MEMBERSHIP_PRIM_HASH(key, key_len, prim_hash_seed) &
+ SIG_BITMASK;
+
+
+ uint32_t hash_val = MEMBERSHIP_SEC_HASH(key, key_len, sec_hash_seed);
+ uint32_t prim_bucket = hash_val & bucket_mask;
+ uint32_t sec_bucket = (prim_bucket ^ tmp_sig) & bucket_mask;
+
+ for (i = 0; i < MEMBERSHIP_BUCKET_ENTRIES; i++) {
+ if (tmp_sig == buckets[prim_bucket].sigs[i] &&
+ target_id == buckets[prim_bucket].targets[i]){
+ buckets[prim_bucket].targets[i] = RTE_MEMBERSHIP_NO_MATCH;
+ return 0;
+ }
+ }
+
+ for (i = 0; i < MEMBERSHIP_BUCKET_ENTRIES; i++){
+ if(tmp_sig == buckets[sec_bucket].sigs[i] &&
+ target_id == buckets[sec_bucket].targets[i]){
+ buckets[prim_bucket].targets[i] = RTE_MEMBERSHIP_NO_MATCH;
+ return 0;
+ }
+ }
+ return -ENOENT;
+}
+
+
+void
+rte_membership_reset_ht(const struct rte_membership_setsum *setsum)
+{
+ uint32_t i, j;
+ struct membership_ht_ss *ht = setsum->ss;
+ /* FIXME: inefficient*/
+ for (i = 0; i < ht->bucket_cnt; i++) {
+ for (j = 0; j < MEMBERSHIP_BUCKET_ENTRIES; j++){
+ ht->buckets[i].targets[j] = RTE_MEMBERSHIP_NO_MATCH;
+ }
+ }
+}
+
new file mode 100644
@@ -0,0 +1,98 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 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.
+ */
+
+#ifndef _RTE_MEMBERSHIP_HT_H_
+#define _RTE_MEMBERSHIP_HT_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int
+rte_membership_create_ht(struct rte_membership_setsum *ss);
+
+
+int
+rte_membership_lookup_ht(const struct rte_membership_setsum *setsum,
+ const void *key, MEMBERSHIP_TARGET_TYPE *target_id);
+
+
+
+int
+rte_membership_lookup_bulk_ht(const struct rte_membership_setsum *setsum,
+ const void **keys, uint32_t num_keys, MEMBERSHIP_TARGET_TYPE *target_ids);
+
+
+
+
+int
+rte_membership_lookup_multi_ht(const struct rte_membership_setsum *setsum,
+ const void *key, MEMBERSHIP_TARGET_TYPE *target_id);
+
+
+
+int
+rte_membership_lookup_multi_bulk_ht(const struct rte_membership_setsum *setsum,
+ const void **keys, uint32_t num_keys, uint32_t match_per_key,
+ uint32_t *match_count,
+ MEMBERSHIP_TARGET_TYPE *target_ids);
+
+
+
+
+int
+rte_membership_add_ht(const struct rte_membership_setsum *setsum,
+ const void *key, MEMBERSHIP_TARGET_TYPE target_id);
+
+void
+rte_membership_free_ht(struct rte_membership_setsum *setsum);
+
+
+
+
+int
+rte_membership_delete_ht(struct rte_membership_setsum *ss, const void *key,
+ MEMBERSHIP_TARGET_TYPE target_id);
+
+
+void
+rte_membership_reset_ht(const struct rte_membership_setsum *setsum);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+#endif /* _RTE_MEMBERSHIP_HT_H_ */
new file mode 100644
@@ -0,0 +1,391 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 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.
+ */
+
+#include "rte_membership.h"
+#include "rte_membership_bf.h"
+#include "rte_membership_vbf.h"
+
+#include <rte_bitmap.h>
+#include <rte_malloc.h>
+#include <rte_memory.h>
+#include <rte_hash_crc.h>
+#include <rte_errno.h>
+
+
+/*
+ * vBF currently implemented as a linked list of BFs
+ */
+
+int
+__membership_push(const struct rte_membership_setsum *setsum,
+ struct rte_membership_bf *bf, MEMBERSHIP_TARGET_TYPE target_id);
+
+
+struct rte_membership_vbf_node
+{
+ struct rte_membership_bf *bf;
+ MEMBERSHIP_TARGET_TYPE target_id;
+ struct rte_membership_vbf_node *next;
+};
+
+struct rte_membership_vbf
+{
+ struct rte_membership_vbf_node *root;
+};
+
+
+int
+__membership_push(const struct rte_membership_setsum *setsum,
+ struct rte_membership_bf *bf, MEMBERSHIP_TARGET_TYPE target_id)
+{
+ struct rte_membership_vbf *vbf = setsum->ss;
+ struct rte_membership_vbf_node *current = vbf->root;
+
+ struct rte_membership_vbf_node *new_node;
+ new_node = rte_zmalloc_socket(NULL, sizeof(struct rte_membership_vbf_node),
+ RTE_CACHE_LINE_SIZE, setsum->socket_id);
+ if (new_node == NULL) {
+ return -ENOMEM;
+ }
+
+ new_node->bf = bf;
+ new_node->target_id = target_id;
+ new_node->next = NULL;
+
+
+ if (current != NULL) {
+ while(current->next != NULL){
+ current = current->next;
+ }
+ current->next = new_node;
+ }
+ else {
+ vbf->root = new_node;
+ }
+
+ return 0;
+}
+
+
+
+int
+rte_membership_create_vbf(struct rte_membership_setsum *setsum)
+{
+ int i;
+ int num_target = setsum->num_target;
+ struct rte_membership_vbf *vbf =
+ rte_zmalloc_socket(NULL, sizeof(struct rte_membership_vbf),
+ RTE_CACHE_LINE_SIZE, setsum->socket_id);
+ if(vbf == NULL)
+ return -ENOMEM;
+
+ vbf->root = NULL;
+ setsum->ss = vbf;
+ for (i = 1; i < num_target+1; i++) {
+ struct rte_membership_bf *bloom =
+ __membership_create_bf((const struct rte_membership_setsum *)setsum);
+
+ if (bloom == NULL) {
+ rte_membership_free_vbf(setsum);
+ return -ENOMEM;
+ }
+ if (__membership_push((const struct rte_membership_setsum *)setsum,
+ bloom, i) < 0) {
+ rte_membership_free_vbf(setsum);
+ return -ENOMEM;
+ }
+ }
+ return 0;
+}
+
+
+int
+rte_membership_lookup_vbf(const struct rte_membership_setsum *setsum,
+ const void *key, MEMBERSHIP_TARGET_TYPE *target_id)
+{
+ uint32_t key_len = setsum->key_len;
+ uint32_t prim_hash_seed = setsum->prim_hash_seed;
+ uint32_t sec_hash_seed = setsum->sec_hash_seed;
+ uint32_t a = MEMBERSHIP_PRIM_HASH(key, key_len, prim_hash_seed);
+ uint32_t b = MEMBERSHIP_SEC_HASH(key, key_len, sec_hash_seed);
+
+ struct rte_membership_vbf* vbf = setsum->ss;
+ struct rte_membership_vbf_node* current = vbf->root;
+
+ while (current != NULL) {
+ struct rte_membership_bf* bloom = current->bf;
+ uint32_t x;
+ uint32_t i;
+
+ struct rte_bitmap *bmp = bloom->bmp;
+
+ for (i = 0; i < bloom->num_hashes; i++) {
+ x = (a + i*b) & bloom->bucket_bitmask;
+ if (rte_bitmap_get(bmp, x) == 0) {
+ current = current->next;
+ break;
+ }
+ }
+ if(i == bloom->num_hashes){
+ *target_id = current->target_id;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+int
+rte_membership_lookup_bulk_vbf(const struct rte_membership_setsum *setsum,
+ const void **keys, uint32_t num_keys, MEMBERSHIP_TARGET_TYPE *target_ids)
+{
+ uint32_t i;
+ int ret = 0;
+ uint32_t key_len = setsum->key_len;
+ uint32_t prim_hash_seed = setsum->prim_hash_seed;
+ uint32_t sec_hash_seed = setsum->sec_hash_seed;
+
+ struct rte_membership_vbf* vbf = setsum->ss;
+
+ for (i = 0; i < num_keys; i++) {
+ uint32_t a = MEMBERSHIP_PRIM_HASH(keys[i], key_len, prim_hash_seed);
+ uint32_t b = MEMBERSHIP_SEC_HASH(keys[i], key_len, sec_hash_seed);
+ struct rte_membership_vbf_node* current = vbf->root;
+ while (current != NULL) {
+ struct rte_membership_bf* bloom = current->bf;
+ uint32_t x;
+ uint32_t j;
+
+ struct rte_bitmap *bmp = bloom->bmp;
+
+ for (j = 0; j < bloom->num_hashes; j++) {
+ x = (a + j*b) & bloom->bucket_bitmask;
+ if (rte_bitmap_get(bmp, x) == 0) {
+ current = current->next;
+ break;
+ }
+ }
+ if (j == bloom->num_hashes) {
+ target_ids[i] = current->target_id;
+ ret++;
+ break;
+ }
+ }
+ if (current == NULL)
+ target_ids[i] = RTE_MEMBERSHIP_NO_MATCH;
+ }
+ return ret;
+}
+
+
+
+
+int
+rte_membership_lookup_multi_vbf(const struct rte_membership_setsum *setsum,
+ const void *key, MEMBERSHIP_TARGET_TYPE *target_id)
+{
+ int ret = 0;
+ uint32_t key_len = setsum->key_len;
+ uint32_t prim_hash_seed = setsum->prim_hash_seed;
+ uint32_t sec_hash_seed = setsum->sec_hash_seed;
+ uint32_t a = MEMBERSHIP_PRIM_HASH(key, key_len, prim_hash_seed);
+ uint32_t b = MEMBERSHIP_SEC_HASH(key, key_len, sec_hash_seed);
+
+ struct rte_membership_vbf* vbf = setsum->ss;
+ struct rte_membership_vbf_node* current = vbf->root;
+
+ while (current != NULL) {
+ struct rte_membership_bf* bloom = current->bf;
+ uint32_t x;
+ uint32_t i;
+
+ struct rte_bitmap *bmp = bloom->bmp;
+
+ for (i = 0; i < bloom->num_hashes; i++) {
+ x = (a + i*b) & bloom->bucket_bitmask;
+ if (rte_bitmap_get(bmp, x) == 0) {
+ current = current->next;
+ break;
+ }
+ }
+ if(i == bloom->num_hashes){
+ target_id[ret] = current->target_id;
+ ret++;
+ current = current->next;
+ }
+ }
+ return ret;
+}
+
+
+
+int
+rte_membership_lookup_multi_bulk_vbf(const struct rte_membership_setsum *setsum,
+ const void **keys, uint32_t num_keys, uint32_t match_per_key,
+ uint32_t *match_count,
+ MEMBERSHIP_TARGET_TYPE *target_ids)
+{
+ uint32_t j;
+ int ret = 0;
+ uint32_t key_len = setsum->key_len;
+ uint32_t prim_hash_seed = setsum->prim_hash_seed;
+ uint32_t sec_hash_seed = setsum->sec_hash_seed;
+ struct rte_membership_vbf* vbf = setsum->ss;
+
+ for (j = 0; j < num_keys; j++) {
+ uint32_t match_cnt=0;
+ uint32_t a = MEMBERSHIP_PRIM_HASH(keys[j], key_len, prim_hash_seed);
+ uint32_t b = MEMBERSHIP_SEC_HASH(keys[j], key_len, sec_hash_seed);
+ struct rte_membership_vbf_node* current = vbf->root;
+ while (current != NULL) {
+ struct rte_membership_bf* bloom = current->bf;
+ uint32_t x;
+ uint32_t i;
+
+ struct rte_bitmap *bmp = bloom->bmp;
+
+ for (i = 0; i < bloom->num_hashes; i++) {
+ x = (a + i * b) & bloom->bucket_bitmask;
+ if (rte_bitmap_get(bmp, x) == 0) {
+ current = current->next;
+ break;
+ }
+ }
+ if (i == bloom->num_hashes) {
+ if (match_cnt >= match_per_key)
+ break;
+ target_ids[j*match_per_key+match_cnt] = current->target_id;
+ match_cnt++;
+ current = current->next;
+ }
+ }
+ match_count[j] = match_cnt;
+ if (match_cnt != 0)
+ ret++;
+ }
+ return ret;
+}
+
+
+
+int
+rte_membership_add_vbf(const struct rte_membership_setsum *setsum,
+ const void *key, MEMBERSHIP_TARGET_TYPE target_id)
+{
+
+ uint32_t key_len = setsum->key_len;
+ uint32_t prim_hash_seed = setsum->prim_hash_seed;
+ uint32_t sec_hash_seed = setsum->sec_hash_seed;
+ uint32_t a = MEMBERSHIP_PRIM_HASH(key, key_len, prim_hash_seed);
+ uint32_t b = MEMBERSHIP_SEC_HASH(key, key_len, sec_hash_seed);
+ struct rte_membership_vbf* vbf = setsum->ss;
+ struct rte_membership_vbf_node* current = vbf->root;
+ uint32_t x;
+ uint32_t i;
+
+ while (current != NULL) {
+ if (current->target_id != target_id) {
+ current = current->next;
+ continue;
+ }
+
+ struct rte_membership_bf *bloom = current->bf;
+
+ struct rte_bitmap *bmp = bloom->bmp;
+
+ for (i = 0; i < bloom->num_hashes; i++) {
+ x = (a + i * b) & bloom->bucket_bitmask;
+ rte_bitmap_set(bmp, x);
+ }
+ return 0;
+ }
+
+ /* Here means there is no BF matches the target. So we add a new BF */
+
+ struct rte_membership_bf *bloom = __membership_create_bf(setsum);
+
+ if(bloom == NULL) {
+ return -ENOMEM;
+ }
+
+ struct rte_bitmap *bmp = bloom->bmp;
+
+ for (i = 0; i < bloom->num_hashes; i++) {
+ x = (a + i * b) & bloom->bucket_bitmask;
+ rte_bitmap_set(bmp, x);
+ }
+
+ if (__membership_push(setsum, bloom, i) < 0) {
+ rte_free(bloom->bmp_array);
+ rte_free(bloom);
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+
+void
+rte_membership_free_vbf(struct rte_membership_setsum *setsum)
+{
+ struct rte_membership_vbf* vbf = setsum->ss;
+ if (vbf != NULL) {
+ struct rte_membership_vbf_node* current = vbf->root;
+ struct rte_membership_vbf_node* next;
+ while (current != NULL) {
+ next = current->next;
+ if(current->bf != NULL){
+ rte_free(current->bf->bmp_array);
+ rte_free(current->bf);
+ }
+ rte_free(current);
+ current = next;
+ }
+ }
+}
+
+
+
+
+void
+rte_membership_reset_vbf(const struct rte_membership_setsum *setsum)
+{
+
+ struct rte_membership_vbf *vbf = setsum->ss;
+ struct rte_membership_vbf_node *current = vbf->root;
+
+ while (current != NULL) {
+ if (current->bf != NULL)
+ rte_bitmap_reset(current->bf->bmp_array);
+ current = current->next;
+ }
+}
\ No newline at end of file
new file mode 100644
@@ -0,0 +1,85 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 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.
+ */
+
+#ifndef _RTE_MEMBERSHIP_VBF_H_
+#define _RTE_MEMBERSHIP_VBF_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int
+rte_membership_create_vbf(struct rte_membership_setsum *ss);
+
+
+int
+rte_membership_lookup_vbf(const struct rte_membership_setsum *setsum,
+ const void *key, MEMBERSHIP_TARGET_TYPE *target_id);
+
+
+int
+rte_membership_lookup_bulk_vbf(const struct rte_membership_setsum *setsum,
+ const void **keys, uint32_t num_keys, MEMBERSHIP_TARGET_TYPE *target_ids);
+
+
+int
+rte_membership_lookup_multi_vbf(const struct rte_membership_setsum *setsum,
+ const void *key, MEMBERSHIP_TARGET_TYPE *target_id);
+
+
+int
+rte_membership_lookup_multi_bulk_vbf(const struct rte_membership_setsum *setsum,
+ const void **keys, uint32_t num_keys, uint32_t match_per_key,
+ uint32_t *match_count,
+ MEMBERSHIP_TARGET_TYPE *target_ids);
+
+
+
+int
+rte_membership_add_vbf(const struct rte_membership_setsum *setsum,
+ const void *key, MEMBERSHIP_TARGET_TYPE target_id);
+
+
+void
+rte_membership_free_vbf(struct rte_membership_setsum *ss);
+
+
+void
+rte_membership_reset_vbf(const struct rte_membership_setsum *setsum);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_MEMBERSHIP_VBF_H_ */
new file mode 100644
@@ -0,0 +1,15 @@
+DPDK_17.08 {
+ global:
+
+ rte_membership_create;
+ rte_membership_lookup;
+ rte_membership_lookup_bulk;
+ rte_membership_lookup_multi;
+ rte_membership_lookup_multi_bulk;
+ rte_membership_add;
+ rte_membership_free;
+ rte_membership_reset;
+ rte_membership_delete;
+
+ local: *;
+};
@@ -85,6 +85,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE) += -lrte_cfgfile
_LDLIBS-y += --whole-archive
_LDLIBS-$(CONFIG_RTE_LIBRTE_HASH) += -lrte_hash
+_LDLIBS-$(CONFIG_RTE_LIBRTE_MEMBERSHIP) += -lrte_membership
_LDLIBS-$(CONFIG_RTE_LIBRTE_VHOST) += -lrte_vhost
_LDLIBS-$(CONFIG_RTE_LIBRTE_KVARGS) += -lrte_kvargs
_LDLIBS-$(CONFIG_RTE_LIBRTE_MBUF) += -lrte_mbuf
@@ -123,6 +123,8 @@ SRCS-y += test_logs.c
SRCS-y += test_memcpy.c
SRCS-y += test_memcpy_perf.c
+
+SRCS-$(CONFIG_RTE_LIBRTE_MEMBERSHIP) += test_membership.c
SRCS-$(CONFIG_RTE_LIBRTE_EFD) += test_efd.c
SRCS-$(CONFIG_RTE_LIBRTE_EFD) += test_efd_perf.c
new file mode 100644
@@ -0,0 +1,459 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 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.
+ */
+
+
+#include <rte_memcpy.h>
+#include <rte_malloc.h>
+#include <rte_membership.h>
+#include <rte_byteorder.h>
+#include <rte_random.h>
+#include <rte_debug.h>
+#include <rte_ip.h>
+
+
+#include "test.h"
+
+void *setsum_ht;
+void *setsum_cache;
+void *setsum_bf;
+void *setsum_vbf;
+
+#define KEY 0xffff
+#define KEY1 0xfffe
+#define TARGET 31
+
+#define ITERATIONS 3
+#define MAX_KEYSIZE 4
+
+static struct rte_membership_parameters params = {
+ .name = "test_membership_ht",
+ .type = SETSUM_TYPE_HT,
+ .num_keys = 1 << 16, /* Total hash table entries. */
+ .key_len = 4, /* Length of hash key. */
+
+ /*num_target and false_postive_rate only relevent with BF based set summary*/
+ .num_target = 32,
+ .false_postive_rate = 0.03,
+ .prim_hash_seed = 1,
+ .sec_hash_seed = 11,
+ .socket_id = 0 /* NUMA Socket ID for memory. */
+ };
+
+
+#define RETURN_IF_ERROR(cond, str, ...) do { \
+ if (cond) { \
+ printf("ERROR line %d: " str "\n", __LINE__, ##__VA_ARGS__); \
+ return -1; \
+ } \
+} while(0)
+
+static int test_membership_create(void)
+{
+
+
+ setsum_ht = rte_membership_create(¶ms);
+
+ params.name = "test_membership_cache";
+ params.type = SETSUM_TYPE_CACHE;
+
+ setsum_cache = rte_membership_create(¶ms);
+
+ params.name = "test_membership_bf";
+ params.type = SETSUM_TYPE_BF;
+
+ setsum_bf = rte_membership_create(¶ms);
+
+ params.name = "test_membership_vbf";
+ params.type = SETSUM_TYPE_VBF;
+
+ setsum_vbf = rte_membership_create(¶ms);
+
+ if(setsum_ht==NULL || setsum_cache == NULL || setsum_bf == NULL ||
+ setsum_vbf == NULL) {
+ printf("Creation of setsums fail\n");
+ return -1;
+ }
+ printf("Creation of setsums success\n");
+ return 0;
+}
+
+static int test_membership_insert(void)
+{
+ int ret_ht, ret_cache, ret_bf, ret_vbf;
+ uint32_t key=KEY;
+ uint32_t target_bf = 1;
+ ret_ht = rte_membership_add(setsum_ht, &key, TARGET);
+ ret_cache = rte_membership_add(setsum_cache, &key, TARGET);
+ ret_bf = rte_membership_add(setsum_bf, &key, target_bf);
+ ret_vbf = rte_membership_add(setsum_vbf, &key, TARGET);
+ printf("%d, %d, %d, %d\n", ret_ht, ret_cache, ret_bf, ret_vbf);
+ RETURN_IF_ERROR(ret_ht < 0 || ret_cache < 0 || ret_bf < 0 || ret_vbf < 0,
+ "insert error");
+
+ printf("insert key %d with target %d success\n", key, TARGET);
+ return 0;
+}
+
+static int test_membership_lookup(void)
+{
+ int ret_ht, ret_cache, ret_bf, ret_vbf;
+ uint16_t target_ht, target_cache, target_bf, target_vbf;
+ MEMBERSHIP_TARGET_TYPE target_ids_ht[8] = {0};
+ MEMBERSHIP_TARGET_TYPE target_ids_cache[8] = {0};
+ MEMBERSHIP_TARGET_TYPE target_ids_bf[8] = {0};
+ MEMBERSHIP_TARGET_TYPE target_ids_vbf[8] = {0};
+ uint32_t key = KEY;
+ uint32_t key1 = KEY1;
+ uint32_t *key_array[8];
+ uint32_t num_key_ht = 2;
+ uint32_t num_key_cache = 2;
+ uint32_t num_key_bf = 2;
+
+ /* single lookup test */
+ ret_ht = rte_membership_lookup(setsum_ht, &key, &target_ht);
+ ret_cache = rte_membership_lookup(setsum_cache, &key, &target_cache);
+ ret_bf = rte_membership_lookup(setsum_bf, &key, &target_bf);
+ ret_vbf = rte_membership_lookup(setsum_vbf, &key, &target_vbf);
+ if(ret_ht < 0 || ret_cache < 0 || ret_bf < 0 || ret_vbf < 0){
+ printf("lookup ret:%d, %d, %d, %d\n", ret_ht, ret_cache, ret_bf, ret_vbf);
+ return -1;
+ }
+ printf("lookup get target:%d, %d, %d, %d\n", target_ht, target_cache,
+ target_bf, target_vbf);
+ printf("lookup single key success\n");
+
+ /* bulk lookup test */
+ key_array[0] = &key1;
+ key_array[1] = &key;
+
+ ret_ht = rte_membership_lookup_bulk(setsum_ht, (const void**)(key_array),
+ num_key_ht, target_ids_ht);
+
+ ret_cache = rte_membership_lookup_bulk(setsum_cache, (const void**)(key_array),
+ num_key_cache,target_ids_cache);
+
+ ret_bf = rte_membership_lookup_bulk(setsum_bf, (const void**)(key_array),
+ num_key_bf, target_ids_bf);
+
+ ret_vbf = rte_membership_lookup_bulk(setsum_vbf, (const void**)(key_array),
+ num_key_bf, target_ids_vbf);
+
+ RETURN_IF_ERROR((target_ids_ht[0] != target_ids_cache[0]) ||
+ (target_ids_ht[1] != target_ids_cache[1]), "bulk lookup error");
+ printf("bulk lookup target 0:%d, %d, %d, %d\n", target_ids_ht[0],
+ target_ids_cache[0], target_ids_bf[0], target_ids_vbf[0]);
+
+ printf("bulk lookup target 1:%d, %d, %d, %d\n", target_ids_ht[1],
+ target_ids_cache[1], target_ids_bf[1], target_ids_vbf[1]);
+
+ RETURN_IF_ERROR((ret_ht != ret_cache || ret_ht != ret_bf || ret_ht != ret_vbf),
+ "bulk lookup error");
+
+ return 0;
+}
+
+
+static int test_membership_delete(void)
+{
+ int ret_ht, ret_cache, ret_bf, ret_vbf;
+ uint32_t key = KEY;
+ uint16_t target_ht, target_cache, target_bf, target_vbf;
+ ret_ht = rte_membership_delete(setsum_ht, &key, TARGET);
+ ret_cache = rte_membership_delete(setsum_cache, &key, TARGET);
+ ret_bf = rte_membership_delete(setsum_bf, &key, TARGET);
+ ret_vbf = rte_membership_delete(setsum_vbf, &key, TARGET);
+ RETURN_IF_ERROR(ret_ht < 0 || ret_cache < 0 || ret_bf > 0 || ret_vbf > 0,
+ "bulk lookup error");
+
+ ret_ht = rte_membership_lookup(setsum_ht, &key, &target_ht);
+ ret_cache = rte_membership_lookup(setsum_cache, &key, &target_cache);
+ ret_bf = rte_membership_lookup(setsum_bf, &key, &target_bf);
+ ret_vbf = rte_membership_lookup(setsum_vbf, &key, &target_vbf);
+ printf("lookup delete target:%d, %d, %d, %d\n", target_ht, target_cache,
+ target_bf, target_vbf);
+ printf("lookup delete ret:%d, %d, %d, %d\n", ret_ht, ret_cache,
+ ret_bf, ret_vbf);
+ return 0;
+}
+
+
+static int test_membership_multimatch(void)
+{
+ int ret_ht, ret_vbf, ret_cache, ret_bf;
+ MEMBERSHIP_TARGET_TYPE target_ids_ht[32] = {0};
+ MEMBERSHIP_TARGET_TYPE target_ids_vbf[32] = {0};
+ MEMBERSHIP_TARGET_TYPE target_ids_bf[32] = {0};
+ MEMBERSHIP_TARGET_TYPE target_ids_cache[32] = {0};
+
+ MEMBERSHIP_TARGET_TYPE target_ids_ht_m[2][32] = {{0}};
+ MEMBERSHIP_TARGET_TYPE target_ids_vbf_m[2][32] = {{0}};
+ MEMBERSHIP_TARGET_TYPE target_ids_bf_m[2][32] = {{0}};
+ MEMBERSHIP_TARGET_TYPE target_ids_cache_m[2][32] = {{0}};
+ uint32_t key = KEY;
+ uint32_t key1 = KEY1;
+ uint32_t* key_array[8];
+ uint32_t match_count_ht[8];
+ uint32_t match_count_vbf[8];
+ uint32_t match_count_cache[8];
+ uint32_t match_count_bf[8];
+
+ uint32_t num_key_ht = 2;
+ uint32_t num_key_vbf = 2;
+ uint32_t num_key_cache = 2;
+ uint32_t num_key_bf = 2;
+
+ uint32_t i, j;
+ /* same key at most inserted 2*entry_per_bucket times for HT mode */
+ for (i = 1; i < 33; i++) {
+ ret_ht = rte_membership_add(setsum_ht, &key, i);
+ ret_ht = rte_membership_add(setsum_ht, &key1, i);
+ ret_vbf = rte_membership_add(setsum_vbf, &key, i);
+ ret_vbf = rte_membership_add(setsum_vbf, &key1, i);
+
+ /* for cache and bf mode, they do not support multimatch
+ * the mutimatch should works like single match
+ */
+ ret_cache = rte_membership_add(setsum_cache, &key, i);
+ ret_cache = rte_membership_add(setsum_cache, &key1, i);
+ ret_bf = rte_membership_add(setsum_bf, &key, 1);
+ ret_bf = rte_membership_add(setsum_bf, &key1, 1);
+
+ RETURN_IF_ERROR(ret_ht < 0 || ret_vbf < 0 || ret_cache < 0 ||
+ ret_bf < 0, "insert error");
+ }
+
+ /* single multimatch test */
+ ret_vbf = rte_membership_lookup_multi(setsum_vbf, &key, target_ids_vbf);
+ ret_ht = rte_membership_lookup_multi(setsum_ht, &key, target_ids_ht);
+ ret_bf = rte_membership_lookup_multi(setsum_bf, &key, target_ids_bf);
+ ret_cache = rte_membership_lookup_multi(setsum_cache, &key, target_ids_cache);
+ RETURN_IF_ERROR(ret_ht < 0 || ret_vbf < 0 || ret_cache < 0 ||
+ ret_bf < 0, "lookup_multi error");
+
+ for (i=0; i < (uint32_t)ret_ht; i++) {
+ printf("%d,", target_ids_ht[i]);
+ RETURN_IF_ERROR(target_ids_ht[i] != target_ids_vbf[i],
+ "singl multimatch lookup error");
+ }
+ printf("\n");
+
+ /* bulk multimatch test */
+ key_array[0] = &key;
+ key_array[1] = &key1;
+ ret_vbf = rte_membership_lookup_multi_bulk(setsum_vbf,
+ (const void **)key_array, num_key_ht, 32, match_count_vbf,
+ (MEMBERSHIP_TARGET_TYPE *)target_ids_vbf_m);
+
+ ret_ht = rte_membership_lookup_multi_bulk(setsum_ht,
+ (const void **)key_array, num_key_vbf, 32, match_count_ht,
+ (MEMBERSHIP_TARGET_TYPE *)target_ids_ht_m);
+
+ ret_cache = rte_membership_lookup_multi_bulk(setsum_cache,
+ (const void **)key_array, num_key_cache, 32, match_count_cache,
+ (MEMBERSHIP_TARGET_TYPE *)target_ids_cache_m);
+
+ ret_bf = rte_membership_lookup_multi_bulk(setsum_bf,
+ (const void **)key_array, num_key_bf, 32, match_count_bf,
+ (MEMBERSHIP_TARGET_TYPE *)target_ids_bf_m);
+
+
+ for (i = 0; i < num_key_ht; i++) {
+ printf("ht match count %d %d\n", match_count_ht[0], match_count_ht[1]);
+ printf("vbf match count %d %d\n", match_count_vbf[0], match_count_vbf[1]);
+ printf("cache match count %d %d\n", match_count_cache[0], match_count_cache[1]);
+ printf("bf match count %d %d\n", match_count_bf[0], match_count_bf[1]);
+ }
+
+
+ for (i = 0; i < num_key_ht; i++) {
+ printf("target for key %d: ", i);
+ printf("ht:");
+ for (j = 0; j < match_count_ht[i]; j++) {
+ printf("%d,", target_ids_ht_m[i][j]);
+ }
+ printf("vbf:");
+ for (j = 0; j < match_count_vbf[i]; j++) {
+ printf("%d,", target_ids_vbf_m[i][j]);
+ }
+ printf("cache:");
+ for (j = 0; j < match_count_cache[i]; j++) {
+ printf("%d,", target_ids_cache_m[i][j]);
+ }
+ printf("bf:");
+ for (j = 0; j < match_count_bf[i]; j++) {
+ printf("%d,", target_ids_bf_m[i][j]);
+ }
+ printf("\n");
+ }
+ return 0;
+}
+
+
+
+
+static int test_membership_loadfactor(void)
+{
+ uint8_t simple_key[MAX_KEYSIZE];
+ unsigned i, j;
+ unsigned added_keys, average_keys_added = 0;
+ int ret;
+
+ rte_membership_reset(setsum_ht);
+ rte_membership_reset(setsum_cache);
+
+
+ /* test HT mode */
+ for (j = 0; j < ITERATIONS; j++) {
+ ret = 0;
+ /* Add random entries until key cannot be added */
+ for (added_keys = 0; ret >= 0; added_keys++) {
+ for (i = 0; i < params.key_len; i++)
+ simple_key[i] = rte_rand() % 255;
+ uint16_t target = rte_rand() % ((1 << 16) - 1);
+ ret = rte_membership_add(setsum_ht, simple_key, target);
+ }
+ if (ret != -ENOSPC) {
+ printf("Unexpected error when adding keys\n");
+ return -1;
+ }
+
+ average_keys_added += added_keys;
+
+ /* Reset the table */
+ rte_membership_reset(setsum_ht);
+
+ /* Print a dot to show progress on operations */
+ printf(".");
+ fflush(stdout);
+ }
+
+ average_keys_added /= ITERATIONS;
+
+ printf("\nAverage table utilization for HT mode = %.2f%% (%u/%u)\n",
+ ((double) average_keys_added / params.num_keys * 100),
+ average_keys_added, params.num_keys);
+
+
+
+ /* test cache mode */
+ added_keys = average_keys_added = 0;
+ for (j = 0; j < ITERATIONS; j++) {
+ ret = 0;
+ /* Add random entries until key cannot be added */
+ for (added_keys = 0; ret == 0; added_keys++) {
+ for (i = 0; i < params.key_len; i++)
+ simple_key[i] = rte_rand() % 255;
+ uint16_t target = rte_rand() % ((1 << 16) - 1);
+ ret = rte_membership_add(setsum_cache, simple_key, target);
+ }
+ if (ret != 1) {
+ printf("Unexpected error when adding keys\n");
+ return -1;
+ }
+
+ average_keys_added += added_keys;
+
+ /* Reset the table */
+ rte_membership_reset(setsum_cache);
+
+ /* Print a dot to show progress on operations */
+ printf(".");
+ fflush(stdout);
+ }
+
+ average_keys_added /= ITERATIONS;
+
+ printf("\nAverage table utilization for cache mode = %.2f%% (%u/%u)\n",
+ ((double) average_keys_added / params.num_keys * 100),
+ average_keys_added, params.num_keys);
+ return 0;
+}
+
+
+
+
+
+
+static int
+test_membership(void)
+{
+
+ /* Simple tests for initial debug usage */
+ if (test_membership_create() < 0) {
+ rte_membership_free(setsum_ht);
+ rte_membership_free(setsum_cache);
+ rte_membership_free(setsum_bf);
+ rte_membership_free(setsum_vbf);
+ return -1;
+ }
+ if (test_membership_insert() < 0) {
+ rte_membership_free(setsum_ht);
+ rte_membership_free(setsum_cache);
+ rte_membership_free(setsum_bf);
+ rte_membership_free(setsum_vbf);
+ return -1;
+ }
+ if (test_membership_lookup() < 0) {
+ rte_membership_free(setsum_ht);
+ rte_membership_free(setsum_cache);
+ rte_membership_free(setsum_bf);
+ rte_membership_free(setsum_vbf);
+ return -1;
+ }
+ if (test_membership_delete() < 0) {
+ rte_membership_free(setsum_ht);
+ rte_membership_free(setsum_cache);
+ rte_membership_free(setsum_bf);
+ rte_membership_free(setsum_vbf);
+ return -1;
+ }
+ if (test_membership_multimatch() < 0) {
+ rte_membership_free(setsum_ht);
+ rte_membership_free(setsum_cache);
+ rte_membership_free(setsum_bf);
+ rte_membership_free(setsum_vbf);
+ return -1;
+ }
+
+
+ if (test_membership_loadfactor() < 0) {
+ rte_membership_free(setsum_ht);
+ rte_membership_free(setsum_cache);
+ }
+ /* more complex test */
+ /* FIXME: to be implemented */
+
+ return 0;
+}
+
+REGISTER_TEST_COMMAND(membership_autotest, test_membership);