Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -6,3 +6,4 @@ obj-$(CONFIG_HSR) += hsr.o

hsr-y			:= hsr_main.o hsr_framereg.o hsr_device.o \
			   hsr_netlink.o hsr_slave.o hsr_forward.o
hsr-$(CONFIG_DEBUG_FS) += hsr_prp_debugfs.o
+28 −38
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/* 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
@@ -23,7 +19,6 @@
#include "hsr_main.h"
#include "hsr_forward.h"


static bool is_admin_up(struct net_device *dev)
{
	return dev && (dev->flags & IFF_UP);
@@ -68,7 +63,7 @@ static bool hsr_check_carrier(struct hsr_port *master)

	rcu_read_lock();
	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;
			break;
		}
@@ -82,7 +77,6 @@ static bool hsr_check_carrier(struct hsr_port *master)
	return has_carrier;
}


static void hsr_check_announce(struct net_device *hsr_dev,
			       unsigned char old_operstate)
{
@@ -90,15 +84,14 @@ static void hsr_check_announce(struct net_device *hsr_dev,

	hsr = netdev_priv(hsr_dev);

	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 up */
		hsr->announce_count = 0;
		mod_timer(&hsr->announce_timer,
			  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 */
		del_timer(&hsr->announce_timer);
}
@@ -136,7 +129,6 @@ int hsr_get_max_mtu(struct hsr_priv *hsr)
	return mtu_max - HSR_HLEN;
}


static int hsr_dev_change_mtu(struct net_device *dev, int new_mtu)
{
	struct hsr_priv *hsr;
@@ -191,14 +183,12 @@ static int hsr_dev_open(struct net_device *dev)
	return 0;
}


static int hsr_dev_close(struct net_device *dev)
{
	/* Nothing to do here. */
	return 0;
}


static netdev_features_t hsr_features_recompute(struct hsr_priv *hsr,
						netdev_features_t features)
{
@@ -231,7 +221,6 @@ static netdev_features_t hsr_fix_features(struct net_device *dev,
	return hsr_features_recompute(hsr, features);
}


static int hsr_dev_xmit(struct sk_buff *skb, struct net_device *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)
	return NETDEV_TX_OK;
}


static const struct header_ops hsr_header_ops = {
	.create	 = eth_header,
	.parse	 = eth_header_parse,
};

static void send_hsr_supervision_frame(struct hsr_port *master,
		u8 type, u8 hsrVer)
				       u8 type, u8 hsr_ver)
{
	struct sk_buff *skb;
	int hlen, tlen;
@@ -262,39 +250,38 @@ static void send_hsr_supervision_frame(struct hsr_port *master,

	hlen = LL_RESERVED_SPACE(master->dev);
	tlen = master->dev->needed_tailroom;
	skb = dev_alloc_skb(
			sizeof(struct hsr_tag) +
	skb = dev_alloc_skb(sizeof(struct hsr_tag) +
			    sizeof(struct hsr_sup_tag) +
			    sizeof(struct hsr_sup_payload) + hlen + tlen);

	if (skb == NULL)
	if (!skb)
		return;

	skb_reserve(skb, hlen);

	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;

	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,
			    skb->dev->dev_addr, skb->len) <= 0)
		goto out;
	skb_reset_mac_header(skb);

	if (hsrVer > 0) {
	if (hsr_ver > 0) {
		hsr_tag = skb_put(skb, sizeof(struct hsr_tag));
		hsr_tag->encap_proto = htons(ETH_P_PRP);
		set_hsr_tag_LSDU_size(hsr_tag, HSR_V1_SUP_LSDUSIZE);
	}

	hsr_stag = skb_put(skb, sizeof(struct hsr_sup_tag));
	set_hsr_stag_path(hsr_stag, (hsrVer ? 0x0 : 0xf));
	set_hsr_stag_HSR_Ver(hsr_stag, hsrVer);
	set_hsr_stag_path(hsr_stag, (hsr_ver ? 0x0 : 0xf));
	set_hsr_stag_HSR_ver(hsr_stag, hsr_ver);

	/* From HSRv1 on we have separate supervision sequence numbers. */
	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_tag->sequence_nr = htons(master->hsr->sequence_nr);
		master->hsr->sup_sequence_nr++;
@@ -305,13 +292,14 @@ static void send_hsr_supervision_frame(struct hsr_port *master,
	}
	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? */
	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 */
	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))
		return;
@@ -324,7 +312,6 @@ static void send_hsr_supervision_frame(struct hsr_port *master,
	kfree_skb(skb);
}


/* Announce (supervision frame) timer function
 */
