Only linearizeblock on #M qremoves
[akaros.git] / kern / drivers / dev / ether.c
index fdc7c56..4319b86 100644 (file)
 #include <smp.h>
 #include <ip.h>
 
-#include <vfs.h>
-#include <kfs.h>
-#include <slab.h>
-#include <kmalloc.h>
-#include <kref.h>
-#include <string.h>
-#include <stdio.h>
-#include <assert.h>
-#include <error.h>
-#include <cpio.h>
-#include <pmap.h>
-#include <smp.h>
-#include <ip.h>
-
 enum {
        Type8021Q = 0x8100,                     /* value of type field for 802.1[pQ] tags */
 };
@@ -265,6 +251,18 @@ static void etherrtrace(struct netfile *f, struct etherpkt *pkt, int len)
        qpass(f->in, bp);
 }
 
+#ifdef CONFIG_RISCV
+#warning "Potentially unaligned ethernet addrs!"
+#endif
+
+static inline int eaddrcmp(uint8_t *x, uint8_t *y)
+{
+       uint16_t *a = (uint16_t *)x;
+       uint16_t *b = (uint16_t *)y;
+
+       return (a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]);
+}
+
 struct block *etheriq(struct ether *ether, struct block *bp, int fromwire)
 {
        struct etherpkt *pkt;
@@ -299,7 +297,7 @@ struct block *etheriq(struct ether *ether, struct block *bp, int fromwire)
 
        multi = pkt->d[0] & 1;
        /* check for valid multcast addresses */
-       if (multi && memcmp(pkt->d, ether->netif.bcast, sizeof(pkt->d)) != 0
+       if (multi && eaddrcmp(pkt->d, ether->netif.bcast) != 0
                && ether->netif.prom == 0) {
                if (!activemulti(&ether->netif, pkt->d, sizeof(pkt->d))) {
                        if (fromwire) {
@@ -311,8 +309,8 @@ struct block *etheriq(struct ether *ether, struct block *bp, int fromwire)
        }
 
        /* is it for me? */
-       tome = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
-       fromme = memcmp(pkt->s, ether->ea, sizeof(pkt->s)) == 0;
+       tome = eaddrcmp(pkt->d, ether->ea) == 0;
+       fromme = eaddrcmp(pkt->s, ether->ea) == 0;
 
        /*
         * Multiplex the packet to all the connections which want it.
@@ -362,6 +360,8 @@ static int etheroq(struct ether *ether, struct block *bp)
 
        ether->netif.outpackets++;
 
+       if (!(ether->netif.feat & NETF_SG))
+               bp = linearizeblock(bp);
        /*
         * Check if the packet has to be placed back onto the input queue,
         * i.e. if it's a loopback or broadcast packet or the interface is
@@ -373,8 +373,8 @@ static int etheroq(struct ether *ether, struct block *bp)
         */
        pkt = (struct etherpkt *)bp->rp;
        len = BLEN(bp);
-       loopback = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
-       if (loopback || memcmp(pkt->d, ether->netif.bcast, sizeof(pkt->d)) == 0
+       loopback = eaddrcmp(pkt->d, ether->ea) == 0;
+       if (loopback || eaddrcmp(pkt->d, ether->netif.bcast) == 0
                || ether->netif.prom) {
                disable_irqsave(&irq_state);
                etheriq(ether, bp, 0);
@@ -390,6 +390,11 @@ static int etheroq(struct ether *ether, struct block *bp)
                        hnputs(bp->rp + 2 * Eaddrlen + 2, ether->vlanid & 0xFFF);       /* prio:3 0:1 vid:12 */
                        ether = ether->ctlr;
                }
+
+               if ((ether->netif.feat & NETF_PADMIN) == 0 && BLEN(bp) < ether->minmtu)
+                       bp = adjustblock(bp, ether->minmtu);
+
+               ptclcsum_finalize(bp, ether->netif.feat);
                qbwrite(ether->oq, bp);
                if (ether->transmit != NULL)
                        ether->transmit(ether);
@@ -439,8 +444,6 @@ static long etherwrite(struct chan *chan, void *buf, long n, int64_t unused)
 
        if (n > ether->maxmtu)
                error(Etoobig);
-       if (n < ether->minmtu)
-               error(Etoosmall);
        bp = allocb(n);
        if (waserror()) {
                freeb(bp);
@@ -485,10 +488,6 @@ static long etherbwrite(struct chan *chan, struct block *bp, uint32_t unused)
                freeb(bp);
                error(Etoobig);
        }
-       if (n < ether->minmtu) {
-               freeb(bp);
-               error(Etoosmall);
-       }
        n = etheroq(ether, bp);
        poperror();
        runlock(&ether->rwlock);
@@ -636,7 +635,7 @@ int parseether(uint8_t * to, char *from)
 static void etherreset(void)
 {
        struct ether *ether;
-       int i, n, ctlrno;
+       int i, n, ctlrno, qsize;
        char name[KNAMELEN], buf[128];
 
        for (ether = 0, ctlrno = 0; ctlrno < MaxEther; ctlrno++) {
@@ -681,9 +680,6 @@ static void etherreset(void)
                        ether->type = cards[n].type;
                        snprintf(name, sizeof(name), "ether%d", ctlrno);
 
-                       if (ether->interrupt != NULL)
-                               register_irq(ether->irq, ether->interrupt, ether, ether->tbdf);
-
                        i = snprintf(buf, sizeof(buf),
                                                 "#l%d: %s: %dMbps port 0x%x irq %u", ctlrno,
                                                 ether->type, ether->netif.mbps, ether->port,
@@ -704,15 +700,23 @@ static void etherreset(void)
                        snprintf(buf + i, sizeof(buf) - i, "\n");
                        printk(buf);
 
-                       if (ether->netif.mbps == 100) {
-                               netifinit(&ether->netif, name, Ntypes, 256 * 1024);
-                               if (ether->oq == 0)
-                                       ether->oq = qopen(256 * 1024, Qmsg, 0, 0);
-                       } else {
-                               netifinit(&ether->netif, name, Ntypes, 64 * 1024);
-                               if (ether->oq == 0)
-                                       ether->oq = qopen(64 * 1024, Qmsg, 0, 0);
+                       switch (ether->netif.mbps) {
+
+                       case 1 ... 99:
+                               qsize = 64 * 1024;
+                               break;
+                       case 100 ... 999:
+                               qsize = 256 * 1024;
+                               break;
+                       case 1000 ... 9999:
+                               qsize = 1024 * 1024;
+                               break;
+                       default:
+                               qsize = 8 * 1024 * 1024;
                        }
+                       netifinit(&ether->netif, name, Ntypes, qsize);
+                       if (ether->oq == 0)
+                               ether->oq = qopen(qsize, Qmsg, 0, 0);
                        if (ether->oq == 0)
                                panic("etherreset %s", name);
                        ether->netif.alen = Eaddrlen;