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_strength.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 <netdb.h>
00037 #include <syslog.h>
00038 
00039 #include "mesh_strength.h"
00040 
00041 
00042 enum metric_index { min_signal = 0, };
00043 
00044 
00045 void strength_on_demand_discovery(protocol_t *proto, u_int32_t dest)
00046 {
00047   // FIXME: implement on_demand
00048 }
00049 
00050 
00051 int strength_send_mesh_discovery(protocol_t *proto, int sd, int flags)
00052 {
00053   int error, i = 0;
00054   link_entry_t *entry, *dbentry;
00055   struct sockaddr_in their_addr;
00056   struct hostent *he;
00057   char link_string[MESH_LINK_STRLEN];
00058   char their_addr_string[NET_ADDR_LEN];
00059   unsigned int num_links;
00060   database_t *db;
00061 
00062   if (proto == NULL) {
00063     errno = EINVAL;
00064     return -1;
00065   }
00066 
00067   /* unload kernel routing table */
00068   while ((dbentry = iterate_entries(proto)) != NULL)
00069     remove_kernel_route(dbentry);
00070   empty_entries(proto);
00071 
00072   if (flags == MESH_REDISCOVER) {
00073     num_links = 1;
00074     db = new_database(proto, 1);
00075     entry = new_link_entry(proto);
00076     entry->link.rediscover++;
00077     link_to_string(&entry->link, link_string);
00078     memcpy(&db->links, &entry->link, sizeof(link_t));
00079 
00080 #ifdef DEBUG_DISCOVERY
00081     syslog(LOG_INFO, "(re)discover %s", proto->sensor->broadcast);
00082 #endif
00083   } else {
00084     if (proto->db_altered == 0)
00085       return 0;
00086 
00087     num_links = num_entries(proto) + 1;
00088     db = new_database(proto, num_links);
00089 
00090 #ifdef DEBUG_DISCOVERY
00091     syslog(LOG_INFO, "broadcast database (%d links)", num_links);
00092 #endif
00093 
00094     while ((dbentry = iterate_entries(proto)) != NULL) {
00095 #ifdef DEBUG_DISCOVERY
00096       char string[MESH_LINK_STRLEN];
00097       link_to_string(&dbentry->link, string);
00098       syslog(LOG_INFO, " #%d - %d : %s", i+1, dbentry->node_id, string);
00099 #endif
00100       dbentry->link.rediscover = 0;
00101       memcpy(&db->links[i++], &dbentry->link, sizeof(link_t));
00102 
00103       /* add to kernel routing table */
00104       add_kernel_route(dbentry);
00105     }
00106     entry = new_link_entry(proto);
00107     memcpy(&db->links[i], &entry->link, sizeof(link_t));
00108 
00109     proto->db_altered = 0;
00110   }
00111 
00112   if ((he = gethostbyname(proto->sensor->broadcast)) == NULL) {
00113     syslog(LOG_ERR, "gethostbyname(%s): %s",
00114            proto->sensor->broadcast, hstrerror(h_errno));
00115     return -1;
00116   }
00117   their_addr.sin_family = AF_INET;
00118   their_addr.sin_port = htons(MESH_DISCOVERY_PORT);
00119   their_addr.sin_addr = *((struct in_addr*)he->h_addr);
00120   memset(&(their_addr.sin_zero), 0, sizeof(their_addr.sin_zero));
00121   strcpy(their_addr_string, ip_to_dot(their_addr.sin_addr.s_addr));
00122 
00123 #ifdef DEBUG_DISCOVERY
00124   syslog(LOG_INFO, "sending %d links:", num_links);
00125   for (i = 0; i < num_links; i++) {
00126     char link_string[MESH_LINK_STRLEN];
00127     link_to_string(&db->links[i], link_string);
00128     syslog(LOG_INFO, "    %s", link_string);
00129   }
00130 #endif
00131 
00132   if ((error = send_routes(proto->sensor, sd, db, num_links,
00133                            &their_addr)) < 0) {
00134     syslog(LOG_ERR, "rediscover send_routes %s: %m", their_addr_string);
00135     return error;
00136   }
00137 
00138 #ifdef DEBUG_DISCOVERY
00139   syslog(LOG_INFO, "sent \"%s\"", link_string);
00140 #endif
00141   free(db);
00142   free(entry);
00143   return 0;
00144 }
00145 
00146 
00147 int strength_recv_mesh_discovery(protocol_t *proto, int sd, int num_links)
00148 {
00149   int bytes, i, signal_str = INT_MAX, noise_lvl = 0;
00150   database_t *db = malloc(database_size(num_links));
00151   link_t *links;
00152   struct sockaddr_in their_addr;
00153   struct in_addr *from;
00154   struct msghdr msg_header;
00155   struct cmsghdr *control;
00156   size_t ctl_msg_size = CMSG_SPACE(sizeof(struct in_pktinfo));
00157 
00158   if (proto == NULL) {
00159     errno = EINVAL;
00160     return -1;
00161   }
00162 
00163   if ((bytes = receive_routes(sd, db, num_links, &their_addr,
00164                               &msg_header, ctl_msg_size)) < 0) {
00165     syslog(LOG_ERR, "receive_routes: %m");
00166     return bytes;
00167   }
00168   for (control = CMSG_FIRSTHDR(&msg_header); control != NULL;
00169        control = CMSG_NXTHDR(&msg_header, control)) {
00170     if (control->cmsg_level == SOL_IP && 
00171         control->cmsg_type == IP_PKTINFO) {
00172       struct in_pktinfo *packet_info =
00173         (struct in_pktinfo*)CMSG_DATA(control);
00174       signal_str = min(signal_str, packet_info->signal);
00175       noise_lvl = max(noise_lvl, packet_info->noise);
00176       break;
00177     }
00178   }
00179 
00180   from = &their_addr.sin_addr;
00181   if (strcmp(proto->sensor->ip_addr,
00182              ip_to_dot(their_addr.sin_addr.s_addr)) == 0)
00183     return 0;  /* ignore my own messages */
00184 
00185   // TODO: monitor noise_lvl, send JAM_ALERT to neighbors upon increase
00186 
00187   links = db->links;
00188 #ifdef DEBUG_DISCOVERY
00189   syslog(LOG_INFO, "recvd %d links: (from %s, rss: %d)", num_links,
00190          ip_to_dot(their_addr.sin_addr.s_addr), signal_str);
00191   for (i = 0; i < num_links; i++) {
00192     char string[MESH_LINK_STRLEN];
00193     link_to_string(&links[i], string);
00194     syslog(LOG_INFO, "    %s", string);
00195   }
00196 #endif
00197 
00198   if (links[0].rediscover != 0) {
00199     link_entry_t *dbentry;
00200 #ifdef DEBUG_DISCOVERY
00201     syslog(LOG_INFO, "rediscover initiated");
00202 #endif
00203     /* unload kernel routing table */
00204     while ((dbentry = iterate_entries(proto)) != NULL)
00205       remove_kernel_route(dbentry);
00206     empty_entries(proto);
00207     links[0].rediscover = 0;
00208   }
00209 
00210   for (i = 0; i < num_links; i++) {
00211     link_entry_t *entry, *db_link;
00212 
00213     entry = new_link_entry(proto);
00214     memcpy(&entry->link, &links[i], sizeof(link_t));
00215     entry->node_id = entry->link.node.s_addr;
00216     entry->link.metrics[min_signal] = INT_MAX;
00217 
00218     if (strcmp(ip_to_dot(entry->link.node.s_addr),
00219                proto->sensor->ip_addr) == 0)
00220       return 0;  /* ignore routes to myself */
00221 
00222     entry->link.hop_count++;
00223     /* can't be better than strength of last hop */
00224     entry->link.metrics[min_signal] = min(entry->link.metrics[min_signal],
00225                                           signal_str);
00226 
00227     db_link = retrieve_entry(proto, entry->node_id);
00228     /* this is our key metric: maximize the minimum signal strength,
00229      *  in case of equal strength signals, prefer fewer hops
00230      */
00231     if (db_link != NULL) {
00232 #ifdef DEBUG_DISCOVERY
00233       char string[MESH_LINK_STRLEN];
00234       link_to_string(&db_link->link, string);
00235       syslog(LOG_INFO, "update link %s", string);
00236 #endif
00237 
00238       if (db_link->link.metrics[min_signal] > entry->link.metrics[min_signal] ||
00239           (db_link->link.metrics[min_signal] == entry->link.metrics[min_signal] &&
00240            db_link->link.hop_count > entry->link.hop_count)) {
00241         if (memcmp(&db_link->link.next_hop, from, sizeof(from)) != 0)
00242           proto->db_altered++;
00243         /* only interested in route updates, not signal updates */
00244 
00245         db_link->link.metrics[min_signal] = entry->link.metrics[min_signal];
00246         db_link->link.hop_count = entry->link.hop_count;
00247         memcpy(&db_link->link.next_hop, from, sizeof(from));
00248       }
00249       free(entry);
00250     } else {
00251 #ifdef DEBUG_DISCOVERY
00252       char string[MESH_LINK_STRLEN];
00253       link_to_string(&entry->link, string);
00254       syslog(LOG_INFO, "add link %s", string);
00255 #endif
00256       add_entry(proto, entry->node_id, entry);
00257       proto->db_altered++;
00258     }
00259   }
00260 
00261   free(db);
00262   return 0;
00263 }


© 2007, Los Alamos National Security, LLC.