From: Venkitachalam Gopalakrishnan <g...@vmware.com> --- lib/ofp-util.c | 32 ++++++++++++++++++++++ lib/ofp-util.h | 5 ++++ ofproto/ofproto.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++- utilities/ovs-ofctl.c | 42 ++++++++++++++++++++++++++++ 4 files changed, 151 insertions(+), 1 deletion(-)
diff --git a/lib/ofp-util.c b/lib/ofp-util.c index b181a0d..93e3f14 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -2185,6 +2185,38 @@ ofputil_decode_nxst_flow_request(struct ofputil_flow_stats_request *fsr, return 0; } +/* Decode func to decode a queue_get_config_request. */ +enum ofperr +ofputil_decode_queue_get_config_request + (struct ofp11_queue_get_config_request *request, + const struct ofp_header *oh) +{ + enum ofpraw raw; + struct ofpbuf b; + enum ofperr status; + struct ofp11_queue_get_config_request *inreq; + ofp_port_t ofp_port; + + ofpbuf_use_const(&b, oh, ntohs(oh->length)); + raw = ofpraw_pull_assert(&b); + + switch ((int)raw) { + /* There is no 1.0 decode yet. To be added later. */ + + case OFPRAW_OFPT11_QUEUE_GET_CONFIG_REQUEST: + inreq = (struct ofp11_queue_get_config_request *) (b.data); + if ((status = ofputil_port_from_ofp11(inreq->port, &ofp_port)) != 0) + return status; + + request->port = ofputil_port_to_ofp11(ofp_port); + return 0; + + default: + NOT_REACHED(); + } + return 0; +} + /* Converts an OFPST_FLOW, OFPST_AGGREGATE, NXST_FLOW, or NXST_AGGREGATE * request 'oh', into an abstract flow_stats_request in 'fsr'. Returns 0 if * successful, otherwise an OpenFlow error code. */ diff --git a/lib/ofp-util.h b/lib/ofp-util.h index 6de2a05..7e2a769 100644 --- a/lib/ofp-util.h +++ b/lib/ofp-util.h @@ -26,6 +26,7 @@ #include "match.h" #include "netdev.h" #include "openflow/nicira-ext.h" +#include "openflow/openflow-1.1.h" #include "openvswitch/types.h" #include "type-props.h" @@ -331,6 +332,10 @@ int ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *, void ofputil_append_flow_stats_reply(const struct ofputil_flow_stats *, struct list *replies); +enum ofperr ofputil_decode_queue_get_config_request( + struct ofp11_queue_get_config_request *request, + const struct ofp_header *); + /* Aggregate stats reply, independent of protocol. */ struct ofputil_aggregate_stats { uint64_t packet_count; /* Packet count, UINT64_MAX if unknown. */ diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index dacbb71..791332e 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -49,6 +49,7 @@ #include "random.h" #include "shash.h" #include "simap.h" +#include "smap.h" #include "sset.h" #include "timeval.h" #include "unaligned.h" @@ -4880,6 +4881,74 @@ handle_group_features_stats_request(struct ofconn *ofconn, return 0; } +static enum ofperr +handle_queue_get_config_request(struct ofconn *ofconn, + const struct ofp_header *oh) +{ + struct ofproto *p = ofconn_get_ofproto(ofconn); + struct ofpbuf *msg; + struct ofp11_queue_get_config_request request; + struct ofp11_queue_get_config_reply reply; + struct ofport *ofp_port; + enum ofperr oferr; + struct netdev_queue_dump queue_dump; + unsigned int queue_id; + struct smap details; + + /* The reply here has + * the port which is queried + * A list of queue_properties. + * We will add the port to the msg and then + * append each queue property via encode and finally send + * the reply. + */ + + /* Decode the request. */ + oferr = ofputil_decode_queue_get_config_request(&request, oh); + if (oferr != 0) + return oferr; + + /* Now check whether this port number actually exists. */ + if (!(ofp_port = ofproto_get_port(p, request.port))) { + return OFPERR_OFPQOFC_BAD_PORT; + } + + /* Now let us form the reply buffer. + * First add the port to it. + */ + msg = ofpraw_alloc_reply(OFPRAW_OFPT11_QUEUE_GET_CONFIG_REPLY, + oh, 0); + + memset(&reply, 0x00, sizeof(reply)); + reply.port = ofputil_port_to_ofp11(request.port); + ofpbuf_put(msg, &reply, sizeof(reply)); + + /* Now we will loop thro each queue for this port and + * add that to the buffer before we reply. */ + + smap_init(&details); + + NETDEV_QUEUE_FOR_EACH(&queue_id, &details, &queue_dump, ofp_port->netdev) { + struct ofp_packet_queue q; + memset(&q, 0x00, sizeof(struct ofp_packet_queue)); + + q.queue_id = htonl(queue_id); + q.len = htons(sizeof(struct ofp_packet_queue)); + + /* Todo - at a later time, if the queue struct adds more fields, + * we would have to add an encode API to get the data encoded + * which would be added to the msg here. + */ + ofpbuf_put(msg, &q, sizeof(struct ofp_packet_queue)); + } + + smap_destroy(&details); + + ofconn_send_reply(ofconn, msg); + + return 0; +} + /* Implements OFPGC11_ADD * in which no matching flow already exists in the flow table. * @@ -5230,8 +5299,10 @@ handle_openflow__(struct ofconn *ofconn, const struct ofpbuf *msg) case OFPTYPE_GROUP_FEATURES_STATS_REQUEST: return handle_group_features_stats_request(ofconn, oh); - /* FIXME: Change the following once they are implemented: */ case OFPTYPE_QUEUE_GET_CONFIG_REQUEST: + return handle_queue_get_config_request(ofconn, oh); + + /* FIXME: Change the following once they are implemented: */ case OFPTYPE_GET_ASYNC_REQUEST: case OFPTYPE_TABLE_FEATURES_STATS_REQUEST: return OFPERR_OFPBRC_BAD_TYPE; diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c index 9294752..10f10fe 100644 --- a/utilities/ovs-ofctl.c +++ b/utilities/ovs-ofctl.c @@ -308,6 +308,7 @@ usage(void) " dump-group-features SWITCH print group features\n" " dump-groups SWITCH print group description\n" " dump-group-stats SWITCH [GROUP] print group statistics\n" + " queue-get-config SWITCH PORT print queue information for port\n" "\nFor OpenFlow switches and controllers:\n" " probe TARGET probe whether TARGET is up\n" " ping TARGET [N] latency of N-byte echos\n" @@ -2935,6 +2936,46 @@ ofctl_parse_ofp11_instructions(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) ds_destroy(&in); } +static void +ofctl_queue_get_config(int argc OVS_UNUSED, char *argv[]) +{ + uint32_t port; + const char *vconn_name = argv[1]; + struct vconn *vconn; + struct ofp11_queue_get_config_request ovs_request; + struct ofpbuf *request; + struct ofpbuf *reply; + bool convert = true; + uint32_t inport; + char *end = NULL; + + open_vconn(vconn_name, &vconn); + request = ofpraw_alloc(OFPRAW_OFPT11_QUEUE_GET_CONFIG_REQUEST, + vconn_get_version(vconn), 0); + + memset(&ovs_request, 0x00, sizeof(ovs_request)); + + VLOG_WARN("Getting queue config for %s %s", + argv[1], argv[2]); + + inport = strtoul(argv[2], &end, 10); + if (*argv[2] != '\0' && *end == '\0') { + convert = false; + } + + if (convert) { + port = str_to_port_no(argv[1], argv[2]); + ovs_request.port = ofputil_port_to_ofp11(port); + VLOG_WARN("Converted port is %d", ovs_request.port); + } else { + ovs_request.port = htonl(inport); + VLOG_WARN("Un Converted port is %d", ovs_request.port); + } + ofpbuf_put(request, &ovs_request, sizeof(ovs_request)); + run(vconn_transact(vconn, request, &reply), "talking to %s", vconn_name); +} + + /* "check-vlan VLAN_TCI VLAN_TCI_MASK": converts the specified vlan_tci and * mask values to and from various formats and prints the results. */ static void @@ -3179,6 +3220,7 @@ static const struct command all_commands[] = { { "parse-ofp11-match", 0, 0, ofctl_parse_ofp11_match }, { "parse-ofp11-actions", 0, 0, ofctl_parse_ofp11_actions }, { "parse-ofp11-instructions", 0, 0, ofctl_parse_ofp11_instructions }, + { "queue-get-config", 2, 2, ofctl_queue_get_config }, { "check-vlan", 2, 2, ofctl_check_vlan }, { "print-error", 1, 1, ofctl_print_error }, { "encode-error-reply", 2, 2, ofctl_encode_error_reply }, -- 1.7.10.4 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev