/* Copyright 2011-2013 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-2013 Arvid Brodin, arvid.brodin@xdin.com
 *
 * The HSR spec says never to forward the same frame twice on the same
 * interface. A frame is identified by its source MAC address and its HSR
 * sequence number. This code keeps track of senders and their sequence numbers
 * to allow filtering of duplicate frames, and to detect HSR ring errors.
 */

#include <linux/if_ether.h>
#include <linux/etherdevice.h>
#include <linux/slab.h>
#include <linux/rculist.h>
#include "hsr_main.h"
#include "hsr_framereg.h"
#include "hsr_netlink.h"


struct node_entry {
	struct list_head mac_list;
	unsigned char	MacAddressA[ETH_ALEN];
	unsigned char	MacAddressB[ETH_ALEN];
	enum hsr_dev_idx   AddrB_if;	/* The local slave through which AddrB
					 * frames are received from this node
					 */
	unsigned long	time_in[HSR_MAX_SLAVE];
	bool		time_in_stale[HSR_MAX_SLAVE];
	u16		seq_out[HSR_MAX_DEV];
	struct rcu_head rcu_head;
};

/*	TODO: use hash lists for mac addresses (linux/jhash.h)?    */



/* Search for mac entry. Caller must hold rcu read lock.
 */
static struct node_entry *find_node_by_AddrA(struct list_head *node_db,
					     const unsigned char addr[ETH_ALEN])
{
	struct node_entry *node;

	list_for_each_entry_rcu(node, node_db, mac_list) {
		if (ether_addr_equal(node->MacAddressA, addr))
			return node;
	}

	return NULL;
}


/* Search for mac entry. Caller must hold rcu read lock.
 */
static struct node_entry *find_node_by_AddrB(struct list_head *node_db,
					     const unsigned char addr[ETH_ALEN])
{
	struct node_entry *node;

	list_for_each_entry_rcu(node, node_db, mac_list) {
		if (ether_addr_equal(node->MacAddressB, addr))
			return node;
	}

	return NULL;
}


/* Search for mac entry. Caller must hold rcu read lock.
 */
struct node_entry *hsr_find_node(struct list_head *node_db, struct sk_buff *skb)
{
	struct node_entry *node;
	struct ethhdr *ethhdr;

	if (!skb_mac_header_was_set(skb))
		return NULL;

	ethhdr = (struct ethhdr *) skb_mac_header(skb);

	list_for_each_entry_rcu(node, node_db, mac_list) {
		if (ether_addr_equal(node->MacAddressA, ethhdr->h_source))
			return node;
		if (ether_addr_equal(node->MacAddressB, ethhdr->h_source))
			return node;
	}

	return NULL;
}


/* Helper for device init; the self_node_db is used in hsr_rcv() to recognize
 * frames from self that's been looped over the HSR ring.
 */
int hsr_create_self_node(struct list_head *self_node_db,
			 unsigned char addr_a[ETH_ALEN],
			 unsigned char addr_b[ETH_ALEN])
{
	struct node_entry *node, *oldnode;

	node = kmalloc(sizeof(*node), GFP_KERNEL);
	if (!node)
		return -ENOMEM;

	memcpy(node->MacAddressA, addr_a, ETH_ALEN);
	memcpy(node->MacAddressB, addr_b, ETH_ALEN);

	rcu_read_lock();
	oldnode = list_first_or_null_rcu(self_node_db,
						struct node_entry, mac_list);
	if (oldnode) {
		list_replace_rcu(&oldnode->mac_list, &node->mac_list);
		rcu_read_unlock();
		synchronize_rcu();
		kfree(oldnode);
	} else {
		rcu_read_unlock();
		list_add_tail_rcu(&node->mac_list, self_node_db);
	}

	return 0;
}


/* Add/merge node to the database of nodes. 'skb' must contain an HSR
 * supervision frame.
 * - If the supervision header's MacAddressA field is not yet in the database,
 * this frame is from an hitherto unknown node - add it to the database.
 * - If the sender's MAC address is not the same as its MacAddressA address,
 * the node is using PICS_SUBS (address substitution). Record the sender's
 * address as the node's MacAddressB.
 *
 * This function needs to work even if the sender node has changed one of its
 * slaves' MAC addresses. In this case, there are four different cases described
 * by (Addr-changed, received-from) pairs as follows. Note that changing the
 * SlaveA address is equal to changing the node's own address:
 *
 * - (AddrB, SlaveB): The new AddrB will be recorded by PICS_SUBS code since
 *		      node == NULL.
 * - (AddrB, SlaveA): Will work as usual (the AddrB change won't be detected
 *		      from this frame).
 *
 * - (AddrA, SlaveB): The old node will be found. We need to detect this and
 *		      remove the node.
 * - (AddrA, SlaveA): A new node will be registered (non-PICS_SUBS at first).
 *		      The old one will be pruned after HSR_NODE_FORGET_TIME.
 *
 * We also need to detect if the sender's SlaveA and SlaveB cables have been
 * swapped.
 */
