struct io_buffer *iobuf = NULL;
size_t len;
size_t frag_len;
+ size_t max_frag_len;
int rc;
if ( ! undinic->isr_processing ) {
/* Packet fragment received */
len = undi_isr.FrameLength;
frag_len = undi_isr.BufferLength;
+ if ( ( len == 0 ) || ( len < frag_len ) ) {
+ /* Don't laugh. VMWare does it. */
+ DBGC ( undinic, "UNDINIC %p reported insane "
+ "fragment (%zd of %zd bytes)\n",
+ undinic, frag_len, len );
+ netdev_rx_err ( netdev, NULL, -EINVAL );
+ break;
+ }
if ( ! iobuf )
iobuf = alloc_iob ( len );
if ( ! iobuf ) {
netdev_rx_err ( netdev, NULL, -ENOMEM );
goto done;
}
- if ( frag_len > iob_tailroom ( iobuf ) ) {
- DBGC ( undinic, "UNDINIC %p fragment too "
- "large\n", undinic );
- frag_len = iob_tailroom ( iobuf );
+ max_frag_len = iob_tailroom ( iobuf );
+ if ( frag_len > max_frag_len ) {
+ DBGC ( undinic, "UNDINIC %p fragment too big "
+ "(%zd+%zd does not fit into %zd)\n",
+ undinic, iob_len ( iobuf ), frag_len,
+ ( iob_len ( iobuf ) + max_frag_len ) );
+ frag_len = max_frag_len;
}
copy_from_real ( iob_put ( iobuf, frag_len ),
undi_isr.Frame.segment,
*/
if ( undinic->hacks & UNDI_HACK_EB54 )
--last_trigger_count;
+ /** HACK: effective RX quota of 1 */
+ goto done;
}
break;
case PXENV_UNDI_ISR_OUT_DONE:
done:
if ( iobuf ) {
- DBGC ( undinic, "UNDINIC %p returned incomplete packet\n",
- undinic );
+ DBGC ( undinic, "UNDINIC %p returned incomplete packet "
+ "(%zd of %zd)\n", undinic, iob_len ( iobuf ),
+ ( iob_len ( iobuf ) + iob_tailroom ( iobuf ) ) );
netdev_rx_err ( netdev, iobuf, -EINVAL );
}
}