Main Page | Directories | File List | Globals

arp_core.c

Go to the documentation of this file.
00001 /*
00002  * kernel_net/layer_2/arp/arp_core.c
00003  *
00004  * Copyright (c) 2003-2005 Lukasz Dembinski <dembol@nasa.com.pl>
00005  * All Rights Reserved
00006  * 
00007  * Date:        2005/06
00008  * Author:      Lukasz Dembinski
00009  * Info:        arp_core.c core file
00010  * Contact:     mailto: <dembol@nasa.com.pl>
00011  *
00012  */
00013 
00014 #include <agnix/agnix.h>
00015 #include <agnix/adi/adi.h>
00016 #include <agnix/net/net.h>
00017 #include <agnix/memory.h>
00018 #include <agnix/console.h>
00019 #include <agnix/resources.h>
00020 #include <agnix/timers.h>
00021 #include <agnix/counters.h>
00022 #include <agnix/list.h>
00023 #include <agnix/wait.h>
00024 #include <agnix/sched.h>
00025 #include <agnix/spinlock.h>
00026 #include <agnix/data_structures.h>
00027 
00028 #define MOD_NAME        "ARP: "
00029 
00030 struct arp_entry_s arp_entries[ARP_MAX_ENTRIES];
00031 u32 arp_bitmap[ARP_BITMAP_LEN];
00032 
00033 struct list_head arp_entries_list;
00034 struct list_head arp_requests_list;
00035 spinlock_t arp_entries_list_lock;
00036 spinlock_t arp_requests_list_lock;
00037 
00038 int arp_hash_desc;
00039 int arp_resource_desc;
00040 int arp_cache;
00041 
00042 void arp_timer_expire(void *data);
00043 int arp_del_entry_lock(struct arp_entry_s *entry);
00044 
00045 struct resource_s arp_resource = {
00046     .resource_name      = "arp",
00047     .resource_bitmap    = arp_bitmap,
00048     .resource_len       = ARP_BITMAP_LEN
00049 };
00050 
00051 struct timer_s arp_timer = {
00052     .timer_function     = arp_timer_expire,
00053     .timer_data         = NULL,
00054     .timer_expire       = 0,
00055     .timer_flags        = TIMER_FLAG_ONESHOT,
00056 };
00057 
00058 struct arp_stats_s arp_stats;
00059 
00060 extern int counter_jiffies_desc;
00061 extern struct list_head adi_netdev_list;
00062 extern spinlock_t adi_netdev_list_lock;
00063 
00064 int arp_reply(struct adi_netdev_s *netdev, struct arp_neigh_s *neigh_src, struct arp_neigh_s *neigh_dest,
00065               u8 *mac_dest);
00066 
00067 int get_free_arp_entry(void)
00068 {
00069     return get_free_resource(arp_resource_desc);
00070 }
00071 
00072 int put_free_arp_entry(int arp_entry_desc)
00073 {
00074     return put_free_resource(arp_resource_desc, arp_entry_desc);
00075 }
00076 
00077 int arp_request_add_lock(struct arp_request_s *arp_request)
00078 {
00079     list_add_tail(&(arp_request->list), &arp_requests_list);
00080     return 0;
00081 }
00082 
00083 int arp_request_add(struct arp_request_s *arp_request)
00084 {
00085     u32 flags;
00086 
00087     spin_lock_irqsave(&arp_requests_list_lock, flags);
00088     arp_request_add_lock(arp_request);
00089     spin_unlock_irqrestore(&arp_requests_list_lock, flags);
00090     
00091     return 0;
00092 }
00093 
00094 int arp_request_del_lock(struct arp_request_s *arp_request)
00095 {
00096     list_del(&(arp_request->list));
00097     return 0;
00098 }
00099 
00100 int arp_request_del(struct arp_request_s *arp_request)
00101 {
00102     u32 flags;
00103 
00104     spin_lock_irqsave(&arp_requests_list_lock, flags);
00105     arp_request_del_lock(arp_request);
00106     spin_unlock_irqrestore(&arp_requests_list_lock, flags);
00107     
00108     return 0;
00109 }
00110 
00111 int arp_request_wake_up(struct arp_neigh_s *neigh)
00112 {
00113     struct arp_request_s *arp_request;
00114     struct list_head *tmp;
00115     u32 flags;
00116 
00117     spin_lock_irqsave(&arp_requests_list_lock, flags);        
00118 
00119     if (list_empty(&arp_requests_list)) {
00120         spin_unlock_irqrestore(&arp_requests_list_lock, flags);    
00121         return 0;
00122     }
00123     
00124     list_for_each(tmp, &arp_requests_list) {
00125         arp_request = list_entry(tmp, struct arp_request_s, list);
00126 
00127         if (!memcmp(arp_request->neigh->addr.address, neigh->addr.address, neigh->addr.address_len)) {
00128             sched_activate_task(arp_request->task);
00129         }
00130     }
00131 
00132     spin_unlock_irqrestore(&arp_requests_list_lock, flags);    
00133     
00134     return 0;
00135 }
00136 
00137 int arp_timer_refresh_lock(void)
00138 {
00139     struct arp_entry_s *arp_entry;
00140 
00141     if (arp_timer.timer_expire != 0) {
00142         arp_timer.timer_expire = 0;
00143         unregister_timer(&arp_timer);
00144     }
00145     
00146     if (list_empty(&arp_entries_list))
00147         return 1;
00148 
00149     arp_entry = list_entry(arp_entries_list.prev, struct arp_entry_s, list);    
00150 
00151     arp_timer.timer_flags  = TIMER_FLAG_ONESHOT;
00152     arp_timer.timer_expire = ARP_EXPIRE;
00153     arp_timer.timer_data   = (void *)arp_entry;
00154     register_timer(&arp_timer);
00155 
00156     return 0;
00157 }
00158 
00159 int arp_timer_refresh(void)
00160 {
00161     int ret;
00162     u32 flags;
00163 
00164     spin_lock_irqsave(&arp_entries_list_lock, flags);        
00165     ret = arp_timer_refresh_lock();
00166     spin_unlock_irqrestore(&arp_entries_list_lock, flags);    
00167     
00168     return ret;
00169 }
00170 
00171 void arp_timer_expire(void *data)
00172 {
00173     struct arp_entry_s *arp_entry;
00174     struct arp_entry_s *arp_entry_list;
00175     struct list_head *tmp, *n;
00176     u32 flags;
00177 
00178     spin_lock_irqsave(&arp_entries_list_lock, flags);    
00179 
00180     arp_entry = (struct arp_entry_s *)data;
00181     list_for_each_safe(tmp, n, &arp_entries_list) {
00182         arp_entry_list = list_entry(tmp, struct arp_entry_s, list);        
00183         if (arp_entry_list->timer == arp_entry->timer) {
00184             arp_del_entry_lock(arp_entry_list);
00185         }
00186     }
00187     arp_timer_refresh_lock();
00188 
00189     spin_unlock_irqrestore(&arp_entries_list_lock, flags);    
00190 }
00191 
00192 void arp_cache_set(int on)
00193 {
00194     arp_cache = on;
00195 }
00196 
00197 struct arp_entry_s *arp_get_entry_lock(struct net_addr_s *addr)
00198 {
00199     struct arp_entry_s *arp_entry;
00200     u32 ptr;
00201 
00202     arp_entry = NULL;
00203     if ((ptr = hash_entry_find(arp_hash_desc, *(u32 *)addr->address))) {
00204         arp_entry = (struct arp_entry_s *)ptr;
00205     }
00206     
00207     return arp_entry;
00208 }
00209 
00210 int arp_get_local_mac(struct arp_neigh_s *neigh)
00211 {
00212     struct list_head *tmp;
00213     struct adi_netdev_s *netdev;
00214     int found;
00215     u32 flags;
00216     
00217     spin_lock_irqsave(&adi_netdev_list_lock, flags);
00218     
00219     found = 0;
00220     list_for_each(tmp, &adi_netdev_list) {
00221         netdev = list_entry(tmp, struct adi_netdev_s, list);
00222 
00223         if (!memcmp(netdev->if_layer_3.if_addr.address, neigh->addr.address, neigh->addr.address_len)) {
00224             found = 1;
00225             break;
00226         }
00227     }
00228     
00229     spin_unlock_irqrestore(&adi_netdev_list_lock, flags);
00230     
00231     if (found) {
00232         memcpy(neigh->mac, netdev->if_layer_2.if_addr, ETH_ALEN);
00233         return 1;
00234     }
00235     
00236     return 0;
00237 }
00238 
00239 int arp_get_neigh_lock(struct arp_neigh_s *neigh)
00240 {
00241     struct arp_entry_s *arp_entry;
00242 
00243     if ((arp_entry = arp_get_entry_lock(&neigh->addr)) != NULL) {
00244 
00245         memcpy(neigh->mac, arp_entry->neigh->mac, ETH_ALEN);
00246         return 1;       
00247     }
00248     
00249     return 0;
00250 }
00251 
00252 int arp_get_neigh(struct arp_neigh_s *neigh)
00253 {
00254     int ret;
00255     u32 flags;
00256     
00257     spin_lock_irqsave(&arp_entries_list_lock, flags);
00258     ret = arp_get_neigh_lock(neigh);    
00259     spin_unlock_irqrestore(&arp_entries_list_lock, flags);
00260     
00261     return ret;
00262 }
00263 
00264 struct arp_neigh_s *arp_neigh_clone(struct arp_neigh_s *neigh)
00265 {
00266     struct arp_neigh_s *neigh_cloned;
00267     
00268     /* yes, slab allocator is required, I know */
00269     neigh_cloned = (struct arp_neigh_s *)get_free_pages(0);
00270     memcpy(neigh_cloned, neigh, sizeof(struct arp_neigh_s));
00271     
00272     return neigh_cloned;
00273 }
00274 
00275 int arp_add_neigh_lock(struct arp_neigh_s *neigh)
00276 {
00277     u32 arp_entry_idx;
00278     struct arp_entry_s *arp_entry;
00279     struct arp_neigh_s *neigh_cloned;
00280 
00281     neigh_cloned     = arp_neigh_clone(neigh);
00282     arp_entry_idx    = get_free_arp_entry();
00283     arp_entry        = (struct arp_entry_s *)&arp_entries[arp_entry_idx];
00284     arp_entry->neigh = neigh_cloned;
00285     arp_entry->idx   = arp_entry_idx;
00286     hash_entry_add(arp_hash_desc, *(u32 *)neigh->addr.address, (u32)arp_entry);
00287     arp_entry->timer = ARP_EXPIRE;
00288     
00289     list_add_tail(&arp_entry->list, &arp_entries_list);
00290     arp_timer_refresh_lock();
00291     
00292     return 0;
00293 }
00294 
00295 int arp_del_entry_lock(struct arp_entry_s *arp_entry)
00296 {
00297     int ret;
00298 
00299     ret = hash_entry_del(arp_hash_desc, *(u32 *)arp_entry->neigh->addr.address);
00300     list_del(&arp_entry->list);
00301     put_free_arp_entry(arp_entry->idx);
00302     put_free_pages((u32)arp_entry->neigh, 0);
00303     memset(arp_entry, 0, sizeof(struct arp_entry_s));
00304     
00305     return 0;
00306 }
00307 
00308 int arp_header_build(struct frb_s *frb, u16 ar_hrd, u16 ar_pro, u8 ar_hln, u8 ar_pln,
00309                      u16 ar_op, u8 *ar_sha, u8 *ar_sip, u8 *ar_tha, u8 *ar_tip)
00310 {
00311     struct arp_hdr_s *arphdr = (struct arp_hdr_s *)frb_pop(frb, sizeof(struct arp_hdr_s));
00312 
00313     arphdr->ar_hrd = htons(ar_hrd);
00314     arphdr->ar_pro = htons(ar_pro);
00315     arphdr->ar_hln = ar_hln;
00316     arphdr->ar_pln = ar_pln;
00317     arphdr->ar_op  = htons(ar_op);
00318     memcpy(arphdr->ar_sha, ar_sha, ar_hln);
00319     memcpy(arphdr->ar_sip, ar_sip, ar_pln);
00320     memcpy(arphdr->ar_tha, ar_tha, ar_hln);
00321     memcpy(arphdr->ar_tip, ar_tip, ar_pln);
00322     
00323     return 0;
00324 }
00325 
00326 int arp_header_build_wrapper(struct frb_s *frb, struct adi_netdev_s *netdev,
00327                              struct arp_neigh_s *neigh_src, struct arp_neigh_s *neigh_dest,
00328                              u8 ar_op)
00329 {
00330     return arp_header_build(frb, ARPHRD_ETHER, ETH_P_IP, ETH_ALEN, 
00331                             neigh_src->addr.address_len, ar_op, 
00332                             neigh_src->mac,  neigh_src->addr.address,
00333                             neigh_dest->mac, neigh_dest->addr.address);
00334 }
00335 
00336 int arp_entry_refresh_lock(struct arp_entry_s *arp_entry)
00337 {
00338     u32 timer[2];
00339 
00340     counter_read(counter_jiffies_desc, timer);
00341     arp_entry->timer = timer[0];
00342 
00343     list_del(&arp_entry->list);
00344     list_add_tail(&arp_entry->list, &arp_entries_list);
00345 
00346     return 0;
00347 }
00348 
00349 int arp_recv_request_lock(struct frb_s *frb, struct arp_neigh_s *neigh)
00350 {
00351     struct arp_neigh_s neigh_dest;
00352     struct arp_hdr_s *arp = (struct arp_hdr_s *)frb_data(frb);
00353 
00354     if (arp->ar_hln > ETH_ALEN)
00355         arp->ar_hln = ETH_ALEN;
00356 
00357     if (arp->ar_pln > NET_ADDR_MAX_LEN)
00358         arp->ar_pln = NET_ADDR_MAX_LEN;
00359 
00360     if (!arp_get_local_mac(neigh) && (arp_cache && !arp_get_neigh_lock(neigh)))
00361         return 0;
00362 
00363     memcpy(neigh_dest.mac, arp->ar_sha, arp->ar_hln);
00364     memcpy(neigh_dest.addr.address, arp->ar_sip, arp->ar_pln);
00365     neigh_dest.addr.address_len = arp->ar_pln;
00366 
00367     arp_reply(frb->frb_dev, neigh, &neigh_dest, arp->ar_sha);
00368     
00369     return 0;    
00370 }
00371 
00372 int arp_recv_reply_lock(struct frb_s *frb, struct arp_neigh_s *neigh)
00373 {
00374     struct arp_entry_s *arp_entry;
00375 
00376     arp_request_wake_up(neigh);
00377 
00378     if ((arp_entry = arp_get_entry_lock(&neigh->addr))) {
00379         arp_entry_refresh_lock(arp_entry);
00380 
00381         return 1;
00382     }
00383 
00384     arp_add_neigh_lock(neigh);
00385     
00386     return 0;
00387 }
00388 
00389 int arp_recv(struct frb_s *frb)
00390 {
00391     struct arp_hdr_s *arp = (struct arp_hdr_s *)frb_data(frb);
00392     struct arp_neigh_s neigh;
00393     int ret = 0;
00394     u32 flags;
00395 
00396     neigh.addr.address_len = arp->ar_pln;
00397 
00398     spin_lock_irqsave(&arp_entries_list_lock, flags);
00399 
00400     arp_stats.total_recv_arps++;
00401 
00402     if (ntohs(arp->ar_op) == ARPOP_REQUEST) {
00403         memcpy(neigh.addr.address, arp->ar_tip, arp->ar_pln);
00404         memcpy(neigh.mac,          arp->ar_tha, arp->ar_hln);
00405         arp_stats.recv_reply_arps++;
00406         
00407         ret = arp_recv_request_lock(frb, &neigh);
00408     }
00409     else
00410     if (ntohs(arp->ar_op) == ARPOP_REPLY) {
00411         memcpy(neigh.addr.address, arp->ar_sip, arp->ar_pln);
00412         memcpy(neigh.mac,          arp->ar_sha, arp->ar_hln);
00413         arp_stats.recv_reply_arps++;
00414 
00415         ret = arp_recv_reply_lock(frb, &neigh);
00416     }
00417     
00418     spin_unlock_irqrestore(&arp_entries_list_lock, flags);
00419     
00420     return ret;
00421 }
00422 
00423 int arp_send(struct adi_netdev_s *netdev, struct frb_s *frb, u8 *mac_dest)
00424 {
00425     frb->frb_dev = netdev;
00426     netdev->if_ops->header_build(frb, mac_dest, netdev->if_layer_2.if_addr, ETH_P_ARP);
00427     netdev->if_ops->transmit_frame(frb);
00428 
00429     return 0;
00430 }
00431 
00432 int arp_request(struct adi_netdev_s *netdev, struct arp_neigh_s *neigh)
00433 {
00434     struct frb_s frb;
00435     struct arp_neigh_s neigh_src;
00436 
00437     if (arp_get_neigh(neigh)) {
00438         return 1;
00439     }
00440     
00441     arp_stats.total_send_arps++;
00442     arp_stats.send_request_arps++;
00443     
00444     memcpy(neigh_src.mac, netdev->if_layer_2.if_addr, ETH_ALEN);
00445     memcpy(neigh_src.addr.address, netdev->if_layer_3.if_addr.address, netdev->if_layer_3.if_addr.address_len);
00446     neigh_src.addr.address_len = netdev->if_layer_3.if_addr.address_len;
00447     
00448     frb_create(&frb);
00449     frb_reverse(&frb);
00450     arp_header_build_wrapper(&frb, netdev, &neigh_src, neigh, ARPOP_REQUEST);
00451     arp_send(netdev, &frb, netdev->if_layer_2.if_addr_broadcast);
00452     frb_destroy(&frb);
00453     
00454     return 0;
00455 }
00456 
00457 int arp_reply(struct adi_netdev_s *netdev, struct arp_neigh_s *neigh_src,
00458               struct arp_neigh_s *neigh_dest, u8 *mac_dest)
00459 {
00460     struct frb_s frb;
00461 
00462     arp_stats.total_send_arps++;
00463     arp_stats.send_reply_arps++;
00464 
00465     frb_create(&frb);
00466     frb_reverse(&frb);
00467     arp_header_build_wrapper(&frb, netdev, neigh_src, neigh_dest, ARPOP_REPLY);
00468     arp_send(netdev, &frb, mac_dest);
00469     frb_destroy(&frb);
00470     
00471     return 0;
00472 }
00473 
00474 void arp_timeout(void *data)
00475 {
00476     sched_activate_task((struct task_s *)data);
00477 }
00478 
00479 int arp_resolve(struct adi_netdev_s *netdev, struct arp_neigh_s *neigh)
00480 {
00481     struct arp_request_s *request;
00482     struct timer_s arp_timer;
00483     u32 flags;
00484     
00485     if (arp_get_neigh(neigh)) {
00486         return 0;
00487     }
00488     
00489     request = (struct arp_request_s *)get_free_pages(0);
00490     request->neigh = neigh;
00491     request->task  = current_task;
00492     INIT_LIST_HEAD(&(request->list));    
00493     
00494     arp_timer.timer_function = arp_timeout;
00495     arp_timer.timer_data     = current_task;
00496     arp_timer.timer_expire   = ARP_TIMEOUT;
00497     arp_timer.timer_flags    = TIMER_FLAG_ONESHOT;
00498     
00499     spin_lock_irqsave(&arp_entries_list_lock, flags);    
00500     
00501     arp_request_add(request);
00502 
00503     if (arp_request(netdev, neigh)) {
00504         arp_request_del(request);
00505         spin_unlock_irqrestore(&arp_entries_list_lock, flags);    
00506         return 0;
00507     }
00508 
00509     spin_unlock_irqrestore(&arp_entries_list_lock, flags);    
00510     sched_deactivate_task(current_task);
00511     register_timer(&arp_timer);
00512     schedule_task();
00513 
00514     unregister_timer(&arp_timer);
00515     spin_lock_irqsave(&arp_entries_list_lock, flags);    
00516     arp_request_del(request);
00517     spin_unlock_irqrestore(&arp_entries_list_lock, flags);    
00518     
00519     put_free_pages((u32)request, 0);
00520 
00521     if (arp_get_neigh(neigh)) {
00522         return 0;
00523     }
00524 
00525     return -1;
00526 }
00527 
00528 int arp_print_stats(void)
00529 {
00530     printf("\n");
00531     printf("Total recv arps:         %d\n", arp_stats.total_recv_arps);
00532     printf("Total recv request arps: %d\n", arp_stats.recv_request_arps);
00533     printf("Total recv reply arps:   %d\n", arp_stats.recv_reply_arps);
00534     printf("Total send arps:         %d\n", arp_stats.total_send_arps);
00535     printf("Total send request arps: %d\n", arp_stats.send_request_arps);
00536     printf("Total send reply arps:   %d\n", arp_stats.send_reply_arps);
00537     
00538     return 0;
00539 }
00540 
00541 struct net_layer_2_pack arp_pack = {
00542     .pack_type          = 0x0608,
00543     .receiver           = arp_recv,
00544 };
00545 
00546 int net_layer_2_arp_init(void)
00547 {
00548     printk(", arp");
00549 
00550     net_layer_2_add_pack(&arp_pack);
00551     
00552     if ((arp_hash_desc = register_hash_table("arp", 4096, NULL)) < 0) {
00553         kernel_panic("can not create hash table for arp!");
00554     }
00555 
00556     arp_cache_set(1);    
00557     arp_resource_desc = register_resource(&arp_resource);
00558     spin_lock_init(&arp_entries_list_lock);
00559     INIT_LIST_HEAD(&arp_entries_list);
00560     spin_lock_init(&arp_requests_list_lock);
00561     INIT_LIST_HEAD(&arp_requests_list);
00562 
00563     return 0;
00564 }
Dokumentacje wygenerowano programem Doxygen 1.4.2 dla projektu Agnix