Skip to content

Commit dcb780f

Browse files
atenartdavem330
authored andcommitted
net: macsec: add nla support for changing the offloading selection
MACsec offloading to underlying hardware devices is disabled by default (the software implementation is used). This patch adds support for changing this setting through the MACsec netlink interface. Many checks are done when enabling offloading on a given MACsec interface as there are limitations (it must be supported by the hardware, only a single interface can be offloaded on a given physical device at a time, rules can't be moved for now). Signed-off-by: Antoine Tenart <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 3cf3227 commit dcb780f

File tree

2 files changed

+153
-3
lines changed

2 files changed

+153
-3
lines changed

drivers/net/macsec.c

Lines changed: 142 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1484,6 +1484,7 @@ static const struct nla_policy macsec_genl_policy[NUM_MACSEC_ATTR] = {
14841484
[MACSEC_ATTR_IFINDEX] = { .type = NLA_U32 },
14851485
[MACSEC_ATTR_RXSC_CONFIG] = { .type = NLA_NESTED },
14861486
[MACSEC_ATTR_SA_CONFIG] = { .type = NLA_NESTED },
1487+
[MACSEC_ATTR_OFFLOAD] = { .type = NLA_NESTED },
14871488
};
14881489

14891490
static const struct nla_policy macsec_genl_rxsc_policy[NUM_MACSEC_RXSC_ATTR] = {
@@ -1501,6 +1502,10 @@ static const struct nla_policy macsec_genl_sa_policy[NUM_MACSEC_SA_ATTR] = {
15011502
.len = MACSEC_MAX_KEY_LEN, },
15021503
};
15031504

1505+
static const struct nla_policy macsec_genl_offload_policy[NUM_MACSEC_OFFLOAD_ATTR] = {
1506+
[MACSEC_OFFLOAD_ATTR_TYPE] = { .type = NLA_U8 },
1507+
};
1508+
15041509
/* Offloads an operation to a device driver */
15051510
static int macsec_offload(int (* const func)(struct macsec_context *),
15061511
struct macsec_context *ctx)
@@ -2329,6 +2334,126 @@ static int macsec_upd_rxsc(struct sk_buff *skb, struct genl_info *info)
23292334
return ret;
23302335
}
23312336

