platform: parse netlink messages ourselves without libnl-route-3
Constructing the libnl3 object only to parse the message is wasteful. It involves several memory allocations, thread synchronization and parsing fields that we don't care about. But moreover, older libnl version might not support all the fields we are interested in, hence we have workarounds like _nl_link_parse_info_data(). Certain features might not fully work unless libnl supports it too (although kernel would). As we already parse the data ourselves sometimes, just go all they way and don't construct the intermediate libnl object. This will allow us to drop the _nl_link_parse_info_data() workarounds in next commits. That is important, because _nl_link_parse_info_data() sidesteps our platform cache and is not in sync with the cache (not to mention the extra work to explicitly refetch the data on every lookup). Also, it gets us 60% on the way to no longer needing 'libnl-route-3.so' at all and eventually drop requiring the library.
This commit is contained in:
17
configure.ac
17
configure.ac
@@ -534,23 +534,6 @@ AC_CHECK_LIB([nl-route-3], [rtnl_link_inet6_get_addr_gen_mode],
|
||||
AC_DEFINE_UNQUOTED(HAVE_LIBNL_INET6_ADDR_GEN_MODE,
|
||||
$ac_have_addr_gen_mode, [Define if libnl has rtnl_link_inet6_get_addr_gen_mode()])
|
||||
|
||||
AC_MSG_CHECKING([Linux kernel IN6_ADDR_GEN_MODE enum])
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[#ifndef __user
|
||||
#define __user
|
||||
#endif
|
||||
#include <linux/if_link.h>]],
|
||||
[[int a = IN6_ADDR_GEN_MODE_EUI64; a++;]])],
|
||||
[ac_have_kernel_gen_mode=yes],
|
||||
[ac_have_kernel_gen_mode=no])
|
||||
AC_MSG_RESULT($ac_have_kernel_gen_mode)
|
||||
if test "$ac_have_kernel_gen_mode" = yes; then
|
||||
AC_DEFINE(HAVE_KERNEL_INET6_ADDR_GEN_MODE, 1, [Define if the kernel has IN6_ADDR_GEN_MODE_*])
|
||||
else
|
||||
AC_DEFINE(HAVE_KERNEL_INET6_ADDR_GEN_MODE, 0, [Define if the kernel has IN6_ADDR_GEN_MODE_*])
|
||||
fi
|
||||
|
||||
# IPv6 tokenized identifiers support in libnl
|
||||
AC_CHECK_LIB([nl-route-3], [rtnl_link_inet6_get_token],
|
||||
ac_have_ipv6_token="1",
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -454,8 +454,7 @@ nm_platform_link_get_all (NMPlatform *self)
|
||||
if (item->parent != NM_PLATFORM_LINK_OTHER_NETNS) {
|
||||
g_warn_if_fail (item->parent > 0);
|
||||
g_warn_if_fail (item->parent != item->ifindex);
|
||||
g_warn_if_fail ( !nm_platform_check_support_libnl_link_netnsid ()
|
||||
|| g_hash_table_contains (unseen, GINT_TO_POINTER (item->parent)));
|
||||
g_warn_if_fail (g_hash_table_contains (unseen, GINT_TO_POINTER (item->parent)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -951,23 +950,18 @@ nm_platform_link_get_udev_device (NMPlatform *self, int ifindex)
|
||||
gboolean
|
||||
nm_platform_link_get_user_ipv6ll_enabled (NMPlatform *self, int ifindex)
|
||||
{
|
||||
const NMPlatformLink *pllink;
|
||||
|
||||
_CHECK_SELF (self, klass, FALSE);
|
||||
|
||||
g_return_val_if_fail (ifindex >= 0, FALSE);
|
||||
|
||||
#if HAVE_LIBNL_INET6_ADDR_GEN_MODE && HAVE_KERNEL_INET6_ADDR_GEN_MODE
|
||||
{
|
||||
const NMPlatformLink *pllink;
|
||||
|
||||
pllink = nm_platform_link_get (self, ifindex);
|
||||
if (pllink && pllink->inet6_addr_gen_mode_inv)
|
||||
return _nm_platform_uint8_inv (pllink->inet6_addr_gen_mode_inv) == IN6_ADDR_GEN_MODE_NONE;
|
||||
}
|
||||
#endif
|
||||
return _nm_platform_uint8_inv (pllink->inet6_addr_gen_mode_inv) == NM_IN6_ADDR_GEN_MODE_NONE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* nm_platform_link_set_user_ip6vll_enabled:
|
||||
* @self: platform instance
|
||||
|
@@ -52,6 +52,13 @@ typedef struct _NMPlatform NMPlatform;
|
||||
#define IFA_F_NOPREFIXROUTE 0x200
|
||||
#endif
|
||||
|
||||
/* Define of the IN6_ADDR_GEN_MODE_* values to workaround old kernel headers
|
||||
* that don't define it. */
|
||||
#define NM_IN6_ADDR_GEN_MODE_UNKNOWN 255 /* no corresponding value. */
|
||||
#define NM_IN6_ADDR_GEN_MODE_EUI64 0 /* IN6_ADDR_GEN_MODE_EUI64 */
|
||||
#define NM_IN6_ADDR_GEN_MODE_NONE 1 /* IN6_ADDR_GEN_MODE_NONE */
|
||||
#define NM_IN6_ADDR_GEN_MODE_STABLE_PRIVACY 2 /* IN6_ADDR_GEN_MODE_STABLE_PRIVACY */
|
||||
|
||||
typedef enum { /*< skip >*/
|
||||
|
||||
/* dummy value, to enforce that the enum type is signed and has a size
|
||||
@@ -771,7 +778,6 @@ int nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4R
|
||||
int nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route *b);
|
||||
|
||||
gboolean nm_platform_check_support_libnl_extended_ifa_flags (void);
|
||||
gboolean nm_platform_check_support_libnl_link_netnsid (void);
|
||||
gboolean nm_platform_check_support_kernel_extended_ifa_flags (NMPlatform *self);
|
||||
gboolean nm_platform_check_support_user_ipv6ll (NMPlatform *self);
|
||||
|
||||
|
@@ -82,6 +82,8 @@ _id_hash_ip6_addr (const struct in6_addr *addr)
|
||||
return hash;
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
|
||||
static const char *
|
||||
_link_get_driver (GUdevDevice *udev_device, const char *kind, const char *ifname)
|
||||
{
|
||||
@@ -796,38 +798,6 @@ _vt_cmd_obj_is_visible_ipx_route (const NMPObject *obj)
|
||||
|
||||
/******************************************************************/
|
||||
|
||||
/**
|
||||
* nmp_object_from_nl:
|
||||
* @platform: platform instance (needed to lookup sysctl)
|
||||
* @nlo:
|
||||
* @id_only: if %TRUE, only fill the id fields of the object and leave the
|
||||
* other fields unset. This is useful to create a needle to lookup a matching
|
||||
* item in the cache.
|
||||
* @complete_from_cache: sometimes the netlink object doesn't contain all information.
|
||||
* If true, look them up in the cache and preserve the original value.
|
||||
*
|
||||
* Convert a libnl object to a platform object.
|
||||
* Returns: a NMPObject containing @nlo. If @id_only is %TRUE, only the id fields
|
||||
* are defined.
|
||||
**/
|
||||
NMPObject *
|
||||
nmp_object_from_nl (NMPlatform *platform, const struct nl_object *nlo, gboolean id_only, gboolean complete_from_cache)
|
||||
{
|
||||
NMPObjectType obj_type = _nlo_get_object_type (nlo);
|
||||
NMPObject *obj;
|
||||
|
||||
if (obj_type == NMP_OBJECT_TYPE_UNKNOWN)
|
||||
return NULL;
|
||||
|
||||
obj = nmp_object_new (obj_type, NULL);
|
||||
|
||||
if (!NMP_OBJECT_GET_CLASS (obj)->cmd_plobj_init_from_nl (platform, &obj->object, nlo, id_only, complete_from_cache)) {
|
||||
nmp_object_unref (obj);
|
||||
return NULL;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
struct nl_object *
|
||||
nmp_object_to_nl (NMPlatform *platform, const NMPObject *obj, gboolean id_only)
|
||||
{
|
||||
@@ -1522,8 +1492,8 @@ nmp_cache_update_netlink (NMPCache *cache, NMPObject *obj, NMPObject **out_obj,
|
||||
* We could add efficient reverse lookup by adding a reverse index to NMMultiIndex. But that
|
||||
* also adds some cost to support an (uncommon?) usage pattern.
|
||||
*
|
||||
* Instead we just don't support it. Actually, we expect the user to
|
||||
* create a new instance with nmp_object_from_nl(). That is what nmp_cache_update_netlink().
|
||||
* Instead we just don't support it, instead we expect the user to
|
||||
* create a new instance from netlink.
|
||||
*
|
||||
* TL;DR: a cached object must never be modified.
|
||||
*/
|
||||
@@ -1809,7 +1779,6 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
|
||||
.cmd_obj_dispose = _vt_cmd_obj_dispose_link,
|
||||
.cmd_obj_is_alive = _vt_cmd_obj_is_alive_link,
|
||||
.cmd_obj_is_visible = _vt_cmd_obj_is_visible_link,
|
||||
.cmd_plobj_init_from_nl = _nmp_vt_cmd_plobj_init_from_nl_link,
|
||||
.cmd_plobj_to_nl = _nmp_vt_cmd_plobj_to_nl_link,
|
||||
.cmd_plobj_id_copy = _vt_cmd_plobj_id_copy_link,
|
||||
.cmd_plobj_id_equal = _vt_cmd_plobj_id_equal_link,
|
||||
@@ -1830,7 +1799,6 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
|
||||
.cmd_obj_stackinit_id = _vt_cmd_obj_stackinit_id_ip4_address,
|
||||
.cmd_obj_is_alive = _vt_cmd_obj_is_alive_ipx_address,
|
||||
.cmd_obj_is_visible = _vt_cmd_obj_is_visible_ipx_address,
|
||||
.cmd_plobj_init_from_nl = _nmp_vt_cmd_plobj_init_from_nl_ip4_address,
|
||||
.cmd_plobj_to_nl = _nmp_vt_cmd_plobj_to_nl_ip4_address,
|
||||
.cmd_plobj_id_copy = _vt_cmd_plobj_id_copy_ip4_address,
|
||||
.cmd_plobj_id_equal = _vt_cmd_plobj_id_equal_ip4_address,
|
||||
@@ -1851,7 +1819,6 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
|
||||
.cmd_obj_stackinit_id = _vt_cmd_obj_stackinit_id_ip6_address,
|
||||
.cmd_obj_is_alive = _vt_cmd_obj_is_alive_ipx_address,
|
||||
.cmd_obj_is_visible = _vt_cmd_obj_is_visible_ipx_address,
|
||||
.cmd_plobj_init_from_nl = _nmp_vt_cmd_plobj_init_from_nl_ip6_address,
|
||||
.cmd_plobj_to_nl = _nmp_vt_cmd_plobj_to_nl_ip6_address,
|
||||
.cmd_plobj_id_copy = _vt_cmd_plobj_id_copy_ip6_address,
|
||||
.cmd_plobj_id_equal = _vt_cmd_plobj_id_equal_ip6_address,
|
||||
@@ -1872,7 +1839,6 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
|
||||
.cmd_obj_stackinit_id = _vt_cmd_obj_stackinit_id_ip4_route,
|
||||
.cmd_obj_is_alive = _vt_cmd_obj_is_alive_ipx_route,
|
||||
.cmd_obj_is_visible = _vt_cmd_obj_is_visible_ipx_route,
|
||||
.cmd_plobj_init_from_nl = _nmp_vt_cmd_plobj_init_from_nl_ip4_route,
|
||||
.cmd_plobj_to_nl = _nmp_vt_cmd_plobj_to_nl_ip4_route,
|
||||
.cmd_plobj_id_copy = _vt_cmd_plobj_id_copy_ip4_route,
|
||||
.cmd_plobj_id_equal = _vt_cmd_plobj_id_equal_ip4_route,
|
||||
@@ -1893,7 +1859,6 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
|
||||
.cmd_obj_stackinit_id = _vt_cmd_obj_stackinit_id_ip6_route,
|
||||
.cmd_obj_is_alive = _vt_cmd_obj_is_alive_ipx_route,
|
||||
.cmd_obj_is_visible = _vt_cmd_obj_is_visible_ipx_route,
|
||||
.cmd_plobj_init_from_nl = _nmp_vt_cmd_plobj_init_from_nl_ip6_route,
|
||||
.cmd_plobj_to_nl = _nmp_vt_cmd_plobj_to_nl_ip6_route,
|
||||
.cmd_plobj_id_copy = _vt_cmd_plobj_id_copy_ip6_route,
|
||||
.cmd_plobj_id_equal = _vt_cmd_plobj_id_equal_ip6_route,
|
||||
|
@@ -131,7 +131,6 @@ typedef struct {
|
||||
gboolean (*cmd_obj_is_visible) (const NMPObject *obj);
|
||||
|
||||
/* functions that operate on NMPlatformObject */
|
||||
gboolean (*cmd_plobj_init_from_nl) (NMPlatform *platform, NMPlatformObject *obj, const struct nl_object *nlo, gboolean id_only, gboolean complete_from_cache);
|
||||
struct nl_object *(*cmd_plobj_to_nl) (NMPlatform *platform, const NMPlatformObject *obj, gboolean id_only);
|
||||
void (*cmd_plobj_id_copy) (NMPlatformObject *dst, const NMPlatformObject *src);
|
||||
gboolean (*cmd_plobj_id_equal) (const NMPlatformObject *obj1, const NMPlatformObject *obj2);
|
||||
@@ -340,17 +339,10 @@ NMPCacheOpsType nmp_cache_update_link_master_connected (NMPCache *cache, int ifi
|
||||
NMPCache *nmp_cache_new (void);
|
||||
void nmp_cache_free (NMPCache *cache);
|
||||
|
||||
NMPObject *nmp_object_from_nl (NMPlatform *platform, const struct nl_object *nlo, gboolean id_only, gboolean complete_from_cache);
|
||||
struct nl_object *nmp_object_to_nl (NMPlatform *platform, const NMPObject *obj, gboolean id_only);
|
||||
|
||||
/* the following functions are currently implemented inside nm-linux-platform, because
|
||||
* they depend on utility functions there. */
|
||||
NMPObjectType _nlo_get_object_type (const struct nl_object *nlo);
|
||||
gboolean _nmp_vt_cmd_plobj_init_from_nl_link (NMPlatform *platform, NMPlatformObject *_obj, const struct nl_object *_nlo, gboolean id_only, gboolean complete_from_cache);
|
||||
gboolean _nmp_vt_cmd_plobj_init_from_nl_ip4_address (NMPlatform *platform, NMPlatformObject *_obj, const struct nl_object *_nlo, gboolean id_only, gboolean complete_from_cache);
|
||||
gboolean _nmp_vt_cmd_plobj_init_from_nl_ip6_address (NMPlatform *platform, NMPlatformObject *_obj, const struct nl_object *_nlo, gboolean id_only, gboolean complete_from_cache);
|
||||
gboolean _nmp_vt_cmd_plobj_init_from_nl_ip4_route (NMPlatform *platform, NMPlatformObject *_obj, const struct nl_object *_nlo, gboolean id_only, gboolean complete_from_cache);
|
||||
gboolean _nmp_vt_cmd_plobj_init_from_nl_ip6_route (NMPlatform *platform, NMPlatformObject *_obj, const struct nl_object *_nlo, gboolean id_only, gboolean complete_from_cache);
|
||||
struct nl_object *_nmp_vt_cmd_plobj_to_nl_link (NMPlatform *platform, const NMPlatformObject *_obj, gboolean id_only);
|
||||
struct nl_object *_nmp_vt_cmd_plobj_to_nl_ip4_address (NMPlatform *platform, const NMPlatformObject *_obj, gboolean id_only);
|
||||
struct nl_object *_nmp_vt_cmd_plobj_to_nl_ip6_address (NMPlatform *platform, const NMPlatformObject *_obj, gboolean id_only);
|
||||
|
Reference in New Issue
Block a user