Skip to content

Commit 51f3c60

Browse files
Arvid Brodindavem330
Arvid Brodin
authored andcommitted
net/hsr: Move slave init to hsr_slave.c.
Also try to prevent some possible slave dereference race conditions. This is finalized in the next patch, which abandons the slave array in favour of a list_head list and list RCU. Signed-off-by: Arvid Brodin <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent e9aae56 commit 51f3c60

File tree

6 files changed

+205
-164
lines changed

6 files changed

+205
-164
lines changed

net/hsr/hsr_device.c

+55-137
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
#include <linux/netdevice.h>
1616
#include <linux/skbuff.h>
1717
#include <linux/etherdevice.h>
18-
#include <linux/if_arp.h>
1918
#include <linux/rtnetlink.h>
2019
#include <linux/pkt_sched.h>
2120
#include "hsr_device.h"
@@ -108,23 +107,27 @@ void hsr_check_carrier_and_operstate(struct hsr_priv *hsr)
108107
hsr_check_announce(hsr->dev, old_operstate);
109108
}
110109

111-
112110
int hsr_get_max_mtu(struct hsr_priv *hsr)
113111
{
114-
int mtu_max;
115-
116-
if (hsr->slave[0] && hsr->slave[1])
117-
mtu_max = min(hsr->slave[0]->mtu, hsr->slave[1]->mtu);
118-
else if (hsr->slave[0])
119-
mtu_max = hsr->slave[0]->mtu;
120-
else if (hsr->slave[1])
121-
mtu_max = hsr->slave[1]->mtu;
122-
else
123-
mtu_max = HSR_HLEN;
124-
112+
unsigned int mtu_max;
113+
struct net_device *slave;
114+
115+
mtu_max = ETH_DATA_LEN;
116+
rcu_read_lock();
117+
slave = hsr->slave[0];
118+
if (slave)
119+
mtu_max = min(slave->mtu, mtu_max);
120+
slave = hsr->slave[1];
121+
if (slave)
122+
mtu_max = min(slave->mtu, mtu_max);
123+
rcu_read_unlock();
124+
125+
if (mtu_max < HSR_HLEN)
126+
return 0;
125127
return mtu_max - HSR_HLEN;
126128
}
127129