static void hsr_announce(struct timer_list *t)
@@ -338,15 +325,15 @@ static void hsr_announce(struct timer_list *t)
	rcu_read_lock();
	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,
				hsr->protVersion);
					   hsr->prot_version);
		hsr->announce_count++;

		interval = msecs_to_jiffies(HSR_ANNOUNCE_INTERVAL);
	} else {
		send_hsr_supervision_frame(master, HSR_TLV_LIFE_CHECK,
				hsr->protVersion);
					   hsr->prot_version);

		interval = msecs_to_jiffies(HSR_LIFE_CHECK_INTERVAL);
	}
@@ -357,7 +344,6 @@ static void hsr_announce(struct timer_list *t)
	rcu_read_unlock();
}


/* 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...
 */
@@ -368,6 +354,8 @@ static void hsr_dev_destroy(struct net_device *hsr_dev)

	hsr = netdev_priv(hsr_dev);

	hsr_prp_debugfs_term(hsr);

	rtnl_lock();
	hsr_for_each_port(hsr, port)
		hsr_del_port(port);
@@ -423,7 +411,6 @@ void hsr_dev_setup(struct net_device *dev)
	dev->features |= NETIF_F_NETNS_LOCAL;
}


/* Return true if dev is a HSR master; return false otherwise.
 */
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],
	ether_addr_copy(hsr->sup_multicast_addr, def_multicast_addr);
	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?
	 *
@@ -498,6 +485,9 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2],
		goto fail;

	mod_timer(&hsr->prune_timer, jiffies + msecs_to_jiffies(PRUNE_PERIOD));
	res = hsr_prp_debugfs_init(hsr);
	if (res)
		goto fail;

	return 0;

+1 −5
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
/* 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
+39 −51
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/* 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
@@ -17,7 +13,6 @@
#include "hsr_main.h"
#include "hsr_framereg.h"


struct hsr_node;

struct hsr_frame_info {
@@ -32,7 +27,6 @@ struct hsr_frame_info {
	bool is_local_exclusive;
};


/* The uses I can see for these HSR supervision frames are:
 * 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
@@ -50,46 +44,45 @@ struct hsr_frame_info {
 */
static bool is_supervision_frame(struct hsr_priv *hsr, struct sk_buff *skb)
{
	struct ethhdr *ethHdr;
	struct hsr_sup_tag *hsrSupTag;
	struct hsrv1_ethhdr_sp *hsrV1Hdr;
	struct ethhdr *eth_hdr;
	struct hsr_sup_tag *hsr_sup_tag;
	struct hsrv1_ethhdr_sp *hsr_V1_hdr;

	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? */
	if (!ether_addr_equal(ethHdr->h_dest,
	if (!ether_addr_equal(eth_hdr->h_dest,
			      hsr->sup_multicast_addr))
		return false;

	/* Correct ether type?. */
	if (!(ethHdr->h_proto == htons(ETH_P_PRP)
			|| ethHdr->h_proto == htons(ETH_P_HSR)))
	if (!(eth_hdr->h_proto == htons(ETH_P_PRP) ||
	      eth_hdr->h_proto == htons(ETH_P_HSR)))
		return false;

	/* Get the supervision header from correct location. */
	if (ethHdr->h_proto == htons(ETH_P_HSR)) { /* Okay HSRv1. */
		hsrV1Hdr = (struct hsrv1_ethhdr_sp *) skb_mac_header(skb);
		if (hsrV1Hdr->hsr.encap_proto != htons(ETH_P_PRP))
	if (eth_hdr->h_proto == htons(ETH_P_HSR)) { /* Okay HSRv1. */
		hsr_V1_hdr = (struct hsrv1_ethhdr_sp *)skb_mac_header(skb);
		if (hsr_V1_hdr->hsr.encap_proto != htons(ETH_P_PRP))
			return false;

		hsrSupTag = &hsrV1Hdr->hsr_sup;
		hsr_sup_tag = &hsr_V1_hdr->hsr_sup;
	} 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) &&
	    (hsrSupTag->HSR_TLV_Type != HSR_TLV_LIFE_CHECK))
	if (hsr_sup_tag->HSR_TLV_type != HSR_TLV_ANNOUNCE &&
	    hsr_sup_tag->HSR_TLV_type != HSR_TLV_LIFE_CHECK)
		return false;
	if ((hsrSupTag->HSR_TLV_Length != 12) &&
			(hsrSupTag->HSR_TLV_Length !=
					sizeof(struct hsr_sup_payload)))
	if (hsr_sup_tag->HSR_TLV_length != 12 &&
	    hsr_sup_tag->HSR_TLV_length != sizeof(struct hsr_sup_payload))
		return false;

	return true;
}


static struct sk_buff *create_stripped_skb(struct sk_buff *skb_in,
					   struct hsr_frame_info *frame)
{
@@ -100,7 +93,7 @@ static struct sk_buff *create_stripped_skb(struct sk_buff *skb_in,
	skb_pull(skb_in, HSR_HLEN);
	skb = __pskb_copy(skb_in, skb_headroom(skb_in) - HSR_HLEN, GFP_ATOMIC);
	skb_push(skb_in, HSR_HLEN);
	if (skb == NULL)
	if (!skb)
		return NULL;

	skb_reset_mac_header(skb);
@@ -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);
}


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;
	int lane_id;
@@ -150,7 +142,7 @@ static void hsr_fill_tag(struct sk_buff *skb, struct hsr_frame_info *frame,
	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;
	hsr_ethhdr->ethhdr.h_proto = htons(protoVersion ?
	hsr_ethhdr->ethhdr.h_proto = htons(proto_version ?
			ETH_P_HSR : ETH_P_PRP);
}

@@ -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 */
	skb = __pskb_copy(skb_o, skb_headroom(skb_o) + HSR_HLEN, GFP_ATOMIC);
	if (skb == NULL)
	if (!skb)
		return NULL;
	skb_reset_mac_header(skb);

@@ -180,7 +172,7 @@ static struct sk_buff *create_tagged_skb(struct sk_buff *skb_o,
	memmove(dst, src, movelen);
	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;
}
@@ -194,7 +186,7 @@ static struct sk_buff *frame_get_tagged_skb(struct hsr_frame_info *frame,
	if (frame->skb_hsr)
		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");
		return NULL;
	}
@@ -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);
}


