summaryrefslogtreecommitdiffstats
path: root/usr.sbin/switchd
diff options
context:
space:
mode:
authorrzalamena <rzalamena@openbsd.org>2016-12-22 15:31:43 +0000
committerrzalamena <rzalamena@openbsd.org>2016-12-22 15:31:43 +0000
commitcc4fa12dd49a79985bb07c935a3ca2dd5017257e (patch)
tree40be7bd7502fea94c5426f7a1fa19e3e4a2de030 /usr.sbin/switchd
parentRelease the NET_LOCK() before namei(9) as a workaround to let NFS boot (diff)
downloadwireguard-openbsd-cc4fa12dd49a79985bb07c935a3ca2dd5017257e.tar.xz
wireguard-openbsd-cc4fa12dd49a79985bb07c935a3ca2dd5017257e.zip
Learn remote switch flow tables properties to find out where to install
the default table-miss flow for OpenFlow 1.3.5. This is enough to make switchd(8) to work with switch(4) and HP 3800 switch out-of-the-box. ok reyk@
Diffstat (limited to 'usr.sbin/switchd')
-rw-r--r--usr.sbin/switchd/ofp.c7
-rw-r--r--usr.sbin/switchd/ofp13.c347
-rw-r--r--usr.sbin/switchd/ofp_common.c69
-rw-r--r--usr.sbin/switchd/ofrelay.c4
-rw-r--r--usr.sbin/switchd/switchd.h38
5 files changed, 338 insertions, 127 deletions
diff --git a/usr.sbin/switchd/ofp.c b/usr.sbin/switchd/ofp.c
index bce8941c557..bf0ef100891 100644
--- a/usr.sbin/switchd/ofp.c
+++ b/usr.sbin/switchd/ofp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ofp.c,v 1.17 2016/12/02 14:39:46 rzalamena Exp $ */
+/* $OpenBSD: ofp.c,v 1.18 2016/12/22 15:31:43 rzalamena Exp $ */
/*
* Copyright (c) 2013-2016 Reyk Floeter <reyk@openbsd.org>
@@ -231,14 +231,11 @@ ofp_nextstate(struct switchd *sc, struct switch_connection *con,
/* Let's not ask this while we don't use it. */
ofp13_flow_stats(sc, con, OFP_PORT_ANY, OFP_GROUP_ID_ANY,
OFP_TABLE_ID_ALL);
- ofp13_table_features(sc, con, 0);
ofp13_desc(sc, con);
#endif
+ rv |= ofp13_table_features(sc, con, 0);
rv |= ofp13_setconfig(sc, con, OFP_CONFIG_FRAG_NORMAL,
OFP_CONTROLLER_MAXLEN_NO_BUFFER);
-
- /* Use table '0' for switch(4) and '100' for HP 3800. */
- rv |= ofp13_tablemiss_sendctrl(sc, con, 0);
break;
diff --git a/usr.sbin/switchd/ofp13.c b/usr.sbin/switchd/ofp13.c
index 3aacbcd4154..e16381bf5ad 100644
--- a/usr.sbin/switchd/ofp13.c
+++ b/usr.sbin/switchd/ofp13.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ofp13.c,v 1.41 2016/12/02 14:39:46 rzalamena Exp $ */
+/* $OpenBSD: ofp13.c,v 1.42 2016/12/22 15:31:43 rzalamena Exp $ */
/*
* Copyright (c) 2013-2016 Reyk Floeter <reyk@openbsd.org>
@@ -70,10 +70,8 @@ int ofp13_packet_in(struct switchd *, struct switch_connection *,
struct ofp_header *, struct ibuf *);
int ofp13_flow_removed(struct switchd *, struct switch_connection *,
struct ofp_header *, struct ibuf *);
-int ofp13_parse_instruction(struct ibuf *, struct ofp_instruction *);
-int ofp13_parse_action(struct ibuf *, struct ofp_action_header *);
-int ofp13_parse_oxm(struct ibuf *, struct ofp_ox_match *);
-int ofp13_parse_tableproperties(struct ibuf *, struct ofp_table_features *);
+int ofp13_tableproperties(struct switch_connection *, struct ibuf *,
+ off_t, size_t, int);
int ofp13_multipart_reply(struct switchd *, struct switch_connection *,
struct ofp_header *, struct ibuf *);
int ofp13_validate_tableproperty(struct ibuf *, off_t, int);
@@ -104,6 +102,9 @@ int ofp13_setconfig_validate(struct switchd *,
struct sockaddr_storage *, struct sockaddr_storage *,
struct ofp_header *, struct ibuf *);
+int ofp13_switchconfigure(struct switchd *, struct switch_connection *);
+int ofp13_getflowtable(struct switch_connection *);
+
struct ofp_callback ofp13_callbacks[] = {
{ OFP_T_HELLO, ofp13_hello, ofp_validate_hello },
{ OFP_T_ERROR, NULL, ofp13_validate_error },
@@ -1013,7 +1014,7 @@ ofp13_packet_in(struct switchd *sc, struct switch_connection *con,
struct ofp_ox_match *oxm;
struct packet pkt;
struct ibuf *obuf = NULL;
- int ret = -1;
+ int table, ret = -1;
ssize_t len, mlen;
uint32_t srcport = 0, dstport;
int addflow = 0, sendbuffer = 0;
@@ -1091,6 +1092,13 @@ ofp13_packet_in(struct switchd *sc, struct switch_connection *con,
again:
if (addflow) {
+ table = ofp13_getflowtable(con);
+ if (table > OFP_TABLE_ID_MAX || table < 0) {
+ /* This switch doesn't support installing flows. */
+ addflow = 0;
+ goto again;
+ }
+
if ((fm = ibuf_advance(obuf, sizeof(*fm))) == NULL)
goto done;
@@ -1101,6 +1109,7 @@ ofp13_packet_in(struct switchd *sc, struct switch_connection *con,
fm->fm_hard_timeout = 0; /* permanent */
fm->fm_priority = 0;
fm->fm_buffer_id = pin->pin_buffer_id;
+ fm->fm_table_id = table;
fm->fm_flags = htons(OFP_FLOWFLAG_SEND_FLOW_REMOVED);
if (pin->pin_buffer_id == htonl(OFP_PKTOUT_NO_BUFFER))
sendbuffer = 1;
@@ -1191,83 +1200,50 @@ ofp13_flow_removed(struct switchd *sc, struct switch_connection *con,
}
int
-ofp13_parse_instruction(struct ibuf *ibuf, struct ofp_instruction *i)
-{
- int type;
- int len;
-
- type = ntohs(i->i_type);
- len = ntohs(i->i_len);
-
- log_debug("\t\t%s", print_map(type, ofp_instruction_t_map));
-
- return (len);
-}
-
-int
-ofp13_parse_action(struct ibuf *ibuf, struct ofp_action_header *ah)
-{
- int len, type;
-
- len = htons(ah->ah_len);
- type = htons(ah->ah_type);
-
- log_debug("\t\t%s", print_map(type, ofp_action_map));
-
- return (len);
-}
-
-int
-ofp13_parse_oxm(struct ibuf *ibuf, struct ofp_ox_match *oxm)
+ofp13_tableproperties(struct switch_connection *con, struct ibuf *ibuf,
+ off_t off, size_t total, int new)
{
- int length, type, class, hasmask;
+ struct ofp_table_features *tf;
+ struct ofp_table_feature_property *tp;
+ struct ofp_instruction *i;
+ struct ofp_action_header *ah;
+ struct ofp_ox_match *oxm;
+ struct switch_table *st;
+ uint8_t *next_table;
+ int remaining, type, length;
+ int hlen, padsize;
+ int class, dtype, dlen;
- class = ntohs(oxm->oxm_class);
- type = OFP_OXM_GET_FIELD(oxm);
- hasmask = OFP_OXM_GET_HASMASK(oxm);
/*
- * XXX the OpenFlow 1.3.5 specification says this field is only
- * 4 bytes long, however the experimental type is 8 bytes.
+ * This is a new table features reply, free our previous tables
+ * to get the updated ones.
*/
- length = sizeof(*oxm);
+ if (new)
+ switch_freetables(con);
- log_debug("\t\t%s hasmask %s type %s",
- print_map(class, ofp_oxm_c_map), hasmask ? "yes" : "no",
- print_map(type, ofp_xm_t_map));
+ next_table:
+ if ((tf = ibuf_seek(ibuf, off, sizeof(*tf))) == NULL)
+ return (-1);
- if (class == OFP_OXM_C_OPENFLOW_EXPERIMENTER) {
- /* Get the last bytes. */
- if (ibuf_getdata(ibuf, 4) == NULL)
- return (-1);
+ hlen = htons(tf->tf_length);
+ total -= hlen;
+ remaining = hlen - sizeof(*tf);
+ off += sizeof(*tf);
- return (8);
+ st = switch_tablelookup(con, tf->tf_tableid);
+ if (st == NULL) {
+ st = switch_newtable(con, tf->tf_tableid);
+ if (st == NULL)
+ return (-1);
}
- return (length);
-}
-
-int
-ofp13_parse_tableproperties(struct ibuf *ibuf, struct ofp_table_features *tf)
-{
- struct ofp_table_feature_property *tp;
- struct ofp_instruction *i;
- struct ofp_action_header *ah;
- struct ofp_ox_match *oxm;
- uint8_t *next_table;
- int remaining, type, length;
- int totallen, padsize, rv;
-
- log_debug("Table %s (%d) max_entries %u config %u "
- "metadata match %#016llx write %#016llx",
- tf->tf_name, tf->tf_tableid, ntohl(tf->tf_max_entries),
- ntohl(tf->tf_config), be64toh(tf->tf_metadata_match),
- be64toh(tf->tf_metadata_write));
- totallen = htons(tf->tf_length);
- remaining = totallen - sizeof(*tf);
+ st->st_maxentries = ntohl(tf->tf_max_entries);
next_table_property:
- if ((tp = ibuf_getdata(ibuf, sizeof(*tp))) == NULL)
+ if ((tp = ibuf_seek(ibuf, off, sizeof(*tp))) == NULL) {
+ switch_deltable(con, st);
return (-1);
+ }
type = ntohs(tp->tp_type);
length = ntohs(tp->tp_length);
@@ -1276,32 +1252,63 @@ ofp13_parse_tableproperties(struct ibuf *ibuf, struct ofp_table_features *tf)
padsize = OFP_ALIGN(length) - length;
remaining -= OFP_ALIGN(length);
length -= sizeof(*tp);
-
- log_debug("\t%s:", print_map(type, ofp_table_featprop_map));
- if (length == 0)
- log_debug("\t\tNONE");
+ off += sizeof(*tp);
switch (type) {
case OFP_TABLE_FEATPROP_INSTRUCTION:
case OFP_TABLE_FEATPROP_INSTRUCTION_MISS:
+ if (type == OFP_TABLE_FEATPROP_INSTRUCTION)
+ st->st_instructions = 0;
+ else
+ st->st_instructionsmiss = 0;
+
while (length) {
- if ((i = ibuf_getdata(ibuf, sizeof(*i))) == NULL)
- return (-1);
- if ((rv = ofp13_parse_instruction(ibuf, i)) == -1)
+ if ((i = ibuf_seek(ibuf, off, sizeof(*i))) == NULL) {
+ switch_deltable(con, st);
return (-1);
- length -= rv;
+ }
+
+ dtype = ntohs(i->i_type);
+ dlen = ntohs(i->i_len);
+ if (type == OFP_TABLE_FEATPROP_INSTRUCTION)
+ st->st_instructions |= 1ULL << dtype;
+ else
+ st->st_instructionsmiss |= 1ULL << dtype;
+
+ if (dtype == OFP_INSTRUCTION_T_EXPERIMENTER) {
+ length -= dlen;
+ off += dlen;
+ } else {
+ length -= sizeof(*i);
+ off += sizeof(*i);
+ }
}
break;
case OFP_TABLE_FEATPROP_NEXT_TABLES:
case OFP_TABLE_FEATPROP_NEXT_TABLES_MISS:
+ if (type == OFP_TABLE_FEATPROP_NEXT_TABLES)
+ memset(st->st_nexttable, 0, sizeof(st->st_nexttable));
+ else
+ memset(st->st_nexttablemiss, 0,
+ sizeof(st->st_nexttablemiss));
+
while (length) {
- if ((next_table = ibuf_getdata(ibuf,
- sizeof(*next_table))) == NULL)
+ if ((next_table = ibuf_seek(ibuf, off,
+ sizeof(*next_table))) == NULL) {
+ switch_deltable(con, st);
return (-1);
+ }
+
+ if (type == OFP_TABLE_FEATPROP_NEXT_TABLES)
+ st->st_nexttable[(*next_table) / 64] |=
+ 1ULL << ((*next_table) % 64);
+ else
+ st->st_nexttablemiss[(*next_table) / 64] |=
+ 1ULL << ((*next_table) % 64);
- log_debug("\t\t%d", *next_table);
length -= sizeof(*next_table);
+ off += sizeof(*next_table);
}
break;
@@ -1309,16 +1316,37 @@ ofp13_parse_tableproperties(struct ibuf *ibuf, struct ofp_table_features *tf)
case OFP_TABLE_FEATPROP_WRITE_ACTIONS_MISS:
case OFP_TABLE_FEATPROP_APPLY_ACTIONS:
case OFP_TABLE_FEATPROP_APPLY_ACTIONS_MISS:
+ if (type == OFP_TABLE_FEATPROP_WRITE_ACTIONS ||
+ type == OFP_TABLE_FEATPROP_APPLY_ACTIONS)
+ st->st_actions = 0;
+ else
+ st->st_actionsmiss = 0;
+
while (length) {
/*
- * XXX the OpenFlow 1.3.5 specs says that we only
- * get 4 bytes here instead of the full OXM.
+ * NOTE the OpenFlow 1.3.5 specs says that we only
+ * get 4 bytes here instead of the full action header.
*/
- if ((ah = ibuf_getdata(ibuf, 4)) == NULL)
- return (-1);
- if ((rv = ofp13_parse_action(ibuf, ah)) == -1)
+ if ((ah = ibuf_seek(ibuf, off, 4)) == NULL) {
+ switch_deltable(con, st);
return (-1);
- length -= rv;
+ }
+
+ dtype = ntohs(ah->ah_type);
+ dlen = ntohs(ah->ah_len);
+ if (type == OFP_TABLE_FEATPROP_WRITE_ACTIONS ||
+ type == OFP_TABLE_FEATPROP_APPLY_ACTIONS)
+ st->st_actions |= 1ULL << dtype;
+ else
+ st->st_actionsmiss |= 1ULL << dtype;
+
+ if (dtype == OFP_ACTION_EXPERIMENTER) {
+ length -= dlen;
+ off += dlen;
+ } else {
+ length -= 4;
+ off += 4;
+ }
}
break;
@@ -1328,32 +1356,72 @@ ofp13_parse_tableproperties(struct ibuf *ibuf, struct ofp_table_features *tf)
case OFP_TABLE_FEATPROP_WRITE_SETFIELD_MISS:
case OFP_TABLE_FEATPROP_APPLY_SETFIELD:
case OFP_TABLE_FEATPROP_APPLY_SETFIELD_MISS:
+ if (type == OFP_TABLE_FEATPROP_WRITE_SETFIELD ||
+ type == OFP_TABLE_FEATPROP_APPLY_SETFIELD)
+ st->st_setfield = 0;
+ else if (type == OFP_TABLE_FEATPROP_WRITE_SETFIELD_MISS ||
+ type == OFP_TABLE_FEATPROP_APPLY_SETFIELD_MISS)
+ st->st_setfieldmiss = 0;
+ else if (type == OFP_TABLE_FEATPROP_MATCH)
+ st->st_match = 0;
+ else
+ st->st_wildcard = 0;
+
while (length) {
- if ((oxm = ibuf_getdata(ibuf, sizeof(*oxm))) == NULL)
- return (-1);
- if ((rv = ofp13_parse_oxm(ibuf, oxm)) == -1)
+ if ((oxm = ibuf_seek(ibuf, off,
+ sizeof(*oxm))) == NULL) {
+ switch_deltable(con, st);
return (-1);
- length -= rv;
- }
- break;
+ }
- default:
- log_debug("%s: unsupported property type: %d", __func__, type);
+ class = ntohs(oxm->oxm_class);
+ if (class != OFP_OXM_C_OPENFLOW_BASIC) {
+ if (class == OFP_OXM_C_OPENFLOW_EXPERIMENTER) {
+ length -= sizeof(*oxm) + 4;
+ off += sizeof(*oxm) + 4;
+ } else {
+ length -= sizeof(*oxm);
+ off += sizeof(*oxm);
+ }
+ continue;
+ }
- /* Skip this field and try to continue otherwise fail. */
- if (ibuf_getdata(ibuf, length) == NULL)
- return (-1);
+ dtype = OFP_OXM_GET_FIELD(oxm);
+ if (type == OFP_TABLE_FEATPROP_WRITE_SETFIELD ||
+ type == OFP_TABLE_FEATPROP_APPLY_SETFIELD)
+ st->st_setfield |= 1ULL << dtype;
+ else if
+ (type == OFP_TABLE_FEATPROP_WRITE_SETFIELD_MISS ||
+ type == OFP_TABLE_FEATPROP_APPLY_SETFIELD_MISS)
+ st->st_setfieldmiss |= 1ULL << dtype;
+ else if (type == OFP_TABLE_FEATPROP_MATCH)
+ st->st_match |= 1ULL << dtype;
+ else
+ st->st_wildcard |= 1ULL << dtype;
+ length -= sizeof(*oxm);
+ off += sizeof(*oxm);
+ }
break;
- }
- /* Skip the padding and read the next property if any. */
- if (padsize && ibuf_getdata(ibuf, padsize) == NULL)
+ case OFP_TABLE_FEATPROP_EXPERIMENTER:
+ case OFP_TABLE_FEATPROP_EXPERIMENTER_MISS:
+ off += length;
+ break;
+
+ default:
+ log_debug("Unsupported table property %d", type);
return (-1);
- if (remaining)
+ }
+
+ if (padsize)
+ off += padsize;
+ if (remaining > 0)
goto next_table_property;
+ if (total > 0)
+ goto next_table;
- return (totallen);
+ return (0);
}
int
@@ -1361,18 +1429,25 @@ ofp13_multipart_reply(struct switchd *sc, struct switch_connection *con,
struct ofp_header *oh, struct ibuf *ibuf)
{
struct ofp_multipart *mp;
- struct ofp_table_features *tf;
- int readlen, type, flags;
+ int type, flags, more, new = 0;
int remaining;
+ off_t off;
- if ((mp = ibuf_getdata(ibuf, sizeof(*mp))) == NULL)
+ off = 0;
+ if ((mp = ibuf_seek(ibuf, 0, sizeof(*mp))) == NULL)
return (-1);
type = ntohs(mp->mp_type);
flags = ntohs(mp->mp_flags);
remaining = ntohs(oh->oh_length) - sizeof(*mp);
+ off += sizeof(*mp);
+
+ more = (flags & OFP_MP_FLAG_REPLY_MORE) == OFP_MP_FLAG_REPLY_MORE;
+ /* Signalize new requests. */
+ if (ofp_multipart_lookup(con, oh->oh_xid) == NULL)
+ new = 1;
- if (flags & OFP_MP_FLAG_REPLY_MORE) {
+ if (more) {
if (ofp_multipart_add(con, oh->oh_xid, type) == -1) {
ofp13_error(sc, con, oh, ibuf,
OFP_ERRTYPE_BAD_REQUEST,
@@ -1393,15 +1468,12 @@ ofp13_multipart_reply(struct switchd *sc, struct switch_connection *con,
switch (type) {
case OFP_MP_T_TABLE_FEATURES:
- read_next_table:
- if ((tf = ibuf_getdata(ibuf, sizeof(*tf))) == NULL)
- return (-1);
- if ((readlen = ofp13_parse_tableproperties(ibuf, tf)) == -1)
+ if (ofp13_tableproperties(con, ibuf, off, remaining, new))
return (-1);
- remaining -= readlen;
- if (remaining)
- goto read_next_table;
+ /* We finished receiving tables, configure the switch. */
+ if (more == 0)
+ return (ofp13_switchconfigure(sc, con));
break;
}
@@ -2137,3 +2209,48 @@ ofp13_tablemiss_sendctrl(struct switchd *sc, struct switch_connection *con,
(void)oflowmod_err(&ctx, __func__, __LINE__);
return (-1);
}
+
+int
+ofp13_switchconfigure(struct switchd *sc, struct switch_connection *con)
+{
+ struct switch_table *st;
+
+ /* Look for a table with 'apply' and 'output' support for miss. */
+ TAILQ_FOREACH(st, &con->con_stlist, st_entry) {
+ if ((st->st_instructionsmiss &
+ (1ULL << OFP_INSTRUCTION_T_APPLY_ACTIONS)) == 0)
+ continue;
+ if ((st->st_actionsmiss & (1ULL << OFP_ACTION_OUTPUT)) == 0)
+ continue;
+
+ break;
+ }
+ if (st == NULL) {
+ log_warn("No apply output for this switch");
+ return (-1);
+ }
+
+ /* Install the flow to receive packets from the switch. */
+ return (ofp13_tablemiss_sendctrl(sc, con, st->st_table));
+}
+
+int
+ofp13_getflowtable(struct switch_connection *con)
+{
+ struct switch_table *st;
+
+ /* Look for a table with 'apply' and 'output' support. */
+ TAILQ_FOREACH(st, &con->con_stlist, st_entry) {
+ if ((st->st_instructions &
+ (1ULL << OFP_INSTRUCTION_T_APPLY_ACTIONS)) == 0)
+ continue;
+ if ((st->st_actions & (1ULL << OFP_ACTION_OUTPUT)) == 0)
+ continue;
+
+ break;
+ }
+ if (st == NULL)
+ return (-1);
+
+ return (st->st_table);
+}
diff --git a/usr.sbin/switchd/ofp_common.c b/usr.sbin/switchd/ofp_common.c
index fd48d14ae69..0f832cb069b 100644
--- a/usr.sbin/switchd/ofp_common.c
+++ b/usr.sbin/switchd/ofp_common.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ofp_common.c,v 1.9 2016/12/02 14:39:46 rzalamena Exp $ */
+/* $OpenBSD: ofp_common.c,v 1.10 2016/12/22 15:31:43 rzalamena Exp $ */
/*
* Copyright (c) 2013-2016 Reyk Floeter <reyk@openbsd.org>
@@ -1115,15 +1115,31 @@ ofp_instruction(struct ibuf *ibuf, uint16_t type, uint16_t hlen)
return (oi);
}
-int
-ofp_multipart_add(struct switch_connection *con, uint32_t xid, uint8_t type)
+struct multipart_message *
+ofp_multipart_lookup(struct switch_connection *con, uint32_t xid)
{
struct multipart_message *mm;
- /* A multipart reply have the same xid and type in all parts. */
SLIST_FOREACH(mm, &con->con_mmlist, mm_entry) {
if (mm->mm_xid != xid)
continue;
+
+ return (mm);
+ }
+
+ return (NULL);
+}
+
+int
+ofp_multipart_add(struct switch_connection *con, uint32_t xid, uint8_t type)
+{
+ struct multipart_message *mm;
+
+ if ((mm = ofp_multipart_lookup(con, xid)) != NULL) {
+ /*
+ * A multipart reply has the same xid and type, otherwise
+ * something went wrong.
+ */
if (mm->mm_type != type)
return (-1);
@@ -1173,6 +1189,51 @@ ofp_multipart_clear(struct switch_connection *con)
}
}
+struct switch_table *
+switch_tablelookup(struct switch_connection *con, int table)
+{
+ struct switch_table *st;
+
+ TAILQ_FOREACH(st, &con->con_stlist, st_entry) {
+ if (st->st_table == table)
+ return (st);
+ }
+
+ return (NULL);
+}
+
+struct switch_table *
+switch_newtable(struct switch_connection *con, int table)
+{
+ struct switch_table *st;
+
+ if ((st = calloc(1, sizeof(*st))) == NULL)
+ return (NULL);
+
+ st->st_table = table;
+ TAILQ_INSERT_TAIL(&con->con_stlist, st, st_entry);
+
+ return (st);
+}
+
+void
+switch_deltable(struct switch_connection *con, struct switch_table *st)
+{
+ TAILQ_REMOVE(&con->con_stlist, st, st_entry);
+ free(st);
+}
+
+void
+switch_freetables(struct switch_connection *con)
+{
+ struct switch_table *st;
+
+ while (!TAILQ_EMPTY(&con->con_stlist)) {
+ st = TAILQ_FIRST(&con->con_stlist);
+ switch_deltable(con, st);
+ }
+}
+
int
oflowmod_state(struct oflowmod_ctx *ctx, unsigned int old, unsigned int new)
{
diff --git a/usr.sbin/switchd/ofrelay.c b/usr.sbin/switchd/ofrelay.c
index 9cf4ac83f4a..653882caa4c 100644
--- a/usr.sbin/switchd/ofrelay.c
+++ b/usr.sbin/switchd/ofrelay.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ofrelay.c,v 1.9 2016/12/02 14:39:46 rzalamena Exp $ */
+/* $OpenBSD: ofrelay.c,v 1.10 2016/12/22 15:31:43 rzalamena Exp $ */
/*
* Copyright (c) 2016 Reyk Floeter <reyk@openbsd.org>
@@ -98,6 +98,7 @@ ofrelay_close(struct switch_connection *con)
TAILQ_REMOVE(&sc->sc_conns, con, con_entry);
ofrelay_sessions--;
+ switch_freetables(con);
ofp_multipart_clear(con);
switch_remove(con->con_sc, con->con_switch);
msgbuf_clear(&con->con_wbuf);
@@ -405,6 +406,7 @@ ofrelay_attach(struct switch_server *srv, int s, struct sockaddr *sa)
con->con_srv = srv;
con->con_state = OFP_STATE_CLOSED;
SLIST_INIT(&con->con_mmlist);
+ TAILQ_INIT(&con->con_stlist);
memcpy(&con->con_peer, sa, sa->sa_len);
con->con_port = htons(socket_getport(&con->con_peer));
diff --git a/usr.sbin/switchd/switchd.h b/usr.sbin/switchd/switchd.h
index b4337f9924c..68549f7c2b9 100644
--- a/usr.sbin/switchd/switchd.h
+++ b/usr.sbin/switchd/switchd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: switchd.h,v 1.27 2016/12/02 14:39:46 rzalamena Exp $ */
+/* $OpenBSD: switchd.h,v 1.28 2016/12/22 15:31:43 rzalamena Exp $ */
/*
* Copyright (c) 2013-2016 Reyk Floeter <reyk@openbsd.org>
@@ -68,6 +68,30 @@ struct switch_control {
};
RB_HEAD(switch_head, switch_control);
+struct switch_table {
+ TAILQ_ENTRY(switch_table) st_entry;
+
+ int st_table;
+ unsigned int st_entries;
+ unsigned int st_maxentries;
+
+ uint32_t st_actions;
+ uint32_t st_actionsmiss;
+
+ uint32_t st_instructions;
+ uint32_t st_instructionsmiss;
+
+ uint64_t st_setfield;
+ uint64_t st_setfieldmiss;
+ uint64_t st_match;
+ uint64_t st_wildcard;
+
+ /* Maximum of 256 tables (64 * 4). */
+ uint64_t st_nexttable[4];
+ uint64_t st_nexttablemiss[4];
+};
+TAILQ_HEAD(switch_table_list, switch_table);
+
struct multipart_message {
SLIST_ENTRY(multipart_message)
mm_entry;
@@ -105,6 +129,8 @@ struct switch_connection {
struct switch_server *con_srv;
struct multipart_list con_mmlist;
+ struct switch_table_list
+ con_stlist;
TAILQ_ENTRY(switch_connection)
con_entry;
@@ -247,6 +273,13 @@ void ofp_accept(int, short, void *);
int ofp_input(struct switch_connection *, struct ibuf *);
int ofp_nextstate(struct switchd *, struct switch_connection *,
enum ofp_state);
+struct switch_table *
+ switch_tablelookup(struct switch_connection *, int);
+struct switch_table *
+ switch_newtable(struct switch_connection *, int);
+void switch_deltable(struct switch_connection *,
+ struct switch_table *);
+void switch_freetables(struct switch_connection *);
/* ofp10.c */
int ofp10_hello(struct switchd *, struct switch_connection *,
@@ -289,6 +322,8 @@ int ofp_validate(struct switchd *,
struct ofp_header *, struct ibuf *, uint8_t);
int ofp_output(struct switch_connection *, struct ofp_header *,
struct ibuf *);
+struct multipart_message *
+ ofp_multipart_lookup(struct switch_connection *, uint32_t);
int ofp_multipart_add(struct switch_connection *, uint32_t,
uint8_t);
void ofp_multipart_del(struct switch_connection *, uint32_t);
@@ -364,7 +399,6 @@ int ofp_send_hello(struct switchd *, struct switch_connection *,
int);
int ofp_send_featuresrequest(struct switchd *,
struct switch_connection *);
-
/* ofcconn.c */
void ofcconn(struct privsep *, struct privsep_proc *);
void ofcconn_shutdown(void);