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: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Nikolay Aleksandrov 2018-09-11 09:39:53 +03:00 коммит произвёл David S. Miller
Родитель 15665342d4
Коммит 435f2e7cc0
3 изменённых файлов: 18 добавлений и 3 удалений

Просмотреть файл

@ -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
/*

Просмотреть файл

@ -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 @@ skip:
/* 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);
}

Просмотреть файл

@ -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;