X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=ofproto%2Fofproto.c;h=bc900dadff928f9a3e12e8b6072a48f2223c95b9;hb=0b9275b2c7ed2f88491898345e03618dbfbf4b0f;hp=39e2b30e1ddad90e7b108ca864292c6f321393c8;hpb=b33951b80fa2040ea10d1e247f416f65da062d1e;p=openvswitch diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index 39e2b30e..bc900dad 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -101,7 +101,7 @@ struct rule; struct ofport { struct hmap_node hmap_node; /* In struct ofproto's "ports" hmap. */ struct netdev *netdev; - struct ofp_phy_port opp; /* In host byte order. */ + struct ofp_phy_port opp; uint16_t odp_port; struct cfm *cfm; /* Connectivity Fault Management, if any. */ }; @@ -268,6 +268,7 @@ static void facet_flush_stats(struct ofproto *, struct facet *); static void facet_make_actions(struct ofproto *, struct facet *, const struct ofpbuf *packet); +static void facet_reset_dp_stats(struct facet *, struct dpif_flow_stats *); static void facet_update_stats(struct ofproto *, struct facet *, const struct dpif_flow_stats *); static void facet_push_stats(struct ofproto *, struct facet *); @@ -938,27 +939,20 @@ bool ofproto_port_is_floodable(struct ofproto *ofproto, uint16_t odp_port) { struct ofport *ofport = get_port(ofproto, odp_port); - return ofport && !(ofport->opp.config & OFPPC_NO_FLOOD); + return ofport && !(ofport->opp.config & htonl(OFPPC_NO_FLOOD)); } -/* Sends 'packet' out of port 'port_no' within 'p'. If 'vlan_tci' is zero the - * packet will not have any 802.1Q hader; if it is nonzero, then the packet - * will be sent with the VLAN TCI specified by 'vlan_tci & ~VLAN_CFI'. +/* Sends 'packet' out of port 'port_no' within 'p'. * * Returns 0 if successful, otherwise a positive errno value. */ int ofproto_send_packet(struct ofproto *ofproto, - uint32_t port_no, uint16_t vlan_tci, - const struct ofpbuf *packet) + uint32_t port_no, const struct ofpbuf *packet) { struct ofpbuf odp_actions; int error; ofpbuf_init(&odp_actions, 32); - if (vlan_tci != 0) { - nl_msg_put_u32(&odp_actions, ODP_ACTION_ATTR_SET_DL_TCI, - ntohs(vlan_tci & ~VLAN_CFI)); - } nl_msg_put_u32(&odp_actions, ODP_ACTION_ATTR_OUTPUT, port_no); error = dpif_execute(ofproto->dpif, odp_actions.data, odp_actions.size, packet); @@ -1062,10 +1056,11 @@ reinit_ports(struct ofproto *p) } /* Opens and returns a netdev for 'dpif_port', or a null pointer if the netdev - * cannot be opened. On success, also fills in 'opp', in *HOST* byte order. */ + * cannot be opened. On success, also fills in 'opp'. */ static struct netdev * ofport_open(const struct dpif_port *dpif_port, struct ofp_phy_port *opp) { + uint32_t curr, advertised, supported, peer; struct netdev_options netdev_options; enum netdev_flags flags; struct netdev *netdev; @@ -1086,14 +1081,18 @@ ofport_open(const struct dpif_port *dpif_port, struct ofp_phy_port *opp) } netdev_get_flags(netdev, &flags); + netdev_get_features(netdev, &curr, &advertised, &supported, &peer); - opp->port_no = odp_port_to_ofp_port(dpif_port->port_no); + opp->port_no = htons(odp_port_to_ofp_port(dpif_port->port_no)); netdev_get_etheraddr(netdev, opp->hw_addr); ovs_strzcpy(opp->name, dpif_port->name, sizeof opp->name); - opp->config = flags & NETDEV_UP ? 0 : OFPPC_PORT_DOWN; - opp->state = netdev_get_carrier(netdev) ? 0 : OFPPS_LINK_DOWN; - netdev_get_features(netdev, &opp->curr, &opp->advertised, - &opp->supported, &opp->peer); + opp->config = flags & NETDEV_UP ? 0 : htonl(OFPPC_PORT_DOWN); + opp->state = netdev_get_carrier(netdev) ? 0 : htonl(OFPPS_LINK_DOWN); + opp->curr = htonl(curr); + opp->advertised = htonl(advertised); + opp->supported = htonl(supported); + opp->peer = htonl(peer); + return netdev; } @@ -1122,7 +1121,7 @@ ofport_equal(const struct ofp_phy_port *a, const struct ofp_phy_port *b) BUILD_ASSERT_DECL(sizeof *a == 48); /* Detect ofp_phy_port changes. */ return (!memcmp(a->hw_addr, b->hw_addr, sizeof a->hw_addr) && a->state == b->state - && !((a->config ^ b->config) & OFPPC_PORT_DOWN) + && !((a->config ^ b->config) & htonl(OFPPC_PORT_DOWN)) && a->curr == b->curr && a->advertised == b->advertised && a->supported == b->supported @@ -1145,7 +1144,7 @@ ofport_install(struct ofproto *p, ofport = xmalloc(sizeof *ofport); ofport->netdev = netdev; ofport->opp = *opp; - ofport->odp_port = ofp_port_to_odp_port(opp->port_no); + ofport->odp_port = ofp_port_to_odp_port(ntohs(opp->port_no)); ofport->cfm = NULL; /* Add port to 'p'. */ @@ -1195,14 +1194,17 @@ ofport_modified(struct ofproto *ofproto, struct ofport *port, struct netdev *netdev, struct ofp_phy_port *opp) { memcpy(port->opp.hw_addr, opp->hw_addr, ETH_ADDR_LEN); - port->opp.config = ((port->opp.config & ~OFPPC_PORT_DOWN) - | (opp->config & OFPPC_PORT_DOWN)); + port->opp.config = ((port->opp.config & ~htonl(OFPPC_PORT_DOWN)) + | (opp->config & htonl(OFPPC_PORT_DOWN))); port->opp.state = opp->state; port->opp.curr = opp->curr; port->opp.advertised = opp->advertised; port->opp.supported = opp->supported; port->opp.peer = opp->peer; + netdev_monitor_remove(ofproto->netdev_monitor, port->netdev); + netdev_monitor_add(ofproto->netdev_monitor, netdev); + netdev_close(port->netdev); port->netdev = netdev; @@ -1223,7 +1225,7 @@ ofport_run(struct ofproto *ofproto, struct ofport *ofport) ccm = eth_compose(&packet, eth_addr_ccm, ofport->opp.hw_addr, ETH_TYPE_CFM, sizeof *ccm); cfm_compose_ccm(ofport->cfm, ccm); - ofproto_send_packet(ofproto, ofport->odp_port, 0, &packet); + ofproto_send_packet(ofproto, ofport->odp_port, &packet); ofpbuf_uninit(&packet); } } @@ -1629,6 +1631,12 @@ facet_make_actions(struct ofproto *p, struct facet *facet, ofpbuf_delete(odp_actions); } +/* Updates 'facet''s flow in the datapath setting its actions to 'actions_len' + * bytes of actions in 'actions'. If 'stats' is non-null, statistics counters + * in the datapath will be zeroed and 'stats' will be updated with traffic new + * since 'facet' was last updated. + * + * Returns 0 if successful, otherwise a positive errno value.*/ static int facet_put__(struct ofproto *ofproto, struct facet *facet, const struct nlattr *actions, size_t actions_len, @@ -1637,19 +1645,24 @@ facet_put__(struct ofproto *ofproto, struct facet *facet, struct odputil_keybuf keybuf; enum dpif_flow_put_flags flags; struct ofpbuf key; + int ret; flags = DPIF_FP_CREATE | DPIF_FP_MODIFY; if (stats) { flags |= DPIF_FP_ZERO_STATS; - facet->dp_packet_count = 0; - facet->dp_byte_count = 0; } ofpbuf_use_stack(&key, &keybuf, sizeof keybuf); odp_flow_key_from_flow(&key, &facet->flow); - return dpif_flow_put(ofproto->dpif, flags, key.data, key.size, - actions, actions_len, stats); + ret = dpif_flow_put(ofproto->dpif, flags, key.data, key.size, + actions, actions_len, stats); + + if (stats) { + facet_reset_dp_stats(facet, stats); + } + + return ret; } /* If 'facet' is installable, inserts or re-inserts it into 'p''s datapath. If @@ -1693,16 +1706,18 @@ facet_uninstall(struct ofproto *p, struct facet *facet) struct odputil_keybuf keybuf; struct dpif_flow_stats stats; struct ofpbuf key; + int error; ofpbuf_use_stack(&key, &keybuf, sizeof keybuf); odp_flow_key_from_flow(&key, &facet->flow); - if (!dpif_flow_del(p->dpif, key.data, key.size, &stats)) { + error = dpif_flow_del(p->dpif, key.data, key.size, &stats); + facet_reset_dp_stats(facet, &stats); + if (!error) { facet_update_stats(p, facet, &stats); } + facet->installed = false; - facet->dp_packet_count = 0; - facet->dp_byte_count = 0; } else { assert(facet->dp_packet_count == 0); assert(facet->dp_byte_count == 0); @@ -1721,6 +1736,24 @@ facet_is_controller_flow(struct facet *facet) htons(OFPP_CONTROLLER))); } +/* Resets 'facet''s datapath statistics counters. This should be called when + * 'facet''s statistics are cleared in the datapath. If 'stats' is non-null, + * it should contain the statistics returned by dpif when 'facet' was reset in + * the datapath. 'stats' will be modified to only included statistics new + * since 'facet' was last updated. */ +static void +facet_reset_dp_stats(struct facet *facet, struct dpif_flow_stats *stats) +{ + if (stats && facet->dp_packet_count < stats->n_packets + && facet->dp_byte_count < stats->n_bytes) { + stats->n_packets -= facet->dp_packet_count; + stats->n_bytes -= facet->dp_byte_count; + } + + facet->dp_packet_count = 0; + facet->dp_byte_count = 0; +} + /* Folds all of 'facet''s statistics into its rule. Also updates the * accounting ofhook and emits a NetFlow expiration if appropriate. All of * 'facet''s statistics in the datapath should have been zeroed and folded into @@ -1925,7 +1958,7 @@ handle_features_request(struct ofconn *ofconn, const struct ofp_header *oh) (1u << OFPAT_ENQUEUE)); HMAP_FOR_EACH (port, hmap_node, &ofproto->ports) { - hton_ofp_phy_port(ofpbuf_put(buf, &port->opp, sizeof port->opp)); + ofpbuf_put(buf, &port->opp, sizeof port->opp); } ofconn_send_reply(ofconn, buf); @@ -1990,7 +2023,7 @@ add_output_action(struct action_xlate_ctx *ctx, uint16_t port) const struct ofport *ofport = get_port(ctx->ofproto, port); if (ofport) { - if (ofport->opp.config & OFPPC_NO_FWD) { + if (ofport->opp.config & htonl(OFPPC_NO_FWD)) { /* Forwarding disabled on port. */ return; } @@ -2045,7 +2078,7 @@ xlate_table_action(struct action_xlate_ctx *ctx, uint16_t in_port) } static void -flood_packets(struct ofproto *ofproto, uint16_t odp_in_port, uint32_t mask, +flood_packets(struct ofproto *ofproto, uint16_t odp_in_port, ovs_be32 mask, uint16_t *nf_output_iface, struct ofpbuf *odp_actions) { struct ofport *ofport; @@ -2085,11 +2118,11 @@ xlate_output_action__(struct action_xlate_ctx *ctx, } break; case OFPP_FLOOD: - flood_packets(ctx->ofproto, ctx->flow.in_port, OFPPC_NO_FLOOD, + flood_packets(ctx->ofproto, ctx->flow.in_port, htonl(OFPPC_NO_FLOOD), &ctx->nf_output_iface, ctx->odp_actions); break; case OFPP_ALL: - flood_packets(ctx->ofproto, ctx->flow.in_port, 0, + flood_packets(ctx->ofproto, ctx->flow.in_port, htonl(0), &ctx->nf_output_iface, ctx->odp_actions); break; case OFPP_CONTROLLER: @@ -2342,9 +2375,10 @@ do_xlate_actions(const union ofp_action *in, size_t n_in, const struct ofport *port; port = get_port(ctx->ofproto, ctx->flow.in_port); - if (port && port->opp.config & (OFPPC_NO_RECV | OFPPC_NO_RECV_STP) && + if (port && port->opp.config & htonl(OFPPC_NO_RECV | OFPPC_NO_RECV_STP) && port->opp.config & (eth_addr_equals(ctx->flow.dl_dst, eth_addr_stp) - ? OFPPC_NO_RECV_STP : OFPPC_NO_RECV)) { + ? htonl(OFPPC_NO_RECV_STP) + : htonl(OFPPC_NO_RECV))) { /* Drop this flow. */ return; } @@ -2505,7 +2539,7 @@ xlate_actions(struct action_xlate_ctx *ctx, * * The log message mentions 'msg_type'. */ static int -reject_slave_controller(struct ofconn *ofconn, const const char *msg_type) +reject_slave_controller(struct ofconn *ofconn, const char *msg_type) { if (ofconn_get_type(ofconn) == OFCONN_PRIMARY && ofconn_get_role(ofconn) == NX_ROLE_SLAVE) { @@ -2586,11 +2620,11 @@ exit: static void update_port_config(struct ofproto *p, struct ofport *port, - uint32_t config, uint32_t mask) + ovs_be32 config, ovs_be32 mask) { mask &= config ^ port->opp.config; - if (mask & OFPPC_PORT_DOWN) { - if (config & OFPPC_PORT_DOWN) { + if (mask & htonl(OFPPC_PORT_DOWN)) { + if (config & htonl(OFPPC_PORT_DOWN)) { netdev_turn_flags_off(port->netdev, NETDEV_UP, true); } else { netdev_turn_flags_on(port->netdev, NETDEV_UP, true); @@ -2598,14 +2632,14 @@ update_port_config(struct ofproto *p, struct ofport *port, } #define REVALIDATE_BITS (OFPPC_NO_RECV | OFPPC_NO_RECV_STP | \ OFPPC_NO_FWD | OFPPC_NO_FLOOD) - if (mask & REVALIDATE_BITS) { + if (mask & htonl(REVALIDATE_BITS)) { COVERAGE_INC(ofproto_costly_flags); - port->opp.config ^= mask & REVALIDATE_BITS; + port->opp.config ^= mask & htonl(REVALIDATE_BITS); p->need_revalidate = true; } #undef REVALIDATE_BITS - if (mask & OFPPC_NO_PACKET_IN) { - port->opp.config ^= OFPPC_NO_PACKET_IN; + if (mask & htonl(OFPPC_NO_PACKET_IN)) { + port->opp.config ^= htonl(OFPPC_NO_PACKET_IN); } } @@ -2628,7 +2662,7 @@ handle_port_mod(struct ofconn *ofconn, const struct ofp_header *oh) } else if (memcmp(port->opp.hw_addr, opm->hw_addr, OFP_ETH_ALEN)) { return ofp_mkerr(OFPET_PORT_MOD_FAILED, OFPPMFC_BAD_HW_ADDR); } else { - update_port_config(p, port, ntohl(opm->config), ntohl(opm->mask)); + update_port_config(p, port, opm->config, opm->mask); if (opm->advertise) { netdev_set_advertisements(port->netdev, ntohl(opm->advertise)); } @@ -2743,8 +2777,7 @@ handle_table_stats_request(struct ofconn *ofconn, ots = append_ofp_stats_reply(sizeof *ots, ofconn, &msg); memset(ots, 0, sizeof *ots); strcpy(ots->name, "classifier"); - ots->wildcards = (ofconn_get_flow_format(ofconn) == NXFF_OPENFLOW10 - ? htonl(OFPFW_ALL) : htonl(OVSFW_ALL)); + ots->wildcards = htonl(OFPFW_ALL); ots->max_entries = htonl(1024 * 1024); /* An arbitrary big number. */ ots->active_count = htonl(classifier_count(&p->cls)); put_32aligned_be64(&ots->lookup_count, htonll(0)); /* XXX */ @@ -2767,7 +2800,7 @@ append_port_stat(struct ofport *port, struct ofconn *ofconn, netdev_get_stats(port->netdev, &stats); ops = append_ofp_stats_reply(sizeof *ops, ofconn, msgp); - ops->port_no = htons(port->opp.port_no); + ops->port_no = port->opp.port_no; memset(ops->pad, 0, sizeof ops->pad); put_32aligned_be64(&ops->rx_packets, htonll(stats.rx_packets)); put_32aligned_be64(&ops->tx_packets, htonll(stats.tx_packets)); @@ -2832,7 +2865,6 @@ put_ofp_flow_stats(struct ofconn *ofconn, struct rule *rule, { struct ofp_flow_stats *ofs; uint64_t packet_count, byte_count; - ovs_be64 cookie; size_t act_len, len; if (rule_is_hidden(rule) || !rule_has_out_port(rule, out_port)) { @@ -2848,9 +2880,8 @@ put_ofp_flow_stats(struct ofconn *ofconn, struct rule *rule, ofs->length = htons(len); ofs->table_id = 0; ofs->pad = 0; - ofputil_cls_rule_to_match(&rule->cr, ofconn_get_flow_format(ofconn), - &ofs->match, rule->flow_cookie, &cookie); - put_32aligned_be64(&ofs->cookie, cookie); + ofputil_cls_rule_to_match(&rule->cr, &ofs->match); + put_32aligned_be64(&ofs->cookie, rule->flow_cookie); calc_flow_duration(rule->created, &ofs->duration_sec, &ofs->duration_nsec); ofs->priority = htons(rule->cr.priority); ofs->idle_timeout = htons(rule->idle_timeout); @@ -2892,8 +2923,7 @@ handle_flow_stats_request(struct ofconn *ofconn, const struct ofp_header *oh) struct cls_rule target; struct rule *rule; - ofputil_cls_rule_from_match(&fsr->match, 0, NXFF_OPENFLOW10, 0, - &target); + ofputil_cls_rule_from_match(&fsr->match, 0, &target); cls_cursor_init(&cursor, &ofproto->cls, &target); CLS_CURSOR_FOR_EACH (rule, cr, &cursor) { put_ofp_flow_stats(ofconn, rule, fsr->out_port, &reply); @@ -3065,8 +3095,7 @@ handle_aggregate_stats_request(struct ofconn *ofconn, struct cls_rule target; struct ofpbuf *msg; - ofputil_cls_rule_from_match(&request->match, 0, NXFF_OPENFLOW10, 0, - &target); + ofputil_cls_rule_from_match(&request->match, 0, &target); msg = start_ofp_stats_reply(oh, sizeof *reply); reply = append_ofp_stats_reply(sizeof *reply, ofconn, &msg); @@ -3123,7 +3152,7 @@ put_queue_stats(struct queue_stats_cbdata *cbdata, uint32_t queue_id, struct ofp_queue_stats *reply; reply = append_ofp_stats_reply(sizeof *reply, cbdata->ofconn, &cbdata->msg); - reply->port_no = htons(cbdata->ofport->opp.port_no); + reply->port_no = cbdata->ofport->opp.port_no; memset(reply->pad, 0, sizeof reply->pad); reply->queue_id = htonl(queue_id); put_32aligned_be64(&reply->tx_bytes, htonll(stats->tx_bytes)); @@ -3513,7 +3542,7 @@ handle_flow_mod(struct ofconn *ofconn, const struct ofp_header *oh) return error; } - error = ofputil_decode_flow_mod(&fm, oh, ofconn_get_flow_format(ofconn)); + error = ofputil_decode_flow_mod(&fm, oh); if (error) { return error; } @@ -3555,19 +3584,6 @@ handle_flow_mod(struct ofconn *ofconn, const struct ofp_header *oh) } } -static int -handle_tun_id_from_cookie(struct ofconn *ofconn, const struct ofp_header *oh) -{ - const struct nxt_tun_id_cookie *msg - = (const struct nxt_tun_id_cookie *) oh; - enum nx_flow_format flow_format; - - flow_format = msg->set ? NXFF_TUN_ID_FROM_COOKIE : NXFF_OPENFLOW10; - ofconn_set_flow_format(ofconn, flow_format); - - return 0; -} - static int handle_role_request(struct ofconn *ofconn, const struct ofp_header *oh) { @@ -3608,7 +3624,6 @@ handle_nxt_set_flow_format(struct ofconn *ofconn, const struct ofp_header *oh) format = ntohl(msg->format); if (format == NXFF_OPENFLOW10 - || format == NXFF_TUN_ID_FROM_COOKIE || format == NXFF_NXM) { ofconn_set_flow_format(ofconn, format); return 0; @@ -3673,9 +3688,6 @@ handle_openflow__(struct ofconn *ofconn, const struct ofpbuf *msg) return 0; /* Nicira extension requests. */ - case OFPUTIL_NXT_TUN_ID_FROM_COOKIE: - return handle_tun_id_from_cookie(ofconn, oh); - case OFPUTIL_NXT_ROLE_REQUEST: return handle_role_request(ofconn, oh); @@ -3781,7 +3793,7 @@ handle_miss_upcall(struct ofproto *p, struct dpif_upcall *upcall) /* Check with in-band control to see if this packet should be sent * to the local port regardless of the flow table. */ if (connmgr_msg_in_hook(p->connmgr, &flow, upcall->packet)) { - ofproto_send_packet(p, ODPP_LOCAL, 0, upcall->packet); + ofproto_send_packet(p, ODPP_LOCAL, upcall->packet); } facet = facet_lookup_valid(p, &flow); @@ -3791,7 +3803,7 @@ handle_miss_upcall(struct ofproto *p, struct dpif_upcall *upcall) /* Don't send a packet-in if OFPPC_NO_PACKET_IN asserted. */ struct ofport *port = get_port(p, flow.in_port); if (port) { - if (port->opp.config & OFPPC_NO_PACKET_IN) { + if (port->opp.config & htonl(OFPPC_NO_PACKET_IN)) { COVERAGE_INC(ofproto_no_packet_in); /* XXX install 'drop' flow entry */ ofpbuf_delete(upcall->packet); @@ -4192,13 +4204,6 @@ static void send_packet_in(struct ofproto *ofproto, struct dpif_upcall *upcall, const struct flow *flow, bool clone) { - struct ofputil_packet_in pin; - - pin.packet = upcall->packet; - pin.in_port = odp_port_to_ofp_port(flow->in_port); - pin.reason = upcall->type == DPIF_UC_MISS ? OFPR_NO_MATCH : OFPR_ACTION; - pin.buffer_id = 0; /* not yet known */ - pin.send_len = upcall->userdata; connmgr_send_packet_in(ofproto->connmgr, upcall, flow, clone ? NULL : upcall->packet); } @@ -4434,7 +4439,7 @@ default_normal_ofhook_cb(const struct flow *flow, const struct ofpbuf *packet, /* Determine output port. */ dst_mac = mac_learning_lookup(ofproto->ml, flow->dl_dst, 0, tags); if (!dst_mac) { - flood_packets(ofproto, flow->in_port, OFPPC_NO_FLOOD, + flood_packets(ofproto, flow->in_port, htonl(OFPPC_NO_FLOOD), nf_output_iface, odp_actions); } else { int out_port = dst_mac->port.i;