Change-Id: I9960d2e10f0b61bc0829e4aa431e1efa950f8fb5
Signed-off-by: Ronald G. Minnich <[email protected]>
---
kern/drivers/dev/Kbuild | 1 +
kern/drivers/dev/bridge.c | 676 +++++++++++++++++++++++----------------------
kern/include/ip.h | 18 ++
kern/src/net/ethermedium.c | 11 -
kern/src/net/ip.c | 10 -
kern/src/net/ipv6.c | 11 +-
6 files changed, 371 insertions(+), 356 deletions(-)
diff --git a/kern/drivers/dev/Kbuild b/kern/drivers/dev/Kbuild
index 040bab3..58bd176 100644
--- a/kern/drivers/dev/Kbuild
+++ b/kern/drivers/dev/Kbuild
@@ -1,5 +1,6 @@
obj-y += acpi.o
obj-y += alarm.o
+obj-y += bridge.o
obj-y += coreboot.o
obj-y += cons.o
obj-y += ether.o
diff --git a/kern/drivers/dev/bridge.c b/kern/drivers/dev/bridge.c
index 7cdf02e..b434cdb 100644
--- a/kern/drivers/dev/bridge.c
+++ b/kern/drivers/dev/bridge.c
@@ -10,20 +10,19 @@
/*
* IPv4 Ethernet bridge
*/
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "../ip/ip.h"
-#include "../port/netif.h"
-#include "../port/error.h"
-
-typedef struct Bridge Bridge;
-typedef struct Port Port;
-typedef struct Centry Centry;
-typedef struct Iphdr Iphdr;
-typedef struct Tcphdr Tcphdr;
+#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
{
@@ -54,17 +53,17 @@ enum
TunnelMtu = 1400,
};
-static Dirtab bridgedirtab[]={
- "ctl", {Qbctl}, 0, 0666,
- "stats", {Qstats}, 0, 0444,
- "cache", {Qcache}, 0, 0444,
- "log", {Qlog}, 0, 0666,
+static struct dirtab bridgedirtab[]={
+ {"ctl", {Qbctl}, 0, 0666},
+ {"stats", {Qstats}, 0, 0444},
+ {"cache", {Qcache}, 0, 0444},
+ {"log", {Qlog}, 0, 0666},
};
-static Dirtab portdirtab[]={
- "ctl", {Qpctl}, 0, 0666,
- "local", {Qlocal}, 0, 0444,
- "status", {Qstatus}, 0, 0444,
+static struct dirtab portdirtab[]={
+ {"ctl", {Qpctl}, 0, 0666},
+ {"local", {Qlocal}, 0, 0444},
+ {"status", {Qstatus}, 0, 0444},
};
enum {
@@ -79,22 +78,26 @@ enum
Ttun,
};
-static Logflag logflags[] =
-{
- { "cache", Logcache, },
- { "multicast", Logmcast, },
- { nil, 0, },
-};
-
-static Dirtab *dirtab[MaxQ];
-
-#define TYPE(x) (((ulong)(x).path) & 0xff)
-#define PORT(x) ((((ulong)(x).path) >> 8)&(Maxport-1))
+/* TODO
+ static Logflag logflags[] =
+ {
+ { "cache", Logcache, },
+ { "multicast", Logmcast, },
+ { NULL, 0, },
+ };
+*/
+/* TODO: we may want the log stuff someday. */
+#define log(...)
+
+static struct dirtab *dirtab[MaxQ];
+
+#define TYPE(x) (((uint32_t)(x).path) & 0xff)
+#define PORT(x) ((((uint32_t)(x).path) >> 8)&(Maxport-1))
#define QID(x, y) (((x)<<8) | (y))
struct Centry
{
- uchar d[Eaddrlen];
+ uint8_t d[Eaddrlen];
int port;
long expire; // entry expires this many seconds after bootime
long src;
@@ -103,37 +106,37 @@ struct Centry
struct Bridge
{
- QLock;
+ qlock_t qlock;
int nport;
- Port *port[Maxport];
- Centry cache[CacheSize];
- ulong hit;
- ulong miss;
- ulong copy;
+ struct Port *port[Maxport];
+ struct Centry cache[CacheSize];
+ unsigned int hit;
+ unsigned int miss;
+ unsigned int copy;
long delay0; // constant microsecond delay per packet
long delayn; // microsecond delay per byte
int tcpmss; // modify tcpmss value
- Log;
+ /* TODO Log; */
};
struct Port
{
- Ref;
+ struct kref kref;
int id;
- Bridge *bridge;
+ struct Bridge *bridge;
int closed;
- Chan *data[2]; // channel to data
+ struct chan *data[2]; // channel to data
+
+ struct proc *readp; // read proc
- Proc *readp; // read proc
-
// the following uniquely identifies the port
int type;
char name[KNAMELEN];
-
+
// owner hash - avoids bind/unbind races
- ulong ownhash;
+ uint32_t ownhash;
// various stats
int in; // number of packets read
@@ -158,111 +161,114 @@ enum {
struct Iphdr
{
- uchar vihl; /* Version and header length */
- uchar tos; /* Type of service */
- uchar length[2]; /* packet length */
- uchar id[2]; /* ip->identification */
- uchar frag[2]; /* Fragment information */
- uchar ttl; /* Time to live */
- uchar proto; /* Protocol */
- uchar cksum[2]; /* Header checksum */
- uchar src[4]; /* IP source */
- uchar dst[4]; /* IP destination */
+ uint8_t vihl; /* Version and header length */
+ uint8_t tos; /* Type of service */
+ uint8_t length[2]; /* packet length */
+ uint8_t id[2]; /* ip->identification */
+ uint8_t frag[2]; /* Fragment information */
+ uint8_t ttl; /* Time to live */
+ uint8_t proto; /* Protocol */
+ uint8_t cksum[2]; /* Header checksum */
+ uint8_t src[4]; /* IP source */
+ uint8_t dst[4]; /* IP destination */
};
struct Tcphdr
{
- uchar sport[2];
- uchar dport[2];
- uchar seq[4];
- uchar ack[4];
- uchar flag[2];
- uchar win[2];
- uchar cksum[2];
- uchar urg[2];
+ uint8_t sport[2];
+ uint8_t dport[2];
+ uint8_t seq[4];
+ uint8_t ack[4];
+ uint8_t flag[2];
+ uint8_t win[2];
+ uint8_t cksum[2];
+ uint8_t urg[2];
};
-static Bridge bridgetab[Maxbridge];
+static struct Bridge bridgetab[Maxbridge];
static int m2p[] = {
- [OREAD] 4,
- [OWRITE] 2,
- [ORDWR] 6
+ [O_READ] 4,
+ [O_WRITE] 2,
+ [O_RDWR] 6
};
-static int bridgegen(Chan *c, char*, Dirtab*, int, int s, Dir *dp);
-static void portbind(Bridge *b, int argc, char *argv[]);
-static void portunbind(Bridge *b, int argc, char *argv[]);
+static int bridgegen(struct chan *c, char*, struct dirtab*, int,
+ int s,
+ struct dir *dp);
+static void portbind(struct Bridge *b, int argc, char *argv[]);
+static void portunbind(struct Bridge *b, int argc, char *argv[]);
static void etherread(void *a);
-static char *cachedump(Bridge *b);
-static void portfree(Port *port);
-static void cacheflushport(Bridge *b, int port);
-static void etherwrite(Port *port, Block *bp);
+static char *cachedump(struct Bridge *b);
+static void portfree(struct kref *);
+static void cacheflushport(struct Bridge *b, int port);
+static void etherwrite(struct Port *port, struct block *bp);
static void
bridgeinit(void)
{
int i;
- Dirtab *dt;
-
+ struct dirtab *dt;
+
// setup dirtab with non directory entries
- for(i=0; i<nelem(bridgedirtab); i++) {
+ for(i=0; i<COUNT_OF(bridgedirtab); i++) {
dt = bridgedirtab + i;
dirtab[TYPE(dt->qid)] = dt;
}
- for(i=0; i<nelem(portdirtab); i++) {
+ for(i=0; i<COUNT_OF(portdirtab); i++) {
dt = portdirtab + i;
dirtab[TYPE(dt->qid)] = dt;
}
}
-static Chan*
+static struct chan*
bridgeattach(char* spec)
{
- Chan *c;
+ ERRSTACK(1);
+ struct chan *c;
int dev;
dev = atoi(spec);
if(dev<0 || dev >= Maxbridge)
- error("bad specification");
+ error(EINVAL, "bad specification");
- c = devattach('B', spec);
+ c = devattach("bridge", spec);
mkqid(&c->qid, QID(0, Qtopdir), 0, QTDIR);
c->dev = dev;
return c;
}
-static Walkqid*
-bridgewalk(Chan *c, Chan *nc, char **name, int nname)
+static struct walkqid*
+bridgewalk(struct chan *c, struct chan *nc, char **name, int nname)
{
- return devwalk(c, nc, name, nname, (Dirtab*)0, 0, bridgegen);
+ return devwalk(c, nc, name, nname, (struct dirtab*)0, 0, bridgegen);
}
static int
-bridgestat(Chan* c, uchar* db, int n)
+bridgestat(struct chan* c, uint8_t* db, int n)
{
- return devstat(c, db, n, (Dirtab *)0, 0L, bridgegen);
+ return devstat(c, db, n, (struct dirtab *)0, 0L, bridgegen);
}
-static Chan*
-bridgeopen(Chan* c, int omode)
+static struct chan*
+bridgeopen(struct chan* c, int omode)
{
int perm;
- Bridge *b;
+ struct Bridge *b;
omode &= 3;
perm = m2p[omode];
- USED(perm);
b = bridgetab + c->dev;
- USED(b);
switch(TYPE(c->qid)) {
default:
break;
- case Qlog:
- logopen(b);
- break;
+ /* TODO: we might want log someday?
+ case Qlog:
+ logopen(b);
+ break;
+ */
case Qcache:
c->aux = cachedump(b);
break;
@@ -274,122 +280,127 @@ bridgeopen(Chan* c, int omode)
}
static void
-bridgeclose(Chan* c)
+bridgeclose(struct chan* c)
{
- Bridge *b = bridgetab + c->dev;
+ struct Bridge *b = bridgetab + c->dev;
switch(TYPE(c->qid)) {
case Qcache:
if(c->flag & COPEN)
- free(c->aux);
- break;
- case Qlog:
- if(c->flag & COPEN)
- logclose(b);
+ kfree(c->aux);
break;
+ /* TODO
+ * case Qlog:
+ if(c->flag & COPEN)
+ logclose(b);
+ break;
+ */
}
}
static long
-bridgeread(Chan *c, void *a, long n, vlong off)
+bridgeread(struct chan *c, void *a, long n, int64_t off)
{
+ ERRSTACK(1);
char buf[256];
- Bridge *b = bridgetab + c->dev;
- Port *port;
+ struct Bridge *b = bridgetab + c->dev;
+ struct Port *port;
int i, ingood, outgood;
- USED(off);
switch(TYPE(c->qid)) {
default:
- error(Egreg);
+ error(EINVAL, "bridgeread: bad qid");
case Qtopdir:
case Qbridgedir:
case Qportdir:
return devdirread(c, a, n, 0, 0, bridgegen);
- case Qlog:
- return logread(b, a, off, n);
+ /* TODO
+ case Qlog:
+ return logread(b, a, off, n);
+ */
case Qlocal:
return 0; /* TO DO */
case Qstatus:
- qlock(b);
+ qlock(&b->qlock);
if(waserror()){
- qunlock(b);
+ qunlock(&b->qlock);
nexterror();
}
port = b->port[PORT(c->qid)];
if(port == 0)
- strcpy(buf, "unbound\n");
+ strncpy(buf, "unbound\n", sizeof(buf));
else {
i = 0;
switch(port->type) {
default:
panic("bridgeread: unknown port type: %d",
- port->type);
+ port->type);
case Tether:
- i += snprint(buf+i, sizeof(buf)-i, "ether %s:
", port->name);
+ i += snprintf(buf+i, sizeof(buf)-i, "ether %s:
", port->name);
break;
case Ttun:
- i += snprint(buf+i, sizeof(buf)-i, "tunnel %s:
", port->name);
+ i += snprintf(buf+i, sizeof(buf)-i, "tunnel %s:
", port->name);
break;
}
ingood = port->in - port->inmulti - port->inunknown;
outgood = port->out - port->outmulti - port->outunknown;
- snprint(buf+i, sizeof(buf)-i,
- "in=%d(%d:%d:%d) out=%d(%d:%d:%d:%d)\n",
- port->in, ingood, port->inmulti,
port->inunknown,
- port->out, outgood, port->outmulti,
- port->outunknown, port->outfrag);
+ snprintf(buf+i, sizeof(buf)-i,
+ "in=%d(%d:%d:%d)
out=%d(%d:%d:%d:%d)\n",
+ port->in, ingood, port->inmulti,
port->inunknown,
+ port->out, outgood, port->outmulti,
+ port->outunknown, port->outfrag);
}
poperror();
- qunlock(b);
+ qunlock(&b->qlock);
return readstr(off, a, n, buf);
case Qbctl:
- snprint(buf, sizeof(buf), "%s tcpmss\ndelay %ld %ld\n",
- b->tcpmss ? "set" : "clear", b->delay0, b->delayn);
+ snprintf(buf, sizeof(buf), "%s tcpmss\ndelay %ld %ld\n",
+ b->tcpmss ? "set" : "clear", b->delay0,
b->delayn);
n = readstr(off, a, n, buf);
return n;
case Qcache:
n = readstr(off, a, n, c->aux);
return n;
case Qstats:
- snprint(buf, sizeof(buf), "hit=%uld miss=%uld copy=%uld\n",
- b->hit, b->miss, b->copy);
+ snprintf(buf, sizeof(buf), "hit=%uld miss=%uld copy=%uld\n",
+ b->hit, b->miss, b->copy);
n = readstr(off, a, n, buf);
return n;
}
}
static void
-bridgeoption(Bridge *b, char *option, int value)
+bridgeoption(struct Bridge *b, char *option, int value)
{
+ ERRSTACK(1);
if(strcmp(option, "tcpmss") == 0)
b->tcpmss = value;
else
- error("unknown bridge option");
+ error(EINVAL, "unknown bridge option");
}
static long
-bridgewrite(Chan *c, void *a, long n, vlong off)
+bridgewrite(struct chan *c, void *a, long n, int64_t off)
{
- Bridge *b = bridgetab + c->dev;
- Cmdbuf *cb;
+ ERRSTACK(1);
+ struct Bridge *b = bridgetab + c->dev;
+ struct cmdbuf *cb;
char *arg0, *p;
- USED(off);
switch(TYPE(c->qid)) {
default:
- error(Eperm);
+ error(EPERM, "Permission denied");
case Qbctl:
cb = parsecmd(a, n);
- qlock(b);
+ qlock(&b->qlock);
if(waserror()) {
- qunlock(b);
- free(cb);
+ qunlock(&b->qlock);
+ kfree(cb);
nexterror();
}
if(cb->nf == 0)
- error("short write");
+ error(EIO, "short write");
arg0 = cb->f[0];
if(strcmp(arg0, "bind") == 0) {
portbind(b, cb->nf-1, cb->f+1);
@@ -397,56 +408,59 @@ bridgewrite(Chan *c, void *a, long n, vlong off)
portunbind(b, cb->nf-1, cb->f+1);
} else if(strcmp(arg0, "cacheflush") == 0) {
log(b, Logcache, "cache flush\n");
- memset(b->cache, 0, CacheSize*sizeof(Centry));
+ memset(b->cache, 0, CacheSize*sizeof(struct Centry));
} else if(strcmp(arg0, "set") == 0) {
if(cb->nf != 2)
- error("usage: set option");
+ error(EINVAL, "usage: set option");
bridgeoption(b, cb->f[1], 1);
} else if(strcmp(arg0, "clear") == 0) {
if(cb->nf != 2)
- error("usage: clear option");
+ error(EINVAL, "usage: clear option");
bridgeoption(b, cb->f[1], 0);
} else if(strcmp(arg0, "delay") == 0) {
if(cb->nf != 3)
- error("usage: delay delay0 delayn");
- b->delay0 = strtol(cb->f[1], nil, 10);
- b->delayn = strtol(cb->f[2], nil, 10);
+ error(EINVAL, "usage: delay delay0 delayn");
+ b->delay0 = strtol(cb->f[1], NULL, 10);
+ b->delayn = strtol(cb->f[2], NULL, 10);
} else
- error("unknown control request");
+ error(EINVAL, "unknown control request");
poperror();
- qunlock(b);
- free(cb);
+ qunlock(&b->qlock);
+ kfree(cb);
return n;
case Qlog:
- cb = parsecmd(a, n);
- p = logctl(b, cb->nf, cb->f, logflags);
- free(cb);
- if(p != nil)
- error(p);
- return n;
+ error(EINVAL, "logflag not supported");
+ /* TODO
+ cb = parsecmd(a, n);
+ p = logctl(b, cb->nf, cb->f, logflags);
+ free(cb);
+ if(p != NULL)
+ error(p);
+ return n;
+ */
}
}
static int
-bridgegen(Chan *c, char *, Dirtab*, int, int s, Dir *dp)
+bridgegen(struct chan *c, char *_, struct dirtab*__, int ___, int s, struct
dir *dp)
{
- Bridge *b = bridgetab + c->dev;
+ struct Bridge *b = bridgetab + c->dev;
int type = TYPE(c->qid);
- Dirtab *dt;
- Qid qid;
+ struct dirtab *dt;
+ struct qid qid;
if(s == DEVDOTDOT){
switch(TYPE(c->qid)){
case Qtopdir:
case Qbridgedir:
- snprint(up->genbuf, sizeof(up->genbuf), "#B%ld",
c->dev);
+ snprintf(get_cur_genbuf(), GENBUF_SZ, "#B%ld", c->dev);
mkqid(&qid, Qtopdir, 0, QTDIR);
- devdir(c, qid, up->genbuf, 0, eve, 0555, dp);
+ devdir(c, qid, get_cur_genbuf(), 0, eve, 0555, dp);
break;
case Qportdir:
- snprint(up->genbuf, sizeof(up->genbuf), "bridge%ld",
c->dev);
+ snprintf(get_cur_genbuf(), GENBUF_SZ, "bridge%ld",
c->dev);
mkqid(&qid, Qbridgedir, 0, QTDIR);
- devdir(c, qid, up->genbuf, 0, eve, 0555, dp);
+ devdir(c, qid, get_cur_genbuf(), 0, eve, 0555, dp);
break;
default:
panic("bridgewalk %llux", c->qid.path);
@@ -462,32 +476,32 @@ bridgegen(Chan *c, char *, Dirtab*, int, int s, Dir *dp)
if(s != 0)
return -1;
dt = dirtab[TYPE(c->qid)];
- if(dt == nil)
+ if(dt == NULL)
panic("bridgegen: unknown type: %lud", TYPE(c->qid));
devdir(c, c->qid, dt->name, dt->length, eve, dt->perm, dp);
return 1;
case Qtopdir:
if(s != 0)
return -1;
- snprint(up->genbuf, sizeof(up->genbuf), "bridge%ld", c->dev);
+ snprintf(get_cur_genbuf(), GENBUF_SZ, "bridge%ld", c->dev);
mkqid(&qid, QID(0, Qbridgedir), 0, QTDIR);
- devdir(c, qid, up->genbuf, 0, eve, 0555, dp);
+ devdir(c, qid, get_cur_genbuf(), 0, eve, 0555, dp);
return 1;
case Qbridgedir:
- if(s<nelem(bridgedirtab)) {
+ if(s<COUNT_OF(bridgedirtab)) {
dt = bridgedirtab+s;
devdir(c, dt->qid, dt->name, dt->length, eve, dt->perm,
dp);
return 1;
}
- s -= nelem(bridgedirtab);
+ s -= COUNT_OF(bridgedirtab);
if(s >= b->nport)
return -1;
mkqid(&qid, QID(s, Qportdir), 0, QTDIR);
- snprint(up->genbuf, sizeof(up->genbuf), "%d", s);
- devdir(c, qid, up->genbuf, 0, eve, 0555, dp);
+ snprintf(get_cur_genbuf(), GENBUF_SZ, "%d", s);
+ devdir(c, qid, get_cur_genbuf(), 0, eve, 0555, dp);
return 1;
case Qportdir:
- if(s>=nelem(portdirtab))
+ if(s>=COUNT_OF(portdirtab))
return -1;
dt = portdirtab+s;
mkqid(&qid, QID(PORT(c->qid),TYPE(dt->qid)), 0, QTFILE);
@@ -498,7 +512,7 @@ bridgegen(Chan *c, char *, Dirtab*, int, int s, Dir *dp)
// parse mac address; also in netif.c
static int
-parseaddr(uchar *to, char *from, int alen)
+parseaddr(uint8_t *to, char *from, int alen)
{
char nip[4];
char *p;
@@ -522,56 +536,57 @@ parseaddr(uchar *to, char *from, int alen)
// assumes b is locked
static void
-portbind(Bridge *b, int argc, char *argv[])
+portbind(struct Bridge *b, int argc, char *argv[])
{
- Port *port;
- Chan *ctl;
+ ERRSTACK(2);
+ struct Port *port;
+ struct chan *ctl;
int type = 0, i, n;
- ulong ownhash;
- char *dev, *dev2 = nil;
+ uint32_t ownhash;
+ char *dev, *dev2 = NULL;
char buf[100], name[KNAMELEN], path[8*KNAMELEN];
static char usage[] = "usage: bind ether|tunnel name ownhash dev
[dev2]";
memset(name, 0, KNAMELEN);
if(argc < 4)
- error(usage);
+ error(EINVAL, usage);
if(strcmp(argv[0], "ether") == 0) {
if(argc != 4)
- error(usage);
+ error(EINVAL, usage);
type = Tether;
strncpy(name, argv[1], KNAMELEN);
name[KNAMELEN-1] = 0;
// parseaddr(addr, argv[1], Eaddrlen);
} else if(strcmp(argv[0], "tunnel") == 0) {
if(argc != 5)
- error(usage);
+ error(EINVAL, usage);
type = Ttun;
strncpy(name, argv[1], KNAMELEN);
name[KNAMELEN-1] = 0;
// parseip(addr, argv[1]);
dev2 = argv[4];
} else
- error(usage);
+ error(EINVAL, usage);
ownhash = atoi(argv[2]);
dev = argv[3];
for(i=0; i<b->nport; i++) {
port = b->port[i];
- if(port != nil && port->type == type &&
- memcmp(port->name, name, KNAMELEN) == 0)
- error("port in use");
+ if(port != NULL && port->type == type &&
+ memcmp(port->name, name, KNAMELEN) == 0)
+ error(EBUSY, "port in use");
}
for(i=0; i<Maxport; i++)
- if(b->port[i] == nil)
+ if(b->port[i] == NULL)
break;
if(i == Maxport)
- error("no more ports");
- port = smalloc(sizeof(Port));
- port->ref = 1;
+ error(EAGAIN, "no more ports");
+ port = kzmalloc(sizeof(struct Port), 0);
+ kref_init(&port->kref, portfree, 1);
port->id = i;
port->ownhash = ownhash;
if(waserror()) {
- portfree(port);
+ kref_put(&port->kref);
nexterror();
}
port->type = type;
@@ -580,8 +595,8 @@ portbind(Bridge *b, int argc, char *argv[])
default:
panic("portbind: unknown port type: %d", type);
case Tether:
- snprint(path, sizeof(path), "%s/clone", dev);
- ctl = namec(path, Aopen, ORDWR, 0);
+ snprintf(path, sizeof(path), "%s/clone", dev);
+ ctl = namec(path, Aopen, O_RDWR, 0);
if(waserror()) {
cclose(ctl);
nexterror();
@@ -589,22 +604,22 @@ portbind(Bridge *b, int argc, char *argv[])
// check addr?
// get directory name
- n = devtab[ctl->type]->read(ctl, buf, sizeof(buf)-1, 0);
+ n = devtab[ctl->type].read(ctl, buf, sizeof(buf)-1, 0);
buf[n] = 0;
- snprint(path, sizeof(path), "%s/%lud/data", dev, strtoul(buf,
0, 0));
+ snprintf(path, sizeof(path), "%s/%lud/data", dev, strtoul(buf,
0, 0));
// setup connection to be promiscuous
- snprint(buf, sizeof(buf), "connect -1");
- devtab[ctl->type]->write(ctl, buf, strlen(buf), 0);
- snprint(buf, sizeof(buf), "promiscuous");
- devtab[ctl->type]->write(ctl, buf, strlen(buf), 0);
- snprint(buf, sizeof(buf), "bridge");
- devtab[ctl->type]->write(ctl, buf, strlen(buf), 0);
+ snprintf(buf, sizeof(buf), "connect -1");
+ devtab[ctl->type].write(ctl, buf, strlen(buf), 0);
+ snprintf(buf, sizeof(buf), "promiscuous");
+ devtab[ctl->type].write(ctl, buf, strlen(buf), 0);
+ snprintf(buf, sizeof(buf), "bridge");
+ devtab[ctl->type].write(ctl, buf, strlen(buf), 0);
// open data port
- port->data[0] = namec(path, Aopen, ORDWR, 0);
+ port->data[0] = namec(path, Aopen, O_RDWR, 0);
// dup it
- incref(port->data[0]);
+ chan_incref(port->data[0]);
port->data[1] = port->data[0];
poperror();
@@ -612,8 +627,8 @@ portbind(Bridge *b, int argc, char *argv[])
break;
case Ttun:
- port->data[0] = namec(dev, Aopen, OREAD, 0);
- port->data[1] = namec(dev2, Aopen, OWRITE, 0);
+ port->data[0] = namec(dev, Aopen, O_READ, 0);
+ port->data[1] = namec(dev2, Aopen, O_WRITE, 0);
break;
}
@@ -626,24 +641,27 @@ portbind(Bridge *b, int argc, char *argv[])
b->nport = port->id+1;
// assumes kproc always succeeds
- incref(port);
- snprint(buf, sizeof(buf), "bridge:%s", dev);
- kproc(buf, etherread, port);
+ kref_get(&port->kref, 1);
+ snprintf(buf, sizeof(buf), "bridge:%s", dev);
+ panic("Starting bridge kproc");
+ // TODO: kproc? What do we do?
+// kproc(buf, etherread, port);
}
// assumes b is locked
static void
-portunbind(Bridge *b, int argc, char *argv[])
+portunbind(struct Bridge *b, int argc, char *argv[])
{
+ ERRSTACK(1);
int type = 0, i;
char name[KNAMELEN];
- ulong ownhash;
- Port *port = nil;
+ uint32_t ownhash;
+ struct Port *port = NULL;
static char usage[] = "usage: unbind ether|tunnel addr [ownhash]";
memset(name, 0, KNAMELEN);
if(argc < 2 || argc > 3)
- error(usage);
+ error(EINVAL, usage);
if(strcmp(argv[0], "ether") == 0) {
type = Tether;
strncpy(name, argv[1], KNAMELEN);
@@ -655,39 +673,41 @@ portunbind(Bridge *b, int argc, char *argv[])
name[KNAMELEN-1] = 0;
// parseip(addr, argv[1]);
} else
- error(usage);
+ error(EINVAL, usage);
if(argc == 3)
ownhash = atoi(argv[2]);
else
ownhash = 0;
for(i=0; i<b->nport; i++) {
port = b->port[i];
- if(port != nil && port->type == type &&
- memcmp(port->name, name, KNAMELEN) == 0)
+ if(port != NULL && port->type == type &&
+ memcmp(port->name, name, KNAMELEN) == 0)
break;
}
if(i == b->nport)
- error("port not found");
+ error(ESRCH, "port not found");
if(ownhash != 0 && port->ownhash != 0 && ownhash != port->ownhash)
- error("bad owner hash");
+ error(EINVAL, "bad owner hash");
port->closed = 1;
- b->port[i] = nil; // port is now unbound
+ b->port[i] = NULL; // port is now unbound
cacheflushport(b, i);
// try and stop reader
- if(port->readp)
- postnote(port->readp, 1, "unbind", 0);
- portfree(port);
+ /* TODO
+ if(port->readp)
+ postnote(port->readp, 1, "unbind", 0);
+ */
+ kref_put(&port->kref);
}
// assumes b is locked
-static Centry *
-cachelookup(Bridge *b, uchar d[Eaddrlen])
+static struct Centry *
+cachelookup(struct Bridge *b, uint8_t d[Eaddrlen])
{
int i;
- uint h;
- Centry *p;
+ unsigned int h;
+ struct Centry *p;
long sec;
// dont cache multicast or broadcast
@@ -701,30 +721,30 @@ cachelookup(Bridge *b, uchar d[Eaddrlen])
}
h %= CacheHash;
p = b->cache + h;
- sec = TK2SEC(m->ticks);
+ sec = seconds();
for(i=0; i<CacheLook; i++,p++) {
if(memcmp(d, p->d, Eaddrlen) == 0) {
p->dst++;
if(sec >= p->expire) {
log(b, Logcache, "expired cache entry: %E %d\n",
d, p->port);
- return nil;
+ return NULL;
}
p->expire = sec + CacheTimeout;
return p;
}
}
log(b, Logcache, "cache miss: %E\n", d);
- return nil;
+ return NULL;
}
// assumes b is locked
static void
-cacheupdate(Bridge *b, uchar d[Eaddrlen], int port)
+cacheupdate(struct Bridge *b, uint8_t d[Eaddrlen], int port)
{
int i;
- uint h;
- Centry *p, *pp;
+ unsigned int h;
+ struct Centry *p, *pp;
long sec;
// dont cache multicast or broadcast
@@ -746,7 +766,7 @@ cacheupdate(Bridge *b, uchar d[Eaddrlen], int port)
// look for oldest entry
for(i=0; i<CacheLook; i++,p++) {
if(memcmp(p->d, d, Eaddrlen) == 0) {
- p->expire = TK2SEC(m->ticks) + CacheTimeout;
+ p->expire = seconds() + CacheTimeout;
if(p->port != port) {
log(b, Logcache, "NIC changed port %d->%d:
%E\n",
p->port, port, d);
@@ -762,7 +782,7 @@ cacheupdate(Bridge *b, uchar d[Eaddrlen], int port)
}
if(pp->expire != 0)
log(b, Logcache, "bumping from cache: %E %d\n", pp->d,
pp->port);
- pp->expire = TK2SEC(m->ticks) + CacheTimeout;
+ pp->expire = seconds() + CacheTimeout;
memmove(pp->d, d, Eaddrlen);
pp->port = port;
pp->src = 1;
@@ -772,34 +792,35 @@ cacheupdate(Bridge *b, uchar d[Eaddrlen], int port)
// assumes b is locked
static void
-cacheflushport(Bridge *b, int port)
+cacheflushport(struct Bridge *b, int port)
{
- Centry *ce;
+ struct Centry *ce;
int i;
ce = b->cache;
for(i=0; i<CacheSize; i++,ce++) {
if(ce->port != port)
continue;
- memset(ce, 0, sizeof(Centry));
+ memset(ce, 0, sizeof(struct Centry));
}
}
static char *
-cachedump(Bridge *b)
+cachedump(struct Bridge *b)
{
+ ERRSTACK(1);
int i, n;
long sec, off;
char *buf, *p, *ep;
- Centry *ce;
+ struct Centry *ce;
char c;
- qlock(b);
+ qlock(&b->qlock);
if(waserror()) {
- qunlock(b);
+ qunlock(&b->qlock);
nexterror();
}
- sec = TK2SEC(m->ticks);
+ sec = seconds();
n = 0;
for(i=0; i<CacheSize; i++)
if(b->cache[i].expire != 0)
@@ -807,9 +828,9 @@ cachedump(Bridge *b)
n *= 51; // change if print format is changed
n += 10; // some slop at the end
- buf = malloc(n);
- if(buf == nil)
- error(Enomem);
+ buf = kzmalloc(n, 0);
+ if(buf == NULL)
+ error(ENOMEM, "cachedump: out of memory");
p = buf;
ep = buf + n;
ce = b->cache;
@@ -818,12 +839,12 @@ cachedump(Bridge *b)
if(ce->expire == 0)
continue;
c = (sec < ce->expire)?'v':'e';
- p += snprint(p, ep-p, "%E %2d %10ld %10ld %10ld %c\n", ce->d,
- ce->port, ce->src, ce->dst, ce->expire+off, c);
+ p += snprintf(p, ep-p, "%E %2d %10ld %10ld %10ld %c\n", ce->d,
+ ce->port, ce->src, ce->dst,
ce->expire+off, c);
}
*p = 0;
poperror();
- qunlock(b);
+ qunlock(&b->qlock);
return buf;
}
@@ -832,18 +853,18 @@ cachedump(Bridge *b)
// assumes b is locked, no error return
static void
-ethermultiwrite(Bridge *b, Block *bp, Port *port)
+ethermultiwrite(struct Bridge *b, struct block *bp, struct Port *port)
{
- Port *oport;
- Etherpkt *ep;
+ struct Port *oport;
+ struct etherpkt *ep;
int i, mcast;
- ep = (Etherpkt*)bp->rp;
+ ep = (struct etherpkt*)bp->rp;
mcast = ep->d[0] & 1; /* multicast bit of ethernet address */
- oport = nil;
+ oport = NULL;
for(i=0; i<b->nport; i++) {
- if(i == port->id || b->port[i] == nil)
+ if(i == port->id || b->port[i] == NULL)
continue;
/*
* we need to forward multicast packets for ipv6,
@@ -855,7 +876,7 @@ ethermultiwrite(Bridge *b, Block *bp, Port *port)
b->port[i]->outunknown++;
// delay one so that the last write does not copy
- if(oport != nil) {
+ if(oport != NULL) {
b->copy++;
etherwrite(oport, copyblock(bp, blocklen(bp)));
}
@@ -870,18 +891,18 @@ ethermultiwrite(Bridge *b, Block *bp, Port *port)
}
static void
-tcpmsshack(Etherpkt *epkt, int n)
+tcpmsshack(struct etherpkt *epkt, int n)
{
int hl, optlen;
- Iphdr *iphdr;
- Tcphdr *tcphdr;
- ulong mss, cksum;
- uchar *optr;
+ struct Iphdr *iphdr;
+ struct Tcphdr *tcphdr;
+ uint32_t mss, cksum;
+ uint8_t *optr;
/* ignore non-ipv4 packets */
if(nhgets(epkt->type) != ETIP4)
return;
- iphdr = (Iphdr*)(epkt->data);
+ iphdr = (struct Iphdr*)(epkt->data);
n -= ETHERHDRSIZE;
if(n < IPHDR)
return;
@@ -898,9 +919,9 @@ tcpmsshack(Etherpkt *epkt, int n)
if(iphdr->proto != IP_TCPPROTO)
return;
n -= hl;
- if(n < sizeof(Tcphdr))
+ if(n < sizeof(struct Tcphdr))
return;
- tcphdr = (Tcphdr*)((uchar*)(iphdr) + hl);
+ tcphdr = (struct Tcphdr*)((uint8_t*)(iphdr) + hl);
// MSS can only appear in SYN packet
if(!(tcphdr->flag[1] & SYN))
return;
@@ -909,8 +930,8 @@ tcpmsshack(Etherpkt *epkt, int n)
return;
// check for MSS option
- optr = (uchar*)tcphdr + sizeof(Tcphdr);
- n = hl - sizeof(Tcphdr);
+ optr = (uint8_t*)tcphdr + sizeof(struct Tcphdr);
+ n = hl - sizeof(struct Tcphdr);
for(;;) {
if(n <= 0 || *optr == EOLOPT)
return;
@@ -933,8 +954,8 @@ tcpmsshack(Etherpkt *epkt, int n)
return;
// fit checksum
cksum = nhgets(tcphdr->cksum);
- if(optr-(uchar*)tcphdr & 1) {
-print("tcpmsshack: odd alignment!\n");
+ if((optr-(uint8_t*)tcphdr) & 1) {
+ printd("tcpmsshack: odd alignment!\n");
// odd alignments are a pain
cksum += nhgets(optr+1);
cksum -= (optr[1]<<8)|(TcpMssMax>>8);
@@ -958,28 +979,29 @@ print("tcpmsshack: odd alignment!\n");
static void
etherread(void *a)
{
- Port *port = a;
- Bridge *b = port->bridge;
- Block *bp;
- Etherpkt *ep;
- Centry *ce;
+ ERRSTACK(1);
+ struct Port *port = a;
+ struct Bridge *b = port->bridge;
+ struct block *bp;
+ struct etherpkt *ep;
+ struct Centry *ce;
long md, n;
- qlock(b);
- port->readp = up; /* hide identity under a rock for unbind */
+ qlock(&b->qlock);
+ port->readp = current; /* hide identity under a rock for unbind */
while(!port->closed){
// release lock to read - error means it is time to quit
- qunlock(b);
+ qunlock(&b->qlock);
if(waserror()) {
- print("etherread read error: %s\n", up->errstr);
- qlock(b);
+ printd("etherread read error: %s\n", up->errstr);
+ qlock(&b->qlock);
break;
}
- bp = devtab[port->data[0]->type]->bread(port->data[0], MaxMTU,
0);
+ bp = devtab[port->data[0]->type].bread(port->data[0], MaxMTU,
0);
poperror();
- qlock(b);
- if(bp == nil)
+ qlock(&b->qlock);
+ if(bp == NULL)
break;
n = blocklen(bp);
if(port->closed || n < ETHERMINTU){
@@ -993,7 +1015,7 @@ etherread(void *a)
}
port->in++;
- ep = (Etherpkt*)bp->rp;
+ ep = (struct etherpkt*)bp->rp;
cacheupdate(b, ep->s, port->id);
if(b->tcpmss)
tcpmsshack(ep, n);
@@ -1016,7 +1038,7 @@ etherread(void *a)
ethermultiwrite(b, bp, port);
} else {
ce = cachelookup(b, ep->d);
- if(ce == nil) {
+ if(ce == NULL) {
b->miss++;
port->inunknown++;
ethermultiwrite(b, bp, port);
@@ -1028,16 +1050,18 @@ etherread(void *a)
}
}
// print("etherread: trying to exit\n");
- port->readp = nil;
- portfree(port);
- qunlock(b);
- pexit("hangup", 1);
+ port->readp = NULL;
+ kref_put(&port->kref);
+ qunlock(&b->qlock);
+ // TODO: pexit?
+ panic("calling pexit");
+ //pexit("hangup", 1);
}
static int
-fragment(Etherpkt *epkt, int n)
+fragment(struct etherpkt *epkt, int n)
{
- Iphdr *iphdr;
+ struct Iphdr *iphdr;
if(n <= TunnelMtu)
return 0;
@@ -1045,7 +1069,7 @@ fragment(Etherpkt *epkt, int n)
/* ignore non-ipv4 packets */
if(nhgets(epkt->type) != ETIP4)
return 0;
- iphdr = (Iphdr*)(epkt->data);
+ iphdr = (struct Iphdr*)(epkt->data);
n -= ETHERHDRSIZE;
/*
* ignore: IP runt packets, bad packets (I don't handle IP
@@ -1053,27 +1077,28 @@ fragment(Etherpkt *epkt, int n)
* and short blocks.
*/
if(n < IPHDR || iphdr->vihl != (IP_VER4|IP_HLEN4) ||
- iphdr->frag[0] & (IP_DF>>8) || nhgets(iphdr->length) > n)
+ iphdr->frag[0] & (IP_DF>>8) || nhgets(iphdr->length) > n)
return 0;
return 1;
}
static void
-etherwrite(Port *port, Block *bp)
+etherwrite(struct Port *port, struct block *bp)
{
- Iphdr *eh, *feh;
- Etherpkt *epkt;
+ ERRSTACK(2);
+ struct Iphdr *eh, *feh;
+ struct etherpkt *epkt;
int n, lid, len, seglen, chunk, dlen, blklen, offset, mf;
- Block *xp, *nb;
- ushort fragoff, frag;
+ struct block *xp, *nb;
+ uint16_t fragoff, frag;
port->out++;
- epkt = (Etherpkt*)bp->rp;
+ epkt = (struct etherpkt*)bp->rp;
n = blocklen(bp);
if(port->type != Ttun || !fragment(epkt, n)) {
if(!waserror()){
- devtab[port->data[1]->type]->bwrite(port->data[1], bp,
0);
+ devtab[port->data[1]->type].bwrite(port->data[1], bp,
0);
poperror();
}
return;
@@ -1085,7 +1110,7 @@ etherwrite(Port *port, Block *bp)
}
seglen = (TunnelMtu - ETHERHDRSIZE - IPHDR) & ~7;
- eh = (Iphdr*)(epkt->data);
+ eh = (struct Iphdr*)(epkt->data);
len = nhgets(eh->length);
frag = nhgets(eh->frag);
mf = frag & IP_MF;
@@ -1094,19 +1119,19 @@ etherwrite(Port *port, Block *bp)
xp = bp;
lid = nhgets(eh->id);
offset = ETHERHDRSIZE+IPHDR;
- while(xp != nil && offset && offset >= BLEN(xp)) {
+ while(xp != NULL && offset && offset >= BLEN(xp)) {
offset -= BLEN(xp);
xp = xp->next;
}
xp->rp += offset;
if(0)
- print("seglen=%d, dlen=%d, mf=%x, frag=%d\n",
- seglen, dlen, mf, frag);
+ printd("seglen=%d, dlen=%d, mf=%x, frag=%d\n",
+ seglen, dlen, mf, frag);
for(fragoff = 0; fragoff < dlen; fragoff += seglen) {
- nb = allocb(ETHERHDRSIZE+IPHDR+seglen);
+ nb = block_alloc(ETHERHDRSIZE+IPHDR+seglen, MEM_WAIT);
- feh = (Iphdr*)(nb->wp+ETHERHDRSIZE);
+ feh = (struct Iphdr*)(nb->wp+ETHERHDRSIZE);
memmove(nb->wp, epkt, ETHERHDRSIZE+IPHDR);
nb->wp += ETHERHDRSIZE+IPHDR;
@@ -1116,7 +1141,7 @@ etherwrite(Port *port, Block *bp)
hnputs(feh->frag, (frag+fragoff)>>3 | mf);
}
else
- hnputs(feh->frag, (frag+fragoff>>3) | IP_MF);
+ hnputs(feh->frag, ((frag+fragoff)>>3) | IP_MF);
hnputs(feh->length, seglen + IPHDR);
hnputs(feh->id, lid);
@@ -1142,7 +1167,7 @@ etherwrite(Port *port, Block *bp)
/* don't generate small packets */
if(BLEN(nb) < ETHERMINTU)
nb->wp = nb->rp + ETHERMINTU;
- devtab[port->data[1]->type]->bwrite(port->data[1], nb, 0);
+ devtab[port->data[1]->type].bwrite(port->data[1], nb, 0);
}
poperror();
freeblist(bp);
@@ -1150,36 +1175,33 @@ etherwrite(Port *port, Block *bp)
// hold b lock
static void
-portfree(Port *port)
+portfree(struct kref *kref)
{
- if(decref(port) != 0)
- return;
-
+ struct Port *port = container_of(kref, struct Port, kref);
if(port->data[0])
cclose(port->data[0]);
if(port->data[1])
cclose(port->data[1]);
- memset(port, 0, sizeof(Port));
- free(port);
+ memset(port, 0, sizeof(struct Port));
+ kfree(port);
}
-Dev bridgedevtab = {
- 'B',
- "bridge",
-
- devreset,
- bridgeinit,
- devshutdown,
- bridgeattach,
- bridgewalk,
- bridgestat,
- bridgeopen,
- devcreate,
- bridgeclose,
- bridgeread,
- devbread,
- bridgewrite,
- devbwrite,
- devremove,
- devwstat,
+struct dev bridgedevtab = {
+ .name = "bridge",
+
+ .reset = devreset,
+ .init = bridgeinit,
+ .shutdown = devshutdown,
+ .attach = bridgeattach,
+ .walk = bridgewalk,
+ .stat = bridgestat,
+ .open = bridgeopen,
+ .create = devcreate,
+ .close = bridgeclose,
+ .read = bridgeread,
+ .bread = devbread,
+ .write = bridgewrite,
+ .bwrite = devbwrite,
+ .remove = devremove,
+ .wstat = devwstat,
};
diff --git a/kern/include/ip.h b/kern/include/ip.h
index dd1edcc..7493db2 100644
--- a/kern/include/ip.h
+++ b/kern/include/ip.h
@@ -56,6 +56,24 @@ enum {
Lroot = 10,
Maxpath = 64,
+
+ /* headers, and flags in headers. */
+ IP4HDR = 20, /* sizeof(Ip4hdr) */
+ IP6HDR = 40, /* sizeof(Ip6hdr) */
+ IP_HLEN4 = 0x05, /* Header length in words */
+ IP_DF = 0x4000, /* Don't fragment */
+ IP_MF = 0x2000, /* More fragments */
+ IP6FHDR = 8, /* sizeof(Fraghdr6) */
+ IP_MAX = 64 * 1024, /* Maximum Internet packet size */
+
+ /* Ethernet constants related to ip. One might argue that they go
+ * in some other place, but let's face it: all our interfaces try
+ * to look like ethernet, nowadays. */
+ ETARP = 0x0806,
+ ETIP4 = 0x0800,
+ ETIP6 = 0x86DD,
+ ARPREQUEST = 1,
+ ARPREPLY = 2,
};
enum {
diff --git a/kern/src/net/ethermedium.c b/kern/src/net/ethermedium.c
index d1393f0..fd3b5dd 100644
--- a/kern/src/net/ethermedium.c
+++ b/kern/src/net/ethermedium.c
@@ -118,17 +118,6 @@ struct Etherrock {
struct chan *cchan6; /* Control channel for v6 */
};
-/*
- * ethernet arp request
- */
-enum {
- ETARP = 0x0806,
- ETIP4 = 0x0800,
- ETIP6 = 0x86DD,
- ARPREQUEST = 1,
- ARPREPLY = 2,
-};
-
typedef struct Etherarp Etherarp;
struct Etherarp {
uint8_t d[6];
diff --git a/kern/src/net/ip.c b/kern/src/net/ip.c
index 58f3c29..7f9232f 100644
--- a/kern/src/net/ip.c
+++ b/kern/src/net/ip.c
@@ -46,16 +46,6 @@ typedef struct Fragment4 Fragment4;
typedef struct Fragment6 Fragment6;
typedef struct Ipfrag Ipfrag;
-enum {
- IP4HDR = 20, /* sizeof(Ip4hdr) */
- IP6HDR = 40, /* sizeof(Ip6hdr) */
- IP_HLEN4 = 0x05, /* Header length in words */
- IP_DF = 0x4000, /* Don't fragment */
- IP_MF = 0x2000, /* More fragments */
- IP6FHDR = 8, /* sizeof(Fraghdr6) */
- IP_MAX = 64 * 1024, /* Maximum Internet packet size */
-};
-
#define BLKIPVER(xp) (((struct Ip4hdr*)((xp)->rp))->vihl&0xF0)
#define NEXT_ID(x) (__sync_add_and_fetch(&(x), 1))
diff --git a/kern/src/net/ipv6.c b/kern/src/net/ipv6.c
index e2b9450..4c84aba 100644
--- a/kern/src/net/ipv6.c
+++ b/kern/src/net/ipv6.c
@@ -32,13 +32,8 @@
#include <kmalloc.h>
enum {
- IP4HDR = 20, /* sizeof(Ip4hdr) */
- IP6HDR = 40, /* sizeof(Ip6hdr) */
- IP_HLEN4 = 0x05, /* Header length in words */
- IP_DF = 0x4000, /* Don't fragment */
- IP_MF = 0x2000, /* More fragments */
- IP6FHDR = 8, /* sizeof(Fraghdr6) */
- IP_MAX = (32 * 1024), /* Maximum Internet packet size */
+ /* TODO: why is this here and why is it different. */
+ IPV6_MAX = (32 * 1024), /* Maximum Internet packet size */
};
#define IPV6CLASS(hdr) ((hdr->vcf[0]&0x0F)<<2 | (hdr->vcf[1]&0xF0)>>2)
@@ -188,7 +183,7 @@ int ipoput6(struct Fs *f, struct block *bp,
len = chunk + IPV6HDR_LEN;
}
- if (len >= IP_MAX) {
+ if (len >= IPV6_MAX) {
ip->stats[OutDiscards]++;
netlog(f, Logip, "exceeded ip max size %I\n", eh->dst);
goto free;
--
2.8.0.rc3.226.g39d4020
--
You received this message because you are subscribed to the Google Groups
"Akaros" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
For more options, visit https://groups.google.com/d/optout.