Skip to content

zdtm: add UDP multicast checkpoint/restore test#2897

Open
Piyushkhobragade wants to merge 1 commit intocheckpoint-restore:criu-devfrom
Piyushkhobragade:zdtm-socket-udp-multicast
Open

zdtm: add UDP multicast checkpoint/restore test#2897
Piyushkhobragade wants to merge 1 commit intocheckpoint-restore:criu-devfrom
Piyushkhobragade:zdtm-socket-udp-multicast

Conversation

@Piyushkhobragade
Copy link
Copy Markdown

This PR introduces a deterministic ZDTM test (socket_udp-multicast.c) to exercise UDP multicast group membership (IP_ADD_MEMBERSHIP) across the CRIU checkpoint/restore lifecycle.

Test Design

The test:

  • Creates a UDP socket
  • Joins multicast group 239.0.0.1
  • Binds to a non-loopback IPv4 interface that is IFF_UP
  • Performs dump/restore
  • Verifies multicast functionality after restore via packet transmission

The implementation is intentionally minimal and avoids namespace-specific assumptions.

Observed Behavior

  • Multicast join succeeds before checkpoint

  • criu dump and criu restore both complete successfully

  • After restore, the verification step fails:

    sendto() → ENETUNREACH (Network is unreachable)

The multicast route (224.0.0.0/4) is present and the interface is UP.
No explicit IP_MULTICAST_IF reconfiguration is performed after restore.

This suggests that multicast egress/interface state may not be fully preserved across checkpoint/restore.

Question

Is multicast egress/interface state expected to be restored for UDP sockets?

If this is currently unsupported, I can:

  • Mark the test as expected-fail
  • Adjust the modeling approach
  • Or treat this as a reproducer for missing restoration support

Looking for guidance on the preferred direction.

Add socket_udp-multicast ZDTM test to validate preservation of
IP_ADD_MEMBERSHIP across CRIU dump/restore.

The test joins 239.0.0.1, performs checkpoint/restore, and verifies
post-restore multicast packet transmission.

Current behavior indicates sendto() fails with ENETUNREACH after
restore, suggesting multicast egress state may not be fully restored.
@avagin
Copy link
Copy Markdown
Member

avagin commented Feb 19, 2026

We usually don't add tests for unsupported things. Could you try to investigate what we need to do to support C/R of socket multicast groups.

@Piyushkhobragade
Copy link
Copy Markdown
Author

@avagin I investigated the kernel and CRIU architecture to map out exactly what is missing and what it will take to fully support C/R for socket multicast groups.

The Architectural Blocker

Currently, the Linux kernel does not expose a socket's multicast group memberships (mc_list in struct inet_sock, or ipv6_mc_list in struct ipv6_pinfo) to userspace:

  1. getsockopt() for IP_ADD_MEMBERSHIP is fundamentally write-only.
  2. The sock_diag / inet_diag netlink subsystem does not serialize these linked lists during a socket dump.
  3. /proc/net/igmp maps groups to interfaces but drops the specific socket FD context entirely.

To support this in CRIU, we have to execute a full-stack fix starting upstream:

1. Kernel Patch (netdev)

We need to introduce a new netlink attribute, e.g., INET_DIAG_MCAST_GROUPS, to the inet_diag subsystem. During a udp_diag_dump(), the kernel would iterate over inet->mc_list and export an array containing the multicast addresses and their bound ifindex.

(Alternative Kernel approach): We could theoretically use an eBPF iterator (bpf_iter_udp) during the CRIU dump phase to walk the sockets, match the socket cookie, and extract the mc_list directly. However, extending inet_diag aligns much better with CRIU's existing sk-inet.c netlink parsing logic.

2. CRIU Protobuf Changes

Update images/sk-inet.proto to persist the memberships:

message mcast_group {
    required uint32 family = 1;
    required bytes multiaddr = 2;
    required uint32 ifindex = 3;
}

// Inside inet_sk_entry:
repeated mcast_group mcast_groups = X;

@avagin
Copy link
Copy Markdown
Member

avagin commented Feb 20, 2026

Could you try to implement a socket diag extension to dump multicast groups?

@Piyushkhobragade
Copy link
Copy Markdown
Author

@avagin Absolutely, I will take this on.

Before I start drafting the patch for the upstream netdev mailing list, I want to ensure the UAPI extension perfectly fits CRIU's needs for parsing.

I propose adding a new extension flag, e.g., INET_DIAG_MCAST, to include/uapi/linux/inet_diag.h.

During a udp_diag_dump(), if this flag is requested, the kernel will iterate through inet->mc_list (and ipv6_mc_list) and append a nested netlink attribute containing an array of structures. Something along these lines:

/* In include/uapi/linux/inet_diag.h */
struct inet_diag_mcast_item {
	__u8	family;      /* AF_INET or AF_INET6 */
	__u8	pad[3];
	__u32	ifindex;     /* Interface index bound to */
	__u32	addr[4];     /* Multicast address (up to 128 bits for IPv6) */
};

@avagin
Copy link
Copy Markdown
Member

avagin commented Feb 20, 2026

@avagin Absolutely, I will take this on.

Before I start drafting the patch for the upstream netdev mailing list, I want to ensure the UAPI extension perfectly fits CRIU's needs for parsing.

It is a long way to the netdev mailing list. Let's implement both linux kernel and criu changes. Then we will discuss/review them and only then you will start thinking on sending something to netdev.

I propose adding a new extension flag, e.g., INET_DIAG_MCAST, to include/uapi/linux/inet_diag.h.

During a udp_diag_dump(), if this flag is requested, the kernel will iterate through inet->mc_list (and ipv6_mc_list) and append a nested netlink attribute containing an array of structures. Something along these lines:

/* In include/uapi/linux/inet_diag.h */
struct inet_diag_mcast_item {
	__u8	family;      /* AF_INET or AF_INET6 */
	__u8	pad[3];
	__u32	ifindex;     /* Interface index bound to */
	__u32	addr[4];     /* Multicast address (up to 128 bits for IPv6) */
};

I don't have time right now to deep dive into details. So far it looks okay, we will be able to adjust it later.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants