2 * swconfig.c: Switch configuration API
4 * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
17 #include <linux/types.h>
18 #include <linux/module.h>
19 #include <linux/init.h>
20 #include <linux/list.h>
22 #include <linux/if_ether.h>
23 #include <linux/capability.h>
24 #include <linux/skbuff.h>
25 #include <linux/switch.h>
29 #define DPRINTF(format, ...) printk("%s: " format, __func__, ##__VA_ARGS__)
31 #define DPRINTF(...) do {} while(0)
34 MODULE_AUTHOR("Felix Fietkau <nbd@openwrt.org>");
35 MODULE_LICENSE("GPL");
37 static int swdev_id = 0;
38 static struct list_head swdevs;
39 static spinlock_t swdevs_lock = SPIN_LOCK_UNLOCKED;
40 struct swconfig_callback;
42 struct swconfig_callback
45 struct genlmsghdr *hdr;
46 struct genl_info *info;
49 /* callback for filling in the message data */
50 int (*fill)(struct swconfig_callback *cb, void *arg);
52 /* callback for closing the message before sending it */
53 int (*close)(struct swconfig_callback *cb, void *arg);
55 struct nlattr *nest[4];
62 swconfig_get_vlan_ports(struct switch_dev *dev, struct switch_attr *attr, struct switch_val *val)
65 if (val->port_vlan >= dev->vlans)
68 if (!dev->get_vlan_ports)
71 ret = dev->get_vlan_ports(dev, val);
72 printk("SET PORTS %d\n", val->len);
77 swconfig_set_vlan_ports(struct switch_dev *dev, struct switch_attr *attr, struct switch_val *val)
81 if (val->port_vlan >= dev->vlans)
85 if (val->len > dev->ports)
88 for (i = 0; i < val->len; i++) {
89 if (val->value.ports[i].id >= dev->ports)
93 if (!dev->set_vlan_ports)
96 printk("SET PORTS %d\n", val->len);
97 return dev->set_vlan_ports(dev, val);
101 swconfig_apply_config(struct switch_dev *dev, struct switch_attr *attr, struct switch_val *val)
103 /* don't complain if not supported by the switch driver */
104 if (!dev->apply_config)
107 return dev->apply_config(dev);
111 enum global_defaults {
123 static struct switch_attr default_global[] = {
125 .type = SWITCH_TYPE_NOVAL,
127 .description = "Activate changes in the hardware",
128 .set = swconfig_apply_config,
132 static struct switch_attr default_port[] = {
134 .type = SWITCH_TYPE_INT,
136 .description = "Current link speed",
140 static struct switch_attr default_vlan[] = {
142 .type = SWITCH_TYPE_PORTS,
144 .description = "VLAN port mapping",
145 .set = swconfig_set_vlan_ports,
146 .get = swconfig_get_vlan_ports,
151 static void swconfig_defaults_init(struct switch_dev *dev)
157 if (dev->get_vlan_ports || dev->set_vlan_ports)
158 set_bit(VLAN_PORTS, &dev->def_vlan);
160 /* always present, can be no-op */
161 set_bit(GLOBAL_APPLY, &dev->def_global);
165 static struct genl_family switch_fam = {
166 .id = GENL_ID_GENERATE,
170 .maxattr = SWITCH_ATTR_MAX,
173 static const struct nla_policy switch_policy[SWITCH_ATTR_MAX+1] = {
174 [SWITCH_ATTR_ID] = { .type = NLA_U32 },
175 [SWITCH_ATTR_OP_ID] = { .type = NLA_U32 },
176 [SWITCH_ATTR_OP_PORT] = { .type = NLA_U32 },
177 [SWITCH_ATTR_OP_VLAN] = { .type = NLA_U32 },
178 [SWITCH_ATTR_OP_VALUE_INT] = { .type = NLA_U32 },
179 [SWITCH_ATTR_OP_VALUE_STR] = { .type = NLA_NUL_STRING },
180 [SWITCH_ATTR_OP_VALUE_PORTS] = { .type = NLA_NESTED },
181 [SWITCH_ATTR_TYPE] = { .type = NLA_U32 },
184 static const struct nla_policy port_policy[SWITCH_PORT_ATTR_MAX+1] = {
185 [SWITCH_PORT_ID] = { .type = NLA_U32 },
186 [SWITCH_PORT_FLAG_TAGGED] = { .type = NLA_FLAG },
192 spin_lock(&swdevs_lock);
196 swconfig_unlock(void)
198 spin_unlock(&swdevs_lock);
201 static struct switch_dev *
202 swconfig_get_dev(struct genl_info *info)
204 struct switch_dev *dev = NULL;
205 struct switch_dev *p;
208 if (!info->attrs[SWITCH_ATTR_ID])
211 id = nla_get_u32(info->attrs[SWITCH_ATTR_ID]);
213 list_for_each_entry(p, &swdevs, dev_list) {
221 spin_lock(&dev->lock);
223 DPRINTF("device %d not found\n", id);
230 swconfig_put_dev(struct switch_dev *dev)
232 spin_unlock(&dev->lock);
236 swconfig_dump_attr(struct swconfig_callback *cb, void *arg)
238 struct switch_attr *op = arg;
239 struct genl_info *info = cb->info;
240 struct sk_buff *msg = cb->msg;
241 int id = cb->args[0];
244 hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, &switch_fam,
245 NLM_F_MULTI, SWITCH_CMD_NEW_ATTR);
249 NLA_PUT_U32(msg, SWITCH_ATTR_OP_ID, id);
250 NLA_PUT_U32(msg, SWITCH_ATTR_OP_TYPE, op->type);
251 NLA_PUT_STRING(msg, SWITCH_ATTR_OP_NAME, op->name);
253 NLA_PUT_STRING(msg, SWITCH_ATTR_OP_DESCRIPTION,
256 return genlmsg_end(msg, hdr);
258 genlmsg_cancel(msg, hdr);
262 /* spread multipart messages across multiple message buffers */
264 swconfig_send_multipart(struct swconfig_callback *cb, void *arg)
266 struct genl_info *info = cb->info;
272 cb->msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
277 if (!(cb->fill(cb, arg) < 0))
280 /* fill failed, check if this was already the second attempt */
284 /* try again in a new message, send the current one */
287 if (cb->close(cb, arg) < 0)
290 err = genlmsg_unicast(cb->msg, info->snd_pid);
306 swconfig_list_attrs(struct sk_buff *skb, struct genl_info *info)
308 struct genlmsghdr *hdr = nlmsg_data(info->nlhdr);
309 const struct switch_attrlist *alist;
310 struct switch_dev *dev;
311 struct swconfig_callback cb;
316 struct switch_attr *def_list;
317 unsigned long *def_active;
320 dev = swconfig_get_dev(info);
325 case SWITCH_CMD_LIST_GLOBAL:
326 alist = &dev->attr_global;
327 def_list = default_global;
328 def_active = &dev->def_global;
329 n_def = ARRAY_SIZE(default_global);
331 case SWITCH_CMD_LIST_VLAN:
332 alist = &dev->attr_vlan;
333 def_list = default_vlan;
334 def_active = &dev->def_vlan;
335 n_def = ARRAY_SIZE(default_vlan);
337 case SWITCH_CMD_LIST_PORT:
338 alist = &dev->attr_port;
339 def_list = default_port;
340 def_active = &dev->def_port;
341 n_def = ARRAY_SIZE(default_port);
348 memset(&cb, 0, sizeof(cb));
350 cb.fill = swconfig_dump_attr;
351 for (i = 0; i < alist->n_attr; i++) {
352 if (alist->attr[i].disabled)
355 err = swconfig_send_multipart(&cb, &alist->attr[i]);
361 for (i = 0; i < n_def; i++) {
362 if (!test_bit(i, def_active))
364 cb.args[0] = SWITCH_ATTR_DEFAULTS_OFFSET + i;
365 err = swconfig_send_multipart(&cb, &def_list[i]);
369 swconfig_put_dev(dev);
374 return genlmsg_unicast(cb.msg, info->snd_pid);
380 swconfig_put_dev(dev);
384 static struct switch_attr *
385 swconfig_lookup_attr(struct switch_dev *dev, struct genl_info *info,
386 struct switch_val *val)
388 struct genlmsghdr *hdr = nlmsg_data(info->nlhdr);
389 const struct switch_attrlist *alist;
390 struct switch_attr *attr = NULL;
394 struct switch_attr *def_list;
395 unsigned long *def_active;
398 if (!info->attrs[SWITCH_ATTR_OP_ID])
402 case SWITCH_CMD_SET_GLOBAL:
403 case SWITCH_CMD_GET_GLOBAL:
404 alist = &dev->attr_global;
405 def_list = default_global;
406 def_active = &dev->def_global;
407 n_def = ARRAY_SIZE(default_global);
409 case SWITCH_CMD_SET_VLAN:
410 case SWITCH_CMD_GET_VLAN:
411 alist = &dev->attr_vlan;
412 def_list = default_vlan;
413 def_active = &dev->def_vlan;
414 n_def = ARRAY_SIZE(default_vlan);
415 if (!info->attrs[SWITCH_ATTR_OP_VLAN])
417 val->port_vlan = nla_get_u32(info->attrs[SWITCH_ATTR_OP_VLAN]);
419 case SWITCH_CMD_SET_PORT:
420 case SWITCH_CMD_GET_PORT:
421 alist = &dev->attr_port;
422 def_list = default_port;
423 def_active = &dev->def_port;
424 n_def = ARRAY_SIZE(default_port);
425 if (!info->attrs[SWITCH_ATTR_OP_PORT])
427 val->port_vlan = nla_get_u32(info->attrs[SWITCH_ATTR_OP_PORT]);
437 attr_id = nla_get_u32(info->attrs[SWITCH_ATTR_OP_ID]);
438 if (attr_id >= SWITCH_ATTR_DEFAULTS_OFFSET) {
439 attr_id -= SWITCH_ATTR_DEFAULTS_OFFSET;
440 if (attr_id >= n_def)
442 if (!test_bit(attr_id, def_active))
444 attr = &def_list[attr_id];
446 if (attr_id >= alist->n_attr)
448 attr = &alist->attr[attr_id];
456 DPRINTF("attribute lookup failed\n");
462 swconfig_parse_ports(struct sk_buff *msg, struct nlattr *head,
463 struct switch_val *val, int max)
469 nla_for_each_nested(nla, head, rem) {
470 struct nlattr *tb[SWITCH_PORT_ATTR_MAX+1];
471 struct switch_port *port = &val->value.ports[val->len];
476 if (nla_parse_nested(tb, SWITCH_PORT_ATTR_MAX, nla,
480 if (!tb[SWITCH_PORT_ID])
483 port->id = nla_get_u32(tb[SWITCH_PORT_ID]);
484 if (tb[SWITCH_PORT_FLAG_TAGGED])
485 port->flags |= (1 << SWITCH_PORT_FLAG_TAGGED);
493 swconfig_set_attr(struct sk_buff *skb, struct genl_info *info)
495 struct switch_attr *attr;
496 struct switch_dev *dev;
497 struct switch_val val;
500 dev = swconfig_get_dev(info);
504 memset(&val, 0, sizeof(val));
505 attr = swconfig_lookup_attr(dev, info, &val);
506 if (!attr || !attr->set)
511 case SWITCH_TYPE_NOVAL:
513 case SWITCH_TYPE_INT:
514 if (!info->attrs[SWITCH_ATTR_OP_VALUE_INT])
517 nla_get_u32(info->attrs[SWITCH_ATTR_OP_VALUE_INT]);
519 case SWITCH_TYPE_STRING:
520 if (!info->attrs[SWITCH_ATTR_OP_VALUE_STR])
523 nla_data(info->attrs[SWITCH_ATTR_OP_VALUE_STR]);
525 case SWITCH_TYPE_PORTS:
526 val.value.ports = dev->portbuf;
527 memset(dev->portbuf, 0,
528 sizeof(struct switch_port) * dev->ports);
530 /* TODO: implement multipart? */
531 if (info->attrs[SWITCH_ATTR_OP_VALUE_PORTS]) {
532 err = swconfig_parse_ports(skb,
533 info->attrs[SWITCH_ATTR_OP_VALUE_PORTS], &val, dev->ports);
545 err = attr->set(dev, attr, &val);
547 swconfig_put_dev(dev);
552 swconfig_close_portlist(struct swconfig_callback *cb, void *arg)
555 nla_nest_end(cb->msg, cb->nest[0]);
560 swconfig_send_port(struct swconfig_callback *cb, void *arg)
562 const struct switch_port *port = arg;
563 struct nlattr *p = NULL;
566 cb->nest[0] = nla_nest_start(cb->msg, cb->cmd);
571 p = nla_nest_start(cb->msg, SWITCH_ATTR_PORT);
575 NLA_PUT_U32(cb->msg, SWITCH_PORT_ID, port->id);
576 if (port->flags & (1 << SWITCH_PORT_FLAG_TAGGED))
577 NLA_PUT_FLAG(cb->msg, SWITCH_PORT_FLAG_TAGGED);
579 nla_nest_end(cb->msg, p);
583 nla_nest_cancel(cb->msg, p);
585 nla_nest_cancel(cb->msg, cb->nest[0]);
590 swconfig_send_ports(struct sk_buff **msg, struct genl_info *info, int attr,
591 const struct switch_val *val)
593 struct swconfig_callback cb;
597 if (!val->value.ports)
600 memset(&cb, 0, sizeof(cb));
604 cb.fill = swconfig_send_port;
605 cb.close = swconfig_close_portlist;
607 cb.nest[0] = nla_nest_start(cb.msg, cb.cmd);
608 for (i = 0; i < val->len; i++) {
609 err = swconfig_send_multipart(&cb, &val->value.ports[i]);
614 swconfig_close_portlist(&cb, NULL);
622 swconfig_get_attr(struct sk_buff *skb, struct genl_info *info)
624 struct genlmsghdr *hdr = nlmsg_data(info->nlhdr);
625 struct switch_attr *attr;
626 struct switch_dev *dev;
627 struct sk_buff *msg = NULL;
628 struct switch_val val;
632 dev = swconfig_get_dev(info);
636 memset(&val, 0, sizeof(val));
637 attr = swconfig_lookup_attr(dev, info, &val);
638 if (!attr || !attr->get)
641 if (attr->type == SWITCH_TYPE_PORTS) {
642 val.value.ports = dev->portbuf;
643 memset(dev->portbuf, 0,
644 sizeof(struct switch_port) * dev->ports);
647 err = attr->get(dev, attr, &val);
651 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
655 hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, &switch_fam,
658 goto nla_put_failure;
661 case SWITCH_TYPE_INT:
662 NLA_PUT_U32(msg, SWITCH_ATTR_OP_VALUE_INT, val.value.i);
664 case SWITCH_TYPE_STRING:
665 NLA_PUT_STRING(msg, SWITCH_ATTR_OP_VALUE_STR, val.value.s);
667 case SWITCH_TYPE_PORTS:
668 err = swconfig_send_ports(&msg, info,
669 SWITCH_ATTR_OP_VALUE_PORTS, &val);
671 goto nla_put_failure;
674 DPRINTF("invalid type in attribute\n");
678 err = genlmsg_end(msg, hdr);
680 goto nla_put_failure;
682 swconfig_put_dev(dev);
683 return genlmsg_unicast(msg, info->snd_pid);
689 swconfig_put_dev(dev);
697 swconfig_send_switch(struct sk_buff *msg, u32 pid, u32 seq, int flags,
698 const struct switch_dev *dev)
702 hdr = genlmsg_put(msg, pid, seq, &switch_fam, flags,
703 SWITCH_CMD_NEW_ATTR);
707 NLA_PUT_U32(msg, SWITCH_ATTR_ID, dev->id);
708 NLA_PUT_STRING(msg, SWITCH_ATTR_NAME, dev->name);
709 NLA_PUT_STRING(msg, SWITCH_ATTR_DEV_NAME, dev->devname);
710 NLA_PUT_U32(msg, SWITCH_ATTR_VLANS, dev->vlans);
711 NLA_PUT_U32(msg, SWITCH_ATTR_PORTS, dev->ports);
713 return genlmsg_end(msg, hdr);
715 genlmsg_cancel(msg, hdr);
719 static int swconfig_dump_switches(struct sk_buff *skb,
720 struct netlink_callback *cb)
722 struct switch_dev *dev;
723 int start = cb->args[0];
727 list_for_each_entry(dev, &swdevs, dev_list) {
730 if (swconfig_send_switch(skb, NETLINK_CB(cb->skb).pid,
731 cb->nlh->nlmsg_seq, NLM_F_MULTI,
742 swconfig_done(struct netlink_callback *cb)
747 static struct genl_ops swconfig_ops[] = {
749 .cmd = SWITCH_CMD_LIST_GLOBAL,
750 .doit = swconfig_list_attrs,
751 .policy = switch_policy,
754 .cmd = SWITCH_CMD_LIST_VLAN,
755 .doit = swconfig_list_attrs,
756 .policy = switch_policy,
759 .cmd = SWITCH_CMD_LIST_PORT,
760 .doit = swconfig_list_attrs,
761 .policy = switch_policy,
764 .cmd = SWITCH_CMD_GET_GLOBAL,
765 .doit = swconfig_get_attr,
766 .policy = switch_policy,
769 .cmd = SWITCH_CMD_GET_VLAN,
770 .doit = swconfig_get_attr,
771 .policy = switch_policy,
774 .cmd = SWITCH_CMD_GET_PORT,
775 .doit = swconfig_get_attr,
776 .policy = switch_policy,
779 .cmd = SWITCH_CMD_SET_GLOBAL,
780 .doit = swconfig_set_attr,
781 .policy = switch_policy,
784 .cmd = SWITCH_CMD_SET_VLAN,
785 .doit = swconfig_set_attr,
786 .policy = switch_policy,
789 .cmd = SWITCH_CMD_SET_PORT,
790 .doit = swconfig_set_attr,
791 .policy = switch_policy,
794 .cmd = SWITCH_CMD_GET_SWITCH,
795 .dumpit = swconfig_dump_switches,
796 .policy = switch_policy,
797 .done = swconfig_done,
802 register_switch(struct switch_dev *dev, struct net_device *netdev)
804 INIT_LIST_HEAD(&dev->dev_list);
806 dev->netdev = netdev;
808 dev->devname = netdev->name;
810 BUG_ON(!dev->devname);
812 if (dev->ports > 0) {
813 dev->portbuf = kzalloc(sizeof(struct switch_port) * dev->ports,
818 dev->id = ++swdev_id;
819 swconfig_defaults_init(dev);
820 spin_lock_init(&dev->lock);
822 list_add(&dev->dev_list, &swdevs);
827 EXPORT_SYMBOL_GPL(register_switch);
830 unregister_switch(struct switch_dev *dev)
833 spin_lock(&dev->lock);
835 list_del(&dev->dev_list);
838 EXPORT_SYMBOL_GPL(unregister_switch);
846 INIT_LIST_HEAD(&swdevs);
847 err = genl_register_family(&switch_fam);
851 for (i = 0; i < ARRAY_SIZE(swconfig_ops); i++) {
852 err = genl_register_ops(&switch_fam, &swconfig_ops[i]);
860 genl_unregister_family(&switch_fam);
867 genl_unregister_family(&switch_fam);
870 module_init(swconfig_init);
871 module_exit(swconfig_exit);