diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index 8bcd78f9496638e30c313abb74d004729d0dae16..0cbb935078dad95474f29842d138c41ddb665e24 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -18,6 +18,7 @@ #include #include #include +#include #include @@ -268,6 +269,7 @@ struct macsec_dev { struct net_device *real_dev; struct pcpu_secy_stats __percpu *stats; struct list_head secys; + struct gro_cells gro_cells; }; /** @@ -879,7 +881,7 @@ static void macsec_decrypt_done(struct crypto_async_request *base, int err) macsec_reset_skb(skb, macsec->secy.netdev); len = skb->len; - ret = netif_rx(skb); + ret = gro_cells_receive(&macsec->gro_cells, skb); if (ret == NET_RX_SUCCESS) count_rx(dev, len); else @@ -1052,6 +1054,7 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb) struct pcpu_rx_sc_stats *rxsc_stats; struct pcpu_secy_stats *secy_stats; bool pulled_sci; + int ret; if (skb_headroom(skb) < ETH_HLEN) goto drop_direct; @@ -1193,12 +1196,17 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb) if (rx_sa) macsec_rxsa_put(rx_sa); - count_rx(dev, skb->len); + + ret = gro_cells_receive(&macsec->gro_cells, skb); + if (ret == NET_RX_SUCCESS) + count_rx(dev, skb->len); + else + macsec->secy.netdev->stats.rx_dropped++; rcu_read_unlock(); - *pskb = skb; - return RX_HANDLER_ANOTHER; + *pskb = NULL; + return RX_HANDLER_CONSUMED; drop: macsec_rxsa_put(rx_sa); @@ -1218,7 +1226,6 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb) list_for_each_entry_rcu(macsec, &rxd->secys, secys) { struct sk_buff *nskb; - int ret; secy_stats = this_cpu_ptr(macsec->stats); @@ -2675,11 +2682,18 @@ static int macsec_dev_init(struct net_device *dev) { struct macsec_dev *macsec = macsec_priv(dev); struct net_device *real_dev = macsec->real_dev; + int err; dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); if (!dev->tstats) return -ENOMEM; + err = gro_cells_init(&macsec->gro_cells, dev); + if (err) { + free_percpu(dev->tstats); + return err; + } + dev->features = real_dev->features & MACSEC_FEATURES; dev->features |= NETIF_F_LLTX | NETIF_F_GSO_SOFTWARE; @@ -2698,6 +2712,9 @@ static int macsec_dev_init(struct net_device *dev) static void macsec_dev_uninit(struct net_device *dev) { + struct macsec_dev *macsec = macsec_priv(dev); + + gro_cells_destroy(&macsec->gro_cells); free_percpu(dev->tstats); } @@ -2707,8 +2724,9 @@ static netdev_features_t macsec_fix_features(struct net_device *dev, struct macsec_dev *macsec = macsec_priv(dev); struct net_device *real_dev = macsec->real_dev; - features &= real_dev->features & MACSEC_FEATURES; - features |= NETIF_F_LLTX | NETIF_F_GSO_SOFTWARE; + features &= (real_dev->features & MACSEC_FEATURES) | + NETIF_F_GSO_SOFTWARE | NETIF_F_SOFT_FEATURES; + features |= NETIF_F_LLTX; return features; }