summaryrefslogtreecommitdiff
path: root/net/hsr
diff options
context:
space:
mode:
Diffstat (limited to 'net/hsr')
-rw-r--r--net/hsr/hsr_device.c25
-rw-r--r--net/hsr/hsr_forward.c22
-rw-r--r--net/hsr/hsr_netlink.c8
-rw-r--r--net/hsr/hsr_slave.c7
4 files changed, 51 insertions, 11 deletions
diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c
index fbbc3ccf9df6..d1bfc49b5f01 100644
--- a/net/hsr/hsr_device.c
+++ b/net/hsr/hsr_device.c
@@ -320,6 +320,9 @@ static void send_hsr_supervision_frame(struct hsr_port *port,
}
hsr_stag = skb_put(skb, sizeof(struct hsr_sup_tag));
+ skb_set_network_header(skb, ETH_HLEN + HSR_HLEN);
+ skb_reset_mac_len(skb);
+
set_hsr_stag_path(hsr_stag, (hsr->prot_version ? 0x0 : 0xf));
set_hsr_stag_HSR_ver(hsr_stag, hsr->prot_version);
@@ -334,7 +337,7 @@ static void send_hsr_supervision_frame(struct hsr_port *port,
}
hsr_stag->tlv.HSR_TLV_type = type;
- /* TODO: Why 12 in HSRv0? */
+ /* HSRv0 has 6 unused bytes after the MAC */
hsr_stag->tlv.HSR_TLV_length = hsr->prot_version ?
sizeof(struct hsr_sup_payload) : 12;
@@ -687,6 +690,26 @@ struct net_device *hsr_get_port_ndev(struct net_device *ndev,
}
EXPORT_SYMBOL(hsr_get_port_ndev);
+int hsr_get_port_type(struct net_device *hsr_dev, struct net_device *dev,
+ enum hsr_port_type *type)
+{
+ struct hsr_priv *hsr = netdev_priv(hsr_dev);
+ struct hsr_port *port;
+
+ rcu_read_lock();
+ hsr_for_each_port(hsr, port) {
+ if (port->dev == dev) {
+ *type = port->type;
+ rcu_read_unlock();
+ return 0;
+ }
+ }
+ rcu_read_unlock();
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL(hsr_get_port_type);
+
/* Default multicast address for HSR Supervision frames */
static const unsigned char def_multicast_addr[ETH_ALEN] __aligned(2) = {
0x01, 0x15, 0x4e, 0x00, 0x01, 0x00
diff --git a/net/hsr/hsr_forward.c b/net/hsr/hsr_forward.c
index c67c0d35921d..339f0d220212 100644
--- a/net/hsr/hsr_forward.c
+++ b/net/hsr/hsr_forward.c
@@ -262,15 +262,23 @@ static struct sk_buff *prp_fill_rct(struct sk_buff *skb,
return skb;
}
-static void hsr_set_path_id(struct hsr_ethhdr *hsr_ethhdr,
+static void hsr_set_path_id(struct hsr_frame_info *frame,
+ struct hsr_ethhdr *hsr_ethhdr,
struct hsr_port *port)
{
int path_id;
- if (port->type == HSR_PT_SLAVE_A)
- path_id = 0;
- else
- path_id = 1;
+ if (port->hsr->prot_version) {
+ if (port->type == HSR_PT_SLAVE_A)
+ path_id = 0;
+ else
+ path_id = 1;
+ } else {
+ if (frame->is_supervision)
+ path_id = 0xf;
+ else
+ path_id = 1;
+ }
set_hsr_tag_path(&hsr_ethhdr->hsr_tag, path_id);
}
@@ -304,7 +312,7 @@ static struct sk_buff *hsr_fill_tag(struct sk_buff *skb,
else
hsr_ethhdr = (struct hsr_ethhdr *)pc;
- hsr_set_path_id(hsr_ethhdr, port);
+ hsr_set_path_id(frame, hsr_ethhdr, port);
set_hsr_tag_LSDU_size(&hsr_ethhdr->hsr_tag, lsdu_size);
hsr_ethhdr->hsr_tag.sequence_nr = htons(frame->sequence_nr);
hsr_ethhdr->hsr_tag.encap_proto = hsr_ethhdr->ethhdr.h_proto;
@@ -330,7 +338,7 @@ struct sk_buff *hsr_create_tagged_frame(struct hsr_frame_info *frame,
(struct hsr_ethhdr *)skb_mac_header(frame->skb_hsr);
/* set the lane id properly */
- hsr_set_path_id(hsr_ethhdr, port);
+ hsr_set_path_id(frame, hsr_ethhdr, port);
return skb_clone(frame->skb_hsr, GFP_ATOMIC);
} else if (port->dev->features & NETIF_F_HW_HSR_TAG_INS) {
return skb_clone(frame->skb_std, GFP_ATOMIC);
diff --git a/net/hsr/hsr_netlink.c b/net/hsr/hsr_netlink.c
index c96b63adf96f..db0b0af7a692 100644
--- a/net/hsr/hsr_netlink.c
+++ b/net/hsr/hsr_netlink.c
@@ -166,12 +166,20 @@ static int hsr_fill_info(struct sk_buff *skb, const struct net_device *dev)
goto nla_put_failure;
}
+ port = hsr_port_get_hsr(hsr, HSR_PT_INTERLINK);
+ if (port) {
+ if (nla_put_u32(skb, IFLA_HSR_INTERLINK, port->dev->ifindex))
+ goto nla_put_failure;
+ }
+
if (nla_put(skb, IFLA_HSR_SUPERVISION_ADDR, ETH_ALEN,
hsr->sup_multicast_addr) ||
nla_put_u16(skb, IFLA_HSR_SEQ_NR, hsr->sequence_nr))
goto nla_put_failure;
if (hsr->prot_version == PRP_V1)
proto = HSR_PROTOCOL_PRP;
+ else if (nla_put_u8(skb, IFLA_HSR_VERSION, hsr->prot_version))
+ goto nla_put_failure;
if (nla_put_u8(skb, IFLA_HSR_PROTOCOL, proto))
goto nla_put_failure;
diff --git a/net/hsr/hsr_slave.c b/net/hsr/hsr_slave.c
index 8177ac6c2d26..afe06ba00ea4 100644
--- a/net/hsr/hsr_slave.c
+++ b/net/hsr/hsr_slave.c
@@ -207,14 +207,14 @@ int hsr_add_port(struct hsr_priv *hsr, struct net_device *dev,
port->type = type;
ether_addr_copy(port->original_macaddress, dev->dev_addr);
+ list_add_tail_rcu(&port->port_list, &hsr->ports);
+
if (type != HSR_PT_MASTER) {
res = hsr_portdev_setup(hsr, dev, port, extack);
if (res)
goto fail_dev_setup;
}
- list_add_tail_rcu(&port->port_list, &hsr->ports);
-
master = hsr_port_get_hsr(hsr, HSR_PT_MASTER);
netdev_update_features(master->dev);
dev_set_mtu(master->dev, hsr_get_max_mtu(hsr));
@@ -222,7 +222,8 @@ int hsr_add_port(struct hsr_priv *hsr, struct net_device *dev,
return 0;
fail_dev_setup:
- kfree(port);
+ list_del_rcu(&port->port_list);
+ kfree_rcu(port, rcu);
return res;
}