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

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [tags/] [linux-2.6/] [linux-2.6.24_or32_unified_v2.3/] [net/] [tipc/] [eth_media.c] - Blame information for rev 8

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*
2
 * net/tipc/eth_media.c: Ethernet bearer support for TIPC
3
 *
4
 * Copyright (c) 2001-2007, Ericsson AB
5
 * Copyright (c) 2005-2007, Wind River Systems
6
 * All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions are met:
10
 *
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 * 3. Neither the names of the copyright holders nor the names of its
17
 *    contributors may be used to endorse or promote products derived from
18
 *    this software without specific prior written permission.
19
 *
20
 * Alternatively, this software may be distributed under the terms of the
21
 * GNU General Public License ("GPL") version 2 as published by the Free
22
 * Software Foundation.
23
 *
24
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34
 * POSSIBILITY OF SUCH DAMAGE.
35
 */
36
 
37
#include <net/tipc/tipc.h>
38
#include <net/tipc/tipc_bearer.h>
39
#include <net/tipc/tipc_msg.h>
40
#include <linux/netdevice.h>
41
#include <net/net_namespace.h>
42
 
43
#define MAX_ETH_BEARERS         2
44
#define ETH_LINK_PRIORITY       TIPC_DEF_LINK_PRI
45
#define ETH_LINK_TOLERANCE      TIPC_DEF_LINK_TOL
46
#define ETH_LINK_WINDOW         TIPC_DEF_LINK_WIN
47
 
48
/**
49
 * struct eth_bearer - Ethernet bearer data structure
50
 * @bearer: ptr to associated "generic" bearer structure
51
 * @dev: ptr to associated Ethernet network device
52
 * @tipc_packet_type: used in binding TIPC to Ethernet driver
53
 */
54
 
55
struct eth_bearer {
56
        struct tipc_bearer *bearer;
57
        struct net_device *dev;
58
        struct packet_type tipc_packet_type;
59
};
60
 
61
static struct eth_bearer eth_bearers[MAX_ETH_BEARERS];
62
static int eth_started = 0;
63
static struct notifier_block notifier;
64
 
65
/**
66
 * send_msg - send a TIPC message out over an Ethernet interface
67
 */
68
 
69
static int send_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr,
70
                    struct tipc_media_addr *dest)
71
{
72
        struct sk_buff *clone;
73
        struct net_device *dev;
74
 
75
        clone = skb_clone(buf, GFP_ATOMIC);
76
        if (clone) {
77
                skb_reset_network_header(clone);
78
                dev = ((struct eth_bearer *)(tb_ptr->usr_handle))->dev;
79
                clone->dev = dev;
80
                dev_hard_header(clone, dev, ETH_P_TIPC,
81
                                 &dest->dev_addr.eth_addr,
82
                                 dev->dev_addr, clone->len);
83
                dev_queue_xmit(clone);
84
        }
85
        return TIPC_OK;
86
}
87
 
88
/**
89
 * recv_msg - handle incoming TIPC message from an Ethernet interface
90
 *
91
 * Accept only packets explicitly sent to this node, or broadcast packets;
92
 * ignores packets sent using Ethernet multicast, and traffic sent to other
93
 * nodes (which can happen if interface is running in promiscuous mode).
94
 * Routine truncates any Ethernet padding/CRC appended to the message,
95
 * and ensures message size matches actual length
96
 */
97
 
98
static int recv_msg(struct sk_buff *buf, struct net_device *dev,
99
                    struct packet_type *pt, struct net_device *orig_dev)
100
{
101
        struct eth_bearer *eb_ptr = (struct eth_bearer *)pt->af_packet_priv;
102
        u32 size;
103
 
104
        if (dev->nd_net != &init_net) {
105
                kfree_skb(buf);
106
                return 0;
107
        }
108
 
109
        if (likely(eb_ptr->bearer)) {
110
                if (likely(buf->pkt_type <= PACKET_BROADCAST)) {
111
                        size = msg_size((struct tipc_msg *)buf->data);
112
                        skb_trim(buf, size);
113
                        if (likely(buf->len == size)) {
114
                                buf->next = NULL;
115
                                tipc_recv_msg(buf, eb_ptr->bearer);
116
                                return TIPC_OK;
117
                        }
118
                }
119
        }
120
        kfree_skb(buf);
121
        return TIPC_OK;
122
}
123
 
