【问题标题】:Reduce list of cidrs by a defined limit通过定义的限制减少 cidr 列表
【发布时间】:2016-11-08 17:08:58
【问题描述】:

我得到了以下实现来将一堆 ips 解析成多个 cidr 范围。我最多限制为 50 个 cidr。我需要以某种方式添加该限制。我正在考虑计算每个 cidr 之间的距离以对它们进行分组,直到我达到某种递归算法的 50 限制。

有什么建议吗?

    public static IEnumerable<string> Parse(IEnumerable<string> ipCollection)
    {
        var ips = ipCollection as IList<string> ?? ipCollection.ToList();

        if (!ips.Any()) return Enumerable.Empty<string>();

        var parsedIps = new List<IPNetwork>();

        foreach (var ip in ips)
        {
            IPNetwork ipNetwork;
            if (IPNetwork.TryParse(ip, out ipNetwork)) parsedIps.Add(ipNetwork);
        }

        // unable to parse any ips
        if (!parsedIps.Any()) return Enumerable.Empty<string>();

        return parsedIps.Count == 1
            ? ips.Select(ip => $"{ip}/32")
            : IPNetwork.Supernet(parsedIps.ToArray()).Select(x => x.ToString());
    }

响应即:

【问题讨论】:

    标签: .net network-programming cidr


    【解决方案1】:

    新的希望

    我找到了一种更好的方法来生成我的 cidr。我使用的方法是按提供的 ip 的前两个八位字节分组,基本上是因为提供商总是有这些 ip 的范围。

        public static IEnumerable<string> Parse(IEnumerable<string> ipCollection)
        {
            var parsedIpAddresses = new List<IPAddress>();
    
            ipCollection.ForEach(ip =>
            {
                IPAddress validIp;
                if (IPAddress.TryParse(ip, out validIp)) parsedIpAddresses.Add(validIp);
            });
    
            return SplitCidrs(parsedIpAddresses);
        }
    
        private static IEnumerable<string> SplitCidrs(List<IPAddress> ips)
        {
            var cidrs = new List<IPNetwork>();
    
            foreach (var mask in GetOrderedMasks(ips))
            {
                var filterIps = ips.Where(
                        x => x.ToString().StartsWith(mask)
                    )
                    .OrderBy(x => x.Address)
                    .Select(x => x.ToString())
                    .ToList();
    
                var newCidr = IPNetwork.WideSubnet(filterIps.First(), filterIps.Last());
    
                if (!cidrs.Contains(newCidr))
                {
                    cidrs.Add(newCidr);
                }
    
                if (cidrs.Count >= AwsSgLimit - 1)
                {
                    throw new AmazonSgLimitReached();
                }
            }
    
            return cidrs.Select(x => x.ToString());
        }
    
        private static IEnumerable<string> GetOrderedMasks(IEnumerable<IPAddress> ips)
        {
            return ips
                .Where(x => !x.ToString().StartsWith("10."))
                .GroupBy(
                    x => string.Join(".", x.GetAddressBytes().Take(2))
                )
                .OrderByDescending(x => x.Count())
                .Select(group => group.Key.ToString() + ".");
        }
    

    测试

    在下面的算法中,我使用了一种完全不同的方法,我已经用不同的 IP 群体进行了测试。在其中一项测试中,我将 55 个不一致的 ips(记住我的限制是 50 个 cidr)传递给函数,使用上面的原始代码最终会返回非常宽的 cidr(/8、/16)。使用新算法,我只得到 /32,这是 100% 优化更新。我知道有 5 个被浪费了,但这种情况在 Internet 提供商子网环境下并不真实。

    在第二次测试中,我再次通过了真实的生产数据。结果非常好,因为我摆脱了所有的“/7”和九个“/8”(1.61 亿 ips现在我只获得一个“/16”(65k ips)作为最差 cidr。考虑到这是真实数据,这也是一个巨大的改进,我基本上得到了相同的结果。

    其余的是实际范围,但仍然很小(21、24、28)和孤立的 ips (32)。仍有改进的空间,因为我们没有达到 AWS 50 x 28 个免费插槽的限制。

    结果

    结论

    我绝对推荐此算法根据特定提供商分配的 ips 生成 cidr,因为这些提供商通常在一定范围内移动。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-04
      • 1970-01-01
      • 1970-01-01
      • 2014-12-02
      • 2021-07-12
      • 2018-11-28
      • 1970-01-01
      • 2016-10-19
      相关资源
      最近更新 更多