In order to measure the packet drop rate for TCP packets on mininet we don’t find such APIs to get these statistics. For example, if we sent more packets than the link’s bandwidth or the switch buffer size, some of the packets would be dropped, but we don’t get the statistics since the TCP is a reliable protocol and it will re-transmit the packet if it detects some packet has been dropped. Hence we don’t get the packet loss rate on the application view (iperf).
To take it back to the application view, i.e. iperf, it makes more sense to talk about the “re-transmission rate” for TCP, while I searched through the link https://www.reddit.com/r/networking/comments/3w2t8d/trying_to_understand_iperf3_logs/ i found that it suggested that IPERF3 will tell you the number of retransmitted packets (per interval, and total), but it does not show the total number of packets transmitted and received, but only bytes. Since, Iperf3 gets the re transmission information from the kernel via the function getsockopt so when the third parameter is “TCP_INFO”, kernel will return some metadata of the specific TCP connection which include the re transmission. SO we night use the TCP_INFO field to get the statistics.The code as follows:
To take it back to the application view, i.e. iperf, it makes more sense to talk about the “re-transmission rate” for TCP, while I searched through the link https://www.reddit.com/r/networking/comments/3w2t8d/trying_to_understand_iperf3_logs/ i found that it suggested that IPERF3 will tell you the number of retransmitted packets (per interval, and total), but it does not show the total number of packets transmitted and received, but only bytes. Since, Iperf3 gets the re transmission information from the kernel via the function getsockopt so when the third parameter is “TCP_INFO”, kernel will return some metadata of the specific TCP connection which include the re transmission. SO we night use the TCP_INFO field to get the statistics.The code as follows:
#include <stdio.h>
#include <stdlib.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <errno.h>
#include "iperf.h"
#include "iperf_api.h"
#include "iperf_locale.h"
/*************************************************************/
int
has_tcpinfo(void)
{
#if (defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__)) \
&& defined(TCP_INFO)
return 1;
#else
return 0;
#endif
}
/*************************************************************/
int
has_tcpinfo_retransmits(void)
{
#if defined(linux) && defined(TCP_MD5SIG)
/* TCP_MD5SIG doesn't actually have anything to do with TCP
** retransmits, it just showed up in the same rev of the header
** file. If it's present then struct tcp_info has the
** tcpi_total_retrans field that we need; if not, not.
*/
return 1;
#else
#if defined(__FreeBSD__) && __FreeBSD_version >= 600000
return 1; /* Should work now */
#elif defined(__NetBSD__) && defined(TCP_INFO)
return 1;
#else
return 0;
#endif
#endif
}
/*************************************************************/
void
save_tcpinfo(struct iperf_stream *sp, struct iperf_interval_results *irp)
{
#if (defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__)) && \
defined(TCP_INFO)
socklen_t tcp_info_length = sizeof(struct tcp_info);
if (getsockopt(sp->socket, IPPROTO_TCP, TCP_INFO, (void *)&irp->tcpInfo, &tcp_info_length) < 0)
iperf_err(sp->test, "getsockopt - %s", strerror(errno));
if (sp->test->debug) {
printf("tcpi_snd_cwnd %u tcpi_snd_mss %u tcpi_rtt %u\n",
irp->tcpInfo.tcpi_snd_cwnd, irp->tcpInfo.tcpi_snd_mss,
irp->tcpInfo.tcpi_rtt);
}
#endif
}
/*************************************************************/
long
get_total_retransmits(struct iperf_interval_results *irp)
{
#if defined(linux) && defined(TCP_MD5SIG)
return irp->tcpInfo.tcpi_total_retrans;
#elif defined(__FreeBSD__) && __FreeBSD_version >= 600000
return irp->tcpInfo.tcpi_snd_rexmitpack;
#elif defined(__NetBSD__) && defined(TCP_INFO)
return irp->tcpInfo.tcpi_snd_rexmitpack;
#else
return -1;
#endif
}
/*************************************************************/
/*
* Return snd_cwnd in octets.
*/
long
get_snd_cwnd(struct iperf_interval_results *irp)
{
#if defined(linux) && defined(TCP_MD5SIG)
return irp->tcpInfo.tcpi_snd_cwnd * irp->tcpInfo.tcpi_snd_mss;
#elif defined(__FreeBSD__) && __FreeBSD_version >= 600000
return irp->tcpInfo.tcpi_snd_cwnd;
#elif defined(__NetBSD__) && defined(TCP_INFO)
return irp->tcpInfo.tcpi_snd_cwnd * irp->tcpInfo.tcpi_snd_mss;
#else
return -1;
#endif
}
/*************************************************************/
/*
* Return rtt in usec.
*/
long
get_rtt(struct iperf_interval_results *irp)
{
#if defined(linux) && defined(TCP_MD5SIG)
return irp->tcpInfo.tcpi_rtt;
#elif defined(__FreeBSD__) && __FreeBSD_version >= 600000
return irp->tcpInfo.tcpi_rtt;
#elif defined(__NetBSD__) && defined(TCP_INFO)
return irp->tcpInfo.tcpi_rtt;
#else
return -1;
#endif
}
/*************************************************************/
/*
* Return rttvar in usec.
*/
long
get_rttvar(struct iperf_interval_results *irp)
{
#if defined(linux) && defined(TCP_MD5SIG)
return irp->tcpInfo.tcpi_rttvar;
#elif defined(__FreeBSD__) && __FreeBSD_version >= 600000
return irp->tcpInfo.tcpi_rttvar;
#elif defined(__NetBSD__) && defined(TCP_INFO)
return irp->tcpInfo.tcpi_rttvar;
#else
return -1;
#endif
}
/*************************************************************/
/*
* Return PMTU in bytes.
*/
long
get_pmtu(struct iperf_interval_results *irp)
{
#if defined(linux) && defined(TCP_MD5SIG)
No comments:
Post a Comment