Change NHLFE MTU calculation
[mpls-linux.git] / src / mpls_proto.c
blob40c2c251e015cffba98aabfbefbab937bd4e629b
1 /*****************************************************************************
2 * MPLS
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.
16 * Changes:
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>
28 #include <linux/mm.h>
29 #include <linux/errno.h>
30 #include <linux/interrupt.h>
31 #include <linux/skbuff.h>
32 #include <linux/rculist.h>
33 #include <net/mpls.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);
46 return 0;
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) {
59 retval = -EADDRINUSE;
60 } else {
61 list_del_rcu(&proto->list);
62 retval = 0;
64 break;
67 spin_unlock_bh(&mpls_proto_lock);
69 synchronize_net();
70 return retval;
73 struct mpls_prot_driver *mpls_proto_find_by_family(unsigned short fam)
75 struct mpls_prot_driver *proto;
77 rcu_read_lock();
78 list_for_each_entry_rcu(proto, &mpls_proto_list, list) {
79 if (fam == proto->family) {
80 mpls_proto_hold(proto);
81 goto out;
84 proto = NULL;
85 out:
86 rcu_read_unlock();
88 return proto;
91 struct mpls_prot_driver *mpls_proto_find_by_ethertype(unsigned short type)
93 struct mpls_prot_driver *proto;
95 rcu_read_lock();
96 list_for_each_entry_rcu(proto, &mpls_proto_list, list) {
97 if (type == proto->ethertype) {
98 mpls_proto_hold(proto);
99 goto out;
102 proto = NULL;
103 out:
104 rcu_read_unlock();
106 return proto;
109 struct mpls_prot_driver *mpls_proto_find_by_name(char *name)
111 struct mpls_prot_driver *proto;
113 rcu_read_lock();
114 list_for_each_entry_rcu(proto, &mpls_proto_list, list) {
115 if (!strncmp(name, proto->name, MPLSPROTONAMSIZ)) {
116 mpls_proto_hold(proto);
117 goto out;
120 proto = NULL;
121 out:
122 rcu_read_unlock();
124 return proto;
127 void mpls_proto_cache_flush_all(struct net *net)
129 struct mpls_prot_driver *proto;
131 rcu_read_lock();
132 list_for_each_entry_rcu(proto, &mpls_proto_list, list) {
133 proto->cache_flush(net);
135 rcu_read_unlock();
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);