/* * Copyright (c) 2020, Broadband Forum * Copyright (c) 2020, AT&T Communications * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * * UDP Speed Test - udpst_srates.c * * This file builds or displays the sending rate table containing the send * parameters used for testing. * * Author Date Comments * -------------------- ---------- ---------------------------------- * Len Ciavattone 09/05/2019 Split off from udpst.c * Len Ciavattone 09/24/2019 Include max burst when jumbo false * Len Ciavattone 12/14/2021 Modified largest jumbo sizes to be * even multiple of 1500 byte packets * with IPv6. No longer mixing jumbo * sizes with non-jumbo sizes. * Len Ciavattone 12/21/2021 Add traditional (1500 byte) MTU * */ #define UDPST_SRATES #ifdef __linux__ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #ifdef AUTH_KEY_ENABLE #include #include #endif #else #include "../udpst_srates_alt1.h" #endif // #include "cJSON.h" #include "udpst_common.h" #include "udpst_protocol.h" #include "udpst.h" #include "udpst_srates.h" #ifndef __linux__ #include "../udpst_srates_alt2.h" #endif //---------------------------------------------------------------------------- // // External data // extern char scratch[STRING_SIZE]; extern struct configuration conf; extern struct repository repo; //---------------------------------------------------------------------------- // Function definitions //---------------------------------------------------------------------------- // // Define sending rate table (with or without jumbo payload sizes above 1 Gbps) // // Populate scratch buffer and return length on error // int def_sending_rates(void) { int var, i, j, k, jmax, kmax; unsigned int payload; BOOL stop; struct sendingRate *sr; // // Define initial sending rates up to 1 Gbps // if (conf.traditionalMTU) { jmax = 11; kmax = 8; payload = MAX_TPAYLOAD_SIZE; } else { jmax = 9; kmax = 10; payload = MAX_PAYLOAD_SIZE; } stop = FALSE; for (k = 0; k <= kmax; k++) { for (i = 0; i < 10; i++) { sr = &repo.sendingRates[repo.maxSendingRates++]; if (k > 0) { sr->txInterval1 = BASE_SEND_TIMER1; sr->udpPayload1 = payload; sr->burstSize1 = k; } if (i > 0) { sr->txInterval2 = BASE_SEND_TIMER2; sr->udpPayload2 = payload; sr->burstSize2 = i; sr->udpAddon2 = 0; } if (k == 0 && i == 0) { sr->txInterval2 = BASE_SEND_TIMER2; sr->udpAddon2 = MIN_PAYLOAD_SIZE; } else if (!conf.traditionalMTU && k == kmax) { break; } for (j = 1; j <= jmax; j++) { sr = &repo.sendingRates[repo.maxSendingRates++]; if (k > 0) { sr->txInterval1 = BASE_SEND_TIMER1; sr->udpPayload1 = payload; sr->burstSize1 = k; } sr->txInterval2 = BASE_SEND_TIMER2; if (i > 0) { sr->udpPayload2 = payload; sr->burstSize2 = i; } sr->udpAddon2 = ((j * 1000) / 8) - L3DG_OVERHEAD; // Explicit stop at 1 Gbps if (repo.maxSendingRates > 1000) { stop = TRUE; break; } } if (stop) break; } if (stop) break; } repo.hSpeedThresh = repo.maxSendingRates - 1; // Index of high-speed threshold // // Finish jumbo or non-jumbo payload sizes above 1 Gbps // // NOTE: Total sending rate rows are the same in either case // if (conf.jumboStatus) { // // Increase payload sizes until jumbo limit // for (i = MAX_L3_PACKET + 125; i <= MAX_JL3_PACKET; i += 125) { sr = &repo.sendingRates[repo.maxSendingRates++]; sr->txInterval1 = BASE_SEND_TIMER1; sr->udpPayload1 = i - L3DG_OVERHEAD; sr->burstSize1 = 10; } // // With jumbo payload size for transmitter 1, add additional payload required for 2 // // To better support the use of jumbo sizes with a non-jumbo MTU, do not use any payload sizes // that would mix datagrams requiring fragmentation with datagrams not requiring fragmentation. // Because this has been shown to produce reordering, all payload sizes will be greater than // what can be accommodated in IPv6 with a 1500 byte MTU. // for (i = 0; i < 4; i++) { var = MAX_L3_PACKET - (i * 125 * 2); for (j = 0; j < 7; j++) { sr = &repo.sendingRates[repo.maxSendingRates++]; sr->txInterval1 = BASE_SEND_TIMER1; sr->udpPayload1 = MAX_JPAYLOAD_SIZE; sr->burstSize1 = 10 + i; sr->txInterval2 = BASE_SEND_TIMER1; sr->udpPayload2 = (var + (j * MAX_L3_PACKET)) - L3DG_OVERHEAD; // Avoid non-jumbo sizes with less frequent larger payloads if (j == 0) { sr->txInterval2 *= 4; sr->udpPayload2 *= 4; } else if (j == 1) { sr->txInterval2 *= 2; sr->udpPayload2 *= 2; } sr->burstSize2 = 1; sr->udpAddon2 = 0; } } } else { if (conf.traditionalMTU) { jmax = 9; payload = MAX_TPAYLOAD_SIZE; } else { jmax = 11; payload = MAX_PAYLOAD_SIZE; } for (j = jmax; j <= MAX_BURST_SIZE; j++) { sr = &repo.sendingRates[repo.maxSendingRates++]; sr->txInterval1 = BASE_SEND_TIMER1; sr->udpPayload1 = payload; sr->burstSize1 = j; if (conf.traditionalMTU && j < 23) { sr = &repo.sendingRates[repo.maxSendingRates++]; sr->txInterval1 = BASE_SEND_TIMER1; sr->udpPayload1 = payload; sr->burstSize1 = j; sr->txInterval2 = BASE_SEND_TIMER2; sr->udpPayload2 = payload; sr->burstSize2 = 5; } if (repo.maxSendingRates == MAX_SENDING_RATES) break; } } // // Sanity check table // if (repo.maxSendingRates > MAX_SENDING_RATES) { var = sprintf(scratch, "ERROR: Sending rate table build failure (overrun)\n"); return var; } return 0; } //---------------------------------------------------------------------------- // // Display sending rate table parameters for each index // void show_sending_rates(int fd) { int i, var, var2, payload1, payload2, addon, ipv6add; char ipver[8]; double dvar; struct sendingRate *sr; // // Output header // if (conf.ipv6Only) { ipv6add = IPV6_ADDSIZE; strcpy(ipver, "IPv6"); } else { ipv6add = 0; strcpy(ipver, "IPv4"); } var = sprintf(scratch, "Sending Rate Table for %s (Dual Transmitters, Referenced by Index)...\n", ipver); var = write(fd, scratch, var); var = sprintf(scratch, "%s) %s %s %s + %s %s %s %s = %s\n", "Index", "TxInt(us)", "Payload", "Burst", "TxInt(us)", "Payload", "Burst", "Add-On", "Mbps(L3/IP)"); var = write(fd, scratch, var); // // Output each row // for (i = 0, sr = repo.sendingRates; i < repo.maxSendingRates; i++, sr++) { var = var2 = 0; payload1 = payload2 = addon = 0; if (sr->burstSize1 > 0) { var = (USECINSEC / sr->txInterval1) * sr->burstSize1; payload1 = (int) sr->udpPayload1 - ipv6add; var *= payload1 + L3DG_OVERHEAD + ipv6add; } if (sr->burstSize2 > 0) { var2 = (USECINSEC / sr->txInterval2) * sr->burstSize2; payload2 = (int) sr->udpPayload2 - ipv6add; var2 *= payload2 + L3DG_OVERHEAD + ipv6add; } if (sr->udpAddon2 > 0) { addon = (int) sr->udpAddon2 - ipv6add; var2 += (USECINSEC / sr->txInterval2) * (addon + L3DG_OVERHEAD + ipv6add); } dvar = (double) (var + var2); dvar *= 8; // Convert to bits/sec dvar /= 1000000; // Convert to Mbps var = sprintf(scratch, "%5d) %8u %7d %5u + %8u %7d %5u %5d = %10.2f\n", i, sr->txInterval1, payload1, sr->burstSize1, sr->txInterval2, payload2, sr->burstSize2, addon, dvar); var = write(fd, scratch, var); } if (!conf.jumboStatus) { var = sprintf(scratch, "NOTE: Disabling jumbo datagram sizes may impede rates above 1 Gbps\n"); var = write(fd, scratch, var); } return; } //----------------------------------------------------------------------------