aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/netdevice.h3
-rw-r--r--net/tipc/bearer.h2
-rw-r--r--net/tipc/eth_media.c55
-rw-r--r--net/tipc/ib_media.c54
4 files changed, 68 insertions, 46 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 9d55e5188b96..0ca8100f9fbc 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1283,6 +1283,9 @@ struct net_device {
1283#if IS_ENABLED(CONFIG_NET_DSA) 1283#if IS_ENABLED(CONFIG_NET_DSA)
1284 struct dsa_switch_tree *dsa_ptr; /* dsa specific data */ 1284 struct dsa_switch_tree *dsa_ptr; /* dsa specific data */
1285#endif 1285#endif
1286#if IS_ENABLED(CONFIG_TIPC)
1287 struct tipc_bearer __rcu *tipc_ptr; /* TIPC specific data */
1288#endif
1286 void *atalk_ptr; /* AppleTalk link */ 1289 void *atalk_ptr; /* AppleTalk link */
1287 struct in_device __rcu *ip_ptr; /* IPv4 specific data */ 1290 struct in_device __rcu *ip_ptr; /* IPv4 specific data */
1288 struct dn_dev __rcu *dn_ptr; /* DECnet specific data */ 1291 struct dn_dev __rcu *dn_ptr; /* DECnet specific data */
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h
index e50266aa4d10..91b8d8b92373 100644
--- a/net/tipc/bearer.h
+++ b/net/tipc/bearer.h
@@ -105,6 +105,7 @@ struct tipc_media {
105 105
106/** 106/**
107 * struct tipc_bearer - Generic TIPC bearer structure 107 * struct tipc_bearer - Generic TIPC bearer structure
108 * @dev: ptr to associated network device
108 * @usr_handle: pointer to additional media-specific information about bearer 109 * @usr_handle: pointer to additional media-specific information about bearer
109 * @mtu: max packet size bearer can support 110 * @mtu: max packet size bearer can support
110 * @lock: spinlock for controlling access to bearer 111 * @lock: spinlock for controlling access to bearer
@@ -127,6 +128,7 @@ struct tipc_media {
127 * care of initializing all other fields. 128 * care of initializing all other fields.
128 */ 129 */
129struct tipc_bearer { 130struct tipc_bearer {
131 struct net_device *dev;
130 void *usr_handle; /* initalized by media */ 132 void *usr_handle; /* initalized by media */
131 u32 mtu; /* initalized by media */ 133 u32 mtu; /* initalized by media */
132 struct tipc_media_addr addr; /* initalized by media */ 134 struct tipc_media_addr addr; /* initalized by media */
diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c
index 37fb145476ec..c5f685dee15b 100644
--- a/net/tipc/eth_media.c
+++ b/net/tipc/eth_media.c
@@ -63,6 +63,9 @@ static int eth_started;
63 63
64static int recv_notification(struct notifier_block *nb, unsigned long evt, 64static int recv_notification(struct notifier_block *nb, unsigned long evt,
65 void *dv); 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
66/* 69/*
67 * Network device notifier info 70 * Network device notifier info
68 */ 71 */
@@ -71,6 +74,11 @@ static struct notifier_block notifier = {
71 .priority = 0 74 .priority = 0
72}; 75};
73 76
77static struct packet_type tipc_packet_type __read_mostly = {
78 .type = __constant_htons(ETH_P_TIPC),
79 .func = recv_msg,
80};
81
74/** 82/**
75 * eth_media_addr_set - initialize Ethernet media address structure 83 * eth_media_addr_set - initialize Ethernet media address structure
76 * 84 *
@@ -128,20 +136,25 @@ static int send_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr,
128static int recv_msg(struct sk_buff *buf, struct net_device *dev, 136static int recv_msg(struct sk_buff *buf, struct net_device *dev,
129 struct packet_type *pt, struct net_device *orig_dev) 137 struct packet_type *pt, struct net_device *orig_dev)
130{ 138{
131 struct eth_media *eb_ptr = (struct eth_media *)pt->af_packet_priv; 139 struct tipc_bearer *b_ptr;
132 140
133 if (!net_eq(dev_net(dev), &init_net)) { 141 if (!net_eq(dev_net(dev), &init_net)) {
134 kfree_skb(buf); 142 kfree_skb(buf);
135 return NET_RX_DROP; 143 return NET_RX_DROP;
136 } 144 }
137 145
138 if (likely(eb_ptr->bearer)) { 146 rcu_read_lock();
147 b_ptr = rcu_dereference(dev->tipc_ptr);
148 if (likely(b_ptr)) {
139 if (likely(buf->pkt_type <= PACKET_BROADCAST)) { 149 if (likely(buf->pkt_type <= PACKET_BROADCAST)) {
140 buf->next = NULL; 150 buf->next = NULL;
141 tipc_recv_msg(buf, eb_ptr->bearer); 151 tipc_recv_msg(buf, b_ptr);
152 rcu_read_unlock();
142 return NET_RX_SUCCESS; 153 return NET_RX_SUCCESS;
143 } 154 }
144 } 155 }
156 rcu_read_unlock();
157
145 kfree_skb(buf); 158 kfree_skb(buf);
146 return NET_RX_DROP; 159 return NET_RX_DROP;
147} 160}
@@ -151,10 +164,7 @@ static int recv_msg(struct sk_buff *buf, struct net_device *dev,
151 */ 164 */
152static void setup_media(struct work_struct *work) 165static void setup_media(struct work_struct *work)
153{ 166{
154 struct eth_media *eb_ptr = 167 dev_add_pack(&tipc_packet_type);
155 container_of(work, struct eth_media, setup);
156
157 dev_add_pack(&eb_ptr->tipc_packet_type);
158} 168}
159 169
160/** 170/**
@@ -183,15 +193,11 @@ static int enable_media(struct tipc_bearer *tb_ptr)
183 193
184 /* Create Ethernet bearer for device */ 194 /* Create Ethernet bearer for device */
185 eb_ptr->dev = dev; 195 eb_ptr->dev = dev;
186 eb_ptr->tipc_packet_type.type = htons(ETH_P_TIPC);
187 eb_ptr->tipc_packet_type.dev = dev;
188 eb_ptr->tipc_packet_type.func = recv_msg;
189 eb_ptr->tipc_packet_type.af_packet_priv = eb_ptr;
190 INIT_LIST_HEAD(&(eb_ptr->tipc_packet_type.list));
191 INIT_WORK(&eb_ptr->setup, setup_media); 196 INIT_WORK(&eb_ptr->setup, setup_media);
192 schedule_work(&eb_ptr->setup); 197 schedule_work(&eb_ptr->setup);
193 198
194 /* Associate TIPC bearer with Ethernet bearer */ 199 /* Associate TIPC bearer with Ethernet bearer */
200 tb_ptr->dev = dev;
195 eb_ptr->bearer = tb_ptr; 201 eb_ptr->bearer = tb_ptr;
196 tb_ptr->usr_handle = (void *)eb_ptr; 202 tb_ptr->usr_handle = (void *)eb_ptr;
197 memset(tb_ptr->bcast_addr.value, 0, sizeof(tb_ptr->bcast_addr.value)); 203 memset(tb_ptr->bcast_addr.value, 0, sizeof(tb_ptr->bcast_addr.value));
@@ -200,6 +206,7 @@ static int enable_media(struct tipc_bearer *tb_ptr)
200 tb_ptr->bcast_addr.broadcast = 1; 206 tb_ptr->bcast_addr.broadcast = 1;
201 tb_ptr->mtu = dev->mtu; 207 tb_ptr->mtu = dev->mtu;
202 eth_media_addr_set(tb_ptr, &tb_ptr->addr, (char *)dev->dev_addr); 208 eth_media_addr_set(tb_ptr, &tb_ptr->addr, (char *)dev->dev_addr);
209 rcu_assign_pointer(dev->tipc_ptr, tb_ptr);
203 return 0; 210 return 0;
204} 211}
205 212
@@ -213,7 +220,7 @@ static void cleanup_media(struct work_struct *work)
213 struct eth_media *eb_ptr = 220 struct eth_media *eb_ptr =
214 container_of(work, struct eth_media, cleanup); 221 container_of(work, struct eth_media, cleanup);
215 222
216 dev_remove_pack(&eb_ptr->tipc_packet_type); 223 dev_remove_pack(&tipc_packet_type);
217 dev_put(eb_ptr->dev); 224 dev_put(eb_ptr->dev);
218 eb_ptr->dev = NULL; 225 eb_ptr->dev = NULL;
219} 226}
@@ -232,6 +239,7 @@ static void disable_media(struct tipc_bearer *tb_ptr)
232 eb_ptr->bearer = NULL; 239 eb_ptr->bearer = NULL;
233 INIT_WORK(&eb_ptr->cleanup, cleanup_media); 240 INIT_WORK(&eb_ptr->cleanup, cleanup_media);
234 schedule_work(&eb_ptr->cleanup); 241 schedule_work(&eb_ptr->cleanup);
242 RCU_INIT_POINTER(tb_ptr->dev->tipc_ptr, NULL);
235} 243}
236 244
237/** 245/**
@@ -243,21 +251,20 @@ static void disable_media(struct tipc_bearer *tb_ptr)
243static int recv_notification(struct notifier_block *nb, unsigned long evt, 251static int recv_notification(struct notifier_block *nb, unsigned long evt,
244 void *ptr) 252 void *ptr)
245{ 253{
254 struct tipc_bearer *b_ptr;
246 struct net_device *dev = netdev_notifier_info_to_dev(ptr); 255 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
247 struct eth_media *eb_ptr = &eth_media_array[0];
248 struct eth_media *stop = &eth_media_array[MAX_ETH_MEDIA];
249 256
250 if (!net_eq(dev_net(dev), &init_net)) 257 if (!net_eq(dev_net(dev), &init_net))
251 return NOTIFY_DONE; 258 return NOTIFY_DONE;
252 259
253 while ((eb_ptr->dev != dev)) { 260 rcu_read_lock();
254 if (++eb_ptr == stop) 261 b_ptr = rcu_dereference(dev->tipc_ptr);
255 return NOTIFY_DONE; /* couldn't find device */ 262 if (!b_ptr) {
256 } 263 rcu_read_unlock();
257 if (!eb_ptr->bearer)
258 return NOTIFY_DONE; /* bearer had been disabled */ 264 return NOTIFY_DONE; /* bearer had been disabled */
265 }
259 266
260 eb_ptr->bearer->mtu = dev->mtu; 267 b_ptr->mtu = dev->mtu;
261 268
262 switch (evt) { 269 switch (evt) {
263 case NETDEV_CHANGE: 270 case NETDEV_CHANGE:
@@ -266,13 +273,15 @@ static int recv_notification(struct notifier_block *nb, unsigned long evt,
266 case NETDEV_DOWN: 273 case NETDEV_DOWN:
267 case NETDEV_CHANGEMTU: 274 case NETDEV_CHANGEMTU:
268 case NETDEV_CHANGEADDR: 275 case NETDEV_CHANGEADDR:
269 tipc_reset_bearer(eb_ptr->bearer); 276 tipc_reset_bearer(b_ptr);
270 break; 277 break;
271 case NETDEV_UNREGISTER: 278 case NETDEV_UNREGISTER:
272 case NETDEV_CHANGENAME: 279 case NETDEV_CHANGENAME:
273 tipc_disable_bearer(eb_ptr->bearer->name); 280 tipc_disable_bearer(b_ptr->name);
274 break; 281 break;
275 } 282 }
283 rcu_read_unlock();
284
276 return NOTIFY_OK; 285 return NOTIFY_OK;
277} 286}
278 287
diff --git a/net/tipc/ib_media.c b/net/tipc/ib_media.c
index 48e1c07842e6..9fdf03cd672b 100644
--- a/net/tipc/ib_media.c
+++ b/net/tipc/ib_media.c
@@ -62,6 +62,13 @@ struct ib_media {
62 62
63static struct ib_media ib_media_array[MAX_IB_MEDIA]; 63static struct ib_media ib_media_array[MAX_IB_MEDIA];
64static int ib_started; 64static int ib_started;
65static int recv_msg(struct sk_buff *buf, struct net_device *dev,
66 struct packet_type *pt, struct net_device *orig_dev);
67
68static struct packet_type tipc_packet_type __read_mostly = {
69 .type = __constant_htons(ETH_P_TIPC),
70 .func = recv_msg,
71};
65 72
66/** 73/**
67 * ib_media_addr_set - initialize Infiniband media address structure 74 * ib_media_addr_set - initialize Infiniband media address structure
@@ -120,20 +127,25 @@ static int send_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr,
120static int recv_msg(struct sk_buff *buf, struct net_device *dev, 127static int recv_msg(struct sk_buff *buf, struct net_device *dev,
121 struct packet_type *pt, struct net_device *orig_dev) 128 struct packet_type *pt, struct net_device *orig_dev)
122{ 129{
123 struct ib_media *ib_ptr = (struct ib_media *)pt->af_packet_priv; 130 struct tipc_bearer *b_ptr;
124 131
125 if (!net_eq(dev_net(dev), &init_net)) { 132 if (!net_eq(dev_net(dev), &init_net)) {
126 kfree_skb(buf); 133 kfree_skb(buf);
127 return NET_RX_DROP; 134 return NET_RX_DROP;
128 } 135 }
129 136
130 if (likely(ib_ptr->bearer)) { 137 rcu_read_lock();
138 b_ptr = rcu_dereference(dev->tipc_ptr);
139 if (likely(b_ptr)) {
131 if (likely(buf->pkt_type <= PACKET_BROADCAST)) { 140 if (likely(buf->pkt_type <= PACKET_BROADCAST)) {
132 buf->next = NULL; 141 buf->next = NULL;
133 tipc_recv_msg(buf, ib_ptr->bearer); 142 tipc_recv_msg(buf, b_ptr);
143 rcu_read_unlock();
134 return NET_RX_SUCCESS; 144 return NET_RX_SUCCESS;
135 } 145 }
136 } 146 }
147 rcu_read_unlock();
148
137 kfree_skb(buf); 149 kfree_skb(buf);
138 return NET_RX_DROP; 150 return NET_RX_DROP;
139} 151}
@@ -143,10 +155,7 @@ static int recv_msg(struct sk_buff *buf, struct net_device *dev,
143 */ 155 */
144static void setup_media(struct work_struct *work) 156static void setup_media(struct work_struct *work)
145{ 157{
146 struct ib_media *ib_ptr = 158 dev_add_pack(&tipc_packet_type);
147 container_of(work, struct ib_media, setup);
148
149 dev_add_pack(&ib_ptr->tipc_packet_type);
150} 159}
151 160
152/** 161/**
@@ -175,15 +184,11 @@ static int enable_media(struct tipc_bearer *tb_ptr)
175 184
176 /* Create InfiniBand bearer for device */ 185 /* Create InfiniBand bearer for device */
177 ib_ptr->dev = dev; 186 ib_ptr->dev = dev;
178 ib_ptr->tipc_packet_type.type = htons(ETH_P_TIPC);
179 ib_ptr->tipc_packet_type.dev = dev;
180 ib_ptr->tipc_packet_type.func = recv_msg;
181 ib_ptr->tipc_packet_type.af_packet_priv = ib_ptr;
182 INIT_LIST_HEAD(&(ib_ptr->tipc_packet_type.list));
183 INIT_WORK(&ib_ptr->setup, setup_media); 187 INIT_WORK(&ib_ptr->setup, setup_media);
184 schedule_work(&ib_ptr->setup); 188 schedule_work(&ib_ptr->setup);
185 189
186 /* Associate TIPC bearer with InfiniBand bearer */ 190 /* Associate TIPC bearer with InfiniBand bearer */
191 tb_ptr->dev = dev;
187 ib_ptr->bearer = tb_ptr; 192 ib_ptr->bearer = tb_ptr;
188 tb_ptr->usr_handle = (void *)ib_ptr; 193 tb_ptr->usr_handle = (void *)ib_ptr;
189 memset(tb_ptr->bcast_addr.value, 0, sizeof(tb_ptr->bcast_addr.value)); 194 memset(tb_ptr->bcast_addr.value, 0, sizeof(tb_ptr->bcast_addr.value));
@@ -192,6 +197,7 @@ static int enable_media(struct tipc_bearer *tb_ptr)
192 tb_ptr->bcast_addr.broadcast = 1; 197 tb_ptr->bcast_addr.broadcast = 1;
193 tb_ptr->mtu = dev->mtu; 198 tb_ptr->mtu = dev->mtu;
194 ib_media_addr_set(tb_ptr, &tb_ptr->addr, (char *)dev->dev_addr); 199 ib_media_addr_set(tb_ptr, &tb_ptr->addr, (char *)dev->dev_addr);
200 rcu_assign_pointer(dev->tipc_ptr, tb_ptr);
195 return 0; 201 return 0;
196} 202}
197 203
@@ -205,7 +211,7 @@ static void cleanup_bearer(struct work_struct *work)
205 struct ib_media *ib_ptr = 211 struct ib_media *ib_ptr =
206 container_of(work, struct ib_media, cleanup); 212 container_of(work, struct ib_media, cleanup);
207 213
208 dev_remove_pack(&ib_ptr->tipc_packet_type); 214 dev_remove_pack(&tipc_packet_type);
209 dev_put(ib_ptr->dev); 215 dev_put(ib_ptr->dev);
210 ib_ptr->dev = NULL; 216 ib_ptr->dev = NULL;
211} 217}
@@ -224,6 +230,7 @@ static void disable_media(struct tipc_bearer *tb_ptr)
224 ib_ptr->bearer = NULL; 230 ib_ptr->bearer = NULL;
225 INIT_WORK(&ib_ptr->cleanup, cleanup_bearer); 231 INIT_WORK(&ib_ptr->cleanup, cleanup_bearer);
226 schedule_work(&ib_ptr->cleanup); 232 schedule_work(&ib_ptr->cleanup);
233 RCU_INIT_POINTER(tb_ptr->dev->tipc_ptr, NULL);
227} 234}
228 235
229/** 236/**
@@ -235,21 +242,20 @@ static void disable_media(struct tipc_bearer *tb_ptr)
235static int recv_notification(struct notifier_block *nb, unsigned long evt, 242static int recv_notification(struct notifier_block *nb, unsigned long evt,
236 void *ptr) 243 void *ptr)
237{ 244{
245 struct tipc_bearer *b_ptr;
238 struct net_device *dev = netdev_notifier_info_to_dev(ptr); 246 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
239 struct ib_media *ib_ptr = &ib_media_array[0];
240 struct ib_media *stop = &ib_media_array[MAX_IB_MEDIA];
241 247
242 if (!net_eq(dev_net(dev), &init_net)) 248 if (!net_eq(dev_net(dev), &init_net))
243 return NOTIFY_DONE; 249 return NOTIFY_DONE;
244 250
245 while ((ib_ptr->dev != dev)) { 251 rcu_read_lock();
246 if (++ib_ptr == stop) 252 b_ptr = rcu_dereference(dev->tipc_ptr);
247 return NOTIFY_DONE; /* couldn't find device */ 253 if (!b_ptr) {
248 } 254 rcu_read_unlock();
249 if (!ib_ptr->bearer)
250 return NOTIFY_DONE; /* bearer had been disabled */ 255 return NOTIFY_DONE; /* bearer had been disabled */
256 }
251 257
252 ib_ptr->bearer->mtu = dev->mtu; 258 b_ptr->mtu = dev->mtu;
253 259
254 switch (evt) { 260 switch (evt) {
255 case NETDEV_CHANGE: 261 case NETDEV_CHANGE:
@@ -258,13 +264,15 @@ static int recv_notification(struct notifier_block *nb, unsigned long evt,
258 case NETDEV_DOWN: 264 case NETDEV_DOWN:
259 case NETDEV_CHANGEMTU: 265 case NETDEV_CHANGEMTU:
260 case NETDEV_CHANGEADDR: 266 case NETDEV_CHANGEADDR:
261 tipc_reset_bearer(ib_ptr->bearer); 267 tipc_reset_bearer(b_ptr);
262 break; 268 break;
263 case NETDEV_UNREGISTER: 269 case NETDEV_UNREGISTER:
264 case NETDEV_CHANGENAME: 270 case NETDEV_CHANGENAME:
265 tipc_disable_bearer(ib_ptr->bearer->name); 271 tipc_disable_bearer(b_ptr->name);
266 break; 272 break;
267 } 273 }
274 rcu_read_unlock();
275
268 return NOTIFY_OK; 276 return NOTIFY_OK;
269} 277}
270 278