124
/**
125
 * enable_bearer - attach TIPC bearer to an Ethernet interface
126
 */
127
 
128
static int enable_bearer(struct tipc_bearer *tb_ptr)
129
{
130
        struct net_device *dev = NULL;
131
        struct net_device *pdev = NULL;
132
        struct eth_bearer *eb_ptr = &eth_bearers[0];
133
        struct eth_bearer *stop = &eth_bearers[MAX_ETH_BEARERS];
134
        char *driver_name = strchr((const char *)tb_ptr->name, ':') + 1;
135
 
136
        /* Find device with specified name */
137
 
138
        for_each_netdev(&init_net, pdev){
139
                if (!strncmp(pdev->name, driver_name, IFNAMSIZ)) {
140
                        dev = pdev;
141
                        break;
142
                }
143
        }
144
        if (!dev)
145
                return -ENODEV;
146
 
147
        /* Find Ethernet bearer for device (or create one) */
148
 
149
        for (;(eb_ptr != stop) && eb_ptr->dev && (eb_ptr->dev != dev); eb_ptr++);
150
        if (eb_ptr == stop)
151
                return -EDQUOT;
152
        if (!eb_ptr->dev) {
153
                eb_ptr->dev = dev;
154
                eb_ptr->tipc_packet_type.type = htons(ETH_P_TIPC);
155
                eb_ptr->tipc_packet_type.dev = dev;
156
                eb_ptr->tipc_packet_type.func = recv_msg;
157
                eb_ptr->tipc_packet_type.af_packet_priv = eb_ptr;
158
                INIT_LIST_HEAD(&(eb_ptr->tipc_packet_type.list));
159
                dev_hold(dev);
160
                dev_add_pack(&eb_ptr->tipc_packet_type);
161
        }
162
 
163
        /* Associate TIPC bearer with Ethernet bearer */
164
 
165
        eb_ptr->bearer = tb_ptr;
166
        tb_ptr->usr_handle = (void *)eb_ptr;
167
        tb_ptr->mtu = dev->mtu;
168
        tb_ptr->blocked = 0;
169
        tb_ptr->addr.type = htonl(TIPC_MEDIA_TYPE_ETH);
170
        memcpy(&tb_ptr->addr.dev_addr, &dev->dev_addr, ETH_ALEN);
171
        return 0;
172
}
173
 
174
/**
175
 * disable_bearer - detach TIPC bearer from an Ethernet interface
176
 *
177
 * We really should do dev_remove_pack() here, but this function can not be
178
 * called at tasklet level. => Use eth_bearer->bearer as a flag to throw away
179
 * incoming buffers, & postpone dev_remove_pack() to eth_media_stop() on exit.
180
 */
181
 
182
static void disable_bearer(struct tipc_bearer *tb_ptr)
183
{
184
        ((struct eth_bearer *)tb_ptr->usr_handle)->bearer = NULL;
185
}
186
 
187
/**
188
 * recv_notification - handle device updates from OS
189
 *
190
 * Change the state of the Ethernet bearer (if any) associated with the
191
 * specified device.
192
 */
193
 
194
static int recv_notification(struct notifier_block *nb, unsigned long evt,
195
                             void *dv)
