00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
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
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 }