Skip to content

Instantly share code, notes, and snippets.

@carlos-jenkins
Created October 22, 2025 18:15
Show Gist options
  • Select an option

  • Save carlos-jenkins/64e2d6bcc19e036e5eecc3fda60828af to your computer and use it in GitHub Desktop.

Select an option

Save carlos-jenkins/64e2d6bcc19e036e5eecc3fda60828af to your computer and use it in GitHub Desktop.

Revisions

  1. carlos-jenkins created this gist Oct 22, 2025.
    76 changes: 76 additions & 0 deletions predict.py
    Original 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')