@@ -697,6 +697,212 @@ batadv_mcast_forw_scrub_dests(struct batadv_priv *bat_priv,
697
697
}
698
698
}
699
699
700
+ /**
701
+ * batadv_mcast_forw_shrink_fill() - swap slot with next non-zero destination
702
+ * @slot: the to be filled zero-MAC destination entry in a tracker TVLV
703
+ * @num_dests_slot: remaining entries in tracker TVLV from/including slot
704
+ *
705
+ * Searches for the next non-zero-MAC destination entry in a tracker TVLV after
706
+ * the given slot pointer. And if found, swaps it with the zero-MAC destination
707
+ * entry which the slot points to.
708
+ *
709
+ * Return: true if slot was swapped/filled successfully, false otherwise.
710
+ */
711
+ static bool batadv_mcast_forw_shrink_fill (u8 * slot , u16 num_dests_slot )
712
+ {
713
+ u16 num_dests_filler ;
714
+ u8 * filler ;
715
+
716
+ /* sanity check, should not happen */
717
+ if (!num_dests_slot )
718
+ return false;
719
+
720
+ num_dests_filler = num_dests_slot - 1 ;
721
+ filler = slot + ETH_ALEN ;
722
+
723
+ /* find a candidate to fill the empty slot */
724
+ batadv_mcast_forw_tracker_for_each_dest (filler , num_dests_filler ) {
725
+ if (is_zero_ether_addr (filler ))
726
+ continue ;
727
+
728
+ ether_addr_copy (slot , filler );
729
+ eth_zero_addr (filler );
730
+ return true;
731
+ }
732
+
733
+ return false;
734
+ }
735
+
736
+ /**
737
+ * batadv_mcast_forw_shrink_pack_dests() - pack destinations of a tracker TVLV
738
+ * @skb: the batman-adv multicast packet to compact destinations in
739
+ *
740
+ * Compacts the originator destination MAC addresses in the multicast tracker
741
+ * TVLV of the given multicast packet. This is done by moving all non-zero
742
+ * MAC addresses in direction of the skb head and all zero MAC addresses in skb
743
+ * tail direction, within the multicast tracker TVLV.
744
+ *
745
+ * Return: The number of consecutive zero MAC address destinations which are
746
+ * now at the end of the multicast tracker TVLV.
747
+ */
748
+ static int batadv_mcast_forw_shrink_pack_dests (struct sk_buff * skb )
749
+ {
750
+ struct batadv_tvlv_mcast_tracker * mcast_tracker ;
751
+ unsigned char * skb_net_hdr ;
752
+ u16 num_dests_slot ;
753
+ u8 * slot ;
754
+
755
+ skb_net_hdr = skb_network_header (skb );
756
+ mcast_tracker = (struct batadv_tvlv_mcast_tracker * )skb_net_hdr ;
757
+ num_dests_slot = ntohs (mcast_tracker -> num_dests );
758
+
759
+ slot = (u8 * )mcast_tracker + sizeof (* mcast_tracker );
760
+
761
+ batadv_mcast_forw_tracker_for_each_dest (slot , num_dests_slot ) {
762
+ /* find an empty slot */
763
+ if (!is_zero_ether_addr (slot ))
764
+ continue ;
765
+
766
+ if (!batadv_mcast_forw_shrink_fill (slot , num_dests_slot ))
767
+ /* could not find a filler, so we successfully packed
768
+ * and can stop - and must not reduce num_dests_slot!
769
+ */
770
+ break ;
771
+ }
772
+
773
+ /* num_dests_slot is now the amount of reduced, zeroed
774
+ * destinations at the end of the tracker TVLV
775
+ */
776
+ return num_dests_slot ;
777
+ }
778
+
779
+ /**
780
+ * batadv_mcast_forw_shrink_align_offset() - get new alignment offset
781
+ * @num_dests_old: the old, to be updated amount of destination nodes
782
+ * @num_dests_reduce: the number of destinations that were removed
783
+ *
784
+ * Calculates the amount of potential extra alignment offset that is needed to
785
+ * adjust the TVLV padding after the change in destination nodes.
786
+ *
787
+ * Return:
788
+ * 0: If no change to padding is needed.
789
+ * 2: If padding needs to be removed.
790
+ * -2: If padding needs to be added.
791
+ */
792
+ static short
793
+ batadv_mcast_forw_shrink_align_offset (unsigned int num_dests_old ,
794
+ unsigned int num_dests_reduce )
795
+ {
796
+ /* even amount of removed destinations -> no alignment change */
797
+ if (!(num_dests_reduce % 2 ))
798
+ return 0 ;
799
+
800
+ /* even to odd amount of destinations -> remove padding */
801
+ if (!(num_dests_old % 2 ))
802
+ return 2 ;
803
+
804
+ /* odd to even amount of destinations -> add padding */
805
+ return -2 ;
806
+ }
807
+
808
+ /**
809
+ * batadv_mcast_forw_shrink_update_headers() - update shrunk mc packet headers
810
+ * @skb: the batman-adv multicast packet to update headers of
811
+ * @num_dests_reduce: the number of destinations that were removed
812
+ *
813
+ * This updates any fields of a batman-adv multicast packet that are affected
814
+ * by the reduced number of destinations in the multicast tracket TVLV. In
815
+ * particular this updates:
816
+ *
817
+ * The num_dest field of the multicast tracker TVLV.
818
+ * The TVLV length field of the according generic TVLV header.
819
+ * The batman-adv multicast packet's total TVLV length field.
820
+ *
821
+ * Return: The offset in skb's tail direction at which the new batman-adv
822
+ * multicast packet header needs to start.
823
+ */
824
+ static unsigned int
825
+ batadv_mcast_forw_shrink_update_headers (struct sk_buff * skb ,
826
+ unsigned int num_dests_reduce )
827
+ {
828
+ struct batadv_tvlv_mcast_tracker * mcast_tracker ;
829
+ struct batadv_mcast_packet * mcast_packet ;
830
+ struct batadv_tvlv_hdr * tvlv_hdr ;
831
+ unsigned char * skb_net_hdr ;
832
+ unsigned int offset ;
833
+ short align_offset ;
834
+ u16 num_dests ;
835
+
836
+ skb_net_hdr = skb_network_header (skb );
837
+ mcast_tracker = (struct batadv_tvlv_mcast_tracker * )skb_net_hdr ;
838
+ num_dests = ntohs (mcast_tracker -> num_dests );
839
+
840
+ align_offset = batadv_mcast_forw_shrink_align_offset (num_dests ,
841
+ num_dests_reduce );
842
+ offset = ETH_ALEN * num_dests_reduce + align_offset ;
843
+ num_dests -= num_dests_reduce ;
844
+
845
+ /* update tracker header */
846
+ mcast_tracker -> num_dests = htons (num_dests );
847
+
848
+ /* update tracker's tvlv header's length field */
849
+ tvlv_hdr = (struct batadv_tvlv_hdr * )(skb_network_header (skb ) -
850
+ sizeof (* tvlv_hdr ));
851
+ tvlv_hdr -> len = htons (ntohs (tvlv_hdr -> len ) - offset );
852
+
853
+ /* update multicast packet header's tvlv length field */
854
+ mcast_packet = (struct batadv_mcast_packet * )skb -> data ;
855
+ mcast_packet -> tvlv_len = htons (ntohs (mcast_packet -> tvlv_len ) - offset );
856
+
857
+ return offset ;
858
+ }
859
+
860
+ /**
861
+ * batadv_mcast_forw_shrink_move_headers() - move multicast headers by offset
862
+ * @skb: the batman-adv multicast packet to move headers for
863
+ * @offset: a non-negative offset to move headers by, towards the skb tail
864
+ *
865
+ * Moves the batman-adv multicast packet header, its multicast tracker TVLV and
866
+ * any TVLVs in between by the given offset in direction towards the tail.
867
+ */
868
+ static void
869
+ batadv_mcast_forw_shrink_move_headers (struct sk_buff * skb , unsigned int offset )
870
+ {
871
+ struct batadv_tvlv_mcast_tracker * mcast_tracker ;
872
+ unsigned char * skb_net_hdr ;
873
+ unsigned int len ;
874
+ u16 num_dests ;
875
+
876
+ skb_net_hdr = skb_network_header (skb );
877
+ mcast_tracker = (struct batadv_tvlv_mcast_tracker * )skb_net_hdr ;
878
+ num_dests = ntohs (mcast_tracker -> num_dests );
879
+ len = skb_network_offset (skb ) + sizeof (* mcast_tracker );
880
+ len += num_dests * ETH_ALEN ;
881
+
882
+ batadv_mcast_forw_scrape (skb , len , offset );
883
+ }
884
+
885
+ /**
886
+ * batadv_mcast_forw_shrink_tracker() - remove zero addresses in a tracker tvlv
887
+ * @skb: the batman-adv multicast packet to (potentially) shrink
888
+ *
889
+ * Removes all destinations with a zero MAC addresses (00:00:00:00:00:00) from
890
+ * the given batman-adv multicast packet's tracker TVLV and updates headers
891
+ * accordingly to maintain a valid batman-adv multicast packet.
892
+ */
893
+ static void batadv_mcast_forw_shrink_tracker (struct sk_buff * skb )
894
+ {
895
+ unsigned int offset ;
896
+ u16 dests_reduced ;
897
+
898
+ dests_reduced = batadv_mcast_forw_shrink_pack_dests (skb );
899
+ if (!dests_reduced )
900
+ return ;
901
+
902
+ offset = batadv_mcast_forw_shrink_update_headers (skb , dests_reduced );
903
+ batadv_mcast_forw_shrink_move_headers (skb , offset );
904
+ }
905
+
700
906
/**
701
907
* batadv_mcast_forw_packet() - forward a batman-adv multicast packet
702
908
* @bat_priv: the bat priv with all the soft interface information
@@ -786,6 +992,7 @@ static int batadv_mcast_forw_packet(struct batadv_priv *bat_priv,
786
992
787
993
batadv_mcast_forw_scrub_dests (bat_priv , neigh_node , dest ,
788
994
next_dest , num_dests );
995
+ batadv_mcast_forw_shrink_tracker (nexthop_skb );
789
996
790
997
batadv_inc_counter (bat_priv , BATADV_CNT_MCAST_TX );
791
998
batadv_add_counter (bat_priv , BATADV_CNT_MCAST_TX_BYTES ,
0 commit comments