X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=ofproto%2Fofproto.c;h=af02a0e35664e5dbc6254b93e115dd0fb58b214a;hb=59d0f2c8a0a16ef5ebc35e815bd82605b70fa7e2;hp=7543e1140bbc1958b06b99407a62fcb14846cfcc;hpb=63adcc7d3fa1e136685f44edb03887222ea74bd8;p=sliver-openvswitch.git diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index 7543e1140..af02a0e35 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -603,6 +603,33 @@ ofproto_port_get_stp_status(struct ofproto *ofproto, uint16_t ofp_port, : EOPNOTSUPP); } +/* Queue DSCP configuration. */ + +/* Registers meta-data associated with the 'n_qdscp' Qualities of Service + * 'queues' attached to 'ofport'. This data is not intended to be sufficient + * to implement QoS. Instead, it is used to implement features which require + * knowledge of what queues exist on a port, and some basic information about + * them. + * + * Returns 0 if successful, otherwise a positive errno value. */ +int +ofproto_port_set_queues(struct ofproto *ofproto, uint16_t ofp_port, + const struct ofproto_port_queue *queues, + size_t n_queues) +{ + struct ofport *ofport = ofproto_get_port(ofproto, ofp_port); + + if (!ofport) { + VLOG_WARN("%s: cannot set queues on nonexistent port %"PRIu16, + ofproto->name, ofp_port); + return ENODEV; + } + + return (ofproto->ofproto_class->set_queues + ? ofproto->ofproto_class->set_queues(ofport, queues, n_queues) + : EOPNOTSUPP); +} + /* Connectivity Fault Management configuration. */ /* Clears the CFM configuration from 'ofp_port' on 'ofproto'. */ @@ -1367,6 +1394,9 @@ ofproto_port_unregister(struct ofproto *ofproto, uint16_t ofp_port) { struct ofport *port = ofproto_get_port(ofproto, ofp_port); if (port) { + if (port->ofproto->ofproto_class->set_stp_port) { + port->ofproto->ofproto_class->set_stp_port(port, NULL); + } if (port->ofproto->ofproto_class->set_cfm) { port->ofproto->ofproto_class->set_cfm(port, NULL); } @@ -1607,7 +1637,7 @@ rule_execute(struct rule *rule, uint16_t in_port, struct ofpbuf *packet) assert(ofpbuf_headroom(packet) >= sizeof(struct ofp_packet_in)); - flow_extract(packet, 0, in_port, &flow); + flow_extract(packet, 0, 0, in_port, &flow); return rule->ofproto->ofproto_class->rule_execute(rule, &flow, packet); } @@ -1647,7 +1677,7 @@ handle_features_request(struct ofconn *ofconn, const struct ofp_header *oh) osf->n_buffers = htonl(pktbuf_capacity()); osf->n_tables = ofproto->n_tables; osf->capabilities = htonl(OFPC_FLOW_STATS | OFPC_TABLE_STATS | - OFPC_PORT_STATS); + OFPC_PORT_STATS | OFPC_QUEUE_STATS); if (arp_match_ip) { osf->capabilities |= htonl(OFPC_ARP_MATCH_IP); } @@ -1707,18 +1737,12 @@ handle_set_config(struct ofconn *ofconn, const struct ofp_switch_config *osc) /* Checks whether 'ofconn' is a slave controller. If so, returns an OpenFlow * error message code (composed with ofp_mkerr()) for the caller to propagate - * upward. Otherwise, returns 0. - * - * The log message mentions 'msg_type'. */ + * upward. Otherwise, returns 0. */ static int -reject_slave_controller(struct ofconn *ofconn, const char *msg_type) +reject_slave_controller(const struct ofconn *ofconn) { if (ofconn_get_type(ofconn) == OFCONN_PRIMARY && ofconn_get_role(ofconn) == NX_ROLE_SLAVE) { - static struct vlog_rate_limit perm_rl = VLOG_RATE_LIMIT_INIT(1, 5); - VLOG_WARN_RL(&perm_rl, "rejecting %s message from slave controller", - msg_type); - return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_EPERM); } else { return 0; @@ -1735,11 +1759,12 @@ handle_packet_out(struct ofconn *ofconn, const struct ofp_header *oh) struct ofpbuf request; struct flow flow; size_t n_ofp_actions; + uint16_t in_port; int error; COVERAGE_INC(ofproto_packet_out); - error = reject_slave_controller(ofconn, "OFPT_PACKET_OUT"); + error = reject_slave_controller(ofconn); if (error) { return error; } @@ -1768,8 +1793,18 @@ handle_packet_out(struct ofconn *ofconn, const struct ofp_header *oh) buffer = NULL; } + /* Get in_port and partially validate it. + * + * We don't know what range of ports the ofproto actually implements, but + * we do know that only certain reserved ports (numbered OFPP_MAX and + * above) are valid. */ + in_port = ntohs(opo->in_port); + if (in_port >= OFPP_MAX && in_port != OFPP_LOCAL && in_port != OFPP_NONE) { + return ofp_mkerr_nicira(OFPET_BAD_REQUEST, NXBRC_BAD_IN_PORT); + } + /* Send out packet. */ - flow_extract(&payload, 0, ntohs(opo->in_port), &flow); + flow_extract(&payload, 0, 0, in_port, &flow); error = p->ofproto_class->packet_out(p, &payload, &flow, ofp_actions, n_ofp_actions); ofpbuf_delete(buffer); @@ -1807,7 +1842,7 @@ handle_port_mod(struct ofconn *ofconn, const struct ofp_header *oh) struct ofport *port; int error; - error = reject_slave_controller(ofconn, "OFPT_PORT_MOD"); + error = reject_slave_controller(ofconn); if (error) { return error; } @@ -1931,6 +1966,17 @@ calc_flow_duration__(long long int start, uint32_t *sec, uint32_t *nsec) *nsec = (msecs % 1000) * (1000 * 1000); } +/* Checks whether 'table_id' is 0xff or a valid table ID in 'ofproto'. Returns + * 0 if 'table_id' is OK, otherwise an OpenFlow error code. */ +static int +check_table_id(const struct ofproto *ofproto, uint8_t table_id) +{ + return (table_id == 0xff || table_id < ofproto->n_tables + ? 0 + : ofp_mkerr_nicira(OFPET_BAD_REQUEST, NXBRC_BAD_TABLE_ID)); + +} + static struct classifier * first_matching_table(struct ofproto *ofproto, uint8_t table_id) { @@ -1939,11 +1985,6 @@ first_matching_table(struct ofproto *ofproto, uint8_t table_id) } else if (table_id < ofproto->n_tables) { return &ofproto->tables[table_id]; } else { - /* It would probably be better to reply with an error but there doesn't - * seem to be any appropriate value, so that might just be - * confusing. */ - VLOG_WARN_RL(&rl, "controller asked for invalid table %"PRIu8, - table_id); return NULL; } } @@ -1966,8 +2007,9 @@ next_matching_table(struct ofproto *ofproto, * - If TABLE_ID is the number of a table in OFPROTO, then the loop iterates * only once, for that table. * - * - Otherwise, TABLE_ID isn't valid for OFPROTO, so ofproto logs a warning - * and does not enter the loop at all. + * - Otherwise, TABLE_ID isn't valid for OFPROTO, so the loop won't be + * entered at all. (Perhaps you should have validated TABLE_ID with + * check_table_id().) * * All parameters are evaluated multiple times. */ @@ -1993,6 +2035,12 @@ collect_rules_loose(struct ofproto *ofproto, uint8_t table_id, struct list *rules) { struct classifier *cls; + int error; + + error = check_table_id(ofproto, table_id); + if (error) { + return error; + } list_init(rules); FOR_EACH_MATCHING_TABLE (cls, table_id, ofproto) { @@ -2029,6 +2077,12 @@ collect_rules_strict(struct ofproto *ofproto, uint8_t table_id, struct list *rules) { struct classifier *cls; + int error; + + error = check_table_id(ofproto, table_id); + if (error) { + return error; + } list_init(rules); FOR_EACH_MATCHING_TABLE (cls, table_id, ofproto) { @@ -2356,6 +2410,11 @@ add_flow(struct ofproto *ofproto, struct ofconn *ofconn, struct rule *rule; int error; + error = check_table_id(ofproto, fm->table_id); + if (error) { + return error; + } + /* Pick table. */ if (fm->table_id == 0xff) { uint8_t table_id; @@ -2621,7 +2680,7 @@ handle_flow_mod(struct ofconn *ofconn, const struct ofp_header *oh) struct ofputil_flow_mod fm; int error; - error = reject_slave_controller(ofconn, "flow_mod"); + error = reject_slave_controller(ofconn); if (error) { return error; } @@ -2687,17 +2746,13 @@ handle_role_request(struct ofconn *ofconn, const struct ofp_header *oh) uint32_t role; if (ofconn_get_type(ofconn) != OFCONN_PRIMARY) { - VLOG_WARN_RL(&rl, "ignoring role request on service connection"); return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_EPERM); } role = ntohl(nrr->role); if (role != NX_ROLE_OTHER && role != NX_ROLE_MASTER && role != NX_ROLE_SLAVE) { - VLOG_WARN_RL(&rl, "received request for unknown role %"PRIu32, role); - - /* There's no good error code for this. */ - return ofp_mkerr(OFPET_BAD_REQUEST, -1); + return ofp_mkerr_nicira(OFPET_BAD_REQUEST, NXBRC_BAD_ROLE); } if (ofconn_get_role(ofconn) != role @@ -2860,11 +2915,6 @@ handle_openflow__(struct ofconn *ofconn, const struct ofpbuf *msg) case OFPUTIL_NXST_FLOW_REPLY: case OFPUTIL_NXST_AGGREGATE_REPLY: default: - if (VLOG_IS_WARN_ENABLED()) { - char *s = ofp_to_string(oh, ntohs(oh->length), 2); - VLOG_DBG_RL(&rl, "OpenFlow message ignored: %s", s); - free(s); - } if (oh->type == OFPT_STATS_REQUEST || oh->type == OFPT_STATS_REPLY) { return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_STAT); } else {