Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'batadv-next-for-davem-20180319' of git://git.open-mesh.org/linux-merge

Simon Wunderlich says:

====================
This feature/cleanup patchset includes the following patches:

- avoid redundant multicast TT entries, by Linus Luessing

- add netlink support for distributed arp table cache and multicast flags,
by Linus Luessing (2 patches)
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+604 -37
+82
include/uapi/linux/batman_adv.h
··· 92 92 }; 93 93 94 94 /** 95 + * enum batadv_mcast_flags_priv - Private, own multicast flags 96 + * 97 + * These are internal, multicast related flags. Currently they describe certain 98 + * multicast related attributes of the segment this originator bridges into the 99 + * mesh. 100 + * 101 + * Those attributes are used to determine the public multicast flags this 102 + * originator is going to announce via TT. 103 + * 104 + * For netlink, if BATADV_MCAST_FLAGS_BRIDGED is unset then all querier 105 + * related flags are undefined. 106 + */ 107 + enum batadv_mcast_flags_priv { 108 + /** 109 + * @BATADV_MCAST_FLAGS_BRIDGED: There is a bridge on top of the mesh 110 + * interface. 111 + */ 112 + BATADV_MCAST_FLAGS_BRIDGED = (1 << 0), 113 + 114 + /** 115 + * @BATADV_MCAST_FLAGS_QUERIER_IPV4_EXISTS: Whether an IGMP querier 116 + * exists in the mesh 117 + */ 118 + BATADV_MCAST_FLAGS_QUERIER_IPV4_EXISTS = (1 << 1), 119 + 120 + /** 121 + * @BATADV_MCAST_FLAGS_QUERIER_IPV6_EXISTS: Whether an MLD querier 122 + * exists in the mesh 123 + */ 124 + BATADV_MCAST_FLAGS_QUERIER_IPV6_EXISTS = (1 << 2), 125 + 126 + /** 127 + * @BATADV_MCAST_FLAGS_QUERIER_IPV4_SHADOWING: If an IGMP querier 128 + * exists, whether it is potentially shadowing multicast listeners 129 + * (i.e. querier is behind our own bridge segment) 130 + */ 131 + BATADV_MCAST_FLAGS_QUERIER_IPV4_SHADOWING = (1 << 3), 132 + 133 + /** 134 + * @BATADV_MCAST_FLAGS_QUERIER_IPV6_SHADOWING: If an MLD querier 135 + * exists, whether it is potentially shadowing multicast listeners 136 + * (i.e. querier is behind our own bridge segment) 137 + */ 138 + BATADV_MCAST_FLAGS_QUERIER_IPV6_SHADOWING = (1 << 4), 139 + }; 140 + 141 + /** 95 142 * enum batadv_nl_attrs - batman-adv netlink attributes 96 143 */ 97 144 enum batadv_nl_attrs { ··· 319 272 */ 320 273 BATADV_ATTR_BLA_CRC, 321 274 275 + /** 276 + * @BATADV_ATTR_DAT_CACHE_IP4ADDRESS: Client IPv4 address 277 + */ 278 + BATADV_ATTR_DAT_CACHE_IP4ADDRESS, 279 + 280 + /** 281 + * @BATADV_ATTR_DAT_CACHE_HWADDRESS: Client MAC address 282 + */ 283 + BATADV_ATTR_DAT_CACHE_HWADDRESS, 284 + 285 + /** 286 + * @BATADV_ATTR_DAT_CACHE_VID: VLAN ID 287 + */ 288 + BATADV_ATTR_DAT_CACHE_VID, 289 + 290 + /** 291 + * @BATADV_ATTR_MCAST_FLAGS: Per originator multicast flags 292 + */ 293 + BATADV_ATTR_MCAST_FLAGS, 294 + 295 + /** 296 + * @BATADV_ATTR_MCAST_FLAGS_PRIV: Private, own multicast flags 297 + */ 298 + BATADV_ATTR_MCAST_FLAGS_PRIV, 299 + 322 300 /* add attributes above here, update the policy in netlink.c */ 323 301 324 302 /** ··· 432 360 * backbones 433 361 */ 434 362 BATADV_CMD_GET_BLA_BACKBONE, 363 + 364 + /** 365 + * @BATADV_CMD_GET_DAT_CACHE: Query list of DAT cache entries 366 + */ 367 + BATADV_CMD_GET_DAT_CACHE, 368 + 369 + /** 370 + * @BATADV_CMD_GET_MCAST_FLAGS: Query list of multicast flags 371 + */ 372 + BATADV_CMD_GET_MCAST_FLAGS, 435 373 436 374 /* add new commands above here */ 437 375
+152
net/batman-adv/distributed-arp-table.c
··· 33 33 #include <linux/kernel.h> 34 34 #include <linux/kref.h> 35 35 #include <linux/list.h> 36 + #include <linux/netlink.h> 36 37 #include <linux/rculist.h> 37 38 #include <linux/rcupdate.h> 38 39 #include <linux/seq_file.h> ··· 44 43 #include <linux/string.h> 45 44 #include <linux/workqueue.h> 46 45 #include <net/arp.h> 46 + #include <net/genetlink.h> 47 + #include <net/netlink.h> 48 + #include <net/sock.h> 49 + #include <uapi/linux/batman_adv.h> 47 50 48 51 #include "bridge_loop_avoidance.h" 49 52 #include "hard-interface.h" 50 53 #include "hash.h" 51 54 #include "log.h" 55 + #include "netlink.h" 52 56 #include "originator.h" 53 57 #include "send.h" 58 + #include "soft-interface.h" 54 59 #include "translation-table.h" 55 60 #include "tvlv.h" 56 61 ··· 857 850 return 0; 858 851 } 859 852 #endif 853 + 854 + /** 855 + * batadv_dat_cache_dump_entry() - dump one entry of the DAT cache table to a 856 + * netlink socket 857 + * @msg: buffer for the message 858 + * @portid: netlink port 859 + * @seq: Sequence number of netlink message 860 + * @dat_entry: entry to dump 861 + * 862 + * Return: 0 or error code. 863 + */ 864 + static int 865 + batadv_dat_cache_dump_entry(struct sk_buff *msg, u32 portid, u32 seq, 866 + struct batadv_dat_entry *dat_entry) 867 + { 868 + int msecs; 869 + void *hdr; 870 + 871 + hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, 872 + NLM_F_MULTI, BATADV_CMD_GET_DAT_CACHE); 873 + if (!hdr) 874 + return -ENOBUFS; 875 + 876 + msecs = jiffies_to_msecs(jiffies - dat_entry->last_update); 877 + 878 + if (nla_put_in_addr(msg, BATADV_ATTR_DAT_CACHE_IP4ADDRESS, 879 + dat_entry->ip) || 880 + nla_put(msg, BATADV_ATTR_DAT_CACHE_HWADDRESS, ETH_ALEN, 881 + dat_entry->mac_addr) || 882 + nla_put_u16(msg, BATADV_ATTR_DAT_CACHE_VID, dat_entry->vid) || 883 + nla_put_u32(msg, BATADV_ATTR_LAST_SEEN_MSECS, msecs)) { 884 + genlmsg_cancel(msg, hdr); 885 + return -EMSGSIZE; 886 + } 887 + 888 + genlmsg_end(msg, hdr); 889 + return 0; 890 + } 891 + 892 + /** 893 + * batadv_dat_cache_dump_bucket() - dump one bucket of the DAT cache table to 894 + * a netlink socket 895 + * @msg: buffer for the message 896 + * @portid: netlink port 897 + * @seq: Sequence number of netlink message 898 + * @head: bucket to dump 899 + * @idx_skip: How many entries to skip 900 + * 901 + * Return: 0 or error code. 902 + */ 903 + static int 904 + batadv_dat_cache_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq, 905 + struct hlist_head *head, int *idx_skip) 906 + { 907 + struct batadv_dat_entry *dat_entry; 908 + int idx = 0; 909 + 910 + rcu_read_lock(); 911 + hlist_for_each_entry_rcu(dat_entry, head, hash_entry) { 912 + if (idx < *idx_skip) 913 + goto skip; 914 + 915 + if (batadv_dat_cache_dump_entry(msg, portid, seq, 916 + dat_entry)) { 917 + rcu_read_unlock(); 918 + *idx_skip = idx; 919 + 920 + return -EMSGSIZE; 921 + } 922 + 923 + skip: 924 + idx++; 925 + } 926 + rcu_read_unlock(); 927 + 928 + return 0; 929 + } 930 + 931 + /** 932 + * batadv_dat_cache_dump() - dump DAT cache table to a netlink socket 933 + * @msg: buffer for the message 934 + * @cb: callback structure containing arguments 935 + * 936 + * Return: message length. 937 + */ 938 + int batadv_dat_cache_dump(struct sk_buff *msg, struct netlink_callback *cb) 939 + { 940 + struct batadv_hard_iface *primary_if = NULL; 941 + int portid = NETLINK_CB(cb->skb).portid; 942 + struct net *net = sock_net(cb->skb->sk); 943 + struct net_device *soft_iface; 944 + struct batadv_hashtable *hash; 945 + struct batadv_priv *bat_priv; 946 + int bucket = cb->args[0]; 947 + struct hlist_head *head; 948 + int idx = cb->args[1]; 949 + int ifindex; 950 + int ret = 0; 951 + 952 + ifindex = batadv_netlink_get_ifindex(cb->nlh, 953 + BATADV_ATTR_MESH_IFINDEX); 954 + if (!ifindex) 955 + return -EINVAL; 956 + 957 + soft_iface = dev_get_by_index(net, ifindex); 958 + if (!soft_iface || !batadv_softif_is_valid(soft_iface)) { 959 + ret = -ENODEV; 960 + goto out; 961 + } 962 + 963 + bat_priv = netdev_priv(soft_iface); 964 + hash = bat_priv->dat.hash; 965 + 966 + primary_if = batadv_primary_if_get_selected(bat_priv); 967 + if (!primary_if || primary_if->if_status != BATADV_IF_ACTIVE) { 968 + ret = -ENOENT; 969 + goto out; 970 + } 971 + 972 + while (bucket < hash->size) { 973 + head = &hash->table[bucket]; 974 + 975 + if (batadv_dat_cache_dump_bucket(msg, portid, 976 + cb->nlh->nlmsg_seq, head, 977 + &idx)) 978 + break; 979 + 980 + bucket++; 981 + idx = 0; 982 + } 983 + 984 + cb->args[0] = bucket; 985 + cb->args[1] = idx; 986 + 987 + ret = msg->len; 988 + 989 + out: 990 + if (primary_if) 991 + batadv_hardif_put(primary_if); 992 + 993 + if (soft_iface) 994 + dev_put(soft_iface); 995 + 996 + return ret; 997 + } 860 998 861 999 /** 862 1000 * batadv_arp_get_type() - parse an ARP packet and gets the type
+8
net/batman-adv/distributed-arp-table.h
··· 28 28 29 29 #include "originator.h" 30 30 31 + struct netlink_callback; 31 32 struct seq_file; 32 33 struct sk_buff; 33 34 ··· 82 81 int batadv_dat_init(struct batadv_priv *bat_priv); 83 82 void batadv_dat_free(struct batadv_priv *bat_priv); 84 83 int batadv_dat_cache_seq_print_text(struct seq_file *seq, void *offset); 84 + int batadv_dat_cache_dump(struct sk_buff *msg, struct netlink_callback *cb); 85 85 86 86 /** 87 87 * batadv_dat_inc_counter() - increment the correct DAT packet counter ··· 169 167 170 168 static inline void batadv_dat_free(struct batadv_priv *bat_priv) 171 169 { 170 + } 171 + 172 + static inline int 173 + batadv_dat_cache_dump(struct sk_buff *msg, struct netlink_callback *cb) 174 + { 175 + return -EOPNOTSUPP; 172 176 } 173 177 174 178 static inline void batadv_dat_inc_counter(struct batadv_priv *bat_priv,
+289 -4
net/batman-adv/multicast.c
··· 40 40 #include <linux/list.h> 41 41 #include <linux/lockdep.h> 42 42 #include <linux/netdevice.h> 43 + #include <linux/netlink.h> 43 44 #include <linux/printk.h> 44 45 #include <linux/rculist.h> 45 46 #include <linux/rcupdate.h> ··· 53 52 #include <linux/types.h> 54 53 #include <linux/workqueue.h> 55 54 #include <net/addrconf.h> 55 + #include <net/genetlink.h> 56 56 #include <net/if_inet6.h> 57 57 #include <net/ip.h> 58 58 #include <net/ipv6.h> 59 + #include <net/netlink.h> 60 + #include <net/sock.h> 59 61 #include <uapi/linux/batadv_packet.h> 62 + #include <uapi/linux/batman_adv.h> 60 63 61 64 #include "hard-interface.h" 62 65 #include "hash.h" 63 66 #include "log.h" 67 + #include "netlink.h" 68 + #include "soft-interface.h" 64 69 #include "translation-table.h" 65 70 #include "tvlv.h" 66 71 ··· 109 102 } 110 103 111 104 /** 105 + * batadv_mcast_addr_is_ipv4() - check if multicast MAC is IPv4 106 + * @addr: the MAC address to check 107 + * 108 + * Return: True, if MAC address is one reserved for IPv4 multicast, false 109 + * otherwise. 110 + */ 111 + static bool batadv_mcast_addr_is_ipv4(const u8 *addr) 112 + { 113 + static const u8 prefix[] = {0x01, 0x00, 0x5E}; 114 + 115 + return memcmp(prefix, addr, sizeof(prefix)) == 0; 116 + } 117 + 118 + /** 119 + * batadv_mcast_addr_is_ipv6() - check if multicast MAC is IPv6 120 + * @addr: the MAC address to check 121 + * 122 + * Return: True, if MAC address is one reserved for IPv6 multicast, false 123 + * otherwise. 124 + */ 125 + static bool batadv_mcast_addr_is_ipv6(const u8 *addr) 126 + { 127 + static const u8 prefix[] = {0x33, 0x33}; 128 + 129 + return memcmp(prefix, addr, sizeof(prefix)) == 0; 130 + } 131 + 132 + /** 112 133 * batadv_mcast_mla_softif_get() - get softif multicast listeners 134 + * @bat_priv: the bat priv with all the soft interface information 113 135 * @dev: the device to collect multicast addresses from 114 136 * @mcast_list: a list to put found addresses into 115 137 * ··· 155 119 * Return: -ENOMEM on memory allocation error or the number of 156 120 * items added to the mcast_list otherwise. 157 121 */ 158 - static int batadv_mcast_mla_softif_get(struct net_device *dev, 122 + static int batadv_mcast_mla_softif_get(struct batadv_priv *bat_priv, 123 + struct net_device *dev, 159 124 struct hlist_head *mcast_list) 160 125 { 126 + bool all_ipv4 = bat_priv->mcast.flags & BATADV_MCAST_WANT_ALL_IPV4; 127 + bool all_ipv6 = bat_priv->mcast.flags & BATADV_MCAST_WANT_ALL_IPV6; 161 128 struct net_device *bridge = batadv_mcast_get_bridge(dev); 162 129 struct netdev_hw_addr *mc_list_entry; 163 130 struct batadv_hw_addr *new; ··· 168 129 169 130 netif_addr_lock_bh(bridge ? bridge : dev); 170 131 netdev_for_each_mc_addr(mc_list_entry, bridge ? bridge : dev) { 132 + if (all_ipv4 && batadv_mcast_addr_is_ipv4(mc_list_entry->addr)) 133 + continue; 134 + 135 + if (all_ipv6 && batadv_mcast_addr_is_ipv6(mc_list_entry->addr)) 136 + continue; 137 + 171 138 new = kmalloc(sizeof(*new), GFP_ATOMIC); 172 139 if (!new) { 173 140 ret = -ENOMEM; ··· 238 193 239 194 /** 240 195 * batadv_mcast_mla_bridge_get() - get bridged-in multicast listeners 196 + * @bat_priv: the bat priv with all the soft interface information 241 197 * @dev: a bridge slave whose bridge to collect multicast addresses from 242 198 * @mcast_list: a list to put found addresses into 243 199 * ··· 250 204 * Return: -ENOMEM on memory allocation error or the number of 251 205 * items added to the mcast_list otherwise. 252 206 */ 253 - static int batadv_mcast_mla_bridge_get(struct net_device *dev, 207 + static int batadv_mcast_mla_bridge_get(struct batadv_priv *bat_priv, 208 + struct net_device *dev, 254 209 struct hlist_head *mcast_list) 255 210 { 256 211 struct list_head bridge_mcast_list = LIST_HEAD_INIT(bridge_mcast_list); 212 + bool all_ipv4 = bat_priv->mcast.flags & BATADV_MCAST_WANT_ALL_IPV4; 213 + bool all_ipv6 = bat_priv->mcast.flags & BATADV_MCAST_WANT_ALL_IPV6; 257 214 struct br_ip_list *br_ip_entry, *tmp; 258 215 struct batadv_hw_addr *new; 259 216 u8 mcast_addr[ETH_ALEN]; ··· 270 221 goto out; 271 222 272 223 list_for_each_entry(br_ip_entry, &bridge_mcast_list, list) { 224 + if (all_ipv4 && br_ip_entry->addr.proto == htons(ETH_P_IP)) 225 + continue; 226 + 227 + if (all_ipv6 && br_ip_entry->addr.proto == htons(ETH_P_IPV6)) 228 + continue; 229 + 273 230 batadv_mcast_mla_br_addr_cpy(mcast_addr, &br_ip_entry->addr); 274 231 if (batadv_mcast_mla_is_duplicate(mcast_addr, mcast_list)) 275 232 continue; ··· 623 568 if (!batadv_mcast_mla_tvlv_update(bat_priv)) 624 569 goto update; 625 570 626 - ret = batadv_mcast_mla_softif_get(soft_iface, &mcast_list); 571 + ret = batadv_mcast_mla_softif_get(bat_priv, soft_iface, &mcast_list); 627 572 if (ret < 0) 628 573 goto out; 629 574 630 - ret = batadv_mcast_mla_bridge_get(soft_iface, &mcast_list); 575 + ret = batadv_mcast_mla_bridge_get(bat_priv, soft_iface, &mcast_list); 631 576 if (ret < 0) 632 577 goto out; 633 578 ··· 1339 1284 return 0; 1340 1285 } 1341 1286 #endif 1287 + 1288 + /** 1289 + * batadv_mcast_mesh_info_put() - put multicast info into a netlink message 1290 + * @msg: buffer for the message 1291 + * @bat_priv: the bat priv with all the soft interface information 1292 + * 1293 + * Return: 0 or error code. 1294 + */ 1295 + int batadv_mcast_mesh_info_put(struct sk_buff *msg, 1296 + struct batadv_priv *bat_priv) 1297 + { 1298 + u32 flags = bat_priv->mcast.flags; 1299 + u32 flags_priv = BATADV_NO_FLAGS; 1300 + 1301 + if (bat_priv->mcast.bridged) { 1302 + flags_priv |= BATADV_MCAST_FLAGS_BRIDGED; 1303 + 1304 + if (bat_priv->mcast.querier_ipv4.exists) 1305 + flags_priv |= BATADV_MCAST_FLAGS_QUERIER_IPV4_EXISTS; 1306 + if (bat_priv->mcast.querier_ipv6.exists) 1307 + flags_priv |= BATADV_MCAST_FLAGS_QUERIER_IPV6_EXISTS; 1308 + if (bat_priv->mcast.querier_ipv4.shadowing) 1309 + flags_priv |= BATADV_MCAST_FLAGS_QUERIER_IPV4_SHADOWING; 1310 + if (bat_priv->mcast.querier_ipv6.shadowing) 1311 + flags_priv |= BATADV_MCAST_FLAGS_QUERIER_IPV6_SHADOWING; 1312 + } 1313 + 1314 + if (nla_put_u32(msg, BATADV_ATTR_MCAST_FLAGS, flags) || 1315 + nla_put_u32(msg, BATADV_ATTR_MCAST_FLAGS_PRIV, flags_priv)) 1316 + return -EMSGSIZE; 1317 + 1318 + return 0; 1319 + } 1320 + 1321 + /** 1322 + * batadv_mcast_flags_dump_entry() - dump one entry of the multicast flags table 1323 + * to a netlink socket 1324 + * @msg: buffer for the message 1325 + * @portid: netlink port 1326 + * @seq: Sequence number of netlink message 1327 + * @orig_node: originator to dump the multicast flags of 1328 + * 1329 + * Return: 0 or error code. 1330 + */ 1331 + static int 1332 + batadv_mcast_flags_dump_entry(struct sk_buff *msg, u32 portid, u32 seq, 1333 + struct batadv_orig_node *orig_node) 1334 + { 1335 + void *hdr; 1336 + 1337 + hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, 1338 + NLM_F_MULTI, BATADV_CMD_GET_MCAST_FLAGS); 1339 + if (!hdr) 1340 + return -ENOBUFS; 1341 + 1342 + if (nla_put(msg, BATADV_ATTR_ORIG_ADDRESS, ETH_ALEN, 1343 + orig_node->orig)) { 1344 + genlmsg_cancel(msg, hdr); 1345 + return -EMSGSIZE; 1346 + } 1347 + 1348 + if (test_bit(BATADV_ORIG_CAPA_HAS_MCAST, 1349 + &orig_node->capabilities)) { 1350 + if (nla_put_u32(msg, BATADV_ATTR_MCAST_FLAGS, 1351 + orig_node->mcast_flags)) { 1352 + genlmsg_cancel(msg, hdr); 1353 + return -EMSGSIZE; 1354 + } 1355 + } 1356 + 1357 + genlmsg_end(msg, hdr); 1358 + return 0; 1359 + } 1360 + 1361 + /** 1362 + * batadv_mcast_flags_dump_bucket() - dump one bucket of the multicast flags 1363 + * table to a netlink socket 1364 + * @msg: buffer for the message 1365 + * @portid: netlink port 1366 + * @seq: Sequence number of netlink message 1367 + * @head: bucket to dump 1368 + * @idx_skip: How many entries to skip 1369 + * 1370 + * Return: 0 or error code. 1371 + */ 1372 + static int 1373 + batadv_mcast_flags_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq, 1374 + struct hlist_head *head, long *idx_skip) 1375 + { 1376 + struct batadv_orig_node *orig_node; 1377 + long idx = 0; 1378 + 1379 + rcu_read_lock(); 1380 + hlist_for_each_entry_rcu(orig_node, head, hash_entry) { 1381 + if (!test_bit(BATADV_ORIG_CAPA_HAS_MCAST, 1382 + &orig_node->capa_initialized)) 1383 + continue; 1384 + 1385 + if (idx < *idx_skip) 1386 + goto skip; 1387 + 1388 + if (batadv_mcast_flags_dump_entry(msg, portid, seq, 1389 + orig_node)) { 1390 + rcu_read_unlock(); 1391 + *idx_skip = idx; 1392 + 1393 + return -EMSGSIZE; 1394 + } 1395 + 1396 + skip: 1397 + idx++; 1398 + } 1399 + rcu_read_unlock(); 1400 + 1401 + return 0; 1402 + } 1403 + 1404 + /** 1405 + * __batadv_mcast_flags_dump() - dump multicast flags table to a netlink socket 1406 + * @msg: buffer for the message 1407 + * @portid: netlink port 1408 + * @seq: Sequence number of netlink message 1409 + * @bat_priv: the bat priv with all the soft interface information 1410 + * @bucket: current bucket to dump 1411 + * @idx: index in current bucket to the next entry to dump 1412 + * 1413 + * Return: 0 or error code. 1414 + */ 1415 + static int 1416 + __batadv_mcast_flags_dump(struct sk_buff *msg, u32 portid, u32 seq, 1417 + struct batadv_priv *bat_priv, long *bucket, long *idx) 1418 + { 1419 + struct batadv_hashtable *hash = bat_priv->orig_hash; 1420 + long bucket_tmp = *bucket; 1421 + struct hlist_head *head; 1422 + long idx_tmp = *idx; 1423 + 1424 + while (bucket_tmp < hash->size) { 1425 + head = &hash->table[bucket_tmp]; 1426 + 1427 + if (batadv_mcast_flags_dump_bucket(msg, portid, seq, head, 1428 + &idx_tmp)) 1429 + break; 1430 + 1431 + bucket_tmp++; 1432 + idx_tmp = 0; 1433 + } 1434 + 1435 + *bucket = bucket_tmp; 1436 + *idx = idx_tmp; 1437 + 1438 + return msg->len; 1439 + } 1440 + 1441 + /** 1442 + * batadv_mcast_netlink_get_primary() - get primary interface from netlink 1443 + * callback 1444 + * @cb: netlink callback structure 1445 + * @primary_if: the primary interface pointer to return the result in 1446 + * 1447 + * Return: 0 or error code. 1448 + */ 1449 + static int 1450 + batadv_mcast_netlink_get_primary(struct netlink_callback *cb, 1451 + struct batadv_hard_iface **primary_if) 1452 + { 1453 + struct batadv_hard_iface *hard_iface = NULL; 1454 + struct net *net = sock_net(cb->skb->sk); 1455 + struct net_device *soft_iface; 1456 + struct batadv_priv *bat_priv; 1457 + int ifindex; 1458 + int ret = 0; 1459 + 1460 + ifindex = batadv_netlink_get_ifindex(cb->nlh, BATADV_ATTR_MESH_IFINDEX); 1461 + if (!ifindex) 1462 + return -EINVAL; 1463 + 1464 + soft_iface = dev_get_by_index(net, ifindex); 1465 + if (!soft_iface || !batadv_softif_is_valid(soft_iface)) { 1466 + ret = -ENODEV; 1467 + goto out; 1468 + } 1469 + 1470 + bat_priv = netdev_priv(soft_iface); 1471 + 1472 + hard_iface = batadv_primary_if_get_selected(bat_priv); 1473 + if (!hard_iface || hard_iface->if_status != BATADV_IF_ACTIVE) { 1474 + ret = -ENOENT; 1475 + goto out; 1476 + } 1477 + 1478 + out: 1479 + if (soft_iface) 1480 + dev_put(soft_iface); 1481 + 1482 + if (!ret && primary_if) 1483 + *primary_if = hard_iface; 1484 + else 1485 + batadv_hardif_put(hard_iface); 1486 + 1487 + return ret; 1488 + } 1489 + 1490 + /** 1491 + * batadv_mcast_flags_dump() - dump multicast flags table to a netlink socket 1492 + * @msg: buffer for the message 1493 + * @cb: callback structure containing arguments 1494 + * 1495 + * Return: message length. 1496 + */ 1497 + int batadv_mcast_flags_dump(struct sk_buff *msg, struct netlink_callback *cb) 1498 + { 1499 + struct batadv_hard_iface *primary_if = NULL; 1500 + int portid = NETLINK_CB(cb->skb).portid; 1501 + struct batadv_priv *bat_priv; 1502 + long *bucket = &cb->args[0]; 1503 + long *idx = &cb->args[1]; 1504 + int ret; 1505 + 1506 + ret = batadv_mcast_netlink_get_primary(cb, &primary_if); 1507 + if (ret) 1508 + return ret; 1509 + 1510 + bat_priv = netdev_priv(primary_if->soft_iface); 1511 + ret = __batadv_mcast_flags_dump(msg, portid, cb->nlh->nlmsg_seq, 1512 + bat_priv, bucket, idx); 1513 + 1514 + batadv_hardif_put(primary_if); 1515 + return ret; 1516 + } 1342 1517 1343 1518 /** 1344 1519 * batadv_mcast_free() - free the multicast optimizations structures
+18
net/batman-adv/multicast.h
··· 21 21 22 22 #include "main.h" 23 23 24 + struct netlink_callback; 24 25 struct seq_file; 25 26 struct sk_buff; 26 27 ··· 55 54 56 55 int batadv_mcast_flags_seq_print_text(struct seq_file *seq, void *offset); 57 56 57 + int batadv_mcast_mesh_info_put(struct sk_buff *msg, 58 + struct batadv_priv *bat_priv); 59 + 60 + int batadv_mcast_flags_dump(struct sk_buff *msg, struct netlink_callback *cb); 61 + 58 62 void batadv_mcast_free(struct batadv_priv *bat_priv); 59 63 60 64 void batadv_mcast_purge_orig(struct batadv_orig_node *orig_node); ··· 76 70 static inline int batadv_mcast_init(struct batadv_priv *bat_priv) 77 71 { 78 72 return 0; 73 + } 74 + 75 + static inline int 76 + batadv_mcast_mesh_info_put(struct sk_buff *msg, struct batadv_priv *bat_priv) 77 + { 78 + return 0; 79 + } 80 + 81 + static inline int batadv_mcast_flags_dump(struct sk_buff *msg, 82 + struct netlink_callback *cb) 83 + { 84 + return -EOPNOTSUPP; 79 85 } 80 86 81 87 static inline void batadv_mcast_free(struct batadv_priv *bat_priv)
+55 -33
net/batman-adv/netlink.c
··· 45 45 46 46 #include "bat_algo.h" 47 47 #include "bridge_loop_avoidance.h" 48 + #include "distributed-arp-table.h" 48 49 #include "gateway_client.h" 49 50 #include "hard-interface.h" 51 + #include "multicast.h" 50 52 #include "originator.h" 51 53 #include "soft-interface.h" 52 54 #include "tp_meter.h" ··· 66 64 }; 67 65 68 66 static const struct nla_policy batadv_netlink_policy[NUM_BATADV_ATTR] = { 69 - [BATADV_ATTR_VERSION] = { .type = NLA_STRING }, 70 - [BATADV_ATTR_ALGO_NAME] = { .type = NLA_STRING }, 71 - [BATADV_ATTR_MESH_IFINDEX] = { .type = NLA_U32 }, 72 - [BATADV_ATTR_MESH_IFNAME] = { .type = NLA_STRING }, 73 - [BATADV_ATTR_MESH_ADDRESS] = { .len = ETH_ALEN }, 74 - [BATADV_ATTR_HARD_IFINDEX] = { .type = NLA_U32 }, 75 - [BATADV_ATTR_HARD_IFNAME] = { .type = NLA_STRING }, 76 - [BATADV_ATTR_HARD_ADDRESS] = { .len = ETH_ALEN }, 77 - [BATADV_ATTR_ORIG_ADDRESS] = { .len = ETH_ALEN }, 78 - [BATADV_ATTR_TPMETER_RESULT] = { .type = NLA_U8 }, 79 - [BATADV_ATTR_TPMETER_TEST_TIME] = { .type = NLA_U32 }, 80 - [BATADV_ATTR_TPMETER_BYTES] = { .type = NLA_U64 }, 81 - [BATADV_ATTR_TPMETER_COOKIE] = { .type = NLA_U32 }, 82 - [BATADV_ATTR_ACTIVE] = { .type = NLA_FLAG }, 83 - [BATADV_ATTR_TT_ADDRESS] = { .len = ETH_ALEN }, 84 - [BATADV_ATTR_TT_TTVN] = { .type = NLA_U8 }, 85 - [BATADV_ATTR_TT_LAST_TTVN] = { .type = NLA_U8 }, 86 - [BATADV_ATTR_TT_CRC32] = { .type = NLA_U32 }, 87 - [BATADV_ATTR_TT_VID] = { .type = NLA_U16 }, 88 - [BATADV_ATTR_TT_FLAGS] = { .type = NLA_U32 }, 89 - [BATADV_ATTR_FLAG_BEST] = { .type = NLA_FLAG }, 90 - [BATADV_ATTR_LAST_SEEN_MSECS] = { .type = NLA_U32 }, 91 - [BATADV_ATTR_NEIGH_ADDRESS] = { .len = ETH_ALEN }, 92 - [BATADV_ATTR_TQ] = { .type = NLA_U8 }, 93 - [BATADV_ATTR_THROUGHPUT] = { .type = NLA_U32 }, 94 - [BATADV_ATTR_BANDWIDTH_UP] = { .type = NLA_U32 }, 95 - [BATADV_ATTR_BANDWIDTH_DOWN] = { .type = NLA_U32 }, 96 - [BATADV_ATTR_ROUTER] = { .len = ETH_ALEN }, 97 - [BATADV_ATTR_BLA_OWN] = { .type = NLA_FLAG }, 98 - [BATADV_ATTR_BLA_ADDRESS] = { .len = ETH_ALEN }, 99 - [BATADV_ATTR_BLA_VID] = { .type = NLA_U16 }, 100 - [BATADV_ATTR_BLA_BACKBONE] = { .len = ETH_ALEN }, 101 - [BATADV_ATTR_BLA_CRC] = { .type = NLA_U16 }, 67 + [BATADV_ATTR_VERSION] = { .type = NLA_STRING }, 68 + [BATADV_ATTR_ALGO_NAME] = { .type = NLA_STRING }, 69 + [BATADV_ATTR_MESH_IFINDEX] = { .type = NLA_U32 }, 70 + [BATADV_ATTR_MESH_IFNAME] = { .type = NLA_STRING }, 71 + [BATADV_ATTR_MESH_ADDRESS] = { .len = ETH_ALEN }, 72 + [BATADV_ATTR_HARD_IFINDEX] = { .type = NLA_U32 }, 73 + [BATADV_ATTR_HARD_IFNAME] = { .type = NLA_STRING }, 74 + [BATADV_ATTR_HARD_ADDRESS] = { .len = ETH_ALEN }, 75 + [BATADV_ATTR_ORIG_ADDRESS] = { .len = ETH_ALEN }, 76 + [BATADV_ATTR_TPMETER_RESULT] = { .type = NLA_U8 }, 77 + [BATADV_ATTR_TPMETER_TEST_TIME] = { .type = NLA_U32 }, 78 + [BATADV_ATTR_TPMETER_BYTES] = { .type = NLA_U64 }, 79 + [BATADV_ATTR_TPMETER_COOKIE] = { .type = NLA_U32 }, 80 + [BATADV_ATTR_ACTIVE] = { .type = NLA_FLAG }, 81 + [BATADV_ATTR_TT_ADDRESS] = { .len = ETH_ALEN }, 82 + [BATADV_ATTR_TT_TTVN] = { .type = NLA_U8 }, 83 + [BATADV_ATTR_TT_LAST_TTVN] = { .type = NLA_U8 }, 84 + [BATADV_ATTR_TT_CRC32] = { .type = NLA_U32 }, 85 + [BATADV_ATTR_TT_VID] = { .type = NLA_U16 }, 86 + [BATADV_ATTR_TT_FLAGS] = { .type = NLA_U32 }, 87 + [BATADV_ATTR_FLAG_BEST] = { .type = NLA_FLAG }, 88 + [BATADV_ATTR_LAST_SEEN_MSECS] = { .type = NLA_U32 }, 89 + [BATADV_ATTR_NEIGH_ADDRESS] = { .len = ETH_ALEN }, 90 + [BATADV_ATTR_TQ] = { .type = NLA_U8 }, 91 + [BATADV_ATTR_THROUGHPUT] = { .type = NLA_U32 }, 92 + [BATADV_ATTR_BANDWIDTH_UP] = { .type = NLA_U32 }, 93 + [BATADV_ATTR_BANDWIDTH_DOWN] = { .type = NLA_U32 }, 94 + [BATADV_ATTR_ROUTER] = { .len = ETH_ALEN }, 95 + [BATADV_ATTR_BLA_OWN] = { .type = NLA_FLAG }, 96 + [BATADV_ATTR_BLA_ADDRESS] = { .len = ETH_ALEN }, 97 + [BATADV_ATTR_BLA_VID] = { .type = NLA_U16 }, 98 + [BATADV_ATTR_BLA_BACKBONE] = { .len = ETH_ALEN }, 99 + [BATADV_ATTR_BLA_CRC] = { .type = NLA_U16 }, 100 + [BATADV_ATTR_DAT_CACHE_IP4ADDRESS] = { .type = NLA_U32 }, 101 + [BATADV_ATTR_DAT_CACHE_HWADDRESS] = { .len = ETH_ALEN }, 102 + [BATADV_ATTR_DAT_CACHE_VID] = { .type = NLA_U16 }, 103 + [BATADV_ATTR_MCAST_FLAGS] = { .type = NLA_U32 }, 104 + [BATADV_ATTR_MCAST_FLAGS_PRIV] = { .type = NLA_U32 }, 102 105 }; 103 106 104 107 /** ··· 153 146 ntohs(bat_priv->bla.claim_dest.group))) 154 147 goto out; 155 148 #endif 149 + 150 + if (batadv_mcast_mesh_info_put(msg, bat_priv)) 151 + goto out; 156 152 157 153 primary_if = batadv_primary_if_get_selected(bat_priv); 158 154 if (primary_if && primary_if->if_status == BATADV_IF_ACTIVE) { ··· 613 603 .flags = GENL_ADMIN_PERM, 614 604 .policy = batadv_netlink_policy, 615 605 .dumpit = batadv_bla_backbone_dump, 606 + }, 607 + { 608 + .cmd = BATADV_CMD_GET_DAT_CACHE, 609 + .flags = GENL_ADMIN_PERM, 610 + .policy = batadv_netlink_policy, 611 + .dumpit = batadv_dat_cache_dump, 612 + }, 613 + { 614 + .cmd = BATADV_CMD_GET_MCAST_FLAGS, 615 + .flags = GENL_ADMIN_PERM, 616 + .policy = batadv_netlink_policy, 617 + .dumpit = batadv_mcast_flags_dump, 616 618 }, 617 619 618 620 };