net/netlink: Add RTM preifx notify support

Signed-off-by: meijian <meijian@xiaomi.com>
This commit is contained in:
meijian 2024-04-19 16:47:34 +08:00 committed by Alan Carvalho de Assis
parent 8eaefd2424
commit 4702a09538
5 changed files with 160 additions and 0 deletions

View file

@ -704,6 +704,36 @@ struct rtmsg
uint32_t rtm_flags;
};
/* Structures used in prefix information. */
struct prefixmsg
{
uint8_t prefix_family;
uint8_t prefix_pad1;
uint16_t prefix_pad2;
int32_t prefix_ifindex;
uint8_t prefix_type;
uint8_t prefix_len;
uint8_t prefix_flags;
uint8_t prefix_pad3;
};
enum
{
PREFIX_UNSPEC,
PREFIX_ADDRESS,
PREFIX_CACHEINFO,
__PREFIX_MAX
};
#define PREFIX_MAX (__PREFIX_MAX - 1)
struct prefix_cacheinfo
{
uint32_t preferred_time;
uint32_t valid_time;
};
/* <------- NLA_HDRLEN ------> <-- NLA_ALIGN(payload)-->
* +---------------------+- - -+- - - - - - - - - -+- - -+
* | Header | Pad | Payload | Pad |

View file

@ -36,6 +36,7 @@
#include <nuttx/net/dns.h>
#include "devif/devif.h"
#include "netlink/netlink.h"
#include "neighbor/neighbor.h"
#include "utils/utils.h"
#include "icmpv6/icmpv6.h"
@ -450,6 +451,8 @@ void icmpv6_input(FAR struct net_driver_s *dev, unsigned int iplen)
{
icmpv6_setaddresses(dev, ipv6->srcipaddr,
prefixopt->prefix, prefixopt->preflen);
netlink_ipv6_prefix_notify(dev, RTM_NEWPREFIX,
prefixopt);
}
/* Notify any waiting threads */

View file

@ -116,6 +116,12 @@ config NETLINK_VALIDATE_POLICY
VALIDATE_POLICY is used to make sure the parameters
you pass in are valid.
config NETLINK_DISABLE_NEWPREFIX
bool "Disable RTM_NEWPREFIX support"
default n
---help---
RTM_NEWPREFIX is used to set netdev prefix.
endif # NETLINK_ROUTE
config NETLINK_NETFILTER

View file

