8f4c0e0178
Parallel Redundancy Protocol (PRP) is another redundancy protocol introduced by IEC 63439 standard. It is similar to HSR in many aspects:- - Use a pair of Ethernet interfaces to created the PRP device - Use a 6 byte redundancy protocol part (RCT, Redundancy Check Trailer) similar to HSR Tag. - Has Link Redundancy Entity (LRE) that works with RCT to implement redundancy. Key difference is that the protocol unit is a trailer instead of a prefix as in HSR. That makes it inter-operable with tradition network components such as bridges/switches which treat it as pad bytes, whereas HSR nodes requires some kind of translators (Called redbox) to talk to regular network devices. This features allows regular linux box to be converted to a DAN-P box. DAN-P stands for Dual Attached Node - PRP similar to DAN-H (Dual Attached Node - HSR). Add a comment at the header/source code to explicitly state that the driver files also handles PRP protocol as well. Signed-off-by: Murali Karicheri <m-karicheri2@ti.com> Signed-off-by: David S. Miller <davem@davemloft.net>
145 lines
3.9 KiB
C
145 lines
3.9 KiB
C
/*
|
|
* debugfs code for HSR & PRP
|
|
* Copyright (C) 2019 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 struct dentry *hsr_debugfs_root_dir;
|
|
|
|
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_node_table_show - Formats and prints node_table entries */
|
|
static int
|
|
hsr_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_node_table_open - Open the node_table file
|
|
*
|
|
* Description:
|
|
* This routine opens a debugfs file node_table of specific hsr device
|
|
*/
|
|
static int
|
|
hsr_node_table_open(struct inode *inode, struct file *filp)
|
|
{
|
|
return single_open(filp, hsr_node_table_show, inode->i_private);
|
|
}
|
|
|
|
void hsr_debugfs_rename(struct net_device *dev)
|
|
{
|
|
struct hsr_priv *priv = netdev_priv(dev);
|
|
struct dentry *d;
|
|
|
|
d = debugfs_rename(hsr_debugfs_root_dir, priv->node_tbl_root,
|
|
hsr_debugfs_root_dir, dev->name);
|
|
if (IS_ERR(d))
|
|
netdev_warn(dev, "failed to rename\n");
|
|
else
|
|
priv->node_tbl_root = d;
|
|
}
|
|
|
|
static const struct file_operations hsr_fops = {
|
|
.open = hsr_node_table_open,
|
|
.read = seq_read,
|
|
.llseek = seq_lseek,
|
|
.release = single_release,
|
|
};
|
|
|
|
/* hsr_debugfs_init - create hsr node_table file for dumping
|
|
* the node table
|
|
*
|
|
* Description:
|
|
* When debugfs is configured this routine sets up the node_table file per
|
|
* hsr device for dumping the node_table entries
|
|
*/
|
|
void hsr_debugfs_init(struct hsr_priv *priv, struct net_device *hsr_dev)
|
|
{
|
|
struct dentry *de = NULL;
|
|
|
|
de = debugfs_create_dir(hsr_dev->name, hsr_debugfs_root_dir);
|
|
if (IS_ERR(de)) {
|
|
pr_err("Cannot create hsr debugfs directory\n");
|
|
return;
|
|
}
|
|
|
|
priv->node_tbl_root = de;
|
|
|
|
de = debugfs_create_file("node_table", S_IFREG | 0444,
|
|
priv->node_tbl_root, priv,
|
|
&hsr_fops);
|
|
if (IS_ERR(de)) {
|
|
pr_err("Cannot create hsr node_table file\n");
|
|
debugfs_remove(priv->node_tbl_root);
|
|
priv->node_tbl_root = NULL;
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* hsr_debugfs_term - Tear down debugfs intrastructure
|
|
*
|
|
* Description:
|
|
* When Debufs is configured this routine removes debugfs file system
|
|
* elements that are specific to hsr
|
|
*/
|
|
void
|
|
hsr_debugfs_term(struct hsr_priv *priv)
|
|
{
|
|
debugfs_remove_recursive(priv->node_tbl_root);
|
|
priv->node_tbl_root = NULL;
|
|
}
|
|
|
|
void hsr_debugfs_create_root(void)
|
|
{
|
|
hsr_debugfs_root_dir = debugfs_create_dir("hsr", NULL);
|
|
if (IS_ERR(hsr_debugfs_root_dir)) {
|
|
pr_err("Cannot create hsr debugfs root directory\n");
|
|
hsr_debugfs_root_dir = NULL;
|
|
}
|
|
}
|
|
|
|
void hsr_debugfs_remove_root(void)
|
|
{
|
|
/* debugfs_remove() internally checks NULL and ERROR */
|
|
debugfs_remove(hsr_debugfs_root_dir);
|
|
}
|