From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mout.gmx.net (mout.gmx.net [212.227.17.20]) (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 55D3621F1E5 for ; Tue, 7 Jan 2014 05:02:29 -0800 (PST) Received: from u-081-c096.eap.uni-tuebingen.de ([134.2.81.96]) by mail.gmx.com (mrgmx002) with ESMTPSA (Nemesis) id 0Mg4FJ-1Vo45312kn-00NSTB for ; Tue, 07 Jan 2014 14:02:20 +0100 Content-Type: multipart/mixed; boundary="Apple-Mail=_F37E704F-8506-4422-BEF8-FA0D4BBA44EB" Mime-Version: 1.0 (Mac OS X Mail 6.6 \(1510\)) From: Sebastian Moeller In-Reply-To: Date: Tue, 7 Jan 2014 14:02:22 +0100 Message-Id: <0605567F-B62E-4ABD-9F0A-156BB63328F6@gmx.de> References: <01558084-B7D8-448A-A4ED-CE36D18AAA97@gmail.com> <52C855B1.1040209@imap.cc> <52CA7CC3.2030203@imap.cc> <52CABC11.6040000@imap.cc> To: David Personette X-Mailer: Apple Mail (2.1510) X-Provags-ID: V03:K0:TXqTjGtdXFvb85gPj3OV1rfDuAbq6eLuHl7EsQGae7Xkw+0B4Yq ec4uJweGrkPKyFZY0/lngQ5f2cQcLdWDtBJf7qUdTc9EFK6TyLnrojpL+JSn68y4TIU85J1 kpYV6VIU8PXufOKKTCHnIwGlWvWkfHeajUpDVD7ezm4T/BUpDsPDIrdeCTZcEOUb+zqQ7Qb v7vlAHsAZ9K5Cn/XtXwHg== Cc: "cerowrt-devel@lists.bufferbloat.net" Subject: Re: [Cerowrt-devel] SQM Question #5: Link Layer Adaptation Overheads 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: Tue, 07 Jan 2014 13:02:36 -0000 X-List-Received-Date: Tue, 07 Jan 2014 13:02:36 -0000 --Apple-Mail=_F37E704F-8506-4422-BEF8-FA0D4BBA44EB Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=windows-1252 Hi David, On Jan 7, 2014, at 13:11 , David Personette wrote: > I was going to test the recommended bridge settings for overhead (32 = IIRC), because as far as I can tell there is no PPPoE involved. I've = never seen it in the modems config (in the brief period it has an IP = before I put it in bridge mode as well so the routable IP goes to my = actual router), or needed to configure it on my router. Ah, so there are 2 major variations of "bridged": 1) LLC/SNAP: Bridged - 32 (ATM - 18, ethernet 14, possibly = FCS - 4+padding) 2) VC-MUX: Bridged - 24 (ATM - 10, ethernet 14, possibly FCS - = 4+padding) (he FCS padding potentially turns this into 4 variations, but it should = be really rare, or so I heard). You could just slowly reduce the overhead and see how the link = behaves; honestly I do not know how prominent a slight overhead = underestimate would feel, so by all means go ahead and try :). If you = have a mac or linux computer on your network, you could try to measure = the overhead with the attached ping_sweeper5_dp.sh script (needs = editing). Then you could run tc_stab_parameter_guide_04.m in matlab or = octave (on the matlab command prompt change into the directory = containing the script and the log file run "[ tmp ] =3D = tc_stab_parameter_guide_04( fullfile(pwd, = 'ping_sweep_ADSL2_20140104_122844.txt'))" ; make sure to replace = ping_sweep_ADSL2_20140104_122844.txt with the name of your log file. The = measurement will take around 3 hours (for 10000 samples per size, for = your link 1000 would be enough) and wants an undisturbed network (I = typically run this over night); the parsing of the log file will also = consume 20 minutes or more, the actual analysis will take a few seconds=85= If you go that route I would love it if you could share your log = file, since I only have one old bridged LLC/SNAP example. (I intend to = put all scripts and an instruction on the wiki, with example plots for = the different results). Best Regards Sebastian --Apple-Mail=_F37E704F-8506-4422-BEF8-FA0D4BBA44EB Content-Disposition: attachment; filename=tc_stab_parameter_guide_04.m Content-Type: application/octet-stream; name="tc_stab_parameter_guide_04.m" Content-Transfer-Encoding: 7bit function [ output_args ] = tc_stab_parameter_guide_04( 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 % implement robust mean (mean between certain quantiles), does that make % sense with RTT distribution? % % 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 tunnelling?) % 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 = 1; % the means are noisier than the medians show_robust_mean = 1; % 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, IPv6 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', 'robust_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)); % robust mean, aka mean of 5 to 95 quantiles per_size.data(cur_size, per_size.cols.robust_mean) = robust_mean(ping.data(cur_size_idx, ping.cols.time), 0.1, 0.9); % take the mean while excluding extreme values 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 ]); legend_str{end + 1} = 'robust mean'; plot(per_size.data(:, per_size.cols.size), per_size.data(:, per_size.cols.robust_mean), 'Color', [0 0.75 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 packet % 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 preceding 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 preceding 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 preceding 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.field_names_list = {'size', 'icmp_seq', 'seq', 'ttl', 'time'}; ping_data.header = {'size', 'time'}; % save half the size... ping_data.field_names_list = {'size', '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)); if (ismember(cur_key, ping_data.field_names_list)) 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 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 group's sample size 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 function range_mean = robust_mean(value_list, lower_limit_ratio, upper_limit_ratio) n_vals = length(value_list); sorted_values = sort(value_list); lowest_robust_idx = ceil(n_vals * lower_limit_ratio); highest_robust_idx = floor(n_vals * upper_limit_ratio); range_mean = mean(sorted_values(lowest_robust_idx:highest_robust_idx)); return end --Apple-Mail=_F37E704F-8506-4422-BEF8-FA0D4BBA44EB Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=us-ascii --Apple-Mail=_F37E704F-8506-4422-BEF8-FA0D4BBA44EB Content-Disposition: attachment; filename=ping_sweeper5_dp.sh Content-Type: application/octet-stream; name="ping_sweeper5_dp.sh" Content-Transfer-Encoding: 7bit #! /bin/bash # TODO use seq or bash to generate a list of the requested sizes (to alow for non-equdistantly spaced sizes) # just an identifier for the ping log TECH=ADSL # 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 # for this I typically run "traceroute 8.8.8.8", and then select the first host on the ISP side (typically after # the first large RTT increment) and test its response by "ping -c 10 -s 16 NNN.NNN.NNN.NNN", if this host does not repsond # I pick the next host along the route to 8.8.8.8. I assume the closer the host the less disturbed by other traffic the # response will be. echo "Edit and set TARGET to a valid IPv4 host-address, end comment the exit" exit 0 TARGET=${1} # Replace by an appropriate host DATESTR=`date +%Y%m%d_%H%M%S` # to allow multiple sequential records LOG=ping_sweep_${TECH}_${DATESTR}.txt MAX_PREIP_OVERHEAD_SIZE=44 # as far as I can tell 44 bytes is the maximum pre IP header overhead for an ATM based carrier IP4_HEADER_SIZE=20 # 20 bytes IDEAL_MTU=1500 # what the MTU should look like # 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 host) # at 100 packets/s of 116 + 28 + 40 we would need 4 ATM cells = 192byte * 100/s = 150kbit/s # at 100 packets/s of 16 + 28 + 40nwe would need 2 ATM cells = 96byte * 100/s = 75kbit/s # on average we need 150 + 75 * 0.5 = 112.5 Kbit/s, increase the ping period if uplinh < 112.5 Kbit/s PINGPERIOD=0.01 # in seconds, at 100 packets of 116 + 28 + 40 = 3 ATM cells = 192byte * 100/s = 150kbit/s, PINGSPERSIZE=10000 # the higher the link rate the more samples we need to reliably detect the increasingly smaller ATM quantisation steps. # 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 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=_F37E704F-8506-4422-BEF8-FA0D4BBA44EB Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=windows-1252 >=20 > I am seeing my effective bandwidth be higher by about 50/KBs on = downloads. On Netflix, my Roku used to try HD upon starting playback = then (after 20-30 seconds thinking about it) fail back to SD, but now = the HD streams are working flawlessly for hours. >=20 > --=20 > David P. >=20 >=20 >=20 > On Tue, Jan 7, 2014 at 6:34 AM, Sebastian Moeller = wrote: > Hi David, >=20 >=20 > On Jan 7, 2014, at 12:08 , David Personette wrote: >=20 > > I'm in the US, but live in a relatively rural area. My only internet = options are DSL and satellite. The local provider is Century Link (it = used to be Sprint, but they sold their copper phone business off). I = have the fastest service that they offer (based on distance from the = DSLAM), 4 down / .5 up. >=20 > And you are not alone, a considerable percentage of the = population wherever you look is hanging on such connections. So cerowrt = should really help those folk as well as luckier ones. >=20 > > > > I have had SmokePing monitoring my latency to the first hop outside = my network for over a year now (I've been on CeroWRT the whole time). My = baseline (no load) latency is 31ms. I used to have AQM throttling back = to 80% of my already pathetic bandwidth. I would still regularly see = periods lasting minutes to hours when latency would be 80 - 120ms. > > > > I only recently grokked what you were talking about with tc_stab = since I got back from the holidays with the family, I set things up as = you suggested for Fred (nfq_codel, "target 25ms" in advanced egress, = ATM, per packet overhead 40, >=20 > The exact number depends on the encapsulation your ISP uses, = 40 is right for a typical PPPoE over LLC/SNAP connection, if that is = correct for your link you are fine, otherwise contact me if you want to = empirically find out the proper value for your link. >=20 > > and set my SQM bandwidth limits to 95%). Since the 30th my "worst = case" latency has been 41ms. >=20 > the fq_codels really are great if in control of the = bottleneck, really good work by bright people! >=20 > > Plus I get to use more of my actual bandwidth. >=20 > Well, that I am not so sure. By enabling link layer ATM the = router will automatically take care of the ATM cell overhead for you = (basically reducing the effective rate to ~90% of the link, in other = words you get the same effect by shaping to 90%). It will also handle = the per packet overhead and the nasty potential padding of the last ATM = cell (both have a stronger effect on small packets and are hard to = actually account for by static rate reduction; link layer ATM comes = again to the rescue by taking these two into account individually for = each packet based on the packet size). So effectively 95% with link = layer adjustments might mean a lower wire rate than 80% without; the = important thing is that with the link layer adjustments the link = capacity is estimated correctly avoiding the modem's and the DSLAM's = buffers to fill and cause buffer bloat. >=20 > > I REALLY wish that I'd made the time to read your emails about = setting up the ATM overhead earlier. >=20 > Oh, I can understand, when I learned about this some years ago = (by stumbling over Russel Stuart's website and Jesper Brouer's thesis) = it immediate changed my internet experience (I was on a 3 down / 0.5 up = connection at that time). :) >=20 > Best Regards > Sebastian >=20 > > > > Thank you. > > > > -- > > David P. > > > > > > > > On Mon, Jan 6, 2014 at 9:27 AM, Sebastian Moeller = wrote: > > Hi Fred, > > > > > > On Jan 6, 2014, at 15:22 , Fred Stratton = wrote: > > > > > The line rate is 11744/1022 kb/s, but changes moment to moment. = SNR is 12.1 decibel. I am using 11000/950 kb/s as settings. > > > > So 100 * 11000 / 11744 =3D 93.66% of downlink line rate and = 100* 950 / 1022 =3D 92.95 % of uplink line rate; quite impressive given = the common wisdom of 85% :). > > > > > > > I shall try your suggestion when there is something worth = watching live, to provide a valid comparison, which may not be before = 21:30 CET on Sunday. > > > > Oh, take your time, this is really not essential, butit = would be a nice data point for figuring out how important the correct = overhead estimate really is in real life, theory being theory and all=85 > > > > Best Regards > > Sebastian > > > > > > > > On 06/01/14 14:12, Sebastian Moeller wrote: > > >> Hi Fred, > > >> > > >> > > >> On Jan 6, 2014, at 10:52 , Fred Stratton = wrote: > > >> > > >>> I have been operating the latest build with 6relayd disabled. = The henet /48 I have been allocated is subnetted correctly, presumably = by dnsmasq. > > >>> > > >>> I adopted the suggestions to use nfq_codel and an egress target = of 25ms , with an overhead of 40 on a PPPoE connection. I chose to = watch the first 2 episodes of the 3 part third series of 'Sherlock', = live on iPlayer, and these streamed correctly and uninterrupted for 90 = minutes. This was not previously possible. (Quite whether they were up = to the standard of previous episodes is another matter.) > > >>> > > >>> I can watch iPlayer with little stutter whilst downloading Arch = Linux by torrent, downloading other files at the same time. > > >>> > > >>> So, for a relatively slow ADSL2+ line, the current build works = well. > > >> Out of curiosity, to what percentage of the "current line = rate" (you know the one reported by your modem) you shaped up- and = downlink? And in case you have too much time on your hand, how does the = same feel with an overhead of 10 (to see how bad an overhead = underestimate would feel for a user), since you currently happen to have = a quite sensitive subjective latency evaluation system set up :)=85 > > >> > > >> Best Regards > > >> Sebastian > > >> > > >>> > > >>> On 06/01/14 03:29, Dave Taht wrote: > > >>>> On Sat, Jan 4, 2014 at 10:40 AM, Fred Stratton = wrote: > > >>>>> Link Names: > > >>>>> > > >>>>> For consistency, if ADSL is used as a portmanteau term, them = VDSL should be > > >>>>> used as the equivalent for VDSL and VDSL2. > > >>>>> > > >>>>> CeroWRT has to decide whether it is an experimental build, or = something that > > >>>>> will eventually be used in production, so these decisions can = be made > > >>>>> consistently. > > >>>> Well, what I was aiming for was for us to get the sqm scripts = and gui > > >>>> up to where they were better than the standard openwrt qos = scripts and > > >>>> then push them up to openwrt to where they could be more widely > > >>>> deployed. > > >>>> > > >>>> Aside from being able to dynamically assign priorities in the = gui, we > > >>>> are there. Except that nfq_codel is currently getting better = results > > >>>> than fq_codel at low bandwidths, and I'm tempted to pour all of > > >>>> simple.qos into C. > > >>>> > > >>>> As for cero's future - certainly since all the snowden = revelations > > >>>> I've been going around saying that "friends don't let friends = run > > >>>> factory firmware". I would like a stable build of sqm and = cerowrt to > > >>>> emerge, and to then go off and work on improving wifi. = Regrettably > > >>>> what seems to be happening is more backwards than forwards on = the > > >>>> former, and ramping up on the ath9k and ath10k is taking more = time > > >>>> than I'd like, and it seems likely I'll be working on those = primarily > > >>>> on another platform and only eventually pushing the results out = to > > >>>> cero, mainline kernel > > >>>> > > >>>> So it's still at the "keep plugging away" point for sqm, ipv6, = cero in > > >>>> general, with the stable release always just out of sight. > > >>>> > > >>>> Tackling the ipv6 problem is next on my agenda on cero, and = getting a > > >>>> test suite going is next on my day job. > > >>>> > > >>>>> I concur with your ADSL setup suggestion as default. I have = been running the > > >>>>> Sebastian Moeller ping script overnight to calculate ADSL = overhead for the > > >>>>> last several days. After several hours of curve fitting using = Octave, an > > >>>>> overhead result is displayed. This novel approach works well. > > >>>> It would be nice to get to where we could autoconfigure a = router using > > >>>> tools like these with no human intervention. This includes = bandwidth > > >>>> estimation. > > >>>> > > >>>>> The overhead for the particular setup I use was 40 for PPPoE, = and 10 for > > >>>>> PPPoA. > > >>>>> > > >>>>> The default you suggest is a suitable starting point, I = suggest. > > >>>>> > > >>>>> > > >>>>> On 04/01/14 18:16, Rich Brown wrote: > > >>>>>> QUESTION #5: I still don=92t have any great answers for the = Link Layer > > >>>>>> Adaptation overhead descriptions and recommendations. In an = earlier message, > > >>>>>> (see > > >>>>>> = https://lists.bufferbloat.net/pipermail/cerowrt-devel/2013-December/001914= .html > > >>>>>> and following messages), Fred Stratton described the = overheads carried by > > >>>>>> various options, and Sebastian Moeller also gave some useful = advice. > > >>>>>> > > >>>>>> After looking at the options, I despair of giving people a = clear > > >>>>>> recommendation that would be optimal for their equipment. = Consequently, I > > >>>>>> believe the best we can do is come up with =93good enough=94 = recommendations > > >>>>>> that are not wrong, and still give decent performance. > > >>>>>> > > >>>>>> In this spirit, I have changed Draft #3 of the =93Setting up = SQM=94 page to > > >>>>>> reflect this understanding. See > > >>>>>> = http://www.bufferbloat.net/projects/cerowrt/wiki/Setting_up_AQM_for_CeroWr= t_310 > > >>>>>> > > >>>>>> ADSL/ATM link: Choose =93ADSL/ATM", and set Per = Packet Overhead to > > >>>>>> 40 > > >>>>>> VDSL2 link: Choose =93VDSL=94, and set Per Packet = Overhead to 8 > > >>>>>> Other kind of link (e.g., Cable, Fiber, Ethernet, = other not > > >>>>>> listed): Choose =93None (default)=94, and set Per Packet = Overhead to 0 > > >>>>>> > > >>>>>> NB: I have changed the first menu choice to =93ADSL/ATM=94 = and the second to > > >>>>>> =93VDSL=94 in the description. I would ask that we change to = GUI to reflect > > >>>>>> those names as well. This makes it far easier/less confusing = to talk about > > >>>>>> the options. > > >>>>>> > > >>>>>> As always, I welcome help in setting out clear = recommendations that work > > >>>>>> well for the vast majority of people who try CeroWrt. Thanks. > > >>>>>> > > >>>>>> Rich > > >>>>>> _______________________________________________ > > >>>>>> Cerowrt-devel mailing list > > >>>>>> Cerowrt-devel@lists.bufferbloat.net > > >>>>>> https://lists.bufferbloat.net/listinfo/cerowrt-devel > > >>>>> _______________________________________________ > > >>>>> Cerowrt-devel mailing list > > >>>>> Cerowrt-devel@lists.bufferbloat.net > > >>>>> https://lists.bufferbloat.net/listinfo/cerowrt-devel > > >>>> > > >>> _______________________________________________ > > >>> Cerowrt-devel mailing list > > >>> Cerowrt-devel@lists.bufferbloat.net > > >>> https://lists.bufferbloat.net/listinfo/cerowrt-devel > > > > > > > _______________________________________________ > > Cerowrt-devel mailing list > > Cerowrt-devel@lists.bufferbloat.net > > https://lists.bufferbloat.net/listinfo/cerowrt-devel > > >=20 >=20 --Apple-Mail=_F37E704F-8506-4422-BEF8-FA0D4BBA44EB--