00001
00002
00003
00004
00005
00006
00007 #include "inet.h"
00008 #include "buf.h"
00009 #include "clock.h"
00010 #include "event.h"
00011 #include "osdep_eth.h"
00012 #include "type.h"
00013
00014 #include "assert.h"
00015 #include "buf.h"
00016 #include "eth.h"
00017 #include "eth_int.h"
00018 #include "io.h"
00019 #include "sr.h"
00020
00021 THIS_FILE
00022
00023 #define ETH_FD_NR (4*IP_PORT_MAX)
00024 #define EXPIRE_TIME 60*HZ
00025
00026 typedef struct eth_fd
00027 {
00028 int ef_flags;
00029 nwio_ethopt_t ef_ethopt;
00030 eth_port_t *ef_port;
00031 struct eth_fd *ef_type_next;
00032 struct eth_fd *ef_send_next;
00033 int ef_srfd;
00034 acc_t *ef_rdbuf_head;
00035 acc_t *ef_rdbuf_tail;
00036 get_userdata_t ef_get_userdata;
00037 put_userdata_t ef_put_userdata;
00038 put_pkt_t ef_put_pkt;
00039 time_t ef_exp_time;
00040 size_t ef_write_count;
00041 ioreq_t ef_ioctl_req;
00042 } eth_fd_t;
00043
00044 #define EFF_FLAGS 0xf
00045 # define EFF_EMPTY 0x0
00046 # define EFF_INUSE 0x1
00047 # define EFF_BUSY 0xE
00048 # define EFF_READ_IP 0x2
00049 # define EFF_WRITE_IP 0x4
00050 # define EFF_IOCTL_IP 0x8
00051 # define EFF_OPTSET 0x10
00052
00053
00054
00055
00056 typedef struct
00057 {
00058 u16_t vh_type;
00059 u16_t vh_vlan;
00060 } vlan_hdr_t;
00061
00062 FORWARD int eth_checkopt ARGS(( eth_fd_t *eth_fd ));
00063 FORWARD void hash_fd ARGS(( eth_fd_t *eth_fd ));
00064 FORWARD void unhash_fd ARGS(( eth_fd_t *eth_fd ));
00065 FORWARD void eth_buffree ARGS(( int priority ));
00066 #ifdef BUF_CONSISTENCY_CHECK
00067 FORWARD void eth_bufcheck ARGS(( void ));
00068 #endif
00069 FORWARD void packet2user ARGS(( eth_fd_t *fd, acc_t *pack, time_t exp_time ));
00070 FORWARD void reply_thr_get ARGS(( eth_fd_t *eth_fd,
00071 size_t result, int for_ioctl ));
00072 FORWARD void reply_thr_put ARGS(( eth_fd_t *eth_fd,
00073 size_t result, int for_ioctl ));
00074 FORWARD void do_rec_conf ARGS(( eth_port_t *eth_port ));
00075 FORWARD u32_t compute_rec_conf ARGS(( eth_port_t *eth_port ));
00076 FORWARD acc_t *insert_vlan_hdr ARGS(( eth_port_t *eth_port, acc_t *pack ));
00077
00078 PUBLIC eth_port_t *eth_port_table;
00079 PUBLIC int no_ethWritePort= 0;
00080
00081 PRIVATE eth_fd_t eth_fd_table[ETH_FD_NR];
00082 PRIVATE ether_addr_t broadcast= { { 255, 255, 255, 255, 255, 255 } };
00083
00084 PUBLIC void eth_prep()
00085 {
00086 eth_port_table= alloc(eth_conf_nr * sizeof(eth_port_table[0]));
00087 }
00088
00089 PUBLIC void eth_init()
00090 {
00091 int i, j;
00092
00093 assert (BUF_S >= sizeof(nwio_ethopt_t));
00094 assert (BUF_S >= ETH_HDR_SIZE);
00095
00096
00097
00098
00099 for (i=0; i<ETH_FD_NR; i++)
00100 eth_fd_table[i].ef_flags= EFF_EMPTY;
00101 for (i=0; i<eth_conf_nr; i++)
00102 {
00103 eth_port_table[i].etp_flags= EFF_EMPTY;
00104 eth_port_table[i].etp_sendq_head= NULL;
00105 eth_port_table[i].etp_sendq_tail= NULL;
00106 eth_port_table[i].etp_type_any= NULL;
00107 ev_init(ð_port_table[i].etp_sendev);
00108 for (j= 0; j<ETH_TYPE_HASH_NR; j++)
00109 eth_port_table[i].etp_type[j]= NULL;
00110 for (j= 0; j<ETH_VLAN_HASH_NR; j++)
00111 eth_port_table[i].etp_vlan_tab[j]= NULL;
00112 }
00113
00114 #ifndef BUF_CONSISTENCY_CHECK
00115 bf_logon(eth_buffree);
00116 #else
00117 bf_logon(eth_buffree, eth_bufcheck);
00118 #endif
00119
00120 osdep_eth_init();
00121 }
00122
00123 PUBLIC int eth_open(port, srfd, get_userdata, put_userdata, put_pkt,
00124 select_res)
00125 int port, srfd;
00126 get_userdata_t get_userdata;
00127 put_userdata_t put_userdata;
00128 put_pkt_t put_pkt;
00129 select_res_t select_res;
00130 {
00131 int i;
00132 eth_port_t *eth_port;
00133 eth_fd_t *eth_fd;
00134
00135 DBLOCK(0x20, printf("eth_open (%d, %d, %lx, %lx)\n", port, srfd,
00136 (unsigned long)get_userdata, (unsigned long)put_userdata));
00137 eth_port= ð_port_table[port];
00138 if (!(eth_port->etp_flags & EPF_ENABLED))
00139 return EGENERIC;
00140
00141 for (i=0; i<ETH_FD_NR && (eth_fd_table[i].ef_flags & EFF_INUSE);
00142 i++);
00143
00144 if (i>=ETH_FD_NR)
00145 {
00146 DBLOCK(1, printf("out of fds\n"));
00147 return EAGAIN;
00148 }
00149
00150 eth_fd= ð_fd_table[i];
00151
00152 eth_fd->ef_flags= EFF_INUSE;
00153 eth_fd->ef_ethopt.nweo_flags=NWEO_DEFAULT;
00154 eth_fd->ef_port= eth_port;
00155 eth_fd->ef_srfd= srfd;
00156 assert(eth_fd->ef_rdbuf_head == NULL);
00157 eth_fd->ef_get_userdata= get_userdata;
00158 eth_fd->ef_put_userdata= put_userdata;
00159 eth_fd->ef_put_pkt= put_pkt;
00160
00161 return i;
00162 }
00163
00164 PUBLIC int eth_ioctl(fd, req)
00165 int fd;
00166 ioreq_t req;
00167 {
00168 acc_t *data;
00169 eth_fd_t *eth_fd;
00170 eth_port_t *eth_port;
00171
00172 DBLOCK(0x20, printf("eth_ioctl (%d, 0x%lx)\n", fd, (unsigned long)req));
00173 eth_fd= ð_fd_table[fd];
00174 eth_port= eth_fd->ef_port;
00175
00176 assert (eth_fd->ef_flags & EFF_INUSE);
00177
00178 switch (req)
00179 {
00180 case NWIOSETHOPT:
00181 {
00182 nwio_ethopt_t *ethopt;
00183 nwio_ethopt_t oldopt, newopt;
00184 int result;
00185 u32_t new_en_flags, new_di_flags,
00186 old_en_flags, old_di_flags;
00187
00188 data= (*eth_fd->ef_get_userdata)(eth_fd->
00189 ef_srfd, 0, sizeof(nwio_ethopt_t), TRUE);
00190
00191 ethopt= (nwio_ethopt_t *)ptr2acc_data(data);
00192 oldopt= eth_fd->ef_ethopt;
00193 newopt= *ethopt;
00194
00195 old_en_flags= oldopt.nweo_flags & 0xffff;
00196 old_di_flags= (oldopt.nweo_flags >> 16) & 0xffff;
00197 new_en_flags= newopt.nweo_flags & 0xffff;
00198 new_di_flags= (newopt.nweo_flags >> 16) & 0xffff;
00199 if (new_en_flags & new_di_flags)
00200 {
00201 bf_afree(data);
00202 reply_thr_get (eth_fd, EBADMODE, TRUE);
00203 return NW_OK;
00204 }
00205
00206
00207 if (new_di_flags & NWEO_ACC_MASK)
00208 {
00209 bf_afree(data);
00210 reply_thr_get (eth_fd, EBADMODE, TRUE);
00211 return NW_OK;
00212 }
00213
00214
00215 if (!(new_en_flags & NWEO_ACC_MASK))
00216 new_en_flags |= (old_en_flags & NWEO_ACC_MASK);
00217
00218
00219
00220 if (!((new_en_flags | new_di_flags) & NWEO_LOC_MASK))
00221 {
00222 new_en_flags |= (old_en_flags & NWEO_LOC_MASK);
00223 new_di_flags |= (old_di_flags & NWEO_LOC_MASK);
00224 }
00225
00226
00227 if (!((new_en_flags | new_di_flags) & NWEO_BROAD_MASK))
00228 {
00229 new_en_flags |= (old_en_flags & NWEO_BROAD_MASK);
00230 new_di_flags |= (old_di_flags & NWEO_BROAD_MASK);
00231 }
00232
00233
00234 if (!((new_en_flags | new_di_flags) & NWEO_MULTI_MASK))
00235 {
00236 new_en_flags |= (old_en_flags & NWEO_MULTI_MASK);
00237 new_di_flags |= (old_di_flags & NWEO_MULTI_MASK);
00238 newopt.nweo_multi= oldopt.nweo_multi;
00239 }
00240
00241
00242 if (!((new_en_flags | new_di_flags) & NWEO_PROMISC_MASK))
00243 {
00244 new_en_flags |= (old_en_flags & NWEO_PROMISC_MASK);
00245 new_di_flags |= (old_di_flags & NWEO_PROMISC_MASK);
00246 }
00247
00248
00249 if (!((new_en_flags | new_di_flags) & NWEO_REM_MASK))
00250 {
00251 new_en_flags |= (old_en_flags & NWEO_REM_MASK);
00252 new_di_flags |= (old_di_flags & NWEO_REM_MASK);
00253 newopt.nweo_rem= oldopt.nweo_rem;
00254 }
00255
00256
00257 if (!((new_en_flags | new_di_flags) & NWEO_TYPE_MASK))
00258 {
00259 new_en_flags |= (old_en_flags & NWEO_TYPE_MASK);
00260 new_di_flags |= (old_di_flags & NWEO_TYPE_MASK);
00261 newopt.nweo_type= oldopt.nweo_type;
00262 }
00263
00264
00265 if (!((new_en_flags | new_di_flags) & NWEO_RW_MASK))
00266 {
00267 new_en_flags |= (old_en_flags & NWEO_RW_MASK);
00268 new_di_flags |= (old_di_flags & NWEO_RW_MASK);
00269 }
00270
00271 if (eth_fd->ef_flags & EFF_OPTSET)
00272 unhash_fd(eth_fd);
00273
00274 newopt.nweo_flags= ((unsigned long)new_di_flags << 16) |
00275 new_en_flags;
00276 eth_fd->ef_ethopt= newopt;
00277
00278 result= eth_checkopt(eth_fd);
00279
00280 if (result<0)
00281 eth_fd->ef_ethopt= oldopt;
00282 else
00283 {
00284 unsigned long opt_flags;
00285 unsigned changes;
00286 opt_flags= oldopt.nweo_flags ^
00287 eth_fd->ef_ethopt.nweo_flags;
00288 changes= ((opt_flags >> 16) | opt_flags) &
00289 0xffff;
00290 if (changes & (NWEO_BROAD_MASK |
00291 NWEO_MULTI_MASK | NWEO_PROMISC_MASK))
00292 {
00293 do_rec_conf(eth_port);
00294 }
00295 }
00296
00297 if (eth_fd->ef_flags & EFF_OPTSET)
00298 hash_fd(eth_fd);
00299
00300 bf_afree(data);
00301 reply_thr_get (eth_fd, result, TRUE);
00302 return NW_OK;
00303 }
00304
00305 case NWIOGETHOPT:
00306 {
00307 nwio_ethopt_t *ethopt;
00308 acc_t *acc;
00309 int result;
00310
00311 acc= bf_memreq(sizeof(nwio_ethopt_t));
00312
00313 ethopt= (nwio_ethopt_t *)ptr2acc_data(acc);
00314
00315 *ethopt= eth_fd->ef_ethopt;
00316
00317 result= (*eth_fd->ef_put_userdata)(eth_fd->
00318 ef_srfd, 0, acc, TRUE);
00319 if (result >= 0)
00320 reply_thr_put(eth_fd, NW_OK, TRUE);
00321 return result;
00322 }
00323 case NWIOGETHSTAT:
00324 {
00325 nwio_ethstat_t *ethstat;
00326 acc_t *acc;
00327 int result;
00328
00329 assert (sizeof(nwio_ethstat_t) <= BUF_S);
00330
00331 eth_port= eth_fd->ef_port;
00332 if (!(eth_port->etp_flags & EPF_ENABLED))
00333 {
00334 reply_thr_put(eth_fd, EGENERIC, TRUE);
00335 return NW_OK;
00336 }
00337
00338 if (!(eth_port->etp_flags & EPF_GOT_ADDR))
00339 {
00340 printf(
00341 "eth_ioctl: suspending NWIOGETHSTAT ioctl\n");
00342
00343 eth_fd->ef_ioctl_req= req;
00344 assert(!(eth_fd->ef_flags & EFF_IOCTL_IP));
00345 eth_fd->ef_flags |= EFF_IOCTL_IP;
00346 return NW_SUSPEND;
00347 }
00348
00349 acc= bf_memreq(sizeof(nwio_ethstat_t));
00350 compare (bf_bufsize(acc), ==, sizeof(*ethstat));
00351
00352 ethstat= (nwio_ethstat_t *)ptr2acc_data(acc);
00353 ethstat->nwes_addr= eth_port->etp_ethaddr;
00354
00355 if (!eth_port->etp_vlan)
00356 {
00357 result= eth_get_stat(eth_port,
00358 ðstat->nwes_stat);
00359 if (result != NW_OK)
00360 {
00361 bf_afree(acc);
00362 reply_thr_put(eth_fd, result, TRUE);
00363 return NW_OK;
00364 }
00365 }
00366 else
00367 {
00368
00369 memset(ðstat->nwes_stat, '\0',
00370 sizeof(ethstat->nwes_stat));
00371 }
00372
00373 result= (*eth_fd->ef_put_userdata)(eth_fd->
00374 ef_srfd, 0, acc, TRUE);
00375 if (result >= 0)
00376 reply_thr_put(eth_fd, NW_OK, TRUE);
00377 return result;
00378 }
00379 default:
00380 break;
00381 }
00382 reply_thr_put(eth_fd, EBADIOCTL, TRUE);
00383 return NW_OK;
00384 }
00385
00386 PUBLIC int eth_write(fd, count)
00387 int fd;
00388 size_t count;
00389 {
00390 eth_fd_t *eth_fd;
00391 eth_port_t *eth_port, *rep;
00392 acc_t *user_data;
00393 int r;
00394
00395 eth_fd= ð_fd_table[fd];
00396 eth_port= eth_fd->ef_port;
00397
00398 if (!(eth_fd->ef_flags & EFF_OPTSET))
00399 {
00400 reply_thr_get (eth_fd, EBADMODE, FALSE);
00401 return NW_OK;
00402 }
00403
00404 assert (!(eth_fd->ef_flags & EFF_WRITE_IP));
00405
00406 eth_fd->ef_write_count= count;
00407 if (eth_fd->ef_ethopt.nweo_flags & NWEO_RWDATONLY)
00408 count += ETH_HDR_SIZE;
00409
00410 if (count<ETH_MIN_PACK_SIZE || count>ETH_MAX_PACK_SIZE)
00411 {
00412 DBLOCK(1, printf("illegal packetsize (%d)\n",count));
00413 reply_thr_get (eth_fd, EPACKSIZE, FALSE);
00414 return NW_OK;
00415 }
00416 eth_fd->ef_flags |= EFF_WRITE_IP;
00417
00418
00419 rep= eth_port->etp_vlan_port;
00420 if (!rep)
00421 rep= eth_port;
00422 if (rep->etp_wr_pack)
00423 {
00424 eth_fd->ef_send_next= NULL;
00425 if (rep->etp_sendq_head)
00426 rep->etp_sendq_tail->ef_send_next= eth_fd;
00427 else
00428 rep->etp_sendq_head= eth_fd;
00429 rep->etp_sendq_tail= eth_fd;
00430 return NW_SUSPEND;
00431 }
00432
00433 user_data= (*eth_fd->ef_get_userdata)(eth_fd->ef_srfd, 0,
00434 eth_fd->ef_write_count, FALSE);
00435 if (!user_data)
00436 {
00437 eth_fd->ef_flags &= ~EFF_WRITE_IP;
00438 reply_thr_get (eth_fd, EFAULT, FALSE);
00439 return NW_OK;
00440 }
00441 r= eth_send(fd, user_data, eth_fd->ef_write_count);
00442 assert(r == NW_OK);
00443
00444 eth_fd->ef_flags &= ~EFF_WRITE_IP;
00445 reply_thr_get(eth_fd, eth_fd->ef_write_count, FALSE);
00446 return NW_OK;
00447 }
00448
00449 PUBLIC int eth_send(fd, data, data_len)
00450 int fd;
00451 acc_t *data;
00452 size_t data_len;
00453 {
00454 eth_fd_t *eth_fd;
00455 eth_port_t *eth_port, *rep;
00456 eth_hdr_t *eth_hdr;
00457 acc_t *eth_pack;
00458 unsigned long nweo_flags;
00459 size_t count;
00460 ev_arg_t ev_arg;
00461
00462 eth_fd= ð_fd_table[fd];
00463 eth_port= eth_fd->ef_port;
00464
00465 if (!(eth_fd->ef_flags & EFF_OPTSET))
00466 return EBADMODE;
00467
00468 count= data_len;
00469 if (eth_fd->ef_ethopt.nweo_flags & NWEO_RWDATONLY)
00470 count += ETH_HDR_SIZE;
00471
00472 if (count<ETH_MIN_PACK_SIZE || count>ETH_MAX_PACK_SIZE)
00473 {
00474 DBLOCK(1, printf("illegal packetsize (%d)\n",count));
00475 return EPACKSIZE;
00476 }
00477 rep= eth_port->etp_vlan_port;
00478 if (!rep)
00479 rep= eth_port;
00480
00481 if (rep->etp_wr_pack)
00482 return NW_WOULDBLOCK;
00483
00484 nweo_flags= eth_fd->ef_ethopt.nweo_flags;
00485 if (nweo_flags & NWEO_RWDATONLY)
00486 {
00487 eth_pack= bf_memreq(ETH_HDR_SIZE);
00488 eth_pack->acc_next= data;
00489 }
00490 else
00491 eth_pack= bf_packIffLess(data, ETH_HDR_SIZE);
00492
00493 eth_hdr= (eth_hdr_t *)ptr2acc_data(eth_pack);
00494
00495 if (nweo_flags & NWEO_REMSPEC)
00496 eth_hdr->eh_dst= eth_fd->ef_ethopt.nweo_rem;
00497
00498 if (!(eth_port->etp_flags & EPF_GOT_ADDR))
00499 {
00500
00501 bf_afree(eth_pack);
00502 return NW_OK;
00503 }
00504
00505 if (!(nweo_flags & NWEO_EN_PROMISC))
00506 eth_hdr->eh_src= eth_port->etp_ethaddr;
00507
00508 if (nweo_flags & NWEO_TYPESPEC)
00509 eth_hdr->eh_proto= eth_fd->ef_ethopt.nweo_type;
00510
00511 if (eth_addrcmp(eth_hdr->eh_dst, eth_port->etp_ethaddr) == 0)
00512 {
00513
00514 eth_port->etp_wr_pack= eth_pack;
00515 ev_arg.ev_ptr= eth_port;
00516 ev_enqueue(ð_port->etp_sendev, eth_loop_ev, ev_arg);
00517 return NW_OK;
00518 }
00519
00520 if (rep != eth_port)
00521 {
00522 eth_pack= insert_vlan_hdr(eth_port, eth_pack);
00523 if (!eth_pack)
00524 {
00525
00526 return NW_OK;
00527 }
00528 }
00529
00530 eth_write_port(rep, eth_pack);
00531 return NW_OK;
00532 }
00533
00534 PUBLIC int eth_read (fd, count)
00535 int fd;
00536 size_t count;
00537 {
00538 eth_fd_t *eth_fd;
00539 acc_t *pack;
00540
00541 eth_fd= ð_fd_table[fd];
00542 if (!(eth_fd->ef_flags & EFF_OPTSET))
00543 {
00544 reply_thr_put(eth_fd, EBADMODE, FALSE);
00545 return NW_OK;
00546 }
00547 if (count < ETH_MAX_PACK_SIZE)
00548 {
00549 reply_thr_put(eth_fd, EPACKSIZE, FALSE);
00550 return NW_OK;
00551 }
00552
00553 assert(!(eth_fd->ef_flags & EFF_READ_IP));
00554 eth_fd->ef_flags |= EFF_READ_IP;
00555
00556 while (eth_fd->ef_rdbuf_head)
00557 {
00558 pack= eth_fd->ef_rdbuf_head;
00559 eth_fd->ef_rdbuf_head= pack->acc_ext_link;
00560 if (get_time() <= eth_fd->ef_exp_time)
00561 {
00562 packet2user(eth_fd, pack, eth_fd->ef_exp_time);
00563 if (!(eth_fd->ef_flags & EFF_READ_IP))
00564 return NW_OK;
00565 }
00566 else
00567 bf_afree(pack);
00568 }
00569 return NW_SUSPEND;
00570 }
00571
00572 PUBLIC int eth_cancel(fd, which_operation)
00573 int fd;
00574 int which_operation;
00575 {
00576 eth_fd_t *eth_fd, *prev, *loc_fd;
00577 eth_port_t *eth_port;
00578
00579 DBLOCK(2, printf("eth_cancel (%d)\n", fd));
00580 eth_fd= ð_fd_table[fd];
00581
00582 switch (which_operation)
00583 {
00584 case SR_CANCEL_READ:
00585 assert (eth_fd->ef_flags & EFF_READ_IP);
00586 eth_fd->ef_flags &= ~EFF_READ_IP;
00587 reply_thr_put(eth_fd, EINTR, FALSE);
00588 break;
00589 case SR_CANCEL_WRITE:
00590 assert (eth_fd->ef_flags & EFF_WRITE_IP);
00591 eth_fd->ef_flags &= ~EFF_WRITE_IP;
00592
00593
00594 eth_port= eth_fd->ef_port;
00595 if (eth_port->etp_vlan_port)
00596 eth_port= eth_port->etp_vlan_port;
00597 for (prev= 0, loc_fd= eth_port->etp_sendq_head; loc_fd != NULL;
00598 prev= loc_fd, loc_fd= loc_fd->ef_send_next)
00599 {
00600 if (loc_fd == eth_fd)
00601 break;
00602 }
00603 assert(loc_fd == eth_fd);
00604 if (prev == NULL)
00605 eth_port->etp_sendq_head= loc_fd->ef_send_next;
00606 else
00607 prev->ef_send_next= loc_fd->ef_send_next;
00608 if (loc_fd->ef_send_next == NULL)
00609 eth_port->etp_sendq_tail= prev;
00610
00611 reply_thr_get(eth_fd, EINTR, FALSE);
00612 break;
00613 case SR_CANCEL_IOCTL:
00614 assert (eth_fd->ef_flags & EFF_IOCTL_IP);
00615 eth_fd->ef_flags &= ~EFF_IOCTL_IP;
00616 reply_thr_get(eth_fd, EINTR, TRUE);
00617 break;
00618 default:
00619 ip_panic(( "got unknown cancel request" ));
00620 }
00621 return NW_OK;
00622 }
00623
00624 PUBLIC int eth_select(fd, operations)
00625 int fd;
00626 unsigned operations;
00627 {
00628 printf("eth_select: not implemented\n");
00629 return 0;
00630 }
00631
00632 PUBLIC void eth_close(fd)
00633 int fd;
00634 {
00635 eth_fd_t *eth_fd;
00636 eth_port_t *eth_port;
00637 acc_t *pack;
00638
00639 eth_fd= ð_fd_table[fd];
00640
00641 assert ((eth_fd->ef_flags & EFF_INUSE) &&
00642 !(eth_fd->ef_flags & EFF_BUSY));
00643
00644 if (eth_fd->ef_flags & EFF_OPTSET)
00645 unhash_fd(eth_fd);
00646 while (eth_fd->ef_rdbuf_head != NULL)
00647 {
00648 pack= eth_fd->ef_rdbuf_head;
00649 eth_fd->ef_rdbuf_head= pack->acc_ext_link;
00650 bf_afree(pack);
00651 }
00652 eth_fd->ef_flags= EFF_EMPTY;
00653
00654 eth_port= eth_fd->ef_port;
00655 do_rec_conf(eth_port);
00656 }
00657
00658 PUBLIC void eth_loop_ev(ev, ev_arg)
00659 event_t *ev;
00660 ev_arg_t ev_arg;
00661 {
00662 acc_t *pack;
00663 eth_port_t *eth_port;
00664
00665 eth_port= ev_arg.ev_ptr;
00666 assert(ev == ð_port->etp_sendev);
00667
00668 pack= eth_port->etp_wr_pack;
00669
00670 assert(!no_ethWritePort);
00671 no_ethWritePort= 1;
00672 eth_arrive(eth_port, pack, bf_bufsize(pack));
00673 assert(no_ethWritePort);
00674 no_ethWritePort= 0;
00675
00676 eth_port->etp_wr_pack= NULL;
00677 eth_restart_write(eth_port);
00678 }
00679
00680 PRIVATE int eth_checkopt (eth_fd)
00681 eth_fd_t *eth_fd;
00682 {
00683
00684
00685 unsigned long flags;
00686 unsigned int en_di_flags;
00687 eth_port_t *eth_port;
00688 acc_t *pack;
00689
00690 eth_port= eth_fd->ef_port;
00691 flags= eth_fd->ef_ethopt.nweo_flags;
00692 en_di_flags= (flags >>16) | (flags & 0xffff);
00693
00694 if ((en_di_flags & NWEO_ACC_MASK) &&
00695 (en_di_flags & NWEO_LOC_MASK) &&
00696 (en_di_flags & NWEO_BROAD_MASK) &&
00697 (en_di_flags & NWEO_MULTI_MASK) &&
00698 (en_di_flags & NWEO_PROMISC_MASK) &&
00699 (en_di_flags & NWEO_REM_MASK) &&
00700 (en_di_flags & NWEO_TYPE_MASK) &&
00701 (en_di_flags & NWEO_RW_MASK))
00702 {
00703 eth_fd->ef_flags |= EFF_OPTSET;
00704 }
00705 else
00706 eth_fd->ef_flags &= ~EFF_OPTSET;
00707
00708 while (eth_fd->ef_rdbuf_head != NULL)
00709 {
00710 pack= eth_fd->ef_rdbuf_head;
00711 eth_fd->ef_rdbuf_head= pack->acc_ext_link;
00712 bf_afree(pack);
00713 }
00714
00715 return NW_OK;
00716 }
00717
00718 PRIVATE void hash_fd(eth_fd)
00719 eth_fd_t *eth_fd;
00720 {
00721 eth_port_t *eth_port;
00722 int hash;
00723
00724 eth_port= eth_fd->ef_port;
00725 if (eth_fd->ef_ethopt.nweo_flags & NWEO_TYPEANY)
00726 {
00727 eth_fd->ef_type_next= eth_port->etp_type_any;
00728 eth_port->etp_type_any= eth_fd;
00729 }
00730 else
00731 {
00732 hash= eth_fd->ef_ethopt.nweo_type;
00733 hash ^= (hash >> 8);
00734 hash &= (ETH_TYPE_HASH_NR-1);
00735
00736 eth_fd->ef_type_next= eth_port->etp_type[hash];
00737 eth_port->etp_type[hash]= eth_fd;
00738 }
00739 }
00740
00741 PRIVATE void unhash_fd(eth_fd)
00742 eth_fd_t *eth_fd;
00743 {
00744 eth_port_t *eth_port;
00745 eth_fd_t *prev, *curr, **eth_fd_p;
00746 int hash;
00747
00748 eth_port= eth_fd->ef_port;
00749 if (eth_fd->ef_ethopt.nweo_flags & NWEO_TYPEANY)
00750 {
00751 eth_fd_p= ð_port->etp_type_any;
00752 }
00753 else
00754 {
00755 hash= eth_fd->ef_ethopt.nweo_type;
00756 hash ^= (hash >> 8);
00757 hash &= (ETH_TYPE_HASH_NR-1);
00758
00759 eth_fd_p= ð_port->etp_type[hash];
00760 }
00761 for (prev= NULL, curr= *eth_fd_p; curr;
00762 prev= curr, curr= curr->ef_type_next)
00763 {
00764 if (curr == eth_fd)
00765 break;
00766 }
00767 assert(curr);
00768 if (prev)
00769 prev->ef_type_next= curr->ef_type_next;
00770 else
00771 *eth_fd_p= curr->ef_type_next;
00772 }
00773
00774 PUBLIC void eth_restart_write(eth_port)
00775 eth_port_t *eth_port;
00776 {
00777 eth_fd_t *eth_fd;
00778 int r;
00779
00780 assert(eth_port->etp_wr_pack == NULL);
00781 while (eth_fd= eth_port->etp_sendq_head, eth_fd != NULL)
00782 {
00783 if (eth_port->etp_wr_pack)
00784 return;
00785 eth_port->etp_sendq_head= eth_fd->ef_send_next;
00786
00787 assert(eth_fd->ef_flags & EFF_WRITE_IP);
00788 eth_fd->ef_flags &= ~EFF_WRITE_IP;
00789 r= eth_write(eth_fd-eth_fd_table, eth_fd->ef_write_count);
00790 assert(r == NW_OK);
00791 }
00792 }
00793
00794 PUBLIC void eth_arrive (eth_port, pack, pack_size)
00795 eth_port_t *eth_port;
00796 acc_t *pack;
00797 size_t pack_size;
00798 {
00799
00800 eth_hdr_t *eth_hdr;
00801 ether_addr_t *dst_addr;
00802 int pack_stat;
00803 ether_type_t type;
00804 eth_fd_t *eth_fd, *first_fd, *share_fd;
00805 int hash, i;
00806 u16_t vlan, temp;
00807 time_t exp_time;
00808 acc_t *vlan_pack, *hdr_acc, *tmp_acc;
00809 eth_port_t *vp;
00810 vlan_hdr_t vh;
00811 u32_t *p;
00812
00813 exp_time= get_time() + EXPIRE_TIME;
00814
00815 pack= bf_packIffLess(pack, ETH_HDR_SIZE);
00816
00817 eth_hdr= (eth_hdr_t*)ptr2acc_data(pack);
00818 dst_addr= ð_hdr->eh_dst;
00819
00820 DIFBLOCK(0x20, dst_addr->ea_addr[0] != 0xFF &&
00821 (dst_addr->ea_addr[0] & 0x1),
00822 printf("got multicast packet\n"));
00823
00824 if (dst_addr->ea_addr[0] & 0x1)
00825 {
00826
00827 if (eth_addrcmp(*dst_addr, broadcast) == 0)
00828 pack_stat= NWEO_EN_BROAD;
00829 else
00830 pack_stat= NWEO_EN_MULTI;
00831 }
00832 else
00833 {
00834 assert(eth_port->etp_flags & EPF_GOT_ADDR);
00835 if (eth_addrcmp (*dst_addr, eth_port->etp_ethaddr) == 0)
00836 pack_stat= NWEO_EN_LOC;
00837 else
00838 pack_stat= NWEO_EN_PROMISC;
00839 }
00840 type= eth_hdr->eh_proto;
00841 hash= type;
00842 hash ^= (hash >> 8);
00843 hash &= (ETH_TYPE_HASH_NR-1);
00844
00845 if (type == HTONS(ETH_VLAN_PROTO))
00846 {
00847
00848
00849 vlan_pack= pack;
00850 vlan_pack->acc_linkC++;
00851 hdr_acc= bf_cut(vlan_pack, 0, 2*sizeof(ether_addr_t));
00852 vlan_pack= bf_delhead(vlan_pack, 2*sizeof(ether_addr_t));
00853 vlan_pack= bf_packIffLess(vlan_pack, sizeof(vh));
00854 vh= *(vlan_hdr_t *)ptr2acc_data(vlan_pack);
00855 vlan_pack= bf_delhead(vlan_pack, sizeof(vh));
00856 hdr_acc= bf_append(hdr_acc, vlan_pack);
00857 vlan_pack= hdr_acc; hdr_acc= NULL;
00858 if (bf_bufsize(vlan_pack) < ETH_MIN_PACK_SIZE)
00859 {
00860 tmp_acc= bf_memreq(sizeof(vh));
00861
00862
00863 assert(sizeof(vh) <= sizeof(*p));
00864 p= (u32_t *)ptr2acc_data(tmp_acc);
00865 *p= 0xdeadbeef;
00866
00867 vlan_pack= bf_append(vlan_pack, tmp_acc);
00868 tmp_acc= NULL;
00869 }
00870 vlan= ntohs(vh.vh_vlan);
00871 if (vlan & ETH_TCI_CFI)
00872 {
00873
00874 bf_afree(vlan_pack); vlan_pack= NULL;
00875 }
00876 vlan &= ETH_TCI_VLAN_MASK;
00877 }
00878 else
00879 {
00880
00881 vlan_pack= NULL;
00882 vlan= 0;
00883 }
00884
00885 first_fd= NULL;
00886 for (i= 0; i<2; i++)
00887 {
00888 share_fd= NULL;
00889
00890 eth_fd= (i == 0) ? eth_port->etp_type_any :
00891 eth_port->etp_type[hash];
00892 for (; eth_fd; eth_fd= eth_fd->ef_type_next)
00893 {
00894 if (i && eth_fd->ef_ethopt.nweo_type != type)
00895 continue;
00896 if (!(eth_fd->ef_ethopt.nweo_flags & pack_stat))
00897 continue;
00898 if (eth_fd->ef_ethopt.nweo_flags & NWEO_REMSPEC &&
00899 eth_addrcmp(eth_hdr->eh_src,
00900 eth_fd->ef_ethopt.nweo_rem) != 0)
00901 {
00902 continue;
00903 }
00904 if ((eth_fd->ef_ethopt.nweo_flags & NWEO_ACC_MASK) ==
00905 NWEO_SHARED)
00906 {
00907 if (!share_fd)
00908 {
00909 share_fd= eth_fd;
00910 continue;
00911 }
00912 if (!eth_fd->ef_rdbuf_head)
00913 share_fd= eth_fd;
00914 continue;
00915 }
00916 if (!first_fd)
00917 {
00918 first_fd= eth_fd;
00919 continue;
00920 }
00921 pack->acc_linkC++;
00922 packet2user(eth_fd, pack, exp_time);
00923 }
00924 if (share_fd)
00925 {
00926 pack->acc_linkC++;
00927 packet2user(share_fd, pack, exp_time);
00928 }
00929 }
00930 if (first_fd)
00931 {
00932 if (first_fd->ef_put_pkt &&
00933 (first_fd->ef_flags & EFF_READ_IP) &&
00934 !(first_fd->ef_ethopt.nweo_flags & NWEO_RWDATONLY))
00935 {
00936 (*first_fd->ef_put_pkt)(first_fd->ef_srfd, pack,
00937 pack_size);
00938 }
00939 else
00940 packet2user(first_fd, pack, exp_time);
00941 }
00942 else
00943 {
00944 if (pack_stat == NWEO_EN_LOC)
00945 {
00946 DBLOCK(0x01,
00947 printf("eth_arrive: dropping packet for proto 0x%x\n",
00948 ntohs(type)));
00949 }
00950 else
00951 {
00952 DBLOCK(0x20, printf("dropping packet for proto 0x%x\n",
00953 ntohs(type)));
00954 }
00955 bf_afree(pack);
00956 }
00957 if (vlan_pack)
00958 {
00959 hash= ETH_HASH_VLAN(vlan, temp);
00960 for (vp= eth_port->etp_vlan_tab[hash]; vp;
00961 vp= vp->etp_vlan_next)
00962 {
00963 if (vp->etp_vlan == vlan)
00964 break;
00965 }
00966 if (vp)
00967 {
00968 eth_arrive(vp, vlan_pack, pack_size-sizeof(vh));
00969 vlan_pack= NULL;
00970 }
00971 else
00972 {
00973
00974 bf_afree(vlan_pack);
00975 vlan_pack= NULL;
00976 }
00977 }
00978 }
00979
00980 PUBLIC void eth_reg_vlan(eth_port, vlan_port)
00981 eth_port_t *eth_port;
00982 eth_port_t *vlan_port;
00983 {
00984 u16_t t, vlan;
00985 int h;
00986
00987 vlan= vlan_port->etp_vlan;
00988 h= ETH_HASH_VLAN(vlan, t);
00989 vlan_port->etp_vlan_next= eth_port->etp_vlan_tab[h];
00990 eth_port->etp_vlan_tab[h]= vlan_port;
00991 }
00992
00993 PUBLIC void eth_restart_ioctl(eth_port)
00994 eth_port_t *eth_port;
00995 {
00996 int i;
00997 eth_fd_t *eth_fd;
00998
00999 for (i= 0, eth_fd= eth_fd_table; i<ETH_FD_NR; i++, eth_fd++)
01000 {
01001 if (!(eth_fd->ef_flags & EFF_INUSE))
01002 continue;
01003 if (eth_fd->ef_port != eth_port)
01004 continue;
01005 if (!(eth_fd->ef_flags & EFF_IOCTL_IP))
01006 continue;
01007 if (eth_fd->ef_ioctl_req != NWIOGETHSTAT)
01008 continue;
01009
01010 eth_fd->ef_flags &= ~EFF_IOCTL_IP;
01011 eth_ioctl(i, eth_fd->ef_ioctl_req);
01012 }
01013 }
01014
01015 PRIVATE void packet2user (eth_fd, pack, exp_time)
01016 eth_fd_t *eth_fd;
01017 acc_t *pack;
01018 time_t exp_time;
01019 {
01020 int result;
01021 acc_t *tmp_pack;
01022 size_t size;
01023
01024 assert (eth_fd->ef_flags & EFF_INUSE);
01025 if (!(eth_fd->ef_flags & EFF_READ_IP))
01026 {
01027 if (pack->acc_linkC != 1)
01028 {
01029 tmp_pack= bf_dupacc(pack);
01030 bf_afree(pack);
01031 pack= tmp_pack;
01032 tmp_pack= NULL;
01033 }
01034 pack->acc_ext_link= NULL;
01035 if (eth_fd->ef_rdbuf_head == NULL)
01036 {
01037 eth_fd->ef_rdbuf_head= pack;
01038 eth_fd->ef_exp_time= exp_time;
01039 }
01040 else
01041 eth_fd->ef_rdbuf_tail->acc_ext_link= pack;
01042 eth_fd->ef_rdbuf_tail= pack;
01043 return;
01044 }
01045
01046 if (eth_fd->ef_ethopt.nweo_flags & NWEO_RWDATONLY)
01047 pack= bf_delhead(pack, ETH_HDR_SIZE);
01048
01049 size= bf_bufsize(pack);
01050
01051 if (eth_fd->ef_put_pkt)
01052 {
01053 (*eth_fd->ef_put_pkt)(eth_fd->ef_srfd, pack, size);
01054 return;
01055 }
01056
01057 eth_fd->ef_flags &= ~EFF_READ_IP;
01058 result= (*eth_fd->ef_put_userdata)(eth_fd->ef_srfd, (size_t)0, pack,
01059 FALSE);
01060 if (result >=0)
01061 reply_thr_put(eth_fd, size, FALSE);
01062 else
01063 reply_thr_put(eth_fd, result, FALSE);
01064 }
01065
01066 PRIVATE void eth_buffree (priority)
01067 int priority;
01068 {
01069 int i;
01070 eth_fd_t *eth_fd;
01071 acc_t *pack;
01072
01073 if (priority == ETH_PRI_FDBUFS_EXTRA)
01074 {
01075 for (i= 0, eth_fd= eth_fd_table; i<ETH_FD_NR; i++, eth_fd++)
01076 {
01077 while (eth_fd->ef_rdbuf_head &&
01078 eth_fd->ef_rdbuf_head->acc_ext_link)
01079 {
01080 pack= eth_fd->ef_rdbuf_head;
01081 eth_fd->ef_rdbuf_head= pack->acc_ext_link;
01082 bf_afree(pack);
01083 }
01084 }
01085 }
01086 if (priority == ETH_PRI_FDBUFS)
01087 {
01088 for (i= 0, eth_fd= eth_fd_table; i<ETH_FD_NR; i++, eth_fd++)
01089 {
01090 while (eth_fd->ef_rdbuf_head)
01091 {
01092 pack= eth_fd->ef_rdbuf_head;
01093 eth_fd->ef_rdbuf_head= pack->acc_ext_link;
01094 bf_afree(pack);
01095 }
01096 }
01097 }
01098 }
01099
01100 #ifdef BUF_CONSISTENCY_CHECK
01101 PRIVATE void eth_bufcheck()
01102 {
01103 int i;
01104 eth_fd_t *eth_fd;
01105 acc_t *pack;
01106
01107 for (i= 0; i<eth_conf_nr; i++)
01108 {
01109 bf_check_acc(eth_port_table[i].etp_rd_pack);
01110 bf_check_acc(eth_port_table[i].etp_wr_pack);
01111 }
01112 for (i= 0, eth_fd= eth_fd_table; i<ETH_FD_NR; i++, eth_fd++)
01113 {
01114 for (pack= eth_fd->ef_rdbuf_head; pack;
01115 pack= pack->acc_ext_link)
01116 {
01117 bf_check_acc(pack);
01118 }
01119 }
01120 }
01121 #endif
01122
01123 PRIVATE void do_rec_conf(eth_port)
01124 eth_port_t *eth_port;
01125 {
01126 int i;
01127 u32_t flags;
01128 eth_port_t *vp;
01129
01130 if (eth_port->etp_vlan)
01131 {
01132
01133 eth_port= eth_port->etp_vlan_port;
01134 }
01135 flags= compute_rec_conf(eth_port);
01136 for (i= 0; i<ETH_VLAN_HASH_NR; i++)
01137 {
01138 for (vp= eth_port->etp_vlan_tab[i]; vp; vp= vp->etp_vlan_next)
01139 flags |= compute_rec_conf(vp);
01140 }
01141 eth_set_rec_conf(eth_port, flags);
01142 }
01143
01144 PRIVATE u32_t compute_rec_conf(eth_port)
01145 eth_port_t *eth_port;
01146 {
01147 eth_fd_t *eth_fd;
01148 u32_t flags;
01149 int i;
01150
01151 flags= NWEO_NOFLAGS;
01152 for (i=0, eth_fd= eth_fd_table; i<ETH_FD_NR; i++, eth_fd++)
01153 {
01154 if ((eth_fd->ef_flags & (EFF_INUSE|EFF_OPTSET)) !=
01155 (EFF_INUSE|EFF_OPTSET))
01156 {
01157 continue;
01158 }
01159 if (eth_fd->ef_port != eth_port)
01160 continue;
01161 flags |= eth_fd->ef_ethopt.nweo_flags;
01162 }
01163 return flags;
01164 }
01165
01166 PRIVATE void reply_thr_get (eth_fd, result, for_ioctl)
01167 eth_fd_t *eth_fd;
01168 size_t result;
01169 int for_ioctl;
01170 {
01171 acc_t *data;
01172
01173 data= (*eth_fd->ef_get_userdata)(eth_fd->ef_srfd, result, 0, for_ioctl);
01174 assert (!data);
01175 }
01176
01177 PRIVATE void reply_thr_put (eth_fd, result, for_ioctl)
01178 eth_fd_t *eth_fd;
01179 size_t result;
01180 int for_ioctl;
01181 {
01182 int error;
01183
01184 error= (*eth_fd->ef_put_userdata)(eth_fd->ef_srfd, result, (acc_t *)0,
01185 for_ioctl);
01186 assert(error == NW_OK);
01187 }
01188
01189 PRIVATE acc_t *insert_vlan_hdr(eth_port, pack)
01190 eth_port_t *eth_port;
01191 acc_t *pack;
01192 {
01193 acc_t *head_acc, *vh_acc;
01194 u16_t type, vlan;
01195 vlan_hdr_t *vp;
01196
01197 head_acc= bf_cut(pack, 0, 2*sizeof(ether_addr_t));
01198 pack= bf_delhead(pack, 2*sizeof(ether_addr_t));
01199 pack= bf_packIffLess(pack, sizeof(type));
01200 type= *(u16_t *)ptr2acc_data(pack);
01201 if (type == HTONS(ETH_VLAN_PROTO))
01202 {
01203
01204
01205
01206 printf("insert_vlan_hdr: discarding vlan packet\n");
01207 bf_afree(head_acc); head_acc= NULL;
01208 bf_afree(pack); pack= NULL;
01209 return NULL;
01210 }
01211 vlan= eth_port->etp_vlan;
01212
01213 vh_acc= bf_memreq(sizeof(vlan_hdr_t));
01214 vp= (vlan_hdr_t *)ptr2acc_data(vh_acc);
01215 vp->vh_type= HTONS(ETH_VLAN_PROTO);
01216 vp->vh_vlan= htons(vlan);
01217
01218 head_acc= bf_append(head_acc, vh_acc); vh_acc= NULL;
01219 head_acc= bf_append(head_acc, pack); pack= NULL;
01220 pack= head_acc; head_acc= NULL;
01221 return pack;
01222 }
01223
01224
01225
01226