return sa;
 }
 
+static struct macsec_rx_sa *macsec_active_rxsa_get(struct macsec_rx_sc *rx_sc)
+{
+       struct macsec_rx_sa *sa = NULL;
+       int an;
+
+       for (an = 0; an < MACSEC_NUM_AN; an++)  {
+               sa = macsec_rxsa_get(rx_sc->sa[an]);
+               if (sa)
+                       break;
+       }
+       return sa;
+}
+
 static void free_rx_sc_rcu(struct rcu_head *head)
 {
        struct macsec_rx_sc *rx_sc = container_of(head, struct macsec_rx_sc, rcu_head);
        skb->protocol = eth_hdr(skb)->h_proto;
 }
 
+static unsigned int macsec_msdu_len(struct sk_buff *skb)
+{
+       struct macsec_dev *macsec = macsec_priv(skb->dev);
+       struct macsec_secy *secy = &macsec->secy;
+       bool sci_present = macsec_skb_cb(skb)->has_sci;
+
+       return skb->len - macsec_hdr_len(sci_present) - secy->icv_len;
+}
+
 static void macsec_count_tx(struct sk_buff *skb, struct macsec_tx_sc *tx_sc,
                            struct macsec_tx_sa *tx_sa)
 {
+       unsigned int msdu_len = macsec_msdu_len(skb);
        struct pcpu_tx_sc_stats *txsc_stats = this_cpu_ptr(tx_sc->stats);
 
        u64_stats_update_begin(&txsc_stats->syncp);
        if (tx_sc->encrypt) {
-               txsc_stats->stats.OutOctetsEncrypted += skb->len;
+               txsc_stats->stats.OutOctetsEncrypted += msdu_len;
                txsc_stats->stats.OutPktsEncrypted++;
                this_cpu_inc(tx_sa->stats->OutPktsEncrypted);
        } else {
-               txsc_stats->stats.OutOctetsProtected += skb->len;
+               txsc_stats->stats.OutOctetsProtected += msdu_len;
                txsc_stats->stats.OutPktsProtected++;
                this_cpu_inc(tx_sa->stats->OutPktsProtected);
        }
        aead_request_free(macsec_skb_cb(skb)->req);
 
        rcu_read_lock_bh();
-       macsec_encrypt_finish(skb, dev);
        macsec_count_tx(skb, &macsec->secy.tx_sc, macsec_skb_cb(skb)->tx_sa);
-       len = skb->len;
+       /* packet is encrypted/protected so tx_bytes must be calculated */
+       len = macsec_msdu_len(skb) + 2 * ETH_ALEN;
+       macsec_encrypt_finish(skb, dev);
        ret = dev_queue_xmit(skb);
        count_tx(dev, ret, len);
        rcu_read_unlock_bh();
 
        macsec_skb_cb(skb)->req = req;
        macsec_skb_cb(skb)->tx_sa = tx_sa;
+       macsec_skb_cb(skb)->has_sci = sci_present;
        aead_request_set_callback(req, 0, macsec_encrypt_done, skb);
 
        dev_hold(skb->dev);
                u64_stats_update_begin(&rxsc_stats->syncp);
                rxsc_stats->stats.InPktsLate++;
                u64_stats_update_end(&rxsc_stats->syncp);
+               secy->netdev->stats.rx_dropped++;
                return false;
        }
 
        if (secy->validate_frames != MACSEC_VALIDATE_DISABLED) {
+               unsigned int msdu_len = macsec_msdu_len(skb);
                u64_stats_update_begin(&rxsc_stats->syncp);
                if (hdr->tci_an & MACSEC_TCI_E)
-                       rxsc_stats->stats.InOctetsDecrypted += skb->len;
+                       rxsc_stats->stats.InOctetsDecrypted += msdu_len;
                else
-                       rxsc_stats->stats.InOctetsValidated += skb->len;
+                       rxsc_stats->stats.InOctetsValidated += msdu_len;
                u64_stats_update_end(&rxsc_stats->syncp);
        }
 
                        u64_stats_update_begin(&rxsc_stats->syncp);
                        rxsc_stats->stats.InPktsNotValid++;
                        u64_stats_update_end(&rxsc_stats->syncp);
