From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mout.gmx.net (mout.gmx.net [212.227.15.19]) (using TLSv1 with cipher DHE-RSA-AES128-SHA (128/128 bits)) (Client CN "mout.gmx.net", Issuer "TeleSec ServerPass DE-1" (verified OK)) by huchra.bufferbloat.net (Postfix) with ESMTPS id 2AEC921F1CA for ; Sat, 28 Dec 2013 05:42:13 -0800 (PST) Received: from [192.168.2.43] ([79.202.2.233]) by mail.gmx.com (mrgmx102) with ESMTPSA (Nemesis) id 0LaaVn-1VBEeZ0Axz-00mKKU for ; Sat, 28 Dec 2013 14:42:10 +0100 Content-Type: multipart/mixed; boundary="Apple-Mail=_ECBD3467-0744-4FDD-B95E-51D2AAEBC818" Mime-Version: 1.0 (Mac OS X Mail 6.6 \(1510\)) From: Sebastian Moeller In-Reply-To: <52BEB166.903@imap.cc> Date: Sat, 28 Dec 2013 14:42:02 +0100 Message-Id: <48F50AF1-018A-400F-BBA4-D6F6B95B8AD2@gmx.de> References: <75A7B6AE-8ECA-4FAC-B4D3-08FD14078DA2@gmail.com> <52BEB166.903@imap.cc> To: Fred Stratton X-Mailer: Apple Mail (2.1510) X-Provags-ID: V03:K0:hW7PeFAq/5aANEYRwYjBma60qSEVGTILTrW3sqgfTQDxX/oOHqs ScgmZ/3JheOSQCsuZTgx/jqaOgMbOEI8X1yVhynio3do2wd/RUHaP7UgSVdYPhXemg44HPp dOUNPDojol8RfeSM48cqIPlXyJm7wsY4ckvgv5/qYnT8o/Y+g7WdcWxqEyqkijyr60anl6r MobMDxoMn2O/UjN6uDXJA== Cc: cerowrt-devel@lists.bufferbloat.net Subject: Re: [Cerowrt-devel] Update to "Setting up SQM for CeroWrt 3.10" web page. Comments needed. X-BeenThere: cerowrt-devel@lists.bufferbloat.net X-Mailman-Version: 2.1.13 Precedence: list List-Id: Development issues regarding the cerowrt test router project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 28 Dec 2013 13:42:14 -0000 --Apple-Mail=_ECBD3467-0744-4FDD-B95E-51D2AAEBC818 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=windows-1252 Hi Fred, On Dec 28, 2013, at 12:09 , Fred Stratton wrote: > IThe UK consensus fudge factor has always been 85 per cent of the rate = achieved, not 95 or 99 per cent. I know that the recommendations have been lower in the past; I = think this is partly because before Jesper Brouer's and Russels Stuart's = work to properly account for ATM "quantization" people typically had to = deal with a ~10% rate tax for the 5byte per cell overhead (48 byte = payload in 53 byte cells 90.57% useable rate) plus an additional 5% to = stochastically account for the padding of the last cell and the per = packet overhead both of which affect the effective good put way more for = small than large packets, so the 85% never worked well for all packet = sizes. My hypothesis now is since we can and do properly account for = these effects of ATM framing we can afford to start with a fudge factor = of 90% or even 95% percent. As far as I know the recommended fudge = factors are never ever explained by more than "this works = empirically"... >=20 > Devices express 2 values: the sync rate - or 'maximum rate attainable' = - and the dynamic value of 'current rate'. The actual data rate is the relevant information for shaping, = often DSL modems report the link capacity as "maximum rate attainable" = or some such, while the actual bandwidth is limited to a rate below what = the line would support by contract (often this bandwidth reduction is = performed on the PPPoE link to the BRAS). >=20 > As the sync rate is fairly stable for any given installation - ADSL or = Fibre - this could be used as a starting value. decremented by the = traditional 15 per cent of 'overhead'. and the 85 per cent fudge factor = applied to that. I would like to propose to use the "current rate" as starting = point, as 'maximum rate attainable' >=3D 'current rate'. >=20 > Fibre - FTTC - connections can suffer quite large download speed = fluctuations over the 200 - 500 metre link to the MSAN. This phenomenon = is not confined to ADSL links. On the actual xDSL link? As far as I know no telco actually uses = SRA (seamless rate adaptation or so) so the current link speed will only = get lower not higher, so I would expect a relative stable current rate = (it might take a while, a few days to actually slowly degrade to the = highest link speed supported under all conditions, but I hope you still = get my point). >=20 >=20 > An alternative speed test is something like this >=20 > http://download.bethere.co.uk/downloadMeter.html >=20 > which, as Be has been bought by Sky, may not exist after the end of = April 2014. But, if we recommend to run speed tests we really need to advise = our users to start several concurrent up- and downloads to independent = servers to actually measure the bandwidth of our bottleneck link; often = a single server connection will not saturate a link (I seem to recall = that with TCP it is guaranteed to only reach 75% or so averaged over = time, is that correct?). But I think this is not the proper way to set the bandwidth for = the shaper, because upstream of our link to the ISP we have no = guaranteed bandwidth at all and just can hope the ISP is oing the right = thing AQM-wise. >=20 > =95 [What is the proper description here?] If you use PPPoE (but = not over ADSL/DSL link), PPPoATM, or bridging that isn=92t Ethernet, you = should choose [what?] and set the Per-packet Overhead to [what?] >=20 > For a PPPoA service, the PPPoA link is treated as PPPoE on the second = device, here running ceroWRT. This still means you should specify the PPPoA overhead, not = PPPoE. > The packet overhead values are written in the dubious man page for = tc_stab. The only real flaw in that man page, as far as I know, is the = fact that it indicates that the kernel will account for the 18byte = ethernet header automatically, while the kernel does no such thing = (which I hope to change). > Sebastian has a potential alternative method of formal calculation. So, I have no formal calculation method available, but an = empirical way of detecting ATM quantization as well as measuring the per = packet overhead of an ATM link.=20 The idea is to measure the RTT of ICMP packets of increasing = length and then displaying the distribution of RTTs by ICMP packet = length, on an ATM carrier we expect to see a step function with steps 48 = bytes apart. For non-ATM carrier we expect to rather see a smooth ramp. = By comparing the residuals of a linear fit of the data with the = residuals of the best step function fit to the data. The fit with the = lower residuals "wins". Attached you will find an example of this = approach, ping data in red (median of NNN repetitions for each ICMP = packet size), linear fit in blue, and best staircase fit in green. You = notice that data starts somewhere in a 48 byte ATM cell. Since the ATM = encapsulation overhead is maximally 44 bytes and we know the IP and ICMP = overhead of the ping probe we can calculate the overhead preceding the = IP header, which is what needs to be put in the overhead field in the = GUI. (Note where the green line intersect the y-axis at 0 bytes packet = size? this is where the IP header starts, the "missing" part of this ATM = cell is the overhead). --Apple-Mail=_ECBD3467-0744-4FDD-B95E-51D2AAEBC818 Content-Disposition: inline; filename=PastedGraphic-1.tiff Content-Type: image/tiff; x-unix-mode=0666; name="PastedGraphic-1.tiff" Content-Transfer-Encoding: base64 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 DCIcygq/vNnUDUHULUPUTUXUYdHE4+869LnGV98ctFEPcPM9Ff7M8ApM0AbAhRM8m66McfTReQMf PS+fvQ4fHT7LbUfWjWnWrWvWzW2Yy5cQg7aMLXPUs7HXU7fXLXcQjQ268fLXzV0fPV+tEfXWK+zW QfDWZRbW7YvYzY3Y7Y/ZBBPUkfbX8/y628rX3WXI1e7YMfTYXPjZTLSgvLfZHaXabafajanao1Qz kJXa4wTVsYDa67kwPbEcPbPbA3s0ci6wwwOCiUPa/bVAm/o40GDcbavcjcncrcvczc0fLOnUMgSL Aw3dIw5RXc7djdndrdvdzd0Sc7DdDd7eLePeTeXebefegw7eDeneze3e7e/fDfHfIdHevfPfbfff jfnfrfvaffXfzf/gDgHgLgPgSYvf7gXgjgngrgvgzg1BTgfg7hHhLhPhThXhY1ThDhfhrhvhzh3h 7h8evhniDiPiTiXibifiXiLijivizi3i7i/fbirjDjPjTjXjbjfaXjLjjjvjzj3j7j+5PjrkDkPk TkXkbkdsHkLkjkvkzk3k7k8+XkrlDlPlTlXlblfhg6PeHljlzl3l7l/mAvzlLmHmTmXmbmfmjfTl rmnmzm3m7m/nA6zlvnHnTnXnbnfjfmPnjnvnzn3n7hXnrn/oLoPoToXfPoHobonorovozcvojo3p DpHpLpPUYQGAMCBP8AQWDQeEQmFQuGQ2HQ+IRGJROKRWLReMRmNRuOR2PR+QSGRSOSSWTSeUSmVS uWS2XS+YTGZTOaTWbTecTmdTueT2fT+gUGhUOiUWOQJgQSjUumU2nU+oVGpVOqVWrVesVmtVuuV2 vV+wWGxWOyVKkUqy2m1Wu2W23W+4XG5XO6XW7Xe8Xm9Xu+TWz33AYHBYPCYXDYfEYnFYvGY3HY/I RC/5HKZXLZfMZnNZvOZ3PZ/QaHK5PRaXTafUanVavWa3Xa/YbGnaTZbXbbfcbndbveb3fb/gTTac HicXjcfkcnlcvmc3nUXh8/pdPqdXrdfsdntdvB9Hud/weHxePyeXzefy970ev2e33e/4fH5fO5er 6ff8fn9fv+f3/P+gz7QBAcCQLA0DwRBMFMzAUFwdB8IQjCUJwpCqeQbC0Mw1DcOQ7D0PwHDEQRHE kSxNE8URS20RRVFsXRfGEYxlGa2xZGkbxxHMdR3HkepKgIAADwEAAAMAAAABAjAAAAEBAAMAAAAB AeIAAAECAAMAAAAEAAC55AEDAAMAAAABAAUAAAEGAAMAAAABAAIAAAERAAQAAAAJAAC57AESAAMA AAABAAEAAAEVAAMAAAABAAQAAAEWAAMAAAABADoAAAEXAAQAAAAJAAC6EAEcAAMAAAABAAEAAAE9 AAMAAAABAAIAAAFSAAMAAAABAAEAAAFTAAMAAAAEAAC6NIdzAAcAAAxIAAC6PAAAAAAACAAIAAgA CAAAAAgAAGWPAABy1wAAes4AAIVIAACOHAAAljsAAJ1AAAC3uQAAZYcAAA1IAAAH9wAACnoAAAjU AAAIHwAABwUAABp5AAABcQABAAEAAQABAAAMSExpbm8CEAAAbW50clJHQiBYWVogB84AAgAJAAYA MQAAYWNzcE1TRlQAAAAASUVDIHNSR0IAAAAAAAAAAAAAAAAAAPbWAAEAAAAA0y1IUCAgAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARY3BydAAAAVAAAAAzZGVz YwAAAYQAAABsd3RwdAAAAfAAAAAUYmtwdAAAAgQAAAAUclhZWgAAAhgAAAAUZ1hZWgAAAiwAAAAU YlhZWgAAAkAAAAAUZG1uZAAAAlQAAABwZG1kZAAAAsQAAACIdnVlZAAAA0wAAACGdmlldwAAA9QA AAAkbHVtaQAAA/gAAAAUbWVhcwAABAwAAAAkdGVjaAAABDAAAAAMclRSQwAABDwAAAgMZ1RSQwAA BDwAAAgMYlRSQwAABDwAAAgMdGV4dAAAAABDb3B5cmlnaHQgKGMpIDE5OTggSGV3bGV0dC1QYWNr YXJkIENvbXBhbnkAAGRlc2MAAAAAAAAAEnNSR0IgSUVDNjE5NjYtMi4xAAAAAAAAAAAAAAASc1JH QiBJRUM2MTk2Ni0yLjEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAFhZWiAAAAAAAADzUQABAAAAARbMWFlaIAAAAAAAAAAAAAAAAAAAAABYWVogAAAAAAAA b6IAADj1AAADkFhZWiAAAAAAAABimQAAt4UAABjaWFlaIAAAAAAAACSgAAAPhAAAts9kZXNjAAAA AAAAABZJRUMgaHR0cDovL3d3dy5pZWMuY2gAAAAAAAAAAAAAABZJRUMgaHR0cDovL3d3dy5pZWMu Y2gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZGVzYwAAAAAA AAAuSUVDIDYxOTY2LTIuMSBEZWZhdWx0IFJHQiBjb2xvdXIgc3BhY2UgLSBzUkdCAAAAAAAAAAAA AAAuSUVDIDYxOTY2LTIuMSBEZWZhdWx0IFJHQiBjb2xvdXIgc3BhY2UgLSBzUkdCAAAAAAAAAAAA AAAAAAAAAAAAAAAAAGRlc2MAAAAAAAAALFJlZmVyZW5jZSBWaWV3aW5nIENvbmRpdGlvbiBpbiBJ RUM2MTk2Ni0yLjEAAAAAAAAAAAAAACxSZWZlcmVuY2UgVmlld2luZyBDb25kaXRpb24gaW4gSUVD NjE5NjYtMi4xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB2aWV3AAAAAAATpP4AFF8uABDPFAAD 7cwABBMLAANcngAAAAFYWVogAAAAAABMCVYAUAAAAFcf521lYXMAAAAAAAAAAQAAAAAAAAAAAAAA AAAAAAAAAAKPAAAAAnNpZyAAAAAAQ1JUIGN1cnYAAAAAAAAEAAAAAAUACgAPABQAGQAeACMAKAAt ADIANwA7AEAARQBKAE8AVABZAF4AYwBoAG0AcgB3AHwAgQCGAIsAkACVAJoAnwCkAKkArgCyALcA vADBAMYAywDQANUA2wDgAOUA6wDwAPYA+wEBAQcBDQETARkBHwElASsBMgE4AT4BRQFMAVIBWQFg AWcBbgF1AXwBgwGLAZIBmgGhAakBsQG5AcEByQHRAdkB4QHpAfIB+gIDAgwCFAIdAiYCLwI4AkEC SwJUAl0CZwJxAnoChAKOApgCogKsArYCwQLLAtUC4ALrAvUDAAMLAxYDIQMtAzgDQwNPA1oDZgNy A34DigOWA6IDrgO6A8cD0wPgA+wD+QQGBBMEIAQtBDsESARVBGMEcQR+BIwEmgSoBLYExATTBOEE 8AT+BQ0FHAUrBToFSQVYBWcFdwWGBZYFpgW1BcUF1QXlBfYGBgYWBicGNwZIBlkGagZ7BowGnQav BsAG0QbjBvUHBwcZBysHPQdPB2EHdAeGB5kHrAe/B9IH5Qf4CAsIHwgyCEYIWghuCIIIlgiqCL4I 0gjnCPsJEAklCToJTwlkCXkJjwmkCboJzwnlCfsKEQonCj0KVApqCoEKmAquCsUK3ArzCwsLIgs5 C1ELaQuAC5gLsAvIC+EL+QwSDCoMQwxcDHUMjgynDMAM2QzzDQ0NJg1ADVoNdA2ODakNww3eDfgO Ew4uDkkOZA5/DpsOtg7SDu4PCQ8lD0EPXg96D5YPsw/PD+wQCRAmEEMQYRB+EJsQuRDXEPURExEx EU8RbRGMEaoRyRHoEgcSJhJFEmQShBKjEsMS4xMDEyMTQxNjE4MTpBPFE+UUBhQnFEkUahSLFK0U zhTwFRIVNBVWFXgVmxW9FeAWAxYmFkkWbBaPFrIW1hb6Fx0XQRdlF4kXrhfSF/cYGxhAGGUYihiv GNUY+hkgGUUZaxmRGbcZ3RoEGioaURp3Gp4axRrsGxQbOxtjG4obshvaHAIcKhxSHHscoxzMHPUd Hh1HHXAdmR3DHeweFh5AHmoelB6+HukfEx8+H2kflB+/H+ogFSBBIGwgmCDEIPAhHCFIIXUhoSHO IfsiJyJVIoIiryLdIwojOCNmI5QjwiPwJB8kTSR8JKsk2iUJJTglaCWXJccl9yYnJlcmhya3Jugn GCdJJ3onqyfcKA0oPyhxKKIo1CkGKTgpaymdKdAqAio1KmgqmyrPKwIrNitpK50r0SwFLDksbiyi LNctDC1BLXYtqy3hLhYuTC6CLrcu7i8kL1ovkS/HL/4wNTBsMKQw2zESMUoxgjG6MfIyKjJjMpsy 1DMNM0YzfzO4M/E0KzRlNJ402DUTNU01hzXCNf02NzZyNq426TckN2A3nDfXOBQ4UDiMOMg5BTlC OX85vDn5OjY6dDqyOu87LTtrO6o76DwnPGU8pDzjPSI9YT2hPeA+ID5gPqA+4D8hP2E/oj/iQCNA ZECmQOdBKUFqQaxB7kIwQnJCtUL3QzpDfUPARANER0SKRM5FEkVVRZpF3kYiRmdGq0bwRzVHe0fA SAVIS0iRSNdJHUljSalJ8Eo3Sn1KxEsMS1NLmkviTCpMcky6TQJNSk2TTdxOJU5uTrdPAE9JT5NP 3VAnUHFQu1EGUVBRm1HmUjFSfFLHUxNTX1OqU/ZUQlSPVNtVKFV1VcJWD1ZcVqlW91dEV5JX4Fgv WH1Yy1kaWWlZuFoHWlZaplr1W0VblVvlXDVchlzWXSddeF3JXhpebF69Xw9fYV+zYAVgV2CqYPxh T2GiYfViSWKcYvBjQ2OXY+tkQGSUZOllPWWSZedmPWaSZuhnPWeTZ+loP2iWaOxpQ2maafFqSGqf avdrT2una/9sV2yvbQhtYG25bhJua27Ebx5veG/RcCtwhnDgcTpxlXHwcktypnMBc11zuHQUdHB0 zHUodYV14XY+dpt2+HdWd7N4EXhueMx5KnmJeed6RnqlewR7Y3vCfCF8gXzhfUF9oX4BfmJ+wn8j f4R/5YBHgKiBCoFrgc2CMIKSgvSDV4O6hB2EgITjhUeFq4YOhnKG14c7h5+IBIhpiM6JM4mZif6K ZIrKizCLlov8jGOMyo0xjZiN/45mjs6PNo+ekAaQbpDWkT+RqJIRknqS45NNk7aUIJSKlPSVX5XJ ljSWn5cKl3WX4JhMmLiZJJmQmfyaaJrVm0Kbr5wcnImc951kndKeQJ6unx2fi5/6oGmg2KFHobai JqKWowajdqPmpFakx6U4pammGqaLpv2nbqfgqFKoxKk3qamqHKqPqwKrdavprFys0K1ErbiuLa6h rxavi7AAsHWw6rFgsdayS7LCszizrrQltJy1E7WKtgG2ebbwt2i34LhZuNG5SrnCuju6tbsuu6e8 IbybvRW9j74KvoS+/796v/XAcMDswWfB48JfwtvDWMPUxFHEzsVLxcjGRsbDx0HHv8g9yLzJOsm5 yjjKt8s2y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DY ZNjo2WzZ8dp22vvbgNwF3IrdEN2W3hzeot8p36/gNuC94UThzOJT4tvjY+Pr5HPk/OWE5g3mlucf 56noMui86Ubp0Opb6uXrcOv77IbtEe2c7ijutO9A78zwWPDl8XLx//KM8xnzp/Q09ML1UPXe9m32 +/eK+Bn4qPk4+cf6V/rn+3f8B/yY/Sn9uv5L/tz/bf// --Apple-Mail=_ECBD3467-0744-4FDD-B95E-51D2AAEBC818 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=windows-1252 Believe it or not, this methods works reasonable well (I tested = successfully with one Bridged, LLC/SNAP RFC-1483/2684 connection = (overhead 32 bytes), and several PPPOE, LLC, (overhead 40) connections = (from ADSL1 @ 3008/512 to ADSL2+ @ 16402/2558)). But it takes relative = long time to measure the ping train especially at the higher rates=85 = and it requires ping time stamps with decent resolution (which rules out = windows) and my naive data acquisition scripts creates really large raw = data files. I guess I should post the code somewhere so others can test = and improve it. Fred I would be delighted to get a data set from your = connection, to test a known different encapsulation.=20 > TYPICAL OVERHEADS > The following values are typical for different adsl scenarios = (based on > [1] and [2]): >=20 > LLC based: > PPPoA - 14 (PPP - 2, ATM - 12) > PPPoE - 40+ (PPPoE - 8, ATM - 18, ethernet 14, possibly FCS = - 4+padding) > Bridged - 32 (ATM - 18, ethernet 14, possibly FCS - = 4+padding) > IPoA - 16 (ATM - 16) >=20 > VC Mux based: > PPPoA - 10 (PPP - 2, ATM - 8) > PPPoE - 32+ (PPPoE - 8, ATM - 10, ethernet 14, possibly FCS = - 4+padding) > Bridged - 24+ (ATM - 10, ethernet 14, possibly FCS - = 4+padding) > IPoA - 8 (ATM - 8) >=20 >=20 > For VC Mux based PPPoA, I am currently using an overhead of 18 for the = PPPoE setting in ceroWRT. Yeah we could put this list into the wiki, but how shall a = typical user figure out which encapsulation is used? And good luck in = figuring out whether the frame check sequence (FCS) is included or not=85 BTW 18, I predict that if PPPoE is only used between cerowrt and the = "modem' or gateway your effective overhead should be 10 bytes; I would = love if you could run the following against your link at night (also = attached=20= --Apple-Mail=_ECBD3467-0744-4FDD-B95E-51D2AAEBC818 Content-Disposition: attachment; filename=ping_sweeper5_fs.sh Content-Type: application/octet-stream; name="ping_sweeper5_fs.sh" Content-Transfer-Encoding: 7bit #! /bin/bash # TODO use seq or bash to generate a list of the requested sizes (to allow for non-equidistantly spaced sizes) # TECH=ADSL2 # just a name... # finding a proper target IP is somewhat of an art, just traceroute a remote site # and find the nearest host reliably responding to pings showing the smallet variation of pingtimes TARGET=${1} # which ip to ping DATESTR=`date +%Y%m%d_%H%M%S` # to allow multiple sequential records LOG=ping_sweep_${TECH}_${DATESTR}.txt # by default non-root ping will only end one packet per second, so work around that by calling ping independently for each package # empirically figure out the shortest period still giving the standard ping time (to avoid being slow-pathed by our target) PINGPERIOD=0.01 # in seconds PINGSPERSIZE=10000 # Start, needed to find the per packet overhead dependent on the ATM encapsulation # to reiably show ATM quantization one would like to see at least two steps, so cover a range > 2 ATM cells (so > 96 bytes) SWEEPMINSIZE=16 # 64bit systems seem to require 16 bytes of payload to include a timestamp... SWEEPMAXSIZE=116 n_SWEEPS=`expr ${SWEEPMAXSIZE} - ${SWEEPMINSIZE}` i_sweep=0 i_size=0 echo "Running ICMP RTT measurement against: ${TARGET}" while [ ${i_sweep} -lt ${PINGSPERSIZE} ] do (( i_sweep++ )) echo "Current iteration: ${i_sweep}" # now loop from sweepmin to sweepmax i_size=${SWEEPMINSIZE} while [ ${i_size} -le ${SWEEPMAXSIZE} ] do echo "${i_sweep}. repetition of ping size ${i_size}" ping -c 1 -s ${i_size} ${TARGET} >> ${LOG} & (( i_size++ )) # we need a sleep binary that allows non integer times (GNU sleep is fine as is sleep of macosx 10.8.4) sleep ${PINGPERIOD} done done #tail -f ${LOG} echo "Done... ($0)" --Apple-Mail=_ECBD3467-0744-4FDD-B95E-51D2AAEBC818 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=windows-1252 ): #! /bin/bash # TODO use seq or bash to generate a list of the requested sizes (to = allow for non-equidistantly spaced sizes) #. TECH=3DADSL2 # just to give some meaning to the ping trace file name # finding a proper target IP is somewhat of an art, just traceroute a = remote site. # and find the nearest host reliably responding to pings showing the = smallet variation of pingtimes TARGET=3D${1} # the IP against which to run the ICMP pings DATESTR=3D`date +%Y%m%d_%H%M%S`<-># to allow multiple sequential records LOG=3Dping_sweep_${TECH}_${DATESTR}.txt # by default non-root ping will only end one packet per second, so work = around that by calling ping independently for each package # empirically figure out the shortest period still giving the standard = ping time (to avoid being slow-pathed by our target) PINGPERIOD=3D0.01><------># in seconds PINGSPERSIZE=3D10000 # Start, needed to find the per packet overhead dependent on the ATM = encapsulation # to reiably show ATM quantization one would like to see at least two = steps, so cover a range > 2 ATM cells (so > 96 bytes) SWEEPMINSIZE=3D16><------># 64bit systems seem to require 16 bytes of = payload to include a timestamp... SWEEPMAXSIZE=3D116 n_SWEEPS=3D`expr ${SWEEPMAXSIZE} - ${SWEEPMINSIZE}` i_sweep=3D0 i_size=3D0 echo "Running ICMP RTT measurement against: ${TARGET}" while [ ${i_sweep} -lt ${PINGSPERSIZE} ] do (( i_sweep++ )) echo "Current iteration: ${i_sweep}" # now loop from sweepmin to sweepmax i_size=3D${SWEEPMINSIZE} while [ ${i_size} -le ${SWEEPMAXSIZE} ] do echo "${i_sweep}. repetition of ping size ${i_size}" ping -c 1 -s ${i_size} ${TARGET} >> ${LOG} &\ (( i_size++ )) # we need a sleep binary that allows non integer times (GNU = sleep is fine as is sleep of macosx 10.8.4) sleep ${PINGPERIOD} done done echo "Done... ($0)" This will try to run 10000 repetitions for ICMP packet sizes from 16 to = 116 bytes running (10000 * 101 * 0.01 / 60 =3D) 168 minutes, but you = should be able to stop it with ctrl c if you are not patience enough, = with your link I would estimate that 3000 should be plenty, but if you = could run it over night that would be great and then ~3 hours should not = matter much. And then run the following attached code in octave or matlab=20= --Apple-Mail=_ECBD3467-0744-4FDD-B95E-51D2AAEBC818 Content-Disposition: attachment; filename=tc_stab_parameter_guide_03.m Content-Type: application/octet-stream; name="tc_stab_parameter_guide_03.m" Content-Transfer-Encoding: 7bit function [ output_args ] = tc_stab_parameter_guide_03( sweep_fqn, up_Kbit, down_Kbit ) %TC_STAB_PARAMETER_GUIDE Summary of this function goes here % try to read in the result from a ping sweep run % sweep_fqn: the log file of the ping sweep against the first hop after % the DSL link % up_Kbit: the uplink rate in Kilobits per second % down_Kbit: the downlink rate in Kilobits per second % % TODO: % find whether the carrier is ATM quantized (via FFT?) % test whther best stair fits better than a simple linear regresson % line? % if yes: % what is the RTT step (try to deduce the combined up and down rates from this) % estimate the best MTU for the estimated protocol stack (how to test this?) % 1) estimate the largest MTU that avoids fragmentation (default 1500 - 28 should be largest without fragmentation) % 2) estimate the largest MTU that does not have padding in the last % ATM cell, for this pick the MTU that no partial ATM cell remains % % DONE: % Allow for holes in the ping data (missing sizes) % make sure all sizes are filled (use NaN for empty ones???) % maybe require to give the nominal up and down rates, to estimate the % RTT stepsize % try to figure out the overhead for each packet % %Thoughts: % ask about IPv4 or IPv6 (what about tunneling?) % the sweep should be taken directly connected to the modem to reduce % non-ATM routing delays dbstop if error; if ~(isoctave) timestamps.(mfilename).start = tic; else tic(); end disp(['Starting: ', mfilename]); output_args = []; % control options show_mean = 0; % the means are noisier than the medians show_median = 1; % the median seems the way to go show_min = 1; % the min should be the best measure, but in the ATM test sweep it is too variable show_max = 0; % only useful for debugging show_sem = 0; % give some estimate of the variance show_ci = 1; % show the confidence interval of the mean, if the mean is shown ci_alpha = 0.05; % alpha for confidence interval calculation use_measure = 'median'; use_processed_results = 1; max_samples_per_size = []; % if not empty only use maximally that many samples per size % if not specified we try to estimate the per cell RTT from the data default_up_Kbit = []; default_down_KBit = []; if (nargin == 0) sweep_fqn = ''; sweep_fqn = fullfile(pwd, 'ping_sweep_ATM.txt'); % was Bridged, LLC/SNAP RFC-1483/2684 connection (overhead 32 bytes - 14 = 18) sweep_fqn = fullfile(pwd, 'ping_sweep_ATM_20130610_234707.txt'); % telekom PPPOE, LLC, overhead 40! sweep_fqn = fullfile(pwd, 'ping_sweep_ATM_20130618_233008.txt'); % telekom PPPOE sweep_fqn = fullfile(pwd, 'ping_sweep_ATM_20130620_234659.txt'); % telekom PPPOE sweep_fqn = fullfile(pwd, 'ping_sweep_ATM_20130618-20.txt'); % telekom PPPOE % sweep_fqn = fullfile(pwd, 'ping_sweep_CABLE_20120426_230227.txt'); % sweep_fqn = fullfile(pwd, 'ping_sweep_CABLE_20120801_001235.txt'); if isempty(sweep_fqn) [sweep_name, sweep_dir] = uigetfile('ping*.txt'); sweep_fqn = fullfile(sweep_dir, sweep_name); end up_Kbit = default_up_Kbit; down_Kbit = default_down_KBit; end if (nargin == 1) up_Kbit = default_up_Kbit; down_Kbit = default_down_KBit; end if (nargin == 2) down_Kbit = default_down_KBit; end %ATM quantum.byte = 48; % ATM packets are always 53 bytes, 48 thereof payload quantum.bit = quantum.byte * 8; ATM_cell.byte = 53; ATM_cell.bit = ATM_cell.byte * 8; % known packet size offsets in bytes offsets.IPv4 = 20; % assume no IPv4 options are used, IP 6 would be 40bytes? offsets.IPv6 = 40; % not used yet... offsets.ICMP = 8; % ICMP header offsets.ethernet = 14; % ethernet header offset.ATM.max_encapsulation_bytes = 44; % see http://ace-host.stuart.id.au/russell/files/tc/tc-atm/ MTU = 1500; % the nominal MTU to the ping host should be 1500, but might be lower if using a VPN % fragmentation will cause an addition relative large increase in RTT (not necessarily registered to the ATM cells) % that will confuse the ATM quantisation offset detector, so exclude all % ping sizes that are potentially affected by fragmentation max_ping_size_without_fragmentation = MTU + offsets.ethernet - offsets.IPv4 - offset.ATM.max_encapsulation_bytes; % unknown offsets is what we need to figure out to feed tc-stab... [sweep_dir, sweep_name] = fileparts(sweep_fqn); cur_parsed_data_mat = [sweep_fqn(1:end-4), '.mat']; if (use_processed_results && ~isempty(dir(cur_parsed_data_mat))) disp(['Loading processed ping data from ', cur_parsed_data_mat]); load(cur_parsed_data_mat, 'ping'); else % read in the result from a ping sweep disp(['Processing ping data from ', sweep_fqn]); ping = parse_ping_output(sweep_fqn); if isempty(ping) disp('No useable ping data found, exiting...'); return end save(cur_parsed_data_mat, 'ping'); end % analyze the data min_ping_size = min(ping.data(:, ping.cols.size)) - offsets.ICMP; disp(['Minimum size of ping payload used: ', num2str(min_ping_size), ' bytes.']); known_overhead = offsets.IPv4; % ping reports the ICMP header already included in size ping.data(:, ping.cols.size) = ping.data(:, ping.cols.size) + known_overhead; % we know we used IPv4 so add the 20 bytes already, so that size are relative to the start of the IP header size_list = unique(ping.data(:, ping.cols.size)); % this is the number of different sizes, but there might be holes/missing sizes max_pingsize = max(size_list); per_size.header = {'size', 'mean', 'median', 'min', 'max', 'std', 'n', 'sem', 'ci'}; per_size.cols = get_column_name_indices(per_size.header); per_size.data = zeros([max_pingsize, length(per_size.header)]) / 0; % NaNs per_size.data(:, per_size.cols.size) = (1:1:max_pingsize); if ~isempty(max_samples_per_size) disp(['Analysing only the first ', num2str(max_samples_per_size), ' samples.']); end for i_size = 1 : length(size_list) cur_size = size_list(i_size); cur_size_idx = find(ping.data(:, ping.cols.size) == cur_size); if ~isempty(max_samples_per_size) n_selected_samples = min([length(cur_size_idx), max_samples_per_size]); cur_size_idx = cur_size_idx(1:n_selected_samples); %disp(['Analysing only the first ', num2str(max_samples_per_size), ' samples of ', num2str(length(cur_size_idx))]); end per_size.data(cur_size, per_size.cols.mean) = mean(ping.data(cur_size_idx, ping.cols.time)); per_size.data(cur_size, per_size.cols.median) = median(ping.data(cur_size_idx, ping.cols.time)); per_size.data(cur_size, per_size.cols.min) = min(ping.data(cur_size_idx, ping.cols.time)); per_size.data(cur_size, per_size.cols.max) = max(ping.data(cur_size_idx, ping.cols.time)); per_size.data(cur_size, per_size.cols.std) = std(ping.data(cur_size_idx, ping.cols.time), 0); per_size.data(cur_size, per_size.cols.n) = length(cur_size_idx); per_size.data(cur_size, per_size.cols.sem) = per_size.data(cur_size, per_size.cols.std) / sqrt(length(cur_size_idx)); per_size.data(cur_size, per_size.cols.ci) = calc_cihw(per_size.data(cur_size, per_size.cols.std), per_size.data(cur_size, per_size.cols.n), ci_alpha); end clear ping % with large data sets 32bit matlab will run into memory issues... figure('Name', sweep_name); hold on; legend_str = {}; if (show_mean) % means legend_str{end + 1} = 'mean'; plot(per_size.data(:, per_size.cols.size), per_size.data(:, per_size.cols.mean), 'Color', [0 1 0 ]); if (show_sem) legend_str{end + 1} = '+sem'; legend_str{end + 1} = '-sem'; plot(per_size.data(:, per_size.cols.size), per_size.data(:, per_size.cols.mean) - per_size.data(:, per_size.cols.sem), 'Color', [0 0.66 0]); plot(per_size.data(:, per_size.cols.size), per_size.data(:, per_size.cols.mean) + per_size.data(:, per_size.cols.sem), 'Color', [0 0.66 0]); end if (show_ci) legend_str{end + 1} = '+ci'; legend_str{end + 1} = '-ci'; plot(per_size.data(:, per_size.cols.size), per_size.data(:, per_size.cols.mean) - per_size.data(:, per_size.cols.ci), 'Color', [0 0.37 0]); plot(per_size.data(:, per_size.cols.size), per_size.data(:, per_size.cols.mean) + per_size.data(:, per_size.cols.ci), 'Color', [0 0.37 0]); end end if(show_median) % median +- standard error of the mean, confidence interval would be % better legend_str{end + 1} = 'median'; plot(per_size.data(:, per_size.cols.size), per_size.data(:, per_size.cols.median), 'Color', [1 0 0]); if (show_sem) legend_str{end + 1} = '+sem'; legend_str{end + 1} = '-sem'; plot(per_size.data(:, per_size.cols.size), per_size.data(:, per_size.cols.median) - per_size.data(:, per_size.cols.sem), 'Color', [0.66 0 0]); plot(per_size.data(:, per_size.cols.size), per_size.data(:, per_size.cols.median) + per_size.data(:, per_size.cols.sem), 'Color', [0.66 0 0]); end if(show_min) % minimum, should be cleanest, but for the test data set looks quite sad... legend_str{end + 1} = 'min'; plot(per_size.data(:, per_size.cols.size), per_size.data(:, per_size.cols.min), 'Color', [0 0 1]); end if(show_max) % minimum, should be cleanest, but for the test data set looks quite sad... legend_str{end + 1} = 'max'; plot(per_size.data(:, per_size.cols.size), per_size.data(:, per_size.cols.max), 'Color', [0 0 0.66]); end end title(['If this plot shows a (noisy) step function with a stepping ~', num2str(quantum.byte), ' bytes then the data carrier is quantised, make sure to use tc-stab']); xlabel('Approximate packet size [bytes]'); ylabel('ICMP round trip times (ping RTT) [ms]'); legend(legend_str, 'Location', 'NorthWest'); hold off; % potentially clean up the data, by interpolating values with large sem % from the neighbours or replacing those with NaNs? % if the size of the ping packet exceeds the MTU the ping packets gets % fragmented the step over this ping size will cause a RTT increaser >> one % RTT_quantum, so exclude all sizes potentially affected by this from the % search space, (for now assume that the route to the ping host actually can carry 1500 byte MTUs...) measured_pingsize_idx = find(~isnan(per_size.data(:, per_size.cols.(use_measure)))); tmp_idx = find(measured_pingsize_idx <= max_ping_size_without_fragmentation); last_non_fragmented_pingsize = measured_pingsize_idx(tmp_idx(end)); ping_sizes_for_linear_fit = measured_pingsize_idx(tmp_idx); % fit a line to the data, to estimate the RTT per byte [p, S] = polyfit(per_size.data(ping_sizes_for_linear_fit, per_size.cols.size), per_size.data(ping_sizes_for_linear_fit, per_size.cols.(use_measure)), 1); RTT_per_byte = p(end - 1); fitted_line = polyval(p, per_size.data(ping_sizes_for_linear_fit, per_size.cols.size), S); input_data = per_size.data(ping_sizes_for_linear_fit, per_size.cols.(use_measure)); % estimate the goodness of the linear fit the same way as for the stair % function linear_cumulative_difference = sum(abs(input_data - fitted_line)); % figure % hold on % plot(per_size.data(ping_sizes_for_linear_fit, per_size.cols.size), per_size.data(ping_sizes_for_linear_fit, per_size.cols.(use_measure)), 'Color', [0 1 0]); % plot(per_size.data(ping_sizes_for_linear_fit, per_size.cols.size), fitted_line, 'Color', [1 0 0]); % hold off % based on the linear fit we can estimate the average RTT per ATM cell estimated_RTT_quantum_ms = RTT_per_byte * 48; % the RTT should equal the average RTT increase per ATM quantum % estimate the RTT step size % at ADSL down 3008kbit/sec up 512kbit/sec we expect, this does not include % processing time if ~isempty(down_Kbit) || ~isempty(up_Kbit) expected_RTT_quantum_ms = (ATM_cell.bit / (down_Kbit * 1024) + ATM_cell.bit / (up_Kbit * 1024) ) * 1000; % this estimate is rather a lower bound for fastpath , so search for best fits else expected_RTT_quantum_ms = estimated_RTT_quantum_ms; end disp(['lower bound estimate for one ATM cell RTT based of specified up and downlink is ', num2str(expected_RTT_quantum_ms), ' ms.']); disp(['estimate for one ATM cell RTT based on linear fit of the ping sweep data is ', num2str(estimated_RTT_quantum_ms), ' ms.']); % lets search from expected_RTT_quantum_ms to 1.5 * expected_RTT_quantum_ms % in steps of expected_RTT_quantum_ms / 100 % to allow for interleaved ATM set ups increase the search space up to 32 % times best fastpath RTT estimate, 64 interleave seems to add 25ms to the % latency, but this only RTT_quantum_list = (expected_RTT_quantum_ms / 2 : expected_RTT_quantum_ms / 100 : 32 * expected_RTT_quantum_ms); quantum_list = (1 : 1 : quantum.byte); % BRUTE FORCE search of best fitting stair... differences = zeros([length(RTT_quantum_list) length(quantum_list)]); cumulative_differences = differences; all_stairs = zeros([length(RTT_quantum_list) length(quantum_list) length(per_size.data(1:last_non_fragmented_pingsize, per_size.cols.(use_measure)))]); for i_RTT_quant = 1 : length(RTT_quantum_list) cur_RTT_quant = RTT_quantum_list(i_RTT_quant); for i_quant = 1 : quantum.byte [differences(i_RTT_quant, i_quant), cumulative_differences(i_RTT_quant, i_quant), all_stairs(i_RTT_quant, i_quant, :)] = ... get_difference_between_data_and_stair( per_size.data(1:last_non_fragmented_pingsize, per_size.cols.size), per_size.data(1:last_non_fragmented_pingsize, per_size.cols.(use_measure)), ... quantum_list(i_quant), quantum.byte, 0, cur_RTT_quant ); end end % for the initial test DSL set the best x_offset was 21, corresponding to 32 bytes overhead before the IP header. [min_cum_diff, min_cum_diff_idx] = min(cumulative_differences(:)); [min_cum_diff_row_idx, min_cum_diff_col_idx] = ind2sub(size(cumulative_differences),min_cum_diff_idx); best_difference = differences(min_cum_diff_row_idx, min_cum_diff_col_idx); disp(['Best staircase fit cumulative difference is: ', num2str(cumulative_differences(min_cum_diff_row_idx, min_cum_diff_col_idx))]); disp(['Best linear fit cumulative difference is: ', num2str(linear_cumulative_difference)]); % judge the quantization if (cumulative_differences(min_cum_diff_row_idx, min_cum_diff_col_idx) < linear_cumulative_difference) % stair fits better than line quant_string = ['Quantized ATM carrier LIKELY (cummulative residual: stair fit ', num2str(cumulative_differences(min_cum_diff_row_idx, min_cum_diff_col_idx)), ' linear fit ', num2str(linear_cumulative_difference)]; else quant_string = ['Quantized ATM carrier UNLIKELY (cummulative residual: stair fit ', num2str(cumulative_differences(min_cum_diff_row_idx, min_cum_diff_col_idx)), ' linear fit ', num2str(linear_cumulative_difference)]; end disp(quant_string); disp(['remaining ATM cell length after ICMP header is ', num2str(quantum_list(min_cum_diff_col_idx)), ' bytes.']); disp(['ICMP RTT of a single ATM cell is ', num2str(RTT_quantum_list(min_cum_diff_col_idx)), ' ms.']); % as first approximation use the ATM cell offset and known offsets (ICMP % IPv4 min_ping_size) to estimate the number of cells used for per paket % overhead % this assumes that no ATM related overhead is >= ATM cell size % -1 to account for matlab 1 based indices % what is the offset in the 2nd ATM cell n_bytes_overhead_2nd_cell = quantum.byte - (quantum_list(min_cum_diff_col_idx) - 1); % just assume we can not fit all overhead into one cell... % what is the known overhead size for the first data point: tmp_idx = find(~isnan(per_size.data(:, per_size.cols.mean))); known_overhead_first_ping_size = tmp_idx(1); %pre_IP_overhead = quantum.byte + (n_bytes_overhead_2nd_cell - known_overhead); % ths is the one we are after in the end pre_IP_overhead = quantum.byte + (n_bytes_overhead_2nd_cell - known_overhead_first_ping_size); % ths is the one we are after in the end disp(' '); disp(['Estimated overhead preceeding the IP header: ', num2str(pre_IP_overhead), ' bytes']); figure('Name', 'Comparing ping data with'); hold on legend_str = {'ping_data', 'fitted_stair', 'fitted_line'}; plot(per_size.data(1:last_non_fragmented_pingsize, per_size.cols.size), per_size.data(1:last_non_fragmented_pingsize, per_size.cols.(use_measure)), 'Color', [1 0 0]); plot(per_size.data(1:last_non_fragmented_pingsize, per_size.cols.size), squeeze(all_stairs(min_cum_diff_row_idx, min_cum_diff_col_idx, :)) + best_difference, 'Color', [0 1 0]); fitted_line = polyval(p, per_size.data(1:last_non_fragmented_pingsize, per_size.cols.size), S); plot(per_size.data(1:last_non_fragmented_pingsize, per_size.cols.size), fitted_line, 'Color', [0 0 1]); title({['Estimated RTT per quantum: ', num2str(RTT_quantum_list(min_cum_diff_col_idx)), ' ms; ICMP data offset in quantum ', num2str(quantum_list(min_cum_diff_col_idx)), ' bytes'];... ['Estimated overhead preceeding the IP header: ', num2str(pre_IP_overhead), ' bytes'];... quant_string}); xlabel('Approximate packet size [bytes]'); ylabel('ICMP round trip times (ping RTT) [ms]'); if (isoctave) legend(legend_str, 'Location', 'NorthWest'); else %annotation('textbox', [0.0 0.95 1.0 .05], 'String', ['Estimated overhead preceeding the IP header: ', num2str(pre_IP_overhead), ' bytes'], 'FontSize', 9, 'Interpreter', 'none', 'Color', [1 0 0], 'LineStyle', 'none'); legend(legend_str, 'Interpreter', 'none', 'Location', 'NorthWest'); end hold off % use http://ace-host.stuart.id.au/russell/files/tc/tc-atm/ to present the % most likely ATM encapsulation for a given overhead and present a recommendation % for the tc stab invocation display_protocol_stack_information(pre_IP_overhead); % now turn this into tc-stab recommendations: disp(['Add the following to both the egress root qdisc:']); % disp(' '); disp(['A) Assuming the router connects over ethernet to the DSL-modem:']); disp(['stab mtu 2048 tsize 128 overhead ', num2str(pre_IP_overhead), ' linklayer atm']); % currently tc stab does not account for the ethernet header % disp(['stab mtu 2048 tsize 128 overhead ', num2str(pre_IP_overhead - offsets.ethernet), ' linklayer atm']); % disp(' '); % disp(['B) Assuming the router connects via PPP and non-ethernet to the modem:']); % disp(['stab mtu 2048 tsize 128 overhead ', num2str(pre_IP_overhead), ' linklayer atm']); disp(' '); % on ingress do not exclude the the ethernet header? disp(['Add the following to both the ingress root qdisc:']); disp(' '); disp(['A) Assuming the router connects over ethernet to the DSL-modem:']); disp(['stab mtu 2048 tsize 128 overhead ', num2str(pre_IP_overhead), ' linklayer atm']); disp(' '); if ~(isoctave) timestamps.(mfilename).end = toc(timestamps.(mfilename).start); disp([mfilename, ' took: ', num2str(timestamps.(mfilename).end), ' seconds.']); else toc end % and now the other end of the data, what is the max MTU for the link and % what is the best ATM cell aligned MTU disp('Done...'); return end function [ ping_data ] = parse_ping_output( ping_log_fqn ) %PARSE_PING_OUTPUT read the putput of a ping run/sweep % for further processing % TODO: % use a faster parser, using srtok is quite expensive % if ~(isoctave) timestamps.parse_ping_output.start = tic; else tic(); end verbose = 0; n_rows_to_grow_table_by = 10000; % grow table increment to avoid excessive memory copy ops ping_data = []; cur_sweep_fd = fopen(ping_log_fqn, 'r'); if (cur_sweep_fd == -1) disp(['Could not open ', ping_log_fqn, '.']); if isempty(dir(ping_log_fqn)) disp('Reason: file does not seem to exist at the given directory...') end return end ping_data.header = {'size', 'icmp_seq', 'ttl', 'time'}; ping_data.cols = get_column_name_indices(ping_data.header); ping_data.data = zeros([n_rows_to_grow_table_by, length(ping_data.header)]); cur_data_lines = 0; cur_lines = 0; % skip the first line % PING netblock-75-79-143-1.dslextreme.com (75.79.143.1): (16 ... 1000) % data bytes header_line = fgetl(cur_sweep_fd); while ~feof(cur_sweep_fd) % grow the data table if need be if (size(ping_data.data, 1) == cur_data_lines) if (verbose) disp('Growing ping data table...'); end ping_data.data = [ping_data.data; zeros([n_rows_to_grow_table_by, length(ping_data.header)])]; end cur_line = fgetl(cur_sweep_fd); if ~(mod(cur_lines, 1000)) disp([num2str(cur_lines +1), ' lines parsed...']); end cur_lines = cur_lines + 1; [first_element, remainder] = strtok(cur_line); first_element_as_number = str2double(first_element); if isempty(first_element) || strcmp('Request', first_element) || strcmp('---', first_element) % skip empty lines explicitly continue; end % the following will not work for merged ping %if strmatch('---', first_element) % %we reached the end of sweeps % break; %end % now read in the data % 30 bytes from 75.79.143.1: icmp_seq=339 ttl=63 time=14.771 ms if ~isempty(first_element_as_number) % get the next element [tmp_next_item, tmp_remainder] = strtok(remainder); if strcmp(tmp_next_item, 'bytes') if ~(mod(cur_data_lines, 1000)) disp(['Milestone ', num2str(cur_data_lines +1), ' ping packets reached...']); end cur_data_lines = cur_data_lines + 1; % size of the ICMP package ping_data.data(cur_data_lines, ping_data.cols.size) = first_element_as_number; % now process the remainder while ~isempty(remainder) [next_item, remainder] = strtok(remainder); equality_pos = strfind(next_item, '='); % data items are name+value pairs if ~isempty(equality_pos); cur_key = next_item(1: equality_pos - 1); cur_value = str2double(next_item(equality_pos + 1: end)); switch cur_key % busybox ping and macosx ping return different key names case {'seq', 'icmp_seq'} ping_data.data(cur_data_lines, ping_data.cols.icmp_seq) = cur_value; case 'ttl' ping_data.data(cur_data_lines, ping_data.cols.ttl) = cur_value; case 'time' ping_data.data(cur_data_lines, ping_data.cols.time) = cur_value; end end end else % skip this line if (verbose) disp(['Skipping: ', cur_line]); end end else if (verbose) disp(['Ping output: ', cur_line, ' not handled yet...']); end end end % remove empty lines if (size(ping_data.data, 1) > cur_data_lines) ping_data.data = ping_data.data(1:cur_data_lines, :); end disp(['Found ', num2str(cur_data_lines), ' ping packets in ', ping_log_fqn]); % clean up fclose(cur_sweep_fd); if ~(isoctave) timestamps.parse_ping_output.end = toc(timestamps.parse_ping_output.start); disp(['Parsing took: ', num2str(timestamps.parse_ping_output.end), ' seconds.']); else toc end return end function [ difference , cumulative_difference, stair_y ] = get_difference_between_data_and_stair( data_x, data_y, x_size, stair_x_step_size, y_offset, stair_y_step_size ) % 130619sm: handle NaNs in data_y (marker for missing ping sizes) % x_size is the flat part of the first stair, that is quantum minus the % offset % TODO: understand the offset issue and simplify this function % extrapolate the stair towards x = 0 again debug = 0; difference = []; tmp_idx = find(~isnan(data_y)); x_start_val_idx = tmp_idx(1); x_start_val = data_x(x_start_val_idx); x_end_val = data_x(end); % data_x is sorted... % construct stair stair_x = data_x; proto_stair_y = zeros([x_end_val 1]); % we need the final value in % make sure the x_size values do not exceed the step size... if (x_size > stair_x_step_size) if mod(x_size, stair_x_step_size) == 0 x_size = stair_x_step_size; else x_size = mod(x_size, stair_x_step_size); end end %stair_y_step_idx = (x_start_val + x_size : stair_x_step_size : x_end_val); %% we really want steps registered to x_start_val %stair_y_step_idx = (mod(x_start_val, stair_x_step_size) + x_size : stair_x_step_size : x_end_val); stair_y_step_idx = (mod(x_start_val + x_size, stair_x_step_size) : stair_x_step_size : x_end_val); if stair_y_step_idx(1) == 0 stair_y_step_idx(1) = []; end proto_stair_y(stair_y_step_idx) = stair_y_step_size; stair_y = cumsum(proto_stair_y); if (debug) figure hold on; title(['x offset used: ', num2str(x_size), ' with quantum ', num2str(stair_x_step_size)]); plot(data_x, data_y, 'Color', [0 1 0]); plot(stair_x, stair_y, 'Color', [1 0 0]); hold off; end % missing ping sizes are filled with NaNs, so skip those notnan_idx = find(~isnan(data_y)); % estimate the best y_offset for the stair difference = sum(abs(data_y(notnan_idx) - stair_y(notnan_idx))) / length(data_y(notnan_idx)); % calculate the cumulative difference between stair and data... cumulative_difference = sum(abs(data_y(notnan_idx) - (stair_y(notnan_idx) + difference))); return end % function [ stair ] = build_stair(x_vector, x_size, stair_x_step_size, y_offset, stair_y_step_size ) % stair = []; % % return % end function [columnnames_struct, n_fields] = get_column_name_indices(name_list) % return a structure with each field for each member if the name_list cell % array, giving the position in the name_list, then the columnnames_struct % can serve as to address the columns, so the functions assitgning values % to the columns do not have to care too much about the positions, and it % becomes easy to add fields. n_fields = length(name_list); for i_col = 1 : length(name_list) cur_name = name_list{i_col}; columnnames_struct.(cur_name) = i_col; end return end function [ci_halfwidth_vector] = calc_cihw(std_vector, n, alpha) %calc_ci : calculate the half width of the confidence interval (for 1 - alpha) % the t_value lookup depends on alpha and the samplesize n; the relevant % calculation of the degree of freedom is performed inside calc_t_val. % ci_halfwidth = t_val(alpha, n-1) * std / sqrt(n) % Each groups CI ranges from mean - ci_halfwidth to mean - ci_halfwidth, so % the calling function has to perform this calculation... % % INPUTS: % std_vector: vector containing the standard deviations of all requested % groups % n: number of samples in each group, if the groups have different % samplesizes, specify each groups samplesize in a vector % alpha: the desired maximal uncertainty/error in the range of [0, 1] % OUTPUT: % ci_halfwidth_vector: vector containing the confidence intervals half width % for each group % calc_t_val return one sided t-values, for the desired two sidedness one has % to half the alpha for the table lookup cur_alpha = alpha / 2; % if n is scalar use same n for all elements of std_vec if isscalar(n) t_ci = calc_t_val(cur_alpha, n); ci_halfwidth_vector = std_vector * t_ci / sqrt(n); % if n is a vector, prepare a matching vector of t_ci values elseif isvector(n) t_ci_vector = n; % this is probably ugly, but calc_t_val only accepts scalars. for i_pos = 1 : length(n) t_ci_vector(i_pos) = calc_t_val(cur_alpha, n(i_pos)); end ci_halfwidth_vector = std_vector .* t_ci_vector ./ sqrt(n); end return end %----------------------------------------------------------------------------- function [t_val] = calc_t_val(alpha, n) % the t value for the given alpha and n % so call with the n of the sample, not with degres of freedom % see http://mathworld.wolfram.com/Studentst-Distribution.html for formulas % return values follow Bortz, Statistik fuer Sozialwissenschaftler, Springer % 1999, table D page 775. That is it returns one sided t-values. % primary author S. Moeller % TODO: % sidedness of t-value??? % basic error checking if nargin < 2 error('alpha and n have to be specified...'); end % probabilty of error tmp_alpha = alpha ;%/ 2; if (tmp_alpha < 0) || (tmp_alpha > 1) msgbox('alpha has to be taken from [0, 1]...'); t_val = NaN; return end if tmp_alpha == 0 t_val = -Inf; return elseif tmp_alpha ==1 t_val = Inf; return end % degree of freedom df = n - 1; if df < 1 %msgbox('The n has to be >= 2 (=> df >= 1)...'); % disp('The n has to be >= 2 (=> df >= 1)...'); t_val = NaN; return end % only calculate each (alpha, df) combination once, store the results persistent t_val_array; % create the t_val_array if ~iscell(t_val_array) t_val_array = {[NaN;NaN]}; end % search for the (alpha, df) tupel, avoid calculation if already stored if iscell(t_val_array) % cell array of 2d arrays containing alpha / t_val pairs if df <= length(t_val_array) % test whether the required alpha, t_val tupel exists if ~isempty(t_val_array{df}) % search for alpha tmp_array = t_val_array{df}; alpha_index = find(tmp_array(1,:) == tmp_alpha); if any(alpha_index) t_val = tmp_array(2, alpha_index); return end end else % grow t_val_array to length of n missing_cols = df - length(t_val_array); for i_missing_cols = 1: missing_cols t_val_array{end + 1} = [NaN;NaN]; end end end % check the sign cdf_sign = 1; if (1 - tmp_alpha) == 0.5 t_val = t_cdf; elseif (1 - tmp_alpha) < 0.5 % the t-cdf is point symmetric around (0, 0.5) cdf_sign = -1; tmp_alpha = 1 - tmp_alpha; % this will be undone later end % init some variables n_iterations = 0; delta_t = 1; last_alpha = 1; higher_t = 50; lower_t = 0; % find a t-value pair around the desired alpha value while norm_students_cdf(higher_t, df) < (1 - tmp_alpha); lower_t = higher_t; higher_t = higher_t * 2; end % search the t value for the given alpha... while (n_iterations < 1000) && (abs(delta_t) >= 0.0001) n_iterations = n_iterations + 1; % get the test_t (TODO linear interpolation) % higher_alpha = norm_students_cdf(higher_t, df); % lower_alpha = norm_students_cdf(lower_t, df); test_t = lower_t + ((higher_t - lower_t) / 2); cur_alpha = norm_students_cdf(test_t, df); % just in case we hit the right t spot on... if cur_alpha == (1 - tmp_alpha) t_crit = test_t; break; % probably we have to search for the right t elseif cur_alpha < (1 - tmp_alpha) % test_t is the new lower_t lower_t = test_t; %higher_t = higher_t; % this stays as is... elseif cur_alpha > (1 - tmp_alpha) % %lower_t = lower_t; % this stays as is... higher_t = test_t; end delta_t = higher_t - lower_t; last_alpha = cur_alpha; end t_crit = test_t; % set the return value, correct for negative t values t_val = t_crit * cdf_sign; if cdf_sign < 0 tmp_alpha = 1 - tmp_alpha; end % store the alpha, n, t_val tupel in t_val_array pos = size(t_val_array{df}, 2); t_val_array{df}(1, (pos + 1)) = tmp_alpha; t_val_array{df}(2, (pos + 1)) = t_val; return end %----------------------------------------------------------------------------- function [scaled_cdf] = norm_students_cdf(t, df) % calculate the cdf of students distribution for a given degree of freedom df, % and all given values of t, then normalize the result % the extreme values depend on the values of df!!! % get min and max by calculating values for extrem t-values (e.g. -10000000, % 10000000) extreme_cdf_vals = students_cdf([-10000000, 10000000], df); tmp_cdf = students_cdf(t, df); scaled_cdf = (tmp_cdf - extreme_cdf_vals(1)) /... (extreme_cdf_vals(2) - extreme_cdf_vals(1)); return end %----------------------------------------------------------------------------- function [cdf_value_array] = students_cdf(t_value_array, df) %students_cdf: calc the cumulative density function for a t-distribution % Calculate the CDF value for each value t of the input array % see http://mathworld.wolfram.com/Studentst-Distribution.html for formulas % INPUTS: t_value_array: array containing the t values for which to % calculate the cdf % df: degree of freedom; equals n - 1 for the t-distribution cdf_value_array = 0.5 +... ((betainc(1, 0.5 * df, 0.5) / beta(0.5 * df, 0.5)) - ... (betainc((df ./ (df + t_value_array.^2)), 0.5 * df, 0.5) /... beta(0.5 * df, 0.5))) .*... sign(t_value_array); return end %----------------------------------------------------------------------------- function [t_prob_dist] = students_pf(df, t_arr) % calculate the probability function for students t-distribution t_prob_dist = (df ./ (df + t_arr.^2)).^((1 + df) / 2) /... (sqrt(df) * beta(0.5 * df, 0.5)); % % calculate and scale the cdf by hand... % cdf = cumsum(t_prob_dist); % discrete_t_cdf = (cdf - min(cdf)) / (max(cdf) - min(cdf)); % % numericaly get the t-value for the given alpha % tmp_index = find(discrete_t_cdf > (1 - tmp_alpha)); % t_crit = t(tmp_index(1)); return end function in = isoctave () persistent inout; if isempty(inout), inout = exist('OCTAVE_VERSION','builtin') ~= 0; end; in = inout; return; end function [] = display_protocol_stack_information(pre_IP_overhead) % use [1] http://ace-host.stuart.id.au/russell/files/tc/tc-atm/ to present the % most likely ATM protocol stack setup for a given overhead so the user can % compare with his prior knowledge % how much data fits into ATM cells without padding? 32 cells would be 1519 % which is larger than the 1500 max MTU for ethernet ATM_31_cells_proto_MTU = 31 * 48; % according to [1] 31 cells are the optimum for all protocol stacks ATM_32_cells_proto_MTU = 32 * 48; % should be best for case 44 disp(' '); disp('According to http://ace-host.stuart.id.au/russell/files/tc/tc-atm/'); disp(['', num2str(pre_IP_overhead), ' bytes overhead indicate']); switch pre_IP_overhead case 8 disp('Connection: IPoA, VC/Mux RFC-2684'); disp('Protocol (bytes): ATM AAL5 SAR (8) : Total 8'); overhead_bytes_around_MTU = 8; overhead_bytes_in_MTU = 0; case 16 disp('Connection: IPoA, LLC/SNAP RFC-2684'); disp('Protocol (bytes): ATM LLC (3), ATM SNAP (5), ATM AAL5 SAR (8) : Total 16'); overhead_bytes_around_MTU = 16; overhead_bytes_in_MTU = 0; case 24 disp('Connection: Bridged, VC/Mux RFC-1483/2684'); disp('Protocol (bytes): Ethernet Header (14), ATM pad (2), ATM AAL5 SAR (8) : Total 24'); overhead_bytes_around_MTU = 24; overhead_bytes_in_MTU = 0; case 28 disp('Connection: Bridged, VC/Mux+FCS RFC-1483/2684'); disp('Protocol (bytes): Ethernet Header (14), Ethernet PAD [8] (0), Ethernet Checksum (4), ATM pad (2), ATM AAL5 SAR (8) : Total 28'); overhead_bytes_around_MTU = 28; overhead_bytes_in_MTU = 0; case 32 disp('Connection: Bridged, LLC/SNAP RFC-1483/2684'); disp('Protocol (bytes): Ethernet Header (14), ATM LLC (3), ATM SNAP (5), ATM pad (2), ATM AAL5 SAR (8) : Total 32'); overhead_bytes_around_MTU = 32; overhead_bytes_in_MTU = 0; disp('OR'); disp('Connection: PPPoE, VC/Mux RFC-2684'); disp('Protocol (bytes): PPP (2), PPPoE (6), Ethernet Header (14), ATM pad (2), ATM AAL5 SAR (8) : Total 32'); overhead_bytes_around_MTU = 24; overhead_bytes_in_MTU = 8; case 36 disp('Connection: Bridged, LLC/SNAP+FCS RFC-1483/2684'); disp('Protocol (bytes): Ethernet Header (14), Ethernet PAD [8] (0), Ethernet Checksum (4), ATM LLC (3), ATM SNAP (5), ATM pad (2), ATM AAL5 SAR (8) : Total 36'); overhead_bytes_around_MTU = 36; overhead_bytes_in_MTU = 0; disp('OR'); disp('Connection: PPPoE, VC/Mux+FCS RFC-2684'); disp('Protocol (bytes): PPP (2), PPPoE (6), Ethernet Header (14), Ethernet PAD [8] (0), Ethernet Checksum (4), ATM pad (2), ATM AAL5 SAR (8) : Total 36'); overhead_bytes_around_MTU = 28; overhead_bytes_in_MTU = 8; case 10 disp('Connection: PPPoA, VC/Mux RFC-2364'); disp('Protocol (bytes): PPP (2), ATM AAL5 SAR (8) : Total 10'); overhead_bytes_around_MTU = 8; overhead_bytes_in_MTU = 2; case 14 disp('Connection: PPPoA, LLC RFC-2364'); disp('Protocol (bytes): PPP (2), ATM LLC (3), ATM LLC-NLPID (1), ATM AAL5 SAR (8) : Total 14'); overhead_bytes_around_MTU = 12; overhead_bytes_in_MTU = 2; case 40 disp('Connection: PPPoE, LLC/SNAP RFC-2684'); disp('Protocol (bytes): PPP (2), PPPoE (6), Ethernet Header (14), ATM LLC (3), ATM SNAP (5), ATM pad (2), ATM AAL5 SAR (8) : Total 40'); overhead_bytes_around_MTU = 32; overhead_bytes_in_MTU = 8; case 44 disp('Connection: PPPoE, LLC/SNAP+FCS RFC-2684'); disp('Protocol (bytes): PPP (2), PPPoE (6), Ethernet Header (14), Ethernet PAD [8] (0), Ethernet Checksum (4), ATM LLC (3), ATM SNAP (5), ATM pad (2), ATM AAL5 SAR (8) : Total 44'); overhead_bytes_around_MTU = 36; overhead_bytes_in_MTU = 8; otherwise disp('a protocol stack this program does NOT know (yet)...'); end disp(' '); return; end --Apple-Mail=_ECBD3467-0744-4FDD-B95E-51D2AAEBC818 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=windows-1252 . Invoce with = "tc_stab_parameter_guide_03('path/to/the/data/file/you/created/name_of_sai= d_file')". The parser will run on the first invocation and is reallr = really slow, but further invocations should be faster. If issues arise, = let me know, I am happy to help. >=20 > Were I to use a single directly connected gateway, I would input a = suitable value for PPPoA in that openWRT firmware. I think you should do that right now. > In theory, I might need to use a negative value, bmt the current = kernel does not support that. If you use tc_stab, negative overheads are fully supported, only = htb_private has overhead defined as unsigned integer and hence does not = allow negative values. > I have used many different arbitrary values for overhead. All appear = to have little effect. So the issue here is that only at small packet sizes does the = overhead and last cell padding eat a disproportionate amount of your = bandwidth (64 byte packet plus 44 byte overhead plus 47 byte worst case = cell padding: 100* (44+47+64)/64 =3D 242% effective packet size to what = the shaper estimated ), at typical packet sizes the max error (44 bytes = missing overhead and potentially misjudged cell padding of 47 bytes adds = up to a theoretical 100*(44+47+1500)/1500 =3D 106% effective packet = size to what the shaper estimated). It is obvious that at 1500 byte = packets the whole ATM issue can be easily dismissed with just reducing = the link rate by ~10% for the 48 in 53 framing and an additional ~6% for = overhead and cell padding. But once you mix smaller packets in your = traffic for say VoIP, the effective wire size misjudgment will kill your = ability to control the queueing. Note that the common wisdom of shape = down to 85% might be fem the ~15% ATM "tax" on 1500 byte traffic size... > As I understand it, the current recommendation is to use tc_stab in = preference to htb_private. I do not know the basis for this value = judgement. In short: tc_stab allows negative overheads, tc_stab works with = HTB, TBF, HFSC while htb_private only works with HTB. Currently = htb_private has two advantages: it will estimate the per packet overhead = correctly of GSO (generic segmentation offload) is enabled and it will = produce exact ATM link layer estimates for all possible packet sizes. In = practice almost everyone uses an MTU of 1500 or less for their internet = access making both htb_private advantages effectively moot. (Plus if no = one beats me to it I intend to address both theoretical short coming of = tc_stab next year). Best Regards Sebastian >=20 >=20 >=20 >=20 >=20 > On 28/12/13 10:01, Sebastian Moeller wrote: >> Hi Rich, >>=20 >> great! A few comments: >>=20 >> Basic Settings: >> [Is 95% the right fudge factor?] I think that ideally, if we get can = precisely measure the useable link rate even 99% of that should work out = well, to keep the queue in our device. I assume that due to the = difficulties in measuring and accounting for the link properties as link = layer and overhead people typically rely on setting the shaped rate a = bit lower than required to stochastically/empirically account for the = link properties. I predict that if we get a correct description of the = link properties to the shaper we should be fine with 95% shaping. Note = though, it is not trivial on an adel link to get the actually useable = bit rate from the modem so 95% of what can be deduced from the modem or = the ISP's invoice might be a decent proxy=85 >>=20 >> [Do we have a recommendation for an easy way to tell if it's working? = Perhaps a link to a new Quick Test for Bufferbloat page. ] The linked = page looks like a decent probe for buffer bloat. >>=20 >>=20 >>> Basic Settings - the details... >>>=20 >>> CeroWrt is designed to manage the queues of packets waiting to be = sent across the slowest (bottleneck) link, which is usually your = connection to the Internet. >>>=20 >> I think we can only actually control the first link to the ISP, = which often happens to be the bottleneck. At a typical DSLAM (xDSL head = end station) the cumulative sold bandwidth to the customers is larger = than the back bone connection (which is called over-subscription and is = almost guaranteed to be the case in every DSLAM) which typically is not = a problem, as typically people do not use their internet that much. My = point being we can not really control congestion in the DSLAM's uplink = (as we have no idea what the reserved rate per customer is in the worst = case, if there is any). >>=20 >>=20 >>> CeroWrt can automatically adapt to network conditions to improve the = delay/latency of data without any settings. >>>=20 >> Does this describe the default fq_codels on each interface = (except fib?)? >>=20 >>=20 >>> However, it can do a better job if it knows more about the actual = link speeds available. You can adjust this setting by entering link = speeds that are a few percent below the actual speeds.=20 >>>=20 >>> Note: it can be difficult to get an accurate measurement of the link = speeds. The speed advertised by your provider is a starting point, but = your experience often won't meet their published specs. You can also use = a speed test program or web site like=20 >>> http://speedtest.net >>> to estimate actual operating speeds. >>>=20 >> While this approach is commonly recommended on the internet, I = do not believe that it is that useful. Between a user and the speediest = site there are a number of potential congestion points that can affect = (reduce) the throughput, like bad peering. Now that said the sppedtets = will report something <=3D the actual link speed and hence be = conservative (interactivity stays great at 90% of link rate as well as = 80% so underestimating the bandwidth within reason does not affect the = latency gains from traffic shaping it just sacrifices a bit more = bandwidth; and given the difficulty to actually measure the actually = attainable bandwidth might have been effectively a decent recommendation = even though the theory of it seems flawed) >>=20 >>=20 >>> Be sure to make your measurement when network is quiet, and others = in your home aren=92t generating traffic. >>>=20 >> This is great advise. >>=20 >> I would love to comment further, but after reloading=20 >> = http://www.bufferbloat.net/projects/cerowrt/wiki/Setting_up_AQM_for_CeroWr= t_310 >> just returns a blank page and I can not get back to the page as of = yesterday evening=85 I will have a look later to see whether the page = resurfaces=85 >>=20 >> Best >> Sebastian >>=20 >>=20 >> On Dec 27, 2013, at 23:09 , Rich Brown=20 >> >> wrote: >>=20 >>=20 >>>> You are a very good writer and I am on a tablet. >>>>=20 >>>>=20 >>> Thanks! >>>=20 >>>> Ill take a pass at the wiki tomorrow. >>>>=20 >>>> The shaper does up and down was my first thought... >>>>=20 >>>>=20 >>> Everyone else=85 Don=92t let Dave hog all the fun! Read the tech = note and give feedback! >>>=20 >>> Rich >>>=20 >>>=20 >>>> On Dec 27, 2013 10:48 AM, "Rich Brown" >>>> wrote: >>>> I updated the page to reflect the 3.10.24-8 build, and its new GUI = pages. >>>>=20 >>>>=20 >>>> = http://www.bufferbloat.net/projects/cerowrt/wiki/Setting_up_AQM_for_CeroWr= t_310 >>>>=20 >>>>=20 >>>> There are still lots of open questions. Comments, please. >>>>=20 >>>> Rich >>>> _______________________________________________ >>>> Cerowrt-devel mailing list >>>>=20 >>>> Cerowrt-devel@lists.bufferbloat.net >>>> https://lists.bufferbloat.net/listinfo/cerowrt-devel >>> _______________________________________________ >>> Cerowrt-devel mailing list >>>=20 >>> Cerowrt-devel@lists.bufferbloat.net >>> https://lists.bufferbloat.net/listinfo/cerowrt-devel >> _______________________________________________ >> Cerowrt-devel mailing list >>=20 >> Cerowrt-devel@lists.bufferbloat.net >> https://lists.bufferbloat.net/listinfo/cerowrt-devel >=20 --Apple-Mail=_ECBD3467-0744-4FDD-B95E-51D2AAEBC818--