196
{
197
        struct net_device *dev = (struct net_device *)dv;
198
        struct eth_bearer *eb_ptr = &eth_bearers[0];
199
        struct eth_bearer *stop = &eth_bearers[MAX_ETH_BEARERS];
200
 
201
        if (dev->nd_net != &init_net)
202
                return NOTIFY_DONE;
203
 
204
        while ((eb_ptr->dev != dev)) {
205
                if (++eb_ptr == stop)
206
                        return NOTIFY_DONE;     /* couldn't find device */
207
        }
208
        if (!eb_ptr->bearer)
209
                return NOTIFY_DONE;             /* bearer had been disabled */
210
 
211
        eb_ptr->bearer->mtu = dev->mtu;
212
 
213
        switch (evt) {
214
        case NETDEV_CHANGE:
215
                if (netif_carrier_ok(dev))
216
                        tipc_continue(eb_ptr->bearer);
217
                else
218
                        tipc_block_bearer(eb_ptr->bearer->name);
219
                break;
220
        case NETDEV_UP:
221
                tipc_continue(eb_ptr->bearer);
222
                break;
223
        case NETDEV_DOWN:
224
                tipc_block_bearer(eb_ptr->bearer->name);
225
                break;
226
        case NETDEV_CHANGEMTU:
227
        case NETDEV_CHANGEADDR:
228
                tipc_block_bearer(eb_ptr->bearer->name);
229
                tipc_continue(eb_ptr->bearer);
230
                break;
231
        case NETDEV_UNREGISTER:
232
        case NETDEV_CHANGENAME:
233
                tipc_disable_bearer(eb_ptr->bearer->name);
234
                break;
235
        }
236
        return NOTIFY_OK;
237
}
238
 
239
/**
240
 * eth_addr2str - convert Ethernet address to string
241
 */
242
 
243
static char *eth_addr2str(struct tipc_media_addr *a, char *str_buf, int str_size)
244
{
245
        unchar *addr = (unchar *)&a->dev_addr;
246
        DECLARE_MAC_BUF(mac);
247
 
248
        if (str_size < 18)
249
                *str_buf = '\0';
250
        else
251
                sprintf(str_buf, "%s", print_mac(mac, addr));
252
        return str_buf;
253
}
254
 
255
/**
256
 * tipc_eth_media_start - activate Ethernet bearer support
257
 *
258
 * Register Ethernet media type with TIPC bearer code.  Also register
259
 * with OS for notifications about device state changes.
260
 */
261
 
262
int tipc_eth_media_start(void)
263
{
264
        struct tipc_media_addr bcast_addr;
265
        int res;
266
 
267
        if (eth_started)
268
                return -EINVAL;
269
 
270
        bcast_addr.type = htonl(TIPC_MEDIA_TYPE_ETH);
271
        memset(&bcast_addr.dev_addr, 0xff, ETH_ALEN);
272
 
273
        memset(eth_bearers, 0, sizeof(eth_bearers));
274
 
275
        res = tipc_register_media(TIPC_MEDIA_TYPE_ETH, "eth",
276
                                  enable_bearer, disable_bearer, send_msg,
277
                                  eth_addr2str, &bcast_addr, ETH_LINK_PRIORITY,
278
                                  ETH_LINK_TOLERANCE, ETH_LINK_WINDOW);
279
        if (res)
280
                return res;
281
 
282
        notifier.notifier_call = &recv_notification;
283
        notifier.priority = 0;
284
        res = register_netdevice_notifier(&notifier);
285
        if (!res)
286
                eth_started = 1;
287
        return res;
288
}
289
 
290
/**
291
 * tipc_eth_media_stop - deactivate Ethernet bearer support
292
 */
293
 
294
void tipc_eth_media_stop(void)
295
{
296
        int i;
297
 
298
        if (!eth_started)
299
                return;
300
 
301
        unregister_netdevice_notifier(&notifier);
302
        for (i = 0; i < MAX_ETH_BEARERS ; i++) {
303
                if (eth_bearers[i].bearer) {
304
                        eth_bearers[i].bearer->blocked = 1;
305
                        eth_bearers[i].bearer = NULL;
306
                }
307
                if (eth_bearers[i].dev) {
308
                        dev_remove_pack(&eth_bearers[i].tipc_packet_type);
309
                        dev_put(eth_bearers[i].dev);
310
                }
311
        }
312
        memset(&eth_bearers, 0, sizeof(eth_bearers));
313
        eth_started = 0;
314
}

powered by: WebSVN 2.1.0

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