Skip to content

Commit 2dfe644

Browse files
T-Xsimonwunderlich
authored andcommitted
batman-adv: mcast: shrink tracker packet after scrubbing
Remove all zero MAC address entries (00:00:00:00:00:00) from a multicast packet's tracker TVLV before transmitting it and update all headers accordingly. This way, instead of keeping the multicast packet at a constant size throughout its journey through the mesh, it will become more lightweight, smaller with every interested receiver on the way and on each splitting intersection. Which can save some valuable bandwidth. Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue> Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
1 parent 9003913 commit 2dfe644

File tree

1 file changed

+207
-0
lines changed

1 file changed

+207
-0
lines changed

net/batman-adv/multicast_forw.c

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,212 @@ batadv_mcast_forw_scrub_dests(struct batadv_priv *bat_priv,
697697
}
698698
}
699699

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+
700906
/**
701907
* batadv_mcast_forw_packet() - forward a batman-adv multicast packet
702908
* @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,
786992

787993
batadv_mcast_forw_scrub_dests(bat_priv, neigh_node, dest,
788994
next_dest, num_dests);
995+
batadv_mcast_forw_shrink_tracker(nexthop_skb);
789996

790997
batadv_inc_counter(bat_priv, BATADV_CNT_MCAST_TX);
791998
batadv_add_counter(bat_priv, BATADV_CNT_MCAST_TX_BYTES,

0 commit comments

Comments
 (0)