N-sim
Emulation and simulation of
Wireless Sensor Networks



   Home


   Project Page


   Download


   CVS



   Installation


   Configuration


   Plug-ins




 Hosted by
SourceForge.net Logo

/home/brennan/n-sim/Vaike/linux/system-addons/networking/mesh_metrics.c

Go to the documentation of this file.
00001 
00014 /*
00015  * Copyright 2007. Los Alamos National Security, LLC. This material
00016  * was produced under U.S. Government contract DE-AC52-06NA25396 for
00017  * Los Alamos National Laboratory (LANL), which is operated by Los
00018  * Alamos National Security, LLC, for the Department of Energy. The
00019  * U.S. Government has rights to use, reproduce, and distribute this
00020  * software. NEITHER THE GOVERNMENT NOR LOS ALAMOS NATIONAL SECURITY,
00021  * LLC, MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY LEGAL
00022  * LIABILITY FOR THE USE OF THIS SOFTWARE. If software is modified to
00023  * produce derivative works, such modified software should be clearly
00024  * marked, so as not to confuse it with the version available from LANL.
00025  *
00026  * Additionally, this program is free software; you can redistribute
00027  * it and/or modify it under the terms of the GNU General Public
00028  * License as published by the Free Software Foundation; version 2 of
00029  * the License. Accordingly, this program is distributed in the hope
00030  * it will be useful, but WITHOUT ANY WARRANTY; without even the
00031  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
00032  * PURPOSE. See the GNU General Public License for more details.
00033  */
00034 
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037 #include <unistd.h>
00038 #include <string.h>
00039 #include <sys/time.h>
00040 #include <sys/ioctl.h>
00041 #include <netinet/in.h>
00042 #include <arpa/inet.h>
00043 #include <net/if.h>
00044 #include <syslog.h>
00045 
00046 #include "mesh_metrics.h"
00047 #include "mesh_link.h"
00048 #include "mesh_discovery.h"
00049 #include "sensor_self.h"
00050 #include "sensor_mesh.h"
00051 
00052 
00053 #define MESH_METRICS            3
00054 static const char *mesh_metric_names[MESH_METRICS] =
00055   { "reliability", "goodput", "energy" };
00056 
00057 
00058 int metric_by_name(char *name)
00059 {
00060   int i;
00061   for (i = 0; i < MESH_METRICS; i++) {
00062     if (strcmp(name, mesh_metric_names[i]) == 0)
00063       break;
00064   }
00065   if (i >= MESH_METRICS)
00066     return -1;
00067   return i;
00068 }
00069 
00070 
00071 
00072 void init_metrics(metric_t *metrics)
00073 {
00074   metrics->reliability = -1.0;
00075   metrics->goodput = -1.0;
00076   metrics->energy = -1.0;
00077 }
00078 
00079 
00080 double compile_mesh_metrics(protocol_t *proto, enum mesh_metric m,
00081                             char *destination)
00082 {
00083   double data = 0.0;
00084   link_entry_t *entry = retrieve_entry(proto, ip_to_id(destination));
00085 
00086   if (entry != NULL) {
00087     if (m == RELIABILITY)
00088       data = entry->metrics.reliability;
00089     else if (m == GOODPUT)
00090       data = entry->metrics.goodput;
00091     else if (m == ENERGY)
00092       data = entry->metrics.energy * entry->link.hop_count;
00093   }
00094   return data;
00095 }
00096 
00097 
00098 /* thread */
00099 int echo_statistics(self_t *self)
00100 {
00101   int sd, error, mtu = 1500;
00102   struct sockaddr_in my_addr, their_addr;
00103   struct ifreq ifr;
00104   socklen_t addr_len = sizeof(struct sockaddr);
00105 
00106   if ((sd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
00107     syslog(LOG_ERR, "socket: %m");
00108     return sd;
00109   }
00110 
00111   strcpy(ifr.ifr_name, self->interface);
00112   ifr.ifr_addr.sa_family = AF_INET;
00113   if (ioctl(sd, SIOCGIFMTU, &ifr) < 0)
00114     syslog(LOG_ERR, "net interface \"%s\" not found (%m)", self->interface);
00115   else
00116     mtu = ifr.ifr_mtu;
00117 
00118   my_addr.sin_family = AF_INET;
00119   my_addr.sin_port = htons(MESH_METRICS_PORT+1);
00120   my_addr.sin_addr.s_addr = INADDR_ANY;
00121   memset(my_addr.sin_zero, 0, sizeof(my_addr.sin_zero));
00122 
00123   if ((error = bind(sd, (struct sockaddr*)&my_addr,
00124                     sizeof(struct sockaddr))) < 0) {
00125     syslog(LOG_ERR, "bind: %m");
00126     return error;
00127   }
00128 
00129   while (1) {
00130     int i, nbytes, total_bytes = 0;
00131     for (i = 0; i < MESH_METRICS_PACKETS; i++) {
00132       char buf[mtu];
00133 
00134       if ((nbytes = timed_recv(sd, buf, mtu, &their_addr,
00135                                MESH_METRICS_ROUND)) < 0) {
00136         if (nbytes == -2)
00137           break;
00138         if (nbytes == -1) {
00139           syslog(LOG_ERR, "timed_recv: %m");
00140           continue;
00141         }
00142       }
00143       total_bytes += nbytes;
00144     }
00145     if (i == 0 && nbytes == -2)
00146       continue;
00147     if (strcmp(self->ip_addr, inet_ntoa(their_addr.sin_addr)) == 0)
00148       continue;
00149 
00150 #ifdef DEBUG_METRICS
00151     syslog(LOG_INFO, "echoing metrics measurement packets");
00152 #endif
00153     if (sendto(sd, &nbytes, sizeof(int), 0,
00154                (struct sockaddr*)&their_addr, addr_len) < 0)
00155       syslog(LOG_ERR, "sendto: %m");
00156   }
00157   return 0;
00158 }
00159 
00160 
00161 static void time_difference(struct timeval *ans, struct timeval *larger,
00162                             struct timeval *smaller)
00163 {
00164   ans->tv_sec = larger->tv_sec - smaller->tv_sec;
00165   ans->tv_usec = larger->tv_usec - smaller->tv_usec;
00166   if (ans->tv_usec < 0) {
00167     ans->tv_sec--;
00168     ans->tv_usec = 1000000 + ans->tv_usec;
00169   }
00170 }
00171 
00172 
00173 /* thread */
00174 int gather_statistics(self_t *self)
00175 {
00176   int sd, mtu = 1500;
00177   int error, yes = 1, ttl = 1;
00178   struct ifreq ifr;
00179   struct timeval now;
00180   struct sockaddr_in my_addr;
00181 
00182   gettimeofday(&now, NULL);
00183   srand(now.tv_usec);
00184 
00185   if ((sd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
00186     syslog(LOG_ERR, "socket: %m");
00187     return sd;
00188   }
00189 
00190   strcpy(ifr.ifr_name, self->interface);
00191   ifr.ifr_addr.sa_family = AF_INET;
00192   if (ioctl(sd, SIOCGIFMTU, &ifr) < 0)
00193     syslog(LOG_ERR, "net interface \"%s\" not found (%m)", self->interface);
00194   else
00195     mtu = ifr.ifr_mtu;
00196 
00197   if ((error = setsockopt(sd, SOL_SOCKET, SO_BROADCAST,
00198                           &yes, sizeof(int))) < 0) {
00199     syslog(LOG_ERR, "setsockopt (BROADCAST): %m");
00200     close(sd);
00201     return error;
00202   }
00203 
00204   if ((error = setsockopt(sd, IPPROTO_IP, IP_TTL, &ttl, sizeof(int))) < 0) {
00205     syslog(LOG_ERR, "setsockopt (IP_TTL): %m");
00206     close(sd);
00207     return error;
00208   }
00209 
00210   my_addr.sin_family = AF_INET;
00211   my_addr.sin_port = htons(MESH_METRICS_PORT);
00212   my_addr.sin_addr.s_addr = INADDR_ANY;
00213   memset(my_addr.sin_zero, 0, sizeof(my_addr.sin_zero));
00214 
00215   if ((error = bind(sd, (struct sockaddr*)&my_addr,
00216                     sizeof(struct sockaddr))) < 0) {
00217     syslog(LOG_ERR, "bind: %m");
00218     return error;
00219   }
00220 
00221   while (1) {
00222     struct timeval begin, middle, end, offset, elapsed;
00223     int i, nbytes = 0, bytes_sent = 0, bytes_thru = 0;
00224     double amps_begin = 0.0, amps_end = 0.0, seconds_passed;
00225     int rand_offset = (int) ((double)(MESH_METRICS_INTERVAL / 2) *
00226                              (rand() / (double)RAND_MAX));
00227     link_entry_t *entry;
00228     char packet[mtu];
00229     struct sockaddr_in their_addr;
00230     socklen_t addr_len = sizeof(struct sockaddr);
00231     protocol_t *proto = self->protocols;
00232 
00233     memset(&begin, 0, sizeof(struct timeval));
00234     memset(&middle, 0, sizeof(struct timeval));
00235     memset(&end, 0, sizeof(struct timeval));
00236     memset(&offset, 0, sizeof(struct timeval));
00237     memset(&elapsed, 0, sizeof(struct timeval));
00238 
00239     their_addr.sin_family = AF_INET;
00240     their_addr.sin_port = htons(MESH_METRICS_PORT+1);
00241     their_addr.sin_addr.s_addr = INADDR_ANY;
00242     memset(their_addr.sin_zero, 0, sizeof(their_addr.sin_zero));
00243 
00244 #ifdef DEBUG_METRICS
00245     syslog(LOG_INFO, "metrics interval: %d (%d)",
00246            MESH_METRICS_INTERVAL + rand_offset,
00247            (MESH_METRICS_INTERVAL / 2) - rand_offset);
00248 #endif
00249     sleep(MESH_METRICS_INTERVAL + rand_offset);
00250 
00251     while (proto != NULL) {
00252 #ifdef DEBUG_METRICS
00253       syslog(LOG_INFO, "sending metrics measurement packets");
00254 #endif
00255       gettimeofday(&begin, NULL);
00256       if (self->battery_enabled)
00257         amps_begin = get_discharge_rate(self);
00258       for (i = 0; i < MESH_METRICS_PACKETS; i++) {
00259         if ((nbytes = sendto(sd, packet, mtu, 0,
00260                              (struct sockaddr*)&their_addr, addr_len)) < 0) {
00261           syslog(LOG_ERR, "sendto: %m");
00262           continue;
00263         }
00264         bytes_sent += nbytes;
00265       }
00266       if (self->battery_enabled)
00267         amps_end = get_discharge_rate(self);
00268 
00269 #ifdef DEBUG_METRICS
00270       syslog(LOG_INFO, "recving metrics packet ACKs");
00271 #endif
00272       while (1) {
00273         if ((nbytes = timed_recv(sd, &bytes_thru, sizeof(int), &their_addr,
00274                                  MESH_METRICS_ROUND)) < 0) {
00275           if (nbytes == -2)
00276             break;
00277           if (nbytes == -1) {
00278             syslog(LOG_ERR, "timed_recv: %m");
00279             continue;
00280           }
00281         }
00282 
00283         gettimeofday(&middle, NULL);
00284         entry = retrieve_entry(proto,
00285                                ip_to_id(inet_ntoa(their_addr.sin_addr)));
00286         if (entry == NULL)
00287           continue;
00288 
00289         if (entry->metrics.reliability < 0.0)
00290           entry->metrics.reliability = (double)bytes_thru / (double)bytes_sent;
00291         else
00292           entry->metrics.reliability = (((double)bytes_thru / (double)bytes_sent)
00293                                         + entry->metrics.reliability) / 2;
00294         time_difference(&offset, &middle, &end);
00295         time_difference(&elapsed, &middle, &begin);
00296         time_difference(&elapsed, &elapsed, &offset);
00297         seconds_passed = (double) elapsed.tv_sec;
00298         seconds_passed += elapsed.tv_usec / 1000000.0;
00299         if (entry->metrics.goodput < 0.0)
00300           entry->metrics.goodput = (double)bytes_thru / seconds_passed;
00301         else
00302           entry->metrics.goodput = (((double)bytes_thru / seconds_passed)
00303                                     + entry->metrics.goodput) / 2;
00304         if (entry->metrics.energy < 0.0)
00305           entry->metrics.energy = amps_end - amps_begin;
00306         else
00307           entry->metrics.energy = (amps_end - amps_begin +
00308                                    entry->metrics.energy) / 2;
00309         gettimeofday(&end, NULL);
00310       }
00311       proto = proto->next;
00312     }
00313     sleep((MESH_METRICS_INTERVAL / 2) - rand_offset);
00314   }
00315   return 0;
00316 }


© 2007, Los Alamos National Security, LLC.