Root/target/linux/generic/files/drivers/net/phy/swconfig.c

1/*
2 * swconfig.c: Switch configuration API
3 *
4 * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
5 *
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.
10 *
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.
15 */
16
17#include <linux/types.h>
18#include <linux/module.h>
19#include <linux/init.h>
20#include <linux/list.h>
21#include <linux/if.h>
22#include <linux/if_ether.h>
23#include <linux/capability.h>
24#include <linux/skbuff.h>
25#include <linux/switch.h>
26
27//#define DEBUG 1
28#ifdef DEBUG
29#define DPRINTF(format, ...) printk("%s: " format, __func__, ##__VA_ARGS__)
30#else
31#define DPRINTF(...) do {} while(0)
32#endif
33
34#define SWCONFIG_DEVNAME "switch%d"
35
36#include "swconfig_leds.c"
37
38MODULE_AUTHOR("Felix Fietkau <nbd@openwrt.org>");
39MODULE_LICENSE("GPL");
40
41static int swdev_id = 0;
42static struct list_head swdevs;
43static DEFINE_SPINLOCK(swdevs_lock);
44struct swconfig_callback;
45
46struct swconfig_callback
47{
48    struct sk_buff *msg;
49    struct genlmsghdr *hdr;
50    struct genl_info *info;
51    int cmd;
52
53    /* callback for filling in the message data */
54    int (*fill)(struct swconfig_callback *cb, void *arg);
55
56    /* callback for closing the message before sending it */
57    int (*close)(struct swconfig_callback *cb, void *arg);
58
59    struct nlattr *nest[4];
60    int args[4];
61};
62
63/* defaults */
64
65static int
66swconfig_get_vlan_ports(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val)
67{
68    int ret;
69    if (val->port_vlan >= dev->vlans)
70        return -EINVAL;
71
72    if (!dev->ops->get_vlan_ports)
73        return -EOPNOTSUPP;
74
75    ret = dev->ops->get_vlan_ports(dev, val);
76    return ret;
77}
78
79static int
80swconfig_set_vlan_ports(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val)
81{
82    struct switch_port *ports = val->value.ports;
83    const struct switch_dev_ops *ops = dev->ops;
84    int i;
85
86    if (val->port_vlan >= dev->vlans)
87        return -EINVAL;
88
89    /* validate ports */
90    if (val->len > dev->ports)
91        return -EINVAL;
92
93    if (!ops->set_vlan_ports)
94        return -EOPNOTSUPP;
95
96    for (i = 0; i < val->len; i++) {
97        if (ports[i].id >= dev->ports)
98            return -EINVAL;
99
100        if (ops->set_port_pvid &&
101            !(ports[i].flags & (1 << SWITCH_PORT_FLAG_TAGGED)))
102            ops->set_port_pvid(dev, ports[i].id, val->port_vlan);
103    }
104
105    return ops->set_vlan_ports(dev, val);
106}
107
108static int
109swconfig_set_pvid(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val)
110{
111    if (val->port_vlan >= dev->ports)
112        return -EINVAL;
113
114    if (!dev->ops->set_port_pvid)
115        return -EOPNOTSUPP;
116
117    return dev->ops->set_port_pvid(dev, val->port_vlan, val->value.i);
118}
119
120static int
121swconfig_get_pvid(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val)
122{
123    if (val->port_vlan >= dev->ports)
124        return -EINVAL;
125
126    if (!dev->ops->get_port_pvid)
127        return -EOPNOTSUPP;
128
129    return dev->ops->get_port_pvid(dev, val->port_vlan, &val->value.i);
130}
131
132static int
133swconfig_apply_config(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val)
134{
135    /* don't complain if not supported by the switch driver */
136    if (!dev->ops->apply_config)
137        return 0;
138
139    return dev->ops->apply_config(dev);
140}
141
142static int
143swconfig_reset_switch(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val)
144{
145    /* don't complain if not supported by the switch driver */
146    if (!dev->ops->reset_switch)
147        return 0;
148
149    return dev->ops->reset_switch(dev);
150}
151
152enum global_defaults {
153    GLOBAL_APPLY,
154    GLOBAL_RESET,
155};
156
157enum vlan_defaults {
158    VLAN_PORTS,
159};
160
161enum port_defaults {
162    PORT_PVID,
163};
164
165static struct switch_attr default_global[] = {
166    [GLOBAL_APPLY] = {
167        .type = SWITCH_TYPE_NOVAL,
168        .name = "apply",
169        .description = "Activate changes in the hardware",
170        .set = swconfig_apply_config,
171    },
172    [GLOBAL_RESET] = {
173        .type = SWITCH_TYPE_NOVAL,
174        .name = "reset",
175        .description = "Reset the switch",
176        .set = swconfig_reset_switch,
177    }
178};
179
180static struct switch_attr default_port[] = {
181    [PORT_PVID] = {
182        .type = SWITCH_TYPE_INT,
183        .name = "pvid",
184        .description = "Primary VLAN ID",
185        .set = swconfig_set_pvid,
186        .get = swconfig_get_pvid,
187    }
188};
189
190static struct switch_attr default_vlan[] = {
191    [VLAN_PORTS] = {
192        .type = SWITCH_TYPE_PORTS,
193        .name = "ports",
194        .description = "VLAN port mapping",
195        .set = swconfig_set_vlan_ports,
196        .get = swconfig_get_vlan_ports,
197    },
198};
199
200
201static void swconfig_defaults_init(struct switch_dev *dev)
202{
203    const struct switch_dev_ops *ops = dev->ops;
204
205    dev->def_global = 0;
206    dev->def_vlan = 0;
207    dev->def_port = 0;
208
209    if (ops->get_vlan_ports || ops->set_vlan_ports)
210        set_bit(VLAN_PORTS, &dev->def_vlan);
211
212    if (ops->get_port_pvid || ops->set_port_pvid)
213        set_bit(PORT_PVID, &dev->def_port);
214
215    /* always present, can be no-op */
216    set_bit(GLOBAL_APPLY, &dev->def_global);
217    set_bit(GLOBAL_RESET, &dev->def_global);
218}
219
220
221static struct genl_family switch_fam = {
222    .id = GENL_ID_GENERATE,
223    .name = "switch",
224    .hdrsize = 0,
225    .version = 1,
226    .maxattr = SWITCH_ATTR_MAX,
227};
228
229static const struct nla_policy switch_policy[SWITCH_ATTR_MAX+1] = {
230    [SWITCH_ATTR_ID] = { .type = NLA_U32 },
231    [SWITCH_ATTR_OP_ID] = { .type = NLA_U32 },
232    [SWITCH_ATTR_OP_PORT] = { .type = NLA_U32 },
233    [SWITCH_ATTR_OP_VLAN] = { .type = NLA_U32 },
234    [SWITCH_ATTR_OP_VALUE_INT] = { .type = NLA_U32 },
235    [SWITCH_ATTR_OP_VALUE_STR] = { .type = NLA_NUL_STRING },
236    [SWITCH_ATTR_OP_VALUE_PORTS] = { .type = NLA_NESTED },
237    [SWITCH_ATTR_TYPE] = { .type = NLA_U32 },
238};
239
240static const struct nla_policy port_policy[SWITCH_PORT_ATTR_MAX+1] = {
241    [SWITCH_PORT_ID] = { .type = NLA_U32 },
242    [SWITCH_PORT_FLAG_TAGGED] = { .type = NLA_FLAG },
243};
244
245static inline void
246swconfig_lock(void)
247{
248    spin_lock(&swdevs_lock);
249}
250
251static inline void
252swconfig_unlock(void)
253{
254    spin_unlock(&swdevs_lock);
255}
256
257static struct switch_dev *
258swconfig_get_dev(struct genl_info *info)
259{
260    struct switch_dev *dev = NULL;
261    struct switch_dev *p;
262    int id;
263
264    if (!info->attrs[SWITCH_ATTR_ID])
265        goto done;
266
267    id = nla_get_u32(info->attrs[SWITCH_ATTR_ID]);
268    swconfig_lock();
269    list_for_each_entry(p, &swdevs, dev_list) {
270        if (id != p->id)
271            continue;
272
273        dev = p;
274        break;
275    }
276    if (dev)
277        spin_lock(&dev->lock);
278    else
279        DPRINTF("device %d not found\n", id);
280    swconfig_unlock();
281done:
282    return dev;
283}
284
285static inline void
286swconfig_put_dev(struct switch_dev *dev)
287{
288    spin_unlock(&dev->lock);
289}
290
291static int
292swconfig_dump_attr(struct swconfig_callback *cb, void *arg)
293{
294    struct switch_attr *op = arg;
295    struct genl_info *info = cb->info;
296    struct sk_buff *msg = cb->msg;
297    int id = cb->args[0];
298    void *hdr;
299
300    hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, &switch_fam,
301            NLM_F_MULTI, SWITCH_CMD_NEW_ATTR);
302    if (IS_ERR(hdr))
303        return -1;
304
305    NLA_PUT_U32(msg, SWITCH_ATTR_OP_ID, id);
306    NLA_PUT_U32(msg, SWITCH_ATTR_OP_TYPE, op->type);
307    NLA_PUT_STRING(msg, SWITCH_ATTR_OP_NAME, op->name);
308    if (op->description)
309        NLA_PUT_STRING(msg, SWITCH_ATTR_OP_DESCRIPTION,
310            op->description);
311
312    return genlmsg_end(msg, hdr);
313nla_put_failure:
314    genlmsg_cancel(msg, hdr);
315    return -EMSGSIZE;
316}
317
318/* spread multipart messages across multiple message buffers */
319static int
320swconfig_send_multipart(struct swconfig_callback *cb, void *arg)
321{
322    struct genl_info *info = cb->info;
323    int restart = 0;
324    int err;
325
326    do {
327        if (!cb->msg) {
328            cb->msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
329            if (cb->msg == NULL)
330                goto error;
331        }
332
333        if (!(cb->fill(cb, arg) < 0))
334            break;
335
336        /* fill failed, check if this was already the second attempt */
337        if (restart)
338            goto error;
339
340        /* try again in a new message, send the current one */
341        restart = 1;
342        if (cb->close) {
343            if (cb->close(cb, arg) < 0)
344                goto error;
345        }
346        err = genlmsg_reply(cb->msg, info);
347        cb->msg = NULL;
348        if (err < 0)
349            goto error;
350
351    } while (restart);
352
353    return 0;
354
355error:
356    if (cb->msg)
357        nlmsg_free(cb->msg);
358    return -1;
359}
360
361static int
362swconfig_list_attrs(struct sk_buff *skb, struct genl_info *info)
363{
364    struct genlmsghdr *hdr = nlmsg_data(info->nlhdr);
365    const struct switch_attrlist *alist;
366    struct switch_dev *dev;
367    struct swconfig_callback cb;
368    int err = -EINVAL;
369    int i;
370
371    /* defaults */
372    struct switch_attr *def_list;
373    unsigned long *def_active;
374    int n_def;
375
376    dev = swconfig_get_dev(info);
377    if (!dev)
378        return -EINVAL;
379
380    switch(hdr->cmd) {
381    case SWITCH_CMD_LIST_GLOBAL:
382        alist = &dev->ops->attr_global;
383        def_list = default_global;
384        def_active = &dev->def_global;
385        n_def = ARRAY_SIZE(default_global);
386        break;
387    case SWITCH_CMD_LIST_VLAN:
388        alist = &dev->ops->attr_vlan;
389        def_list = default_vlan;
390        def_active = &dev->def_vlan;
391        n_def = ARRAY_SIZE(default_vlan);
392        break;
393    case SWITCH_CMD_LIST_PORT:
394        alist = &dev->ops->attr_port;
395        def_list = default_port;
396        def_active = &dev->def_port;
397        n_def = ARRAY_SIZE(default_port);
398        break;
399    default:
400        WARN_ON(1);
401        goto out;
402    }
403
404    memset(&cb, 0, sizeof(cb));
405    cb.info = info;
406    cb.fill = swconfig_dump_attr;
407    for (i = 0; i < alist->n_attr; i++) {
408        if (alist->attr[i].disabled)
409            continue;
410        cb.args[0] = i;
411        err = swconfig_send_multipart(&cb, (void *) &alist->attr[i]);
412        if (err < 0)
413            goto error;
414    }
415
416    /* defaults */
417    for (i = 0; i < n_def; i++) {
418        if (!test_bit(i, def_active))
419            continue;
420        cb.args[0] = SWITCH_ATTR_DEFAULTS_OFFSET + i;
421        err = swconfig_send_multipart(&cb, (void *) &def_list[i]);
422        if (err < 0)
423            goto error;
424    }
425    swconfig_put_dev(dev);
426
427    if (!cb.msg)
428        return 0;
429
430    return genlmsg_reply(cb.msg, info);
431
432error:
433    if (cb.msg)
434        nlmsg_free(cb.msg);
435out:
436    swconfig_put_dev(dev);
437    return err;
438}
439
440static const struct switch_attr *
441swconfig_lookup_attr(struct switch_dev *dev, struct genl_info *info,
442        struct switch_val *val)
443{
444    struct genlmsghdr *hdr = nlmsg_data(info->nlhdr);
445    const struct switch_attrlist *alist;
446    const struct switch_attr *attr = NULL;
447    int attr_id;
448
449    /* defaults */
450    struct switch_attr *def_list;
451    unsigned long *def_active;
452    int n_def;
453
454    if (!info->attrs[SWITCH_ATTR_OP_ID])
455        goto done;
456
457    switch(hdr->cmd) {
458    case SWITCH_CMD_SET_GLOBAL:
459    case SWITCH_CMD_GET_GLOBAL:
460        alist = &dev->ops->attr_global;
461        def_list = default_global;
462        def_active = &dev->def_global;
463        n_def = ARRAY_SIZE(default_global);
464        break;
465    case SWITCH_CMD_SET_VLAN:
466    case SWITCH_CMD_GET_VLAN:
467        alist = &dev->ops->attr_vlan;
468        def_list = default_vlan;
469        def_active = &dev->def_vlan;
470        n_def = ARRAY_SIZE(default_vlan);
471        if (!info->attrs[SWITCH_ATTR_OP_VLAN])
472            goto done;
473        val->port_vlan = nla_get_u32(info->attrs[SWITCH_ATTR_OP_VLAN]);
474        if (val->port_vlan >= dev->vlans)
475            goto done;
476        break;
477    case SWITCH_CMD_SET_PORT:
478    case SWITCH_CMD_GET_PORT:
479        alist = &dev->ops->attr_port;
480        def_list = default_port;
481        def_active = &dev->def_port;
482        n_def = ARRAY_SIZE(default_port);
483        if (!info->attrs[SWITCH_ATTR_OP_PORT])
484            goto done;
485        val->port_vlan = nla_get_u32(info->attrs[SWITCH_ATTR_OP_PORT]);
486        if (val->port_vlan >= dev->ports)
487            goto done;
488        break;
489    default:
490        WARN_ON(1);
491        goto done;
492    }
493
494    if (!alist)
495        goto done;
496
497    attr_id = nla_get_u32(info->attrs[SWITCH_ATTR_OP_ID]);
498    if (attr_id >= SWITCH_ATTR_DEFAULTS_OFFSET) {
499        attr_id -= SWITCH_ATTR_DEFAULTS_OFFSET;
500        if (attr_id >= n_def)
501            goto done;
502        if (!test_bit(attr_id, def_active))
503            goto done;
504        attr = &def_list[attr_id];
505    } else {
506        if (attr_id >= alist->n_attr)
507            goto done;
508        attr = &alist->attr[attr_id];
509    }
510
511    if (attr->disabled)
512        attr = NULL;
513
514done:
515    if (!attr)
516        DPRINTF("attribute lookup failed\n");
517    val->attr = attr;
518    return attr;
519}
520
521static int
522swconfig_parse_ports(struct sk_buff *msg, struct nlattr *head,
523        struct switch_val *val, int max)
524{
525    struct nlattr *nla;
526    int rem;
527
528    val->len = 0;
529    nla_for_each_nested(nla, head, rem) {
530        struct nlattr *tb[SWITCH_PORT_ATTR_MAX+1];
531        struct switch_port *port = &val->value.ports[val->len];
532
533        if (val->len >= max)
534            return -EINVAL;
535
536        if (nla_parse_nested(tb, SWITCH_PORT_ATTR_MAX, nla,
537                port_policy))
538            return -EINVAL;
539
540        if (!tb[SWITCH_PORT_ID])
541            return -EINVAL;
542
543        port->id = nla_get_u32(tb[SWITCH_PORT_ID]);
544        if (tb[SWITCH_PORT_FLAG_TAGGED])
545            port->flags |= (1 << SWITCH_PORT_FLAG_TAGGED);
546        val->len++;
547    }
548
549    return 0;
550}
551
552static int
553swconfig_set_attr(struct sk_buff *skb, struct genl_info *info)
554{
555    const struct switch_attr *attr;
556    struct switch_dev *dev;
557    struct switch_val val;
558    int err = -EINVAL;
559
560    dev = swconfig_get_dev(info);
561    if (!dev)
562        return -EINVAL;
563
564    memset(&val, 0, sizeof(val));
565    attr = swconfig_lookup_attr(dev, info, &val);
566    if (!attr || !attr->set)
567        goto error;
568
569    val.attr = attr;
570    switch(attr->type) {
571    case SWITCH_TYPE_NOVAL:
572        break;
573    case SWITCH_TYPE_INT:
574        if (!info->attrs[SWITCH_ATTR_OP_VALUE_INT])
575            goto error;
576        val.value.i =
577            nla_get_u32(info->attrs[SWITCH_ATTR_OP_VALUE_INT]);
578        break;
579    case SWITCH_TYPE_STRING:
580        if (!info->attrs[SWITCH_ATTR_OP_VALUE_STR])
581            goto error;
582        val.value.s =
583            nla_data(info->attrs[SWITCH_ATTR_OP_VALUE_STR]);
584        break;
585    case SWITCH_TYPE_PORTS:
586        val.value.ports = dev->portbuf;
587        memset(dev->portbuf, 0,
588            sizeof(struct switch_port) * dev->ports);
589
590        /* TODO: implement multipart? */
591        if (info->attrs[SWITCH_ATTR_OP_VALUE_PORTS]) {
592            err = swconfig_parse_ports(skb,
593                info->attrs[SWITCH_ATTR_OP_VALUE_PORTS], &val, dev->ports);
594            if (err < 0)
595                goto error;
596        } else {
597            val.len = 0;
598            err = 0;
599        }
600        break;
601    default:
602        goto error;
603    }
604
605    err = attr->set(dev, attr, &val);
606error:
607    swconfig_put_dev(dev);
608    return err;
609}
610
611static int
612swconfig_close_portlist(struct swconfig_callback *cb, void *arg)
613{
614    if (cb->nest[0])
615        nla_nest_end(cb->msg, cb->nest[0]);
616    return 0;
617}
618
619static int
620swconfig_send_port(struct swconfig_callback *cb, void *arg)
621{
622    const struct switch_port *port = arg;
623    struct nlattr *p = NULL;
624
625    if (!cb->nest[0]) {
626        cb->nest[0] = nla_nest_start(cb->msg, cb->cmd);
627        if (!cb->nest[0])
628            return -1;
629    }
630
631    p = nla_nest_start(cb->msg, SWITCH_ATTR_PORT);
632    if (!p)
633        goto error;
634
635    NLA_PUT_U32(cb->msg, SWITCH_PORT_ID, port->id);
636    if (port->flags & (1 << SWITCH_PORT_FLAG_TAGGED))
637        NLA_PUT_FLAG(cb->msg, SWITCH_PORT_FLAG_TAGGED);
638
639    nla_nest_end(cb->msg, p);
640    return 0;
641
642nla_put_failure:
643        nla_nest_cancel(cb->msg, p);
644error:
645    nla_nest_cancel(cb->msg, cb->nest[0]);
646    return -1;
647}
648
649static int
650swconfig_send_ports(struct sk_buff **msg, struct genl_info *info, int attr,
651        const struct switch_val *val)
652{
653    struct swconfig_callback cb;
654    int err = 0;
655    int i;
656
657    if (!val->value.ports)
658        return -EINVAL;
659
660    memset(&cb, 0, sizeof(cb));
661    cb.cmd = attr;
662    cb.msg = *msg;
663    cb.info = info;
664    cb.fill = swconfig_send_port;
665    cb.close = swconfig_close_portlist;
666
667    cb.nest[0] = nla_nest_start(cb.msg, cb.cmd);
668    for (i = 0; i < val->len; i++) {
669        err = swconfig_send_multipart(&cb, &val->value.ports[i]);
670        if (err)
671            goto done;
672    }
673    err = val->len;
674    swconfig_close_portlist(&cb, NULL);
675    *msg = cb.msg;
676
677done:
678    return err;
679}
680
681static int
682swconfig_get_attr(struct sk_buff *skb, struct genl_info *info)
683{
684    struct genlmsghdr *hdr = nlmsg_data(info->nlhdr);
685    const struct switch_attr *attr;
686    struct switch_dev *dev;
687    struct sk_buff *msg = NULL;
688    struct switch_val val;
689    int err = -EINVAL;
690    int cmd = hdr->cmd;
691
692    dev = swconfig_get_dev(info);
693    if (!dev)
694        return -EINVAL;
695
696    memset(&val, 0, sizeof(val));
697    attr = swconfig_lookup_attr(dev, info, &val);
698    if (!attr || !attr->get)
699        goto error;
700
701    if (attr->type == SWITCH_TYPE_PORTS) {
702        val.value.ports = dev->portbuf;
703        memset(dev->portbuf, 0,
704            sizeof(struct switch_port) * dev->ports);
705    }
706
707    err = attr->get(dev, attr, &val);
708    if (err)
709        goto error;
710
711    msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
712    if (!msg)
713        goto error;
714
715    hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, &switch_fam,
716            0, cmd);
717    if (IS_ERR(hdr))
718        goto nla_put_failure;
719
720    switch(attr->type) {
721    case SWITCH_TYPE_INT:
722        NLA_PUT_U32(msg, SWITCH_ATTR_OP_VALUE_INT, val.value.i);
723        break;
724    case SWITCH_TYPE_STRING:
725        NLA_PUT_STRING(msg, SWITCH_ATTR_OP_VALUE_STR, val.value.s);
726        break;
727    case SWITCH_TYPE_PORTS:
728        err = swconfig_send_ports(&msg, info,
729                SWITCH_ATTR_OP_VALUE_PORTS, &val);
730        if (err < 0)
731            goto nla_put_failure;
732        break;
733    default:
734        DPRINTF("invalid type in attribute\n");
735        err = -EINVAL;
736        goto error;
737    }
738    err = genlmsg_end(msg, hdr);
739    if (err < 0)
740        goto nla_put_failure;
741
742    swconfig_put_dev(dev);
743    return genlmsg_reply(msg, info);
744
745nla_put_failure:
746    if (msg)
747        nlmsg_free(msg);
748error:
749    swconfig_put_dev(dev);
750    if (!err)
751        err = -ENOMEM;
752    return err;
753}
754
755static int
756swconfig_send_switch(struct sk_buff *msg, u32 pid, u32 seq, int flags,
757        const struct switch_dev *dev)
758{
759    void *hdr;
760
761    hdr = genlmsg_put(msg, pid, seq, &switch_fam, flags,
762            SWITCH_CMD_NEW_ATTR);
763    if (IS_ERR(hdr))
764        return -1;
765
766    NLA_PUT_U32(msg, SWITCH_ATTR_ID, dev->id);
767    NLA_PUT_STRING(msg, SWITCH_ATTR_DEV_NAME, dev->devname);
768    NLA_PUT_STRING(msg, SWITCH_ATTR_ALIAS, dev->alias);
769    NLA_PUT_STRING(msg, SWITCH_ATTR_NAME, dev->name);
770    NLA_PUT_U32(msg, SWITCH_ATTR_VLANS, dev->vlans);
771    NLA_PUT_U32(msg, SWITCH_ATTR_PORTS, dev->ports);
772    NLA_PUT_U32(msg, SWITCH_ATTR_CPU_PORT, dev->cpu_port);
773
774    return genlmsg_end(msg, hdr);
775nla_put_failure:
776    genlmsg_cancel(msg, hdr);
777    return -EMSGSIZE;
778}
779
780static int swconfig_dump_switches(struct sk_buff *skb,
781        struct netlink_callback *cb)
782{
783    struct switch_dev *dev;
784    int start = cb->args[0];
785    int idx = 0;
786
787    swconfig_lock();
788    list_for_each_entry(dev, &swdevs, dev_list) {
789        if (++idx <= start)
790            continue;
791        if (swconfig_send_switch(skb, NETLINK_CB(cb->skb).pid,
792                cb->nlh->nlmsg_seq, NLM_F_MULTI,
793                dev) < 0)
794            break;
795    }
796    swconfig_unlock();
797    cb->args[0] = idx;
798
799    return skb->len;
800}
801
802static int
803swconfig_done(struct netlink_callback *cb)
804{
805    return 0;
806}
807
808static struct genl_ops swconfig_ops[] = {
809    {
810        .cmd = SWITCH_CMD_LIST_GLOBAL,
811        .doit = swconfig_list_attrs,
812        .policy = switch_policy,
813    },
814    {
815        .cmd = SWITCH_CMD_LIST_VLAN,
816        .doit = swconfig_list_attrs,
817        .policy = switch_policy,
818    },
819    {
820        .cmd = SWITCH_CMD_LIST_PORT,
821        .doit = swconfig_list_attrs,
822        .policy = switch_policy,
823    },
824    {
825        .cmd = SWITCH_CMD_GET_GLOBAL,
826        .doit = swconfig_get_attr,
827        .policy = switch_policy,
828    },
829    {
830        .cmd = SWITCH_CMD_GET_VLAN,
831        .doit = swconfig_get_attr,
832        .policy = switch_policy,
833    },
834    {
835        .cmd = SWITCH_CMD_GET_PORT,
836        .doit = swconfig_get_attr,
837        .policy = switch_policy,
838    },
839    {
840        .cmd = SWITCH_CMD_SET_GLOBAL,
841        .doit = swconfig_set_attr,
842        .policy = switch_policy,
843    },
844    {
845        .cmd = SWITCH_CMD_SET_VLAN,
846        .doit = swconfig_set_attr,
847        .policy = switch_policy,
848    },
849    {
850        .cmd = SWITCH_CMD_SET_PORT,
851        .doit = swconfig_set_attr,
852        .policy = switch_policy,
853    },
854    {
855        .cmd = SWITCH_CMD_GET_SWITCH,
856        .dumpit = swconfig_dump_switches,
857        .policy = switch_policy,
858        .done = swconfig_done,
859    }
860};
861
862int
863register_switch(struct switch_dev *dev, struct net_device *netdev)
864{
865    struct switch_dev *sdev;
866    const int max_switches = 8 * sizeof(unsigned long);
867    unsigned long in_use = 0;
868    int err;
869    int i;
870
871    INIT_LIST_HEAD(&dev->dev_list);
872    if (netdev) {
873        dev->netdev = netdev;
874        if (!dev->alias)
875            dev->alias = netdev->name;
876    }
877    BUG_ON(!dev->alias);
878
879    if (dev->ports > 0) {
880        dev->portbuf = kzalloc(sizeof(struct switch_port) * dev->ports,
881                GFP_KERNEL);
882        if (!dev->portbuf)
883            return -ENOMEM;
884    }
885    swconfig_defaults_init(dev);
886    spin_lock_init(&dev->lock);
887    swconfig_lock();
888    dev->id = ++swdev_id;
889
890    list_for_each_entry(sdev, &swdevs, dev_list) {
891        if (!sscanf(sdev->devname, SWCONFIG_DEVNAME, &i))
892            continue;
893        if (i < 0 || i > max_switches)
894            continue;
895
896        set_bit(i, &in_use);
897    }
898    i = find_first_zero_bit(&in_use, max_switches);
899
900    if (i == max_switches) {
901        swconfig_unlock();
902        return -ENFILE;
903    }
904
905    /* fill device name */
906    snprintf(dev->devname, IFNAMSIZ, SWCONFIG_DEVNAME, i);
907
908    list_add(&dev->dev_list, &swdevs);
909    swconfig_unlock();
910
911    err = swconfig_create_led_trigger(dev);
912    if (err)
913        return err;
914
915    return 0;
916}
917EXPORT_SYMBOL_GPL(register_switch);
918
919void
920unregister_switch(struct switch_dev *dev)
921{
922    swconfig_destroy_led_trigger(dev);
923    kfree(dev->portbuf);
924    spin_lock(&dev->lock);
925    swconfig_lock();
926    list_del(&dev->dev_list);
927    swconfig_unlock();
928    spin_unlock(&dev->lock);
929}
930EXPORT_SYMBOL_GPL(unregister_switch);
931
932
933static int __init
934swconfig_init(void)
935{
936    int i, err;
937
938    INIT_LIST_HEAD(&swdevs);
939    err = genl_register_family(&switch_fam);
940    if (err)
941        return err;
942
943    for (i = 0; i < ARRAY_SIZE(swconfig_ops); i++) {
944        err = genl_register_ops(&switch_fam, &swconfig_ops[i]);
945        if (err)
946            goto unregister;
947    }
948
949    return 0;
950
951unregister:
952    genl_unregister_family(&switch_fam);
953    return err;
954}
955
956static void __exit
957swconfig_exit(void)
958{
959    genl_unregister_family(&switch_fam);
960}
961
962module_init(swconfig_init);
963module_exit(swconfig_exit);
964
965

Archive Download this file



interactive