aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/macsec.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/macsec.c')
-rw-r--r--drivers/net/macsec.c91
1 files changed, 56 insertions, 35 deletions
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
index f83cf6696820..5e1ab1160856 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -588,8 +588,6 @@ static void count_tx(struct net_device *dev, int ret, int len)
stats->tx_packets++;
stats->tx_bytes += len;
u64_stats_update_end(&stats->syncp);
- } else {
- dev->stats.tx_dropped++;
}
}
@@ -617,7 +615,8 @@ static void macsec_encrypt_done(struct crypto_async_request *base, int err)
static struct aead_request *macsec_alloc_req(struct crypto_aead *tfm,
unsigned char **iv,
- struct scatterlist **sg)
+ struct scatterlist **sg,
+ int num_frags)
{
size_t size, iv_offset, sg_offset;
struct aead_request *req;
@@ -629,7 +628,7 @@ static struct aead_request *macsec_alloc_req(struct crypto_aead *tfm,
size = ALIGN(size, __alignof__(struct scatterlist));
sg_offset = size;
- size += sizeof(struct scatterlist) * (MAX_SKB_FRAGS + 1);
+ size += sizeof(struct scatterlist) * num_frags;
tmp = kmalloc(size, GFP_ATOMIC);
if (!tmp)
@@ -649,6 +648,7 @@ static struct sk_buff *macsec_encrypt(struct sk_buff *skb,
{
int ret;
struct scatterlist *sg;
+ struct sk_buff *trailer;
unsigned char *iv;
struct ethhdr *eth;
struct macsec_eth_header *hh;
@@ -697,7 +697,7 @@ static struct sk_buff *macsec_encrypt(struct sk_buff *skb,
unprotected_len = skb->len;
eth = eth_hdr(skb);
sci_present = send_sci(secy);
- hh = (struct macsec_eth_header *)skb_push(skb, macsec_extra_len(sci_present));
+ hh = skb_push(skb, macsec_extra_len(sci_present));
memmove(hh, eth, 2 * ETH_ALEN);
pn = tx_sa_update_pn(tx_sa, secy);
@@ -723,7 +723,14 @@ static struct sk_buff *macsec_encrypt(struct sk_buff *skb,
return ERR_PTR(-EINVAL);
}
- req = macsec_alloc_req(tx_sa->key.tfm, &iv, &sg);
+ ret = skb_cow_data(skb, 0, &trailer);
+ if (unlikely(ret < 0)) {
+ macsec_txsa_put(tx_sa);
+ kfree_skb(skb);
+ return ERR_PTR(ret);
+ }
+
+ req = macsec_alloc_req(tx_sa->key.tfm, &iv, &sg, ret);
if (!req) {
macsec_txsa_put(tx_sa);
kfree_skb(skb);
@@ -732,8 +739,13 @@ static struct sk_buff *macsec_encrypt(struct sk_buff *skb,
macsec_fill_iv(iv, secy->sci, pn);
- sg_init_table(sg, MAX_SKB_FRAGS + 1);
- skb_to_sgvec(skb, sg, 0, skb->len);
+ sg_init_table(sg, ret);
+ ret = skb_to_sgvec(skb, sg, 0, skb->len);
+ if (unlikely(ret < 0)) {
+ macsec_txsa_put(tx_sa);
+ kfree_skb(skb);
+ return ERR_PTR(ret);
+ }
if (tx_sc->encrypt) {
int len = skb->len - macsec_hdr_len(sci_present) -
@@ -874,11 +886,14 @@ static void macsec_decrypt_done(struct crypto_async_request *base, int err)
struct macsec_dev *macsec = macsec_priv(dev);
struct macsec_rx_sa *rx_sa = macsec_skb_cb(skb)->rx_sa;
struct macsec_rx_sc *rx_sc = rx_sa->sc;
- int len, ret;
+ int len;
u32 pn;
aead_request_free(macsec_skb_cb(skb)->req);
+ if (!err)
+ macsec_skb_cb(skb)->valid = true;
+
rcu_read_lock_bh();
pn = ntohl(macsec_ethhdr(skb)->packet_number);
if (!macsec_post_decrypt(skb, &macsec->secy, pn)) {
@@ -892,11 +907,8 @@ static void macsec_decrypt_done(struct crypto_async_request *base, int err)
macsec_reset_skb(skb, macsec->secy.netdev);
len = skb->len;
- ret = gro_cells_receive(&macsec->gro_cells, skb);
- if (ret == NET_RX_SUCCESS)
+ if (gro_cells_receive(&macsec->gro_cells, skb) == NET_RX_SUCCESS)
count_rx(dev, len);
- else
- macsec->secy.netdev->stats.rx_dropped++;
rcu_read_unlock_bh();
@@ -914,6 +926,7 @@ static struct sk_buff *macsec_decrypt(struct sk_buff *skb,
{
int ret;
struct scatterlist *sg;
+ struct sk_buff *trailer;
unsigned char *iv;
struct aead_request *req;
struct macsec_eth_header *hdr;
@@ -924,7 +937,12 @@ static struct sk_buff *macsec_decrypt(struct sk_buff *skb,
if (!skb)
return ERR_PTR(-ENOMEM);
- req = macsec_alloc_req(rx_sa->key.tfm, &iv, &sg);
+ ret = skb_cow_data(skb, 0, &trailer);
+ if (unlikely(ret < 0)) {
+ kfree_skb(skb);
+ return ERR_PTR(ret);
+ }
+ req = macsec_alloc_req(rx_sa->key.tfm, &iv, &sg, ret);
if (!req) {
kfree_skb(skb);
return ERR_PTR(-ENOMEM);
@@ -933,8 +951,12 @@ static struct sk_buff *macsec_decrypt(struct sk_buff *skb,
hdr = (struct macsec_eth_header *)skb->data;
macsec_fill_iv(iv, sci, ntohl(hdr->packet_number));
- sg_init_table(sg, MAX_SKB_FRAGS + 1);
- skb_to_sgvec(skb, sg, 0, skb->len);
+ sg_init_table(sg, ret);
+ ret = skb_to_sgvec(skb, sg, 0, skb->len);
+ if (unlikely(ret < 0)) {
+ kfree_skb(skb);
+ return ERR_PTR(ret);
+ }
if (hdr->tci_an & MACSEC_TCI_E) {
/* confidentiality: ethernet + macsec header
@@ -1019,7 +1041,6 @@ static void handle_not_macsec(struct sk_buff *skb)
*/
list_for_each_entry_rcu(macsec, &rxd->secys, secys) {
struct sk_buff *nskb;
- int ret;
struct pcpu_secy_stats *secy_stats = this_cpu_ptr(macsec->stats);
if (macsec->secy.validate_frames == MACSEC_VALIDATE_STRICT) {
@@ -1036,13 +1057,10 @@ static void handle_not_macsec(struct sk_buff *skb)
nskb->dev = macsec->secy.netdev;
- ret = netif_rx(nskb);
- if (ret == NET_RX_SUCCESS) {
+ if (netif_rx(nskb) == NET_RX_SUCCESS) {
u64_stats_update_begin(&secy_stats->syncp);
secy_stats->stats.InPktsUntagged++;
u64_stats_update_end(&secy_stats->syncp);
- } else {
- macsec->secy.netdev->stats.rx_dropped++;
}
}
@@ -1587,8 +1605,9 @@ static int parse_sa_config(struct nlattr **attrs, struct nlattr **tb_sa)
if (!attrs[MACSEC_ATTR_SA_CONFIG])
return -EINVAL;
- if (nla_parse_nested(tb_sa, MACSEC_SA_ATTR_MAX, attrs[MACSEC_ATTR_SA_CONFIG],
- macsec_genl_sa_policy))
+ if (nla_parse_nested(tb_sa, MACSEC_SA_ATTR_MAX,
+ attrs[MACSEC_ATTR_SA_CONFIG],
+ macsec_genl_sa_policy, NULL))
return -EINVAL;
return 0;
@@ -1599,8 +1618,9 @@ static int parse_rxsc_config(struct nlattr **attrs, struct nlattr **tb_rxsc)
if (!attrs[MACSEC_ATTR_RXSC_CONFIG])
return -EINVAL;
- if (nla_parse_nested(tb_rxsc, MACSEC_RXSC_ATTR_MAX, attrs[MACSEC_ATTR_RXSC_CONFIG],
- macsec_genl_rxsc_policy))
+ if (nla_parse_nested(tb_rxsc, MACSEC_RXSC_ATTR_MAX,
+ attrs[MACSEC_ATTR_RXSC_CONFIG],
+ macsec_genl_rxsc_policy, NULL))
return -EINVAL;
return 0;
@@ -2888,13 +2908,13 @@ static int macsec_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
-static struct rtnl_link_stats64 *macsec_get_stats64(struct net_device *dev,
- struct rtnl_link_stats64 *s)
+static void macsec_get_stats64(struct net_device *dev,
+ struct rtnl_link_stats64 *s)
{
int cpu;
if (!dev->tstats)
- return s;
+ return;
for_each_possible_cpu(cpu) {
struct pcpu_sw_netstats *stats;
@@ -2918,8 +2938,6 @@ static struct rtnl_link_stats64 *macsec_get_stats64(struct net_device *dev,
s->rx_dropped = dev->stats.rx_dropped;
s->tx_dropped = dev->stats.tx_dropped;
-
- return s;
}
static int macsec_get_iflink(const struct net_device *dev)
@@ -2978,7 +2996,6 @@ static void macsec_free_netdev(struct net_device *dev)
free_percpu(macsec->secy.tx_sc.stats);
dev_put(real_dev);
- free_netdev(dev);
}
static void macsec_setup(struct net_device *dev)
@@ -2988,7 +3005,8 @@ static void macsec_setup(struct net_device *dev)
dev->max_mtu = ETH_MAX_MTU;
dev->priv_flags |= IFF_NO_QUEUE;
dev->netdev_ops = &macsec_netdev_ops;
- dev->destructor = macsec_free_netdev;
+ dev->needs_free_netdev = true;
+ dev->priv_destructor = macsec_free_netdev;
SET_NETDEV_DEVTYPE(dev, &macsec_type);
eth_zero_addr(dev->broadcast);
@@ -3038,7 +3056,8 @@ static void macsec_changelink_common(struct net_device *dev,
}
static int macsec_changelink(struct net_device *dev, struct nlattr *tb[],
- struct nlattr *data[])
+ struct nlattr *data[],
+ struct netlink_ext_ack *extack)
{
if (!data)
return 0;
@@ -3185,7 +3204,8 @@ static int macsec_add_dev(struct net_device *dev, sci_t sci, u8 icv_len)
}
static int macsec_newlink(struct net *net, struct net_device *dev,
- struct nlattr *tb[], struct nlattr *data[])
+ struct nlattr *tb[], struct nlattr *data[],
+ struct netlink_ext_ack *extack)
{
struct macsec_dev *macsec = macsec_priv(dev);
struct net_device *real_dev;
@@ -3267,7 +3287,8 @@ unregister:
return err;
}
-static int macsec_validate_attr(struct nlattr *tb[], struct nlattr *data[])
+static int macsec_validate_attr(struct nlattr *tb[], struct nlattr *data[],
+ struct netlink_ext_ack *extack)
{
u64 csid = MACSEC_DEFAULT_CIPHER_ID;
u8 icv_len = DEFAULT_ICV_LEN;