#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/netdevice.h>
#include <linux/rtnetlink.h>
#include <linux/skbuff.h>
#include <net/switchdev.h>

#include "br_private.h"

static int br_switchdev_mark_get(struct net_bridge *br, struct net_device *dev)
{
	struct net_bridge_port *p;

	/* dev is yet to be added to the port list. */
	list_for_each_entry(p, &br->port_list, list) {
		if (switchdev_port_same_parent_id(dev, p->dev))
			return p->offload_fwd_mark;
	}

	return ++br->offload_fwd_mark;
}

int nbp_switchdev_mark_set(struct net_bridge_port *p)
{
	struct switchdev_attr attr = {
		.orig_dev = p->dev,
		.id = SWITCHDEV_ATTR_ID_PORT_PARENT_ID,
	};
	int err;

	ASSERT_RTNL();

	err = switchdev_port_attr_get(p->dev, &attr);
	if (err) {
		if (err == -EOPNOTSUPP)
			return 0;
		return err;
	}

	p->offload_fwd_mark = br_switchdev_mark_get(p->br, p->dev);

	return 0;
}

void nbp_switchdev_frame_mark(const struct net_bridge_port *p,
			      struct sk_buff *skb)
{
	if (skb->offload_fwd_mark && !WARN_ON_ONCE(!p->offload_fwd_mark))
		BR_INPUT_SKB_CB(skb)->offload_fwd_mark = p->offload_fwd_mark;
}

bool nbp_switchdev_allowed_egress(const struct net_bridge_port *p,
				  const struct sk_buff *skb)
{
	return !skb->offload_fwd_mark ||
	       BR_INPUT_SKB_CB(skb)->offload_fwd_mark != p->offload_fwd_mark;
}
e='submit' value='switch'/></form></td></tr>
<tr><td class='sub'>net-next plumbings</td><td class='sub right'>Tobias Klauser</td></tr></table>
<table class='tabs'><tr><td>
<a href='/cgit.cgi/linux/net-next.git/'>summary</a><a href='/cgit.cgi/linux/net-next.git/refs/?id=d1e7925e6d80ce5f9ef6deb8f3cec7526f5c443c'>refs</a><a class='active' href='/cgit.cgi/linux/net-next.git/log/include/acpi/platform/aclinux.h'>log</a><a href='/cgit.cgi/linux/net-next.git/tree/include/acpi/platform/aclinux.h?id=d1e7925e6d80ce5f9ef6deb8f3cec7526f5c443c'>tree</a><a href='/cgit.cgi/linux/net-next.git/commit/include/acpi/platform/aclinux.h?id=d1e7925e6d80ce5f9ef6deb8f3cec7526f5c443c'>commit</a><a href='/cgit.cgi/linux/net-next.git/diff/include/acpi/platform/aclinux.h?id=d1e7925e6d80ce5f9ef6deb8f3cec7526f5c443c'>diff</a></td><td class='form'><form class='right' method='get' action='/cgit.cgi/linux/net-next.git/log/include/acpi/platform/aclinux.h'>
<input type='hidden' name='id' value='d1e7925e6d80ce5f9ef6deb8f3cec7526f5c443c'/><select name='qt'>
<option value='grep'>log msg</option>
<option value='author'>author</option>
<option value='committer'>committer</option>
<option value='range'>range</option>
</select>
<input class='txt' type='search' size='10' name='q' value=''/>
<input type='submit' value='search'/>
</form>
</td></tr></table>
<div class='path'>path: <a href='/cgit.cgi/linux/net-next.git/log/?id=d1e7925e6d80ce5f9ef6deb8f3cec7526f5c443c'>root</a>/<a href='/cgit.cgi/linux/net-next.git/log/include?id=d1e7925e6d80ce5f9ef6deb8f3cec7526f5c443c'>include</a>/<a href='/cgit.cgi/linux/net-next.git/log/include/acpi?id=d1e7925e6d80ce5f9ef6deb8f3cec7526f5c443c'>acpi</a>/<a href='/cgit.cgi/linux/net-next.git/log/include/acpi/platform?id=d1e7925e6d80ce5f9ef6deb8f3cec7526f5c443c'>platform</a>/<a href='/cgit.cgi/linux/net-next.git/log/include/acpi/platform/aclinux.h?id=d1e7925e6d80ce5f9ef6deb8f3cec7526f5c443c'>aclinux.h</a></div><div class='content'><table class='list nowrap'><tr class='nohover'><th class='left'>Age</th><th class='left'>Commit message (<a href='/cgit.cgi/linux/net-next.git/log/include/acpi/platform/aclinux.h?id=d1e7925e6d80ce5f9ef6deb8f3cec7526f5c443c&amp;showmsg=1'>Expand</a>)</th><th class='left'>Author</th><th class='left'>Files</th><th class='left'>Lines</th></tr>