Ejemplo n.º 1
0
  static int read_ethtool_info(struct ifreq *ifr, int fd, SFLAdaptor *adaptor)
  {
    // Try to get the ethtool info for this interface so we can infer the
    // ifDirection and ifSpeed. Learned from openvswitch (http://www.openvswitch.org).
    int changed = NO;
    struct ethtool_cmd ecmd = { 0 };
    ecmd.cmd = ETHTOOL_GSET;
    ifr->ifr_data = (char *)&ecmd;
    if(ioctl(fd, SIOCETHTOOL, ifr) >= 0) {
      uint32_t direction = ecmd.duplex ? 1 : 2;
      if(direction != adaptor->ifDirection) {
	changed = YES;
      }
      adaptor->ifDirection = direction;
      uint64_t ifSpeed_mb = ecmd.speed;
      // ethtool_cmd_speed(&ecmd) is available in newer systems and uses the
      // speed_hi field too,  but we would need to run autoconf-style
      // tests to see if it was there and we are trying to avoid that.
      if(ifSpeed_mb == (uint16_t)-1 ||
	 ifSpeed_mb == (uint32_t)-1) {
	// unknown
	if(adaptor->ifSpeed != 0) {
	  changed = YES;
	}
	adaptor->ifSpeed = 0;
      }
      else {
	uint64_t ifSpeed_bps = ifSpeed_mb * 1000000;
	if(adaptor->ifSpeed != ifSpeed_bps) {
	  changed = YES;
	}
	adaptor->ifSpeed = ifSpeed_bps;
      }
#if (HSP_ETHTOOL_STATS || HSF_DOCKER)
      // see if the ethtool stats block can give us multicast/broadcast counters too
      HSPAdaptorNIO *adaptorNIO = (HSPAdaptorNIO *)adaptor->userData;
      adaptorNIO->et_nfound=0;
      adaptorNIO->et_nctrs = ethtool_num_counters(ifr, fd);
      if(adaptorNIO->et_nctrs) {
	struct ethtool_gstrings *ctrNames;
	uint32_t bytes = sizeof(*ctrNames) + (adaptorNIO->et_nctrs * ETH_GSTRING_LEN);
	ctrNames = (struct ethtool_gstrings *)my_calloc(bytes);
	ctrNames->cmd = ETHTOOL_GSTRINGS;
	ctrNames->string_set = ETH_SS_STATS;
	ctrNames->len = adaptorNIO->et_nctrs;
	ifr->ifr_data = (char *)ctrNames;
	if(ioctl(fd, SIOCETHTOOL, ifr) >= 0) {
	  // copy out one at a time to make sure we have null-termination
	  char cname[ETH_GSTRING_LEN+1];
	  cname[ETH_GSTRING_LEN] = '\0';
	  for(int ii=0; ii < adaptorNIO->et_nctrs; ii++) {
	    memcpy(cname, &ctrNames->data[ii * ETH_GSTRING_LEN], ETH_GSTRING_LEN);
	    if(debug) myLog(LOG_INFO, "ethtool counter %s is at index %d", cname, ii);
	    // then see if this is one of the ones we want,
	    // and record the index if it is.
#ifdef HSP_ETHTOOL_STATS
	    if(staticStringsIndexOf(HSP_ethtool_mcasts_in_names, cname) != -1) {
	      adaptorNIO->et_idx_mcasts_in = ii+1;
	      adaptorNIO->et_nfound++;
	    }
	    else if(staticStringsIndexOf(HSP_ethtool_mcasts_out_names, cname) != -1) {
	      adaptorNIO->et_idx_mcasts_out = ii+1;
	      adaptorNIO->et_nfound++;
	    }
	    else if(staticStringsIndexOf(HSP_ethtool_bcasts_in_names, cname) != -1) {
	      adaptorNIO->et_idx_bcasts_in = ii+1;
	      adaptorNIO->et_nfound++;
	    }
	    else if(staticStringsIndexOf(HSP_ethtool_bcasts_out_names, cname) != -1) {
	      adaptorNIO->et_idx_bcasts_out = ii+1;
	      adaptorNIO->et_nfound++;
	    }
#endif
#ifdef HSF_DOCKER
	    if(staticStringsIndexOf(HSP_ethtool_peer_ifindex_names, cname) != -1) {
	      // Now go ahead and make the call to get the peer_ifindex.
	      struct ethtool_stats *et_stats = (struct ethtool_stats *)my_calloc(bytes);
	      et_stats->cmd = ETHTOOL_GSTATS;
	      et_stats->n_stats = adaptorNIO->et_nctrs;
	      ifr->ifr_data = (char *)et_stats;
	      if(ioctl(fd, SIOCETHTOOL, ifr) >= 0) {
		adaptorNIO->peer_ifIndex = et_stats->data[ii];
		if(debug) myLog(LOG_INFO, "Interface %s (ifIndex=%u) has peer_ifindex=%u", 
				adaptor->deviceName,
				adaptor->ifIndex,
				adaptorNIO->peer_ifIndex);
	      }
	    }
#endif
	  }
	}
	my_free(ctrNames);
      }
#endif
    }
    return changed;
  }
