diff options
author | Rafael Zalamena <rzalamena@cvs.openbsd.org> | 2016-12-22 15:31:44 +0000 |
---|---|---|
committer | Rafael Zalamena <rzalamena@cvs.openbsd.org> | 2016-12-22 15:31:44 +0000 |
commit | 5f6c4bfb8ab57234316acbc5431637e414d77e4c (patch) | |
tree | 5195f490b55891fc0ef6709c9c5189f5a2540ffe /usr.sbin/switchd | |
parent | 957e12d9ffe5ff68adab535d762271df7e99ce63 (diff) |
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.c | 7 | ||||
-rw-r--r-- | usr.sbin/switchd/ofp13.c | 347 | ||||
-rw-r--r-- | usr.sbin/switchd/ofp_common.c | 69 | ||||
-rw-r--r-- | usr.sbin/switchd/ofrelay.c | 4 | ||||
-rw-r--r-- | usr.sbin/switchd/switchd.h | 38 |
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); |