4 Copyright 1995 Philip Homburg
11 #include "osdep_eth.h"
23 #define ETH_FD_NR (4*IP_PORT_MAX)
24 #define EXPIRE_TIME 60*HZ /* seconds */
29 nwio_ethopt_t ef_ethopt
;
31 struct eth_fd
*ef_type_next
;
32 struct eth_fd
*ef_send_next
;
36 get_userdata_t ef_get_userdata
;
37 put_userdata_t ef_put_userdata
;
39 select_res_t ef_select_res
;
41 size_t ef_write_count
;
46 # define EFF_EMPTY 0x0
47 # define EFF_INUSE 0x1
49 # define EFF_READ_IP 0x2
50 # define EFF_WRITE_IP 0x4
51 # define EFF_IOCTL_IP 0x8
52 # define EFF_OPTSET 0x10
53 # define EFF_SEL_READ 0x20
55 /* Note that the vh_type field is normally considered part of the ethernet
64 FORWARD
int eth_checkopt
ARGS(( eth_fd_t
*eth_fd
));
65 FORWARD
void hash_fd
ARGS(( eth_fd_t
*eth_fd
));
66 FORWARD
void unhash_fd
ARGS(( eth_fd_t
*eth_fd
));
67 FORWARD
void eth_buffree
ARGS(( int priority
));
68 #ifdef BUF_CONSISTENCY_CHECK
69 FORWARD
void eth_bufcheck
ARGS(( void ));
71 FORWARD
int eth_sel_read
ARGS(( eth_fd_t
* ));
72 FORWARD
void packet2user
ARGS(( eth_fd_t
*fd
, acc_t
*pack
, time_t exp_time
));
73 FORWARD
void reply_thr_get
ARGS(( eth_fd_t
*eth_fd
,
74 size_t result
, int for_ioctl
));
75 FORWARD
void reply_thr_put
ARGS(( eth_fd_t
*eth_fd
,
76 size_t result
, int for_ioctl
));
77 FORWARD
void do_rec_conf
ARGS(( eth_port_t
*eth_port
));
78 FORWARD u32_t compute_rec_conf
ARGS(( eth_port_t
*eth_port
));
79 FORWARD acc_t
*insert_vlan_hdr
ARGS(( eth_port_t
*eth_port
, acc_t
*pack
));
81 PUBLIC eth_port_t
*eth_port_table
;
82 PUBLIC
int no_ethWritePort
= 0;
84 PRIVATE eth_fd_t eth_fd_table
[ETH_FD_NR
];
85 PRIVATE ether_addr_t broadcast
= { { 255, 255, 255, 255, 255, 255 } };
87 PUBLIC
void eth_prep()
89 eth_port_table
= alloc(eth_conf_nr
* sizeof(eth_port_table
[0]));
92 PUBLIC
void eth_init()
96 assert (BUF_S
>= sizeof(nwio_ethopt_t
));
97 assert (BUF_S
>= ETH_HDR_SIZE
); /* these are in fact static assertions,
98 thus a good compiler doesn't
99 generate any code for this */
102 for (i
=0; i
<ETH_FD_NR
; i
++)
103 eth_fd_table
[i
].ef_flags
= EFF_EMPTY
;
104 for (i
=0; i
<eth_conf_nr
; i
++)
106 eth_port_table
[i
].etp_flags
= EPF_EMPTY
;
107 eth_port_table
[i
].etp_getstat
= NULL
;
108 eth_port_table
[i
].etp_sendq_head
= NULL
;
109 eth_port_table
[i
].etp_sendq_tail
= NULL
;
110 eth_port_table
[i
].etp_type_any
= NULL
;
111 ev_init(ð_port_table
[i
].etp_sendev
);
112 for (j
= 0; j
<ETH_TYPE_HASH_NR
; j
++)
113 eth_port_table
[i
].etp_type
[j
]= NULL
;
114 for (j
= 0; j
<ETH_VLAN_HASH_NR
; j
++)
115 eth_port_table
[i
].etp_vlan_tab
[j
]= NULL
;
118 #ifndef BUF_CONSISTENCY_CHECK
119 bf_logon(eth_buffree
);
121 bf_logon(eth_buffree
, eth_bufcheck
);
127 PUBLIC
int eth_open(port
, srfd
, get_userdata
, put_userdata
, put_pkt
,
130 get_userdata_t get_userdata
;
131 put_userdata_t put_userdata
;
133 select_res_t select_res
;
136 eth_port_t
*eth_port
;
139 DBLOCK(0x20, printf("eth_open (%d, %d, %lx, %lx)\n", port
, srfd
,
140 (unsigned long)get_userdata
, (unsigned long)put_userdata
));
141 eth_port
= ð_port_table
[port
];
142 if (!(eth_port
->etp_flags
& EPF_ENABLED
))
145 for (i
=0; i
<ETH_FD_NR
&& (eth_fd_table
[i
].ef_flags
& EFF_INUSE
);
150 DBLOCK(1, printf("out of fds\n"));
154 eth_fd
= ð_fd_table
[i
];
156 eth_fd
->ef_flags
= EFF_INUSE
;
157 eth_fd
->ef_ethopt
.nweo_flags
=NWEO_DEFAULT
;
158 eth_fd
->ef_port
= eth_port
;
159 eth_fd
->ef_srfd
= srfd
;
160 assert(eth_fd
->ef_rdbuf_head
== NULL
);
161 eth_fd
->ef_get_userdata
= get_userdata
;
162 eth_fd
->ef_put_userdata
= put_userdata
;
163 eth_fd
->ef_put_pkt
= put_pkt
;
164 eth_fd
->ef_select_res
= select_res
;
169 PUBLIC
int eth_ioctl(fd
, req
)
175 eth_port_t
*eth_port
;
177 DBLOCK(0x20, printf("eth_ioctl (%d, 0x%lx)\n", fd
, (unsigned long)req
));
178 eth_fd
= ð_fd_table
[fd
];
179 eth_port
= eth_fd
->ef_port
;
181 assert (eth_fd
->ef_flags
& EFF_INUSE
);
187 nwio_ethopt_t
*ethopt
;
188 nwio_ethopt_t oldopt
, newopt
;
190 u32_t new_en_flags
, new_di_flags
,
191 old_en_flags
, old_di_flags
;
193 data
= (*eth_fd
->ef_get_userdata
)(eth_fd
->
194 ef_srfd
, 0, sizeof(nwio_ethopt_t
), TRUE
);
196 ethopt
= (nwio_ethopt_t
*)ptr2acc_data(data
);
197 oldopt
= eth_fd
->ef_ethopt
;
200 old_en_flags
= oldopt
.nweo_flags
& 0xffff;
201 old_di_flags
= (oldopt
.nweo_flags
>> 16) & 0xffff;
202 new_en_flags
= newopt
.nweo_flags
& 0xffff;
203 new_di_flags
= (newopt
.nweo_flags
>> 16) & 0xffff;
204 if (new_en_flags
& new_di_flags
)
207 reply_thr_get (eth_fd
, EBADMODE
, TRUE
);
212 if (new_di_flags
& NWEO_ACC_MASK
)
215 reply_thr_get (eth_fd
, EBADMODE
, TRUE
);
218 /* you can't disable access modes */
220 if (!(new_en_flags
& NWEO_ACC_MASK
))
221 new_en_flags
|= (old_en_flags
& NWEO_ACC_MASK
);
225 if (!((new_en_flags
| new_di_flags
) & NWEO_LOC_MASK
))
227 new_en_flags
|= (old_en_flags
& NWEO_LOC_MASK
);
228 new_di_flags
|= (old_di_flags
& NWEO_LOC_MASK
);
231 /* NWEO_BROAD_MASK */
232 if (!((new_en_flags
| new_di_flags
) & NWEO_BROAD_MASK
))
234 new_en_flags
|= (old_en_flags
& NWEO_BROAD_MASK
);
235 new_di_flags
|= (old_di_flags
& NWEO_BROAD_MASK
);
238 /* NWEO_MULTI_MASK */
239 if (!((new_en_flags
| new_di_flags
) & NWEO_MULTI_MASK
))
241 new_en_flags
|= (old_en_flags
& NWEO_MULTI_MASK
);
242 new_di_flags
|= (old_di_flags
& NWEO_MULTI_MASK
);
243 newopt
.nweo_multi
= oldopt
.nweo_multi
;
246 /* NWEO_PROMISC_MASK */
247 if (!((new_en_flags
| new_di_flags
) & NWEO_PROMISC_MASK
))
249 new_en_flags
|= (old_en_flags
& NWEO_PROMISC_MASK
);
250 new_di_flags
|= (old_di_flags
& NWEO_PROMISC_MASK
);
254 if (!((new_en_flags
| new_di_flags
) & NWEO_REM_MASK
))
256 new_en_flags
|= (old_en_flags
& NWEO_REM_MASK
);
257 new_di_flags
|= (old_di_flags
& NWEO_REM_MASK
);
258 newopt
.nweo_rem
= oldopt
.nweo_rem
;
262 if (!((new_en_flags
| new_di_flags
) & NWEO_TYPE_MASK
))
264 new_en_flags
|= (old_en_flags
& NWEO_TYPE_MASK
);
265 new_di_flags
|= (old_di_flags
& NWEO_TYPE_MASK
);
266 newopt
.nweo_type
= oldopt
.nweo_type
;
270 if (!((new_en_flags
| new_di_flags
) & NWEO_RW_MASK
))
272 new_en_flags
|= (old_en_flags
& NWEO_RW_MASK
);
273 new_di_flags
|= (old_di_flags
& NWEO_RW_MASK
);
276 if (eth_fd
->ef_flags
& EFF_OPTSET
)
279 newopt
.nweo_flags
= ((unsigned long)new_di_flags
<< 16) |
281 eth_fd
->ef_ethopt
= newopt
;
283 result
= eth_checkopt(eth_fd
);
286 eth_fd
->ef_ethopt
= oldopt
;
289 unsigned long opt_flags
;
291 opt_flags
= oldopt
.nweo_flags
^
292 eth_fd
->ef_ethopt
.nweo_flags
;
293 changes
= ((opt_flags
>> 16) | opt_flags
) &
295 if (changes
& (NWEO_BROAD_MASK
|
296 NWEO_MULTI_MASK
| NWEO_PROMISC_MASK
))
298 do_rec_conf(eth_port
);
302 if (eth_fd
->ef_flags
& EFF_OPTSET
)
306 reply_thr_get (eth_fd
, result
, TRUE
);
312 nwio_ethopt_t
*ethopt
;
316 acc
= bf_memreq(sizeof(nwio_ethopt_t
));
318 ethopt
= (nwio_ethopt_t
*)ptr2acc_data(acc
);
320 *ethopt
= eth_fd
->ef_ethopt
;
322 result
= (*eth_fd
->ef_put_userdata
)(eth_fd
->
323 ef_srfd
, 0, acc
, TRUE
);
325 reply_thr_put(eth_fd
, NW_OK
, TRUE
);
330 nwio_ethstat_t
*ethstat
;
334 assert (sizeof(nwio_ethstat_t
) <= BUF_S
);
336 eth_port
= eth_fd
->ef_port
;
337 if (!(eth_port
->etp_flags
& EPF_ENABLED
))
339 reply_thr_put(eth_fd
, EGENERIC
, TRUE
);
343 if (!(eth_port
->etp_flags
& EPF_GOT_ADDR
))
347 "eth_ioctl: suspending NWIOGETHSTAT ioctl\n");
350 eth_fd
->ef_ioctl_req
= req
;
351 assert(!(eth_fd
->ef_flags
& EFF_IOCTL_IP
));
352 eth_fd
->ef_flags
|= EFF_IOCTL_IP
;
356 if (eth_port
->etp_getstat
)
359 "eth_ioctl: pending eth_get_stat request, suspending caller\n");
360 assert(!(eth_fd
->ef_flags
& EFF_IOCTL_IP
));
361 eth_fd
->ef_flags
|= EFF_IOCTL_IP
;
365 acc
= bf_memreq(sizeof(nwio_ethstat_t
));
366 compare (bf_bufsize(acc
), ==, sizeof(*ethstat
));
368 ethstat
= (nwio_ethstat_t
*)ptr2acc_data(acc
);
369 ethstat
->nwes_addr
= eth_port
->etp_ethaddr
;
371 if (!eth_port
->etp_vlan
)
373 result
= eth_get_stat(eth_port
,
374 ðstat
->nwes_stat
);
375 if (result
== SUSPEND
)
379 "eth_ioctl: eth_get_stat returned SUSPEND\n");
381 eth_fd
->ef_ioctl_req
= req
;
382 assert(!(eth_fd
->ef_flags
&
384 eth_fd
->ef_flags
|= EFF_IOCTL_IP
;
386 printf("eth_ioctl: setting etp_getstat in port %d to %p\n",
387 eth_port
-eth_port_table
, acc
);
389 eth_port
->etp_getstat
= acc
;
396 reply_thr_put(eth_fd
, result
, TRUE
);
403 memset(ðstat
->nwes_stat
, '\0',
404 sizeof(ethstat
->nwes_stat
));
407 result
= (*eth_fd
->ef_put_userdata
)(eth_fd
->
408 ef_srfd
, 0, acc
, TRUE
);
410 reply_thr_put(eth_fd
, NW_OK
, TRUE
);
416 reply_thr_put(eth_fd
, EBADIOCTL
, TRUE
);
420 PUBLIC
int eth_write(fd
, count
)
425 eth_port_t
*eth_port
, *rep
;
429 eth_fd
= ð_fd_table
[fd
];
430 eth_port
= eth_fd
->ef_port
;
432 if (!(eth_fd
->ef_flags
& EFF_OPTSET
))
434 reply_thr_get (eth_fd
, EBADMODE
, FALSE
);
438 assert (!(eth_fd
->ef_flags
& EFF_WRITE_IP
));
440 eth_fd
->ef_write_count
= count
;
441 if (eth_fd
->ef_ethopt
.nweo_flags
& NWEO_RWDATONLY
)
442 count
+= ETH_HDR_SIZE
;
444 if (count
<ETH_MIN_PACK_SIZE
|| count
>ETH_MAX_PACK_SIZE
)
446 DBLOCK(1, printf("illegal packetsize (%d)\n",count
));
447 reply_thr_get (eth_fd
, EPACKSIZE
, FALSE
);
450 eth_fd
->ef_flags
|= EFF_WRITE_IP
;
452 /* Enqueue at the real ethernet port */
453 rep
= eth_port
->etp_vlan_port
;
456 if (rep
->etp_wr_pack
)
458 eth_fd
->ef_send_next
= NULL
;
459 if (rep
->etp_sendq_head
)
460 rep
->etp_sendq_tail
->ef_send_next
= eth_fd
;
462 rep
->etp_sendq_head
= eth_fd
;
463 rep
->etp_sendq_tail
= eth_fd
;
467 user_data
= (*eth_fd
->ef_get_userdata
)(eth_fd
->ef_srfd
, 0,
468 eth_fd
->ef_write_count
, FALSE
);
471 eth_fd
->ef_flags
&= ~EFF_WRITE_IP
;
472 reply_thr_get (eth_fd
, EFAULT
, FALSE
);
475 r
= eth_send(fd
, user_data
, eth_fd
->ef_write_count
);
478 eth_fd
->ef_flags
&= ~EFF_WRITE_IP
;
479 reply_thr_get(eth_fd
, eth_fd
->ef_write_count
, FALSE
);
483 PUBLIC
int eth_send(fd
, data
, data_len
)
489 eth_port_t
*eth_port
, *rep
;
492 unsigned long nweo_flags
;
496 eth_fd
= ð_fd_table
[fd
];
497 eth_port
= eth_fd
->ef_port
;
499 if (!(eth_fd
->ef_flags
& EFF_OPTSET
))
503 if (eth_fd
->ef_ethopt
.nweo_flags
& NWEO_RWDATONLY
)
504 count
+= ETH_HDR_SIZE
;
506 if (count
<ETH_MIN_PACK_SIZE
|| count
>ETH_MAX_PACK_SIZE
)
508 DBLOCK(1, printf("illegal packetsize (%d)\n",count
));
511 rep
= eth_port
->etp_vlan_port
;
515 if (rep
->etp_wr_pack
)
516 return NW_WOULDBLOCK
;
518 nweo_flags
= eth_fd
->ef_ethopt
.nweo_flags
;
519 if (nweo_flags
& NWEO_RWDATONLY
)
521 eth_pack
= bf_memreq(ETH_HDR_SIZE
);
522 eth_pack
->acc_next
= data
;
525 eth_pack
= bf_packIffLess(data
, ETH_HDR_SIZE
);
527 eth_hdr
= (eth_hdr_t
*)ptr2acc_data(eth_pack
);
529 if (nweo_flags
& NWEO_REMSPEC
)
530 eth_hdr
->eh_dst
= eth_fd
->ef_ethopt
.nweo_rem
;
532 if (!(eth_port
->etp_flags
& EPF_GOT_ADDR
))
534 /* No device, discard packet */
539 if (!(nweo_flags
& NWEO_EN_PROMISC
))
540 eth_hdr
->eh_src
= eth_port
->etp_ethaddr
;
542 if (nweo_flags
& NWEO_TYPESPEC
)
543 eth_hdr
->eh_proto
= eth_fd
->ef_ethopt
.nweo_type
;
545 if (eth_addrcmp(eth_hdr
->eh_dst
, eth_port
->etp_ethaddr
) == 0)
547 /* Local loopback. */
548 eth_port
->etp_wr_pack
= eth_pack
;
549 ev_arg
.ev_ptr
= eth_port
;
550 ev_enqueue(ð_port
->etp_sendev
, eth_loop_ev
, ev_arg
);
556 eth_pack
= insert_vlan_hdr(eth_port
, eth_pack
);
559 /* Packet is silently discarded */
564 eth_write_port(rep
, eth_pack
);
568 PUBLIC
int eth_read (fd
, count
)
575 eth_fd
= ð_fd_table
[fd
];
576 if (!(eth_fd
->ef_flags
& EFF_OPTSET
))
578 reply_thr_put(eth_fd
, EBADMODE
, FALSE
);
581 if (count
< ETH_MAX_PACK_SIZE
)
583 reply_thr_put(eth_fd
, EPACKSIZE
, FALSE
);
587 assert(!(eth_fd
->ef_flags
& EFF_READ_IP
));
588 eth_fd
->ef_flags
|= EFF_READ_IP
;
590 while (eth_fd
->ef_rdbuf_head
)
592 pack
= eth_fd
->ef_rdbuf_head
;
593 eth_fd
->ef_rdbuf_head
= pack
->acc_ext_link
;
594 if (get_time() <= eth_fd
->ef_exp_time
)
596 packet2user(eth_fd
, pack
, eth_fd
->ef_exp_time
);
597 if (!(eth_fd
->ef_flags
& EFF_READ_IP
))
606 PUBLIC
int eth_cancel(fd
, which_operation
)
610 eth_fd_t
*eth_fd
, *prev
, *loc_fd
;
611 eth_port_t
*eth_port
;
613 DBLOCK(2, printf("eth_cancel (%d)\n", fd
));
614 eth_fd
= ð_fd_table
[fd
];
616 switch (which_operation
)
619 assert (eth_fd
->ef_flags
& EFF_READ_IP
);
620 eth_fd
->ef_flags
&= ~EFF_READ_IP
;
621 reply_thr_put(eth_fd
, EINTR
, FALSE
);
623 case SR_CANCEL_WRITE
:
624 assert (eth_fd
->ef_flags
& EFF_WRITE_IP
);
625 eth_fd
->ef_flags
&= ~EFF_WRITE_IP
;
627 /* Remove fd from send queue */
628 eth_port
= eth_fd
->ef_port
;
629 if (eth_port
->etp_vlan_port
)
630 eth_port
= eth_port
->etp_vlan_port
;
631 for (prev
= 0, loc_fd
= eth_port
->etp_sendq_head
; loc_fd
!= NULL
;
632 prev
= loc_fd
, loc_fd
= loc_fd
->ef_send_next
)
634 if (loc_fd
== eth_fd
)
637 assert(loc_fd
== eth_fd
);
639 eth_port
->etp_sendq_head
= loc_fd
->ef_send_next
;
641 prev
->ef_send_next
= loc_fd
->ef_send_next
;
642 if (loc_fd
->ef_send_next
== NULL
)
643 eth_port
->etp_sendq_tail
= prev
;
645 reply_thr_get(eth_fd
, EINTR
, FALSE
);
647 case SR_CANCEL_IOCTL
:
648 assert (eth_fd
->ef_flags
& EFF_IOCTL_IP
);
649 eth_fd
->ef_flags
&= ~EFF_IOCTL_IP
;
650 reply_thr_get(eth_fd
, EINTR
, TRUE
);
653 ip_panic(( "got unknown cancel request" ));
658 PUBLIC
int eth_select(fd
, operations
)
666 eth_fd
= ð_fd_table
[fd
];
667 assert (eth_fd
->ef_flags
& EFF_INUSE
);
671 if (operations
& SR_SELECT_READ
)
673 if (eth_sel_read(eth_fd
))
674 resops
|= SR_SELECT_READ
;
675 else if (!(operations
& SR_SELECT_POLL
))
676 eth_fd
->ef_flags
|= EFF_SEL_READ
;
678 if (operations
& SR_SELECT_WRITE
)
680 /* Should handle special case when the interface is down */
681 resops
|= SR_SELECT_WRITE
;
683 if (operations
& SR_SELECT_EXCEPTION
)
685 printf("eth_select: not implemented for exceptions\n");
690 PUBLIC
void eth_close(fd
)
694 eth_port_t
*eth_port
;
697 eth_fd
= ð_fd_table
[fd
];
699 assert ((eth_fd
->ef_flags
& EFF_INUSE
) &&
700 !(eth_fd
->ef_flags
& EFF_BUSY
));
702 if (eth_fd
->ef_flags
& EFF_OPTSET
)
704 while (eth_fd
->ef_rdbuf_head
!= NULL
)
706 pack
= eth_fd
->ef_rdbuf_head
;
707 eth_fd
->ef_rdbuf_head
= pack
->acc_ext_link
;
710 eth_fd
->ef_flags
= EFF_EMPTY
;
712 eth_port
= eth_fd
->ef_port
;
713 do_rec_conf(eth_port
);
716 PUBLIC
void eth_loop_ev(ev
, ev_arg
)
721 eth_port_t
*eth_port
;
723 eth_port
= ev_arg
.ev_ptr
;
724 assert(ev
== ð_port
->etp_sendev
);
726 pack
= eth_port
->etp_wr_pack
;
728 assert(!no_ethWritePort
);
730 eth_arrive(eth_port
, pack
, bf_bufsize(pack
));
731 assert(no_ethWritePort
);
734 eth_port
->etp_wr_pack
= NULL
;
735 eth_restart_write(eth_port
);
738 PRIVATE
int eth_checkopt (eth_fd
)
741 /* bug: we don't check access modes yet */
744 unsigned int en_di_flags
;
745 eth_port_t
*eth_port
;
748 eth_port
= eth_fd
->ef_port
;
749 flags
= eth_fd
->ef_ethopt
.nweo_flags
;
750 en_di_flags
= (flags
>>16) | (flags
& 0xffff);
752 if ((en_di_flags
& NWEO_ACC_MASK
) &&
753 (en_di_flags
& NWEO_LOC_MASK
) &&
754 (en_di_flags
& NWEO_BROAD_MASK
) &&
755 (en_di_flags
& NWEO_MULTI_MASK
) &&
756 (en_di_flags
& NWEO_PROMISC_MASK
) &&
757 (en_di_flags
& NWEO_REM_MASK
) &&
758 (en_di_flags
& NWEO_TYPE_MASK
) &&
759 (en_di_flags
& NWEO_RW_MASK
))
761 eth_fd
->ef_flags
|= EFF_OPTSET
;
764 eth_fd
->ef_flags
&= ~EFF_OPTSET
;
766 while (eth_fd
->ef_rdbuf_head
!= NULL
)
768 pack
= eth_fd
->ef_rdbuf_head
;
769 eth_fd
->ef_rdbuf_head
= pack
->acc_ext_link
;
776 PRIVATE
void hash_fd(eth_fd
)
779 eth_port_t
*eth_port
;
782 eth_port
= eth_fd
->ef_port
;
783 if (eth_fd
->ef_ethopt
.nweo_flags
& NWEO_TYPEANY
)
785 eth_fd
->ef_type_next
= eth_port
->etp_type_any
;
786 eth_port
->etp_type_any
= eth_fd
;
790 hash
= eth_fd
->ef_ethopt
.nweo_type
;
792 hash
&= (ETH_TYPE_HASH_NR
-1);
794 eth_fd
->ef_type_next
= eth_port
->etp_type
[hash
];
795 eth_port
->etp_type
[hash
]= eth_fd
;
799 PRIVATE
void unhash_fd(eth_fd
)
802 eth_port_t
*eth_port
;
803 eth_fd_t
*prev
, *curr
, **eth_fd_p
;
806 eth_port
= eth_fd
->ef_port
;
807 if (eth_fd
->ef_ethopt
.nweo_flags
& NWEO_TYPEANY
)
809 eth_fd_p
= ð_port
->etp_type_any
;
813 hash
= eth_fd
->ef_ethopt
.nweo_type
;
815 hash
&= (ETH_TYPE_HASH_NR
-1);
817 eth_fd_p
= ð_port
->etp_type
[hash
];
819 for (prev
= NULL
, curr
= *eth_fd_p
; curr
;
820 prev
= curr
, curr
= curr
->ef_type_next
)
827 prev
->ef_type_next
= curr
->ef_type_next
;
829 *eth_fd_p
= curr
->ef_type_next
;
832 PUBLIC
void eth_restart_write(eth_port
)
833 eth_port_t
*eth_port
;
838 assert(eth_port
->etp_wr_pack
== NULL
);
839 while (eth_fd
= eth_port
->etp_sendq_head
, eth_fd
!= NULL
)
841 if (eth_port
->etp_wr_pack
)
843 eth_port
->etp_sendq_head
= eth_fd
->ef_send_next
;
845 assert(eth_fd
->ef_flags
& EFF_WRITE_IP
);
846 eth_fd
->ef_flags
&= ~EFF_WRITE_IP
;
847 r
= eth_write(eth_fd
-eth_fd_table
, eth_fd
->ef_write_count
);
852 PUBLIC
void eth_arrive (eth_port
, pack
, pack_size
)
853 eth_port_t
*eth_port
;
859 ether_addr_t
*dst_addr
;
862 eth_fd_t
*eth_fd
, *first_fd
, *share_fd
;
866 acc_t
*vlan_pack
, *hdr_acc
, *tmp_acc
;
871 exp_time
= get_time() + EXPIRE_TIME
;
873 pack
= bf_packIffLess(pack
, ETH_HDR_SIZE
);
875 eth_hdr
= (eth_hdr_t
*)ptr2acc_data(pack
);
876 dst_addr
= ð_hdr
->eh_dst
;
878 DIFBLOCK(0x20, dst_addr
->ea_addr
[0] != 0xFF &&
879 (dst_addr
->ea_addr
[0] & 0x1),
880 printf("got multicast packet\n"));
882 if (dst_addr
->ea_addr
[0] & 0x1)
884 /* multi cast or broadcast */
885 if (eth_addrcmp(*dst_addr
, broadcast
) == 0)
886 pack_stat
= NWEO_EN_BROAD
;
888 pack_stat
= NWEO_EN_MULTI
;
892 assert(eth_port
->etp_flags
& EPF_GOT_ADDR
);
893 if (eth_addrcmp (*dst_addr
, eth_port
->etp_ethaddr
) == 0)
894 pack_stat
= NWEO_EN_LOC
;
896 pack_stat
= NWEO_EN_PROMISC
;
898 type
= eth_hdr
->eh_proto
;
901 hash
&= (ETH_TYPE_HASH_NR
-1);
903 if (type
== HTONS(ETH_VLAN_PROTO
))
905 /* VLAN packet. Extract original ethernet packet */
908 vlan_pack
->acc_linkC
++;
909 hdr_acc
= bf_cut(vlan_pack
, 0, 2*sizeof(ether_addr_t
));
910 vlan_pack
= bf_delhead(vlan_pack
, 2*sizeof(ether_addr_t
));
911 vlan_pack
= bf_packIffLess(vlan_pack
, sizeof(vh
));
912 vh
= *(vlan_hdr_t
*)ptr2acc_data(vlan_pack
);
913 vlan_pack
= bf_delhead(vlan_pack
, sizeof(vh
));
914 hdr_acc
= bf_append(hdr_acc
, vlan_pack
);
915 vlan_pack
= hdr_acc
; hdr_acc
= NULL
;
916 if (bf_bufsize(vlan_pack
) < ETH_MIN_PACK_SIZE
)
918 tmp_acc
= bf_memreq(sizeof(vh
));
921 assert(sizeof(vh
) <= sizeof(*p
));
922 p
= (u32_t
*)ptr2acc_data(tmp_acc
);
925 vlan_pack
= bf_append(vlan_pack
, tmp_acc
);
928 vlan
= ntohs(vh
.vh_vlan
);
929 if (vlan
& ETH_TCI_CFI
)
931 /* No support for extended address formats */
932 bf_afree(vlan_pack
); vlan_pack
= NULL
;
934 vlan
&= ETH_TCI_VLAN_MASK
;
938 /* No VLAN processing */
948 eth_fd
= (i
== 0) ? eth_port
->etp_type_any
:
949 eth_port
->etp_type
[hash
];
950 for (; eth_fd
; eth_fd
= eth_fd
->ef_type_next
)
952 if (i
&& eth_fd
->ef_ethopt
.nweo_type
!= type
)
954 if (!(eth_fd
->ef_ethopt
.nweo_flags
& pack_stat
))
956 if (eth_fd
->ef_ethopt
.nweo_flags
& NWEO_REMSPEC
&&
957 eth_addrcmp(eth_hdr
->eh_src
,
958 eth_fd
->ef_ethopt
.nweo_rem
) != 0)
962 if ((eth_fd
->ef_ethopt
.nweo_flags
& NWEO_ACC_MASK
) ==
970 if (!eth_fd
->ef_rdbuf_head
)
980 packet2user(eth_fd
, pack
, exp_time
);
985 packet2user(share_fd
, pack
, exp_time
);
990 if (first_fd
->ef_put_pkt
&&
991 (first_fd
->ef_flags
& EFF_READ_IP
) &&
992 !(first_fd
->ef_ethopt
.nweo_flags
& NWEO_RWDATONLY
))
994 (*first_fd
->ef_put_pkt
)(first_fd
->ef_srfd
, pack
,
998 packet2user(first_fd
, pack
, exp_time
);
1002 if (pack_stat
== NWEO_EN_LOC
)
1005 printf("eth_arrive: dropping packet for proto 0x%x\n",
1010 DBLOCK(0x20, printf("dropping packet for proto 0x%x\n",
1017 hash
= ETH_HASH_VLAN(vlan
, temp
);
1018 for (vp
= eth_port
->etp_vlan_tab
[hash
]; vp
;
1019 vp
= vp
->etp_vlan_next
)
1021 if (vp
->etp_vlan
== vlan
)
1026 eth_arrive(vp
, vlan_pack
, pack_size
-sizeof(vh
));
1031 /* No device for VLAN */
1032 bf_afree(vlan_pack
);
1038 PUBLIC
void eth_reg_vlan(eth_port
, vlan_port
)
1039 eth_port_t
*eth_port
;
1040 eth_port_t
*vlan_port
;
1045 vlan
= vlan_port
->etp_vlan
;
1046 h
= ETH_HASH_VLAN(vlan
, t
);
1047 vlan_port
->etp_vlan_next
= eth_port
->etp_vlan_tab
[h
];
1048 eth_port
->etp_vlan_tab
[h
]= vlan_port
;
1051 PUBLIC
void eth_restart_ioctl(eth_port
)
1052 eth_port_t
*eth_port
;
1059 printf("in eth_restart_ioctl\n");
1062 /* eth_restart_ioctl is called on too occasions: when a device
1063 * driver registers with inet and when a eth_get_stat call has
1064 * completed. We assume the second option when etp_getstat is
1065 * not equal to zero at the start of the call.
1067 acc
= eth_port
->etp_getstat
;
1069 for (i
= 0, eth_fd
= eth_fd_table
; i
<ETH_FD_NR
; i
++, eth_fd
++)
1071 if (!(eth_fd
->ef_flags
& EFF_INUSE
))
1073 if (eth_fd
->ef_port
!= eth_port
)
1075 if (!(eth_fd
->ef_flags
& EFF_IOCTL_IP
))
1077 if (eth_fd
->ef_ioctl_req
!= NWIOGETHSTAT
)
1081 printf("eth_restart_ioctl: etp_getstat in port %d is %p\n",
1082 eth_port
-eth_port_table
, acc
);
1088 printf("eth_restart_ioctl: completed getstat\n");
1091 r
= (*eth_fd
->ef_put_userdata
)(eth_fd
->ef_srfd
, 0,
1094 reply_thr_put(eth_fd
, NW_OK
, TRUE
);
1095 eth_fd
->ef_flags
&= ~EFF_IOCTL_IP
;
1099 { static int count
; if (++count
> 5) ip_panic(("too many restarts")); }
1101 eth_fd
->ef_flags
&= ~EFF_IOCTL_IP
;
1102 eth_ioctl(i
, eth_fd
->ef_ioctl_req
);
1108 printf("eth_restart_ioctl: clearing etp_getstat in port %d\n",
1109 eth_port
-eth_port_table
);
1111 assert(acc
== eth_port
->etp_getstat
);
1114 eth_port
->etp_getstat
= NULL
;
1118 PRIVATE
int eth_sel_read (eth_fd
)
1121 acc_t
*pack
, *tmp_acc
, *next_acc
;
1124 if (!(eth_fd
->ef_flags
& EFF_OPTSET
))
1125 return 1; /* Read will not block */
1127 if (eth_fd
->ef_rdbuf_head
)
1129 if (get_time() <= eth_fd
->ef_exp_time
)
1132 tmp_acc
= eth_fd
->ef_rdbuf_head
;
1135 next_acc
= tmp_acc
->acc_ext_link
;
1139 eth_fd
->ef_rdbuf_head
= NULL
;
1144 PRIVATE
void packet2user (eth_fd
, pack
, exp_time
)
1153 assert (eth_fd
->ef_flags
& EFF_INUSE
);
1154 if (!(eth_fd
->ef_flags
& EFF_READ_IP
))
1156 if (pack
->acc_linkC
!= 1)
1158 tmp_pack
= bf_dupacc(pack
);
1163 pack
->acc_ext_link
= NULL
;
1164 if (eth_fd
->ef_rdbuf_head
== NULL
)
1166 eth_fd
->ef_rdbuf_head
= pack
;
1167 eth_fd
->ef_exp_time
= exp_time
;
1170 eth_fd
->ef_rdbuf_tail
->acc_ext_link
= pack
;
1171 eth_fd
->ef_rdbuf_tail
= pack
;
1173 if (eth_fd
->ef_flags
& EFF_SEL_READ
)
1175 eth_fd
->ef_flags
&= ~EFF_SEL_READ
;
1176 if (eth_fd
->ef_select_res
)
1177 eth_fd
->ef_select_res(eth_fd
->ef_srfd
, SR_SELECT_READ
);
1179 printf("packet2user: no select_res\n");
1184 if (eth_fd
->ef_ethopt
.nweo_flags
& NWEO_RWDATONLY
)
1185 pack
= bf_delhead(pack
, ETH_HDR_SIZE
);
1187 size
= bf_bufsize(pack
);
1189 if (eth_fd
->ef_put_pkt
)
1191 (*eth_fd
->ef_put_pkt
)(eth_fd
->ef_srfd
, pack
, size
);
1195 eth_fd
->ef_flags
&= ~EFF_READ_IP
;
1196 result
= (*eth_fd
->ef_put_userdata
)(eth_fd
->ef_srfd
, (size_t)0, pack
,
1199 reply_thr_put(eth_fd
, size
, FALSE
);
1201 reply_thr_put(eth_fd
, result
, FALSE
);
1204 PRIVATE
void eth_buffree (priority
)
1211 if (priority
== ETH_PRI_FDBUFS_EXTRA
)
1213 for (i
= 0, eth_fd
= eth_fd_table
; i
<ETH_FD_NR
; i
++, eth_fd
++)
1215 while (eth_fd
->ef_rdbuf_head
&&
1216 eth_fd
->ef_rdbuf_head
->acc_ext_link
)
1218 pack
= eth_fd
->ef_rdbuf_head
;
1219 eth_fd
->ef_rdbuf_head
= pack
->acc_ext_link
;
1224 if (priority
== ETH_PRI_FDBUFS
)
1226 for (i
= 0, eth_fd
= eth_fd_table
; i
<ETH_FD_NR
; i
++, eth_fd
++)
1228 while (eth_fd
->ef_rdbuf_head
)
1230 pack
= eth_fd
->ef_rdbuf_head
;
1231 eth_fd
->ef_rdbuf_head
= pack
->acc_ext_link
;
1238 #ifdef BUF_CONSISTENCY_CHECK
1239 PRIVATE
void eth_bufcheck()
1245 for (i
= 0; i
<eth_conf_nr
; i
++)
1247 bf_check_acc(eth_port_table
[i
].etp_rd_pack
);
1248 bf_check_acc(eth_port_table
[i
].etp_wr_pack
);
1250 for (i
= 0, eth_fd
= eth_fd_table
; i
<ETH_FD_NR
; i
++, eth_fd
++)
1252 for (pack
= eth_fd
->ef_rdbuf_head
; pack
;
1253 pack
= pack
->acc_ext_link
)
1261 PRIVATE
void do_rec_conf(eth_port
)
1262 eth_port_t
*eth_port
;
1270 if (eth_port
->etp_vlan
)
1272 /* Configure underlying device */
1273 eth_port
= eth_port
->etp_vlan_port
;
1275 flags
= compute_rec_conf(eth_port
);
1276 for (i
= 0; i
<ETH_VLAN_HASH_NR
; i
++)
1278 for (vp
= eth_port
->etp_vlan_tab
[i
]; vp
; vp
= vp
->etp_vlan_next
)
1279 flags
|= compute_rec_conf(vp
);
1281 eth_set_rec_conf(eth_port
, flags
);
1284 PRIVATE u32_t
compute_rec_conf(eth_port
)
1285 eth_port_t
*eth_port
;
1291 flags
= NWEO_NOFLAGS
;
1292 for (i
=0, eth_fd
= eth_fd_table
; i
<ETH_FD_NR
; i
++, eth_fd
++)
1294 if ((eth_fd
->ef_flags
& (EFF_INUSE
|EFF_OPTSET
)) !=
1295 (EFF_INUSE
|EFF_OPTSET
))
1299 if (eth_fd
->ef_port
!= eth_port
)
1301 flags
|= eth_fd
->ef_ethopt
.nweo_flags
;
1306 PRIVATE
void reply_thr_get (eth_fd
, result
, for_ioctl
)
1313 data
= (*eth_fd
->ef_get_userdata
)(eth_fd
->ef_srfd
, result
, 0, for_ioctl
);
1317 PRIVATE
void reply_thr_put (eth_fd
, result
, for_ioctl
)
1324 error
= (*eth_fd
->ef_put_userdata
)(eth_fd
->ef_srfd
, result
, (acc_t
*)0,
1326 assert(error
== NW_OK
);
1329 PRIVATE acc_t
*insert_vlan_hdr(eth_port
, pack
)
1330 eth_port_t
*eth_port
;
1333 acc_t
*head_acc
, *vh_acc
;
1337 head_acc
= bf_cut(pack
, 0, 2*sizeof(ether_addr_t
));
1338 pack
= bf_delhead(pack
, 2*sizeof(ether_addr_t
));
1339 pack
= bf_packIffLess(pack
, sizeof(type
));
1340 type
= *(u16_t
*)ptr2acc_data(pack
);
1341 if (type
== HTONS(ETH_VLAN_PROTO
))
1343 /* Packeted is already tagged. Should update vlan number.
1344 * For now, just discard packet.
1346 printf("insert_vlan_hdr: discarding vlan packet\n");
1347 bf_afree(head_acc
); head_acc
= NULL
;
1348 bf_afree(pack
); pack
= NULL
;
1351 vlan
= eth_port
->etp_vlan
; /* priority and CFI are zero */
1353 vh_acc
= bf_memreq(sizeof(vlan_hdr_t
));
1354 vp
= (vlan_hdr_t
*)ptr2acc_data(vh_acc
);
1355 vp
->vh_type
= HTONS(ETH_VLAN_PROTO
);
1356 vp
->vh_vlan
= htons(vlan
);
1358 head_acc
= bf_append(head_acc
, vh_acc
); vh_acc
= NULL
;
1359 head_acc
= bf_append(head_acc
, pack
); pack
= NULL
;
1360 pack
= head_acc
; head_acc
= NULL
;
1365 * $PchId: eth.c,v 1.23 2005/06/28 14:15:58 philip Exp $