Hello Florian,
I've made some functionality extension to debug QoS in the network -
ability to set tos (present in most standard "pings") and to verify
received tos field (didn't see any ping command with this feature).
May be it will need to someone else.
Best regards,
Vladimir
double latency;
uint32_t dropped;
int recv_ttl;
double latency;
uint32_t dropped;
int recv_ttl;
char *data;
void *context;
char *data;
void *context;
double timeout;
int ttl;
int addrfamily;
double timeout;
int ttl;
int addrfamily;
char *data;
struct sockaddr *srcaddr;
char *data;
struct sockaddr *srcaddr;
ptr->recv_ttl = ip_hdr->ip_ttl;
ptr->recv_ttl = ip_hdr->ip_ttl;
+ ptr->recv_tos = ip_hdr->ip_tos;
+ }
struct timeval diff;
pinghost_t *host = NULL;
int recv_ttl;
struct timeval diff;
pinghost_t *host = NULL;
int recv_ttl;
/*
* Set up the receive buffer..
/*
* Set up the receive buffer..
/* Iterate over all auxiliary data in msghdr */
recv_ttl = -1;
/* Iterate over all auxiliary data in msghdr */
recv_ttl = -1;
for (cmsg = CMSG_FIRSTHDR (&msghdr); /* {{{ */
cmsg != NULL;
cmsg = CMSG_NXTHDR (&msghdr, cmsg))
for (cmsg = CMSG_FIRSTHDR (&msghdr); /* {{{ */
cmsg != NULL;
cmsg = CMSG_NXTHDR (&msghdr, cmsg))
if (cmsg->cmsg_level != IPPROTO_IP)
continue;
if (cmsg->cmsg_level != IPPROTO_IP)
continue;
+ if (cmsg->cmsg_type == IP_TOS)
+ {
+ memcpy (&recv_tos, CMSG_DATA (cmsg),
+ sizeof (recv_tos));
+ dprintf ("TOSv4 = %u;\n", recv_tos);
+ } else
if (cmsg->cmsg_type == IP_TTL)
{
memcpy (&recv_ttl, CMSG_DATA (cmsg),
if (cmsg->cmsg_type == IP_TTL)
{
memcpy (&recv_ttl, CMSG_DATA (cmsg),
if (cmsg->cmsg_level != IPPROTO_IPV6)
continue;
if (cmsg->cmsg_level != IPPROTO_IPV6)
continue;
+ if (cmsg->cmsg_type == IPV6_RECVTCLASS)
+ {
+ memcpy (&recv_tos, CMSG_DATA (cmsg),
+ sizeof (recv_tos));
+ dprintf ("TOSv6 = %u;\n", recv_tos);
+ } else
if (cmsg->cmsg_type == IPV6_HOPLIMIT)
{
memcpy (&recv_ttl, CMSG_DATA (cmsg),
if (cmsg->cmsg_type == IPV6_HOPLIMIT)
{
memcpy (&recv_ttl, CMSG_DATA (cmsg),
if (recv_ttl >= 0)
host->recv_ttl = recv_ttl;
if (recv_ttl >= 0)
host->recv_ttl = recv_ttl;
+ if (recv_tos != 0xffff)
+ host->recv_tos = recv_tos;
host->latency = ((double) diff.tv_usec) / 1000.0;
host->latency += ((double) diff.tv_sec) * 1000.0;
host->latency = ((double) diff.tv_usec) / 1000.0;
host->latency += ((double) diff.tv_sec) * 1000.0;
+/*
+ * Set the TOS of a socket protocol independently.
+ */
+static int ping_set_tos (pinghost_t *ph, unsigned tos)
+{
+ int ret = -2;
+
+ if (ph->addrfamily == AF_INET)
+ {
+ dprintf ("Setting TP_TOS to %i\n", ttl);
+ ret = setsockopt (ph->fd, IPPROTO_IP, IP_TOS,
+ &tos, sizeof (tos));
+ }
+ else if (ph->addrfamily == AF_INET6)
+ {
+ dprintf ("Setting IPV6_TCLASS to %i\n", ttl);
+ ret = setsockopt (ph->fd, IPPROTO_IPV6, IPV6_TCLASS,
+ &tos, sizeof (tos));
+ }
+
+ return (ret);
+}
+
static int ping_get_ident (void)
{
int fd;
static int ping_get_ident (void)
{
int fd;
obj->ttl = PING_DEF_TTL;
obj->addrfamily = PING_DEF_AF;
obj->data = strdup (PING_DEF_DATA);
obj->ttl = PING_DEF_TTL;
obj->addrfamily = PING_DEF_AF;
obj->data = strdup (PING_DEF_DATA);
+ case PING_OPT_TOS:{
+ obj->tos=*(unsigned *)value;
+ pinghost_t *ph;
+ for (ph = obj->head; ph != NULL; ph = ph->next)
+ ping_set_tos (ph, obj->tos);
+ break;
+ }
case PING_OPT_TIMEOUT:
obj->timeout = *((double *) value);
if (obj->timeout < 0.0)
case PING_OPT_TIMEOUT:
obj->timeout = *((double *) value);
if (obj->timeout < 0.0)
}
ping_set_ttl (ph, obj->ttl);
}
ping_set_ttl (ph, obj->ttl);
+ ping_set_tos (ph, obj->tos);
return (0);
} /* int ping_host_add */
return (0);
} /* int ping_host_add */
*((int *) buffer) = iter->recv_ttl;
ret = 0;
break;
*((int *) buffer) = iter->recv_ttl;
ret = 0;
break;
+
+ case PING_INFO_TOS:
+ ret = ENOMEM;
+ if (*buffer_len>sizeof(unsigned)) *buffer_len=sizeof(unsigned);
+ if (!*buffer_len) *buffer_len=1;
+ if (orig_buffer_len < *buffer_len)
+ break;
+ memcpy(buffer,&iter->recv_tos,*buffer_len);
+ ret = 0;
+ break;
static char *opt_filename = NULL;
static int opt_count = -1;
static int opt_send_ttl = 64;
static char *opt_filename = NULL;
static int opt_count = -1;
static int opt_send_ttl = 64;
+static unsigned opt_send_tos = 0;
" -c count number of ICMP packets to send\n"
" -i interval interval with which to send ICMP packets\n"
" -t ttl time to live for each ICMP packet\n"
" -c count number of ICMP packets to send\n"
" -i interval interval with which to send ICMP packets\n"
" -t ttl time to live for each ICMP packet\n"
+ " -z tos Type-of-service/class-of-service for each ICMP packet\n"
" -I srcaddr source address\n"
" -D device outgoing interface name\n"
" -f filename filename to read hosts from\n"
" -I srcaddr source address\n"
" -D device outgoing interface name\n"
" -f filename filename to read hosts from\n"
- optchar = getopt (argc, argv, "46c:hi:I:t:f:D:");
+ optchar = getopt (argc, argv, "46c:hi:I:t:z:f:D:");
if (optchar == -1)
break;
if (optchar == -1)
break;
+ case 'z':
+ {
+ int new_send_tos;
+ new_send_tos = atoi (optarg);
+ if ((new_send_tos > 0) && (new_send_tos < 256))
+ opt_send_tos = new_send_tos;
+ else
+ fprintf (stderr, "Ignoring invalid TOS argument: %s\n",
+ optarg);
+ break;
+ }
+
case 'h':
usage_exit (argv[0], 0);
break;
case 'h':
usage_exit (argv[0], 0);
break;
double latency;
unsigned int sequence;
int recv_ttl;
double latency;
unsigned int sequence;
int recv_ttl;
size_t buffer_len;
size_t data_len;
ping_context_t *context;
size_t buffer_len;
size_t data_len;
ping_context_t *context;
ping_iterator_get_info (iter, PING_INFO_RECV_TTL,
&recv_ttl, &buffer_len);
ping_iterator_get_info (iter, PING_INFO_RECV_TTL,
&recv_ttl, &buffer_len);
+ recv_tos = 0;
+ buffer_len = sizeof (recv_tos);
+ ping_iterator_get_info (iter, PING_INFO_TOS,
+ &recv_tos, &buffer_len);
+
data_len = 0;
ping_iterator_get_info (iter, PING_INFO_DATA,
NULL, &data_len);
data_len = 0;
ping_iterator_get_info (iter, PING_INFO_DATA,
NULL, &data_len);
|| (latency > (average + stddev)))
color = OPING_YELLOW;
|| (latency > (average + stddev)))
color = OPING_YELLOW;
- HOST_PRINTF ("%zu bytes from %s (%s): icmp_seq=%u ttl=%i "
+ HOST_PRINTF ("%zu bytes from %s (%s): icmp_seq=%u ttl=%i tos=%u "
"time=",
data_len, context->host, context->addr,
"time=",
data_len, context->host, context->addr,
+ sequence, recv_ttl, recv_tos);
wattron (main_win, COLOR_PAIR(color));
HOST_PRINTF ("%.2f", latency);
wattroff (main_win, COLOR_PAIR(color));
wattron (main_win, COLOR_PAIR(color));
HOST_PRINTF ("%.2f", latency);
wattroff (main_win, COLOR_PAIR(color));
- HOST_PRINTF ("%zu bytes from %s (%s): icmp_seq=%u ttl=%i "
+ HOST_PRINTF ("%zu bytes from %s (%s): icmp_seq=%u ttl=%i tos=%u "
"time=%.2f ms\n",
data_len,
context->host, context->addr,
"time=%.2f ms\n",
data_len,
context->host, context->addr,
- sequence, recv_ttl, latency);
+ sequence, recv_ttl, recv_tos, latency);
opt_send_ttl, ping_get_error (ping));
}
opt_send_ttl, ping_get_error (ping));
}
+ if (ping_setopt (ping, PING_OPT_TOS, &opt_send_tos) != 0)
+ {
+ fprintf (stderr, "Setting TOS to %i failed: %s\n",
+ opt_send_tos, ping_get_error (ping));
+ }
+
{
double temp_sec;
double temp_nsec;
{
double temp_sec;
double temp_nsec;
#define PING_OPT_DATA 0x08
#define PING_OPT_SOURCE 0x10
#define PING_OPT_DEVICE 0x20
#define PING_OPT_DATA 0x08
#define PING_OPT_SOURCE 0x10
#define PING_OPT_DEVICE 0x20
+#define PING_OPT_TOS 0x40
#define PING_DEF_TIMEOUT 1.0
#define PING_DEF_TTL 255
#define PING_DEF_TIMEOUT 1.0
#define PING_DEF_TTL 255
#define PING_INFO_USERNAME 8
#define PING_INFO_DROPPED 9
#define PING_INFO_RECV_TTL 10
#define PING_INFO_USERNAME 8
#define PING_INFO_DROPPED 9
#define PING_INFO_RECV_TTL 10
+#define PING_INFO_TOS 11
int ping_iterator_get_info (pingobj_iter_t *iter, int info,
void *buffer, size_t *buffer_len);
int ping_iterator_get_info (pingobj_iter_t *iter, int info,
void *buffer, size_t *buffer_len);