static void hsr_deliver_master(struct sk_buff *skb, struct net_device *dev,
			       struct hsr_node *node_src)
{
@@ -237,7 +228,6 @@ static int hsr_xmit(struct sk_buff *skb, struct hsr_port *port,
	return dev_queue_xmit(skb);
}


/* Forward the frame through all devices except:
 * - Back through the receiving device
 * - 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)
			continue;

		/* 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;

		/* 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;

		/* 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)
					   frame->sequence_nr))
			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,
					     frame->node_src,
					     frame->port_rcv);
@@ -283,7 +273,7 @@ static void hsr_forward_do(struct hsr_frame_info *frame)
			skb = frame_get_tagged_skb(frame, port);
		else
			skb = frame_get_stripped_skb(frame, port);
		if (skb == NULL) {
		if (!skb) {
			/* FIXME: Record the dropped frame? */
			continue;
		}
@@ -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,
			     struct hsr_frame_info *frame)
{
@@ -307,16 +296,15 @@ static void check_local_dest(struct hsr_priv *hsr, struct sk_buff *skb,
		frame->is_local_exclusive = false;
	}

	if ((skb->pkt_type == PACKET_HOST) ||
	    (skb->pkt_type == PACKET_MULTICAST) ||
	    (skb->pkt_type == PACKET_BROADCAST)) {
	if (skb->pkt_type == PACKET_HOST ||
	    skb->pkt_type == PACKET_MULTICAST ||
	    skb->pkt_type == PACKET_BROADCAST) {
		frame->is_local_dest = true;
	} else {
		frame->is_local_dest = false;
	}
}


static int hsr_fill_frame_info(struct hsr_frame_info *frame,
			       struct sk_buff *skb, struct hsr_port *port)
{
@@ -325,7 +313,7 @@ static int hsr_fill_frame_info(struct hsr_frame_info *frame,

	frame->is_supervision = is_supervision_frame(port->hsr, skb);
	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 */

	ethhdr = (struct ethhdr *)skb_mac_header(skb);
@@ -335,8 +323,8 @@ static int hsr_fill_frame_info(struct hsr_frame_info *frame,
		/* FIXME: */
		WARN_ONCE(1, "HSR: VLAN not yet supported");
	}
	if (ethhdr->h_proto == htons(ETH_P_PRP)
			|| ethhdr->h_proto == htons(ETH_P_HSR)) {
	if (ethhdr->h_proto == htons(ETH_P_PRP) ||
	    ethhdr->h_proto == htons(ETH_P_HSR)) {
		frame->skb_std = NULL;
		frame->skb_hsr = 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)
	hsr_register_frame_in(frame.node_src, port, frame.sequence_nr);
	hsr_forward_do(&frame);

	if (frame.skb_hsr != NULL)
	if (frame.skb_hsr)
		kfree_skb(frame.skb_hsr);
	if (frame.skb_std != NULL)
	if (frame.skb_std)
		kfree_skb(frame.skb_std);
	return;

+1 −5
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
/* 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
Loading