Commit 292d1398 authored by stephen hemminger's avatar stephen hemminger Committed by David S. Miller

bridge: add NTF_USE support

More changes to the recent code to support control of forwarding
database via netlink.
   * Support NTF_USE like neighbour table
   * Validate state bits from application
   * Only send notifications (and change bits) if new entry is
     different.
Signed-off-by: default avatarStephen Hemminger <shemminger@vyatta.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 23020ab3
...@@ -556,7 +556,7 @@ int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -556,7 +556,7 @@ int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
return skb->len; return skb->len;
} }
/* Create new static fdb entry */ /* Update (create or replace) forwarding database entry */
static int fdb_add_entry(struct net_bridge_port *source, const __u8 *addr, static int fdb_add_entry(struct net_bridge_port *source, const __u8 *addr,
__u16 state, __u16 flags) __u16 state, __u16 flags)
{ {
...@@ -575,16 +575,21 @@ static int fdb_add_entry(struct net_bridge_port *source, const __u8 *addr, ...@@ -575,16 +575,21 @@ static int fdb_add_entry(struct net_bridge_port *source, const __u8 *addr,
} else { } else {
if (flags & NLM_F_EXCL) if (flags & NLM_F_EXCL)
return -EEXIST; return -EEXIST;
}
if (fdb_to_nud(fdb) != state) {
if (state & NUD_PERMANENT)
fdb->is_local = fdb->is_static = 1;
else if (state & NUD_NOARP) {
fdb->is_local = 0;
fdb->is_static = 1;
} else
fdb->is_local = fdb->is_static = 0;
if (flags & NLM_F_REPLACE) fdb->updated = fdb->used = jiffies;
fdb->updated = fdb->used = jiffies; fdb_notify(fdb, RTM_NEWNEIGH);
fdb->is_local = fdb->is_static = 0;
} }
if (state & NUD_PERMANENT)
fdb->is_local = fdb->is_static = 1;
else if (state & NUD_NOARP)
fdb->is_static = 1;
return 0; return 0;
} }
...@@ -627,6 +632,11 @@ int br_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) ...@@ -627,6 +632,11 @@ int br_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
return -EINVAL; return -EINVAL;
} }
if (!(ndm->ndm_state & (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE))) {
pr_info("bridge: RTM_NEWNEIGH with invalid state %#x\n", ndm->ndm_state);
return -EINVAL;
}
p = br_port_get_rtnl(dev); p = br_port_get_rtnl(dev);
if (p == NULL) { if (p == NULL) {
pr_info("bridge: RTM_NEWNEIGH %s not a bridge port\n", pr_info("bridge: RTM_NEWNEIGH %s not a bridge port\n",
...@@ -634,9 +644,15 @@ int br_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) ...@@ -634,9 +644,15 @@ int br_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
return -EINVAL; return -EINVAL;
} }
spin_lock_bh(&p->br->hash_lock); if (ndm->ndm_flags & NTF_USE) {
err = fdb_add_entry(p, addr, ndm->ndm_state, nlh->nlmsg_flags); rcu_read_lock();
spin_unlock_bh(&p->br->hash_lock); br_fdb_update(p->br, p, addr);
rcu_read_unlock();
} else {
spin_lock_bh(&p->br->hash_lock);
err = fdb_add_entry(p, addr, ndm->ndm_state, nlh->nlmsg_flags);
spin_unlock_bh(&p->br->hash_lock);
}
return err; return err;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment