Created
October 22, 2025 18:15
-
-
Save carlos-jenkins/64e2d6bcc19e036e5eecc3fda60828af to your computer and use it in GitHub Desktop.
Revisions
-
carlos-jenkins created this gist
Oct 22, 2025 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,76 @@ import socket import struct def _ipv4_to_u32(ip_str: str) -> int: # network-order (big-endian) to host int return struct.unpack("!I", socket.inet_aton(ip_str))[0] def bond_layer3_4_hash_tcp( src_ip: str, dst_ip: str, src_port: int, dst_port: int, slave_count: int ) -> int: """ Predict the slave index for Linux bonding xmit_hash_policy=layer3+4 for unfragmented TCP. :param str src_ip: Source IPv4 address, e.g. "192.168.1.10" :param str dst_ip: Destination IPv4 address, e.g. "10.0.0.5" :param int src_port: TCP source port (0..65535) :param int dst_port: TCP destination port (0..65535) :param int slave_count: Number of slaves (>0) :return: Slave index in [0, slave_count-1] :rtype: int """ if not (0 <= src_port <= 0xFFFF and 0 <= dst_port <= 0xFFFF): raise ValueError("Ports must be 0..65535") if slave_count <= 0: raise ValueError("slave_count must be > 0") sip = _ipv4_to_u32(src_ip) dip = _ipv4_to_u32(dst_ip) # Start with ports "as in the header". # A common interpretation is to pack them as 16|16 bits: h = ((src_port & 0xFFFF) << 16) | (dst_port & 0xFFFF) # Then XOR in the IPs (L3) h ^= sip ^ dip # Fold/mix as per docs h ^= (h >> 16) h ^= (h >> 8) # Bonding special-case for LAYER34: discard lowest bit h >>= 1 # Reduce to slave index return h % slave_count # Example usage ip_src = '192.168.1.10' ip_dst = '10.0.0.5' slave_count = 2 port_dst = 80 # Show distribution of source ports to slave indices distribution = [0] * slave_count for port_src in range(1, 65536): slave_index = bond_layer3_4_hash_tcp( ip_src, ip_dst, port_src, port_dst, slave_count, ) distribution[slave_index] += 1 print(f'Distribution of source ports to {slave_count} slaves:') for idx, count in enumerate(distribution): print(f' Slave {idx}: {count} ports')