Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 435f2e7c authored by Nikolay Aleksandrov's avatar Nikolay Aleksandrov Committed by David S. Miller
Browse files

net: bridge: add support for sticky fdb entries



Add support for entries which are "sticky", i.e. will not change their port
if they show up from a different one. A new ndm flag is introduced for that
purpose - NTF_STICKY. We allow to set it only to non-local entries.

Signed-off-by: default avatarNikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 15665342
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ enum {
#define NTF_PROXY	0x08	/* == ATF_PUBL */
#define NTF_EXT_LEARNED	0x10
#define NTF_OFFLOADED   0x20
#define NTF_STICKY	0x40
#define NTF_ROUTER	0x80

/*
+16 −3
Original line number Diff line number Diff line
@@ -584,7 +584,7 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
			unsigned long now = jiffies;

			/* fastpath: update of existing entry */
			if (unlikely(source != fdb->dst)) {
			if (unlikely(source != fdb->dst && !fdb->is_sticky)) {
				fdb->dst = source;
				fdb_modified = true;
				/* Take over HW learned entry */
@@ -656,6 +656,8 @@ static int fdb_fill_info(struct sk_buff *skb, const struct net_bridge *br,
		ndm->ndm_flags |= NTF_OFFLOADED;
	if (fdb->added_by_external_learn)
		ndm->ndm_flags |= NTF_EXT_LEARNED;
	if (fdb->is_sticky)
		ndm->ndm_flags |= NTF_STICKY;

	if (nla_put(skb, NDA_LLADDR, ETH_ALEN, &fdb->key.addr))
		goto nla_put_failure;
@@ -772,8 +774,10 @@ int br_fdb_dump(struct sk_buff *skb,

/* Update (create or replace) forwarding database entry */
static int fdb_add_entry(struct net_bridge *br, struct net_bridge_port *source,
			 const __u8 *addr, __u16 state, __u16 flags, __u16 vid)
			 const u8 *addr, u16 state, u16 flags, u16 vid,
			 u8 ndm_flags)
{
	u8 is_sticky = !!(ndm_flags & NTF_STICKY);
	struct net_bridge_fdb_entry *fdb;
	bool modified = false;

@@ -789,6 +793,9 @@ static int fdb_add_entry(struct net_bridge *br, struct net_bridge_port *source,
		return -EINVAL;
	}

	if (is_sticky && (state & NUD_PERMANENT))
		return -EINVAL;

	fdb = br_fdb_find(br, addr, vid);
	if (fdb == NULL) {
		if (!(flags & NLM_F_CREATE))
@@ -832,6 +839,12 @@ static int fdb_add_entry(struct net_bridge *br, struct net_bridge_port *source,

		modified = true;
	}

	if (is_sticky != fdb->is_sticky) {
		fdb->is_sticky = is_sticky;
		modified = true;
	}

	fdb->added_by_user = 1;

	fdb->used = jiffies;
@@ -865,7 +878,7 @@ static int __br_fdb_add(struct ndmsg *ndm, struct net_bridge *br,
	} else {
		spin_lock_bh(&br->hash_lock);
		err = fdb_add_entry(br, p, addr, ndm->ndm_state,
				    nlh_flags, vid);
				    nlh_flags, vid, ndm->ndm_flags);
		spin_unlock_bh(&br->hash_lock);
	}

+1 −0
Original line number Diff line number Diff line
@@ -181,6 +181,7 @@ struct net_bridge_fdb_entry {
	struct hlist_node		fdb_node;
	unsigned char			is_local:1,
					is_static:1,
					is_sticky:1,
					added_by_user:1,
					added_by_external_learn:1,
					offloaded:1;