// SPDX-License-Identifier: GPL-2.0-or-later
#include <linux/mrp_bridge.h>
#include "br_private_mrp.h"
static const u8 mrp_test_dmac[ETH_ALEN] = { 0x1, 0x15, 0x4e, 0x0, 0x0, 0x1 };
static const u8 mrp_in_test_dmac[ETH_ALEN] = { 0x1, 0x15, 0x4e, 0x0, 0x0, 0x3 };
static bool br_mrp_is_ring_port(struct net_bridge_port *p_port,
struct net_bridge_port *s_port,
struct net_bridge_port *port)
{
if (port == p_port ||
port == s_port)
return true;
return false;
}
static bool br_mrp_is_in_port(struct net_bridge_port *i_port,
struct net_bridge_port *port)
{
if (port == i_port)
return true;
return false;
}
static struct net_bridge_port *br_mrp_get_port(struct net_bridge *br,
u32 ifindex)
{
struct net_bridge_port *res = NULL;
struct net_bridge_port *port;
list_for_each_entry(port, &br->port_list, list) {
if (port->dev->ifindex == ifindex) {
res = port;
break;
}
}
return res;
}
static struct br_mrp *br_mrp_find_id(struct net_bridge *br, u32 ring_id)
{
struct br_mrp *res = NULL;
struct br_mrp *mrp;
list_for_each_entry_rcu(mrp, &br->mrp_list, list,
lockdep_rtnl_is_held()) {
if (mrp->ring_id == ring_id) {
res = mrp;
break;
}
}
return res;
}
static struct br_mrp *br_mrp_find_in_id(struct net_bridge *br, u32 in_id)
{
struct br_mrp *res = NULL;
struct br_mrp *mrp;
list_for_each_entry_rcu(mrp, &br->mrp_list, list,
lockdep_rtnl_is_held()) {
if (mrp->in_id == in_id) {
res = mrp;
break;
}
}
return res;
}
static bool br_mrp_unique_ifindex(struct net_bridge *br, u32 ifindex)
{
struct br_mrp *mrp;
list_for_each_entry_rcu(mrp, &br->mrp_list, list,
lockdep_rtnl_is_held()) {
struct net_bridge_port *p;
p = rtnl_dereference(mrp->p_port);
if (p && p->dev->ifindex == ifindex)
return false;
p = rtnl_dereference(mrp->s_port);
if (p && p->dev->ifindex == ifindex)
return false;
p = rtnl_dereference(mrp->i_port);
if (p && p->dev->ifindex == ifindex)
return false;
}
return true;
}
static struct br_mrp *br_mrp_find_port(struct net_bridge *br,
struct net_bridge_port *p)
{
struct br_mrp *res = NULL;
struct br_mrp *mrp;
list_for_each_entry_rcu(mrp, &br->mrp_list, list,
lockdep_rtnl_is_held()) {
if (rcu_access_pointer(mrp->p_port) == p ||
rcu_access_pointer(mrp->s_port) == p ||
rcu_access_pointer(mrp->i_port) == p) {
res = mrp;
break;
}
}
return res;
}
static int br_mrp_next_seq(struct br_mrp *mrp)
{
mrp->seq_id++;
return mrp->seq_id;
}
static struct sk_buff *br_mrp_skb_alloc(struct net_bridge_port *p,
const u8 *src, const u8 *dst)
{
struct ethhdr *eth_hdr;
struct sk_buff *skb;
__be16 *version;
skb = dev_alloc_skb(MRP_MAX_FRAME_LENGTH);
if (!skb)
return NULL;
skb->dev = p->dev;