Ejemplo n.º 2
0
/*________________---------------------------__________________
  ________________    read_ethtool_info      __________________
  ----------------___________________________------------------
*/
  static void read_ethtool_info(struct ifreq *ifr, int fd, SFLAdaptor *adaptor)
  {
    // Try to get the ethtool info for this interface so we can infer the
    // ifDirection and ifSpeed. Learned from openvswitch (http://www.openvswitch.org).
    struct ethtool_cmd ecmd = { 0 };
    ecmd.cmd = ETHTOOL_GSET;
    ifr->ifr_data = (char *)&ecmd;
    if(ioctl(fd, SIOCETHTOOL, ifr) >= 0) {
      adaptor->ifDirection = ecmd.duplex ? 1 : 2;
      uint64_t ifSpeed_mb = ecmd.speed;
      // ethtool_cmd_speed(&ecmd) is available in newer systems and uses the
      // speed_hi field too,  but we would need to run autoconf-style
      // tests to see if it was there and we are trying to avoid that.
      if(ifSpeed_mb == (uint16_t)-1 ||
	 ifSpeed_mb == (uint32_t)-1) {
	// unknown
	adaptor->ifSpeed = 0;
      }
      else {
	adaptor->ifSpeed = ifSpeed_mb * 1000000;
      }
#ifdef HSP_ETHTOOL_STATS
      // see if the ethtool stats block can give us multicast/broadcast counters too
      HSPAdaptorNIO *adaptorNIO = (HSPAdaptorNIO *)adaptor->userData;
      adaptorNIO->et_nfound=0;
      struct {
	struct ethtool_sset_info ssi;
	uint32_t data;
      } sset_info;
      memset(&sset_info, 0, sizeof(sset_info));
      sset_info.ssi.cmd = ETHTOOL_GSSET_INFO;
      sset_info.ssi.sset_mask = (uint64_t)1 << ETH_SS_STATS;
      ifr->ifr_data = (char *)&sset_info;
      if(ioctl(fd, SIOCETHTOOL, ifr) >= 0) {
	if(sset_info.ssi.sset_mask) {
	  adaptorNIO->et_nctrs = sset_info.data;
	  if(adaptorNIO->et_nctrs) {
	    struct ethtool_gstrings *ctrNames;
	    uint32_t bytes = sizeof(ctrNames) + (adaptorNIO->et_nctrs * ETH_GSTRING_LEN);
	    ctrNames = (struct ethtool_gstrings *)my_calloc(bytes);
	    ctrNames->cmd = ETHTOOL_GSTRINGS;
	    ctrNames->string_set = ETH_SS_STATS;
	    ctrNames->len = adaptorNIO->et_nctrs;
	    ifr->ifr_data = (char *)ctrNames;
	    if(ioctl(fd, SIOCETHTOOL, ifr) >= 0) {
	      // copy out one at a time to make sure we have null-termination
	      char cname[ETH_GSTRING_LEN+1];
	      cname[ETH_GSTRING_LEN] = '\0';
	      for(int ii=0; ii < adaptorNIO->et_nctrs; ii++) {
		memcpy(cname, &ctrNames->data[ii * ETH_GSTRING_LEN], ETH_GSTRING_LEN);
		// then see if this is one of the ones we want,
		// and record the index if it is.
		if(staticStringsIndexOf(HSP_ethtool_mcasts_in_names, cname) != -1) {
		  adaptorNIO->et_idx_mcasts_in = ii+1;
		  adaptorNIO->et_nfound++;
		}
		else if(staticStringsIndexOf(HSP_ethtool_mcasts_out_names, cname) != -1) {
		  adaptorNIO->et_idx_mcasts_out = ii+1;
		  adaptorNIO->et_nfound++;
		}
		else if(staticStringsIndexOf(HSP_ethtool_bcasts_in_names, cname) != -1) {
		  adaptorNIO->et_idx_bcasts_in = ii+1;
		  adaptorNIO->et_nfound++;
		}
		else if(staticStringsIndexOf(HSP_ethtool_bcasts_out_names, cname) != -1) {
		  adaptorNIO->et_idx_bcasts_out = ii+1;
		  adaptorNIO->et_nfound++;
		}
	      }
	    }
	    my_free(ctrNames);
	  }
	}
      }
#endif
    }
  }