@ -32,6 +32,7 @@
#include <netpacket/netlink.h>
#include <nuttx/queue.h>
#include <nuttx/net/icmpv6.h>
#include <nuttx/net/netlink.h>
#include <nuttx/semaphore.h>
#include <nuttx/wqueue.h>
@ -48,6 +49,7 @@
# define netlink_device_notify_ipaddr(dev, type, domain, addr, preflen)
# define netlink_route_notify(route, type, domain)
# define netlink_neigh_notify(neigh, type, domain)
# define netlink_ipv6_prefix_notify(dev, type, pinfo)
#endif
#ifdef CONFIG_NET_NETLINK
@ -552,6 +554,21 @@ void netlink_route_notify(FAR const void *route, int type, int domain);
void netlink_neigh_notify(FAR const void *neigh, int type, int domain);
#endif
/****************************************************************************
* Name: netlink_ipv6_prefix_notify()
*
* Description:
* Perform the RA prefix for the NETLINK_ROUTE protocol.
*
****************************************************************************/
#if defined(CONFIG_NETLINK_DISABLE_NEWPREFIX) || !defined(CONFIG_NET_IPV6)
# define netlink_ipv6_prefix_notify(dev, type, pinfo)
#else
void netlink_ipv6_prefix_notify(FAR struct net_driver_s *dev, int type,
FAR const struct icmpv6_prefixinfo_s *pinfo);
#endif
/****************************************************************************
* Name: nla_next
*

View file

@ -29,6 +29,7 @@
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <arpa/inet.h>
#include <net/route.h>
#include <netpacket/netlink.h>
@ -179,6 +180,32 @@ struct getaddr_recvfrom_rsplist_s
struct getaddr_recvfrom_response_s payload;
};
struct getprefix_recvfrom_addr_s
{
struct rtattr attr;
net_ipv6addr_t addr;
};
struct getprefix_recvfrom_cache_s
{
struct rtattr attr;
struct prefix_cacheinfo pci;
};
struct getprefix_recvfrom_response_s
{
struct nlmsghdr hdr;
struct prefixmsg pmsg;
struct getprefix_recvfrom_addr_s prefix;
struct getprefix_recvfrom_cache_s pci;
};
struct getprefix_recvfrom_rsplist_s
{
sq_entry_t flink;
struct getprefix_recvfrom_response_s payload;
};
/* netdev_foreach() callback */
struct nlroute_sendto_request_s
@ -1249,6 +1276,58 @@ static int netlink_get_addr(NETLINK_HANDLE handle,
}
#endif
#if !defined(CONFIG_NETLINK_DISABLE_NEWADDR) && defined(CONFIG_NET_IPV6)
static FAR struct netlink_response_s *
netlink_fill_ipv6prefix(FAR struct net_driver_s *dev, int type,
FAR const struct icmpv6_prefixinfo_s *pinfo)
{
FAR struct getprefix_recvfrom_rsplist_s *alloc;
FAR struct getprefix_recvfrom_response_s *resp;
DEBUGASSERT(dev != NULL && pinfo != NULL);
alloc = kmm_zalloc(sizeof(struct getprefix_recvfrom_rsplist_s));
if (alloc == NULL)
{
nerr("ERROR: Failed to allocate response buffer.\n");
return NULL;
}
/* Initialize the response buffer */
resp = &alloc->payload;
resp->hdr.nlmsg_len = sizeof(struct getprefix_recvfrom_response_s);
resp->hdr.nlmsg_type = type;
resp->hdr.nlmsg_flags = 0;
resp->hdr.nlmsg_seq = 0;
resp->hdr.nlmsg_pid = 0;
resp->pmsg.prefix_family = AF_INET6;
#ifdef CONFIG_NETDEV_IFINDEX
resp->pmsg.prefix_ifindex = dev->d_ifindex;
#endif
resp->pmsg.prefix_len = pinfo->optlen;
resp->pmsg.prefix_type = pinfo->opttype;
resp->prefix.attr.rta_len = RTA_LENGTH(sizeof(net_ipv6addr_t));
resp->prefix.attr.rta_type = PREFIX_ADDRESS;
net_ipv6addr_copy(resp->prefix.addr, pinfo->prefix);
resp->pci.attr.rta_len = RTA_LENGTH(sizeof(struct prefix_cacheinfo));
resp->pci.attr.rta_type = PREFIX_CACHEINFO;
resp->pci.pci.preferred_time = NTOHS(pinfo->plifetime[0]) << 16;
resp->pci.pci.preferred_time |= NTOHS(pinfo->plifetime[1]);
resp->pci.pci.valid_time = NTOHS(pinfo->vlifetime[0]) << 16;
resp->pci.pci.valid_time |= NTOHS(pinfo->vlifetime[1]);
/* Finally, return the response */
return (FAR struct netlink_response_s *)alloc;
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@ -1582,4 +1661,29 @@ void netlink_neigh_notify(FAR const void *neigh, int type, int domain)
}
#endif
/****************************************************************************
* Name: netlink_ipv6_prefix_notify()
*
* Description:
* Perform the RA prefix for the NETLINK_ROUTE protocol.
*
****************************************************************************/
#if !defined(CONFIG_NETLINK_DISABLE_NEWADDR) && defined(CONFIG_NET_IPV6)
void netlink_ipv6_prefix_notify(FAR struct net_driver_s *dev, int type,
FAR const struct icmpv6_prefixinfo_s *pinfo)
{
FAR struct netlink_response_s *resp;
resp = netlink_fill_ipv6prefix(dev, type, pinfo);
if (resp == NULL)
{
return;
}
netlink_add_broadcast(RTNLGRP_IPV6_PREFIX, resp);
netlink_add_terminator(NULL, NULL, RTNLGRP_IPV6_PREFIX);
}
#endif
#endif /* CONFIG_NETLINK_ROUTE */