]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blame - net/core/devlink.c
gre: eliminate holes in ip_tunnel
[mirror_ubuntu-zesty-kernel.git] / net / core / devlink.c
CommitLineData
bfcd3a46
JP
1/*
2 * net/core/devlink.c - Network physical/parent device Netlink interface
3 *
4 * Heavily inspired by net/wireless/
5 * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
6 * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 */
13
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/types.h>
17#include <linux/slab.h>
18#include <linux/gfp.h>
19#include <linux/device.h>
20#include <linux/list.h>
21#include <linux/netdevice.h>
22#include <rdma/ib_verbs.h>
23#include <net/netlink.h>
24#include <net/genetlink.h>
25#include <net/rtnetlink.h>
26#include <net/net_namespace.h>
27#include <net/sock.h>
28#include <net/devlink.h>
29
30static LIST_HEAD(devlink_list);
31
32/* devlink_mutex
33 *
34 * An overall lock guarding every operation coming from userspace.
35 * It also guards devlink devices list and it is taken when
36 * driver registers/unregisters it.
37 */
38static DEFINE_MUTEX(devlink_mutex);
39
40/* devlink_port_mutex
41 *
42 * Shared lock to guard lists of ports in all devlink devices.
43 */
44static DEFINE_MUTEX(devlink_port_mutex);
45
46static struct net *devlink_net(const struct devlink *devlink)
47{
48 return read_pnet(&devlink->_net);
49}
50
51static void devlink_net_set(struct devlink *devlink, struct net *net)
52{
53 write_pnet(&devlink->_net, net);
54}
55
56static struct devlink *devlink_get_from_attrs(struct net *net,
57 struct nlattr **attrs)
58{
59 struct devlink *devlink;
60 char *busname;
61 char *devname;
62
63 if (!attrs[DEVLINK_ATTR_BUS_NAME] || !attrs[DEVLINK_ATTR_DEV_NAME])
64 return ERR_PTR(-EINVAL);
65
66 busname = nla_data(attrs[DEVLINK_ATTR_BUS_NAME]);
67 devname = nla_data(attrs[DEVLINK_ATTR_DEV_NAME]);
68
69 list_for_each_entry(devlink, &devlink_list, list) {
70 if (strcmp(devlink->dev->bus->name, busname) == 0 &&
71 strcmp(dev_name(devlink->dev), devname) == 0 &&
72 net_eq(devlink_net(devlink), net))
73 return devlink;
74 }
75
76 return ERR_PTR(-ENODEV);
77}
78
79static struct devlink *devlink_get_from_info(struct genl_info *info)
80{
81 return devlink_get_from_attrs(genl_info_net(info), info->attrs);
82}
83
84static struct devlink_port *devlink_port_get_by_index(struct devlink *devlink,
85 int port_index)
86{
87 struct devlink_port *devlink_port;
88
89 list_for_each_entry(devlink_port, &devlink->port_list, list) {
90 if (devlink_port->index == port_index)
91 return devlink_port;
92 }
93 return NULL;
94}
95
96static bool devlink_port_index_exists(struct devlink *devlink, int port_index)
97{
98 return devlink_port_get_by_index(devlink, port_index);
99}
100
101static struct devlink_port *devlink_port_get_from_attrs(struct devlink *devlink,
102 struct nlattr **attrs)
103{
104 if (attrs[DEVLINK_ATTR_PORT_INDEX]) {
105 u32 port_index = nla_get_u32(attrs[DEVLINK_ATTR_PORT_INDEX]);
106 struct devlink_port *devlink_port;
107
108 devlink_port = devlink_port_get_by_index(devlink, port_index);
109 if (!devlink_port)
110 return ERR_PTR(-ENODEV);
111 return devlink_port;
112 }
113 return ERR_PTR(-EINVAL);
114}
115
116static struct devlink_port *devlink_port_get_from_info(struct devlink *devlink,
117 struct genl_info *info)
118{
119 return devlink_port_get_from_attrs(devlink, info->attrs);
120}
121
1fc2257e
JP
122#define DEVLINK_NL_FLAG_NEED_DEVLINK BIT(0)
123#define DEVLINK_NL_FLAG_NEED_PORT BIT(1)
bfcd3a46
JP
124
125static int devlink_nl_pre_doit(const struct genl_ops *ops,
126 struct sk_buff *skb, struct genl_info *info)
127{
128 struct devlink *devlink;
129
130 mutex_lock(&devlink_mutex);
131 devlink = devlink_get_from_info(info);
132 if (IS_ERR(devlink)) {
133 mutex_unlock(&devlink_mutex);
134 return PTR_ERR(devlink);
135 }
1fc2257e
JP
136 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_DEVLINK) {
137 info->user_ptr[0] = devlink;
138 } else if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_PORT) {
bfcd3a46
JP
139 struct devlink_port *devlink_port;
140
141 mutex_lock(&devlink_port_mutex);
142 devlink_port = devlink_port_get_from_info(devlink, info);
143 if (IS_ERR(devlink_port)) {
144 mutex_unlock(&devlink_port_mutex);
145 mutex_unlock(&devlink_mutex);
146 return PTR_ERR(devlink_port);
147 }
1fc2257e 148 info->user_ptr[0] = devlink_port;
bfcd3a46
JP
149 }
150 return 0;
151}
152
153static void devlink_nl_post_doit(const struct genl_ops *ops,
154 struct sk_buff *skb, struct genl_info *info)
155{
156 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_PORT)
157 mutex_unlock(&devlink_port_mutex);
158 mutex_unlock(&devlink_mutex);
159}
160
161static struct genl_family devlink_nl_family = {
162 .id = GENL_ID_GENERATE,
163 .name = DEVLINK_GENL_NAME,
164 .version = DEVLINK_GENL_VERSION,
165 .maxattr = DEVLINK_ATTR_MAX,
166 .netnsok = true,
167 .pre_doit = devlink_nl_pre_doit,
168 .post_doit = devlink_nl_post_doit,
169};
170
171enum devlink_multicast_groups {
172 DEVLINK_MCGRP_CONFIG,
173};
174
175static const struct genl_multicast_group devlink_nl_mcgrps[] = {
176 [DEVLINK_MCGRP_CONFIG] = { .name = DEVLINK_GENL_MCGRP_CONFIG_NAME },
177};
178
179static int devlink_nl_put_handle(struct sk_buff *msg, struct devlink *devlink)
180{
181 if (nla_put_string(msg, DEVLINK_ATTR_BUS_NAME, devlink->dev->bus->name))
182 return -EMSGSIZE;
183 if (nla_put_string(msg, DEVLINK_ATTR_DEV_NAME, dev_name(devlink->dev)))
184 return -EMSGSIZE;
185 return 0;
186}
187
188static int devlink_nl_fill(struct sk_buff *msg, struct devlink *devlink,
189 enum devlink_command cmd, u32 portid,
190 u32 seq, int flags)
191{
192 void *hdr;
193
194 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
195 if (!hdr)
196 return -EMSGSIZE;
197
198 if (devlink_nl_put_handle(msg, devlink))
199 goto nla_put_failure;
200
201 genlmsg_end(msg, hdr);
202 return 0;
203
204nla_put_failure:
205 genlmsg_cancel(msg, hdr);
206 return -EMSGSIZE;
207}
208
209static void devlink_notify(struct devlink *devlink, enum devlink_command cmd)
210{
211 struct sk_buff *msg;
212 int err;
213
214 WARN_ON(cmd != DEVLINK_CMD_NEW && cmd != DEVLINK_CMD_DEL);
215
216 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
217 if (!msg)
218 return;
219
220 err = devlink_nl_fill(msg, devlink, cmd, 0, 0, 0);
221 if (err) {
222 nlmsg_free(msg);
223 return;
224 }
225
226 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
227 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
228}
229
230static int devlink_nl_port_fill(struct sk_buff *msg, struct devlink *devlink,
231 struct devlink_port *devlink_port,
232 enum devlink_command cmd, u32 portid,
233 u32 seq, int flags)
234{
235 void *hdr;
236
237 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
238 if (!hdr)
239 return -EMSGSIZE;
240
241 if (devlink_nl_put_handle(msg, devlink))
242 goto nla_put_failure;
243 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
244 goto nla_put_failure;
245 if (nla_put_u16(msg, DEVLINK_ATTR_PORT_TYPE, devlink_port->type))
246 goto nla_put_failure;
247 if (devlink_port->desired_type != DEVLINK_PORT_TYPE_NOTSET &&
248 nla_put_u16(msg, DEVLINK_ATTR_PORT_DESIRED_TYPE,
249 devlink_port->desired_type))
250 goto nla_put_failure;
251 if (devlink_port->type == DEVLINK_PORT_TYPE_ETH) {
252 struct net_device *netdev = devlink_port->type_dev;
253
254 if (netdev &&
255 (nla_put_u32(msg, DEVLINK_ATTR_PORT_NETDEV_IFINDEX,
256 netdev->ifindex) ||
257 nla_put_string(msg, DEVLINK_ATTR_PORT_NETDEV_NAME,
258 netdev->name)))
259 goto nla_put_failure;
260 }
261 if (devlink_port->type == DEVLINK_PORT_TYPE_IB) {
262 struct ib_device *ibdev = devlink_port->type_dev;
263
264 if (ibdev &&
265 nla_put_string(msg, DEVLINK_ATTR_PORT_IBDEV_NAME,
266 ibdev->name))
267 goto nla_put_failure;
268 }
269 if (devlink_port->split &&
270 nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_GROUP,
271 devlink_port->split_group))
272 goto nla_put_failure;
273
274 genlmsg_end(msg, hdr);
275 return 0;
276
277nla_put_failure:
278 genlmsg_cancel(msg, hdr);
279 return -EMSGSIZE;
280}
281
282static void devlink_port_notify(struct devlink_port *devlink_port,
283 enum devlink_command cmd)
284{
285 struct devlink *devlink = devlink_port->devlink;
286 struct sk_buff *msg;
287 int err;
288
289 if (!devlink_port->registered)
290 return;
291
292 WARN_ON(cmd != DEVLINK_CMD_PORT_NEW && cmd != DEVLINK_CMD_PORT_DEL);
293
294 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
295 if (!msg)
296 return;
297
298 err = devlink_nl_port_fill(msg, devlink, devlink_port, cmd, 0, 0, 0);
299 if (err) {
300 nlmsg_free(msg);
301 return;
302 }
303
304 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
305 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
306}
307
308static int devlink_nl_cmd_get_doit(struct sk_buff *skb, struct genl_info *info)
309{
310 struct devlink *devlink = info->user_ptr[0];
311 struct sk_buff *msg;
312 int err;
313
314 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
315 if (!msg)
316 return -ENOMEM;
317
318 err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW,
319 info->snd_portid, info->snd_seq, 0);
320 if (err) {
321 nlmsg_free(msg);
322 return err;
323 }
324
325 return genlmsg_reply(msg, info);
326}
327
328static int devlink_nl_cmd_get_dumpit(struct sk_buff *msg,
329 struct netlink_callback *cb)
330{
331 struct devlink *devlink;
332 int start = cb->args[0];
333 int idx = 0;
334 int err;
335
336 mutex_lock(&devlink_mutex);
337 list_for_each_entry(devlink, &devlink_list, list) {
338 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
339 continue;
340 if (idx < start) {
341 idx++;
342 continue;
343 }
344 err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW,
345 NETLINK_CB(cb->skb).portid,
346 cb->nlh->nlmsg_seq, NLM_F_MULTI);
347 if (err)
348 goto out;
349 idx++;
350 }
351out:
352 mutex_unlock(&devlink_mutex);
353
354 cb->args[0] = idx;
355 return msg->len;
356}
357
358static int devlink_nl_cmd_port_get_doit(struct sk_buff *skb,
359 struct genl_info *info)
360{
1fc2257e
JP
361 struct devlink_port *devlink_port = info->user_ptr[0];
362 struct devlink *devlink = devlink_port->devlink;
bfcd3a46
JP
363 struct sk_buff *msg;
364 int err;
365
366 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
367 if (!msg)
368 return -ENOMEM;
369
370 err = devlink_nl_port_fill(msg, devlink, devlink_port,
371 DEVLINK_CMD_PORT_NEW,
372 info->snd_portid, info->snd_seq, 0);
373 if (err) {
374 nlmsg_free(msg);
375 return err;
376 }
377
378 return genlmsg_reply(msg, info);
379}
380
381static int devlink_nl_cmd_port_get_dumpit(struct sk_buff *msg,
382 struct netlink_callback *cb)
383{
384 struct devlink *devlink;
385 struct devlink_port *devlink_port;
386 int start = cb->args[0];
387 int idx = 0;
388 int err;
389
390 mutex_lock(&devlink_mutex);
391 mutex_lock(&devlink_port_mutex);
392 list_for_each_entry(devlink, &devlink_list, list) {
393 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
394 continue;
395 list_for_each_entry(devlink_port, &devlink->port_list, list) {
396 if (idx < start) {
397 idx++;
398 continue;
399 }
400 err = devlink_nl_port_fill(msg, devlink, devlink_port,
401 DEVLINK_CMD_NEW,
402 NETLINK_CB(cb->skb).portid,
403 cb->nlh->nlmsg_seq,
404 NLM_F_MULTI);
405 if (err)
406 goto out;
407 idx++;
408 }
409 }
410out:
411 mutex_unlock(&devlink_port_mutex);
412 mutex_unlock(&devlink_mutex);
413
414 cb->args[0] = idx;
415 return msg->len;
416}
417
418static int devlink_port_type_set(struct devlink *devlink,
419 struct devlink_port *devlink_port,
420 enum devlink_port_type port_type)
421
422{
423 int err;
424
425 if (devlink->ops && devlink->ops->port_type_set) {
426 if (port_type == DEVLINK_PORT_TYPE_NOTSET)
427 return -EINVAL;
428 err = devlink->ops->port_type_set(devlink_port, port_type);
429 if (err)
430 return err;
431 devlink_port->desired_type = port_type;
432 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
433 return 0;
434 }
435 return -EOPNOTSUPP;
436}
437
438static int devlink_nl_cmd_port_set_doit(struct sk_buff *skb,
439 struct genl_info *info)
440{
1fc2257e
JP
441 struct devlink_port *devlink_port = info->user_ptr[0];
442 struct devlink *devlink = devlink_port->devlink;
bfcd3a46
JP
443 int err;
444
445 if (info->attrs[DEVLINK_ATTR_PORT_TYPE]) {
446 enum devlink_port_type port_type;
447
448 port_type = nla_get_u16(info->attrs[DEVLINK_ATTR_PORT_TYPE]);
449 err = devlink_port_type_set(devlink, devlink_port, port_type);
450 if (err)
451 return err;
452 }
453 return 0;
454}
455
456static int devlink_port_split(struct devlink *devlink,
457 u32 port_index, u32 count)
458
459{
460 if (devlink->ops && devlink->ops->port_split)
461 return devlink->ops->port_split(devlink, port_index, count);
462 return -EOPNOTSUPP;
463}
464
465static int devlink_nl_cmd_port_split_doit(struct sk_buff *skb,
466 struct genl_info *info)
467{
468 struct devlink *devlink = info->user_ptr[0];
469 u32 port_index;
470 u32 count;
471
472 if (!info->attrs[DEVLINK_ATTR_PORT_INDEX] ||
473 !info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT])
474 return -EINVAL;
475
476 port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
477 count = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT]);
478 return devlink_port_split(devlink, port_index, count);
479}
480
481static int devlink_port_unsplit(struct devlink *devlink, u32 port_index)
482
483{
484 if (devlink->ops && devlink->ops->port_unsplit)
485 return devlink->ops->port_unsplit(devlink, port_index);
486 return -EOPNOTSUPP;
487}
488
489static int devlink_nl_cmd_port_unsplit_doit(struct sk_buff *skb,
490 struct genl_info *info)
491{
492 struct devlink *devlink = info->user_ptr[0];
493 u32 port_index;
494
495 if (!info->attrs[DEVLINK_ATTR_PORT_INDEX])
496 return -EINVAL;
497
498 port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
499 return devlink_port_unsplit(devlink, port_index);
500}
501
502static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
503 [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING },
504 [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING },
505 [DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32 },
506 [DEVLINK_ATTR_PORT_TYPE] = { .type = NLA_U16 },
507 [DEVLINK_ATTR_PORT_SPLIT_COUNT] = { .type = NLA_U32 },
508};
509
510static const struct genl_ops devlink_nl_ops[] = {
511 {
512 .cmd = DEVLINK_CMD_GET,
513 .doit = devlink_nl_cmd_get_doit,
514 .dumpit = devlink_nl_cmd_get_dumpit,
515 .policy = devlink_nl_policy,
1fc2257e 516 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
bfcd3a46
JP
517 /* can be retrieved by unprivileged users */
518 },
519 {
520 .cmd = DEVLINK_CMD_PORT_GET,
521 .doit = devlink_nl_cmd_port_get_doit,
522 .dumpit = devlink_nl_cmd_port_get_dumpit,
523 .policy = devlink_nl_policy,
524 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
525 /* can be retrieved by unprivileged users */
526 },
527 {
528 .cmd = DEVLINK_CMD_PORT_SET,
529 .doit = devlink_nl_cmd_port_set_doit,
530 .policy = devlink_nl_policy,
531 .flags = GENL_ADMIN_PERM,
532 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
533 },
534 {
535 .cmd = DEVLINK_CMD_PORT_SPLIT,
536 .doit = devlink_nl_cmd_port_split_doit,
537 .policy = devlink_nl_policy,
538 .flags = GENL_ADMIN_PERM,
1fc2257e 539 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
bfcd3a46
JP
540 },
541 {
542 .cmd = DEVLINK_CMD_PORT_UNSPLIT,
543 .doit = devlink_nl_cmd_port_unsplit_doit,
544 .policy = devlink_nl_policy,
545 .flags = GENL_ADMIN_PERM,
1fc2257e 546 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
bfcd3a46
JP
547 },
548};
549
550/**
551 * devlink_alloc - Allocate new devlink instance resources
552 *
553 * @ops: ops
554 * @priv_size: size of user private data
555 *
556 * Allocate new devlink instance resources, including devlink index
557 * and name.
558 */
559struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size)
560{
561 struct devlink *devlink;
562
563 devlink = kzalloc(sizeof(*devlink) + priv_size, GFP_KERNEL);
564 if (!devlink)
565 return NULL;
566 devlink->ops = ops;
567 devlink_net_set(devlink, &init_net);
568 INIT_LIST_HEAD(&devlink->port_list);
569 return devlink;
570}
571EXPORT_SYMBOL_GPL(devlink_alloc);
572
573/**
574 * devlink_register - Register devlink instance
575 *
576 * @devlink: devlink
577 */
578int devlink_register(struct devlink *devlink, struct device *dev)
579{
580 mutex_lock(&devlink_mutex);
581 devlink->dev = dev;
582 list_add_tail(&devlink->list, &devlink_list);
583 devlink_notify(devlink, DEVLINK_CMD_NEW);
584 mutex_unlock(&devlink_mutex);
585 return 0;
586}
587EXPORT_SYMBOL_GPL(devlink_register);
588
589/**
590 * devlink_unregister - Unregister devlink instance
591 *
592 * @devlink: devlink
593 */
594void devlink_unregister(struct devlink *devlink)
595{
596 mutex_lock(&devlink_mutex);
597 devlink_notify(devlink, DEVLINK_CMD_DEL);
598 list_del(&devlink->list);
599 mutex_unlock(&devlink_mutex);
600}
601EXPORT_SYMBOL_GPL(devlink_unregister);
602
603/**
604 * devlink_free - Free devlink instance resources
605 *
606 * @devlink: devlink
607 */
608void devlink_free(struct devlink *devlink)
609{
610 kfree(devlink);
611}
612EXPORT_SYMBOL_GPL(devlink_free);
613
614/**
615 * devlink_port_register - Register devlink port
616 *
617 * @devlink: devlink
618 * @devlink_port: devlink port
619 * @port_index
620 *
621 * Register devlink port with provided port index. User can use
622 * any indexing, even hw-related one. devlink_port structure
623 * is convenient to be embedded inside user driver private structure.
624 * Note that the caller should take care of zeroing the devlink_port
625 * structure.
626 */
627int devlink_port_register(struct devlink *devlink,
628 struct devlink_port *devlink_port,
629 unsigned int port_index)
630{
631 mutex_lock(&devlink_port_mutex);
632 if (devlink_port_index_exists(devlink, port_index)) {
633 mutex_unlock(&devlink_port_mutex);
634 return -EEXIST;
635 }
636 devlink_port->devlink = devlink;
637 devlink_port->index = port_index;
bfcd3a46
JP
638 devlink_port->registered = true;
639 list_add_tail(&devlink_port->list, &devlink->port_list);
640 mutex_unlock(&devlink_port_mutex);
641 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
642 return 0;
643}
644EXPORT_SYMBOL_GPL(devlink_port_register);
645
646/**
647 * devlink_port_unregister - Unregister devlink port
648 *
649 * @devlink_port: devlink port
650 */
651void devlink_port_unregister(struct devlink_port *devlink_port)
652{
653 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL);
654 mutex_lock(&devlink_port_mutex);
655 list_del(&devlink_port->list);
656 mutex_unlock(&devlink_port_mutex);
657}
658EXPORT_SYMBOL_GPL(devlink_port_unregister);
659
660static void __devlink_port_type_set(struct devlink_port *devlink_port,
661 enum devlink_port_type type,
662 void *type_dev)
663{
664 devlink_port->type = type;
665 devlink_port->type_dev = type_dev;
666 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
667}
668
669/**
670 * devlink_port_type_eth_set - Set port type to Ethernet
671 *
672 * @devlink_port: devlink port
673 * @netdev: related netdevice
674 */
675void devlink_port_type_eth_set(struct devlink_port *devlink_port,
676 struct net_device *netdev)
677{
678 return __devlink_port_type_set(devlink_port,
679 DEVLINK_PORT_TYPE_ETH, netdev);
680}
681EXPORT_SYMBOL_GPL(devlink_port_type_eth_set);
682
683/**
684 * devlink_port_type_ib_set - Set port type to InfiniBand
685 *
686 * @devlink_port: devlink port
687 * @ibdev: related IB device
688 */
689void devlink_port_type_ib_set(struct devlink_port *devlink_port,
690 struct ib_device *ibdev)
691{
692 return __devlink_port_type_set(devlink_port,
693 DEVLINK_PORT_TYPE_IB, ibdev);
694}
695EXPORT_SYMBOL_GPL(devlink_port_type_ib_set);
696
697/**
698 * devlink_port_type_clear - Clear port type
699 *
700 * @devlink_port: devlink port
701 */
702void devlink_port_type_clear(struct devlink_port *devlink_port)
703{
704 return __devlink_port_type_set(devlink_port,
705 DEVLINK_PORT_TYPE_NOTSET, NULL);
706}
707EXPORT_SYMBOL_GPL(devlink_port_type_clear);
708
709/**
710 * devlink_port_split_set - Set port is split
711 *
712 * @devlink_port: devlink port
713 * @split_group: split group - identifies group split port is part of
714 */
715void devlink_port_split_set(struct devlink_port *devlink_port,
716 u32 split_group)
717{
718 devlink_port->split = true;
719 devlink_port->split_group = split_group;
720 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
721}
722EXPORT_SYMBOL_GPL(devlink_port_split_set);
723
724static int __init devlink_module_init(void)
725{
726 return genl_register_family_with_ops_groups(&devlink_nl_family,
727 devlink_nl_ops,
728 devlink_nl_mcgrps);
729}
730
731static void __exit devlink_module_exit(void)
732{
733 genl_unregister_family(&devlink_nl_family);
734}
735
736module_init(devlink_module_init);
737module_exit(devlink_module_exit);
738
739MODULE_LICENSE("GPL v2");
740MODULE_AUTHOR("Jiri Pirko <jiri@mellanox.com>");
741MODULE_DESCRIPTION("Network physical device Netlink interface");
742MODULE_ALIAS_GENL_FAMILY(DEVLINK_GENL_NAME);