From e2f503cf79af28d3283357fc61fcc34f82ad5555 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sat, 9 Apr 2016 17:38:04 +0300 Subject: [PATCH] More logging, validation, do not immediately drop packets if there is no readers active. --- sana2.cpp | 143 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 106 insertions(+), 37 deletions(-) diff --git a/sana2.cpp b/sana2.cpp index 02714127..c9588193 100644 --- a/sana2.cpp +++ b/sana2.cpp @@ -43,6 +43,8 @@ static int uaenet_getdata (void *dev, uae_u8 *d, int *len); #define MAX_ASYNC_REQUESTS 200 #define MAX_OPEN_DEVICES 20 +#define DELAYED_DROPPED_PACKET_FRAMES 100 + #define S2_START (CMD_NONSTD) // 9 #define S2_DEVICEQUERY (S2_START+ 0) // 9 #define S2_GETSTATIONADDRESS (S2_START+ 1) // 10 @@ -140,6 +142,9 @@ static int uaenet_getdata (void *dev, uae_u8 *d, int *len); #define S2_CopyFromBuff32 (S2_Dummy + 7) #define S2_DMACopyToBuff32 (S2_Dummy + 8) #define S2_DMACopyFromBuff32 (S2_Dummy + 9) +#define S2_DMACopyToBuff64 (S2_Dummy + 10) +#define S2_DMACopyFromBuff64 (S2_Dummy + 11) +#define S2_Log (S2_Dummy + 12) #define SANA2_IOREQSIZE (32 + 4 + 4 + SANA2_MAX_ADDR_BYTES * 2 + 4 + 4 + 4 + 4) @@ -147,6 +152,8 @@ struct s2packet { struct s2packet *next; uae_u8 *data; int len; + int drop_start; + int drop_count; }; static int uaenet_int_late; @@ -467,6 +474,8 @@ static uae_u32 REGPARAM2 dev_open_2 (TrapContext *ctx) while (tagpnext) { uae_u32 tag = trap_get_long(ctx, tagpnext); uae_u32 val = trap_get_long(ctx, tagpnext + 4); + if (log_net) + write_log(_T("%s:%d TAG %08x %08x\n"), getdevname(), unit, tag, val); tagp = tagpnext; tagpnext += 8; switch (tag) @@ -817,6 +826,17 @@ static struct s2packet *createreadpacket (struct s2devstruct *dev, const uae_u8 return s2p; } +static const TCHAR *dumphead(uae_u8 *d, int len) +{ + static TCHAR dumptxt[256]; + uae_u16 type = (d[2 * ADDR_SIZE] << 8) | d[2 * ADDR_SIZE + 1]; + _stprintf(dumptxt, _T("DST:%02X.%02X.%02X.%02X.%02X.%02X SRC:%02X.%02X.%02X.%02X.%02X.%02X E=%04X L=%d"), + d[0], d[1], d[2], d[3], d[4], d[5], + d[6], d[7], d[8], d[9], d[10], d[11], + type, len); + return dumptxt; +} + static int handleread (TrapContext *ctx, struct priv_s2devstruct *pdev, struct s2devstruct *dev, uae_u8 *request, uaecptr arequest, uae_u8 *d, int len, int cmd) { uae_u8 flags = get_byte_host(request + 30); @@ -863,7 +883,7 @@ static int handleread (TrapContext *ctx, struct priv_s2devstruct *pdev, struct s } if (!mc) { if (log_net) - write_log(_T("-> multicast filter rejected, CMD_READ, REQ=%08X LEN=%d\n"), arequest, len); + write_log(_T("-> %s multicast filter rejected, CMD_READ, REQ=%08X LEN=%d\n"), dumphead(d, len), arequest, len); return 0; } } @@ -871,7 +891,7 @@ static int handleread (TrapContext *ctx, struct priv_s2devstruct *pdev, struct s if (cmd == CMD_READ) { if (pdev->packetfilter && packetfilter (ctx, pdev->packetfilter, arequest, data2) == 0) { if (log_net) - write_log(_T("-> PacketFilter() rejected, CMD_READ, REQ=%08X LEN=%d\n"), arequest, len); + write_log(_T("-> %s PacketFilter() rejected, CMD_READ, REQ=%08X LEN=%d\n"), dumphead(d, len), arequest, len); return 0; } } @@ -880,7 +900,7 @@ static int handleread (TrapContext *ctx, struct priv_s2devstruct *pdev, struct s put_long_host(request + 32, S2WERR_BUFF_ERROR); put_byte_host(request + 31, S2ERR_NO_RESOURCES); if (log_net) - write_log(_T("-> CopyToBuff() rejected, CMD_READ, REQ=%08X LEN=%d\n"), arequest, len); + write_log(_T("-> %s CopyToBuff() rejected, CMD_READ, REQ=%08X LEN=%d\n"), dumphead(d, len), arequest, len); } return 1; } @@ -894,8 +914,11 @@ static void uaenet_gotdata (void *devv, const uae_u8 *d, int len) if (!dev->online) return; /* drop if bogus size */ - if (len < 20 || len >= dev->td->mtu + ETH_HEADER_SIZE + 2) + if (len < 20 || len >= dev->td->mtu + ETH_HEADER_SIZE + 2) { + if (log_net) + write_log(_T("<- invalid packet size %d\n"), len); return; + } /* drop if dst == broadcast and src == me */ if (isbroadcast (d) && !memcmp (d + 6, dev->td->mac, ADDR_SIZE)) return; @@ -907,9 +930,9 @@ static void uaenet_gotdata (void *devv, const uae_u8 *d, int len) s2p = createreadpacket (dev, d, len); if (log_net) write_log (_T("<-DST:%02X.%02X.%02X.%02X.%02X.%02X SRC:%02X.%02X.%02X.%02X.%02X.%02X E=%04X L=%d P=%p\n"), - d[0], d[1], d[2], d[3], d[4], d[5], - d[6], d[7], d[8], d[9], d[10], d[11], - type, len, s2p); + d[0], d[1], d[2], d[3], d[4], d[5], + d[6], d[7], d[8], d[9], d[10], d[11], + type, len, s2p); uae_sem_wait (&async_sem); if (!dev->readqueue) { dev->readqueue = s2p; @@ -934,8 +957,11 @@ static struct s2packet *createwritepacket(TrapContext *ctx, uae_u8 *request, uae uae_u16 packettype = get_long_host(request + 32 + 4); struct s2packet *s2p; - if (!pdev) + if (!pdev) { + if (log_net) + write_log(_T("-> createwritepacket() without device, REQ=%08X LEN=%d\n"), arequest, datalength); return NULL; + } if (!copyfrombuff (ctx, data, pdev->tempbuf, datalength, pdev->copyfrombuff)) { if (log_net) write_log(_T("-> CopyFromBuff() rejected, CMD_READ, REQ=%08X LEN=%d\n"), arequest, datalength); @@ -986,9 +1012,9 @@ static int uaenet_getdata(void *devv, uae_u8 *d, int *len) memcpy(d, ars2p->s2p->data, *len); if (log_net) write_log (_T("->DST:%02X.%02X.%02X.%02X.%02X.%02X SRC:%02X.%02X.%02X.%02X.%02X.%02X E=%04X S=%d\n"), - d[0], d[1], d[2], d[3], d[4], d[5], - d[6], d[7], d[8], d[9], d[10], d[11], - packettype, *len); + d[0], d[1], d[2], d[3], d[4], d[5], + d[6], d[7], d[8], d[9], d[10], d[11], + packettype, *len); gotit = 1; dev->packetssent++; signalasync(dev->ctx, dev, ar, *len, 0); @@ -1083,6 +1109,11 @@ static int dev_do_io_2 (TrapContext *ctx, struct s2devstruct *dev, uae_u8 *reque goto end; } } + if (statdata == 0 && (command == S2_DEVICEQUERY || command == S2_GETTYPESTATS || command == S2_GETGLOBALSTATS || command == S2_GETSPECIALSTATS)) { + io_error = S2ERR_BAD_ARGUMENT; + wire_error = S2WERR_NULL_POINTER; + goto end; + } switch (command) { @@ -1155,6 +1186,11 @@ static int dev_do_io_2 (TrapContext *ctx, struct s2devstruct *dev, uae_u8 *reque { uae_u8 statbuf[34]; int size = trap_get_long(ctx, statdata); + if (size < 8 || size >= 0x10000) { + io_error = S2ERR_BAD_ARGUMENT; + wire_error = S2WERR_BAD_STATDATA; + goto end; + } if (size > 34) size = 34; put_long_host(statbuf + 4 , size); @@ -1301,7 +1337,7 @@ toobig: } end: if (log_net && (io_error || wire_error)) - write_log (_T("-> %d (%d)\n"), io_error, wire_error); + write_log (_T("-> ERR %d (%d)\n"), io_error, wire_error); put_long_host(request + 32, wire_error); put_byte_host(request + 31, io_error); return async; @@ -1344,12 +1380,19 @@ static int dev_can_quick (uae_u32 command) case S2_GETSTATIONADDRESS: case S2_TRACKTYPE: case S2_UNTRACKTYPE: + case S2_ADDMULTICASTADDRESS: + case S2_ADDMULTICASTADDRESSES: + case S2_DELMULTICASTADDRESS: + case S2_DELMULTICASTADDRESSES: + case S2_GETTYPESTATS: + case S2_GETGLOBALSTATS: + case S2_GETSPECIALSTATS: return 1; } return 0; } -static int dev_canquick (TrapContext *ctx, struct s2devstruct *dev, uae_u8 *request) +static int dev_canquick (struct s2devstruct *dev, uae_u8 *request) { uae_u32 command = get_word_host(request + 28); return dev_can_quick (command); @@ -1359,25 +1402,29 @@ static void storerequest(TrapContext *ctx, uae_u8 *src, uaecptr dst) { uae_u32 cmd = get_word_host(src + 28); uae_u16 len = get_word_host(src + 18); - if (len < 30) + + if (len < 8) return; - len -= 30; - src += 30; - dst += 30; + // IORequest ln_Type needs to be copied + len -= 8; + src += 8; + dst += 8; if (cmd == S2_BROADCAST || cmd == S2_MULTICAST || cmd == S2_READORPHAN || cmd == CMD_WRITE || cmd == CMD_READ || cmd == S2_GETSTATIONADDRESS) { // Copy: + // IORequest // io_Flags, ioError // ios2_WireError, ios2_PacketType // ios2_SrcAddr, ios2_DstAddr // ios2_DataLength - if (len > 1 + 1 + 4 + 4 + 2 * SANA2_MAX_ADDR_BYTES + 4) - len = 1 + 1 + 4 + 4 + 2 * SANA2_MAX_ADDR_BYTES + 4; + if (len > SANA2_IOREQSIZE - (8 + 3 * 4)) + len = SANA2_IOREQSIZE - (8 + 3 * 4); trap_put_bytes(ctx, src, dst, len); } else { // Copy: + // IORequest // io_Flags, ioError // ios2_WireError - trap_put_bytes(ctx, src, dst, 1 + 1 + 4); + trap_put_bytes(ctx, src, dst, (32 - 8) + 1 + 1 + 4); } } @@ -1408,7 +1455,7 @@ static uae_u32 REGPARAM2 dev_beginio (TrapContext *ctx) goto err; } - if ((flags & 1) && dev_canquick (ctx, dev, request)) { + if ((flags & 1) && dev_canquick (dev, request)) { if (dev_do_io(ctx, dev, request, arequest, 1)) write_log (_T("%s: command %d bug with IO_QUICK\n"), SANA2NAME, command); err = get_byte_host(request + 31); @@ -1538,15 +1585,24 @@ static uae_u32 REGPARAM2 dev_abortio (TrapContext *ctx) return 0; } +static void resetpackettimer(struct s2packet *p) +{ + while (p) { + p->drop_start = 0; + p->drop_count = 0; + p = p->next; + } +} + static int uaenet_int_handler2(TrapContext *ctx) { int i, j; - int gotit; struct asyncreq *ar; bool irq = false; - for (i = 0; i < MAX_OPEN_DEVICES; i++) + for (i = 0; i < MAX_OPEN_DEVICES; i++) { pdevst[i].tmp = 0; + } for (i = 0; i < MAX_TOTAL_NET_DEVICES; i++) { struct s2devstruct *dev = &devst[i]; @@ -1557,7 +1613,6 @@ static int uaenet_int_handler2(TrapContext *ctx) p = dev->readqueue; type = (p->data[2 * ADDR_SIZE] << 8) | p->data[2 * ADDR_SIZE + 1]; ar = dev->ar; - gotit = 0; while (ar) { if (!ar->ready) { uaecptr arequest = ar->arequest; @@ -1569,8 +1624,9 @@ static int uaenet_int_handler2(TrapContext *ctx) struct priv_s2devstruct *pdev = getps2devstruct(ctx, request, arequest); if (pdev && pdev->tmp == 0) { if (handleread (ctx, pdev, dev, request, arequest, p->data, p->len, command)) { - if (log_net) - write_log (_T("-> %p Accepted, CMD_READ, REQ=%08X LEN=%d\n"), p, arequest, p->len); + if (log_net) { + write_log (_T("-> %s Accepted, CMD_READ, REQ=%08X LEN=%d D=%d\n"), dumphead(p->data, p->len), arequest, p->len, p->drop_start ? 1 : 0); + } ar->ready = 1; uae_sem_wait(&pipe_sem); trap_set_background(ctx); @@ -1581,6 +1637,7 @@ static int uaenet_int_handler2(TrapContext *ctx) dev->packetsreceived++; pdev->tmp = 1; dev->readqueue = dev->readqueue->next; + resetpackettimer(dev->readqueue); freepacket(p); return -1; } else { @@ -1602,7 +1659,7 @@ static int uaenet_int_handler2(TrapContext *ctx) struct priv_s2devstruct *pdev = getps2devstruct(ctx, request, arequest); if (pdev && pdev->tmp <= 0) { if (log_net) - write_log (_T("-> %p Accepted, S2_READORPHAN, REQ=%08X LEN=%d\n"), p, arequest, p->len); + write_log (_T("-> %s Accepted, S2_READORPHAN, REQ=%08X D=%d\n"), dumphead(p->data, p->len), arequest, p->drop_start ? 1 : 0); handleread (ctx, pdev, dev, request, arequest, p->data, p->len, command); ar->ready = 1; uae_sem_wait(&pipe_sem); @@ -1613,9 +1670,9 @@ static int uaenet_int_handler2(TrapContext *ctx) uae_sem_post(&pipe_sem); dev->packetsreceived++; dev->unknowntypesreceived++; - gotit = 1; pdev->tmp = 1; dev->readqueue = dev->readqueue->next; + resetpackettimer(dev->readqueue); freepacket(p); return -1; } @@ -1623,18 +1680,30 @@ static int uaenet_int_handler2(TrapContext *ctx) } ar = ar->next; } - if (!gotit) { - if (log_net) - write_log (_T("-> %p packet dropped, LEN=%d\n"), p, p->len); - for (j = 0; j < MAX_OPEN_DEVICES; j++) { - if (pdevst[j].unit == dev->unit) { - if (pdevst[j].tracks[type]) - pdevst[j].packetsdropped++; - } + if (p->drop_start == 0 || p->drop_count - p->drop_start < DELAYED_DROPPED_PACKET_FRAMES) { + // we got packet but there was no readers, lets wait a bit before dropping it. + if (log_net && p->drop_start == 0) { + write_log(_T("-> %s No readers, queued for dropping\n"), dumphead(p->data, p->len)); + } + while (p) { + if (p->drop_start == 0) + p->drop_start = timeframes; + p->drop_count = timeframes; + p = p->next; + } + break; + } + if (log_net) { + write_log (_T("-> %s packet dropped, CNT=%d/%d:%d\n"), dumphead(p->data, p->len), p->drop_start, p->drop_count, p->drop_count - p->drop_start); + } + for (j = 0; j < MAX_OPEN_DEVICES; j++) { + if (pdevst[j].unit == dev->unit) { + if (pdevst[j].tracks[type]) + pdevst[j].packetsdropped++; } } dev->readqueue = dev->readqueue->next; - freepacket (p); + freepacket(p); } } else { while (dev->readqueue) { -- 2.47.3