netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Paolo Abeni <pabeni@redhat.com>
To: John Ousterhout <ouster@cs.stanford.edu>, netdev@vger.kernel.org
Cc: edumazet@google.com, horms@kernel.org, kuba@kernel.org
Subject: Re: [PATCH net-next v15 14/15] net: homa: create homa_plumbing.c
Date: Tue, 26 Aug 2025 18:17:09 +0200	[thread overview]
Message-ID: <a2dec2d0-84be-4a4f-bfd4-b5f56219ac82@redhat.com> (raw)
In-Reply-To: <20250818205551.2082-15-ouster@cs.stanford.edu>

On 8/18/25 10:55 PM, John Ousterhout wrote:
> +/* This variable contains the address of the statically-allocated struct homa
> + * used throughout Homa. This variable should almost never be used directly:
> + * it should be passed as a parameter to functions that need it. This
> + * variable is used only by a few functions called from Linux where there
> + * is no struct homa* available.
> + */
> +static struct homa *global_homa = &homa_data;

No need for this, use hame_data directly everywhere.

> +static struct proto homav6_prot = {
> +	.name		   = "HOMAv6",
> +	.owner		   = THIS_MODULE,
> +	.close		   = homa_close,
> +	.connect	   = ip6_datagram_connect,
> +	.ioctl		   = homa_ioctl,
> +	.init		   = homa_socket,
> +	.destroy	   = homa_sock_destroy,
> +	.setsockopt	   = homa_setsockopt,
> +	.getsockopt	   = homa_getsockopt,
> +	.sendmsg	   = homa_sendmsg,
> +	.recvmsg	   = homa_recvmsg,
> +	.hash		   = homa_hash,
> +	.unhash		   = homa_unhash,
> +	.obj_size	   = sizeof(struct homa_v6_sock),
> +	.ipv6_pinfo_offset = offsetof(struct homa_v6_sock, inet6),
> +
> +	.no_autobind       = 1,

Minor nit: no empty line above

> +};
> +
> +/* Top-level structure describing the Homa protocol. */
> +static struct inet_protosw homa_protosw = {
> +	.type              = SOCK_DGRAM,
> +	.protocol          = IPPROTO_HOMA,
> +	.prot              = &homa_prot,
> +	.ops               = &homa_proto_ops,
> +	.flags             = INET_PROTOSW_REUSE,
> +};
> +
> +static struct inet_protosw homav6_protosw = {
> +	.type              = SOCK_DGRAM,
> +	.protocol          = IPPROTO_HOMA,
> +	.prot              = &homav6_prot,
> +	.ops               = &homav6_proto_ops,
> +	.flags             = INET_PROTOSW_REUSE,
> +};
> +
> +/* This structure is used by IP to deliver incoming Homa packets to us. */
> +static struct net_protocol homa_protocol = {
> +	.handler =	homa_softirq,
> +	.err_handler =	homa_err_handler_v4,
> +	.no_policy =     1,
> +};
> +
> +static struct inet6_protocol homav6_protocol = {
> +	.handler =	homa_softirq,
> +	.err_handler =	homa_err_handler_v6,
> +	.flags =        INET6_PROTO_NOPOLICY | INET6_PROTO_FINAL,
> +};
> +
> +/* Sizes of the headers for each Homa packet type, in bytes. */
> +static u16 header_lengths[] = {
> +	sizeof(struct homa_data_hdr),
> +	0,
> +	sizeof(struct homa_resend_hdr),
> +	sizeof(struct homa_rpc_unknown_hdr),
> +	sizeof(struct homa_busy_hdr),
> +	0,
> +	0,
> +	sizeof(struct homa_need_ack_hdr),
> +	sizeof(struct homa_ack_hdr)
> +};
> +
> +/* Thread that runs timer code to detect lost packets and crashed peers. */
> +static struct task_struct *timer_kthread;
> +static DECLARE_COMPLETION(timer_thread_done);
> +
> +/* Used to wakeup timer_kthread at regular intervals. */
> +static struct hrtimer hrtimer;
> +
> +/* Nonzero is an indication to the timer thread that it should exit. */
> +static int timer_thread_exit;
> +
> +/**
> + * homa_load() - invoked when this module is loaded into the Linux kernel
> + * Return: 0 on success, otherwise a negative errno.
> + */
> +int __init homa_load(void)
> +{
> +	struct homa *homa = global_homa;
> +	bool init_protocol6 = false;
> +	bool init_protosw6 = false;
> +	bool init_protocol = false;
> +	bool init_protosw = false;
> +	bool init_net_ops = false;
> +	bool init_proto6 = false;
> +	bool init_proto = false;
> +	bool init_homa = false;
> +	int status;
> +
> +	/* Compile-time validations that no packet header is longer
> +	 * than HOMA_MAX_HEADER.
> +	 */
> +	BUILD_BUG_ON(sizeof(struct homa_data_hdr) > HOMA_MAX_HEADER);
> +	BUILD_BUG_ON(sizeof(struct homa_resend_hdr) > HOMA_MAX_HEADER);
> +	BUILD_BUG_ON(sizeof(struct homa_rpc_unknown_hdr) > HOMA_MAX_HEADER);
> +	BUILD_BUG_ON(sizeof(struct homa_busy_hdr) > HOMA_MAX_HEADER);
> +	BUILD_BUG_ON(sizeof(struct homa_need_ack_hdr) > HOMA_MAX_HEADER);
> +	BUILD_BUG_ON(sizeof(struct homa_ack_hdr) > HOMA_MAX_HEADER);
> +
> +	/* Extra constraints on data packets:
> +	 * - Ensure minimum header length so Homa doesn't have to worry about
> +	 *   padding data packets.
> +	 * - Make sure data packet headers are a multiple of 4 bytes (needed
> +	 *   for TCP/TSO compatibility).
> +	 */
> +	BUILD_BUG_ON(sizeof(struct homa_data_hdr) < HOMA_MIN_PKT_LENGTH);
> +	BUILD_BUG_ON((sizeof(struct homa_data_hdr) -
> +		      sizeof(struct homa_seg_hdr)) & 0x3);
> +
> +	/* Detect size changes in uAPI structs. */
> +	BUILD_BUG_ON(sizeof(struct homa_sendmsg_args) != 24);
> +	BUILD_BUG_ON(sizeof(struct homa_recvmsg_args) != 88);
> +
> +	pr_err("Homa module loading\n");

Please use pr_notice() instead.

> +	status = proto_register(&homa_prot, 1);
> +	if (status != 0) {
> +		pr_err("proto_register failed for homa_prot: %d\n", status);
> +		goto error;
> +	}
> +	init_proto = true;

The standard way of handling the error paths it to avoid local flags and
use different goto labels.

> +
> +	status = proto_register(&homav6_prot, 1);
> +	if (status != 0) {
> +		pr_err("proto_register failed for homav6_prot: %d\n", status);
> +		goto error;
> +	}
> +	init_proto6 = true;
> +
> +	inet_register_protosw(&homa_protosw);
> +	init_protosw = true;
> +
> +	status = inet6_register_protosw(&homav6_protosw);
> +	if (status != 0) {
> +		pr_err("inet6_register_protosw failed in %s: %d\n", __func__,
> +		       status);
> +		goto error;
> +	}
> +	init_protosw6 = true;
> +
> +	status = inet_add_protocol(&homa_protocol, IPPROTO_HOMA);
> +	if (status != 0) {
> +		pr_err("inet_add_protocol failed in %s: %d\n", __func__,
> +		       status);
> +		goto error;
> +	}
> +	init_protocol = true;
> +
> +	status = inet6_add_protocol(&homav6_protocol, IPPROTO_HOMA);
> +	if (status != 0) {
> +		pr_err("inet6_add_protocol failed in %s: %d\n",  __func__,
> +		       status);
> +		goto error;
> +	}
> +	init_protocol6 = true;
> +
> +	status = homa_init(homa);
> +	if (status)
> +		goto error;
> +	init_homa = true;

home_init() should be likely the first call in this function

> +
> +	status = register_pernet_subsys(&homa_net_ops);
> +	if (status != 0) {
> +		pr_err("Homa got error from register_pernet_subsys: %d\n",
> +		       status);
> +		goto error;
> +	}
> +	init_net_ops = true;
> +
> +	timer_kthread = kthread_run(homa_timer_main, homa, "homa_timer");
> +	if (IS_ERR(timer_kthread)) {
> +		status = PTR_ERR(timer_kthread);
> +		pr_err("couldn't create Homa timer thread: error %d\n",
> +		       status);
> +		timer_kthread = NULL;
> +		goto error;
> +	}
> +
> +	return 0;
> +
> +error:
> +	if (timer_kthread) {
> +		timer_thread_exit = 1;
> +		wake_up_process(timer_kthread);
> +		wait_for_completion(&timer_thread_done);
> +	}
> +	if (init_net_ops)
> +		unregister_pernet_subsys(&homa_net_ops);
> +	if (init_homa)
> +		homa_destroy(homa);
> +	if (init_protocol)
> +		inet_del_protocol(&homa_protocol, IPPROTO_HOMA);
> +	if (init_protocol6)
> +		inet6_del_protocol(&homav6_protocol, IPPROTO_HOMA);
> +	if (init_protosw)
> +		inet_unregister_protosw(&homa_protosw);
> +	if (init_protosw6)
> +		inet6_unregister_protosw(&homav6_protosw);
> +	if (init_proto)
> +		proto_unregister(&homa_prot);
> +	if (init_proto6)
> +		proto_unregister(&homav6_prot);
> +	return status;
> +}
> +
> +/**
> + * homa_unload() - invoked when this module is unloaded from the Linux kernel.
> + */
> +void __exit homa_unload(void)
> +{
> +	struct homa *homa = global_homa;
> +
> +	pr_notice("Homa module unloading\n");
> +
> +	unregister_pernet_subsys(&homa_net_ops);
> +	homa_destroy(homa);

home_destroy() should likely be the last call of this function.

> +/**
> + * homa_softirq() - This function is invoked at SoftIRQ level to handle
> + * incoming packets.
> + * @skb:   The incoming packet.
> + * Return: Always 0
> + */
> +int homa_softirq(struct sk_buff *skb)
> +{
> +	struct sk_buff *packets, *other_pkts, *next;
> +	struct sk_buff **prev_link, **other_link;
> +	struct homa_common_hdr *h;
> +	int header_offset;
> +
> +	/* skb may actually contain many distinct packets, linked through
> +	 * skb_shinfo(skb)->frag_list by the Homa GRO mechanism. Make a
> +	 * pass through the list to process all of the short packets,
> +	 * leaving the longer packets in the list. Also, perform various
> +	 * prep/cleanup/error checking functions.

It's hard to tell without the GRO/GSO code handy, but I guess the
implementation here could be simplified invoking __skb_gso_segment()...

> +	 */
> +	skb->next = skb_shinfo(skb)->frag_list;
> +	skb_shinfo(skb)->frag_list = NULL;
> +	packets = skb;
> +	prev_link = &packets;
> +	for (skb = packets; skb; skb = next) {
> +		next = skb->next;
> +
> +		/* Make the header available at skb->data, even if the packet
> +		 * is fragmented. One complication: it's possible that the IP
> +		 * header hasn't yet been removed (this happens for GRO packets
> +		 * on the frag_list, since they aren't handled explicitly by IP.

... at very least it will avoif this complication and will simplify the
list handling.

> +		 */
> +		if (!homa_make_header_avl(skb))
> +			goto discard;

It looks like the above is too aggressive, i.e. pskb_may_pull() may fail
for a correctly formatted homa_ack_hdr - or any other packet with hdr
size < HOMA_MAX_HEADER

> +		header_offset = skb_transport_header(skb) - skb->data;
> +		if (header_offset)
> +			__skb_pull(skb, header_offset);
> +
> +		/* Reject packets that are too short or have bogus types. */
> +		h = (struct homa_common_hdr *)skb->data;
> +		if (unlikely(skb->len < sizeof(struct homa_common_hdr) ||
> +			     h->type < DATA || h->type > MAX_OP ||
> +			     skb->len < header_lengths[h->type - DATA]))
> +			goto discard;
> +
> +		/* Process the packet now if it is a control packet or
> +		 * if it contains an entire short message.
> +		 */
> +		if (h->type != DATA || ntohl(((struct homa_data_hdr *)h)
> +				->message_length) < 1400) {

I could not fined where `message_length` is validated. AFAICS
data_hdr->message_length could be > skb->len.

Also I don't see how the condition checked above ensures that the pkt
contains the whole message.

/P


  reply	other threads:[~2025-08-26 16:17 UTC|newest]

Thread overview: 47+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-08-18 20:55 [PATCH net-next v15 00/15] Begin upstreaming Homa transport protocol John Ousterhout
2025-08-18 20:55 ` [PATCH net-next v15 01/15] net: homa: define user-visible API for Homa John Ousterhout
2025-08-18 20:55 ` [PATCH net-next v15 02/15] net: homa: create homa_wire.h John Ousterhout
2025-08-18 20:55 ` [PATCH net-next v15 03/15] net: homa: create shared Homa header files John Ousterhout
2025-08-26  9:05   ` Paolo Abeni
2025-08-26 23:10     ` John Ousterhout
2025-08-27  7:21       ` Paolo Abeni
2025-08-29  3:03         ` John Ousterhout
2025-08-29  7:53           ` Paolo Abeni
2025-08-29 17:08             ` John Ousterhout
2025-09-01  7:59               ` Paolo Abeni
2025-08-27 12:16       ` Eric Dumazet
2025-08-18 20:55 ` [PATCH net-next v15 04/15] net: homa: create homa_pool.h and homa_pool.c John Ousterhout
2025-08-18 20:55 ` [PATCH net-next v15 05/15] net: homa: create homa_peer.h and homa_peer.c John Ousterhout
2025-08-26  9:32   ` Paolo Abeni
2025-08-27 23:27     ` John Ousterhout
2025-08-18 20:55 ` [PATCH net-next v15 06/15] net: homa: create homa_sock.h and homa_sock.c John Ousterhout
2025-08-26 10:10   ` Paolo Abeni
2025-08-31 23:29     ` John Ousterhout
2025-08-18 20:55 ` [PATCH net-next v15 07/15] net: homa: create homa_interest.h and homa_interest.c John Ousterhout
2025-08-18 20:55 ` [PATCH net-next v15 08/15] net: homa: create homa_pacer.h and homa_pacer.c John Ousterhout
2025-08-26 10:53   ` Paolo Abeni
2025-09-01 16:35     ` John Ousterhout
2025-08-18 20:55 ` [PATCH net-next v15 09/15] net: homa: create homa_rpc.h and homa_rpc.c John Ousterhout
2025-08-26 11:31   ` Paolo Abeni
2025-09-01 20:10     ` John Ousterhout
2025-08-18 20:55 ` [PATCH net-next v15 10/15] net: homa: create homa_outgoing.c John Ousterhout
2025-08-26 11:50   ` Paolo Abeni
2025-09-01 20:21     ` John Ousterhout
2025-08-18 20:55 ` [PATCH net-next v15 11/15] net: homa: create homa_utils.c John Ousterhout
2025-08-26 11:52   ` Paolo Abeni
2025-09-01 20:30     ` John Ousterhout
2025-08-18 20:55 ` [PATCH net-next v15 12/15] net: homa: create homa_incoming.c John Ousterhout
2025-08-26 12:05   ` Paolo Abeni
2025-09-01 22:12     ` John Ousterhout
2025-09-02  7:19   ` Eric Dumazet
2025-08-18 20:55 ` [PATCH net-next v15 13/15] net: homa: create homa_timer.c John Ousterhout
2025-08-18 20:55 ` [PATCH net-next v15 14/15] net: homa: create homa_plumbing.c John Ousterhout
2025-08-26 16:17   ` Paolo Abeni [this message]
2025-09-01 22:53     ` John Ousterhout
2025-09-01 23:03       ` Andrew Lunn
2025-09-02  4:54         ` John Ousterhout
2025-09-02  8:12       ` Paolo Abeni
2025-09-02 23:15         ` John Ousterhout
2025-08-18 20:55 ` [PATCH net-next v15 15/15] net: homa: create Makefile and Kconfig John Ousterhout
2025-08-23  5:36   ` kernel test robot
2025-08-22 15:51 ` [PATCH net-next v15 00/15] Begin upstreaming Homa transport protocol John Ousterhout

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=a2dec2d0-84be-4a4f-bfd4-b5f56219ac82@redhat.com \
    --to=pabeni@redhat.com \
    --cc=edumazet@google.com \
    --cc=horms@kernel.org \
    --cc=kuba@kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=ouster@cs.stanford.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).