X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fofp-util.c;h=90124ec86af0104bda224608d142f7ab22c44423;hb=44bac24ba5d22fe238bd96702707eb2029efec41;hp=90475f7ae31cca8277fde4501ec7fed5b6c92535;hpb=e9358af610c1f1826f8d7c9114ce0247e746083c;p=openvswitch diff --git a/lib/ofp-util.c b/lib/ofp-util.c index 90475f7a..90124ec8 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira Networks. + * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -101,7 +101,7 @@ static const flow_wildcards_t WC_INVARIANTS = 0 void ofputil_wildcard_from_openflow(uint32_t ofpfw, struct flow_wildcards *wc) { - BUILD_ASSERT_DECL(FLOW_WC_SEQ == 9); + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 10); /* Initialize most of rule->wc. */ flow_wildcards_init_catchall(wc); @@ -109,7 +109,7 @@ ofputil_wildcard_from_openflow(uint32_t ofpfw, struct flow_wildcards *wc) /* Wildcard fields that aren't defined by ofp_match or tun_id. */ wc->wildcards |= (FWW_ARP_SHA | FWW_ARP_THA | FWW_NW_ECN | FWW_NW_TTL - | FWW_ND_TARGET | FWW_IPV6_LABEL); + | FWW_IPV6_LABEL); if (ofpfw & OFPFW_NW_TOS) { /* OpenFlow 1.0 defines a TOS wildcard, but it's much later in @@ -587,6 +587,10 @@ ofputil_decode_ofpst_request(const struct ofp_header *oh, size_t length, OFPST_QUEUE, "OFPST_QUEUE request", sizeof(struct ofp_queue_stats_request), 0 }, + { OFPUTIL_OFPST_PORT_DESC_REQUEST, OFP10_VERSION, + OFPST_PORT_DESC, "OFPST_PORT_DESC request", + sizeof(struct ofp_stats_msg), 0 }, + { 0, 0, OFPST_VENDOR, "OFPST_VENDOR request", sizeof(struct ofp_vendor_stats_msg), 1 }, @@ -644,6 +648,10 @@ ofputil_decode_ofpst_reply(const struct ofp_header *oh, size_t length, OFPST_QUEUE, "OFPST_QUEUE reply", sizeof(struct ofp_stats_msg), sizeof(struct ofp_queue_stats) }, + { OFPUTIL_OFPST_PORT_DESC_REPLY, OFP10_VERSION, + OFPST_PORT_DESC, "OFPST_PORT_DESC reply", + sizeof(struct ofp_stats_msg), sizeof(struct ofp10_phy_port) }, + { 0, 0, OFPST_VENDOR, "OFPST_VENDOR reply", sizeof(struct ofp_vendor_stats_msg), 1 }, @@ -1166,7 +1174,7 @@ ofputil_usable_protocols(const struct cls_rule *rule) { const struct flow_wildcards *wc = &rule->wc; - BUILD_ASSERT_DECL(FLOW_WC_SEQ == 9); + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 10); /* Only NXM supports separately wildcards the Ethernet multicast bit. */ if (!(wc->wildcards & FWW_DL_DST) != !(wc->wildcards & FWW_ETH_MCAST)) { @@ -1453,10 +1461,7 @@ ofputil_decode_flow_mod(struct ofputil_flow_mod *fm, } /* Converts 'fm' into an OFPT_FLOW_MOD or NXT_FLOW_MOD message according to - * 'protocol' and returns the message. - * - * 'flow_mod_table_id' should be true if the NXT_FLOW_MOD_TABLE_ID extension is - * enabled, false otherwise. */ + * 'protocol' and returns the message. */ struct ofpbuf * ofputil_encode_flow_mod(const struct ofputil_flow_mod *fm, enum ofputil_protocol protocol) @@ -2224,7 +2229,7 @@ ofputil_decode_packet_out(struct ofputil_packet_out *po, po->buffer_id = ntohl(opo->buffer_id); po->in_port = ntohs(opo->in_port); if (po->in_port >= OFPP_MAX && po->in_port != OFPP_LOCAL - && po->in_port != OFPP_NONE) { + && po->in_port != OFPP_NONE && po->in_port != OFPP_CONTROLLER) { VLOG_WARN_RL(&bad_ofmsg_rl, "packet-out has bad input port %#"PRIx16, po->in_port); return OFPERR_NXBRC_BAD_IN_PORT; @@ -2363,17 +2368,11 @@ ofputil_decode_ofp11_port(struct ofputil_phy_port *pp, return 0; } -static int -ofputil_pull_phy_port(uint8_t ofp_version, struct ofpbuf *b, - struct ofputil_phy_port *pp) +static size_t +ofputil_get_phy_port_size(uint8_t ofp_version) { - if (ofp_version == OFP10_VERSION) { - const struct ofp10_phy_port *opp = ofpbuf_try_pull(b, sizeof *opp); - return opp ? ofputil_decode_ofp10_phy_port(pp, opp) : EOF; - } else { - const struct ofp11_port *op = ofpbuf_try_pull(b, sizeof *op); - return op ? ofputil_decode_ofp11_port(pp, op) : EOF; - } + return ofp_version == OFP10_VERSION ? sizeof(struct ofp10_phy_port) + : sizeof(struct ofp11_port); } static void @@ -2435,6 +2434,24 @@ ofputil_put_phy_port(uint8_t ofp_version, const struct ofputil_phy_port *pp, } } } + +void +ofputil_append_port_desc_stats_reply(uint8_t ofp_version, + const struct ofputil_phy_port *pp, + struct list *replies) +{ + if (ofp_version == OFP10_VERSION) { + struct ofp10_phy_port *opp; + + opp = ofputil_append_stats_reply(sizeof *opp, replies); + ofputil_encode_ofp10_phy_port(pp, opp); + } else { + struct ofp11_port *op; + + op = ofputil_append_stats_reply(sizeof *op, replies); + ofputil_encode_ofp11_port(pp, op); + } +} /* ofputil_switch_features */ @@ -2515,7 +2532,7 @@ decode_action_bits(ovs_be32 of_actions, /* Decodes an OpenFlow 1.0 or 1.1 "switch_features" structure 'osf' into an * abstract representation in '*features'. Initializes '*b' to iterate over * the OpenFlow port structures following 'osf' with later calls to - * ofputil_pull_switch_features_port(). Returns 0 if successful, otherwise an + * ofputil_pull_phy_port(). Returns 0 if successful, otherwise an * OFPERR_* value. */ enum ofperr ofputil_decode_switch_features(const struct ofp_switch_features *osf, @@ -2524,27 +2541,23 @@ ofputil_decode_switch_features(const struct ofp_switch_features *osf, { ofpbuf_use_const(b, osf, ntohs(osf->header.length)); ofpbuf_pull(b, sizeof *osf); - b->l2 = (struct ofputil_switch_features *) osf; features->datapath_id = ntohll(osf->datapath_id); features->n_buffers = ntohl(osf->n_buffers); features->n_tables = osf->n_tables; features->capabilities = ntohl(osf->capabilities) & OFPC_COMMON; - if (osf->header.version == OFP10_VERSION) { - if (b->size % sizeof(struct ofp10_phy_port)) { - return OFPERR_OFPBRC_BAD_LEN; - } + if (b->size % ofputil_get_phy_port_size(osf->header.version)) { + return OFPERR_OFPBRC_BAD_LEN; + } + + if (osf->header.version == OFP10_VERSION) { if (osf->capabilities & htonl(OFPC10_STP)) { features->capabilities |= OFPUTIL_C_STP; } features->actions = decode_action_bits(osf->actions, of10_action_bits); } else if (osf->header.version == OFP11_VERSION) { - if (b->size % sizeof(struct ofp11_port)) { - return OFPERR_OFPBRC_BAD_LEN; - } - if (osf->capabilities & htonl(OFPC11_GROUP_STATS)) { features->capabilities |= OFPUTIL_C_GROUP_STATS; } @@ -2556,31 +2569,35 @@ ofputil_decode_switch_features(const struct ofp_switch_features *osf, return 0; } -/* Given a buffer 'b' that was initialized by a previous successful call to - * ofputil_decode_switch_features(), tries to decode an OpenFlow port structure - * following the main switch features information. If successful, initializes - * '*pp' with an abstract representation of the port and returns 0. If no - * ports remained to be decoded, returns EOF. On an error, returns a positive - * OFPERR_* value. */ -int -ofputil_pull_switch_features_port(struct ofpbuf *b, - struct ofputil_phy_port *pp) +/* Returns true if the maximum number of ports are in 'osf'. */ +static bool +max_ports_in_features(const struct ofp_switch_features *osf) { - const struct ofp_switch_features *osf = b->l2; - return ofputil_pull_phy_port(osf->header.version, b, pp); + size_t pp_size = ofputil_get_phy_port_size(osf->header.version); + return ntohs(osf->header.length) + pp_size > UINT16_MAX; } -/* Returns the number of OpenFlow port structures that follow the main switch - * features information in '*osf'. The return value is only guaranteed to be - * accurate if '*osf' is well-formed, that is, if - * ofputil_decode_switch_features() can process '*osf' successfully. */ -size_t -ofputil_count_phy_ports(const struct ofp_switch_features *osf) +/* Given a buffer 'b' that contains a Features Reply message, checks if + * it contains the maximum number of ports that will fit. If so, it + * returns true and removes the ports from the message. The caller + * should then send an OFPST_PORT_DESC stats request to get the ports, + * since the switch may have more ports than could be represented in the + * Features Reply. Otherwise, returns false. + */ +bool +ofputil_switch_features_ports_trunc(struct ofpbuf *b) { - size_t ports_len = ntohs(osf->header.length) - sizeof *osf; - return (osf->header.version == OFP10_VERSION - ? ports_len / sizeof(struct ofp10_phy_port) - : ports_len / sizeof(struct ofp11_port)); + struct ofp_switch_features *osf = b->data; + + if (max_ports_in_features(osf)) { + /* Remove all the ports. */ + b->size = sizeof(*osf); + update_openflow_length(b); + + return true; + } + + return false; } static ovs_be32 @@ -3289,6 +3306,7 @@ ofputil_check_output_port(uint16_t port, int max_ports) case OFPP_FLOOD: case OFPP_ALL: case OFPP_CONTROLLER: + case OFPP_NONE: case OFPP_LOCAL: return 0; @@ -3362,6 +3380,31 @@ ofputil_format_port(uint16_t port, struct ds *s) ds_put_cstr(s, name); } +/* Given a buffer 'b' that contains an array of OpenFlow ports of type + * 'ofp_version', tries to pull the first element from the array. If + * successful, initializes '*pp' with an abstract representation of the + * port and returns 0. If no ports remain to be decoded, returns EOF. + * On an error, returns a positive OFPERR_* value. */ +int +ofputil_pull_phy_port(uint8_t ofp_version, struct ofpbuf *b, + struct ofputil_phy_port *pp) +{ + if (ofp_version == OFP10_VERSION) { + const struct ofp10_phy_port *opp = ofpbuf_try_pull(b, sizeof *opp); + return opp ? ofputil_decode_ofp10_phy_port(pp, opp) : EOF; + } else { + const struct ofp11_port *op = ofpbuf_try_pull(b, sizeof *op); + return op ? ofputil_decode_ofp11_port(pp, op) : EOF; + } +} + +/* Given a buffer 'b' that contains an array of OpenFlow ports of type + * 'ofp_version', returns the number of elements. */ +size_t ofputil_count_phy_ports(uint8_t ofp_version, struct ofpbuf *b) +{ + return b->size / ofputil_get_phy_port_size(ofp_version); +} + static enum ofperr check_resubmit_table(const struct nx_action_resubmit *nar) { @@ -3715,11 +3758,13 @@ ofputil_put_action(enum ofputil_action_code code, struct ofpbuf *buf) bool action_outputs_to_port(const union ofp_action *action, ovs_be16 port) { - switch (ntohs(action->type)) { - case OFPAT10_OUTPUT: + switch (ofputil_decode_action(action)) { + case OFPUTIL_OFPAT10_OUTPUT: return action->output.port == port; - case OFPAT10_ENQUEUE: + case OFPUTIL_OFPAT10_ENQUEUE: return ((const struct ofp_action_enqueue *) action)->port == port; + case OFPUTIL_NXAST_CONTROLLER: + return port == htons(OFPP_CONTROLLER); default: return false; } @@ -3810,7 +3855,7 @@ ofputil_normalize_rule(struct cls_rule *rule) wc.wildcards |= FWW_IPV6_LABEL; } if (!(may_match & MAY_ND_TARGET)) { - wc.wildcards |= FWW_ND_TARGET; + wc.nd_target_mask = in6addr_any; } /* Log any changes. */ @@ -3926,7 +3971,8 @@ ofputil_parse_key_value(char **stringp, char **keyp, char **valuep) for (value_len = 0; level > 0; value_len++) { switch (value[value_len]) { case '\0': - ovs_fatal(0, "unbalanced parentheses in argument to %s", key); + level = 0; + break; case '(': level++;