linux/net/sched/sch_plug.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * sch_plug.c Queue traffic until an explicit release command
 *
 * There are two ways to use this qdisc:
 * 1. A simple "instantaneous" plug/unplug operation, by issuing an alternating
 *    sequence of TCQ_PLUG_BUFFER & TCQ_PLUG_RELEASE_INDEFINITE commands.
 *
 * 2. For network output buffering (a.k.a output commit) functionality.
 *    Output commit property is commonly used by applications using checkpoint
 *    based fault-tolerance to ensure that the checkpoint from which a system
 *    is being restored is consistent w.r.t outside world.
 *
 *    Consider for e.g. Remus - a Virtual Machine checkpointing system,
 *    wherein a VM is checkpointed, say every 50ms. The checkpoint is replicated
 *    asynchronously to the backup host, while the VM continues executing the
 *    next epoch speculatively.
 *
 *    The following is a typical sequence of output buffer operations:
 *       1.At epoch i, start_buffer(i)
 *       2. At end of epoch i (i.e. after 50ms):
 *          2.1 Stop VM and take checkpoint(i).
 *          2.2 start_buffer(i+1) and Resume VM
 *       3. While speculatively executing epoch(i+1), asynchronously replicate
 *          checkpoint(i) to backup host.
 *       4. When checkpoint_ack(i) is received from backup, release_buffer(i)
 *    Thus, this Qdisc would receive the following sequence of commands:
 *       TCQ_PLUG_BUFFER (epoch i)
 *       .. TCQ_PLUG_BUFFER (epoch i+1)
 *       ....TCQ_PLUG_RELEASE_ONE (epoch i)
 *       ......TCQ_PLUG_BUFFER (epoch i+2)
 *       ........
 */

#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <net/pkt_sched.h>

/*
 * State of the queue, when used for network output buffering:
 *
 *                 plug(i+1)            plug(i)          head
 * ------------------+--------------------+---------------->
 *                   |                    |
 *                   |                    |
 * pkts_current_epoch| pkts_last_epoch    |pkts_to_release
 * ----------------->|<--------+--------->|+--------------->
 *                   v                    v
 *
 */

struct plug_sched_data {};

static int plug_enqueue(struct sk_buff *skb, struct Qdisc *sch,
			struct sk_buff **to_free)
{}

static struct sk_buff *plug_dequeue(struct Qdisc *sch)
{}

static int plug_init(struct Qdisc *sch, struct nlattr *opt,
		     struct netlink_ext_ack *extack)
{}

/* Receives 4 types of messages:
 * TCQ_PLUG_BUFFER: Inset a plug into the queue and
 *  buffer any incoming packets
 * TCQ_PLUG_RELEASE_ONE: Dequeue packets from queue head
 *   to beginning of the next plug.
 * TCQ_PLUG_RELEASE_INDEFINITE: Dequeue all packets from queue.
 *   Stop buffering packets until the next TCQ_PLUG_BUFFER
 *   command is received (just act as a pass-thru queue).
 * TCQ_PLUG_LIMIT: Increase/decrease queue size
 */
static int plug_change(struct Qdisc *sch, struct nlattr *opt,
		       struct netlink_ext_ack *extack)
{}

static struct Qdisc_ops plug_qdisc_ops __read_mostly =;
MODULE_ALIAS_NET_SCH();

static int __init plug_module_init(void)
{}

static void __exit plug_module_exit(void)
{}
module_init()
module_exit()
MODULE_LICENSE();
MODULE_DESCRIPTION();