Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 45 additions & 1 deletion common/ipprefix.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include <assert.h>
#include <stdexcept>
#include <arpa/inet.h>
#include "ipaddress.h"

namespace swss {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down
29 changes: 29 additions & 0 deletions tests/ipprefix_ut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}