Skip to content

Commit ea4152e

Browse files
batman-adv: add backbone table netlink support
Dump the list of bridge loop avoidance backbones via the netlink socket. Signed-off-by: Simon Wunderlich <[email protected]> Signed-off-by: Sven Eckelmann <[email protected]> Signed-off-by: Marek Lindner <[email protected]>
1 parent 8dad6f0 commit ea4152e

File tree

4 files changed

+180
-0
lines changed

4 files changed

+180
-0
lines changed

include/uapi/linux/batman_adv.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ enum batadv_nl_attrs {
157157
* @BATADV_CMD_GET_NEIGHBORS: Query list of neighbours
158158
* @BATADV_CMD_GET_GATEWAYS: Query list of gateways
159159
* @BATADV_CMD_GET_BLA_CLAIM: Query list of bridge loop avoidance claims
160+
* @BATADV_CMD_GET_BLA_BACKBONE: Query list of bridge loop avoidance backbones
160161
* @__BATADV_CMD_AFTER_LAST: internal use
161162
* @BATADV_CMD_MAX: highest used command number
162163
*/
@@ -173,6 +174,7 @@ enum batadv_nl_commands {
173174
BATADV_CMD_GET_NEIGHBORS,
174175
BATADV_CMD_GET_GATEWAYS,
175176
BATADV_CMD_GET_BLA_CLAIM,
177+
BATADV_CMD_GET_BLA_BACKBONE,
176178
/* add new commands above here */
177179
__BATADV_CMD_AFTER_LAST,
178180
BATADV_CMD_MAX = __BATADV_CMD_AFTER_LAST - 1

net/batman-adv/bridge_loop_avoidance.c

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2283,3 +2283,167 @@ int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset)
22832283
batadv_hardif_put(primary_if);
22842284
return 0;
22852285
}
2286+
2287+
/**
2288+
* batadv_bla_backbone_dump_entry - dump one entry of the backbone table
2289+
* to a netlink socket
2290+
* @msg: buffer for the message
2291+
* @portid: netlink port
2292+
* @seq: Sequence number of netlink message
2293+
* @primary_if: primary interface
2294+
* @backbone_gw: entry to dump
2295+
*
2296+
* Return: 0 or error code.
2297+
*/
2298+
static int
2299+
batadv_bla_backbone_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
2300+
struct batadv_hard_iface *primary_if,
2301+
struct batadv_bla_backbone_gw *backbone_gw)
2302+
{
2303+
u8 *primary_addr = primary_if->net_dev->dev_addr;
2304+
u16 backbone_crc;
2305+
bool is_own;
2306+
int msecs;
2307+
void *hdr;
2308+
int ret = -EINVAL;
2309+
2310+
hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family,
2311+
NLM_F_MULTI, BATADV_CMD_GET_BLA_BACKBONE);
2312+
if (!hdr) {
2313+
ret = -ENOBUFS;
2314+
goto out;
2315+
}
2316+
2317+
is_own = batadv_compare_eth(backbone_gw->orig, primary_addr);
2318+
2319+
spin_lock_bh(&backbone_gw->crc_lock);
2320+
backbone_crc = backbone_gw->crc;
2321+
spin_unlock_bh(&backbone_gw->crc_lock);
2322+
2323+
msecs = jiffies_to_msecs(jiffies - backbone_gw->lasttime);
2324+
2325+
if (is_own)
2326+
if (nla_put_flag(msg, BATADV_ATTR_BLA_OWN)) {
2327+
genlmsg_cancel(msg, hdr);
2328+
goto out;
2329+
}
2330+
2331+
if (nla_put(msg, BATADV_ATTR_BLA_BACKBONE, ETH_ALEN,
2332+
backbone_gw->orig) ||
2333+
nla_put_u16(msg, BATADV_ATTR_BLA_VID, backbone_gw->vid) ||
2334+
nla_put_u16(msg, BATADV_ATTR_BLA_CRC,
2335+
backbone_crc) ||
2336+
nla_put_u32(msg, BATADV_ATTR_LAST_SEEN_MSECS, msecs)) {
2337+
genlmsg_cancel(msg, hdr);
2338+
goto out;
2339+
}
2340+
2341+
genlmsg_end(msg, hdr);
2342+
ret = 0;
2343+
2344+
out:
2345+
return ret;
2346+
}
2347+
2348+
/**
2349+
* batadv_bla_backbone_dump_bucket - dump one bucket of the backbone table
2350+
* to a netlink socket
2351+
* @msg: buffer for the message
2352+
* @portid: netlink port
2353+
* @seq: Sequence number of netlink message
2354+
* @primary_if: primary interface
2355+
* @head: bucket to dump
2356+
* @idx_skip: How many entries to skip
2357+
*
2358+
* Return: always 0.
2359+
*/
2360+
static int
2361+
batadv_bla_backbone_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq,
2362+
struct batadv_hard_iface *primary_if,
2363+
struct hlist_head *head, int *idx_skip)
2364+
{
2365+
struct batadv_bla_backbone_gw *backbone_gw;
2366+
int idx = 0;
2367+
2368+
rcu_read_lock();
2369+
hlist_for_each_entry_rcu(backbone_gw, head, hash_entry) {
2370+
if (idx++ < *idx_skip)
2371+
continue;
2372+
if (batadv_bla_backbone_dump_entry(msg, portid, seq,
2373+
primary_if, backbone_gw)) {
2374+
*idx_skip = idx - 1;
2375+
goto unlock;
2376+
}
2377+
}
2378+
2379+
*idx_skip = idx;
2380+
unlock:
2381+
rcu_read_unlock();
2382+
return 0;
2383+
}
2384+
2385+
/**
2386+
* batadv_bla_backbone_dump - dump backbone table to a netlink socket
2387+
* @msg: buffer for the message
2388+
* @cb: callback structure containing arguments
2389+
*
2390+
* Return: message length.
2391+
*/
2392+
int batadv_bla_backbone_dump(struct sk_buff *msg, struct netlink_callback *cb)
2393+
{
2394+
struct batadv_hard_iface *primary_if = NULL;
2395+
int portid = NETLINK_CB(cb->skb).portid;
2396+
struct net *net = sock_net(cb->skb->sk);
2397+
struct net_device *soft_iface;
2398+
struct batadv_hashtable *hash;
2399+
struct batadv_priv *bat_priv;
2400+
int bucket = cb->args[0];
2401+
struct hlist_head *head;
2402+
int idx = cb->args[1];
2403+
int ifindex;
2404+
int ret = 0;
2405+
2406+
ifindex = batadv_netlink_get_ifindex(cb->nlh,
2407+
BATADV_ATTR_MESH_IFINDEX);
2408+
if (!ifindex)
2409+
return -EINVAL;
2410+
2411+
soft_iface = dev_get_by_index(net, ifindex);
2412+
if (!soft_iface || !batadv_softif_is_valid(soft_iface)) {
2413+
ret = -ENODEV;
2414+
goto out;
2415+
}
2416+
2417+
bat_priv = netdev_priv(soft_iface);
2418+
hash = bat_priv->bla.backbone_hash;
2419+
2420+
primary_if = batadv_primary_if_get_selected(bat_priv);
2421+
if (!primary_if || primary_if->if_status != BATADV_IF_ACTIVE) {
2422+
ret = -ENOENT;
2423+
goto out;
2424+
}
2425+
2426+
while (bucket < hash->size) {
2427+
head = &hash->table[bucket];
2428+
2429+
if (batadv_bla_backbone_dump_bucket(msg, portid,
2430+
cb->nlh->nlmsg_seq,
2431+
primary_if, head, &idx))
2432+
break;
2433+
bucket++;
2434+
}
2435+
2436+
cb->args[0] = bucket;
2437+
cb->args[1] = idx;
2438+
2439+
ret = msg->len;
2440+
2441+
out:
2442+
if (primary_if)
2443+
batadv_hardif_put(primary_if);
2444+
2445+
if (soft_iface)
2446+
dev_put(soft_iface);
2447+
2448+
return ret;
2449+
}

