Changes in interface metric code and initial NIC speed code for linux
authorAndreas Tonnesen <andreto@olsr.org>
Thu, 17 Feb 2005 07:19:49 +0000 (07:19 +0000)
committerAndreas Tonnesen <andreto@olsr.org>
Thu, 17 Feb 2005 07:19:49 +0000 (07:19 +0000)
src/bsd/net.c
src/interfaces.h
src/linux/net.c
src/net_os.h
src/unix/ifnet.c

index 0f93966..cdac93e 100644 (file)
@@ -36,7 +36,7 @@
  * to the project. For more information see the website or contact
  * the copyright holders.
  *
- * $Id: net.c,v 1.12 2005/02/15 20:49:20 kattemat Exp $
+ * $Id: net.c,v 1.13 2005/02/17 07:19:49 kattemat Exp $
  */
 
 #include "../defs.h"
@@ -334,7 +334,6 @@ olsr_recvfrom(int  s,
 }
 
 
-#warning FreeBSD WLAN detection untested!
 int 
 check_wireless_interface(char *ifname)
 {
@@ -350,13 +349,21 @@ check_wireless_interface(char *ifname)
   strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
   ifr.ifr_data = (caddr_t)&wreq;
 
-  if(ioctl(ioctl_s, SIOCGWAVELAN, &ifr) >= 0)
+  return (ioctl(ioctl_s, SIOCGWAVELAN, &ifr) >= 0) ? 1 : 0;
+}
+
+
+int
+calculate_if_metric(char *ifname)
+{
+  if(check_wireless_interface(ifname))
     {
+      /* Wireless */
       return 1;
     }
   else
     {
+      /* Ethernet */
       return 0;
     }
-  return 1;
 }
index f7bc3b2..5d7aaa3 100644 (file)
@@ -36,7 +36,7 @@
  * to the project. For more information see the website or contact
  * the copyright holders.
  *
- * $Id: interfaces.h,v 1.15 2005/02/12 22:32:42 kattemat Exp $
+ * $Id: interfaces.h,v 1.16 2005/02/17 07:19:40 kattemat Exp $
  */
 
 
 
 #define MAX_IF_METRIC           100
 
