2013년 2월 18일 월요일

Interface Name to PCI bus information

Interface Name 을 이용해서 PCI bus를 조회해야하는 API가 필요해서 popen()을 통해서 ethtool을 실행하여 간단하게 만들어 봤다.

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

char * ifname2pcibus(const char *ifname)

{
    int i;
    size_t rs;
    FILE *fp = NULL;
    char buf1[1024];
    char buf2[1024];
    char full_bus_name[1024];

    // Run command

    sprintf(buf1,"ethtool -i %s | grep \"bus-info:\" | sed -e \"s/bus-info: //\"", ifname);
    fp = popen(buf1, "r");
    if(!fp)
    {
        fprintf(stderr,"popen error\n");
        return NULL;
    }

    // Read PCI bus information

    rs = fread((void*)buf2, sizeof(char), 1024-1, fp);
    if(!rs)
    {
        pclose(fp);
        fprintf(stderr,"popen read error\n");
        return NULL;
    }
    pclose(fp);
    buf2[rs] = '\0';

    // Remove Newline character

    for ( i = 0 ; i < rs ; i++ )
    {
        if ( isspace(buf2[i]) )
            buf2[i] = '\0';
    }

    return strdup(buf2);

}

int main(void)

{
    char * pcibus;
    pcibus = ifname2pcibus("eth0");
    if(pcibus)
    {
        printf("eth0 : %s \n", pcibus);
        free(pcibus);
    }

    return 0;

}

위 상태로 사용하는 것도 문제 될 만한 것은 없지만 매우 무거운 프로그램 내부에서 popen()을 하게 될 경우 내부적으로 수행되는 fork()에 의한 부담이 커지는 관계로 ioctl()을 이용한 버전을 다시 만듦.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <net/if.h>
#include <sys/socket.h>
#include <linux/ethtool.h>
#include <linux/sockios.h>

char *ifname2pcibus(const char *ifname)

{
    int fd;
    struct ifreq ifr;
    struct ethtool_drvinfo drvinfo;

    // Open socket

    fd = socket(AF_INET, SOCK_DGRAM, 0);
    if(fd<0)
        return NULL;

    // Make Request structure

    memset(&ifr, 0x00, sizeof(ifr));
    strcpy(ifr.ifr_name, ifname);
    drvinfo.cmd = ETHTOOL_GDRVINFO;
    ifr.ifr_data = (void*)&drvinfo;

    // Get Driver information

    ioctl(fd, SIOCETHTOOL, &ifr);

    close(fd);

    return strdup(drvinfo.bus_info);
}

int main(void)

{
    char * pcibus;
    pcibus = ifname2pcibus("eth0");
    if(pcibus)
    {
        printf("eth0 : %s \n", pcibus);
        free(pcibus);
    }

    return 0;

}