OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [net/] [bridge/] [br_if.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *      Userspace interface
3
 *      Linux ethernet bridge
4
 *
5
 *      Authors:
6
 *      Lennert Buytenhek               <buytenh@gnu.org>
7
 *
8
 *      $Id: br_if.c,v 1.1.1.1 2004-04-15 01:16:27 phoenix Exp $
9
 *
10
 *      This program is free software; you can redistribute it and/or
11
 *      modify it under the terms of the GNU General Public License
12
 *      as published by the Free Software Foundation; either version
13
 *      2 of the License, or (at your option) any later version.
14
 */
15
 
16
#include <linux/kernel.h>
17
#include <linux/if_arp.h>
18
#include <linux/if_bridge.h>
19
#include <linux/inetdevice.h>
20
#include <linux/rtnetlink.h>
21
#include <linux/brlock.h>
22
#include <asm/uaccess.h>
23
#include "br_private.h"
24
 
25
static struct net_bridge *bridge_list;
26
 
27
static int br_initial_port_cost(struct net_device *dev)
28
{
29
        if (!strncmp(dev->name, "lec", 3))
30
                return 7;
31
 
32
        if (!strncmp(dev->name, "eth", 3))
33
                return 100;                     /* FIXME handle 100Mbps */
34
 
35
        if (!strncmp(dev->name, "plip", 4))
36
                return 2500;
37
 
38
        return 100;
39
}
40
 
41
/* called under BR_NETPROTO_LOCK and bridge lock */
42
static int __br_del_if(struct net_bridge *br, struct net_device *dev)
43
{
44
        struct net_bridge_port *p;
45
        struct net_bridge_port **pptr;
46
 
47
        if ((p = dev->br_port) == NULL)
48
                return -EINVAL;
49
 
50
        br_stp_disable_port(p);
51
 
52
        dev_set_promiscuity(dev, -1);
53
        dev->br_port = NULL;
54
 
55
        pptr = &br->port_list;
56
        while (*pptr != NULL) {
57
                if (*pptr == p) {
58
                        *pptr = p->next;
59
                        break;
60
                }
61
 
62
                pptr = &((*pptr)->next);
63
        }
64
 
65
        br_fdb_delete_by_port(br, p);
66
        kfree(p);
67
        dev_put(dev);
68
 
69
        return 0;
70
}
71
 
72
static struct net_bridge **__find_br(char *name)
73
{
74
        struct net_bridge **b;
75
        struct net_bridge *br;
76
 
77
        b = &bridge_list;
78
        while ((br = *b) != NULL) {
79
                if (!strncmp(br->dev.name, name, IFNAMSIZ))
80
                        return b;
81
 
82
                b = &(br->next);
83
        }
84
 
85
        return NULL;
86
}
87
 
88
static void del_ifs(struct net_bridge *br)
89
{
90
        br_write_lock_bh(BR_NETPROTO_LOCK);
91
        write_lock(&br->lock);
92
        while (br->port_list != NULL)
93
                __br_del_if(br, br->port_list->dev);
94
        write_unlock(&br->lock);
95
        br_write_unlock_bh(BR_NETPROTO_LOCK);
96
}
97
 
98
static struct net_bridge *new_nb(char *name)
99
{
100
        struct net_bridge *br;
101
        struct net_device *dev;
102
 
103
        if ((br = kmalloc(sizeof(*br), GFP_KERNEL)) == NULL)
104
                return NULL;
105
 
106
        memset(br, 0, sizeof(*br));
107
        dev = &br->dev;
108
 
109
        strncpy(dev->name, name, IFNAMSIZ);
110
        dev->priv = br;
111
        ether_setup(dev);
112
        br_dev_setup(dev);
113
 
114
        br->lock = RW_LOCK_UNLOCKED;
115
        br->hash_lock = RW_LOCK_UNLOCKED;
116
 
117
        br->bridge_id.prio[0] = 0x80;
118
        br->bridge_id.prio[1] = 0x00;
119
        memset(br->bridge_id.addr, 0, ETH_ALEN);
120
 
121
        br->stp_enabled = 0;
122
        br->designated_root = br->bridge_id;
123
        br->root_path_cost = 0;
124
        br->root_port = 0;
125
        br->bridge_max_age = br->max_age = 20 * HZ;
126
        br->bridge_hello_time = br->hello_time = 2 * HZ;
127
        br->bridge_forward_delay = br->forward_delay = 15 * HZ;
128
        br->topology_change = 0;
129
        br->topology_change_detected = 0;
130
        br_timer_clear(&br->hello_timer);
131
        br_timer_clear(&br->tcn_timer);
132
        br_timer_clear(&br->topology_change_timer);
133
 
134
        br->ageing_time = 300 * HZ;
135
        br->gc_interval = 4 * HZ;
136
 
137
        return br;
138
}
139
 
140
/* called under bridge lock */
141
static struct net_bridge_port *new_nbp(struct net_bridge *br, struct net_device *dev)
142
{
143
        int i;
144
        struct net_bridge_port *p;
145
 
146
        p = kmalloc(sizeof(*p), GFP_ATOMIC);
147
        if (p == NULL)
148
                return p;
149
 
150
        memset(p, 0, sizeof(*p));
151
        p->br = br;
152
        p->dev = dev;
153
        p->path_cost = br_initial_port_cost(dev);
154
        p->priority = 0x80;
155
 
156
        for (i=1;i<255;i++)
157
                if (br_get_port(br, i) == NULL)
158
                        break;
159
 
160
        if (i == 255) {
161
                kfree(p);
162
                return NULL;
163
        }
164
 
165
        dev->br_port = p;
166
 
167
        p->port_no = i;
168
        br_init_port(p);
169
        p->state = BR_STATE_DISABLED;
170
 
171
        p->next = br->port_list;
172
        br->port_list = p;
173
 
174
        return p;
175
}
176
 
177
int br_add_bridge(char *name)
178
{
179
        struct net_bridge *br;
180
 
181
        if ((br = new_nb(name)) == NULL)
182
                return -ENOMEM;
183
 
184
        if (__dev_get_by_name(name) != NULL) {
185
                kfree(br);
186
                return -EEXIST;
187
        }
188
 
189
        br->next = bridge_list;
190
        bridge_list = br;
191
 
192
        br_inc_use_count();
193
        register_netdev(&br->dev);
194
 
195
        return 0;
196
}
197
 
198
int br_del_bridge(char *name)
199
{
200
        struct net_bridge **b;
201
        struct net_bridge *br;
202
 
203
        if ((b = __find_br(name)) == NULL)
204
                return -ENXIO;
205
 
206
        br = *b;
207
 
208
        if (br->dev.flags & IFF_UP)
209
                return -EBUSY;
210
 
211
        del_ifs(br);
212
 
213
        *b = br->next;
214
 
215
        unregister_netdev(&br->dev);
216
        kfree(br);
217
        br_dec_use_count();
218
 
219
        return 0;
220
}
221
 
222
int br_add_if(struct net_bridge *br, struct net_device *dev)
223
{
224
        struct net_bridge_port *p;
225
 
226
        if (dev->br_port != NULL)
227
                return -EBUSY;
228
 
229
        if (dev->flags & IFF_LOOPBACK || dev->type != ARPHRD_ETHER)
230
                return -EINVAL;
231
 
232
        if (dev->hard_start_xmit == br_dev_xmit)
233
                return -ELOOP;
234
 
235
        dev_hold(dev);
236
        write_lock_bh(&br->lock);
237
        if ((p = new_nbp(br, dev)) == NULL) {
238
                write_unlock_bh(&br->lock);
239
                dev_put(dev);
240
                return -EXFULL;
241
        }
242
 
243
        dev_set_promiscuity(dev, 1);
244
 
245
        br_stp_recalculate_bridge_id(br);
246
        br_fdb_insert(br, p, dev->dev_addr, 1);
247
        if ((br->dev.flags & IFF_UP) && (dev->flags & IFF_UP))
248
                br_stp_enable_port(p);
249
        write_unlock_bh(&br->lock);
250
 
251
        return 0;
252
}
253
 
254
int br_del_if(struct net_bridge *br, struct net_device *dev)
255
{
256
        int retval;
257
 
258
        br_write_lock_bh(BR_NETPROTO_LOCK);
259
        write_lock(&br->lock);
260
        retval = __br_del_if(br, dev);
261
        br_stp_recalculate_bridge_id(br);
262
        write_unlock(&br->lock);
263
        br_write_unlock_bh(BR_NETPROTO_LOCK);
264
 
265
        return retval;
266
}
267
 
268
int br_get_bridge_ifindices(int *indices, int num)
269
{
270
        struct net_bridge *br;
271
        int i;
272
 
273
        br = bridge_list;
274
        for (i=0;i<num;i++) {
275
                if (br == NULL)
276
                        break;
277
 
278
                indices[i] = br->dev.ifindex;
279
                br = br->next;
280
        }
281
 
282
        return i;
283
}
284
 
285
/* called under ioctl_lock */
286
void br_get_port_ifindices(struct net_bridge *br, int *ifindices)
287
{
288
        struct net_bridge_port *p;
289
 
290
        p = br->port_list;
291
        while (p != NULL) {
292
                ifindices[p->port_no] = p->dev->ifindex;
293
                p = p->next;
294
        }
295
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.