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

batman-adv: mcast: implement multicast packet reception and forwarding

Implement functionality to receive and forward a new TVLV capable
multicast packet type.

The new batman-adv multicast packet type allows to contain several
originator destination addresses within a TVLV. Routers on the way will
potentially split the batman-adv multicast packet and adjust its tracker
TVLV contents.

Routing decisions are still based on the selected BATMAN IV or BATMAN V
routing algorithm. So this new batman-adv multicast packet type retains
the same loop-free properties.

Also a new OGM multicast TVLV flag is introduced to signal to other
nodes that we are capable of handling a batman-adv multicast packet and
multicast tracker TVLV. And that all of our hard interfaces have an MTU
of at least 1280 bytes (IPv6 minimum MTU), as a simple solution for now
to avoid MTU issues while forwarding.

Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>

authored by

Linus Lüssing and committed by
Simon Wunderlich
07afe1ba e4679a1b

+518 -18
+39 -6
include/uapi/linux/batadv_packet.h
··· 116 116 * only need routable IPv4 multicast packets we signed up for explicitly 117 117 * @BATADV_MCAST_WANT_NO_RTR6: we have no IPv6 multicast router and therefore 118 118 * only need routable IPv6 multicast packets we signed up for explicitly 119 + * @BATADV_MCAST_HAVE_MC_PTYPE_CAPA: we can parse, receive and forward 120 + * batman-adv multicast packets with a multicast tracker TVLV. And all our 121 + * hard interfaces have an MTU of at least 1280 bytes. 119 122 */ 120 123 enum batadv_mcast_flags { 121 124 BATADV_MCAST_WANT_ALL_UNSNOOPABLES = 1UL << 0, ··· 126 123 BATADV_MCAST_WANT_ALL_IPV6 = 1UL << 2, 127 124 BATADV_MCAST_WANT_NO_RTR4 = 1UL << 3, 128 125 BATADV_MCAST_WANT_NO_RTR6 = 1UL << 4, 126 + BATADV_MCAST_HAVE_MC_PTYPE_CAPA = 1UL << 5, 129 127 }; 130 128 131 129 /* tt data subtypes */ ··· 178 174 * @BATADV_TVLV_TT: translation table tvlv 179 175 * @BATADV_TVLV_ROAM: roaming advertisement tvlv 180 176 * @BATADV_TVLV_MCAST: multicast capability tvlv 177 + * @BATADV_TVLV_MCAST_TRACKER: multicast tracker tvlv 181 178 */ 182 179 enum batadv_tvlv_type { 183 - BATADV_TVLV_GW = 0x01, 184 - BATADV_TVLV_DAT = 0x02, 185 - BATADV_TVLV_NC = 0x03, 186 - BATADV_TVLV_TT = 0x04, 187 - BATADV_TVLV_ROAM = 0x05, 188 - BATADV_TVLV_MCAST = 0x06, 180 + BATADV_TVLV_GW = 0x01, 181 + BATADV_TVLV_DAT = 0x02, 182 + BATADV_TVLV_NC = 0x03, 183 + BATADV_TVLV_TT = 0x04, 184 + BATADV_TVLV_ROAM = 0x05, 185 + BATADV_TVLV_MCAST = 0x06, 186 + BATADV_TVLV_MCAST_TRACKER = 0x07, 189 187 }; 190 188 191 189 #pragma pack(2) ··· 494 488 }; 495 489 496 490 /** 491 + * struct batadv_mcast_packet - multicast packet for network payload 492 + * @packet_type: batman-adv packet type, part of the general header 493 + * @version: batman-adv protocol version, part of the general header 494 + * @ttl: time to live for this packet, part of the general header 495 + * @reserved: reserved byte for alignment 496 + * @tvlv_len: length of the appended tvlv buffer (in bytes) 497 + */ 498 + struct batadv_mcast_packet { 499 + __u8 packet_type; 500 + __u8 version; 501 + __u8 ttl; 502 + __u8 reserved; 503 + __be16 tvlv_len; 504 + /* "4 bytes boundary + 2 bytes" long to make the payload after the 505 + * following ethernet header again 4 bytes boundary aligned 506 + */ 507 + }; 508 + 509 + /** 497 510 * struct batadv_coded_packet - network coded packet 498 511 * @packet_type: batman-adv packet type, part of the general header 499 512 * @version: batman-adv protocol version, part of the general header ··· 651 626 struct batadv_tvlv_mcast_data { 652 627 __u8 flags; 653 628 __u8 reserved[3]; 629 + }; 630 + 631 + /** 632 + * struct batadv_tvlv_mcast_tracker - payload of a multicast tracker tvlv 633 + * @num_dests: number of subsequent destination originator MAC addresses 634 + */ 635 + struct batadv_tvlv_mcast_tracker { 636 + __be16 num_dests; 654 637 }; 655 638 656 639 #pragma pack()
+1
net/batman-adv/Makefile
··· 20 20 batman-adv-$(CONFIG_BATMAN_ADV_DEBUG) += log.o 21 21 batman-adv-y += main.o 22 22 batman-adv-$(CONFIG_BATMAN_ADV_MCAST) += multicast.o 23 + batman-adv-$(CONFIG_BATMAN_ADV_MCAST) += multicast_forw.o 23 24 batman-adv-y += netlink.o 24 25 batman-adv-$(CONFIG_BATMAN_ADV_NC) += network-coding.o 25 26 batman-adv-y += originator.o
+1 -7
net/batman-adv/fragmentation.c
··· 25 25 26 26 #include "hard-interface.h" 27 27 #include "originator.h" 28 - #include "routing.h" 29 28 #include "send.h" 30 29 31 30 /** ··· 350 351 struct batadv_orig_node *orig_node_src) 351 352 { 352 353 struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); 353 - struct batadv_orig_node *orig_node_dst; 354 354 struct batadv_neigh_node *neigh_node = NULL; 355 355 struct batadv_frag_packet *packet; 356 356 u16 total_size; 357 357 bool ret = false; 358 358 359 359 packet = (struct batadv_frag_packet *)skb->data; 360 - orig_node_dst = batadv_orig_hash_find(bat_priv, packet->dest); 361 - if (!orig_node_dst) 362 - goto out; 363 360 364 - neigh_node = batadv_find_router(bat_priv, orig_node_dst, recv_if); 361 + neigh_node = batadv_orig_to_router(bat_priv, packet->dest, recv_if); 365 362 if (!neigh_node) 366 363 goto out; 367 364 ··· 376 381 } 377 382 378 383 out: 379 - batadv_orig_node_put(orig_node_dst); 380 384 batadv_neigh_node_put(neigh_node); 381 385 return ret; 382 386 }
+2
net/batman-adv/main.c
··· 532 532 533 533 /* broadcast packet */ 534 534 batadv_rx_handler[BATADV_BCAST] = batadv_recv_bcast_packet; 535 + /* multicast packet */ 536 + batadv_rx_handler[BATADV_MCAST] = batadv_recv_mcast_packet; 535 537 536 538 /* unicast packets ... */ 537 539 /* unicast with 4 addresses packet */
+43 -5
net/batman-adv/multicast.c
··· 236 236 } 237 237 238 238 /** 239 + * batadv_mcast_mla_forw_flags_get() - get multicast forwarding flags 240 + * @bat_priv: the bat priv with all the soft interface information 241 + * 242 + * Checks if all active hard interfaces have an MTU larger or equal to 1280 243 + * bytes (IPv6 minimum MTU). 244 + * 245 + * Return: BATADV_MCAST_HAVE_MC_PTYPE_CAPA if yes, BATADV_NO_FLAGS otherwise. 246 + */ 247 + static u8 batadv_mcast_mla_forw_flags_get(struct batadv_priv *bat_priv) 248 + { 249 + const struct batadv_hard_iface *hard_iface; 250 + 251 + rcu_read_lock(); 252 + list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) { 253 + if (hard_iface->if_status != BATADV_IF_ACTIVE) 254 + continue; 255 + 256 + if (hard_iface->soft_iface != bat_priv->soft_iface) 257 + continue; 258 + 259 + if (hard_iface->net_dev->mtu < IPV6_MIN_MTU) { 260 + rcu_read_unlock(); 261 + return BATADV_NO_FLAGS; 262 + } 263 + } 264 + rcu_read_unlock(); 265 + 266 + return BATADV_MCAST_HAVE_MC_PTYPE_CAPA; 267 + } 268 + 269 + /** 239 270 * batadv_mcast_mla_flags_get() - get the new multicast flags 240 271 * @bat_priv: the bat priv with all the soft interface information 241 272 * ··· 287 256 mla_flags.enabled = 1; 288 257 mla_flags.tvlv_flags |= batadv_mcast_mla_rtr_flags_get(bat_priv, 289 258 bridge); 259 + mla_flags.tvlv_flags |= batadv_mcast_mla_forw_flags_get(bat_priv); 290 260 291 261 if (!bridge) 292 262 return mla_flags; ··· 838 806 { 839 807 bool old_enabled = bat_priv->mcast.mla_flags.enabled; 840 808 u8 old_flags = bat_priv->mcast.mla_flags.tvlv_flags; 841 - char str_old_flags[] = "[.... . ]"; 809 + char str_old_flags[] = "[.... . .]"; 842 810 843 - sprintf(str_old_flags, "[%c%c%c%s%s]", 811 + sprintf(str_old_flags, "[%c%c%c%s%s%c]", 844 812 (old_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES) ? 'U' : '.', 845 813 (old_flags & BATADV_MCAST_WANT_ALL_IPV4) ? '4' : '.', 846 814 (old_flags & BATADV_MCAST_WANT_ALL_IPV6) ? '6' : '.', 847 815 !(old_flags & BATADV_MCAST_WANT_NO_RTR4) ? "R4" : ". ", 848 - !(old_flags & BATADV_MCAST_WANT_NO_RTR6) ? "R6" : ". "); 816 + !(old_flags & BATADV_MCAST_WANT_NO_RTR6) ? "R6" : ". ", 817 + !(old_flags & BATADV_MCAST_HAVE_MC_PTYPE_CAPA) ? 'P' : '.'); 849 818 850 819 batadv_dbg(BATADV_DBG_MCAST, bat_priv, 851 - "Changing multicast flags from '%s' to '[%c%c%c%s%s]'\n", 820 + "Changing multicast flags from '%s' to '[%c%c%c%s%s%c]'\n", 852 821 old_enabled ? str_old_flags : "<undefined>", 853 822 (flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES) ? 'U' : '.', 854 823 (flags & BATADV_MCAST_WANT_ALL_IPV4) ? '4' : '.', 855 824 (flags & BATADV_MCAST_WANT_ALL_IPV6) ? '6' : '.', 856 825 !(flags & BATADV_MCAST_WANT_NO_RTR4) ? "R4" : ". ", 857 - !(flags & BATADV_MCAST_WANT_NO_RTR6) ? "R6" : ". "); 826 + !(flags & BATADV_MCAST_WANT_NO_RTR6) ? "R6" : ". ", 827 + !(flags & BATADV_MCAST_HAVE_MC_PTYPE_CAPA) ? 'P' : '.'); 858 828 } 859 829 860 830 /** ··· 1853 1819 { 1854 1820 batadv_tvlv_handler_register(bat_priv, batadv_mcast_tvlv_ogm_handler, 1855 1821 NULL, NULL, BATADV_TVLV_MCAST, 2, 1822 + BATADV_TVLV_HANDLER_OGM_CIFNOTFND); 1823 + batadv_tvlv_handler_register(bat_priv, NULL, NULL, 1824 + batadv_mcast_forw_tracker_tvlv_handler, 1825 + BATADV_TVLV_MCAST_TRACKER, 1, 1856 1826 BATADV_TVLV_HANDLER_OGM_CIFNOTFND); 1857 1827 1858 1828 INIT_DELAYED_WORK(&bat_priv->mcast.work, batadv_mcast_mla_update);
+5
net/batman-adv/multicast.h
··· 52 52 53 53 void batadv_mcast_purge_orig(struct batadv_orig_node *orig_node); 54 54 55 + /* multicast_forw.c */ 56 + 57 + int batadv_mcast_forw_tracker_tvlv_handler(struct batadv_priv *bat_priv, 58 + struct sk_buff *skb); 59 + 55 60 #else 56 61 57 62 static inline enum batadv_forw_mode
+239
net/batman-adv/multicast_forw.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (C) B.A.T.M.A.N. contributors: 3 + * 4 + * Linus Lüssing 5 + */ 6 + 7 + #include "multicast.h" 8 + #include "main.h" 9 + 10 + #include <linux/byteorder/generic.h> 11 + #include <linux/errno.h> 12 + #include <linux/etherdevice.h> 13 + #include <linux/gfp.h> 14 + #include <linux/if_ether.h> 15 + #include <linux/netdevice.h> 16 + #include <linux/skbuff.h> 17 + #include <linux/stddef.h> 18 + #include <linux/types.h> 19 + #include <uapi/linux/batadv_packet.h> 20 + 21 + #include "originator.h" 22 + #include "send.h" 23 + 24 + #define batadv_mcast_forw_tracker_for_each_dest(dest, num_dests) \ 25 + for (; num_dests; num_dests--, (dest) += ETH_ALEN) 26 + 27 + #define batadv_mcast_forw_tracker_for_each_dest2(dest1, dest2, num_dests) \ 28 + for (; num_dests; num_dests--, (dest1) += ETH_ALEN, (dest2) += ETH_ALEN) 29 + 30 + /** 31 + * batadv_mcast_forw_scrub_dests() - scrub destinations in a tracker TVLV 32 + * @bat_priv: the bat priv with all the soft interface information 33 + * @comp_neigh: next hop neighbor to scrub+collect destinations for 34 + * @dest: start MAC entry in original skb's tracker TVLV 35 + * @next_dest: start MAC entry in to be sent skb's tracker TVLV 36 + * @num_dests: number of remaining destination MAC entries to iterate over 37 + * 38 + * This sorts destination entries into either the original batman-adv 39 + * multicast packet or the skb (copy) that is going to be sent to comp_neigh 40 + * next. 41 + * 42 + * In preparation for the next, to be (unicast) transmitted batman-adv multicast 43 + * packet skb to be sent to the given neighbor node, tries to collect all 44 + * originator MAC addresses that have the given neighbor node as their next hop 45 + * in the to be transmitted skb (copy), which next_dest points into. That is we 46 + * zero all destination entries in next_dest which do not have comp_neigh as 47 + * their next hop. And zero all destination entries in the original skb that 48 + * would have comp_neigh as their next hop (to avoid redundant transmissions and 49 + * duplicated payload later). 50 + */ 51 + static void 52 + batadv_mcast_forw_scrub_dests(struct batadv_priv *bat_priv, 53 + struct batadv_neigh_node *comp_neigh, u8 *dest, 54 + u8 *next_dest, u16 num_dests) 55 + { 56 + struct batadv_neigh_node *next_neigh; 57 + 58 + /* skip first entry, this is what we are comparing with */ 59 + eth_zero_addr(dest); 60 + dest += ETH_ALEN; 61 + next_dest += ETH_ALEN; 62 + num_dests--; 63 + 64 + batadv_mcast_forw_tracker_for_each_dest2(dest, next_dest, num_dests) { 65 + if (is_zero_ether_addr(next_dest)) 66 + continue; 67 + 68 + /* sanity check, we expect unicast destinations */ 69 + if (is_multicast_ether_addr(next_dest)) { 70 + eth_zero_addr(dest); 71 + eth_zero_addr(next_dest); 72 + continue; 73 + } 74 + 75 + next_neigh = batadv_orig_to_router(bat_priv, next_dest, NULL); 76 + if (!next_neigh) { 77 + eth_zero_addr(next_dest); 78 + continue; 79 + } 80 + 81 + if (!batadv_compare_eth(next_neigh->addr, comp_neigh->addr)) { 82 + eth_zero_addr(next_dest); 83 + batadv_neigh_node_put(next_neigh); 84 + continue; 85 + } 86 + 87 + /* found an entry for our next packet to transmit, so remove it 88 + * from the original packet 89 + */ 90 + eth_zero_addr(dest); 91 + batadv_neigh_node_put(next_neigh); 92 + } 93 + } 94 + 95 + /** 96 + * batadv_mcast_forw_packet() - forward a batman-adv multicast packet 97 + * @bat_priv: the bat priv with all the soft interface information 98 + * @skb: the received or locally generated batman-adv multicast packet 99 + * @local_xmit: indicates that the packet was locally generated and not received 100 + * 101 + * Parses the tracker TVLV of a batman-adv multicast packet and forwards the 102 + * packet as indicated in this TVLV. 103 + * 104 + * Caller needs to set the skb network header to the start of the multicast 105 + * tracker TVLV (excluding the generic TVLV header) and the skb transport header 106 + * to the next byte after this multicast tracker TVLV. 107 + * 108 + * Caller needs to free the skb. 109 + * 110 + * Return: NET_RX_SUCCESS or NET_RX_DROP on success or a negative error 111 + * code on failure. NET_RX_SUCCESS if the received packet is supposed to be 112 + * decapsulated and forwarded to the own soft interface, NET_RX_DROP otherwise. 113 + */ 114 + static int batadv_mcast_forw_packet(struct batadv_priv *bat_priv, 115 + struct sk_buff *skb, bool local_xmit) 116 + { 117 + struct batadv_tvlv_mcast_tracker *mcast_tracker; 118 + struct batadv_neigh_node *neigh_node; 119 + unsigned long offset, num_dests_off; 120 + struct sk_buff *nexthop_skb; 121 + unsigned char *skb_net_hdr; 122 + bool local_recv = false; 123 + unsigned int tvlv_len; 124 + bool xmitted = false; 125 + u8 *dest, *next_dest; 126 + u16 num_dests; 127 + int ret; 128 + 129 + /* (at least) TVLV part needs to be linearized */ 130 + SKB_LINEAR_ASSERT(skb); 131 + 132 + /* check if num_dests is within skb length */ 133 + num_dests_off = offsetof(struct batadv_tvlv_mcast_tracker, num_dests); 134 + if (num_dests_off > skb_network_header_len(skb)) 135 + return -EINVAL; 136 + 137 + skb_net_hdr = skb_network_header(skb); 138 + mcast_tracker = (struct batadv_tvlv_mcast_tracker *)skb_net_hdr; 139 + num_dests = ntohs(mcast_tracker->num_dests); 140 + 141 + dest = (u8 *)mcast_tracker + sizeof(*mcast_tracker); 142 + 143 + /* check if full tracker tvlv is within skb length */ 144 + tvlv_len = sizeof(*mcast_tracker) + ETH_ALEN * num_dests; 145 + if (tvlv_len > skb_network_header_len(skb)) 146 + return -EINVAL; 147 + 148 + /* invalidate checksum: */ 149 + skb->ip_summed = CHECKSUM_NONE; 150 + 151 + batadv_mcast_forw_tracker_for_each_dest(dest, num_dests) { 152 + if (is_zero_ether_addr(dest)) 153 + continue; 154 + 155 + /* only unicast originator addresses supported */ 156 + if (is_multicast_ether_addr(dest)) { 157 + eth_zero_addr(dest); 158 + continue; 159 + } 160 + 161 + if (batadv_is_my_mac(bat_priv, dest)) { 162 + eth_zero_addr(dest); 163 + local_recv = true; 164 + continue; 165 + } 166 + 167 + neigh_node = batadv_orig_to_router(bat_priv, dest, NULL); 168 + if (!neigh_node) { 169 + eth_zero_addr(dest); 170 + continue; 171 + } 172 + 173 + nexthop_skb = skb_copy(skb, GFP_ATOMIC); 174 + if (!nexthop_skb) { 175 + batadv_neigh_node_put(neigh_node); 176 + return -ENOMEM; 177 + } 178 + 179 + offset = dest - skb->data; 180 + next_dest = nexthop_skb->data + offset; 181 + 182 + batadv_mcast_forw_scrub_dests(bat_priv, neigh_node, dest, 183 + next_dest, num_dests); 184 + 185 + batadv_inc_counter(bat_priv, BATADV_CNT_MCAST_TX); 186 + batadv_add_counter(bat_priv, BATADV_CNT_MCAST_TX_BYTES, 187 + nexthop_skb->len + ETH_HLEN); 188 + xmitted = true; 189 + ret = batadv_send_unicast_skb(nexthop_skb, neigh_node); 190 + 191 + batadv_neigh_node_put(neigh_node); 192 + 193 + if (ret < 0) 194 + return ret; 195 + } 196 + 197 + if (xmitted) { 198 + if (local_xmit) { 199 + batadv_inc_counter(bat_priv, BATADV_CNT_MCAST_TX_LOCAL); 200 + batadv_add_counter(bat_priv, 201 + BATADV_CNT_MCAST_TX_LOCAL_BYTES, 202 + skb->len - 203 + skb_transport_offset(skb)); 204 + } else { 205 + batadv_inc_counter(bat_priv, BATADV_CNT_MCAST_FWD); 206 + batadv_add_counter(bat_priv, BATADV_CNT_MCAST_FWD_BYTES, 207 + skb->len + ETH_HLEN); 208 + } 209 + } 210 + 211 + if (local_recv) 212 + return NET_RX_SUCCESS; 213 + else 214 + return NET_RX_DROP; 215 + } 216 + 217 + /** 218 + * batadv_mcast_forw_tracker_tvlv_handler() - handle an mcast tracker tvlv 219 + * @bat_priv: the bat priv with all the soft interface information 220 + * @skb: the received batman-adv multicast packet 221 + * 222 + * Parses the tracker TVLV of an incoming batman-adv multicast packet and 223 + * forwards the packet as indicated in this TVLV. 224 + * 225 + * Caller needs to set the skb network header to the start of the multicast 226 + * tracker TVLV (excluding the generic TVLV header) and the skb transport header 227 + * to the next byte after this multicast tracker TVLV. 228 + * 229 + * Caller needs to free the skb. 230 + * 231 + * Return: NET_RX_SUCCESS or NET_RX_DROP on success or a negative error 232 + * code on failure. NET_RX_SUCCESS if the received packet is supposed to be 233 + * decapsulated and forwarded to the own soft interface, NET_RX_DROP otherwise. 234 + */ 235 + int batadv_mcast_forw_tracker_tvlv_handler(struct batadv_priv *bat_priv, 236 + struct sk_buff *skb) 237 + { 238 + return batadv_mcast_forw_packet(bat_priv, skb, false); 239 + }
+28
net/batman-adv/originator.c
··· 312 312 } 313 313 314 314 /** 315 + * batadv_orig_to_router() - get next hop neighbor to an orig address 316 + * @bat_priv: the bat priv with all the soft interface information 317 + * @orig_addr: the originator MAC address to search the best next hop router for 318 + * @if_outgoing: the interface where the payload packet has been received or 319 + * the OGM should be sent to 320 + * 321 + * Return: A neighbor node which is the best router towards the given originator 322 + * address. 323 + */ 324 + struct batadv_neigh_node * 325 + batadv_orig_to_router(struct batadv_priv *bat_priv, u8 *orig_addr, 326 + struct batadv_hard_iface *if_outgoing) 327 + { 328 + struct batadv_neigh_node *neigh_node; 329 + struct batadv_orig_node *orig_node; 330 + 331 + orig_node = batadv_orig_hash_find(bat_priv, orig_addr); 332 + if (!orig_node) 333 + return NULL; 334 + 335 + neigh_node = batadv_find_router(bat_priv, orig_node, if_outgoing); 336 + batadv_orig_node_put(orig_node); 337 + 338 + return neigh_node; 339 + } 340 + 341 + /** 315 342 * batadv_orig_ifinfo_get() - find the ifinfo from an orig_node 316 343 * @orig_node: the orig node to be queried 317 344 * @if_outgoing: the interface for which the ifinfo should be acquired ··· 969 942 #ifdef CONFIG_BATMAN_ADV_MCAST 970 943 orig_node->mcast_flags = BATADV_MCAST_WANT_NO_RTR4; 971 944 orig_node->mcast_flags |= BATADV_MCAST_WANT_NO_RTR6; 945 + orig_node->mcast_flags |= BATADV_MCAST_HAVE_MC_PTYPE_CAPA; 972 946 INIT_HLIST_NODE(&orig_node->mcast_want_all_unsnoopables_node); 973 947 INIT_HLIST_NODE(&orig_node->mcast_want_all_ipv4_node); 974 948 INIT_HLIST_NODE(&orig_node->mcast_want_all_ipv6_node);
+3
net/batman-adv/originator.h
··· 36 36 struct batadv_neigh_node * 37 37 batadv_orig_router_get(struct batadv_orig_node *orig_node, 38 38 const struct batadv_hard_iface *if_outgoing); 39 + struct batadv_neigh_node * 40 + batadv_orig_to_router(struct batadv_priv *bat_priv, u8 *orig_addr, 41 + struct batadv_hard_iface *if_outgoing); 39 42 struct batadv_neigh_ifinfo * 40 43 batadv_neigh_ifinfo_new(struct batadv_neigh_node *neigh, 41 44 struct batadv_hard_iface *if_outgoing);
+70
net/batman-adv/routing.c
··· 1270 1270 batadv_orig_node_put(orig_node); 1271 1271 return ret; 1272 1272 } 1273 + 1274 + #ifdef CONFIG_BATMAN_ADV_MCAST 1275 + /** 1276 + * batadv_recv_mcast_packet() - process received batman-adv multicast packet 1277 + * @skb: the received batman-adv multicast packet 1278 + * @recv_if: interface that the skb is received on 1279 + * 1280 + * Parses the given, received batman-adv multicast packet. Depending on the 1281 + * contents of its TVLV forwards it and/or decapsulates it to hand it to the 1282 + * soft interface. 1283 + * 1284 + * Return: NET_RX_DROP if the skb is not consumed, NET_RX_SUCCESS otherwise. 1285 + */ 1286 + int batadv_recv_mcast_packet(struct sk_buff *skb, 1287 + struct batadv_hard_iface *recv_if) 1288 + { 1289 + struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); 1290 + struct batadv_mcast_packet *mcast_packet; 1291 + int hdr_size = sizeof(*mcast_packet); 1292 + unsigned char *tvlv_buff; 1293 + int ret = NET_RX_DROP; 1294 + u16 tvlv_buff_len; 1295 + 1296 + if (batadv_check_unicast_packet(bat_priv, skb, hdr_size) < 0) 1297 + goto free_skb; 1298 + 1299 + /* create a copy of the skb, if needed, to modify it. */ 1300 + if (skb_cow(skb, ETH_HLEN) < 0) 1301 + goto free_skb; 1302 + 1303 + /* packet needs to be linearized to access the tvlv content */ 1304 + if (skb_linearize(skb) < 0) 1305 + goto free_skb; 1306 + 1307 + mcast_packet = (struct batadv_mcast_packet *)skb->data; 1308 + if (mcast_packet->ttl-- < 2) 1309 + goto free_skb; 1310 + 1311 + tvlv_buff = (unsigned char *)(skb->data + hdr_size); 1312 + tvlv_buff_len = ntohs(mcast_packet->tvlv_len); 1313 + 1314 + if (tvlv_buff_len > skb->len - hdr_size) 1315 + goto free_skb; 1316 + 1317 + ret = batadv_tvlv_containers_process(bat_priv, BATADV_MCAST, NULL, skb, 1318 + tvlv_buff, tvlv_buff_len); 1319 + if (ret >= 0) { 1320 + batadv_inc_counter(bat_priv, BATADV_CNT_MCAST_RX); 1321 + batadv_add_counter(bat_priv, BATADV_CNT_MCAST_RX_BYTES, 1322 + skb->len + ETH_HLEN); 1323 + } 1324 + 1325 + hdr_size += tvlv_buff_len; 1326 + 1327 + if (ret == NET_RX_SUCCESS && (skb->len - hdr_size >= ETH_HLEN)) { 1328 + batadv_inc_counter(bat_priv, BATADV_CNT_MCAST_RX_LOCAL); 1329 + batadv_add_counter(bat_priv, BATADV_CNT_MCAST_RX_LOCAL_BYTES, 1330 + skb->len - hdr_size); 1331 + 1332 + batadv_interface_rx(bat_priv->soft_iface, skb, hdr_size, NULL); 1333 + /* skb was consumed */ 1334 + skb = NULL; 1335 + } 1336 + 1337 + free_skb: 1338 + kfree_skb(skb); 1339 + 1340 + return ret; 1341 + } 1342 + #endif /* CONFIG_BATMAN_ADV_MCAST */
+11
net/batman-adv/routing.h
··· 27 27 struct batadv_hard_iface *iface); 28 28 int batadv_recv_bcast_packet(struct sk_buff *skb, 29 29 struct batadv_hard_iface *recv_if); 30 + #ifdef CONFIG_BATMAN_ADV_MCAST 31 + int batadv_recv_mcast_packet(struct sk_buff *skb, 32 + struct batadv_hard_iface *recv_if); 33 + #else 34 + static inline int batadv_recv_mcast_packet(struct sk_buff *skb, 35 + struct batadv_hard_iface *recv_if) 36 + { 37 + kfree_skb(skb); 38 + return NET_RX_DROP; 39 + } 40 + #endif 30 41 int batadv_recv_unicast_tvlv(struct sk_buff *skb, 31 42 struct batadv_hard_iface *recv_if); 32 43 int batadv_recv_unhandled_unicast_packet(struct sk_buff *skb,
+12
net/batman-adv/soft-interface.c
··· 925 925 { "tt_response_rx" }, 926 926 { "tt_roam_adv_tx" }, 927 927 { "tt_roam_adv_rx" }, 928 + #ifdef CONFIG_BATMAN_ADV_MCAST 929 + { "mcast_tx" }, 930 + { "mcast_tx_bytes" }, 931 + { "mcast_tx_local" }, 932 + { "mcast_tx_local_bytes" }, 933 + { "mcast_rx" }, 934 + { "mcast_rx_bytes" }, 935 + { "mcast_rx_local" }, 936 + { "mcast_rx_local_bytes" }, 937 + { "mcast_fwd" }, 938 + { "mcast_fwd_bytes" }, 939 + #endif 928 940 #ifdef CONFIG_BATMAN_ADV_DAT 929 941 { "dat_get_tx" }, 930 942 { "dat_get_rx" },
+64
net/batman-adv/types.h
··· 862 862 */ 863 863 BATADV_CNT_TT_ROAM_ADV_RX, 864 864 865 + #ifdef CONFIG_BATMAN_ADV_MCAST 866 + /** 867 + * @BATADV_CNT_MCAST_TX: transmitted batman-adv multicast packets 868 + * counter 869 + */ 870 + BATADV_CNT_MCAST_TX, 871 + 872 + /** 873 + * @BATADV_CNT_MCAST_TX_BYTES: transmitted batman-adv multicast packets 874 + * bytes counter 875 + */ 876 + BATADV_CNT_MCAST_TX_BYTES, 877 + 878 + /** 879 + * @BATADV_CNT_MCAST_TX_LOCAL: counter for multicast packets which 880 + * were locally encapsulated and transmitted as batman-adv multicast 881 + * packets 882 + */ 883 + BATADV_CNT_MCAST_TX_LOCAL, 884 + 885 + /** 886 + * @BATADV_CNT_MCAST_TX_LOCAL_BYTES: bytes counter for multicast packets 887 + * which were locally encapsulated and transmitted as batman-adv 888 + * multicast packets 889 + */ 890 + BATADV_CNT_MCAST_TX_LOCAL_BYTES, 891 + 892 + /** 893 + * @BATADV_CNT_MCAST_RX: received batman-adv multicast packet counter 894 + */ 895 + BATADV_CNT_MCAST_RX, 896 + 897 + /** 898 + * @BATADV_CNT_MCAST_RX_BYTES: received batman-adv multicast packet 899 + * bytes counter 900 + */ 901 + BATADV_CNT_MCAST_RX_BYTES, 902 + 903 + /** 904 + * @BATADV_CNT_MCAST_RX_LOCAL: counter for received batman-adv multicast 905 + * packets which were forwarded to the local soft interface 906 + */ 907 + BATADV_CNT_MCAST_RX_LOCAL, 908 + 909 + /** 910 + * @BATADV_CNT_MCAST_RX_LOCAL_BYTES: bytes counter for received 911 + * batman-adv multicast packets which were forwarded to the local soft 912 + * interface 913 + */ 914 + BATADV_CNT_MCAST_RX_LOCAL_BYTES, 915 + 916 + /** 917 + * @BATADV_CNT_MCAST_FWD: counter for received batman-adv multicast 918 + * packets which were forwarded to other, neighboring nodes 919 + */ 920 + BATADV_CNT_MCAST_FWD, 921 + 922 + /** 923 + * @BATADV_CNT_MCAST_FWD_BYTES: bytes counter for received batman-adv 924 + * multicast packets which were forwarded to other, neighboring nodes 925 + */ 926 + BATADV_CNT_MCAST_FWD_BYTES, 927 + #endif 928 + 865 929 #ifdef CONFIG_BATMAN_ADV_DAT 866 930 /** 867 931 * @BATADV_CNT_DAT_GET_TX: transmitted dht GET traffic packet counter