130+
128131
static int hsr_dev_change_mtu(struct net_device *dev, int new_mtu)
129132
{
130133
struct hsr_priv *hsr;
@@ -145,18 +148,20 @@ static int hsr_dev_change_mtu(struct net_device *dev, int new_mtu)
145148
static int hsr_dev_open(struct net_device *dev)
146149
{
147150
struct hsr_priv *hsr;
151+
struct net_device *slave;
148152
int i;
149153
char *slave_name;
150154

151155
hsr = netdev_priv(dev);
152156

153157
for (i = 0; i < HSR_MAX_SLAVE; i++) {
154-
if (hsr->slave[i])
155-
slave_name = hsr->slave[i]->name;
158+
slave = hsr->slave[i];
159+
if (slave)
160+
slave_name = slave->name;
156161
else
157162
slave_name = "null";
158163

159-
if (!is_slave_up(hsr->slave[i]))
164+
if (!is_slave_up(slave))
160165
netdev_warn(dev, "Slave %c (%s) is not up; please bring it up to get a working HSR network\n",
161166
'A' + i, slave_name);
162167
}
@@ -223,6 +228,8 @@ static int slave_xmit(struct sk_buff *skb, struct hsr_priv *hsr,
223228
hsr_ethhdr = (struct hsr_ethhdr *) skb->data;
224229

225230
skb->dev = hsr->slave[dev_idx];
231+
if (unlikely(!skb->dev))
232+
return NET_XMIT_DROP;
226233

227234
hsr_addr_subst_dest(hsr, &hsr_ethhdr->ethhdr, dev_idx);
228235

@@ -252,14 +259,8 @@ static int hsr_dev_xmit(struct sk_buff *skb, struct net_device *dev)
252259
}
253260

254261
skb2 = pskb_copy(skb, GFP_ATOMIC);
255-
256-
res1 = NET_XMIT_DROP;
257-
if (likely(hsr->slave[HSR_DEV_SLAVE_A]))
258-
res1 = slave_xmit(skb, hsr, HSR_DEV_SLAVE_A);
259-
260-
res2 = NET_XMIT_DROP;
261-
if (likely(skb2 && hsr->slave[HSR_DEV_SLAVE_B]))
262-
res2 = slave_xmit(skb2, hsr, HSR_DEV_SLAVE_B);
262+
res1 = slave_xmit(skb, hsr, HSR_DEV_SLAVE_A);
263+
res2 = slave_xmit(skb2, hsr, HSR_DEV_SLAVE_B);
263264

264265
if (likely(res1 == NET_XMIT_SUCCESS || res1 == NET_XMIT_CN ||
265266
res2 == NET_XMIT_SUCCESS || res2 == NET_XMIT_CN)) {
@@ -406,28 +407,10 @@ static void hsr_announce(unsigned long data)
406407
static void restore_slaves(struct net_device *hsr_dev)
407408
{
408409
struct hsr_priv *hsr;
409-
int i;
410-
int res;
411410

412411
hsr = netdev_priv(hsr_dev);
413-
414-
rtnl_lock();
415-
416-
for (i = 0; i < HSR_MAX_SLAVE; i++) {
417-
if (!hsr->slave[i])
418-
continue;
419-
res = dev_set_promiscuity(hsr->slave[i], -1);
420-
if (res)
421-
netdev_info(hsr_dev,
422-
"Cannot restore slave promiscuity (%s, %d)\n",
423-
hsr->slave[i]->name, res);
424-
425-
if (hsr->slave[i]->rx_handler == hsr_handle_frame)
426-
netdev_rx_handler_unregister(hsr->slave[i]);
427-
}
428-
429-
430-
rtnl_unlock();
412+
hsr_del_slave(hsr, 1);
413+
hsr_del_slave(hsr, 0);
431414
}
432415

433416
static void reclaim_hsr_dev(struct rcu_head *rh)
@@ -483,38 +466,6 @@ bool is_hsr_master(struct net_device *dev)
483466
return (dev->netdev_ops->ndo_start_xmit == hsr_dev_xmit);
484467
}
485468

486-
static int check_slave_ok(struct net_device *dev)
487-
{
488-
/* Don't allow HSR on non-ethernet like devices */
489-
if ((dev->flags & IFF_LOOPBACK) || (dev->type != ARPHRD_ETHER) ||
490-
(dev->addr_len != ETH_ALEN)) {
491-
netdev_info(dev, "Cannot use loopback or non-ethernet device as HSR slave.\n");
492-
return -EINVAL;
493-
}
494-
495-
/* Don't allow enslaving hsr devices */
496-
if (is_hsr_master(dev)) {
497-
netdev_info(dev, "Cannot create trees of HSR devices.\n");
498-
return -EINVAL;
499-
}
500-
501-
if (is_hsr_slave(dev)) {
502-
netdev_info(dev, "This device is already a HSR slave.\n");
503-
return -EINVAL;
504-
}
505-
506-
if (dev->priv_flags & IFF_802_1Q_VLAN) {
507-
netdev_info(dev, "HSR on top of VLAN is not yet supported in this driver.\n");
508-
return -EINVAL;
509-
}
510-
511-
/* HSR over bonded devices has not been tested, but I'm not sure it
512-
* won't work...
513-
*/
514-
515-
return 0;
516-
}
517-
518469

519470
/* Default multicast address for HSR Supervision frames */
520471
static const unsigned char def_multicast_addr[ETH_ALEN] __aligned(2) = {
@@ -525,15 +476,30 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2],
525476
unsigned char multicast_spec)
526477
{
527478
struct hsr_priv *hsr;
528-
int i;
529479
int res;
530480

531481
hsr = netdev_priv(hsr_dev);
532482
hsr->dev = hsr_dev;
483+
hsr->slave[0] = NULL;
484+
hsr->slave[1] = NULL;
533485
INIT_LIST_HEAD(&hsr->node_db);
534486
INIT_LIST_HEAD(&hsr->self_node_db);
535-
for (i = 0; i < HSR_MAX_SLAVE; i++)
536-
hsr->slave[i] = slave[i];
487+
488+
ether_addr_copy(hsr_dev->dev_addr, slave[0]->dev_addr);
489+
490+
/* Make sure we recognize frames from ourselves in hsr_rcv() */
491+
res = hsr_create_self_node(&hsr->self_node_db, hsr_dev->dev_addr,
492+
slave[1]->dev_addr);
493+
if (res < 0)
494+
return res;
495+
496+
hsr_dev->features = slave[0]->features & slave[1]->features;
497+
/* Prevent recursive tx locking */
498+
hsr_dev->features |= NETIF_F_LLTX;
499+
/* VLAN on top of HSR needs testing and probably some work on
500+
* hsr_header_create() etc.
501+
*/
502+
hsr_dev->features |= NETIF_F_VLAN_CHALLENGED;
537503

538504
spin_lock_init(&hsr->seqnr_lock);
539505
/* Overflow soon to find bugs easier: */
@@ -560,74 +526,26 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2],
560526
* IFF_HSR_MASTER/SLAVE?
561527
*/
562528

563-
for (i = 0; i < HSR_MAX_SLAVE; i++) {
564-
res = check_slave_ok(slave[i]);
565-
if (res)
566-
return res;
567-
}
568-
569-
hsr_dev->features = slave[0]->features & slave[1]->features;
570-
/* Prevent recursive tx locking */
571-
hsr_dev->features |= NETIF_F_LLTX;
572-
/* VLAN on top of HSR needs testing and probably some work on
573-
* hsr_header_create() etc.
574-
*/
575-
hsr_dev->features |= NETIF_F_VLAN_CHALLENGED;
576-
577-
/* Set hsr_dev's MAC address to that of mac_slave1 */
578-
ether_addr_copy(hsr_dev->dev_addr, hsr->slave[0]->dev_addr);
579-
580-
/* Set required header length */
581-
for (i = 0; i < HSR_MAX_SLAVE; i++) {
582-
if (slave[i]->hard_header_len + HSR_HLEN >
583-
hsr_dev->hard_header_len)
584-
hsr_dev->hard_header_len =
585-
slave[i]->hard_header_len + HSR_HLEN;
586-
}
587-
588-
/* MTU */
589-
for (i = 0; i < HSR_MAX_SLAVE; i++)
590-
if (slave[i]->mtu - HSR_HLEN < hsr_dev->mtu)
591-
hsr_dev->mtu = slave[i]->mtu - HSR_HLEN;
592-
593529
/* Make sure the 1st call to netif_carrier_on() gets through */
594530
netif_carrier_off(hsr_dev);
595531

596-
/* Promiscuity */
597-
for (i = 0; i < HSR_MAX_SLAVE; i++) {
598-
res = dev_set_promiscuity(slave[i], 1);
599-
if (res) {
600-
netdev_info(hsr_dev, "Cannot set slave promiscuity (%s, %d)\n",
601-
slave[i]->name, res);
602-
goto fail;
603-
}
604-
}
605-
606-
for (i = 0; i < HSR_MAX_SLAVE; i++) {
607-
res = netdev_rx_handler_register(slave[i], hsr_handle_frame,
608-
hsr);
609-
if (res)
610-
goto fail;
611-
}
612-
613-
/* Make sure we recognize frames from ourselves in hsr_rcv() */
614-
res = hsr_create_self_node(&hsr->self_node_db, hsr_dev->dev_addr,
615-
hsr->slave[1]->dev_addr);
616-
if (res < 0)
617-
goto fail;
618-
619532
res = register_netdevice(hsr_dev);
620533
if (res)
621-
goto fail;
534+
return res;
535+
536+
res = hsr_add_slave(hsr, slave[0], 0);
537+
if (res)
538+
return res;
539+
res = hsr_add_slave(hsr, slave[1], 1);
540+
if (res) {
541+
hsr_del_slave(hsr, 0);
542+
return res;
543+
}
622544

623545
hsr->prune_timer.expires = jiffies + msecs_to_jiffies(PRUNE_PERIOD);
624546
add_timer(&hsr->prune_timer);
625547

626548
register_hsr_master(hsr);
627549

628550
return 0;
629-
630-
fail:
631-
restore_slaves(hsr_dev);
632-
return res;
633551
}

