diff --git a/common/ipprefix.h b/common/ipprefix.h index f1c4d27fe..0b1815799 100644 --- a/common/ipprefix.h +++ b/common/ipprefix.h @@ -3,6 +3,7 @@ #include #include +#include #include "ipaddress.h" namespace swss { @@ -65,7 +66,7 @@ class IpPrefix { ip_addr_t ipa; ipa.family = AF_INET6; - + assert(m_mask >= 0 && m_mask <= 128); int mid = m_mask >> 3; int bits = m_mask & 0x7; @@ -133,6 +134,49 @@ class IpPrefix } } + inline IpPrefix getSubnet() const + { + switch (m_ip.getIp().family) + { + case AF_INET: + { + uint32_t ipaddr = m_ip.getV4Addr(); + uint32_t mask = getMask().getV4Addr(); + + ipaddr &= mask; + return IpPrefix(ipaddr, m_mask); + } + + case AF_INET6: + { + const uint8_t *ipaddr = m_ip.getV6Addr(); + uint8_t subnet[INET6_ADDRSTRLEN] = {0}; + memcpy(subnet, ipaddr, 16); + + IpAddress ip6mask = getMask(); + const uint8_t *mask = ip6mask.getV6Addr(); + + for (int i = 0; i < 16; ++i) + { + subnet[i] &= mask[i]; + } + + char buf[INET6_ADDRSTRLEN]; + std::string ipStr(inet_ntop(AF_INET6, + &subnet, + buf, + INET6_ADDRSTRLEN)); + + return IpPrefix(ipStr + "/" + std::to_string(m_mask)); + } + + default: + { + throw std::logic_error("Invalid family"); + } + } + } + inline bool operator<(const IpPrefix &o) const { if (m_mask != o.m_mask) diff --git a/tests/ipprefix_ut.cpp b/tests/ipprefix_ut.cpp index 623693955..26d60fbce 100644 --- a/tests/ipprefix_ut.cpp +++ b/tests/ipprefix_ut.cpp @@ -115,3 +115,32 @@ TEST(IpPrefix, subnet) EXPECT_FALSE(prefix1.isAddressInSubnet(ip3)); EXPECT_FALSE(prefix2.isAddressInSubnet(ip3)); } + +TEST(IpPrefix, getSubnet) +{ + // IPv4 prefixes + IpPrefix prefix1("1.1.1.0/0"); + IpPrefix prefix2("1.1.1.191/24"); + IpPrefix prefix3("1.1.1.191/26"); + IpPrefix prefix4("1.1.191.1/20"); + IpPrefix prefix5("2.2.2.2/32"); + + // IPv6 prefixes + IpPrefix prefix6("::/0"); + IpPrefix prefix7("2001:4898:f0:f153:357c:77b2:49c9:627c/64"); + IpPrefix prefix8("2001:4898:f0:f153:357c:77b2:49c9:627c/63"); + IpPrefix prefix9("2001:4898:f0:f153:357c:77b2:49c9:627c/45"); + IpPrefix prefix10("2001:4898:f0:f153:357c:77b2:49c9:627c/128"); + + EXPECT_EQ("0.0.0.0/0", prefix1.getSubnet().to_string()); + EXPECT_EQ("1.1.1.0/24", prefix2.getSubnet().to_string()); + EXPECT_EQ("1.1.1.128/26", prefix3.getSubnet().to_string()); + EXPECT_EQ("1.1.176.0/20", prefix4.getSubnet().to_string()); + EXPECT_EQ("2.2.2.2/32", prefix5.getSubnet().to_string()); + + EXPECT_EQ("::/0", prefix6.getSubnet().to_string()); + EXPECT_EQ("2001:4898:f0:f153::/64", prefix7.getSubnet().to_string()); + EXPECT_EQ("2001:4898:f0:f152::/63", prefix8.getSubnet().to_string()); + EXPECT_EQ("2001:4898:f0::/45", prefix9.getSubnet().to_string()); + EXPECT_EQ("2001:4898:f0:f153:357c:77b2:49c9:627c/128", prefix10.getSubnet().to_string()); +}