diff options
Diffstat (limited to 'net/tipc')
-rw-r--r-- | net/tipc/bearer.c | 105 | ||||
-rw-r--r-- | net/tipc/bearer.h | 11 | ||||
-rw-r--r-- | net/tipc/core.c | 8 | ||||
-rw-r--r-- | net/tipc/eth_media.c | 199 | ||||
-rw-r--r-- | net/tipc/ib_media.c | 192 |
5 files changed, 114 insertions, 401 deletions
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 2411bac2b8f9..e95e0b91ef30 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c | |||
@@ -367,7 +367,7 @@ exit: | |||
367 | /** | 367 | /** |
368 | * tipc_reset_bearer - Reset all links established over this bearer | 368 | * tipc_reset_bearer - Reset all links established over this bearer |
369 | */ | 369 | */ |
370 | int tipc_reset_bearer(struct tipc_bearer *b_ptr) | 370 | static int tipc_reset_bearer(struct tipc_bearer *b_ptr) |
371 | { | 371 | { |
372 | struct tipc_link *l_ptr; | 372 | struct tipc_link *l_ptr; |
373 | struct tipc_link *temp_l_ptr; | 373 | struct tipc_link *temp_l_ptr; |
@@ -432,7 +432,110 @@ int tipc_disable_bearer(const char *name) | |||
432 | return res; | 432 | return res; |
433 | } | 433 | } |
434 | 434 | ||
435 | /** | ||
436 | * tipc_l2_rcv_msg - handle incoming TIPC message from an interface | ||
437 | * @buf: the received packet | ||
438 | * @dev: the net device that the packet was received on | ||
439 | * @pt: the packet_type structure which was used to register this handler | ||
440 | * @orig_dev: the original receive net device in case the device is a bond | ||
441 | * | ||
442 | * Accept only packets explicitly sent to this node, or broadcast packets; | ||
443 | * ignores packets sent using interface multicast, and traffic sent to other | ||
444 | * nodes (which can happen if interface is running in promiscuous mode). | ||
445 | */ | ||
446 | static int tipc_l2_rcv_msg(struct sk_buff *buf, struct net_device *dev, | ||
447 | struct packet_type *pt, struct net_device *orig_dev) | ||
448 | { | ||
449 | struct tipc_bearer *b_ptr; | ||
450 | |||
451 | if (!net_eq(dev_net(dev), &init_net)) { | ||
452 | kfree_skb(buf); | ||
453 | return NET_RX_DROP; | ||
454 | } | ||
455 | |||
456 | rcu_read_lock(); | ||
457 | b_ptr = rcu_dereference(dev->tipc_ptr); | ||
458 | if (likely(b_ptr)) { | ||
459 | if (likely(buf->pkt_type <= PACKET_BROADCAST)) { | ||
460 | buf->next = NULL; | ||
461 | tipc_recv_msg(buf, b_ptr); | ||
462 | rcu_read_unlock(); | ||
463 | return NET_RX_SUCCESS; | ||
464 | } | ||
465 | } | ||
466 | rcu_read_unlock(); | ||
467 | |||
468 | kfree_skb(buf); | ||
469 | return NET_RX_DROP; | ||
470 | } | ||
471 | |||
472 | /** | ||
473 | * tipc_l2_device_event - handle device events from network device | ||
474 | * @nb: the context of the notification | ||
475 | * @evt: the type of event | ||
476 | * @ptr: the net device that the event was on | ||
477 | * | ||
478 | * This function is called by the Ethernet driver in case of link | ||
479 | * change event. | ||
480 | */ | ||
481 | static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt, | ||
482 | void *ptr) | ||
483 | { | ||
484 | struct tipc_bearer *b_ptr; | ||
485 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); | ||
435 | 486 | ||
487 | if (!net_eq(dev_net(dev), &init_net)) | ||
488 | return NOTIFY_DONE; | ||
489 | |||
490 | rcu_read_lock(); | ||
491 | b_ptr = rcu_dereference(dev->tipc_ptr); | ||
492 | if (!b_ptr) { | ||
493 | rcu_read_unlock(); | ||
494 | return NOTIFY_DONE; | ||
495 | } | ||
496 | |||
497 | b_ptr->mtu = dev->mtu; | ||
498 | |||
499 | switch (evt) { | ||
500 | case NETDEV_CHANGE: | ||
501 | if (netif_carrier_ok(dev)) | ||
502 | break; | ||
503 | case NETDEV_DOWN: | ||
504 | case NETDEV_CHANGEMTU: | ||
505 | case NETDEV_CHANGEADDR: | ||
506 | tipc_reset_bearer(b_ptr); | ||
507 | break; | ||
508 | case NETDEV_UNREGISTER: | ||
509 | case NETDEV_CHANGENAME: | ||
510 | tipc_disable_bearer(b_ptr->name); | ||
511 | break; | ||
512 | } | ||
513 | rcu_read_unlock(); | ||
514 | |||
515 | return NOTIFY_OK; | ||
516 | } | ||
517 | |||
518 | static struct packet_type tipc_packet_type __read_mostly = { | ||
519 | .type = __constant_htons(ETH_P_TIPC), | ||
520 | .func = tipc_l2_rcv_msg, | ||
521 | }; | ||
522 | |||
523 | static struct notifier_block notifier = { | ||
524 | .notifier_call = tipc_l2_device_event, | ||
525 | .priority = 0, | ||
526 | }; | ||
527 | |||
528 | int tipc_bearer_setup(void) | ||
529 | { | ||
530 | dev_add_pack(&tipc_packet_type); | ||
531 | return register_netdevice_notifier(¬ifier); | ||
532 | } | ||
533 | |||
534 | void tipc_bearer_cleanup(void) | ||
535 | { | ||
536 | unregister_netdevice_notifier(¬ifier); | ||
537 | dev_remove_pack(&tipc_packet_type); | ||
538 | } | ||
436 | 539 | ||
437 | void tipc_bearer_stop(void) | 540 | void tipc_bearer_stop(void) |
438 | { | 541 | { |
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h index 91b8d8b92373..0974c2f2bbe5 100644 --- a/net/tipc/bearer.h +++ b/net/tipc/bearer.h | |||
@@ -162,25 +162,16 @@ extern struct tipc_bearer tipc_bearers[]; | |||
162 | 162 | ||
163 | void tipc_recv_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr); | 163 | void tipc_recv_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr); |
164 | 164 | ||
165 | int tipc_reset_bearer(struct tipc_bearer *b_ptr); | ||
166 | |||
167 | int tipc_enable_bearer(const char *bearer_name, u32 disc_domain, u32 priority); | 165 | int tipc_enable_bearer(const char *bearer_name, u32 disc_domain, u32 priority); |
168 | int tipc_disable_bearer(const char *name); | 166 | int tipc_disable_bearer(const char *name); |
169 | 167 | ||
170 | /* | 168 | /* |
171 | * Routines made available to TIPC by supported media types | 169 | * Routines made available to TIPC by supported media types |
172 | */ | 170 | */ |
173 | int tipc_eth_media_start(void); | ||
174 | void tipc_eth_media_stop(void); | ||
175 | extern struct tipc_media eth_media_info; | 171 | extern struct tipc_media eth_media_info; |
176 | 172 | ||
177 | #ifdef CONFIG_TIPC_MEDIA_IB | 173 | #ifdef CONFIG_TIPC_MEDIA_IB |
178 | int tipc_ib_media_start(void); | ||
179 | void tipc_ib_media_stop(void); | ||
180 | extern struct tipc_media ib_media_info; | 174 | extern struct tipc_media ib_media_info; |
181 | #else | ||
182 | static inline int tipc_ib_media_start(void) { return 0; } | ||
183 | static inline void tipc_ib_media_stop(void) { return; } | ||
184 | #endif | 175 | #endif |
185 | 176 | ||
186 | int tipc_media_set_priority(const char *name, u32 new_value); | 177 | int tipc_media_set_priority(const char *name, u32 new_value); |
@@ -194,6 +185,8 @@ void tipc_bearer_remove_dest(struct tipc_bearer *b_ptr, u32 dest); | |||
194 | struct tipc_bearer *tipc_bearer_find(const char *name); | 185 | struct tipc_bearer *tipc_bearer_find(const char *name); |
195 | struct tipc_bearer *tipc_bearer_find_interface(const char *if_name); | 186 | struct tipc_bearer *tipc_bearer_find_interface(const char *if_name); |
196 | struct tipc_media *tipc_media_find(const char *name); | 187 | struct tipc_media *tipc_media_find(const char *name); |
188 | int tipc_bearer_setup(void); | ||
189 | void tipc_bearer_cleanup(void); | ||
197 | void tipc_bearer_stop(void); | 190 | void tipc_bearer_stop(void); |
198 | 191 | ||
199 | /** | 192 | /** |
diff --git a/net/tipc/core.c b/net/tipc/core.c index fd4eeeaa972a..68977c423022 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c | |||
@@ -82,8 +82,7 @@ struct sk_buff *tipc_buf_acquire(u32 size) | |||
82 | static void tipc_core_stop_net(void) | 82 | static void tipc_core_stop_net(void) |
83 | { | 83 | { |
84 | tipc_net_stop(); | 84 | tipc_net_stop(); |
85 | tipc_eth_media_stop(); | 85 | tipc_bearer_cleanup(); |
86 | tipc_ib_media_stop(); | ||
87 | } | 86 | } |
88 | 87 | ||
89 | /** | 88 | /** |
@@ -94,10 +93,7 @@ int tipc_core_start_net(unsigned long addr) | |||
94 | int res; | 93 | int res; |
95 | 94 | ||
96 | tipc_net_start(addr); | 95 | tipc_net_start(addr); |
97 | res = tipc_eth_media_start(); | 96 | res = tipc_bearer_setup(); |
98 | if (res < 0) | ||
99 | goto err; | ||
100 | res = tipc_ib_media_start(); | ||
101 | if (res < 0) | 97 | if (res < 0) |
102 | goto err; | 98 | goto err; |
103 | return res; | 99 | return res; |
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 | */ | ||
52 | struct 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 | |||
61 | static struct eth_media eth_media_array[MAX_ETH_MEDIA]; | ||
62 | static int eth_started; | ||
63 | |||
64 | static int recv_notification(struct notifier_block *nb, unsigned long evt, | ||
65 | void *dv); | ||
66 | static 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 | */ | ||
72 | static struct notifier_block notifier = { | ||
73 | .notifier_call = recv_notification, | ||
74 | .priority = 0 | ||
75 | }; | ||
76 | |||
77 | static 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 | */ | ||
136 | static 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 | */ | ||
165 | static 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 | */ |
173 | static int enable_media(struct tipc_bearer *tb_ptr) | 90 | static 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 = ð_media_array[0]; | ||
177 | struct eth_media *stop = ð_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 | */ | ||
218 | static 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 | */ |
235 | static void disable_media(struct tipc_bearer *tb_ptr) | 120 | static 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 | */ | ||
251 | static 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 | */ | ||
347 | int tipc_eth_media_start(void) | ||
348 | { | ||
349 | int res; | ||
350 | |||
351 | if (eth_started) | ||
352 | return -EINVAL; | ||
353 | |||
354 | res = register_netdevice_notifier(¬ifier); | ||
355 | if (!res) | ||
356 | eth_started = 1; | ||
357 | return res; | ||
358 | } | ||
359 | |||
360 | /** | ||
361 | * tipc_eth_media_stop - deactivate Ethernet bearer support | ||
362 | */ | ||
363 | void tipc_eth_media_stop(void) | ||
364 | { | ||
365 | if (!eth_started) | ||
366 | return; | ||
367 | |||
368 | flush_scheduled_work(); | ||
369 | unregister_netdevice_notifier(¬ifier); | ||
370 | eth_started = 0; | ||
371 | } | ||
diff --git a/net/tipc/ib_media.c b/net/tipc/ib_media.c index 9fdf03cd672b..62d91aeda058 100644 --- a/net/tipc/ib_media.c +++ b/net/tipc/ib_media.c | |||
@@ -42,34 +42,6 @@ | |||
42 | #include "core.h" | 42 | #include "core.h" |
43 | #include "bearer.h" | 43 | #include "bearer.h" |
44 | 44 | ||
45 | #define MAX_IB_MEDIA MAX_BEARERS | ||
46 | |||
47 | /** | ||
48 | * struct ib_media - Infiniband media data structure | ||
49 | * @bearer: ptr to associated "generic" bearer structure | ||
50 | * @dev: ptr to associated Infiniband network device | ||
51 | * @tipc_packet_type: used in binding TIPC to Infiniband driver | ||
52 | * @cleanup: work item used when disabling bearer | ||
53 | */ | ||
54 | |||
55 | struct ib_media { | ||
56 | struct tipc_bearer *bearer; | ||
57 | struct net_device *dev; | ||
58 | struct packet_type tipc_packet_type; | ||
59 | struct work_struct setup; | ||
60 | struct work_struct cleanup; | ||
61 | }; | ||
62 | |||
63 | static struct ib_media ib_media_array[MAX_IB_MEDIA]; | ||
64 | static int ib_started; | ||
65 | static int recv_msg(struct sk_buff *buf, struct net_device *dev, | ||
66 | struct packet_type *pt, struct net_device *orig_dev); | ||
67 | |||
68 | static struct packet_type tipc_packet_type __read_mostly = { | ||
69 | .type = __constant_htons(ETH_P_TIPC), | ||
70 | .func = recv_msg, | ||
71 | }; | ||
72 | |||
73 | /** | 45 | /** |
74 | * ib_media_addr_set - initialize Infiniband media address structure | 46 | * ib_media_addr_set - initialize Infiniband media address structure |
75 | * | 47 | * |
@@ -92,16 +64,14 @@ static int send_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr, | |||
92 | struct tipc_media_addr *dest) | 64 | struct tipc_media_addr *dest) |
93 | { | 65 | { |
94 | struct sk_buff *clone; | 66 | struct sk_buff *clone; |
95 | struct net_device *dev; | ||
96 | int delta; | 67 | int delta; |
68 | struct net_device *dev = tb_ptr->dev; | ||
97 | 69 | ||
98 | clone = skb_clone(buf, GFP_ATOMIC); | 70 | clone = skb_clone(buf, GFP_ATOMIC); |
99 | if (!clone) | 71 | if (!clone) |
100 | return 0; | 72 | return 0; |
101 | 73 | ||
102 | dev = ((struct ib_media *)(tb_ptr->usr_handle))->dev; | ||
103 | delta = dev->hard_header_len - skb_headroom(buf); | 74 | delta = dev->hard_header_len - skb_headroom(buf); |
104 | |||
105 | if ((delta > 0) && | 75 | if ((delta > 0) && |
106 | pskb_expand_head(clone, SKB_DATA_ALIGN(delta), 0, GFP_ATOMIC)) { | 76 | pskb_expand_head(clone, SKB_DATA_ALIGN(delta), 0, GFP_ATOMIC)) { |
107 | kfree_skb(clone); | 77 | kfree_skb(clone); |
@@ -118,79 +88,21 @@ static int send_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr, | |||
118 | } | 88 | } |
119 | 89 | ||
120 | /** | 90 | /** |
121 | * recv_msg - handle incoming TIPC message from an InfiniBand interface | ||
122 | * | ||
123 | * Accept only packets explicitly sent to this node, or broadcast packets; | ||
124 | * ignores packets sent using InfiniBand multicast, and traffic sent to other | ||
125 | * nodes (which can happen if interface is running in promiscuous mode). | ||
126 | */ | ||
127 | static int recv_msg(struct sk_buff *buf, struct net_device *dev, | ||
128 | struct packet_type *pt, struct net_device *orig_dev) | ||
129 | { | ||
130 | struct tipc_bearer *b_ptr; | ||
131 | |||
132 | if (!net_eq(dev_net(dev), &init_net)) { | ||
133 | kfree_skb(buf); | ||
134 | return NET_RX_DROP; | ||
135 | } | ||
136 | |||
137 | rcu_read_lock(); | ||
138 | b_ptr = rcu_dereference(dev->tipc_ptr); | ||
139 | if (likely(b_ptr)) { | ||
140 | if (likely(buf->pkt_type <= PACKET_BROADCAST)) { | ||
141 | buf->next = NULL; | ||
142 | tipc_recv_msg(buf, b_ptr); | ||
143 | rcu_read_unlock(); | ||
144 | return NET_RX_SUCCESS; | ||
145 | } | ||
146 | } | ||
147 | rcu_read_unlock(); | ||
148 | |||
149 | kfree_skb(buf); | ||
150 | return NET_RX_DROP; | ||
151 | } | ||
152 | |||
153 | /** | ||
154 | * setup_bearer - setup association between InfiniBand bearer and interface | ||
155 | */ | ||
156 | static void setup_media(struct work_struct *work) | ||
157 | { | ||
158 | dev_add_pack(&tipc_packet_type); | ||
159 | } | ||
160 | |||
161 | /** | ||
162 | * enable_media - attach TIPC bearer to an InfiniBand interface | 91 | * enable_media - attach TIPC bearer to an InfiniBand interface |
163 | */ | 92 | */ |
164 | static int enable_media(struct tipc_bearer *tb_ptr) | 93 | static int enable_media(struct tipc_bearer *tb_ptr) |
165 | { | 94 | { |
166 | struct net_device *dev; | 95 | struct net_device *dev; |
167 | struct ib_media *ib_ptr = &ib_media_array[0]; | ||
168 | struct ib_media *stop = &ib_media_array[MAX_IB_MEDIA]; | ||
169 | char *driver_name = strchr((const char *)tb_ptr->name, ':') + 1; | 96 | char *driver_name = strchr((const char *)tb_ptr->name, ':') + 1; |
170 | int pending_dev = 0; | ||
171 | |||
172 | /* Find unused InfiniBand bearer structure */ | ||
173 | while (ib_ptr->dev) { | ||
174 | if (!ib_ptr->bearer) | ||
175 | pending_dev++; | ||
176 | if (++ib_ptr == stop) | ||
177 | return pending_dev ? -EAGAIN : -EDQUOT; | ||
178 | } | ||
179 | 97 | ||
180 | /* Find device with specified name */ | 98 | /* Find device with specified name */ |
181 | dev = dev_get_by_name(&init_net, driver_name); | 99 | dev = dev_get_by_name(&init_net, driver_name); |
182 | if (!dev) | 100 | if (!dev) |
183 | return -ENODEV; | 101 | return -ENODEV; |
184 | 102 | ||
185 | /* Create InfiniBand bearer for device */ | ||
186 | ib_ptr->dev = dev; | ||
187 | INIT_WORK(&ib_ptr->setup, setup_media); | ||
188 | schedule_work(&ib_ptr->setup); | ||
189 | |||
190 | /* Associate TIPC bearer with InfiniBand bearer */ | 103 | /* Associate TIPC bearer with InfiniBand bearer */ |
191 | tb_ptr->dev = dev; | 104 | tb_ptr->dev = dev; |
192 | ib_ptr->bearer = tb_ptr; | 105 | tb_ptr->usr_handle = NULL; |
193 | tb_ptr->usr_handle = (void *)ib_ptr; | ||
194 | memset(tb_ptr->bcast_addr.value, 0, sizeof(tb_ptr->bcast_addr.value)); | 106 | memset(tb_ptr->bcast_addr.value, 0, sizeof(tb_ptr->bcast_addr.value)); |
195 | memcpy(tb_ptr->bcast_addr.value, dev->broadcast, INFINIBAND_ALEN); | 107 | memcpy(tb_ptr->bcast_addr.value, dev->broadcast, INFINIBAND_ALEN); |
196 | tb_ptr->bcast_addr.media_id = TIPC_MEDIA_TYPE_IB; | 108 | tb_ptr->bcast_addr.media_id = TIPC_MEDIA_TYPE_IB; |
@@ -202,21 +114,6 @@ static int enable_media(struct tipc_bearer *tb_ptr) | |||
202 | } | 114 | } |
203 | 115 | ||
204 | /** | 116 | /** |
205 | * cleanup_bearer - break association between InfiniBand bearer and interface | ||
206 | * | ||
207 | * This routine must be invoked from a work queue because it can sleep. | ||
208 | */ | ||
209 | static void cleanup_bearer(struct work_struct *work) | ||
210 | { | ||
211 | struct ib_media *ib_ptr = | ||
212 | container_of(work, struct ib_media, cleanup); | ||
213 | |||
214 | dev_remove_pack(&tipc_packet_type); | ||
215 | dev_put(ib_ptr->dev); | ||
216 | ib_ptr->dev = NULL; | ||
217 | } | ||
218 | |||
219 | /** | ||
220 | * disable_media - detach TIPC bearer from an InfiniBand interface | 117 | * disable_media - detach TIPC bearer from an InfiniBand interface |
221 | * | 118 | * |
222 | * Mark InfiniBand bearer as inactive so that incoming buffers are thrown away, | 119 | * Mark InfiniBand bearer as inactive so that incoming buffers are thrown away, |
@@ -225,63 +122,11 @@ static void cleanup_bearer(struct work_struct *work) | |||
225 | */ | 122 | */ |
226 | static void disable_media(struct tipc_bearer *tb_ptr) | 123 | static void disable_media(struct tipc_bearer *tb_ptr) |
227 | { | 124 | { |
228 | struct ib_media *ib_ptr = (struct ib_media *)tb_ptr->usr_handle; | ||
229 | |||
230 | ib_ptr->bearer = NULL; | ||
231 | INIT_WORK(&ib_ptr->cleanup, cleanup_bearer); | ||
232 | schedule_work(&ib_ptr->cleanup); | ||
233 | RCU_INIT_POINTER(tb_ptr->dev->tipc_ptr, NULL); | 125 | RCU_INIT_POINTER(tb_ptr->dev->tipc_ptr, NULL); |
126 | dev_put(tb_ptr->dev); | ||
234 | } | 127 | } |
235 | 128 | ||
236 | /** | 129 | /** |
237 | * recv_notification - handle device updates from OS | ||
238 | * | ||
239 | * Change the state of the InfiniBand bearer (if any) associated with the | ||
240 | * specified device. | ||
241 | */ | ||
242 | static int recv_notification(struct notifier_block *nb, unsigned long evt, | ||
243 | void *ptr) | ||
244 | { | ||
245 | struct tipc_bearer *b_ptr; | ||
246 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); | ||
247 | |||
248 | if (!net_eq(dev_net(dev), &init_net)) | ||
249 | return NOTIFY_DONE; | ||
250 | |||
251 | rcu_read_lock(); | ||
252 | b_ptr = rcu_dereference(dev->tipc_ptr); | ||
253 | if (!b_ptr) { | ||
254 | rcu_read_unlock(); | ||
255 | return NOTIFY_DONE; /* bearer had been disabled */ | ||
256 | } | ||
257 | |||
258 | b_ptr->mtu = dev->mtu; | ||
259 | |||
260 | switch (evt) { | ||
261 | case NETDEV_CHANGE: | ||
262 | if (netif_carrier_ok(dev)) | ||
263 | break; | ||
264 | case NETDEV_DOWN: | ||
265 | case NETDEV_CHANGEMTU: | ||
266 | case NETDEV_CHANGEADDR: | ||
267 | tipc_reset_bearer(b_ptr); | ||
268 | break; | ||
269 | case NETDEV_UNREGISTER: | ||
270 | case NETDEV_CHANGENAME: | ||
271 | tipc_disable_bearer(b_ptr->name); | ||
272 | break; | ||
273 | } | ||
274 | rcu_read_unlock(); | ||
275 | |||
276 | return NOTIFY_OK; | ||
277 | } | ||
278 | |||
279 | static struct notifier_block notifier = { | ||
280 | .notifier_call = recv_notification, | ||
281 | .priority = 0, | ||
282 | }; | ||
283 | |||
284 | /** | ||
285 | * ib_addr2str - convert InfiniBand address to string | 130 | * ib_addr2str - convert InfiniBand address to string |
286 | */ | 131 | */ |
287 | static int ib_addr2str(struct tipc_media_addr *a, char *str_buf, int str_size) | 132 | static int ib_addr2str(struct tipc_media_addr *a, char *str_buf, int str_size) |
@@ -332,34 +177,3 @@ struct tipc_media ib_media_info = { | |||
332 | .name = "ib" | 177 | .name = "ib" |
333 | }; | 178 | }; |
334 | 179 | ||
335 | /** | ||
336 | * tipc_ib_media_start - activate InfiniBand bearer support | ||
337 | * | ||
338 | * Register InfiniBand media type with TIPC bearer code. Also register | ||
339 | * with OS for notifications about device state changes. | ||
340 | */ | ||
341 | int tipc_ib_media_start(void) | ||
342 | { | ||
343 | int res; | ||
344 | |||
345 | if (ib_started) | ||
346 | return -EINVAL; | ||
347 | |||
348 | res = register_netdevice_notifier(¬ifier); | ||
349 | if (!res) | ||
350 | ib_started = 1; | ||
351 | return res; | ||
352 | } | ||
353 | |||
354 | /** | ||
355 | * tipc_ib_media_stop - deactivate InfiniBand bearer support | ||
356 | */ | ||
357 | void tipc_ib_media_stop(void) | ||
358 | { | ||
359 | if (!ib_started) | ||
360 | return; | ||
361 | |||
362 | flush_scheduled_work(); | ||
363 | unregister_netdevice_notifier(¬ifier); | ||
364 | ib_started = 0; | ||
365 | } | ||