]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
More logging, validation, do not immediately drop packets if there is no readers...
authorToni Wilen <twilen@winuae.net>
Sat, 9 Apr 2016 14:38:04 +0000 (17:38 +0300)
committerToni Wilen <twilen@winuae.net>
Sat, 9 Apr 2016 14:38:04 +0000 (17:38 +0300)
sana2.cpp

index 02714127342c3ab4233827a8f8e9d858f129f6b3..c9588193eedd46484a75d57a943044ddca896364 100644 (file)
--- 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) {