今天在添加mtu的metric时, 发现一个ganglia bug, MTU值获取的应该是所有UP端口的最小MTU值, 但是实际上得到的结果并非如此.
gmond.conf配置如下 :
所有端口的MTU,
libmetrics/ interface.c
libmetrics/get_ifi_info.c
gmond.conf
collection_group {
collect_once = yes
time_threshold = 1200
metric {
name = "mtu"
title = "MTU"
}
所有端口的MTU,
# ifconfig -a|grep MTU
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
BROADCAST MULTICAST MTU:1500 Metric:1
UP LOOPBACK RUNNING MTU:16436 Metric:1
BROADCAST MULTICAST MTU:1500 Metric:1
UP端口的mtu最小值是第一条1500, 但是实际ganglia画出来的是回环口的MTU 16436.
获取mtu的代码如下 :
libmetrics/linux/metrics.c
/* --------------------------------------------------------------------------- */
g_val_t
mtu_func ( void )
{
/* We want to find the minimum MTU (Max packet size) over all UP interfaces. */
g_val_t val;
val.uint32 = get_min_mtu();
/* A val of 0 means there are no UP interfaces. Shouldn't happen. */
return val;
}
libmetrics/ interface.c
int
get_min_mtu( void )
{
struct ifi_info *info, *n;
unsigned min_mtu_set = 0;
unsigned min_mtu = 0;
info = Get_ifi_info(AF_INET, 0);
for(n = info; n; n = n->ifi_next)
{
if(!min_mtu_set)
{
min_mtu = n->ifi_mtu;
min_mtu_set = 1;
}
else if( n->ifi_mtu < min_mtu )
{
min_mtu = n->ifi_mtu;
}
}
free_ifi_info(info);
return min_mtu;
}
libmetrics/get_ifi_info.c
struct ifi_info *
get_ifi_info(int family, int doaliases)
{
struct ifi_info *ifi, *ifihead, **ifipnext;
int sockfd, len, lastlen, flags, myflags;
char *ptr, *buf, lastname[IFNAMSIZ], *cptr;
struct ifconf ifc;
struct ifreq *ifr, ifrcopy;
struct sockaddr_in *sinptr;
struct ifreq mtu;
#ifdef SOLARIS
int _c_virt = 0;
#endif /* SOLARIS */
int _all_virt = 0;
sockfd = Socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == -1) {
err_ret("get_ifi_info error: socket returns -1");
return NULL;
}
lastlen = 0;
len = 100 * sizeof(struct ifreq); /* initial buffer size guess */
for ( ; ; ) {
buf = Malloc(len);
ifc.ifc_len = len;
ifc.ifc_buf = buf;
if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
if (errno != EINVAL || lastlen != 0)
err_sys("ioctl error");
} else {
if (ifc.ifc_len == lastlen)
break; /* success, len has not changed */
lastlen = ifc.ifc_len;
}
len += 10 * sizeof(struct ifreq); /* increment */
free(buf);
}
ifihead = NULL;
ifipnext = &ifihead;
lastname[0] = 0;
/* end get_ifi_info1 */
.......
略
struct ifi_info *
Get_ifi_info(int family, int doaliases)
{
struct ifi_info *ifi;
if ( (ifi = get_ifi_info(family, doaliases)) == NULL)
err_quit("get_ifi_info error");
return(ifi);
}
[参考]