- port = get_port(p, ofp_port_to_odp_port(ntohs(opm->port_no)));
- if (!port) {
- return ofp_mkerr(OFPET_PORT_MOD_FAILED, OFPPMFC_BAD_PORT);
- } 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, opm->config, opm->mask);
- if (opm->advertise) {
- netdev_set_advertisements(port->netdev, ntohl(opm->advertise));
- }
- }
- return 0;
-}
-
-static struct ofpbuf *
-make_ofp_stats_reply(ovs_be32 xid, ovs_be16 type, size_t body_len)
-{
- struct ofp_stats_reply *osr;
- struct ofpbuf *msg;
-
- msg = ofpbuf_new(MIN(sizeof *osr + body_len, UINT16_MAX));
- osr = put_openflow_xid(sizeof *osr, OFPT_STATS_REPLY, xid, msg);
- osr->type = type;
- osr->flags = htons(0);
- return msg;
-}
-
-static struct ofpbuf *
-start_ofp_stats_reply(const struct ofp_header *request, size_t body_len)
-{
- const struct ofp_stats_request *osr
- = (const struct ofp_stats_request *) request;
- return make_ofp_stats_reply(osr->header.xid, osr->type, body_len);
-}
-
-static void *
-append_ofp_stats_reply(size_t nbytes, struct ofconn *ofconn,
- struct ofpbuf **msgp)
-{
- struct ofpbuf *msg = *msgp;
- assert(nbytes <= UINT16_MAX - sizeof(struct ofp_stats_reply));
- if (nbytes + msg->size > UINT16_MAX) {
- struct ofp_stats_reply *reply = msg->data;
- reply->flags = htons(OFPSF_REPLY_MORE);
- *msgp = make_ofp_stats_reply(reply->header.xid, reply->type, nbytes);
- ofconn_send_reply(ofconn, msg);
- }
- return ofpbuf_put_uninit(*msgp, nbytes);
-}
-
-static struct ofpbuf *
-make_nxstats_reply(ovs_be32 xid, ovs_be32 subtype, size_t body_len)
-{
- struct nicira_stats_msg *nsm;
- struct ofpbuf *msg;
-
- msg = ofpbuf_new(MIN(sizeof *nsm + body_len, UINT16_MAX));
- nsm = put_openflow_xid(sizeof *nsm, OFPT_STATS_REPLY, xid, msg);
- nsm->type = htons(OFPST_VENDOR);
- nsm->flags = htons(0);
- nsm->vendor = htonl(NX_VENDOR_ID);
- nsm->subtype = subtype;
- return msg;
-}
-
-static struct ofpbuf *
-start_nxstats_reply(const struct nicira_stats_msg *request, size_t body_len)
-{
- return make_nxstats_reply(request->header.xid, request->subtype, body_len);
-}
-
-static void
-append_nxstats_reply(size_t nbytes, struct ofconn *ofconn,
- struct ofpbuf **msgp)
-{
- struct ofpbuf *msg = *msgp;
- assert(nbytes <= UINT16_MAX - sizeof(struct nicira_stats_msg));
- if (nbytes + msg->size > UINT16_MAX) {
- struct nicira_stats_msg *reply = msg->data;
- reply->flags = htons(OFPSF_REPLY_MORE);
- *msgp = make_nxstats_reply(reply->header.xid, reply->subtype, nbytes);
- ofconn_send_reply(ofconn, msg);
- }
- ofpbuf_prealloc_tailroom(*msgp, nbytes);
-}
-
-static int
-handle_desc_stats_request(struct ofconn *ofconn,
- const struct ofp_header *request)
-{
- struct ofproto *p = ofconn_get_ofproto(ofconn);
- struct ofp_desc_stats *ods;
- struct ofpbuf *msg;
-
- msg = start_ofp_stats_reply(request, sizeof *ods);
- ods = append_ofp_stats_reply(sizeof *ods, ofconn, &msg);
- memset(ods, 0, sizeof *ods);
- ovs_strlcpy(ods->mfr_desc, p->mfr_desc, sizeof ods->mfr_desc);
- ovs_strlcpy(ods->hw_desc, p->hw_desc, sizeof ods->hw_desc);
- ovs_strlcpy(ods->sw_desc, p->sw_desc, sizeof ods->sw_desc);
- ovs_strlcpy(ods->serial_num, p->serial_desc, sizeof ods->serial_num);
- ovs_strlcpy(ods->dp_desc, p->dp_desc, sizeof ods->dp_desc);
- ofconn_send_reply(ofconn, msg);
-
- return 0;
-}
-
-static int
-handle_table_stats_request(struct ofconn *ofconn,
- const struct ofp_header *request)
-{
- struct ofproto *p = ofconn_get_ofproto(ofconn);
- struct ofp_table_stats *ots;
- struct ofpbuf *msg;
-
- msg = start_ofp_stats_reply(request, sizeof *ots * 2);
-
- /* Classifier table. */
- ots = append_ofp_stats_reply(sizeof *ots, ofconn, &msg);
- memset(ots, 0, sizeof *ots);
- strcpy(ots->name, "classifier");
- 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 */
- put_32aligned_be64(&ots->matched_count, htonll(0)); /* XXX */
-
- ofconn_send_reply(ofconn, msg);
- return 0;
-}
-
-static void
-append_port_stat(struct ofport *port, struct ofconn *ofconn,
- struct ofpbuf **msgp)
-{
- struct netdev_stats stats;
- struct ofp_port_stats *ops;
-
- /* Intentionally ignore return value, since errors will set
- * 'stats' to all-1s, which is correct for OpenFlow, and
- * netdev_get_stats() will log errors. */
- netdev_get_stats(port->netdev, &stats);
-
- ops = append_ofp_stats_reply(sizeof *ops, ofconn, msgp);
- 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));
- put_32aligned_be64(&ops->rx_bytes, htonll(stats.rx_bytes));
- put_32aligned_be64(&ops->tx_bytes, htonll(stats.tx_bytes));
- put_32aligned_be64(&ops->rx_dropped, htonll(stats.rx_dropped));
- put_32aligned_be64(&ops->tx_dropped, htonll(stats.tx_dropped));
- put_32aligned_be64(&ops->rx_errors, htonll(stats.rx_errors));
- put_32aligned_be64(&ops->tx_errors, htonll(stats.tx_errors));
- put_32aligned_be64(&ops->rx_frame_err, htonll(stats.rx_frame_errors));
- put_32aligned_be64(&ops->rx_over_err, htonll(stats.rx_over_errors));
- put_32aligned_be64(&ops->rx_crc_err, htonll(stats.rx_crc_errors));
- put_32aligned_be64(&ops->collisions, htonll(stats.collisions));
-}
-
-static int
-handle_port_stats_request(struct ofconn *ofconn, const struct ofp_header *oh)
-{
- struct ofproto *p = ofconn_get_ofproto(ofconn);
- const struct ofp_port_stats_request *psr = ofputil_stats_body(oh);
- struct ofp_port_stats *ops;
- struct ofpbuf *msg;
- struct ofport *port;
-
- msg = start_ofp_stats_reply(oh, sizeof *ops * 16);
- if (psr->port_no != htons(OFPP_NONE)) {
- port = get_port(p, ofp_port_to_odp_port(ntohs(psr->port_no)));
- if (port) {
- append_port_stat(port, ofconn, &msg);