1 diff -Nur linux-2.6.30.orig/drivers/net/phy/Kconfig linux-2.6.30/drivers/net/phy/Kconfig
2 --- linux-2.6.30.orig/drivers/net/phy/Kconfig 2009-06-10 05:05:27.000000000 +0200
3 +++ linux-2.6.30/drivers/net/phy/Kconfig 2009-06-11 09:22:50.000000000 +0200
9 + tristate "Switch configuration API"
11 + Switch configuration API using netlink. This allows
12 + you to configure the VLAN features of certain switches.
14 comment "MII PHY device drivers"
17 diff -Nur linux-2.6.30.orig/drivers/net/phy/Makefile linux-2.6.30/drivers/net/phy/Makefile
18 --- linux-2.6.30.orig/drivers/net/phy/Makefile 2009-06-10 05:05:27.000000000 +0200
19 +++ linux-2.6.30/drivers/net/phy/Makefile 2009-06-11 09:22:50.000000000 +0200
21 libphy-objs := phy.o phy_device.o mdio_bus.o
23 obj-$(CONFIG_PHYLIB) += libphy.o
24 +obj-$(CONFIG_SWCONFIG) += swconfig.o
25 obj-$(CONFIG_MARVELL_PHY) += marvell.o
26 obj-$(CONFIG_DAVICOM_PHY) += davicom.o
27 obj-$(CONFIG_CICADA_PHY) += cicada.o
28 diff -Nur linux-2.6.30.orig/drivers/net/phy/swconfig.c linux-2.6.30/drivers/net/phy/swconfig.c
29 --- linux-2.6.30.orig/drivers/net/phy/swconfig.c 1970-01-01 01:00:00.000000000 +0100
30 +++ linux-2.6.30/drivers/net/phy/swconfig.c 2009-06-11 09:22:50.000000000 +0200
33 + * swconfig.c: Switch configuration API
35 + * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
37 + * This program is free software; you can redistribute it and/or
38 + * modify it under the terms of the GNU General Public License
39 + * as published by the Free Software Foundation; either version 2
40 + * of the License, or (at your option) any later version.
42 + * This program is distributed in the hope that it will be useful,
43 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
44 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
45 + * GNU General Public License for more details.
48 +#include <linux/types.h>
49 +#include <linux/module.h>
50 +#include <linux/init.h>
51 +#include <linux/list.h>
52 +#include <linux/if.h>
53 +#include <linux/if_ether.h>
54 +#include <linux/capability.h>
55 +#include <linux/skbuff.h>
56 +#include <linux/switch.h>
60 +#define DPRINTF(format, ...) printk("%s: " format, __func__, ##__VA_ARGS__)
62 +#define DPRINTF(...) do {} while(0)
65 +MODULE_AUTHOR("Felix Fietkau <nbd@openwrt.org>");
66 +MODULE_LICENSE("GPL");
68 +static int swdev_id = 0;
69 +static struct list_head swdevs;
70 +static spinlock_t swdevs_lock = SPIN_LOCK_UNLOCKED;
71 +struct swconfig_callback;
73 +struct swconfig_callback
75 + struct sk_buff *msg;
76 + struct genlmsghdr *hdr;
77 + struct genl_info *info;
80 + /* callback for filling in the message data */
81 + int (*fill)(struct swconfig_callback *cb, void *arg);
83 + /* callback for closing the message before sending it */
84 + int (*close)(struct swconfig_callback *cb, void *arg);
86 + struct nlattr *nest[4];
93 +swconfig_get_vlan_ports(struct switch_dev *dev, struct switch_attr *attr, struct switch_val *val)
96 + if (val->port_vlan >= dev->vlans)
99 + if (!dev->get_vlan_ports)
100 + return -EOPNOTSUPP;
102 + ret = dev->get_vlan_ports(dev, val);
103 + printk("SET PORTS %d\n", val->len);
108 +swconfig_set_vlan_ports(struct switch_dev *dev, struct switch_attr *attr, struct switch_val *val)
112 + if (val->port_vlan >= dev->vlans)
115 + /* validate ports */
116 + if (val->len > dev->ports)
119 + for (i = 0; i < val->len; i++) {
120 + if (val->value.ports[i].id >= dev->ports)
124 + if (!dev->set_vlan_ports)
125 + return -EOPNOTSUPP;
127 + printk("SET PORTS %d\n", val->len);
128 + return dev->set_vlan_ports(dev, val);
132 +swconfig_apply_config(struct switch_dev *dev, struct switch_attr *attr, struct switch_val *val)
134 + /* don't complain if not supported by the switch driver */
135 + if (!dev->apply_config)
138 + return dev->apply_config(dev);
142 +enum global_defaults {
146 +enum vlan_defaults {
150 +enum port_defaults {
154 +static struct switch_attr default_global[] = {
156 + .type = SWITCH_TYPE_NOVAL,
158 + .description = "Activate changes in the hardware",
159 + .set = swconfig_apply_config,
163 +static struct switch_attr default_port[] = {
165 + .type = SWITCH_TYPE_INT,
167 + .description = "Current link speed",
171 +static struct switch_attr default_vlan[] = {
173 + .type = SWITCH_TYPE_PORTS,
175 + .description = "VLAN port mapping",
176 + .set = swconfig_set_vlan_ports,
177 + .get = swconfig_get_vlan_ports,
182 +static void swconfig_defaults_init(struct switch_dev *dev)
184 + dev->def_global = 0;
188 + if (dev->get_vlan_ports || dev->set_vlan_ports)
189 + set_bit(VLAN_PORTS, &dev->def_vlan);
191 + /* always present, can be no-op */
192 + set_bit(GLOBAL_APPLY, &dev->def_global);
196 +static struct genl_family switch_fam = {
197 + .id = GENL_ID_GENERATE,
201 + .maxattr = SWITCH_ATTR_MAX,
204 +static const struct nla_policy switch_policy[SWITCH_ATTR_MAX+1] = {
205 + [SWITCH_ATTR_ID] = { .type = NLA_U32 },
206 + [SWITCH_ATTR_OP_ID] = { .type = NLA_U32 },
207 + [SWITCH_ATTR_OP_PORT] = { .type = NLA_U32 },
208 + [SWITCH_ATTR_OP_VLAN] = { .type = NLA_U32 },
209 + [SWITCH_ATTR_OP_VALUE_INT] = { .type = NLA_U32 },
210 + [SWITCH_ATTR_OP_VALUE_STR] = { .type = NLA_NUL_STRING },
211 + [SWITCH_ATTR_OP_VALUE_PORTS] = { .type = NLA_NESTED },
212 + [SWITCH_ATTR_TYPE] = { .type = NLA_U32 },
215 +static const struct nla_policy port_policy[SWITCH_PORT_ATTR_MAX+1] = {
216 + [SWITCH_PORT_ID] = { .type = NLA_U32 },
217 + [SWITCH_PORT_FLAG_TAGGED] = { .type = NLA_FLAG },
223 + spin_lock(&swdevs_lock);
227 +swconfig_unlock(void)
229 + spin_unlock(&swdevs_lock);
232 +static struct switch_dev *
233 +swconfig_get_dev(struct genl_info *info)
235 + struct switch_dev *dev = NULL;
236 + struct switch_dev *p;
239 + if (!info->attrs[SWITCH_ATTR_ID])
242 + id = nla_get_u32(info->attrs[SWITCH_ATTR_ID]);
244 + list_for_each_entry(p, &swdevs, dev_list) {
252 + spin_lock(&dev->lock);
254 + DPRINTF("device %d not found\n", id);
261 +swconfig_put_dev(struct switch_dev *dev)
263 + spin_unlock(&dev->lock);
267 +swconfig_dump_attr(struct swconfig_callback *cb, void *arg)
269 + struct switch_attr *op = arg;
270 + struct genl_info *info = cb->info;
271 + struct sk_buff *msg = cb->msg;
272 + int id = cb->args[0];
275 + hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, &switch_fam,
276 + NLM_F_MULTI, SWITCH_CMD_NEW_ATTR);
280 + NLA_PUT_U32(msg, SWITCH_ATTR_OP_ID, id);
281 + NLA_PUT_U32(msg, SWITCH_ATTR_OP_TYPE, op->type);
282 + NLA_PUT_STRING(msg, SWITCH_ATTR_OP_NAME, op->name);
283 + if (op->description)
284 + NLA_PUT_STRING(msg, SWITCH_ATTR_OP_DESCRIPTION,
287 + return genlmsg_end(msg, hdr);
289 + genlmsg_cancel(msg, hdr);
293 +/* spread multipart messages across multiple message buffers */
295 +swconfig_send_multipart(struct swconfig_callback *cb, void *arg)
297 + struct genl_info *info = cb->info;
303 + cb->msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
304 + if (cb->msg == NULL)
308 + if (!(cb->fill(cb, arg) < 0))
311 + /* fill failed, check if this was already the second attempt */
315 + /* try again in a new message, send the current one */
318 + if (cb->close(cb, arg) < 0)
321 + err = genlmsg_unicast(cb->msg, info->snd_pid);
332 + nlmsg_free(cb->msg);
337 +swconfig_list_attrs(struct sk_buff *skb, struct genl_info *info)
339 + struct genlmsghdr *hdr = nlmsg_data(info->nlhdr);
340 + const struct switch_attrlist *alist;
341 + struct switch_dev *dev;
342 + struct swconfig_callback cb;
347 + struct switch_attr *def_list;
348 + unsigned long *def_active;
351 + dev = swconfig_get_dev(info);
356 + case SWITCH_CMD_LIST_GLOBAL:
357 + alist = &dev->attr_global;
358 + def_list = default_global;
359 + def_active = &dev->def_global;
360 + n_def = ARRAY_SIZE(default_global);
362 + case SWITCH_CMD_LIST_VLAN:
363 + alist = &dev->attr_vlan;
364 + def_list = default_vlan;
365 + def_active = &dev->def_vlan;
366 + n_def = ARRAY_SIZE(default_vlan);
368 + case SWITCH_CMD_LIST_PORT:
369 + alist = &dev->attr_port;
370 + def_list = default_port;
371 + def_active = &dev->def_port;
372 + n_def = ARRAY_SIZE(default_port);
379 + memset(&cb, 0, sizeof(cb));
381 + cb.fill = swconfig_dump_attr;
382 + for (i = 0; i < alist->n_attr; i++) {
383 + if (alist->attr[i].disabled)
386 + err = swconfig_send_multipart(&cb, &alist->attr[i]);
392 + for (i = 0; i < n_def; i++) {
393 + if (!test_bit(i, def_active))
395 + cb.args[0] = SWITCH_ATTR_DEFAULTS_OFFSET + i;
396 + err = swconfig_send_multipart(&cb, &def_list[i]);
400 + swconfig_put_dev(dev);
405 + return genlmsg_unicast(cb.msg, info->snd_pid);
409 + nlmsg_free(cb.msg);
411 + swconfig_put_dev(dev);
415 +static struct switch_attr *
416 +swconfig_lookup_attr(struct switch_dev *dev, struct genl_info *info,
417 + struct switch_val *val)
419 + struct genlmsghdr *hdr = nlmsg_data(info->nlhdr);
420 + const struct switch_attrlist *alist;
421 + struct switch_attr *attr = NULL;
425 + struct switch_attr *def_list;
426 + unsigned long *def_active;
429 + if (!info->attrs[SWITCH_ATTR_OP_ID])
433 + case SWITCH_CMD_SET_GLOBAL:
434 + case SWITCH_CMD_GET_GLOBAL:
435 + alist = &dev->attr_global;
436 + def_list = default_global;
437 + def_active = &dev->def_global;
438 + n_def = ARRAY_SIZE(default_global);
440 + case SWITCH_CMD_SET_VLAN:
441 + case SWITCH_CMD_GET_VLAN:
442 + alist = &dev->attr_vlan;
443 + def_list = default_vlan;
444 + def_active = &dev->def_vlan;
445 + n_def = ARRAY_SIZE(default_vlan);
446 + if (!info->attrs[SWITCH_ATTR_OP_VLAN])
448 + val->port_vlan = nla_get_u32(info->attrs[SWITCH_ATTR_OP_VLAN]);
450 + case SWITCH_CMD_SET_PORT:
451 + case SWITCH_CMD_GET_PORT:
452 + alist = &dev->attr_port;
453 + def_list = default_port;
454 + def_active = &dev->def_port;
455 + n_def = ARRAY_SIZE(default_port);
456 + if (!info->attrs[SWITCH_ATTR_OP_PORT])
458 + val->port_vlan = nla_get_u32(info->attrs[SWITCH_ATTR_OP_PORT]);
468 + attr_id = nla_get_u32(info->attrs[SWITCH_ATTR_OP_ID]);
469 + if (attr_id >= SWITCH_ATTR_DEFAULTS_OFFSET) {
470 + attr_id -= SWITCH_ATTR_DEFAULTS_OFFSET;
471 + if (attr_id >= n_def)
473 + if (!test_bit(attr_id, def_active))
475 + attr = &def_list[attr_id];
477 + if (attr_id >= alist->n_attr)
479 + attr = &alist->attr[attr_id];
482 + if (attr->disabled)
487 + DPRINTF("attribute lookup failed\n");
493 +swconfig_parse_ports(struct sk_buff *msg, struct nlattr *head,
494 + struct switch_val *val, int max)
496 + struct nlattr *nla;
500 + nla_for_each_nested(nla, head, rem) {
501 + struct nlattr *tb[SWITCH_PORT_ATTR_MAX+1];
502 + struct switch_port *port = &val->value.ports[val->len];
504 + if (val->len >= max)
507 + if (nla_parse_nested(tb, SWITCH_PORT_ATTR_MAX, nla,
511 + if (!tb[SWITCH_PORT_ID])
514 + port->id = nla_get_u32(tb[SWITCH_PORT_ID]);
515 + if (tb[SWITCH_PORT_FLAG_TAGGED])
516 + port->flags |= (1 << SWITCH_PORT_FLAG_TAGGED);
524 +swconfig_set_attr(struct sk_buff *skb, struct genl_info *info)
526 + struct switch_attr *attr;
527 + struct switch_dev *dev;
528 + struct switch_val val;
531 + dev = swconfig_get_dev(info);
535 + memset(&val, 0, sizeof(val));
536 + attr = swconfig_lookup_attr(dev, info, &val);
537 + if (!attr || !attr->set)
541 + switch(attr->type) {
542 + case SWITCH_TYPE_NOVAL:
544 + case SWITCH_TYPE_INT:
545 + if (!info->attrs[SWITCH_ATTR_OP_VALUE_INT])
548 + nla_get_u32(info->attrs[SWITCH_ATTR_OP_VALUE_INT]);
550 + case SWITCH_TYPE_STRING:
551 + if (!info->attrs[SWITCH_ATTR_OP_VALUE_STR])
554 + nla_data(info->attrs[SWITCH_ATTR_OP_VALUE_STR]);
556 + case SWITCH_TYPE_PORTS:
557 + val.value.ports = dev->portbuf;
558 + memset(dev->portbuf, 0,
559 + sizeof(struct switch_port) * dev->ports);
561 + /* TODO: implement multipart? */
562 + if (info->attrs[SWITCH_ATTR_OP_VALUE_PORTS]) {
563 + err = swconfig_parse_ports(skb,
564 + info->attrs[SWITCH_ATTR_OP_VALUE_PORTS], &val, dev->ports);
576 + err = attr->set(dev, attr, &val);
578 + swconfig_put_dev(dev);
583 +swconfig_close_portlist(struct swconfig_callback *cb, void *arg)
586 + nla_nest_end(cb->msg, cb->nest[0]);
591 +swconfig_send_port(struct swconfig_callback *cb, void *arg)
593 + const struct switch_port *port = arg;
594 + struct nlattr *p = NULL;
596 + if (!cb->nest[0]) {
597 + cb->nest[0] = nla_nest_start(cb->msg, cb->cmd);
602 + p = nla_nest_start(cb->msg, SWITCH_ATTR_PORT);
606 + NLA_PUT_U32(cb->msg, SWITCH_PORT_ID, port->id);
607 + if (port->flags & (1 << SWITCH_PORT_FLAG_TAGGED))
608 + NLA_PUT_FLAG(cb->msg, SWITCH_PORT_FLAG_TAGGED);
610 + nla_nest_end(cb->msg, p);
614 + nla_nest_cancel(cb->msg, p);
616 + nla_nest_cancel(cb->msg, cb->nest[0]);
621 +swconfig_send_ports(struct sk_buff **msg, struct genl_info *info, int attr,
622 + const struct switch_val *val)
624 + struct swconfig_callback cb;
628 + if (!val->value.ports)
631 + memset(&cb, 0, sizeof(cb));
635 + cb.fill = swconfig_send_port;
636 + cb.close = swconfig_close_portlist;
638 + cb.nest[0] = nla_nest_start(cb.msg, cb.cmd);
639 + for (i = 0; i < val->len; i++) {
640 + err = swconfig_send_multipart(&cb, &val->value.ports[i]);
645 + swconfig_close_portlist(&cb, NULL);
653 +swconfig_get_attr(struct sk_buff *skb, struct genl_info *info)
655 + struct genlmsghdr *hdr = nlmsg_data(info->nlhdr);
656 + struct switch_attr *attr;
657 + struct switch_dev *dev;
658 + struct sk_buff *msg = NULL;
659 + struct switch_val val;
661 + int cmd = hdr->cmd;
663 + dev = swconfig_get_dev(info);
667 + memset(&val, 0, sizeof(val));
668 + attr = swconfig_lookup_attr(dev, info, &val);
669 + if (!attr || !attr->get)
672 + if (attr->type == SWITCH_TYPE_PORTS) {
673 + val.value.ports = dev->portbuf;
674 + memset(dev->portbuf, 0,
675 + sizeof(struct switch_port) * dev->ports);
678 + err = attr->get(dev, attr, &val);
682 + msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
686 + hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, &switch_fam,
689 + goto nla_put_failure;
691 + switch(attr->type) {
692 + case SWITCH_TYPE_INT:
693 + NLA_PUT_U32(msg, SWITCH_ATTR_OP_VALUE_INT, val.value.i);
695 + case SWITCH_TYPE_STRING:
696 + NLA_PUT_STRING(msg, SWITCH_ATTR_OP_VALUE_STR, val.value.s);
698 + case SWITCH_TYPE_PORTS:
699 + err = swconfig_send_ports(&msg, info,
700 + SWITCH_ATTR_OP_VALUE_PORTS, &val);
702 + goto nla_put_failure;
705 + DPRINTF("invalid type in attribute\n");
709 + err = genlmsg_end(msg, hdr);
711 + goto nla_put_failure;
713 + swconfig_put_dev(dev);
714 + return genlmsg_unicast(msg, info->snd_pid);
720 + swconfig_put_dev(dev);
728 +swconfig_send_switch(struct sk_buff *msg, u32 pid, u32 seq, int flags,
729 + const struct switch_dev *dev)
733 + hdr = genlmsg_put(msg, pid, seq, &switch_fam, flags,
734 + SWITCH_CMD_NEW_ATTR);
738 + NLA_PUT_U32(msg, SWITCH_ATTR_ID, dev->id);
739 + NLA_PUT_STRING(msg, SWITCH_ATTR_NAME, dev->name);
740 + NLA_PUT_STRING(msg, SWITCH_ATTR_DEV_NAME, dev->devname);
741 + NLA_PUT_U32(msg, SWITCH_ATTR_VLANS, dev->vlans);
742 + NLA_PUT_U32(msg, SWITCH_ATTR_PORTS, dev->ports);
744 + return genlmsg_end(msg, hdr);
746 + genlmsg_cancel(msg, hdr);
750 +static int swconfig_dump_switches(struct sk_buff *skb,
751 + struct netlink_callback *cb)
753 + struct switch_dev *dev;
754 + int start = cb->args[0];
758 + list_for_each_entry(dev, &swdevs, dev_list) {
759 + if (++idx <= start)
761 + if (swconfig_send_switch(skb, NETLINK_CB(cb->skb).pid,
762 + cb->nlh->nlmsg_seq, NLM_F_MULTI,
773 +swconfig_done(struct netlink_callback *cb)
778 +static struct genl_ops swconfig_ops[] = {
780 + .cmd = SWITCH_CMD_LIST_GLOBAL,
781 + .doit = swconfig_list_attrs,
782 + .policy = switch_policy,
785 + .cmd = SWITCH_CMD_LIST_VLAN,
786 + .doit = swconfig_list_attrs,
787 + .policy = switch_policy,
790 + .cmd = SWITCH_CMD_LIST_PORT,
791 + .doit = swconfig_list_attrs,
792 + .policy = switch_policy,
795 + .cmd = SWITCH_CMD_GET_GLOBAL,
796 + .doit = swconfig_get_attr,
797 + .policy = switch_policy,
800 + .cmd = SWITCH_CMD_GET_VLAN,
801 + .doit = swconfig_get_attr,
802 + .policy = switch_policy,
805 + .cmd = SWITCH_CMD_GET_PORT,
806 + .doit = swconfig_get_attr,
807 + .policy = switch_policy,
810 + .cmd = SWITCH_CMD_SET_GLOBAL,
811 + .doit = swconfig_set_attr,
812 + .policy = switch_policy,
815 + .cmd = SWITCH_CMD_SET_VLAN,
816 + .doit = swconfig_set_attr,
817 + .policy = switch_policy,
820 + .cmd = SWITCH_CMD_SET_PORT,
821 + .doit = swconfig_set_attr,
822 + .policy = switch_policy,
825 + .cmd = SWITCH_CMD_GET_SWITCH,
826 + .dumpit = swconfig_dump_switches,
827 + .policy = switch_policy,
828 + .done = swconfig_done,
833 +register_switch(struct switch_dev *dev, struct net_device *netdev)
835 + INIT_LIST_HEAD(&dev->dev_list);
837 + dev->netdev = netdev;
839 + dev->devname = netdev->name;
841 + BUG_ON(!dev->devname);
843 + if (dev->ports > 0) {
844 + dev->portbuf = kzalloc(sizeof(struct switch_port) * dev->ports,
849 + dev->id = ++swdev_id;
850 + swconfig_defaults_init(dev);
851 + spin_lock_init(&dev->lock);
853 + list_add(&dev->dev_list, &swdevs);
858 +EXPORT_SYMBOL_GPL(register_switch);
861 +unregister_switch(struct switch_dev *dev)
863 + kfree(dev->portbuf);
864 + spin_lock(&dev->lock);
866 + list_del(&dev->dev_list);
869 +EXPORT_SYMBOL_GPL(unregister_switch);
877 + INIT_LIST_HEAD(&swdevs);
878 + err = genl_register_family(&switch_fam);
882 + for (i = 0; i < ARRAY_SIZE(swconfig_ops); i++) {
883 + err = genl_register_ops(&switch_fam, &swconfig_ops[i]);
891 + genl_unregister_family(&switch_fam);
898 + genl_unregister_family(&switch_fam);
901 +module_init(swconfig_init);
902 +module_exit(swconfig_exit);
904 diff -Nur linux-2.6.30.orig/include/linux/switch.h linux-2.6.30/include/linux/switch.h
905 --- linux-2.6.30.orig/include/linux/switch.h 1970-01-01 01:00:00.000000000 +0100
906 +++ linux-2.6.30/include/linux/switch.h 2009-06-11 09:22:50.000000000 +0200
909 + * switch.h: Switch configuration API
911 + * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
913 + * This program is free software; you can redistribute it and/or
914 + * modify it under the terms of the GNU General Public License
915 + * as published by the Free Software Foundation; either version 2
916 + * of the License, or (at your option) any later version.
918 + * This program is distributed in the hope that it will be useful,
919 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
920 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
921 + * GNU General Public License for more details.
924 +#ifndef __LINUX_SWITCH_H
925 +#define __LINUX_SWITCH_H
927 +#include <linux/types.h>
928 +#include <linux/netdevice.h>
929 +#include <linux/netlink.h>
930 +#include <linux/genetlink.h>
932 +#include <netlink/netlink.h>
933 +#include <netlink/genl/genl.h>
934 +#include <netlink/genl/ctrl.h>
936 +#include <net/genetlink.h>
939 +/* main attributes */
941 + SWITCH_ATTR_UNSPEC,
947 + SWITCH_ATTR_DEV_NAME,
952 + SWITCH_ATTR_OP_TYPE,
953 + SWITCH_ATTR_OP_NAME,
954 + SWITCH_ATTR_OP_PORT,
955 + SWITCH_ATTR_OP_VLAN,
956 + SWITCH_ATTR_OP_VALUE_INT,
957 + SWITCH_ATTR_OP_VALUE_STR,
958 + SWITCH_ATTR_OP_VALUE_PORTS,
959 + SWITCH_ATTR_OP_DESCRIPTION,
968 + SWITCH_CMD_GET_SWITCH,
969 + SWITCH_CMD_NEW_ATTR,
970 + SWITCH_CMD_LIST_GLOBAL,
971 + SWITCH_CMD_GET_GLOBAL,
972 + SWITCH_CMD_SET_GLOBAL,
973 + SWITCH_CMD_LIST_PORT,
974 + SWITCH_CMD_GET_PORT,
975 + SWITCH_CMD_SET_PORT,
976 + SWITCH_CMD_LIST_VLAN,
977 + SWITCH_CMD_GET_VLAN,
978 + SWITCH_CMD_SET_VLAN
982 +enum switch_val_type {
983 + SWITCH_TYPE_UNSPEC,
985 + SWITCH_TYPE_STRING,
990 +/* port nested attributes */
992 + SWITCH_PORT_UNSPEC,
994 + SWITCH_PORT_FLAG_TAGGED,
995 + SWITCH_PORT_ATTR_MAX
998 +#define SWITCH_ATTR_DEFAULTS_OFFSET 0x1000
1005 +struct switch_attr;
1006 +struct switch_attrlist;
1008 +int register_switch(struct switch_dev *dev, struct net_device *netdev);
1009 +void unregister_switch(struct switch_dev *dev);
1011 +struct switch_attrlist {
1012 + /* filled in by the driver */
1014 + struct switch_attr *attr;
1018 +struct switch_dev {
1023 + /* NB: either devname or netdev must be set */
1024 + const char *devname;
1025 + struct net_device *netdev;
1030 + struct switch_attrlist attr_global, attr_port, attr_vlan;
1033 + struct switch_port *portbuf;
1034 + struct list_head dev_list;
1035 + unsigned long def_global, def_port, def_vlan;
1037 + int (*get_vlan_ports)(struct switch_dev *dev, struct switch_val *val);
1038 + int (*set_vlan_ports)(struct switch_dev *dev, struct switch_val *val);
1039 + int (*apply_config)(struct switch_dev *dev);
1042 +struct switch_port {
1047 +struct switch_val {
1048 + struct switch_attr *attr;
1054 + struct switch_port *ports;
1058 +struct switch_attr {
1062 + const char *description;
1064 + int (*set)(struct switch_dev *dev, struct switch_attr *attr, struct switch_val *val);
1065 + int (*get)(struct switch_dev *dev, struct switch_attr *attr, struct switch_val *val);
1067 + /* for driver internal use */