2337+
static bool macsec_is_configured(struct macsec_dev *macsec)
2338+
{
2339+
struct macsec_secy *secy = &macsec->secy;
2340+
struct macsec_tx_sc *tx_sc = &secy->tx_sc;
2341+
int i;
2342+
2343+
if (secy->n_rx_sc > 0)
2344+
return true;
2345+
2346+
for (i = 0; i < MACSEC_NUM_AN; i++)
2347+
if (tx_sc->sa[i])
2348+
return true;
2349+
2350+
return false;
2351+
}
2352+
2353+
static int macsec_upd_offload(struct sk_buff *skb, struct genl_info *info)
2354+
{
2355+
struct nlattr *tb_offload[MACSEC_OFFLOAD_ATTR_MAX + 1];
2356+
enum macsec_offload offload, prev_offload;
2357+
int (*func)(struct macsec_context *ctx);
2358+
struct nlattr **attrs = info->attrs;
2359+
struct net_device *dev, *loop_dev;
2360+
const struct macsec_ops *ops;
2361+
struct macsec_context ctx;
2362+
struct macsec_dev *macsec;
2363+
struct net *loop_net;
2364+
int ret;
2365+
2366+
if (!attrs[MACSEC_ATTR_IFINDEX])
2367+
return -EINVAL;
2368+
2369+
if (!attrs[MACSEC_ATTR_OFFLOAD])
2370+
return -EINVAL;
2371+
2372+
if (nla_parse_nested_deprecated(tb_offload, MACSEC_OFFLOAD_ATTR_MAX,
2373+
attrs[MACSEC_ATTR_OFFLOAD],
2374+
macsec_genl_offload_policy, NULL))
2375+
return -EINVAL;
2376+
2377+
dev = get_dev_from_nl(genl_info_net(info), attrs);
2378+
if (IS_ERR(dev))
2379+
return PTR_ERR(dev);
2380+
macsec = macsec_priv(dev);
2381+
2382+
offload = nla_get_u8(tb_offload[MACSEC_OFFLOAD_ATTR_TYPE]);
2383+
if (macsec->offload == offload)
2384+
return 0;
2385+
2386+
/* Check if the offloading mode is supported by the underlying layers */
2387+
if (offload != MACSEC_OFFLOAD_OFF &&
2388+
!macsec_check_offload(offload, macsec))
2389+
return -EOPNOTSUPP;
2390+
2391+
if (offload == MACSEC_OFFLOAD_OFF)
2392+
goto skip_limitation;
2393+
2394+
/* Check the physical interface isn't offloading another interface
2395+
* first.
2396+
*/
2397+
for_each_net(loop_net) {
2398+
for_each_netdev(loop_net, loop_dev) {
2399+
struct macsec_dev *priv;
2400+
2401+
if (!netif_is_macsec(loop_dev))
2402+
continue;
2403+
2404+
priv = macsec_priv(loop_dev);
2405+
2406+
if (priv->real_dev == macsec->real_dev &&
2407+
priv->offload != MACSEC_OFFLOAD_OFF)
2408+
return -EBUSY;
2409+
}
2410+
}
2411+
2412+
skip_limitation:
2413+
/* Check if the net device is busy. */
2414+
if (netif_running(dev))
2415+
return -EBUSY;
2416+
2417+
rtnl_lock();
2418+
2419+
prev_offload = macsec->offload;
2420+
macsec->offload = offload;
2421+
2422+
/* Check if the device already has rules configured: we do not support
2423+
* rules migration.
2424+
*/
2425+
if (macsec_is_configured(macsec)) {
2426+
ret = -EBUSY;
2427+
goto rollback;
2428+
}
2429+
2430+
ops = __macsec_get_ops(offload == MACSEC_OFFLOAD_OFF ? prev_offload : offload,
2431+
macsec, &ctx);
2432+
if (!ops) {
2433+
ret = -EOPNOTSUPP;
2434+
goto rollback;
2435+
}
2436+
2437+
if (prev_offload == MACSEC_OFFLOAD_OFF)
2438+
func = ops->mdo_add_secy;
2439+
else
2440+
func = ops->mdo_del_secy;
2441+
2442+
ctx.secy = &macsec->secy;
2443+
ret = macsec_offload(func, &ctx);
2444+
if (ret)
2445+
goto rollback;
2446+
2447+
rtnl_unlock();
2448+
return 0;
2449+
2450+
rollback:
2451+
macsec->offload = prev_offload;
2452+
2453+
rtnl_unlock();
2454+
return ret;
2455+
}
2456+
23322457
static int copy_tx_sa_stats(struct sk_buff *skb,
23332458
struct macsec_tx_sa_stats __percpu *pstats)
23342459
{
@@ -2590,12 +2715,13 @@ static noinline_for_stack int
25902715
dump_secy(struct macsec_secy *secy, struct net_device *dev,
25912716
struct sk_buff *skb, struct netlink_callback *cb)
25922717
{
2593-
struct macsec_rx_sc *rx_sc;
2718+
struct macsec_dev *macsec = netdev_priv(dev);
25942719
struct macsec_tx_sc *tx_sc = &secy->tx_sc;
25952720
struct nlattr *txsa_list, *rxsc_list;
2596-
int i, j;
2597-
void *hdr;
2721+
struct macsec_rx_sc *rx_sc;
25982722
struct nlattr *attr;
2723+
void *hdr;
2724+
int i, j;
25992725

26002726
hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
26012727
&macsec_fam, NLM_F_MULTI, MACSEC_CMD_GET_TXSC);
@@ -2607,6 +2733,13 @@ dump_secy(struct macsec_secy *secy, struct net_device *dev,
26072733
if (nla_put_u32(skb, MACSEC_ATTR_IFINDEX, dev->ifindex))
26082734
goto nla_put_failure;
26092735

2736+
attr = nla_nest_start_noflag(skb, MACSEC_ATTR_OFFLOAD);
2737+
if (!attr)
2738+
goto nla_put_failure;
2739+
if (nla_put_u8(skb, MACSEC_OFFLOAD_ATTR_TYPE, macsec->offload))
2740+
goto nla_put_failure;
2741+
nla_nest_end(skb, attr);
2742+
26102743
if (nla_put_secy(secy, skb))
26112744
goto nla_put_failure;
26122745

@@ -2872,6 +3005,12 @@ static const struct genl_ops macsec_genl_ops[] = {
28723005
.doit = macsec_upd_rxsa,
28733006
.flags = GENL_ADMIN_PERM,
28743007
},
3008+
{
3009+
.cmd = MACSEC_CMD_UPD_OFFLOAD,
3010+
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
3011+
.doit = macsec_upd_offload,
3012+
.flags = GENL_ADMIN_PERM,
3013+
},
28753014
};
28763015

28773016
static struct genl_family macsec_fam __ro_after_init = {

include/uapi/linux/if_macsec.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ enum macsec_attrs {
4545
MACSEC_ATTR_RXSC_LIST, /* dump, nested, macsec_rxsc_attrs for each RXSC */
4646
MACSEC_ATTR_TXSC_STATS, /* dump, nested, macsec_txsc_stats_attr */
4747
MACSEC_ATTR_SECY_STATS, /* dump, nested, macsec_secy_stats_attr */
48+
MACSEC_ATTR_OFFLOAD, /* config, nested, macsec_offload_attrs */
4849
__MACSEC_ATTR_END,
4950
NUM_MACSEC_ATTR = __MACSEC_ATTR_END,
5051
MACSEC_ATTR_MAX = __MACSEC_ATTR_END - 1,
@@ -97,6 +98,15 @@ enum macsec_sa_attrs {
9798
MACSEC_SA_ATTR_MAX = __MACSEC_SA_ATTR_END - 1,
9899
};
99100

101+
enum macsec_offload_attrs {
102+
MACSEC_OFFLOAD_ATTR_UNSPEC,
103+
MACSEC_OFFLOAD_ATTR_TYPE, /* config/dump, u8 0..2 */
104+
MACSEC_OFFLOAD_ATTR_PAD,
105+
__MACSEC_OFFLOAD_ATTR_END,
106+
NUM_MACSEC_OFFLOAD_ATTR = __MACSEC_OFFLOAD_ATTR_END,
107+
MACSEC_OFFLOAD_ATTR_MAX = __MACSEC_OFFLOAD_ATTR_END - 1,
108+
};
109+
100110
enum macsec_nl_commands {
101111
MACSEC_CMD_GET_TXSC,
102112
MACSEC_CMD_ADD_RXSC,
@@ -108,6 +118,7 @@ enum macsec_nl_commands {
108118
MACSEC_CMD_ADD_RXSA,
109119
MACSEC_CMD_DEL_RXSA,
110120
MACSEC_CMD_UPD_RXSA,
121+
MACSEC_CMD_UPD_OFFLOAD,
111122
};
112123

113124
/* u64 per-RXSC stats */

0 commit comments

Comments
 (0)