rerr.c

説明を見る。
00001 /*
00002                Kernel AODV  v2.1
00003 National Institute of Standards and Technology
00004                Luke Klein-Berndt
00005 -----------------------------------------------------
00006   Version 2.1 new features:
00007      * Much more stable!
00008      * Added locks around important areas
00009      * Multihop Internet gatewaying now works
00010      * Multicast hack added
00011      * Many bug fixes!
00012 -----------------------------------------------------
00013 
00014 Originally based upon MadHoc code. I am not
00015 sure how much of it is left anymore, but MadHoc
00016 proved to be a great starting point.
00017 
00018 MadHoc was written by - Fredrik Lilieblad,
00019 Oskar Mattsson, Petra Nylund, Dan Ouchterlony
00020 and Anders Roxenhag Mail: mad-hoc@flyinglinux.net
00021 
00022 This software is Open Source under the GNU General Public Licence.
00023 
00024 */
00025 
00026 #include "rerr.h"
00027 
00028 /****************************************************
00029 
00030    rerr
00031 ----------------------------------------------------
00032 Handles the generation of RERR messages
00033 ****************************************************/
00034 
00035 
00036 extern u_int32_t g_broadcast_ip;
00037 extern u_int32_t g_my_ip;
00038 
00039 
00040 
00041 void free_rerrhdr(struct rerrhdr *tmp_rerrhdr);
00042 
00043 int send_rerr(struct rerrhdr *tmp_rerrhdr, u_int32_t sent_to);
00044 
00045 /****************************************************
00046 
00047    link_break
00048 ----------------------------------------------------
00049 link_break is called when a broken link to a neighbouring
00050 is detected. All active routes that have the unreachable node as next
00051 hop are invalidated. All precursors for this entry are removed. The
00052 RERR meassage including the unreachable destinations and their
00053  incremented seq numbers is finally rebroadcast.
00054 
00055 ****************************************************/
00056 
00057 int link_break( u_int32_t brk_dst_ip)
00058 {
00059     struct route_table_entry *tmp_entry;
00060     struct rerrhdr *new_rerrhdr = NULL;
00061     struct precursor_entry *tmp_precursor;
00062     struct precursor_entry *dead_precursor;
00063 
00064 
00065     u_int32_t last_precursor;
00066     u_int8_t precursor_num=0;
00067 
00068 
00069     int rerrhdr_created = 0;
00070 
00071     // remove the borken link from all the route table entries
00072     delete_precursor_entry_from_route_table(brk_dst_ip);
00073 
00074 
00075     tmp_entry=get_first_route_table_entry();
00076 
00077     //go through list
00078     while(tmp_entry != NULL)
00079     {
00080         //if the route has the broken IP for the next hop and is active
00081         if((tmp_entry->next_hop == brk_dst_ip) && (tmp_entry->route_valid))
00082         {
00083 
00084 
00085             printk(KERN_INFO "RERR: Broken link as next hop for - %s \n",inet_ntoa(tmp_entry->dst_ip));
00086 
00087             //expire the route
00088             route_expiry(tmp_entry);
00089 
00090             if(tmp_entry->precursors!=NULL)
00091               {
00092                 //if the rerr header has not been created yet
00093                 if(!rerrhdr_created)
00094                   {
00095                     if((new_rerrhdr =create_rerrhdr(tmp_entry->dst_ip,tmp_entry->dst_seq)) == NULL)
00096                       return 1;
00097                     rerrhdr_created = 1;
00098                   }
00099                 else
00100                   {
00101                     append_unr_dst(new_rerrhdr, tmp_entry->dst_ip, tmp_entry->dst_seq);
00102                   }
00103               }
00104 
00105             //remove all the precursors from the route
00106             tmp_precursor=tmp_entry->precursors;
00107 
00108             while (tmp_precursor!=NULL)
00109             {
00110                 last_precursor=tmp_precursor->ip;
00111                 dead_precursor=tmp_precursor;
00112                 tmp_precursor=tmp_precursor->next;
00113                 kfree(dead_precursor);
00114             }
00115             tmp_entry->precursors=NULL;
00116 
00117             
00118 
00119         }
00120 
00121         //move on to the next entry
00122         tmp_entry = tmp_entry->next;
00123     }
00124 
00125 
00126 
00127     //if there was a RERR created, send it out
00128     if(rerrhdr_created)
00129     {
00130         if (precursor_num==1)
00131             send_rerr(new_rerrhdr,last_precursor);
00132         else
00133             send_rerr(new_rerrhdr,g_broadcast_ip);
00134 
00135         free_rerrhdr(new_rerrhdr);
00136     }
00137 
00138     return 0;
00139 }
00140 
00141 
00142 
00143 /****************************************************
00144 
00145    route_expiry
00146 ----------------------------------------------------
00147  route_expiry invalidates an active route, i e an entry
00148  in the routing table.
00149 ****************************************************/
00150 
00151 void route_expiry(struct route_table_entry *tmp_entry)
00152 {
00153     //marks a route as expired
00154 
00155 
00156     tmp_entry->lifetime = (getcurrtime() + DELETE_PERIOD);
00157     tmp_entry->dst_seq++;
00158     tmp_entry->route_valid=FALSE;
00159     delete_kernel_route_entry(tmp_entry->dst_ip, tmp_entry->next_hop);
00160 }
00161 
00162 
00163 
00164 /****************************************************
00165 
00166    host_unr
00167 ----------------------------------------------------
00168 host_unr is called when a packet is received destined for a node
00169 which the forwarding node does not have an active route to. A RERR
00170 message is created to inform neighbours.
00171 ****************************************************/
00172 int  host_unr(u_int32_t brk_dst_ip)
00173 {
00174     struct rerrhdr *new_rerrhdr = NULL;
00175     struct route_table_entry *tmp_entry;
00176 
00177     tmp_entry = find_route_table_entry(brk_dst_ip);
00178 
00179     if((new_rerrhdr = create_rerrhdr(brk_dst_ip, 1)) == NULL)
00180         return -ENOMEM;
00181 
00182     send_rerr(new_rerrhdr,g_broadcast_ip);
00183     free_rerrhdr(new_rerrhdr);
00184 
00185     return 0;
00186 }
00187 
00188 
00189 /****************************************************
00190 
00191    rec_rerr
00192 ----------------------------------------------------
00193 rec_rerr is called when the node receives a RERR packet from
00194 another node. If the precursor list for a broken destinations is
00195 not empty a new RERR is created for that destination.
00196 ****************************************************/
00197 
00198 int recv_rerr(struct event_queue_entry *working_packet)
00199 {
00200     struct rerr *tmp_hdr;
00201     struct rerrhdr *new_rerrhdr = NULL;
00202     struct rerrdst *tmp_dst;
00203     struct route_table_entry *tmp_route;
00204     struct interface_list_entry *tmp_interface;
00205 
00206     int new_rerr_created = 0;
00207     int i;
00208 
00209     tmp_interface=find_interface_by_dev(working_packet->dev);
00210     if (tmp_interface==NULL)
00211       {
00212         printk(KERN_WARNING "AODV: Recieved RERR on an unknown device!\n");
00213         return -ENODEV;
00214       }
00215 
00216     tmp_hdr =(struct rerr *) ((char *) working_packet->data);
00217     tmp_dst = (struct rerrdst *) ((char *) tmp_hdr + sizeof (struct rerr));
00218 
00219 
00220     printk(KERN_INFO "AODV: recieved a route error from %s, count= %u\n",inet_ntoa(working_packet->src_ip),tmp_hdr->dst_count);
00221 
00222 
00223     for(i = 0; i < tmp_hdr->dst_count; i++)
00224     {
00225         //go through all the unr dst in the rerr
00226 
00227         printk(KERN_INFO "       -> %s",inet_ntoa(tmp_dst->unr_dst_ip));
00228 
00229 
00230         tmp_route = find_route_table_entry(tmp_dst->unr_dst_ip);
00231 
00232         //Is the sender of the rerr the next hop for a broken destination for the current node?
00233         if(tmp_route != NULL)
00234         {
00235 
00236             if( !tmp_route->self_route )
00237             {
00238 
00239                 if (tmp_route->next_hop == working_packet->src_ip)
00240                 {
00241 
00242                     printk(KERN_INFO " Removing route");
00243 
00244 
00245                     tmp_route->dst_seq = ntohl(tmp_dst->unr_dst_seq);
00246                     tmp_route->route_valid=FALSE;
00247                     tmp_route->lifetime = (getcurrtime() + DELETE_PERIOD);
00248                     delete_kernel_route_entry(tmp_route->dst_ip, tmp_route->next_hop);
00249 
00250                     if(tmp_route->precursors != NULL)
00251                     {
00252                         // precursors exist
00253                         if(!new_rerr_created)
00254                         {
00255                             new_rerr_created = 1;
00256                             new_rerrhdr = create_rerrhdr(tmp_dst->unr_dst_ip,ntohl( tmp_dst->unr_dst_seq));
00257 
00258                         }
00259                         else
00260                         {
00261                             append_unr_dst(new_rerrhdr, tmp_dst->unr_dst_ip,  ntohl(tmp_dst->unr_dst_seq));
00262 
00263                         }
00264                     }
00265                 }
00266             }
00267 
00268         }
00269 
00270         printk(KERN_INFO" \n");
00271 
00272         tmp_dst =(struct rerrdst *) ((char *) tmp_dst + sizeof (struct rerrdst));
00273 
00274 
00275 
00276     }
00277 
00278     if(new_rerr_created)
00279     {
00280         send_rerr(new_rerrhdr,g_broadcast_ip);
00281         free_rerrhdr(new_rerrhdr);
00282     }
00283 
00284     return 0;
00285 }
00286 
00287 
00288 /****************************************************
00289 
00290    create_rerrhdr
00291 ----------------------------------------------------
00292 create_rerrhdr is used to create a new RERR message
00293 ****************************************************/
00294 
00295 struct rerrhdr* create_rerrhdr(u_int32_t tmp_ip, u_int32_t tmp_dst_seq)
00296 {
00297     struct rerr_unr_dst *tmp_rerr_unr_dst;
00298     struct rerrhdr *tmp_rerrhdr;
00299 
00300     //create header
00301     if((tmp_rerrhdr = kmalloc(sizeof(struct rerrhdr),GFP_ATOMIC)) == NULL)
00302     {
00303 
00304         printk(KERN_WARNING "AODV: Error creating tmp_rerrhdr \n");
00305 
00306         return NULL;
00307     }
00308     
00309     //create spot for first entry
00310     if((tmp_rerr_unr_dst = kmalloc(sizeof(struct rerr_unr_dst),GFP_ATOMIC)) == NULL)
00311     {
00312       kfree(tmp_rerrhdr);
00313       printk(KERN_WARNING "AODV: Error creating temp_rerr_unr_dst\n");
00314 
00315       return NULL;
00316     }
00317 
00318 
00319     //fill in info for first entry
00320     tmp_rerr_unr_dst->unr_dst_ip = tmp_ip;
00321     tmp_rerr_unr_dst->unr_dst_seq = tmp_dst_seq;
00322     tmp_rerr_unr_dst->next = NULL;
00323 
00324     //fill in info for header
00325     tmp_rerrhdr->unr_dst = tmp_rerr_unr_dst;
00326     tmp_rerrhdr->type = 3;
00327     tmp_rerrhdr->dst_count = 1;
00328 
00329     return tmp_rerrhdr;
00330 }
00331 
00332 
00333 /****************************************************
00334 
00335    append_unr_dst
00336 ----------------------------------------------------
00337 append_unr_dst adds an unreachable node to the previously
00338 created RERR message.
00339 ****************************************************/
00340 
00341 int append_unr_dst(struct rerrhdr *tmp_rerrhdr, u_int32_t tmp_ip,u_int32_t tmp_dst_seq)
00342 {
00343     struct rerr_unr_dst *tmp_rerr_unr_dst;
00344 
00345     //get memory for new entry
00346     if((tmp_rerr_unr_dst = kmalloc(sizeof(struct rerr_unr_dst),GFP_ATOMIC)) == NULL)
00347     {
00348         printk(KERN_WARNING "AODV: Error appending new unr_dst\n");
00349         return -ENOMEM;
00350     }
00351 
00352 
00353 
00354     //fill in info for entry
00355     tmp_rerr_unr_dst->next = tmp_rerrhdr->unr_dst;
00356     tmp_rerrhdr->unr_dst = tmp_rerr_unr_dst;
00357     tmp_rerrhdr->dst_count++;
00358     tmp_rerr_unr_dst->unr_dst_ip = tmp_ip;
00359     tmp_rerr_unr_dst->unr_dst_seq = tmp_dst_seq;
00360 
00361     return 0;
00362 }
00363 
00364 /****************************************************
00365 
00366    free_rerrhdr
00367 ----------------------------------------------------
00368  free_rerrhdr frees the allocated memory for the rerrhdr
00369  list structure.
00370 ****************************************************/
00371 void free_rerrhdr(struct rerrhdr *tmp_rerrhdr)
00372 {
00373     struct rerr_unr_dst *tmp_unr_dst;
00374     struct rerr_unr_dst *dead_dst;
00375 
00376     //for all the unreachable destinataion in the rerr
00377     tmp_unr_dst=tmp_rerrhdr->unr_dst;
00378 
00379     while (tmp_unr_dst!=NULL)
00380     {
00381         dead_dst=tmp_unr_dst;
00382 
00383         tmp_unr_dst = tmp_unr_dst->next;
00384         kfree(dead_dst); //Bug Fix thanks to Soyeon Ahn!
00385     }
00386 
00387     kfree(tmp_rerrhdr);
00388 }
00389 
00390 
00391 
00392 /****************************************************
00393 
00394    send_rerr
00395 ----------------------------------------------------
00396  send_rerr copies the incoming RERR message to a connected
00397  data area, which is a suitable format for the function send_datagram.
00398 ****************************************************/
00399 int send_rerr(struct rerrhdr *tmp_rerrhdr, u_int32_t sent_to)
00400 {
00401     struct rerr *out_hdr;
00402     struct rerrdst *out_dst;
00403     struct rerr_unr_dst *tmp_dst;
00404     void *data;
00405 
00406     int datalen, i;
00407 
00408     datalen = sizeof(struct rerr) + sizeof(struct rerrdst) * (tmp_rerrhdr->dst_count);
00409     //get the needed memory
00410     if((data = kmalloc(datalen,GFP_ATOMIC)) == NULL)
00411     {
00412 
00413         printk(KERN_WARNING"AODV: Error creating packet to send RERR\n");
00414 
00415         return -ENOMEM;
00416     }
00417 
00418 
00419     out_hdr =(struct rerr *) ((char *) data);
00420     out_hdr->type = 3;
00421     out_hdr->dst_count = tmp_rerrhdr->dst_count;
00422     out_hdr->reserved =0;
00423 
00424     out_dst=(struct rerrdst *) ((char *) out_hdr + sizeof(struct rerr));
00425     tmp_dst = tmp_rerrhdr->unr_dst;
00426 
00427     for(i = 0; i < tmp_rerrhdr->dst_count; i++)
00428     {
00429         out_dst->unr_dst_ip=tmp_dst->unr_dst_ip;
00430 
00431         printk(KERN_INFO "AODV: adding... %s to RERR\n",inet_ntoa(out_dst->unr_dst_ip));
00432 
00433 
00434         //convert it to network byte order
00435         out_dst->unr_dst_seq=htonl(tmp_dst->unr_dst_seq);
00436         out_dst =(struct rerrdst *) ((char *) out_dst + sizeof(struct rerrdst));
00437         tmp_dst = tmp_dst->next;
00438     }
00439 
00440     if (sent_to==g_broadcast_ip)
00441         local_broadcast(NET_DIAMETER, data, datalen);
00442     else
00443         send_message(sent_to,NET_DIAMETER, data, datalen);
00444 
00445     kfree(data);
00446     return 0;
00447 }
00448 
00449 /*
00450  * print_rerrhdr
00451  *
00452  * Description:
00453  *   print_rerrhdr prints a RERR message
00454  *
00455  * Arguments:
00456  *   struct rerrhdr *new_rerrhdr - Pointer to the rerrhdr
00457  *
00458  * Returns: void
00459  */
00460 
00461 void print_rerrhdr(struct rerrhdr *new_rerrhdr)
00462 {
00463     struct rerr_unr_dst *tmp_rerr_unr_dst;
00464     struct in_addr tmp_in_addr;
00465     int i;
00466 
00467     printk(KERN_INFO "Outgoing RERR message: type: %d dst_cnt: %d\n",
00468            new_rerrhdr->type, new_rerrhdr->dst_count);
00469 
00470     for(i = 0, tmp_rerr_unr_dst = new_rerrhdr->unr_dst;
00471             i < new_rerrhdr->dst_count;
00472             i++, tmp_rerr_unr_dst = tmp_rerr_unr_dst->next)
00473     {
00474         tmp_in_addr.s_addr = tmp_rerr_unr_dst->unr_dst_ip;
00475         printk(KERN_INFO "unr_dst_ip: %s unr_dst_seq %d\n",
00476                inet_ntoa(tmp_in_addr.s_addr),
00477                tmp_rerr_unr_dst->unr_dst_seq);
00478     }
00479 }
00480 
00481 
00482 
00483 
00484 
00485 
00486 
00487 
00488 
00489 
00490 
00491 

kernel_aodvmに対してThu Nov 10 18:53:11 2005に生成されました。  doxygen 1.4.5