X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=ofproto%2Fofproto.c;h=ce36d95691c786931f4fa19ce2880a99d5937208;hb=67e96a5dca90225358936b1392bba8b3207805b1;hp=ca2032deb74864391d487681c03293d5d5bcd1f8;hpb=254750ceb233f44744c1a9331145c3c2287bd0df;p=openvswitch diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index ca2032de..ce36d956 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -503,6 +503,16 @@ ofproto_set_forward_bpdu(struct ofproto *ofproto, bool forward_bpdu) } } +/* Sets the MAC aging timeout for the OFPP_NORMAL action on 'ofproto' to + * 'idle_time', in seconds. */ +void +ofproto_set_mac_idle_time(struct ofproto *ofproto, unsigned idle_time) +{ + if (ofproto->ofproto_class->set_mac_idle_time) { + ofproto->ofproto_class->set_mac_idle_time(ofproto, idle_time); + } +} + void ofproto_set_desc(struct ofproto *p, const char *mfr_desc, const char *hw_desc, @@ -1943,17 +1953,13 @@ reject_slave_controller(struct ofconn *ofconn) } static enum ofperr -handle_packet_out(struct ofconn *ofconn, const struct ofp_header *oh) +handle_packet_out(struct ofconn *ofconn, const struct ofp_packet_out *opo) { struct ofproto *p = ofconn_get_ofproto(ofconn); - struct ofp_packet_out *opo; - struct ofpbuf payload, *buffer; - union ofp_action *ofp_actions; - struct ofpbuf request; + struct ofputil_packet_out po; + struct ofpbuf *payload; struct flow flow; - size_t n_ofp_actions; enum ofperr error; - uint16_t in_port; COVERAGE_INC(ofproto_packet_out); @@ -1962,45 +1968,28 @@ handle_packet_out(struct ofconn *ofconn, const struct ofp_header *oh) return error; } - /* Get ofp_packet_out. */ - ofpbuf_use_const(&request, oh, ntohs(oh->length)); - opo = ofpbuf_pull(&request, offsetof(struct ofp_packet_out, actions)); - - /* Get actions. */ - error = ofputil_pull_actions(&request, ntohs(opo->actions_len), - &ofp_actions, &n_ofp_actions); + /* Decode message. */ + error = ofputil_decode_packet_out(&po, opo); if (error) { return error; } /* Get payload. */ - if (opo->buffer_id != htonl(UINT32_MAX)) { - error = ofconn_pktbuf_retrieve(ofconn, ntohl(opo->buffer_id), - &buffer, NULL); - if (error || !buffer) { + if (po.buffer_id != UINT32_MAX) { + error = ofconn_pktbuf_retrieve(ofconn, po.buffer_id, &payload, NULL); + if (error || !payload) { return error; } - payload = *buffer; } else { - payload = request; - 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 OFPERR_NXBRC_BAD_IN_PORT; + payload = xmalloc(sizeof *payload); + ofpbuf_use_const(payload, po.packet, po.packet_len); } /* Send out packet. */ - 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); + flow_extract(payload, 0, 0, po.in_port, &flow); + error = p->ofproto_class->packet_out(p, payload, &flow, + po.actions, po.n_actions); + ofpbuf_delete(payload); return error; } @@ -2164,9 +2153,10 @@ handle_port_stats_request(struct ofconn *ofconn, } static void -calc_flow_duration__(long long int start, uint32_t *sec, uint32_t *nsec) +calc_flow_duration__(long long int start, long long int now, + uint32_t *sec, uint32_t *nsec) { - long long int msecs = time_msec() - start; + long long int msecs = now - start; *sec = msecs / 1000; *nsec = (msecs % 1000) * (1000 * 1000); } @@ -2327,6 +2317,16 @@ collect_rules_strict(struct ofproto *ofproto, uint8_t table_id, return 0; } +/* Returns 'age_ms' (a duration in milliseconds), converted to seconds and + * forced into the range of a uint16_t. */ +static int +age_secs(long long int age_ms) +{ + return (age_ms < 0 ? 0 + : age_ms >= UINT16_MAX * 1000 ? UINT16_MAX + : (unsigned int) age_ms / 1000); +} + static enum ofperr handle_flow_stats_request(struct ofconn *ofconn, const struct ofp_stats_msg *osm) @@ -2352,15 +2352,18 @@ handle_flow_stats_request(struct ofconn *ofconn, ofputil_start_stats_reply(osm, &replies); LIST_FOR_EACH (rule, ofproto_node, &rules) { + long long int now = time_msec(); struct ofputil_flow_stats fs; fs.rule = rule->cr; fs.cookie = rule->flow_cookie; fs.table_id = rule->table_id; - calc_flow_duration__(rule->created, &fs.duration_sec, + calc_flow_duration__(rule->created, now, &fs.duration_sec, &fs.duration_nsec); fs.idle_timeout = rule->idle_timeout; fs.hard_timeout = rule->hard_timeout; + fs.idle_age = age_secs(now - rule->used); + fs.hard_age = age_secs(now - rule->modified); ofproto->ofproto_class->rule_get_stats(rule, &fs.packet_count, &fs.byte_count); fs.actions = rule->actions; @@ -2425,9 +2428,10 @@ ofproto_get_netflow_ids(const struct ofproto *ofproto, ofproto->ofproto_class->get_netflow_ids(ofproto, engine_type, engine_id); } -/* Checks the fault status of CFM for 'ofp_port' within 'ofproto'. Returns 1 - * if CFM is faulted (generally indiciating a connectivity problem), 0 if CFM - * is not faulted, and -1 if CFM is not enabled on 'ofp_port'. */ +/* Checks the fault status of CFM for 'ofp_port' within 'ofproto'. Returns a + * bitmask of 'cfm_fault_reason's to indicate a CFM fault (generally + * indicating a connectivity problem). Returns zero if CFM is not faulted, + * and -1 if CFM is not enabled on 'port'. */ int ofproto_port_get_cfm_fault(const struct ofproto *ofproto, uint16_t ofp_port) { @@ -2920,7 +2924,8 @@ ofproto_rule_send_removed(struct rule *rule, uint8_t reason) fr.rule = rule->cr; fr.cookie = rule->flow_cookie; fr.reason = reason; - calc_flow_duration__(rule->created, &fr.duration_sec, &fr.duration_nsec); + calc_flow_duration__(rule->created, time_msec(), + &fr.duration_sec, &fr.duration_nsec); fr.idle_timeout = rule->idle_timeout; rule->ofproto->ofproto_class->rule_get_stats(rule, &fr.packet_count, &fr.byte_count); @@ -3036,10 +3041,6 @@ handle_role_request(struct ofconn *ofconn, const struct ofp_header *oh) struct ofpbuf *buf; uint32_t role; - if (ofconn_get_type(ofconn) != OFCONN_PRIMARY) { - return OFPERR_OFPBRC_EPERM; - } - role = ntohl(nrr->role); if (role != NX_ROLE_OTHER && role != NX_ROLE_MASTER && role != NX_ROLE_SLAVE) { @@ -3116,6 +3117,41 @@ handle_nxt_set_packet_in_format(struct ofconn *ofconn, return 0; } +static enum ofperr +handle_nxt_set_async_config(struct ofconn *ofconn, const struct ofp_header *oh) +{ + const struct nx_async_config *msg = (const struct nx_async_config *) oh; + uint32_t master[OAM_N_TYPES]; + uint32_t slave[OAM_N_TYPES]; + + master[OAM_PACKET_IN] = ntohl(msg->packet_in_mask[0]); + master[OAM_PORT_STATUS] = ntohl(msg->port_status_mask[0]); + master[OAM_FLOW_REMOVED] = ntohl(msg->flow_removed_mask[0]); + + slave[OAM_PACKET_IN] = ntohl(msg->packet_in_mask[1]); + slave[OAM_PORT_STATUS] = ntohl(msg->port_status_mask[1]); + slave[OAM_FLOW_REMOVED] = ntohl(msg->flow_removed_mask[1]); + + ofconn_set_async_config(ofconn, master, slave); + + return 0; +} + +static enum ofperr +handle_nxt_set_controller_id(struct ofconn *ofconn, + const struct ofp_header *oh) +{ + const struct nx_controller_id *nci; + + nci = (const struct nx_controller_id *) oh; + if (!is_all_zeros(nci->zero, sizeof nci->zero)) { + return OFPERR_NXBRC_MUST_BE_ZERO; + } + + ofconn_set_controller_id(ofconn, ntohs(nci->controller_id)); + return 0; +} + static enum ofperr handle_barrier_request(struct ofconn *ofconn, const struct ofp_header *oh) { @@ -3158,7 +3194,7 @@ handle_openflow__(struct ofconn *ofconn, const struct ofpbuf *msg) return handle_set_config(ofconn, msg->data); case OFPUTIL_OFPT_PACKET_OUT: - return handle_packet_out(ofconn, oh); + return handle_packet_out(ofconn, msg->data); case OFPUTIL_OFPT_PORT_MOD: return handle_port_mod(ofconn, oh); @@ -3186,9 +3222,19 @@ handle_openflow__(struct ofconn *ofconn, const struct ofpbuf *msg) case OFPUTIL_NXT_SET_PACKET_IN_FORMAT: return handle_nxt_set_packet_in_format(ofconn, oh); + case OFPUTIL_NXT_SET_CONTROLLER_ID: + return handle_nxt_set_controller_id(ofconn, oh); + case OFPUTIL_NXT_FLOW_MOD: return handle_flow_mod(ofconn, oh); + case OFPUTIL_NXT_FLOW_AGE: + /* Nothing to do. */ + return 0; + + case OFPUTIL_NXT_SET_ASYNC_CONFIG: + return handle_nxt_set_async_config(ofconn, oh); + /* Statistics requests. */ case OFPUTIL_OFPST_DESC_REQUEST: return handle_desc_stats_request(ofconn, msg->data); @@ -3937,7 +3983,7 @@ ofproto_unixctl_list(struct unixctl_conn *conn, int argc OVS_UNUSED, HMAP_FOR_EACH (ofproto, hmap_node, &all_ofprotos) { ds_put_format(&results, "%s\n", ofproto->name); } - unixctl_command_reply(conn, 200, ds_cstr(&results)); + unixctl_command_reply(conn, ds_cstr(&results)); ds_destroy(&results); }