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
;
40 size_t ef_write_count
;
45 # define EFF_EMPTY 0x0
46 # define EFF_INUSE 0x1
48 # define EFF_READ_IP 0x2
49 # define EFF_WRITE_IP 0x4
50 # define EFF_IOCTL_IP 0x8
51 # define EFF_OPTSET 0x10
53 /* Note that the vh_type field is normally considered part of the ethernet
62 FORWARD
int eth_checkopt
ARGS(( eth_fd_t
*eth_fd
));
63 FORWARD
void hash_fd
ARGS(( eth_fd_t
*eth_fd
));
64 FORWARD
void unhash_fd
ARGS(( eth_fd_t
*eth_fd
));
65 FORWARD
void eth_buffree
ARGS(( int priority
));
66 #ifdef BUF_CONSISTENCY_CHECK
67 FORWARD
void eth_bufcheck
ARGS(( void ));
69 FORWARD
void packet2user
ARGS(( eth_fd_t
*fd
, acc_t
*pack
, time_t exp_time
));
70 FORWARD
void reply_thr_get
ARGS(( eth_fd_t
*eth_fd
,
71 size_t result
, int for_ioctl
));
72 FORWARD
void reply_thr_put
ARGS(( eth_fd_t
*eth_fd
,
73 size_t result
, int for_ioctl
));
74 FORWARD
void do_rec_conf
ARGS(( eth_port_t
*eth_port
));
75 FORWARD u32_t compute_rec_conf
ARGS(( eth_port_t
*eth_port
));
76 FORWARD acc_t
*insert_vlan_hdr
ARGS(( eth_port_t
*eth_port
, acc_t
*pack
));
78 PUBLIC eth_port_t
*eth_port_table
;
79 PUBLIC
int no_ethWritePort
= 0;
81 PRIVATE eth_fd_t eth_fd_table
[ETH_FD_NR
];
82 PRIVATE ether_addr_t broadcast
= { { 255, 255, 255, 255, 255, 255 } };
84 PUBLIC
void eth_prep()
86 eth_port_table
= alloc(eth_conf_nr
* sizeof(eth_port_table
[0]));
89 PUBLIC
void eth_init()
93 assert (BUF_S
>= sizeof(nwio_ethopt_t
));
94 assert (BUF_S
>= ETH_HDR_SIZE
); /* these are in fact static assertions,
95 thus a good compiler doesn't
96 generate any code for this */
99 for (i
=0; i
<ETH_FD_NR
; i
++)
100 eth_fd_table
[i
].ef_flags
= EFF_EMPTY
;
101 for (i
=0; i
<eth_conf_nr
; i
++)
103 eth_port_table
[i
].etp_flags
= EFF_EMPTY
;
104 eth_port_table
[i
].etp_sendq_head
= NULL
;
105 eth_port_table
[i
].etp_sendq_tail
= NULL
;
106 eth_port_table
[i
].etp_type_any
= NULL
;
107 ev_init(ð_port_table
[i
].etp_sendev
);
108 for (j
= 0; j
<ETH_TYPE_HASH_NR
; j
++)
109 eth_port_table
[i
].etp_type
[j
]= NULL
;
110 for (j
= 0; j
<ETH_VLAN_HASH_NR
; j
++)
111 eth_port_table
[i
].etp_vlan_tab
[j
]= NULL
;
114 #ifndef BUF_CONSISTENCY_CHECK
115 bf_logon(eth_buffree
);
117 bf_logon(eth_buffree
, eth_bufcheck
);
123 PUBLIC
int eth_open(port
, srfd
, get_userdata
, put_userdata
, put_pkt
,
126 get_userdata_t get_userdata
;
127 put_userdata_t put_userdata
;
129 select_res_t select_res
;
132 eth_port_t
*eth_port
;
135 DBLOCK(0x20, printf("eth_open (%d, %d, %lx, %lx)\n", port
, srfd
,
136 (unsigned long)get_userdata
, (unsigned long)put_userdata
));
137 eth_port
= ð_port_table
[port
];
138 if (!(eth_port
->etp_flags
& EPF_ENABLED
))
141 for (i
=0; i
<ETH_FD_NR
&& (eth_fd_table
[i
].ef_flags
& EFF_INUSE
);
146 DBLOCK(1, printf("out of fds\n"));
150 eth_fd
= ð_fd_table
[i
];
152 eth_fd
->ef_flags
= EFF_INUSE
;
153 eth_fd
->ef_ethopt
.nweo_flags
=NWEO_DEFAULT
;
154 eth_fd
->ef_port
= eth_port
;
155 eth_fd
->ef_srfd
= srfd
;
156 assert(eth_fd
->ef_rdbuf_head
== NULL
);
157 eth_fd
->ef_get_userdata
= get_userdata
;
158 eth_fd
->ef_put_userdata
= put_userdata
;
159 eth_fd
->ef_put_pkt
= put_pkt
;
164 PUBLIC
int eth_ioctl(fd
, req
)
170 eth_port_t
*eth_port
;
172 DBLOCK(0x20, printf("eth_ioctl (%d, 0x%lx)\n", fd
, (unsigned long)req
));
173 eth_fd
= ð_fd_table
[fd
];
174 eth_port
= eth_fd
->ef_port
;
176 assert (eth_fd
->ef_flags
& EFF_INUSE
);
182 nwio_ethopt_t
*ethopt
;
183 nwio_ethopt_t oldopt
, newopt
;
185 u32_t new_en_flags
, new_di_flags
,
186 old_en_flags
, old_di_flags
;
188 data
= (*eth_fd
->ef_get_userdata
)(eth_fd
->
189 ef_srfd
, 0, sizeof(nwio_ethopt_t
), TRUE
);
191 ethopt
= (nwio_ethopt_t
*)ptr2acc_data(data
);
192 oldopt
= eth_fd
->ef_ethopt
;
195 old_en_flags
= oldopt
.nweo_flags
& 0xffff;
196 old_di_flags
= (oldopt
.nweo_flags
>> 16) & 0xffff;
197 new_en_flags
= newopt
.nweo_flags
& 0xffff;
198 new_di_flags
= (newopt
.nweo_flags
>> 16) & 0xffff;
199 if (new_en_flags
& new_di_flags
)
202 reply_thr_get (eth_fd
, EBADMODE
, TRUE
);
207 if (new_di_flags
& NWEO_ACC_MASK
)
210 reply_thr_get (eth_fd
, EBADMODE
, TRUE
);
213 /* you can't disable access modes */
215 if (!(new_en_flags
& NWEO_ACC_MASK
))
216 new_en_flags
|= (old_en_flags
& NWEO_ACC_MASK
);
220 if (!((new_en_flags
| new_di_flags
) & NWEO_LOC_MASK
))
222 new_en_flags
|= (old_en_flags
& NWEO_LOC_MASK
);
223 new_di_flags
|= (old_di_flags
& NWEO_LOC_MASK
);
226 /* NWEO_BROAD_MASK */
227 if (!((new_en_flags
| new_di_flags
) & NWEO_BROAD_MASK
))
229 new_en_flags
|= (old_en_flags
& NWEO_BROAD_MASK
);
230 new_di_flags
|= (old_di_flags
& NWEO_BROAD_MASK
);
233 /* NWEO_MULTI_MASK */
234 if (!((new_en_flags
| new_di_flags
) & NWEO_MULTI_MASK
))
236 new_en_flags
|= (old_en_flags
& NWEO_MULTI_MASK
);
237 new_di_flags
|= (old_di_flags
& NWEO_MULTI_MASK
);
238 newopt
.nweo_multi
= oldopt
.nweo_multi
;
241 /* NWEO_PROMISC_MASK */
242 if (!((new_en_flags
| new_di_flags
) & NWEO_PROMISC_MASK
))
244 new_en_flags
|= (old_en_flags
& NWEO_PROMISC_MASK
);
245 new_di_flags
|= (old_di_flags
& NWEO_PROMISC_MASK
);
249 if (!((new_en_flags
| new_di_flags
) & NWEO_REM_MASK
))
251 new_en_flags
|= (old_en_flags
& NWEO_REM_MASK
);
252 new_di_flags
|= (old_di_flags
& NWEO_REM_MASK
);
253 newopt
.nweo_rem
= oldopt
.nweo_rem
;
257 if (!((new_en_flags
| new_di_flags
) & NWEO_TYPE_MASK
))
259 new_en_flags
|= (old_en_flags
& NWEO_TYPE_MASK
);
260 new_di_flags
|= (old_di_flags
& NWEO_TYPE_MASK
);
261 newopt
.nweo_type
= oldopt
.nweo_type
;
265 if (!((new_en_flags
| new_di_flags
) & NWEO_RW_MASK
))
267 new_en_flags
|= (old_en_flags
& NWEO_RW_MASK
);
268 new_di_flags
|= (old_di_flags
& NWEO_RW_MASK
);
271 if (eth_fd
->ef_flags
& EFF_OPTSET
)
274 newopt
.nweo_flags
= ((unsigned long)new_di_flags
<< 16) |
276 eth_fd
->ef_ethopt
= newopt
;
278 result
= eth_checkopt(eth_fd
);
281 eth_fd
->ef_ethopt
= oldopt
;
284 unsigned long opt_flags
;
286 opt_flags
= oldopt
.nweo_flags
^
287 eth_fd
->ef_ethopt
.nweo_flags
;
288 changes
= ((opt_flags
>> 16) | opt_flags
) &
290 if (changes
& (NWEO_BROAD_MASK
|
291 NWEO_MULTI_MASK
| NWEO_PROMISC_MASK
))
293 do_rec_conf(eth_port
);
297 if (eth_fd
->ef_flags
& EFF_OPTSET
)
301 reply_thr_get (eth_fd
, result
, TRUE
);
307 nwio_ethopt_t
*ethopt
;
311 acc
= bf_memreq(sizeof(nwio_ethopt_t
));
313 ethopt
= (nwio_ethopt_t
*)ptr2acc_data(acc
);
315 *ethopt
= eth_fd
->ef_ethopt
;
317 result
= (*eth_fd
->ef_put_userdata
)(eth_fd
->
318 ef_srfd
, 0, acc
, TRUE
);
320 reply_thr_put(eth_fd
, NW_OK
, TRUE
);
325 nwio_ethstat_t
*ethstat
;
329 assert (sizeof(nwio_ethstat_t
) <= BUF_S
);
331 eth_port
= eth_fd
->ef_port
;
332 if (!(eth_port
->etp_flags
& EPF_ENABLED
))
334 reply_thr_put(eth_fd
, EGENERIC
, TRUE
);
338 if (!(eth_port
->etp_flags
& EPF_GOT_ADDR
))
341 "eth_ioctl: suspending NWIOGETHSTAT ioctl\n");
343 eth_fd
->ef_ioctl_req
= req
;
344 assert(!(eth_fd
->ef_flags
& EFF_IOCTL_IP
));
345 eth_fd
->ef_flags
|= EFF_IOCTL_IP
;
349 acc
= bf_memreq(sizeof(nwio_ethstat_t
));
350 compare (bf_bufsize(acc
), ==, sizeof(*ethstat
));
352 ethstat
= (nwio_ethstat_t
*)ptr2acc_data(acc
);
353 ethstat
->nwes_addr
= eth_port
->etp_ethaddr
;
355 if (!eth_port
->etp_vlan
)
357 result
= eth_get_stat(eth_port
,
358 ðstat
->nwes_stat
);
362 reply_thr_put(eth_fd
, result
, TRUE
);
369 memset(ðstat
->nwes_stat
, '\0',
370 sizeof(ethstat
->nwes_stat
));
373 result
= (*eth_fd
->ef_put_userdata
)(eth_fd
->
374 ef_srfd
, 0, acc
, TRUE
);
376 reply_thr_put(eth_fd
, NW_OK
, TRUE
);
382 reply_thr_put(eth_fd
, EBADIOCTL
, TRUE
);
386 PUBLIC
int eth_write(fd
, count
)
391 eth_port_t
*eth_port
, *rep
;
395 eth_fd
= ð_fd_table
[fd
];
396 eth_port
= eth_fd
->ef_port
;
398 if (!(eth_fd
->ef_flags
& EFF_OPTSET
))
400 reply_thr_get (eth_fd
, EBADMODE
, FALSE
);
404 assert (!(eth_fd
->ef_flags
& EFF_WRITE_IP
));
406 eth_fd
->ef_write_count
= count
;
407 if (eth_fd
->ef_ethopt
.nweo_flags
& NWEO_RWDATONLY
)
408 count
+= ETH_HDR_SIZE
;
410 if (count
<ETH_MIN_PACK_SIZE
|| count
>ETH_MAX_PACK_SIZE
)
412 DBLOCK(1, printf("illegal packetsize (%d)\n",count
));
413 reply_thr_get (eth_fd
, EPACKSIZE
, FALSE
);
416 eth_fd
->ef_flags
|= EFF_WRITE_IP
;
418 /* Enqueue at the real ethernet port */
419 rep
= eth_port
->etp_vlan_port
;
422 if (rep
->etp_wr_pack
)
424 eth_fd
->ef_send_next
= NULL
;
425 if (rep
->etp_sendq_head
)
426 rep
->etp_sendq_tail
->ef_send_next
= eth_fd
;
428 rep
->etp_sendq_head
= eth_fd
;
429 rep
->etp_sendq_tail
= eth_fd
;
433 user_data
= (*eth_fd
->ef_get_userdata
)(eth_fd
->ef_srfd
, 0,
434 eth_fd
->ef_write_count
, FALSE
);
437 eth_fd
->ef_flags
&= ~EFF_WRITE_IP
;
438 reply_thr_get (eth_fd
, EFAULT
, FALSE
);
441 r
= eth_send(fd
, user_data
, eth_fd
->ef_write_count
);
444 eth_fd
->ef_flags
&= ~EFF_WRITE_IP
;
445 reply_thr_get(eth_fd
, eth_fd
->ef_write_count
, FALSE
);
449 PUBLIC
int eth_send(fd
, data
, data_len
)
455 eth_port_t
*eth_port
, *rep
;
458 unsigned long nweo_flags
;
462 eth_fd
= ð_fd_table
[fd
];
463 eth_port
= eth_fd
->ef_port
;
465 if (!(eth_fd
->ef_flags
& EFF_OPTSET
))
469 if (eth_fd
->ef_ethopt
.nweo_flags
& NWEO_RWDATONLY
)
470 count
+= ETH_HDR_SIZE
;
472 if (count
<ETH_MIN_PACK_SIZE
|| count
>ETH_MAX_PACK_SIZE
)
474 DBLOCK(1, printf("illegal packetsize (%d)\n",count
));
477 rep
= eth_port
->etp_vlan_port
;
481 if (rep
->etp_wr_pack
)
482 return NW_WOULDBLOCK
;
484 nweo_flags
= eth_fd
->ef_ethopt
.nweo_flags
;
485 if (nweo_flags
& NWEO_RWDATONLY
)
487 eth_pack
= bf_memreq(ETH_HDR_SIZE
);
488 eth_pack
->acc_next
= data
;
491 eth_pack
= bf_packIffLess(data
, ETH_HDR_SIZE
);
493 eth_hdr
= (eth_hdr_t
*)ptr2acc_data(eth_pack
);
495 if (nweo_flags
& NWEO_REMSPEC
)
496 eth_hdr
->eh_dst
= eth_fd
->ef_ethopt
.nweo_rem
;
498 if (!(eth_port
->etp_flags
& EPF_GOT_ADDR
))
500 /* No device, discard packet */
505 if (!(nweo_flags
& NWEO_EN_PROMISC
))
506 eth_hdr
->eh_src
= eth_port
->etp_ethaddr
;
508 if (nweo_flags
& NWEO_TYPESPEC
)
509 eth_hdr
->eh_proto
= eth_fd
->ef_ethopt
.nweo_type
;
511 if (eth_addrcmp(eth_hdr
->eh_dst
, eth_port
->etp_ethaddr
) == 0)
513 /* Local loopback. */
514 eth_port
->etp_wr_pack
= eth_pack
;
515 ev_arg
.ev_ptr
= eth_port
;
516 ev_enqueue(ð_port
->etp_sendev
, eth_loop_ev
, ev_arg
);
522 eth_pack
= insert_vlan_hdr(eth_port
, eth_pack
);
525 /* Packet is silently discarded */
530 eth_write_port(rep
, eth_pack
);
534 PUBLIC
int eth_read (fd
, count
)
541 eth_fd
= ð_fd_table
[fd
];
542 if (!(eth_fd
->ef_flags
& EFF_OPTSET
))
544 reply_thr_put(eth_fd
, EBADMODE
, FALSE
);
547 if (count
< ETH_MAX_PACK_SIZE
)
549 reply_thr_put(eth_fd
, EPACKSIZE
, FALSE
);
553 assert(!(eth_fd
->ef_flags
& EFF_READ_IP
));
554 eth_fd
->ef_flags
|= EFF_READ_IP
;
556 while (eth_fd
->ef_rdbuf_head
)
558 pack
= eth_fd
->ef_rdbuf_head
;
559 eth_fd
->ef_rdbuf_head
= pack
->acc_ext_link
;
560 if (get_time() <= eth_fd
->ef_exp_time
)
562 packet2user(eth_fd
, pack
, eth_fd
->ef_exp_time
);
563 if (!(eth_fd
->ef_flags
& EFF_READ_IP
))
572 PUBLIC
int eth_cancel(fd
, which_operation
)
576 eth_fd_t
*eth_fd
, *prev
, *loc_fd
;
577 eth_port_t
*eth_port
;
579 DBLOCK(2, printf("eth_cancel (%d)\n", fd
));
580 eth_fd
= ð_fd_table
[fd
];
582 switch (which_operation
)
585 assert (eth_fd
->ef_flags
& EFF_READ_IP
);
586 eth_fd
->ef_flags
&= ~EFF_READ_IP
;
587 reply_thr_put(eth_fd
, EINTR
, FALSE
);
589 case SR_CANCEL_WRITE
:
590 assert (eth_fd
->ef_flags
& EFF_WRITE_IP
);
591 eth_fd
->ef_flags
&= ~EFF_WRITE_IP
;
593 /* Remove fd from send queue */
594 eth_port
= eth_fd
->ef_port
;
595 if (eth_port
->etp_vlan_port
)
596 eth_port
= eth_port
->etp_vlan_port
;
597 for (prev
= 0, loc_fd
= eth_port
->etp_sendq_head
; loc_fd
!= NULL
;
598 prev
= loc_fd
, loc_fd
= loc_fd
->ef_send_next
)
600 if (loc_fd
== eth_fd
)
603 assert(loc_fd
== eth_fd
);
605 eth_port
->etp_sendq_head
= loc_fd
->ef_send_next
;
607 prev
->ef_send_next
= loc_fd
->ef_send_next
;
608 if (loc_fd
->ef_send_next
== NULL
)
609 eth_port
->etp_sendq_tail
= prev
;
611 reply_thr_get(eth_fd
, EINTR
, FALSE
);
613 case SR_CANCEL_IOCTL
:
614 assert (eth_fd
->ef_flags
& EFF_IOCTL_IP
);
615 eth_fd
->ef_flags
&= ~EFF_IOCTL_IP
;
616 reply_thr_get(eth_fd
, EINTR
, TRUE
);
619 ip_panic(( "got unknown cancel request" ));
624 PUBLIC
int eth_select(fd
, operations
)
628 printf("eth_select: not implemented\n");
632 PUBLIC
void eth_close(fd
)
636 eth_port_t
*eth_port
;
639 eth_fd
= ð_fd_table
[fd
];
641 assert ((eth_fd
->ef_flags
& EFF_INUSE
) &&
642 !(eth_fd
->ef_flags
& EFF_BUSY
));
644 if (eth_fd
->ef_flags
& EFF_OPTSET
)
646 while (eth_fd
->ef_rdbuf_head
!= NULL
)
648 pack
= eth_fd
->ef_rdbuf_head
;
649 eth_fd
->ef_rdbuf_head
= pack
->acc_ext_link
;
652 eth_fd
->ef_flags
= EFF_EMPTY
;
654 eth_port
= eth_fd
->ef_port
;
655 do_rec_conf(eth_port
);
658 PUBLIC
void eth_loop_ev(ev
, ev_arg
)
663 eth_port_t
*eth_port
;
665 eth_port
= ev_arg
.ev_ptr
;
666 assert(ev
== ð_port
->etp_sendev
);
668 pack
= eth_port
->etp_wr_pack
;
670 assert(!no_ethWritePort
);
672 eth_arrive(eth_port
, pack
, bf_bufsize(pack
));
673 assert(no_ethWritePort
);
676 eth_port
->etp_wr_pack
= NULL
;
677 eth_restart_write(eth_port
);
680 PRIVATE
int eth_checkopt (eth_fd
)
683 /* bug: we don't check access modes yet */
686 unsigned int en_di_flags
;
687 eth_port_t
*eth_port
;
690 eth_port
= eth_fd
->ef_port
;
691 flags
= eth_fd
->ef_ethopt
.nweo_flags
;
692 en_di_flags
= (flags
>>16) | (flags
& 0xffff);
694 if ((en_di_flags
& NWEO_ACC_MASK
) &&
695 (en_di_flags
& NWEO_LOC_MASK
) &&
696 (en_di_flags
& NWEO_BROAD_MASK
) &&
697 (en_di_flags
& NWEO_MULTI_MASK
) &&
698 (en_di_flags
& NWEO_PROMISC_MASK
) &&
699 (en_di_flags
& NWEO_REM_MASK
) &&
700 (en_di_flags
& NWEO_TYPE_MASK
) &&
701 (en_di_flags
& NWEO_RW_MASK
))
703 eth_fd
->ef_flags
|= EFF_OPTSET
;
706 eth_fd
->ef_flags
&= ~EFF_OPTSET
;
708 while (eth_fd
->ef_rdbuf_head
!= NULL
)
710 pack
= eth_fd
->ef_rdbuf_head
;
711 eth_fd
->ef_rdbuf_head
= pack
->acc_ext_link
;
718 PRIVATE
void hash_fd(eth_fd
)
721 eth_port_t
*eth_port
;
724 eth_port
= eth_fd
->ef_port
;
725 if (eth_fd
->ef_ethopt
.nweo_flags
& NWEO_TYPEANY
)
727 eth_fd
->ef_type_next
= eth_port
->etp_type_any
;
728 eth_port
->etp_type_any
= eth_fd
;
732 hash
= eth_fd
->ef_ethopt
.nweo_type
;
734 hash
&= (ETH_TYPE_HASH_NR
-1);
736 eth_fd
->ef_type_next
= eth_port
->etp_type
[hash
];
737 eth_port
->etp_type
[hash
]= eth_fd
;
741 PRIVATE
void unhash_fd(eth_fd
)
744 eth_port_t
*eth_port
;
745 eth_fd_t
*prev
, *curr
, **eth_fd_p
;
748 eth_port
= eth_fd
->ef_port
;
749 if (eth_fd
->ef_ethopt
.nweo_flags
& NWEO_TYPEANY
)
751 eth_fd_p
= ð_port
->etp_type_any
;
755 hash
= eth_fd
->ef_ethopt
.nweo_type
;
757 hash
&= (ETH_TYPE_HASH_NR
-1);
759 eth_fd_p
= ð_port
->etp_type
[hash
];
761 for (prev
= NULL
, curr
= *eth_fd_p
; curr
;
762 prev
= curr
, curr
= curr
->ef_type_next
)
769 prev
->ef_type_next
= curr
->ef_type_next
;
771 *eth_fd_p
= curr
->ef_type_next
;
774 PUBLIC
void eth_restart_write(eth_port
)
775 eth_port_t
*eth_port
;
780 assert(eth_port
->etp_wr_pack
== NULL
);
781 while (eth_fd
= eth_port
->etp_sendq_head
, eth_fd
!= NULL
)
783 if (eth_port
->etp_wr_pack
)
785 eth_port
->etp_sendq_head
= eth_fd
->ef_send_next
;
787 assert(eth_fd
->ef_flags
& EFF_WRITE_IP
);
788 eth_fd
->ef_flags
&= ~EFF_WRITE_IP
;
789 r
= eth_write(eth_fd
-eth_fd_table
, eth_fd
->ef_write_count
);
794 PUBLIC
void eth_arrive (eth_port
, pack
, pack_size
)
795 eth_port_t
*eth_port
;
801 ether_addr_t
*dst_addr
;
804 eth_fd_t
*eth_fd
, *first_fd
, *share_fd
;
808 acc_t
*vlan_pack
, *hdr_acc
, *tmp_acc
;
813 exp_time
= get_time() + EXPIRE_TIME
;
815 pack
= bf_packIffLess(pack
, ETH_HDR_SIZE
);
817 eth_hdr
= (eth_hdr_t
*)ptr2acc_data(pack
);
818 dst_addr
= ð_hdr
->eh_dst
;
820 DIFBLOCK(0x20, dst_addr
->ea_addr
[0] != 0xFF &&
821 (dst_addr
->ea_addr
[0] & 0x1),
822 printf("got multicast packet\n"));
824 if (dst_addr
->ea_addr
[0] & 0x1)
826 /* multi cast or broadcast */
827 if (eth_addrcmp(*dst_addr
, broadcast
) == 0)
828 pack_stat
= NWEO_EN_BROAD
;
830 pack_stat
= NWEO_EN_MULTI
;
834 assert(eth_port
->etp_flags
& EPF_GOT_ADDR
);
835 if (eth_addrcmp (*dst_addr
, eth_port
->etp_ethaddr
) == 0)
836 pack_stat
= NWEO_EN_LOC
;
838 pack_stat
= NWEO_EN_PROMISC
;
840 type
= eth_hdr
->eh_proto
;
843 hash
&= (ETH_TYPE_HASH_NR
-1);
845 if (type
== HTONS(ETH_VLAN_PROTO
))
847 /* VLAN packet. Extract original ethernet packet */
850 vlan_pack
->acc_linkC
++;
851 hdr_acc
= bf_cut(vlan_pack
, 0, 2*sizeof(ether_addr_t
));
852 vlan_pack
= bf_delhead(vlan_pack
, 2*sizeof(ether_addr_t
));
853 vlan_pack
= bf_packIffLess(vlan_pack
, sizeof(vh
));
854 vh
= *(vlan_hdr_t
*)ptr2acc_data(vlan_pack
);
855 vlan_pack
= bf_delhead(vlan_pack
, sizeof(vh
));
856 hdr_acc
= bf_append(hdr_acc
, vlan_pack
);
857 vlan_pack
= hdr_acc
; hdr_acc
= NULL
;
858 if (bf_bufsize(vlan_pack
) < ETH_MIN_PACK_SIZE
)
860 tmp_acc
= bf_memreq(sizeof(vh
));
863 assert(sizeof(vh
) <= sizeof(*p
));
864 p
= (u32_t
*)ptr2acc_data(tmp_acc
);
867 vlan_pack
= bf_append(vlan_pack
, tmp_acc
);
870 vlan
= ntohs(vh
.vh_vlan
);
871 if (vlan
& ETH_TCI_CFI
)
873 /* No support for extended address formats */
874 bf_afree(vlan_pack
); vlan_pack
= NULL
;
876 vlan
&= ETH_TCI_VLAN_MASK
;
880 /* No VLAN processing */
890 eth_fd
= (i
== 0) ? eth_port
->etp_type_any
:
891 eth_port
->etp_type
[hash
];
892 for (; eth_fd
; eth_fd
= eth_fd
->ef_type_next
)
894 if (i
&& eth_fd
->ef_ethopt
.nweo_type
!= type
)
896 if (!(eth_fd
->ef_ethopt
.nweo_flags
& pack_stat
))
898 if (eth_fd
->ef_ethopt
.nweo_flags
& NWEO_REMSPEC
&&
899 eth_addrcmp(eth_hdr
->eh_src
,
900 eth_fd
->ef_ethopt
.nweo_rem
) != 0)
904 if ((eth_fd
->ef_ethopt
.nweo_flags
& NWEO_ACC_MASK
) ==
912 if (!eth_fd
->ef_rdbuf_head
)
922 packet2user(eth_fd
, pack
, exp_time
);
927 packet2user(share_fd
, pack
, exp_time
);
932 if (first_fd
->ef_put_pkt
&&
933 (first_fd
->ef_flags
& EFF_READ_IP
) &&
934 !(first_fd
->ef_ethopt
.nweo_flags
& NWEO_RWDATONLY
))
936 (*first_fd
->ef_put_pkt
)(first_fd
->ef_srfd
, pack
,
940 packet2user(first_fd
, pack
, exp_time
);
944 if (pack_stat
== NWEO_EN_LOC
)
947 printf("eth_arrive: dropping packet for proto 0x%x\n",
952 DBLOCK(0x20, printf("dropping packet for proto 0x%x\n",
959 hash
= ETH_HASH_VLAN(vlan
, temp
);
960 for (vp
= eth_port
->etp_vlan_tab
[hash
]; vp
;
961 vp
= vp
->etp_vlan_next
)
963 if (vp
->etp_vlan
== vlan
)
968 eth_arrive(vp
, vlan_pack
, pack_size
-sizeof(vh
));
973 /* No device for VLAN */
980 PUBLIC
void eth_reg_vlan(eth_port
, vlan_port
)
981 eth_port_t
*eth_port
;
982 eth_port_t
*vlan_port
;
987 vlan
= vlan_port
->etp_vlan
;
988 h
= ETH_HASH_VLAN(vlan
, t
);
989 vlan_port
->etp_vlan_next
= eth_port
->etp_vlan_tab
[h
];
990 eth_port
->etp_vlan_tab
[h
]= vlan_port
;
993 PUBLIC
void eth_restart_ioctl(eth_port
)
994 eth_port_t
*eth_port
;
999 for (i
= 0, eth_fd
= eth_fd_table
; i
<ETH_FD_NR
; i
++, eth_fd
++)
1001 if (!(eth_fd
->ef_flags
& EFF_INUSE
))
1003 if (eth_fd
->ef_port
!= eth_port
)
1005 if (!(eth_fd
->ef_flags
& EFF_IOCTL_IP
))
1007 if (eth_fd
->ef_ioctl_req
!= NWIOGETHSTAT
)
1010 eth_fd
->ef_flags
&= ~EFF_IOCTL_IP
;
1011 eth_ioctl(i
, eth_fd
->ef_ioctl_req
);
1015 PRIVATE
void packet2user (eth_fd
, pack
, exp_time
)
1024 assert (eth_fd
->ef_flags
& EFF_INUSE
);
1025 if (!(eth_fd
->ef_flags
& EFF_READ_IP
))
1027 if (pack
->acc_linkC
!= 1)
1029 tmp_pack
= bf_dupacc(pack
);
1034 pack
->acc_ext_link
= NULL
;
1035 if (eth_fd
->ef_rdbuf_head
== NULL
)
1037 eth_fd
->ef_rdbuf_head
= pack
;
1038 eth_fd
->ef_exp_time
= exp_time
;
1041 eth_fd
->ef_rdbuf_tail
->acc_ext_link
= pack
;
1042 eth_fd
->ef_rdbuf_tail
= pack
;
1046 if (eth_fd
->ef_ethopt
.nweo_flags
& NWEO_RWDATONLY
)
1047 pack
= bf_delhead(pack
, ETH_HDR_SIZE
);
1049 size
= bf_bufsize(pack
);
1051 if (eth_fd
->ef_put_pkt
)
1053 (*eth_fd
->ef_put_pkt
)(eth_fd
->ef_srfd
, pack
, size
);
1057 eth_fd
->ef_flags
&= ~EFF_READ_IP
;
1058 result
= (*eth_fd
->ef_put_userdata
)(eth_fd
->ef_srfd
, (size_t)0, pack
,
1061 reply_thr_put(eth_fd
, size
, FALSE
);
1063 reply_thr_put(eth_fd
, result
, FALSE
);
1066 PRIVATE
void eth_buffree (priority
)
1073 if (priority
== ETH_PRI_FDBUFS_EXTRA
)
1075 for (i
= 0, eth_fd
= eth_fd_table
; i
<ETH_FD_NR
; i
++, eth_fd
++)
1077 while (eth_fd
->ef_rdbuf_head
&&
1078 eth_fd
->ef_rdbuf_head
->acc_ext_link
)
1080 pack
= eth_fd
->ef_rdbuf_head
;
1081 eth_fd
->ef_rdbuf_head
= pack
->acc_ext_link
;
1086 if (priority
== ETH_PRI_FDBUFS
)
1088 for (i
= 0, eth_fd
= eth_fd_table
; i
<ETH_FD_NR
; i
++, eth_fd
++)
1090 while (eth_fd
->ef_rdbuf_head
)
1092 pack
= eth_fd
->ef_rdbuf_head
;
1093 eth_fd
->ef_rdbuf_head
= pack
->acc_ext_link
;
1100 #ifdef BUF_CONSISTENCY_CHECK
1101 PRIVATE
void eth_bufcheck()
1107 for (i
= 0; i
<eth_conf_nr
; i
++)
1109 bf_check_acc(eth_port_table
[i
].etp_rd_pack
);
1110 bf_check_acc(eth_port_table
[i
].etp_wr_pack
);
1112 for (i
= 0, eth_fd
= eth_fd_table
; i
<ETH_FD_NR
; i
++, eth_fd
++)
1114 for (pack
= eth_fd
->ef_rdbuf_head
; pack
;
1115 pack
= pack
->acc_ext_link
)
1123 PRIVATE
void do_rec_conf(eth_port
)
1124 eth_port_t
*eth_port
;
1132 if (eth_port
->etp_vlan
)
1134 /* Configure underlying device */
1135 eth_port
= eth_port
->etp_vlan_port
;
1137 flags
= compute_rec_conf(eth_port
);
1138 for (i
= 0; i
<ETH_VLAN_HASH_NR
; i
++)
1140 for (vp
= eth_port
->etp_vlan_tab
[i
]; vp
; vp
= vp
->etp_vlan_next
)
1141 flags
|= compute_rec_conf(vp
);
1143 eth_set_rec_conf(eth_port
, flags
);
1146 PRIVATE u32_t
compute_rec_conf(eth_port
)
1147 eth_port_t
*eth_port
;
1153 flags
= NWEO_NOFLAGS
;
1154 for (i
=0, eth_fd
= eth_fd_table
; i
<ETH_FD_NR
; i
++, eth_fd
++)
1156 if ((eth_fd
->ef_flags
& (EFF_INUSE
|EFF_OPTSET
)) !=
1157 (EFF_INUSE
|EFF_OPTSET
))
1161 if (eth_fd
->ef_port
!= eth_port
)
1163 flags
|= eth_fd
->ef_ethopt
.nweo_flags
;
1168 PRIVATE
void reply_thr_get (eth_fd
, result
, for_ioctl
)
1175 data
= (*eth_fd
->ef_get_userdata
)(eth_fd
->ef_srfd
, result
, 0, for_ioctl
);
1179 PRIVATE
void reply_thr_put (eth_fd
, result
, for_ioctl
)
1186 error
= (*eth_fd
->ef_put_userdata
)(eth_fd
->ef_srfd
, result
, (acc_t
*)0,
1188 assert(error
== NW_OK
);
1191 PRIVATE acc_t
*insert_vlan_hdr(eth_port
, pack
)
1192 eth_port_t
*eth_port
;
1195 acc_t
*head_acc
, *vh_acc
;
1199 head_acc
= bf_cut(pack
, 0, 2*sizeof(ether_addr_t
));
1200 pack
= bf_delhead(pack
, 2*sizeof(ether_addr_t
));
1201 pack
= bf_packIffLess(pack
, sizeof(type
));
1202 type
= *(u16_t
*)ptr2acc_data(pack
);
1203 if (type
== HTONS(ETH_VLAN_PROTO
))
1205 /* Packeted is already tagged. Should update vlan number.
1206 * For now, just discard packet.
1208 printf("insert_vlan_hdr: discarding vlan packet\n");
1209 bf_afree(head_acc
); head_acc
= NULL
;
1210 bf_afree(pack
); pack
= NULL
;
1213 vlan
= eth_port
->etp_vlan
; /* priority and CFI are zero */
1215 vh_acc
= bf_memreq(sizeof(vlan_hdr_t
));
1216 vp
= (vlan_hdr_t
*)ptr2acc_data(vh_acc
);
1217 vp
->vh_type
= HTONS(ETH_VLAN_PROTO
);
1218 vp
->vh_vlan
= htons(vlan
);
1220 head_acc
= bf_append(head_acc
, vh_acc
); vh_acc
= NULL
;
1221 head_acc
= bf_append(head_acc
, pack
); pack
= NULL
;
1222 pack
= head_acc
; head_acc
= NULL
;
1227 * $PchId: eth.c,v 1.23 2005/06/28 14:15:58 philip Exp $