Signed-off-by: Ben Pfaff <b...@nicira.com> --- include/openflow/openflow-1.4.h | 44 +++++++++++++++++++-- lib/ofp-msgs.h | 7 +++- lib/ofp-print.c | 2 +- lib/ofp-util.c | 86 ++++++++++++++++++++++++++++++++++++++--- lib/ofp-util.h | 2 +- ofproto/ofproto.c | 2 +- tests/ofp-print.at | 14 +++++++ tests/ofproto.at | 32 +++++++++++++++ 8 files changed, 175 insertions(+), 14 deletions(-)
diff --git a/include/openflow/openflow-1.4.h b/include/openflow/openflow-1.4.h index 9c03cf4..08f98f9 100644 --- a/include/openflow/openflow-1.4.h +++ b/include/openflow/openflow-1.4.h @@ -38,9 +38,11 @@ #define OPENFLOW_14_H 1 #include "openflow/openflow-1.3.h" -/* - * OpenFlow 1.4 is more extensible by using TLV structures - */ + + +/* ## ---------- ## */ +/* ## ofp14_port ## */ +/* ## ---------- ## */ /* Port description property types. */ enum ofp_port_desc_prop_type { @@ -81,6 +83,42 @@ struct ofp14_port { }; OFP_ASSERT(sizeof(struct ofp14_port) == 40); + +/* ## -------------- ## */ +/* ## ofp14_port_mod ## */ +/* ## -------------- ## */ + +enum ofp14_port_mod_prop_type { + OFPPMPT14_ETHERNET = 0, /* Ethernet property. */ + OFPPMPT14_OPTICAL = 1, /* Optical property. */ + OFPPMPT14_EXPERIMENTER = 0xFFFF, /* Experimenter property. */ +}; + +/* Ethernet port mod property. */ +struct ofp14_port_mod_prop_ethernet { + ovs_be16 type; /* OFPPMPT14_ETHERNET. */ + ovs_be16 length; /* Length in bytes of this property. */ + ovs_be32 advertise; /* Bitmap of OFPPF_*. Zero all bits to prevent + any action taking place. */ +}; +OFP_ASSERT(sizeof(struct ofp14_port_mod_prop_ethernet) == 8); + +struct ofp14_port_mod { + ovs_be32 port_no; + uint8_t pad[4]; + uint8_t hw_addr[OFP_ETH_ALEN]; + uint8_t pad2[2]; + ovs_be32 config; /* Bitmap of OFPPC_* flags. */ + ovs_be32 mask; /* Bitmap of OFPPC_* flags to be changed. */ + /* Followed by 0 or more OFPPMPT14_* properties. */ +}; +OFP_ASSERT(sizeof(struct ofp14_port_mod) == 24); + + +/* ## -------------- ## */ +/* ## Miscellaneous. ## */ +/* ## -------------- ## */ + /* Common header for all async config Properties */ struct ofp14_async_config_prop_header { ovs_be16 type; /* One of OFPACPT_*. */ diff --git a/lib/ofp-msgs.h b/lib/ofp-msgs.h index b548f6b..45271b7 100644 --- a/lib/ofp-msgs.h +++ b/lib/ofp-msgs.h @@ -184,8 +184,10 @@ enum ofpraw { /* OFPT 1.0 (15): struct ofp10_port_mod. */ OFPRAW_OFPT10_PORT_MOD, - /* OFPT 1.1+ (16): struct ofp11_port_mod. */ + /* OFPT 1.1-1.3 (16): struct ofp11_port_mod. */ OFPRAW_OFPT11_PORT_MOD, + /* OFPT 1.4+ (16): struct ofp14_port_mod, uint8_t[8][]. */ + OFPRAW_OFPT14_PORT_MOD, /* OFPT 1.1+ (17): struct ofp11_table_mod. */ OFPRAW_OFPT11_TABLE_MOD, @@ -486,7 +488,8 @@ enum ofptype { * OFPRAW_NXT_FLOW_MOD. */ OFPTYPE_GROUP_MOD, /* OFPRAW_OFPT11_GROUP_MOD. */ OFPTYPE_PORT_MOD, /* OFPRAW_OFPT10_PORT_MOD. - * OFPRAW_OFPT11_PORT_MOD. */ + * OFPRAW_OFPT11_PORT_MOD. + * OFPRAW_OFPT14_PORT_MOD. */ OFPTYPE_TABLE_MOD, /* OFPRAW_OFPT11_TABLE_MOD. */ /* Barrier messages. */ diff --git a/lib/ofp-print.c b/lib/ofp-print.c index 909a846..ba808af 100644 --- a/lib/ofp-print.c +++ b/lib/ofp-print.c @@ -970,7 +970,7 @@ ofp_print_port_mod(struct ds *string, const struct ofp_header *oh) struct ofputil_port_mod pm; enum ofperr error; - error = ofputil_decode_port_mod(oh, &pm); + error = ofputil_decode_port_mod(oh, &pm, true); if (error) { ofp_print_error(string, error); return; diff --git a/lib/ofp-util.c b/lib/ofp-util.c index 33d1728..3a6eb5d 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -3989,10 +3989,8 @@ ofputil_capabilities_mask(enum ofp_version ofp_version) return OFPC_COMMON | OFPC_ARP_MATCH_IP; case OFP12_VERSION: case OFP13_VERSION: - return OFPC_COMMON | OFPC12_PORT_BLOCKED; case OFP14_VERSION: - OVS_NOT_REACHED(); - break; + return OFPC_COMMON | OFPC12_PORT_BLOCKED; default: /* Caller needs to check osf->header.version itself */ return 0; @@ -4250,11 +4248,25 @@ ofputil_encode_port_status(const struct ofputil_port_status *ps, /* ofputil_port_mod */ +static enum ofperr +parse_port_mod_ethernet_property(struct ofpbuf *property, + struct ofputil_port_mod *pm) +{ + struct ofp14_port_mod_prop_ethernet *eth = ofpbuf_data(property); + + if (ofpbuf_size(property) != sizeof *eth) { + return OFPERR_OFPBRC_BAD_LEN; + } + + pm->advertise = netdev_port_features_from_ofp11(eth->advertise); + return 0; +} + /* Decodes the OpenFlow "port mod" message in '*oh' into an abstract form in * '*pm'. Returns 0 if successful, otherwise an OFPERR_* value. */ enum ofperr ofputil_decode_port_mod(const struct ofp_header *oh, - struct ofputil_port_mod *pm) + struct ofputil_port_mod *pm, bool loose) { enum ofpraw raw; struct ofpbuf b; @@ -4283,6 +4295,52 @@ ofputil_decode_port_mod(const struct ofp_header *oh, pm->config = ntohl(opm->config) & OFPPC11_ALL; pm->mask = ntohl(opm->mask) & OFPPC11_ALL; pm->advertise = netdev_port_features_from_ofp11(opm->advertise); + } else if (raw == OFPRAW_OFPT14_PORT_MOD) { + const struct ofp14_port_mod *opm = ofpbuf_pull(&b, sizeof *opm); + enum ofperr error; + + memset(pm, 0, sizeof *pm); + + error = ofputil_port_from_ofp11(opm->port_no, &pm->port_no); + if (error) { + return error; + } + + memcpy(pm->hw_addr, opm->hw_addr, ETH_ADDR_LEN); + pm->config = ntohl(opm->config) & OFPPC11_ALL; + pm->mask = ntohl(opm->mask) & OFPPC11_ALL; + + while (ofpbuf_size(&b) > 0) { + struct ofpbuf property; + enum ofperr error; + uint16_t type; + + error = ofputil_pull_property(&b, &property, &type); + if (error) { + return error; + } + + switch (type) { + case OFPPMPT14_ETHERNET: + error = parse_port_mod_ethernet_property(&property, pm); + break; + + default: + log_property(loose, "unknown port_mod property %"PRIu16, type); + if (loose) { + error = 0; + } else if (type == OFPPMPT14_EXPERIMENTER) { + error = OFPERR_OFPBPC_BAD_EXPERIMENTER; + } else { + error = OFPERR_OFPBRC_BAD_TYPE; + } + break; + } + + if (error) { + return error; + } + } } else { return OFPERR_OFPBRC_BAD_TYPE; } @@ -4329,9 +4387,25 @@ ofputil_encode_port_mod(const struct ofputil_port_mod *pm, opm->advertise = netdev_port_features_to_ofp11(pm->advertise); break; } - case OFP14_VERSION: - OVS_NOT_REACHED(); + case OFP14_VERSION: { + struct ofp14_port_mod_prop_ethernet *eth; + struct ofp14_port_mod *opm; + + b = ofpraw_alloc(OFPRAW_OFPT14_PORT_MOD, ofp_version, sizeof *eth); + opm = ofpbuf_put_zeros(b, sizeof *opm); + opm->port_no = ofputil_port_to_ofp11(pm->port_no); + memcpy(opm->hw_addr, pm->hw_addr, ETH_ADDR_LEN); + opm->config = htonl(pm->config & OFPPC11_ALL); + opm->mask = htonl(pm->mask & OFPPC11_ALL); + + if (pm->advertise) { + eth = ofpbuf_put_zeros(b, sizeof *eth); + eth->type = htons(OFPPMPT14_ETHERNET); + eth->length = htons(sizeof *eth); + eth->advertise = netdev_port_features_to_ofp11(pm->advertise); + } break; + } default: OVS_NOT_REACHED(); } diff --git a/lib/ofp-util.h b/lib/ofp-util.h index bb3d647..63e1fd5 100644 --- a/lib/ofp-util.h +++ b/lib/ofp-util.h @@ -594,7 +594,7 @@ struct ofputil_port_mod { }; enum ofperr ofputil_decode_port_mod(const struct ofp_header *, - struct ofputil_port_mod *); + struct ofputil_port_mod *, bool loose); struct ofpbuf *ofputil_encode_port_mod(const struct ofputil_port_mod *, enum ofputil_protocol); diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index 557f124..ea11e5d 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -3038,7 +3038,7 @@ handle_port_mod(struct ofconn *ofconn, const struct ofp_header *oh) return error; } - error = ofputil_decode_port_mod(oh, &pm); + error = ofputil_decode_port_mod(oh, &pm, false); if (error) { return error; } diff --git a/tests/ofp-print.at b/tests/ofp-print.at index 640d114..7d31d5b 100644 --- a/tests/ofp-print.at +++ b/tests/ofp-print.at @@ -1025,6 +1025,20 @@ OFPT_PORT_MOD (OF1.3) (xid=0x3):port: 3: addr:50:54:00:00:00:01 ]) AT_CLEANUP +AT_SETUP([OFPT_PORT_MOD - OF1.4]) +AT_KEYWORDS([ofp-print]) +AT_CHECK([ovs-ofctl ofp-print "\ +05 10 00 28 00 00 00 03 00 00 00 03 00 00 00 00 \ +50 54 00 00 00 01 00 00 00 00 00 01 00 00 00 01 \ +00 00 00 08 00 00 00 01 +" 3], [0], [dnl +OFPT_PORT_MOD (OF1.4) (xid=0x3):port: 3: addr:50:54:00:00:00:01 + config: PORT_DOWN + mask: PORT_DOWN + advertise: 10MB-HD +]) +AT_CLEANUP + AT_SETUP([OFPT_TABLE_MOD - OF1.1]) AT_KEYWORDS([ofp-print]) AT_CHECK([ovs-ofctl ofp-print "\ diff --git a/tests/ofproto.at b/tests/ofproto.at index 2ffe653..b9c6d28 100644 --- a/tests/ofproto.at +++ b/tests/ofproto.at @@ -423,6 +423,38 @@ done OVS_VSWITCHD_STOP AT_CLEANUP +AT_SETUP([ofproto - mod-port (OpenFlow 1.4)]) +OVS_VSWITCHD_START +for command_config_state in \ + 'up 0 0' \ + 'down PORT_DOWN LINK_DOWN' \ + 'no-receive PORT_DOWN,NO_RECV LINK_DOWN' \ + 'no-forward PORT_DOWN,NO_RECV,NO_FWD LINK_DOWN' \ + 'no-packet-in PORT_DOWN,NO_RECV,NO_FWD,NO_PACKET_IN LINK_DOWN' \ + 'forward PORT_DOWN,NO_RECV,NO_PACKET_IN LINK_DOWN' \ + 'packet-in PORT_DOWN,NO_RECV LINK_DOWN' \ + 'up NO_RECV 0' \ + 'receive 0 0' +do + set $command_config_state + command=$[1] config=`echo $[2] | sed 's/,/ /g'` state=$[3] + AT_CHECK([ovs-ofctl -O OpenFlow14 -vwarn mod-port br0 br0 $command]) + AT_CHECK([ovs-ofctl -O OpenFlow14 -vwarn show br0], [0], [stdout]) + AT_CHECK_UNQUOTED([STRIP_XIDS stdout], [0], [dnl +OFPT_FEATURES_REPLY (OF1.4): dpid:fedcba9876543210 +n_tables:254, n_buffers:256 +capabilities: FLOW_STATS TABLE_STATS PORT_STATS QUEUE_STATS +OFPST_PORT_DESC reply (OF1.4): + LOCAL(br0): addr:aa:55:aa:55:00:00 + config: $config + state: $state + speed: 0 Mbps now, 0 Mbps max +OFPT_GET_CONFIG_REPLY (OF1.4): frags=normal miss_send_len=0 +]) +done +OVS_VSWITCHD_STOP +AT_CLEANUP + AT_SETUP([ofproto - basic flow_mod commands (NXM)]) OVS_VSWITCHD_START AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip], [0], [NXST_FLOW reply: -- 1.9.1 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev