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

static void node_entry_reclaim(struct rcu_head *rh)
{
	kfree(container_of(rh, struct node_entry, rcu_head));
}


/* 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);
		call_rcu(&node->rcu_head, node_entry_reclaim);
		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);
		call_rcu(&node->rcu_head, node_entry_reclaim);
		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);
		call_rcu(&node->rcu_head, node_entry_reclaim);
		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: */
			call_rcu(&node->rcu_head, node_entry_reclaim);
		}
	}
	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;
}
