X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=ofproto%2Fofproto.c;h=d773c91cf80d6942481680f5cdd059ff4128e960;hb=27cafc5fc0869236b8cd696eef535eca879a0949;hp=522b791f48220226863996beec720bdc1a64ea5c;hpb=e2b9ac44c82590c2a9a27bff79ae43899277f703;p=openvswitch diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index 522b791f..d773c91c 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -390,6 +390,7 @@ ofproto_create(const char *datapath_name, const char *datapath_type, ofproto->frag_handling = OFPC_FRAG_NORMAL; hmap_init(&ofproto->ports); shash_init(&ofproto->port_by_name); + ofproto->max_ports = OFPP_MAX; ofproto->tables = NULL; ofproto->n_tables = 0; ofproto->connmgr = connmgr_create(ofproto, datapath_name, datapath_name); @@ -422,6 +423,9 @@ ofproto_create(const char *datapath_name, const char *datapath_type, return 0; } +/* Must be called (only) by an ofproto implementation in its constructor + * function. See the large comment on 'construct' in struct ofproto_class for + * details. */ void ofproto_init_tables(struct ofproto *ofproto, int n_tables) { @@ -437,6 +441,24 @@ ofproto_init_tables(struct ofproto *ofproto, int n_tables) } } +/* To be optionally called (only) by an ofproto implementation in its + * constructor function. See the large comment on 'construct' in struct + * ofproto_class for details. + * + * Sets the maximum number of ports to 'max_ports'. The ofproto generic layer + * will then ensure that actions passed into the ofproto implementation will + * not refer to OpenFlow ports numbered 'max_ports' or higher. If this + * function is not called, there will be no such restriction. + * + * Reserved ports numbered OFPP_MAX and higher are special and not subject to + * the 'max_ports' restriction. */ +void +ofproto_init_max_ports(struct ofproto *ofproto, uint16_t max_ports) +{ + assert(max_ports <= OFPP_MAX); + ofproto->max_ports = max_ports; +} + uint64_t ofproto_get_datapath_id(const struct ofproto *ofproto) { @@ -2103,6 +2125,10 @@ handle_packet_out(struct ofconn *ofconn, const struct ofp_header *oh) if (error) { goto exit_free_ofpacts; } + if (po.in_port >= p->max_ports && po.in_port < OFPP_MAX) { + error = OFPERR_NXBRC_BAD_IN_PORT; + goto exit_free_ofpacts; + } /* Get payload. */ if (po.buffer_id != UINT32_MAX) { @@ -2115,10 +2141,13 @@ handle_packet_out(struct ofconn *ofconn, const struct ofp_header *oh) ofpbuf_use_const(payload, po.packet, po.packet_len); } - /* Send out packet. */ + /* Verify actions against packet, then send packet if successful. */ flow_extract(payload, 0, 0, po.in_port, &flow); - error = p->ofproto_class->packet_out(p, payload, &flow, - po.ofpacts, po.ofpacts_len); + error = ofpacts_check(po.ofpacts, po.ofpacts_len, &flow, p->max_ports); + if (!error) { + error = p->ofproto_class->packet_out(p, payload, &flow, + po.ofpacts, po.ofpacts_len); + } ofpbuf_delete(payload); exit_free_ofpacts: @@ -2298,14 +2327,15 @@ handle_port_desc_stats_request(struct ofconn *ofconn, const struct ofp_header *request) { struct ofproto *p = ofconn_get_ofproto(ofconn); + enum ofp_version version; struct ofport *port; struct list replies; ofpmp_init(&replies, request); + version = ofputil_protocol_to_ofp_version(ofconn_get_protocol(ofconn)); HMAP_FOR_EACH (port, hmap_node, &p->ports) { - ofputil_append_port_desc_stats_reply(ofconn_get_protocol(ofconn), - &port->pp, &replies); + ofputil_append_port_desc_stats_reply(version, &port->pp, &replies); } ofconn_send_replies(ofconn, &replies); @@ -2593,7 +2623,7 @@ ofproto_get_netflow_ids(const struct ofproto *ofproto, /* 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'. */ + * and -1 if CFM is not enabled on 'ofp_port'. */ int ofproto_port_get_cfm_fault(const struct ofproto *ofproto, uint16_t ofp_port) { @@ -2603,6 +2633,19 @@ ofproto_port_get_cfm_fault(const struct ofproto *ofproto, uint16_t ofp_port) : -1); } +/* Checks the operational status reported by the remote CFM endpoint of + * 'ofp_port' Returns 1 if operationally up, 0 if operationally down, and -1 + * if CFM is not enabled on 'ofp_port' or does not support operational status. + */ +int +ofproto_port_get_cfm_opup(const struct ofproto *ofproto, uint16_t ofp_port) +{ + struct ofport *ofport = ofproto_get_port(ofproto, ofp_port); + return (ofport && ofproto->ofproto_class->get_cfm_opup + ? ofproto->ofproto_class->get_cfm_opup(ofport) + : -1); +} + /* Gets the MPIDs of the remote maintenance points broadcasting to 'ofp_port' * within 'ofproto'. Populates 'rmps' with an array of MPIDs owned by * 'ofproto', and 'n_rmps' with the number of MPIDs in 'rmps'. Returns a @@ -3141,6 +3184,7 @@ ofproto_rule_send_removed(struct rule *rule, uint8_t reason) calc_flow_duration__(rule->created, time_msec(), &fr.duration_sec, &fr.duration_nsec); fr.idle_timeout = rule->idle_timeout; + fr.hard_timeout = rule->hard_timeout; rule->ofproto->ofproto_class->rule_get_stats(rule, &fr.packet_count, &fr.byte_count); @@ -3209,14 +3253,19 @@ handle_flow_mod(struct ofconn *ofconn, const struct ofp_header *oh) goto exit_free_ofpacts; } + if (fm.flags & OFPFF10_EMERG) { /* We do not support the OpenFlow 1.0 emergency flow cache, which is not * required in OpenFlow 1.0.1 and removed from OpenFlow 1.1. */ - if (fm.flags & OFPFF_EMERG) { /* We do not support the emergency flow cache. It will hopefully get * dropped from OpenFlow in the near future. There is no good error * code, so just state that the flow table is full. */ error = OFPERR_OFPFMFC_ALL_TABLES_FULL; - } else { + } + if (!error) { + error = ofpacts_check(fm.ofpacts, fm.ofpacts_len, + &fm.cr.flow, ofproto->max_ports); + } + if (!error) { error = handle_flow_mod__(ofconn_get_ofproto(ofconn), ofconn, &fm, oh); } if (error) { @@ -3454,7 +3503,7 @@ ofproto_compose_flow_refresh_update(const struct rule *rule, fu.hard_timeout = rule->hard_timeout; fu.table_id = rule->table_id; fu.cookie = rule->flow_cookie; - fu.match = (struct cls_rule *) &rule->cr; + fu.match = CONST_CAST(struct cls_rule *, &rule->cr); if (!(flags & NXFMF_ACTIONS)) { fu.ofpacts = NULL; fu.ofpacts_len = 0;