aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/eth_media.c
diff options
context:
space:
mode:
authorYing Xue <ying.xue@windriver.com>2013-12-10 23:45:42 -0500
committerDavid S. Miller <davem@davemloft.net>2013-12-11 00:17:43 -0500
commit6e967adf798ae5066488fd0c2b2466d06c642f23 (patch)
tree5087be7329e5f2fd83c0f92e5cade64fd3c0d545 /net/tipc/eth_media.c
parent37cb0620073cb64101d9307931c135c70b2e3f04 (diff)
tipc: relocate common functions from media to bearer
Currently, registering a TIPC stack handler in the network device layer is done twice, once for Ethernet (eth_media) and Infiniband (ib_media) repectively. But, as this registration is not media specific, we can avoid some code duplication by moving the registering function to the generic bearer layer, to the file bearer.c, and call it only once. The same is true for the network device event notifier. As a side effect, the two workqueues we are using for for setting up/ cleaning up media can now be eliminated. Furthermore, the array for storing the specific media type structs, media_array[], can be entirely deleted. Note that the eth_started and ib_started flags were removed during the code relocation. There is now only one call to bearer_setup and bearer_cleanup, and these can logically not race against each other. Despite its size, this cleanup work incurs no functional changes in TIPC. In particular, it should be noted that the sequence ordering of received packets is unaffected by this change, since packet reception never was subject to any work queue handling in the first place. Signed-off-by: Ying Xue <ying.xue@windriver.com> Cc: Patrick McHardy <kaber@trash.net> Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Reviewed-by: Paul Gortmaker <paul.gortmaker@windriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/eth_media.c')
-rw-r--r--net/tipc/eth_media.c199
1 files changed, 3 insertions, 196 deletions
diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c
index c5f685dee15b..f28f7160adba 100644
--- a/net/tipc/eth_media.c
+++ b/net/tipc/eth_media.c
@@ -37,49 +37,9 @@
37#include "core.h" 37#include "core.h"
38#include "bearer.h" 38#include "bearer.h"
39 39
40#define MAX_ETH_MEDIA MAX_BEARERS
41
42#define ETH_ADDR_OFFSET 4 /* message header offset of MAC address */ 40#define ETH_ADDR_OFFSET 4 /* message header offset of MAC address */
43 41
44/** 42/**
45 * struct eth_media - Ethernet bearer data structure
46 * @bearer: ptr to associated "generic" bearer structure
47 * @dev: ptr to associated Ethernet network device
48 * @tipc_packet_type: used in binding TIPC to Ethernet driver
49 * @setup: work item used when enabling bearer
50 * @cleanup: work item used when disabling bearer
51 */
52struct eth_media {
53 struct tipc_bearer *bearer;
54 struct net_device *dev;
55 struct packet_type tipc_packet_type;
56 struct work_struct setup;
57 struct work_struct cleanup;
58};
59
60
61static struct eth_media eth_media_array[MAX_ETH_MEDIA];
62static int eth_started;
63
64static int recv_notification(struct notifier_block *nb, unsigned long evt,
65 void *dv);
66static int recv_msg(struct sk_buff *buf, struct net_device *dev,
67 struct packet_type *pt, struct net_device *orig_dev);
68
69/*
70 * Network device notifier info
71 */
72static struct notifier_block notifier = {
73 .notifier_call = recv_notification,
74 .priority = 0
75};
76
77static struct packet_type tipc_packet_type __read_mostly = {
78 .type = __constant_htons(ETH_P_TIPC),
79 .func = recv_msg,
80};
81
82/**
83 * eth_media_addr_set - initialize Ethernet media address structure 43 * eth_media_addr_set - initialize Ethernet media address structure
84 * 44 *
85 * Media-dependent "value" field stores MAC address in first 6 bytes 45 * Media-dependent "value" field stores MAC address in first 6 bytes
@@ -101,16 +61,14 @@ static int send_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr,
101 struct tipc_media_addr *dest) 61 struct tipc_media_addr *dest)
102{ 62{
103 struct sk_buff *clone; 63 struct sk_buff *clone;
104 struct net_device *dev;
105 int delta; 64 int delta;
65 struct net_device *dev = tb_ptr->dev;
106 66
107 clone = skb_clone(buf, GFP_ATOMIC); 67 clone = skb_clone(buf, GFP_ATOMIC);
108 if (!clone) 68 if (!clone)
109 return 0; 69 return 0;
110 70
111 dev = ((struct eth_media *)(tb_ptr->usr_handle))->dev;
112 delta = dev->hard_header_len - skb_headroom(buf); 71 delta = dev->hard_header_len - skb_headroom(buf);
113
114 if ((delta > 0) && 72 if ((delta > 0) &&
115 pskb_expand_head(clone, SKB_DATA_ALIGN(delta), 0, GFP_ATOMIC)) { 73 pskb_expand_head(clone, SKB_DATA_ALIGN(delta), 0, GFP_ATOMIC)) {
116 kfree_skb(clone); 74 kfree_skb(clone);
@@ -127,79 +85,21 @@ static int send_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr,
127} 85}
128 86
129/** 87/**
130 * recv_msg - handle incoming TIPC message from an Ethernet interface
131 *
132 * Accept only packets explicitly sent to this node, or broadcast packets;
133 * ignores packets sent using Ethernet multicast, and traffic sent to other
134 * nodes (which can happen if interface is running in promiscuous mode).
135 */
136static int recv_msg(struct sk_buff *buf, struct net_device *dev,
137 struct packet_type *pt, struct net_device *orig_dev)
138{
139 struct tipc_bearer *b_ptr;
140
141 if (!net_eq(dev_net(dev), &init_net)) {
142 kfree_skb(buf);
143 return NET_RX_DROP;
144 }
145
146 rcu_read_lock();
147 b_ptr = rcu_dereference(dev->tipc_ptr);
148 if (likely(b_ptr)) {
149 if (likely(buf->pkt_type <= PACKET_BROADCAST)) {
150 buf->next = NULL;
151 tipc_recv_msg(buf, b_ptr);
152 rcu_read_unlock();
153 return NET_RX_SUCCESS;
154 }
155 }
156 rcu_read_unlock();
157
158 kfree_skb(buf);
159 return NET_RX_DROP;
160}
161
162/**
163 * setup_media - setup association between Ethernet bearer and interface
164 */
165static void setup_media(struct work_struct *work)
166{
167 dev_add_pack(&tipc_packet_type);
168}
169
170/**
171 * enable_media - attach TIPC bearer to an Ethernet interface 88 * enable_media - attach TIPC bearer to an Ethernet interface
172 */ 89 */
173static int enable_media(struct tipc_bearer *tb_ptr) 90static int enable_media(struct tipc_bearer *tb_ptr)
174{ 91{
175 struct net_device *dev; 92 struct net_device *dev;
176 struct eth_media *eb_ptr = &eth_media_array[0];
177 struct eth_media *stop = &eth_media_array[MAX_ETH_MEDIA];
178 char *driver_name = strchr((const char *)tb_ptr->name, ':') + 1; 93 char *driver_name = strchr((const char *)tb_ptr->name, ':') + 1;
179 int pending_dev = 0;
180
181 /* Find unused Ethernet bearer structure */
182 while (eb_ptr->dev) {
183 if (!eb_ptr->bearer)
184 pending_dev++;
185 if (++eb_ptr == stop)
186 return pending_dev ? -EAGAIN : -EDQUOT;
187 }
188 94
189 /* Find device with specified name */ 95 /* Find device with specified name */
190 dev = dev_get_by_name(&init_net, driver_name); 96 dev = dev_get_by_name(&init_net, driver_name);
191 if (!dev) 97 if (!dev)
192 return -ENODEV; 98 return -ENODEV;
193 99
194 /* Create Ethernet bearer for device */
195 eb_ptr->dev = dev;
196 INIT_WORK(&eb_ptr->setup, setup_media);
197 schedule_work(&eb_ptr->setup);
198
199 /* Associate TIPC bearer with Ethernet bearer */ 100 /* Associate TIPC bearer with Ethernet bearer */
200 tb_ptr->dev = dev; 101 tb_ptr->dev = dev;
201 eb_ptr->bearer = tb_ptr; 102 tb_ptr->usr_handle = NULL;
202 tb_ptr->usr_handle = (void *)eb_ptr;
203 memset(tb_ptr->bcast_addr.value, 0, sizeof(tb_ptr->bcast_addr.value)); 103 memset(tb_ptr->bcast_addr.value, 0, sizeof(tb_ptr->bcast_addr.value));
204 memcpy(tb_ptr->bcast_addr.value, dev->broadcast, ETH_ALEN); 104 memcpy(tb_ptr->bcast_addr.value, dev->broadcast, ETH_ALEN);
205 tb_ptr->bcast_addr.media_id = TIPC_MEDIA_TYPE_ETH; 105 tb_ptr->bcast_addr.media_id = TIPC_MEDIA_TYPE_ETH;
@@ -211,21 +111,6 @@ static int enable_media(struct tipc_bearer *tb_ptr)
211} 111}
212 112
213/** 113/**
214 * cleanup_media - break association between Ethernet bearer and interface
215 *
216 * This routine must be invoked from a work queue because it can sleep.
217 */
218static void cleanup_media(struct work_struct *work)
219{
220 struct eth_media *eb_ptr =
221 container_of(work, struct eth_media, cleanup);
222
223 dev_remove_pack(&tipc_packet_type);
224 dev_put(eb_ptr->dev);
225 eb_ptr->dev = NULL;
226}
227
228/**
229 * disable_media - detach TIPC bearer from an Ethernet interface 114 * disable_media - detach TIPC bearer from an Ethernet interface
230 * 115 *
231 * Mark Ethernet bearer as inactive so that incoming buffers are thrown away, 116 * Mark Ethernet bearer as inactive so that incoming buffers are thrown away,
@@ -234,55 +119,8 @@ static void cleanup_media(struct work_struct *work)
234 */ 119 */
235static void disable_media(struct tipc_bearer *tb_ptr) 120static void disable_media(struct tipc_bearer *tb_ptr)
236{ 121{
237 struct eth_media *eb_ptr = (struct eth_media *)tb_ptr->usr_handle;
238
239 eb_ptr->bearer = NULL;
240 INIT_WORK(&eb_ptr->cleanup, cleanup_media);
241 schedule_work(&eb_ptr->cleanup);
242 RCU_INIT_POINTER(tb_ptr->dev->tipc_ptr, NULL); 122 RCU_INIT_POINTER(tb_ptr->dev->tipc_ptr, NULL);
243} 123 dev_put(tb_ptr->dev);
244
245/**
246 * recv_notification - handle device updates from OS
247 *
248 * Change the state of the Ethernet bearer (if any) associated with the
249 * specified device.
250 */
251static int recv_notification(struct notifier_block *nb, unsigned long evt,
252 void *ptr)
253{
254 struct tipc_bearer *b_ptr;
255 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
256
257 if (!net_eq(dev_net(dev), &init_net))
258 return NOTIFY_DONE;
259
260 rcu_read_lock();
261 b_ptr = rcu_dereference(dev->tipc_ptr);
262 if (!b_ptr) {
263 rcu_read_unlock();
264 return NOTIFY_DONE; /* bearer had been disabled */
265 }
266
267 b_ptr->mtu = dev->mtu;
268
269 switch (evt) {
270 case NETDEV_CHANGE:
271 if (netif_carrier_ok(dev))
272 break;
273 case NETDEV_DOWN:
274 case NETDEV_CHANGEMTU:
275 case NETDEV_CHANGEADDR:
276 tipc_reset_bearer(b_ptr);
277 break;
278 case NETDEV_UNREGISTER:
279 case NETDEV_CHANGENAME:
280 tipc_disable_bearer(b_ptr->name);
281 break;
282 }
283 rcu_read_unlock();
284
285 return NOTIFY_OK;
286} 124}
287 125
288/** 126/**
@@ -338,34 +176,3 @@ struct tipc_media eth_media_info = {
338 .name = "eth" 176 .name = "eth"
339}; 177};
340 178
341/**
342 * tipc_eth_media_start - activate Ethernet bearer support
343 *
344 * Register Ethernet media type with TIPC bearer code. Also register
345 * with OS for notifications about device state changes.
346 */
347int tipc_eth_media_start(void)
348{
349 int res;
350
351 if (eth_started)
352 return -EINVAL;
353
354 res = register_netdevice_notifier(&notifier);
355 if (!res)
356 eth_started = 1;
357 return res;
358}
359
360/**
361 * tipc_eth_media_stop - deactivate Ethernet bearer support
362 */
363void tipc_eth_media_stop(void)
364{
365 if (!eth_started)
366 return;
367
368 flush_scheduled_work();
369 unregister_netdevice_notifier(&notifier);
370 eth_started = 0;
371}