diff options
author | roopa <roopa@cumulusnetworks.com> | 2012-11-14 11:33:51 -0800 |
---|---|---|
committer | Thomas Graf <tgraf@suug.ch> | 2012-11-15 19:42:47 +0100 |
commit | cb25338ac35b5174f03c19e00733d9366f6b9482 (patch) | |
tree | 1b633930f4bfa34cce0734f6ab1e007da4068735 /lib/route | |
parent | 64fcb47a36ec12d7e7f00605f6a8952ce985dd08 (diff) | |
download | libnl-cb25338ac35b5174f03c19e00733d9366f6b9482.tar.gz |
Add master support to rtnl_neigh for AF_BRIDGE objects
AF_BRIDGE neigh objects can be uniquely identified by
the family, lladdr and bridge ifindex. This patch adds
bridge ifindex to AF_BRIDGE neigh objects.
Things will be ok even without this patch with just family and
lladdr if we assume that we will have unique lladdr's
accross bridges in a system.
Kernel does not send the bridge ifindex in the AF_BRIDGE
fdb/neigh message. This patch tries to get that info by a
link cache lookup and adds it to the bridge neigh object
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
Reviewed-by: Nolan Leake <nolan@cumulusnetworks.com>
Reviewed-by: Shrijeet Mukherjee <shm@cumulusnetworks.com>
Reviewed-by: Wilson Kok <wkok@cumulusnetworks.com>
Signed-off-by: Thomas Graf <tgraf@suug.ch>
Diffstat (limited to 'lib/route')
-rw-r--r-- | lib/route/neigh.c | 24 |
1 files changed, 22 insertions, 2 deletions
diff --git a/lib/route/neigh.c b/lib/route/neigh.c index 8e1f422..4b5893a 100644 --- a/lib/route/neigh.c +++ b/lib/route/neigh.c @@ -167,6 +167,7 @@ #define NEIGH_ATTR_FAMILY 0x40 #define NEIGH_ATTR_TYPE 0x80 #define NEIGH_ATTR_PROBES 0x100 +#define NEIGH_ATTR_MASTER 0x200 static struct nl_cache_ops rtnl_neigh_ops; static struct nl_object_ops neigh_obj_ops; @@ -229,7 +230,9 @@ static void neigh_keygen(struct nl_object *obj, uint32_t *hashkey, return; } nkey->n_family = neigh->n_family; - if (neigh->n_family != AF_BRIDGE) + if (neigh->n_family == AF_BRIDGE) + nkey->n_ifindex = neigh->n_master; + else nkey->n_ifindex = neigh->n_ifindex; if (addr) memcpy(nkey->n_addr, @@ -262,6 +265,7 @@ static int neigh_compare(struct nl_object *_a, struct nl_object *_b, diff |= NEIGH_DIFF(TYPE, a->n_type != b->n_type); diff |= NEIGH_DIFF(LLADDR, nl_addr_cmp(a->n_lladdr, b->n_lladdr)); diff |= NEIGH_DIFF(DST, nl_addr_cmp(a->n_dst, b->n_dst)); + diff |= NEIGH_DIFF(MASTER, a->n_master != b->n_master); if (flags & LOOSE_COMPARISON) { diff |= NEIGH_DIFF(STATE, @@ -301,7 +305,7 @@ static uint32_t neigh_id_attrs_get(struct nl_object *obj) struct rtnl_neigh *neigh = (struct rtnl_neigh *)obj; if (neigh->n_family == AF_BRIDGE) - return (NEIGH_ATTR_LLADDR | NEIGH_ATTR_FAMILY); + return (NEIGH_ATTR_LLADDR | NEIGH_ATTR_FAMILY | NEIGH_ATTR_MASTER); else return (NEIGH_ATTR_IFINDEX | NEIGH_ATTR_DST | NEIGH_ATTR_FAMILY); } @@ -393,6 +397,22 @@ int rtnl_neigh_parse(struct nlmsghdr *n, struct rtnl_neigh **result) neigh->ce_mask |= NEIGH_ATTR_PROBES; } + /* + * Get the bridge index for AF_BRIDGE family entries + */ + if (neigh->n_family == AF_BRIDGE) { + struct nl_cache *lcache = nl_cache_mngt_require("route/link"); + if (lcache ) { + struct rtnl_link *link = rtnl_link_get(lcache, + neigh->n_ifindex); + if (link) { + neigh->n_master = link->l_master; + rtnl_link_put(link); + neigh->ce_mask |= NEIGH_ATTR_MASTER; + } + } + } + *result = neigh; return 0; |