按定义的限制减少cidrs列表

时间:2016-11-08 17:08:58

标签: .net network-programming cidr

我有以下实现来将一堆ips解析为多个范围的cidrs。我被最多50个cidrs限制。我需要以某种方式添加该限制。我正在考虑计算每个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());
    }

回应即: enter image description here

1 个答案:

答案 0 :(得分:0)

新希望

我找到了一种更好的方法来生成我的cidrs。我使用的方法是提供ips的前两个八位字节,这主要是因为提供者总是有这些ips的范围。

    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个cidrs),使用上面的原始代码最终返回非常宽的cidrs(/ 8,/ 16)。使用新算法,我只得到/ 32,这是100%优化更新。我知道有5个被浪费了,但这种情况在互联网提供商子网环境下并不真实。

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

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

结果

enter image description here

结论

我绝对建议使用此算法根据特定提供商分配的ips生成cidrs,因为这些提供商通常会在特定范围内移动。