problem probing network interfaces

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



   Date: Thu, 08 May 2003 10:29:06 -0700 (PDT)
   From: "David S. Miller" <davem@redhat.com>

      From: Chris Hanson <cph@zurich.ai.mit.edu>
      Date: Thu, 08 May 2003 14:34:21 -0400

      For example, is it sufficient to just set IFF_UP and leave the
      other flags off?

   Setting this interface flag from userspace should work.

OK, but...  (I bet you thought this conversation was finished :)

This seems to work most of the time, except for one of my users.  He's
using the sis900 driver in kernel 2.4.21-rc1.  When I don't force the
interface up, my code is able to detect link beat with no trouble.
When I _do_ force the interface up, it doesn't.

Any ideas why this would be true?  I've tried a number of different
things and have failed to come up with a working configuration, other
than to leave the interface down when it is already down.

I did notice that the sis900 doesn't seem to immediately detect
link-beat when it is up, instead deferring to a timer event, but
sleeping for a full second after bringing the interface up didn't
change anything.

FYI, here is my current detection code.  Perhaps there's something
wrong with it, although it's quite similar to mii-diag.

Chris



static unsigned int
get_link_status (int fd, const char * if_name, unsigned int * result_r)
{
  struct ifreq ifr;
  u16 * data = ((u16 *) (& (ifr . ifr_data)));
  unsigned int if_flags;
  int up_p;
  int run_p;
  int conn_p;
  unsigned int retval;

  strncpy ((ifr . ifr_name), if_name, IFNAMSIZ);
  if ((ioctl (fd, SIOCGIFFLAGS, (&ifr))) < 0)
    return (errno);
  if_flags = (ifr . ifr_flags);
  up_p = ((if_flags & IFF_UP) != 0);
  run_p = ((if_flags & IFF_RUNNING) != 0);

  /* As of 2.4.20, interfaces must be up in order to be interrogated.  */
  if (!up_p)
    {
      strncpy ((ifr . ifr_name), if_name, IFNAMSIZ);
      (ifr . ifr_flags) = IFF_UP;
      ioctl (fd, SIOCSIFFLAGS, (&ifr));
    }

  strncpy ((ifr . ifr_name), if_name, IFNAMSIZ);
  (data[1]) = 1;		/* read Basic Mode Status Register */
  if ((ioctl (fd, SIOCGMIIPHY, (&ifr))) < 0)
    retval = errno;
  else if ((data[3]) == 0xFFFF)
    /* Interface no longer available.  */
    retval = ENODEV;
  else
    {
      /* Check for:
	 0x0002 clear = no jabber
	 0x0004 set = link up
	 0x0010 clear = no remote fault */
      conn_p = (((data[3]) & 0x0016) == 0x0004);
      retval = 0;
    }

  /* Restore original interface flags.  */
  if (!up_p)
    {
      strncpy ((ifr . ifr_name), if_name, IFNAMSIZ);
      (ifr . ifr_flags) = if_flags;
      ioctl (fd, SIOCSIFFLAGS, (&ifr));
    }

  if (retval == 0)
    (*result_r)
      = ((up_p ? STATUS_UP : 0)
	 | (run_p ? STATUS_RUNNING : 0)
	 | (conn_p ? STATUS_CONNECTED : 0));
  return (retval);
}
-
: send the line "unsubscribe linux-net" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux 802.1Q VLAN]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Git]     [Bugtraq]     [Yosemite News and Information]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux PCI]     [Linux Admin]     [Samba]

  Powered by Linux