struct node_entry *hsr_merge_node(struct hsr_priv *hsr_priv,
				  struct node_entry *node,
				  struct sk_buff *skb,
				  enum hsr_dev_idx dev_idx)
{
	struct hsr_sup_payload *hsr_sp;
	struct hsr_ethhdr_sp *hsr_ethsup;
	int i;
	unsigned long now;

	hsr_ethsup = (struct hsr_ethhdr_sp *) skb_mac_header(skb);
	hsr_sp = (struct hsr_sup_payload *) skb->data;

	if (node && !ether_addr_equal(node->MacAddressA, hsr_sp->MacAddressA)) {
		/* Node has changed its AddrA, frame was received from SlaveB */
		list_del_rcu(&node->mac_list);
		kfree_rcu(node, rcu_head);
		node = NULL;
	}

	if (node && (dev_idx == node->AddrB_if) &&
	    !ether_addr_equal(node->MacAddressB, hsr_ethsup->ethhdr.h_source)) {
		/* Cables have been swapped */
		list_del_rcu(&node->mac_list);
		kfree_rcu(node, rcu_head);
		node = NULL;
	}

	if (node && (dev_idx != node->AddrB_if) &&
	    (node->AddrB_if != HSR_DEV_NONE) &&
	    !ether_addr_equal(node->MacAddressA, hsr_ethsup->ethhdr.h_source)) {
		/* Cables have been swapped */
		list_del_rcu(&node->mac_list);
		kfree_rcu(node, rcu_head);
		node = NULL;
	}

	if (node)
		return node;

	node = find_node_by_AddrA(&hsr_priv->node_db, hsr_sp->MacAddressA);
	if (node) {
		/* Node is known, but frame was received from an unknown
		 * address. Node is PICS_SUBS capable; merge its AddrB.
		 */
		memcpy(node->MacAddressB, hsr_ethsup->ethhdr.h_source, ETH_ALEN);
		node->AddrB_if = dev_idx;
		return node;
	}

	node = kzalloc(sizeof(*node), GFP_ATOMIC);
	if (!node)
		return NULL;

	memcpy(node->MacAddressA, hsr_sp->MacAddressA, ETH_ALEN);
	memcpy(node->MacAddressB, hsr_ethsup->ethhdr.h_source, ETH_ALEN);
	if (!ether_addr_equal(hsr_sp->MacAddressA, hsr_ethsup->ethhdr.h_source))
		node->AddrB_if = dev_idx;
	else
		node->AddrB_if = HSR_DEV_NONE;

	/* We are only interested in time diffs here, so use current jiffies
	 * as initialization. (0 could trigger an spurious ring error warning).
	 */
	now = jiffies;
	for (i = 0; i < HSR_MAX_SLAVE; i++)
		node->time_in[i] = now;
	for (i = 0; i < HSR_MAX_DEV; i++)
		node->seq_out[i] = ntohs(hsr_ethsup->hsr_sup.sequence_nr) - 1;

	list_add_tail_rcu(&node->mac_list, &hsr_priv->node_db);

	return node;
}


/* 'skb' is a frame meant for this host, that is to be passed to upper layers.
 *
 * If the frame was sent by a node's B interface, replace the sender
 * address with that node's "official" address (MacAddressA) so that upper
 * layers recognize where it came from.
 */
void hsr_addr_subst_source(struct hsr_priv *hsr_priv, struct sk_buff *skb)
{
	struct ethhdr *ethhdr;
	struct node_entry *node;

	if (!skb_mac_header_was_set(skb)) {
		WARN_ONCE(1, "%s: Mac header not set\n", __func__);
		return;
	}
	ethhdr = (struct ethhdr *) skb_mac_header(skb);

	rcu_read_lock();
	node = find_node_by_AddrB(&hsr_priv->node_db, ethhdr->h_source);
	if (node)
		memcpy(ethhdr->h_source, node->MacAddressA, ETH_ALEN);
	rcu_read_unlock();
}


