Commit 1e045a62 authored by David S. Miller's avatar David S. Miller

Merge branch 'net-hsr-improvements-and-bug-fixes'

Murali Karicheri says:

====================
net: hsr: improvements and bug fixes

This series has some coding style fixes and other bug fixes.
Patch 12/14, I have also done SPDX conversion. Not sure if
that is the only thing needed and is correct. So please pay
close attention to this patch before merge as I would like to
avoid any issue related to licensing applicable for this code.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents f1054c65 5150b45f
...@@ -6,3 +6,4 @@ obj-$(CONFIG_HSR) += hsr.o ...@@ -6,3 +6,4 @@ obj-$(CONFIG_HSR) += hsr.o
hsr-y := hsr_main.o hsr_framereg.o hsr_device.o \ hsr-y := hsr_main.o hsr_framereg.o hsr_device.o \
hsr_netlink.o hsr_slave.o hsr_forward.o hsr_netlink.o hsr_slave.o hsr_forward.o
hsr-$(CONFIG_DEBUG_FS) += hsr_prp_debugfs.o
// SPDX-License-Identifier: GPL-2.0
/* Copyright 2011-2014 Autronica Fire and Security AS /* Copyright 2011-2014 Autronica Fire and Security AS
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
* *
* Author(s): * Author(s):
* 2011-2014 Arvid Brodin, arvid.brodin@alten.se * 2011-2014 Arvid Brodin, arvid.brodin@alten.se
...@@ -23,7 +19,6 @@ ...@@ -23,7 +19,6 @@
#include "hsr_main.h" #include "hsr_main.h"
#include "hsr_forward.h" #include "hsr_forward.h"
static bool is_admin_up(struct net_device *dev) static bool is_admin_up(struct net_device *dev)
{ {
return dev && (dev->flags & IFF_UP); return dev && (dev->flags & IFF_UP);
...@@ -68,7 +63,7 @@ static bool hsr_check_carrier(struct hsr_port *master) ...@@ -68,7 +63,7 @@ static bool hsr_check_carrier(struct hsr_port *master)
rcu_read_lock(); rcu_read_lock();
hsr_for_each_port(master->hsr, port) hsr_for_each_port(master->hsr, port)
if ((port->type != HSR_PT_MASTER) && is_slave_up(port->dev)) { if (port->type != HSR_PT_MASTER && is_slave_up(port->dev)) {
has_carrier = true; has_carrier = true;
break; break;
} }
...@@ -82,7 +77,6 @@ static bool hsr_check_carrier(struct hsr_port *master) ...@@ -82,7 +77,6 @@ static bool hsr_check_carrier(struct hsr_port *master)
return has_carrier; return has_carrier;
} }
static void hsr_check_announce(struct net_device *hsr_dev, static void hsr_check_announce(struct net_device *hsr_dev,
unsigned char old_operstate) unsigned char old_operstate)
{ {
...@@ -90,15 +84,14 @@ static void hsr_check_announce(struct net_device *hsr_dev, ...@@ -90,15 +84,14 @@ static void hsr_check_announce(struct net_device *hsr_dev,
hsr = netdev_priv(hsr_dev); hsr = netdev_priv(hsr_dev);
if ((hsr_dev->operstate == IF_OPER_UP) if (hsr_dev->operstate == IF_OPER_UP && old_operstate != IF_OPER_UP) {
&& (old_operstate != IF_OPER_UP)) {
/* Went up */ /* Went up */
hsr->announce_count = 0; hsr->announce_count = 0;
mod_timer(&hsr->announce_timer, mod_timer(&hsr->announce_timer,
jiffies + msecs_to_jiffies(HSR_ANNOUNCE_INTERVAL)); jiffies + msecs_to_jiffies(HSR_ANNOUNCE_INTERVAL));
} }
if ((hsr_dev->operstate != IF_OPER_UP) && (old_operstate == IF_OPER_UP)) if (hsr_dev->operstate != IF_OPER_UP && old_operstate == IF_OPER_UP)
/* Went down */ /* Went down */
del_timer(&hsr->announce_timer); del_timer(&hsr->announce_timer);
} }
...@@ -136,7 +129,6 @@ int hsr_get_max_mtu(struct hsr_priv *hsr) ...@@ -136,7 +129,6 @@ int hsr_get_max_mtu(struct hsr_priv *hsr)
return mtu_max - HSR_HLEN; return mtu_max - HSR_HLEN;
} }
static int hsr_dev_change_mtu(struct net_device *dev, int new_mtu) static int hsr_dev_change_mtu(struct net_device *dev, int new_mtu)
{ {
struct hsr_priv *hsr; struct hsr_priv *hsr;
...@@ -191,14 +183,12 @@ static int hsr_dev_open(struct net_device *dev) ...@@ -191,14 +183,12 @@ static int hsr_dev_open(struct net_device *dev)
return 0; return 0;
} }
static int hsr_dev_close(struct net_device *dev) static int hsr_dev_close(struct net_device *dev)
{ {
/* Nothing to do here. */ /* Nothing to do here. */
return 0; return 0;
} }
static netdev_features_t hsr_features_recompute(struct hsr_priv *hsr, static netdev_features_t hsr_features_recompute(struct hsr_priv *hsr,
netdev_features_t features) netdev_features_t features)
{ {
...@@ -231,7 +221,6 @@ static netdev_features_t hsr_fix_features(struct net_device *dev, ...@@ -231,7 +221,6 @@ static netdev_features_t hsr_fix_features(struct net_device *dev,
return hsr_features_recompute(hsr, features); return hsr_features_recompute(hsr, features);
} }
static int hsr_dev_xmit(struct sk_buff *skb, struct net_device *dev) static int hsr_dev_xmit(struct sk_buff *skb, struct net_device *dev)
{ {
struct hsr_priv *hsr = netdev_priv(dev); struct hsr_priv *hsr = netdev_priv(dev);
...@@ -244,14 +233,13 @@ static int hsr_dev_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -244,14 +233,13 @@ static int hsr_dev_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }
static const struct header_ops hsr_header_ops = { static const struct header_ops hsr_header_ops = {
.create = eth_header, .create = eth_header,
.parse = eth_header_parse, .parse = eth_header_parse,
}; };
static void send_hsr_supervision_frame(struct hsr_port *master, static void send_hsr_supervision_frame(struct hsr_port *master,
u8 type, u8 hsrVer) u8 type, u8 hsr_ver)
{ {
struct sk_buff *skb; struct sk_buff *skb;
int hlen, tlen; int hlen, tlen;
...@@ -262,39 +250,38 @@ static void send_hsr_supervision_frame(struct hsr_port *master, ...@@ -262,39 +250,38 @@ static void send_hsr_supervision_frame(struct hsr_port *master,
hlen = LL_RESERVED_SPACE(master->dev); hlen = LL_RESERVED_SPACE(master->dev);
tlen = master->dev->needed_tailroom; tlen = master->dev->needed_tailroom;
skb = dev_alloc_skb( skb = dev_alloc_skb(sizeof(struct hsr_tag) +
sizeof(struct hsr_tag) + sizeof(struct hsr_sup_tag) +
sizeof(struct hsr_sup_tag) + sizeof(struct hsr_sup_payload) + hlen + tlen);
sizeof(struct hsr_sup_payload) + hlen + tlen);
if (skb == NULL) if (!skb)
return; return;
skb_reserve(skb, hlen); skb_reserve(skb, hlen);
skb->dev = master->dev; skb->dev = master->dev;
skb->protocol = htons(hsrVer ? ETH_P_HSR : ETH_P_PRP); skb->protocol = htons(hsr_ver ? ETH_P_HSR : ETH_P_PRP);
skb->priority = TC_PRIO_CONTROL; skb->priority = TC_PRIO_CONTROL;
if (dev_hard_header(skb, skb->dev, (hsrVer ? ETH_P_HSR : ETH_P_PRP), if (dev_hard_header(skb, skb->dev, (hsr_ver ? ETH_P_HSR : ETH_P_PRP),
master->hsr->sup_multicast_addr, master->hsr->sup_multicast_addr,
skb->dev->dev_addr, skb->len) <= 0) skb->dev->dev_addr, skb->len) <= 0)
goto out; goto out;
skb_reset_mac_header(skb); skb_reset_mac_header(skb);
if (hsrVer > 0) { if (hsr_ver > 0) {
hsr_tag = skb_put(skb, sizeof(struct hsr_tag)); hsr_tag = skb_put(skb, sizeof(struct hsr_tag));
hsr_tag->encap_proto = htons(ETH_P_PRP); hsr_tag->encap_proto = htons(ETH_P_PRP);
set_hsr_tag_LSDU_size(hsr_tag, HSR_V1_SUP_LSDUSIZE); set_hsr_tag_LSDU_size(hsr_tag, HSR_V1_SUP_LSDUSIZE);
} }
hsr_stag = skb_put(skb, sizeof(struct hsr_sup_tag)); hsr_stag = skb_put(skb, sizeof(struct hsr_sup_tag));
set_hsr_stag_path(hsr_stag, (hsrVer ? 0x0 : 0xf)); set_hsr_stag_path(hsr_stag, (hsr_ver ? 0x0 : 0xf));
set_hsr_stag_HSR_Ver(hsr_stag, hsrVer); set_hsr_stag_HSR_ver(hsr_stag, hsr_ver);
/* From HSRv1 on we have separate supervision sequence numbers. */ /* From HSRv1 on we have separate supervision sequence numbers. */
spin_lock_irqsave(&master->hsr->seqnr_lock, irqflags); spin_lock_irqsave(&master->hsr->seqnr_lock, irqflags);
if (hsrVer > 0) { if (hsr_ver > 0) {
hsr_stag->sequence_nr = htons(master->hsr->sup_sequence_nr); hsr_stag->sequence_nr = htons(master->hsr->sup_sequence_nr);
hsr_tag->sequence_nr = htons(master->hsr->sequence_nr); hsr_tag->sequence_nr = htons(master->hsr->sequence_nr);
master->hsr->sup_sequence_nr++; master->hsr->sup_sequence_nr++;
...@@ -305,13 +292,14 @@ static void send_hsr_supervision_frame(struct hsr_port *master, ...@@ -305,13 +292,14 @@ static void send_hsr_supervision_frame(struct hsr_port *master,
} }
spin_unlock_irqrestore(&master->hsr->seqnr_lock, irqflags); spin_unlock_irqrestore(&master->hsr->seqnr_lock, irqflags);
hsr_stag->HSR_TLV_Type = type; hsr_stag->HSR_TLV_type = type;
/* TODO: Why 12 in HSRv0? */ /* TODO: Why 12 in HSRv0? */
hsr_stag->HSR_TLV_Length = hsrVer ? sizeof(struct hsr_sup_payload) : 12; hsr_stag->HSR_TLV_length =
hsr_ver ? sizeof(struct hsr_sup_payload) : 12;
/* Payload: MacAddressA */ /* Payload: MacAddressA */
hsr_sp = skb_put(skb, sizeof(struct hsr_sup_payload)); hsr_sp = skb_put(skb, sizeof(struct hsr_sup_payload));
ether_addr_copy(hsr_sp->MacAddressA, master->dev->dev_addr); ether_addr_copy(hsr_sp->macaddress_A, master->dev->dev_addr);
if (skb_put_padto(skb, ETH_ZLEN + HSR_HLEN)) if (skb_put_padto(skb, ETH_ZLEN + HSR_HLEN))
return; return;
...@@ -324,7 +312,6 @@ static void send_hsr_supervision_frame(struct hsr_port *master, ...@@ -324,7 +312,6 @@ static void send_hsr_supervision_frame(struct hsr_port *master,
kfree_skb(skb); kfree_skb(skb);
} }
/* Announce (supervision frame) timer function /* Announce (supervision frame) timer function
*/ */
static void hsr_announce(struct timer_list *t) static void hsr_announce(struct timer_list *t)
...@@ -338,15 +325,15 @@ static void hsr_announce(struct timer_list *t) ...@@ -338,15 +325,15 @@ static void hsr_announce(struct timer_list *t)
rcu_read_lock(); rcu_read_lock();
master = hsr_port_get_hsr(hsr, HSR_PT_MASTER); master = hsr_port_get_hsr(hsr, HSR_PT_MASTER);
if (hsr->announce_count < 3 && hsr->protVersion == 0) { if (hsr->announce_count < 3 && hsr->prot_version == 0) {
send_hsr_supervision_frame(master, HSR_TLV_ANNOUNCE, send_hsr_supervision_frame(master, HSR_TLV_ANNOUNCE,
hsr->protVersion); hsr->prot_version);
hsr->announce_count++; hsr->announce_count++;
interval = msecs_to_jiffies(HSR_ANNOUNCE_INTERVAL); interval = msecs_to_jiffies(HSR_ANNOUNCE_INTERVAL);
} else { } else {
send_hsr_supervision_frame(master, HSR_TLV_LIFE_CHECK, send_hsr_supervision_frame(master, HSR_TLV_LIFE_CHECK,
hsr->protVersion); hsr->prot_version);
interval = msecs_to_jiffies(HSR_LIFE_CHECK_INTERVAL); interval = msecs_to_jiffies(HSR_LIFE_CHECK_INTERVAL);
} }
...@@ -357,7 +344,6 @@ static void hsr_announce(struct timer_list *t) ...@@ -357,7 +344,6 @@ static void hsr_announce(struct timer_list *t)
rcu_read_unlock(); rcu_read_unlock();
} }
/* According to comments in the declaration of struct net_device, this function /* According to comments in the declaration of struct net_device, this function
* is "Called from unregister, can be used to call free_netdev". Ok then... * is "Called from unregister, can be used to call free_netdev". Ok then...
*/ */
...@@ -368,6 +354,8 @@ static void hsr_dev_destroy(struct net_device *hsr_dev) ...@@ -368,6 +354,8 @@ static void hsr_dev_destroy(struct net_device *hsr_dev)
hsr = netdev_priv(hsr_dev); hsr = netdev_priv(hsr_dev);
hsr_prp_debugfs_term(hsr);
rtnl_lock(); rtnl_lock();
hsr_for_each_port(hsr, port) hsr_for_each_port(hsr, port)
hsr_del_port(port); hsr_del_port(port);
...@@ -423,7 +411,6 @@ void hsr_dev_setup(struct net_device *dev) ...@@ -423,7 +411,6 @@ void hsr_dev_setup(struct net_device *dev)
dev->features |= NETIF_F_NETNS_LOCAL; dev->features |= NETIF_F_NETNS_LOCAL;
} }
/* Return true if dev is a HSR master; return false otherwise. /* Return true if dev is a HSR master; return false otherwise.
*/ */
inline bool is_hsr_master(struct net_device *dev) inline bool is_hsr_master(struct net_device *dev)
...@@ -467,7 +454,7 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2], ...@@ -467,7 +454,7 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2],
ether_addr_copy(hsr->sup_multicast_addr, def_multicast_addr); ether_addr_copy(hsr->sup_multicast_addr, def_multicast_addr);
hsr->sup_multicast_addr[ETH_ALEN - 1] = multicast_spec; hsr->sup_multicast_addr[ETH_ALEN - 1] = multicast_spec;
hsr->protVersion = protocol_version; hsr->prot_version = protocol_version;
/* FIXME: should I modify the value of these? /* FIXME: should I modify the value of these?
* *
...@@ -498,6 +485,9 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2], ...@@ -498,6 +485,9 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2],
goto fail; goto fail;
mod_timer(&hsr->prune_timer, jiffies + msecs_to_jiffies(PRUNE_PERIOD)); mod_timer(&hsr->prune_timer, jiffies + msecs_to_jiffies(PRUNE_PERIOD));
res = hsr_prp_debugfs_init(hsr);
if (res)
goto fail;
return 0; return 0;
......
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright 2011-2014 Autronica Fire and Security AS /* Copyright 2011-2014 Autronica Fire and Security AS
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
* *
* Author(s): * Author(s):
* 2011-2014 Arvid Brodin, arvid.brodin@alten.se * 2011-2014 Arvid Brodin, arvid.brodin@alten.se
......
// SPDX-License-Identifier: GPL-2.0
/* Copyright 2011-2014 Autronica Fire and Security AS /* Copyright 2011-2014 Autronica Fire and Security AS
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
* *
* Author(s): * Author(s):
* 2011-2014 Arvid Brodin, arvid.brodin@alten.se * 2011-2014 Arvid Brodin, arvid.brodin@alten.se
...@@ -17,7 +13,6 @@ ...@@ -17,7 +13,6 @@
#include "hsr_main.h" #include "hsr_main.h"
#include "hsr_framereg.h" #include "hsr_framereg.h"
struct hsr_node; struct hsr_node;
struct hsr_frame_info { struct hsr_frame_info {
...@@ -32,7 +27,6 @@ struct hsr_frame_info { ...@@ -32,7 +27,6 @@ struct hsr_frame_info {
bool is_local_exclusive; bool is_local_exclusive;
}; };
/* The uses I can see for these HSR supervision frames are: /* The uses I can see for these HSR supervision frames are:
* 1) Use the frames that are sent after node initialization ("HSR_TLV.Type = * 1) Use the frames that are sent after node initialization ("HSR_TLV.Type =
* 22") to reset any sequence_nr counters belonging to that node. Useful if * 22") to reset any sequence_nr counters belonging to that node. Useful if
...@@ -50,46 +44,45 @@ struct hsr_frame_info { ...@@ -50,46 +44,45 @@ struct hsr_frame_info {
*/ */
static bool is_supervision_frame(struct hsr_priv *hsr, struct sk_buff *skb) static bool is_supervision_frame(struct hsr_priv *hsr, struct sk_buff *skb)
{ {
struct ethhdr *ethHdr; struct ethhdr *eth_hdr;
struct hsr_sup_tag *hsrSupTag; struct hsr_sup_tag *hsr_sup_tag;
struct hsrv1_ethhdr_sp *hsrV1Hdr; struct hsrv1_ethhdr_sp *hsr_V1_hdr;
WARN_ON_ONCE(!skb_mac_header_was_set(skb)); WARN_ON_ONCE(!skb_mac_header_was_set(skb));
ethHdr = (struct ethhdr *) skb_mac_header(skb); eth_hdr = (struct ethhdr *)skb_mac_header(skb);
/* Correct addr? */ /* Correct addr? */
if (!ether_addr_equal(ethHdr->h_dest, if (!ether_addr_equal(eth_hdr->h_dest,
hsr->sup_multicast_addr)) hsr->sup_multicast_addr))
return false; return false;
/* Correct ether type?. */ /* Correct ether type?. */
if (!(ethHdr->h_proto == htons(ETH_P_PRP) if (!(eth_hdr->h_proto == htons(ETH_P_PRP) ||
|| ethHdr->h_proto == htons(ETH_P_HSR))) eth_hdr->h_proto == htons(ETH_P_HSR)))
return false; return false;
/* Get the supervision header from correct location. */ /* Get the supervision header from correct location. */
if (ethHdr->h_proto == htons(ETH_P_HSR)) { /* Okay HSRv1. */ if (eth_hdr->h_proto == htons(ETH_P_HSR)) { /* Okay HSRv1. */
hsrV1Hdr = (struct hsrv1_ethhdr_sp *) skb_mac_header(skb); hsr_V1_hdr = (struct hsrv1_ethhdr_sp *)skb_mac_header(skb);
if (hsrV1Hdr->hsr.encap_proto != htons(ETH_P_PRP)) if (hsr_V1_hdr->hsr.encap_proto != htons(ETH_P_PRP))
return false; return false;
hsrSupTag = &hsrV1Hdr->hsr_sup; hsr_sup_tag = &hsr_V1_hdr->hsr_sup;
} else { } else {
hsrSupTag = &((struct hsrv0_ethhdr_sp *) skb_mac_header(skb))->hsr_sup; hsr_sup_tag =
&((struct hsrv0_ethhdr_sp *)skb_mac_header(skb))->hsr_sup;
} }
if ((hsrSupTag->HSR_TLV_Type != HSR_TLV_ANNOUNCE) && if (hsr_sup_tag->HSR_TLV_type != HSR_TLV_ANNOUNCE &&
(hsrSupTag->HSR_TLV_Type != HSR_TLV_LIFE_CHECK)) hsr_sup_tag->HSR_TLV_type != HSR_TLV_LIFE_CHECK)
return false; return false;
if ((hsrSupTag->HSR_TLV_Length != 12) && if (hsr_sup_tag->HSR_TLV_length != 12 &&
(hsrSupTag->HSR_TLV_Length != hsr_sup_tag->HSR_TLV_length != sizeof(struct hsr_sup_payload))
sizeof(struct hsr_sup_payload)))
return false; return false;
return true; return true;
} }
static struct sk_buff *create_stripped_skb(struct sk_buff *skb_in, static struct sk_buff *create_stripped_skb(struct sk_buff *skb_in,
struct hsr_frame_info *frame) struct hsr_frame_info *frame)
{ {
...@@ -100,7 +93,7 @@ static struct sk_buff *create_stripped_skb(struct sk_buff *skb_in, ...@@ -100,7 +93,7 @@ static struct sk_buff *create_stripped_skb(struct sk_buff *skb_in,
skb_pull(skb_in, HSR_HLEN); skb_pull(skb_in, HSR_HLEN);
skb = __pskb_copy(skb_in, skb_headroom(skb_in) - HSR_HLEN, GFP_ATOMIC); skb = __pskb_copy(skb_in, skb_headroom(skb_in) - HSR_HLEN, GFP_ATOMIC);
skb_push(skb_in, HSR_HLEN); skb_push(skb_in, HSR_HLEN);
if (skb == NULL) if (!skb)
return NULL; return NULL;
skb_reset_mac_header(skb); skb_reset_mac_header(skb);
...@@ -108,7 +101,7 @@ static struct sk_buff *create_stripped_skb(struct sk_buff *skb_in, ...@@ -108,7 +101,7 @@ static struct sk_buff *create_stripped_skb(struct sk_buff *skb_in,
if (skb->ip_summed == CHECKSUM_PARTIAL) if (skb->ip_summed == CHECKSUM_PARTIAL)
skb->csum_start -= HSR_HLEN; skb->csum_start -= HSR_HLEN;
copylen = 2*ETH_ALEN; copylen = 2 * ETH_ALEN;
if (frame->is_vlan) if (frame->is_vlan)
copylen += VLAN_HLEN; copylen += VLAN_HLEN;
src = skb_mac_header(skb_in); src = skb_mac_header(skb_in);
...@@ -127,9 +120,8 @@ static struct sk_buff *frame_get_stripped_skb(struct hsr_frame_info *frame, ...@@ -127,9 +120,8 @@ static struct sk_buff *frame_get_stripped_skb(struct hsr_frame_info *frame,
return skb_clone(frame->skb_std, GFP_ATOMIC); return skb_clone(frame->skb_std, GFP_ATOMIC);
} }
static void hsr_fill_tag(struct sk_buff *skb, struct hsr_frame_info *frame, static void hsr_fill_tag(struct sk_buff *skb, struct hsr_frame_info *frame,
struct hsr_port *port, u8 protoVersion) struct hsr_port *port, u8 proto_version)
{ {
struct hsr_ethhdr *hsr_ethhdr; struct hsr_ethhdr *hsr_ethhdr;
int lane_id; int lane_id;
...@@ -144,13 +136,13 @@ static void hsr_fill_tag(struct sk_buff *skb, struct hsr_frame_info *frame, ...@@ -144,13 +136,13 @@ static void hsr_fill_tag(struct sk_buff *skb, struct hsr_frame_info *frame,
if (frame->is_vlan) if (frame->is_vlan)
lsdu_size -= 4; lsdu_size -= 4;
hsr_ethhdr = (struct hsr_ethhdr *) skb_mac_header(skb); hsr_ethhdr = (struct hsr_ethhdr *)skb_mac_header(skb);
set_hsr_tag_path(&hsr_ethhdr->hsr_tag, lane_id); set_hsr_tag_path(&hsr_ethhdr->hsr_tag, lane_id);
set_hsr_tag_LSDU_size(&hsr_ethhdr->hsr_tag, lsdu_size); 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.sequence_nr = htons(frame->sequence_nr);
hsr_ethhdr->hsr_tag.encap_proto = hsr_ethhdr->ethhdr.h_proto; hsr_ethhdr->hsr_tag.encap_proto = hsr_ethhdr->ethhdr.h_proto;
hsr_ethhdr->ethhdr.h_proto = htons(protoVersion ? hsr_ethhdr->ethhdr.h_proto = htons(proto_version ?
ETH_P_HSR : ETH_P_PRP); ETH_P_HSR : ETH_P_PRP);
} }
...@@ -164,7 +156,7 @@ static struct sk_buff *create_tagged_skb(struct sk_buff *skb_o, ...@@ -164,7 +156,7 @@ static struct sk_buff *create_tagged_skb(struct sk_buff *skb_o,
/* Create the new skb with enough headroom to fit the HSR tag */ /* Create the new skb with enough headroom to fit the HSR tag */
skb = __pskb_copy(skb_o, skb_headroom(skb_o) + HSR_HLEN, GFP_ATOMIC); skb = __pskb_copy(skb_o, skb_headroom(skb_o) + HSR_HLEN, GFP_ATOMIC);
if (skb == NULL) if (!skb)
return NULL; return NULL;
skb_reset_mac_header(skb); skb_reset_mac_header(skb);
...@@ -180,7 +172,7 @@ static struct sk_buff *create_tagged_skb(struct sk_buff *skb_o, ...@@ -180,7 +172,7 @@ static struct sk_buff *create_tagged_skb(struct sk_buff *skb_o,
memmove(dst, src, movelen); memmove(dst, src, movelen);
skb_reset_mac_header(skb); skb_reset_mac_header(skb);
hsr_fill_tag(skb, frame, port, port->hsr->protVersion); hsr_fill_tag(skb, frame, port, port->hsr->prot_version);
return skb; return skb;
} }
...@@ -194,7 +186,7 @@ static struct sk_buff *frame_get_tagged_skb(struct hsr_frame_info *frame, ...@@ -194,7 +186,7 @@ static struct sk_buff *frame_get_tagged_skb(struct hsr_frame_info *frame,
if (frame->skb_hsr) if (frame->skb_hsr)
return skb_clone(frame->skb_hsr, GFP_ATOMIC); return skb_clone(frame->skb_hsr, GFP_ATOMIC);
if ((port->type != HSR_PT_SLAVE_A) && (port->type != HSR_PT_SLAVE_B)) { if (port->type != HSR_PT_SLAVE_A && port->type != HSR_PT_SLAVE_B) {
WARN_ONCE(1, "HSR: Bug: trying to create a tagged frame for a non-ring port"); WARN_ONCE(1, "HSR: Bug: trying to create a tagged frame for a non-ring port");
return NULL; return NULL;
} }
...@@ -202,7 +194,6 @@ static struct sk_buff *frame_get_tagged_skb(struct hsr_frame_info *frame, ...@@ -202,7 +194,6 @@ static struct sk_buff *frame_get_tagged_skb(struct hsr_frame_info *frame,
return create_tagged_skb(frame->skb_std, frame, port); return create_tagged_skb(frame->skb_std, frame, port);
} }
static void hsr_deliver_master(struct sk_buff *skb, struct net_device *dev, static void hsr_deliver_master(struct sk_buff *skb, struct net_device *dev,
struct hsr_node *node_src) struct hsr_node *node_src)
{ {
...@@ -237,7 +228,6 @@ static int hsr_xmit(struct sk_buff *skb, struct hsr_port *port, ...@@ -237,7 +228,6 @@ static int hsr_xmit(struct sk_buff *skb, struct hsr_port *port,
return dev_queue_xmit(skb); return dev_queue_xmit(skb);
} }
/* Forward the frame through all devices except: /* Forward the frame through all devices except:
* - Back through the receiving device * - Back through the receiving device
* - If it's a HSR frame: through a device where it has passed before * - If it's a HSR frame: through a device where it has passed before
...@@ -260,11 +250,11 @@ static void hsr_forward_do(struct hsr_frame_info *frame) ...@@ -260,11 +250,11 @@ static void hsr_forward_do(struct hsr_frame_info *frame)
continue; continue;
/* Don't deliver locally unless we should */ /* Don't deliver locally unless we should */
if ((port->type == HSR_PT_MASTER) && !frame->is_local_dest) if (port->type == HSR_PT_MASTER && !frame->is_local_dest)
continue; continue;
/* Deliver frames directly addressed to us to master only */ /* Deliver frames directly addressed to us to master only */
if ((port->type != HSR_PT_MASTER) && frame->is_local_exclusive) if (port->type != HSR_PT_MASTER && frame->is_local_exclusive)
continue; continue;
/* Don't send frame over port where it has been sent before */ /* Don't send frame over port where it has been sent before */
...@@ -272,7 +262,7 @@ static void hsr_forward_do(struct hsr_frame_info *frame) ...@@ -272,7 +262,7 @@ static void hsr_forward_do(struct hsr_frame_info *frame)
frame->sequence_nr)) frame->sequence_nr))
continue; continue;
if (frame->is_supervision && (port->type == HSR_PT_MASTER)) { if (frame->is_supervision && port->type == HSR_PT_MASTER) {
hsr_handle_sup_frame(frame->skb_hsr, hsr_handle_sup_frame(frame->skb_hsr,
frame->node_src, frame->node_src,
frame->port_rcv); frame->port_rcv);
...@@ -283,7 +273,7 @@ static void hsr_forward_do(struct hsr_frame_info *frame) ...@@ -283,7 +273,7 @@ static void hsr_forward_do(struct hsr_frame_info *frame)
skb = frame_get_tagged_skb(frame, port); skb = frame_get_tagged_skb(frame, port);
else else
skb = frame_get_stripped_skb(frame, port); skb = frame_get_stripped_skb(frame, port);
if (skb == NULL) { if (!skb) {
/* FIXME: Record the dropped frame? */ /* FIXME: Record the dropped frame? */
continue; continue;
} }
...@@ -296,7 +286,6 @@ static void hsr_forward_do(struct hsr_frame_info *frame) ...@@ -296,7 +286,6 @@ static void hsr_forward_do(struct hsr_frame_info *frame)
} }
} }
static void check_local_dest(struct hsr_priv *hsr, struct sk_buff *skb, static void check_local_dest(struct hsr_priv *hsr, struct sk_buff *skb,
struct hsr_frame_info *frame) struct hsr_frame_info *frame)
{ {
...@@ -307,16 +296,15 @@ static void check_local_dest(struct hsr_priv *hsr, struct sk_buff *skb, ...@@ -307,16 +296,15 @@ static void check_local_dest(struct hsr_priv *hsr, struct sk_buff *skb,
frame->is_local_exclusive = false; frame->is_local_exclusive = false;
} }
if ((skb->pkt_type == PACKET_HOST) || if (skb->pkt_type == PACKET_HOST ||
(skb->pkt_type == PACKET_MULTICAST) || skb->pkt_type == PACKET_MULTICAST ||
(skb->pkt_type == PACKET_BROADCAST)) { skb->pkt_type == PACKET_BROADCAST) {
frame->is_local_dest = true; frame->is_local_dest = true;
} else { } else {
frame->is_local_dest = false; frame->is_local_dest = false;
} }
} }
static int hsr_fill_frame_info(struct hsr_frame_info *frame, static int hsr_fill_frame_info(struct hsr_frame_info *frame,
struct sk_buff *skb, struct hsr_port *port) struct sk_buff *skb, struct hsr_port *port)
{ {
...@@ -325,18 +313,18 @@ static int hsr_fill_frame_info(struct hsr_frame_info *frame, ...@@ -325,18 +313,18 @@ static int hsr_fill_frame_info(struct hsr_frame_info *frame,
frame->is_supervision = is_supervision_frame(port->hsr, skb); frame->is_supervision = is_supervision_frame(port->hsr, skb);
frame->node_src = hsr_get_node(port, skb, frame->is_supervision); frame->node_src = hsr_get_node(port, skb, frame->is_supervision);
if (frame->node_src == NULL) if (!frame->node_src)
return -1; /* Unknown node and !is_supervision, or no mem */ return -1; /* Unknown node and !is_supervision, or no mem */
ethhdr = (struct ethhdr *) skb_mac_header(skb); ethhdr = (struct ethhdr *)skb_mac_header(skb);
frame->is_vlan = false; frame->is_vlan = false;
if (ethhdr->h_proto == htons(ETH_P_8021Q)) { if (ethhdr->h_proto == htons(ETH_P_8021Q)) {
frame->is_vlan = true; frame->is_vlan = true;
/* FIXME: */ /* FIXME: */
WARN_ONCE(1, "HSR: VLAN not yet supported"); WARN_ONCE(1, "HSR: VLAN not yet supported");
} }
if (ethhdr->h_proto == htons(ETH_P_PRP) if (ethhdr->h_proto == htons(ETH_P_PRP) ||
|| ethhdr->h_proto == htons(ETH_P_HSR)) { ethhdr->h_proto == htons(ETH_P_HSR)) {
frame->skb_std = NULL; frame->skb_std = NULL;
frame->skb_hsr = skb; frame->skb_hsr = skb;
frame->sequence_nr = hsr_get_skb_sequence_nr(skb); frame->sequence_nr = hsr_get_skb_sequence_nr(skb);
...@@ -372,9 +360,9 @@ void hsr_forward_skb(struct sk_buff *skb, struct hsr_port *port) ...@@ -372,9 +360,9 @@ void hsr_forward_skb(struct sk_buff *skb, struct hsr_port *port)
hsr_register_frame_in(frame.node_src, port, frame.sequence_nr); hsr_register_frame_in(frame.node_src, port, frame.sequence_nr);
hsr_forward_do(&frame); hsr_forward_do(&frame);
if (frame.skb_hsr != NULL) if (frame.skb_hsr)
kfree_skb(frame.skb_hsr); kfree_skb(frame.skb_hsr);
if (frame.skb_std != NULL) if (frame.skb_std)
kfree_skb(frame.skb_std); kfree_skb(frame.skb_std);
return; return;
......
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright 2011-2014 Autronica Fire and Security AS /* Copyright 2011-2014 Autronica Fire and Security AS
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
* *
* Author(s): * Author(s):
* 2011-2014 Arvid Brodin, arvid.brodin@alten.se * 2011-2014 Arvid Brodin, arvid.brodin@alten.se
......
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright 2011-2014 Autronica Fire and Security AS /* Copyright 2011-2014 Autronica Fire and Security AS
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
* *
* Author(s): * Author(s):
* 2011-2014 Arvid Brodin, arvid.brodin@alten.se * 2011-2014 Arvid Brodin, arvid.brodin@alten.se
...@@ -52,4 +48,16 @@ int hsr_get_node_data(struct hsr_priv *hsr, ...@@ -52,4 +48,16 @@ int hsr_get_node_data(struct hsr_priv *hsr,
int *if2_age, int *if2_age,
u16 *if2_seq); u16 *if2_seq);
struct hsr_node {
struct list_head mac_list;
unsigned char macaddress_A[ETH_ALEN];
unsigned char macaddress_B[ETH_ALEN];
/* Local slave through which AddrB frames are received from this node */
enum hsr_port_type addr_B_port;
unsigned long time_in[HSR_PT_PORTS];
bool time_in_stale[HSR_PT_PORTS];
u16 seq_out[HSR_PT_PORTS];
struct rcu_head rcu_head;
};
#endif /* __HSR_FRAMEREG_H */ #endif /* __HSR_FRAMEREG_H */
// SPDX-License-Identifier: GPL-2.0
/* Copyright 2011-2014 Autronica Fire and Security AS /* Copyright 2011-2014 Autronica Fire and Security AS
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
* *
* Author(s): * Author(s):
* 2011-2014 Arvid Brodin, arvid.brodin@alten.se * 2011-2014 Arvid Brodin, arvid.brodin@alten.se
...@@ -19,7 +15,6 @@ ...@@ -19,7 +15,6 @@
#include "hsr_framereg.h" #include "hsr_framereg.h"
#include "hsr_slave.h" #include "hsr_slave.h"
static int hsr_netdev_notify(struct notifier_block *nb, unsigned long event, static int hsr_netdev_notify(struct notifier_block *nb, unsigned long event,
void *ptr) void *ptr)
{ {
...@@ -31,12 +26,12 @@ static int hsr_netdev_notify(struct notifier_block *nb, unsigned long event, ...@@ -31,12 +26,12 @@ static int hsr_netdev_notify(struct notifier_block *nb, unsigned long event,
dev = netdev_notifier_info_to_dev(ptr); dev = netdev_notifier_info_to_dev(ptr);
port = hsr_port_get_rtnl(dev); port = hsr_port_get_rtnl(dev);
if (port == NULL) { if (!port) {
if (!is_hsr_master(dev)) if (!is_hsr_master(dev))
return NOTIFY_DONE; /* Not an HSR device */ return NOTIFY_DONE; /* Not an HSR device */
hsr = netdev_priv(dev); hsr = netdev_priv(dev);
port = hsr_port_get_hsr(hsr, HSR_PT_MASTER); port = hsr_port_get_hsr(hsr, HSR_PT_MASTER);
if (port == NULL) { if (!port) {
/* Resend of notification concerning removed device? */ /* Resend of notification concerning removed device? */
return NOTIFY_DONE; return NOTIFY_DONE;
} }
...@@ -63,7 +58,8 @@ static int hsr_netdev_notify(struct notifier_block *nb, unsigned long event, ...@@ -63,7 +58,8 @@ static int hsr_netdev_notify(struct notifier_block *nb, unsigned long event,
if (port->type == HSR_PT_SLAVE_A) { if (port->type == HSR_PT_SLAVE_A) {
ether_addr_copy(master->dev->dev_addr, dev->dev_addr); ether_addr_copy(master->dev->dev_addr, dev->dev_addr);
call_netdevice_notifiers(NETDEV_CHANGEADDR, master->dev); call_netdevice_notifiers(NETDEV_CHANGEADDR,
master->dev);
} }
/* Make sure we recognize frames from ourselves in hsr_rcv() */ /* Make sure we recognize frames from ourselves in hsr_rcv() */
...@@ -97,7 +93,6 @@ static int hsr_netdev_notify(struct notifier_block *nb, unsigned long event, ...@@ -97,7 +93,6 @@ static int hsr_netdev_notify(struct notifier_block *nb, unsigned long event,
return NOTIFY_DONE; return NOTIFY_DONE;
} }
struct hsr_port *hsr_port_get_hsr(struct hsr_priv *hsr, enum hsr_port_type pt) struct hsr_port *hsr_port_get_hsr(struct hsr_priv *hsr, enum hsr_port_type pt)
{ {
struct hsr_port *port; struct hsr_port *port;
...@@ -112,7 +107,6 @@ static struct notifier_block hsr_nb = { ...@@ -112,7 +107,6 @@ static struct notifier_block hsr_nb = {
.notifier_call = hsr_netdev_notify, /* Slave event notifications */ .notifier_call = hsr_netdev_notify, /* Slave event notifications */
}; };
static int __init hsr_init(void) static int __init hsr_init(void)
{ {
int res; int res;
......
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright 2011-2014 Autronica Fire and Security AS /* Copyright 2011-2014 Autronica Fire and Security AS
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
* *
* Author(s): * Author(s):
* 2011-2014 Arvid Brodin, arvid.brodin@alten.se * 2011-2014 Arvid Brodin, arvid.brodin@alten.se
...@@ -15,7 +11,6 @@ ...@@ -15,7 +11,6 @@
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/list.h> #include <linux/list.h>
/* Time constants as specified in the HSR specification (IEC-62439-3 2010) /* Time constants as specified in the HSR specification (IEC-62439-3 2010)
* Table 8. * Table 8.
* All values in milliseconds. * All values in milliseconds.
...@@ -24,7 +19,6 @@ ...@@ -24,7 +19,6 @@
#define HSR_NODE_FORGET_TIME 60000 /* ms */ #define HSR_NODE_FORGET_TIME 60000 /* ms */
#define HSR_ANNOUNCE_INTERVAL 100 /* ms */ #define HSR_ANNOUNCE_INTERVAL 100 /* ms */
/* By how much may slave1 and slave2 timestamps of latest received frame from /* By how much may slave1 and slave2 timestamps of latest received frame from
* each node differ before we notify of communication problem? * each node differ before we notify of communication problem?
*/ */
...@@ -32,17 +26,14 @@ ...@@ -32,17 +26,14 @@
#define HSR_SEQNR_START (USHRT_MAX - 1024) #define HSR_SEQNR_START (USHRT_MAX - 1024)
#define HSR_SUP_SEQNR_START (HSR_SEQNR_START / 2) #define HSR_SUP_SEQNR_START (HSR_SEQNR_START / 2)
/* How often shall we check for broken ring and remove node entries older than /* How often shall we check for broken ring and remove node entries older than
* HSR_NODE_FORGET_TIME? * HSR_NODE_FORGET_TIME?
*/ */
#define PRUNE_PERIOD 3000 /* ms */ #define PRUNE_PERIOD 3000 /* ms */
#define HSR_TLV_ANNOUNCE 22 #define HSR_TLV_ANNOUNCE 22
#define HSR_TLV_LIFE_CHECK 23 #define HSR_TLV_LIFE_CHECK 23
/* HSR Tag. /* HSR Tag.
* As defined in IEC-62439-3:2010, the HSR tag is really { ethertype = 0x88FB, * As defined in IEC-62439-3:2010, the HSR tag is really { ethertype = 0x88FB,
* path, LSDU_size, sequence Nr }. But we let eth_header() create { h_dest, * path, LSDU_size, sequence Nr }. But we let eth_header() create { h_dest,
...@@ -83,15 +74,14 @@ static inline u16 get_hsr_tag_LSDU_size(struct hsr_tag *ht) ...@@ -83,15 +74,14 @@ static inline u16 get_hsr_tag_LSDU_size(struct hsr_tag *ht)
static inline void set_hsr_tag_path(struct hsr_tag *ht, u16 path) static inline void set_hsr_tag_path(struct hsr_tag *ht, u16 path)
{ {
ht->path_and_LSDU_size = htons( ht->path_and_LSDU_size =
(ntohs(ht->path_and_LSDU_size) & 0x0FFF) | (path << 12)); htons((ntohs(ht->path_and_LSDU_size) & 0x0FFF) | (path << 12));
} }
static inline void set_hsr_tag_LSDU_size(struct hsr_tag *ht, u16 LSDU_size) static inline void set_hsr_tag_LSDU_size(struct hsr_tag *ht, u16 LSDU_size)
{ {
ht->path_and_LSDU_size = htons( ht->path_and_LSDU_size = htons((ntohs(ht->path_and_LSDU_size) &
(ntohs(ht->path_and_LSDU_size) & 0xF000) | 0xF000) | (LSDU_size & 0x0FFF));
(LSDU_size & 0x0FFF));
} }
struct hsr_ethhdr { struct hsr_ethhdr {
...@@ -99,39 +89,38 @@ struct hsr_ethhdr { ...@@ -99,39 +89,38 @@ struct hsr_ethhdr {
struct hsr_tag hsr_tag; struct hsr_tag hsr_tag;
} __packed; } __packed;
/* HSR Supervision Frame data types. /* HSR Supervision Frame data types.
* Field names as defined in the IEC:2010 standard for HSR. * Field names as defined in the IEC:2010 standard for HSR.
*/ */
struct hsr_sup_tag { struct hsr_sup_tag {
__be16 path_and_HSR_Ver; __be16 path_and_HSR_ver;
__be16 sequence_nr; __be16 sequence_nr;
__u8 HSR_TLV_Type; __u8 HSR_TLV_type;
__u8 HSR_TLV_Length; __u8 HSR_TLV_length;
} __packed; } __packed;
struct hsr_sup_payload { struct hsr_sup_payload {
unsigned char MacAddressA[ETH_ALEN]; unsigned char macaddress_A[ETH_ALEN];
} __packed; } __packed;
static inline u16 get_hsr_stag_path(struct hsr_sup_tag *hst) static inline u16 get_hsr_stag_path(struct hsr_sup_tag *hst)
{ {
return get_hsr_tag_path((struct hsr_tag *) hst); return get_hsr_tag_path((struct hsr_tag *)hst);
} }
static inline u16 get_hsr_stag_HSR_ver(struct hsr_sup_tag *hst) static inline u16 get_hsr_stag_HSR_ver(struct hsr_sup_tag *hst)
{ {
return get_hsr_tag_LSDU_size((struct hsr_tag *) hst); return get_hsr_tag_LSDU_size((struct hsr_tag *)hst);
} }
static inline void set_hsr_stag_path(struct hsr_sup_tag *hst, u16 path) static inline void set_hsr_stag_path(struct hsr_sup_tag *hst, u16 path)
{ {
set_hsr_tag_path((struct hsr_tag *) hst, path); set_hsr_tag_path((struct hsr_tag *)hst, path);
} }
static inline void set_hsr_stag_HSR_Ver(struct hsr_sup_tag *hst, u16 HSR_Ver) static inline void set_hsr_stag_HSR_ver(struct hsr_sup_tag *hst, u16 HSR_ver)
{ {
set_hsr_tag_LSDU_size((struct hsr_tag *) hst, HSR_Ver); set_hsr_tag_LSDU_size((struct hsr_tag *)hst, HSR_ver);
} }
struct hsrv0_ethhdr_sp { struct hsrv0_ethhdr_sp {
...@@ -145,7 +134,6 @@ struct hsrv1_ethhdr_sp { ...@@ -145,7 +134,6 @@ struct hsrv1_ethhdr_sp {
struct hsr_sup_tag hsr_sup; struct hsr_sup_tag hsr_sup;
} __packed; } __packed;
enum hsr_port_type { enum hsr_port_type {
HSR_PT_NONE = 0, /* Must be 0, used by framereg */ HSR_PT_NONE = 0, /* Must be 0, used by framereg */
HSR_PT_SLAVE_A, HSR_PT_SLAVE_A,
...@@ -171,10 +159,14 @@ struct hsr_priv { ...@@ -171,10 +159,14 @@ struct hsr_priv {
struct timer_list prune_timer; struct timer_list prune_timer;
int announce_count; int announce_count;
u16 sequence_nr; u16 sequence_nr;
u16 sup_sequence_nr; /* For HSRv1 separate seq_nr for supervision */ u16 sup_sequence_nr; /* For HSRv1 separate seq_nr for supervision */
u8 protVersion; /* Indicate if HSRv0 or HSRv1. */ u8 prot_version; /* Indicate if HSRv0 or HSRv1. */
spinlock_t seqnr_lock; /* locking for sequence_nr */ spinlock_t seqnr_lock; /* locking for sequence_nr */
unsigned char sup_multicast_addr[ETH_ALEN]; unsigned char sup_multicast_addr[ETH_ALEN];
#ifdef CONFIG_DEBUG_FS
struct dentry *node_tbl_root;
struct dentry *node_tbl_file;
#endif
}; };
#define hsr_for_each_port(hsr, port) \ #define hsr_for_each_port(hsr, port) \
...@@ -187,8 +179,21 @@ static inline u16 hsr_get_skb_sequence_nr(struct sk_buff *skb) ...@@ -187,8 +179,21 @@ static inline u16 hsr_get_skb_sequence_nr(struct sk_buff *skb)
{ {
struct hsr_ethhdr *hsr_ethhdr; struct hsr_ethhdr *hsr_ethhdr;
hsr_ethhdr = (struct hsr_ethhdr *) skb_mac_header(skb); hsr_ethhdr = (struct hsr_ethhdr *)skb_mac_header(skb);
return ntohs(hsr_ethhdr->hsr_tag.sequence_nr); return ntohs(hsr_ethhdr->hsr_tag.sequence_nr);
} }
#if IS_ENABLED(CONFIG_DEBUG_FS)
int hsr_prp_debugfs_init(struct hsr_priv *priv);
void hsr_prp_debugfs_term(struct hsr_priv *priv);
#else
static inline int hsr_prp_debugfs_init(struct hsr_priv *priv)
{
return 0;
}
static inline void hsr_prp_debugfs_term(struct hsr_priv *priv)
{}
#endif
#endif /* __HSR_PRIVATE_H */ #endif /* __HSR_PRIVATE_H */
// SPDX-License-Identifier: GPL-2.0
/* Copyright 2011-2014 Autronica Fire and Security AS /* Copyright 2011-2014 Autronica Fire and Security AS
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
* *
* Author(s): * Author(s):
* 2011-2014 Arvid Brodin, arvid.brodin@alten.se * 2011-2014 Arvid Brodin, arvid.brodin@alten.se
...@@ -28,7 +24,6 @@ static const struct nla_policy hsr_policy[IFLA_HSR_MAX + 1] = { ...@@ -28,7 +24,6 @@ static const struct nla_policy hsr_policy[IFLA_HSR_MAX + 1] = {
[IFLA_HSR_SEQ_NR] = { .type = NLA_U16 }, [IFLA_HSR_SEQ_NR] = { .type = NLA_U16 },
}; };
/* Here, it seems a netdevice has already been allocated for us, and the /* Here, it seems a netdevice has already been allocated for us, and the
* hsr_dev_setup routine has been executed. Nice! * hsr_dev_setup routine has been executed. Nice!
*/ */
...@@ -47,12 +42,14 @@ static int hsr_newlink(struct net *src_net, struct net_device *dev, ...@@ -47,12 +42,14 @@ static int hsr_newlink(struct net *src_net, struct net_device *dev,
netdev_info(dev, "HSR: Slave1 device not specified\n"); netdev_info(dev, "HSR: Slave1 device not specified\n");
return -EINVAL; return -EINVAL;
} }
link[0] = __dev_get_by_index(src_net, nla_get_u32(data[IFLA_HSR_SLAVE1])); link[0] = __dev_get_by_index(src_net,
nla_get_u32(data[IFLA_HSR_SLAVE1]));
if (!data[IFLA_HSR_SLAVE2]) { if (!data[IFLA_HSR_SLAVE2]) {
netdev_info(dev, "HSR: Slave2 device not specified\n"); netdev_info(dev, "HSR: Slave2 device not specified\n");
return -EINVAL; return -EINVAL;
} }
link[1] = __dev_get_by_index(src_net, nla_get_u32(data[IFLA_HSR_SLAVE2])); link[1] = __dev_get_by_index(src_net,
nla_get_u32(data[IFLA_HSR_SLAVE2]));
if (!link[0] || !link[1]) if (!link[0] || !link[1])
return -ENODEV; return -ENODEV;
...@@ -119,8 +116,6 @@ static struct rtnl_link_ops hsr_link_ops __read_mostly = { ...@@ -119,8 +116,6 @@ static struct rtnl_link_ops hsr_link_ops __read_mostly = {
.fill_info = hsr_fill_info, .fill_info = hsr_fill_info,
}; };
/* attribute policy */ /* attribute policy */
static const struct nla_policy hsr_genl_policy[HSR_A_MAX + 1] = { static const struct nla_policy hsr_genl_policy[HSR_A_MAX + 1] = {
[HSR_A_NODE_ADDR] = { .len = ETH_ALEN }, [HSR_A_NODE_ADDR] = { .len = ETH_ALEN },
...@@ -138,8 +133,6 @@ static const struct genl_multicast_group hsr_mcgrps[] = { ...@@ -138,8 +133,6 @@ static const struct genl_multicast_group hsr_mcgrps[] = {
{ .name = "hsr-network", }, { .name = "hsr-network", },
}; };
/* This is called if for some node with MAC address addr, we only get frames /* This is called if for some node with MAC address addr, we only get frames
* over one of the slave interfaces. This would indicate an open network ring * over one of the slave interfaces. This would indicate an open network ring
* (i.e. a link has failed somewhere). * (i.e. a link has failed somewhere).
...@@ -156,7 +149,8 @@ void hsr_nl_ringerror(struct hsr_priv *hsr, unsigned char addr[ETH_ALEN], ...@@ -156,7 +149,8 @@ void hsr_nl_ringerror(struct hsr_priv *hsr, unsigned char addr[ETH_ALEN],
if (!skb) if (!skb)
goto fail; goto fail;
msg_head = genlmsg_put(skb, 0, 0, &hsr_genl_family, 0, HSR_C_RING_ERROR); msg_head = genlmsg_put(skb, 0, 0, &hsr_genl_family, 0,
HSR_C_RING_ERROR);
if (!msg_head) if (!msg_head)
goto nla_put_failure; goto nla_put_failure;
...@@ -201,7 +195,6 @@ void hsr_nl_nodedown(struct hsr_priv *hsr, unsigned char addr[ETH_ALEN]) ...@@ -201,7 +195,6 @@ void hsr_nl_nodedown(struct hsr_priv *hsr, unsigned char addr[ETH_ALEN])
if (!msg_head) if (!msg_head)
goto nla_put_failure; goto nla_put_failure;
res = nla_put(skb, HSR_A_NODE_ADDR, ETH_ALEN, addr); res = nla_put(skb, HSR_A_NODE_ADDR, ETH_ALEN, addr);
if (res < 0) if (res < 0)
goto nla_put_failure; goto nla_put_failure;
...@@ -221,7 +214,6 @@ void hsr_nl_nodedown(struct hsr_priv *hsr, unsigned char addr[ETH_ALEN]) ...@@ -221,7 +214,6 @@ void hsr_nl_nodedown(struct hsr_priv *hsr, unsigned char addr[ETH_ALEN])
rcu_read_unlock(); rcu_read_unlock();
} }
/* HSR_C_GET_NODE_STATUS lets userspace query the internal HSR node table /* HSR_C_GET_NODE_STATUS lets userspace query the internal HSR node table
* about the status of a specific node in the network, defined by its MAC * about the status of a specific node in the network, defined by its MAC
* address. * address.
...@@ -260,15 +252,13 @@ static int hsr_get_node_status(struct sk_buff *skb_in, struct genl_info *info) ...@@ -260,15 +252,13 @@ static int hsr_get_node_status(struct sk_buff *skb_in, struct genl_info *info)
goto invalid; goto invalid;
hsr_dev = __dev_get_by_index(genl_info_net(info), hsr_dev = __dev_get_by_index(genl_info_net(info),
nla_get_u32(info->attrs[HSR_A_IFINDEX])); nla_get_u32(info->attrs[HSR_A_IFINDEX]));
if (!hsr_dev) if (!hsr_dev)
goto invalid; goto invalid;
if (!is_hsr_master(hsr_dev)) if (!is_hsr_master(hsr_dev))
goto invalid; goto invalid;
/* Send reply */ /* Send reply */
skb_out = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); skb_out = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
if (!skb_out) { if (!skb_out) {
res = -ENOMEM; res = -ENOMEM;
...@@ -276,8 +266,8 @@ static int hsr_get_node_status(struct sk_buff *skb_in, struct genl_info *info) ...@@ -276,8 +266,8 @@ static int hsr_get_node_status(struct sk_buff *skb_in, struct genl_info *info)
} }
msg_head = genlmsg_put(skb_out, NETLINK_CB(skb_in).portid, msg_head = genlmsg_put(skb_out, NETLINK_CB(skb_in).portid,
info->snd_seq, &hsr_genl_family, 0, info->snd_seq, &hsr_genl_family, 0,
HSR_C_SET_NODE_STATUS); HSR_C_SET_NODE_STATUS);
if (!msg_head) { if (!msg_head) {
res = -ENOMEM; res = -ENOMEM;
goto nla_put_failure; goto nla_put_failure;
...@@ -289,28 +279,30 @@ static int hsr_get_node_status(struct sk_buff *skb_in, struct genl_info *info) ...@@ -289,28 +279,30 @@ static int hsr_get_node_status(struct sk_buff *skb_in, struct genl_info *info)
hsr = netdev_priv(hsr_dev); hsr = netdev_priv(hsr_dev);
res = hsr_get_node_data(hsr, res = hsr_get_node_data(hsr,
(unsigned char *) nla_data(info->attrs[HSR_A_NODE_ADDR]), (unsigned char *)
hsr_node_addr_b, nla_data(info->attrs[HSR_A_NODE_ADDR]),
&addr_b_ifindex, hsr_node_addr_b,
&hsr_node_if1_age, &addr_b_ifindex,
&hsr_node_if1_seq, &hsr_node_if1_age,
&hsr_node_if2_age, &hsr_node_if1_seq,
&hsr_node_if2_seq); &hsr_node_if2_age,
&hsr_node_if2_seq);
if (res < 0) if (res < 0)
goto nla_put_failure; goto nla_put_failure;
res = nla_put(skb_out, HSR_A_NODE_ADDR, ETH_ALEN, res = nla_put(skb_out, HSR_A_NODE_ADDR, ETH_ALEN,
nla_data(info->attrs[HSR_A_NODE_ADDR])); nla_data(info->attrs[HSR_A_NODE_ADDR]));
if (res < 0) if (res < 0)
goto nla_put_failure; goto nla_put_failure;
if (addr_b_ifindex > -1) { if (addr_b_ifindex > -1) {
res = nla_put(skb_out, HSR_A_NODE_ADDR_B, ETH_ALEN, res = nla_put(skb_out, HSR_A_NODE_ADDR_B, ETH_ALEN,
hsr_node_addr_b); hsr_node_addr_b);
if (res < 0) if (res < 0)
goto nla_put_failure; goto nla_put_failure;
res = nla_put_u32(skb_out, HSR_A_ADDR_B_IFINDEX, addr_b_ifindex); res = nla_put_u32(skb_out, HSR_A_ADDR_B_IFINDEX,
addr_b_ifindex);
if (res < 0) if (res < 0)
goto nla_put_failure; goto nla_put_failure;
} }
...@@ -392,9 +384,7 @@ static int hsr_get_node_list(struct sk_buff *skb_in, struct genl_info *info) ...@@ -392,9 +384,7 @@ static int hsr_get_node_list(struct sk_buff *skb_in, struct genl_info *info)
if (!is_hsr_master(hsr_dev)) if (!is_hsr_master(hsr_dev))
goto invalid; goto invalid;
/* Send reply */ /* Send reply */
skb_out = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); skb_out = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
if (!skb_out) { if (!skb_out) {
res = -ENOMEM; res = -ENOMEM;
...@@ -402,8 +392,8 @@ static int hsr_get_node_list(struct sk_buff *skb_in, struct genl_info *info) ...@@ -402,8 +392,8 @@ static int hsr_get_node_list(struct sk_buff *skb_in, struct genl_info *info)
} }
msg_head = genlmsg_put(skb_out, NETLINK_CB(skb_in).portid, msg_head = genlmsg_put(skb_out, NETLINK_CB(skb_in).portid,
info->snd_seq, &hsr_genl_family, 0, info->snd_seq, &hsr_genl_family, 0,
HSR_C_SET_NODE_LIST); HSR_C_SET_NODE_LIST);
if (!msg_head) { if (!msg_head) {
res = -ENOMEM; res = -ENOMEM;
goto nla_put_failure; goto nla_put_failure;
...@@ -444,7 +434,6 @@ static int hsr_get_node_list(struct sk_buff *skb_in, struct genl_info *info) ...@@ -444,7 +434,6 @@ static int hsr_get_node_list(struct sk_buff *skb_in, struct genl_info *info)
return res; return res;
} }
static const struct genl_ops hsr_ops[] = { static const struct genl_ops hsr_ops[] = {
{ {
.cmd = HSR_C_GET_NODE_STATUS, .cmd = HSR_C_GET_NODE_STATUS,
......
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright 2011-2014 Autronica Fire and Security AS /* Copyright 2011-2014 Autronica Fire and Security AS
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
* *
* Author(s): * Author(s):
* 2011-2014 Arvid Brodin, arvid.brodin@alten.se * 2011-2014 Arvid Brodin, arvid.brodin@alten.se
......
/*
* hsr_prp_debugfs code
* Copyright (C) 2017 Texas Instruments Incorporated
*
* Author(s):
* Murali Karicheri <m-karicheri2@ti.com?
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation version 2.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/debugfs.h>
#include "hsr_main.h"
#include "hsr_framereg.h"
static void print_mac_address(struct seq_file *sfp, unsigned char *mac)
{
seq_printf(sfp, "%02x:%02x:%02x:%02x:%02x:%02x:",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}
/* hsr_prp_node_table_show - Formats and prints node_table entries */
static int
hsr_prp_node_table_show(struct seq_file *sfp, void *data)
{
struct hsr_priv *priv = (struct hsr_priv *)sfp->private;
struct hsr_node *node;
seq_puts(sfp, "Node Table entries\n");
seq_puts(sfp, "MAC-Address-A, MAC-Address-B, time_in[A], ");
seq_puts(sfp, "time_in[B], Address-B port\n");
rcu_read_lock();
list_for_each_entry_rcu(node, &priv->node_db, mac_list) {
/* skip self node */
if (hsr_addr_is_self(priv, node->macaddress_A))
continue;
print_mac_address(sfp, &node->macaddress_A[0]);
seq_puts(sfp, " ");
print_mac_address(sfp, &node->macaddress_B[0]);
seq_printf(sfp, "0x%lx, ", node->time_in[HSR_PT_SLAVE_A]);
seq_printf(sfp, "0x%lx ", node->time_in[HSR_PT_SLAVE_B]);
seq_printf(sfp, "0x%x\n", node->addr_B_port);
}
rcu_read_unlock();
return 0;
}
/* hsr_prp_node_table_open - Open the node_table file
*
* Description:
* This routine opens a debugfs file node_table of specific hsr device
*/
static int
hsr_prp_node_table_open(struct inode *inode, struct file *filp)
{
return single_open(filp, hsr_prp_node_table_show, inode->i_private);
}
static const struct file_operations hsr_prp_fops = {
.owner = THIS_MODULE,
.open = hsr_prp_node_table_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
/* hsr_prp_debugfs_init - create hsr-prp node_table file for dumping
* the node table
*
* Description:
* When debugfs is configured this routine sets up the node_table file per
* hsr/prp device for dumping the node_table entries
*/
int hsr_prp_debugfs_init(struct hsr_priv *priv)
{
int rc = -1;
struct dentry *de = NULL;
de = debugfs_create_dir("hsr", NULL);
if (!de) {
pr_err("Cannot create hsr-prp debugfs root\n");
return rc;
}
priv->node_tbl_root = de;
de = debugfs_create_file("node_table", S_IFREG | 0444,
priv->node_tbl_root, priv,
&hsr_prp_fops);
if (!de) {
pr_err("Cannot create hsr-prp node_table directory\n");
return rc;
}
priv->node_tbl_file = de;
rc = 0;
return rc;
}
/* hsr_prp_debugfs_term - Tear down debugfs intrastructure
*
* Description:
* When Debufs is configured this routine removes debugfs file system
* elements that are specific to hsr-prp
*/
void
hsr_prp_debugfs_term(struct hsr_priv *priv)
{
debugfs_remove(priv->node_tbl_file);
priv->node_tbl_file = NULL;
debugfs_remove(priv->node_tbl_root);
priv->node_tbl_root = NULL;
}
// SPDX-License-Identifier: GPL-2.0
/* Copyright 2011-2014 Autronica Fire and Security AS /* Copyright 2011-2014 Autronica Fire and Security AS
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
* *
* Author(s): * Author(s):
* 2011-2014 Arvid Brodin, arvid.brodin@alten.se * 2011-2014 Arvid Brodin, arvid.brodin@alten.se
...@@ -18,7 +14,6 @@ ...@@ -18,7 +14,6 @@
#include "hsr_forward.h" #include "hsr_forward.h"
#include "hsr_framereg.h" #include "hsr_framereg.h"
static rx_handler_result_t hsr_handle_frame(struct sk_buff **pskb) static rx_handler_result_t hsr_handle_frame(struct sk_buff **pskb)
{ {
struct sk_buff *skb = *pskb; struct sk_buff *skb = *pskb;
...@@ -61,12 +56,11 @@ bool hsr_port_exists(const struct net_device *dev) ...@@ -61,12 +56,11 @@ bool hsr_port_exists(const struct net_device *dev)
return rcu_access_pointer(dev->rx_handler) == hsr_handle_frame; return rcu_access_pointer(dev->rx_handler) == hsr_handle_frame;
} }
static int hsr_check_dev_ok(struct net_device *dev) static int hsr_check_dev_ok(struct net_device *dev)
{ {
/* Don't allow HSR on non-ethernet like devices */ /* Don't allow HSR on non-ethernet like devices */
if ((dev->flags & IFF_LOOPBACK) || (dev->type != ARPHRD_ETHER) || if ((dev->flags & IFF_LOOPBACK) || dev->type != ARPHRD_ETHER ||
(dev->addr_len != ETH_ALEN)) { dev->addr_len != ETH_ALEN) {
netdev_info(dev, "Cannot use loopback or non-ethernet device as HSR slave.\n"); netdev_info(dev, "Cannot use loopback or non-ethernet device as HSR slave.\n");
return -EINVAL; return -EINVAL;
} }
...@@ -99,7 +93,6 @@ static int hsr_check_dev_ok(struct net_device *dev) ...@@ -99,7 +93,6 @@ static int hsr_check_dev_ok(struct net_device *dev)
return 0; return 0;
} }
/* Setup device to be added to the HSR bridge. */ /* Setup device to be added to the HSR bridge. */
static int hsr_portdev_setup(struct net_device *dev, struct hsr_port *port) static int hsr_portdev_setup(struct net_device *dev, struct hsr_port *port)
{ {
...@@ -143,11 +136,11 @@ int hsr_add_port(struct hsr_priv *hsr, struct net_device *dev, ...@@ -143,11 +136,11 @@ int hsr_add_port(struct hsr_priv *hsr, struct net_device *dev,
} }
port = hsr_port_get_hsr(hsr, type); port = hsr_port_get_hsr(hsr, type);
if (port != NULL) if (port)
return -EBUSY; /* This port already exists */ return -EBUSY; /* This port already exists */
port = kzalloc(sizeof(*port), GFP_KERNEL); port = kzalloc(sizeof(*port), GFP_KERNEL);
if (port == NULL) if (!port)
return -ENOMEM; return -ENOMEM;
if (type != HSR_PT_MASTER) { if (type != HSR_PT_MASTER) {
...@@ -184,7 +177,7 @@ void hsr_del_port(struct hsr_port *port) ...@@ -184,7 +177,7 @@ void hsr_del_port(struct hsr_port *port)
list_del_rcu(&port->port_list); list_del_rcu(&port->port_list);
if (port != master) { if (port != master) {
if (master != NULL) { if (master) {
netdev_update_features(master->dev); netdev_update_features(master->dev);
dev_set_mtu(master->dev, hsr_get_max_mtu(hsr)); dev_set_mtu(master->dev, hsr_get_max_mtu(hsr));
} }
......
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright 2011-2014 Autronica Fire and Security AS /* Copyright 2011-2014 Autronica Fire and Security AS
* *
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* Author(s):
* 2011-2014 Arvid Brodin, arvid.brodin@alten.se * 2011-2014 Arvid Brodin, arvid.brodin@alten.se
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment