def generate_ULA(mac, subnet_id = 0, locally_assigned=true)
      now = Time.now.utc
      ntp_time = ((now.to_i + 2208988800) << 32) + now.nsec # Convert time to an NTP timstamp.
      system_id = '::/64'.to_ip.eui_64(mac).to_i # Generate an EUI64 from the provided MAC address.
      key = [ ntp_time, system_id ].pack('QQ') # Pack the ntp timestamp and the system_id into a binary string
      global_id = Digest::SHA1.digest( key ).unpack('QQ').last & 0xffffffffff # Use only the last 40 bytes of the SHA1 digest.

      prefix =
      (126 << 121) + # 0xfc (bytes 0..6)
      ((locally_assigned ? 1 : 0) << 120) + # locally assigned? (byte 7)
      (global_id << 80) + # 40 bit global idenfitier (bytes 8..48)
      ((subnet_id & 0xffff) << 64) # 16 bit subnet_id (bytes 48..64)

      prefix.to_ip(Socket::AF_INET6).tap { |p| p.length = 64 }
    end
def generate_ULA(mac, subnet_id = 0, locally_assigned=true)
      now = Time.now.utc
      ntp_time = ((now.to_i + 2208988800) << 32) + now.nsec # Convert time to an NTP timstamp.
      system_id = '::/64'.to_ip.eui_64(mac).to_i # Generate an EUI64 from the provided MAC address.
      key = [ ntp_time, system_id ].pack('QQ') # Pack the ntp timestamp and the system_id into a binary string
      global_id = Digest::SHA1.digest( key ).unpack('QQ').last & 0xffffffffff # Use only the last 40 bytes of the SHA1 digest.

      prefix =
      (126 << 121) + # 0xfc (bytes 0..6)
      ((locally_assigned ? 1 : 0) << 120) + # locally assigned? (byte 7)
      (global_id << 80) + # 40 bit global idenfitier (bytes 8..48)
      ((subnet_id & 0xffff) << 64) # 16 bit subnet_id (bytes 48..64)

      prefix.to_ip(Socket::AF_INET6).tap { |p| p.length = 64 }
    end
Generate an IPv6 Unique Local Address using the supplied system MAC address.
 Note that the MAC address is just used as a source of randomness, so where you
 get it from is not important and doesn't restrict this ULA to just that system.
 See RFC4193