X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=ofproto%2Fofproto.c;h=e7e040126eb12c13259b78e2d13e66e7f43673be;hb=2e0525bcf5ba3f348795f303f8cb69c9fc033ff3;hp=473ae41be28a756f46f9c6e2f2eee3557aaab7cf;hpb=f27f21341ab42ad0e898d6c0e1bd4e98af82afda;p=openvswitch diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index 473ae41b..e7e04012 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -196,7 +196,7 @@ static enum ofperr handle_flow_mod__(struct ofproto *, struct ofconn *, static uint64_t pick_datapath_id(const struct ofproto *); static uint64_t pick_fallback_dpid(void); static void ofproto_destroy__(struct ofproto *); -static void set_internal_devs_mtu(struct ofproto *); +static void update_mtu(struct ofproto *, struct ofport *); /* unixctl. */ static void ofproto_unixctl_init(void); @@ -387,6 +387,7 @@ ofproto_create(const char *datapath_name, const char *datapath_type, hmap_init(&ofproto->deletions); ofproto->vlan_bitmap = NULL; ofproto->vlans_changed = false; + ofproto->min_mtu = INT_MAX; error = ofproto->ofproto_class->construct(ofproto); if (error) { @@ -1400,9 +1401,9 @@ reinit_ports(struct ofproto *p) /* Opens and returns a netdev for 'ofproto_port', or a null pointer if the * netdev cannot be opened. On success, also fills in 'opp'. */ static struct netdev * -ofport_open(const struct ofproto_port *ofproto_port, struct ofp_phy_port *opp) +ofport_open(const struct ofproto_port *ofproto_port, + struct ofputil_phy_port *pp) { - uint32_t curr, advertised, supported, peer; enum netdev_flags flags; struct netdev *netdev; int error; @@ -1416,36 +1417,36 @@ ofport_open(const struct ofproto_port *ofproto_port, struct ofp_phy_port *opp) return NULL; } + pp->port_no = ofproto_port->ofp_port; + netdev_get_etheraddr(netdev, pp->hw_addr); + ovs_strlcpy(pp->name, ofproto_port->name, sizeof pp->name); netdev_get_flags(netdev, &flags); - netdev_get_features(netdev, &curr, &advertised, &supported, &peer); - - opp->port_no = htons(ofproto_port->ofp_port); - netdev_get_etheraddr(netdev, opp->hw_addr); - ovs_strzcpy(opp->name, ofproto_port->name, sizeof opp->name); - 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); + pp->config = flags & NETDEV_UP ? 0 : OFPUTIL_PC_PORT_DOWN; + pp->state = netdev_get_carrier(netdev) ? 0 : OFPUTIL_PS_LINK_DOWN; + netdev_get_features(netdev, &pp->curr, &pp->advertised, + &pp->supported, &pp->peer); + pp->curr_speed = netdev_features_to_bps(pp->curr); + pp->max_speed = netdev_features_to_bps(pp->supported); return netdev; } /* Returns true if most fields of 'a' and 'b' are equal. Differences in name, - * port number, and 'config' bits other than OFPPC_PORT_DOWN are + * port number, and 'config' bits other than OFPUTIL_PS_LINK_DOWN are * disregarded. */ static bool -ofport_equal(const struct ofp_phy_port *a, const struct ofp_phy_port *b) +ofport_equal(const struct ofputil_phy_port *a, + const struct ofputil_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) + return (eth_addr_equals(a->hw_addr, b->hw_addr) && a->state == b->state - && !((a->config ^ b->config) & htonl(OFPPC_PORT_DOWN)) + && !((a->config ^ b->config) & OFPUTIL_PC_PORT_DOWN) && a->curr == b->curr && a->advertised == b->advertised && a->supported == b->supported - && a->peer == b->peer); + && a->peer == b->peer + && a->curr_speed == b->curr_speed + && a->max_speed == b->max_speed); } /* Adds an ofport to 'p' initialized based on the given 'netdev' and 'opp'. @@ -1453,11 +1454,10 @@ ofport_equal(const struct ofp_phy_port *a, const struct ofp_phy_port *b) * one with the same name or port number). */ static void ofport_install(struct ofproto *p, - struct netdev *netdev, const struct ofp_phy_port *opp) + struct netdev *netdev, const struct ofputil_phy_port *pp) { const char *netdev_name = netdev_get_name(netdev); struct ofport *ofport; - int dev_mtu; int error; /* Create ofport. */ @@ -1469,26 +1469,21 @@ ofport_install(struct ofproto *p, ofport->ofproto = p; ofport->netdev = netdev; ofport->change_seq = netdev_change_seq(netdev); - ofport->opp = *opp; - ofport->ofp_port = ntohs(opp->port_no); + ofport->pp = *pp; + ofport->ofp_port = pp->port_no; /* Add port to 'p'. */ hmap_insert(&p->ports, &ofport->hmap_node, hash_int(ofport->ofp_port, 0)); shash_add(&p->port_by_name, netdev_name, ofport); - if (!netdev_get_mtu(netdev, &dev_mtu)) { - set_internal_devs_mtu(p); - ofport->mtu = dev_mtu; - } else { - ofport->mtu = 0; - } + update_mtu(p, ofport); /* Let the ofproto_class initialize its private data. */ error = p->ofproto_class->port_construct(ofport); if (error) { goto error; } - connmgr_send_port_status(p->connmgr, opp, OFPPR_ADD); + connmgr_send_port_status(p->connmgr, pp, OFPPR_ADD); return; error: @@ -1505,7 +1500,7 @@ error: static void ofport_remove(struct ofport *ofport) { - connmgr_send_port_status(ofport->ofproto->connmgr, &ofport->opp, + connmgr_send_port_status(ofport->ofproto->connmgr, &ofport->pp, OFPPR_DELETE); ofport_destroy(ofport); } @@ -1521,32 +1516,34 @@ ofport_remove_with_name(struct ofproto *ofproto, const char *name) } } -/* Updates 'port' with new 'opp' description. +/* Updates 'port' with new 'pp' description. * * Does not handle a name or port number change. The caller must implement * such a change as a delete followed by an add. */ static void -ofport_modified(struct ofport *port, struct ofp_phy_port *opp) +ofport_modified(struct ofport *port, struct ofputil_phy_port *pp) { - memcpy(port->opp.hw_addr, opp->hw_addr, ETH_ADDR_LEN); - 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; + memcpy(port->pp.hw_addr, pp->hw_addr, ETH_ADDR_LEN); + port->pp.config = ((port->pp.config & ~OFPUTIL_PC_PORT_DOWN) + | (pp->config & OFPUTIL_PC_PORT_DOWN)); + port->pp.state = pp->state; + port->pp.curr = pp->curr; + port->pp.advertised = pp->advertised; + port->pp.supported = pp->supported; + port->pp.peer = pp->peer; + port->pp.curr_speed = pp->curr_speed; + port->pp.max_speed = pp->max_speed; - connmgr_send_port_status(port->ofproto->connmgr, &port->opp, OFPPR_MODIFY); + connmgr_send_port_status(port->ofproto->connmgr, &port->pp, OFPPR_MODIFY); } /* Update OpenFlow 'state' in 'port' and notify controller. */ void -ofproto_port_set_state(struct ofport *port, ovs_be32 state) +ofproto_port_set_state(struct ofport *port, enum ofputil_port_state state) { - if (port->opp.state != state) { - port->opp.state = state; - connmgr_send_port_status(port->ofproto->connmgr, &port->opp, + if (port->pp.state != state) { + port->pp.state = state; + connmgr_send_port_status(port->ofproto->connmgr, &port->pp, OFPPR_MODIFY); } } @@ -1627,7 +1624,7 @@ static void update_port(struct ofproto *ofproto, const char *name) { struct ofproto_port ofproto_port; - struct ofp_phy_port opp; + struct ofputil_phy_port pp; struct netdev *netdev; struct ofport *port; @@ -1635,27 +1632,19 @@ update_port(struct ofproto *ofproto, const char *name) /* Fetch 'name''s location and properties from the datapath. */ netdev = (!ofproto_port_query_by_name(ofproto, name, &ofproto_port) - ? ofport_open(&ofproto_port, &opp) + ? ofport_open(&ofproto_port, &pp) : NULL); if (netdev) { port = ofproto_get_port(ofproto, ofproto_port.ofp_port); if (port && !strcmp(netdev_get_name(port->netdev), name)) { struct netdev *old_netdev = port->netdev; - int dev_mtu; /* 'name' hasn't changed location. Any properties changed? */ - if (!ofport_equal(&port->opp, &opp)) { - ofport_modified(port, &opp); + if (!ofport_equal(&port->pp, &pp)) { + ofport_modified(port, &pp); } - /* If this is a non-internal port and the MTU changed, check - * if the datapath's MTU needs to be updated. */ - if (strcmp(netdev_get_type(netdev), "internal") - && !netdev_get_mtu(netdev, &dev_mtu) - && port->mtu != dev_mtu) { - set_internal_devs_mtu(ofproto); - port->mtu = dev_mtu; - } + update_mtu(ofproto, port); /* Install the newly opened netdev in case it has changed. * Don't close the old netdev yet in case port_modified has to @@ -1676,7 +1665,7 @@ update_port(struct ofproto *ofproto, const char *name) ofport_remove(port); } ofport_remove_with_name(ofproto, name); - ofport_install(ofproto, netdev, &opp); + ofport_install(ofproto, netdev, &pp); } } else { /* Any port named 'name' is gone now. */ @@ -1700,12 +1689,12 @@ init_ports(struct ofproto *p) VLOG_WARN_RL(&rl, "ignoring duplicate device %s in datapath", ofproto_port.name); } else { - struct ofp_phy_port opp; + struct ofputil_phy_port pp; struct netdev *netdev; - netdev = ofport_open(&ofproto_port, &opp); + netdev = ofport_open(&ofproto_port, &pp); if (netdev) { - ofport_install(p, netdev, &opp); + ofport_install(p, netdev, &pp); } } } @@ -1742,19 +1731,44 @@ find_min_mtu(struct ofproto *p) return mtu ? mtu: ETH_PAYLOAD_MAX; } -/* Set the MTU of all datapath devices on 'p' to the minimum of the - * non-datapath ports. */ +/* Update MTU of all datapath devices on 'p' to the minimum of the + * non-datapath ports in event of 'port' added or changed. */ static void -set_internal_devs_mtu(struct ofproto *p) +update_mtu(struct ofproto *p, struct ofport *port) { struct ofport *ofport; - int mtu = find_min_mtu(p); + struct netdev *netdev = port->netdev; + int dev_mtu, old_min; + + if (netdev_get_mtu(netdev, &dev_mtu)) { + port->mtu = 0; + return; + } + if (!strcmp(netdev_get_type(port->netdev), "internal")) { + if (dev_mtu > p->min_mtu) { + if (!netdev_set_mtu(port->netdev, p->min_mtu)) { + dev_mtu = p->min_mtu; + } + } + port->mtu = dev_mtu; + return; + } + + /* For non-internal port find new min mtu. */ + old_min = p->min_mtu; + port->mtu = dev_mtu; + p->min_mtu = find_min_mtu(p); + if (p->min_mtu == old_min) { + return; + } HMAP_FOR_EACH (ofport, hmap_node, &p->ports) { struct netdev *netdev = ofport->netdev; if (!strcmp(netdev_get_type(netdev), "internal")) { - netdev_set_mtu(netdev, mtu); + if (!netdev_set_mtu(netdev, p->min_mtu)) { + ofport->mtu = p->min_mtu; + } } } } @@ -1857,31 +1871,31 @@ static enum ofperr handle_features_request(struct ofconn *ofconn, const struct ofp_header *oh) { struct ofproto *ofproto = ofconn_get_ofproto(ofconn); - struct ofp_switch_features *osf; - struct ofpbuf *buf; + struct ofputil_switch_features features; struct ofport *port; bool arp_match_ip; - uint32_t actions; + struct ofpbuf *b; - ofproto->ofproto_class->get_features(ofproto, &arp_match_ip, &actions); - assert(actions & (1 << OFPAT_OUTPUT)); /* sanity check */ + ofproto->ofproto_class->get_features(ofproto, &arp_match_ip, + &features.actions); + assert(features.actions & OFPUTIL_A_OUTPUT); /* sanity check */ - osf = make_openflow_xid(sizeof *osf, OFPT_FEATURES_REPLY, oh->xid, &buf); - osf->datapath_id = htonll(ofproto->datapath_id); - 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_QUEUE_STATS); + features.datapath_id = ofproto->datapath_id; + features.n_buffers = pktbuf_capacity(); + features.n_tables = ofproto->n_tables; + features.capabilities = (OFPUTIL_C_FLOW_STATS | OFPUTIL_C_TABLE_STATS | + OFPUTIL_C_PORT_STATS | OFPUTIL_C_QUEUE_STATS); if (arp_match_ip) { - osf->capabilities |= htonl(OFPC_ARP_MATCH_IP); + features.capabilities |= OFPUTIL_C_ARP_MATCH_IP; } - osf->actions = htonl(actions); + b = ofputil_encode_switch_features(&features, ofconn_get_protocol(ofconn), + oh->xid); HMAP_FOR_EACH (port, hmap_node, &ofproto->ports) { - ofpbuf_put(buf, &port->opp, sizeof port->opp); + ofputil_put_switch_features_port(&port->pp, b); } - ofconn_send_reply(ofconn, buf); + ofconn_send_reply(ofconn, b); return 0; } @@ -1929,7 +1943,7 @@ handle_set_config(struct ofconn *ofconn, const struct ofp_switch_config *osc) } } ofconn_set_invalid_ttl_to_controller(ofconn, - (flags & OFPC_INVALID_TTL_TO_CONTROLLER)); + (flags & OFPC_INVALID_TTL_TO_CONTROLLER)); ofconn_set_miss_send_len(ofconn, ntohs(osc->miss_send_len)); @@ -1953,17 +1967,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); @@ -1972,67 +1982,52 @@ 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; } static void -update_port_config(struct ofport *port, ovs_be32 config, ovs_be32 mask) +update_port_config(struct ofport *port, + enum ofputil_port_config config, + enum ofputil_port_config mask) { - ovs_be32 old_config = port->opp.config; + enum ofputil_port_config old_config = port->pp.config; + enum ofputil_port_config toggle; - mask &= config ^ port->opp.config; - if (mask & htonl(OFPPC_PORT_DOWN)) { - if (config & htonl(OFPPC_PORT_DOWN)) { + toggle = (config ^ port->pp.config) & mask; + if (toggle & OFPUTIL_PC_PORT_DOWN) { + if (config & OFPUTIL_PC_PORT_DOWN) { netdev_turn_flags_off(port->netdev, NETDEV_UP, true); } else { netdev_turn_flags_on(port->netdev, NETDEV_UP, true); } + toggle &= ~OFPUTIL_PC_PORT_DOWN; } - port->opp.config ^= mask & (htonl(OFPPC_NO_RECV | OFPPC_NO_RECV_STP | - OFPPC_NO_FLOOD | OFPPC_NO_FWD | - OFPPC_NO_PACKET_IN)); - if (port->opp.config != old_config) { + port->pp.config ^= toggle; + if (port->pp.config != old_config) { port->ofproto->ofproto_class->port_reconfigured(port, old_config); } } @@ -2041,24 +2036,29 @@ static enum ofperr handle_port_mod(struct ofconn *ofconn, const struct ofp_header *oh) { struct ofproto *p = ofconn_get_ofproto(ofconn); - const struct ofp_port_mod *opm = (const struct ofp_port_mod *) oh; + struct ofputil_port_mod pm; struct ofport *port; - int error; + enum ofperr error; error = reject_slave_controller(ofconn); if (error) { return error; } - port = ofproto_get_port(p, ntohs(opm->port_no)); + error = ofputil_decode_port_mod(oh, &pm); + if (error) { + return error; + } + + port = ofproto_get_port(p, pm.port_no); if (!port) { return OFPERR_OFPPMFC_BAD_PORT; - } else if (memcmp(port->opp.hw_addr, opm->hw_addr, OFP_ETH_ALEN)) { + } else if (!eth_addr_equals(port->pp.hw_addr, pm.hw_addr)) { return OFPERR_OFPPMFC_BAD_HW_ADDR; } else { - update_port_config(port, opm->config, opm->mask); - if (opm->advertise) { - netdev_set_advertisements(port->netdev, ntohl(opm->advertise)); + update_port_config(port, pm.config, pm.mask); + if (pm.advertise) { + netdev_set_advertisements(port->netdev, pm.advertise); } } return 0; @@ -2133,7 +2133,7 @@ append_port_stat(struct ofport *port, struct list *replies) ofproto_port_get_stats(port, &stats); ops = ofputil_append_stats_reply(sizeof *ops, replies); - ops->port_no = port->opp.port_no; + ops->port_no = htons(port->pp.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)); @@ -2449,9 +2449,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) { @@ -2553,7 +2554,7 @@ put_queue_stats(struct queue_stats_cbdata *cbdata, uint32_t queue_id, struct ofp_queue_stats *reply; reply = ofputil_append_stats_reply(sizeof *reply, &cbdata->replies); - reply->port_no = cbdata->ofport->opp.port_no; + reply->port_no = htons(cbdata->ofport->pp.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)); @@ -3001,8 +3002,7 @@ handle_flow_mod(struct ofconn *ofconn, const struct ofp_header *oh) return error; } - error = ofputil_decode_flow_mod(&fm, oh, - ofconn_get_flow_mod_table_id(ofconn)); + error = ofputil_decode_flow_mod(&fm, oh, ofconn_get_protocol(ofconn)); if (error) { return error; } @@ -3061,14 +3061,10 @@ 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) { - return OFPERR_NXBRC_BAD_ROLE; + return OFPERR_OFPRRFC_BAD_ROLE; } if (ofconn_get_role(ofconn) != role @@ -3091,8 +3087,12 @@ handle_nxt_flow_mod_table_id(struct ofconn *ofconn, { const struct nx_flow_mod_table_id *msg = (const struct nx_flow_mod_table_id *) oh; + enum ofputil_protocol cur, next; + + cur = ofconn_get_protocol(ofconn); + next = ofputil_protocol_set_tid(cur, msg->set != 0); + ofconn_set_protocol(ofconn, next); - ofconn_set_flow_mod_table_id(ofconn, msg->set != 0); return 0; } @@ -3101,20 +3101,22 @@ handle_nxt_set_flow_format(struct ofconn *ofconn, const struct ofp_header *oh) { const struct nx_set_flow_format *msg = (const struct nx_set_flow_format *) oh; - uint32_t format; + enum ofputil_protocol cur, next; + enum ofputil_protocol next_base; - format = ntohl(msg->format); - if (format != NXFF_OPENFLOW10 && format != NXFF_NXM) { + next_base = ofputil_nx_flow_format_to_protocol(ntohl(msg->format)); + if (!next_base) { return OFPERR_OFPBRC_EPERM; } - if (format != ofconn_get_flow_format(ofconn) - && ofconn_has_pending_opgroups(ofconn)) { - /* Avoid sending async messages in surprising flow format. */ + cur = ofconn_get_protocol(ofconn); + next = ofputil_protocol_set_base(cur, next_base); + if (cur != next && ofconn_has_pending_opgroups(ofconn)) { + /* Avoid sending async messages in surprising protocol. */ return OFPROTO_POSTPONE; } - ofconn_set_flow_format(ofconn, format); + ofconn_set_protocol(ofconn, next); return 0; } @@ -3141,6 +3143,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) { @@ -3151,7 +3188,7 @@ handle_barrier_request(struct ofconn *ofconn, const struct ofp_header *oh) return OFPROTO_POSTPONE; } - ob = make_openflow_xid(sizeof *ob, OFPT_BARRIER_REPLY, oh->xid, &buf); + ob = make_openflow_xid(sizeof *ob, OFPT10_BARRIER_REPLY, oh->xid, &buf); ofconn_send_reply(ofconn, buf); return 0; } @@ -3183,7 +3220,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); @@ -3211,6 +3248,9 @@ 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); @@ -3218,6 +3258,9 @@ handle_openflow__(struct ofconn *ofconn, const struct ofpbuf *msg) /* 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); @@ -3262,11 +3305,10 @@ handle_openflow__(struct ofconn *ofconn, const struct ofpbuf *msg) case OFPUTIL_NXST_FLOW_REPLY: case OFPUTIL_NXST_AGGREGATE_REPLY: default: - if (oh->type == OFPT_STATS_REQUEST || oh->type == OFPT_STATS_REPLY) { - return OFPERR_OFPBRC_BAD_STAT; - } else { - return OFPERR_OFPBRC_BAD_TYPE; - } + return (oh->type == OFPT10_STATS_REQUEST || + oh->type == OFPT10_STATS_REPLY + ? OFPERR_OFPBRC_BAD_STAT + : OFPERR_OFPBRC_BAD_TYPE); } } @@ -3966,7 +4008,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); }