1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright Samuel Mendoza-Jonas, IBM Corporation 2018.
6 #include <linux/module.h>
7 #include <linux/kernel.h>
8 #include <linux/if_arp.h>
9 #include <linux/rtnetlink.h>
10 #include <linux/etherdevice.h>
11 #include <net/genetlink.h>
13 #include <linux/skbuff.h>
15 #include <uapi/linux/ncsi.h>
19 #include "ncsi-netlink.h"
21 static struct genl_family ncsi_genl_family
;
23 static const struct nla_policy ncsi_genl_policy
[NCSI_ATTR_MAX
+ 1] = {
24 [NCSI_ATTR_IFINDEX
] = { .type
= NLA_U32
},
25 [NCSI_ATTR_PACKAGE_LIST
] = { .type
= NLA_NESTED
},
26 [NCSI_ATTR_PACKAGE_ID
] = { .type
= NLA_U32
},
27 [NCSI_ATTR_CHANNEL_ID
] = { .type
= NLA_U32
},
28 [NCSI_ATTR_DATA
] = { .type
= NLA_BINARY
, .len
= 2048 },
29 [NCSI_ATTR_MULTI_FLAG
] = { .type
= NLA_FLAG
},
30 [NCSI_ATTR_PACKAGE_MASK
] = { .type
= NLA_U32
},
31 [NCSI_ATTR_CHANNEL_MASK
] = { .type
= NLA_U32
},
34 static struct ncsi_dev_priv
*ndp_from_ifindex(struct net
*net
, u32 ifindex
)
36 struct ncsi_dev_priv
*ndp
;
37 struct net_device
*dev
;
44 dev
= dev_get_by_index(net
, ifindex
);
46 pr_err("NCSI netlink: No device for ifindex %u\n", ifindex
);
50 nd
= ncsi_find_dev(dev
);
51 ndp
= nd
? TO_NCSI_DEV_PRIV(nd
) : NULL
;
57 static int ncsi_write_channel_info(struct sk_buff
*skb
,
58 struct ncsi_dev_priv
*ndp
,
59 struct ncsi_channel
*nc
)
61 struct ncsi_channel_vlan_filter
*ncf
;
62 struct ncsi_channel_mode
*m
;
63 struct nlattr
*vid_nest
;
66 nla_put_u32(skb
, NCSI_CHANNEL_ATTR_ID
, nc
->id
);
67 m
= &nc
->modes
[NCSI_MODE_LINK
];
68 nla_put_u32(skb
, NCSI_CHANNEL_ATTR_LINK_STATE
, m
->data
[2]);
69 if (nc
->state
== NCSI_CHANNEL_ACTIVE
)
70 nla_put_flag(skb
, NCSI_CHANNEL_ATTR_ACTIVE
);
71 if (nc
== nc
->package
->preferred_channel
)
72 nla_put_flag(skb
, NCSI_CHANNEL_ATTR_FORCED
);
74 nla_put_u32(skb
, NCSI_CHANNEL_ATTR_VERSION_MAJOR
, nc
->version
.major
);
75 nla_put_u32(skb
, NCSI_CHANNEL_ATTR_VERSION_MINOR
, nc
->version
.minor
);
76 nla_put_string(skb
, NCSI_CHANNEL_ATTR_VERSION_STR
, nc
->version
.fw_name
);
78 vid_nest
= nla_nest_start_noflag(skb
, NCSI_CHANNEL_ATTR_VLAN_LIST
);
81 ncf
= &nc
->vlan_filter
;
83 while ((i
= find_next_bit((void *)&ncf
->bitmap
, ncf
->n_vids
,
84 i
+ 1)) < ncf
->n_vids
) {
86 nla_put_u16(skb
, NCSI_CHANNEL_ATTR_VLAN_ID
,
89 nla_nest_end(skb
, vid_nest
);
94 static int ncsi_write_package_info(struct sk_buff
*skb
,
95 struct ncsi_dev_priv
*ndp
, unsigned int id
)
97 struct nlattr
*pnest
, *cnest
, *nest
;
98 struct ncsi_package
*np
;
99 struct ncsi_channel
*nc
;
103 if (id
> ndp
->package_num
- 1) {
104 netdev_info(ndp
->ndev
.dev
, "NCSI: No package with id %u\n", id
);
109 NCSI_FOR_EACH_PACKAGE(ndp
, np
) {
112 pnest
= nla_nest_start_noflag(skb
, NCSI_PKG_ATTR
);
115 rc
= nla_put_u32(skb
, NCSI_PKG_ATTR_ID
, np
->id
);
117 nla_nest_cancel(skb
, pnest
);
120 if ((0x1 << np
->id
) == ndp
->package_whitelist
)
121 nla_put_flag(skb
, NCSI_PKG_ATTR_FORCED
);
122 cnest
= nla_nest_start_noflag(skb
, NCSI_PKG_ATTR_CHANNEL_LIST
);
124 nla_nest_cancel(skb
, pnest
);
127 NCSI_FOR_EACH_CHANNEL(np
, nc
) {
128 nest
= nla_nest_start_noflag(skb
, NCSI_CHANNEL_ATTR
);
130 nla_nest_cancel(skb
, cnest
);
131 nla_nest_cancel(skb
, pnest
);
134 rc
= ncsi_write_channel_info(skb
, ndp
, nc
);
136 nla_nest_cancel(skb
, nest
);
137 nla_nest_cancel(skb
, cnest
);
138 nla_nest_cancel(skb
, pnest
);
141 nla_nest_end(skb
, nest
);
143 nla_nest_end(skb
, cnest
);
144 nla_nest_end(skb
, pnest
);
154 static int ncsi_pkg_info_nl(struct sk_buff
*msg
, struct genl_info
*info
)
156 struct ncsi_dev_priv
*ndp
;
157 unsigned int package_id
;
163 if (!info
|| !info
->attrs
)
166 if (!info
->attrs
[NCSI_ATTR_IFINDEX
])
169 if (!info
->attrs
[NCSI_ATTR_PACKAGE_ID
])
172 ndp
= ndp_from_ifindex(genl_info_net(info
),
173 nla_get_u32(info
->attrs
[NCSI_ATTR_IFINDEX
]));
177 skb
= genlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_KERNEL
);
181 hdr
= genlmsg_put(skb
, info
->snd_portid
, info
->snd_seq
,
182 &ncsi_genl_family
, 0, NCSI_CMD_PKG_INFO
);
188 package_id
= nla_get_u32(info
->attrs
[NCSI_ATTR_PACKAGE_ID
]);
190 attr
= nla_nest_start_noflag(skb
, NCSI_ATTR_PACKAGE_LIST
);
195 rc
= ncsi_write_package_info(skb
, ndp
, package_id
);
198 nla_nest_cancel(skb
, attr
);
202 nla_nest_end(skb
, attr
);
204 genlmsg_end(skb
, hdr
);
205 return genlmsg_reply(skb
, info
);
212 static int ncsi_pkg_info_all_nl(struct sk_buff
*skb
,
213 struct netlink_callback
*cb
)
215 struct nlattr
*attrs
[NCSI_ATTR_MAX
+ 1];
216 struct ncsi_package
*np
, *package
;
217 struct ncsi_dev_priv
*ndp
;
218 unsigned int package_id
;
223 rc
= genlmsg_parse_deprecated(cb
->nlh
, &ncsi_genl_family
, attrs
, NCSI_ATTR_MAX
,
224 ncsi_genl_policy
, NULL
);
228 if (!attrs
[NCSI_ATTR_IFINDEX
])
231 ndp
= ndp_from_ifindex(get_net(sock_net(skb
->sk
)),
232 nla_get_u32(attrs
[NCSI_ATTR_IFINDEX
]));
237 package_id
= cb
->args
[0];
239 NCSI_FOR_EACH_PACKAGE(ndp
, np
)
240 if (np
->id
== package_id
)
246 hdr
= genlmsg_put(skb
, NETLINK_CB(cb
->skb
).portid
, cb
->nlh
->nlmsg_seq
,
247 &ncsi_genl_family
, NLM_F_MULTI
, NCSI_CMD_PKG_INFO
);
253 attr
= nla_nest_start_noflag(skb
, NCSI_ATTR_PACKAGE_LIST
);
258 rc
= ncsi_write_package_info(skb
, ndp
, package
->id
);
260 nla_nest_cancel(skb
, attr
);
264 nla_nest_end(skb
, attr
);
265 genlmsg_end(skb
, hdr
);
267 cb
->args
[0] = package_id
+ 1;
271 genlmsg_cancel(skb
, hdr
);
275 static int ncsi_set_interface_nl(struct sk_buff
*msg
, struct genl_info
*info
)
277 struct ncsi_package
*np
, *package
;
278 struct ncsi_channel
*nc
, *channel
;
279 u32 package_id
, channel_id
;
280 struct ncsi_dev_priv
*ndp
;
283 if (!info
|| !info
->attrs
)
286 if (!info
->attrs
[NCSI_ATTR_IFINDEX
])
289 if (!info
->attrs
[NCSI_ATTR_PACKAGE_ID
])
292 ndp
= ndp_from_ifindex(get_net(sock_net(msg
->sk
)),
293 nla_get_u32(info
->attrs
[NCSI_ATTR_IFINDEX
]));
297 package_id
= nla_get_u32(info
->attrs
[NCSI_ATTR_PACKAGE_ID
]);
300 NCSI_FOR_EACH_PACKAGE(ndp
, np
)
301 if (np
->id
== package_id
)
304 /* The user has set a package that does not exist */
309 if (info
->attrs
[NCSI_ATTR_CHANNEL_ID
]) {
310 channel_id
= nla_get_u32(info
->attrs
[NCSI_ATTR_CHANNEL_ID
]);
311 NCSI_FOR_EACH_CHANNEL(package
, nc
)
312 if (nc
->id
== channel_id
) {
317 netdev_info(ndp
->ndev
.dev
,
318 "NCSI: Channel %u does not exist!\n",
324 spin_lock_irqsave(&ndp
->lock
, flags
);
325 ndp
->package_whitelist
= 0x1 << package
->id
;
326 ndp
->multi_package
= false;
327 spin_unlock_irqrestore(&ndp
->lock
, flags
);
329 spin_lock_irqsave(&package
->lock
, flags
);
330 package
->multi_channel
= false;
332 package
->channel_whitelist
= 0x1 << channel
->id
;
333 package
->preferred_channel
= channel
;
335 /* Allow any channel */
336 package
->channel_whitelist
= UINT_MAX
;
337 package
->preferred_channel
= NULL
;
339 spin_unlock_irqrestore(&package
->lock
, flags
);
342 netdev_info(ndp
->ndev
.dev
,
343 "Set package 0x%x, channel 0x%x as preferred\n",
344 package_id
, channel_id
);
346 netdev_info(ndp
->ndev
.dev
, "Set package 0x%x as preferred\n",
349 /* Update channel configuration */
350 if (!(ndp
->flags
& NCSI_DEV_RESET
))
351 ncsi_reset_dev(&ndp
->ndev
);
356 static int ncsi_clear_interface_nl(struct sk_buff
*msg
, struct genl_info
*info
)
358 struct ncsi_dev_priv
*ndp
;
359 struct ncsi_package
*np
;
362 if (!info
|| !info
->attrs
)
365 if (!info
->attrs
[NCSI_ATTR_IFINDEX
])
368 ndp
= ndp_from_ifindex(get_net(sock_net(msg
->sk
)),
369 nla_get_u32(info
->attrs
[NCSI_ATTR_IFINDEX
]));
373 /* Reset any whitelists and disable multi mode */
374 spin_lock_irqsave(&ndp
->lock
, flags
);
375 ndp
->package_whitelist
= UINT_MAX
;
376 ndp
->multi_package
= false;
377 spin_unlock_irqrestore(&ndp
->lock
, flags
);
379 NCSI_FOR_EACH_PACKAGE(ndp
, np
) {
380 spin_lock_irqsave(&np
->lock
, flags
);
381 np
->multi_channel
= false;
382 np
->channel_whitelist
= UINT_MAX
;
383 np
->preferred_channel
= NULL
;
384 spin_unlock_irqrestore(&np
->lock
, flags
);
386 netdev_info(ndp
->ndev
.dev
, "NCSI: Cleared preferred package/channel\n");
388 /* Update channel configuration */
389 if (!(ndp
->flags
& NCSI_DEV_RESET
))
390 ncsi_reset_dev(&ndp
->ndev
);
395 static int ncsi_send_cmd_nl(struct sk_buff
*msg
, struct genl_info
*info
)
397 struct ncsi_dev_priv
*ndp
;
398 struct ncsi_pkt_hdr
*hdr
;
399 struct ncsi_cmd_arg nca
;
405 if (!info
|| !info
->attrs
) {
410 if (!info
->attrs
[NCSI_ATTR_IFINDEX
]) {
415 if (!info
->attrs
[NCSI_ATTR_PACKAGE_ID
]) {
420 if (!info
->attrs
[NCSI_ATTR_CHANNEL_ID
]) {
425 if (!info
->attrs
[NCSI_ATTR_DATA
]) {
430 ndp
= ndp_from_ifindex(get_net(sock_net(msg
->sk
)),
431 nla_get_u32(info
->attrs
[NCSI_ATTR_IFINDEX
]));
437 package_id
= nla_get_u32(info
->attrs
[NCSI_ATTR_PACKAGE_ID
]);
438 channel_id
= nla_get_u32(info
->attrs
[NCSI_ATTR_CHANNEL_ID
]);
440 if (package_id
>= NCSI_MAX_PACKAGE
|| channel_id
>= NCSI_MAX_CHANNEL
) {
445 len
= nla_len(info
->attrs
[NCSI_ATTR_DATA
]);
446 if (len
< sizeof(struct ncsi_pkt_hdr
)) {
447 netdev_info(ndp
->ndev
.dev
, "NCSI: no command to send %u\n",
452 data
= (unsigned char *)nla_data(info
->attrs
[NCSI_ATTR_DATA
]);
455 hdr
= (struct ncsi_pkt_hdr
*)data
;
458 nca
.package
= (unsigned char)package_id
;
459 nca
.channel
= (unsigned char)channel_id
;
460 nca
.type
= hdr
->type
;
461 nca
.req_flags
= NCSI_REQ_FLAG_NETLINK_DRIVEN
;
463 nca
.payload
= ntohs(hdr
->length
);
464 nca
.data
= data
+ sizeof(*hdr
);
466 ret
= ncsi_xmit_cmd(&nca
);
469 netdev_err(ndp
->ndev
.dev
,
470 "NCSI: Error %d sending command\n",
472 ncsi_send_netlink_err(ndp
->ndev
.dev
,
482 int ncsi_send_netlink_rsp(struct ncsi_request
*nr
,
483 struct ncsi_package
*np
,
484 struct ncsi_channel
*nc
)
491 net
= dev_net(nr
->rsp
->dev
);
493 skb
= genlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_ATOMIC
);
497 hdr
= genlmsg_put(skb
, nr
->snd_portid
, nr
->snd_seq
,
498 &ncsi_genl_family
, 0, NCSI_CMD_SEND_CMD
);
504 nla_put_u32(skb
, NCSI_ATTR_IFINDEX
, nr
->rsp
->dev
->ifindex
);
506 nla_put_u32(skb
, NCSI_ATTR_PACKAGE_ID
, np
->id
);
508 nla_put_u32(skb
, NCSI_ATTR_CHANNEL_ID
, nc
->id
);
510 nla_put_u32(skb
, NCSI_ATTR_CHANNEL_ID
, NCSI_RESERVED_CHANNEL
);
512 rc
= nla_put(skb
, NCSI_ATTR_DATA
, nr
->rsp
->len
, (void *)nr
->rsp
->data
);
516 genlmsg_end(skb
, hdr
);
517 return genlmsg_unicast(net
, skb
, nr
->snd_portid
);
524 int ncsi_send_netlink_timeout(struct ncsi_request
*nr
,
525 struct ncsi_package
*np
,
526 struct ncsi_channel
*nc
)
532 skb
= genlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_ATOMIC
);
536 hdr
= genlmsg_put(skb
, nr
->snd_portid
, nr
->snd_seq
,
537 &ncsi_genl_family
, 0, NCSI_CMD_SEND_CMD
);
543 net
= dev_net(nr
->cmd
->dev
);
545 nla_put_u32(skb
, NCSI_ATTR_IFINDEX
, nr
->cmd
->dev
->ifindex
);
548 nla_put_u32(skb
, NCSI_ATTR_PACKAGE_ID
, np
->id
);
550 nla_put_u32(skb
, NCSI_ATTR_PACKAGE_ID
,
551 NCSI_PACKAGE_INDEX((((struct ncsi_pkt_hdr
*)
552 nr
->cmd
->data
)->channel
)));
555 nla_put_u32(skb
, NCSI_ATTR_CHANNEL_ID
, nc
->id
);
557 nla_put_u32(skb
, NCSI_ATTR_CHANNEL_ID
, NCSI_RESERVED_CHANNEL
);
559 genlmsg_end(skb
, hdr
);
560 return genlmsg_unicast(net
, skb
, nr
->snd_portid
);
563 int ncsi_send_netlink_err(struct net_device
*dev
,
566 const struct nlmsghdr
*nlhdr
,
569 struct nlmsghdr
*nlh
;
570 struct nlmsgerr
*nle
;
574 skb
= nlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_ATOMIC
);
580 nlh
= nlmsg_put(skb
, snd_portid
, snd_seq
,
581 NLMSG_ERROR
, sizeof(*nle
), 0);
582 nle
= (struct nlmsgerr
*)nlmsg_data(nlh
);
584 memcpy(&nle
->msg
, nlhdr
, sizeof(*nlh
));
588 return nlmsg_unicast(net
->genl_sock
, skb
, snd_portid
);
591 static int ncsi_set_package_mask_nl(struct sk_buff
*msg
,
592 struct genl_info
*info
)
594 struct ncsi_dev_priv
*ndp
;
598 if (!info
|| !info
->attrs
)
601 if (!info
->attrs
[NCSI_ATTR_IFINDEX
])
604 if (!info
->attrs
[NCSI_ATTR_PACKAGE_MASK
])
607 ndp
= ndp_from_ifindex(get_net(sock_net(msg
->sk
)),
608 nla_get_u32(info
->attrs
[NCSI_ATTR_IFINDEX
]));
612 spin_lock_irqsave(&ndp
->lock
, flags
);
613 if (nla_get_flag(info
->attrs
[NCSI_ATTR_MULTI_FLAG
])) {
614 if (ndp
->flags
& NCSI_DEV_HWA
) {
615 ndp
->multi_package
= true;
618 netdev_err(ndp
->ndev
.dev
,
619 "NCSI: Can't use multiple packages without HWA\n");
623 ndp
->multi_package
= false;
628 ndp
->package_whitelist
=
629 nla_get_u32(info
->attrs
[NCSI_ATTR_PACKAGE_MASK
]);
630 spin_unlock_irqrestore(&ndp
->lock
, flags
);
633 /* Update channel configuration */
634 if (!(ndp
->flags
& NCSI_DEV_RESET
))
635 ncsi_reset_dev(&ndp
->ndev
);
641 static int ncsi_set_channel_mask_nl(struct sk_buff
*msg
,
642 struct genl_info
*info
)
644 struct ncsi_package
*np
, *package
;
645 struct ncsi_channel
*nc
, *channel
;
646 u32 package_id
, channel_id
;
647 struct ncsi_dev_priv
*ndp
;
650 if (!info
|| !info
->attrs
)
653 if (!info
->attrs
[NCSI_ATTR_IFINDEX
])
656 if (!info
->attrs
[NCSI_ATTR_PACKAGE_ID
])
659 if (!info
->attrs
[NCSI_ATTR_CHANNEL_MASK
])
662 ndp
= ndp_from_ifindex(get_net(sock_net(msg
->sk
)),
663 nla_get_u32(info
->attrs
[NCSI_ATTR_IFINDEX
]));
667 package_id
= nla_get_u32(info
->attrs
[NCSI_ATTR_PACKAGE_ID
]);
669 NCSI_FOR_EACH_PACKAGE(ndp
, np
)
670 if (np
->id
== package_id
) {
677 spin_lock_irqsave(&package
->lock
, flags
);
680 if (info
->attrs
[NCSI_ATTR_CHANNEL_ID
]) {
681 channel_id
= nla_get_u32(info
->attrs
[NCSI_ATTR_CHANNEL_ID
]);
682 NCSI_FOR_EACH_CHANNEL(np
, nc
)
683 if (nc
->id
== channel_id
) {
688 spin_unlock_irqrestore(&package
->lock
, flags
);
691 netdev_dbg(ndp
->ndev
.dev
,
692 "NCSI: Channel %u set as preferred channel\n",
696 package
->channel_whitelist
=
697 nla_get_u32(info
->attrs
[NCSI_ATTR_CHANNEL_MASK
]);
698 if (package
->channel_whitelist
== 0)
699 netdev_dbg(ndp
->ndev
.dev
,
700 "NCSI: Package %u set to all channels disabled\n",
703 package
->preferred_channel
= channel
;
705 if (nla_get_flag(info
->attrs
[NCSI_ATTR_MULTI_FLAG
])) {
706 package
->multi_channel
= true;
707 netdev_info(ndp
->ndev
.dev
,
708 "NCSI: Multi-channel enabled on package %u\n",
711 package
->multi_channel
= false;
714 spin_unlock_irqrestore(&package
->lock
, flags
);
716 /* Update channel configuration */
717 if (!(ndp
->flags
& NCSI_DEV_RESET
))
718 ncsi_reset_dev(&ndp
->ndev
);
723 static const struct genl_small_ops ncsi_ops
[] = {
725 .cmd
= NCSI_CMD_PKG_INFO
,
726 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
727 .doit
= ncsi_pkg_info_nl
,
728 .dumpit
= ncsi_pkg_info_all_nl
,
732 .cmd
= NCSI_CMD_SET_INTERFACE
,
733 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
734 .doit
= ncsi_set_interface_nl
,
735 .flags
= GENL_ADMIN_PERM
,
738 .cmd
= NCSI_CMD_CLEAR_INTERFACE
,
739 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
740 .doit
= ncsi_clear_interface_nl
,
741 .flags
= GENL_ADMIN_PERM
,
744 .cmd
= NCSI_CMD_SEND_CMD
,
745 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
746 .doit
= ncsi_send_cmd_nl
,
747 .flags
= GENL_ADMIN_PERM
,
750 .cmd
= NCSI_CMD_SET_PACKAGE_MASK
,
751 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
752 .doit
= ncsi_set_package_mask_nl
,
753 .flags
= GENL_ADMIN_PERM
,
756 .cmd
= NCSI_CMD_SET_CHANNEL_MASK
,
757 .validate
= GENL_DONT_VALIDATE_STRICT
| GENL_DONT_VALIDATE_DUMP
,
758 .doit
= ncsi_set_channel_mask_nl
,
759 .flags
= GENL_ADMIN_PERM
,
763 static struct genl_family ncsi_genl_family __ro_after_init
= {
766 .maxattr
= NCSI_ATTR_MAX
,
767 .policy
= ncsi_genl_policy
,
768 .module
= THIS_MODULE
,
769 .small_ops
= ncsi_ops
,
770 .n_small_ops
= ARRAY_SIZE(ncsi_ops
),
771 .resv_start_op
= NCSI_CMD_SET_CHANNEL_MASK
+ 1,
774 static int __init
ncsi_init_netlink(void)
776 return genl_register_family(&ncsi_genl_family
);
778 subsys_initcall(ncsi_init_netlink
);