1 /*****************************************************************************
3 * An implementation of the MPLS (MultiProtocol Label
4 * Switching) Architecture for Linux.
6 * mpls_proto.c: MPLS Proto management
8 * Copyright (C) David S. Miller (davem@redhat.com),
9 * James R. Leu (jleu@mindspring.com)
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version
14 * 2 of the License, or (at your option) any later version.
17 * RCAS: minor changes (formatting) and added addr
18 * JLEU: added mpls_prot_cache_flush_all()
19 * JLEU: rewrote most of the functions to allow for more
20 * families then just IPv4 and IPv6
21 *****************************************************************************/
23 #include <linux/autoconf.h>
24 #include <linux/types.h>
25 #include <linux/kernel.h>
26 #include <linux/sched.h>
27 #include <linux/string.h>
29 #include <linux/errno.h>
30 #include <linux/interrupt.h>
31 #include <linux/skbuff.h>
32 #include <linux/rculist.h>
35 DEFINE_SPINLOCK(mpls_proto_lock
);
36 LIST_HEAD(mpls_proto_list
);
38 int mpls_proto_add(struct mpls_prot_driver
*proto
)
40 spin_lock_bh(&mpls_proto_lock
);
42 atomic_set(&proto
->__refcnt
, 1);
43 list_add_rcu(&proto
->list
, &mpls_proto_list
);
45 spin_unlock_bh(&mpls_proto_lock
);
49 int mpls_proto_remove(struct mpls_prot_driver
*proto
)
51 struct mpls_prot_driver
*proto1
;
52 int retval
= -EPROTONOSUPPORT
;
54 spin_lock_bh(&mpls_proto_lock
);
56 list_for_each_entry(proto1
, &mpls_proto_list
, list
) {
57 if (proto
== proto1
) {
58 if (atomic_read(&proto
->__refcnt
) != 1) {
61 list_del_rcu(&proto
->list
);
67 spin_unlock_bh(&mpls_proto_lock
);
73 struct mpls_prot_driver
*mpls_proto_find_by_family(unsigned short fam
)
75 struct mpls_prot_driver
*proto
;
78 list_for_each_entry_rcu(proto
, &mpls_proto_list
, list
) {
79 if (fam
== proto
->family
) {
80 mpls_proto_hold(proto
);
91 struct mpls_prot_driver
*mpls_proto_find_by_ethertype(unsigned short type
)
93 struct mpls_prot_driver
*proto
;
96 list_for_each_entry_rcu(proto
, &mpls_proto_list
, list
) {
97 if (type
== proto
->ethertype
) {
98 mpls_proto_hold(proto
);
109 struct mpls_prot_driver
*mpls_proto_find_by_name(char *name
)
111 struct mpls_prot_driver
*proto
;
114 list_for_each_entry_rcu(proto
, &mpls_proto_list
, list
) {
115 if (!strncmp(name
, proto
->name
, MPLSPROTONAMSIZ
)) {
116 mpls_proto_hold(proto
);
127 void mpls_proto_cache_flush_all(struct net
*net
)
129 struct mpls_prot_driver
*proto
;
132 list_for_each_entry_rcu(proto
, &mpls_proto_list
, list
) {
133 proto
->cache_flush(net
);
138 void __init
mpls_proto_init(void)
140 printk("MPLS: protocol driver interface - <jleu@mindspring.com>\n");
143 void __exit
mpls_proto_exit(void)
147 EXPORT_SYMBOL(mpls_proto_add
);
148 EXPORT_SYMBOL(mpls_proto_remove
);
149 EXPORT_SYMBOL(mpls_proto_find_by_family
);
150 EXPORT_SYMBOL(mpls_proto_find_by_ethertype
);
151 EXPORT_SYMBOL(mpls_proto_find_by_name
);
152 EXPORT_SYMBOL(mpls_proto_cache_flush_all
);
153 EXPORT_SYMBOL(mpls_proto_lock
);
154 EXPORT_SYMBOL(mpls_proto_list
);