+                       this_cpu_inc(rx_sa->stats->InPktsNotValid);
+                       secy->netdev->stats.rx_errors++;
                        return false;
                }
 
 
        macsec_finalize_skb(skb, macsec->secy.icv_len,
                            macsec_extra_len(macsec_skb_cb(skb)->has_sci));
+       len = skb->len;
        macsec_reset_skb(skb, macsec->secy.netdev);
 
-       len = skb->len;
        if (gro_cells_receive(&macsec->gro_cells, skb) == NET_RX_SUCCESS)
                count_rx(dev, len);
 
                        u64_stats_update_begin(&secy_stats->syncp);
                        secy_stats->stats.InPktsNoTag++;
                        u64_stats_update_end(&secy_stats->syncp);
+                       macsec->secy.netdev->stats.rx_dropped++;
                        continue;
                }
 
                u64_stats_update_begin(&secy_stats->syncp);
                secy_stats->stats.InPktsBadTag++;
                u64_stats_update_end(&secy_stats->syncp);
+               secy->netdev->stats.rx_errors++;
                goto drop_nosa;
        }
 
                /* If validateFrames is Strict or the C bit in the
                 * SecTAG is set, discard
                 */
+               struct macsec_rx_sa *active_rx_sa = macsec_active_rxsa_get(rx_sc);
                if (hdr->tci_an & MACSEC_TCI_C ||
                    secy->validate_frames == MACSEC_VALIDATE_STRICT) {
                        u64_stats_update_begin(&rxsc_stats->syncp);
                        rxsc_stats->stats.InPktsNotUsingSA++;
                        u64_stats_update_end(&rxsc_stats->syncp);
+                       secy->netdev->stats.rx_errors++;
+                       if (active_rx_sa)
+                               this_cpu_inc(active_rx_sa->stats->InPktsNotUsingSA);
                        goto drop_nosa;
                }
 
                u64_stats_update_begin(&rxsc_stats->syncp);
                rxsc_stats->stats.InPktsUnusedSA++;
                u64_stats_update_end(&rxsc_stats->syncp);
+               if (active_rx_sa)
+                       this_cpu_inc(active_rx_sa->stats->InPktsUnusedSA);
                goto deliver;
        }
 
                        u64_stats_update_begin(&rxsc_stats->syncp);
                        rxsc_stats->stats.InPktsLate++;
                        u64_stats_update_end(&rxsc_stats->syncp);
+                       macsec->secy.netdev->stats.rx_dropped++;
                        goto drop;
                }
        }
 deliver:
        macsec_finalize_skb(skb, secy->icv_len,
                            macsec_extra_len(macsec_skb_cb(skb)->has_sci));
+       len = skb->len;
        macsec_reset_skb(skb, secy->netdev);
 
        if (rx_sa)
        macsec_rxsc_put(rx_sc);
 
        skb_orphan(skb);
-       len = skb->len;
        ret = gro_cells_receive(&macsec->gro_cells, skb);
        if (ret == NET_RX_SUCCESS)
                count_rx(dev, len);
                        u64_stats_update_begin(&secy_stats->syncp);
                        secy_stats->stats.InPktsNoSCI++;
                        u64_stats_update_end(&secy_stats->syncp);
+                       macsec->secy.netdev->stats.rx_errors++;
                        continue;
                }
 
                return NETDEV_TX_OK;
        }
 
+       len = skb->len;
        skb = macsec_encrypt(skb, dev);
        if (IS_ERR(skb)) {
                if (PTR_ERR(skb) != -EINPROGRESS)
        macsec_count_tx(skb, &macsec->secy.tx_sc, macsec_skb_cb(skb)->tx_sa);
 
        macsec_encrypt_finish(skb, dev);
-       len = skb->len;
        ret = dev_queue_xmit(skb);
        count_tx(dev, ret, len);
        return ret;
 
        s->rx_dropped = dev->stats.rx_dropped;
        s->tx_dropped = dev->stats.tx_dropped;
+       s->rx_errors = dev->stats.rx_errors;
 }
 
 static int macsec_get_iflink(const struct net_device *dev)