+
+/*
+ * Weights for interface types, higher
+ * weights are prefered over lower
+ */
+enum olsr_if_wieght
+  {
+    WEIGHT_LOWEST = 0,
+    WEIGHT_SERIAL_LOW,        /* Serial device        */
+    WEIGHT_WLAN_DEFAULT,      /* WLAN unknown rate    */
+    WEIGHT_WLAN_LOW,          /* <11Mb WLAN           */
+    WEIGHT_WLAN_11MB,         /* 11Mb 802.11b         */
+    WEIGHT_WLAN_54MB,         /* 54Mb 802.11g         */
+    WEIGHT_WLAN_HIGH,         /* >54Mb WLAN           */
+    WEIGHT_ETHERNET_DEFAULT,  /* Ethernet unknown rate*/
+    WEIGHT_ETHERNET_10MB,     /* Ethernet 10Mb        */
+    WEIGHT_ETHERNET_100MB,    /* Ethernet 100Mb       */
+    WEIGHT_ETHERNET_1GB,      /* Ethernet 1Gb         */
+    WEIGHT_HIGH,              /* Max                  */
+    WEIGHT_HIGHEST = WEIGHT_HIGH
+  };
+
+
 struct vtimes
 {
   olsr_u8_t hello;
index 7e39f20..7a423c4 100644 (file)
@@ -36,7 +36,7 @@
  * to the project. For more information see the website or contact
  * the copyright holders.
  *
- * $Id: net.c,v 1.18 2005/02/15 21:03:40 kattemat Exp $
+ * $Id: net.c,v 1.19 2005/02/17 07:19:49 kattemat Exp $
  */
 
 
 #include "../net_os.h"
 #include "../parser.h"
 
+
 /*
  *Wireless definitions for ioctl calls
  *(from linux/wireless.h)
  */
 #define SIOCGIWNAME    0x8B01          /* get name == wireless protocol */
+#define SIOCGIWRATE    0x8B21          /* get default bit rate (bps) */
 
 /**
  *Bind a socket to a device
@@ -614,13 +616,141 @@ check_wireless_interface(char *ifname)
   memset(&ifr, 0, sizeof(ifr));
   strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
 
-  if(ioctl(ioctl_s, SIOCGIWNAME, &ifr) >= 0)
+  return (ioctl(ioctl_s, SIOCGIWNAME, &ifr) >= 0) ? 1 : 0;
+}
+
+#if 0
+/* network interface ioctl's for MII commands */
+#ifndef SIOCGMIIPHY
+#define SIOCGMIIPHY (SIOCDEVPRIVATE)   /* Read from current PHY */
+#define SIOCGMIIREG (SIOCDEVPRIVATE+1)         /* Read any PHY register */
+#define SIOCSMIIREG (SIOCDEVPRIVATE+2)         /* Write any PHY register */
+#define SIOCGPARAMS (SIOCDEVPRIVATE+3)         /* Read operational parameters */
+#define SIOCSPARAMS (SIOCDEVPRIVATE+4)         /* Set operational parameters */
+#endif
+
+#include <linux/types.h>
+
+/* This data structure is used for all the MII ioctl's */
+struct mii_data {
+    __u16      phy_id;
+    __u16      reg_num;
+    __u16      val_in;
+    __u16      val_out;
+};
+
+
+/* Basic Mode Control Register */
+#define MII_BMCR               0x00
+#define  MII_BMCR_RESET                0x8000
+#define  MII_BMCR_LOOPBACK     0x4000
+#define  MII_BMCR_100MBIT      0x2000
+#define  MII_BMCR_AN_ENA       0x1000
+#define  MII_BMCR_ISOLATE      0x0400
+#define  MII_BMCR_RESTART      0x0200
+#define  MII_BMCR_DUPLEX       0x0100
+#define  MII_BMCR_COLTEST      0x0080
+
+/* Basic Mode Status Register */
+#define MII_BMSR               0x01
+#define  MII_BMSR_CAP_MASK     0xf800
+#define  MII_BMSR_100BASET4    0x8000
+#define  MII_BMSR_100BASETX_FD 0x4000
+#define  MII_BMSR_100BASETX_HD 0x2000
+#define  MII_BMSR_10BASET_FD   0x1000
+#define  MII_BMSR_10BASET_HD   0x0800
+#define  MII_BMSR_NO_PREAMBLE  0x0040
+#define  MII_BMSR_AN_COMPLETE  0x0020
+#define  MII_BMSR_REMOTE_FAULT 0x0010
+#define  MII_BMSR_AN_ABLE      0x0008
+#define  MII_BMSR_LINK_VALID   0x0004
+#define  MII_BMSR_JABBER       0x0002
+#define  MII_BMSR_EXT_CAP      0x0001
+
+#define MII_PHY_ID1            0x02
+#define MII_PHY_ID2            0x03
+
+/* Auto-Negotiation Advertisement Register */
+#define MII_ANAR               0x04
+/* Auto-Negotiation Link Partner Ability Register */
+#define MII_ANLPAR             0x05
+#define  MII_AN_NEXT_PAGE      0x8000
+#define  MII_AN_ACK            0x4000
+#define  MII_AN_REMOTE_FAULT   0x2000
+#define  MII_AN_ABILITY_MASK   0x07e0
+#define  MII_AN_FLOW_CONTROL   0x0400
+#define  MII_AN_100BASET4      0x0200
+#define  MII_AN_100BASETX_FD   0x0100
+#define  MII_AN_100BASETX_HD   0x0080
+#define  MII_AN_10BASET_FD     0x0040
+#define  MII_AN_10BASET_HD     0x0020
+#define  MII_AN_PROT_MASK      0x001f
+#define  MII_AN_PROT_802_3     0x0001
+
+/* Auto-Negotiation Expansion Register */
+#define MII_ANER               0x06
+#define  MII_ANER_MULT_FAULT   0x0010
+#define  MII_ANER_LP_NP_ABLE   0x0008
+#define  MII_ANER_NP_ABLE      0x0004
+#define  MII_ANER_PAGE_RX      0x0002
+#define  MII_ANER_LP_AN_ABLE   0x0001
+
+
+int
+calculate_if_metric(char *ifname)
+{
+  if(check_wireless_interface(ifname))
     {
-      return 1;
+      //WEIGHT_WLAN_LOW,          /* <11Mb WLAN     */
+      //WEIGHT_WLAN_11MB,         /* 11Mb 802.11b   */
+      //WEIGHT_WLAN_54MB,         /* 54Mb 802.11g   */
+      return WEIGHT_WLAN_LOW;
     }
   else
     {
-      return 0;
+      /* Mii wizardry */
+      struct ifreq ifr;
+      struct mii_data *mii = (struct mii_data *)&ifr.ifr_data;
+      mii->reg_num = MII_BMSR;
+      memset(&ifr, 0, sizeof(ifr));
+      strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+
+      printf("Ethernet device assumed. Trying to get configuration...\n");      
+      if (ioctl(ioctl_s, SIOCGMIIPHY, &ifr) < 0) {
+       if (errno != ENODEV)
+         olsr_printf(1, "SIOCGMIIPHY on '%s' failed: %s\n",
+                     ifr.ifr_name, strerror(errno));
+       //return WEIGHT_ETHERNET_DEFAULT;
+      }
+      if (ioctl(ioctl_s, SIOCGMIIREG, &ifr) < 0) {
+       olsr_printf(1, "SIOCGMIIREG on %s failed: %s\n", ifr.ifr_name,
+                   strerror(errno));
+       //return WEIGHT_ETHERNET_DEFAULT;
+      }
+
+      olsr_printf(1, "%s Mbit, %s duplex\n",
+                 (mii->val_out & MII_BMCR_100MBIT) ? "100" : "10",
+                 (mii->val_out & MII_BMCR_DUPLEX) ? "full" : "half");
+
+
+
+      if(mii->val_out & MII_BMCR_100MBIT)
+       return WEIGHT_ETHERNET_100MB;
+      else
+       return WEIGHT_ETHERNET_10MB;
+      /* Ethernet */
+      //WEIGHT_ETHERNET_10MB,     /* Ethernet 10Mb  */
+      //WEIGHT_ETHERNET_100MB,    /* Ethernet 100Mb */
+      //WEIGHT_ETHERNET_1GB,      /* Ethernet 1Gb   */
+
     }
+}
 
+#else
+int
+calculate_if_metric(char *ifname)
+{
+  return check_wireless_interface(ifname);
 }
+#endif
+  
index 6b3fe32..99480b3 100644 (file)
@@ -36,7 +36,7 @@
  * to the project. For more information see the website or contact
  * the copyright holders.
  *
- * $Id: net_os.h,v 1.6 2005/02/15 20:40:26 kattemat Exp $
+ * $Id: net_os.h,v 1.7 2005/02/17 07:19:49 kattemat Exp $
  */
 
 
@@ -96,9 +96,10 @@ getsocket6(struct sockaddr_in6 *, int, char *);
 int
 get_ipv6_address(char *, struct sockaddr_in6 *, int);
 
-#ifndef WIN32
+int
+calculate_if_metric(char *);
+
 int
 check_wireless_interface(char *);
-#endif
 
 #endif
index 540ecf5..4e27348 100644 (file)
@@ -36,7 +36,7 @@
  * to the project. For more information see the website or contact
  * the copyright holders.
  *
- * $Id: ifnet.c,v 1.15 2005/02/15 20:40:42 kattemat Exp $
+ * $Id: ifnet.c,v 1.16 2005/02/17 07:19:49 kattemat Exp $
  */
 
 
@@ -202,7 +202,7 @@ chk_if_changed(struct olsr_if *iface)
   ifp->is_wireless = check_wireless_interface(ifr.ifr_name);
 
   /* Set interface metric */
-  ifp->int_metric = ifp->is_wireless;
+  ifp->int_metric = calculate_if_metric(ifr.ifr_name);
 
   /* Get MTU */
   if (ioctl(ioctl_s, SIOCGIFMTU, &ifr) < 0)
@@ -566,16 +566,12 @@ chk_if_up(struct olsr_if *iface, int debuglvl)
     }
 
   /* trying to detect if interface is wireless. */
-  if(check_wireless_interface(ifr.ifr_name))
-    {
-      olsr_printf(debuglvl, "\tWireless interface detected\n");
-      ifs.is_wireless = 1;
-    }
+  ifs.is_wireless = check_wireless_interface(ifr.ifr_name);
+
+  if(ifs.is_wireless)
+    olsr_printf(debuglvl, "\tWireless interface detected\n");
   else
-    {
-      olsr_printf(debuglvl, "\tNot a wireless interface\n");
-      ifs.is_wireless = 0;
-    }
+    olsr_printf(debuglvl, "\tNot a wireless interface\n");
 
   
   /* IP version 6 */
@@ -664,8 +660,9 @@ chk_if_up(struct olsr_if *iface, int debuglvl)
   ifs.if_index = if_nametoindex(ifr.ifr_name);
   
   /* Set interface metric */
-  ifs.int_metric = ifs.is_wireless;
-  
+  ifs.int_metric = calculate_if_metric(ifr.ifr_name);
+  olsr_printf(1, "\tMetric: %d\n", ifs.int_metric);
+
   /* setting the interfaces number*/
   ifs.if_nr = iface->index;