diff options
author | Rafael Zalamena <rzalamena@cvs.openbsd.org> | 2016-11-17 09:42:12 +0000 |
---|---|---|
committer | Rafael Zalamena <rzalamena@cvs.openbsd.org> | 2016-11-17 09:42:12 +0000 |
commit | 6f09aefc3da8aaa3de36589d4e9beae41b901cad (patch) | |
tree | ed71b11550659b6da282095ab30fa65f55e93445 /usr.sbin/switchd | |
parent | bcb3d1a1d33aba1147ad94a8419ef430870dc55b (diff) |
Added the missing code to build flow-mod messages and to install
table-miss by default for switch(4).
ok reyk@
Diffstat (limited to 'usr.sbin/switchd')
-rw-r--r-- | usr.sbin/switchd/ofp13.c | 97 | ||||
-rw-r--r-- | usr.sbin/switchd/ofp_common.c | 21 | ||||
-rw-r--r-- | usr.sbin/switchd/switchd.h | 8 |
3 files changed, 123 insertions, 3 deletions
diff --git a/usr.sbin/switchd/ofp13.c b/usr.sbin/switchd/ofp13.c index 07dc6034893..a39bcff23e4 100644 --- a/usr.sbin/switchd/ofp13.c +++ b/usr.sbin/switchd/ofp13.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ofp13.c,v 1.25 2016/11/07 13:27:11 rzalamena Exp $ */ +/* $OpenBSD: ofp13.c,v 1.26 2016/11/17 09:42:11 rzalamena Exp $ */ /* * Copyright (c) 2013-2016 Reyk Floeter <reyk@openbsd.org> @@ -104,6 +104,8 @@ int ofp13_setconfig_validate(struct switchd *, struct ofp_header *, struct ibuf *); int ofp13_setconfig(struct switchd *, struct switch_connection *, uint16_t, uint16_t); +int ofp13_tablemiss_sendctrl(struct switchd *, struct switch_connection *, + uint8_t); struct ofp_callback ofp13_callbacks[] = { { OFP_T_HELLO, ofp13_hello, NULL }, @@ -641,6 +643,9 @@ ofp13_features_reply(struct switchd *sc, struct switch_connection *con, ofp13_setconfig(sc, con, OFP_CONFIG_FRAG_NORMAL, OFP_CONTROLLER_MAXLEN_NO_BUFFER); + /* Use table '0' for switch(4) and '100' for HP 3800. */ + ofp13_tablemiss_sendctrl(sc, con, 0); + return (0); } @@ -1863,3 +1868,93 @@ ofp13_featuresrequest(struct switchd *sc, struct switch_connection *con) ibuf_free(ibuf); return (rv); } + +/* + * Flow modification message. + * + * After the flow-mod header we have N OXM filters to match packets, when + * you finish adding them you must update match header: + * fm_match.om_length = sizeof(fm_match) + OXM length. + * + * Then you must add flow instructions and update the OFP header length: + * fm_oh.oh_length = + * sizeof(*fm) + (fm_match.om_len - sizeof(fm_match)) + instructionslen. + * or + * fm_oh.oh_length = ibuf_length(ibuf). + * + * Note on match payload: + * After adding all matches and before starting to insert instructions you + * must add the mandatory padding to fm_match. You can calculate the padding + * size with this formula: + * padsize = OFP_ALIGN(fm_match.om_length) - fm_match.om_length; + * + * Note on Table-miss: + * To make a table miss you need to set priority 0 and don't add any + * matches, just instructions. + */ +struct ofp_flow_mod * +ofp13_flowmod(struct switch_connection *con, struct ibuf *ibuf, + uint8_t cmd, uint8_t table, uint16_t idleto, uint16_t hardto, + uint16_t prio) +{ + struct ofp_flow_mod *fm; + + if ((fm = ibuf_advance(ibuf, sizeof(*fm))) == NULL) + return (NULL); + + fm->fm_oh.oh_version = OFP_V_1_3; + fm->fm_oh.oh_type = OFP_T_FLOW_MOD; + fm->fm_oh.oh_length = htons(sizeof(*fm)); + fm->fm_oh.oh_xid = htonl(con->con_xidnxt++); + fm->fm_match.om_type = htons(OFP_MATCH_OXM); + fm->fm_match.om_length = htons(sizeof(fm->fm_match)); + return (fm); +} + +int +ofp13_tablemiss_sendctrl(struct switchd *sc, struct switch_connection *con, + uint8_t table) +{ + struct ofp_flow_mod *fm; + struct ofp_instruction *oi; + struct ibuf *ibuf; + size_t istart, iend; + int padding; + int rv = -1; + + if ((ibuf = ibuf_static()) == NULL) + return (-1); + + fm = ofp13_flowmod(con, ibuf, OFP_FLOWCMD_ADD, table, 0, 0, 0); + if (fm == NULL) + goto done; + + padding = OFP_ALIGN(sizeof(fm->fm_match)) - sizeof(fm->fm_match); + if (padding && ibuf_advance(ibuf, padding) == NULL) + goto done; + + istart = ibuf->wpos; + oi = (struct ofp_instruction *)ofp_instruction(ibuf, + OFP_INSTRUCTION_T_APPLY_ACTIONS, + sizeof(struct ofp_instruction_actions)); + + if (oi == NULL || + action_output(ibuf, OFP_PORT_CONTROLLER, + OFP_CONTROLLER_MAXLEN_MAX) == -1) + goto done; + iend = ibuf->wpos; + + /* Set header sizes. */ + oi->i_len = htons(iend - istart); + fm->fm_oh.oh_length = htons(ibuf_length(ibuf)); + + if (ofp13_validate(sc, &con->con_local, &con->con_peer, &fm->fm_oh, + ibuf) != 0) + goto done; + + rv = ofp_output(con, NULL, ibuf); + + done: + ibuf_release(ibuf); + return (rv); +} diff --git a/usr.sbin/switchd/ofp_common.c b/usr.sbin/switchd/ofp_common.c index d3f882442ef..09047dd34b9 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.3 2016/11/11 22:07:40 reyk Exp $ */ +/* $OpenBSD: ofp_common.c,v 1.4 2016/11/17 09:42:11 rzalamena Exp $ */ /* * Copyright (c) 2013-2016 Reyk Floeter <reyk@openbsd.org> @@ -881,6 +881,25 @@ oxm_ipv6exthdr(struct ibuf *ibuf, int hasmask, uint16_t exthdr, uint16_t mask) return (0); } +/* + * Appends a new instruction with hlen size. + * + * Remember to set the instruction length (i->i_len) if it has more data, + * like ofp_instruction_actions, ofp_instruction_goto_table etc... + */ +struct ofp_instruction * +ofp_instruction(struct ibuf *ibuf, uint16_t type, uint16_t hlen) +{ + struct ofp_instruction *oi; + + if ((oi = ibuf_advance(ibuf, hlen)) == NULL) + return (NULL); + + oi->i_type = htons(type); + oi->i_len = htons(hlen); + return (oi); +} + int ofp_multipart_add(struct switch_connection *con, uint32_t xid, uint8_t type) { diff --git a/usr.sbin/switchd/switchd.h b/usr.sbin/switchd/switchd.h index f1b34246f24..1665e509c0d 100644 --- a/usr.sbin/switchd/switchd.h +++ b/usr.sbin/switchd/switchd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: switchd.h,v 1.20 2016/11/15 09:05:14 reyk Exp $ */ +/* $OpenBSD: switchd.h,v 1.21 2016/11/17 09:42:11 rzalamena Exp $ */ /* * Copyright (c) 2013-2016 Reyk Floeter <reyk@openbsd.org> @@ -251,6 +251,9 @@ int ofp13_table_features(struct switchd *, struct switch_connection *, uint8_t); int ofp13_featuresrequest(struct switchd *, struct switch_connection *); +struct ofp_flow_mod * + ofp13_flowmod(struct switch_connection *, struct ibuf *, + uint8_t, uint8_t, uint16_t, uint16_t, uint16_t); /* ofp_common.c */ int ofp_validate_header(struct switchd *, @@ -308,6 +311,9 @@ int oxm_mplstc(struct ibuf *, uint8_t); int oxm_mplsbos(struct ibuf *, uint8_t); int oxm_tunnelid(struct ibuf *, int, uint64_t, uint64_t); int oxm_ipv6exthdr(struct ibuf *, int, uint16_t, uint16_t); +struct ofp_instruction * + ofp_instruction(struct ibuf *, uint16_t, uint16_t); + /* ofcconn.c */ void ofcconn(struct privsep *, struct privsep_proc *); |