net/batman-adv/bridge_loop_avoidance.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset);
3939
int batadv_bla_claim_dump(struct sk_buff *msg, struct netlink_callback *cb);
4040
int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq,
4141
void *offset);
42+
int batadv_bla_backbone_dump(struct sk_buff *msg, struct netlink_callback *cb);
4243
bool batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, u8 *orig,
4344
unsigned short vid);
4445
bool batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
@@ -120,6 +121,12 @@ static inline int batadv_bla_claim_dump(struct sk_buff *msg,
120121
return -EOPNOTSUPP;
121122
}
122123

124+
static inline int batadv_bla_backbone_dump(struct sk_buff *msg,
125+
struct netlink_callback *cb)
126+
{
127+
return -EOPNOTSUPP;
128+
}
129+
123130
#endif /* ifdef CONFIG_BATMAN_ADV_BLA */
124131

125132
#endif /* ifndef _NET_BATMAN_ADV_BLA_H_ */

net/batman-adv/netlink.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,13 @@ static struct genl_ops batadv_netlink_ops[] = {
600600
.policy = batadv_netlink_policy,
601601
.dumpit = batadv_bla_claim_dump,
602602
},
603+
{
604+
.cmd = BATADV_CMD_GET_BLA_BACKBONE,
605+
.flags = GENL_ADMIN_PERM,
606+
.policy = batadv_netlink_policy,
607+
.dumpit = batadv_bla_backbone_dump,
608+
},
609+
603610
};
604611

605612
/**

0 commit comments

Comments
 (0)