summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2022-07-13 16:24:05 +0200
committerThomas Haller <thaller@redhat.com>2022-07-20 10:25:47 +0200
commit1a0c8772b0d9bfce14e8f1bd8d290d00d824dbb5 (patch)
tree54f0c9180ffc1865624fc1ad7f474f18585d1c73
parentbe4b775585a7cddf0a35edacbe04be591dfde4e9 (diff)
downloadNetworkManager-1a0c8772b0d9bfce14e8f1bd8d290d00d824dbb5.tar.gz
platform: add NMPlatformMptcpAddr object
An NMPObject is hashable, can be compared and printed. That is useful. Make an NMPObject for MPTCP addresses. It will hold the content of MPTCP_PM_ATTR_ADDR netlink attribute. But like other NMPObject types it will also be used to represent the data as NetworkManager tracks it.
-rw-r--r--src/libnm-platform/nm-linux-platform.c9
-rw-r--r--src/libnm-platform/nm-platform.c87
-rw-r--r--src/libnm-platform/nm-platform.h36
-rw-r--r--src/libnm-platform/nmp-base.h2
-rw-r--r--src/libnm-platform/nmp-object.c54
-rw-r--r--src/libnm-platform/nmp-object.h11
6 files changed, 195 insertions, 4 deletions
diff --git a/src/libnm-platform/nm-linux-platform.c b/src/libnm-platform/nm-linux-platform.c
index 3c873c9ea7..01505c5b82 100644
--- a/src/libnm-platform/nm-linux-platform.c
+++ b/src/libnm-platform/nm-linux-platform.c
@@ -23,6 +23,7 @@
#include <linux/if_vlan.h>
#include <linux/ip6_tunnel.h>
#include <linux/tc_act/tc_mirred.h>
+#include <linux-headers/mptcp.h>
#include <netinet/icmp6.h>
#include <netinet/in.h>
#include <net/if_arp.h>
@@ -50,6 +51,14 @@
/*****************************************************************************/
+G_STATIC_ASSERT(NM_MPTCP_PM_ADDR_FLAG_SIGNAL == MPTCP_PM_ADDR_FLAG_SIGNAL);
+G_STATIC_ASSERT(NM_MPTCP_PM_ADDR_FLAG_SUBFLOW == MPTCP_PM_ADDR_FLAG_SUBFLOW);
+G_STATIC_ASSERT(NM_MPTCP_PM_ADDR_FLAG_BACKUP == MPTCP_PM_ADDR_FLAG_BACKUP);
+G_STATIC_ASSERT(NM_MPTCP_PM_ADDR_FLAG_FULLMESH == MPTCP_PM_ADDR_FLAG_FULLMESH);
+G_STATIC_ASSERT(NM_MPTCP_PM_ADDR_FLAG_IMPLICIT == MPTCP_PM_ADDR_FLAG_IMPLICIT);
+
+/*****************************************************************************/
+
/* re-implement <linux/tc_act/tc_defact.h> to build against kernel
* headers that lack this. */
diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c
index 961c617cc6..bfe80c0d4c 100644
--- a/src/libnm-platform/nm-platform.c
+++ b/src/libnm-platform/nm-platform.c
@@ -7586,6 +7586,93 @@ nm_platform_tfilter_cmp(const NMPlatformTfilter *a, const NMPlatformTfilter *b)
return 0;
}
+static NM_UTILS_FLAGS2STR_DEFINE(_mptcp_flags_to_string,
+ guint32,
+ NM_UTILS_FLAGS2STR(NM_MPTCP_PM_ADDR_FLAG_SIGNAL, "signal"),
+ NM_UTILS_FLAGS2STR(NM_MPTCP_PM_ADDR_FLAG_SUBFLOW, "subflow"),
+ NM_UTILS_FLAGS2STR(NM_MPTCP_PM_ADDR_FLAG_BACKUP, "backup"),
+ NM_UTILS_FLAGS2STR(NM_MPTCP_PM_ADDR_FLAG_FULLMESH, "fullmesh"));
+
+const char *
+nm_platform_mptcp_addr_to_string(const NMPlatformMptcpAddr *mptcp_addr, char *buf, gsize len)
+{
+ char str_addr[30 + NM_UTILS_INET_ADDRSTRLEN];
+ char str_port[30];
+ char str_id[30];
+ char str_flags[200];
+ char str_flags2[30 + sizeof(str_flags)];
+ char str_ifindex[30];
+
+ if (!nm_utils_to_string_buffer_init_null(mptcp_addr, &buf, &len))
+ return buf;
+
+ if (mptcp_addr->addr_family == 0)
+ nm_sprintf_buf(str_addr, "no-addr");
+ else if (NM_IN_SET(mptcp_addr->addr_family, AF_INET, AF_INET6))
+ nm_utils_inet_ntop(mptcp_addr->addr_family, &mptcp_addr->addr, str_addr);
+ else
+ nm_sprintf_buf(str_addr, "af %d", mptcp_addr->addr_family);
+
+ if (mptcp_addr->flags != 0)
+ _mptcp_flags_to_string(mptcp_addr->flags, str_flags, sizeof(str_flags));
+ else
+ str_flags[0] = '\0';
+
+ g_snprintf(buf,
+ len,
+ "%s" /* in_kernel */
+ "%s" /* address */
+ "%s" /* port */
+ "%s" /* id */
+ "%s" /* flags */
+ "%s" /* ifindex */
+ "",
+ mptcp_addr->in_kernel ? "" : "[nm] ",
+ str_addr,
+ mptcp_addr->port == 0 ? "" : nm_sprintf_buf(str_port, " port %u", mptcp_addr->port),
+ mptcp_addr->id == 0 ? "" : nm_sprintf_buf(str_id, " id %u", mptcp_addr->id),
+ str_flags[0] == '\0' ? "" : nm_sprintf_buf(str_flags2, " flags %s", str_flags),
+ mptcp_addr->ifindex == 0
+ ? ""
+ : nm_sprintf_buf(str_ifindex, " ifindex %d", mptcp_addr->ifindex));
+ return buf;
+}
+
+void
+nm_platform_mptcp_addr_hash_update(const NMPlatformMptcpAddr *obj, NMHashState *h)
+{
+ nm_assert(obj);
+ nm_assert_addr_family_or_unspec(obj->addr_family);
+
+ nm_hash_update_vals(h,
+ obj->id,
+ obj->flags,
+ obj->port,
+ obj->addr_family,
+ (bool) obj->in_kernel,
+ obj->ifindex);
+ if (NM_IN_SET(obj->addr_family, AF_INET, AF_INET6))
+ nm_hash_update(h, &obj->addr, nm_utils_addr_family_to_size(obj->addr_family));
+}
+
+int
+nm_platform_mptcp_addr_cmp(const NMPlatformMptcpAddr *a, const NMPlatformMptcpAddr *b)
+{
+ NM_CMP_SELF(a, b);
+
+ nm_assert_addr_family_or_unspec(a->addr_family);
+ nm_assert_addr_family_or_unspec(b->addr_family);
+
+ NM_CMP_FIELD(a, b, id);
+ NM_CMP_FIELD_UNSAFE(a, b, in_kernel);
+ NM_CMP_FIELD(a, b, addr_family);
+ if (NM_IN_SET(a->addr_family, AF_INET, AF_INET6))
+ NM_CMP_FIELD_MEMCMP_LEN(a, b, addr, nm_utils_addr_family_to_size(a->addr_family));
+ NM_CMP_FIELD(a, b, ifindex);
+
+ return 0;
+}
+
const char *
nm_platform_vf_to_string(const NMPlatformVF *vf, char *buf, gsize len)
{
diff --git a/src/libnm-platform/nm-platform.h b/src/libnm-platform/nm-platform.h
index 984ad79cba..19b00c961d 100644
--- a/src/libnm-platform/nm-platform.h
+++ b/src/libnm-platform/nm-platform.h
@@ -61,6 +61,12 @@ typedef gboolean (*NMPObjectPredicateFunc)(const NMPObject *obj, gpointer user_d
#define NM_IFF_MULTI_QUEUE 0x0100 /* IFF_MULTI_QUEUE */
+#define NM_MPTCP_PM_ADDR_FLAG_SIGNAL ((guint32) (1 << 0))
+#define NM_MPTCP_PM_ADDR_FLAG_SUBFLOW ((guint32) (1 << 1))
+#define NM_MPTCP_PM_ADDR_FLAG_BACKUP ((guint32) (1 << 2))
+#define NM_MPTCP_PM_ADDR_FLAG_FULLMESH ((guint32) (1 << 3))
+#define NM_MPTCP_PM_ADDR_FLAG_IMPLICIT ((guint32) (1 << 4))
+
/* Redefine this in host's endianness */
#define NM_GRE_KEY 0x2000
@@ -782,8 +788,6 @@ typedef struct {
NMPlatformAction action;
} NMPlatformTfilter;
-#undef __NMPlatformObjWithIfindex_COMMON
-
typedef struct {
bool is_ip4;
NMPObjectType obj_type;
@@ -1045,6 +1049,27 @@ typedef enum {
typedef void (*NMPlatformAsyncCallback)(GError *error, gpointer user_data);
+typedef struct {
+ __NMPlatformObjWithIfindex_COMMON;
+
+ guint32 id;
+ guint32 flags;
+ guint16 port;
+ NMIPAddr addr;
+ gint8 addr_family;
+
+ /* If TRUE, then the instance was received by kernel and is inside NMPlatform
+ * cache. In that case, the "id" is set and acts as primary key for the instance.
+ *
+ * If FALSE, this instance is not yet configured in kernel. In this case,
+ * the tuple (id, addr_family, addr) is the primary key of the instance.
+ * This way, we can track mptcp addresses in NetworkManager internally,
+ * before configuring them in kernel. */
+ bool in_kernel : 1;
+} NMPlatformMptcpAddr;
+
+#undef __NMPlatformObjWithIfindex_COMMON
+
/*****************************************************************************/
typedef struct _NMPlatformCsmeConnInfo {
@@ -2355,6 +2380,9 @@ const char *nm_platform_vlan_qos_mapping_to_string(const char *name,
const char *
nm_platform_wireguard_peer_to_string(const struct _NMPWireGuardPeer *peer, char *buf, gsize len);
+const char *
+nm_platform_mptcp_addr_to_string(const NMPlatformMptcpAddr *mptcp_addr, char *buf, gsize len);
+
int nm_platform_link_cmp(const NMPlatformLink *a, const NMPlatformLink *b);
int nm_platform_lnk_bridge_cmp(const NMPlatformLnkBridge *a, const NMPlatformLnkBridge *b);
int nm_platform_lnk_gre_cmp(const NMPlatformLnkGre *a, const NMPlatformLnkGre *b);
@@ -2433,6 +2461,8 @@ int nm_platform_qdisc_cmp_full(const NMPlatformQdisc *a,
gboolean compare_handle);
int nm_platform_tfilter_cmp(const NMPlatformTfilter *a, const NMPlatformTfilter *b);
+int nm_platform_mptcp_addr_cmp(const NMPlatformMptcpAddr *a, const NMPlatformMptcpAddr *b);
+
void nm_platform_link_hash_update(const NMPlatformLink *obj, NMHashState *h);
void nm_platform_ip4_address_hash_update(const NMPlatformIP4Address *obj, NMHashState *h);
void nm_platform_ip6_address_hash_update(const NMPlatformIP6Address *obj, NMHashState *h);
@@ -2462,6 +2492,8 @@ void nm_platform_lnk_wireguard_hash_update(const NMPlatformLnkWireGuard *obj, NM
void nm_platform_qdisc_hash_update(const NMPlatformQdisc *obj, NMHashState *h);
void nm_platform_tfilter_hash_update(const NMPlatformTfilter *obj, NMHashState *h);
+void nm_platform_mptcp_addr_hash_update(const NMPlatformMptcpAddr *obj, NMHashState *h);
+
#define NM_PLATFORM_LINK_FLAGS2STR_MAX_LEN ((gsize) 162)
const char *nm_platform_link_flags2str(unsigned flags, char *buf, gsize len);
diff --git a/src/libnm-platform/nmp-base.h b/src/libnm-platform/nmp-base.h
index 4863168855..02420ebf4b 100644
--- a/src/libnm-platform/nmp-base.h
+++ b/src/libnm-platform/nmp-base.h
@@ -148,6 +148,8 @@ typedef enum _nm_packed {
NMP_OBJECT_TYPE_LNK_VXLAN,
NMP_OBJECT_TYPE_LNK_WIREGUARD,
+ NMP_OBJECT_TYPE_MPTCP_ADDR,
+
__NMP_OBJECT_TYPE_LAST,
NMP_OBJECT_TYPE_MAX = __NMP_OBJECT_TYPE_LAST - 1,
} NMPObjectType;
diff --git a/src/libnm-platform/nmp-object.c b/src/libnm-platform/nmp-object.c
index d281cc7be0..eb5306a66d 100644
--- a/src/libnm-platform/nmp-object.c
+++ b/src/libnm-platform/nmp-object.c
@@ -381,7 +381,8 @@ _idx_obj_part(const DedupMultiIdxType *idx_type,
NMP_OBJECT_TYPE_IP4_ROUTE,
NMP_OBJECT_TYPE_IP6_ROUTE,
NMP_OBJECT_TYPE_QDISC,
- NMP_OBJECT_TYPE_TFILTER)
+ NMP_OBJECT_TYPE_TFILTER,
+ NMP_OBJECT_TYPE_MPTCP_ADDR)
|| !nmp_object_is_visible(obj_a)) {
if (h)
nm_hash_update_val(h, obj_a);
@@ -1551,6 +1552,21 @@ _vt_cmd_plobj_id_cmp_routing_rule(const NMPlatformObject *obj1, const NMPlatform
NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID);
}
+_vt_cmd_plobj_id_cmp(mptcp_addr, NMPlatformMptcpAddr, {
+ NM_CMP_FIELD(obj1, obj2, id);
+ NM_CMP_FIELD_UNSAFE(obj1, obj2, in_kernel);
+ if (!obj1->in_kernel) {
+ /* See comment NMPlatformMptcpAddr.in_kernel for why. */
+ NM_CMP_FIELD(obj1, obj2, addr_family);
+
+ /* nm_utils_addr_family_to_size() asserts that addr-family is either AF_INET or AF_INET6.
+ * This means, we cannot compare totally bogus objects. That is in particular fine
+ * for instances which are not "in_kernel". While we might receive unexpected values
+ * from kernel, we should not create them for internal purposes. */
+ NM_CMP_FIELD_MEMCMP_LEN(obj1, obj2, addr, nm_utils_addr_family_to_size(obj1->addr_family));
+ }
+});
+
void
nmp_object_id_hash_update(const NMPObject *obj, NMHashState *h)
{
@@ -1636,6 +1652,16 @@ _vt_cmd_plobj_id_hash_update(tfilter, NMPlatformTfilter, {
nm_hash_update_vals(h, obj->ifindex, obj->handle);
});
+_vt_cmd_plobj_id_hash_update(mptcp_addr, NMPlatformMptcpAddr, {
+ if (obj->in_kernel) {
+ nm_hash_update_val(h, obj->id);
+ } else {
+ /* _vt_cmd_plobj_id_cmp_mptcp_addr for why. */
+ nm_hash_update_vals(h, obj->id, obj->addr_family);
+ nm_hash_update(h, &obj->addr, nm_utils_addr_family_to_size(obj->addr_family));
+ }
+});
+
static void
_vt_cmd_plobj_hash_update_ip4_route(const NMPlatformObject *obj, NMHashState *h)
{
@@ -1744,6 +1770,12 @@ _vt_cmd_obj_is_alive_tfilter(const NMPObject *obj)
return NMP_OBJECT_CAST_TFILTER(obj)->ifindex > 0;
}
+static gboolean
+_vt_cmd_obj_is_alive_mptcp_addr(const NMPObject *obj)
+{
+ return NM_IN_SET(obj->mptcp_addr.addr_family, AF_INET, AF_INET6);
+}
+
gboolean
nmp_object_is_visible(const NMPObject *obj)
{
@@ -2089,6 +2121,7 @@ nmp_lookup_init_obj_type(NMPLookup *lookup, NMPObjectType obj_type)
case NMP_OBJECT_TYPE_ROUTING_RULE:
case NMP_OBJECT_TYPE_QDISC:
case NMP_OBJECT_TYPE_TFILTER:
+ case NMP_OBJECT_TYPE_MPTCP_ADDR:
_nmp_object_stackinit_from_type(&lookup->selector_obj, obj_type);
lookup->cache_id_type = NMP_CACHE_ID_TYPE_OBJECT_TYPE;
return _L(lookup);
@@ -2123,7 +2156,8 @@ nmp_lookup_init_object_by_ifindex(NMPLookup *lookup, NMPObjectType obj_type, int
NMP_OBJECT_TYPE_IP4_ROUTE,
NMP_OBJECT_TYPE_IP6_ROUTE,
NMP_OBJECT_TYPE_QDISC,
- NMP_OBJECT_TYPE_TFILTER));
+ NMP_OBJECT_TYPE_TFILTER,
+ NMP_OBJECT_TYPE_MPTCP_ADDR));
nm_assert(ifindex > 0
|| (ifindex == 0
&& NM_IN_SET(obj_type, NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE)));
@@ -3463,4 +3497,20 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
.cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_lnk_wireguard_hash_update,
.cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_lnk_wireguard_cmp,
},
+ [NMP_OBJECT_TYPE_MPTCP_ADDR - 1] =
+ {
+ .parent = DEDUP_MULTI_OBJ_CLASS_INIT(),
+ .obj_type = NMP_OBJECT_TYPE_MPTCP_ADDR,
+ .sizeof_data = sizeof(NMPObjectMptcpAddr),
+ .sizeof_public = sizeof(NMPlatformMptcpAddr),
+ .obj_type_name = "mptcp-addr",
+ .supported_cache_ids = _supported_cache_ids_object,
+ .cmd_obj_is_alive = _vt_cmd_obj_is_alive_mptcp_addr,
+ .cmd_plobj_id_cmp = _vt_cmd_plobj_id_cmp_mptcp_addr,
+ .cmd_plobj_id_hash_update = _vt_cmd_plobj_id_hash_update_mptcp_addr,
+ .cmd_plobj_to_string_id = (CmdPlobjToStringIdFunc) nm_platform_mptcp_addr_to_string,
+ .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_mptcp_addr_to_string,
+ .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_mptcp_addr_hash_update,
+ .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_mptcp_addr_cmp,
+ },
};
diff --git a/src/libnm-platform/nmp-object.h b/src/libnm-platform/nmp-object.h
index 7d2ebf979a..5b789404a4 100644
--- a/src/libnm-platform/nmp-object.h
+++ b/src/libnm-platform/nmp-object.h
@@ -331,6 +331,10 @@ typedef struct {
NMPlatformTfilter _public;
} NMPObjectTfilter;
+typedef struct {
+ NMPlatformMptcpAddr _public;
+} NMPObjectMptcpAddr;
+
struct _NMPObject {
union {
NMDedupMultiObj parent;
@@ -404,6 +408,9 @@ struct _NMPObject {
NMPObjectQdisc _qdisc;
NMPlatformTfilter tfilter;
NMPObjectTfilter _tfilter;
+
+ NMPlatformMptcpAddr mptcp_addr;
+ NMPObjectMptcpAddr _mptcp_addr;
};
};
@@ -504,6 +511,8 @@ _NMP_OBJECT_TYPE_IS_OBJ_WITH_IFINDEX(NMPObjectType obj_type)
case NMP_OBJECT_TYPE_LNK_VRF:
case NMP_OBJECT_TYPE_LNK_VXLAN:
case NMP_OBJECT_TYPE_LNK_WIREGUARD:
+
+ case NMP_OBJECT_TYPE_MPTCP_ADDR:
return TRUE;
case NMP_OBJECT_TYPE_ROUTING_RULE:
@@ -565,6 +574,8 @@ _NMP_OBJECT_TYPE_IS_OBJ_WITH_IFINDEX(NMPObjectType obj_type)
_NMP_OBJECT_CAST(obj, lnk_wireguard, NMP_OBJECT_TYPE_LNK_WIREGUARD)
#define NMP_OBJECT_CAST_LNK_BRIDGE(obj) \
_NMP_OBJECT_CAST(obj, lnk_bridge, NMP_OBJECT_TYPE_LNK_BRIDGE)
+#define NMP_OBJECT_CAST_MPTCP_ADDR(obj) \
+ _NMP_OBJECT_CAST(obj, mptcp_addr, NMP_OBJECT_TYPE_MPTCP_ADDR)
static inline int
NMP_OBJECT_TYPE_TO_ADDR_FAMILY(NMPObjectType obj_type)