/* 'skb' is a frame meant for another host.
 * 'hsr_dev_idx' is the HSR index of the outgoing device
 *
 * Substitute the target (dest) MAC address if necessary, so the it matches the
 * recipient interface MAC address, regardless of whether that is the
 * recipient's A or B interface.
 * This is needed to keep the packets flowing through switches that learn on
 * which "side" the different interfaces are.
 */
void hsr_addr_subst_dest(struct hsr_priv *hsr_priv, struct ethhdr *ethhdr,
			 enum hsr_dev_idx dev_idx)
{
	struct node_entry *node;

	rcu_read_lock();
	node = find_node_by_AddrA(&hsr_priv->node_db, ethhdr->h_dest);
	if (node && (node->AddrB_if == dev_idx))
		memcpy(ethhdr->h_dest, node->MacAddressB, ETH_ALEN);
	rcu_read_unlock();
}


/* seq_nr_after(a, b) - return true if a is after (higher in sequence than) b,
 * false otherwise.
 */
static bool seq_nr_after(u16 a, u16 b)
{
	/* Remove inconsistency where
	 * seq_nr_after(a, b) == seq_nr_before(a, b)
	 */
	if ((int) b - a == 32768)
		return false;

	return (((s16) (b - a)) < 0);
}
#define seq_nr_before(a, b)		seq_nr_after((b), (a))
#define seq_nr_after_or_eq(a, b)	(!seq_nr_before((a), (b)))
#define seq_nr_before_or_eq(a, b)	(!seq_nr_after((a), (b)))


void hsr_register_frame_in(struct node_entry *node, enum hsr_dev_idx dev_idx)
{
	if ((dev_idx < 0) || (dev_idx >= HSR_MAX_DEV)) {
		WARN_ONCE(1, "%s: Invalid dev_idx (%d)\n", __func__, dev_idx);
		return;
	}
	node->time_in[dev_idx] = jiffies;
	node->time_in_stale[dev_idx] = false;
}


/* 'skb' is a HSR Ethernet frame (with a HSR tag inserted), with a valid
 * ethhdr->h_source address and skb->mac_header set.
 *
 * Return:
 *	 1 if frame can be shown to have been sent recently on this interface,
 *	 0 otherwise, or
 *	 negative error code on error
 */
int hsr_register_frame_out(struct node_entry *node, enum hsr_dev_idx dev_idx,
			   struct sk_buff *skb)
{
	struct hsr_ethhdr *hsr_ethhdr;
	u16 sequence_nr;

	if ((dev_idx < 0) || (dev_idx >= HSR_MAX_DEV)) {
		WARN_ONCE(1, "%s: Invalid dev_idx (%d)\n", __func__, dev_idx);
		return -EINVAL;
	}
	if (!skb_mac_header_was_set(skb)) {
		WARN_ONCE(1, "%s: Mac header not set\n", __func__);
		return -EINVAL;
	}
	hsr_ethhdr = (struct hsr_ethhdr *) skb_mac_header(skb);

	sequence_nr = ntohs(hsr_ethhdr->hsr_tag.sequence_nr);
	if (seq_nr_before_or_eq(sequence_nr, node->seq_out[dev_idx]))
		return 1;

	node->seq_out[dev_idx] = sequence_nr;
	return 0;
}



static bool is_late(struct node_entry *node, enum hsr_dev_idx dev_idx)
{
	enum hsr_dev_idx other;

	if (node->time_in_stale[dev_idx])
		return true;

	if (dev_idx == HSR_DEV_SLAVE_A)
		other = HSR_DEV_SLAVE_B;
	else
		other = HSR_DEV_SLAVE_A;

	if (node->time_in_stale[other])
		return false;

	if (time_after(node->time_in[other], node->time_in[dev_idx] +
		       msecs_to_jiffies(MAX_SLAVE_DIFF)))
		return true;

	return false;
}


/* Remove stale sequence_nr records. Called by timer every
 * HSR_LIFE_CHECK_INTERVAL (two seconds or so).
 */
