static void ofport_destroy__(struct ofport *) OVS_EXCLUDED(ofproto_mutex);
static void ofport_destroy(struct ofport *);
-static void update_port(struct ofproto *, const char *devname);
+static int update_port(struct ofproto *, const char *devname);
static int init_ports(struct ofproto *);
static void reinit_ports(struct ofproto *);
static bool ofproto_group_exists(const struct ofproto *ofproto,
uint32_t group_id)
OVS_EXCLUDED(ofproto->groups_rwlock);
-static enum ofperr add_group(struct ofproto *, struct ofputil_group_mod *);
+static enum ofperr add_group(struct ofproto *,
+ const struct ofputil_group_mod *);
static void handle_openflow(struct ofconn *, const struct ofpbuf *);
static enum ofperr ofproto_flow_mod_start(struct ofproto *,
struct ofproto_flow_mod *)
ofproto->sw_desc = NULL;
ofproto->serial_desc = NULL;
ofproto->dp_desc = NULL;
- ofproto->frag_handling = OFPC_FRAG_NORMAL;
+ ofproto->frag_handling = OFPUTIL_FRAG_NORMAL;
hmap_init(&ofproto->ports);
hmap_init(&ofproto->ofport_usage);
shash_init(&ofproto->port_by_name);
simap_put(&ofproto->ofp_requests, netdev_name,
ofp_to_u16(ofp_port));
- update_port(ofproto, netdev_name);
+ error = update_port(ofproto, netdev_name);
}
if (ofp_portp) {
*ofp_portp = OFPP_NONE;
/* Adds an ofport to 'p' initialized based on the given 'netdev' and 'opp'.
* The caller must ensure that 'p' does not have a conflicting ofport (that is,
* one with the same name or port number). */
-static void
+static int
ofport_install(struct ofproto *p,
struct netdev *netdev, const struct ofputil_phy_port *pp)
{
goto error;
}
connmgr_send_port_status(p->connmgr, NULL, pp, OFPPR_ADD);
- return;
+ return 0;
error:
VLOG_WARN_RL(&rl, "%s: could not add port %s (%s)",
} else {
netdev_close(netdev);
}
+ return error;
}
/* Removes 'ofport' from 'p' and destroys it. */
return error;
}
-static void
+static int
update_port(struct ofproto *ofproto, const char *name)
{
struct ofproto_port ofproto_port;
struct ofputil_phy_port pp;
struct netdev *netdev;
struct ofport *port;
+ int error = 0;
COVERAGE_INC(ofproto_update_port);
ofport_remove(port);
}
ofport_remove_with_name(ofproto, name);
- ofport_install(ofproto, netdev, &pp);
+ error = ofport_install(ofproto, netdev, &pp);
}
} else {
/* Any port named 'name' is gone now. */
ofport_remove_with_name(ofproto, name);
}
ofproto_port_destroy(&ofproto_port);
+
+ return error;
}
static int
static enum ofperr
handle_get_config_request(struct ofconn *ofconn, const struct ofp_header *oh)
{
- struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
- struct ofp_switch_config *osc;
- enum ofp_config_flags flags;
- struct ofpbuf *buf;
+ struct ofputil_switch_config config;
+ config.frag = ofconn_get_ofproto(ofconn)->frag_handling;
+ config.invalid_ttl_to_controller
+ = ofconn_get_invalid_ttl_to_controller(ofconn);
+ config.miss_send_len = ofconn_get_miss_send_len(ofconn);
- /* Send reply. */
- buf = ofpraw_alloc_reply(OFPRAW_OFPT_GET_CONFIG_REPLY, oh, 0);
- osc = ofpbuf_put_uninit(buf, sizeof *osc);
- flags = ofproto->frag_handling;
- /* OFPC_INVALID_TTL_TO_CONTROLLER is deprecated in OF 1.3 */
- if (oh->version < OFP13_VERSION
- && ofconn_get_invalid_ttl_to_controller(ofconn)) {
- flags |= OFPC_INVALID_TTL_TO_CONTROLLER;
- }
- osc->flags = htons(flags);
- osc->miss_send_len = htons(ofconn_get_miss_send_len(ofconn));
- ofconn_send_reply(ofconn, buf);
+ ofconn_send_reply(ofconn, ofputil_encode_get_config_reply(oh, &config));
return 0;
}
static enum ofperr
handle_set_config(struct ofconn *ofconn, const struct ofp_header *oh)
{
- const struct ofp_switch_config *osc = ofpmsg_body(oh);
struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
- uint16_t flags = ntohs(osc->flags);
+ struct ofputil_switch_config config;
+ enum ofperr error;
+
+ error = ofputil_decode_set_config(oh, &config);
+ if (error) {
+ return error;
+ }
if (ofconn_get_type(ofconn) != OFCONN_PRIMARY
|| ofconn_get_role(ofconn) != OFPCR12_ROLE_SLAVE) {
- enum ofp_config_flags cur = ofproto->frag_handling;
- enum ofp_config_flags next = flags & OFPC_FRAG_MASK;
+ enum ofputil_frag_handling cur = ofproto->frag_handling;
+ enum ofputil_frag_handling next = config.frag;
- ovs_assert((cur & OFPC_FRAG_MASK) == cur);
if (cur != next) {
if (ofproto->ofproto_class->set_frag_handling(ofproto, next)) {
ofproto->frag_handling = next;
}
}
}
- /* OFPC_INVALID_TTL_TO_CONTROLLER is deprecated in OF 1.3 */
- ofconn_set_invalid_ttl_to_controller(ofconn,
- (oh->version < OFP13_VERSION
- && flags & OFPC_INVALID_TTL_TO_CONTROLLER));
- ofconn_set_miss_send_len(ofconn, ntohs(osc->miss_send_len));
+ if (config.invalid_ttl_to_controller >= 0) {
+ ofconn_set_invalid_ttl_to_controller(ofconn,
+ config.invalid_ttl_to_controller);
+ }
+
+ ofconn_set_miss_send_len(ofconn, config.miss_send_len);
return 0;
}
/* Get payload. */
if (po.buffer_id != UINT32_MAX) {
error = ofconn_pktbuf_retrieve(ofconn, po.buffer_id, &payload, NULL);
- if (error || !payload) {
+ if (error) {
goto exit_free_ofpacts;
}
} else {
static enum ofperr
handle_nxt_set_async_config(struct ofconn *ofconn, const struct ofp_header *oh)
{
+ struct ofputil_async_cfg basis = ofconn_get_async_config(ofconn);
+ struct ofputil_async_cfg ac;
enum ofperr error;
- uint32_t master[OAM_N_TYPES] = {0};
- uint32_t slave[OAM_N_TYPES] = {0};
- error = ofputil_decode_set_async_config(oh, master, slave, false);
+ error = ofputil_decode_set_async_config(oh, false, &basis, &ac);
if (error) {
return error;
}
- ofconn_set_async_config(ofconn, master, slave);
+ ofconn_set_async_config(ofconn, &ac);
if (ofconn_get_type(ofconn) == OFCONN_SERVICE &&
!ofconn_get_miss_send_len(ofconn)) {
ofconn_set_miss_send_len(ofconn, OFP_DEFAULT_MISS_SEND_LEN);
static enum ofperr
handle_nxt_get_async_request(struct ofconn *ofconn, const struct ofp_header *oh)
{
- struct ofpbuf *buf;
- uint32_t master[OAM_N_TYPES];
- uint32_t slave[OAM_N_TYPES];
-
- ofconn_get_async_config(ofconn, master, slave);
-
- buf = ofputil_encode_get_async_config(oh, master, slave);
- ofconn_send_reply(ofconn, buf);
+ struct ofputil_async_cfg ac = ofconn_get_async_config(ofconn);
+ ofconn_send_reply(ofconn, ofputil_encode_get_async_reply(oh, &ac));
return 0;
}
}
static void
-put_queue_config(struct ofport *ofport, struct ofpbuf *reply)
+put_queue_get_config_reply(struct ofport *port, uint32_t queue,
+ struct ovs_list *replies)
{
- struct netdev_queue_dump queue_dump;
- unsigned int queue_id;
- struct smap details;
+ struct ofputil_queue_config qc;
+
+ /* None of the existing queues have compatible properties, so we hard-code
+ * omitting min_rate and max_rate. */
+ qc.port = port->ofp_port;
+ qc.queue = queue;
+ qc.min_rate = UINT16_MAX;
+ qc.max_rate = UINT16_MAX;
+ ofputil_append_queue_get_config_reply(&qc, replies);
+}
- smap_init(&details);
- NETDEV_QUEUE_FOR_EACH (&queue_id, &details, &queue_dump, ofport->netdev) {
- struct ofputil_queue_config queue;
+static int
+handle_queue_get_config_request_for_port(struct ofport *port, uint32_t queue,
+ struct ovs_list *replies)
+{
+ struct smap details = SMAP_INITIALIZER(&details);
+ if (queue != OFPQ_ALL) {
+ int error = netdev_get_queue(port->netdev, queue, &details);
+ switch (error) {
+ case 0:
+ put_queue_get_config_reply(port, queue, replies);
+ break;
+ case EOPNOTSUPP:
+ case EINVAL:
+ return OFPERR_OFPQOFC_BAD_QUEUE;
+ default:
+ return OFPERR_NXQOFC_QUEUE_ERROR;
+ }
+ } else {
+ struct netdev_queue_dump queue_dump;
+ uint32_t queue_id;
- /* None of the existing queues have compatible properties, so we
- * hard-code omitting min_rate and max_rate. */
- queue.port = ofport->ofp_port;
- queue.queue_id = queue_id;
- queue.min_rate = UINT16_MAX;
- queue.max_rate = UINT16_MAX;
- ofputil_append_queue_get_config_reply(reply, &queue);
- }
- smap_destroy(&details);
+ NETDEV_QUEUE_FOR_EACH (&queue_id, &details, &queue_dump,
+ port->netdev) {
+ put_queue_get_config_reply(port, queue_id, replies);
+ }
+ }
+ smap_destroy(&details);
+ return 0;
}
static enum ofperr
handle_queue_get_config_request(struct ofconn *ofconn,
const struct ofp_header *oh)
{
- struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
- ofp_port_t port;
- enum ofperr error;
-
- error = ofputil_decode_queue_get_config_request(oh, &port);
- if (error) {
- return error;
- }
-
- struct ofpbuf *reply = ofputil_encode_queue_get_config_reply(oh);
- struct ofport *ofport;
- if (port == OFPP_ANY) {
- HMAP_FOR_EACH (ofport, hmap_node, &ofproto->ports) {
- put_queue_config(ofport, reply);
- }
- } else {
- ofport = ofproto_get_port(ofproto, port);
- if (!ofport) {
- ofpbuf_delete(reply);
- return OFPERR_OFPQOFC_BAD_PORT;
- }
- put_queue_config(ofport, reply);
- }
- ofconn_send_reply(ofconn, reply);
-
- return 0;
+ struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
+ struct ovs_list replies;
+ struct ofport *port;
+ ofp_port_t req_port;
+ uint32_t req_queue;
+ enum ofperr error;
+
+ error = ofputil_decode_queue_get_config_request(oh, &req_port, &req_queue);
+ if (error) {
+ return error;
+ }
+
+ ofputil_start_queue_get_config_reply(oh, &replies);
+ if (req_port == OFPP_ANY) {
+ error = OFPERR_OFPQOFC_BAD_QUEUE;
+ HMAP_FOR_EACH (port, hmap_node, &ofproto->ports) {
+ if (!handle_queue_get_config_request_for_port(port, req_queue,
+ &replies)) {
+ error = 0;
+ }
+ }
+ } else {
+ port = ofproto_get_port(ofproto, req_port);
+ error = (port
+ ? handle_queue_get_config_request_for_port(port, req_queue,
+ &replies)
+ : OFPERR_OFPQOFC_BAD_PORT);
+ }
+ if (!error) {
+ ofconn_send_replies(ofconn, &replies);
+ } else {
+ ofpbuf_list_delete(&replies);
+ }
+
+ return error;
}
static enum ofperr
-init_group(struct ofproto *ofproto, struct ofputil_group_mod *gm,
+init_group(struct ofproto *ofproto, const struct ofputil_group_mod *gm,
struct ofgroup **ofgroup)
{
enum ofperr error;
*CONST_CAST(long long int *, &((*ofgroup)->modified)) = now;
ovs_refcount_init(&(*ofgroup)->ref_count);
- list_move(&(*ofgroup)->buckets, &gm->buckets);
+ list_init(&(*ofgroup)->buckets);
+ ofputil_bucket_clone_list(&(*ofgroup)->buckets, &gm->buckets, NULL);
+
*CONST_CAST(uint32_t *, &(*ofgroup)->n_buckets) =
list_size(&(*ofgroup)->buckets);
* 'ofproto''s group table. Returns 0 on success or an OpenFlow error code on
* failure. */
static enum ofperr
-add_group(struct ofproto *ofproto, struct ofputil_group_mod *gm)
+add_group(struct ofproto *ofproto, const struct ofputil_group_mod *gm)
{
struct ofgroup *ofgroup;
enum ofperr error;
* ofproto's ofgroup hash map. Thus, the group is never altered while users of
* the xlate module hold a pointer to the group. */
static enum ofperr
-modify_group(struct ofproto *ofproto, struct ofputil_group_mod *gm)
+modify_group(struct ofproto *ofproto, const struct ofputil_group_mod *gm)
{
struct ofgroup *ofgroup, *new_ofgroup, *retiring;
enum ofperr error;
VLOG_INFO_RL(&rl, "%s: Invalid group_mod command type %d",
ofproto->name, gm.command);
}
- return OFPERR_OFPGMFC_BAD_COMMAND;
+ error = OFPERR_OFPGMFC_BAD_COMMAND;
}
if (!error) {
rf.group_mod = &gm;
connmgr_send_requestforward(ofproto->connmgr, ofconn, &rf);
}
+ ofputil_bucket_list_destroy(&gm.buckets);
+
return error;
}