Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 300770
b: refs/heads/master
c: 7716202
h: refs/heads/master
v: v3
  • Loading branch information
John Fastabend authored and David S. Miller committed Apr 15, 2012
1 parent 22810ca commit 2a8a06e
Show file tree
Hide file tree
Showing 9 changed files with 229 additions and 113 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 136cd14e1ea2bfde66d212d8e18e81552c94e4e3
refs/heads/master: 77162022ab26a1f99d3af30c03760a76f86e193d
3 changes: 3 additions & 0 deletions trunk/include/linux/neighbour.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ enum {
#define NTF_PROXY 0x08 /* == ATF_PUBL */
#define NTF_ROUTER 0x80

#define NTF_SELF 0x02
#define NTF_MASTER 0x04

/*
* Neighbor Cache Entry States.
*/
Expand Down
23 changes: 23 additions & 0 deletions trunk/include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
#include <net/netprio_cgroup.h>

#include <linux/netdev_features.h>
#include <linux/neighbour.h>

struct netpoll_info;
struct device;
Expand Down Expand Up @@ -905,6 +906,16 @@ struct netdev_fcoe_hbainfo {
* feature set might be less than what was returned by ndo_fix_features()).
* Must return >0 or -errno if it changed dev->features itself.
*
* int (*ndo_fdb_add)(struct ndmsg *ndm, struct net_device *dev,
* unsigned char *addr, u16 flags)
* Adds an FDB entry to dev for addr.
* int (*ndo_fdb_del)(struct ndmsg *ndm, struct net_device *dev,
* unsigned char *addr)
* Deletes the FDB entry from dev coresponding to addr.
* int (*ndo_fdb_dump)(struct sk_buff *skb, struct netlink_callback *cb,
* struct net_device *dev, int idx)
* Used to add FDB entries to dump requests. Implementers should add
* entries to skb and update idx with the number of entries.
*/
struct net_device_ops {
int (*ndo_init)(struct net_device *dev);
Expand Down Expand Up @@ -1002,6 +1013,18 @@ struct net_device_ops {
netdev_features_t features);
int (*ndo_neigh_construct)(struct neighbour *n);
void (*ndo_neigh_destroy)(struct neighbour *n);

int (*ndo_fdb_add)(struct ndmsg *ndm,
struct net_device *dev,
unsigned char *addr,
u16 flags);
int (*ndo_fdb_del)(struct ndmsg *ndm,
struct net_device *dev,
unsigned char *addr);
int (*ndo_fdb_dump)(struct sk_buff *skb,
struct netlink_callback *cb,
struct net_device *dev,
int idx);
};

/*
Expand Down
4 changes: 4 additions & 0 deletions trunk/include/linux/rtnetlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -801,6 +801,10 @@ static inline u32 rtm_get_table(struct rtattr **rta, u8 table)
return table;
}

extern int ndo_dflt_fdb_dump(struct sk_buff *skb,
struct netlink_callback *cb,
struct net_device *dev,
int idx);
#endif /* __KERNEL__ */


Expand Down
3 changes: 3 additions & 0 deletions trunk/net/bridge/br_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,9 @@ static const struct net_device_ops br_netdev_ops = {
.ndo_add_slave = br_add_slave,
.ndo_del_slave = br_del_slave,
.ndo_fix_features = br_fix_features,
.ndo_fdb_add = br_fdb_add,
.ndo_fdb_del = br_fdb_delete,
.ndo_fdb_dump = br_fdb_dump,
};

static void br_dev_free(struct net_device *dev)
Expand Down
128 changes: 31 additions & 97 deletions trunk/net/bridge/br_fdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -535,44 +535,38 @@ static void fdb_notify(struct net_bridge *br,
}

/* Dump information about entries, in response to GETNEIGH */
int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
int br_fdb_dump(struct sk_buff *skb,
struct netlink_callback *cb,
struct net_device *dev,
int idx)
{
struct net *net = sock_net(skb->sk);
struct net_device *dev;
int idx = 0;

rcu_read_lock();
for_each_netdev_rcu(net, dev) {
struct net_bridge *br = netdev_priv(dev);
int i;

if (!(dev->priv_flags & IFF_EBRIDGE))
continue;
struct net_bridge *br = netdev_priv(dev);
int i;

for (i = 0; i < BR_HASH_SIZE; i++) {
struct hlist_node *h;
struct net_bridge_fdb_entry *f;
if (!(dev->priv_flags & IFF_EBRIDGE))
goto out;

hlist_for_each_entry_rcu(f, h, &br->hash[i], hlist) {
if (idx < cb->args[0])
goto skip;
for (i = 0; i < BR_HASH_SIZE; i++) {
struct hlist_node *h;
struct net_bridge_fdb_entry *f;

if (fdb_fill_info(skb, br, f,
NETLINK_CB(cb->skb).pid,
cb->nlh->nlmsg_seq,
RTM_NEWNEIGH,
NLM_F_MULTI) < 0)
break;
hlist_for_each_entry_rcu(f, h, &br->hash[i], hlist) {
if (idx < cb->args[0])
goto skip;

if (fdb_fill_info(skb, br, f,
NETLINK_CB(cb->skb).pid,
cb->nlh->nlmsg_seq,
RTM_NEWNEIGH,
NLM_F_MULTI) < 0)
break;
skip:
++idx;
}
++idx;
}
}
rcu_read_unlock();

cb->args[0] = idx;

return skb->len;
out:
return idx;
}

/* Update (create or replace) forwarding database entry */
Expand Down Expand Up @@ -614,43 +608,11 @@ static int fdb_add_entry(struct net_bridge_port *source, const __u8 *addr,
}

/* Add new permanent fdb entry with RTM_NEWNEIGH */
int br_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
int br_fdb_add(struct ndmsg *ndm, struct net_device *dev,
unsigned char *addr, u16 nlh_flags)
{
struct net *net = sock_net(skb->sk);
struct ndmsg *ndm;
struct nlattr *tb[NDA_MAX+1];
struct net_device *dev;
struct net_bridge_port *p;
const __u8 *addr;
int err;

ASSERT_RTNL();
err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL);
if (err < 0)
return err;

ndm = nlmsg_data(nlh);
if (ndm->ndm_ifindex == 0) {
pr_info("bridge: RTM_NEWNEIGH with invalid ifindex\n");
return -EINVAL;
}

dev = __dev_get_by_index(net, ndm->ndm_ifindex);
if (dev == NULL) {
pr_info("bridge: RTM_NEWNEIGH with unknown ifindex\n");
return -ENODEV;
}

if (!tb[NDA_LLADDR] || nla_len(tb[NDA_LLADDR]) != ETH_ALEN) {
pr_info("bridge: RTM_NEWNEIGH with invalid address\n");
return -EINVAL;
}

addr = nla_data(tb[NDA_LLADDR]);
if (!is_valid_ether_addr(addr)) {
pr_info("bridge: RTM_NEWNEIGH with invalid ether address\n");
return -EINVAL;
}
int err = 0;

if (!(ndm->ndm_state & (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE))) {
pr_info("bridge: RTM_NEWNEIGH with invalid state %#x\n", ndm->ndm_state);
Expand All @@ -670,14 +632,14 @@ int br_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
rcu_read_unlock();
} else {
spin_lock_bh(&p->br->hash_lock);
err = fdb_add_entry(p, addr, ndm->ndm_state, nlh->nlmsg_flags);
err = fdb_add_entry(p, addr, ndm->ndm_state, nlh_flags);
spin_unlock_bh(&p->br->hash_lock);
}

return err;
}

static int fdb_delete_by_addr(struct net_bridge_port *p, const u8 *addr)
static int fdb_delete_by_addr(struct net_bridge_port *p, u8 *addr)
{
struct net_bridge *br = p->br;
struct hlist_head *head = &br->hash[br_mac_hash(addr)];
Expand All @@ -692,40 +654,12 @@ static int fdb_delete_by_addr(struct net_bridge_port *p, const u8 *addr)
}

/* Remove neighbor entry with RTM_DELNEIGH */
int br_fdb_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
int br_fdb_delete(struct ndmsg *ndm, struct net_device *dev,
unsigned char *addr)
{
struct net *net = sock_net(skb->sk);
struct ndmsg *ndm;
struct net_bridge_port *p;
struct nlattr *llattr;
const __u8 *addr;
struct net_device *dev;
int err;

ASSERT_RTNL();
if (nlmsg_len(nlh) < sizeof(*ndm))
return -EINVAL;

ndm = nlmsg_data(nlh);
if (ndm->ndm_ifindex == 0) {
pr_info("bridge: RTM_DELNEIGH with invalid ifindex\n");
return -EINVAL;
}

dev = __dev_get_by_index(net, ndm->ndm_ifindex);
if (dev == NULL) {
pr_info("bridge: RTM_DELNEIGH with unknown ifindex\n");
return -ENODEV;
}

llattr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_LLADDR);
if (llattr == NULL || nla_len(llattr) != ETH_ALEN) {
pr_info("bridge: RTM_DELNEIGH with invalid address\n");
return -EINVAL;
}

addr = nla_data(llattr);

p = br_port_get_rtnl(dev);
if (p == NULL) {
pr_info("bridge: RTM_DELNEIGH %s not a bridge port\n",
Expand Down
12 changes: 0 additions & 12 deletions trunk/net/bridge/br_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,18 +232,6 @@ int __init br_netlink_init(void)
br_rtm_setlink, NULL, NULL);
if (err)
goto err3;
err = __rtnl_register(PF_BRIDGE, RTM_NEWNEIGH,
br_fdb_add, NULL, NULL);
if (err)
goto err3;
err = __rtnl_register(PF_BRIDGE, RTM_DELNEIGH,
br_fdb_delete, NULL, NULL);
if (err)
goto err3;
err = __rtnl_register(PF_BRIDGE, RTM_GETNEIGH,
NULL, br_fdb_dump, NULL);
if (err)
goto err3;

return 0;

Expand Down
15 changes: 12 additions & 3 deletions trunk/net/bridge/br_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -360,9 +360,18 @@ extern int br_fdb_insert(struct net_bridge *br,
extern void br_fdb_update(struct net_bridge *br,
struct net_bridge_port *source,
const unsigned char *addr);
extern int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb);
extern int br_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);
extern int br_fdb_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);

extern int br_fdb_delete(struct ndmsg *ndm,
struct net_device *dev,
unsigned char *addr);
extern int br_fdb_add(struct ndmsg *nlh,
struct net_device *dev,
unsigned char *addr,
u16 nlh_flags);
extern int br_fdb_dump(struct sk_buff *skb,
struct netlink_callback *cb,
struct net_device *dev,
int idx);

/* br_forward.c */
extern void br_deliver(const struct net_bridge_port *to,
Expand Down
Loading

0 comments on commit 2a8a06e

Please sign in to comment.