diff options
Diffstat (limited to 'drivers/net/macsec.c')
| -rw-r--r-- | drivers/net/macsec.c | 150 | 
1 files changed, 86 insertions, 64 deletions
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index f41f67b583db..25616247d7a5 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -528,9 +528,9 @@ static void count_tx(struct net_device *dev, int ret, int len)  	}  } -static void macsec_encrypt_done(struct crypto_async_request *base, int err) +static void macsec_encrypt_done(void *data, int err)  { -	struct sk_buff *skb = base->data; +	struct sk_buff *skb = data;  	struct net_device *dev = skb->dev;  	struct macsec_dev *macsec = macsec_priv(dev);  	struct macsec_tx_sa *sa = macsec_skb_cb(skb)->tx_sa; @@ -835,9 +835,9 @@ static void count_rx(struct net_device *dev, int len)  	u64_stats_update_end(&stats->syncp);  } -static void macsec_decrypt_done(struct crypto_async_request *base, int err) +static void macsec_decrypt_done(void *data, int err)  { -	struct sk_buff *skb = base->data; +	struct sk_buff *skb = data;  	struct net_device *dev = skb->dev;  	struct macsec_dev *macsec = macsec_priv(dev);  	struct macsec_rx_sa *rx_sa = macsec_skb_cb(skb)->rx_sa; @@ -2583,41 +2583,16 @@ static bool macsec_is_configured(struct macsec_dev *macsec)  	return false;  } -static int macsec_upd_offload(struct sk_buff *skb, struct genl_info *info) +static int macsec_update_offload(struct net_device *dev, enum macsec_offload offload)  { -	struct nlattr *tb_offload[MACSEC_OFFLOAD_ATTR_MAX + 1]; -	enum macsec_offload offload, prev_offload; -	int (*func)(struct macsec_context *ctx); -	struct nlattr **attrs = info->attrs; -	struct net_device *dev; +	enum macsec_offload prev_offload;  	const struct macsec_ops *ops;  	struct macsec_context ctx;  	struct macsec_dev *macsec; -	int ret; - -	if (!attrs[MACSEC_ATTR_IFINDEX]) -		return -EINVAL; - -	if (!attrs[MACSEC_ATTR_OFFLOAD]) -		return -EINVAL; - -	if (nla_parse_nested_deprecated(tb_offload, MACSEC_OFFLOAD_ATTR_MAX, -					attrs[MACSEC_ATTR_OFFLOAD], -					macsec_genl_offload_policy, NULL)) -		return -EINVAL; +	int ret = 0; -	dev = get_dev_from_nl(genl_info_net(info), attrs); -	if (IS_ERR(dev)) -		return PTR_ERR(dev);  	macsec = macsec_priv(dev); -	if (!tb_offload[MACSEC_OFFLOAD_ATTR_TYPE]) -		return -EINVAL; - -	offload = nla_get_u8(tb_offload[MACSEC_OFFLOAD_ATTR_TYPE]); -	if (macsec->offload == offload) -		return 0; -  	/* Check if the offloading mode is supported by the underlying layers */  	if (offload != MACSEC_OFFLOAD_OFF &&  	    !macsec_check_offload(offload, macsec)) @@ -2627,42 +2602,69 @@ static int macsec_upd_offload(struct sk_buff *skb, struct genl_info *info)  	if (netif_running(dev))  		return -EBUSY; -	rtnl_lock(); - -	prev_offload = macsec->offload; -	macsec->offload = offload; -  	/* Check if the device already has rules configured: we do not support  	 * rules migration.  	 */ -	if (macsec_is_configured(macsec)) { -		ret = -EBUSY; -		goto rollback; -	} +	if (macsec_is_configured(macsec)) +		return -EBUSY; + +	prev_offload = macsec->offload;  	ops = __macsec_get_ops(offload == MACSEC_OFFLOAD_OFF ? prev_offload : offload,  			       macsec, &ctx); -	if (!ops) { -		ret = -EOPNOTSUPP; -		goto rollback; -	} +	if (!ops) +		return -EOPNOTSUPP; -	if (prev_offload == MACSEC_OFFLOAD_OFF) -		func = ops->mdo_add_secy; -	else -		func = ops->mdo_del_secy; +	macsec->offload = offload;  	ctx.secy = &macsec->secy; -	ret = macsec_offload(func, &ctx); +	ret = offload == MACSEC_OFFLOAD_OFF ? macsec_offload(ops->mdo_del_secy, &ctx) +					    : macsec_offload(ops->mdo_add_secy, &ctx);  	if (ret) -		goto rollback; +		macsec->offload = prev_offload; -	rtnl_unlock(); -	return 0; +	return ret; +} + +static int macsec_upd_offload(struct sk_buff *skb, struct genl_info *info) +{ +	struct nlattr *tb_offload[MACSEC_OFFLOAD_ATTR_MAX + 1]; +	struct nlattr **attrs = info->attrs; +	enum macsec_offload offload; +	struct macsec_dev *macsec; +	struct net_device *dev; +	int ret = 0; + +	if (!attrs[MACSEC_ATTR_IFINDEX]) +		return -EINVAL; + +	if (!attrs[MACSEC_ATTR_OFFLOAD]) +		return -EINVAL; + +	if (nla_parse_nested_deprecated(tb_offload, MACSEC_OFFLOAD_ATTR_MAX, +					attrs[MACSEC_ATTR_OFFLOAD], +					macsec_genl_offload_policy, NULL)) +		return -EINVAL; + +	rtnl_lock(); + +	dev = get_dev_from_nl(genl_info_net(info), attrs); +	if (IS_ERR(dev)) { +		ret = PTR_ERR(dev); +		goto out; +	} +	macsec = macsec_priv(dev); -rollback: -	macsec->offload = prev_offload; +	if (!tb_offload[MACSEC_OFFLOAD_ATTR_TYPE]) { +		ret = -EINVAL; +		goto out; +	} +	offload = nla_get_u8(tb_offload[MACSEC_OFFLOAD_ATTR_TYPE]); + +	if (macsec->offload != offload) +		ret = macsec_update_offload(dev, offload); +out:  	rtnl_unlock();  	return ret;  } @@ -2793,9 +2795,9 @@ static void get_rx_sc_stats(struct net_device *dev,  		stats = per_cpu_ptr(rx_sc->stats, cpu);  		do { -			start = u64_stats_fetch_begin_irq(&stats->syncp); +			start = u64_stats_fetch_begin(&stats->syncp);  			memcpy(&tmp, &stats->stats, sizeof(tmp)); -		} while (u64_stats_fetch_retry_irq(&stats->syncp, start)); +		} while (u64_stats_fetch_retry(&stats->syncp, start));  		sum->InOctetsValidated += tmp.InOctetsValidated;  		sum->InOctetsDecrypted += tmp.InOctetsDecrypted; @@ -2874,9 +2876,9 @@ static void get_tx_sc_stats(struct net_device *dev,  		stats = per_cpu_ptr(macsec_priv(dev)->secy.tx_sc.stats, cpu);  		do { -			start = u64_stats_fetch_begin_irq(&stats->syncp); +			start = u64_stats_fetch_begin(&stats->syncp);  			memcpy(&tmp, &stats->stats, sizeof(tmp)); -		} while (u64_stats_fetch_retry_irq(&stats->syncp, start)); +		} while (u64_stats_fetch_retry(&stats->syncp, start));  		sum->OutPktsProtected   += tmp.OutPktsProtected;  		sum->OutPktsEncrypted   += tmp.OutPktsEncrypted; @@ -2930,9 +2932,9 @@ static void get_secy_stats(struct net_device *dev, struct macsec_dev_stats *sum)  		stats = per_cpu_ptr(macsec_priv(dev)->stats, cpu);  		do { -			start = u64_stats_fetch_begin_irq(&stats->syncp); +			start = u64_stats_fetch_begin(&stats->syncp);  			memcpy(&tmp, &stats->stats, sizeof(tmp)); -		} while (u64_stats_fetch_retry_irq(&stats->syncp, start)); +		} while (u64_stats_fetch_retry(&stats->syncp, start));  		sum->OutPktsUntagged  += tmp.OutPktsUntagged;  		sum->InPktsUntagged   += tmp.InPktsUntagged; @@ -3698,6 +3700,7 @@ static const struct nla_policy macsec_rtnl_policy[IFLA_MACSEC_MAX + 1] = {  	[IFLA_MACSEC_SCB] = { .type = NLA_U8 },  	[IFLA_MACSEC_REPLAY_PROTECT] = { .type = NLA_U8 },  	[IFLA_MACSEC_VALIDATION] = { .type = NLA_U8 }, +	[IFLA_MACSEC_OFFLOAD] = { .type = NLA_U8 },  };  static void macsec_free_netdev(struct net_device *dev) @@ -3808,6 +3811,8 @@ static int macsec_changelink(struct net_device *dev, struct nlattr *tb[],  			     struct netlink_ext_ack *extack)  {  	struct macsec_dev *macsec = macsec_priv(dev); +	bool macsec_offload_state_change = false; +	enum macsec_offload offload;  	struct macsec_tx_sc tx_sc;  	struct macsec_secy secy;  	int ret; @@ -3831,8 +3836,18 @@ static int macsec_changelink(struct net_device *dev, struct nlattr *tb[],  	if (ret)  		goto cleanup; +	if (data[IFLA_MACSEC_OFFLOAD]) { +		offload = nla_get_u8(data[IFLA_MACSEC_OFFLOAD]); +		if (macsec->offload != offload) { +			macsec_offload_state_change = true; +			ret = macsec_update_offload(dev, offload); +			if (ret) +				goto cleanup; +		} +	} +  	/* If h/w offloading is available, propagate to the device */ -	if (macsec_is_offloaded(macsec)) { +	if (!macsec_offload_state_change && macsec_is_offloaded(macsec)) {  		const struct macsec_ops *ops;  		struct macsec_context ctx; @@ -4231,16 +4246,22 @@ static size_t macsec_get_size(const struct net_device *dev)  		nla_total_size(1) + /* IFLA_MACSEC_SCB */  		nla_total_size(1) + /* IFLA_MACSEC_REPLAY_PROTECT */  		nla_total_size(1) + /* IFLA_MACSEC_VALIDATION */ +		nla_total_size(1) + /* IFLA_MACSEC_OFFLOAD */  		0;  }  static int macsec_fill_info(struct sk_buff *skb,  			    const struct net_device *dev)  { -	struct macsec_secy *secy = &macsec_priv(dev)->secy; -	struct macsec_tx_sc *tx_sc = &secy->tx_sc; +	struct macsec_tx_sc *tx_sc; +	struct macsec_dev *macsec; +	struct macsec_secy *secy;  	u64 csid; +	macsec = macsec_priv(dev); +	secy = &macsec->secy; +	tx_sc = &secy->tx_sc; +  	switch (secy->key_len) {  	case MACSEC_GCM_AES_128_SAK_LEN:  		csid = secy->xpn ? MACSEC_CIPHER_ID_GCM_AES_XPN_128 : MACSEC_DEFAULT_CIPHER_ID; @@ -4265,6 +4286,7 @@ static int macsec_fill_info(struct sk_buff *skb,  	    nla_put_u8(skb, IFLA_MACSEC_SCB, tx_sc->scb) ||  	    nla_put_u8(skb, IFLA_MACSEC_REPLAY_PROTECT, secy->replay_protect) ||  	    nla_put_u8(skb, IFLA_MACSEC_VALIDATION, secy->validate_frames) || +	    nla_put_u8(skb, IFLA_MACSEC_OFFLOAD, macsec->offload) ||  	    0)  		goto nla_put_failure;  |