nuttx/net/utils/net_mask2pref.c
Zhe Weng 96233e0c42 net/netdev: Support multiple IPv6 addresses per device
Compatible with previous usage, because may network drivers are using old member name to print logs, and there's no significant need to change them now.

Signed-off-by: Zhe Weng <wengzhe@xiaomi.com>
2023-11-07 19:30:36 +08:00

249 lines
7.3 KiB
C

/****************************************************************************
* net/utils/net_mask2pref.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include "utils/utils.h"
#if defined(CONFIG_NET_IPv4) || defined(CONFIG_NET_IPv6)
/****************************************************************************
* Private Data
****************************************************************************/
static const uint8_t g_nibblemap[16] =
{
0, 0, 0, 0, 0, 0, 0, 0, /* 0: No bits, 1-7: Should not happen */
1, 1, 1, 1, /* 8: 1 bit, 9-b: Should not happen */
2, 2, 3, 4 /* c: 2 bits, d: Should not happen, e: 3 bits, f: 4 bits */
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: net_msbits4
*
* Description:
* Count the number of leading '1' bits in an 4-bit nibble
*
****************************************************************************/
static inline uint8_t net_msbits4(uint8_t nibble)
{
/* Return the number of leading ones: 0-4) */
return g_nibblemap[nibble];
}
/****************************************************************************
* Name: net_msbits8
*
* Description:
* Count the number of leading '1' bits in an 8-bit byte
*
****************************************************************************/
static uint8_t net_msbits8(uint8_t byval)
{
uint8_t ones;
/* Check the MS nibble */
ones = net_msbits4(byval >> 4);
if (ones == 4)
{
/* All ones, try the LS nibble */
ones += net_msbits4(byval & 0x0f);
}
/* Return the number of leading ones (0-8) */
return ones;
}
/****************************************************************************
* Name: net_msbits16
*
* Description:
* Count the number of leading '1' bits in a 16-bit half-workd
*
****************************************************************************/
static inline uint8_t net_msbits16(uint16_t hword)
{
uint8_t ones;
/* Look at the MS byte of the 16-bit value */
ones = net_msbits8((uint8_t)(hword >> 8));
if (ones == 8)
{
/* All '1's, try the LS byte */
ones += net_msbits8((uint8_t)(hword & 0xff));
}
/* Return the number of leading ones (0-15) */
return ones;
}
#endif /* CONFIG_NET_IPv4 || CONFIG_NET_IPv6 */
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: net_ipv4_mask2pref
*
* Description:
* Convert a 32-bit netmask to a prefix length. The NuttX IPv4
* networking uses 32-bit network masks internally. This function
* converts the IPv4 netmask to a prefix length.
*
* The prefix length is the number of MS '1' bits on in the netmask.
* This, of course, assumes that all MS bits are '1' and all LS bits are
* '0' with no intermixed 1's and 0's. This function searches from the MS
* bit until the first '0' is found (this does not necessary mean that
* there might not be additional '1' bits following the firs '0', but that
* will be a malformed netmask.
*
* Input Parameters:
* mask An IPv4 netmask in the form of in_addr_t
*
* Returned Value:
* The prefix length, range 0-32 on success; This function will not
* fail.
*
****************************************************************************/
#ifdef CONFIG_NET_IPv4
uint8_t net_ipv4_mask2pref(in_addr_t mask)
{
uint32_t hmask = NTOHL(mask);
uint8_t ones = net_msbits16((uint16_t)(hmask >> 16));
if (ones == 16)
{
ones += net_msbits16((uint16_t)(hmask & 0xffff));
}
return ones;
}
#endif /* CONFIG_NET_IPv4 */
/****************************************************************************
* Name: net_ipv6_mask2pref
*
* Description:
* Convert a 128-bit netmask to a prefix length. The NuttX IPv6
* networking uses 128-bit network masks internally. This function
* converts the IPv6 netmask to a prefix length.
*
* The prefix length is the number of MS '1' bits on in the netmask.
* This, of course, assumes that all MS bits are '1' and all LS bits are
* '0' with no intermixed 1's and 0's. This function searches from the MS
* bit until the first '0' is found (this does not necessary mean that
* there might not be additional '1' bits following the firs '0', but that
* will be a malformed netmask.
*
* Input Parameters:
* mask Points to an IPv6 netmask in the form of uint16_t[8]
*
* Returned Value:
* The prefix length, range 0-128 on success; This function will not
* fail.
*
****************************************************************************/
#ifdef CONFIG_NET_IPv6
uint8_t net_ipv6_mask2pref(FAR const uint16_t *mask)
{
uint8_t preflen;
int i;
/* Count the leading all '1' 16-bit groups */
for (i = 0, preflen = 0; i < 8 && mask[i] == 0xffff; i++, preflen += 16);
/* Now i either, (1) indexes past the end of the mask, or (2) is the index
* to the first half-word that is not equal to 0xffff.
*/
if (i < 8)
{
preflen += net_msbits16(NTOHS(mask[i]));
}
/* Return the prefix length */
return preflen;
}
/****************************************************************************
* Name: net_ipv6_common_pref
*
* Description:
* Calculate the common prefix length of two IPv6 addresses.
*
* Input Parameters:
* a1,a2 Points to IPv6 addresses in the form of uint16_t[8]
*
* Returned Value:
* The common prefix length, range 0-128 on success; This function will
* not fail.
*
****************************************************************************/
uint8_t net_ipv6_common_pref(FAR const uint16_t *a1, FAR const uint16_t *a2)
{
uint8_t preflen;
int i;
/* Count the leading same 16-bit groups */
for (i = 0, preflen = 0; i < 8 && a1[i] == a2[i]; i++, preflen += 16);
/* Now i either, (1) indexes past the end of the mask, or (2) is the index
* to the first half-word that is not equal between the addresses.
*/
if (i < 8)
{
preflen += net_msbits16(NTOHS(~(a1[i] ^ a2[i])));
}
/* Return the prefix length */
return preflen;
}
#endif /* CONFIG_NET_IPv6 */