core: implement nm_utils_ip4_netmask_to_prefix() via __builtin_ctz()
Taken from systemd's in4_addr_netmask_to_prefixlen(). Yes, this adds the requirement that "int" is 32 bits. But systemd already has the same requirement in u32ctz(), hence we anyway cannot build on other architectures. If that is ever necessary, it's easy to adjust.
This commit is contained in:
@@ -1389,30 +1389,13 @@ nm_utils_ip4_routes_from_variant (GVariant *value)
|
|||||||
guint32
|
guint32
|
||||||
nm_utils_ip4_netmask_to_prefix (guint32 netmask)
|
nm_utils_ip4_netmask_to_prefix (guint32 netmask)
|
||||||
{
|
{
|
||||||
guint32 prefix;
|
G_STATIC_ASSERT_EXPR (__SIZEOF_INT__ == 4);
|
||||||
guint8 v;
|
G_STATIC_ASSERT_EXPR (sizeof (int) == 4);
|
||||||
const guint8 *p = (guint8 *) &netmask;
|
G_STATIC_ASSERT_EXPR (sizeof (netmask) == 4);
|
||||||
|
|
||||||
if (p[3]) {
|
return ( (netmask != 0)
|
||||||
prefix = 24;
|
? (32 - __builtin_ctz (ntohl (netmask)))
|
||||||
v = p[3];
|
: 0);
|
||||||
} else if (p[2]) {
|
|
||||||
prefix = 16;
|
|
||||||
v = p[2];
|
|
||||||
} else if (p[1]) {
|
|
||||||
prefix = 8;
|
|
||||||
v = p[1];
|
|
||||||
} else {
|
|
||||||
prefix = 0;
|
|
||||||
v = p[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
while (v) {
|
|
||||||
prefix++;
|
|
||||||
v <<= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return prefix;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -3468,6 +3468,41 @@ test_connection_changed_cb (NMConnection *connection, gboolean *data)
|
|||||||
*data = TRUE;
|
*data = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static guint32
|
||||||
|
_netmask_to_prefix (guint32 netmask)
|
||||||
|
{
|
||||||
|
guint32 prefix;
|
||||||
|
guint8 v;
|
||||||
|
const guint8 *p = (guint8 *) &netmask;
|
||||||
|
|
||||||
|
if (p[3]) {
|
||||||
|
prefix = 24;
|
||||||
|
v = p[3];
|
||||||
|
} else if (p[2]) {
|
||||||
|
prefix = 16;
|
||||||
|
v = p[2];
|
||||||
|
} else if (p[1]) {
|
||||||
|
prefix = 8;
|
||||||
|
v = p[1];
|
||||||
|
} else {
|
||||||
|
prefix = 0;
|
||||||
|
v = p[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
while (v) {
|
||||||
|
prefix++;
|
||||||
|
v <<= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_assert_cmpint (prefix, <=, 32);
|
||||||
|
|
||||||
|
/* we re-implemented the netmask-to-prefix code differently. Check
|
||||||
|
* that they agree. */
|
||||||
|
g_assert_cmpint (prefix, ==, nm_utils_ip4_netmask_to_prefix (netmask));
|
||||||
|
|
||||||
|
return prefix;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_ip4_prefix_to_netmask (void)
|
test_ip4_prefix_to_netmask (void)
|
||||||
{
|
{
|
||||||
@@ -3475,7 +3510,7 @@ test_ip4_prefix_to_netmask (void)
|
|||||||
|
|
||||||
for (i = 0; i<=32; i++) {
|
for (i = 0; i<=32; i++) {
|
||||||
guint32 netmask = _nm_utils_ip4_prefix_to_netmask (i);
|
guint32 netmask = _nm_utils_ip4_prefix_to_netmask (i);
|
||||||
int plen = nm_utils_ip4_netmask_to_prefix (netmask);
|
int plen = _netmask_to_prefix (netmask);
|
||||||
|
|
||||||
g_assert_cmpint (i, ==, plen);
|
g_assert_cmpint (i, ==, plen);
|
||||||
{
|
{
|
||||||
@@ -3505,7 +3540,7 @@ test_ip4_netmask_to_prefix (void)
|
|||||||
guint32 netmask = _nm_utils_ip4_prefix_to_netmask (i);
|
guint32 netmask = _nm_utils_ip4_prefix_to_netmask (i);
|
||||||
guint32 netmask_lowest_bit = netmask & ~_nm_utils_ip4_prefix_to_netmask (i-1);
|
guint32 netmask_lowest_bit = netmask & ~_nm_utils_ip4_prefix_to_netmask (i-1);
|
||||||
|
|
||||||
g_assert_cmpint (i, ==, nm_utils_ip4_netmask_to_prefix (netmask));
|
g_assert_cmpint (i, ==, _netmask_to_prefix (netmask));
|
||||||
|
|
||||||
for (j = 0; j < 2*i; j++) {
|
for (j = 0; j < 2*i; j++) {
|
||||||
guint32 r = g_rand_int (rand);
|
guint32 r = g_rand_int (rand);
|
||||||
@@ -3519,7 +3554,7 @@ test_ip4_netmask_to_prefix (void)
|
|||||||
|
|
||||||
/* create an invalid netmask with holes and check that the function
|
/* create an invalid netmask with holes and check that the function
|
||||||
* returns the longest prefix. */
|
* returns the longest prefix. */
|
||||||
prefix_holey = nm_utils_ip4_netmask_to_prefix (netmask_holey);
|
prefix_holey = _netmask_to_prefix (netmask_holey);
|
||||||
|
|
||||||
g_assert_cmpint (i, ==, prefix_holey);
|
g_assert_cmpint (i, ==, prefix_holey);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user