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

batman-adv: Announce new capability via multicast TVLV

If the soft interface of a node is not part of a bridge then a node
announces a new multicast TVLV: The existence of this TVLV
signalizes that this node is announcing all of its multicast listeners
via the translation table infrastructure.

Signed-off-by: Linus Lüssing <linus.luessing@web.de>
Signed-off-by: Marek Lindner <mareklindner@neomailbox.ch>
Signed-off-by: Antonio Quartulli <antonio@meshcoding.com>

authored by

Linus Lüssing and committed by
Antonio Quartulli
60432d75 e17931d1

+167 -6
+1
net/batman-adv/main.c
··· 149 149 goto err; 150 150 151 151 batadv_gw_init(bat_priv); 152 + batadv_mcast_init(bat_priv); 152 153 153 154 atomic_set(&bat_priv->gw.reselect, 0); 154 155 atomic_set(&bat_priv->mesh_state, BATADV_MESH_ACTIVE);
+117 -6
net/batman-adv/multicast.c
··· 178 178 } 179 179 180 180 /** 181 + * batadv_mcast_mla_tvlv_update - update multicast tvlv 182 + * @bat_priv: the bat priv with all the soft interface information 183 + * 184 + * Updates the own multicast tvlv with our current multicast related settings, 185 + * capabilities and inabilities. 186 + * 187 + * Returns true if the tvlv container is registered afterwards. Otherwise 188 + * returns false. 189 + */ 190 + static bool batadv_mcast_mla_tvlv_update(struct batadv_priv *bat_priv) 191 + { 192 + struct batadv_tvlv_mcast_data mcast_data; 193 + 194 + mcast_data.flags = BATADV_NO_FLAGS; 195 + memset(mcast_data.reserved, 0, sizeof(mcast_data.reserved)); 196 + 197 + /* Avoid attaching MLAs, if there is a bridge on top of our soft 198 + * interface, we don't support that yet (TODO) 199 + */ 200 + if (batadv_mcast_has_bridge(bat_priv)) { 201 + if (bat_priv->mcast.enabled) { 202 + batadv_tvlv_container_unregister(bat_priv, 203 + BATADV_TVLV_MCAST, 1); 204 + bat_priv->mcast.enabled = false; 205 + } 206 + 207 + return false; 208 + } 209 + 210 + if (!bat_priv->mcast.enabled || 211 + mcast_data.flags != bat_priv->mcast.flags) { 212 + batadv_tvlv_container_register(bat_priv, BATADV_TVLV_MCAST, 1, 213 + &mcast_data, sizeof(mcast_data)); 214 + bat_priv->mcast.flags = mcast_data.flags; 215 + bat_priv->mcast.enabled = true; 216 + } 217 + 218 + return true; 219 + } 220 + 221 + /** 181 222 * batadv_mcast_mla_update - update the own MLAs 182 223 * @bat_priv: the bat priv with all the soft interface information 183 224 * 184 - * Update the own multicast listener announcements in the translation 185 - * table. 225 + * Updates the own multicast listener announcements in the translation 226 + * table as well as the own, announced multicast tvlv container. 186 227 */ 187 228 void batadv_mcast_mla_update(struct batadv_priv *bat_priv) 188 229 { ··· 231 190 struct hlist_head mcast_list = HLIST_HEAD_INIT; 232 191 int ret; 233 192 234 - /* Avoid attaching MLAs, if there is a bridge on top of our soft 235 - * interface, we don't support that yet (TODO) 236 - */ 237 - if (batadv_mcast_has_bridge(bat_priv)) 193 + if (!batadv_mcast_mla_tvlv_update(bat_priv)) 238 194 goto update; 239 195 240 196 ret = batadv_mcast_mla_softif_get(soft_iface, &mcast_list); ··· 247 209 } 248 210 249 211 /** 212 + * batadv_mcast_tvlv_ogm_handler_v1 - process incoming multicast tvlv container 213 + * @bat_priv: the bat priv with all the soft interface information 214 + * @orig: the orig_node of the ogm 215 + * @flags: flags indicating the tvlv state (see batadv_tvlv_handler_flags) 216 + * @tvlv_value: tvlv buffer containing the multicast data 217 + * @tvlv_value_len: tvlv buffer length 218 + */ 219 + static void batadv_mcast_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv, 220 + struct batadv_orig_node *orig, 221 + uint8_t flags, 222 + void *tvlv_value, 223 + uint16_t tvlv_value_len) 224 + { 225 + bool orig_mcast_enabled = !(flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND); 226 + uint8_t mcast_flags = BATADV_NO_FLAGS; 227 + bool orig_initialized; 228 + 229 + orig_initialized = orig->capa_initialized & BATADV_ORIG_CAPA_HAS_MCAST; 230 + 231 + /* If mcast support is turned on decrease the disabled mcast node 232 + * counter only if we had increased it for this node before. If this 233 + * is a completely new orig_node no need to decrease the counter. 234 + */ 235 + if (orig_mcast_enabled && 236 + !(orig->capabilities & BATADV_ORIG_CAPA_HAS_MCAST)) { 237 + if (orig_initialized) 238 + atomic_dec(&bat_priv->mcast.num_disabled); 239 + orig->capabilities |= BATADV_ORIG_CAPA_HAS_MCAST; 240 + /* If mcast support is being switched off increase the disabled 241 + * mcast node counter. 242 + */ 243 + } else if (!orig_mcast_enabled && 244 + orig->capabilities & BATADV_ORIG_CAPA_HAS_MCAST) { 245 + atomic_inc(&bat_priv->mcast.num_disabled); 246 + orig->capabilities &= ~BATADV_ORIG_CAPA_HAS_MCAST; 247 + } 248 + 249 + orig->capa_initialized |= BATADV_ORIG_CAPA_HAS_MCAST; 250 + 251 + if (orig_mcast_enabled && tvlv_value && 252 + (tvlv_value_len >= sizeof(mcast_flags))) 253 + mcast_flags = *(uint8_t *)tvlv_value; 254 + 255 + orig->mcast_flags = mcast_flags; 256 + } 257 + 258 + /** 259 + * batadv_mcast_init - initialize the multicast optimizations structures 260 + * @bat_priv: the bat priv with all the soft interface information 261 + */ 262 + void batadv_mcast_init(struct batadv_priv *bat_priv) 263 + { 264 + batadv_tvlv_handler_register(bat_priv, batadv_mcast_tvlv_ogm_handler_v1, 265 + NULL, BATADV_TVLV_MCAST, 1, 266 + BATADV_TVLV_HANDLER_OGM_CIFNOTFND); 267 + } 268 + 269 + /** 250 270 * batadv_mcast_free - free the multicast optimizations structures 251 271 * @bat_priv: the bat priv with all the soft interface information 252 272 */ 253 273 void batadv_mcast_free(struct batadv_priv *bat_priv) 254 274 { 275 + batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_MCAST, 1); 276 + batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_MCAST, 1); 277 + 255 278 batadv_mcast_mla_tt_retract(bat_priv, NULL); 279 + } 280 + 281 + /** 282 + * batadv_mcast_purge_orig - reset originator global mcast state modifications 283 + * @orig: the originator which is going to get purged 284 + */ 285 + void batadv_mcast_purge_orig(struct batadv_orig_node *orig) 286 + { 287 + struct batadv_priv *bat_priv = orig->bat_priv; 288 + 289 + if (!(orig->capabilities & BATADV_ORIG_CAPA_HAS_MCAST)) 290 + atomic_dec(&bat_priv->mcast.num_disabled); 256 291 }
+14
net/batman-adv/multicast.h
··· 22 22 23 23 void batadv_mcast_mla_update(struct batadv_priv *bat_priv); 24 24 25 + void batadv_mcast_init(struct batadv_priv *bat_priv); 26 + 25 27 void batadv_mcast_free(struct batadv_priv *bat_priv); 28 + 29 + void batadv_mcast_purge_orig(struct batadv_orig_node *orig_node); 26 30 27 31 #else 28 32 ··· 35 31 return; 36 32 } 37 33 34 + static inline int batadv_mcast_init(struct batadv_priv *bat_priv) 35 + { 36 + return 0; 37 + } 38 + 38 39 static inline void batadv_mcast_free(struct batadv_priv *bat_priv) 40 + { 41 + return; 42 + } 43 + 44 + static inline void batadv_mcast_purge_orig(struct batadv_orig_node *orig_node) 39 45 { 40 46 return; 41 47 }
+6
net/batman-adv/originator.c
··· 27 27 #include "bridge_loop_avoidance.h" 28 28 #include "network-coding.h" 29 29 #include "fragmentation.h" 30 + #include "multicast.h" 30 31 31 32 /* hash class keys */ 32 33 static struct lock_class_key batadv_orig_hash_lock_class_key; ··· 558 557 } 559 558 spin_unlock_bh(&orig_node->neigh_list_lock); 560 559 560 + batadv_mcast_purge_orig(orig_node); 561 + 561 562 /* Free nc_nodes */ 562 563 batadv_nc_purge_orig(orig_node->bat_priv, orig_node, NULL); 563 564 ··· 675 672 orig_node->tt_buff_len = 0; 676 673 reset_time = jiffies - 1 - msecs_to_jiffies(BATADV_RESET_PROTECTION_MS); 677 674 orig_node->bcast_seqno_reset = reset_time; 675 + #ifdef CONFIG_BATMAN_ADV_MCAST 676 + orig_node->mcast_flags = BATADV_NO_FLAGS; 677 + #endif 678 678 679 679 /* create a vlan object for the "untagged" LAN */ 680 680 vlan = batadv_orig_node_vlan_new(orig_node, BATADV_NO_FLAGS);
+12
net/batman-adv/packet.h
··· 145 145 * @BATADV_TVLV_NC: network coding tvlv 146 146 * @BATADV_TVLV_TT: translation table tvlv 147 147 * @BATADV_TVLV_ROAM: roaming advertisement tvlv 148 + * @BATADV_TVLV_MCAST: multicast capability tvlv 148 149 */ 149 150 enum batadv_tvlv_type { 150 151 BATADV_TVLV_GW = 0x01, ··· 153 152 BATADV_TVLV_NC = 0x03, 154 153 BATADV_TVLV_TT = 0x04, 155 154 BATADV_TVLV_ROAM = 0x05, 155 + BATADV_TVLV_MCAST = 0x06, 156 156 }; 157 157 158 158 #pragma pack(2) ··· 504 502 struct batadv_tvlv_roam_adv { 505 503 uint8_t client[ETH_ALEN]; 506 504 __be16 vid; 505 + }; 506 + 507 + /** 508 + * struct batadv_tvlv_mcast_data - payload of a multicast tvlv 509 + * @flags: multicast flags announced by the orig node 510 + * @reserved: reserved field 511 + */ 512 + struct batadv_tvlv_mcast_data { 513 + uint8_t flags; 514 + uint8_t reserved[3]; 507 515 }; 508 516 509 517 #endif /* _NET_BATMAN_ADV_PACKET_H_ */
+4
net/batman-adv/soft-interface.c
··· 689 689 #ifdef CONFIG_BATMAN_ADV_DAT 690 690 atomic_set(&bat_priv->distributed_arp_table, 1); 691 691 #endif 692 + #ifdef CONFIG_BATMAN_ADV_MCAST 693 + bat_priv->mcast.flags = BATADV_NO_FLAGS; 694 + atomic_set(&bat_priv->mcast.num_disabled, 0); 695 + #endif 692 696 atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF); 693 697 atomic_set(&bat_priv->gw_sel_class, 20); 694 698 atomic_set(&bat_priv->gw.bandwidth_down, 100);
+13
net/batman-adv/types.h
··· 204 204 * @batadv_dat_addr_t: address of the orig node in the distributed hash 205 205 * @last_seen: time when last packet from this node was received 206 206 * @bcast_seqno_reset: time when the broadcast seqno window was reset 207 + * @mcast_flags: multicast flags announced by the orig node 207 208 * @capabilities: announced capabilities of this originator 208 209 * @capa_initialized: bitfield to remember whether a capability was initialized 209 210 * @last_ttvn: last seen translation table version number ··· 247 246 #endif 248 247 unsigned long last_seen; 249 248 unsigned long bcast_seqno_reset; 249 + #ifdef CONFIG_BATMAN_ADV_MCAST 250 + uint8_t mcast_flags; 251 + #endif 250 252 uint8_t capabilities; 251 253 uint8_t capa_initialized; 252 254 atomic_t last_ttvn; ··· 286 282 * @BATADV_ORIG_CAPA_HAS_DAT: orig node has distributed arp table enabled 287 283 * @BATADV_ORIG_CAPA_HAS_NC: orig node has network coding enabled 288 284 * @BATADV_ORIG_CAPA_HAS_TT: orig node has tt capability 285 + * @BATADV_ORIG_CAPA_HAS_MCAST: orig node has some multicast capability 286 + * (= orig node announces a tvlv of type BATADV_TVLV_MCAST) 289 287 */ 290 288 enum batadv_orig_capabilities { 291 289 BATADV_ORIG_CAPA_HAS_DAT = BIT(0), 292 290 BATADV_ORIG_CAPA_HAS_NC = BIT(1), 293 291 BATADV_ORIG_CAPA_HAS_TT = BIT(2), 292 + BATADV_ORIG_CAPA_HAS_MCAST = BIT(3), 294 293 }; 295 294 296 295 /** ··· 619 612 /** 620 613 * struct batadv_priv_mcast - per mesh interface mcast data 621 614 * @mla_list: list of multicast addresses we are currently announcing via TT 615 + * @flags: the flags we have last sent in our mcast tvlv 616 + * @enabled: whether the multicast tvlv is currently enabled 617 + * @num_disabled: number of nodes that have no mcast tvlv 622 618 */ 623 619 struct batadv_priv_mcast { 624 620 struct hlist_head mla_list; 621 + uint8_t flags; 622 + bool enabled; 623 + atomic_t num_disabled; 625 624 }; 626 625 #endif 627 626