net/hsr/hsr_framereg.c

+4-2
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,7 @@ int hsr_get_node_data(struct hsr_priv *hsr,
455455
u16 *if2_seq)
456456
{
457457
struct hsr_node *node;
458+
struct net_device *slave;
458459
unsigned long tdiff;
459460

460461

@@ -491,8 +492,9 @@ int hsr_get_node_data(struct hsr_priv *hsr,
491492
*if1_seq = node->seq_out[HSR_DEV_SLAVE_B];
492493
*if2_seq = node->seq_out[HSR_DEV_SLAVE_A];
493494

494-
if ((node->AddrB_if != HSR_DEV_NONE) && hsr->slave[node->AddrB_if])
495-
*addr_b_ifindex = hsr->slave[node->AddrB_if]->ifindex;
495+
slave = hsr->slave[node->AddrB_if];
496+
if ((node->AddrB_if != HSR_DEV_NONE) && slave)
497+
*addr_b_ifindex = slave->ifindex;
496498
else
497499
*addr_b_ifindex = -1;
498500

net/hsr/hsr_main.c

+14-10
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "hsr_device.h"
1818
#include "hsr_netlink.h"
1919
#include "hsr_framereg.h"
20+
#include "hsr_slave.h"
2021

2122

2223
/* List of all registered virtual HSR devices */
@@ -124,22 +125,21 @@ static int hsr_netdev_notify(struct notifier_block *nb, unsigned long event,
124125
if (dev == hsr->dev)
125126
break;
126127

127-
if (dev == hsr->slave[0])
128-
ether_addr_copy(hsr->dev->dev_addr,
129-
hsr->slave[0]->dev_addr);
128+
if (dev == hsr->slave[0]) {
129+
ether_addr_copy(hsr->dev->dev_addr, dev->dev_addr);
130+
call_netdevice_notifiers(NETDEV_CHANGEADDR, hsr->dev);
131+
}
130132

131133
/* Make sure we recognize frames from ourselves in hsr_rcv() */
134+
other_slave = hsr->slave[1];
132135
res = hsr_create_self_node(&hsr->self_node_db,
133136
hsr->dev->dev_addr,
134-
hsr->slave[1] ?
135-
hsr->slave[1]->dev_addr :
137+
other_slave ?
138+
other_slave->dev_addr :
136139
hsr->dev->dev_addr);
137140
if (res)
138141
netdev_warn(hsr->dev,
139142
"Could not update HSR node address.\n");
140-
141-
if (dev == hsr->slave[0])
142-
call_netdevice_notifiers(NETDEV_CHANGEADDR, hsr->dev);
143143
break;
144144
case NETDEV_CHANGEMTU:
145145
if (dev == hsr->dev)
@@ -149,10 +149,14 @@ static int hsr_netdev_notify(struct notifier_block *nb, unsigned long event,
149149
dev_set_mtu(hsr->dev, mtu_max);
150150
break;
151151
case NETDEV_UNREGISTER:
152-
if (dev == hsr->slave[0])
152+
if (dev == hsr->slave[0]) {
153153
hsr->slave[0] = NULL;
154-
if (dev == hsr->slave[1])
154+
hsr_del_slave(hsr, 0);
155+
}
156+
if (dev == hsr->slave[1]) {
155157
hsr->slave[1] = NULL;
158+
hsr_del_slave(hsr, 1);
159+
}
156160

157161
/* There should really be a way to set a new slave device... */
158162

0 commit comments

Comments
 (0)