void hsr_prune_nodes(struct hsr_priv *hsr_priv)
{
	struct node_entry *node;
	unsigned long timestamp;
	unsigned long time_a, time_b;

	rcu_read_lock();
	list_for_each_entry_rcu(node, &hsr_priv->node_db, mac_list) {
		/* Shorthand */
		time_a = node->time_in[HSR_DEV_SLAVE_A];
		time_b = node->time_in[HSR_DEV_SLAVE_B];

		/* Check for timestamps old enough to risk wrap-around */
		if (time_after(jiffies, time_a + MAX_JIFFY_OFFSET/2))
			node->time_in_stale[HSR_DEV_SLAVE_A] = true;
		if (time_after(jiffies, time_b + MAX_JIFFY_OFFSET/2))
			node->time_in_stale[HSR_DEV_SLAVE_B] = true;

		/* Get age of newest frame from node.
		 * At least one time_in is OK here; nodes get pruned long
		 * before both time_ins can get stale
		 */
		timestamp = time_a;
		if (node->time_in_stale[HSR_DEV_SLAVE_A] ||
		    (!node->time_in_stale[HSR_DEV_SLAVE_B] &&
		    time_after(time_b, time_a)))
			timestamp = time_b;

		/* Warn of ring error only as long as we get frames at all */
		if (time_is_after_jiffies(timestamp +
					msecs_to_jiffies(1.5*MAX_SLAVE_DIFF))) {

			if (is_late(node, HSR_DEV_SLAVE_A))
				hsr_nl_ringerror(hsr_priv, node->MacAddressA,
						 HSR_DEV_SLAVE_A);
			else if (is_late(node, HSR_DEV_SLAVE_B))
				hsr_nl_ringerror(hsr_priv, node->MacAddressA,
						 HSR_DEV_SLAVE_B);
		}

		/* Prune old entries */
		if (time_is_before_jiffies(timestamp +
					msecs_to_jiffies(HSR_NODE_FORGET_TIME))) {
			hsr_nl_nodedown(hsr_priv, node->MacAddressA);
			list_del_rcu(&node->mac_list);
			/* Note that we need to free this entry later: */
			kfree_rcu(node, rcu_head);
		}
	}
	rcu_read_unlock();
}


void *hsr_get_next_node(struct hsr_priv *hsr_priv, void *_pos,
			unsigned char addr[ETH_ALEN])
{
	struct node_entry *node;

	if (!_pos) {
		node = list_first_or_null_rcu(&hsr_priv->node_db,
						struct node_entry, mac_list);
		if (node)
			memcpy(addr, node->MacAddressA, ETH_ALEN);
		return node;
	}

	node = _pos;
	list_for_each_entry_continue_rcu(node, &hsr_priv->node_db, mac_list) {
		memcpy(addr, node->MacAddressA, ETH_ALEN);
		return node;
	}

	return NULL;
}


int hsr_get_node_data(struct hsr_priv *hsr_priv,
		      const unsigned char *addr,
		      unsigned char addr_b[ETH_ALEN],
		      unsigned int *addr_b_ifindex,
		      int *if1_age,
		      u16 *if1_seq,
		      int *if2_age,
		      u16 *if2_seq)
{
	struct node_entry *node;
	unsigned long tdiff;


	rcu_read_lock();
	node = find_node_by_AddrA(&hsr_priv->node_db, addr);
	if (!node) {
		rcu_read_unlock();
		return -ENOENT;	/* No such entry */
	}

	memcpy(addr_b, node->MacAddressB, ETH_ALEN);

	tdiff = jiffies - node->time_in[HSR_DEV_SLAVE_A];
	if (node->time_in_stale[HSR_DEV_SLAVE_A])
		*if1_age = INT_MAX;
#if HZ <= MSEC_PER_SEC
	else if (tdiff > msecs_to_jiffies(INT_MAX))
		*if1_age = INT_MAX;
#endif
	else
		*if1_age = jiffies_to_msecs(tdiff);

	tdiff = jiffies - node->time_in[HSR_DEV_SLAVE_B];
	if (node->time_in_stale[HSR_DEV_SLAVE_B])
		*if2_age = INT_MAX;
#if HZ <= MSEC_PER_SEC
	else if (tdiff > msecs_to_jiffies(INT_MAX))
		*if2_age = INT_MAX;
#endif
	else
		*if2_age = jiffies_to_msecs(tdiff);

	/* Present sequence numbers as if they were incoming on interface */
	*if1_seq = node->seq_out[HSR_DEV_SLAVE_B];
	*if2_seq = node->seq_out[HSR_DEV_SLAVE_A];

	if ((node->AddrB_if != HSR_DEV_NONE) && hsr_priv->slave[node->AddrB_if])
		*addr_b_ifindex = hsr_priv->slave[node->AddrB_if]->ifindex;
	else
		*addr_b_ifindex = -1;

	rcu_read_unlock();

	return 0;
}
