X-Git-Url: http://git.cascardo.eti.br/?a=blobdiff_plain;f=ofproto%2Fofproto.c;h=1335da6757507f4136625b05dd3eff33f57d4a1f;hb=6c6eedc5d6730835a0d9724e2e8cfe9cdf03b07d;hp=4f69cc2c9dcef7b72941273e20bade8118874f7a;hpb=bab86012066c353c75d2b8446c25daea2471d939;p=cascardo%2Fovs.git diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index 4f69cc2c9..1335da675 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2015 Nicira, Inc. + * Copyright (c) 2009-2016 Nicira, Inc. * Copyright (c) 2010 Jean Tourrilhes - HP-Labs. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -217,9 +217,9 @@ static void learned_cookies_flush(struct ofproto *, struct ovs_list *dead_cookie /* ofport. */ static void ofport_destroy__(struct ofport *) OVS_EXCLUDED(ofproto_mutex); -static void ofport_destroy(struct ofport *); +static void ofport_destroy(struct ofport *, bool del); -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 *); @@ -297,7 +297,8 @@ static bool ofproto_group_exists__(const struct ofproto *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 *) @@ -336,7 +337,6 @@ unsigned ofproto_flow_limit = OFPROTO_FLOW_LIMIT_DEFAULT; unsigned ofproto_max_idle = OFPROTO_MAX_IDLE_DEFAULT; size_t n_handlers, n_revalidators; -size_t n_dpdk_rxqs; char *pmd_cpu_mask; /* Map from datapath name to struct ofproto, for use by unixctl commands. */ @@ -544,7 +544,7 @@ ofproto_create(const char *datapath_name, const char *datapath_type, 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); @@ -779,12 +779,6 @@ ofproto_port_set_mcast_snooping(struct ofproto *ofproto, void *aux, : EOPNOTSUPP); } -void -ofproto_set_n_dpdk_rxqs(int n_rxqs) -{ - n_dpdk_rxqs = MAX(n_rxqs, 0); -} - void ofproto_set_cpu_mask(const char *cmask) { @@ -1579,7 +1573,7 @@ ofproto_destroy_defer__(struct ofproto *ofproto) } void -ofproto_destroy(struct ofproto *p) +ofproto_destroy(struct ofproto *p, bool del) OVS_EXCLUDED(ofproto_mutex) { struct ofport *ofport, *next_ofport; @@ -1598,7 +1592,7 @@ ofproto_destroy(struct ofproto *p) ofproto_flush__(p); HMAP_FOR_EACH_SAFE (ofport, next_ofport, hmap_node, &p->ports) { - ofport_destroy(ofport); + ofport_destroy(ofport, del); } HMAP_FOR_EACH_SAFE (usage, next_usage, hmap_node, &p->ofport_usage) { @@ -1961,7 +1955,7 @@ ofproto_port_add(struct ofproto *ofproto, struct netdev *netdev, 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; @@ -2033,24 +2027,18 @@ flow_mod_init(struct ofputil_flow_mod *fm, const struct ofpact *ofpacts, size_t ofpacts_len, enum ofp_flow_mod_command command) { - memset(fm, 0, sizeof *fm); - fm->match = *match; - fm->priority = priority; - fm->cookie = 0; - fm->new_cookie = 0; - fm->modify_cookie = false; - fm->table_id = 0; - fm->command = command; - fm->idle_timeout = 0; - fm->hard_timeout = 0; - fm->importance = 0; - fm->buffer_id = UINT32_MAX; - fm->out_port = OFPP_ANY; - fm->out_group = OFPG_ANY; - fm->flags = 0; - fm->ofpacts = CONST_CAST(struct ofpact *, ofpacts); - fm->ofpacts_len = ofpacts_len; - fm->delete_reason = OFPRR_DELETE; + *fm = (struct ofputil_flow_mod) { + .match = *match, + .priority = priority, + .table_id = 0, + .command = command, + .buffer_id = UINT32_MAX, + .out_port = OFPP_ANY, + .out_group = OFPG_ANY, + .ofpacts = CONST_CAST(struct ofpact *, ofpacts), + .ofpacts_len = ofpacts_len, + .delete_reason = OFPRR_DELETE, + }; } static int @@ -2351,7 +2339,7 @@ ofport_equal(const struct ofputil_phy_port *a, /* 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) { @@ -2385,7 +2373,7 @@ ofport_install(struct ofproto *p, 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)", @@ -2395,6 +2383,7 @@ error: } else { netdev_close(netdev); } + return error; } /* Removes 'ofport' from 'p' and destroys it. */ @@ -2403,7 +2392,7 @@ ofport_remove(struct ofport *ofport) { connmgr_send_port_status(ofport->ofproto->connmgr, NULL, &ofport->pp, OFPPR_DELETE); - ofport_destroy(ofport); + ofport_destroy(ofport, true); } /* If 'ofproto' contains an ofport named 'name', removes it from 'ofproto' and @@ -2489,11 +2478,11 @@ ofport_destroy__(struct ofport *port) } static void -ofport_destroy(struct ofport *port) +ofport_destroy(struct ofport *port, bool del) { if (port) { dealloc_ofp_port(port->ofproto, port->ofp_port); - port->ofproto->ofproto_class->port_destruct(port); + port->ofproto->ofproto_class->port_destruct(port, del); ofport_destroy__(port); } } @@ -2576,13 +2565,14 @@ ofproto_port_get_stats(const struct ofport *port, struct netdev_stats *stats) 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); @@ -2622,13 +2612,15 @@ update_port(struct ofproto *ofproto, const char *name) 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 @@ -3255,23 +3247,13 @@ handle_features_request(struct ofconn *ofconn, const struct ofp_header *oh) 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; } @@ -3279,16 +3261,20 @@ handle_get_config_request(struct ofconn *ofconn, const struct ofp_header *oh) 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; @@ -3299,12 +3285,13 @@ handle_set_config(struct ofconn *ofconn, const struct ofp_header *oh) } } } - /* 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; } @@ -3388,7 +3375,7 @@ handle_packet_out(struct ofconn *ofconn, const struct ofp_header *oh) /* 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 { @@ -3424,6 +3411,27 @@ exit: return error; } +static enum ofperr +handle_nxt_resume(struct ofconn *ofconn, const struct ofp_header *oh) +{ + struct ofproto *ofproto = ofconn_get_ofproto(ofconn); + struct ofputil_packet_in_private pin; + enum ofperr error; + + error = ofputil_decode_packet_in_private(oh, false, &pin, NULL, NULL); + if (error) { + return error; + } + + error = (ofproto->ofproto_class->nxt_resume + ? ofproto->ofproto_class->nxt_resume(ofproto, &pin) + : OFPERR_NXR_NOT_SUPPORTED); + + ofputil_packet_in_private_destroy(&pin); + + return error; +} + static void update_port_config(struct ofconn *ofconn, struct ofport *port, enum ofputil_port_config config, @@ -3562,21 +3570,19 @@ handle_table_features_request(struct ofconn *ofconn, const struct ofp_header *request) { struct ofproto *ofproto = ofconn_get_ofproto(ofconn); - struct ofputil_table_features *features; - struct ovs_list replies; - struct ofpbuf msg; - size_t i; - - ofpbuf_use_const(&msg, request, ntohs(request->length)); + struct ofpbuf msg = ofpbuf_const_initializer(request, + ntohs(request->length)); ofpraw_pull_assert(&msg); if (msg.size || ofpmp_more(request)) { return OFPERR_OFPTFFC_EPERM; } + struct ofputil_table_features *features; query_tables(ofproto, &features, NULL); + struct ovs_list replies; ofpmp_init(&replies, request); - for (i = 0; i < ofproto->n_tables; i++) { + for (size_t i = 0; i < ofproto->n_tables; i++) { if (!(ofproto->tables[i].flags & OFTABLE_HIDDEN)) { ofputil_append_table_features_reply(&features[i], &replies); } @@ -3588,24 +3594,35 @@ handle_table_features_request(struct ofconn *ofconn, return 0; } +/* Returns the vacancy of 'oftable', a number that ranges from 0 (if the table + * is full) to 100 (if the table is empty). + * + * A table without a limit on flows is considered to be empty. */ +static uint8_t +oftable_vacancy(const struct oftable *t) +{ + return (!t->max_flows ? 100 + : t->n_flows >= t->max_flows ? 0 + : (t->max_flows - t->n_flows) * 100.0 / t->max_flows); +} + static void query_table_desc__(struct ofputil_table_desc *td, struct ofproto *ofproto, uint8_t table_id) { - unsigned int count = ofproto->tables[table_id].n_flows; - unsigned int max_flows = ofproto->tables[table_id].max_flows; + const struct oftable *t = &ofproto->tables[table_id]; td->table_id = table_id; - td->eviction = (ofproto->tables[table_id].eviction & EVICTION_OPENFLOW + td->eviction = (t->eviction & EVICTION_OPENFLOW ? OFPUTIL_TABLE_EVICTION_ON : OFPUTIL_TABLE_EVICTION_OFF); td->eviction_flags = OFPROTO_EVICTION_FLAGS; - td->vacancy = (ofproto->tables[table_id].vacancy_enabled + td->vacancy = (t->vacancy_event ? OFPUTIL_TABLE_VACANCY_ON : OFPUTIL_TABLE_VACANCY_OFF); - td->table_vacancy.vacancy_down = ofproto->tables[table_id].vacancy_down; - td->table_vacancy.vacancy_up = ofproto->tables[table_id].vacancy_up; - td->table_vacancy.vacancy = max_flows ? (count * 100) / max_flows : 0; + td->table_vacancy.vacancy_down = t->vacancy_down; + td->table_vacancy.vacancy_up = t->vacancy_up; + td->table_vacancy.vacancy = oftable_vacancy(t); } /* This function queries the database for dumping table-desc. */ @@ -3645,6 +3662,40 @@ handle_table_desc_request(struct ofconn *ofconn, return 0; } +/* This function determines and sends the vacancy event, based on the value + * of current vacancy and threshold vacancy. If the current vacancy is less + * than or equal to vacancy_down, vacancy up events must be enabled, and when + * the current vacancy is greater or equal to vacancy_up, vacancy down events + * must be enabled. */ +static void +send_table_status(struct ofproto *ofproto, uint8_t table_id) +{ + struct oftable *t = &ofproto->tables[table_id]; + if (!t->vacancy_event) { + return; + } + + uint8_t vacancy = oftable_vacancy(t); + enum ofp14_table_reason event; + if (vacancy < t->vacancy_down) { + event = OFPTR_VACANCY_DOWN; + } else if (vacancy > t->vacancy_up) { + event = OFPTR_VACANCY_UP; + } else { + return; + } + + if (event == t->vacancy_event) { + struct ofputil_table_desc td; + query_table_desc__(&td, ofproto, table_id); + connmgr_send_table_status(ofproto->connmgr, &td, event); + + t->vacancy_event = (event == OFPTR_VACANCY_DOWN + ? OFPTR_VACANCY_UP + : OFPTR_VACANCY_DOWN); + } +} + static void append_port_stat(struct ofport *port, struct ovs_list *replies) { @@ -4680,6 +4731,9 @@ add_flow_finish(struct ofproto *ofproto, struct ofproto_flow_mod *ofm, ofmonitor_report(ofproto->connmgr, new_rule, NXFME_ADDED, 0, req ? req->ofconn : NULL, req ? req->request->xid : 0, NULL); + + /* Send Vacancy Events for OF1.4+. */ + send_table_status(ofproto, new_rule->table_id); } send_buffered_packet(req, fm->buffer_id, new_rule); @@ -5075,6 +5129,10 @@ delete_flows_finish__(struct ofproto *ofproto, ofmonitor_report(ofproto->connmgr, rule, NXFME_DELETED, reason, req ? req->ofconn : NULL, req ? req->request->xid : 0, NULL); + + /* Send Vacancy Event for OF1.4+. */ + send_table_status(ofproto, rule->table_id); + ofproto_rule_remove__(ofproto, rule); learned_cookies_dec(ofproto, rule_get_actions(rule), &dead_cookies); @@ -5402,7 +5460,7 @@ handle_nxt_set_packet_in_format(struct ofconn *ofconn, uint32_t format; format = ntohl(msg->format); - if (format != NXPIF_OPENFLOW10 && format != NXPIF_NXM) { + if (!ofputil_packet_in_format_is_valid(format)) { return OFPERR_OFPBRC_EPERM; } @@ -5413,12 +5471,16 @@ handle_nxt_set_packet_in_format(struct ofconn *ofconn, static enum ofperr handle_nxt_set_async_config(struct ofconn *ofconn, const struct ofp_header *oh) { - uint32_t master[OAM_N_TYPES] = {0}; - uint32_t slave[OAM_N_TYPES] = {0}; + struct ofputil_async_cfg basis = ofconn_get_async_config(ofconn); + struct ofputil_async_cfg ac; + enum ofperr 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); @@ -5430,14 +5492,8 @@ handle_nxt_set_async_config(struct ofconn *ofconn, const struct ofp_header *oh) 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; } @@ -5617,17 +5673,14 @@ handle_flow_monitor_request(struct ofconn *ofconn, const struct ofp_header *oh) OVS_EXCLUDED(ofproto_mutex) { struct ofproto *ofproto = ofconn_get_ofproto(ofconn); - struct ofmonitor **monitors; - size_t n_monitors, allocated_monitors; - struct rule_collection rules; - struct ovs_list replies; - enum ofperr error; - struct ofpbuf b; - size_t i; - ofpbuf_use_const(&b, oh, ntohs(oh->length)); - monitors = NULL; - n_monitors = allocated_monitors = 0; + struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length)); + + struct ofmonitor **monitors = NULL; + size_t allocated_monitors = 0; + size_t n_monitors = 0; + + enum ofperr error; ovs_mutex_lock(&ofproto_mutex); for (;;) { @@ -5661,11 +5714,13 @@ handle_flow_monitor_request(struct ofconn *ofconn, const struct ofp_header *oh) monitors[n_monitors++] = m; } + struct rule_collection rules; rule_collection_init(&rules); - for (i = 0; i < n_monitors; i++) { + for (size_t i = 0; i < n_monitors; i++) { ofproto_collect_ofmonitor_initial_rules(monitors[i], &rules); } + struct ovs_list replies; ofpmp_init(&replies, oh); ofmonitor_compose_refresh_updates(&rules, &replies); ovs_mutex_unlock(&ofproto_mutex); @@ -5678,7 +5733,7 @@ handle_flow_monitor_request(struct ofconn *ofconn, const struct ofp_header *oh) return 0; error: - for (i = 0; i < n_monitors; i++) { + for (size_t i = 0; i < n_monitors; i++) { ofmonitor_destroy(monitors[i]); } free(monitors); @@ -6232,51 +6287,94 @@ 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) +static void +put_queue_get_config_reply(struct ofport *port, uint32_t queue, + struct ovs_list *replies) { - struct ofproto *p = ofconn_get_ofproto(ofconn); - struct netdev_queue_dump queue_dump; - struct ofport *ofport; - unsigned int queue_id; - struct ofpbuf *reply; - struct smap details; - ofp_port_t request; - enum ofperr error; + struct ofputil_queue_config qc; - error = ofputil_decode_queue_get_config_request(oh, &request); - if (error) { - return error; - } + /* 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); +} - ofport = ofproto_get_port(p, request); - if (!ofport) { - return OFPERR_OFPQOFC_BAD_PORT; - } +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; - reply = ofputil_encode_queue_get_config_reply(oh); + 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; +} - smap_init(&details); - NETDEV_QUEUE_FOR_EACH (&queue_id, &details, &queue_dump, ofport->netdev) { - struct ofputil_queue_config queue; +static enum ofperr +handle_queue_get_config_request(struct ofconn *ofconn, + const struct ofp_header *oh) +{ + 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; - /* None of the existing queues have compatible properties, so we - * hard-code omitting min_rate and max_rate. */ - 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); + error = ofputil_decode_queue_get_config_request(oh, &req_port, &req_queue); + if (error) { + return error; + } - ofconn_send_reply(ofconn, reply); + 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 0; + 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; @@ -6302,7 +6400,9 @@ init_group(struct ofproto *ofproto, struct ofputil_group_mod *gm, *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); @@ -6322,7 +6422,7 @@ init_group(struct ofproto *ofproto, struct ofputil_group_mod *gm, * '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; @@ -6470,7 +6570,7 @@ copy_buckets_for_remove_bucket(const struct ofgroup *ofgroup, * 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; @@ -6544,6 +6644,7 @@ delete_group__(struct ofproto *ofproto, struct ofgroup *ofgroup) flow_mod_init(&ofm.fm, &match, 0, NULL, 0, OFPFC_DELETE); ofm.fm.delete_reason = OFPRR_GROUP_DELETE; ofm.fm.out_group = ofgroup->group_id; + ofm.fm.table_id = OFPTT_ALL; handle_flow_mod__(ofproto, &ofm, NULL); hmap_remove(&ofproto->groups, &ofgroup->hmap_node); @@ -6638,7 +6739,7 @@ handle_group_mod(struct ofconn *ofconn, const struct ofp_header *oh) 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) { @@ -6648,6 +6749,8 @@ handle_group_mod(struct ofconn *ofconn, const struct ofp_header *oh) rf.group_mod = &gm; connmgr_send_requestforward(ofproto->connmgr, ofconn, &rf); } + ofputil_bucket_list_destroy(&gm.buckets); + return error; } @@ -6689,11 +6792,16 @@ table_mod__(struct oftable *oftable, if (tm->vacancy != OFPUTIL_TABLE_VACANCY_DEFAULT) { ovs_mutex_lock(&ofproto_mutex); - oftable->vacancy_enabled = (tm->vacancy == OFPUTIL_TABLE_VACANCY_ON - ? OFPTC14_VACANCY_EVENTS - : 0); oftable->vacancy_down = tm->table_vacancy.vacancy_down; oftable->vacancy_up = tm->table_vacancy.vacancy_up; + if (tm->vacancy == OFPUTIL_TABLE_VACANCY_OFF) { + oftable->vacancy_event = 0; + } else if (!oftable->vacancy_event) { + uint8_t vacancy = oftable_vacancy(oftable); + oftable->vacancy_event = (vacancy < oftable->vacancy_up + ? OFPTR_VACANCY_UP + : OFPTR_VACANCY_DOWN); + } ovs_mutex_unlock(&ofproto_mutex); } } @@ -7058,9 +7166,9 @@ handle_bundle_add(struct ofconn *ofconn, const struct ofp_header *oh) } static enum ofperr -handle_geneve_table_mod(struct ofconn *ofconn, const struct ofp_header *oh) +handle_tlv_table_mod(struct ofconn *ofconn, const struct ofp_header *oh) { - struct ofputil_geneve_table_mod gtm; + struct ofputil_tlv_table_mod ttm; enum ofperr error; error = reject_slave_controller(ofconn); @@ -7068,26 +7176,26 @@ handle_geneve_table_mod(struct ofconn *ofconn, const struct ofp_header *oh) return error; } - error = ofputil_decode_geneve_table_mod(oh, >m); + error = ofputil_decode_tlv_table_mod(oh, &ttm); if (error) { return error; } - error = tun_metadata_table_mod(>m); + error = tun_metadata_table_mod(&ttm); - ofputil_uninit_geneve_table(>m.mappings); + ofputil_uninit_tlv_table(&ttm.mappings); return error; } static enum ofperr -handle_geneve_table_request(struct ofconn *ofconn, const struct ofp_header *oh) +handle_tlv_table_request(struct ofconn *ofconn, const struct ofp_header *oh) { - struct ofputil_geneve_table_reply gtr; + struct ofputil_tlv_table_reply ttr; struct ofpbuf *b; - tun_metadata_table_request(>r); - b = ofputil_encode_geneve_table_reply(oh, >r); - ofputil_uninit_geneve_table(>r.mappings); + tun_metadata_table_request(&ttr); + b = ofputil_encode_tlv_table_reply(oh, &ttr); + ofputil_uninit_tlv_table(&ttr.mappings); ofconn_send_reply(ofconn, b); return 0; @@ -7181,6 +7289,9 @@ handle_openflow__(struct ofconn *ofconn, const struct ofpbuf *msg) case OFPTYPE_GET_ASYNC_REQUEST: return handle_nxt_get_async_request(ofconn, oh); + case OFPTYPE_NXT_RESUME: + return handle_nxt_resume(ofconn, oh); + /* Statistics requests. */ case OFPTYPE_DESC_STATS_REQUEST: return handle_desc_stats_request(ofconn, oh); @@ -7237,11 +7348,11 @@ handle_openflow__(struct ofconn *ofconn, const struct ofpbuf *msg) case OFPTYPE_BUNDLE_ADD_MESSAGE: return handle_bundle_add(ofconn, oh); - case OFPTYPE_NXT_GENEVE_TABLE_MOD: - return handle_geneve_table_mod(ofconn, oh); + case OFPTYPE_NXT_TLV_TABLE_MOD: + return handle_tlv_table_mod(ofconn, oh); - case OFPTYPE_NXT_GENEVE_TABLE_REQUEST: - return handle_geneve_table_request(ofconn, oh); + case OFPTYPE_NXT_TLV_TABLE_REQUEST: + return handle_tlv_table_request(ofconn, oh); case OFPTYPE_HELLO: case OFPTYPE_ERROR: @@ -7274,7 +7385,8 @@ handle_openflow__(struct ofconn *ofconn, const struct ofpbuf *msg) case OFPTYPE_TABLE_DESC_REPLY: case OFPTYPE_ROLE_STATUS: case OFPTYPE_REQUESTFORWARD: - case OFPTYPE_NXT_GENEVE_TABLE_REPLY: + case OFPTYPE_TABLE_STATUS: + case OFPTYPE_NXT_TLV_TABLE_REPLY: default: if (ofpmsg_is_stat_request(oh)) { return OFPERR_OFPBRC_BAD_STAT;