Anzeige:
Ergebnis 1 bis 3 von 3

Thema: eth0: Link is down detektieren

  1. #1
    Registrierter Benutzer
    Registriert seit
    04.07.1999
    Ort
    Zürich
    Beiträge
    221

    eth0: Link is down detektieren

    Hi folks,

    Ich stehe vor folgender Aufgabe: Ich habe mehrere TCP/IP-Verbindungen, über die sporadisch Daten gesendet werden. Bricht ein Client die Verbindung zum Server ab, so kann ich dies detektieren. (read = 0)

    Zieht jedoch jemand das Netzwerkkabel aus, bleibt meine Verbindung bis zum nächsten read bestehen. Der Kernel merk jedoch sofort, dass der Link down ist.
    Code:
    [4297696.224000] tg3: eth0: Link is down.
    [4297704.237000] tg3: eth0: Link is up at 100 Mbps, full duplex.
    [4297704.237000] tg3: eth0: Flow control is on for TX and on for RX.
    Besteht die Möglichkeit, dass meine Applikation ein Event (Signal?) erhält, dass der Link down ist?

    Besten Dank

    Grüsse
    f0rtex
    Doctrína est fructus dulcis radícis amárae.

  2. #2
    Registrierter Benutzer
    Registriert seit
    04.07.1999
    Ort
    Zürich
    Beiträge
    221
    Meine Ansätze bis jetzt:

    1. Den Kernel mich infromieren lassen, dass sich /sys/class/net/eth0/carrier geändert hat:

    Code:
    #include <iostream>
    
    extern "C"
    {
    #include <fcntl.h>
    #include <linux/ethtool.h>
    #include <linux/if_ether.h>
    #include <linux/if.h>
    #include <linux/sockios.h>
    #include <unistd.h>
    #include <signal.h>
    #include <sys/ioctl.h>
    #include <sys/select.h>
    #include <sys/stat.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    }
    
    using namespace std;
    
    static volatile int event_fd;
    
    static void handler(int sig, siginfo_t *si, void *data)
    {
    	event_fd = si->si_fd;
    }
    
    int main(void)
    {
    	struct sigaction act;
    	int fd; 
    
    	act.sa_sigaction = handler;
    	sigemptyset(&act.sa_mask);
    	act.sa_flags = SA_SIGINFO;
    	sigaction(SIGRTMIN + 1, &act, NULL);
    	
    	if ((fd = open("/sys/class/net/eth0", O_RDONLY)) == -1)
    	{
    		perror("open");
    		return EXIT_FAILURE;
    	}
    	cout << "fd: " << fd << endl;
    
    	fcntl(fd, F_SETSIG, SIGRTMIN + 1);
    	fcntl(fd, F_NOTIFY, DN_MODIFY|DN_CREATE|DN_ACCESS|DN_RENAME|DN_ATTRIB|DN_MULTISHOT);
    
    	while (1)
    	{
    		pause();
    		cout << "eth0 changed" << endl;
    	}
    	close(fd);
    }
    Funktioniert leider nur, wenn ich auf die Datei zugreife (cat, touch...).
    Wieso ändert der Kernel den timestamp der Datei nicht, sobald er diese ändert?

    2. Mittels ioctl den Status erfragen.

    Code:
    #include <iostream>
    
    extern "C"
    {
    #include <fcntl.h>
    #include <linux/ethtool.h>
    #include <linux/if_ether.h>
    #include <linux/if.h>
    #include <linux/sockios.h>
    #include <unistd.h>
    #include <signal.h>
    #include <sys/ioctl.h>
    #include <sys/select.h>
    #include <sys/stat.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    }
    
    using namespace std;
    
    int main(void)
    {	
    	int fd;
    	struct ifreq ifr;
    	struct ethtool_value edata;
    
    	fd = socket(AF_INET, SOCK_DGRAM, 0);
    
    	memset(&ifr, 0, sizeof(ifr));
    	strncpy(ifr.ifr_name, "eth0", sizeof(ifr.ifr_name)-1);
    	edata.cmd = ETHTOOL_GLINK;
    	ifr.ifr_data = (caddr_t) &edata;
    	
    
    	while(1)
    	{
    		if(ioctl(fd, SIOCETHTOOL, &ifr) == -1)
    		{
    			perror("ETHTOOL_GLINK");
    			return -1;
    		}
    
    		string foo = edata.data ? "up": "down";
    		cout << foo << endl;
    		sleep(1);
    	}
    	close(fd);
    	return 0;
    }
    Bei dieser Lösung gefällt mir nicht, dass ich das IF pollen müsste. Dazu kommt noch, dass ich root-Rechte benötige.

    Hat jemand einen hinweis, wie ich das (möglichst ohne root) mittels asynchrones Event lösen könnte?


    Any hints?
    Geändert von f0rtex (10-05-2006 um 13:15 Uhr)
    Doctrína est fructus dulcis radícis amárae.

  3. #3
    Registrierter Benutzer
    Registriert seit
    04.07.1999
    Ort
    Zürich
    Beiträge
    221
    Also und hier die Lösung welche nicht die ethtools voraussetzt.
    Ich habe das so gelöst, dass ein Thread den Status pollt und jeweils ein Signal auslöst, wenn das IF down ist.

    Code:
    static void *IfMonitoring(void *arg)
    {
        int fd;
        struct ifreq ifr;
    
        memset(&ifr, 0, sizeof(ifr));  
        strncpy(ifr.ifr_name, "eth0", sizeof(ifr.ifr_name)-1);
        fd = socket(AF_INET, SOCK_DGRAM, 0);
    
        while(1)
        {
            if (ioctl(fd, SIOCGIFFLAGS, &ifr))
            {
                std::cerr << "Could not determin LINK-Status" << std::endl;
                perror("SIOCGIFFFLAGS");       
                close(fd);
                raise(SIGINT);
            }
    
            if ((ifr.ifr_flags & IFF_UP) && !(ifr.ifr_flags & IFF_RUNNING))
            {
                std::cerr << "Interface eth0 down! " << std::endl;
                raise(SIGUSR1);
            }
            sleep(2);
        }
    }
    Grüsse
    f0rtex
    Doctrína est fructus dulcis radícis amárae.

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •