+static int
+port_get_stats(const struct ofport *ofport_, struct netdev_stats *stats)
+{
+ struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
+ int error;
+
+ error = netdev_get_stats(ofport->up.netdev, stats);
+
+ if (!error && ofport->odp_port == OVSP_LOCAL) {
+ struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto);
+
+ /* ofproto->stats.tx_packets represents packets that we created
+ * internally and sent to some port (e.g. packets sent with
+ * send_packet()). Account for them as if they had come from
+ * OFPP_LOCAL and got forwarded. */
+
+ if (stats->rx_packets != UINT64_MAX) {
+ stats->rx_packets += ofproto->stats.tx_packets;
+ }
+
+ if (stats->rx_bytes != UINT64_MAX) {
+ stats->rx_bytes += ofproto->stats.tx_bytes;
+ }
+
+ /* ofproto->stats.rx_packets represents packets that were received on
+ * some port and we processed internally and dropped (e.g. STP).
+ * Account fro them as if they had been forwarded to OFPP_LOCAL. */
+
+ if (stats->tx_packets != UINT64_MAX) {
+ stats->tx_packets += ofproto->stats.rx_packets;
+ }
+
+ if (stats->tx_bytes != UINT64_MAX) {
+ stats->tx_bytes += ofproto->stats.rx_bytes;
+ }
+ }
+
+ return error;
+}
+
+/* Account packets for LOCAL port. */
+static void
+ofproto_update_local_port_stats(const struct ofproto *ofproto_,
+ size_t tx_size, size_t rx_size)
+{
+ struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
+
+ if (rx_size) {
+ ofproto->stats.rx_packets++;
+ ofproto->stats.rx_bytes += rx_size;
+ }
+ if (tx_size) {
+ ofproto->stats.tx_packets++;
+ ofproto->stats.tx_bytes += tx_size;
+ }
+}
+